@svgrid/grid 1.1.0 → 1.1.2
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/dist/FlexRender.svelte +96 -96
- package/dist/GridMenus.svelte +205 -127
- package/dist/SvGrid.controller.svelte.d.ts +44 -1
- package/dist/SvGrid.controller.svelte.js +240 -44
- package/dist/SvGrid.css +325 -22
- package/dist/SvGrid.helpers.test.d.ts +1 -0
- package/dist/SvGrid.helpers.test.js +298 -0
- package/dist/SvGrid.svelte +729 -203
- package/dist/SvGrid.types.d.ts +91 -4
- 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.js +61 -31
- package/dist/cell-render.test.d.ts +1 -0
- package/dist/cell-render.test.js +338 -0
- package/dist/cell-values.d.ts +1 -1
- package/dist/cell-values.js +7 -7
- 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/clipboard.js +88 -24
- 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.test.d.ts +1 -0
- package/dist/columns.test.js +625 -0
- package/dist/core.d.ts +86 -1
- package/dist/core.js +2 -2
- package/dist/editing.d.ts +7 -0
- package/dist/editing.js +191 -5
- 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/facet-buckets.test.d.ts +1 -0
- package/dist/facet-buckets.test.js +296 -0
- package/dist/filter-operators.test.d.ts +1 -0
- package/dist/filter-operators.test.js +135 -0
- package/dist/hyperformula-adapter.test.d.ts +1 -0
- package/dist/hyperformula-adapter.test.js +205 -0
- package/dist/index.d.ts +5 -2
- package/dist/index.js +4 -1
- package/dist/keyboard-handlers.coverage.test.d.ts +1 -0
- package/dist/keyboard-handlers.coverage.test.js +495 -0
- package/dist/keyboard-handlers.js +7 -2
- package/dist/menus.js +1 -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/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.test.d.ts +1 -0
- package/dist/row-resize.test.js +329 -0
- package/dist/scroll-sync.js +3 -0
- package/dist/scroll-sync.test.d.ts +1 -0
- package/dist/scroll-sync.test.js +290 -0
- package/dist/selection.d.ts +7 -1
- package/dist/selection.js +76 -36
- 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 +30 -0
- package/dist/spreadsheet.js +48 -0
- package/dist/spreadsheet.test.d.ts +1 -0
- package/dist/spreadsheet.test.js +446 -0
- package/dist/summaries.js +4 -4
- package/dist/sv-grid-scrollbar.js +13 -1
- package/dist/svgrid-wrapper.types.d.ts +19 -0
- package/dist/svgrid.behavior.test.js +20 -0
- package/dist/svgrid.interaction.test.js +31 -0
- package/dist/svgrid.new-features.wrapper.test.js +34 -2
- package/dist/test-setup.js +9 -3
- package/dist/virtualization/scroll-scaling.d.ts +17 -0
- package/dist/virtualization/scroll-scaling.js +35 -0
- package/dist/virtualization/scroll-scaling.test.js +42 -1
- package/package.json +2 -1
- package/src/FlexRender.svelte +96 -96
- package/src/GridMenus.svelte +205 -127
- package/src/SvGrid.controller.svelte.ts +204 -36
- package/src/SvGrid.css +277 -12
- package/src/SvGrid.svelte +727 -205
- package/src/SvGrid.types.ts +85 -4
- package/src/a11y.contract.test.ts +49 -49
- package/src/a11y.test.ts +59 -59
- package/src/a11y.ts +59 -59
- package/src/aligned-grids.test.ts +80 -0
- package/src/aligned-grids.ts +87 -0
- package/src/build-api.ts +43 -23
- package/src/cell-formatting.ts +169 -169
- package/src/cell-values.ts +4 -4
- package/src/clipboard.test.ts +49 -0
- package/src/clipboard.ts +51 -23
- 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/core.performance.test.ts +30 -30
- package/src/core.ts +1077 -999
- package/src/createGrid.svelte.ts +42 -42
- package/src/createGrid.test.ts +10 -10
- package/src/createGridState.svelte.ts +17 -17
- package/src/editing.ts +161 -5
- package/src/flex-render.ts +3 -3
- package/src/index.ts +208 -196
- package/src/keyboard.test.ts +59 -59
- package/src/keyboard.ts +97 -97
- package/src/menus.ts +1 -0
- package/src/merge-objects.ts +48 -48
- package/src/render-component.ts +28 -28
- package/src/row-drag.test.ts +168 -0
- package/src/row-drag.ts +255 -0
- package/src/scroll-sync.ts +2 -0
- package/src/selection.multi-range.test.ts +61 -0
- package/src/selection.ts +71 -37
- package/src/spreadsheet.test.ts +46 -2
- package/src/spreadsheet.ts +58 -0
- package/src/static-functions.ts +11 -11
- package/src/subscribe.ts +38 -38
- package/src/summaries.ts +4 -4
- package/src/svgrid-wrapper.types.ts +412 -393
- package/src/svgrid.features.test.ts +157 -157
- package/src/svgrid.new-features.wrapper.test.ts +2 -2
- package/src/svgrid.wrapper.test.ts +40 -40
- package/src/virtualization/column-virtualizer.test.ts +27 -27
- package/src/virtualization/column-virtualizer.ts +30 -30
- package/src/virtualization/svelte-virtualizer.svelte.ts +26 -26
- package/src/virtualization/types.ts +30 -30
- package/src/virtualization/virtualizer.test.ts +47 -47
- package/src/virtualization/virtualizer.ts +296 -296
package/dist/selection.js
CHANGED
|
@@ -158,9 +158,47 @@ export function createSelection(ctx) {
|
|
|
158
158
|
// No inline scrollVersion bump - the `scroll` event triggers
|
|
159
159
|
// onBodyScroll which flushes via rAF, doing one batched update.
|
|
160
160
|
}
|
|
161
|
-
|
|
161
|
+
// Normalize a range to a rectangle, or null when incomplete.
|
|
162
|
+
function rangeRect(range) {
|
|
163
|
+
const a = range?.anchor;
|
|
164
|
+
const f = range?.focus;
|
|
165
|
+
if (!a || !f)
|
|
166
|
+
return null;
|
|
167
|
+
return {
|
|
168
|
+
minRow: Math.min(a.rowIndex, f.rowIndex),
|
|
169
|
+
maxRow: Math.max(a.rowIndex, f.rowIndex),
|
|
170
|
+
minCol: Math.min(a.colIndex, f.colIndex),
|
|
171
|
+
maxCol: Math.max(a.colIndex, f.colIndex),
|
|
172
|
+
};
|
|
173
|
+
}
|
|
174
|
+
// Every selected rectangle: the committed extra ranges plus the active one.
|
|
175
|
+
// Order matters for copy (added-order); the active range comes last.
|
|
176
|
+
function getSelectionRects() {
|
|
177
|
+
const rects = [];
|
|
178
|
+
for (const r of ctx.selectionRanges ?? []) {
|
|
179
|
+
const rect = rangeRect(r);
|
|
180
|
+
if (rect)
|
|
181
|
+
rects.push(rect);
|
|
182
|
+
}
|
|
183
|
+
const active = rangeRect(ctx.selectionRange);
|
|
184
|
+
if (active)
|
|
185
|
+
rects.push(active);
|
|
186
|
+
return rects;
|
|
187
|
+
}
|
|
188
|
+
function setSelection(rowIndex, colIndex, additive = false) {
|
|
162
189
|
if (!ctx.enableCellSelectionEffective)
|
|
163
190
|
return;
|
|
191
|
+
if (additive) {
|
|
192
|
+
// Commit the current active range (if any) and start a fresh one, so the
|
|
193
|
+
// previous rectangle stays highlighted alongside the new Ctrl+drag.
|
|
194
|
+
const active = ctx.selectionRange;
|
|
195
|
+
if (active.anchor && active.focus) {
|
|
196
|
+
ctx.selectionRanges = [...ctx.selectionRanges, active];
|
|
197
|
+
}
|
|
198
|
+
}
|
|
199
|
+
else {
|
|
200
|
+
ctx.selectionRanges = [];
|
|
201
|
+
}
|
|
164
202
|
const point = { rowIndex, colIndex };
|
|
165
203
|
ctx.selectionRange = { anchor: point, focus: point };
|
|
166
204
|
}
|
|
@@ -171,44 +209,38 @@ export function createSelection(ctx) {
|
|
|
171
209
|
ctx.selectionRange = { anchor, focus: { rowIndex, colIndex } };
|
|
172
210
|
}
|
|
173
211
|
function isCellInSelectedRange(rowIndex, colIndex) {
|
|
174
|
-
const
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
return
|
|
183
|
-
rowIndex <= maxRow &&
|
|
184
|
-
colIndex >= minCol &&
|
|
185
|
-
colIndex <= maxCol);
|
|
212
|
+
for (const rect of getSelectionRects()) {
|
|
213
|
+
if (rowIndex >= rect.minRow &&
|
|
214
|
+
rowIndex <= rect.maxRow &&
|
|
215
|
+
colIndex >= rect.minCol &&
|
|
216
|
+
colIndex <= rect.maxCol) {
|
|
217
|
+
return true;
|
|
218
|
+
}
|
|
219
|
+
}
|
|
220
|
+
return false;
|
|
186
221
|
}
|
|
187
222
|
/**
|
|
188
|
-
* Returns which sides of
|
|
189
|
-
* Excel-style outline.
|
|
223
|
+
* Returns which sides of a selection rectangle a cell sits on, for the
|
|
224
|
+
* Excel-style outline. With multiple ranges, the edges of the FIRST range
|
|
225
|
+
* that contains the cell are returned (active range checked last so its
|
|
226
|
+
* outline wins on overlap). Returns null when the cell is in no range.
|
|
190
227
|
*/
|
|
191
228
|
function getCellRangeEdges(rowIndex, colIndex) {
|
|
192
|
-
const
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
|
|
229
|
+
for (const rect of getSelectionRects()) {
|
|
230
|
+
if (rowIndex < rect.minRow ||
|
|
231
|
+
rowIndex > rect.maxRow ||
|
|
232
|
+
colIndex < rect.minCol ||
|
|
233
|
+
colIndex > rect.maxCol) {
|
|
234
|
+
continue;
|
|
235
|
+
}
|
|
236
|
+
return {
|
|
237
|
+
top: rowIndex === rect.minRow,
|
|
238
|
+
bottom: rowIndex === rect.maxRow,
|
|
239
|
+
left: colIndex === rect.minCol,
|
|
240
|
+
right: colIndex === rect.maxCol,
|
|
241
|
+
};
|
|
205
242
|
}
|
|
206
|
-
return
|
|
207
|
-
top: rowIndex === minRow,
|
|
208
|
-
bottom: rowIndex === maxRow,
|
|
209
|
-
left: colIndex === minCol,
|
|
210
|
-
right: colIndex === maxCol,
|
|
211
|
-
};
|
|
243
|
+
return null;
|
|
212
244
|
}
|
|
213
245
|
/** Returns true when the given cell is inside the fill-drag preview
|
|
214
246
|
* range BUT outside the original source range. Used to paint a
|
|
@@ -259,8 +291,15 @@ export function createSelection(ctx) {
|
|
|
259
291
|
}
|
|
260
292
|
else {
|
|
261
293
|
setActiveCell(rowIndex, colIndex);
|
|
262
|
-
|
|
263
|
-
|
|
294
|
+
// Ctrl/Cmd starts an ADDITIONAL range, keeping prior ranges highlighted.
|
|
295
|
+
setSelection(rowIndex, colIndex, event.ctrlKey || event.metaKey);
|
|
296
|
+
// Range drag-select is a mouse/pen affordance. On touch, starting a drag
|
|
297
|
+
// here would rubber-band a selection AND fight the browser's native
|
|
298
|
+
// scroll (we never preventDefault), so a finger-drag to scroll the grid
|
|
299
|
+
// instead selected cells. Tap still selects the single cell above; we
|
|
300
|
+
// just don't enter drag-select mode for touch. (issue #23)
|
|
301
|
+
if (event.pointerType !== "touch")
|
|
302
|
+
ctx.isDraggingSelection = true;
|
|
264
303
|
}
|
|
265
304
|
}
|
|
266
305
|
function onCellPointerEnter(rowIndex, colIndex) {
|
|
@@ -375,6 +414,7 @@ export function createSelection(ctx) {
|
|
|
375
414
|
extendSelection,
|
|
376
415
|
isCellInSelectedRange,
|
|
377
416
|
getCellRangeEdges,
|
|
417
|
+
getSelectionRects,
|
|
378
418
|
isInFillPreview,
|
|
379
419
|
findColumnById,
|
|
380
420
|
onCellPointerDown,
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|
|
@@ -0,0 +1,55 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Unit tests for multiple-range (Ctrl+drag) cell selection, driven through the
|
|
3
|
+
* pure range helpers of createSelection(ctx) with a minimal fake ctx.
|
|
4
|
+
*/
|
|
5
|
+
import { describe, expect, it } from 'vitest';
|
|
6
|
+
import { createSelection } from './selection';
|
|
7
|
+
function makeCtx() {
|
|
8
|
+
return {
|
|
9
|
+
enableCellSelectionEffective: true,
|
|
10
|
+
selectionRange: { anchor: null, focus: null },
|
|
11
|
+
selectionRanges: [],
|
|
12
|
+
};
|
|
13
|
+
}
|
|
14
|
+
describe('multiple range selection', () => {
|
|
15
|
+
it('a plain selection replaces any committed ranges', () => {
|
|
16
|
+
const ctx = makeCtx();
|
|
17
|
+
const s = createSelection(ctx);
|
|
18
|
+
s.setSelection(0, 0);
|
|
19
|
+
s.extendSelection(1, 1); // active range 0,0..1,1
|
|
20
|
+
s.setSelection(5, 5, true); // additive: commit prior, start new
|
|
21
|
+
expect(ctx.selectionRanges.length).toBe(1);
|
|
22
|
+
s.setSelection(9, 9, false); // plain: clears committed
|
|
23
|
+
expect(ctx.selectionRanges.length).toBe(0);
|
|
24
|
+
});
|
|
25
|
+
it('Ctrl+drag commits the prior range and keeps both highlighted', () => {
|
|
26
|
+
const ctx = makeCtx();
|
|
27
|
+
const s = createSelection(ctx);
|
|
28
|
+
s.setSelection(0, 0);
|
|
29
|
+
s.extendSelection(1, 1); // range A: rows 0-1, cols 0-1
|
|
30
|
+
s.setSelection(3, 3, true); // start range B additively
|
|
31
|
+
s.extendSelection(4, 4); // range B: rows 3-4, cols 3-4
|
|
32
|
+
const rects = s.getSelectionRects();
|
|
33
|
+
expect(rects.length).toBe(2);
|
|
34
|
+
// both ranges report cells as selected
|
|
35
|
+
expect(s.isCellInSelectedRange(0, 0)).toBe(true);
|
|
36
|
+
expect(s.isCellInSelectedRange(1, 1)).toBe(true);
|
|
37
|
+
expect(s.isCellInSelectedRange(4, 4)).toBe(true);
|
|
38
|
+
// a cell in neither is not selected
|
|
39
|
+
expect(s.isCellInSelectedRange(2, 2)).toBe(false);
|
|
40
|
+
});
|
|
41
|
+
it('getCellRangeEdges outlines each range independently', () => {
|
|
42
|
+
const ctx = makeCtx();
|
|
43
|
+
const s = createSelection(ctx);
|
|
44
|
+
s.setSelection(0, 0);
|
|
45
|
+
s.extendSelection(1, 1);
|
|
46
|
+
s.setSelection(3, 3, true);
|
|
47
|
+
s.extendSelection(4, 4);
|
|
48
|
+
// top-left corner of range A
|
|
49
|
+
expect(s.getCellRangeEdges(0, 0)).toEqual({ top: true, bottom: false, left: true, right: false });
|
|
50
|
+
// bottom-right corner of range B
|
|
51
|
+
expect(s.getCellRangeEdges(4, 4)).toEqual({ top: false, bottom: true, left: false, right: true });
|
|
52
|
+
// outside every range
|
|
53
|
+
expect(s.getCellRangeEdges(2, 2)).toBeNull();
|
|
54
|
+
});
|
|
55
|
+
});
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|