@svgrid/grid 1.1.2 → 1.2.3

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 (143) hide show
  1. package/dist/SvGrid.css +294 -16
  2. package/dist/SvGrid.svelte +4 -1
  3. package/dist/SvGridDropdown.svelte +7 -3
  4. package/dist/cdn/svgrid.js +13506 -0
  5. package/dist/cdn/svgrid.svelte-external.js +11190 -0
  6. package/package.json +12 -2
  7. package/src/SvGrid.css +294 -16
  8. package/src/SvGrid.svelte +4 -1
  9. package/src/SvGridDropdown.svelte +7 -3
  10. package/dist/SvGrid.helpers.test.d.ts +0 -1
  11. package/dist/SvGrid.helpers.test.js +0 -298
  12. package/dist/SvGridChart.test.d.ts +0 -1
  13. package/dist/SvGridChart.test.js +0 -62
  14. package/dist/a11y.contract.test.d.ts +0 -1
  15. package/dist/a11y.contract.test.js +0 -39
  16. package/dist/a11y.test.d.ts +0 -1
  17. package/dist/a11y.test.js +0 -44
  18. package/dist/aligned-grids.test.d.ts +0 -1
  19. package/dist/aligned-grids.test.js +0 -75
  20. package/dist/build-api.coverage.test.d.ts +0 -20
  21. package/dist/build-api.coverage.test.js +0 -505
  22. package/dist/cell-formatting.test.d.ts +0 -1
  23. package/dist/cell-formatting.test.js +0 -234
  24. package/dist/cell-render.test.d.ts +0 -1
  25. package/dist/cell-render.test.js +0 -338
  26. package/dist/chart-export.test.d.ts +0 -1
  27. package/dist/chart-export.test.js +0 -302
  28. package/dist/chart.coverage.test.d.ts +0 -1
  29. package/dist/chart.coverage.test.js +0 -748
  30. package/dist/chart.test.d.ts +0 -1
  31. package/dist/chart.test.js +0 -289
  32. package/dist/clipboard.test.d.ts +0 -1
  33. package/dist/clipboard.test.js +0 -700
  34. package/dist/collaboration.coverage.test.d.ts +0 -1
  35. package/dist/collaboration.coverage.test.js +0 -200
  36. package/dist/collaboration.test.d.ts +0 -1
  37. package/dist/collaboration.test.js +0 -65
  38. package/dist/column-groups.test.d.ts +0 -1
  39. package/dist/column-groups.test.js +0 -56
  40. package/dist/column-types.test.d.ts +0 -1
  41. package/dist/column-types.test.js +0 -62
  42. package/dist/columns.test.d.ts +0 -1
  43. package/dist/columns.test.js +0 -625
  44. package/dist/conditional-formatting.test.d.ts +0 -1
  45. package/dist/conditional-formatting.test.js +0 -87
  46. package/dist/core.coverage.test.d.ts +0 -1
  47. package/dist/core.coverage.test.js +0 -186
  48. package/dist/core.performance.test.d.ts +0 -1
  49. package/dist/core.performance.test.js +0 -29
  50. package/dist/createGrid.test.d.ts +0 -1
  51. package/dist/createGrid.test.js +0 -9
  52. package/dist/editing.test.d.ts +0 -1
  53. package/dist/editing.test.js +0 -732
  54. package/dist/editors/cell-editors.coverage.test.d.ts +0 -1
  55. package/dist/editors/cell-editors.coverage.test.js +0 -139
  56. package/dist/editors/cell-editors.test.d.ts +0 -1
  57. package/dist/editors/cell-editors.test.js +0 -75
  58. package/dist/facet-buckets.test.d.ts +0 -1
  59. package/dist/facet-buckets.test.js +0 -296
  60. package/dist/fill-patterns.test.d.ts +0 -1
  61. package/dist/fill-patterns.test.js +0 -81
  62. package/dist/filter-operators.test.d.ts +0 -1
  63. package/dist/filter-operators.test.js +0 -135
  64. package/dist/filtering/excel-filters.test.d.ts +0 -1
  65. package/dist/filtering/excel-filters.test.js +0 -116
  66. package/dist/filtering/locale-filter.test.d.ts +0 -13
  67. package/dist/filtering/locale-filter.test.js +0 -189
  68. package/dist/flex-render.test.d.ts +0 -1
  69. package/dist/flex-render.test.js +0 -142
  70. package/dist/group-aggregate.test.d.ts +0 -1
  71. package/dist/group-aggregate.test.js +0 -32
  72. package/dist/hyperformula-adapter.test.d.ts +0 -1
  73. package/dist/hyperformula-adapter.test.js +0 -205
  74. package/dist/keyboard-handlers.coverage.test.d.ts +0 -1
  75. package/dist/keyboard-handlers.coverage.test.js +0 -495
  76. package/dist/keyboard.test.d.ts +0 -1
  77. package/dist/keyboard.test.js +0 -27
  78. package/dist/menus.test.d.ts +0 -1
  79. package/dist/menus.test.js +0 -560
  80. package/dist/named-views.coverage.test.d.ts +0 -1
  81. package/dist/named-views.coverage.test.js +0 -180
  82. package/dist/named-views.test.d.ts +0 -1
  83. package/dist/named-views.test.js +0 -57
  84. package/dist/new-features.test.d.ts +0 -1
  85. package/dist/new-features.test.js +0 -183
  86. package/dist/render-component.test.d.ts +0 -1
  87. package/dist/render-component.test.js +0 -41
  88. package/dist/row-drag.test.d.ts +0 -1
  89. package/dist/row-drag.test.js +0 -142
  90. package/dist/row-resize.test.d.ts +0 -1
  91. package/dist/row-resize.test.js +0 -329
  92. package/dist/scroll-sync.test.d.ts +0 -1
  93. package/dist/scroll-sync.test.js +0 -290
  94. package/dist/selection.multi-range.test.d.ts +0 -1
  95. package/dist/selection.multi-range.test.js +0 -55
  96. package/dist/selection.test.d.ts +0 -1
  97. package/dist/selection.test.js +0 -647
  98. package/dist/server-data-source.coverage.test.d.ts +0 -1
  99. package/dist/server-data-source.coverage.test.js +0 -154
  100. package/dist/server-data-source.test.d.ts +0 -1
  101. package/dist/server-data-source.test.js +0 -81
  102. package/dist/sparkline.test.d.ts +0 -1
  103. package/dist/sparkline.test.js +0 -52
  104. package/dist/spreadsheet.test.d.ts +0 -1
  105. package/dist/spreadsheet.test.js +0 -446
  106. package/dist/subscribe.test.d.ts +0 -1
  107. package/dist/subscribe.test.js +0 -93
  108. package/dist/svgrid.api-extensions.test.d.ts +0 -14
  109. package/dist/svgrid.api-extensions.test.js +0 -334
  110. package/dist/svgrid.api.test.d.ts +0 -15
  111. package/dist/svgrid.api.test.js +0 -169
  112. package/dist/svgrid.behavior.test.d.ts +0 -15
  113. package/dist/svgrid.behavior.test.js +0 -625
  114. package/dist/svgrid.column-reorder.test.d.ts +0 -15
  115. package/dist/svgrid.column-reorder.test.js +0 -224
  116. package/dist/svgrid.comments-autocomplete.test.d.ts +0 -1
  117. package/dist/svgrid.comments-autocomplete.test.js +0 -96
  118. package/dist/svgrid.context-menu.test.d.ts +0 -1
  119. package/dist/svgrid.context-menu.test.js +0 -102
  120. package/dist/svgrid.features.test.d.ts +0 -1
  121. package/dist/svgrid.features.test.js +0 -129
  122. package/dist/svgrid.interaction.test.d.ts +0 -9
  123. package/dist/svgrid.interaction.test.js +0 -349
  124. package/dist/svgrid.locale-filtering.test.d.ts +0 -15
  125. package/dist/svgrid.locale-filtering.test.js +0 -261
  126. package/dist/svgrid.new-features.wrapper.test.d.ts +0 -1
  127. package/dist/svgrid.new-features.wrapper.test.js +0 -194
  128. package/dist/svgrid.row-pinning.test.d.ts +0 -14
  129. package/dist/svgrid.row-pinning.test.js +0 -250
  130. package/dist/svgrid.set-filter.test.d.ts +0 -17
  131. package/dist/svgrid.set-filter.test.js +0 -268
  132. package/dist/svgrid.wrapper.test.d.ts +0 -1
  133. package/dist/svgrid.wrapper.test.js +0 -59
  134. package/dist/test-setup.d.ts +0 -1
  135. package/dist/test-setup.js +0 -35
  136. package/dist/transaction.test.d.ts +0 -1
  137. package/dist/transaction.test.js +0 -89
  138. package/dist/virtualization/column-virtualizer.test.d.ts +0 -1
  139. package/dist/virtualization/column-virtualizer.test.js +0 -25
  140. package/dist/virtualization/scroll-scaling.test.d.ts +0 -1
  141. package/dist/virtualization/scroll-scaling.test.js +0 -127
  142. package/dist/virtualization/virtualizer.test.d.ts +0 -1
  143. package/dist/virtualization/virtualizer.test.js +0 -41
