@svgrid/grid 1.1.0 → 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 (117) hide show
  1. package/dist/GridMenus.svelte +205 -127
  2. package/dist/SvGrid.controller.svelte.d.ts +44 -1
  3. package/dist/SvGrid.controller.svelte.js +223 -38
  4. package/dist/SvGrid.css +2012 -1709
  5. package/dist/SvGrid.helpers.test.d.ts +1 -0
  6. package/dist/SvGrid.helpers.test.js +298 -0
  7. package/dist/SvGrid.svelte +2346 -2043
  8. package/dist/SvGrid.types.d.ts +91 -4
  9. package/dist/aligned-grids.d.ts +6 -0
  10. package/dist/aligned-grids.js +84 -0
  11. package/dist/aligned-grids.test.d.ts +1 -0
  12. package/dist/aligned-grids.test.js +75 -0
  13. package/dist/build-api.coverage.test.d.ts +20 -0
  14. package/dist/build-api.coverage.test.js +505 -0
  15. package/dist/build-api.js +59 -29
  16. package/dist/cell-render.test.d.ts +1 -0
  17. package/dist/cell-render.test.js +338 -0
  18. package/dist/chart-export.test.d.ts +1 -0
  19. package/dist/chart-export.test.js +302 -0
  20. package/dist/chart.coverage.test.d.ts +1 -0
  21. package/dist/chart.coverage.test.js +748 -0
  22. package/dist/clipboard.js +88 -24
  23. package/dist/clipboard.test.d.ts +1 -0
  24. package/dist/clipboard.test.js +700 -0
  25. package/dist/collaboration.coverage.test.d.ts +1 -0
  26. package/dist/collaboration.coverage.test.js +200 -0
  27. package/dist/column-groups.d.ts +19 -0
  28. package/dist/column-groups.js +62 -0
  29. package/dist/column-groups.test.d.ts +1 -0
  30. package/dist/column-groups.test.js +56 -0
  31. package/dist/column-types.d.ts +10 -0
  32. package/dist/column-types.js +63 -0
  33. package/dist/column-types.test.d.ts +1 -0
  34. package/dist/column-types.test.js +62 -0
  35. package/dist/columns.test.d.ts +1 -0
  36. package/dist/columns.test.js +625 -0
  37. package/dist/core.d.ts +85 -0
  38. package/dist/editing.d.ts +7 -0
  39. package/dist/editing.js +191 -5
  40. package/dist/editing.test.d.ts +1 -0
  41. package/dist/editing.test.js +732 -0
  42. package/dist/editors/cell-editors.coverage.test.d.ts +1 -0
  43. package/dist/editors/cell-editors.coverage.test.js +139 -0
  44. package/dist/facet-buckets.test.d.ts +1 -0
  45. package/dist/facet-buckets.test.js +296 -0
  46. package/dist/filter-operators.test.d.ts +1 -0
  47. package/dist/filter-operators.test.js +135 -0
  48. package/dist/hyperformula-adapter.test.d.ts +1 -0
  49. package/dist/hyperformula-adapter.test.js +205 -0
  50. package/dist/index.d.ts +5 -2
  51. package/dist/index.js +4 -1
  52. package/dist/keyboard-handlers.coverage.test.d.ts +1 -0
  53. package/dist/keyboard-handlers.coverage.test.js +495 -0
  54. package/dist/keyboard-handlers.js +7 -2
  55. package/dist/menus.js +1 -0
  56. package/dist/menus.test.d.ts +1 -0
  57. package/dist/menus.test.js +560 -0
  58. package/dist/named-views.coverage.test.d.ts +1 -0
  59. package/dist/named-views.coverage.test.js +180 -0
  60. package/dist/row-drag.d.ts +49 -0
  61. package/dist/row-drag.js +221 -0
  62. package/dist/row-drag.test.d.ts +1 -0
  63. package/dist/row-drag.test.js +142 -0
  64. package/dist/row-resize.test.d.ts +1 -0
  65. package/dist/row-resize.test.js +329 -0
  66. package/dist/scroll-sync.js +3 -0
  67. package/dist/scroll-sync.test.d.ts +1 -0
  68. package/dist/scroll-sync.test.js +290 -0
  69. package/dist/selection.d.ts +7 -1
  70. package/dist/selection.js +76 -36
  71. package/dist/selection.multi-range.test.d.ts +1 -0
  72. package/dist/selection.multi-range.test.js +55 -0
  73. package/dist/selection.test.d.ts +1 -0
  74. package/dist/selection.test.js +647 -0
  75. package/dist/server-data-source.coverage.test.d.ts +1 -0
  76. package/dist/server-data-source.coverage.test.js +154 -0
  77. package/dist/spreadsheet.d.ts +30 -0
  78. package/dist/spreadsheet.js +48 -0
  79. package/dist/spreadsheet.test.d.ts +1 -0
  80. package/dist/spreadsheet.test.js +446 -0
  81. package/dist/sv-grid-scrollbar.js +13 -1
  82. package/dist/svgrid-wrapper.types.d.ts +19 -0
  83. package/dist/svgrid.behavior.test.js +20 -0
  84. package/dist/svgrid.interaction.test.js +31 -0
  85. package/dist/svgrid.new-features.wrapper.test.js +34 -2
  86. package/dist/test-setup.js +9 -3
  87. package/dist/virtualization/scroll-scaling.d.ts +17 -0
  88. package/dist/virtualization/scroll-scaling.js +35 -0
  89. package/dist/virtualization/scroll-scaling.test.js +42 -1
  90. package/package.json +2 -1
  91. package/src/GridMenus.svelte +205 -127
  92. package/src/SvGrid.controller.svelte.ts +2352 -2195
  93. package/src/SvGrid.css +2012 -1747
  94. package/src/SvGrid.svelte +2346 -2047
  95. package/src/SvGrid.types.ts +537 -456
  96. package/src/aligned-grids.test.ts +80 -0
  97. package/src/aligned-grids.ts +87 -0
  98. package/src/build-api.ts +683 -663
  99. package/src/clipboard.test.ts +49 -0
  100. package/src/clipboard.ts +51 -23
  101. package/src/column-groups.test.ts +59 -0
  102. package/src/column-groups.ts +80 -0
  103. package/src/column-types.test.ts +68 -0
  104. package/src/column-types.ts +82 -0
  105. package/src/core.ts +78 -0
  106. package/src/editing.ts +669 -513
  107. package/src/index.ts +12 -0
  108. package/src/menus.ts +1 -0
  109. package/src/row-drag.test.ts +168 -0
  110. package/src/row-drag.ts +255 -0
  111. package/src/scroll-sync.ts +2 -0
  112. package/src/selection.multi-range.test.ts +61 -0
  113. package/src/selection.ts +71 -37
  114. package/src/spreadsheet.test.ts +489 -445
  115. package/src/spreadsheet.ts +304 -246
  116. package/src/svgrid-wrapper.types.ts +19 -0
  117. package/src/svgrid.new-features.wrapper.test.ts +2 -2
