@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.
- package/LICENSE +1 -1
- package/README.md +137 -39
- package/dist/GridFooter.svelte +164 -0
- package/dist/GridFooter.svelte.d.ts +29 -0
- package/dist/GridMenus.svelte +648 -0
- package/dist/GridMenus.svelte.d.ts +31 -0
- package/dist/SvGrid.controller.svelte.d.ts +472 -0
- package/dist/SvGrid.controller.svelte.js +1917 -0
- package/dist/SvGrid.css +2012 -0
- package/dist/SvGrid.helpers.d.ts +35 -0
- package/dist/SvGrid.helpers.js +160 -0
- package/dist/SvGrid.helpers.test.d.ts +1 -0
- package/dist/SvGrid.helpers.test.js +298 -0
- package/dist/SvGrid.svelte +2346 -8742
- package/dist/SvGrid.svelte.d.ts +4 -357
- package/dist/SvGrid.types.d.ts +523 -0
- package/dist/SvGrid.types.js +1 -0
- package/dist/SvGridChart.svelte +1060 -23
- package/dist/SvGridChart.svelte.d.ts +17 -0
- package/dist/aligned-grids.d.ts +6 -0
- package/dist/aligned-grids.js +84 -0
- package/dist/aligned-grids.test.d.ts +1 -0
- package/dist/aligned-grids.test.js +75 -0
- package/dist/build-api.coverage.test.d.ts +20 -0
- package/dist/build-api.coverage.test.js +505 -0
- package/dist/build-api.d.ts +5 -0
- package/dist/build-api.js +557 -0
- package/dist/cell-render.d.ts +15 -0
- package/dist/cell-render.js +246 -0
- package/dist/cell-render.test.d.ts +1 -0
- package/dist/cell-render.test.js +338 -0
- package/dist/cell-values.d.ts +28 -0
- package/dist/cell-values.js +89 -0
- package/dist/chart-export.test.d.ts +1 -0
- package/dist/chart-export.test.js +302 -0
- package/dist/chart.coverage.test.d.ts +1 -0
- package/dist/chart.coverage.test.js +748 -0
- package/dist/chart.d.ts +370 -3
- package/dist/chart.js +1135 -42
- package/dist/clipboard.d.ts +15 -0
- package/dist/clipboard.js +420 -0
- package/dist/clipboard.test.d.ts +1 -0
- package/dist/clipboard.test.js +700 -0
- package/dist/collaboration.coverage.test.d.ts +1 -0
- package/dist/collaboration.coverage.test.js +200 -0
- package/dist/column-groups.d.ts +19 -0
- package/dist/column-groups.js +62 -0
- package/dist/column-groups.test.d.ts +1 -0
- package/dist/column-groups.test.js +56 -0
- package/dist/column-types.d.ts +10 -0
- package/dist/column-types.js +63 -0
- package/dist/column-types.test.d.ts +1 -0
- package/dist/column-types.test.js +62 -0
- package/dist/columns.d.ts +30 -0
- package/dist/columns.js +277 -0
- package/dist/columns.test.d.ts +1 -0
- package/dist/columns.test.js +625 -0
- package/dist/core.d.ts +86 -1
- package/dist/css.d.ts +3 -0
- package/dist/editing.d.ts +31 -0
- package/dist/editing.js +529 -0
- package/dist/editing.test.d.ts +1 -0
- package/dist/editing.test.js +732 -0
- package/dist/editors/cell-editors.coverage.test.d.ts +1 -0
- package/dist/editors/cell-editors.coverage.test.js +139 -0
- package/dist/editors/cell-editors.d.ts +1 -1
- package/dist/facet-buckets.d.ts +13 -0
- package/dist/facet-buckets.js +54 -0
- package/dist/facet-buckets.test.d.ts +1 -0
- package/dist/facet-buckets.test.js +296 -0
- package/dist/features.d.ts +5 -0
- package/dist/features.js +30 -0
- package/dist/filter-operators.d.ts +16 -0
- package/dist/filter-operators.js +69 -0
- package/dist/filter-operators.test.d.ts +1 -0
- package/dist/filter-operators.test.js +135 -0
- package/dist/hyperformula-adapter.d.ts +82 -0
- package/dist/hyperformula-adapter.js +73 -0
- package/dist/hyperformula-adapter.test.d.ts +1 -0
- package/dist/hyperformula-adapter.test.js +205 -0
- package/dist/index.d.ts +9 -3
- package/dist/index.js +8 -2
- package/dist/keyboard-handlers.coverage.test.d.ts +1 -0
- package/dist/keyboard-handlers.coverage.test.js +495 -0
- package/dist/keyboard-handlers.d.ts +7 -0
- package/dist/keyboard-handlers.js +202 -0
- package/dist/menus.d.ts +40 -0
- package/dist/menus.js +390 -0
- package/dist/menus.test.d.ts +1 -0
- package/dist/menus.test.js +560 -0
- package/dist/named-views.coverage.test.d.ts +1 -0
- package/dist/named-views.coverage.test.js +180 -0
- package/dist/named-views.d.ts +27 -0
- package/dist/named-views.js +39 -0
- package/dist/row-drag.d.ts +49 -0
- package/dist/row-drag.js +221 -0
- package/dist/row-drag.test.d.ts +1 -0
- package/dist/row-drag.test.js +142 -0
- package/dist/row-resize.d.ts +43 -0
- package/dist/row-resize.js +158 -0
- package/dist/row-resize.test.d.ts +1 -0
- package/dist/row-resize.test.js +329 -0
- package/dist/scroll-sync.d.ts +9 -0
- package/dist/scroll-sync.js +89 -0
- package/dist/scroll-sync.test.d.ts +1 -0
- package/dist/scroll-sync.test.js +290 -0
- package/dist/selection.d.ts +32 -0
- package/dist/selection.js +427 -0
- package/dist/selection.multi-range.test.d.ts +1 -0
- package/dist/selection.multi-range.test.js +55 -0
- package/dist/selection.test.d.ts +1 -0
- package/dist/selection.test.js +647 -0
- package/dist/server-data-source.coverage.test.d.ts +1 -0
- package/dist/server-data-source.coverage.test.js +154 -0
- package/dist/spreadsheet.d.ts +110 -0
- package/dist/spreadsheet.js +242 -0
- package/dist/spreadsheet.test.d.ts +1 -0
- package/dist/spreadsheet.test.js +446 -0
- package/dist/summaries.d.ts +12 -0
- package/dist/summaries.js +65 -0
- package/dist/sv-grid-scrollbar.js +13 -1
- package/dist/svgrid-wrapper.types.d.ts +31 -1
- package/dist/svgrid.behavior.test.js +20 -0
- package/dist/svgrid.comments-autocomplete.test.d.ts +1 -0
- package/dist/svgrid.comments-autocomplete.test.js +96 -0
- package/dist/svgrid.context-menu.test.d.ts +1 -0
- package/dist/svgrid.context-menu.test.js +102 -0
- package/dist/svgrid.interaction.test.js +31 -0
- package/dist/svgrid.new-features.wrapper.test.js +64 -6
- package/dist/svgrid.wrapper.test.js +27 -1
- package/dist/test-setup.js +9 -3
- package/dist/virtualization/column-virtualizer.d.ts +2 -0
- package/dist/virtualization/scroll-scaling.d.ts +45 -0
- package/dist/virtualization/scroll-scaling.js +99 -0
- package/dist/virtualization/scroll-scaling.test.d.ts +1 -0
- package/dist/virtualization/scroll-scaling.test.js +127 -0
- package/dist/virtualization/svelte-virtualizer.svelte.d.ts +2 -0
- package/dist/virtualization/svelte-virtualizer.svelte.js +2 -0
- package/dist/virtualization/virtualizer.d.ts +7 -0
- package/dist/virtualization/virtualizer.js +30 -0
- package/package.json +2 -1
- package/src/GridFooter.svelte +164 -0
- package/src/GridMenus.svelte +648 -0
- package/src/SvGrid.controller.svelte.ts +2352 -0
- package/src/SvGrid.css +2012 -0
- package/src/SvGrid.helpers.test.ts +415 -0
- package/src/SvGrid.helpers.ts +185 -0
- package/src/SvGrid.svelte +2346 -8742
- package/src/SvGrid.types.ts +537 -0
- package/src/SvGridChart.svelte +1060 -23
- package/src/aligned-grids.test.ts +80 -0
- package/src/aligned-grids.ts +87 -0
- package/src/build-api.coverage.test.ts +532 -0
- package/src/build-api.ts +683 -0
- package/src/cell-render.test.ts +451 -0
- package/src/cell-render.ts +426 -0
- package/src/cell-values.ts +114 -0
- package/src/chart-export.test.ts +370 -0
- package/src/chart.coverage.test.ts +814 -0
- package/src/chart.ts +1352 -47
- package/src/clipboard.test.ts +780 -0
- package/src/clipboard.ts +552 -0
- package/src/collaboration.coverage.test.ts +220 -0
- package/src/column-groups.test.ts +59 -0
- package/src/column-groups.ts +80 -0
- package/src/column-types.test.ts +68 -0
- package/src/column-types.ts +82 -0
- package/src/columns.test.ts +702 -0
- package/src/columns.ts +419 -0
- package/src/core.ts +86 -0
- package/src/css.d.ts +3 -0
- package/src/editing.test.ts +837 -0
- package/src/editing.ts +669 -0
- package/src/editors/cell-editors.coverage.test.ts +156 -0
- package/src/editors/cell-editors.ts +1 -0
- package/src/facet-buckets.test.ts +353 -0
- package/src/facet-buckets.ts +67 -0
- package/src/features.ts +128 -0
- package/src/filter-operators.test.ts +174 -0
- package/src/filter-operators.ts +87 -0
- package/src/hyperformula-adapter.test.ts +256 -0
- package/src/hyperformula-adapter.ts +124 -0
- package/src/index.ts +49 -0
- package/src/keyboard-handlers.coverage.test.ts +560 -0
- package/src/keyboard-handlers.ts +353 -0
- package/src/keyboard.ts +97 -97
- package/src/menus.test.ts +620 -0
- package/src/menus.ts +555 -0
- package/src/named-views.coverage.test.ts +210 -0
- package/src/named-views.ts +48 -0
- package/src/row-drag.test.ts +168 -0
- package/src/row-drag.ts +255 -0
- package/src/row-resize.test.ts +369 -0
- package/src/row-resize.ts +171 -0
- package/src/scroll-sync.test.ts +330 -0
- package/src/scroll-sync.ts +218 -0
- package/src/selection.multi-range.test.ts +61 -0
- package/src/selection.test.ts +722 -0
- package/src/selection.ts +579 -0
- package/src/server-data-source.coverage.test.ts +180 -0
- package/src/spreadsheet.test.ts +489 -0
- package/src/spreadsheet.ts +304 -0
- package/src/summaries.ts +204 -0
- package/src/sv-grid-scrollbar.ts +13 -1
- package/src/svgrid-wrapper.types.ts +31 -1
- package/src/svgrid.behavior.test.ts +22 -0
- package/src/svgrid.comments-autocomplete.test.ts +112 -0
- package/src/svgrid.context-menu.test.ts +126 -0
- package/src/svgrid.interaction.test.ts +30 -0
- package/src/svgrid.new-features.wrapper.test.ts +67 -6
- package/src/svgrid.wrapper.test.ts +27 -1
- package/src/test-setup.ts +9 -6
- package/src/virtualization/scroll-scaling.test.ts +148 -0
- package/src/virtualization/scroll-scaling.ts +121 -0
- package/src/virtualization/svelte-virtualizer.svelte.ts +2 -0
- 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
|
},
|