import React, { useState, useRef, useEffect } from 'react'; import { NativeSyntheticEvent, TextInputFocusEventData, Animated, LayoutAnimation, } from 'react-native'; import * as Styled from './TextInput.style'; import type { ITextInputProps } from './TextInput.types'; import { Typography, Box, Spacing } from '../../ui'; export const TextInput = ({ label, onFocus, onBlur, error, placeholder, onChangeText, containerStyle, // maskType, hideErrorMessage, value: propValue, ...textInputProps }: ITextInputProps) => { const [value, setValue] = useState(propValue || ''); const [isFocused, setIsFocused] = useState(false); const translateY = useRef(new Animated.Value(0)).current; const scale = useRef(new Animated.Value(1)).current; const hasValue = !!value; const hasError = !!error; const duration = 150; const useNativeDriver = true; const moveUp = Animated.timing(translateY, { toValue: -28.5, duration, useNativeDriver, }); const moveDown = Animated.timing(translateY, { toValue: 0, duration, useNativeDriver, }); const scaleUp = Animated.timing(scale, { toValue: 1, duration, useNativeDriver, }); const scaleDown = Animated.timing(scale, { toValue: 0.9, duration, useNativeDriver, }); const handleFocus = ( event: NativeSyntheticEvent ) => { Animated.parallel([moveUp, scaleDown]).start(); setIsFocused(true); onFocus && onFocus(event); }; const handleBlur = (event: NativeSyntheticEvent) => { if (!hasValue) { Animated.parallel([moveDown, scaleUp]).start(); } setIsFocused(false); onBlur && onBlur(event); }; useEffect(() => { if (hasValue) { Animated.parallel([moveUp, scaleDown]).start(); } }, []); useEffect(() => { if (propValue === value) return; onChangeText && onChangeText(value); }, [value]); useEffect(() => { setValue(propValue || ''); }, [propValue]); useEffect(() => { LayoutAnimation.configureNext(LayoutAnimation.Presets.easeInEaseOut); }, [hasError]); const handleTextChange = (val: string) => setValue(val); const Label = ( {label} ); const Error = hasError && ( {error} ); return ( {Label} {!hideErrorMessage && Error} ); };