@svgrid/grid 1.0.2 → 1.1.1

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 (216) hide show
  1. package/LICENSE +1 -1
  2. package/README.md +137 -39
  3. package/dist/GridFooter.svelte +164 -0
  4. package/dist/GridFooter.svelte.d.ts +29 -0
  5. package/dist/GridMenus.svelte +648 -0
  6. package/dist/GridMenus.svelte.d.ts +31 -0
  7. package/dist/SvGrid.controller.svelte.d.ts +472 -0
  8. package/dist/SvGrid.controller.svelte.js +1917 -0
  9. package/dist/SvGrid.css +2012 -0
  10. package/dist/SvGrid.helpers.d.ts +35 -0
  11. package/dist/SvGrid.helpers.js +160 -0
  12. package/dist/SvGrid.helpers.test.d.ts +1 -0
  13. package/dist/SvGrid.helpers.test.js +298 -0
  14. package/dist/SvGrid.svelte +2346 -8742
  15. package/dist/SvGrid.svelte.d.ts +4 -357
  16. package/dist/SvGrid.types.d.ts +523 -0
  17. package/dist/SvGrid.types.js +1 -0
  18. package/dist/SvGridChart.svelte +1060 -23
  19. package/dist/SvGridChart.svelte.d.ts +17 -0
  20. package/dist/aligned-grids.d.ts +6 -0
  21. package/dist/aligned-grids.js +84 -0
  22. package/dist/aligned-grids.test.d.ts +1 -0
  23. package/dist/aligned-grids.test.js +75 -0
  24. package/dist/build-api.coverage.test.d.ts +20 -0
  25. package/dist/build-api.coverage.test.js +505 -0
  26. package/dist/build-api.d.ts +5 -0
  27. package/dist/build-api.js +557 -0
  28. package/dist/cell-render.d.ts +15 -0
  29. package/dist/cell-render.js +246 -0
  30. package/dist/cell-render.test.d.ts +1 -0
  31. package/dist/cell-render.test.js +338 -0
  32. package/dist/cell-values.d.ts +28 -0
  33. package/dist/cell-values.js +89 -0
  34. package/dist/chart-export.test.d.ts +1 -0
  35. package/dist/chart-export.test.js +302 -0
  36. package/dist/chart.coverage.test.d.ts +1 -0
  37. package/dist/chart.coverage.test.js +748 -0
  38. package/dist/chart.d.ts +370 -3
  39. package/dist/chart.js +1135 -42
  40. package/dist/clipboard.d.ts +15 -0
  41. package/dist/clipboard.js +420 -0
  42. package/dist/clipboard.test.d.ts +1 -0
  43. package/dist/clipboard.test.js +700 -0
  44. package/dist/collaboration.coverage.test.d.ts +1 -0
  45. package/dist/collaboration.coverage.test.js +200 -0
  46. package/dist/column-groups.d.ts +19 -0
  47. package/dist/column-groups.js +62 -0
  48. package/dist/column-groups.test.d.ts +1 -0
  49. package/dist/column-groups.test.js +56 -0
  50. package/dist/column-types.d.ts +10 -0
  51. package/dist/column-types.js +63 -0
  52. package/dist/column-types.test.d.ts +1 -0
  53. package/dist/column-types.test.js +62 -0
  54. package/dist/columns.d.ts +30 -0
  55. package/dist/columns.js +277 -0
  56. package/dist/columns.test.d.ts +1 -0
  57. package/dist/columns.test.js +625 -0
  58. package/dist/core.d.ts +86 -1
  59. package/dist/css.d.ts +3 -0
  60. package/dist/editing.d.ts +31 -0
  61. package/dist/editing.js +529 -0
  62. package/dist/editing.test.d.ts +1 -0
  63. package/dist/editing.test.js +732 -0
  64. package/dist/editors/cell-editors.coverage.test.d.ts +1 -0
  65. package/dist/editors/cell-editors.coverage.test.js +139 -0
  66. package/dist/editors/cell-editors.d.ts +1 -1
  67. package/dist/facet-buckets.d.ts +13 -0
  68. package/dist/facet-buckets.js +54 -0
  69. package/dist/facet-buckets.test.d.ts +1 -0
  70. package/dist/facet-buckets.test.js +296 -0
  71. package/dist/features.d.ts +5 -0
  72. package/dist/features.js +30 -0
  73. package/dist/filter-operators.d.ts +16 -0
  74. package/dist/filter-operators.js +69 -0
  75. package/dist/filter-operators.test.d.ts +1 -0
  76. package/dist/filter-operators.test.js +135 -0
  77. package/dist/hyperformula-adapter.d.ts +82 -0
  78. package/dist/hyperformula-adapter.js +73 -0
  79. package/dist/hyperformula-adapter.test.d.ts +1 -0
  80. package/dist/hyperformula-adapter.test.js +205 -0
  81. package/dist/index.d.ts +9 -3
  82. package/dist/index.js +8 -2
  83. package/dist/keyboard-handlers.coverage.test.d.ts +1 -0
  84. package/dist/keyboard-handlers.coverage.test.js +495 -0
  85. package/dist/keyboard-handlers.d.ts +7 -0
  86. package/dist/keyboard-handlers.js +202 -0
  87. package/dist/menus.d.ts +40 -0
  88. package/dist/menus.js +390 -0
  89. package/dist/menus.test.d.ts +1 -0
  90. package/dist/menus.test.js +560 -0
  91. package/dist/named-views.coverage.test.d.ts +1 -0
  92. package/dist/named-views.coverage.test.js +180 -0
  93. package/dist/named-views.d.ts +27 -0
  94. package/dist/named-views.js +39 -0
  95. package/dist/row-drag.d.ts +49 -0
  96. package/dist/row-drag.js +221 -0
  97. package/dist/row-drag.test.d.ts +1 -0
  98. package/dist/row-drag.test.js +142 -0
  99. package/dist/row-resize.d.ts +43 -0
  100. package/dist/row-resize.js +158 -0
  101. package/dist/row-resize.test.d.ts +1 -0
  102. package/dist/row-resize.test.js +329 -0
  103. package/dist/scroll-sync.d.ts +9 -0
  104. package/dist/scroll-sync.js +89 -0
  105. package/dist/scroll-sync.test.d.ts +1 -0
  106. package/dist/scroll-sync.test.js +290 -0
  107. package/dist/selection.d.ts +32 -0
  108. package/dist/selection.js +427 -0
  109. package/dist/selection.multi-range.test.d.ts +1 -0
  110. package/dist/selection.multi-range.test.js +55 -0
  111. package/dist/selection.test.d.ts +1 -0
  112. package/dist/selection.test.js +647 -0
  113. package/dist/server-data-source.coverage.test.d.ts +1 -0
  114. package/dist/server-data-source.coverage.test.js +154 -0
  115. package/dist/spreadsheet.d.ts +110 -0
  116. package/dist/spreadsheet.js +242 -0
  117. package/dist/spreadsheet.test.d.ts +1 -0
  118. package/dist/spreadsheet.test.js +446 -0
  119. package/dist/summaries.d.ts +12 -0
  120. package/dist/summaries.js +65 -0
  121. package/dist/sv-grid-scrollbar.js +13 -1
  122. package/dist/svgrid-wrapper.types.d.ts +31 -1
  123. package/dist/svgrid.behavior.test.js +20 -0
  124. package/dist/svgrid.comments-autocomplete.test.d.ts +1 -0
  125. package/dist/svgrid.comments-autocomplete.test.js +96 -0
  126. package/dist/svgrid.context-menu.test.d.ts +1 -0
  127. package/dist/svgrid.context-menu.test.js +102 -0
  128. package/dist/svgrid.interaction.test.js +31 -0
  129. package/dist/svgrid.new-features.wrapper.test.js +64 -6
  130. package/dist/svgrid.wrapper.test.js +27 -1
  131. package/dist/test-setup.js +9 -3
  132. package/dist/virtualization/column-virtualizer.d.ts +2 -0
  133. package/dist/virtualization/scroll-scaling.d.ts +45 -0
  134. package/dist/virtualization/scroll-scaling.js +99 -0
  135. package/dist/virtualization/scroll-scaling.test.d.ts +1 -0
  136. package/dist/virtualization/scroll-scaling.test.js +127 -0
  137. package/dist/virtualization/svelte-virtualizer.svelte.d.ts +2 -0
  138. package/dist/virtualization/svelte-virtualizer.svelte.js +2 -0
  139. package/dist/virtualization/virtualizer.d.ts +7 -0
  140. package/dist/virtualization/virtualizer.js +30 -0
  141. package/package.json +2 -1
  142. package/src/GridFooter.svelte +164 -0
  143. package/src/GridMenus.svelte +648 -0
  144. package/src/SvGrid.controller.svelte.ts +2352 -0
  145. package/src/SvGrid.css +2012 -0
  146. package/src/SvGrid.helpers.test.ts +415 -0
  147. package/src/SvGrid.helpers.ts +185 -0
  148. package/src/SvGrid.svelte +2346 -8742
  149. package/src/SvGrid.types.ts +537 -0
  150. package/src/SvGridChart.svelte +1060 -23
  151. package/src/aligned-grids.test.ts +80 -0
  152. package/src/aligned-grids.ts +87 -0
  153. package/src/build-api.coverage.test.ts +532 -0
  154. package/src/build-api.ts +683 -0
  155. package/src/cell-render.test.ts +451 -0
  156. package/src/cell-render.ts +426 -0
  157. package/src/cell-values.ts +114 -0
  158. package/src/chart-export.test.ts +370 -0
  159. package/src/chart.coverage.test.ts +814 -0
  160. package/src/chart.ts +1352 -47
  161. package/src/clipboard.test.ts +780 -0
  162. package/src/clipboard.ts +552 -0
  163. package/src/collaboration.coverage.test.ts +220 -0
  164. package/src/column-groups.test.ts +59 -0
  165. package/src/column-groups.ts +80 -0
  166. package/src/column-types.test.ts +68 -0
  167. package/src/column-types.ts +82 -0
  168. package/src/columns.test.ts +702 -0
  169. package/src/columns.ts +419 -0
  170. package/src/core.ts +86 -0
  171. package/src/css.d.ts +3 -0
  172. package/src/editing.test.ts +837 -0
  173. package/src/editing.ts +669 -0
  174. package/src/editors/cell-editors.coverage.test.ts +156 -0
  175. package/src/editors/cell-editors.ts +1 -0
  176. package/src/facet-buckets.test.ts +353 -0
  177. package/src/facet-buckets.ts +67 -0
  178. package/src/features.ts +128 -0
  179. package/src/filter-operators.test.ts +174 -0
  180. package/src/filter-operators.ts +87 -0
  181. package/src/hyperformula-adapter.test.ts +256 -0
  182. package/src/hyperformula-adapter.ts +124 -0
  183. package/src/index.ts +49 -0
  184. package/src/keyboard-handlers.coverage.test.ts +560 -0
  185. package/src/keyboard-handlers.ts +353 -0
  186. package/src/keyboard.ts +97 -97
  187. package/src/menus.test.ts +620 -0
  188. package/src/menus.ts +555 -0
  189. package/src/named-views.coverage.test.ts +210 -0
  190. package/src/named-views.ts +48 -0
  191. package/src/row-drag.test.ts +168 -0
  192. package/src/row-drag.ts +255 -0
  193. package/src/row-resize.test.ts +369 -0
  194. package/src/row-resize.ts +171 -0
  195. package/src/scroll-sync.test.ts +330 -0
  196. package/src/scroll-sync.ts +218 -0
  197. package/src/selection.multi-range.test.ts +61 -0
  198. package/src/selection.test.ts +722 -0
  199. package/src/selection.ts +579 -0
  200. package/src/server-data-source.coverage.test.ts +180 -0
  201. package/src/spreadsheet.test.ts +489 -0
  202. package/src/spreadsheet.ts +304 -0
  203. package/src/summaries.ts +204 -0
  204. package/src/sv-grid-scrollbar.ts +13 -1
  205. package/src/svgrid-wrapper.types.ts +31 -1
  206. package/src/svgrid.behavior.test.ts +22 -0
  207. package/src/svgrid.comments-autocomplete.test.ts +112 -0
  208. package/src/svgrid.context-menu.test.ts +126 -0
  209. package/src/svgrid.interaction.test.ts +30 -0
  210. package/src/svgrid.new-features.wrapper.test.ts +67 -6
  211. package/src/svgrid.wrapper.test.ts +27 -1
  212. package/src/test-setup.ts +9 -6
  213. package/src/virtualization/scroll-scaling.test.ts +148 -0
  214. package/src/virtualization/scroll-scaling.ts +121 -0
  215. package/src/virtualization/svelte-virtualizer.svelte.ts +2 -0
  216. package/src/virtualization/virtualizer.ts +26 -0
