UNPKG

15 kBTypeScriptView Raw
1import * as React from 'react';
2
3export interface CreateFilterOptionsConfig<Value> {
4 ignoreAccents?: boolean;
5 ignoreCase?: boolean;
6 limit?: number;
7 matchFrom?: 'any' | 'start';
8 stringify?: (option: Value) => string;
9 trim?: boolean;
10}
11
12export interface FilterOptionsState<Value> {
13 inputValue: string;
14 getOptionLabel: (option: Value) => string;
15}
16
17export interface AutocompleteGroupedOption<Value = string> {
18 key: number;
19 index: number;
20 group: string;
21 options: Value[];
22}
23
24export function createFilterOptions<Value>(
25 config?: CreateFilterOptionsConfig<Value>,
26): (options: Value[], state: FilterOptionsState<Value>) => Value[];
27
28export type AutocompleteFreeSoloValueMapping<FreeSolo> = FreeSolo extends true ? string : never;
29
30export type AutocompleteValue<Value, Multiple, DisableClearable, FreeSolo> = Multiple extends true
31 ? Array<Value | AutocompleteFreeSoloValueMapping<FreeSolo>>
32 : DisableClearable extends true
33 ? NonNullable<Value | AutocompleteFreeSoloValueMapping<FreeSolo>>
34 : Value | null | AutocompleteFreeSoloValueMapping<FreeSolo>;
35
36export interface UseAutocompleteProps<
37 Value,
38 Multiple extends boolean | undefined,
39 DisableClearable extends boolean | undefined,
40 FreeSolo extends boolean | undefined,
41> {
42 /**
43 * @internal The prefix of the state class name, temporary for Joy UI
44 * @default 'Mui'
45 */
46 unstable_classNamePrefix?: string;
47 /**
48 * @internal
49 * Temporary for Joy UI because the parent listbox is the document object
50 * TODO v6: Normalize the logic and remove this param.
51 */
52 unstable_isActiveElementInListbox?: (listbox: React.RefObject<HTMLElement | null>) => boolean;
53 /**
54 * If `true`, the portion of the selected suggestion that the user hasn't typed,
55 * known as the completion string, appears inline after the input cursor in the textbox.
56 * The inline completion string is visually highlighted and has a selected state.
57 * @default false
58 */
59 autoComplete?: boolean;
60 /**
61 * If `true`, the first option is automatically highlighted.
62 * @default false
63 */
64 autoHighlight?: boolean;
65 /**
66 * If `true`, the selected option becomes the value of the input
67 * when the Autocomplete loses focus unless the user chooses
68 * a different option or changes the character string in the input.
69 *
70 * When using the `freeSolo` mode, the typed value will be the input value
71 * if the Autocomplete loses focus without highlighting an option.
72 * @default false
73 */
74 autoSelect?: boolean;
75 /**
76 * Control if the input should be blurred when an option is selected:
77 *
78 * - `false` the input is not blurred.
79 * - `true` the input is always blurred.
80 * - `touch` the input is blurred after a touch event.
81 * - `mouse` the input is blurred after a mouse event.
82 * @default false
83 */
84 blurOnSelect?: 'touch' | 'mouse' | true | false;
85 /**
86 * If `true`, the input's text is cleared on blur if no value is selected.
87 *
88 * Set it to `true` if you want to help the user enter a new value.
89 * Set it to `false` if you want to help the user resume their search.
90 * @default !props.freeSolo
91 */
92 clearOnBlur?: boolean;
93 /**
94 * If `true`, clear all values when the user presses escape and the popup is closed.
95 * @default false
96 */
97 clearOnEscape?: boolean;
98 /**
99 * The component name that is using this hook. Used for warnings.
100 */
101 componentName?: string;
102 /**
103 * The default value. Use when the component is not controlled.
104 * @default props.multiple ? [] : null
105 */
106 defaultValue?: AutocompleteValue<Value, Multiple, DisableClearable, FreeSolo>;
107 /**
108 * If `true`, the input can't be cleared.
109 * @default false
110 */
111 disableClearable?: DisableClearable;
112 /**
113 * If `true`, the popup won't close when a value is selected.
114 * @default false
115 */
116 disableCloseOnSelect?: boolean;
117 /**
118 * If `true`, the component is disabled.
119 * @default false
120 */
121 disabled?: boolean;
122 /**
123 * If `true`, will allow focus on disabled items.
124 * @default false
125 */
126 disabledItemsFocusable?: boolean;
127 /**
128 * If `true`, the list box in the popup will not wrap focus.
129 * @default false
130 */
131 disableListWrap?: boolean;
132 /**
133 * A function that determines the filtered options to be rendered on search.
134 *
135 * @default createFilterOptions()
136 * @param {Value[]} options The options to render.
137 * @param {object} state The state of the component.
138 * @returns {Value[]}
139 */
140 filterOptions?: (options: Value[], state: FilterOptionsState<Value>) => Value[];
141 /**
142 * If `true`, hide the selected options from the list box.
143 * @default false
144 */
145 filterSelectedOptions?: boolean;
146 /**
147 * If `true`, the Autocomplete is free solo, meaning that the user input is not bound to provided options.
148 * @default false
149 */
150 freeSolo?: FreeSolo;
151 /**
152 * Used to determine the disabled state for a given option.
153 *
154 * @param {Value} option The option to test.
155 * @returns {boolean}
156 */
157 getOptionDisabled?: (option: Value) => boolean;
158 /**
159 * Used to determine the key for a given option.
160 * This can be useful when the labels of options are not unique (since labels are used as keys by default).
161 *
162 * @param {Value} option The option to get the key for.
163 * @returns {string | number}
164 */
165 getOptionKey?: (option: Value | AutocompleteFreeSoloValueMapping<FreeSolo>) => string | number;
166 /**
167 * Used to determine the string value for a given option.
168 * It's used to fill the input (and the list box options if `renderOption` is not provided).
169 *
170 * If used in free solo mode, it must accept both the type of the options and a string.
171 *
172 * @param {Value} option
173 * @returns {string}
174 * @default (option) => option.label ?? option
175 */
176 getOptionLabel?: (option: Value | AutocompleteFreeSoloValueMapping<FreeSolo>) => string;
177 /**
178 * If provided, the options will be grouped under the returned string.
179 * The groupBy value is also used as the text for group headings when `renderGroup` is not provided.
180 *
181 * @param {Value} options The options to group.
182 * @returns {string}
183 */
184 groupBy?: (option: Value) => string;
185
186 /**
187 * If `true`, the component handles the "Home" and "End" keys when the popup is open.
188 * It should move focus to the first option and last option, respectively.
189 * @default !props.freeSolo
190 */
191 handleHomeEndKeys?: boolean;
192 /**
193 * This prop is used to help implement the accessibility logic.
194 * If you don't provide an id it will fall back to a randomly generated one.
195 */
196 id?: string;
197 /**
198 * If `true`, the highlight can move to the input.
199 * @default false
200 */
201 includeInputInList?: boolean;
202 /**
203 * The input value.
204 */
205 inputValue?: string;
206 /**
207 * Used to determine if the option represents the given value.
208 * Uses strict equality by default.
209 * ⚠️ Both arguments need to be handled, an option can only match with one value.
210 *
211 * @param {Value} option The option to test.
212 * @param {Value} value The value to test against.
213 * @returns {boolean}
214 */
215 isOptionEqualToValue?: (option: Value, value: Value) => boolean;
216 /**
217 * If `true`, `value` must be an array and the menu will support multiple selections.
218 * @default false
219 */
220 multiple?: Multiple;
221 /**
222 * Callback fired when the value changes.
223 *
224 * @param {React.SyntheticEvent} event The event source of the callback.
225 * @param {Value|Value[]} value The new value of the component.
226 * @param {string} reason One of "createOption", "selectOption", "removeOption", "blur" or "clear".
227 * @param {string} [details]
228 */
229 onChange?: (
230 event: React.SyntheticEvent,
231 value: AutocompleteValue<Value, Multiple, DisableClearable, FreeSolo>,
232 reason: AutocompleteChangeReason,
233 details?: AutocompleteChangeDetails<Value>,
234 ) => void;
235 /**
236 * Callback fired when the popup requests to be closed.
237 * Use in controlled mode (see open).
238 *
239 * @param {React.SyntheticEvent} event The event source of the callback.
240 * @param {string} reason Can be: `"toggleInput"`, `"escape"`, `"selectOption"`, `"removeOption"`, `"blur"`.
241 */
242 onClose?: (event: React.SyntheticEvent, reason: AutocompleteCloseReason) => void;
243 /**
244 * Callback fired when the highlight option changes.
245 *
246 * @param {React.SyntheticEvent} event The event source of the callback.
247 * @param {Value} option The highlighted option.
248 * @param {string} reason Can be: `"keyboard"`, `"auto"`, `"mouse"`, `"touch"`.
249 */
250 onHighlightChange?: (
251 event: React.SyntheticEvent,
252 option: Value | null,
253 reason: AutocompleteHighlightChangeReason,
254 ) => void;
255 /**
256 * Callback fired when the input value changes.
257 *
258 * @param {React.SyntheticEvent} event The event source of the callback.
259 * @param {string} value The new value of the text input.
260 * @param {string} reason Can be: `"input"` (user input), `"reset"` (programmatic change), `"clear"`, `"blur"`, `"selectOption"`, `"removeOption"`
261 */
262 onInputChange?: (
263 event: React.SyntheticEvent,
264 value: string,
265 reason: AutocompleteInputChangeReason,
266 ) => void;
267 /**
268 * Callback fired when the popup requests to be opened.
269 * Use in controlled mode (see open).
270 *
271 * @param {React.SyntheticEvent} event The event source of the callback.
272 */
273 onOpen?: (event: React.SyntheticEvent) => void;
274 /**
275 * If `true`, the component is shown.
276 */
277 open?: boolean;
278 /**
279 * If `true`, the popup will open on input focus.
280 * @default false
281 */
282 openOnFocus?: boolean;
283 /**
284 * A list of options that will be shown in the Autocomplete.
285 */
286 options: ReadonlyArray<Value>;
287 /**
288 * If `true`, the component becomes readonly. It is also supported for multiple tags where the tag cannot be deleted.
289 * @default false
290 */
291 readOnly?: boolean;
292 /**
293 * If `true`, the input's text is selected on focus.
294 * It helps the user clear the selected value.
295 * @default !props.freeSolo
296 */
297 selectOnFocus?: boolean;
298 /**
299 * The value of the autocomplete.
300 *
301 * The value must have reference equality with the option in order to be selected.
302 * You can customize the equality behavior with the `isOptionEqualToValue` prop.
303 */
304 value?: AutocompleteValue<Value, Multiple, DisableClearable, FreeSolo>;
305}
306
307export interface UseAutocompleteParameters<
308 Value,
309 Multiple extends boolean | undefined,
310 DisableClearable extends boolean | undefined,
311 FreeSolo extends boolean | undefined,
312> extends UseAutocompleteProps<Value, Multiple, DisableClearable, FreeSolo> {}
313
314export type AutocompleteHighlightChangeReason = 'keyboard' | 'mouse' | 'auto' | 'touch';
315
316export type AutocompleteChangeReason =
317 | 'createOption'
318 | 'selectOption'
319 | 'removeOption'
320 | 'clear'
321 | 'blur';
322export interface AutocompleteChangeDetails<Value = string> {
323 option: Value;
324}
325export type AutocompleteCloseReason =
326 | 'createOption'
327 | 'toggleInput'
328 | 'escape'
329 | 'selectOption'
330 | 'removeOption'
331 | 'blur';
332export type AutocompleteInputChangeReason =
333 | 'input'
334 | 'reset'
335 | 'clear'
336 | 'blur'
337 | 'selectOption'
338 | 'removeOption';
339
340export type AutocompleteGetTagProps = ({ index }: { index: number }) => {
341 key: number;
342 'data-tag-index': number;
343 tabIndex: -1;
344 onDelete: (event: any) => void;
345};
346/**
347 *
348 * Demos:
349 *
350 * - [Autocomplete](https://mui.com/base-ui/react-autocomplete/#hook)
351 *
352 * API:
353 *
354 * - [useAutocomplete API](https://mui.com/base-ui/react-autocomplete/hooks-api/#use-autocomplete)
355 */
356export function useAutocomplete<
357 Value,
358 Multiple extends boolean | undefined = false,
359 DisableClearable extends boolean | undefined = false,
360 FreeSolo extends boolean | undefined = false,
361>(
362 props: UseAutocompleteProps<Value, Multiple, DisableClearable, FreeSolo>,
363): UseAutocompleteReturnValue<Value, Multiple, DisableClearable, FreeSolo>;
364
365export interface UseAutocompleteRenderedOption<Value> {
366 option: Value;
367 index: number;
368}
369
370export interface UseAutocompleteReturnValue<
371 Value,
372 Multiple extends boolean | undefined = false,
373 DisableClearable extends boolean | undefined = false,
374 FreeSolo extends boolean | undefined = false,
375> {
376 /**
377 * Resolver for the root slot's props.
378 * @param externalProps props for the root slot
379 * @returns props that should be spread on the root slot
380 */
381 getRootProps: (externalProps?: any) => React.HTMLAttributes<HTMLDivElement>;
382 /**
383 * Resolver for the input element's props.
384 * @returns props that should be spread on the input element
385 */
386 getInputProps: () => React.InputHTMLAttributes<HTMLInputElement> & {
387 ref: React.Ref<HTMLInputElement>;
388 };
389 /**
390 * Resolver for the input label element's props.
391 * @returns props that should be spread on the input label element
392 */
393 getInputLabelProps: () => Omit<React.HTMLAttributes<HTMLLabelElement>, 'color'>;
394 /**
395 * Resolver for the `clear` button element's props.
396 * @returns props that should be spread on the *clear* button element
397 */
398 getClearProps: () => React.HTMLAttributes<HTMLButtonElement>;
399 /**
400 * Resolver for the popup icon's props.
401 * @returns props that should be spread on the popup icon
402 */
403 getPopupIndicatorProps: () => React.HTMLAttributes<HTMLButtonElement>;
404 /**
405 * A tag props getter.
406 */
407 getTagProps: AutocompleteGetTagProps;
408 /**
409 * Resolver for the listbox component's props.
410 * @returns props that should be spread on the listbox component
411 */
412 getListboxProps: () => React.HTMLAttributes<HTMLUListElement>;
413 /**
414 * Resolver for the rendered option element's props.
415 * @param renderedOption option rendered on the Autocomplete
416 * @returns props that should be spread on the li element
417 */
418 getOptionProps: (
419 renderedOption: UseAutocompleteRenderedOption<Value>,
420 ) => React.HTMLAttributes<HTMLLIElement> & { key: any };
421 /**
422 * Id for the Autocomplete.
423 */
424 id: string;
425 /**
426 * The input value.
427 */
428 inputValue: string;
429 /**
430 * The value of the autocomplete.
431 */
432 value: AutocompleteValue<Value, Multiple, DisableClearable, FreeSolo>;
433 /**
434 * If `true`, the component input has some values.
435 */
436 dirty: boolean;
437 /**
438 * If `true`, the listbox is being displayed.
439 */
440 expanded: boolean;
441 /**
442 * If `true`, the popup is open on the component.
443 */
444 popupOpen: boolean;
445 /**
446 * If `true`, the component is focused.
447 */
448 focused: boolean;
449 /**
450 * An HTML element that is used to set the position of the component.
451 */
452 anchorEl: null | HTMLElement;
453 /**
454 * Setter for the component `anchorEl`.
455 * @returns function for setting `anchorEl`
456 */
457 setAnchorEl: () => void;
458 /**
459 * Index of the focused tag for the component.
460 */
461 focusedTag: number;
462 /**
463 * The options to render. It's either `Value[]` or `AutocompleteGroupedOption<Value>[]` if the groupBy prop is provided.
464 */
465 groupedOptions: Value[] | Array<AutocompleteGroupedOption<Value>>;
466}
467
468export default useAutocomplete;