@@ -1,224 +0,0 @@
1
- /**
2
- * Component tests for engine-level column reorder. Mount a real
3
- * <SvGrid> with `enableColumnReorder={true}`, then exercise both
4
- * surfaces:
5
- *
6
- * - Imperative: api.setColumnOrder() / getColumnOrder() reorders the
7
- * DOM and fires onColumnOrderChange.
8
- * - User drag: dispatch dragstart / dragover / drop events on header
9
- * elements, assert the resulting DOM order matches the drop side.
10
- * - Drop indicator: the hovered header gets `is-drag-target-before` /
11
- * `is-drag-target-after` while a drag is in flight.
12
- * - Headers carry `draggable=true` only when the prop is on.
13
- * - Pin groups: reorder within a pin group is honored.
14
- */
15
- import { describe, expect, it } from 'vitest';
16
- import { mount, unmount } from 'svelte';
17
- import SvGrid from './SvGrid.svelte';
18
- import { columnFilteringFeature, createCoreRowModel, createFilteredRowModel, createSortedRowModel, rowSortingFeature, sortFns, tableFeatures, } from './index';
19
- const features = tableFeatures({ columnFilteringFeature, rowSortingFeature });
20
- const rows = [
21
- { id: 'P-1', first: 'Ada', last: 'Lovelace', team: 'Research', salary: 145000 },
22
- { id: 'P-2', first: 'Linus', last: 'Torvalds', team: 'Kernel', salary: 188000 },
23
- { id: 'P-3', first: 'Grace', last: 'Hopper', team: 'Compilers', salary: 152000 },
24
- ];
25
- const cols = [
26
- { field: 'id', header: 'ID', width: 100 },
27
- { field: 'first', header: 'First', width: 140 },
28
- { field: 'last', header: 'Last', width: 140 },
29
- { field: 'team', header: 'Team', width: 160 },
30
- { field: 'salary', header: 'Salary', width: 130 },
31
- ];
32
- function mountGrid(opts = {}) {
33
- return new Promise((res, rej) => {
34
- const target = document.createElement('div');
35
- document.body.appendChild(target);
36
- let api = null;
37
- const app = mount(SvGrid, {
38
- target,
39
- props: {
40
- data: rows,
41
- columns: cols,
42
- features,
43
- _rowModels: {
44
- coreRowModel: createCoreRowModel(),
45
- filteredRowModel: createFilteredRowModel(),
46
- sortedRowModel: createSortedRowModel(sortFns),
47
- },
48
- containerHeight: 360,
49
- virtualization: false,
50
- columnVirtualization: false,
51
- enableInlineEditing: false,
52
- showPagination: false,
53
- showColumnFilters: false,
54
- showGlobalFilter: false,
55
- showRowSelection: false,
56
- enableColumnReorder: opts.enableColumnReorder,
57
- columnOrder: opts.columnOrder,
58
- onColumnOrderChange: opts.onColumnOrderChange,
59
- onApiReady(received) {
60
- api = received;
61
- res({
62
- target,
63
- api,
64
- destroy: () => {
65
- unmount(app);
66
- target.remove();
67
- },
68
- });
69
- },
70
- },
71
- });
72
- queueMicrotask(() => { if (!api)
73
- rej(new Error('onApiReady never fired')); });
74
- });
75
- }
76
- const tick = () => new Promise((r) => queueMicrotask(r));
77
- function headerOrder(target) {
78
- const ths = target.querySelectorAll('th[data-svgrid-header-col]');
79
- return Array.from(ths).map((th) => th.dataset.svgridHeaderCol ?? '');
80
- }
81
- function header(target, id) {
82
- // jsdom doesn't ship CSS.escape; our ids are simple alphanumerics so
83
- // a plain attribute selector is fine.
84
- const el = target.querySelector(`th[data-svgrid-header-col="${id}"]`);
85
- if (!el)
86
- throw new Error(`header not found: ${id}`);
87
- return el;
88
- }
89
- describe('SvGrid column reorder - default off', () => {
90
- it('does NOT set draggable on headers when the prop is unset', async () => {
91
- const { target, destroy } = await mountGrid();
92
- try {
93
- await tick();
94
- const draggables = target.querySelectorAll('th[data-svgrid-header-col][draggable="true"]');
95
- expect(draggables.length).toBe(0);
96
- }
97
- finally {
98
- destroy();
99
- }
100
- });
101
- });
102
- describe('SvGrid column reorder - enableColumnReorder=true', () => {
103
- it('sets draggable=true on every visible header', async () => {
104
- const { target, destroy } = await mountGrid({ enableColumnReorder: true });
105
- try {
106
- await tick();
107
- const ths = target.querySelectorAll('th[data-svgrid-header-col]');
108
- expect(ths.length).toBe(cols.length);
109
- for (const th of ths) {
110
- expect(th.getAttribute('draggable')).toBe('true');
111
- }
112
- }
113
- finally {
114
- destroy();
115
- }
116
- });
117
- it('honors the initial columnOrder prop', async () => {
118
- const order = ['salary', 'id', 'last', 'first', 'team'];
119
- const { target, destroy } = await mountGrid({
120
- enableColumnReorder: true,
121
- columnOrder: order,
122
- });
123
- try {
124
- await tick();
125
- expect(headerOrder(target)).toEqual(order);
126
- }
127
- finally {
128
- destroy();
129
- }
130
- });
131
- });
132
- describe('SvGrid column reorder - imperative api', () => {
133
- it('api.getColumnOrder() returns the current visual order', async () => {
134
- const { api, destroy } = await mountGrid({ enableColumnReorder: true });
135
- try {
136
- expect(api.getColumnOrder()).toEqual(['id', 'first', 'last', 'team', 'salary']);
137
- }
138
- finally {
139
- destroy();
140
- }
141
- });
142
- it('api.setColumnOrder() reorders the DOM headers', async () => {
143
- const { target, api, destroy } = await mountGrid({ enableColumnReorder: true });
144
- try {
145
- api.setColumnOrder(['team', 'id', 'salary', 'first', 'last']);
146
- await tick();
147
- expect(headerOrder(target)).toEqual(['team', 'id', 'salary', 'first', 'last']);
148
- }
149
- finally {
150
- destroy();
151
- }
152
- });
153
- it('api.setColumnOrder() fires onColumnOrderChange with the new order', async () => {
154
- const events = [];
155
- const { api, destroy } = await mountGrid({
156
- enableColumnReorder: true,
157
- onColumnOrderChange: (order) => events.push([...order]),
158
- });
159
- try {
160
- api.setColumnOrder(['last', 'first', 'id', 'team', 'salary']);
161
- await tick();
162
- expect(events.length).toBeGreaterThanOrEqual(1);
163
- const latest = events[events.length - 1];
164
- expect(latest).toEqual(['last', 'first', 'id', 'team', 'salary']);
165
- }
166
- finally {
167
- destroy();
168
- }
169
- });
170
- it('api.setColumnOrder() with a partial list keeps unlisted columns in their existing relative position', async () => {
171
- // Pass only ['salary', 'id']; the other three keep their original
172
- // relative order AFTER the listed ones.
173
- const { target, api, destroy } = await mountGrid({ enableColumnReorder: true });
174
- try {
175
- api.setColumnOrder(['salary', 'id']);
176
- await tick();
177
- const order = headerOrder(target);
178
- expect(order[0]).toBe('salary');
179
- expect(order[1]).toBe('id');
180
- // The remaining columns (first / last / team) should follow,
181
- // in their original relative order from `cols`.
182
- expect(order.slice(2)).toEqual(['first', 'last', 'team']);
183
- }
184
- finally {
185
- destroy();
186
- }
187
- });
188
- });
189
- describe('SvGrid column reorder - drag wiring (DOM)', () => {
190
- // Note: jsdom does not ship `DragEvent`, so we can't drive the full
191
- // dragstart → dragover → drop pipeline end-to-end here. Real-browser
192
- // coverage lives in the Playwright suite. These tests verify that the
193
- // wiring IS present in the DOM so a real DragEvent would reach the
194
- // grid's reactive state.
195
- it('every header has dragstart / dragover / dragleave / drop / dragend listeners attached', async () => {
196
- const { target, destroy } = await mountGrid({ enableColumnReorder: true });
197
- try {
198
- await tick();
199
- const ths = target.querySelectorAll('th[data-svgrid-header-col]');
200
- expect(ths.length).toBe(cols.length);
201
- // Each <th> must be draggable AND have an onclick-equivalent
202
- // dispatch chain. We can't easily probe addEventListener
203
- // attachments, so use the `draggable` attribute as the proxy -
204
- // the grid only sets it when listeners are wired.
205
- for (const th of ths) {
206
- expect(th.getAttribute('draggable')).toBe('true');
207
- }
208
- }
209
- finally {
210
- destroy();
211
- }
212
- });
213
- it('does NOT add the drop-target class before any drag is initiated', async () => {
214
- const { target, destroy } = await mountGrid({ enableColumnReorder: true });
215
- try {
216
- await tick();
217
- const drop = target.querySelectorAll('.is-drag-target-before, .is-drag-target-after, .is-dragging');
218
- expect(drop.length).toBe(0);
219
- }
220
- finally {
221
- destroy();
222
- }
223
- });
224
- });
@@ -1 +0,0 @@
1
- export {};
@@ -1,96 +0,0 @@
1
- /**
2
- * Track C: free-text autocomplete cell type + editable cell comments.
3
- */
4
- import { describe, expect, it } from 'vitest';
5
- import { mount, unmount } from 'svelte';
6
- import SvGrid from './SvGrid.svelte';
7
- import { createCoreRowModel, tableFeatures } from './index';
8
- const features = tableFeatures({});
9
- const rows = [
10
- { id: 1, name: 'Ann', city: 'Paris' },
11
- { id: 2, name: 'Bo', city: 'Berlin' },
12
- ];
13
- const tick = () => new Promise((r) => queueMicrotask(r));
14
- function mountGrid(extraCols, props = {}) {
15
- return new Promise((res) => {
16
- const target = document.createElement('div');
17
- document.body.appendChild(target);
18
- const app = mount(SvGrid, {
19
- target,
20
- props: {
21
- data: rows,
22
- columns: [{ field: 'name', header: 'Name', width: 160, editorType: 'text' }, ...extraCols],
23
- features,
24
- _rowModels: { coreRowModel: createCoreRowModel() },
25
- rowHeight: 32,
26
- containerHeight: 360,
27
- virtualization: false,
28
- enableInlineEditing: true,
29
- enableCellSelection: true,
30
- onApiReady(api) {
31
- res({ api, target, destroy: () => { unmount(app); target.remove(); } });
32
- },
33
- ...props,
34
- },
35
- });
36
- });
37
- }
38
- function dataCell(target, col) {
39
- return target.querySelectorAll('.sv-grid-cell[data-svgrid-row]')[col];
40
- }
41
- describe('autocomplete cell type', () => {
42
- it('filters suggestions as you type and commits the picked option', async () => {
43
- const { api, target, destroy } = await mountGrid([
44
- {
45
- field: 'city',
46
- header: 'City',
47
- width: 200,
48
- editorType: 'autocomplete',
49
- editorOptions: ['Paris', 'Berlin', 'Boston', 'Brussels'],
50
- },
51
- ]);
52
- await tick();
53
- // city is the 2nd column => index 1 in the first row's cells
54
- const cell = target.querySelectorAll('.sv-grid-cell[data-svgrid-row="0"]')[1];
55
- cell.dispatchEvent(new MouseEvent('dblclick', { bubbles: true }));
56
- await tick();
57
- const input = target.querySelector('.sv-grid-cell-editor-autocomplete');
58
- expect(input).not.toBeNull();
59
- input.value = 'B';
60
- input.dispatchEvent(new Event('input', { bubbles: true }));
61
- await tick();
62
- const opts = [...target.querySelectorAll('.sv-grid-autocomplete-option')].map((b) => b.textContent?.trim());
63
- // 'B' matches Berlin, Boston, Brussels - not Paris
64
- expect(opts).toEqual(['Berlin', 'Boston', 'Brussels']);
65
- const berlin = [...target.querySelectorAll('.sv-grid-autocomplete-option')].find((b) => b.textContent?.trim() === 'Boston');
66
- berlin.dispatchEvent(new MouseEvent('mousedown', { bubbles: true }));
67
- await tick();
68
- expect(api.getCellValue(0, 'city')).toBe('Boston');
69
- destroy();
70
- });
71
- });
72
- describe('editable comments', () => {
73
- it('adds a comment via the context menu and emits onNoteChange', async () => {
74
- const changes = [];
75
- const { target, destroy } = await mountGrid([{ field: 'city', header: 'City', width: 200, editorType: 'text' }], { contextMenu: true, editableComments: true, onNoteChange: (e) => changes.push(e) });
76
- await tick();
77
- const cell = dataCell(target, 0);
78
- cell.dispatchEvent(new MouseEvent('contextmenu', { bubbles: true, cancelable: true }));
79
- await tick();
80
- const editItem = [...target.querySelectorAll('.sv-grid-context-menu .sv-grid-menu-item')].find((b) => b.textContent?.trim() === 'Edit comment');
81
- expect(editItem).toBeTruthy();
82
- editItem.click();
83
- await tick();
84
- const ta = target.querySelector('.sv-grid-comment-textarea');
85
- expect(ta).not.toBeNull();
86
- ta.value = 'Needs review';
87
- ta.dispatchEvent(new Event('input', { bubbles: true }));
88
- await tick();
89
- target.querySelector('.sv-grid-comment-save').click();
90
- await tick();
91
- expect(changes.length).toBe(1);
92
- expect(changes[0].note).toBe('Needs review');
93
- expect(target.querySelector('.sv-grid-comment-editor')).toBeNull();
94
- destroy();
95
- });
96
- });
@@ -1 +0,0 @@
1
- export {};
@@ -1,102 +0,0 @@
1
- /**
2
- * Right-click context menu (Track A). Mounts a grid with `contextMenu`,
3
- * fires a synthetic `contextmenu` event on a cell, and asserts the menu
4
- * opens with the expected items and that actions/close work.
5
- */
6
- import { describe, expect, it } from 'vitest';
7
- import { mount, unmount } from 'svelte';
8
- import SvGrid from './SvGrid.svelte';
9
- import { createCoreRowModel, createFilteredRowModel, createSortedRowModel, rowSelectionFeature, rowSortingFeature, sortFns, tableFeatures, } from './index';
10
- const features = tableFeatures({ rowSortingFeature, rowSelectionFeature });
11
- const rows = Array.from({ length: 6 }, (_, i) => ({
12
- id: i + 1,
13
- name: `Person ${i + 1}`,
14
- team: ['A', 'B'][i % 2],
15
- }));
16
- const cols = [
17
- { field: 'name', header: 'Name', width: 200, editorType: 'text' },
18
- { field: 'team', header: 'Team', width: 160, editorType: 'text' },
19
- ];
20
- const tick = () => new Promise((r) => queueMicrotask(r));
21
- function mountGrid(contextMenu) {
22
- return new Promise((res, rej) => {
23
- const target = document.createElement('div');
24
- document.body.appendChild(target);
25
- const app = mount(SvGrid, {
26
- target,
27
- props: {
28
- data: rows,
29
- columns: cols,
30
- features,
31
- _rowModels: {
32
- coreRowModel: createCoreRowModel(),
33
- filteredRowModel: createFilteredRowModel(),
34
- sortedRowModel: createSortedRowModel(sortFns),
35
- },
36
- rowHeight: 32,
37
- containerHeight: 400,
38
- virtualization: false,
39
- enableCellSelection: true,
40
- contextMenu,
41
- onApiReady(api) {
42
- res({ api, target, destroy: () => { unmount(app); target.remove(); } });
43
- },
44
- },
45
- });
46
- queueMicrotask(() => { if (!target.querySelector('[role="grid"]'))
47
- rej(new Error('no grid')); });
48
- });
49
- }
50
- function rightClickFirstCell(target) {
51
- const cell = target.querySelector('.sv-grid-cell[data-svgrid-row]');
52
- const r = cell.getBoundingClientRect();
53
- cell.dispatchEvent(new MouseEvent('contextmenu', { bubbles: true, cancelable: true, clientX: r.x + 4, clientY: r.y + 4 }));
54
- return cell;
55
- }
56
- describe('SvGrid context menu', () => {
57
- it('opens the default menu on right-click with the built-in items', async () => {
58
- const { target, destroy } = await mountGrid(true);
59
- await tick();
60
- rightClickFirstCell(target);
61
- await tick();
62
- const menu = target.querySelector('.sv-grid-context-menu');
63
- expect(menu).not.toBeNull();
64
- const labels = [...menu.querySelectorAll('.sv-grid-menu-item')].map((b) => b.textContent?.trim());
65
- expect(labels).toContain('Copy');
66
- expect(labels).toContain('Paste');
67
- expect(labels).toContain('Remove row');
68
- expect(labels).toContain('Remove column');
69
- destroy();
70
- });
71
- it('does not open when contextMenu is omitted (native menu shows)', async () => {
72
- const { target, destroy } = await mountGrid(undefined);
73
- await tick();
74
- const cell = target.querySelector('.sv-grid-cell[data-svgrid-row]');
75
- const ev = new MouseEvent('contextmenu', { bubbles: true, cancelable: true });
76
- cell.dispatchEvent(ev);
77
- await tick();
78
- expect(target.querySelector('.sv-grid-context-menu')).toBeNull();
79
- expect(ev.defaultPrevented).toBe(false);
80
- destroy();
81
- });
82
- it('renders only the configured custom items and runs the action', async () => {
83
- let ran = 0;
84
- const items = [
85
- 'copy',
86
- 'separator',
87
- { key: 'flag', label: 'Flag row', action: () => { ran += 1; } },
88
- ];
89
- const { target, destroy } = await mountGrid(items);
90
- await tick();
91
- rightClickFirstCell(target);
92
- await tick();
93
- const labels = [...target.querySelectorAll('.sv-grid-context-menu .sv-grid-menu-item')].map((b) => b.textContent?.trim());
94
- expect(labels).toEqual(['Copy', 'Flag row']);
95
- const flag = [...target.querySelectorAll('.sv-grid-context-menu .sv-grid-menu-item')].find((b) => b.textContent?.trim() === 'Flag row');
96
- flag.click();
97
- expect(ran).toBe(1);
98
- await tick();
99
- expect(target.querySelector('.sv-grid-context-menu')).toBeNull();
100
- destroy();
101
- });
102
- });
@@ -1 +0,0 @@
1
- export {};
@@ -1,129 +0,0 @@
1
- import { describe, expect, it } from 'vitest';
2
- import { columnFilteringFeature, columnGroupingFeature, createCoreRowModel, createExpandedRowModel, createFilteredRowModel, createGroupedRowModel, createPaginatedRowModel, createSortedRowModel, createSvGrid, rowExpandingFeature, rowSelectionFeature, rowSortingFeature, sortFns, subscribeSvGrid, tableFeatures, } from './index';
3
- describe('SvGrid features', () => {
4
- it('supports sorting and pagination row model pipeline', () => {
5
- const _features = tableFeatures({
6
- columnFilteringFeature,
7
- columnGroupingFeature,
8
- rowExpandingFeature,
9
- rowSelectionFeature,
10
- rowSortingFeature,
11
- });
12
- const columns = [
13
- { field: 'firstName' },
14
- { field: 'age' },
15
- ];
16
- const data = [
17
- { firstName: 'John', age: 40, status: 'pending' },
18
- { firstName: 'Amy', age: 22, status: 'active' },
19
- { firstName: 'Kate', age: 31, status: 'active' },
20
- ];
21
- const grid = createSvGrid({
22
- _features,
23
- _rowModels: {
24
- coreRowModel: createCoreRowModel(),
25
- filteredRowModel: createFilteredRowModel(),
26
- sortedRowModel: createSortedRowModel(sortFns),
27
- groupedRowModel: createGroupedRowModel(),
28
- expandedRowModel: createExpandedRowModel(),
29
- paginatedRowModel: createPaginatedRowModel(),
30
- },
31
- columns,
32
- data,
33
- state: {
34
- columnFilters: [{ id: 'firstName', value: 'a', fn: 'includesString' }],
35
- grouping: ['status'],
36
- expanded: { group_status_active: true },
37
- sorting: [{ id: 'age', desc: false }],
38
- pagination: { pageIndex: 0, pageSize: 2 },
39
- },
40
- });
41
- const rows = grid.getRowModel().rows;
42
- expect(rows).toHaveLength(1);
43
- expect(rows[0]?.id).toContain('group_status_');
44
- });
45
- it('supports row selection and expansion toggles', () => {
46
- const _features = tableFeatures({
47
- rowExpandingFeature,
48
- rowSelectionFeature,
49
- });
50
- const columns = [
51
- { field: 'firstName' },
52
- ];
53
- const data = [
54
- { firstName: 'Amy', age: 22 },
55
- ];
56
- const grid = createSvGrid({
57
- _features,
58
- _rowModels: {
59
- coreRowModel: createCoreRowModel(),
60
- },
61
- columns,
62
- data,
63
- });
64
- const row = grid.getRowModel().rows[0];
65
- expect(row).toBeDefined();
66
- row?.toggleSelected();
67
- row?.toggleExpanded();
68
- expect(row?.getIsSelected()).toBe(true);
69
- expect(row?.getIsExpanded()).toBe(true);
70
- });
71
- it('supports selector subscriptions with stable shape', () => {
72
- const _features = tableFeatures({ rowSortingFeature });
73
- const grid = createSvGrid({
74
- _features,
75
- _rowModels: {
76
- coreRowModel: createCoreRowModel(),
77
- },
78
- columns: [{ field: 'firstName' }],
79
- data: [{ firstName: 'Amy', age: 22 }],
80
- });
81
- const selected = subscribeSvGrid(grid, (state) => ({
82
- sorting: state.sorting,
83
- pageIndex: state.pagination?.pageIndex ?? 0,
84
- }));
85
- expect(selected.current.pageIndex).toBe(0);
86
- });
87
- it('supports active cell movement primitives', () => {
88
- const _features = tableFeatures({ rowSortingFeature });
89
- const grid = createSvGrid({
90
- _features,
91
- _rowModels: { coreRowModel: createCoreRowModel() },
92
- columns: [
93
- { field: 'firstName' },
94
- { field: 'age' },
95
- ],
96
- data: [
97
- { firstName: 'Amy', age: 22 },
98
- { firstName: 'John', age: 40 },
99
- ],
100
- });
101
- grid.moveActiveCell({ rowDelta: 1, colDelta: 1 });
102
- expect(grid.getState().activeCell.rowIndex).toBe(1);
103
- expect(grid.getState().activeCell.colIndex).toBe(1);
104
- });
105
- it('supports multi-column sorting clauses', () => {
106
- const _features = tableFeatures({ rowSortingFeature });
107
- const grid = createSvGrid({
108
- _features,
109
- _rowModels: {
110
- coreRowModel: createCoreRowModel(),
111
- sortedRowModel: createSortedRowModel(sortFns),
112
- },
113
- columns: [
114
- { field: 'firstName' },
115
- { field: 'age', editorType: 'number' },
116
- ],
117
- data: [
118
- { firstName: 'Amy', age: 20 },
119
- { firstName: 'Amy', age: 30 },
120
- { firstName: 'Bob', age: 10 },
121
- ],
122
- state: { sorting: [{ id: 'firstName', desc: false }, { id: 'age', desc: true }] },
123
- });
124
- const rows = grid.getRowModel().rows;
125
- expect(rows[0]?.original.firstName).toBe('Amy');
126
- expect(rows[0]?.original.age).toBe(30);
127
- expect(rows[1]?.original.age).toBe(20);
128
- });
129
- });
@@ -1,9 +0,0 @@
1
- /**
2
- * Interaction-driven tests against <SvGrid />. Targeting code paths that
3
- * only run in response to events: keyboard, pointer, scroll, edit lifecycle.
4
- *
5
- * Each test mounts a small grid, fires a synthetic event, awaits a tick,
6
- * then asserts on the api object's snapshot. The goal is breadth: hit as
7
- * many branches inside SvGrid.svelte as possible.
8
- */
9
- export {};