import * as ngwr_i18n from 'ngwr/i18n'; import * as _angular_core from '@angular/core'; import { InjectionToken, Signal, TemplateRef, ElementRef } from '@angular/core'; import { BooleanInput } from '@angular/cdk/coercion'; import { ControlValueAccessor } from '@angular/forms'; import { Observable } from 'rxjs'; /** * @license * * Use of this source code is governed by an MIT-style license that can be * found in the LICENSE file at https://github.com/thekhegay/ngwr/blob/main/LICENSE */ /** * Behavior mode for ``. The component is the unified * combobox primitive — every shape (single, multi, type-to-search, * free-text-tags) is the same component with a different `mode`. * * - `'single'` — one value, no input field. The classic dropdown. * - `'multi'` — array value, chips on the trigger, options toggle on click. * - `'search'` — type-ahead with sync filter or async loader (replaces * the standalone ``). * - `'tag'` — free-text + chips, with optional `allowCreate` / * `createValidator` for typed lists (replaces ``). */ type WrSelectMode = 'single' | 'multi' | 'search' | 'tag'; /** * Tag-mode validator. Return `true` to accept the value, `false` to * silently reject (e.g. shape check, dedupe against a custom set). */ type WrSelectTagValidator = (value: string, existing: readonly string[]) => boolean; /** * Search-mode async loader. Receives the current query, returns matching * items as an array, Observable, or Promise. Cancellation: `switchMap` * inside `WrSelect` cancels in-flight calls when a new keystroke lands, * so stale responses can't clobber fresh ones. */ type WrSelectSearchLoader = (query: string) => Observable | Promise | readonly T[]; /** Control size for `` — shares the `--wr-control-*` contract. */ type WrSelectSize = 'sm' | 'md' | 'lg'; /** * @license * * Use of this source code is governed by an MIT-style license that can be * found in the LICENSE file at https://github.com/thekhegay/ngwr/blob/main/LICENSE */ /** Per-option registration metadata. @internal */ interface WrSelectOptionRegistration { readonly id: string; readonly value: unknown; readonly disabled: boolean; /** * Lazy label reader. Options render text via ``, so we * read it at call time once Angular has settled the projected content. */ readonly getLabel: () => string; } /** * Contract a `` uses to talk to its parent ``. * * @internal */ interface WrSelectContext { /** * Currently selected value. Single mode: `T | null`. Multi mode: * `readonly T[]`. Options consult {@link isSelected} instead of * reading this directly so the same option code works in both modes. */ readonly value: Signal; /** Whether the select is in multi-selection mode. */ readonly multi: Signal; /** Whether the select is disabled. */ readonly isDisabled: Signal; /** Id of the option currently highlighted by keyboard navigation. */ readonly activeOptionId: Signal; /** * Active search query (search mode only). Empty string when there is * no filter applied — options treat that as "show me". */ readonly searchQuery: Signal; /** True only when `mode="search"`. Options gate filtering on this. */ readonly isSearch: Signal; /** Is the given option value currently selected? Handles both single and multi. */ isSelected(value: unknown): boolean; /** * Called when a child option is clicked. The label is read lazily * via {@link WrSelectOptionRegistration.getLabel}, so callers don't * need to thread it through. */ selectOption(value: unknown): void; /** Register an option; returns an unregister function. */ registerOption(reg: WrSelectOptionRegistration): () => void; } /** * Token a `` injects to register itself with and notify its * parent ``. * * @internal */ declare const WR_SELECT: InjectionToken; interface SelectedChip { readonly value: unknown; readonly label: string; } /** * Combobox primitive. Renders a button that opens a CDK overlay * containing the projected `` (and optionally * ``) children. Every shape is the same component * with a different `[mode]`: * * - `'single'` (default) — one value, no input. Classic dropdown. * - `'multi'` — array value, chips on the trigger; clicking an option * toggles instead of closing, Backspace removes the last chip. * - `'search'` — type-ahead with sync `[options]` filter or async * `[loader]`. Replaces the standalone ``. * - `'tag'` — free-text + chips with `[separators]` / `[validate]` / * `[allowDuplicates]`. Replaces ``. * * Implements `ControlValueAccessor` — usable with `[(ngModel)]`, * `formControl`, or `formControlName`. * * @example * ```html * * * Small * Medium * Large * * * * * TypeScript * Angular * * ``` * * The legacy `[multi]="true"` boolean is still accepted but is now an * alias for `[mode]="'multi'"` — prefer the explicit mode. * * @see https://ngwr.dev/components/select */ declare class WrSelect implements ControlValueAccessor, WrSelectContext { /** Placeholder shown when no option is selected. Falls back to `select.placeholder`. */ readonly placeholder: _angular_core.InputSignal; /** Clear-selection (×) button aria-label. Falls back to `select.clearSelection`. */ readonly clearLabel: _angular_core.InputSignal; protected readonly resolvedPlaceholder: _angular_core.Signal; protected readonly resolvedClear: _angular_core.Signal; /** Per-chip ARIA label — interpolates `{{label}}`. @internal */ protected readonly chipRemoveLabel: (params?: ngwr_i18n.WrI18nParams) => string; /** Disable the select. Also set by Angular forms via `setDisabledState`. */ readonly disabled: _angular_core.InputSignalWithTransform; /** Pill-shaped corners on the trigger. @default false */ readonly rounded: _angular_core.InputSignalWithTransform; /** Control size — shares the `--wr-control-*` contract. @default 'md' */ readonly size: _angular_core.InputSignal; /** * Present the option panel as a full-width bottom-sheet on small * viewports instead of an anchored dropdown. `undefined` follows the * app-wide `provideWrResponsiveOverlays()` setting; `true`/`false` * overrides it. @default undefined */ readonly responsive: _angular_core.InputSignalWithTransform; /** * Behavior mode. `` is the unified combobox primitive — * pick the shape via `[mode]`: * * - `'single'` (default) — one value, no input. Classic dropdown. * - `'multi'` — array value, chips on the trigger. * - `'search'` *(planned)* — type-ahead with sync filter or async loader. * - `'tag'` *(planned)* — free-text + chips with optional `allowCreate`. * */ readonly mode: _angular_core.InputSignal; /** Resolved mode — `'single'` unless `[mode]` says otherwise. */ protected readonly effectiveMode: _angular_core.Signal; /** Convenience — `effectiveMode() === 'multi'`. */ protected readonly isMulti: _angular_core.Signal; /** Convenience — `effectiveMode() === 'tag'`. */ protected readonly isTag: _angular_core.Signal; /** Convenience — `effectiveMode() === 'search'`. Exposed via context for options. */ readonly isSearch: _angular_core.Signal; /** WrSelectContext — resolved multi-selection flag for child options. */ readonly multi: _angular_core.Signal; /** Both multi and tag render chips on the trigger. */ protected readonly hasChips: _angular_core.Signal; /** * Search-mode query. Empty string = no filter. Exposed via context so * each `` can self-hide non-matching rows. */ readonly searchQuery: _angular_core.WritableSignal; /** * Search mode: dynamic option array. Each item is rendered as a * `` whose label comes from `[displayWith]`. Works * alongside projected `` children — both lists are * filtered by the search query. */ readonly options: _angular_core.InputSignal; /** Search mode: map a dynamic option item to its display label. @default String */ readonly displayWith: _angular_core.InputSignal<(item: unknown) => string>; /** * Search mode: async loader. When set, the loader is called on every * (debounced) keystroke and its result replaces `[options]`. Supports * Observables, Promises, and plain arrays. */ readonly loader: _angular_core.InputSignal | null>; /** Search mode: debounce (ms) applied to the loader. @default 250 */ readonly debounceMs: _angular_core.InputSignalWithTransform; /** Search mode: minimum query length before the panel opens / loader fires. @default 0 */ readonly minChars: _angular_core.InputSignalWithTransform; /** * Search mode: allow values not in the options list. Enter on an * unmatched query commits the raw text as the form value. @default false */ readonly freeText: _angular_core.InputSignalWithTransform; /** Search mode: text shown when the filter / loader returns nothing. Falls back to `select.noResults`. */ readonly noResultsText: _angular_core.InputSignal; /** Search mode: text shown while the async loader is in flight. Falls back to `select.loading`. */ readonly loadingText: _angular_core.InputSignal; protected readonly resolvedNoResults: _angular_core.Signal; protected readonly resolvedLoading: _angular_core.Signal; /** Search mode: results returned by the async loader. @internal */ protected readonly loadedOptions: _angular_core.WritableSignal; /** Search mode: true while the loader is in flight. @internal */ protected readonly loading: _angular_core.WritableSignal; /** * Tag mode: keys / characters that commit the current draft into a chip. * `'Enter'` is the key name; everything else is a literal character watched * in keypresses and pastes. @default ['Enter', ','] */ readonly separators: _angular_core.InputSignal; /** Tag mode: allow the same value to appear more than once. @default false */ readonly allowDuplicates: _angular_core.InputSignalWithTransform; /** * Tag mode: custom validator — return `true` to accept the value, `false` * to silently reject. Receives the trimmed draft + the existing chips. */ readonly validate: _angular_core.InputSignal; /** Tag-mode draft (text currently typed in the inline input). @internal */ protected readonly draft: _angular_core.WritableSignal; /** * Show a clear-all (×) button at the end of the chip row when at * least one option is selected (multi mode only). @default true */ readonly clearable: _angular_core.InputSignalWithTransform; /** * Cap on selected items (multi mode). `0` = unlimited. Once reached, * additional clicks on unselected options are ignored. @default 0 */ readonly maxItems: _angular_core.InputSignalWithTransform; /** * Maximum number of chips rendered before collapsing the rest into a * `+N more` indicator. `0` = render every chip. @default 0 */ readonly maxTagCount: _angular_core.InputSignalWithTransform; /** * Unified value signal. Single mode holds `T | null`; multi mode * holds `readonly T[]`. Internal — consumers go through `[(ngModel)]` * or `[formControl]` via CVA. * @internal */ readonly value: _angular_core.WritableSignal; /** Listbox id used by the trigger's `aria-controls`. */ protected readonly listboxId: string; /** Registered options (insertion order). Internal — distinct from the public `[options]` input. */ private readonly registry; /** Keyboard cursor index into `options`. -1 = none. */ private readonly activeIndex; /** Id of the active option (for `aria-activedescendant`). */ readonly activeOptionId: _angular_core.Signal; protected readonly open: _angular_core.WritableSignal; protected readonly selectedLabel: _angular_core.WritableSignal; /** * Selected chips (multi + tag modes). Multi reads labels from the * registered `` children; tag uses each raw string as * both value and label. */ protected readonly selectedChips: _angular_core.Signal; protected readonly visibleChips: _angular_core.Signal; protected readonly hiddenChipCount: _angular_core.Signal; protected readonly hasSelection: _angular_core.Signal; private readonly disabledFromCva; /** Effective disabled state — input wins, CVA second. */ readonly isDisabled: _angular_core.Signal; protected readonly classes: _angular_core.Signal; /** * Search-mode dynamic options. Loader results win when the loader is * set; otherwise the static `[options]` array. Each item is rendered * as an internal `` in the panel. */ protected readonly dynamicOptions: _angular_core.Signal; /** * Count of registered options that pass the current search filter. * Hides the noResults state when the panel has at least one visible row. */ protected readonly visibleCount: _angular_core.Signal; /** Search mode: show "no results" when the panel has nothing to offer. */ protected readonly hasNoResults: _angular_core.Signal; /** Search mode: is this option hidden by the current query? @internal */ private isOptionHidden; protected readonly panelTpl: _angular_core.Signal>; /** Tag-mode inline input. Present only when `mode="tag"`. @internal */ protected readonly tagInputEl: _angular_core.Signal | undefined>; /** Search-mode inline input. Present only when `mode="search"`. @internal */ protected readonly searchInputEl: _angular_core.Signal | undefined>; protected focusTagInput(): void; protected focusSearchInput(): void; protected onSearchInput(event: Event): void; protected onSearchFocus(): void; protected onSearchKey(event: KeyboardEvent): void; /** * Display text for the search input. Shows the selected option's * label when collapsed, or the live query while typing / panel open. * @internal */ protected readonly searchDisplay: _angular_core.Signal; private readonly host; private readonly overlay; private readonly responsiveConfig; private readonly vcr; private readonly scrollStrategies; private readonly destroyRef; private overlayRef; private onChange; protected onTouched: () => void; constructor(); isSelected(value: unknown): boolean; selectOption(value: unknown): void; registerOption(reg: WrSelectOptionRegistration): () => void; /** Remove one selection (chip × button). Works for multi and tag modes. */ protected removeChip(value: unknown, event: Event): void; /** Clear every selection (× button). Multi/tag → empty array; search → null. */ protected clearAll(event: Event): void; /** Capacity check used by tag mode to refuse the next add. */ protected readonly atCapacity: _angular_core.Signal; protected onTagInput(event: Event): void; protected onTagKeydown(event: KeyboardEvent): void; protected onTagPaste(event: ClipboardEvent): void; protected onTagBlur(): void; private commitDraft; private tryAddTag; writeValue(value: unknown): void; registerOnChange(fn: (value: unknown) => void): void; registerOnTouched(fn: () => void): void; setDisabledState(isDisabled: boolean): void; protected onTriggerClick(): void; protected onTriggerKey(event: KeyboardEvent): void; private seedActiveIndex; private moveActive; private firstEnabled; private lastEnabled; /** Coerce the multi-mode value signal into an array (handles writeValue from non-array). */ private asArray; private openOverlay; private closeOverlay; static ɵfac: _angular_core.ɵɵFactoryDeclaration; static ɵcmp: _angular_core.ɵɵComponentDeclaration; } /** * Single option inside a ``. * * The option's display label is taken from its projected text content; * the form value is its `value` input. * * @example * ```html * Small * Forty-two * ``` */ declare class WrOption { /** The value contributed when this option is chosen. Required. */ readonly value: _angular_core.InputSignal; /** Disable this option. @default false */ readonly disabled: _angular_core.InputSignalWithTransform; /** Stable id used for `aria-activedescendant`. */ readonly id: string; private readonly host; private readonly parent; /** * @internal — true when this option is currently selected. Works for * both single and multi-select parents via `WrSelectContext.isSelected`. */ protected readonly selected: _angular_core.Signal; /** @internal — true when this option is the keyboard cursor target. */ protected readonly active: _angular_core.Signal; /** * @internal — search mode only. True when the parent has a query that * the option's text content does not match (case-insensitive substring). * Hidden options stay in the DOM so registration order survives but * collapse via CSS. */ protected readonly hidden: _angular_core.Signal; protected readonly classes: _angular_core.Signal; constructor(); protected onClick(): void; static ɵfac: _angular_core.ɵɵFactoryDeclaration; static ɵcmp: _angular_core.ɵɵComponentDeclaration; } /** * Visually groups options under a label inside a ``. * * @example * ```html * * Small * Medium * * ``` */ declare class WrOptionGroup { /** Section heading shown above the options. */ readonly label: _angular_core.InputSignal; static ɵfac: _angular_core.ɵɵFactoryDeclaration; static ɵcmp: _angular_core.ɵɵComponentDeclaration; } export { WR_SELECT, WrOption, WrOptionGroup, WrSelect }; export type { WrSelectContext, WrSelectMode, WrSelectSearchLoader, WrSelectSize, WrSelectTagValidator };