@svgrid/grid 2.6.22 → 2.7.0
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/CHANGELOG.md +88 -88
- package/README.md +199 -199
- package/dist/FlexRender.svelte +96 -96
- package/dist/GridFooter.svelte +181 -181
- package/dist/GridMenus.svelte +184 -6
- package/dist/SvAutoComplete.svelte +169 -165
- package/dist/SvAvatar.svelte +75 -75
- package/dist/SvCalendar.svelte +503 -503
- package/dist/SvCarousel.svelte +141 -141
- package/dist/SvCheckBox.svelte +102 -102
- package/dist/SvCircularProgress.svelte +109 -109
- package/dist/SvColorInput.svelte +181 -181
- package/dist/SvComboBox.svelte +279 -275
- package/dist/SvContextMenu.svelte +116 -116
- package/dist/SvCountryInput.svelte +163 -163
- package/dist/SvDateRangeInput.svelte +25 -3
- package/dist/SvDrawer.svelte +254 -254
- package/dist/SvDropDownList.svelte +378 -374
- package/dist/SvDurationInput.svelte +126 -126
- package/dist/SvField.svelte +293 -293
- package/dist/SvForm.svelte +437 -437
- package/dist/SvGrid.controller.svelte.d.ts +48 -1
- package/dist/SvGrid.controller.svelte.js +214 -52
- package/dist/SvGrid.css +221 -0
- package/dist/SvGrid.helpers.d.ts +55 -0
- package/dist/SvGrid.helpers.js +83 -0
- package/dist/SvGrid.svelte +145 -0
- package/dist/SvGrid.types.d.ts +105 -0
- package/dist/SvGridCellEditor.svelte +744 -662
- package/dist/SvGridChart.svelte +1716 -1716
- package/dist/SvGridChartPanel.svelte +485 -485
- package/dist/SvGridChartView.svelte +70 -70
- package/dist/SvGridDropdown.svelte +728 -728
- package/dist/SvGridSelect.svelte +270 -266
- package/dist/SvGridSelect.svelte.d.ts +1 -1
- package/dist/SvGroupCell.svelte +116 -116
- package/dist/SvListBox.svelte +334 -326
- package/dist/SvMaskedInput.svelte +122 -122
- package/dist/SvMenu.svelte +124 -124
- package/dist/SvMenuList.svelte +146 -146
- package/dist/SvMultiSelect.svelte +293 -289
- package/dist/SvMultiSelect.svelte.d.ts +1 -1
- package/dist/SvNumberInput.svelte +172 -168
- package/dist/SvOtpInput.svelte +158 -158
- package/dist/SvPasswordInput.svelte +151 -151
- package/dist/SvPhoneInput.svelte +133 -133
- package/dist/SvPopover.svelte +197 -197
- package/dist/SvProgress.svelte +116 -116
- package/dist/SvRadioGroup.svelte +107 -107
- package/dist/SvRating.svelte +112 -112
- package/dist/SvResult.svelte +73 -73
- package/dist/SvRichCell.svelte +125 -0
- package/dist/SvRichCell.svelte.d.ts +15 -0
- package/dist/SvRichText.svelte +211 -211
- package/dist/SvRowGroupPanel.svelte +170 -170
- package/dist/SvScrollArea.svelte +61 -61
- package/dist/SvSlider.svelte +203 -203
- package/dist/SvSwitchButton.svelte +108 -108
- package/dist/SvTagsInput.svelte +115 -115
- package/dist/SvTextArea.svelte +5 -1
- package/dist/SvTextInput.svelte +147 -147
- package/dist/SvTimePicker.svelte +245 -245
- package/dist/SvToaster.svelte +159 -159
- package/dist/SvToggleButton.svelte +85 -85
- package/dist/SvTooltip.svelte +161 -161
- package/dist/SvTour.svelte +208 -208
- package/dist/SvTree.svelte +444 -444
- package/dist/SvTreeSelect.svelte +239 -235
- package/dist/SvTreeSelect.svelte.d.ts +1 -1
- package/dist/builtin-editors.d.ts +2 -2
- package/dist/builtin-editors.js +19 -3
- package/dist/cdn/GridMenus-C4oLsJyj.js +600 -0
- package/dist/cdn/GridMenus-yEivjNwl.js +601 -0
- package/dist/cdn/SvDateRangeInput-Bh0A0JkF.js +199 -0
- package/dist/cdn/SvDateRangeInput-DflbiP7N.js +198 -0
- package/dist/cdn/SvDateTimePicker-BWwpfB_o.js +812 -0
- package/dist/cdn/SvDateTimePicker-Bivn8dAP.js +816 -0
- package/dist/cdn/SvGridCellEditor-AXL8cHGO.js +550 -0
- package/dist/cdn/SvGridCellEditor-Ba7rY3eu.js +549 -0
- package/dist/cdn/{SvGridChart-BwVos976.js → SvGridChart-Bs2GIR2Q.js} +1 -1
- package/dist/cdn/{SvGridChart-BEJmNNx9.js → SvGridChart-CwhFz7GV.js} +1 -1
- package/dist/cdn/{SvGridChartPanel-BOknOkrP.js → SvGridChartPanel-1WXuStzM.js} +1 -1
- package/dist/cdn/{SvGridChartPanel-D2PjII4O.js → SvGridChartPanel-e5_nqNP9.js} +1 -1
- package/dist/cdn/{SvGridChartView-00LPUHL1.js → SvGridChartView-SmPW10dI.js} +1 -1
- package/dist/cdn/{SvGridChartView-BhUEJ5ki.js → SvGridChartView-eSPuJE6g.js} +1 -1
- package/dist/cdn/{SvGridDropdown-D0VdjeR8.js → SvGridDropdown-B1ZcLpgs.js} +1 -1
- package/dist/cdn/{SvGridDropdown-D13MtJ2j.js → SvGridDropdown-CtdbHcIS.js} +1 -1
- package/dist/cdn/date-format-CcP1tafP.js +1395 -0
- package/dist/cdn/date-format-DZT7T1wf.js +1393 -0
- package/dist/cdn/{editor-registry-CiI0xlKg.js → editor-registry-BhgE3S84.js} +51 -25
- package/dist/cdn/{src-C9Hihx1W.js → src-COC0vnpg.js} +7233 -6701
- package/dist/cdn/{src-D1lXwq1l.js → src-pYGV2rMR.js} +5747 -5215
- package/dist/cdn/svgrid.js +15 -13
- package/dist/cdn/svgrid.svelte-external.js +15 -13
- package/dist/cell-values.d.ts +16 -0
- package/dist/cell-values.js +28 -0
- package/dist/chart-export.js +8 -8
- package/dist/clipboard.d.ts +22 -0
- package/dist/clipboard.js +405 -27
- package/dist/editing.js +12 -7
- package/dist/editors/cell-editors.d.ts +11 -0
- package/dist/editors/cell-editors.js +18 -1
- package/dist/grid-messages.d.ts +15 -0
- package/dist/grid-messages.js +15 -0
- package/dist/index.d.ts +4 -0
- package/dist/index.js +4 -0
- package/dist/list-option.d.ts +6 -0
- package/dist/menus.js +40 -7
- package/dist/sanitize-html.d.ts +37 -0
- package/dist/sanitize-html.js +234 -0
- package/dist/selection-bar-view.svelte.d.ts +25 -0
- package/dist/selection-bar-view.svelte.js +13 -0
- package/dist/selection.d.ts +2 -1
- package/dist/selection.js +129 -13
- package/package.json +11 -11
- package/src/FlexRender.svelte +96 -96
- package/src/GridFooter.svelte +181 -181
- package/src/GridMenus.svelte +184 -6
- package/src/SvAutoComplete.svelte +169 -165
- package/src/SvAvatar.svelte +75 -75
- package/src/SvCalendar.svelte +503 -503
- package/src/SvCalendar.test.ts +226 -226
- package/src/SvCarousel.svelte +141 -141
- package/src/SvCheckBox.svelte +102 -102
- package/src/SvCircularProgress.svelte +109 -109
- package/src/SvColorInput.svelte +181 -181
- package/src/SvComboBox.svelte +279 -275
- package/src/SvContextMenu.svelte +116 -116
- package/src/SvCountryInput.svelte +163 -163
- package/src/SvDateRangeInput.svelte +25 -3
- package/src/SvDrawer.svelte +254 -254
- package/src/SvDropDownList.svelte +378 -374
- package/src/SvDurationInput.svelte +126 -126
- package/src/SvField.svelte +293 -293
- package/src/SvForm.svelte +437 -437
- package/src/SvForm.test.ts +411 -411
- package/src/SvGrid.controller.svelte.ts +251 -61
- package/src/SvGrid.css +221 -0
- package/src/SvGrid.helpers.ts +87 -0
- package/src/SvGrid.svelte +145 -0
- package/src/SvGrid.types.ts +2092 -1980
- package/src/SvGridCellEditor.svelte +744 -662
- package/src/SvGridChart.svelte +1716 -1716
- package/src/SvGridChartPanel.svelte +485 -485
- package/src/SvGridChartView.svelte +70 -70
- package/src/SvGridDropdown.svelte +728 -728
- package/src/SvGridSelect.svelte +270 -266
- package/src/SvGroupCell.svelte +116 -116
- package/src/SvListBox.svelte +334 -326
- package/src/SvMaskedInput.svelte +122 -122
- package/src/SvMenu.svelte +124 -124
- package/src/SvMenu.test.ts +97 -97
- package/src/SvMenuList.svelte +146 -146
- package/src/SvMultiSelect.svelte +293 -289
- package/src/SvNumberInput.svelte +172 -168
- package/src/SvOtpInput.svelte +158 -158
- package/src/SvPasswordInput.svelte +151 -151
- package/src/SvPhoneInput.svelte +133 -133
- package/src/SvPopover.svelte +197 -197
- package/src/SvProgress.svelte +116 -116
- package/src/SvRadioGroup.svelte +107 -107
- package/src/SvRating.svelte +112 -112
- package/src/SvResult.svelte +73 -73
- package/src/SvRichCell.svelte +125 -0
- package/src/SvRichText.svelte +211 -211
- package/src/SvRowGroupPanel.svelte +170 -170
- package/src/SvScrollArea.svelte +61 -61
- package/src/SvSlider.svelte +203 -203
- package/src/SvSwitchButton.svelte +108 -108
- package/src/SvTagsInput.svelte +115 -115
- package/src/SvTextArea.svelte +5 -1
- package/src/SvTextInput.svelte +147 -147
- package/src/SvTimePicker.svelte +245 -245
- package/src/SvToaster.svelte +159 -159
- package/src/SvToaster.test.ts +95 -95
- package/src/SvToggleButton.svelte +85 -85
- package/src/SvTooltip.svelte +161 -161
- package/src/SvTour.svelte +208 -208
- package/src/SvTree.svelte +444 -444
- package/src/SvTreeSelect.svelte +239 -235
- package/src/a11y/dismissable.test.ts +119 -119
- package/src/a11y/dismissable.ts +114 -114
- package/src/a11y.contract.test.ts +49 -49
- package/src/a11y.test.ts +59 -59
- package/src/a11y.ts +61 -61
- package/src/ai.test.ts +502 -502
- package/src/ai.ts +1419 -1419
- package/src/build-api.coverage.test.ts +633 -633
- package/src/build-api.ts +846 -846
- package/src/builtin-editors.grid.test.ts +83 -83
- package/src/builtin-editors.test.ts +18 -1
- package/src/builtin-editors.ts +19 -3
- package/src/cell-formatting.ts +171 -171
- package/src/cell-render.test.ts +513 -513
- package/src/cell-render.ts +496 -496
- package/src/cell-values.ts +148 -118
- package/src/chart-export.ts +202 -202
- package/src/chart-view.svelte.ts +36 -36
- package/src/chart.ts +2321 -2321
- package/src/clipboard.test.ts +93 -20
- package/src/clipboard.ts +433 -33
- package/src/collaboration.test.ts +104 -104
- package/src/collaboration.ts +167 -167
- package/src/column-groups.ts +78 -78
- package/src/core.performance.test.ts +30 -30
- package/src/core.ts +1865 -1865
- package/src/createAutocomplete.svelte.ts +132 -132
- package/src/createCombobox.svelte.ts +191 -191
- package/src/createCountryInput.svelte.ts +157 -157
- package/src/createDropdownList.svelte.ts +168 -168
- package/src/createForm.svelte.ts +386 -386
- package/src/createGrid.svelte.ts +42 -42
- package/src/createGrid.test.ts +10 -10
- package/src/createGridState.svelte.ts +17 -17
- package/src/createListbox.svelte.ts +250 -250
- package/src/createMenu.svelte.ts +224 -224
- package/src/createPopoverSelect.svelte.ts +213 -213
- package/src/createSlider.svelte.ts +191 -191
- package/src/createTooltip.svelte.ts +144 -144
- package/src/createTree.svelte.ts +322 -322
- package/src/date-string-column.test.ts +87 -0
- package/src/datetime/date-core.ts +206 -206
- package/src/datetime/date-restrict.ts +61 -61
- package/src/datetime/timezone.ts +135 -135
- package/src/dock-manager-model.ts +596 -596
- package/src/dock-model.ts +374 -374
- package/src/editing.test.ts +974 -949
- package/src/editing.ts +609 -606
- package/src/editor-block-prop.test.ts +132 -0
- package/src/editor-contract.ts +171 -171
- package/src/editor-registry.grid.test.ts +144 -144
- package/src/editor-registry.ts +122 -122
- package/src/editors/cell-editors.ts +27 -1
- package/src/export-data-api.test.ts +126 -126
- package/src/export-format.test.ts +107 -107
- package/src/export-format.ts +601 -601
- package/src/filter-operators.ts +160 -160
- package/src/filtering/excel-filters.ts +325 -325
- package/src/flex-render.ts +3 -3
- package/src/form-field.ts +127 -127
- package/src/grid-messages.ts +34 -0
- package/src/group-display.test.ts +167 -167
- package/src/group-display.ts +200 -200
- package/src/headless.ts +87 -87
- package/src/index.ts +13 -0
- package/src/js-scroller.svelte.ts +173 -173
- package/src/keyboard-handlers.ts +270 -270
- package/src/keyboard.test.ts +59 -59
- package/src/keyboard.ts +97 -97
- package/src/list-nav.test.ts +49 -49
- package/src/list-nav.ts +29 -29
- package/src/list-option.test.ts +56 -56
- package/src/list-option.ts +179 -173
- package/src/menus.test.ts +43 -0
- package/src/menus.ts +597 -567
- package/src/merge-objects.ts +48 -48
- package/src/move-cells.test.ts +850 -0
- package/src/number-editor-literal.test.ts +84 -0
- package/src/number-editor.grid.test.ts +160 -0
- package/src/overlays.test.ts +90 -90
- package/src/positioning.ts +268 -268
- package/src/render-component.ts +28 -28
- package/src/row-drag-touch.ts +211 -211
- package/src/row-drag.test.ts +353 -353
- package/src/row-drag.ts +415 -415
- package/src/row-resize.test.ts +524 -524
- package/src/row-resize.ts +228 -228
- package/src/sanitize-html.test.ts +182 -0
- package/src/sanitize-html.ts +235 -0
- package/src/scheduler-ical.ts +181 -181
- package/src/scheduler-model.test.ts +562 -562
- package/src/scheduler-model.ts +873 -873
- package/src/selection-bar-view.svelte.ts +36 -0
- package/src/selection.test.ts +900 -743
- package/src/selection.ts +131 -13
- package/src/server-data-source.test.ts +383 -383
- package/src/server-data-source.ts +469 -469
- package/src/sparkline.test.ts +68 -68
- package/src/sparkline.ts +169 -169
- package/src/spreadsheet.test.ts +488 -488
- package/src/spreadsheet.ts +312 -312
- package/src/static-functions.ts +11 -11
- package/src/subscribe.ts +38 -38
- package/src/summaries.ts +113 -113
- package/src/svgrid-wrapper.types.ts +563 -563
- package/src/svgrid.async-editor-options.test.ts +273 -273
- package/src/svgrid.auto-row-height.test.ts +204 -204
- package/src/svgrid.behavior.test.ts +910 -910
- package/src/svgrid.charting.test.ts +534 -534
- package/src/svgrid.comments-autocomplete.test.ts +127 -127
- package/src/svgrid.context-menu.test.ts +147 -147
- package/src/svgrid.features.test.ts +157 -157
- package/src/svgrid.filter-depth.test.ts +163 -163
- package/src/svgrid.filter-menu-listbox.svelte.test.ts +377 -331
- package/src/svgrid.filter-menu-scroll.test.ts +112 -112
- package/src/svgrid.grand-total.test.ts +188 -188
- package/src/svgrid.group-display-mode.test.ts +171 -171
- package/src/svgrid.group-footers.test.ts +121 -121
- package/src/svgrid.group-pagination.test.ts +153 -153
- package/src/svgrid.in-suggest-snapshot.svelte.test.ts +91 -0
- package/src/svgrid.menu-scroll-close.test.ts +204 -0
- package/src/svgrid.new-features.wrapper.test.ts +251 -251
- package/src/svgrid.selection-bar-seam.test.ts +185 -0
- package/src/svgrid.tree-data.test.ts +186 -186
- package/src/svgrid.upsell-license.test.ts +117 -0
- package/src/svgrid.wrapper.test.ts +63 -63
- package/src/svgriddropdown.async-panel.svelte.test.ts +195 -195
- package/src/test-setup.ts +62 -62
- package/src/themes/index.ts +288 -288
- package/src/toast-store.svelte.ts +250 -250
- package/src/toast-store.test.ts +147 -147
- package/src/tree-row-model.test.ts +168 -168
- package/src/ui-buttons.test.ts +144 -144
- package/src/ui-inputs.test.ts +118 -118
- package/src/ui-localization.test.ts +113 -113
- package/src/ui-range.test.ts +70 -70
- package/src/ui-selection.test.ts +155 -155
- package/src/ui-tier1.test.ts +142 -142
- package/src/virtual.test.ts +88 -88
- 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 +322 -322
- package/dist/cdn/GridMenus-BuoBPqxx.js +0 -493
- package/dist/cdn/GridMenus-n4llxoOI.js +0 -494
- package/dist/cdn/SvDateTimePicker-CHnUkWcH.js +0 -2206
- package/dist/cdn/SvDateTimePicker-CRQH_U7E.js +0 -2201
- package/dist/cdn/SvGridCellEditor-BGUCzuPB.js +0 -523
- package/dist/cdn/SvGridCellEditor-G8IMWIws.js +0 -522
package/dist/selection.js
CHANGED
|
@@ -224,15 +224,21 @@ export function createSelection(ctx) {
|
|
|
224
224
|
* that contains the cell are returned (active range checked last so its
|
|
225
225
|
* outline wins on overlap). Returns null when the cell is in no range.
|
|
226
226
|
*/
|
|
227
|
+
/** Could `getSelectionRects()` return anything? An anchored active range or
|
|
228
|
+
* a committed one is the only way a rect can exist, and both are plain
|
|
229
|
+
* property reads - so this is the cheap guard in front of anything that
|
|
230
|
+
* would otherwise allocate a rect array to discover there is nothing. */
|
|
231
|
+
function hasAnySelectionRect() {
|
|
232
|
+
const active = ctx.selectionRange;
|
|
233
|
+
const committed = ctx.selectionRanges;
|
|
234
|
+
return Boolean(committed?.length) || Boolean(active?.anchor && active?.focus);
|
|
235
|
+
}
|
|
227
236
|
function getCellRangeEdges(rowIndex, colIndex) {
|
|
228
237
|
// Bail before `getSelectionRects()`, which allocates an array and resolves
|
|
229
238
|
// every range. This runs once per rendered CELL on every render - about 250
|
|
230
239
|
// times per frame on a default grid - and with nothing selected it did all
|
|
231
|
-
// that work to return null every time.
|
|
232
|
-
|
|
233
|
-
const active = ctx.selectionRange;
|
|
234
|
-
const committed = ctx.selectionRanges;
|
|
235
|
-
if (!committed?.length && !(active?.anchor && active?.focus))
|
|
240
|
+
// that work to return null every time.
|
|
241
|
+
if (!hasAnySelectionRect())
|
|
236
242
|
return null;
|
|
237
243
|
for (const rect of getSelectionRects()) {
|
|
238
244
|
if (rowIndex < rect.minRow ||
|
|
@@ -250,10 +256,40 @@ export function createSelection(ctx) {
|
|
|
250
256
|
}
|
|
251
257
|
return null;
|
|
252
258
|
}
|
|
259
|
+
/**
|
|
260
|
+
* The rectangle a drag is currently promising, or null when no drag is in
|
|
261
|
+
* flight. A fill grows the source rectangle out to the pointer; a move
|
|
262
|
+
* detaches an identically-sized rectangle and drops it at the offset the
|
|
263
|
+
* pointer has travelled. Both feed the same preview tint and marquee, so a
|
|
264
|
+
* range move looks like the fill handle users already know.
|
|
265
|
+
*/
|
|
266
|
+
function dragPreviewRect() {
|
|
267
|
+
const m = ctx.moveDrag;
|
|
268
|
+
if (m)
|
|
269
|
+
return ctx.moveDestRect(m);
|
|
270
|
+
const d = ctx.fillDrag;
|
|
271
|
+
if (!d)
|
|
272
|
+
return null;
|
|
273
|
+
return {
|
|
274
|
+
minRow: Math.min(d.sourceMinRow, d.targetRow),
|
|
275
|
+
maxRow: Math.max(d.sourceMaxRow, d.targetRow),
|
|
276
|
+
minCol: Math.min(d.sourceMinCol, d.targetCol),
|
|
277
|
+
maxCol: Math.max(d.sourceMaxCol, d.targetCol),
|
|
278
|
+
};
|
|
279
|
+
}
|
|
253
280
|
/** Returns true when the given cell is inside the fill-drag preview
|
|
254
281
|
* range BUT outside the original source range. Used to paint a
|
|
255
282
|
* dashed-outline preview while the user is dragging the handle. */
|
|
256
283
|
function isInFillPreview(rowIndex, colIndex) {
|
|
284
|
+
if (ctx.moveDrag) {
|
|
285
|
+
const rect = dragPreviewRect();
|
|
286
|
+
if (!rect)
|
|
287
|
+
return false;
|
|
288
|
+
return (rowIndex >= rect.minRow &&
|
|
289
|
+
rowIndex <= rect.maxRow &&
|
|
290
|
+
colIndex >= rect.minCol &&
|
|
291
|
+
colIndex <= rect.maxCol);
|
|
292
|
+
}
|
|
257
293
|
const d = ctx.fillDrag;
|
|
258
294
|
if (!d)
|
|
259
295
|
return false;
|
|
@@ -279,13 +315,14 @@ export function createSelection(ctx) {
|
|
|
279
315
|
* border. Returns null when the cell isn't on the rectangle's boundary.
|
|
280
316
|
*/
|
|
281
317
|
function fillMarqueeEdges(rowIndex, colIndex) {
|
|
282
|
-
|
|
283
|
-
|
|
318
|
+
// Cheap bail before the shared rect helper, which allocates: this runs
|
|
319
|
+
// once per rendered cell and no drag is in flight almost all the time.
|
|
320
|
+
if (!ctx.fillDrag && !ctx.moveDrag)
|
|
284
321
|
return null;
|
|
285
|
-
const
|
|
286
|
-
|
|
287
|
-
|
|
288
|
-
const maxC =
|
|
322
|
+
const rect = dragPreviewRect();
|
|
323
|
+
if (!rect)
|
|
324
|
+
return null;
|
|
325
|
+
const { minRow: minR, maxRow: maxR, minCol: minC, maxCol: maxC } = rect;
|
|
289
326
|
if (rowIndex < minR || rowIndex > maxR || colIndex < minC || colIndex > maxC) {
|
|
290
327
|
return null;
|
|
291
328
|
}
|
|
@@ -309,6 +346,18 @@ export function createSelection(ctx) {
|
|
|
309
346
|
const column = ctx.allColumns[colIndex];
|
|
310
347
|
if (!row || !column || isGroupRow(row))
|
|
311
348
|
return;
|
|
349
|
+
// A pointerdown on the outer few pixels of a selection border grabs the
|
|
350
|
+
// range to move it. Checked before anything else, because everything below
|
|
351
|
+
// would first collapse the selection this drag is about to relocate.
|
|
352
|
+
// Returns false unless the pointer really was on the strip, so a click
|
|
353
|
+
// anywhere further inside falls straight through to the old behaviour.
|
|
354
|
+
if (ctx.startMoveDrag(event, rowIndex, colIndex)) {
|
|
355
|
+
// A grab that never moves still ends in a `click` on the cell under the
|
|
356
|
+
// border. Left alone that click would collapse the range the user was
|
|
357
|
+
// clearly reaching for, and on a checkbox column it would flip the value.
|
|
358
|
+
moveGrabSwallowsClick = true;
|
|
359
|
+
return;
|
|
360
|
+
}
|
|
312
361
|
// NOTE: we no longer bail for checkbox columns. Bailing here meant a
|
|
313
362
|
// range drag could never START on a checkbox cell. A plain click still
|
|
314
363
|
// toggles the checkbox via onCellClick (a same-cell click), while a
|
|
@@ -344,27 +393,93 @@ export function createSelection(ctx) {
|
|
|
344
393
|
extendSelection(rowIndex, colIndex);
|
|
345
394
|
setActiveCell(rowIndex, colIndex);
|
|
346
395
|
}
|
|
347
|
-
|
|
396
|
+
/** `event` is the window `pointerup` when this comes from the real gesture,
|
|
397
|
+
* and absent when `onWindowPointerMove` calls it to recover from a release
|
|
398
|
+
* it never saw. A range move reads its copy modifier from it, so holding
|
|
399
|
+
* Ctrl between the last movement and the release still copies. */
|
|
400
|
+
function endDragSelection(event) {
|
|
348
401
|
ctx.isDraggingSelection = false;
|
|
402
|
+
// Every drag shares one edge-scroll loop, and it exits on its own once no
|
|
403
|
+
// drag is live - but stopping it here cancels the pending frame rather
|
|
404
|
+
// than letting one more fire after the gesture is over.
|
|
405
|
+
ctx.stopEdgeScroll();
|
|
349
406
|
// Also commit a fill-handle drag if one was in progress - the user
|
|
350
407
|
// released the mouse, time to apply the pattern.
|
|
351
408
|
if (ctx.fillDrag)
|
|
352
409
|
ctx.onFillPointerUp();
|
|
410
|
+
if (ctx.moveDrag)
|
|
411
|
+
ctx.onMovePointerUp(event);
|
|
353
412
|
}
|
|
354
413
|
function onWindowPointerMove(event) {
|
|
414
|
+
if (ctx.moveDrag) {
|
|
415
|
+
ctx.onMovePointerMove(event);
|
|
416
|
+
return;
|
|
417
|
+
}
|
|
355
418
|
if (ctx.fillDrag) {
|
|
356
419
|
ctx.onFillPointerMove(event);
|
|
357
420
|
return;
|
|
358
421
|
}
|
|
359
|
-
if (!ctx.isDraggingSelection)
|
|
422
|
+
if (!ctx.isDraggingSelection) {
|
|
423
|
+
updateMoveGrabHover(event);
|
|
360
424
|
return;
|
|
425
|
+
}
|
|
361
426
|
// Safety: if no mouse button is held the drag is over (we may have
|
|
362
427
|
// missed pointerup because the user lifted outside the window).
|
|
363
428
|
if (event.buttons === 0) {
|
|
364
429
|
endDragSelection();
|
|
430
|
+
return;
|
|
365
431
|
}
|
|
432
|
+
// Drag-select past the viewport edge scrolls the grid, same as the fill
|
|
433
|
+
// and move drags. Without it a range can only ever cover what was already
|
|
434
|
+
// on screen when the drag started. `onCellPointerEnter` keeps extending
|
|
435
|
+
// the range for cells the pointer actually crosses; this covers the case
|
|
436
|
+
// where the pointer has stopped at the edge and the CELLS are moving.
|
|
437
|
+
ctx.trackEdgeScroll(event);
|
|
366
438
|
}
|
|
439
|
+
/**
|
|
440
|
+
* Switch the grid to a move cursor while the pointer sits on the grab strip
|
|
441
|
+
* of a selection border - without it the feature is invisible, since the
|
|
442
|
+
* border is painted, not a hit target.
|
|
443
|
+
*
|
|
444
|
+
* This runs on every window pointermove, so the order of the guards is the
|
|
445
|
+
* point: `moveCellsEffective` and the already-hovering flag are plain
|
|
446
|
+
* property reads, and `isOnMoveGrabStrip` bails on `getCellRangeEdges`
|
|
447
|
+
* before measuring anything when no range is selected.
|
|
448
|
+
*/
|
|
449
|
+
function updateMoveGrabHover(event) {
|
|
450
|
+
const wasHovering = ctx.moveGrabHover;
|
|
451
|
+
// Two property reads before anything touches the DOM. `closest()` walks
|
|
452
|
+
// ancestors on EVERY pointer move over the page, so it has to sit behind
|
|
453
|
+
// both "the feature is on" and "there is a range to grab".
|
|
454
|
+
if (!ctx.moveCellsEffective || !hasAnySelectionRect()) {
|
|
455
|
+
if (wasHovering)
|
|
456
|
+
ctx.moveGrabHover = false;
|
|
457
|
+
return;
|
|
458
|
+
}
|
|
459
|
+
const target = event.target;
|
|
460
|
+
const cell = target?.closest?.("td[data-svgrid-row][data-svgrid-col]");
|
|
461
|
+
let hovering = false;
|
|
462
|
+
if (cell) {
|
|
463
|
+
const r = Number(cell.dataset.svgridRow);
|
|
464
|
+
const c = Number(cell.dataset.svgridCol);
|
|
465
|
+
if (Number.isFinite(r) && Number.isFinite(c)) {
|
|
466
|
+
hovering = ctx.isOnMoveGrabStrip(cell, r, c, event.clientX, event.clientY);
|
|
467
|
+
}
|
|
468
|
+
}
|
|
469
|
+
if (hovering !== wasHovering)
|
|
470
|
+
ctx.moveGrabHover = hovering;
|
|
471
|
+
}
|
|
472
|
+
/** Set when a pointerdown started a range move, so the `click` that
|
|
473
|
+
* follows a zero-distance grab is discarded instead of collapsing the
|
|
474
|
+
* selection it grabbed. One gesture, one flag - cleared on the next click
|
|
475
|
+
* whether or not the grab turned into a real drag. */
|
|
476
|
+
let moveGrabSwallowsClick = false;
|
|
367
477
|
function onCellClick(rowIndex, colIndex) {
|
|
478
|
+
if (moveGrabSwallowsClick) {
|
|
479
|
+
moveGrabSwallowsClick = false;
|
|
480
|
+
ctx.gridRootEl?.focus({ preventScroll: true });
|
|
481
|
+
return;
|
|
482
|
+
}
|
|
368
483
|
const row = ctx.allRows[rowIndex];
|
|
369
484
|
const column = ctx.allColumns[colIndex];
|
|
370
485
|
if (!row || !column)
|
|
@@ -450,6 +565,7 @@ export function createSelection(ctx) {
|
|
|
450
565
|
fillMarqueeEdges,
|
|
451
566
|
getSelectionRects,
|
|
452
567
|
isInFillPreview,
|
|
568
|
+
dragPreviewRect,
|
|
453
569
|
findColumnById,
|
|
454
570
|
onCellPointerDown,
|
|
455
571
|
onCellPointerEnter,
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@svgrid/grid",
|
|
3
|
-
"version": "2.
|
|
3
|
+
"version": "2.7.0",
|
|
4
4
|
"description": "Svelte 5-native data grid and data table. Headless-first engine with virtual scrolling for 100k+ rows, Excel-style filtering, inline editing, grouping, tree data, pivot, and server-side data. Drop-in <SvGrid> component. TypeScript, SSR-ready.",
|
|
5
5
|
"author": "jQWidgets <boikom@jqwidgets.com>",
|
|
6
6
|
"license": "MIT",
|
|
@@ -116,15 +116,6 @@
|
|
|
116
116
|
"themes",
|
|
117
117
|
"CHANGELOG.md"
|
|
118
118
|
],
|
|
119
|
-
"scripts": {
|
|
120
|
-
"clean": "rimraf ./build && rimraf ./dist",
|
|
121
|
-
"test:eslint": "eslint ./src",
|
|
122
|
-
"test:types": "svelte-check --tsconfig ./tsconfig.json",
|
|
123
|
-
"test:lib": "vitest run --coverage",
|
|
124
|
-
"test:build": "publint --strict",
|
|
125
|
-
"build": "svelte-package --input ./src --output ./dist && node ../../tools/strip-dist-tests.mjs ./dist && node ../../tools/add-dist-extensions.mjs ./dist && node ./scripts/build-cdn.mjs && node ./scripts/build-themes.mjs",
|
|
126
|
-
"lint": "eslint ./src"
|
|
127
|
-
},
|
|
128
119
|
"devDependencies": {
|
|
129
120
|
"@sveltejs/package": "^2.5.7",
|
|
130
121
|
"@sveltejs/vite-plugin-svelte": "^7.0.0",
|
|
@@ -141,5 +132,14 @@
|
|
|
141
132
|
},
|
|
142
133
|
"dependencies": {
|
|
143
134
|
"esm-env": "^1.2.2"
|
|
135
|
+
},
|
|
136
|
+
"scripts": {
|
|
137
|
+
"clean": "rimraf ./build && rimraf ./dist",
|
|
138
|
+
"test:eslint": "eslint ./src",
|
|
139
|
+
"test:types": "svelte-check --tsconfig ./tsconfig.json",
|
|
140
|
+
"test:lib": "vitest run --coverage",
|
|
141
|
+
"test:build": "publint --strict",
|
|
142
|
+
"build": "svelte-package --input ./src --output ./dist && node ../../tools/strip-dist-tests.mjs ./dist && node ../../tools/add-dist-extensions.mjs ./dist && node ./scripts/build-cdn.mjs && node ./scripts/build-themes.mjs",
|
|
143
|
+
"lint": "eslint ./src"
|
|
144
144
|
}
|
|
145
|
-
}
|
|
145
|
+
}
|
package/src/FlexRender.svelte
CHANGED
|
@@ -1,96 +1,96 @@
|
|
|
1
|
-
<script
|
|
2
|
-
lang="ts"
|
|
3
|
-
generics="TData extends RowData"
|
|
4
|
-
>
|
|
5
|
-
import { isFunction } from './core'
|
|
6
|
-
import {
|
|
7
|
-
RenderComponentConfig,
|
|
8
|
-
RenderSnippetConfig,
|
|
9
|
-
} from './render-component'
|
|
10
|
-
import type {
|
|
11
|
-
Cell,
|
|
12
|
-
CellContext,
|
|
13
|
-
ColumnDefTemplate,
|
|
14
|
-
Header,
|
|
15
|
-
HeaderContext,
|
|
16
|
-
RowData,
|
|
17
|
-
} from './core'
|
|
18
|
-
|
|
19
|
-
type Props =
|
|
20
|
-
| {
|
|
21
|
-
content?: ColumnDefTemplate<
|
|
22
|
-
| HeaderContext<TData>
|
|
23
|
-
| CellContext<TData>
|
|
24
|
-
>
|
|
25
|
-
context:
|
|
26
|
-
| HeaderContext<TData>
|
|
27
|
-
| CellContext<TData>
|
|
28
|
-
cell?: never
|
|
29
|
-
header?: never
|
|
30
|
-
footer?: never
|
|
31
|
-
}
|
|
32
|
-
| {
|
|
33
|
-
cell: Cell<TData>
|
|
34
|
-
content?: never
|
|
35
|
-
context?: never
|
|
36
|
-
header?: never
|
|
37
|
-
footer?: never
|
|
38
|
-
}
|
|
39
|
-
| {
|
|
40
|
-
header: Header<TData>
|
|
41
|
-
content?: never
|
|
42
|
-
context?: never
|
|
43
|
-
cell?: never
|
|
44
|
-
footer?: never
|
|
45
|
-
}
|
|
46
|
-
| {
|
|
47
|
-
footer: Header<TData>
|
|
48
|
-
content?: never
|
|
49
|
-
context?: never
|
|
50
|
-
cell?: never
|
|
51
|
-
header?: never
|
|
52
|
-
}
|
|
53
|
-
|
|
54
|
-
let props: Props = $props()
|
|
55
|
-
|
|
56
|
-
const resolved = $derived.by(() => {
|
|
57
|
-
if ('cell' in props && props.cell) {
|
|
58
|
-
return {
|
|
59
|
-
content: props.cell.column.columnDef.cell,
|
|
60
|
-
context: props.cell.getContext(),
|
|
61
|
-
}
|
|
62
|
-
}
|
|
63
|
-
if ('header' in props && props.header) {
|
|
64
|
-
return {
|
|
65
|
-
content: props.header.column.columnDef.header,
|
|
66
|
-
context: props.header.getContext(),
|
|
67
|
-
}
|
|
68
|
-
}
|
|
69
|
-
if ('footer' in props && props.footer) {
|
|
70
|
-
return {
|
|
71
|
-
content: props.footer.column.columnDef.footer,
|
|
72
|
-
context: props.footer.getContext(),
|
|
73
|
-
}
|
|
74
|
-
}
|
|
75
|
-
return {
|
|
76
|
-
content: props.content,
|
|
77
|
-
context: props.context,
|
|
78
|
-
}
|
|
79
|
-
})
|
|
80
|
-
|
|
81
|
-
const result = $derived(
|
|
82
|
-
isFunction(resolved.content)
|
|
83
|
-
? resolved.content(resolved.context as any)
|
|
84
|
-
: undefined,
|
|
85
|
-
)
|
|
86
|
-
</script>
|
|
87
|
-
|
|
88
|
-
{#if typeof resolved.content === 'string'}
|
|
89
|
-
{resolved.content}
|
|
90
|
-
{:else if result instanceof RenderComponentConfig}
|
|
91
|
-
<result.component {...result.props} />
|
|
92
|
-
{:else if result instanceof RenderSnippetConfig}
|
|
93
|
-
{@render result.snippet(result.params)}
|
|
94
|
-
{:else if result !== undefined}
|
|
95
|
-
{result}
|
|
96
|
-
{/if}
|
|
1
|
+
<script
|
|
2
|
+
lang="ts"
|
|
3
|
+
generics="TData extends RowData"
|
|
4
|
+
>
|
|
5
|
+
import { isFunction } from './core'
|
|
6
|
+
import {
|
|
7
|
+
RenderComponentConfig,
|
|
8
|
+
RenderSnippetConfig,
|
|
9
|
+
} from './render-component'
|
|
10
|
+
import type {
|
|
11
|
+
Cell,
|
|
12
|
+
CellContext,
|
|
13
|
+
ColumnDefTemplate,
|
|
14
|
+
Header,
|
|
15
|
+
HeaderContext,
|
|
16
|
+
RowData,
|
|
17
|
+
} from './core'
|
|
18
|
+
|
|
19
|
+
type Props =
|
|
20
|
+
| {
|
|
21
|
+
content?: ColumnDefTemplate<
|
|
22
|
+
| HeaderContext<TData>
|
|
23
|
+
| CellContext<TData>
|
|
24
|
+
>
|
|
25
|
+
context:
|
|
26
|
+
| HeaderContext<TData>
|
|
27
|
+
| CellContext<TData>
|
|
28
|
+
cell?: never
|
|
29
|
+
header?: never
|
|
30
|
+
footer?: never
|
|
31
|
+
}
|
|
32
|
+
| {
|
|
33
|
+
cell: Cell<TData>
|
|
34
|
+
content?: never
|
|
35
|
+
context?: never
|
|
36
|
+
header?: never
|
|
37
|
+
footer?: never
|
|
38
|
+
}
|
|
39
|
+
| {
|
|
40
|
+
header: Header<TData>
|
|
41
|
+
content?: never
|
|
42
|
+
context?: never
|
|
43
|
+
cell?: never
|
|
44
|
+
footer?: never
|
|
45
|
+
}
|
|
46
|
+
| {
|
|
47
|
+
footer: Header<TData>
|
|
48
|
+
content?: never
|
|
49
|
+
context?: never
|
|
50
|
+
cell?: never
|
|
51
|
+
header?: never
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
let props: Props = $props()
|
|
55
|
+
|
|
56
|
+
const resolved = $derived.by(() => {
|
|
57
|
+
if ('cell' in props && props.cell) {
|
|
58
|
+
return {
|
|
59
|
+
content: props.cell.column.columnDef.cell,
|
|
60
|
+
context: props.cell.getContext(),
|
|
61
|
+
}
|
|
62
|
+
}
|
|
63
|
+
if ('header' in props && props.header) {
|
|
64
|
+
return {
|
|
65
|
+
content: props.header.column.columnDef.header,
|
|
66
|
+
context: props.header.getContext(),
|
|
67
|
+
}
|
|
68
|
+
}
|
|
69
|
+
if ('footer' in props && props.footer) {
|
|
70
|
+
return {
|
|
71
|
+
content: props.footer.column.columnDef.footer,
|
|
72
|
+
context: props.footer.getContext(),
|
|
73
|
+
}
|
|
74
|
+
}
|
|
75
|
+
return {
|
|
76
|
+
content: props.content,
|
|
77
|
+
context: props.context,
|
|
78
|
+
}
|
|
79
|
+
})
|
|
80
|
+
|
|
81
|
+
const result = $derived(
|
|
82
|
+
isFunction(resolved.content)
|
|
83
|
+
? resolved.content(resolved.context as any)
|
|
84
|
+
: undefined,
|
|
85
|
+
)
|
|
86
|
+
</script>
|
|
87
|
+
|
|
88
|
+
{#if typeof resolved.content === 'string'}
|
|
89
|
+
{resolved.content}
|
|
90
|
+
{:else if result instanceof RenderComponentConfig}
|
|
91
|
+
<result.component {...result.props} />
|
|
92
|
+
{:else if result instanceof RenderSnippetConfig}
|
|
93
|
+
{@render result.snippet(result.params)}
|
|
94
|
+
{:else if result !== undefined}
|
|
95
|
+
{result}
|
|
96
|
+
{/if}
|