@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
@@ -137,7 +137,32 @@ export type Props<TFeatures extends TableFeatures = TableFeatures, TData extends
137
137
  showFilterMenu?: boolean;
138
138
  showFilterRow?: boolean;
139
139
  enableCellSelection?: boolean;
140
+ /**
141
+ * Prepend a header row (the column labels) to copied cell ranges, so pasting
142
+ * into Excel / Sheets includes the headers. Applies per copied range.
143
+ */
144
+ copyHeadersToClipboard?: boolean;
145
+ /**
146
+ * Transform each cell value on its way to the clipboard - e.g. strip
147
+ * currency symbols, expand codes to labels, or redact. Receives the display
148
+ * value plus the row/column context; return the string (or value) to copy.
149
+ */
150
+ processCellForClipboard?: (params: {
151
+ value: unknown;
152
+ column: unknown;
153
+ row: TData;
154
+ rowIndex: number;
155
+ columnId: string;
156
+ }) => unknown;
140
157
  enableInlineEditing?: boolean;
158
+ /**
159
+ * Full-row editing. When `true`, starting an edit puts the WHOLE row into
160
+ * edit mode - every editable cell shows an inline editor at once - and a
161
+ * single Enter (or focus leaving the row) commits all of them; Esc cancels
162
+ * the whole row. Requires `enableInlineEditing`. The full-row editor covers
163
+ * text / number / date / datetime / checkbox / list-select editor types.
164
+ */
165
+ fullRowEditing?: boolean;
141
166
  enableRowSummaries?: boolean;
142
167
  /**
143
168
  * Excel-style status bar under the grid showing live aggregates of the
@@ -149,12 +174,21 @@ export type Props<TFeatures extends TableFeatures = TableFeatures, TData extends
149
174
  aggregates?: ReadonlyArray<"count" | "numericCount" | "sum" | "avg" | "min" | "max">;
150
175
  };
151
176
  /**
152
- * Show a docked Columns tool panel - the enterprise sidebar for toggling
153
- * column visibility, reordering, and grouping without a right-click. A
154
- * toggle button appears at the grid's top-right; the panel itself docks
155
- * on the right edge.
177
+ * Show the docked tool panel - the enterprise sidebar with Columns and
178
+ * Filters tabs. A "Columns & Filters" button appears in a toolbar above the
179
+ * grid; the panel docks on the right edge.
156
180
  */
157
181
  toolPanel?: boolean;
182
+ /**
183
+ * Render the header column menu (⋮) as a tabbed popover - **General**,
184
+ * **Filter**, and **Columns** tabs (the AG-Grid layout). Defaults to `false`,
185
+ * which keeps the flat menu (actions list + "Choose columns" submenu).
186
+ */
187
+ columnMenuTabs?: boolean;
188
+ /** Open the tool panel on first render (instead of collapsed). */
189
+ toolPanelDefaultOpen?: boolean;
190
+ /** Which tab the tool panel starts on. Defaults to `'columns'`. */
191
+ toolPanelDefaultTab?: "columns" | "filters";
158
192
  /**
159
193
  * Quick way to pick which selection surfaces are active. `'row'` shows the
160
194
  * selection checkbox column only, `'cell'` allows rectangle/range cell
@@ -167,6 +201,12 @@ export type Props<TFeatures extends TableFeatures = TableFeatures, TData extends
167
201
  * column. Useful as a permanent anchor when scrolling wide grids.
168
202
  */
169
203
  showRowNumbers?: boolean;
204
+ /**
205
+ * Paint alternating data rows with the `--sg-row-alt-bg` color (zebra
206
+ * striping). Only data rows stripe - pinned, group, detail, and summary
207
+ * rows keep their single background. Defaults to `false`.
208
+ */
209
+ zebraRows?: boolean;
170
210
  /**
171
211
  * Width (px) of the row-number column. Defaults to 56, which fits up
172
212
  * to "99,999"; bump this when the dataset crosses six digits so the
@@ -401,6 +441,53 @@ export type Props<TFeatures extends TableFeatures = TableFeatures, TData extends
401
441
  columnOrder?: ReadonlyArray<string>;
402
442
  /** Fires every time the column order changes (drag or `api.setColumnOrder`). */
403
443
  onColumnOrderChange?: (order: ReadonlyArray<string>) => void;
