({
value,
onChange,
options,
getOptionValue,
getOptionLabel,
isOptionEqualToValue,
renderOption,
loading = false,
placeholder = "Select an option",
noOptionsText = "No results found",
open: controlledOpen,
onOpenChange,
inputValue: controlledInputValue,
onInputChange,
onEscapeKeyDown,
onEnterEmpty,
inlineSearch = false,
clearable = true,
disabled = false,
startAdornment,
className,
triggerAriaInvalid,
triggerAriaDescribedBy,
id,
"data-testid": testId,
}: AutocompleteProps<TOption>)
| 56 | } |
| 57 | |
| 58 | export function Autocomplete<TOption>({ |
| 59 | value, |
| 60 | onChange, |
| 61 | options, |
| 62 | getOptionValue, |
| 63 | getOptionLabel, |
| 64 | isOptionEqualToValue, |
| 65 | renderOption, |
| 66 | loading = false, |
| 67 | placeholder = "Select an option", |
| 68 | noOptionsText = "No results found", |
| 69 | open: controlledOpen, |
| 70 | onOpenChange, |
| 71 | inputValue: controlledInputValue, |
| 72 | onInputChange, |
| 73 | onEscapeKeyDown, |
| 74 | onEnterEmpty, |
| 75 | inlineSearch = false, |
| 76 | clearable = true, |
| 77 | disabled = false, |
| 78 | startAdornment, |
| 79 | className, |
| 80 | triggerAriaInvalid, |
| 81 | triggerAriaDescribedBy, |
| 82 | id, |
| 83 | "data-testid": testId, |
| 84 | }: AutocompleteProps<TOption>) { |
| 85 | const inlineInputRef = useRef<HTMLInputElement>(null); |
| 86 | const highlightedValueRef = useRef<string | null>(null); |
| 87 | const [managedOpen, setManagedOpen] = useState(false); |
| 88 | const [managedInputValue, setManagedInputValue] = useState(""); |
| 89 | const [highlightedValue, setHighlightedValue] = useState<string | null>(null); |
| 90 | const generatedListboxId = useId(); |
| 91 | const listboxId = `${generatedListboxId}-listbox`; |
| 92 | |
| 93 | const updateHighlightedValue = useCallback((newValue: string | null) => { |
| 94 | highlightedValueRef.current = newValue; |
| 95 | setHighlightedValue(newValue); |
| 96 | }, []); |
| 97 | const isOpen = controlledOpen ?? managedOpen; |
| 98 | const inputValue = controlledInputValue ?? managedInputValue; |
| 99 | |
| 100 | const handleOpenChange = useCallback( |
| 101 | (newOpen: boolean) => { |
| 102 | setManagedOpen(newOpen); |
| 103 | onOpenChange?.(newOpen); |
| 104 | if (!newOpen) { |
| 105 | updateHighlightedValue(null); |
| 106 | } |
| 107 | if (!newOpen && controlledInputValue === undefined) { |
| 108 | setManagedInputValue(""); |
| 109 | } |
| 110 | }, |
| 111 | [onOpenChange, controlledInputValue, updateHighlightedValue], |
| 112 | ); |
| 113 | |
| 114 | const handleInputChange = useCallback( |
| 115 | (newValue: string) => { |
nothing calls this directly
no test coverage detected