ngwr 14.2.0 → 14.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.
Files changed (120) hide show
  1. package/README.md +23 -22
  2. package/fesm2022/ngwr-calendar.mjs +4 -2
  3. package/fesm2022/ngwr-calendar.mjs.map +1 -1
  4. package/fesm2022/ngwr-event-calendar.mjs +17 -5
  5. package/fesm2022/ngwr-event-calendar.mjs.map +1 -1
  6. package/fesm2022/ngwr-form.mjs +30 -1
  7. package/fesm2022/ngwr-form.mjs.map +1 -1
  8. package/fesm2022/ngwr-i18n-ar.mjs +429 -0
  9. package/fesm2022/ngwr-i18n-ar.mjs.map +1 -0
  10. package/fesm2022/ngwr-i18n-cs.mjs +399 -0
  11. package/fesm2022/ngwr-i18n-cs.mjs.map +1 -0
  12. package/fesm2022/ngwr-i18n-de.mjs +418 -0
  13. package/fesm2022/ngwr-i18n-de.mjs.map +1 -0
  14. package/fesm2022/ngwr-i18n-en.mjs +23 -0
  15. package/fesm2022/ngwr-i18n-en.mjs.map +1 -1
  16. package/fesm2022/ngwr-i18n-es.mjs +399 -0
  17. package/fesm2022/ngwr-i18n-es.mjs.map +1 -0
  18. package/fesm2022/ngwr-i18n-fr.mjs +423 -0
  19. package/fesm2022/ngwr-i18n-fr.mjs.map +1 -0
  20. package/fesm2022/ngwr-i18n-he.mjs +422 -0
  21. package/fesm2022/ngwr-i18n-he.mjs.map +1 -0
  22. package/fesm2022/ngwr-i18n-hi.mjs +399 -0
  23. package/fesm2022/ngwr-i18n-hi.mjs.map +1 -0
  24. package/fesm2022/ngwr-i18n-id.mjs +399 -0
  25. package/fesm2022/ngwr-i18n-id.mjs.map +1 -0
  26. package/fesm2022/ngwr-i18n-it.mjs +418 -0
  27. package/fesm2022/ngwr-i18n-it.mjs.map +1 -0
  28. package/fesm2022/ngwr-i18n-ja.mjs +403 -0
  29. package/fesm2022/ngwr-i18n-ja.mjs.map +1 -0
  30. package/fesm2022/ngwr-i18n-ko.mjs +411 -0
  31. package/fesm2022/ngwr-i18n-ko.mjs.map +1 -0
  32. package/fesm2022/ngwr-i18n-nl.mjs +415 -0
  33. package/fesm2022/ngwr-i18n-nl.mjs.map +1 -0
  34. package/fesm2022/ngwr-i18n-pl.mjs +425 -0
  35. package/fesm2022/ngwr-i18n-pl.mjs.map +1 -0
  36. package/fesm2022/ngwr-i18n-pt.mjs +408 -0
  37. package/fesm2022/ngwr-i18n-pt.mjs.map +1 -0
  38. package/fesm2022/ngwr-i18n-ru.mjs +11 -0
  39. package/fesm2022/ngwr-i18n-ru.mjs.map +1 -1
  40. package/fesm2022/ngwr-i18n-sv.mjs +399 -0
  41. package/fesm2022/ngwr-i18n-sv.mjs.map +1 -0
  42. package/fesm2022/ngwr-i18n-tr.mjs +423 -0
  43. package/fesm2022/ngwr-i18n-tr.mjs.map +1 -0
  44. package/fesm2022/ngwr-i18n-uk.mjs +420 -0
  45. package/fesm2022/ngwr-i18n-uk.mjs.map +1 -0
  46. package/fesm2022/ngwr-i18n-vi.mjs +416 -0
  47. package/fesm2022/ngwr-i18n-vi.mjs.map +1 -0
  48. package/fesm2022/ngwr-i18n-zh-TW.mjs +407 -0
  49. package/fesm2022/ngwr-i18n-zh-TW.mjs.map +1 -0
  50. package/fesm2022/ngwr-i18n-zh.mjs +398 -0
  51. package/fesm2022/ngwr-i18n-zh.mjs.map +1 -0
  52. package/fesm2022/ngwr-line-chart.mjs +24 -4
  53. package/fesm2022/ngwr-line-chart.mjs.map +1 -1
  54. package/fesm2022/ngwr-pipes.mjs +75 -10
  55. package/fesm2022/ngwr-pipes.mjs.map +1 -1
  56. package/fesm2022/ngwr-schema-form.mjs +185 -0
  57. package/fesm2022/ngwr-schema-form.mjs.map +1 -0
  58. package/fesm2022/ngwr-select.mjs +2 -2
  59. package/fesm2022/ngwr-select.mjs.map +1 -1
  60. package/fesm2022/ngwr-validators.mjs +8 -1
  61. package/fesm2022/ngwr-validators.mjs.map +1 -1
  62. package/fesm2022/ngwr-version.mjs +1 -1
  63. package/fesm2022/ngwr-version.mjs.map +1 -1
  64. package/i18n/ar.json +389 -0
  65. package/i18n/cs.json +389 -0
  66. package/i18n/de.json +389 -0
  67. package/i18n/en.json +10 -2
  68. package/i18n/es.json +389 -0
  69. package/i18n/fr.json +389 -0
  70. package/i18n/he.json +389 -0
  71. package/i18n/hi.json +389 -0
  72. package/i18n/id.json +389 -0
  73. package/i18n/it.json +389 -0
  74. package/i18n/ja.json +389 -0
  75. package/i18n/ko.json +389 -0
  76. package/i18n/nl.json +389 -0
  77. package/i18n/pl.json +389 -0
  78. package/i18n/pt.json +389 -0
  79. package/i18n/ru.json +10 -2
  80. package/i18n/sv.json +389 -0
  81. package/i18n/tr.json +389 -0
  82. package/i18n/uk.json +389 -0
  83. package/i18n/vi.json +389 -0
  84. package/i18n/zh-TW.json +389 -0
  85. package/i18n/zh.json +389 -0
  86. package/llms-full.txt +87 -1
  87. package/llms.txt +1 -1
  88. package/package.json +89 -7
  89. package/schema-form/styles/_index.scss +15 -0
  90. package/schematics/use/symbol-map.json +1 -0
  91. package/skills/ngwr/SKILL.md +1 -1
  92. package/skills/ngwr/references/catalog.md +21 -0
  93. package/styles.scss +1 -0
  94. package/types/ngwr-calendar.d.ts +2 -0
  95. package/types/ngwr-event-calendar.d.ts +5 -0
  96. package/types/ngwr-form.d.ts +88 -2
  97. package/types/ngwr-i18n-ar.d.ts +6 -0
  98. package/types/ngwr-i18n-cs.d.ts +6 -0
  99. package/types/ngwr-i18n-de.d.ts +6 -0
  100. package/types/ngwr-i18n-es.d.ts +6 -0
  101. package/types/ngwr-i18n-fr.d.ts +6 -0
  102. package/types/ngwr-i18n-he.d.ts +6 -0
  103. package/types/ngwr-i18n-hi.d.ts +6 -0
  104. package/types/ngwr-i18n-id.d.ts +6 -0
  105. package/types/ngwr-i18n-it.d.ts +6 -0
  106. package/types/ngwr-i18n-ja.d.ts +6 -0
  107. package/types/ngwr-i18n-ko.d.ts +6 -0
  108. package/types/ngwr-i18n-nl.d.ts +6 -0
  109. package/types/ngwr-i18n-pl.d.ts +6 -0
  110. package/types/ngwr-i18n-pt.d.ts +6 -0
  111. package/types/ngwr-i18n-sv.d.ts +6 -0
  112. package/types/ngwr-i18n-tr.d.ts +6 -0
  113. package/types/ngwr-i18n-uk.d.ts +6 -0
  114. package/types/ngwr-i18n-vi.d.ts +6 -0
  115. package/types/ngwr-i18n-zh-TW.d.ts +6 -0
  116. package/types/ngwr-i18n-zh.d.ts +6 -0
  117. package/types/ngwr-line-chart.d.ts +15 -0
  118. package/types/ngwr-pipes.d.ts +45 -4
  119. package/types/ngwr-schema-form.d.ts +90 -0
  120. package/types/ngwr-version.d.ts +1 -1
