@svgrid/grid 3.0.7 → 3.0.9

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 (91) hide show
  1. package/README.md +1 -1
  2. package/dist/GridMenus.svelte +3 -2
  3. package/dist/SvGrid.controller.svelte.d.ts +60 -8
  4. package/dist/SvGrid.controller.svelte.js +490 -114
  5. package/dist/SvGrid.css +186 -3
  6. package/dist/SvGrid.svelte +285 -164
  7. package/dist/SvGrid.types.d.ts +24 -7
  8. package/dist/cdn/{GridMenus-CcwU8I4t.js → GridMenus-B1sipj6y.js} +165 -165
  9. package/dist/cdn/{GridMenus-BgUS-W3o.js → GridMenus-DlAzfHLk.js} +201 -201
  10. package/dist/cdn/server-block-cache-Dj-KPqEQ.js +1289 -0
  11. package/dist/cdn/{src-kE9B98r6.js → src-BYsa66I0.js} +9747 -10178
  12. package/dist/cdn/{src-25JmJ_7g.js → src-pA4RroLV.js} +10709 -11140
  13. package/dist/cdn/svgrid.js +27 -27
  14. package/dist/cdn/svgrid.svelte-external.js +27 -27
  15. package/dist/cdn/validate-XuMe4_KR.js +80 -0
  16. package/dist/cell-render.js +25 -3
  17. package/dist/columns.js +16 -1
  18. package/dist/conditional-formatting.js +9 -2
  19. package/dist/core.d.ts +93 -0
  20. package/dist/core.js +313 -47
  21. package/dist/filtering/excel-filters.js +41 -6
  22. package/dist/headless.d.ts +1 -1
  23. package/dist/headless.js +1 -1
  24. package/dist/index.d.ts +2 -1
  25. package/dist/index.js +2 -1
  26. package/dist/keyboard-handlers.js +5 -1
  27. package/dist/selection.d.ts +2 -2
  28. package/dist/selection.js +46 -12
  29. package/dist/server-block-cache.d.ts +7 -32
  30. package/dist/server-block-cache.js +21 -12
  31. package/dist/server-data-source.js +3 -1
  32. package/dist/server.d.ts +1 -0
  33. package/dist/server.js +1 -0
  34. package/dist/spreadsheet.js +7 -0
  35. package/dist/{subscribe.js → subscribe.svelte.js} +5 -1
  36. package/dist/validate.js +13 -14
  37. package/dist/virtualization/column-virtualizer.d.ts +4 -0
  38. package/dist/virtualization/column-virtualizer.js +2 -0
  39. package/dist/virtualization/types.d.ts +20 -0
  40. package/dist/virtualization/virtualizer.js +90 -24
  41. package/dist/windowed-brand.d.ts +22 -0
  42. package/dist/windowed-brand.js +60 -0
  43. package/dist/windowed-data.d.ts +6 -0
  44. package/dist/windowed-data.js +34 -0
  45. package/dist/windowed-row-model.d.ts +1 -0
  46. package/dist/windowed-row-model.js +97 -0
  47. package/package.json +1 -1
  48. package/src/GridMenus.svelte +3 -2
  49. package/src/SvGrid.controller.svelte.ts +483 -122
  50. package/src/SvGrid.css +186 -3
  51. package/src/SvGrid.svelte +285 -164
  52. package/src/SvGrid.types.ts +24 -7
  53. package/src/cell-render.ts +24 -2
  54. package/src/columns.ts +16 -1
  55. package/src/conditional-formatting.ts +6 -4
  56. package/src/core.sort.test.ts +61 -0
  57. package/src/core.ts +309 -49
  58. package/src/counting-cell.test.svelte +11 -0
  59. package/src/filtering/excel-filters.ts +39 -6
  60. package/src/headless.reactivity.svelte.test.ts +89 -0
  61. package/src/headless.ts +1 -1
  62. package/src/index.ts +7 -1
  63. package/src/keyboard-handlers.ts +5 -1
  64. package/src/new-features.test.ts +24 -0
  65. package/src/selection.test.ts +51 -0
  66. package/src/selection.ts +47 -14
  67. package/src/server-block-cache.ts +27 -10
  68. package/src/server-data-source.ts +3 -1
  69. package/src/server.ts +6 -0
  70. package/src/spreadsheet.ts +6 -0
  71. package/src/{subscribe.test.ts → subscribe.svelte.test.ts} +1 -1
  72. package/src/{subscribe.ts → subscribe.svelte.ts} +5 -1
  73. package/src/svgrid.behavior.test.ts +58 -0
  74. package/src/svgrid.column-cell-recycling.test.ts +120 -0
  75. package/src/svgrid.interaction.test.ts +4 -1
  76. package/src/svgrid.new-features.wrapper.test.ts +5 -4
  77. package/src/svgrid.pinned-column-virtualization.test.ts +162 -0
  78. package/src/svgrid.row-model-prop.svelte.test.ts +15 -3
  79. package/src/validate.test.ts +20 -4
  80. package/src/validate.ts +13 -16
  81. package/src/virtualization/column-virtualizer.ts +6 -0
  82. package/src/virtualization/types.ts +20 -0
  83. package/src/virtualization/virtualizer.test.ts +152 -0
  84. package/src/virtualization/virtualizer.ts +93 -27
  85. package/src/windowed-brand.ts +67 -0
  86. package/src/windowed-data.test.ts +105 -0
  87. package/src/windowed-data.ts +36 -0
  88. package/src/windowed-row-model.ts +113 -0
  89. package/dist/cdn/server-block-cache-DIqb3VZn.js +0 -241
  90. package/dist/cdn/validate-AZoD8BoR.js +0 -80
  91. /package/dist/{subscribe.d.ts → subscribe.svelte.d.ts} +0 -0
