@clr/angular 18.2.2 → 18.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 (112) hide show
  1. package/fesm2022/clr-angular-accordion.mjs +28 -28
  2. package/fesm2022/clr-angular-accordion.mjs.map +1 -1
  3. package/fesm2022/clr-angular-button.mjs +27 -27
  4. package/fesm2022/clr-angular-button.mjs.map +1 -1
  5. package/fesm2022/clr-angular-card.mjs +417 -0
  6. package/fesm2022/clr-angular-card.mjs.map +1 -0
  7. package/fesm2022/clr-angular-collapsible-panel.mjs +6 -6
  8. package/fesm2022/clr-angular-collapsible-panel.mjs.map +1 -1
  9. package/fesm2022/clr-angular-data-datagrid.mjs +1578 -415
  10. package/fesm2022/clr-angular-data-datagrid.mjs.map +1 -1
  11. package/fesm2022/clr-angular-data-stack-view.mjs +23 -23
  12. package/fesm2022/clr-angular-data-stack-view.mjs.map +1 -1
  13. package/fesm2022/clr-angular-data-tree-view.mjs +283 -48
  14. package/fesm2022/clr-angular-data-tree-view.mjs.map +1 -1
  15. package/fesm2022/clr-angular-data.mjs +4 -4
  16. package/fesm2022/clr-angular-data.mjs.map +1 -1
  17. package/fesm2022/clr-angular-emphasis-alert.mjs +26 -26
  18. package/fesm2022/clr-angular-emphasis-alert.mjs.map +1 -1
  19. package/fesm2022/clr-angular-emphasis-badge.mjs +3 -3
  20. package/fesm2022/clr-angular-emphasis-badge.mjs.map +1 -1
  21. package/fesm2022/clr-angular-emphasis-label.mjs +3 -3
  22. package/fesm2022/clr-angular-emphasis-label.mjs.map +1 -1
  23. package/fesm2022/clr-angular-emphasis.mjs +4 -4
  24. package/fesm2022/clr-angular-emphasis.mjs.map +1 -1
  25. package/fesm2022/clr-angular-forms-checkbox.mjs +23 -14
  26. package/fesm2022/clr-angular-forms-checkbox.mjs.map +1 -1
  27. package/fesm2022/clr-angular-forms-combobox.mjs +35 -35
  28. package/fesm2022/clr-angular-forms-combobox.mjs.map +1 -1
  29. package/fesm2022/clr-angular-forms-common.mjs +69 -69
  30. package/fesm2022/clr-angular-forms-common.mjs.map +1 -1
  31. package/fesm2022/clr-angular-forms-datalist.mjs +17 -17
  32. package/fesm2022/clr-angular-forms-datalist.mjs.map +1 -1
  33. package/fesm2022/clr-angular-forms-datepicker.mjs +73 -73
  34. package/fesm2022/clr-angular-forms-datepicker.mjs.map +1 -1
  35. package/fesm2022/clr-angular-forms-file-input.mjs +36 -36
  36. package/fesm2022/clr-angular-forms-file-input.mjs.map +1 -1
  37. package/fesm2022/clr-angular-forms-input.mjs +10 -10
  38. package/fesm2022/clr-angular-forms-input.mjs.map +1 -1
  39. package/fesm2022/clr-angular-forms-number-input.mjs +12 -12
  40. package/fesm2022/clr-angular-forms-number-input.mjs.map +1 -1
  41. package/fesm2022/clr-angular-forms-password.mjs +11 -11
  42. package/fesm2022/clr-angular-forms-password.mjs.map +1 -1
  43. package/fesm2022/clr-angular-forms-radio.mjs +17 -24
  44. package/fesm2022/clr-angular-forms-radio.mjs.map +1 -1
  45. package/fesm2022/clr-angular-forms-range.mjs +10 -10
  46. package/fesm2022/clr-angular-forms-range.mjs.map +1 -1
  47. package/fesm2022/clr-angular-forms-select.mjs +10 -10
  48. package/fesm2022/clr-angular-forms-select.mjs.map +1 -1
  49. package/fesm2022/clr-angular-forms-textarea.mjs +10 -10
  50. package/fesm2022/clr-angular-forms-textarea.mjs.map +1 -1
  51. package/fesm2022/clr-angular-forms.mjs +4 -4
  52. package/fesm2022/clr-angular-forms.mjs.map +1 -1
  53. package/fesm2022/clr-angular-icon.mjs +101 -47
  54. package/fesm2022/clr-angular-icon.mjs.map +1 -1
  55. package/fesm2022/clr-angular-layout-breadcrumbs.mjs +10 -10
  56. package/fesm2022/clr-angular-layout-breadcrumbs.mjs.map +1 -1
  57. package/fesm2022/clr-angular-layout-main-container.mjs +7 -7
  58. package/fesm2022/clr-angular-layout-main-container.mjs.map +1 -1
  59. package/fesm2022/clr-angular-layout-nav.mjs +22 -22
  60. package/fesm2022/clr-angular-layout-nav.mjs.map +1 -1
  61. package/fesm2022/clr-angular-layout-tabs.mjs +35 -35
  62. package/fesm2022/clr-angular-layout-tabs.mjs.map +1 -1
  63. package/fesm2022/clr-angular-layout-vertical-nav.mjs +31 -31
  64. package/fesm2022/clr-angular-layout-vertical-nav.mjs.map +1 -1
  65. package/fesm2022/clr-angular-layout.mjs +4 -4
  66. package/fesm2022/clr-angular-layout.mjs.map +1 -1
  67. package/fesm2022/clr-angular-modal.mjs +29 -27
  68. package/fesm2022/clr-angular-modal.mjs.map +1 -1
  69. package/fesm2022/clr-angular-popover-common.mjs +70 -35
  70. package/fesm2022/clr-angular-popover-common.mjs.map +1 -1
  71. package/fesm2022/clr-angular-popover-dropdown.mjs +63 -26
  72. package/fesm2022/clr-angular-popover-dropdown.mjs.map +1 -1
  73. package/fesm2022/clr-angular-popover-signpost.mjs +27 -25
  74. package/fesm2022/clr-angular-popover-signpost.mjs.map +1 -1
  75. package/fesm2022/clr-angular-popover-tooltip.mjs +19 -19
  76. package/fesm2022/clr-angular-popover-tooltip.mjs.map +1 -1
  77. package/fesm2022/clr-angular-popover.mjs +4 -4
  78. package/fesm2022/clr-angular-popover.mjs.map +1 -1
  79. package/fesm2022/clr-angular-progress-progress-bars.mjs +7 -7
  80. package/fesm2022/clr-angular-progress-progress-bars.mjs.map +1 -1
  81. package/fesm2022/clr-angular-progress-spinner.mjs +7 -7
  82. package/fesm2022/clr-angular-progress-spinner.mjs.map +1 -1
  83. package/fesm2022/clr-angular-stepper.mjs +31 -31
  84. package/fesm2022/clr-angular-stepper.mjs.map +1 -1
  85. package/fesm2022/clr-angular-timeline.mjs +24 -24
  86. package/fesm2022/clr-angular-timeline.mjs.map +1 -1
  87. package/fesm2022/clr-angular-utils-conditional.mjs +16 -16
  88. package/fesm2022/clr-angular-utils-conditional.mjs.map +1 -1
  89. package/fesm2022/clr-angular-utils-loading.mjs +7 -7
  90. package/fesm2022/clr-angular-utils-loading.mjs.map +1 -1
  91. package/fesm2022/clr-angular-utils.mjs +149 -150
  92. package/fesm2022/clr-angular-utils.mjs.map +1 -1
  93. package/fesm2022/clr-angular-wizard.mjs +51 -51
  94. package/fesm2022/clr-angular-wizard.mjs.map +1 -1
  95. package/fesm2022/clr-angular.mjs +9 -4
  96. package/fesm2022/clr-angular.mjs.map +1 -1
  97. package/package.json +9 -5
  98. package/types/clr-angular-card.d.ts +110 -0
  99. package/types/clr-angular-data-datagrid.d.ts +427 -57
  100. package/types/clr-angular-data-tree-view.d.ts +126 -88
  101. package/types/clr-angular-forms-checkbox.d.ts +3 -0
  102. package/types/clr-angular-forms-datepicker.d.ts +1 -1
  103. package/types/clr-angular-forms-file-input.d.ts +1 -1
  104. package/types/clr-angular-forms-radio.d.ts +1 -2
  105. package/types/clr-angular-icon.d.ts +22 -2
  106. package/types/clr-angular-popover-common.d.ts +6 -0
  107. package/types/clr-angular-popover-dropdown.d.ts +33 -4
  108. package/types/clr-angular-utils.d.ts +61 -20
  109. package/types/clr-angular.d.ts +8 -6
  110. package/schematics/vitest.config.d.ts +0 -2
  111. package/schematics/vitest.config.js +0 -17
  112. package/schematics/vitest.config.js.map +0 -1
@@ -1,35 +1,37 @@
1
1
  import * as i0 from '@angular/core';
2
- import { Injectable, Directive, ViewChild, Component, PLATFORM_ID, Inject, DOCUMENT, EventEmitter, ElementRef, booleanAttribute, Input, Output, Optional, ContentChild, ChangeDetectionStrategy, ContentChildren, forwardRef, HostListener, ViewContainerRef, runInInjectionContext, Injector, ChangeDetectorRef, NgZone, Renderer2, inject, EnvironmentInjector, TemplateRef, IterableDiffers, afterNextRender, ViewChildren, InjectionToken, NgModule } from '@angular/core';
2
+ import { signal, Injectable, InjectionToken, Directive, ViewChild, Component, PLATFORM_ID, Inject, DOCUMENT, EventEmitter, ElementRef, booleanAttribute, Input, Output, Optional, inject, ContentChild, ChangeDetectionStrategy, ContentChildren, forwardRef, HostListener, ViewContainerRef, runInInjectionContext, createEnvironmentInjector, ChangeDetectorRef, NgZone, Renderer2, EnvironmentInjector, TemplateRef, IterableDiffers, afterNextRender, RendererStyleFlags2, ViewChildren, SkipSelf, NgModule } from '@angular/core';
3
3
  import * as i2 from '@clr/angular/utils';
4
- import { uniqueIdFactory, Keys, HostWrapper, IfExpandService, ClrLoadingState, ClrExpandableAnimationDirective, LoadingListener, WillyWonka, OompaLoompa, ClrKeyFocus, DomAdapter, ClrIfExpanded, CdkDragModule, CdkTrapFocusModule, ClrLoadingModule, ClrConditionalModule, ClrOutsideClickModule, ClrExpandableAnimationModule, ClrKeyFocusModule } from '@clr/angular/utils';
5
- import * as i2$2 from 'rxjs';
4
+ import { uniqueIdFactory, Keys, HostWrapper, IfExpandService, ClrLoadingState, ClrExpandableAnimationDirective, LoadingListener, WillyWonka, OompaLoompa, ClrKeyFocus, FocusableItem, FOCUS_SERVICE_PROVIDER, BASIC_FOCUSABLE_ITEM_PROVIDER, DomAdapter, ClrIfExpanded, CdkDragModule, CdkTrapFocusModule, ClrLoadingModule, ClrConditionalModule, ClrOutsideClickModule, ClrExpandableAnimationModule, ClrKeyFocusModule } from '@clr/angular/utils';
5
+ import * as i12 from 'rxjs';
6
6
  import { Subject, BehaviorSubject, fromEvent, ReplaySubject, combineLatest, merge, of } from 'rxjs';
7
7
  import { filter, takeUntil, delay, debounceTime, map, switchMap } from 'rxjs/operators';
8
8
  import * as i3 from '@clr/angular/popover/common';
9
- import { ClrPopoverPosition, ClrPopoverType, ClrPopoverHostDirective, mapPopoverKeyToPosition, ClrPopoverModuleNext } from '@clr/angular/popover/common';
9
+ import { ClrPopoverPosition, ClrPopoverType, ClrPopoverHostDirective, mapPopoverKeyToPosition, ClrPopoverContent, ClrPopoverModuleNext } from '@clr/angular/popover/common';
10
10
  import * as i1 from '@clr/angular/modal';
11
- import * as i9 from '@angular/common';
11
+ import * as i10 from '@angular/common';
12
12
  import { isPlatformBrowser, NgForOf, CommonModule } from '@angular/common';
13
- import * as i5 from '@clr/angular/icon';
14
- import { ClarityIcons, ellipsisVerticalIcon, viewColumnsIcon, windowCloseIcon, arrowIcon, timesIcon, twoWayArrowsIcon, stepForward2Icon, angleDoubleIcon, filterGridCircleIcon, filterGridIcon, ClrIcon } from '@clr/angular/icon';
15
- import * as i4 from '@clr/angular/forms/common';
13
+ import * as i4 from '@clr/angular/icon';
14
+ import { ClarityIcons, ellipsisVerticalIcon, ellipsisGridCircleIcon, viewColumnsIcon, windowCloseIcon, arrowIcon, timesIcon, twoWayArrowsIcon, stepForward2Icon, angleDoubleIcon, filterGridCircleIcon, filterGridIcon, pinIcon, unpinIcon, ClrIcon } from '@clr/angular/icon';
15
+ import * as i4$1 from '@clr/angular/forms/common';
16
16
  import { ClrControlLabel } from '@clr/angular/forms/common';
17
- import * as i5$1 from '@clr/angular/forms/number-input';
17
+ import * as i5 from '@clr/angular/forms/number-input';
18
18
  import { ClrNumberInputModule } from '@clr/angular/forms/number-input';
19
- import * as i13 from '@angular/forms';
19
+ import * as i14 from '@angular/forms';
20
20
  import { NG_VALUE_ACCESSOR, FormsModule } from '@angular/forms';
21
- import * as i5$2 from '@clr/angular/forms/input';
21
+ import * as i5$1 from '@clr/angular/forms/input';
22
22
  import { ClrInputModule } from '@clr/angular/forms/input';
23
23
  import { ClrSignpost } from '@clr/angular/popover/signpost';
24
- import * as i12 from '@clr/angular/forms/radio';
24
+ import * as i13 from '@clr/angular/forms/radio';
25
25
  import { ClrRadioModule } from '@clr/angular/forms/radio';
26
- import * as i14 from '@clr/angular/progress/spinner';
26
+ import * as i15 from '@clr/angular/progress/spinner';
27
27
  import { ClrSpinnerModule } from '@clr/angular/progress/spinner';
28
28
  import * as i2$1 from '@angular/cdk/bidi';
29
29
  import { Directionality } from '@angular/cdk/bidi';
30
30
  import { coerceNumberProperty } from '@angular/cdk/coercion';
31
31
  import * as i3$1 from '@angular/cdk/scrolling';
32
- import { FixedSizeVirtualScrollStrategy, VIRTUAL_SCROLL_STRATEGY, ScrollDispatcher, ViewportRuler, CdkVirtualScrollable, CdkVirtualScrollViewport, CDK_VIRTUAL_SCROLL_VIEWPORT, CdkVirtualForOf } from '@angular/cdk/scrolling';
32
+ import { FixedSizeVirtualScrollStrategy, VIRTUAL_SCROLL_STRATEGY, CdkVirtualScrollable, CdkVirtualScrollViewport, ScrollDispatcher, ViewportRuler, CDK_VIRTUAL_SCROLL_VIEWPORT, CdkVirtualForOf } from '@angular/cdk/scrolling';
33
+ import * as i6 from '@clr/angular/popover/dropdown';
34
+ import { DropdownFocusHandler, ClrDropdown, ClrDropdownMenu, ROOT_DROPDOWN_PROVIDER, ClrDropdownItem, ClrDropdownModule } from '@clr/angular/popover/dropdown';
33
35
  import * as i7 from '@clr/angular/forms/checkbox';
34
36
  import { ClrCheckboxModule } from '@clr/angular/forms/checkbox';
35
37
  import { ClrSelectModule } from '@clr/angular/forms/select';
@@ -341,6 +343,23 @@ class DatagridStringFilterImpl {
341
343
  }
342
344
  }
343
345
 
346
+ /*
347
+ * Copyright (c) 2016-2026 Broadcom. All Rights Reserved.
348
+ * The term "Broadcom" refers to Broadcom Inc. and/or its subsidiaries.
349
+ * This software is released under MIT license.
350
+ * The full license information can be found in LICENSE in the root directory of this project.
351
+ */
352
+ var DatagridColumnChanges;
353
+ (function (DatagridColumnChanges) {
354
+ DatagridColumnChanges[DatagridColumnChanges["WIDTH"] = 0] = "WIDTH";
355
+ DatagridColumnChanges[DatagridColumnChanges["HIDDEN"] = 1] = "HIDDEN";
356
+ DatagridColumnChanges[DatagridColumnChanges["INITIALIZE"] = 2] = "INITIALIZE";
357
+ DatagridColumnChanges[DatagridColumnChanges["PINNED"] = 3] = "PINNED";
358
+ })(DatagridColumnChanges || (DatagridColumnChanges = {}));
359
+ const ALL_COLUMN_CHANGES = Object.keys(DatagridColumnChanges)
360
+ .map(key => DatagridColumnChanges[key])
361
+ .filter(key => key === parseInt(key, 10) && key !== DatagridColumnChanges.INITIALIZE); // extracts only integer keys
362
+
344
363
  /*
345
364
  * Copyright (c) 2016-2026 Broadcom. All Rights Reserved.
346
365
  * The term "Broadcom" refers to Broadcom Inc. and/or its subsidiaries.
@@ -367,6 +386,63 @@ var ClrDatagridAriaSortOrder;
367
386
  ClrDatagridAriaSortOrder["DESC"] = "descending";
368
387
  })(ClrDatagridAriaSortOrder || (ClrDatagridAriaSortOrder = {}));
369
388
 
389
+ /*
390
+ * Copyright (c) 2016-2026 Broadcom. All Rights Reserved.
391
+ * The term "Broadcom" refers to Broadcom Inc. and/or its subsidiaries.
392
+ * This software is released under MIT license.
393
+ * The full license information can be found in LICENSE in the root directory of this project.
394
+ */
395
+ /**
396
+ * Lets `clr-dg-column-actions` and the filter of the same column find each other without either
397
+ * importing the other, and without depending on the order they are declared in.
398
+ *
399
+ * It is provided by `ClrDatagridColumn`, so every filter flavour resolves the same instance - a
400
+ * projected `clr-dg-filter` is a content child of the column, and the `clr-dg-string-filter` and
401
+ * `clr-dg-numeric-filter` the column creates for `clrDgField` live in its view.
402
+ */
403
+ class ColumnActionsService {
404
+ constructor() {
405
+ /**
406
+ * Whether the filter keeps its own toggle in the column header. An actions menu turns this off and
407
+ * opens the filter itself, so the header keeps a single control per column - unless
408
+ * `clrDgKeepFilterInHeader` asks to keep the toggle.
409
+ *
410
+ * A signal rather than a plain flag because the menu and the filter are siblings: either can be
411
+ * created first, and the filter has to react whenever the answer changes.
412
+ */
413
+ this.filterInHeader = signal(true, ...(ngDevMode ? [{ debugName: "filterInHeader" }] : /* istanbul ignore next */ []));
414
+ /**
415
+ * Whether the column has an actions menu at all, whatever it does with the filter. While it does,
416
+ * the column drops its own pin toggle, because the menu offers Pin Column instead.
417
+ */
418
+ this.menuPresent = signal(false, ...(ngDevMode ? [{ debugName: "menuPresent" }] : /* istanbul ignore next */ []));
419
+ /** The filter rendered for this column, if it has one. */
420
+ this.filter = signal(null, ...(ngDevMode ? [{ debugName: "filter" }] : /* istanbul ignore next */ []));
421
+ }
422
+ static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.25", ngImport: i0, type: ColumnActionsService, deps: [], target: i0.ɵɵFactoryTarget.Injectable }); }
423
+ static { this.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "21.2.25", ngImport: i0, type: ColumnActionsService }); }
424
+ }
425
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.25", ngImport: i0, type: ColumnActionsService, decorators: [{
426
+ type: Injectable
427
+ }] });
428
+
429
+ /*
430
+ * Copyright (c) 2016-2026 Broadcom. All Rights Reserved.
431
+ * The term "Broadcom" refers to Broadcom Inc. and/or its subsidiaries.
432
+ * This software is released under MIT license.
433
+ * The full license information can be found in LICENSE in the root directory of this project.
434
+ */
435
+ const COLUMN_STATE = new InjectionToken('COLUMN_STATE');
436
+ function columnStateFactory() {
437
+ return new BehaviorSubject({
438
+ changes: [],
439
+ });
440
+ }
441
+ const COLUMN_STATE_PROVIDER = {
442
+ provide: COLUMN_STATE,
443
+ useFactory: columnStateFactory,
444
+ };
445
+
370
446
  /*
371
447
  * Copyright (c) 2016-2026 Broadcom. All Rights Reserved.
372
448
  * The term "Broadcom" refers to Broadcom Inc. and/or its subsidiaries.
@@ -384,6 +460,7 @@ class CustomFilter {
384
460
  */
385
461
  const STRICT_WIDTH_CLASS = 'datagrid-fixed-width';
386
462
  const HIDDEN_COLUMN_CLASS = 'datagrid-hidden-column';
463
+ const PINNED_COLUMN_CLASS = 'datagrid-pinned-column';
387
464
 
388
465
  /*
389
466
  * Copyright (c) 2016-2026 Broadcom. All Rights Reserved.
@@ -418,10 +495,10 @@ class StateDebouncer {
418
495
  this._change.next();
419
496
  }
420
497
  }
421
- static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.1.3", ngImport: i0, type: StateDebouncer, deps: [], target: i0.ɵɵFactoryTarget.Injectable }); }
422
- static { this.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "21.1.3", ngImport: i0, type: StateDebouncer }); }
498
+ static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.25", ngImport: i0, type: StateDebouncer, deps: [], target: i0.ɵɵFactoryTarget.Injectable }); }
499
+ static { this.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "21.2.25", ngImport: i0, type: StateDebouncer }); }
423
500
  }
424
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.1.3", ngImport: i0, type: StateDebouncer, decorators: [{
501
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.25", ngImport: i0, type: StateDebouncer, decorators: [{
425
502
  type: Injectable
426
503
  }] });
427
504
 
@@ -570,10 +647,10 @@ class Page {
570
647
  this.preventEmit = preventEmit;
571
648
  this.size = 0;
572
649
  }
573
- static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.1.3", ngImport: i0, type: Page, deps: [{ token: StateDebouncer }], target: i0.ɵɵFactoryTarget.Injectable }); }
574
- static { this.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "21.1.3", ngImport: i0, type: Page }); }
650
+ static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.25", ngImport: i0, type: Page, deps: [{ token: StateDebouncer }], target: i0.ɵɵFactoryTarget.Injectable }); }
651
+ static { this.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "21.2.25", ngImport: i0, type: Page }); }
575
652
  }
576
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.1.3", ngImport: i0, type: Page, decorators: [{
653
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.25", ngImport: i0, type: Page, decorators: [{
577
654
  type: Injectable
578
655
  }], ctorParameters: () => [{ type: StateDebouncer }] });
579
656
 
@@ -671,10 +748,10 @@ class FiltersProvider {
671
748
  this._change.next(filters);
672
749
  this.stateDebouncer.changeDone();
673
750
  }
674
- static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.1.3", ngImport: i0, type: FiltersProvider, deps: [{ token: Page }, { token: StateDebouncer }], target: i0.ɵɵFactoryTarget.Injectable }); }
675
- static { this.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "21.1.3", ngImport: i0, type: FiltersProvider }); }
751
+ static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.25", ngImport: i0, type: FiltersProvider, deps: [{ token: Page }, { token: StateDebouncer }], target: i0.ɵɵFactoryTarget.Injectable }); }
752
+ static { this.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "21.2.25", ngImport: i0, type: FiltersProvider }); }
676
753
  }
677
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.1.3", ngImport: i0, type: FiltersProvider, decorators: [{
754
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.25", ngImport: i0, type: FiltersProvider, decorators: [{
678
755
  type: Injectable
679
756
  }], ctorParameters: () => [{ type: Page }, { type: StateDebouncer }] });
680
757
  class RegisteredFilter {
@@ -716,10 +793,10 @@ class DatagridFilterRegistrar {
716
793
  delete this.registered;
717
794
  }
718
795
  }
719
- static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.1.3", ngImport: i0, type: DatagridFilterRegistrar, deps: [{ token: FiltersProvider }], target: i0.ɵɵFactoryTarget.Directive }); }
720
- static { this.ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "14.0.0", version: "21.1.3", type: DatagridFilterRegistrar, isStandalone: true, ngImport: i0 }); }
796
+ static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.25", ngImport: i0, type: DatagridFilterRegistrar, deps: [{ token: FiltersProvider }], target: i0.ɵɵFactoryTarget.Directive }); }
797
+ static { this.ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "14.0.0", version: "21.2.25", type: DatagridFilterRegistrar, isStandalone: true, ngImport: i0 }); }
721
798
  }
722
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.1.3", ngImport: i0, type: DatagridFilterRegistrar, decorators: [{
799
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.25", ngImport: i0, type: DatagridFilterRegistrar, decorators: [{
723
800
  type: Directive
724
801
  }], ctorParameters: () => [{ type: FiltersProvider }] });
725
802
 
@@ -737,14 +814,14 @@ class WrappedColumn {
737
814
  ngOnDestroy() {
738
815
  this.columnView.destroy();
739
816
  }
740
- static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.1.3", ngImport: i0, type: WrappedColumn, deps: [], target: i0.ɵɵFactoryTarget.Component }); }
741
- static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "21.1.3", type: WrappedColumn, isStandalone: false, selector: "dg-wrapped-column", viewQueries: [{ propertyName: "templateRef", first: true, predicate: ["columnPortal"], descendants: true }], ngImport: i0, template: `
817
+ static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.25", ngImport: i0, type: WrappedColumn, deps: [], target: i0.ɵɵFactoryTarget.Component }); }
818
+ static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "21.2.25", type: WrappedColumn, isStandalone: false, selector: "dg-wrapped-column", viewQueries: [{ propertyName: "templateRef", first: true, predicate: ["columnPortal"], descendants: true }], ngImport: i0, template: `
742
819
  <ng-template #columnPortal>
743
820
  <ng-content></ng-content>
744
821
  </ng-template>
745
822
  `, isInline: true }); }
746
823
  }
747
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.1.3", ngImport: i0, type: WrappedColumn, decorators: [{
824
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.25", ngImport: i0, type: WrappedColumn, decorators: [{
748
825
  type: Component,
749
826
  args: [{
750
827
  selector: 'dg-wrapped-column',
@@ -835,10 +912,10 @@ class Sort {
835
912
  emitChange() {
836
913
  this._change.next(this);
837
914
  }
838
- static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.1.3", ngImport: i0, type: Sort, deps: [{ token: StateDebouncer }], target: i0.ɵɵFactoryTarget.Injectable }); }
839
- static { this.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "21.1.3", ngImport: i0, type: Sort }); }
915
+ static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.25", ngImport: i0, type: Sort, deps: [{ token: StateDebouncer }], target: i0.ɵɵFactoryTarget.Injectable }); }
916
+ static { this.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "21.2.25", ngImport: i0, type: Sort }); }
840
917
  }
841
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.1.3", ngImport: i0, type: Sort, decorators: [{
918
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.25", ngImport: i0, type: Sort, decorators: [{
842
919
  type: Injectable
843
920
  }], ctorParameters: () => [{ type: StateDebouncer }] });
844
921
 
@@ -848,9 +925,13 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.1.3", ngImpor
848
925
  * This software is released under MIT license.
849
926
  * The full license information can be found in LICENSE in the root directory of this project.
850
927
  */
928
+ const MAX_DETAIL_WIDTH = 100;
929
+ const DEFAULT_DETAIL_WIDTH = 66;
930
+ const MIN_DETAIL_WIDTH = 0;
851
931
  class DetailService {
852
932
  constructor(modalStackService) {
853
933
  this.modalStackService = modalStackService;
934
+ this.detailWidth = DEFAULT_DETAIL_WIDTH;
854
935
  this.preventScroll = false;
855
936
  this.toggleState = false;
856
937
  this._enabled = false;
@@ -907,13 +988,83 @@ class DetailService {
907
988
  isRowOpen(item) {
908
989
  return !!(this.toggleState && this.cache === item);
909
990
  }
910
- static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.1.3", ngImport: i0, type: DetailService, deps: [{ token: i1.ModalStackService }], target: i0.ɵɵFactoryTarget.Injectable }); }
911
- static { this.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "21.1.3", ngImport: i0, type: DetailService }); }
991
+ static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.25", ngImport: i0, type: DetailService, deps: [{ token: i1.ModalStackService }], target: i0.ɵɵFactoryTarget.Injectable }); }
992
+ static { this.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "21.2.25", ngImport: i0, type: DetailService }); }
912
993
  }
913
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.1.3", ngImport: i0, type: DetailService, decorators: [{
994
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.25", ngImport: i0, type: DetailService, decorators: [{
914
995
  type: Injectable
915
996
  }], ctorParameters: () => [{ type: i1.ModalStackService }] });
916
997
 
998
+ /*
999
+ * Copyright (c) 2016-2026 Broadcom. All Rights Reserved.
1000
+ * The term "Broadcom" refers to Broadcom Inc. and/or its subsidiaries.
1001
+ * This software is released under MIT license.
1002
+ * The full license information can be found in LICENSE in the root directory of this project.
1003
+ */
1004
+ class ColumnsService {
1005
+ constructor() {
1006
+ this.columns = [];
1007
+ this.columnsStateChange = new BehaviorSubject(null);
1008
+ this._cache = [];
1009
+ }
1010
+ get columnStates() {
1011
+ return this.columns.map(column => column.value);
1012
+ }
1013
+ get hasHideableColumns() {
1014
+ return this.columnStates.filter(state => state.hideable).length > 0;
1015
+ }
1016
+ get visibleColumns() {
1017
+ return this.columnStates.filter(state => !state.hidden);
1018
+ }
1019
+ get hasPinnedColumns() {
1020
+ return this.columnStates.some(state => state.pinned);
1021
+ }
1022
+ /**
1023
+ * Tells whether the column at the given index is pinned (static). Columns and cells are
1024
+ * matched by their declaration index, so this is what the header, the rows and a column aligned
1025
+ * row detail use to decide which views belong in the static container.
1026
+ */
1027
+ isPinned(columnIndex) {
1028
+ return !!this.columns[columnIndex]?.value.pinned;
1029
+ }
1030
+ cache() {
1031
+ this._cache = this.columns.map(subject => {
1032
+ const value = { ...subject.value };
1033
+ delete value.changes;
1034
+ return value;
1035
+ });
1036
+ }
1037
+ hasCache() {
1038
+ return !!this._cache.length;
1039
+ }
1040
+ resetToLastCache() {
1041
+ this._cache.forEach((state, index) => {
1042
+ // Just emit the exact value from the cache
1043
+ const cachedState = { ...state, changes: ALL_COLUMN_CHANGES };
1044
+ this.columns[index].next(cachedState);
1045
+ this.columnsStateChange.next(cachedState);
1046
+ });
1047
+ this._cache = [];
1048
+ }
1049
+ // Helper method to emit a change to a column only when there is an actual diff to process for that column
1050
+ emitStateChangeAt(columnIndex, diff) {
1051
+ if (!this.columns[columnIndex]) {
1052
+ return;
1053
+ }
1054
+ this.emitStateChange(this.columns[columnIndex], diff);
1055
+ }
1056
+ emitStateChange(column, diff) {
1057
+ const changedState = { ...column.value, ...diff };
1058
+ column.next(changedState);
1059
+ this.columnsStateChange.next(changedState);
1060
+ }
1061
+ static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.25", ngImport: i0, type: ColumnsService, deps: [], target: i0.ɵɵFactoryTarget.Injectable }); }
1062
+ static { this.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "21.2.25", ngImport: i0, type: ColumnsService }); }
1063
+ }
1064
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.25", ngImport: i0, type: ColumnsService, decorators: [{
1065
+ type: Injectable
1066
+ }] });
1067
+
917
1068
  /*
918
1069
  * Copyright (c) 2016-2026 Broadcom. All Rights Reserved.
919
1070
  * The term "Broadcom" refers to Broadcom Inc. and/or its subsidiaries.
@@ -956,10 +1107,10 @@ class DatagridRenderOrganizer {
956
1107
  this.alreadySized = true;
957
1108
  this._renderStep.next(DatagridRenderStep.CALCULATE_MODE_OFF);
958
1109
  }
959
- static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.1.3", ngImport: i0, type: DatagridRenderOrganizer, deps: [], target: i0.ɵɵFactoryTarget.Injectable }); }
960
- static { this.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "21.1.3", ngImport: i0, type: DatagridRenderOrganizer }); }
1110
+ static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.25", ngImport: i0, type: DatagridRenderOrganizer, deps: [], target: i0.ɵɵFactoryTarget.Injectable }); }
1111
+ static { this.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "21.2.25", ngImport: i0, type: DatagridRenderOrganizer }); }
961
1112
  }
962
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.1.3", ngImport: i0, type: DatagridRenderOrganizer, decorators: [{
1113
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.25", ngImport: i0, type: DatagridRenderOrganizer, decorators: [{
963
1114
  type: Injectable
964
1115
  }] });
965
1116
 
@@ -1010,10 +1161,10 @@ class ColumnResizerService {
1010
1161
  this.isWithinMaxResizeRange = true;
1011
1162
  }
1012
1163
  }
1013
- static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.1.3", ngImport: i0, type: ColumnResizerService, deps: [{ token: i0.ElementRef }, { token: i2.DomAdapter }, { token: DatagridRenderOrganizer }], target: i0.ɵɵFactoryTarget.Injectable }); }
1014
- static { this.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "21.1.3", ngImport: i0, type: ColumnResizerService }); }
1164
+ static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.25", ngImport: i0, type: ColumnResizerService, deps: [{ token: i0.ElementRef }, { token: i2.DomAdapter }, { token: DatagridRenderOrganizer }], target: i0.ɵɵFactoryTarget.Injectable }); }
1165
+ static { this.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "21.2.25", ngImport: i0, type: ColumnResizerService }); }
1015
1166
  }
1016
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.1.3", ngImport: i0, type: ColumnResizerService, decorators: [{
1167
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.25", ngImport: i0, type: ColumnResizerService, decorators: [{
1017
1168
  type: Injectable
1018
1169
  }], ctorParameters: () => [{ type: i0.ElementRef }, { type: i2.DomAdapter }, { type: DatagridRenderOrganizer }] });
1019
1170
 
@@ -1049,10 +1200,10 @@ class TableSizeService {
1049
1200
  }
1050
1201
  return `${this.tableRef.clientHeight}px`;
1051
1202
  }
1052
- static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.1.3", ngImport: i0, type: TableSizeService, deps: [{ token: PLATFORM_ID }], target: i0.ɵɵFactoryTarget.Injectable }); }
1053
- static { this.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "21.1.3", ngImport: i0, type: TableSizeService }); }
1203
+ static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.25", ngImport: i0, type: TableSizeService, deps: [{ token: PLATFORM_ID }], target: i0.ɵɵFactoryTarget.Injectable }); }
1204
+ static { this.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "21.2.25", ngImport: i0, type: TableSizeService }); }
1054
1205
  }
1055
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.1.3", ngImport: i0, type: TableSizeService, decorators: [{
1206
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.25", ngImport: i0, type: TableSizeService, decorators: [{
1056
1207
  type: Injectable
1057
1208
  }], ctorParameters: () => [{ type: undefined, decorators: [{
1058
1209
  type: Inject,
@@ -1163,8 +1314,8 @@ class ClrDatagridColumnSeparator {
1163
1314
  isArrowRightKeyEvent(event) {
1164
1315
  return event.key === Keys.ArrowRight;
1165
1316
  }
1166
- static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.1.3", ngImport: i0, type: ClrDatagridColumnSeparator, deps: [{ token: ColumnResizerService }, { token: i0.Renderer2 }, { token: i0.NgZone }, { token: TableSizeService }, { token: i2.ClrCommonStringsService }, { token: DOCUMENT }], target: i0.ɵɵFactoryTarget.Component }); }
1167
- static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "21.1.3", type: ClrDatagridColumnSeparator, isStandalone: false, selector: "clr-dg-column-separator", host: { properties: { "class.datagrid-column-separator": "true" } }, viewQueries: [{ propertyName: "resizeTrackerRef", first: true, predicate: ["resizeTracker"], descendants: true }, { propertyName: "columnHandleRef", first: true, predicate: ["columnHandle"], descendants: true }], ngImport: i0, template: `
1317
+ static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.25", ngImport: i0, type: ClrDatagridColumnSeparator, deps: [{ token: ColumnResizerService }, { token: i0.Renderer2 }, { token: i0.NgZone }, { token: TableSizeService }, { token: i2.ClrCommonStringsService }, { token: DOCUMENT }], target: i0.ɵɵFactoryTarget.Component }); }
1318
+ static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "21.2.25", type: ClrDatagridColumnSeparator, isStandalone: false, selector: "clr-dg-column-separator", host: { properties: { "class.datagrid-column-separator": "true" } }, viewQueries: [{ propertyName: "resizeTrackerRef", first: true, predicate: ["resizeTracker"], descendants: true }, { propertyName: "columnHandleRef", first: true, predicate: ["columnHandle"], descendants: true }], ngImport: i0, template: `
1168
1319
  <button
1169
1320
  type="button"
1170
1321
  class="datagrid-column-handle"
@@ -1183,7 +1334,7 @@ class ClrDatagridColumnSeparator {
1183
1334
  <div class="datagrid-column-resize-tracker" #resizeTracker></div>
1184
1335
  `, isInline: true, dependencies: [{ kind: "directive", type: i2.CdkDragModule_CdkDrag, selector: "[cdkDrag]" }] }); }
1185
1336
  }
1186
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.1.3", ngImport: i0, type: ClrDatagridColumnSeparator, decorators: [{
1337
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.25", ngImport: i0, type: ClrDatagridColumnSeparator, decorators: [{
1187
1338
  type: Component,
1188
1339
  args: [{
1189
1340
  selector: 'clr-dg-column-separator',
@@ -1904,10 +2055,10 @@ class KeyNavigationGridController {
1904
2055
  }
1905
2056
  elementToFocus.focus(options);
1906
2057
  }
1907
- static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.1.3", ngImport: i0, type: KeyNavigationGridController, deps: [{ token: i0.NgZone }], target: i0.ɵɵFactoryTarget.Injectable }); }
1908
- static { this.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "21.1.3", ngImport: i0, type: KeyNavigationGridController }); }
2058
+ static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.25", ngImport: i0, type: KeyNavigationGridController, deps: [{ token: i0.NgZone }], target: i0.ɵɵFactoryTarget.Injectable }); }
2059
+ static { this.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "21.2.25", ngImport: i0, type: KeyNavigationGridController }); }
1909
2060
  }
1910
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.1.3", ngImport: i0, type: KeyNavigationGridController, decorators: [{
2061
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.25", ngImport: i0, type: KeyNavigationGridController, decorators: [{
1911
2062
  type: Injectable
1912
2063
  }], ctorParameters: () => [{ type: i0.NgZone }] });
1913
2064
 
@@ -1923,11 +2074,12 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.1.3", ngImpor
1923
2074
  * since it can be anything (not just a text input).
1924
2075
  */
1925
2076
  class ClrDatagridFilter extends DatagridFilterRegistrar {
1926
- constructor(_filters, commonStrings, popoverService, keyNavigation) {
2077
+ constructor(_filters, commonStrings, popoverService, keyNavigation, columnActions) {
1927
2078
  super(_filters);
1928
2079
  this.commonStrings = commonStrings;
1929
2080
  this.popoverService = popoverService;
1930
2081
  this.keyNavigation = keyNavigation;
2082
+ this.columnActions = columnActions;
1931
2083
  this.openChange = new EventEmitter(false);
1932
2084
  this.ariaExpanded = false;
1933
2085
  this.popoverId = uniqueIdFactory();
@@ -1938,7 +2090,14 @@ class ClrDatagridFilter extends DatagridFilterRegistrar {
1938
2090
  this.subs.push(popoverService.openChange.subscribe(change => {
1939
2091
  this.ariaExpanded = change;
1940
2092
  this.openChange.emit(change);
2093
+ // Set here rather than in the open setter, so it applies however the filter is opened - its
2094
+ // own toggle, clrDgFilterOpen, or the column actions menu.
2095
+ if (keyNavigation) {
2096
+ keyNavigation.skipItemFocus = change;
2097
+ }
1941
2098
  }));
2099
+ // Optional so the filter keeps working outside a column, e.g. in isolated tests.
2100
+ columnActions?.filter.set(this);
1942
2101
  }
1943
2102
  get open() {
1944
2103
  return this.popoverService.open;
@@ -1947,9 +2106,6 @@ class ClrDatagridFilter extends DatagridFilterRegistrar {
1947
2106
  if (this.popoverService.open !== open) {
1948
2107
  this.popoverService.open = open;
1949
2108
  this.openChange.emit(open);
1950
- if (this.keyNavigation) {
1951
- this.keyNavigation.skipItemFocus = open;
1952
- }
1953
2109
  }
1954
2110
  }
1955
2111
  set customFilter(filter) {
@@ -1964,26 +2120,36 @@ class ClrDatagridFilter extends DatagridFilterRegistrar {
1964
2120
  ngOnDestroy() {
1965
2121
  super.ngOnDestroy();
1966
2122
  this.subs.forEach(sub => sub.unsubscribe());
2123
+ if (this.columnActions?.filter() === this) {
2124
+ this.columnActions.filter.set(null);
2125
+ }
2126
+ }
2127
+ static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.25", ngImport: i0, type: ClrDatagridFilter, deps: [{ token: FiltersProvider }, { token: i2.ClrCommonStringsService }, { token: i3.ClrPopoverService }, { token: KeyNavigationGridController, optional: true }, { token: ColumnActionsService, optional: true }], target: i0.ɵɵFactoryTarget.Component }); }
2128
+ static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.2.25", type: ClrDatagridFilter, isStandalone: false, selector: "clr-dg-filter", inputs: { open: ["clrDgFilterOpen", "open", booleanAttribute], customFilter: ["clrDgFilter", "customFilter"] }, outputs: { openChange: "clrDgFilterOpenChange" }, providers: [{ provide: CustomFilter, useExisting: ClrDatagridFilter }], viewQueries: [{ propertyName: "anchor", first: true, predicate: ["anchor"], descendants: true, read: ElementRef }], usesInheritance: true, ngImport: i0, template: `
2129
+ <!--
2130
+ The toggle stands down when the column has a clr-dg-column-actions menu, which then owns
2131
+ opening this filter. Nothing else here changes: the popover is still driven through the
2132
+ column's ClrPopoverService, the menu just points its origin at its own trigger instead.
2133
+ -->
2134
+ @if (columnActions?.filterInHeader() ?? true) {
2135
+ <button
2136
+ class="datagrid-filter-toggle"
2137
+ type="button"
2138
+ #anchor
2139
+ [attr.aria-expanded]="ariaExpanded"
2140
+ [attr.aria-controls]="popoverId"
2141
+ clrPopoverOrigin
2142
+ clrPopoverOpenCloseButton
2143
+ [class.datagrid-filter-open]="open"
2144
+ [class.datagrid-filtered]="active"
2145
+ >
2146
+ <cds-icon
2147
+ [status]="active ? 'info' : null"
2148
+ [shape]="active ? 'filter-grid-circle' : 'filter-grid'"
2149
+ solid
2150
+ ></cds-icon>
2151
+ </button>
1967
2152
  }
1968
- static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.1.3", ngImport: i0, type: ClrDatagridFilter, deps: [{ token: FiltersProvider }, { token: i2.ClrCommonStringsService }, { token: i3.ClrPopoverService }, { token: KeyNavigationGridController, optional: true }], target: i0.ɵɵFactoryTarget.Component }); }
1969
- static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "16.1.0", version: "21.1.3", type: ClrDatagridFilter, isStandalone: false, selector: "clr-dg-filter", inputs: { open: ["clrDgFilterOpen", "open", booleanAttribute], customFilter: ["clrDgFilter", "customFilter"] }, outputs: { openChange: "clrDgFilterOpenChange" }, providers: [{ provide: CustomFilter, useExisting: ClrDatagridFilter }], viewQueries: [{ propertyName: "anchor", first: true, predicate: ["anchor"], descendants: true, read: ElementRef }], usesInheritance: true, ngImport: i0, template: `
1970
- <button
1971
- class="datagrid-filter-toggle"
1972
- type="button"
1973
- #anchor
1974
- [attr.aria-expanded]="ariaExpanded"
1975
- [attr.aria-controls]="popoverId"
1976
- clrPopoverOrigin
1977
- clrPopoverOpenCloseButton
1978
- [class.datagrid-filter-open]="open"
1979
- [class.datagrid-filtered]="active"
1980
- >
1981
- <cds-icon
1982
- [status]="active ? 'info' : null"
1983
- [shape]="active ? 'filter-grid-circle' : 'filter-grid'"
1984
- solid
1985
- ></cds-icon>
1986
- </button>
1987
2153
 
1988
2154
  <div
1989
2155
  class="datagrid-filter"
@@ -2001,32 +2167,39 @@ class ClrDatagridFilter extends DatagridFilterRegistrar {
2001
2167
 
2002
2168
  <ng-content></ng-content>
2003
2169
  </div>
2004
- `, isInline: true, dependencies: [{ kind: "directive", type: i2.CdkTrapFocusModule_CdkTrapFocus, selector: "[cdkTrapFocus]" }, { kind: "component", type: i5.ClrIcon, selector: "clr-icon, cds-icon", inputs: ["shape", "size", "direction", "flip", "solid", "status", "inverse", "badge"] }, { kind: "directive", type: i3.ClrPopoverOrigin, selector: "[clrPopoverOrigin]" }, { kind: "directive", type: i3.ClrPopoverCloseButton, selector: "[clrPopoverCloseButton]", outputs: ["clrPopoverOnCloseChange"] }, { kind: "directive", type: i3.ClrPopoverOpenCloseButton, selector: "[clrPopoverOpenCloseButton]", outputs: ["clrPopoverOpenCloseChange"] }, { kind: "directive", type: i3.ClrPopoverContent, selector: "[clrPopoverContent]", inputs: ["clrPopoverContent", "clrPopoverContentAt", "clrPopoverContentAvailablePositions", "clrPopoverContentType", "clrPopoverContentOutsideClickToClose", "clrPopoverContentScrollToClose", "clrPopoverContentOrigin"] }] }); }
2170
+ `, isInline: true, dependencies: [{ kind: "directive", type: i2.CdkTrapFocusModule_CdkTrapFocus, selector: "[cdkTrapFocus]" }, { kind: "component", type: i4.ClrIcon, selector: "clr-icon, cds-icon", inputs: ["shape", "size", "direction", "flip", "solid", "status", "inverse", "badge", "innerOffset"] }, { kind: "directive", type: i3.ClrPopoverOrigin, selector: "[clrPopoverOrigin]" }, { kind: "directive", type: i3.ClrPopoverCloseButton, selector: "[clrPopoverCloseButton]", outputs: ["clrPopoverOnCloseChange"] }, { kind: "directive", type: i3.ClrPopoverOpenCloseButton, selector: "[clrPopoverOpenCloseButton]", outputs: ["clrPopoverOpenCloseChange"] }, { kind: "directive", type: i3.ClrPopoverContent, selector: "[clrPopoverContent]", inputs: ["clrPopoverContent", "clrPopoverContentAt", "clrPopoverContentAvailablePositions", "clrPopoverContentType", "clrPopoverContentOutsideClickToClose", "clrPopoverContentScrollToClose", "clrPopoverContentOrigin"] }] }); }
2005
2171
  }
2006
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.1.3", ngImport: i0, type: ClrDatagridFilter, decorators: [{
2172
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.25", ngImport: i0, type: ClrDatagridFilter, decorators: [{
2007
2173
  type: Component,
2008
2174
  args: [{
2009
2175
  selector: 'clr-dg-filter',
2010
2176
  // We register this component as a CustomFilter, for the parent column to detect it.
2011
2177
  providers: [{ provide: CustomFilter, useExisting: ClrDatagridFilter }],
2012
2178
  template: `
2013
- <button
2014
- class="datagrid-filter-toggle"
2015
- type="button"
2016
- #anchor
2017
- [attr.aria-expanded]="ariaExpanded"
2018
- [attr.aria-controls]="popoverId"
2019
- clrPopoverOrigin
2020
- clrPopoverOpenCloseButton
2021
- [class.datagrid-filter-open]="open"
2022
- [class.datagrid-filtered]="active"
2023
- >
2024
- <cds-icon
2025
- [status]="active ? 'info' : null"
2026
- [shape]="active ? 'filter-grid-circle' : 'filter-grid'"
2027
- solid
2028
- ></cds-icon>
2029
- </button>
2179
+ <!--
2180
+ The toggle stands down when the column has a clr-dg-column-actions menu, which then owns
2181
+ opening this filter. Nothing else here changes: the popover is still driven through the
2182
+ column's ClrPopoverService, the menu just points its origin at its own trigger instead.
2183
+ -->
2184
+ @if (columnActions?.filterInHeader() ?? true) {
2185
+ <button
2186
+ class="datagrid-filter-toggle"
2187
+ type="button"
2188
+ #anchor
2189
+ [attr.aria-expanded]="ariaExpanded"
2190
+ [attr.aria-controls]="popoverId"
2191
+ clrPopoverOrigin
2192
+ clrPopoverOpenCloseButton
2193
+ [class.datagrid-filter-open]="open"
2194
+ [class.datagrid-filtered]="active"
2195
+ >
2196
+ <cds-icon
2197
+ [status]="active ? 'info' : null"
2198
+ [shape]="active ? 'filter-grid-circle' : 'filter-grid'"
2199
+ solid
2200
+ ></cds-icon>
2201
+ </button>
2202
+ }
2030
2203
 
2031
2204
  <div
2032
2205
  class="datagrid-filter"
@@ -2049,6 +2222,8 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.1.3", ngImpor
2049
2222
  }]
2050
2223
  }], ctorParameters: () => [{ type: FiltersProvider }, { type: i2.ClrCommonStringsService }, { type: i3.ClrPopoverService }, { type: KeyNavigationGridController, decorators: [{
2051
2224
  type: Optional
2225
+ }] }, { type: ColumnActionsService, decorators: [{
2226
+ type: Optional
2052
2227
  }] }], propDecorators: { openChange: [{
2053
2228
  type: Output,
2054
2229
  args: ['clrDgFilterOpenChange']
@@ -2201,8 +2376,8 @@ class DatagridNumericFilter extends DatagridFilterRegistrar {
2201
2376
  sub.unsubscribe();
2202
2377
  });
2203
2378
  }
2204
- static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.1.3", ngImport: i0, type: DatagridNumericFilter, deps: [{ token: FiltersProvider }, { token: i2.DomAdapter }, { token: i2.ClrCommonStringsService }, { token: i3.ClrPopoverService }, { token: i0.NgZone }], target: i0.ɵɵFactoryTarget.Component }); }
2205
- static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "21.1.3", type: DatagridNumericFilter, isStandalone: false, selector: "clr-dg-numeric-filter", inputs: { minPlaceholder: ["clrFilterMinPlaceholder", "minPlaceholder"], maxPlaceholder: ["clrFilterMaxPlaceholder", "maxPlaceholder"], fromLabel: ["clrFilterFromLabel", "fromLabel"], toLabel: ["clrFilterToLabel", "toLabel"], value: ["clrFilterValue", "value"], customNumericFilter: ["clrDgNumericFilter", "customNumericFilter"] }, outputs: { filterValueChange: "clrFilterValueChange" }, providers: [{ provide: CustomFilter, useExisting: DatagridNumericFilter }], viewQueries: [{ propertyName: "input", first: true, predicate: ["input_low"], descendants: true }, { propertyName: "filterContainer", first: true, predicate: ClrDatagridFilter, descendants: true }], usesInheritance: true, ngImport: i0, template: `
2379
+ static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.25", ngImport: i0, type: DatagridNumericFilter, deps: [{ token: FiltersProvider }, { token: i2.DomAdapter }, { token: i2.ClrCommonStringsService }, { token: i3.ClrPopoverService }, { token: i0.NgZone }], target: i0.ɵɵFactoryTarget.Component }); }
2380
+ static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "21.2.25", type: DatagridNumericFilter, isStandalone: false, selector: "clr-dg-numeric-filter", inputs: { minPlaceholder: ["clrFilterMinPlaceholder", "minPlaceholder"], maxPlaceholder: ["clrFilterMaxPlaceholder", "maxPlaceholder"], fromLabel: ["clrFilterFromLabel", "fromLabel"], toLabel: ["clrFilterToLabel", "toLabel"], value: ["clrFilterValue", "value"], customNumericFilter: ["clrDgNumericFilter", "customNumericFilter"] }, outputs: { filterValueChange: "clrFilterValueChange" }, providers: [{ provide: CustomFilter, useExisting: DatagridNumericFilter }], viewQueries: [{ propertyName: "input", first: true, predicate: ["input_low"], descendants: true }, { propertyName: "filterContainer", first: true, predicate: ClrDatagridFilter, descendants: true }], usesInheritance: true, ngImport: i0, template: `
2206
2381
  <clr-dg-filter [clrDgFilter]="registered" [(clrDgFilterOpen)]="open">
2207
2382
  <div class="datagrid-numeric-filter-form">
2208
2383
  <clr-number-input-container>
@@ -2235,9 +2410,9 @@ class DatagridNumericFilter extends DatagridFilterRegistrar {
2235
2410
  </clr-number-input-container>
2236
2411
  </div>
2237
2412
  </clr-dg-filter>
2238
- `, isInline: true, dependencies: [{ kind: "directive", type: i4.ClrControlLabel, selector: "label", inputs: ["id", "for"] }, { kind: "directive", type: i5$1.ClrNumberInput, selector: "input[type=\"number\"][clrNumberInput]" }, { kind: "component", type: i5$1.ClrNumberInputContainer, selector: "clr-number-input-container" }, { kind: "directive", type: i13.DefaultValueAccessor, selector: "input:not([type=checkbox])[formControlName],textarea[formControlName],input:not([type=checkbox])[formControl],textarea[formControl],input:not([type=checkbox])[ngModel],textarea[ngModel],[ngDefaultControl]" }, { kind: "directive", type: i13.NumberValueAccessor, selector: "input[type=number][formControlName],input[type=number][formControl],input[type=number][ngModel]" }, { kind: "directive", type: i13.NgControlStatus, selector: "[formControlName],[ngModel],[formControl]" }, { kind: "directive", type: i13.NgModel, selector: "[ngModel]:not([formControlName]):not([formControl])", inputs: ["name", "disabled", "ngModel", "ngModelOptions"], outputs: ["ngModelChange"], exportAs: ["ngModel"] }, { kind: "component", type: ClrDatagridFilter, selector: "clr-dg-filter", inputs: ["clrDgFilterOpen", "clrDgFilter"], outputs: ["clrDgFilterOpenChange"] }] }); }
2413
+ `, isInline: true, dependencies: [{ kind: "directive", type: i4$1.ClrControlLabel, selector: "label", inputs: ["id", "for"] }, { kind: "directive", type: i5.ClrNumberInput, selector: "input[type=\"number\"][clrNumberInput]" }, { kind: "component", type: i5.ClrNumberInputContainer, selector: "clr-number-input-container" }, { kind: "directive", type: i14.DefaultValueAccessor, selector: "input:not([type=checkbox])[formControlName],textarea[formControlName],input:not([type=checkbox])[formControl],textarea[formControl],input:not([type=checkbox])[ngModel],textarea[ngModel],[ngDefaultControl]" }, { kind: "directive", type: i14.NumberValueAccessor, selector: "input[type=number][formControlName],input[type=number][formControl],input[type=number][ngModel]" }, { kind: "directive", type: i14.NgControlStatus, selector: "[formControlName],[ngModel],[formControl]" }, { kind: "directive", type: i14.NgModel, selector: "[ngModel]:not([formControlName]):not([formControl])", inputs: ["name", "disabled", "ngModel", "ngModelOptions"], outputs: ["ngModelChange"], exportAs: ["ngModel"] }, { kind: "component", type: ClrDatagridFilter, selector: "clr-dg-filter", inputs: ["clrDgFilterOpen", "clrDgFilter"], outputs: ["clrDgFilterOpenChange"] }] }); }
2239
2414
  }
2240
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.1.3", ngImport: i0, type: DatagridNumericFilter, decorators: [{
2415
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.25", ngImport: i0, type: DatagridNumericFilter, decorators: [{
2241
2416
  type: Component,
2242
2417
  args: [{
2243
2418
  selector: 'clr-dg-numeric-filter',
@@ -2411,8 +2586,8 @@ class DatagridStringFilter extends DatagridFilterRegistrar {
2411
2586
  COLUMN: columnTitleElement?.textContent.trim() || '',
2412
2587
  });
2413
2588
  }
2414
- static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.1.3", ngImport: i0, type: DatagridStringFilter, deps: [{ token: FiltersProvider }, { token: i2.DomAdapter }, { token: i2.ClrCommonStringsService }, { token: i3.ClrPopoverService }, { token: i0.ElementRef }, { token: i0.ChangeDetectorRef }, { token: i0.NgZone }], target: i0.ɵɵFactoryTarget.Component }); }
2415
- static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "21.1.3", type: DatagridStringFilter, isStandalone: false, selector: "clr-dg-string-filter", inputs: { placeholder: ["clrFilterPlaceholder", "placeholder"], label: ["clrFilterLabel", "label"], customStringFilter: ["clrDgStringFilter", "customStringFilter"], value: ["clrFilterValue", "value"] }, outputs: { filterValueChange: "clrFilterValueChange" }, providers: [{ provide: CustomFilter, useExisting: DatagridStringFilter }], viewQueries: [{ propertyName: "input", first: true, predicate: ["input"], descendants: true }, { propertyName: "filterContainer", first: true, predicate: ClrDatagridFilter, descendants: true }], usesInheritance: true, usesOnChanges: true, ngImport: i0, template: `
2589
+ static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.25", ngImport: i0, type: DatagridStringFilter, deps: [{ token: FiltersProvider }, { token: i2.DomAdapter }, { token: i2.ClrCommonStringsService }, { token: i3.ClrPopoverService }, { token: i0.ElementRef }, { token: i0.ChangeDetectorRef }, { token: i0.NgZone }], target: i0.ɵɵFactoryTarget.Component }); }
2590
+ static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "21.2.25", type: DatagridStringFilter, isStandalone: false, selector: "clr-dg-string-filter", inputs: { placeholder: ["clrFilterPlaceholder", "placeholder"], label: ["clrFilterLabel", "label"], customStringFilter: ["clrDgStringFilter", "customStringFilter"], value: ["clrFilterValue", "value"] }, outputs: { filterValueChange: "clrFilterValueChange" }, providers: [{ provide: CustomFilter, useExisting: DatagridStringFilter }], viewQueries: [{ propertyName: "input", first: true, predicate: ["input"], descendants: true }, { propertyName: "filterContainer", first: true, predicate: ClrDatagridFilter, descendants: true }], usesInheritance: true, usesOnChanges: true, ngImport: i0, template: `
2416
2591
  <clr-dg-filter [clrDgFilter]="registered" [(clrDgFilterOpen)]="open">
2417
2592
  <clr-input-container>
2418
2593
  <label>{{ labelValue }}</label>
@@ -2428,9 +2603,9 @@ class DatagridStringFilter extends DatagridFilterRegistrar {
2428
2603
  />
2429
2604
  </clr-input-container>
2430
2605
  </clr-dg-filter>
2431
- `, isInline: true, dependencies: [{ kind: "directive", type: i4.ClrControlLabel, selector: "label", inputs: ["id", "for"] }, { kind: "directive", type: i5$2.ClrInput, selector: "[clrInput]" }, { kind: "component", type: i5$2.ClrInputContainer, selector: "clr-input-container" }, { kind: "directive", type: i13.DefaultValueAccessor, selector: "input:not([type=checkbox])[formControlName],textarea[formControlName],input:not([type=checkbox])[formControl],textarea[formControl],input:not([type=checkbox])[ngModel],textarea[ngModel],[ngDefaultControl]" }, { kind: "directive", type: i13.NgControlStatus, selector: "[formControlName],[ngModel],[formControl]" }, { kind: "directive", type: i13.NgModel, selector: "[ngModel]:not([formControlName]):not([formControl])", inputs: ["name", "disabled", "ngModel", "ngModelOptions"], outputs: ["ngModelChange"], exportAs: ["ngModel"] }, { kind: "component", type: ClrDatagridFilter, selector: "clr-dg-filter", inputs: ["clrDgFilterOpen", "clrDgFilter"], outputs: ["clrDgFilterOpenChange"] }] }); }
2606
+ `, isInline: true, dependencies: [{ kind: "directive", type: i4$1.ClrControlLabel, selector: "label", inputs: ["id", "for"] }, { kind: "directive", type: i5$1.ClrInput, selector: "[clrInput]" }, { kind: "component", type: i5$1.ClrInputContainer, selector: "clr-input-container" }, { kind: "directive", type: i14.DefaultValueAccessor, selector: "input:not([type=checkbox])[formControlName],textarea[formControlName],input:not([type=checkbox])[formControl],textarea[formControl],input:not([type=checkbox])[ngModel],textarea[ngModel],[ngDefaultControl]" }, { kind: "directive", type: i14.NgControlStatus, selector: "[formControlName],[ngModel],[formControl]" }, { kind: "directive", type: i14.NgModel, selector: "[ngModel]:not([formControlName]):not([formControl])", inputs: ["name", "disabled", "ngModel", "ngModelOptions"], outputs: ["ngModelChange"], exportAs: ["ngModel"] }, { kind: "component", type: ClrDatagridFilter, selector: "clr-dg-filter", inputs: ["clrDgFilterOpen", "clrDgFilter"], outputs: ["clrDgFilterOpenChange"] }] }); }
2432
2607
  }
2433
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.1.3", ngImport: i0, type: DatagridStringFilter, decorators: [{
2608
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.25", ngImport: i0, type: DatagridStringFilter, decorators: [{
2434
2609
  type: Component,
2435
2610
  args: [{
2436
2611
  selector: 'clr-dg-string-filter',
@@ -2484,7 +2659,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.1.3", ngImpor
2484
2659
  * The full license information can be found in LICENSE in the root directory of this project.
2485
2660
  */
2486
2661
  class ClrDatagridColumn extends DatagridFilterRegistrar {
2487
- constructor(el, _sort, filters, vcr, detailService, changeDetectorRef, commonStrings) {
2662
+ constructor(el, _sort, filters, vcr, detailService, changeDetectorRef, commonStrings, columnsService, columnState) {
2488
2663
  super(filters);
2489
2664
  this.el = el;
2490
2665
  this._sort = _sort;
@@ -2492,13 +2667,25 @@ class ClrDatagridColumn extends DatagridFilterRegistrar {
2492
2667
  this.detailService = detailService;
2493
2668
  this.changeDetectorRef = changeDetectorRef;
2494
2669
  this.commonStrings = commonStrings;
2670
+ this.columnsService = columnsService;
2671
+ this.columnState = columnState;
2495
2672
  this.disableUnsort = false;
2673
+ /**
2674
+ * Lets the user pin and unpin the column from within the datagrid. It only offers the control - the
2675
+ * pinned state itself stays on `clrDgPinned`.
2676
+ * The control is a pin toggle in the column header, or Pin Column in the column's
2677
+ * `clr-dg-column-actions` when it has one - never both, so the header keeps one control per action.
2678
+ */
2679
+ this.pinnable = false;
2496
2680
  this.sortOrderChange = new EventEmitter();
2681
+ this.pinnedChange = new EventEmitter();
2497
2682
  this.filterValueChange = new EventEmitter();
2498
2683
  /**
2499
2684
  * A custom filter for this column that can be provided in the projected content
2500
2685
  */
2501
2686
  this.customFilter = false;
2687
+ // Provided by this column itself, and shared with its actions menu and filter.
2688
+ this.columnActions = inject(ColumnActionsService);
2502
2689
  /*
2503
2690
  * What type is this column? This defaults to STRING, but can also be
2504
2691
  * set to NUMBER. Unsupported types default to STRING. Users can set it
@@ -2514,12 +2701,21 @@ class ClrDatagridColumn extends DatagridFilterRegistrar {
2514
2701
  */
2515
2702
  this.subscriptions = [];
2516
2703
  this._showSeparator = true;
2704
+ this._pinned = false;
2517
2705
  this.subscriptions.push(this.listenForSortingChanges());
2518
2706
  this.subscriptions.push(this.listenForDetailPaneChanges());
2519
2707
  }
2520
2708
  get isHidden() {
2521
2709
  return this.el.nativeElement.classList.contains(HIDDEN_COLUMN_CLASS);
2522
2710
  }
2711
+ /**
2712
+ * Whether the column is currently rendered as pinned. This can differ from the `pinned` input
2713
+ * while the detail pane is open, because pinning is suspended for as long as it shows a single
2714
+ * column.
2715
+ */
2716
+ get isPinned() {
2717
+ return this.el.nativeElement.classList.contains(PINNED_COLUMN_CLASS);
2718
+ }
2523
2719
  get showSeparator() {
2524
2720
  return this._showSeparator;
2525
2721
  }
@@ -2527,6 +2723,29 @@ class ClrDatagridColumn extends DatagridFilterRegistrar {
2527
2723
  this._showSeparator = value;
2528
2724
  this.changeDetectorRef.markForCheck();
2529
2725
  }
2726
+ /**
2727
+ * Pins the column to the left of the datagrid, so it stays visible while the remaining
2728
+ * columns are scrolled horizontally. Pinned columns keep their declaration order and are
2729
+ * rendered before the scrollable ones, right after the built-in row controls.
2730
+ */
2731
+ get pinned() {
2732
+ return this._pinned;
2733
+ }
2734
+ set pinned(value) {
2735
+ if (this._pinned === value) {
2736
+ return;
2737
+ }
2738
+ this._pinned = value;
2739
+ // The column state is what the header and the rows read to decide where to project the
2740
+ // column and its cells. It is optional only so the column keeps working when it is used
2741
+ // outside the render directives, e.g. in isolated tests.
2742
+ if (this.columnState) {
2743
+ this.columnsService.emitStateChange(this.columnState, {
2744
+ pinned: value,
2745
+ changes: [DatagridColumnChanges.PINNED],
2746
+ });
2747
+ }
2748
+ }
2530
2749
  // TODO: We might want to make this an enum in the future
2531
2750
  get colType() {
2532
2751
  return this._colType;
@@ -2692,10 +2911,7 @@ class ClrDatagridColumn extends DatagridFilterRegistrar {
2692
2911
  return;
2693
2912
  }
2694
2913
  if (!this.disableUnsort && reverse === undefined && this.sortOrder === ClrDatagridSortOrder.DESC) {
2695
- this._sortOrder = ClrDatagridSortOrder.UNSORTED;
2696
- this._sort.clear();
2697
- this._sortDirection = null;
2698
- this.sortOrderChange.emit(this._sortOrder);
2914
+ this.clearSort();
2699
2915
  return;
2700
2916
  }
2701
2917
  this._sort.toggle(this._sortBy, reverse);
@@ -2705,6 +2921,34 @@ class ClrDatagridColumn extends DatagridFilterRegistrar {
2705
2921
  this._sortDirection = this._sortOrder === ClrDatagridSortOrder.DESC ? 'down' : 'up';
2706
2922
  this.sortOrderChange.emit(this._sortOrder);
2707
2923
  }
2924
+ /**
2925
+ * Returns the datagrid to its unsorted state. Both the tri-state title button and the sort actions
2926
+ * in `clr-dg-column-actions` go through here, so the two cannot drift apart.
2927
+ */
2928
+ clearSort() {
2929
+ if (!this.sortable || this._sortOrder === ClrDatagridSortOrder.UNSORTED) {
2930
+ return;
2931
+ }
2932
+ this._sortOrder = ClrDatagridSortOrder.UNSORTED;
2933
+ this._sort.clear();
2934
+ this._sortDirection = null;
2935
+ this.sortOrderChange.emit(this._sortOrder);
2936
+ }
2937
+ /**
2938
+ * Pins or unpins the column. Going through the `pinned` setter keeps the rendering in sync, and the
2939
+ * output lets the application follow a change it did not initiate - without it a one-way
2940
+ * [clrDgPinned] binding would write the old value straight back.
2941
+ */
2942
+ togglePinned() {
2943
+ this.pinned = !this.pinned;
2944
+ this.pinnedChange.emit(this.pinned);
2945
+ }
2946
+ onPinToggleClick(event) {
2947
+ // The header is a drop target for the column ordering addon and a click target for the sort
2948
+ // button next to the toggle, so the toggle keeps its click to itself.
2949
+ event.stopPropagation();
2950
+ this.togglePinned();
2951
+ }
2708
2952
  listenForDetailPaneChanges() {
2709
2953
  return this.detailService.stateChange.subscribe(state => {
2710
2954
  if (this.showSeparator !== !state) {
@@ -2748,8 +2992,8 @@ class ClrDatagridColumn extends DatagridFilterRegistrar {
2748
2992
  delete this.initFilterValue;
2749
2993
  }
2750
2994
  }
2751
- static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.1.3", ngImport: i0, type: ClrDatagridColumn, deps: [{ token: i0.ElementRef }, { token: Sort }, { token: FiltersProvider }, { token: i0.ViewContainerRef }, { token: DetailService }, { token: i0.ChangeDetectorRef }, { token: i2.ClrCommonStringsService }], target: i0.ɵɵFactoryTarget.Component }); }
2752
- static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.1.3", type: ClrDatagridColumn, isStandalone: false, selector: "clr-dg-column", inputs: { filterStringPlaceholder: ["clrFilterStringPlaceholder", "filterStringPlaceholder"], filterNumberMaxPlaceholder: ["clrFilterNumberMaxPlaceholder", "filterNumberMaxPlaceholder"], filterNumberMinPlaceholder: ["clrFilterNumberMinPlaceholder", "filterNumberMinPlaceholder"], disableUnsort: ["clrDgDisableUnsort", "disableUnsort"], colType: ["clrDgColType", "colType"], field: ["clrDgField", "field"], sortBy: ["clrDgSortBy", "sortBy"], sortOrder: ["clrDgSortOrder", "sortOrder"], updateFilterValue: ["clrFilterValue", "updateFilterValue"] }, outputs: { sortOrderChange: "clrDgSortOrderChange", filterValueChange: "clrFilterValueChange" }, host: { attributes: { "role": "columnheader" }, properties: { "class.datagrid-column": "true", "attr.aria-sort": "ariaSort" } }, queries: [{ propertyName: "projectedFilter", first: true, predicate: CustomFilter, descendants: true }], viewQueries: [{ propertyName: "titleContainer", first: true, predicate: ["titleContainer"], descendants: true, read: ElementRef }], usesInheritance: true, usesOnChanges: true, hostDirectives: [{ directive: i3.ClrPopoverHostDirective }], ngImport: i0, template: `
2995
+ static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.25", ngImport: i0, type: ClrDatagridColumn, deps: [{ token: i0.ElementRef }, { token: Sort }, { token: FiltersProvider }, { token: i0.ViewContainerRef }, { token: DetailService }, { token: i0.ChangeDetectorRef }, { token: i2.ClrCommonStringsService }, { token: ColumnsService }, { token: COLUMN_STATE, optional: true }], target: i0.ɵɵFactoryTarget.Component }); }
2996
+ static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.2.25", type: ClrDatagridColumn, isStandalone: false, selector: "clr-dg-column", inputs: { filterStringPlaceholder: ["clrFilterStringPlaceholder", "filterStringPlaceholder"], filterNumberMaxPlaceholder: ["clrFilterNumberMaxPlaceholder", "filterNumberMaxPlaceholder"], filterNumberMinPlaceholder: ["clrFilterNumberMinPlaceholder", "filterNumberMinPlaceholder"], disableUnsort: ["clrDgDisableUnsort", "disableUnsort"], pinnable: ["clrDgPinnable", "pinnable", booleanAttribute], pinned: ["clrDgPinned", "pinned", booleanAttribute], colType: ["clrDgColType", "colType"], field: ["clrDgField", "field"], sortBy: ["clrDgSortBy", "sortBy"], sortOrder: ["clrDgSortOrder", "sortOrder"], updateFilterValue: ["clrFilterValue", "updateFilterValue"] }, outputs: { sortOrderChange: "clrDgSortOrderChange", pinnedChange: "clrDgPinnedChange", filterValueChange: "clrFilterValueChange" }, host: { attributes: { "role": "columnheader" }, properties: { "class.datagrid-column": "true", "attr.aria-sort": "ariaSort" } }, providers: [ColumnActionsService], queries: [{ propertyName: "projectedFilter", first: true, predicate: CustomFilter, descendants: true }], viewQueries: [{ propertyName: "titleContainer", first: true, predicate: ["titleContainer"], descendants: true, read: ElementRef }], usesInheritance: true, usesOnChanges: true, hostDirectives: [{ directive: i3.ClrPopoverHostDirective }], ngImport: i0, template: `
2753
2997
  <div class="datagrid-column-flex">
2754
2998
  @if (sortable) {
2755
2999
  <button class="datagrid-column-title" (click)="sort()" type="button" #titleContainer>
@@ -2790,13 +3034,32 @@ class ClrDatagridColumn extends DatagridFilterRegistrar {
2790
3034
  <ng-container *ngTemplateOutlet="columnTitle"></ng-container>
2791
3035
  </span>
2792
3036
  }
3037
+
3038
+ <!--
3039
+ The actions menu needs its own slot: the default ng-content lives inside the #columnTitle
3040
+ template, which is rendered inside the sort button, so an unselected clr-dg-column-actions
3041
+ would end up as a button within a button.
3042
+ -->
3043
+ <ng-content select="clr-dg-column-actions"></ng-content>
3044
+
3045
+ @if (pinnable && !columnActions.menuPresent()) {
3046
+ <button
3047
+ class="datagrid-column-pin"
3048
+ type="button"
3049
+ [attr.aria-label]="pinned ? commonStrings.keys.unpinColumn : commonStrings.keys.pinColumn"
3050
+ (click)="onPinToggleClick($event)"
3051
+ >
3052
+ <cds-icon [size]="'12'" [shape]="pinned ? 'unpin' : 'pin'" solid aria-hidden="true"></cds-icon>
3053
+ </button>
3054
+ }
3055
+
2793
3056
  @if (showSeparator) {
2794
3057
  <clr-dg-column-separator></clr-dg-column-separator>
2795
3058
  }
2796
3059
  </div>
2797
- `, isInline: true, dependencies: [{ kind: "directive", type: i9.NgTemplateOutlet, selector: "[ngTemplateOutlet]", inputs: ["ngTemplateOutletContext", "ngTemplateOutlet", "ngTemplateOutletInjector"] }, { kind: "component", type: i5.ClrIcon, selector: "clr-icon, cds-icon", inputs: ["shape", "size", "direction", "flip", "solid", "status", "inverse", "badge"] }, { kind: "component", type: ClrDatagridColumnSeparator, selector: "clr-dg-column-separator" }, { kind: "component", type: DatagridNumericFilter, selector: "clr-dg-numeric-filter", inputs: ["clrFilterMinPlaceholder", "clrFilterMaxPlaceholder", "clrFilterFromLabel", "clrFilterToLabel", "clrFilterValue", "clrDgNumericFilter"], outputs: ["clrFilterValueChange"] }, { kind: "component", type: DatagridStringFilter, selector: "clr-dg-string-filter", inputs: ["clrFilterPlaceholder", "clrFilterLabel", "clrDgStringFilter", "clrFilterValue"], outputs: ["clrFilterValueChange"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush }); }
3060
+ `, isInline: true, dependencies: [{ kind: "directive", type: i10.NgTemplateOutlet, selector: "[ngTemplateOutlet]", inputs: ["ngTemplateOutletContext", "ngTemplateOutlet", "ngTemplateOutletInjector"] }, { kind: "component", type: i4.ClrIcon, selector: "clr-icon, cds-icon", inputs: ["shape", "size", "direction", "flip", "solid", "status", "inverse", "badge", "innerOffset"] }, { kind: "component", type: ClrDatagridColumnSeparator, selector: "clr-dg-column-separator" }, { kind: "component", type: DatagridNumericFilter, selector: "clr-dg-numeric-filter", inputs: ["clrFilterMinPlaceholder", "clrFilterMaxPlaceholder", "clrFilterFromLabel", "clrFilterToLabel", "clrFilterValue", "clrDgNumericFilter"], outputs: ["clrFilterValueChange"] }, { kind: "component", type: DatagridStringFilter, selector: "clr-dg-string-filter", inputs: ["clrFilterPlaceholder", "clrFilterLabel", "clrDgStringFilter", "clrFilterValue"], outputs: ["clrFilterValueChange"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush }); }
2798
3061
  }
2799
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.1.3", ngImport: i0, type: ClrDatagridColumn, decorators: [{
3062
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.25", ngImport: i0, type: ClrDatagridColumn, decorators: [{
2800
3063
  type: Component,
2801
3064
  args: [{
2802
3065
  selector: 'clr-dg-column',
@@ -2841,12 +3104,33 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.1.3", ngImpor
2841
3104
  <ng-container *ngTemplateOutlet="columnTitle"></ng-container>
2842
3105
  </span>
2843
3106
  }
3107
+
3108
+ <!--
3109
+ The actions menu needs its own slot: the default ng-content lives inside the #columnTitle
3110
+ template, which is rendered inside the sort button, so an unselected clr-dg-column-actions
3111
+ would end up as a button within a button.
3112
+ -->
3113
+ <ng-content select="clr-dg-column-actions"></ng-content>
3114
+
3115
+ @if (pinnable && !columnActions.menuPresent()) {
3116
+ <button
3117
+ class="datagrid-column-pin"
3118
+ type="button"
3119
+ [attr.aria-label]="pinned ? commonStrings.keys.unpinColumn : commonStrings.keys.pinColumn"
3120
+ (click)="onPinToggleClick($event)"
3121
+ >
3122
+ <cds-icon [size]="'12'" [shape]="pinned ? 'unpin' : 'pin'" solid aria-hidden="true"></cds-icon>
3123
+ </button>
3124
+ }
3125
+
2844
3126
  @if (showSeparator) {
2845
3127
  <clr-dg-column-separator></clr-dg-column-separator>
2846
3128
  }
2847
3129
  </div>
2848
3130
  `,
2849
3131
  hostDirectives: [ClrPopoverHostDirective],
3132
+ // Shared by clr-dg-column-actions and this column's filter, whichever order they are created in.
3133
+ providers: [ColumnActionsService],
2850
3134
  host: {
2851
3135
  '[class.datagrid-column]': 'true',
2852
3136
  '[attr.aria-sort]': 'ariaSort',
@@ -2855,7 +3139,12 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.1.3", ngImpor
2855
3139
  changeDetection: ChangeDetectionStrategy.OnPush,
2856
3140
  standalone: false,
2857
3141
  }]
2858
- }], ctorParameters: () => [{ type: i0.ElementRef }, { type: Sort }, { type: FiltersProvider }, { type: i0.ViewContainerRef }, { type: DetailService }, { type: i0.ChangeDetectorRef }, { type: i2.ClrCommonStringsService }], propDecorators: { filterStringPlaceholder: [{
3142
+ }], ctorParameters: () => [{ type: i0.ElementRef }, { type: Sort }, { type: FiltersProvider }, { type: i0.ViewContainerRef }, { type: DetailService }, { type: i0.ChangeDetectorRef }, { type: i2.ClrCommonStringsService }, { type: ColumnsService }, { type: i12.BehaviorSubject, decorators: [{
3143
+ type: Optional
3144
+ }, {
3145
+ type: Inject,
3146
+ args: [COLUMN_STATE]
3147
+ }] }], propDecorators: { filterStringPlaceholder: [{
2859
3148
  type: Input,
2860
3149
  args: ['clrFilterStringPlaceholder']
2861
3150
  }], filterNumberMaxPlaceholder: [{
@@ -2867,15 +3156,24 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.1.3", ngImpor
2867
3156
  }], disableUnsort: [{
2868
3157
  type: Input,
2869
3158
  args: ['clrDgDisableUnsort']
3159
+ }], pinnable: [{
3160
+ type: Input,
3161
+ args: [{ alias: 'clrDgPinnable', transform: booleanAttribute }]
2870
3162
  }], sortOrderChange: [{
2871
3163
  type: Output,
2872
3164
  args: ['clrDgSortOrderChange']
3165
+ }], pinnedChange: [{
3166
+ type: Output,
3167
+ args: ['clrDgPinnedChange']
2873
3168
  }], filterValueChange: [{
2874
3169
  type: Output,
2875
3170
  args: ['clrFilterValueChange']
2876
3171
  }], titleContainer: [{
2877
3172
  type: ViewChild,
2878
3173
  args: ['titleContainer', { read: ElementRef }]
3174
+ }], pinned: [{
3175
+ type: Input,
3176
+ args: [{ alias: 'clrDgPinned', transform: booleanAttribute }]
2879
3177
  }], colType: [{
2880
3178
  type: Input,
2881
3179
  args: ['clrDgColType']
@@ -3060,10 +3358,10 @@ class Items {
3060
3358
  }
3061
3359
  this.emitChange();
3062
3360
  }
3063
- static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.1.3", ngImport: i0, type: Items, deps: [{ token: FiltersProvider }, { token: Sort }, { token: Page }], target: i0.ɵɵFactoryTarget.Injectable }); }
3064
- static { this.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "21.1.3", ngImport: i0, type: Items }); }
3361
+ static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.25", ngImport: i0, type: Items, deps: [{ token: FiltersProvider }, { token: Sort }, { token: Page }], target: i0.ɵɵFactoryTarget.Injectable }); }
3362
+ static { this.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "21.2.25", ngImport: i0, type: Items }); }
3065
3363
  }
3066
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.1.3", ngImport: i0, type: Items, decorators: [{
3364
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.25", ngImport: i0, type: Items, decorators: [{
3067
3365
  type: Injectable
3068
3366
  }], ctorParameters: () => [{ type: FiltersProvider }, { type: Sort }, { type: Page }] });
3069
3367
 
@@ -3118,11 +3416,12 @@ class ClrDatagridItems {
3118
3416
  }
3119
3417
  ngOnDestroy() {
3120
3418
  this.subscriptions.forEach(sub => sub.unsubscribe());
3419
+ this.items.smartenDown();
3121
3420
  }
3122
- static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.1.3", ngImport: i0, type: ClrDatagridItems, deps: [{ token: i0.TemplateRef }, { token: i0.IterableDiffers }, { token: Items }, { token: i0.ViewContainerRef }], target: i0.ɵɵFactoryTarget.Directive }); }
3123
- static { this.ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "14.0.0", version: "21.1.3", type: ClrDatagridItems, isStandalone: false, selector: "[clrDgItems][clrDgItemsOf]", inputs: { rawItems: ["clrDgItemsOf", "rawItems"], trackBy: ["clrDgItemsTrackBy", "trackBy"] }, ngImport: i0 }); }
3421
+ static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.25", ngImport: i0, type: ClrDatagridItems, deps: [{ token: i0.TemplateRef }, { token: i0.IterableDiffers }, { token: Items }, { token: i0.ViewContainerRef }], target: i0.ɵɵFactoryTarget.Directive }); }
3422
+ static { this.ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "14.0.0", version: "21.2.25", type: ClrDatagridItems, isStandalone: false, selector: "[clrDgItems][clrDgItemsOf]", inputs: { rawItems: ["clrDgItemsOf", "rawItems"], trackBy: ["clrDgItemsTrackBy", "trackBy"] }, ngImport: i0 }); }
3124
3423
  }
3125
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.1.3", ngImport: i0, type: ClrDatagridItems, decorators: [{
3424
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.25", ngImport: i0, type: ClrDatagridItems, decorators: [{
3126
3425
  type: Directive,
3127
3426
  args: [{
3128
3427
  selector: '[clrDgItems][clrDgItemsOf]',
@@ -3152,8 +3451,8 @@ class ClrDatagridPlaceholder {
3152
3451
  get emptyDatagrid() {
3153
3452
  return !this.items.loading && (!this.items.displayed || this.items.displayed.length === 0);
3154
3453
  }
3155
- static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.1.3", ngImport: i0, type: ClrDatagridPlaceholder, deps: [{ token: Items }], target: i0.ɵɵFactoryTarget.Component }); }
3156
- static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.1.3", type: ClrDatagridPlaceholder, isStandalone: false, selector: "clr-dg-placeholder", host: { properties: { "class.datagrid-placeholder-container": "true" } }, ngImport: i0, template: `
3454
+ static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.25", ngImport: i0, type: ClrDatagridPlaceholder, deps: [{ token: Items }], target: i0.ɵɵFactoryTarget.Component }); }
3455
+ static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.2.25", type: ClrDatagridPlaceholder, isStandalone: false, selector: "clr-dg-placeholder", host: { properties: { "class.datagrid-placeholder-container": "true" } }, ngImport: i0, template: `
3157
3456
  <div class="datagrid-placeholder" [class.datagrid-empty]="emptyDatagrid">
3158
3457
  @if (emptyDatagrid) {
3159
3458
  <div class="datagrid-placeholder-image"></div>
@@ -3166,7 +3465,7 @@ class ClrDatagridPlaceholder {
3166
3465
  </div>
3167
3466
  `, isInline: true }); }
3168
3467
  }
3169
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.1.3", ngImport: i0, type: ClrDatagridPlaceholder, decorators: [{
3468
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.25", ngImport: i0, type: ClrDatagridPlaceholder, decorators: [{
3170
3469
  type: Component,
3171
3470
  args: [{
3172
3471
  selector: 'clr-dg-placeholder',
@@ -3200,14 +3499,14 @@ class WrappedCell {
3200
3499
  ngOnDestroy() {
3201
3500
  this.cellView.destroy();
3202
3501
  }
3203
- static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.1.3", ngImport: i0, type: WrappedCell, deps: [], target: i0.ɵɵFactoryTarget.Component }); }
3204
- static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "21.1.3", type: WrappedCell, isStandalone: false, selector: "dg-wrapped-cell", viewQueries: [{ propertyName: "templateRef", first: true, predicate: ["cellPortal"], descendants: true }], ngImport: i0, template: `
3502
+ static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.25", ngImport: i0, type: WrappedCell, deps: [], target: i0.ɵɵFactoryTarget.Component }); }
3503
+ static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "21.2.25", type: WrappedCell, isStandalone: false, selector: "dg-wrapped-cell", viewQueries: [{ propertyName: "templateRef", first: true, predicate: ["cellPortal"], descendants: true }], ngImport: i0, template: `
3205
3504
  <ng-template #cellPortal>
3206
3505
  <ng-content></ng-content>
3207
3506
  </ng-template>
3208
3507
  `, isInline: true }); }
3209
3508
  }
3210
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.1.3", ngImport: i0, type: WrappedCell, decorators: [{
3509
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.25", ngImport: i0, type: WrappedCell, decorators: [{
3211
3510
  type: Component,
3212
3511
  args: [{
3213
3512
  selector: 'dg-wrapped-cell',
@@ -3239,10 +3538,10 @@ class ClrDatagridCell {
3239
3538
  ngOnInit() {
3240
3539
  this.wrappedInjector = new HostWrapper(WrappedCell, this.vcr);
3241
3540
  }
3242
- static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.1.3", ngImport: i0, type: ClrDatagridCell, deps: [{ token: i0.ViewContainerRef }], target: i0.ɵɵFactoryTarget.Component }); }
3243
- static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "21.1.3", type: ClrDatagridCell, isStandalone: false, selector: "clr-dg-cell", host: { attributes: { "role": "gridcell" }, properties: { "class.datagrid-cell": "true", "class.datagrid-signpost-trigger": "signpost.length > 0" } }, queries: [{ propertyName: "signpost", predicate: ClrSignpost }], ngImport: i0, template: `<ng-content></ng-content>`, isInline: true }); }
3541
+ static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.25", ngImport: i0, type: ClrDatagridCell, deps: [{ token: i0.ViewContainerRef }], target: i0.ɵɵFactoryTarget.Component }); }
3542
+ static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "21.2.25", type: ClrDatagridCell, isStandalone: false, selector: "clr-dg-cell", host: { attributes: { "role": "gridcell" }, properties: { "class.datagrid-cell": "true", "class.datagrid-signpost-trigger": "signpost.length > 0" } }, queries: [{ propertyName: "signpost", predicate: ClrSignpost }], ngImport: i0, template: `<ng-content></ng-content>`, isInline: true }); }
3244
3543
  }
3245
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.1.3", ngImport: i0, type: ClrDatagridCell, decorators: [{
3544
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.25", ngImport: i0, type: ClrDatagridCell, decorators: [{
3246
3545
  type: Component,
3247
3546
  args: [{
3248
3547
  selector: 'clr-dg-cell',
@@ -3302,10 +3601,10 @@ class DatagridIfExpandService extends IfExpandService {
3302
3601
  setReplace(replaceValue) {
3303
3602
  this._replace.next(replaceValue);
3304
3603
  }
3305
- static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.1.3", ngImport: i0, type: DatagridIfExpandService, deps: [], target: i0.ɵɵFactoryTarget.Injectable }); }
3306
- static { this.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "21.1.3", ngImport: i0, type: DatagridIfExpandService }); }
3604
+ static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.25", ngImport: i0, type: DatagridIfExpandService, deps: [], target: i0.ɵɵFactoryTarget.Injectable }); }
3605
+ static { this.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "21.2.25", ngImport: i0, type: DatagridIfExpandService }); }
3307
3606
  }
3308
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.1.3", ngImport: i0, type: DatagridIfExpandService, decorators: [{
3607
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.25", ngImport: i0, type: DatagridIfExpandService, decorators: [{
3309
3608
  type: Injectable
3310
3609
  }], ctorParameters: () => [] });
3311
3610
 
@@ -3364,14 +3663,14 @@ class WrappedRow {
3364
3663
  ngOnDestroy() {
3365
3664
  this.rowView.destroy();
3366
3665
  }
3367
- static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.1.3", ngImport: i0, type: WrappedRow, deps: [], target: i0.ɵɵFactoryTarget.Component }); }
3368
- static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "21.1.3", type: WrappedRow, isStandalone: false, selector: "dg-wrapped-row", viewQueries: [{ propertyName: "templateRef", first: true, predicate: ["rowPortal"], descendants: true }], ngImport: i0, template: `
3666
+ static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.25", ngImport: i0, type: WrappedRow, deps: [], target: i0.ɵɵFactoryTarget.Component }); }
3667
+ static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "21.2.25", type: WrappedRow, isStandalone: false, selector: "dg-wrapped-row", viewQueries: [{ propertyName: "templateRef", first: true, predicate: ["rowPortal"], descendants: true }], ngImport: i0, template: `
3369
3668
  <ng-template #rowPortal>
3370
3669
  <ng-content></ng-content>
3371
3670
  </ng-template>
3372
3671
  `, isInline: true }); }
3373
3672
  }
3374
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.1.3", ngImport: i0, type: WrappedRow, decorators: [{
3673
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.25", ngImport: i0, type: WrappedRow, decorators: [{
3375
3674
  type: Component,
3376
3675
  args: [{
3377
3676
  selector: 'dg-wrapped-row',
@@ -3721,10 +4020,10 @@ class Selection {
3721
4020
  updateCurrentSelectionRefs() {
3722
4021
  this._currentSelectionRefs = this._current?.map(item => this._items.identifyBy(item)) || [];
3723
4022
  }
3724
- static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.1.3", ngImport: i0, type: Selection, deps: [{ token: Items }, { token: FiltersProvider }, { token: i0.IterableDiffers }], target: i0.ɵɵFactoryTarget.Injectable }); }
3725
- static { this.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "21.1.3", ngImport: i0, type: Selection }); }
4023
+ static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.25", ngImport: i0, type: Selection, deps: [{ token: Items }, { token: FiltersProvider }, { token: i0.IterableDiffers }], target: i0.ɵɵFactoryTarget.Injectable }); }
4024
+ static { this.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "21.2.25", ngImport: i0, type: Selection }); }
3726
4025
  }
3727
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.1.3", ngImport: i0, type: Selection, decorators: [{
4026
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.25", ngImport: i0, type: Selection, decorators: [{
3728
4027
  type: Injectable
3729
4028
  }], ctorParameters: () => [{ type: Items }, { type: FiltersProvider }, { type: i0.IterableDiffers }] });
3730
4029
 
@@ -3750,10 +4049,10 @@ class RowActionService {
3750
4049
  unregister() {
3751
4050
  this.actionableCount--;
3752
4051
  }
3753
- static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.1.3", ngImport: i0, type: RowActionService, deps: [], target: i0.ɵɵFactoryTarget.Injectable }); }
3754
- static { this.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "21.1.3", ngImport: i0, type: RowActionService }); }
4052
+ static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.25", ngImport: i0, type: RowActionService, deps: [], target: i0.ɵɵFactoryTarget.Injectable }); }
4053
+ static { this.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "21.2.25", ngImport: i0, type: RowActionService }); }
3755
4054
  }
3756
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.1.3", ngImport: i0, type: RowActionService, decorators: [{
4055
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.25", ngImport: i0, type: RowActionService, decorators: [{
3757
4056
  type: Injectable
3758
4057
  }] });
3759
4058
 
@@ -3781,10 +4080,10 @@ class ExpandableRowsCount {
3781
4080
  unregister() {
3782
4081
  this.expandableCount--;
3783
4082
  }
3784
- static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.1.3", ngImport: i0, type: ExpandableRowsCount, deps: [{ token: DetailService }], target: i0.ɵɵFactoryTarget.Injectable }); }
3785
- static { this.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "21.1.3", ngImport: i0, type: ExpandableRowsCount }); }
4083
+ static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.25", ngImport: i0, type: ExpandableRowsCount, deps: [{ token: DetailService }], target: i0.ɵɵFactoryTarget.Injectable }); }
4084
+ static { this.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "21.2.25", ngImport: i0, type: ExpandableRowsCount }); }
3786
4085
  }
3787
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.1.3", ngImport: i0, type: ExpandableRowsCount, decorators: [{
4086
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.25", ngImport: i0, type: ExpandableRowsCount, decorators: [{
3788
4087
  type: Injectable
3789
4088
  }], ctorParameters: () => [{ type: DetailService }] });
3790
4089
 
@@ -3811,10 +4110,10 @@ class DisplayModeService {
3811
4110
  ngOnDestroy() {
3812
4111
  this.subscriptions.forEach(sub => sub.unsubscribe());
3813
4112
  }
3814
- static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.1.3", ngImport: i0, type: DisplayModeService, deps: [{ token: DatagridRenderOrganizer }], target: i0.ɵɵFactoryTarget.Injectable }); }
3815
- static { this.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "21.1.3", ngImport: i0, type: DisplayModeService }); }
4113
+ static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.25", ngImport: i0, type: DisplayModeService, deps: [{ token: DatagridRenderOrganizer }], target: i0.ɵɵFactoryTarget.Injectable }); }
4114
+ static { this.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "21.2.25", ngImport: i0, type: DisplayModeService }); }
3816
4115
  }
3817
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.1.3", ngImport: i0, type: DisplayModeService, decorators: [{
4116
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.25", ngImport: i0, type: DisplayModeService, decorators: [{
3818
4117
  type: Injectable
3819
4118
  }], ctorParameters: () => [{ type: DatagridRenderOrganizer }] });
3820
4119
 
@@ -3862,8 +4161,8 @@ class ClrDatagridSingleSelectionValueAccessor {
3862
4161
  const value = this.keyOf(this.value);
3863
4162
  this.renderer.setProperty(this.elementRef.nativeElement, 'checked', state === value);
3864
4163
  }
3865
- static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.1.3", ngImport: i0, type: ClrDatagridSingleSelectionValueAccessor, deps: [{ token: i0.Renderer2 }, { token: i0.ElementRef }], target: i0.ɵɵFactoryTarget.Directive }); }
3866
- static { this.ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "14.0.0", version: "21.1.3", type: ClrDatagridSingleSelectionValueAccessor, isStandalone: true, selector: "input[type=radio][clrDgSingleSelectionRadio]", inputs: { value: "value", clrDgIdentityFn: "clrDgIdentityFn" }, host: { listeners: { "change": "onChange(value)", "blur": "onTouched()" } }, providers: [
4164
+ static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.25", ngImport: i0, type: ClrDatagridSingleSelectionValueAccessor, deps: [{ token: i0.Renderer2 }, { token: i0.ElementRef }], target: i0.ɵɵFactoryTarget.Directive }); }
4165
+ static { this.ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "14.0.0", version: "21.2.25", type: ClrDatagridSingleSelectionValueAccessor, isStandalone: true, selector: "input[type=radio][clrDgSingleSelectionRadio]", inputs: { value: "value", clrDgIdentityFn: "clrDgIdentityFn" }, host: { listeners: { "change": "onChange(value)", "blur": "onTouched()" } }, providers: [
3867
4166
  {
3868
4167
  provide: NG_VALUE_ACCESSOR,
3869
4168
  useExisting: forwardRef(() => ClrDatagridSingleSelectionValueAccessor),
@@ -3871,7 +4170,7 @@ class ClrDatagridSingleSelectionValueAccessor {
3871
4170
  },
3872
4171
  ], ngImport: i0 }); }
3873
4172
  }
3874
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.1.3", ngImport: i0, type: ClrDatagridSingleSelectionValueAccessor, decorators: [{
4173
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.25", ngImport: i0, type: ClrDatagridSingleSelectionValueAccessor, decorators: [{
3875
4174
  type: Directive,
3876
4175
  args: [{
3877
4176
  selector: 'input[type=radio][clrDgSingleSelectionRadio]',
@@ -3914,10 +4213,10 @@ class ClrDatagridSelectionCellDirective {
3914
4213
  event.target.querySelector('input')?.click();
3915
4214
  }
3916
4215
  }
3917
- static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.1.3", ngImport: i0, type: ClrDatagridSelectionCellDirective, deps: [{ token: Selection }], target: i0.ɵɵFactoryTarget.Directive }); }
3918
- static { this.ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "14.0.0", version: "21.1.3", type: ClrDatagridSelectionCellDirective, isStandalone: false, selector: ".datagrid-select", host: { listeners: { "click": "onSelectionCellClick($event)" } }, ngImport: i0 }); }
4216
+ static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.25", ngImport: i0, type: ClrDatagridSelectionCellDirective, deps: [{ token: Selection }], target: i0.ɵɵFactoryTarget.Directive }); }
4217
+ static { this.ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "14.0.0", version: "21.2.25", type: ClrDatagridSelectionCellDirective, isStandalone: false, selector: ".datagrid-select", host: { listeners: { "click": "onSelectionCellClick($event)" } }, ngImport: i0 }); }
3919
4218
  }
3920
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.1.3", ngImport: i0, type: ClrDatagridSelectionCellDirective, decorators: [{
4219
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.25", ngImport: i0, type: ClrDatagridSelectionCellDirective, decorators: [{
3921
4220
  type: Directive,
3922
4221
  args: [{
3923
4222
  selector: '.datagrid-select',
@@ -3936,7 +4235,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.1.3", ngImpor
3936
4235
  */
3937
4236
  let nbRow = 0;
3938
4237
  class ClrDatagridRow {
3939
- constructor(selection, rowActionService, globalExpandable, expand, detailService, displayMode, vcr, renderer, el, commonStrings, items, document) {
4238
+ constructor(selection, rowActionService, globalExpandable, expand, detailService, displayMode, vcr, renderer, el, commonStrings, items, columnsService, document) {
3940
4239
  this.selection = selection;
3941
4240
  this.rowActionService = rowActionService;
3942
4241
  this.globalExpandable = globalExpandable;
@@ -3947,6 +4246,7 @@ class ClrDatagridRow {
3947
4246
  this.el = el;
3948
4247
  this.commonStrings = commonStrings;
3949
4248
  this.items = items;
4249
+ this.columnsService = columnsService;
3950
4250
  this.document = document;
3951
4251
  this.selectedChanged = new EventEmitter(false);
3952
4252
  this.expandedChange = new EventEmitter(false);
@@ -3966,6 +4266,13 @@ class ClrDatagridRow {
3966
4266
  this._detailCloseLabel = '';
3967
4267
  this._rowSelectionLabel = '';
3968
4268
  this.subscriptions = [];
4269
+ /**
4270
+ * The placeholder cells we create from `fixedCellTemplate` for the calculate pass. Unlike the
4271
+ * cell views, which belong to their `WrappedCell`, these are created here on every pass, so
4272
+ * they are ours to destroy. Detaching them from the container only unlinks them - the views
4273
+ * themselves would stay alive and keep the whole row, and the datagrid with it, in memory.
4274
+ */
4275
+ this.fixedCellViews = [];
3969
4276
  // By default, every item is selectable; it becomes not selectable only if it's explicitly set to false
3970
4277
  this._selectable = true;
3971
4278
  nbRow++;
@@ -4074,11 +4381,7 @@ class ClrDatagridRow {
4074
4381
  }
4075
4382
  ngAfterContentInit() {
4076
4383
  this.dgCells.changes.subscribe(() => {
4077
- this.dgCells.forEach(cell => {
4078
- if (!cell._view.destroyed) {
4079
- this._scrollableCells.insert(cell._view);
4080
- }
4081
- });
4384
+ this.insertCellViews();
4082
4385
  });
4083
4386
  }
4084
4387
  ngAfterViewInit() {
@@ -4088,7 +4391,12 @@ class ClrDatagridRow {
4088
4391
  for (let i = this._scrollableCells.length; i > 0; i--) {
4089
4392
  this._scrollableCells.detach();
4090
4393
  }
4394
+ // remove cell views of pinned columns from their static container
4395
+ for (let i = this._pinnedCells.length; i > 0; i--) {
4396
+ this._pinnedCells.detach();
4397
+ }
4091
4398
  // remove cell views from calculated view
4399
+ this.destroyFixedCellViews();
4092
4400
  for (let i = this._calculatedCells.length; i > 0; i--) {
4093
4401
  this._calculatedCells.detach();
4094
4402
  }
@@ -4101,9 +4409,11 @@ class ClrDatagridRow {
4101
4409
  this.globalExpandable.hasExpandableRow,
4102
4410
  this.detailService.enabled,
4103
4411
  ];
4104
- fixedCellConditions
4105
- .filter(Boolean)
4106
- .forEach(() => this._calculatedCells.insert(this._fixedCellTemplate.createEmbeddedView(null)));
4412
+ fixedCellConditions.filter(Boolean).forEach(() => {
4413
+ const fixedCellView = this._fixedCellTemplate.createEmbeddedView(null);
4414
+ this.fixedCellViews.push(fixedCellView);
4415
+ this._calculatedCells.insert(fixedCellView);
4416
+ });
4107
4417
  this.dgCells.forEach(cell => {
4108
4418
  if (!cell._view.destroyed) {
4109
4419
  this._calculatedCells.insert(cell._view);
@@ -4112,17 +4422,14 @@ class ClrDatagridRow {
4112
4422
  }
4113
4423
  else {
4114
4424
  this.displayCells = true;
4115
- this.dgCells.forEach(cell => {
4116
- if (!cell._view.destroyed) {
4117
- this._scrollableCells.insert(cell._view);
4118
- }
4119
- });
4425
+ this.insertCellViews();
4120
4426
  }
4121
4427
  }), this.expand.animate.subscribe(() => {
4122
4428
  this.expandAnimationTrigger = !this.expandAnimationTrigger;
4123
4429
  }));
4124
4430
  }
4125
4431
  ngOnDestroy() {
4432
+ this.destroyFixedCellViews();
4126
4433
  this.subscriptions.forEach((sub) => sub.unsubscribe());
4127
4434
  }
4128
4435
  toggle(selected = !this.selected) {
@@ -4173,6 +4480,31 @@ class ClrDatagridRow {
4173
4480
  this.toggle(selected);
4174
4481
  }
4175
4482
  }
4483
+ destroyFixedCellViews() {
4484
+ // On teardown Angular has already destroyed the views in our container by the time it runs our
4485
+ // `ngOnDestroy`, so only the calculate/display transition has live ones to release here.
4486
+ this.fixedCellViews.forEach(view => {
4487
+ if (!view.destroyed) {
4488
+ view.destroy();
4489
+ }
4490
+ });
4491
+ this.fixedCellViews = [];
4492
+ }
4493
+ /**
4494
+ * Projects the cells into the display containers. Cells of pinned columns go into their static
4495
+ * container so they stay visible during horizontal scroll; the rest stay scrollable. Cells are
4496
+ * matched with their column by declaration index, and iterating in that order keeps both groups
4497
+ * aligned with the header.
4498
+ */
4499
+ insertCellViews() {
4500
+ this.dgCells.forEach((cell, index) => {
4501
+ if (cell._view.destroyed) {
4502
+ return;
4503
+ }
4504
+ const container = this.columnsService.isPinned(index) ? this._pinnedCells : this._scrollableCells;
4505
+ container.insert(cell._view);
4506
+ });
4507
+ }
4176
4508
  rangeSelect() {
4177
4509
  const items = this.items.displayed;
4178
4510
  if (!items) {
@@ -4195,14 +4527,14 @@ class ClrDatagridRow {
4195
4527
  this.selection.rangeStart = this.item;
4196
4528
  }
4197
4529
  }
4198
- static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.1.3", ngImport: i0, type: ClrDatagridRow, deps: [{ token: Selection }, { token: RowActionService }, { token: ExpandableRowsCount }, { token: DatagridIfExpandService }, { token: DetailService }, { token: DisplayModeService }, { token: i0.ViewContainerRef }, { token: i0.Renderer2 }, { token: i0.ElementRef }, { token: i2.ClrCommonStringsService }, { token: Items }, { token: DOCUMENT }], target: i0.ɵɵFactoryTarget.Component }); }
4199
- static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.1.3", type: ClrDatagridRow, isStandalone: false, selector: "clr-dg-row", inputs: { detailDisabled: ["clrDgDetailDisabled", "detailDisabled"], detailHidden: ["clrDgDetailHidden", "detailHidden"], skeletonLoading: ["clrDgSkeletonLoading", "skeletonLoading"], item: ["clrDgItem", "item"], clrDgSelectable: "clrDgSelectable", selected: ["clrDgSelected", "selected"], expanded: ["clrDgExpanded", "expanded"], clrDgDetailOpenLabel: "clrDgDetailOpenLabel", clrDgDetailCloseLabel: "clrDgDetailCloseLabel", clrDgRowSelectionLabel: "clrDgRowSelectionLabel" }, outputs: { selectedChanged: "clrDgSelectedChange", expandedChange: "clrDgExpandedChange" }, host: { attributes: { "role": "rowgroup" }, properties: { "class.datagrid-row": "true", "class.datagrid-row-skeleton": "skeletonLoading", "class.datagrid-selected": "selected", "attr.aria-owns": "id" } }, providers: [
4530
+ static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.25", ngImport: i0, type: ClrDatagridRow, deps: [{ token: Selection }, { token: RowActionService }, { token: ExpandableRowsCount }, { token: DatagridIfExpandService }, { token: DetailService }, { token: DisplayModeService }, { token: i0.ViewContainerRef }, { token: i0.Renderer2 }, { token: i0.ElementRef }, { token: i2.ClrCommonStringsService }, { token: Items }, { token: ColumnsService }, { token: DOCUMENT }], target: i0.ɵɵFactoryTarget.Component }); }
4531
+ static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.2.25", type: ClrDatagridRow, isStandalone: false, selector: "clr-dg-row", inputs: { detailDisabled: ["clrDgDetailDisabled", "detailDisabled"], detailHidden: ["clrDgDetailHidden", "detailHidden"], skeletonLoading: ["clrDgSkeletonLoading", "skeletonLoading"], item: ["clrDgItem", "item"], clrDgSelectable: "clrDgSelectable", selected: ["clrDgSelected", "selected"], expanded: ["clrDgExpanded", "expanded"], clrDgDetailOpenLabel: "clrDgDetailOpenLabel", clrDgDetailCloseLabel: "clrDgDetailCloseLabel", clrDgRowSelectionLabel: "clrDgRowSelectionLabel" }, outputs: { selectedChanged: "clrDgSelectedChange", expandedChange: "clrDgExpandedChange" }, host: { attributes: { "role": "rowgroup" }, properties: { "class.datagrid-row": "true", "class.datagrid-row-skeleton": "skeletonLoading", "class.datagrid-selected": "selected", "attr.aria-owns": "id" } }, providers: [
4200
4532
  DatagridIfExpandService,
4201
4533
  { provide: IfExpandService, useExisting: DatagridIfExpandService },
4202
4534
  { provide: LoadingListener, useExisting: DatagridIfExpandService },
4203
- ], queries: [{ propertyName: "dgCells", predicate: ClrDatagridCell }], viewQueries: [{ propertyName: "expandAnimation", first: true, predicate: ClrExpandableAnimationDirective, descendants: true }, { propertyName: "detailButton", first: true, predicate: ["detailButton"], descendants: true }, { propertyName: "_stickyCells", first: true, predicate: ["stickyCells"], descendants: true, read: ViewContainerRef }, { propertyName: "_scrollableCells", first: true, predicate: ["scrollableCells"], descendants: true, read: ViewContainerRef }, { propertyName: "_calculatedCells", first: true, predicate: ["calculatedCells"], descendants: true, read: ViewContainerRef }, { propertyName: "_fixedCellTemplate", first: true, predicate: ["fixedCellTemplate"], descendants: true }], ngImport: i0, template: "<!--\n ~ Copyright (c) 2016-2026 Broadcom. All Rights Reserved.\n ~ The term \"Broadcom\" refers to Broadcom Inc. and/or its subsidiaries.\n ~ This software is released under MIT license.\n ~ The full license information can be found in LICENSE in the root directory of this project.\n -->\n<div\n role=\"row\"\n [id]=\"id\"\n class=\"datagrid-row-master datagrid-row-flex\"\n [clrExpandableAnimation]=\"expandAnimationTrigger\"\n (mousedown)=\"clearRanges($event)\"\n (click)=\"selectRow(!selected, $event)\"\n [class.datagrid-row-clickable]=\"selection.rowSelectionMode\"\n [class.datagrid-row-detail-open]=\"detailService.isRowOpen(item)\"\n>\n <div class=\"datagrid-row-sticky\">\n <!-- Sticky elements here -->\n <ng-container #stickyCells>\n @if (selection.selectionType === SELECTION_TYPE.Multi) {\n <div\n class=\"datagrid-select datagrid-fixed-column datagrid-cell\"\n [ngClass]=\"{ 'clr-form-control-disabled': !clrDgSelectable }\"\n role=\"gridcell\"\n >\n <div class=\"clr-checkbox-wrapper\">\n <input\n tabindex=\"-1\"\n type=\"checkbox\"\n [ngModel]=\"selected\"\n (ngModelChange)=\"toggle($event)\"\n [id]=\"checkboxId\"\n [disabled]=\"clrDgSelectable ? null : true\"\n [attr.aria-disabled]=\"clrDgSelectable ? null : true\"\n />\n <!-- Usage of class clr-col-null here prevents clr-col-* classes from being added when a datagrid is wrapped inside clrForm -->\n <label [for]=\"checkboxId\" class=\"clr-control-label clr-col-null\" (click)=\"clearRanges($event)\">\n <span class=\"clr-sr-only\">{{clrDgRowSelectionLabel || commonStrings.keys.select}}</span>\n </label>\n </div>\n </div>\n } @if (selection.selectionType === SELECTION_TYPE.Single) {\n <div\n class=\"datagrid-select datagrid-fixed-column datagrid-cell\"\n [ngClass]=\"{ 'clr-form-control-disabled': !clrDgSelectable }\"\n role=\"gridcell\"\n >\n <clr-radio-wrapper>\n <input\n tabindex=\"-1\"\n type=\"radio\"\n clrRadio\n clrDgSingleSelectionRadio\n [clrDgIdentityFn]=\"identifyBy\"\n [id]=\"radioId\"\n [name]=\"selection.id + '-radio'\"\n [value]=\"item\"\n [ngModel]=\"selection.currentSingle\"\n (ngModelChange)=\"selection.current = [$event]\"\n [disabled]=\"clrDgSelectable ? null : true\"\n [attr.aria-disabled]=\"clrDgSelectable ? null : true\"\n />\n <label class=\"clr-control-label clr-col-null\" [for]=\"radioId\">\n <span class=\"clr-sr-only\">{{ clrDgRowSelectionLabel || commonStrings.keys.select }}</span>\n </label>\n </clr-radio-wrapper>\n </div>\n } @if (rowActionService.hasActionableRow) {\n <div class=\"datagrid-row-actions datagrid-fixed-column datagrid-cell\" role=\"gridcell\">\n <ng-content select=\"clr-dg-action-overflow\"></ng-content>\n </div>\n } @if (globalExpandable.hasExpandableRow) {\n <div class=\"datagrid-expandable-caret datagrid-fixed-column datagrid-cell\" role=\"gridcell\">\n @if (expand.expandable) { @if (!expand.loading) {\n <button\n tabindex=\"-1\"\n (click)=\"toggleExpand($event)\"\n type=\"button\"\n class=\"datagrid-expandable-caret-button\"\n [attr.aria-expanded]=\"expand.expanded\"\n [attr.aria-label]=\"expand.expanded ? clrDgDetailCloseLabel : clrDgDetailOpenLabel\"\n [attr.aria-controls]=\"expand.hasExpandTemplate && !expand.expanded ? null : expandableId\"\n >\n <cds-icon\n shape=\"angle\"\n class=\"datagrid-expandable-caret-icon\"\n [direction]=\"expand.expanded ? 'down' : 'right'\"\n [attr.title]=\"expand.expanded ? commonStrings.keys.collapse : commonStrings.keys.expand\"\n ></cds-icon>\n </button>\n } @if (expand.loading) {\n <clr-spinner clrSmall>{{ commonStrings.keys.loading }}</clr-spinner>\n } }\n </div>\n } @if (detailService.enabled) {\n <div class=\"datagrid-detail-caret datagrid-fixed-column datagrid-cell\" role=\"gridcell\">\n @if (!detailHidden) {\n <button\n tabindex=\"-1\"\n (click)=\"openDetails($event, detailButton)\"\n type=\"button\"\n #detailButton\n class=\"datagrid-detail-caret-button\"\n [disabled]=\"detailDisabled\"\n [class.is-open]=\"detailService.isRowOpen(item)\"\n [attr.aria-label]=\"detailService.isRowOpen(item) ? clrDgDetailCloseLabel : clrDgDetailOpenLabel\"\n [attr.aria-expanded]=\"detailService.isRowOpen(item)\"\n [attr.aria-controls]=\"detailService.id\"\n aria-haspopup=\"dialog\"\n >\n <cds-icon\n shape=\"angle-double\"\n [direction]=\"detailService.isRowOpen(item) ? 'left' : 'right'\"\n class=\"datagrid-detail-caret-icon\"\n [attr.title]=\"detailService.isRowOpen(item) ? commonStrings.keys.close: commonStrings.keys.open\"\n ></cds-icon>\n </button>\n }\n </div>\n }\n </ng-container>\n <!-- placeholder for projecting other sticky cells as pinned-->\n </div>\n <div class=\"datagrid-row-scrollable\" [ngClass]=\"{'is-replaced': replaced && expanded}\">\n <div class=\"datagrid-scrolling-cells\">\n <ng-content select=\"clr-dg-cell\"></ng-content>\n <ng-container #scrollableCells></ng-container>\n </div>\n <!-- details here when replace, re-visit when sticky container is used for pinned cells -->\n @if (replaced && !expand.loading) {\n <ng-template [ngTemplateOutlet]=\"detail\"></ng-template>\n } @if (!replaced && !expand.loading) {\n <ng-template [ngTemplateOutlet]=\"detail\"></ng-template>\n }\n </div>\n</div>\n<!--\nWe need the \"project into template\" hacks because we need this in 2 different places\ndepending on whether the details replace the row or not.\n-->\n<ng-template #detail>\n <ng-content select=\"clr-dg-row-detail\"></ng-content>\n</ng-template>\n\n<ng-container #calculatedCells></ng-container>\n\n<ng-template #fixedCellTemplate>\n <div class=\"datagrid-fixed-column datagrid-cell\" role=\"gridcell\"></div>\n</ng-template>\n", dependencies: [{ kind: "directive", type: i9.NgClass, selector: "[ngClass]", inputs: ["class", "ngClass"] }, { kind: "directive", type: i9.NgTemplateOutlet, selector: "[ngTemplateOutlet]", inputs: ["ngTemplateOutletContext", "ngTemplateOutlet", "ngTemplateOutletInjector"] }, { kind: "component", type: i5.ClrIcon, selector: "clr-icon, cds-icon", inputs: ["shape", "size", "direction", "flip", "solid", "status", "inverse", "badge"] }, { kind: "directive", type: i4.ClrControlLabel, selector: "label", inputs: ["id", "for"] }, { kind: "directive", type: i12.ClrRadio, selector: "[clrRadio]" }, { kind: "component", type: i12.ClrRadioWrapper, selector: "clr-radio-wrapper" }, { kind: "directive", type: i13.DefaultValueAccessor, selector: "input:not([type=checkbox])[formControlName],textarea[formControlName],input:not([type=checkbox])[formControl],textarea[formControl],input:not([type=checkbox])[ngModel],textarea[ngModel],[ngDefaultControl]" }, { kind: "directive", type: i13.CheckboxControlValueAccessor, selector: "input[type=checkbox][formControlName],input[type=checkbox][formControl],input[type=checkbox][ngModel]" }, { kind: "directive", type: i13.RadioControlValueAccessor, selector: "input[type=radio][formControlName],input[type=radio][formControl],input[type=radio][ngModel]", inputs: ["name", "formControlName", "value"] }, { kind: "directive", type: i13.NgControlStatus, selector: "[formControlName],[ngModel],[formControl]" }, { kind: "directive", type: i13.NgModel, selector: "[ngModel]:not([formControlName]):not([formControl])", inputs: ["name", "disabled", "ngModel", "ngModelOptions"], outputs: ["ngModelChange"], exportAs: ["ngModel"] }, { kind: "directive", type: i2.ClrExpandableAnimationDirective, selector: "[clrExpandableAnimation]", inputs: ["clrExpandableAnimation"] }, { kind: "component", type: i14.ClrSpinner, selector: "clr-spinner", inputs: ["clrInline", "clrInverse", "clrSmall", "clrMedium"] }, { kind: "directive", type: ClrDatagridSingleSelectionValueAccessor, selector: "input[type=radio][clrDgSingleSelectionRadio]", inputs: ["value", "clrDgIdentityFn"] }, { kind: "directive", type: ClrDatagridSelectionCellDirective, selector: ".datagrid-select" }] }); }
4535
+ ], queries: [{ propertyName: "dgCells", predicate: ClrDatagridCell }], viewQueries: [{ propertyName: "expandAnimation", first: true, predicate: ClrExpandableAnimationDirective, descendants: true }, { propertyName: "detailButton", first: true, predicate: ["detailButton"], descendants: true }, { propertyName: "_stickyCells", first: true, predicate: ["stickyCells"], descendants: true, read: ViewContainerRef }, { propertyName: "_pinnedCells", first: true, predicate: ["pinnedCells"], descendants: true, read: ViewContainerRef }, { propertyName: "_scrollableCells", first: true, predicate: ["scrollableCells"], descendants: true, read: ViewContainerRef }, { propertyName: "_calculatedCells", first: true, predicate: ["calculatedCells"], descendants: true, read: ViewContainerRef }, { propertyName: "_fixedCellTemplate", first: true, predicate: ["fixedCellTemplate"], descendants: true }], ngImport: i0, template: "<!--\n ~ Copyright (c) 2016-2026 Broadcom. All Rights Reserved.\n ~ The term \"Broadcom\" refers to Broadcom Inc. and/or its subsidiaries.\n ~ This software is released under MIT license.\n ~ The full license information can be found in LICENSE in the root directory of this project.\n -->\n<div\n role=\"row\"\n [id]=\"id\"\n class=\"datagrid-row-master datagrid-row-flex\"\n (mousedown)=\"clearRanges($event)\"\n (click)=\"selectRow(!selected, $event)\"\n [class.datagrid-row-clickable]=\"selection.rowSelectionMode\"\n [class.datagrid-row-detail-open]=\"detailService.isRowOpen(item)\"\n>\n <div class=\"datagrid-row-sticky\">\n <!-- Sticky elements here -->\n <ng-container #stickyCells>\n @if (selection.selectionType === SELECTION_TYPE.Multi) {\n <div\n class=\"datagrid-select datagrid-fixed-column datagrid-cell\"\n [ngClass]=\"{ 'clr-form-control-disabled': !clrDgSelectable }\"\n role=\"gridcell\"\n >\n <div class=\"clr-checkbox-wrapper\">\n <input\n tabindex=\"-1\"\n type=\"checkbox\"\n [ngModel]=\"selected\"\n (ngModelChange)=\"toggle($event)\"\n [id]=\"checkboxId\"\n [disabled]=\"clrDgSelectable ? null : true\"\n [attr.aria-disabled]=\"clrDgSelectable ? null : true\"\n />\n <!-- Usage of class clr-col-null here prevents clr-col-* classes from being added when a datagrid is wrapped inside clrForm -->\n <label [for]=\"checkboxId\" class=\"clr-control-label clr-col-null\" (click)=\"clearRanges($event)\">\n <span class=\"clr-sr-only\">{{clrDgRowSelectionLabel || commonStrings.keys.select}}</span>\n </label>\n </div>\n </div>\n } @if (selection.selectionType === SELECTION_TYPE.Single) {\n <div\n class=\"datagrid-select datagrid-fixed-column datagrid-cell\"\n [ngClass]=\"{ 'clr-form-control-disabled': !clrDgSelectable }\"\n role=\"gridcell\"\n >\n <clr-radio-wrapper>\n <input\n tabindex=\"-1\"\n type=\"radio\"\n clrRadio\n clrDgSingleSelectionRadio\n [clrDgIdentityFn]=\"identifyBy\"\n [id]=\"radioId\"\n [name]=\"selection.id + '-radio'\"\n [value]=\"item\"\n [ngModel]=\"selection.currentSingle\"\n (ngModelChange)=\"selection.current = [$event]\"\n [disabled]=\"clrDgSelectable ? null : true\"\n [attr.aria-disabled]=\"clrDgSelectable ? null : true\"\n />\n <label class=\"clr-control-label clr-col-null\" [for]=\"radioId\">\n <span class=\"clr-sr-only\">{{ clrDgRowSelectionLabel || commonStrings.keys.select }}</span>\n </label>\n </clr-radio-wrapper>\n </div>\n } @if (rowActionService.hasActionableRow) {\n <div class=\"datagrid-row-actions datagrid-fixed-column datagrid-cell\" role=\"gridcell\">\n <ng-content select=\"clr-dg-action-overflow\"></ng-content>\n </div>\n } @if (globalExpandable.hasExpandableRow) {\n <div class=\"datagrid-expandable-caret datagrid-fixed-column datagrid-cell\" role=\"gridcell\">\n @if (expand.expandable) { @if (!expand.loading) {\n <button\n tabindex=\"-1\"\n (click)=\"toggleExpand($event)\"\n type=\"button\"\n class=\"datagrid-expandable-caret-button\"\n [attr.aria-expanded]=\"expand.expanded\"\n [attr.aria-label]=\"expand.expanded ? clrDgDetailCloseLabel : clrDgDetailOpenLabel\"\n [attr.aria-controls]=\"expand.hasExpandTemplate && !expand.expanded ? null : expandableId\"\n >\n <cds-icon\n shape=\"angle\"\n class=\"datagrid-expandable-caret-icon\"\n [direction]=\"expand.expanded ? 'down' : 'right'\"\n [attr.title]=\"expand.expanded ? commonStrings.keys.collapse : commonStrings.keys.expand\"\n ></cds-icon>\n </button>\n } @if (expand.loading) {\n <clr-spinner clrSmall>{{ commonStrings.keys.loading }}</clr-spinner>\n } }\n </div>\n } @if (detailService.enabled) {\n <div class=\"datagrid-detail-caret datagrid-fixed-column datagrid-cell\" role=\"gridcell\">\n @if (!detailHidden) {\n <button\n tabindex=\"-1\"\n (click)=\"openDetails($event, detailButton)\"\n type=\"button\"\n #detailButton\n class=\"datagrid-detail-caret-button\"\n [disabled]=\"detailDisabled\"\n [class.is-open]=\"detailService.isRowOpen(item)\"\n [attr.aria-label]=\"detailService.isRowOpen(item) ? clrDgDetailCloseLabel : clrDgDetailOpenLabel\"\n [attr.aria-expanded]=\"detailService.isRowOpen(item)\"\n [attr.aria-controls]=\"detailService.id\"\n aria-haspopup=\"dialog\"\n >\n <cds-icon\n shape=\"angle-double\"\n [direction]=\"detailService.isRowOpen(item) ? 'left' : 'right'\"\n class=\"datagrid-detail-caret-icon\"\n [attr.title]=\"detailService.isRowOpen(item) ? commonStrings.keys.close: commonStrings.keys.open\"\n ></cds-icon>\n </button>\n }\n </div>\n }\n </ng-container>\n </div>\n <div\n class=\"datagrid-row-scrollable\"\n [ngClass]=\"{'is-replaced': replaced && expanded}\"\n [clrExpandableAnimation]=\"expandAnimationTrigger\"\n >\n <div class=\"datagrid-scrolling-cells\">\n <div class=\"datagrid-pinned-cells\">\n <ng-container #pinnedCells></ng-container>\n </div>\n <ng-content select=\"clr-dg-cell\"></ng-content>\n <ng-container #scrollableCells></ng-container>\n </div>\n\n @if (!expand.loading) {\n <ng-template [ngTemplateOutlet]=\"detail\"></ng-template>\n }\n </div>\n</div>\n<!--\nWe need the \"project into template\" hacks because we need this in 2 different places\ndepending on whether the details replace the row or not.\n-->\n<ng-template #detail>\n <ng-content select=\"clr-dg-row-detail\"></ng-content>\n</ng-template>\n\n<ng-container #calculatedCells></ng-container>\n\n<ng-template #fixedCellTemplate>\n <div class=\"datagrid-fixed-column datagrid-cell\" role=\"gridcell\"></div>\n</ng-template>\n", dependencies: [{ kind: "directive", type: i10.NgClass, selector: "[ngClass]", inputs: ["class", "ngClass"] }, { kind: "directive", type: i10.NgTemplateOutlet, selector: "[ngTemplateOutlet]", inputs: ["ngTemplateOutletContext", "ngTemplateOutlet", "ngTemplateOutletInjector"] }, { kind: "component", type: i4.ClrIcon, selector: "clr-icon, cds-icon", inputs: ["shape", "size", "direction", "flip", "solid", "status", "inverse", "badge", "innerOffset"] }, { kind: "directive", type: i4$1.ClrControlLabel, selector: "label", inputs: ["id", "for"] }, { kind: "directive", type: i13.ClrRadio, selector: "[clrRadio]" }, { kind: "component", type: i13.ClrRadioWrapper, selector: "clr-radio-wrapper" }, { kind: "directive", type: i14.DefaultValueAccessor, selector: "input:not([type=checkbox])[formControlName],textarea[formControlName],input:not([type=checkbox])[formControl],textarea[formControl],input:not([type=checkbox])[ngModel],textarea[ngModel],[ngDefaultControl]" }, { kind: "directive", type: i14.CheckboxControlValueAccessor, selector: "input[type=checkbox][formControlName],input[type=checkbox][formControl],input[type=checkbox][ngModel]" }, { kind: "directive", type: i14.RadioControlValueAccessor, selector: "input[type=radio][formControlName],input[type=radio][formControl],input[type=radio][ngModel]", inputs: ["name", "formControlName", "value"] }, { kind: "directive", type: i14.NgControlStatus, selector: "[formControlName],[ngModel],[formControl]" }, { kind: "directive", type: i14.NgModel, selector: "[ngModel]:not([formControlName]):not([formControl])", inputs: ["name", "disabled", "ngModel", "ngModelOptions"], outputs: ["ngModelChange"], exportAs: ["ngModel"] }, { kind: "directive", type: i2.ClrExpandableAnimationDirective, selector: "[clrExpandableAnimation]", inputs: ["clrExpandableAnimation"] }, { kind: "component", type: i15.ClrSpinner, selector: "clr-spinner", inputs: ["clrInline", "clrInverse", "clrSmall", "clrMedium"] }, { kind: "directive", type: ClrDatagridSingleSelectionValueAccessor, selector: "input[type=radio][clrDgSingleSelectionRadio]", inputs: ["value", "clrDgIdentityFn"] }, { kind: "directive", type: ClrDatagridSelectionCellDirective, selector: ".datagrid-select" }] }); }
4204
4536
  }
4205
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.1.3", ngImport: i0, type: ClrDatagridRow, decorators: [{
4537
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.25", ngImport: i0, type: ClrDatagridRow, decorators: [{
4206
4538
  type: Component,
4207
4539
  args: [{ selector: 'clr-dg-row', host: {
4208
4540
  '[class.datagrid-row]': 'true',
@@ -4214,8 +4546,8 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.1.3", ngImpor
4214
4546
  DatagridIfExpandService,
4215
4547
  { provide: IfExpandService, useExisting: DatagridIfExpandService },
4216
4548
  { provide: LoadingListener, useExisting: DatagridIfExpandService },
4217
- ], standalone: false, template: "<!--\n ~ Copyright (c) 2016-2026 Broadcom. All Rights Reserved.\n ~ The term \"Broadcom\" refers to Broadcom Inc. and/or its subsidiaries.\n ~ This software is released under MIT license.\n ~ The full license information can be found in LICENSE in the root directory of this project.\n -->\n<div\n role=\"row\"\n [id]=\"id\"\n class=\"datagrid-row-master datagrid-row-flex\"\n [clrExpandableAnimation]=\"expandAnimationTrigger\"\n (mousedown)=\"clearRanges($event)\"\n (click)=\"selectRow(!selected, $event)\"\n [class.datagrid-row-clickable]=\"selection.rowSelectionMode\"\n [class.datagrid-row-detail-open]=\"detailService.isRowOpen(item)\"\n>\n <div class=\"datagrid-row-sticky\">\n <!-- Sticky elements here -->\n <ng-container #stickyCells>\n @if (selection.selectionType === SELECTION_TYPE.Multi) {\n <div\n class=\"datagrid-select datagrid-fixed-column datagrid-cell\"\n [ngClass]=\"{ 'clr-form-control-disabled': !clrDgSelectable }\"\n role=\"gridcell\"\n >\n <div class=\"clr-checkbox-wrapper\">\n <input\n tabindex=\"-1\"\n type=\"checkbox\"\n [ngModel]=\"selected\"\n (ngModelChange)=\"toggle($event)\"\n [id]=\"checkboxId\"\n [disabled]=\"clrDgSelectable ? null : true\"\n [attr.aria-disabled]=\"clrDgSelectable ? null : true\"\n />\n <!-- Usage of class clr-col-null here prevents clr-col-* classes from being added when a datagrid is wrapped inside clrForm -->\n <label [for]=\"checkboxId\" class=\"clr-control-label clr-col-null\" (click)=\"clearRanges($event)\">\n <span class=\"clr-sr-only\">{{clrDgRowSelectionLabel || commonStrings.keys.select}}</span>\n </label>\n </div>\n </div>\n } @if (selection.selectionType === SELECTION_TYPE.Single) {\n <div\n class=\"datagrid-select datagrid-fixed-column datagrid-cell\"\n [ngClass]=\"{ 'clr-form-control-disabled': !clrDgSelectable }\"\n role=\"gridcell\"\n >\n <clr-radio-wrapper>\n <input\n tabindex=\"-1\"\n type=\"radio\"\n clrRadio\n clrDgSingleSelectionRadio\n [clrDgIdentityFn]=\"identifyBy\"\n [id]=\"radioId\"\n [name]=\"selection.id + '-radio'\"\n [value]=\"item\"\n [ngModel]=\"selection.currentSingle\"\n (ngModelChange)=\"selection.current = [$event]\"\n [disabled]=\"clrDgSelectable ? null : true\"\n [attr.aria-disabled]=\"clrDgSelectable ? null : true\"\n />\n <label class=\"clr-control-label clr-col-null\" [for]=\"radioId\">\n <span class=\"clr-sr-only\">{{ clrDgRowSelectionLabel || commonStrings.keys.select }}</span>\n </label>\n </clr-radio-wrapper>\n </div>\n } @if (rowActionService.hasActionableRow) {\n <div class=\"datagrid-row-actions datagrid-fixed-column datagrid-cell\" role=\"gridcell\">\n <ng-content select=\"clr-dg-action-overflow\"></ng-content>\n </div>\n } @if (globalExpandable.hasExpandableRow) {\n <div class=\"datagrid-expandable-caret datagrid-fixed-column datagrid-cell\" role=\"gridcell\">\n @if (expand.expandable) { @if (!expand.loading) {\n <button\n tabindex=\"-1\"\n (click)=\"toggleExpand($event)\"\n type=\"button\"\n class=\"datagrid-expandable-caret-button\"\n [attr.aria-expanded]=\"expand.expanded\"\n [attr.aria-label]=\"expand.expanded ? clrDgDetailCloseLabel : clrDgDetailOpenLabel\"\n [attr.aria-controls]=\"expand.hasExpandTemplate && !expand.expanded ? null : expandableId\"\n >\n <cds-icon\n shape=\"angle\"\n class=\"datagrid-expandable-caret-icon\"\n [direction]=\"expand.expanded ? 'down' : 'right'\"\n [attr.title]=\"expand.expanded ? commonStrings.keys.collapse : commonStrings.keys.expand\"\n ></cds-icon>\n </button>\n } @if (expand.loading) {\n <clr-spinner clrSmall>{{ commonStrings.keys.loading }}</clr-spinner>\n } }\n </div>\n } @if (detailService.enabled) {\n <div class=\"datagrid-detail-caret datagrid-fixed-column datagrid-cell\" role=\"gridcell\">\n @if (!detailHidden) {\n <button\n tabindex=\"-1\"\n (click)=\"openDetails($event, detailButton)\"\n type=\"button\"\n #detailButton\n class=\"datagrid-detail-caret-button\"\n [disabled]=\"detailDisabled\"\n [class.is-open]=\"detailService.isRowOpen(item)\"\n [attr.aria-label]=\"detailService.isRowOpen(item) ? clrDgDetailCloseLabel : clrDgDetailOpenLabel\"\n [attr.aria-expanded]=\"detailService.isRowOpen(item)\"\n [attr.aria-controls]=\"detailService.id\"\n aria-haspopup=\"dialog\"\n >\n <cds-icon\n shape=\"angle-double\"\n [direction]=\"detailService.isRowOpen(item) ? 'left' : 'right'\"\n class=\"datagrid-detail-caret-icon\"\n [attr.title]=\"detailService.isRowOpen(item) ? commonStrings.keys.close: commonStrings.keys.open\"\n ></cds-icon>\n </button>\n }\n </div>\n }\n </ng-container>\n <!-- placeholder for projecting other sticky cells as pinned-->\n </div>\n <div class=\"datagrid-row-scrollable\" [ngClass]=\"{'is-replaced': replaced && expanded}\">\n <div class=\"datagrid-scrolling-cells\">\n <ng-content select=\"clr-dg-cell\"></ng-content>\n <ng-container #scrollableCells></ng-container>\n </div>\n <!-- details here when replace, re-visit when sticky container is used for pinned cells -->\n @if (replaced && !expand.loading) {\n <ng-template [ngTemplateOutlet]=\"detail\"></ng-template>\n } @if (!replaced && !expand.loading) {\n <ng-template [ngTemplateOutlet]=\"detail\"></ng-template>\n }\n </div>\n</div>\n<!--\nWe need the \"project into template\" hacks because we need this in 2 different places\ndepending on whether the details replace the row or not.\n-->\n<ng-template #detail>\n <ng-content select=\"clr-dg-row-detail\"></ng-content>\n</ng-template>\n\n<ng-container #calculatedCells></ng-container>\n\n<ng-template #fixedCellTemplate>\n <div class=\"datagrid-fixed-column datagrid-cell\" role=\"gridcell\"></div>\n</ng-template>\n" }]
4218
- }], ctorParameters: () => [{ type: Selection }, { type: RowActionService }, { type: ExpandableRowsCount }, { type: DatagridIfExpandService }, { type: DetailService }, { type: DisplayModeService }, { type: i0.ViewContainerRef }, { type: i0.Renderer2 }, { type: i0.ElementRef }, { type: i2.ClrCommonStringsService }, { type: Items }, { type: undefined, decorators: [{
4549
+ ], standalone: false, template: "<!--\n ~ Copyright (c) 2016-2026 Broadcom. All Rights Reserved.\n ~ The term \"Broadcom\" refers to Broadcom Inc. and/or its subsidiaries.\n ~ This software is released under MIT license.\n ~ The full license information can be found in LICENSE in the root directory of this project.\n -->\n<div\n role=\"row\"\n [id]=\"id\"\n class=\"datagrid-row-master datagrid-row-flex\"\n (mousedown)=\"clearRanges($event)\"\n (click)=\"selectRow(!selected, $event)\"\n [class.datagrid-row-clickable]=\"selection.rowSelectionMode\"\n [class.datagrid-row-detail-open]=\"detailService.isRowOpen(item)\"\n>\n <div class=\"datagrid-row-sticky\">\n <!-- Sticky elements here -->\n <ng-container #stickyCells>\n @if (selection.selectionType === SELECTION_TYPE.Multi) {\n <div\n class=\"datagrid-select datagrid-fixed-column datagrid-cell\"\n [ngClass]=\"{ 'clr-form-control-disabled': !clrDgSelectable }\"\n role=\"gridcell\"\n >\n <div class=\"clr-checkbox-wrapper\">\n <input\n tabindex=\"-1\"\n type=\"checkbox\"\n [ngModel]=\"selected\"\n (ngModelChange)=\"toggle($event)\"\n [id]=\"checkboxId\"\n [disabled]=\"clrDgSelectable ? null : true\"\n [attr.aria-disabled]=\"clrDgSelectable ? null : true\"\n />\n <!-- Usage of class clr-col-null here prevents clr-col-* classes from being added when a datagrid is wrapped inside clrForm -->\n <label [for]=\"checkboxId\" class=\"clr-control-label clr-col-null\" (click)=\"clearRanges($event)\">\n <span class=\"clr-sr-only\">{{clrDgRowSelectionLabel || commonStrings.keys.select}}</span>\n </label>\n </div>\n </div>\n } @if (selection.selectionType === SELECTION_TYPE.Single) {\n <div\n class=\"datagrid-select datagrid-fixed-column datagrid-cell\"\n [ngClass]=\"{ 'clr-form-control-disabled': !clrDgSelectable }\"\n role=\"gridcell\"\n >\n <clr-radio-wrapper>\n <input\n tabindex=\"-1\"\n type=\"radio\"\n clrRadio\n clrDgSingleSelectionRadio\n [clrDgIdentityFn]=\"identifyBy\"\n [id]=\"radioId\"\n [name]=\"selection.id + '-radio'\"\n [value]=\"item\"\n [ngModel]=\"selection.currentSingle\"\n (ngModelChange)=\"selection.current = [$event]\"\n [disabled]=\"clrDgSelectable ? null : true\"\n [attr.aria-disabled]=\"clrDgSelectable ? null : true\"\n />\n <label class=\"clr-control-label clr-col-null\" [for]=\"radioId\">\n <span class=\"clr-sr-only\">{{ clrDgRowSelectionLabel || commonStrings.keys.select }}</span>\n </label>\n </clr-radio-wrapper>\n </div>\n } @if (rowActionService.hasActionableRow) {\n <div class=\"datagrid-row-actions datagrid-fixed-column datagrid-cell\" role=\"gridcell\">\n <ng-content select=\"clr-dg-action-overflow\"></ng-content>\n </div>\n } @if (globalExpandable.hasExpandableRow) {\n <div class=\"datagrid-expandable-caret datagrid-fixed-column datagrid-cell\" role=\"gridcell\">\n @if (expand.expandable) { @if (!expand.loading) {\n <button\n tabindex=\"-1\"\n (click)=\"toggleExpand($event)\"\n type=\"button\"\n class=\"datagrid-expandable-caret-button\"\n [attr.aria-expanded]=\"expand.expanded\"\n [attr.aria-label]=\"expand.expanded ? clrDgDetailCloseLabel : clrDgDetailOpenLabel\"\n [attr.aria-controls]=\"expand.hasExpandTemplate && !expand.expanded ? null : expandableId\"\n >\n <cds-icon\n shape=\"angle\"\n class=\"datagrid-expandable-caret-icon\"\n [direction]=\"expand.expanded ? 'down' : 'right'\"\n [attr.title]=\"expand.expanded ? commonStrings.keys.collapse : commonStrings.keys.expand\"\n ></cds-icon>\n </button>\n } @if (expand.loading) {\n <clr-spinner clrSmall>{{ commonStrings.keys.loading }}</clr-spinner>\n } }\n </div>\n } @if (detailService.enabled) {\n <div class=\"datagrid-detail-caret datagrid-fixed-column datagrid-cell\" role=\"gridcell\">\n @if (!detailHidden) {\n <button\n tabindex=\"-1\"\n (click)=\"openDetails($event, detailButton)\"\n type=\"button\"\n #detailButton\n class=\"datagrid-detail-caret-button\"\n [disabled]=\"detailDisabled\"\n [class.is-open]=\"detailService.isRowOpen(item)\"\n [attr.aria-label]=\"detailService.isRowOpen(item) ? clrDgDetailCloseLabel : clrDgDetailOpenLabel\"\n [attr.aria-expanded]=\"detailService.isRowOpen(item)\"\n [attr.aria-controls]=\"detailService.id\"\n aria-haspopup=\"dialog\"\n >\n <cds-icon\n shape=\"angle-double\"\n [direction]=\"detailService.isRowOpen(item) ? 'left' : 'right'\"\n class=\"datagrid-detail-caret-icon\"\n [attr.title]=\"detailService.isRowOpen(item) ? commonStrings.keys.close: commonStrings.keys.open\"\n ></cds-icon>\n </button>\n }\n </div>\n }\n </ng-container>\n </div>\n <div\n class=\"datagrid-row-scrollable\"\n [ngClass]=\"{'is-replaced': replaced && expanded}\"\n [clrExpandableAnimation]=\"expandAnimationTrigger\"\n >\n <div class=\"datagrid-scrolling-cells\">\n <div class=\"datagrid-pinned-cells\">\n <ng-container #pinnedCells></ng-container>\n </div>\n <ng-content select=\"clr-dg-cell\"></ng-content>\n <ng-container #scrollableCells></ng-container>\n </div>\n\n @if (!expand.loading) {\n <ng-template [ngTemplateOutlet]=\"detail\"></ng-template>\n }\n </div>\n</div>\n<!--\nWe need the \"project into template\" hacks because we need this in 2 different places\ndepending on whether the details replace the row or not.\n-->\n<ng-template #detail>\n <ng-content select=\"clr-dg-row-detail\"></ng-content>\n</ng-template>\n\n<ng-container #calculatedCells></ng-container>\n\n<ng-template #fixedCellTemplate>\n <div class=\"datagrid-fixed-column datagrid-cell\" role=\"gridcell\"></div>\n</ng-template>\n" }]
4550
+ }], ctorParameters: () => [{ type: Selection }, { type: RowActionService }, { type: ExpandableRowsCount }, { type: DatagridIfExpandService }, { type: DetailService }, { type: DisplayModeService }, { type: i0.ViewContainerRef }, { type: i0.Renderer2 }, { type: i0.ElementRef }, { type: i2.ClrCommonStringsService }, { type: Items }, { type: ColumnsService }, { type: undefined, decorators: [{
4219
4551
  type: Inject,
4220
4552
  args: [DOCUMENT]
4221
4553
  }] }], propDecorators: { selectedChanged: [{
@@ -4245,6 +4577,9 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.1.3", ngImpor
4245
4577
  }], _stickyCells: [{
4246
4578
  type: ViewChild,
4247
4579
  args: ['stickyCells', { read: ViewContainerRef }]
4580
+ }], _pinnedCells: [{
4581
+ type: ViewChild,
4582
+ args: ['pinnedCells', { read: ViewContainerRef }]
4248
4583
  }], _scrollableCells: [{
4249
4584
  type: ViewChild,
4250
4585
  args: ['scrollableCells', { read: ViewContainerRef }]
@@ -4303,6 +4638,14 @@ class ClrDatagridVirtualScrollDirective {
4303
4638
  this.shouldUpdateAriaRowIndexes = false;
4304
4639
  this.subscriptions = [];
4305
4640
  this.topIndex = 0;
4641
+ /**
4642
+ * Injectors for the CDK virtual scroll instances we create by hand, in the order they have to be
4643
+ * destroyed. Destroying them is what runs the CDK teardown: their `ngOnDestroy` and, importantly,
4644
+ * the `DestroyRef` cleanup `CdkVirtualScrollViewport` registers for the effect it creates on the
4645
+ * application injector. Leaving them alive keeps that effect registered, which retains the
4646
+ * viewport and the entire datagrid view tree for as long as the application lives.
4647
+ */
4648
+ this.cdkInjectors = [];
4306
4649
  // @deprecated remove the mutation observer when `datagrid-compact` class is deleted
4307
4650
  this.mutationChanges = new MutationObserver((mutations) => {
4308
4651
  mutations.forEach((mutation) => {
@@ -4410,7 +4753,7 @@ class ClrDatagridVirtualScrollDirective {
4410
4753
  ngAfterViewInit() {
4411
4754
  runInInjectionContext(this.injector, () => {
4412
4755
  this.virtualScrollViewport = this.createVirtualScrollViewportForDatagrid(this.changeDetectorRef, this.ngZone, this.renderer2, this.directionality, this.scrollDispatcher, this.viewportRuler, this.datagridElementRef, this.virtualScrollStrategy);
4413
- this.cdkVirtualFor = createCdkVirtualForOfDirective(this.viewContainerRef, this.templateRef, this.iterableDiffers, this.virtualScrollViewport, this.ngZone);
4756
+ this.cdkVirtualFor = this.createCdkVirtualForOfDirective(this.viewContainerRef, this.templateRef, this.iterableDiffers, this.virtualScrollViewport, this.ngZone);
4414
4757
  this.virtualScrollViewport.ngOnInit();
4415
4758
  });
4416
4759
  this.gridRoleElement = this.datagridElementRef.nativeElement.querySelector('[role="grid"]');
@@ -4441,12 +4784,21 @@ class ClrDatagridVirtualScrollDirective {
4441
4784
  }
4442
4785
  }
4443
4786
  ngOnDestroy() {
4444
- this.cdkVirtualFor?.ngOnDestroy();
4445
- this.virtualScrollViewport?.ngOnDestroy();
4787
+ // Ours first: CDK teardown emits on the streams we subscribe to, and third-party teardown that
4788
+ // throws must not be able to leave our own observer and subscriptions behind.
4446
4789
  this.mutationChanges?.disconnect();
4447
4790
  this.subscriptions.forEach(subscription => {
4448
4791
  subscription.unsubscribe();
4449
4792
  });
4793
+ try {
4794
+ // Destroying the injectors calls `ngOnDestroy` on the CDK instances they created and runs the
4795
+ // `DestroyRef` cleanup CDK registered for them, so we must not call those hooks ourselves.
4796
+ this.cdkInjectors.forEach(injector => injector.destroy());
4797
+ }
4798
+ finally {
4799
+ // An injector cannot be destroyed twice, so drop them even if one of them threw.
4800
+ this.cdkInjectors.length = 0;
4801
+ }
4450
4802
  }
4451
4803
  scrollUp(offset, behavior = 'auto') {
4452
4804
  this.scrollToIndex(this.topIndex - offset, behavior);
@@ -4502,13 +4854,62 @@ class ClrDatagridVirtualScrollDirective {
4502
4854
  createVirtualScrollViewportForDatagrid(changeDetectorRef, ngZone, renderer2, directionality, scrollDispatcher, viewportRuler, datagridElementRef, virtualScrollStrategy) {
4503
4855
  const datagridContentElement = datagridElementRef.nativeElement.querySelector('.datagrid-content');
4504
4856
  const datagridRowsElement = datagridElementRef.nativeElement.querySelector('.datagrid-rows');
4505
- const virtualScrollViewport = createCdkVirtualScrollViewport(new ElementRef(datagridContentElement), new ElementRef(datagridRowsElement), changeDetectorRef, ngZone, renderer2, virtualScrollStrategy, directionality, scrollDispatcher, viewportRuler, null);
4857
+ return this.createCdkVirtualScrollViewport(new ElementRef(datagridContentElement), new ElementRef(datagridRowsElement), changeDetectorRef, ngZone, renderer2, virtualScrollStrategy, directionality, scrollDispatcher, viewportRuler, null);
4858
+ }
4859
+ createCdkVirtualScrollViewport(datagridDivElementRef, contentWrapper, changeDetectorRef, ngZone, renderer2, virtualScrollStrategy, directionality, scrollDispatcher, viewportRuler, scrollable) {
4860
+ const injector = createEnvironmentInjector([
4861
+ { provide: ElementRef, useValue: datagridDivElementRef },
4862
+ { provide: ChangeDetectorRef, useValue: changeDetectorRef },
4863
+ { provide: NgZone, useValue: ngZone },
4864
+ { provide: Renderer2, useValue: renderer2 },
4865
+ { provide: VIRTUAL_SCROLL_STRATEGY, useValue: virtualScrollStrategy },
4866
+ { provide: CdkVirtualScrollable, useValue: scrollable },
4867
+ { provide: CdkVirtualScrollViewport, useClass: CdkVirtualScrollViewport },
4868
+ ], this.createApplicationInjector(directionality, scrollDispatcher, viewportRuler));
4869
+ const virtualScrollViewport = injector.get(CdkVirtualScrollViewport);
4870
+ virtualScrollViewport._contentWrapper = contentWrapper;
4871
+ // Registered before the caller creates anything else, so a half-finished init still tears down
4872
+ // what it did manage to create.
4873
+ this.cdkInjectors.push(injector);
4506
4874
  return virtualScrollViewport;
4507
4875
  }
4508
- static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.1.3", ngImport: i0, type: ClrDatagridVirtualScrollDirective, deps: [{ token: i0.ChangeDetectorRef }, { token: i0.IterableDiffers }, { token: Items }, { token: i0.NgZone }, { token: i0.Renderer2 }, { token: i0.TemplateRef }, { token: i0.ViewContainerRef }, { token: i2$1.Directionality }, { token: i3$1.ScrollDispatcher }, { token: i3$1.ViewportRuler }, { token: forwardRef(() => ClrDatagrid) }, { token: i0.EnvironmentInjector }], target: i0.ɵɵFactoryTarget.Directive }); }
4509
- static { this.ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "14.0.0", version: "21.1.3", type: ClrDatagridVirtualScrollDirective, isStandalone: false, selector: "[clrVirtualScroll],[ClrVirtualScroll]", inputs: { persistItems: ["clrVirtualPersistItems", "persistItems"], cdkVirtualForOf: ["clrVirtualRowsOf", "cdkVirtualForOf"], cdkVirtualForTrackBy: ["clrVirtualRowsTrackBy", "cdkVirtualForTrackBy"], cdkVirtualForTemplate: ["clrVirtualRowsTemplate", "cdkVirtualForTemplate"], cdkVirtualForTemplateCacheSize: ["clrVirtualRowsTemplateCacheSize", "cdkVirtualForTemplateCacheSize"], itemSize: ["clrVirtualRowsItemSize", "itemSize"], minBufferPx: ["clrVirtualRowsMinBufferPx", "minBufferPx"], maxBufferPx: ["clrVirtualRowsMaxBufferPx", "maxBufferPx"], dataRange: ["clrVirtualDataRange", "dataRange"] }, outputs: { renderedRangeChange: "renderedRangeChange" }, providers: [Items], ngImport: i0 }); }
4876
+ /**
4877
+ * `Directionality`, `ScrollDispatcher` and `ViewportRuler` belong to the application, not to us.
4878
+ * Angular registers every value an injector hands out that has an `ngOnDestroy` - `useValue`
4879
+ * providers included - and calls it from `injector.destroy()`, so putting them in an injector we
4880
+ * destroy would end scroll, resize and text-direction notification for the whole application the
4881
+ * first time a virtual scroll datagrid goes away. They live in this parent, which nothing destroys,
4882
+ * so the viewport still resolves the very instances our host injector gave us - including a
4883
+ * `Directionality` overridden by an ancestor `[dir]`.
4884
+ */
4885
+ createApplicationInjector(directionality, scrollDispatcher, viewportRuler) {
4886
+ return createEnvironmentInjector([
4887
+ { provide: Directionality, useValue: directionality },
4888
+ { provide: ScrollDispatcher, useValue: scrollDispatcher },
4889
+ { provide: ViewportRuler, useValue: viewportRuler },
4890
+ ], inject(EnvironmentInjector));
4891
+ }
4892
+ createCdkVirtualForOfDirective(viewContainerRef, templateRef, iterableDiffers, virtualScrollViewport, ngZone) {
4893
+ // `CdkVirtualForOf` resolves the viewport with `skipSelf`, so it has to come from a parent
4894
+ // injector rather than the one that provides `CdkVirtualForOf` itself. That parent holds nothing
4895
+ // but the value provider, and destroying it would run the viewport's `ngOnDestroy` a second time
4896
+ // on top of the one its own injector already runs, so it is left to be garbage collected.
4897
+ const virtualScrollViewportInjector = createEnvironmentInjector([{ provide: CDK_VIRTUAL_SCROLL_VIEWPORT, useValue: virtualScrollViewport }], inject(EnvironmentInjector));
4898
+ const cdkVirtualForInjector = createEnvironmentInjector([
4899
+ { provide: ViewContainerRef, useValue: viewContainerRef },
4900
+ { provide: TemplateRef, useValue: templateRef },
4901
+ { provide: IterableDiffers, useValue: iterableDiffers },
4902
+ { provide: NgZone, useValue: ngZone },
4903
+ { provide: CdkVirtualForOf, useClass: CdkVirtualForOf },
4904
+ ], virtualScrollViewportInjector);
4905
+ // `CdkVirtualForOf` reads from the viewport, so it has to go away first.
4906
+ this.cdkInjectors.unshift(cdkVirtualForInjector);
4907
+ return cdkVirtualForInjector.get(CdkVirtualForOf);
4908
+ }
4909
+ static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.25", ngImport: i0, type: ClrDatagridVirtualScrollDirective, deps: [{ token: i0.ChangeDetectorRef }, { token: i0.IterableDiffers }, { token: Items }, { token: i0.NgZone }, { token: i0.Renderer2 }, { token: i0.TemplateRef }, { token: i0.ViewContainerRef }, { token: i2$1.Directionality }, { token: i3$1.ScrollDispatcher }, { token: i3$1.ViewportRuler }, { token: forwardRef(() => ClrDatagrid) }, { token: i0.EnvironmentInjector }], target: i0.ɵɵFactoryTarget.Directive }); }
4910
+ static { this.ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "14.0.0", version: "21.2.25", type: ClrDatagridVirtualScrollDirective, isStandalone: false, selector: "[clrVirtualScroll],[ClrVirtualScroll]", inputs: { persistItems: ["clrVirtualPersistItems", "persistItems"], cdkVirtualForOf: ["clrVirtualRowsOf", "cdkVirtualForOf"], cdkVirtualForTrackBy: ["clrVirtualRowsTrackBy", "cdkVirtualForTrackBy"], cdkVirtualForTemplate: ["clrVirtualRowsTemplate", "cdkVirtualForTemplate"], cdkVirtualForTemplateCacheSize: ["clrVirtualRowsTemplateCacheSize", "cdkVirtualForTemplateCacheSize"], itemSize: ["clrVirtualRowsItemSize", "itemSize"], minBufferPx: ["clrVirtualRowsMinBufferPx", "minBufferPx"], maxBufferPx: ["clrVirtualRowsMaxBufferPx", "maxBufferPx"], dataRange: ["clrVirtualDataRange", "dataRange"] }, outputs: { renderedRangeChange: "renderedRangeChange" }, providers: [Items], ngImport: i0 }); }
4510
4911
  }
4511
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.1.3", ngImport: i0, type: ClrDatagridVirtualScrollDirective, decorators: [{
4912
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.25", ngImport: i0, type: ClrDatagridVirtualScrollDirective, decorators: [{
4512
4913
  type: Directive,
4513
4914
  args: [{
4514
4915
  selector: '[clrVirtualScroll],[ClrVirtualScroll]',
@@ -4548,118 +4949,6 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.1.3", ngImpor
4548
4949
  type: Input,
4549
4950
  args: ['clrVirtualDataRange']
4550
4951
  }] } });
4551
- function createCdkVirtualScrollViewport(datagridDivElementRef, contentWrapper, changeDetectorRef, ngZone, renderer2, virtualScrollStrategy, directionality, scrollDispatcher, viewportRuler, scrollable) {
4552
- const virtualScrollViewportInjector = Injector.create({
4553
- parent: inject(EnvironmentInjector),
4554
- providers: [
4555
- { provide: ElementRef, useValue: datagridDivElementRef },
4556
- { provide: ChangeDetectorRef, useValue: changeDetectorRef },
4557
- { provide: NgZone, useValue: ngZone },
4558
- { provide: Renderer2, useValue: renderer2 },
4559
- { provide: VIRTUAL_SCROLL_STRATEGY, useValue: virtualScrollStrategy },
4560
- { provide: Directionality, useValue: directionality },
4561
- { provide: ScrollDispatcher, useValue: scrollDispatcher },
4562
- { provide: ViewportRuler, useValue: viewportRuler },
4563
- { provide: CdkVirtualScrollable, useValue: scrollable },
4564
- { provide: CdkVirtualScrollViewport, useClass: CdkVirtualScrollViewport },
4565
- ],
4566
- });
4567
- const viewPort = virtualScrollViewportInjector.get(CdkVirtualScrollViewport);
4568
- viewPort._contentWrapper = contentWrapper;
4569
- return viewPort;
4570
- }
4571
- function createCdkVirtualForOfDirective(viewContainerRef, templateRef, iterableDiffers, virtualScrollViewport, ngZone) {
4572
- const virtualScrollViewportInjector = Injector.create({
4573
- parent: inject(EnvironmentInjector),
4574
- providers: [{ provide: CDK_VIRTUAL_SCROLL_VIEWPORT, useValue: virtualScrollViewport }],
4575
- });
4576
- const cdkVirtualForInjector = Injector.create({
4577
- parent: virtualScrollViewportInjector,
4578
- providers: [
4579
- { provide: ViewContainerRef, useValue: viewContainerRef },
4580
- { provide: TemplateRef, useValue: templateRef },
4581
- { provide: IterableDiffers, useValue: iterableDiffers },
4582
- { provide: NgZone, useValue: ngZone },
4583
- { provide: CdkVirtualForOf, useClass: CdkVirtualForOf },
4584
- ],
4585
- });
4586
- return cdkVirtualForInjector.get(CdkVirtualForOf);
4587
- }
4588
-
4589
- /*
4590
- * Copyright (c) 2016-2026 Broadcom. All Rights Reserved.
4591
- * The term "Broadcom" refers to Broadcom Inc. and/or its subsidiaries.
4592
- * This software is released under MIT license.
4593
- * The full license information can be found in LICENSE in the root directory of this project.
4594
- */
4595
- var DatagridColumnChanges;
4596
- (function (DatagridColumnChanges) {
4597
- DatagridColumnChanges[DatagridColumnChanges["WIDTH"] = 0] = "WIDTH";
4598
- DatagridColumnChanges[DatagridColumnChanges["HIDDEN"] = 1] = "HIDDEN";
4599
- DatagridColumnChanges[DatagridColumnChanges["INITIALIZE"] = 2] = "INITIALIZE";
4600
- })(DatagridColumnChanges || (DatagridColumnChanges = {}));
4601
- const ALL_COLUMN_CHANGES = Object.keys(DatagridColumnChanges)
4602
- .map(key => DatagridColumnChanges[key])
4603
- .filter(key => key === parseInt(key, 10) && key !== DatagridColumnChanges.INITIALIZE); // extracts only integer keys
4604
-
4605
- /*
4606
- * Copyright (c) 2016-2026 Broadcom. All Rights Reserved.
4607
- * The term "Broadcom" refers to Broadcom Inc. and/or its subsidiaries.
4608
- * This software is released under MIT license.
4609
- * The full license information can be found in LICENSE in the root directory of this project.
4610
- */
4611
- class ColumnsService {
4612
- constructor() {
4613
- this.columns = [];
4614
- this.columnsStateChange = new BehaviorSubject(null);
4615
- this._cache = [];
4616
- }
4617
- get columnStates() {
4618
- return this.columns.map(column => column.value);
4619
- }
4620
- get hasHideableColumns() {
4621
- return this.columnStates.filter(state => state.hideable).length > 0;
4622
- }
4623
- get visibleColumns() {
4624
- return this.columnStates.filter(state => !state.hidden);
4625
- }
4626
- cache() {
4627
- this._cache = this.columns.map(subject => {
4628
- const value = { ...subject.value };
4629
- delete value.changes;
4630
- return value;
4631
- });
4632
- }
4633
- hasCache() {
4634
- return !!this._cache.length;
4635
- }
4636
- resetToLastCache() {
4637
- this._cache.forEach((state, index) => {
4638
- // Just emit the exact value from the cache
4639
- const cachedState = { ...state, changes: ALL_COLUMN_CHANGES };
4640
- this.columns[index].next(cachedState);
4641
- this.columnsStateChange.next(cachedState);
4642
- });
4643
- this._cache = [];
4644
- }
4645
- // Helper method to emit a change to a column only when there is an actual diff to process for that column
4646
- emitStateChangeAt(columnIndex, diff) {
4647
- if (!this.columns[columnIndex]) {
4648
- return;
4649
- }
4650
- this.emitStateChange(this.columns[columnIndex], diff);
4651
- }
4652
- emitStateChange(column, diff) {
4653
- const changedState = { ...column.value, ...diff };
4654
- column.next(changedState);
4655
- this.columnsStateChange.next(changedState);
4656
- }
4657
- static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.1.3", ngImport: i0, type: ColumnsService, deps: [], target: i0.ɵɵFactoryTarget.Injectable }); }
4658
- static { this.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "21.1.3", ngImport: i0, type: ColumnsService }); }
4659
- }
4660
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.1.3", ngImport: i0, type: ColumnsService, decorators: [{
4661
- type: Injectable
4662
- }] });
4663
4952
 
4664
4953
  /*
4665
4954
  * Copyright (c) 2016-2026 Broadcom. All Rights Reserved.
@@ -4721,10 +5010,10 @@ class StateProvider {
4721
5010
  }
4722
5011
  return state;
4723
5012
  }
4724
- static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.1.3", ngImport: i0, type: StateProvider, deps: [{ token: FiltersProvider }, { token: Sort }, { token: Page }, { token: StateDebouncer }], target: i0.ɵɵFactoryTarget.Injectable }); }
4725
- static { this.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "21.1.3", ngImport: i0, type: StateProvider }); }
5013
+ static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.25", ngImport: i0, type: StateProvider, deps: [{ token: FiltersProvider }, { token: Sort }, { token: Page }, { token: StateDebouncer }], target: i0.ɵɵFactoryTarget.Injectable }); }
5014
+ static { this.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "21.2.25", ngImport: i0, type: StateProvider }); }
4726
5015
  }
4727
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.1.3", ngImport: i0, type: StateProvider, decorators: [{
5016
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.25", ngImport: i0, type: StateProvider, decorators: [{
4728
5017
  type: Injectable
4729
5018
  }], ctorParameters: () => [{ type: FiltersProvider }, { type: Sort }, { type: Page }, { type: StateDebouncer }] });
4730
5019
 
@@ -4750,6 +5039,7 @@ class DatagridCellRenderer {
4750
5039
  resetState(state) {
4751
5040
  this.setWidth(state);
4752
5041
  this.setHidden(state);
5042
+ this.setPinned(state);
4753
5043
  }
4754
5044
  setWidth(state) {
4755
5045
  if (state.strictWidth) {
@@ -4768,14 +5058,22 @@ class DatagridCellRenderer {
4768
5058
  this.renderer.removeClass(this.el.nativeElement, HIDDEN_COLUMN_CLASS);
4769
5059
  }
4770
5060
  }
5061
+ setPinned(state) {
5062
+ if (state.pinned) {
5063
+ this.renderer.addClass(this.el.nativeElement, PINNED_COLUMN_CLASS);
5064
+ }
5065
+ else {
5066
+ this.renderer.removeClass(this.el.nativeElement, PINNED_COLUMN_CLASS);
5067
+ }
5068
+ }
4771
5069
  clearWidth() {
4772
5070
  this.renderer.removeClass(this.el.nativeElement, STRICT_WIDTH_CLASS);
4773
5071
  this.renderer.setStyle(this.el.nativeElement, 'width', null);
4774
5072
  }
4775
- static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.1.3", ngImport: i0, type: DatagridCellRenderer, deps: [{ token: i0.ElementRef }, { token: i0.Renderer2 }, { token: DatagridRenderOrganizer }], target: i0.ɵɵFactoryTarget.Directive }); }
4776
- static { this.ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "14.0.0", version: "21.1.3", type: DatagridCellRenderer, isStandalone: false, selector: "clr-dg-cell", ngImport: i0 }); }
5073
+ static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.25", ngImport: i0, type: DatagridCellRenderer, deps: [{ token: i0.ElementRef }, { token: i0.Renderer2 }, { token: DatagridRenderOrganizer }], target: i0.ɵɵFactoryTarget.Directive }); }
5074
+ static { this.ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "14.0.0", version: "21.2.25", type: DatagridCellRenderer, isStandalone: false, selector: "clr-dg-cell", ngImport: i0 }); }
4777
5075
  }
4778
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.1.3", ngImport: i0, type: DatagridCellRenderer, decorators: [{
5076
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.25", ngImport: i0, type: DatagridCellRenderer, decorators: [{
4779
5077
  type: Directive,
4780
5078
  args: [{
4781
5079
  selector: 'clr-dg-cell',
@@ -4842,10 +5140,10 @@ class DatagridRowRenderer {
4842
5140
  }
4843
5141
  }));
4844
5142
  }
4845
- static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.1.3", ngImport: i0, type: DatagridRowRenderer, deps: [{ token: ColumnsService }, { token: i0.ElementRef }], target: i0.ɵɵFactoryTarget.Directive }); }
4846
- static { this.ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "14.0.0", version: "21.1.3", type: DatagridRowRenderer, isStandalone: false, selector: "clr-dg-row", queries: [{ propertyName: "cells", predicate: DatagridCellRenderer }], ngImport: i0 }); }
5143
+ static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.25", ngImport: i0, type: DatagridRowRenderer, deps: [{ token: ColumnsService }, { token: i0.ElementRef }], target: i0.ɵɵFactoryTarget.Directive }); }
5144
+ static { this.ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "14.0.0", version: "21.2.25", type: DatagridRowRenderer, isStandalone: false, selector: "clr-dg-row", queries: [{ propertyName: "cells", predicate: DatagridCellRenderer }], ngImport: i0 }); }
4847
5145
  }
4848
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.1.3", ngImport: i0, type: DatagridRowRenderer, decorators: [{
5146
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.25", ngImport: i0, type: DatagridRowRenderer, decorators: [{
4849
5147
  type: Directive,
4850
5148
  args: [{
4851
5149
  selector: 'clr-dg-row',
@@ -4863,10 +5161,10 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.1.3", ngImpor
4863
5161
  * The full license information can be found in LICENSE in the root directory of this project.
4864
5162
  */
4865
5163
  class DatagridWillyWonka extends WillyWonka {
4866
- static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.1.3", ngImport: i0, type: DatagridWillyWonka, deps: null, target: i0.ɵɵFactoryTarget.Directive }); }
4867
- static { this.ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "14.0.0", version: "21.1.3", type: DatagridWillyWonka, isStandalone: false, selector: "clr-datagrid", usesInheritance: true, ngImport: i0 }); }
5164
+ static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.25", ngImport: i0, type: DatagridWillyWonka, deps: null, target: i0.ɵɵFactoryTarget.Directive }); }
5165
+ static { this.ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "14.0.0", version: "21.2.25", type: DatagridWillyWonka, isStandalone: false, selector: "clr-datagrid", usesInheritance: true, ngImport: i0 }); }
4868
5166
  }
4869
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.1.3", ngImport: i0, type: DatagridWillyWonka, decorators: [{
5167
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.25", ngImport: i0, type: DatagridWillyWonka, decorators: [{
4870
5168
  type: Directive,
4871
5169
  args: [{
4872
5170
  selector: 'clr-datagrid',
@@ -4891,10 +5189,10 @@ class ActionableOompaLoompa extends OompaLoompa {
4891
5189
  get flavor() {
4892
5190
  return this.rowActions.hasActionableRow;
4893
5191
  }
4894
- static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.1.3", ngImport: i0, type: ActionableOompaLoompa, deps: [{ token: i0.ChangeDetectorRef }, { token: DatagridWillyWonka, optional: true }, { token: RowActionService }], target: i0.ɵɵFactoryTarget.Directive }); }
4895
- static { this.ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "14.0.0", version: "21.1.3", type: ActionableOompaLoompa, isStandalone: false, selector: "clr-datagrid, clr-dg-row", usesInheritance: true, ngImport: i0 }); }
5192
+ static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.25", ngImport: i0, type: ActionableOompaLoompa, deps: [{ token: i0.ChangeDetectorRef }, { token: DatagridWillyWonka, optional: true }, { token: RowActionService }], target: i0.ɵɵFactoryTarget.Directive }); }
5193
+ static { this.ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "14.0.0", version: "21.2.25", type: ActionableOompaLoompa, isStandalone: false, selector: "clr-datagrid, clr-dg-row", usesInheritance: true, ngImport: i0 }); }
4896
5194
  }
4897
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.1.3", ngImport: i0, type: ActionableOompaLoompa, decorators: [{
5195
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.25", ngImport: i0, type: ActionableOompaLoompa, decorators: [{
4898
5196
  type: Directive,
4899
5197
  args: [{
4900
5198
  selector: 'clr-datagrid, clr-dg-row',
@@ -4921,10 +5219,10 @@ class ExpandableOompaLoompa extends OompaLoompa {
4921
5219
  get flavor() {
4922
5220
  return this.expandableCount.hasExpandableRow;
4923
5221
  }
4924
- static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.1.3", ngImport: i0, type: ExpandableOompaLoompa, deps: [{ token: i0.ChangeDetectorRef }, { token: DatagridWillyWonka, optional: true }, { token: ExpandableRowsCount }], target: i0.ɵɵFactoryTarget.Directive }); }
4925
- static { this.ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "14.0.0", version: "21.1.3", type: ExpandableOompaLoompa, isStandalone: false, selector: "clr-datagrid, clr-dg-row", usesInheritance: true, ngImport: i0 }); }
5222
+ static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.25", ngImport: i0, type: ExpandableOompaLoompa, deps: [{ token: i0.ChangeDetectorRef }, { token: DatagridWillyWonka, optional: true }, { token: ExpandableRowsCount }], target: i0.ɵɵFactoryTarget.Directive }); }
5223
+ static { this.ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "14.0.0", version: "21.2.25", type: ExpandableOompaLoompa, isStandalone: false, selector: "clr-datagrid, clr-dg-row", usesInheritance: true, ngImport: i0 }); }
4926
5224
  }
4927
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.1.3", ngImport: i0, type: ExpandableOompaLoompa, decorators: [{
5225
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.25", ngImport: i0, type: ExpandableOompaLoompa, decorators: [{
4928
5226
  type: Directive,
4929
5227
  args: [{
4930
5228
  selector: 'clr-datagrid, clr-dg-row',
@@ -4941,7 +5239,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.1.3", ngImpor
4941
5239
  * The full license information can be found in LICENSE in the root directory of this project.
4942
5240
  */
4943
5241
  class ClrDatagrid {
4944
- constructor(organizer, items, expandableRows, selection, rowActionService, stateProvider, displayMode, renderer, detailService, document, el, page, commonStrings, keyNavigation, zone) {
5242
+ constructor(organizer, items, expandableRows, selection, rowActionService, stateProvider, displayMode, renderer, detailService, document, el, page, commonStrings, keyNavigation, zone, columnsService) {
4945
5243
  this.organizer = organizer;
4946
5244
  this.items = items;
4947
5245
  this.expandableRows = expandableRows;
@@ -4957,6 +5255,7 @@ class ClrDatagrid {
4957
5255
  this.commonStrings = commonStrings;
4958
5256
  this.keyNavigation = keyNavigation;
4959
5257
  this.zone = zone;
5258
+ this.columnsService = columnsService;
4960
5259
  this.clrDgSingleSelectionAriaLabel = this.commonStrings.keys.singleSelectionAriaLabel;
4961
5260
  this.clrDgSingleActionableAriaLabel = this.commonStrings.keys.singleActionableAriaLabel;
4962
5261
  this.clrDetailExpandableAriaLabel = this.commonStrings.keys.detailExpandableAriaLabel;
@@ -4980,6 +5279,13 @@ class ClrDatagrid {
4980
5279
  */
4981
5280
  this._subscriptions = [];
4982
5281
  this._virtualScrollSubscriptions = [];
5282
+ /**
5283
+ * The placeholder columns we create from `fixedColumnTemplate` for the calculate pass. Unlike
5284
+ * the column views, which belong to their `WrappedColumn`, these are created here on every
5285
+ * pass, so they are ours to destroy. Detaching them from the container only unlinks them - the
5286
+ * views themselves would stay alive and keep the whole datagrid in memory.
5287
+ */
5288
+ this.fixedColumnViews = [];
4983
5289
  this.cachedRowsHeight = 0;
4984
5290
  this.cachedContentHeight = 0;
4985
5291
  this.resizeObserver = new ResizeObserver(entries => {
@@ -4987,6 +5293,11 @@ class ClrDatagrid {
4987
5293
  this.handleResizeChanges(entries);
4988
5294
  });
4989
5295
  });
5296
+ /**
5297
+ * Watches the row controls for anything that changes their width without going through a render
5298
+ * cycle - a density change, or an application restyling them.
5299
+ */
5300
+ this.rowControlsObserver = new ResizeObserver(() => this.updateRowControlsWidth());
4990
5301
  const datagridId = uniqueIdFactory();
4991
5302
  this.selectAllId = 'clr-dg-select-all-' + datagridId;
4992
5303
  detailService.id = datagridId;
@@ -5060,6 +5371,9 @@ class ClrDatagrid {
5060
5371
  get virtualScroll() {
5061
5372
  return this._virtualScroll?.get(0);
5062
5373
  }
5374
+ get isDetailOverlay() {
5375
+ return this.detailService.detailWidth === MAX_DETAIL_WIDTH;
5376
+ }
5063
5377
  ngAfterContentInit() {
5064
5378
  if (!this.items.smart) {
5065
5379
  this.items.all = this.rows.map((row) => row.item);
@@ -5109,6 +5423,7 @@ class ClrDatagrid {
5109
5423
  ngAfterViewInit() {
5110
5424
  this.keyNavigation.initializeKeyGrid(this.el.nativeElement);
5111
5425
  this.updateDetailState();
5426
+ this.zone.runOutsideAngular(() => this.rowControlsObserver.observe(this.rowControls.nativeElement));
5112
5427
  // Emit the state only if it is not an empty object.
5113
5428
  // Default state of `ClrDatagridStateInterface` is an empty object.
5114
5429
  // The refresh emit is needed in Server-driven datagrid when pagination is set, but the data is still not requested.
@@ -5135,7 +5450,12 @@ class ClrDatagrid {
5135
5450
  for (let i = this._projectedDisplayColumns.length; i > 0; i--) {
5136
5451
  this._projectedDisplayColumns.detach();
5137
5452
  }
5453
+ // Remove any projected columns from the projectedStickyColumns container
5454
+ for (let i = this._projectedStickyColumns.length; i > 0; i--) {
5455
+ this._projectedStickyColumns.detach();
5456
+ }
5138
5457
  // Remove any projected columns from the projectedCalculationColumns container
5458
+ this.destroyFixedColumnViews();
5139
5459
  for (let i = this._projectedCalculationColumns.length; i > 0; i--) {
5140
5460
  this._projectedCalculationColumns.detach();
5141
5461
  }
@@ -5150,12 +5470,21 @@ class ClrDatagrid {
5150
5470
  if (viewChange === DatagridDisplayMode.DISPLAY) {
5151
5471
  // Set state, style for the datagrid to DISPLAY and insert row & columns into containers
5152
5472
  this.renderer.removeClass(this.el.nativeElement, 'datagrid-calculate-mode');
5153
- this.columns.forEach(column => {
5154
- this._projectedDisplayColumns.insert(column._view);
5473
+ // Pinned columns go into the pinned container so they stay visible during horizontal
5474
+ // scroll. Iterating in declaration order keeps both groups in their original order,
5475
+ // which is what matches them with the cells of every row.
5476
+ this.columns.forEach((column, index) => {
5477
+ const container = this.columnsService.isPinned(index)
5478
+ ? this._projectedStickyColumns
5479
+ : this._projectedDisplayColumns;
5480
+ container.insert(column._view);
5155
5481
  });
5156
5482
  this.rows.forEach(row => {
5157
5483
  this._displayedRows.insert(row._view);
5158
5484
  });
5485
+ // The row controls are only laid out in this mode, and this is also the point where
5486
+ // their number can have changed.
5487
+ this.updateRowControlsWidth();
5159
5488
  }
5160
5489
  else {
5161
5490
  // Set state, style for the datagrid to CALCULATE and insert row & columns into containers
@@ -5166,9 +5495,11 @@ class ClrDatagrid {
5166
5495
  this.selection.selectionType !== this.SELECTION_TYPE.None,
5167
5496
  this.expandableRows.hasExpandableRow || this.detailService.enabled,
5168
5497
  ];
5169
- fixedColumnConditions
5170
- .filter(Boolean)
5171
- .forEach(() => this._projectedCalculationColumns.insert(this._fixedColumnTemplate.createEmbeddedView(null)));
5498
+ fixedColumnConditions.filter(Boolean).forEach(() => {
5499
+ const fixedColumnView = this._fixedColumnTemplate.createEmbeddedView(null);
5500
+ this.fixedColumnViews.push(fixedColumnView);
5501
+ this._projectedCalculationColumns.insert(fixedColumnView);
5502
+ });
5172
5503
  this.columns.forEach(column => {
5173
5504
  this._projectedCalculationColumns.insert(column._view);
5174
5505
  });
@@ -5200,9 +5531,16 @@ class ClrDatagrid {
5200
5531
  this.selection.checkForChanges();
5201
5532
  }
5202
5533
  ngOnDestroy() {
5534
+ this.destroyFixedColumnViews();
5203
5535
  this._subscriptions.forEach((sub) => sub.unsubscribe());
5204
5536
  this._virtualScrollSubscriptions.forEach((sub) => sub.unsubscribe());
5205
5537
  this.resizeObserver.disconnect();
5538
+ this.rowControlsObserver.disconnect();
5539
+ // If the detail pane is left open, close it so the DetailService unregisters itself from the
5540
+ // root ModalStackService instead of staying referenced there after this datagrid is gone.
5541
+ if (this.detailService.isOpen) {
5542
+ this.detailService.close();
5543
+ }
5206
5544
  }
5207
5545
  toggleAllSelected($event) {
5208
5546
  $event.preventDefault();
@@ -5240,6 +5578,16 @@ class ClrDatagrid {
5240
5578
  dataChanged() {
5241
5579
  this.items.refresh();
5242
5580
  }
5581
+ destroyFixedColumnViews() {
5582
+ // On teardown Angular has already destroyed the views in our container by the time it runs our
5583
+ // `ngOnDestroy`, so only the calculate/display transition has live ones to release here.
5584
+ this.fixedColumnViews.forEach(view => {
5585
+ if (!view.destroyed) {
5586
+ view.destroy();
5587
+ }
5588
+ });
5589
+ this.fixedColumnViews = [];
5590
+ }
5243
5591
  toggleVirtualScrollSubscriptions() {
5244
5592
  const hasVirtualScroll = !!this.virtualScroll;
5245
5593
  // the virtual scroll will handle the scrolling
@@ -5277,6 +5625,42 @@ class ClrDatagrid {
5277
5625
  this._virtualScrollSubscriptions = [];
5278
5626
  }
5279
5627
  }
5628
+ /**
5629
+ * Publishes the width of the row controls - the static container holding the select, action and
5630
+ * caret cells - as a custom property, which is where the pinned columns read the offset they
5631
+ * became static at. They are static right after the controls rather than at the edge of the datagrid,
5632
+ * and `position: sticky` always measures its offsets from that edge, so the distance between the
5633
+ * two has to be measured and handed to the stylesheet.
5634
+ *
5635
+ * The header and the rows get their own value: the header renders one caret column for both
5636
+ * kinds of caret where a row renders one cell per caret, so the two containers are not
5637
+ * necessarily the same width.
5638
+ *
5639
+ * Nothing reads this property unless a column is pinned - `.datagrid-pinned-cells` is the only
5640
+ * consumer, and it is `display: none` while empty - so the measurement is skipped entirely
5641
+ * otherwise. It matters on a datagrid with many rows: `getBoundingClientRect()` forces the
5642
+ * browser to resolve any pending layout first, and on a large datagrid that resolution is not
5643
+ * cheap. Both boxes are read before either write for the same reason - writing the custom
5644
+ * property is itself layout-affecting (`.datagrid-pinned-cells` reads it back for its own
5645
+ * position and width), so reading again in between would force that resolution twice.
5646
+ */
5647
+ updateRowControlsWidth() {
5648
+ const headerControls = this.rowControls?.nativeElement;
5649
+ if (!headerControls || !this.datagridHeader || !this.columnsService.hasPinnedColumns) {
5650
+ return;
5651
+ }
5652
+ const rowControls = this.rowsWrapper.nativeElement.querySelector('.datagrid-row-master > .datagrid-row-sticky:not(.datagrid-row-sticky-scroll)');
5653
+ // Measured from the box rather than from offsetWidth, which is rounded to whole pixels and
5654
+ // would leave the pinned columns off by up to a pixel.
5655
+ const headerWidth = headerControls.getBoundingClientRect().width;
5656
+ // Without a row there is nothing to line up with, so the header is a good enough stand-in.
5657
+ const rowWidth = (rowControls || headerControls).getBoundingClientRect().width;
5658
+ this.setRowControlsWidth(this.datagridHeader.nativeElement, headerWidth);
5659
+ this.setRowControlsWidth(this.rowsWrapper.nativeElement, rowWidth);
5660
+ }
5661
+ setRowControlsWidth(target, width) {
5662
+ this.renderer.setStyle(target, '--clr-datagrid-row-controls-width', `${width}px`, RendererStyleFlags2.DashCase);
5663
+ }
5280
5664
  handleResizeChanges(entries) {
5281
5665
  const rowsWrapper = this.rowsWrapper.nativeElement;
5282
5666
  for (const entry of entries) {
@@ -5295,8 +5679,8 @@ class ClrDatagrid {
5295
5679
  this.renderer.removeClass(rowsWrapper, scrollClass);
5296
5680
  }
5297
5681
  }
5298
- static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.1.3", ngImport: i0, type: ClrDatagrid, deps: [{ token: DatagridRenderOrganizer }, { token: Items }, { token: ExpandableRowsCount }, { token: Selection }, { token: RowActionService }, { token: StateProvider }, { token: DisplayModeService }, { token: i0.Renderer2 }, { token: DetailService }, { token: DOCUMENT }, { token: i0.ElementRef }, { token: Page }, { token: i2.ClrCommonStringsService }, { token: KeyNavigationGridController }, { token: i0.NgZone }], target: i0.ɵɵFactoryTarget.Component }); }
5299
- static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.1.3", type: ClrDatagrid, isStandalone: false, selector: "clr-datagrid", inputs: { loadingMoreItems: ["clrLoadingMoreItems", "loadingMoreItems"], clrDgSingleSelectionAriaLabel: "clrDgSingleSelectionAriaLabel", clrDgSingleActionableAriaLabel: "clrDgSingleActionableAriaLabel", clrDetailExpandableAriaLabel: "clrDetailExpandableAriaLabel", clrDgDisablePageFocus: "clrDgDisablePageFocus", customSelectAllEnabled: ["clrDgCustomSelectAllEnabled", "customSelectAllEnabled"], selectAllDisabled: ["clrDgSelectAllDisabled", "selectAllDisabled"], loading: ["clrDgLoading", "loading"], selectionType: ["clrDgSelectionType", "selectionType", selectionTypeAttribute], selected: ["clrDgSelected", "selected"], clrDgPreserveSelection: "clrDgPreserveSelection", rowSelectionMode: ["clrDgRowSelection", "rowSelectionMode"], identityFn: ["clrDgItemsIdentityFn", "identityFn"] }, outputs: { selectedChanged: "clrDgSelectedChange", refresh: "clrDgRefresh", customSelectAll: "clrDgCustomSelectAll" }, host: { properties: { "class.datagrid-host": "true", "class.datagrid-detail-open": "detailService.isOpen", "class.datagrid-virtual-scroll": "!!virtualScroll" } }, providers: [
5682
+ static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.25", ngImport: i0, type: ClrDatagrid, deps: [{ token: DatagridRenderOrganizer }, { token: Items }, { token: ExpandableRowsCount }, { token: Selection }, { token: RowActionService }, { token: StateProvider }, { token: DisplayModeService }, { token: i0.Renderer2 }, { token: DetailService }, { token: DOCUMENT }, { token: i0.ElementRef }, { token: Page }, { token: i2.ClrCommonStringsService }, { token: KeyNavigationGridController }, { token: i0.NgZone }, { token: ColumnsService }], target: i0.ɵɵFactoryTarget.Component }); }
5683
+ static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.2.25", type: ClrDatagrid, isStandalone: false, selector: "clr-datagrid", inputs: { loadingMoreItems: ["clrLoadingMoreItems", "loadingMoreItems"], clrDgSingleSelectionAriaLabel: "clrDgSingleSelectionAriaLabel", clrDgSingleActionableAriaLabel: "clrDgSingleActionableAriaLabel", clrDetailExpandableAriaLabel: "clrDetailExpandableAriaLabel", clrDgDisablePageFocus: "clrDgDisablePageFocus", customSelectAllEnabled: ["clrDgCustomSelectAllEnabled", "customSelectAllEnabled"], selectAllDisabled: ["clrDgSelectAllDisabled", "selectAllDisabled"], loading: ["clrDgLoading", "loading"], selectionType: ["clrDgSelectionType", "selectionType", selectionTypeAttribute], selected: ["clrDgSelected", "selected"], clrDgPreserveSelection: "clrDgPreserveSelection", rowSelectionMode: ["clrDgRowSelection", "rowSelectionMode"], identityFn: ["clrDgItemsIdentityFn", "identityFn"] }, outputs: { selectedChanged: "clrDgSelectedChange", refresh: "clrDgRefresh", customSelectAll: "clrDgCustomSelectAll" }, host: { properties: { "class.datagrid-host": "true", "class.datagrid-detail-open": "detailService.isOpen", "class.datagrid-detail-overlay": "isDetailOverlay", "class.datagrid-virtual-scroll": "!!virtualScroll" } }, providers: [
5300
5684
  Selection,
5301
5685
  Sort,
5302
5686
  FiltersProvider,
@@ -5312,9 +5696,9 @@ class ClrDatagrid {
5312
5696
  ColumnsService,
5313
5697
  DisplayModeService,
5314
5698
  KeyNavigationGridController,
5315
- ], queries: [{ propertyName: "iterator", first: true, predicate: ClrDatagridItems, descendants: true }, { propertyName: "placeholder", first: true, predicate: ClrDatagridPlaceholder, descendants: true }, { propertyName: "_virtualScroll", predicate: i0.forwardRef(() => ClrDatagridVirtualScrollDirective) }, { propertyName: "columns", predicate: ClrDatagridColumn }, { propertyName: "rows", predicate: ClrDatagridRow, emitDistinctChangesOnly: false }], viewQueries: [{ propertyName: "datagrid", first: true, predicate: ["datagrid"], descendants: true, read: ElementRef }, { propertyName: "datagridTable", first: true, predicate: ["datagridTable"], descendants: true, read: ElementRef }, { propertyName: "datagridHeader", first: true, predicate: ["datagridHeader"], descendants: true, read: ElementRef }, { propertyName: "contentWrapper", first: true, predicate: ["contentWrapper"], descendants: true, read: ElementRef, static: true }, { propertyName: "rowsWrapper", first: true, predicate: ["rowsWrapper"], descendants: true, read: ElementRef, static: true }, { propertyName: "scrollableColumns", first: true, predicate: ["scrollableColumns"], descendants: true, read: ViewContainerRef }, { propertyName: "_projectedDisplayColumns", first: true, predicate: ["projectedDisplayColumns"], descendants: true, read: ViewContainerRef }, { propertyName: "_projectedCalculationColumns", first: true, predicate: ["projectedCalculationColumns"], descendants: true, read: ViewContainerRef }, { propertyName: "_displayedRows", first: true, predicate: ["displayedRows"], descendants: true, read: ViewContainerRef }, { propertyName: "_calculationRows", first: true, predicate: ["calculationRows"], descendants: true, read: ViewContainerRef }, { propertyName: "_fixedColumnTemplate", first: true, predicate: ["fixedColumnTemplate"], descendants: true }, { propertyName: "selectAllCheckbox", first: true, predicate: ["selectAllCheckbox"], descendants: true }, { propertyName: "stickyHeaders", predicate: ["stickyHeader"], descendants: true }], ngImport: i0, template: "<!--\n ~ Copyright (c) 2016-2026 Broadcom. All Rights Reserved.\n ~ The term \"Broadcom\" refers to Broadcom Inc. and/or its subsidiaries.\n ~ This software is released under MIT license.\n ~ The full license information can be found in LICENSE in the root directory of this project.\n -->\n\n<ng-content select=\"clr-dg-action-bar\"></ng-content>\n<div class=\"datagrid-outer-wrapper\">\n <div class=\"datagrid-inner-wrapper\">\n <div class=\"datagrid\" #datagrid [attr.aria-hidden]=\"detailService.isOpen ? true : null\">\n <div class=\"datagrid-table-wrapper\">\n <div role=\"grid\" class=\"datagrid-table\" tabindex=\"-1\" #datagridTable>\n <div role=\"rowgroup\" class=\"datagrid-header\" #datagridHeader>\n <div role=\"row\" class=\"datagrid-row\">\n <div class=\"datagrid-row-master datagrid-row-flex\">\n <div class=\"datagrid-row-sticky\">\n <!--header for datagrid where you can select multiple rows -->\n @if (selection.selectionType === SELECTION_TYPE.Multi) {\n <div\n #stickyHeader\n role=\"columnheader\"\n class=\"datagrid-column datagrid-select datagrid-fixed-column\"\n (keydown.space)=\"toggleAllSelected($event)\"\n >\n @if (!virtualScroll || customSelectAllEnabled) {\n <div class=\"clr-checkbox-wrapper\">\n <!-- We need to move focus and space-key handling to the parent because of keyboard arrow key navigation,\n which is not able to transfer focus directly on the input when focused with the tab key -->\n <input\n #selectAllCheckbox\n type=\"checkbox\"\n [id]=\"selectAllId\"\n [(ngModel)]=\"allSelected\"\n [attr.aria-label]=\"commonStrings.keys.selectAll\"\n tabindex=\"-1\"\n [attr.disabled]=\"selectAllDisabled ? true : null\"\n />\n <!-- Usage of class clr-col-null here prevents clr-col-* classes from being added when a datagrid is wrapped inside clrForm -->\n <label [for]=\"selectAllId\" class=\"clr-control-label clr-col-null\">\n <span class=\"clr-sr-only\">{{commonStrings.keys.selectAll}}</span>\n </label>\n </div>\n }\n <div class=\"datagrid-column-separator\"></div>\n </div>\n }\n <!-- header for datagrid where you can select one row only -->\n @if (selection.selectionType === SELECTION_TYPE.Single) {\n <div #stickyHeader role=\"columnheader\" class=\"datagrid-column datagrid-select datagrid-fixed-column\">\n <div class=\"clr-sr-only\">{{clrDgSingleSelectionAriaLabel}}</div>\n <div class=\"datagrid-column-separator\"></div>\n </div>\n }\n <!-- header for single row action; only displayType if we have at least one actionable row in datagrid -->\n @if (rowActionService.hasActionableRow) {\n <div\n #stickyHeader\n role=\"columnheader\"\n class=\"datagrid-column datagrid-row-actions datagrid-fixed-column\"\n >\n <div class=\"clr-sr-only\">{{clrDgSingleActionableAriaLabel}}</div>\n <div class=\"datagrid-column-separator\"></div>\n </div>\n }\n <!-- header for carets; only displayType if we have at least one expandable row in datagrid -->\n @if (expandableRows.hasExpandableRow || detailService.enabled) {\n <div\n #stickyHeader\n role=\"columnheader\"\n class=\"datagrid-column datagrid-expandable-caret datagrid-fixed-column\"\n >\n <div class=\"clr-sr-only\">{{clrDetailExpandableAriaLabel}}</div>\n <div class=\"datagrid-column-separator\"></div>\n </div>\n }\n </div>\n <div class=\"datagrid-row-scrollable\">\n <ng-container #projectedDisplayColumns></ng-container>\n </div>\n @if (virtualScroll) {\n <div class=\"datagrid-row-sticky datagrid-row-sticky-scroll\">\n <div class=\"datagrid-column\"></div>\n </div>\n }\n </div>\n </div>\n </div>\n\n <div class=\"datagrid-content\" [class.datagrid-content-virtual]=\"virtualScroll\" #contentWrapper>\n @if (virtualScroll) {\n <div class=\"datagrid-content-virtual-spacer\" [style.height]=\"virtualScroll?.totalContentHeight\"></div>\n }\n <div role=\"presentation\" #rowsWrapper class=\"datagrid-rows\">\n @if (loadingMoreItems) {\n <clr-dg-row class=\"datagrid-row-loading\">\n <clr-dg-cell>\n <clr-spinner clrMedium></clr-spinner>\n <span>{{ commonStrings.keys.loading }}</span>\n </clr-dg-cell>\n </clr-dg-row>\n }\n\n <ng-container #displayedRows></ng-container>\n\n @if (loadingMoreItems) {\n <clr-dg-row class=\"datagrid-row-loading\">\n <clr-dg-cell>\n <clr-spinner clrMedium></clr-spinner>\n <span>{{ commonStrings.keys.loading }}</span>\n </clr-dg-cell>\n </clr-dg-row>\n }\n\n <!-- Custom placeholder overrides the default empty one -->\n <ng-content select=\"clr-dg-placeholder\"></ng-content>\n @if (!placeholder) {\n <clr-dg-placeholder></clr-dg-placeholder>\n }\n </div>\n </div>\n </div>\n </div>\n </div>\n <ng-content select=\"clr-dg-footer\"></ng-content>\n @if (loading) {\n <div class=\"datagrid-spinner\">\n <clr-spinner clrMedium>Loading</clr-spinner>\n </div>\n }\n </div>\n <ng-content select=\"[clrIfDetail],clr-dg-detail\"></ng-content>\n</div>\n\n<div class=\"datagrid-calculation-table\">\n <div class=\"datagrid-calculation-header\">\n <ng-container #projectedCalculationColumns></ng-container>\n </div>\n <ng-container #calculationRows></ng-container>\n</div>\n\n<ng-template #fixedColumnTemplate>\n <div class=\"datagrid-column datagrid-fixed-column\"></div>\n</ng-template>\n", dependencies: [{ kind: "directive", type: i4.ClrControlLabel, selector: "label", inputs: ["id", "for"] }, { kind: "directive", type: i13.CheckboxControlValueAccessor, selector: "input[type=checkbox][formControlName],input[type=checkbox][formControl],input[type=checkbox][ngModel]" }, { kind: "directive", type: i13.NgControlStatus, selector: "[formControlName],[ngModel],[formControl]" }, { kind: "directive", type: i13.NgModel, selector: "[ngModel]:not([formControlName]):not([formControl])", inputs: ["name", "disabled", "ngModel", "ngModelOptions"], outputs: ["ngModelChange"], exportAs: ["ngModel"] }, { kind: "component", type: i14.ClrSpinner, selector: "clr-spinner", inputs: ["clrInline", "clrInverse", "clrSmall", "clrMedium"] }, { kind: "component", type: ClrDatagridCell, selector: "clr-dg-cell" }, { kind: "component", type: ClrDatagridPlaceholder, selector: "clr-dg-placeholder" }, { kind: "component", type: ClrDatagridRow, selector: "clr-dg-row", inputs: ["clrDgDetailDisabled", "clrDgDetailHidden", "clrDgSkeletonLoading", "clrDgItem", "clrDgSelectable", "clrDgSelected", "clrDgExpanded", "clrDgDetailOpenLabel", "clrDgDetailCloseLabel", "clrDgRowSelectionLabel"], outputs: ["clrDgSelectedChange", "clrDgExpandedChange"] }, { kind: "directive", type: ClrDatagridSelectionCellDirective, selector: ".datagrid-select" }, { kind: "directive", type: DatagridCellRenderer, selector: "clr-dg-cell" }, { kind: "directive", type: DatagridRowRenderer, selector: "clr-dg-row" }, { kind: "directive", type: ActionableOompaLoompa, selector: "clr-datagrid, clr-dg-row" }, { kind: "directive", type: ExpandableOompaLoompa, selector: "clr-datagrid, clr-dg-row" }] }); }
5699
+ ], queries: [{ propertyName: "iterator", first: true, predicate: ClrDatagridItems, descendants: true }, { propertyName: "placeholder", first: true, predicate: ClrDatagridPlaceholder, descendants: true }, { propertyName: "_virtualScroll", predicate: i0.forwardRef(() => ClrDatagridVirtualScrollDirective) }, { propertyName: "columns", predicate: ClrDatagridColumn }, { propertyName: "rows", predicate: ClrDatagridRow, emitDistinctChangesOnly: false }], viewQueries: [{ propertyName: "datagrid", first: true, predicate: ["datagrid"], descendants: true, read: ElementRef }, { propertyName: "datagridTable", first: true, predicate: ["datagridTable"], descendants: true, read: ElementRef }, { propertyName: "datagridHeader", first: true, predicate: ["datagridHeader"], descendants: true, read: ElementRef }, { propertyName: "contentWrapper", first: true, predicate: ["contentWrapper"], descendants: true, read: ElementRef, static: true }, { propertyName: "rowsWrapper", first: true, predicate: ["rowsWrapper"], descendants: true, read: ElementRef, static: true }, { propertyName: "scrollableColumns", first: true, predicate: ["scrollableColumns"], descendants: true, read: ViewContainerRef }, { propertyName: "_projectedDisplayColumns", first: true, predicate: ["projectedDisplayColumns"], descendants: true, read: ViewContainerRef }, { propertyName: "_projectedStickyColumns", first: true, predicate: ["projectedStickyColumns"], descendants: true, read: ViewContainerRef }, { propertyName: "_projectedCalculationColumns", first: true, predicate: ["projectedCalculationColumns"], descendants: true, read: ViewContainerRef }, { propertyName: "_displayedRows", first: true, predicate: ["displayedRows"], descendants: true, read: ViewContainerRef }, { propertyName: "_calculationRows", first: true, predicate: ["calculationRows"], descendants: true, read: ViewContainerRef }, { propertyName: "_fixedColumnTemplate", first: true, predicate: ["fixedColumnTemplate"], descendants: true }, { propertyName: "selectAllCheckbox", first: true, predicate: ["selectAllCheckbox"], descendants: true }, { propertyName: "rowControls", first: true, predicate: ["rowControls"], descendants: true, read: ElementRef }, { propertyName: "stickyHeaders", predicate: ["stickyHeader"], descendants: true }], ngImport: i0, template: "<!--\n ~ Copyright (c) 2016-2026 Broadcom. All Rights Reserved.\n ~ The term \"Broadcom\" refers to Broadcom Inc. and/or its subsidiaries.\n ~ This software is released under MIT license.\n ~ The full license information can be found in LICENSE in the root directory of this project.\n -->\n\n<ng-content select=\"clr-dg-action-bar\"></ng-content>\n<div class=\"datagrid-outer-wrapper\">\n <div class=\"datagrid-inner-wrapper\">\n <div class=\"datagrid\" #datagrid [attr.aria-hidden]=\"detailService.isOpen ? true : null\">\n <div class=\"datagrid-table-wrapper\">\n <div role=\"grid\" class=\"datagrid-table\" tabindex=\"-1\" #datagridTable>\n <div role=\"rowgroup\" class=\"datagrid-header\" #datagridHeader>\n <div role=\"row\" class=\"datagrid-row\">\n <div class=\"datagrid-row-master datagrid-row-flex\">\n <div class=\"datagrid-row-sticky\" #rowControls>\n <!--header for datagrid where you can select multiple rows -->\n @if (selection.selectionType === SELECTION_TYPE.Multi) {\n <div\n #stickyHeader\n role=\"columnheader\"\n class=\"datagrid-column datagrid-select datagrid-fixed-column\"\n (keydown.space)=\"toggleAllSelected($event)\"\n >\n @if (!virtualScroll || customSelectAllEnabled) {\n <div class=\"clr-checkbox-wrapper\">\n <!-- We need to move focus and space-key handling to the parent because of keyboard arrow key navigation,\n which is not able to transfer focus directly on the input when focused with the tab key -->\n <input\n #selectAllCheckbox\n type=\"checkbox\"\n [id]=\"selectAllId\"\n [(ngModel)]=\"allSelected\"\n [attr.aria-label]=\"commonStrings.keys.selectAll\"\n tabindex=\"-1\"\n [attr.disabled]=\"selectAllDisabled ? true : null\"\n />\n <!-- Usage of class clr-col-null here prevents clr-col-* classes from being added when a datagrid is wrapped inside clrForm -->\n <label [for]=\"selectAllId\" class=\"clr-control-label clr-col-null\">\n <span class=\"clr-sr-only\">{{commonStrings.keys.selectAll}}</span>\n </label>\n </div>\n }\n <div class=\"datagrid-column-separator\"></div>\n </div>\n }\n <!-- header for datagrid where you can select one row only -->\n @if (selection.selectionType === SELECTION_TYPE.Single) {\n <div #stickyHeader role=\"columnheader\" class=\"datagrid-column datagrid-select datagrid-fixed-column\">\n <div class=\"clr-sr-only\">{{clrDgSingleSelectionAriaLabel}}</div>\n <div class=\"datagrid-column-separator\"></div>\n </div>\n }\n <!-- header for single row action; only displayType if we have at least one actionable row in datagrid -->\n @if (rowActionService.hasActionableRow) {\n <div\n #stickyHeader\n role=\"columnheader\"\n class=\"datagrid-column datagrid-row-actions datagrid-fixed-column\"\n >\n <div class=\"clr-sr-only\">{{clrDgSingleActionableAriaLabel}}</div>\n <div class=\"datagrid-column-separator\"></div>\n </div>\n }\n <!-- header for carets; only displayType if we have at least one expandable row in datagrid -->\n @if (expandableRows.hasExpandableRow || detailService.enabled) {\n <div\n #stickyHeader\n role=\"columnheader\"\n class=\"datagrid-column datagrid-expandable-caret datagrid-fixed-column\"\n >\n <div class=\"clr-sr-only\">{{clrDetailExpandableAriaLabel}}</div>\n <div class=\"datagrid-column-separator\"></div>\n </div>\n }\n </div>\n <div class=\"datagrid-row-scrollable\">\n <div class=\"datagrid-pinned-cells\">\n <ng-container #projectedStickyColumns></ng-container>\n </div>\n <ng-container #projectedDisplayColumns></ng-container>\n </div>\n @if (virtualScroll) {\n <div class=\"datagrid-row-sticky datagrid-row-sticky-scroll\">\n <div class=\"datagrid-column\"></div>\n </div>\n }\n </div>\n </div>\n </div>\n\n <div class=\"datagrid-content\" [class.datagrid-content-virtual]=\"virtualScroll\" #contentWrapper>\n @if (virtualScroll) {\n <div class=\"datagrid-content-virtual-spacer\" [style.height]=\"virtualScroll?.totalContentHeight\"></div>\n }\n <div role=\"presentation\" #rowsWrapper class=\"datagrid-rows\">\n @if (loadingMoreItems) {\n <clr-dg-row class=\"datagrid-row-loading\">\n <clr-dg-cell>\n <clr-spinner clrMedium></clr-spinner>\n <span>{{ commonStrings.keys.loading }}</span>\n </clr-dg-cell>\n </clr-dg-row>\n }\n\n <ng-container #displayedRows></ng-container>\n\n @if (loadingMoreItems) {\n <clr-dg-row class=\"datagrid-row-loading\">\n <clr-dg-cell>\n <clr-spinner clrMedium></clr-spinner>\n <span>{{ commonStrings.keys.loading }}</span>\n </clr-dg-cell>\n </clr-dg-row>\n }\n\n <!-- Custom placeholder overrides the default empty one -->\n <ng-content select=\"clr-dg-placeholder\"></ng-content>\n @if (!placeholder) {\n <clr-dg-placeholder></clr-dg-placeholder>\n }\n </div>\n </div>\n </div>\n </div>\n </div>\n <ng-content select=\"clr-dg-footer\"></ng-content>\n @if (loading) {\n <div class=\"datagrid-spinner\">\n <clr-spinner clrMedium>Loading</clr-spinner>\n </div>\n }\n </div>\n <ng-content select=\"[clrIfDetail],clr-dg-detail\"></ng-content>\n</div>\n\n<div class=\"datagrid-calculation-table\">\n <div class=\"datagrid-calculation-header\">\n <ng-container #projectedCalculationColumns></ng-container>\n </div>\n <ng-container #calculationRows></ng-container>\n</div>\n\n<ng-template #fixedColumnTemplate>\n <div class=\"datagrid-column datagrid-fixed-column\"></div>\n</ng-template>\n", dependencies: [{ kind: "directive", type: i4$1.ClrControlLabel, selector: "label", inputs: ["id", "for"] }, { kind: "directive", type: i14.CheckboxControlValueAccessor, selector: "input[type=checkbox][formControlName],input[type=checkbox][formControl],input[type=checkbox][ngModel]" }, { kind: "directive", type: i14.NgControlStatus, selector: "[formControlName],[ngModel],[formControl]" }, { kind: "directive", type: i14.NgModel, selector: "[ngModel]:not([formControlName]):not([formControl])", inputs: ["name", "disabled", "ngModel", "ngModelOptions"], outputs: ["ngModelChange"], exportAs: ["ngModel"] }, { kind: "component", type: i15.ClrSpinner, selector: "clr-spinner", inputs: ["clrInline", "clrInverse", "clrSmall", "clrMedium"] }, { kind: "component", type: ClrDatagridCell, selector: "clr-dg-cell" }, { kind: "component", type: ClrDatagridPlaceholder, selector: "clr-dg-placeholder" }, { kind: "component", type: ClrDatagridRow, selector: "clr-dg-row", inputs: ["clrDgDetailDisabled", "clrDgDetailHidden", "clrDgSkeletonLoading", "clrDgItem", "clrDgSelectable", "clrDgSelected", "clrDgExpanded", "clrDgDetailOpenLabel", "clrDgDetailCloseLabel", "clrDgRowSelectionLabel"], outputs: ["clrDgSelectedChange", "clrDgExpandedChange"] }, { kind: "directive", type: ClrDatagridSelectionCellDirective, selector: ".datagrid-select" }, { kind: "directive", type: DatagridCellRenderer, selector: "clr-dg-cell" }, { kind: "directive", type: DatagridRowRenderer, selector: "clr-dg-row" }, { kind: "directive", type: ActionableOompaLoompa, selector: "clr-datagrid, clr-dg-row" }, { kind: "directive", type: ExpandableOompaLoompa, selector: "clr-datagrid, clr-dg-row" }] }); }
5316
5700
  }
5317
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.1.3", ngImport: i0, type: ClrDatagrid, decorators: [{
5701
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.25", ngImport: i0, type: ClrDatagrid, decorators: [{
5318
5702
  type: Component,
5319
5703
  args: [{ selector: 'clr-datagrid', providers: [
5320
5704
  Selection,
@@ -5335,12 +5719,13 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.1.3", ngImpor
5335
5719
  ], host: {
5336
5720
  '[class.datagrid-host]': 'true',
5337
5721
  '[class.datagrid-detail-open]': 'detailService.isOpen',
5722
+ '[class.datagrid-detail-overlay]': 'isDetailOverlay',
5338
5723
  '[class.datagrid-virtual-scroll]': '!!virtualScroll',
5339
- }, standalone: false, template: "<!--\n ~ Copyright (c) 2016-2026 Broadcom. All Rights Reserved.\n ~ The term \"Broadcom\" refers to Broadcom Inc. and/or its subsidiaries.\n ~ This software is released under MIT license.\n ~ The full license information can be found in LICENSE in the root directory of this project.\n -->\n\n<ng-content select=\"clr-dg-action-bar\"></ng-content>\n<div class=\"datagrid-outer-wrapper\">\n <div class=\"datagrid-inner-wrapper\">\n <div class=\"datagrid\" #datagrid [attr.aria-hidden]=\"detailService.isOpen ? true : null\">\n <div class=\"datagrid-table-wrapper\">\n <div role=\"grid\" class=\"datagrid-table\" tabindex=\"-1\" #datagridTable>\n <div role=\"rowgroup\" class=\"datagrid-header\" #datagridHeader>\n <div role=\"row\" class=\"datagrid-row\">\n <div class=\"datagrid-row-master datagrid-row-flex\">\n <div class=\"datagrid-row-sticky\">\n <!--header for datagrid where you can select multiple rows -->\n @if (selection.selectionType === SELECTION_TYPE.Multi) {\n <div\n #stickyHeader\n role=\"columnheader\"\n class=\"datagrid-column datagrid-select datagrid-fixed-column\"\n (keydown.space)=\"toggleAllSelected($event)\"\n >\n @if (!virtualScroll || customSelectAllEnabled) {\n <div class=\"clr-checkbox-wrapper\">\n <!-- We need to move focus and space-key handling to the parent because of keyboard arrow key navigation,\n which is not able to transfer focus directly on the input when focused with the tab key -->\n <input\n #selectAllCheckbox\n type=\"checkbox\"\n [id]=\"selectAllId\"\n [(ngModel)]=\"allSelected\"\n [attr.aria-label]=\"commonStrings.keys.selectAll\"\n tabindex=\"-1\"\n [attr.disabled]=\"selectAllDisabled ? true : null\"\n />\n <!-- Usage of class clr-col-null here prevents clr-col-* classes from being added when a datagrid is wrapped inside clrForm -->\n <label [for]=\"selectAllId\" class=\"clr-control-label clr-col-null\">\n <span class=\"clr-sr-only\">{{commonStrings.keys.selectAll}}</span>\n </label>\n </div>\n }\n <div class=\"datagrid-column-separator\"></div>\n </div>\n }\n <!-- header for datagrid where you can select one row only -->\n @if (selection.selectionType === SELECTION_TYPE.Single) {\n <div #stickyHeader role=\"columnheader\" class=\"datagrid-column datagrid-select datagrid-fixed-column\">\n <div class=\"clr-sr-only\">{{clrDgSingleSelectionAriaLabel}}</div>\n <div class=\"datagrid-column-separator\"></div>\n </div>\n }\n <!-- header for single row action; only displayType if we have at least one actionable row in datagrid -->\n @if (rowActionService.hasActionableRow) {\n <div\n #stickyHeader\n role=\"columnheader\"\n class=\"datagrid-column datagrid-row-actions datagrid-fixed-column\"\n >\n <div class=\"clr-sr-only\">{{clrDgSingleActionableAriaLabel}}</div>\n <div class=\"datagrid-column-separator\"></div>\n </div>\n }\n <!-- header for carets; only displayType if we have at least one expandable row in datagrid -->\n @if (expandableRows.hasExpandableRow || detailService.enabled) {\n <div\n #stickyHeader\n role=\"columnheader\"\n class=\"datagrid-column datagrid-expandable-caret datagrid-fixed-column\"\n >\n <div class=\"clr-sr-only\">{{clrDetailExpandableAriaLabel}}</div>\n <div class=\"datagrid-column-separator\"></div>\n </div>\n }\n </div>\n <div class=\"datagrid-row-scrollable\">\n <ng-container #projectedDisplayColumns></ng-container>\n </div>\n @if (virtualScroll) {\n <div class=\"datagrid-row-sticky datagrid-row-sticky-scroll\">\n <div class=\"datagrid-column\"></div>\n </div>\n }\n </div>\n </div>\n </div>\n\n <div class=\"datagrid-content\" [class.datagrid-content-virtual]=\"virtualScroll\" #contentWrapper>\n @if (virtualScroll) {\n <div class=\"datagrid-content-virtual-spacer\" [style.height]=\"virtualScroll?.totalContentHeight\"></div>\n }\n <div role=\"presentation\" #rowsWrapper class=\"datagrid-rows\">\n @if (loadingMoreItems) {\n <clr-dg-row class=\"datagrid-row-loading\">\n <clr-dg-cell>\n <clr-spinner clrMedium></clr-spinner>\n <span>{{ commonStrings.keys.loading }}</span>\n </clr-dg-cell>\n </clr-dg-row>\n }\n\n <ng-container #displayedRows></ng-container>\n\n @if (loadingMoreItems) {\n <clr-dg-row class=\"datagrid-row-loading\">\n <clr-dg-cell>\n <clr-spinner clrMedium></clr-spinner>\n <span>{{ commonStrings.keys.loading }}</span>\n </clr-dg-cell>\n </clr-dg-row>\n }\n\n <!-- Custom placeholder overrides the default empty one -->\n <ng-content select=\"clr-dg-placeholder\"></ng-content>\n @if (!placeholder) {\n <clr-dg-placeholder></clr-dg-placeholder>\n }\n </div>\n </div>\n </div>\n </div>\n </div>\n <ng-content select=\"clr-dg-footer\"></ng-content>\n @if (loading) {\n <div class=\"datagrid-spinner\">\n <clr-spinner clrMedium>Loading</clr-spinner>\n </div>\n }\n </div>\n <ng-content select=\"[clrIfDetail],clr-dg-detail\"></ng-content>\n</div>\n\n<div class=\"datagrid-calculation-table\">\n <div class=\"datagrid-calculation-header\">\n <ng-container #projectedCalculationColumns></ng-container>\n </div>\n <ng-container #calculationRows></ng-container>\n</div>\n\n<ng-template #fixedColumnTemplate>\n <div class=\"datagrid-column datagrid-fixed-column\"></div>\n</ng-template>\n" }]
5724
+ }, standalone: false, template: "<!--\n ~ Copyright (c) 2016-2026 Broadcom. All Rights Reserved.\n ~ The term \"Broadcom\" refers to Broadcom Inc. and/or its subsidiaries.\n ~ This software is released under MIT license.\n ~ The full license information can be found in LICENSE in the root directory of this project.\n -->\n\n<ng-content select=\"clr-dg-action-bar\"></ng-content>\n<div class=\"datagrid-outer-wrapper\">\n <div class=\"datagrid-inner-wrapper\">\n <div class=\"datagrid\" #datagrid [attr.aria-hidden]=\"detailService.isOpen ? true : null\">\n <div class=\"datagrid-table-wrapper\">\n <div role=\"grid\" class=\"datagrid-table\" tabindex=\"-1\" #datagridTable>\n <div role=\"rowgroup\" class=\"datagrid-header\" #datagridHeader>\n <div role=\"row\" class=\"datagrid-row\">\n <div class=\"datagrid-row-master datagrid-row-flex\">\n <div class=\"datagrid-row-sticky\" #rowControls>\n <!--header for datagrid where you can select multiple rows -->\n @if (selection.selectionType === SELECTION_TYPE.Multi) {\n <div\n #stickyHeader\n role=\"columnheader\"\n class=\"datagrid-column datagrid-select datagrid-fixed-column\"\n (keydown.space)=\"toggleAllSelected($event)\"\n >\n @if (!virtualScroll || customSelectAllEnabled) {\n <div class=\"clr-checkbox-wrapper\">\n <!-- We need to move focus and space-key handling to the parent because of keyboard arrow key navigation,\n which is not able to transfer focus directly on the input when focused with the tab key -->\n <input\n #selectAllCheckbox\n type=\"checkbox\"\n [id]=\"selectAllId\"\n [(ngModel)]=\"allSelected\"\n [attr.aria-label]=\"commonStrings.keys.selectAll\"\n tabindex=\"-1\"\n [attr.disabled]=\"selectAllDisabled ? true : null\"\n />\n <!-- Usage of class clr-col-null here prevents clr-col-* classes from being added when a datagrid is wrapped inside clrForm -->\n <label [for]=\"selectAllId\" class=\"clr-control-label clr-col-null\">\n <span class=\"clr-sr-only\">{{commonStrings.keys.selectAll}}</span>\n </label>\n </div>\n }\n <div class=\"datagrid-column-separator\"></div>\n </div>\n }\n <!-- header for datagrid where you can select one row only -->\n @if (selection.selectionType === SELECTION_TYPE.Single) {\n <div #stickyHeader role=\"columnheader\" class=\"datagrid-column datagrid-select datagrid-fixed-column\">\n <div class=\"clr-sr-only\">{{clrDgSingleSelectionAriaLabel}}</div>\n <div class=\"datagrid-column-separator\"></div>\n </div>\n }\n <!-- header for single row action; only displayType if we have at least one actionable row in datagrid -->\n @if (rowActionService.hasActionableRow) {\n <div\n #stickyHeader\n role=\"columnheader\"\n class=\"datagrid-column datagrid-row-actions datagrid-fixed-column\"\n >\n <div class=\"clr-sr-only\">{{clrDgSingleActionableAriaLabel}}</div>\n <div class=\"datagrid-column-separator\"></div>\n </div>\n }\n <!-- header for carets; only displayType if we have at least one expandable row in datagrid -->\n @if (expandableRows.hasExpandableRow || detailService.enabled) {\n <div\n #stickyHeader\n role=\"columnheader\"\n class=\"datagrid-column datagrid-expandable-caret datagrid-fixed-column\"\n >\n <div class=\"clr-sr-only\">{{clrDetailExpandableAriaLabel}}</div>\n <div class=\"datagrid-column-separator\"></div>\n </div>\n }\n </div>\n <div class=\"datagrid-row-scrollable\">\n <div class=\"datagrid-pinned-cells\">\n <ng-container #projectedStickyColumns></ng-container>\n </div>\n <ng-container #projectedDisplayColumns></ng-container>\n </div>\n @if (virtualScroll) {\n <div class=\"datagrid-row-sticky datagrid-row-sticky-scroll\">\n <div class=\"datagrid-column\"></div>\n </div>\n }\n </div>\n </div>\n </div>\n\n <div class=\"datagrid-content\" [class.datagrid-content-virtual]=\"virtualScroll\" #contentWrapper>\n @if (virtualScroll) {\n <div class=\"datagrid-content-virtual-spacer\" [style.height]=\"virtualScroll?.totalContentHeight\"></div>\n }\n <div role=\"presentation\" #rowsWrapper class=\"datagrid-rows\">\n @if (loadingMoreItems) {\n <clr-dg-row class=\"datagrid-row-loading\">\n <clr-dg-cell>\n <clr-spinner clrMedium></clr-spinner>\n <span>{{ commonStrings.keys.loading }}</span>\n </clr-dg-cell>\n </clr-dg-row>\n }\n\n <ng-container #displayedRows></ng-container>\n\n @if (loadingMoreItems) {\n <clr-dg-row class=\"datagrid-row-loading\">\n <clr-dg-cell>\n <clr-spinner clrMedium></clr-spinner>\n <span>{{ commonStrings.keys.loading }}</span>\n </clr-dg-cell>\n </clr-dg-row>\n }\n\n <!-- Custom placeholder overrides the default empty one -->\n <ng-content select=\"clr-dg-placeholder\"></ng-content>\n @if (!placeholder) {\n <clr-dg-placeholder></clr-dg-placeholder>\n }\n </div>\n </div>\n </div>\n </div>\n </div>\n <ng-content select=\"clr-dg-footer\"></ng-content>\n @if (loading) {\n <div class=\"datagrid-spinner\">\n <clr-spinner clrMedium>Loading</clr-spinner>\n </div>\n }\n </div>\n <ng-content select=\"[clrIfDetail],clr-dg-detail\"></ng-content>\n</div>\n\n<div class=\"datagrid-calculation-table\">\n <div class=\"datagrid-calculation-header\">\n <ng-container #projectedCalculationColumns></ng-container>\n </div>\n <ng-container #calculationRows></ng-container>\n</div>\n\n<ng-template #fixedColumnTemplate>\n <div class=\"datagrid-column datagrid-fixed-column\"></div>\n</ng-template>\n" }]
5340
5725
  }], ctorParameters: () => [{ type: DatagridRenderOrganizer }, { type: Items }, { type: ExpandableRowsCount }, { type: Selection }, { type: RowActionService }, { type: StateProvider }, { type: DisplayModeService }, { type: i0.Renderer2 }, { type: DetailService }, { type: undefined, decorators: [{
5341
5726
  type: Inject,
5342
5727
  args: [DOCUMENT]
5343
- }] }, { type: i0.ElementRef }, { type: Page }, { type: i2.ClrCommonStringsService }, { type: KeyNavigationGridController }, { type: i0.NgZone }], propDecorators: { loadingMoreItems: [{
5728
+ }] }, { type: i0.ElementRef }, { type: Page }, { type: i2.ClrCommonStringsService }, { type: KeyNavigationGridController }, { type: i0.NgZone }, { type: ColumnsService }], propDecorators: { loadingMoreItems: [{
5344
5729
  type: Input,
5345
5730
  args: ['clrLoadingMoreItems']
5346
5731
  }], clrDgSingleSelectionAriaLabel: [{
@@ -5402,6 +5787,9 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.1.3", ngImpor
5402
5787
  }], _projectedDisplayColumns: [{
5403
5788
  type: ViewChild,
5404
5789
  args: ['projectedDisplayColumns', { read: ViewContainerRef }]
5790
+ }], _projectedStickyColumns: [{
5791
+ type: ViewChild,
5792
+ args: ['projectedStickyColumns', { read: ViewContainerRef }]
5405
5793
  }], _projectedCalculationColumns: [{
5406
5794
  type: ViewChild,
5407
5795
  args: ['projectedCalculationColumns', { read: ViewContainerRef }]
@@ -5420,6 +5808,9 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.1.3", ngImpor
5420
5808
  }], selectAllCheckbox: [{
5421
5809
  type: ViewChild,
5422
5810
  args: ['selectAllCheckbox']
5811
+ }], rowControls: [{
5812
+ type: ViewChild,
5813
+ args: ['rowControls', { read: ElementRef }]
5423
5814
  }], loading: [{
5424
5815
  type: Input,
5425
5816
  args: ['clrDgLoading']
@@ -5446,10 +5837,10 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.1.3", ngImpor
5446
5837
  * The full license information can be found in LICENSE in the root directory of this project.
5447
5838
  */
5448
5839
  class ClrDatagridActionBar {
5449
- static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.1.3", ngImport: i0, type: ClrDatagridActionBar, deps: [], target: i0.ɵɵFactoryTarget.Component }); }
5450
- static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "21.1.3", type: ClrDatagridActionBar, isStandalone: false, selector: "clr-dg-action-bar", host: { properties: { "class.datagrid-action-bar": "true" } }, ngImport: i0, template: `<ng-content></ng-content>`, isInline: true }); }
5840
+ static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.25", ngImport: i0, type: ClrDatagridActionBar, deps: [], target: i0.ɵɵFactoryTarget.Component }); }
5841
+ static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "21.2.25", type: ClrDatagridActionBar, isStandalone: false, selector: "clr-dg-action-bar", host: { properties: { "class.datagrid-action-bar": "true" } }, ngImport: i0, template: `<ng-content></ng-content>`, isInline: true }); }
5451
5842
  }
5452
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.1.3", ngImport: i0, type: ClrDatagridActionBar, decorators: [{
5843
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.25", ngImport: i0, type: ClrDatagridActionBar, decorators: [{
5453
5844
  type: Component,
5454
5845
  args: [{
5455
5846
  selector: 'clr-dg-action-bar',
@@ -5520,8 +5911,8 @@ class ClrDatagridActionOverflow {
5520
5911
  }
5521
5912
  }
5522
5913
  }
5523
- static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.1.3", ngImport: i0, type: ClrDatagridActionOverflow, deps: [{ token: RowActionService }, { token: i2.ClrCommonStringsService }, { token: PLATFORM_ID }, { token: i3.ClrPopoverService }], target: i0.ɵɵFactoryTarget.Component }); }
5524
- static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "21.1.3", type: ClrDatagridActionOverflow, isStandalone: false, selector: "clr-dg-action-overflow", inputs: { buttonLabel: ["clrDgActionOverflowButtonLabel", "buttonLabel"], open: ["clrDgActionOverflowOpen", "open"] }, outputs: { openChange: "clrDgActionOverflowOpenChange" }, viewQueries: [{ propertyName: "keyFocus", first: true, predicate: ClrKeyFocus, descendants: true }], hostDirectives: [{ directive: i3.ClrPopoverHostDirective }], ngImport: i0, template: `
5914
+ static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.25", ngImport: i0, type: ClrDatagridActionOverflow, deps: [{ token: RowActionService }, { token: i2.ClrCommonStringsService }, { token: PLATFORM_ID }, { token: i3.ClrPopoverService }], target: i0.ɵɵFactoryTarget.Component }); }
5915
+ static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "21.2.25", type: ClrDatagridActionOverflow, isStandalone: false, selector: "clr-dg-action-overflow", inputs: { buttonLabel: ["clrDgActionOverflowButtonLabel", "buttonLabel"], open: ["clrDgActionOverflowOpen", "open"] }, outputs: { openChange: "clrDgActionOverflowOpenChange" }, viewQueries: [{ propertyName: "keyFocus", first: true, predicate: ClrKeyFocus, descendants: true }], hostDirectives: [{ directive: i3.ClrPopoverHostDirective }], ngImport: i0, template: `
5525
5916
  <button
5526
5917
  tabindex="-1"
5527
5918
  class="datagrid-action-toggle"
@@ -5557,9 +5948,9 @@ class ClrDatagridActionOverflow {
5557
5948
  >
5558
5949
  <ng-content></ng-content>
5559
5950
  </div>
5560
- `, isInline: true, dependencies: [{ kind: "directive", type: i2.CdkTrapFocusModule_CdkTrapFocus, selector: "[cdkTrapFocus]" }, { kind: "component", type: i5.ClrIcon, selector: "clr-icon, cds-icon", inputs: ["shape", "size", "direction", "flip", "solid", "status", "inverse", "badge"] }, { kind: "directive", type: i3.ClrPopoverOrigin, selector: "[clrPopoverOrigin]" }, { kind: "directive", type: i3.ClrPopoverOpenCloseButton, selector: "[clrPopoverOpenCloseButton]", outputs: ["clrPopoverOpenCloseChange"] }, { kind: "directive", type: i3.ClrPopoverContent, selector: "[clrPopoverContent]", inputs: ["clrPopoverContent", "clrPopoverContentAt", "clrPopoverContentAvailablePositions", "clrPopoverContentType", "clrPopoverContentOutsideClickToClose", "clrPopoverContentScrollToClose", "clrPopoverContentOrigin"] }, { kind: "component", type: i2.ClrKeyFocus, selector: "[clrKeyFocus]", inputs: ["clrDirection", "clrFocusOnLoad", "clrKeyFocus"], outputs: ["clrFocusChange"] }] }); }
5951
+ `, isInline: true, dependencies: [{ kind: "directive", type: i2.CdkTrapFocusModule_CdkTrapFocus, selector: "[cdkTrapFocus]" }, { kind: "component", type: i4.ClrIcon, selector: "clr-icon, cds-icon", inputs: ["shape", "size", "direction", "flip", "solid", "status", "inverse", "badge", "innerOffset"] }, { kind: "directive", type: i3.ClrPopoverOrigin, selector: "[clrPopoverOrigin]" }, { kind: "directive", type: i3.ClrPopoverOpenCloseButton, selector: "[clrPopoverOpenCloseButton]", outputs: ["clrPopoverOpenCloseChange"] }, { kind: "directive", type: i3.ClrPopoverContent, selector: "[clrPopoverContent]", inputs: ["clrPopoverContent", "clrPopoverContentAt", "clrPopoverContentAvailablePositions", "clrPopoverContentType", "clrPopoverContentOutsideClickToClose", "clrPopoverContentScrollToClose", "clrPopoverContentOrigin"] }, { kind: "component", type: i2.ClrKeyFocus, selector: "[clrKeyFocus]", inputs: ["clrDirection", "clrFocusOnLoad", "clrKeyFocus"], outputs: ["clrFocusChange"] }] }); }
5561
5952
  }
5562
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.1.3", ngImport: i0, type: ClrDatagridActionOverflow, decorators: [{
5953
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.25", ngImport: i0, type: ClrDatagridActionOverflow, decorators: [{
5563
5954
  type: Component,
5564
5955
  args: [{
5565
5956
  selector: 'clr-dg-action-overflow',
@@ -5620,6 +6011,591 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.1.3", ngImpor
5620
6011
  args: ['clrDgActionOverflowOpen']
5621
6012
  }] } });
5622
6013
 
6014
+ /*
6015
+ * Copyright (c) 2016-2026 Broadcom. All Rights Reserved.
6016
+ * The term "Broadcom" refers to Broadcom Inc. and/or its subsidiaries.
6017
+ * This software is released under MIT license.
6018
+ * The full license information can be found in LICENSE in the root directory of this project.
6019
+ */
6020
+ /**
6021
+ * The focus handler of the `clr-dg-column-actions` menu, with the items projected into the menu
6022
+ * appended to the ones it declares. ClrDropdownMenu only hands over its own content query, which
6023
+ * cannot see projected items, and it hands it over again whenever that query changes - so the
6024
+ * projected ones are added here, where every one of those hand-overs passes through.
6025
+ */
6026
+ class ColumnActionsFocusHandler extends DropdownFocusHandler {
6027
+ constructor() {
6028
+ super(...arguments);
6029
+ this.ownItems = [];
6030
+ this.projectedItems = [];
6031
+ }
6032
+ addChildren(children) {
6033
+ this.ownItems = children;
6034
+ super.addChildren([...children, ...this.projectedItems]);
6035
+ }
6036
+ // The menu resets its children when it closes, and the items it declared go with it.
6037
+ resetChildren() {
6038
+ this.ownItems = [];
6039
+ super.resetChildren();
6040
+ }
6041
+ setProjectedItems(items) {
6042
+ this.projectedItems = items;
6043
+ this.addChildren(this.ownItems);
6044
+ }
6045
+ static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.25", ngImport: i0, type: ColumnActionsFocusHandler, deps: null, target: i0.ɵɵFactoryTarget.Injectable }); }
6046
+ static { this.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "21.2.25", ngImport: i0, type: ColumnActionsFocusHandler }); }
6047
+ }
6048
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.25", ngImport: i0, type: ColumnActionsFocusHandler, decorators: [{
6049
+ type: Injectable
6050
+ }] });
6051
+
6052
+ /*
6053
+ * Copyright (c) 2016-2026 Broadcom. All Rights Reserved.
6054
+ * The term "Broadcom" refers to Broadcom Inc. and/or its subsidiaries.
6055
+ * This software is released under MIT license.
6056
+ * The full license information can be found in LICENSE in the root directory of this project.
6057
+ */
6058
+ /**
6059
+ * Groups the actions of a single column behind one menu in the column header. It only gathers
6060
+ * controls that already exist on the column - the behavior itself stays on `ClrDatagridColumn`,
6061
+ * so the menu and the header controls can never drift apart.
6062
+ *
6063
+ * Each item is rendered only when the column can actually perform it, so the menu never offers a
6064
+ * dead option - that covers both what the column can never do, such as sorting when it is not
6065
+ * sortable, and what it cannot do right now, such as clearing a sort while nothing is sorted.
6066
+ * Anything projected into the component is appended after the built-in items.
6067
+ *
6068
+ * A column that has a filter gets a filter action automatically, and the filter drops its own toggle
6069
+ * for as long as this menu is present - the header keeps one control per column rather than two. The
6070
+ * trigger also takes over showing that the column is filtered, which the toggle used to do.
6071
+ * `clrDgKeepFilterInHeader` opts back into the toggle, and then the menu drops the filter action in
6072
+ * exchange: a column offers one way to reach its filter, never both at once.
6073
+ *
6074
+ * Projected items can be `clrDgColumnAction`s, plain `clrDropdownItem`s, or a nested `clr-dropdown`.
6075
+ * They join the arrow key order after the built-in items as long as they are projected directly -
6076
+ * an item wrapped in an element of its own is not found. A nested dropdown's own items stay in its
6077
+ * own menu.
6078
+ *
6079
+ * The component is the dropdown itself rather than wrapping one, so that a projected item can reach
6080
+ * it: injection resolves from where a node is declared, and an item declared outside this component
6081
+ * would sit outside the injector of any `clr-dropdown` in its template.
6082
+ */
6083
+ class ClrDatagridColumnActions extends ClrDropdown {
6084
+ constructor(column, commonStrings, columnActions,
6085
+ // The column's own popover service, shared with its filter. This component brings its own for
6086
+ // the menu, so the menu and the filter never fight over one overlay - which is also why this one
6087
+ // has to be resolved from the column rather than from here.
6088
+ columnPopover, changeDetectorRef, injector, filters, parent, popoverService, focusHandler, dropdownService) {
6089
+ super(parent, popoverService, focusHandler, changeDetectorRef, dropdownService);
6090
+ this.column = column;
6091
+ this.commonStrings = commonStrings;
6092
+ this.columnActions = columnActions;
6093
+ this.columnPopover = columnPopover;
6094
+ this.changeDetectorRef = changeDetectorRef;
6095
+ this.injector = injector;
6096
+ this.filters = filters;
6097
+ // Exposed so the template can compare against the enum.
6098
+ this.ClrDatagridSortOrder = ClrDatagridSortOrder;
6099
+ this._keepFilterInHeader = false;
6100
+ // Named for this component rather than inherited: ClrDropdown keeps its own private list.
6101
+ this.subs = [];
6102
+ this.columnActionsFocusHandler = inject(ColumnActionsFocusHandler);
6103
+ this.isMenuClosable = false;
6104
+ // Tells the filter to drop its own toggle - from here on this menu is the only way to open it,
6105
+ // unless clrDgKeepFilterInHeader asked to keep both. Reading the backing field rather than the
6106
+ // getter covers the default: Angular only invokes the setter above when the input is actually
6107
+ // bound, and by then the field initializer has already run.
6108
+ columnActions.filterInHeader.set(this._keepFilterInHeader);
6109
+ // Tells the column to drop its pin toggle, since Pin Column is offered here instead.
6110
+ columnActions.menuPresent.set(true);
6111
+ }
6112
+ /**
6113
+ * Keeps the filter's own toggle in the column header instead of moving it into this menu, and the
6114
+ * menu drops its filter action in exchange - a column offers one way to reach its filter at a
6115
+ * time, never two.
6116
+ */
6117
+ get keepFilterInHeader() {
6118
+ return this._keepFilterInHeader;
6119
+ }
6120
+ set keepFilterInHeader(value) {
6121
+ this._keepFilterInHeader = value;
6122
+ this.columnActions.filterInHeader.set(value);
6123
+ }
6124
+ /**
6125
+ * The menu is a live view of the column, so the label has to be read at render time rather than
6126
+ * cached - the column title can change, and so can the sort state it reports.
6127
+ */
6128
+ get triggerLabel() {
6129
+ const title = this.column.titleContainer?.nativeElement.textContent.trim();
6130
+ return title
6131
+ ? this.commonStrings.parse(this.commonStrings.keys.datagridColumnActionsAriaLabel, { COLUMN: title })
6132
+ : this.commonStrings.keys.columnActions;
6133
+ }
6134
+ get sortOrder() {
6135
+ return this.column.sortOrder;
6136
+ }
6137
+ get canClearSort() {
6138
+ return this.sortOrder !== ClrDatagridSortOrder.UNSORTED && !this.column.disableUnsort;
6139
+ }
6140
+ get hasFilter() {
6141
+ return !!this.columnActions.filter();
6142
+ }
6143
+ /**
6144
+ * Hiding the filter toggle also hides the only sign that a column is filtered, so the trigger and
6145
+ * the filter action carry that state instead.
6146
+ */
6147
+ get filterActive() {
6148
+ return !!this.columnActions.filter()?.active && !this.keepFilterInHeader;
6149
+ }
6150
+ /**
6151
+ * Whether the filter this menu opens is open, for the filter action to report the same way the
6152
+ * toggle it replaced did. Read from the column's popover service rather than from the filter,
6153
+ * because that service is what the action opens.
6154
+ */
6155
+ get filterOpen() {
6156
+ return this.columnPopover.open;
6157
+ }
6158
+ /**
6159
+ * The popover the filter action opens, so it can point at what it controls - again the same thing
6160
+ * the replaced toggle pointed at.
6161
+ */
6162
+ get filterPopoverId() {
6163
+ return this.columnActions.filter()?.popoverId ?? null;
6164
+ }
6165
+ /**
6166
+ * The items projected into the menu. The menu's own content query cannot see them, so they are
6167
+ * handed to the focus handler from here.
6168
+ *
6169
+ * Only direct children are queried, not descendants: a nested `clr-dropdown` is one item here - its
6170
+ * focus handler - and the items inside it belong to its own menu, not to this one.
6171
+ */
6172
+ set projectedItems(items) {
6173
+ this.projectedItemsSubscription?.unsubscribe();
6174
+ this.projectedItemsSubscription = items.changes.subscribe(() => this.columnActionsFocusHandler.setProjectedItems(items.toArray()));
6175
+ this.columnActionsFocusHandler.setProjectedItems(items.toArray());
6176
+ }
6177
+ set menuPopoverContent(popoverContent) {
6178
+ this._menuPopoverContent = popoverContent;
6179
+ // A dropdown menu closes on scroll by default. This one stays open so that pinning or
6180
+ // reordering a column - which can itself move the page under the menu - does not also close it.
6181
+ if (popoverContent) {
6182
+ popoverContent.scrollToClose = false;
6183
+ }
6184
+ }
6185
+ ngAfterViewInit() {
6186
+ // The trigger and the filter action show whether the column is filtered, and this component is
6187
+ // OnPush, so it has to be told when a filter value changes.
6188
+ if (this.filters) {
6189
+ this.subs.push(this.filters.change.subscribe(() => this.changeDetectorRef.markForCheck()));
6190
+ }
6191
+ // Same for the filter action reporting whether the filter is open: opening it goes through this
6192
+ // template and refreshes the view on its own, but closing it does not - that is an outside click
6193
+ // or an escape key handled by the overlay, and the item would be left announcing itself expanded.
6194
+ this.subs.push(this.columnPopover.openChange.subscribe(open => {
6195
+ this.changeDetectorRef.markForCheck();
6196
+ // openFilter() links the filter's popover to this menu's so they scroll together.
6197
+ // Clearing it here keeps the link scoped to one filter opening.
6198
+ if (!open) {
6199
+ this.columnPopover.parent = null;
6200
+ }
6201
+ }));
6202
+ }
6203
+ ngOnDestroy() {
6204
+ super.ngOnDestroy();
6205
+ this.subs.forEach(sub => sub.unsubscribe());
6206
+ this.projectedItemsSubscription?.unsubscribe();
6207
+ // Hands the filter and the pin their own toggles back, in case the menu is removed while the
6208
+ // column stays.
6209
+ this.columnActions.filterInHeader.set(true);
6210
+ this.columnActions.menuPresent.set(false);
6211
+ // doesn't really matter who the current column popover parent is. The original value is null returning it to that.
6212
+ this.columnPopover.parent = null;
6213
+ }
6214
+ /**
6215
+ * Returns focus to the trigger before closing, the same order `clrDropdownItem` uses - moving focus
6216
+ * first means it lands correctly even when the action opens a modal.
6217
+ */
6218
+ closeMenu() {
6219
+ this.focusHandler.focus();
6220
+ this.popoverService.open = false;
6221
+ }
6222
+ /**
6223
+ * Re-anchors the open menu to the trigger, for an action that moves the column it belongs to
6224
+ * instead of closing the menu behind it.
6225
+ *
6226
+ * Deferred to after the next render rather than run straight away, because the action that asked
6227
+ * for this has only just been clicked - the column is relocated by the change detection that
6228
+ * follows, so measuring the trigger now would re-anchor the menu to where it already is.
6229
+ */
6230
+ repositionMenu() {
6231
+ afterNextRender(() => this.popoverService.updatePosition(), { injector: this.injector });
6232
+ }
6233
+ /**
6234
+ * Moves focus to one of the projected actions, keeping the menu's keyboard handling in step with
6235
+ * it.
6236
+ *
6237
+ * Called by `clrDgColumnAction` when the item takes focus, so that focusing an item by any means -
6238
+ * including a plain `focus()` from outside, after an action rebuilt the menu - leaves space and
6239
+ * enter acting on that same item rather than on whatever the menu focused when it opened.
6240
+ */
6241
+ focusAction(item) {
6242
+ this.focusHandler.moveTo(item);
6243
+ }
6244
+ /**
6245
+ * The menu states a direction rather than cycling through them, so asking for the direction the
6246
+ * column already has is a no-op.
6247
+ *
6248
+ * The guard is needed because `Sort.toggle()` reads `forceReverse: false` as "toggle" rather than
6249
+ * "ascending" - `forceReverse || !this._reverse` falls through to the toggle for a falsy value - so
6250
+ * `sort(false)` on an already ascending column would flip it to descending. The tri-state title
6251
+ * button never hits that path, because it always calls `sort()` without an argument.
6252
+ */
6253
+ sort(descending) {
6254
+ const requested = descending ? ClrDatagridSortOrder.DESC : ClrDatagridSortOrder.ASC;
6255
+ if (this.sortOrder !== requested) {
6256
+ this.column.sort(descending);
6257
+ }
6258
+ }
6259
+ /**
6260
+ * Pins or unpins the column, then re-anchors this menu to the trigger.
6261
+ *
6262
+ * Pinning moves the column between the datagrid's static and scrollable containers, and the
6263
+ * trigger this menu is anchored to travels with it - far enough that the menu would otherwise be
6264
+ * left hanging next to where the column used to be. The menu stays open on purpose, so the action
6265
+ * it now offers is the one that undoes the pin the user just applied.
6266
+ *
6267
+ * The columns are relocated on the render cycle the pinned state change schedules, not while this
6268
+ * runs, so the overlay can only be re-anchored once that has happened - which `repositionMenu`
6269
+ * takes care of.
6270
+ */
6271
+ togglePinned() {
6272
+ this.column.togglePinned();
6273
+ this.repositionMenu();
6274
+ }
6275
+ /**
6276
+ * Opens the filter of this column, anchored to the "Filter Column" menu item itself (`#trigger`
6277
+ * above), so the popover positions off the item that was actually clicked rather than the kebab.
6278
+ *
6279
+ * The popover is driven through the column's ClrPopoverService rather than through
6280
+ * `ClrDatagridFilter.open`, because that is the one thing every filter flavour has in common - a
6281
+ * projected clr-dg-filter, and the string and numeric filters the column builds for clrDgField,
6282
+ * all share this service. Setting `origin` is all it takes to re-anchor it: `clrPopoverOrigin` is
6283
+ * itself only an assignment to that property, and with the toggle gone nothing else claims it.
6284
+ *
6285
+ * `parent` links the filter's popover to this menu's, so that scrolling while both are open closes
6286
+ * or repositions them together rather than leaving one behind. It is cleared again once the filter
6287
+ * closes, in the `openChange` subscription below, so it never outlives the menu session that set it.
6288
+ */
6289
+ openFilter(event) {
6290
+ // reroute filter popover origin to filter trigger and set dropdown menu as parent.
6291
+ this.columnPopover.origin = this.trigger;
6292
+ this.columnPopover.parent = this._menuPopoverContent;
6293
+ // The popover closes on an outside click, and ignores exactly one event while doing so: the one
6294
+ // that opened it. Without this, the very click on this menu item would close the filter again.
6295
+ this.columnPopover.openEvent = event;
6296
+ this.columnPopover.open = true;
6297
+ }
6298
+ static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.25", ngImport: i0, type: ClrDatagridColumnActions, deps: [{ token: ClrDatagridColumn }, { token: i2.ClrCommonStringsService }, { token: ColumnActionsService }, { token: i3.ClrPopoverService, skipSelf: true }, { token: i0.ChangeDetectorRef }, { token: i0.Injector }, { token: FiltersProvider, optional: true }, { token: i6.ClrDropdown, optional: true, skipSelf: true }, { token: i3.ClrPopoverService }, { token: i6.DropdownFocusHandler }, { token: i6.RootDropdownService }], target: i0.ɵɵFactoryTarget.Component }); }
6299
+ static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.2.25", type: ClrDatagridColumnActions, isStandalone: false, selector: "clr-dg-column-actions", inputs: { keepFilterInHeader: ["clrDgKeepFilterInHeader", "keepFilterInHeader", booleanAttribute] }, host: { properties: { "class.datagrid-column-actions": "true" } }, providers: [
6300
+ ROOT_DROPDOWN_PROVIDER,
6301
+ FOCUS_SERVICE_PROVIDER,
6302
+ ColumnActionsFocusHandler,
6303
+ { provide: DropdownFocusHandler, useExisting: ColumnActionsFocusHandler },
6304
+ { provide: FocusableItem, useExisting: ColumnActionsFocusHandler },
6305
+ { provide: ClrDropdown, useExisting: ClrDatagridColumnActions },
6306
+ ], queries: [{ propertyName: "projectedItems", predicate: FocusableItem }], viewQueries: [{ propertyName: "trigger", first: true, predicate: ["trigger"], descendants: true, read: ElementRef }, { propertyName: "menuPopoverContent", first: true, predicate: ClrDropdownMenu, descendants: true, read: ClrPopoverContent }], usesInheritance: true, ngImport: i0, template: `
6307
+ <button
6308
+ class="datagrid-column-actions-toggle"
6309
+ type="button"
6310
+ clrDropdownTrigger
6311
+ [class.datagrid-column-actions-filtered]="filterActive"
6312
+ [attr.aria-label]="triggerLabel"
6313
+ >
6314
+ <cds-icon
6315
+ [size]="filterActive ? '16' : '12'"
6316
+ [shape]="filterActive ? 'ellipsis-grid-circle' : 'ellipsis-vertical'"
6317
+ [status]="filterActive ? 'info' : null"
6318
+ aria-hidden="true"
6319
+ />
6320
+ </button>
6321
+
6322
+ <clr-dropdown-menu *clrIfOpen clrPosition="bottom-right">
6323
+ @if (column.sortable) {
6324
+ <!--
6325
+ The two directions are one exclusive setting rather than two commands, so they are radio
6326
+ items: the applied one is then announced as such. The active class alone would leave it
6327
+ visible only to a sighted user - the column header's aria-sort is not read from in here.
6328
+ -->
6329
+ <button
6330
+ type="button"
6331
+ clrDropdownItem
6332
+ role="menuitemradio"
6333
+ [attr.aria-checked]="sortOrder === ClrDatagridSortOrder.ASC"
6334
+ [class.active]="sortOrder === ClrDatagridSortOrder.ASC"
6335
+ (click)="sort(false)"
6336
+ >
6337
+ <cds-icon shape="arrow" direction="up" aria-hidden="true"></cds-icon>
6338
+ {{ commonStrings.keys.sortColumnAscending }}
6339
+ </button>
6340
+ <button
6341
+ type="button"
6342
+ clrDropdownItem
6343
+ role="menuitemradio"
6344
+ [attr.aria-checked]="sortOrder === ClrDatagridSortOrder.DESC"
6345
+ [class.active]="sortOrder === ClrDatagridSortOrder.DESC"
6346
+ (click)="sort(true)"
6347
+ >
6348
+ <cds-icon shape="arrow" direction="down" aria-hidden="true"></cds-icon>
6349
+ {{ commonStrings.keys.sortColumnDescending }}
6350
+ </button>
6351
+ @if (canClearSort) {
6352
+ <button type="button" clrDropdownItem (click)="column.clearSort()">
6353
+ <cds-icon shape="times" aria-hidden="true"></cds-icon>
6354
+ {{ commonStrings.keys.clearColumnSort }}
6355
+ </button>
6356
+ }
6357
+ }
6358
+
6359
+ @if (column.pinnable) {
6360
+ @if (column.sortable) {
6361
+ <div class="dropdown-divider" role="separator"></div>
6362
+ }
6363
+ <button type="button" clrDropdownItem (click)="togglePinned()">
6364
+ <cds-icon
6365
+ [shape]="column.pinned ? 'unpin' : 'pin'"
6366
+ solid
6367
+ size="12"
6368
+ style="margin: 2px;"
6369
+ aria-hidden="true"
6370
+ ></cds-icon>
6371
+ {{ column.pinned ? commonStrings.keys.unpinColumn : commonStrings.keys.pinColumn }}
6372
+ </button>
6373
+ }
6374
+
6375
+ @if (hasFilter && !keepFilterInHeader) {
6376
+ @if (column.sortable || column.pinnable) {
6377
+ <div class="dropdown-divider" role="separator"></div>
6378
+ }
6379
+ <!--
6380
+ This item stands in for the filter's own toggle, so it takes over the state that toggle
6381
+ announced: that it opens a dialog, and whether that dialog is open right now.
6382
+ -->
6383
+ <button
6384
+ type="button"
6385
+ #trigger
6386
+ clrDropdownItem
6387
+ aria-haspopup="dialog"
6388
+ [attr.aria-expanded]="filterOpen"
6389
+ [attr.aria-controls]="filterPopoverId"
6390
+ (click)="openFilter($event)"
6391
+ >
6392
+ <cds-icon [shape]="filterActive ? 'filter-grid-circle' : 'filter-grid'" solid aria-hidden="true"></cds-icon>
6393
+ {{ commonStrings.keys.filterColumn }}
6394
+ </button>
6395
+ }
6396
+
6397
+ <ng-content></ng-content>
6398
+ </clr-dropdown-menu>
6399
+ `, isInline: true, dependencies: [{ kind: "component", type: i4.ClrIcon, selector: "clr-icon, cds-icon", inputs: ["shape", "size", "direction", "flip", "solid", "status", "inverse", "badge", "innerOffset"] }, { kind: "directive", type: i3.ClrIfOpen, selector: "[clrIfOpen]", inputs: ["clrIfOpen"], outputs: ["clrIfOpenChange"] }, { kind: "component", type: i6.ClrDropdownMenu, selector: "clr-dropdown-menu", inputs: ["clrPosition"] }, { kind: "directive", type: i6.ClrDropdownTrigger, selector: "[clrDropdownTrigger],[clrDropdownToggle]" }, { kind: "directive", type: i6.ClrDropdownItem, selector: "[clrDropdownItem]", inputs: ["role", "clrDisabled", "id"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush }); }
6400
+ }
6401
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.25", ngImport: i0, type: ClrDatagridColumnActions, decorators: [{
6402
+ type: Component,
6403
+ args: [{
6404
+ selector: 'clr-dg-column-actions',
6405
+ template: `
6406
+ <button
6407
+ class="datagrid-column-actions-toggle"
6408
+ type="button"
6409
+ clrDropdownTrigger
6410
+ [class.datagrid-column-actions-filtered]="filterActive"
6411
+ [attr.aria-label]="triggerLabel"
6412
+ >
6413
+ <cds-icon
6414
+ [size]="filterActive ? '16' : '12'"
6415
+ [shape]="filterActive ? 'ellipsis-grid-circle' : 'ellipsis-vertical'"
6416
+ [status]="filterActive ? 'info' : null"
6417
+ aria-hidden="true"
6418
+ />
6419
+ </button>
6420
+
6421
+ <clr-dropdown-menu *clrIfOpen clrPosition="bottom-right">
6422
+ @if (column.sortable) {
6423
+ <!--
6424
+ The two directions are one exclusive setting rather than two commands, so they are radio
6425
+ items: the applied one is then announced as such. The active class alone would leave it
6426
+ visible only to a sighted user - the column header's aria-sort is not read from in here.
6427
+ -->
6428
+ <button
6429
+ type="button"
6430
+ clrDropdownItem
6431
+ role="menuitemradio"
6432
+ [attr.aria-checked]="sortOrder === ClrDatagridSortOrder.ASC"
6433
+ [class.active]="sortOrder === ClrDatagridSortOrder.ASC"
6434
+ (click)="sort(false)"
6435
+ >
6436
+ <cds-icon shape="arrow" direction="up" aria-hidden="true"></cds-icon>
6437
+ {{ commonStrings.keys.sortColumnAscending }}
6438
+ </button>
6439
+ <button
6440
+ type="button"
6441
+ clrDropdownItem
6442
+ role="menuitemradio"
6443
+ [attr.aria-checked]="sortOrder === ClrDatagridSortOrder.DESC"
6444
+ [class.active]="sortOrder === ClrDatagridSortOrder.DESC"
6445
+ (click)="sort(true)"
6446
+ >
6447
+ <cds-icon shape="arrow" direction="down" aria-hidden="true"></cds-icon>
6448
+ {{ commonStrings.keys.sortColumnDescending }}
6449
+ </button>
6450
+ @if (canClearSort) {
6451
+ <button type="button" clrDropdownItem (click)="column.clearSort()">
6452
+ <cds-icon shape="times" aria-hidden="true"></cds-icon>
6453
+ {{ commonStrings.keys.clearColumnSort }}
6454
+ </button>
6455
+ }
6456
+ }
6457
+
6458
+ @if (column.pinnable) {
6459
+ @if (column.sortable) {
6460
+ <div class="dropdown-divider" role="separator"></div>
6461
+ }
6462
+ <button type="button" clrDropdownItem (click)="togglePinned()">
6463
+ <cds-icon
6464
+ [shape]="column.pinned ? 'unpin' : 'pin'"
6465
+ solid
6466
+ size="12"
6467
+ style="margin: 2px;"
6468
+ aria-hidden="true"
6469
+ ></cds-icon>
6470
+ {{ column.pinned ? commonStrings.keys.unpinColumn : commonStrings.keys.pinColumn }}
6471
+ </button>
6472
+ }
6473
+
6474
+ @if (hasFilter && !keepFilterInHeader) {
6475
+ @if (column.sortable || column.pinnable) {
6476
+ <div class="dropdown-divider" role="separator"></div>
6477
+ }
6478
+ <!--
6479
+ This item stands in for the filter's own toggle, so it takes over the state that toggle
6480
+ announced: that it opens a dialog, and whether that dialog is open right now.
6481
+ -->
6482
+ <button
6483
+ type="button"
6484
+ #trigger
6485
+ clrDropdownItem
6486
+ aria-haspopup="dialog"
6487
+ [attr.aria-expanded]="filterOpen"
6488
+ [attr.aria-controls]="filterPopoverId"
6489
+ (click)="openFilter($event)"
6490
+ >
6491
+ <cds-icon [shape]="filterActive ? 'filter-grid-circle' : 'filter-grid'" solid aria-hidden="true"></cds-icon>
6492
+ {{ commonStrings.keys.filterColumn }}
6493
+ </button>
6494
+ }
6495
+
6496
+ <ng-content></ng-content>
6497
+ </clr-dropdown-menu>
6498
+ `,
6499
+ host: {
6500
+ '[class.datagrid-column-actions]': 'true',
6501
+ },
6502
+ // ClrDropdown's providers are not inherited, so they have to be repeated for this component to be
6503
+ // one. Its host directives and host bindings - the popover host, and the dropdown classes - are
6504
+ // inherited, and must not be repeated.
6505
+ providers: [
6506
+ ROOT_DROPDOWN_PROVIDER,
6507
+ FOCUS_SERVICE_PROVIDER,
6508
+ ColumnActionsFocusHandler,
6509
+ { provide: DropdownFocusHandler, useExisting: ColumnActionsFocusHandler },
6510
+ { provide: FocusableItem, useExisting: ColumnActionsFocusHandler },
6511
+ { provide: ClrDropdown, useExisting: ClrDatagridColumnActions },
6512
+ ],
6513
+ changeDetection: ChangeDetectionStrategy.OnPush,
6514
+ standalone: false,
6515
+ }]
6516
+ }], ctorParameters: () => [{ type: ClrDatagridColumn }, { type: i2.ClrCommonStringsService }, { type: ColumnActionsService }, { type: i3.ClrPopoverService, decorators: [{
6517
+ type: SkipSelf
6518
+ }] }, { type: i0.ChangeDetectorRef }, { type: i0.Injector }, { type: FiltersProvider, decorators: [{
6519
+ type: Optional
6520
+ }] }, { type: i6.ClrDropdown, decorators: [{
6521
+ type: SkipSelf
6522
+ }, {
6523
+ type: Optional
6524
+ }] }, { type: i3.ClrPopoverService }, { type: i6.DropdownFocusHandler }, { type: i6.RootDropdownService }], propDecorators: { trigger: [{
6525
+ type: ViewChild,
6526
+ args: ['trigger', { read: ElementRef }]
6527
+ }], keepFilterInHeader: [{
6528
+ type: Input,
6529
+ args: [{ alias: 'clrDgKeepFilterInHeader', transform: booleanAttribute }]
6530
+ }], projectedItems: [{
6531
+ type: ContentChildren,
6532
+ args: [FocusableItem]
6533
+ }], menuPopoverContent: [{
6534
+ type: ViewChild,
6535
+ args: [ClrDropdownMenu, { read: ClrPopoverContent }]
6536
+ }] } });
6537
+
6538
+ /*
6539
+ * Copyright (c) 2016-2026 Broadcom. All Rights Reserved.
6540
+ * The term "Broadcom" refers to Broadcom Inc. and/or its subsidiaries.
6541
+ * This software is released under MIT license.
6542
+ * The full license information can be found in LICENSE in the root directory of this project.
6543
+ */
6544
+ /**
6545
+ * An application provided item in a `clr-dg-column-actions` menu. It is the dropdown item - same
6546
+ * inputs, styling and arrow key order - with what a column action needs on top: it closes the menu
6547
+ * when picked, or re-anchors it after an action that leaves it open.
6548
+ */
6549
+ class ClrDatagridColumnAction extends ClrDropdownItem {
6550
+ constructor(columnActions, item, dropdownService, el, renderer) {
6551
+ super(columnActions, dropdownService, item, el, renderer);
6552
+ this.columnActions = columnActions;
6553
+ /**
6554
+ * Whether activating this item should close the menu.
6555
+ */
6556
+ this.canClosePopover = true;
6557
+ }
6558
+ // Space and enter both turn into a click, so this covers the keyboard as well.
6559
+ onColumnActionClick() {
6560
+ if (this.disabled) {
6561
+ return;
6562
+ }
6563
+ if (this.canClosePopover) {
6564
+ this.columnActions.closeMenu();
6565
+ }
6566
+ else {
6567
+ this.columnActions.repositionMenu();
6568
+ }
6569
+ }
6570
+ /**
6571
+ * Focus can arrive from anywhere - the arrow keys, or a plain `focus()` from an application that
6572
+ * moved the column this action belongs to and rebuilt the menu. Reporting it keeps space and enter
6573
+ * acting on this item rather than on whatever the menu focused when it opened.
6574
+ */
6575
+ onFocus() {
6576
+ this.columnActions.focusAction(this.focusableItem);
6577
+ }
6578
+ static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.25", ngImport: i0, type: ClrDatagridColumnAction, deps: [{ token: ClrDatagridColumnActions }, { token: i2.FocusableItem }, { token: i6.RootDropdownService }, { token: i0.ElementRef }, { token: i0.Renderer2 }], target: i0.ɵɵFactoryTarget.Directive }); }
6579
+ static { this.ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "16.1.0", version: "21.2.25", type: ClrDatagridColumnAction, isStandalone: false, selector: "[clrDgColumnAction]", inputs: { canClosePopover: ["clrCanClosePopover", "canClosePopover", booleanAttribute] }, host: { listeners: { "click": "onColumnActionClick()", "focus": "onFocus()" } }, providers: [BASIC_FOCUSABLE_ITEM_PROVIDER], usesInheritance: true, ngImport: i0 }); }
6580
+ }
6581
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.25", ngImport: i0, type: ClrDatagridColumnAction, decorators: [{
6582
+ type: Directive,
6583
+ args: [{
6584
+ selector: '[clrDgColumnAction]',
6585
+ providers: [BASIC_FOCUSABLE_ITEM_PROVIDER],
6586
+ standalone: false,
6587
+ }]
6588
+ }], ctorParameters: () => [{ type: ClrDatagridColumnActions }, { type: i2.FocusableItem }, { type: i6.RootDropdownService }, { type: i0.ElementRef }, { type: i0.Renderer2 }], propDecorators: { canClosePopover: [{
6589
+ type: Input,
6590
+ args: [{ alias: 'clrCanClosePopover', transform: booleanAttribute }]
6591
+ }], onColumnActionClick: [{
6592
+ type: HostListener,
6593
+ args: ['click']
6594
+ }], onFocus: [{
6595
+ type: HostListener,
6596
+ args: ['focus']
6597
+ }] } });
6598
+
5623
6599
  /*
5624
6600
  * Copyright (c) 2016-2026 Broadcom. All Rights Reserved.
5625
6601
  * The term "Broadcom" refers to Broadcom Inc. and/or its subsidiaries.
@@ -5656,8 +6632,8 @@ class ClrDatagridColumnToggleButton {
5656
6632
  hideableColumns() {
5657
6633
  return this.columnsService.columns.filter(column => column.value.hideable);
5658
6634
  }
5659
- static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.1.3", ngImport: i0, type: ClrDatagridColumnToggleButton, deps: [{ token: i2.ClrCommonStringsService }, { token: ColumnsService }], target: i0.ɵɵFactoryTarget.Component }); }
5660
- static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "21.1.3", type: ClrDatagridColumnToggleButton, isStandalone: false, selector: "clr-dg-column-toggle-button", outputs: { clrAllSelected: "clrAllSelected" }, ngImport: i0, template: `
6635
+ static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.25", ngImport: i0, type: ClrDatagridColumnToggleButton, deps: [{ token: i2.ClrCommonStringsService }, { token: ColumnsService }], target: i0.ɵɵFactoryTarget.Component }); }
6636
+ static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "21.2.25", type: ClrDatagridColumnToggleButton, isStandalone: false, selector: "clr-dg-column-toggle-button", outputs: { clrAllSelected: "clrAllSelected" }, ngImport: i0, template: `
5661
6637
  <button
5662
6638
  class="btn btn-sm btn-link switch-button"
5663
6639
  (click)="selectAll()"
@@ -5668,7 +6644,7 @@ class ClrDatagridColumnToggleButton {
5668
6644
  </button>
5669
6645
  `, isInline: true }); }
5670
6646
  }
5671
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.1.3", ngImport: i0, type: ClrDatagridColumnToggleButton, decorators: [{
6647
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.25", ngImport: i0, type: ClrDatagridColumnToggleButton, decorators: [{
5672
6648
  type: Component,
5673
6649
  args: [{
5674
6650
  selector: 'clr-dg-column-toggle-button',
@@ -5740,8 +6716,8 @@ class ClrDatagridColumnToggle {
5740
6716
  allColumnsSelected() {
5741
6717
  this.allSelectedElement.nativeElement.focus();
5742
6718
  }
5743
- static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.1.3", ngImport: i0, type: ClrDatagridColumnToggle, deps: [{ token: i2.ClrCommonStringsService }, { token: ColumnsService }, { token: i3.ClrPopoverService }], target: i0.ɵɵFactoryTarget.Component }); }
5744
- static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.1.3", type: ClrDatagridColumnToggle, isStandalone: false, selector: "clr-dg-column-toggle", host: { properties: { "class.column-switch-wrapper": "true", "class.active": "openState" } }, viewQueries: [{ propertyName: "allSelectedElement", first: true, predicate: ["allSelected"], descendants: true, read: ElementRef }], hostDirectives: [{ directive: i3.ClrPopoverHostDirective }], ngImport: i0, template: `
6719
+ static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.25", ngImport: i0, type: ClrDatagridColumnToggle, deps: [{ token: i2.ClrCommonStringsService }, { token: ColumnsService }, { token: i3.ClrPopoverService }], target: i0.ɵɵFactoryTarget.Component }); }
6720
+ static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.2.25", type: ClrDatagridColumnToggle, isStandalone: false, selector: "clr-dg-column-toggle", host: { properties: { "class.column-switch-wrapper": "true", "class.active": "openState" } }, viewQueries: [{ propertyName: "allSelectedElement", first: true, predicate: ["allSelected"], descendants: true, read: ElementRef }], hostDirectives: [{ directive: i3.ClrPopoverHostDirective }], ngImport: i0, template: `
5745
6721
  <button
5746
6722
  role="button"
5747
6723
  type="button"
@@ -5804,9 +6780,9 @@ class ClrDatagridColumnToggle {
5804
6780
  <clr-dg-column-toggle-button (clrAllSelected)="allColumnsSelected()"></clr-dg-column-toggle-button>
5805
6781
  </div>
5806
6782
  </div>
5807
- `, isInline: true, dependencies: [{ kind: "directive", type: i9.NgTemplateOutlet, selector: "[ngTemplateOutlet]", inputs: ["ngTemplateOutletContext", "ngTemplateOutlet", "ngTemplateOutletInjector"] }, { kind: "directive", type: i2.CdkTrapFocusModule_CdkTrapFocus, selector: "[cdkTrapFocus]" }, { kind: "component", type: i5.ClrIcon, selector: "clr-icon, cds-icon", inputs: ["shape", "size", "direction", "flip", "solid", "status", "inverse", "badge"] }, { kind: "directive", type: i4.ClrControlLabel, selector: "label", inputs: ["id", "for"] }, { kind: "directive", type: i7.ClrCheckbox, selector: "[clrCheckbox],[clrToggle]" }, { kind: "component", type: i7.ClrCheckboxWrapper, selector: "clr-checkbox-wrapper,clr-toggle-wrapper" }, { kind: "directive", type: i13.CheckboxControlValueAccessor, selector: "input[type=checkbox][formControlName],input[type=checkbox][formControl],input[type=checkbox][ngModel]" }, { kind: "directive", type: i13.NgControlStatus, selector: "[formControlName],[ngModel],[formControl]" }, { kind: "directive", type: i13.NgModel, selector: "[ngModel]:not([formControlName]):not([formControl])", inputs: ["name", "disabled", "ngModel", "ngModelOptions"], outputs: ["ngModelChange"], exportAs: ["ngModel"] }, { kind: "directive", type: i3.ClrPopoverOrigin, selector: "[clrPopoverOrigin]" }, { kind: "directive", type: i3.ClrPopoverCloseButton, selector: "[clrPopoverCloseButton]", outputs: ["clrPopoverOnCloseChange"] }, { kind: "directive", type: i3.ClrPopoverOpenCloseButton, selector: "[clrPopoverOpenCloseButton]", outputs: ["clrPopoverOpenCloseChange"] }, { kind: "directive", type: i3.ClrPopoverContent, selector: "[clrPopoverContent]", inputs: ["clrPopoverContent", "clrPopoverContentAt", "clrPopoverContentAvailablePositions", "clrPopoverContentType", "clrPopoverContentOutsideClickToClose", "clrPopoverContentScrollToClose", "clrPopoverContentOrigin"] }, { kind: "component", type: ClrDatagridColumnToggleButton, selector: "clr-dg-column-toggle-button", outputs: ["clrAllSelected"] }] }); }
6783
+ `, isInline: true, dependencies: [{ kind: "directive", type: i10.NgTemplateOutlet, selector: "[ngTemplateOutlet]", inputs: ["ngTemplateOutletContext", "ngTemplateOutlet", "ngTemplateOutletInjector"] }, { kind: "directive", type: i2.CdkTrapFocusModule_CdkTrapFocus, selector: "[cdkTrapFocus]" }, { kind: "component", type: i4.ClrIcon, selector: "clr-icon, cds-icon", inputs: ["shape", "size", "direction", "flip", "solid", "status", "inverse", "badge", "innerOffset"] }, { kind: "directive", type: i4$1.ClrControlLabel, selector: "label", inputs: ["id", "for"] }, { kind: "directive", type: i7.ClrCheckbox, selector: "[clrCheckbox],[clrToggle]" }, { kind: "component", type: i7.ClrCheckboxWrapper, selector: "clr-checkbox-wrapper,clr-toggle-wrapper" }, { kind: "directive", type: i14.CheckboxControlValueAccessor, selector: "input[type=checkbox][formControlName],input[type=checkbox][formControl],input[type=checkbox][ngModel]" }, { kind: "directive", type: i14.NgControlStatus, selector: "[formControlName],[ngModel],[formControl]" }, { kind: "directive", type: i14.NgModel, selector: "[ngModel]:not([formControlName]):not([formControl])", inputs: ["name", "disabled", "ngModel", "ngModelOptions"], outputs: ["ngModelChange"], exportAs: ["ngModel"] }, { kind: "directive", type: i3.ClrPopoverOrigin, selector: "[clrPopoverOrigin]" }, { kind: "directive", type: i3.ClrPopoverCloseButton, selector: "[clrPopoverCloseButton]", outputs: ["clrPopoverOnCloseChange"] }, { kind: "directive", type: i3.ClrPopoverOpenCloseButton, selector: "[clrPopoverOpenCloseButton]", outputs: ["clrPopoverOpenCloseChange"] }, { kind: "directive", type: i3.ClrPopoverContent, selector: "[clrPopoverContent]", inputs: ["clrPopoverContent", "clrPopoverContentAt", "clrPopoverContentAvailablePositions", "clrPopoverContentType", "clrPopoverContentOutsideClickToClose", "clrPopoverContentScrollToClose", "clrPopoverContentOrigin"] }, { kind: "component", type: ClrDatagridColumnToggleButton, selector: "clr-dg-column-toggle-button", outputs: ["clrAllSelected"] }] }); }
5808
6784
  }
5809
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.1.3", ngImport: i0, type: ClrDatagridColumnToggle, decorators: [{
6785
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.25", ngImport: i0, type: ClrDatagridColumnToggle, decorators: [{
5810
6786
  type: Component,
5811
6787
  args: [{
5812
6788
  selector: 'clr-dg-column-toggle',
@@ -5900,8 +6876,8 @@ class ClrDatagridDetailHeader {
5900
6876
  ngAfterViewInit() {
5901
6877
  this.title.nativeElement.focus();
5902
6878
  }
5903
- static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.1.3", ngImport: i0, type: ClrDatagridDetailHeader, deps: [{ token: DetailService }, { token: i2.ClrCommonStringsService }], target: i0.ɵɵFactoryTarget.Component }); }
5904
- static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "21.1.3", type: ClrDatagridDetailHeader, isStandalone: false, selector: "clr-dg-detail-header", host: { properties: { "class.datagrid-detail-header": "true" } }, viewQueries: [{ propertyName: "title", first: true, predicate: ["title"], descendants: true }], ngImport: i0, template: `
6879
+ static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.25", ngImport: i0, type: ClrDatagridDetailHeader, deps: [{ token: DetailService }, { token: i2.ClrCommonStringsService }], target: i0.ɵɵFactoryTarget.Component }); }
6880
+ static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "21.2.25", type: ClrDatagridDetailHeader, isStandalone: false, selector: "clr-dg-detail-header", host: { properties: { "class.datagrid-detail-header": "true" } }, viewQueries: [{ propertyName: "title", first: true, predicate: ["title"], descendants: true }], ngImport: i0, template: `
5905
6881
  <div #title class="datagrid-detail-header-title" tabindex="-1" [id]="titleId">
5906
6882
  <ng-content></ng-content>
5907
6883
  </div>
@@ -5915,9 +6891,9 @@ class ClrDatagridDetailHeader {
5915
6891
  <cds-icon shape="times"></cds-icon>
5916
6892
  </button>
5917
6893
  </div>
5918
- `, isInline: true, dependencies: [{ kind: "component", type: i5.ClrIcon, selector: "clr-icon, cds-icon", inputs: ["shape", "size", "direction", "flip", "solid", "status", "inverse", "badge"] }] }); }
6894
+ `, isInline: true, dependencies: [{ kind: "component", type: i4.ClrIcon, selector: "clr-icon, cds-icon", inputs: ["shape", "size", "direction", "flip", "solid", "status", "inverse", "badge", "innerOffset"] }] }); }
5919
6895
  }
5920
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.1.3", ngImport: i0, type: ClrDatagridDetailHeader, decorators: [{
6896
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.25", ngImport: i0, type: ClrDatagridDetailHeader, decorators: [{
5921
6897
  type: Component,
5922
6898
  args: [{
5923
6899
  selector: 'clr-dg-detail-header',
@@ -5957,6 +6933,32 @@ class ClrDatagridDetail {
5957
6933
  this.detailService = detailService;
5958
6934
  this.commonStrings = commonStrings;
5959
6935
  }
6936
+ get detailWidth() {
6937
+ return this.detailService.detailWidth;
6938
+ }
6939
+ set detailWidth(value) {
6940
+ if (value === null || value === undefined) {
6941
+ this.detailService.detailWidth = DEFAULT_DETAIL_WIDTH;
6942
+ return;
6943
+ }
6944
+ if (value < MIN_DETAIL_WIDTH) {
6945
+ this.detailService.detailWidth = MIN_DETAIL_WIDTH;
6946
+ return;
6947
+ }
6948
+ if (value > MAX_DETAIL_WIDTH) {
6949
+ this.detailService.detailWidth = MAX_DETAIL_WIDTH;
6950
+ return;
6951
+ }
6952
+ this.detailService.detailWidth = value;
6953
+ }
6954
+ get isCustomWidth() {
6955
+ return this.detailWidth !== DEFAULT_DETAIL_WIDTH;
6956
+ }
6957
+ get width() {
6958
+ // Skip the inline style at 100% so the .datagrid-detail-overlay CSS rule takes over
6959
+ // without needing !important to override an inline style.
6960
+ return this.detailWidth !== MAX_DETAIL_WIDTH ? this.detailWidth : null;
6961
+ }
5960
6962
  get labelledBy() {
5961
6963
  if (this.ariaLabelledBy) {
5962
6964
  return this.header ? `${this.header.titleId} ${this.ariaLabelledBy}` : this.ariaLabelledBy;
@@ -5980,8 +6982,8 @@ class ClrDatagridDetail {
5980
6982
  close() {
5981
6983
  this.detailService.close();
5982
6984
  }
5983
- static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.1.3", ngImport: i0, type: ClrDatagridDetail, deps: [{ token: DetailService }, { token: i2.ClrCommonStringsService }], target: i0.ɵɵFactoryTarget.Component }); }
5984
- static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.1.3", type: ClrDatagridDetail, isStandalone: false, selector: "clr-dg-detail", inputs: { ariaLabelledBy: ["clrDetailAriaLabelledBy", "ariaLabelledBy"], ariaLabel: ["clrDetailAriaLabel", "ariaLabel"] }, host: { properties: { "class.datagrid-detail-pane": "true" } }, queries: [{ propertyName: "header", first: true, predicate: ClrDatagridDetailHeader, descendants: true }], ngImport: i0, template: `
6985
+ static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.25", ngImport: i0, type: ClrDatagridDetail, deps: [{ token: DetailService }, { token: i2.ClrCommonStringsService }], target: i0.ɵɵFactoryTarget.Component }); }
6986
+ static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.2.25", type: ClrDatagridDetail, isStandalone: false, selector: "clr-dg-detail", inputs: { ariaLabelledBy: ["clrDetailAriaLabelledBy", "ariaLabelledBy"], ariaLabel: ["clrDetailAriaLabel", "ariaLabel"], detailWidth: ["clrDetailWidth", "detailWidth"] }, host: { properties: { "class.datagrid-detail-pane": "true", "class.datagrid-detail-custom-width": "isCustomWidth", "style.width.%": "width" } }, queries: [{ propertyName: "header", first: true, predicate: ClrDatagridDetailHeader, descendants: true }], ngImport: i0, template: `
5985
6987
  @if (detailService.isOpen) {
5986
6988
  <div
5987
6989
  cdkTrapFocus
@@ -6000,12 +7002,14 @@ class ClrDatagridDetail {
6000
7002
  }
6001
7003
  `, isInline: true, dependencies: [{ kind: "directive", type: i2.CdkTrapFocusModule_CdkTrapFocus, selector: "[cdkTrapFocus]" }] }); }
6002
7004
  }
6003
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.1.3", ngImport: i0, type: ClrDatagridDetail, decorators: [{
7005
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.25", ngImport: i0, type: ClrDatagridDetail, decorators: [{
6004
7006
  type: Component,
6005
7007
  args: [{
6006
7008
  selector: 'clr-dg-detail',
6007
7009
  host: {
6008
7010
  '[class.datagrid-detail-pane]': 'true',
7011
+ '[class.datagrid-detail-custom-width]': 'isCustomWidth',
7012
+ '[style.width.%]': 'width',
6009
7013
  },
6010
7014
  // We put the @if on the cdkTrapFocus so it doesn't always exist on the page
6011
7015
  // have to test for presence of header for aria-describedby because it was causing unit tests to crash
@@ -6038,6 +7042,9 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.1.3", ngImpor
6038
7042
  }], header: [{
6039
7043
  type: ContentChild,
6040
7044
  args: [ClrDatagridDetailHeader]
7045
+ }], detailWidth: [{
7046
+ type: Input,
7047
+ args: ['clrDetailWidth']
6041
7048
  }] } });
6042
7049
 
6043
7050
  /*
@@ -6047,14 +7054,14 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.1.3", ngImpor
6047
7054
  * The full license information can be found in LICENSE in the root directory of this project.
6048
7055
  */
6049
7056
  class ClrDatagridDetailBody {
6050
- static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.1.3", ngImport: i0, type: ClrDatagridDetailBody, deps: [], target: i0.ɵɵFactoryTarget.Component }); }
6051
- static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "21.1.3", type: ClrDatagridDetailBody, isStandalone: false, selector: "clr-dg-detail-body", host: { properties: { "class.datagrid-detail-body": "true" } }, ngImport: i0, template: `
7057
+ static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.25", ngImport: i0, type: ClrDatagridDetailBody, deps: [], target: i0.ɵɵFactoryTarget.Component }); }
7058
+ static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "21.2.25", type: ClrDatagridDetailBody, isStandalone: false, selector: "clr-dg-detail-body", host: { properties: { "class.datagrid-detail-body": "true" } }, ngImport: i0, template: `
6052
7059
  <div class="clr-dg-detail-body-wrapper">
6053
7060
  <ng-content></ng-content>
6054
7061
  </div>
6055
7062
  `, isInline: true }); }
6056
7063
  }
6057
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.1.3", ngImport: i0, type: ClrDatagridDetailBody, decorators: [{
7064
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.25", ngImport: i0, type: ClrDatagridDetailBody, decorators: [{
6058
7065
  type: Component,
6059
7066
  args: [{
6060
7067
  selector: 'clr-dg-detail-body',
@@ -6070,23 +7077,6 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.1.3", ngImpor
6070
7077
  }]
6071
7078
  }] });
6072
7079
 
6073
- /*
6074
- * Copyright (c) 2016-2026 Broadcom. All Rights Reserved.
6075
- * The term "Broadcom" refers to Broadcom Inc. and/or its subsidiaries.
6076
- * This software is released under MIT license.
6077
- * The full license information can be found in LICENSE in the root directory of this project.
6078
- */
6079
- const COLUMN_STATE = new InjectionToken('COLUMN_STATE');
6080
- function columnStateFactory() {
6081
- return new BehaviorSubject({
6082
- changes: [],
6083
- });
6084
- }
6085
- const COLUMN_STATE_PROVIDER = {
6086
- provide: COLUMN_STATE,
6087
- useFactory: columnStateFactory,
6088
- };
6089
-
6090
7080
  /*
6091
7081
  * Copyright (c) 2016-2026 Broadcom. All Rights Reserved.
6092
7082
  * The term "Broadcom" refers to Broadcom Inc. and/or its subsidiaries.
@@ -6163,16 +7153,16 @@ class ClrDatagridHideableColumn {
6163
7153
  ngOnDestroy() {
6164
7154
  this.subscriptions.forEach(sub => sub.unsubscribe());
6165
7155
  }
6166
- static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.1.3", ngImport: i0, type: ClrDatagridHideableColumn, deps: [{ token: i0.TemplateRef }, { token: i0.ViewContainerRef }, { token: ColumnsService }, { token: COLUMN_STATE, optional: true }], target: i0.ɵɵFactoryTarget.Directive }); }
6167
- static { this.ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "14.0.0", version: "21.1.3", type: ClrDatagridHideableColumn, isStandalone: false, selector: "[clrDgHideableColumn]", inputs: { clrDgHideableColumn: "clrDgHideableColumn", clrDgHidden: "clrDgHidden" }, outputs: { hiddenChange: "clrDgHiddenChange" }, ngImport: i0 }); }
7156
+ static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.25", ngImport: i0, type: ClrDatagridHideableColumn, deps: [{ token: i0.TemplateRef }, { token: i0.ViewContainerRef }, { token: ColumnsService }, { token: COLUMN_STATE, optional: true }], target: i0.ɵɵFactoryTarget.Directive }); }
7157
+ static { this.ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "14.0.0", version: "21.2.25", type: ClrDatagridHideableColumn, isStandalone: false, selector: "[clrDgHideableColumn]", inputs: { clrDgHideableColumn: "clrDgHideableColumn", clrDgHidden: "clrDgHidden" }, outputs: { hiddenChange: "clrDgHiddenChange" }, ngImport: i0 }); }
6168
7158
  }
6169
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.1.3", ngImport: i0, type: ClrDatagridHideableColumn, decorators: [{
7159
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.25", ngImport: i0, type: ClrDatagridHideableColumn, decorators: [{
6170
7160
  type: Directive,
6171
7161
  args: [{
6172
7162
  selector: '[clrDgHideableColumn]',
6173
7163
  standalone: false,
6174
7164
  }]
6175
- }], ctorParameters: () => [{ type: i0.TemplateRef }, { type: i0.ViewContainerRef }, { type: ColumnsService }, { type: i2$2.BehaviorSubject, decorators: [{
7165
+ }], ctorParameters: () => [{ type: i0.TemplateRef }, { type: i0.ViewContainerRef }, { type: ColumnsService }, { type: i12.BehaviorSubject, decorators: [{
6176
7166
  type: Optional
6177
7167
  }, {
6178
7168
  type: Inject,
@@ -6265,10 +7255,10 @@ class ClrIfDetail {
6265
7255
  },
6266
7256
  });
6267
7257
  }
6268
- static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.1.3", ngImport: i0, type: ClrIfDetail, deps: [{ token: i0.TemplateRef }, { token: i0.ViewContainerRef }, { token: DetailService }], target: i0.ɵɵFactoryTarget.Directive }); }
6269
- static { this.ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "14.0.0", version: "21.1.3", type: ClrIfDetail, isStandalone: false, selector: "[clrIfDetail]", inputs: { state: ["clrIfDetail", "state"] }, outputs: { stateChange: "clrIfDetailChange" }, ngImport: i0 }); }
7258
+ static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.25", ngImport: i0, type: ClrIfDetail, deps: [{ token: i0.TemplateRef }, { token: i0.ViewContainerRef }, { token: DetailService }], target: i0.ɵɵFactoryTarget.Directive }); }
7259
+ static { this.ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "14.0.0", version: "21.2.25", type: ClrIfDetail, isStandalone: false, selector: "[clrIfDetail]", inputs: { state: ["clrIfDetail", "state"] }, outputs: { stateChange: "clrIfDetailChange" }, ngImport: i0 }); }
6270
7260
  }
6271
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.1.3", ngImport: i0, type: ClrIfDetail, decorators: [{
7261
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.25", ngImport: i0, type: ClrIfDetail, decorators: [{
6272
7262
  type: Directive,
6273
7263
  args: [{
6274
7264
  selector: '[clrIfDetail]',
@@ -6293,16 +7283,25 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.1.3", ngImpor
6293
7283
  * For instance, it can help span a text over multiple rows in detail view.
6294
7284
  */
6295
7285
  class ClrDatagridRowDetail {
6296
- constructor(selection, rowActionService, expand, expandableRows, commonStrings) {
7286
+ constructor(selection, rowActionService, expand, expandableRows, commonStrings, columnsService, displayMode) {
6297
7287
  this.selection = selection;
6298
7288
  this.rowActionService = rowActionService;
6299
7289
  this.expand = expand;
6300
7290
  this.expandableRows = expandableRows;
6301
7291
  this.commonStrings = commonStrings;
7292
+ this.columnsService = columnsService;
7293
+ this.displayMode = displayMode;
6302
7294
  this.replacedRow = false;
7295
+ /**
7296
+ * Whether the detail lays its cells out in the same columns as the row, which it does when it
7297
+ * holds one cell per column and at least one of those columns is pinned. The cells of the pinned
7298
+ * columns are then static alongside the ones in the row above.
7299
+ */
7300
+ this.columnAligned = false;
6303
7301
  /* reference to the enum so that template can access it */
6304
7302
  this.SELECTION_TYPE = SelectionType;
6305
7303
  this.subscriptions = [];
7304
+ this.cellsMoved = false;
6306
7305
  }
6307
7306
  set replace(value) {
6308
7307
  this.expand.setReplace(!!value);
@@ -6318,19 +7317,93 @@ class ClrDatagridRowDetail {
6318
7317
  ngAfterContentInit() {
6319
7318
  this.subscriptions.push(this.expand.replace.subscribe(replaceChange => {
6320
7319
  this.replacedRow = replaceChange;
6321
- }));
7320
+ }),
7321
+ // New cells have to be moved even when the columns did not change.
7322
+ this.cells.changes.subscribe(() => this.syncColumnAlignment(true)));
7323
+ }
7324
+ ngAfterViewInit() {
7325
+ this.subscriptions.push(
7326
+ // The columns are set up after the detail's content, and pinning one happens later still.
7327
+ // Both land as a new render cycle, which is where the cells are moved.
7328
+ this.displayMode.view.subscribe(() => this.syncColumnAlignment()));
7329
+ this.syncColumnAlignment(true);
7330
+ this.hadCells = this.cells?.length > 0;
7331
+ }
7332
+ ngAfterViewChecked() {
7333
+ // The template holds the content in one of two places, depending on whether the detail has cells
7334
+ // of its own, and creating either of them projects the content into it - which takes the cells
7335
+ // back out of the containers they were moved into. That happens when a detail turns up with no
7336
+ // cells and receives them later, as it does when its content is behind a `clrLoading` template.
7337
+ // By this point the swap has happened, so the move can be repeated for good.
7338
+ const hasCells = this.cells?.length > 0;
7339
+ if (hasCells !== this.hadCells) {
7340
+ this.hadCells = hasCells;
7341
+ this.syncColumnAlignment(true);
7342
+ }
6322
7343
  }
6323
7344
  ngOnDestroy() {
6324
7345
  this.subscriptions.forEach(sub => sub.unsubscribe());
6325
7346
  }
6326
- static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.1.3", ngImport: i0, type: ClrDatagridRowDetail, deps: [{ token: Selection }, { token: RowActionService }, { token: DatagridIfExpandService }, { token: ExpandableRowsCount }, { token: i2.ClrCommonStringsService }], target: i0.ɵɵFactoryTarget.Component }); }
6327
- static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.1.3", type: ClrDatagridRowDetail, isStandalone: false, selector: "clr-dg-row-detail", inputs: { _beginningOfExpandableContentAriaText: ["clrRowDetailBeginningAriaText", "_beginningOfExpandableContentAriaText"], _endOfExpandableContentAriaText: ["clrRowDetailEndAriaText", "_endOfExpandableContentAriaText"], replace: ["clrDgReplace", "replace"] }, host: { attributes: { "role": "row" }, properties: { "class.datagrid-row-flex": "true", "class.datagrid-row-detail": "true", "attr.id": "expand.expandableId" } }, queries: [{ propertyName: "cells", predicate: ClrDatagridCell }], ngImport: i0, template: `
7347
+ /**
7348
+ * Moves the cells into the containers that lay them out in the same columns as the row, or back
7349
+ * out of them once that stops making sense.
7350
+ */
7351
+ syncColumnAlignment(force = false) {
7352
+ if (!this._pinnedCells || !this._scrollableCells) {
7353
+ return;
7354
+ }
7355
+ const columns = this.columnsService.columnStates;
7356
+ const cells = this.cells ? this.cells.toArray() : [];
7357
+ // One cell per column is what makes the two comparable. Pinning is what makes the split worth
7358
+ // doing at all: with nothing pinned there is nothing to line up with, and the detail is left
7359
+ // exactly as it was authored.
7360
+ const columnAligned = cells.length > 0 && cells.length === columns.length && columns.some(column => column.pinned);
7361
+ const layout = columnAligned ? columns.map(column => (column.pinned ? '1' : '0')).join('') : '';
7362
+ if (!force && layout === this.lastLayout) {
7363
+ return;
7364
+ }
7365
+ this.lastLayout = layout;
7366
+ this.columnAligned = columnAligned;
7367
+ if (!columnAligned) {
7368
+ // Only worth doing if the cells were moved in the first place. Leaving an untouched detail
7369
+ // alone keeps whatever the author wrote between the cells where they wrote it.
7370
+ if (this.cellsMoved) {
7371
+ cells.forEach(cell => this.moveCell(this._plainCells, cell));
7372
+ this.cellsMoved = false;
7373
+ }
7374
+ return;
7375
+ }
7376
+ cells.forEach((cell, index) => this.moveCell(this.columnsService.isPinned(index) ? this._pinnedCells : this._scrollableCells, cell));
7377
+ this.cellsMoved = true;
7378
+ }
7379
+ moveCell(container, cell) {
7380
+ if (container && !cell._view.destroyed) {
7381
+ container.insert(cell._view);
7382
+ }
7383
+ }
7384
+ static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.25", ngImport: i0, type: ClrDatagridRowDetail, deps: [{ token: Selection }, { token: RowActionService }, { token: DatagridIfExpandService }, { token: ExpandableRowsCount }, { token: i2.ClrCommonStringsService }, { token: ColumnsService }, { token: DisplayModeService }], target: i0.ɵɵFactoryTarget.Component }); }
7385
+ static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.2.25", type: ClrDatagridRowDetail, isStandalone: false, selector: "clr-dg-row-detail", inputs: { _beginningOfExpandableContentAriaText: ["clrRowDetailBeginningAriaText", "_beginningOfExpandableContentAriaText"], _endOfExpandableContentAriaText: ["clrRowDetailEndAriaText", "_endOfExpandableContentAriaText"], replace: ["clrDgReplace", "replace"] }, host: { attributes: { "role": "row" }, properties: { "class.datagrid-row-flex": "true", "class.datagrid-row-detail": "true", "attr.id": "expand.expandableId" } }, queries: [{ propertyName: "cells", predicate: ClrDatagridCell }], viewQueries: [{ propertyName: "_pinnedCells", first: true, predicate: ["pinnedCells"], descendants: true, read: ViewContainerRef }, { propertyName: "_scrollableCells", first: true, predicate: ["scrollableCells"], descendants: true, read: ViewContainerRef }, { propertyName: "_plainCells", first: true, predicate: ["plainCells"], descendants: true, read: ViewContainerRef }], ngImport: i0, template: `
6328
7386
  <div class="clr-sr-only">
6329
7387
  {{ beginningOfExpandableContentAriaText }}
6330
7388
  {{ commonStrings.keys.datagridExpandableRowsHelperText }}
6331
7389
  </div>
7390
+ <!--
7391
+ These two containers mirror the ones in the row above and are only used while the detail is
7392
+ column aligned - see columnAligned. They are always rendered so the cells always have
7393
+ somewhere to be moved into, and the pinned one takes itself out of the layout while empty.
7394
+ -->
7395
+ <div class="datagrid-pinned-cells">
7396
+ <ng-container #pinnedCells></ng-container>
7397
+ </div>
7398
+ <ng-container #scrollableCells></ng-container>
6332
7399
  @if (this.cells?.length > 0) {
6333
7400
  <ng-container [ngTemplateOutlet]="noCells"></ng-container>
7401
+ <!--
7402
+ Where the cells go back to when the detail stops being column aligned, because a column was
7403
+ unpinned. A view that has been moved into a container cannot be handed back to the content
7404
+ projection it came from, so it needs a container of its own in the same place.
7405
+ -->
7406
+ <ng-container #plainCells></ng-container>
6334
7407
  }
6335
7408
  @if (this.cells?.length === 0) {
6336
7409
  <clr-dg-cell class="datagrid-container">
@@ -6342,9 +7415,9 @@ class ClrDatagridRowDetail {
6342
7415
  <ng-content></ng-content>
6343
7416
  </ng-template>
6344
7417
  <div class="clr-sr-only">{{ endOfExpandableContentAriaText }}</div>
6345
- `, isInline: true, dependencies: [{ kind: "directive", type: i9.NgTemplateOutlet, selector: "[ngTemplateOutlet]", inputs: ["ngTemplateOutletContext", "ngTemplateOutlet", "ngTemplateOutletInjector"] }, { kind: "component", type: ClrDatagridCell, selector: "clr-dg-cell" }, { kind: "directive", type: DatagridCellRenderer, selector: "clr-dg-cell" }] }); }
7418
+ `, isInline: true, dependencies: [{ kind: "directive", type: i10.NgTemplateOutlet, selector: "[ngTemplateOutlet]", inputs: ["ngTemplateOutletContext", "ngTemplateOutlet", "ngTemplateOutletInjector"] }, { kind: "component", type: ClrDatagridCell, selector: "clr-dg-cell" }, { kind: "directive", type: DatagridCellRenderer, selector: "clr-dg-cell" }] }); }
6346
7419
  }
6347
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.1.3", ngImport: i0, type: ClrDatagridRowDetail, decorators: [{
7420
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.25", ngImport: i0, type: ClrDatagridRowDetail, decorators: [{
6348
7421
  type: Component,
6349
7422
  args: [{
6350
7423
  selector: 'clr-dg-row-detail',
@@ -6353,8 +7426,23 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.1.3", ngImpor
6353
7426
  {{ beginningOfExpandableContentAriaText }}
6354
7427
  {{ commonStrings.keys.datagridExpandableRowsHelperText }}
6355
7428
  </div>
7429
+ <!--
7430
+ These two containers mirror the ones in the row above and are only used while the detail is
7431
+ column aligned - see columnAligned. They are always rendered so the cells always have
7432
+ somewhere to be moved into, and the pinned one takes itself out of the layout while empty.
7433
+ -->
7434
+ <div class="datagrid-pinned-cells">
7435
+ <ng-container #pinnedCells></ng-container>
7436
+ </div>
7437
+ <ng-container #scrollableCells></ng-container>
6356
7438
  @if (this.cells?.length > 0) {
6357
7439
  <ng-container [ngTemplateOutlet]="noCells"></ng-container>
7440
+ <!--
7441
+ Where the cells go back to when the detail stops being column aligned, because a column was
7442
+ unpinned. A view that has been moved into a container cannot be handed back to the content
7443
+ projection it came from, so it needs a container of its own in the same place.
7444
+ -->
7445
+ <ng-container #plainCells></ng-container>
6358
7446
  }
6359
7447
  @if (this.cells?.length === 0) {
6360
7448
  <clr-dg-cell class="datagrid-container">
@@ -6375,7 +7463,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.1.3", ngImpor
6375
7463
  },
6376
7464
  standalone: false,
6377
7465
  }]
6378
- }], ctorParameters: () => [{ type: Selection }, { type: RowActionService }, { type: DatagridIfExpandService }, { type: ExpandableRowsCount }, { type: i2.ClrCommonStringsService }], propDecorators: { _beginningOfExpandableContentAriaText: [{
7466
+ }], ctorParameters: () => [{ type: Selection }, { type: RowActionService }, { type: DatagridIfExpandService }, { type: ExpandableRowsCount }, { type: i2.ClrCommonStringsService }, { type: ColumnsService }, { type: DisplayModeService }], propDecorators: { _beginningOfExpandableContentAriaText: [{
6379
7467
  type: Input,
6380
7468
  args: ['clrRowDetailBeginningAriaText']
6381
7469
  }], _endOfExpandableContentAriaText: [{
@@ -6384,6 +7472,15 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.1.3", ngImpor
6384
7472
  }], cells: [{
6385
7473
  type: ContentChildren,
6386
7474
  args: [ClrDatagridCell]
7475
+ }], _pinnedCells: [{
7476
+ type: ViewChild,
7477
+ args: ['pinnedCells', { read: ViewContainerRef }]
7478
+ }], _scrollableCells: [{
7479
+ type: ViewChild,
7480
+ args: ['scrollableCells', { read: ViewContainerRef }]
7481
+ }], _plainCells: [{
7482
+ type: ViewChild,
7483
+ args: ['plainCells', { read: ViewContainerRef }]
6387
7484
  }], replace: [{
6388
7485
  type: Input,
6389
7486
  args: ['clrDgReplace']
@@ -6407,8 +7504,8 @@ class ClrDatagridFooter {
6407
7504
  get hasHideableColumns() {
6408
7505
  return this.columnsService.hasHideableColumns;
6409
7506
  }
6410
- static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.1.3", ngImport: i0, type: ClrDatagridFooter, deps: [{ token: Selection }, { token: DetailService }, { token: ColumnsService }, { token: i2.ClrCommonStringsService }], target: i0.ɵɵFactoryTarget.Component }); }
6411
- static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.1.3", type: ClrDatagridFooter, isStandalone: false, selector: "clr-dg-footer", host: { properties: { "class.datagrid-footer": "true" } }, ngImport: i0, template: `
7507
+ static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.25", ngImport: i0, type: ClrDatagridFooter, deps: [{ token: Selection }, { token: DetailService }, { token: ColumnsService }, { token: i2.ClrCommonStringsService }], target: i0.ɵɵFactoryTarget.Component }); }
7508
+ static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.2.25", type: ClrDatagridFooter, isStandalone: false, selector: "clr-dg-footer", host: { properties: { "class.datagrid-footer": "true" } }, ngImport: i0, template: `
6412
7509
  @if (selection.selectionType === SELECTION_TYPE.Multi && selection.current?.length > 0) {
6413
7510
  <div class="clr-form-control-disabled">
6414
7511
  <clr-checkbox-wrapper class="datagrid-footer-select">
@@ -6427,9 +7524,9 @@ class ClrDatagridFooter {
6427
7524
  </div>
6428
7525
  }
6429
7526
  <ng-content select="clr-dg-pagination"></ng-content>
6430
- `, isInline: true, dependencies: [{ kind: "directive", type: i4.ClrControlLabel, selector: "label", inputs: ["id", "for"] }, { kind: "directive", type: i7.ClrCheckbox, selector: "[clrCheckbox],[clrToggle]" }, { kind: "component", type: i7.ClrCheckboxWrapper, selector: "clr-checkbox-wrapper,clr-toggle-wrapper" }, { kind: "component", type: ClrDatagridColumnToggle, selector: "clr-dg-column-toggle" }] }); }
7527
+ `, isInline: true, dependencies: [{ kind: "directive", type: i4$1.ClrControlLabel, selector: "label", inputs: ["id", "for"] }, { kind: "directive", type: i7.ClrCheckbox, selector: "[clrCheckbox],[clrToggle]" }, { kind: "component", type: i7.ClrCheckboxWrapper, selector: "clr-checkbox-wrapper,clr-toggle-wrapper" }, { kind: "component", type: ClrDatagridColumnToggle, selector: "clr-dg-column-toggle" }] }); }
6431
7528
  }
6432
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.1.3", ngImport: i0, type: ClrDatagridFooter, decorators: [{
7529
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.25", ngImport: i0, type: ClrDatagridFooter, decorators: [{
6433
7530
  type: Component,
6434
7531
  args: [{
6435
7532
  selector: 'clr-dg-footer',
@@ -6481,8 +7578,8 @@ class ClrDatagridPageSize {
6481
7578
  this.pageSizeOptions = [this.page.size];
6482
7579
  }
6483
7580
  }
6484
- static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.1.3", ngImport: i0, type: ClrDatagridPageSize, deps: [{ token: Page }], target: i0.ɵɵFactoryTarget.Component }); }
6485
- static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.1.3", type: ClrDatagridPageSize, isStandalone: false, selector: "clr-dg-page-size", inputs: { pageSizeOptions: ["clrPageSizeOptions", "pageSizeOptions"], pageSizeOptionsId: ["clrPageSizeOptionsId", "pageSizeOptionsId"] }, viewQueries: [{ propertyName: "label", first: true, predicate: ClrControlLabel, descendants: true, static: true }], ngImport: i0, template: `
7581
+ static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.25", ngImport: i0, type: ClrDatagridPageSize, deps: [{ token: Page }], target: i0.ɵɵFactoryTarget.Component }); }
7582
+ static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.2.25", type: ClrDatagridPageSize, isStandalone: false, selector: "clr-dg-page-size", inputs: { pageSizeOptions: ["clrPageSizeOptions", "pageSizeOptions"], pageSizeOptionsId: ["clrPageSizeOptionsId", "pageSizeOptionsId"] }, viewQueries: [{ propertyName: "label", first: true, predicate: ClrControlLabel, descendants: true, static: true }], ngImport: i0, template: `
6486
7583
  <label [for]="pageSizeOptionsId"><ng-content></ng-content></label>
6487
7584
  <div class="clr-select-wrapper">
6488
7585
  <select [id]="pageSizeOptionsId" [class.clr-page-size-select]="true" [(ngModel)]="page.size">
@@ -6491,9 +7588,9 @@ class ClrDatagridPageSize {
6491
7588
  }
6492
7589
  </select>
6493
7590
  </div>
6494
- `, isInline: true, dependencies: [{ kind: "directive", type: i4.ClrControlLabel, selector: "label", inputs: ["id", "for"] }, { kind: "directive", type: i13.NgSelectOption, selector: "option", inputs: ["ngValue", "value"] }, { kind: "directive", type: i13.ɵNgSelectMultipleOption, selector: "option", inputs: ["ngValue", "value"] }, { kind: "directive", type: i13.SelectControlValueAccessor, selector: "select:not([multiple])[formControlName],select:not([multiple])[formControl],select:not([multiple])[ngModel]", inputs: ["compareWith"] }, { kind: "directive", type: i13.NgControlStatus, selector: "[formControlName],[ngModel],[formControl]" }, { kind: "directive", type: i13.NgModel, selector: "[ngModel]:not([formControlName]):not([formControl])", inputs: ["name", "disabled", "ngModel", "ngModelOptions"], outputs: ["ngModelChange"], exportAs: ["ngModel"] }] }); }
7591
+ `, isInline: true, dependencies: [{ kind: "directive", type: i4$1.ClrControlLabel, selector: "label", inputs: ["id", "for"] }, { kind: "directive", type: i14.NgSelectOption, selector: "option", inputs: ["ngValue", "value"] }, { kind: "directive", type: i14.ɵNgSelectMultipleOption, selector: "option", inputs: ["ngValue", "value"] }, { kind: "directive", type: i14.SelectControlValueAccessor, selector: "select:not([multiple])[formControlName],select:not([multiple])[formControl],select:not([multiple])[ngModel]", inputs: ["compareWith"] }, { kind: "directive", type: i14.NgControlStatus, selector: "[formControlName],[ngModel],[formControl]" }, { kind: "directive", type: i14.NgModel, selector: "[ngModel]:not([formControlName]):not([formControl])", inputs: ["name", "disabled", "ngModel", "ngModelOptions"], outputs: ["ngModelChange"], exportAs: ["ngModel"] }] }); }
6495
7592
  }
6496
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.1.3", ngImport: i0, type: ClrDatagridPageSize, decorators: [{
7593
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.25", ngImport: i0, type: ClrDatagridPageSize, decorators: [{
6497
7594
  type: Component,
6498
7595
  args: [{
6499
7596
  selector: 'clr-dg-page-size',
@@ -6670,8 +7767,8 @@ class ClrDatagridPagination {
6670
7767
  */
6671
7768
  this.currentPageInputRef.nativeElement.value = this.page.current.toString();
6672
7769
  }
6673
- static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.1.3", ngImport: i0, type: ClrDatagridPagination, deps: [{ token: Page }, { token: i2.ClrCommonStringsService }, { token: DetailService }], target: i0.ɵɵFactoryTarget.Component }); }
6674
- static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.1.3", type: ClrDatagridPagination, isStandalone: false, selector: "clr-dg-pagination", inputs: { disableCurrentPageInput: ["clrDgPageInputDisabled", "disableCurrentPageInput"], pageSize: ["clrDgPageSize", "pageSize"], totalItems: ["clrDgTotalItems", "totalItems"], lastPage: ["clrDgLastPage", "lastPage"], currentPage: ["clrDgPage", "currentPage"] }, outputs: { currentChanged: "clrDgPageChange" }, host: { properties: { "class.pagination": "true" } }, queries: [{ propertyName: "_pageSizeComponent", first: true, predicate: ClrDatagridPageSize, descendants: true }], viewQueries: [{ propertyName: "currentPageInputRef", first: true, predicate: ["currentPageInput"], descendants: true }], ngImport: i0, template: `
7770
+ static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.25", ngImport: i0, type: ClrDatagridPagination, deps: [{ token: Page }, { token: i2.ClrCommonStringsService }, { token: DetailService }], target: i0.ɵɵFactoryTarget.Component }); }
7771
+ static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.2.25", type: ClrDatagridPagination, isStandalone: false, selector: "clr-dg-pagination", inputs: { disableCurrentPageInput: ["clrDgPageInputDisabled", "disableCurrentPageInput"], pageSize: ["clrDgPageSize", "pageSize"], totalItems: ["clrDgTotalItems", "totalItems"], lastPage: ["clrDgLastPage", "lastPage"], currentPage: ["clrDgPage", "currentPage"] }, outputs: { currentChanged: "clrDgPageChange" }, host: { properties: { "class.pagination": "true" } }, queries: [{ propertyName: "_pageSizeComponent", first: true, predicate: ClrDatagridPageSize, descendants: true }], viewQueries: [{ propertyName: "currentPageInputRef", first: true, predicate: ["currentPageInput"], descendants: true }], ngImport: i0, template: `
6675
7772
  @if (!detailService.isOpen) {
6676
7773
  @if (_pageSizeComponent) {
6677
7774
  <div class="pagination-size">
@@ -6771,9 +7868,9 @@ class ClrDatagridPagination {
6771
7868
  </button>
6772
7869
  </div>
6773
7870
  }
6774
- `, isInline: true, dependencies: [{ kind: "component", type: i5.ClrIcon, selector: "clr-icon, cds-icon", inputs: ["shape", "size", "direction", "flip", "solid", "status", "inverse", "badge"] }] }); }
7871
+ `, isInline: true, dependencies: [{ kind: "component", type: i4.ClrIcon, selector: "clr-icon, cds-icon", inputs: ["shape", "size", "direction", "flip", "solid", "status", "inverse", "badge", "innerOffset"] }] }); }
6775
7872
  }
6776
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.1.3", ngImport: i0, type: ClrDatagridPagination, decorators: [{
7873
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.25", ngImport: i0, type: ClrDatagridPagination, decorators: [{
6777
7874
  type: Component,
6778
7875
  args: [{
6779
7876
  selector: 'clr-dg-pagination',
@@ -6971,10 +8068,10 @@ class DatagridDetailRegisterer {
6971
8068
  this.expandableRowsCount.unregister();
6972
8069
  }
6973
8070
  }
6974
- static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.1.3", ngImport: i0, type: DatagridDetailRegisterer, deps: [{ token: ExpandableRowsCount, optional: true }], target: i0.ɵɵFactoryTarget.Directive }); }
6975
- static { this.ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "14.0.0", version: "21.1.3", type: DatagridDetailRegisterer, isStandalone: false, selector: "[clrIfExpanded]", ngImport: i0 }); }
8071
+ static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.25", ngImport: i0, type: DatagridDetailRegisterer, deps: [{ token: ExpandableRowsCount, optional: true }], target: i0.ɵɵFactoryTarget.Directive }); }
8072
+ static { this.ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "14.0.0", version: "21.2.25", type: DatagridDetailRegisterer, isStandalone: false, selector: "[clrIfExpanded]", ngImport: i0 }); }
6976
8073
  }
6977
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.1.3", ngImport: i0, type: DatagridDetailRegisterer, decorators: [{
8074
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.25", ngImport: i0, type: DatagridDetailRegisterer, decorators: [{
6978
8075
  type: Directive,
6979
8076
  args: [{
6980
8077
  selector: '[clrIfExpanded]',
@@ -7046,6 +8143,14 @@ class DatagridHeaderRenderer {
7046
8143
  this.renderer.removeClass(this.el.nativeElement, HIDDEN_COLUMN_CLASS);
7047
8144
  }
7048
8145
  }
8146
+ setPinned(state) {
8147
+ if (state.pinned) {
8148
+ this.renderer.addClass(this.el.nativeElement, PINNED_COLUMN_CLASS);
8149
+ }
8150
+ else {
8151
+ this.renderer.removeClass(this.el.nativeElement, PINNED_COLUMN_CLASS);
8152
+ }
8153
+ }
7049
8154
  clearWidth() {
7050
8155
  // remove the width only if we set it, and it is not changed by dragging.
7051
8156
  if (this.widthSet && !this.columnResizerService.resizedBy) {
@@ -7073,17 +8178,17 @@ class DatagridHeaderRenderer {
7073
8178
  }
7074
8179
  return width;
7075
8180
  }
7076
- static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.1.3", ngImport: i0, type: DatagridHeaderRenderer, deps: [{ token: i0.ElementRef }, { token: i0.Renderer2 }, { token: DatagridRenderOrganizer }, { token: i2.DomAdapter }, { token: ColumnResizerService }, { token: ColumnsService }, { token: COLUMN_STATE }], target: i0.ɵɵFactoryTarget.Directive }); }
7077
- static { this.ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "14.0.0", version: "21.1.3", type: DatagridHeaderRenderer, isStandalone: false, selector: "clr-dg-column", outputs: { resizeEmitter: "clrDgColumnResize" }, providers: [ColumnResizerService, COLUMN_STATE_PROVIDER], ngImport: i0 }); }
8181
+ static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.25", ngImport: i0, type: DatagridHeaderRenderer, deps: [{ token: i0.ElementRef }, { token: i0.Renderer2 }, { token: DatagridRenderOrganizer }, { token: i2.DomAdapter }, { token: ColumnResizerService }, { token: ColumnsService }, { token: COLUMN_STATE }], target: i0.ɵɵFactoryTarget.Directive }); }
8182
+ static { this.ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "14.0.0", version: "21.2.25", type: DatagridHeaderRenderer, isStandalone: false, selector: "clr-dg-column", outputs: { resizeEmitter: "clrDgColumnResize" }, providers: [ColumnResizerService, COLUMN_STATE_PROVIDER], ngImport: i0 }); }
7078
8183
  }
7079
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.1.3", ngImport: i0, type: DatagridHeaderRenderer, decorators: [{
8184
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.25", ngImport: i0, type: DatagridHeaderRenderer, decorators: [{
7080
8185
  type: Directive,
7081
8186
  args: [{
7082
8187
  selector: 'clr-dg-column',
7083
8188
  providers: [ColumnResizerService, COLUMN_STATE_PROVIDER],
7084
8189
  standalone: false,
7085
8190
  }]
7086
- }], ctorParameters: () => [{ type: i0.ElementRef }, { type: i0.Renderer2 }, { type: DatagridRenderOrganizer }, { type: i2.DomAdapter }, { type: ColumnResizerService }, { type: ColumnsService }, { type: i2$2.BehaviorSubject, decorators: [{
8191
+ }], ctorParameters: () => [{ type: i0.ElementRef }, { type: i0.Renderer2 }, { type: DatagridRenderOrganizer }, { type: i2.DomAdapter }, { type: ColumnResizerService }, { type: ColumnsService }, { type: i12.BehaviorSubject, decorators: [{
7087
8192
  type: Inject,
7088
8193
  args: [COLUMN_STATE]
7089
8194
  }] }], propDecorators: { resizeEmitter: [{
@@ -7130,10 +8235,10 @@ class NoopDomAdapter {
7130
8235
  focus(_element) {
7131
8236
  // Do nothing
7132
8237
  }
7133
- static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.1.3", ngImport: i0, type: NoopDomAdapter, deps: [], target: i0.ɵɵFactoryTarget.Injectable }); }
7134
- static { this.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "21.1.3", ngImport: i0, type: NoopDomAdapter }); }
8238
+ static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.25", ngImport: i0, type: NoopDomAdapter, deps: [], target: i0.ɵɵFactoryTarget.Injectable }); }
8239
+ static { this.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "21.2.25", ngImport: i0, type: NoopDomAdapter }); }
7135
8240
  }
7136
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.1.3", ngImport: i0, type: NoopDomAdapter, decorators: [{
8241
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.25", ngImport: i0, type: NoopDomAdapter, decorators: [{
7137
8242
  type: Injectable
7138
8243
  }] });
7139
8244
 
@@ -7237,13 +8342,27 @@ class DatagridMainRenderer {
7237
8342
  if (this.headers) {
7238
8343
  if (state && !this.columnsService.hasCache()) {
7239
8344
  this.columnsService.cache();
7240
- this.columnsService.visibleColumns.forEach((header, index) => {
7241
- if (index > 0) {
8345
+ // The pane leaves room for a single column, and it should be the one the user was already
8346
+ // looking at on the left of the row. Pinned columns are rendered before the rest, so that
8347
+ // is the first pinned column whenever anything is pinned, and the first declared one
8348
+ // otherwise.
8349
+ const keptColumn = this.columnsService.visibleColumns.find(column => column.pinned) || this.columnsService.visibleColumns[0];
8350
+ this.columnsService.visibleColumns.forEach(header => {
8351
+ if (header !== keptColumn) {
7242
8352
  this.columnsService.emitStateChangeAt(header.columnIndex, {
7243
8353
  changes: [DatagridColumnChanges.HIDDEN],
7244
8354
  hidden: state,
7245
8355
  });
7246
8356
  }
8357
+ // That single column is full width, so there is nothing to scroll and nothing to pin
8358
+ // against - the column that stays included. Pinning is suspended while the pane is open
8359
+ // and restored from the cache when it closes.
8360
+ if (header.pinned) {
8361
+ this.columnsService.emitStateChangeAt(header.columnIndex, {
8362
+ changes: [DatagridColumnChanges.PINNED],
8363
+ pinned: false,
8364
+ });
8365
+ }
7247
8366
  });
7248
8367
  }
7249
8368
  else if (!state) {
@@ -7336,15 +8455,47 @@ class DatagridMainRenderer {
7336
8455
  this.updateColumnSeparatorsVisibility();
7337
8456
  this.keyNavigation.resetKeyGrid();
7338
8457
  break;
8458
+ case DatagridColumnChanges.PINNED: {
8459
+ // Read before the class is updated below. The state can be re-emitted with the same
8460
+ // value, e.g. by resetToLastCache, and relocating the views then is pure overhead.
8461
+ const wasPinned = this.datagrid.columns.get(columnIndex)?.isPinned;
8462
+ this.headers.get(columnIndex).setPinned(state);
8463
+ this.rows.forEach(row => {
8464
+ if (row.cells && row.cells.length) {
8465
+ row.cells.get(columnIndex)?.setPinned(state);
8466
+ row.expandableRows.forEach(expandableRow => {
8467
+ expandableRow.cells.get(columnIndex)?.setPinned(state);
8468
+ });
8469
+ }
8470
+ });
8471
+ if (wasPinned !== !!state.pinned) {
8472
+ this.updateColumnSeparatorsVisibility();
8473
+ this.keyNavigation.resetKeyGrid();
8474
+ // The column and its cells have to move between the static and the scrollable
8475
+ // containers, which happens on the next CALCULATE/DISPLAY cycle. Widths are
8476
+ // recomputed there as well, since the flex context of the column changes.
8477
+ // Deferring to ngAfterViewChecked keeps us out of the change detection pass that
8478
+ // the `clrDgPinned` input setter runs in.
8479
+ this.columnsSizesStable = false;
8480
+ this.shouldStabilizeColumns = true;
8481
+ }
8482
+ break;
8483
+ }
7339
8484
  case DatagridColumnChanges.INITIALIZE:
8485
+ if (state.pinned) {
8486
+ this.headers.get(columnIndex).setPinned(state);
8487
+ }
7340
8488
  if (state.hideable && state.hidden) {
7341
8489
  this.headers.get(columnIndex).setHidden(state);
8490
+ }
8491
+ if (state.pinned || (state.hideable && state.hidden)) {
7342
8492
  this.rows.forEach(row => {
7343
8493
  row.setCellsState();
7344
8494
  row.expandableRows.forEach(expandableRow => {
7345
8495
  expandableRow.setCellsState();
7346
8496
  });
7347
8497
  });
8498
+ this.updateColumnSeparatorsVisibility();
7348
8499
  }
7349
8500
  break;
7350
8501
  default:
@@ -7369,19 +8520,22 @@ class DatagridMainRenderer {
7369
8520
  }
7370
8521
  updateColumnSeparatorsVisibility() {
7371
8522
  const visibleColumns = this.datagrid.columns.filter(column => !column.isHidden);
7372
- visibleColumns.forEach((column, index) => {
7373
- if (index === visibleColumns.length - 1) {
7374
- column.showSeparator = false;
7375
- }
7376
- else if (!column.showSeparator) {
7377
- column.showSeparator = true;
8523
+ // Pinned columns are rendered in the static container, so they always have something after
8524
+ // them and keep their separator - it is what marks the boundary with the scrollable columns.
8525
+ // Only the last scrollable column has nothing after it and must hide its separator.
8526
+ const scrollableColumns = visibleColumns.filter(column => !column.isPinned);
8527
+ const lastScrollableColumn = scrollableColumns[scrollableColumns.length - 1];
8528
+ visibleColumns.forEach(column => {
8529
+ const showSeparator = column !== lastScrollableColumn;
8530
+ if (column.showSeparator !== showSeparator) {
8531
+ column.showSeparator = showSeparator;
7378
8532
  }
7379
8533
  });
7380
8534
  }
7381
- static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.1.3", ngImport: i0, type: DatagridMainRenderer, deps: [{ token: ClrDatagrid }, { token: DatagridRenderOrganizer }, { token: Items }, { token: Page }, { token: i0.ElementRef }, { token: i0.Renderer2 }, { token: DetailService }, { token: TableSizeService }, { token: ColumnsService }, { token: i0.NgZone }, { token: KeyNavigationGridController }, { token: i0.ChangeDetectorRef }], target: i0.ɵɵFactoryTarget.Directive }); }
7382
- static { this.ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "14.0.0", version: "21.1.3", type: DatagridMainRenderer, isStandalone: false, selector: "clr-datagrid", providers: [{ provide: DomAdapter, useFactory: domAdapterFactory, deps: [PLATFORM_ID] }], queries: [{ propertyName: "headers", predicate: DatagridHeaderRenderer }, { propertyName: "rows", predicate: DatagridRowRenderer }], ngImport: i0 }); }
8535
+ static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.25", ngImport: i0, type: DatagridMainRenderer, deps: [{ token: ClrDatagrid }, { token: DatagridRenderOrganizer }, { token: Items }, { token: Page }, { token: i0.ElementRef }, { token: i0.Renderer2 }, { token: DetailService }, { token: TableSizeService }, { token: ColumnsService }, { token: i0.NgZone }, { token: KeyNavigationGridController }, { token: i0.ChangeDetectorRef }], target: i0.ɵɵFactoryTarget.Directive }); }
8536
+ static { this.ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "14.0.0", version: "21.2.25", type: DatagridMainRenderer, isStandalone: false, selector: "clr-datagrid", providers: [{ provide: DomAdapter, useFactory: domAdapterFactory, deps: [PLATFORM_ID] }], queries: [{ propertyName: "headers", predicate: DatagridHeaderRenderer }, { propertyName: "rows", predicate: DatagridRowRenderer }], ngImport: i0 }); }
7383
8537
  }
7384
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.1.3", ngImport: i0, type: DatagridMainRenderer, decorators: [{
8538
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.25", ngImport: i0, type: DatagridMainRenderer, decorators: [{
7385
8539
  type: Directive,
7386
8540
  args: [{
7387
8541
  selector: 'clr-datagrid',
@@ -7412,10 +8566,10 @@ class DatagridRowDetailRenderer extends DatagridRowRenderer {
7412
8566
  this.parentRow.expandableRows = [];
7413
8567
  super.ngOnDestroy();
7414
8568
  }
7415
- static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.1.3", ngImport: i0, type: DatagridRowDetailRenderer, deps: [{ token: DatagridRowRenderer }, { token: ColumnsService }, { token: i0.ElementRef }], target: i0.ɵɵFactoryTarget.Directive }); }
7416
- static { this.ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "14.0.0", version: "21.1.3", type: DatagridRowDetailRenderer, isStandalone: false, selector: "clr-dg-row-detail", usesInheritance: true, ngImport: i0 }); }
8569
+ static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.25", ngImport: i0, type: DatagridRowDetailRenderer, deps: [{ token: DatagridRowRenderer }, { token: ColumnsService }, { token: i0.ElementRef }], target: i0.ɵɵFactoryTarget.Directive }); }
8570
+ static { this.ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "14.0.0", version: "21.2.25", type: DatagridRowDetailRenderer, isStandalone: false, selector: "clr-dg-row-detail", usesInheritance: true, ngImport: i0 }); }
7417
8571
  }
7418
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.1.3", ngImport: i0, type: DatagridRowDetailRenderer, decorators: [{
8572
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.25", ngImport: i0, type: DatagridRowDetailRenderer, decorators: [{
7419
8573
  type: Directive,
7420
8574
  args: [{
7421
8575
  selector: 'clr-dg-row-detail',
@@ -7436,6 +8590,8 @@ const CLR_DATAGRID_DIRECTIVES = [
7436
8590
  ClrDatagridActionOverflow,
7437
8591
  ClrDatagridCell,
7438
8592
  ClrDatagridColumn,
8593
+ ClrDatagridColumnAction,
8594
+ ClrDatagridColumnActions,
7439
8595
  ClrDatagridColumnSeparator,
7440
8596
  ClrDatagridDetail,
7441
8597
  ClrDatagridDetailBody,
@@ -7475,16 +8631,18 @@ const CLR_DATAGRID_STANDALONE_DIRECTIVES = [ClrDatagridSingleSelectionValueAcces
7475
8631
  const CLR_DATAGRID_SHARED_DIRECTIVES = [ClrIfExpanded];
7476
8632
  class ClrDatagridModule {
7477
8633
  constructor() {
7478
- ClarityIcons.addIcons(ellipsisVerticalIcon, viewColumnsIcon, windowCloseIcon, arrowIcon, timesIcon, twoWayArrowsIcon, stepForward2Icon, angleDoubleIcon, filterGridCircleIcon, filterGridIcon);
8634
+ ClarityIcons.addIcons(ellipsisVerticalIcon, ellipsisGridCircleIcon, viewColumnsIcon, windowCloseIcon, arrowIcon, timesIcon, twoWayArrowsIcon, stepForward2Icon, angleDoubleIcon, filterGridCircleIcon, filterGridIcon, pinIcon, unpinIcon);
7479
8635
  }
7480
- static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.1.3", ngImport: i0, type: ClrDatagridModule, deps: [], target: i0.ɵɵFactoryTarget.NgModule }); }
7481
- static { this.ɵmod = i0.ɵɵngDeclareNgModule({ minVersion: "14.0.0", version: "21.1.3", ngImport: i0, type: ClrDatagridModule, declarations: [
8636
+ static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.25", ngImport: i0, type: ClrDatagridModule, deps: [], target: i0.ɵɵFactoryTarget.NgModule }); }
8637
+ static { this.ɵmod = i0.ɵɵngDeclareNgModule({ minVersion: "14.0.0", version: "21.2.25", ngImport: i0, type: ClrDatagridModule, declarations: [
7482
8638
  // Core
7483
8639
  ClrDatagrid,
7484
8640
  ClrDatagridActionBar,
7485
8641
  ClrDatagridActionOverflow,
7486
8642
  ClrDatagridCell,
7487
8643
  ClrDatagridColumn,
8644
+ ClrDatagridColumnAction,
8645
+ ClrDatagridColumnActions,
7488
8646
  ClrDatagridColumnSeparator,
7489
8647
  ClrDatagridDetail,
7490
8648
  ClrDatagridDetailBody,
@@ -7533,6 +8691,7 @@ class ClrDatagridModule {
7533
8691
  ClrExpandableAnimationModule,
7534
8692
  ClrSpinnerModule,
7535
8693
  ClrPopoverModuleNext,
8694
+ ClrDropdownModule,
7536
8695
  ClrKeyFocusModule, ClrDatagridSingleSelectionValueAccessor, ClrIfExpanded], exports: [
7537
8696
  // Core
7538
8697
  ClrDatagrid,
@@ -7540,6 +8699,8 @@ class ClrDatagridModule {
7540
8699
  ClrDatagridActionOverflow,
7541
8700
  ClrDatagridCell,
7542
8701
  ClrDatagridColumn,
8702
+ ClrDatagridColumnAction,
8703
+ ClrDatagridColumnActions,
7543
8704
  ClrDatagridColumnSeparator,
7544
8705
  ClrDatagridDetail,
7545
8706
  ClrDatagridDetailBody,
@@ -7573,7 +8734,7 @@ class ClrDatagridModule {
7573
8734
  // Built-in shortcuts
7574
8735
  DatagridNumericFilter,
7575
8736
  DatagridStringFilter, ClrDatagridSingleSelectionValueAccessor, ClrIfExpanded] }); }
7576
- static { this.ɵinj = i0.ɵɵngDeclareInjector({ minVersion: "12.0.0", version: "21.1.3", ngImport: i0, type: ClrDatagridModule, imports: [CommonModule,
8737
+ static { this.ɵinj = i0.ɵɵngDeclareInjector({ minVersion: "12.0.0", version: "21.2.25", ngImport: i0, type: ClrDatagridModule, imports: [CommonModule,
7577
8738
  CdkDragModule,
7578
8739
  CdkTrapFocusModule,
7579
8740
  ClrIcon,
@@ -7589,9 +8750,10 @@ class ClrDatagridModule {
7589
8750
  ClrExpandableAnimationModule,
7590
8751
  ClrSpinnerModule,
7591
8752
  ClrPopoverModuleNext,
8753
+ ClrDropdownModule,
7592
8754
  ClrKeyFocusModule] }); }
7593
8755
  }
7594
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.1.3", ngImport: i0, type: ClrDatagridModule, decorators: [{
8756
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.25", ngImport: i0, type: ClrDatagridModule, decorators: [{
7595
8757
  type: NgModule,
7596
8758
  args: [{
7597
8759
  imports: [
@@ -7611,6 +8773,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.1.3", ngImpor
7611
8773
  ClrExpandableAnimationModule,
7612
8774
  ClrSpinnerModule,
7613
8775
  ClrPopoverModuleNext,
8776
+ ClrDropdownModule,
7614
8777
  ClrKeyFocusModule,
7615
8778
  CLR_DATAGRID_STANDALONE_DIRECTIVES,
7616
8779
  CLR_DATAGRID_SHARED_DIRECTIVES,
@@ -7631,5 +8794,5 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.1.3", ngImpor
7631
8794
  * Generated bundle index. Do not edit.
7632
8795
  */
7633
8796
 
7634
- export { ActionableOompaLoompa, CLR_DATAGRID_DIRECTIVES, ClrDatagrid, ClrDatagridActionBar, ClrDatagridActionOverflow, ClrDatagridAriaSortOrder, ClrDatagridCell, ClrDatagridColumn, ClrDatagridColumnSeparator, ClrDatagridColumnToggle, ClrDatagridColumnToggleButton, ClrDatagridDetail, ClrDatagridDetailBody, ClrDatagridDetailHeader, ClrDatagridFilter, ClrDatagridFooter, ClrDatagridHideableColumn, ClrDatagridItems, ClrDatagridModule, ClrDatagridPageSize, ClrDatagridPagination, ClrDatagridPlaceholder, ClrDatagridRow, ClrDatagridRowDetail, ClrDatagridSelectionCellDirective, ClrDatagridSingleSelectionValueAccessor, ClrDatagridSortOrder, ClrDatagridVirtualScrollDirective, ClrIfDetail, DatagridCellRenderer, DatagridDetailRegisterer, DatagridHeaderRenderer, DatagridMainRenderer, DatagridNumericFilter, DatagridPropertyComparator, DatagridPropertyNumericFilter, DatagridPropertyStringFilter, DatagridRowDetailRenderer, DatagridRowRenderer, DatagridStringFilter, DatagridWillyWonka, ExpandableOompaLoompa, Selection, SelectionType, WrappedCell, WrappedColumn, WrappedRow, selectionTypeAttribute };
8797
+ export { ActionableOompaLoompa, CLR_DATAGRID_DIRECTIVES, ClrDatagrid, ClrDatagridActionBar, ClrDatagridActionOverflow, ClrDatagridAriaSortOrder, ClrDatagridCell, ClrDatagridColumn, ClrDatagridColumnAction, ClrDatagridColumnActions, ClrDatagridColumnSeparator, ClrDatagridColumnToggle, ClrDatagridColumnToggleButton, ClrDatagridDetail, ClrDatagridDetailBody, ClrDatagridDetailHeader, ClrDatagridFilter, ClrDatagridFooter, ClrDatagridHideableColumn, ClrDatagridItems, ClrDatagridModule, ClrDatagridPageSize, ClrDatagridPagination, ClrDatagridPlaceholder, ClrDatagridRow, ClrDatagridRowDetail, ClrDatagridSelectionCellDirective, ClrDatagridSingleSelectionValueAccessor, ClrDatagridSortOrder, ClrDatagridVirtualScrollDirective, ClrIfDetail, DatagridCellRenderer, DatagridDetailRegisterer, DatagridHeaderRenderer, DatagridMainRenderer, DatagridNumericFilter, DatagridPropertyComparator, DatagridPropertyNumericFilter, DatagridPropertyStringFilter, DatagridRowDetailRenderer, DatagridRowRenderer, DatagridStringFilter, DatagridWillyWonka, ExpandableOompaLoompa, Selection, SelectionType, WrappedCell, WrappedColumn, WrappedRow, selectionTypeAttribute };
7635
8798
  //# sourceMappingURL=clr-angular-data-datagrid.mjs.map