@alaarab/ogrid-angular-primeng 2.0.19 → 2.0.22

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,8 +4,7 @@ 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 } from '@angular/core';
8
- import { CommonModule } from '@angular/common';
7
+ import { Component, ChangeDetectionStrategy } from '@angular/core';
9
8
  import { BaseColumnChooserComponent } from '@alaarab/ogrid-angular';
10
9
  let ColumnChooserComponent = class ColumnChooserComponent extends BaseColumnChooserComponent {
11
10
  // PrimeNG uses 'open' instead of 'isOpen'
@@ -17,7 +16,7 @@ ColumnChooserComponent = __decorate([
17
16
  Component({
18
17
  selector: 'ogrid-primeng-column-chooser',
19
18
  standalone: true,
20
- imports: [CommonModule],
19
+ changeDetection: ChangeDetectionStrategy.OnPush,
21
20
  template: `
22
21
  <div style="position:relative;display:inline-block">
23
22
  <button
@@ -35,7 +34,7 @@ ColumnChooserComponent = __decorate([
35
34
 
36
35
  @if (open()) {
37
36
  <div
38
- style="position:absolute;right:0;top:100%;z-index:100;min-width:220px;max-height:320px;overflow-y:auto;background:var(--ogrid-bg, #fff);border:1px solid var(--ogrid-border, #e0e0e0);border-radius:6px;box-shadow:0 2px 8px rgba(0,0,0,0.12);padding:8px 0"
37
+ style="position:absolute;right:0;top:100%;z-index:1000;min-width:220px;max-height:320px;overflow-y:auto;background:var(--ogrid-bg, #fff);border:1px solid var(--ogrid-border, rgba(0, 0, 0, 0.12));border-radius:6px;box-shadow:0 2px 8px rgba(0,0,0,0.12);padding:8px 0"
39
38
  >
40
39
  <div style="padding:4px 12px;font-weight:600;font-size:12px;color:var(--ogrid-fg-secondary, rgba(0, 0, 0, 0.6))">
41
40
  Select Columns ({{ visibleCount() }} of {{ totalCount() }})
@@ -51,7 +50,7 @@ ColumnChooserComponent = __decorate([
51
50
  {{ col.name }}
52
51
  </label>
53
52
  }
54
- <div style="display:flex;gap:4px;padding:8px 12px;border-top:1px solid var(--ogrid-border, #e0e0e0);margin-top:4px">
53
+ <div style="display:flex;gap:4px;padding:8px 12px;border-top:1px solid var(--ogrid-border, rgba(0, 0, 0, 0.12));margin-top:4px">
55
54
  <button
56
55
  type="button"
57
56
  class="p-button p-button-text p-button-sm"
@@ -4,8 +4,7 @@ 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, ViewChild, DestroyRef, inject, effect } from '@angular/core';
8
- import { CommonModule } from '@angular/common';
7
+ import { Component, ViewChild, DestroyRef, inject, effect, ChangeDetectionStrategy } from '@angular/core';
9
8
  import { BaseColumnHeaderFilterComponent } from '@alaarab/ogrid-angular';
10
9
  let ColumnHeaderFilterComponent = class ColumnHeaderFilterComponent extends BaseColumnHeaderFilterComponent {
11
10
  getHeaderEl() {
@@ -62,7 +61,7 @@ ColumnHeaderFilterComponent = __decorate([
62
61
  Component({
63
62
  selector: 'ogrid-primeng-column-header-filter',
64
63
  standalone: true,
65
- imports: [CommonModule],
64
+ changeDetection: ChangeDetectionStrategy.OnPush,
66
65
  template: `
67
66
  <div style="display:flex;align-items:center;flex:1;min-width:0;gap:4px">
68
67
  <div style="flex:1;min-width:0;overflow:hidden">
@@ -71,19 +70,6 @@ ColumnHeaderFilterComponent = __decorate([
71
70
  </span>
72
71
  </div>
73
72
  <div style="display:flex;align-items:center;gap:2px;flex-shrink:0">
74
- @if (onSort) {
75
- <button
76
- type="button"
77
- (click)="handleSortClick()"
78
- [attr.aria-label]="'Sort by ' + columnName"
79
- [title]="isSorted ? (isSortedDescending ? 'Sorted descending' : 'Sorted ascending') : 'Sort'"
80
- style="border:none;background:transparent;cursor:pointer;padding:2px 4px;font-size:12px;color:var(--ogrid-fg, #242424)"
81
- [style.font-weight]="isSorted ? 'bold' : 'normal'"
82
- >
83
- {{ isSorted ? (isSortedDescending ? '\u2193' : '\u2191') : '\u21C5' }}
84
- </button>
85
- }
86
-
87
73
  @if (filterType !== 'none') {
88
74
  <button
89
75
  type="button"
@@ -103,9 +89,9 @@ ColumnHeaderFilterComponent = __decorate([
103
89
  @if (isFilterOpen()) {
104
90
  <div
105
91
  #filterPanel
106
- style="position:absolute;top:100%;left:0;z-index:200;min-width:200px;background:var(--ogrid-bg, #fff);border:1px solid var(--ogrid-border, #e0e0e0);border-radius:6px;box-shadow:0 2px 8px rgba(0,0,0,0.12);font-weight:normal"
92
+ style="position:absolute;top:100%;left:0;z-index:1000;min-width:200px;background:var(--ogrid-bg, #fff);border:1px solid var(--ogrid-border, rgba(0, 0, 0, 0.12));border-radius:6px;box-shadow:0 2px 8px rgba(0,0,0,0.12);font-weight:normal"
107
93
  >
108
- <div style="padding:8px 12px;font-weight:600;font-size:12px;border-bottom:1px solid var(--ogrid-border, #e0e0e0)">
94
+ <div style="padding:8px 12px;font-weight:600;font-size:12px;border-bottom:1px solid var(--ogrid-border, rgba(0, 0, 0, 0.12))">
109
95
  Filter: {{ columnName }}
110
96
  </div>
111
97
 
@@ -116,11 +102,11 @@ ColumnHeaderFilterComponent = __decorate([
116
102
  [value]="tempTextValue()"
117
103
  (input)="tempTextValue.set($any($event.target).value)"
118
104
  placeholder="Filter text..."
119
- style="width:100%;box-sizing:border-box;padding:6px 8px;border:1px solid var(--ogrid-border, #e0e0e0);border-radius:4px;font-size:13px;background:var(--ogrid-bg, #fff);color:var(--ogrid-fg, #242424)"
105
+ style="width:100%;box-sizing:border-box;padding:6px 8px;border:1px solid var(--ogrid-border, rgba(0, 0, 0, 0.12));border-radius:4px;font-size:13px;background:var(--ogrid-bg, #fff);color:var(--ogrid-fg, #242424)"
120
106
  [attr.aria-label]="'Filter ' + columnName"
121
107
  />
122
108
  </div>
123
- <div style="display:flex;justify-content:flex-end;gap:6px;padding:6px 12px;border-top:1px solid var(--ogrid-border, #e0e0e0)">
109
+ <div style="display:flex;justify-content:flex-end;gap:6px;padding:6px 12px;border-top:1px solid var(--ogrid-border, rgba(0, 0, 0, 0.12))">
124
110
  <button
125
111
  type="button"
126
112
  class="p-button p-button-text p-button-sm"
@@ -144,7 +130,7 @@ ColumnHeaderFilterComponent = __decorate([
144
130
  [value]="searchText()"
145
131
  (input)="searchText.set($any($event.target).value)"
146
132
  placeholder="Search options..."
147
- style="width:100%;box-sizing:border-box;padding:6px 8px;border:1px solid var(--ogrid-border, #e0e0e0);border-radius:4px;font-size:13px;margin-bottom:6px;background:var(--ogrid-bg, #fff);color:var(--ogrid-fg, #242424)"
133
+ style="width:100%;box-sizing:border-box;padding:6px 8px;border:1px solid var(--ogrid-border, rgba(0, 0, 0, 0.12));border-radius:4px;font-size:13px;margin-bottom:6px;background:var(--ogrid-bg, #fff);color:var(--ogrid-fg, #242424)"
148
134
  [attr.aria-label]="'Search ' + columnName + ' options'"
149
135
  />
150
136
  @if (isLoadingOptions) {
@@ -168,7 +154,7 @@ ColumnHeaderFilterComponent = __decorate([
168
154
  </div>
169
155
  }
170
156
  </div>
171
- <div style="display:flex;justify-content:flex-end;gap:6px;padding:6px 12px;border-top:1px solid var(--ogrid-border, #e0e0e0)">
157
+ <div style="display:flex;justify-content:flex-end;gap:6px;padding:6px 12px;border-top:1px solid var(--ogrid-border, rgba(0, 0, 0, 0.12))">
172
158
  <button
173
159
  type="button"
174
160
  class="p-button p-button-sm"
@@ -191,7 +177,7 @@ ColumnHeaderFilterComponent = __decorate([
191
177
  [value]="peopleSearchText()"
192
178
  (input)="onPeopleSearchInput($any($event.target).value)"
193
179
  placeholder="Search people..."
194
- style="width:100%;box-sizing:border-box;padding:6px 8px;border:1px solid var(--ogrid-border, #e0e0e0);border-radius:4px;font-size:13px;background:var(--ogrid-bg, #fff);color:var(--ogrid-fg, #242424)"
180
+ style="width:100%;box-sizing:border-box;padding:6px 8px;border:1px solid var(--ogrid-border, rgba(0, 0, 0, 0.12));border-radius:4px;font-size:13px;background:var(--ogrid-bg, #fff);color:var(--ogrid-fg, #242424)"
195
181
  [attr.aria-label]="'Search people for ' + columnName"
196
182
  />
197
183
  @if (isPeopleLoading()) {
@@ -217,7 +203,7 @@ ColumnHeaderFilterComponent = __decorate([
217
203
  type="date"
218
204
  [value]="tempDateFrom()"
219
205
  (change)="tempDateFrom.set($any($event.target).value)"
220
- style="flex:1;padding:4px 6px;border:1px solid var(--ogrid-border, #e0e0e0);border-radius:4px;background:var(--ogrid-bg, #fff);color:var(--ogrid-fg, #242424)"
206
+ style="flex:1;padding:4px 6px;border:1px solid var(--ogrid-border, rgba(0, 0, 0, 0.12));border-radius:4px;background:var(--ogrid-bg, #fff);color:var(--ogrid-fg, #242424)"
221
207
  />
222
208
  </label>
223
209
  <label style="display:flex;align-items:center;gap:6px;font-size:12px">
@@ -226,11 +212,11 @@ ColumnHeaderFilterComponent = __decorate([
226
212
  type="date"
227
213
  [value]="tempDateTo()"
228
214
  (change)="tempDateTo.set($any($event.target).value)"
229
- style="flex:1;padding:4px 6px;border:1px solid var(--ogrid-border, #e0e0e0);border-radius:4px;background:var(--ogrid-bg, #fff);color:var(--ogrid-fg, #242424)"
215
+ style="flex:1;padding:4px 6px;border:1px solid var(--ogrid-border, rgba(0, 0, 0, 0.12));border-radius:4px;background:var(--ogrid-bg, #fff);color:var(--ogrid-fg, #242424)"
230
216
  />
231
217
  </label>
232
218
  </div>
233
- <div style="display:flex;justify-content:flex-end;gap:6px;padding:6px 12px;border-top:1px solid var(--ogrid-border, #e0e0e0)">
219
+ <div style="display:flex;justify-content:flex-end;gap:6px;padding:6px 12px;border-top:1px solid var(--ogrid-border, rgba(0, 0, 0, 0.12))">
234
220
  <button
235
221
  type="button"
236
222
  class="p-button p-button-text p-button-sm"
@@ -5,7 +5,7 @@ var __decorate = (this && this.__decorate) || function (decorators, target, key,
5
5
  return c > 3 && r && Object.defineProperty(target, key, r), r;
6
6
  };
7
7
  import { Component, Input, signal, computed, ViewChild, ChangeDetectionStrategy, ViewEncapsulation, } from '@angular/core';
8
- import { BaseDataGridTableComponent, DataGridStateService, StatusBarComponent, GridContextMenuComponent, MarchingAntsOverlayComponent, EmptyStateComponent, DEFAULT_MIN_COLUMN_WIDTH, getCellValue, resolveCellDisplayContent, resolveCellStyle, } from '@alaarab/ogrid-angular';
8
+ import { BaseDataGridTableComponent, DataGridStateService, StatusBarComponent, GridContextMenuComponent, MarchingAntsOverlayComponent, EmptyStateComponent, DEFAULT_MIN_COLUMN_WIDTH, OGRID_THEME_VARS_CSS, } from '@alaarab/ogrid-angular';
9
9
  import { ColumnHeaderFilterComponent } from '../column-header-filter/column-header-filter.component';
10
10
  import { ColumnHeaderMenuComponent } from '../column-header-menu/column-header-menu.component';
11
11
  import { InlineCellEditorComponent } from './inline-cell-editor.component';
@@ -100,8 +100,26 @@ let DataGridTableComponent = class DataGridTableComponent extends BaseDataGridTa
100
100
  this.primengColumnSizingOverrides.set({ ...iw });
101
101
  }
102
102
  }
103
- // Rebuild props signal whenever any input changes so computed chains track it
104
- this.propsSignal.set(this.buildProps());
103
+ // Rebuild props and only set if values actually changed (shallow compare)
104
+ const next = this.buildProps();
105
+ const prev = this.propsSignal();
106
+ if (!prev || !this.shallowEqual(prev, next)) {
107
+ this.propsSignal.set(next);
108
+ }
109
+ }
110
+ /** Shallow-compare two props objects by their top-level keys. */
111
+ shallowEqual(a, b) {
112
+ const aObj = a;
113
+ const bObj = b;
114
+ const keysA = Object.keys(aObj);
115
+ const keysB = Object.keys(bObj);
116
+ if (keysA.length !== keysB.length)
117
+ return false;
118
+ for (const key of keysA) {
119
+ if (aObj[key] !== bObj[key])
120
+ return false;
121
+ }
122
+ return true;
105
123
  }
106
124
  // --- Abstract method implementations ---
107
125
  getProps() {
@@ -124,94 +142,7 @@ let DataGridTableComponent = class DataGridTableComponent extends BaseDataGridTa
124
142
  trackByRowId(_index, item) {
125
143
  return this.getRowIdInput(item);
126
144
  }
127
- getCellValueFn(item, col) {
128
- return getCellValue(item, col);
129
- }
130
- resolveCellDisplay(col, item) {
131
- const value = getCellValue(item, col);
132
- const result = resolveCellDisplayContent(col, item, value);
133
- return result != null ? String(result) : '';
134
- }
135
- getCellStyleObj(col, item) {
136
- return resolveCellStyle(col, item) ?? null;
137
- }
138
- canEditCell(col, item) {
139
- const colEditable = col.editable === true || (typeof col.editable === 'function' && col.editable(item));
140
- return this.editable !== false && !!colEditable && this.onCellValueChanged != null && typeof col.cellEditor !== 'function';
141
- }
142
- isEditingCell(item, col) {
143
- const editing = this.editingCell();
144
- if (!editing)
145
- return false;
146
- return editing.rowId === this.getRowIdInput(item) && editing.columnId === col.columnId;
147
- }
148
- isEditingCellInline(item, col) {
149
- return this.isEditingCell(item, col) && typeof col.cellEditor !== 'function';
150
- }
151
- isEditingCellPopover(item, col) {
152
- return this.isEditingCell(item, col) && typeof col.cellEditor === 'function';
153
- }
154
- buildPopoverEditorPropsForPrimeng(item, col, rowIndex, colIdx) {
155
- const oldValue = getCellValue(item, col);
156
- const pendingValue = this.pendingEditorValue();
157
- const displayValue = pendingValue !== undefined ? pendingValue : oldValue;
158
- return {
159
- value: displayValue,
160
- onValueChange: (value) => this.setPendingEditorValue(value),
161
- item,
162
- column: col,
163
- rowIndex,
164
- onCommit: (newValue) => this.onCellEditorCommit(item, col, rowIndex, colIdx, newValue),
165
- onCancel: () => this.cancelEdit(),
166
- };
167
- }
168
- getEditorType(col, _item) {
169
- if (col.cellEditor === 'text' || col.cellEditor === 'select' || col.cellEditor === 'checkbox' || col.cellEditor === 'date' || col.cellEditor === 'richSelect') {
170
- return col.cellEditor;
171
- }
172
- if (col.type === 'date')
173
- return 'date';
174
- if (col.type === 'boolean')
175
- return 'checkbox';
176
- return 'text';
177
- }
178
- isActiveCell(rowIndex, colIdx) {
179
- const ac = this.activeCell();
180
- if (!ac)
181
- return false;
182
- return ac.rowIndex === rowIndex && ac.columnIndex === colIdx + this.colOffset();
183
- }
184
- isInSelectionRange(rowIndex, colIdx) {
185
- const range = this.selectionRange();
186
- if (!range)
187
- return false;
188
- const minR = Math.min(range.startRow, range.endRow);
189
- const maxR = Math.max(range.startRow, range.endRow);
190
- const minC = Math.min(range.startCol, range.endCol);
191
- const maxC = Math.max(range.startCol, range.endCol);
192
- return rowIndex >= minR && rowIndex <= maxR && colIdx >= minC && colIdx <= maxC;
193
- }
194
- isSelectionEndCell(rowIndex, colIdx) {
195
- const range = this.selectionRange();
196
- if (!range || this.isDragging() || this.copyRange() || this.cutRange())
197
- return false;
198
- return rowIndex === range.endRow && colIdx === range.endCol;
199
- }
200
- getCellBackground(rowIndex, colIdx) {
201
- if (this.isInSelectionRange(rowIndex, colIdx))
202
- return 'var(--ogrid-range-bg, rgba(33, 115, 70, 0.08))';
203
- return null;
204
- }
205
145
  // --- PrimeNG-specific event handlers ---
206
- onCellDblClickPrimeng(item, col, _rowIndex, _colIdx) {
207
- if (this.canEditCell(col, item)) {
208
- this.stateService.setEditingCell({ rowId: this.getRowIdInput(item), columnId: col.columnId });
209
- }
210
- }
211
- onCellEditorCommit(item, col, rowIndex, colIdx, newValue) {
212
- const oldValue = getCellValue(item, col);
213
- this.stateService.commitCellEdit(item, col.columnId, oldValue, newValue, rowIndex, colIdx + this.colOffset());
214
- }
215
146
  onSelectAllChangePrimeng(checked) {
216
147
  this.state().rowSelection.handleSelectAll(checked);
217
148
  }
@@ -222,19 +153,6 @@ let DataGridTableComponent = class DataGridTableComponent extends BaseDataGridTa
222
153
  const ids = this.selectedRowIds();
223
154
  this.state().rowSelection.updateSelection(ids.has(rowId) ? new Set() : new Set([rowId]));
224
155
  }
225
- getColumnHeaderMenuHandlers(columnId) {
226
- return {
227
- onPinLeft: () => this.onPinColumn(columnId, 'left'),
228
- onPinRight: () => this.onPinColumn(columnId, 'right'),
229
- onUnpin: () => this.onUnpinColumn(columnId),
230
- onSortAsc: () => this.onSortAsc(columnId),
231
- onSortDesc: () => this.onSortDesc(columnId),
232
- onClearSort: () => this.onClearSort(columnId),
233
- onAutosizeThis: () => this.onAutosizeColumn(columnId),
234
- onAutosizeAll: () => this.onAutosizeAllColumns(),
235
- onClose: () => { }
236
- };
237
- }
238
156
  onRowCheckboxChangePrimeng(item, checked, rowIndex, _e) {
239
157
  const rowId = this.getRowIdInput(item);
240
158
  this.state().rowSelection.handleRowCheckboxChange(rowId, checked, rowIndex, this.lastMouseShift);
@@ -489,6 +407,7 @@ DataGridTableComponent = __decorate([
489
407
  [style.--data-table-column-count]="state().layout.totalColCount"
490
408
  [style.--data-table-width]="tableWidthStyle()"
491
409
  [style.--data-table-min-width]="tableMinWidthStyle()"
410
+ [style.--ogrid-row-height]="rowHeightCssVar()"
492
411
  >
493
412
  <div class="ogrid-table-wrapper">
494
413
  <div [class.loading-dimmed]="isLoading() && items().length > 0" class="ogrid-table-wrapper">
@@ -519,7 +438,7 @@ DataGridTableComponent = __decorate([
519
438
  @if (rowIdx === 0 && rowIdx < headerRows().length - 1 && hasRowNumbersCol()) {
520
439
  <th [attr.rowSpan]="headerRows().length - 1" class="ogrid-row-number-spacer"></th>
521
440
  }
522
- @for (cell of row; track $index; let cellIdx = $index) {
441
+ @for (cell of row; track cell.columnDef?.columnId ?? $index; let cellIdx = $index) {
523
442
  @if (cell.isGroup) {
524
443
  <th
525
444
  [attr.colSpan]="cell.colSpan"
@@ -531,10 +450,14 @@ DataGridTableComponent = __decorate([
531
450
  } @else {
532
451
  @let col = asColumnDef(cell.columnDef);
533
452
  @let pinned = isPinned(col.columnId);
453
+ @let config = getFilterConfig(col);
454
+ @let sortState = getSortState(col.columnId);
455
+ @let ariaSort = sortState === 'asc' ? 'ascending' : sortState === 'desc' ? 'descending' : null;
534
456
  <th
535
457
  scope="col"
536
458
  class="ogrid-header-cell"
537
459
  [attr.data-column-id]="col.columnId"
460
+ [attr.aria-sort]="ariaSort"
538
461
  [attr.rowSpan]="headerRows().length > 1 && rowIdx < headerRows().length - 1 ? headerRows().length - rowIdx : null"
539
462
  [class.ogrid-th-pinned-left]="pinned === 'left'"
540
463
  [class.ogrid-th-pinned-right]="pinned === 'right'"
@@ -550,33 +473,32 @@ DataGridTableComponent = __decorate([
550
473
  <ogrid-primeng-column-header-filter
551
474
  [columnKey]="col.columnId"
552
475
  [columnName]="col.name"
553
- [filterType]="getFilterConfig(col).filterType"
554
- [isSorted]="getFilterConfig(col).isSorted ?? false"
555
- [isSortedDescending]="getFilterConfig(col).isSortedDescending ?? false"
556
- [onSort]="getFilterConfig(col).onSort"
557
- [selectedValues]="getFilterConfig(col).selectedValues"
558
- [onFilterChange]="getFilterConfig(col).onFilterChange"
559
- [options]="getFilterConfig(col).options ?? []"
560
- [isLoadingOptions]="getFilterConfig(col).isLoadingOptions ?? false"
561
- [textValue]="getFilterConfig(col).textValue ?? ''"
562
- [onTextChange]="getFilterConfig(col).onTextChange"
563
- [selectedUser]="getFilterConfig(col).selectedUser"
564
- [onUserChange]="getFilterConfig(col).onUserChange"
565
- [peopleSearch]="getFilterConfig(col).peopleSearch"
566
- [dateValue]="getFilterConfig(col).dateValue"
567
- [onDateChange]="getFilterConfig(col).onDateChange"
476
+ [filterType]="config.filterType"
477
+ [isSorted]="config.isSorted ?? false"
478
+ [isSortedDescending]="config.isSortedDescending ?? false"
479
+ [onSort]="config.onSort"
480
+ [selectedValues]="config.selectedValues"
481
+ [onFilterChange]="config.onFilterChange"
482
+ [options]="config.options ?? []"
483
+ [isLoadingOptions]="config.isLoadingOptions ?? false"
484
+ [textValue]="config.textValue ?? ''"
485
+ [onTextChange]="config.onTextChange"
486
+ [selectedUser]="config.selectedUser"
487
+ [onUserChange]="config.onUserChange"
488
+ [peopleSearch]="config.peopleSearch"
489
+ [dateValue]="config.dateValue"
490
+ [onDateChange]="config.onDateChange"
568
491
  ></ogrid-primeng-column-header-filter>
569
492
  @let colPinState = getPinState(col.columnId);
570
- @let colSortState = getSortState(col.columnId);
571
493
  <column-header-menu
572
494
  [columnId]="col.columnId"
573
495
  [canPinLeft]="colPinState.canPinLeft"
574
496
  [canPinRight]="colPinState.canPinRight"
575
497
  [canUnpin]="colPinState.canUnpin"
576
- [currentSort]="colSortState"
498
+ [currentSort]="sortState"
577
499
  [isSortable]="col.sortable !== false"
578
500
  [isResizable]="col.resizable !== false"
579
- [handlers]="getColumnHeaderMenuHandlers(col.columnId)"
501
+ [handlers]="getColumnMenuHandlersMemoized(col.columnId)"
580
502
  />
581
503
  </div>
582
504
  <div
@@ -640,44 +562,45 @@ DataGridTableComponent = __decorate([
640
562
  [style.right.px]="pinned === 'right' ? getPinnedRightOffset(col.columnId) : null"
641
563
  [style.text-align]="col.type === 'numeric' ? 'right' : col.type === 'boolean' ? 'center' : null"
642
564
  >
643
- @if (isEditingCellInline(item, col)) {
565
+ @let descriptor = getCellDescriptor(item, col, rowIndex, colIdx);
566
+ @if (descriptor.mode === 'editing-inline') {
644
567
  <div class="ogrid-editing-cell">
645
568
  <ogrid-primeng-inline-cell-editor
646
- [value]="getCellValueFn(item, col)"
569
+ [value]="descriptor.value"
647
570
  [item]="item"
648
571
  [column]="col"
649
572
  [rowIndex]="rowIndex"
650
- [editorType]="getEditorType(col, item)"
651
- (commit)="onCellEditorCommit(item, col, rowIndex, colIdx, $event)"
573
+ [editorType]="descriptor.editorType ?? 'text'"
574
+ (commit)="commitEdit(item, col.columnId, descriptor.value, $event, rowIndex, descriptor.globalColIndex)"
652
575
  (cancel)="cancelEdit()"
653
576
  ></ogrid-primeng-inline-cell-editor>
654
577
  </div>
655
- } @else if (isEditingCellPopover(item, col)) {
656
- @let editorProps = buildPopoverEditorPropsForPrimeng(item, col, rowIndex, colIdx);
578
+ } @else if (descriptor.mode === 'editing-popover') {
579
+ @let editorProps = buildPopoverEditorProps(item, col, descriptor);
657
580
  <ogrid-primeng-popover-cell-editor
658
581
  [item]="item"
659
582
  [column]="col"
660
583
  [rowIndex]="rowIndex"
661
- [globalColIndex]="colIdx + colOffset()"
662
- [displayValue]="getCellValueFn(item, col)"
584
+ [globalColIndex]="descriptor.globalColIndex"
585
+ [displayValue]="descriptor.displayValue"
663
586
  [editorProps]="editorProps"
664
587
  [onCancel]="cancelEditHandler"
665
588
  ></ogrid-primeng-popover-cell-editor>
666
589
  } @else {
667
590
  <div
668
591
  [attr.data-row-index]="rowIndex"
669
- [attr.data-col-index]="colIdx + colOffset()"
670
- (mousedown)="onCellMouseDown($event, rowIndex, colIdx + colOffset())"
671
- (dblclick)="onCellDblClickPrimeng(item, col, rowIndex, colIdx)"
592
+ [attr.data-col-index]="descriptor.globalColIndex"
593
+ (mousedown)="onCellMouseDown($event, rowIndex, descriptor.globalColIndex)"
594
+ (dblclick)="descriptor.canEditAny ? onCellDblClick(descriptor.rowId, col.columnId) : null"
672
595
  (contextmenu)="onCellContextMenu($event)"
673
596
  class="ogrid-cell-content"
674
- [style.cursor]="canEditCell(col, item) ? 'cell' : 'default'"
675
- [style.background]="getCellBackground(rowIndex, colIdx)"
676
- [style.outline]="isActiveCell(rowIndex, colIdx) ? '2px solid var(--ogrid-selection, #217346)' : null"
677
- [style.outline-offset]="isActiveCell(rowIndex, colIdx) ? '-2px' : null"
597
+ [style.cursor]="descriptor.canEditAny ? 'cell' : 'default'"
598
+ [style.background]="descriptor.isInRange ? 'var(--ogrid-range-bg, rgba(33, 115, 70, 0.08))' : null"
599
+ [style.outline]="descriptor.isActive ? '2px solid var(--ogrid-selection, #217346)' : null"
600
+ [style.outline-offset]="descriptor.isActive ? '-2px' : null"
678
601
  >
679
- <span [style]="getCellStyleObj(col, item)">{{ resolveCellDisplay(col, item) }}</span>
680
- @if (canEditCell(col, item) && isSelectionEndCell(rowIndex, colIdx)) {
602
+ <span [style]="resolveCellStyleFn(col, item)">{{ resolveCellContent(col, item, descriptor.displayValue) }}</span>
603
+ @if (descriptor.canEditAny && descriptor.isSelectionEndCell) {
681
604
  <div
682
605
  (mousedown)="onFillHandleMouseDown($event)"
683
606
  class="ogrid-fill-handle"
@@ -749,14 +672,15 @@ DataGridTableComponent = __decorate([
749
672
  ></ogrid-context-menu>
750
673
  }
751
674
 
752
- @if (statusBarConfig()) {
675
+ @let sbConfig = statusBarConfig();
676
+ @if (sbConfig) {
753
677
  <ogrid-status-bar
754
- [totalCount]="statusBarConfig()!.totalCount"
755
- [filteredCount]="statusBarConfig()!.filteredCount"
756
- [selectedCount]="statusBarConfig()!.selectedCount ?? selectedRowIds().size"
678
+ [totalCount]="sbConfig.totalCount"
679
+ [filteredCount]="sbConfig.filteredCount"
680
+ [selectedCount]="sbConfig.selectedCount ?? selectedRowIds().size"
757
681
  [selectedCellCount]="selectionCellCount()"
758
- [aggregation]="statusBarConfig()!.aggregation"
759
- [suppressRowCount]="statusBarConfig()!.suppressRowCount"
682
+ [aggregation]="sbConfig.aggregation"
683
+ [suppressRowCount]="sbConfig.suppressRowCount"
760
684
  [classNames]="statusBarClasses"
761
685
  ></ogrid-status-bar>
762
686
  }
@@ -770,55 +694,7 @@ DataGridTableComponent = __decorate([
770
694
  }
771
695
  </div>
772
696
  `,
773
- styles: [`
774
- /* ─── OGrid Theme Variables ─── */
775
- :root {
776
- --ogrid-bg: #ffffff;
777
- --ogrid-fg: rgba(0, 0, 0, 0.87);
778
- --ogrid-fg-secondary: rgba(0, 0, 0, 0.6);
779
- --ogrid-fg-muted: rgba(0, 0, 0, 0.5);
780
- --ogrid-border: rgba(0, 0, 0, 0.12);
781
- --ogrid-header-bg: rgba(0, 0, 0, 0.04);
782
- --ogrid-hover-bg: rgba(0, 0, 0, 0.04);
783
- --ogrid-selected-row-bg: #e6f0fb;
784
- --ogrid-active-cell-bg: rgba(0, 0, 0, 0.02);
785
- --ogrid-range-bg: rgba(33, 115, 70, 0.12);
786
- --ogrid-accent: #0078d4;
787
- --ogrid-selection-color: #217346;
788
- --ogrid-loading-overlay: rgba(255, 255, 255, 0.7);
789
- }
790
- @media (prefers-color-scheme: dark) {
791
- :root:not([data-theme="light"]) {
792
- --ogrid-bg: #1e1e1e;
793
- --ogrid-fg: rgba(255, 255, 255, 0.87);
794
- --ogrid-fg-secondary: rgba(255, 255, 255, 0.6);
795
- --ogrid-fg-muted: rgba(255, 255, 255, 0.5);
796
- --ogrid-border: rgba(255, 255, 255, 0.12);
797
- --ogrid-header-bg: rgba(255, 255, 255, 0.06);
798
- --ogrid-hover-bg: rgba(255, 255, 255, 0.08);
799
- --ogrid-selected-row-bg: #1a3a5c;
800
- --ogrid-active-cell-bg: rgba(255, 255, 255, 0.06);
801
- --ogrid-range-bg: rgba(46, 160, 67, 0.15);
802
- --ogrid-accent: #4da6ff;
803
- --ogrid-selection-color: #2ea043;
804
- --ogrid-loading-overlay: rgba(0, 0, 0, 0.7);
805
- }
806
- }
807
- [data-theme="dark"] {
808
- --ogrid-bg: #1e1e1e;
809
- --ogrid-fg: rgba(255, 255, 255, 0.87);
810
- --ogrid-fg-secondary: rgba(255, 255, 255, 0.6);
811
- --ogrid-fg-muted: rgba(255, 255, 255, 0.5);
812
- --ogrid-border: rgba(255, 255, 255, 0.12);
813
- --ogrid-header-bg: rgba(255, 255, 255, 0.06);
814
- --ogrid-hover-bg: rgba(255, 255, 255, 0.08);
815
- --ogrid-selected-row-bg: #1a3a5c;
816
- --ogrid-active-cell-bg: rgba(255, 255, 255, 0.06);
817
- --ogrid-range-bg: rgba(46, 160, 67, 0.15);
818
- --ogrid-accent: #4da6ff;
819
- --ogrid-selection-color: #2ea043;
820
- --ogrid-loading-overlay: rgba(0, 0, 0, 0.7);
821
- }
697
+ styles: [OGRID_THEME_VARS_CSS, `
822
698
  :host { display: block; }
823
699
  .ogrid-root {
824
700
  position: relative;
@@ -846,6 +722,7 @@ DataGridTableComponent = __decorate([
846
722
  border-collapse: collapse;
847
723
  table-layout: fixed;
848
724
  }
725
+ .ogrid-table tbody tr { height: var(--ogrid-row-height, auto); }
849
726
  .ogrid-thead {
850
727
  z-index: 3;
851
728
  background: var(--ogrid-header-bg, #f5f5f5);
@@ -858,7 +735,7 @@ DataGridTableComponent = __decorate([
858
735
  max-width: 48px;
859
736
  text-align: center;
860
737
  background: var(--ogrid-header-bg, #f5f5f5);
861
- border-bottom: 2px solid var(--ogrid-border, #e0e0e0);
738
+ border-bottom: 2px solid var(--ogrid-border, rgba(0, 0, 0, 0.12));
862
739
  position: sticky;
863
740
  top: 0;
864
741
  z-index: 3;
@@ -870,7 +747,7 @@ DataGridTableComponent = __decorate([
870
747
  text-align: center;
871
748
  font-weight: 600;
872
749
  background: var(--ogrid-header-bg, #f5f5f5);
873
- border-bottom: 2px solid var(--ogrid-border, #e0e0e0);
750
+ border-bottom: 2px solid var(--ogrid-border, rgba(0, 0, 0, 0.12));
874
751
  position: sticky;
875
752
  top: 0;
876
753
  z-index: 3;
@@ -885,12 +762,12 @@ DataGridTableComponent = __decorate([
885
762
  text-align: center;
886
763
  font-weight: 600;
887
764
  background: var(--ogrid-header-bg, #f5f5f5);
888
- border-bottom: 2px solid var(--ogrid-border, #e0e0e0);
765
+ border-bottom: 2px solid var(--ogrid-border, rgba(0, 0, 0, 0.12));
889
766
  padding: 6px 10px;
890
767
  }
891
768
  .ogrid-header-cell {
892
769
  background: var(--ogrid-header-bg, #f5f5f5);
893
- border-bottom: 2px solid var(--ogrid-border, #e0e0e0);
770
+ border-bottom: 2px solid var(--ogrid-border, rgba(0, 0, 0, 0.12));
894
771
  padding: 0;
895
772
  position: relative;
896
773
  user-select: none;
@@ -915,7 +792,7 @@ DataGridTableComponent = __decorate([
915
792
  max-width: 48px;
916
793
  padding: 6px 4px;
917
794
  text-align: center;
918
- border-bottom: 1px solid var(--ogrid-border, #f0f0f0);
795
+ border-bottom: 1px solid var(--ogrid-border, rgba(0, 0, 0, 0.12));
919
796
  }
920
797
  .ogrid-row-number-cell {
921
798
  width: 50px;
@@ -927,14 +804,14 @@ DataGridTableComponent = __decorate([
927
804
  font-variant-numeric: tabular-nums;
928
805
  color: var(--ogrid-fg-secondary, rgba(0, 0, 0, 0.6));
929
806
  background: var(--ogrid-header-bg, rgba(0, 0, 0, 0.04));
930
- border-bottom: 1px solid var(--ogrid-border, #f0f0f0);
807
+ border-bottom: 1px solid var(--ogrid-border, rgba(0, 0, 0, 0.12));
931
808
  position: sticky;
932
809
  left: 0;
933
810
  z-index: 3;
934
811
  }
935
812
  .ogrid-data-cell {
936
813
  padding: 0;
937
- border-bottom: 1px solid var(--ogrid-border, #f0f0f0);
814
+ border-bottom: 1px solid var(--ogrid-border, rgba(0, 0, 0, 0.12));
938
815
  position: relative;
939
816
  }
940
817
  .ogrid-cell-content {
@@ -1050,7 +927,7 @@ DataGridTableComponent = __decorate([
1050
927
  /* Context menu */
1051
928
  .ogrid-context-menu {
1052
929
  position: fixed;
1053
- z-index: 10000;
930
+ z-index: 1000;
1054
931
  min-width: 160px;
1055
932
  padding: 4px 0;
1056
933
  background: var(--ogrid-bg, #fff);
@@ -4,119 +4,17 @@ 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 } from '@angular/core';
8
- import { CommonModule } from '@angular/common';
9
- import { BaseInlineCellEditorComponent } from '@alaarab/ogrid-angular';
7
+ import { Component, ChangeDetectionStrategy } from '@angular/core';
8
+ import { BaseInlineCellEditorComponent, INLINE_CELL_EDITOR_TEMPLATE, INLINE_CELL_EDITOR_STYLES } from '@alaarab/ogrid-angular';
10
9
  let InlineCellEditorComponent = class InlineCellEditorComponent extends BaseInlineCellEditorComponent {
11
10
  };
12
11
  InlineCellEditorComponent = __decorate([
13
12
  Component({
14
13
  selector: 'ogrid-primeng-inline-cell-editor',
15
14
  standalone: true,
16
- imports: [CommonModule],
17
- template: `
18
- @switch (editorType) {
19
- @case ('text') {
20
- <input
21
- #inputEl
22
- type="text"
23
- [value]="localValue()"
24
- (input)="localValue.set($any($event.target).value)"
25
- (keydown)="onTextKeyDown($event)"
26
- (blur)="onTextBlur()"
27
- [style]="getInputStyle()"
28
- />
29
- }
30
- @case ('richSelect') {
31
- <div #richSelectWrapper
32
- style="width:100%;height:100%;display:flex;align-items:center;padding:6px 10px;box-sizing:border-box;min-width:0;position:relative">
33
- <input
34
- #richSelectInput
35
- type="text"
36
- [value]="searchText()"
37
- (input)="onRichSelectSearch($any($event.target).value)"
38
- (keydown)="onRichSelectKeyDown($event)"
39
- placeholder="Search..."
40
- style="width:100%;padding:0;border:none;background:transparent;color:inherit;font:inherit;font-size:13px;outline:none;min-width:0"
41
- />
42
- <div #richSelectDropdown role="listbox"
43
- style="position:absolute;top:100%;left:0;right:0;max-height:200px;overflow-y:auto;background:var(--ogrid-bg, #fff);border:1px solid var(--ogrid-border, rgba(0,0,0,0.12));z-index:10;box-shadow:0 4px 16px rgba(0,0,0,0.2)">
44
- @for (opt of filteredOptions(); track opt; let i = $index) {
45
- <div role="option"
46
- [attr.aria-selected]="i === highlightedIndex()"
47
- (click)="commitValue(opt)"
48
- [style]="i === highlightedIndex() ? 'padding:6px 8px;cursor:pointer;color:var(--ogrid-fg, #242424);background:var(--ogrid-bg-hover, #e8f0fe)' : 'padding:6px 8px;cursor:pointer;color:var(--ogrid-fg, #242424)'">
49
- {{ getDisplayText(opt) }}
50
- </div>
51
- }
52
- @if (filteredOptions().length === 0) {
53
- <div style="padding:6px 8px;color:var(--ogrid-muted, #999)">No matches</div>
54
- }
55
- </div>
56
- </div>
57
- }
58
- @case ('select') {
59
- <div #selectWrapper tabindex="0"
60
- style="width:100%;height:100%;display:flex;align-items:center;padding:6px 10px;box-sizing:border-box;min-width:0;position:relative"
61
- (keydown)="onCustomSelectKeyDown($event)">
62
- <div style="display:flex;align-items:center;justify-content:space-between;width:100%;cursor:pointer;font-size:13px;color:inherit">
63
- <span>{{ getDisplayText(value) }}</span>
64
- <span style="margin-left:4px;font-size:10px;opacity:0.5">&#9662;</span>
65
- </div>
66
- <div #selectDropdown role="listbox"
67
- style="position:absolute;top:100%;left:0;right:0;max-height:200px;overflow-y:auto;background:var(--ogrid-bg, #fff);border:1px solid var(--ogrid-border, rgba(0,0,0,0.12));z-index:10;box-shadow:0 4px 16px rgba(0,0,0,0.2)">
68
- @for (opt of selectOptions(); track opt; let i = $index) {
69
- <div role="option"
70
- [attr.aria-selected]="i === highlightedIndex()"
71
- (click)="commitValue(opt)"
72
- [style]="i === highlightedIndex() ? 'padding:6px 8px;cursor:pointer;color:var(--ogrid-fg, #242424);background:var(--ogrid-bg-hover, #e8f0fe)' : 'padding:6px 8px;cursor:pointer;color:var(--ogrid-fg, #242424)'">
73
- {{ getDisplayText(opt) }}
74
- </div>
75
- }
76
- </div>
77
- </div>
78
- }
79
- @case ('checkbox') {
80
- <div style="display:flex;align-items:center;justify-content:center;width:100%;height:100%">
81
- <input
82
- type="checkbox"
83
- [checked]="!!localValue()"
84
- (change)="commitValue($any($event.target).checked)"
85
- (keydown)="onCheckboxKeyDown($event)"
86
- />
87
- </div>
88
- }
89
- @case ('date') {
90
- <input
91
- #inputEl
92
- type="date"
93
- [value]="localValue()"
94
- (change)="commitValue($any($event.target).value)"
95
- (keydown)="onTextKeyDown($event)"
96
- (blur)="onTextBlur()"
97
- [style]="getInputStyle()"
98
- />
99
- }
100
- @default {
101
- <input
102
- #inputEl
103
- type="text"
104
- [value]="localValue()"
105
- (input)="localValue.set($any($event.target).value)"
106
- (keydown)="onTextKeyDown($event)"
107
- (blur)="onTextBlur()"
108
- [style]="getInputStyle()"
109
- />
110
- }
111
- }
112
- `,
113
- styles: [`
114
- :host {
115
- display: block;
116
- width: 100%;
117
- height: 100%;
118
- }
119
- `],
15
+ changeDetection: ChangeDetectionStrategy.OnPush,
16
+ template: INLINE_CELL_EDITOR_TEMPLATE,
17
+ styles: [INLINE_CELL_EDITOR_STYLES],
120
18
  })
121
19
  ], InlineCellEditorComponent);
122
20
  export { InlineCellEditorComponent };
@@ -4,114 +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, ChangeDetectionStrategy, signal, effect, ViewChild, Injector, createComponent, EnvironmentInjector, inject, Input } from '@angular/core';
8
- /**
9
- * PopoverCellEditor component for Angular PrimeNG.
10
- * Renders custom popover editor when anchor element is set.
11
- */
12
- let PopoverCellEditorComponent = class PopoverCellEditorComponent {
13
- constructor() {
14
- this.injector = inject(Injector);
15
- this.envInjector = inject(EnvironmentInjector);
16
- this.showEditor = signal(false);
17
- // Show editor after anchor is rendered
18
- effect(() => {
19
- const anchor = this.anchorRef;
20
- if (anchor) {
21
- setTimeout(() => this.showEditor.set(true), 0);
22
- }
23
- });
24
- // Render custom editor component when container is available
25
- effect(() => {
26
- const container = this.editorContainerRef;
27
- const props = this.editorProps;
28
- const col = this.column;
29
- if (!container || !this.showEditor() || typeof col.cellEditor !== 'function')
30
- return;
31
- // eslint-disable-next-line @typescript-eslint/no-explicit-any
32
- const EditorComponent = col.cellEditor; // ComponentType
33
- const componentRef = createComponent(EditorComponent, {
34
- environmentInjector: this.envInjector,
35
- elementInjector: this.injector,
36
- });
37
- // Pass props to component instance
38
- // eslint-disable-next-line @typescript-eslint/no-explicit-any
39
- Object.assign(componentRef.instance, props);
40
- componentRef.changeDetectorRef.detectChanges();
41
- // Append to DOM
42
- container.nativeElement.appendChild(componentRef.location.nativeElement);
43
- // Cleanup on destroy
44
- return () => componentRef.destroy();
45
- });
46
- }
47
- handleOverlayClick() {
48
- this.onCancel();
49
- }
7
+ import { Component, ChangeDetectionStrategy } from '@angular/core';
8
+ import { BasePopoverCellEditorComponent, POPOVER_CELL_EDITOR_TEMPLATE, POPOVER_CELL_EDITOR_OVERLAY_STYLES } from '@alaarab/ogrid-angular';
9
+ let PopoverCellEditorComponent = class PopoverCellEditorComponent extends BasePopoverCellEditorComponent {
50
10
  };
51
- __decorate([
52
- Input({ required: true })
53
- ], PopoverCellEditorComponent.prototype, "item", void 0);
54
- __decorate([
55
- Input({ required: true })
56
- ], PopoverCellEditorComponent.prototype, "column", void 0);
57
- __decorate([
58
- Input({ required: true })
59
- ], PopoverCellEditorComponent.prototype, "rowIndex", void 0);
60
- __decorate([
61
- Input({ required: true })
62
- ], PopoverCellEditorComponent.prototype, "globalColIndex", void 0);
63
- __decorate([
64
- Input({ required: true })
65
- ], PopoverCellEditorComponent.prototype, "displayValue", void 0);
66
- __decorate([
67
- Input({ required: true })
68
- ], PopoverCellEditorComponent.prototype, "editorProps", void 0);
69
- __decorate([
70
- Input({ required: true })
71
- ], PopoverCellEditorComponent.prototype, "onCancel", void 0);
72
- __decorate([
73
- ViewChild('anchorEl')
74
- ], PopoverCellEditorComponent.prototype, "anchorRef", void 0);
75
- __decorate([
76
- ViewChild('editorContainer')
77
- ], PopoverCellEditorComponent.prototype, "editorContainerRef", void 0);
78
11
  PopoverCellEditorComponent = __decorate([
79
12
  Component({
80
13
  selector: 'ogrid-primeng-popover-cell-editor',
81
14
  standalone: true,
82
15
  changeDetection: ChangeDetectionStrategy.OnPush,
83
- template: `
84
- <div #anchorEl
85
- class="ogrid-popover-anchor"
86
- [attr.data-row-index]="rowIndex"
87
- [attr.data-col-index]="globalColIndex"
88
- >
89
- {{ displayValue }}
90
- </div>
91
- @if (showEditor()) {
92
- <div class="ogrid-popover-editor-overlay" (click)="handleOverlayClick()">
93
- <div class="ogrid-popover-editor-content" #editorContainer></div>
94
- </div>
95
- }
96
- `,
16
+ template: POPOVER_CELL_EDITOR_TEMPLATE,
97
17
  styles: [`
98
- :host { display: contents; }
18
+ ${POPOVER_CELL_EDITOR_OVERLAY_STYLES}
99
19
  .ogrid-popover-anchor {
100
20
  padding: 6px 10px; min-height: 20px; cursor: default; overflow: hidden;
101
21
  text-overflow: ellipsis; white-space: nowrap;
102
22
  outline: 2px solid var(--ogrid-selection, #217346); outline-offset: -2px;
103
23
  }
104
- .ogrid-popover-editor-overlay {
105
- position: fixed; inset: 0; z-index: 1000;
106
- background: rgba(0,0,0,0.3);
107
- display: flex; align-items: center; justify-content: center;
108
- }
109
- .ogrid-popover-editor-content {
110
- background: var(--ogrid-bg, #ffffff); border-radius: 4px; padding: 16px;
111
- box-shadow: 0 4px 12px rgba(0, 0, 0, 0.15);
112
- max-width: 90vw; max-height: 90vh; overflow: auto;
113
- color: var(--ogrid-fg, rgba(0, 0, 0, 0.87));
114
- }
115
24
  `],
116
25
  })
117
26
  ], PopoverCellEditorComponent);
package/dist/esm/index.js CHANGED
@@ -1,4 +1,6 @@
1
- // Re-export everything from angular adapter
1
+ // Re-export all from base package for consumer convenience.
2
+ // Note: This prevents tree-shaking of unused utilities.
3
+ // Consider explicit named exports in a future major version.
2
4
  export * from '@alaarab/ogrid-angular';
3
5
  // PrimeNG UI components
4
6
  export { OGridComponent } from './ogrid/ogrid.component';
@@ -5,7 +5,6 @@ var __decorate = (this && this.__decorate) || function (decorators, target, key,
5
5
  return c > 3 && r && Object.defineProperty(target, key, r), r;
6
6
  };
7
7
  import { Component, inject, ChangeDetectionStrategy, Input, signal, effect } from '@angular/core';
8
- import { CommonModule } from '@angular/common';
9
8
  import { OGridService, OGridLayoutComponent, } from '@alaarab/ogrid-angular';
10
9
  import { DataGridTableComponent } from '../datagrid-table/datagrid-table.component';
11
10
  import { ColumnChooserComponent } from '../column-chooser/column-chooser.component';
@@ -52,7 +51,6 @@ OGridComponent = __decorate([
52
51
  selector: 'ogrid-primeng',
53
52
  standalone: true,
54
53
  imports: [
55
- CommonModule,
56
54
  OGridLayoutComponent,
57
55
  DataGridTableComponent,
58
56
  ColumnChooserComponent,
@@ -4,8 +4,7 @@ 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 } from '@angular/core';
8
- import { CommonModule } from '@angular/common';
7
+ import { Component, ChangeDetectionStrategy } from '@angular/core';
9
8
  import { BasePaginationControlsComponent } from '@alaarab/ogrid-angular';
10
9
  let PaginationControlsComponent = class PaginationControlsComponent extends BasePaginationControlsComponent {
11
10
  };
@@ -13,7 +12,7 @@ PaginationControlsComponent = __decorate([
13
12
  Component({
14
13
  selector: 'ogrid-primeng-pagination-controls',
15
14
  standalone: true,
16
- imports: [CommonModule],
15
+ changeDetection: ChangeDetectionStrategy.OnPush,
17
16
  template: `
18
17
  @if (vm()) {
19
18
  <div style="display:flex;align-items:center;justify-content:space-between;gap:12px;flex-wrap:wrap;font-size:13px;color:var(--ogrid-fg, #242424)">
@@ -97,7 +96,7 @@ PaginationControlsComponent = __decorate([
97
96
  [value]="'' + pageSize"
98
97
  (change)="onPageSizeChange($any($event.target).value)"
99
98
  aria-label="Rows per page"
100
- style="padding:4px 6px;border:1px solid var(--ogrid-border, #e0e0e0);border-radius:4px;background:var(--ogrid-bg, #fff);color:var(--ogrid-fg, #242424)"
99
+ style="padding:4px 6px;border:1px solid var(--ogrid-border, rgba(0, 0, 0, 0.12));border-radius:4px;background:var(--ogrid-bg, #fff);color:var(--ogrid-fg, #242424)"
101
100
  >
102
101
  @for (opt of vm()!.pageSizeOptions; track opt) {
103
102
  <option [value]="opt">{{ opt }}</option>
@@ -54,7 +54,7 @@ export declare class DataGridTableComponent<T = unknown> extends BaseDataGridTab
54
54
  message?: string;
55
55
  render?: unknown;
56
56
  } | undefined;
57
- onCellError: ((error: Error) => void) | undefined;
57
+ onCellError: ((error: Error, info: unknown) => void) | undefined;
58
58
  ariaLabelInput: string | undefined;
59
59
  ariaLabelledByInput: string | undefined;
60
60
  showRowNumbers: boolean;
@@ -82,6 +82,8 @@ export declare class DataGridTableComponent<T = unknown> extends BaseDataGridTab
82
82
  readonly cancelEditHandler: () => void;
83
83
  constructor();
84
84
  ngOnChanges(changes: SimpleChanges): void;
85
+ /** Shallow-compare two props objects by their top-level keys. */
86
+ private shallowEqual;
85
87
  protected getProps(): IOGridDataGridProps<T> | undefined;
86
88
  protected getWrapperRef(): ElementRef<HTMLElement> | undefined;
87
89
  protected getTableContainerRef(): ElementRef<HTMLElement> | undefined;
@@ -90,34 +92,8 @@ export declare class DataGridTableComponent<T = unknown> extends BaseDataGridTab
90
92
  readonly tableMinWidthStyle: import("@angular/core").Signal<"100%" | "max-content">;
91
93
  getColumnWidth(col: IColumnDef<T>): number;
92
94
  trackByRowId(_index: number, item: T): RowId;
93
- getCellValueFn(item: T, col: IColumnDef<T>): unknown;
94
- resolveCellDisplay(col: IColumnDef<T>, item: T): string;
95
- getCellStyleObj(col: IColumnDef<T>, item: T): Record<string, string> | null;
96
- canEditCell(col: IColumnDef<T>, item: T): boolean;
97
- isEditingCell(item: T, col: IColumnDef<T>): boolean;
98
- isEditingCellInline(item: T, col: IColumnDef<T>): boolean;
99
- isEditingCellPopover(item: T, col: IColumnDef<T>): boolean;
100
- buildPopoverEditorPropsForPrimeng(item: T, col: IColumnDef<T>, rowIndex: number, colIdx: number): unknown;
101
- getEditorType(col: IColumnDef<T>, _item: T): 'text' | 'select' | 'checkbox' | 'date' | 'richSelect';
102
- isActiveCell(rowIndex: number, colIdx: number): boolean;
103
- isInSelectionRange(rowIndex: number, colIdx: number): boolean;
104
- isSelectionEndCell(rowIndex: number, colIdx: number): boolean;
105
- getCellBackground(rowIndex: number, colIdx: number): string | null;
106
- onCellDblClickPrimeng(item: T, col: IColumnDef<T>, _rowIndex: number, _colIdx: number): void;
107
- onCellEditorCommit(item: T, col: IColumnDef<T>, rowIndex: number, colIdx: number, newValue: unknown): void;
108
95
  onSelectAllChangePrimeng(checked: boolean): void;
109
96
  onRowClickPrimeng(e: MouseEvent, item: T): void;
110
- getColumnHeaderMenuHandlers(columnId: string): {
111
- onPinLeft: () => void;
112
- onPinRight: () => void;
113
- onUnpin: () => void;
114
- onSortAsc: () => void;
115
- onSortDesc: () => void;
116
- onClearSort: () => void;
117
- onAutosizeThis: () => void;
118
- onAutosizeAll: () => void;
119
- onClose: () => void;
120
- };
121
97
  onRowCheckboxChangePrimeng(item: T, checked: boolean, rowIndex: number, _e: Event): void;
122
98
  onResizeStartPrimeng(e: MouseEvent, col: IColumnDef<T>): void;
123
99
  private buildProps;
@@ -1,21 +1,3 @@
1
- import type { IColumnDef, ICellEditorProps } from '@alaarab/ogrid-angular';
2
- /**
3
- * PopoverCellEditor component for Angular PrimeNG.
4
- * Renders custom popover editor when anchor element is set.
5
- */
6
- export declare class PopoverCellEditorComponent<T> {
7
- item: T;
8
- column: IColumnDef<T>;
9
- rowIndex: number;
10
- globalColIndex: number;
11
- displayValue: unknown;
12
- editorProps: ICellEditorProps<T>;
13
- onCancel: () => void;
14
- private anchorRef?;
15
- private editorContainerRef?;
16
- private readonly injector;
17
- private readonly envInjector;
18
- protected readonly showEditor: import("@angular/core").WritableSignal<boolean>;
19
- constructor();
20
- protected handleOverlayClick(): void;
1
+ import { BasePopoverCellEditorComponent } from '@alaarab/ogrid-angular';
2
+ export declare class PopoverCellEditorComponent<T = unknown> extends BasePopoverCellEditorComponent<T> {
21
3
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@alaarab/ogrid-angular-primeng",
3
- "version": "2.0.19",
3
+ "version": "2.0.22",
4
4
  "description": "OGrid PrimeNG – PrimeNG Table-based data grid with sorting, filtering, pagination, column chooser, and CSV export.",
5
5
  "main": "dist/esm/index.js",
6
6
  "module": "dist/esm/index.js",
@@ -37,7 +37,7 @@
37
37
  "node": ">=18"
38
38
  },
39
39
  "dependencies": {
40
- "@alaarab/ogrid-angular": "2.0.19"
40
+ "@alaarab/ogrid-angular": "2.0.22"
41
41
  },
42
42
  "peerDependencies": {
43
43
  "@angular/core": "^21.0.0",