@koobiq/components 20.3.1 → 20.4.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 (104) hide show
  1. package/accordion/accordion.scss +4 -1
  2. package/accordion/index.d.ts +36 -12
  3. package/alert/index.d.ts +8 -0
  4. package/breadcrumbs/index.d.ts +2 -0
  5. package/button-toggle/button-toggle-tokens.scss +14 -0
  6. package/button-toggle/button-toggle.scss +75 -3
  7. package/core/index.d.ts +146 -5
  8. package/core/option/_option-theme.scss +3 -0
  9. package/core/styles/common/_select.scss +98 -3
  10. package/core/styles/typography/_typography.scss +8 -0
  11. package/ellipsis-center/ellipsis-center.scss +31 -0
  12. package/ellipsis-center/index.d.ts +35 -2
  13. package/fesm2022/koobiq-components-accordion.mjs +143 -44
  14. package/fesm2022/koobiq-components-accordion.mjs.map +1 -1
  15. package/fesm2022/koobiq-components-alert.mjs +17 -1
  16. package/fesm2022/koobiq-components-alert.mjs.map +1 -1
  17. package/fesm2022/koobiq-components-autocomplete.mjs +2 -2
  18. package/fesm2022/koobiq-components-autocomplete.mjs.map +1 -1
  19. package/fesm2022/koobiq-components-breadcrumbs.mjs +8 -3
  20. package/fesm2022/koobiq-components-breadcrumbs.mjs.map +1 -1
  21. package/fesm2022/koobiq-components-button-toggle.mjs +2 -2
  22. package/fesm2022/koobiq-components-button-toggle.mjs.map +1 -1
  23. package/fesm2022/koobiq-components-code-block.mjs +10 -5
  24. package/fesm2022/koobiq-components-code-block.mjs.map +1 -1
  25. package/fesm2022/koobiq-components-core.mjs +214 -11
  26. package/fesm2022/koobiq-components-core.mjs.map +1 -1
  27. package/fesm2022/koobiq-components-dropdown.mjs +2 -2
  28. package/fesm2022/koobiq-components-dropdown.mjs.map +1 -1
  29. package/fesm2022/koobiq-components-ellipsis-center.mjs +101 -34
  30. package/fesm2022/koobiq-components-ellipsis-center.mjs.map +1 -1
  31. package/fesm2022/koobiq-components-file-upload.mjs +7 -7
  32. package/fesm2022/koobiq-components-file-upload.mjs.map +1 -1
  33. package/fesm2022/koobiq-components-filter-bar.mjs +94 -55
  34. package/fesm2022/koobiq-components-filter-bar.mjs.map +1 -1
  35. package/fesm2022/koobiq-components-inline-edit.mjs +177 -14
  36. package/fesm2022/koobiq-components-inline-edit.mjs.map +1 -1
  37. package/fesm2022/koobiq-components-list.mjs +359 -44
  38. package/fesm2022/koobiq-components-list.mjs.map +1 -1
  39. package/fesm2022/koobiq-components-markdown.mjs +6 -2
  40. package/fesm2022/koobiq-components-markdown.mjs.map +1 -1
  41. package/fesm2022/koobiq-components-modal.mjs +48 -7
  42. package/fesm2022/koobiq-components-modal.mjs.map +1 -1
  43. package/fesm2022/koobiq-components-select.mjs +117 -12
  44. package/fesm2022/koobiq-components-select.mjs.map +1 -1
  45. package/fesm2022/koobiq-components-sidebar.mjs +5 -1
  46. package/fesm2022/koobiq-components-sidebar.mjs.map +1 -1
  47. package/fesm2022/koobiq-components-sidepanel.mjs +25 -6
  48. package/fesm2022/koobiq-components-sidepanel.mjs.map +1 -1
  49. package/fesm2022/koobiq-components-tabs.mjs +460 -197
  50. package/fesm2022/koobiq-components-tabs.mjs.map +1 -1
  51. package/fesm2022/koobiq-components-time-range.mjs +388 -74
  52. package/fesm2022/koobiq-components-time-range.mjs.map +1 -1
  53. package/fesm2022/koobiq-components-timezone.mjs +4 -4
  54. package/fesm2022/koobiq-components-timezone.mjs.map +1 -1
  55. package/fesm2022/koobiq-components-title.mjs +15 -3
  56. package/fesm2022/koobiq-components-title.mjs.map +1 -1
  57. package/fesm2022/koobiq-components-tree-select.mjs +2 -2
  58. package/fesm2022/koobiq-components-tree-select.mjs.map +1 -1
  59. package/fesm2022/koobiq-components-tree.mjs +14 -4
  60. package/fesm2022/koobiq-components-tree.mjs.map +1 -1
  61. package/file-upload/file-upload.scss +0 -18
  62. package/file-upload/index.d.ts +1 -1
  63. package/file-upload/multiple-file-upload.component.scss +15 -3
  64. package/file-upload/single-file-upload.component.scss +10 -2
  65. package/filter-bar/filter-bar-tokens.scss +2 -1
  66. package/filter-bar/index.d.ts +41 -4
  67. package/filter-bar/pipes/base-pipe.scss +24 -6
  68. package/filter-bar/pipes/pipe-input.scss +3 -1
  69. package/inline-edit/index.d.ts +87 -8
  70. package/inline-edit/inline-edit-tokens.scss +1 -0
  71. package/inline-edit/inline-edit.scss +26 -0
  72. package/link/_link-theme.scss +50 -15
  73. package/list/index.d.ts +126 -5
  74. package/markdown/index.d.ts +2 -0
  75. package/modal/index.d.ts +16 -7
  76. package/navbar/_navbar-item_horizontal.scss +5 -0
  77. package/package.json +3 -3
  78. package/prebuilt-themes/dark-theme.css +1 -1
  79. package/prebuilt-themes/light-theme.css +1 -1
  80. package/prebuilt-themes/theme.css +1 -1
  81. package/schematics/migrations/alert-signals/index.js +4 -1
  82. package/schematics/migrations/autocomplete-panel-width-auto/index.js +3 -34
  83. package/schematics/migrations/empty-state-size-attr/index.js +3 -34
  84. package/schematics/migrations/filter-bar-signals/index.js +4 -1
  85. package/schematics/migrations/loader-overlay-size-attr/index.js +3 -34
  86. package/schematics/migrations/v20-upgrade/index.js +4 -1
  87. package/schematics/ng-add/index.js +1 -1
  88. package/schematics/utils/angular-parsing.js +11 -12
  89. package/schematics/utils/package-config.js +5 -4
  90. package/schematics/utils/typescript.js +24 -0
  91. package/select/_select-theme.scss +9 -1
  92. package/select/index.d.ts +18 -2
  93. package/select/select.scss +13 -0
  94. package/sidebar/index.d.ts +1 -0
  95. package/sidepanel/index.d.ts +9 -0
  96. package/tabs/_tabs-common.scss +111 -2
  97. package/tabs/index.d.ts +79 -48
  98. package/tabs/tab-group.scss +0 -4
  99. package/tabs/tab-header.scss +0 -2
  100. package/tabs/tab-nav-bar.scss +3 -11
  101. package/time-range/index.d.ts +140 -5
  102. package/time-range/time-range.scss +16 -1
  103. package/title/index.d.ts +10 -2
  104. package/tree/index.d.ts +1 -0
@@ -5,11 +5,12 @@ import { SelectionModel } from '@angular/cdk/collections';
5
5
  import * as i1 from '@angular/cdk/drag-drop';
6
6
  import { CdkDropList, CdkDrag, CDK_DRAG_HANDLE, CdkDragPreview, CdkDragHandle } from '@angular/cdk/drag-drop';
7
7
  import { Platform } from '@angular/cdk/platform';
8
+ import { CdkVirtualForOf } from '@angular/cdk/scrolling';
8
9
  import * as i0 from '@angular/core';
9
- import { forwardRef, inject, ElementRef, ChangeDetectorRef, output, EventEmitter, input, booleanAttribute, DestroyRef, NgZone, signal, HostAttributeToken, effect, isDevMode, Input, Output, ContentChildren, ViewEncapsulation, ChangeDetectionStrategy, Component, Directive, contentChild, contentChildren, viewChild, ViewChild, ContentChild, NgModule } from '@angular/core';
10
+ import { forwardRef, inject, ElementRef, ChangeDetectorRef, output, EventEmitter, input, booleanAttribute, viewChild, QueryList, contentChild, DestroyRef, NgZone, signal, HostAttributeToken, effect, isDevMode, Input, Output, ContentChildren, ViewEncapsulation, ChangeDetectionStrategy, Component, Directive, contentChildren, ViewChild, ContentChild, NgModule } from '@angular/core';
10
11
  import { takeUntilDestroyed } from '@angular/core/rxjs-interop';
11
12
  import { NG_VALUE_ACCESSOR } from '@angular/forms';
12
- import { MultipleMode, getKbqSelectNonFunctionValueError, KBQ_WINDOW, FocusKeyManager, SPACE, ENTER, LEFT_ARROW, RIGHT_ARROW, isVerticalMovement, isSelectAll, isCopy, TAB, DOWN_ARROW, UP_ARROW, HOME, END, PAGE_UP, PAGE_DOWN, hasModifierKey, runCompareWith, toggleSelectAll, KbqOptgroup, KbqOptionActionComponent, KbqPseudoCheckbox, kbqFocusOptionActionOnTab, KbqActionContainer, KBQ_OPTION_ACTION_PARENT, KBQ_TITLE_TEXT_REF, KbqLineSetter, KbqLine, KbqOptionModule, KbqPseudoCheckboxModule } from '@koobiq/components/core';
13
+ import { MultipleMode, getSelectAllState, ruRULocaleData, KBQ_LOCALE_SERVICE, getKbqSelectNonFunctionValueError, KBQ_WINDOW, toggleSelectAll, FocusKeyManager, kbqGetElementHeight, SPACE, ENTER, LEFT_ARROW, RIGHT_ARROW, isVerticalMovement, isSelectAll, isCopy, TAB, DOWN_ARROW, UP_ARROW, HOME, END, PAGE_UP, PAGE_DOWN, hasModifierKey, runCompareWith, KbqPseudoCheckbox, KbqOptgroup, KbqOptionActionComponent, kbqFocusOptionActionOnTab, KbqActionContainer, KBQ_OPTION_ACTION_PARENT, KBQ_TITLE_TEXT_REF, KbqLineSetter, KbqLine, KbqOptionModule, KbqPseudoCheckboxModule } from '@koobiq/components/core';
13
14
  import { KbqDropdownTrigger } from '@koobiq/components/dropdown';
14
15
  import { KbqTooltipTrigger } from '@koobiq/components/tooltip';
15
16
  import { merge, fromEvent, Subject } from 'rxjs';
@@ -93,6 +94,53 @@ class KbqListSelection {
93
94
  this._draggable = value;
94
95
  this.syncDraggableState();
95
96
  }
97
+ /**
98
+ * Whether the "select all" row is currently rendered.
99
+ *
100
+ * Suppressed inside a `cdk-virtual-scroll-viewport`: `options` then holds only the options currently
101
+ * rendered, so the checkbox would report "everything selected" after touching a fraction of the data
102
+ * — the same reason `kbq-select` refuses the row under `withVirtualScroll`. Suppressed on an empty
103
+ * list too: a master checkbox over nothing has nothing to say.
104
+ */
105
+ get showSelectAll() {
106
+ return (this.selectAllEnabled() &&
107
+ this.multipleMode === MultipleMode.CHECKBOX &&
108
+ !this.horizontal() &&
109
+ !this.virtualScroll() &&
110
+ !!this.options?.length);
111
+ }
112
+ /** Whether every option "select all" can act on is selected. */
113
+ get allOptionsSelected() {
114
+ const targets = this.selectAllTargets;
115
+ // `[].every()` is `true`: with nothing for "select all" to act on, claiming "all selected" would
116
+ // send the toggle down the deselect branch and check the master checkbox over an untouchable list.
117
+ return targets.length > 0 && targets.every((option) => option.selected);
118
+ }
119
+ /** State of the "select all" master checkbox. */
120
+ get selectAllState() {
121
+ return getSelectAllState(this.selectAllAdapter(this.selectAllTargets));
122
+ }
123
+ /**
124
+ * Options "select all" acts on, and the ones its checkbox state is derived from. Read from
125
+ * {@link options}, so the row it renders itself is never among them.
126
+ */
127
+ get selectAllTargets() {
128
+ return this.options?.filter((option) => !option.disabled) ?? [];
129
+ }
130
+ /**
131
+ * Adapter shared by the master checkbox and the Ctrl/Cmd + A handler, so the two cannot drift apart.
132
+ *
133
+ * Takes the items rather than reading {@link selectAllTargets} itself: the toggle needs that array for
134
+ * the emitted event anyway, and deriving it here as well would walk the whole option list twice.
135
+ */
136
+ selectAllAdapter(items) {
137
+ return {
138
+ items,
139
+ isSelectable: () => true,
140
+ isSelected: (option) => option.selected,
141
+ setSelected: (option, selected) => option.setSelected(selected)
142
+ };
143
+ }
96
144
  get multiple() {
97
145
  return !!this.multipleMode;
98
146
  }
