@alaarab/ogrid-angular-material 2.0.9 → 2.0.12

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,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: var(--ogrid-fg-secondary, 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: var(--ogrid-hover-bg, rgba(0, 0, 0, 0.08));
129
+ color: var(--ogrid-fg, rgba(0, 0, 0, 0.87));
97
130
  }
98
131
  `],
99
132
  })
@@ -4,8 +4,8 @@ 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';
8
- import { BaseDataGridTableComponent, DataGridStateService, MarchingAntsOverlayComponent, CHECKBOX_COLUMN_WIDTH, ROW_NUMBER_COLUMN_WIDTH, } from '@alaarab/ogrid-angular';
7
+ import { Component, ChangeDetectionStrategy, ViewEncapsulation, Input, ViewChild, signal } from '@angular/core';
8
+ import { BaseDataGridTableComponent, DataGridStateService, MarchingAntsOverlayComponent, StatusBarComponent, GridContextMenuComponent, EmptyStateComponent, CHECKBOX_COLUMN_WIDTH, ROW_NUMBER_COLUMN_WIDTH, } 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';
@@ -15,30 +15,55 @@ import { PopoverCellEditorComponent } from './popover-cell-editor.component';
15
15
  * Standalone component — this is the workhorse of the grid.
16
16
  */
17
17
  let DataGridTableComponent = class DataGridTableComponent extends BaseDataGridTableComponent {
18
+ set propsInput(value) {
19
+ this.propsSignal.set(value);
20
+ }
18
21
  constructor() {
19
22
  super();
20
- this.propsInput = input.required({ alias: 'props' });
21
- this.wrapperRef = viewChild('wrapperEl');
22
- this.tableContainerRef = viewChild('tableContainerEl');
23
+ this.propsSignal = signal(undefined);
23
24
  this.initBase();
24
25
  }
25
26
  getProps() {
26
- return this.propsInput();
27
+ return this.propsSignal();
27
28
  }
28
29
  getWrapperRef() {
29
- return this.wrapperRef();
30
+ return this.wrapperRef;
30
31
  }
31
32
  getTableContainerRef() {
32
- return this.tableContainerRef();
33
+ return this.tableContainerRef;
34
+ }
35
+ /** Build column header menu handlers for a given column */
36
+ getColumnMenuHandlers(columnId) {
37
+ return {
38
+ onPinLeft: () => this.onPinColumn(columnId, 'left'),
39
+ onPinRight: () => this.onPinColumn(columnId, 'right'),
40
+ onUnpin: () => this.onUnpinColumn(columnId),
41
+ onSortAsc: () => this.onSortAsc(columnId),
42
+ onSortDesc: () => this.onSortDesc(columnId),
43
+ onClearSort: () => this.onClearSort(columnId),
44
+ onAutosizeThis: () => this.onAutosizeColumn(columnId),
45
+ onAutosizeAll: () => this.onAutosizeAllColumns(),
46
+ onClose: () => { }
47
+ };
33
48
  }
34
49
  };
50
+ __decorate([
51
+ Input({ required: true, alias: 'props' })
52
+ ], DataGridTableComponent.prototype, "propsInput", null);
53
+ __decorate([
54
+ ViewChild('wrapperEl')
55
+ ], DataGridTableComponent.prototype, "wrapperRef", void 0);
56
+ __decorate([
57
+ ViewChild('tableContainerEl')
58
+ ], DataGridTableComponent.prototype, "tableContainerRef", void 0);
35
59
  DataGridTableComponent = __decorate([
36
60
  Component({
37
61
  selector: 'ogrid-datagrid-table',
38
62
  standalone: true,
39
- imports: [ColumnHeaderFilterComponent, ColumnHeaderMenuComponent, MarchingAntsOverlayComponent, InlineCellEditorComponent, PopoverCellEditorComponent],
40
- providers: [DataGridStateService],
41
63
  changeDetection: ChangeDetectionStrategy.OnPush,
64
+ encapsulation: ViewEncapsulation.None,
65
+ imports: [ColumnHeaderFilterComponent, ColumnHeaderMenuComponent, StatusBarComponent, GridContextMenuComponent, MarchingAntsOverlayComponent, EmptyStateComponent, InlineCellEditorComponent, PopoverCellEditorComponent],
66
+ providers: [DataGridStateService],
42
67
  template: `
