@zengrid/core 1.2.2 → 1.3.0

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.
Files changed (105) hide show
  1. package/dist/index.cjs.js +1873 -1095
  2. package/dist/index.esm.js +1936 -1161
  3. package/dist/package.json +2 -2
  4. package/dist/src/datetime-core/formatting/date-formatter.d.ts +2 -0
  5. package/dist/src/datetime-core/formatting/date-formatter.d.ts.map +1 -1
  6. package/dist/src/datetime-core/theming/datetime.css +463 -407
  7. package/dist/src/editing/checkbox/checkbox-dom.d.ts.map +1 -1
  8. package/dist/src/editing/datetime/date-editor/date-editor.d.ts.map +1 -1
  9. package/dist/src/editing/datetime/date-range-editor/date-range-calendar.d.ts.map +1 -1
  10. package/dist/src/editing/editor-manager/editor-manager.d.ts +23 -1
  11. package/dist/src/editing/editor-manager/editor-manager.d.ts.map +1 -1
  12. package/dist/src/editing/number/number-editor.d.ts.map +1 -1
  13. package/dist/src/editing/select/select-editor.d.ts.map +1 -1
  14. package/dist/src/features/column-drag/drag-mouse-handler.d.ts +1 -0
  15. package/dist/src/features/column-drag/drag-mouse-handler.d.ts.map +1 -1
  16. package/dist/src/features/copy-paste/clipboard-manager.d.ts +24 -2
  17. package/dist/src/features/copy-paste/clipboard-manager.d.ts.map +1 -1
  18. package/dist/src/features/loading/loading-indicator.d.ts.map +1 -1
  19. package/dist/src/features/loading/loading.styles.css +346 -342
  20. package/dist/src/features/selection/selection-manager.d.ts +14 -0
  21. package/dist/src/features/selection/selection-manager.d.ts.map +1 -1
  22. package/dist/src/grid/grid-core.d.ts.map +1 -1
  23. package/dist/src/grid/grid-setup.d.ts.map +1 -1
  24. package/dist/src/index.d.ts +6 -2
  25. package/dist/src/index.d.ts.map +1 -1
  26. package/dist/src/plugins/clipboard/clipboard-plugin.d.ts +21 -0
  27. package/dist/src/plugins/clipboard/clipboard-plugin.d.ts.map +1 -0
  28. package/dist/src/plugins/clipboard/index.d.ts +3 -0
  29. package/dist/src/plugins/clipboard/index.d.ts.map +1 -0
  30. package/dist/src/plugins/column/column-plugin.d.ts.map +1 -1
  31. package/dist/src/plugins/dom/dom-plugin.d.ts.map +1 -1
  32. package/dist/src/plugins/editing/editing-plugin.d.ts.map +1 -1
  33. package/dist/src/plugins/filter-ui/field-state-utils.d.ts +6 -0
  34. package/dist/src/plugins/filter-ui/field-state-utils.d.ts.map +1 -0
  35. package/dist/src/plugins/filter-ui/filter-chip-bar.d.ts +16 -0
  36. package/dist/src/plugins/filter-ui/filter-chip-bar.d.ts.map +1 -0
  37. package/dist/src/plugins/filter-ui/filter-chip-descriptors.d.ts +4 -0
  38. package/dist/src/plugins/filter-ui/filter-chip-descriptors.d.ts.map +1 -0
  39. package/dist/src/plugins/filter-ui/filter-popup-dom.d.ts +32 -0
  40. package/dist/src/plugins/filter-ui/filter-popup-dom.d.ts.map +1 -0
  41. package/dist/src/plugins/filter-ui/filter-popup.d.ts +3 -0
  42. package/dist/src/plugins/filter-ui/filter-popup.d.ts.map +1 -0
  43. package/dist/src/plugins/filter-ui/filter-ui-operators.d.ts +9 -0
  44. package/dist/src/plugins/filter-ui/filter-ui-operators.d.ts.map +1 -0
  45. package/dist/src/plugins/filter-ui/filter-ui-types.d.ts +56 -0
  46. package/dist/src/plugins/filter-ui/filter-ui-types.d.ts.map +1 -0
  47. package/dist/src/plugins/filter-ui/grid-filter-ui.d.ts +20 -0
  48. package/dist/src/plugins/filter-ui/grid-filter-ui.d.ts.map +1 -0
  49. package/dist/src/plugins/filter-ui/index.d.ts +1 -0
  50. package/dist/src/plugins/filter-ui/index.d.ts.map +1 -1
  51. package/dist/src/plugins/header/header-dom-operations.d.ts +6 -0
  52. package/dist/src/plugins/header/header-dom-operations.d.ts.map +1 -1
  53. package/dist/src/plugins/header/header-plugin.d.ts.map +1 -1
  54. package/dist/src/plugins/header/header-registry-setup.d.ts.map +1 -1
  55. package/dist/src/plugins/header/header-rendering.d.ts.map +1 -1
  56. package/dist/src/plugins/header/header-types.d.ts +8 -1
  57. package/dist/src/plugins/header/header-types.d.ts.map +1 -1
  58. package/dist/src/plugins/index.d.ts +4 -0
  59. package/dist/src/plugins/index.d.ts.map +1 -1
  60. package/dist/src/plugins/keyboard/index.d.ts +3 -0
  61. package/dist/src/plugins/keyboard/index.d.ts.map +1 -0
  62. package/dist/src/plugins/keyboard/keyboard-nav-utils.d.ts +13 -0
  63. package/dist/src/plugins/keyboard/keyboard-nav-utils.d.ts.map +1 -0
  64. package/dist/src/plugins/keyboard/keyboard-plugin.d.ts +17 -0
  65. package/dist/src/plugins/keyboard/keyboard-plugin.d.ts.map +1 -0
  66. package/dist/src/plugins/lifecycle/lifecycle-plugin.d.ts +1 -0
  67. package/dist/src/plugins/lifecycle/lifecycle-plugin.d.ts.map +1 -1
  68. package/dist/src/plugins/pagination/pagination-plugin.d.ts.map +1 -1
  69. package/dist/src/plugins/rendering/rendering-plugin.d.ts.map +1 -1
  70. package/dist/src/plugins/selection/selection-plugin.d.ts.map +1 -1
  71. package/dist/src/reactive/store.d.ts +1 -0
  72. package/dist/src/reactive/store.d.ts.map +1 -1
  73. package/dist/src/reactive/types.d.ts +1 -0
  74. package/dist/src/reactive/types.d.ts.map +1 -1
  75. package/dist/src/rendering/cache/renderer-cache.interface.d.ts +6 -0
  76. package/dist/src/rendering/cache/renderer-cache.interface.d.ts.map +1 -1
  77. package/dist/src/rendering/cell-positioner/cell-positioner.d.ts +21 -0
  78. package/dist/src/rendering/cell-positioner/cell-positioner.d.ts.map +1 -1
  79. package/dist/src/rendering/headers/header-renderer.interface.d.ts +6 -0
  80. package/dist/src/rendering/headers/header-renderer.interface.d.ts.map +1 -1
  81. package/dist/src/rendering/headers/renderers/sortable-header-renderer.d.ts +4 -0
  82. package/dist/src/rendering/headers/renderers/sortable-header-renderer.d.ts.map +1 -1
  83. package/dist/src/rendering/renderers/dropdown/dropdown-dom.d.ts.map +1 -1
  84. package/dist/src/rendering/renderers/dropdown/dropdown-renderer.d.ts +2 -0
  85. package/dist/src/rendering/renderers/dropdown/dropdown-renderer.d.ts.map +1 -1
  86. package/dist/src/rendering/renderers/dropdown/dropdown-state.d.ts.map +1 -1
  87. package/dist/src/rendering/renderers/renderer.interface.d.ts +7 -0
  88. package/dist/src/rendering/renderers/renderer.interface.d.ts.map +1 -1
  89. package/dist/src/styles/a11y.css +20 -0
  90. package/dist/src/styles/calendar.css +291 -0
  91. package/dist/src/styles/cell-overflow.css +129 -0
  92. package/dist/src/styles/cell-renderers.css +90 -0
  93. package/dist/src/styles/date-picker.css +125 -0
  94. package/dist/src/styles/dropdown.css +156 -0
  95. package/dist/src/styles/filter.css +166 -0
  96. package/dist/src/styles/grid.css +91 -287
  97. package/dist/src/styles/header.css +60 -0
  98. package/dist/src/styles/overlays.css +44 -0
  99. package/dist/src/styles/tokens.css +86 -0
  100. package/dist/src/styles.css +24 -1112
  101. package/dist/src/types/grid.d.ts +32 -2
  102. package/dist/src/types/grid.d.ts.map +1 -1
  103. package/package.json +3 -3
  104. package/dist/src/grid/filter-ui.d.ts +0 -71
  105. package/dist/src/grid/filter-ui.d.ts.map +0 -1
