import type WaOption from '../../components/option/option.js';
import type WaPopup from '../../components/popup/popup.js';
import '../../components/spinner/spinner.js';
import { WebAwesomeFormAssociatedElement } from '../../internal/webawesome-form-associated-element.js';
import type { PropertyValues, TemplateResult } from 'lit';
import '../icon/icon.js';
import '../option/option.js';
import '../popup/popup.js';
import '../tag/tag.js';
/** The request passed to a `dataSource` callback (and the `wa-options-request` event) in server mode. */
export interface ComboboxRequest {
    /** The text the user has typed since opening. Empty on open and on `reload()` when the listbox is closed. */
    query: string;
    /** Aborts when the request is superseded, or when the listbox closes or the control is disabled or disconnected. */
    signal: AbortSignal;
}
/** A single option returned by a `dataSource` callback. */
export interface ComboboxOption {
    /** The option's value, used as the reconciliation key and as the combobox's value when selected. */
    value: string;
    /** The option's visible label. */
    label: string;
    /** Whether the option is disabled. */
    disabled?: boolean;
}
/**
 * What a `dataSource` callback resolves with — the options to show, in display order. HTML takes the same markup
 * you'd slot by hand; elements are adopted as-is. Empty means "no options", and duplicate values are dropped.
 */
export type ComboboxOptions = ComboboxOption[] | string | HTMLElement[];
/**
 * @summary Comboboxes combine a text input with a listbox, allowing users to filter and select from predefined options
 *  or enter custom values.
 * @documentation https://webawesome.com/docs/components/combobox
 * @status stable
 * @since 3.1
 *
 * @dependency wa-icon
 * @dependency wa-option
 * @dependency wa-popup
 * @dependency wa-spinner
 * @dependency wa-tag
 *
 * @slot - The listbox options. Must be `<wa-option>` elements. You can use `<wa-divider>` to group items visually.
 * @slot label - The input's label. Alternatively, you can use the `label` attribute.
 * @slot start - An element, such as `<wa-icon>`, placed at the start of the combobox.
 * @slot end - An element, such as `<wa-icon>`, placed at the end of the combobox.
 * @slot clear-icon - An icon to use in lieu of the default clear icon.
 * @slot expand-icon - The icon to show when the control is expanded and collapsed. Rotates on open and close.
 * @slot hint - Text that describes how to use the input. Alternatively, you can use the `hint` attribute.
 * @slot loading - Shown in the listbox while options are loading and none are available yet.
 * @slot no-results - Shown in the listbox when the query matched nothing.
 * @slot empty - Shown in the listbox when there are no options and no query has been typed.
 * @slot error - Shown in the listbox when the last `dataSource` request failed.
 *
 * @event change - Emitted when the control's value changes.
 * @event input - Emitted when the control receives input.
 * @event focus - Emitted when the control gains focus.
 * @event blur - Emitted when the control loses focus.
 * @event wa-clear - Emitted when the control's value is cleared.
 * @event wa-show - Emitted when the combobox's menu opens.
 * @event wa-after-show - Emitted after the combobox's menu opens and all animations are complete.
 * @event wa-hide - Emitted when the combobox's menu closes.
 * @event wa-after-hide - Emitted after the combobox's menu closes and all animations are complete.
 * @event wa-create - Emitted when the user selects the "create" option. Call `event.preventDefault()` to handle creation yourself. The event `detail` contains `{ inputValue: string }`.
 * @event wa-invalid - Emitted when the form control has been checked for validity and its constraints aren't satisfied.
 * @event wa-options-request - Emitted in server mode whenever a request for options starts. The event `detail` contains `{ query: string, signal: AbortSignal }`.
 * @event wa-options-error - Emitted when a `dataSource` request rejects. The event `detail` contains `{ error: unknown, request: { query: string } }`.
 *
 * @csspart form-control - The form control that wraps the label, input, and hint.
 * @csspart form-control-label - The label.
 * @csspart label - Deprecated. Use the `form-control-label` part instead.
 * @csspart form-control-input - The combobox's wrapper.
 * @csspart hint - The hint's wrapper.
 * @csspart combobox - The container the wraps the start, end, value, clear icon, and expand button.
 * @csspart start - The container that wraps the `start` slot.
 * @csspart end - The container that wraps the `end` slot.
 * @csspart combobox-input - The text input element.
 * @csspart listbox - The listbox container where options are slotted.
 * @csspart tags - The container that houses option tags when `multiselect` is used.
 * @csspart tag - The individual tags that represent each multiselect option.
 * @csspart tag__content - The tag's content part.
 * @csspart tag__remove-button - The tag's remove button.
 * @csspart tag__remove-button__base - The tag's remove button base part.
 * @csspart clear-button - The clear button.
 * @csspart expand-icon - The container that wraps the expand icon.
 * @csspart spinner - The loading spinner shown in the field while options are loading.
 * @csspart status - The listbox status row shown in place of options. Also carries a state-specific part.
 * @csspart loading - The status row shown while options are loading and none are available yet.
 * @csspart no-results - The status row shown when the query matched nothing.
 * @csspart empty - The status row shown when there are no options and no query has been typed.
 * @csspart error - The status row shown when the last `dataSource` request failed.
 *
 * @cssproperty [--show-duration=var(--wa-transition-fast)] - The duration of the show animation.
 * @cssproperty [--hide-duration=var(--wa-transition-fast)] - The duration of the hide animation.
 * @cssproperty [--tag-max-size=10ch] - When using `multiple`, the max size of tags before their content is truncated.
 *
 * @cssstate blank - The combobox is empty.
 * @cssstate disabled - The combobox is disabled.
 * @cssstate loading - A request for options is pending.
 * @cssstate showing-loading-row - The open listbox is showing its loading row, so the in-field spinner stays hidden.
 */
