UNPKG

14.1 kBTypeScriptView Raw
1import * as React from 'react';
2
3export interface CreateFilterOptionsConfig<T> {
4 ignoreAccents?: boolean;
5 ignoreCase?: boolean;
6 limit?: number;
7 matchFrom?: 'any' | 'start';
8 stringify?: (option: T) => string;
9 trim?: boolean;
10}
11
12export interface FilterOptionsState<T> {
13 inputValue: string;
14 getOptionLabel: (option: T) => string;
15}
16
17export interface AutocompleteGroupedOption<T = string> {
18 key: number;
19 index: number;
20 group: string;
21 options: T[];
22}
23
24export function createFilterOptions<T>(
25 config?: CreateFilterOptionsConfig<T>,
26): (options: T[], state: FilterOptionsState<T>) => T[];
27
28export type AutocompleteFreeSoloValueMapping<FreeSolo> = FreeSolo extends true ? string : never;
29
30export type AutocompleteValue<T, Multiple, DisableClearable, FreeSolo> = Multiple extends true
31 ? Array<T | AutocompleteFreeSoloValueMapping<FreeSolo>>
32 : DisableClearable extends true
33 ? NonNullable<T | AutocompleteFreeSoloValueMapping<FreeSolo>>
34 : T | null | AutocompleteFreeSoloValueMapping<FreeSolo>;
35
36export interface UseAutocompleteProps<
37 T,
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>) => boolean;
53 /**
54 * If `true`, the portion of the selected suggestion that has not been typed by the user,
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 `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 to `true` if you want to help the user enter a new value.
89 * Set 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<T, 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 {T[]} options The options to render.
137 * @param {object} state The state of the component.
138 * @returns {T[]}
139 */
140 filterOptions?: (options: T[], state: FilterOptionsState<T>) => T[];
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 {T} option The option to test.
155 * @returns {boolean}
156 */
157 getOptionDisabled?: (option: T) => boolean;
158 /**
159 * Used to determine the string value for a given option.
160 * It's used to fill the input (and the list box options if `renderOption` is not provided).
161 *
162 * If used in free solo mode, it must accept both the type of the options and a string.
163 *
164 * @param {T} option
165 * @returns {string}
166 * @default (option) => option.label ?? option
167 */
168 getOptionLabel?: (option: T | AutocompleteFreeSoloValueMapping<FreeSolo>) => string;
169 /**
170 * If provided, the options will be grouped under the returned string.
171 * The groupBy value is also used as the text for group headings when `renderGroup` is not provided.
172 *
173 * @param {T} options The options to group.
174 * @returns {string}
175 */
176 groupBy?: (option: T) => string;
177
178 /**
179 * If `true`, the component handles the "Home" and "End" keys when the popup is open.
180 * It should move focus to the first option and last option, respectively.
181 * @default !props.freeSolo
182 */
183 handleHomeEndKeys?: boolean;
184 /**
185 * This prop is used to help implement the accessibility logic.
186 * If you don't provide an id it will fall back to a randomly generated one.
187 */
188 id?: string;
189 /**
190 * If `true`, the highlight can move to the input.
191 * @default false
192 */
193 includeInputInList?: boolean;
194 /**
195 * The input value.
196 */
197 inputValue?: string;
198 /**
199 * Used to determine if the option represents the given value.
200 * Uses strict equality by default.
201 * ⚠️ Both arguments need to be handled, an option can only match with one value.
202 *
203 * @param {T} option The option to test.
204 * @param {T} value The value to test against.
205 * @returns {boolean}
206 */
207 isOptionEqualToValue?: (option: T, value: T) => boolean;
208 /**
209 * If `true`, `value` must be an array and the menu will support multiple selections.
210 * @default false
211 */
212 multiple?: Multiple;
213 /**
214 * Callback fired when the value changes.
215 *
216 * @param {React.SyntheticEvent} event The event source of the callback.
217 * @param {T|T[]} value The new value of the component.
218 * @param {string} reason One of "createOption", "selectOption", "removeOption", "blur" or "clear".
219 * @param {string} [details]
220 */
221 onChange?: (
222 event: React.SyntheticEvent,
223 value: AutocompleteValue<T, Multiple, DisableClearable, FreeSolo>,
224 reason: AutocompleteChangeReason,
225 details?: AutocompleteChangeDetails<T>,
226 ) => void;
227 /**
228 * Callback fired when the popup requests to be closed.
229 * Use in controlled mode (see open).
230 *
231 * @param {React.SyntheticEvent} event The event source of the callback.
232 * @param {string} reason Can be: `"toggleInput"`, `"escape"`, `"selectOption"`, `"removeOption"`, `"blur"`.
233 */
234 onClose?: (event: React.SyntheticEvent, reason: AutocompleteCloseReason) => void;
235 /**
236 * Callback fired when the highlight option changes.
237 *
238 * @param {React.SyntheticEvent} event The event source of the callback.
239 * @param {T} option The highlighted option.
240 * @param {string} reason Can be: `"keyboard"`, `"auto"`, `"mouse"`, `"touch"`.
241 */
242 onHighlightChange?: (
243 event: React.SyntheticEvent,
244 option: T | null,
245 reason: AutocompleteHighlightChangeReason,
246 ) => void;
247 /**
248 * Callback fired when the input value changes.
249 *
250 * @param {React.SyntheticEvent} event The event source of the callback.
251 * @param {string} value The new value of the text input.
252 * @param {string} reason Can be: `"input"` (user input), `"reset"` (programmatic change), `"clear"`.
253 */
254 onInputChange?: (
255 event: React.SyntheticEvent,
256 value: string,
257 reason: AutocompleteInputChangeReason,
258 ) => void;
259 /**
260 * Callback fired when the popup requests to be opened.
261 * Use in controlled mode (see open).
262 *
263 * @param {React.SyntheticEvent} event The event source of the callback.
264 */
265 onOpen?: (event: React.SyntheticEvent) => void;
266 /**
267 * If `true`, the component is shown.
268 */
269 open?: boolean;
270 /**
271 * If `true`, the popup will open on input focus.
272 * @default false
273 */
274 openOnFocus?: boolean;
275 /**
276 * Array of options.
277 */
278 options: ReadonlyArray<T>;
279 /**
280 * If `true`, the component becomes readonly. It is also supported for multiple tags where the tag cannot be deleted.
281 * @default false
282 */
283 readOnly?: boolean;
284 /**
285 * If `true`, the input's text is selected on focus.
286 * It helps the user clear the selected value.
287 * @default !props.freeSolo
288 */
289 selectOnFocus?: boolean;
290 /**
291 * The value of the autocomplete.
292 *
293 * The value must have reference equality with the option in order to be selected.
294 * You can customize the equality behavior with the `isOptionEqualToValue` prop.
295 */
296 value?: AutocompleteValue<T, Multiple, DisableClearable, FreeSolo>;
297}
298
299export interface UseAutocompleteParameters<
300 T,
301 Multiple extends boolean | undefined,
302 DisableClearable extends boolean | undefined,
303 FreeSolo extends boolean | undefined,
304> extends UseAutocompleteProps<T, Multiple, DisableClearable, FreeSolo> {}
305
306export type AutocompleteHighlightChangeReason = 'keyboard' | 'mouse' | 'auto' | 'touch';
307
308export type AutocompleteChangeReason =
309 | 'createOption'
310 | 'selectOption'
311 | 'removeOption'
312 | 'clear'
313 | 'blur';
314export interface AutocompleteChangeDetails<T = string> {
315 option: T;
316}
317export type AutocompleteCloseReason =
318 | 'createOption'
319 | 'toggleInput'
320 | 'escape'
321 | 'selectOption'
322 | 'removeOption'
323 | 'blur';
324export type AutocompleteInputChangeReason = 'input' | 'reset' | 'clear';
325
326export type AutocompleteGetTagProps = ({ index }: { index: number }) => {
327 key: number;
328 'data-tag-index': number;
329 tabIndex: -1;
330 onDelete: (event: any) => void;
331};
332/**
333 *
334 * Demos:
335 *
336 * - [Autocomplete](https://mui.com/base/react-autocomplete/#hook)
337 *
338 * API:
339 *
340 * - [useAutocomplete API](https://mui.com/base/react-autocomplete/hooks-api/#use-autocomplete)
341 */
342export default function useAutocomplete<
343 T,
344 Multiple extends boolean | undefined = false,
345 DisableClearable extends boolean | undefined = false,
346 FreeSolo extends boolean | undefined = false,
347>(
348 props: UseAutocompleteProps<T, Multiple, DisableClearable, FreeSolo>,
349): UseAutocompleteReturnValue<T, Multiple, DisableClearable, FreeSolo>;
350
351export interface UseAutocompleteRenderedOption<T> {
352 option: T;
353 index: number;
354}
355
356export interface UseAutocompleteReturnValue<
357 T,
358 Multiple extends boolean | undefined = false,
359 DisableClearable extends boolean | undefined = false,
360 FreeSolo extends boolean | undefined = false,
361> {
362 /**
363 * Resolver for the root slot's props.
364 * @param externalProps props for the root slot
365 * @returns props that should be spread on the root slot
366 */
367 getRootProps: (externalProps?: any) => React.HTMLAttributes<HTMLDivElement>;
368 /**
369 * Resolver for the input element's props.
370 * @returns props that should be spread on the input element
371 */
372 getInputProps: () => React.InputHTMLAttributes<HTMLInputElement>;
373 /**
374 * Resolver for the input label element's props.
375 * @returns props that should be spread on the input label element
376 */
377 getInputLabelProps: () => Omit<React.HTMLAttributes<HTMLLabelElement>, 'color'>;
378 /**
379 * Resolver for the `clear` button element's props.
380 * @returns props that should be spread on the *clear* button element
381 */
382 getClearProps: () => React.HTMLAttributes<HTMLButtonElement>;
383 /**
384 * Resolver for the popup icon's props.
385 * @returns props that should be spread on the popup icon
386 */
387 getPopupIndicatorProps: () => React.HTMLAttributes<HTMLButtonElement>;
388 /**
389 * A tag props getter.
390 */
391 getTagProps: AutocompleteGetTagProps;
392 /**
393 * Resolver for the listbox component's props.
394 * @returns props that should be spread on the listbox component
395 */
396 getListboxProps: () => React.HTMLAttributes<HTMLUListElement>;
397 /**
398 * Resolver for the rendered option element's props.
399 * @param renderedOption option rendered on the Autocomplete
400 * @returns props that should be spread on the li element
401 */
402 getOptionProps: (
403 renderedOption: UseAutocompleteRenderedOption<T>,
404 ) => React.HTMLAttributes<HTMLLIElement>;
405 /**
406 * Id for the Autocomplete.
407 */
408 id: string;
409 /**
410 * The input value.
411 */
412 inputValue: string;
413 /**
414 * The value of the autocomplete.
415 */
416 value: AutocompleteValue<T, Multiple, DisableClearable, FreeSolo>;
417 /**
418 * If `true`, the component input has some values.
419 */
420 dirty: boolean;
421 /**
422 * If `true`, the listbox is being displayed.
423 */
424 expanded: boolean;
425 /**
426 * If `true`, the popup is open on the component.
427 */
428 popupOpen: boolean;
429 /**
430 * If `true`, the component is focused.
431 */
432 focused: boolean;
433 /**
434 * An HTML element that is used to set the position of the component.
435 */
436 anchorEl: null | HTMLElement;
437 /**
438 * Setter for the component `anchorEl`.
439 * @returns function for setting `anchorEl`
440 */
441 setAnchorEl: () => void;
442 /**
443 * Index of the focused tag for the component.
444 */
445 focusedTag: number;
446 /**
447 * The options to render. It's either `T[]` or `AutocompleteGroupedOption<T>[]` if the groupBy prop is provided.
448 */
449 groupedOptions: T[] | Array<AutocompleteGroupedOption<T>>;
450}