"use client"; import { useEffect, useId, useRef, useState } from "react"; import { filterUsStateOptions, formatUsStateOption, normalizeUsStateCode, } from "@/lib/frontend/us-states"; interface StateComboboxFieldProps { label: string; name: string; value: string; disabled?: boolean; error?: string; onChange: (code: string) => void; onBlur?: () => void; } export function StateComboboxField({ label, name, value, disabled, error, onChange, onBlur, }: StateComboboxFieldProps) { const listId = useId(); const rootRef = useRef(null); const [draft, setDraft] = useState(value); const [open, setOpen] = useState(false); useEffect(() => { setDraft(value); }, [value]); const options = filterUsStateOptions(draft); const commitDraft = () => { const normalized = normalizeUsStateCode(draft); if (normalized) { onChange(normalized); setDraft(normalized); } else { onChange(draft.trim().toUpperCase()); } onBlur?.(); }; const selectOption = (code: string, labelText: string) => { onChange(code); setDraft(labelText); setOpen(false); onBlur?.(); }; useEffect(() => { const onDocMouseDown = (e: MouseEvent) => { if (!rootRef.current?.contains(e.target as Node)) { setOpen(false); } }; document.addEventListener("mousedown", onDocMouseDown); return () => document.removeEventListener("mousedown", onDocMouseDown); }, []); return (
{ const next = e.target.value; setDraft(next); setOpen(true); const normalized = normalizeUsStateCode(next); if (normalized) onChange(normalized); }} onFocus={() => setOpen(true)} onBlur={() => { window.setTimeout(() => { if (!rootRef.current?.contains(document.activeElement)) { commitDraft(); setOpen(false); } }, 120); }} onKeyDown={(e) => { if (e.key === "Escape") { setOpen(false); return; } if (e.key === "Enter" && open && options.length > 0) { e.preventDefault(); const first = options[0]; selectOption(first.code, formatUsStateOption(first)); } }} className={`h-10 w-full rounded-sm border px-3 text-sm transition-colors focus:border-primary focus:outline-none focus:ring-2 focus:ring-primary/20 disabled:cursor-not-allowed disabled:bg-bg disabled:opacity-60 ${ error ? "border-error" : "border-border" }`} /> {open && !disabled && options.length > 0 && ( )} {error &&

{error}

}
); }