@@ -0,0 +1,80 @@
1
+ /**
2
+ * Unit tests for aligned grids: two members sharing a group mirror horizontal
3
+ * scroll and column-resize widths to each other. Driven with minimal fake ctxs.
4
+ */
5
+ import { describe, expect, it } from 'vitest'
6
+ import { createAlignedGrids } from './aligned-grids'
7
+
8
+ function makeCtx(group: string | undefined) {
9
+ return {
10
+ props: { alignedGridGroup: group },
11
+ scrollContainer: { scrollLeft: 0 } as { scrollLeft: number },
12
+ columnWidths: {} as Record<string, number>,
13
+ } as Record<string, any>
14
+ }
15
+
16
+ describe('aligned grids', () => {
17
+ it('mirrors horizontal scroll to peers in the same group', () => {
18
+ const a = makeCtx('g')
19
+ const b = makeCtx('g')
20
+ const ha = createAlignedGrids(a)
21
+ const hb = createAlignedGrids(b)
22
+ const un1 = ha.register()
23
+ const un2 = hb.register()
24
+
25
+ ha.broadcastScroll(240)
26
+ expect(b.scrollContainer.scrollLeft).toBe(240)
27
+ // and the other way
28
+ hb.broadcastScroll(80)
29
+ expect(a.scrollContainer.scrollLeft).toBe(80)
30
+ un1(); un2()
31
+ })
32
+
33
+ it('mirrors column-resize widths to peers (matched by column id)', () => {
34
+ const a = makeCtx('g')
35
+ const b = makeCtx('g')
36
+ const ha = createAlignedGrids(a)
37
+ const hb = createAlignedGrids(b)
38
+ ha.register(); hb.register()
39
+
40
+ a.columnWidths = { Feb: 180 }
41
+ ha.broadcastWidths()
42
+ expect(b.columnWidths.Feb).toBe(180)
43
+ })
44
+
45
+ it('does NOT mirror across different groups', () => {
46
+ const a = makeCtx('one')
47
+ const b = makeCtx('two')
48
+ const ha = createAlignedGrids(a)
49
+ const hb = createAlignedGrids(b)
50
+ ha.register(); hb.register()
51
+
52
+ ha.broadcastScroll(200)
53
+ expect(b.scrollContainer.scrollLeft).toBe(0)
54
+ a.columnWidths = { Feb: 999 }
55
+ ha.broadcastWidths()
56
+ expect(b.columnWidths.Feb).toBeUndefined()
57
+ })
58
+
59
+ it('is inert with no group set, and after unregister', () => {
60
+ const a = makeCtx(undefined)
61
+ const b = makeCtx(undefined)
62
+ const ha = createAlignedGrids(a)
63
+ const hb = createAlignedGrids(b)
64
+ ha.register(); hb.register()
65
+ ha.broadcastScroll(120)
66
+ expect(b.scrollContainer.scrollLeft).toBe(0)
67
+
68
+ // Grouped, then unregistered -> no longer receives updates.
69
+ const c = makeCtx('gg')
70
+ const d = makeCtx('gg')
71
+ const hc = createAlignedGrids(c)
72
+ const hd = createAlignedGrids(d)
73
+ const unc = hc.register()
74
+ const und = hd.register()
75
+ und() // d leaves the group
76
+ hc.broadcastScroll(55)
77
+ expect(d.scrollContainer.scrollLeft).toBe(0)
78
+ unc()
79
+ })
80
+ })
@@ -0,0 +1,87 @@
1
+ // Aligned grids - keep two or more independent grids in lockstep on horizontal
2
+ // scroll and column widths. Grids that share the same `alignedGridGroup` string
3
+ // register with a module-level registry (same pattern as managed row dragging);
4
+ // when one scrolls horizontally or a column is resized, the others follow.
5
+ //
6
+ // Loop-safety without flags: scroll sync no-ops when the target already has the
7
+ // value (so the echo scroll event never fires); width sync compares a serialized
8
+ // snapshot and pre-seeds it on apply, so the reactive effect that fires after
9
+ // applying a peer's widths sees "no change" and doesn't echo.
10
+
11
+ type Member = {
12
+ id: number;
13
+ applyScroll: (left: number) => void;
14
+ applyWidths: (widths: Record<string, number>) => void;
15
+ };
16
+
17
+ // Shared across every grid in the bundle.
18
+ const groups = new Map<string, Map<number, Member>>();
19
+ let seq = 0;
20
+
21
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
22
+ export function createAlignedGrids<TFeatures, TData>(ctx: any) {
23
+ const id = ++seq;
24
+ let lastWidthsSerial = "";
25
+
26
+ const group = (): string | null => ctx.props.alignedGridGroup ?? null;
27
+
28
+ function peers(): Member[] {
29
+ const g = group();
30
+ if (!g) return [];
31
+ const m = groups.get(g);
32
+ if (!m) return [];
33
+ const out: Member[] = [];
34
+ for (const member of m.values()) if (member.id !== id) out.push(member);
35
+ return out;
36
+ }
37
+
38
+ const self: Member = {
39
+ id,
40
+ applyScroll(left: number) {
41
+ const el = ctx.scrollContainer as HTMLElement | null;
42
+ // Only set when it differs, so no echo scroll event fires -> no loop.
43
+ if (el && el.scrollLeft !== left) el.scrollLeft = left;
44
+ },
45
+ applyWidths(widths: Record<string, number>) {
46
+ const merged = { ...(ctx.columnWidths as Record<string, number>), ...widths };
47
+ // Pre-seed the serial so the columnWidths effect that fires after this
48
+ // set sees an unchanged snapshot and skips its own broadcast.
49
+ lastWidthsSerial = JSON.stringify(merged);
50
+ ctx.columnWidths = merged;
51
+ },
52
+ };
53
+
54
+ // Register on mount; returns the unregister for the effect's cleanup.
55
+ function register(): () => void {
56
+ const g = group();
57
+ if (!g) return () => {};
58
+ let m = groups.get(g);
59
+ if (!m) {
60
+ m = new Map();
61
+ groups.set(g, m);
62
+ }
63
+ m.set(id, self);
64
+ return () => {
65
+ const mm = groups.get(g);
66
+ if (!mm) return;
67
+ mm.delete(id);
68
+ if (!mm.size) groups.delete(g);
69
+ };
70
+ }
71
+
72
+ function broadcastScroll(left: number) {
73
+ const p = peers();
74
+ for (const member of p) member.applyScroll(left);
75
+ }
76
+
77
+ function broadcastWidths() {
78
+ if (!group()) return;
79
+ const serial = JSON.stringify((ctx.columnWidths as Record<string, number>) ?? {});
80
+ if (serial === lastWidthsSerial) return; // nothing new (or echo of an apply)
81
+ lastWidthsSerial = serial;
82
+ const w = ctx.columnWidths as Record<string, number>;
83
+ for (const member of peers()) member.applyWidths(w);
84
+ }
85
+
86
+ return { register, broadcastScroll, broadcastWidths, alignedGridId: id };
87
+ }