@reforgium/data-grid 2.2.3 → 2.3.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -593,42 +593,82 @@ import { DataGridColumnManager } from '@reforgium/data-grid/column-manager';
593
593
  <re-data-grid [columns]="managedColumns()" ... />
594
594
  ```
595
595
 
596
- Custom trigger template:
597
-
598
- ```html
599
-
600
- <ng-template #cmTrigger let-label let-visible="visible" let-total="total">
601
- <span>{{ label }}</span>
602
- <strong>{{ visible }}/{{ total }}</strong>
603
- </ng-template>
604
-
605
- <re-data-grid-column-manager
606
- [columns]="managedColumns()"
607
- [triggerTemplate]="cmTrigger"
608
- (columnsChange)="managedColumns.set($event)"
609
- />
610
- ```
611
-
612
- Trigger template context:
613
-
614
- - `$implicit` - trigger label
615
- - `visible` - visible columns count
616
- - `total` - total columns count
617
-
618
- Inputs:
619
-
620
- - `columns: GridColumn<T>[]`
621
- - `triggerLabel?: string`
622
- - `triggerTemplate?: TemplateRef<{ $implicit: string; visible: number; total: number }>`
623
- - `controlsVisible?: boolean` - hides search and "show all / hide optional" panel
624
- - `searchable?: boolean`
625
- - `allowReorder?: boolean`
626
- - `allowPin?: boolean`
627
- - `allowVisibility?: boolean`
628
-
629
- Outputs:
630
-
631
- - `columnsChange: GridColumn<T>[]`
596
+ Custom trigger via content projection:
597
+
598
+ ```html
599
+
600
+ <re-data-grid-column-manager
601
+ triggerLabel="Columns"
602
+ [columns]="managedColumns()"
603
+ (columnsChange)="managedColumns.set($event)"
604
+ >
605
+ <span reDataGridColumnManagerTrigger>Manage columns</span>
606
+ </re-data-grid-column-manager>
607
+ ```
608
+
609
+ Custom column title template (controls stay built-in):
610
+
611
+ ```html
612
+ <re-data-grid-column-manager
613
+ [columns]="managedColumns()"
614
+ (columnsChange)="managedColumns.set($event)"
615
+ >
616
+ <ng-template reDataGridColumnManagerColumnTitle let-title let-column="column">
617
+ <span class="font-medium">{{ title }}</span>
618
+ </ng-template>
619
+ </re-data-grid-column-manager>
620
+ ```
621
+
622
+ `reDataGridColumnManagerColumnTitle` context:
623
+
624
+ - `$implicit` / `title` - resolved column title (`header || key`)
625
+ - `column` - current `GridColumn<T>`
626
+
627
+ Standalone imports for custom trigger/title markers:
628
+
629
+ ```ts
630
+ import {
631
+ DataGridColumnManager,
632
+ DataGridColumnManagerColumnTitleDirective,
633
+ DataGridColumnManagerTriggerDirective,
634
+ } from '@reforgium/data-grid/column-manager';
635
+ ```
636
+
637
+ ```ts
638
+ @Component({
639
+ imports: [
640
+ DataGridColumnManager,
641
+ DataGridColumnManagerTriggerDirective,
642
+ DataGridColumnManagerColumnTitleDirective,
643
+ ],
644
+ })
645
+ export class ExampleComponent {}
646
+ ```
647
+
648
+ Example with both trigger and column title customizations:
649
+
650
+ ```html
651
+ <re-data-grid-column-manager [columns]="managedColumns()" (columnsChange)="managedColumns.set($event)">
652
+ <span reDataGridColumnManagerTrigger>Manage columns</span>
653
+ <ng-template reDataGridColumnManagerColumnTitle let-title>
654
+ <span>{{ title }}</span>
655
+ </ng-template>
656
+ </re-data-grid-column-manager>
657
+ ```
658
+
659
+ Inputs:
660
+
661
+ - `columns: GridColumn<T>[]`
662
+ - `triggerLabel?: string`
663
+ - `controlsVisible?: boolean` - hides search and "show all / hide optional" panel
664
+ - `searchable?: boolean`
665
+ - `allowReorder?: boolean`
666
+ - `allowPin?: boolean`
667
+ - `allowVisibility?: boolean`
668
+
669
+ Outputs:
670
+
671
+ - `columnsChange: GridColumn<T>[]`
632
672
 
633
673
  ### Column manager CSS Variables
634
674
 
@@ -1,5 +1,5 @@
1
1
  import * as i0 from '@angular/core';
2
- import { Component, input, booleanAttribute, output, signal, viewChild, computed, effect } from '@angular/core';
2
+ import { inject, TemplateRef, Directive, Component, input, booleanAttribute, ElementRef, output, contentChild, signal, computed, viewChild, effect, afterNextRender } from '@angular/core';
3
3
  import { NgTemplateOutlet } from '@angular/common';
4
4
 
5
5
  const isVisible = (column) => column.visible !== false;
@@ -61,31 +61,53 @@ function setColumnVisibility(columns, key, visible) {
61
61
  return next;
62
62
  }
63
63
 
64
+ class DataGridColumnManagerColumnTitleDirective {
65
+ template = inject((TemplateRef));
66
+ static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.1.1", ngImport: i0, type: DataGridColumnManagerColumnTitleDirective, deps: [], target: i0.ɵɵFactoryTarget.Directive });
67
+ static ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "14.0.0", version: "21.1.1", type: DataGridColumnManagerColumnTitleDirective, isStandalone: true, selector: "ng-template[reDataGridColumnManagerColumnTitle]", ngImport: i0 });
68
+ }
69
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.1.1", ngImport: i0, type: DataGridColumnManagerColumnTitleDirective, decorators: [{
70
+ type: Directive,
71
+ args: [{
72
+ selector: 'ng-template[reDataGridColumnManagerColumnTitle]',
73
+ standalone: true,
74
+ }]
75
+ }] });
76
+
77
+ class DataGridColumnManagerTriggerDirective {
78
+ template = inject((TemplateRef), { optional: true });
79
+ static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.1.1", ngImport: i0, type: DataGridColumnManagerTriggerDirective, deps: [], target: i0.ɵɵFactoryTarget.Directive });
80
+ static ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "14.0.0", version: "21.1.1", type: DataGridColumnManagerTriggerDirective, isStandalone: true, selector: "[reDataGridColumnManagerTrigger]", ngImport: i0 });
81
+ }
82
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.1.1", ngImport: i0, type: DataGridColumnManagerTriggerDirective, decorators: [{
83
+ type: Directive,
84
+ args: [{
85
+ selector: '[reDataGridColumnManagerTrigger]',
86
+ standalone: true,
87
+ }]
88
+ }] });
89
+
64
90
  class CrossIcon {
65
91
  static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.1.1", ngImport: i0, type: CrossIcon, deps: [], target: i0.ɵɵFactoryTarget.Component });
66
92
  static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "21.1.1", type: CrossIcon, isStandalone: true, selector: "re-cross-ic", ngImport: i0, template: `
67
- <svg width="16" height="16" viewBox="0 0 20 18" fill="none" xmlns="http://www.w3.org/2000/svg">
68
- <svg width="15" height="15" viewBox="0 0 15 15" fill="none" xmlns="http://www.w3.org/2000/svg">
69
- <path
70
- d="M10.1958 7.3658L14.4358 3.1258C14.5295 3.03284 14.6039 2.92223 14.6547 2.80037C14.7055 2.67852 14.7316 2.54781 14.7316 2.4158C14.7316 2.28379 14.7055 2.15308 14.6547 2.03122C14.6039 1.90936 14.5295 1.79876 14.4358 1.7058L13.0258 0.295798C12.9328 0.20207 12.8222 0.127676 12.7004 0.0769072C12.5785 0.0261385 12.4478 0 12.3158 0C12.1838 0 12.0531 0.0261385 11.9312 0.0769072C11.8094 0.127676 11.6988 0.20207 11.6058 0.295798L7.3658 4.5358L3.1258 0.295798C3.03284 0.20207 2.92223 0.127676 2.80037 0.0769072C2.67852 0.0261385 2.54781 0 2.4158 0C2.28379 0 2.15308 0.0261385 2.03122 0.0769072C1.90936 0.127676 1.79876 0.20207 1.7058 0.295798L0.295798 1.7058C0.20207 1.79876 0.127676 1.90936 0.0769072 2.03122C0.0261385 2.15308 0 2.28379 0 2.4158C0 2.54781 0.0261385 2.67852 0.0769072 2.80037C0.127676 2.92223 0.20207 3.03284 0.295798 3.1258L4.5358 7.3658L0.295798 11.6058C0.20207 11.6988 0.127676 11.8094 0.0769072 11.9312C0.0261385 12.0531 0 12.1838 0 12.3158C0 12.4478 0.0261385 12.5785 0.0769072 12.7004C0.127676 12.8222 0.20207 12.9328 0.295798 13.0258L1.7058 14.4358C1.79876 14.5295 1.90936 14.6039 2.03122 14.6547C2.15308 14.7055 2.28379 14.7316 2.4158 14.7316C2.54781 14.7316 2.67852 14.7055 2.80037 14.6547C2.92223 14.6039 3.03284 14.5295 3.1258 14.4358L7.3658 10.1958L11.6058 14.4358C11.6988 14.5295 11.8094 14.6039 11.9312 14.6547C12.0531 14.7055 12.1838 14.7316 12.3158 14.7316C12.4478 14.7316 12.5785 14.7055 12.7004 14.6547C12.8222 14.6039 12.9328 14.5295 13.0258 14.4358L14.4358 13.0258C14.5295 12.9328 14.6039 12.8222 14.6547 12.7004C14.7055 12.5785 14.7316 12.4478 14.7316 12.3158C14.7316 12.1838 14.7055 12.0531 14.6547 11.9312C14.6039 11.8094 14.5295 11.6988 14.4358 11.6058L10.1958 7.3658Z"
71
- fill="var(--re-data-grid-cross-ic-surface)"
72
- />
73
- </svg>
93
+ <svg width="16" height="16" viewBox="0 0 16 16" fill="none" xmlns="http://www.w3.org/2000/svg">
94
+ <path
95
+ d="M10.3052 8L13.759 4.5462C13.8354 4.47048 13.896 4.38038 13.9374 4.28111C13.9787 4.18186 14 4.07538 14 3.96785C14 3.86032 13.9787 3.75385 13.9374 3.65458C13.896 3.55532 13.8354 3.46523 13.759 3.3895L12.6105 2.24095C12.5347 2.1646 12.4447 2.104 12.3454 2.06265C12.2461 2.02129 12.1397 2 12.0321 2C11.9246 2 11.8182 2.02129 11.7189 2.06265C11.6196 2.104 11.5296 2.1646 11.4538 2.24095L8 5.69475L4.5462 2.24095C4.47048 2.1646 4.38038 2.104 4.28111 2.06265C4.18186 2.02129 4.07538 2 3.96785 2C3.86032 2 3.75385 2.02129 3.65458 2.06265C3.55532 2.104 3.46523 2.1646 3.3895 2.24095L2.24095 3.3895C2.1646 3.46523 2.104 3.55532 2.06265 3.65458C2.02129 3.75385 2 3.86032 2 3.96785C2 4.07538 2.02129 4.18186 2.06265 4.28111C2.104 4.38038 2.1646 4.47048 2.24095 4.5462L5.69475 8L2.24095 11.4538C2.1646 11.5296 2.104 11.6196 2.06265 11.7189C2.02129 11.8182 2 11.9246 2 12.0321C2 12.1397 2.02129 12.2461 2.06265 12.3454C2.104 12.4447 2.1646 12.5347 2.24095 12.6105L3.3895 13.759C3.46523 13.8354 3.55532 13.896 3.65458 13.9374C3.75385 13.9787 3.86032 14 3.96785 14C4.07538 14 4.18186 13.9787 4.28111 13.9374C4.38038 13.896 4.47048 13.8354 4.5462 13.759L8 10.3052L11.4538 13.759C11.5296 13.8354 11.6196 13.896 11.7189 13.9374C11.8182 13.9787 11.9246 14 12.0321 14C12.1397 14 12.2461 13.9787 12.3454 13.9374C12.4447 13.896 12.5347 13.8354 12.6105 13.759L13.759 12.6105C13.8354 12.5347 13.896 12.4447 13.9374 12.3454C13.9787 12.2461 14 12.1397 14 12.0321C14 11.9246 13.9787 11.8182 13.9374 11.7189C13.896 11.6196 13.8354 11.5296 13.759 11.4538L10.3052 8Z"
96
+ fill="var(--re-data-grid-cross-ic-surface)"
97
+ />
74
98
  </svg>
