import { LLSelectBase, type LLSelectBaseSettings, type LLSelectChangeMeta, type LLSelectSettingsInputOf } from './base.js'; /** * Context passed to {@link LLSelectSingleSettings.createTriggerContentElFn}. * @group Settings * @category Single */ export interface LLSelectSingleTriggerContext { chosenItem: T | undefined; items: readonly T[]; } /** * Resolved (defaults applied) settings for {@link LLSelectSingle}: the base * settings plus the single-mode fields - the runtime type of `this.settings`, * one bag built complete in the constructor. * @group Settings * @category Single */ export interface LLSelectSingleSettings extends LLSelectBaseSettings { /** * Fired when the chosen item actually changes (compared via `compareFn`). * Receives the new value and the PREVIOUS one (the snapshot from before * this change); `undefined` means "no selection" on either side. Does NOT * fire on construction nor on `setChosenItem` with an equivalent item. * `null` (default) = no listener. * - `meta.source` says who initiated the change: `'user'` for a pointer or * keyboard interaction inside the widget, `'api'` for any programmatic * call. See {@link LLSelectChangeMeta}. * @group Events */ onChange: ((chosenItem: T | undefined, previousChosenItem: T | undefined, meta: LLSelectChangeMeta) => void) | null; /** * Render the trigger's content ELEMENT without subclassing - the setting * equivalent of overriding `renderTriggerContent`. Receives the chosen item * + items (same convention as `createItemContentElFn`): * - `HTMLElement` - inserted into the trigger as-is; you own it. Use this for * real markup (icon + text, etc.). * - fn returns `null` - use the default for this render: the chosen item's * `itemToString`, or the placeholder when nothing is chosen. * - setting is `null` (default) - always use that default rendering. * The DEFAULT `renderTriggerContent` checks it first; a subclass override * replaces that default entirely and may ignore the setting - override * wins, per DESIGN.md "Customization model". * @group Trigger */ createTriggerContentElFn: ((ctx: LLSelectSingleTriggerContext) => HTMLElement | null) | null; } /** * Constructor-time settings input for {@link LLSelectSingle}. * Every field is optional; missing fields use defaults. * @group Settings * @category Single */ export type LLSelectSingleSettingsInput = LLSelectSettingsInputOf>; /** * Single-selection select. Picking an item replaces any prior chosen item * and closes the popup. Use `setChosenItem(undefined)` to clear the selection. * * @typeParam T - item type. Supply your own `compareFn` for non-primitive `T`. * @typeParam GroupKey - group key type of `itemToGroupKeyFn`; see * {@link LLSelectBase}. * @typeParam S - resolved settings type, for subclasses extending the * settings bag; see {@link LLSelectBase}. * @group Select classes */ export declare class LLSelectSingle = LLSelectSingleSettings> extends LLSelectBase { /** * Currently chosen item, or `undefined` if none. * @group State (protected) */ protected chosenItem: T | undefined; /** * Build the control inside `targetEl`. * - Settings are resolved once here; missing fields get defaults. * - They are frozen afterwards, except `placeholder` and `uiTranslationPack`, * which have runtime setters; the rule is at {@link LLSelectBaseSettings}. * - This plain form infers `T` from a typed callback in `settings` whose * signature contains `T` (`itemToStringFn: (u: User) => ...`). With no * such callback, pass `T` explicitly: `new LLSelectSingle(...)`. * @group Lifecycle */ constructor(targetEl: HTMLElement, settings?: LLSelectSingleSettingsInput); /** * Subclass form. `subclassSettings` is the typed pass-through for subclasses * that extend the settings bag further; see `LLSelectBase`'s `S` param. * @group Lifecycle */ constructor(targetEl: HTMLElement, settings?: LLSelectSettingsInputOf, subclassSettings?: Omit>); /** * Return the currently chosen item, or `undefined` if none. * @group Selection */ getChosenItem(): T | undefined; /** * Set the chosen item programmatically. * - `undefined` clears the choice. * - Fires `onChange` only when the item actually differs from the current * one (compared via `compareFn`). * - Accepts an item that is not (yet) in the items list, for async data * flows. If a later `setItems` does not include it, it is dropped * automatically. * - It does not check disabled state: a disabled item can be chosen * programmatically. Native ``: typing its initial cycles to the next match. * - Returns `-1` when nothing is chosen, or the chosen item left the list; * the search then starts from the top. * @group Subclassing: focus */ protected computeTypeaheadClosedStartIndex(list: readonly T[]): number; /** * Re-match the chosen item against the new list after `setItems`. * - If the list no longer holds it (by `compareFn`), it is dropped and * `onChange` fires. * - If the list holds a compareFn-equal but DIFFERENT object (`track by` * style reload: same key, fresh fields), the stored reference is swapped * to the list's object. The logical value did not change, so `onChange` * does not fire. * - The trigger content re-renders after every `setItems`, because a custom * `createTriggerContentElFn` receives `items`. * - The arrow re-renders only when the chosen item is dropped, because that * runs the whole trigger. * @group Subclassing: reactions */ protected onItemsChanged(): void; private areEqual; private fireChange; } //# sourceMappingURL=single.d.ts.map