@svgrid/grid 1.1.0 → 1.1.2

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 (148) hide show
  1. package/dist/FlexRender.svelte +96 -96
  2. package/dist/GridMenus.svelte +205 -127
  3. package/dist/SvGrid.controller.svelte.d.ts +44 -1
  4. package/dist/SvGrid.controller.svelte.js +240 -44
  5. package/dist/SvGrid.css +325 -22
  6. package/dist/SvGrid.helpers.test.d.ts +1 -0
  7. package/dist/SvGrid.helpers.test.js +298 -0
  8. package/dist/SvGrid.svelte +729 -203
  9. package/dist/SvGrid.types.d.ts +91 -4
  10. package/dist/aligned-grids.d.ts +6 -0
  11. package/dist/aligned-grids.js +84 -0
  12. package/dist/aligned-grids.test.d.ts +1 -0
  13. package/dist/aligned-grids.test.js +75 -0
  14. package/dist/build-api.coverage.test.d.ts +20 -0
  15. package/dist/build-api.coverage.test.js +505 -0
  16. package/dist/build-api.js +61 -31
  17. package/dist/cell-render.test.d.ts +1 -0
  18. package/dist/cell-render.test.js +338 -0
  19. package/dist/cell-values.d.ts +1 -1
  20. package/dist/cell-values.js +7 -7
  21. package/dist/chart-export.test.d.ts +1 -0
  22. package/dist/chart-export.test.js +302 -0
  23. package/dist/chart.coverage.test.d.ts +1 -0
  24. package/dist/chart.coverage.test.js +748 -0
  25. package/dist/clipboard.js +88 -24
  26. package/dist/clipboard.test.d.ts +1 -0
  27. package/dist/clipboard.test.js +700 -0
  28. package/dist/collaboration.coverage.test.d.ts +1 -0
  29. package/dist/collaboration.coverage.test.js +200 -0
  30. package/dist/column-groups.d.ts +19 -0
  31. package/dist/column-groups.js +62 -0
  32. package/dist/column-groups.test.d.ts +1 -0
  33. package/dist/column-groups.test.js +56 -0
  34. package/dist/column-types.d.ts +10 -0
  35. package/dist/column-types.js +63 -0
  36. package/dist/column-types.test.d.ts +1 -0
  37. package/dist/column-types.test.js +62 -0
  38. package/dist/columns.test.d.ts +1 -0
  39. package/dist/columns.test.js +625 -0
  40. package/dist/core.d.ts +86 -1
  41. package/dist/core.js +2 -2
  42. package/dist/editing.d.ts +7 -0
  43. package/dist/editing.js +191 -5
  44. package/dist/editing.test.d.ts +1 -0
  45. package/dist/editing.test.js +732 -0
  46. package/dist/editors/cell-editors.coverage.test.d.ts +1 -0
  47. package/dist/editors/cell-editors.coverage.test.js +139 -0
  48. package/dist/facet-buckets.test.d.ts +1 -0
  49. package/dist/facet-buckets.test.js +296 -0
  50. package/dist/filter-operators.test.d.ts +1 -0
  51. package/dist/filter-operators.test.js +135 -0
  52. package/dist/hyperformula-adapter.test.d.ts +1 -0
  53. package/dist/hyperformula-adapter.test.js +205 -0
  54. package/dist/index.d.ts +5 -2
  55. package/dist/index.js +4 -1
  56. package/dist/keyboard-handlers.coverage.test.d.ts +1 -0
  57. package/dist/keyboard-handlers.coverage.test.js +495 -0
  58. package/dist/keyboard-handlers.js +7 -2
  59. package/dist/menus.js +1 -0
  60. package/dist/menus.test.d.ts +1 -0
  61. package/dist/menus.test.js +560 -0
  62. package/dist/named-views.coverage.test.d.ts +1 -0
  63. package/dist/named-views.coverage.test.js +180 -0
  64. package/dist/row-drag.d.ts +49 -0
  65. package/dist/row-drag.js +221 -0
  66. package/dist/row-drag.test.d.ts +1 -0
  67. package/dist/row-drag.test.js +142 -0
  68. package/dist/row-resize.test.d.ts +1 -0
  69. package/dist/row-resize.test.js +329 -0
  70. package/dist/scroll-sync.js +3 -0
  71. package/dist/scroll-sync.test.d.ts +1 -0
  72. package/dist/scroll-sync.test.js +290 -0
  73. package/dist/selection.d.ts +7 -1
  74. package/dist/selection.js +76 -36
  75. package/dist/selection.multi-range.test.d.ts +1 -0
  76. package/dist/selection.multi-range.test.js +55 -0
  77. package/dist/selection.test.d.ts +1 -0
  78. package/dist/selection.test.js +647 -0
  79. package/dist/server-data-source.coverage.test.d.ts +1 -0
  80. package/dist/server-data-source.coverage.test.js +154 -0
  81. package/dist/spreadsheet.d.ts +30 -0
  82. package/dist/spreadsheet.js +48 -0
  83. package/dist/spreadsheet.test.d.ts +1 -0
  84. package/dist/spreadsheet.test.js +446 -0
  85. package/dist/summaries.js +4 -4
  86. package/dist/sv-grid-scrollbar.js +13 -1
  87. package/dist/svgrid-wrapper.types.d.ts +19 -0
  88. package/dist/svgrid.behavior.test.js +20 -0
  89. package/dist/svgrid.interaction.test.js +31 -0
  90. package/dist/svgrid.new-features.wrapper.test.js +34 -2
  91. package/dist/test-setup.js +9 -3
  92. package/dist/virtualization/scroll-scaling.d.ts +17 -0
  93. package/dist/virtualization/scroll-scaling.js +35 -0
  94. package/dist/virtualization/scroll-scaling.test.js +42 -1
  95. package/package.json +2 -1
  96. package/src/FlexRender.svelte +96 -96
  97. package/src/GridMenus.svelte +205 -127
  98. package/src/SvGrid.controller.svelte.ts +204 -36
  99. package/src/SvGrid.css +277 -12
  100. package/src/SvGrid.svelte +727 -205
  101. package/src/SvGrid.types.ts +85 -4
  102. package/src/a11y.contract.test.ts +49 -49
  103. package/src/a11y.test.ts +59 -59
  104. package/src/a11y.ts +59 -59
  105. package/src/aligned-grids.test.ts +80 -0
  106. package/src/aligned-grids.ts +87 -0
  107. package/src/build-api.ts +43 -23
  108. package/src/cell-formatting.ts +169 -169
  109. package/src/cell-values.ts +4 -4
  110. package/src/clipboard.test.ts +49 -0
  111. package/src/clipboard.ts +51 -23
  112. package/src/column-groups.test.ts +59 -0
  113. package/src/column-groups.ts +80 -0
  114. package/src/column-types.test.ts +68 -0
  115. package/src/column-types.ts +82 -0
  116. package/src/core.performance.test.ts +30 -30
  117. package/src/core.ts +1077 -999
  118. package/src/createGrid.svelte.ts +42 -42
  119. package/src/createGrid.test.ts +10 -10
  120. package/src/createGridState.svelte.ts +17 -17
  121. package/src/editing.ts +161 -5
  122. package/src/flex-render.ts +3 -3
  123. package/src/index.ts +208 -196
  124. package/src/keyboard.test.ts +59 -59
  125. package/src/keyboard.ts +97 -97
  126. package/src/menus.ts +1 -0
  127. package/src/merge-objects.ts +48 -48
  128. package/src/render-component.ts +28 -28
  129. package/src/row-drag.test.ts +168 -0
  130. package/src/row-drag.ts +255 -0
  131. package/src/scroll-sync.ts +2 -0
  132. package/src/selection.multi-range.test.ts +61 -0
  133. package/src/selection.ts +71 -37
  134. package/src/spreadsheet.test.ts +46 -2
  135. package/src/spreadsheet.ts +58 -0
  136. package/src/static-functions.ts +11 -11
  137. package/src/subscribe.ts +38 -38
  138. package/src/summaries.ts +4 -4
  139. package/src/svgrid-wrapper.types.ts +412 -393
  140. package/src/svgrid.features.test.ts +157 -157
  141. package/src/svgrid.new-features.wrapper.test.ts +2 -2
  142. package/src/svgrid.wrapper.test.ts +40 -40
  143. package/src/virtualization/column-virtualizer.test.ts +27 -27
  144. package/src/virtualization/column-virtualizer.ts +30 -30
  145. package/src/virtualization/svelte-virtualizer.svelte.ts +26 -26
  146. package/src/virtualization/types.ts +30 -30
  147. package/src/virtualization/virtualizer.test.ts +47 -47
  148. package/src/virtualization/virtualizer.ts +296 -296
