import { PropertyValues, TemplateResult } from 'lit'; import { BahtElement } from '../base.js'; export interface TypeaheadOption { key: string; label: string; /** Secondary text shown right-aligned (e.g. an email under a name). */ sub?: string; } /** * Text input with suggestions (autocomplete). The value IS the text — pick a * suggestion and the input shows its label; keep typing and the text stands * on its own (`free-text`, default) or is only a filter (`free-text="false"`, * blur then reverts to the last picked option). * * Suggestions come from a static `options` list (filtered here — labels that * start with the term rank first, then labels that contain it) or from an * async `fetcher(term)`. Typing is debounced (`debounce`, 150 ms) before the * host hears `baht-change` and before a fetcher runs. * * const el = document.createElement('baht-typeahead'); * el.options = [{ key: 'th', label: 'Thailand' }, { key: 'tw', label: 'Taiwan' }]; * el.addEventListener('baht-change', (e) => (draft.country = e.detail.value)); * el.addEventListener('baht-select', (e) => (draft.countryCode = e.detail.option.key)); * * ARIA: APG editable combobox with list autocomplete — the input is the * combobox, `aria-activedescendant` walks the listbox, Escape closes, Enter * picks. Unlike the input is always editable and the * text itself is a valid value; unlike the list is a filter of * what was typed, not a fixed menu. */ export declare class BahtTypeahead extends BahtElement { /** Accessible name (also the listbox name). */ label: string; /** The text. Controlled: re-feed after `baht-change` (or don't — the input keeps what was typed). */ value: string; placeholder: string; disabled: boolean; /** Marks the control invalid (styles + aria-invalid). */ invalid: boolean; /** Static suggestion list, filtered client-side. Ignored when `fetcher` is set. */ options: TypeaheadOption[]; /** Async suggestions: term in, options out. Errors show as "no matches". */ fetcher: ((term: string) => Promise) | null; /** Quiet time (ms) before the host hears the text and suggestions are (re)computed. */ debounce: number; /** Characters typed before suggestions appear (0 = suggest on focus/arrow too). */ minChars: number; /** Cap on suggestions shown. */ maxItems: number; /** false = the text must be a picked option; blur reverts otherwise. */ freeText: boolean; /** HTML autocomplete token forwarded to the input ('off' keeps the browser's own list away). */ autocomplete: string; private term; private open; private results; private loading; private activeIndex; private inputEl; private timer; private fetchSeq; /** The text currently IS this picked option (null once the user types again). */ private picked; /** Most recent pick ever — what `free-text="false"` reverts to on blur. */ private lastPicked; private readonly onDocMousedown; private get inputId(); private get listboxId(); private optionId; disconnectedCallback(): void; protected willUpdate(changed: PropertyValues): void; protected updated(): void; private filterStatic; private suggest; private highlight; private listen; private close; private emitChange; private onInput; /** Hand pending text to the host now (blur, Enter). */ private flush; private pick; private onBlur; private onKeydown; protected render(): TemplateResult; } declare global { interface HTMLElementTagNameMap { 'baht-typeahead': BahtTypeahead; } }