@alaarab/ogrid-angular-material 2.0.8 → 2.0.11

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.
@@ -4,43 +4,14 @@ var __decorate = (this && this.__decorate) || function (decorators, target, key,
4
4
  else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
5
5
  return c > 3 && r && Object.defineProperty(target, key, r), r;
6
6
  };
7
- import { Component, input, output, signal, computed, ChangeDetectionStrategy } from '@angular/core';
7
+ import { Component, ChangeDetectionStrategy } from '@angular/core';
8
+ import { BaseColumnChooserComponent } from '@alaarab/ogrid-angular';
8
9
  /**
9
10
  * Column visibility chooser dropdown using Angular Material styling.
10
11
  * Standalone component with inline template.
11
12
  */
12
- let ColumnChooserComponent = class ColumnChooserComponent {
13
- constructor() {
14
- this.columns = input.required();
15
- this.visibleColumns = input.required();
16
- this.visibilityChange = output();
17
- this.isOpen = signal(false);
18
- this.visibleCount = computed(() => this.visibleColumns().size);
19
- this.totalCount = computed(() => this.columns().length);
20
- }
21
- toggle() {
22
- this.isOpen.update((v) => !v);
23
- }
24
- onCheckboxChange(columnKey, event) {
25
- const checked = event.target.checked;
26
- this.visibilityChange.emit({ columnKey, visible: checked });
27
- }
28
- selectAll() {
29
- for (const col of this.columns()) {
30
- if (!this.visibleColumns().has(col.columnId)) {
31
- this.visibilityChange.emit({ columnKey: col.columnId, visible: true });
32
- }
33
- }
34
- }
35
- clearAll() {
36
- for (const col of this.columns()) {
37
- if (this.visibleColumns().has(col.columnId)) {
38
- this.visibilityChange.emit({ columnKey: col.columnId, visible: false });
39
- }
40
- }
41
- }
13
+ let ColumnChooserComponent = class ColumnChooserComponent extends BaseColumnChooserComponent {
42
14
  onDocumentClick(event) {
43
- // Close dropdown when clicking outside
44
15
  const el = event.target;
45
16
  if (!el.closest('ogrid-column-chooser')) {
46
17
  this.isOpen.set(false);
@@ -71,11 +42,11 @@ ColumnChooserComponent = __decorate([
71
42
  </div>
72
43
 
73
44
  <div class="ogrid-column-chooser__list">
74
- @for (col of columns(); track col.columnId) {
45
+ @for (col of columns; track col.columnId) {
75
46
  <label class="ogrid-column-chooser__item">
76
47
  <input
77
48
  type="checkbox"
78
- [checked]="visibleColumns().has(col.columnId)"
49
+ [checked]="visibleColumns.has(col.columnId)"
79
50
  (change)="onCheckboxChange(col.columnId, $event)"
80
51
  />
81
52
  <span>{{ col.name }}</span>
@@ -4,195 +4,23 @@ var __decorate = (this && this.__decorate) || function (decorators, target, key,
4
4
  else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
5
5
  return c > 3 && r && Object.defineProperty(target, key, r), r;
6
6
  };
7
- import { Component, input, signal, computed, ChangeDetectionStrategy, viewChild, } from '@angular/core';
7
+ import { Component, ChangeDetectionStrategy, ViewChild } from '@angular/core';
8
+ import { BaseColumnHeaderFilterComponent } from '@alaarab/ogrid-angular';
8
9
  /**
9
10
  * Column header filter component with sort + filter icon + popover.
10
11
  * Standalone component with inline template.
11
12
  */
12
- let ColumnHeaderFilterComponent = class ColumnHeaderFilterComponent {
13
- constructor() {
14
- this.columnKey = input.required();
15
- this.columnName = input.required();
16
- this.filterType = input.required();
17
- this.isSorted = input(false);
18
- this.isSortedDescending = input(false);
19
- this.onSort = input(undefined);
20
- this.selectedValues = input(undefined);
21
- this.onFilterChange = input(undefined);
22
- this.options = input(undefined);
23
- this.isLoadingOptions = input(false);
24
- this.textValue = input('');
25
- this.onTextChange = input(undefined);
26
- this.selectedUser = input(undefined);
27
- this.onUserChange = input(undefined);
28
- this.peopleSearch = input(undefined);
29
- this.dateValue = input(undefined);
30
- this.onDateChange = input(undefined);
31
- this.headerEl = viewChild('headerEl');
32
- // Internal state
33
- this.isFilterOpen = signal(false);
34
- this.tempTextValue = signal('');
35
- this.searchText = signal('');
36
- this.tempSelected = signal(new Set());
37
- this.peopleSearchText = signal('');
38
- this.peopleSuggestions = signal([]);
39
- this.isPeopleLoading = signal(false);
40
- this.tempDateFrom = signal('');
41
- this.tempDateTo = signal('');
42
- // Popover position
43
- this.popoverTop = signal(0);
44
- this.popoverLeft = signal(0);
45
- this.peopleDebounceTimer = null;
46
- this.hasActiveFilter = computed(() => {
47
- const ft = this.filterType();
48
- if (ft === 'text')
49
- return !!this.textValue();
50
- if (ft === 'multiSelect')
51
- return (this.selectedValues()?.length ?? 0) > 0;
52
- if (ft === 'people')
53
- return this.selectedUser() != null;
54
- if (ft === 'date')
55
- return this.dateValue() != null;
56
- return false;
57
- });
58
- this.filteredOptions = computed(() => {
59
- const opts = this.options() ?? [];
60
- const search = this.searchText().toLowerCase().trim();
61
- if (!search)
62
- return opts;
63
- return opts.filter((o) => o.toLowerCase().includes(search));
64
- });
13
+ let ColumnHeaderFilterComponent = class ColumnHeaderFilterComponent extends BaseColumnHeaderFilterComponent {
14
+ getHeaderEl() {
15
+ return this.headerEl;
65
16
  }
66
- asInputValue(event) {
67
- return event.target.value;
68
- }
69
- toggleFilter(event) {
70
- event.stopPropagation();
71
- if (this.isFilterOpen()) {
72
- this.isFilterOpen.set(false);
73
- return;
74
- }
75
- // Initialize temp state from current values
76
- this.tempTextValue.set(this.textValue());
77
- this.tempSelected.set(new Set(this.selectedValues() ?? []));
78
- this.searchText.set('');
79
- this.peopleSearchText.set('');
80
- this.peopleSuggestions.set([]);
81
- const dv = this.dateValue();
82
- this.tempDateFrom.set(dv?.from ?? '');
83
- this.tempDateTo.set(dv?.to ?? '');
84
- // Compute popover position
85
- const el = this.headerEl()?.nativeElement;
86
- if (el) {
87
- const rect = el.getBoundingClientRect();
88
- this.popoverTop.set(rect.bottom + 4);
89
- this.popoverLeft.set(rect.left);
90
- }
91
- this.isFilterOpen.set(true);
92
- }
93
- // --- Text filter ---
94
- onTextKeydown(event) {
95
- event.stopPropagation();
96
- if (event.key === 'Enter') {
97
- event.preventDefault();
98
- this.handleTextApply();
99
- }
100
- }
101
- handleTextApply() {
102
- this.onTextChange()(this.tempTextValue());
103
- this.isFilterOpen.set(false);
104
- }
105
- handleTextClear() {
106
- this.tempTextValue.set('');
107
- this.onTextChange()('');
108
- this.isFilterOpen.set(false);
109
- }
110
- // --- MultiSelect filter ---
111
- handleCheckboxChange(option, event) {
112
- const checked = event.target.checked;
113
- this.tempSelected.update((s) => {
114
- const next = new Set(s);
115
- if (checked)
116
- next.add(option);
117
- else
118
- next.delete(option);
119
- return next;
120
- });
121
- }
122
- handleSelectAllFiltered() {
123
- this.tempSelected.update((s) => {
124
- const next = new Set(s);
125
- for (const opt of this.filteredOptions())
126
- next.add(opt);
127
- return next;
128
- });
129
- }
130
- handleClearSelection() {
131
- this.tempSelected.set(new Set());
132
- }
133
- handleApplyMultiSelect() {
134
- this.onFilterChange()(Array.from(this.tempSelected()));
135
- this.isFilterOpen.set(false);
136
- }
137
- // --- People filter ---
138
- onPeopleSearchInput(event) {
139
- const value = event.target.value;
140
- this.peopleSearchText.set(value);
141
- if (this.peopleDebounceTimer)
142
- clearTimeout(this.peopleDebounceTimer);
143
- const query = value.trim();
144
- if (!query) {
145
- this.peopleSuggestions.set([]);
146
- this.isPeopleLoading.set(false);
147
- return;
148
- }
149
- this.isPeopleLoading.set(true);
150
- this.peopleDebounceTimer = setTimeout(() => {
151
- const fn = this.peopleSearch();
152
- if (!fn)
153
- return;
154
- fn(query).then((results) => {
155
- this.peopleSuggestions.set(results);
156
- this.isPeopleLoading.set(false);
157
- }).catch(() => {
158
- this.peopleSuggestions.set([]);
159
- this.isPeopleLoading.set(false);
160
- });
161
- }, 300);
162
- }
163
- handleUserSelect(user) {
164
- this.onUserChange()(user);
165
- this.isFilterOpen.set(false);
166
- }
167
- handleClearUser() {
168
- this.onUserChange()(undefined);
169
- this.isFilterOpen.set(false);
170
- }
171
- // --- Date filter ---
172
- handleDateApply() {
173
- const from = this.tempDateFrom();
174
- const to = this.tempDateTo();
175
- if (!from && !to) {
176
- this.onDateChange()(undefined);
177
- }
178
- else {
179
- this.onDateChange()({ from: from || undefined, to: to || undefined });
180
- }
181
- this.isFilterOpen.set(false);
182
- }
183
- handleDateClear() {
184
- this.tempDateFrom.set('');
185
- this.tempDateTo.set('');
186
- this.onDateChange()(undefined);
187
- this.isFilterOpen.set(false);
188
- }
189
- onDocumentClick(event) {
190
- const el = event.target;
191
- if (!el.closest('ogrid-column-header-filter') && !el.closest('.ogrid-header-filter__popover')) {
192
- this.isFilterOpen.set(false);
193
- }
17
+ onDocumentClickWrapper(event) {
18
+ this.onDocumentClick(event, 'ogrid-column-header-filter');
194
19
  }
195
20
  };
21
+ __decorate([
22
+ ViewChild('headerEl')
23
+ ], ColumnHeaderFilterComponent.prototype, "headerEl", void 0);
196
24
  ColumnHeaderFilterComponent = __decorate([
197
25
  Component({
198
26
  selector: 'ogrid-column-header-filter',
@@ -201,23 +29,23 @@ ColumnHeaderFilterComponent = __decorate([
201
29
  template: `
202
30
  <div class="ogrid-header-filter" #headerEl>
203
31
  <div class="ogrid-header-filter__label">
204
- <span class="ogrid-header-filter__name" [title]="columnName()" data-header-label>
205
- {{ columnName() }}
32
+ <span class="ogrid-header-filter__name" [title]="columnName" data-header-label>
33
+ {{ columnName }}
206
34
  </span>
207
35
  </div>
208
36
 
209
37
  <div class="ogrid-header-filter__actions">
210
- @if (onSort()) {
38
+ @if (onSort) {
211
39
  <button
212
40
  class="ogrid-header-filter__btn"
213
- [class.ogrid-header-filter__btn--active]="isSorted()"
214
- (click)="onSort()!()"
215
- [attr.aria-label]="'Sort by ' + columnName()"
216
- [title]="isSorted() ? (isSortedDescending() ? 'Sorted descending' : 'Sorted ascending') : 'Sort'"
41
+ [class.ogrid-header-filter__btn--active]="isSorted"
42
+ (click)="onSort!()"
43
+ [attr.aria-label]="'Sort by ' + columnName"
44
+ [title]="isSorted ? (isSortedDescending ? 'Sorted descending' : 'Sorted ascending') : 'Sort'"
217
45
  >
218
- @if (isSorted() && isSortedDescending()) {
46
+ @if (isSorted && isSortedDescending) {
219
47
  &#9660;
220
- } @else if (isSorted()) {
48
+ } @else if (isSorted) {
221
49
  &#9650;
222
50
  } @else {
223
51
  &#8597;
@@ -225,15 +53,15 @@ ColumnHeaderFilterComponent = __decorate([
225
53
  </button>
226
54
  }
227
55
 
228
- @if (filterType() !== 'none') {
56
+ @if (filterType !== 'none') {
229
57
  <button
230
- class="ogrid-header-filter__btn"
231
- [class.ogrid-header-filter__btn--active]="hasActiveFilter() || isFilterOpen()"
58
+ class="ogrid-header-filter__filter-btn"
59
+ [class.ogrid-header-filter__filter-btn--active]="hasActiveFilter() || isFilterOpen()"
232
60
  (click)="toggleFilter($event)"
233
- [attr.aria-label]="'Filter ' + columnName()"
234
- [title]="'Filter ' + columnName()"
61
+ [attr.aria-label]="'Filter ' + columnName"
62
+ [title]="'Filter ' + columnName"
235
63
  >
236
- &#9783;
64
+ <span class="ogrid-header-filter__funnel"></span>
237
65
  @if (hasActiveFilter()) {
238
66
  <span class="ogrid-header-filter__dot"></span>
239
67
  }
@@ -242,7 +70,7 @@ ColumnHeaderFilterComponent = __decorate([
242
70
  </div>
243
71
  </div>
244
72
 
245
- @if (isFilterOpen() && filterType() !== 'none') {
73
+ @if (isFilterOpen() && filterType !== 'none') {
246
74
  <div
247
75
  class="ogrid-header-filter__popover"
248
76
  [style.top.px]="popoverTop()"
@@ -250,10 +78,10 @@ ColumnHeaderFilterComponent = __decorate([
250
78
  (click)="$event.stopPropagation()"
251
79
  >
252
80
  <div class="ogrid-header-filter__popover-header">
253
- Filter: {{ columnName() }}
81
+ Filter: {{ columnName }}
254
82
  </div>
255
83
 
256
- @switch (filterType()) {
84
+ @switch (filterType) {
257
85
  @case ('text') {
258
86
  <div class="ogrid-header-filter__popover-body" style="width: 260px;">
259
87
  <div style="padding: 12px;">
@@ -286,7 +114,7 @@ ColumnHeaderFilterComponent = __decorate([
286
114
  autocomplete="off"
287
115
  />
288
116
  <div class="ogrid-header-filter__options-info">
289
- {{ filteredOptions().length }} of {{ (options() ?? []).length }} options
117
+ {{ filteredOptions().length }} of {{ (options ?? []).length }} options
290
118
  </div>
291
119
  </div>
292
120
  <div class="ogrid-header-filter__select-actions">
@@ -296,7 +124,7 @@ ColumnHeaderFilterComponent = __decorate([
296
124
  <button class="ogrid-header-filter__action-btn" (click)="handleClearSelection()">Clear</button>
297
125
  </div>
298
126
  <div class="ogrid-header-filter__options-list">
299
- @if (isLoadingOptions()) {
127
+ @if (isLoadingOptions) {
300
128
  <div class="ogrid-header-filter__loading">Loading...</div>
301
129
  } @else if (filteredOptions().length === 0) {
302
130
  <div class="ogrid-header-filter__empty">No options found</div>
@@ -321,14 +149,14 @@ ColumnHeaderFilterComponent = __decorate([
321
149
  }
322
150
  @case ('people') {
323
151
  <div class="ogrid-header-filter__popover-body" style="width: 300px;">
324
- @if (selectedUser()) {
152
+ @if (selectedUser) {
325
153
  <div class="ogrid-header-filter__people-selected">
326
154
  <div class="ogrid-header-filter__people-info-label">Currently filtered by:</div>
327
155
  <div class="ogrid-header-filter__people-card">
328
- <div class="ogrid-header-filter__people-avatar">{{ selectedUser()!.displayName?.[0] ?? '?' }}</div>
156
+ <div class="ogrid-header-filter__people-avatar">{{ selectedUser!.displayName?.[0] ?? '?' }}</div>
329
157
  <div class="ogrid-header-filter__people-details">
330
- <div>{{ selectedUser()!.displayName }}</div>
331
- <div class="ogrid-header-filter__people-email">{{ selectedUser()!.email }}</div>
158
+ <div>{{ selectedUser!.displayName }}</div>
159
+ <div class="ogrid-header-filter__people-email">{{ selectedUser!.email }}</div>
332
160
  </div>
333
161
  <button class="ogrid-header-filter__btn" (click)="handleClearUser()" aria-label="Remove filter">&times;</button>
334
162
  </div>
@@ -364,7 +192,7 @@ ColumnHeaderFilterComponent = __decorate([
364
192
  <div class="ogrid-header-filter__empty">Type to search...</div>
365
193
  }
366
194
  </div>
367
- @if (selectedUser()) {
195
+ @if (selectedUser) {
368
196
  <div style="padding: 8px 12px; border-top: 1px solid rgba(0,0,0,0.12);">
369
197
  <button class="ogrid-header-filter__action-btn" style="width: 100%;" (click)="handleClearUser()">Clear Filter</button>
370
198
  </div>
@@ -392,7 +220,7 @@ ColumnHeaderFilterComponent = __decorate([
392
220
  }
393
221
  `,
394
222
  styles: [`
395
- :host { display: flex; align-items: center; width: 100%; min-width: 0; position: relative; }
223
+ :host { display: flex; align-items: center; flex: 1; min-width: 0; position: relative; }
396
224
  .ogrid-header-filter { display: flex; align-items: center; width: 100%; min-width: 0; }
397
225
  .ogrid-header-filter__label { flex: 1; min-width: 0; overflow: hidden; }
398
226
  .ogrid-header-filter__name {
@@ -406,17 +234,43 @@ ColumnHeaderFilterComponent = __decorate([
406
234
  display: inline-flex; align-items: center; justify-content: center; position: relative;
407
235
  color: rgba(0,0,0,0.54);
408
236
  }
409
- .ogrid-header-filter__btn:hover { background: rgba(0,0,0,0.04); }
237
+ .ogrid-header-filter__btn:hover { background: rgba(0,0,0,0.08); }
410
238
  .ogrid-header-filter__btn--active { color: var(--mat-sys-primary, #1976d2); }
239
+ .ogrid-header-filter__filter-btn {
240
+ width: 24px; height: 24px; padding: 2px; border: none; border-radius: 4px;
241
+ background: transparent; cursor: pointer; line-height: 1;
242
+ display: inline-flex; align-items: center; justify-content: center; position: relative;
243
+ opacity: 0.6; transition: opacity 0.15s;
244
+ }
245
+ .ogrid-header-filter:hover .ogrid-header-filter__filter-btn { opacity: 0.8; }
246
+ .ogrid-header-filter__filter-btn:hover { background: rgba(0,0,0,0.08); opacity: 1 !important; }
247
+ .ogrid-header-filter__filter-btn--active { opacity: 1 !important; }
248
+ .ogrid-header-filter__funnel {
249
+ display: block; width: 0; height: 0;
250
+ border-left: 5px solid transparent; border-right: 5px solid transparent;
251
+ border-top: 6px solid rgba(0,0,0,0.65);
252
+ position: relative;
253
+ }
254
+ .ogrid-header-filter__funnel::after {
255
+ content: ''; display: block; width: 2px; height: 4px;
256
+ background: rgba(0,0,0,0.65); position: absolute;
257
+ top: -1px; left: -1px;
258
+ }
259
+ .ogrid-header-filter__filter-btn--active .ogrid-header-filter__funnel {
260
+ border-top-color: var(--mat-sys-primary, #1976d2);
261
+ }
262
+ .ogrid-header-filter__filter-btn--active .ogrid-header-filter__funnel::after {
263
+ background: var(--mat-sys-primary, #1976d2);
264
+ }
411
265
  .ogrid-header-filter__dot {
412
266
  position: absolute; top: 2px; right: 2px;
413
267
  width: 6px; height: 6px; border-radius: 50%;
414
268
  background: var(--mat-sys-primary, #1976d2);
415
269
  }
416
270
  .ogrid-header-filter__popover {
417
- position: fixed; z-index: 1000;
418
- background: #fff; border: 1px solid rgba(0,0,0,0.12);
419
- border-radius: 4px; box-shadow: 0 2px 8px rgba(0,0,0,0.15);
271
+ position: fixed; z-index: 10000;
272
+ background: #ffffff; border: 1px solid rgba(0,0,0,0.2);
273
+ border-radius: 8px; box-shadow: 0 4px 16px rgba(0,0,0,0.2), 0 1px 4px rgba(0,0,0,0.1);
420
274
  margin-top: 4px;
421
275
  }
422
276
  .ogrid-header-filter__popover-header {
@@ -476,7 +330,7 @@ ColumnHeaderFilterComponent = __decorate([
476
330
  .ogrid-header-filter__people-option:hover { background: rgba(0,0,0,0.04); }
477
331
  `],
478
332
  host: {
479
- '(document:click)': 'onDocumentClick($event)',
333
+ '(document:click)': 'onDocumentClickWrapper($event)',
480
334
  },
481
335
  })
482
336
  ], ColumnHeaderFilterComponent);
@@ -4,96 +4,129 @@ var __decorate = (this && this.__decorate) || function (decorators, target, key,
4
4
  else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
5
5
  return c > 3 && r && Object.defineProperty(target, key, r), r;
6
6
  };
7
- import { Component, input, viewChild, ChangeDetectionStrategy } from '@angular/core';
7
+ import { Component, ChangeDetectionStrategy, ViewChild, computed, Input } from '@angular/core';
8
8
  import { MatMenuModule, MatMenuTrigger } from '@angular/material/menu';
9
- import { MatButtonModule } from '@angular/material/button';
10
- import { MatIconModule } from '@angular/material/icon';
11
- import { COLUMN_HEADER_MENU_ITEMS } from '@alaarab/ogrid-core';
9
+ import { MatDividerModule } from '@angular/material/divider';
10
+ import { getColumnHeaderMenuItems } from '@alaarab/ogrid-core';
12
11
  /**
13
- * Column header dropdown menu for pin/unpin actions.
12
+ * Column header dropdown menu for pin/unpin, sort, and autosize actions.
14
13
  * Uses Angular Material MatMenu.
15
14
  */
16
15
  let ColumnHeaderMenuComponent = class ColumnHeaderMenuComponent {
17
16
  constructor() {
18
- this.columnId = input.required();
19
- this.canPinLeft = input(true);
20
- this.canPinRight = input(true);
21
- this.canUnpin = input(false);
22
- this.onPinLeft = input(undefined);
23
- this.onPinRight = input(undefined);
24
- this.onUnpin = input(undefined);
25
- this.menuTrigger = viewChild(MatMenuTrigger);
26
- this.menuItems = COLUMN_HEADER_MENU_ITEMS;
17
+ this.canPinLeft = true;
18
+ this.canPinRight = true;
19
+ this.canUnpin = false;
20
+ this.currentSort = null;
21
+ this.isSortable = true;
22
+ this.isResizable = true;
23
+ this.handlers = {};
24
+ this.menuItems = computed(() => getColumnHeaderMenuItems({
25
+ canPinLeft: this.canPinLeft,
26
+ canPinRight: this.canPinRight,
27
+ canUnpin: this.canUnpin,
28
+ currentSort: this.currentSort,
29
+ isSortable: this.isSortable,
30
+ isResizable: this.isResizable,
31
+ }));
27
32
  }
28
- handlePinLeft() {
29
- if (this.canPinLeft()) {
30
- this.onPinLeft()?.();
31
- }
32
- }
33
- handlePinRight() {
34
- if (this.canPinRight()) {
35
- this.onPinRight()?.();
36
- }
37
- }
38
- handleUnpin() {
39
- if (this.canUnpin()) {
40
- this.onUnpin()?.();
33
+ handleMenuItemClick(itemId) {
34
+ const h = this.handlers;
35
+ const actionMap = {
36
+ pinLeft: h.onPinLeft,
37
+ pinRight: h.onPinRight,
38
+ unpin: h.onUnpin,
39
+ sortAsc: h.onSortAsc,
40
+ sortDesc: h.onSortDesc,
41
+ clearSort: h.onClearSort,
42
+ autosizeThis: h.onAutosizeThis,
43
+ autosizeAll: h.onAutosizeAll,
44
+ };
45
+ const action = actionMap[itemId];
46
+ if (action) {
47
+ action();
48
+ h.onClose?.();
41
49
  }
42
50
  }
43
51
  };
52
+ __decorate([
53
+ Input({ required: true })
54
+ ], ColumnHeaderMenuComponent.prototype, "columnId", void 0);
55
+ __decorate([
56
+ Input()
57
+ ], ColumnHeaderMenuComponent.prototype, "canPinLeft", void 0);
58
+ __decorate([
59
+ Input()
60
+ ], ColumnHeaderMenuComponent.prototype, "canPinRight", void 0);
61
+ __decorate([
62
+ Input()
63
+ ], ColumnHeaderMenuComponent.prototype, "canUnpin", void 0);
64
+ __decorate([
65
+ Input()
66
+ ], ColumnHeaderMenuComponent.prototype, "currentSort", void 0);
67
+ __decorate([
68
+ Input()
69
+ ], ColumnHeaderMenuComponent.prototype, "isSortable", void 0);
70
+ __decorate([
71
+ Input()
72
+ ], ColumnHeaderMenuComponent.prototype, "isResizable", void 0);
73
+ __decorate([
74
+ Input()
75
+ ], ColumnHeaderMenuComponent.prototype, "handlers", void 0);
76
+ __decorate([
77
+ ViewChild(MatMenuTrigger)
78
+ ], ColumnHeaderMenuComponent.prototype, "menuTrigger", void 0);
44
79
  ColumnHeaderMenuComponent = __decorate([
45
80
  Component({
46
81
  selector: 'column-header-menu',
47
82
  standalone: true,
48
- imports: [MatMenuModule, MatButtonModule, MatIconModule],
49
83
  changeDetection: ChangeDetectionStrategy.OnPush,
84
+ imports: [MatMenuModule, MatDividerModule],
50
85
  template: `
51
86
  <button
52
- mat-icon-button
53
87
  [matMenuTriggerFor]="menu"
54
88
  class="column-header-menu-trigger"
55
- [attr.aria-label]="'Column options for ' + columnId()"
89
+ [attr.aria-label]="'Column options for ' + columnId"
56
90
  >
57
- <mat-icon>more_vert</mat-icon>
91
+ &#8942;
58
92
  </button>
59
93
 
60
94
  <mat-menu #menu="matMenu">
61
- <button
62
- mat-menu-item
63
- [disabled]="!canPinLeft()"
64
- (click)="handlePinLeft()"
65
- >
66
- {{ menuItems[0].label }}
67
- </button>
68
- <button
69
- mat-menu-item
70
- [disabled]="!canPinRight()"
71
- (click)="handlePinRight()"
72
- >
73
- {{ menuItems[1].label }}
74
- </button>
75
- <button
76
- mat-menu-item
77
- [disabled]="!canUnpin()"
78
- (click)="handleUnpin()"
79
- >
80
- {{ menuItems[2].label }}
81
- </button>
95
+ @for (item of menuItems(); track item.id) {
96
+ <button
97
+ mat-menu-item
98
+ [disabled]="item.disabled"
99
+ (click)="handleMenuItemClick(item.id)"
100
+ >
101
+ {{ item.label }}
102
+ </button>
103
+ @if (item.divider) {
104
+ <mat-divider></mat-divider>
105
+ }
106
+ }
82
107
  </mat-menu>
83
108
  `,
84
109
  styles: [`
110
+ :host { flex-shrink: 0; }
85
111
  .column-header-menu-trigger {
86
- opacity: 0;
87
- transition: opacity 0.15s;
88
112
  width: 24px;
89
113
  height: 24px;
90
- line-height: 24px;
91
114
  padding: 0;
115
+ border: none;
116
+ border-radius: 4px;
117
+ background: transparent;
118
+ cursor: pointer;
119
+ font-size: 16px;
120
+ line-height: 1;
121
+ display: inline-flex;
122
+ align-items: center;
123
+ justify-content: center;
124
+ color: rgba(0,0,0,0.54);
92
125
  }
93
126
 
94
- :host:hover .column-header-menu-trigger,
95
- .column-header-menu-trigger:focus {
96
- opacity: 1;
127
+ .column-header-menu-trigger:hover {
128
+ background: rgba(0,0,0,0.08);
129
+ color: rgba(0,0,0,0.87);
97
130
  }
98
131
  `],
99
132
  })