/** * createCombobox - the HEADLESS core behind , in the same spirit as * `createListbox` / `createSvGrid`: a runes-based state machine (type-to-filter, * roving active index, full keyboard, unmatched-text revert) exposed as * **prop-getters** you spread onto YOUR OWN markup. No styles, no DOM, no portal * or measurement - those render concerns stay in the styled component. * * ```svelte * * * {#if cb.open} * * {/if} * ``` */ import { type ListOption } from './list-option'; export type ComboboxValue = string | number | null; /** Reactive inputs are passed as getters so the core tracks live prop changes. */ export type ComboboxConfig = { options: () => ReadonlyArray; value: () => ComboboxValue; onChange?: (value: ComboboxValue) => void; disabled?: () => boolean; /** Read-only: value shown, input focusable, but not editable and the panel will not open. */ readonly?: () => boolean; ariaLabel?: () => string | undefined; /** Filter the options locally by the query. Set false for server-side search. */ localFilter?: () => boolean; /** DOM focus hooks provided by the renderer; the core itself never touches the DOM. */ focusInput?: () => void; blurInput?: () => void; id?: () => string | undefined; invalid?: () => boolean; required?: () => boolean; error?: () => string | undefined; hint?: () => string | undefined; }; export declare function createCombobox(config: ComboboxConfig): { /** Panel open state. */ readonly open: boolean; /** Highlighted option index into `filtered`. */ readonly activeIndex: number; /** True while the user is typing a filter query. */ readonly editing: boolean; /** Current filter query text. */ readonly query: string; /** Options after the live substring filter. */ readonly filtered: ListOption[]; /** The option matching the controlled value, if any. */ readonly selected: ListOption | null; /** Text shown in the field (query while editing, else the selected label). */ readonly shownText: string; /** Controlled value. */ readonly value: ComboboxValue; /** id of the listbox element (matches inputProps `aria-controls`). */ listId: string; isActive: (i: number) => boolean; isSelected: (o: ListOption) => boolean; setActive: (i: number) => void; openPanel: () => void; close: (revert?: boolean) => void; toggle: () => void; pick: (o: ListOption | undefined) => void; clear: () => void; onInput: (e: Event) => void; onFocus: () => void; onKeydown: (e: KeyboardEvent) => void; /** Spread onto the editable . */ inputProps: () => { 'aria-readonly': true | undefined; value: string; disabled: boolean; readonly: true | undefined; oninput: (e: Event) => void; onfocus: () => void; onkeydown: (e: KeyboardEvent) => void; 'aria-invalid': "true" | undefined; 'aria-required': "true" | undefined; 'aria-describedby': string | undefined; 'aria-label': string | undefined; id: string | undefined; role: "combobox"; 'aria-expanded': boolean; 'aria-controls': string; 'aria-autocomplete': "list"; 'aria-activedescendant': string | undefined; }; /** Spread onto the chevron/toggle