@alaarab/ogrid-angular-primeng 2.0.6 → 2.0.8

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,23 +4,21 @@ 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, inject, signal, computed, effect, viewChild, ChangeDetectionStrategy, } from '@angular/core';
8
- import { CommonModule } from '@angular/common';
9
- import { DataGridStateService, ColumnReorderService, VirtualScrollService, StatusBarComponent, GridContextMenuComponent, MarchingAntsOverlayComponent, EmptyStateComponent, DEFAULT_MIN_COLUMN_WIDTH, buildHeaderRows, getCellValue, getHeaderFilterConfig, resolveCellDisplayContent, resolveCellStyle, } from '@alaarab/ogrid-angular';
7
+ import { Component, input, signal, computed, effect, viewChild, ChangeDetectionStrategy, } from '@angular/core';
8
+ import { BaseDataGridTableComponent, DataGridStateService, StatusBarComponent, GridContextMenuComponent, MarchingAntsOverlayComponent, EmptyStateComponent, DEFAULT_MIN_COLUMN_WIDTH, getCellValue, resolveCellDisplayContent, resolveCellStyle, } from '@alaarab/ogrid-angular';
10
9
  import { ColumnHeaderFilterComponent } from '../column-header-filter/column-header-filter.component';
11
10
  import { ColumnHeaderMenuComponent } from '../column-header-menu/column-header-menu.component';
12
11
  import { InlineCellEditorComponent } from './inline-cell-editor.component';
