import { createRef, useMemo, useState } from 'react'; import { type NativeSyntheticEvent, TextInput, type TextInputKeyPressEventData, View, Platform } from 'react-native'; import { InputNumeric, type InputNumericProps } from '../wui-input-numeric'; import styles from './styles'; export interface OtpProps { length: number; style?: InputNumericProps['style']; onChangeText?: (text: string) => void; autoFocus?: boolean; } export function Otp({ length, style, onChangeText, autoFocus }: OtpProps) { const [value, setValue] = useState([]); const refArray = useMemo( () => Array.from({ length }).map(() => createRef()), [length] ); const _onChangeText = (text: string, index: number) => { let newValue; if (text.length <= 1) { newValue = [...value.slice(0, index), text, ...value.slice(index + 1)]; } else if (text.length === length) { // Paste OTP newValue = text.split(''); focusInputField('next', length - 1); } else if (text.length === 2) { // Replace value newValue = [ ...value.slice(0, index), (value[index] === text[0] ? text[1] : text[0]) ?? '', ...value.slice(index + 1) ]; } else { newValue = [...value.slice(0, index), text[0] ?? '', ...value.slice(index + 1)]; focusInputField('next', index); } setValue(newValue); onChangeText?.(newValue.join('')); }; const focusInputField = (dir: 'prev' | 'next', currentIndex: number, clear = false) => { let newIndex; if (dir === 'prev' && currentIndex > 0) { newIndex = currentIndex - 1; } else if (dir === 'next' && currentIndex < length - 1) { newIndex = currentIndex + 1; } if (newIndex !== undefined) { refArray[newIndex]?.current?.focus(); if (clear) { refArray[newIndex]?.current?.clear(); _onChangeText('', newIndex); } } }; const onKeyPress = (e: NativeSyntheticEvent, index: number) => { const currentValue = value[index] || ''; const key = e.nativeEvent.key; if (key === 'Backspace') { if (!currentValue) { focusInputField('prev', index, true); } } else { focusInputField('next', index); } }; return ( {Array.from({ length }).map((_, index) => ( _onChangeText(text, index)} onKeyPress={(e: any) => onKeyPress(e, index)} textContentType="oneTimeCode" autoComplete={Platform.OS === 'android' ? 'sms-otp' : 'one-time-code'} /> ))} ); }