Skip to content

Instantly share code, notes, and snippets.

@brunocroh
Created November 20, 2023 22:32
Show Gist options
  • Save brunocroh/67d07a7f00a6d51a6e2770679f0898ec to your computer and use it in GitHub Desktop.
Save brunocroh/67d07a7f00a6d51a6e2770679f0898ec to your computer and use it in GitHub Desktop.
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