@@ -0,0 +1,121 @@
1
+ // Pure math for "huge list" vertical scroll scaling.
2
+ //
3
+ // Browsers cap how tall a single element may be (Chrome/Safari ~33.5M px,
4
+ // Firefox ~17.9M, mobile/high-DPR lower). Once a virtualized grid's true
5
+ // content height (count * rowHeight) exceeds that cap the scroll container
6
+ // silently clamps its scrollHeight and the tail rows become unreachable - a
7
+ // 1,000,000-row grid that only scrolls to ~994,000 on a phone.
8
+ //
9
+ // The fix (the technique react-virtualized calls "scaling"): size the DOM
10
+ // scroll spacer to a capped height the browser CAN render, and map between the
11
+ // limited DOM scroll range and the full logical range the virtualizer works
12
+ // in. This module is the pure, side-effect-free core of that mapping so the
13
+ // invariants can be unit-tested independently of the Svelte controller.
14
+ //
15
+ // When the true height fits under the cap, scaling is INERT: every mapping is
16
+ // the identity and callers behave exactly as before.
17
+
18
+ export type RowScrollScaling = {
19
+ /** True when the true content height exceeds the cap and mapping applies. */
20
+ readonly active: boolean
21
+ /** Height (px) the DOM scroll spacer should occupy - capped at maxDomHeight. */
22
+ readonly domTotal: number
23
+ /** Map a DOM scrollTop into the virtualizer's logical scroll offset. */
24
+ domToLogical(domTop: number): number
25
+ /** Map a virtualizer logical offset back into a DOM scrollTop. */
26
+ logicalToDom(logical: number): number
27
+ }
28
+
29
+ function clamp01(value: number): number {
30
+ if (value <= 0) return 0
31
+ if (value >= 1) return 1
32
+ return value
33
+ }
34
+
35
+ /** Below this a reading is junk (0 from jsdom, a sub-cap layout quirk, etc). */
36
+ const MAX_DOM_HEIGHT_SANITY_FLOOR = 100_000
37
+ /** At/above this the browser didn't clamp (returned ~the 1e9 we asked for). */
38
+ const MAX_DOM_HEIGHT_SANITY_CEIL = 900_000_000
39
+ /**
40
+ * Shave a hair off the detected cap so the spacer never sits at the exact
41
+ * physical edge, where sub-pixel rounding could leave the final row a touch
42
+ * out of reach. 0.5% is invisible at desktop caps (~33.5M -> ~33.3M) yet
43
+ * keeps a safety gap proportional to the cap.
44
+ */
45
+ const MAX_DOM_HEIGHT_SAFETY = 0.995
46
+
47
+ /**
48
+ * Resolve the usable max element height from the two raw DOM signals.
49
+ *
50
+ * `layoutCap` is a tall probe's clamped `offsetHeight` - the height layout
51
+ * assigns the element. `scrollCap` is the `scrollHeight` a real `overflow:auto`
52
+ * container exposes for that same probe - the height the user can actually
53
+ * scroll through. They differ on mobile / high-DPR engines, which report a
54
+ * generous `offsetHeight` but then expose a SMALLER scrollable range (the
55
+ * physical limit is in device px, so a 3x-DPR phone has ~1/3 the CSS-px scroll
56
+ * cap). Trusting `offsetHeight` alone is exactly what strands the last rows of
57
+ * a huge grid on a phone, so we take the smaller of the two.
58
+ *
59
+ * A junk reading (<= the sanity floor, or so large the browser clearly didn't
60
+ * clamp) is dropped; if neither signal survives, the caller's conservative
61
+ * `fallback` is returned unchanged.
62
+ */
63
+ export function resolveMaxDomHeight(
64
+ layoutCap: number,
65
+ scrollCap: number,
66
+ fallback: number,
67
+ ): number {
68
+ const usable = [layoutCap, scrollCap].filter(
69
+ (v) =>
70
+ Number.isFinite(v) &&
71
+ v > MAX_DOM_HEIGHT_SANITY_FLOOR &&
72
+ v < MAX_DOM_HEIGHT_SANITY_CEIL,
73
+ )
74
+ if (usable.length === 0) return fallback
75
+ return Math.floor(Math.min(...usable) * MAX_DOM_HEIGHT_SAFETY)
76
+ }
77
+
78
+ /**
79
+ * Build the scaling mapping for one axis.
80
+ *
81
+ * @param trueTotal The real content height in logical px (count * rowH, or
82
+ * the cumulative offset total for variable rows).
83
+ * @param maxDomHeight The browser's max element height (detected at runtime).
84
+ * @param viewport The scroll viewport height in px.
85
+ *
86
+ * Invariants (verified in scroll-scaling.test.ts):
87
+ * - Inert when `trueTotal <= maxDomHeight`: both maps are the identity.
88
+ * - `domTotal <= maxDomHeight` always, so the spacer never exceeds the cap.
89
+ * - Endpoints line up: domTop 0 -> logical 0, and the DOM max
90
+ * (`domTotal - viewport`) -> the logical max (`trueTotal - viewport`), so
91
+ * the very last row is always reachable.
92
+ * - `logicalToDom` is the inverse of `domToLogical` across the range.
93
+ * - Both maps are monotonic non-decreasing and clamp out-of-range inputs.
94
+ */
95
+ export function createRowScrollScaling(
96
+ trueTotal: number,
97
+ maxDomHeight: number,
98
+ viewport: number,
99
+ ): RowScrollScaling {
100
+ const safeMax = Math.max(maxDomHeight, 1)
101
+ const domTotal = Math.min(Math.max(trueTotal, 0), safeMax)
102
+ const active = trueTotal > safeMax
103
+ // Scrollable ranges (content minus one viewport). Guard against zero so the
104
+ // ratios below never divide by zero on tiny / empty grids.
105
+ const domRange = Math.max(domTotal - viewport, 1)
106
+ const logicalRange = Math.max(trueTotal - viewport, 0)
107
+
108
+ return {
109
+ active,
110
+ domTotal,
111
+ domToLogical(domTop: number): number {
112
+ if (!active) return domTop
113
+ return clamp01(domTop / domRange) * logicalRange
114
+ },
115
+ logicalToDom(logical: number): number {
116
+ if (!active) return logical
117
+ const lr = Math.max(logicalRange, 1)
118
+ return clamp01(logical / lr) * Math.max(domTotal - viewport, 0)
119
+ },
120
+ }
121
+ }
@@ -19,6 +19,8 @@ export function createSvelteVirtualizer(options: VirtualizerOptions) {
19
19
  scrollToIndex: virtualizer.scrollToIndex,
20
20
  getVirtualItems: virtualizer.getVirtualItems,
21
21
  getTotalSize: virtualizer.getTotalSize,
22
+ getOffsetForIndex: virtualizer.getOffsetForIndex,
23
+ getSizeForIndex: virtualizer.getSizeForIndex,
22
24
  getState: virtualizer.getState,
23
25
  }