444
+ /**
445
+ * Infer each column's data type (number / boolean / date / ISO date-string /
446
+ * text) from the first data row, for columns that declare neither an
447
+ * explicit `editorType` nor a `cellDataType`. Sets the matching editor,
448
+ * alignment, date format, and filter operators automatically. Explicit
449
+ * column config always wins. Defaults to `false`.
450
+ */
451
+ inferColumnTypes?: boolean;
452
+ /**
453
+ * Enables managed row dragging. When `true`, every row becomes a drag
454
+ * source (grab cursor + a grip in the row-number cell) and a drop
455
+ * indicator paints between rows during a drag. On drop the grid mutates
456
+ * its own internal data - reordering within the grid, or moving the row
457
+ * across grids that share the same {@link rowDragGroup}. Defaults to
458
+ * `false`.
459
+ */
460
+ rowDragManaged?: boolean;
461
+ /**
462
+ * Connection group for cross-grid row dragging. Grids that share the same
463
+ * non-empty `rowDragGroup` string (and have `rowDragManaged` on) can
464
+ * exchange rows: dragging a row out of one and dropping it into another
465
+ * removes it from the source and inserts it into the target. Omit to keep
466
+ * dragging confined to reordering within a single grid.
467
+ */
468
+ rowDragGroup?: string;
469
+ /**
470
+ * Fires on the TARGET grid after a managed row drag settles, with the
471
+ * moved row, its landing index, whether it stayed in the same grid, and
472
+ * the source / target grid ids. Use it to mirror the move into your own
473
+ * state (persistence, server sync). The grid has already applied the
474
+ * change to its internal data by the time this fires.
475
+ */
476
+ onRowDragEnd?: (event: {
477
+ row: TData;
478
+ toIndex: number;
479
+ sameGrid: boolean;
480
+ fromGridId: number;
481
+ toGridId: number;
482
+ }) => void;
483
+ /**
484
+ * Align this grid with others that share the same non-empty
485
+ * `alignedGridGroup` string: horizontal scroll and column-resize widths are
486
+ * kept in lockstep across every grid in the group. Use for a totals/header
487
+ * grid above a body grid, or side-by-side comparison grids that must line up.
488
+ * The grids should declare the same columns (matched by id) for widths to map.
489
+ */
490
+ alignedGridGroup?: string;
404
491
  /**
405
492
  * BCP-47 locale tag (or array of fallbacks) used for accent- and
406
493
  * case-insensitive text filtering / sorting / search. Powered by
@@ -0,0 +1,6 @@
1
+ export declare function createAlignedGrids<TFeatures, TData>(ctx: any): {
2
+ register: () => () => void;
3
+ broadcastScroll: (left: number) => void;
4
+ broadcastWidths: () => void;
5
+ alignedGridId: number;
6
+ };
@@ -0,0 +1,84 @@
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
+ // Shared across every grid in the bundle.
11
+ const groups = new Map();
12
+ let seq = 0;
13
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
14
+ export function createAlignedGrids(ctx) {
15
+ const id = ++seq;
16
+ let lastWidthsSerial = "";
17
+ const group = () => ctx.props.alignedGridGroup ?? null;
18
+ function peers() {
19
+ const g = group();
20
+ if (!g)
21
+ return [];
22
+ const m = groups.get(g);
23
+ if (!m)
24
+ return [];
25
+ const out = [];
26
+ for (const member of m.values())
27
+ if (member.id !== id)
28
+ out.push(member);
29
+ return out;
30
+ }
31
+ const self = {
32
+ id,
33
+ applyScroll(left) {
34
+ const el = ctx.scrollContainer;
35
+ // Only set when it differs, so no echo scroll event fires -> no loop.
36
+ if (el && el.scrollLeft !== left)
37
+ el.scrollLeft = left;
38
+ },
39
+ applyWidths(widths) {
40
+ const merged = { ...ctx.columnWidths, ...widths };
41
+ // Pre-seed the serial so the columnWidths effect that fires after this
42
+ // set sees an unchanged snapshot and skips its own broadcast.
43
+ lastWidthsSerial = JSON.stringify(merged);
44
+ ctx.columnWidths = merged;
45
+ },
46
+ };
47
+ // Register on mount; returns the unregister for the effect's cleanup.
48
+ function register() {
49
+ const g = group();
50
+ if (!g)
51
+ return () => { };
52
+ let m = groups.get(g);
53
+ if (!m) {
54
+ m = new Map();
55
+ groups.set(g, m);
56
+ }
57
+ m.set(id, self);
58
+ return () => {
59
+ const mm = groups.get(g);
60
+ if (!mm)
61
+ return;
62
+ mm.delete(id);
63
+ if (!mm.size)
64
+ groups.delete(g);
65
+ };
66
+ }
67
+ function broadcastScroll(left) {
68
+ const p = peers();
69
+ for (const member of p)
70
+ member.applyScroll(left);
71
+ }
72
+ function broadcastWidths() {
73
+ if (!group())
74
+ return;
75
+ const serial = JSON.stringify(ctx.columnWidths ?? {});
76
+ if (serial === lastWidthsSerial)
77
+ return; // nothing new (or echo of an apply)
78
+ lastWidthsSerial = serial;
79
+ const w = ctx.columnWidths;
80
+ for (const member of peers())
81
+ member.applyWidths(w);
82
+ }
83
+ return { register, broadcastScroll, broadcastWidths, alignedGridId: id };
84
+ }
@@ -0,0 +1 @@
1
+ export {};
@@ -0,0 +1,75 @@
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
+ function makeCtx(group) {
8
+ return {
9
+ props: { alignedGridGroup: group },
10
+ scrollContainer: { scrollLeft: 0 },
11
+ columnWidths: {},
12
+ };
13
+ }
14
+ describe('aligned grids', () => {
15
+ it('mirrors horizontal scroll to peers in the same group', () => {
16
+ const a = makeCtx('g');
17
+ const b = makeCtx('g');
18
+ const ha = createAlignedGrids(a);
19
+ const hb = createAlignedGrids(b);
20
+ const un1 = ha.register();
21
+ const un2 = hb.register();
22
+ ha.broadcastScroll(240);
23
+ expect(b.scrollContainer.scrollLeft).toBe(240);
24
+ // and the other way
25
+ hb.broadcastScroll(80);
26
+ expect(a.scrollContainer.scrollLeft).toBe(80);
27
+ un1();
28
+ un2();
29
+ });
30
+ it('mirrors column-resize widths to peers (matched by column id)', () => {
31
+ const a = makeCtx('g');
32
+ const b = makeCtx('g');
33
+ const ha = createAlignedGrids(a);
34
+ const hb = createAlignedGrids(b);
35
+ ha.register();
36
+ hb.register();
37
+ a.columnWidths = { Feb: 180 };
38
+ ha.broadcastWidths();
39
+ expect(b.columnWidths.Feb).toBe(180);
40
+ });
41
+ it('does NOT mirror across different groups', () => {
42
+ const a = makeCtx('one');
43
+ const b = makeCtx('two');
44
+ const ha = createAlignedGrids(a);
45
+ const hb = createAlignedGrids(b);
46
+ ha.register();
47
+ hb.register();
48
+ ha.broadcastScroll(200);
49
+ expect(b.scrollContainer.scrollLeft).toBe(0);
50
+ a.columnWidths = { Feb: 999 };
51
+ ha.broadcastWidths();
52
+ expect(b.columnWidths.Feb).toBeUndefined();
53
+ });
54
+ it('is inert with no group set, and after unregister', () => {
55
+ const a = makeCtx(undefined);
56
+ const b = makeCtx(undefined);
57
+ const ha = createAlignedGrids(a);
58
+ const hb = createAlignedGrids(b);
59
+ ha.register();
60
+ hb.register();
61
+ ha.broadcastScroll(120);
62
+ expect(b.scrollContainer.scrollLeft).toBe(0);
63
+ // Grouped, then unregistered -> no longer receives updates.
64
+ const c = makeCtx('gg');
65
+ const d = makeCtx('gg');
66
+ const hc = createAlignedGrids(c);
67
+ const hd = createAlignedGrids(d);
68
+ const unc = hc.register();
69
+ const und = hd.register();
70
+ und(); // d leaves the group
71
+ hc.broadcastScroll(55);
72
+ expect(d.scrollContainer.scrollLeft).toBe(0);
73
+ unc();
74
+ });
75
+ });
@@ -0,0 +1,20 @@
1
+ /**
2
+ * Coverage-focused behavioral tests for the SvGridApi assembled in
3
+ * `build-api.ts`. The existing `svgrid.api.test.ts` / `svgrid.api-extensions
4
+ * .test.ts` cover filters, row selection, pagination, navigation, and
5
+ * getState/setState. This file exercises the remaining surface:
6
+ * - getCellValue / setCellValue
7
+ * - selectCells / getSelected
8
+ * - addRow(s) / removeRow(s) / applyTransaction
9
+ * - addColumn(s) / removeColumn / setColumnVisible / getColumns
10
+ * - setColumnWidth / setColumnPinning / setColumnOrder
11
+ * - setFacetFilter
12
+ * - undo / redo / canUndo / canRedo / clearHistory
13
+ * - find (open/close/query/hits)
14
+ * - grouping (setGroupBy / expandAllGroups / collapseAllGroups)
15
+ * - autosizeColumn / refresh
16
+ *
17
+ * All tests mount the real <SvGrid /> in jsdom and drive the api handed back
18
+ * from onApiReady.
19
+ */
20
+ export {};