@alaarab/ogrid-js 2.0.11 → 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.
package/dist/esm/OGrid.js CHANGED
@@ -22,7 +22,90 @@ import { MarchingAntsOverlay } from './components/MarchingAntsOverlay';
22
22
  import { InlineCellEditor } from './components/InlineCellEditor';
23
23
  import { ContextMenu } from './components/ContextMenu';
24
24
  import { EventEmitter } from './state/EventEmitter';
25
- import { normalizeSelectionRange, isInSelectionRange, flattenColumns } from '@alaarab/ogrid-core';
25
+ import { normalizeSelectionRange, isInSelectionRange, flattenColumns, injectGlobalStyles } from '@alaarab/ogrid-core';
26
+ /** CSS variable definitions for light and dark themes (injected once per page). */
27
+ const OGRID_THEME_CSS = `
28
+ :root {
29
+ --ogrid-bg: #ffffff;
30
+ --ogrid-fg: rgba(0, 0, 0, 0.87);
31
+ --ogrid-fg-secondary: rgba(0, 0, 0, 0.6);
32
+ --ogrid-fg-muted: rgba(0, 0, 0, 0.5);
33
+ --ogrid-border: rgba(0, 0, 0, 0.12);
34
+ --ogrid-header-bg: rgba(0, 0, 0, 0.04);
35
+ --ogrid-hover-bg: rgba(0, 0, 0, 0.04);
36
+ --ogrid-selected-row-bg: #e6f0fb;
37
+ --ogrid-active-cell-bg: rgba(0, 0, 0, 0.02);
38
+ --ogrid-range-bg: rgba(33, 115, 70, 0.12);
39
+ --ogrid-accent: #0078d4;
40
+ --ogrid-selection-color: #217346;
41
+ --ogrid-loading-overlay: rgba(255, 255, 255, 0.7);
42
+ --ogrid-bg-subtle: #f3f2f1;
43
+ --ogrid-bg-hover: rgba(0, 0, 0, 0.04);
44
+ --ogrid-bg-selected: #e6f0fb;
45
+ --ogrid-bg-selected-hover: #dae8f8;
46
+ --ogrid-bg-range: rgba(33, 115, 70, 0.12);
47
+ --ogrid-muted: rgba(0, 0, 0, 0.5);
48
+ --ogrid-selection: #217346;
49
+ --ogrid-primary: #217346;
50
+ --ogrid-primary-fg: #fff;
51
+ --ogrid-loading-bg: rgba(255, 255, 255, 0.7);
52
+ --ogrid-shadow: 0 4px 16px rgba(0, 0, 0, 0.12);
53
+ }
54
+ [data-theme='dark'] {
55
+ --ogrid-bg: #1e1e1e;
56
+ --ogrid-fg: rgba(255, 255, 255, 0.87);
57
+ --ogrid-fg-secondary: rgba(255, 255, 255, 0.6);
58
+ --ogrid-fg-muted: rgba(255, 255, 255, 0.5);
59
+ --ogrid-border: rgba(255, 255, 255, 0.12);
60
+ --ogrid-header-bg: rgba(255, 255, 255, 0.06);
61
+ --ogrid-hover-bg: rgba(255, 255, 255, 0.08);
62
+ --ogrid-selected-row-bg: #1a3a5c;
63
+ --ogrid-active-cell-bg: rgba(255, 255, 255, 0.06);
64
+ --ogrid-range-bg: rgba(46, 160, 67, 0.15);
65
+ --ogrid-accent: #4da6ff;
66
+ --ogrid-selection-color: #2ea043;
67
+ --ogrid-loading-overlay: rgba(0, 0, 0, 0.7);
68
+ --ogrid-bg-subtle: #2a2a2a;
69
+ --ogrid-bg-hover: rgba(255, 255, 255, 0.08);
70
+ --ogrid-bg-selected: #1a3a5c;
71
+ --ogrid-bg-selected-hover: #1f426b;
72
+ --ogrid-bg-range: rgba(46, 160, 67, 0.15);
73
+ --ogrid-muted: rgba(255, 255, 255, 0.5);
74
+ --ogrid-selection: #2ea043;
75
+ --ogrid-primary: #2ea043;
76
+ --ogrid-primary-fg: #fff;
77
+ --ogrid-loading-bg: rgba(0, 0, 0, 0.7);
78
+ --ogrid-shadow: 0 4px 16px rgba(0, 0, 0, 0.35);
79
+ }
80
+ @media (prefers-color-scheme: dark) {
81
+ :root:not([data-theme='light']) {
82
+ --ogrid-bg: #1e1e1e;
83
+ --ogrid-fg: rgba(255, 255, 255, 0.87);
84
+ --ogrid-fg-secondary: rgba(255, 255, 255, 0.6);
85
+ --ogrid-fg-muted: rgba(255, 255, 255, 0.5);
86
+ --ogrid-border: rgba(255, 255, 255, 0.12);
87
+ --ogrid-header-bg: rgba(255, 255, 255, 0.06);
88
+ --ogrid-hover-bg: rgba(255, 255, 255, 0.08);
89
+ --ogrid-selected-row-bg: #1a3a5c;
90
+ --ogrid-active-cell-bg: rgba(255, 255, 255, 0.06);
91
+ --ogrid-range-bg: rgba(46, 160, 67, 0.15);
92
+ --ogrid-accent: #4da6ff;
93
+ --ogrid-selection-color: #2ea043;
94
+ --ogrid-loading-overlay: rgba(0, 0, 0, 0.7);
95
+ --ogrid-bg-subtle: #2a2a2a;
96
+ --ogrid-bg-hover: rgba(255, 255, 255, 0.08);
97
+ --ogrid-bg-selected: #1a3a5c;
98
+ --ogrid-bg-selected-hover: #1f426b;
99
+ --ogrid-bg-range: rgba(46, 160, 67, 0.15);
100
+ --ogrid-muted: rgba(255, 255, 255, 0.5);
101
+ --ogrid-selection: #2ea043;
102
+ --ogrid-primary: #2ea043;
103
+ --ogrid-primary-fg: #fff;
104
+ --ogrid-loading-bg: rgba(0, 0, 0, 0.7);
105
+ --ogrid-shadow: 0 4px 16px rgba(0, 0, 0, 0.35);
106
+ }
107
+ }
108
+ `;
26
109
  export class OGrid {
27
110
  constructor(container, options) {
28
111
  // Sidebar
@@ -54,12 +137,17 @@ export class OGrid {
54
137
  this.options = options;
55
138
  this.state = new GridState(options);
56
139
  this.api = this.state.getApi();
140
+ // Inject theme CSS variables (light + dark) once per page
141
+ injectGlobalStyles('ogrid-theme-vars', OGRID_THEME_CSS);
57
142
  // Build layout
58
143
  this.containerEl = document.createElement('div');
59
144
  this.containerEl.className = 'ogrid-container';
60
145
  // Toolbar
61
146
  this.toolbarEl = document.createElement('div');
62
147
  this.toolbarEl.className = 'ogrid-toolbar';
148
+ // Left spacer keeps column chooser on the right via justify-content: space-between
149
+ const toolbarSpacer = document.createElement('div');
150
+ this.toolbarEl.appendChild(toolbarSpacer);
63
151
  this.containerEl.appendChild(this.toolbarEl);
64
152
  // Body area (holds sidebar + table, side by side)
65
153
  this.bodyArea = document.createElement('div');
@@ -641,7 +729,7 @@ export class OGrid {
641
729
  this.loadingOverlay.style.display = 'flex';
642
730
  this.loadingOverlay.style.alignItems = 'center';
643
731
  this.loadingOverlay.style.justifyContent = 'center';
644
- this.loadingOverlay.style.background = 'rgba(255,255,255,0.7)';
732
+ this.loadingOverlay.style.background = 'var(--ogrid-loading-overlay, rgba(255, 255, 255, 0.7))';
645
733
  this.loadingOverlay.style.zIndex = '100';
646
734
  const spinner = document.createElement('div');
647
735
  spinner.className = 'ogrid-loading-spinner';
@@ -26,7 +26,7 @@ export class HeaderFilter {
26
26
  this.popoverEl.style.color = 'var(--ogrid-fg, #242424)';
27
27
  this.popoverEl.style.border = '1px solid var(--ogrid-border, #e0e0e0)';
28
28
  this.popoverEl.style.borderRadius = '4px';
29
- this.popoverEl.style.boxShadow = '0 2px 8px rgba(0,0,0,0.15)';
29
+ this.popoverEl.style.boxShadow = 'var(--ogrid-shadow, 0 2px 8px rgba(0,0,0,0.15))';
30
30
  this.popoverEl.style.padding = '8px';
31
31
  this.popoverEl.style.minWidth = '200px';
32
32
  this.popoverEl.style.maxHeight = '320px';
@@ -243,6 +243,8 @@ export class InlineCellEditor {
243
243
  input.style.outline = 'none';
244
244
  input.style.padding = '4px';
245
245
  input.style.boxSizing = 'border-box';
246
+ input.style.background = 'var(--ogrid-bg, #fff)';
247
+ input.style.color = 'var(--ogrid-fg, rgba(0, 0, 0, 0.87))';
246
248
  wrapper.appendChild(input);
247
249
  const dropdown = document.createElement('div');
248
250
  dropdown.style.position = 'absolute';
@@ -251,8 +253,8 @@ export class InlineCellEditor {
251
253
  dropdown.style.width = '100%';
252
254
  dropdown.style.maxHeight = '200px';
253
255
  dropdown.style.overflowY = 'auto';
254
- dropdown.style.backgroundColor = 'white';
255
- dropdown.style.border = '1px solid #ccc';
256
+ dropdown.style.backgroundColor = 'var(--ogrid-bg, #fff)';
257
+ dropdown.style.border = '1px solid var(--ogrid-border, rgba(0, 0, 0, 0.12))';
256
258
  dropdown.style.zIndex = '1001';
257
259
  wrapper.appendChild(dropdown);
258
260
  const values = column.cellEditorParams?.values ?? [];
@@ -273,10 +275,10 @@ export class InlineCellEditor {
273
275
  this.closeEditor();
274
276
  });
275
277
  option.addEventListener('mouseenter', () => {
276
- option.style.backgroundColor = '#f0f0f0';
278
+ option.style.backgroundColor = 'var(--ogrid-hover-bg, rgba(0, 0, 0, 0.04))';
277
279
  });
278
280
  option.addEventListener('mouseleave', () => {
279
- option.style.backgroundColor = 'white';
281
+ option.style.backgroundColor = 'var(--ogrid-bg, #fff)';
280
282
  });
281
283
  dropdown.appendChild(option);
282
284
  }
@@ -110,7 +110,7 @@ export class TableRenderer {
110
110
  }
111
111
  // Background must be set on pinned cells to avoid showing content underneath
112
112
  if (!isHeader) {
113
- el.style.backgroundColor = el.style.backgroundColor || '#fff';
113
+ el.style.backgroundColor = el.style.backgroundColor || 'var(--ogrid-bg, #fff)';
114
114
  }
115
115
  }
116
116
  renderHeader() {
@@ -410,20 +410,20 @@ export class TableRenderer {
410
410
  // Active cell
411
411
  if (activeCell && activeCell.rowIndex === rowIndex && activeCell.columnIndex === globalColIndex) {
412
412
  td.setAttribute('data-active-cell', 'true');
413
- td.style.outline = '2px solid #0078d4';
413
+ td.style.outline = '2px solid var(--ogrid-accent, #0078d4)';
414
414
  }
415
415
  // Selection range
416
416
  if (selectionRange && isInSelectionRange(selectionRange, rowIndex, colIndex)) {
417
417
  td.setAttribute('data-in-range', 'true');
418
- td.style.backgroundColor = '#e3f2fd';
418
+ td.style.backgroundColor = 'var(--ogrid-range-bg, rgba(33, 115, 70, 0.12))';
419
419
  }
420
420
  // Copy range
421
421
  if (copyRange && isInSelectionRange(copyRange, rowIndex, colIndex)) {
422
- td.style.outline = '1px dashed #666';
422
+ td.style.outline = '1px dashed var(--ogrid-fg-muted, rgba(0, 0, 0, 0.5))';
423
423
  }
424
424
  // Cut range
425
425
  if (cutRange && isInSelectionRange(cutRange, rowIndex, colIndex)) {
426
- td.style.outline = '1px dashed #d32f2f';
426
+ td.style.outline = '1px dashed var(--ogrid-accent, #0078d4)';
427
427
  }
428
428
  // Editing cell (hide content, editor overlay will be shown)
429
429
  if (editingCell && editingCell.rowId === rowId && editingCell.columnId === col.columnId) {
@@ -7,23 +7,31 @@
7
7
  /* ── Light Theme (default) ── */
8
8
  :root {
9
9
  --ogrid-bg: #ffffff;
10
- --ogrid-fg: #242424;
11
- --ogrid-border: #e0e0e0;
10
+ --ogrid-fg: rgba(0, 0, 0, 0.87);
11
+ --ogrid-fg-secondary: rgba(0, 0, 0, 0.6);
12
+ --ogrid-fg-muted: rgba(0, 0, 0, 0.5);
13
+ --ogrid-border: rgba(0, 0, 0, 0.12);
14
+ --ogrid-header-bg: rgba(0, 0, 0, 0.04);
15
+ --ogrid-hover-bg: rgba(0, 0, 0, 0.04);
16
+ --ogrid-selected-row-bg: #e6f0fb;
17
+ --ogrid-active-cell-bg: rgba(0, 0, 0, 0.02);
18
+ --ogrid-range-bg: rgba(33, 115, 70, 0.12);
19
+ --ogrid-accent: #0078d4;
20
+ --ogrid-selection-color: #217346;
21
+ --ogrid-loading-overlay: rgba(255, 255, 255, 0.7);
22
+ /* Aliases for backward compat */
12
23
  --ogrid-border-strong: #888;
13
24
  --ogrid-border-hover: #999;
14
25
  --ogrid-bg-subtle: #f3f2f1;
15
- --ogrid-bg-hover: #f5f5f5;
26
+ --ogrid-bg-hover: rgba(0, 0, 0, 0.04);
16
27
  --ogrid-bg-selected: #e6f0fb;
17
28
  --ogrid-bg-selected-hover: #dae8f8;
18
29
  --ogrid-bg-range: rgba(33, 115, 70, 0.12);
19
- --ogrid-header-bg: #f5f5f5;
20
- --ogrid-muted: #616161;
21
- --ogrid-fg-muted: rgba(0, 0, 0, 0.4);
30
+ --ogrid-muted: rgba(0, 0, 0, 0.5);
22
31
  --ogrid-selection: #217346;
23
32
  --ogrid-primary: #217346;
24
33
  --ogrid-primary-fg: #fff;
25
34
  --ogrid-primary-hover: #1b5f39;
26
- --ogrid-accent: #217346;
27
35
  --ogrid-accent-dark: #1b5f39;
28
36
  --ogrid-shadow: 0 4px 16px rgba(0, 0, 0, 0.12);
29
37
  --ogrid-shadow-sm: 0 2px 4px rgba(0, 0, 0, 0.08);
@@ -33,55 +41,71 @@
33
41
 
34
42
  /* ── Dark Theme ── */
35
43
  [data-theme='dark'] {
36
- --ogrid-bg: #1a1a24;
37
- --ogrid-fg: #e0e0e0;
38
- --ogrid-border: #333340;
44
+ --ogrid-bg: #1e1e1e;
45
+ --ogrid-fg: rgba(255, 255, 255, 0.87);
46
+ --ogrid-fg-secondary: rgba(255, 255, 255, 0.6);
47
+ --ogrid-fg-muted: rgba(255, 255, 255, 0.5);
48
+ --ogrid-border: rgba(255, 255, 255, 0.12);
49
+ --ogrid-header-bg: rgba(255, 255, 255, 0.06);
50
+ --ogrid-hover-bg: rgba(255, 255, 255, 0.08);
51
+ --ogrid-selected-row-bg: #1a3a5c;
52
+ --ogrid-active-cell-bg: rgba(255, 255, 255, 0.06);
53
+ --ogrid-range-bg: rgba(46, 160, 67, 0.15);
54
+ --ogrid-accent: #4da6ff;
55
+ --ogrid-selection-color: #2ea043;
56
+ --ogrid-loading-overlay: rgba(0, 0, 0, 0.7);
57
+ /* Aliases for backward compat */
39
58
  --ogrid-border-strong: #555;
40
59
  --ogrid-border-hover: #666;
41
- --ogrid-bg-subtle: #22222e;
42
- --ogrid-bg-hover: #2a2a38;
43
- --ogrid-bg-selected: #1a2f45;
44
- --ogrid-bg-selected-hover: #1f3650;
45
- --ogrid-bg-range: rgba(58, 184, 118, 0.12);
46
- --ogrid-header-bg: #22222e;
47
- --ogrid-muted: #999;
48
- --ogrid-fg-muted: rgba(255, 255, 255, 0.3);
49
- --ogrid-selection: #3ab876;
50
- --ogrid-primary: #3ab876;
51
- --ogrid-primary-fg: #0a0a0f;
52
- --ogrid-primary-hover: #4ec484;
53
- --ogrid-accent: #3ab876;
54
- --ogrid-accent-dark: #2fa768;
60
+ --ogrid-bg-subtle: #2a2a2a;
61
+ --ogrid-bg-hover: rgba(255, 255, 255, 0.08);
62
+ --ogrid-bg-selected: #1a3a5c;
63
+ --ogrid-bg-selected-hover: #1f426b;
64
+ --ogrid-bg-range: rgba(46, 160, 67, 0.15);
65
+ --ogrid-muted: rgba(255, 255, 255, 0.5);
66
+ --ogrid-selection: #2ea043;
67
+ --ogrid-primary: #2ea043;
68
+ --ogrid-primary-fg: #fff;
69
+ --ogrid-primary-hover: #3db852;
70
+ --ogrid-accent-dark: #3db852;
55
71
  --ogrid-shadow: 0 4px 16px rgba(0, 0, 0, 0.35);
56
72
  --ogrid-shadow-sm: 0 2px 4px rgba(0, 0, 0, 0.25);
57
- --ogrid-loading-bg: rgba(26, 26, 36, 0.7);
73
+ --ogrid-loading-bg: rgba(0, 0, 0, 0.7);
58
74
  --ogrid-pinned-shadow: rgba(0, 0, 0, 0.4);
59
75
  }
60
76
 
61
77
  @media (prefers-color-scheme: dark) {
62
78
  :root:not([data-theme='light']) {
63
- --ogrid-bg: #1a1a24;
64
- --ogrid-fg: #e0e0e0;
65
- --ogrid-border: #333340;
79
+ --ogrid-bg: #1e1e1e;
80
+ --ogrid-fg: rgba(255, 255, 255, 0.87);
81
+ --ogrid-fg-secondary: rgba(255, 255, 255, 0.6);
82
+ --ogrid-fg-muted: rgba(255, 255, 255, 0.5);
83
+ --ogrid-border: rgba(255, 255, 255, 0.12);
84
+ --ogrid-header-bg: rgba(255, 255, 255, 0.06);
85
+ --ogrid-hover-bg: rgba(255, 255, 255, 0.08);
86
+ --ogrid-selected-row-bg: #1a3a5c;
87
+ --ogrid-active-cell-bg: rgba(255, 255, 255, 0.06);
88
+ --ogrid-range-bg: rgba(46, 160, 67, 0.15);
89
+ --ogrid-accent: #4da6ff;
90
+ --ogrid-selection-color: #2ea043;
91
+ --ogrid-loading-overlay: rgba(0, 0, 0, 0.7);
92
+ /* Aliases for backward compat */
66
93
  --ogrid-border-strong: #555;
67
94
  --ogrid-border-hover: #666;
68
- --ogrid-bg-subtle: #22222e;
69
- --ogrid-bg-hover: #2a2a38;
70
- --ogrid-bg-selected: #1a2f45;
71
- --ogrid-bg-selected-hover: #1f3650;
72
- --ogrid-bg-range: rgba(58, 184, 118, 0.12);
73
- --ogrid-header-bg: #22222e;
74
- --ogrid-muted: #999;
75
- --ogrid-fg-muted: rgba(255, 255, 255, 0.3);
76
- --ogrid-selection: #3ab876;
77
- --ogrid-primary: #3ab876;
78
- --ogrid-primary-fg: #0a0a0f;
79
- --ogrid-primary-hover: #4ec484;
80
- --ogrid-accent: #3ab876;
81
- --ogrid-accent-dark: #2fa768;
95
+ --ogrid-bg-subtle: #2a2a2a;
96
+ --ogrid-bg-hover: rgba(255, 255, 255, 0.08);
97
+ --ogrid-bg-selected: #1a3a5c;
98
+ --ogrid-bg-selected-hover: #1f426b;
99
+ --ogrid-bg-range: rgba(46, 160, 67, 0.15);
100
+ --ogrid-muted: rgba(255, 255, 255, 0.5);
101
+ --ogrid-selection: #2ea043;
102
+ --ogrid-primary: #2ea043;
103
+ --ogrid-primary-fg: #fff;
104
+ --ogrid-primary-hover: #3db852;
105
+ --ogrid-accent-dark: #3db852;
82
106
  --ogrid-shadow: 0 4px 16px rgba(0, 0, 0, 0.35);
83
107
  --ogrid-shadow-sm: 0 2px 4px rgba(0, 0, 0, 0.25);
84
- --ogrid-loading-bg: rgba(26, 26, 36, 0.7);
108
+ --ogrid-loading-bg: rgba(0, 0, 0, 0.7);
85
109
  --ogrid-pinned-shadow: rgba(0, 0, 0, 0.4);
86
110
  }
87
111
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@alaarab/ogrid-js",
3
- "version": "2.0.11",
3
+ "version": "2.0.12",
4
4
  "description": "OGrid vanilla JS – framework-free data grid with sorting, filtering, pagination, and spreadsheet-style editing.",
5
5
  "main": "dist/esm/index.js",
6
6
  "module": "dist/esm/index.js",
@@ -36,7 +36,7 @@
36
36
  "node": ">=18"
37
37
  },
38
38
  "dependencies": {
39
- "@alaarab/ogrid-core": "2.0.11"
39
+ "@alaarab/ogrid-core": "2.0.12"
40
40
  },
41
41
  "sideEffects": false,
42
42
  "publishConfig": {