export default class WaCombobox extends WebAwesomeFormAssociatedElement {
    static css: import("lit").CSSResult[];
    static get validators(): import("../../internal/webawesome-form-associated-element.js").Validator<WebAwesomeFormAssociatedElement>[];
    assumeInteractionOn: string[];
    private createOptionEl;
    private hasInputSinceOpening;
    private readonly hasSlotController;
    private readonly localize;
    private listboxId;
    private selectionOrder;
    private slotChangePending;
    private cachedOptions;
    /** Aborts the in-flight request. Recreated per request. */
    private abortController;
    /** Monotonically increasing; a response whose token isn't current is a stale, out-of-order arrival. */
    private requestToken;
    /** Pending debounce timer for typing-driven requests. */
    private debounceTimer;
    /** Delays the "loading" announcement until a request is slow enough to be worth interrupting for. */
    private loadingAnnounceTimer;
    /** The query of the in-flight or last-applied request, used to skip echoes of a request already made. */
    private lastRequestedQuery;
    /** True when the last completed request rejected. Cleared when the next request starts. */
    private hasRequestError;
    /** True while an IME composition is active; requests wait for `compositionend`. */
    private isComposing;
    /** The markup each showing result arrived with, so a response that repeats it can leave the listbox alone. */
    private appliedMarkup;
    private rawValuesEqual;
    popup: WaPopup;
    combobox: HTMLSlotElement;
    comboboxInput: HTMLInputElement;
    valueInput: HTMLInputElement;
    listbox: HTMLSlotElement;
    /** Where to anchor native constraint validation */
    get validationTarget(): HTMLInputElement;
    private _currentOption;
    /**
     * The option the user is keying through, or `undefined` once it's unusable. In server mode a response or a consumer
     * swap can remove or hide the highlighted option at any moment, and no reader — Enter above all — may act on it.
     */
    get currentOption(): WaOption | undefined;
    set currentOption(option: WaOption | undefined);
    selectedOptions: WaOption[];
    /** @internal */
    optionValues: Set<string | null> | undefined;
    filteredOptions: WaOption[];
    /** The current text value in the input field. */
    inputValue: string;
    /** The name of the combobox, submitted as a name/value pair with form data. */
    name: string;
    private _defaultValue;
    set defaultValue(val: null | string | string[]);
    get defaultValue(): null | string | string[];
    /**
     * A converter for defaultValue from array to string if its multiple. Also fixes some hydration issues.
     */
    private convertDefaultValue;
    private _value;
    /** The combobox's value. This will be a string for single select or an array for multi-select. */
    set value(val: string | string[] | null);
    get value(): string | string[] | null;
    /** The combobox's size. */
    size: 'xs' | 's' | 'm' | 'l' | 'xl' | 'small' | 'medium' | 'large';
    handleSizeChange(): void;
    /** Placeholder text to show as a hint when the combobox is empty. */
    placeholder: string;
    /** Allows more than one option to be selected. */
    multiple: boolean;
    /**
     * The maximum number of selected options to show when `multiple` is true. After the maximum, "+n" will be shown to
     * indicate the number of additional items that are selected. Set to 0 to remove the limit.
     */
    maxOptionsVisible: number;
    /** Disables the combobox control. */
    disabled: boolean;
    /** Adds a clear button when the combobox is not empty. */
    withClear: boolean;
    /**
     * Indicates whether or not the combobox is open. You can toggle this attribute to show and hide the menu, or you can
     * use the `show()` and `hide()` methods and this attribute will reflect the combobox's open state.
     */
    open: boolean;
    /** The combobox's visual appearance. */
    appearance: 'filled' | 'outlined' | 'filled-outlined';
    /** Draws a pill-style combobox with rounded edges. */
    pill: boolean;
    /** The combobox's label. If you need to display HTML, use the `label` slot instead. */
    label: string;
    /**
     * The preferred placement of the combobox's menu. Note that the actual placement may vary as needed to keep the
     * listbox inside of the viewport.
     */
    placement: 'top' | 'bottom';
    /** The combobox's hint. If you need to display HTML, use the `hint` slot instead. */
    hint: string;
    /**
     * Only required for SSR. Set to `true` if you're slotting in a `label` element so the server-rendered markup
     * includes the label before the component hydrates on the client.
     */
    withLabel: boolean;
    /**
     * Only required for SSR. Set to `true` if you're slotting in a `hint` element so the server-rendered markup
     * includes the hint before the component hydrates on the client.
     */
    withHint: boolean;
    /** The combobox's required attribute. */
    required: boolean;
    /**
     * When true, allows the user to enter a value that doesn't match any of the options. Only applies to single-select
     * comboboxes. When false, the combobox will only accept values that match an option.
     */
    allowCustomValue: boolean;
    /**
     * When true, if the user types text that doesn't match any existing option, a "Create [value]" option appears in the
     * listbox. Selecting it creates a new `<wa-option>` in the DOM and selects it. A cancelable `wa-create` event fires
     * before creation.
     */
    allowCreate: boolean;
    /**
     * A function that customizes how options are filtered based on the input value. The function receives the option
     * and the current input query string. Return `true` to include the option in the filtered list, `false` to exclude.
     * By default, options are filtered by checking if the option's label contains the query (case-insensitive).
     *
     * Ignored in server mode — the server decides what matches.
     */
    filter: ((option: WaOption, query: string) => boolean) | null;
    /**
     * A callback that loads options from a server. It receives the current query and an `AbortSignal` and returns the
     * options to show — an array of `{ value, label, disabled? }` objects, a string of HTML, or an array of elements.
     * Setting this puts the combobox in server mode, which turns off client-side filtering. HTML is inserted as-is and
     * is never sanitized, so make sure you trust it.
     */
    dataSource: ((request: ComboboxRequest) => Promise<ComboboxOptions> | ComboboxOptions) | null;
    /**
     * Switches the combobox to server mode without a `dataSource` callback: client-side filtering is turned off and you
     * swap the slotted `<wa-option>` elements yourself in response to `wa-options-request`, then set `loading` to
     * `false`. Implied when `dataSource` is set.
     */
    server: boolean;
    /**
     * Whether a request for options is pending. The combobox sets this to `true` the moment a request is scheduled
     * (including the debounce wait) and, with a `dataSource`, clears it when the request settles. In event mode, set it
     * to `false` yourself once you've updated the options.
     */
    loading: boolean;
    /**
     * How long to wait, in milliseconds, after the user stops typing before requesting options in server mode. Opening
     * the listbox and calling `reload()` request immediately.
     */
    filterDebounce: number;
    /** Controls whether and how text input is automatically capitalized as it is entered/edited by the user. */
    autocapitalize: 'off' | 'none' | 'on' | 'sentences' | 'words' | 'characters';
    /**
     * Indicates whether the browser's autocorrect feature is on or off. When set as an attribute, use `"off"` or `"on"`.
     * When set as a property, use `true` or `false`.
     */
    autocorrect: boolean;
    /**
     * Tells the browser what type of data will be entered by the user, allowing it to display the appropriate virtual
     * keyboard on supportive devices.
     */
    inputmode: 'none' | 'text' | 'decimal' | 'numeric' | 'tel' | 'search' | 'email' | 'url';
    /** Used to customize the label or icon of the Enter key on virtual keyboards. */
    enterkeyhint: 'enter' | 'done' | 'go' | 'next' | 'previous' | 'search' | 'send';
    /** Enables spell checking on the combobox. */
    spellcheck: boolean;
    /**
     * A function that customizes the tags to be rendered when multiple=true. The first argument is the option, the second
     * is the current tag's index.  The function should return either a Lit TemplateResult or a string containing trusted
     * HTML of the symbol to render at the specified value.
     */
    getTag: (option: WaOption, index: number) => TemplateResult | string | HTMLElement;
    connectedCallback(): void;
    disconnectedCallback(): void;
    /**
     * @internal
     */
    protected updateFormValue(value: unknown): void;
    private updateDefaultValue;
    private addOpenListeners;
    private removeOpenListeners;
    private handleFocus;
    private handleBlur;
    private handleDocumentFocusIn;
    private handleDocumentKeyDown;
    private handleDocumentMouseDown;
    private handleLabelClick;
    private handleComboboxClick;
    private handleComboboxMouseDown;
    private handleComboboxKeyDown;
    private handleCompositionStart;
    private handleCompositionEnd;
    private handleInputChange;
    private handleClearClick;
    private handleClearMouseDown;
    private handleOptionClick;
    handleDefaultSlotChange(): void;
    private processSlotChange;
    private handleTagRemove;
    private getAllOptions;
    private getRealOptions;
    /** True when options come from a server, either via `dataSource` or via `wa-options-request`. */
    private get isServerMode();
    /** The text the user has typed since opening. A selected option's label sitting in the input is never a query. */
    private get currentQuery();
    /**
     * Schedules a request for options. `debounce` waits `filterDebounce` ms (typing); opening and `reload()` go
     * immediately. `force` bypasses the dedupe check so a repeat of the last query still refetches.
     */
    private requestOptions;
    /**
     * Sends the request. Aborts whatever was in flight, emits `wa-options-request`, and — with a `dataSource` — applies
     * the response. A monotonic token drops out-of-order arrivals.
     */
    private sendRequest;
    /**
     * Re-requests options using the current query (or an empty query when the listbox is closed). Resolves once the
     * response has been applied in `dataSource` mode, or immediately after `wa-options-request` is emitted in event
     * mode, so `await combobox.reload()` followed by setting `value` works.
     */
    reload(): Promise<void>;
    /** Aborts any pending or in-flight request and stops reporting as busy. Never touches the options already applied. */
    private cancelOptionsRequest;
    /** Turns a `dataSource` response into elements. HTML is parsed in an inert template, so nothing runs until adopted. */
    private toElements;
    /**
     * Replaces the options with a response. The response's nodes are appended in order, deduped by value, and the
     * selection carries across by value: a selected value the response omits is parked in a hidden stand-in so `value`
     * and the tags survive. The create option and existing stand-ins are left alone.
     */
    private applyOptions;
    /**
     * Keeps a selection alive when the options backing it leave the DOM — a response that omits a selected value, or a
     * consumer swapping the children in event mode. Each such value gets a hidden, selected stand-in carrying its label.
     * We insert our own node rather than re-appending the consumer's, which frameworks own.
     */
    private retainSelections;
    /** Retires stand-ins that are no longer selected or whose real option is back, handing the selection over to it. */
    private pruneStandIns;
    /**
     * Settles the component once the options change in server mode, for both the callback and event paths: refresh the
     * visible set, announce the result, re-pick the current option, and let the result open or close the listbox.
     */
    private finishOptionsChange;
    /**
     * Picks the current option once a fresh set is in place. Typed since opening → the first result; otherwise the option
     * with the previous highlight's value (element identity isn't stable across a response), else a selected option,
     * else the first result. Speaks the landing option when the highlight actually moved.
     */
    private reseatCurrentOption;
    /**
     * Opens or closes the listbox once a response lands, for server mode with `allow-custom-value`. Free-text entry
     * can't open eagerly ("no results" for text the user is inventing) or close eagerly (flicker on every keystroke),
     * so typing leaves the listbox as-is and the response decides. An error row stays put so it can be read.
     */
    private syncOpenStateAfterResponse;
    private updateCreateOption;
    private removeCreateOption;
    private handleCreateOptionSelected;
    private getVisibleOptions;
    private getFirstVisibleOption;
    private updateFilteredOptions;
    /**
     * Sets the current option — the one the user is keying through. Deliberately no `aria-activedescendant`: it would
     * live on the shadow-DOM input but name a light-DOM `<wa-option>`, and ARIA id references don't cross shadow
     * boundaries. `announceOption` conveys the active option instead.
     */
    private setCurrentOption;
    private setSelectedOptions;
    private toggleOptionSelection;
    /**
     * Announces the current option and its position in the list. With no `aria-activedescendant` (see
     * `setCurrentOption`), this is the only way the active option reaches a screen reader, so it must accompany every
     * user-driven change of the current option.
     */
    private announceOption;
    /**
     * Announces a message politely via the library's shared live region, which lives in the light DOM because a live
     * region inside a shadow root isn't reliably announced (JAWS + Firefox ignores them entirely).
     */
    private announce;
    /**
     * What a status state should say: the author's slotted text if there is any, else the localized default. An author
     * who replaces the visible message shouldn't have the default announced to screen reader users instead.
     */
    private statusAnnouncement;
    private announceFilterResults;
    selectionChanged(): void;
    protected get tags(): (import("lit-html/directive.js").DirectiveResult<typeof import("lit-html/directives/unsafe-html.js").UnsafeHTMLDirective> | null)[];
    updated(changedProperties: PropertyValues<this>): void;
    handleDisabledChange(): void;
    handleDataSourceChange(): void;
    handleLoadingChange(): void;
    handleValueChange(): void;
    handleOpenChange(): Promise<void>;
    /** Shows the listbox. */
    show(): Promise<void>;
    /** Hides the listbox. */
    hide(): Promise<void>;
    /** Sets focus on the control. */
    focus(options?: FocusOptions): void;
    /** Removes focus from the control. */
    blur(): void;
    formResetCallback(): void;
    /**
     * Which listbox status row to render, or `null` when real options are showing. Gated on `hasUpdated` so
     * server-rendered markup is unchanged.
     */
    private get listboxState();
    /** The localized default text for a status row. */
    private statusText;
    render(): TemplateResult<1>;
}
declare global {
    interface HTMLElementTagNameMap {
        'wa-combobox': WaCombobox;
    }
}
