UNPKG

@mui/base

Version:

Base UI is a library of headless ('unstyled') React components and low-level hooks. You gain complete control over your app's CSS and accessibility features.

225 lines (224 loc) 8.79 kB
import * as React from 'react'; import { ListAction, ListState, UseListRootSlotProps } from '../useList'; import { SelectOption } from '../useOption/useOption.types'; import { SelectProviderValue } from './SelectProvider'; import { MuiCancellableEventHandler } from '../utils/MuiCancellableEvent'; import { UseButtonRootSlotProps } from '../useButton'; export type SelectChangeEventType = React.MouseEvent<Element, MouseEvent> | React.KeyboardEvent<Element> | React.FocusEvent<Element, Element> | null; export type SelectValue<Value, Multiple> = Multiple extends true ? Value[] : Value | null; export interface SelectOptionDefinition<Value> { value: Value; disabled?: boolean; label: string; } export interface UseSelectParameters<OptionValue, Multiple extends boolean = false> { /** * A function used to determine if two options' values are equal. * By default, reference equality is used. * * There is a performance impact when using the `areOptionsEqual` prop (proportional to the number of options). * Therefore, it's recommented to use the default reference equality comparison whenever possible. */ areOptionsEqual?: (a: OptionValue, b: OptionValue) => boolean; /** * If `true`, the select will be open by default. * @default false */ defaultOpen?: boolean; /** * The default selected value. Use when the component is not controlled. */ defaultValue?: SelectValue<OptionValue, Multiple>; /** * If `true`, the select is disabled. * @default false */ disabled?: boolean; /** * The ref of the trigger button element. */ buttonRef?: React.Ref<Element>; /** * The `id` attribute of the listbox element. */ listboxId?: string; /** * The ref of the listbox element. */ listboxRef?: React.Ref<Element>; /** * If `true`, the end user can select multiple values. * This affects the type of the `value`, `defaultValue`, and `onChange` props. * * @default false */ multiple?: Multiple; /** * The `name` attribute of the hidden input element. * This is useful when the select is embedded in a form and you want to access the selected value in the form data. */ name?: string; /** * If `true`, the select embedded in a form must have a selected value. * Otherwise, the form submission will fail. */ required?: boolean; /** * Callback fired when an option is selected. */ onChange?: (event: React.MouseEvent | React.KeyboardEvent | React.FocusEvent | null, value: SelectValue<OptionValue, Multiple>) => void; /** * Callback fired when an option is highlighted. */ onHighlightChange?: (event: React.MouseEvent<Element, MouseEvent> | React.KeyboardEvent<Element> | React.FocusEvent<Element, Element> | null, highlighted: OptionValue | null) => void; /** * Callback fired when the listbox is opened or closed. */ onOpenChange?: (open: boolean) => void; /** * Controls the open state of the select's listbox. * This is the controlled equivalent of the `defaultOpen` prop. */ open?: boolean; /** * An alternative way to specify the options. * If this parameter is set, options defined as JSX children are ignored. */ options?: ReadonlyArray<SelectOptionDefinition<OptionValue>>; /** * A function to convert the currently selected value to a string. * Used to set a value of a hidden input associated with the select, * so that the selected value can be posted with a form. */ getSerializedValue?: (option: SelectValue<SelectOption<OptionValue>, Multiple>) => React.InputHTMLAttributes<HTMLInputElement>['value']; /** * A function used to convert the option label to a string. * This is useful when labels are elements and need to be converted to plain text * to enable keyboard navigation with character keys. * * @default defaultOptionStringifier */ getOptionAsString?: (option: SelectOption<OptionValue>) => string; /** * The selected value. * Set to `null` to deselect all options. */ value?: SelectValue<OptionValue, Multiple>; /** * The name of the component using useSelect. * For debugging purposes. * @default 'useSelect' */ componentName?: string; } interface UseSelectButtonSlotEventHandlers { onMouseDown: MuiCancellableEventHandler<React.MouseEvent>; } export type UseSelectButtonSlotProps<TOther = {}> = UseButtonRootSlotProps<Omit<TOther, keyof UseSelectButtonSlotEventHandlers>> & UseSelectButtonSlotEventHandlers & { 'aria-expanded': React.AriaAttributes['aria-expanded']; 'aria-controls': React.AriaAttributes['aria-controls']; role: React.HTMLAttributes<Element>['role']; ref: React.RefCallback<Element> | null; }; interface UseSelectHiddenInputSlotEventHandlers { onChange: MuiCancellableEventHandler<React.ChangeEvent<HTMLInputElement>>; } export type UseSelectHiddenInputSlotProps<TOther = {}> = UseSelectHiddenInputSlotEventHandlers & React.InputHTMLAttributes<HTMLInputElement> & TOther; interface UseSelectListboxSlotEventHandlers { onBlur: MuiCancellableEventHandler<React.FocusEvent<HTMLElement>>; } export type UseSelectListboxSlotProps<TOther = {}> = UseListRootSlotProps<Omit<TOther, keyof UseSelectListboxSlotEventHandlers>> & UseSelectListboxSlotEventHandlers & { 'aria-multiselectable': React.AriaAttributes['aria-multiselectable']; id: string | undefined; role: React.HTMLAttributes<Element>['role']; }; export interface UseSelectReturnValue<Value, Multiple> { /** * If `true`, the trigger button is active (pressed). */ buttonActive: boolean; /** * If `true`, the trigger button has a visible focus. */ buttonFocusVisible: boolean; /** * Ref to the button slot DOM node. */ buttonRef: React.RefCallback<Element> | null; /** * If `true`, the select is disabled. */ disabled: boolean; /** * Action dispatcher for the select component. * Allows to programmatically control the select. */ dispatch: (action: ListAction<Value> | SelectAction<Value>) => void; /** * Resolver for the button slot's props. * @param externalProps event handlers for the button slot * @returns props that should be spread on the button slot */ getButtonProps: <ExternalProps extends Record<string, unknown> = {}>(externalProps?: ExternalProps) => UseSelectButtonSlotProps<ExternalProps>; /** * Resolver for the hidden input slot's props. * @param externalProps event handlers for the hidden input slot * @returns HTML input attributes that should be spread on the hidden input slot */ getHiddenInputProps: <ExternalProps extends Record<string, unknown> = {}>(externalProps?: ExternalProps) => UseSelectHiddenInputSlotProps<ExternalProps>; /** * Resolver for the listbox slot's props. * @param externalProps event handlers for the listbox slot * @returns props that should be spread on the listbox slot */ getListboxProps: <ExternalProps extends Record<string, unknown> = {}>(externalProps?: ExternalProps) => UseSelectListboxSlotProps<ExternalProps>; /** * A function that returns the metadata of an option with a given value. * * @param optionValue the value of the option * @returns */ getOptionMetadata: (optionValue: Value) => SelectOption<Value> | undefined; /** * A value to be passed to the `SelectProvider` component. */ contextValue: SelectProviderValue<Value>; /** * The value of the highlighted option. */ highlightedOption: Value | null; /** * Ref to the listbox slot DOM node. */ listboxRef: React.RefCallback<Element> | null; /** * If `true`, the listbox is open. */ open: boolean; /** * Values of all the registered options. */ options: Value[]; /** * The value of the selected option(s). */ value: SelectValue<Value, Multiple>; } export declare const SelectActionTypes: { readonly buttonClick: "buttonClick"; readonly browserAutoFill: "browserAutoFill"; }; export interface ButtonClickAction { type: typeof SelectActionTypes.buttonClick; event: React.MouseEvent; } export interface BrowserAutofillAction<OptionValue> { type: typeof SelectActionTypes.browserAutoFill; item: OptionValue; event: React.ChangeEvent; } export type SelectAction<OptionValue> = ButtonClickAction | BrowserAutofillAction<OptionValue>; export interface SelectInternalState<OptionValue> extends ListState<OptionValue> { open: boolean; } export {};