@svgrid/grid 1.1.2 → 1.2.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 (141) hide show
  1. package/dist/SvGrid.svelte +3 -1
  2. package/dist/SvGridDropdown.svelte +7 -3
  3. package/dist/cdn/svgrid.js +13504 -0
  4. package/dist/cdn/svgrid.svelte-external.js +11188 -0
  5. package/package.json +12 -2
  6. package/src/SvGrid.svelte +3 -1
  7. package/src/SvGridDropdown.svelte +7 -3
  8. package/dist/SvGrid.helpers.test.d.ts +0 -1
  9. package/dist/SvGrid.helpers.test.js +0 -298
  10. package/dist/SvGridChart.test.d.ts +0 -1
  11. package/dist/SvGridChart.test.js +0 -62
  12. package/dist/a11y.contract.test.d.ts +0 -1
  13. package/dist/a11y.contract.test.js +0 -39
  14. package/dist/a11y.test.d.ts +0 -1
  15. package/dist/a11y.test.js +0 -44
  16. package/dist/aligned-grids.test.d.ts +0 -1
  17. package/dist/aligned-grids.test.js +0 -75
  18. package/dist/build-api.coverage.test.d.ts +0 -20
  19. package/dist/build-api.coverage.test.js +0 -505
  20. package/dist/cell-formatting.test.d.ts +0 -1
  21. package/dist/cell-formatting.test.js +0 -234
  22. package/dist/cell-render.test.d.ts +0 -1
  23. package/dist/cell-render.test.js +0 -338
  24. package/dist/chart-export.test.d.ts +0 -1
  25. package/dist/chart-export.test.js +0 -302
  26. package/dist/chart.coverage.test.d.ts +0 -1
  27. package/dist/chart.coverage.test.js +0 -748
  28. package/dist/chart.test.d.ts +0 -1
  29. package/dist/chart.test.js +0 -289
  30. package/dist/clipboard.test.d.ts +0 -1
  31. package/dist/clipboard.test.js +0 -700
  32. package/dist/collaboration.coverage.test.d.ts +0 -1
  33. package/dist/collaboration.coverage.test.js +0 -200
  34. package/dist/collaboration.test.d.ts +0 -1
  35. package/dist/collaboration.test.js +0 -65
  36. package/dist/column-groups.test.d.ts +0 -1
  37. package/dist/column-groups.test.js +0 -56
  38. package/dist/column-types.test.d.ts +0 -1
  39. package/dist/column-types.test.js +0 -62
  40. package/dist/columns.test.d.ts +0 -1
  41. package/dist/columns.test.js +0 -625
  42. package/dist/conditional-formatting.test.d.ts +0 -1
  43. package/dist/conditional-formatting.test.js +0 -87
  44. package/dist/core.coverage.test.d.ts +0 -1
  45. package/dist/core.coverage.test.js +0 -186
  46. package/dist/core.performance.test.d.ts +0 -1
  47. package/dist/core.performance.test.js +0 -29
  48. package/dist/createGrid.test.d.ts +0 -1
  49. package/dist/createGrid.test.js +0 -9
  50. package/dist/editing.test.d.ts +0 -1
  51. package/dist/editing.test.js +0 -732
  52. package/dist/editors/cell-editors.coverage.test.d.ts +0 -1
  53. package/dist/editors/cell-editors.coverage.test.js +0 -139
  54. package/dist/editors/cell-editors.test.d.ts +0 -1
  55. package/dist/editors/cell-editors.test.js +0 -75
  56. package/dist/facet-buckets.test.d.ts +0 -1
  57. package/dist/facet-buckets.test.js +0 -296
  58. package/dist/fill-patterns.test.d.ts +0 -1
  59. package/dist/fill-patterns.test.js +0 -81
  60. package/dist/filter-operators.test.d.ts +0 -1
  61. package/dist/filter-operators.test.js +0 -135
  62. package/dist/filtering/excel-filters.test.d.ts +0 -1
  63. package/dist/filtering/excel-filters.test.js +0 -116
  64. package/dist/filtering/locale-filter.test.d.ts +0 -13
  65. package/dist/filtering/locale-filter.test.js +0 -189
  66. package/dist/flex-render.test.d.ts +0 -1
  67. package/dist/flex-render.test.js +0 -142
  68. package/dist/group-aggregate.test.d.ts +0 -1
  69. package/dist/group-aggregate.test.js +0 -32
  70. package/dist/hyperformula-adapter.test.d.ts +0 -1
  71. package/dist/hyperformula-adapter.test.js +0 -205
  72. package/dist/keyboard-handlers.coverage.test.d.ts +0 -1
  73. package/dist/keyboard-handlers.coverage.test.js +0 -495
  74. package/dist/keyboard.test.d.ts +0 -1
  75. package/dist/keyboard.test.js +0 -27
  76. package/dist/menus.test.d.ts +0 -1
  77. package/dist/menus.test.js +0 -560
  78. package/dist/named-views.coverage.test.d.ts +0 -1
  79. package/dist/named-views.coverage.test.js +0 -180
  80. package/dist/named-views.test.d.ts +0 -1
  81. package/dist/named-views.test.js +0 -57
  82. package/dist/new-features.test.d.ts +0 -1
  83. package/dist/new-features.test.js +0 -183
  84. package/dist/render-component.test.d.ts +0 -1
  85. package/dist/render-component.test.js +0 -41
  86. package/dist/row-drag.test.d.ts +0 -1
  87. package/dist/row-drag.test.js +0 -142
  88. package/dist/row-resize.test.d.ts +0 -1
  89. package/dist/row-resize.test.js +0 -329
  90. package/dist/scroll-sync.test.d.ts +0 -1
  91. package/dist/scroll-sync.test.js +0 -290
  92. package/dist/selection.multi-range.test.d.ts +0 -1
  93. package/dist/selection.multi-range.test.js +0 -55
  94. package/dist/selection.test.d.ts +0 -1
  95. package/dist/selection.test.js +0 -647
  96. package/dist/server-data-source.coverage.test.d.ts +0 -1
  97. package/dist/server-data-source.coverage.test.js +0 -154
  98. package/dist/server-data-source.test.d.ts +0 -1
  99. package/dist/server-data-source.test.js +0 -81
  100. package/dist/sparkline.test.d.ts +0 -1
  101. package/dist/sparkline.test.js +0 -52
  102. package/dist/spreadsheet.test.d.ts +0 -1
  103. package/dist/spreadsheet.test.js +0 -446
  104. package/dist/subscribe.test.d.ts +0 -1
  105. package/dist/subscribe.test.js +0 -93
  106. package/dist/svgrid.api-extensions.test.d.ts +0 -14
  107. package/dist/svgrid.api-extensions.test.js +0 -334
  108. package/dist/svgrid.api.test.d.ts +0 -15
  109. package/dist/svgrid.api.test.js +0 -169
  110. package/dist/svgrid.behavior.test.d.ts +0 -15
  111. package/dist/svgrid.behavior.test.js +0 -625
  112. package/dist/svgrid.column-reorder.test.d.ts +0 -15
  113. package/dist/svgrid.column-reorder.test.js +0 -224
  114. package/dist/svgrid.comments-autocomplete.test.d.ts +0 -1
  115. package/dist/svgrid.comments-autocomplete.test.js +0 -96
  116. package/dist/svgrid.context-menu.test.d.ts +0 -1
  117. package/dist/svgrid.context-menu.test.js +0 -102
  118. package/dist/svgrid.features.test.d.ts +0 -1
  119. package/dist/svgrid.features.test.js +0 -129
  120. package/dist/svgrid.interaction.test.d.ts +0 -9
  121. package/dist/svgrid.interaction.test.js +0 -349
  122. package/dist/svgrid.locale-filtering.test.d.ts +0 -15
  123. package/dist/svgrid.locale-filtering.test.js +0 -261
  124. package/dist/svgrid.new-features.wrapper.test.d.ts +0 -1
  125. package/dist/svgrid.new-features.wrapper.test.js +0 -194
  126. package/dist/svgrid.row-pinning.test.d.ts +0 -14
  127. package/dist/svgrid.row-pinning.test.js +0 -250
  128. package/dist/svgrid.set-filter.test.d.ts +0 -17
  129. package/dist/svgrid.set-filter.test.js +0 -268
  130. package/dist/svgrid.wrapper.test.d.ts +0 -1
  131. package/dist/svgrid.wrapper.test.js +0 -59
  132. package/dist/test-setup.d.ts +0 -1
  133. package/dist/test-setup.js +0 -35
  134. package/dist/transaction.test.d.ts +0 -1
  135. package/dist/transaction.test.js +0 -89
  136. package/dist/virtualization/column-virtualizer.test.d.ts +0 -1
  137. package/dist/virtualization/column-virtualizer.test.js +0 -25
  138. package/dist/virtualization/scroll-scaling.test.d.ts +0 -1
  139. package/dist/virtualization/scroll-scaling.test.js +0 -127
  140. package/dist/virtualization/virtualizer.test.d.ts +0 -1
  141. package/dist/virtualization/virtualizer.test.js +0 -41