package/dist/SvGrid.css CHANGED
@@ -90,33 +90,48 @@
90
90
  100% { background-position: -200% 0; }
91
91
  }
92
92
 
93
- .sv-grid-tool-panel-toggle {
94
- position: absolute;
95
- top: 6px;
96
- right: 6px;
97
- z-index: 21;
93
+ /* Grid toolbar strip above the shell - hosts the tool-panel trigger (and is a
94
+ natural home for future grid-level actions). */
95
+ .sv-grid-toolbar {
96
+ display: flex;
97
+ align-items: center;
98
+ gap: 8px;
99
+ padding: 6px 2px;
100
+ }
101
+ .sv-grid-toolbar-btn {
98
102
  display: inline-flex;
99
103
  align-items: center;
100
- justify-content: center;
101
- width: 30px;
102
- height: 30px;
104
+ gap: 6px;
105
+ padding: 6px 12px;
103
106
  border: 1px solid var(--sg-border, #e2e8f0);
104
107
  border-radius: var(--sg-radius, 6px);
105
108
  background: var(--sg-bg, #fff);
106
- color: var(--sg-muted, #64748b);
109
+ color: var(--sg-fg, #0f172a);
110
+ font-size: 12.5px;
111
+ font-weight: 600;
107
112
  cursor: pointer;
113
+ transition: background-color 120ms ease, color 120ms ease, border-color 120ms ease;
108
114
  }
109
- .sv-grid-tool-panel-toggle:hover,
110
- .sv-grid-tool-panel-toggle.is-open {
115
+ .sv-grid-toolbar-btn:hover {
116
+ border-color: var(--sg-accent, #2563eb);
111
117
  color: var(--sg-accent, #2563eb);
118
+ }
119
+ .sv-grid-toolbar-btn.is-active {
120
+ background: var(--sg-accent, #2563eb);
112
121
  border-color: var(--sg-accent, #2563eb);
122
+ color: #fff;
113
123
  }
114
124
  .sv-grid-tool-panel {
115
125
  position: absolute;
116
126
  top: 0;
117
127
  right: 0;
118
128
  bottom: 0;
119
- z-index: 20;
129
+ /* Above the grid's sticky header (z-index 30) and custom scrollbars (z ~900)
130
+ so the docked panel fully overlays the grid instead of the header/right
131
+ columns bleeding through its top-right. Ties the menu layer (901) but the
132
+ menus render later in the DOM, so a column menu opened over the panel still
133
+ wins. */
134
+ z-index: 901;
120
135
  width: 250px;
121
136
  display: flex;
122
137
  flex-direction: column;
@@ -205,6 +220,83 @@
205
220
  opacity: 0.35;
206
221
  cursor: default;
207
222
  }
223
+ /* Tool-panel tab bar (Columns | Filters) */
224
+ .sv-grid-tool-panel-tabs {
225
+ display: flex;
226
+ gap: 2px;
227
+ padding: 6px 6px 0;
228
+ border-bottom: 1px solid var(--sg-border, #e2e8f0);
229
+ }
230
+ .sv-grid-tool-panel-tab {
231
+ flex: 1;
232
+ padding: 6px 8px;
233
+ border: 0;
234
+ border-bottom: 2px solid transparent;
235
+ background: transparent;
236
+ color: var(--sg-muted, #64748b);
237
+ font-size: 12px;
238
+ font-weight: 600;
239
+ cursor: pointer;
240
+ }
241
+ .sv-grid-tool-panel-tab:hover {
242
+ color: var(--sg-fg, #0f172a);
243
+ }
244
+ .sv-grid-tool-panel-tab.is-active {
245
+ color: var(--sg-accent, #2563eb);
246
+ border-bottom-color: var(--sg-accent, #2563eb);
247
+ }
248
+ /* Filters tab: one control block per filterable column */
249
+ .sv-grid-tool-panel-filters {
250
+ padding: 6px;
251
+ overflow-y: auto;
252
+ flex: 1;
253
+ display: flex;
254
+ flex-direction: column;
255
+ gap: 8px;
256
+ }
257
+ .sv-grid-tp-filter {
258
+ display: flex;
259
+ flex-direction: column;
260
+ gap: 4px;
261
+ padding: 6px;
262
+ border: 1px solid var(--sg-border, #e2e8f0);
263
+ border-radius: 6px;
264
+ }
265
+ .sv-grid-tp-filter.is-filtered {
266
+ border-color: var(--sg-accent, #2563eb);
267
+ }
268
+ .sv-grid-tp-filter-head {
269
+ display: flex;
270
+ align-items: center;
271
+ justify-content: space-between;
272
+ }
273
+ .sv-grid-tp-filter-name {
274
+ font-size: 12px;
275
+ font-weight: 600;
276
+ color: var(--sg-fg, #0f172a);
277
+ }
278
+ .sv-grid-tp-filter-clear {
279
+ border: 0;
280
+ background: transparent;
281
+ color: var(--sg-muted, #64748b);
282
+ font-size: 11px;
283
+ cursor: pointer;
284
+ padding: 0 2px;
285
+ }
286
+ .sv-grid-tp-filter-clear:hover {
287
+ color: var(--sg-accent, #2563eb);
288
+ }
289
+ .sv-grid-tp-filter-op,
290
+ .sv-grid-tp-filter-input {
291
+ width: 100%;
292
+ box-sizing: border-box;
293
+ padding: 4px 6px;
294
+ font-size: 12px;
295
+ border: 1px solid var(--sg-border, #e2e8f0);
296
+ border-radius: 5px;
297
+ background: var(--sg-bg, #fff);
298
+ color: var(--sg-fg, #0f172a);
299
+ }
208
300
  /* Root wrapper fill mode: only takes effect when consumer passes
209
301
  * containerHeight='100%'. The shell becomes a flex item that expands
210
302
  * while the pager keeps its natural height. */
@@ -311,6 +403,14 @@
311
403
  background: var(--sg-pinned-header-bg, color-mix(in oklab, var(--sg-header-bg, #f1f5f9) 60%, var(--sg-accent, #2563eb) 14%));
312
404
  font-weight: 600;
313
405
  }
406
+ /* Zebra striping, opt-in via the `zebraRows` prop (which adds
407
+ `.sv-grid-row-alt` to alternating DATA rows only - pinned, group,
408
+ detail, and summary rows never get the class, so they keep a single
409
+ background). This rule sits before `.sv-grid-row-selected` /
410
+ `:hover` so those states paint over the stripe. */
411
+ .sv-grid-row-alt > .sv-grid-cell {
412
+ background: var(--sg-row-alt-bg, #f8fafc);
413
+ }
314
414
  /* Zebra rows: keep the pinned tint visible (don't let the row-alt
315
415
  background bleed through) by re-painting the pinned cells. */
316
416
  .sv-grid-row-alt > .sv-grid-cell[data-pinned] {
@@ -380,7 +480,7 @@
380
480
 
381
481
  .sv-grid-resize-handle:hover,
382
482
  .sv-grid-resize-handle.is-resizing {
383
- background: rgba(11, 99, 243, 0.3);
483
+ background: color-mix(in srgb, var(--sg-accent, #0b63f3) 30%, transparent);
384
484
  }
385
485
 
386
486
  /* Row resize handle (counterpart of the column resize handle). Lives
@@ -395,7 +495,7 @@
395
495
  }
396
496
  .sv-grid-row-resize-handle:hover,
397
497
  .sv-grid-row-resize-handle.is-resizing {
398
- background: rgba(11, 99, 243, 0.3);
498
+ background: color-mix(in srgb, var(--sg-accent, #0b63f3) 30%, transparent);
399
499
  }
400
500
 
401
501
  .sv-grid-head {
@@ -409,6 +509,22 @@
409
509
  z-index: 35;
410
510
  background: var(--sg-header-bg, #f5f7fb);
411
511
  }
512
+ /* Column-header cells take the header background (and header foreground)
513
+ so the header row paints as a solid band rather than body-colored
514
+ cells over the sticky header strip. Together with the row-number
515
+ gutter below - which uses the same --sg-header-bg - the column headers
516
+ and row headers read as one continuous header chrome. */
517
+ .sv-grid-head .sv-grid-column {
518
+ background: var(--sg-header-bg, #f5f7fb);
519
+ /* Header typography is themeable so each design-system preset can match
520
+ its real grid header (e.g. Excel bold, Atlassian uppercase + subtle,
521
+ shadcn medium + muted). The label/sort-button inherit these. */
522
+ color: var(--sg-header-label-color, var(--sg-header-fg, var(--sg-fg, #0f172a)));
523
+ font-weight: var(--sg-header-weight, 600);
524
+ font-size: var(--sg-header-size, inherit);
525
+ text-transform: var(--sg-header-transform, none);
526
+ letter-spacing: var(--sg-header-tracking, normal);
527
+ }
412
528
 
413
529
  /* Header drag-to-reorder. The `draggable` attribute is only set
414
530
  * when `enableColumnReorder` is true, so the cursor and drop
@@ -435,6 +551,48 @@
435
551
  .sv-grid-column.is-drag-target-after::after { right: -2px; }
436
552
  @keyframes sg-drop-pulse { from { opacity: 0.55; } to { opacity: 1; } }
437
553
 
554
+ /* Managed row dragging ----------------------------------------------------- */
555
+ /* The whole row is the drag source; the row-number cell shows a grip so the
556
+ * affordance is discoverable. Pair `rowDragManaged` with `showRowNumbers` for
557
+ * the grip; without row numbers the grab cursor still hints it. */
558
+ .sv-grid-row-draggable { cursor: grab; }
559
+ .sv-grid-row-draggable:active { cursor: grabbing; }
560
+ .sv-grid-row-draggable .sv-grid-row-number-cell {
561
+ position: relative;
562
+ padding-left: 14px;
563
+ }
564
+ .sv-grid-row-draggable .sv-grid-row-number-cell::before {
565
+ content: "\2807"; /* braille grip glyph */
566
+ position: absolute;
567
+ left: 3px;
568
+ top: 50%;
569
+ transform: translateY(-50%);
570
+ font-size: 13px;
571
+ line-height: 1;
572
+ color: var(--sg-muted, #94a3b8);
573
+ opacity: 0.4;
574
+ transition: opacity 120ms ease;
575
+ pointer-events: none;
576
+ }
577
+ .sv-grid-row-draggable:hover .sv-grid-row-number-cell::before { opacity: 1; }
578
+
579
+ /* Default highlight for an external drop zone (use:rowDropZone) while a
580
+ matching row is dragged over it. Consumers can override the class. */
581
+ .sv-grid-row-dropzone-over {
582
+ outline: 2px dashed var(--sg-accent, #6366f1);
583
+ outline-offset: -2px;
584
+ background: color-mix(in srgb, var(--sg-accent, #6366f1) 10%, transparent);
585
+ }
586
+
587
+ /* Drop indicator: a glowing line on the row's top (before) or bottom (after)
588
+ * edge. Painted on the cells so it spans the full row across table layouts. */
589
+ .sv-grid-row-drop-before > td {
590
+ box-shadow: inset 0 2px 0 0 var(--sg-accent, #6366f1);
591
+ }
592
+ .sv-grid-row-drop-after > td {
593
+ box-shadow: inset 0 -2px 0 0 var(--sg-accent, #6366f1);
594
+ }
595
+
438
596
  /* Pinned rows (top / bottom). Each cell sticks individually so the
439
597
  * row tracks scroll on every browser. Top rows stick below the sticky
440
598
  * thead via --sg-thead-h; bottom rows stick to the bottom of the
@@ -490,6 +648,34 @@
490
648
  text-overflow: ellipsis;
491
649
  white-space: nowrap;
492
650
  }
651
+ /* Collapse toggle on a collapsible column group header. */
652
+ .sv-grid-group-toggle {
653
+ display: inline-flex;
654
+ align-items: center;
655
+ gap: 5px;
656
+ max-width: 100%;
657
+ border: 0;
658
+ background: transparent;
659
+ color: inherit;
660
+ font: inherit;
661
+ letter-spacing: inherit;
662
+ text-transform: inherit;
663
+ cursor: pointer;
664
+ padding: 2px 6px;
665
+ border-radius: 5px;
666
+ }
667
+ .sv-grid-group-toggle:hover {
668
+ background: color-mix(in srgb, var(--sg-accent, #2563eb) 12%, transparent);
669
+ color: var(--sg-accent, #2563eb);
670
+ }
671
+ .sv-grid-group-caret {
672
+ flex-shrink: 0;
673
+ transition: transform 140ms ease;
674
+ }
675
+ /* Collapsed: point the caret right (like a closed disclosure). */
676
+ .sv-grid-group-toggle.is-collapsed .sv-grid-group-caret {
677
+ transform: rotate(-90deg);
678
+ }
493
679
 
494
680
  .sv-grid-foot {
495
681
  position: sticky;
@@ -602,6 +788,9 @@
602
788
  position: sticky;
603
789
  left: 0;
604
790
  z-index: 4;
791
+ /* Match the column-header band so the row-number gutter and the column
792
+ headers form one continuous header chrome. */
793
+ background: var(--sg-header-bg, #f5f7fb);
605
794
  color: var(--sg-muted, #64748b);
606
795
  font-variant-numeric: tabular-nums;
607
796
  }
@@ -635,9 +824,9 @@
635
824
  animation: sv-grid-filter-pulse 700ms ease-out;
636
825
  }
637
826
  @keyframes sv-grid-filter-pulse {
638
- 0% { box-shadow: 0 0 0 0 rgba(11, 99, 243, 0.55); }
639
- 70% { box-shadow: 0 0 0 6px rgba(11, 99, 243, 0); }
640
- 100% { box-shadow: 0 0 0 0 rgba(11, 99, 243, 0); }
827
+ 0% { box-shadow: 0 0 0 0 color-mix(in srgb, var(--sg-accent, #0b63f3) 55%, transparent); }
828
+ 70% { box-shadow: 0 0 0 6px color-mix(in srgb, var(--sg-accent, #0b63f3) 0%, transparent); }
829
+ 100% { box-shadow: 0 0 0 0 color-mix(in srgb, var(--sg-accent, #0b63f3) 0%, transparent); }
641
830
  }
642
831
 
643
832
  .sv-grid-checkbox {
@@ -658,6 +847,23 @@
658
847
  background-color 120ms ease;
659
848
  }
660
849
 
850
+ /* Full-row editor: inline editors shown for every editable cell of a row
851
+ in full-row edit. Fill the cell so the row reads as a form line. */
852
+ .sv-grid-fr-editor {
853
+ width: 100%;
854
+ box-sizing: border-box;
855
+ }
856
+ select.sv-grid-fr-editor {
857
+ height: 100%;
858
+ min-height: 26px;
859
+ }
860
+ .sv-grid-fr-checkbox {
861
+ width: 16px;
862
+ height: 16px;
863
+ accent-color: var(--sg-accent, #3b82f6);
864
+ cursor: pointer;
865
+ }
866
+
661
867
  /* Color editor - native HTML color input filling the cell so the
662
868
  swatch is clickable across the whole cell area, not just the tiny
663
869
  OS default size. */
@@ -732,6 +938,19 @@
732
938
  pointer-events: none;
733
939
  }
734
940
 
941
+ /* Built-in cell flash (ColumnDef `cellFlash`). Theme-tinted fade; consumers
942
+ can pass their own class (e.g. up/down colouring) via `cellFlash.className`. */
943
+ @keyframes sv-grid-cell-flash-kf {
944
+ 0% { background-color: var(--sg-cell-flash, color-mix(in oklab, var(--sg-accent, #3b82f6) 42%, transparent)); }
945
+ 100% { background-color: transparent; }
946
+ }
947
+ .sv-grid-cell-flash {
948
+ animation: sv-grid-cell-flash-kf 0.7s ease-out;
949
+ }
950
+ @media (prefers-reduced-motion: reduce) {
951
+ .sv-grid-cell-flash { animation: none; }
952
+ }
953
+
735
954
  .sv-grid-cell-active,
736
955
  .sv-grid-cell-editing {
737
956
  position: relative;
@@ -802,12 +1021,18 @@
802
1021
  transform-origin: bottom right;
803
1022
  }
804
1023
 
805
- /* Fill-preview overlay paints a dashed accent border on the cells the
806
- user is about to fill. Source cells (still in the selection range)
807
- keep their normal range styling. */
1024
+ /* Fill-preview overlay paints an accent border on the cells the user is
1025
+ about to fill. Source cells (still in the selection range) keep their
1026
+ normal range styling. The border + tint derive from the theme accent
1027
+ (`--sg-accent`) so they match each theme instead of a fixed blue;
1028
+ `--sg-fill-preview-border` / `--sg-fill-preview-bg` let a theme override
1029
+ them directly. */
808
1030
  .sv-grid-cell[data-fill-preview="true"] {
809
- box-shadow: inset 0 0 0 2px rgba(11, 99, 243, 0.5);
810
- background: rgba(11, 99, 243, 0.08);
1031
+ box-shadow: inset 0 0 0 2px
1032
+ var(--sg-fill-preview-border,
1033
+ color-mix(in srgb, var(--sg-accent, #0b63f3) 50%, transparent));
1034
+ background: var(--sg-fill-preview-bg,
1035
+ color-mix(in srgb, var(--sg-accent, #0b63f3) 8%, transparent));
811
1036
  }
812
1037
 
813
1038
  .sv-grid-cell-editing {
@@ -1119,6 +1344,11 @@
1119
1344
  gap: 2px;
1120
1345
  width: 100%;
1121
1346
  min-width: 0;
1347
+ /* Themeable header height. Defaults to auto (content-driven); presets
1348
+ can set a taller header (e.g. Material's roomy data-table header).
1349
+ The component measures the rendered header height for sticky offsets,
1350
+ so this propagates to --sg-thead-h automatically. */
1351
+ min-height: var(--sg-header-min-height, auto);
1122
1352
  }
1123
1353
 
1124
1354
  .sv-grid-header-sort {
@@ -1287,6 +1517,32 @@
1287
1517
  .sv-grid-column-menu {
1288
1518
  width: 260px;
1289
1519
  }
1520
+ /* Column-menu tab bar (General / Filter / Columns). */
1521
+ .sv-grid-menu-tabs {
1522
+ display: flex;
1523
+ gap: 2px;
1524
+ margin: -2px -2px 4px;
1525
+ padding: 2px 2px 0;
1526
+ border-bottom: 1px solid var(--sg-border, #e2e8f0);
1527
+ }
1528
+ .sv-grid-menu-tab {
1529
+ flex: 1;
1530
+ padding: 6px 6px;
1531
+ border: 0;
1532
+ border-bottom: 2px solid transparent;
1533
+ background: transparent;
1534
+ color: var(--sg-muted, #64748b);
1535
+ font-size: 12px;
1536
+ font-weight: 600;
1537
+ cursor: pointer;
1538
+ }
1539
+ .sv-grid-menu-tab:hover {
1540
+ color: var(--sg-fg, #0f172a);
1541
+ }
1542
+ .sv-grid-menu-tab.is-active {
1543
+ color: var(--sg-accent, #2563eb);
1544
+ border-bottom-color: var(--sg-accent, #2563eb);
1545
+ }
1290
1546
 
1291
1547
  .sv-grid-operator-menu {
1292
1548
  width: 184px;
@@ -1449,6 +1705,53 @@
1449
1705
  font: inherit;
1450
1706
  }
1451
1707
 
1708
+ /* Multi-condition filter: AND/OR join toggle + add-condition button. */
1709
+ .sv-grid-menu-add-cond {
1710
+ align-self: flex-start;
1711
+ margin-top: 2px;
1712
+ padding: 3px 8px;
1713
+ font-size: 11.5px;
1714
+ font-weight: 600;
1715
+ color: var(--sg-accent, #3b82f6);
1716
+ background: transparent;
1717
+ border: 1px dashed var(--sg-border, #cbd5e1);
1718
+ border-radius: 5px;
1719
+ cursor: pointer;
1720
+ }
1721
+ .sv-grid-menu-add-cond:hover {
1722
+ background: color-mix(in oklab, var(--sg-accent, #3b82f6) 8%, transparent);
1723
+ border-style: solid;
1724
+ }
1725
+ .sv-grid-menu-join {
1726
+ display: inline-flex;
1727
+ align-items: center;
1728
+ gap: 2px;
1729
+ margin: 2px 0;
1730
+ }
1731
+ .sv-grid-menu-join button {
1732
+ padding: 2px 10px;
1733
+ font-size: 11px;
1734
+ font-weight: 700;
1735
+ color: var(--sg-muted, #64748b);
1736
+ background: transparent;
1737
+ border: 1px solid var(--sg-border, #cbd5e1);
1738
+ cursor: pointer;
1739
+ }
1740
+ .sv-grid-menu-join button:first-child { border-radius: 5px 0 0 5px; }
1741
+ .sv-grid-menu-join button:nth-child(2) { border-radius: 0; border-left: 0; }
1742
+ .sv-grid-menu-join button.is-on {
1743
+ background: var(--sg-accent, #3b82f6);
1744
+ color: #fff;
1745
+ border-color: var(--sg-accent, #3b82f6);
1746
+ }
1747
+ .sv-grid-menu-join-x {
1748
+ margin-left: auto;
1749
+ border-radius: 5px !important;
1750
+ font-size: 14px;
1751
+ line-height: 1;
1752
+ padding: 2px 7px !important;
1753
+ }
1754
+
1452
1755
  .sv-grid-facet-list {
1453
1756
  max-height: 200px;
1454
1757
  overflow: auto;
@@ -0,0 +1 @@
1
+ export {};