@svgrid/grid 3.0.3 → 3.0.5
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/README.md +6 -5
- package/dist/GridMenus.svelte +44 -2
- package/dist/SvChartMenu.svelte +69 -0
- package/dist/SvChartMenu.svelte.d.ts +11 -0
- package/dist/SvChartPanes.svelte +113 -0
- package/dist/SvChartPanes.svelte.d.ts +20 -0
- package/dist/SvGrid.controller.svelte.d.ts +122 -41
- package/dist/SvGrid.controller.svelte.js +846 -207
- package/dist/SvGrid.css +178 -2
- package/dist/SvGrid.svelte +717 -720
- package/dist/SvGrid.types.d.ts +566 -12
- package/dist/SvGridCellEditor.svelte +17 -0
- package/dist/SvGridChart.svelte +2257 -329
- package/dist/SvGridChart.svelte.d.ts +6 -106
- package/dist/SvGridChart.types.d.ts +338 -0
- package/dist/SvGridChart.types.js +1 -0
- package/dist/SvGridChartBuilder.svelte +323 -0
- package/dist/SvGridChartBuilder.svelte.d.ts +34 -0
- package/dist/SvGridChartPanel.svelte +221 -275
- package/dist/SvGridChartPickers.svelte +417 -0
- package/dist/SvGridChartPickers.svelte.d.ts +70 -0
- package/dist/SvGridChartView.svelte +13 -14
- package/dist/SvModal.svelte +7 -1
- package/dist/SvModal.svelte.d.ts +5 -0
- package/dist/ai.d.ts +40 -8
- package/dist/ai.js +135 -24
- package/dist/aria.d.ts +11 -0
- package/dist/build-api.js +119 -28
- package/dist/cdn/GridMenus-CID62rlI.js +636 -0
- package/dist/cdn/GridMenus-DLL-qZeu.js +635 -0
- package/dist/cdn/SvChartMenu-Bl6PBbkT.js +58 -0
- package/dist/cdn/SvChartMenu-FBSMINA6.js +59 -0
- package/dist/cdn/{SvDateRangeInput-DMLKmGEc.js → SvDateRangeInput-BeU_TkbQ.js} +15 -14
- package/dist/cdn/{SvDateRangeInput-CaOuMs8O.js → SvDateRangeInput-yX8vzleW.js} +38 -37
- package/dist/cdn/{SvDateTimePicker-sonaH0oh.js → SvDateTimePicker-DQwt4UAs.js} +139 -180
- package/dist/cdn/SvDateTimePicker-vNU6bZ-q.js +775 -0
- package/dist/cdn/{SvGridCellEditor-CjEJMJKc.js → SvGridCellEditor-B1p-vCK5.js} +188 -178
- package/dist/cdn/{SvGridCellEditor-BWnTi2N7.js → SvGridCellEditor-D_0q4xAu.js} +98 -88
- package/dist/cdn/SvGridChart-C3EWAZaM.js +3574 -0
- package/dist/cdn/SvGridChart-DzLkSwCH.js +3572 -0
- package/dist/cdn/SvGridChartBuilder-BE2T1ykB.js +783 -0
- package/dist/cdn/SvGridChartBuilder-CfII62sZ.js +784 -0
- package/dist/cdn/SvGridChartPanel-CCX5_Wgd.js +675 -0
- package/dist/cdn/SvGridChartPanel-xf4sWVTo.js +699 -0
- package/dist/cdn/SvGridChartView-CfuXmY5I.js +48 -0
- package/dist/cdn/SvGridChartView-DYwabQWj.js +47 -0
- package/dist/cdn/SvMenuList-CLN8OuIK.js +452 -0
- package/dist/cdn/SvMenuList-DkGhNKjf.js +451 -0
- package/dist/cdn/SvModal-BAE-pjZX.js +396 -0
- package/dist/cdn/SvModal-CIZWCcad.js +397 -0
- package/dist/cdn/chart-Dz7SqMXH.js +4341 -0
- package/dist/cdn/chart-export-BXqueeWJ.js +135 -0
- package/dist/cdn/chart-export-pdf-DONFUnNY.js +110 -0
- package/dist/cdn/chart-panel-messages-CUbf2R4i.js +1052 -0
- package/dist/cdn/chart-panel-messages-CmNrMdsr.js +1053 -0
- package/dist/cdn/chart-summary-BJW_tg_X.js +138 -0
- package/dist/cdn/chart-trend-CaN9mDEV.js +50 -0
- package/dist/cdn/chart-validate-HcOVFAfJ.js +188 -0
- package/dist/cdn/{column-resize-DsfNXMom.js → column-resize-DpmOLfRp.js} +3 -3
- package/dist/cdn/{date-format-BnnHlqGw.js → date-format-CtquV-p3.js} +583 -603
- package/dist/cdn/{date-format-BNii4zeD.js → date-format-D6KFzU_W.js} +347 -367
- package/dist/cdn/dismissable-DAHetSNk.js +44 -0
- package/dist/cdn/editor-contract-LXgQJAgd.js +22 -0
- package/dist/cdn/focus-trap-BBOQYBma.js +65 -0
- package/dist/cdn/{row-resize-BRcimkUT.js → row-resize-niQCp040.js} +44 -36
- package/dist/cdn/server-block-cache-CGoWz-87.js +237 -0
- package/dist/cdn/{src-D6XvA1Ij.js → src-Bklofsad.js} +10615 -10155
- package/dist/cdn/{src-Bugf5XlI.js → src-jcFMkBnN.js} +7111 -6651
- package/dist/cdn/svgrid.js +27 -15
- package/dist/cdn/svgrid.svelte-external.js +27 -15
- package/dist/cdn/validate-C7Rn_Bns.js +76 -0
- package/dist/chart-axes.d.ts +53 -0
- package/dist/chart-axes.js +351 -0
- package/dist/chart-cartesian.d.ts +88 -0
- package/dist/chart-cartesian.js +1862 -0
- package/dist/chart-decimate.d.ts +51 -0
- package/dist/chart-decimate.js +199 -0
- package/dist/chart-export-pdf.d.ts +47 -0
- package/dist/chart-export-pdf.js +187 -0
- package/dist/chart-export.d.ts +2 -1
- package/dist/chart-export.js +18 -3
- package/dist/chart-financial.d.ts +91 -0
- package/dist/chart-financial.js +175 -0
- package/dist/chart-flow.d.ts +10 -0
- package/dist/chart-flow.js +298 -0
- package/dist/chart-format.d.ts +18 -0
- package/dist/chart-format.js +65 -0
- package/dist/chart-grid.d.ts +8 -0
- package/dist/chart-grid.js +190 -0
- package/dist/chart-hierarchy.d.ts +17 -0
- package/dist/chart-hierarchy.js +146 -0
- package/dist/chart-indicators.d.ts +115 -0
- package/dist/chart-indicators.js +389 -0
- package/dist/chart-messages.d.ts +95 -0
- package/dist/chart-messages.js +92 -0
- package/dist/chart-motion.d.ts +16 -0
- package/dist/chart-motion.js +141 -0
- package/dist/chart-panel-messages.d.ts +265 -0
- package/dist/chart-panel-messages.js +285 -0
- package/dist/chart-pivot.d.ts +87 -0
- package/dist/chart-pivot.js +156 -0
- package/dist/chart-polar.d.ts +25 -0
- package/dist/chart-polar.js +700 -0
- package/dist/chart-samples.d.ts +16 -0
- package/dist/chart-samples.js +153 -0
- package/dist/chart-scale.d.ts +113 -0
- package/dist/chart-scale.js +405 -0
- package/dist/chart-stats.d.ts +111 -0
- package/dist/chart-stats.js +419 -0
- package/dist/chart-stream.d.ts +45 -0
- package/dist/chart-stream.js +91 -0
- package/dist/chart-summary.d.ts +27 -0
- package/dist/chart-summary.js +205 -0
- package/dist/chart-sync.svelte.d.ts +32 -0
- package/dist/chart-sync.svelte.js +23 -0
- package/dist/chart-table.d.ts +35 -0
- package/dist/chart-table.js +165 -0
- package/dist/chart-trend.d.ts +19 -0
- package/dist/chart-trend.js +61 -0
- package/dist/chart-types.d.ts +1456 -0
- package/dist/chart-types.js +6 -0
- package/dist/chart-validate.d.ts +43 -0
- package/dist/chart-validate.js +272 -0
- package/dist/chart-zoom.d.ts +40 -0
- package/dist/chart-zoom.js +145 -0
- package/dist/chart.d.ts +186 -865
- package/dist/chart.js +460 -2204
- package/dist/clipboard.d.ts +1 -0
- package/dist/clipboard.js +137 -18
- package/dist/column-resize.d.ts +3 -0
- package/dist/column-resize.js +4 -1
- package/dist/columns.js +3 -0
- package/dist/command-context.d.ts +19 -0
- package/dist/command-context.js +116 -0
- package/dist/core.d.ts +7 -0
- package/dist/core.js +36 -13
- package/dist/createPopoverSelect.svelte.d.ts +2 -2
- package/dist/editing.d.ts +2 -8
- package/dist/editing.js +272 -33
- package/dist/fill-patterns.d.ts +0 -5
- package/dist/fill-patterns.js +56 -2
- package/dist/gantt-view.svelte.d.ts +24 -0
- package/dist/gantt-view.svelte.js +13 -0
- package/dist/grid-icons.d.ts +2 -2
- package/dist/grid-icons.js +2 -2
- package/dist/grid-messages.d.ts +16 -3
- package/dist/grid-messages.js +10 -0
- package/dist/history.d.ts +83 -0
- package/dist/history.js +133 -0
- package/dist/index.d.ts +29 -10
- package/dist/index.js +23 -5
- package/dist/keyboard-handlers.js +88 -31
- package/dist/keyboard.d.ts +55 -0
- package/dist/keyboard.js +132 -0
- package/dist/menus.d.ts +3 -1
- package/dist/menus.js +7 -2
- package/dist/merges.d.ts +97 -0
- package/dist/merges.js +147 -0
- package/dist/row-model.d.ts +133 -0
- package/dist/row-model.js +16 -0
- package/dist/row-resize.d.ts +3 -0
- package/dist/row-resize.js +14 -0
- package/dist/scroll-sync.d.ts +1 -0
- package/dist/scroll-sync.js +24 -0
- package/dist/selection.d.ts +18 -1
- package/dist/selection.js +138 -18
- package/dist/server-block-cache.d.ts +214 -0
- package/dist/server-block-cache.js +531 -0
- package/dist/server-data-source.d.ts +240 -6
- package/dist/server-data-source.js +220 -20
- package/dist/server.d.ts +13 -0
- package/dist/server.js +13 -0
- package/dist/shortcut-registry.d.ts +145 -0
- package/dist/shortcut-registry.js +44 -0
- package/dist/svgrid-wrapper.types.d.ts +213 -22
- package/dist/validate.d.ts +4 -0
- package/dist/validate.js +21 -3
- package/dist/virtualization/virtualizer.js +38 -17
- package/package.json +11 -1
- package/src/GridMenus.svelte +44 -2
- package/src/SvChartMenu.svelte +69 -0
- package/src/SvChartPanes.svelte +113 -0
- package/src/SvChartPanes.test.ts +66 -0
- package/src/SvGrid.controller.svelte.ts +819 -179
- package/src/SvGrid.css +178 -2
- package/src/SvGrid.svelte +717 -720
- package/src/SvGrid.types.ts +564 -11
- package/src/SvGridCellEditor.svelte +17 -0
- package/src/SvGridChart.svelte +2257 -329
- package/src/SvGridChart.test.ts +1419 -1
- package/src/SvGridChart.types.ts +336 -0
- package/src/SvGridChartBuilder.svelte +323 -0
- package/src/SvGridChartPanel.svelte +221 -275
- package/src/SvGridChartPickers.svelte +417 -0
- package/src/SvGridChartView.svelte +13 -14
- package/src/SvModal.svelte +7 -1
- package/src/SvModal.test.ts +9 -0
- package/src/ai.test.ts +57 -2
- package/src/ai.ts +166 -22
- package/src/aria.d.ts +11 -0
- package/src/build-api.coverage.test.ts +184 -0
- package/src/build-api.ts +118 -22
- package/src/chart-axes.test.ts +573 -0
- package/src/chart-axes.ts +342 -0
- package/src/chart-cartesian.ts +1863 -0
- package/src/chart-decimate.test.ts +249 -0
- package/src/chart-decimate.ts +186 -0
- package/src/chart-export-pdf.test.ts +91 -0
- package/src/chart-export-pdf.ts +207 -0
- package/src/chart-export.test.ts +14 -0
- package/src/chart-export.ts +13 -3
- package/src/chart-financial.ts +208 -0
- package/src/chart-flow.ts +286 -0
- package/src/chart-format.ts +67 -0
- package/src/chart-grid.ts +179 -0
- package/src/chart-hierarchy.ts +135 -0
- package/src/chart-indicators.test.ts +443 -0
- package/src/chart-indicators.ts +384 -0
- package/src/chart-messages.test.ts +21 -0
- package/src/chart-messages.ts +184 -0
- package/src/chart-motion.test.ts +71 -0
- package/src/chart-motion.ts +148 -0
- package/src/chart-panel-messages.test.ts +29 -0
- package/src/chart-panel-messages.ts +550 -0
- package/src/chart-pivot.test.ts +54 -0
- package/src/chart-pivot.ts +225 -0
- package/src/chart-polar.ts +674 -0
- package/src/chart-samples.ts +106 -0
- package/src/chart-scale.ts +394 -0
- package/src/chart-series-types.test.ts +714 -0
- package/src/chart-stats.ts +409 -0
- package/src/chart-stream.test.ts +75 -0
- package/src/chart-stream.ts +114 -0
- package/src/chart-summary.test.ts +90 -0
- package/src/chart-summary.ts +197 -0
- package/src/chart-sync.svelte.ts +41 -0
- package/src/chart-table.test.ts +76 -0
- package/src/chart-table.ts +178 -0
- package/src/chart-trend.ts +47 -0
- package/src/chart-types.ts +1309 -0
- package/src/chart-validate.test.ts +100 -0
- package/src/chart-validate.ts +247 -0
- package/src/chart-zoom.test.ts +137 -0
- package/src/chart-zoom.ts +124 -0
- package/src/chart.coverage.test.ts +81 -0
- package/src/chart.test.ts +56 -3
- package/src/chart.ts +557 -2784
- package/src/clipboard.test.ts +151 -0
- package/src/clipboard.ts +145 -16
- package/src/column-resize.ts +7 -1
- package/src/columns.ts +2 -0
- package/src/command-context.test.ts +200 -0
- package/src/command-context.ts +137 -0
- package/src/core.rowmodel-cache.test.ts +51 -0
- package/src/core.ts +40 -12
- package/src/editing.test.ts +281 -3
- package/src/editing.ts +264 -38
- package/src/fill-patterns.test.ts +35 -0
- package/src/fill-patterns.ts +56 -2
- package/src/gantt-stub.test.svelte +38 -0
- package/src/gantt-view.svelte.ts +35 -0
- package/src/grid-icons.ts +2 -2
- package/src/grid-messages.ts +28 -3
- package/src/history.test.ts +196 -0
- package/src/history.ts +162 -0
- package/src/icon-seam.test.ts +5 -6
- package/src/index.ts +186 -12
- package/src/keyboard-handlers.coverage.test.ts +126 -6
- package/src/keyboard-handlers.ts +91 -30
- package/src/keyboard-shortcuts.seam.test.ts +200 -0
- package/src/keyboard.test.ts +124 -1
- package/src/keyboard.ts +142 -0
- package/src/menus.test.ts +26 -0
- package/src/menus.ts +10 -3
- package/src/merges.test.ts +112 -0
- package/src/merges.ts +168 -0
- package/src/pivot.grid.test.ts +40 -5
- package/src/row-model.ts +146 -0
- package/src/row-resize.test.ts +44 -0
- package/src/row-resize.ts +17 -0
- package/src/scroll-sync.test.ts +42 -1
- package/src/scroll-sync.ts +25 -0
- package/src/selection.multi-range.test.ts +34 -0
- package/src/selection.test.ts +33 -2
- package/src/selection.ts +143 -21
- package/src/server-block-cache.test.ts +645 -0
- package/src/server-block-cache.ts +677 -0
- package/src/server-data-source.infinite.test.ts +343 -0
- package/src/server-data-source.ts +450 -27
- package/src/server.ts +47 -0
- package/src/shortcut-registry.test.ts +97 -0
- package/src/shortcut-registry.ts +181 -0
- package/src/svgrid-wrapper.types.ts +184 -13
- package/src/svgrid.behavior.test.ts +135 -0
- package/src/svgrid.charting.test.ts +513 -3
- package/src/svgrid.context-menu.test.ts +31 -0
- package/src/svgrid.gantt-seam.test.ts +199 -0
- package/src/svgrid.new-features.wrapper.test.ts +10 -3
- package/src/svgrid.row-model-prop.svelte.test.ts +352 -0
- package/src/svgrid.row-model-seam.svelte.test.ts +289 -0
- package/src/svgrid.upsell-license.test.ts +7 -4
- package/src/validate.test.ts +29 -0
- package/src/validate.ts +28 -3
- package/src/virtualization/virtualizer.ts +39 -17
- package/dist/SvGroupCell.svelte +0 -141
- package/dist/SvGroupCell.svelte.d.ts +0 -49
- package/dist/SvRowGroupPanel.svelte +0 -186
- package/dist/SvRowGroupPanel.svelte.d.ts +0 -25
- package/dist/cdn/GridMenus-CHOMnW-c.js +0 -602
- package/dist/cdn/GridMenus-DhdPF700.js +0 -603
- package/dist/cdn/SvDateTimePicker-CCbDZNZB.js +0 -816
- package/dist/cdn/SvGridChart-1PMSp2LZ.js +0 -1481
- package/dist/cdn/SvGridChart-D02avhyr.js +0 -1480
- package/dist/cdn/SvGridChartPanel-DJnViOv4.js +0 -834
- package/dist/cdn/SvGridChartPanel-vPTNerFZ.js +0 -810
- package/dist/cdn/SvGridChartView-C--HhdUo.js +0 -56
- package/dist/cdn/SvGridChartView-KyyFG-wY.js +0 -55
- package/dist/cdn/chart-DLg3_zTQ.js +0 -1652
- package/dist/cdn/validate-_CDJzgIo.js +0 -75
- package/dist/server-group-model.d.ts +0 -98
- package/dist/server-group-model.js +0 -263
- package/src/SvGroupCell.svelte +0 -141
- package/src/SvRowGroupPanel.svelte +0 -186
- package/src/server-group-model.test.ts +0 -294
- package/src/server-group-model.ts +0 -370
package/src/selection.test.ts
CHANGED
|
@@ -39,6 +39,9 @@ function makeCtx(overrides: any = {}) {
|
|
|
39
39
|
allRows: [],
|
|
40
40
|
allColumns: [],
|
|
41
41
|
headerSelectionState: 'none',
|
|
42
|
+
// The real controller always supplies this; a fake that omits it would
|
|
43
|
+
// make every select-all path throw rather than assert.
|
|
44
|
+
placeholderStateOf: () => null,
|
|
42
45
|
userHasActivatedCell: false,
|
|
43
46
|
enableCellSelectionEffective: true,
|
|
44
47
|
selectionRange: { anchor: null, focus: null },
|
|
@@ -75,6 +78,8 @@ function makeCtx(overrides: any = {}) {
|
|
|
75
78
|
// for plain drag-select. Its own behaviour is covered in move-cells.test.ts.
|
|
76
79
|
trackEdgeScroll: vi.fn(),
|
|
77
80
|
stopEdgeScroll: vi.fn(),
|
|
81
|
+
// Inline virtualizer sync after a programmatic scroll (scroll-sync.ts).
|
|
82
|
+
syncScrollNow: vi.fn(),
|
|
78
83
|
grid: {
|
|
79
84
|
setRowSelection,
|
|
80
85
|
setActiveCell,
|
|
@@ -367,6 +372,19 @@ describe('createSelection - onCellPointerDown', () => {
|
|
|
367
372
|
expect(ctx.selectionRange.anchor).toEqual({ rowIndex: 0, colIndex: 0 })
|
|
368
373
|
expect(ctx.selectionRange.focus).toEqual({ rowIndex: 1, colIndex: 1 })
|
|
369
374
|
expect(ctx.activeAtPointerDown).toEqual({ rowIndex: 0, colIndex: 0 })
|
|
375
|
+
// The active cell stays at the anchor, as in Excel.
|
|
376
|
+
expect(ctx.grid.setActiveCell).not.toHaveBeenCalled()
|
|
377
|
+
})
|
|
378
|
+
|
|
379
|
+
it('Shift+click on a grid never clicked makes the cell active', () => {
|
|
380
|
+
const ctx = makeCtx({
|
|
381
|
+
allRows: [makeDataRow('r0'), makeDataRow('r1')],
|
|
382
|
+
allColumns: [makeColumn('c0'), makeColumn('c1')],
|
|
383
|
+
activeCell: null,
|
|
384
|
+
})
|
|
385
|
+
const sel = createSelection(ctx)
|
|
386
|
+
sel.onCellPointerDown(1, 1, { button: 0, shiftKey: true } as any)
|
|
387
|
+
expect(ctx.grid.setActiveCell).toHaveBeenCalled()
|
|
370
388
|
})
|
|
371
389
|
})
|
|
372
390
|
|
|
@@ -378,7 +396,7 @@ describe('createSelection - onCellPointerEnter / drag', () => {
|
|
|
378
396
|
expect(ctx.grid.setActiveCell).not.toHaveBeenCalled()
|
|
379
397
|
})
|
|
380
398
|
|
|
381
|
-
it('extends selection and
|
|
399
|
+
it('extends the selection while dragging and leaves the active cell where the drag began', () => {
|
|
382
400
|
const ctx = makeCtx({
|
|
383
401
|
isDraggingSelection: true,
|
|
384
402
|
selectionRange: { anchor: { rowIndex: 0, colIndex: 0 }, focus: { rowIndex: 0, colIndex: 0 } },
|
|
@@ -388,7 +406,7 @@ describe('createSelection - onCellPointerEnter / drag', () => {
|
|
|
388
406
|
const sel = createSelection(ctx)
|
|
389
407
|
sel.onCellPointerEnter(1, 1)
|
|
390
408
|
expect(ctx.selectionRange.focus).toEqual({ rowIndex: 1, colIndex: 1 })
|
|
391
|
-
expect(ctx.grid.setActiveCell).toHaveBeenCalled()
|
|
409
|
+
expect(ctx.grid.setActiveCell).not.toHaveBeenCalled()
|
|
392
410
|
})
|
|
393
411
|
|
|
394
412
|
it('ignores group rows while dragging', () => {
|
|
@@ -649,6 +667,19 @@ describe('createSelection - onCellClick', () => {
|
|
|
649
667
|
expect(ctx.onCellDoubleClick).toHaveBeenCalledWith(0, 0)
|
|
650
668
|
})
|
|
651
669
|
|
|
670
|
+
it('leaves the cell alone on a second click when editOnSecondClick is off', () => {
|
|
671
|
+
// A sheet: clicking the active cell again is a click, not an edit.
|
|
672
|
+
const ctx = clickCtx({
|
|
673
|
+
editingEnabled: true,
|
|
674
|
+
activeAtPointerDown: { rowIndex: 0, colIndex: 0 },
|
|
675
|
+
props: { editOnSecondClick: false },
|
|
676
|
+
})
|
|
677
|
+
const sel = createSelection(ctx)
|
|
678
|
+
sel.onCellClick(0, 0)
|
|
679
|
+
expect(ctx.onCellDoubleClick).not.toHaveBeenCalled()
|
|
680
|
+
expect(ctx.editingCell).toBeNull()
|
|
681
|
+
})
|
|
682
|
+
|
|
652
683
|
it('clears editing when not re-clicking the active cell', () => {
|
|
653
684
|
const ctx = clickCtx({
|
|
654
685
|
editingEnabled: true,
|
package/src/selection.ts
CHANGED
|
@@ -14,22 +14,52 @@ import {
|
|
|
14
14
|
getColumnBaseValue,
|
|
15
15
|
isGroupRow,
|
|
16
16
|
} from "./cell-values";
|
|
17
|
+
import { expandRectToMerges, originOf, endOf } from "./merges";
|
|
17
18
|
|
|
18
19
|
export function createSelection<
|
|
19
20
|
TFeatures extends TableFeatures = TableFeatures,
|
|
20
21
|
TData extends RowData = RowData,
|
|
21
22
|
>(ctx: any) {
|
|
22
23
|
function isRowSelected(rowId: string) {
|
|
24
|
+
const model = ctx.props.rowSelectionModel;
|
|
25
|
+
if (model) {
|
|
26
|
+
const row = ctx.allRows.find((r: any) => r.id === rowId);
|
|
27
|
+
return row ? model.isSelected(rowId, row.original) : false;
|
|
28
|
+
}
|
|
23
29
|
return Boolean(ctx.rowSelectionState[rowId]);
|
|
24
30
|
}
|
|
25
31
|
|
|
26
32
|
function toggleRowSelectionById(rowId: string) {
|
|
33
|
+
const model = ctx.props.rowSelectionModel;
|
|
34
|
+
if (model) {
|
|
35
|
+
const row = ctx.allRows.find((r: any) => r.id === rowId);
|
|
36
|
+
if (!row) return;
|
|
37
|
+
model.toggle(rowId, row.original, !model.isSelected(rowId, row.original));
|
|
38
|
+
return;
|
|
39
|
+
}
|
|
27
40
|
ctx.grid.setRowSelection((prev: any) => ({ ...prev, [rowId]: !prev[rowId] }));
|
|
28
41
|
}
|
|
29
42
|
|
|
30
43
|
function toggleSelectAllRows() {
|
|
31
|
-
|
|
32
|
-
|
|
44
|
+
setSelectAllRows(ctx.headerSelectionState !== "all");
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
/**
|
|
48
|
+
* Select or clear every row, for the header checkbox and for
|
|
49
|
+
* `api.selectAllRows()`.
|
|
50
|
+
*/
|
|
51
|
+
function setSelectAllRows(select: boolean) {
|
|
52
|
+
// An external model decides what "all" means - possibly a million rows
|
|
53
|
+
// the grid has never seen - so it gets the intent, not a row list.
|
|
54
|
+
if (ctx.props.rowSelectionModel) {
|
|
55
|
+
ctx.props.rowSelectionModel.toggleAll(select);
|
|
56
|
+
return;
|
|
57
|
+
}
|
|
58
|
+
// Placeholder rows are excluded: there is no row there to select yet,
|
|
59
|
+
// and ticking one would leave a selected id that never resolves.
|
|
60
|
+
const selectable = ctx.allRows.filter(
|
|
61
|
+
(row: any) => !isGroupRow(row) && !ctx.placeholderStateOf(row),
|
|
62
|
+
);
|
|
33
63
|
ctx.grid.setRowSelection((prev: any) => {
|
|
34
64
|
const next = { ...prev };
|
|
35
65
|
for (const row of selectable) {
|
|
@@ -41,7 +71,18 @@ export function createSelection<
|
|
|
41
71
|
}
|
|
42
72
|
|
|
43
73
|
function setActiveCell(rowIndex: number, colIndex: number) {
|
|
74
|
+
// The active cell inside a merge is its origin: the one that draws, the
|
|
75
|
+
// one the formula bar shows, the one an edit writes.
|
|
76
|
+
({ rowIndex, colIndex } = originOf(ctx.mergeIndex, rowIndex, colIndex));
|
|
44
77
|
ctx.userHasActivatedCell = true;
|
|
78
|
+
// A click, an arrow, a jump: the Tab run is over. The Tab and Enter
|
|
79
|
+
// paths put the origin back after this call when it should live on.
|
|
80
|
+
// Activating the cell the cursor is already on (typing into it, F2, a
|
|
81
|
+
// double-click) is not a move and keeps the run.
|
|
82
|
+
const prev = ctx.grid.getState().activeCell;
|
|
83
|
+
if (!prev || prev.rowIndex !== rowIndex || prev.colIndex !== colIndex) {
|
|
84
|
+
ctx.tabRunOrigin = null;
|
|
85
|
+
}
|
|
45
86
|
ctx.grid.setActiveCell({
|
|
46
87
|
rowIndex,
|
|
47
88
|
colIndex,
|
|
@@ -64,8 +105,16 @@ export function createSelection<
|
|
|
64
105
|
if (!ctx.scrollContainer) return;
|
|
65
106
|
if (rowIndex < 0 || rowIndex >= ctx.allRows.length) return;
|
|
66
107
|
if (colIndex < 0 || colIndex >= ctx.allColumns.length) return;
|
|
67
|
-
|
|
68
|
-
|
|
108
|
+
const container = ctx.scrollContainer as HTMLElement;
|
|
109
|
+
const topBefore = container.scrollTop;
|
|
110
|
+
const leftBefore = container.scrollLeft;
|
|
111
|
+
// A frozen row is always in view; only the column may need to move.
|
|
112
|
+
const frozen: number = ctx.frozenRowCount ?? 0;
|
|
113
|
+
const frozenBand: number = ctx.frozenBandHeight ?? 0;
|
|
114
|
+
|
|
115
|
+
if (rowIndex < frozen) {
|
|
116
|
+
// Always in view; only the column below may need to move.
|
|
117
|
+
} else if (ctx.rowVirtualizationEnabled) {
|
|
69
118
|
// Prefer the browser's native `scrollIntoView({ block: 'nearest' })`
|
|
70
119
|
// when the target row is already mounted. It does Excel-style
|
|
71
120
|
// minimum-scroll, respects the sticky thead via the
|
|
@@ -116,8 +165,10 @@ export function createSelection<
|
|
|
116
165
|
const rowHeight = ctx.virtualizer.getSizeForIndex(rowIndex)
|
|
117
166
|
const rowBottom = rowTopScroll + rowHeight
|
|
118
167
|
let nextTop = currentTop
|
|
119
|
-
|
|
120
|
-
|
|
168
|
+
// The frozen band sits under the header, so a row is hidden until
|
|
169
|
+
// it clears both.
|
|
170
|
+
if (rowTopScroll < currentTop + headerHeight + frozenBand) {
|
|
171
|
+
nextTop = rowTopScroll - headerHeight - frozenBand
|
|
121
172
|
} else if (rowBottom > currentTop + clientHeight) {
|
|
122
173
|
nextTop = rowBottom - clientHeight
|
|
123
174
|
}
|
|
@@ -170,33 +221,66 @@ export function createSelection<
|
|
|
170
221
|
} else if (cellEnd > viewEnd) {
|
|
171
222
|
ctx.scrollContainer.scrollLeft = cellEnd - ctx.scrollContainer.clientWidth;
|
|
172
223
|
}
|
|
173
|
-
//
|
|
174
|
-
//
|
|
224
|
+
// The scroll position is known right here, so hand it to the
|
|
225
|
+
// virtualizers now rather than waiting for the `scroll` event + rAF:
|
|
226
|
+
// that put the new row window one painted frame behind the active-cell
|
|
227
|
+
// move (see `syncScrollNow`). Reading the position back is cheap - the
|
|
228
|
+
// scrollIntoView / scrollTop writes above already laid the tree out.
|
|
229
|
+
const topAfter = container.scrollTop;
|
|
230
|
+
const leftAfter = container.scrollLeft;
|
|
231
|
+
if (topAfter !== topBefore || leftAfter !== leftBefore) {
|
|
232
|
+
ctx.syncScrollNow(topAfter, leftAfter);
|
|
233
|
+
}
|
|
175
234
|
}
|
|
176
235
|
|
|
177
|
-
// Normalize a range to a rectangle, or null when incomplete.
|
|
236
|
+
// Normalize a range to a rectangle, or null when incomplete. A merge
|
|
237
|
+
// the rectangle touches is in it whole, as a spreadsheet's selection
|
|
238
|
+
// has it: a merged cell is one cell.
|
|
178
239
|
function rangeRect(range: SelectionRange | null) {
|
|
179
240
|
const a = range?.anchor;
|
|
180
241
|
const f = range?.focus;
|
|
181
242
|
if (!a || !f) return null;
|
|
182
|
-
return {
|
|
243
|
+
return expandRectToMerges(ctx.mergeIndex, {
|
|
183
244
|
minRow: Math.min(a.rowIndex, f.rowIndex),
|
|
184
245
|
maxRow: Math.max(a.rowIndex, f.rowIndex),
|
|
185
246
|
minCol: Math.min(a.colIndex, f.colIndex),
|
|
186
247
|
maxCol: Math.max(a.colIndex, f.colIndex),
|
|
187
|
-
};
|
|
248
|
+
});
|
|
249
|
+
}
|
|
250
|
+
|
|
251
|
+
type SelectionRect = { minRow: number; maxRow: number; minCol: number; maxCol: number };
|
|
252
|
+
|
|
253
|
+
/** The active range as a rectangle, or null while nothing is anchored. */
|
|
254
|
+
function activeRangeRect(): SelectionRect | null {
|
|
255
|
+
return rangeRect(ctx.selectionRange as SelectionRange);
|
|
188
256
|
}
|
|
257
|
+
// Memo for `getSelectionRects`, keyed on the identity of its two inputs.
|
|
258
|
+
// Both are replaced wholesale on every change and never mutated in place,
|
|
259
|
+
// so identity is a complete change check. Without it, every rendered
|
|
260
|
+
// cell's outline derived rebuilt this array on every arrow key - ~300
|
|
261
|
+
// arrays plus their rect objects per key press, for a result that is the
|
|
262
|
+
// same until the selection moves.
|
|
263
|
+
let rectsForRange: SelectionRange | null = null;
|
|
264
|
+
let rectsForRanges: SelectionRange[] | null = null;
|
|
265
|
+
let rectsMemo: SelectionRect[] = [];
|
|
189
266
|
|
|
190
267
|
// Every selected rectangle: the committed extra ranges plus the active one.
|
|
191
268
|
// Order matters for copy (added-order); the active range comes last.
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
|
|
269
|
+
// Callers must treat the result as read-only.
|
|
270
|
+
function getSelectionRects(): SelectionRect[] {
|
|
271
|
+
const range = ctx.selectionRange as SelectionRange;
|
|
272
|
+
const ranges = (ctx.selectionRanges as SelectionRange[]) ?? [];
|
|
273
|
+
if (range === rectsForRange && ranges === rectsForRanges) return rectsMemo;
|
|
274
|
+
const rects: SelectionRect[] = [];
|
|
275
|
+
for (const r of ranges) {
|
|
195
276
|
const rect = rangeRect(r);
|
|
196
277
|
if (rect) rects.push(rect);
|
|
197
278
|
}
|
|
198
|
-
const active = rangeRect(
|
|
279
|
+
const active = rangeRect(range);
|
|
199
280
|
if (active) rects.push(active);
|
|
281
|
+
rectsForRange = range;
|
|
282
|
+
rectsForRanges = ranges;
|
|
283
|
+
rectsMemo = rects;
|
|
200
284
|
return rects;
|
|
201
285
|
}
|
|
202
286
|
|
|
@@ -259,6 +343,9 @@ export function createSelection<
|
|
|
259
343
|
// that work to return null every time.
|
|
260
344
|
if (!hasAnySelectionRect()) return null;
|
|
261
345
|
|
|
346
|
+
// A td inside a merge draws to the merge's far corner, so its bottom and
|
|
347
|
+
// right edges are the merge's, not the cell's.
|
|
348
|
+
const end = endOf(ctx.mergeIndex, rowIndex, colIndex);
|
|
262
349
|
for (const rect of getSelectionRects()) {
|
|
263
350
|
if (
|
|
264
351
|
rowIndex < rect.minRow ||
|
|
@@ -270,14 +357,40 @@ export function createSelection<
|
|
|
270
357
|
}
|
|
271
358
|
return {
|
|
272
359
|
top: rowIndex === rect.minRow,
|
|
273
|
-
bottom: rowIndex === rect.maxRow,
|
|
360
|
+
bottom: end.rowIndex === rect.maxRow,
|
|
274
361
|
left: colIndex === rect.minCol,
|
|
275
|
-
right: colIndex === rect.maxCol,
|
|
362
|
+
right: end.colIndex === rect.maxCol,
|
|
276
363
|
};
|
|
277
364
|
}
|
|
278
365
|
return null;
|
|
279
366
|
}
|
|
280
367
|
|
|
368
|
+
/**
|
|
369
|
+
* Everything a cell's outline needs from the selection model, in ONE value:
|
|
370
|
+
* whether it is the active cell, which range edges it sits on (`edges` is
|
|
371
|
+
* null when it is in no range) and whether it carries the fill handle.
|
|
372
|
+
* `null` for a cell that is none of those - nearly every cell.
|
|
373
|
+
*
|
|
374
|
+
* One value on purpose. The view reads it through a single `{@const}`, so
|
|
375
|
+
* an active-cell move re-marks one derived per rendered cell instead of
|
|
376
|
+
* three (active flag, range edges, fill handle) plus the fill handle's
|
|
377
|
+
* `{#if}`. With ~300 cells rendered, that marking was the largest single
|
|
378
|
+
* cost of an arrow key that does not scroll. A plain cell returns the same
|
|
379
|
+
* `null` it returned before the move, so its attribute effect stays put.
|
|
380
|
+
*/
|
|
381
|
+
function cellSelectionState(rowIndex: number, colIndex: number) {
|
|
382
|
+
const a = ctx.activeCell;
|
|
383
|
+
const active = !!a && a.rowIndex === rowIndex && a.colIndex === colIndex;
|
|
384
|
+
const edges = getCellRangeEdges(rowIndex, colIndex);
|
|
385
|
+
const fh = ctx.fillHandleCell;
|
|
386
|
+
// The handle sits on the range's bottom-right cell; when that is inside
|
|
387
|
+
// a merge, the td that draws the merge carries it.
|
|
388
|
+
const end = fh ? endOf(ctx.mergeIndex, rowIndex, colIndex) : null;
|
|
389
|
+
const fillHandle = !!fh && !!end && fh.rowIndex === end.rowIndex && fh.colIndex === end.colIndex;
|
|
390
|
+
if (!active && !edges && !fillHandle) return null;
|
|
391
|
+
return { active, edges, fillHandle };
|
|
392
|
+
}
|
|
393
|
+
|
|
281
394
|
/**
|
|
282
395
|
* The rectangle a drag is currently promising, or null when no drag is in
|
|
283
396
|
* flight. A fill grows the source rectangle out to the pointer; a move
|
|
@@ -395,8 +508,12 @@ export function createSelection<
|
|
|
395
508
|
? { rowIndex: active.rowIndex, colIndex: active.colIndex }
|
|
396
509
|
: null;
|
|
397
510
|
if (event.shiftKey) {
|
|
511
|
+
// The range grows to the clicked cell and the active cell stays where
|
|
512
|
+
// it is, as in Excel: it is the cell the formula bar shows and the
|
|
513
|
+
// one the next keystroke edits. Used to jump to the clicked corner,
|
|
514
|
+
// so a Shift+click to select B2:D5 then typing wrote into D5.
|
|
398
515
|
extendSelection(rowIndex, colIndex);
|
|
399
|
-
setActiveCell(rowIndex, colIndex);
|
|
516
|
+
if (!active) setActiveCell(rowIndex, colIndex);
|
|
400
517
|
} else {
|
|
401
518
|
setActiveCell(rowIndex, colIndex);
|
|
402
519
|
// Ctrl/Cmd starts an ADDITIONAL range, keeping prior ranges highlighted.
|
|
@@ -414,8 +531,9 @@ export function createSelection<
|
|
|
414
531
|
if (!ctx.isDraggingSelection) return;
|
|
415
532
|
const row = ctx.allRows[rowIndex];
|
|
416
533
|
if (!row || isGroupRow(row)) return;
|
|
534
|
+
// The active cell is where the drag began; only the range's far corner
|
|
535
|
+
// follows the pointer.
|
|
417
536
|
extendSelection(rowIndex, colIndex);
|
|
418
|
-
setActiveCell(rowIndex, colIndex);
|
|
419
537
|
}
|
|
420
538
|
|
|
421
539
|
/** `event` is the window `pointerup` when this comes from the real gesture,
|
|
@@ -550,12 +668,13 @@ export function createSelection<
|
|
|
550
668
|
}
|
|
551
669
|
|
|
552
670
|
// onCellPointerDown already set active+selection for data cells. Only
|
|
553
|
-
// decide whether to enter edit mode (click on the previously-active cell
|
|
671
|
+
// decide whether to enter edit mode (click on the previously-active cell,
|
|
672
|
+
// unless the grid was told a second click is just a click).
|
|
554
673
|
const wasActive =
|
|
555
674
|
ctx.activeAtPointerDown !== null &&
|
|
556
675
|
ctx.activeAtPointerDown.rowIndex === rowIndex &&
|
|
557
676
|
ctx.activeAtPointerDown.colIndex === colIndex;
|
|
558
|
-
if (wasActive && ctx.editingEnabled) {
|
|
677
|
+
if (wasActive && ctx.editingEnabled && ctx.props.editOnSecondClick !== false) {
|
|
559
678
|
ctx.onCellDoubleClick(rowIndex, colIndex);
|
|
560
679
|
return;
|
|
561
680
|
}
|
|
@@ -597,12 +716,15 @@ export function createSelection<
|
|
|
597
716
|
isRowSelected,
|
|
598
717
|
toggleRowSelectionById,
|
|
599
718
|
toggleSelectAllRows,
|
|
719
|
+
setSelectAllRows,
|
|
600
720
|
setActiveCell,
|
|
601
721
|
scrollActiveCellIntoView,
|
|
602
722
|
setSelection,
|
|
603
723
|
extendSelection,
|
|
604
724
|
isCellInSelectedRange,
|
|
605
725
|
getCellRangeEdges,
|
|
726
|
+
activeRangeRect,
|
|
727
|
+
cellSelectionState,
|
|
606
728
|
fillMarqueeEdges,
|
|
607
729
|
getSelectionRects,
|
|
608
730
|
isInFillPreview,
|