43
68
  <div class="ogrid-datagrid-root">
44
69
  <div
@@ -103,16 +128,21 @@ DataGridTableComponent = __decorate([
103
128
  @let pinned = isPinned(col.columnId);
104
129
  @let pinnedLeft = pinned === 'left' || (isFreezeCol && colIdx === 0);
105
130
  @let pinnedRight = pinned === 'right';
131
+ @let sortState = getSortState(col.columnId);
132
+ @let ariaSort = sortState === 'asc' ? 'ascending' : sortState === 'desc' ? 'descending' : null;
106
133
  <th scope="col"
107
134
  class="ogrid-datagrid-th"
108
135
  [class.ogrid-datagrid-th--pinned-left]="pinnedLeft"
109
136
  [class.ogrid-datagrid-th--pinned-right]="pinnedRight"
110
137
  [attr.rowSpan]="headerRows().length > 1 ? headerRows().length - rowIdx : null"
111
138
  [attr.data-column-id]="col.columnId"
139
+ [attr.aria-sort]="ariaSort"
112
140
  [style.minWidth.px]="col.minWidth ?? 80"
113
141
  [style.width.px]="colW"
114
142
  [style.maxWidth.px]="colW"
115
143
  [style.cursor]="columnReorderService.isDragging() ? 'grabbing' : 'grab'"
144
+ [style.left.px]="pinnedLeft ? getPinnedLeftOffset(col.columnId) : null"
145
+ [style.right.px]="pinnedRight ? getPinnedRightOffset(col.columnId) : null"
116
146
  (mousedown)="onHeaderMouseDown(col.columnId, $event)"
117
147
  >
118
148
  <div style="display:flex;align-items:center;gap:4px;">
@@ -136,14 +166,16 @@ DataGridTableComponent = __decorate([
136
166
  [onDateChange]="getFilterConfig(col).onDateChange"
137
167
  />
138
168
  @let pinState = getPinState(col.columnId);
169
+ @let sortState = getSortState(col.columnId);
139
170
  <column-header-menu
140
171
  [columnId]="col.columnId"
141
- [onPinLeft]="() => onPinColumn(col.columnId, 'left')"
142
- [onPinRight]="() => onPinColumn(col.columnId, 'right')"
143
- [onUnpin]="() => onUnpinColumn(col.columnId)"
144
172
  [canPinLeft]="pinState.canPinLeft"
145
173
  [canPinRight]="pinState.canPinRight"
146
174
  [canUnpin]="pinState.canUnpin"
175
+ [currentSort]="sortState"
176
+ [isSortable]="col.sortable !== false"
177
+ [isResizable]="col.resizable !== false"
178
+ [handlers]="getColumnMenuHandlers(col.columnId)"
147
179
  />
148
180
  </div>
149
181
  <div class="ogrid-datagrid-resize-handle" (mousedown)="onResizeStart($event, col)"></div>
@@ -195,11 +227,14 @@ DataGridTableComponent = __decorate([
195
227
  @for (colLayout of columnLayouts(); track colLayout.col.columnId; let colIdx = $index) {
196
228
  <td
197
229
  class="ogrid-datagrid-td"
230
+ [attr.data-column-id]="colLayout.col.columnId"
198
231
  [class.ogrid-datagrid-td--pinned-left]="colLayout.pinnedLeft"
199
232
  [class.ogrid-datagrid-td--pinned-right]="colLayout.pinnedRight"
200
233
  [style.minWidth.px]="colLayout.minWidth"
201
234
  [style.width.px]="colLayout.width"
202
235
  [style.maxWidth.px]="colLayout.width"
236
+ [style.left.px]="colLayout.pinnedLeft ? getPinnedLeftOffset(colLayout.col.columnId) : null"
237
+ [style.right.px]="colLayout.pinnedRight ? getPinnedRightOffset(colLayout.col.columnId) : null"
203
238
  >
204
239
  @let descriptor = getCellDescriptor(item, colLayout.col, rowIndex, colIdx);
205
240
  @if (descriptor.mode === 'editing-inline') {
@@ -221,7 +256,7 @@ DataGridTableComponent = __decorate([
221
256
  [globalColIndex]="descriptor.globalColIndex"
222
257
  [displayValue]="descriptor.displayValue"
223
258
  [editorProps]="editorProps"
224
- [onCancel]="() => cancelEdit()"
259
+ [onCancel]="cancelEdit.bind(this)"
225
260
  ></ogrid-mat-popover-cell-editor>
226
261
  } @else {
227
262
  @let content = resolveCellContent(colLayout.col, item, descriptor.displayValue);
@@ -267,27 +302,27 @@ DataGridTableComponent = __decorate([
267
302
  </table>
268
303
 
269
304
  <ogrid-marching-ants-overlay
270
- [containerEl]="tableContainerEl()"
305
+ [containerEl]="tableContainerEl"
271
306
  [selectionRange]="state().interaction.selectionRange"
272
307
  [copyRange]="state().interaction.copyRange"
273
308
  [cutRange]="state().interaction.cutRange"
274
309
  [colOffset]="state().layout.colOffset"
275
310
  [columnSizingVersion]="columnSizingVersion()"
311
+ [items]="items()"
312
+ [visibleColumns]="propsVisibleColumns()"
313
+ [columnOrder]="propsColumnOrder()"
276
314
  ></ogrid-marching-ants-overlay>
277
315
 
278
316
  @if (showEmptyInGrid() && emptyState()) {
279
317
  <div class="ogrid-datagrid-empty">
280
318
  <div class="ogrid-datagrid-empty__title">No results found</div>
281
319
  <div class="ogrid-datagrid-empty__message">
282
- @if (emptyState()!.message != null) {
283
- {{ emptyState()!.message }}
284
- } @else if (emptyState()!.hasActiveFilters) {
285
- No items match your current filters. Try adjusting your search or
286
- <button class="ogrid-datagrid-empty__clear" (click)="emptyState()!.onClearAll?.()">clear all filters</button>
287
- to see all items.
288
- } @else {
289
- There are no items available at this time.
290
- }
320
+ <ogrid-empty-state
321
+ [message]="emptyState()?.message"
322
+ [hasActiveFilters]="emptyState()?.hasActiveFilters ?? false"
323
+ [render]="emptyState()?.render"
324
+ (clearAll)="emptyState()?.onClearAll()"
325
+ ></ogrid-empty-state>
291
326
  </div>
292
327
  </div>
293
328
  }
@@ -305,12 +340,12 @@ DataGridTableComponent = __decorate([
305
340
  (click)="closeContextMenu()"
306
341
  (contextmenu)="$event.preventDefault(); closeContextMenu()"
307
342
  >
308
- <ogrid-grid-context-menu
343
+ <ogrid-context-menu
309
344
  [x]="menuPosition()!.x"
310
345
  [y]="menuPosition()!.y"
311
346
  [hasSelection]="hasCellSelection()"
312
- [canUndo]="canUndo()"
313
- [canRedo]="canRedo()"
347
+ [canUndoProp]="canUndo()"
348
+ [canRedoProp]="canRedo()"
314
349
  (undoAction)="onUndo()"
315
350
  (redoAction)="onRedo()"
316
351
  (copyAction)="handleCopy()"
@@ -345,40 +380,94 @@ DataGridTableComponent = __decorate([
345
380
  </div>
346
381
  `,
347
382
  styles: [`
383
+ /* ─── OGrid Theme Variables ─── */
384
+ :root {
385
+ --ogrid-bg: #ffffff;
386
+ --ogrid-fg: rgba(0, 0, 0, 0.87);
387
+ --ogrid-fg-secondary: rgba(0, 0, 0, 0.6);
388
+ --ogrid-fg-muted: rgba(0, 0, 0, 0.5);
389
+ --ogrid-border: rgba(0, 0, 0, 0.12);
390
+ --ogrid-header-bg: rgba(0, 0, 0, 0.04);
391
+ --ogrid-hover-bg: rgba(0, 0, 0, 0.04);
392
+ --ogrid-selected-row-bg: #e6f0fb;
393
+ --ogrid-active-cell-bg: rgba(0, 0, 0, 0.02);
394
+ --ogrid-range-bg: rgba(33, 115, 70, 0.12);
395
+ --ogrid-accent: #0078d4;
396
+ --ogrid-selection-color: #217346;
397
+ --ogrid-loading-overlay: rgba(255, 255, 255, 0.7);
398
+ }
399
+ @media (prefers-color-scheme: dark) {
400
+ :root:not([data-theme="light"]) {
401
+ --ogrid-bg: #1e1e1e;
402
+ --ogrid-fg: rgba(255, 255, 255, 0.87);
403
+ --ogrid-fg-secondary: rgba(255, 255, 255, 0.6);
404
+ --ogrid-fg-muted: rgba(255, 255, 255, 0.5);
405
+ --ogrid-border: rgba(255, 255, 255, 0.12);
406
+ --ogrid-header-bg: rgba(255, 255, 255, 0.06);
407
+ --ogrid-hover-bg: rgba(255, 255, 255, 0.08);
408
+ --ogrid-selected-row-bg: #1a3a5c;
409
+ --ogrid-active-cell-bg: rgba(255, 255, 255, 0.06);
410
+ --ogrid-range-bg: rgba(46, 160, 67, 0.15);
411
+ --ogrid-accent: #4da6ff;
412
+ --ogrid-selection-color: #2ea043;
413
+ --ogrid-loading-overlay: rgba(0, 0, 0, 0.7);
414
+ }
415
+ }
416
+ [data-theme="dark"] {
417
+ --ogrid-bg: #1e1e1e;
418
+ --ogrid-fg: rgba(255, 255, 255, 0.87);
419
+ --ogrid-fg-secondary: rgba(255, 255, 255, 0.6);
420
+ --ogrid-fg-muted: rgba(255, 255, 255, 0.5);
421
+ --ogrid-border: rgba(255, 255, 255, 0.12);
422
+ --ogrid-header-bg: rgba(255, 255, 255, 0.06);
423
+ --ogrid-hover-bg: rgba(255, 255, 255, 0.08);
424
+ --ogrid-selected-row-bg: #1a3a5c;
425
+ --ogrid-active-cell-bg: rgba(255, 255, 255, 0.06);
426
+ --ogrid-range-bg: rgba(46, 160, 67, 0.15);
427
+ --ogrid-accent: #4da6ff;
428
+ --ogrid-selection-color: #2ea043;
429
+ --ogrid-loading-overlay: rgba(0, 0, 0, 0.7);
430
+ }
348
431
  :host { display: block; }
349
432
  .ogrid-datagrid-root { position: relative; flex: 1; min-height: 0; display: flex; flex-direction: column; }
350
433
  .ogrid-datagrid-wrapper {
351
434
  position: relative; flex: 1; min-height: 0; width: 100%; max-width: 100%;
352
- overflow-x: hidden; overflow-y: auto; background: #fff;
435
+ overflow-x: hidden; overflow-y: auto; background: var(--ogrid-bg, #ffffff);
436
+ color: var(--ogrid-fg, rgba(0, 0, 0, 0.87));
353
437
  will-change: scroll-position; outline: none;
354
438
  }
355
- .ogrid-datagrid-wrapper [data-drag-range] { background: rgba(33, 115, 70, 0.12) !important; }
439
+ .ogrid-datagrid-wrapper [data-drag-range] { background: var(--ogrid-range-bg, rgba(33, 115, 70, 0.12)) !important; }
356
440
  .ogrid-datagrid-wrapper--fit { width: fit-content; }
357
441
  .ogrid-datagrid-wrapper--overflow-x { overflow-x: auto; }
358
442
  .ogrid-datagrid-scroll-wrapper { display: flex; flex-direction: column; min-height: 100%; }
359
443
  .ogrid-datagrid-table-wrapper--loading { position: relative; opacity: 0.6; }
360
444
  .ogrid-datagrid-table {
361
- width: 100%; border-collapse: collapse; overflow: hidden; table-layout: fixed;
445
+ width: 100%; border-collapse: collapse; table-layout: fixed;
362
446
  }
363
447
  .ogrid-datagrid-thead {
364
- position: sticky; top: 0; z-index: 8; background: rgba(0,0,0,0.04);
448
+ z-index: 8; background: var(--ogrid-header-bg, rgba(0, 0, 0, 0.04));
365
449
  }
366
- .ogrid-datagrid-thead th { background: rgba(0,0,0,0.04); }
367
- .ogrid-datagrid-header-row { background: rgba(0,0,0,0.04); }
450
+ .ogrid-datagrid-thead th { background: var(--ogrid-header-bg, rgba(0, 0, 0, 0.04)); }
451
+ .ogrid-datagrid-header-row { background: var(--ogrid-header-bg, rgba(0, 0, 0, 0.04)); }
368
452
  .ogrid-datagrid-th {
369
- font-weight: 600; position: relative; padding: 6px 10px; text-align: left;
370
- font-size: 14px; border-bottom: 1px solid rgba(0,0,0,0.12);
453
+ font-weight: 600; position: sticky; top: 0; padding: 6px 10px; text-align: left;
454
+ font-size: 14px; border-bottom: 1px solid var(--ogrid-border, rgba(0, 0, 0, 0.12));
455
+ background: var(--ogrid-header-bg, rgba(0, 0, 0, 0.04)); z-index: 8;
456
+ color: var(--ogrid-fg, rgba(0, 0, 0, 0.87));
457
+ }
458
+ .ogrid-datagrid-th:focus-visible {
459
+ outline: 2px solid var(--mat-sys-primary, #1976d2); outline-offset: -2px; z-index: 11;
371
460
  }
372
461
  .ogrid-datagrid-th--pinned-left {
373
- position: sticky; left: 0; z-index: 9; background: rgba(0,0,0,0.04); will-change: transform;
374
- border-left: 2px solid var(--mat-sys-primary, #1976d2);
462
+ position: sticky; top: 0; left: 0; z-index: 10; background: var(--ogrid-header-bg, rgba(0, 0, 0, 0.04)); will-change: transform;
463
+ border-right: 2px solid var(--ogrid-border, rgba(0, 0, 0, 0.12));
375
464
  }
376
465
  .ogrid-datagrid-th--pinned-right {
377
- position: sticky; right: 0; z-index: 9; background: rgba(0,0,0,0.04); will-change: transform;
378
- border-right: 2px solid var(--mat-sys-primary, #1976d2);
466
+ position: sticky; top: 0; right: 0; z-index: 10; background: var(--ogrid-header-bg, rgba(0, 0, 0, 0.04)); will-change: transform;
467
+ border-left: 2px solid var(--ogrid-border, rgba(0, 0, 0, 0.12));
379
468
  }
380
469
  .ogrid-datagrid-group-header {
381
- text-align: center; font-weight: 600; border-bottom: 2px solid rgba(0,0,0,0.12); padding: 6px;
470
+ text-align: center; font-weight: 600; border-bottom: 2px solid var(--ogrid-border, rgba(0, 0, 0, 0.12)); padding: 6px;
382
471
  }
383
472
  .ogrid-datagrid-checkbox-col {
384
473
  width: ${CHECKBOX_COLUMN_WIDTH}px; min-width: ${CHECKBOX_COLUMN_WIDTH}px;
@@ -388,8 +477,8 @@ DataGridTableComponent = __decorate([
388
477
  .ogrid-row-number-header, .ogrid-row-number-cell {
389
478
  width: ${ROW_NUMBER_COLUMN_WIDTH}px; min-width: ${ROW_NUMBER_COLUMN_WIDTH}px;
390
479
  max-width: ${ROW_NUMBER_COLUMN_WIDTH}px; text-align: center;
391
- background: rgba(0,0,0,0.04); font-weight: 600;
392
- font-variant-numeric: tabular-nums; color: rgba(0,0,0,0.6);
480
+ background: var(--ogrid-header-bg, rgba(0, 0, 0, 0.04)); font-weight: 600;
481
+ font-variant-numeric: tabular-nums; color: var(--ogrid-fg-secondary, rgba(0, 0, 0, 0.6));
393
482
  position: sticky; left: 0; z-index: 3;
394
483
  }
395
484
  .ogrid-row-number-header { z-index: 4; }
@@ -397,48 +486,53 @@ DataGridTableComponent = __decorate([
397
486
  display: flex; align-items: center; justify-content: center;
398
487
  }
399
488
  .ogrid-datagrid-row { }
400
- .ogrid-datagrid-row:hover { background: rgba(0,0,0,0.04); }
401
- .ogrid-datagrid-row--selected { background: rgba(25,118,210,0.08); }
402
- .ogrid-datagrid-td { position: relative; padding: 0; height: 1px; border-bottom: 1px solid rgba(0,0,0,0.06); }
489
+ .ogrid-datagrid-row:hover { background: var(--ogrid-hover-bg, rgba(0, 0, 0, 0.04)); }
490
+ .ogrid-datagrid-row--selected { background: var(--ogrid-selected-row-bg, #e6f0fb); }
491
+ .ogrid-datagrid-td { position: relative; padding: 0; height: 1px; border-bottom: 1px solid var(--ogrid-border, rgba(0, 0, 0, 0.06)); }
403
492
  .ogrid-datagrid-td--pinned-left {
404
- position: sticky; left: 0; z-index: 6; background: #fff; will-change: transform;
405
- border-left: 2px solid var(--mat-sys-primary, #1976d2);
493
+ position: sticky; left: 0; z-index: 6; background: var(--ogrid-bg, #ffffff); will-change: transform;
494
+ border-right: 2px solid var(--ogrid-border, rgba(0, 0, 0, 0.12));
406
495
  }
407
496
  .ogrid-datagrid-td--pinned-right {
408
- position: sticky; right: 0; z-index: 6; background: #fff; will-change: transform;
409
- border-right: 2px solid var(--mat-sys-primary, #1976d2);
497
+ position: sticky; right: 0; z-index: 6; background: var(--ogrid-bg, #ffffff); will-change: transform;
498
+ border-left: 2px solid var(--ogrid-border, rgba(0, 0, 0, 0.12));
410
499
  }
411
500
  .ogrid-datagrid-cell {
412
501
  width: 100%; height: 100%; display: flex; align-items: center; min-width: 0;
413
502
  padding: 6px 10px; box-sizing: border-box; overflow: hidden;
414
503
  text-overflow: ellipsis; white-space: nowrap; user-select: none; outline: none;
415
- font-size: 14px;
504
+ font-size: 14px; color: var(--ogrid-fg, rgba(0, 0, 0, 0.87));
505
+ }
506
+ .ogrid-datagrid-cell:focus-visible {
507
+ outline: 2px solid var(--mat-sys-primary, #1976d2); outline-offset: -2px; z-index: 3;
416
508
  }
417
509
  .ogrid-datagrid-cell--numeric { justify-content: flex-end; text-align: right; }
418
510
  .ogrid-datagrid-cell--boolean { justify-content: center; text-align: center; }
419
511
  .ogrid-datagrid-cell--editable { cursor: cell; }
420
512
  .ogrid-datagrid-cell--active {
421
- outline: 2px solid var(--ogrid-selection, #217346); outline-offset: -1px;
513
+ outline: 2px solid var(--ogrid-selection-color, #217346); outline-offset: -1px;
422
514
  z-index: 2; position: relative; overflow: visible;
423
515
  }
424
- .ogrid-datagrid-cell--in-range { background: var(--ogrid-bg-range, rgba(33, 115, 70, 0.12)); }
425
- .ogrid-datagrid-cell--in-cut-range { background: rgba(0,0,0,0.04); opacity: 0.7; }
516
+ .ogrid-datagrid-cell--in-range { background: var(--ogrid-range-bg, rgba(33, 115, 70, 0.12)); }
517
+ .ogrid-datagrid-cell--in-cut-range { background: var(--ogrid-hover-bg, rgba(0, 0, 0, 0.04)); opacity: 0.7; }
426
518
  .ogrid-datagrid-cell--editing { padding: 0; }
427
519
  .ogrid-datagrid-editor-input {
428
- width: 100%; height: 100%; padding: 6px 10px; border: 2px solid var(--ogrid-selection, #217346);
520
+ width: 100%; height: 100%; padding: 6px 10px; border: 2px solid var(--ogrid-selection-color, #217346);
429
521
  box-sizing: border-box; font-size: 14px; outline: none; font-family: inherit; line-height: inherit;
522
+ background: var(--ogrid-bg, #ffffff); color: var(--ogrid-fg, rgba(0, 0, 0, 0.87));
430
523
  }
431
524
  .ogrid-datagrid-cell--numeric .ogrid-datagrid-editor-input {
432
525
  text-align: right;
433
526
  }
434
527
  .ogrid-datagrid-editor-select {
435
- width: 100%; height: 100%; padding: 4px 8px; border: 2px solid var(--ogrid-selection, #217346);
528
+ width: 100%; height: 100%; padding: 4px 8px; border: 2px solid var(--ogrid-selection-color, #217346);
436
529
  box-sizing: border-box; font-size: 14px;
530
+ background: var(--ogrid-bg, #ffffff); color: var(--ogrid-fg, rgba(0, 0, 0, 0.87));
437
531
  }
438
532
  .ogrid-datagrid-fill-handle {
439
533
  position: absolute; right: -3px; bottom: -3px; width: 7px; height: 7px;
440
- background: var(--ogrid-selection, #217346);
441
- border: 1px solid var(--ogrid-bg, #fff); border-radius: 1px;
534
+ background: var(--ogrid-selection-color, #217346);
535
+ border: 1px solid var(--ogrid-bg, #ffffff); border-radius: 1px;
442
536
  cursor: crosshair; pointer-events: auto; z-index: 3;
443
537
  }
444
538
  .ogrid-datagrid-resize-handle {
@@ -446,16 +540,17 @@ DataGridTableComponent = __decorate([
446
540
  cursor: col-resize; user-select: none;
447
541
  }
448
542
  .ogrid-datagrid-resize-handle::after {
449
- content: ''; position: absolute; top: 0; right: 3px; bottom: 0; width: 2px;
543
+ content: ''; position: absolute; top: 4px; right: 3px; bottom: 4px; width: 2px;
544
+ background: var(--ogrid-border, rgba(0, 0, 0, 0.12)); border-radius: 1px; transition: background 0.15s;
450
545
  }
451
- .ogrid-datagrid-resize-handle:hover::after { background: var(--mat-sys-primary, #1976d2); }
452
- .ogrid-datagrid-resize-handle:active::after { background: var(--mat-sys-primary, #1565c0); }
546
+ .ogrid-datagrid-resize-handle:hover::after { background: var(--ogrid-fg-muted, rgba(0, 0, 0, 0.4)); }
547
+ .ogrid-datagrid-resize-handle:active::after { background: var(--mat-sys-primary, #1976d2); }
453
548
  .ogrid-datagrid-empty {
454
- padding: 32px 16px; text-align: center; border-top: 1px solid rgba(0,0,0,0.12);
455
- background: rgba(0,0,0,0.04);
549
+ padding: 32px 16px; text-align: center; border-top: 1px solid var(--ogrid-border, rgba(0, 0, 0, 0.12));
550
+ background: var(--ogrid-header-bg, rgba(0, 0, 0, 0.04));
456
551
  }
457
- .ogrid-datagrid-empty__title { font-size: 18px; font-weight: 600; margin-bottom: 8px; }
458
- .ogrid-datagrid-empty__message { font-size: 14px; color: rgba(0,0,0,0.6); }
552
+ .ogrid-datagrid-empty__title { font-size: 18px; font-weight: 600; margin-bottom: 8px; color: var(--ogrid-fg, rgba(0, 0, 0, 0.87)); }
553
+ .ogrid-datagrid-empty__message { font-size: 14px; color: var(--ogrid-fg-secondary, rgba(0, 0, 0, 0.6)); }
459
554
  .ogrid-datagrid-empty__clear {
460
555
  background: none; border: none; color: var(--mat-sys-primary, #1976d2);
461
556
  cursor: pointer; font-size: inherit; text-decoration: underline; padding: 0;
@@ -463,26 +558,42 @@ DataGridTableComponent = __decorate([
463
558
  .ogrid-datagrid-loading-overlay {
464
559
  position: absolute; inset: 0; z-index: 2;
465
560
  display: flex; align-items: center; justify-content: center;
466
- background: rgba(255,255,255,0.7);
561
+ background: var(--ogrid-loading-overlay, rgba(255, 255, 255, 0.7));
467
562
  }
468
563
  .ogrid-datagrid-loading-inner {
469
564
  display: flex; flex-direction: column; align-items: center; gap: 8px;
470
- padding: 16px; background: #fff; border: 1px solid rgba(0,0,0,0.12); border-radius: 4px;
565
+ padding: 16px; background: var(--ogrid-bg, #ffffff); border: 1px solid var(--ogrid-border, rgba(0, 0, 0, 0.12)); border-radius: 4px;
566
+ color: var(--ogrid-fg, rgba(0, 0, 0, 0.87));
471
567
  }
472
568
  .ogrid-datagrid-spinner {
473
- width: 24px; height: 24px; border: 3px solid rgba(0,0,0,0.12);
569
+ width: 24px; height: 24px; border: 3px solid var(--ogrid-border, rgba(0, 0, 0, 0.12));
474
570
  border-top-color: var(--mat-sys-primary, #1976d2);
475
571
  border-radius: 50%; animation: ogrid-spin 0.8s linear infinite;
476
572
  }
477
573
  @keyframes ogrid-spin { to { transform: rotate(360deg); } }
478
574
  .ogrid-datagrid-drop-indicator {
479
575
  position: absolute; top: 0; bottom: 0; width: 3px;
480
- background: var(--ogrid-primary, #217346);
576
+ background: var(--ogrid-selection-color, #217346);
481
577
  pointer-events: none; z-index: 100; transition: left 0.05s;
482
578
  }
483
579
  .ogrid-datagrid-context-menu-overlay {
484
580
  position: fixed; inset: 0; z-index: 1000;
485
581
  }
582
+
583
+ /* Angular Material Menu popup dark mode overrides */
584
+ .mat-mdc-menu-panel {
585
+ background: var(--ogrid-bg, #ffffff) !important;
586
+ color: var(--ogrid-fg, rgba(0, 0, 0, 0.87)) !important;
587
+ }
588
+ .mat-mdc-menu-item {
589
+ color: var(--ogrid-fg, rgba(0, 0, 0, 0.87)) !important;
590
+ }
591
+ .mat-mdc-menu-item:hover:not([disabled]) {
592
+ background: var(--ogrid-hover-bg, rgba(0, 0, 0, 0.04)) !important;
593
+ }
594
+ .mat-mdc-menu-item .mat-mdc-menu-item-text {
595
+ color: var(--ogrid-fg, rgba(0, 0, 0, 0.87)) !important;
596
+ }
486
597
  `],
487
598
  })
488
599
  ], DataGridTableComponent);