/* eslint-disable react-hooks/exhaustive-deps */ import React, { FC, forwardRef, ForwardRefRenderFunction, useContext, useEffect, useImperativeHandle, useRef, useState, } from 'react'; import { NativeSyntheticEvent, TextInput, TextInputFocusEventData, TouchableOpacity, View, } from 'react-native'; import { useComponentId } from '../Application'; import { ApplicationContext, ComponentContext, MiniAppContext, } from '../Context'; import { Icon } from '../Icon'; import { Text, useScaleSize } from '../Text'; import { InputRef, InputSearchProps } from './index'; import styles from './styles'; import { Styles } from '../Consts'; import SystemTextInput from './SystemTextInput'; const TextTyping: FC = ({ data = [], timeDelayEnd = 2000, timeDelayNextChar = 20, }) => { const textRef = useRef(null); const currentIndex = useRef(0); const currentCharIndex = useRef(0); const currentText = useRef(''); useEffect(() => { setTimeout(() => { playAnimation(); }, 1000); }, []); const playAnimation = () => { const handleResetList = () => { currentIndex.current = 0; handleAnimation(); }; const handleAnimation = () => { const listChar = data?.[currentIndex.current]?.split('') || []; listChar.length !== 0 && showChar(listChar?.[currentCharIndex.current]); }; currentIndex.current >= data?.length ? handleResetList() : handleAnimation(); }; const showChar = (char?: string) => { const handleResetString = () => { setTimeout(() => { reset(); }, timeDelayEnd); }; const handleShowChar = () => { setTimeout(() => { textRef.current?.setNativeProps?.({ text: currentText.current + char, }); currentText.current += char; currentCharIndex.current++; playAnimation(); }, timeDelayNextChar); }; currentCharIndex.current >= (data?.[currentIndex.current]?.length || 0) ? handleResetString() : handleShowChar(); }; const reset = () => { const handleNextString = () => { currentIndex.current++; playAnimation(); }; const handleReset = () => { setTimeout(() => { textRef.current?.setNativeProps?.({ text: currentText.current.slice(0, -1), }); currentText.current = currentText.current.slice(0, -1); currentCharIndex.current--; reset(); }, timeDelayNextChar); }; currentCharIndex.current <= 0 ? handleNextString() : handleReset(); }; return ( ); }; const InputSearch: ForwardRefRenderFunction = ( { placeholder, onFocus, onBlur, value, trailing, trailingColor, onPressTrailing, onChangeText, buttonText = 'Hủy', showButtonText = true, style, defaultValue, onPressButtonText, params, backgroundColor, onPress, typingData, ...props }, ref, ) => { const { theme } = useContext(ApplicationContext); const context = useContext(MiniAppContext); const scaledFontSize = useScaleSize(14); const showBaseLineDebug = context?.features?.showBaseLineDebug ?? false; const [focused, setFocused] = useState(false); const [internalText, setInternalText] = useState(defaultValue || ''); const currentValue = value !== undefined ? value : internalText; const haveValue = !!currentValue; const inputRef = useRef(null); const componentName = 'InputSearch'; const { componentId } = useComponentId( `${componentName}/${placeholder}`, props.accessibilityLabel, ); const _onFocus = (e: NativeSyntheticEvent) => { setFocused(true); onFocus?.(e); }; const _onBlur = (e: NativeSyntheticEvent) => { setFocused(false); onBlur?.(e); }; const onClearText = () => { inputRef?.current?.clear(); inputRef.current?.setNativeProps({ text: '' }); _onChangeText(''); }; const _onChangeText = (text: string) => { if (value === undefined) { setInternalText(text); } onChangeText?.(text); }; const _setText = (text: string) => { inputRef?.current?.setNativeProps({ text }); _onChangeText(text); }; useImperativeHandle(ref, () => { return { clear: onClearText, focus: () => inputRef.current?.focus(), blur: () => inputRef.current?.blur(), setText: _setText, }; }); /** * Render the input view */ const renderInputView = () => { if (typingData && typingData?.length > 0) { return ( ); } return ( ); }; /** * Render trailing icon or text */ const renderTrailing = () => { return ( {haveValue && ( )} {!!trailing && ( )} ); }; let inputState = 'empty'; if (focused) { inputState = 'focus'; } if (value && value?.length > 0) { inputState = 'filled'; } return ( {renderInputView()} {renderTrailing()} {showButtonText && ( {buttonText} )} ); }; export default forwardRef(InputSearch);