2025-08-08 19:05:43 +08:00

122 lines
3.6 KiB
TypeScript

import { ThemedText } from "@/components/ThemedText";
import { Fonts } from "@/constants/Fonts";
import { Ionicons } from "@expo/vector-icons";
import { TextInput as RNTextInput, TextInputProps as RNTextInputProps, StyleProp, StyleSheet, TextStyle, TouchableOpacity, View, ViewStyle } from "react-native";
interface CustomTextInputProps {
label: string;
placeholder: string;
value: string;
onChangeText: (text: string) => void;
showPassword?: boolean;
setShowPassword?: (showPassword: boolean) => void;
setError?: (error: string) => void;
type?: 'default' | 'password';
containerStyle?: StyleProp<ViewStyle>;
style?: StyleProp<TextStyle>;
error?: string;
}
type TextInputProps = RNTextInputProps & CustomTextInputProps;
const TextInput = ({
type = 'default',
label,
placeholder,
value,
onChangeText,
setError,
showPassword,
setShowPassword,
error,
style,
containerStyle,
...props
}: TextInputProps) => {
return (
<View style={[styles.inputContainer, containerStyle]}>
<View className="w-full flex flex-row justify-between">
<ThemedText style={styles.inputLabel}>
{label}
</ThemedText>
{
error &&
<ThemedText color="bgSecondary" size="xxs">
{error}
</ThemedText>
}
</View>
<View style={styles.inputTextContainer}>
<RNTextInput
style={[styles.textInput, style]}
placeholder={placeholder}
placeholderTextColor={Fonts['placeholderTextColor']}
value={value}
onChangeText={onChangeText}
secureTextEntry={type === 'password' ? !showPassword : undefined}
{...props}
/>
{
type === 'password' &&
<TouchableOpacity
style={styles.eyeIcon}
onPress={() => {
if (setShowPassword) {
setShowPassword(!showPassword);
}
}}
>
<Ionicons
name={showPassword ? 'eye' : 'eye-off'}
size={20}
color="#666"
/>
</TouchableOpacity>
}
</View>
</View>
);
}
const styles = StyleSheet.create({
inputContainer: {
marginBottom: 20,
},
inputLabel: {
fontSize: Fonts['sm'],
color: Fonts['textPrimary'],
fontWeight: Fonts['bold'],
fontFamily: Fonts['sfPro'],
marginBottom: 8,
marginLeft: 8,
},
textInput: {
borderRadius: Fonts['xs'],
paddingHorizontal: Fonts['base'],
paddingVertical: Fonts['sm'],
fontSize: Fonts['sm'],
lineHeight: Fonts['base'],
textAlignVertical: 'center',
backgroundColor: Fonts['bgInput'],
color: Fonts['textSecondary'],
fontFamily: Fonts['inter'],
paddingRight: 48, // Make space for the eye icon
},
inputTextContainer: {
position: 'relative',
},
eyeIcon: {
position: 'absolute',
right: 12,
top: '50%',
transform: [{ translateY: -10 }], // Half of the icon's height (20/2 = 10)
height: 20,
width: 20,
justifyContent: 'center',
alignItems: 'center',
},
})
export default TextInput;