import { AriaAttributes, CSSProperties, ReactElement } from 'react';
import { AiMarkWithTooltipOrPopoverProps, LayoutUtilProps, Size } from '../../../types';
import { AvatarProps, ChipProps, IconProps } from '../../..';
/**
 * Configuration options for the SelectField 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 SelectFieldCacheOptions = {
    enabled?: boolean;
    maxSize?: number;
};
/**
 * Imperative handle for the SelectField component.
 * @property clearCache - Clears the options cache.
 * @property invalidate - Clears the cache and triggers a fresh options load from the data source.
 */
export type SelectFieldHandle = {
    clearCache: () => void;
    invalidate: () => void;
};
export type SelectFieldGroupByValue = string | number;
export type SelectFieldOption = {
    id: string | number;
    label: string;
    searchText?: string;
    group?: SelectFieldGroupByValue;
    disabled?: boolean;
    extra?: Record<string, unknown>;
    content?: {
        title?: string;
        description?: string;
        chips?: Pick<ChipProps, "label" | "color" | "textWrap">[];
        avatar?: Pick<AvatarProps, "name" | "status" | "color" | "image">;
        icon?: Pick<IconProps, "svg" | "color"> & {
            /** Accessible label for the icon. When omitted, the icon is treated as decorative. */
            label?: string;
        };
    };
};
export type SelectFieldGroupedOption = SelectFieldOption & {
    group: SelectFieldGroupByValue;
};
export type SelectFieldUngroupedOption = Omit<SelectFieldOption, "group"> & {
    group?: never;
};
export type SelectFieldOptionsResult = SelectFieldOption[] | Promise<SelectFieldOption[]>;
export type SelectFieldEagerLoader = (searchValue: string) => SelectFieldOptionsResult;
export type SelectFieldOffsetLazyResult = {
    options: SelectFieldUngroupedOption[];
    hasMore?: boolean;
};
export type SelectFieldOffsetLazyLoader = (searchValue: string, offset: number, limit: number) => SelectFieldOffsetLazyResult | Promise<SelectFieldOffsetLazyResult>;
export type SelectFieldPageLazyResult = {
    options: SelectFieldUngroupedOption[];
    hasMore?: boolean;
};
export type SelectFieldPageLazyLoader = (searchValue: string, pageNumber: number, pageSize: number) => SelectFieldPageLazyResult | Promise<SelectFieldPageLazyResult>;
export type SelectFieldGroupLazyResult = {
    options: SelectFieldGroupedOption[];
    hasMore?: boolean;
};
export type SelectFieldGroupLazyLoader = (searchValue: string, previousGroupKey: SelectFieldGroupByValue | null) => SelectFieldGroupLazyResult | Promise<SelectFieldGroupLazyResult>;
export type SelectFieldSearchProps = {
    /**
     * The current search value.
     * Not a preferred usage. You likely don't need to control the searchValue yourself.
     */
    searchValue?: string;
    /**
     * Callback when the search value changes.
     * Not a preferred usage. Lean on the searchValue in the loadOptions function instead.
     */
    onSearchChange?: (searchValue: string) => void;
    /**
     * The number of milliseconds to debounce the search input.
     */
    debounceMs?: number;
};
type SelectFieldAddNewOptionProps = {
    /**
     * The configuration for the add new option.
     */
    addNewOption?: {
        /**
         * The label to display for the add new option.
         */
        label: string;
        /**
         * The content to display in the add new option dialog.
         */
        renderDialogContent: (searchValue: string) => React.ReactNode;
    };
};
export type SelectFieldPinnedOptionsSection = {
    options: SelectFieldOption[] | ((searchValue: string) => SelectFieldOption[] | Promise<SelectFieldOption[]>);
    label: string;
    /**
     * Whether to re-call the loader when search value changes.
     * Only applies when `options` is a function. Defaults to true.
     * When false, the loader is called once and the result is reused for all search values.
     *
     * You may wish to use this, for example, if you are loading a set of "favorites" options that should not be re-loaded when the search value changes.
     */
    searchReactive?: boolean;
    /**
     * Maximum number of search results to cache per section.
     * Only applies when `options` is a function and `searchReactive` is true.
     * Oldest entries are evicted when the limit is reached. Defaults to 15.
     */
    cacheSize?: number;
};
/**
 * There are two ways to configure pinned options.
 * 1. A labeled pinned options object (e.g. "Favorites", "Recent", "AI Suggestions", etc.)
 * 2. An array of labeled pinned options objects (e.g. [{"label": "Favorites", "options": [...]}])
 */