@@ -1790,7 +1790,7 @@ class WrSelect {
1790
1790
  // eslint-disable-next-line @angular-eslint/no-forward-ref
1791
1791
  useExisting: forwardRef(() => WrSelect),
1792
1792
  },
1793
- ], queries: [{ propertyName: "projectedOptions", predicate: WrOption, descendants: true, isSignal: true }], viewQueries: [{ propertyName: "panelTpl", first: true, predicate: ["panelTpl"], descendants: true, read: TemplateRef, isSignal: true }, { propertyName: "tagInputEl", first: true, predicate: ["tagInput"], descendants: true, isSignal: true }, { propertyName: "searchInputEl", first: true, predicate: ["searchInput"], descendants: true, isSignal: true }], ngImport: i0, template: "@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 \u2014 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 <!-- `id` / `aria-describedby` / `aria-invalid` come from a surrounding\n `<wr-form-field>` and are null without one \u2014 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 \u2014 the one shape where the documented `ariaLabel` input reached\n nothing. -->\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]=\"resolvedAriaLabel()\"\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 [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 \u00D7\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` \u2014 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 \u2014 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 <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 \u00D7 and the clear button are\n `tabindex=\"-1\"` spans), so disabling it left a full tag select with\n nothing focusable at all \u2014 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 <input\n #tagInput\n type=\"text\"\n class=\"wr-select__tag-input\"\n autocomplete=\"off\"\n [attr.id]=\"controlId()\"\n [attr.aria-label]=\"resolvedAriaLabel()\"\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-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 </div>\n} @else {\n <button\n type=\"button\"\n class=\"wr-select__trigger\"\n role=\"combobox\"\n [attr.id]=\"controlId()\"\n [attr.aria-label]=\"resolvedAriaLabel()\"\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 <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 <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]=\"resolvedSize() === 'sm'\"\n [class.wr-select-panel--lg]=\"resolvedSize() === '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 \u2014 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 [attr.aria-selected]=\"isSelected(entry.item)\"\n [attr.aria-setsize]=\"filteredDynamicOptions().length\"\n [attr.aria-posinset]=\"entry.index + 1\"\n (click)=\"selectOption(entry.item)\"\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 \u2014 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 \u2014 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 \u2014 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", dependencies: [{ kind: "component", type: WrOption, selector: "wr-option", inputs: ["value", "disabled"] }], encapsulation: i0.ViewEncapsulation.None });
1793
+ ], queries: [{ propertyName: "projectedOptions", predicate: WrOption, descendants: true, isSignal: true }], viewQueries: [{ propertyName: "panelTpl", first: true, predicate: ["panelTpl"], descendants: true, read: TemplateRef, isSignal: true }, { propertyName: "tagInputEl", first: true, predicate: ["tagInput"], descendants: true, isSignal: true }, { propertyName: "searchInputEl", first: true, predicate: ["searchInput"], descendants: true, isSignal: true }], ngImport: i0, template: "@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 \u2014 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 <!-- `id` / `aria-describedby` / `aria-invalid` come from a surrounding\n `<wr-form-field>` and are null without one \u2014 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 \u2014 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()` \u2014 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]=\"resolvedAriaLabel()\"\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 \u00D7\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` \u2014 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 \u2014 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 <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 \u00D7 and the clear button are\n `tabindex=\"-1\"` spans), so disabling it left a full tag select with\n nothing focusable at all \u2014 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]=\"resolvedAriaLabel()\"\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 </div>\n} @else {\n <button\n type=\"button\"\n class=\"wr-select__trigger\"\n role=\"combobox\"\n [attr.id]=\"controlId()\"\n [attr.aria-label]=\"resolvedAriaLabel()\"\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 <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 <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]=\"resolvedSize() === 'sm'\"\n [class.wr-select-panel--lg]=\"resolvedSize() === '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 \u2014 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 [attr.aria-selected]=\"isSelected(entry.item)\"\n [attr.aria-setsize]=\"filteredDynamicOptions().length\"\n [attr.aria-posinset]=\"entry.index + 1\"\n (click)=\"selectOption(entry.item)\"\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 \u2014 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 \u2014 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 \u2014 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", dependencies: [{ kind: "component", type: WrOption, selector: "wr-option", inputs: ["value", "disabled"] }], encapsulation: i0.ViewEncapsulation.None });
1794
1794
  }