@@ -1,362 +1,166 @@
1
1
  /**
2
- * ZenGrid Core Styles
3
- * Minimal, themeable CSS for the grid component
2
+ * Grid shell — container, viewport, virtual scroll surface, cells and cell states.
4
3
  */
5
4
 
6
- /* CSS Variables for theming */
7
- :root {
8
- /* Colors - Light Theme */
9
- --zg-bg-primary: #ffffff;
10
- --zg-bg-secondary: #f5f5f5;
11
- --zg-bg-hover: #f0f4f8;
12
- --zg-bg-selected: #e3f2fd;
13
- --zg-bg-active: #ffffff;
14
- --zg-bg-editing: #ffffff;
15
-
16
- --zg-border-color: #e0e0e0;
17
- --zg-border-active: #2196f3;
18
- --zg-border-editing: #4caf50;
19
- --zg-border-selected: #2196f3;
20
-
21
- --zg-text-primary: #333333;
22
- --zg-text-secondary: #666666;
23
- --zg-text-disabled: #999999;
24
-
25
- /* Focus ring */
26
- --zg-focus-ring: 2px solid #2196f3;
27
- --zg-focus-offset: 2px;
28
-
29
- /* Spacing */
30
- --zg-cell-padding-x: 8px;
31
- --zg-cell-padding-y: 0;
32
-
33
- /* Typography */
34
- --zg-font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, Oxygen, Ubuntu, Cantarell, sans-serif;
35
- --zg-font-size: 14px;
36
- --zg-line-height: 1.5;
37
-
38
- /* Shadows */
39
- --zg-shadow-sm: 0 1px 2px rgba(0, 0, 0, 0.05);
40
- --zg-shadow-md: 0 2px 4px rgba(0, 0, 0, 0.1);
41
- --zg-shadow-lg: 0 4px 8px rgba(0, 0, 0, 0.15);
42
-
43
- /* Transitions */
44
- --zg-transition-fast: 0.1s ease;
45
- --zg-transition-normal: 0.2s ease;
46
- }
47
-
48
- /* Dark theme — Slate/Emerald palette (matches zengrid.dev) */
49
- [data-theme="dark"] {
50
- --zg-bg-primary: #0f172a; /* Slate 900 */
51
- --zg-bg-secondary: #1e293b; /* Slate 800 */
52
- --zg-bg-hover: #334155; /* Slate 700 */
53
- --zg-bg-selected: #064e3b; /* Emerald 900 */
54
- --zg-bg-active: #0f172a; /* Slate 900 */
55
- --zg-bg-editing: #0f172a; /* Slate 900 */
56
-
57
- --zg-border-color: #1e293b; /* Slate 800 */
58
- --zg-border-active: #10b981; /* Emerald 500 */
59
- --zg-border-editing: #34d399; /* Emerald 400 */
60
- --zg-border-selected: #10b981; /* Emerald 500 */
61
-
62
- --zg-text-primary: #f8fafc; /* Slate 50 */
63
- --zg-text-secondary: #94a3b8; /* Slate 400 */
64
- --zg-text-disabled: #475569; /* Slate 600 */
65
- }
66
-
67
5
  /* Grid container */
