@koobiq/components 20.2.0 → 20.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 (212) hide show
  1. package/accordion/_accordion-theme.scss +5 -1
  2. package/accordion/accordion-tokens.scss +2 -0
  3. package/accordion/accordion-trigger.scss +6 -0
  4. package/accordion/accordion.scss +21 -0
  5. package/accordion/index.d.ts +55 -8
  6. package/actions-panel/index.d.ts +25 -13
  7. package/app-switcher/app-switcher-dropdown-app.scss +7 -5
  8. package/app-switcher/app-switcher-dropdown-site.scss +6 -4
  9. package/app-switcher/index.d.ts +41 -4
  10. package/app-switcher/kbq-app-switcher-list-item.scss +6 -8
  11. package/autocomplete/index.d.ts +24 -9
  12. package/breadcrumbs/index.d.ts +1 -1
  13. package/button/index.d.ts +2 -2
  14. package/button-toggle/button-toggle-tokens.scss +2 -0
  15. package/button-toggle/button-toggle.scss +9 -0
  16. package/button-toggle/index.d.ts +5 -0
  17. package/checkbox/index.d.ts +33 -29
  18. package/clamped-text/index.d.ts +1 -1
  19. package/code-block/index.d.ts +24 -19
  20. package/content-panel/index.d.ts +1 -1
  21. package/core/index.d.ts +1125 -199
  22. package/core/option/_action-container-mixins.scss +28 -0
  23. package/core/option/_option-theme.scss +24 -0
  24. package/core/option/action.scss +7 -0
  25. package/core/styles/_koobiq-theme.scss +2 -0
  26. package/core/styles/_tokens.scss +1 -0
  27. package/core/styles/common/_connected-overlay.scss +6 -3
  28. package/core/styles/common/_select.scss +12 -0
  29. package/core/styles/common/_tokens.scss +0 -9
  30. package/core/styles/theming/_index.scss +0 -1
  31. package/core/styles/theming/_theming.scss +34 -5
  32. package/datepicker/index.d.ts +46 -15
  33. package/dl/dl.scss +26 -0
  34. package/dl/index.d.ts +8 -1
  35. package/dropdown/_dropdown-theme.scss +28 -2
  36. package/dropdown/dropdown-item.scss +13 -0
  37. package/dropdown/dropdown.scss +7 -1
  38. package/dropdown/index.d.ts +264 -17
  39. package/dynamic-translation/index.d.ts +1 -1
  40. package/fesm2022/koobiq-components-accordion.mjs +106 -46
  41. package/fesm2022/koobiq-components-accordion.mjs.map +1 -1
  42. package/fesm2022/koobiq-components-actions-panel.mjs +57 -46
  43. package/fesm2022/koobiq-components-actions-panel.mjs.map +1 -1
  44. package/fesm2022/koobiq-components-alert.mjs +16 -16
  45. package/fesm2022/koobiq-components-app-switcher.mjs +233 -38
  46. package/fesm2022/koobiq-components-app-switcher.mjs.map +1 -1
  47. package/fesm2022/koobiq-components-autocomplete.mjs +54 -31
  48. package/fesm2022/koobiq-components-autocomplete.mjs.map +1 -1
  49. package/fesm2022/koobiq-components-badge.mjs +13 -13
  50. package/fesm2022/koobiq-components-breadcrumbs.mjs +25 -25
  51. package/fesm2022/koobiq-components-breadcrumbs.mjs.map +1 -1
  52. package/fesm2022/koobiq-components-button-toggle.mjs +17 -12
  53. package/fesm2022/koobiq-components-button-toggle.mjs.map +1 -1
  54. package/fesm2022/koobiq-components-button.mjs +25 -25
  55. package/fesm2022/koobiq-components-checkbox.mjs +69 -92
  56. package/fesm2022/koobiq-components-checkbox.mjs.map +1 -1
  57. package/fesm2022/koobiq-components-clamped-text.mjs +13 -13
  58. package/fesm2022/koobiq-components-code-block.mjs +56 -69
  59. package/fesm2022/koobiq-components-code-block.mjs.map +1 -1
  60. package/fesm2022/koobiq-components-content-panel.mjs +29 -29
  61. package/fesm2022/koobiq-components-core.mjs +2445 -789
  62. package/fesm2022/koobiq-components-core.mjs.map +1 -1
  63. package/fesm2022/koobiq-components-datepicker.mjs +160 -121
  64. package/fesm2022/koobiq-components-datepicker.mjs.map +1 -1
  65. package/fesm2022/koobiq-components-divider.mjs +7 -7
  66. package/fesm2022/koobiq-components-dl.mjs +23 -15
  67. package/fesm2022/koobiq-components-dl.mjs.map +1 -1
  68. package/fesm2022/koobiq-components-dropdown.mjs +754 -155
  69. package/fesm2022/koobiq-components-dropdown.mjs.map +1 -1
  70. package/fesm2022/koobiq-components-dynamic-translation.mjs +13 -13
  71. package/fesm2022/koobiq-components-ellipsis-center.mjs +7 -7
  72. package/fesm2022/koobiq-components-empty-state.mjs +19 -19
  73. package/fesm2022/koobiq-components-file-upload.mjs +74 -42
  74. package/fesm2022/koobiq-components-file-upload.mjs.map +1 -1
  75. package/fesm2022/koobiq-components-filter-bar.mjs +605 -192
  76. package/fesm2022/koobiq-components-filter-bar.mjs.map +1 -1
  77. package/fesm2022/koobiq-components-flag.mjs +7 -7
  78. package/fesm2022/koobiq-components-form-field.mjs +346 -158
  79. package/fesm2022/koobiq-components-form-field.mjs.map +1 -1
  80. package/fesm2022/koobiq-components-icon.mjs +39 -21
  81. package/fesm2022/koobiq-components-icon.mjs.map +1 -1
  82. package/fesm2022/koobiq-components-inline-edit.mjs +172 -27
  83. package/fesm2022/koobiq-components-inline-edit.mjs.map +1 -1
  84. package/fesm2022/koobiq-components-input.mjs +41 -24
  85. package/fesm2022/koobiq-components-input.mjs.map +1 -1
  86. package/fesm2022/koobiq-components-link.mjs +8 -8
  87. package/fesm2022/koobiq-components-list.mjs +657 -143
  88. package/fesm2022/koobiq-components-list.mjs.map +1 -1
  89. package/fesm2022/koobiq-components-loader-overlay.mjs +16 -16
  90. package/fesm2022/koobiq-components-markdown.mjs +14 -11
  91. package/fesm2022/koobiq-components-markdown.mjs.map +1 -1
  92. package/fesm2022/koobiq-components-modal.mjs +59 -35
  93. package/fesm2022/koobiq-components-modal.mjs.map +1 -1
  94. package/fesm2022/koobiq-components-navbar.mjs +69 -54
  95. package/fesm2022/koobiq-components-navbar.mjs.map +1 -1
  96. package/fesm2022/koobiq-components-notification-center.mjs +23 -22
  97. package/fesm2022/koobiq-components-notification-center.mjs.map +1 -1
  98. package/fesm2022/koobiq-components-overflow-items.mjs +16 -17
  99. package/fesm2022/koobiq-components-overflow-items.mjs.map +1 -1
  100. package/fesm2022/koobiq-components-popover.mjs +26 -21
  101. package/fesm2022/koobiq-components-popover.mjs.map +1 -1
  102. package/fesm2022/koobiq-components-progress-bar.mjs +13 -13
  103. package/fesm2022/koobiq-components-progress-spinner.mjs +13 -13
  104. package/fesm2022/koobiq-components-radio.mjs +10 -10
  105. package/fesm2022/koobiq-components-resizer.mjs +33 -14
  106. package/fesm2022/koobiq-components-resizer.mjs.map +1 -1
  107. package/fesm2022/koobiq-components-scrollbar.mjs +10 -10
  108. package/fesm2022/koobiq-components-search-expandable.mjs +7 -7
  109. package/fesm2022/koobiq-components-search-expandable.mjs.map +1 -1
  110. package/fesm2022/koobiq-components-select.mjs +419 -106
  111. package/fesm2022/koobiq-components-select.mjs.map +1 -1
  112. package/fesm2022/koobiq-components-sidebar.mjs +14 -14
  113. package/fesm2022/koobiq-components-sidepanel.mjs +26 -26
  114. package/fesm2022/koobiq-components-skeleton.mjs +10 -10
  115. package/fesm2022/koobiq-components-split-button.mjs +7 -7
  116. package/fesm2022/koobiq-components-splitter.mjs +17 -17
  117. package/fesm2022/koobiq-components-table.mjs +15 -13
  118. package/fesm2022/koobiq-components-table.mjs.map +1 -1
  119. package/fesm2022/koobiq-components-tabs.mjs +54 -54
  120. package/fesm2022/koobiq-components-tabs.mjs.map +1 -1
  121. package/fesm2022/koobiq-components-tags.mjs +283 -122
  122. package/fesm2022/koobiq-components-tags.mjs.map +1 -1
  123. package/fesm2022/koobiq-components-textarea.mjs +13 -8
  124. package/fesm2022/koobiq-components-textarea.mjs.map +1 -1
  125. package/fesm2022/koobiq-components-time-range.mjs +29 -24
  126. package/fesm2022/koobiq-components-time-range.mjs.map +1 -1
  127. package/fesm2022/koobiq-components-timepicker.mjs +58 -26
  128. package/fesm2022/koobiq-components-timepicker.mjs.map +1 -1
  129. package/fesm2022/koobiq-components-timezone.mjs +76 -39
  130. package/fesm2022/koobiq-components-timezone.mjs.map +1 -1
  131. package/fesm2022/koobiq-components-title.mjs +7 -7
  132. package/fesm2022/koobiq-components-toast.mjs +51 -26
  133. package/fesm2022/koobiq-components-toast.mjs.map +1 -1
  134. package/fesm2022/koobiq-components-toggle.mjs +72 -64
  135. package/fesm2022/koobiq-components-toggle.mjs.map +1 -1
  136. package/fesm2022/koobiq-components-tooltip.mjs +115 -36
  137. package/fesm2022/koobiq-components-tooltip.mjs.map +1 -1
  138. package/fesm2022/koobiq-components-top-bar.mjs +13 -13
  139. package/fesm2022/koobiq-components-tree-select.mjs +189 -55
  140. package/fesm2022/koobiq-components-tree-select.mjs.map +1 -1
  141. package/fesm2022/koobiq-components-tree.mjs +302 -81
  142. package/fesm2022/koobiq-components-tree.mjs.map +1 -1
  143. package/fesm2022/koobiq-components-username.mjs +27 -27
  144. package/file-upload/index.d.ts +25 -6
  145. package/file-upload/multiple-file-upload.component.scss +14 -0
  146. package/filter-bar/_filter-bar-theme.scss +0 -6
  147. package/filter-bar/index.d.ts +222 -9
  148. package/filter-bar/pipes/pipe-multi-tree-select.scss +0 -6
  149. package/filter-bar/pipes/pipe-multiselect.scss +0 -6
  150. package/filter-bar/pipes/pipe-tree-select.scss +0 -6
  151. package/form-field/_form-field-theme.scss +76 -20
  152. package/form-field/fieldset.scss +10 -0
  153. package/form-field/form-field-tokens.scss +15 -1
  154. package/form-field/form-field.scss +15 -19
  155. package/form-field/index.d.ts +147 -65
  156. package/icon/index.d.ts +31 -6
  157. package/inline-edit/index.d.ts +57 -4
  158. package/inline-edit/inline-edit.scss +10 -0
  159. package/input/index.d.ts +17 -2
  160. package/list/_list-theme.scss +42 -10
  161. package/list/index.d.ts +326 -79
  162. package/list/list-tokens.scss +43 -8
  163. package/list/list.scss +186 -12
  164. package/markdown/index.d.ts +1 -1
  165. package/modal/index.d.ts +21 -4
  166. package/modal/modal-tokens.scss +1 -1
  167. package/navbar/index.d.ts +16 -1
  168. package/navbar/navbar-brand.scss +6 -0
  169. package/navbar/vertical-navbar.scss +6 -0
  170. package/notification-center/notification-item.scss +6 -0
  171. package/package.json +3 -6
  172. package/popover/index.d.ts +2 -2
  173. package/prebuilt-themes/dark-theme.css +1 -1
  174. package/prebuilt-themes/light-theme.css +1 -1
  175. package/prebuilt-themes/theme.css +1 -1
  176. package/resizer/index.d.ts +12 -0
  177. package/schematics/migrations/deprecated-icons/README.md +29 -4
  178. package/schematics/migrations/deprecated-icons/data.js +7 -0
  179. package/schematics/migrations/deprecated-icons/index.js +62 -35
  180. package/schematics/migrations/new-icons-pack/README.md +37 -2
  181. package/schematics/migrations/new-icons-pack/data.js +8 -0
  182. package/schematics/migrations/new-icons-pack/index.js +144 -53
  183. package/schematics/ng-add/index.js +3 -3
  184. package/schematics/utils/angular-parsing.js +30 -12
  185. package/schematics/utils/ast.js +31 -0
  186. package/schematics/utils/icon-migration.js +530 -0
  187. package/schematics/utils/typescript.js +44 -0
  188. package/scrollbar/index.d.ts +1 -1
  189. package/select/index.d.ts +163 -18
  190. package/select/select-tokens.scss +0 -1
  191. package/select/select.scss +0 -2
  192. package/splitter/index.d.ts +1 -1
  193. package/table/_table-theme.scss +4 -0
  194. package/table/index.d.ts +2 -1
  195. package/table/table.scss +8 -0
  196. package/tags/index.d.ts +128 -29
  197. package/textarea/index.d.ts +5 -0
  198. package/time-range/index.d.ts +1 -1
  199. package/timepicker/index.d.ts +4 -0
  200. package/timezone/index.d.ts +9 -5
  201. package/toast/index.d.ts +26 -3
  202. package/toggle/index.d.ts +34 -14
  203. package/tooltip/index.d.ts +54 -11
  204. package/tree/_tree-theme.scss +25 -5
  205. package/tree/index.d.ts +71 -3
  206. package/tree/tree-option.scss +2 -8
  207. package/tree-select/_tree-select-theme.scss +22 -0
  208. package/tree-select/index.d.ts +83 -16
  209. package/core/styles/_tokens.kbq.import.scss +0 -4
  210. package/core/styles/theming/_components-theming.scss +0 -1927
  211. package/filter-bar/pipes/pipe-select.scss +0 -5
  212. package/overflow-items/overflow-items.scss +0 -20
@@ -1,19 +1,20 @@
1
- import { trigger, state, transition, style, animate, group, query } from '@angular/animations';
1
+ import { trigger, state, style, transition, animate, group, query } from '@angular/animations';
2
2
  import { TemplatePortal, DomPortalOutlet } from '@angular/cdk/portal';
3
3
  import { DOCUMENT } from '@angular/common';
4
4
  import * as i0 from '@angular/core';
5
- import { inject, TemplateRef, ApplicationRef, Injector, ViewContainerRef, Directive, InjectionToken, ElementRef, input, booleanAttribute, Input, ContentChild, ViewChild, ViewEncapsulation, ChangeDetectionStrategy, Component, NgZone, contentChild, computed, numberAttribute, EventEmitter, QueryList, Output, ContentChildren, ChangeDetectorRef, Renderer2, output, NgModule } from '@angular/core';
6
- import { Subject, Subscription, merge, of, asapScheduler } from 'rxjs';
5
+ import { inject, TemplateRef, ApplicationRef, Injector, ViewContainerRef, Directive, InjectionToken, ElementRef, effect, contentChild, input, booleanAttribute, signal, Input, ContentChild, ViewChild, ViewEncapsulation, ChangeDetectionStrategy, Component, NgZone, DestroyRef, contentChildren, computed, numberAttribute, EventEmitter, QueryList, untracked, Output, ContentChildren, ChangeDetectorRef, Renderer2, output, NgModule } from '@angular/core';
6
+ import { Subject, Subscription, merge, timer, of, asapScheduler } from 'rxjs';
7
7
  import { FocusMonitor } from '@angular/cdk/a11y';
8
- import { KBQ_PANEL_DEFAULT_MIN_WIDTH, KbqComponentColors, KBQ_TITLE_TEXT_REF, FocusKeyManager, RIGHT_ARROW, LEFT_ARROW, ESCAPE, ENTER, SPACE, DOWN_ARROW as DOWN_ARROW$1, defaultOffsetY, kbqResolvePanelWidth, kbqGetPanelWidthOrigin } from '@koobiq/components/core';
8
+ import { TAB, UP_ARROW, DOWN_ARROW, ENTER } from '@angular/cdk/keycodes';
9
+ import { KBQ_PANEL_DEFAULT_MIN_WIDTH, KbqComponentColors, KBQ_TITLE_TEXT_REF, ESCAPE, LEFT_ARROW, RIGHT_ARROW, isPointInRect, isPointInTriangle, ActiveDescendantKeyManager, FocusKeyManager, getSafeTriangleVertices, ENTER as ENTER$1, SPACE, DOWN_ARROW as DOWN_ARROW$1, defaultOffsetY, kbqResolvePanelWidth, kbqGetPanelWidthOrigin, kbqSiblingPopupProvider } from '@koobiq/components/core';
9
10
  import { KbqIcon, KbqIconModule } from '@koobiq/components/icon';
11
+ import { KBQ_FORM_FIELD, KBQ_FORM_FIELD_DEFAULT_OPTIONS, KbqFormField } from '@koobiq/components/form-field';
10
12
  import { Directionality } from '@angular/cdk/bidi';
11
13
  import { Overlay, OverlayContainer, OverlayConfig, OverlayModule } from '@angular/cdk/overlay';
12
14
  import { normalizePassiveListenerOptions, Platform } from '@angular/cdk/platform';
13
- import { startWith, switchMap, take, filter, takeUntil, delay } from 'rxjs/operators';
15
+ import { takeUntilDestroyed, outputToObservable } from '@angular/core/rxjs-interop';
16
+ import { take, startWith, switchMap, filter, delay, map, takeUntil } from 'rxjs/operators';
14
17
  import { coerceBooleanProperty } from '@angular/cdk/coercion';
15
- import { UP_ARROW, DOWN_ARROW } from '@angular/cdk/keycodes';
16
- import { KbqFormField } from '@koobiq/components/form-field';
17
18
 
18
19
  /**
19
20
  * Animations used by the kbq-dropdown component.
@@ -100,10 +101,10 @@ class KbqDropdownContent {
100
101
  ngOnDestroy() {
101
102
  this.outlet?.dispose();
102
103
  }
103
- /** @nocollapse */ static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.25", ngImport: i0, type: KbqDropdownContent, deps: [], target: i0.ɵɵFactoryTarget.Directive }); }
104
- /** @nocollapse */ static { this.ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "14.0.0", version: "20.3.25", type: KbqDropdownContent, isStandalone: true, selector: "ng-template[kbqDropdownContent]", ngImport: i0 }); }
104
+ /** @nocollapse */ static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.30", ngImport: i0, type: KbqDropdownContent, deps: [], target: i0.ɵɵFactoryTarget.Directive }); }
105
+ /** @nocollapse */ static { this.ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "14.0.0", version: "20.3.30", type: KbqDropdownContent, isStandalone: true, selector: "ng-template[kbqDropdownContent]", ngImport: i0 }); }
105
106
  }
106
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.25", ngImport: i0, type: KbqDropdownContent, decorators: [{
107
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.30", ngImport: i0, type: KbqDropdownContent, decorators: [{
107
108
  type: Directive,
108
109
  args: [{
109
110
  selector: 'ng-template[kbqDropdownContent]'
@@ -138,6 +139,99 @@ function throwKbqDropdownInvalidPositionY() {
138
139
  throw Error(`yPosition value must be either 'above' or below'.
139
140
  Example: <kbq-dropdown [yPosition]="'above'" #dropdown="kbqDropdown"></kbq-dropdown>`);
140
141
  }
142
+ /**
143
+ * Throws an exception for the case when `kbqDropdownSearch` is applied to a form field that doesn't
144
+ * host a `kbqInput`.
145
+ * @docs-private
146
+ */
147
+ function throwKbqDropdownSearchMissingInputError() {
148
+ throw Error(`kbqDropdownSearch: must be applied to a kbq-form-field containing an input[kbqInput].
149
+ Example:
150
+ <kbq-form-field kbqDropdownSearch>
151
+ <input kbqInput [formControl]="control" />
152
+ </kbq-form-field>`);
153
+ }
154
+ /**
155
+ * Throws an exception for the case when `kbqDropdownSearch`'s input isn't bound to a form control, so
156
+ * there is no query to react to.
157
+ * @docs-private
158
+ */
159
+ function throwKbqDropdownSearchMissingNgControlError() {
160
+ throw Error(`kbqDropdownSearch: the input must be bound to a form control.
161
+ Example:
162
+ <kbq-form-field kbqDropdownSearch>
163
+ <input kbqInput [formControl]="control" />
164
+ </kbq-form-field>`);
165
+ }
166
+
167
+ /** @docs-private */
168
+ const KBQ_DROPDOWN_ITEM_ACTION_HOST = new InjectionToken('kbqDropdownItemAction-host');
169
+ /**
170
+ * Marks a secondary, independently-focusable/clickable element (e.g. a settings link) projected
171
+ * inside a `kbq-dropdown-item` alongside the item's own primary action. Requires the item's host
172
+ * element to be non-interactive (e.g. `<div kbq-dropdown-item>`), since interactive content
173
+ * cannot validly nest inside another interactive element.
174
+ */
175
+ class KbqDropdownItemAction {
176
+ constructor() {
177
+ this.elementRef = inject(ElementRef);
178
+ this.dropdownItem = inject(KBQ_DROPDOWN_ITEM_ACTION_HOST);
179
+ /**
180
+ * The `tabindex` this element had before `isInactive()` first forced it to `-1`, so it can be
181
+ * restored instead of left removed. Plain `[attr.tabindex]` can't do this: co-located host
182
+ * bindings for the same attribute (e.g. `KbqIconButton`'s own `tabindex`) apply in directive
183
+ * order and the last one always wins outright, so writing `null` here on the active branch
184
+ * would strip whatever tabindex the host component set, not just leave it alone.
185
+ */
186
+ this.originalTabindex = null;
187
+ effect(() => {
188
+ const el = this.elementRef.nativeElement;
189
+ if (this.isInactive()) {
190
+ if (this.originalTabindex === null)
191
+ this.originalTabindex = el.getAttribute('tabindex');
192
+ el.setAttribute('tabindex', '-1');
193
+ }
194
+ else if (this.originalTabindex !== null) {
195
+ el.setAttribute('tabindex', this.originalTabindex);
196
+ this.originalTabindex = null;
197
+ }
198
+ });
199
+ }
200
+ /** Returns the host DOM element. */
201
+ getHostElement() {
202
+ return this.elementRef.nativeElement;
203
+ }
204
+ /** `progress` takes priority over the action, same as `disabled`. */
205
+ isInactive() {
206
+ return this.dropdownItem.disabled || this.dropdownItem.progress();
207
+ }
208
+ /**
209
+ * Always stops the click from bubbling to the item's own primary click handler.
210
+ * Additionally, blocks the action's own default behavior when the parent item is
211
+ * disabled/loading — `<a>` has no native `disabled`.
212
+ */
213
+ onClick(event) {
214
+ event.stopPropagation();
215
+ if (this.isInactive()) {
216
+ event.preventDefault();
217
+ event.stopImmediatePropagation();
218
+ }
219
+ }
220
+ /** @nocollapse */ static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.30", ngImport: i0, type: KbqDropdownItemAction, deps: [], target: i0.ɵɵFactoryTarget.Directive }); }
221
+ /** @nocollapse */ static { this.ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "14.0.0", version: "20.3.30", type: KbqDropdownItemAction, isStandalone: true, selector: "[kbqDropdownItemAction]", host: { listeners: { "click": "onClick($event)" }, properties: { "class.kbq-disabled": "isInactive()", "attr.aria-disabled": "isInactive() || null" }, classAttribute: "kbq-dropdown-item__action" }, ngImport: i0 }); }
222
+ }
223
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.30", ngImport: i0, type: KbqDropdownItemAction, decorators: [{
224
+ type: Directive,
225
+ args: [{
226
+ selector: '[kbqDropdownItemAction]',
227
+ host: {
228
+ class: 'kbq-dropdown-item__action',
229
+ '[class.kbq-disabled]': 'isInactive()',
230
+ '[attr.aria-disabled]': 'isInactive() || null',
231
+ '(click)': 'onClick($event)'
232
+ }
233
+ }]
234
+ }], ctorParameters: () => [] });
141
235
 