1795
1795
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.1.5", ngImport: i0, type: WrSelect, decorators: [{
1796
1796
  type: Component,
@@ -1800,7 +1800,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.1.5", ngImpor
1800
1800
  // eslint-disable-next-line @angular-eslint/no-forward-ref
1801
1801
  useExisting: forwardRef(() => WrSelect),
1802
1802
  },
1803
- ], template: "@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 \u2014 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 <!-- `id` / `aria-describedby` / `aria-invalid` come from a surrounding\n `<wr-form-field>` and are null without one \u2014 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 \u2014 the one shape where the documented `ariaLabel` input reached\n nothing. -->\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]=\"resolvedAriaLabel()\"\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 [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 \u00D7\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` \u2014 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 \u2014 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 <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 \u00D7 and the clear button are\n `tabindex=\"-1\"` spans), so disabling it left a full tag select with\n nothing focusable at all \u2014 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 <input\n #tagInput\n type=\"text\"\n class=\"wr-select__tag-input\"\n autocomplete=\"off\"\n [attr.id]=\"controlId()\"\n [attr.aria-label]=\"resolvedAriaLabel()\"\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-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 </div>\n} @else {\n <button\n type=\"button\"\n class=\"wr-select__trigger\"\n role=\"combobox\"\n [attr.id]=\"controlId()\"\n [attr.aria-label]=\"resolvedAriaLabel()\"\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 <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 <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]=\"resolvedSize() === 'sm'\"\n [class.wr-select-panel--lg]=\"resolvedSize() === '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 \u2014 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 [attr.aria-selected]=\"isSelected(entry.item)\"\n [attr.aria-setsize]=\"filteredDynamicOptions().length\"\n [attr.aria-posinset]=\"entry.index + 1\"\n (click)=\"selectOption(entry.item)\"\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 \u2014 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 \u2014 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 \u2014 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" }]
1803
+ ], template: "@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 \u2014 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 <!-- `id` / `aria-describedby` / `aria-invalid` come from a surrounding\n `<wr-form-field>` and are null without one \u2014 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 \u2014 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()` \u2014 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]=\"resolvedAriaLabel()\"\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 \u00D7\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` \u2014 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 \u2014 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 <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 \u00D7 and the clear button are\n `tabindex=\"-1\"` spans), so disabling it left a full tag select with\n nothing focusable at all \u2014 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]=\"resolvedAriaLabel()\"\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 </div>\n} @else {\n <button\n type=\"button\"\n class=\"wr-select__trigger\"\n role=\"combobox\"\n [attr.id]=\"controlId()\"\n [attr.aria-label]=\"resolvedAriaLabel()\"\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 <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 <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]=\"resolvedSize() === 'sm'\"\n [class.wr-select-panel--lg]=\"resolvedSize() === '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 \u2014 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 [attr.aria-selected]=\"isSelected(entry.item)\"\n [attr.aria-setsize]=\"filteredDynamicOptions().length\"\n [attr.aria-posinset]=\"entry.index + 1\"\n (click)=\"selectOption(entry.item)\"\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 \u2014 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 \u2014 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 \u2014 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" }]
1804
1804
  }], ctorParameters: () => [], propDecorators: { placeholder: [{ type: i0.Input, args: [{ isSignal: true, alias: "placeholder", required: false }] }], clearLabel: [{ type: i0.Input, args: [{ isSignal: true, alias: "clearLabel", required: false }] }], ariaLabel: [{ type: i0.Input, args: [{ isSignal: true, alias: "ariaLabel", required: false }] }], disabled: [{ type: i0.Input, args: [{ isSignal: true, alias: "disabled", required: false }] }], readonly: [{ type: i0.Input, args: [{ isSignal: true, alias: "readonly", required: false }] }], rounded: [{ type: i0.Input, args: [{ isSignal: true, alias: "rounded", required: false }] }], size: [{ type: i0.Input, args: [{ isSignal: true, alias: "size", required: false }] }], responsive: [{ type: i0.Input, args: [{ isSignal: true, alias: "responsive", required: false }] }], mode: [{ type: i0.Input, args: [{ isSignal: true, alias: "mode", required: false }] }], searchable: [{ type: i0.Input, args: [{ isSignal: true, alias: "searchable", required: false }] }], searchQuery: [{ type: i0.Input, args: [{ isSignal: true, alias: "searchQuery", required: false }] }, { type: i0.Output, args: ["searchQueryChange"] }], options: [{ type: i0.Input, args: [{ isSignal: true, alias: "options", required: false }] }], displayWith: [{ type: i0.Input, args: [{ isSignal: true, alias: "displayWith", required: false }] }], loader: [{ type: i0.Input, args: [{ isSignal: true, alias: "loader", required: false }] }], serverSearch: [{ type: i0.Input, args: [{ isSignal: true, alias: "serverSearch", required: false }] }], debounceMs: [{ type: i0.Input, args: [{ isSignal: true, alias: "debounceMs", required: false }] }], minChars: [{ type: i0.Input, args: [{ isSignal: true, alias: "minChars", required: false }] }], freeText: [{ type: i0.Input, args: [{ isSignal: true, alias: "freeText", required: false }] }], virtualScroll: [{ type: i0.Input, args: [{ isSignal: true, alias: "virtualScroll", required: false }] }], rowHeight: [{ type: i0.Input, args: [{ isSignal: true, alias: "rowHeight", required: false }] }], viewportHeight: [{ type: i0.Input, args: [{ isSignal: true, alias: "viewportHeight", required: false }] }], overscan: [{ type: i0.Input, args: [{ isSignal: true, alias: "overscan", required: false }] }], noResultsText: [{ type: i0.Input, args: [{ isSignal: true, alias: "noResultsText", required: false }] }], loadingText: [{ type: i0.Input, args: [{ isSignal: true, alias: "loadingText", required: false }] }], searchChange: [{ type: i0.Output, args: ["searchChange"] }], loading: [{ type: i0.Input, args: [{ isSignal: true, alias: "loading", required: false }] }], separators: [{ type: i0.Input, args: [{ isSignal: true, alias: "separators", required: false }] }], allowDuplicates: [{ type: i0.Input, args: [{ isSignal: true, alias: "allowDuplicates", required: false }] }], validate: [{ type: i0.Input, args: [{ isSignal: true, alias: "validate", required: false }] }], clearable: [{ type: i0.Input, args: [{ isSignal: true, alias: "clearable", required: false }] }], maxItems: [{ type: i0.Input, args: [{ isSignal: true, alias: "maxItems", required: false }] }], maxTagCount: [{ type: i0.Input, args: [{ isSignal: true, alias: "maxTagCount", required: false }] }], value: [{ type: i0.Input, args: [{ isSignal: true, alias: "value", required: false }] }, { type: i0.Output, args: ["valueChange"] }], touch: [{ type: i0.Output, args: ["touch"] }], projectedOptions: [{ type: i0.ContentChildren, args: [i0.forwardRef(() => WrOption), { ...{ descendants: true }, isSignal: true }] }], panelTpl: [{ type: i0.ViewChild, args: ['panelTpl', { ...{ read: TemplateRef }, isSignal: true }] }], tagInputEl: [{ type: i0.ViewChild, args: ['tagInput', { isSignal: true }] }], searchInputEl: [{ type: i0.ViewChild, args: ['searchInput', { isSignal: true }] }] } });
1805
1805
 
1806
1806
  /**