13
- let DataGridTableComponent = class DataGridTableComponent {
12
+ import { PopoverCellEditorComponent } from './popover-cell-editor.component';
13
+ let DataGridTableComponent = class DataGridTableComponent extends BaseDataGridTableComponent {
14
14
  constructor() {
15
- this.stateService = inject(DataGridStateService);
16
- this.columnReorderService = new ColumnReorderService();
17
- this.virtualScrollService = new VirtualScrollService();
15
+ super();
18
16
  this.wrapperRef = viewChild('wrapper');
19
- this.tableContainerRef = viewChild('tableContainer');
17
+ this.tableContainerRefEl = viewChild('tableContainer');
20
18
  // Inputs mapped from IOGridDataGridProps
21
- this.items = input.required();
19
+ this.itemsInput = input.required({ alias: 'items' });
22
20
  this.columns = input.required();
23
- this.getRowIdFn = input.required({ alias: 'getRowId' });
21
+ this.getRowIdInput = input.required({ alias: 'getRowId' });
24
22
  this.sortBy = input(undefined);
25
23
  this.sortDirection = input('asc');
26
24
  this.onColumnSort = input.required();
@@ -29,21 +27,21 @@ let DataGridTableComponent = class DataGridTableComponent {
29
27
  this.onColumnOrderChange = input(undefined);
30
28
  this.onColumnResized = input(undefined);
31
29
  this.onColumnPinned = input(undefined);
32
- this.pinnedColumns = input(undefined);
30
+ this.pinnedColumnsInput = input(undefined, { alias: 'pinnedColumns' });
33
31
  this.initialColumnWidths = input(undefined);
34
- this.freezeRows = input(undefined);
35
- this.freezeCols = input(undefined);
32
+ this.freezeRowsInput = input(undefined, { alias: 'freezeRows' });
33
+ this.freezeColsInput = input(undefined, { alias: 'freezeCols' });
36
34
  this.layoutMode = input('fill');
37
35
  this.suppressHorizontalScroll = input(undefined);
38
- this.isLoading = input(false);
39
- this.loadingMessage = input('Loading\u2026');
36
+ this.isLoadingInput = input(false, { alias: 'isLoading' });
37
+ this.loadingMessageInput = input('Loading\u2026', { alias: 'loadingMessage' });
40
38
  this.editable = input(undefined);
41
39
  this.cellSelection = input(undefined);
42
40
  this.onCellValueChanged = input(undefined);
43
- this.onUndo = input(undefined);
44
- this.onRedo = input(undefined);
45
- this.canUndo = input(undefined);
46
- this.canRedo = input(undefined);
41
+ this.onUndoInput = input(undefined, { alias: 'onUndo' });
42
+ this.onRedoInput = input(undefined, { alias: 'onRedo' });
43
+ this.canUndoInput = input(undefined, { alias: 'canUndo' });
44
+ this.canRedoInput = input(undefined, { alias: 'canRedo' });
47
45
  this.rowSelectionMode = input('none', { alias: 'rowSelection' });
48
46
  this.selectedRows = input(undefined);
49
47
  this.onSelectionChange = input(undefined);
@@ -54,13 +52,13 @@ let DataGridTableComponent = class DataGridTableComponent {
54
52
  this.loadingFilterOptions = input({});
55
53
  this.peopleSearch = input(undefined);
56
54
  this.getUserByEmail = input(undefined);
57
- this.emptyState = input(undefined);
55
+ this.emptyStateInput = input(undefined, { alias: 'emptyState' });
58
56
  this.onCellError = input(undefined);
59
- this.ariaLabel = input(undefined, { alias: 'aria-label' });
60
- this.ariaLabelledBy = input(undefined, { alias: 'aria-labelledby' });
57
+ this.ariaLabelInput = input(undefined, { alias: 'aria-label' });
58
+ this.ariaLabelledByInput = input(undefined, { alias: 'aria-labelledby' });
61
59
  this.showRowNumbers = input(false);
62
- this.currentPage = input(1);
63
- this.pageSize = input(25);
60
+ this.currentPageInput = input(1, { alias: 'currentPage' });
61
+ this.pageSizeInput = input(25, { alias: 'pageSize' });
64
62
  this.defaultMinWidth = DEFAULT_MIN_COLUMN_WIDTH;
65
63
  this.statusBarClasses = {
66
64
  statusBar: 'ogrid-status-bar',
@@ -68,27 +66,15 @@ let DataGridTableComponent = class DataGridTableComponent {
68
66
  statusBarLabel: 'ogrid-status-bar-label',
69
67
  statusBarValue: 'ogrid-status-bar-value',
70
68
  };
71
- // Column sizing
72
- this.columnSizingOverrides = signal({});
69
+ // PrimeNG uses flat number overrides for column sizing
70
+ this.primengColumnSizingOverrides = signal({});
73
71
  this.resizeStartX = 0;
74
72
  this.resizeColumnId = '';
75
73
  this.resizeStartWidth = 0;
76
- // Last shift state for row checkbox
77
- this.lastMouseShift = false;
78
- this.columnSizingVersion = signal(0);
79
- this.state = computed(() => this.stateService.getState());
80
- this.tableContainerEl = computed(() => this.tableContainerRef()?.nativeElement ?? null);
81
- this.resolvedAriaLabel = computed(() => this.ariaLabel() ?? (this.ariaLabelledBy() ? undefined : 'Data grid'));
82
- this.rowNumberOffset = computed(() => this.state().layout.hasRowNumbersCol ? (this.currentPage() - 1) * this.pageSize() : 0);
83
- this.headerRows = computed(() => buildHeaderRows(this.columns(), this.visibleColumns()));
84
- this.allowOverflowX = computed(() => {
85
- const s = this.state();
86
- return !this.suppressHorizontalScroll() && s.layout.containerWidth > 0 &&
87
- (s.layout.minTableWidth > s.layout.containerWidth || s.layout.desiredTableWidth > s.layout.containerWidth);
88
- });
74
+ // --- PrimeNG-specific computed signals ---
75
+ this.resolvedAriaLabel = computed(() => this.ariaLabelInput() ?? (this.ariaLabelledByInput() ? undefined : 'Data grid'));
89
76
  this.tableWidthStyle = computed(() => {
90
- const s = this.state();
91
- if (s.viewModels.showEmptyInGrid)
77
+ if (this.showEmptyInGrid())
92
78
  return '100%';
93
79
  if (this.allowOverflowX())
94
80
  return 'fit-content';
@@ -97,8 +83,7 @@ let DataGridTableComponent = class DataGridTableComponent {
97
83
  return '100%';
98
84
  });
99
85
  this.tableMinWidthStyle = computed(() => {
100
- const s = this.state();
101
- if (s.viewModels.showEmptyInGrid)
86
+ if (this.showEmptyInGrid())
102
87
  return '100%';
103
88
  if (this.allowOverflowX())
104
89
  return 'max-content';
@@ -106,62 +91,43 @@ let DataGridTableComponent = class DataGridTableComponent {
106
91
  return 'max-content';
107
92
  return '100%';
108
93
  });
109
- this.selectedCellCount = computed(() => {
110
- const range = this.state().interaction.selectionRange;
111
- if (!range)
112
- return undefined;
113
- return (Math.abs(range.endRow - range.startRow) + 1) *
114
- (Math.abs(range.endCol - range.startCol) + 1);
115
- });
116
- // Wire inputs to DataGridStateService
117
- effect(() => {
118
- const props = this.buildProps();
119
- this.stateService.props.set(props);
120
- });
121
- effect(() => {
122
- const el = this.wrapperRef()?.nativeElement ?? null;
123
- this.stateService.wrapperEl.set(el);
124
- this.columnReorderService.wrapperEl.set(el);
125
- });
126
- // Wire column reorder service inputs
127
- effect(() => {
128
- const cols = this.state().layout.visibleCols;
129
- this.columnReorderService.columns.set(cols);
130
- this.columnReorderService.columnOrder.set(this.columnOrder());
131
- this.columnReorderService.onColumnOrderChange.set(this.onColumnOrderChange());
132
- this.columnReorderService.enabled.set(!!this.onColumnOrderChange());
133
- });
134
- // Wire virtual scroll service inputs
135
- effect(() => {
136
- this.virtualScrollService.totalRows.set(this.items().length);
137
- });
94
+ this.initBase();
138
95
  // Initialize column sizing from initial widths
139
96
  effect(() => {
140
97
  const iw = this.initialColumnWidths();
141
98
  if (iw) {
142
- this.columnSizingOverrides.set({ ...iw });
99
+ this.primengColumnSizingOverrides.set({ ...iw });
143
100
  }
144
101
  });
145
102
  }
146
- trackByRowId(_index, item) {
147
- return this.getRowIdFn()(item);
103
+ // --- Abstract method implementations ---
104
+ getProps() {
105
+ return this.buildProps();
148
106
  }
107
+ getWrapperRef() {
108
+ return this.wrapperRef();
109
+ }
110
+ getTableContainerRef() {
111
+ return this.tableContainerRefEl();
112
+ }
113
+ // --- Column width override (PrimeNG uses flat number instead of { widthPx }) ---
149
114
  getColumnWidth(col) {
150
- const override = this.columnSizingOverrides()[col.columnId];
115
+ const override = this.primengColumnSizingOverrides()[col.columnId];
151
116
  if (override)
152
117
  return override;
153
- return col.idealWidth ?? col.defaultWidth ?? undefined;
118
+ return col.idealWidth ?? col.defaultWidth ?? col.minWidth ?? DEFAULT_MIN_COLUMN_WIDTH;
154
119
  }
155
- getFilterConfig(col) {
156
- const s = this.state();
157
- return getHeaderFilterConfig(col, s.viewModels.headerFilterInput);
120
+ // --- PrimeNG-specific helpers ---
121
+ trackByRowId(_index, item) {
122
+ return this.getRowIdInput()(item);
158
123
  }
159
124
  getCellValueFn(item, col) {
160
125
  return getCellValue(item, col);
161
126
  }
162
127
  resolveCellDisplay(col, item) {
163
128
  const value = getCellValue(item, col);
164
- return resolveCellDisplayContent(col, item, value);
129
+ const result = resolveCellDisplayContent(col, item, value);
130
+ return result != null ? String(result) : '';
165
131
  }
166
132
  getCellStyleObj(col, item) {
167
133
  return resolveCellStyle(col, item) ?? null;
@@ -171,10 +137,30 @@ let DataGridTableComponent = class DataGridTableComponent {
171
137
  return this.editable() !== false && !!colEditable && this.onCellValueChanged() != null && typeof col.cellEditor !== 'function';
172
138
  }
173
139
  isEditingCell(item, col) {
174
- const editing = this.state().editing.editingCell;
140
+ const editing = this.editingCell();
175
141
  if (!editing)
176
142
  return false;
177
- return editing.rowId === this.getRowIdFn()(item) && editing.columnId === col.columnId;
143
+ return editing.rowId === this.getRowIdInput()(item) && editing.columnId === col.columnId;
144
+ }
145
+ isEditingCellInline(item, col) {
146
+ return this.isEditingCell(item, col) && typeof col.cellEditor !== 'function';
147
+ }
148
+ isEditingCellPopover(item, col) {
149
+ return this.isEditingCell(item, col) && typeof col.cellEditor === 'function';
150
+ }
151
+ buildPopoverEditorPropsForPrimeng(item, col, rowIndex, colIdx) {
152
+ const oldValue = getCellValue(item, col);
153
+ const pendingValue = this.pendingEditorValue();
154
+ const displayValue = pendingValue !== undefined ? pendingValue : oldValue;
155
+ return {
156
+ value: displayValue,
157
+ onValueChange: (value) => this.setPendingEditorValue(value),
158
+ item,
159
+ column: col,
160
+ rowIndex,
161
+ onCommit: (newValue) => this.onCellEditorCommit(item, col, rowIndex, colIdx, newValue),
162
+ onCancel: () => this.cancelEdit(),
163
+ };
178
164
  }
179
165
  getEditorType(col, _item) {
180
166
  if (col.cellEditor === 'text' || col.cellEditor === 'select' || col.cellEditor === 'checkbox' || col.cellEditor === 'date' || col.cellEditor === 'richSelect') {
@@ -187,13 +173,13 @@ let DataGridTableComponent = class DataGridTableComponent {
187
173
  return 'text';
188
174
  }
189
175
  isActiveCell(rowIndex, colIdx) {
190
- const ac = this.state().interaction.activeCell;
176
+ const ac = this.activeCell();
191
177
  if (!ac)
192
178
  return false;
193
- return ac.rowIndex === rowIndex && ac.columnIndex === colIdx + this.state().layout.colOffset;
179
+ return ac.rowIndex === rowIndex && ac.columnIndex === colIdx + this.colOffset();
194
180
  }
195
181
  isInSelectionRange(rowIndex, colIdx) {
196
- const range = this.state().interaction.selectionRange;
182
+ const range = this.selectionRange();
197
183
  if (!range)
198
184
  return false;
199
185
  const minR = Math.min(range.startRow, range.endRow);
@@ -203,9 +189,8 @@ let DataGridTableComponent = class DataGridTableComponent {
203
189
  return rowIndex >= minR && rowIndex <= maxR && colIdx >= minC && colIdx <= maxC;
204
190
  }
205
191
  isSelectionEndCell(rowIndex, colIdx) {
206
- const s = this.state();
207
- const range = s.interaction.selectionRange;
208
- if (!range || s.interaction.isDragging || s.interaction.copyRange || s.interaction.cutRange)
192
+ const range = this.selectionRange();
193
+ if (!range || this.isDragging() || this.copyRange() || this.cutRange())
209
194
  return false;
210
195
  return rowIndex === range.endRow && colIdx === range.endCol;
211
196
  }
@@ -214,71 +199,50 @@ let DataGridTableComponent = class DataGridTableComponent {
214
199
  return 'var(--ogrid-range-bg, rgba(33, 115, 70, 0.08))';
215
200
  return null;
216
201
  }
217
- // --- Event handlers ---
218
- onMouseDown(e) {
219
- this.lastMouseShift = e.shiftKey;
220
- }
221
- onGridKeyDown(e) {
222
- this.state().interaction.handleGridKeyDown(e);
223
- }
224
- onCellMouseDown(e, rowIndex, globalColIndex) {
225
- this.state().interaction.handleCellMouseDown(e, rowIndex, globalColIndex);
226
- }
227
- onCellDblClick(item, col, rowIndex, colIdx) {
202
+ // --- PrimeNG-specific event handlers ---
203
+ onCellDblClickPrimeng(item, col, _rowIndex, _colIdx) {
228
204
  if (this.canEditCell(col, item)) {
229
- this.stateService.setEditingCell({ rowId: this.getRowIdFn()(item), columnId: col.columnId });
205
+ this.stateService.setEditingCell({ rowId: this.getRowIdInput()(item), columnId: col.columnId });
230
206
  }
231
207
  }
232
- onCellContextMenu(e) {
233
- this.state().contextMenu.handleCellContextMenu(e);
234
- }
235
208
  onCellEditorCommit(item, col, rowIndex, colIdx, newValue) {
236
209
  const oldValue = getCellValue(item, col);
237
- this.stateService.commitCellEdit(item, col.columnId, oldValue, newValue, rowIndex, colIdx + this.state().layout.colOffset);
210
+ this.stateService.commitCellEdit(item, col.columnId, oldValue, newValue, rowIndex, colIdx + this.colOffset());
238
211
  }
239
- onFillHandleMouseDown(e) {
240
- this.state().interaction.handleFillHandleMouseDown(e);
241
- }
242
- onSelectAllChange(checked) {
212
+ onSelectAllChangePrimeng(checked) {
243
213
  this.state().rowSelection.handleSelectAll(checked);
244
214
  }
245
- onRowClick(e, item) {
215
+ onRowClickPrimeng(e, item) {
246
216
  if (this.rowSelectionMode() !== 'single')
247
217
  return;
248
- const rowId = this.getRowIdFn()(item);
249
- const ids = this.state().rowSelection.selectedRowIds;
218
+ const rowId = this.getRowIdInput()(item);
219
+ const ids = this.selectedRowIds();
250
220
  this.state().rowSelection.updateSelection(ids.has(rowId) ? new Set() : new Set([rowId]));
251
221
  }
252
- onRowCheckboxChange(item, checked, rowIndex, e) {
253
- const rowId = this.getRowIdFn()(item);
222
+ onRowCheckboxChangePrimeng(item, checked, rowIndex, _e) {
223
+ const rowId = this.getRowIdInput()(item);
254
224
  this.state().rowSelection.handleRowCheckboxChange(rowId, checked, rowIndex, this.lastMouseShift);
255
225
  }
256
- handlePaste() {
257
- void this.state().interaction.handlePaste();
258
- }
259
- onHeaderMouseDown(columnId, event) {
260
- this.columnReorderService.handleHeaderMouseDown(columnId, event);
261
- }
262
- onResizeStart(e, col) {
226
+ onResizeStartPrimeng(e, col) {
263
227
  e.preventDefault();
264
228
  this.resizeStartX = e.clientX;
265
229
  this.resizeColumnId = col.columnId;
266
- this.resizeStartWidth = this.getColumnWidth(col) ?? col.minWidth ?? DEFAULT_MIN_COLUMN_WIDTH;
230
+ this.resizeStartWidth = this.getColumnWidth(col);
267
231
  const onMove = (me) => {
268
232
  const delta = me.clientX - this.resizeStartX;
269
233
  const minW = col.minWidth ?? DEFAULT_MIN_COLUMN_WIDTH;
270
234
  const newWidth = Math.max(minW, this.resizeStartWidth + delta);
271
- this.columnSizingOverrides.update((prev) => ({ ...prev, [this.resizeColumnId]: newWidth }));
235
+ this.primengColumnSizingOverrides.update((prev) => ({ ...prev, [this.resizeColumnId]: newWidth }));
272
236
  this.columnSizingVersion.update(v => v + 1);
273
237
  };
274
238
  const onUp = () => {
275
239
  window.removeEventListener('mousemove', onMove, true);
276
240
  window.removeEventListener('mouseup', onUp, true);
277
- const finalWidth = this.columnSizingOverrides()[this.resizeColumnId];
241
+ const finalWidth = this.primengColumnSizingOverrides()[this.resizeColumnId];
278
242
  if (finalWidth) {
279
243
  this.onColumnResized()?.(this.resizeColumnId, finalWidth);
280
244
  const overrides = {};
281
- for (const [id, w] of Object.entries(this.columnSizingOverrides())) {
245
+ for (const [id, w] of Object.entries(this.primengColumnSizingOverrides())) {
282
246
  overrides[id] = { widthPx: w };
283
247
  }
284
248
  this.state().layout.setColumnSizingOverrides(overrides);
@@ -287,29 +251,12 @@ let DataGridTableComponent = class DataGridTableComponent {
287
251
  window.addEventListener('mousemove', onMove, true);
288
252
  window.addEventListener('mouseup', onUp, true);
289
253
  }
290
- // --- Column pinning methods ---
291
- onPinColumn(columnId, side) {
292
- this.onColumnPinned()?.(columnId, side);
293
- }
294
- onUnpinColumn(columnId) {
295
- this.onColumnPinned()?.(columnId, null);
296
- }
297
- isPinned(columnId) {
298
- return this.pinnedColumns()?.[columnId];
299
- }
300
- getPinState(columnId) {
301
- const pinned = this.isPinned(columnId);
302
- return {
303
- canPinLeft: pinned !== 'left',
304
- canPinRight: pinned !== 'right',
305
- canUnpin: !!pinned,
306
- };
307
- }
254
+ // --- Build props ---
308
255
  buildProps() {
309
256
  return {
310
- items: this.items(),
257
+ items: this.itemsInput(),
311
258
  columns: this.columns(),
312
- getRowId: this.getRowIdFn(),
259
+ getRowId: this.getRowIdInput(),
313
260
  sortBy: this.sortBy(),
314
261
  sortDirection: this.sortDirection(),
315
262
  onColumnSort: this.onColumnSort(),
@@ -318,27 +265,27 @@ let DataGridTableComponent = class DataGridTableComponent {
318
265
  onColumnOrderChange: this.onColumnOrderChange(),
319
266
  onColumnResized: this.onColumnResized(),
320
267
  onColumnPinned: this.onColumnPinned(),
321
- pinnedColumns: this.pinnedColumns(),
268
+ pinnedColumns: this.pinnedColumnsInput(),
322
269
  initialColumnWidths: this.initialColumnWidths(),
323
- freezeRows: this.freezeRows(),
324
- freezeCols: this.freezeCols(),
270
+ freezeRows: this.freezeRowsInput(),
271
+ freezeCols: this.freezeColsInput(),
325
272
  layoutMode: this.layoutMode(),
326
273
  suppressHorizontalScroll: this.suppressHorizontalScroll(),
327
- isLoading: this.isLoading(),
328
- loadingMessage: this.loadingMessage(),
274
+ isLoading: this.isLoadingInput(),
275
+ loadingMessage: this.loadingMessageInput(),
329
276
  editable: this.editable(),
330
277
  cellSelection: this.cellSelection(),
331
278
  onCellValueChanged: this.onCellValueChanged(),
332
- onUndo: this.onUndo(),
333
- onRedo: this.onRedo(),
334
- canUndo: this.canUndo(),
335
- canRedo: this.canRedo(),
279
+ onUndo: this.onUndoInput(),
280
+ onRedo: this.onRedoInput(),
281
+ canUndo: this.canUndoInput(),
282
+ canRedo: this.canRedoInput(),
336
283
  rowSelection: this.rowSelectionMode(),
337
284
  selectedRows: this.selectedRows(),
338
285
  onSelectionChange: this.onSelectionChange(),
339
286
  showRowNumbers: this.showRowNumbers(),
340
- currentPage: this.currentPage(),
341
- pageSize: this.pageSize(),
287
+ currentPage: this.currentPageInput(),
288
+ pageSize: this.pageSizeInput(),
342
289
  statusBar: this.statusBar(),
343
290
  filters: this.filters(),
344
291
  onFilterChange: this.onFilterChange(),
@@ -346,10 +293,10 @@ let DataGridTableComponent = class DataGridTableComponent {
346
293
  loadingFilterOptions: this.loadingFilterOptions(),
347
294
  peopleSearch: this.peopleSearch(),
348
295
  getUserByEmail: this.getUserByEmail(),
349
- emptyState: this.emptyState(),
296
+ emptyState: this.emptyStateInput(),
350
297
  onCellError: this.onCellError(),
351
- 'aria-label': this.ariaLabel(),
352
- 'aria-labelledby': this.ariaLabelledBy(),
298
+ 'aria-label': this.ariaLabelInput(),
299
+ 'aria-labelledby': this.ariaLabelledByInput(),
353
300
  };
354
301
  }
355
302
  };
@@ -358,7 +305,6 @@ DataGridTableComponent = __decorate([
358
305
  selector: 'ogrid-primeng-datagrid-table',
359
306
  standalone: true,
360
307
  imports: [
361
- CommonModule,
362
308
  StatusBarComponent,
363
309
  GridContextMenuComponent,
364
310
  MarchingAntsOverlayComponent,
@@ -366,6 +312,7 @@ DataGridTableComponent = __decorate([
366
312
  ColumnHeaderFilterComponent,
367
313
  ColumnHeaderMenuComponent,
368
314
  InlineCellEditorComponent,
315
+ PopoverCellEditorComponent,
369
316
  ],
370
317
  changeDetection: ChangeDetectionStrategy.OnPush,
371
318
  providers: [DataGridStateService],
@@ -377,7 +324,7 @@ DataGridTableComponent = __decorate([
377
324
  role="region"
378
325
  [attr.aria-label]="resolvedAriaLabel()"
379
326
  [attr.aria-labelledby]="ariaLabelledBy()"
380
- [attr.data-empty]="state().viewModels.showEmptyInGrid ? 'true' : null"
327
+ [attr.data-empty]="showEmptyInGrid() ? 'true' : null"
381
328
  [attr.data-column-count]="state().layout.totalColCount"
382
329
  [attr.data-freeze-rows]="freezeRows() != null && freezeRows()! >= 1 ? freezeRows() : null"
383
330
  [attr.data-freeze-cols]="freezeCols() != null && freezeCols()! >= 1 ? freezeCols() : null"
@@ -385,7 +332,8 @@ DataGridTableComponent = __decorate([
385
332
  [attr.data-has-selection]="rowSelectionMode() !== 'none' ? 'true' : null"
386
333
  (contextmenu)="$event.preventDefault()"
387
334
  (keydown)="onGridKeyDown($event)"
388
- (mousedown)="onMouseDown($event)"
335
+ (mousedown)="onWrapperMouseDown($event)"
336
+ (scroll)="onWrapperScroll($event)"
389
337
  style="flex:1;min-height:0;overflow:auto;outline:none;position:relative;font-size:13px;color:var(--ogrid-fg, #242424)"
390
338
  [style.--data-table-column-count]="state().layout.totalColCount"
391
339
  [style.--data-table-width]="tableWidthStyle()"
@@ -400,7 +348,7 @@ DataGridTableComponent = __decorate([
400
348
  <thead style="position:sticky;top:0;z-index:3;background:var(--ogrid-header-bg, #f5f5f5)">
401
349
  @for (row of headerRows(); track $index; let rowIdx = $index) {
402
350
  <tr>
403
- @if (rowIdx === headerRows().length - 1 && state().layout.hasCheckboxCol) {
351
+ @if (rowIdx === headerRows().length - 1 && hasCheckboxCol()) {
404
352
  <th
405
353
  scope="col"
406
354
  rowSpan="1"
@@ -408,17 +356,17 @@ DataGridTableComponent = __decorate([
408
356
  >
409
357
  <input
410
358
  type="checkbox"
411
- [checked]="state().rowSelection.allSelected"
412
- [indeterminate]="state().rowSelection.someSelected && !state().rowSelection.allSelected"
413
- (change)="onSelectAllChange($any($event.target).checked)"
359
+ [checked]="allSelected()"
360
+ [indeterminate]="someSelected() && !allSelected()"
361
+ (change)="onSelectAllChangePrimeng($any($event.target).checked)"
414
362
  aria-label="Select all rows"
415
363
  />
416
364
  </th>
417
365
  }
418
- @if (rowIdx === 0 && rowIdx < headerRows().length - 1 && state().layout.hasCheckboxCol) {
366
+ @if (rowIdx === 0 && rowIdx < headerRows().length - 1 && hasCheckboxCol()) {
419
367
  <th [attr.rowSpan]="headerRows().length - 1"></th>
420
368
  }
421
- @if (rowIdx === headerRows().length - 1 && state().layout.hasRowNumbersCol) {
369
+ @if (rowIdx === headerRows().length - 1 && hasRowNumbersCol()) {
422
370
  <th
423
371
  scope="col"
424
372
  rowSpan="1"
@@ -427,7 +375,7 @@ DataGridTableComponent = __decorate([
427
375
  #
428
376
  </th>
429
377
  }
430
- @if (rowIdx === 0 && rowIdx < headerRows().length - 1 && state().layout.hasRowNumbersCol) {
378
+ @if (rowIdx === 0 && rowIdx < headerRows().length - 1 && hasRowNumbersCol()) {
431
379
  <th [attr.rowSpan]="headerRows().length - 1" style="width:50px;min-width:50px"></th>
432
380
  }
433
381
  @for (cell of row; track $index; let cellIdx = $index) {
@@ -440,55 +388,56 @@ DataGridTableComponent = __decorate([
440
388
  {{ cell.label }}
441
389
  </th>
442
390
  } @else {
443
- @let pinned = isPinned(cell.columnDef!.columnId);
391
+ @let col = asColumnDef(cell.columnDef);
392
+ @let pinned = isPinned(col.columnId);
444
393
  <th
445
394
  scope="col"
446
- [attr.data-column-id]="cell.columnDef!.columnId"
395
+ [attr.data-column-id]="col.columnId"
447
396
  [attr.rowSpan]="headerRows().length > 1 && rowIdx < headerRows().length - 1 ? headerRows().length - rowIdx : null"
448
397
  [class.ogrid-th-pinned-left]="pinned === 'left'"
449
398
  [class.ogrid-th-pinned-right]="pinned === 'right'"
450
399
  style="padding:6px 8px;text-align:left;font-weight:600;border-bottom:1px solid var(--ogrid-border, #e0e0e0);position:relative"
451
- [style.min-width.px]="cell.columnDef!.minWidth ?? defaultMinWidth"
452
- [style.width.px]="getColumnWidth(cell.columnDef!)"
453
- [style.max-width.px]="getColumnWidth(cell.columnDef!)"
400
+ [style.min-width.px]="col.minWidth ?? defaultMinWidth"
401
+ [style.width.px]="getColumnWidth(col)"
402
+ [style.max-width.px]="getColumnWidth(col)"
454
403
  [style.cursor]="columnReorderService.isDragging() ? 'grabbing' : 'grab'"
455
- (mousedown)="onHeaderMouseDown(cell.columnDef!.columnId, $event)"
404
+ (mousedown)="onHeaderMouseDown(col.columnId, $event)"
456
405
  >
457
406
  <div style="display:flex;align-items:center;gap:4px;">
458
407
  <ogrid-primeng-column-header-filter
459
- [columnKey]="cell.columnDef!.columnId"
460
- [columnName]="cell.columnDef!.name"
461
- [filterType]="getFilterConfig(cell.columnDef!).filterType"
462
- [isSorted]="getFilterConfig(cell.columnDef!).isSorted ?? false"
463
- [isSortedDescending]="getFilterConfig(cell.columnDef!).isSortedDescending ?? false"
464
- [onSort]="getFilterConfig(cell.columnDef!).onSort"
465
- [selectedValues]="getFilterConfig(cell.columnDef!).selectedValues"
466
- [onFilterChange]="getFilterConfig(cell.columnDef!).onFilterChange"
467
- [options]="getFilterConfig(cell.columnDef!).options ?? []"
468
- [isLoadingOptions]="getFilterConfig(cell.columnDef!).isLoadingOptions ?? false"
469
- [textValue]="getFilterConfig(cell.columnDef!).textValue ?? ''"
470
- [onTextChange]="getFilterConfig(cell.columnDef!).onTextChange"
471
- [selectedUser]="getFilterConfig(cell.columnDef!).selectedUser"
472
- [onUserChange]="getFilterConfig(cell.columnDef!).onUserChange"
473
- [peopleSearch]="getFilterConfig(cell.columnDef!).peopleSearch"
474
- [dateValue]="getFilterConfig(cell.columnDef!).dateValue"
475
- [onDateChange]="getFilterConfig(cell.columnDef!).onDateChange"
408
+ [columnKey]="col.columnId"
409
+ [columnName]="col.name"
410
+ [filterType]="getFilterConfig(col).filterType"
411
+ [isSorted]="getFilterConfig(col).isSorted ?? false"
412
+ [isSortedDescending]="getFilterConfig(col).isSortedDescending ?? false"
413
+ [onSort]="getFilterConfig(col).onSort"
414
+ [selectedValues]="getFilterConfig(col).selectedValues"
415
+ [onFilterChange]="getFilterConfig(col).onFilterChange"
416
+ [options]="getFilterConfig(col).options ?? []"
417
+ [isLoadingOptions]="getFilterConfig(col).isLoadingOptions ?? false"
418
+ [textValue]="getFilterConfig(col).textValue ?? ''"
419
+ [onTextChange]="getFilterConfig(col).onTextChange"
420
+ [selectedUser]="getFilterConfig(col).selectedUser"
421
+ [onUserChange]="getFilterConfig(col).onUserChange"
422
+ [peopleSearch]="getFilterConfig(col).peopleSearch"
423
+ [dateValue]="getFilterConfig(col).dateValue"
424
+ [onDateChange]="getFilterConfig(col).onDateChange"
476
425
  ></ogrid-primeng-column-header-filter>
477
- @let pinState = getPinState(cell.columnDef!.columnId);
426
+ @let colPinState = getPinState(col.columnId);
478
427
  <column-header-menu
479
- [columnId]="cell.columnDef!.columnId"
480
- [onPinLeft]="() => onPinColumn(cell.columnDef!.columnId, 'left')"
481
- [onPinRight]="() => onPinColumn(cell.columnDef!.columnId, 'right')"
482
- [onUnpin]="() => onUnpinColumn(cell.columnDef!.columnId)"
483
- [canPinLeft]="pinState.canPinLeft"
484
- [canPinRight]="pinState.canPinRight"
485
- [canUnpin]="pinState.canUnpin"
428
+ [columnId]="col.columnId"
429
+ [onPinLeft]="() => onPinColumn(col.columnId, 'left')"
430
+ [onPinRight]="() => onPinColumn(col.columnId, 'right')"
431
+ [onUnpin]="() => onUnpinColumn(col.columnId)"
432
+ [canPinLeft]="colPinState.canPinLeft"
433
+ [canPinRight]="colPinState.canPinRight"
434
+ [canUnpin]="colPinState.canUnpin"
486
435
  />
487
436
  </div>
488
437
  <div
489
438
  style="position:absolute;top:0;right:0;bottom:0;width:4px;cursor:col-resize"
490
- (mousedown)="onResizeStart($event, cell.columnDef!)"
491
- [attr.aria-label]="'Resize ' + cell.columnDef!.name"
439
+ (mousedown)="onResizeStartPrimeng($event, col)"
440
+ [attr.aria-label]="'Resize ' + col.name"
492
441
  ></div>
493
442
  </th>
494
443
  }
@@ -497,15 +446,21 @@ DataGridTableComponent = __decorate([
497
446
  }
498
447
  </thead>
499
448
 
500
- @if (!state().viewModels.showEmptyInGrid) {
449
+ @if (!showEmptyInGrid()) {
501
450
  <tbody>
502
- @for (item of items(); track trackByRowId($index, item); let rowIndex = $index) {
451
+ @if (vsEnabled() && vsTopSpacerHeight() > 0) {
452
+ <tr [style.height.px]="vsTopSpacerHeight()"></tr>
453
+ }
454
+ @for (item of vsVisibleItems(); track trackByRowId($index, item); let localIdx = $index) {
455
+ @let rowIndex = vsStartIndex() + localIdx;
456
+ @let rowId = getRowIdInput()(item);
457
+ @let isSelected = selectedRowIds().has(rowId);
503
458
  <tr
504
- [attr.data-row-id]="getRowIdFn()(item)"
505
- [style.background]="state().rowSelection.selectedRowIds.has(getRowIdFn()(item)) ? 'var(--ogrid-selected-bg, #e8f0fe)' : null"
506
- (click)="onRowClick($event, item)"
459
+ [attr.data-row-id]="rowId"
460
+ [style.background]="isSelected ? 'var(--ogrid-selected-bg, #e8f0fe)' : null"
461
+ (click)="onRowClickPrimeng($event, item)"
507
462
  >
508
- @if (state().layout.hasCheckboxCol) {
463
+ @if (hasCheckboxCol()) {
509
464
  <td
510
465
  style="width:48px;min-width:48px;max-width:48px;padding:6px 4px;text-align:center;border-bottom:1px solid var(--ogrid-border, #f0f0f0)"
511
466
  [attr.data-row-index]="rowIndex"
@@ -514,20 +469,20 @@ DataGridTableComponent = __decorate([
514
469
  >
515
470
  <input
516
471
  type="checkbox"
517
- [checked]="state().rowSelection.selectedRowIds.has(getRowIdFn()(item))"
518
- (change)="onRowCheckboxChange(item, $any($event.target).checked, rowIndex, $event)"
472
+ [checked]="isSelected"
473
+ (change)="onRowCheckboxChangePrimeng(item, $any($event.target).checked, rowIndex, $event)"
519
474
  [attr.aria-label]="'Select row ' + (rowIndex + 1)"
520
475
  />
521
476
  </td>
522
477
  }
523
- @if (state().layout.hasRowNumbersCol) {
478
+ @if (hasRowNumbersCol()) {
524
479
  <td
525
480
  style="width:50px;min-width:50px;max-width:50px;padding:6px;text-align:center;font-weight:600;font-variant-numeric:tabular-nums;color:var(--ogrid-text-secondary,#666);background:var(--ogrid-bg-subtle,#fafafa);border-bottom:1px solid var(--ogrid-border,#f0f0f0);position:sticky;left:0;z-index:3"
526
481
  >
527
482
  {{ rowNumberOffset() + rowIndex + 1 }}
528
483
  </td>
529
484
  }
530
- @for (col of state().layout.visibleCols; track col.columnId; let colIdx = $index) {
485
+ @for (col of visibleCols(); track col.columnId; let colIdx = $index) {
531
486
  @let pinned = isPinned(col.columnId);
532
487
  <td
533
488
  [class.ogrid-td-pinned-left]="pinned === 'left'"
@@ -538,7 +493,7 @@ DataGridTableComponent = __decorate([
538
493
  [style.max-width.px]="getColumnWidth(col)"
539
494
  [style.text-align]="col.type === 'numeric' ? 'right' : col.type === 'boolean' ? 'center' : null"
540
495
  >
541
- @if (isEditingCell(item, col)) {
496
+ @if (isEditingCellInline(item, col)) {
542
497
  <ogrid-primeng-inline-cell-editor
543
498
  [value]="getCellValueFn(item, col)"
544
499
  [item]="item"
@@ -546,14 +501,25 @@ DataGridTableComponent = __decorate([
546
501
  [rowIndex]="rowIndex"
547
502
  [editorType]="getEditorType(col, item)"
548
503
  (commit)="onCellEditorCommit(item, col, rowIndex, colIdx, $event)"
549
- (cancel)="state().editing.setEditingCell(null)"
504
+ (cancel)="cancelEdit()"
550
505
  ></ogrid-primeng-inline-cell-editor>
506
+ } @else if (isEditingCellPopover(item, col)) {
507
+ @let editorProps = buildPopoverEditorPropsForPrimeng(item, col, rowIndex, colIdx);
508
+ <ogrid-primeng-popover-cell-editor
509
+ [item]="item"
510
+ [column]="col"
511
+ [rowIndex]="rowIndex"
512
+ [globalColIndex]="colIdx + colOffset()"
513
+ [displayValue]="getCellValueFn(item, col)"
514
+ [editorProps]="editorProps"
515
+ [onCancel]="() => cancelEdit()"
516
+ ></ogrid-primeng-popover-cell-editor>
551
517
  } @else {
552
518
  <div
553
519
  [attr.data-row-index]="rowIndex"
554
- [attr.data-col-index]="colIdx + state().layout.colOffset"
555
- (mousedown)="onCellMouseDown($event, rowIndex, colIdx + state().layout.colOffset)"
556
- (dblclick)="onCellDblClick(item, col, rowIndex, colIdx)"
520
+ [attr.data-col-index]="colIdx + colOffset()"
521
+ (mousedown)="onCellMouseDown($event, rowIndex, colIdx + colOffset())"
522
+ (dblclick)="onCellDblClickPrimeng(item, col, rowIndex, colIdx)"
557
523
  (contextmenu)="onCellContextMenu($event)"
558
524
  style="padding:6px 10px;min-height:20px;cursor:default;overflow:hidden;text-overflow:ellipsis;white-space:nowrap"
559
525
  [style.cursor]="canEditCell(col, item) ? 'cell' : 'default'"
@@ -575,6 +541,9 @@ DataGridTableComponent = __decorate([
575
541
  }
576
542
  </tr>
577
543
  }
544
+ @if (vsEnabled() && vsBottomSpacerHeight() > 0) {
545
+ <tr [style.height.px]="vsBottomSpacerHeight()"></tr>
546
+ }
578
547
  </tbody>
579
548
  }
580
549
  </table>
@@ -588,7 +557,7 @@ DataGridTableComponent = __decorate([
588
557
  [columnSizingVersion]="columnSizingVersion()"
589
558
  ></ogrid-marching-ants-overlay>
590
559
 
591
- @if (state().viewModels.showEmptyInGrid && emptyState()) {
560
+ @if (showEmptyInGrid() && emptyState()) {
592
561
  <div style="display:flex;align-items:center;justify-content:center;padding:48px 24px;text-align:center;color:var(--ogrid-muted, #999)">
593
562
  <div>
594
563
  <div style="font-weight:600;margin-bottom:8px">No results found</div>
@@ -610,31 +579,31 @@ DataGridTableComponent = __decorate([
610
579
  <div class="ogrid-drop-indicator" [style.left.px]="columnReorderService.dropIndicatorX()"></div>
611
580
  }
612
581
 
613
- @if (state().contextMenu.menuPosition) {
582
+ @if (menuPosition()) {
614
583
  <ogrid-context-menu
615
- [x]="state().contextMenu.menuPosition!.x"
616
- [y]="state().contextMenu.menuPosition!.y"
617
- [hasSelection]="state().interaction.hasCellSelection"
618
- [canUndoProp]="state().interaction.canUndo"
619
- [canRedoProp]="state().interaction.canRedo"
620
- (copy)="state().interaction.handleCopy()"
621
- (cut)="state().interaction.handleCut()"
584
+ [x]="menuPosition()!.x"
585
+ [y]="menuPosition()!.y"
586
+ [hasSelection]="hasCellSelection()"
587
+ [canUndoProp]="canUndo()"
588
+ [canRedoProp]="canRedo()"
589
+ (copy)="handleCopy()"
590
+ (cut)="handleCut()"
622
591
  (paste)="handlePaste()"
623
- (selectAll)="state().interaction.handleSelectAllCells()"
624
- (undoAction)="state().interaction.onUndo?.()"
625
- (redoAction)="state().interaction.onRedo?.()"
626
- (close)="state().contextMenu.closeContextMenu()"
592
+ (selectAll)="handleSelectAllCells()"
593
+ (undoAction)="onUndo()"
594
+ (redoAction)="onRedo()"
595
+ (close)="closeContextMenu()"
627
596
  ></ogrid-context-menu>
628
597
  }
629
598
 
630
- @if (state().viewModels.statusBarConfig) {
599
+ @if (statusBarConfig()) {
631
600
  <ogrid-status-bar
632
- [totalCount]="state().viewModels.statusBarConfig!.totalCount"
633
- [filteredCount]="state().viewModels.statusBarConfig!.filteredCount"
634
- [selectedCount]="state().viewModels.statusBarConfig!.selectedCount ?? state().rowSelection.selectedRowIds.size"
635
- [selectedCellCount]="selectedCellCount()"
636
- [aggregation]="state().viewModels.statusBarConfig!.aggregation"
637
- [suppressRowCount]="state().viewModels.statusBarConfig!.suppressRowCount"
601
+ [totalCount]="statusBarConfig()!.totalCount"
602
+ [filteredCount]="statusBarConfig()!.filteredCount"
603
+ [selectedCount]="statusBarConfig()!.selectedCount ?? selectedRowIds().size"
604
+ [selectedCellCount]="selectionCellCount()"
605
+ [aggregation]="statusBarConfig()!.aggregation"
606
+ [suppressRowCount]="statusBarConfig()!.suppressRowCount"
638
607
  [classNames]="statusBarClasses"
639
608
  ></ogrid-status-bar>
640
609
  }