@@ -1,349 +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
- import { describe, expect, it } from 'vitest';
10
- import { mount, unmount } from 'svelte';
11
- import SvGrid from './SvGrid.svelte';
12
- import { columnFilteringFeature, createCoreRowModel, createFilteredRowModel, createPaginatedRowModel, createSortedRowModel, rowPaginationFeature, rowSelectionFeature, rowSortingFeature, sortFns, tableFeatures, } from './index';
13
- const features = tableFeatures({
14
- columnFilteringFeature,
15
- rowSortingFeature,
16
- rowSelectionFeature,
17
- rowPaginationFeature,
18
- });
19
- const rows = Array.from({ length: 25 }, (_, i) => ({
20
- id: i + 1,
21
- name: `Person ${(i + 1).toString().padStart(2, '0')}`,
22
- team: ['Research', 'Compilers', 'Apollo', 'Kernel'][i % 4],
23
- salary: 100000 + i * 1000,
24
- }));
25
- const cols = [
26
- { field: 'name', header: 'Name', width: 220, editorType: 'text' },
27
- { field: 'team', header: 'Team', width: 160, editorType: 'text' },
28
- { field: 'salary', header: 'Salary', width: 140, editorType: 'number' },
29
- ];
30
- function mountInteractive(overrides = {}) {
31
- return new Promise((res, rej) => {
32
- const target = document.createElement('div');
33
- document.body.appendChild(target);
34
- let api = null;
35
- const app = mount(SvGrid, {
36
- target,
37
- props: {
38
- data: rows,
39
- columns: cols,
40
- features,
41
- _rowModels: {
42
- coreRowModel: createCoreRowModel(),
43
- filteredRowModel: createFilteredRowModel(),
44
- sortedRowModel: createSortedRowModel(sortFns),
45
- paginatedRowModel: createPaginatedRowModel(),
46
- },
47
- rowHeight: 36,
48
- containerHeight: 480,
49
- virtualization: false,
50
- enableInlineEditing: true,
51
- enableCellSelection: true,
52
- showPagination: true,
53
- pageSize: 10,
54
- showColumnFilters: true,
55
- showGlobalFilter: true,
56
- showRowSelection: true,
57
- onApiReady(received) {
58
- api = received;
59
- const grid = target.querySelector('[role="grid"]') ?? target;
60
- res({
61
- api,
62
- target,
63
- grid,
64
- destroy: () => {
65
- unmount(app);
66
- target.remove();
67
- },
68
- });
69
- },
70
- ...overrides,
71
- },
72
- });
73
- queueMicrotask(() => {
74
- if (!api)
75
- rej(new Error('onApiReady never fired'));
76
- });
77
- });
78
- }
79
- const tick = () => new Promise((r) => queueMicrotask(r));
80
- describe('SvGrid interactions - keyboard', () => {
81
- it('dispatches ArrowRight without throwing', async () => {
82
- const { grid, destroy } = await mountInteractive();
83
- try {
84
- const ev = new KeyboardEvent('keydown', { key: 'ArrowRight', bubbles: true });
85
- grid.dispatchEvent(ev);
86
- await tick();
87
- expect(true).toBe(true);
88
- }
89
- finally {
90
- destroy();
91
- }
92
- });
93
- it('dispatches ArrowDown / ArrowUp / Home / End', async () => {
94
- const { grid, destroy } = await mountInteractive();
95
- try {
96
- for (const key of ['ArrowDown', 'ArrowUp', 'Home', 'End', 'PageDown', 'PageUp']) {
97
- grid.dispatchEvent(new KeyboardEvent('keydown', { key, bubbles: true }));
98
- await tick();
99
- }
100
- expect(true).toBe(true);
101
- }
102
- finally {
103
- destroy();
104
- }
105
- });
106
- it('dispatches Ctrl+Home and Ctrl+End', async () => {
107
- const { grid, destroy } = await mountInteractive();
108
- try {
109
- grid.dispatchEvent(new KeyboardEvent('keydown', { key: 'Home', ctrlKey: true, bubbles: true }));
110
- await tick();
111
- grid.dispatchEvent(new KeyboardEvent('keydown', { key: 'End', ctrlKey: true, bubbles: true }));
112
- await tick();
113
- expect(true).toBe(true);
114
- }
115
- finally {
116
- destroy();
117
- }
118
- });
119
- it('dispatches Escape to close any open menu / cancel edit', async () => {
120
- const { grid, destroy } = await mountInteractive();
121
- try {
122
- grid.dispatchEvent(new KeyboardEvent('keydown', { key: 'Escape', bubbles: true }));
123
- await tick();
124
- expect(true).toBe(true);
125
- }
126
- finally {
127
- destroy();
128
- }
129
- });
130
- it('dispatches Tab and Shift+Tab', async () => {
131
- const { grid, destroy } = await mountInteractive();
132
- try {
133
- grid.dispatchEvent(new KeyboardEvent('keydown', { key: 'Tab', bubbles: true }));
134
- await tick();
135
- grid.dispatchEvent(new KeyboardEvent('keydown', { key: 'Tab', shiftKey: true, bubbles: true }));
136
- await tick();
137
- expect(true).toBe(true);
138
- }
139
- finally {
140
- destroy();
141
- }
142
- });
143
- });
144
- describe('SvGrid interactions - global filter input', () => {
145
- it('typing in the global filter narrows the displayed rows', async () => {
146
- const { api, target, destroy } = await mountInteractive();
147
- try {
148
- const input = target.querySelector('.sv-grid-global-filter input');
149
- if (!input) {
150
- // global filter input wasn't rendered (jsdom quirk) - just verify api still works.
151
- expect(api.getData().length).toBe(rows.length);
152
- return;
153
- }
154
- input.value = 'Person 01';
155
- input.dispatchEvent(new Event('input', { bubbles: true }));
156
- await tick();
157
- await tick();
158
- // Some narrowing happened.
159
- expect(api.getDisplayedRows().length).toBeLessThanOrEqual(rows.length);
160
- }
161
- finally {
162
- destroy();
163
- }
164
- });
165
- });
166
- describe('SvGrid interactions - column resize', () => {
167
- it('starts a column resize via pointerdown on the handle', async () => {
168
- const { target, destroy } = await mountInteractive();
169
- try {
170
- const handle = target.querySelector('.sv-grid-resize-handle');
171
- if (!handle) {
172
- // jsdom may not lay out the handle; assertion skipped.
173
- return;
174
- }
175
- handle.dispatchEvent(new PointerEvent('pointerdown', { bubbles: true, pointerId: 1, button: 0 }));
176
- await tick();
177
- window.dispatchEvent(new PointerEvent('pointermove', { clientX: 200, clientY: 0 }));
178
- await tick();
179
- window.dispatchEvent(new PointerEvent('pointerup', { clientX: 200, clientY: 0 }));
180
- await tick();
181
- expect(true).toBe(true);
182
- }
183
- finally {
184
- destroy();
185
- }
186
- });
187
- });
188
- describe('SvGrid interactions - pagination nav', () => {
189
- it('clicking next/prev/last/first paginator buttons does not throw', async () => {
190
- const { target, destroy } = await mountInteractive();
191
- try {
192
- const buttons = target.querySelectorAll('.sv-grid-pagination-btn');
193
- for (const btn of Array.from(buttons)) {
194
- ;
195
- btn.click();
196
- await tick();
197
- }
198
- expect(true).toBe(true);
199
- }
200
- finally {
201
- destroy();
202
- }
203
- });
204
- });
205
- describe('SvGrid interactions - sort header click', () => {
206
- it('clicking a column header toggles the sort indicator', async () => {
207
- const { api, target, destroy } = await mountInteractive();
208
- try {
209
- const headerEl = target.querySelector('[data-svgrid-header-col]');
210
- if (!headerEl)
211
- return;
212
- headerEl.click();
213
- await tick();
214
- headerEl.click();
215
- await tick();
216
- headerEl.click();
217
- await tick();
218
- // No throw means we exercised onHeaderSortClick.
219
- expect(api.getData().length).toBe(rows.length);
220
- }
221
- finally {
222
- destroy();
223
- }
224
- });
225
- it('shift-click on a header adds a secondary sort clause', async () => {
226
- const { target, destroy } = await mountInteractive();
227
- try {
228
- const headers = target.querySelectorAll('[data-svgrid-header-col]');
229
- if (headers.length < 2)
230
- return;
231
- headers[0].click();
232
- await tick();
233
- headers[1].dispatchEvent(new MouseEvent('click', { bubbles: true, shiftKey: true }));
234
- await tick();
235
- expect(true).toBe(true);
236
- }
237
- finally {
238
- destroy();
239
- }
240
- });
241
- });
242
- describe('SvGrid interactions - cell pointer events', () => {
243
- it('pointerdown on a cell starts a selection', async () => {
244
- const { target, destroy } = await mountInteractive();
245
- try {
246
- const cell = target.querySelector('.sv-grid-cell');
247
- if (!cell)
248
- return;
249
- cell.dispatchEvent(new PointerEvent('pointerdown', { bubbles: true, pointerId: 1, button: 0 }));
250
- await tick();
251
- cell.dispatchEvent(new PointerEvent('pointerup', { bubbles: true, pointerId: 1 }));
252
- await tick();
253
- expect(true).toBe(true);
254
- }
255
- finally {
256
- destroy();
257
- }
258
- });
259
- it('double-click on an editable cell enters edit mode', async () => {
260
- const { target, destroy } = await mountInteractive();
261
- try {
262
- const cell = target.querySelector('.sv-grid-cell');
263
- if (!cell)
264
- return;
265
- cell.dispatchEvent(new MouseEvent('dblclick', { bubbles: true }));
266
- await tick();
267
- // Editor input may or may not be in DOM depending on layout; just
268
- // exercising the codepath is enough.
269
- expect(true).toBe(true);
270
- }
271
- finally {
272
- destroy();
273
- }
274
- });
275
- // issue #23: a mouse drag extends the cell range, but a touch drag must NOT -
276
- // it should leave the single tapped cell selected so the finger-drag scrolls.
277
- async function dragSelectCount(pointerType) {
278
- const { target, destroy } = await mountInteractive();
279
- try {
280
- const a = target.querySelector('[data-svgrid-row="0"][data-svgrid-col="0"]');
281
- const c = target.querySelector('[data-svgrid-row="0"][data-svgrid-col="2"]');
282
- if (!a || !c)
283
- return -1; // jsdom didn't lay the cells out; caller skips
284
- a.dispatchEvent(new PointerEvent('pointerdown', { bubbles: true, pointerId: 1, button: 0, pointerType }));
285
- await tick();
286
- c.dispatchEvent(new PointerEvent('pointerenter', { bubbles: true, pointerId: 1, pointerType }));
287
- await tick();
288
- return target.querySelectorAll('[data-selected-range="true"]').length;
289
- }
290
- finally {
291
- destroy();
292
- }
293
- }
294
- it('mouse drag extends the selection across cells', async () => {
295
- const n = await dragSelectCount('mouse');
296
- if (n < 0)
297
- return;
298
- expect(n).toBeGreaterThan(1); // (0,0) -> (0,2) selects the row's 3 cells
299
- });
300
- it('touch drag does not start a range selection (issue #23)', async () => {
301
- const n = await dragSelectCount('touch');
302
- if (n < 0)
303
- return;
304
- expect(n).toBeLessThanOrEqual(1); // only the tapped cell; finger-drag scrolls
305
- });
306
- });
307
- describe('SvGrid interactions - copy', () => {
308
- it('Ctrl+C with a cell range does not throw', async () => {
309
- const { grid, destroy } = await mountInteractive();
310
- try {
311
- const cev = new KeyboardEvent('keydown', { key: 'c', ctrlKey: true, bubbles: true });
312
- grid.dispatchEvent(cev);
313
- await tick();
314
- expect(true).toBe(true);
315
- }
316
- finally {
317
- destroy();
318
- }
319
- });
320
- });
321
- describe('SvGrid interactions - selection mode', () => {
322
- it('selecting a row via the API surfaces via getDisplayedRows', async () => {
323
- const { api, destroy } = await mountInteractive();
324
- try {
325
- // Simulate clicking the first row checkbox via the API.
326
- expect(api.getDisplayedRows().length).toBeGreaterThan(0);
327
- }
328
- finally {
329
- destroy();
330
- }
331
- });
332
- });
333
- describe('SvGrid interactions - clearAllFilters round-trip', () => {
334
- it('setting + clearing global + column filters returns to full set', async () => {
335
- const { api, destroy } = await mountInteractive();
336
- try {
337
- api.setFilter('name', { operator: 'contains', value: 'XYZ-NONE' });
338
- await tick();
339
- expect(api.getDisplayedRows().length).toBeLessThanOrEqual(rows.length);
340
- api.clearAllFilters();
341
- await tick();
342
- await tick();
343
- expect(api.getDisplayedRows().length).toBeGreaterThanOrEqual(1);
344
- }
345
- finally {
346
- destroy();
347
- }
348
- });
349
- });
@@ -1,15 +0,0 @@
1
- /**
2
- * Integration tests for the `filterLocale` prop. Mounts a real
3
- * <SvGrid> with accented data, drives the column-menu filter via
4
- * `api.setFilter()`, then asserts the visible row count via
5
- * `api.getDisplayedRows()`.
6
- *
7
- * Covers:
8
- * - Accent-insensitive `contains` operator on the menu filter
9
- * - Diacritic-stripped global filter (via `setGlobalFilter` not in
10
- * the public api yet; here we use `api.setFilter('city', ...)`
11
- * which exercises the same pipeline)
12
- * - filterLocale prop pass-through (es-ES, de-DE)
13
- * - Regression: ASCII queries still narrow rows
14
- */
15
- export {};
@@ -1,261 +0,0 @@
1
- /**
2
- * Integration tests for the `filterLocale` prop. Mounts a real
3
- * <SvGrid> with accented data, drives the column-menu filter via
4
- * `api.setFilter()`, then asserts the visible row count via
5
- * `api.getDisplayedRows()`.
6
- *
7
- * Covers:
8
- * - Accent-insensitive `contains` operator on the menu filter
9
- * - Diacritic-stripped global filter (via `setGlobalFilter` not in
10
- * the public api yet; here we use `api.setFilter('city', ...)`
11
- * which exercises the same pipeline)
12
- * - filterLocale prop pass-through (es-ES, de-DE)
13
- * - Regression: ASCII queries still narrow rows
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: 1, city: 'München', country: 'Deutschland', region: 'Europe', population: 1510000 },
22
- { id: 2, city: 'Köln', country: 'Deutschland', region: 'Europe', population: 1080000 },
23
- { id: 3, city: 'Genève', country: 'Suisse', region: 'Europe', population: 203000 },
24
- { id: 4, city: 'Montréal', country: 'Canada', region: 'Americas', population: 1780000 },
25
- { id: 5, city: 'México', country: 'México', region: 'Americas', population: 9210000 },
26
- { id: 6, city: 'São Paulo', country: 'Brasil', region: 'Americas', population: 12330000 },
27
- { id: 7, city: 'Tōkyō', country: '日本', region: 'Asia', population: 13960000 },
28
- { id: 8, city: 'İstanbul', country: 'Türkiye', region: 'Asia', population: 15840000 },
29
- { id: 9, city: 'Málaga', country: 'España', region: 'Europe', population: 580000 },
30
- { id: 10, city: 'Berlin', country: 'Deutschland', region: 'Europe', population: 3770000 },
31
- ];
32
- const cols = [
33
- { field: 'city', header: 'City', width: 180, editable: false },
34
- { field: 'country', header: 'Country', width: 160, editable: false },
35
- { field: 'region', header: 'Region', width: 110, editable: false },
36
- { field: 'population', header: 'Population', width: 130, editable: false, align: 'right' },
37
- ];
38
- function mountGrid(opts = {}) {
39
- return new Promise((res, rej) => {
40
- const target = document.createElement('div');
41
- document.body.appendChild(target);
42
- let api = null;
43
- const app = mount(SvGrid, {
44
- target,
45
- props: {
46
- data: rows,
47
- columns: cols,
48
- features,
49
- _rowModels: {
50
- coreRowModel: createCoreRowModel(),
51
- filteredRowModel: createFilteredRowModel(),
52
- sortedRowModel: createSortedRowModel(sortFns),
53
- },
54
- containerHeight: 360,
55
- virtualization: false,
56
- columnVirtualization: false,
57
- showPagination: false,
58
- showColumnFilters: false,
59
- showGlobalFilter: false,
60
- showRowSelection: false,
61
- filterLocale: opts.filterLocale,
62
- onApiReady(received) {
63
- api = received;
64
- res({
65
- api,
66
- destroy: () => { unmount(app); target.remove(); },
67
- });
68
- },
69
- },
70
- });
71
- queueMicrotask(() => { if (!api)
72
- rej(new Error('onApiReady never fired')); });
73
- });
74
- }
75
- const tick = () => new Promise((r) => queueMicrotask(r));
76
- describe('SvGrid filter - default locale (no prop)', () => {
77
- it('"munch" matches "München" via contains operator', async () => {
78
- const { api, destroy } = await mountGrid();
79
- try {
80
- api.setFilter('city', { operator: 'contains', value: 'munch' });
81
- await tick();
82
- const visible = api.getDisplayedRows();
83
- expect(visible.map((r) => r.city)).toEqual(['München']);
84
- }
85
- finally {
86
- destroy();
87
- }
88
- });
89
- it('"geneve" matches "Genève"', async () => {
90
- const { api, destroy } = await mountGrid();
91
- try {
92
- api.setFilter('city', { operator: 'contains', value: 'geneve' });
93
- await tick();
94
- const visible = api.getDisplayedRows();
95
- expect(visible.map((r) => r.city)).toEqual(['Genève']);
96
- }
97
- finally {
98
- destroy();
99
- }
100
- });
101
- it('"sao paulo" matches "São Paulo"', async () => {
102
- const { api, destroy } = await mountGrid();
103
- try {
104
- api.setFilter('city', { operator: 'contains', value: 'sao paulo' });
105
- await tick();
106
- const visible = api.getDisplayedRows();
107
- expect(visible.map((r) => r.city)).toEqual(['São Paulo']);
108
- }
109
- finally {
110
- destroy();
111
- }
112
- });
113
- it('"tokyo" matches "Tōkyō"', async () => {
114
- const { api, destroy } = await mountGrid();
115
- try {
116
- api.setFilter('city', { operator: 'contains', value: 'tokyo' });
117
- await tick();
118
- const visible = api.getDisplayedRows();
119
- expect(visible.map((r) => r.city)).toEqual(['Tōkyō']);
120
- }
121
- finally {
122
- destroy();
123
- }
124
- });
125
- it('"istanbul" matches "İstanbul" (dotted-I default folding)', async () => {
126
- const { api, destroy } = await mountGrid();
127
- try {
128
- api.setFilter('city', { operator: 'contains', value: 'istanbul' });
129
- await tick();
130
- const visible = api.getDisplayedRows();
131
- expect(visible.map((r) => r.city)).toEqual(['İstanbul']);
132
- }
133
- finally {
134
- destroy();
135
- }
136
- });
137
- it('"deutschland" matches all German cities', async () => {
138
- const { api, destroy } = await mountGrid();
139
- try {
140
- api.setFilter('country', { operator: 'contains', value: 'deutschland' });
141
- await tick();
142
- const visible = api.getDisplayedRows();
143
- expect(visible.map((r) => r.city).sort()).toEqual(['Berlin', 'Köln', 'München']);
144
- }
145
- finally {
146
- destroy();
147
- }
148
- });
149
- });
150
- describe('SvGrid filter - filterLocale="de-DE"', () => {
151
- it('explicit German locale - "munchen" still matches "München"', async () => {
152
- const { api, destroy } = await mountGrid({ filterLocale: 'de-DE' });
153
- try {
154
- api.setFilter('city', { operator: 'contains', value: 'munchen' });
155
- await tick();
156
- expect(api.getDisplayedRows().map((r) => r.city)).toEqual(['München']);
157
- }
158
- finally {
159
- destroy();
160
- }
161
- });
162
- it('"koln" matches "Köln"', async () => {
163
- const { api, destroy } = await mountGrid({ filterLocale: 'de-DE' });
164
- try {
165
- api.setFilter('city', { operator: 'contains', value: 'koln' });
166
- await tick();
167
- expect(api.getDisplayedRows().map((r) => r.city)).toEqual(['Köln']);
168
- }
169
- finally {
170
- destroy();
171
- }
172
- });
173
- });
174
- describe('SvGrid filter - filterLocale="es-ES"', () => {
175
- it('"mexico" matches "México"', async () => {
176
- const { api, destroy } = await mountGrid({ filterLocale: 'es-ES' });
177
- try {
178
- api.setFilter('city', { operator: 'contains', value: 'mexico' });
179
- await tick();
180
- const cities = api.getDisplayedRows().map((r) => r.city);
181
- expect(cities).toContain('México');
182
- }
183
- finally {
184
- destroy();
185
- }
186
- });
187
- it('"malaga" matches "Málaga"', async () => {
188
- const { api, destroy } = await mountGrid({ filterLocale: 'es-ES' });
189
- try {
190
- api.setFilter('city', { operator: 'contains', value: 'malaga' });
191
- await tick();
192
- expect(api.getDisplayedRows().map((r) => r.city)).toEqual(['Málaga']);
193
- }
194
- finally {
195
- destroy();
196
- }
197
- });
198
- });
199
- describe('SvGrid filter - startsWith + equals operators', () => {
200
- it('startsWith "mun" matches München', async () => {
201
- const { api, destroy } = await mountGrid();
202
- try {
203
- api.setFilter('city', { operator: 'startsWith', value: 'mun' });
204
- await tick();
205
- expect(api.getDisplayedRows().map((r) => r.city)).toEqual(['München']);
206
- }
207
- finally {
208
- destroy();
209
- }
210
- });
211
- it('equals "berlin" matches exactly "Berlin" (case-insensitive)', async () => {
212
- const { api, destroy } = await mountGrid();
213
- try {
214
- api.setFilter('city', { operator: 'equals', value: 'berlin' });
215
- await tick();
216
- expect(api.getDisplayedRows().map((r) => r.city)).toEqual(['Berlin']);
217
- }
218
- finally {
219
- destroy();
220
- }
221
- });
222
- it('equals "kolN" matches "Köln" (case + accent insensitive)', async () => {
223
- const { api, destroy } = await mountGrid();
224
- try {
225
- api.setFilter('city', { operator: 'equals', value: 'kolN' });
226
- await tick();
227
- expect(api.getDisplayedRows().map((r) => r.city)).toEqual(['Köln']);
228
- }
229
- finally {
230
- destroy();
231
- }
232
- });
233
- });
234
- describe('SvGrid filter - clear + compose', () => {
235
- it('clearFilter removes the narrowing', async () => {
236
- const { api, destroy } = await mountGrid();
237
- try {
238
- api.setFilter('city', { operator: 'contains', value: 'munch' });
239
- await tick();
240
- expect(api.getDisplayedRows().length).toBe(1);
241
- api.clearFilter('city');
242
- await tick();
243
- expect(api.getDisplayedRows().length).toBe(rows.length);
244
- }
245
- finally {
246
- destroy();
247
- }
248
- });
249
- it('two column filters compose (AND across columns)', async () => {
250
- const { api, destroy } = await mountGrid();
251
- try {
252
- api.setFilter('country', { operator: 'contains', value: 'deutschland' });
253
- api.setFilter('city', { operator: 'contains', value: 'mun' });
254
- await tick();
255
- expect(api.getDisplayedRows().map((r) => r.city)).toEqual(['München']);
256
- }
257
- finally {
258
- destroy();
259
- }
260
- });
261
- });
@@ -1 +0,0 @@
1
- export {};