68
6
  .zg-grid {
69
7
  position: relative;
70
8
  width: 100%;
71
9
  height: 100%;
72
- background: var(--zg-bg-primary);
10
+ overflow: hidden;
11
+ background: var(--zg-bg-color);
73
12
  font-family: var(--zg-font-family);
74
13
  font-size: var(--zg-font-size);
75
14
  line-height: var(--zg-line-height);
76
- color: var(--zg-text-primary);
77
- overflow: hidden;
78
- user-select: none;
79
- -webkit-user-select: none;
15
+ color: var(--zg-text-color);
80
16
  }
81
17
 
82
- /* Viewport */
18
+ /* Viewport (scrollable area) */
83
19
  .zg-viewport {
84
20
  position: relative;
85
21
  width: 100%;
86
22
  height: 100%;
87
- overflow: hidden;
88
- }
89
-
90
- /* Scroll container */
91
- .zg-scroll-container {
92
- position: absolute;
93
- top: 0;
94
- left: 0;
95
- right: 0;
96
- bottom: 0;
97
23
  overflow: auto;
98
- scrollbar-width: thin;
99
- scrollbar-color: rgba(0, 0, 0, 0.3) transparent;
100
- }
101
-
102
- .zg-scroll-container::-webkit-scrollbar {
103
- width: 12px;
104
- height: 12px;
24
+ will-change: scroll-position;
105
25
  }
