import { useEffect, useRef } from 'react'; import { Pressable, StyleSheet, Text, TextInput, View, type TextInput as TextInputType, } from 'react-native'; import { colors } from '../theme/colors'; interface Props { value: string; onChange: (next: string) => void; length?: number; autoFocus?: boolean; disabled?: boolean; ariaLabel: string; onSubmit?: () => void; } // Six-slot numeric PIN entry. The actual input is an invisible TextInput // that captures the numeric keyboard; visible slots render bullets when // filled. Tapping anywhere on the row re-focuses the input. export function PinInput({ value, onChange, length = 6, autoFocus, disabled, ariaLabel, onSubmit, }: Props) { const ref = useRef(null); useEffect(() => { if (autoFocus) ref.current?.focus(); }, [autoFocus]); return ( ref.current?.focus()} style={styles.row}> onChange(t.replace(/\D/g, '').slice(0, length))} onSubmitEditing={() => { if (value.length === length) onSubmit?.(); }} style={styles.hidden} /> {Array.from({ length }).map((_, i) => { const filled = i < value.length; return ( {filled && } ); })} ); } const styles = StyleSheet.create({ row: { alignItems: 'center' }, hidden: { position: 'absolute', width: 1, height: 1, opacity: 0, }, slots: { flexDirection: 'row', gap: 8 }, slot: { width: 40, height: 48, borderRadius: 10, borderWidth: 1, borderColor: colors.border, alignItems: 'center', justifyContent: 'center', backgroundColor: colors.surface, }, slotFilled: { borderColor: colors.accent, backgroundColor: colors.bg, }, bullet: { color: colors.text, fontSize: 22 }, });