Press n or j to go to the next uncovered block, b, p or k for the previous block.
| 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 | 12x 12x 43x 43x 43x 35x 8x 12x | import { forwardRef } from 'react';
import { Input as TamaguiInput, styled, GetProps, XStack, YStack, Text } from 'tamagui';
const StyledInput = styled(TamaguiInput, {
name: 'Input',
borderWidth: 1,
borderColor: '$borderColor',
borderRadius: '$4',
paddingHorizontal: '$3',
backgroundColor: '$background',
color: '$foreground',
placeholderTextColor: '$placeholderColor',
fontSize: '$5',
focusStyle: {
borderColor: '$borderColorFocus',
outlineWidth: 0,
},
hoverStyle: {
borderColor: '$borderColorHover',
},
variants: {
size: {
sm: { height: 46, fontSize: '$4' },
md: { height: 54, fontSize: '$5' },
lg: { height: 62, fontSize: '$6' },
},
error: {
true: {
borderColor: '$red',
focusStyle: { borderColor: '$red' },
},
},
disabled: {
true: {
opacity: 0.5,
backgroundColor: '$color2',
},
},
} as const,
defaultVariants: {
size: 'md',
},
});
type StyledInputProps = GetProps<typeof StyledInput>;
interface InputProps extends StyledInputProps {
label?: string;
errorMessage?: string;
leftIcon?: React.ReactNode;
rightIcon?: React.ReactNode;
}
export const Input = forwardRef<React.ElementRef<typeof StyledInput>, InputProps>(
({ label, errorMessage, leftIcon, rightIcon, error, testID, ...props }, ref) => {
const hasError = !!errorMessage || error;
// 同时设置 testID 和 accessibilityLabel 以支持 Detox E2E 测试
const a11yProps = testID ? { testID, accessibilityLabel: testID, nativeID: testID } : {};
if (!label && !errorMessage && !leftIcon && !rightIcon) {
return <StyledInput ref={ref} error={hasError} {...a11yProps} {...props} />;
}
return (
<YStack gap="$1.5">
{label && (
<Text fontSize="$4" fontWeight="500" color="$foregroundMuted">
{label}
</Text>
)}
<XStack alignItems="center" position="relative">
{leftIcon && (
<YStack position="absolute" left="$3" zIndex={1}>
{leftIcon}
</YStack>
)}
<StyledInput
ref={ref}
error={hasError}
paddingLeft={leftIcon ? '$9' : '$3'}
paddingRight={rightIcon ? '$9' : '$3'}
flex={1}
{...a11yProps}
{...props}
/>
{rightIcon && (
<YStack position="absolute" right="$3" zIndex={1}>
{rightIcon}
</YStack>
)}
</XStack>
{errorMessage && (
<Text fontSize="$3" color="$red">
{errorMessage}
</Text>
)}
</YStack>
);
}
);
Input.displayName = 'Input';
|