import { KeyboardEvent, ReactElement, RefObject } from 'react';
import { SelectFieldGroupByValue, SelectFieldOption, SelectFieldOptionContent } from '../SelectField/types';
import { MultiSelectFieldCacheOptions, MultiSelectFieldEagerLoader, MultiSelectFieldGroupLazyLoader, MultiSelectFieldOffsetLazyLoader, MultiSelectFieldPageLazyLoader, MultiSelectFieldPinnedOptions, MultiSelectFieldSearchProps } from '../MultiSelectField/types';
import { AddNewItemProps } from '../../internal/types/addNewItemTypes';
import { ConfirmationProp } from '../../internal/types/confirmationTypes';
import { BulkActionConfig } from '../../internal/types/bulkActionTypes';
/**
 * Configuration for the "Select All" / "Select Filtered" rows.
 */
export type MultiSelectMenuBulkActionConfig = BulkActionConfig;
/**
 * Rich content configuration for a MultiSelectMenu option row.
 * Controls the avatar, icon, description, and chip display within an option.
 */
export type MultiSelectMenuOptionContent = SelectFieldOptionContent;
export type MultiSelectMenuOption = SelectFieldOption;
export type MultiSelectMenuGroupByValue = SelectFieldGroupByValue;
/**
 * Configuration options for the MultiSelectMenu 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 MultiSelectMenuCacheOptions = MultiSelectFieldCacheOptions;
/**
 * Imperative handle for the MultiSelectMenu component.
 * @property clearCache - Clears the options cache.
 * @property invalidate - Clears the cache and triggers a fresh options load from the data source.
 */
