@naarni/design-system
Version:
Naarni React Native Design System for EV Fleet Apps
107 lines (102 loc) • 4.16 kB
JavaScript
import React, { useState, forwardRef } from 'react';
import { View, TextInput, Text, TouchableOpacity, } from 'react-native';
import { useDeviceTheme } from '../../theme/deviceTheme';
import { Icon } from '../Icon/Icon';
import { styles } from './styles';
export const InputBox = forwardRef(({ placeholder, error, type = 'text', leftIcon, rightIcon, onRightIconPress, disabled = false, label, helperText, variant = 'outlined', size = 'medium', fullWidth = true, style, containerStyle, ...props }, ref) => {
const { colors } = useDeviceTheme();
const [isFocused, setIsFocused] = useState(false);
const [showPassword, setShowPassword] = useState(false);
const getKeyboardType = () => {
switch (type) {
case 'email':
return 'email-address';
case 'phone':
return 'phone-pad';
case 'number':
return 'numeric';
case 'url':
return 'url';
default:
return 'default';
}
};
const getSecureTextEntry = () => {
if (type === 'password') {
return !showPassword;
}
return false;
};
const getRightIcon = () => {
if (type === 'password') {
return showPassword ? 'eye-off' : 'eye';
}
return rightIcon;
};
const handleRightIconPress = () => {
if (type === 'password') {
setShowPassword(!showPassword);
}
else if (onRightIconPress) {
onRightIconPress();
}
};
const getInputStyles = () => {
const baseStyles = {
borderColor: error
? colors.error.main
: isFocused
? colors.primary.main
: colors.surface.border,
backgroundColor: variant === 'filled'
? colors.surface.card
: colors.background.default,
};
if (disabled) {
baseStyles.backgroundColor = colors.surface.card;
baseStyles.borderColor = colors.surface.border;
}
return baseStyles;
};
const getSizeStyles = () => {
switch (size) {
case 'small':
return { height: 36, fontSize: 14 };
case 'large':
return { height: 48, fontSize: 16 };
default:
return { height: 44, fontSize: 16 };
}
};
return (<View style={[styles.container, fullWidth && styles.fullWidth, containerStyle]}>
{label && (<Text style={[styles.label, { color: colors.text.primary }]}>
{label}
</Text>)}
<View style={[
styles.inputContainer,
getInputStyles(),
getSizeStyles(),
variant === 'outlined' ? styles.outlined : styles.filled,
disabled && styles.disabled
]}>
{leftIcon && (<Icon name={leftIcon} size={20} color={disabled ? colors.text.disabled : colors.text.secondary} style={styles.leftIcon}/>)}
<TextInput ref={ref} style={[
styles.input,
getSizeStyles(),
{ color: disabled ? colors.text.disabled : colors.text.primary },
leftIcon && styles.inputWithLeftIcon,
rightIcon && styles.inputWithRightIcon,
style
]} placeholder={placeholder} placeholderTextColor={colors.text.disabled} keyboardType={getKeyboardType()} secureTextEntry={getSecureTextEntry()} editable={!disabled} onFocus={() => setIsFocused(true)} onBlur={() => setIsFocused(false)} {...props}/>
{getRightIcon() && (<TouchableOpacity onPress={handleRightIconPress} disabled={disabled} style={styles.rightIconContainer}>
<Icon name={getRightIcon()} size={20} color={disabled ? colors.text.disabled : colors.text.secondary}/>
</TouchableOpacity>)}
</View>
{(error || helperText) && (<Text style={[
styles.helperText,
{ color: error ? colors.error.main : colors.text.secondary }
]}>
{error || helperText}
</Text>)}
</View>);
});