UNPKG

14.8 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>) => 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"`.
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 * Array of options.
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 = 'input' | 'reset' | 'clear';
333
334export type AutocompleteGetTagProps = ({ index }: { index: number }) => {
335 key: number;
336 'data-tag-index': number;
337 tabIndex: -1;
338 onDelete: (event: any) => void;
339};
340/**
341 *
342 * Demos:
343 *
344 * - [Autocomplete](https://mui.com/base-ui/react-autocomplete/#hook)
345 *
346 * API:
347 *
348 * - [useAutocomplete API](https://mui.com/base-ui/react-autocomplete/hooks-api/#use-autocomplete)
349 */
350export function useAutocomplete<
351 Value,
352 Multiple extends boolean | undefined = false,
353 DisableClearable extends boolean | undefined = false,
354 FreeSolo extends boolean | undefined = false,
355>(
356 props: UseAutocompleteProps<Value, Multiple, DisableClearable, FreeSolo>,
357): UseAutocompleteReturnValue<Value, Multiple, DisableClearable, FreeSolo>;
358
359export interface UseAutocompleteRenderedOption<Value> {
360 option: Value;
361 index: number;
362}
363
364export interface UseAutocompleteReturnValue<
365 Value,
366 Multiple extends boolean | undefined = false,
367 DisableClearable extends boolean | undefined = false,
368 FreeSolo extends boolean | undefined = false,
369> {
370 /**
371 * Resolver for the root slot's props.
372 * @param externalProps props for the root slot
373 * @returns props that should be spread on the root slot
374 */
375 getRootProps: (externalProps?: any) => React.HTMLAttributes<HTMLDivElement>;
376 /**
377 * Resolver for the input element's props.
378 * @returns props that should be spread on the input element
379 */
380 getInputProps: () => React.InputHTMLAttributes<HTMLInputElement> & {
381 ref: React.Ref<HTMLInputElement>;
382 };
383 /**
384 * Resolver for the input label element's props.
385 * @returns props that should be spread on the input label element
386 */
387 getInputLabelProps: () => Omit<React.HTMLAttributes<HTMLLabelElement>, 'color'>;
388 /**
389 * Resolver for the `clear` button element's props.
390 * @returns props that should be spread on the *clear* button element
391 */
392 getClearProps: () => React.HTMLAttributes<HTMLButtonElement>;
393 /**
394 * Resolver for the popup icon's props.
395 * @returns props that should be spread on the popup icon
396 */
397 getPopupIndicatorProps: () => React.HTMLAttributes<HTMLButtonElement>;
398 /**
399 * A tag props getter.
400 */
401 getTagProps: AutocompleteGetTagProps;
402 /**
403 * Resolver for the listbox component's props.
404 * @returns props that should be spread on the listbox component
405 */
406 getListboxProps: () => React.HTMLAttributes<HTMLUListElement>;
407 /**
408 * Resolver for the rendered option element's props.
409 * @param renderedOption option rendered on the Autocomplete
410 * @returns props that should be spread on the li element
411 */
412 getOptionProps: (
413 renderedOption: UseAutocompleteRenderedOption<Value>,
414 ) => React.HTMLAttributes<HTMLLIElement>;
415 /**
416 * Id for the Autocomplete.
417 */
418 id: string;
419 /**
420 * The input value.
421 */
422 inputValue: string;
423 /**
424 * The value of the autocomplete.
425 */
426 value: AutocompleteValue<Value, Multiple, DisableClearable, FreeSolo>;
427 /**
428 * If `true`, the component input has some values.
429 */
430 dirty: boolean;
431 /**
432 * If `true`, the listbox is being displayed.
433 */
434 expanded: boolean;
435 /**
436 * If `true`, the popup is open on the component.
437 */
438 popupOpen: boolean;
439 /**
440 * If `true`, the component is focused.
441 */
442 focused: boolean;
443 /**
444 * An HTML element that is used to set the position of the component.
445 */
446 anchorEl: null | HTMLElement;
447 /**
448 * Setter for the component `anchorEl`.
449 * @returns function for setting `anchorEl`
450 */
451 setAnchorEl: () => void;
452 /**
453 * Index of the focused tag for the component.
454 */
455 focusedTag: number;
456 /**
457 * The options to render. It's either `Value[]` or `AutocompleteGroupedOption<Value>[]` if the groupBy prop is provided.
458 */
459 groupedOptions: Value[] | Array<AutocompleteGroupedOption<Value>>;
460}