export type SelectFieldPinnedOptions = SelectFieldPinnedOptionsSection | SelectFieldPinnedOptionsSection[];
type SelectFieldCommonSelectFieldProps = {
    /**
     * The id of the select field.
     */
    id?: string;
    /**
     * The label of the select field.
     */
    label: string;
    /**
     * The placeholder of the select field.
     */
    placeholder?: string;
    /**
     * The size of the select field.
     */
    size?: Extract<Size, "small" | "medium" | "large">;
    /**
     * The value of the select field. Must be controlled state.
     */
    value: SelectFieldOption | null;
    /**
     * The callback to call when an item is clicked.
     * @param option - The option that was selected.
     */
    onSelectedOptionChange: (option: SelectFieldOption | null) => void;
    /**
     * Defines the initial loading behavior of the options. Controls when loadOptions is called.
     * @default "auto"
     * @description "auto" default behavior, currently equivalent to "immediate".
     * @description "immediate" will load the initial options when the component is mounted.
     * @description "open" will load the initial options if/when the user opens the dropdown.
     */
    initialLoad?: "auto" | "immediate" | "open";
    /**
     * The options to pin to the top of the list.
     */
    pinned?: SelectFieldPinnedOptions;
    /**
     * Whether to disable the clear button.
     * @default false
     */
    disableClearButton?: boolean;
    /**
     * Configuration for caching loadOptions results.
     * Caching is enabled by default. Set `{ enabled: false }` to disable.
     */
    cache?: SelectFieldCacheOptions;
    /**
     * The way to display the menu.
     * @default "auto"
     * @description "auto" will display the menu as a popover on mobile and a dialog on desktop.
     * @description "popover" will always display the menu as a popover.
     * @description "dialog" will always display the menu as a dialog.
     */
    displayMenuAs?: "auto" | "popover" | "dialog";
    /**
     * Error state for the field. Pass `true` to indicate error styling without a message.
     * Pass a string, string[], or ReactElement (deprecated) for error messages.
     */
    error?: boolean | string | ReactElement | string[];
    /**
     * Visually hides the label while keeping it accessible to screen readers.
     * @default false
     */
    hideLabel?: boolean;
    /**
     * Hint text displayed below the input field.
     */
    hint?: ReactElement | string;
    /**
     * AI mark configuration to display next to the label.
     * Can be a boolean to show a simple AI mark, or an object with tooltip/popover configuration.
     */
    labelAiMark?: AiMarkWithTooltipOrPopoverProps["aiMark"];
    /**
     * Description text displayed below the input field.
     */
    description?: ReactElement | string;
    /**
     * @deprecated No longer used. Error messages always use `aria-live="assertive"`.
     */
    errorAriaLive?: AriaAttributes["aria-live"];
    /**
     * Warning message(s) to display. Supports a single string or an array of strings.
     */
    warning?: string | string[];
    /**
     * Whether the field is required. Shows a red asterisk (*) next to the label.
     */
    required?: boolean;
    /**
     * Whether the field is disabled.
     * When disabled, the input is still focusable but menu items cannot be selected.
     */
    disabled?: boolean;
    /**
     * Whether the field is read-only.
     * When read-only, the input is still focusable but menu items cannot be selected.
     */
    readOnly?: boolean;
    /**
     * Content to display before the input field.
     */
    prefix?: string | ReactElement;
    /**
     * Content to display after the input field.
     */
    suffix?: string | ReactElement;
    /**
     * Custom CSS class name for the wrapper element.
     */
    className?: string;
    /**
     * Custom inline styles for the wrapper element.
     */
    style?: CSSProperties;
    /**
     * Whether to virtualize the dropdown list using windowed rendering.
     * Enable this for large option sets to improve performance by only rendering visible items.
     * @default false
     */
    virtualize?: boolean;
    /**
     * Whether to disable the search input.
     * When true, the input is replaced with a non-editable select trigger and the ARIA pattern
     * changes from combobox to listbox.
     * @default false
     */
    disableSearch?: boolean;
} & SelectFieldSearchProps & SelectFieldAddNewOptionProps & LayoutUtilProps;
type SelectFieldGroupingProps = {
    /**
     * Function to convert a group value to a display label.
     * Only used when options have a `group` property.
     * @param groupValue - The group value from the option's `group` property
     * @returns The formatted group label
     */
    groupToString?: (groupValue: SelectFieldGroupByValue) => string;
    /**
     * Function to compare two group values for sorting.
     * When provided, options are sorted by group using this comparator,
     * then by match-sort order within each group.
     * @param a - First group value to compare
     * @param b - Second group value to compare
     * @returns Negative if a < b, positive if a > b, zero if equal
     */
    groupSorter?: (a: SelectFieldGroupByValue, b: SelectFieldGroupByValue) => number;
};
type SelectFieldNonGroupingProps = {
    /**
     * Incompatible with non-group lazy loading.
     */
    groupToString?: never;
    /**
     * Incompatible with non-group lazy loading.
     */
    groupSorter?: never;
};
export type SelectFieldPropsLazyPage = SelectFieldCommonSelectFieldProps & {
    /**
     * Lazy loading mode using page-based pagination.
     * Options will be loaded on demand when the user scrolls to the bottom of the list.
     * This mode only supports flat options (i.e. cannot be used with grouped options).
     */
    lazy: "page";
    lazyOptions?: {
        pageSize?: number;
    };
    /**
     * Function to load the options.
     */
    loadOptions: SelectFieldPageLazyLoader;
} & SelectFieldNonGroupingProps;
export type SelectFieldPropsLazyOffset = SelectFieldCommonSelectFieldProps & {
    /**
     * Lazy loading mode using offset-based pagination.
     * Options will be loaded on demand when the user scrolls to the bottom of the list.
     * This mode only supports flat options (i.e. cannot be used with grouped options).
     */
    lazy: "offset";
    lazyOptions?: {
        limit?: number;
    };
    /**
     * Function to load the options.
     */
    loadOptions: SelectFieldOffsetLazyLoader;
} & SelectFieldNonGroupingProps;
export type SelectFieldPropsLazyGroup = SelectFieldCommonSelectFieldProps & {
    /**
     * Lazy loading mode using incremental group loading.
     * Groups will be loaded on demand when the user scrolls to the bottom of the list.
     * This mode supports grouped options.
     */
    lazy: "group";
    lazyOptions?: object;
    /**
     * Function to load the options.
     */
    loadOptions: SelectFieldGroupLazyLoader;
} & SelectFieldGroupingProps;
export type SelectFieldPropsEager = SelectFieldCommonSelectFieldProps & {
    /**
     * Whether the options are lazy loaded. If true, the options will be loaded on demand when the user scrolls to the bottom of the list.
     * @default false
     */
    lazy?: false;
    /**
     * Function to load the options.
     */
    loadOptions: SelectFieldEagerLoader;
} & SelectFieldGroupingProps;
export type SelectFieldPropsLazy = SelectFieldPropsLazyPage | SelectFieldPropsLazyOffset | SelectFieldPropsLazyGroup;
export type SelectFieldProps = SelectFieldPropsLazy | SelectFieldPropsEager;
export {};
