@svgrid/grid 3.0.2 → 3.0.4
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 +2 -1
- 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 +110 -39
- package/dist/SvGrid.controller.svelte.js +655 -200
- package/dist/SvGrid.css +105 -2
- package/dist/SvGrid.svelte +386 -514
- package/dist/SvGrid.types.d.ts +210 -9
- 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 +108 -22
- package/dist/cdn/GridMenus-7kbpnnBW.js +635 -0
- package/dist/cdn/GridMenus-BL7ZgQvU.js +636 -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/{src-DNbz94Ct.js → src-BKhZ6eXd.js} +10227 -9787
- package/dist/cdn/{src-BJ2opd0j.js → src-V1uu8iE9.js} +6568 -6128
- package/dist/cdn/svgrid.js +26 -15
- package/dist/cdn/svgrid.svelte-external.js +26 -15
- 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/createPopoverSelect.svelte.d.ts +2 -2
- package/dist/editing.d.ts +2 -8
- package/dist/editing.js +262 -33
- package/dist/fill-patterns.d.ts +0 -5
- package/dist/fill-patterns.js +56 -2
- package/dist/grid-messages.d.ts +10 -3
- package/dist/grid-messages.js +5 -0
- package/dist/history.d.ts +83 -0
- package/dist/history.js +133 -0
- package/dist/index.d.ts +24 -6
- package/dist/index.js +20 -2
- 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-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 +16 -0
- package/dist/selection.js +108 -16
- 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/virtualization/virtualizer.js +38 -17
- package/package.json +6 -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 +629 -172
- package/src/SvGrid.css +105 -2
- package/src/SvGrid.svelte +386 -514
- package/src/SvGrid.types.ts +188 -8
- 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 +107 -18
- 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.ts +7 -0
- package/src/editing.test.ts +281 -3
- package/src/editing.ts +256 -38
- package/src/fill-patterns.test.ts +35 -0
- package/src/fill-patterns.ts +56 -2
- package/src/grid-messages.ts +16 -3
- package/src/history.test.ts +196 -0
- package/src/history.ts +162 -0
- package/src/icon-seam.test.ts +3 -2
- package/src/index.ts +150 -2
- 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-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 +30 -2
- package/src/selection.ts +111 -19
- 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.new-features.wrapper.test.ts +10 -3
- package/src/virtualization/virtualizer.ts +39 -17
- package/dist/cdn/GridMenus-DyFA-QxA.js +0 -602
- package/dist/cdn/GridMenus-M2XP9t0_.js +0 -603
- package/dist/cdn/SvDateTimePicker-CCbDZNZB.js +0 -816
- package/dist/cdn/SvGridChart-DAb9RbRs.js +0 -1480
- package/dist/cdn/SvGridChart-Yl-IXZFO.js +0 -1481
- package/dist/cdn/SvGridChartPanel-DayQpDsR.js +0 -834
- package/dist/cdn/SvGridChartPanel-aqf8n-vJ.js +0 -810
- package/dist/cdn/SvGridChartView-CxfakxR0.js +0 -56
- package/dist/cdn/SvGridChartView-Dm_YEx9L.js +0 -55
- package/dist/cdn/chart-CKJRCPOk.js +0 -1652
package/dist/clipboard.d.ts
CHANGED
|
@@ -8,6 +8,7 @@ export declare function createClipboard<TFeatures extends TableFeatures = TableF
|
|
|
8
8
|
startFillDrag: (event: PointerEvent, rowIndex: number, colIndex: number) => void;
|
|
9
9
|
onFillPointerMove: (event: PointerEvent) => void;
|
|
10
10
|
onFillPointerUp: () => void;
|
|
11
|
+
fillDownToNeighbour: () => void;
|
|
11
12
|
isOnMoveGrabStrip: (cell: HTMLElement, rowIndex: number, colIndex: number, clientX: number, clientY: number) => boolean;
|
|
12
13
|
startMoveDrag: (event: PointerEvent, rowIndex: number, colIndex: number) => boolean;
|
|
13
14
|
onMovePointerMove: (event: PointerEvent) => void;
|
package/dist/clipboard.js
CHANGED
|
@@ -6,6 +6,7 @@ import "./sv-grid-scrollbar.js";
|
|
|
6
6
|
import { buildFillPattern } from "./fill-patterns.js";
|
|
7
7
|
import { getCellKey, } from "./SvGrid.helpers.js";
|
|
8
8
|
import { createDataIndexLookup, getColumnBaseValue, isGroupRow, toolPanelHeaderLabel, } from "./cell-values.js";
|
|
9
|
+
import { pushHistory, nextGroupId, runHistoryGroup } from "./history.js";
|
|
9
10
|
export function createClipboard(ctx) {
|
|
10
11
|
/**
|
|
11
12
|
* `rowIndex` here is a DISPLAY index - a position in `allRows`, the space the
|
|
@@ -69,7 +70,86 @@ export function createClipboard(ctx) {
|
|
|
69
70
|
/** Apply the pattern fill on pointerup. Each NEW row (or column) is
|
|
70
71
|
* filled from a pattern derived from the matching column (or row) of
|
|
71
72
|
* the source. Handles all four drag directions. */
|
|
73
|
+
/**
|
|
74
|
+
* Write one filled cell and remember it, so the drag undoes as a unit.
|
|
75
|
+
* `writeCellRaw` keeps no history of its own; the fill used to call it in
|
|
76
|
+
* a loop and push nothing, which left Ctrl+Z blind to a whole drag.
|
|
77
|
+
*/
|
|
78
|
+
function writeFilled(steps, rowIndex, columnId, value) {
|
|
79
|
+
const row = ctx.allRows[rowIndex];
|
|
80
|
+
const column = ctx.findColumnById(columnId);
|
|
81
|
+
const field = column?.columnDef.field;
|
|
82
|
+
if (!row || field == null)
|
|
83
|
+
return;
|
|
84
|
+
const before = readCellRaw(rowIndex, columnId);
|
|
85
|
+
writeCellRaw(rowIndex, columnId, value);
|
|
86
|
+
if (before !== value)
|
|
87
|
+
steps.push({ rowId: row.id, columnId, field, before, after: value });
|
|
88
|
+
}
|
|
72
89
|
function applyFillPattern() {
|
|
90
|
+
const steps = [];
|
|
91
|
+
runHistoryGroup(ctx, () => applyFillCells(steps));
|
|
92
|
+
if (steps.length)
|
|
93
|
+
pushHistory(ctx, steps, nextGroupId());
|
|
94
|
+
}
|
|
95
|
+
/**
|
|
96
|
+
* The value for the i-th filled cell: the consumer's, when its hook has
|
|
97
|
+
* one for the source cell the target cycles back to, else the pattern's.
|
|
98
|
+
* `sourceStart` is the row (or column) of the first source value and
|
|
99
|
+
* `targetStart` that of the first target; `step` is -1 filling upward.
|
|
100
|
+
*/
|
|
101
|
+
function filledValue(sources, pattern, i, sourceStart, targetStart, step, axis, rowIndex, columnId) {
|
|
102
|
+
const hook = ctx.props.processCellForFill;
|
|
103
|
+
if (hook && sources.length) {
|
|
104
|
+
const k = i % sources.length;
|
|
105
|
+
const distance = (targetStart + step * i) - (sourceStart + step * k);
|
|
106
|
+
const delta = axis === "rows" ? { rows: distance, cols: 0 } : { rows: 0, cols: distance };
|
|
107
|
+
const decided = hook({ value: sources[k], delta, rowIndex, columnId });
|
|
108
|
+
if (decided !== undefined)
|
|
109
|
+
return decided;
|
|
110
|
+
}
|
|
111
|
+
return pattern[i];
|
|
112
|
+
}
|
|
113
|
+
/**
|
|
114
|
+
* Double-click on the fill handle: fill down as far as the column beside
|
|
115
|
+
* the selection has data, the way Excel's does. The column to the left
|
|
116
|
+
* decides; when it is blank below the selection (or there is none) the
|
|
117
|
+
* one to the right does. Nothing to follow, nothing filled.
|
|
118
|
+
*/
|
|
119
|
+
function fillDownToNeighbour() {
|
|
120
|
+
const anchor = ctx.selectionRange.anchor ?? ctx.grid.getState().activeCell;
|
|
121
|
+
if (!anchor)
|
|
122
|
+
return;
|
|
123
|
+
const focus = ctx.selectionRange.focus ?? anchor;
|
|
124
|
+
const minRow = Math.min(anchor.rowIndex, focus.rowIndex);
|
|
125
|
+
const maxRow = Math.max(anchor.rowIndex, focus.rowIndex);
|
|
126
|
+
const minCol = Math.min(anchor.colIndex, focus.colIndex);
|
|
127
|
+
const maxCol = Math.max(anchor.colIndex, focus.colIndex);
|
|
128
|
+
const filled = (r, c) => {
|
|
129
|
+
const col = ctx.allColumns[c];
|
|
130
|
+
if (!col)
|
|
131
|
+
return false;
|
|
132
|
+
const v = readCellRaw(r, col.id);
|
|
133
|
+
return v != null && v !== "";
|
|
134
|
+
};
|
|
135
|
+
const extent = (c) => {
|
|
136
|
+
let r = maxRow;
|
|
137
|
+
while (r + 1 < ctx.allRows.length && filled(r + 1, c))
|
|
138
|
+
r += 1;
|
|
139
|
+
return r;
|
|
140
|
+
};
|
|
141
|
+
let target = minCol > 0 ? extent(minCol - 1) : maxRow;
|
|
142
|
+
if (target === maxRow)
|
|
143
|
+
target = extent(maxCol + 1);
|
|
144
|
+
if (target <= maxRow)
|
|
145
|
+
return;
|
|
146
|
+
ctx.fillDrag = {
|
|
147
|
+
sourceMinRow: minRow, sourceMaxRow: maxRow, sourceMinCol: minCol, sourceMaxCol: maxCol,
|
|
148
|
+
targetRow: target, targetCol: maxCol,
|
|
149
|
+
};
|
|
150
|
+
applyFillPattern();
|
|
151
|
+
}
|
|
152
|
+
function applyFillCells(steps) {
|
|
73
153
|
const d = ctx.fillDrag;
|
|
74
154
|
if (!d)
|
|
75
155
|
return;
|
|
@@ -102,7 +182,7 @@ export function createClipboard(ctx) {
|
|
|
102
182
|
for (let i = 0; i < targetRows; i += 1) {
|
|
103
183
|
const targetRow = d.sourceMaxRow + 1 + i;
|
|
104
184
|
if (ctx.isCellEditableAt(targetRow, c))
|
|
105
|
-
|
|
185
|
+
writeFilled(steps, targetRow, column.id, filledValue(sourceColValues, fills, i, d.sourceMinRow, d.sourceMaxRow + 1, 1, "rows", targetRow, column.id));
|
|
106
186
|
}
|
|
107
187
|
}
|
|
108
188
|
if (newMinRow < d.sourceMinRow) {
|
|
@@ -113,7 +193,7 @@ export function createClipboard(ctx) {
|
|
|
113
193
|
for (let i = 0; i < targetRows; i += 1) {
|
|
114
194
|
const targetRow = d.sourceMinRow - 1 - i;
|
|
115
195
|
if (ctx.isCellEditableAt(targetRow, c))
|
|
116
|
-
|
|
196
|
+
writeFilled(steps, targetRow, column.id, filledValue(reversed, fills, i, d.sourceMaxRow, d.sourceMinRow - 1, -1, "rows", targetRow, column.id));
|
|
117
197
|
}
|
|
118
198
|
}
|
|
119
199
|
}
|
|
@@ -136,7 +216,7 @@ export function createClipboard(ctx) {
|
|
|
136
216
|
const targetCol = d.sourceMaxCol + 1 + i;
|
|
137
217
|
const col = ctx.allColumns[targetCol];
|
|
138
218
|
if (col && ctx.isCellEditableAt(r, targetCol))
|
|
139
|
-
|
|
219
|
+
writeFilled(steps, r, col.id, filledValue(sourceRowValues, fills, i, d.sourceMinCol, d.sourceMaxCol + 1, 1, "cols", r, col.id));
|
|
140
220
|
}
|
|
141
221
|
}
|
|
142
222
|
if (newMinCol < d.sourceMinCol) {
|
|
@@ -147,7 +227,7 @@ export function createClipboard(ctx) {
|
|
|
147
227
|
const targetCol = d.sourceMinCol - 1 - i;
|
|
148
228
|
const col = ctx.allColumns[targetCol];
|
|
149
229
|
if (col && ctx.isCellEditableAt(r, targetCol))
|
|
150
|
-
|
|
230
|
+
writeFilled(steps, r, col.id, filledValue(reversed, fills, i, d.sourceMaxCol, d.sourceMinCol - 1, -1, "cols", r, col.id));
|
|
151
231
|
}
|
|
152
232
|
}
|
|
153
233
|
}
|
|
@@ -572,19 +652,10 @@ export function createClipboard(ctx) {
|
|
|
572
652
|
write(dest.minRow + r, dest.minCol + c, values[r][c]);
|
|
573
653
|
}
|
|
574
654
|
}
|
|
575
|
-
//
|
|
576
|
-
//
|
|
577
|
-
//
|
|
578
|
-
|
|
579
|
-
let hist = ctx.history.slice(0, ctx.historyPtr + 1);
|
|
580
|
-
for (const step of steps)
|
|
581
|
-
hist.push(step);
|
|
582
|
-
if (hist.length > ctx.UNDO_LIMIT)
|
|
583
|
-
hist = hist.slice(hist.length - ctx.UNDO_LIMIT);
|
|
584
|
-
ctx.history = hist;
|
|
585
|
-
ctx.historyPtr = ctx.history.length - 1;
|
|
586
|
-
ctx.historyVersion += 1;
|
|
587
|
-
}
|
|
655
|
+
// The whole move is ONE undo entry. It used to be one step per changed
|
|
656
|
+
// cell, so walking a 15x20 move back took 300 presses of Ctrl+Z and blew
|
|
657
|
+
// past UNDO_LIMIT, evicting every step behind it.
|
|
658
|
+
pushHistory(ctx, steps, nextGroupId());
|
|
588
659
|
// Follow the values: the range stays selected where it landed, so a
|
|
589
660
|
// second drag can chain off the first the way it does in a spreadsheet.
|
|
590
661
|
ctx.selectionRanges = [];
|
|
@@ -629,6 +700,41 @@ export function createClipboard(ctx) {
|
|
|
629
700
|
}
|
|
630
701
|
legacyCopyText(text);
|
|
631
702
|
}
|
|
703
|
+
/**
|
|
704
|
+
* Text and HTML together. The `copy` event is the first path: a listener
|
|
705
|
+
* armed for this one call puts both types on the event's clipboardData
|
|
706
|
+
* while the legacy textarea copy runs, which works in a secure and an
|
|
707
|
+
* insecure context alike and keeps every attribute of the HTML. Only when
|
|
708
|
+
* the browser refuses that does the async `ClipboardItem` write run, and
|
|
709
|
+
* text alone after that.
|
|
710
|
+
*/
|
|
711
|
+
function writeClipboard(text, html) {
|
|
712
|
+
if (typeof document !== "undefined") {
|
|
713
|
+
let armed = true;
|
|
714
|
+
const onCopy = (event) => {
|
|
715
|
+
if (!armed || !event.clipboardData)
|
|
716
|
+
return;
|
|
717
|
+
armed = false;
|
|
718
|
+
event.clipboardData.setData("text/plain", text);
|
|
719
|
+
event.clipboardData.setData("text/html", html);
|
|
720
|
+
event.preventDefault();
|
|
721
|
+
};
|
|
722
|
+
document.addEventListener("copy", onCopy, { once: true, capture: true });
|
|
723
|
+
const ok = legacyCopyText(text);
|
|
724
|
+
document.removeEventListener("copy", onCopy, { capture: true });
|
|
725
|
+
if (ok && !armed)
|
|
726
|
+
return;
|
|
727
|
+
}
|
|
728
|
+
if (navigator.clipboard?.write && typeof ClipboardItem !== "undefined") {
|
|
729
|
+
const item = new ClipboardItem({
|
|
730
|
+
"text/plain": new Blob([text], { type: "text/plain" }),
|
|
731
|
+
"text/html": new Blob([html], { type: "text/html" }),
|
|
732
|
+
});
|
|
733
|
+
void navigator.clipboard.write([item]).catch(() => writeClipboardText(text));
|
|
734
|
+
return;
|
|
735
|
+
}
|
|
736
|
+
writeClipboardText(text);
|
|
737
|
+
}
|
|
632
738
|
function legacyCopyText(text) {
|
|
633
739
|
if (typeof document === "undefined")
|
|
634
740
|
return false;
|
|
@@ -705,7 +811,13 @@ export function createClipboard(ctx) {
|
|
|
705
811
|
}
|
|
706
812
|
blocks.push(lines.join("\n"));
|
|
707
813
|
}
|
|
708
|
-
|
|
814
|
+
const text = blocks.join("\n\n");
|
|
815
|
+
const toHtml = ctx.props.clipboardHtml;
|
|
816
|
+
const html = toHtml?.({ rects, text });
|
|
817
|
+
if (html)
|
|
818
|
+
writeClipboard(text, html);
|
|
819
|
+
else
|
|
820
|
+
writeClipboardText(text);
|
|
709
821
|
}
|
|
710
822
|
/**
|
|
711
823
|
* Clear every editable cell in the current selection range. Used by
|
|
@@ -725,6 +837,10 @@ export function createClipboard(ctx) {
|
|
|
725
837
|
const next = ctx.internalData.slice();
|
|
726
838
|
let mutated = false;
|
|
727
839
|
const changes = [];
|
|
840
|
+
// One history step per cleared cell, grouped, so Delete over a block is
|
|
841
|
+
// one Ctrl+Z. Clearing used to record nothing at all: the values were
|
|
842
|
+
// gone and undo skipped straight past them to whatever came before.
|
|
843
|
+
const steps = [];
|
|
728
844
|
const dataIndexOf = createDataIndexLookup(next);
|
|
729
845
|
for (let r = startRow; r <= endRow; r += 1) {
|
|
730
846
|
const row = ctx.allRows[r];
|
|
@@ -757,6 +873,7 @@ export function createClipboard(ctx) {
|
|
|
757
873
|
const cleared = parseEditorValue(editorType, "");
|
|
758
874
|
updated[field] = cleared;
|
|
759
875
|
rowChanged = true;
|
|
876
|
+
steps.push({ rowId: row.id, columnId: column.id, field, before: oldValue, after: cleared });
|
|
760
877
|
changes.push({
|
|
761
878
|
rowIndex: dataIndex,
|
|
762
879
|
columnId: column.id,
|
|
@@ -773,6 +890,7 @@ export function createClipboard(ctx) {
|
|
|
773
890
|
if (mutated) {
|
|
774
891
|
ctx.internalData = next;
|
|
775
892
|
ctx.grid.store.setState((prev) => ({ ...prev }));
|
|
893
|
+
pushHistory(ctx, steps, nextGroupId());
|
|
776
894
|
// Fire onCellValueChange per cleared cell - same as paste's writeCellRaw -
|
|
777
895
|
// so consumers (formula engines, autosave) recompute. Clear IS a value
|
|
778
896
|
// change; without this, a HyperFormula-backed grid wouldn't re-evaluate.
|
|
@@ -800,6 +918,7 @@ export function createClipboard(ctx) {
|
|
|
800
918
|
startFillDrag,
|
|
801
919
|
onFillPointerMove,
|
|
802
920
|
onFillPointerUp,
|
|
921
|
+
fillDownToNeighbour,
|
|
803
922
|
isOnMoveGrabStrip,
|
|
804
923
|
startMoveDrag,
|
|
805
924
|
onMovePointerMove,
|
package/dist/column-resize.d.ts
CHANGED
|
@@ -24,6 +24,9 @@ export type ColumnResizeOptions = {
|
|
|
24
24
|
getWidth: (columnId: string) => number;
|
|
25
25
|
/** Called on every animation frame of the drag, and once at the end. */
|
|
26
26
|
onResize: (columnId: string, width: number) => void;
|
|
27
|
+
/** Called once when a drag ends or an arrow key has resized, with the
|
|
28
|
+
* width the gesture started from: what an undo puts back. */
|
|
29
|
+
onResizeEnd?: (columnId: string, width: number, startWidth: number) => void;
|
|
27
30
|
/** Accessible name for the handle. Defaults to the column id. */
|
|
28
31
|
label?: (columnId: string) => string;
|
|
29
32
|
/**
|
package/dist/column-resize.js
CHANGED
|
@@ -58,6 +58,7 @@ export function columnResize(node, opts) {
|
|
|
58
58
|
// Commit the final width even if the last frame was cancelled mid-flight.
|
|
59
59
|
pendingWidth = Math.max(minWidth(), drag.startWidth + (e.clientX - drag.startX));
|
|
60
60
|
commit();
|
|
61
|
+
current.onResizeEnd?.(drag.columnId, pendingWidth, drag.startWidth);
|
|
61
62
|
drag.handle.classList.remove('is-resizing');
|
|
62
63
|
syncAria(drag.handle, drag.columnId);
|
|
63
64
|
try {
|
|
@@ -121,8 +122,10 @@ export function columnResize(node, opts) {
|
|
|
121
122
|
return;
|
|
122
123
|
e.preventDefault();
|
|
123
124
|
e.stopPropagation();
|
|
124
|
-
const
|
|
125
|
+
const start = current.getWidth(columnId);
|
|
126
|
+
const next = Math.max(minWidth(), Math.round(start + delta));
|
|
125
127
|
current.onResize(columnId, next);
|
|
128
|
+
current.onResizeEnd?.(columnId, next, start);
|
|
126
129
|
syncAria(t, columnId);
|
|
127
130
|
}
|
|
128
131
|
/** A focusable separator is a widget, so ARIA wants a current value. */
|
package/dist/columns.js
CHANGED
|
@@ -151,6 +151,9 @@ export function createColumns(ctx) {
|
|
|
151
151
|
return ctx.props.columnWidth ?? 140;
|
|
152
152
|
}
|
|
153
153
|
function getColumnWidth(columnId) {
|
|
154
|
+
// Collapsed: no room at all, whatever width it keeps for later.
|
|
155
|
+
if (ctx.collapsedColumns?.[columnId])
|
|
156
|
+
return 0;
|
|
154
157
|
const fitted = ctx.fittedColumnWidths?.[columnId];
|
|
155
158
|
if (fitted !== undefined && ctx.columnWidths[columnId] === undefined)
|
|
156
159
|
return fitted;
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Builds the `GridCommandContext` handed to registered keyboard commands.
|
|
3
|
+
*
|
|
4
|
+
* Deliberately a getter object over the controller `ctx` rather than a
|
|
5
|
+
* snapshot: it is constructed on every keystroke that reaches a registered
|
|
6
|
+
* handler, so copying row and column arrays into it would put an allocation
|
|
7
|
+
* proportional to the grid in the hot path. Getters make construction O(1) and
|
|
8
|
+
* charge only for what a handler actually reads.
|
|
9
|
+
*
|
|
10
|
+
* Everything here is display-indexed, matching `SelectionPoint` and the rest of
|
|
11
|
+
* the selection model, so indices follow sort, filter and pagination. That is
|
|
12
|
+
* why `getCellValue` / `setCellValue` exist here rather than being left to
|
|
13
|
+
* `api.getCellValue`: the api pair indexes the DATA array, so handing a handler
|
|
14
|
+
* a selection index and an api that reads a different index space would give
|
|
15
|
+
* the wrong cell the moment the grid is sorted or filtered. `api.refresh()` has
|
|
16
|
+
* no index in it, so that one is left to the api.
|
|
17
|
+
*/
|
|
18
|
+
import type { GridCommandContext } from "./shortcut-registry.js";
|
|
19
|
+
export declare function buildCommandContext(ctx: any, editing: boolean): GridCommandContext;
|
|
@@ -0,0 +1,116 @@
|
|
|
1
|
+
import { pushHistory, runHistoryGroup } from "./history.js";
|
|
2
|
+
export function buildCommandContext(ctx, editing) {
|
|
3
|
+
function columnIdAt(colIndex) {
|
|
4
|
+
return ctx.allColumns[colIndex]?.id ?? null;
|
|
5
|
+
}
|
|
6
|
+
return {
|
|
7
|
+
get api() {
|
|
8
|
+
return ctx.buildApi();
|
|
9
|
+
},
|
|
10
|
+
editing,
|
|
11
|
+
get editor() {
|
|
12
|
+
const root = ctx.gridRootEl ?? null;
|
|
13
|
+
const el = root?.querySelector(".sv-grid-cell-editor") ?? null;
|
|
14
|
+
return el;
|
|
15
|
+
},
|
|
16
|
+
get activeCell() {
|
|
17
|
+
const active = ctx.grid.getState().activeCell;
|
|
18
|
+
if (!active)
|
|
19
|
+
return null;
|
|
20
|
+
return {
|
|
21
|
+
rowIndex: active.rowIndex,
|
|
22
|
+
colIndex: active.colIndex,
|
|
23
|
+
columnId: columnIdAt(active.colIndex),
|
|
24
|
+
};
|
|
25
|
+
},
|
|
26
|
+
get selectionFocus() {
|
|
27
|
+
const focus = ctx.selectionRange?.focus;
|
|
28
|
+
return focus ? { rowIndex: focus.rowIndex, colIndex: focus.colIndex } : null;
|
|
29
|
+
},
|
|
30
|
+
get rowCount() {
|
|
31
|
+
return ctx.allRows.length;
|
|
32
|
+
},
|
|
33
|
+
get colCount() {
|
|
34
|
+
return ctx.allColumns.length;
|
|
35
|
+
},
|
|
36
|
+
get ranges() {
|
|
37
|
+
// getSelectionRects() already normalises anchor/focus into rectangles
|
|
38
|
+
// and puts the active range last, which is the order a handler wants
|
|
39
|
+
// when it has to pick one.
|
|
40
|
+
return ctx.getSelectionRects().map((r) => [r.minRow, r.minCol, r.maxRow, r.maxCol]);
|
|
41
|
+
},
|
|
42
|
+
columnIdAt,
|
|
43
|
+
getCellValue(rowIndex, colIndex) {
|
|
44
|
+
const columnId = columnIdAt(colIndex);
|
|
45
|
+
return columnId == null ? undefined : ctx.readCellRaw(rowIndex, columnId);
|
|
46
|
+
},
|
|
47
|
+
setCellValue(rowIndex, colIndex, value) {
|
|
48
|
+
const columnId = columnIdAt(colIndex);
|
|
49
|
+
if (columnId == null)
|
|
50
|
+
return;
|
|
51
|
+
// Record the write so Ctrl+Z walks it back. `writeCellRaw` is the raw
|
|
52
|
+
// writer and deliberately keeps no history of its own - the fill handle
|
|
53
|
+
// and paste call it in loops and push their own entries (or, today, none
|
|
54
|
+
// at all). A command has to push here or every multi-cell command it
|
|
55
|
+
// runs would be silently un-undoable.
|
|
56
|
+
//
|
|
57
|
+
// Both reads happen BEFORE the write: writeCellRaw swaps a fresh row
|
|
58
|
+
// object into `internalData`, so afterwards the id lookup would miss.
|
|
59
|
+
const field = ctx.allColumns[colIndex]?.columnDef?.field;
|
|
60
|
+
const rowId = ctx.allRows[rowIndex]?.id;
|
|
61
|
+
const before = ctx.readCellRaw(rowIndex, columnId);
|
|
62
|
+
ctx.writeCellRaw(rowIndex, columnId, value);
|
|
63
|
+
// Only when something actually changed: writeCellRaw no-ops on an equal
|
|
64
|
+
// value, and a step whose before and after match would make Ctrl+Z look
|
|
65
|
+
// like it had swallowed a press.
|
|
66
|
+
if (field != null && rowId != null && before !== value) {
|
|
67
|
+
pushHistory(ctx, [{ rowId, columnId, field, before, after: value }]);
|
|
68
|
+
}
|
|
69
|
+
},
|
|
70
|
+
setActiveCell(rowIndex, colIndex) {
|
|
71
|
+
ctx.setActiveCell(rowIndex, colIndex);
|
|
72
|
+
},
|
|
73
|
+
setSelection(rowIndex, colIndex) {
|
|
74
|
+
ctx.setSelection(rowIndex, colIndex);
|
|
75
|
+
},
|
|
76
|
+
extendSelection(rowIndex, colIndex) {
|
|
77
|
+
ctx.extendSelection(rowIndex, colIndex);
|
|
78
|
+
},
|
|
79
|
+
scrollIntoView(rowIndex, colIndex) {
|
|
80
|
+
ctx.scrollActiveCellIntoView(rowIndex, colIndex);
|
|
81
|
+
},
|
|
82
|
+
startEditing(rowIndex, colIndex, seed) {
|
|
83
|
+
if (seed !== undefined) {
|
|
84
|
+
return ctx.startEditingWithChar(rowIndex, colIndex, seed) === true;
|
|
85
|
+
}
|
|
86
|
+
ctx.onCellDoubleClick(rowIndex, colIndex);
|
|
87
|
+
return true;
|
|
88
|
+
},
|
|
89
|
+
batch(fn) {
|
|
90
|
+
return runHistoryGroup(ctx, fn);
|
|
91
|
+
},
|
|
92
|
+
recordUndo(undo, redo) {
|
|
93
|
+
pushHistory(ctx, [
|
|
94
|
+
{ rowId: "", columnId: "", field: "", before: undefined, after: undefined, custom: { undo, redo } },
|
|
95
|
+
]);
|
|
96
|
+
},
|
|
97
|
+
focus() {
|
|
98
|
+
// preventScroll: the grid keeps its own scroll position, and a focus
|
|
99
|
+
// that yanked the viewport to the root's top edge would undo whatever
|
|
100
|
+
// scrollIntoView the command just asked for.
|
|
101
|
+
ctx.gridRootEl?.focus({ preventScroll: true });
|
|
102
|
+
},
|
|
103
|
+
async paste() {
|
|
104
|
+
await ctx.pasteFromClipboard?.();
|
|
105
|
+
},
|
|
106
|
+
copy() {
|
|
107
|
+
ctx.copySelectionToClipboard?.();
|
|
108
|
+
},
|
|
109
|
+
async cut() {
|
|
110
|
+
await ctx.cutSelectionToClipboard?.();
|
|
111
|
+
},
|
|
112
|
+
canEdit(rowIndex, colIndex) {
|
|
113
|
+
return ctx.isCellEditableAt?.(rowIndex, colIndex) ?? true;
|
|
114
|
+
},
|
|
115
|
+
};
|
|
116
|
+
}
|
package/dist/core.d.ts
CHANGED
|
@@ -348,6 +348,13 @@ export type ColumnDef<TFeatures extends TableFeatures, TData extends RowData> =
|
|
|
348
348
|
editorOptions?: EditorOptionSource | Promise<EditorOptionSource> | ((row: TData) => EditorOptionSource | Promise<EditorOptionSource>);
|
|
349
349
|
/** When true, list/chips allow multiple selections. Cell value becomes an array. */
|
|
350
350
|
editorMultiple?: boolean;
|
|
351
|
+
/**
|
|
352
|
+
* The text editor accepts line breaks: Alt+Enter inserts one and the
|
|
353
|
+
* editor grows a line per break, while Enter still commits. What a
|
|
354
|
+
* spreadsheet cell with wrapped text wants; `editorType: 'textarea'` is
|
|
355
|
+
* the other shape, where Enter itself is the line break.
|
|
356
|
+
*/
|
|
357
|
+
editorMultiline?: boolean;
|
|
351
358
|
/** Separator used when joining array values for the readonly cell display. Defaults to ', '. */
|
|
352
359
|
editorSeparator?: string;
|
|
353
360
|
format?: CellFormatConfig;
|
|
@@ -68,7 +68,7 @@ export declare function createPopoverSelect(config: PopoverSelectConfig): {
|
|
|
68
68
|
* exposes (mirrors `focusOwnerProps(role)`); defaults to 'listbox' for
|
|
69
69
|
* the classic select panels. */
|
|
70
70
|
triggerProps: (haspopup?: "listbox" | "tree" | "grid") => {
|
|
71
|
-
'aria-haspopup': "grid" | "
|
|
71
|
+
'aria-haspopup': "grid" | "tree" | "listbox";
|
|
72
72
|
'aria-expanded': boolean;
|
|
73
73
|
'aria-controls': string | undefined;
|
|
74
74
|
'aria-readonly': true | undefined;
|
|
@@ -77,7 +77,7 @@ export declare function createPopoverSelect(config: PopoverSelectConfig): {
|
|
|
77
77
|
/** Attributes for the element that OWNS focus + activedescendant (the panel,
|
|
78
78
|
* or a search input). Pass the ARIA role the panel should expose. */
|
|
79
79
|
focusOwnerProps: (role?: "listbox" | "tree" | "grid") => {
|
|
80
|
-
role: "grid" | "
|
|
80
|
+
role: "grid" | "tree" | "listbox";
|
|
81
81
|
'aria-activedescendant': string | undefined;
|
|
82
82
|
onkeydown: (e: KeyboardEvent) => void;
|
|
83
83
|
};
|
package/dist/editing.d.ts
CHANGED
|
@@ -1,12 +1,6 @@
|
|
|
1
1
|
import { type Column, type Row, type RowData, type TableFeatures } from "./index.js";
|
|
2
2
|
import "./sv-grid-scrollbar.js";
|
|
3
|
-
type HistoryStep
|
|
4
|
-
rowId: string;
|
|
5
|
-
columnId: string;
|
|
6
|
-
field: string;
|
|
7
|
-
before: unknown;
|
|
8
|
-
after: unknown;
|
|
9
|
-
};
|
|
3
|
+
import { type HistoryStep } from "./history.js";
|
|
10
4
|
export declare function createEditing<TFeatures extends TableFeatures = TableFeatures, TData extends RowData = RowData>(ctx: any): {
|
|
11
5
|
isCellEditable: (column: Column<TData>, row?: Row<TData>) => boolean;
|
|
12
6
|
isCellEditableAt: (rowIndex: number, colIndex: number) => boolean;
|
|
@@ -28,5 +22,5 @@ export declare function createEditing<TFeatures extends TableFeatures = TableFea
|
|
|
28
22
|
onCellDoubleClick: (rowIndex: number, colIndex: number) => void;
|
|
29
23
|
pasteFromClipboard: () => Promise<void>;
|
|
30
24
|
onGridPaste: (event: ClipboardEvent) => void;
|
|
25
|
+
armPasteFallback: () => void;
|
|
31
26
|
};
|
|
32
|
-
export {};
|