import { KeyboardEvent, ReactElement, RefObject } from 'react'; import { SelectFieldCacheOptions, SelectFieldEagerLoader, SelectFieldGroupByValue, SelectFieldGroupLazyLoader, SelectFieldGroupedOption, SelectFieldOffsetLazyLoader, SelectFieldOption, SelectFieldPageLazyLoader, SelectFieldPinnedOptions, SelectFieldSearchProps } from '../SelectField/types'; export type SelectMenuOption = SelectFieldOption; export type SelectMenuGroupByValue = SelectFieldGroupByValue; export type SelectMenuGroupedOption = SelectFieldGroupedOption; /** * Configuration options for the SelectMenu cache. * @property enabled - Whether caching is enabled. Defaults to true. * @property maxSize - Maximum number of cached entries before clearing the cache. Defaults to 15. */ export type SelectMenuCacheOptions = SelectFieldCacheOptions; /** * Imperative handle for the SelectMenu component. * @property clearCache - Clears the options cache. * @property invalidate - Clears the cache and triggers a fresh options load from the data source. */ export type SelectMenuHandle = { clearCache: () => void; invalidate: () => void; }; export type SelectMenuEagerLoader = SelectFieldEagerLoader; export type SelectMenuPageLazyLoader = SelectFieldPageLazyLoader; export type SelectMenuOffsetLazyLoader = SelectFieldOffsetLazyLoader; export type SelectMenuGroupLazyLoader = SelectFieldGroupLazyLoader; export type SelectMenuPinnedOptions = SelectFieldPinnedOptions; export type SelectMenuSearchProps = SelectFieldSearchProps; /** * Props provided to the trigger render function. * @property ref - Ref to attach to the trigger element for positioning * @property onClick - Click handler to toggle the menu * @property onKeyDown - Key handler for keyboard navigation * @property aria-haspopup - ARIA attribute indicating the trigger opens a listbox * @property aria-controls - ARIA attribute linking to the menu element * @property aria-expanded - ARIA attribute indicating whether the menu is open * @property data-state - Data attribute indicating the open/close state */ export type SelectMenuTriggerProps = { ref: RefObject; onClick: () => void; onKeyDown: (e: KeyboardEvent) => void; "aria-haspopup": "listbox"; "aria-controls": string; "aria-expanded": boolean; "data-state": "open" | "close"; }; type SelectMenuCommonProps = { /** * The id of the select menu. */ id?: string; /** * Render function that receives trigger props and returns the element that opens the menu. */ trigger: (props: SelectMenuTriggerProps) => ReactElement; /** * Called when a key is pressed inside the menu (search field or listbox), before the * menu's own key handling. Use `e.preventDefault()` to suppress the default behavior. */ onMenuKeyDown?: (e: KeyboardEvent) => void; /** * Called when the menu closes implicitly — due to Tab navigation, clicking outside, * or other ambient focus loss. Focus is not restored to the trigger in these cases. */ onImplicitClose?: () => void; /** * Called when the menu closes explicitly — the user intentionally dismissed it * via Escape, selecting an option, or toggling the trigger. Focus is restored to the trigger. */ onExplicitClose?: () => void; /** * Accessible label for the menu. Used by screen readers but not rendered visually. */ label: string; /** * Placeholder text shown in the search input inside the menu. */ searchPlaceholder?: string; /** * The selected option. Must be controlled state. */ value: SelectMenuOption | null; /** * Callback fired when the selected option changes. * @param option - The newly selected option, or null if cleared. */ onSelectedOptionChange: (option: SelectMenuOption | null) => void; /** * Defines the initial loading behavior of the options. * @default "auto" */ initialLoad?: "auto" | "immediate" | "open"; /** * Options to pin to the top of the list. */ pinned?: SelectMenuPinnedOptions; /** * Configuration for caching loadOptions results. * Caching is enabled by default. Set `{ enabled: false }` to disable. */ cache?: SelectMenuCacheOptions; /** * Controls how the menu is displayed. * @default "auto" * @description "auto" uses a popover on desktop and a dialog on mobile. * @description "popover" always uses a popover. * @description "dialog" always uses a dialog. */ displayMenuAs?: "auto" | "popover" | "dialog"; /** * Whether to virtualize the list using windowed rendering. * Enable for large option sets to improve performance. * @default false */ virtualize?: boolean; /** * Whether to disable the search input inside the menu. * When true, the menu shows only the list without a search field. * @default false */ disableSearch?: boolean; /** * Width of the popover. Only applies when `displayMenuAs="popover"` (or when the adaptive mode resolves to popover). Has no effect in dialog mode. * Accepts a CSS width value or "reference" to match the trigger element's width. * @default 320 */ popoverWidth?: "reference" | number | string; } & SelectMenuSearchProps; type SelectMenuGroupingProps = { /** * Function to convert a group value to a display label. * Only used when options have a `group` property. */ groupToString?: (groupValue: SelectMenuGroupByValue) => string; /** * Custom comparator function to sort groups. */ groupSorter?: (a: SelectMenuGroupByValue, b: SelectMenuGroupByValue) => number; }; type SelectMenuNonGroupingProps = { groupToString?: never; groupSorter?: never; }; export type SelectMenuPropsLazyPage = SelectMenuCommonProps & { lazy: "page"; lazyOptions?: { pageSize?: number; }; loadOptions: SelectMenuPageLazyLoader; } & SelectMenuNonGroupingProps; export type SelectMenuPropsLazyOffset = SelectMenuCommonProps & { lazy: "offset"; lazyOptions?: { limit?: number; }; loadOptions: SelectMenuOffsetLazyLoader; } & SelectMenuNonGroupingProps; export type SelectMenuPropsLazyGroup = SelectMenuCommonProps & { lazy: "group"; lazyOptions?: object; loadOptions: SelectMenuGroupLazyLoader; } & SelectMenuGroupingProps; export type SelectMenuPropsEager = SelectMenuCommonProps & { lazy?: false; loadOptions: SelectMenuEagerLoader; } & SelectMenuGroupingProps; export type SelectMenuPropsLazy = SelectMenuPropsLazyPage | SelectMenuPropsLazyOffset | SelectMenuPropsLazyGroup; export type SelectMenuProps = SelectMenuPropsLazy | SelectMenuPropsEager; export {};