24
26
  }
@@ -259,6 +259,32 @@ export function createVirtualizer(initial: VirtualizerOptions) {
259
259
  getTotalSize() {
260
260
  return state.totalSize
261
261
  },
262
+ /** Cumulative offset of row `index` from the top in px, regardless
263
+ * of whether `estimateSize` is uniform or per-index. Uses the
264
+ * cached offsets array under function-form sizing so the lookup
265
+ * is O(1) instead of O(index). */
266
+ getOffsetForIndex(index: number): number {
267
+ if (index <= 0) return 0
268
+ const count = Math.max(options.count, 0)
269
+ const bounded = Math.min(index, count)
270
+ if (typeof options.estimateSize === 'function') {
271
+ const offsets = getOffsets()
272
+ if (offsets) return offsets[bounded] ?? 0
273
+ let acc = 0
274
+ const fn = options.estimateSize
275
+ for (let i = 0; i < bounded; i += 1) acc += Math.max(fn(i), 1)
276
+ return acc
277
+ }
278
+ return bounded * Math.max(options.estimateSize, 1)
279
+ },
280
+ /** Height of row `index` in px (whichever estimateSize provides). */
281
+ getSizeForIndex(index: number): number {
282
+ if (index < 0 || index >= options.count) return 0
283
+ if (typeof options.estimateSize === 'function') {
284
+ return Math.max(options.estimateSize(index), 1)
285
+ }
286
+ return Math.max(options.estimateSize, 1)
287
+ },
262
288
  getState() {
263
289
  return state
264
290
  },