106
26
 
107
- .zg-scroll-container::-webkit-scrollbar-track {
108
- background: transparent;
109
- }
110
-
111
- .zg-scroll-container::-webkit-scrollbar-thumb {
112
- background: rgba(0, 0, 0, 0.3);
113
- border-radius: 6px;
114
- border: 2px solid transparent;
115
- background-clip: content-box;
116
- }
117
-
118
- .zg-scroll-container::-webkit-scrollbar-thumb:hover {
119
- background: rgba(0, 0, 0, 0.5);
120
- background-clip: content-box;
121
- }
122
-
123
- /* Canvas (scroll area) */
124
- .zg-canvas {
125
- position: relative;
126
- pointer-events: none;
27
+ /* Scroll container (defines virtual scroll area) */
28
+ .zg-scroll-container {
29
+ pointer-events: auto;
127
30
  }
128
31
 
129
- /* Cells container */
32
+ /* Cell container (holds visible cells) */
130
33
  .zg-cells {
131
34
  position: absolute;
132
35
  top: 0;
133
36
  left: 0;
134
37
  pointer-events: auto;
38
+ /* Performance optimization: hint browser about transform animations */
39
+ will-change: transform;
135
40
  }
136
41
 
137
- /* Cell base styles */
42
+ /* Individual cell */
138
43
  .zg-cell {
139
44
  position: absolute;
140
45
  box-sizing: border-box;
46
+ padding: var(--zg-cell-padding);
141
47
  /* Use box-shadow instead of border for consistent rendering at fractional devicePixelRatio */
142
48
  /* Borders render inconsistently at 125%/150% Windows scaling due to sub-pixel rounding */
143
49
  box-shadow:
144
50
  inset -1px 0 0 0 var(--zg-border-color),
145
51
  inset 0 -1px 0 0 var(--zg-border-color);
146
- padding: var(--zg-cell-padding-y) var(--zg-cell-padding-x);
52
+ background: var(--zg-bg-color);
53
+ color: var(--zg-text-color);
54
+ /* Vertically center single-line cell content regardless of row height */
147
55
  display: flex;
148
56
  align-items: center;
149
- background: var(--zg-bg-primary);
150
- color: var(--zg-text-primary);
151
- overflow: hidden;
152
57
  white-space: nowrap;
58
+ overflow: hidden;
153
59
  text-overflow: ellipsis;
154
- transition: background-color var(--zg-transition-fast);
155
- cursor: default;
156
- }
60
+ user-select: none;
157
61
 
158
- /* Cell states */
159
- .zg-cell:hover {
160
- background: var(--zg-bg-hover);
62
+ /* Performance optimization: contain layout/style/paint within cell boundaries */
63
+ /* This helps browser optimize rendering by isolating cell changes */
64
+ contain: layout style paint;
161
65
  }
162
66
 
163
- .zg-grid .zg-cell.zg-cell-selected {
164
- background: var(--zg-bg-selected);
67
+ .zg-cell[data-col="0"] {
165
68
  box-shadow:
166
- inset -1px 0 0 0 var(--zg-border-selected),
167
- inset 0 -1px 0 0 var(--zg-border-selected);
168
- }
169
-
170
- .zg-grid .zg-cell.zg-cell-active {
171
- box-shadow: inset 0 0 0 2px var(--zg-border-active);
172
- background: var(--zg-bg-active);
173
- z-index: 2;
174
- }
175
-
176
- .zg-grid .zg-cell.zg-cell-editing {
177
- background: var(--zg-bg-editing);
178
- box-shadow: inset 0 0 0 2px var(--zg-border-editing);
179
- z-index: 3;
180
- }
181
-
182
- .zg-cell-readonly {
183
- background: var(--zg-bg-secondary);
184
- color: var(--zg-text-secondary);
185
- cursor: not-allowed;
186
- }
187
-
188
- .zg-cell-disabled {
189
- color: var(--zg-text-disabled);
190
- cursor: not-allowed;
191
- opacity: 0.6;
192
- }
193
-
194
- /* Cell alignment */
195
- .zg-cell-align-left {
196
- justify-content: flex-start;
197
- text-align: left;
198
- }
199
-
200
- .zg-cell-align-center {
201
- justify-content: center;
202
- text-align: center;
69
+ inset 1px 0 0 0 var(--zg-border-color),
70
+ inset -1px 0 0 0 var(--zg-border-color),
71
+ inset 0 -1px 0 0 var(--zg-border-color);
203
72
  }
204
73
 
205
- .zg-cell-align-right {
206
- justify-content: flex-end;
207
- text-align: right;
74
+ /* hideLastColumnBorder: drop the last column's own right border so it doesn't
75
+ double up against a bordered container. Selection/active keep their box. */
76
+ .zg-hide-last-col-border .zg-cell-last-col:not(.zg-cell-selected):not(.zg-cell-active) {
77
+ box-shadow: inset 0 -1px 0 0 var(--zg-border-color);
208
78
  }
209
-
210
- /* Cell types */
211
- .zg-cell-number {
212
- justify-content: flex-end;
213
- text-align: right;
214
- font-variant-numeric: tabular-nums;
79
+ .zg-hide-last-col-border .zg-cell-last-col[data-col="0"]:not(.zg-cell-selected):not(.zg-cell-active) {
80
+ box-shadow:
81
+ inset 1px 0 0 0 var(--zg-border-color),
82
+ inset 0 -1px 0 0 var(--zg-border-color);
215
83
  }
216
84
 
217
- .zg-cell-boolean {
218
- justify-content: center;
85
+ .zg-cell:hover {
86
+ background: var(--zg-hover-bg);
219
87
  }
220
88
 
221
- .zg-cell-date {
222
- font-variant-numeric: tabular-nums;
89
+ /* Selected cell - full border box, raised above neighbors so no edge is clipped */
90
+ .zg-cell-selected {
91
+ background: var(--zg-selected-bg);
92
+ box-shadow:
93
+ inset 1px 0 0 0 var(--zg-selected-border),
94
+ inset -1px 0 0 0 var(--zg-selected-border),
95
+ inset 0 1px 0 0 var(--zg-selected-border),
96
+ inset 0 -1px 0 0 var(--zg-selected-border);
97
+ z-index: 3;
223
98
  }
224
99
 
225
- /* Header cells */
226
- .zg-header-cell {
227
- background: var(--zg-bg-secondary);
228
- font-weight: 600;
229
- border-bottom: 2px solid var(--zg-border-color);
230
- position: sticky;
231
- top: 0;
232
- z-index: 10;
100
+ /* Active/focused cell */
101
+ .zg-cell-active {
102
+ outline: 2px solid var(--zg-focus-ring);
103
+ outline-offset: -2px;
104
+ z-index: 2;
233
105
  }
234
106
 
235
- .zg-header-cell:hover {
236
- background: var(--zg-bg-hover);
107
+ /* Editing cell - inset outline so the overlay editor's own border covers it
108
+ (matches .zg-cell-active); a non-inset outline showed as a second ring
109
+ outside the editor border, e.g. the native select editor. */
110
+ .zg-cell-editing {
111
+ outline: 2px solid var(--zg-focus-ring);
112
+ outline-offset: -2px;
113
+ background: var(--zg-bg-color);
114
+ z-index: 3;
237
115
  }
238
116
 
239
- /* Row header */
240
- .zg-row-header {
241
- background: var(--zg-bg-secondary);
242
- font-weight: 500;
243
- text-align: center;
244
- border-right: 2px solid var(--zg-border-color);
245
- position: sticky;
246
- left: 0;
247
- z-index: 9;
117
+ .zg-cell-editing input {
118
+ width: 100%;
119
+ height: 100%;
120
+ border: none;
121
+ outline: none;
122
+ padding: 0;
123
+ font: inherit;
124
+ background: transparent;
248
125
  }
249
126
 
250
- /* Focus ring (keyboard navigation) */
251
- .zg-cell:focus,
252
- .zg-cell:focus-visible {
253
- outline: var(--zg-focus-ring);
254
- outline-offset: calc(-1 * var(--zg-focus-offset));
255
- z-index: 4;
127
+ /* Cell holding a value that failed validation (editing invalidEditMode: 'commit').
128
+ Uses background + text color (not box-shadow) so it isn't overridden by the
129
+ higher-specificity cell-border rules above. */
130
+ .zg-cell-invalid {
131
+ background: color-mix(in srgb, var(--zg-error, #d32f2f) 12%, transparent);
132
+ color: var(--zg-error, #d32f2f);
256
133
  }
257
134
 
258
- /* Selection highlight overlay */
259
- .zg-selection-overlay {
135
+ /* Inline validation message shown under a blocked editor (invalidEditMode: 'block') */
136
+ .zg-editor-error {
260
137
  position: absolute;
138
+ top: 100%;
139
+ left: 0;
140
+ margin-top: 2px;
141
+ padding: 2px 6px;
142
+ max-width: 240px;
143
+ font-size: 11px;
144
+ line-height: 1.4;
145
+ color: #fff;
146
+ background: var(--zg-error, #d32f2f);
147
+ border-radius: 3px;
148
+ white-space: normal;
149
+ z-index: 10003;
261
150
  pointer-events: none;
262
- border: 2px solid var(--zg-border-selected);
263
- background: var(--zg-bg-selected);
264
- opacity: 0.3;
265
- z-index: 1;
266
- }
267
-
268
- /* Loading state */
269
- .zg-grid.is-loading {
270
- cursor: wait;
271
- opacity: 0.7;
272
- }
273
-
274
- .zg-grid.is-loading::after {
275
- content: '';
276
- position: absolute;
277
- top: 50%;
278
- left: 50%;
279
- width: 40px;
280
- height: 40px;
281
- margin: -20px 0 0 -20px;
282
- border: 4px solid var(--zg-border-color);
283
- border-top-color: var(--zg-border-active);
284
- border-radius: 50%;
285
- animation: zg-spin 0.8s linear infinite;
286
- }
287
-
288
- @keyframes zg-spin {
289
- to { transform: rotate(360deg); }
290
151
  }
291
152
 
292
153
  /* RTL support */
293
- [dir="rtl"] .zg-grid {
154
+ .zg-grid[dir='rtl'] {
294
155
  direction: rtl;
295
156
  }
296
157
 
297
- [dir="rtl"] .zg-cell {
158
+ .zg-grid[dir='rtl'] .zg-cell {
298
159
  box-shadow:
299
160
  inset 1px 0 0 0 var(--zg-border-color),
300
161
  inset 0 -1px 0 0 var(--zg-border-color);
301
162
  }
302
163
 
303
- [dir="rtl"] .zg-cell-number {
304
- justify-content: flex-start;
305
- text-align: left;
306
- }
307
-
308
- [dir="rtl"] .zg-row-header {
309
- left: auto;
310
- right: 0;
311
- border-right: none;
312
- border-left: 2px solid var(--zg-border-color);
313
- }
314
-
315
- /* Print styles */
316
- @media print {
317
- .zg-scroll-container {
318
- overflow: visible !important;
319
- }
320
-
321
- .zg-cell {
322
- page-break-inside: avoid;
323
- }
324
-
325
- .zg-grid {
326
- background: white !important;
327
- }
328
- }
329
-
330
- /* High contrast mode */
331
- @media (prefers-contrast: high) {
332
- .zg-cell {
333
- border-width: 2px;
334
- }
335
-
336
- .zg-cell-active,
337
- .zg-cell-editing {
338
- border-width: 3px;
339
- }
340
- }
341
-
342
- /* Reduced motion */
343
- @media (prefers-reduced-motion: reduce) {
344
- .zg-cell,
345
- .zg-grid::after {
346
- transition: none !important;
347
- animation: none !important;
348
- }
349
- }
350
-
351
- /* Accessibility - Screen reader only */
352
- .zg-sr-only {
353
- position: absolute;
354
- width: 1px;
355
- height: 1px;
356
- padding: 0;
357
- margin: -1px;
358
- overflow: hidden;
359
- clip: rect(0, 0, 0, 0);
360
- white-space: nowrap;
361
- border-width: 0;
362
- }
164
+ /* Dark theme - applied via ThemeManager inline CSS variables on container.
165
+ Legacy .zg-theme-dark class is still set for backwards compat but
166
+ no CSS overrides are needed here since the theme manager handles it. */
@@ -0,0 +1,60 @@
1
+ /**
2
+ * Column header — header row, header cells and the header select-all checkbox.
3
+ */
4
+
5
+ .zg-header {
6
+ position: absolute;
7
+ top: 0;
8
+ left: 0;
9
+ right: 0;
10
+ z-index: 10;
11
+ background: var(--zg-header-bg);
12
+ color: var(--zg-header-text);
13
+ font-weight: 600;
14
+ border-bottom: 2px solid var(--zg-border-color);
15
+ box-shadow: 0 1px 3px rgba(0,0,0,0.1);
16
+ overflow: hidden;
17
+ }
18
+
19
+ .zg-header-cells {
20
+ display: flex;
21
+ }
22
+
23
+ .zg-header-cell {
24
+ box-sizing: border-box;
25
+ padding: var(--zg-header-padding);
26
+ border-right: var(--zg-border-width) solid var(--zg-border-color);
27
+ display: flex;
28
+ align-items: center;
29
+ cursor: pointer;
30
+ background: var(--zg-header-bg);
31
+ color: var(--zg-header-text);
32
+ font-weight: 600;
33
+ white-space: nowrap;
34
+ overflow: hidden;
35
+ text-overflow: ellipsis;
36
+ }
37
+
38
+ .zg-header-cell:first-child {
39
+ border-left: var(--zg-border-width) solid var(--zg-border-color);
40
+ }
41
+
42
+ .zg-header-cell:hover {
43
+ background: var(--zg-hover-bg);
44
+ }
45
+
46
+ /* hideLastColumnBorder: match the body — the last header cell drops its own
47
+ right border so it doesn't double up against a bordered container. */
48
+ .zg-hide-last-col-border .zg-header-cell:last-child {
49
+ border-right-color: transparent;
50
+ }
51
+
52
+ /* Header checkbox */
53
+ .zg-header-checkbox {
54
+ justify-content: center;
55
+ }
56
+
57
+ .zg-header-checkbox-input {
58
+ cursor: pointer;
59
+ accent-color: var(--zg-selected-border);
60
+ }
@@ -0,0 +1,44 @@
1
+ /**
2
+ * Floating grid layers — selection overlay, focus ring, loading indicator,
3
+ * and the screen-reader-only helper.
4
+ */
5
+
6
+ /* Selection overlay */
7
+ .zg-selection-overlay {
8
+ position: absolute;
9
+ pointer-events: none;
10
+ border: 2px solid var(--zg-selected-border);
11
+ background: transparent;
12
+ z-index: 5;
13
+ }
14
+
15
+ /* Focus ring (separate element for virtual scrolling) */
16
+ .zg-focus-ring {
17
+ position: absolute;
18
+ pointer-events: none;
19
+ border: 2px solid var(--zg-focus-ring);
20
+ box-shadow: inset 0 0 0 1px #ffffff;
21
+ z-index: 6;
22
+ }
23
+
24
+ /* Loading indicator */
25
+ .zg-loading {
26
+ position: absolute;
27
+ top: 50%;
28
+ left: 50%;
29
+ transform: translate(-50%, -50%);
30
+ z-index: 100;
31
+ }
32
+
33
+ /* Accessibility - screen reader only */
34
+ .zg-sr-only {
35
+ position: absolute;
36
+ width: 1px;
37
+ height: 1px;
38
+ padding: 0;
39
+ margin: -1px;
40
+ overflow: hidden;
41
+ clip: rect(0, 0, 0, 0);
42
+ white-space: nowrap;
43
+ border-width: 0;
44
+ }
@@ -0,0 +1,86 @@
1
+ /**
2
+ * Design tokens — CSS custom properties consumed across all ZenGrid styles.
3
+ */
4
+ :root {
5
+ /* Grid dimensions */
6
+ --zg-row-height: 30px;
7
+ --zg-header-height: 35px;
8
+ --zg-col-width: 100px;
9
+
10
+ /* Colors - Background */
11
+ --zg-bg-primary: #ffffff;
12
+ --zg-bg-secondary: #f5f5f5;
13
+ --zg-bg-hover: #f0f4f8;
14
+ --zg-bg-selected: #e3f2fd;
15
+ --zg-bg-active: #ffffff;
16
+ --zg-bg-editing: #ffffff;
17
+ --zg-bg-disabled: #fafafa;
18
+
19
+ /* Colors - Border */
20
+ --zg-border-color: #e0e0e0;
21
+ --zg-border-active: #2196f3;
22
+ --zg-border-selected: #2196f3;
23
+ --zg-border-editing: #4caf50;
24
+ --zg-border-focus: #2196f3;
25
+
26
+ /* Colors - Text */
27
+ --zg-text-primary: #333333;
28
+ --zg-text-secondary: #666666;
29
+ --zg-text-disabled: #999999;
30
+ --zg-text-negative: #d32f2f;
31
+ --zg-text-link: #1976d2;
32
+
33
+ /* Colors - State */
34
+ --zg-state-success: #4caf50;
35
+ --zg-state-warning: #ff9800;
36
+ --zg-state-error: #f44336;
37
+ --zg-state-info: #2196f3;
38
+
39
+ /* Colors - Scrollbar */
40
+ --zg-scrollbar-thumb: rgba(0, 0, 0, 0.3);
41
+ --zg-scrollbar-thumb-hover: rgba(0, 0, 0, 0.5);
42
+
43
+ /* Spacing */
44
+ --zg-cell-padding-x: 8px;
45
+ --zg-cell-padding-y: 0;
46
+ --zg-header-padding: 12px;
47
+ --zg-border-width: 1px;
48
+
49
+ /* Typography */
50
+ --zg-font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, 'Helvetica Neue', Arial, sans-serif;
51
+ --zg-font-size: 14px;
52
+ --zg-line-height: 1.5;
53
+
54
+ /* Shadows */
55
+ --zg-shadow-sm: 0 1px 2px rgba(0, 0, 0, 0.05);
56
+ --zg-shadow-md: 0 2px 4px rgba(0, 0, 0, 0.1);
57
+ --zg-shadow-lg: 0 4px 8px rgba(0, 0, 0, 0.15);
58
+
59
+ /* Transitions */
60
+ --zg-transition-fast: 0.1s ease;
61
+ --zg-transition-normal: 0.2s ease;
62
+
63
+ /* Legacy aliases (backwards compat) */
64
+ --zg-bg-color: var(--zg-bg-primary);
65
+ --zg-text-color: var(--zg-text-primary);
66
+ --zg-header-bg: var(--zg-bg-secondary);
67
+ --zg-header-text: var(--zg-text-primary);
68
+ --zg-selected-bg: var(--zg-bg-selected);
69
+ --zg-selected-border: var(--zg-border-selected);
70
+ --zg-focus-ring: var(--zg-border-focus);
71
+ --zg-hover-bg: var(--zg-bg-hover);
72
+ --zg-cell-padding: var(--zg-cell-padding-y) var(--zg-cell-padding-x);
73
+
74
+ /* Calendar theming variables */
75
+ --zg-calendar-bg: var(--zg-bg-primary);
76
+ --zg-calendar-text: var(--zg-text-primary);
77
+ --zg-calendar-border: var(--zg-border-color);
78
+ --zg-calendar-header-bg: var(--zg-bg-secondary);
79
+ --zg-calendar-selected-bg: var(--zg-bg-selected);
80
+ --zg-calendar-selected-text: var(--zg-text-primary);
81
+ --zg-calendar-today-border: var(--zg-border-focus);
82
+ --zg-calendar-hover-bg: var(--zg-bg-hover);
83
+ --zg-calendar-disabled-text: var(--zg-text-disabled);
84
+ --zg-calendar-shadow: var(--zg-shadow-lg);
85
+ --zg-calendar-radius: 8px;
86
+ }