import { useId, useLayoutEffect, useRef, useState } from 'react' import { getRecoverySuggestions, getRecoveryWord } from '../lib/recoveryInput' import { ClearButtonOnInput, ScanButtonOnInput } from './Button' import { Autocomplete } from '@base-ui/react/autocomplete' import { useTranslation } from '../providers/language' import { hapticLight } from '../lib/haptics' import FlexRow from './FlexRow' import Paste from './Paste' interface InputNsecProps { value: string cursor: number | null error?: string helperText: string onChange: (value: string, cursor: number | null) => void onSubmit: () => void openScan: () => void } export default function InputNsec({ value, cursor, error, helperText, onChange, onSubmit, openScan }: InputNsecProps) { const { t } = useTranslation() const id = useId() const inputRef = useRef(null) const pendingCursor = useRef(null) const [composing, setComposing] = useState(false) const suggestions = composing ? [] : getRecoverySuggestions(value, cursor) useLayoutEffect(() => { if (pendingCursor.current !== null) { inputRef.current?.setSelectionRange(pendingCursor.current, pendingCursor.current) pendingCursor.current = null } }, [value, cursor]) const handlePaste = (data: string) => { hapticLight() onChange(data, data.length) } const handleClear = () => { hapticLight() onChange('', 0) } const handleScan = () => { hapticLight() openScan() } const hasValue = Boolean(value && value.length > 0) return (
{ if (details.reason === 'item-press') { const token = getRecoveryWord(value, cursor) if (!token) return const suffix = value.slice(token.end) const separator = /^\s/.test(suffix) ? '' : ' ' const completed = value.slice(0, token.start) + next + separator + suffix // Advance over the inserted or existing space to the next word. const nextCursor = token.start + next.length + 1 pendingCursor.current = nextCursor hapticLight() onChange(completed, nextCursor) } else { onChange(next, inputRef.current?.selectionStart ?? next.length) } }} >
onChange(value, event.currentTarget.selectionStart)} onFocus={(event) => onChange(value, event.currentTarget.selectionStart)} onBlur={() => onChange(value, null)} onCompositionStart={() => setComposing(true)} onCompositionEnd={() => setComposing(false)} onKeyDown={(event) => { if ( event.key === 'Enter' && !event.nativeEvent.isComposing && !event.currentTarget.getAttribute('aria-activedescendant') ) { event.preventDefault() onSubmit() } }} />
{hasValue ? ( ) : ( )}
{suggestions.length > 0 ? ( {(word: string) => ( {word} )} ) : null}

{error || helperText}

) }