export type MultiSelectMenuHandle = {
    clearCache: () => void;
    invalidate: () => void;
};
export type MultiSelectMenuEagerLoader = MultiSelectFieldEagerLoader;
export type MultiSelectMenuPageLazyLoader = MultiSelectFieldPageLazyLoader;
export type MultiSelectMenuOffsetLazyLoader = MultiSelectFieldOffsetLazyLoader;
export type MultiSelectMenuGroupLazyLoader = MultiSelectFieldGroupLazyLoader;
export type MultiSelectMenuPinnedOptions = MultiSelectFieldPinnedOptions;
export type MultiSelectMenuSearchProps = MultiSelectFieldSearchProps;
/**
 * 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 MultiSelectMenuTriggerProps = {
    ref: RefObject<HTMLButtonElement>;
    onClick: () => void;
    onKeyDown: (e: KeyboardEvent<HTMLButtonElement>) => void;
    "aria-haspopup": "listbox";
    "aria-controls": string;
    "aria-expanded": boolean;
    "data-state": "open" | "close";
};
type MultiSelectMenuCommonProps = {
    /**
     * The id of the multi-select menu.
     */
    id?: string;
    /**
     * Render function that receives trigger props and returns the element that opens the menu.
     */
    trigger: (props: MultiSelectMenuTriggerProps) => 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 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 options. Must be controlled state.
     */
    value: MultiSelectMenuOption[];
    /**
     * Callback fired when the selected options change.
     * @param options - The new array of selected options.
     */
    onSelectedOptionsChange: (options: MultiSelectMenuOption[]) => 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?: MultiSelectMenuPinnedOptions;
    /**
     * Configuration for caching loadOptions results.
     * Caching is enabled by default. Set `{ enabled: false }` to disable.
     */
    cache?: MultiSelectMenuCacheOptions;
    /**
     * 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.
     * @default false
     */
    virtualize?: boolean;
    /**
     * Whether to disable the search input inside the menu.
     * @default false
     */
    disableSearch?: boolean;
    /**
     * Configuration for the "Select All" option at the top of the list.
     * Shown when the search input is empty.
     *
     * Pass exactly one of `onClick` (fire-and-forget; the consumer commits via
     * `onSelectedOptionsChange`) or `compute` (returns the next selection;
     * integrates with confirmation drafts and supports async resolution).
     *
     * `compute` is required when you want the action to participate in the
     * confirmation draft. While a `compute` promise is pending, the menu shows
     * a loading state, disables all options, and disables Apply.
     *
     * `checkState` may be a static value or a function of the current selection
     * (the confirmation draft when confirmation is enabled, otherwise the
     * committed value), so the row's checkbox can reflect how much of the set is
     * selected.
     */
    selectAll?: MultiSelectMenuBulkActionConfig;
    /**
     * Function that receives the current search value and returns configuration for
     * the "Select Filtered" option at the top of the list.
     * Shown when a search term is active (instead of Select All).
     *
     * See `selectAll` for the `onClick` / `compute` choice.
     */
    selectFiltered?: (searchValue: string) => MultiSelectMenuBulkActionConfig;
    /**
     * 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;
    /**
     * When set, the menu becomes a buffered selection: clicks update a draft
     * value inside the open menu, and `onSelectedOptionsChange` only fires when
     * the user clicks Apply. Dismissing the menu (Escape, click outside,
     * toggling the trigger) discards the draft. Pass `true` for the default
     * "Apply" / "Cancel" labels, or an object to customize.
     *
     * Note: a `selectAll` / `selectFiltered` row configured with `onClick`
     * bypasses the draft and applies immediately. Use the `compute` variant
     * to integrate the bulk action with the draft.
     * @default undefined (off — selections apply immediately)
     */
    confirmation?: ConfirmationProp;
    /**
     * Configures a "Clear" button in the menu footer. Presence of this prop
     * enables the button; omit to suppress.
     *
     * - `onClick` — called when the user clicks Clear.
     * - `label` — button label (default "Clear").
     * - `disabled` — whether the button is inert. Filter adapters typically
     *   tie this to `!isActive(filter)` so the button is dim when nothing is
     *   selected.
     */
    clear?: {
        onClick: () => void;
        label?: string;
        disabled?: boolean;
    };
} & MultiSelectMenuSearchProps & AddNewItemProps;
type MultiSelectMenuGroupingProps = {
    /**
     * Function to convert a group value to a display label.
     */
    groupToString?: (groupValue: MultiSelectMenuGroupByValue) => string;
    /**
     * Custom comparator function to sort groups.
     */
    groupSorter?: (a: MultiSelectMenuGroupByValue, b: MultiSelectMenuGroupByValue) => number;
};
type MultiSelectMenuNonGroupingProps = {
    groupToString?: never;
    groupSorter?: never;
};
export type MultiSelectMenuPropsLazyPage = MultiSelectMenuCommonProps & {
    lazy: "page";
    lazyOptions?: {
        pageSize?: number;
    };
    loadOptions: MultiSelectMenuPageLazyLoader;
} & MultiSelectMenuNonGroupingProps;
export type MultiSelectMenuPropsLazyOffset = MultiSelectMenuCommonProps & {
    lazy: "offset";
    lazyOptions?: {
        limit?: number;
    };
    loadOptions: MultiSelectMenuOffsetLazyLoader;
} & MultiSelectMenuNonGroupingProps;
export type MultiSelectMenuPropsLazyGroup = MultiSelectMenuCommonProps & {
    lazy: "group";
    lazyOptions?: object;
    loadOptions: MultiSelectMenuGroupLazyLoader;
} & MultiSelectMenuGroupingProps;
export type MultiSelectMenuPropsEager = MultiSelectMenuCommonProps & {
    lazy?: false;
    loadOptions: MultiSelectMenuEagerLoader;
} & MultiSelectMenuGroupingProps;
export type MultiSelectMenuPropsLazy = MultiSelectMenuPropsLazyPage | MultiSelectMenuPropsLazyOffset | MultiSelectMenuPropsLazyGroup;
export type MultiSelectMenuProps = MultiSelectMenuPropsLazy | MultiSelectMenuPropsEager;
export {};
