@alaarab/ogrid-js 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.
- package/dist/esm/OGrid.js +94 -3
- package/dist/esm/components/HeaderFilter.js +1 -1
- package/dist/esm/components/InlineCellEditor.js +6 -4
- package/dist/esm/components/MarchingAntsOverlay.js +23 -29
- package/dist/esm/renderer/TableRenderer.js +5 -5
- package/dist/styles/ogrid.css +67 -43
- package/dist/types/OGrid.d.ts +1 -0
- package/dist/types/components/MarchingAntsOverlay.d.ts +3 -2
- package/package.json +2 -2
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
|
|
@@ -50,15 +133,21 @@ export class OGrid {
|
|
|
50
133
|
this.contextMenu = null;
|
|
51
134
|
this.events = new EventEmitter();
|
|
52
135
|
this.unsubscribes = [];
|
|
136
|
+
this.layoutVersion = 0; // Incremented when items, columns, sizing, or order change
|
|
53
137
|
this.options = options;
|
|
54
138
|
this.state = new GridState(options);
|
|
55
139
|
this.api = this.state.getApi();
|
|
140
|
+
// Inject theme CSS variables (light + dark) once per page
|
|
141
|
+
injectGlobalStyles('ogrid-theme-vars', OGRID_THEME_CSS);
|
|
56
142
|
// Build layout
|
|
57
143
|
this.containerEl = document.createElement('div');
|
|
58
144
|
this.containerEl.className = 'ogrid-container';
|
|
59
145
|
// Toolbar
|
|
60
146
|
this.toolbarEl = document.createElement('div');
|
|
61
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);
|
|
62
151
|
this.containerEl.appendChild(this.toolbarEl);
|
|
63
152
|
// Body area (holds sidebar + table, side by side)
|
|
64
153
|
this.bodyArea = document.createElement('div');
|
|
@@ -384,7 +473,7 @@ export class OGrid {
|
|
|
384
473
|
});
|
|
385
474
|
this.renderer.update();
|
|
386
475
|
// Update marching ants overlay
|
|
387
|
-
this.marchingAnts?.update(this.selectionState.selectionRange, this.clipboardState.copyRange, this.clipboardState.cutRange);
|
|
476
|
+
this.marchingAnts?.update(this.selectionState.selectionRange, this.clipboardState.copyRange, this.clipboardState.cutRange, this.layoutVersion);
|
|
388
477
|
}
|
|
389
478
|
updateDragAttributes() {
|
|
390
479
|
const wrapper = this.renderer.getWrapperElement();
|
|
@@ -640,7 +729,7 @@ export class OGrid {
|
|
|
640
729
|
this.loadingOverlay.style.display = 'flex';
|
|
641
730
|
this.loadingOverlay.style.alignItems = 'center';
|
|
642
731
|
this.loadingOverlay.style.justifyContent = 'center';
|
|
643
|
-
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))';
|
|
644
733
|
this.loadingOverlay.style.zIndex = '100';
|
|
645
734
|
const spinner = document.createElement('div');
|
|
646
735
|
spinner.className = 'ogrid-loading-spinner';
|
|
@@ -658,6 +747,8 @@ export class OGrid {
|
|
|
658
747
|
}
|
|
659
748
|
}
|
|
660
749
|
renderAll() {
|
|
750
|
+
// Increment layout version to trigger marching ants re-measurement
|
|
751
|
+
this.layoutVersion++;
|
|
661
752
|
const colOffset = this.rowSelectionState ? 1 : 0;
|
|
662
753
|
// Update header filter state with current filters and options
|
|
663
754
|
this.headerFilterState.setFilters(this.state.filters);
|
|
@@ -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 = '
|
|
255
|
-
dropdown.style.border = '1px solid
|
|
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 = '
|
|
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 = '
|
|
281
|
+
option.style.backgroundColor = 'var(--ogrid-bg, #fff)';
|
|
280
282
|
});
|
|
281
283
|
dropdown.appendChild(option);
|
|
282
284
|
}
|
|
@@ -1,31 +1,18 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
return;
|
|
7
|
-
const style = document.createElement('style');
|
|
8
|
-
style.id = 'ogrid-marching-ants-keyframes';
|
|
9
|
-
style.textContent =
|
|
10
|
-
'@keyframes ogrid-marching-ants{to{stroke-dashoffset:-8}}';
|
|
11
|
-
document.head.appendChild(style);
|
|
12
|
-
}
|
|
13
|
-
/** Measure the bounding rect of a range within a container. */
|
|
1
|
+
import { injectGlobalStyles, measureRange as measureRangeCore } from '@alaarab/ogrid-core';
|
|
2
|
+
/**
|
|
3
|
+
* Measure the bounding rect of a range within a container, with scroll offsets.
|
|
4
|
+
* This variant adds scroll offsets for the JS implementation's scrollable container.
|
|
5
|
+
*/
|
|
14
6
|
function measureRange(container, range, colOffset) {
|
|
15
|
-
const
|
|
16
|
-
|
|
17
|
-
const topLeft = container.querySelector(`[data-row-index="${range.startRow}"][data-col-index="${startGlobalCol}"]`);
|
|
18
|
-
const bottomRight = container.querySelector(`[data-row-index="${range.endRow}"][data-col-index="${endGlobalCol}"]`);
|
|
19
|
-
if (!topLeft || !bottomRight)
|
|
7
|
+
const rect = measureRangeCore(container, range, colOffset);
|
|
8
|
+
if (!rect)
|
|
20
9
|
return null;
|
|
21
|
-
|
|
22
|
-
const tlRect = topLeft.getBoundingClientRect();
|
|
23
|
-
const brRect = bottomRight.getBoundingClientRect();
|
|
10
|
+
// Add scroll offsets for JS implementation's scrollable container
|
|
24
11
|
return {
|
|
25
|
-
top:
|
|
26
|
-
left:
|
|
27
|
-
width:
|
|
28
|
-
height:
|
|
12
|
+
top: rect.top + container.scrollTop,
|
|
13
|
+
left: rect.left + container.scrollLeft,
|
|
14
|
+
width: rect.width,
|
|
15
|
+
height: rect.height,
|
|
29
16
|
};
|
|
30
17
|
}
|
|
31
18
|
function rangesEqual(a, b) {
|
|
@@ -51,18 +38,25 @@ export class MarchingAntsOverlay {
|
|
|
51
38
|
this.copyRange = null;
|
|
52
39
|
this.cutRange = null;
|
|
53
40
|
this.rafHandle = 0;
|
|
41
|
+
this.layoutVersion = 0; // Tracks layout changes to force re-measurement
|
|
54
42
|
this.container = container;
|
|
55
43
|
this.colOffset = colOffset;
|
|
56
|
-
|
|
44
|
+
injectGlobalStyles('ogrid-marching-ants-keyframes', '@keyframes ogrid-marching-ants{to{stroke-dashoffset:-8}}');
|
|
57
45
|
// The container must be positioned for absolute SVGs
|
|
58
46
|
const pos = getComputedStyle(container).position;
|
|
59
47
|
if (pos === 'static' || pos === '') {
|
|
60
48
|
container.style.position = 'relative';
|
|
61
49
|
}
|
|
62
50
|
}
|
|
63
|
-
update(selectionRange, copyRange, cutRange) {
|
|
64
|
-
//
|
|
65
|
-
|
|
51
|
+
update(selectionRange, copyRange, cutRange, layoutVersion) {
|
|
52
|
+
// Track layout changes separately from range changes
|
|
53
|
+
const layoutChanged = layoutVersion !== undefined && layoutVersion !== this.layoutVersion;
|
|
54
|
+
if (layoutChanged && layoutVersion !== undefined) {
|
|
55
|
+
this.layoutVersion = layoutVersion;
|
|
56
|
+
}
|
|
57
|
+
// Skip if nothing changed (ranges or layout)
|
|
58
|
+
if (!layoutChanged &&
|
|
59
|
+
rangesEqual(this.selectionRange, selectionRange) &&
|
|
66
60
|
rangesEqual(this.copyRange, copyRange) &&
|
|
67
61
|
rangesEqual(this.cutRange, cutRange)) {
|
|
68
62
|
return;
|
|
@@ -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 = '
|
|
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
|
|
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 #
|
|
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) {
|
package/dist/styles/ogrid.css
CHANGED
|
@@ -7,23 +7,31 @@
|
|
|
7
7
|
/* ── Light Theme (default) ── */
|
|
8
8
|
:root {
|
|
9
9
|
--ogrid-bg: #ffffff;
|
|
10
|
-
--ogrid-fg:
|
|
11
|
-
--ogrid-
|
|
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:
|
|
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-
|
|
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: #
|
|
37
|
-
--ogrid-fg:
|
|
38
|
-
--ogrid-
|
|
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: #
|
|
42
|
-
--ogrid-bg-hover:
|
|
43
|
-
--ogrid-bg-selected: #
|
|
44
|
-
--ogrid-bg-selected-hover: #
|
|
45
|
-
--ogrid-bg-range: rgba(
|
|
46
|
-
--ogrid-
|
|
47
|
-
--ogrid-
|
|
48
|
-
--ogrid-
|
|
49
|
-
--ogrid-
|
|
50
|
-
--ogrid-primary: #
|
|
51
|
-
--ogrid-
|
|
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(
|
|
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: #
|
|
64
|
-
--ogrid-fg:
|
|
65
|
-
--ogrid-
|
|
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: #
|
|
69
|
-
--ogrid-bg-hover:
|
|
70
|
-
--ogrid-bg-selected: #
|
|
71
|
-
--ogrid-bg-selected-hover: #
|
|
72
|
-
--ogrid-bg-range: rgba(
|
|
73
|
-
--ogrid-
|
|
74
|
-
--ogrid-
|
|
75
|
-
--ogrid-
|
|
76
|
-
--ogrid-
|
|
77
|
-
--ogrid-primary: #
|
|
78
|
-
--ogrid-
|
|
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(
|
|
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/dist/types/OGrid.d.ts
CHANGED
|
@@ -35,6 +35,7 @@ export declare class OGrid<T> {
|
|
|
35
35
|
private paginationContainer;
|
|
36
36
|
private statusBarContainer;
|
|
37
37
|
private options;
|
|
38
|
+
private layoutVersion;
|
|
38
39
|
/** The imperative grid API (extends React's IOGridApi with JS-specific methods). */
|
|
39
40
|
readonly api: IJsOGridApi<T>;
|
|
40
41
|
constructor(container: HTMLElement, options: OGridOptions<T>);
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import type
|
|
1
|
+
import { type ISelectionRange } from '@alaarab/ogrid-core';
|
|
2
2
|
/**
|
|
3
3
|
* MarchingAntsOverlay — renders SVG overlays on top of the grid:
|
|
4
4
|
* 1. Selection range: solid green border
|
|
@@ -15,8 +15,9 @@ export declare class MarchingAntsOverlay {
|
|
|
15
15
|
private copyRange;
|
|
16
16
|
private cutRange;
|
|
17
17
|
private rafHandle;
|
|
18
|
+
private layoutVersion;
|
|
18
19
|
constructor(container: HTMLElement, colOffset?: number);
|
|
19
|
-
update(selectionRange: ISelectionRange | null, copyRange: ISelectionRange | null, cutRange: ISelectionRange | null): void;
|
|
20
|
+
update(selectionRange: ISelectionRange | null, copyRange: ISelectionRange | null, cutRange: ISelectionRange | null, layoutVersion?: number): void;
|
|
20
21
|
private render;
|
|
21
22
|
private createSvg;
|
|
22
23
|
private positionSvg;
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@alaarab/ogrid-js",
|
|
3
|
-
"version": "2.0.
|
|
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.
|
|
39
|
+
"@alaarab/ogrid-core": "2.0.12"
|
|
40
40
|
},
|
|
41
41
|
"sideEffects": false,
|
|
42
42
|
"publishConfig": {
|