142
236
  /**
143
237
  * Injection token used to provide the parent dropdown to dropdown-specific components.
@@ -158,6 +252,7 @@ function KBQ_DROPDOWN_DEFAULT_OPTIONS_FACTORY() {
158
252
  yPosition: 'below',
159
253
  backdropClass: 'cdk-overlay-transparent-backdrop',
160
254
  hasBackdrop: false,
255
+ safeArea: true,
161
256
  // Reproduces the pre-existing CSS-driven sizing: grow with content, never narrower than the
162
257
  // trigger or `--kbq-dropdown-size-container-width-min`, capped by the token.
163
258
  panelWidth: null,
@@ -171,10 +266,22 @@ function KBQ_DROPDOWN_DEFAULT_OPTIONS_FACTORY() {
171
266
  * It exists mostly to set the role attribute.
172
267
  */
173
268
  class KbqDropdownItem {
269
+ // TODO: Skipped for migration because:
270
+ // Accessor inputs cannot be migrated as they are too complex.
271
+ get disabled() {
272
+ return this._disabled;
273
+ }
274
+ set disabled(value) {
275
+ if (value !== this.disabled) {
276
+ this._disabled = value;
277
+ }
278
+ }
174
279
  constructor() {
175
280
  this.elementRef = inject(ElementRef);
176
281
  this.focusMonitor = inject(FocusMonitor);
177
282
  this.parentDropdownPanel = inject(KBQ_DROPDOWN_PANEL, { optional: true });
283
+ /** Secondary, independently-focusable icon action projected into the item (e.g. a settings link). */
284
+ this.itemAction = contentChild(KbqDropdownItemAction, ...(ngDevMode ? [{ debugName: "itemAction" }] : []));
178
285
  this._disabled = false;
179
286
  /** Whether the dropdown item is in a loading state. */
180
287
  this.progress = input(false, ...(ngDevMode ? [{ debugName: "progress", transform: booleanAttribute }] : [{ transform: booleanAttribute }]));
@@ -184,28 +291,22 @@ class KbqDropdownItem {
184
291
  this.focused = new Subject();
185
292
  /** Whether the dropdown item is highlighted. */
186
293
  this.highlighted = false;
294
+ /** Whether the item is the panel's active item while DOM focus is held elsewhere. */
295
+ this.active = signal(false, ...(ngDevMode ? [{ debugName: "active" }] : []));
187
296
  /** Whether the dropdown item acts as a trigger for a nested dropdown. */
188
297
  this.isNested = false;
189
298
  /** @docs-private */
190
299
  this.componentColors = KbqComponentColors;
191
- }
192
- // TODO: Skipped for migration because:
193
- // Accessor inputs cannot be migrated as they are too complex.
194
- get disabled() {
195
- return this._disabled;
196
- }
197
- set disabled(value) {
198
- if (value !== this.disabled) {
199
- this._disabled = value;
200
- }
201
- }
202
- ngAfterViewInit() {
203
- if (this.focusMonitor) {
204
- // Start monitoring the element so it gets the appropriate focused classes. We want
205
- // to show the focus style for menu items only when the focus was not caused by a
206
- // mouse or touch interaction.
207
- this.focusMonitor.monitor(this.elementRef, false);
208
- }
300
+ effect(() => {
301
+ // Start monitoring the element so it gets the appropriate focused classes. We want to
302
+ // show the focus style for menu items only when the focus was not caused by a mouse or
303
+ // touch interaction. When `itemAction` is present, focus can land on it instead of the
304
+ // host, so children must be checked too for the focused classes to still be applied to
305
+ // the host. `monitor()` doesn't update `checkChildren` on an already-monitored element,
306
+ // so this restarts monitoring whenever `itemAction()` changes to keep it in sync.
307
+ this.focusMonitor.stopMonitoring(this.elementRef);
308
+ this.focusMonitor.monitor(this.elementRef, !!this.itemAction());
309
+ });
209
310
  }
210
311
  ngOnDestroy() {
211
312
  if (this.focusMonitor) {
@@ -217,15 +318,35 @@ class KbqDropdownItem {
217
318
  resetStyles() {
218
319
  this.getHostElement().classList.remove('cdk-keyboard-focused');
219
320
  }
220
- /** Focuses the dropdown item. */
321
+ /** Styles the item as active without focusing it. */
322
+ setActiveStyles() {
323
+ this.active.set(true);
324
+ }
325
+ /** Removes the styles applied by `setActiveStyles`. */
326
+ setInactiveStyles() {
327
+ this.active.set(false);
328
+ }
329
+ /**
330
+ * Focuses the dropdown item and reveals it.
331
+ *
332
+ * The reveal is explicit because the one `focus()` performs implicitly is not portable: WebKit defers
333
+ * it to a later rendering update, where it lands after — and undoes — any scrolling the reader did in
334
+ * the meantime. `preventScroll` is therefore always forced on, overriding `options`.
335
+ */
221
336
  focus(origin, options) {
222
337
  if (this.disabled)
223
338
  return;
339
+ const element = this.getHostElement();
340
+ const focusOptions = { ...options, preventScroll: true };
224
341
  if (this.focusMonitor && origin) {
225
- this.focusMonitor.focusVia(this.getHostElement(), origin, options);
342
+ this.focusMonitor.focusVia(element, origin, focusOptions);
226
343
  }
227
344
  else {
228
- this.getHostElement().focus(options);
345
+ element.focus(focusOptions);
346
+ }
347
+ // With the pointer already on this item, revealing it would shift the list out from under it.
348
+ if (origin !== 'mouse') {
349
+ element.scrollIntoView?.({ block: 'nearest', inline: 'nearest' });
229
350
  }
230
351
  this.focused.next(this);
231
352
  }
@@ -247,129 +368,227 @@ class KbqDropdownItem {
247
368
  /** Emits to the hover stream. Bound via `host` metadata. */
248
369
  handleMouseEnter() {
249
370
  this.hovered.next(this);
371
+ // In search mode the panel makes the hovered item active instead, keeping the caret in the query.
372
+ if (this.parentDropdownPanel?.inSearchMode?.())
373
+ return;
250
374
  this.focus('mouse');
251
375
  }
376
+ /**
377
+ * Lets Tab move focus between the host and `itemAction` without leaving the dropdown
378
+ * (`stopPropagation` only — the browser's native focus move still happens). Any other Tab
379
+ * press, i.e. actually leaving the item, is left untouched and still closes the dropdown via
380
+ * the panel's `FocusKeyManager.tabOut`. Bound via `host` metadata.
381
+ */
382
+ handleActionKeydown(event) {
383
+ const action = this.itemAction();
384
+ if (!action || event.keyCode !== TAB || this.disabled || this.progress())
385
+ return;
386
+ const target = event.target;
387
+ const hostEl = this.getHostElement();
388
+ const actionEl = action.getHostElement();
389
+ const movesToAction = !event.shiftKey && target === hostEl;
390
+ const movesBackToHost = event.shiftKey && target === actionEl;
391
+ if (movesToAction || movesBackToHost) {
392
+ event.stopPropagation();
393
+ }
394
+ }
252
395
  /** Gets the label to be used when determining whether the option should be focused. */
253
396
  getLabel() {
254
397
  const clone = this.getHostElement().cloneNode(true);
255
- const icons = clone.querySelectorAll('[kbq-icon], .kbq-icon');
256
- // Strip away icons so they don't show up in the text.
257
- for (let i = 0; i < icons.length; i++) {
258
- const icon = icons[i];
259
- icon.parentNode?.removeChild(icon);
398
+ const stripped = clone.querySelectorAll('[kbq-icon], .kbq-icon, [kbqDropdownItemAction]');
399
+ // Strip away icons and the action so they don't show up in the text.
400
+ for (let i = 0; i < stripped.length; i++) {
401
+ const node = stripped[i];
402
+ node.parentNode?.removeChild(node);
260
403
  }
261
404
  return clone.textContent?.trim() || '';
262
405
  }
263
406
  haltDisabledEvents(event) {
264
- if (this.disabled) {
407
+ if (this.disabled || this.progress()) {
265
408
  event.preventDefault();
266
409
  event.stopImmediatePropagation();
267
410
  event.stopPropagation();
268
411
  }
269
412
  }
270
- /** @nocollapse */ static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.25", ngImport: i0, type: KbqDropdownItem, deps: [], target: i0.ɵɵFactoryTarget.Component }); }
271
- /** @nocollapse */ static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "20.3.25", type: KbqDropdownItem, isStandalone: true, selector: "kbq-dropdown-item, [kbq-dropdown-item]", inputs: { disabled: { classPropertyName: "disabled", publicName: "disabled", isSignal: false, isRequired: false, transformFunction: booleanAttribute }, progress: { classPropertyName: "progress", publicName: "progress", isSignal: true, isRequired: false, transformFunction: null } }, host: { listeners: { "click": "checkDisabled($event)", "mouseenter": "handleMouseEnter()" }, properties: { "class.kbq-dropdown-item_with-icon": "icon", "class.kbq-dropdown-item_highlighted": "highlighted", "class.kbq-disabled": "disabled", "class.kbq-progress": "progress()", "attr.disabled": "disabled || null", "attr.tabindex": "getTabIndex()" }, classAttribute: "kbq-dropdown-item" }, providers: [
272
- { provide: KBQ_TITLE_TEXT_REF, useExisting: KbqDropdownItem }
273
- ], queries: [{ propertyName: "icon", first: true, predicate: KbqIcon, descendants: true }], viewQueries: [{ propertyName: "textElement", first: true, predicate: ["kbqTitleText"], descendants: true, static: true }], exportAs: ["kbqDropdownItem"], ngImport: i0, template: "<ng-content select=\"[kbq-icon]\" />\n\n<div #kbqTitleText class=\"kbq-dropdown-item__text\">\n <ng-content />\n</div>\n\n@if (isNested) {\n <i kbq-icon=\"kbq-chevron-right-s_16\" class=\"kbq-dropdown-trigger__icon\" [color]=\"componentColors.ContrastFade\"></i>\n}\n\n<div class=\"kbq-dropdown-item-overlay\" (click)=\"haltDisabledEvents($event)\"></div>\n", styles: ["@keyframes kbq-progress{0%{background-position:0 0}to{background-position:64px 0}}.kbq-progress{position:relative}.kbq-progress:after{content:\"\";position:absolute;border-radius:inherit;inset:0;background:linear-gradient(135deg,#0000000a 12px,#ffffff1a 12px 22px,#0000000a 22px 34px,#ffffff1a 34px) repeat;background-size:32px 32px;animation:kbq-progress 1s linear infinite}@media(prefers-reduced-motion:reduce){.kbq-progress:after{animation:none}}.kbq-truncate-line{white-space:nowrap;overflow:hidden;text-overflow:ellipsis}.kbq-no-select{-webkit-user-select:none;-moz-user-select:none;-ms-user-select:none;user-select:none}.kbq-dropdown-item{width:100%;border-radius:var(--kbq-dropdown-item-border-radius);-webkit-user-select:none;-moz-user-select:none;-ms-user-select:none;user-select:none;position:relative;display:flex;flex-direction:row;align-items:center;box-sizing:border-box;outline:none;-webkit-tap-highlight-color:transparent;min-height:32px;gap:var(--kbq-size-s);border:var(--kbq-size-3xs) solid transparent;padding:var(--kbq-size-xxs) calc(var(--kbq-size-m) - var(--kbq-size-3xs))}.kbq-dropdown-item .kbq-list-text>*{margin:0;padding:0;font-weight:400;font-size:inherit}.kbq-dropdown-item .kbq-list-text{display:flex;flex-direction:column;width:100%;box-sizing:content-box;overflow:hidden}.kbq-dropdown-item .kbq-list-text:empty{display:none}.kbq-dropdown-item .kbq-list-text{display:inline-block;white-space:nowrap;overflow:hidden;text-overflow:ellipsis}.kbq-dropdown-item .kbq-list-option-caption{padding-top:var(--kbq-size-3xs)}.kbq-dropdown-item:not(.kbq-disabled){cursor:pointer}.kbq-dropdown-item{text-align:left;align-items:flex-start;text-decoration:none}.kbq-dropdown-item>.kbq-icon:first-child:before,.kbq-dropdown-item>.kbq-icon:first-child>svg{align-self:center;display:flex;height:var(--kbq-size-xl);width:16px;align-items:center}.kbq-dropdown-item .kbq-dropdown-item__caption{padding-top:var(--kbq-size-3xs)}.kbq-dropdown-item__text>*{margin:0;padding:0;font-weight:400;font-size:inherit}.kbq-dropdown-item__text{display:flex;flex-direction:column;width:100%;box-sizing:content-box;overflow:hidden}.kbq-dropdown-item__text:empty{display:none}.kbq-dropdown-item__text{display:inline-block;white-space:nowrap;overflow:hidden;text-overflow:ellipsis}.kbq-dropdown-item-overlay{position:absolute;inset:-1px;border-radius:inherit}.kbq-dropdown-item.kbq-progress .kbq-dropdown-item-overlay{content:\"\";position:absolute;border-radius:inherit;inset:0;background:linear-gradient(135deg,#0000000a 12px,#ffffff1a 12px 22px,#0000000a 22px 34px,#ffffff1a 34px) repeat;background-size:32px 32px;animation:kbq-progress 1s linear infinite;inset:calc(-1 * var(--kbq-size-3xs))}@media(prefers-reduced-motion:reduce){.kbq-dropdown-item.kbq-progress .kbq-dropdown-item-overlay{animation:none}}.kbq-dropdown__group-header{-webkit-user-select:none;-moz-user-select:none;-ms-user-select:none;user-select:none;display:flex;flex-direction:row;align-items:center;box-sizing:border-box;min-height:32px;border-left:var(--kbq-size-3xs) solid transparent;border-right:var(--kbq-size-3xs) solid transparent;padding-top:var(--kbq-size-xs);padding-left:calc(var(--kbq-size-m) - var(--kbq-size-3xs));padding-right:calc(var(--kbq-size-m) - var(--kbq-size-3xs));padding-bottom:var(--kbq-size-3xs)}.kbq-dropdown__group-header .kbq-list-text>*{margin:0;padding:0;font-weight:400;font-size:inherit}.kbq-dropdown__group-header .kbq-list-text{display:flex;flex-direction:column;width:100%;box-sizing:content-box;overflow:hidden}.kbq-dropdown__group-header .kbq-list-text:empty{display:none}.kbq-dropdown__group-header .kbq-list-text{display:inline-block;white-space:nowrap;overflow:hidden;text-overflow:ellipsis}.kbq-dropdown__group-header.kbq-dropdown__group-header_small{display:flex;flex-direction:row;align-items:center;box-sizing:border-box;min-height:32px;border-left:var(--kbq-size-3xs) solid transparent;border-right:var(--kbq-size-3xs) solid transparent;padding-top:var(--kbq-size-m);padding-left:calc(var(--kbq-size-m) - var(--kbq-size-3xs));padding-right:calc(var(--kbq-size-m) - var(--kbq-size-3xs));padding-bottom:var(--kbq-size-xxs)}.kbq-dropdown__group-header.kbq-dropdown__group-header_small .kbq-list-text>*{margin:0;padding:0;font-weight:400;font-size:inherit}.kbq-dropdown__group-header.kbq-dropdown__group-header_small .kbq-list-text{display:flex;flex-direction:column;width:100%;box-sizing:content-box;overflow:hidden}.kbq-dropdown__group-header.kbq-dropdown__group-header_small .kbq-list-text:empty{display:none}.kbq-dropdown__group-header.kbq-dropdown__group-header_small .kbq-list-text{display:inline-block;white-space:nowrap;overflow:hidden;text-overflow:ellipsis}\n"], dependencies: [{ kind: "component", type: KbqIcon, selector: "[kbq-icon]", inputs: ["small", "autoColor", "kbq-icon"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush, encapsulation: i0.ViewEncapsulation.None }); }
413
+ /** @nocollapse */ static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.30", ngImport: i0, type: KbqDropdownItem, deps: [], target: i0.ɵɵFactoryTarget.Component }); }
414
+ /** @nocollapse */ static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "20.3.30", type: KbqDropdownItem, isStandalone: true, selector: "kbq-dropdown-item, [kbq-dropdown-item]", inputs: { disabled: { classPropertyName: "disabled", publicName: "disabled", isSignal: false, isRequired: false, transformFunction: booleanAttribute }, progress: { classPropertyName: "progress", publicName: "progress", isSignal: true, isRequired: false, transformFunction: null } }, host: { listeners: { "click": "checkDisabled($event)", "mouseenter": "handleMouseEnter()", "keydown": "handleActionKeydown($event)" }, properties: { "class.kbq-dropdown-item_with-icon": "icon", "class.kbq-dropdown-item_highlighted": "highlighted", "class.kbq-dropdown-item_active": "active()", "class.kbq-disabled": "disabled", "class.kbq-progress": "progress()", "class.kbq-dropdown-item_has-action": "!!itemAction()", "attr.disabled": "disabled || null", "attr.tabindex": "getTabIndex()" }, classAttribute: "kbq-dropdown-item" }, providers: [
415
+ { provide: KBQ_TITLE_TEXT_REF, useExisting: KbqDropdownItem },
416
+ { provide: KBQ_DROPDOWN_ITEM_ACTION_HOST, useExisting: KbqDropdownItem }
417
+ ], queries: [{ propertyName: "itemAction", first: true, predicate: KbqDropdownItemAction, descendants: true, isSignal: true }, { propertyName: "icon", first: true, predicate: KbqIcon, descendants: true }], viewQueries: [{ propertyName: "textElement", first: true, predicate: ["kbqTitleText"], descendants: true }], exportAs: ["kbqDropdownItem"], ngImport: i0, template: "<ng-content select=\"[kbq-icon]\" />\n\n<div #kbqTitleText class=\"kbq-dropdown-item__text\">\n <ng-content />\n</div>\n\n<ng-content select=\"[kbqDropdownItemAction]\" />\n\n@if (isNested) {\n <i kbq-icon=\"kbq-chevron-right-s_16\" class=\"kbq-dropdown-trigger__icon\" [color]=\"componentColors.ContrastFade\"></i>\n}\n\n<div class=\"kbq-dropdown-item-overlay\" (click)=\"haltDisabledEvents($event)\"></div>\n", styles: ["@keyframes kbq-progress{0%{background-position:0 0}to{background-position:64px 0}}.kbq-progress{position:relative}.kbq-progress:after{content:\"\";position:absolute;border-radius:inherit;inset:0;background:linear-gradient(135deg,#0000000a 12px,#ffffff1a 12px 22px,#0000000a 22px 34px,#ffffff1a 34px) repeat;background-size:32px 32px;animation:kbq-progress 1s linear infinite}@media(prefers-reduced-motion:reduce){.kbq-progress:after{animation:none}}.kbq-truncate-line{white-space:nowrap;overflow:hidden;text-overflow:ellipsis}.kbq-no-select{-webkit-user-select:none;-moz-user-select:none;-ms-user-select:none;user-select:none}.kbq-dropdown-item{width:100%;border-radius:var(--kbq-dropdown-item-border-radius);-webkit-user-select:none;-moz-user-select:none;-ms-user-select:none;user-select:none;position:relative;display:flex;flex-direction:row;align-items:center;box-sizing:border-box;outline:none;-webkit-tap-highlight-color:transparent;min-height:32px;gap:var(--kbq-size-s);border:var(--kbq-size-3xs) solid transparent;padding:var(--kbq-size-xxs) calc(var(--kbq-size-m) - var(--kbq-size-3xs))}.kbq-dropdown-item .kbq-list-text>*{margin:0;padding:0;font-weight:400;font-size:inherit}.kbq-dropdown-item .kbq-list-text{display:flex;flex-direction:column;width:100%;box-sizing:content-box;overflow:hidden}.kbq-dropdown-item .kbq-list-text:empty{display:none}.kbq-dropdown-item .kbq-list-text{display:inline-block;white-space:nowrap;overflow:hidden;text-overflow:ellipsis}.kbq-dropdown-item .kbq-list-option-caption{padding-top:var(--kbq-size-3xs)}.kbq-dropdown-item:not(.kbq-disabled){cursor:pointer}.kbq-dropdown-item{text-align:left;align-items:flex-start;text-decoration:none}.kbq-dropdown-item>.kbq-icon:first-child:before,.kbq-dropdown-item>.kbq-icon:first-child>svg{align-self:center;display:flex;height:var(--kbq-size-xl);width:16px;align-items:center}.kbq-dropdown-item .kbq-dropdown-item__caption{padding-top:var(--kbq-size-3xs)}.kbq-dropdown-item__text>*{margin:0;padding:0;font-weight:400;font-size:inherit}.kbq-dropdown-item__text{display:flex;flex-direction:column;width:100%;box-sizing:content-box;overflow:hidden}.kbq-dropdown-item__text:empty{display:none}.kbq-dropdown-item__text{display:inline-block;white-space:nowrap;overflow:hidden;text-overflow:ellipsis}.kbq-dropdown-item-overlay{position:absolute;inset:-1px;border-radius:inherit}.kbq-dropdown-item_has-action{align-items:center}.kbq-dropdown-item_has-action>.kbq-dropdown-item__action{position:relative;z-index:1;flex:0 0 auto}.kbq-dropdown-item.kbq-progress .kbq-dropdown-item-overlay{content:\"\";position:absolute;border-radius:inherit;inset:0;background:linear-gradient(135deg,#0000000a 12px,#ffffff1a 12px 22px,#0000000a 22px 34px,#ffffff1a 34px) repeat;background-size:32px 32px;animation:kbq-progress 1s linear infinite;inset:calc(-1 * var(--kbq-size-3xs))}@media(prefers-reduced-motion:reduce){.kbq-dropdown-item.kbq-progress .kbq-dropdown-item-overlay{animation:none}}.kbq-dropdown__group-header{-webkit-user-select:none;-moz-user-select:none;-ms-user-select:none;user-select:none;display:flex;flex-direction:row;align-items:center;box-sizing:border-box;min-height:32px;border-left:var(--kbq-size-3xs) solid transparent;border-right:var(--kbq-size-3xs) solid transparent;padding-top:var(--kbq-size-xs);padding-left:calc(var(--kbq-size-m) - var(--kbq-size-3xs));padding-right:calc(var(--kbq-size-m) - var(--kbq-size-3xs));padding-bottom:var(--kbq-size-3xs)}.kbq-dropdown__group-header .kbq-list-text>*{margin:0;padding:0;font-weight:400;font-size:inherit}.kbq-dropdown__group-header .kbq-list-text{display:flex;flex-direction:column;width:100%;box-sizing:content-box;overflow:hidden}.kbq-dropdown__group-header .kbq-list-text:empty{display:none}.kbq-dropdown__group-header .kbq-list-text{display:inline-block;white-space:nowrap;overflow:hidden;text-overflow:ellipsis}.kbq-dropdown__group-header.kbq-dropdown__group-header_small{display:flex;flex-direction:row;align-items:center;box-sizing:border-box;min-height:32px;border-left:var(--kbq-size-3xs) solid transparent;border-right:var(--kbq-size-3xs) solid transparent;padding-top:var(--kbq-size-m);padding-left:calc(var(--kbq-size-m) - var(--kbq-size-3xs));padding-right:calc(var(--kbq-size-m) - var(--kbq-size-3xs));padding-bottom:var(--kbq-size-xxs)}.kbq-dropdown__group-header.kbq-dropdown__group-header_small .kbq-list-text>*{margin:0;padding:0;font-weight:400;font-size:inherit}.kbq-dropdown__group-header.kbq-dropdown__group-header_small .kbq-list-text{display:flex;flex-direction:column;width:100%;box-sizing:content-box;overflow:hidden}.kbq-dropdown__group-header.kbq-dropdown__group-header_small .kbq-list-text:empty{display:none}.kbq-dropdown__group-header.kbq-dropdown__group-header_small .kbq-list-text{display:inline-block;white-space:nowrap;overflow:hidden;text-overflow:ellipsis}\n"], dependencies: [{ kind: "component", type: KbqIcon, selector: "[kbq-icon]", inputs: ["small", "autoColor", "kbq-icon"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush, encapsulation: i0.ViewEncapsulation.None }); }
274
418
  }
275
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.25", ngImport: i0, type: KbqDropdownItem, decorators: [{
419
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.30", ngImport: i0, type: KbqDropdownItem, decorators: [{
276
420
  type: Component,
277
421
  args: [{ selector: 'kbq-dropdown-item, [kbq-dropdown-item]', imports: [
278
422
  KbqIcon
279
423
  ], providers: [
280
- { provide: KBQ_TITLE_TEXT_REF, useExisting: KbqDropdownItem }
424
+ { provide: KBQ_TITLE_TEXT_REF, useExisting: KbqDropdownItem },
425
+ { provide: KBQ_DROPDOWN_ITEM_ACTION_HOST, useExisting: KbqDropdownItem }
281
426
  ], changeDetection: ChangeDetectionStrategy.OnPush, encapsulation: ViewEncapsulation.None, host: {
282
427
  class: 'kbq-dropdown-item',
283
428
  '[class.kbq-dropdown-item_with-icon]': 'icon',
284
429
  '[class.kbq-dropdown-item_highlighted]': 'highlighted',
430
+ '[class.kbq-dropdown-item_active]': 'active()',
285
431
  '[class.kbq-disabled]': 'disabled',
286
432
  '[class.kbq-progress]': 'progress()',
433
+ '[class.kbq-dropdown-item_has-action]': '!!itemAction()',
287
434
  '[attr.disabled]': 'disabled || null',
288
435
  '[attr.tabindex]': 'getTabIndex()',
289
436
  '(click)': 'checkDisabled($event)',
290
- '(mouseenter)': 'handleMouseEnter()'
291
- }, exportAs: 'kbqDropdownItem', template: "<ng-content select=\"[kbq-icon]\" />\n\n<div #kbqTitleText class=\"kbq-dropdown-item__text\">\n <ng-content />\n</div>\n\n@if (isNested) {\n <i kbq-icon=\"kbq-chevron-right-s_16\" class=\"kbq-dropdown-trigger__icon\" [color]=\"componentColors.ContrastFade\"></i>\n}\n\n<div class=\"kbq-dropdown-item-overlay\" (click)=\"haltDisabledEvents($event)\"></div>\n", styles: ["@keyframes kbq-progress{0%{background-position:0 0}to{background-position:64px 0}}.kbq-progress{position:relative}.kbq-progress:after{content:\"\";position:absolute;border-radius:inherit;inset:0;background:linear-gradient(135deg,#0000000a 12px,#ffffff1a 12px 22px,#0000000a 22px 34px,#ffffff1a 34px) repeat;background-size:32px 32px;animation:kbq-progress 1s linear infinite}@media(prefers-reduced-motion:reduce){.kbq-progress:after{animation:none}}.kbq-truncate-line{white-space:nowrap;overflow:hidden;text-overflow:ellipsis}.kbq-no-select{-webkit-user-select:none;-moz-user-select:none;-ms-user-select:none;user-select:none}.kbq-dropdown-item{width:100%;border-radius:var(--kbq-dropdown-item-border-radius);-webkit-user-select:none;-moz-user-select:none;-ms-user-select:none;user-select:none;position:relative;display:flex;flex-direction:row;align-items:center;box-sizing:border-box;outline:none;-webkit-tap-highlight-color:transparent;min-height:32px;gap:var(--kbq-size-s);border:var(--kbq-size-3xs) solid transparent;padding:var(--kbq-size-xxs) calc(var(--kbq-size-m) - var(--kbq-size-3xs))}.kbq-dropdown-item .kbq-list-text>*{margin:0;padding:0;font-weight:400;font-size:inherit}.kbq-dropdown-item .kbq-list-text{display:flex;flex-direction:column;width:100%;box-sizing:content-box;overflow:hidden}.kbq-dropdown-item .kbq-list-text:empty{display:none}.kbq-dropdown-item .kbq-list-text{display:inline-block;white-space:nowrap;overflow:hidden;text-overflow:ellipsis}.kbq-dropdown-item .kbq-list-option-caption{padding-top:var(--kbq-size-3xs)}.kbq-dropdown-item:not(.kbq-disabled){cursor:pointer}.kbq-dropdown-item{text-align:left;align-items:flex-start;text-decoration:none}.kbq-dropdown-item>.kbq-icon:first-child:before,.kbq-dropdown-item>.kbq-icon:first-child>svg{align-self:center;display:flex;height:var(--kbq-size-xl);width:16px;align-items:center}.kbq-dropdown-item .kbq-dropdown-item__caption{padding-top:var(--kbq-size-3xs)}.kbq-dropdown-item__text>*{margin:0;padding:0;font-weight:400;font-size:inherit}.kbq-dropdown-item__text{display:flex;flex-direction:column;width:100%;box-sizing:content-box;overflow:hidden}.kbq-dropdown-item__text:empty{display:none}.kbq-dropdown-item__text{display:inline-block;white-space:nowrap;overflow:hidden;text-overflow:ellipsis}.kbq-dropdown-item-overlay{position:absolute;inset:-1px;border-radius:inherit}.kbq-dropdown-item.kbq-progress .kbq-dropdown-item-overlay{content:\"\";position:absolute;border-radius:inherit;inset:0;background:linear-gradient(135deg,#0000000a 12px,#ffffff1a 12px 22px,#0000000a 22px 34px,#ffffff1a 34px) repeat;background-size:32px 32px;animation:kbq-progress 1s linear infinite;inset:calc(-1 * var(--kbq-size-3xs))}@media(prefers-reduced-motion:reduce){.kbq-dropdown-item.kbq-progress .kbq-dropdown-item-overlay{animation:none}}.kbq-dropdown__group-header{-webkit-user-select:none;-moz-user-select:none;-ms-user-select:none;user-select:none;display:flex;flex-direction:row;align-items:center;box-sizing:border-box;min-height:32px;border-left:var(--kbq-size-3xs) solid transparent;border-right:var(--kbq-size-3xs) solid transparent;padding-top:var(--kbq-size-xs);padding-left:calc(var(--kbq-size-m) - var(--kbq-size-3xs));padding-right:calc(var(--kbq-size-m) - var(--kbq-size-3xs));padding-bottom:var(--kbq-size-3xs)}.kbq-dropdown__group-header .kbq-list-text>*{margin:0;padding:0;font-weight:400;font-size:inherit}.kbq-dropdown__group-header .kbq-list-text{display:flex;flex-direction:column;width:100%;box-sizing:content-box;overflow:hidden}.kbq-dropdown__group-header .kbq-list-text:empty{display:none}.kbq-dropdown__group-header .kbq-list-text{display:inline-block;white-space:nowrap;overflow:hidden;text-overflow:ellipsis}.kbq-dropdown__group-header.kbq-dropdown__group-header_small{display:flex;flex-direction:row;align-items:center;box-sizing:border-box;min-height:32px;border-left:var(--kbq-size-3xs) solid transparent;border-right:var(--kbq-size-3xs) solid transparent;padding-top:var(--kbq-size-m);padding-left:calc(var(--kbq-size-m) - var(--kbq-size-3xs));padding-right:calc(var(--kbq-size-m) - var(--kbq-size-3xs));padding-bottom:var(--kbq-size-xxs)}.kbq-dropdown__group-header.kbq-dropdown__group-header_small .kbq-list-text>*{margin:0;padding:0;font-weight:400;font-size:inherit}.kbq-dropdown__group-header.kbq-dropdown__group-header_small .kbq-list-text{display:flex;flex-direction:column;width:100%;box-sizing:content-box;overflow:hidden}.kbq-dropdown__group-header.kbq-dropdown__group-header_small .kbq-list-text:empty{display:none}.kbq-dropdown__group-header.kbq-dropdown__group-header_small .kbq-list-text{display:inline-block;white-space:nowrap;overflow:hidden;text-overflow:ellipsis}\n"] }]
292
- }], propDecorators: { textElement: [{
437
+ '(mouseenter)': 'handleMouseEnter()',
438
+ '(keydown)': 'handleActionKeydown($event)'
439
+ }, exportAs: 'kbqDropdownItem', template: "<ng-content select=\"[kbq-icon]\" />\n\n<div #kbqTitleText class=\"kbq-dropdown-item__text\">\n <ng-content />\n</div>\n\n<ng-content select=\"[kbqDropdownItemAction]\" />\n\n@if (isNested) {\n <i kbq-icon=\"kbq-chevron-right-s_16\" class=\"kbq-dropdown-trigger__icon\" [color]=\"componentColors.ContrastFade\"></i>\n}\n\n<div class=\"kbq-dropdown-item-overlay\" (click)=\"haltDisabledEvents($event)\"></div>\n", styles: ["@keyframes kbq-progress{0%{background-position:0 0}to{background-position:64px 0}}.kbq-progress{position:relative}.kbq-progress:after{content:\"\";position:absolute;border-radius:inherit;inset:0;background:linear-gradient(135deg,#0000000a 12px,#ffffff1a 12px 22px,#0000000a 22px 34px,#ffffff1a 34px) repeat;background-size:32px 32px;animation:kbq-progress 1s linear infinite}@media(prefers-reduced-motion:reduce){.kbq-progress:after{animation:none}}.kbq-truncate-line{white-space:nowrap;overflow:hidden;text-overflow:ellipsis}.kbq-no-select{-webkit-user-select:none;-moz-user-select:none;-ms-user-select:none;user-select:none}.kbq-dropdown-item{width:100%;border-radius:var(--kbq-dropdown-item-border-radius);-webkit-user-select:none;-moz-user-select:none;-ms-user-select:none;user-select:none;position:relative;display:flex;flex-direction:row;align-items:center;box-sizing:border-box;outline:none;-webkit-tap-highlight-color:transparent;min-height:32px;gap:var(--kbq-size-s);border:var(--kbq-size-3xs) solid transparent;padding:var(--kbq-size-xxs) calc(var(--kbq-size-m) - var(--kbq-size-3xs))}.kbq-dropdown-item .kbq-list-text>*{margin:0;padding:0;font-weight:400;font-size:inherit}.kbq-dropdown-item .kbq-list-text{display:flex;flex-direction:column;width:100%;box-sizing:content-box;overflow:hidden}.kbq-dropdown-item .kbq-list-text:empty{display:none}.kbq-dropdown-item .kbq-list-text{display:inline-block;white-space:nowrap;overflow:hidden;text-overflow:ellipsis}.kbq-dropdown-item .kbq-list-option-caption{padding-top:var(--kbq-size-3xs)}.kbq-dropdown-item:not(.kbq-disabled){cursor:pointer}.kbq-dropdown-item{text-align:left;align-items:flex-start;text-decoration:none}.kbq-dropdown-item>.kbq-icon:first-child:before,.kbq-dropdown-item>.kbq-icon:first-child>svg{align-self:center;display:flex;height:var(--kbq-size-xl);width:16px;align-items:center}.kbq-dropdown-item .kbq-dropdown-item__caption{padding-top:var(--kbq-size-3xs)}.kbq-dropdown-item__text>*{margin:0;padding:0;font-weight:400;font-size:inherit}.kbq-dropdown-item__text{display:flex;flex-direction:column;width:100%;box-sizing:content-box;overflow:hidden}.kbq-dropdown-item__text:empty{display:none}.kbq-dropdown-item__text{display:inline-block;white-space:nowrap;overflow:hidden;text-overflow:ellipsis}.kbq-dropdown-item-overlay{position:absolute;inset:-1px;border-radius:inherit}.kbq-dropdown-item_has-action{align-items:center}.kbq-dropdown-item_has-action>.kbq-dropdown-item__action{position:relative;z-index:1;flex:0 0 auto}.kbq-dropdown-item.kbq-progress .kbq-dropdown-item-overlay{content:\"\";position:absolute;border-radius:inherit;inset:0;background:linear-gradient(135deg,#0000000a 12px,#ffffff1a 12px 22px,#0000000a 22px 34px,#ffffff1a 34px) repeat;background-size:32px 32px;animation:kbq-progress 1s linear infinite;inset:calc(-1 * var(--kbq-size-3xs))}@media(prefers-reduced-motion:reduce){.kbq-dropdown-item.kbq-progress .kbq-dropdown-item-overlay{animation:none}}.kbq-dropdown__group-header{-webkit-user-select:none;-moz-user-select:none;-ms-user-select:none;user-select:none;display:flex;flex-direction:row;align-items:center;box-sizing:border-box;min-height:32px;border-left:var(--kbq-size-3xs) solid transparent;border-right:var(--kbq-size-3xs) solid transparent;padding-top:var(--kbq-size-xs);padding-left:calc(var(--kbq-size-m) - var(--kbq-size-3xs));padding-right:calc(var(--kbq-size-m) - var(--kbq-size-3xs));padding-bottom:var(--kbq-size-3xs)}.kbq-dropdown__group-header .kbq-list-text>*{margin:0;padding:0;font-weight:400;font-size:inherit}.kbq-dropdown__group-header .kbq-list-text{display:flex;flex-direction:column;width:100%;box-sizing:content-box;overflow:hidden}.kbq-dropdown__group-header .kbq-list-text:empty{display:none}.kbq-dropdown__group-header .kbq-list-text{display:inline-block;white-space:nowrap;overflow:hidden;text-overflow:ellipsis}.kbq-dropdown__group-header.kbq-dropdown__group-header_small{display:flex;flex-direction:row;align-items:center;box-sizing:border-box;min-height:32px;border-left:var(--kbq-size-3xs) solid transparent;border-right:var(--kbq-size-3xs) solid transparent;padding-top:var(--kbq-size-m);padding-left:calc(var(--kbq-size-m) - var(--kbq-size-3xs));padding-right:calc(var(--kbq-size-m) - var(--kbq-size-3xs));padding-bottom:var(--kbq-size-xxs)}.kbq-dropdown__group-header.kbq-dropdown__group-header_small .kbq-list-text>*{margin:0;padding:0;font-weight:400;font-size:inherit}.kbq-dropdown__group-header.kbq-dropdown__group-header_small .kbq-list-text{display:flex;flex-direction:column;width:100%;box-sizing:content-box;overflow:hidden}.kbq-dropdown__group-header.kbq-dropdown__group-header_small .kbq-list-text:empty{display:none}.kbq-dropdown__group-header.kbq-dropdown__group-header_small .kbq-list-text{display:inline-block;white-space:nowrap;overflow:hidden;text-overflow:ellipsis}\n"] }]
440
+ }], ctorParameters: () => [], propDecorators: { textElement: [{
293
441
  type: ViewChild,
294
- args: ['kbqTitleText', { static: true }]
442
+ args: ['kbqTitleText']
295
443
  }], icon: [{
296
444
  type: ContentChild,
297
445
  args: [KbqIcon]
298
- }], disabled: [{
446
+ }], itemAction: [{ type: i0.ContentChild, args: [i0.forwardRef(() => KbqDropdownItemAction), { isSignal: true }] }], disabled: [{
299
447
  type: Input,
300
448
  args: [{ transform: booleanAttribute }]
301
449
  }], progress: [{ type: i0.Input, args: [{ isSignal: true, alias: "progress", required: false }] }] } });
302
450
 
451
+ /**
452
+ * Marks a `kbq-form-field` projected into a `kbq-dropdown` as the panel's search field.
453
+ *
454
+ * The panel keeps DOM focus in the field, so arrow keys move the highlighted item while the query
455
+ * stays editable.
456
+ */
457
+ class KbqDropdownSearch {
458
+ constructor() {
459
+ this.formField = inject(KBQ_FORM_FIELD);
460
+ /**
461
+ * Panel this field searches. A nested panel declared inside its parent's content shares the view with
462
+ * it, so the parent has to be able to tell which of the projected fields is its own.
463
+ * @docs-private
464
+ */
465
+ this.panel = inject(KBQ_DROPDOWN_PANEL, { optional: true });
466
+ }
467
+ /** The form control the query is bound to. */
468
+ get ngControl() {
469
+ return this.formField.control().ngControl;
470
+ }
471
+ ngAfterContentInit() {
472
+ if (this.formField.control().controlType !== 'input') {
473
+ throwKbqDropdownSearchMissingInputError();
474
+ }
475
+ if (!this.ngControl) {
476
+ throwKbqDropdownSearchMissingNgControlError();
477
+ }
478
+ }
479
+ /** Focuses the search field. */
480
+ focus() {
481
+ this.formField.focus();
482
+ }
483
+ /** Clears the search query. */
484
+ reset() {
485
+ this.ngControl?.reset();
486
+ }
487
+ /** The current search query. */
488
+ value() {
489
+ return this.formField.control().value;
490
+ }
491
+ /** @docs-private */
492
+ handleClick(event) {
493
+ event.stopPropagation();
494
+ }
495
+ /** @docs-private */
496
+ handleKeydown(event) {
497
+ // The panel owns ESCAPE: the first press clears the query, the second closes the dropdown. This
498
+ // handler runs before the cleaner's own listener on the same element, so the field is already
499
+ // empty by the time the cleaner looks at the key.
500
+ if (event.keyCode === ESCAPE && this.value()) {
501
+ this.reset();
502
+ event.stopPropagation();
503
+ return;
504
+ }
505
+ // A nested panel closes on the horizontal arrow that points back at its trigger, so the key is
506
+ // only kept while the caret still has somewhere to go — the top-level panel ignores it anyway.
507
+ if (this.movesCaret(event)) {
508
+ event.stopPropagation();
509
+ }
510
+ }
511
+ /** Whether the key still has caret to travel inside the field, rather than acting on the panel. */
512
+ movesCaret(event) {
513
+ const { keyCode, target } = event;
514
+ if (keyCode !== LEFT_ARROW && keyCode !== RIGHT_ARROW)
515
+ return false;
516
+ // The keydown starts on the input and bubbles to this host, so the target is the field itself.
517
+ const { selectionStart, selectionEnd, value } = target;
518
+ if (selectionStart === null || selectionEnd === null)
519
+ return true;
520
+ const edge = keyCode === LEFT_ARROW ? 0 : value.length;
521
+ return selectionStart !== edge || selectionEnd !== edge;
522
+ }
523
+ /** @nocollapse */ static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.30", ngImport: i0, type: KbqDropdownSearch, deps: [], target: i0.ɵɵFactoryTarget.Directive }); }
524
+ /** @nocollapse */ static { this.ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "14.0.0", version: "20.3.30", type: KbqDropdownSearch, isStandalone: true, selector: "[kbqDropdownSearch]", host: { listeners: { "click": "handleClick($event)", "keydown": "handleKeydown($event)" } }, providers: [
525
+ {
526
+ // Merged, not replaced: the field still inherits whatever defaults the app configures.
527
+ provide: KBQ_FORM_FIELD_DEFAULT_OPTIONS,
528
+ useFactory: (() => ({
529
+ ...inject(KBQ_FORM_FIELD_DEFAULT_OPTIONS, { optional: true, skipSelf: true }),
530
+ noBorders: true,
531
+ inOverlay: true
532
+ }))
533
+ }
534
+ ], exportAs: ["kbqDropdownSearch"], ngImport: i0 }); }
535
+ }
536
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.30", ngImport: i0, type: KbqDropdownSearch, decorators: [{
537
+ type: Directive,
538
+ args: [{
539
+ selector: '[kbqDropdownSearch]',
540
+ providers: [
541
+ {
542
+ // Merged, not replaced: the field still inherits whatever defaults the app configures.
543
+ provide: KBQ_FORM_FIELD_DEFAULT_OPTIONS,
544
+ useFactory: (() => ({
545
+ ...inject(KBQ_FORM_FIELD_DEFAULT_OPTIONS, { optional: true, skipSelf: true }),
546
+ noBorders: true,
547
+ inOverlay: true
548
+ }))
549
+ }
550
+ ],
551
+ host: {
552
+ '(click)': 'handleClick($event)',
553
+ '(keydown)': 'handleKeydown($event)'
554
+ },
555
+ exportAs: 'kbqDropdownSearch'
556
+ }]
557
+ }] });
558
+
559
+ /** Options for binding a passive event listener. */
560
+ const passiveEventListenerOptions$1 = normalizePassiveListenerOptions({ passive: true });
561
+ /**
562
+ * Grace period before switching to a different nested trigger hovered while a safe area is
563
+ * protecting the currently open submenu. Without it, sweeping the pointer down a long list of
564
+ * nested triggers on the way to the submenu would flicker each row's submenu open and closed.
565
+ */
566
+ const NESTED_HOVER_SWITCH_DELAY = 50;
567
+ /** Class applied to the panel while its safe area is protecting an open submenu, see `activateSafeArea`. */
568
+ const SAFE_AREA_ACTIVE_CLASS = 'kbq-dropdown__panel_safe-area-active';
303
569
  class KbqDropdownStaticContent {
304
- /** @nocollapse */ static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.25", ngImport: i0, type: KbqDropdownStaticContent, deps: [], target: i0.ɵɵFactoryTarget.Directive }); }
305
- /** @nocollapse */ static { this.ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "14.0.0", version: "20.3.25", type: KbqDropdownStaticContent, isStandalone: true, selector: "[kbqDropdownStaticContent]", ngImport: i0 }); }
570
+ /** @nocollapse */ static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.30", ngImport: i0, type: KbqDropdownStaticContent, deps: [], target: i0.ɵɵFactoryTarget.Directive }); }
571
+ /** @nocollapse */ static { this.ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "14.0.0", version: "20.3.30", type: KbqDropdownStaticContent, isStandalone: true, selector: "[kbqDropdownStaticContent]", ngImport: i0 }); }
306
572
  }
