feat: add expo mobile application source code
This commit is contained in:
@@ -0,0 +1,144 @@
|
||||
import React, { useState } from 'react';
|
||||
import { View, TextInput, Text, StyleSheet, ViewStyle, TouchableOpacity, Platform } from 'react-native';
|
||||
import { useAppTheme } from '../context/ThemeContext';
|
||||
import { Feather } from '@expo/vector-icons';
|
||||
|
||||
interface InputProps {
|
||||
label?: string;
|
||||
placeholder?: string;
|
||||
value: string;
|
||||
onChangeText: (text: string) => void;
|
||||
secureTextEntry?: boolean;
|
||||
style?: ViewStyle;
|
||||
keyboardType?: 'default' | 'email-address' | 'numeric' | 'phone-pad';
|
||||
multiline?: boolean;
|
||||
required?: boolean;
|
||||
infoText?: string;
|
||||
}
|
||||
|
||||
const LIME = '#C6F135';
|
||||
|
||||
export const Input: React.FC<InputProps> = ({
|
||||
label,
|
||||
placeholder,
|
||||
value,
|
||||
onChangeText,
|
||||
secureTextEntry,
|
||||
style,
|
||||
keyboardType = 'default',
|
||||
multiline = false,
|
||||
required = false,
|
||||
infoText
|
||||
}) => {
|
||||
const { colors, isDark } = useAppTheme();
|
||||
const [isFocused, setIsFocused] = useState(false);
|
||||
const [isPasswordVisible, setIsPasswordVisible] = useState(false);
|
||||
|
||||
const handleFocus = () => setIsFocused(true);
|
||||
const handleBlur = () => setIsFocused(false);
|
||||
|
||||
const isSecure = secureTextEntry && !isPasswordVisible;
|
||||
|
||||
const bg = isDark ? '#1A1A1A' : '#F5F5F5';
|
||||
const border = isDark ? '#2A2A2A' : '#EEEEEE';
|
||||
|
||||
return (
|
||||
<View style={[styles.container, style]}>
|
||||
{label && (
|
||||
<View style={styles.labelRow}>
|
||||
<Text style={[styles.label, { color: colors.textSecondary }]}>
|
||||
{label}
|
||||
{required && <Text style={{ color: '#EF4444' }}> *</Text>}
|
||||
</Text>
|
||||
</View>
|
||||
)}
|
||||
<View style={[
|
||||
styles.inputWrapper,
|
||||
{
|
||||
backgroundColor: bg,
|
||||
borderColor: isFocused ? LIME : border,
|
||||
},
|
||||
multiline && { height: 120, borderRadius: 20, alignItems: 'flex-start', paddingTop: 16 }
|
||||
]}>
|
||||
<TextInput
|
||||
style={[
|
||||
styles.input,
|
||||
{ color: colors.text, paddingRight: secureTextEntry ? 45 : 16 },
|
||||
Platform.OS === 'web' && { outlineStyle: 'none' } as any
|
||||
]}
|
||||
placeholder={placeholder}
|
||||
placeholderTextColor={isDark ? '#444' : '#BBB'}
|
||||
value={value}
|
||||
onChangeText={onChangeText}
|
||||
secureTextEntry={isSecure}
|
||||
onFocus={handleFocus}
|
||||
onBlur={handleBlur}
|
||||
keyboardType={keyboardType}
|
||||
autoCapitalize="none"
|
||||
multiline={multiline}
|
||||
textAlignVertical={multiline ? 'top' : 'center'}
|
||||
/>
|
||||
|
||||
{secureTextEntry && (
|
||||
<TouchableOpacity
|
||||
style={styles.eyeIcon}
|
||||
onPress={() => setIsPasswordVisible(!isPasswordVisible)}
|
||||
>
|
||||
<Feather
|
||||
name={isPasswordVisible ? "eye" : "eye-off"}
|
||||
size={18}
|
||||
color={isDark ? '#555' : '#AAA'}
|
||||
/>
|
||||
</TouchableOpacity>
|
||||
)}
|
||||
</View>
|
||||
{infoText && <Text style={[styles.infoText, { color: isDark ? '#6B6B6B' : '#9B9B9B' }]}>{infoText}</Text>}
|
||||
</View>
|
||||
);
|
||||
};
|
||||
|
||||
const styles = StyleSheet.create({
|
||||
container: {
|
||||
marginBottom: 18,
|
||||
width: '100%',
|
||||
},
|
||||
labelRow: {
|
||||
flexDirection: 'row',
|
||||
justifyContent: 'space-between',
|
||||
alignItems: 'flex-end',
|
||||
marginBottom: 8,
|
||||
},
|
||||
label: {
|
||||
fontSize: 11,
|
||||
fontFamily: 'Outfit_700Bold',
|
||||
letterSpacing: 1,
|
||||
textTransform: 'uppercase',
|
||||
},
|
||||
inputWrapper: {
|
||||
height: 56,
|
||||
borderRadius: 14,
|
||||
paddingLeft: 16,
|
||||
borderWidth: 1.5,
|
||||
flexDirection: 'row',
|
||||
alignItems: 'center',
|
||||
},
|
||||
input: {
|
||||
flex: 1,
|
||||
fontSize: 15,
|
||||
fontFamily: 'Outfit_500Medium',
|
||||
height: '100%',
|
||||
},
|
||||
eyeIcon: {
|
||||
position: 'absolute',
|
||||
right: 15,
|
||||
height: '100%',
|
||||
justifyContent: 'center',
|
||||
paddingHorizontal: 5,
|
||||
},
|
||||
infoText: {
|
||||
fontSize: 12,
|
||||
marginTop: 6,
|
||||
marginLeft: 4,
|
||||
fontFamily: 'Outfit_400Regular',
|
||||
},
|
||||
});
|
||||
Reference in New Issue
Block a user