package/dist/SvGrid.css CHANGED
@@ -955,6 +955,15 @@
955
955
  .sv-grid-container {
956
956
  scrollbar-width: auto;
957
957
  -ms-overflow-style: auto;
958
+ /* An opaque background is what lets Chrome scroll the body on the
959
+ compositor. Without one, at fractional display scaling (110-125%,
960
+ where Chrome keeps LCD text), it did not composite this scroller: every
961
+ scroll frame repainted the rows on the main thread while the compositor
962
+ placed the sticky header, and the two drifted apart - the header shook
963
+ a few pixels up and down during a vertical scroll and showed the tops of
964
+ the letters behind it. Composited, rows and header move together. A
965
+ theme that sets a transparent `--sg-bg` keeps the old behaviour. */
966
+ background-color: var(--sg-bg, #fff);
958
967
  /* Trap wheel scroll inside the grid. Without this, hitting the top
959
968
  * or bottom edge of the grid lets the wheel event chain to the
960
969
  * outer page (or any scrollable ancestor), so what feels like one
@@ -3213,9 +3222,14 @@ select.sv-grid-fr-editor {
3213
3222
  border-right-color: var(--sg-header-bg, #f1f5f9);
3214
3223
  }
3215
3224
  /* The detail-toggle gutter fuses with the row numbers the same way; only
3216
- its own right edge keeps a line, between the chrome and the data. */
3217
- .sv-grid-row-number-cell:has(+ .sv-grid-detail-toggle-cell),
3218
- .sv-grid-row-number-column:has(+ .sv-grid-detail-toggle-column) {
3225
+ its own right edge keeps a line, between the chrome and the data. The
3226
+ table carries a class for "row numbers directly before the toggle" (no
3227
+ selection column between them). This was `:has(+ .sv-grid-detail-toggle-cell)`,
3228
+ and a sibling `:has()` makes Chrome restyle every cell of a row whenever a
3229
+ cell is added to or taken out of it: each horizontal column move restyled
3230
+ ~1,500 elements (8 ms) instead of ~400 (3 ms) in a grid with row numbers. */
3231
+ .sv-grid-numbers-beside-toggle .sv-grid-row-number-cell,
3232
+ .sv-grid-numbers-beside-toggle .sv-grid-row-number-column {
3219
3233
  border-right-color: var(--sg-header-bg, #f1f5f9);
3220
3234
  }
3221
3235
 
@@ -3496,3 +3510,172 @@ select.sv-grid-fr-editor {
3496
3510
  .sv-grid-chart-tab.is-active .sv-grid-chart-tab-label { color: var(--sg-accent, #2563eb); }
3497
3511
  .sv-grid-chart-tab-x { border: 0; background: transparent; color: var(--sg-muted, #64748b); font-size: 14px; line-height: 1; padding: 0 6px 0 2px; cursor: pointer; }
3498
3512
  .sv-grid-chart-tab-x:hover { color: var(--sg-fg, #0f172a); }
3513
+
3514
+ /* ===========================================================================
3515
+ Flex rows (`.sv-grid-table-flex`, the default; see the `rowLayout` prop).
3516
+ A table marked `data-row-layout="table"` (spreadsheetLayout, whose
3517
+ merges are DOM colspan / rowspan) keeps table layout.
3518
+
3519
+ Every row is a flex line of fixed-width cells instead of a table row. The
3520
+ cells already carry their width inline, so the columns line up the same;
3521
+ what changes is the cost of a change. A table lays every row out again
3522
+ when one cell is added or removed (a horizontal scroll adds a column of
3523
+ cells per frame): ~7 ms of layout a frame on a wide grid. A flex row lays
3524
+ out its own cells only: ~1.5 ms. Table layout stays available for what
3525
+ only a table can draw - a merged cell spanning rows - and the grid picks it
3526
+ automatically then.
3527
+
3528
+ Every selector walks the grid's own structure with child combinators
3529
+ (table > section > tr > cell): a table inside a detail panel or a cell,
3530
+ or a nested grid, keeps its own layout.
3531
+ =========================================================================== */
3532
+ .sv-grid-table-flex:not([data-row-layout="table"]),
3533
+ .sv-grid-table-flex:not([data-row-layout="table"]) > :is(thead, tbody, tfoot) {
3534
+ display: block;
3535
+ }
3536
+ .sv-grid-table-flex:not([data-row-layout="table"]) > :is(thead, tbody, tfoot) > tr {
3537
+ display: flex;
3538
+ }
3539
+ /* A collapsed row (a sheet's hidden or filtered row) leaves the flow, as it
3540
+ does in table layout. The rule above outranks .sv-grid-row-collapsed, and
3541
+ a 0px flex row still paints its cells' bottom border 1px into the next. */
3542
+ .sv-grid-table-flex:not([data-row-layout="table"]) > tbody > tr.sv-grid-row-collapsed {
3543
+ display: none;
3544
+ }
3545
+ /* Rows are not contained by default. Each body row used to be its own
3546
+ layout and paint island (`contain: layout paint`), so a scroll frame
3547
+ re-recorded only the rows that changed. Once the body scrolled on the
3548
+ compositor (the scroller's own background) that saving was gone, and
3549
+ every contained row was a separate clipped piece of paint Chrome sorted
3550
+ into layers again on each frame: layerize took 4-7x longer, and a
3551
+ horizontal wheel scroll of the 1M-row x 1,000-column demo about twice the
3552
+ main-thread work. An app can still opt in with --sg-row-contain. */
3553
+ .sv-grid-table-flex:not([data-row-layout="table"]) > tbody > tr {
3554
+ contain: var(--sg-row-contain, none);
3555
+ }
3556
+ /* Cells: a fixed-width flex item each, centring what they hold vertically
3557
+ the way a table cell's `vertical-align: middle` did. */
3558
+ .sv-grid-table-flex:not([data-row-layout="table"]) > :is(thead, tbody, tfoot) > tr > :is(td, th) {
3559
+ display: flex;
3560
+ flex: none;
3561
+ }
3562
+ /* Zero specificity, so `.my-grid .sv-grid-cell { align-items: flex-start }`
3563
+ re-aligns cells (docs/help/rows/styling-rows.md). */
3564
+ :where(.sv-grid-table-flex:not([data-row-layout="table"]) > :is(thead, tbody, tfoot) > tr > :is(td, th)) {
3565
+ align-items: center;
3566
+ }
3567
+ /* What a cell holds may shrink below its content's width, so the cell clips
3568
+ and ellipsizes it rather than overflowing. Named by class, not `> *`: a
3569
+ universal right-hand selector is tested against every element on each
3570
+ style recalc, which cost ~0.5 ms a frame of vertical scroll. Outside a flex
3571
+ row `min-width: 0` is already the computed default, so these rules are
3572
+ unscoped. */
3573
+ .sv-grid-header-cell,
3574
+ .sv-grid-filter-row-control,
3575
+ .sv-grid-row-number-head,
3576
+ .sv-grid-group-content,
3577
+ .sv-grid-cf-content {
3578
+ min-width: 0;
3579
+ }
3580
+ /* `th` is centred by the user-agent sheet (`text-align: center`); flex items
3581
+ follow `justify-content` instead. */
3582
+ .sv-grid-table-flex:not([data-row-layout="table"]) > :is(thead, tbody, tfoot) > tr > th {
3583
+ justify-content: center;
3584
+ }
3585
+ /* A header cell's inline content used to sit on a line box, whose height
3586
+ (the inherited line-height) set the cell's minimum height; a flex cell has
3587
+ no line box, so a band like the column-group row shrank from 33px to 20px.
3588
+ A zero-width text strut puts the line height back. `:where` keeps it at
3589
+ the lowest specificity, so the drag-indicator ::before rules replace it. */
3590
+ :where(.sv-grid-table-flex:not([data-row-layout="table"]) > :is(thead, tbody, tfoot) > tr > th)::before {
3591
+ content: "\200b";
3592
+ width: 0;
3593
+ overflow: hidden;
3594
+ }
3595
+ /* A cell's text sits in its own span so the ellipsis still works: a flex
3596
+ container cannot clip and ellipsize a bare text node. The span takes the
3597
+ cell's width, so `text-align` keeps aligning it. */
3598
+ .sv-grid-cell-text {
3599
+ min-width: 0;
3600
+ overflow: hidden;
3601
+ text-overflow: ellipsis;
3602
+ white-space: inherit;
3603
+ }
3604
+ .sv-grid-table-flex:not([data-row-layout="table"]) > :is(thead, tbody, tfoot) > tr > :is(td, th) .sv-grid-cell-text,
3605
+ .sv-grid-table-flex:not([data-row-layout="table"]) > :is(thead, tbody, tfoot) > tr > td > .sv-grid-cf-content {
3606
+ flex: 1 1 auto;
3607
+ }
3608
+ .sv-grid-table-flex:not([data-row-layout="table"]) > :is(thead, tbody, tfoot) > tr > td > .sv-grid-cf-content {
3609
+ overflow: hidden;
3610
+ text-overflow: ellipsis;
3611
+ }
3612
+ /* Non-text content (checkbox, chips, icons) follows the column alignment.
3613
+ `right` is physical, like the `text-align: right` it stands beside, so a
3614
+ right-aligned column stays right under `dir="rtl"`. */
3615
+ .sv-grid-table-flex:not([data-row-layout="table"]) > :is(thead, tbody, tfoot) > tr > .sv-grid-cell[data-align="right"] {
3616
+ justify-content: right;
3617
+ }
3618
+ .sv-grid-table-flex:not([data-row-layout="table"]) > :is(thead, tbody, tfoot) > tr > :is(
3619
+ .sv-grid-cell[data-align="center"],
3620
+ .sv-grid-selection-cell,
3621
+ .sv-grid-selection-column,
3622
+ .sv-grid-detail-toggle-cell,
3623
+ .sv-grid-detail-toggle-column
3624
+ ) {
3625
+ justify-content: center;
3626
+ }
3627
+ /* The header cell's content fills it, and so does the row-number corner, so
3628
+ a `text-align` set on the header cell (an app re-centring its headers)
3629
+ still places them. */
3630
+ .sv-grid-table-flex:not([data-row-layout="table"]) > thead > tr > th > :is(.sv-grid-header-cell, .sv-grid-row-number-head) {
3631
+ flex: 1 1 auto;
3632
+ }
3633
+ /* A cell that spans the whole row (a group banner, a detail panel, a failed
3634
+ block's message) has no width of its own: it fills the row. A merged cell
3635
+ spans columns too, but carries its own width. */
3636
+ .sv-grid-table-flex:not([data-row-layout="table"]) > tbody > tr > td[colspan]:not([data-merge-origin]) {
3637
+ flex: 1 1 auto;
3638
+ min-width: 0;
3639
+ }
3640
+ .sv-grid-table-flex:not([data-row-layout="table"]) > tbody > tr > td.sv-grid-detail-cell {
3641
+ display: block;
3642
+ }
3643
+ .sv-grid-table-flex:not([data-row-layout="table"]) > tbody > tr > td.sv-grid-group-cell > .sv-grid-group-content {
3644
+ flex: 1 1 auto;
3645
+ }
3646
+ /* Pinned rows stick as a band: a sticky cell cannot leave its flex row, so
3647
+ the band's body is the sticky box instead of each cell. */
3648
+ .sv-grid-table-flex:not([data-row-layout="table"]) > tbody.sv-grid-pinned-top-body {
3649
+ position: sticky;
3650
+ top: var(--sg-thead-h, 36px);
3651
+ z-index: 4;
3652
+ }
3653
+ .sv-grid-table-flex:not([data-row-layout="table"]) > tbody.sv-grid-pinned-bottom-body {
3654
+ position: sticky;
3655
+ bottom: 0;
3656
+ z-index: 4;
3657
+ }
3658
+ .sv-grid-table-flex:not([data-row-layout="table"]) > tbody > .sv-grid-pinned-row > td {
3659
+ top: auto;
3660
+ bottom: auto;
3661
+ }
3662
+ /* A flex row is exactly as tall as its `height`, which is the row height the
3663
+ virtualizer places it at. A rule here used to turn that into a minimum, as
3664
+ a table row's is, so content taller than `rowHeight` grew the row; the
3665
+ virtualizer still placed every row at `rowHeight`, so the rows drifted and
3666
+ jumped while scrolling (the 1M-row demo: 25 px rows placed as 18). Taller
3667
+ content is clipped by its cell now; `autoRowHeight` is the way to let rows
3668
+ grow. */
3669
+ /* A body cell's content line (see the bodyRow snippet). Block-level, so the
3670
+ inline content in it sits on one line box exactly as it did directly in a
3671
+ table cell; it carries the ellipsis and takes the cell's text-align. */
3672
+ .sv-grid-cell-line {
3673
+ display: block;
3674
+ min-width: 0;
3675
+ overflow: hidden;
3676
+ text-overflow: ellipsis;
3677
+ white-space: inherit;
3678
+ }
3679
+ .sv-grid-table-flex:not([data-row-layout="table"]) > :is(thead, tbody, tfoot) > tr > td > .sv-grid-cell-line {
3680
+ flex: 1 1 auto;
3681
+ }