307
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.25", ngImport: i0, type: KbqDropdownStaticContent, decorators: [{
573
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.30", ngImport: i0, type: KbqDropdownStaticContent, decorators: [{
308
574
  type: Directive,
309
575
  args: [{
310
576
  selector: '[kbqDropdownStaticContent]'
311
577
  }]
312
578
  }] });
579
+ /** Footer that is rendered below the dropdown options panel. */
580
+ class KbqDropdownFooter {
581
+ /** @nocollapse */ static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.30", ngImport: i0, type: KbqDropdownFooter, deps: [], target: i0.ɵɵFactoryTarget.Directive }); }
582
+ /** @nocollapse */ static { this.ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "14.0.0", version: "20.3.30", type: KbqDropdownFooter, isStandalone: true, selector: "[kbqDropdownFooter], kbq-dropdown-footer", host: { classAttribute: "kbq-dropdown-footer" }, ngImport: i0 }); }
583
+ }
584
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.30", ngImport: i0, type: KbqDropdownFooter, decorators: [{
585
+ type: Directive,
586
+ args: [{
587
+ selector: '[kbqDropdownFooter], kbq-dropdown-footer',
588
+ host: { class: 'kbq-dropdown-footer' }
589
+ }]
590
+ }] });
313
591
  class KbqDropdown {
314
- constructor() {
315
- this.elementRef = inject(ElementRef);
316
- this.ngZone = inject(NgZone);
317
- this.defaultOptions = inject(KBQ_DROPDOWN_DEFAULT_OPTIONS);
318
- this.search = contentChild(KbqFormField, ...(ngDevMode ? [{ debugName: "search" }] : []));
319
- /** Whether the dropdown projects a search form-field. @docs-private */
320
- this.hasSearch = computed(() => !!this.search(), ...(ngDevMode ? [{ debugName: "hasSearch" }] : []));
321
- this.navigationWithWrap = input(false, ...(ngDevMode ? [{ debugName: "navigationWithWrap" }] : []));
322
- this._xPosition = this.defaultOptions.xPosition;
323
- this._yPosition = this.defaultOptions.yPosition;
324
- this._overlapTriggerX = this.defaultOptions.overlapTriggerX;
325
- this._overlapTriggerY = this.defaultOptions.overlapTriggerY;
326
- this._hasBackdrop = this.defaultOptions.hasBackdrop;
327
- /** Config object to be passed into the dropdown panel's `[class]` binding */
328
- this.classList = {};
329
- /** Current state of the panel animation. */
330
- this.panelAnimationState = 'void';
331
- /** Emits whenever an animation on the dropdown completes. */
332
- this.animationDone = new Subject();
333
- /** Class to be added to the backdrop element. */
334
- // TODO: Skipped for migration because:
335
- // This input overrides a field from a superclass, while the superclass field
336
- // is not migrated.
337
- this.backdropClass = this.defaultOptions.backdropClass;
338
- /**
339
- * Width of the panel. If set to `auto`, the panel will match the trigger width, but will never be
340
- * narrower than `panelMinWidth`. If set to null, the panel will grow to match its content.
341
- * Any other value is used as an exact width, and `panelMinWidth` is not applied.
342
- */
343
- this.panelWidth = input(this.defaultOptions.panelWidth ?? null, ...(ngDevMode ? [{ debugName: "panelWidth" }] : []));
344
- /**
345
- * Minimum width of the panel in pixels. The panel is never narrower than this, nor than its trigger.
346
- */
347
- this.panelMinWidth = input(this.defaultOptions.panelMinWidth === undefined
348
- ? KBQ_PANEL_DEFAULT_MIN_WIDTH
349
- : this.defaultOptions.panelMinWidth, ...(ngDevMode ? [{ debugName: "panelMinWidth", transform: numberAttribute }] : [{ transform: numberAttribute }]));
350
- /**
351
- * Maximum width of the panel in pixels. Caps how far the panel grows with its content — it never makes
352
- * the panel narrower than the trigger, and never clamps an explicit `panelWidth`.
353
- * When null, the `--kbq-dropdown-size-container-width-max` token applies.
354
- */
355
- this.panelMaxWidth = input(this.defaultOptions.panelMaxWidth === undefined ? null : this.defaultOptions.panelMaxWidth, ...(ngDevMode ? [{ debugName: "panelMaxWidth", transform: numberAttribute }] : [{ transform: numberAttribute }]));
356
- /**
357
- * `panelMinWidth` rendered as a CSS length for the `--kbq-dropdown-size-container-width-min`
358
- * token, so the panel's CSS `min-width` floor tracks the input — mirroring how `panelMaxWidth`
359
- * drives `max-width`. Non-finite input (e.g. `null`) leaves the token's static default in place.
360
- * @docs-private
361
- */
362
- this.panelMinWidthToken = computed(() => {
363
- const minWidth = this.panelMinWidth();
364
- return Number.isFinite(minWidth) ? `${minWidth}px` : null;
365
- }, ...(ngDevMode ? [{ debugName: "panelMinWidthToken" }] : []));
366
- /** Event emitted when the dropdown is closed. */
367
- this.closed = new EventEmitter();
368
- /** Only the direct descendant menu items. */
369
- this.directDescendantItems = new QueryList();
370
- /** Subscription to tab events on the dropdown panel */
371
- this.tabSubscription = Subscription.EMPTY;
372
- }
373
592
  /** Position of the dropdown in the X axis. */
374
593
  // TODO: Skipped for migration because:
375
594
  // Accessor inputs cannot be migrated as they are too complex.
@@ -445,34 +664,258 @@ class KbqDropdown {
445
664
  // Reassign a new object reference so the native `[class]` binding picks up the change.
446
665
  this.classList = classList;
447
666
  }
667
+ constructor() {
668
+ this.elementRef = inject(ElementRef);
669
+ this.ngZone = inject(NgZone);
670
+ this.document = inject(DOCUMENT);
671
+ this.defaultOptions = inject(KBQ_DROPDOWN_DEFAULT_OPTIONS);
672
+ this.destroyRef = inject(DestroyRef);
673
+ this.panelFormField = contentChild(KbqFormField, ...(ngDevMode ? [{ debugName: "panelFormField" }] : []));
674
+ /**
675
+ * Signal content queries carry `descendants: true`, and a nested panel declared inside this one's
676
+ * content is part of the same view — so the match has to be narrowed to the fields this panel owns,
677
+ * the way `updateDirectDescendants` narrows the items.
678
+ */
679
+ this.searches = contentChildren(KbqDropdownSearch, ...(ngDevMode ? [{ debugName: "searches", descendants: true }] : [{ descendants: true }]));
680
+ this.search = computed(() => this.searches().find((search) => search.panel === this), ...(ngDevMode ? [{ debugName: "search" }] : []));
681
+ /** Whether the dropdown projects a search form-field. @docs-private */
682
+ this.hasSearch = computed(() => !!this.panelFormField(), ...(ngDevMode ? [{ debugName: "hasSearch" }] : []));
683
+ /** Whether the panel highlights the active item instead of focusing it. @docs-private */
684
+ this.inSearchMode = computed(() => !!this.search(), ...(ngDevMode ? [{ debugName: "inSearchMode" }] : []));
685
+ this.navigationWithWrap = input(false, ...(ngDevMode ? [{ debugName: "navigationWithWrap" }] : []));
686
+ this._xPosition = this.defaultOptions.xPosition;
687
+ this._yPosition = this.defaultOptions.yPosition;
688
+ this._overlapTriggerX = this.defaultOptions.overlapTriggerX;
689
+ this._overlapTriggerY = this.defaultOptions.overlapTriggerY;
690
+ this._hasBackdrop = this.defaultOptions.hasBackdrop;
691
+ /** Config object to be passed into the dropdown panel's `[class]` binding */
692
+ this.classList = {};
693
+ /** Current state of the panel animation. */
694
+ this.panelAnimationState = 'void';
695
+ /** Emits whenever an animation on the dropdown completes. */
696
+ this.animationDone = new Subject();
697
+ /** Class to be added to the backdrop element. */
698
+ // TODO: Skipped for migration because:
699
+ // This input overrides a field from a superclass, while the superclass field
700
+ // is not migrated.
701
+ this.backdropClass = this.defaultOptions.backdropClass;
702
+ /**
703
+ * Width of the panel. If set to `auto`, the panel will match the trigger width, but will never be
704
+ * narrower than `panelMinWidth`. If set to null, the panel will grow to match its content.
705
+ * Any other value is used as an exact width, and `panelMinWidth` is not applied.
706
+ */
707
+ this.panelWidth = input(this.defaultOptions.panelWidth ?? null, ...(ngDevMode ? [{ debugName: "panelWidth" }] : []));
708
+ /**
709
+ * Minimum width of the panel in pixels. The panel is never narrower than this, nor than its trigger.
710
+ */
711
+ this.panelMinWidth = input(this.defaultOptions.panelMinWidth === undefined
712
+ ? KBQ_PANEL_DEFAULT_MIN_WIDTH
713
+ : this.defaultOptions.panelMinWidth, ...(ngDevMode ? [{ debugName: "panelMinWidth", transform: numberAttribute }] : [{ transform: numberAttribute }]));
714
+ /**
715
+ * Maximum width of the panel in pixels. Caps how far the panel grows with its content — it never makes
716
+ * the panel narrower than the trigger, and never clamps an explicit `panelWidth`.
717
+ * When null, the `--kbq-dropdown-size-container-width-max` token applies.
718
+ */
719
+ this.panelMaxWidth = input(this.defaultOptions.panelMaxWidth === undefined ? null : this.defaultOptions.panelMaxWidth, ...(ngDevMode ? [{ debugName: "panelMaxWidth", transform: numberAttribute }] : [{ transform: numberAttribute }]));
720
+ /**
721
+ * Whether nested dropdowns opened from this dropdown's items use a "safe area": while the
722
+ * pointer moves from a trigger toward its open submenu, sibling items it crosses over on the way
723
+ * don't prematurely close the submenu.
724
+ */
725
+ this.safeArea = input(this.defaultOptions.safeArea ?? true, ...(ngDevMode ? [{ debugName: "safeArea", transform: booleanAttribute }] : [{ transform: booleanAttribute }]));
726
+ /**
727
+ * `panelMinWidth` rendered as a CSS length for the `--kbq-dropdown-size-container-width-min`
728
+ * token, so the panel's CSS `min-width` floor tracks the input — mirroring how `panelMaxWidth`
729
+ * drives `max-width`. Non-finite input (e.g. `null`) leaves the token's static default in place.
730
+ * @docs-private
731
+ */
732
+ this.panelMinWidthToken = computed(() => {
733
+ const minWidth = this.panelMinWidth();
734
+ return Number.isFinite(minWidth) ? `${minWidth}px` : null;
735
+ }, ...(ngDevMode ? [{ debugName: "panelMinWidthToken" }] : []));
736
+ /** Event emitted when the dropdown is closed. */
737
+ this.closed = new EventEmitter();
738
+ this.focusOrigin = 'program';
739
+ /** Only the direct descendant menu items. */
740
+ this.directDescendantItems = new QueryList();
741
+ /** Subscription to tab events on the dropdown panel */
742
+ this.tabSubscription = Subscription.EMPTY;
743
+ /** Cleans up the safe-area `mousemove` listener. `null` when no safe area is being tracked. */
744
+ this.safeAreaCleanup = null;
745
+ /** The nested trigger currently protected by the active safe area, if any. */
746
+ this.safeAreaOwner = null;
747
+ /**
748
+ * The most recently hovered item, tracked independently of the safe area so that leaving it
749
+ * straight onto a sibling's nested trigger can switch to it immediately instead of waiting for a
750
+ * `mouseenter` that already happened.
751
+ */
752
+ this.currentHovered = null;
753
+ /** Emits when the pointer reaches the panel the active safe area protects. */
754
+ this.panelReached = new Subject();
755
+ /** Emits the sibling trigger that should open once a forced switch has closed the current one. */
756
+ this.switchTarget = new Subject();
757
+ /** Watches for a forced switch to a sibling trigger while a safe area is active. */
758
+ this.switchTargetSubscription = Subscription.EMPTY;
759
+ // The search field can show up long after content init — rendered by `kbqDropdownContent` when
760
+ // the panel first opens, or revealed by a structural directive — so the key manager follows the
761
+ // mode instead of being decided once.
762
+ effect(() => {
763
+ const inSearchMode = this.inSearchMode();
764
+ if (!this.keyManager || this.keyManagerInstalledForSearch() === inSearchMode)
765
+ return;
766
+ this.initKeyManager();
767
+ // A flip while the panel is open leaves focus wherever the previous mode put it: on an item
768
+ // the new manager will not track, or on an input that is being destroyed. Hand it over the
769
+ // same way opening does, deferred so the write lands outside this change detection pass.
770
+ if (this.panelAnimationState === 'enter') {
771
+ this.ngZone.onStable.pipe(take(1)).subscribe(() => this.applyInitialFocus(this.focusOrigin));
772
+ }
773
+ });
774
+ }
448
775
  ngOnInit() {
449
776
  this.setPositionClasses();
450
777
  }
451
778
  ngAfterContentInit() {
452
779
  this.updateDirectDescendants();
453
- this.keyManager = new FocusKeyManager(this.directDescendantItems).withTypeAhead();
454
- if (this.navigationWithWrap()) {
455
- this.keyManager.withWrap();
456
- }
457
- this.tabSubscription = this.keyManager.tabOut.subscribe(() => this.closed.emit('tab'));
780
+ this.initKeyManager();
458
781
  // If a user manually (programmatically) focuses a menu item, we need to reflect that focus
459
782
  // change back to the key manager. Note that we don't need to unsubscribe here because focused
460
783
  // is internal and we know that it gets completed on destroy.
461
784
  this.directDescendantItems.changes
462
785
  .pipe(startWith(this.directDescendantItems), switchMap((items) => merge(...items.map((item) => item.focused))))
463
786
  .subscribe((focusedItem) => this.keyManager.updateActiveItem(focusedItem));
464
- this.search()?.inOverlay.set(true);
787
+ this.panelFormField()?.inOverlay.set(true);
788
+ // Driven by the item list rather than by the query, because consumers commonly debounce their
789
+ // own filtering. `delay(0)` keeps the write out of the pass that reported the new items.
790
+ this.directDescendantItems.changes
791
+ .pipe(filter(() => !!this.search()), delay(0), filter(() => this.isActiveItemStale()), takeUntilDestroyed(this.destroyRef))
792
+ .subscribe(() => {
793
+ // An item the highlight sat on is gone. With a query in the field the top result takes
794
+ // over, so that ENTER picks it; with the field cleared nothing is highlighted — but the
795
+ // stale instance still has to be dropped, or ENTER would replay a click on a detached
796
+ // element and the arrows would resume from its index.
797
+ if (this.search()?.value()) {
798
+ this.keyManager.setFirstItemActive();
799
+ }
800
+ else {
801
+ this.resetActiveItem();
802
+ }
803
+ });
804
+ // Internal and completes with the items on destroy, so no explicit unsubscribe is needed.
805
+ this.hovered().subscribe((item) => {
806
+ this.currentHovered = item;
807
+ // Hovering doesn't focus the item in search mode, so arrowing on has to resume from it.
808
+ // Disabled items are skipped, the same way the key manager skips them for the arrows.
809
+ if (this.inSearchMode() && !item.disabled) {
810
+ this.keyManager.setActiveItem(item);
811
+ }
812
+ });
465
813
  }
466
814
  ngOnDestroy() {
467
815
  this.directDescendantItems.destroy();
468
816
  this.tabSubscription.unsubscribe();
469
817
  this.closed.complete();
818
+ this.deactivateSafeArea();
819
+ this.panelReached.complete();
820
+ this.switchTarget.complete();
470
821
  }
471
822
  /** Stream that emits whenever the hovered dropdown item changes. */
472
823
  hovered() {
473
824
  const itemChanges = this.directDescendantItems.changes;
474
825
  return itemChanges.pipe(startWith(this.directDescendantItems), switchMap((items) => merge(...items.map((item) => item.hovered))));
475
826
  }
827
+ /**
828
+ * Tracks the pointer against `triangle` to protect `owner`'s open submenu, closing it via
829
+ * `onExit` if the pointer leaves the triangle without first reaching `panelRect`. Meanwhile, if a
830
+ * different nested trigger is hovered, `switchTarget()` emits it — immediately if it's outside
831
+ * the triangle, otherwise after a grace period (see `NESTED_HOVER_SWITCH_DELAY`). Replaces any
832
+ * safe area already being tracked.
833
+ * @docs-private
834
+ */
835
+ activateSafeArea(owner, triangle, panelRect, onExit) {
836
+ this.deactivateSafeArea();
837
+ this.safeAreaOwner = owner;
838
+ this.classList = { ...this.classList, [SAFE_AREA_ACTIVE_CLASS]: true };
839
+ this.safeAreaCleanup = this.ngZone.runOutsideAngular(() => {
840
+ const listener = (event) => {
841
+ const point = { x: event.clientX, y: event.clientY };
842
+ if (isPointInRect(point, panelRect)) {
843
+ this.panelReached.next();
844
+ this.deactivateSafeArea();
845
+ return;
846
+ }
847
+ if (!isPointInTriangle(point, triangle)) {
848
+ const switchTo = this.currentHovered?.isNested && this.currentHovered !== owner && !this.currentHovered.disabled
849
+ ? this.currentHovered
850
+ : null;
851
+ this.deactivateSafeArea();
852
+ this.ngZone.run(() => {
853
+ onExit();
854
+ if (switchTo) {
855
+ this.switchTarget.next(switchTo);
856
+ }
857
+ });
858
+ }
859
+ };
860
+ this.document.addEventListener('mousemove', listener, passiveEventListenerOptions$1);
861
+ return () => this.document.removeEventListener('mousemove', listener, passiveEventListenerOptions$1);
862
+ });
863
+ this.switchTargetSubscription = this.hovered()
864
+ .pipe(filter((active) => active.isNested && active !== owner && !active.disabled), switchMap((active) => timer(NESTED_HOVER_SWITCH_DELAY).pipe(map(() => active), takeUntil(this.panelReached))))
865
+ .subscribe((active) => {
866
+ this.deactivateSafeArea();
867
+ onExit();
868
+ this.switchTarget.next(active);
869
+ });
870
+ }
871
+ /**
872
+ * Stops tracking the current safe area, if any.
873
+ * @docs-private
874
+ */
875
+ deactivateSafeArea() {
876
+ this.safeAreaCleanup?.();
877
+ this.safeAreaCleanup = null;
878
+ this.safeAreaOwner = null;
879
+ this.switchTargetSubscription.unsubscribe();
880
+ this.switchTargetSubscription = Subscription.EMPTY;
881
+ if (this.classList[SAFE_AREA_ACTIVE_CLASS]) {
882
+ // The mousemove listener that can reach this runs outside the Angular zone, so re-enter it
883
+ // to make sure the `classList` update is picked up by change detection.
884
+ this.ngZone.run(() => {
885
+ this.classList = { ...this.classList, [SAFE_AREA_ACTIVE_CLASS]: false };
886
+ });
887
+ }
888
+ }
889
+ /**
890
+ * Whether a safe area is currently being tracked.
891
+ * @docs-private
892
+ */
893
+ isSafeAreaActive() {
894
+ return this.safeAreaCleanup !== null;
895
+ }
896
+ /**
897
+ * Whether `item` is the nested trigger currently protected by an active safe area.
898
+ * @docs-private
899
+ */
900
+ isSafeAreaOwner(item) {
901
+ return this.safeAreaOwner === item;
902
+ }
903
+ /**
904
+ * Stream that emits when the pointer reaches the panel the active safe area protects (as opposed
905
+ * to leaving the safe area, which closes the panel instead).
906
+ * @docs-private
907
+ */
908
+ onPanelReached() {
909
+ return this.panelReached.asObservable();
910
+ }
911
+ /**
912
+ * Stream that emits the sibling trigger that should open once a forced safe-area switch has
913
+ * closed the trigger it was protecting.
914
+ * @docs-private
915
+ */
916
+ onSwitchTarget() {
917
+ return this.switchTarget.asObservable();
918
+ }
476
919
  /** Handle a keyboard event from the dropdown, delegating to the appropriate action. */
477
920
  handleKeydown(event) {
478
921
  const keyCode = event.keyCode;
@@ -490,11 +933,29 @@ class KbqDropdown {
490
933
  this.closed.emit('keydown');
491
934
  }
492
935
  break;
936
+ case ENTER:
937
+ // The highlighted item never sees the key event itself, so replay it as a click and let
938
+ // consumer handlers and nested triggers behave exactly as they do for the mouse.
939
+ if (this.inSearchMode() && this.keyManager.activeItem) {
940
+ event.preventDefault();
941
+ // The click can close the dropdown synchronously, unregistering the overlay from the
942
+ // CDK keyboard dispatcher before this keydown reaches `body` — where it would be
943
+ // handed to whichever overlay was opened earlier.
944
+ event.stopPropagation();
945
+ this.keyManager.activeItem.getHostElement().click();
946
+ }
947
+ return;
493
948
  default:
949
+ // Only the vertical arrows move the highlight in search mode; every other key that the
950
+ // search field lets through would otherwise scroll the list back on each keystroke.
494
951
  if (keyCode === UP_ARROW || keyCode === DOWN_ARROW) {
495
- this.keyManager.setFocusOrigin('keyboard');
952
+ this.setFocusOrigin('keyboard');
953
+ this.keyManager.onKeydown(event);
954
+ this.revealActiveItem();
955
+ }
956
+ else {
957
+ this.keyManager.onKeydown(event);
496
958
  }
497
- this.keyManager.onKeydown(event);
498
959
  return;
499
960
  }
500
961
  // Don't allow the event to propagate if we've already handled it, or it may
@@ -502,7 +963,7 @@ class KbqDropdown {
502
963
  event.stopPropagation();
503
964
  }
504
965
  /**
505
- * Focus the first item in the dropdown.
966
+ * Applies the panel's initial focus, see `applyInitialFocus`.
506
967
  * @param origin Action from which the focus originated. Used to set the correct styling.
507
968
  */
508
969
  focusFirstItem(origin = 'program') {
@@ -515,28 +976,50 @@ class KbqDropdown {
515
976
  }
516
977
  }
517
978
  /**
518
- * Applies focus when the dropdown is opened. When opened by mouse or touch, the first item
519
- * should not be highlighted, so the panel itself is focused instead — keyboard events still
520
- * reach the panel and the first arrow key press will highlight the first item.
979
+ * Applies focus when the dropdown is opened.
980
+ *
981
+ * A projected search field takes the caret for every origin and keeps it: the first arrow key press
982
+ * only highlights an item. Without one, opening by mouse or touch focuses the panel rather than an
983
+ * item, so that nothing is highlighted while keyboard events still reach the panel; any other origin
984
+ * highlights the first item. A submenu of a search panel focuses nothing at all, so that hovering it
985
+ * does not pull the caret out of the query.
521
986
  */
522
987
  applyInitialFocus(origin) {
523
988
  // The origin should be set even when no item gets activated,
524
989
  // since `close` relies on it to emit the correct close reason.
525
- this.keyManager.setFocusOrigin(origin);
526
- if (origin === 'mouse' || origin === 'touch') {
990
+ this.setFocusOrigin(origin);
991
+ const search = this.search();
992
+ if (search) {
993
+ search.focus();
994
+ }
995
+ else if (this.parent?.inSearchMode?.()) {
996
+ return;
997
+ }
998
+ else if (origin === 'mouse' || origin === 'touch') {
527
999
  this.focusPanel();
528
1000
  }
529
1001
  else {
530
1002
  this.keyManager.setFirstItemActive();
531
1003
  }
532
1004
  }
1005
+ /**
1006
+ * Moves focus back into the projected search field, reporting whether there was one. A nested panel
1007
+ * restores focus through this instead of onto its trigger item, which would strand the caret outside
1008
+ * the query.
1009
+ * @docs-private
1010
+ */
1011
+ restoreFocus() {
1012
+ const search = this.search();
1013
+ search?.focus();
1014
+ return !!search;
1015
+ }
533
1016
  /** Moves DOM focus onto the dropdown panel so that keydown events keep being handled. */
534
1017
  focusPanel() {
535
1018
  // The panel is rendered into the overlay through a `TemplatePortal`, so it can't be
536
1019
  // queried with a `ViewChild`. If there are no rendered items, focus stays on the trigger,
537
1020
  // same as `setFirstItemActive` no-ops in that case.
538
1021
  const panel = this.directDescendantItems.first?.getHostElement().closest('.kbq-dropdown__panel');
539
- panel?.focus();
1022
+ panel?.focus({ preventScroll: true });
540
1023
  }
541
1024
  /**
542
1025
  * Resets the active item in the dropdown. This is used when the dropdown is opened, allowing
@@ -590,8 +1073,57 @@ class KbqDropdown {
590
1073
  }
591
1074
  }
592
1075
  close() {
593
- const focusOrigin = this.keyManager.getFocusOrigin() === 'keyboard' ? 'keydown' : 'click';
594
- this.closed.emit(focusOrigin);
1076
+ this.closed.emit(this.focusOrigin === 'keyboard' ? 'keydown' : 'click');
1077
+ }
1078
+ /**
1079
+ * With a search field the caret has to stay in the input, so the active item is only highlighted and
1080
+ * typeahead is left off — it would race the query the user is typing.
1081
+ */
1082
+ initKeyManager() {
1083
+ // The forked `ListKeyManager` subscribes to the item list in its constructor and has no teardown,
1084
+ // so a manager is built once per mode and kept — rebuilding on every switch would strand the
1085
+ // previous one, twice per open/close cycle with lazy content. The outgoing manager's highlight
1086
+ // has to go with it: the incoming one will never call `setInactiveStyles` on an item it does not
1087
+ // know about.
1088
+ if (this.keyManager) {
1089
+ this.resetActiveItem();
1090
+ }
1091
+ if (this.inSearchMode()) {
1092
+ this.activeDescendantKeyManager ??= this.configureKeyManager(new ActiveDescendantKeyManager(this.directDescendantItems));
1093
+ this.keyManager = this.activeDescendantKeyManager;
1094
+ }
1095
+ else {
1096
+ this.focusKeyManager ??= this.configureKeyManager(new FocusKeyManager(this.directDescendantItems).withTypeAhead());
1097
+ this.keyManager = this.focusKeyManager;
1098
+ }
1099
+ this.tabSubscription.unsubscribe();
1100
+ this.tabSubscription = this.keyManager.tabOut.subscribe(() => this.closed.emit('tab'));
1101
+ }
1102
+ /** Which mode the installed key manager serves; the wanted one is `inSearchMode()`. */
1103
+ keyManagerInstalledForSearch() {
1104
+ return this.keyManager === this.activeDescendantKeyManager;
1105
+ }
1106
+ configureKeyManager(keyManager) {
1107
+ return untracked(this.navigationWithWrap) ? keyManager.withWrap() : keyManager;
1108
+ }
1109
+ setFocusOrigin(origin) {
1110
+ this.focusOrigin = origin;
1111
+ if (this.keyManager instanceof FocusKeyManager) {
1112
+ this.keyManager.setFocusOrigin(origin);
1113
+ }
1114
+ }
1115
+ isActiveItemStale() {
1116
+ const activeItem = this.keyManager.activeItem;
1117
+ return !activeItem || !this.directDescendantItems.some((item) => item === activeItem);
1118
+ }
1119
+ /**
1120
+ * Reveals the highlighted item, which the browser only does on its own for real focus. Mirrors the
1121
+ * reveal `kbqFocusAndReveal` performs for focused elements.
1122
+ */
1123
+ revealActiveItem() {
1124
+ if (!this.inSearchMode())
1125
+ return;
1126
+ this.keyManager.activeItem?.getHostElement().scrollIntoView?.({ block: 'nearest', inline: 'nearest' });
595
1127
  }
596
1128
  /**
597
1129
  * Sets up a stream that will keep track of any newly-added menu items and will update the list
@@ -605,23 +1137,26 @@ class KbqDropdown {
605
1137
  this.directDescendantItems.notifyOnChanges();
606
1138
  });
607
1139
  }
608
- /** @nocollapse */ static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.25", ngImport: i0, type: KbqDropdown, deps: [], target: i0.ɵɵFactoryTarget.Component }); }
609
- /** @nocollapse */ static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.2.0", version: "20.3.25", type: KbqDropdown, isStandalone: true, selector: "kbq-dropdown", inputs: { navigationWithWrap: { classPropertyName: "navigationWithWrap", publicName: "navigationWithWrap", isSignal: true, isRequired: false, transformFunction: null }, xPosition: { classPropertyName: "xPosition", publicName: "xPosition", isSignal: false, isRequired: false, transformFunction: null }, yPosition: { classPropertyName: "yPosition", publicName: "yPosition", isSignal: false, isRequired: false, transformFunction: null }, overlapTriggerY: { classPropertyName: "overlapTriggerY", publicName: "overlapTriggerY", isSignal: false, isRequired: false, transformFunction: null }, overlapTriggerX: { classPropertyName: "overlapTriggerX", publicName: "overlapTriggerX", isSignal: false, isRequired: false, transformFunction: null }, hasBackdrop: { classPropertyName: "hasBackdrop", publicName: "hasBackdrop", isSignal: false, isRequired: false, transformFunction: null }, panelClass: { classPropertyName: "panelClass", publicName: "class", isSignal: false, isRequired: false, transformFunction: null }, backdropClass: { classPropertyName: "backdropClass", publicName: "backdropClass", isSignal: false, isRequired: false, transformFunction: null }, panelWidth: { classPropertyName: "panelWidth", publicName: "panelWidth", isSignal: true, isRequired: false, transformFunction: null }, panelMinWidth: { classPropertyName: "panelMinWidth", publicName: "panelMinWidth", isSignal: true, isRequired: false, transformFunction: null }, panelMaxWidth: { classPropertyName: "panelMaxWidth", publicName: "panelMaxWidth", isSignal: true, isRequired: false, transformFunction: null } }, outputs: { closed: "closed" }, providers: [
1140
+ /** @nocollapse */ static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.30", ngImport: i0, type: KbqDropdown, deps: [], target: i0.ɵɵFactoryTarget.Component }); }
1141
+ /** @nocollapse */ static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.2.0", version: "20.3.30", type: KbqDropdown, isStandalone: true, selector: "kbq-dropdown", inputs: { navigationWithWrap: { classPropertyName: "navigationWithWrap", publicName: "navigationWithWrap", isSignal: true, isRequired: false, transformFunction: null }, xPosition: { classPropertyName: "xPosition", publicName: "xPosition", isSignal: false, isRequired: false, transformFunction: null }, yPosition: { classPropertyName: "yPosition", publicName: "yPosition", isSignal: false, isRequired: false, transformFunction: null }, overlapTriggerY: { classPropertyName: "overlapTriggerY", publicName: "overlapTriggerY", isSignal: false, isRequired: false, transformFunction: null }, overlapTriggerX: { classPropertyName: "overlapTriggerX", publicName: "overlapTriggerX", isSignal: false, isRequired: false, transformFunction: null }, hasBackdrop: { classPropertyName: "hasBackdrop", publicName: "hasBackdrop", isSignal: false, isRequired: false, transformFunction: null }, panelClass: { classPropertyName: "panelClass", publicName: "class", isSignal: false, isRequired: false, transformFunction: null }, backdropClass: { classPropertyName: "backdropClass", publicName: "backdropClass", isSignal: false, isRequired: false, transformFunction: null }, panelWidth: { classPropertyName: "panelWidth", publicName: "panelWidth", isSignal: true, isRequired: false, transformFunction: null }, panelMinWidth: { classPropertyName: "panelMinWidth", publicName: "panelMinWidth", isSignal: true, isRequired: false, transformFunction: null }, panelMaxWidth: { classPropertyName: "panelMaxWidth", publicName: "panelMaxWidth", isSignal: true, isRequired: false, transformFunction: null }, safeArea: { classPropertyName: "safeArea", publicName: "safeArea", isSignal: true, isRequired: false, transformFunction: null } }, outputs: { closed: "closed" }, host: { styleAttribute: "display: contents" }, providers: [
610
1142
  { provide: KBQ_DROPDOWN_PANEL, useExisting: KbqDropdown }
611
- ], queries: [{ propertyName: "search", first: true, predicate: KbqFormField, descendants: true, isSignal: true }, { propertyName: "lazyContent", first: true, predicate: KbqDropdownContent, descendants: true }, { propertyName: "items", predicate: KbqDropdownItem, descendants: true }], viewQueries: [{ propertyName: "templateRef", first: true, predicate: TemplateRef, descendants: true }], exportAs: ["kbqDropdown"], ngImport: i0, template: "<ng-template>\n <div\n tabindex=\"-1\"\n class=\"kbq-dropdown__panel\"\n [class.kbq-dropdown__panel_nested]=\"parent\"\n [class]=\"classList\"\n [style.max-width.px]=\"panelMaxWidth()\"\n [style.--kbq-dropdown-size-container-width-min]=\"panelMinWidthToken()\"\n [@transformDropdown]=\"panelAnimationState\"\n (@transformDropdown.done)=\"onAnimationDone($event)\"\n (@transformDropdown.start)=\"onAnimationStart($event)\"\n (click)=\"close()\"\n (keydown)=\"handleKeydown($event)\"\n >\n <div class=\"kbq-dropdown__content\">\n <ng-content />\n </div>\n </div>\n</ng-template>\n\n<ng-content select=\"[kbqDropdownStaticContent]\" />\n", styles: [".kbq-dropdown-trigger.kbq-button{padding-left:calc(var(--kbq-dropdown-trigger-horizontal-padding, 10px) - var(--kbq-size-border-width));padding-right:calc(var(--kbq-dropdown-trigger-horizontal-padding, 10px) - var(--kbq-size-border-width))}.kbq-dropdown-trigger.kbq-button .kbq-icon_left{margin-right:var(--kbq-size-xs)}.kbq-dropdown-trigger.kbq-button .kbq-icon_right{margin-left:var(--kbq-size-3xs)}.kbq-dropdown-trigger.kbq-button-icon.kbq-button-icon_right.kbq-button-icon_left .kbq-icon_left{margin-right:0}.kbq-dropdown-trigger.kbq-button-icon.kbq-button-icon_right.kbq-button-icon_left .kbq-icon_right{margin-left:0}.kbq-dropdown-trigger__icon{margin-left:auto;align-self:center}.kbq-dropdown__panel{outline:none;overflow-x:hidden;overflow-y:auto;min-width:max(var(--kbq-dropdown-size-container-width-min),100%);max-width:var(--kbq-dropdown-size-container-width-max);border-radius:var(--kbq-dropdown-size-container-border-radius);box-sizing:border-box;padding:var(--kbq-size-xxs)}.kbq-dropdown__panel.ng-animating{pointer-events:none}.kbq-dropdown__panel .kbq-dropdown-item{position:relative}.kbq-dropdown__panel .kbq-dropdown-item:before,.kbq-dropdown__panel .kbq-dropdown-item:after{position:absolute;content:\"\";width:var(--kbq-size-xxs);height:calc(100% + var(--kbq-size-3xs) * 2)}.kbq-dropdown__panel .kbq-dropdown-item:before{right:calc(100% + var(--kbq-size-3xs))}.kbq-dropdown__panel .kbq-dropdown-item:after{left:calc(100% + var(--kbq-size-3xs))}.kbq-dropdown__panel .kbq-dropdown-item:before,.kbq-dropdown__panel .kbq-dropdown-item:after{top:calc(-1 * var(--kbq-size-3xs));bottom:calc(-1 * var(--kbq-size-3xs))}.kbq-dropdown__panel .kbq-dropdown-item.kbq-progress:after{background:none;animation:none}.kbq-dropdown__panel .kbq-divider{margin-left:calc(var(--kbq-size-xxs) * -1);margin-right:calc(var(--kbq-size-xxs) * -1)}.kbq-dropdown__content{display:flex;flex-direction:column}.kbq-dropdown__panel{box-shadow:var(--kbq-dropdown-container-shadow);background:var(--kbq-dropdown-container-background)}.kbq-dropdown-item{background:var(--kbq-list-default-container-background);color:var(--kbq-list-default-text-color)}.kbq-dropdown-item .kbq-icon.kbq-empty:not(.kbq-icon-button,.kbq-icon-item){color:var(--kbq-list-default-text-color)}.kbq-dropdown-item .kbq-dropdown-item__caption{color:var(--kbq-dropdown-item-caption-color)}.kbq-dropdown-item.kbq-dropdown-item_highlighted,.kbq-dropdown-item.cdk-focused:not(.kbq-disabled){background:var(--kbq-list-states-hover-container-background);color:var(--kbq-list-states-hover-text-color)}.kbq-dropdown-item.kbq-dropdown-item_highlighted .kbq-icon.kbq-empty:not(.kbq-icon-button,.kbq-icon-item),.kbq-dropdown-item.cdk-focused:not(.kbq-disabled) .kbq-icon.kbq-empty:not(.kbq-icon-button,.kbq-icon-item){color:var(--kbq-list-states-hover-text-color)}.kbq-dropdown-item.kbq-selected{background:var(--kbq-list-states-selected-container-background);color:var(--kbq-list-states-selected-text-color)}.kbq-dropdown-item.kbq-selected .kbq-icon.kbq-empty:not(.kbq-icon-button,.kbq-icon-item){color:var(--kbq-list-states-selected-text-color)}.kbq-dropdown-item.kbq-selected.cdk-focused:not(.kbq-disabled){background:var(--kbq-list-states-selected-hover-container-background);color:var(--kbq-list-states-selected-hover-text-color)}.kbq-dropdown-item.kbq-selected.cdk-focused:not(.kbq-disabled) .kbq-icon.kbq-empty:not(.kbq-icon-button,.kbq-icon-item){color:var(--kbq-list-states-selected-hover-text-color)}.kbq-dropdown-item.kbq-disabled{background:var(--kbq-list-states-disabled-container-background);color:var(--kbq-list-states-disabled-text-color)}.kbq-dropdown-item.kbq-disabled .kbq-icon.kbq-empty:not(.kbq-icon-button,.kbq-icon-item){color:var(--kbq-list-states-disabled-text-color)}.kbq-dropdown-item:is(.kbq-selected,.cdk-focused):has(+:is(.kbq-selected,.cdk-focused)){border-bottom-left-radius:0;border-bottom-right-radius:0}.kbq-dropdown-item:is(.kbq-selected,.cdk-focused)+:is(.kbq-selected,.cdk-focused){border-top-left-radius:0;border-top-right-radius:0}.kbq-dropdown__group-header.kbq-dropdown__group-header_small{color:var(--kbq-foreground-contrast-secondary)}.kbq-dropdown-item-overlay{background:transparent}.kbq-dropdown-item,.kbq-dropdown__content{font-size:var(--kbq-typography-text-normal-font-size);font-style:var(--kbq-typography-text-normal-font-style);font-weight:var(--kbq-typography-text-normal-font-weight);line-height:var(--kbq-typography-text-normal-line-height);font-family:var(--kbq-typography-text-normal-font-family);text-transform:var(--kbq-typography-text-normal-text-transform);font-feature-settings:var(--kbq-typography-text-normal-font-feature-settings);letter-spacing:var(--kbq-typography-text-normal-letter-spacing)}.kbq-dropdown-item .kbq-dropdown-item__caption,.kbq-dropdown__content .kbq-dropdown-item__caption{font-size:var(--kbq-typography-text-compact-font-size);font-style:var(--kbq-typography-text-compact-font-style);font-weight:var(--kbq-typography-text-compact-font-weight);line-height:var(--kbq-typography-text-compact-line-height);font-family:var(--kbq-typography-text-compact-font-family);text-transform:var(--kbq-typography-text-compact-text-transform);font-feature-settings:var(--kbq-typography-text-compact-font-feature-settings);letter-spacing:var(--kbq-typography-text-compact-letter-spacing)}.kbq-dropdown__group-header{font-size:var(--kbq-typography-big-strong-font-size);font-style:var(--kbq-typography-big-strong-font-style);font-weight:var(--kbq-typography-big-strong-font-weight);line-height:var(--kbq-typography-big-strong-line-height);font-family:var(--kbq-typography-big-strong-font-family);text-transform:var(--kbq-typography-big-strong-text-transform);font-feature-settings:var(--kbq-typography-big-strong-font-feature-settings);letter-spacing:var(--kbq-typography-big-strong-letter-spacing)}.kbq-dropdown__group-header.kbq-dropdown__group-header_small{font-size:var(--kbq-typography-caps-compact-strong-font-size);font-style:var(--kbq-typography-caps-compact-strong-font-style);font-weight:var(--kbq-typography-caps-compact-strong-font-weight);line-height:var(--kbq-typography-caps-compact-strong-line-height);font-family:var(--kbq-typography-caps-compact-strong-font-family);text-transform:var(--kbq-typography-caps-compact-strong-text-transform);font-feature-settings:var(--kbq-typography-caps-compact-strong-font-feature-settings);letter-spacing:var(--kbq-typography-caps-compact-strong-letter-spacing)}\n", ".kbq-list,.kbq-list-selection{--kbq-list-size-container-padding-left: var(--kbq-size-m);--kbq-list-size-container-padding-right: var(--kbq-size-m);--kbq-list-size-container-padding-vertical: var(--kbq-size-xs);--kbq-list-size-container-content-gap-horizontal: var(--kbq-size-s);--kbq-list-size-container-content-gap-vertical: var(--kbq-size-3xs);--kbq-list-size-container-focus-outline-width: var(--kbq-size-3xs);--kbq-list-size-header-padding-top: var(--kbq-size-s);--kbq-list-size-header-padding-bottom: var(--kbq-size-xxs);--kbq-list-size-header-padding-horizontal: var(--kbq-size-m);--kbq-list-size-subheading-padding-top: var(--kbq-size-m);--kbq-list-size-subheading-padding-bottom: var(--kbq-size-xxs);--kbq-list-size-subheading-padding-horizontal: var(--kbq-size-m);--kbq-list-default-container-background: transparent;--kbq-list-default-text-color: var(--kbq-foreground-contrast);--kbq-list-default-icon-color: var(--kbq-icon-contrast);--kbq-list-default-icon-button-color: var(--kbq-icon-contrast-fade);--kbq-list-default-caption-color: var(--kbq-foreground-contrast-secondary);--kbq-list-states-hover-container-background: var(--kbq-states-background-transparent-hover);--kbq-list-states-active-container-background: var(--kbq-states-background-transparent-active);--kbq-list-states-hover-text-color: var(--kbq-foreground-contrast);--kbq-list-states-hover-icon-color: var(--kbq-icon-contrast);--kbq-list-states-hover-icon-button-color: var(--kbq-icon-contrast-fade);--kbq-list-states-selected-container-background: var(--kbq-background-theme-less);--kbq-list-multiple-states-selected-container-background: var(--kbq-background-contrast-less);--kbq-list-states-selected-text-color: var(--kbq-foreground-contrast);--kbq-list-states-selected-icon-color: var(--kbq-icon-contrast);--kbq-list-states-selected-icon-button-color: var(--kbq-icon-contrast-fade);--kbq-list-states-selected-hover-container-background: var(--kbq-states-background-theme-less-hover);--kbq-list-multiple-states-selected-hover-container-background: var(--kbq-states-background-contrast-less-hover);--kbq-list-states-selected-active-container-background: var(--kbq-states-background-theme-less-active);--kbq-list-multiple-states-selected-active-container-background: var(--kbq-states-background-contrast-less-active);--kbq-list-states-selected-hover-text-color: var(--kbq-foreground-contrast);--kbq-list-states-selected-hover-icon-color: var(--kbq-icon-contrast);--kbq-list-states-selected-hover-icon-button-color: var(--kbq-icon-contrast-fade);--kbq-list-states-focused-focus-outline-color: var(--kbq-states-line-focus-theme);--kbq-list-states-disabled-container-background: transparent;--kbq-list-states-disabled-text-color: var(--kbq-states-foreground-disabled);--kbq-list-states-disabled-icon-color: var(--kbq-states-icon-disabled);--kbq-list-states-disabled-icon-button-color: var(--kbq-states-icon-disabled);--kbq-list-states-disabled-caption-color: var(--kbq-states-foreground-disabled)}.kbq-dropdown__panel{--kbq-dropdown-size-container-width-min: 200px;--kbq-dropdown-size-container-width-max: var(--kbq-panel-size-width-max, 640px);--kbq-dropdown-size-container-padding-vertical: var(--kbq-size-xxs);--kbq-dropdown-size-container-border-radius: var(--kbq-size-s);--kbq-dropdown-container-background: var(--kbq-background-card);--kbq-dropdown-container-shadow: var(--kbq-shadow-popup);--kbq-dropdown-item-border-radius: var(--kbq-size-xs);--kbq-dropdown-item-caption-color: var(--kbq-foreground-contrast-secondary);--kbq-list-default-container-background: transparent;--kbq-list-default-text-color: var(--kbq-foreground-contrast);--kbq-list-default-icon-color: var(--kbq-icon-contrast);--kbq-list-default-icon-button-color: var(--kbq-icon-contrast-fade);--kbq-list-default-caption-color: var(--kbq-foreground-contrast-secondary);--kbq-list-states-hover-container-background: var(--kbq-states-background-transparent-hover);--kbq-list-states-active-container-background: var(--kbq-states-background-transparent-active);--kbq-list-states-hover-text-color: var(--kbq-foreground-contrast);--kbq-list-states-hover-icon-color: var(--kbq-icon-contrast);--kbq-list-states-hover-icon-button-color: var(--kbq-icon-contrast-fade);--kbq-list-states-selected-container-background: var(--kbq-background-theme-less);--kbq-list-multiple-states-selected-container-background: var(--kbq-background-contrast-less);--kbq-list-states-selected-text-color: var(--kbq-foreground-contrast);--kbq-list-states-selected-icon-color: var(--kbq-icon-contrast);--kbq-list-states-selected-icon-button-color: var(--kbq-icon-contrast-fade);--kbq-list-states-selected-hover-container-background: var(--kbq-states-background-theme-less-hover);--kbq-list-multiple-states-selected-hover-container-background: var(--kbq-states-background-contrast-less-hover);--kbq-list-states-selected-active-container-background: var(--kbq-states-background-theme-less-active);--kbq-list-multiple-states-selected-active-container-background: var(--kbq-states-background-contrast-less-active);--kbq-list-states-selected-hover-text-color: var(--kbq-foreground-contrast);--kbq-list-states-selected-hover-icon-color: var(--kbq-icon-contrast);--kbq-list-states-selected-hover-icon-button-color: var(--kbq-icon-contrast-fade);--kbq-list-states-focused-focus-outline-color: var(--kbq-states-line-focus-theme);--kbq-list-states-disabled-container-background: transparent;--kbq-list-states-disabled-text-color: var(--kbq-states-foreground-disabled);--kbq-list-states-disabled-icon-color: var(--kbq-states-icon-disabled);--kbq-list-states-disabled-icon-button-color: var(--kbq-states-icon-disabled);--kbq-list-states-disabled-caption-color: var(--kbq-states-foreground-disabled)}\n"], animations: [
1143
+ ], queries: [{ propertyName: "panelFormField", first: true, predicate: KbqFormField, descendants: true, isSignal: true }, { propertyName: "searches", predicate: KbqDropdownSearch, descendants: true, isSignal: true }, { propertyName: "lazyContent", first: true, predicate: KbqDropdownContent, descendants: true }, { propertyName: "items", predicate: KbqDropdownItem, descendants: true }], viewQueries: [{ propertyName: "templateRef", first: true, predicate: TemplateRef, descendants: true }], exportAs: ["kbqDropdown"], ngImport: i0, template: "<ng-template>\n <div\n tabindex=\"-1\"\n class=\"kbq-dropdown__panel\"\n [class.kbq-dropdown__panel_nested]=\"parent\"\n [class]=\"classList\"\n [style.max-width.px]=\"panelMaxWidth()\"\n [style.--kbq-dropdown-size-container-width-min]=\"panelMinWidthToken()\"\n [@transformDropdown]=\"panelAnimationState\"\n (@transformDropdown.done)=\"onAnimationDone($event)\"\n (@transformDropdown.start)=\"onAnimationStart($event)\"\n (click)=\"close()\"\n (keydown)=\"handleKeydown($event)\"\n >\n <div class=\"kbq-dropdown__content\">\n <ng-content />\n </div>\n <ng-content select=\"[kbqDropdownFooter], kbq-dropdown-footer\" />\n </div>\n</ng-template>\n\n<ng-content select=\"[kbqDropdownStaticContent]\" />\n", styles: [".kbq-dropdown-footer{-webkit-user-select:none;-moz-user-select:none;-ms-user-select:none;user-select:none;display:flex;align-items:center;box-sizing:border-box;min-height:40px;border-top-width:1px;border-top-style:solid;padding:var(--kbq-size-xxs) var(--kbq-size-l)}.kbq-dropdown-trigger.kbq-button{padding-left:calc(var(--kbq-dropdown-trigger-horizontal-padding, 10px) - var(--kbq-size-border-width));padding-right:calc(var(--kbq-dropdown-trigger-horizontal-padding, 10px) - var(--kbq-size-border-width))}.kbq-dropdown-trigger.kbq-button .kbq-icon_left{margin-right:var(--kbq-size-xs)}.kbq-dropdown-trigger.kbq-button .kbq-icon_right{margin-left:var(--kbq-size-3xs)}.kbq-dropdown-trigger.kbq-button-icon.kbq-button-icon_right.kbq-button-icon_left .kbq-icon_left{margin-right:0}.kbq-dropdown-trigger.kbq-button-icon.kbq-button-icon_right.kbq-button-icon_left .kbq-icon_right{margin-left:0}.kbq-dropdown-trigger__icon{margin-left:auto;align-self:center}.kbq-dropdown__panel{outline:none;overflow-x:hidden;overflow-y:auto;min-width:max(var(--kbq-dropdown-size-container-width-min),100%);max-width:var(--kbq-dropdown-size-container-width-max);border-radius:var(--kbq-dropdown-size-container-border-radius);box-sizing:border-box}.kbq-dropdown__panel.ng-animating{pointer-events:none}.kbq-dropdown__panel .kbq-dropdown-item{position:relative}.kbq-dropdown__panel .kbq-dropdown-item:before,.kbq-dropdown__panel .kbq-dropdown-item:after{position:absolute;content:\"\";width:var(--kbq-size-xxs);height:calc(100% + var(--kbq-size-3xs) * 2)}.kbq-dropdown__panel .kbq-dropdown-item:before{right:calc(100% + var(--kbq-size-3xs))}.kbq-dropdown__panel .kbq-dropdown-item:after{left:calc(100% + var(--kbq-size-3xs))}.kbq-dropdown__panel .kbq-dropdown-item:before,.kbq-dropdown__panel .kbq-dropdown-item:after{top:calc(-1 * var(--kbq-size-3xs));bottom:calc(-1 * var(--kbq-size-3xs))}.kbq-dropdown__panel .kbq-dropdown-item.kbq-progress:after{background:none;animation:none}.kbq-dropdown__panel .kbq-divider{margin-left:calc(var(--kbq-size-xxs) * -1);margin-right:calc(var(--kbq-size-xxs) * -1)}.kbq-dropdown__content{display:flex;flex-direction:column;padding:var(--kbq-size-xxs)}.kbq-dropdown-footer{border-color:var(--kbq-line-contrast-less)}.kbq-dropdown__panel{box-shadow:var(--kbq-dropdown-container-shadow);background:var(--kbq-dropdown-container-background)}.kbq-dropdown-item{background:var(--kbq-list-default-container-background);color:var(--kbq-list-default-text-color)}.kbq-dropdown-item .kbq-icon.kbq-empty:not(.kbq-icon-button,.kbq-icon-item){color:var(--kbq-list-default-text-color)}.kbq-dropdown-item .kbq-dropdown-item__caption{color:var(--kbq-dropdown-item-caption-color)}.kbq-dropdown-item.kbq-dropdown-item_highlighted,.kbq-dropdown-item.kbq-dropdown-item_active:not(.kbq-disabled),.kbq-dropdown-item.cdk-focused:not(.kbq-disabled){background:var(--kbq-list-states-hover-container-background);color:var(--kbq-list-states-hover-text-color)}.kbq-dropdown-item.kbq-dropdown-item_highlighted .kbq-icon.kbq-empty:not(.kbq-icon-button,.kbq-icon-item),.kbq-dropdown-item.kbq-dropdown-item_active:not(.kbq-disabled) .kbq-icon.kbq-empty:not(.kbq-icon-button,.kbq-icon-item),.kbq-dropdown-item.cdk-focused:not(.kbq-disabled) .kbq-icon.kbq-empty:not(.kbq-icon-button,.kbq-icon-item){color:var(--kbq-list-states-hover-text-color)}.kbq-dropdown-item .kbq-dropdown__panel_safe-area-active.cdk-focused:not(.kbq-dropdown-item_highlighted,.kbq-selected,.kbq-disabled){background:var(--kbq-list-default-container-background);color:var(--kbq-list-default-text-color)}.kbq-dropdown-item .kbq-dropdown__panel_safe-area-active.cdk-focused:not(.kbq-dropdown-item_highlighted,.kbq-selected,.kbq-disabled) .kbq-icon.kbq-empty:not(.kbq-icon-button,.kbq-icon-item){color:var(--kbq-list-default-text-color)}.kbq-dropdown-item:active:not(.kbq-disabled),.kbq-dropdown-item.kbq-active:not(.kbq-disabled){background:var(--kbq-list-states-active-container-background)}.kbq-dropdown-item.kbq-selected{background:var(--kbq-list-states-selected-container-background);color:var(--kbq-list-states-selected-text-color)}.kbq-dropdown-item.kbq-selected .kbq-icon.kbq-empty:not(.kbq-icon-button,.kbq-icon-item){color:var(--kbq-list-states-selected-text-color)}.kbq-dropdown-item.kbq-selected.kbq-dropdown-item_active:not(.kbq-disabled),.kbq-dropdown-item.kbq-selected.cdk-focused:not(.kbq-disabled){background:var(--kbq-list-states-selected-hover-container-background);color:var(--kbq-list-states-selected-hover-text-color)}.kbq-dropdown-item.kbq-selected.kbq-dropdown-item_active:not(.kbq-disabled) .kbq-icon.kbq-empty:not(.kbq-icon-button,.kbq-icon-item),.kbq-dropdown-item.kbq-selected.cdk-focused:not(.kbq-disabled) .kbq-icon.kbq-empty:not(.kbq-icon-button,.kbq-icon-item){color:var(--kbq-list-states-selected-hover-text-color)}.kbq-dropdown-item.kbq-selected:active:not(.kbq-disabled),.kbq-dropdown-item.kbq-selected.kbq-active:not(.kbq-disabled){background:var(--kbq-list-states-selected-active-container-background)}.kbq-dropdown-item.kbq-disabled{background:var(--kbq-list-states-disabled-container-background);color:var(--kbq-list-states-disabled-text-color)}.kbq-dropdown-item.kbq-disabled .kbq-icon.kbq-empty:not(.kbq-icon-button,.kbq-icon-item){color:var(--kbq-list-states-disabled-text-color)}.kbq-dropdown-item:is(.kbq-selected,.cdk-focused,.kbq-dropdown-item_active):has(+:is(.kbq-selected,.cdk-focused,.kbq-dropdown-item_active)){border-bottom-left-radius:0;border-bottom-right-radius:0}.kbq-dropdown-item:is(.kbq-selected,.cdk-focused,.kbq-dropdown-item_active)+:is(.kbq-selected,.cdk-focused,.kbq-dropdown-item_active){border-top-left-radius:0;border-top-right-radius:0}.kbq-dropdown__group-header.kbq-dropdown__group-header_small{color:var(--kbq-foreground-contrast-secondary)}.kbq-dropdown-item-overlay{background:transparent}.kbq-dropdown-item,.kbq-dropdown__content{font-size:var(--kbq-typography-text-normal-font-size);font-style:var(--kbq-typography-text-normal-font-style);font-weight:var(--kbq-typography-text-normal-font-weight);line-height:var(--kbq-typography-text-normal-line-height);font-family:var(--kbq-typography-text-normal-font-family);text-transform:var(--kbq-typography-text-normal-text-transform);font-feature-settings:var(--kbq-typography-text-normal-font-feature-settings);letter-spacing:var(--kbq-typography-text-normal-letter-spacing)}.kbq-dropdown-item .kbq-dropdown-item__caption,.kbq-dropdown__content .kbq-dropdown-item__caption{font-size:var(--kbq-typography-text-compact-font-size);font-style:var(--kbq-typography-text-compact-font-style);font-weight:var(--kbq-typography-text-compact-font-weight);line-height:var(--kbq-typography-text-compact-line-height);font-family:var(--kbq-typography-text-compact-font-family);text-transform:var(--kbq-typography-text-compact-text-transform);font-feature-settings:var(--kbq-typography-text-compact-font-feature-settings);letter-spacing:var(--kbq-typography-text-compact-letter-spacing)}.kbq-dropdown__group-header{font-size:var(--kbq-typography-big-strong-font-size);font-style:var(--kbq-typography-big-strong-font-style);font-weight:var(--kbq-typography-big-strong-font-weight);line-height:var(--kbq-typography-big-strong-line-height);font-family:var(--kbq-typography-big-strong-font-family);text-transform:var(--kbq-typography-big-strong-text-transform);font-feature-settings:var(--kbq-typography-big-strong-font-feature-settings);letter-spacing:var(--kbq-typography-big-strong-letter-spacing)}.kbq-dropdown__group-header.kbq-dropdown__group-header_small{font-size:var(--kbq-typography-caps-compact-strong-font-size);font-style:var(--kbq-typography-caps-compact-strong-font-style);font-weight:var(--kbq-typography-caps-compact-strong-font-weight);line-height:var(--kbq-typography-caps-compact-strong-line-height);font-family:var(--kbq-typography-caps-compact-strong-font-family);text-transform:var(--kbq-typography-caps-compact-strong-text-transform);font-feature-settings:var(--kbq-typography-caps-compact-strong-font-feature-settings);letter-spacing:var(--kbq-typography-caps-compact-strong-letter-spacing)}\n", "@charset \"UTF-8\";.kbq-list,.kbq-list-selection,.kbq-list-option.cdk-drag-preview,.kbq-list-drag-preview_text{--kbq-list-size-container-padding-left: var(--kbq-size-m);--kbq-list-size-container-padding-right: var(--kbq-size-m);--kbq-list-size-container-padding-vertical: var(--kbq-size-xxs);--kbq-list-size-container-content-gap-horizontal: var(--kbq-size-s);--kbq-list-size-container-content-gap-vertical: var(--kbq-size-3xs);--kbq-list-size-container-focus-outline-width: var(--kbq-size-3xs);--kbq-list-default-container-background: transparent;--kbq-list-default-text-color: var(--kbq-foreground-contrast);--kbq-list-default-icon-color: var(--kbq-icon-contrast);--kbq-list-default-icon-button-color: var(--kbq-icon-contrast-fade);--kbq-list-default-caption-color: var(--kbq-foreground-contrast-secondary);--kbq-list-states-hover-container-background: var(--kbq-states-background-transparent-hover);--kbq-list-states-active-container-background: var(--kbq-states-background-transparent-active);--kbq-list-states-hover-text-color: var(--kbq-foreground-contrast);--kbq-list-states-hover-icon-color: var(--kbq-icon-contrast);--kbq-list-states-hover-icon-button-color: var(--kbq-icon-contrast-fade);--kbq-list-states-hover-caption-color: var(--kbq-foreground-contrast-secondary);--kbq-list-states-selected-container-background: var(--kbq-background-theme-less);--kbq-list-multiple-states-selected-container-background: var(--kbq-background-contrast-less);--kbq-list-states-selected-text-color: var(--kbq-foreground-contrast);--kbq-list-states-selected-icon-color: var(--kbq-icon-contrast);--kbq-list-states-selected-icon-button-color: var(--kbq-icon-contrast-fade);--kbq-list-states-selected-caption-color: var(--kbq-foreground-contrast-secondary);--kbq-list-multiple-states-selected-text-color: var(--kbq-foreground-contrast);--kbq-list-multiple-states-selected-icon-color: var(--kbq-icon-contrast);--kbq-list-multiple-states-selected-icon-button-color: var(--kbq-icon-contrast-fade);--kbq-list-multiple-states-selected-caption-color: var(--kbq-foreground-contrast-secondary);--kbq-list-states-selected-hover-container-background: var(--kbq-states-background-theme-less-hover);--kbq-list-multiple-states-selected-hover-container-background: var(--kbq-states-background-contrast-less-hover);--kbq-list-states-selected-active-container-background: var(--kbq-states-background-theme-less-active);--kbq-list-multiple-states-selected-active-container-background: var(--kbq-states-background-contrast-less-active);--kbq-list-states-selected-hover-text-color: var(--kbq-foreground-contrast);--kbq-list-states-selected-hover-icon-color: var(--kbq-icon-contrast);--kbq-list-states-selected-hover-icon-button-color: var(--kbq-icon-contrast-fade);--kbq-list-states-selected-hover-caption-color: var(--kbq-foreground-contrast-secondary);--kbq-list-multiple-states-selected-hover-text-color: var(--kbq-foreground-contrast);--kbq-list-multiple-states-selected-hover-icon-color: var(--kbq-icon-contrast);--kbq-list-multiple-states-selected-hover-icon-button-color: var(--kbq-icon-contrast-fade);--kbq-list-multiple-states-selected-hover-caption-color: var(--kbq-foreground-contrast-secondary);--kbq-list-states-focused-focus-outline-color: var(--kbq-states-line-focus-theme);--kbq-list-states-disabled-container-background: transparent;--kbq-list-states-disabled-text-color: var(--kbq-states-foreground-disabled);--kbq-list-states-disabled-icon-color: var(--kbq-states-icon-disabled);--kbq-list-states-disabled-icon-button-color: var(--kbq-states-icon-disabled);--kbq-list-states-disabled-caption-color: var(--kbq-states-foreground-disabled);--kbq-list-states-dragged-container-background: var(--kbq-background-card);--kbq-list-states-dragged-container-shadow: var(--kbq-shadow-popup)}.kbq-list-selection{--kbq-list-size-dragged-indicator-thickness: var(--kbq-size-3xs);--kbq-list-states-dragged-indicator-color: var(--kbq-line-theme)}.kbq-list-drag-preview_text{--kbq-list-size-drag-preview-max-width: 480px;--kbq-list-states-drag-preview-background: color-mix( in srgb, var(--kbq-background-card) calc(var(--kbq-opacity-overlay) * 100%), transparent )}.kbq-dropdown__panel{--kbq-dropdown-size-container-width-min: 200px;--kbq-dropdown-size-container-width-max: var(--kbq-panel-size-width-max, 640px);--kbq-dropdown-size-container-padding-vertical: var(--kbq-size-xxs);--kbq-dropdown-size-container-border-radius: var(--kbq-size-s);--kbq-dropdown-container-background: var(--kbq-background-card);--kbq-dropdown-container-shadow: var(--kbq-shadow-popup);--kbq-dropdown-item-border-radius: var(--kbq-size-xs);--kbq-dropdown-item-caption-color: var(--kbq-foreground-contrast-secondary);--kbq-list-default-container-background: transparent;--kbq-list-default-text-color: var(--kbq-foreground-contrast);--kbq-list-default-icon-color: var(--kbq-icon-contrast);--kbq-list-default-icon-button-color: var(--kbq-icon-contrast-fade);--kbq-list-default-caption-color: var(--kbq-foreground-contrast-secondary);--kbq-list-states-hover-container-background: var(--kbq-states-background-transparent-hover);--kbq-list-states-active-container-background: var(--kbq-states-background-transparent-active);--kbq-list-states-hover-text-color: var(--kbq-foreground-contrast);--kbq-list-states-hover-icon-color: var(--kbq-icon-contrast);--kbq-list-states-hover-icon-button-color: var(--kbq-icon-contrast-fade);--kbq-list-states-hover-caption-color: var(--kbq-foreground-contrast-secondary);--kbq-list-states-selected-container-background: var(--kbq-background-theme-less);--kbq-list-multiple-states-selected-container-background: var(--kbq-background-contrast-less);--kbq-list-states-selected-text-color: var(--kbq-foreground-contrast);--kbq-list-states-selected-icon-color: var(--kbq-icon-contrast);--kbq-list-states-selected-icon-button-color: var(--kbq-icon-contrast-fade);--kbq-list-states-selected-caption-color: var(--kbq-foreground-contrast-secondary);--kbq-list-multiple-states-selected-text-color: var(--kbq-foreground-contrast);--kbq-list-multiple-states-selected-icon-color: var(--kbq-icon-contrast);--kbq-list-multiple-states-selected-icon-button-color: var(--kbq-icon-contrast-fade);--kbq-list-multiple-states-selected-caption-color: var(--kbq-foreground-contrast-secondary);--kbq-list-states-selected-hover-container-background: var(--kbq-states-background-theme-less-hover);--kbq-list-multiple-states-selected-hover-container-background: var(--kbq-states-background-contrast-less-hover);--kbq-list-states-selected-active-container-background: var(--kbq-states-background-theme-less-active);--kbq-list-multiple-states-selected-active-container-background: var(--kbq-states-background-contrast-less-active);--kbq-list-states-selected-hover-text-color: var(--kbq-foreground-contrast);--kbq-list-states-selected-hover-icon-color: var(--kbq-icon-contrast);--kbq-list-states-selected-hover-icon-button-color: var(--kbq-icon-contrast-fade);--kbq-list-states-selected-hover-caption-color: var(--kbq-foreground-contrast-secondary);--kbq-list-multiple-states-selected-hover-text-color: var(--kbq-foreground-contrast);--kbq-list-multiple-states-selected-hover-icon-color: var(--kbq-icon-contrast);--kbq-list-multiple-states-selected-hover-icon-button-color: var(--kbq-icon-contrast-fade);--kbq-list-multiple-states-selected-hover-caption-color: var(--kbq-foreground-contrast-secondary);--kbq-list-states-focused-focus-outline-color: var(--kbq-states-line-focus-theme);--kbq-list-states-disabled-container-background: transparent;--kbq-list-states-disabled-text-color: var(--kbq-states-foreground-disabled);--kbq-list-states-disabled-icon-color: var(--kbq-states-icon-disabled);--kbq-list-states-disabled-icon-button-color: var(--kbq-states-icon-disabled);--kbq-list-states-disabled-caption-color: var(--kbq-states-foreground-disabled);--kbq-list-states-dragged-container-background: var(--kbq-background-card);--kbq-list-states-dragged-container-shadow: var(--kbq-shadow-popup)}\n"], animations: [
612
1144
  kbqDropdownAnimations.transformDropdown,
613
1145
  kbqDropdownAnimations.fadeInItems
614
1146
  ], changeDetection: i0.ChangeDetectionStrategy.OnPush, encapsulation: i0.ViewEncapsulation.None }); }
