ngwr 15.2.0 → 15.3.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/alert/styles/_index.scss +13 -5
- package/fesm2022/ngwr-alert.mjs +2 -2
- package/fesm2022/ngwr-alert.mjs.map +1 -1
- package/fesm2022/ngwr-breadcrumbs.mjs +18 -2
- package/fesm2022/ngwr-breadcrumbs.mjs.map +1 -1
- package/fesm2022/ngwr-hotkey.mjs +23 -1
- package/fesm2022/ngwr-hotkey.mjs.map +1 -1
- package/fesm2022/ngwr-i18n-ar.mjs +2 -0
- package/fesm2022/ngwr-i18n-ar.mjs.map +1 -1
- package/fesm2022/ngwr-i18n-cs.mjs +2 -0
- package/fesm2022/ngwr-i18n-cs.mjs.map +1 -1
- package/fesm2022/ngwr-i18n-de.mjs +2 -0
- package/fesm2022/ngwr-i18n-de.mjs.map +1 -1
- package/fesm2022/ngwr-i18n-en.mjs +2 -0
- package/fesm2022/ngwr-i18n-en.mjs.map +1 -1
- package/fesm2022/ngwr-i18n-es.mjs +2 -0
- package/fesm2022/ngwr-i18n-es.mjs.map +1 -1
- package/fesm2022/ngwr-i18n-fr.mjs +2 -0
- package/fesm2022/ngwr-i18n-fr.mjs.map +1 -1
- package/fesm2022/ngwr-i18n-he.mjs +2 -0
- package/fesm2022/ngwr-i18n-he.mjs.map +1 -1
- package/fesm2022/ngwr-i18n-hi.mjs +2 -0
- package/fesm2022/ngwr-i18n-hi.mjs.map +1 -1
- package/fesm2022/ngwr-i18n-id.mjs +2 -0
- package/fesm2022/ngwr-i18n-id.mjs.map +1 -1
- package/fesm2022/ngwr-i18n-it.mjs +2 -0
- package/fesm2022/ngwr-i18n-it.mjs.map +1 -1
- package/fesm2022/ngwr-i18n-ja.mjs +2 -0
- package/fesm2022/ngwr-i18n-ja.mjs.map +1 -1
- package/fesm2022/ngwr-i18n-ko.mjs +2 -0
- package/fesm2022/ngwr-i18n-ko.mjs.map +1 -1
- package/fesm2022/ngwr-i18n-nl.mjs +2 -0
- package/fesm2022/ngwr-i18n-nl.mjs.map +1 -1
- package/fesm2022/ngwr-i18n-pl.mjs +2 -0
- package/fesm2022/ngwr-i18n-pl.mjs.map +1 -1
- package/fesm2022/ngwr-i18n-pt.mjs +2 -0
- package/fesm2022/ngwr-i18n-pt.mjs.map +1 -1
- package/fesm2022/ngwr-i18n-ru.mjs +2 -0
- package/fesm2022/ngwr-i18n-ru.mjs.map +1 -1
- package/fesm2022/ngwr-i18n-sv.mjs +2 -0
- package/fesm2022/ngwr-i18n-sv.mjs.map +1 -1
- package/fesm2022/ngwr-i18n-tr.mjs +2 -0
- package/fesm2022/ngwr-i18n-tr.mjs.map +1 -1
- package/fesm2022/ngwr-i18n-uk.mjs +2 -0
- package/fesm2022/ngwr-i18n-uk.mjs.map +1 -1
- package/fesm2022/ngwr-i18n-vi.mjs +2 -0
- package/fesm2022/ngwr-i18n-vi.mjs.map +1 -1
- package/fesm2022/ngwr-i18n-zh-tw.mjs +2 -0
- package/fesm2022/ngwr-i18n-zh-tw.mjs.map +1 -1
- package/fesm2022/ngwr-i18n-zh.mjs +2 -0
- package/fesm2022/ngwr-i18n-zh.mjs.map +1 -1
- package/fesm2022/ngwr-pagination.mjs +3 -0
- package/fesm2022/ngwr-pagination.mjs.map +1 -1
- package/fesm2022/ngwr-pipes.mjs +5 -2
- package/fesm2022/ngwr-pipes.mjs.map +1 -1
- package/fesm2022/ngwr-schema-form.mjs +3 -0
- package/fesm2022/ngwr-schema-form.mjs.map +1 -1
- package/fesm2022/ngwr-select-testing.mjs +16 -0
- package/fesm2022/ngwr-select-testing.mjs.map +1 -1
- package/fesm2022/ngwr-select.mjs +218 -38
- package/fesm2022/ngwr-select.mjs.map +1 -1
- package/fesm2022/ngwr-statistic.mjs +9 -5
- package/fesm2022/ngwr-statistic.mjs.map +1 -1
- package/fesm2022/ngwr-version.mjs +1 -1
- package/fesm2022/ngwr-version.mjs.map +1 -1
- package/i18n/ar.json +2 -0
- package/i18n/cs.json +2 -0
- package/i18n/de.json +2 -0
- package/i18n/en.json +2 -0
- package/i18n/es.json +2 -0
- package/i18n/fr.json +2 -0
- package/i18n/he.json +2 -0
- package/i18n/hi.json +2 -0
- package/i18n/id.json +2 -0
- package/i18n/it.json +2 -0
- package/i18n/ja.json +2 -0
- package/i18n/ko.json +2 -0
- package/i18n/nl.json +2 -0
- package/i18n/pl.json +2 -0
- package/i18n/pt.json +2 -0
- package/i18n/ru.json +2 -0
- package/i18n/sv.json +2 -0
- package/i18n/tr.json +2 -0
- package/i18n/uk.json +2 -0
- package/i18n/vi.json +2 -0
- package/i18n/zh-TW.json +2 -0
- package/i18n/zh.json +2 -0
- package/llms-full.txt +3 -3
- package/package.json +1 -1
- package/schematics/use/symbol-map.json +1 -0
- package/select/styles/_index.scss +23 -1
- package/skills/ngwr/references/catalog.md +1 -1
- package/types/ngwr-alert.d.ts +3 -1
- package/types/ngwr-breadcrumbs.d.ts +15 -0
- package/types/ngwr-hotkey.d.ts +14 -2
- package/types/ngwr-select-testing.d.ts +9 -0
- package/types/ngwr-select.d.ts +133 -2
- package/types/ngwr-sidebar.d.ts +1 -1
- package/types/ngwr-version.d.ts +1 -1
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"ngwr-select.mjs","names":[],"sources":["../../../projects/lib/select/option-leading.ts","../../../projects/lib/select/tokens/select.token.ts","../../../projects/lib/select/option.ts","../../../projects/lib/select/option.html","../../../projects/lib/select/select.ts","../../../projects/lib/select/select.html","../../../projects/lib/select/option-group.ts","../../../projects/lib/select/option-group.html"],"sourcesContent":["/**\n * @license\n *\n * Use of this source code is governed by an MIT-style license that can be\n * found in the LICENSE file at https://github.com/thekhegay/ngwr/blob/main/LICENSE\n */\n\nimport { Directive, TemplateRef, inject } from '@angular/core';\n\nimport type { SafeAny } from 'ngwr/utils';\n\nimport type { WrOptionLeadingContext } from './types';\n\n/**\n * A leading visual — an avatar, an icon, a colour dot — drawn before an\n * option's label, and kept out of that label.\n *\n * It is a TEMPLATE, and that is the point. Projected `<wr-option>` children are\n * created as soon as the page renders, panel open or not, so an avatar written\n * straight into each option is 200 components and 200 image requests for an\n * assignee picker nobody has opened. A template is only instantiated where it is\n * drawn:\n *\n * - in an option row, while the panel is OPEN — destroyed again when it closes,\n * and under `virtualScroll` only for the rows in the rendered window;\n * - in a selected chip on a `mode=\"multi\"` trigger, one per visible chip;\n * - beside the selected value on a single-mode BUTTON trigger — one copy;\n * - before the input on a SEARCH-shaped trigger (`mode=\"search\"`, a searchable\n * single), while that input is showing the selected label. It goes beside the\n * field rather than into it — an `<input>` holds a string — and it steps aside\n * while a query is on screen, panel open or half-typed, because the value it\n * names is not what the field is showing then. Picking an option brings it\n * back with the label. Stepping aside is a DESTROY, like a closing panel's\n * rows, so an `<img>`-backed visual re-mounts once per open-and-dismiss.\n *\n * Every copy sits in an `aria-hidden` wrapper and is skipped when the option's\n * text is read, so the trigger label, the chip, the search filter and the\n * option's accessible name all stay the option's words — never \"ХР Хегай Роман\".\n * Anything the visual says has to be said by the label as well.\n *\n * Two places to declare it. Inside a `<wr-option>` it belongs to that option.\n * As a DIRECT child of `<wr-select>` it is the default for every row, which is the\n * only way to reach rows the select draws itself — `[options]`, `[loader]`\n * results and virtual rows. An option's own template wins over the select's.\n *\n * @example\n * ```html\n * <wr-select mode=\"multi\" placeholder=\"Assignees\" [(value)]=\"assignees\">\n * @for (p of people; track p.id) {\n * <wr-option [value]=\"p.id\">\n * <ng-template wrOptionLeading let-placement=\"placement\">\n * <wr-avatar shape=\"circle\" [size]=\"placement === 'chip' ? 16 : 24\" [url]=\"p.photo\">{{ p.initials }}</wr-avatar>\n * </ng-template>\n * {{ p.name }}\n * </wr-option>\n * }\n * </wr-select>\n * ```\n */\n@Directive({\n selector: 'ng-template[wrOptionLeading]',\n})\nexport class WrOptionLeading<T = SafeAny> {\n readonly template = inject<TemplateRef<WrOptionLeadingContext<T>>>(TemplateRef);\n\n /**\n * Types the template's `let-` variables under `strictTemplates`. Without it\n * `let-placement` is `any`, and indexing a `Record<WrOptionLeadingPlacement, …>`\n * with it — the obvious way to size one visual per surface — does not compile.\n *\n * **`T` defaults to `SafeAny`, and that is the whole reason this is generic.**\n * The guard used to narrow to a bare `WrOptionLeadingContext`, which is\n * `WrOptionLeadingContext<unknown>` — so `let-value` came out `unknown` and\n * every use of it was a compile error under `strictTemplates`, which made the\n * guard WORSE than no guard at all: without one the variable is `any` and\n * `personName(id)` compiles. The value cannot be inferred — a structural\n * directive with no input has nothing to infer from, and the template is\n * declared on the select rather than on the option it draws — so the honest\n * type at this boundary is the unchecked one. `placement`, which is what the\n * guard exists for, stays narrowed either way.\n *\n * It bit the one documented shape that NEEDS the value: a template written as\n * a direct child of `<wr-select>` over `[options]`, where no outer `@for`\n * variable is in scope. This library's own docs page carries three helpers\n * typed `(id: unknown)` to get around it, with nothing saying why.\n */\n // eslint-disable-next-line @typescript-eslint/no-unused-vars -- a guard's parameters exist to be narrowed, never read\n static ngTemplateContextGuard<T>(_dir: WrOptionLeading<T>, _ctx: unknown): _ctx is WrOptionLeadingContext<T> {\n return true;\n }\n}\n","/**\n * @license\n *\n * Use of this source code is governed by an MIT-style license that can be\n * found in the LICENSE file at https://github.com/thekhegay/ngwr/blob/main/LICENSE\n */\n\nimport { InjectionToken } from '@angular/core';\n\nimport type { WrSelectContext } from '../types';\n\n/**\n * Token a `<wr-option>` injects to register itself with and notify its\n * parent `<wr-select>`.\n *\n * @internal\n */\nexport const WR_SELECT = new InjectionToken<WrSelectContext>('WR_SELECT');\n","/**\n * @license\n *\n * Use of this source code is governed by an MIT-style license that can be\n * found in the LICENSE file at https://github.com/thekhegay/ngwr/blob/main/LICENSE\n */\n\nimport { coerceBooleanProperty } from '@angular/cdk/coercion';\nimport { NgTemplateOutlet } from '@angular/common';\nimport {\n Component,\n ElementRef,\n type Signal,\n type TemplateRef,\n ViewEncapsulation,\n afterEveryRender,\n computed,\n contentChild,\n effect,\n inject,\n input,\n signal,\n untracked,\n viewChild,\n} from '@angular/core';\n\nimport { WrOptionLeading } from './option-leading';\nimport { WR_SELECT } from './tokens';\nimport type { WrOptionLeadingContext } from './types';\n\nlet uid = 0;\n\n/** `Node.TEXT_NODE` / `Node.ELEMENT_NODE`, spelled out: `Node` is not a global on the server. */\nconst TEXT_NODE = 3;\nconst ELEMENT_NODE = 1;\n\n/**\n * Single option inside a `<wr-select>`.\n *\n * The option's display label is taken from its projected text content — or\n * from `label`, when that is set — and the form value is its `value` input. A\n * leading visual goes in an `<ng-template wrOptionLeading>`, which keeps it out\n * of the label and uninstantiated while the panel is closed.\n *\n * @example\n * ```html\n * <wr-option value=\"sm\">Small</wr-option>\n * <wr-option [value]=\"42\">Forty-two</wr-option>\n * <wr-option [value]=\"p.id\" [label]=\"p.name\">\n * <ng-template wrOptionLeading><wr-avatar shape=\"circle\" size=\"1.5rem\">{{ p.initials }}</wr-avatar></ng-template>\n * {{ p.name }}\n * </wr-option>\n * ```\n */\n@Component({\n selector: 'wr-option',\n templateUrl: './option.html',\n encapsulation: ViewEncapsulation.None,\n imports: [NgTemplateOutlet],\n host: {\n role: 'option',\n '[attr.id]': 'id',\n '[class]': 'classes()',\n '[attr.aria-selected]': 'selected()',\n '[attr.aria-disabled]': 'unavailable() ? true : null',\n '(click)': 'onClick()',\n },\n})\nexport class WrOption {\n /** The value contributed when this option is chosen. Required. */\n readonly value = input.required<unknown>();\n\n /** Disable this option. @default false */\n readonly disabled = input(false, { transform: coerceBooleanProperty });\n\n /**\n * The text the select reports for this option — the trigger label, the chip,\n * the chip's remove label and the search filter all read it. Unset (or empty),\n * the option's own text is used, as it always was.\n *\n * Set it when the row shows more than the name: a projected email under a\n * person, a count beside a category. It does NOT rename the row itself — the\n * option's accessible name stays the text it draws, since a screen reader user\n * browsing the list should hear what a sighted one reads there.\n *\n * @default null\n */\n readonly label = input<string | null>(null);\n\n /** Stable id used for `aria-activedescendant`. */\n readonly id = `wr-option-${++uid}`;\n\n private readonly host = inject<ElementRef<HTMLElement>>(ElementRef);\n private readonly parent = inject(WR_SELECT, { optional: true });\n\n /** This option's own `<ng-template wrOptionLeading>`, if it declares one. */\n private readonly ownLeading = contentChild(WrOptionLeading);\n\n /**\n * The leading template that applies to this option: its own, else the\n * select-wide default. Registered with the parent so a chip can draw it.\n */\n private readonly leading: Signal<TemplateRef<WrOptionLeadingContext> | null> = computed(\n () => this.ownLeading()?.template ?? this.parent?.optionLeading() ?? null\n );\n\n /**\n * The leading template to draw in THIS row right now — `null` while the panel\n * is closed. A projected option is created with the page and lives, detached,\n * for as long as the select does, so gating on the template alone would\n * instantiate every row's avatar the moment the page renders. An option with\n * no parent select has no panel to wait for.\n */\n protected readonly rowLeading = computed(() => {\n if (this.parent && !this.parent.panelOpen()) return null;\n return this.leading();\n });\n\n /** The wrapper the leading visual renders into — skipped when reading the text. */\n private readonly leadingSlot = viewChild<ElementRef<HTMLElement>>('leadingSlot');\n\n /**\n * The option's own text, as a signal — the parent's trigger label and the\n * client-side filter both read it from here.\n *\n * It has to be a signal, and a plain `textContent` read cannot be one. The\n * label is PROJECTED content: the host template decides it, and the ordinary\n * way it changes is that a `WrI18n` catalog lands a microtask after the first\n * change-detection pass (`i18n/i18n.ts` writes every loader-backed catalog\n * from `firstValueFrom(...).then(...)`). Read once and cached, a trigger sat\n * on the English fallback while the open panel beside it showed the\n * translation — visible in `wr-pagination`'s size changer, which prints\n * `pagination.perPage` into each `<wr-option>`.\n *\n * Kept in step the way `wr-divider` keeps its own projected label: an\n * `effect` and an `afterEveryRender`, and both are needed. The render hook is\n * a hard no-op under SSR, so on its own the server would emit a trigger with\n * no label at all; the effect is not gated that way and runs after the\n * content has been projected. The effect on its own cannot follow text that\n * moves later, because it reads nothing reactive to be re-run by.\n *\n * @internal\n */\n private readonly labelText = signal('');\n\n /**\n * `label` when set, otherwise the option's own text. What the parent reads.\n * Not `??`: an EMPTY label falls back too, since a blank trigger or a nameless\n * chip is never what a `[label]=\"person.name\"` on a missing name meant.\n */\n private readonly resolvedLabel: Signal<string> = computed(() => {\n const explicit = this.label();\n return explicit !== null && explicit !== '' ? explicit : this.labelText();\n });\n\n /**\n * @internal — true when this option is currently selected. Works for\n * both single and multi-select parents via `WrSelectContext.isSelected`.\n */\n protected readonly selected = computed(() => {\n const parent = this.parent;\n if (!parent) return false;\n // Re-read parent's value signal so the computed recomputes on change.\n parent.value();\n return parent.isSelected(this.value());\n });\n\n /**\n * @internal — disabled, or not chosen in a multi select that already holds\n * `maxItems`: either way a pick is refused, so the row says so rather than\n * looking choosable.\n */\n protected readonly unavailable = computed(() => this.disabled() || (!this.selected() && !!this.parent?.atMaxItems()));\n\n /** @internal — true when this option is the keyboard cursor target. */\n protected readonly active = computed(() => this.parent?.activeOptionId() === this.id);\n\n /**\n * @internal — searchable selects only. True when the parent has a query that\n * the option's label does not match (case-insensitive substring) — `label`\n * when set, the option's text otherwise, and never its leading visual.\n * Hidden options stay in the DOM so registration order survives but\n * collapse via CSS.\n */\n protected readonly hidden = computed(() => {\n const parent = this.parent;\n if (!parent?.isSearchable() || !parent.clientFilter()) return false;\n const q = parent.searchQuery().trim().toLowerCase();\n if (!q) return false;\n return !this.resolvedLabel().toLowerCase().includes(q);\n });\n\n protected readonly classes = computed(() => {\n const parts = ['wr-option'];\n if (this.selected()) parts.push('wr-option--selected');\n if (this.active()) parts.push('wr-option--active');\n if (this.unavailable()) parts.push('wr-option--disabled');\n if (this.hidden()) parts.push('wr-option--hidden');\n return parts.join(' ');\n });\n\n constructor() {\n if (this.parent) {\n const parent = this.parent;\n // Re-register when disabled or value changes so the parent has fresh metadata.\n // The label is seeded here as well, which is the read the server takes.\n effect(onCleanup => {\n // Untracked: the read goes through the `leadingSlot` query, which moves\n // every time the panel opens or closes, and a registration keyed on it\n // would unregister and re-register every option on each of those — a\n // registry write per option, and a recompute of everything the select\n // derives from the registry, for a change the registration does not\n // carry. The label itself still follows through `afterEveryRender`.\n untracked(() => this.syncLabel());\n const unreg = parent.registerOption({\n id: this.id,\n value: this.value(),\n disabled: this.disabled(),\n label: this.resolvedLabel,\n host: this.host.nativeElement,\n leading: this.leading,\n });\n onCleanup(() => unreg());\n });\n\n afterEveryRender(() => this.syncLabel());\n }\n }\n\n /**\n * Read the projected text back off the DOM. Setting the same string again is\n * a signal no-op, so the render hook costs a short walk over the host's\n * children and nothing else on the passes where nothing moved.\n *\n * A walk rather than the host's `textContent`, because the leading visual\n * renders INSIDE the host while the panel is open: a `textContent` read turned\n * an avatar's initials into the first word of the label, so the chip and the\n * search filter read \"ХР Хегай Роман\". Only text and element children count —\n * a comment's `textContent` is its data, and Angular anchors every\n * `<ng-template>` with one.\n */\n private syncLabel(): void {\n const slot = this.leadingSlot()?.nativeElement;\n let text = '';\n for (const node of Array.from(this.host.nativeElement.childNodes)) {\n if (node === slot) continue;\n if (node.nodeType === TEXT_NODE || node.nodeType === ELEMENT_NODE) text += node.textContent ?? '';\n }\n this.labelText.set(text.trim());\n }\n\n protected onClick(): void {\n if (this.disabled() || !this.parent) return;\n this.parent.selectOption(this.value());\n }\n}\n","<!-- The leading visual is a sibling of the projected text, never a wrapper\n around it: `.wr-option` is a flex row, and wrapping the content would fold\n a consumer's own icon and label into one flex item. `aria-hidden` keeps it\n out of the option's accessible name; `syncLabel` skips it by reference. -->\n@if (rowLeading(); as leading) {\n <span #leadingSlot class=\"wr-option__leading\" aria-hidden=\"true\">\n <ng-container\n [ngTemplateOutlet]=\"leading\"\n [ngTemplateOutletContext]=\"{ $implicit: value(), placement: 'option' }\"\n />\n </span>\n}\n<ng-content />\n","/**\n * @license\n *\n * Use of this source code is governed by an MIT-style license that can be\n * found in the LICENSE file at https://github.com/thekhegay/ngwr/blob/main/LICENSE\n */\n\nimport { Directionality } from '@angular/cdk/bidi';\nimport { coerceBooleanProperty, coerceNumberProperty } from '@angular/cdk/coercion';\nimport { type OverlayRef, ScrollStrategyOptions } from '@angular/cdk/overlay';\nimport { TemplatePortal } from '@angular/cdk/portal';\nimport { NgTemplateOutlet, isPlatformBrowser } from '@angular/common';\nimport {\n Component,\n DestroyRef,\n ElementRef,\n Injector,\n PLATFORM_ID,\n TemplateRef,\n ViewContainerRef,\n ViewEncapsulation,\n afterNextRender,\n computed,\n contentChild,\n contentChildren,\n effect,\n forwardRef,\n inject,\n input,\n model,\n output,\n signal,\n viewChild,\n} from '@angular/core';\nimport { takeUntilDestroyed, toObservable } from '@angular/core/rxjs-interop';\nimport type { FormValueControl } from '@angular/forms/signals';\n\nimport {\n type Observable,\n catchError,\n debounce,\n defer,\n finalize,\n from,\n isObservable,\n of,\n skip,\n switchMap,\n tap,\n timer,\n} from 'rxjs';\n\nimport { WR_FORM_FIELD, useFormFieldAria } from 'ngwr/form';\nimport { useI18nFormatter, useI18nText } from 'ngwr/i18n';\nimport { WR_OVERLAY, WrOutsideClick, wrFollowDirection } from 'ngwr/overlay';\nimport { isComposing, toClassList, type WrClassInput } from 'ngwr/utils';\n\nimport { WrOption } from './option';\nimport { WrOptionLeading } from './option-leading';\nimport { WR_SELECT } from './tokens';\nimport type {\n WrOptionLeadingContext,\n WrSelectMode,\n WrSelectSearchLoader,\n WrSelectTagValidator,\n WrSelectSize,\n WrSelectContext,\n WrSelectOptionRegistration,\n} from './types';\n\nlet listboxUid = 0;\n\ninterface SelectedChip {\n readonly value: unknown;\n readonly label: string;\n /** The leading template this chip draws, or `null`. */\n readonly leading: TemplateRef<WrOptionLeadingContext> | null;\n}\n\n/**\n * Combobox primitive. Renders a button that opens a CDK overlay\n * containing the projected `<wr-option>` (and optionally\n * `<wr-option-group>`) children. Every shape is the same component\n * with a different `[mode]`:\n *\n * - `'single'` (default) — one value, no input. Classic dropdown.\n * - `'multi'` — array value, chips on the trigger; clicking an option\n * toggles instead of closing, Backspace removes the last chip.\n * - `'search'` — type-ahead with sync `[options]` filter or async\n * `[loader]`. Replaces the standalone `<wr-autocomplete>`.\n * - `'tag'` — free-text + chips with `[separators]` / `[validate]` /\n * `[allowDuplicates]`. Replaces `<wr-chips-input>`.\n *\n * `[searchable]` is orthogonal to the mode — it adds the type-ahead filter to\n * `single` / `multi` without changing the value shape, which is how you get a\n * searchable multi-select. Server-side search hangs off the `(searchChange)` output\n * plus `[options]` / `[loading]`.\n *\n * A signal-forms native control: it implements `FormValueControl<unknown>`, so\n * `[formField]` binds straight to its `value` model — no\n * `ControlValueAccessor` in between. `[(value)]` works standalone, and classic\n * `[(ngModel)]` / reactive forms keep working through Angular's bridge.\n *\n * @example\n * ```html\n * <!-- Single (signal forms) -->\n * <wr-select placeholder=\"Pick a size\" [formField]=\"form.size\">\n * <wr-option value=\"sm\">Small</wr-option>\n * <wr-option value=\"md\">Medium</wr-option>\n * <wr-option value=\"lg\">Large</wr-option>\n * </wr-select>\n *\n * <!-- Multi (standalone two-way binding) -->\n * <wr-select mode=\"multi\" placeholder=\"Pick tags\" [(value)]=\"tags\">\n * <wr-option value=\"ts\">TypeScript</wr-option>\n * <wr-option value=\"ng\">Angular</wr-option>\n * </wr-select>\n *\n * <!-- Multi + type-ahead, options from a store -->\n * <wr-select\n * mode=\"multi\"\n * searchable\n * [options]=\"results()\"\n * [loading]=\"pending()\"\n * [(value)]=\"categories\"\n * (searchChange)=\"store.search($event)\"\n * />\n * ```\n *\n *\n * @see https://ngwr.dev/reference/components/select\n */\n@Component({\n selector: 'wr-select',\n templateUrl: './select.html',\n encapsulation: ViewEncapsulation.None,\n host: { '[class]': 'classes()' },\n imports: [WrOption, NgTemplateOutlet],\n providers: [\n {\n provide: WR_SELECT,\n // eslint-disable-next-line @angular-eslint/no-forward-ref\n useExisting: forwardRef(() => WrSelect),\n },\n ],\n})\nexport class WrSelect implements FormValueControl<unknown>, WrSelectContext {\n /** Placeholder shown when no option is selected. Falls back to `select.placeholder`. */\n readonly placeholder = input<string | null>(null);\n\n /** Clear-selection (×) button aria-label. Falls back to `select.clearSelection`. */\n readonly clearLabel = input<string | null>(null);\n\n protected readonly resolvedPlaceholder = useI18nText(this.placeholder, 'select.placeholder', '');\n protected readonly resolvedClear = useI18nText(this.clearLabel, 'select.clearSelection', 'Clear selection');\n\n /**\n * Accessible name of the trigger. Falls back to the placeholder, then to\n * `select.label` — `role=\"combobox\"` on an empty trigger otherwise has no name\n * at all, which is the common case before anything is selected.\n */\n readonly ariaLabel = input<string | null>(null);\n\n private readonly labelText = useI18nText(this.ariaLabel, 'select.label', 'Select');\n protected readonly resolvedAriaLabel = computed(() => {\n // Not `??`: an empty placeholder must fall through to the catalog string.\n const explicit = this.ariaLabel();\n if (explicit) return explicit;\n const placeholder = this.resolvedPlaceholder();\n return placeholder ? placeholder : this.labelText();\n });\n\n /**\n * The field's own label, when it renders one — `null` otherwise, and `null`\n * when `[ariaLabel]` was set deliberately.\n *\n * `aria-label` outranks a `<label for>` in the accname order, so a control\n * inside `<wr-form-field label=\"Delivery notes\">` with a placeholder of its\n * own announced the PLACEHOLDER and the visible label reached nobody.\n * Nothing catches it: the control has a name, so axe is satisfied, and the\n * name is plausible, so a reader is too — it fails WCAG 2.5.3, where the\n * visible label has to be IN the accessible name.\n */\n protected readonly labelledBy = computed(() => (this.ariaLabel() ? null : this.fieldAria.labelledBy()));\n\n /** `null` once `aria-labelledby` is carrying the name — see {@link labelledBy}. */\n protected readonly nameLabel = computed(() => (this.labelledBy() ? null : this.resolvedAriaLabel()));\n\n /** Per-chip ARIA label — interpolates `{{label}}`. @internal */\n protected readonly chipRemoveLabel = useI18nFormatter('select.removeItem', 'Remove {{label}}');\n\n /**\n * The overflow chip past `maxTagCount` — interpolates `{{count}}`. Through the\n * catalog, like every other string here: printed as a bare `+{{ extra }} more`\n * it stayed English in a fully localized app, beside an event-calendar cell\n * reading \"ещё 3\" from the same string. @internal\n */\n protected readonly moreLabel = useI18nFormatter('select.more', '+{{count}} more');\n\n private readonly field = inject(WR_FORM_FIELD, { optional: true });\n\n /**\n * Id the surrounding `<wr-form-field>`'s `<label for>` points at.\n *\n * The field renders its label before it can see what was projected into it, so\n * the id travels the other way and the control adopts it, exactly as `[wrInput]`\n * and `wr-slider` do. Without this the `for` named an element that was nowhere in\n * the document: clicking the label did nothing, and the field's own text reached\n * the control through no path at all.\n *\n * It lands on the ONE focusable element each trigger shape has — the button, the\n * search input, or the tag input — never on the host, because only a labelable\n * element can be a label's target and `<wr-select>` is not one.\n *\n * What this does NOT change is that element's NAME: `aria-label` outranks a\n * `<label>` in the accname order, and the trigger keeps `resolvedAriaLabel()`\n * because the field cannot promise it has a name to give — `<wr-form-field>`\n * renders a label only when its `label` input is set, and a combobox that traded\n * a generic name for no name would be the worse bug. `WrFormFieldContext`\n * publishes no \"do I have a visible label\" signal to key that on. Until it does,\n * set `[ariaLabel]` to the field's label where the two should read alike.\n */\n protected readonly controlId = computed(() => this.field?.controlId() ?? null);\n\n /**\n * The field's error message — or, failing that, its hint — wired to the same\n * element, plus the invalid flag.\n *\n * Without it the copy `<wr-form-field>` renders is visible and nothing else: a\n * screen reader on the trigger never learns the field is invalid, nor what the\n * message says. Composed by `useFormFieldAria()` rather than read off the field\n * here, so the trigger picks up the hint the same way the other value controls\n * do and `aria-invalid` stays keyed on the error rather than on \"is anything\n * describing me\".\n */\n private readonly fieldAria = useFormFieldAria();\n protected readonly describedBy = this.fieldAria.describedBy;\n protected readonly ariaInvalid = this.fieldAria.ariaInvalid;\n\n /**\n * Disable the select. Bound automatically from the field's disabled state\n * when used with `[formField]`.\n *\n * @default false\n */\n readonly disabled = input(false, { transform: coerceBooleanProperty });\n\n /**\n * Refuse changes while the trigger stays focusable and the value still\n * submits. Bound automatically from the field's readonly state when used with\n * `[formField]`.\n *\n * The panel is where every edit happens, so a read-only select does not open —\n * and with it go the clear button, the chip ×, the tag draft and the search\n * query. The text-input shapes take the native `readonly` attribute, which is\n * what keeps them focusable and selectable where `disabled` would not; every\n * shape mirrors `aria-readonly`, which role `combobox` supports.\n *\n * @default false\n */\n readonly readonly = input(false, { transform: coerceBooleanProperty });\n\n /** Pill-shaped corners on the trigger. @default false */\n readonly rounded = input(false, { transform: coerceBooleanProperty });\n\n /**\n * Control size — shares the `--wr-control-*` contract. Read by the trigger's\n * host classes AND by the overlay panel, which builds its size modifier\n * separately. @default 'md'\n */\n readonly size = input<WrSelectSize>('md');\n\n /**\n * Behavior mode. `<wr-select>` is the unified combobox primitive —\n * pick the shape via `[mode]`:\n *\n * - `'single'` (default) — one value, no input. Classic dropdown.\n * - `'multi'` — array value, chips on the trigger.\n * - `'search'` — type-ahead with sync filter or async loader.\n * - `'tag'` — free-text + chips.\n *\n */\n readonly mode = input<WrSelectMode | null>(null);\n\n /** Resolved mode — `'single'` unless `[mode]` says otherwise. */\n protected readonly effectiveMode = computed<WrSelectMode>(() => this.mode() ?? 'single');\n\n /** Convenience — `effectiveMode() === 'multi'`. */\n protected readonly isMulti = computed(() => this.effectiveMode() === 'multi');\n\n /** Convenience — `effectiveMode() === 'tag'`. */\n protected readonly isTag = computed(() => this.effectiveMode() === 'tag');\n\n /** Convenience — `effectiveMode() === 'search'`. Exposed via context for options. */\n readonly isSearch = computed(() => this.effectiveMode() === 'search');\n\n /**\n * Add a type-ahead filter without changing the value shape — the missing\n * multi-with-search combination, since `[mode]` picks exactly one shape:\n *\n * ```html\n * <wr-select mode=\"multi\" searchable [(value)]=\"categories\">…</wr-select>\n * ```\n *\n * On `multi` the trigger keeps its chips and grows an inline text field (the\n * shape `tag` mode already uses); on `single` it is equivalent to\n * `mode=\"search\"`. Every search input (`[options]`, `[loader]`,\n * `[debounceMs]`, `[minChars]`, `[virtualScroll]`, the `(searchChange)` output, …)\n * applies either way. Ignored in `tag` mode, which owns its own input.\n * @default false\n */\n readonly searchable = input(false, { transform: coerceBooleanProperty });\n\n /**\n * Filtering is active — either `mode=\"search\"` or `[searchable]`. Exposed via\n * context so each `<wr-option>` can self-hide non-matching rows.\n */\n readonly isSearchable = computed(() => this.isSearch() || (this.searchable() && !this.isTag()));\n\n /** The trigger *is* the search input: `mode=\"search\"`, or a searchable single. */\n protected readonly isSearchTrigger = computed(() => this.isSearch() || (this.searchable() && !this.hasChips()));\n\n /** Chips plus an inline search field — a searchable multi-select. */\n protected readonly hasChipSearch = computed(() => this.searchable() && this.isMulti());\n\n /** WrSelectContext — resolved multi-selection flag for child options. */\n readonly multi = computed(() => this.effectiveMode() === 'multi' || this.effectiveMode() === 'tag');\n\n /** Both multi and tag render chips on the trigger. */\n protected readonly hasChips = computed(() => {\n const m = this.effectiveMode();\n return m === 'multi' || m === 'tag';\n });\n\n /**\n * The live search query. Empty string = no filter. Exposed via context so\n * each `<wr-option>` can self-hide non-matching rows.\n *\n * Two-way bindable, so the query can be owned or reset from outside:\n * `[(searchQuery)]=\"query\"`. For server-side search prefer the debounced\n * {@link searchChange} output — `searchQueryChange` fires on every keystroke.\n */\n readonly searchQuery = model('');\n\n // Search-mode-only inputs (ignored in other modes)\n\n /**\n * Search mode: dynamic option array. Each item is rendered as a\n * `<wr-option>` whose label comes from `[displayWith]`. Works\n * alongside projected `<wr-option>` children — both lists are\n * filtered by the search query.\n */\n readonly options = input<readonly unknown[]>([]);\n\n /** Search mode: map a dynamic option item to its display label. @default String */\n readonly displayWith = input<(item: unknown) => string>((item: unknown) => String(item));\n\n /**\n * Search mode: async loader. When set, the loader is called on every\n * (debounced) keystroke and its result replaces `[options]`. Supports\n * Observables, Promises, and plain arrays.\n */\n readonly loader = input<WrSelectSearchLoader<unknown> | null>(null);\n\n /**\n * The option list is already scoped to the query upstream — skip the built-in\n * client-side label filter. Set it when `[options]` is fed from a server via\n * the {@link searchChange} output; the async `[loader]` path implies it.\n *\n * Without this, a server that ranks or fuzzy-matches (returning rows whose\n * labels don't literally contain the query) would have those rows hidden\n * again on the client. @default false\n */\n readonly serverSearch = input(false, { transform: coerceBooleanProperty });\n\n /**\n * Whether the built-in label filter runs. Exposed via context so each\n * `<wr-option>` knows whether to self-hide. @internal\n */\n readonly clientFilter = computed(() => !this.loader() && !this.serverSearch());\n\n /** Search mode: debounce (ms) applied to the loader. @default 250 */\n readonly debounceMs = input(250, { transform: (v: unknown): number => Math.max(0, Number(v) || 0) });\n\n /** Search mode: minimum query length before the panel opens / loader fires. @default 0 */\n readonly minChars = input(0, { transform: (v: unknown): number => Math.max(0, Number(v) || 0) });\n\n /**\n * Search mode: allow values not in the options list. Enter on an\n * unmatched query commits the raw text as the form value. @default false\n */\n readonly freeText = input(false, { transform: coerceBooleanProperty });\n\n /**\n * Search mode: window the option panel so thousands of `[options]` keep only\n * ~one viewport of rows in the DOM. Opt-in and OFF by default. Engages ONLY on\n * the pure data-array search tier — it silently falls back to the full render\n * when static `<wr-option>` children are projected or the filtered list is\n * empty. While on, rows are plain `role=\"option\"` elements (no `<wr-option>`),\n * navigated via `aria-activedescendant`, selected by value. @default false\n */\n readonly virtualScroll = input(false, { transform: coerceBooleanProperty });\n\n /**\n * Search mode: uniform option-row height in px for the virtual window. `0`\n * (default) measures the first rendered row once and reuses it, so it adapts\n * to the control size. Read only when `virtualScroll` engages. @default 0\n */\n readonly rowHeight = input(0, { transform: (v: unknown): number => Math.max(0, coerceNumberProperty(v, 0)) });\n\n /**\n * Search mode: height of the virtual scroll viewport — a number (px) or any\n * CSS length. @default 256\n */\n readonly viewportHeight = input<number | string>(256);\n\n /** Search mode: extra rows kept above/below the virtual viewport. @default 6 */\n readonly overscan = input(6, { transform: (v: unknown): number => Math.max(0, coerceNumberProperty(v, 6)) });\n\n /** Search mode: text shown when the filter / loader returns nothing. Falls back to `select.noResults`. */\n readonly noResultsText = input<string | null>(null);\n\n /** Search mode: text shown while the async loader is in flight. Falls back to `select.loading`. */\n readonly loadingText = input<string | null>(null);\n\n protected readonly resolvedNoResults = useI18nText(this.noResultsText, 'select.noResults', 'No results');\n protected readonly resolvedLoading = useI18nText(this.loadingText, 'select.loading', 'Loading…');\n\n /**\n * Debounced search query, gated to searchable selects. Emits on every settled\n * change — including the empty string when the field is cleared — so a\n * store-backed option list can stay in sync and reset itself. `[debounceMs]`\n * controls the delay; `[minChars]` does NOT gate it, for the same reason the\n * `[loader]` path clears its results below that threshold.\n *\n * This is the hook for server-side search: dispatch on `(searchChange)`, feed\n * the results back through `[options]` (plus `[serverSearch]`), and drive the\n * panel's progress row with `[loading]`. Prefer it over the model's raw\n * `(searchQueryChange)`, which fires on every keystroke.\n *\n * @example\n * ```html\n * <wr-select\n * mode=\"search\"\n * serverSearch\n * [options]=\"results()\"\n * [loading]=\"pending()\"\n * (searchChange)=\"store.search($event)\"\n * />\n * ```\n */\n readonly searchChange = output<string>();\n\n /**\n * Show the panel's progress row. Independent of `[loader]`, which raises and\n * lowers its own flag — use this when the options come from a store fed by\n * the {@link searchChange} output. @default false\n */\n readonly loading = input(false, { transform: coerceBooleanProperty });\n\n /** Search mode: results returned by the async loader. @internal */\n protected readonly loadedOptions = signal<readonly unknown[]>([]);\n\n /** True while the async `[loader]` is in flight. @internal */\n private readonly loaderLoading = signal(false);\n\n /** Either flag shows the panel's progress row. @internal */\n protected readonly isLoading = computed(() => this.loading() || this.loaderLoading());\n\n // Tag-mode-only inputs (ignored in other modes)\n\n /**\n * Tag mode: keys / characters that commit the current draft into a chip.\n * `'Enter'` is the key name; everything else is a literal character watched\n * in keypresses and pastes. @default ['Enter', ',']\n */\n readonly separators = input<readonly string[]>(['Enter', ',']);\n\n /** Tag mode: allow the same value to appear more than once. @default false */\n readonly allowDuplicates = input(false, { transform: coerceBooleanProperty });\n\n /**\n * Tag mode: custom validator — return `true` to accept the value, `false`\n * to silently reject. Receives the trimmed draft + the existing chips.\n */\n readonly validate = input<WrSelectTagValidator | null>(null);\n\n /** Tag-mode draft (text currently typed in the inline input). @internal */\n protected readonly draft = signal('');\n\n /**\n * Show a clear (×) button once at least one option is selected.\n *\n * NOT multi-only, which this said for a long time and which the template\n * refutes: only the button trigger gates on `isMulti()`, so the chips trigger\n * AND a single `mode=\"search\"` / `[searchable]` select carry it too. The\n * wording mattered little while the default was `true`; it decides what a\n * reader expects to lose now that it is not.\n *\n * The default changed from `true` to `false`: the affordance is opt-in, so a\n * trigger that grew an × on its own no longer does — pass `clearable` to keep\n * it. In `search` mode this also gates Backspace-to-clear on an empty field,\n * since that key is the keyboard twin of this button. @default false\n */\n readonly clearable = input(false, { transform: coerceBooleanProperty });\n\n /**\n * Extra CSS classes for the dropdown panel's overlay pane.\n *\n * The pane is appended to the overlay container, not to this component, so\n * nothing in the consumer's own template encloses it and no descendant rule\n * written around the trigger can reach it. This input is the only per-instance\n * handle on it. A space-separated string works as well as an array.\n *\n * The pane is a positioning wrapper carrying the gap above the list; the\n * box that paints is `.wr-select-panel` inside it, so a rule meant for the\n * surface reads `.my-class .wr-select-panel`.\n */\n readonly panelClass = input<WrClassInput>(null);\n\n /**\n * Cap on selected items (multi mode). `0` = unlimited. Once reached, the\n * unselected options are marked unavailable — `aria-disabled` and the\n * disabled look — and refuse a pick until one is removed. @default 0\n */\n readonly maxItems = input(0, {\n transform: (v: unknown): number => Math.max(0, Number(v) || 0),\n });\n\n /**\n * Maximum number of chips rendered before collapsing the rest into a\n * `+N more` indicator. `0` = render every chip. @default 0\n */\n readonly maxTagCount = input(0, {\n transform: (v: unknown): number => Math.max(0, Number(v) || 0),\n });\n\n /**\n * Unified value. Single mode holds a scalar (or `null`); multi / tag\n * mode holds `readonly unknown[]`. Bound by `[formField]`, or two-way\n * via `[(value)]`.\n */\n readonly value = model<unknown>(null);\n\n /** Emitted on blur / commit so a bound field can mark itself touched. */\n readonly touch = output<void>();\n\n /** Listbox id used by the trigger's `aria-controls`. */\n protected readonly listboxId = `wr-select-listbox-${++listboxUid}`;\n\n /** Registered options (insertion order). Internal — distinct from the public `[options]` input. */\n private readonly registry = signal<readonly WrSelectOptionRegistration[]>([]);\n\n /**\n * The registry in DOM order — the list the keyboard cursor walks.\n *\n * `registry` is CREATION order, and projected `<wr-option>` children are created\n * before the panel renders its own `[options]` rows, so with both in play the\n * cursor moved in an order the eye could not follow: opening highlighted the\n * third row on screen and ArrowDown went to the last. Value lookups keep reading\n * `registry` — they do not care about order — and a registration with no element\n * keeps its place, since the sort is stable.\n */\n private readonly orderedRegistry = computed<readonly WrSelectOptionRegistration[]>(() => {\n const list = this.registry();\n if (list.length < 2) return list;\n return [...list].sort((a, b) => {\n if (!a.host || !b.host || a.host === b.host) return 0;\n const relation = a.host.compareDocumentPosition(b.host);\n // `compareDocumentPosition` returns a BITMASK — a node can be both\n // following and contained — so masking is the API's own idiom, not a\n // cleverness to be rewritten as a comparison.\n /* eslint-disable no-bitwise -- reading the flags of a DOM bitmask */\n // DISCONNECTED is checked FIRST, and it is not defensive noise. Projected\n // `<wr-option>` hosts live in an `<ng-template>` that only instantiates\n // when the panel opens, so on the first change detection they are not in\n // the document yet — and the template's own `aria-activedescendant`\n // binding reads this computed on exactly that pass. For disconnected nodes\n // the spec lets a UA answer PRECEDING or FOLLOWING arbitrarily, as long as\n // it answers consistently; the answer means nothing, and the computed\n // CACHES it until the registry itself changes, so one meaningless\n // comparison decides the cursor order for the life of the select. Chromium\n // happens to answer in tree order and jsdom happens to answer in reverse,\n // which is the whole difference between a working component and one where\n // End lands on the first option. Registration order is the honest fallback:\n // the sort is stable, and it is already DOM order for a static list.\n if (relation & Node.DOCUMENT_POSITION_DISCONNECTED) return 0;\n if (relation & Node.DOCUMENT_POSITION_FOLLOWING) return -1;\n if (relation & Node.DOCUMENT_POSITION_PRECEDING) return 1;\n /* eslint-enable no-bitwise */\n return 0;\n });\n });\n\n /** Keyboard cursor index into `options`. -1 = none. */\n protected readonly activeIndex = signal(-1);\n\n /** Id of the active option (for `aria-activedescendant`). */\n readonly activeOptionId = computed<string | null>(() => {\n const idx = this.activeIndex();\n if (this.virtualActive()) {\n // Virtual rows aren't registered; the active id is derived from the index,\n // and returned only while the row is inside the rendered window so\n // `aria-activedescendant` never dangles at a recycled element.\n const { start, end } = this.virtualWindow();\n return idx >= start && idx < end ? this.virtualRowId(idx) : null;\n }\n const list = this.orderedRegistry();\n return idx >= 0 && idx < list.length ? list[idx].id : null;\n });\n\n protected readonly open = signal(false);\n\n /** WrSelectContext — whether the panel is open. Options gate their leading visual on it. */\n readonly panelOpen = this.open.asReadonly();\n\n /**\n * A `<ng-template wrOptionLeading>` declared as a DIRECT child of the select —\n * `descendants: false`, so an option's own template is never mistaken for the\n * select-wide default.\n */\n private readonly defaultLeading = contentChild(WrOptionLeading, { descendants: false });\n\n /**\n * WrSelectContext — the select-wide leading template, or `null`. The only\n * way to give a leading visual to the rows the select draws itself (`[options]`,\n * `[loader]` results, virtual rows), and the default for projected options that\n * declare none of their own.\n */\n readonly optionLeading = computed<TemplateRef<WrOptionLeadingContext> | null>(\n () => this.defaultLeading()?.template ?? null\n );\n\n /**\n * The leading template for a value: the registered option's (its own, or the\n * default it resolved to), else the select-wide default for a value with no\n * registered option — a virtual row, or one a loader has since dropped.\n */\n private leadingFor(value: unknown): TemplateRef<WrOptionLeadingContext> | null {\n const found = this.registry().find(o => o.value === value);\n if (found?.leading) return found.leading();\n return this.optionLeading();\n }\n\n /**\n * The leading visual beside the selected value on a single-mode BUTTON trigger\n * — one instance, for the one selected value. A search-shaped trigger draws the\n * same visual through {@link searchLeading}, on a narrower condition.\n */\n protected readonly selectedLeading = computed<TemplateRef<WrOptionLeadingContext> | null>(() => {\n if (this.isMulti() || this.selectedLabel() == null) return null;\n return this.leadingFor(this.value());\n });\n\n /**\n * The same visual on a SEARCH-shaped trigger (`mode=\"search\"`, a searchable\n * single), drawn before the input — the surface an assignee picker actually\n * uses, and the one that lost its avatar the moment the trigger became a field.\n *\n * The condition is {@link searchShowsValue} rather than `hasSelection()`, and\n * the two part company on every open panel: focusing the field replaces the\n * label with the live query, which starts empty, so what is on screen is the\n * placeholder. An avatar left standing there names a value the field no longer\n * shows, and then sits in front of whatever the user types next — the visual\n * would be answering a different question from the text beside it. It comes\n * back with the label, which is one signal flipping rather than two things\n * kept in step: committing a choice clears the query and closes the panel.\n *\n * Nothing is instantiated for a search select with no selection, panel open or\n * shut — `selectedLabel()` is `null` there, and this returns `null` with it.\n *\n * The COST of that rule, stated because it is a consumer's to weigh: stepping\n * aside is a destroy, so opening the picker and dismissing it unchanged\n * re-creates the visual — a template built on an `<img>` re-mounts once per\n * round trip, and re-requests unless the cache answers. Kept rather than\n * traded for a hidden-but-alive node: the panel's own rows already create and\n * destroy one apiece on the same gesture, so holding this one back buys a\n * fraction of that, and a node retained while it must not be seen is a second\n * piece of state to keep in step with the field. Pinned in `option.spec.ts`\n * (\"re-creates it after a round trip\"), so a future change here has to say so.\n */\n protected readonly searchLeading = computed<TemplateRef<WrOptionLeadingContext> | null>(() => {\n if (!this.isSearchTrigger() || !this.searchShowsValue()) return null;\n if (this.selectedLabel() == null) return null;\n return this.leadingFor(this.value());\n });\n\n /**\n * Trigger label for single mode. Multi reads `selectedChips` instead.\n *\n * A `computed`, and that is the whole point. It used to be a `signal` written\n * from an effect keyed on `value` / `registry` / `isMulti` / `displayWith` —\n * not one of which moves when the OPTION'S OWN TEXT does, and that text is\n * projected content whose ordinary way of changing is a translation catalog\n * landing a microtask after the first pass. The trigger kept the English\n * fallback while the open panel beside it showed the translation. The\n * registration now carries the label as a signal, so a late catalog and a\n * runtime locale switch both repaint the trigger with the panel.\n */\n protected readonly selectedLabel = computed<string | null>(() => {\n const v = this.value();\n if (this.isMulti()) return null;\n const match = this.registry().find(o => o.value === v);\n if (match) return match.label();\n // Search mode: a value picked from a virtualized (or since-unmounted) row\n // has no registered `<wr-option>`, so derive its label from `displayWith`\n // — the same function that rendered the row.\n return v != null && this.isSearchable() ? this.displayWith()(v) : null;\n });\n\n /**\n * Selected chips (multi + tag modes). Multi reads labels from the\n * registered `<wr-option>` children; tag uses each raw string as\n * both value and label.\n */\n protected readonly selectedChips = computed<readonly SelectedChip[]>(() => {\n if (!this.hasChips()) return [];\n const arr = this.asArray(this.value());\n if (this.isTag()) {\n // Tag values are free text with no option behind them, so no leading.\n return arr.map<SelectedChip>(v => ({ value: v, label: String(v), leading: null }));\n }\n const list = this.registry();\n return arr.map<SelectedChip>(v => {\n const found = list.find(o => o.value === v);\n // Fall back to `displayWith` (defaults to `String`) rather than `String`\n // directly: a searchable multi fed from `[options]` has no registered\n // `<wr-option>` for a virtualized or unmounted row, and object items\n // would otherwise render as \"[object Object]\".\n return {\n value: v,\n label: found?.label() ?? this.displayWith()(v),\n leading: found?.leading ? found.leading() : this.optionLeading(),\n };\n });\n });\n\n protected readonly visibleChips = computed<readonly SelectedChip[]>(() => {\n const cap = this.maxTagCount();\n const chips = this.selectedChips();\n return cap > 0 && chips.length > cap ? chips.slice(0, cap) : chips;\n });\n\n protected readonly hiddenChipCount = computed(() => {\n const cap = this.maxTagCount();\n const total = this.selectedChips().length;\n return cap > 0 && total > cap ? total - cap : 0;\n });\n\n protected readonly hasSelection = computed(() => {\n if (this.hasChips()) return this.selectedChips().length > 0;\n return this.value() != null;\n });\n\n /** Effective disabled state. Part of {@link WrSelectContext} for child options. */\n readonly isDisabled = computed(() => this.disabled());\n\n /** Effective readonly state — refuses every write path without removing focus. */\n protected readonly isReadonly = computed(() => this.readonly());\n\n protected readonly classes = computed(() => {\n const parts = ['wr-select'];\n if (this.open()) parts.push('wr-select--open');\n if (this.rounded()) parts.push('wr-select--rounded');\n const size = this.size();\n if (size !== 'md') parts.push(`wr-select--${size}`);\n if (this.isMulti()) parts.push('wr-select--multi');\n if (this.isTag()) parts.push('wr-select--tag');\n if (this.isSearchTrigger()) parts.push('wr-select--search');\n if (this.hasChipSearch()) parts.push('wr-select--searchable');\n if (this.isDisabled()) parts.push('wr-select--disabled');\n else if (this.isReadonly()) parts.push('wr-select--readonly');\n return parts.join(' ');\n });\n\n /**\n * Search-mode dynamic options. Loader results win when the loader is\n * set; otherwise the static `[options]` array. Each item is rendered\n * as an internal `<wr-option>` in the panel.\n */\n protected readonly dynamicOptions = computed<readonly unknown[]>(() =>\n this.loader() ? this.loadedOptions() : this.options()\n );\n\n // --- Virtual scroll (search mode, data-array path) ------------------------\n\n private static readonly FALLBACK_ROW_PX = 34;\n private static readonly FALLBACK_VIEWPORT_PX = 256;\n\n /**\n * Consumer-projected `<wr-option>` children only (NOT the `@for`-rendered ones\n * — those live in the panel's own view, which a content query never sees).\n *\n * `descendants: true` because a projected option is as often wrapped in a\n * `<wr-option-group>` as it is a direct child, and the signal default is\n * `false`. A grouped list therefore read as NO projected options: `virtualActive`\n * engaged over the (empty) data array, so the panel rendered the group's rows\n * with a virtual window beside them that owned the keyboard — no\n * `aria-activedescendant`, no active row, and Enter committing nothing.\n */\n private readonly projectedOptions = contentChildren(WrOption, { descendants: true });\n\n /**\n * `dynamicOptions()` narrowed to the current search query. `dynamicOptions()`\n * is intentionally UNFILTERED (projected `<wr-option>` self-hide via CSS), so\n * the virtual path — which renders plain rows that can't self-hide — filters\n * here. Loader / `serverSearch` results are already query-scoped upstream.\n */\n protected readonly filteredDynamicOptions = computed<readonly unknown[]>(() => {\n const items = this.dynamicOptions();\n if (!this.clientFilter()) return items;\n const q = this.searchQuery().trim().toLowerCase();\n if (!q) return items;\n const label = this.displayWith();\n return items.filter(it => label(it).toLowerCase().includes(q));\n });\n\n /**\n * Virtualization engaged: opt-in, search mode, and NO projected `<wr-option>`\n * children — grouped ones included (those keep the full-render registry path so\n * their DOM-derived labels / selection still work).\n *\n * NOT gated on there being matches. It used to also require\n * `filteredDynamicOptions().length > 0`, which meant a query matching nothing\n * fell back to the full-render path and mounted the ENTIRE unfiltered array —\n * 2000 `<wr-option>` hosts, every one of them `--hidden`, behind a \"No\n * results\" line — and then tore all of them down again on the next keystroke\n * that matched. The empty window is handled where it belongs: `virtualWindow`\n * already short-circuits on `total === 0`, and `firstEnabled` / `lastEnabled`\n * already answer -1.\n */\n protected readonly virtualActive = computed<boolean>(\n () => this.virtualScroll() && this.isSearchable() && this.projectedOptions().length === 0\n );\n\n private readonly scrollTop = signal(0);\n private readonly viewportPx = signal(0);\n private readonly measuredRowPx = signal(0);\n\n /** Effective uniform row height (px). */\n protected readonly effRowH = computed(() =>\n this.rowHeight() > 0 ? this.rowHeight() : this.measuredRowPx() || WrSelect.FALLBACK_ROW_PX\n );\n\n private readonly fallbackViewportPx = computed(() => {\n const h = this.viewportHeight();\n if (typeof h === 'number') return h;\n return /^\\d+$/.test(h) ? Number(h) : WrSelect.FALLBACK_VIEWPORT_PX;\n });\n\n /** `viewportHeight` as a CSS length for the inline max-height (bare number → px). */\n protected readonly resolvedViewportHeight = computed(() => {\n const h = this.viewportHeight();\n return typeof h === 'number' || /^\\d+$/.test(h) ? `${h}px` : h;\n });\n\n /** Rendered window [start,end) + spacer pads (px). */\n protected readonly virtualWindow = computed<{ start: number; end: number; padTop: number; padBottom: number }>(() => {\n const total = this.filteredDynamicOptions().length;\n if (!this.virtualActive() || total === 0) return { start: 0, end: total, padTop: 0, padBottom: 0 };\n const h = this.effRowH();\n const vp = this.viewportPx() || this.fallbackViewportPx();\n const over = this.overscan();\n const first = Math.min(Math.floor(this.scrollTop() / h), total - 1);\n const count = Math.ceil(vp / h) + 1;\n const start = Math.max(0, first - over);\n const end = Math.min(total, first + count + over);\n return { start, end, padTop: start * h, padBottom: (total - end) * h };\n });\n\n /** The windowed slice of options, each carrying its absolute index. */\n protected readonly windowOptions = computed<readonly { item: unknown; index: number }[]>(() => {\n const { start, end } = this.virtualWindow();\n return this.filteredDynamicOptions()\n .slice(start, end)\n .map((item, k) => ({ item, index: start + k }));\n });\n\n /** Stable id for a virtual option row at filtered index `i`. */\n protected virtualRowId(i: number): string {\n return `${this.listboxId}-vopt-${i}`;\n }\n\n /** The virtual scroll container inside the overlay panel, if attached. */\n private get vlistElement(): HTMLElement | null {\n return this.overlayRef?.overlayElement.querySelector<HTMLElement>('.wr-select-panel__vlist') ?? null;\n }\n\n /** The scrolling listbox inside the overlay panel, if attached. */\n private get panelElement(): HTMLElement | null {\n return this.overlayRef?.overlayElement.querySelector<HTMLElement>('.wr-select-panel') ?? null;\n }\n\n /**\n * Scroll the ordered index `i` just into view. Two implementations, because the\n * two panels scroll different elements and know the row geometry in different\n * ways — the virtual list is index maths against a measured row height, the\n * projected list has to read the row it is moving to.\n *\n * The non-virtual half is not an optimisation, it is the whole keyboard\n * contract: `activeIndex` drives `aria-activedescendant`, and NOTHING else\n * moves a projected panel, because the rows never take DOM focus. Without it\n * End on a 250-option `mode=\"search\"` panel announced Zimbabwe while the panel\n * sat at `scrollTop` 0 with the cursor 9 218 px below the fold, and Enter then\n * committed a row the user could not see.\n */\n private ensureVisible(i: number): void {\n if (i < 0) return;\n if (!this.virtualActive()) {\n this.ensureRowVisible(i);\n return;\n }\n const h = this.effRowH();\n const vp = this.viewportPx() || this.fallbackViewportPx();\n const top = i * h;\n const cur = this.scrollTop();\n let next = cur;\n if (top < cur) next = top;\n else if (top + h > cur + vp) next = top + h - vp;\n if (next !== cur) {\n this.scrollTop.set(next);\n this.vlistElement?.scrollTo({ top: next });\n }\n }\n\n /**\n * Scroll the projected row at ordered index `i` just into view.\n *\n * Geometry is READ rather than computed: projected `<wr-option>` rows are\n * consumer content, so they are not a uniform height the way a virtual row is\n * — a row with a description, an icon or a wrapped label is taller than its\n * neighbours, and index maths would land the panel next to the cursor instead\n * of on it. The offset is taken relative to the panel's own scroll content\n * (`rect.top` difference plus the current `scrollTop`) rather than from\n * `offsetTop`, which is measured against whichever ancestor happens to be\n * positioned.\n *\n * `scrollTop` is written directly instead of `scrollTo`, so the write is\n * observable in a spec — jsdom implements the property and does not implement\n * the method. It still reads as a no-op there, since every jsdom rect is 0×0:\n * a spec asserting a scroll has to stub `getBoundingClientRect` and\n * `clientHeight` on the panel and the row, which `select.spec.ts` does.\n */\n private ensureRowVisible(i: number): void {\n const panel = this.panelElement;\n if (!panel) return;\n const list = this.orderedRegistry();\n if (i >= list.length) return;\n const row = panel.querySelector<HTMLElement>(`#${CSS.escape(list[i].id)}`);\n if (!row) return;\n\n const panelRect = panel.getBoundingClientRect();\n const rowRect = row.getBoundingClientRect();\n const cur = panel.scrollTop;\n const top = rowRect.top - panelRect.top + cur;\n const vp = panel.clientHeight;\n\n let next = cur;\n if (top < cur) next = top;\n else if (top + rowRect.height > cur + vp) next = top + rowRect.height - vp;\n if (next !== cur) panel.scrollTop = next;\n }\n\n /**\n * Count of registered options that pass the current search filter.\n * Hides the noResults state when the panel has at least one visible row.\n */\n protected readonly visibleCount = computed(() => {\n if (this.virtualActive()) return this.filteredDynamicOptions().length;\n const list = this.registry();\n if (!this.isSearchable() || !this.clientFilter()) return list.length;\n const q = this.searchQuery().trim().toLowerCase();\n if (!q) return list.length;\n let count = 0;\n for (const o of list) {\n if (o.label().toLowerCase().includes(q)) count++;\n }\n return count;\n });\n\n /**\n * Whether the panel may be open at all. `minChars` is documented as the\n * \"minimum query length before the panel OPENS\", and nothing gated the open —\n * so a picker with `[minChars]=\"3\"` popped a panel on focus and showed an empty\n * bordered box for the first two keystrokes (with the \"no results\" row itself\n * gated on the same threshold, there was nothing in it to explain the box).\n */\n protected readonly meetsMinChars = computed(\n () => !this.isSearchable() || this.searchQuery().trim().length >= this.minChars()\n );\n\n /** Search mode: show \"no results\" when the panel has nothing to offer. */\n protected readonly hasNoResults = computed(() => {\n if (!this.isSearchable() || !this.open() || this.isLoading()) return false;\n if (this.searchQuery().trim().length < this.minChars()) return false;\n return this.visibleCount() === 0;\n });\n\n /** Search mode: is this option hidden by the current query? @internal */\n private isOptionHidden(label: string): boolean {\n if (!this.isSearchable() || !this.clientFilter()) return false;\n const q = this.searchQuery().trim().toLowerCase();\n if (!q) return false;\n return !label.toLowerCase().includes(q);\n }\n\n protected readonly panelTpl = viewChild.required('panelTpl', { read: TemplateRef });\n\n /** The inline input inside a chip trigger — tag mode or a searchable multi. @internal */\n protected readonly tagInputEl = viewChild<ElementRef<HTMLInputElement>>('tagInput');\n\n /** Search-mode inline input. Present only when `mode=\"search\"`. @internal */\n protected readonly searchInputEl = viewChild<ElementRef<HTMLInputElement>>('searchInput');\n\n /** The button trigger — every shape without a text field of its own. @internal */\n private readonly triggerEl = viewChild<ElementRef<HTMLButtonElement>>('trigger');\n\n /** Set for the length of a `focus()` call, so the field takes focus and nothing opens. @internal */\n private quietFocus = false;\n\n /**\n * Focus the control's tab stop — what Signal Forms calls to focus this\n * control: the search field, the chip field, or the trigger button, whichever\n * the current shape draws.\n *\n * The panel stays shut. A text field opens it when the USER arrives, since\n * they are about to type; a form focusing its first invalid field is pointing\n * at it, and a listbox over the rest of the form is not what that asked for.\n */\n focus(options?: FocusOptions): void {\n const field = this.searchInputEl() ?? this.tagInputEl();\n if (!field) {\n this.triggerEl()?.nativeElement.focus(options);\n return;\n }\n this.quietFocus = true;\n try {\n field.nativeElement.focus(options);\n } finally {\n this.quietFocus = false;\n }\n }\n\n protected focusTagInput(): void {\n this.tagInputEl()?.nativeElement.focus();\n }\n\n protected focusSearchInput(): void {\n this.searchInputEl()?.nativeElement.focus();\n }\n\n // Chip-trigger input dispatch. One inline input, two owners: tag mode\n // commits a draft into chips, a searchable multi filters the panel.\n\n protected onChipsInput(event: Event): void {\n if (this.hasChipSearch()) this.onSearchInput(event);\n else this.onTagInput(event);\n }\n\n protected onChipsKeydown(event: KeyboardEvent): void {\n if (this.imeOwnsKey(event)) return;\n if (this.hasChipSearch()) this.onSearchKey(event);\n else this.onTagKeydown(event);\n }\n\n /**\n * True when the key belongs to an open IME conversion — and, when it does,\n * stops the event on its way out.\n *\n * Not acting is not enough here. The panel closes on Escape from CDK's overlay\n * keyboard dispatcher, one listener on `<body>` in the bubble phase, so a\n * handler that merely returns still loses the panel: the Japanese user meant\n * to cancel a reading and lost the query with it. Stopping the event at the\n * field that owns the composition is the only place that reaches both.\n */\n private imeOwnsKey(event: KeyboardEvent): boolean {\n if (!isComposing(event)) return false;\n event.stopPropagation();\n return true;\n }\n\n protected onChipsFocus(): void {\n // Tag mode has no panel to open.\n if (this.hasChipSearch()) this.onSearchFocus();\n }\n\n protected onChipsPaste(event: ClipboardEvent): void {\n // Splitting a paste into chips is tag-mode behaviour; a search query is\n // pasted as-is.\n if (!this.hasChipSearch()) this.onTagPaste(event);\n }\n\n protected onChipsBlur(): void {\n if (this.hasChipSearch()) this.touch.emit();\n else this.onTagBlur();\n }\n\n // Search-mode handlers\n\n protected onSearchInput(event: Event): void {\n if (this.isDisabled() || this.isReadonly()) return;\n const value = (event.target as HTMLInputElement).value;\n this.searchQuery.set(value);\n if (this.meetsMinChars()) {\n if (!this.open()) this.open.set(true);\n } else if (this.open()) {\n this.open.set(false);\n }\n // A new filter invalidates every index, so re-seed the cursor onto the first\n // option that still matches. This must happen on BOTH paths: on the\n // projected-`<wr-option>` path the registry keeps filtered-out options (they\n // only self-hide via CSS), so a stale `activeIndex` would leave the cursor on\n // a row the user can no longer see — and Enter would select it.\n this.activeIndex.set(this.firstEnabled());\n if (this.virtualActive()) {\n this.scrollTop.set(0);\n this.vlistElement?.scrollTo({ top: 0 });\n return;\n }\n // The projected panel keeps whatever `scrollTop` the previous query left it\n // at, so the re-seeded cursor lands off screen unless it is scrolled to —\n // and this is the ONE cursor move that cannot be handled synchronously.\n // Filtered-out options only self-hide via CSS, applied on the next pass, so\n // a rect read on this line measures the panel as it was BEFORE the new query\n // removed rows above the cursor. `afterNextRender`, not `queueMicrotask`:\n // under zoneless CD the scheduler refreshes the view in a macrotask, and a\n // microtask queued from this handler runs before the DOM reflects the query\n // that caused it.\n afterNextRender(() => this.ensureVisible(this.activeIndex()), { injector: this.injector });\n }\n\n protected onSearchFocus(): void {\n if (this.isDisabled()) return;\n // Focus is tracked even while read-only — the field still takes it, and\n // `searchDisplay()` keys off it — but nothing opens. The same holds for a\n // focus that `focus()` asked for, which is the form's and not the user's.\n this.searchHasFocus.set(true);\n if (this.isReadonly() || this.quietFocus) return;\n if (!this.meetsMinChars()) return;\n if (!this.open()) {\n this.seedActiveIndex();\n this.open.set(true);\n }\n }\n\n protected onSearchBlur(): void {\n this.searchHasFocus.set(false);\n // Leaving the field is what makes a below-threshold query stale, so this is\n // where the panel-close reset would have run if it could have waited.\n if (!this.open() && this.isSearchable()) this.searchQuery.set('');\n this.touch.emit();\n }\n\n protected onSearchKey(event: KeyboardEvent): void {\n // Enter accepts an IME candidate, Escape cancels the reading, the arrows walk\n // the candidate list — none of it is the listbox's while a conversion is open.\n if (this.imeOwnsKey(event)) return;\n\n // freeText: Enter on an unmatched query commits the typed string\n // as the value. Skips when an active option is highlighted (the\n // normal Enter-selects behaviour wins).\n if (event.key === 'Enter' && this.freeText() && this.open()) {\n const q = this.searchQuery().trim();\n const idx = this.activeIndex();\n const list = this.orderedRegistry();\n const hasActive = this.virtualActive()\n ? idx >= 0 && idx < this.filteredDynamicOptions().length\n : idx >= 0 && idx < list.length && !list[idx].disabled && !this.isOptionHidden(list[idx].label());\n if (!hasActive && q) {\n event.preventDefault();\n this.value.set(q);\n this.touch.emit();\n this.open.set(false);\n return;\n }\n }\n // Space belongs to the text field, not to the listbox. The button trigger\n // uses it to pick the active option, but here swallowing it would make a\n // multi-word query (\"dump trucks\") impossible to type.\n if (event.key === ' ') return;\n\n // Backspace on an empty query drops the last chip, matching tag mode. The\n // button-trigger path only does this while closed, and a chip-search input\n // keeps the panel open, so it never reaches that branch.\n if (event.key === 'Backspace' && this.hasChipSearch() && this.searchQuery() === '' && this.hasSelection()) {\n const chips = this.selectedChips();\n if (chips.length > 0) {\n event.preventDefault();\n this.removeChip(chips.length - 1, event);\n return;\n }\n }\n\n // The same key, for the searchable SINGLE: Backspace on an empty field is\n // its clear control. Every other mode could already undo a selection from\n // the keyboard — the chip modes above, the button trigger one chip per\n // Backspace — while here the × was the only way out, and it is a\n // `tabindex=\"-1\"` span no key can reach. A function offered by pointer\n // alone is a WCAG 2.1.1 failure, not a missing convenience.\n //\n // Gated on `clearable()` because that input IS the clear control: a consumer\n // who turned the × off did not ask for a keyboard twin of it. Gated on the\n // FIELD being empty rather than on `searchQuery()`, which is not the same\n // question — under `[minChars]` a collapsed field shows the selected label\n // while the query is still '', and backspacing over that text has always\n // started a query rather than thrown the selection away.\n if (\n event.key === 'Backspace' &&\n !this.hasChipSearch() &&\n this.clearable() &&\n this.hasSelection() &&\n (event.target as HTMLInputElement | null)?.value === ''\n ) {\n event.preventDefault();\n this.clearAll(event);\n return;\n }\n\n // Otherwise route through the same keyboard plumbing as the button trigger.\n this.onTriggerKey(event);\n }\n\n /**\n * Whether the search field is showing the SELECTED VALUE rather than a query.\n * `searchDisplay` takes its text off this, and `searchLeading` the visual that\n * goes before it, so the two can never disagree about which of the two things\n * the field is holding.\n *\n * FOCUS as well as open, and that second term is the whole `[minChars]` story.\n * Backspacing under the threshold closes the panel, and falling back to the\n * selected label the moment `open()` goes false rewrote the field out from\n * under someone who was still typing — \"sma\" -> \"sm\" showed an empty box.\n *\n * A NON-EMPTY query, though: picking an option clears it and leaves focus in\n * the field, and there the label is what belongs on screen.\n *\n * Only the search-shaped trigger reads it. A searchable MULTI binds its input\n * to `searchQuery()` directly and shows its selection as chips, which carry\n * their own leading visuals whatever the field holds.\n * @internal\n */\n protected readonly searchShowsValue = computed(() => {\n if (this.open()) return false;\n return !(this.searchHasFocus() && this.searchQuery() !== '');\n });\n\n /**\n * Display text for the search input. Shows the selected option's\n * label when collapsed, or the live query while typing / panel open.\n * @internal\n */\n protected readonly searchDisplay = computed(() =>\n this.searchShowsValue() ? (this.selectedLabel() ?? '') : this.searchQuery()\n );\n\n /**\n * Whether the search field holds focus.\n *\n * Read by `searchDisplay`, so it has to be a signal — and it is also what\n * lets the panel-close effect tell \"the user walked away\" (reset the query)\n * from \"the query dropped under `minChars` and they are still typing\" (keep\n * it).\n */\n private readonly searchHasFocus = signal(false);\n\n private readonly host = inject<ElementRef<HTMLElement>>(ElementRef);\n private readonly overlay = inject(WR_OVERLAY);\n private readonly outsideClick = inject(WrOutsideClick);\n private readonly vcr = inject(ViewContainerRef);\n private readonly scrollStrategies = inject(ScrollStrategyOptions);\n private readonly destroyRef = inject(DestroyRef);\n private readonly platformId = inject(PLATFORM_ID);\n private readonly injector = inject(Injector);\n /**\n * Ambient reading direction, for the open panel alone — nothing in this\n * component reads it directly. Optional so a bare `TestBed` needs no\n * provider; `Directionality` is root-provided anyway, and a missing one\n * simply reads as `ltr`.\n */\n private readonly dir = inject(Directionality, { optional: true });\n private overlayRef: OverlayRef | null = null;\n\n constructor() {\n // A component destroyed while the panel is open takes its overlay with it.\n // Without this the pane stays in the CDK container forever.\n this.destroyRef.onDestroy(() => this.closeOverlay());\n\n // Close the panel if the control goes read-only or disabled while it is up —\n // a panel whose every row now refuses the click is a trap, not a view.\n effect(() => {\n if (this.isDisabled() || this.isReadonly()) this.open.set(false);\n });\n\n effect(() => {\n if (this.open()) {\n this.openOverlay();\n } else {\n this.closeOverlay();\n // Reset the search query when the panel closes so a re-open doesn't\n // carry a stale filter — but NOT while the field still has focus.\n //\n // With `[minChars]`, backspacing under the threshold closes the panel\n // (`onSearchInput`), and `searchDisplay` falls back to the selected\n // label the moment `open()` is false — so an unconditional reset here\n // erased what the user was still typing, mid-word. A query the user is\n // actively editing is not stale.\n if (this.isSearchable() && !this.searchHasFocus()) this.searchQuery.set('');\n }\n });\n\n // One debounced query stream feeds both the async loader and the public\n // `searchChange` output, so they fire on exactly the same cadence.\n // `debounce(() => timer(...))` rather than `debounceTime(this.debounceMs())`:\n // this runs in the constructor, where inputs aren't bound yet, so reading\n // the input eagerly would pin the delay to the default and ignore\n // `[debounceMs]` forever.\n // `skip(1)` sits BEFORE the debounce so it drops the mount-time replay of the\n // empty query and nothing else. Downstream of `debounce` it would instead\n // drop the first *settled* emission — and when a fast typist's first\n // keystrokes coalesce with that initial `''`, the dropped emission is their\n // query, not the replay.\n const debouncedQuery = toObservable(this.searchQuery).pipe(\n skip(1),\n debounce(() => timer(this.debounceMs()))\n );\n\n debouncedQuery.pipe(takeUntilDestroyed(this.destroyRef)).subscribe(query => {\n if (this.isSearchable()) this.searchChange.emit(query);\n });\n\n // Async loader pipeline (searchable selects only). `switchMap` cancels\n // in-flight requests when a new keystroke arrives.\n debouncedQuery\n .pipe(\n switchMap(query => {\n const loader = this.loader();\n if (!loader || !this.isSearchable() || query.length < this.minChars()) {\n this.loaderLoading.set(false);\n return of<readonly unknown[]>([]);\n }\n this.loaderLoading.set(true);\n // `defer` so the loader CALL is part of the inner observable too. Called\n // out here, a loader that throws SYNCHRONOUSLY throws from switchMap's\n // project function, which rxjs routes straight to the destination — past\n // the `catchError` below and past `finalize`, so the flag raised on the\n // line above would stay up for good.\n const source = defer((): Observable<readonly unknown[]> => {\n const result = loader(query);\n return isObservable(result) ? result : from(Promise.resolve(result));\n });\n return source.pipe(\n // A loader can hand back a long-lived observable (a store selector,\n // say) that emits and never completes — so the first value lowers the\n // flag. `finalize` still covers completion, errors and cancellation,\n // including a loader that completes without emitting.\n tap(() => this.loaderLoading.set(false)),\n // INSIDE the projection, which is the whole point: an error allowed to\n // reach the outer subscriber closes the subscription for good, and the\n // select then never calls the loader again for the life of the\n // component — silently, since nothing here has an error callback. Kept\n // inside, one failed request costs that query and nothing else.\n // Reported as \"no results\" rather than as an error row: the panel has\n // no error state, and stale results for a query two keystrokes old\n // would read as an answer to the current one.\n catchError(() => of<readonly unknown[]>([])),\n finalize(() => this.loaderLoading.set(false))\n );\n }),\n takeUntilDestroyed(this.destroyRef)\n )\n .subscribe(items => this.loadedOptions.set(items));\n\n // Wire the virtual scroll listener + viewport/row measurement while the panel\n // is open and virtualized. Re-runs when the panel opens/closes or the virtual\n // list mounts/unmounts; the microtask defers the DOM read until the overlay\n // portal is attached. Browser-only — the panel never prerenders (overlay).\n effect(onCleanup => {\n if (!isPlatformBrowser(this.platformId)) return;\n if (!this.open() || !this.virtualActive()) return;\n let raf = 0;\n let ro: ResizeObserver | null = null;\n let el: HTMLElement | null = null;\n const onScroll = (): void => {\n if (raf) return;\n raf = requestAnimationFrame(() => {\n raf = 0;\n if (el) this.scrollTop.set(el.scrollTop);\n });\n };\n queueMicrotask(() => {\n el = this.vlistElement;\n if (!el) return;\n this.viewportPx.set(el.clientHeight);\n if (this.rowHeight() === 0) {\n const h = el.querySelector<HTMLElement>('.wr-option')?.offsetHeight ?? 0;\n if (h > 0) this.measuredRowPx.set(h);\n }\n // Re-seed the scroll with the now-measured row height + real viewport so\n // a deep pre-selected active row lands correctly on first open (the seed\n // before open used the fallback height). No-op when it's already in view.\n this.ensureVisible(this.activeIndex());\n // Sync the freshly-attached element to the retained signal — seeds the\n // scroll to the active option and avoids a blank panel on reopen.\n if (el.scrollTop !== this.scrollTop()) el.scrollTop = this.scrollTop();\n el.addEventListener('scroll', onScroll, { passive: true });\n if (typeof ResizeObserver !== 'undefined') {\n ro = new ResizeObserver(() => {\n if (el) this.viewportPx.set(el.clientHeight);\n });\n ro.observe(el);\n }\n });\n onCleanup(() => {\n if (raf) cancelAnimationFrame(raf);\n if (el) el.removeEventListener('scroll', onScroll);\n ro?.disconnect();\n });\n });\n }\n\n // WrSelectContext\n\n isSelected(value: unknown): boolean {\n if (this.isMulti()) return this.asArray(this.value()).includes(value);\n return this.value() === value;\n }\n\n selectOption(value: unknown): void {\n // The panel cannot open while read-only, but `selectOption` is reachable\n // from `WrSelectContext` — a projected `<wr-option>` calls it directly — so\n // the guard belongs on the write, not only on the way in.\n if (this.isReadonly()) return;\n if (this.isMulti()) {\n const current = this.asArray(this.value());\n const idx = current.indexOf(value);\n let next: readonly unknown[];\n if (idx >= 0) {\n next = [...current.slice(0, idx), ...current.slice(idx + 1)];\n } else {\n const cap = this.maxItems();\n if (cap > 0 && current.length >= cap) return;\n next = [...current, value];\n }\n this.value.set(next);\n this.touch.emit();\n // Keep the panel open in multi mode so the user can keep picking.\n return;\n }\n this.value.set(value);\n this.touch.emit();\n // A committed choice replaces the query, focus or no focus: the field goes\n // back to showing the selected label. The close-effect below deliberately\n // will not do it while the field is focused, which is right for a panel\n // that closed under `minChars` and wrong for one that closed on a pick.\n this.searchQuery.set('');\n this.open.set(false);\n }\n\n /**\n * Adds a `<wr-option>` to the registry and returns its unregister function.\n * Public only because `WrSelectContext` requires it: the one caller is the\n * option itself, through `WR_SELECT`, which is why `WrSelectOptionRegistration`\n * is not exported from `ngwr/select`. @internal\n */\n registerOption(reg: WrSelectOptionRegistration): () => void {\n this.registry.update(list => [...list, reg]);\n return () => this.registry.update(list => list.filter(o => o.id !== reg.id));\n }\n\n // Chip handlers (multi + tag)\n\n /**\n * Remove one selection (chip × button) BY POSITION. Works for multi and tag\n * modes.\n *\n * Positional, not by value: under `allowDuplicates` two chips carry the same\n * string, and a filter on equality deleted every copy at once — one click on\n * the second \"red\" took both reds with it. `visibleChips()` slices the HEAD\n * of `selectedChips()`, which maps the value array one for one, so the\n * `$index` a chip was rendered with indexes the value array directly. The\n * multi-mode toggle in `selectOption` was already positional.\n */\n protected removeChip(index: number, event: Event): void {\n event.stopPropagation();\n if (this.isDisabled() || this.isReadonly() || !this.hasChips()) return;\n const current = this.asArray(this.value());\n if (index < 0 || index >= current.length) return;\n this.value.set([...current.slice(0, index), ...current.slice(index + 1)]);\n this.touch.emit();\n }\n\n /** Clear every selection (× button). Multi/tag → empty array; search → null. */\n protected clearAll(event: Event): void {\n event.stopPropagation();\n if (this.isDisabled() || this.isReadonly()) return;\n if (this.hasChips()) {\n this.value.set([]);\n // `isSearchTrigger()`, not `isSearch()` — a searchable single renders the\n // same × and would otherwise fall through to the no-op below.\n } else if (this.isSearchTrigger()) {\n this.value.set(null);\n this.searchQuery.set('');\n } else {\n return;\n }\n this.touch.emit();\n }\n\n // Tag-mode draft handlers\n\n /** Capacity check used by tag mode to refuse the next add. */\n protected readonly atCapacity = computed(() => {\n const cap = this.maxItems();\n return cap > 0 && this.asArray(this.value()).length >= cap;\n });\n\n /**\n * Whether a multi select already holds `maxItems`, so an option it does not\n * hold cannot be added. The options read it to say so: they used to look and\n * announce as choosable and then ignore the click or Enter in silence.\n * @internal\n */\n readonly atMaxItems = computed(() => this.isMulti() && this.atCapacity());\n\n protected onTagInput(event: Event): void {\n if (this.isDisabled() || this.isReadonly()) return;\n this.draft.set((event.target as HTMLInputElement).value);\n }\n\n protected onTagKeydown(event: KeyboardEvent): void {\n if (this.isDisabled() || this.isReadonly()) return;\n const seps = this.separators();\n\n if (seps.includes(event.key)) {\n event.preventDefault();\n this.commitDraft();\n return;\n }\n\n if (event.key === 'Backspace' && this.draft() === '') {\n const chips = this.selectedChips();\n if (chips.length > 0) {\n event.preventDefault();\n this.removeChip(chips.length - 1, event);\n }\n }\n }\n\n protected onTagPaste(event: ClipboardEvent): void {\n if (this.isDisabled() || this.isReadonly()) return;\n const text = event.clipboardData?.getData('text') ?? '';\n if (!text) return;\n\n const seps = this.separators().filter(s => s !== 'Enter');\n if (seps.length === 0) return;\n\n event.preventDefault();\n // `-` has to be escaped too, and it is the one that bites: unescaped it\n // OPENS A RANGE inside the class. `[',', '-']` compiled to `/[,-\\n]+/` —\n // \"Range out of order\", a SyntaxError thrown after `preventDefault()`, so\n // the paste was dropped whole; `[',', '-', ';']` compiled without\n // complaint to a `,`–`;` range that swallowed every digit, shredding\n // `2024-01-02` into nothing. A lone `-` only worked because it landed\n // first in the class, where it is literal — position-dependent luck.\n const escaped = seps.map(s => s.replace(/[-.*+?^${}()|[\\]\\\\]/g, '\\\\$&')).join('');\n const splitRegex = new RegExp(`[${escaped}\\\\n]+`);\n for (const part of text.split(splitRegex)) this.tryAddTag(part);\n }\n\n protected onTagBlur(): void {\n if (this.draft().trim()) this.commitDraft();\n this.touch.emit();\n }\n\n private commitDraft(): void {\n const v = this.draft().trim();\n this.draft.set('');\n if (v) this.tryAddTag(v);\n }\n\n private tryAddTag(raw: string): void {\n if (!this.isTag() || this.atCapacity()) return;\n const value = raw.trim();\n if (!value) return;\n\n const existing = this.asArray(this.value()).map(String);\n if (!this.allowDuplicates() && existing.includes(value)) return;\n\n const validator = this.validate();\n if (validator && !validator(value, existing)) return;\n\n const next = [...existing, value];\n this.value.set(next);\n this.touch.emit();\n }\n\n // Template handlers\n\n protected onTriggerClick(): void {\n if (this.isDisabled() || this.isReadonly()) return;\n // Tag mode has no panel — clicks should land on the inline input,\n // not toggle an overlay that's never created.\n if (this.isTag()) return;\n this.open.update(v => !v);\n }\n\n protected onTriggerKey(event: KeyboardEvent): void {\n if (this.isDisabled() || this.isReadonly()) return;\n\n if (!this.open()) {\n if (event.key === 'Enter' || event.key === ' ' || event.key === 'ArrowDown' || event.key === 'ArrowUp') {\n event.preventDefault();\n this.seedActiveIndex();\n this.open.set(true);\n return;\n }\n // Multi mode: Backspace on closed trigger removes last chip. Tag\n // mode has its own input handler — never reaches this branch. A\n // searchable multi does, so only claim Backspace once its query is empty\n // — otherwise it would eat a chip and a character at once.\n if (\n event.key === 'Backspace' &&\n this.isMulti() &&\n this.hasSelection() &&\n (!this.hasChipSearch() || this.searchQuery() === '')\n ) {\n event.preventDefault();\n const chips = this.selectedChips();\n if (chips.length > 0) this.removeChip(chips.length - 1, event);\n }\n return;\n }\n\n // Open — navigation/selection.\n switch (event.key) {\n case 'Tab':\n // Let focus leave naturally — no `preventDefault` — but do not let the panel\n // outlive it. Nothing closed on Tab, so the listbox stayed on screen with a\n // live `aria-activedescendant` while the combobox no longer had focus: it can\n // cover the control that just took it (WCAG 2.4.11), and it keeps tracking a\n // trigger nobody is on, so a click aimed at what is underneath lands on an\n // option and commits into a select the user had already left. `wr-dropdown`\n // and `wr-context-menu` close on Tab for the same reason.\n //\n // Closing does NOT commit the active option. The cursor is SEEDED on open, so\n // tabbing straight through would select a row the user never looked at — and\n // in multi / search / freeText modes there is no single \"the option\" to take.\n this.open.set(false);\n break;\n case 'ArrowDown':\n event.preventDefault();\n this.moveActive(1);\n break;\n case 'ArrowUp':\n event.preventDefault();\n this.moveActive(-1);\n break;\n case 'Home':\n event.preventDefault();\n this.activeIndex.set(this.firstEnabled());\n this.ensureVisible(this.activeIndex());\n break;\n case 'End':\n event.preventDefault();\n this.activeIndex.set(this.lastEnabled());\n this.ensureVisible(this.activeIndex());\n break;\n case 'Enter':\n case ' ': {\n event.preventDefault();\n const idx = this.activeIndex();\n if (this.virtualActive()) {\n // Virtual rows aren't in the DOM to click — select the value directly.\n const list = this.filteredDynamicOptions();\n if (idx >= 0 && idx < list.length) this.selectOption(list[idx]);\n break;\n }\n const list = this.orderedRegistry();\n // Filtered-out options stay registered (they only self-hide via CSS), so\n // the hidden check is load-bearing: without it Enter can commit a row\n // that is not on screen.\n if (idx >= 0 && idx < list.length && !list[idx].disabled && !this.isOptionHidden(list[idx].label())) {\n const id = list[idx].id;\n const el = this.overlayRef?.overlayElement.querySelector<HTMLElement>(`#${CSS.escape(id)}`);\n el?.click();\n }\n break;\n }\n default:\n break;\n }\n }\n\n private seedActiveIndex(): void {\n if (this.virtualActive()) {\n const list = this.filteredDynamicOptions();\n const idx = list.findIndex(it => this.isSelected(it));\n this.activeIndex.set(idx >= 0 ? idx : this.firstEnabled());\n this.ensureVisible(this.activeIndex());\n return;\n }\n const list = this.orderedRegistry();\n let selectedIdx = -1;\n if (this.isMulti()) {\n const arr = this.asArray(this.value());\n if (arr.length > 0) selectedIdx = list.findIndex(o => o.value === arr[0]);\n } else {\n selectedIdx = list.findIndex(o => o.value === this.value());\n }\n this.activeIndex.set(selectedIdx >= 0 ? selectedIdx : this.firstEnabled());\n }\n\n private moveActive(delta: number): void {\n // Virtual rows are never disabled or hidden (the list is already filtered),\n // so navigation is a plain wrap plus a scroll-into-view.\n if (this.virtualActive()) {\n const len = this.filteredDynamicOptions().length;\n if (len === 0) return;\n const i = (this.activeIndex() + delta + len) % len;\n this.activeIndex.set(i);\n this.ensureVisible(i);\n return;\n }\n const list = this.orderedRegistry();\n if (list.length === 0) return;\n let i = this.activeIndex();\n let attempts = list.length;\n while (attempts-- > 0) {\n i = (i + delta + list.length) % list.length;\n const o = list[i];\n if (!o.disabled && !this.isOptionHidden(o.label())) {\n this.activeIndex.set(i);\n this.ensureVisible(i);\n return;\n }\n }\n }\n\n /**\n * Both scan `orderedRegistry`, and that is not interchangeable with\n * `registry`.\n *\n * They RETURN an index, and every reader of `activeIndex` — `activeOptionId`,\n * `moveActive`, `seedActiveIndex`, the Enter branch of `onTriggerKey` —\n * resolves it against DOM order. Scanning creation order here produced an\n * index into the other list: with projected `<wr-option>` children next to\n * `[options]` rows the two differ, so opening or searching left the cursor on\n * a row the user was not looking at, and Enter committed whatever happened to\n * sit at that position in DOM order — a filter-hidden option, which commits\n * nothing at all.\n */\n private firstEnabled(): number {\n if (this.virtualActive()) return this.filteredDynamicOptions().length > 0 ? 0 : -1;\n return this.orderedRegistry().findIndex(o => !o.disabled && !this.isOptionHidden(o.label()));\n }\n\n private lastEnabled(): number {\n if (this.virtualActive()) return this.filteredDynamicOptions().length - 1;\n const list = this.orderedRegistry();\n let found = -1;\n list.forEach((o, i) => {\n if (!o.disabled && !this.isOptionHidden(o.label())) found = i;\n });\n return found;\n }\n\n /** Coerce the multi-mode value into an array (tolerates a scalar or null write). */\n private asArray(value: unknown): readonly unknown[] {\n if (Array.isArray(value)) return value as readonly unknown[];\n if (value == null) return [];\n return [value];\n }\n\n // Overlay\n\n private openOverlay(): void {\n if (this.overlayRef) return;\n\n const positionStrategy = this.overlay\n .position()\n .flexibleConnectedTo(this.host)\n .withPositions([\n { originX: 'start', originY: 'bottom', overlayX: 'start', overlayY: 'top' },\n { originX: 'start', originY: 'top', overlayX: 'start', overlayY: 'bottom' },\n ])\n .withPush(true);\n\n this.overlayRef = this.overlay.create({\n positionStrategy,\n scrollStrategy: this.scrollStrategies.reposition(),\n // Floor the panel at the trigger width (it can still grow for long\n // options) instead of pinning it. The panel fills this via `width: 100%`,\n // so the flex overlay pane has no transparent gutter beside a\n // content-narrow panel — that gutter would otherwise sit \"inside\" the\n // overlay and swallow outside-clicks, leaving the panel open. Mirrors how\n // mat-select sizes its overlay.\n minWidth: this.host.nativeElement.getBoundingClientRect().width,\n panelClass: toClassList('wr-select-overlay', this.panelClass()),\n });\n\n // The CDK captured a direction STRING when this ref was created and never\n // looks again, so a flip while the list is open leaves the options\n // mirroring the wrong way.\n wrFollowDirection(this.overlayRef, this.dir, this.injector);\n\n const portal = new TemplatePortal(this.panelTpl(), this.vcr);\n this.overlayRef.attach(portal);\n\n // Seed the projected panel's scroll onto the cursor the same way the virtual\n // one is seeded from its own effect: opening a select whose selected option\n // is the 200th shows the cursor, not the top of the list. The virtual path\n // stays on its effect, which has to wait to MEASURE a row height this one\n // never needs.\n //\n // Twice, and both are needed. Synchronously, because `attachTemplatePortal`\n // appends the rows and calls `detectChanges()` before returning, and\n // `activeIndex` was seeded before `open()` flipped, so the row is in the DOM\n // and a panel of plain options lands on the cursor from the first frame.\n // Again after the next render, because that `detectChanges()` refreshes the\n // PORTAL's view and not the options: a projected `<wr-option>` belongs to the\n // consumer's view, so whatever it draws only while the panel is open — its\n // `wrOptionLeading` visual — lands a pass later and makes every row above the\n // cursor taller than it was measured. Measured with 38px avatar rows, the\n // cursor on the last of six sat 9px under the fold of a 90px panel, and the\n // error grows with each row above it. The second call is a no-op for a panel\n // whose rows did not move.\n if (!this.virtualActive()) {\n this.ensureVisible(this.activeIndex());\n afterNextRender(() => this.ensureVisible(this.activeIndex()), { injector: this.injector });\n }\n\n this.outsideClick\n .outsidePointerEvents(this.overlayRef)\n .pipe(takeUntilDestroyed(this.destroyRef))\n .subscribe(event => {\n if (this.host.nativeElement.contains(event.target as Node)) return;\n this.open.set(false);\n });\n\n this.overlayRef\n .keydownEvents()\n .pipe(takeUntilDestroyed(this.destroyRef))\n .subscribe(event => {\n if (event.key === 'Escape') {\n event.preventDefault();\n this.open.set(false);\n }\n });\n }\n\n private closeOverlay(): void {\n if (!this.overlayRef) return;\n this.overlayRef.dispose();\n this.overlayRef = null;\n }\n}\n","@if (isSearchTrigger()) {\n <!-- Search mode (or a searchable single): a real text input drives a filtered\n overlay panel. The wrapper isn't itself focusable — the input is the\n tabstop. -->\n <!-- eslint-disable-next-line @angular-eslint/template/click-events-have-key-events,@angular-eslint/template/interactive-supports-focus -->\n <div class=\"wr-select__trigger wr-select__trigger--search\" (click)=\"focusSearchInput()\">\n <!-- The selected option's leading visual, before the field — the same class\n and the same `placement: 'value'` the button trigger uses, because it is\n the same surface and a consumer who styled one should not have to learn\n a second name. `searchLeading()` draws it only while the field is\n showing the VALUE, so it never stands in front of a query or a bare\n placeholder, and it sits OUTSIDE the input for the obvious reason: an\n `<input>` holds a string. `aria-hidden` keeps it out of the combobox's\n name, which is `resolvedAriaLabel()`, and out of its value, which is the\n input's own text. -->\n @if (searchLeading(); as leading) {\n <span class=\"wr-select__value-leading\" aria-hidden=\"true\">\n <ng-container\n [ngTemplateOutlet]=\"leading\"\n [ngTemplateOutletContext]=\"{ $implicit: value(), placement: 'value' }\"\n />\n </span>\n }\n <!-- `id` / `aria-describedby` / `aria-invalid` come from a surrounding\n `<wr-form-field>` and are null without one — see `controlId` in the\n component. They go on the tab stop, the only labelable element here.\n `aria-label` is the trigger's name and belongs on the same element for\n the same reason: this input carries `role=\"combobox\"`, and the four\n other trigger shapes all bind `resolvedAriaLabel()`. Without it a\n search select with no placeholder rendered a combobox with no name at\n all — the one shape where the documented `ariaLabel` input reached\n nothing. -->\n <!-- `aria-autocomplete` is static, and `list` rather than `both`: the panel\n is the only place a suggestion appears, nothing is written back into\n the field for the user. It describes a permanent CAPABILITY, which is\n why it does not track `open()` — the same reasoning `wr-mention`\n records at its own host binding. -->\n <input\n #searchInput\n type=\"text\"\n role=\"combobox\"\n class=\"wr-select__search-input\"\n autocomplete=\"off\"\n spellcheck=\"false\"\n [attr.id]=\"controlId()\"\n [attr.aria-label]=\"nameLabel()\"\n [attr.aria-labelledby]=\"labelledBy()\"\n [attr.aria-describedby]=\"describedBy()\"\n [attr.aria-invalid]=\"ariaInvalid()\"\n [disabled]=\"isDisabled()\"\n [attr.aria-haspopup]=\"'listbox'\"\n aria-autocomplete=\"list\"\n [attr.aria-expanded]=\"open()\"\n [attr.aria-controls]=\"listboxId\"\n [attr.aria-activedescendant]=\"open() ? activeOptionId() || null : null\"\n [attr.aria-readonly]=\"isReadonly() || null\"\n [readonly]=\"isReadonly()\"\n [placeholder]=\"resolvedPlaceholder()\"\n [value]=\"searchDisplay()\"\n (input)=\"onSearchInput($event)\"\n (focus)=\"onSearchFocus()\"\n (keydown)=\"onSearchKey($event)\"\n (blur)=\"onSearchBlur()\"\n />\n <!-- Pointer-only, and the `keydown.enter` / `keydown.space` pair this used to\n carry was dead code rather than the keyboard path it looked like: the ×\n is `tabindex=\"-1\"` with no roving owner, so no key event ever originates\n here to bubble into a handler. It stays unfocusable because the same\n span sits inside the BUTTON trigger further down, where a focusable\n child is `nested-interactive` — the defect the window taskbar's close\n button already taught this repo. The keyboard reaches the function\n instead: Backspace on the empty field, which `onSearchKey` routes to\n `clearAll` for a single and to the last chip for a multi. -->\n @if (clearable() && hasSelection() && !isDisabled() && !isReadonly()) {\n <span\n class=\"wr-select__clear\"\n role=\"button\"\n [attr.aria-label]=\"resolvedClear()\"\n tabindex=\"-1\"\n (click)=\"clearAll($event)\"\n >\n <svg\n class=\"wr-icon__svg\"\n xmlns=\"http://www.w3.org/2000/svg\"\n viewBox=\"0 0 24 24\"\n fill=\"none\"\n stroke=\"currentColor\"\n stroke-width=\"2\"\n stroke-linecap=\"round\"\n stroke-linejoin=\"round\"\n aria-hidden=\"true\"\n >\n <path d=\"M18 6 6 18\" />\n <path d=\"m6 6 12 12\" />\n </svg>\n </span>\n }\n <svg\n class=\"wr-icon__svg wr-select__chevron\"\n xmlns=\"http://www.w3.org/2000/svg\"\n viewBox=\"0 0 24 24\"\n fill=\"none\"\n stroke=\"currentColor\"\n stroke-width=\"2\"\n stroke-linecap=\"round\"\n stroke-linejoin=\"round\"\n aria-hidden=\"true\"\n >\n <path d=\"m6 9 6 6 6-6\" />\n </svg>\n </div>\n} @else if (isTag() || hasChipSearch()) {\n <!-- Chip trigger — tag mode, or a searchable multi. A focusable input lives\n inside, so the wrapper itself only exists to host chips and forward\n whitespace clicks to the input. Tag mode needs no role (users tab\n straight into the input); the searchable multi is a real combobox, so it\n carries the listbox wiring. The click handler is a mouse-only\n convenience. -->\n <!-- eslint-disable-next-line @angular-eslint/template/click-events-have-key-events,@angular-eslint/template/interactive-supports-focus -->\n <div\n class=\"wr-select__trigger wr-select__trigger--tag\"\n [attr.aria-disabled]=\"isDisabled() || null\"\n (click)=\"focusTagInput()\"\n >\n <span class=\"wr-select__chips\">\n @for (chip of visibleChips(); track $index) {\n <span class=\"wr-select__chip\">\n @if (chip.leading; as leading) {\n <span class=\"wr-select__chip-leading\" aria-hidden=\"true\">\n <ng-container\n [ngTemplateOutlet]=\"leading\"\n [ngTemplateOutletContext]=\"{ $implicit: chip.value, placement: 'chip' }\"\n />\n </span>\n }\n <span class=\"wr-select__chip-label\">{{ chip.label }}</span>\n @if (!isReadonly()) {\n <span\n class=\"wr-select__chip-remove\"\n role=\"button\"\n [attr.aria-label]=\"chipRemoveLabel({ label: chip.label })\"\n tabindex=\"-1\"\n (click)=\"removeChip($index, $event)\"\n >\n <svg\n class=\"wr-icon__svg\"\n xmlns=\"http://www.w3.org/2000/svg\"\n viewBox=\"0 0 24 24\"\n fill=\"none\"\n stroke=\"currentColor\"\n stroke-width=\"2\"\n stroke-linecap=\"round\"\n stroke-linejoin=\"round\"\n aria-hidden=\"true\"\n >\n <path d=\"M18 6 6 18\" />\n <path d=\"m6 6 12 12\" />\n </svg>\n </span>\n }\n </span>\n }\n @if (hiddenChipCount(); as extra) {\n <span class=\"wr-select__chip wr-select__chip--more\">{{ moreLabel({ count: extra }) }}</span>\n }\n <!-- At `maxItems` this input goes READONLY, never disabled: it is the only\n tab stop in the whole control (the chip × and the clear button are\n `tabindex=\"-1\"` spans), so disabling it left a full tag select with\n nothing focusable at all — and Backspace on an empty draft, the one\n keyboard way back UNDER the cap, is bound to this very element. It was\n never needed as enforcement either: `tryAddTag` already refuses past\n capacity. -->\n <!-- `aria-autocomplete` is conditional here, unlike the search input's:\n this field is only a combobox when a panel backs it. In plain tag\n mode there is no popup to suggest from, and claiming otherwise\n describes a control that does not exist. -->\n <input\n #tagInput\n type=\"text\"\n class=\"wr-select__tag-input\"\n autocomplete=\"off\"\n [attr.id]=\"controlId()\"\n [attr.aria-label]=\"nameLabel()\"\n [attr.aria-labelledby]=\"labelledBy()\"\n [attr.aria-describedby]=\"describedBy()\"\n [attr.aria-invalid]=\"ariaInvalid()\"\n spellcheck=\"false\"\n [value]=\"hasChipSearch() ? searchQuery() : draft()\"\n [disabled]=\"isDisabled()\"\n [readonly]=\"isReadonly() || (isTag() && atCapacity())\"\n [attr.aria-readonly]=\"hasChipSearch() && isReadonly() ? true : null\"\n [placeholder]=\"hasSelection() ? '' : resolvedPlaceholder()\"\n [attr.role]=\"hasChipSearch() ? 'combobox' : null\"\n [attr.aria-haspopup]=\"hasChipSearch() ? 'listbox' : null\"\n [attr.aria-autocomplete]=\"hasChipSearch() ? 'list' : null\"\n [attr.aria-expanded]=\"hasChipSearch() ? open() : null\"\n [attr.aria-controls]=\"hasChipSearch() ? listboxId : null\"\n [attr.aria-activedescendant]=\"hasChipSearch() && open() ? activeOptionId() || null : null\"\n (input)=\"onChipsInput($event)\"\n (keydown)=\"onChipsKeydown($event)\"\n (paste)=\"onChipsPaste($event)\"\n (focus)=\"onChipsFocus()\"\n (blur)=\"onChipsBlur()\"\n />\n </span>\n\n @if (clearable() && hasSelection() && !isDisabled() && !isReadonly()) {\n <span\n class=\"wr-select__clear\"\n role=\"button\"\n [attr.aria-label]=\"resolvedClear()\"\n tabindex=\"-1\"\n (click)=\"clearAll($event)\"\n >\n <svg\n class=\"wr-icon__svg\"\n xmlns=\"http://www.w3.org/2000/svg\"\n viewBox=\"0 0 24 24\"\n fill=\"none\"\n stroke=\"currentColor\"\n stroke-width=\"2\"\n stroke-linecap=\"round\"\n stroke-linejoin=\"round\"\n aria-hidden=\"true\"\n >\n <path d=\"M18 6 6 18\" />\n <path d=\"m6 6 12 12\" />\n </svg>\n </span>\n }\n\n <!-- Only for the searchable MULTI, never for tag mode. The two share this\n trigger and differ in the one thing a chevron stands for: the searchable\n multi's input is a `role=\"combobox\"` with `aria-haspopup=\"listbox\"` and\n a panel of options behind it, while tag mode takes free text and has no\n popup at all. Folding the second into this branch left it as the only\n combobox shape in the component with no affordance saying it opens —\n `mode=\"search\"` has one, a searchable single has one, the button trigger\n has one, and this one rendered a bare field. -->\n @if (hasChipSearch()) {\n <svg\n class=\"wr-icon__svg wr-select__chevron\"\n xmlns=\"http://www.w3.org/2000/svg\"\n viewBox=\"0 0 24 24\"\n fill=\"none\"\n stroke=\"currentColor\"\n stroke-width=\"2\"\n stroke-linecap=\"round\"\n stroke-linejoin=\"round\"\n aria-hidden=\"true\"\n >\n <path d=\"m6 9 6 6 6-6\" />\n </svg>\n }\n </div>\n} @else {\n <button\n #trigger\n type=\"button\"\n class=\"wr-select__trigger\"\n role=\"combobox\"\n [attr.id]=\"controlId()\"\n [attr.aria-label]=\"nameLabel()\"\n [attr.aria-labelledby]=\"labelledBy()\"\n [attr.aria-describedby]=\"describedBy()\"\n [attr.aria-invalid]=\"ariaInvalid()\"\n [disabled]=\"isDisabled()\"\n [attr.aria-haspopup]=\"'listbox'\"\n [attr.aria-expanded]=\"open()\"\n [attr.aria-controls]=\"listboxId\"\n [attr.aria-activedescendant]=\"open() ? activeOptionId() || null : null\"\n [attr.aria-readonly]=\"isReadonly() || null\"\n (click)=\"onTriggerClick()\"\n (keydown)=\"onTriggerKey($event)\"\n (blur)=\"touch.emit()\"\n >\n @if (isMulti()) {\n @if (hasSelection()) {\n <span class=\"wr-select__chips\">\n @for (chip of visibleChips(); track $index) {\n <span class=\"wr-select__chip\">\n <!-- A selected chip draws its option's leading visual — one copy per\n VISIBLE chip, so `maxTagCount` caps these too. -->\n @if (chip.leading; as leading) {\n <span class=\"wr-select__chip-leading\" aria-hidden=\"true\">\n <ng-container\n [ngTemplateOutlet]=\"leading\"\n [ngTemplateOutletContext]=\"{ $implicit: chip.value, placement: 'chip' }\"\n />\n </span>\n }\n <span class=\"wr-select__chip-label\">{{ chip.label }}</span>\n @if (!isReadonly()) {\n <span\n class=\"wr-select__chip-remove\"\n role=\"button\"\n [attr.aria-label]=\"chipRemoveLabel({ label: chip.label })\"\n tabindex=\"-1\"\n (click)=\"removeChip($index, $event)\"\n >\n <svg\n class=\"wr-icon__svg\"\n xmlns=\"http://www.w3.org/2000/svg\"\n viewBox=\"0 0 24 24\"\n fill=\"none\"\n stroke=\"currentColor\"\n stroke-width=\"2\"\n stroke-linecap=\"round\"\n stroke-linejoin=\"round\"\n aria-hidden=\"true\"\n >\n <path d=\"M18 6 6 18\" />\n <path d=\"m6 6 12 12\" />\n </svg>\n </span>\n }\n </span>\n }\n @if (hiddenChipCount(); as extra) {\n <span class=\"wr-select__chip wr-select__chip--more\">{{ moreLabel({ count: extra }) }}</span>\n }\n </span>\n } @else {\n <span class=\"wr-select__placeholder\">{{ resolvedPlaceholder() }}</span>\n }\n } @else {\n @if (selectedLabel(); as label) {\n <!-- Beside the label, not inside it: the harness and the accessible name\n both read `.wr-select__value`, and the visual says nothing either should. -->\n @if (selectedLeading(); as leading) {\n <span class=\"wr-select__value-leading\" aria-hidden=\"true\">\n <ng-container\n [ngTemplateOutlet]=\"leading\"\n [ngTemplateOutletContext]=\"{ $implicit: value(), placement: 'value' }\"\n />\n </span>\n }\n <span class=\"wr-select__value\">{{ label }}</span>\n } @else {\n <span class=\"wr-select__placeholder\">{{ resolvedPlaceholder() }}</span>\n }\n }\n\n @if (isMulti() && clearable() && hasSelection() && !isDisabled() && !isReadonly()) {\n <span\n class=\"wr-select__clear\"\n role=\"button\"\n [attr.aria-label]=\"resolvedClear()\"\n tabindex=\"-1\"\n (click)=\"clearAll($event)\"\n >\n <svg\n class=\"wr-icon__svg\"\n xmlns=\"http://www.w3.org/2000/svg\"\n viewBox=\"0 0 24 24\"\n fill=\"none\"\n stroke=\"currentColor\"\n stroke-width=\"2\"\n stroke-linecap=\"round\"\n stroke-linejoin=\"round\"\n aria-hidden=\"true\"\n >\n <path d=\"M18 6 6 18\" />\n <path d=\"m6 6 12 12\" />\n </svg>\n </span>\n }\n\n <svg\n class=\"wr-icon__svg wr-select__chevron\"\n xmlns=\"http://www.w3.org/2000/svg\"\n viewBox=\"0 0 24 24\"\n fill=\"none\"\n stroke=\"currentColor\"\n stroke-width=\"2\"\n stroke-linecap=\"round\"\n stroke-linejoin=\"round\"\n aria-hidden=\"true\"\n >\n <path d=\"m6 9 6 6 6-6\" />\n </svg>\n </button>\n}\n\n<ng-template #panelTpl>\n <div\n class=\"wr-select-panel\"\n [class.wr-select-panel--sm]=\"size() === 'sm'\"\n [class.wr-select-panel--lg]=\"size() === 'lg'\"\n [class.wr-select-panel--virtual]=\"virtualActive()\"\n role=\"listbox\"\n [attr.id]=\"listboxId\"\n [attr.aria-multiselectable]=\"isMulti() ? 'true' : null\"\n [attr.aria-busy]=\"isLoading() ? 'true' : null\"\n >\n <!-- `aria-busy` belongs on the listbox, not on this row: it is the container\n whose required `option` children are temporarily missing, and a global\n ARIA attribute on a role-less child makes that child an owned element the\n listbox may not own (axe `aria-required-children`, critical). Plain text\n inside the listbox is fine — only ELEMENTS are checked. -->\n @if (isLoading()) {\n <div class=\"wr-select-panel__loading\">{{ resolvedLoading() }}</div>\n }\n\n @if (virtualActive()) {\n <!-- Windowed data-array rows: plain role=\"option\" elements (not <wr-option>),\n navigated via the input's aria-activedescendant, selected by value. -->\n <div class=\"wr-select-panel__vlist\" [style.max-height]=\"resolvedViewportHeight()\">\n @if (virtualWindow().padTop > 0) {\n <div class=\"wr-select-panel__vspacer\" aria-hidden=\"true\" [style.height.px]=\"virtualWindow().padTop\"></div>\n }\n @for (entry of windowOptions(); track entry.index) {\n <!-- Keyboard handled by the search input via aria-activedescendant; the\n row is a pointer target only. -->\n <!-- eslint-disable-next-line @angular-eslint/template/click-events-have-key-events,@angular-eslint/template/interactive-supports-focus -->\n <div\n role=\"option\"\n class=\"wr-option\"\n [id]=\"virtualRowId(entry.index)\"\n [class.wr-option--active]=\"entry.index === activeIndex()\"\n [class.wr-option--selected]=\"isSelected(entry.item)\"\n [class.wr-option--disabled]=\"atMaxItems() && !isSelected(entry.item)\"\n [attr.aria-selected]=\"isSelected(entry.item)\"\n [attr.aria-disabled]=\"atMaxItems() && !isSelected(entry.item) ? true : null\"\n [attr.aria-setsize]=\"filteredDynamicOptions().length\"\n [attr.aria-posinset]=\"entry.index + 1\"\n (click)=\"selectOption(entry.item)\"\n >\n <!-- Only the select-wide template reaches a virtual row — there is no\n `<wr-option>` here to declare one — and only rows inside the\n rendered window instantiate it. -->\n @if (optionLeading(); as leading) {\n <span class=\"wr-option__leading\" aria-hidden=\"true\">\n <ng-container\n [ngTemplateOutlet]=\"leading\"\n [ngTemplateOutletContext]=\"{ $implicit: entry.item, placement: 'option' }\"\n />\n </span>\n }\n {{ displayWith()(entry.item) }}\n </div>\n }\n @if (virtualWindow().padBottom > 0) {\n <div class=\"wr-select-panel__vspacer\" aria-hidden=\"true\" [style.height.px]=\"virtualWindow().padBottom\"></div>\n }\n </div>\n } @else {\n <!-- Dynamic options from [options] or async [loader] (search mode).\n Rendered as wr-option so the standard registration / filter\n pipeline applies uniformly. -->\n @for (item of dynamicOptions(); track $index) {\n <wr-option [value]=\"item\">{{ displayWith()(item) }}</wr-option>\n }\n }\n\n <!-- Projected static options — always present (a conditional `<ng-content>`\n would drop projected content). Empty whenever `virtualActive`. -->\n <ng-content />\n\n <!-- A listbox may only own `option` and `group` children, and as a bare `<div>`\n this row was the only thing in the tree when it showed — an\n `aria-required-children` critical. It cannot move out of the listbox the\n way the command palette's does: this element IS the listbox, and the id\n the trigger's `aria-controls` names is what gives it its accessible name.\n So it announces as a disabled option instead. Keyboard navigation skips\n it for free — arrow keys walk the registered `wr-option`s, and nothing\n registers this row. -->\n @if (hasNoResults()) {\n <div class=\"wr-select-panel__empty\" role=\"option\" aria-selected=\"false\" aria-disabled=\"true\">\n {{ resolvedNoResults() }}\n </div>\n }\n </div>\n</ng-template>\n","/**\n * @license\n *\n * Use of this source code is governed by an MIT-style license that can be\n * found in the LICENSE file at https://github.com/thekhegay/ngwr/blob/main/LICENSE\n */\n\nimport { Component, ViewEncapsulation, input } from '@angular/core';\n\nimport { randomId } from 'ngwr/utils';\n\n/**\n * Visually groups options under a label inside a `<wr-select>`.\n *\n * @example\n * ```html\n * <wr-option-group label=\"Sizes\">\n * <wr-option value=\"sm\">Small</wr-option>\n * <wr-option value=\"md\">Medium</wr-option>\n * </wr-option-group>\n * ```\n */\n@Component({\n selector: 'wr-option-group',\n templateUrl: './option-group.html',\n encapsulation: ViewEncapsulation.None,\n host: { class: 'wr-option-group', role: 'group', '[attr.aria-labelledby]': 'labelId' },\n})\nexport class WrOptionGroup {\n /** Section heading shown above the options. */\n readonly label = input.required<string>();\n\n /**\n * `role=\"group\"` alone announces an unnamed group — the visible heading has to\n * be wired to it for the name to reach a screen reader.\n */\n protected readonly labelId = randomId('wr-option-group-label');\n}\n","<div class=\"wr-option-group__label\" [id]=\"labelId\">{{ label() }}</div>\n<ng-content />\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"ngwr-select.mjs","names":[],"sources":["../../../projects/lib/select/load-error.ts","../../../projects/lib/select/option-leading.ts","../../../projects/lib/select/tokens/select.token.ts","../../../projects/lib/select/option.ts","../../../projects/lib/select/option.html","../../../projects/lib/select/select.ts","../../../projects/lib/select/select.html","../../../projects/lib/select/option-group.ts","../../../projects/lib/select/option-group.html"],"sourcesContent":["/**\n * @license\n *\n * Use of this source code is governed by an MIT-style license that can be\n * found in the LICENSE file at https://github.com/thekhegay/ngwr/blob/main/LICENSE\n */\n\nimport { Directive, TemplateRef, inject } from '@angular/core';\n\nimport type { SafeAny } from 'ngwr/utils';\n\nimport type { WrSelectLoadErrorContext } from './types';\n\n/**\n * Replaces what a failed `[loader]` shows in the panel: the message, the retry\n * button, a loader while the retry runs, any text of the app's own. Declare it as\n * a DIRECT child of `<wr-select>`. The context carries the error, the query that\n * failed, `canRetry`, `retry()` and `retrying`.\n *\n * **It draws inside the error row, and that row is an option of the listbox**,\n * since the panel element is the listbox and may own nothing else. So the\n * template holds nothing focusable: a `<button>` inside an option is nested\n * interactive content. Draw a retry the way the default does, a `<span>` with\n * the `.wr-btn` classes and `(click)=\"retry()\"`, inside `@if (canRetry)`. The\n * select's `retryable` decides `canRetry`, and lets Enter in the field reach it.\n *\n * @example\n * ```html\n * <wr-select mode=\"search\" retryable [loader]=\"search\">\n * <ng-template wrSelectLoadError let-error let-canRetry=\"canRetry\" let-retry=\"retry\" let-retrying=\"retrying\">\n * <p>Search is offline: {{ error.message }}</p>\n * @if (canRetry) {\n * <span class=\"wr-btn wr-btn--sm\" (click)=\"retry()\">{{ retrying ? 'Retrying…' : 'Retry' }}</span>\n * }\n * </ng-template>\n * </wr-select>\n * ```\n */\n@Directive({\n selector: 'ng-template[wrSelectLoadError]',\n})\nexport class WrSelectLoadError<E = SafeAny> {\n readonly template = inject<TemplateRef<WrSelectLoadErrorContext<E>>>(TemplateRef);\n\n /**\n * Types the template's `let-` variables under `strictTemplates`. `E` defaults\n * to `SafeAny` for the reason `WrOptionLeading` gives: nothing infers the error\n * type, and narrowed to `unknown`, `error.message` would not compile.\n */\n // eslint-disable-next-line @typescript-eslint/no-unused-vars -- a guard's parameters exist to be narrowed, never read\n static ngTemplateContextGuard<E>(_dir: WrSelectLoadError<E>, _ctx: unknown): _ctx is WrSelectLoadErrorContext<E> {\n return true;\n }\n}\n","/**\n * @license\n *\n * Use of this source code is governed by an MIT-style license that can be\n * found in the LICENSE file at https://github.com/thekhegay/ngwr/blob/main/LICENSE\n */\n\nimport { Directive, TemplateRef, inject } from '@angular/core';\n\nimport type { SafeAny } from 'ngwr/utils';\n\nimport type { WrOptionLeadingContext } from './types';\n\n/**\n * A leading visual — an avatar, an icon, a colour dot — drawn before an\n * option's label, and kept out of that label.\n *\n * It is a TEMPLATE, and that is the point. Projected `<wr-option>` children are\n * created as soon as the page renders, panel open or not, so an avatar written\n * straight into each option is 200 components and 200 image requests for an\n * assignee picker nobody has opened. A template is only instantiated where it is\n * drawn:\n *\n * - in an option row, while the panel is OPEN — destroyed again when it closes,\n * and under `virtualScroll` only for the rows in the rendered window;\n * - in a selected chip on a `mode=\"multi\"` trigger, one per visible chip;\n * - beside the selected value on a single-mode BUTTON trigger — one copy;\n * - before the input on a SEARCH-shaped trigger (`mode=\"search\"`, a searchable\n * single), while that input is showing the selected label. It goes beside the\n * field rather than into it — an `<input>` holds a string — and it steps aside\n * while a query is on screen, panel open or half-typed, because the value it\n * names is not what the field is showing then. Picking an option brings it\n * back with the label. Stepping aside is a DESTROY, like a closing panel's\n * rows, so an `<img>`-backed visual re-mounts once per open-and-dismiss.\n *\n * Every copy sits in an `aria-hidden` wrapper and is skipped when the option's\n * text is read, so the trigger label, the chip, the search filter and the\n * option's accessible name all stay the option's words — never \"ХР Хегай Роман\".\n * Anything the visual says has to be said by the label as well.\n *\n * Two places to declare it. Inside a `<wr-option>` it belongs to that option.\n * As a DIRECT child of `<wr-select>` it is the default for every row, which is the\n * only way to reach rows the select draws itself — `[options]`, `[loader]`\n * results and virtual rows. An option's own template wins over the select's.\n *\n * @example\n * ```html\n * <wr-select mode=\"multi\" placeholder=\"Assignees\" [(value)]=\"assignees\">\n * @for (p of people; track p.id) {\n * <wr-option [value]=\"p.id\">\n * <ng-template wrOptionLeading let-placement=\"placement\">\n * <wr-avatar shape=\"circle\" [size]=\"placement === 'chip' ? 16 : 24\" [url]=\"p.photo\">{{ p.initials }}</wr-avatar>\n * </ng-template>\n * {{ p.name }}\n * </wr-option>\n * }\n * </wr-select>\n * ```\n */\n@Directive({\n selector: 'ng-template[wrOptionLeading]',\n})\nexport class WrOptionLeading<T = SafeAny> {\n readonly template = inject<TemplateRef<WrOptionLeadingContext<T>>>(TemplateRef);\n\n /**\n * Types the template's `let-` variables under `strictTemplates`. Without it\n * `let-placement` is `any`, and indexing a `Record<WrOptionLeadingPlacement, …>`\n * with it — the obvious way to size one visual per surface — does not compile.\n *\n * **`T` defaults to `SafeAny`, and that is the whole reason this is generic.**\n * The guard used to narrow to a bare `WrOptionLeadingContext`, which is\n * `WrOptionLeadingContext<unknown>` — so `let-value` came out `unknown` and\n * every use of it was a compile error under `strictTemplates`, which made the\n * guard WORSE than no guard at all: without one the variable is `any` and\n * `personName(id)` compiles. The value cannot be inferred — a structural\n * directive with no input has nothing to infer from, and the template is\n * declared on the select rather than on the option it draws — so the honest\n * type at this boundary is the unchecked one. `placement`, which is what the\n * guard exists for, stays narrowed either way.\n *\n * It bit the one documented shape that NEEDS the value: a template written as\n * a direct child of `<wr-select>` over `[options]`, where no outer `@for`\n * variable is in scope. This library's own docs page carries three helpers\n * typed `(id: unknown)` to get around it, with nothing saying why.\n */\n // eslint-disable-next-line @typescript-eslint/no-unused-vars -- a guard's parameters exist to be narrowed, never read\n static ngTemplateContextGuard<T>(_dir: WrOptionLeading<T>, _ctx: unknown): _ctx is WrOptionLeadingContext<T> {\n return true;\n }\n}\n","/**\n * @license\n *\n * Use of this source code is governed by an MIT-style license that can be\n * found in the LICENSE file at https://github.com/thekhegay/ngwr/blob/main/LICENSE\n */\n\nimport { InjectionToken } from '@angular/core';\n\nimport type { WrSelectContext } from '../types';\n\n/**\n * Token a `<wr-option>` injects to register itself with and notify its\n * parent `<wr-select>`.\n *\n * @internal\n */\nexport const WR_SELECT = new InjectionToken<WrSelectContext>('WR_SELECT');\n","/**\n * @license\n *\n * Use of this source code is governed by an MIT-style license that can be\n * found in the LICENSE file at https://github.com/thekhegay/ngwr/blob/main/LICENSE\n */\n\nimport { coerceBooleanProperty } from '@angular/cdk/coercion';\nimport { NgTemplateOutlet } from '@angular/common';\nimport {\n Component,\n ElementRef,\n type Signal,\n type TemplateRef,\n ViewEncapsulation,\n afterEveryRender,\n computed,\n contentChild,\n effect,\n inject,\n input,\n signal,\n untracked,\n viewChild,\n} from '@angular/core';\n\nimport { WrOptionLeading } from './option-leading';\nimport { WR_SELECT } from './tokens';\nimport type { WrOptionLeadingContext } from './types';\n\nlet uid = 0;\n\n/** `Node.TEXT_NODE` / `Node.ELEMENT_NODE`, spelled out: `Node` is not a global on the server. */\nconst TEXT_NODE = 3;\nconst ELEMENT_NODE = 1;\n\n/**\n * Single option inside a `<wr-select>`.\n *\n * The option's display label is taken from its projected text content — or\n * from `label`, when that is set — and the form value is its `value` input. A\n * leading visual goes in an `<ng-template wrOptionLeading>`, which keeps it out\n * of the label and uninstantiated while the panel is closed.\n *\n * @example\n * ```html\n * <wr-option value=\"sm\">Small</wr-option>\n * <wr-option [value]=\"42\">Forty-two</wr-option>\n * <wr-option [value]=\"p.id\" [label]=\"p.name\">\n * <ng-template wrOptionLeading><wr-avatar shape=\"circle\" size=\"1.5rem\">{{ p.initials }}</wr-avatar></ng-template>\n * {{ p.name }}\n * </wr-option>\n * ```\n */\n@Component({\n selector: 'wr-option',\n templateUrl: './option.html',\n encapsulation: ViewEncapsulation.None,\n imports: [NgTemplateOutlet],\n host: {\n role: 'option',\n '[attr.id]': 'id',\n '[class]': 'classes()',\n '[attr.aria-selected]': 'selected()',\n '[attr.aria-disabled]': 'unavailable() ? true : null',\n '(click)': 'onClick()',\n },\n})\nexport class WrOption {\n /** The value contributed when this option is chosen. Required. */\n readonly value = input.required<unknown>();\n\n /** Disable this option. @default false */\n readonly disabled = input(false, { transform: coerceBooleanProperty });\n\n /**\n * The text the select reports for this option — the trigger label, the chip,\n * the chip's remove label and the search filter all read it. Unset (or empty),\n * the option's own text is used, as it always was.\n *\n * Set it when the row shows more than the name: a projected email under a\n * person, a count beside a category. It does NOT rename the row itself — the\n * option's accessible name stays the text it draws, since a screen reader user\n * browsing the list should hear what a sighted one reads there.\n *\n * @default null\n */\n readonly label = input<string | null>(null);\n\n /** Stable id used for `aria-activedescendant`. */\n readonly id = `wr-option-${++uid}`;\n\n private readonly host = inject<ElementRef<HTMLElement>>(ElementRef);\n private readonly parent = inject(WR_SELECT, { optional: true });\n\n /** This option's own `<ng-template wrOptionLeading>`, if it declares one. */\n private readonly ownLeading = contentChild(WrOptionLeading);\n\n /**\n * The leading template that applies to this option: its own, else the\n * select-wide default. Registered with the parent so a chip can draw it.\n */\n private readonly leading: Signal<TemplateRef<WrOptionLeadingContext> | null> = computed(\n () => this.ownLeading()?.template ?? this.parent?.optionLeading() ?? null\n );\n\n /**\n * The leading template to draw in THIS row right now — `null` while the panel\n * is closed. A projected option is created with the page and lives, detached,\n * for as long as the select does, so gating on the template alone would\n * instantiate every row's avatar the moment the page renders. An option with\n * no parent select has no panel to wait for.\n */\n protected readonly rowLeading = computed(() => {\n if (this.parent && !this.parent.panelOpen()) return null;\n return this.leading();\n });\n\n /** The wrapper the leading visual renders into — skipped when reading the text. */\n private readonly leadingSlot = viewChild<ElementRef<HTMLElement>>('leadingSlot');\n\n /**\n * The option's own text, as a signal — the parent's trigger label and the\n * client-side filter both read it from here.\n *\n * It has to be a signal, and a plain `textContent` read cannot be one. The\n * label is PROJECTED content: the host template decides it, and the ordinary\n * way it changes is that a `WrI18n` catalog lands a microtask after the first\n * change-detection pass (`i18n/i18n.ts` writes every loader-backed catalog\n * from `firstValueFrom(...).then(...)`). Read once and cached, a trigger sat\n * on the English fallback while the open panel beside it showed the\n * translation — visible in `wr-pagination`'s size changer, which prints\n * `pagination.perPage` into each `<wr-option>`.\n *\n * Kept in step the way `wr-divider` keeps its own projected label: an\n * `effect` and an `afterEveryRender`, and both are needed. The render hook is\n * a hard no-op under SSR, so on its own the server would emit a trigger with\n * no label at all; the effect is not gated that way and runs after the\n * content has been projected. The effect on its own cannot follow text that\n * moves later, because it reads nothing reactive to be re-run by.\n *\n * @internal\n */\n private readonly labelText = signal('');\n\n /**\n * `label` when set, otherwise the option's own text. What the parent reads.\n * Not `??`: an EMPTY label falls back too, since a blank trigger or a nameless\n * chip is never what a `[label]=\"person.name\"` on a missing name meant.\n */\n private readonly resolvedLabel: Signal<string> = computed(() => {\n const explicit = this.label();\n return explicit !== null && explicit !== '' ? explicit : this.labelText();\n });\n\n /**\n * @internal — true when this option is currently selected. Works for\n * both single and multi-select parents via `WrSelectContext.isSelected`.\n */\n protected readonly selected = computed(() => {\n const parent = this.parent;\n if (!parent) return false;\n // Re-read parent's value signal so the computed recomputes on change.\n parent.value();\n return parent.isSelected(this.value());\n });\n\n /**\n * @internal — disabled, or not chosen in a multi select that already holds\n * `maxItems`: either way a pick is refused, so the row says so rather than\n * looking choosable.\n */\n protected readonly unavailable = computed(() => this.disabled() || (!this.selected() && !!this.parent?.atMaxItems()));\n\n /** @internal — true when this option is the keyboard cursor target. */\n protected readonly active = computed(() => this.parent?.activeOptionId() === this.id);\n\n /**\n * @internal — searchable selects only. True when the parent has a query that\n * the option's label does not match (case-insensitive substring) — `label`\n * when set, the option's text otherwise, and never its leading visual.\n * Hidden options stay in the DOM so registration order survives but\n * collapse via CSS.\n */\n protected readonly hidden = computed(() => {\n const parent = this.parent;\n if (!parent?.isSearchable() || !parent.clientFilter()) return false;\n const q = parent.searchQuery().trim().toLowerCase();\n if (!q) return false;\n return !this.resolvedLabel().toLowerCase().includes(q);\n });\n\n protected readonly classes = computed(() => {\n const parts = ['wr-option'];\n if (this.selected()) parts.push('wr-option--selected');\n if (this.active()) parts.push('wr-option--active');\n if (this.unavailable()) parts.push('wr-option--disabled');\n if (this.hidden()) parts.push('wr-option--hidden');\n return parts.join(' ');\n });\n\n constructor() {\n if (this.parent) {\n const parent = this.parent;\n // Re-register when disabled or value changes so the parent has fresh metadata.\n // The label is seeded here as well, which is the read the server takes.\n effect(onCleanup => {\n // Untracked: the read goes through the `leadingSlot` query, which moves\n // every time the panel opens or closes, and a registration keyed on it\n // would unregister and re-register every option on each of those — a\n // registry write per option, and a recompute of everything the select\n // derives from the registry, for a change the registration does not\n // carry. The label itself still follows through `afterEveryRender`.\n untracked(() => this.syncLabel());\n const unreg = parent.registerOption({\n id: this.id,\n value: this.value(),\n disabled: this.disabled(),\n label: this.resolvedLabel,\n host: this.host.nativeElement,\n leading: this.leading,\n });\n onCleanup(() => unreg());\n });\n\n afterEveryRender(() => this.syncLabel());\n }\n }\n\n /**\n * Read the projected text back off the DOM. Setting the same string again is\n * a signal no-op, so the render hook costs a short walk over the host's\n * children and nothing else on the passes where nothing moved.\n *\n * A walk rather than the host's `textContent`, because the leading visual\n * renders INSIDE the host while the panel is open: a `textContent` read turned\n * an avatar's initials into the first word of the label, so the chip and the\n * search filter read \"ХР Хегай Роман\". Only text and element children count —\n * a comment's `textContent` is its data, and Angular anchors every\n * `<ng-template>` with one.\n */\n private syncLabel(): void {\n const slot = this.leadingSlot()?.nativeElement;\n let text = '';\n for (const node of Array.from(this.host.nativeElement.childNodes)) {\n if (node === slot) continue;\n if (node.nodeType === TEXT_NODE || node.nodeType === ELEMENT_NODE) text += node.textContent ?? '';\n }\n this.labelText.set(text.trim());\n }\n\n protected onClick(): void {\n if (this.disabled() || !this.parent) return;\n this.parent.selectOption(this.value());\n }\n}\n","<!-- The leading visual is a sibling of the projected text, never a wrapper\n around it: `.wr-option` is a flex row, and wrapping the content would fold\n a consumer's own icon and label into one flex item. `aria-hidden` keeps it\n out of the option's accessible name; `syncLabel` skips it by reference. -->\n@if (rowLeading(); as leading) {\n <span #leadingSlot class=\"wr-option__leading\" aria-hidden=\"true\">\n <ng-container\n [ngTemplateOutlet]=\"leading\"\n [ngTemplateOutletContext]=\"{ $implicit: value(), placement: 'option' }\"\n />\n </span>\n}\n<ng-content />\n","/**\n * @license\n *\n * Use of this source code is governed by an MIT-style license that can be\n * found in the LICENSE file at https://github.com/thekhegay/ngwr/blob/main/LICENSE\n */\n\nimport { Directionality } from '@angular/cdk/bidi';\nimport { coerceBooleanProperty, coerceNumberProperty } from '@angular/cdk/coercion';\nimport { type OverlayRef, ScrollStrategyOptions } from '@angular/cdk/overlay';\nimport { TemplatePortal } from '@angular/cdk/portal';\nimport { NgTemplateOutlet, isPlatformBrowser } from '@angular/common';\nimport {\n Component,\n DestroyRef,\n ElementRef,\n Injector,\n PLATFORM_ID,\n TemplateRef,\n ViewContainerRef,\n ViewEncapsulation,\n afterNextRender,\n computed,\n contentChild,\n contentChildren,\n effect,\n forwardRef,\n inject,\n input,\n model,\n output,\n signal,\n viewChild,\n} from '@angular/core';\nimport { takeUntilDestroyed, toObservable } from '@angular/core/rxjs-interop';\nimport type { FormValueControl } from '@angular/forms/signals';\n\nimport {\n type Observable,\n Subject,\n catchError,\n debounce,\n defer,\n finalize,\n from,\n isObservable,\n map,\n merge,\n of,\n skip,\n switchMap,\n tap,\n timer,\n} from 'rxjs';\n\nimport { WR_FORM_FIELD, useFormFieldAria } from 'ngwr/form';\nimport { useI18nFormatter, useI18nText } from 'ngwr/i18n';\nimport { WR_OVERLAY, WrOutsideClick, wrFollowDirection } from 'ngwr/overlay';\nimport { WrSpinner } from 'ngwr/spinner';\nimport { isComposing, toClassList, type WrClassInput } from 'ngwr/utils';\n\nimport { WrSelectLoadError } from './load-error';\nimport { WrOption } from './option';\nimport { WrOptionLeading } from './option-leading';\nimport { WR_SELECT } from './tokens';\nimport type {\n WrOptionLeadingContext,\n WrSelectMode,\n WrSelectSearchLoader,\n WrSelectTagValidator,\n WrSelectSize,\n WrSelectContext,\n WrSelectOptionRegistration,\n} from './types';\n\nlet listboxUid = 0;\n\ninterface SelectedChip {\n readonly value: unknown;\n readonly label: string;\n /** The leading template this chip draws, or `null`. */\n readonly leading: TemplateRef<WrOptionLeadingContext> | null;\n}\n\n/**\n * Combobox primitive. Renders a button that opens a CDK overlay\n * containing the projected `<wr-option>` (and optionally\n * `<wr-option-group>`) children. Every shape is the same component\n * with a different `[mode]`:\n *\n * - `'single'` (default) — one value, no input. Classic dropdown.\n * - `'multi'` — array value, chips on the trigger; clicking an option\n * toggles instead of closing, Backspace removes the last chip.\n * - `'search'` — type-ahead with sync `[options]` filter or async\n * `[loader]`. Replaces the standalone `<wr-autocomplete>`.\n * - `'tag'` — free-text + chips with `[separators]` / `[validate]` /\n * `[allowDuplicates]`. Replaces `<wr-chips-input>`.\n *\n * `[searchable]` is orthogonal to the mode — it adds the type-ahead filter to\n * `single` / `multi` without changing the value shape, which is how you get a\n * searchable multi-select. Server-side search hangs off the `(searchChange)` output\n * plus `[options]` / `[loading]`.\n *\n * A signal-forms native control: it implements `FormValueControl<unknown>`, so\n * `[formField]` binds straight to its `value` model — no\n * `ControlValueAccessor` in between. `[(value)]` works standalone, and classic\n * `[(ngModel)]` / reactive forms keep working through Angular's bridge.\n *\n * @example\n * ```html\n * <!-- Single (signal forms) -->\n * <wr-select placeholder=\"Pick a size\" [formField]=\"form.size\">\n * <wr-option value=\"sm\">Small</wr-option>\n * <wr-option value=\"md\">Medium</wr-option>\n * <wr-option value=\"lg\">Large</wr-option>\n * </wr-select>\n *\n * <!-- Multi (standalone two-way binding) -->\n * <wr-select mode=\"multi\" placeholder=\"Pick tags\" [(value)]=\"tags\">\n * <wr-option value=\"ts\">TypeScript</wr-option>\n * <wr-option value=\"ng\">Angular</wr-option>\n * </wr-select>\n *\n * <!-- Multi + type-ahead, options from a store -->\n * <wr-select\n * mode=\"multi\"\n * searchable\n * [options]=\"results()\"\n * [loading]=\"pending()\"\n * [(value)]=\"categories\"\n * (searchChange)=\"store.search($event)\"\n * />\n * ```\n *\n *\n * @see https://ngwr.dev/reference/components/select\n */\n@Component({\n selector: 'wr-select',\n templateUrl: './select.html',\n encapsulation: ViewEncapsulation.None,\n host: { '[class]': 'classes()' },\n imports: [WrOption, NgTemplateOutlet, WrSpinner],\n providers: [\n {\n provide: WR_SELECT,\n // eslint-disable-next-line @angular-eslint/no-forward-ref\n useExisting: forwardRef(() => WrSelect),\n },\n ],\n})\nexport class WrSelect implements FormValueControl<unknown>, WrSelectContext {\n /** Placeholder shown when no option is selected. Falls back to `select.placeholder`. */\n readonly placeholder = input<string | null>(null);\n\n /** Clear-selection (×) button aria-label. Falls back to `select.clearSelection`. */\n readonly clearLabel = input<string | null>(null);\n\n protected readonly resolvedPlaceholder = useI18nText(this.placeholder, 'select.placeholder', '');\n protected readonly resolvedClear = useI18nText(this.clearLabel, 'select.clearSelection', 'Clear selection');\n\n /**\n * Accessible name of the trigger. Falls back to the placeholder, then to\n * `select.label` — `role=\"combobox\"` on an empty trigger otherwise has no name\n * at all, which is the common case before anything is selected.\n */\n readonly ariaLabel = input<string | null>(null);\n\n private readonly labelText = useI18nText(this.ariaLabel, 'select.label', 'Select');\n protected readonly resolvedAriaLabel = computed(() => {\n // Not `??`: an empty placeholder must fall through to the catalog string.\n const explicit = this.ariaLabel();\n if (explicit) return explicit;\n const placeholder = this.resolvedPlaceholder();\n return placeholder ? placeholder : this.labelText();\n });\n\n /**\n * The field's own label, when it renders one — `null` otherwise, and `null`\n * when `[ariaLabel]` was set deliberately.\n *\n * `aria-label` outranks a `<label for>` in the accname order, so a control\n * inside `<wr-form-field label=\"Delivery notes\">` with a placeholder of its\n * own announced the PLACEHOLDER and the visible label reached nobody.\n * Nothing catches it: the control has a name, so axe is satisfied, and the\n * name is plausible, so a reader is too — it fails WCAG 2.5.3, where the\n * visible label has to be IN the accessible name.\n */\n protected readonly labelledBy = computed(() => (this.ariaLabel() ? null : this.fieldAria.labelledBy()));\n\n /** `null` once `aria-labelledby` is carrying the name — see {@link labelledBy}. */\n protected readonly nameLabel = computed(() => (this.labelledBy() ? null : this.resolvedAriaLabel()));\n\n /** Per-chip ARIA label — interpolates `{{label}}`. @internal */\n protected readonly chipRemoveLabel = useI18nFormatter('select.removeItem', 'Remove {{label}}');\n\n /**\n * The overflow chip past `maxTagCount` — interpolates `{{count}}`. Through the\n * catalog, like every other string here: printed as a bare `+{{ extra }} more`\n * it stayed English in a fully localized app, beside an event-calendar cell\n * reading \"ещё 3\" from the same string. @internal\n */\n protected readonly moreLabel = useI18nFormatter('select.more', '+{{count}} more');\n\n private readonly field = inject(WR_FORM_FIELD, { optional: true });\n\n /**\n * Id the surrounding `<wr-form-field>`'s `<label for>` points at.\n *\n * The field renders its label before it can see what was projected into it, so\n * the id travels the other way and the control adopts it, exactly as `[wrInput]`\n * and `wr-slider` do. Without this the `for` named an element that was nowhere in\n * the document: clicking the label did nothing, and the field's own text reached\n * the control through no path at all.\n *\n * It lands on the ONE focusable element each trigger shape has — the button, the\n * search input, or the tag input — never on the host, because only a labelable\n * element can be a label's target and `<wr-select>` is not one.\n *\n * What this does NOT change is that element's NAME: `aria-label` outranks a\n * `<label>` in the accname order, and the trigger keeps `resolvedAriaLabel()`\n * because the field cannot promise it has a name to give — `<wr-form-field>`\n * renders a label only when its `label` input is set, and a combobox that traded\n * a generic name for no name would be the worse bug. `WrFormFieldContext`\n * publishes no \"do I have a visible label\" signal to key that on. Until it does,\n * set `[ariaLabel]` to the field's label where the two should read alike.\n */\n protected readonly controlId = computed(() => this.field?.controlId() ?? null);\n\n /**\n * The field's error message — or, failing that, its hint — wired to the same\n * element, plus the invalid flag.\n *\n * Without it the copy `<wr-form-field>` renders is visible and nothing else: a\n * screen reader on the trigger never learns the field is invalid, nor what the\n * message says. Composed by `useFormFieldAria()` rather than read off the field\n * here, so the trigger picks up the hint the same way the other value controls\n * do and `aria-invalid` stays keyed on the error rather than on \"is anything\n * describing me\".\n */\n private readonly fieldAria = useFormFieldAria();\n protected readonly describedBy = this.fieldAria.describedBy;\n protected readonly ariaInvalid = this.fieldAria.ariaInvalid;\n\n /**\n * Disable the select. Bound automatically from the field's disabled state\n * when used with `[formField]`.\n *\n * @default false\n */\n readonly disabled = input(false, { transform: coerceBooleanProperty });\n\n /**\n * Refuse changes while the trigger stays focusable and the value still\n * submits. Bound automatically from the field's readonly state when used with\n * `[formField]`.\n *\n * The panel is where every edit happens, so a read-only select does not open —\n * and with it go the clear button, the chip ×, the tag draft and the search\n * query. The text-input shapes take the native `readonly` attribute, which is\n * what keeps them focusable and selectable where `disabled` would not; every\n * shape mirrors `aria-readonly`, which role `combobox` supports.\n *\n * @default false\n */\n readonly readonly = input(false, { transform: coerceBooleanProperty });\n\n /** Pill-shaped corners on the trigger. @default false */\n readonly rounded = input(false, { transform: coerceBooleanProperty });\n\n /**\n * Control size — shares the `--wr-control-*` contract. Read by the trigger's\n * host classes AND by the overlay panel, which builds its size modifier\n * separately. @default 'md'\n */\n readonly size = input<WrSelectSize>('md');\n\n /**\n * Behavior mode. `<wr-select>` is the unified combobox primitive —\n * pick the shape via `[mode]`:\n *\n * - `'single'` (default) — one value, no input. Classic dropdown.\n * - `'multi'` — array value, chips on the trigger.\n * - `'search'` — type-ahead with sync filter or async loader.\n * - `'tag'` — free-text + chips.\n *\n */\n readonly mode = input<WrSelectMode | null>(null);\n\n /** Resolved mode — `'single'` unless `[mode]` says otherwise. */\n protected readonly effectiveMode = computed<WrSelectMode>(() => this.mode() ?? 'single');\n\n /** Convenience — `effectiveMode() === 'multi'`. */\n protected readonly isMulti = computed(() => this.effectiveMode() === 'multi');\n\n /** Convenience — `effectiveMode() === 'tag'`. */\n protected readonly isTag = computed(() => this.effectiveMode() === 'tag');\n\n /** Convenience — `effectiveMode() === 'search'`. Exposed via context for options. */\n readonly isSearch = computed(() => this.effectiveMode() === 'search');\n\n /**\n * Add a type-ahead filter without changing the value shape — the missing\n * multi-with-search combination, since `[mode]` picks exactly one shape:\n *\n * ```html\n * <wr-select mode=\"multi\" searchable [(value)]=\"categories\">…</wr-select>\n * ```\n *\n * On `multi` the trigger keeps its chips and grows an inline text field (the\n * shape `tag` mode already uses); on `single` it is equivalent to\n * `mode=\"search\"`. Every search input (`[options]`, `[loader]`,\n * `[debounceMs]`, `[minChars]`, `[virtualScroll]`, the `(searchChange)` output, …)\n * applies either way. Ignored in `tag` mode, which owns its own input.\n * @default false\n */\n readonly searchable = input(false, { transform: coerceBooleanProperty });\n\n /**\n * Filtering is active — either `mode=\"search\"` or `[searchable]`. Exposed via\n * context so each `<wr-option>` can self-hide non-matching rows.\n */\n readonly isSearchable = computed(() => this.isSearch() || (this.searchable() && !this.isTag()));\n\n /** The trigger *is* the search input: `mode=\"search\"`, or a searchable single. */\n protected readonly isSearchTrigger = computed(() => this.isSearch() || (this.searchable() && !this.hasChips()));\n\n /** Chips plus an inline search field — a searchable multi-select. */\n protected readonly hasChipSearch = computed(() => this.searchable() && this.isMulti());\n\n /** WrSelectContext — resolved multi-selection flag for child options. */\n readonly multi = computed(() => this.effectiveMode() === 'multi' || this.effectiveMode() === 'tag');\n\n /** Both multi and tag render chips on the trigger. */\n protected readonly hasChips = computed(() => {\n const m = this.effectiveMode();\n return m === 'multi' || m === 'tag';\n });\n\n /**\n * The live search query. Empty string = no filter. Exposed via context so\n * each `<wr-option>` can self-hide non-matching rows.\n *\n * Two-way bindable, so the query can be owned or reset from outside:\n * `[(searchQuery)]=\"query\"`. For server-side search prefer the debounced\n * {@link searchChange} output — `searchQueryChange` fires on every keystroke.\n */\n readonly searchQuery = model('');\n\n // Search-mode-only inputs (ignored in other modes)\n\n /**\n * Search mode: dynamic option array. Each item is rendered as a\n * `<wr-option>` whose label comes from `[displayWith]`. Works\n * alongside projected `<wr-option>` children — both lists are\n * filtered by the search query.\n */\n readonly options = input<readonly unknown[]>([]);\n\n /** Search mode: map a dynamic option item to its display label. @default String */\n readonly displayWith = input<(item: unknown) => string>((item: unknown) => String(item));\n\n /**\n * Search mode: async loader. When set, the loader is called on every\n * (debounced) keystroke and its result replaces `[options]`. Supports\n * Observables, Promises, and plain arrays.\n */\n readonly loader = input<WrSelectSearchLoader<unknown> | null>(null);\n\n /**\n * The option list is already scoped to the query upstream — skip the built-in\n * client-side label filter. Set it when `[options]` is fed from a server via\n * the {@link searchChange} output; the async `[loader]` path implies it.\n *\n * Without this, a server that ranks or fuzzy-matches (returning rows whose\n * labels don't literally contain the query) would have those rows hidden\n * again on the client. @default false\n */\n readonly serverSearch = input(false, { transform: coerceBooleanProperty });\n\n /**\n * Whether the built-in label filter runs. Exposed via context so each\n * `<wr-option>` knows whether to self-hide. @internal\n */\n readonly clientFilter = computed(() => !this.loader() && !this.serverSearch());\n\n /** Search mode: debounce (ms) applied to the loader. @default 250 */\n readonly debounceMs = input(250, { transform: (v: unknown): number => Math.max(0, Number(v) || 0) });\n\n /** Search mode: minimum query length before the panel opens / loader fires. @default 0 */\n readonly minChars = input(0, { transform: (v: unknown): number => Math.max(0, Number(v) || 0) });\n\n /**\n * Search mode: allow values not in the options list. Enter on an\n * unmatched query commits the raw text as the form value. @default false\n */\n readonly freeText = input(false, { transform: coerceBooleanProperty });\n\n /**\n * Search mode: window the option panel so thousands of `[options]` keep only\n * ~one viewport of rows in the DOM. Opt-in and OFF by default. Engages ONLY on\n * the pure data-array search tier — it silently falls back to the full render\n * when static `<wr-option>` children are projected or the filtered list is\n * empty. While on, rows are plain `role=\"option\"` elements (no `<wr-option>`),\n * navigated via `aria-activedescendant`, selected by value. @default false\n */\n readonly virtualScroll = input(false, { transform: coerceBooleanProperty });\n\n /**\n * Search mode: uniform option-row height in px for the virtual window. `0`\n * (default) measures the first rendered row once and reuses it, so it adapts\n * to the control size. Read only when `virtualScroll` engages. @default 0\n */\n readonly rowHeight = input(0, { transform: (v: unknown): number => Math.max(0, coerceNumberProperty(v, 0)) });\n\n /**\n * Search mode: height of the virtual scroll viewport — a number (px) or any\n * CSS length. @default 256\n */\n readonly viewportHeight = input<number | string>(256);\n\n /** Search mode: extra rows kept above/below the virtual viewport. @default 6 */\n readonly overscan = input(6, { transform: (v: unknown): number => Math.max(0, coerceNumberProperty(v, 6)) });\n\n /** Search mode: text shown when the filter / loader returns nothing. Falls back to `select.noResults`. */\n readonly noResultsText = input<string | null>(null);\n\n /** Search mode: text shown while the async loader is in flight. Falls back to `select.loading`. */\n readonly loadingText = input<string | null>(null);\n\n /**\n * Search mode: text shown in place of the \"no results\" row when the async\n * loader fails. Falls back to `select.loadError`.\n */\n readonly loadErrorText = input<string | null>(null);\n\n /**\n * Search mode: let a failed load be tried again, for the same query, while the\n * panel has nothing else to offer. The error row draws a Try again button, and\n * Enter in the field reaches it, except under `freeText`, where Enter still\n * commits the typed text. Without it the row only reports the failure; the next keystroke\n * tries again either way.\n *\n * @default false\n */\n readonly retryable = input(false, { transform: coerceBooleanProperty });\n\n /** Search mode: label of the retry action on the error row. Falls back to `select.retry`. */\n readonly retryText = input<string | null>(null);\n\n protected readonly resolvedNoResults = useI18nText(this.noResultsText, 'select.noResults', 'No results');\n protected readonly resolvedLoading = useI18nText(this.loadingText, 'select.loading', 'Loading…');\n protected readonly resolvedLoadError = useI18nText(this.loadErrorText, 'select.loadError', 'Could not load results');\n protected readonly resolvedRetry = useI18nText(this.retryText, 'select.retry', 'Try again');\n\n /**\n * Debounced search query, gated to searchable selects. Emits on every settled\n * change — including the empty string when the field is cleared — so a\n * store-backed option list can stay in sync and reset itself. `[debounceMs]`\n * controls the delay; `[minChars]` does NOT gate it, for the same reason the\n * `[loader]` path clears its results below that threshold.\n *\n * This is the hook for server-side search: dispatch on `(searchChange)`, feed\n * the results back through `[options]` (plus `[serverSearch]`), and drive the\n * panel's progress row with `[loading]`. Prefer it over the model's raw\n * `(searchQueryChange)`, which fires on every keystroke.\n *\n * @example\n * ```html\n * <wr-select\n * mode=\"search\"\n * serverSearch\n * [options]=\"results()\"\n * [loading]=\"pending()\"\n * (searchChange)=\"store.search($event)\"\n * />\n * ```\n */\n readonly searchChange = output<string>();\n\n /**\n * Show the panel's progress row. Independent of `[loader]`, which raises and\n * lowers its own flag — use this when the options come from a store fed by\n * the {@link searchChange} output. @default false\n */\n readonly loading = input(false, { transform: coerceBooleanProperty });\n\n /** Search mode: results returned by the async loader. @internal */\n protected readonly loadedOptions = signal<readonly unknown[]>([]);\n\n /** True while the async `[loader]` is in flight. @internal */\n private readonly loaderLoading = signal(false);\n\n /** Either flag shows the panel's progress row. @internal */\n protected readonly isLoading = computed(() => this.loading() || this.loaderLoading());\n\n /** The query whose load failed, until a load for another query starts or one succeeds. */\n private readonly failedQuery = signal<string | null>(null);\n\n /** What the failed load threw or rejected with. */\n private readonly loadErrorValue = signal<unknown>(null);\n\n /** A retry is in flight. The error row stays up for it, with a loader. */\n protected readonly retrying = signal(false);\n\n /**\n * The load for the query on screen failed. Keyed by the query, so a keystroke\n * takes the error down at once, rather than when its debounced load starts.\n */\n protected readonly loadFailed = computed(() => this.failedQuery() === this.searchQuery());\n\n /** Asks the loader pipeline to run the current query again. */\n private readonly retryRequests = new Subject<void>();\n\n // Tag-mode-only inputs (ignored in other modes)\n\n /**\n * Tag mode: keys / characters that commit the current draft into a chip.\n * `'Enter'` is the key name; everything else is a literal character watched\n * in keypresses and pastes. @default ['Enter', ',']\n */\n readonly separators = input<readonly string[]>(['Enter', ',']);\n\n /** Tag mode: allow the same value to appear more than once. @default false */\n readonly allowDuplicates = input(false, { transform: coerceBooleanProperty });\n\n /**\n * Tag mode: custom validator — return `true` to accept the value, `false`\n * to silently reject. Receives the trimmed draft + the existing chips.\n */\n readonly validate = input<WrSelectTagValidator | null>(null);\n\n /** Tag-mode draft (text currently typed in the inline input). @internal */\n protected readonly draft = signal('');\n\n /**\n * Show a clear (×) button once at least one option is selected.\n *\n * NOT multi-only, which this said for a long time and which the template\n * refutes: only the button trigger gates on `isMulti()`, so the chips trigger\n * AND a single `mode=\"search\"` / `[searchable]` select carry it too. The\n * wording mattered little while the default was `true`; it decides what a\n * reader expects to lose now that it is not.\n *\n * The default changed from `true` to `false`: the affordance is opt-in, so a\n * trigger that grew an × on its own no longer does — pass `clearable` to keep\n * it. In `search` mode this also gates Backspace-to-clear on an empty field,\n * since that key is the keyboard twin of this button. @default false\n */\n readonly clearable = input(false, { transform: coerceBooleanProperty });\n\n /**\n * Extra CSS classes for the dropdown panel's overlay pane.\n *\n * The pane is appended to the overlay container, not to this component, so\n * nothing in the consumer's own template encloses it and no descendant rule\n * written around the trigger can reach it. This input is the only per-instance\n * handle on it. A space-separated string works as well as an array.\n *\n * The pane is a positioning wrapper carrying the gap above the list; the\n * box that paints is `.wr-select-panel` inside it, so a rule meant for the\n * surface reads `.my-class .wr-select-panel`.\n */\n readonly panelClass = input<WrClassInput>(null);\n\n /**\n * Cap on selected items (multi mode). `0` = unlimited. Once reached, the\n * unselected options are marked unavailable — `aria-disabled` and the\n * disabled look — and refuse a pick until one is removed. @default 0\n */\n readonly maxItems = input(0, {\n transform: (v: unknown): number => Math.max(0, Number(v) || 0),\n });\n\n /**\n * Maximum number of chips rendered before collapsing the rest into a\n * `+N more` indicator. `0` = render every chip. @default 0\n */\n readonly maxTagCount = input(0, {\n transform: (v: unknown): number => Math.max(0, Number(v) || 0),\n });\n\n /**\n * Unified value. Single mode holds a scalar (or `null`); multi / tag\n * mode holds `readonly unknown[]`. Bound by `[formField]`, or two-way\n * via `[(value)]`.\n */\n readonly value = model<unknown>(null);\n\n /** Emitted on blur / commit so a bound field can mark itself touched. */\n readonly touch = output<void>();\n\n /** Listbox id used by the trigger's `aria-controls`. */\n protected readonly listboxId = `wr-select-listbox-${++listboxUid}`;\n\n /** Registered options (insertion order). Internal — distinct from the public `[options]` input. */\n private readonly registry = signal<readonly WrSelectOptionRegistration[]>([]);\n\n /**\n * The registry in DOM order — the list the keyboard cursor walks.\n *\n * `registry` is CREATION order, and projected `<wr-option>` children are created\n * before the panel renders its own `[options]` rows, so with both in play the\n * cursor moved in an order the eye could not follow: opening highlighted the\n * third row on screen and ArrowDown went to the last. Value lookups keep reading\n * `registry` — they do not care about order — and a registration with no element\n * keeps its place, since the sort is stable.\n */\n private readonly orderedRegistry = computed<readonly WrSelectOptionRegistration[]>(() => {\n const list = this.registry();\n if (list.length < 2) return list;\n return [...list].sort((a, b) => {\n if (!a.host || !b.host || a.host === b.host) return 0;\n const relation = a.host.compareDocumentPosition(b.host);\n // `compareDocumentPosition` returns a BITMASK — a node can be both\n // following and contained — so masking is the API's own idiom, not a\n // cleverness to be rewritten as a comparison.\n /* eslint-disable no-bitwise -- reading the flags of a DOM bitmask */\n // DISCONNECTED is checked FIRST, and it is not defensive noise. Projected\n // `<wr-option>` hosts live in an `<ng-template>` that only instantiates\n // when the panel opens, so on the first change detection they are not in\n // the document yet — and the template's own `aria-activedescendant`\n // binding reads this computed on exactly that pass. For disconnected nodes\n // the spec lets a UA answer PRECEDING or FOLLOWING arbitrarily, as long as\n // it answers consistently; the answer means nothing, and the computed\n // CACHES it until the registry itself changes, so one meaningless\n // comparison decides the cursor order for the life of the select. Chromium\n // happens to answer in tree order and jsdom happens to answer in reverse,\n // which is the whole difference between a working component and one where\n // End lands on the first option. Registration order is the honest fallback:\n // the sort is stable, and it is already DOM order for a static list.\n if (relation & Node.DOCUMENT_POSITION_DISCONNECTED) return 0;\n if (relation & Node.DOCUMENT_POSITION_FOLLOWING) return -1;\n if (relation & Node.DOCUMENT_POSITION_PRECEDING) return 1;\n /* eslint-enable no-bitwise */\n return 0;\n });\n });\n\n /** Keyboard cursor index into `options`. -1 = none. */\n protected readonly activeIndex = signal(-1);\n\n /** Id of the active option (for `aria-activedescendant`). */\n readonly activeOptionId = computed<string | null>(() => {\n // The error row is the one thing on offer after a failed load, so the field\n // names it as active: a screen reader reads it, and Enter runs the retry.\n if (this.retryOffered() && !this.freeText()) return this.retryRowId;\n const idx = this.activeIndex();\n if (this.virtualActive()) {\n // Virtual rows aren't registered; the active id is derived from the index,\n // and returned only while the row is inside the rendered window so\n // `aria-activedescendant` never dangles at a recycled element.\n const { start, end } = this.virtualWindow();\n return idx >= start && idx < end ? this.virtualRowId(idx) : null;\n }\n const list = this.orderedRegistry();\n return idx >= 0 && idx < list.length ? list[idx].id : null;\n });\n\n protected readonly open = signal(false);\n\n /** WrSelectContext — whether the panel is open. Options gate their leading visual on it. */\n readonly panelOpen = this.open.asReadonly();\n\n /**\n * A `<ng-template wrOptionLeading>` declared as a DIRECT child of the select —\n * `descendants: false`, so an option's own template is never mistaken for the\n * select-wide default.\n */\n private readonly defaultLeading = contentChild(WrOptionLeading, { descendants: false });\n\n /**\n * WrSelectContext — the select-wide leading template, or `null`. The only\n * way to give a leading visual to the rows the select draws itself (`[options]`,\n * `[loader]` results, virtual rows), and the default for projected options that\n * declare none of their own.\n */\n readonly optionLeading = computed<TemplateRef<WrOptionLeadingContext> | null>(\n () => this.defaultLeading()?.template ?? null\n );\n\n /**\n * The leading template for a value: the registered option's (its own, or the\n * default it resolved to), else the select-wide default for a value with no\n * registered option — a virtual row, or one a loader has since dropped.\n */\n private leadingFor(value: unknown): TemplateRef<WrOptionLeadingContext> | null {\n const found = this.registry().find(o => o.value === value);\n if (found?.leading) return found.leading();\n return this.optionLeading();\n }\n\n /**\n * The leading visual beside the selected value on a single-mode BUTTON trigger\n * — one instance, for the one selected value. A search-shaped trigger draws the\n * same visual through {@link searchLeading}, on a narrower condition.\n */\n protected readonly selectedLeading = computed<TemplateRef<WrOptionLeadingContext> | null>(() => {\n if (this.isMulti() || this.selectedLabel() == null) return null;\n return this.leadingFor(this.value());\n });\n\n /**\n * The same visual on a SEARCH-shaped trigger (`mode=\"search\"`, a searchable\n * single), drawn before the input — the surface an assignee picker actually\n * uses, and the one that lost its avatar the moment the trigger became a field.\n *\n * The condition is {@link searchShowsValue} rather than `hasSelection()`, and\n * the two part company on every open panel: focusing the field replaces the\n * label with the live query, which starts empty, so what is on screen is the\n * placeholder. An avatar left standing there names a value the field no longer\n * shows, and then sits in front of whatever the user types next — the visual\n * would be answering a different question from the text beside it. It comes\n * back with the label, which is one signal flipping rather than two things\n * kept in step: committing a choice clears the query and closes the panel.\n *\n * Nothing is instantiated for a search select with no selection, panel open or\n * shut — `selectedLabel()` is `null` there, and this returns `null` with it.\n *\n * The COST of that rule, stated because it is a consumer's to weigh: stepping\n * aside is a destroy, so opening the picker and dismissing it unchanged\n * re-creates the visual — a template built on an `<img>` re-mounts once per\n * round trip, and re-requests unless the cache answers. Kept rather than\n * traded for a hidden-but-alive node: the panel's own rows already create and\n * destroy one apiece on the same gesture, so holding this one back buys a\n * fraction of that, and a node retained while it must not be seen is a second\n * piece of state to keep in step with the field. Pinned in `option.spec.ts`\n * (\"re-creates it after a round trip\"), so a future change here has to say so.\n */\n protected readonly searchLeading = computed<TemplateRef<WrOptionLeadingContext> | null>(() => {\n if (!this.isSearchTrigger() || !this.searchShowsValue()) return null;\n if (this.selectedLabel() == null) return null;\n return this.leadingFor(this.value());\n });\n\n /**\n * Trigger label for single mode. Multi reads `selectedChips` instead.\n *\n * A `computed`, and that is the whole point. It used to be a `signal` written\n * from an effect keyed on `value` / `registry` / `isMulti` / `displayWith` —\n * not one of which moves when the OPTION'S OWN TEXT does, and that text is\n * projected content whose ordinary way of changing is a translation catalog\n * landing a microtask after the first pass. The trigger kept the English\n * fallback while the open panel beside it showed the translation. The\n * registration now carries the label as a signal, so a late catalog and a\n * runtime locale switch both repaint the trigger with the panel.\n */\n protected readonly selectedLabel = computed<string | null>(() => {\n const v = this.value();\n if (this.isMulti()) return null;\n const match = this.registry().find(o => o.value === v);\n if (match) return match.label();\n // Search mode: a value picked from a virtualized (or since-unmounted) row\n // has no registered `<wr-option>`, so derive its label from `displayWith`\n // — the same function that rendered the row.\n return v != null && this.isSearchable() ? this.displayWith()(v) : null;\n });\n\n /**\n * Selected chips (multi + tag modes). Multi reads labels from the\n * registered `<wr-option>` children; tag uses each raw string as\n * both value and label.\n */\n protected readonly selectedChips = computed<readonly SelectedChip[]>(() => {\n if (!this.hasChips()) return [];\n const arr = this.asArray(this.value());\n if (this.isTag()) {\n // Tag values are free text with no option behind them, so no leading.\n return arr.map<SelectedChip>(v => ({ value: v, label: String(v), leading: null }));\n }\n const list = this.registry();\n return arr.map<SelectedChip>(v => {\n const found = list.find(o => o.value === v);\n // Fall back to `displayWith` (defaults to `String`) rather than `String`\n // directly: a searchable multi fed from `[options]` has no registered\n // `<wr-option>` for a virtualized or unmounted row, and object items\n // would otherwise render as \"[object Object]\".\n return {\n value: v,\n label: found?.label() ?? this.displayWith()(v),\n leading: found?.leading ? found.leading() : this.optionLeading(),\n };\n });\n });\n\n protected readonly visibleChips = computed<readonly SelectedChip[]>(() => {\n const cap = this.maxTagCount();\n const chips = this.selectedChips();\n return cap > 0 && chips.length > cap ? chips.slice(0, cap) : chips;\n });\n\n protected readonly hiddenChipCount = computed(() => {\n const cap = this.maxTagCount();\n const total = this.selectedChips().length;\n return cap > 0 && total > cap ? total - cap : 0;\n });\n\n protected readonly hasSelection = computed(() => {\n if (this.hasChips()) return this.selectedChips().length > 0;\n return this.value() != null;\n });\n\n /** Effective disabled state. Part of {@link WrSelectContext} for child options. */\n readonly isDisabled = computed(() => this.disabled());\n\n /** Effective readonly state — refuses every write path without removing focus. */\n protected readonly isReadonly = computed(() => this.readonly());\n\n protected readonly classes = computed(() => {\n const parts = ['wr-select'];\n if (this.open()) parts.push('wr-select--open');\n if (this.rounded()) parts.push('wr-select--rounded');\n const size = this.size();\n if (size !== 'md') parts.push(`wr-select--${size}`);\n if (this.isMulti()) parts.push('wr-select--multi');\n if (this.isTag()) parts.push('wr-select--tag');\n if (this.isSearchTrigger()) parts.push('wr-select--search');\n if (this.hasChipSearch()) parts.push('wr-select--searchable');\n if (this.isDisabled()) parts.push('wr-select--disabled');\n else if (this.isReadonly()) parts.push('wr-select--readonly');\n return parts.join(' ');\n });\n\n /**\n * Search-mode dynamic options. Loader results win when the loader is\n * set; otherwise the static `[options]` array. Each item is rendered\n * as an internal `<wr-option>` in the panel.\n */\n protected readonly dynamicOptions = computed<readonly unknown[]>(() =>\n this.loader() ? this.loadedOptions() : this.options()\n );\n\n // --- Virtual scroll (search mode, data-array path) ------------------------\n\n private static readonly FALLBACK_ROW_PX = 34;\n private static readonly FALLBACK_VIEWPORT_PX = 256;\n\n /**\n * Consumer-projected `<wr-option>` children only (NOT the `@for`-rendered ones\n * — those live in the panel's own view, which a content query never sees).\n *\n * `descendants: true` because a projected option is as often wrapped in a\n * `<wr-option-group>` as it is a direct child, and the signal default is\n * `false`. A grouped list therefore read as NO projected options: `virtualActive`\n * engaged over the (empty) data array, so the panel rendered the group's rows\n * with a virtual window beside them that owned the keyboard — no\n * `aria-activedescendant`, no active row, and Enter committing nothing.\n */\n private readonly projectedOptions = contentChildren(WrOption, { descendants: true });\n\n /**\n * `dynamicOptions()` narrowed to the current search query. `dynamicOptions()`\n * is intentionally UNFILTERED (projected `<wr-option>` self-hide via CSS), so\n * the virtual path — which renders plain rows that can't self-hide — filters\n * here. Loader / `serverSearch` results are already query-scoped upstream.\n */\n protected readonly filteredDynamicOptions = computed<readonly unknown[]>(() => {\n const items = this.dynamicOptions();\n if (!this.clientFilter()) return items;\n const q = this.searchQuery().trim().toLowerCase();\n if (!q) return items;\n const label = this.displayWith();\n return items.filter(it => label(it).toLowerCase().includes(q));\n });\n\n /**\n * Virtualization engaged: opt-in, search mode, and NO projected `<wr-option>`\n * children — grouped ones included (those keep the full-render registry path so\n * their DOM-derived labels / selection still work).\n *\n * NOT gated on there being matches. It used to also require\n * `filteredDynamicOptions().length > 0`, which meant a query matching nothing\n * fell back to the full-render path and mounted the ENTIRE unfiltered array —\n * 2000 `<wr-option>` hosts, every one of them `--hidden`, behind a \"No\n * results\" line — and then tore all of them down again on the next keystroke\n * that matched. The empty window is handled where it belongs: `virtualWindow`\n * already short-circuits on `total === 0`, and `firstEnabled` / `lastEnabled`\n * already answer -1.\n */\n protected readonly virtualActive = computed<boolean>(\n () => this.virtualScroll() && this.isSearchable() && this.projectedOptions().length === 0\n );\n\n private readonly scrollTop = signal(0);\n private readonly viewportPx = signal(0);\n private readonly measuredRowPx = signal(0);\n\n /** Effective uniform row height (px). */\n protected readonly effRowH = computed(() =>\n this.rowHeight() > 0 ? this.rowHeight() : this.measuredRowPx() || WrSelect.FALLBACK_ROW_PX\n );\n\n private readonly fallbackViewportPx = computed(() => {\n const h = this.viewportHeight();\n if (typeof h === 'number') return h;\n return /^\\d+$/.test(h) ? Number(h) : WrSelect.FALLBACK_VIEWPORT_PX;\n });\n\n /** `viewportHeight` as a CSS length for the inline max-height (bare number → px). */\n protected readonly resolvedViewportHeight = computed(() => {\n const h = this.viewportHeight();\n return typeof h === 'number' || /^\\d+$/.test(h) ? `${h}px` : h;\n });\n\n /** Rendered window [start,end) + spacer pads (px). */\n protected readonly virtualWindow = computed<{ start: number; end: number; padTop: number; padBottom: number }>(() => {\n const total = this.filteredDynamicOptions().length;\n if (!this.virtualActive() || total === 0) return { start: 0, end: total, padTop: 0, padBottom: 0 };\n const h = this.effRowH();\n const vp = this.viewportPx() || this.fallbackViewportPx();\n const over = this.overscan();\n const first = Math.min(Math.floor(this.scrollTop() / h), total - 1);\n const count = Math.ceil(vp / h) + 1;\n const start = Math.max(0, first - over);\n const end = Math.min(total, first + count + over);\n return { start, end, padTop: start * h, padBottom: (total - end) * h };\n });\n\n /** The windowed slice of options, each carrying its absolute index. */\n protected readonly windowOptions = computed<readonly { item: unknown; index: number }[]>(() => {\n const { start, end } = this.virtualWindow();\n return this.filteredDynamicOptions()\n .slice(start, end)\n .map((item, k) => ({ item, index: start + k }));\n });\n\n /** Stable id for a virtual option row at filtered index `i`. */\n protected virtualRowId(i: number): string {\n return `${this.listboxId}-vopt-${i}`;\n }\n\n /** The virtual scroll container inside the overlay panel, if attached. */\n private get vlistElement(): HTMLElement | null {\n return this.overlayRef?.overlayElement.querySelector<HTMLElement>('.wr-select-panel__vlist') ?? null;\n }\n\n /** The scrolling listbox inside the overlay panel, if attached. */\n private get panelElement(): HTMLElement | null {\n return this.overlayRef?.overlayElement.querySelector<HTMLElement>('.wr-select-panel') ?? null;\n }\n\n /**\n * Scroll the ordered index `i` just into view. Two implementations, because the\n * two panels scroll different elements and know the row geometry in different\n * ways — the virtual list is index maths against a measured row height, the\n * projected list has to read the row it is moving to.\n *\n * The non-virtual half is not an optimisation, it is the whole keyboard\n * contract: `activeIndex` drives `aria-activedescendant`, and NOTHING else\n * moves a projected panel, because the rows never take DOM focus. Without it\n * End on a 250-option `mode=\"search\"` panel announced Zimbabwe while the panel\n * sat at `scrollTop` 0 with the cursor 9 218 px below the fold, and Enter then\n * committed a row the user could not see.\n */\n private ensureVisible(i: number): void {\n if (i < 0) return;\n if (!this.virtualActive()) {\n this.ensureRowVisible(i);\n return;\n }\n const h = this.effRowH();\n const vp = this.viewportPx() || this.fallbackViewportPx();\n const top = i * h;\n const cur = this.scrollTop();\n let next = cur;\n if (top < cur) next = top;\n else if (top + h > cur + vp) next = top + h - vp;\n if (next !== cur) {\n this.scrollTop.set(next);\n this.vlistElement?.scrollTo({ top: next });\n }\n }\n\n /**\n * Scroll the projected row at ordered index `i` just into view.\n *\n * Geometry is READ rather than computed: projected `<wr-option>` rows are\n * consumer content, so they are not a uniform height the way a virtual row is\n * — a row with a description, an icon or a wrapped label is taller than its\n * neighbours, and index maths would land the panel next to the cursor instead\n * of on it. The offset is taken relative to the panel's own scroll content\n * (`rect.top` difference plus the current `scrollTop`) rather than from\n * `offsetTop`, which is measured against whichever ancestor happens to be\n * positioned.\n *\n * `scrollTop` is written directly instead of `scrollTo`, so the write is\n * observable in a spec — jsdom implements the property and does not implement\n * the method. It still reads as a no-op there, since every jsdom rect is 0×0:\n * a spec asserting a scroll has to stub `getBoundingClientRect` and\n * `clientHeight` on the panel and the row, which `select.spec.ts` does.\n */\n private ensureRowVisible(i: number): void {\n const panel = this.panelElement;\n if (!panel) return;\n const list = this.orderedRegistry();\n if (i >= list.length) return;\n const row = panel.querySelector<HTMLElement>(`#${CSS.escape(list[i].id)}`);\n if (!row) return;\n\n const panelRect = panel.getBoundingClientRect();\n const rowRect = row.getBoundingClientRect();\n const cur = panel.scrollTop;\n const top = rowRect.top - panelRect.top + cur;\n const vp = panel.clientHeight;\n\n let next = cur;\n if (top < cur) next = top;\n else if (top + rowRect.height > cur + vp) next = top + rowRect.height - vp;\n if (next !== cur) panel.scrollTop = next;\n }\n\n /**\n * Count of registered options that pass the current search filter.\n * Hides the noResults state when the panel has at least one visible row.\n */\n protected readonly visibleCount = computed(() => {\n if (this.virtualActive()) return this.filteredDynamicOptions().length;\n const list = this.registry();\n if (!this.isSearchable() || !this.clientFilter()) return list.length;\n const q = this.searchQuery().trim().toLowerCase();\n if (!q) return list.length;\n let count = 0;\n for (const o of list) {\n if (o.label().toLowerCase().includes(q)) count++;\n }\n return count;\n });\n\n /**\n * Whether the panel may be open at all. `minChars` is documented as the\n * \"minimum query length before the panel OPENS\", and nothing gated the open —\n * so a picker with `[minChars]=\"3\"` popped a panel on focus and showed an empty\n * bordered box for the first two keystrokes (with the \"no results\" row itself\n * gated on the same threshold, there was nothing in it to explain the box).\n */\n protected readonly meetsMinChars = computed(\n () => !this.isSearchable() || this.searchQuery().trim().length >= this.minChars()\n );\n\n /** Search mode: show \"no results\" when the panel has nothing to offer. */\n protected readonly hasNoResults = computed(() => {\n if (!this.isSearchable() || !this.open() || this.isLoading() || this.loadFailed()) return false;\n if (this.searchQuery().trim().length < this.minChars()) return false;\n return this.visibleCount() === 0;\n });\n\n /** Search mode: the error row, in place of \"no results\", after a failed load and through its retry. */\n protected readonly showLoadError = computed(\n () => this.isSearchable() && this.open() && this.loadFailed() && (!this.isLoading() || this.retrying())\n );\n\n /** A `<ng-template wrSelectLoadError>` declared as a direct child, or `undefined`. */\n protected readonly loadErrorTpl = contentChild(WrSelectLoadError, { descendants: false });\n\n /** What `wrSelectLoadError` is handed. */\n protected readonly loadErrorContext = computed(() => ({\n $implicit: this.loadErrorValue(),\n query: this.failedQuery() ?? '',\n canRetry: this.retryOffered(),\n retry: this.retryFn,\n retrying: this.retrying(),\n }));\n\n /** One function for the context, gated the way the default button is. */\n private readonly retryFn = (): void => this.onLoadErrorClick();\n\n /**\n * Search mode: the error row offers a retry. Only while nothing else is on\n * offer, since the arrows walk the options and never reach this row; with\n * options beside it, a retry by pointer alone would have no keyboard twin.\n */\n protected readonly retryOffered = computed(\n () => this.retryable() && this.showLoadError() && this.visibleCount() === 0\n );\n\n /** Id of the error row, which `aria-activedescendant` names while it offers a retry. */\n protected readonly retryRowId = `${this.listboxId}-retry`;\n\n /** Search mode: is this option hidden by the current query? @internal */\n private isOptionHidden(label: string): boolean {\n if (!this.isSearchable() || !this.clientFilter()) return false;\n const q = this.searchQuery().trim().toLowerCase();\n if (!q) return false;\n return !label.toLowerCase().includes(q);\n }\n\n protected readonly panelTpl = viewChild.required('panelTpl', { read: TemplateRef });\n\n /** The inline input inside a chip trigger — tag mode or a searchable multi. @internal */\n protected readonly tagInputEl = viewChild<ElementRef<HTMLInputElement>>('tagInput');\n\n /** Search-mode inline input. Present only when `mode=\"search\"`. @internal */\n protected readonly searchInputEl = viewChild<ElementRef<HTMLInputElement>>('searchInput');\n\n /** The button trigger — every shape without a text field of its own. @internal */\n private readonly triggerEl = viewChild<ElementRef<HTMLButtonElement>>('trigger');\n\n /** Set for the length of a `focus()` call, so the field takes focus and nothing opens. @internal */\n private quietFocus = false;\n\n /**\n * Focus the control's tab stop — what Signal Forms calls to focus this\n * control: the search field, the chip field, or the trigger button, whichever\n * the current shape draws.\n *\n * The panel stays shut. A text field opens it when the USER arrives, since\n * they are about to type; a form focusing its first invalid field is pointing\n * at it, and a listbox over the rest of the form is not what that asked for.\n */\n focus(options?: FocusOptions): void {\n const field = this.searchInputEl() ?? this.tagInputEl();\n if (!field) {\n this.triggerEl()?.nativeElement.focus(options);\n return;\n }\n this.quietFocus = true;\n try {\n field.nativeElement.focus(options);\n } finally {\n this.quietFocus = false;\n }\n }\n\n protected focusTagInput(): void {\n this.tagInputEl()?.nativeElement.focus();\n }\n\n protected focusSearchInput(): void {\n this.searchInputEl()?.nativeElement.focus();\n }\n\n // Chip-trigger input dispatch. One inline input, two owners: tag mode\n // commits a draft into chips, a searchable multi filters the panel.\n\n protected onChipsInput(event: Event): void {\n if (this.hasChipSearch()) this.onSearchInput(event);\n else this.onTagInput(event);\n }\n\n protected onChipsKeydown(event: KeyboardEvent): void {\n if (this.imeOwnsKey(event)) return;\n if (this.hasChipSearch()) this.onSearchKey(event);\n else this.onTagKeydown(event);\n }\n\n /**\n * True when the key belongs to an open IME conversion — and, when it does,\n * stops the event on its way out.\n *\n * Not acting is not enough here. The panel closes on Escape from CDK's overlay\n * keyboard dispatcher, one listener on `<body>` in the bubble phase, so a\n * handler that merely returns still loses the panel: the Japanese user meant\n * to cancel a reading and lost the query with it. Stopping the event at the\n * field that owns the composition is the only place that reaches both.\n */\n private imeOwnsKey(event: KeyboardEvent): boolean {\n if (!isComposing(event)) return false;\n event.stopPropagation();\n return true;\n }\n\n protected onChipsFocus(): void {\n // Tag mode has no panel to open.\n if (this.hasChipSearch()) this.onSearchFocus();\n }\n\n protected onChipsPaste(event: ClipboardEvent): void {\n // Splitting a paste into chips is tag-mode behaviour; a search query is\n // pasted as-is.\n if (!this.hasChipSearch()) this.onTagPaste(event);\n }\n\n protected onChipsBlur(): void {\n if (this.hasChipSearch()) this.touch.emit();\n else this.onTagBlur();\n }\n\n // Search-mode handlers\n\n protected onSearchInput(event: Event): void {\n if (this.isDisabled() || this.isReadonly()) return;\n const value = (event.target as HTMLInputElement).value;\n this.searchQuery.set(value);\n if (this.meetsMinChars()) {\n if (!this.open()) this.open.set(true);\n } else if (this.open()) {\n this.open.set(false);\n }\n // A new filter invalidates every index, so re-seed the cursor onto the first\n // option that still matches. This must happen on BOTH paths: on the\n // projected-`<wr-option>` path the registry keeps filtered-out options (they\n // only self-hide via CSS), so a stale `activeIndex` would leave the cursor on\n // a row the user can no longer see — and Enter would select it.\n this.activeIndex.set(this.firstEnabled());\n if (this.virtualActive()) {\n this.scrollTop.set(0);\n this.vlistElement?.scrollTo({ top: 0 });\n return;\n }\n // The projected panel keeps whatever `scrollTop` the previous query left it\n // at, so the re-seeded cursor lands off screen unless it is scrolled to —\n // and this is the ONE cursor move that cannot be handled synchronously.\n // Filtered-out options only self-hide via CSS, applied on the next pass, so\n // a rect read on this line measures the panel as it was BEFORE the new query\n // removed rows above the cursor. `afterNextRender`, not `queueMicrotask`:\n // under zoneless CD the scheduler refreshes the view in a macrotask, and a\n // microtask queued from this handler runs before the DOM reflects the query\n // that caused it.\n afterNextRender(() => this.ensureVisible(this.activeIndex()), { injector: this.injector });\n }\n\n protected onSearchFocus(): void {\n if (this.isDisabled()) return;\n // Focus is tracked even while read-only — the field still takes it, and\n // `searchDisplay()` keys off it — but nothing opens. The same holds for a\n // focus that `focus()` asked for, which is the form's and not the user's.\n this.searchHasFocus.set(true);\n if (this.isReadonly() || this.quietFocus) return;\n if (!this.meetsMinChars()) return;\n if (!this.open()) {\n this.seedActiveIndex();\n this.open.set(true);\n }\n }\n\n protected onSearchBlur(): void {\n this.searchHasFocus.set(false);\n // Leaving the field is what makes a below-threshold query stale, so this is\n // where the panel-close reset would have run if it could have waited.\n if (!this.open() && this.isSearchable()) this.searchQuery.set('');\n this.touch.emit();\n }\n\n protected onSearchKey(event: KeyboardEvent): void {\n // Enter accepts an IME candidate, Escape cancels the reading, the arrows walk\n // the candidate list — none of it is the listbox's while a conversion is open.\n if (this.imeOwnsKey(event)) return;\n\n if (event.key === 'Enter' && this.retryOffered() && !this.freeText()) {\n event.preventDefault();\n this.retryLoad();\n return;\n }\n\n // freeText: Enter on an unmatched query commits the typed string\n // as the value. Skips when an active option is highlighted (the\n // normal Enter-selects behaviour wins).\n if (event.key === 'Enter' && this.freeText() && this.open()) {\n const q = this.searchQuery().trim();\n const idx = this.activeIndex();\n const list = this.orderedRegistry();\n const hasActive = this.virtualActive()\n ? idx >= 0 && idx < this.filteredDynamicOptions().length\n : idx >= 0 && idx < list.length && !list[idx].disabled && !this.isOptionHidden(list[idx].label());\n if (!hasActive && q) {\n event.preventDefault();\n this.value.set(q);\n this.touch.emit();\n this.open.set(false);\n return;\n }\n }\n // Space belongs to the text field, not to the listbox. The button trigger\n // uses it to pick the active option, but here swallowing it would make a\n // multi-word query (\"dump trucks\") impossible to type.\n if (event.key === ' ') return;\n\n // Backspace on an empty query drops the last chip, matching tag mode. The\n // button-trigger path only does this while closed, and a chip-search input\n // keeps the panel open, so it never reaches that branch.\n if (event.key === 'Backspace' && this.hasChipSearch() && this.searchQuery() === '' && this.hasSelection()) {\n const chips = this.selectedChips();\n if (chips.length > 0) {\n event.preventDefault();\n this.removeChip(chips.length - 1, event);\n return;\n }\n }\n\n // The same key, for the searchable SINGLE: Backspace on an empty field is\n // its clear control. Every other mode could already undo a selection from\n // the keyboard — the chip modes above, the button trigger one chip per\n // Backspace — while here the × was the only way out, and it is a\n // `tabindex=\"-1\"` span no key can reach. A function offered by pointer\n // alone is a WCAG 2.1.1 failure, not a missing convenience.\n //\n // Gated on `clearable()` because that input IS the clear control: a consumer\n // who turned the × off did not ask for a keyboard twin of it. Gated on the\n // FIELD being empty rather than on `searchQuery()`, which is not the same\n // question — under `[minChars]` a collapsed field shows the selected label\n // while the query is still '', and backspacing over that text has always\n // started a query rather than thrown the selection away.\n if (\n event.key === 'Backspace' &&\n !this.hasChipSearch() &&\n this.clearable() &&\n this.hasSelection() &&\n (event.target as HTMLInputElement | null)?.value === ''\n ) {\n event.preventDefault();\n this.clearAll(event);\n return;\n }\n\n // Otherwise route through the same keyboard plumbing as the button trigger.\n this.onTriggerKey(event);\n }\n\n /**\n * Whether the search field is showing the SELECTED VALUE rather than a query.\n * `searchDisplay` takes its text off this, and `searchLeading` the visual that\n * goes before it, so the two can never disagree about which of the two things\n * the field is holding.\n *\n * FOCUS as well as open, and that second term is the whole `[minChars]` story.\n * Backspacing under the threshold closes the panel, and falling back to the\n * selected label the moment `open()` goes false rewrote the field out from\n * under someone who was still typing — \"sma\" -> \"sm\" showed an empty box.\n *\n * A NON-EMPTY query, though: picking an option clears it and leaves focus in\n * the field, and there the label is what belongs on screen.\n *\n * Only the search-shaped trigger reads it. A searchable MULTI binds its input\n * to `searchQuery()` directly and shows its selection as chips, which carry\n * their own leading visuals whatever the field holds.\n * @internal\n */\n protected readonly searchShowsValue = computed(() => {\n if (this.open()) return false;\n return !(this.searchHasFocus() && this.searchQuery() !== '');\n });\n\n /**\n * Display text for the search input. Shows the selected option's\n * label when collapsed, or the live query while typing / panel open.\n * @internal\n */\n protected readonly searchDisplay = computed(() =>\n this.searchShowsValue() ? (this.selectedLabel() ?? '') : this.searchQuery()\n );\n\n /**\n * Whether the search field holds focus.\n *\n * Read by `searchDisplay`, so it has to be a signal — and it is also what\n * lets the panel-close effect tell \"the user walked away\" (reset the query)\n * from \"the query dropped under `minChars` and they are still typing\" (keep\n * it).\n */\n private readonly searchHasFocus = signal(false);\n\n private readonly host = inject<ElementRef<HTMLElement>>(ElementRef);\n private readonly overlay = inject(WR_OVERLAY);\n private readonly outsideClick = inject(WrOutsideClick);\n private readonly vcr = inject(ViewContainerRef);\n private readonly scrollStrategies = inject(ScrollStrategyOptions);\n private readonly destroyRef = inject(DestroyRef);\n private readonly platformId = inject(PLATFORM_ID);\n private readonly injector = inject(Injector);\n /**\n * Ambient reading direction, for the open panel alone — nothing in this\n * component reads it directly. Optional so a bare `TestBed` needs no\n * provider; `Directionality` is root-provided anyway, and a missing one\n * simply reads as `ltr`.\n */\n private readonly dir = inject(Directionality, { optional: true });\n private overlayRef: OverlayRef | null = null;\n\n constructor() {\n // A component destroyed while the panel is open takes its overlay with it.\n // Without this the pane stays in the CDK container forever.\n this.destroyRef.onDestroy(() => this.closeOverlay());\n\n // Close the panel if the control goes read-only or disabled while it is up —\n // a panel whose every row now refuses the click is a trap, not a view.\n effect(() => {\n if (this.isDisabled() || this.isReadonly()) this.open.set(false);\n });\n\n effect(() => {\n if (this.open()) {\n this.openOverlay();\n } else {\n this.closeOverlay();\n // Reset the search query when the panel closes so a re-open doesn't\n // carry a stale filter — but NOT while the field still has focus.\n //\n // With `[minChars]`, backspacing under the threshold closes the panel\n // (`onSearchInput`), and `searchDisplay` falls back to the selected\n // label the moment `open()` is false — so an unconditional reset here\n // erased what the user was still typing, mid-word. A query the user is\n // actively editing is not stale.\n if (this.isSearchable() && !this.searchHasFocus()) this.searchQuery.set('');\n }\n });\n\n // One debounced query stream feeds both the async loader and the public\n // `searchChange` output, so they fire on exactly the same cadence.\n // `debounce(() => timer(...))` rather than `debounceTime(this.debounceMs())`:\n // this runs in the constructor, where inputs aren't bound yet, so reading\n // the input eagerly would pin the delay to the default and ignore\n // `[debounceMs]` forever.\n // `skip(1)` sits BEFORE the debounce so it drops the mount-time replay of the\n // empty query and nothing else. Downstream of `debounce` it would instead\n // drop the first *settled* emission — and when a fast typist's first\n // keystrokes coalesce with that initial `''`, the dropped emission is their\n // query, not the replay.\n const debouncedQuery = toObservable(this.searchQuery).pipe(\n skip(1),\n debounce(() => timer(this.debounceMs()))\n );\n\n debouncedQuery.pipe(takeUntilDestroyed(this.destroyRef)).subscribe(query => {\n if (this.isSearchable()) this.searchChange.emit(query);\n });\n\n // Async loader pipeline (searchable selects only). `switchMap` cancels\n // in-flight requests when a new keystroke arrives. A retry joins after the\n // debounce, with the query that failed.\n merge(\n debouncedQuery.pipe(map(query => ({ query, retry: false }))),\n this.retryRequests.pipe(map(() => ({ query: this.failedQuery() ?? this.searchQuery(), retry: true })))\n )\n .pipe(\n switchMap(({ query, retry }) => {\n const loader = this.loader();\n // No load to run: with no loader, or under `minChars`, a failure is moot.\n if (!loader || !this.isSearchable() || query.length < this.minChars()) {\n this.loaderLoading.set(false);\n this.retrying.set(false);\n this.failedQuery.set(null);\n return of<readonly unknown[]>([]);\n }\n // A retry keeps the failure on screen, with a loader, until it settles;\n // a new query takes it down at once.\n this.retrying.set(retry);\n if (!retry) this.failedQuery.set(null);\n // Whether this load answered at all, with a value or an error.\n let settled = false;\n this.loaderLoading.set(true);\n // `defer` so the loader CALL is part of the inner observable too. Called\n // out here, a loader that throws SYNCHRONOUSLY throws from switchMap's\n // project function, which rxjs routes straight to the destination — past\n // the `catchError` below and past `finalize`, so the flag raised on the\n // line above would stay up for good.\n const source = defer((): Observable<readonly unknown[]> => {\n const result = loader(query);\n return isObservable(result) ? result : from(Promise.resolve(result));\n });\n return source.pipe(\n // A loader can hand back a long-lived observable (a store selector,\n // say) that emits and never completes — so the first value lowers the\n // flag. `finalize` still covers completion, errors and cancellation,\n // including a loader that completes without emitting.\n tap(() => {\n settled = true;\n this.loaderLoading.set(false);\n this.failedQuery.set(null);\n this.retrying.set(false);\n }),\n // INSIDE the projection, which is the whole point: an error allowed to\n // reach the outer subscriber closes the subscription for good, and the\n // select then never calls the loader again for the life of the\n // component — silently, since nothing here has an error callback. Kept\n // inside, one failed request costs that query and nothing else. The\n // results go empty rather than stale, since rows for a query two\n // keystrokes old would read as an answer to the current one, and the\n // panel says the load failed instead of \"no results\".\n catchError((error: unknown) => {\n settled = true;\n this.failedQuery.set(query);\n this.loadErrorValue.set(error);\n this.retrying.set(false);\n return of<readonly unknown[]>([]);\n }),\n finalize(() => {\n this.loaderLoading.set(false);\n this.retrying.set(false);\n // A retry that completed with nothing did not fail: \"no results\".\n if (retry && !settled) this.failedQuery.set(null);\n })\n );\n }),\n takeUntilDestroyed(this.destroyRef)\n )\n .subscribe(items => this.loadedOptions.set(items));\n\n // Wire the virtual scroll listener + viewport/row measurement while the panel\n // is open and virtualized. Re-runs when the panel opens/closes or the virtual\n // list mounts/unmounts; the microtask defers the DOM read until the overlay\n // portal is attached. Browser-only — the panel never prerenders (overlay).\n effect(onCleanup => {\n if (!isPlatformBrowser(this.platformId)) return;\n if (!this.open() || !this.virtualActive()) return;\n let raf = 0;\n let ro: ResizeObserver | null = null;\n let el: HTMLElement | null = null;\n const onScroll = (): void => {\n if (raf) return;\n raf = requestAnimationFrame(() => {\n raf = 0;\n if (el) this.scrollTop.set(el.scrollTop);\n });\n };\n queueMicrotask(() => {\n el = this.vlistElement;\n if (!el) return;\n this.viewportPx.set(el.clientHeight);\n if (this.rowHeight() === 0) {\n const h = el.querySelector<HTMLElement>('.wr-option')?.offsetHeight ?? 0;\n if (h > 0) this.measuredRowPx.set(h);\n }\n // Re-seed the scroll with the now-measured row height + real viewport so\n // a deep pre-selected active row lands correctly on first open (the seed\n // before open used the fallback height). No-op when it's already in view.\n this.ensureVisible(this.activeIndex());\n // Sync the freshly-attached element to the retained signal — seeds the\n // scroll to the active option and avoids a blank panel on reopen.\n if (el.scrollTop !== this.scrollTop()) el.scrollTop = this.scrollTop();\n el.addEventListener('scroll', onScroll, { passive: true });\n if (typeof ResizeObserver !== 'undefined') {\n ro = new ResizeObserver(() => {\n if (el) this.viewportPx.set(el.clientHeight);\n });\n ro.observe(el);\n }\n });\n onCleanup(() => {\n if (raf) cancelAnimationFrame(raf);\n if (el) el.removeEventListener('scroll', onScroll);\n ro?.disconnect();\n });\n });\n }\n\n // WrSelectContext\n\n isSelected(value: unknown): boolean {\n if (this.isMulti()) return this.asArray(this.value()).includes(value);\n return this.value() === value;\n }\n\n /** Runs the loader again for the query that failed, unless a retry is already in flight. @internal */\n private retryLoad(): void {\n if (this.retrying()) return;\n this.retryRequests.next();\n }\n\n /** The retry button runs the load only while it is on offer. @internal */\n protected onLoadErrorClick(): void {\n if (this.retryOffered()) this.retryLoad();\n }\n\n selectOption(value: unknown): void {\n // The panel cannot open while read-only, but `selectOption` is reachable\n // from `WrSelectContext` — a projected `<wr-option>` calls it directly — so\n // the guard belongs on the write, not only on the way in.\n if (this.isReadonly()) return;\n if (this.isMulti()) {\n const current = this.asArray(this.value());\n const idx = current.indexOf(value);\n let next: readonly unknown[];\n if (idx >= 0) {\n next = [...current.slice(0, idx), ...current.slice(idx + 1)];\n } else {\n const cap = this.maxItems();\n if (cap > 0 && current.length >= cap) return;\n next = [...current, value];\n }\n this.value.set(next);\n this.touch.emit();\n // Keep the panel open in multi mode so the user can keep picking.\n return;\n }\n this.value.set(value);\n this.touch.emit();\n // A committed choice replaces the query, focus or no focus: the field goes\n // back to showing the selected label. The close-effect below deliberately\n // will not do it while the field is focused, which is right for a panel\n // that closed under `minChars` and wrong for one that closed on a pick.\n this.searchQuery.set('');\n this.open.set(false);\n }\n\n /**\n * Adds a `<wr-option>` to the registry and returns its unregister function.\n * Public only because `WrSelectContext` requires it: the one caller is the\n * option itself, through `WR_SELECT`, which is why `WrSelectOptionRegistration`\n * is not exported from `ngwr/select`. @internal\n */\n registerOption(reg: WrSelectOptionRegistration): () => void {\n this.registry.update(list => [...list, reg]);\n return () => this.registry.update(list => list.filter(o => o.id !== reg.id));\n }\n\n // Chip handlers (multi + tag)\n\n /**\n * Remove one selection (chip × button) BY POSITION. Works for multi and tag\n * modes.\n *\n * Positional, not by value: under `allowDuplicates` two chips carry the same\n * string, and a filter on equality deleted every copy at once — one click on\n * the second \"red\" took both reds with it. `visibleChips()` slices the HEAD\n * of `selectedChips()`, which maps the value array one for one, so the\n * `$index` a chip was rendered with indexes the value array directly. The\n * multi-mode toggle in `selectOption` was already positional.\n */\n protected removeChip(index: number, event: Event): void {\n event.stopPropagation();\n if (this.isDisabled() || this.isReadonly() || !this.hasChips()) return;\n const current = this.asArray(this.value());\n if (index < 0 || index >= current.length) return;\n this.value.set([...current.slice(0, index), ...current.slice(index + 1)]);\n this.touch.emit();\n }\n\n /** Clear every selection (× button). Multi/tag → empty array; search → null. */\n protected clearAll(event: Event): void {\n event.stopPropagation();\n if (this.isDisabled() || this.isReadonly()) return;\n if (this.hasChips()) {\n this.value.set([]);\n // `isSearchTrigger()`, not `isSearch()` — a searchable single renders the\n // same × and would otherwise fall through to the no-op below.\n } else if (this.isSearchTrigger()) {\n this.value.set(null);\n this.searchQuery.set('');\n } else {\n return;\n }\n this.touch.emit();\n }\n\n // Tag-mode draft handlers\n\n /** Capacity check used by tag mode to refuse the next add. */\n protected readonly atCapacity = computed(() => {\n const cap = this.maxItems();\n return cap > 0 && this.asArray(this.value()).length >= cap;\n });\n\n /**\n * Whether a multi select already holds `maxItems`, so an option it does not\n * hold cannot be added. The options read it to say so: they used to look and\n * announce as choosable and then ignore the click or Enter in silence.\n * @internal\n */\n readonly atMaxItems = computed(() => this.isMulti() && this.atCapacity());\n\n protected onTagInput(event: Event): void {\n if (this.isDisabled() || this.isReadonly()) return;\n this.draft.set((event.target as HTMLInputElement).value);\n }\n\n protected onTagKeydown(event: KeyboardEvent): void {\n if (this.isDisabled() || this.isReadonly()) return;\n const seps = this.separators();\n\n if (seps.includes(event.key)) {\n event.preventDefault();\n this.commitDraft();\n return;\n }\n\n if (event.key === 'Backspace' && this.draft() === '') {\n const chips = this.selectedChips();\n if (chips.length > 0) {\n event.preventDefault();\n this.removeChip(chips.length - 1, event);\n }\n }\n }\n\n protected onTagPaste(event: ClipboardEvent): void {\n if (this.isDisabled() || this.isReadonly()) return;\n const text = event.clipboardData?.getData('text') ?? '';\n if (!text) return;\n\n const seps = this.separators().filter(s => s !== 'Enter');\n if (seps.length === 0) return;\n\n event.preventDefault();\n // `-` has to be escaped too, and it is the one that bites: unescaped it\n // OPENS A RANGE inside the class. `[',', '-']` compiled to `/[,-\\n]+/` —\n // \"Range out of order\", a SyntaxError thrown after `preventDefault()`, so\n // the paste was dropped whole; `[',', '-', ';']` compiled without\n // complaint to a `,`–`;` range that swallowed every digit, shredding\n // `2024-01-02` into nothing. A lone `-` only worked because it landed\n // first in the class, where it is literal — position-dependent luck.\n const escaped = seps.map(s => s.replace(/[-.*+?^${}()|[\\]\\\\]/g, '\\\\$&')).join('');\n const splitRegex = new RegExp(`[${escaped}\\\\n]+`);\n for (const part of text.split(splitRegex)) this.tryAddTag(part);\n }\n\n protected onTagBlur(): void {\n if (this.draft().trim()) this.commitDraft();\n this.touch.emit();\n }\n\n private commitDraft(): void {\n const v = this.draft().trim();\n this.draft.set('');\n if (v) this.tryAddTag(v);\n }\n\n private tryAddTag(raw: string): void {\n if (!this.isTag() || this.atCapacity()) return;\n const value = raw.trim();\n if (!value) return;\n\n const existing = this.asArray(this.value()).map(String);\n if (!this.allowDuplicates() && existing.includes(value)) return;\n\n const validator = this.validate();\n if (validator && !validator(value, existing)) return;\n\n const next = [...existing, value];\n this.value.set(next);\n this.touch.emit();\n }\n\n // Template handlers\n\n protected onTriggerClick(): void {\n if (this.isDisabled() || this.isReadonly()) return;\n // Tag mode has no panel — clicks should land on the inline input,\n // not toggle an overlay that's never created.\n if (this.isTag()) return;\n this.open.update(v => !v);\n }\n\n protected onTriggerKey(event: KeyboardEvent): void {\n if (this.isDisabled() || this.isReadonly()) return;\n\n if (!this.open()) {\n if (event.key === 'Enter' || event.key === ' ' || event.key === 'ArrowDown' || event.key === 'ArrowUp') {\n event.preventDefault();\n this.seedActiveIndex();\n this.open.set(true);\n return;\n }\n // Multi mode: Backspace on closed trigger removes last chip. Tag\n // mode has its own input handler — never reaches this branch. A\n // searchable multi does, so only claim Backspace once its query is empty\n // — otherwise it would eat a chip and a character at once.\n if (\n event.key === 'Backspace' &&\n this.isMulti() &&\n this.hasSelection() &&\n (!this.hasChipSearch() || this.searchQuery() === '')\n ) {\n event.preventDefault();\n const chips = this.selectedChips();\n if (chips.length > 0) this.removeChip(chips.length - 1, event);\n }\n return;\n }\n\n // Open — navigation/selection.\n switch (event.key) {\n case 'Tab':\n // Let focus leave naturally — no `preventDefault` — but do not let the panel\n // outlive it. Nothing closed on Tab, so the listbox stayed on screen with a\n // live `aria-activedescendant` while the combobox no longer had focus: it can\n // cover the control that just took it (WCAG 2.4.11), and it keeps tracking a\n // trigger nobody is on, so a click aimed at what is underneath lands on an\n // option and commits into a select the user had already left. `wr-dropdown`\n // and `wr-context-menu` close on Tab for the same reason.\n //\n // Closing does NOT commit the active option. The cursor is SEEDED on open, so\n // tabbing straight through would select a row the user never looked at — and\n // in multi / search / freeText modes there is no single \"the option\" to take.\n this.open.set(false);\n break;\n case 'ArrowDown':\n event.preventDefault();\n this.moveActive(1);\n break;\n case 'ArrowUp':\n event.preventDefault();\n this.moveActive(-1);\n break;\n case 'Home':\n event.preventDefault();\n this.activeIndex.set(this.firstEnabled());\n this.ensureVisible(this.activeIndex());\n break;\n case 'End':\n event.preventDefault();\n this.activeIndex.set(this.lastEnabled());\n this.ensureVisible(this.activeIndex());\n break;\n case 'Enter':\n case ' ': {\n event.preventDefault();\n const idx = this.activeIndex();\n if (this.virtualActive()) {\n // Virtual rows aren't in the DOM to click — select the value directly.\n const list = this.filteredDynamicOptions();\n if (idx >= 0 && idx < list.length) this.selectOption(list[idx]);\n break;\n }\n const list = this.orderedRegistry();\n // Filtered-out options stay registered (they only self-hide via CSS), so\n // the hidden check is load-bearing: without it Enter can commit a row\n // that is not on screen.\n if (idx >= 0 && idx < list.length && !list[idx].disabled && !this.isOptionHidden(list[idx].label())) {\n const id = list[idx].id;\n const el = this.overlayRef?.overlayElement.querySelector<HTMLElement>(`#${CSS.escape(id)}`);\n el?.click();\n }\n break;\n }\n default:\n break;\n }\n }\n\n private seedActiveIndex(): void {\n if (this.virtualActive()) {\n const list = this.filteredDynamicOptions();\n const idx = list.findIndex(it => this.isSelected(it));\n this.activeIndex.set(idx >= 0 ? idx : this.firstEnabled());\n this.ensureVisible(this.activeIndex());\n return;\n }\n const list = this.orderedRegistry();\n let selectedIdx = -1;\n if (this.isMulti()) {\n const arr = this.asArray(this.value());\n if (arr.length > 0) selectedIdx = list.findIndex(o => o.value === arr[0]);\n } else {\n selectedIdx = list.findIndex(o => o.value === this.value());\n }\n this.activeIndex.set(selectedIdx >= 0 ? selectedIdx : this.firstEnabled());\n }\n\n private moveActive(delta: number): void {\n // Virtual rows are never disabled or hidden (the list is already filtered),\n // so navigation is a plain wrap plus a scroll-into-view.\n if (this.virtualActive()) {\n const len = this.filteredDynamicOptions().length;\n if (len === 0) return;\n const i = (this.activeIndex() + delta + len) % len;\n this.activeIndex.set(i);\n this.ensureVisible(i);\n return;\n }\n const list = this.orderedRegistry();\n if (list.length === 0) return;\n let i = this.activeIndex();\n let attempts = list.length;\n while (attempts-- > 0) {\n i = (i + delta + list.length) % list.length;\n const o = list[i];\n if (!o.disabled && !this.isOptionHidden(o.label())) {\n this.activeIndex.set(i);\n this.ensureVisible(i);\n return;\n }\n }\n }\n\n /**\n * Both scan `orderedRegistry`, and that is not interchangeable with\n * `registry`.\n *\n * They RETURN an index, and every reader of `activeIndex` — `activeOptionId`,\n * `moveActive`, `seedActiveIndex`, the Enter branch of `onTriggerKey` —\n * resolves it against DOM order. Scanning creation order here produced an\n * index into the other list: with projected `<wr-option>` children next to\n * `[options]` rows the two differ, so opening or searching left the cursor on\n * a row the user was not looking at, and Enter committed whatever happened to\n * sit at that position in DOM order — a filter-hidden option, which commits\n * nothing at all.\n */\n private firstEnabled(): number {\n if (this.virtualActive()) return this.filteredDynamicOptions().length > 0 ? 0 : -1;\n return this.orderedRegistry().findIndex(o => !o.disabled && !this.isOptionHidden(o.label()));\n }\n\n private lastEnabled(): number {\n if (this.virtualActive()) return this.filteredDynamicOptions().length - 1;\n const list = this.orderedRegistry();\n let found = -1;\n list.forEach((o, i) => {\n if (!o.disabled && !this.isOptionHidden(o.label())) found = i;\n });\n return found;\n }\n\n /** Coerce the multi-mode value into an array (tolerates a scalar or null write). */\n private asArray(value: unknown): readonly unknown[] {\n if (Array.isArray(value)) return value as readonly unknown[];\n if (value == null) return [];\n return [value];\n }\n\n // Overlay\n\n private openOverlay(): void {\n if (this.overlayRef) return;\n\n const positionStrategy = this.overlay\n .position()\n .flexibleConnectedTo(this.host)\n .withPositions([\n { originX: 'start', originY: 'bottom', overlayX: 'start', overlayY: 'top' },\n { originX: 'start', originY: 'top', overlayX: 'start', overlayY: 'bottom' },\n ])\n .withPush(true);\n\n this.overlayRef = this.overlay.create({\n positionStrategy,\n scrollStrategy: this.scrollStrategies.reposition(),\n // Floor the panel at the trigger width (it can still grow for long\n // options) instead of pinning it. The panel fills this via `width: 100%`,\n // so the flex overlay pane has no transparent gutter beside a\n // content-narrow panel — that gutter would otherwise sit \"inside\" the\n // overlay and swallow outside-clicks, leaving the panel open. Mirrors how\n // mat-select sizes its overlay.\n minWidth: this.host.nativeElement.getBoundingClientRect().width,\n panelClass: toClassList('wr-select-overlay', this.panelClass()),\n });\n\n // The CDK captured a direction STRING when this ref was created and never\n // looks again, so a flip while the list is open leaves the options\n // mirroring the wrong way.\n wrFollowDirection(this.overlayRef, this.dir, this.injector);\n\n const portal = new TemplatePortal(this.panelTpl(), this.vcr);\n this.overlayRef.attach(portal);\n\n // Seed the projected panel's scroll onto the cursor the same way the virtual\n // one is seeded from its own effect: opening a select whose selected option\n // is the 200th shows the cursor, not the top of the list. The virtual path\n // stays on its effect, which has to wait to MEASURE a row height this one\n // never needs.\n //\n // Twice, and both are needed. Synchronously, because `attachTemplatePortal`\n // appends the rows and calls `detectChanges()` before returning, and\n // `activeIndex` was seeded before `open()` flipped, so the row is in the DOM\n // and a panel of plain options lands on the cursor from the first frame.\n // Again after the next render, because that `detectChanges()` refreshes the\n // PORTAL's view and not the options: a projected `<wr-option>` belongs to the\n // consumer's view, so whatever it draws only while the panel is open — its\n // `wrOptionLeading` visual — lands a pass later and makes every row above the\n // cursor taller than it was measured. Measured with 38px avatar rows, the\n // cursor on the last of six sat 9px under the fold of a 90px panel, and the\n // error grows with each row above it. The second call is a no-op for a panel\n // whose rows did not move.\n if (!this.virtualActive()) {\n this.ensureVisible(this.activeIndex());\n afterNextRender(() => this.ensureVisible(this.activeIndex()), { injector: this.injector });\n }\n\n this.outsideClick\n .outsidePointerEvents(this.overlayRef)\n .pipe(takeUntilDestroyed(this.destroyRef))\n .subscribe(event => {\n if (this.host.nativeElement.contains(event.target as Node)) return;\n this.open.set(false);\n });\n\n this.overlayRef\n .keydownEvents()\n .pipe(takeUntilDestroyed(this.destroyRef))\n .subscribe(event => {\n if (event.key === 'Escape') {\n event.preventDefault();\n this.open.set(false);\n }\n });\n }\n\n private closeOverlay(): void {\n if (!this.overlayRef) return;\n this.overlayRef.dispose();\n this.overlayRef = null;\n }\n}\n","@if (isSearchTrigger()) {\n <!-- Search mode (or a searchable single): a real text input drives a filtered\n overlay panel. The wrapper isn't itself focusable — the input is the\n tabstop. -->\n <!-- eslint-disable-next-line @angular-eslint/template/click-events-have-key-events,@angular-eslint/template/interactive-supports-focus -->\n <div class=\"wr-select__trigger wr-select__trigger--search\" (click)=\"focusSearchInput()\">\n <!-- The selected option's leading visual, before the field — the same class\n and the same `placement: 'value'` the button trigger uses, because it is\n the same surface and a consumer who styled one should not have to learn\n a second name. `searchLeading()` draws it only while the field is\n showing the VALUE, so it never stands in front of a query or a bare\n placeholder, and it sits OUTSIDE the input for the obvious reason: an\n `<input>` holds a string. `aria-hidden` keeps it out of the combobox's\n name, which is `resolvedAriaLabel()`, and out of its value, which is the\n input's own text. -->\n @if (searchLeading(); as leading) {\n <span class=\"wr-select__value-leading\" aria-hidden=\"true\">\n <ng-container\n [ngTemplateOutlet]=\"leading\"\n [ngTemplateOutletContext]=\"{ $implicit: value(), placement: 'value' }\"\n />\n </span>\n }\n <!-- `id` / `aria-describedby` / `aria-invalid` come from a surrounding\n `<wr-form-field>` and are null without one — see `controlId` in the\n component. They go on the tab stop, the only labelable element here.\n `aria-label` is the trigger's name and belongs on the same element for\n the same reason: this input carries `role=\"combobox\"`, and the four\n other trigger shapes all bind `resolvedAriaLabel()`. Without it a\n search select with no placeholder rendered a combobox with no name at\n all — the one shape where the documented `ariaLabel` input reached\n nothing. -->\n <!-- `aria-autocomplete` is static, and `list` rather than `both`: the panel\n is the only place a suggestion appears, nothing is written back into\n the field for the user. It describes a permanent CAPABILITY, which is\n why it does not track `open()` — the same reasoning `wr-mention`\n records at its own host binding. -->\n <input\n #searchInput\n type=\"text\"\n role=\"combobox\"\n class=\"wr-select__search-input\"\n autocomplete=\"off\"\n spellcheck=\"false\"\n [attr.id]=\"controlId()\"\n [attr.aria-label]=\"nameLabel()\"\n [attr.aria-labelledby]=\"labelledBy()\"\n [attr.aria-describedby]=\"describedBy()\"\n [attr.aria-invalid]=\"ariaInvalid()\"\n [disabled]=\"isDisabled()\"\n [attr.aria-haspopup]=\"'listbox'\"\n aria-autocomplete=\"list\"\n [attr.aria-expanded]=\"open()\"\n [attr.aria-controls]=\"listboxId\"\n [attr.aria-activedescendant]=\"open() ? activeOptionId() || null : null\"\n [attr.aria-readonly]=\"isReadonly() || null\"\n [readonly]=\"isReadonly()\"\n [placeholder]=\"resolvedPlaceholder()\"\n [value]=\"searchDisplay()\"\n (input)=\"onSearchInput($event)\"\n (focus)=\"onSearchFocus()\"\n (keydown)=\"onSearchKey($event)\"\n (blur)=\"onSearchBlur()\"\n />\n <!-- Pointer-only, and the `keydown.enter` / `keydown.space` pair this used to\n carry was dead code rather than the keyboard path it looked like: the ×\n is `tabindex=\"-1\"` with no roving owner, so no key event ever originates\n here to bubble into a handler. It stays unfocusable because the same\n span sits inside the BUTTON trigger further down, where a focusable\n child is `nested-interactive` — the defect the window taskbar's close\n button already taught this repo. The keyboard reaches the function\n instead: Backspace on the empty field, which `onSearchKey` routes to\n `clearAll` for a single and to the last chip for a multi. -->\n @if (clearable() && hasSelection() && !isDisabled() && !isReadonly()) {\n <span\n class=\"wr-select__clear\"\n role=\"button\"\n [attr.aria-label]=\"resolvedClear()\"\n tabindex=\"-1\"\n (click)=\"clearAll($event)\"\n >\n <svg\n class=\"wr-icon__svg\"\n xmlns=\"http://www.w3.org/2000/svg\"\n viewBox=\"0 0 24 24\"\n fill=\"none\"\n stroke=\"currentColor\"\n stroke-width=\"2\"\n stroke-linecap=\"round\"\n stroke-linejoin=\"round\"\n aria-hidden=\"true\"\n >\n <path d=\"M18 6 6 18\" />\n <path d=\"m6 6 12 12\" />\n </svg>\n </span>\n }\n <svg\n class=\"wr-icon__svg wr-select__chevron\"\n xmlns=\"http://www.w3.org/2000/svg\"\n viewBox=\"0 0 24 24\"\n fill=\"none\"\n stroke=\"currentColor\"\n stroke-width=\"2\"\n stroke-linecap=\"round\"\n stroke-linejoin=\"round\"\n aria-hidden=\"true\"\n >\n <path d=\"m6 9 6 6 6-6\" />\n </svg>\n </div>\n} @else if (isTag() || hasChipSearch()) {\n <!-- Chip trigger — tag mode, or a searchable multi. A focusable input lives\n inside, so the wrapper itself only exists to host chips and forward\n whitespace clicks to the input. Tag mode needs no role (users tab\n straight into the input); the searchable multi is a real combobox, so it\n carries the listbox wiring. The click handler is a mouse-only\n convenience. -->\n <!-- eslint-disable-next-line @angular-eslint/template/click-events-have-key-events,@angular-eslint/template/interactive-supports-focus -->\n <div\n class=\"wr-select__trigger wr-select__trigger--tag\"\n [attr.aria-disabled]=\"isDisabled() || null\"\n (click)=\"focusTagInput()\"\n >\n <span class=\"wr-select__chips\">\n @for (chip of visibleChips(); track $index) {\n <span class=\"wr-select__chip\">\n @if (chip.leading; as leading) {\n <span class=\"wr-select__chip-leading\" aria-hidden=\"true\">\n <ng-container\n [ngTemplateOutlet]=\"leading\"\n [ngTemplateOutletContext]=\"{ $implicit: chip.value, placement: 'chip' }\"\n />\n </span>\n }\n <span class=\"wr-select__chip-label\">{{ chip.label }}</span>\n @if (!isReadonly()) {\n <span\n class=\"wr-select__chip-remove\"\n role=\"button\"\n [attr.aria-label]=\"chipRemoveLabel({ label: chip.label })\"\n tabindex=\"-1\"\n (click)=\"removeChip($index, $event)\"\n >\n <svg\n class=\"wr-icon__svg\"\n xmlns=\"http://www.w3.org/2000/svg\"\n viewBox=\"0 0 24 24\"\n fill=\"none\"\n stroke=\"currentColor\"\n stroke-width=\"2\"\n stroke-linecap=\"round\"\n stroke-linejoin=\"round\"\n aria-hidden=\"true\"\n >\n <path d=\"M18 6 6 18\" />\n <path d=\"m6 6 12 12\" />\n </svg>\n </span>\n }\n </span>\n }\n @if (hiddenChipCount(); as extra) {\n <span class=\"wr-select__chip wr-select__chip--more\">{{ moreLabel({ count: extra }) }}</span>\n }\n <!-- At `maxItems` this input goes READONLY, never disabled: it is the only\n tab stop in the whole control (the chip × and the clear button are\n `tabindex=\"-1\"` spans), so disabling it left a full tag select with\n nothing focusable at all — and Backspace on an empty draft, the one\n keyboard way back UNDER the cap, is bound to this very element. It was\n never needed as enforcement either: `tryAddTag` already refuses past\n capacity. -->\n <!-- `aria-autocomplete` is conditional here, unlike the search input's:\n this field is only a combobox when a panel backs it. In plain tag\n mode there is no popup to suggest from, and claiming otherwise\n describes a control that does not exist. -->\n <input\n #tagInput\n type=\"text\"\n class=\"wr-select__tag-input\"\n autocomplete=\"off\"\n [attr.id]=\"controlId()\"\n [attr.aria-label]=\"nameLabel()\"\n [attr.aria-labelledby]=\"labelledBy()\"\n [attr.aria-describedby]=\"describedBy()\"\n [attr.aria-invalid]=\"ariaInvalid()\"\n spellcheck=\"false\"\n [value]=\"hasChipSearch() ? searchQuery() : draft()\"\n [disabled]=\"isDisabled()\"\n [readonly]=\"isReadonly() || (isTag() && atCapacity())\"\n [attr.aria-readonly]=\"hasChipSearch() && isReadonly() ? true : null\"\n [placeholder]=\"hasSelection() ? '' : resolvedPlaceholder()\"\n [attr.role]=\"hasChipSearch() ? 'combobox' : null\"\n [attr.aria-haspopup]=\"hasChipSearch() ? 'listbox' : null\"\n [attr.aria-autocomplete]=\"hasChipSearch() ? 'list' : null\"\n [attr.aria-expanded]=\"hasChipSearch() ? open() : null\"\n [attr.aria-controls]=\"hasChipSearch() ? listboxId : null\"\n [attr.aria-activedescendant]=\"hasChipSearch() && open() ? activeOptionId() || null : null\"\n (input)=\"onChipsInput($event)\"\n (keydown)=\"onChipsKeydown($event)\"\n (paste)=\"onChipsPaste($event)\"\n (focus)=\"onChipsFocus()\"\n (blur)=\"onChipsBlur()\"\n />\n </span>\n\n @if (clearable() && hasSelection() && !isDisabled() && !isReadonly()) {\n <span\n class=\"wr-select__clear\"\n role=\"button\"\n [attr.aria-label]=\"resolvedClear()\"\n tabindex=\"-1\"\n (click)=\"clearAll($event)\"\n >\n <svg\n class=\"wr-icon__svg\"\n xmlns=\"http://www.w3.org/2000/svg\"\n viewBox=\"0 0 24 24\"\n fill=\"none\"\n stroke=\"currentColor\"\n stroke-width=\"2\"\n stroke-linecap=\"round\"\n stroke-linejoin=\"round\"\n aria-hidden=\"true\"\n >\n <path d=\"M18 6 6 18\" />\n <path d=\"m6 6 12 12\" />\n </svg>\n </span>\n }\n\n <!-- Only for the searchable MULTI, never for tag mode. The two share this\n trigger and differ in the one thing a chevron stands for: the searchable\n multi's input is a `role=\"combobox\"` with `aria-haspopup=\"listbox\"` and\n a panel of options behind it, while tag mode takes free text and has no\n popup at all. Folding the second into this branch left it as the only\n combobox shape in the component with no affordance saying it opens —\n `mode=\"search\"` has one, a searchable single has one, the button trigger\n has one, and this one rendered a bare field. -->\n @if (hasChipSearch()) {\n <svg\n class=\"wr-icon__svg wr-select__chevron\"\n xmlns=\"http://www.w3.org/2000/svg\"\n viewBox=\"0 0 24 24\"\n fill=\"none\"\n stroke=\"currentColor\"\n stroke-width=\"2\"\n stroke-linecap=\"round\"\n stroke-linejoin=\"round\"\n aria-hidden=\"true\"\n >\n <path d=\"m6 9 6 6 6-6\" />\n </svg>\n }\n </div>\n} @else {\n <button\n #trigger\n type=\"button\"\n class=\"wr-select__trigger\"\n role=\"combobox\"\n [attr.id]=\"controlId()\"\n [attr.aria-label]=\"nameLabel()\"\n [attr.aria-labelledby]=\"labelledBy()\"\n [attr.aria-describedby]=\"describedBy()\"\n [attr.aria-invalid]=\"ariaInvalid()\"\n [disabled]=\"isDisabled()\"\n [attr.aria-haspopup]=\"'listbox'\"\n [attr.aria-expanded]=\"open()\"\n [attr.aria-controls]=\"listboxId\"\n [attr.aria-activedescendant]=\"open() ? activeOptionId() || null : null\"\n [attr.aria-readonly]=\"isReadonly() || null\"\n (click)=\"onTriggerClick()\"\n (keydown)=\"onTriggerKey($event)\"\n (blur)=\"touch.emit()\"\n >\n @if (isMulti()) {\n @if (hasSelection()) {\n <span class=\"wr-select__chips\">\n @for (chip of visibleChips(); track $index) {\n <span class=\"wr-select__chip\">\n <!-- A selected chip draws its option's leading visual — one copy per\n VISIBLE chip, so `maxTagCount` caps these too. -->\n @if (chip.leading; as leading) {\n <span class=\"wr-select__chip-leading\" aria-hidden=\"true\">\n <ng-container\n [ngTemplateOutlet]=\"leading\"\n [ngTemplateOutletContext]=\"{ $implicit: chip.value, placement: 'chip' }\"\n />\n </span>\n }\n <span class=\"wr-select__chip-label\">{{ chip.label }}</span>\n @if (!isReadonly()) {\n <span\n class=\"wr-select__chip-remove\"\n role=\"button\"\n [attr.aria-label]=\"chipRemoveLabel({ label: chip.label })\"\n tabindex=\"-1\"\n (click)=\"removeChip($index, $event)\"\n >\n <svg\n class=\"wr-icon__svg\"\n xmlns=\"http://www.w3.org/2000/svg\"\n viewBox=\"0 0 24 24\"\n fill=\"none\"\n stroke=\"currentColor\"\n stroke-width=\"2\"\n stroke-linecap=\"round\"\n stroke-linejoin=\"round\"\n aria-hidden=\"true\"\n >\n <path d=\"M18 6 6 18\" />\n <path d=\"m6 6 12 12\" />\n </svg>\n </span>\n }\n </span>\n }\n @if (hiddenChipCount(); as extra) {\n <span class=\"wr-select__chip wr-select__chip--more\">{{ moreLabel({ count: extra }) }}</span>\n }\n </span>\n } @else {\n <span class=\"wr-select__placeholder\">{{ resolvedPlaceholder() }}</span>\n }\n } @else {\n @if (selectedLabel(); as label) {\n <!-- Beside the label, not inside it: the harness and the accessible name\n both read `.wr-select__value`, and the visual says nothing either should. -->\n @if (selectedLeading(); as leading) {\n <span class=\"wr-select__value-leading\" aria-hidden=\"true\">\n <ng-container\n [ngTemplateOutlet]=\"leading\"\n [ngTemplateOutletContext]=\"{ $implicit: value(), placement: 'value' }\"\n />\n </span>\n }\n <span class=\"wr-select__value\">{{ label }}</span>\n } @else {\n <span class=\"wr-select__placeholder\">{{ resolvedPlaceholder() }}</span>\n }\n }\n\n @if (isMulti() && clearable() && hasSelection() && !isDisabled() && !isReadonly()) {\n <span\n class=\"wr-select__clear\"\n role=\"button\"\n [attr.aria-label]=\"resolvedClear()\"\n tabindex=\"-1\"\n (click)=\"clearAll($event)\"\n >\n <svg\n class=\"wr-icon__svg\"\n xmlns=\"http://www.w3.org/2000/svg\"\n viewBox=\"0 0 24 24\"\n fill=\"none\"\n stroke=\"currentColor\"\n stroke-width=\"2\"\n stroke-linecap=\"round\"\n stroke-linejoin=\"round\"\n aria-hidden=\"true\"\n >\n <path d=\"M18 6 6 18\" />\n <path d=\"m6 6 12 12\" />\n </svg>\n </span>\n }\n\n <svg\n class=\"wr-icon__svg wr-select__chevron\"\n xmlns=\"http://www.w3.org/2000/svg\"\n viewBox=\"0 0 24 24\"\n fill=\"none\"\n stroke=\"currentColor\"\n stroke-width=\"2\"\n stroke-linecap=\"round\"\n stroke-linejoin=\"round\"\n aria-hidden=\"true\"\n >\n <path d=\"m6 9 6 6 6-6\" />\n </svg>\n </button>\n}\n\n<ng-template #panelTpl>\n <div\n class=\"wr-select-panel\"\n [class.wr-select-panel--sm]=\"size() === 'sm'\"\n [class.wr-select-panel--lg]=\"size() === 'lg'\"\n [class.wr-select-panel--virtual]=\"virtualActive()\"\n role=\"listbox\"\n [attr.id]=\"listboxId\"\n [attr.aria-multiselectable]=\"isMulti() ? 'true' : null\"\n [attr.aria-busy]=\"isLoading() ? 'true' : null\"\n >\n <!-- `aria-busy` belongs on the listbox, not on this row: it is the container\n whose required `option` children are temporarily missing, and a global\n ARIA attribute on a role-less child makes that child an owned element the\n listbox may not own (axe `aria-required-children`, critical). Plain text\n inside the listbox is fine — only ELEMENTS are checked. -->\n <!-- While the error row is up, through a retry, it carries the loader. -->\n @if (isLoading() && !showLoadError()) {\n <div class=\"wr-select-panel__loading\">{{ resolvedLoading() }}</div>\n }\n\n @if (virtualActive()) {\n <!-- Windowed data-array rows: plain role=\"option\" elements (not <wr-option>),\n navigated via the input's aria-activedescendant, selected by value. -->\n <div class=\"wr-select-panel__vlist\" [style.max-height]=\"resolvedViewportHeight()\">\n @if (virtualWindow().padTop > 0) {\n <div class=\"wr-select-panel__vspacer\" aria-hidden=\"true\" [style.height.px]=\"virtualWindow().padTop\"></div>\n }\n @for (entry of windowOptions(); track entry.index) {\n <!-- Keyboard handled by the search input via aria-activedescendant; the\n row is a pointer target only. -->\n <!-- eslint-disable-next-line @angular-eslint/template/click-events-have-key-events,@angular-eslint/template/interactive-supports-focus -->\n <div\n role=\"option\"\n class=\"wr-option\"\n [id]=\"virtualRowId(entry.index)\"\n [class.wr-option--active]=\"entry.index === activeIndex()\"\n [class.wr-option--selected]=\"isSelected(entry.item)\"\n [class.wr-option--disabled]=\"atMaxItems() && !isSelected(entry.item)\"\n [attr.aria-selected]=\"isSelected(entry.item)\"\n [attr.aria-disabled]=\"atMaxItems() && !isSelected(entry.item) ? true : null\"\n [attr.aria-setsize]=\"filteredDynamicOptions().length\"\n [attr.aria-posinset]=\"entry.index + 1\"\n (click)=\"selectOption(entry.item)\"\n >\n <!-- Only the select-wide template reaches a virtual row — there is no\n `<wr-option>` here to declare one — and only rows inside the\n rendered window instantiate it. -->\n @if (optionLeading(); as leading) {\n <span class=\"wr-option__leading\" aria-hidden=\"true\">\n <ng-container\n [ngTemplateOutlet]=\"leading\"\n [ngTemplateOutletContext]=\"{ $implicit: entry.item, placement: 'option' }\"\n />\n </span>\n }\n {{ displayWith()(entry.item) }}\n </div>\n }\n @if (virtualWindow().padBottom > 0) {\n <div class=\"wr-select-panel__vspacer\" aria-hidden=\"true\" [style.height.px]=\"virtualWindow().padBottom\"></div>\n }\n </div>\n } @else {\n <!-- Dynamic options from [options] or async [loader] (search mode).\n Rendered as wr-option so the standard registration / filter\n pipeline applies uniformly. -->\n @for (item of dynamicOptions(); track $index) {\n <wr-option [value]=\"item\">{{ displayWith()(item) }}</wr-option>\n }\n }\n\n <!-- Projected static options — always present (a conditional `<ng-content>`\n would drop projected content). Empty whenever `virtualActive`. -->\n <ng-content />\n\n <!-- A listbox may only own `option` and `group` children, and as a bare `<div>`\n this row was the only thing in the tree when it showed — an\n `aria-required-children` critical. It cannot move out of the listbox the\n way the command palette's does: this element IS the listbox, and the id\n the trigger's `aria-controls` names is what gives it its accessible name.\n So it announces as a disabled option instead. Keyboard navigation skips\n it for free — arrow keys walk the registered `wr-option`s, and nothing\n registers this row. -->\n @if (hasNoResults()) {\n <div class=\"wr-select-panel__empty\" role=\"option\" aria-selected=\"false\" aria-disabled=\"true\">\n {{ resolvedNoResults() }}\n </div>\n }\n\n <!-- A failed load, in place of \"no results\". An option for the same reason as\n that row. While it offers a retry it is the option that runs the loader\n again: the field's aria-activedescendant names it, Enter there reaches it,\n and mousedown keeps focus in the field. The retry is DRAWN as a button but\n cannot be one, since a button inside an option is nested interactive\n content; it wears `.wr-btn` and takes the click. -->\n @if (showLoadError()) {\n <div\n class=\"wr-select-panel__error\"\n [class.wr-select-panel__error--retryable]=\"retryOffered()\"\n [class.wr-select-panel__error--active]=\"retryOffered() && !freeText()\"\n role=\"option\"\n aria-selected=\"false\"\n [attr.id]=\"retryOffered() ? retryRowId : null\"\n [attr.aria-disabled]=\"retryOffered() ? null : true\"\n (mousedown)=\"$event.preventDefault()\"\n >\n @if (loadErrorTpl(); as custom) {\n <ng-container [ngTemplateOutlet]=\"custom.template\" [ngTemplateOutletContext]=\"loadErrorContext()\" />\n } @else {\n {{ resolvedLoadError() }}\n @if (retryOffered()) {\n <!-- The spinner as `wr-btn` draws it while loading: hidden from the\n accessibility tree, since the row already reads the retry label. -->\n <!-- eslint-disable-next-line @angular-eslint/template/click-events-have-key-events,@angular-eslint/template/interactive-supports-focus -->\n <span\n class=\"wr-btn wr-btn--sm wr-select-panel__retry\"\n [class.wr-btn--loading]=\"retrying()\"\n (click)=\"onLoadErrorClick()\"\n >\n @if (retrying()) {\n <wr-spinner class=\"wr-btn__spin\" size=\"sm\" aria-hidden=\"true\" />\n }\n <span class=\"wr-btn__label\">{{ resolvedRetry() }}</span>\n </span>\n }\n }\n </div>\n }\n </div>\n</ng-template>\n","/**\n * @license\n *\n * Use of this source code is governed by an MIT-style license that can be\n * found in the LICENSE file at https://github.com/thekhegay/ngwr/blob/main/LICENSE\n */\n\nimport { Component, ViewEncapsulation, input } from '@angular/core';\n\nimport { randomId } from 'ngwr/utils';\n\n/**\n * Visually groups options under a label inside a `<wr-select>`.\n *\n * @example\n * ```html\n * <wr-option-group label=\"Sizes\">\n * <wr-option value=\"sm\">Small</wr-option>\n * <wr-option value=\"md\">Medium</wr-option>\n * </wr-option-group>\n * ```\n */\n@Component({\n selector: 'wr-option-group',\n templateUrl: './option-group.html',\n encapsulation: ViewEncapsulation.None,\n host: { class: 'wr-option-group', role: 'group', '[attr.aria-labelledby]': 'labelId' },\n})\nexport class WrOptionGroup {\n /** Section heading shown above the options. */\n readonly label = input.required<string>();\n\n /**\n * `role=\"group\"` alone announces an unnamed group — the visible heading has to\n * be wired to it for the name to reach a screen reader.\n */\n protected readonly labelId = randomId('wr-option-group-label');\n}\n","<div class=\"wr-option-group__label\" [id]=\"labelId\">{{ label() }}</div>\n<ng-content />\n"],"mappings":"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"}
|