Created
November 20, 2023 22:32
-
-
Save brunocroh/67d07a7f00a6d51a6e2770679f0898ec to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import React, {Dispatch, SetStateAction, useCallback, useRef, useState} from 'react'; | |
import {Input, TamaguiElement, XStack} from 'tamagui'; | |
import * as Clipboard from 'expo-clipboard'; | |
import {Keyboard} from 'react-native'; | |
type Props = { | |
setState: Dispatch<SetStateAction<string>>; | |
}; | |
type Code = { | |
code: string; | |
id: number; | |
}; | |
export const VerificationInput = ({setState}: Props) => { | |
const codeLength = new Array(6).fill(0); | |
const inputRefs = useRef<TamaguiElement[]>([]); | |
const [code, setCode] = useState<Code[]>([]); | |
const handleSetState = useCallback((index: number, value: string) => { | |
setCode(prev => { | |
const _newCode = [ | |
...prev, | |
{ | |
code: value, | |
id: index, | |
}, | |
]; | |
setState(_newCode.map(code => code.code).join('')); | |
return _newCode; | |
}); | |
}, []); | |
const handleInputChange = async (index: number, value: string) => { | |
if (value !== '') { | |
handleSetState(index, value.length === 1 ? value : value.slice(-1)); | |
} | |
const pasteContent = await Clipboard.getStringAsync(); | |
if (pasteContent?.length === 6) { | |
const _code = pasteContent | |
.split('') | |
.map((c: string, index: number) => ({id: index, code: c})); | |
setCode(_code); | |
setState(_code.map(code => code.code).join('')); | |
Keyboard.dismiss(); | |
Clipboard.setStringAsync(''); | |
return; | |
} | |
if (inputRefs.current[index + 1] && value !== '') { | |
inputRefs.current[index + 1].focus(); | |
} | |
}; | |
const handleInputKeyPress = (index: number, key: string) => { | |
if (key === 'Backspace') { | |
const newCode = code.filter(code => code.id !== index); | |
setCode([...newCode]); | |
} | |
if (key === 'Backspace' && inputRefs.current[index - 1]) { | |
inputRefs.current[index - 1].focus(); | |
} | |
}; | |
return ( | |
<XStack gap={12} pb={15}> | |
{codeLength.map((_, index) => ( | |
<Input | |
ref={ref => ref && (inputRefs.current[index] = ref)} | |
key={index} | |
value={code[index]?.code} | |
borderWidth={0} | |
borderBottomWidth={2} | |
borderBottomColor="$color.gray10Dark" | |
borderRadius={0} | |
bg="transparent" | |
w={40} | |
textContentType="oneTimeCode" | |
autoComplete="one-time-code" | |
inputMode="numeric" | |
maxLength={6} | |
placeholderTextColor="black" | |
textAlign="center" | |
fontSize="$2" | |
autoFocus={index === 0} | |
focusStyle={{borderBottomColor: '$color.purple10Dark'}} | |
onChangeText={e => handleInputChange(index, e)} | |
onKeyPress={e => handleInputKeyPress(index, e.nativeEvent.key)} | |
/> | |
))} | |
</XStack> | |
); | |
}; |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment