Open Psycarlo opened 2 months ago
Example
type SSPinInput2Props = {
pin: string[]
setPin: Dispatch<SetStateAction<string[]>>
autoFocus?: boolean
onFillEnded(): void
}
export default function SSPinInput2({
pin,
setPin,
autoFocus,
onFillEnded
}: SSPinInput2Props) {
const inputRefs = useRef<TextInput[]>([])
const [isBackspace, setIsBackspace] = useState(false)
function handleOnChangeText(text: string, index: number) {
const newPin = [...pin]
newPin[index] = text
setPin(newPin)
if (text === '') return
if (index + 1 < PIN_SIZE) {
inputRefs.current[index + 1]?.focus()
} else {
onFillEnded()
Keyboard.dismiss()
}
}
function handleOnKeyPress(
event: NativeSyntheticEvent<TextInputKeyPressEventData>,
index: number
) {
if (event.nativeEvent.key === 'Backspace') {
setIsBackspace(true)
if (index - 1 >= 0) {
inputRefs.current[index - 1]?.focus()
}
}
}
function handleOnFocus() {
const lastFilledIndex = pin.findIndex((text) => text === '')
if (lastFilledIndex === 0) {
inputRefs.current[0]?.focus()
return
}
if (isBackspace) {
setIsBackspace(false)
return
}
const finalIndex = lastFilledIndex === -1 ? PIN_SIZE - 1 : lastFilledIndex
inputRefs.current[finalIndex]?.focus()
}
return (
<SSHStack gap="sm">
{[...Array(PIN_SIZE)].map((_, index) => (
<TextInput
key={index}
ref={(input) => inputRefs.current.push(input as TextInput)}
style={styles.pinInputBase}
autoFocus={autoFocus && index === 0}
value={pin[index]}
keyboardType="numeric"
maxLength={1}
secureTextEntry
onChangeText={(text) => handleOnChangeText(text, index)}
onKeyPress={(event) => handleOnKeyPress(event, index)}
onFocus={() => handleOnFocus()}
/>
))}
</SSHStack>
)
}
const styles = StyleSheet.create({
pinInputBase: {
borderRadius: Sizes.pinInput.borderRadius,
height: Sizes.pinInput.height,
width: Sizes.pinInput.width,
textAlign: 'center',
backgroundColor: Colors.gray[850],
color: Colors.white,
fontSize: Sizes.textInput.fontSize
}
})
Hi @Psycarlo thanks again for this suggestion, I'm working on a feature for a product today, I'll look into it as soon as I can, in the meantime feel free to make a PR
Hi again @pakenfit
Wouldn't be better to actually set the
value
prop on the TextInput? At the moment, when I backspace one of the Inputs, the value still there:inputValues.current[index]
equals the previous value instead of being set to null since there is no number on the inputIs it better to receive the pin as prop to PinInput? Could we manage more easily this way instead of passing refs?
How we would implement the following feature: When clicking on any Input, if it's full (all 4 filled), focus should be on the last. When clicking on any Input, if it's not full, focus should be on the next empty
What do you think? What are your thoughts?