import React, { forwardRef, useState, useImperativeHandle, useRef, ReactNode, useEffect, } from 'react'; import { TextInput, View, StyleSheet, Text, NativeSyntheticEvent, TextInputFocusEventData, KeyboardTypeOptions, Animated, Platform, Pressable, TextInputProps, } from 'react-native'; import Label from '../Label'; import { colors } from '../../colors'; import ShowTextIcon from '../_icons/ShowTextIcon'; type Validation = { status: boolean; message: string }; interface Props extends TextInputProps { textInputStyle?: object | object[]; children?: ReactNode; underneathText?: string; underneathTextStyle?: object | object[]; label?: string; labelStyle?: object | object[]; isRequired?: boolean; value: string; customValidation?: () => Validation; asterik?: boolean; floatingLabel?: boolean; textArea?: boolean; showErrorIcon?: boolean; errorBorderColor?: string; showIcon?: JSX.Element; hideIcon?: JSX.Element; ref: React.RefObject; } const FormItem = forwardRef(({ children, ...props }: Props, ref: any) => { const [hasError, setHasError] = useState({ status: false, message: '' }); const [animatedBottom] = useState(new Animated.Value(0)); const [shouldAnimate, setShouldAnimate] = useState(true); const [wrapperHeight, setWrapperHeight] = useState(0); const { isRequired, value, keyboardType } = props; const inputRef: any = useRef(); const [hideText, setHideText] = useState(props.secureTextEntry); useImperativeHandle(ref, () => ({ setState: () => { let validation; if (props.customValidation) validation = props.customValidation(); setHasError(containsError(keyboardType, isRequired!, value, validation)); }, focus: () => inputRef.current.focus(), blur: () => inputRef.current.blur(), clear: () => inputRef.current.clear(), isFocused: () => inputRef.current.isFocused(), getComponent: () => 'FormItem', })); const handleBlur = (e: NativeSyntheticEvent) => { let validation; if (props.customValidation) validation = props.customValidation(); setHasError(containsError(keyboardType, isRequired!, value, validation)); if (props.onBlur) props.onBlur(e); }; const handleFocus = (e: NativeSyntheticEvent) => { setHasError({ status: false, message: '' }); if (props.floatingLabel && shouldAnimate) Animated.timing(animatedBottom, { toValue: props.textArea ? 24 : wrapperHeight / 2, useNativeDriver: false, duration: 300, }).start(() => setShouldAnimate(false)); if (props.onFocus) props.onFocus(e); }; useEffect(() => { if (props.floatingLabel && props.value) Animated.timing(animatedBottom, { toValue: props.textArea ? 24 : wrapperHeight / 2, useNativeDriver: false, duration: 300, }).start(() => setShouldAnimate(false)); }, [shouldAnimate]); if (props.floatingLabel) { return ( <> setWrapperHeight(nativeEvent.layout.height) } > {props.label && ( {hasError.status && ( {props.underneathText || hasError.message} )} ); } return ( <> {props.label && (