615
1147
  }
616
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.25", ngImport: i0, type: KbqDropdown, decorators: [{
1148
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.30", ngImport: i0, type: KbqDropdown, decorators: [{
617
1149
  type: Component,
618
1150
  args: [{ selector: 'kbq-dropdown', imports: [], providers: [
619
1151
  { provide: KBQ_DROPDOWN_PANEL, useExisting: KbqDropdown }
620
- ], changeDetection: ChangeDetectionStrategy.OnPush, encapsulation: ViewEncapsulation.None, animations: [
1152
+ ], changeDetection: ChangeDetectionStrategy.OnPush, encapsulation: ViewEncapsulation.None, host: {
1153
+ // Remove the TemplatePortal host box from layout while keeping kbqDropdownStaticContent in the document flow.
1154
+ style: 'display: contents'
1155
+ }, animations: [
621
1156
  kbqDropdownAnimations.transformDropdown,
622
1157
  kbqDropdownAnimations.fadeInItems
623
- ], exportAs: 'kbqDropdown', template: "<ng-template>\n <div\n tabindex=\"-1\"\n class=\"kbq-dropdown__panel\"\n [class.kbq-dropdown__panel_nested]=\"parent\"\n [class]=\"classList\"\n [style.max-width.px]=\"panelMaxWidth()\"\n [style.--kbq-dropdown-size-container-width-min]=\"panelMinWidthToken()\"\n [@transformDropdown]=\"panelAnimationState\"\n (@transformDropdown.done)=\"onAnimationDone($event)\"\n (@transformDropdown.start)=\"onAnimationStart($event)\"\n (click)=\"close()\"\n (keydown)=\"handleKeydown($event)\"\n >\n <div class=\"kbq-dropdown__content\">\n <ng-content />\n </div>\n </div>\n</ng-template>\n\n<ng-content select=\"[kbqDropdownStaticContent]\" />\n", styles: [".kbq-dropdown-trigger.kbq-button{padding-left:calc(var(--kbq-dropdown-trigger-horizontal-padding, 10px) - var(--kbq-size-border-width));padding-right:calc(var(--kbq-dropdown-trigger-horizontal-padding, 10px) - var(--kbq-size-border-width))}.kbq-dropdown-trigger.kbq-button .kbq-icon_left{margin-right:var(--kbq-size-xs)}.kbq-dropdown-trigger.kbq-button .kbq-icon_right{margin-left:var(--kbq-size-3xs)}.kbq-dropdown-trigger.kbq-button-icon.kbq-button-icon_right.kbq-button-icon_left .kbq-icon_left{margin-right:0}.kbq-dropdown-trigger.kbq-button-icon.kbq-button-icon_right.kbq-button-icon_left .kbq-icon_right{margin-left:0}.kbq-dropdown-trigger__icon{margin-left:auto;align-self:center}.kbq-dropdown__panel{outline:none;overflow-x:hidden;overflow-y:auto;min-width:max(var(--kbq-dropdown-size-container-width-min),100%);max-width:var(--kbq-dropdown-size-container-width-max);border-radius:var(--kbq-dropdown-size-container-border-radius);box-sizing:border-box;padding:var(--kbq-size-xxs)}.kbq-dropdown__panel.ng-animating{pointer-events:none}.kbq-dropdown__panel .kbq-dropdown-item{position:relative}.kbq-dropdown__panel .kbq-dropdown-item:before,.kbq-dropdown__panel .kbq-dropdown-item:after{position:absolute;content:\"\";width:var(--kbq-size-xxs);height:calc(100% + var(--kbq-size-3xs) * 2)}.kbq-dropdown__panel .kbq-dropdown-item:before{right:calc(100% + var(--kbq-size-3xs))}.kbq-dropdown__panel .kbq-dropdown-item:after{left:calc(100% + var(--kbq-size-3xs))}.kbq-dropdown__panel .kbq-dropdown-item:before,.kbq-dropdown__panel .kbq-dropdown-item:after{top:calc(-1 * var(--kbq-size-3xs));bottom:calc(-1 * var(--kbq-size-3xs))}.kbq-dropdown__panel .kbq-dropdown-item.kbq-progress:after{background:none;animation:none}.kbq-dropdown__panel .kbq-divider{margin-left:calc(var(--kbq-size-xxs) * -1);margin-right:calc(var(--kbq-size-xxs) * -1)}.kbq-dropdown__content{display:flex;flex-direction:column}.kbq-dropdown__panel{box-shadow:var(--kbq-dropdown-container-shadow);background:var(--kbq-dropdown-container-background)}.kbq-dropdown-item{background:var(--kbq-list-default-container-background);color:var(--kbq-list-default-text-color)}.kbq-dropdown-item .kbq-icon.kbq-empty:not(.kbq-icon-button,.kbq-icon-item){color:var(--kbq-list-default-text-color)}.kbq-dropdown-item .kbq-dropdown-item__caption{color:var(--kbq-dropdown-item-caption-color)}.kbq-dropdown-item.kbq-dropdown-item_highlighted,.kbq-dropdown-item.cdk-focused:not(.kbq-disabled){background:var(--kbq-list-states-hover-container-background);color:var(--kbq-list-states-hover-text-color)}.kbq-dropdown-item.kbq-dropdown-item_highlighted .kbq-icon.kbq-empty:not(.kbq-icon-button,.kbq-icon-item),.kbq-dropdown-item.cdk-focused:not(.kbq-disabled) .kbq-icon.kbq-empty:not(.kbq-icon-button,.kbq-icon-item){color:var(--kbq-list-states-hover-text-color)}.kbq-dropdown-item.kbq-selected{background:var(--kbq-list-states-selected-container-background);color:var(--kbq-list-states-selected-text-color)}.kbq-dropdown-item.kbq-selected .kbq-icon.kbq-empty:not(.kbq-icon-button,.kbq-icon-item){color:var(--kbq-list-states-selected-text-color)}.kbq-dropdown-item.kbq-selected.cdk-focused:not(.kbq-disabled){background:var(--kbq-list-states-selected-hover-container-background);color:var(--kbq-list-states-selected-hover-text-color)}.kbq-dropdown-item.kbq-selected.cdk-focused:not(.kbq-disabled) .kbq-icon.kbq-empty:not(.kbq-icon-button,.kbq-icon-item){color:var(--kbq-list-states-selected-hover-text-color)}.kbq-dropdown-item.kbq-disabled{background:var(--kbq-list-states-disabled-container-background);color:var(--kbq-list-states-disabled-text-color)}.kbq-dropdown-item.kbq-disabled .kbq-icon.kbq-empty:not(.kbq-icon-button,.kbq-icon-item){color:var(--kbq-list-states-disabled-text-color)}.kbq-dropdown-item:is(.kbq-selected,.cdk-focused):has(+:is(.kbq-selected,.cdk-focused)){border-bottom-left-radius:0;border-bottom-right-radius:0}.kbq-dropdown-item:is(.kbq-selected,.cdk-focused)+:is(.kbq-selected,.cdk-focused){border-top-left-radius:0;border-top-right-radius:0}.kbq-dropdown__group-header.kbq-dropdown__group-header_small{color:var(--kbq-foreground-contrast-secondary)}.kbq-dropdown-item-overlay{background:transparent}.kbq-dropdown-item,.kbq-dropdown__content{font-size:var(--kbq-typography-text-normal-font-size);font-style:var(--kbq-typography-text-normal-font-style);font-weight:var(--kbq-typography-text-normal-font-weight);line-height:var(--kbq-typography-text-normal-line-height);font-family:var(--kbq-typography-text-normal-font-family);text-transform:var(--kbq-typography-text-normal-text-transform);font-feature-settings:var(--kbq-typography-text-normal-font-feature-settings);letter-spacing:var(--kbq-typography-text-normal-letter-spacing)}.kbq-dropdown-item .kbq-dropdown-item__caption,.kbq-dropdown__content .kbq-dropdown-item__caption{font-size:var(--kbq-typography-text-compact-font-size);font-style:var(--kbq-typography-text-compact-font-style);font-weight:var(--kbq-typography-text-compact-font-weight);line-height:var(--kbq-typography-text-compact-line-height);font-family:var(--kbq-typography-text-compact-font-family);text-transform:var(--kbq-typography-text-compact-text-transform);font-feature-settings:var(--kbq-typography-text-compact-font-feature-settings);letter-spacing:var(--kbq-typography-text-compact-letter-spacing)}.kbq-dropdown__group-header{font-size:var(--kbq-typography-big-strong-font-size);font-style:var(--kbq-typography-big-strong-font-style);font-weight:var(--kbq-typography-big-strong-font-weight);line-height:var(--kbq-typography-big-strong-line-height);font-family:var(--kbq-typography-big-strong-font-family);text-transform:var(--kbq-typography-big-strong-text-transform);font-feature-settings:var(--kbq-typography-big-strong-font-feature-settings);letter-spacing:var(--kbq-typography-big-strong-letter-spacing)}.kbq-dropdown__group-header.kbq-dropdown__group-header_small{font-size:var(--kbq-typography-caps-compact-strong-font-size);font-style:var(--kbq-typography-caps-compact-strong-font-style);font-weight:var(--kbq-typography-caps-compact-strong-font-weight);line-height:var(--kbq-typography-caps-compact-strong-line-height);font-family:var(--kbq-typography-caps-compact-strong-font-family);text-transform:var(--kbq-typography-caps-compact-strong-text-transform);font-feature-settings:var(--kbq-typography-caps-compact-strong-font-feature-settings);letter-spacing:var(--kbq-typography-caps-compact-strong-letter-spacing)}\n", ".kbq-list,.kbq-list-selection{--kbq-list-size-container-padding-left: var(--kbq-size-m);--kbq-list-size-container-padding-right: var(--kbq-size-m);--kbq-list-size-container-padding-vertical: var(--kbq-size-xs);--kbq-list-size-container-content-gap-horizontal: var(--kbq-size-s);--kbq-list-size-container-content-gap-vertical: var(--kbq-size-3xs);--kbq-list-size-container-focus-outline-width: var(--kbq-size-3xs);--kbq-list-size-header-padding-top: var(--kbq-size-s);--kbq-list-size-header-padding-bottom: var(--kbq-size-xxs);--kbq-list-size-header-padding-horizontal: var(--kbq-size-m);--kbq-list-size-subheading-padding-top: var(--kbq-size-m);--kbq-list-size-subheading-padding-bottom: var(--kbq-size-xxs);--kbq-list-size-subheading-padding-horizontal: var(--kbq-size-m);--kbq-list-default-container-background: transparent;--kbq-list-default-text-color: var(--kbq-foreground-contrast);--kbq-list-default-icon-color: var(--kbq-icon-contrast);--kbq-list-default-icon-button-color: var(--kbq-icon-contrast-fade);--kbq-list-default-caption-color: var(--kbq-foreground-contrast-secondary);--kbq-list-states-hover-container-background: var(--kbq-states-background-transparent-hover);--kbq-list-states-active-container-background: var(--kbq-states-background-transparent-active);--kbq-list-states-hover-text-color: var(--kbq-foreground-contrast);--kbq-list-states-hover-icon-color: var(--kbq-icon-contrast);--kbq-list-states-hover-icon-button-color: var(--kbq-icon-contrast-fade);--kbq-list-states-selected-container-background: var(--kbq-background-theme-less);--kbq-list-multiple-states-selected-container-background: var(--kbq-background-contrast-less);--kbq-list-states-selected-text-color: var(--kbq-foreground-contrast);--kbq-list-states-selected-icon-color: var(--kbq-icon-contrast);--kbq-list-states-selected-icon-button-color: var(--kbq-icon-contrast-fade);--kbq-list-states-selected-hover-container-background: var(--kbq-states-background-theme-less-hover);--kbq-list-multiple-states-selected-hover-container-background: var(--kbq-states-background-contrast-less-hover);--kbq-list-states-selected-active-container-background: var(--kbq-states-background-theme-less-active);--kbq-list-multiple-states-selected-active-container-background: var(--kbq-states-background-contrast-less-active);--kbq-list-states-selected-hover-text-color: var(--kbq-foreground-contrast);--kbq-list-states-selected-hover-icon-color: var(--kbq-icon-contrast);--kbq-list-states-selected-hover-icon-button-color: var(--kbq-icon-contrast-fade);--kbq-list-states-focused-focus-outline-color: var(--kbq-states-line-focus-theme);--kbq-list-states-disabled-container-background: transparent;--kbq-list-states-disabled-text-color: var(--kbq-states-foreground-disabled);--kbq-list-states-disabled-icon-color: var(--kbq-states-icon-disabled);--kbq-list-states-disabled-icon-button-color: var(--kbq-states-icon-disabled);--kbq-list-states-disabled-caption-color: var(--kbq-states-foreground-disabled)}.kbq-dropdown__panel{--kbq-dropdown-size-container-width-min: 200px;--kbq-dropdown-size-container-width-max: var(--kbq-panel-size-width-max, 640px);--kbq-dropdown-size-container-padding-vertical: var(--kbq-size-xxs);--kbq-dropdown-size-container-border-radius: var(--kbq-size-s);--kbq-dropdown-container-background: var(--kbq-background-card);--kbq-dropdown-container-shadow: var(--kbq-shadow-popup);--kbq-dropdown-item-border-radius: var(--kbq-size-xs);--kbq-dropdown-item-caption-color: var(--kbq-foreground-contrast-secondary);--kbq-list-default-container-background: transparent;--kbq-list-default-text-color: var(--kbq-foreground-contrast);--kbq-list-default-icon-color: var(--kbq-icon-contrast);--kbq-list-default-icon-button-color: var(--kbq-icon-contrast-fade);--kbq-list-default-caption-color: var(--kbq-foreground-contrast-secondary);--kbq-list-states-hover-container-background: var(--kbq-states-background-transparent-hover);--kbq-list-states-active-container-background: var(--kbq-states-background-transparent-active);--kbq-list-states-hover-text-color: var(--kbq-foreground-contrast);--kbq-list-states-hover-icon-color: var(--kbq-icon-contrast);--kbq-list-states-hover-icon-button-color: var(--kbq-icon-contrast-fade);--kbq-list-states-selected-container-background: var(--kbq-background-theme-less);--kbq-list-multiple-states-selected-container-background: var(--kbq-background-contrast-less);--kbq-list-states-selected-text-color: var(--kbq-foreground-contrast);--kbq-list-states-selected-icon-color: var(--kbq-icon-contrast);--kbq-list-states-selected-icon-button-color: var(--kbq-icon-contrast-fade);--kbq-list-states-selected-hover-container-background: var(--kbq-states-background-theme-less-hover);--kbq-list-multiple-states-selected-hover-container-background: var(--kbq-states-background-contrast-less-hover);--kbq-list-states-selected-active-container-background: var(--kbq-states-background-theme-less-active);--kbq-list-multiple-states-selected-active-container-background: var(--kbq-states-background-contrast-less-active);--kbq-list-states-selected-hover-text-color: var(--kbq-foreground-contrast);--kbq-list-states-selected-hover-icon-color: var(--kbq-icon-contrast);--kbq-list-states-selected-hover-icon-button-color: var(--kbq-icon-contrast-fade);--kbq-list-states-focused-focus-outline-color: var(--kbq-states-line-focus-theme);--kbq-list-states-disabled-container-background: transparent;--kbq-list-states-disabled-text-color: var(--kbq-states-foreground-disabled);--kbq-list-states-disabled-icon-color: var(--kbq-states-icon-disabled);--kbq-list-states-disabled-icon-button-color: var(--kbq-states-icon-disabled);--kbq-list-states-disabled-caption-color: var(--kbq-states-foreground-disabled)}\n"] }]
624
- }], propDecorators: { search: [{ type: i0.ContentChild, args: [i0.forwardRef(() => KbqFormField), { isSignal: true }] }], navigationWithWrap: [{ type: i0.Input, args: [{ isSignal: true, alias: "navigationWithWrap", required: false }] }], xPosition: [{
1158
+ ], exportAs: 'kbqDropdown', template: "<ng-template>\n <div\n tabindex=\"-1\"\n class=\"kbq-dropdown__panel\"\n [class.kbq-dropdown__panel_nested]=\"parent\"\n [class]=\"classList\"\n [style.max-width.px]=\"panelMaxWidth()\"\n [style.--kbq-dropdown-size-container-width-min]=\"panelMinWidthToken()\"\n [@transformDropdown]=\"panelAnimationState\"\n (@transformDropdown.done)=\"onAnimationDone($event)\"\n (@transformDropdown.start)=\"onAnimationStart($event)\"\n (click)=\"close()\"\n (keydown)=\"handleKeydown($event)\"\n >\n <div class=\"kbq-dropdown__content\">\n <ng-content />\n </div>\n <ng-content select=\"[kbqDropdownFooter], kbq-dropdown-footer\" />\n </div>\n</ng-template>\n\n<ng-content select=\"[kbqDropdownStaticContent]\" />\n", styles: [".kbq-dropdown-footer{-webkit-user-select:none;-moz-user-select:none;-ms-user-select:none;user-select:none;display:flex;align-items:center;box-sizing:border-box;min-height:40px;border-top-width:1px;border-top-style:solid;padding:var(--kbq-size-xxs) var(--kbq-size-l)}.kbq-dropdown-trigger.kbq-button{padding-left:calc(var(--kbq-dropdown-trigger-horizontal-padding, 10px) - var(--kbq-size-border-width));padding-right:calc(var(--kbq-dropdown-trigger-horizontal-padding, 10px) - var(--kbq-size-border-width))}.kbq-dropdown-trigger.kbq-button .kbq-icon_left{margin-right:var(--kbq-size-xs)}.kbq-dropdown-trigger.kbq-button .kbq-icon_right{margin-left:var(--kbq-size-3xs)}.kbq-dropdown-trigger.kbq-button-icon.kbq-button-icon_right.kbq-button-icon_left .kbq-icon_left{margin-right:0}.kbq-dropdown-trigger.kbq-button-icon.kbq-button-icon_right.kbq-button-icon_left .kbq-icon_right{margin-left:0}.kbq-dropdown-trigger__icon{margin-left:auto;align-self:center}.kbq-dropdown__panel{outline:none;overflow-x:hidden;overflow-y:auto;min-width:max(var(--kbq-dropdown-size-container-width-min),100%);max-width:var(--kbq-dropdown-size-container-width-max);border-radius:var(--kbq-dropdown-size-container-border-radius);box-sizing:border-box}.kbq-dropdown__panel.ng-animating{pointer-events:none}.kbq-dropdown__panel .kbq-dropdown-item{position:relative}.kbq-dropdown__panel .kbq-dropdown-item:before,.kbq-dropdown__panel .kbq-dropdown-item:after{position:absolute;content:\"\";width:var(--kbq-size-xxs);height:calc(100% + var(--kbq-size-3xs) * 2)}.kbq-dropdown__panel .kbq-dropdown-item:before{right:calc(100% + var(--kbq-size-3xs))}.kbq-dropdown__panel .kbq-dropdown-item:after{left:calc(100% + var(--kbq-size-3xs))}.kbq-dropdown__panel .kbq-dropdown-item:before,.kbq-dropdown__panel .kbq-dropdown-item:after{top:calc(-1 * var(--kbq-size-3xs));bottom:calc(-1 * var(--kbq-size-3xs))}.kbq-dropdown__panel .kbq-dropdown-item.kbq-progress:after{background:none;animation:none}.kbq-dropdown__panel .kbq-divider{margin-left:calc(var(--kbq-size-xxs) * -1);margin-right:calc(var(--kbq-size-xxs) * -1)}.kbq-dropdown__content{display:flex;flex-direction:column;padding:var(--kbq-size-xxs)}.kbq-dropdown-footer{border-color:var(--kbq-line-contrast-less)}.kbq-dropdown__panel{box-shadow:var(--kbq-dropdown-container-shadow);background:var(--kbq-dropdown-container-background)}.kbq-dropdown-item{background:var(--kbq-list-default-container-background);color:var(--kbq-list-default-text-color)}.kbq-dropdown-item .kbq-icon.kbq-empty:not(.kbq-icon-button,.kbq-icon-item){color:var(--kbq-list-default-text-color)}.kbq-dropdown-item .kbq-dropdown-item__caption{color:var(--kbq-dropdown-item-caption-color)}.kbq-dropdown-item.kbq-dropdown-item_highlighted,.kbq-dropdown-item.kbq-dropdown-item_active:not(.kbq-disabled),.kbq-dropdown-item.cdk-focused:not(.kbq-disabled){background:var(--kbq-list-states-hover-container-background);color:var(--kbq-list-states-hover-text-color)}.kbq-dropdown-item.kbq-dropdown-item_highlighted .kbq-icon.kbq-empty:not(.kbq-icon-button,.kbq-icon-item),.kbq-dropdown-item.kbq-dropdown-item_active:not(.kbq-disabled) .kbq-icon.kbq-empty:not(.kbq-icon-button,.kbq-icon-item),.kbq-dropdown-item.cdk-focused:not(.kbq-disabled) .kbq-icon.kbq-empty:not(.kbq-icon-button,.kbq-icon-item){color:var(--kbq-list-states-hover-text-color)}.kbq-dropdown-item .kbq-dropdown__panel_safe-area-active.cdk-focused:not(.kbq-dropdown-item_highlighted,.kbq-selected,.kbq-disabled){background:var(--kbq-list-default-container-background);color:var(--kbq-list-default-text-color)}.kbq-dropdown-item .kbq-dropdown__panel_safe-area-active.cdk-focused:not(.kbq-dropdown-item_highlighted,.kbq-selected,.kbq-disabled) .kbq-icon.kbq-empty:not(.kbq-icon-button,.kbq-icon-item){color:var(--kbq-list-default-text-color)}.kbq-dropdown-item:active:not(.kbq-disabled),.kbq-dropdown-item.kbq-active:not(.kbq-disabled){background:var(--kbq-list-states-active-container-background)}.kbq-dropdown-item.kbq-selected{background:var(--kbq-list-states-selected-container-background);color:var(--kbq-list-states-selected-text-color)}.kbq-dropdown-item.kbq-selected .kbq-icon.kbq-empty:not(.kbq-icon-button,.kbq-icon-item){color:var(--kbq-list-states-selected-text-color)}.kbq-dropdown-item.kbq-selected.kbq-dropdown-item_active:not(.kbq-disabled),.kbq-dropdown-item.kbq-selected.cdk-focused:not(.kbq-disabled){background:var(--kbq-list-states-selected-hover-container-background);color:var(--kbq-list-states-selected-hover-text-color)}.kbq-dropdown-item.kbq-selected.kbq-dropdown-item_active:not(.kbq-disabled) .kbq-icon.kbq-empty:not(.kbq-icon-button,.kbq-icon-item),.kbq-dropdown-item.kbq-selected.cdk-focused:not(.kbq-disabled) .kbq-icon.kbq-empty:not(.kbq-icon-button,.kbq-icon-item){color:var(--kbq-list-states-selected-hover-text-color)}.kbq-dropdown-item.kbq-selected:active:not(.kbq-disabled),.kbq-dropdown-item.kbq-selected.kbq-active:not(.kbq-disabled){background:var(--kbq-list-states-selected-active-container-background)}.kbq-dropdown-item.kbq-disabled{background:var(--kbq-list-states-disabled-container-background);color:var(--kbq-list-states-disabled-text-color)}.kbq-dropdown-item.kbq-disabled .kbq-icon.kbq-empty:not(.kbq-icon-button,.kbq-icon-item){color:var(--kbq-list-states-disabled-text-color)}.kbq-dropdown-item:is(.kbq-selected,.cdk-focused,.kbq-dropdown-item_active):has(+:is(.kbq-selected,.cdk-focused,.kbq-dropdown-item_active)){border-bottom-left-radius:0;border-bottom-right-radius:0}.kbq-dropdown-item:is(.kbq-selected,.cdk-focused,.kbq-dropdown-item_active)+:is(.kbq-selected,.cdk-focused,.kbq-dropdown-item_active){border-top-left-radius:0;border-top-right-radius:0}.kbq-dropdown__group-header.kbq-dropdown__group-header_small{color:var(--kbq-foreground-contrast-secondary)}.kbq-dropdown-item-overlay{background:transparent}.kbq-dropdown-item,.kbq-dropdown__content{font-size:var(--kbq-typography-text-normal-font-size);font-style:var(--kbq-typography-text-normal-font-style);font-weight:var(--kbq-typography-text-normal-font-weight);line-height:var(--kbq-typography-text-normal-line-height);font-family:var(--kbq-typography-text-normal-font-family);text-transform:var(--kbq-typography-text-normal-text-transform);font-feature-settings:var(--kbq-typography-text-normal-font-feature-settings);letter-spacing:var(--kbq-typography-text-normal-letter-spacing)}.kbq-dropdown-item .kbq-dropdown-item__caption,.kbq-dropdown__content .kbq-dropdown-item__caption{font-size:var(--kbq-typography-text-compact-font-size);font-style:var(--kbq-typography-text-compact-font-style);font-weight:var(--kbq-typography-text-compact-font-weight);line-height:var(--kbq-typography-text-compact-line-height);font-family:var(--kbq-typography-text-compact-font-family);text-transform:var(--kbq-typography-text-compact-text-transform);font-feature-settings:var(--kbq-typography-text-compact-font-feature-settings);letter-spacing:var(--kbq-typography-text-compact-letter-spacing)}.kbq-dropdown__group-header{font-size:var(--kbq-typography-big-strong-font-size);font-style:var(--kbq-typography-big-strong-font-style);font-weight:var(--kbq-typography-big-strong-font-weight);line-height:var(--kbq-typography-big-strong-line-height);font-family:var(--kbq-typography-big-strong-font-family);text-transform:var(--kbq-typography-big-strong-text-transform);font-feature-settings:var(--kbq-typography-big-strong-font-feature-settings);letter-spacing:var(--kbq-typography-big-strong-letter-spacing)}.kbq-dropdown__group-header.kbq-dropdown__group-header_small{font-size:var(--kbq-typography-caps-compact-strong-font-size);font-style:var(--kbq-typography-caps-compact-strong-font-style);font-weight:var(--kbq-typography-caps-compact-strong-font-weight);line-height:var(--kbq-typography-caps-compact-strong-line-height);font-family:var(--kbq-typography-caps-compact-strong-font-family);text-transform:var(--kbq-typography-caps-compact-strong-text-transform);font-feature-settings:var(--kbq-typography-caps-compact-strong-font-feature-settings);letter-spacing:var(--kbq-typography-caps-compact-strong-letter-spacing)}\n", "@charset \"UTF-8\";.kbq-list,.kbq-list-selection,.kbq-list-option.cdk-drag-preview,.kbq-list-drag-preview_text{--kbq-list-size-container-padding-left: var(--kbq-size-m);--kbq-list-size-container-padding-right: var(--kbq-size-m);--kbq-list-size-container-padding-vertical: var(--kbq-size-xxs);--kbq-list-size-container-content-gap-horizontal: var(--kbq-size-s);--kbq-list-size-container-content-gap-vertical: var(--kbq-size-3xs);--kbq-list-size-container-focus-outline-width: var(--kbq-size-3xs);--kbq-list-default-container-background: transparent;--kbq-list-default-text-color: var(--kbq-foreground-contrast);--kbq-list-default-icon-color: var(--kbq-icon-contrast);--kbq-list-default-icon-button-color: var(--kbq-icon-contrast-fade);--kbq-list-default-caption-color: var(--kbq-foreground-contrast-secondary);--kbq-list-states-hover-container-background: var(--kbq-states-background-transparent-hover);--kbq-list-states-active-container-background: var(--kbq-states-background-transparent-active);--kbq-list-states-hover-text-color: var(--kbq-foreground-contrast);--kbq-list-states-hover-icon-color: var(--kbq-icon-contrast);--kbq-list-states-hover-icon-button-color: var(--kbq-icon-contrast-fade);--kbq-list-states-hover-caption-color: var(--kbq-foreground-contrast-secondary);--kbq-list-states-selected-container-background: var(--kbq-background-theme-less);--kbq-list-multiple-states-selected-container-background: var(--kbq-background-contrast-less);--kbq-list-states-selected-text-color: var(--kbq-foreground-contrast);--kbq-list-states-selected-icon-color: var(--kbq-icon-contrast);--kbq-list-states-selected-icon-button-color: var(--kbq-icon-contrast-fade);--kbq-list-states-selected-caption-color: var(--kbq-foreground-contrast-secondary);--kbq-list-multiple-states-selected-text-color: var(--kbq-foreground-contrast);--kbq-list-multiple-states-selected-icon-color: var(--kbq-icon-contrast);--kbq-list-multiple-states-selected-icon-button-color: var(--kbq-icon-contrast-fade);--kbq-list-multiple-states-selected-caption-color: var(--kbq-foreground-contrast-secondary);--kbq-list-states-selected-hover-container-background: var(--kbq-states-background-theme-less-hover);--kbq-list-multiple-states-selected-hover-container-background: var(--kbq-states-background-contrast-less-hover);--kbq-list-states-selected-active-container-background: var(--kbq-states-background-theme-less-active);--kbq-list-multiple-states-selected-active-container-background: var(--kbq-states-background-contrast-less-active);--kbq-list-states-selected-hover-text-color: var(--kbq-foreground-contrast);--kbq-list-states-selected-hover-icon-color: var(--kbq-icon-contrast);--kbq-list-states-selected-hover-icon-button-color: var(--kbq-icon-contrast-fade);--kbq-list-states-selected-hover-caption-color: var(--kbq-foreground-contrast-secondary);--kbq-list-multiple-states-selected-hover-text-color: var(--kbq-foreground-contrast);--kbq-list-multiple-states-selected-hover-icon-color: var(--kbq-icon-contrast);--kbq-list-multiple-states-selected-hover-icon-button-color: var(--kbq-icon-contrast-fade);--kbq-list-multiple-states-selected-hover-caption-color: var(--kbq-foreground-contrast-secondary);--kbq-list-states-focused-focus-outline-color: var(--kbq-states-line-focus-theme);--kbq-list-states-disabled-container-background: transparent;--kbq-list-states-disabled-text-color: var(--kbq-states-foreground-disabled);--kbq-list-states-disabled-icon-color: var(--kbq-states-icon-disabled);--kbq-list-states-disabled-icon-button-color: var(--kbq-states-icon-disabled);--kbq-list-states-disabled-caption-color: var(--kbq-states-foreground-disabled);--kbq-list-states-dragged-container-background: var(--kbq-background-card);--kbq-list-states-dragged-container-shadow: var(--kbq-shadow-popup)}.kbq-list-selection{--kbq-list-size-dragged-indicator-thickness: var(--kbq-size-3xs);--kbq-list-states-dragged-indicator-color: var(--kbq-line-theme)}.kbq-list-drag-preview_text{--kbq-list-size-drag-preview-max-width: 480px;--kbq-list-states-drag-preview-background: color-mix( in srgb, var(--kbq-background-card) calc(var(--kbq-opacity-overlay) * 100%), transparent )}.kbq-dropdown__panel{--kbq-dropdown-size-container-width-min: 200px;--kbq-dropdown-size-container-width-max: var(--kbq-panel-size-width-max, 640px);--kbq-dropdown-size-container-padding-vertical: var(--kbq-size-xxs);--kbq-dropdown-size-container-border-radius: var(--kbq-size-s);--kbq-dropdown-container-background: var(--kbq-background-card);--kbq-dropdown-container-shadow: var(--kbq-shadow-popup);--kbq-dropdown-item-border-radius: var(--kbq-size-xs);--kbq-dropdown-item-caption-color: var(--kbq-foreground-contrast-secondary);--kbq-list-default-container-background: transparent;--kbq-list-default-text-color: var(--kbq-foreground-contrast);--kbq-list-default-icon-color: var(--kbq-icon-contrast);--kbq-list-default-icon-button-color: var(--kbq-icon-contrast-fade);--kbq-list-default-caption-color: var(--kbq-foreground-contrast-secondary);--kbq-list-states-hover-container-background: var(--kbq-states-background-transparent-hover);--kbq-list-states-active-container-background: var(--kbq-states-background-transparent-active);--kbq-list-states-hover-text-color: var(--kbq-foreground-contrast);--kbq-list-states-hover-icon-color: var(--kbq-icon-contrast);--kbq-list-states-hover-icon-button-color: var(--kbq-icon-contrast-fade);--kbq-list-states-hover-caption-color: var(--kbq-foreground-contrast-secondary);--kbq-list-states-selected-container-background: var(--kbq-background-theme-less);--kbq-list-multiple-states-selected-container-background: var(--kbq-background-contrast-less);--kbq-list-states-selected-text-color: var(--kbq-foreground-contrast);--kbq-list-states-selected-icon-color: var(--kbq-icon-contrast);--kbq-list-states-selected-icon-button-color: var(--kbq-icon-contrast-fade);--kbq-list-states-selected-caption-color: var(--kbq-foreground-contrast-secondary);--kbq-list-multiple-states-selected-text-color: var(--kbq-foreground-contrast);--kbq-list-multiple-states-selected-icon-color: var(--kbq-icon-contrast);--kbq-list-multiple-states-selected-icon-button-color: var(--kbq-icon-contrast-fade);--kbq-list-multiple-states-selected-caption-color: var(--kbq-foreground-contrast-secondary);--kbq-list-states-selected-hover-container-background: var(--kbq-states-background-theme-less-hover);--kbq-list-multiple-states-selected-hover-container-background: var(--kbq-states-background-contrast-less-hover);--kbq-list-states-selected-active-container-background: var(--kbq-states-background-theme-less-active);--kbq-list-multiple-states-selected-active-container-background: var(--kbq-states-background-contrast-less-active);--kbq-list-states-selected-hover-text-color: var(--kbq-foreground-contrast);--kbq-list-states-selected-hover-icon-color: var(--kbq-icon-contrast);--kbq-list-states-selected-hover-icon-button-color: var(--kbq-icon-contrast-fade);--kbq-list-states-selected-hover-caption-color: var(--kbq-foreground-contrast-secondary);--kbq-list-multiple-states-selected-hover-text-color: var(--kbq-foreground-contrast);--kbq-list-multiple-states-selected-hover-icon-color: var(--kbq-icon-contrast);--kbq-list-multiple-states-selected-hover-icon-button-color: var(--kbq-icon-contrast-fade);--kbq-list-multiple-states-selected-hover-caption-color: var(--kbq-foreground-contrast-secondary);--kbq-list-states-focused-focus-outline-color: var(--kbq-states-line-focus-theme);--kbq-list-states-disabled-container-background: transparent;--kbq-list-states-disabled-text-color: var(--kbq-states-foreground-disabled);--kbq-list-states-disabled-icon-color: var(--kbq-states-icon-disabled);--kbq-list-states-disabled-icon-button-color: var(--kbq-states-icon-disabled);--kbq-list-states-disabled-caption-color: var(--kbq-states-foreground-disabled);--kbq-list-states-dragged-container-background: var(--kbq-background-card);--kbq-list-states-dragged-container-shadow: var(--kbq-shadow-popup)}\n"] }]
1159
+ }], ctorParameters: () => [], propDecorators: { panelFormField: [{ type: i0.ContentChild, args: [i0.forwardRef(() => KbqFormField), { isSignal: true }] }], searches: [{ type: i0.ContentChildren, args: [i0.forwardRef(() => KbqDropdownSearch), { ...{ descendants: true }, isSignal: true }] }], navigationWithWrap: [{ type: i0.Input, args: [{ isSignal: true, alias: "navigationWithWrap", required: false }] }], xPosition: [{
625
1160
  type: Input
626
1161
  }], yPosition: [{
627
1162
  type: Input
@@ -636,7 +1171,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.25", ngImpo
636
1171
  args: ['class']
637
1172
  }], backdropClass: [{
638
1173
  type: Input
639
- }], panelWidth: [{ type: i0.Input, args: [{ isSignal: true, alias: "panelWidth", required: false }] }], panelMinWidth: [{ type: i0.Input, args: [{ isSignal: true, alias: "panelMinWidth", required: false }] }], panelMaxWidth: [{ type: i0.Input, args: [{ isSignal: true, alias: "panelMaxWidth", required: false }] }], templateRef: [{
1174
+ }], panelWidth: [{ type: i0.Input, args: [{ isSignal: true, alias: "panelWidth", required: false }] }], panelMinWidth: [{ type: i0.Input, args: [{ isSignal: true, alias: "panelMinWidth", required: false }] }], panelMaxWidth: [{ type: i0.Input, args: [{ isSignal: true, alias: "panelMaxWidth", required: false }] }], safeArea: [{ type: i0.Input, args: [{ isSignal: true, alias: "safeArea", required: false }] }], templateRef: [{
640
1175
  type: ViewChild,
641
1176
  args: [TemplateRef, { static: false }]
642
1177
  }], items: [{
@@ -649,8 +1184,14 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.25", ngImpo
649
1184
  type: Output
650
1185
  }] } });