@@ -125,11 +173,14 @@ class KbqListSelection {
125
173
  get showCheckbox() {
126
174
  return this.multipleMode === MultipleMode.CHECKBOX;
127
175
  }
176
+ // Built over the navigable list, not `options`: the "select all" row lives in this component's own
177
+ // view, so its focus would otherwise reach nobody and leave the key manager pointing at whichever
178
+ // option was active before the user clicked the row.
128
179
  get optionFocusChanges() {
129
- return merge(...this.options.map((option) => option.onFocus));
180
+ return merge(...this.navigableOptions.map((option) => option.onFocus));
130
181
  }
131
182
  get optionBlurChanges() {
132
- return merge(...this.options.map((option) => option.onBlur));
183
+ return merge(...this.navigableOptions.map((option) => option.onBlur));
133
184
  }
134
185
  constructor() {
135
186
  this.elementRef = inject(ElementRef);
@@ -168,6 +219,51 @@ class KbqListSelection {
168
219
  this.dropped = output();
169
220
  /** When `true`, a repeated Ctrl/Cmd+A deselects all options. Off by default (Ctrl+A only selects). */
170
221
  this.selectAllToggle = input(false, ...(ngDevMode ? [{ debugName: "selectAllToggle", transform: booleanAttribute }] : [{ transform: booleanAttribute }]));
222
+ /**
223
+ * Whether to render the "select all" master checkbox above the options. `multiple="checkbox"` only —
224
+ * a vertical list, since the row is a full-width heading of the column it governs.
225
+ *
226
+ * The row acts on every option the user can toggle, disabled ones excluded. Enabling it also makes
227
+ * Ctrl/Cmd + A a two-way toggle, so the shortcut and the checkbox never disagree ({@link selectAllToggle}
228
+ * is implied).
229
+ *
230
+ * Aliased rather than named `selectAll`, which is already taken by the imperative method of that name.
231
+ */
232
+ this.selectAllEnabled = input(false, ...(ngDevMode ? [{ debugName: "selectAllEnabled", alias: 'selectAll', transform: booleanAttribute }] : [{ alias: 'selectAll', transform: booleanAttribute }]));
233
+ /**
234
+ * Reference to the built-in "select all" row, rendered only while `selectAll` is on.
235
+ *
236
+ * Located by template reference rather than by the `KbqListOption` type: that class is declared
237
+ * below this one in the same file, and a query locator is evaluated while this class is being
238
+ * defined, which would read it in its temporal dead zone.
239
+ */
240
+ this.selectAllOption = viewChild('selectAllRow', ...(ngDevMode ? [{ debugName: "selectAllOption" }] : []));
241
+ /**
242
+ * The options the key manager navigates: the "select all" row first, then the projected ones.
243
+ *
244
+ * Kept apart from {@link options} because that query is public API and means "the options the consumer
245
+ * projected" — a synthetic entry there would corrupt `getSelectedOptionValues`, the drop-indicator
246
+ * geometry and every consumer tally built on it.
247
+ * @docs-private
248
+ */
249
+ this.navigableOptions = new QueryList();
250
+ /**
251
+ * The virtual scroller rendering the options, when the consumer projected one.
252
+ *
253
+ * A signal query rather than a DOM probe, mirroring `KbqSelect.cdkVirtualForOf`: it resolves on the
254
+ * server as well as in the browser, and it follows a viewport that appears later behind the
255
+ * consumer's own `@if`.
256
+ */
257
+ this.virtualScroll = contentChild(CdkVirtualForOf, ...(ngDevMode ? [{ debugName: "virtualScroll" }] : []));
258
+ /** Label of the "select all" row. Follows the active locale. */
259
+ this.selectAllText = ruRULocaleData.select.selectAll;
260
+ this.localeService = inject(KBQ_LOCALE_SERVICE, { optional: true });
261
+ /** Updates locale parameters from the locale service. */
262
+ this.updateLocaleParams = () => {
263
+ // Locale data registered by a consumer through `KBQ_LOCALE_DATA`/`addLocale` may predate this key.
264
+ this.selectAllText = this.localeService?.getParams('select')?.selectAll ?? ruRULocaleData.select.selectAll;
265
+ this.changeDetectorRef.markForCheck();
266
+ };
171
267
  this.horizontal = input(false, ...(ngDevMode ? [{ debugName: "horizontal", transform: booleanAttribute }] : [{ transform: booleanAttribute }]));
172
268
  this._tabIndex = 0;
173
269
  this._disabled = false;
@@ -239,10 +335,71 @@ class KbqListSelection {
239
335
  this.compareWith();
240
336
  this.initializeSelection();
241
337
  });
338
+ this.localeService?.changes.pipe(takeUntilDestroyed()).subscribe(this.updateLocaleParams);
339
+ // The "select all" row is rendered by this component's own template, so `options.changes` never
340
+ // fires for it — the navigable list has to be rebuilt whenever the view query resolves or drops it.
341
+ effect(() => {
342
+ this.selectAllOption();
343
+ this.syncNavigableOptions();
344
+ });
242
345
  this.setupDropListInitialProperties();
243
346
  }
347
+ /** Rebuilds {@link navigableOptions}: the "select all" row, when rendered, leads the projected options. */
348
+ syncNavigableOptions() {
349
+ const selectAllOption = this.selectAllOption();
350
+ const options = this.options?.toArray() ?? [];
351
+ this.navigableOptions.reset(selectAllOption ? [selectAllOption, ...options] : options);
352
+ this.navigableOptions.notifyOnChanges();
353
+ }
354
+ /**
355
+ * Marks the list for check after an option changed something the "select all" row is derived from —
356
+ * its selection or its `disabled` state.
357
+ *
358
+ * An option marking itself only asks its ancestors to traverse down to it; it does not re-evaluate
359
+ * their own bindings. Without this the row keeps painting a state the options have already left, and
360
+ * a click on a checkbox showing `indeterminate` over an already-full selection takes the deselect
361
+ * branch — doing the opposite of what the user was shown.
362
+ * @docs-private
363
+ */
364
+ refreshSelectAllState() {
365
+ if (this.showSelectAll) {
366
+ this.changeDetectorRef.markForCheck();
367
+ }
368
+ }
369
+ /** Whether the option is the built-in "select all" row rather than one the consumer projected. */
370
+ isSelectAllRow(option) {
371
+ return !!option && option === this.selectAllOption();
372
+ }
373
+ /**
374
+ * Selects every option "select all" can act on, or deselects them all when they are already selected.
375
+ *
376
+ * Backs both the master checkbox and Ctrl/Cmd + A, so the two can never disagree. Reports the value
377
+ * once for the whole batch instead of once per option.
378
+ */
379
+ toggleSelectAll() {
380
+ // The row's own `(click)` and the shortcut both funnel through here, so this is the single place
381
+ // to refuse acting on a disabled list — the guard every option already gets in `handleClick`.
382
+ if (this.disabled)
383
+ return;
384
+ const targets = this.selectAllTargets;
385
+ toggleSelectAll(this.selectAllAdapter(targets), { allowDeselect: this.allowSelectAllDeselect });
386
+ // Reported unconditionally, as the shortcut has always done: a repeat that flips nothing still
387
+ // re-reports the value, which is what normalizes a form value holding entries no option matches.
388
+ this.reportValueChange();
389
+ // Deliberately no `selectionChange`: that event carries a single option, and a batch is
390
+ // reported through `onSelectAll` instead — the contract Ctrl/Cmd + A has always had.
391
+ this.onSelectAll.emit(new KbqListSelectAllEvent(this, targets));
392
+ }
393
+ /**
394
+ * Whether a repeated toggle deselects. Keyed on {@link showSelectAll} rather than on the raw input:
395
+ * with no row on screen there is no checkbox for the shortcut to agree with, so the attribute must
396
+ * not quietly change what Ctrl/Cmd + A does.
397
+ */
398
+ get allowSelectAllDeselect() {
399
+ return this.showSelectAll || this.selectAllToggle();
400
+ }
244
401
  ngAfterContentInit() {
245
- this.keyManager = new FocusKeyManager(this.options)
402
+ this.keyManager = new FocusKeyManager(this.navigableOptions)
246
403
  .withTypeAhead()
247
404
  .withVerticalOrientation(!this.horizontal())
248
405
  .withHorizontalOrientation(this.horizontal() ? 'ltr' : null);
@@ -267,14 +424,21 @@ class KbqListSelection {
267
424
  for (const item of event.removed) {
268
425
  item.selected = false;
269
426
  }
427
+ this.refreshSelectAllState();
270
428
  });
271
429
  this.listenToOptionsFocus();
272
430
  this.options.changes.pipe(startWith(null), takeUntilDestroyed(this.destroyRef)).subscribe(() => {
431
+ this.syncNavigableOptions();
273
432
  this.updateTabIndex();
274
433
  this.initializeSelection();
434
+ // `showSelectAll` is derived from the option count, and nothing else in this view changes
435
+ // when an option is added or removed — without this the row would not appear on the first
436
+ // option, nor go away with the last one.
437
+ this.changeDetectorRef.markForCheck();
275
438
  });
276
439
  if (!this.platform.isBrowser)
277
440
  return;
441
+ this.warnOnUnsupportedSelectAllContainer();
278
442
  this.warnOnUnsupportedDragContainer();
279
443
  this.updateScrollSize();
280
444
  // `updateScrollSize` only feeds the key manager's page size — nothing rendered depends on it,
@@ -311,12 +475,18 @@ class KbqListSelection {
311
475
  this.onTouched();
312
476
  this.changeDetectorRef.markForCheck();
313
477
  }
314
- /** Selects every non-disabled option and reports the new value to the `ControlValueAccessor`. */
478
+ /**
479
+ * Selects every option and reports the new value to the `ControlValueAccessor`.
480
+ *
481
+ * Unlike the `selectAll` attribute and Ctrl/Cmd + A, this acts on disabled options as well — it is
482
+ * an imperative command, not something the user performed. See {@link toggleSelectAll} for the
483
+ * behaviour the master checkbox has.
484
+ */
315
485
  selectAll() {
316
486
  this.options.forEach((option) => option.setSelected(true));
317
487
  this.reportValueChange();
318
488
  }
319
- /** Deselects every option and reports the new value to the `ControlValueAccessor`. */
489
+ /** Deselects every option, disabled ones included, and reports the new value. See {@link selectAll}. */
320
490
  deselectAll() {
321
491
  this.options.forEach((option) => option.setSelected(false));
322
492
  this.reportValueChange();
@@ -372,7 +542,10 @@ class KbqListSelection {
372
542
  }
373
543
  }
374
544
  selectActiveOptions() {
375
- const options = this.options.toArray();
545
+ // Indexed against the navigable list, which is what the key manager reports positions in. The
546
+ // "select all" row leads that list when rendered and is filtered back out below, so a range
547
+ // extended across it selects the options it spans and leaves the row itself alone.
548
+ const options = this.navigableOptions.toArray();
376
549
  let fromIndex = this.keyManager.previousActiveItemIndex;
377
550
  let toIndex = (this.keyManager.previousActiveItemIndex = this.keyManager.activeItemIndex);
378
551
  // `previousActiveItemIndex` stays -1 until the key manager has moved at least once, so a
@@ -380,13 +553,18 @@ class KbqListSelection {
380
553
  if (toIndex === fromIndex || !this.isValidIndex(fromIndex) || !this.isValidIndex(toIndex)) {
381
554
  return;
382
555
  }
383
- const selectedOptionState = options[fromIndex].selected;
556
+ const anchor = options[fromIndex];
557
+ // The row carries no selection of its own, so a range anchored on it has no state to apply.
558
+ if (this.isSelectAllRow(anchor)) {
559
+ return;
560
+ }
561
+ const selectedOptionState = anchor.selected;
384
562
  if (fromIndex > toIndex) {
385
563
  [fromIndex, toIndex] = [toIndex, fromIndex];
386
564
  }
387
565
  options
388
566
  .slice(fromIndex, toIndex + 1)
389
- .filter((item) => !item.disabled)
567
+ .filter((item) => !item.disabled && !this.isSelectAllRow(item))
390
568
  .forEach((renderedOption) => {
391
569
  if (!selectedOptionState && this.noUnselectLast && this.selectionModel.selected.length === 1) {
392
570
  return;
@@ -427,7 +605,13 @@ class KbqListSelection {
427
605
  toggleFocusedOption() {
428
606
  const focusedIndex = this.keyManager.activeItemIndex;
429
607
  if (focusedIndex != null && this.isValidIndex(focusedIndex)) {
430
- const focusedOption = this.options.toArray()[focusedIndex];
608
+ const focusedOption = this.navigableOptions.toArray()[focusedIndex];
609
+ // The row holds no selection of its own, so `toggle()` would be a no-op on it. Space and
610
+ // Enter have to reach the batch toggle instead, exactly as a click on the row does.
611
+ if (this.isSelectAllRow(focusedOption)) {
612
+ this.toggleSelectAll();
613
+ return;
614
+ }
431
615
  if (focusedOption && !focusedOption.disabled && this.canDeselectLast(focusedOption)) {
432
616
  focusedOption.toggle();
433
617
  // Emit a change event because the focused option changed its state through user interaction.
@@ -445,16 +629,16 @@ class KbqListSelection {
445
629
  * @docs-private
446
630
  */
447
631
  getHeight() {
448
- return this.elementRef.nativeElement.getClientRects()?.[0]?.height ?? 0;
632
+ return kbqGetElementHeight(this.elementRef.nativeElement);
449
633
  }
450
634
  // Removes an option from the selection list and updates the active item.
451
635
  removeOptionFromList(option) {
452
636
  if (!option.hasFocus) {
453
637
  return;
454
638
  }
455
- const optionIndex = this.getOptionIndex(option);
639
+ const optionIndex = this.navigableOptions.toArray().indexOf(option);
456
640
  // Check whether the option is the last item
457
- if (optionIndex === this.options.length - 1) {
641
+ if (optionIndex === this.navigableOptions.length - 1) {
458
642
  this.keyManager.setPreviousItemActive();
459
643
  }
460
644
  else {
@@ -507,7 +691,11 @@ class KbqListSelection {
507
691
  // manager's own orientation config cannot double-handle them.
508
692
  this.keyManager.onKeydown(event);
509
693
  }
510
- if (this.keyManager.activeItem && this.isNavigationKey(event)) {
694
+ // Navigating onto the "select all" row must not select it: it holds no selection of its own,
695
+ // and in `autoSelect` mode the branch below would clear the list to select nothing.
696
+ if (this.keyManager.activeItem &&
697
+ this.isNavigationKey(event) &&
698
+ !this.isSelectAllRow(this.keyManager.activeItem)) {
511
699
  this.setSelectedOptionsByKey(this.keyManager.activeItem, hasModifierKey(event, 'shiftKey'),
512
700
  // ctrlKey is for Windows, metaKey is for MacOS
513
701
  hasModifierKey(event, 'ctrlKey', 'metaKey'));
@@ -553,7 +741,9 @@ class KbqListSelection {
553
741
  });
554
742
  }
555
743
  updateTabIndex() {
556
- // Check to see if we need to update our tab index
744
+ // Counted over `options`, not the navigable list: the "select all" row only renders when there
745
+ // is at least one option, so the two are empty together — and `navigableOptions` is rebuilt a
746
+ // pass later, which would leave an emptied list holding a tab stop with nothing to focus.
557
747
  this._tabIndex = this.userTabIndex || (this.options.length === 0 ? -1 : 0);
558
748
  }
559
749
  onCopyDefaultHandler() {
@@ -564,21 +754,25 @@ class KbqListSelection {
564
754
  * `switchMap` tears down the previous `merge` for us, so no manual subscription bookkeeping.
565
755
  */
566
756
  listenToOptionsFocus() {
567
- this.options.changes
757
+ // Re-subscribed on the navigable list rather than on `options`: the latter never fires when the
758
+ // "select all" row alone appears or disappears, which would leave its focus unheard.
759
+ this.navigableOptions.changes
568
760
  .pipe(startWith(null), switchMap(() => this.optionFocusChanges), takeUntilDestroyed(this.destroyRef))
569
761
  .subscribe((event) => {
570
- const index = this.options.toArray().indexOf(event.option);
762
+ const index = this.navigableOptions.toArray().indexOf(event.option);
571
763
  if (this.isValidIndex(index)) {
572
764
  this.keyManager.updateActiveItem(index);
573
765
  }
574
766
  });
575
- this.options.changes
767
+ this.navigableOptions.changes
576
768
  .pipe(startWith(null), switchMap(() => this.optionBlurChanges), takeUntilDestroyed(this.destroyRef))
577
769
  .subscribe(() => this.blur());
578
770
  }
579
771
  /** Checks whether any of the options is focused. */
580
772
  hasFocusedOption() {
581
- return this.options.some((option) => option.hasFocus);
773
+ // Asked of the navigable list so that focus resting on the "select all" row does not read as
774
+ // "nothing is focused" and clear the key manager out from under it.
775
+ return this.navigableOptions.some((option) => option.hasFocus);
582
776
  }
583
777
  // Returns the option with the specified value.
584
778
  getOptionByValue(value) {
@@ -602,7 +796,8 @@ class KbqListSelection {
602
796
  * @returns True if the index is valid for our list of options.
603
797
  */
604
798
  isValidIndex(index) {
605
- return index >= 0 && index < this.options.length;
799
+ // Bounded by the navigable list, the index space the key manager reports in.
800
+ return index >= 0 && index < this.navigableOptions.length;
606
801
  }
607
802
  // Returns the index of the specified list option.
608
803
  getOptionIndex(option) {
@@ -654,6 +849,18 @@ class KbqListSelection {
654
849
  this.followMovedOption(option, target);
655
850
  });
656
851
  }
852
+ /**
853
+ * Says once, in dev mode, why `selectAll` produced no row: the master checkbox could only ever act on
854
+ * the options the scroller happens to have rendered, so the row is dropped rather than left lying.
855
+ */
856
+ warnOnUnsupportedSelectAllContainer() {
857
+ if (!isDevMode() || !this.selectAllEnabled() || !this.virtualScroll()) {
858
+ return;
859
+ }
860
+ // eslint-disable-next-line no-console
861
+ console.warn('KbqListSelection: `selectAll` is not supported inside `cdk-virtual-scroll-viewport`. The ' +
862
+ 'row is not rendered, because it could only act on the options currently rendered.');
863
+ }
657
864
  /**
658
865
  * `CdkDropList` numbers only the options it has rendered, so inside a virtual scroll the indices
659
866
  * `dropped` reports do not address the consumer's backing array and the move silently lands on the
@@ -665,7 +872,7 @@ class KbqListSelection {
665
872
  if (this.hasWarnedOnDragContainer || !isDevMode() || !this.draggable || !this.platform.isBrowser) {
666
873
  return;
667
874
  }
668
- const insideVirtualScroll = !!this.elementRef.nativeElement.querySelector('cdk-virtual-scroll-viewport');
875
+ const insideVirtualScroll = !!this.virtualScroll();
669
876
  if (insideVirtualScroll) {
670
877
  // eslint-disable-next-line no-console
671
878
  console.warn('KbqListSelection: `draggable` is not supported inside `cdk-virtual-scroll-viewport`. The ' +
@@ -786,11 +993,14 @@ class KbqListSelection {
786
993
  container.pendingMoveSubscription = container.options.changes
787
994
  .pipe(take(1), takeUntilDestroyed(container.destroyRef))
788
995
  .subscribe(() => {
789
- const options = container.options.toArray();
996
+ // Resolved against the navigable list: `setActiveItem` takes an index in the key
997
+ // manager's own space, which the "select all" row leads when the target list renders one.
998
+ const options = container.navigableOptions.toArray();
790
999
  // Reordering within a list keeps the instance; moving between lists recreates it.
791
1000
  const index = options.includes(option)
792
1001
  ? options.indexOf(option)
793
- : options.findIndex((item) => runCompareWith(container.compareWith(), item.value, value));
1002
+ : options.findIndex((item) => !container.isSelectAllRow(item) &&
1003
+ runCompareWith(container.compareWith(), item.value, value));
794
1004
  if (index !== -1) {
795
1005
  container.keyManager.setActiveItem(index);
796
1006
  }
@@ -811,20 +1021,17 @@ class KbqListSelection {
811
1021
  }
812
1022
  _selectAllHandler(event, list) {
813
1023
  event.preventDefault();
814
- const options = list.options.toArray();
815
- toggleSelectAll({
816
- items: options,
817
- isSelectable: (option) => !option.disabled,
818
- isSelected: (option) => option.selected,
819
- setSelected: (option, selected) => option.setSelected(selected)
820
- }, { allowDeselect: list.selectAllToggle() });
821
- list.reportValueChange();
822
- list.onSelectAll.emit(new KbqListSelectAllEvent(list, options.filter((option) => !option.disabled)));
1024
+ // Funnelled through the same method the master checkbox uses, so the shortcut and the row can
1025
+ // never disagree about what "select all" acted on.
1026
+ list.toggleSelectAll();
823
1027
  }
824
1028
  copyActiveOption(event) {
825
1029
  if (!this.keyManager.activeItem)
826
1030
  return;
827
1031
  const option = this.keyManager.activeItem;
1032
+ // The row carries no value; copying it would put the string "undefined" on the clipboard.
1033
+ if (this.isSelectAllRow(option))
1034
+ return;
828
1035
  option.preventBlur = true;
829
1036
  if (this.onCopy.observed) {
830
1037
  this.onCopy.emit(new KbqListCopyEvent(this, option, event));
@@ -836,7 +1043,30 @@ class KbqListSelection {
836
1043
  option.preventBlur = false;
837
1044
  }
838
1045
  /** @nocollapse */ static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.30", ngImport: i0, type: KbqListSelection, deps: [], target: i0.ɵɵFactoryTarget.Component }); }
839
- /** @nocollapse */ static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "20.3.30", type: KbqListSelection, isStandalone: true, selector: "kbq-list-selection", inputs: { autoSelect: { classPropertyName: "autoSelect", publicName: "autoSelect", isSignal: false, isRequired: false, transformFunction: null }, noUnselectLast: { classPropertyName: "noUnselectLast", publicName: "noUnselectLast", isSignal: false, isRequired: false, transformFunction: null }, draggable: { classPropertyName: "draggable", publicName: "draggable", isSignal: false, isRequired: false, transformFunction: booleanAttribute }, connectedTo: { classPropertyName: "connectedTo", publicName: "connectedTo", isSignal: true, isRequired: false, transformFunction: null }, dragPreview: { classPropertyName: "dragPreview", publicName: "dragPreview", isSignal: true, isRequired: false, transformFunction: null }, dragCursor: { classPropertyName: "dragCursor", publicName: "dragCursor", isSignal: true, isRequired: false, transformFunction: null }, selectAllToggle: { classPropertyName: "selectAllToggle", publicName: "selectAllToggle", isSignal: true, isRequired: false, transformFunction: null }, horizontal: { classPropertyName: "horizontal", publicName: "horizontal", isSignal: true, isRequired: false, transformFunction: null }, tabIndex: { classPropertyName: "tabIndex", publicName: "tabIndex", isSignal: false, isRequired: false, transformFunction: null }, disabled: { classPropertyName: "disabled", publicName: "disabled", isSignal: false, isRequired: false, transformFunction: booleanAttribute }, compareWith: { classPropertyName: "compareWith", publicName: "compareWith", isSignal: true, isRequired: false, transformFunction: null }, selectAllHandler: { classPropertyName: "selectAllHandler", publicName: "selectAllHandler", isSignal: false, isRequired: false, transformFunction: null } }, outputs: { onSelectAll: "onSelectAll", onCopy: "onCopy", dropped: "dropped", selectionChange: "selectionChange" }, host: { attributes: { "role": "listbox" }, listeners: { "keydown": "onKeyDown($event)", "focus": "focus()", "blur": "blur()" }, properties: { "class.kbq-disabled": "disabled", "class.kbq-list-selection_horizontal": "horizontal()", "class.kbq-list-selection_draggable": "draggable", "attr.aria-multiselectable": "multiple", "attr.aria-orientation": "horizontal() ? \"horizontal\" : null", "attr.aria-disabled": "disabled || null", "attr.tabindex": "tabIndex" }, classAttribute: "kbq-list-selection" }, providers: [KBQ_SELECTION_LIST_VALUE_ACCESSOR], queries: [{ propertyName: "options", predicate: i0.forwardRef(() => KbqListOption), descendants: true }], exportAs: ["kbqListSelection"], hostDirectives: [{ directive: i1.CdkDropList, inputs: ["id", "id"] }], ngImport: i0, template: `
1046
+ /** @nocollapse */ static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "20.3.30", type: KbqListSelection, isStandalone: true, selector: "kbq-list-selection", inputs: { autoSelect: { classPropertyName: "autoSelect", publicName: "autoSelect", isSignal: false, isRequired: false, transformFunction: null }, noUnselectLast: { classPropertyName: "noUnselectLast", publicName: "noUnselectLast", isSignal: false, isRequired: false, transformFunction: null }, draggable: { classPropertyName: "draggable", publicName: "draggable", isSignal: false, isRequired: false, transformFunction: booleanAttribute }, connectedTo: { classPropertyName: "connectedTo", publicName: "connectedTo", isSignal: true, isRequired: false, transformFunction: null }, dragPreview: { classPropertyName: "dragPreview", publicName: "dragPreview", isSignal: true, isRequired: false, transformFunction: null }, dragCursor: { classPropertyName: "dragCursor", publicName: "dragCursor", isSignal: true, isRequired: false, transformFunction: null }, selectAllToggle: { classPropertyName: "selectAllToggle", publicName: "selectAllToggle", isSignal: true, isRequired: false, transformFunction: null }, selectAllEnabled: { classPropertyName: "selectAllEnabled", publicName: "selectAll", isSignal: true, isRequired: false, transformFunction: null }, horizontal: { classPropertyName: "horizontal", publicName: "horizontal", isSignal: true, isRequired: false, transformFunction: null }, tabIndex: { classPropertyName: "tabIndex", publicName: "tabIndex", isSignal: false, isRequired: false, transformFunction: null }, disabled: { classPropertyName: "disabled", publicName: "disabled", isSignal: false, isRequired: false, transformFunction: booleanAttribute }, compareWith: { classPropertyName: "compareWith", publicName: "compareWith", isSignal: true, isRequired: false, transformFunction: null }, selectAllHandler: { classPropertyName: "selectAllHandler", publicName: "selectAllHandler", isSignal: false, isRequired: false, transformFunction: null } }, outputs: { onSelectAll: "onSelectAll", onCopy: "onCopy", dropped: "dropped", selectionChange: "selectionChange" }, host: { attributes: { "role": "listbox" }, listeners: { "keydown": "onKeyDown($event)", "focus": "focus()", "blur": "blur()" }, properties: { "class.kbq-disabled": "disabled", "class.kbq-list-selection_horizontal": "horizontal()", "class.kbq-list-selection_draggable": "draggable", "attr.aria-multiselectable": "multiple", "attr.aria-orientation": "horizontal() ? \"horizontal\" : null", "attr.aria-disabled": "disabled || null", "attr.tabindex": "tabIndex" }, classAttribute: "kbq-list-selection" }, providers: [KBQ_SELECTION_LIST_VALUE_ACCESSOR], queries: [{ propertyName: "virtualScroll", first: true, predicate: CdkVirtualForOf, descendants: true, isSignal: true }, { propertyName: "options", predicate: i0.forwardRef(() => KbqListOption), descendants: true }], viewQueries: [{ propertyName: "selectAllOption", first: true, predicate: ["selectAllRow"], descendants: true, isSignal: true }], exportAs: ["kbqListSelection"], hostDirectives: [{ directive: i1.CdkDropList, inputs: ["id", "id"] }], ngImport: i0, template: `
1047
+ @if (showSelectAll) {
1048
+ <!-- Every read of selectAllState re-filters the whole option list, so the two bindings below
1049
+ share one through @let. The row's own aria-checked host binding walks it a second time:
1050
+ Ivy evaluates that binding after this template, and the option reads the state off the
1051
+ list rather than from here. -->
1052
+ @let selectAllCheckboxState = selectAllState;
1053
+
1054
+ <!--
1055
+ aria-checked and aria-selected come from the option's own host bindings: a host binding
1056
+ runs after the parent template's, so an override here would be the one that loses. The
1057
+ class binding is the other way around, which is why the selected state is written here.
1058
+ -->
1059
+ <kbq-list-option
1060
+ #selectAllRow
1061
+ class="kbq-list-selection__select-all"
1062
+ [selectAllRow]="true"
1063
+ [class.kbq-selected]="selectAllCheckboxState === 'checked'"
1064
+ (click)="toggleSelectAll()"
1065
+ >
1066
+ <kbq-pseudo-checkbox aria-hidden="true" [disabled]="disabled" [state]="selectAllCheckboxState" />
1067
+ {{ selectAllText }}
1068
+ </kbq-list-option>
1069
+ }
840
1070
  <ng-content />
841
1071
  @if (dropIndicatorOffset() !== null) {
842
1072
  <!-- Purely decorative: the drop target is a pointer affordance, not a status message. -->
@@ -846,11 +1076,37 @@ class KbqListSelection {
846
1076
  [style.--kbq-list-drop-indicator-offset.px]="dropIndicatorOffset()"
847
1077
  ></div>
848
1078
  }
849
- `, isInline: true, styles: [".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-list,.kbq-list-selection{display:block;outline:none}.kbq-list-selection_horizontal{display:flex;flex-direction:row}.kbq-list-selection_horizontal .kbq-list-option{flex:0 0 auto}.kbq-list-selection{position:relative}.kbq-list-item,.kbq-list-option{-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-list-item .kbq-list-text>*,.kbq-list-option .kbq-list-text>*{margin:0;padding:0;font-weight:400;font-size:inherit}.kbq-list-item .kbq-list-text,.kbq-list-option .kbq-list-text{display:flex;flex-direction:column;width:100%;box-sizing:content-box;overflow:hidden}.kbq-list-item .kbq-list-text:empty,.kbq-list-option .kbq-list-text:empty{display:none}.kbq-list-item .kbq-list-text,.kbq-list-option .kbq-list-text{display:inline-block;white-space:nowrap;overflow:hidden;text-overflow:ellipsis}.kbq-list-item .kbq-list-option-caption,.kbq-list-option .kbq-list-option-caption{padding-top:var(--kbq-size-3xs)}.kbq-list-item,.kbq-list-option{border-width:var(--kbq-list-size-container-focus-outline-width, var(--kbq-size-3xs));border-radius:var(--kbq-size-border-radius);gap:var(--kbq-list-size-container-content-gap-horizontal, var(--kbq-size-s));padding-top:var(--kbq-list-size-container-padding-vertical, var(--kbq-size-xxs));padding-right:calc(var(--kbq-list-size-container-padding-right, var(--kbq-size-m)) - var(--kbq-list-size-container-focus-outline-width, var(--kbq-size-3xs)));padding-bottom:var(--kbq-list-size-container-padding-vertical, var(--kbq-size-xxs));padding-left:calc(var(--kbq-list-size-container-padding-left, var(--kbq-size-m)) - var(--kbq-list-size-container-focus-outline-width, var(--kbq-size-3xs)))}.kbq-list-item .kbq-list-option-caption,.kbq-list-option .kbq-list-option-caption{padding-top:var(--kbq-list-size-container-content-gap-vertical, var(--kbq-size-3xs))}.kbq-list-item:not(.kbq-disabled),.kbq-list-option:not(.kbq-disabled){cursor:pointer}body:has(.kbq-list-drag-preview){cursor:grabbing}body:has(.kbq-list-drag-preview) .kbq-list-option.kbq-list-option_draggable,body:has(.kbq-list-drag-preview) .kbq-list-option_draggable .cdk-drag-handle{cursor:grabbing}body:has(.kbq-list-drag-preview) .kbq-list-option{pointer-events:none}body:has(.kbq-list-drag-preview) .kbq-optgroup-label{cursor:inherit}body:has(.kbq-list-drag-preview):has(.kbq-list-option_drop-forbidden){cursor:no-drop}.kbq-list-option:is(.kbq-selected):has(+:is(.kbq-selected)){border-bottom-left-radius:unset;border-bottom-right-radius:unset}.kbq-list-option:is(.kbq-selected)+:is(.kbq-selected){border-top-left-radius:unset;border-top-right-radius:unset}.kbq-list-option:not(.kbq-disabled):hover .kbq-action-container,.kbq-list-option:not(.kbq-disabled).kbq-hovered .kbq-action-container,.kbq-list-option:not(.kbq-disabled).kbq-action-button-focused .kbq-action-container{display:flex}.kbq-list-selection.cdk-keyboard-focused .kbq-list-option:not(.kbq-disabled).kbq-focused .kbq-action-container{display:flex}.kbq-list-option.kbq-list-option_draggable .cdk-drag-handle{cursor:grab}.kbq-list-option.kbq-list-option_grab-cursor:not(:has(.cdk-drag-handle)){cursor:grab}.kbq-list-option.cdk-drag-placeholder,.kbq-list-option.cdk-drag-anchor{opacity:var(--kbq-opacity-disabled)}.kbq-list-option.kbq-list-option_foreign-placeholder{display:none}.kbq-list-selection__drop-indicator{position:absolute;background:var(--kbq-list-states-dragged-indicator-color);pointer-events:none}.kbq-list-selection:not(.kbq-list-selection_horizontal) .kbq-list-selection__drop-indicator{left:0;right:0;top:calc(var(--kbq-list-drop-indicator-offset, 0px) - var(--kbq-list-size-dragged-indicator-thickness) / 2);block-size:var(--kbq-list-size-dragged-indicator-thickness)}.kbq-list-selection_horizontal .kbq-list-selection__drop-indicator{top:0;bottom:0;left:calc(var(--kbq-list-drop-indicator-offset, 0px) - var(--kbq-list-size-dragged-indicator-thickness) / 2);inline-size:var(--kbq-list-size-dragged-indicator-thickness)}.kbq-list-option{--kbq-option-background: var(--kbq-list-default-container-background, transparent);background:var(--kbq-list-default-container-background, transparent)}.kbq-list-option .kbq-list-text{color:var(--kbq-list-default-text-color, var(--kbq-list-default-text-color))}.kbq-list-option .kbq-icon.kbq-empty{color:var(--kbq-list-default-icon-color, var(--kbq-list-default-icon-color))}.kbq-list-option .kbq-option-action .kbq-icon.kbq-empty{color:var(--kbq-list-default-icon-button-color, var(--kbq-list-default-icon-button-color))}.kbq-list-option .kbq-list-option-caption{color:var(--kbq-list-default-caption-color, var(--kbq-list-default-caption-color))}.kbq-list-option.kbq-hovered:not(.kbq-disabled),.kbq-list-option:hover:not(.kbq-disabled),.kbq-list-option.kbq-action-button-focused:not(.kbq-disabled){--kbq-option-background: var(--kbq-list-states-hover-container-background, transparent);background:var(--kbq-list-states-hover-container-background, transparent)}.kbq-list-option.kbq-hovered:not(.kbq-disabled) .kbq-list-text,.kbq-list-option:hover:not(.kbq-disabled) .kbq-list-text,.kbq-list-option.kbq-action-button-focused:not(.kbq-disabled) .kbq-list-text{color:var(--kbq-list-states-hover-text-color, var(--kbq-list-default-text-color))}.kbq-list-option.kbq-hovered:not(.kbq-disabled) .kbq-icon.kbq-empty,.kbq-list-option:hover:not(.kbq-disabled) .kbq-icon.kbq-empty,.kbq-list-option.kbq-action-button-focused:not(.kbq-disabled) .kbq-icon.kbq-empty{color:var(--kbq-list-states-hover-icon-color, var(--kbq-list-default-icon-color))}.kbq-list-option.kbq-hovered:not(.kbq-disabled) .kbq-option-action .kbq-icon.kbq-empty,.kbq-list-option:hover:not(.kbq-disabled) .kbq-option-action .kbq-icon.kbq-empty,.kbq-list-option.kbq-action-button-focused:not(.kbq-disabled) .kbq-option-action .kbq-icon.kbq-empty{color:var(--kbq-list-states-hover-icon-button-color, var(--kbq-list-default-icon-button-color))}.kbq-list-option.kbq-hovered:not(.kbq-disabled) .kbq-list-option-caption,.kbq-list-option:hover:not(.kbq-disabled) .kbq-list-option-caption,.kbq-list-option.kbq-action-button-focused:not(.kbq-disabled) .kbq-list-option-caption{color:var(--kbq-list-states-hover-caption-color, var(--kbq-list-default-caption-color))}.kbq-list-option.kbq-active:not(.kbq-disabled),.kbq-list-option:active:not(.kbq-disabled){--kbq-option-background: var(--kbq-list-states-active-container-background);background:var(--kbq-list-states-active-container-background)}.kbq-list-option.kbq-selected:not(.kbq-disabled){--kbq-option-background: var(--kbq-list-states-selected-container-background, transparent);background:var(--kbq-list-states-selected-container-background, transparent)}.kbq-list-option.kbq-selected:not(.kbq-disabled) .kbq-list-text{color:var(--kbq-list-states-selected-text-color, var(--kbq-list-default-text-color))}.kbq-list-option.kbq-selected:not(.kbq-disabled) .kbq-icon.kbq-empty{color:var(--kbq-list-states-selected-icon-color, var(--kbq-list-default-icon-color))}.kbq-list-option.kbq-selected:not(.kbq-disabled) .kbq-option-action .kbq-icon.kbq-empty{color:var(--kbq-list-states-selected-icon-button-color, var(--kbq-list-default-icon-button-color))}.kbq-list-option.kbq-selected:not(.kbq-disabled) .kbq-list-option-caption{color:var(--kbq-list-states-selected-caption-color, var(--kbq-list-default-caption-color))}.kbq-list-option.kbq-selected:not(.kbq-disabled).kbq-hovered,.kbq-list-option.kbq-selected:not(.kbq-disabled):hover{--kbq-option-background: var(--kbq-list-states-selected-hover-container-background, transparent);background:var(--kbq-list-states-selected-hover-container-background, transparent)}.kbq-list-option.kbq-selected:not(.kbq-disabled).kbq-hovered .kbq-list-text,.kbq-list-option.kbq-selected:not(.kbq-disabled):hover .kbq-list-text{color:var(--kbq-list-states-selected-hover-text-color, var(--kbq-list-default-text-color))}.kbq-list-option.kbq-selected:not(.kbq-disabled).kbq-hovered .kbq-icon.kbq-empty,.kbq-list-option.kbq-selected:not(.kbq-disabled):hover .kbq-icon.kbq-empty{color:var(--kbq-list-states-selected-hover-icon-color, var(--kbq-list-default-icon-color))}.kbq-list-option.kbq-selected:not(.kbq-disabled).kbq-hovered .kbq-option-action .kbq-icon.kbq-empty,.kbq-list-option.kbq-selected:not(.kbq-disabled):hover .kbq-option-action .kbq-icon.kbq-empty{color:var(--kbq-list-states-selected-hover-icon-button-color, var(--kbq-list-default-icon-button-color))}.kbq-list-option.kbq-selected:not(.kbq-disabled).kbq-hovered .kbq-list-option-caption,.kbq-list-option.kbq-selected:not(.kbq-disabled):hover .kbq-list-option-caption{color:var(--kbq-list-states-selected-hover-caption-color, var(--kbq-list-default-caption-color))}.kbq-list-option.kbq-selected:not(.kbq-disabled).kbq-active,.kbq-list-option.kbq-selected:not(.kbq-disabled):active{--kbq-option-background: var(--kbq-list-states-selected-active-container-background);background:var(--kbq-list-states-selected-active-container-background)}.kbq-list-option.kbq-disabled{--kbq-option-background: var(--kbq-list-states-disabled-container-background, transparent);background:var(--kbq-list-states-disabled-container-background, transparent)}.kbq-list-option.kbq-disabled .kbq-list-text{color:var(--kbq-list-states-disabled-text-color, var(--kbq-list-default-text-color))}.kbq-list-option.kbq-disabled .kbq-icon.kbq-empty{color:var(--kbq-list-states-disabled-icon-color, var(--kbq-list-default-icon-color))}.kbq-list-option.kbq-disabled .kbq-option-action .kbq-icon.kbq-empty{color:var(--kbq-list-states-disabled-icon-button-color, var(--kbq-list-default-icon-button-color))}.kbq-list-option.kbq-disabled .kbq-list-option-caption{color:var(--kbq-list-states-disabled-caption-color, var(--kbq-list-default-caption-color))}.kbq-list-option.kbq-selected.kbq-disabled{--kbq-option-background: var(--kbq-list-states-selected-container-background);background:var(--kbq-list-states-selected-container-background)}.kbq-list-option.kbq-list-option_multiple.kbq-selected:not(.kbq-disabled){--kbq-option-background: var(--kbq-list-multiple-states-selected-container-background, transparent);background:var(--kbq-list-multiple-states-selected-container-background, transparent)}.kbq-list-option.kbq-list-option_multiple.kbq-selected:not(.kbq-disabled) .kbq-list-text{color:var(--kbq-list-multiple-states-selected-text-color, var(--kbq-list-default-text-color))}.kbq-list-option.kbq-list-option_multiple.kbq-selected:not(.kbq-disabled) .kbq-icon.kbq-empty{color:var(--kbq-list-multiple-states-selected-icon-color, var(--kbq-list-default-icon-color))}.kbq-list-option.kbq-list-option_multiple.kbq-selected:not(.kbq-disabled) .kbq-option-action .kbq-icon.kbq-empty{color:var(--kbq-list-multiple-states-selected-icon-button-color, var(--kbq-list-default-icon-button-color))}.kbq-list-option.kbq-list-option_multiple.kbq-selected:not(.kbq-disabled) .kbq-list-option-caption{color:var(--kbq-list-multiple-states-selected-caption-color, var(--kbq-list-default-caption-color))}.kbq-list-option.kbq-list-option_multiple.kbq-selected:not(.kbq-disabled).kbq-hovered,.kbq-list-option.kbq-list-option_multiple.kbq-selected:not(.kbq-disabled):hover{--kbq-option-background: var(--kbq-list-multiple-states-selected-hover-container-background, transparent);background:var(--kbq-list-multiple-states-selected-hover-container-background, transparent)}.kbq-list-option.kbq-list-option_multiple.kbq-selected:not(.kbq-disabled).kbq-hovered .kbq-list-text,.kbq-list-option.kbq-list-option_multiple.kbq-selected:not(.kbq-disabled):hover .kbq-list-text{color:var(--kbq-list-multiple-states-selected-hover-text-color, var(--kbq-list-default-text-color))}.kbq-list-option.kbq-list-option_multiple.kbq-selected:not(.kbq-disabled).kbq-hovered .kbq-icon.kbq-empty,.kbq-list-option.kbq-list-option_multiple.kbq-selected:not(.kbq-disabled):hover .kbq-icon.kbq-empty{color:var(--kbq-list-multiple-states-selected-hover-icon-color, var(--kbq-list-default-icon-color))}.kbq-list-option.kbq-list-option_multiple.kbq-selected:not(.kbq-disabled).kbq-hovered .kbq-option-action .kbq-icon.kbq-empty,.kbq-list-option.kbq-list-option_multiple.kbq-selected:not(.kbq-disabled):hover .kbq-option-action .kbq-icon.kbq-empty{color:var(--kbq-list-multiple-states-selected-hover-icon-button-color, var(--kbq-list-default-icon-button-color))}.kbq-list-option.kbq-list-option_multiple.kbq-selected:not(.kbq-disabled).kbq-hovered .kbq-list-option-caption,.kbq-list-option.kbq-list-option_multiple.kbq-selected:not(.kbq-disabled):hover .kbq-list-option-caption{color:var(--kbq-list-multiple-states-selected-hover-caption-color, var(--kbq-list-default-caption-color))}.kbq-list-option.kbq-list-option_multiple.kbq-selected:not(.kbq-disabled).kbq-active,.kbq-list-option.kbq-list-option_multiple.kbq-selected:not(.kbq-disabled):active{--kbq-option-background: var(--kbq-list-multiple-states-selected-active-container-background);background:var(--kbq-list-multiple-states-selected-active-container-background)}.kbq-list-option.kbq-list-option_multiple.kbq-selected.kbq-disabled{--kbq-option-background: var(--kbq-list-multiple-states-selected-container-background);background:var(--kbq-list-multiple-states-selected-container-background)}.kbq-list-selection.cdk-keyboard-focused .kbq-list-option.kbq-focused{border-color:var(--kbq-list-states-focused-focus-outline-color)}.kbq-list-item,.kbq-list-option,.kbq-list-drag-preview_text{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-list-item .kbq-list-text .kbq-list-option-caption,.kbq-list-option .kbq-list-text .kbq-list-option-caption,.kbq-list-drag-preview_text .kbq-list-text .kbq-list-option-caption,.kbq-list-item .kbq-list-drag-preview__caption,.kbq-list-option .kbq-list-drag-preview__caption,.kbq-list-drag-preview_text .kbq-list-drag-preview__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-list-option.cdk-drag-preview{background:var(--kbq-list-states-dragged-container-background);box-shadow:var(--kbq-list-states-dragged-container-shadow)}.kbq-list-drag-preview_text{box-sizing:border-box;max-inline-size:var(--kbq-list-size-drag-preview-max-width);border-radius:var(--kbq-size-border-radius);padding:var(--kbq-list-size-container-padding-vertical) var(--kbq-list-size-container-padding-right) var(--kbq-list-size-container-padding-vertical) var(--kbq-list-size-container-padding-left);background:var(--kbq-list-states-drag-preview-background);box-shadow:var(--kbq-list-states-dragged-container-shadow);color:var(--kbq-list-default-text-color)}.kbq-list-drag-preview_text .kbq-list-drag-preview__label,.kbq-list-drag-preview_text .kbq-list-drag-preview__caption{overflow:hidden;text-overflow:ellipsis;white-space:nowrap}.kbq-list-drag-preview_text .kbq-list-drag-preview__caption{color:var(--kbq-list-default-caption-color);padding-top:var(--kbq-list-size-container-content-gap-vertical)}\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 )}\n"], changeDetection: i0.ChangeDetectionStrategy.OnPush, encapsulation: i0.ViewEncapsulation.None }); }
1079
+ `, isInline: true, styles: [".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-list,.kbq-list-selection{display:block;outline:none}.kbq-list-selection_horizontal{display:flex;flex-direction:row}.kbq-list-selection_horizontal .kbq-list-option{flex:0 0 auto}.kbq-list-selection{position:relative}.kbq-list-item,.kbq-list-option{-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-list-item .kbq-list-text>*,.kbq-list-option .kbq-list-text>*{margin:0;padding:0;font-weight:400;font-size:inherit}.kbq-list-item .kbq-list-text,.kbq-list-option .kbq-list-text{display:flex;flex-direction:column;width:100%;box-sizing:content-box;overflow:hidden}.kbq-list-item .kbq-list-text:empty,.kbq-list-option .kbq-list-text:empty{display:none}.kbq-list-item .kbq-list-text,.kbq-list-option .kbq-list-text{display:inline-block;white-space:nowrap;overflow:hidden;text-overflow:ellipsis}.kbq-list-item .kbq-list-option-caption,.kbq-list-option .kbq-list-option-caption{padding-top:var(--kbq-size-3xs)}.kbq-list-item,.kbq-list-option{border-width:var(--kbq-list-size-container-focus-outline-width, var(--kbq-size-3xs));border-radius:var(--kbq-size-border-radius);gap:var(--kbq-list-size-container-content-gap-horizontal, var(--kbq-size-s));padding-top:var(--kbq-list-size-container-padding-vertical, var(--kbq-size-xxs));padding-right:calc(var(--kbq-list-size-container-padding-right, var(--kbq-size-m)) - var(--kbq-list-size-container-focus-outline-width, var(--kbq-size-3xs)));padding-bottom:var(--kbq-list-size-container-padding-vertical, var(--kbq-size-xxs));padding-left:calc(var(--kbq-list-size-container-padding-left, var(--kbq-size-m)) - var(--kbq-list-size-container-focus-outline-width, var(--kbq-size-3xs)))}.kbq-list-item .kbq-list-option-caption,.kbq-list-option .kbq-list-option-caption{padding-top:var(--kbq-list-size-container-content-gap-vertical, var(--kbq-size-3xs))}.kbq-list-item:not(.kbq-disabled),.kbq-list-option:not(.kbq-disabled){cursor:pointer}body:has(.kbq-list-drag-preview){cursor:grabbing}body:has(.kbq-list-drag-preview) .kbq-list-option.kbq-list-option_draggable,body:has(.kbq-list-drag-preview) .kbq-list-option_draggable .cdk-drag-handle{cursor:grabbing}body:has(.kbq-list-drag-preview) .kbq-list-option{pointer-events:none}body:has(.kbq-list-drag-preview) .kbq-optgroup-label{cursor:inherit}body:has(.kbq-list-drag-preview):has(.kbq-list-option_drop-forbidden){cursor:no-drop}.kbq-list-option:is(.kbq-selected):has(+:is(.kbq-selected)){border-bottom-left-radius:unset;border-bottom-right-radius:unset}.kbq-list-option:is(.kbq-selected)+:is(.kbq-selected){border-top-left-radius:unset;border-top-right-radius:unset}.kbq-list-option:not(.kbq-disabled):hover .kbq-action-container,.kbq-list-option:not(.kbq-disabled).kbq-hovered .kbq-action-container,.kbq-list-option:not(.kbq-disabled).kbq-action-button-focused .kbq-action-container{display:flex}.kbq-list-selection.cdk-keyboard-focused .kbq-list-option:not(.kbq-disabled).kbq-focused .kbq-action-container{display:flex}.kbq-list-option.kbq-list-option_draggable .cdk-drag-handle{cursor:grab}.kbq-list-option.kbq-list-option_grab-cursor:not(:has(.cdk-drag-handle)){cursor:grab}.kbq-list-option.cdk-drag-placeholder,.kbq-list-option.cdk-drag-anchor{opacity:var(--kbq-opacity-disabled)}.kbq-list-option.kbq-list-option_foreign-placeholder{display:none}.kbq-list-selection__drop-indicator{position:absolute;background:var(--kbq-list-states-dragged-indicator-color);pointer-events:none}.kbq-list-selection:not(.kbq-list-selection_horizontal) .kbq-list-selection__drop-indicator{left:0;right:0;top:calc(var(--kbq-list-drop-indicator-offset, 0px) - var(--kbq-list-size-dragged-indicator-thickness) / 2);block-size:var(--kbq-list-size-dragged-indicator-thickness)}.kbq-list-selection_horizontal .kbq-list-selection__drop-indicator{top:0;bottom:0;left:calc(var(--kbq-list-drop-indicator-offset, 0px) - var(--kbq-list-size-dragged-indicator-thickness) / 2);inline-size:var(--kbq-list-size-dragged-indicator-thickness)}.kbq-list-option{--kbq-option-background: var(--kbq-list-default-container-background, transparent);background:var(--kbq-list-default-container-background, transparent)}.kbq-list-option .kbq-list-text{color:var(--kbq-list-default-text-color, var(--kbq-list-default-text-color))}.kbq-list-option .kbq-icon.kbq-empty{color:var(--kbq-list-default-icon-color, var(--kbq-list-default-icon-color))}.kbq-list-option .kbq-option-action .kbq-icon.kbq-empty{color:var(--kbq-list-default-icon-button-color, var(--kbq-list-default-icon-button-color))}.kbq-list-option .kbq-list-option-caption{color:var(--kbq-list-default-caption-color, var(--kbq-list-default-caption-color))}.kbq-list-option.kbq-hovered:not(.kbq-disabled),.kbq-list-option:hover:not(.kbq-disabled),.kbq-list-option.kbq-action-button-focused:not(.kbq-disabled){--kbq-option-background: var(--kbq-list-states-hover-container-background, transparent);background:var(--kbq-list-states-hover-container-background, transparent)}.kbq-list-option.kbq-hovered:not(.kbq-disabled) .kbq-list-text,.kbq-list-option:hover:not(.kbq-disabled) .kbq-list-text,.kbq-list-option.kbq-action-button-focused:not(.kbq-disabled) .kbq-list-text{color:var(--kbq-list-states-hover-text-color, var(--kbq-list-default-text-color))}.kbq-list-option.kbq-hovered:not(.kbq-disabled) .kbq-icon.kbq-empty,.kbq-list-option:hover:not(.kbq-disabled) .kbq-icon.kbq-empty,.kbq-list-option.kbq-action-button-focused:not(.kbq-disabled) .kbq-icon.kbq-empty{color:var(--kbq-list-states-hover-icon-color, var(--kbq-list-default-icon-color))}.kbq-list-option.kbq-hovered:not(.kbq-disabled) .kbq-option-action .kbq-icon.kbq-empty,.kbq-list-option:hover:not(.kbq-disabled) .kbq-option-action .kbq-icon.kbq-empty,.kbq-list-option.kbq-action-button-focused:not(.kbq-disabled) .kbq-option-action .kbq-icon.kbq-empty{color:var(--kbq-list-states-hover-icon-button-color, var(--kbq-list-default-icon-button-color))}.kbq-list-option.kbq-hovered:not(.kbq-disabled) .kbq-list-option-caption,.kbq-list-option:hover:not(.kbq-disabled) .kbq-list-option-caption,.kbq-list-option.kbq-action-button-focused:not(.kbq-disabled) .kbq-list-option-caption{color:var(--kbq-list-states-hover-caption-color, var(--kbq-list-default-caption-color))}.kbq-list-option.kbq-active:not(.kbq-disabled),.kbq-list-option:active:not(.kbq-disabled){--kbq-option-background: var(--kbq-list-states-active-container-background);background:var(--kbq-list-states-active-container-background)}.kbq-list-option.kbq-selected:not(.kbq-disabled){--kbq-option-background: var(--kbq-list-states-selected-container-background, transparent);background:var(--kbq-list-states-selected-container-background, transparent)}.kbq-list-option.kbq-selected:not(.kbq-disabled) .kbq-list-text{color:var(--kbq-list-states-selected-text-color, var(--kbq-list-default-text-color))}.kbq-list-option.kbq-selected:not(.kbq-disabled) .kbq-icon.kbq-empty{color:var(--kbq-list-states-selected-icon-color, var(--kbq-list-default-icon-color))}.kbq-list-option.kbq-selected:not(.kbq-disabled) .kbq-option-action .kbq-icon.kbq-empty{color:var(--kbq-list-states-selected-icon-button-color, var(--kbq-list-default-icon-button-color))}.kbq-list-option.kbq-selected:not(.kbq-disabled) .kbq-list-option-caption{color:var(--kbq-list-states-selected-caption-color, var(--kbq-list-default-caption-color))}.kbq-list-option.kbq-selected:not(.kbq-disabled).kbq-hovered,.kbq-list-option.kbq-selected:not(.kbq-disabled):hover{--kbq-option-background: var(--kbq-list-states-selected-hover-container-background, transparent);background:var(--kbq-list-states-selected-hover-container-background, transparent)}.kbq-list-option.kbq-selected:not(.kbq-disabled).kbq-hovered .kbq-list-text,.kbq-list-option.kbq-selected:not(.kbq-disabled):hover .kbq-list-text{color:var(--kbq-list-states-selected-hover-text-color, var(--kbq-list-default-text-color))}.kbq-list-option.kbq-selected:not(.kbq-disabled).kbq-hovered .kbq-icon.kbq-empty,.kbq-list-option.kbq-selected:not(.kbq-disabled):hover .kbq-icon.kbq-empty{color:var(--kbq-list-states-selected-hover-icon-color, var(--kbq-list-default-icon-color))}.kbq-list-option.kbq-selected:not(.kbq-disabled).kbq-hovered .kbq-option-action .kbq-icon.kbq-empty,.kbq-list-option.kbq-selected:not(.kbq-disabled):hover .kbq-option-action .kbq-icon.kbq-empty{color:var(--kbq-list-states-selected-hover-icon-button-color, var(--kbq-list-default-icon-button-color))}.kbq-list-option.kbq-selected:not(.kbq-disabled).kbq-hovered .kbq-list-option-caption,.kbq-list-option.kbq-selected:not(.kbq-disabled):hover .kbq-list-option-caption{color:var(--kbq-list-states-selected-hover-caption-color, var(--kbq-list-default-caption-color))}.kbq-list-option.kbq-selected:not(.kbq-disabled).kbq-active,.kbq-list-option.kbq-selected:not(.kbq-disabled):active{--kbq-option-background: var(--kbq-list-states-selected-active-container-background);background:var(--kbq-list-states-selected-active-container-background)}.kbq-list-option.kbq-disabled{--kbq-option-background: var(--kbq-list-states-disabled-container-background, transparent);background:var(--kbq-list-states-disabled-container-background, transparent)}.kbq-list-option.kbq-disabled .kbq-list-text{color:var(--kbq-list-states-disabled-text-color, var(--kbq-list-default-text-color))}.kbq-list-option.kbq-disabled .kbq-icon.kbq-empty{color:var(--kbq-list-states-disabled-icon-color, var(--kbq-list-default-icon-color))}.kbq-list-option.kbq-disabled .kbq-option-action .kbq-icon.kbq-empty{color:var(--kbq-list-states-disabled-icon-button-color, var(--kbq-list-default-icon-button-color))}.kbq-list-option.kbq-disabled .kbq-list-option-caption{color:var(--kbq-list-states-disabled-caption-color, var(--kbq-list-default-caption-color))}.kbq-list-option.kbq-selected.kbq-disabled{--kbq-option-background: var(--kbq-list-states-selected-container-background);background:var(--kbq-list-states-selected-container-background)}.kbq-list-option.kbq-list-option_multiple.kbq-selected:not(.kbq-disabled){--kbq-option-background: var(--kbq-list-multiple-states-selected-container-background, transparent);background:var(--kbq-list-multiple-states-selected-container-background, transparent)}.kbq-list-option.kbq-list-option_multiple.kbq-selected:not(.kbq-disabled) .kbq-list-text{color:var(--kbq-list-multiple-states-selected-text-color, var(--kbq-list-default-text-color))}.kbq-list-option.kbq-list-option_multiple.kbq-selected:not(.kbq-disabled) .kbq-icon.kbq-empty{color:var(--kbq-list-multiple-states-selected-icon-color, var(--kbq-list-default-icon-color))}.kbq-list-option.kbq-list-option_multiple.kbq-selected:not(.kbq-disabled) .kbq-option-action .kbq-icon.kbq-empty{color:var(--kbq-list-multiple-states-selected-icon-button-color, var(--kbq-list-default-icon-button-color))}.kbq-list-option.kbq-list-option_multiple.kbq-selected:not(.kbq-disabled) .kbq-list-option-caption{color:var(--kbq-list-multiple-states-selected-caption-color, var(--kbq-list-default-caption-color))}.kbq-list-option.kbq-list-option_multiple.kbq-selected:not(.kbq-disabled).kbq-hovered,.kbq-list-option.kbq-list-option_multiple.kbq-selected:not(.kbq-disabled):hover{--kbq-option-background: var(--kbq-list-multiple-states-selected-hover-container-background, transparent);background:var(--kbq-list-multiple-states-selected-hover-container-background, transparent)}.kbq-list-option.kbq-list-option_multiple.kbq-selected:not(.kbq-disabled).kbq-hovered .kbq-list-text,.kbq-list-option.kbq-list-option_multiple.kbq-selected:not(.kbq-disabled):hover .kbq-list-text{color:var(--kbq-list-multiple-states-selected-hover-text-color, var(--kbq-list-default-text-color))}.kbq-list-option.kbq-list-option_multiple.kbq-selected:not(.kbq-disabled).kbq-hovered .kbq-icon.kbq-empty,.kbq-list-option.kbq-list-option_multiple.kbq-selected:not(.kbq-disabled):hover .kbq-icon.kbq-empty{color:var(--kbq-list-multiple-states-selected-hover-icon-color, var(--kbq-list-default-icon-color))}.kbq-list-option.kbq-list-option_multiple.kbq-selected:not(.kbq-disabled).kbq-hovered .kbq-option-action .kbq-icon.kbq-empty,.kbq-list-option.kbq-list-option_multiple.kbq-selected:not(.kbq-disabled):hover .kbq-option-action .kbq-icon.kbq-empty{color:var(--kbq-list-multiple-states-selected-hover-icon-button-color, var(--kbq-list-default-icon-button-color))}.kbq-list-option.kbq-list-option_multiple.kbq-selected:not(.kbq-disabled).kbq-hovered .kbq-list-option-caption,.kbq-list-option.kbq-list-option_multiple.kbq-selected:not(.kbq-disabled):hover .kbq-list-option-caption{color:var(--kbq-list-multiple-states-selected-hover-caption-color, var(--kbq-list-default-caption-color))}.kbq-list-option.kbq-list-option_multiple.kbq-selected:not(.kbq-disabled).kbq-active,.kbq-list-option.kbq-list-option_multiple.kbq-selected:not(.kbq-disabled):active{--kbq-option-background: var(--kbq-list-multiple-states-selected-active-container-background);background:var(--kbq-list-multiple-states-selected-active-container-background)}.kbq-list-option.kbq-list-option_multiple.kbq-selected.kbq-disabled{--kbq-option-background: var(--kbq-list-multiple-states-selected-container-background);background:var(--kbq-list-multiple-states-selected-container-background)}.kbq-list-selection.cdk-keyboard-focused .kbq-list-option.kbq-focused{border-color:var(--kbq-list-states-focused-focus-outline-color)}.kbq-list-item,.kbq-list-option,.kbq-list-drag-preview_text{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-list-item .kbq-list-text .kbq-list-option-caption,.kbq-list-option .kbq-list-text .kbq-list-option-caption,.kbq-list-drag-preview_text .kbq-list-text .kbq-list-option-caption,.kbq-list-item .kbq-list-drag-preview__caption,.kbq-list-option .kbq-list-drag-preview__caption,.kbq-list-drag-preview_text .kbq-list-drag-preview__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-list-option.cdk-drag-preview{background:var(--kbq-list-states-dragged-container-background);box-shadow:var(--kbq-list-states-dragged-container-shadow)}.kbq-list-drag-preview_text{box-sizing:border-box;max-inline-size:var(--kbq-list-size-drag-preview-max-width);border-radius:var(--kbq-size-border-radius);padding:var(--kbq-list-size-container-padding-vertical) var(--kbq-list-size-container-padding-right) var(--kbq-list-size-container-padding-vertical) var(--kbq-list-size-container-padding-left);background:var(--kbq-list-states-drag-preview-background);box-shadow:var(--kbq-list-states-dragged-container-shadow);color:var(--kbq-list-default-text-color)}.kbq-list-drag-preview_text .kbq-list-drag-preview__label,.kbq-list-drag-preview_text .kbq-list-drag-preview__caption{overflow:hidden;text-overflow:ellipsis;white-space:nowrap}.kbq-list-drag-preview_text .kbq-list-drag-preview__caption{color:var(--kbq-list-default-caption-color);padding-top:var(--kbq-list-size-container-content-gap-vertical)}\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 )}\n"], dependencies: [{ kind: "component", type: i0.forwardRef(() => KbqListOption), selector: "kbq-list-option", inputs: ["checkboxPosition", "selectAllRow", "value", "disabled", "draggable", "showCheckbox", "selected"], exportAs: ["kbqListOption"] }, { kind: "component", type: i0.forwardRef(() => KbqPseudoCheckbox), selector: "kbq-pseudo-checkbox", inputs: ["big", "state", "disabled"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush, encapsulation: i0.ViewEncapsulation.None }); }
850
1080
  }
851
1081
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.30", ngImport: i0, type: KbqListSelection, decorators: [{
852
1082
  type: Component,
853
- args: [{ selector: 'kbq-list-selection', template: `
1083
+ args: [{ selector: 'kbq-list-selection', imports: [
1084
+ forwardRef((() => KbqListOption)),
1085
+ KbqPseudoCheckbox
1086
+ ], template: `
1087
+ @if (showSelectAll) {
1088
+ <!-- Every read of selectAllState re-filters the whole option list, so the two bindings below
1089
+ share one through @let. The row's own aria-checked host binding walks it a second time:
1090
+ Ivy evaluates that binding after this template, and the option reads the state off the
1091
+ list rather than from here. -->
1092
+ @let selectAllCheckboxState = selectAllState;
1093
+
1094
+ <!--
1095
+ aria-checked and aria-selected come from the option's own host bindings: a host binding
1096
+ runs after the parent template's, so an override here would be the one that loses. The
1097
+ class binding is the other way around, which is why the selected state is written here.
1098
+ -->
1099
+ <kbq-list-option
1100
+ #selectAllRow
1101
+ class="kbq-list-selection__select-all"
1102
+ [selectAllRow]="true"
1103
+ [class.kbq-selected]="selectAllCheckboxState === 'checked'"
1104
+ (click)="toggleSelectAll()"
1105
+ >
1106
+ <kbq-pseudo-checkbox aria-hidden="true" [disabled]="disabled" [state]="selectAllCheckboxState" />
1107
+ {{ selectAllText }}
1108
+ </kbq-list-option>
1109
+ }
854
1110
  <ng-content />
855
1111
  @if (dropIndicatorOffset() !== null) {
856
1112
  <!-- Purely decorative: the drop target is a pointer affordance, not a status message. -->
@@ -886,7 +1142,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.30", ngImpo
886
1142
  }], draggable: [{
887
1143
  type: Input,
888
1144
  args: [{ transform: booleanAttribute }]
889
- }], connectedTo: [{ type: i0.Input, args: [{ isSignal: true, alias: "connectedTo", required: false }] }], dragPreview: [{ type: i0.Input, args: [{ isSignal: true, alias: "dragPreview", required: false }] }], dragCursor: [{ type: i0.Input, args: [{ isSignal: true, alias: "dragCursor", required: false }] }], dropped: [{ type: i0.Output, args: ["dropped"] }], selectAllToggle: [{ type: i0.Input, args: [{ isSignal: true, alias: "selectAllToggle", required: false }] }], horizontal: [{ type: i0.Input, args: [{ isSignal: true, alias: "horizontal", required: false }] }], tabIndex: [{
1145
+ }], connectedTo: [{ type: i0.Input, args: [{ isSignal: true, alias: "connectedTo", required: false }] }], dragPreview: [{ type: i0.Input, args: [{ isSignal: true, alias: "dragPreview", required: false }] }], dragCursor: [{ type: i0.Input, args: [{ isSignal: true, alias: "dragCursor", required: false }] }], dropped: [{ type: i0.Output, args: ["dropped"] }], selectAllToggle: [{ type: i0.Input, args: [{ isSignal: true, alias: "selectAllToggle", required: false }] }], selectAllEnabled: [{ type: i0.Input, args: [{ isSignal: true, alias: "selectAll", required: false }] }], selectAllOption: [{ type: i0.ViewChild, args: ['selectAllRow', { isSignal: true }] }], virtualScroll: [{ type: i0.ContentChild, args: [i0.forwardRef(() => CdkVirtualForOf), { isSignal: true }] }], horizontal: [{ type: i0.Input, args: [{ isSignal: true, alias: "horizontal", required: false }] }], tabIndex: [{
890
1146
  type: Input
891
1147
  }], disabled: [{
892
1148
  type: Input,
@@ -958,6 +1214,8 @@ class KbqListOption {
958
1214
  if (value !== this._disabled) {
959
1215
  this._disabled = value;
960
1216
  this.syncDraggableState();
1217
+ // A disabled option leaves the set "select all" acts on, which changes the row's checkbox.
1218
+ this.listSelection.refreshSelectAllState();
961
1219
  }
962
1220
  }
963
1221
  /**
@@ -969,7 +1227,8 @@ class KbqListOption {
969
1227
  * the list gates its whole drop list, so an option cannot opt back in on its own.
970
1228
  */
971
1229
  get draggable() {
972
- return this._draggable && this.listSelection.draggable && !this.disabled;
1230
+ // The "select all" row is a command, not one of the items being ordered.
1231
+ return !this.selectAllRow() && this._draggable && this.listSelection.draggable && !this.disabled;
973
1232
  }
974
1233
  set draggable(value) {
975
1234
  this._draggable = value;
@@ -1000,6 +1259,21 @@ class KbqListOption {
1000
1259
  get tabIndex() {
1001
1260
  return this.disabled ? null : -1;
1002
1261
  }
1262
+ /** `aria-selected` of the row. The "select all" row reports `aria-checked` instead. */
1263
+ get ariaSelected() {
1264
+ return this.selectAllRow() ? null : this.selected;
1265
+ }
1266
+ /**
1267
+ * Tri-state of the "select all" row, `mixed` included. `null` for an ordinary option, which
1268
+ * reports `aria-selected` instead.
1269
+ */
1270
+ get ariaChecked() {
1271
+ if (!this.selectAllRow()) {
1272
+ return null;
1273
+ }
1274
+ const state = this.listSelection.selectAllState;
1275
+ return state === 'indeterminate' ? 'mixed' : `${state === 'checked'}`;
1276
+ }
1003
1277
  get externalPseudoCheckbox() {
1004
1278
  return !!this.pseudoCheckbox();
1005
1279
  }
@@ -1033,6 +1307,15 @@ class KbqListOption {
1033
1307
  this.text = viewChild.required('text');
1034
1308
  // Whether the label should appear before or after the checkbox. Defaults to 'after'
1035
1309
  this.checkboxPosition = input(undefined, ...(ngDevMode ? [{ debugName: "checkboxPosition" }] : []));
1310
+ /**
1311
+ * Whether this option is the list's "select all" row rather than one the consumer projected.
1312
+ *
1313
+ * Such a row has no `value` and no place in the `SelectionModel`, so everything that would resolve
1314
+ * it against the list's selection is skipped; its checkbox state and its selected look are driven
1315
+ * from the outside instead. It also stays out of the drag-and-drop registry — see the constructor.
1316
+ * @docs-private
1317
+ */
1318
+ this.selectAllRow = input(false, ...(ngDevMode ? [{ debugName: "selectAllRow", transform: booleanAttribute }] : [{ transform: booleanAttribute }]));
1036
1319
  /**
1037
1320
  * This is set to true after the first OnChanges cycle so we don't clear the value of `selected`
1038
1321
  * in the first cycle.
@@ -1075,6 +1358,22 @@ class KbqListOption {
1075
1358
  this.changeDetector.markForCheck();
1076
1359
  }
1077
1360
  ngOnInit() {
1361
+ if (this.selectAllRow()) {
1362
+ // `CdkDrag` registers itself with the enclosing drop list from its own constructor, and the
1363
+ // row is rendered inside `kbq-list-selection`, so it lands in the registry like any option.
1364
+ // Left there it would take drag item #0 and shift the `previousIndex` every `dropped` event
1365
+ // reports, while `currentIndex` — derived from `options`, which the row is not part of —
1366
+ // would stay put. `disabled` alone does not unregister it. Deferred to here rather than done
1367
+ // in the constructor because a signal input is not set yet at construction time.
1368
+ this.drag.dropContainer?.removeItem(this.drag);
1369
+ // `syncDraggableState()` already ran from the constructor, where this input still read its
1370
+ // default — so on a list that was draggable from the first render the row was left with an
1371
+ // enabled `CdkDrag`. Unregistering it is not enough: `removeItem` leaves `DragRef` pointing
1372
+ // at the drop container, so a pointer-down would still start a drag reporting index -1.
1373
+ this.syncDraggableState();
1374
+ this.inputsInitialized = true;
1375
+ return;
1376
+ }
1078
1377
  // Resolving the model value is the list's job, not the option's. An option that matched itself
1079
1378
  // here answered a different question than `getOptionByValue` does — every match self-selected,
1080
1379
  // while the list picks the first — so a comparator that matches more than one option produced a
@@ -1094,6 +1393,12 @@ class KbqListOption {
1094
1393
  this.inputsInitialized = true;
1095
1394
  }
1096
1395
  ngOnDestroy() {
1396
+ // The row owns no selection, so there is nothing to release — but it does hold a place in the
1397
+ // navigable list, and a focused row that disappears still has to hand the key manager on.
1398
+ if (this.selectAllRow()) {
1399
+ this.listSelection.removeOptionFromList(this);
1400
+ return;
1401
+ }
1097
1402
  if (this.selected) {
1098
1403
  // We have to delay this until the next tick in order
1099
1404
  // to avoid changed after checked errors.
@@ -1106,6 +1411,11 @@ class KbqListOption {
1106
1411
  this.selected = !this.selected;
1107
1412
  }
1108
1413
  getLabel() {
1414
+ // The "select all" row is kept out of type-ahead: its localized label would otherwise shadow
1415
+ // an option starting with the same letter.
1416
+ if (this.selectAllRow()) {
1417
+ return '';
1418
+ }
1109
1419
  const text = this.text();
1110
1420
  return text ? (text.nativeElement.textContent ?? '') : '';
1111
1421
  }
@@ -1133,7 +1443,8 @@ class KbqListOption {
1133
1443
  /** Sets the selected state directly on the list's `SelectionModel`, bypassing the `selected` input setter. */
1134
1444
  setSelected(selected) {
1135
1445
  const { selectionModel } = this.listSelection;
1136
- if (!selectionModel) {
1446
+ // The row has no place in the selection model — its look is driven by `selectAllState`.
1447
+ if (!selectionModel || this.selectAllRow()) {
1137
1448
  return;
1138
1449
  }
1139
1450
  // The model is consulted alongside the mirror so that an option the model dropped behind the
@@ -1156,11 +1467,13 @@ class KbqListOption {
1156
1467
  * @docs-private
1157
1468
  */
1158
1469
  getHeight() {
1159
- return this.elementRef.nativeElement.getClientRects()?.[0]?.height ?? 0;
1470
+ return kbqGetElementHeight(this.elementRef.nativeElement);
1160
1471
  }
1161
1472
  /** Handles click events on the list option. */
1162
1473
  handleClick($event) {
1163
- if (this.disabled) {
1474
+ // The row's own `(click)` in the list's template runs the batch toggle; this handler would
1475
+ // otherwise put the row itself through the ordinary selection path on the same click.
1476
+ if (this.disabled || this.selectAllRow()) {
1164
1477
  return;
1165
1478
  }
1166
1479
  this.listSelection.setSelectedOptionsByClick(this, hasModifierKey($event, 'shiftKey'),
@@ -1210,7 +1523,7 @@ class KbqListOption {
1210
1523
  return this.elementRef.nativeElement;
1211
1524
  }
1212
1525
  /** @nocollapse */ static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.30", ngImport: i0, type: KbqListOption, deps: [], target: i0.ɵɵFactoryTarget.Component }); }
1213
- /** @nocollapse */ static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "20.3.30", type: KbqListOption, isStandalone: true, selector: "kbq-list-option", inputs: { checkboxPosition: { classPropertyName: "checkboxPosition", publicName: "checkboxPosition", isSignal: true, isRequired: false, transformFunction: null }, value: { classPropertyName: "value", publicName: "value", isSignal: false, isRequired: false, transformFunction: null }, disabled: { classPropertyName: "disabled", publicName: "disabled", isSignal: false, isRequired: false, transformFunction: booleanAttribute }, draggable: { classPropertyName: "draggable", publicName: "draggable", isSignal: false, isRequired: false, transformFunction: booleanAttribute }, showCheckbox: { classPropertyName: "showCheckbox", publicName: "showCheckbox", isSignal: false, isRequired: false, transformFunction: null }, selected: { classPropertyName: "selected", publicName: "selected", isSignal: false, isRequired: false, transformFunction: booleanAttribute } }, host: { attributes: { "role": "option" }, listeners: { "focusin": "focus()", "blur": "blur()", "click": "handleClick($event)", "keydown": "onKeydown($event)" }, properties: { "class.kbq-selected": "selected", "class.kbq-list-option_multiple": "listSelection.multiple", "class.kbq-list-option_draggable": "draggable", "class.kbq-list-option_grab-cursor": "showsGrabCursor", "class.kbq-disabled": "disabled", "class.kbq-focused": "hasFocus", "class.kbq-action-button-focused": "actionButton()?.active", "attr.aria-selected": "selected", "attr.aria-disabled": "disabled || null", "attr.tabindex": "tabIndex" }, classAttribute: "kbq-list-option" }, providers: [
1526
+ /** @nocollapse */ static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "20.3.30", type: KbqListOption, isStandalone: true, selector: "kbq-list-option", inputs: { checkboxPosition: { classPropertyName: "checkboxPosition", publicName: "checkboxPosition", isSignal: true, isRequired: false, transformFunction: null }, selectAllRow: { classPropertyName: "selectAllRow", publicName: "selectAllRow", isSignal: true, isRequired: false, transformFunction: null }, value: { classPropertyName: "value", publicName: "value", isSignal: false, isRequired: false, transformFunction: null }, disabled: { classPropertyName: "disabled", publicName: "disabled", isSignal: false, isRequired: false, transformFunction: booleanAttribute }, draggable: { classPropertyName: "draggable", publicName: "draggable", isSignal: false, isRequired: false, transformFunction: booleanAttribute }, showCheckbox: { classPropertyName: "showCheckbox", publicName: "showCheckbox", isSignal: false, isRequired: false, transformFunction: null }, selected: { classPropertyName: "selected", publicName: "selected", isSignal: false, isRequired: false, transformFunction: booleanAttribute } }, host: { attributes: { "role": "option" }, listeners: { "focusin": "focus()", "blur": "blur()", "click": "handleClick($event)", "keydown": "onKeydown($event)" }, properties: { "class.kbq-selected": "selected", "class.kbq-list-option_multiple": "listSelection.multiple", "class.kbq-list-option_draggable": "draggable", "class.kbq-list-option_grab-cursor": "showsGrabCursor", "class.kbq-disabled": "disabled", "class.kbq-focused": "hasFocus", "class.kbq-action-button-focused": "actionButton()?.active", "attr.aria-selected": "ariaSelected", "attr.aria-checked": "ariaChecked", "attr.aria-disabled": "disabled || null", "attr.tabindex": "tabIndex" }, classAttribute: "kbq-list-option" }, providers: [
1214
1527
  { provide: KBQ_OPTION_ACTION_PARENT, useExisting: KbqListOption },
1215
1528
  { provide: KBQ_TITLE_TEXT_REF, useExisting: KbqListOption }
1216
1529
  ], queries: [{ propertyName: "actionButton", first: true, predicate: KbqOptionActionComponent, descendants: true, isSignal: true }, { propertyName: "pseudoCheckbox", first: true, predicate: KbqPseudoCheckbox, descendants: true, isSignal: true }, { propertyName: "dragHandles", predicate: CDK_DRAG_HANDLE, descendants: true, isSignal: true }, { propertyName: "tooltipTrigger", first: true, predicate: KbqTooltipTrigger, descendants: true }, { propertyName: "dropdownTrigger", first: true, predicate: KbqDropdownTrigger, descendants: true }], viewQueries: [{ propertyName: "text", first: true, predicate: ["text"], descendants: true, isSignal: true }, { propertyName: "textElement", first: true, predicate: ["kbqTitleText"], descendants: true }], exportAs: ["kbqListOption"], hostDirectives: [{ directive: i1.CdkDrag }], ngImport: i0, template: "@if (externalPseudoCheckbox) {\n <ng-content select=\"kbq-pseudo-checkbox\" />\n} @else if (showCheckbox) {\n <!-- Decorative: assistive technology reads the selected state from the option's own aria-selected. -->\n <kbq-pseudo-checkbox aria-hidden=\"true\" [disabled]=\"disabled\" [state]=\"selected ? 'checked' : 'unchecked'\" />\n}\n\n<ng-content select=\"[kbq-icon]\" />\n\n<div #kbqTitleText #text class=\"kbq-list-text\">\n <ng-content />\n <ng-content select=\"[kbq-list-option-caption]\" />\n</div>\n\n@if (actionButton()) {\n <kbq-action-container>\n <ng-content select=\"kbq-option-action\" />\n </kbq-action-container>\n}\n\n@if (listSelection.dragPreview() === 'text') {\n <!--\n Registers with the host `CdkDrag` through `CDK_DRAG_PARENT`, not through a content query, which\n is why it can live in the option's own view. The template body is a single element and nothing\n else: CDK wraps the view in a plain div otherwise, and that wrapper \u2014 not this plate \u2014 would\n become the preview. The plate is decorative, it repeats text the listbox already exposes.\n -->\n <ng-template cdkDragPreview>\n <div class=\"kbq-list-drag-preview_text\" aria-hidden=\"true\">\n <!-- Read on render rather than cached on `started`: CDK builds the preview before it emits. -->\n @let text = getDragPreviewText();\n <div class=\"kbq-list-drag-preview__label\">{{ text.label }}</div>\n @if (text.caption) {\n <div class=\"kbq-list-drag-preview__caption\">{{ text.caption }}</div>\n }\n </div>\n </ng-template>\n}\n", dependencies: [{ kind: "directive", type: CdkDragPreview, selector: "ng-template[cdkDragPreview]", inputs: ["data", "matchSize"] }, { kind: "component", type: KbqPseudoCheckbox, selector: "kbq-pseudo-checkbox", inputs: ["big", "state", "disabled"] }, { kind: "component", type: KbqActionContainer, selector: "kbq-action-container", exportAs: ["kbqActionContainer"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush, encapsulation: i0.ViewEncapsulation.None }); }
@@ -1234,7 +1547,8 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.30", ngImpo
1234
1547
  '[class.kbq-disabled]': 'disabled',
1235
1548
  '[class.kbq-focused]': 'hasFocus',
1236
1549
  '[class.kbq-action-button-focused]': 'actionButton()?.active',
1237
- '[attr.aria-selected]': 'selected',
1550
+ '[attr.aria-selected]': 'ariaSelected',
1551
+ '[attr.aria-checked]': 'ariaChecked',
1238
1552
  '[attr.aria-disabled]': 'disabled || null',
1239
1553
  '[attr.tabindex]': 'tabIndex',
1240
1554
  '(focusin)': 'focus()',
@@ -1251,7 +1565,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.30", ngImpo
1251
1565
  }], pseudoCheckbox: [{ type: i0.ContentChild, args: [i0.forwardRef(() => KbqPseudoCheckbox), { isSignal: true }] }], dragHandles: [{ type: i0.ContentChildren, args: [i0.forwardRef(() => CDK_DRAG_HANDLE), { ...{ descendants: true }, isSignal: true }] }], text: [{ type: i0.ViewChild, args: ['text', { isSignal: true }] }], textElement: [{
1252
1566
  type: ViewChild,
1253
1567
  args: ['kbqTitleText', { static: false }]
1254
- }], checkboxPosition: [{ type: i0.Input, args: [{ isSignal: true, alias: "checkboxPosition", required: false }] }], value: [{
1568
+ }], checkboxPosition: [{ type: i0.Input, args: [{ isSignal: true, alias: "checkboxPosition", required: false }] }], selectAllRow: [{ type: i0.Input, args: [{ isSignal: true, alias: "selectAllRow", required: false }] }], value: [{
1255
1569
  type: Input
1256
1570
  }], disabled: [{
1257
1571
  type: Input,
@@ -1340,6 +1654,7 @@ class KbqListModule {
1340
1654
  KbqOptionModule,
1341
1655
  KbqActionContainer,
1342
1656
  KbqIconModule,
1657
+ KbqListSelection,
1343
1658
  KbqListOption, KbqOptionModule] }); }
1344
1659
  }
1345
1660
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.30", ngImport: i0, type: KbqListModule, decorators: [{