75
- `, isInline: true, styles: [":host{--re-data-grid-cross-ic-surface: currentColor}\n"] });
99
+ `, isInline: true, styles: [":host{--re-data-grid-cross-ic-surface: currentColor;display:inline-block;width:16px;height:16px}\n"] });
76
100
  }
77
101
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.1.1", ngImport: i0, type: CrossIcon, decorators: [{
78
102
  type: Component,
79
103
  args: [{ selector: 're-cross-ic', template: `
80
- <svg width="16" height="16" viewBox="0 0 20 18" fill="none" xmlns="http://www.w3.org/2000/svg">
81
- <svg width="15" height="15" viewBox="0 0 15 15" fill="none" xmlns="http://www.w3.org/2000/svg">
82
- <path
83
- d="M10.1958 7.3658L14.4358 3.1258C14.5295 3.03284 14.6039 2.92223 14.6547 2.80037C14.7055 2.67852 14.7316 2.54781 14.7316 2.4158C14.7316 2.28379 14.7055 2.15308 14.6547 2.03122C14.6039 1.90936 14.5295 1.79876 14.4358 1.7058L13.0258 0.295798C12.9328 0.20207 12.8222 0.127676 12.7004 0.0769072C12.5785 0.0261385 12.4478 0 12.3158 0C12.1838 0 12.0531 0.0261385 11.9312 0.0769072C11.8094 0.127676 11.6988 0.20207 11.6058 0.295798L7.3658 4.5358L3.1258 0.295798C3.03284 0.20207 2.92223 0.127676 2.80037 0.0769072C2.67852 0.0261385 2.54781 0 2.4158 0C2.28379 0 2.15308 0.0261385 2.03122 0.0769072C1.90936 0.127676 1.79876 0.20207 1.7058 0.295798L0.295798 1.7058C0.20207 1.79876 0.127676 1.90936 0.0769072 2.03122C0.0261385 2.15308 0 2.28379 0 2.4158C0 2.54781 0.0261385 2.67852 0.0769072 2.80037C0.127676 2.92223 0.20207 3.03284 0.295798 3.1258L4.5358 7.3658L0.295798 11.6058C0.20207 11.6988 0.127676 11.8094 0.0769072 11.9312C0.0261385 12.0531 0 12.1838 0 12.3158C0 12.4478 0.0261385 12.5785 0.0769072 12.7004C0.127676 12.8222 0.20207 12.9328 0.295798 13.0258L1.7058 14.4358C1.79876 14.5295 1.90936 14.6039 2.03122 14.6547C2.15308 14.7055 2.28379 14.7316 2.4158 14.7316C2.54781 14.7316 2.67852 14.7055 2.80037 14.6547C2.92223 14.6039 3.03284 14.5295 3.1258 14.4358L7.3658 10.1958L11.6058 14.4358C11.6988 14.5295 11.8094 14.6039 11.9312 14.6547C12.0531 14.7055 12.1838 14.7316 12.3158 14.7316C12.4478 14.7316 12.5785 14.7055 12.7004 14.6547C12.8222 14.6039 12.9328 14.5295 13.0258 14.4358L14.4358 13.0258C14.5295 12.9328 14.6039 12.8222 14.6547 12.7004C14.7055 12.5785 14.7316 12.4478 14.7316 12.3158C14.7316 12.1838 14.7055 12.0531 14.6547 11.9312C14.6039 11.8094 14.5295 11.6988 14.4358 11.6058L10.1958 7.3658Z"
84
- fill="var(--re-data-grid-cross-ic-surface)"
85
- />
86
- </svg>
104
+ <svg width="16" height="16" viewBox="0 0 16 16" fill="none" xmlns="http://www.w3.org/2000/svg">
105
+ <path
106
+ d="M10.3052 8L13.759 4.5462C13.8354 4.47048 13.896 4.38038 13.9374 4.28111C13.9787 4.18186 14 4.07538 14 3.96785C14 3.86032 13.9787 3.75385 13.9374 3.65458C13.896 3.55532 13.8354 3.46523 13.759 3.3895L12.6105 2.24095C12.5347 2.1646 12.4447 2.104 12.3454 2.06265C12.2461 2.02129 12.1397 2 12.0321 2C11.9246 2 11.8182 2.02129 11.7189 2.06265C11.6196 2.104 11.5296 2.1646 11.4538 2.24095L8 5.69475L4.5462 2.24095C4.47048 2.1646 4.38038 2.104 4.28111 2.06265C4.18186 2.02129 4.07538 2 3.96785 2C3.86032 2 3.75385 2.02129 3.65458 2.06265C3.55532 2.104 3.46523 2.1646 3.3895 2.24095L2.24095 3.3895C2.1646 3.46523 2.104 3.55532 2.06265 3.65458C2.02129 3.75385 2 3.86032 2 3.96785C2 4.07538 2.02129 4.18186 2.06265 4.28111C2.104 4.38038 2.1646 4.47048 2.24095 4.5462L5.69475 8L2.24095 11.4538C2.1646 11.5296 2.104 11.6196 2.06265 11.7189C2.02129 11.8182 2 11.9246 2 12.0321C2 12.1397 2.02129 12.2461 2.06265 12.3454C2.104 12.4447 2.1646 12.5347 2.24095 12.6105L3.3895 13.759C3.46523 13.8354 3.55532 13.896 3.65458 13.9374C3.75385 13.9787 3.86032 14 3.96785 14C4.07538 14 4.18186 13.9787 4.28111 13.9374C4.38038 13.896 4.47048 13.8354 4.5462 13.759L8 10.3052L11.4538 13.759C11.5296 13.8354 11.6196 13.896 11.7189 13.9374C11.8182 13.9787 11.9246 14 12.0321 14C12.1397 14 12.2461 13.9787 12.3454 13.9374C12.4447 13.896 12.5347 13.8354 12.6105 13.759L13.759 12.6105C13.8354 12.5347 13.896 12.4447 13.9374 12.3454C13.9787 12.2461 14 12.1397 14 12.0321C14 11.9246 13.9787 11.8182 13.9374 11.7189C13.896 11.6196 13.8354 11.5296 13.759 11.4538L10.3052 8Z"
107
+ fill="var(--re-data-grid-cross-ic-surface)"
108
+ />
87
109
  </svg>
88
- `, styles: [":host{--re-data-grid-cross-ic-surface: currentColor}\n"] }]
110
+ `, styles: [":host{--re-data-grid-cross-ic-surface: currentColor;display:inline-block;width:16px;height:16px}\n"] }]
89
111
  }] });
90
112
 
91
113
  class EyeIcon {
@@ -147,7 +169,7 @@ class PinIcon {
147
169
  fill="var(--re-data-grid-pin-ic-surface)"
148
170
  />
149
171
  </svg>
150
- `, isInline: true, styles: [":host{--re-data-grid-pin-ic-surface: currentColor}.toRight{transform:rotate(-90deg)}\n"] });
172
+ `, isInline: true, styles: [":host{--re-data-grid-pin-ic-surface: currentColor;display:inline-block;width:16px;height:16px}.toRight{transform:rotate(-90deg)}\n"] });
151
173
  }
152
174
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.1.1", ngImport: i0, type: PinIcon, decorators: [{
153
175
  type: Component,
@@ -165,14 +187,13 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.1.1", ngImpor
165
187
  fill="var(--re-data-grid-pin-ic-surface)"
166
188
  />
167
189
  </svg>
168
- `, styles: [":host{--re-data-grid-pin-ic-surface: currentColor}.toRight{transform:rotate(-90deg)}\n"] }]
190
+ `, styles: [":host{--re-data-grid-pin-ic-surface: currentColor;display:inline-block;width:16px;height:16px}.toRight{transform:rotate(-90deg)}\n"] }]
169
191
  }], propDecorators: { toRight: [{ type: i0.Input, args: [{ isSignal: true, alias: "toRight", required: false }] }] } });
170
192
 
171
- // noinspection CssUnresolvedCustomProperty
172
193
  class DataGridColumnManager {
194
+ host = inject((ElementRef));
173
195
  columns = input([], ...(ngDevMode ? [{ debugName: "columns" }] : []));
174
196
  triggerLabel = input('Columns', ...(ngDevMode ? [{ debugName: "triggerLabel" }] : []));
175
- triggerTemplate = input(undefined, ...(ngDevMode ? [{ debugName: "triggerTemplate" }] : []));
176
197
  controlsVisible = input(true, { ...(ngDevMode ? { debugName: "controlsVisible" } : {}), transform: booleanAttribute });
177
198
  searchable = input(true, { ...(ngDevMode ? { debugName: "searchable" } : {}), transform: booleanAttribute });
178
199
  searchPlaceholder = input('Search columns...', ...(ngDevMode ? [{ debugName: "searchPlaceholder" }] : []));
@@ -180,11 +201,18 @@ class DataGridColumnManager {
180
201
  allowPin = input(true, { ...(ngDevMode ? { debugName: "allowPin" } : {}), transform: booleanAttribute });
181
202
  allowVisibility = input(true, { ...(ngDevMode ? { debugName: "allowVisibility" } : {}), transform: booleanAttribute });
182
203
  columnsChange = output();
204
+ triggerDirective = contentChild(DataGridColumnManagerTriggerDirective, ...(ngDevMode ? [{ debugName: "triggerDirective" }] : []));
205
+ columnTitleTemplate = contentChild((DataGridColumnManagerColumnTitleDirective), ...(ngDevMode ? [{ debugName: "columnTitleTemplate" }] : []));
183
206
  state = signal([], ...(ngDevMode ? [{ debugName: "state" }] : []));
184
207
  searchQuery = signal('', ...(ngDevMode ? [{ debugName: "searchQuery" }] : []));
185
208
  draggingKey = signal(null, ...(ngDevMode ? [{ debugName: "draggingKey" }] : []));
186
209
  opened = signal(false, ...(ngDevMode ? [{ debugName: "opened" }] : []));
210
+ openedPinMenuKey = signal(null, ...(ngDevMode ? [{ debugName: "openedPinMenuKey" }] : []));
211
+ panelLeft = signal(0, ...(ngDevMode ? [{ debugName: "panelLeft" }] : []));
212
+ hasCustomTrigger = signal(false, ...(ngDevMode ? [{ debugName: "hasCustomTrigger" }] : []));
213
+ triggerTemplate = computed(() => this.triggerDirective()?.template ?? null, ...(ngDevMode ? [{ debugName: "triggerTemplate" }] : []));
187
214
  root = viewChild('root', ...(ngDevMode ? [{ debugName: "root" }] : []));
215
+ panel = viewChild('panel', ...(ngDevMode ? [{ debugName: "panel" }] : []));
188
216
  filteredColumns = computed(() => {
189
217
  const query = this.searchQuery().trim().toLowerCase();
190
218
  if (!query) {
@@ -201,20 +229,59 @@ class DataGridColumnManager {
201
229
  effect(() => {
202
230
  this.state.set(cloneColumns(this.columns()));
203
231
  });
232
+ afterNextRender(() => this.syncCustomTriggerState());
233
+ }
234
+ ngAfterContentChecked() {
235
+ this.syncCustomTriggerState();
204
236
  }
205
237
  pin = (key) => resolvePinState(this.state(), key);
206
238
  toggleOpen() {
207
- this.opened.update((current) => !current);
239
+ const nextOpened = !this.opened();
240
+ this.opened.set(nextOpened);
241
+ if (nextOpened) {
242
+ this.schedulePanelPositioning();
243
+ }
244
+ else {
245
+ this.openedPinMenuKey.set(null);
246
+ this.panelLeft.set(0);
247
+ }
248
+ }
249
+ onWindowResize() {
250
+ if (!this.opened()) {
251
+ return;
252
+ }
253
+ this.schedulePanelPositioning();
208
254
  }
209
255
  onDocumentMouseDown(target) {
256
+ if (target instanceof Node && this.openedPinMenuKey() && !this.isInsidePinMenu(target)) {
257
+ this.openedPinMenuKey.set(null);
258
+ }
210
259
  if (!this.opened()) {
211
260
  return;
212
261
  }
213
262
  const root = this.root()?.nativeElement;
214
263
  if (root && target instanceof Node && !root.contains(target)) {
264
+ this.openedPinMenuKey.set(null);
215
265
  this.opened.set(false);
216
266
  }
217
267
  }
268
+ togglePinMenu(event, key) {
269
+ event.stopPropagation();
270
+ this.openedPinMenuKey.update((current) => (current === key ? null : key));
271
+ }
272
+ selectPin(key, pin) {
273
+ this.onPin(key, pin);
274
+ this.openedPinMenuKey.set(null);
275
+ }
276
+ pinLabel(pin) {
277
+ if (pin === 'left') {
278
+ return 'Pin left';
279
+ }
280
+ if (pin === 'right') {
281
+ return 'Pin right';
282
+ }
283
+ return 'Unpinned';
284
+ }
218
285
  onSearch(event) {
219
286
  const target = event.target;
220
287
  this.searchQuery.set(target?.value ?? '');
@@ -343,267 +410,64 @@ class DataGridColumnManager {
343
410
  this.state.set(next);
344
411
  this.columnsChange.emit(cloneColumns(next));
345
412
  }
413
+ hasProjectedTrigger() {
414
+ return !!this.host.nativeElement.querySelector('[reDataGridColumnManagerTrigger]');
415
+ }
416
+ onCustomTriggerSpace(event) {
417
+ event.preventDefault();
418
+ this.toggleOpen();
419
+ }
420
+ syncCustomTriggerState() {
421
+ const hasCustom = !!this.triggerDirective() || this.hasProjectedTrigger();
422
+ if (this.hasCustomTrigger() !== hasCustom) {
423
+ this.hasCustomTrigger.set(hasCustom);
424
+ }
425
+ }
426
+ isInsidePinMenu(target) {
427
+ return target instanceof Element && !!target.closest('[data-pin-menu]');
428
+ }
429
+ buildColumnTitleContext(column) {
430
+ const title = String(column.header || column.key);
431
+ return {
432
+ $implicit: title,
433
+ title,
434
+ column,
435
+ };
436
+ }
437
+ schedulePanelPositioning() {
438
+ afterNextRender(() => this.positionPanel());
439
+ }
440
+ positionPanel() {
441
+ const root = this.root()?.nativeElement;
442
+ const panel = this.panel()?.nativeElement;
443
+ if (!root || !panel || typeof window === 'undefined') {
444
+ this.panelLeft.set(0);
445
+ return;
446
+ }
447
+ const viewportPadding = 8;
448
+ const rootRect = root.getBoundingClientRect();
449
+ const panelWidth = panel.getBoundingClientRect().width;
450
+ const minLeft = viewportPadding - rootRect.left;
451
+ const maxLeft = window.innerWidth - viewportPadding - rootRect.left - panelWidth;
452
+ const lower = Math.min(minLeft, maxLeft);
453
+ const upper = Math.max(minLeft, maxLeft);
454
+ const nextLeft = Math.min(Math.max(0, lower), upper);
455
+ this.panelLeft.set(Number.isFinite(nextLeft) ? nextLeft : 0);
456
+ }
346
457
  static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.1.1", ngImport: i0, type: DataGridColumnManager, deps: [], target: i0.ɵɵFactoryTarget.Component });
347
- static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.1.1", type: DataGridColumnManager, isStandalone: true, selector: "re-data-grid-column-manager", inputs: { columns: { classPropertyName: "columns", publicName: "columns", isSignal: true, isRequired: false, transformFunction: null }, triggerLabel: { classPropertyName: "triggerLabel", publicName: "triggerLabel", isSignal: true, isRequired: false, transformFunction: null }, triggerTemplate: { classPropertyName: "triggerTemplate", publicName: "triggerTemplate", isSignal: true, isRequired: false, transformFunction: null }, controlsVisible: { classPropertyName: "controlsVisible", publicName: "controlsVisible", isSignal: true, isRequired: false, transformFunction: null }, searchable: { classPropertyName: "searchable", publicName: "searchable", isSignal: true, isRequired: false, transformFunction: null }, searchPlaceholder: { classPropertyName: "searchPlaceholder", publicName: "searchPlaceholder", isSignal: true, isRequired: false, transformFunction: null }, allowReorder: { classPropertyName: "allowReorder", publicName: "allowReorder", isSignal: true, isRequired: false, transformFunction: null }, allowPin: { classPropertyName: "allowPin", publicName: "allowPin", isSignal: true, isRequired: false, transformFunction: null }, allowVisibility: { classPropertyName: "allowVisibility", publicName: "allowVisibility", isSignal: true, isRequired: false, transformFunction: null } }, outputs: { columnsChange: "columnsChange" }, host: { attributes: { "document:mousedown": "onDocumentMouseDown($event.target)" } }, viewQueries: [{ propertyName: "root", first: true, predicate: ["root"], descendants: true, isSignal: true }], ngImport: i0, template: `
348
- <div class="re-dg-cm" #root>
349
- <button
350
- type="button"
351
- class="re-dg-cm__trigger"
352
- [class.re-dg-cm__trigger--open]="opened()"
353
- [attr.aria-expanded]="opened()"
354
- [attr.aria-haspopup]="'dialog'"
355
- (click)="toggleOpen()"
356
- >
357
- @if (triggerTemplate()) {
358
- <ng-container
359
- [ngTemplateOutlet]="triggerTemplate()!"
360
- [ngTemplateOutletContext]="{
361
- $implicit: triggerLabel(),
362
- visible: visibleColumnsCount(),
363
- total: state().length,
364
- }"
365
- />
366
- } @else {
367
- <span class="re-dg-cm__trigger-label">{{ triggerLabel() }}</span>
368
- <span class="re-dg-cm__trigger-count">{{ visibleColumnsCount() }}/{{ state().length }}</span>
369
- }
370
- </button>
371
-
372
- @if (opened()) {
373
- <div class="re-dg-cm__panel" role="dialog">
374
- @let list = filteredColumns();
375
-
376
- @if (controlsVisible() && searchable()) {
377
- <label class="re-dg-cm__search">
378
- <input
379
- type="search"
380
- [value]="searchQuery()"
381
- [placeholder]="searchPlaceholder()"
382
- (input)="onSearch($event)"
383
- />
384
- </label>
385
- }
386
-
387
- <div class="re-dg-cm__title-row">
388
- @if (controlsVisible()) {
389
- <div class="re-dg-cm__tools">
390
- <button type="button" (click)="showAll()">Show all</button>
391
- <button type="button" (click)="hideOptional()">Hide All</button>
392
- </div>
393
- } @else {
394
- <span></span>
395
- }
396
-
397
- <span class="re-dg-cm__meta">{{ visibleColumnsCount() }} / {{ state().length }}</span>
398
- </div>
399
-
400
- <div class="re-dg-cm__list">
401
- @for (column of list; track column.key) {
402
- @let currentPin = pin(column.key);
403
- @let disabled = !!column.disabled;
404
- @let canHideValue = canHideColumn(column.key);
405
-
406
- <div
407
- class="re-dg-cm__row"
408
- [attr.draggable]="allowReorder() && !disabled"
409
- [class.re-dg-cm__row--disabled]="disabled"
410
- [class.re-dg-cm__row--dragging]="draggingKey() === column.key"
411
- (dragstart)="onDragStart($event, column.key)"
412
- (dragover)="onDragOver($event)"
413
- (drop)="onDrop($event, column.key)"
414
- (dragend)="draggingKey.set(null)"
415
- >
416
- <span class="re-dg-cm__drag" title="Reorder">::</span>
417
-
418
- <label class="re-dg-cm__checkbox">
419
- <button
420
- [class.active]="column.visible !== false"
421
- [disabled]="disabled || !canHideValue"
422
- (click)="onVisibleChange(column.key)"
423
- >
424
- <re-eye-ic [open]="column.visible !== false" />
425
- </button>
426
- <span>{{ column.header || column.key }}</span>
427
- </label>
428
-
429
- <div class="re-dg-cm__actions">
430
- @if (allowPin()) {
431
- <button
432
- type="button"
433
- class="pin-button"
434
- [class.re-dg-cm__action--active]="currentPin === 'left'"
435
- [disabled]="disabled"
436
- (click)="onPin(column.key, 'left')"
437
- title="Pin left"
438
- >
439
- <re-pin-ic />
440
- </button>
441
-
442
- <button
443
- type="button"
444
- class="pin-button"
445
- [class.re-dg-cm__action--active]="currentPin === 'none'"
446
- [disabled]="disabled"
447
- (click)="onPin(column.key, 'none')"
448
- title="Unpin"
449
- >
450
- <re-cross-ic />
451
- </button>
452
-
453
- <button
454
- type="button"
455
- class="pin-button"
456
- [class.re-dg-cm__action--active]="currentPin === 'right'"
457
- [disabled]="disabled"
458
- (click)="onPin(column.key, 'right')"
459
- title="Pin right"
460
- >
461
- <re-pin-ic toRight />
462
- </button>
463
- }
464
- </div>
465
- </div>
466
- }
467
- </div>
468
- </div>
469
- }
470
- </div>
471
- `, isInline: true, styles: [":host{--re-data-grid-cm-gap: .5rem;--re-data-grid-cm-rounded: .625rem;--re-data-grid-cm-border: 1px solid var(--surface-border, #dfe1e6);--re-data-grid-cm-surface: var(--surface-neutral, #fff);--re-data-grid-cm-muted: var(--text-muted, #64748b);--re-data-grid-cm-active: var(--primary-color, #2a90f4);--re-data-grid-cm-shadow: 0 12px 30px rgba(15, 23, 42, .18);display:inline-block;position:relative}.re-dg-cm{position:relative;display:inline-flex;flex-direction:column;gap:var(--re-data-grid-cm-gap)}.re-dg-cm__trigger{display:inline-flex;align-items:center;gap:.5rem;height:2.25rem;padding:0 .75rem;border:var(--re-data-grid-cm-border);border-radius:999px;background:var(--re-data-grid-cm-surface);color:inherit;cursor:pointer}.re-dg-cm__trigger--open{box-shadow:0 0 0 2px color-mix(in srgb,var(--re-data-grid-cm-active) 25%,transparent)}.re-dg-cm__trigger-label{font-size:.8125rem;font-weight:600}.re-dg-cm__trigger-count{font-size:.75rem;color:var(--re-data-grid-cm-muted)}.re-dg-cm__panel{position:absolute;top:calc(100% + .5rem);left:0;z-index:50;min-width:18rem;width:max-content;max-width:min(24rem,85vw);display:grid;gap:var(--re-data-grid-cm-gap);padding:.75rem;border:var(--re-data-grid-cm-border);border-radius:var(--re-data-grid-cm-rounded);background:var(--re-data-grid-cm-surface);box-shadow:var(--re-data-grid-cm-shadow)}.re-dg-cm__tools,.re-dg-cm__row,.re-dg-cm__actions{display:flex;align-items:center}.re-dg-cm__meta{color:var(--re-data-grid-cm-muted);font-size:.75rem}.re-dg-cm__search input{width:100%;height:2rem;border-radius:.5rem;border:var(--re-data-grid-cm-border);padding:0 .625rem;background:var(--re-data-grid-cm-surface);color:inherit}.re-dg-cm__tools{gap:.5rem}.re-dg-cm__title-row{display:flex;justify-content:space-between}.re-dg-cm__tools button,.re-dg-cm__actions button{color:inherit;cursor:pointer;font-size:.75rem;line-height:1}.re-dg-cm__tools button{height:1.8rem;padding:0 .5rem}.re-dg-cm__actions button{width:1.7rem;height:1.7rem}.re-dg-cm__list{display:grid;gap:.375rem;max-height:22rem;overflow:auto;padding-right:.125rem}.re-dg-cm__row{gap:.5rem;padding:.375rem .5rem;border:var(--re-data-grid-cm-border);border-radius:.5rem;background:color-mix(in srgb,var(--re-data-grid-cm-surface) 88%,#f8fafc)}.re-dg-cm__row--dragging{opacity:.55}.re-dg-cm__row--disabled{opacity:.6}.re-dg-cm__drag{width:1rem;color:var(--re-data-grid-cm-muted);cursor:grab;-webkit-user-select:none;user-select:none}.re-dg-cm__checkbox{display:inline-flex;align-items:center;gap:.5rem;flex:1 1 auto;min-width:0;font-size:.8125rem;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}.re-dg-cm__checkbox>button{color:var(--re-data-grid-cm-muted)}.re-dg-cm__checkbox>button.active{color:var(--re-data-grid-cm-active)}.re-dg-cm__actions{gap:.25rem;margin-left:auto}.re-dg-cm__action--active{color:var(--re-data-grid-cm-active)!important;font-weight:700}\n"], dependencies: [{ kind: "directive", type: NgTemplateOutlet, selector: "[ngTemplateOutlet]", inputs: ["ngTemplateOutletContext", "ngTemplateOutlet", "ngTemplateOutletInjector"] }, { kind: "component", type: EyeIcon, selector: "re-eye-ic", inputs: ["open"] }, { kind: "component", type: CrossIcon, selector: "re-cross-ic" }, { kind: "component", type: PinIcon, selector: "re-pin-ic", inputs: ["toRight"] }] });
458
+ static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.1.1", type: DataGridColumnManager, isStandalone: true, selector: "re-data-grid-column-manager", inputs: { columns: { classPropertyName: "columns", publicName: "columns", isSignal: true, isRequired: false, transformFunction: null }, triggerLabel: { classPropertyName: "triggerLabel", publicName: "triggerLabel", isSignal: true, isRequired: false, transformFunction: null }, controlsVisible: { classPropertyName: "controlsVisible", publicName: "controlsVisible", isSignal: true, isRequired: false, transformFunction: null }, searchable: { classPropertyName: "searchable", publicName: "searchable", isSignal: true, isRequired: false, transformFunction: null }, searchPlaceholder: { classPropertyName: "searchPlaceholder", publicName: "searchPlaceholder", isSignal: true, isRequired: false, transformFunction: null }, allowReorder: { classPropertyName: "allowReorder", publicName: "allowReorder", isSignal: true, isRequired: false, transformFunction: null }, allowPin: { classPropertyName: "allowPin", publicName: "allowPin", isSignal: true, isRequired: false, transformFunction: null }, allowVisibility: { classPropertyName: "allowVisibility", publicName: "allowVisibility", isSignal: true, isRequired: false, transformFunction: null } }, outputs: { columnsChange: "columnsChange" }, host: { attributes: { "document:mousedown": "onDocumentMouseDown($event.target)", "window:resize": "onWindowResize()" } }, queries: [{ propertyName: "triggerDirective", first: true, predicate: DataGridColumnManagerTriggerDirective, descendants: true, isSignal: true }, { propertyName: "columnTitleTemplate", first: true, predicate: (DataGridColumnManagerColumnTitleDirective), descendants: true, isSignal: true }], viewQueries: [{ propertyName: "root", first: true, predicate: ["root"], descendants: true, isSignal: true }, { propertyName: "panel", first: true, predicate: ["panel"], descendants: true, isSignal: true }], ngImport: i0, template: "<div class=\"re-dg-cm\" #root>\n @if (hasCustomTrigger()) {\n <div\n tabindex=\"0\"\n role=\"button\"\n [class.re-dg-cm__trigger--open]=\"opened()\"\n [attr.aria-expanded]=\"opened()\"\n [attr.aria-haspopup]=\"'dialog'\"\n (click)=\"toggleOpen()\"\n (keydown.enter)=\"toggleOpen()\"\n (keydown.space)=\"onCustomTriggerSpace($event)\"\n >\n @if (triggerTemplate(); as template) {\n <ng-container [ngTemplateOutlet]=\"template\" />\n } @else {\n <ng-content select=\"[reDataGridColumnManagerTrigger]\" />\n }\n </div>\n } @else {\n <button\n type=\"button\"\n class=\"re-dg-cm__trigger\"\n [class.re-dg-cm__trigger--open]=\"opened()\"\n [attr.aria-expanded]=\"opened()\"\n [attr.aria-haspopup]=\"'dialog'\"\n (click)=\"toggleOpen()\"\n >\n <span class=\"re-dg-cm__trigger-label\">{{ triggerLabel() }}</span>\n <span class=\"re-dg-cm__trigger-count\">{{ visibleColumnsCount() }}/{{ state().length }}</span>\n </button>\n }\n\n @if (opened()) {\n <div class=\"re-dg-cm__panel\" #panel role=\"dialog\" [style.left.px]=\"panelLeft()\">\n @let list = filteredColumns();\n\n @if (controlsVisible() && searchable()) {\n <label class=\"re-dg-cm__search\">\n <input\n type=\"search\"\n [value]=\"searchQuery()\"\n [placeholder]=\"searchPlaceholder()\"\n (input)=\"onSearch($event)\"\n />\n </label>\n }\n\n <div class=\"re-dg-cm__title-row\">\n @if (controlsVisible()) {\n <div class=\"re-dg-cm__tools\">\n <button type=\"button\" (click)=\"showAll()\">Show all</button>\n <button type=\"button\" (click)=\"hideOptional()\">Hide All</button>\n </div>\n } @else {\n <span></span>\n }\n\n <span class=\"re-dg-cm__meta\">{{ visibleColumnsCount() }} / {{ state().length }}</span>\n </div>\n\n <div class=\"re-dg-cm__list\">\n @for (column of list; track column.key) {\n @let currentPin = pin(column.key);\n @let disabled = !!column.disabled;\n @let canHideValue = canHideColumn(column.key);\n\n <div\n class=\"re-dg-cm__row\"\n [attr.draggable]=\"allowReorder() && !disabled\"\n [class.re-dg-cm__row--disabled]=\"disabled\"\n [class.re-dg-cm__row--dragging]=\"draggingKey() === column.key\"\n (dragstart)=\"onDragStart($event, column.key)\"\n (dragover)=\"onDragOver($event)\"\n (drop)=\"onDrop($event, column.key)\"\n (dragend)=\"draggingKey.set(null)\"\n >\n <span class=\"re-dg-cm__drag\" title=\"Reorder\">::</span>\n\n <label class=\"re-dg-cm__checkbox\">\n <button\n [class.active]=\"column.visible !== false\"\n [disabled]=\"disabled || !canHideValue\"\n (click)=\"onVisibleChange(column.key)\"\n >\n <re-eye-ic [open]=\"column.visible !== false\" />\n </button>\n @if (columnTitleTemplate()) {\n <ng-container\n [ngTemplateOutlet]=\"columnTitleTemplate()!.template\"\n [ngTemplateOutletContext]=\"buildColumnTitleContext(column)\"\n />\n } @else {\n <span>{{ column.header || column.key }}</span>\n }\n </label>\n\n <div class=\"re-dg-cm__actions\">\n @if (allowPin()) {\n <div class=\"re-dg-cm__pin-menu\" data-pin-menu>\n <button\n type=\"button\"\n class=\"re-dg-cm__pin-current\"\n [disabled]=\"disabled\"\n [class.re-dg-cm__action--active]=\"currentPin !== 'none'\"\n [attr.aria-expanded]=\"openedPinMenuKey() === column.key\"\n (click)=\"togglePinMenu($event, column.key)\"\n [title]=\"pinLabel(currentPin)\"\n >\n @if (currentPin === 'left') {\n <re-pin-ic />\n } @else if (currentPin === 'right') {\n <re-pin-ic toRight />\n } @else {\n <re-cross-ic />\n }\n </button>\n\n @if (openedPinMenuKey() === column.key && !disabled) {\n <div class=\"re-dg-cm__pin-popover\" data-pin-menu role=\"menu\">\n <button\n type=\"button\"\n class=\"pin-button\"\n [class.re-dg-cm__action--active]=\"currentPin === 'left'\"\n (click)=\"selectPin(column.key, 'left')\"\n title=\"Pin left\"\n >\n <re-pin-ic />\n </button>\n\n <button\n type=\"button\"\n class=\"pin-button\"\n [class.re-dg-cm__action--active]=\"currentPin === 'none'\"\n (click)=\"selectPin(column.key, 'none')\"\n title=\"Unpin\"\n >\n <re-cross-ic />\n </button>\n\n <button\n type=\"button\"\n class=\"pin-button\"\n [class.re-dg-cm__action--active]=\"currentPin === 'right'\"\n (click)=\"selectPin(column.key, 'right')\"\n title=\"Pin right\"\n >\n <re-pin-ic toRight />\n </button>\n </div>\n }\n </div>\n }\n </div>\n </div>\n }\n </div>\n </div>\n }\n</div>\n", styles: [":host{--re-data-grid-cm-gap: .5rem;--re-data-grid-cm-rounded: .625rem;--re-data-grid-cm-border: 1px solid var(--surface-border, #dfe1e6);--re-data-grid-cm-surface: var(--surface-neutral, #fff);--re-data-grid-cm-muted: var(--text-muted, #64748b);--re-data-grid-cm-active: var(--primary-color, #2a90f4);--re-data-grid-cm-shadow: 0 12px 30px rgba(15, 23, 42, .18);display:inline-block;position:relative}.re-dg-cm{position:relative;display:inline-flex;flex-direction:column;gap:var(--re-data-grid-cm-gap)}.re-dg-cm__trigger{display:inline-flex;align-items:center;gap:.5rem;height:2.25rem;padding:0 .75rem;border:var(--re-data-grid-cm-border);border-radius:999px;background:var(--re-data-grid-cm-surface);color:inherit;cursor:pointer}.re-dg-cm__trigger--open{box-shadow:0 0 0 2px color-mix(in srgb,var(--re-data-grid-cm-active) 25%,transparent)}.re-dg-cm__trigger-label{font-size:.8125rem;font-weight:600}.re-dg-cm__trigger-count{font-size:.75rem;color:var(--re-data-grid-cm-muted)}.re-dg-cm__panel{position:absolute;top:calc(100% + .5rem);left:0;z-index:50;min-width:18rem;width:max-content;max-width:min(24rem,85vw);display:grid;gap:var(--re-data-grid-cm-gap);padding:.75rem;border:var(--re-data-grid-cm-border);border-radius:var(--re-data-grid-cm-rounded);background:var(--re-data-grid-cm-surface);box-shadow:var(--re-data-grid-cm-shadow)}.re-dg-cm__tools,.re-dg-cm__row,.re-dg-cm__actions{display:flex;align-items:center}.re-dg-cm__meta{color:var(--re-data-grid-cm-muted);font-size:.75rem}.re-dg-cm__search input{width:100%;height:2rem;border-radius:.5rem;border:var(--re-data-grid-cm-border);padding:0 .625rem;background:var(--re-data-grid-cm-surface);color:inherit}.re-dg-cm__tools{gap:.5rem}.re-dg-cm__title-row{display:flex;justify-content:space-between}.re-dg-cm__tools button,.re-dg-cm__actions button{color:inherit;cursor:pointer;font-size:.75rem;line-height:1}.re-dg-cm__tools button{height:1.8rem;padding:0 .5rem}.re-dg-cm__actions button{width:1.7rem;height:1.7rem}.re-dg-cm__list{display:grid;gap:.375rem;max-height:22rem;overflow:auto;padding-right:.125rem}.re-dg-cm__row{gap:.5rem;padding:.375rem .5rem;border:var(--re-data-grid-cm-border);border-radius:.5rem;background:color-mix(in srgb,var(--re-data-grid-cm-surface) 88%,#f8fafc)}.re-dg-cm__row--dragging{opacity:.55}.re-dg-cm__row--disabled{opacity:.6}.re-dg-cm__drag{width:1rem;color:var(--re-data-grid-cm-muted);cursor:grab;-webkit-user-select:none;user-select:none}.re-dg-cm__checkbox{display:inline-flex;align-items:center;gap:.5rem;flex:1 1 auto;min-width:0;font-size:.8125rem;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}.re-dg-cm__checkbox>button{color:var(--re-data-grid-cm-muted)}.re-dg-cm__checkbox>button.active{color:var(--re-data-grid-cm-active)}.re-dg-cm__actions{gap:.25rem;margin-left:auto}.re-dg-cm__pin-menu{position:relative}.re-dg-cm__pin-current{width:1.7rem;height:1.7rem}.re-dg-cm__pin-popover{position:absolute;right:0;top:calc(100% + .25rem);z-index:2;display:flex;align-items:center;gap:.25rem;padding:.25rem;border:var(--re-data-grid-cm-border);border-radius:.5rem;background:var(--re-data-grid-cm-surface);box-shadow:var(--re-data-grid-cm-shadow)}.re-dg-cm__action--active{color:var(--re-data-grid-cm-active)!important;font-weight:700}\n"], dependencies: [{ kind: "directive", type: NgTemplateOutlet, selector: "[ngTemplateOutlet]", inputs: ["ngTemplateOutletContext", "ngTemplateOutlet", "ngTemplateOutletInjector"] }, { kind: "component", type: EyeIcon, selector: "re-eye-ic", inputs: ["open"] }, { kind: "component", type: CrossIcon, selector: "re-cross-ic" }, { kind: "component", type: PinIcon, selector: "re-pin-ic", inputs: ["toRight"] }] });
472
459
  }
473
460
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.1.1", ngImport: i0, type: DataGridColumnManager, decorators: [{
474
461
  type: Component,
475
- args: [{ selector: 're-data-grid-column-manager', standalone: true, template: `
476
- <div class="re-dg-cm" #root>
477
- <button
478
- type="button"
479
- class="re-dg-cm__trigger"
480
- [class.re-dg-cm__trigger--open]="opened()"
481
- [attr.aria-expanded]="opened()"
482
- [attr.aria-haspopup]="'dialog'"
483
- (click)="toggleOpen()"
484
- >
485
- @if (triggerTemplate()) {
486
- <ng-container
487
- [ngTemplateOutlet]="triggerTemplate()!"
488
- [ngTemplateOutletContext]="{
489
- $implicit: triggerLabel(),
490
- visible: visibleColumnsCount(),
491
- total: state().length,
492
- }"
493
- />
494
- } @else {
495
- <span class="re-dg-cm__trigger-label">{{ triggerLabel() }}</span>
496
- <span class="re-dg-cm__trigger-count">{{ visibleColumnsCount() }}/{{ state().length }}</span>
497
- }
498
- </button>
499
-
500
- @if (opened()) {
501
- <div class="re-dg-cm__panel" role="dialog">
502
- @let list = filteredColumns();
503
-
504
- @if (controlsVisible() && searchable()) {
505
- <label class="re-dg-cm__search">
506
- <input
507
- type="search"
508
- [value]="searchQuery()"
509
- [placeholder]="searchPlaceholder()"
510
- (input)="onSearch($event)"
511
- />
512
- </label>
513
- }
514
-
515
- <div class="re-dg-cm__title-row">
516
- @if (controlsVisible()) {
517
- <div class="re-dg-cm__tools">
518
- <button type="button" (click)="showAll()">Show all</button>
519
- <button type="button" (click)="hideOptional()">Hide All</button>
520
- </div>
521
- } @else {
522
- <span></span>
523
- }
524
-
525
- <span class="re-dg-cm__meta">{{ visibleColumnsCount() }} / {{ state().length }}</span>
526
- </div>
527
-
528
- <div class="re-dg-cm__list">
529
- @for (column of list; track column.key) {
530
- @let currentPin = pin(column.key);
531
- @let disabled = !!column.disabled;
532
- @let canHideValue = canHideColumn(column.key);
533
-
534
- <div
535
- class="re-dg-cm__row"
536
- [attr.draggable]="allowReorder() && !disabled"
537
- [class.re-dg-cm__row--disabled]="disabled"
538
- [class.re-dg-cm__row--dragging]="draggingKey() === column.key"
539
- (dragstart)="onDragStart($event, column.key)"
540
- (dragover)="onDragOver($event)"
541
- (drop)="onDrop($event, column.key)"
542
- (dragend)="draggingKey.set(null)"
543
- >
544
- <span class="re-dg-cm__drag" title="Reorder">::</span>
545
-
546
- <label class="re-dg-cm__checkbox">
547
- <button
548
- [class.active]="column.visible !== false"
549
- [disabled]="disabled || !canHideValue"
550
- (click)="onVisibleChange(column.key)"
551
- >
552
- <re-eye-ic [open]="column.visible !== false" />
553
- </button>
554
- <span>{{ column.header || column.key }}</span>
555
- </label>
556
-
557
- <div class="re-dg-cm__actions">
558
- @if (allowPin()) {
559
- <button
560
- type="button"
561
- class="pin-button"
562
- [class.re-dg-cm__action--active]="currentPin === 'left'"
563
- [disabled]="disabled"
564
- (click)="onPin(column.key, 'left')"
565
- title="Pin left"
566
- >
567
- <re-pin-ic />
568
- </button>
569
-
570
- <button
571
- type="button"
572
- class="pin-button"
573
- [class.re-dg-cm__action--active]="currentPin === 'none'"
574
- [disabled]="disabled"
575
- (click)="onPin(column.key, 'none')"
576
- title="Unpin"
577
- >
578
- <re-cross-ic />
579
- </button>
580
-
581
- <button
582
- type="button"
583
- class="pin-button"
584
- [class.re-dg-cm__action--active]="currentPin === 'right'"
585
- [disabled]="disabled"
586
- (click)="onPin(column.key, 'right')"
587
- title="Pin right"
588
- >
589
- <re-pin-ic toRight />
590
- </button>
591
- }
592
- </div>
593
- </div>
594
- }
595
- </div>
596
- </div>
597
- }
598
- </div>
599
- `, host: {
462
+ args: [{ selector: 're-data-grid-column-manager', standalone: true, host: {
600
463
  'document:mousedown': 'onDocumentMouseDown($event.target)',
601
- }, imports: [NgTemplateOutlet, EyeIcon, CrossIcon, PinIcon], styles: [":host{--re-data-grid-cm-gap: .5rem;--re-data-grid-cm-rounded: .625rem;--re-data-grid-cm-border: 1px solid var(--surface-border, #dfe1e6);--re-data-grid-cm-surface: var(--surface-neutral, #fff);--re-data-grid-cm-muted: var(--text-muted, #64748b);--re-data-grid-cm-active: var(--primary-color, #2a90f4);--re-data-grid-cm-shadow: 0 12px 30px rgba(15, 23, 42, .18);display:inline-block;position:relative}.re-dg-cm{position:relative;display:inline-flex;flex-direction:column;gap:var(--re-data-grid-cm-gap)}.re-dg-cm__trigger{display:inline-flex;align-items:center;gap:.5rem;height:2.25rem;padding:0 .75rem;border:var(--re-data-grid-cm-border);border-radius:999px;background:var(--re-data-grid-cm-surface);color:inherit;cursor:pointer}.re-dg-cm__trigger--open{box-shadow:0 0 0 2px color-mix(in srgb,var(--re-data-grid-cm-active) 25%,transparent)}.re-dg-cm__trigger-label{font-size:.8125rem;font-weight:600}.re-dg-cm__trigger-count{font-size:.75rem;color:var(--re-data-grid-cm-muted)}.re-dg-cm__panel{position:absolute;top:calc(100% + .5rem);left:0;z-index:50;min-width:18rem;width:max-content;max-width:min(24rem,85vw);display:grid;gap:var(--re-data-grid-cm-gap);padding:.75rem;border:var(--re-data-grid-cm-border);border-radius:var(--re-data-grid-cm-rounded);background:var(--re-data-grid-cm-surface);box-shadow:var(--re-data-grid-cm-shadow)}.re-dg-cm__tools,.re-dg-cm__row,.re-dg-cm__actions{display:flex;align-items:center}.re-dg-cm__meta{color:var(--re-data-grid-cm-muted);font-size:.75rem}.re-dg-cm__search input{width:100%;height:2rem;border-radius:.5rem;border:var(--re-data-grid-cm-border);padding:0 .625rem;background:var(--re-data-grid-cm-surface);color:inherit}.re-dg-cm__tools{gap:.5rem}.re-dg-cm__title-row{display:flex;justify-content:space-between}.re-dg-cm__tools button,.re-dg-cm__actions button{color:inherit;cursor:pointer;font-size:.75rem;line-height:1}.re-dg-cm__tools button{height:1.8rem;padding:0 .5rem}.re-dg-cm__actions button{width:1.7rem;height:1.7rem}.re-dg-cm__list{display:grid;gap:.375rem;max-height:22rem;overflow:auto;padding-right:.125rem}.re-dg-cm__row{gap:.5rem;padding:.375rem .5rem;border:var(--re-data-grid-cm-border);border-radius:.5rem;background:color-mix(in srgb,var(--re-data-grid-cm-surface) 88%,#f8fafc)}.re-dg-cm__row--dragging{opacity:.55}.re-dg-cm__row--disabled{opacity:.6}.re-dg-cm__drag{width:1rem;color:var(--re-data-grid-cm-muted);cursor:grab;-webkit-user-select:none;user-select:none}.re-dg-cm__checkbox{display:inline-flex;align-items:center;gap:.5rem;flex:1 1 auto;min-width:0;font-size:.8125rem;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}.re-dg-cm__checkbox>button{color:var(--re-data-grid-cm-muted)}.re-dg-cm__checkbox>button.active{color:var(--re-data-grid-cm-active)}.re-dg-cm__actions{gap:.25rem;margin-left:auto}.re-dg-cm__action--active{color:var(--re-data-grid-cm-active)!important;font-weight:700}\n"] }]
602
- }], ctorParameters: () => [], propDecorators: { columns: [{ type: i0.Input, args: [{ isSignal: true, alias: "columns", required: false }] }], triggerLabel: [{ type: i0.Input, args: [{ isSignal: true, alias: "triggerLabel", required: false }] }], triggerTemplate: [{ type: i0.Input, args: [{ isSignal: true, alias: "triggerTemplate", required: false }] }], controlsVisible: [{ type: i0.Input, args: [{ isSignal: true, alias: "controlsVisible", required: false }] }], searchable: [{ type: i0.Input, args: [{ isSignal: true, alias: "searchable", required: false }] }], searchPlaceholder: [{ type: i0.Input, args: [{ isSignal: true, alias: "searchPlaceholder", required: false }] }], allowReorder: [{ type: i0.Input, args: [{ isSignal: true, alias: "allowReorder", required: false }] }], allowPin: [{ type: i0.Input, args: [{ isSignal: true, alias: "allowPin", required: false }] }], allowVisibility: [{ type: i0.Input, args: [{ isSignal: true, alias: "allowVisibility", required: false }] }], columnsChange: [{ type: i0.Output, args: ["columnsChange"] }], root: [{ type: i0.ViewChild, args: ['root', { isSignal: true }] }] } });
464
+ 'window:resize': 'onWindowResize()',
465
+ }, imports: [NgTemplateOutlet, EyeIcon, CrossIcon, PinIcon], template: "<div class=\"re-dg-cm\" #root>\n @if (hasCustomTrigger()) {\n <div\n tabindex=\"0\"\n role=\"button\"\n [class.re-dg-cm__trigger--open]=\"opened()\"\n [attr.aria-expanded]=\"opened()\"\n [attr.aria-haspopup]=\"'dialog'\"\n (click)=\"toggleOpen()\"\n (keydown.enter)=\"toggleOpen()\"\n (keydown.space)=\"onCustomTriggerSpace($event)\"\n >\n @if (triggerTemplate(); as template) {\n <ng-container [ngTemplateOutlet]=\"template\" />\n } @else {\n <ng-content select=\"[reDataGridColumnManagerTrigger]\" />\n }\n </div>\n } @else {\n <button\n type=\"button\"\n class=\"re-dg-cm__trigger\"\n [class.re-dg-cm__trigger--open]=\"opened()\"\n [attr.aria-expanded]=\"opened()\"\n [attr.aria-haspopup]=\"'dialog'\"\n (click)=\"toggleOpen()\"\n >\n <span class=\"re-dg-cm__trigger-label\">{{ triggerLabel() }}</span>\n <span class=\"re-dg-cm__trigger-count\">{{ visibleColumnsCount() }}/{{ state().length }}</span>\n </button>\n }\n\n @if (opened()) {\n <div class=\"re-dg-cm__panel\" #panel role=\"dialog\" [style.left.px]=\"panelLeft()\">\n @let list = filteredColumns();\n\n @if (controlsVisible() && searchable()) {\n <label class=\"re-dg-cm__search\">\n <input\n type=\"search\"\n [value]=\"searchQuery()\"\n [placeholder]=\"searchPlaceholder()\"\n (input)=\"onSearch($event)\"\n />\n </label>\n }\n\n <div class=\"re-dg-cm__title-row\">\n @if (controlsVisible()) {\n <div class=\"re-dg-cm__tools\">\n <button type=\"button\" (click)=\"showAll()\">Show all</button>\n <button type=\"button\" (click)=\"hideOptional()\">Hide All</button>\n </div>\n } @else {\n <span></span>\n }\n\n <span class=\"re-dg-cm__meta\">{{ visibleColumnsCount() }} / {{ state().length }}</span>\n </div>\n\n <div class=\"re-dg-cm__list\">\n @for (column of list; track column.key) {\n @let currentPin = pin(column.key);\n @let disabled = !!column.disabled;\n @let canHideValue = canHideColumn(column.key);\n\n <div\n class=\"re-dg-cm__row\"\n [attr.draggable]=\"allowReorder() && !disabled\"\n [class.re-dg-cm__row--disabled]=\"disabled\"\n [class.re-dg-cm__row--dragging]=\"draggingKey() === column.key\"\n (dragstart)=\"onDragStart($event, column.key)\"\n (dragover)=\"onDragOver($event)\"\n (drop)=\"onDrop($event, column.key)\"\n (dragend)=\"draggingKey.set(null)\"\n >\n <span class=\"re-dg-cm__drag\" title=\"Reorder\">::</span>\n\n <label class=\"re-dg-cm__checkbox\">\n <button\n [class.active]=\"column.visible !== false\"\n [disabled]=\"disabled || !canHideValue\"\n (click)=\"onVisibleChange(column.key)\"\n >\n <re-eye-ic [open]=\"column.visible !== false\" />\n </button>\n @if (columnTitleTemplate()) {\n <ng-container\n [ngTemplateOutlet]=\"columnTitleTemplate()!.template\"\n [ngTemplateOutletContext]=\"buildColumnTitleContext(column)\"\n />\n } @else {\n <span>{{ column.header || column.key }}</span>\n }\n </label>\n\n <div class=\"re-dg-cm__actions\">\n @if (allowPin()) {\n <div class=\"re-dg-cm__pin-menu\" data-pin-menu>\n <button\n type=\"button\"\n class=\"re-dg-cm__pin-current\"\n [disabled]=\"disabled\"\n [class.re-dg-cm__action--active]=\"currentPin !== 'none'\"\n [attr.aria-expanded]=\"openedPinMenuKey() === column.key\"\n (click)=\"togglePinMenu($event, column.key)\"\n [title]=\"pinLabel(currentPin)\"\n >\n @if (currentPin === 'left') {\n <re-pin-ic />\n } @else if (currentPin === 'right') {\n <re-pin-ic toRight />\n } @else {\n <re-cross-ic />\n }\n </button>\n\n @if (openedPinMenuKey() === column.key && !disabled) {\n <div class=\"re-dg-cm__pin-popover\" data-pin-menu role=\"menu\">\n <button\n type=\"button\"\n class=\"pin-button\"\n [class.re-dg-cm__action--active]=\"currentPin === 'left'\"\n (click)=\"selectPin(column.key, 'left')\"\n title=\"Pin left\"\n >\n <re-pin-ic />\n </button>\n\n <button\n type=\"button\"\n class=\"pin-button\"\n [class.re-dg-cm__action--active]=\"currentPin === 'none'\"\n (click)=\"selectPin(column.key, 'none')\"\n title=\"Unpin\"\n >\n <re-cross-ic />\n </button>\n\n <button\n type=\"button\"\n class=\"pin-button\"\n [class.re-dg-cm__action--active]=\"currentPin === 'right'\"\n (click)=\"selectPin(column.key, 'right')\"\n title=\"Pin right\"\n >\n <re-pin-ic toRight />\n </button>\n </div>\n }\n </div>\n }\n </div>\n </div>\n }\n </div>\n </div>\n }\n</div>\n", styles: [":host{--re-data-grid-cm-gap: .5rem;--re-data-grid-cm-rounded: .625rem;--re-data-grid-cm-border: 1px solid var(--surface-border, #dfe1e6);--re-data-grid-cm-surface: var(--surface-neutral, #fff);--re-data-grid-cm-muted: var(--text-muted, #64748b);--re-data-grid-cm-active: var(--primary-color, #2a90f4);--re-data-grid-cm-shadow: 0 12px 30px rgba(15, 23, 42, .18);display:inline-block;position:relative}.re-dg-cm{position:relative;display:inline-flex;flex-direction:column;gap:var(--re-data-grid-cm-gap)}.re-dg-cm__trigger{display:inline-flex;align-items:center;gap:.5rem;height:2.25rem;padding:0 .75rem;border:var(--re-data-grid-cm-border);border-radius:999px;background:var(--re-data-grid-cm-surface);color:inherit;cursor:pointer}.re-dg-cm__trigger--open{box-shadow:0 0 0 2px color-mix(in srgb,var(--re-data-grid-cm-active) 25%,transparent)}.re-dg-cm__trigger-label{font-size:.8125rem;font-weight:600}.re-dg-cm__trigger-count{font-size:.75rem;color:var(--re-data-grid-cm-muted)}.re-dg-cm__panel{position:absolute;top:calc(100% + .5rem);left:0;z-index:50;min-width:18rem;width:max-content;max-width:min(24rem,85vw);display:grid;gap:var(--re-data-grid-cm-gap);padding:.75rem;border:var(--re-data-grid-cm-border);border-radius:var(--re-data-grid-cm-rounded);background:var(--re-data-grid-cm-surface);box-shadow:var(--re-data-grid-cm-shadow)}.re-dg-cm__tools,.re-dg-cm__row,.re-dg-cm__actions{display:flex;align-items:center}.re-dg-cm__meta{color:var(--re-data-grid-cm-muted);font-size:.75rem}.re-dg-cm__search input{width:100%;height:2rem;border-radius:.5rem;border:var(--re-data-grid-cm-border);padding:0 .625rem;background:var(--re-data-grid-cm-surface);color:inherit}.re-dg-cm__tools{gap:.5rem}.re-dg-cm__title-row{display:flex;justify-content:space-between}.re-dg-cm__tools button,.re-dg-cm__actions button{color:inherit;cursor:pointer;font-size:.75rem;line-height:1}.re-dg-cm__tools button{height:1.8rem;padding:0 .5rem}.re-dg-cm__actions button{width:1.7rem;height:1.7rem}.re-dg-cm__list{display:grid;gap:.375rem;max-height:22rem;overflow:auto;padding-right:.125rem}.re-dg-cm__row{gap:.5rem;padding:.375rem .5rem;border:var(--re-data-grid-cm-border);border-radius:.5rem;background:color-mix(in srgb,var(--re-data-grid-cm-surface) 88%,#f8fafc)}.re-dg-cm__row--dragging{opacity:.55}.re-dg-cm__row--disabled{opacity:.6}.re-dg-cm__drag{width:1rem;color:var(--re-data-grid-cm-muted);cursor:grab;-webkit-user-select:none;user-select:none}.re-dg-cm__checkbox{display:inline-flex;align-items:center;gap:.5rem;flex:1 1 auto;min-width:0;font-size:.8125rem;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}.re-dg-cm__checkbox>button{color:var(--re-data-grid-cm-muted)}.re-dg-cm__checkbox>button.active{color:var(--re-data-grid-cm-active)}.re-dg-cm__actions{gap:.25rem;margin-left:auto}.re-dg-cm__pin-menu{position:relative}.re-dg-cm__pin-current{width:1.7rem;height:1.7rem}.re-dg-cm__pin-popover{position:absolute;right:0;top:calc(100% + .25rem);z-index:2;display:flex;align-items:center;gap:.25rem;padding:.25rem;border:var(--re-data-grid-cm-border);border-radius:.5rem;background:var(--re-data-grid-cm-surface);box-shadow:var(--re-data-grid-cm-shadow)}.re-dg-cm__action--active{color:var(--re-data-grid-cm-active)!important;font-weight:700}\n"] }]
466
+ }], ctorParameters: () => [], propDecorators: { columns: [{ type: i0.Input, args: [{ isSignal: true, alias: "columns", required: false }] }], triggerLabel: [{ type: i0.Input, args: [{ isSignal: true, alias: "triggerLabel", required: false }] }], controlsVisible: [{ type: i0.Input, args: [{ isSignal: true, alias: "controlsVisible", required: false }] }], searchable: [{ type: i0.Input, args: [{ isSignal: true, alias: "searchable", required: false }] }], searchPlaceholder: [{ type: i0.Input, args: [{ isSignal: true, alias: "searchPlaceholder", required: false }] }], allowReorder: [{ type: i0.Input, args: [{ isSignal: true, alias: "allowReorder", required: false }] }], allowPin: [{ type: i0.Input, args: [{ isSignal: true, alias: "allowPin", required: false }] }], allowVisibility: [{ type: i0.Input, args: [{ isSignal: true, alias: "allowVisibility", required: false }] }], columnsChange: [{ type: i0.Output, args: ["columnsChange"] }], triggerDirective: [{ type: i0.ContentChild, args: [i0.forwardRef(() => DataGridColumnManagerTriggerDirective), { isSignal: true }] }], columnTitleTemplate: [{ type: i0.ContentChild, args: [i0.forwardRef(() => DataGridColumnManagerColumnTitleDirective), { isSignal: true }] }], root: [{ type: i0.ViewChild, args: ['root', { isSignal: true }] }], panel: [{ type: i0.ViewChild, args: ['panel', { isSignal: true }] }] } });
603
467
 
604
468
  /**
605
469
  * Generated bundle index. Do not edit.
606
470
  */
607
471
 
608
- export { DataGridColumnManager };
472
+ export { DataGridColumnManager, DataGridColumnManagerColumnTitleDirective, DataGridColumnManagerTriggerDirective };
609
473
  //# sourceMappingURL=reforgium-data-grid-column-manager.mjs.map
@@ -1,4 +1,4 @@
1
- import { c as computeScrollbarState, a as clampThumbTop, m as mapThumbTopToScrollTop } from './reforgium-data-grid-reforgium-data-grid-Op6gjm7A.mjs';
1
+ import { c as computeScrollbarState, a as clampThumbTop, m as mapThumbTopToScrollTop } from './reforgium-data-grid-reforgium-data-grid-YSzBRJ5h.mjs';
2
2
 
3
3
  function createGridOverlayScrollFeature(ctx) {
4
4
  const showScrollbar = () => {
@@ -76,4 +76,4 @@ function createGridOverlayScrollFeature(ctx) {
76
76
  }
77
77
 
78
78
  export { createGridOverlayScrollFeature };
79
- //# sourceMappingURL=reforgium-data-grid-grid-overlay-scroll.feature-BSdC3IrC.mjs.map
79
+ //# sourceMappingURL=reforgium-data-grid-grid-overlay-scroll.feature-C-_Cnt4M.mjs.map
@@ -3097,12 +3097,6 @@ class DataGrid {
3097
3097
  this.currentSortOrder = last.order;
3098
3098
  return;
3099
3099
  }
3100
- const firstSortable = this.extendedColumns()?.find((c) => !!c.sortKey);
3101
- if (firstSortable) {
3102
- this.currentSortField = firstSortable.sortKey;
3103
- this.currentSortOrder = 'asc';
3104
- this.setCurrentSorts([{ key: firstSortable.sortKey, order: 'asc' }]);
3105
- }
3106
3100
  }
3107
3101
  initScroll() {
3108
3102
  void this.loadOverlayScrollFeature();
@@ -3165,7 +3159,7 @@ class DataGrid {
3165
3159
  if (this.overlayScrollFeaturePromise) {
3166
3160
  return this.overlayScrollFeaturePromise;
3167
3161
  }
3168
- this.overlayScrollFeaturePromise = import('./reforgium-data-grid-grid-overlay-scroll.feature-BSdC3IrC.mjs').then(({ createGridOverlayScrollFeature }) => {
3162
+ this.overlayScrollFeaturePromise = import('./reforgium-data-grid-grid-overlay-scroll.feature-C-_Cnt4M.mjs').then(({ createGridOverlayScrollFeature }) => {
3169
3163
  const feature = createGridOverlayScrollFeature({
3170
3164
  getScrollElement: () => this.scrollEl()?.nativeElement ?? null,
3171
3165
  getThumbTop: () => this.vm.thumbTopPx(),
@@ -3290,4 +3284,4 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.1.1", ngImpor
3290
3284
  */
3291
3285
 
3292
3286
  export { DataGridTypeCellTemplateDirective as D, clampThumbTop as a, DataGridCellTemplateDirective as b, computeScrollbarState as c, DataGridHeaderTemplateDirective as d, DataGridRowDirective as e, DataGridDeclarativeColumn as f, DataGridDeclarativeHeaderDirective as g, DataGridDeclarativeCellDirective as h, DataGridCellEmptyDirective as i, DataGridCellLoadingDirective as j, DataGridStickyRowDirective as k, DataGridSortIconDirective as l, mapThumbTopToScrollTop as m, DataGridExpanderIconDirective as n, DATA_GRID_CONFIG as o, DEFAULT_DATA_GRID_DEFAULTS as p, provideDataGridDefaults as q, DataGrid as r };
3293
- //# sourceMappingURL=reforgium-data-grid-reforgium-data-grid-Op6gjm7A.mjs.map
3287
+ //# sourceMappingURL=reforgium-data-grid-reforgium-data-grid-YSzBRJ5h.mjs.map
@@ -1,2 +1,2 @@
1
- export { o as DATA_GRID_CONFIG, p as DEFAULT_DATA_GRID_DEFAULTS, r as DataGrid, i as DataGridCellEmptyDirective, j as DataGridCellLoadingDirective, b as DataGridCellTemplateDirective, h as DataGridDeclarativeCellDirective, f as DataGridDeclarativeColumn, g as DataGridDeclarativeHeaderDirective, n as DataGridExpanderIconDirective, d as DataGridHeaderTemplateDirective, e as DataGridRowDirective, l as DataGridSortIconDirective, k as DataGridStickyRowDirective, D as DataGridTypeCellTemplateDirective, q as provideDataGridDefaults } from './reforgium-data-grid-reforgium-data-grid-Op6gjm7A.mjs';
1
+ export { o as DATA_GRID_CONFIG, p as DEFAULT_DATA_GRID_DEFAULTS, r as DataGrid, i as DataGridCellEmptyDirective, j as DataGridCellLoadingDirective, b as DataGridCellTemplateDirective, h as DataGridDeclarativeCellDirective, f as DataGridDeclarativeColumn, g as DataGridDeclarativeHeaderDirective, n as DataGridExpanderIconDirective, d as DataGridHeaderTemplateDirective, e as DataGridRowDirective, l as DataGridSortIconDirective, k as DataGridStickyRowDirective, D as DataGridTypeCellTemplateDirective, q as provideDataGridDefaults } from './reforgium-data-grid-reforgium-data-grid-YSzBRJ5h.mjs';
2
2
  //# sourceMappingURL=reforgium-data-grid.mjs.map
package/package.json CHANGED
@@ -1,5 +1,5 @@
1
1
  {
2
- "version": "2.2.3",
2
+ "version": "2.3.1",
3
3
  "name": "@reforgium/data-grid",
4
4
  "description": "reforgium DataGrid component",
5
5
  "author": "rtommievich",
@@ -1,18 +1,26 @@
1
1
  import * as _angular_core from '@angular/core';
2
- import { TemplateRef } from '@angular/core';
2
+ import { TemplateRef, AfterContentChecked } from '@angular/core';
3
3
  import { GridColumn } from '@reforgium/data-grid';
4
4
 
5
5
  type GridColumnPin = 'none' | 'left' | 'right';
6
6
 
7
+ type RowLike$1 = Record<string, unknown>;
8
+ type DataGridColumnManagerColumnTitleContext<Data extends RowLike$1 = RowLike$1> = {
9
+ $implicit: string;
10
+ title: string;
11
+ column: GridColumn<Data>;
12
+ };
13
+ declare class DataGridColumnManagerColumnTitleDirective<Data extends RowLike$1 = RowLike$1> {
14
+ readonly template: TemplateRef<any>;
15
+ static ɵfac: _angular_core.ɵɵFactoryDeclaration<DataGridColumnManagerColumnTitleDirective<any>, never>;
16
+ static ɵdir: _angular_core.ɵɵDirectiveDeclaration<DataGridColumnManagerColumnTitleDirective<any>, "ng-template[reDataGridColumnManagerColumnTitle]", never, {}, {}, never, never, true, never>;
17
+ }
18
+
7
19
  type RowLike = Record<string, unknown>;
8
- declare class DataGridColumnManager<Data extends RowLike = RowLike> {
20
+ declare class DataGridColumnManager<Data extends RowLike = RowLike> implements AfterContentChecked {
21
+ private host;
9
22
  columns: _angular_core.InputSignal<GridColumn<Data>[]>;
10
23
  triggerLabel: _angular_core.InputSignal<string>;
11
- triggerTemplate: _angular_core.InputSignal<TemplateRef<{
12
- $implicit: string;
13
- visible: number;
14
- total: number;
15
- }> | undefined>;
16
24
  controlsVisible: _angular_core.InputSignalWithTransform<boolean, unknown>;
17
25
  searchable: _angular_core.InputSignalWithTransform<boolean, unknown>;
18
26
  searchPlaceholder: _angular_core.InputSignal<string>;
@@ -20,17 +28,29 @@ declare class DataGridColumnManager<Data extends RowLike = RowLike> {
20
28
  allowPin: _angular_core.InputSignalWithTransform<boolean, unknown>;
21
29
  allowVisibility: _angular_core.InputSignalWithTransform<boolean, unknown>;
22
30
  columnsChange: _angular_core.OutputEmitterRef<GridColumn<Data>[]>;
31
+ private triggerDirective;
32
+ protected columnTitleTemplate: _angular_core.Signal<DataGridColumnManagerColumnTitleDirective<any> | undefined>;
23
33
  protected state: _angular_core.WritableSignal<GridColumn<Data>[]>;
24
34
  protected searchQuery: _angular_core.WritableSignal<string>;
25
35
  protected draggingKey: _angular_core.WritableSignal<string | null>;
26
36
  protected opened: _angular_core.WritableSignal<boolean>;
37
+ protected openedPinMenuKey: _angular_core.WritableSignal<string | null>;
38
+ protected panelLeft: _angular_core.WritableSignal<number>;
39
+ protected hasCustomTrigger: _angular_core.WritableSignal<boolean>;
40
+ protected triggerTemplate: _angular_core.Signal<_angular_core.TemplateRef<any> | null>;
27
41
  private root;
42
+ private panel;
28
43
  protected filteredColumns: _angular_core.Signal<GridColumn<Data>[]>;
29
44
  protected visibleColumnsCount: _angular_core.Signal<number>;
30
45
  constructor();
46
+ ngAfterContentChecked(): void;
31
47
  protected pin: (key: string) => GridColumnPin;
32
48
  protected toggleOpen(): void;
49
+ protected onWindowResize(): void;
33
50
  protected onDocumentMouseDown(target: EventTarget | null): void;
51
+ protected togglePinMenu(event: MouseEvent, key: string): void;
52
+ protected selectPin(key: string, pin: GridColumnPin): void;
53
+ protected pinLabel(pin: GridColumnPin): string;
34
54
  protected onSearch(event: Event): void;
35
55
  protected canHideColumn(key: string): boolean;
36
56
  protected onVisibleChange(key: string): void;
@@ -44,10 +64,23 @@ declare class DataGridColumnManager<Data extends RowLike = RowLike> {
44
64
  private reorderByKey;
45
65
  private findColumn;
46
66
  private commit;
67
+ private hasProjectedTrigger;
68
+ protected onCustomTriggerSpace(event: Event): void;
69
+ private syncCustomTriggerState;
70
+ private isInsidePinMenu;
71
+ protected buildColumnTitleContext(column: GridColumn<Data>): DataGridColumnManagerColumnTitleContext<Data>;
72
+ private schedulePanelPositioning;
73
+ private positionPanel;
47
74
  static ɵfac: _angular_core.ɵɵFactoryDeclaration<DataGridColumnManager<any>, never>;
48
- static ɵcmp: _angular_core.ɵɵComponentDeclaration<DataGridColumnManager<any>, "re-data-grid-column-manager", never, { "columns": { "alias": "columns"; "required": false; "isSignal": true; }; "triggerLabel": { "alias": "triggerLabel"; "required": false; "isSignal": true; }; "triggerTemplate": { "alias": "triggerTemplate"; "required": false; "isSignal": true; }; "controlsVisible": { "alias": "controlsVisible"; "required": false; "isSignal": true; }; "searchable": { "alias": "searchable"; "required": false; "isSignal": true; }; "searchPlaceholder": { "alias": "searchPlaceholder"; "required": false; "isSignal": true; }; "allowReorder": { "alias": "allowReorder"; "required": false; "isSignal": true; }; "allowPin": { "alias": "allowPin"; "required": false; "isSignal": true; }; "allowVisibility": { "alias": "allowVisibility"; "required": false; "isSignal": true; }; }, { "columnsChange": "columnsChange"; }, never, never, true, never>;
75
+ static ɵcmp: _angular_core.ɵɵComponentDeclaration<DataGridColumnManager<any>, "re-data-grid-column-manager", never, { "columns": { "alias": "columns"; "required": false; "isSignal": true; }; "triggerLabel": { "alias": "triggerLabel"; "required": false; "isSignal": true; }; "controlsVisible": { "alias": "controlsVisible"; "required": false; "isSignal": true; }; "searchable": { "alias": "searchable"; "required": false; "isSignal": true; }; "searchPlaceholder": { "alias": "searchPlaceholder"; "required": false; "isSignal": true; }; "allowReorder": { "alias": "allowReorder"; "required": false; "isSignal": true; }; "allowPin": { "alias": "allowPin"; "required": false; "isSignal": true; }; "allowVisibility": { "alias": "allowVisibility"; "required": false; "isSignal": true; }; }, { "columnsChange": "columnsChange"; }, ["triggerDirective", "columnTitleTemplate"], ["[reDataGridColumnManagerTrigger]"], true, never>;
76
+ }
77
+
78
+ declare class DataGridColumnManagerTriggerDirective {
79
+ readonly template: TemplateRef<any> | null;
80
+ static ɵfac: _angular_core.ɵɵFactoryDeclaration<DataGridColumnManagerTriggerDirective, never>;
81
+ static ɵdir: _angular_core.ɵɵDirectiveDeclaration<DataGridColumnManagerTriggerDirective, "[reDataGridColumnManagerTrigger]", never, {}, {}, never, never, true, never>;
49
82
  }
50
83
 
51
- export { DataGridColumnManager };
52
- export type { GridColumnPin };
84
+ export { DataGridColumnManager, DataGridColumnManagerColumnTitleDirective, DataGridColumnManagerTriggerDirective };
85
+ export type { DataGridColumnManagerColumnTitleContext, GridColumnPin };
53
86
  //# sourceMappingURL=reforgium-data-grid-column-manager.d.ts.map