651
1186
 
652
- /** Injection token that determines the scroll handling while the dropdown is open. */
653
- const KBQ_DROPDOWN_SCROLL_STRATEGY = new InjectionToken('kbq-dropdown-scroll-strategy');
1187
+ /**
1188
+ * Injection token that determines the scroll handling while the dropdown is open. The root default keeps the
1189
+ * trigger usable outside `KbqDropdownModule`'s injector; providing the token anywhere still wins over it.
1190
+ */
1191
+ const KBQ_DROPDOWN_SCROLL_STRATEGY = new InjectionToken('kbq-dropdown-scroll-strategy', {
1192
+ providedIn: 'root',
1193
+ factory: () => KBQ_DROPDOWN_SCROLL_STRATEGY_FACTORY(inject(Overlay))
1194
+ });
654
1195
  /** @docs-private */
655
1196
  function KBQ_DROPDOWN_SCROLL_STRATEGY_FACTORY(overlay) {
656
1197
  return () => overlay.scrollStrategies.reposition();
@@ -731,6 +1272,16 @@ class KbqDropdownTrigger {
731
1272
  get opened() {
732
1273
  return this._opened;
733
1274
  }
1275
+ /**
1276
+ * Whether the dropdown overlay is currently attached. Part of the `KbqSiblingPopup` contract.
1277
+ *
1278
+ * `opened` is set synchronously right after the overlay is attached and, on close, only once the exit
1279
+ * animation is done — i.e. it stays `true` for the whole time the trigger is busy with its panel,
1280
+ * including the moment `destroy()` restores focus to the trigger.
1281
+ */
1282
+ get isAttached() {
1283
+ return this._opened;
1284
+ }
734
1285
  constructor() {
735
1286
  this.overlay = inject(Overlay);
736
1287
  this.elementRef = inject(ElementRef);
@@ -773,6 +1324,8 @@ class KbqDropdownTrigger {
773
1324
  * KBQ_OPTION_ACTION_PARENT contract, which an `OutputEmitterRef` does not support — see #DS-5079.
774
1325
  */
775
1326
  this.dropdownClosed = new EventEmitter();
1327
+ /** Emits `true` when the dropdown opens and `false` when it closes. Part of the `KbqSiblingPopup` contract. */
1328
+ this.openedChange = merge(outputToObservable(this.dropdownOpened).pipe(map(() => true)), this.dropdownClosed.pipe(map(() => false)));
776
1329
  this._opened = false;
777
1330
  this.overlayRef = null;
778
1331
  this.closeSubscription = Subscription.EMPTY;
@@ -851,6 +1404,10 @@ class KbqDropdownTrigger {
851
1404
  * Focuses the dropdown trigger.
852
1405
  */
853
1406
  focus(origin, options) {
1407
+ // The trigger of a nested panel is an item of a search panel: the caret belongs to the query,
1408
+ // not to the item, so hand it back to the field instead of focusing this element.
1409
+ if (this.isNested() && this.parent.restoreFocus?.())
1410
+ return;
854
1411
  if (this.focusMonitor && origin) {
855
1412
  this.focusMonitor.focusVia(this.elementRef.nativeElement, origin, options);
856
1413
  }
@@ -870,10 +1427,22 @@ class KbqDropdownTrigger {
870
1427
  event.preventDefault();
871
1428
  }
872
1429
  }
1430
+ /**
1431
+ * Starts safe-area protection when the pointer leaves a trigger whose submenu is open, so a
1432
+ * sibling item crossed on the way to the submenu doesn't prematurely close it.
1433
+ */
1434
+ handleMouseLeave(event) {
1435
+ if (!this.isNested() || !this._opened || !this.isBrowser || !this.parent.safeArea() || !this.overlayRef) {
1436
+ return;
1437
+ }
1438
+ const panelRect = this.overlayRef.overlayElement.getBoundingClientRect();
1439
+ const triangle = getSafeTriangleVertices({ x: event.clientX, y: event.clientY }, panelRect);
1440
+ this.parent.activateSafeArea(this.dropdownItemInstance, triangle, panelRect, () => this.close());
1441
+ }
873
1442
  /** Handles key presses on the trigger. */
874
1443
  handleKeydown(event) {
875
1444
  const keyCode = event.keyCode;
876
- if (keyCode === ENTER || keyCode === SPACE) {
1445
+ if (keyCode === ENTER$1 || keyCode === SPACE) {
877
1446
  this.openedBy = 'keyboard';
878
1447
  event.preventDefault();
879
1448
  if (this.isNested()) {
@@ -910,6 +1479,9 @@ class KbqDropdownTrigger {
910
1479
  return;
911
1480
  }
912
1481
  this.lastDestroyReason = reason;
1482
+ if (this.isNested()) {
1483
+ this.parent.deactivateSafeArea();
1484
+ }
913
1485
  this.dropdown.resetActiveItem();
914
1486
  this.closeSubscription.unsubscribe();
915
1487
  this.widthLockSubscription.unsubscribe();
@@ -1114,7 +1686,13 @@ class KbqDropdownTrigger {
1114
1686
  const detachments = this.overlayRef.detachments();
1115
1687
  const parentClose = this.parent ? this.parent.closed : of();
1116
1688
  const hover = this.parent
1117
- ? this.parent.hovered().pipe(filter((active) => active !== this.dropdownItemInstance), filter(() => this._opened))
1689
+ ? this.parent.hovered().pipe(filter((active) => active !== this.dropdownItemInstance), filter(() => this._opened),
1690
+ // While a safe area protects this dropdown, closing is driven by the safe area
1691
+ // itself instead: either it resolves on its own (see `handleMouseLeave()`), or a
1692
+ // forced switch to a different nested trigger closes this one via `onExit` — always
1693
+ // before the new trigger opens, so the two don't race over animation state shared by
1694
+ // triggers pointing at the same dropdown (see `KbqDropdown.activateSafeArea()`).
1695
+ filter(() => !this.parent.isSafeAreaActive()))
1118
1696
  : of();
1119
1697
  return merge(backdrop, outsidePointerEvents, parentClose, hover, detachments);
1120
1698
  }
@@ -1124,13 +1702,21 @@ class KbqDropdownTrigger {
1124
1702
  if (!this.isNested()) {
1125
1703
  return;
1126
1704
  }
1127
- this.hoverSubscription = this.parent
1128
- .hovered()
1705
+ this.hoverSubscription = merge(this.parent.hovered().pipe(filter((active) => active === this.dropdownItemInstance && !active.disabled),
1706
+ // While a *different* trigger's safe area is active, opening is deferred to
1707
+ // `onSwitchTarget()` below, which only fires once that trigger has actually closed.
1708
+ // Hovering the trigger that owns the active safe area (coming back to it) still
1709
+ // passes through immediately — `open()` is a no-op there, but it lets the safe area be
1710
+ // cancelled below.
1711
+ filter(() => !this.parent.isSafeAreaActive() || this.parent.isSafeAreaOwner(this.dropdownItemInstance))), this.parent.onSwitchTarget().pipe(filter((active) => active === this.dropdownItemInstance)))
1129
1712
  // Since we might have multiple competing triggers for the same dropdown (e.g. a nested dropdown
1130
1713
  // with different data and triggers), we have to delay it by a tick to ensure that
1131
1714
  // it won't be closed immediately after it is opened.
1132
- .pipe(filter((active) => active === this.dropdownItemInstance && !active.disabled), delay(0, asapScheduler))
1715
+ .pipe(delay(0, asapScheduler))
1133
1716
  .subscribe(() => {
1717
+ // Coming back to this trigger cancels any safe-area protection left over from a
1718
+ // previous `mouseleave`.
1719
+ this.parent.deactivateSafeArea();
1134
1720
  this.openedBy = 'mouse';
1135
1721
  // If the same dropdown is used between multiple triggers, it might still be animating
1136
1722
  // while the new trigger tries to re-open it. Wait for the animation to finish
@@ -1207,17 +1793,19 @@ class KbqDropdownTrigger {
1207
1793
  this.renderer.removeClass(this.overlayContainer.getContainerElement(), 'cdk-overlay-container_dropdown');
1208
1794
  }
1209
1795
  }
1210
- /** @nocollapse */ static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.25", ngImport: i0, type: KbqDropdownTrigger, deps: [], target: i0.ɵɵFactoryTarget.Directive }); }
1211
- /** @nocollapse */ static { this.ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "16.1.0", version: "20.3.25", type: KbqDropdownTrigger, isStandalone: true, selector: "[kbqDropdownTriggerFor]", inputs: { offsetX: ["offsetX", "offsetX", numberAttribute], offsetY: ["offsetY", "offsetY", numberAttribute], data: ["kbqDropdownTriggerData", "data"], openByArrowDown: "openByArrowDown", demoteOverlay: ["demoteOverlay", "demoteOverlay", booleanAttribute], restoreFocus: ["kbqDropdownTriggerRestoreFocus", "restoreFocus"], dropdown: ["kbqDropdownTriggerFor", "dropdown"] }, outputs: { dropdownOpened: "dropdownOpened", dropdownClosed: "dropdownClosed" }, host: { listeners: { "mousedown": "handleMousedown($event)", "keydown": "handleKeydown($event)", "click": "handleClick($event)" }, properties: { "class.kbq-pressed": "opened" }, classAttribute: "kbq-dropdown-trigger" }, exportAs: ["kbqDropdownTrigger"], ngImport: i0 }); }
1796
+ /** @nocollapse */ static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.30", ngImport: i0, type: KbqDropdownTrigger, deps: [], target: i0.ɵɵFactoryTarget.Directive }); }
1797
+ /** @nocollapse */ static { this.ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "16.1.0", version: "20.3.30", type: KbqDropdownTrigger, isStandalone: true, selector: "[kbqDropdownTriggerFor]", inputs: { offsetX: ["offsetX", "offsetX", numberAttribute], offsetY: ["offsetY", "offsetY", numberAttribute], data: ["kbqDropdownTriggerData", "data"], openByArrowDown: "openByArrowDown", demoteOverlay: ["demoteOverlay", "demoteOverlay", booleanAttribute], restoreFocus: ["kbqDropdownTriggerRestoreFocus", "restoreFocus"], dropdown: ["kbqDropdownTriggerFor", "dropdown"] }, outputs: { dropdownOpened: "dropdownOpened", dropdownClosed: "dropdownClosed" }, host: { listeners: { "mousedown": "handleMousedown($event)", "mouseleave": "handleMouseLeave($event)", "keydown": "handleKeydown($event)", "click": "handleClick($event)" }, properties: { "class.kbq-pressed": "opened" }, classAttribute: "kbq-dropdown-trigger" }, providers: [kbqSiblingPopupProvider(KbqDropdownTrigger)], exportAs: ["kbqDropdownTrigger"], ngImport: i0 }); }
1212
1798
  }
1213
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.25", ngImport: i0, type: KbqDropdownTrigger, decorators: [{
1799
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.30", ngImport: i0, type: KbqDropdownTrigger, decorators: [{
1214
1800
  type: Directive,
1215
1801
  args: [{
1216
1802
  selector: `[kbqDropdownTriggerFor]`,
1803
+ providers: [kbqSiblingPopupProvider(KbqDropdownTrigger)],
1217
1804
  host: {
1218
1805
  class: 'kbq-dropdown-trigger',
1219
1806
  '[class.kbq-pressed]': 'opened',
1220
1807
  '(mousedown)': 'handleMousedown($event)',
1808
+ '(mouseleave)': 'handleMouseLeave($event)',
1221
1809
  '(keydown)': 'handleKeydown($event)',
1222
1810
  '(click)': 'handleClick($event)'
1223
1811
  },
@@ -1248,23 +1836,29 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.25", ngImpo
1248
1836
  }] } });
1249
1837
 
1250
1838
  class KbqDropdownModule {
1251
- /** @nocollapse */ static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.25", ngImport: i0, type: KbqDropdownModule, deps: [], target: i0.ɵɵFactoryTarget.NgModule }); }
1252
- /** @nocollapse */ static { this.ɵmod = i0.ɵɵngDeclareNgModule({ minVersion: "14.0.0", version: "20.3.25", ngImport: i0, type: KbqDropdownModule, imports: [OverlayModule,
1839
+ /** @nocollapse */ static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.30", ngImport: i0, type: KbqDropdownModule, deps: [], target: i0.ɵɵFactoryTarget.NgModule }); }
1840
+ /** @nocollapse */ static { this.ɵmod = i0.ɵɵngDeclareNgModule({ minVersion: "14.0.0", version: "20.3.30", ngImport: i0, type: KbqDropdownModule, imports: [OverlayModule,
1253
1841
  KbqIconModule,
1254
1842
  KbqDropdownStaticContent,
1255
1843
  KbqDropdown,
1256
1844
  KbqDropdownItem,
1845
+ KbqDropdownItemAction,
1257
1846
  KbqDropdownTrigger,
1258
- KbqDropdownContent], exports: [KbqDropdown,
1847
+ KbqDropdownContent,
1848
+ KbqDropdownFooter,
1849
+ KbqDropdownSearch], exports: [KbqDropdown,
1259
1850
  KbqDropdownItem,
1851
+ KbqDropdownItemAction,
1260
1852
  KbqDropdownTrigger,
1261
1853
  KbqDropdownContent,
1262
- KbqDropdownStaticContent] }); }
1263
- /** @nocollapse */ static { this.ɵinj = i0.ɵɵngDeclareInjector({ minVersion: "12.0.0", version: "20.3.25", ngImport: i0, type: KbqDropdownModule, providers: [KBQ_DROPDOWN_SCROLL_STRATEGY_FACTORY_PROVIDER], imports: [OverlayModule,
1854
+ KbqDropdownStaticContent,
1855
+ KbqDropdownFooter,
1856
+ KbqDropdownSearch] }); }
1857
+ /** @nocollapse */ static { this.ɵinj = i0.ɵɵngDeclareInjector({ minVersion: "12.0.0", version: "20.3.30", ngImport: i0, type: KbqDropdownModule, imports: [OverlayModule,
1264
1858
  KbqIconModule,
1265
1859
  KbqDropdownItem] }); }
1266
1860
  }
1267
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.25", ngImport: i0, type: KbqDropdownModule, decorators: [{
1861
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.30", ngImport: i0, type: KbqDropdownModule, decorators: [{
1268
1862
  type: NgModule,
1269
1863
  args: [{
1270
1864
  imports: [
@@ -1273,16 +1867,21 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.25", ngImpo
1273
1867
  KbqDropdownStaticContent,
1274
1868
  KbqDropdown,
1275
1869
  KbqDropdownItem,
1870
+ KbqDropdownItemAction,
1276
1871
  KbqDropdownTrigger,
1277
- KbqDropdownContent
1872
+ KbqDropdownContent,
1873
+ KbqDropdownFooter,
1874
+ KbqDropdownSearch
1278
1875
  ],
1279
- providers: [KBQ_DROPDOWN_SCROLL_STRATEGY_FACTORY_PROVIDER],
1280
1876
  exports: [
1281
1877
  KbqDropdown,
1282
1878
  KbqDropdownItem,
1879
+ KbqDropdownItemAction,
1283
1880
  KbqDropdownTrigger,
1284
1881
  KbqDropdownContent,
1285
- KbqDropdownStaticContent
1882
+ KbqDropdownStaticContent,
1883
+ KbqDropdownFooter,
1884
+ KbqDropdownSearch
1286
1885
  ]
1287
1886
  }]
1288
1887
  }] });
@@ -1291,5 +1890,5 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.25", ngImpo
1291
1890
  * Generated bundle index. Do not edit.
1292
1891
  */
1293
1892
 
1294
- export { KBQ_DROPDOWN_DEFAULT_OPTIONS, KBQ_DROPDOWN_DEFAULT_OPTIONS_FACTORY, KBQ_DROPDOWN_HOST, KBQ_DROPDOWN_PANEL, KBQ_DROPDOWN_SCROLL_STRATEGY, KBQ_DROPDOWN_SCROLL_STRATEGY_FACTORY, KBQ_DROPDOWN_SCROLL_STRATEGY_FACTORY_PROVIDER, KbqDropdown, KbqDropdownContent, KbqDropdownItem, KbqDropdownModule, KbqDropdownStaticContent, KbqDropdownTrigger, NESTED_PANEL_LEFT_PADDING, NESTED_PANEL_TOP_PADDING, fadeInItems, kbqDropdownAnimations, throwKbqDropdownInvalidPositionX, throwKbqDropdownInvalidPositionY, throwKbqDropdownMissingError, transformDropdown };
1893
+ export { KBQ_DROPDOWN_DEFAULT_OPTIONS, KBQ_DROPDOWN_DEFAULT_OPTIONS_FACTORY, KBQ_DROPDOWN_HOST, KBQ_DROPDOWN_PANEL, KBQ_DROPDOWN_SCROLL_STRATEGY, KBQ_DROPDOWN_SCROLL_STRATEGY_FACTORY, KBQ_DROPDOWN_SCROLL_STRATEGY_FACTORY_PROVIDER, KbqDropdown, KbqDropdownContent, KbqDropdownFooter, KbqDropdownItem, KbqDropdownItemAction, KbqDropdownModule, KbqDropdownSearch, KbqDropdownStaticContent, KbqDropdownTrigger, NESTED_HOVER_SWITCH_DELAY, NESTED_PANEL_LEFT_PADDING, NESTED_PANEL_TOP_PADDING, fadeInItems, kbqDropdownAnimations, throwKbqDropdownInvalidPositionX, throwKbqDropdownInvalidPositionY, throwKbqDropdownMissingError, throwKbqDropdownSearchMissingInputError, throwKbqDropdownSearchMissingNgControlError, transformDropdown };
1295
1894
  //# sourceMappingURL=koobiq-components-dropdown.mjs.map