@svgrid/grid 3.0.4 → 3.0.6
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 +32 -11
- package/dist/GridMenus.svelte +34 -4
- package/dist/SvGrid.controller.svelte.d.ts +33 -5
- package/dist/SvGrid.controller.svelte.js +397 -58
- package/dist/SvGrid.css +200 -2
- package/dist/SvGrid.svelte +350 -40
- package/dist/SvGrid.types.d.ts +433 -7
- package/dist/SvGridDropdown.svelte +20 -0
- package/dist/SvGridDropdown.svelte.d.ts +12 -0
- package/dist/SvModal.svelte +22 -0
- package/dist/SvModal.svelte.d.ts +7 -0
- package/dist/a11y/dismissable.d.ts +10 -0
- package/dist/a11y/dismissable.js +24 -2
- package/dist/build-api.js +92 -37
- package/dist/cdn/{GridMenus-BL7ZgQvU.js → GridMenus-C-NtjlrJ.js} +155 -146
- package/dist/cdn/GridMenus-TssHej3q.js +644 -0
- package/dist/cdn/{SvChartMenu-FBSMINA6.js → SvChartMenu-BFSTpvB-.js} +1 -1
- package/dist/cdn/{SvChartMenu-Bl6PBbkT.js → SvChartMenu-BZ1Iwv0y.js} +1 -1
- package/dist/cdn/{SvDateTimePicker-DQwt4UAs.js → SvDateTimePicker-D9u_cOf8.js} +1 -1
- package/dist/cdn/{SvDateTimePicker-vNU6bZ-q.js → SvDateTimePicker-s_6IUpI7.js} +1 -1
- package/dist/cdn/{SvGridCellEditor-B1p-vCK5.js → SvGridCellEditor-BlyCSp0q.js} +1 -1
- package/dist/cdn/{SvGridCellEditor-D_0q4xAu.js → SvGridCellEditor-ClRRA9lW.js} +1 -1
- package/dist/cdn/{SvGridChart-DzLkSwCH.js → SvGridChart-B4EV8U6t.js} +4 -4
- package/dist/cdn/{SvGridChart-C3EWAZaM.js → SvGridChart-DsmwTyZF.js} +4 -4
- package/dist/cdn/{SvGridChartBuilder-CfII62sZ.js → SvGridChartBuilder-cHloHobN.js} +4 -4
- package/dist/cdn/{SvGridChartBuilder-BE2T1ykB.js → SvGridChartBuilder-vOl7C0Za.js} +4 -4
- package/dist/cdn/{SvGridChartPanel-xf4sWVTo.js → SvGridChartPanel-AcqF-Ll5.js} +5 -5
- package/dist/cdn/{SvGridChartPanel-CCX5_Wgd.js → SvGridChartPanel-biMtSBPA.js} +5 -5
- package/dist/cdn/{SvGridChartView-DYwabQWj.js → SvGridChartView-Dx_GmZuL.js} +2 -2
- package/dist/cdn/{SvGridChartView-CfuXmY5I.js → SvGridChartView-I3rDHXAq.js} +2 -2
- package/dist/cdn/{SvGridDropdown-D0VdjeR8.js → SvGridDropdown-BWeM3lMe.js} +46 -46
- package/dist/cdn/{SvGridDropdown-D13MtJ2j.js → SvGridDropdown-CJ6QqTxu.js} +67 -67
- package/dist/cdn/{SvModal-CIZWCcad.js → SvModal-ClxGmpAc.js} +187 -186
- package/dist/cdn/{SvModal-BAE-pjZX.js → SvModal-DhB_VMFR.js} +148 -147
- package/dist/cdn/{cell-formatting-C2Hf5gqd.js → cell-formatting-DVVKOSI9.js} +1 -1
- package/dist/cdn/{chart-Dz7SqMXH.js → chart-DEZxwC0i.js} +1 -1
- package/dist/cdn/{chart-panel-messages-CUbf2R4i.js → chart-panel-messages-D12XcTZJ.js} +1 -1
- package/dist/cdn/{chart-panel-messages-CmNrMdsr.js → chart-panel-messages-DguS7gC5.js} +1 -1
- package/dist/cdn/{chart-summary-BJW_tg_X.js → chart-summary-CMAXBGY-.js} +1 -1
- package/dist/cdn/{chart-trend-CaN9mDEV.js → chart-trend-BkEp61Gj.js} +1 -1
- package/dist/cdn/{dismissable-DAHetSNk.js → dismissable-Brc4EZU1.js} +5 -1
- package/dist/cdn/{export-format-CUDLy2yn.js → export-format-YzdwBww2.js} +1 -1
- package/dist/cdn/{row-resize-niQCp040.js → row-resize-DtOS1KG6.js} +41 -32
- package/dist/cdn/server-block-cache-DIqb3VZn.js +241 -0
- package/dist/cdn/{src-V1uu8iE9.js → src-CgoeSM8k.js} +5339 -4753
- package/dist/cdn/{src-BKhZ6eXd.js → src-DfwxB1TH.js} +9817 -9231
- package/dist/cdn/svgrid.js +28 -27
- package/dist/cdn/svgrid.svelte-external.js +28 -27
- package/dist/cdn/validate-AZoD8BoR.js +80 -0
- package/dist/cell-formatting.js +18 -1
- package/dist/cell-render.js +25 -6
- package/dist/clipboard.d.ts +2 -2
- package/dist/clipboard.js +72 -23
- package/dist/columns.js +7 -2
- package/dist/conditional-formatting.d.ts +2 -0
- package/dist/conditional-formatting.js +2 -0
- package/dist/core.d.ts +22 -6
- package/dist/core.js +401 -38
- package/dist/editing.js +34 -0
- 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 +10 -0
- package/dist/grid-messages.js +9 -0
- package/dist/headless.d.ts +5 -0
- package/dist/headless.js +12 -0
- package/dist/history.d.ts +21 -0
- package/dist/history.js +34 -4
- package/dist/index.d.ts +5 -4
- package/dist/index.js +3 -3
- package/dist/keyboard-handlers.js +24 -1
- package/dist/keyboard.js +4 -0
- package/dist/row-drag-touch.d.ts +1 -1
- package/dist/row-drag.js +35 -1
- package/dist/row-model.d.ts +139 -0
- package/dist/row-model.js +16 -0
- package/dist/row-resize.js +22 -1
- package/dist/selection.d.ts +2 -1
- package/dist/selection.js +31 -3
- package/dist/server-block-cache.d.ts +219 -0
- package/dist/server-block-cache.js +539 -0
- package/dist/server-data-source.d.ts +274 -8
- package/dist/server-data-source.js +229 -20
- package/dist/server.d.ts +13 -0
- package/dist/server.js +13 -0
- package/dist/sparkline.js +7 -5
- package/dist/svgrid-wrapper.types.d.ts +33 -0
- package/dist/validate.d.ts +4 -0
- package/dist/validate.js +29 -3
- package/package.json +11 -1
- package/src/GridMenus.svelte +34 -4
- package/src/SvGrid.controller.svelte.ts +397 -61
- package/src/SvGrid.css +200 -2
- package/src/SvGrid.svelte +350 -40
- package/src/SvGrid.types.ts +453 -7
- package/src/SvGridDropdown.svelte +20 -0
- package/src/SvModal.svelte +22 -0
- package/src/SvModal.test.ts +30 -1
- package/src/a11y/dismissable.test.ts +10 -1
- package/src/a11y/dismissable.ts +22 -2
- package/src/build-api.ts +96 -31
- package/src/cell-formatting.test.ts +17 -0
- package/src/cell-formatting.ts +18 -1
- package/src/cell-render.test.ts +24 -2
- package/src/cell-render.ts +24 -8
- package/src/clipboard.test.ts +107 -0
- package/src/clipboard.ts +62 -23
- package/src/columns.test.ts +4 -4
- package/src/columns.ts +7 -2
- package/src/conditional-formatting.test.ts +8 -0
- package/src/conditional-formatting.ts +3 -0
- package/src/core.rowmodel-cache.test.ts +51 -0
- package/src/core.tick-repair.test.ts +287 -0
- package/src/core.ts +407 -38
- package/src/editing.test.ts +52 -0
- package/src/editing.ts +33 -0
- 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.test.ts +7 -0
- package/src/grid-messages.ts +22 -0
- package/src/headless.ts +24 -0
- package/src/history.test.ts +49 -1
- package/src/history.ts +48 -2
- package/src/icon-seam.test.ts +2 -4
- package/src/index.ts +38 -10
- package/src/keyboard-handlers.coverage.test.ts +65 -0
- package/src/keyboard-handlers.ts +26 -1
- package/src/keyboard.ts +3 -0
- package/src/row-drag-touch.ts +2 -2
- package/src/row-drag.test.ts +51 -0
- package/src/row-drag.ts +35 -2
- package/src/row-model.ts +152 -0
- package/src/row-resize.ts +24 -1
- package/src/selection.test.ts +3 -0
- package/src/selection.ts +33 -3
- package/src/server-block-cache.test.ts +672 -0
- package/src/server-block-cache.ts +690 -0
- package/src/server-data-source.infinite.test.ts +405 -0
- package/src/server-data-source.test.ts +19 -0
- package/src/server-data-source.ts +496 -29
- package/src/server.ts +49 -0
- package/src/sparkline.test.ts +7 -0
- package/src/sparkline.ts +6 -4
- package/src/svgrid-wrapper.types.ts +32 -0
- package/src/svgrid.api.test.ts +21 -0
- package/src/svgrid.charting.test.ts +12 -4
- package/src/svgrid.context-menu.test.ts +12 -0
- package/src/svgrid.detail-rows.svelte.test.ts +187 -0
- package/src/svgrid.filter-menu-scroll.test.ts +9 -0
- package/src/svgrid.gantt-seam.test.ts +199 -0
- package/src/svgrid.live-update-paths.svelte.test.ts +184 -0
- package/src/svgrid.menu-scroll-close.test.ts +10 -0
- package/src/svgrid.row-model-prop.svelte.test.ts +352 -0
- package/src/svgrid.row-model-seam.svelte.test.ts +305 -0
- package/src/svgrid.row-pinning.test.ts +15 -1
- package/src/svgrid.selection-bar-seam.test.ts +1 -1
- package/src/svgrid.sticky-groups.svelte.test.ts +145 -0
- package/src/svgrid.upsell-license.test.ts +8 -5
- package/src/test-setup.ts +12 -0
- package/src/transaction.test.ts +58 -0
- package/src/validate.test.ts +29 -0
- package/src/validate.ts +34 -3
- 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-7kbpnnBW.js +0 -635
- 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/dist/grid-icons.d.ts
CHANGED
|
@@ -35,8 +35,8 @@ export type GridIconName = 'sort' | 'sort-asc' | 'sort-desc' | 'filter' | 'menu'
|
|
|
35
35
|
export type GridIcons = Partial<Record<GridIconName, Snippet>>;
|
|
36
36
|
/**
|
|
37
37
|
* Icons whose built-in form is a character rather than an SVG path. Kept as
|
|
38
|
-
* data so `<SvGrid>`, its footer and the
|
|
39
|
-
* the same defaults instead of three copies drifting apart.
|
|
38
|
+
* data so `<SvGrid>`, its footer and the row-group panel in @svgrid/enterprise
|
|
39
|
+
* render the same defaults instead of three copies drifting apart.
|
|
40
40
|
*
|
|
41
41
|
* Each is the exact character that shipped inline before, so a grid that sets
|
|
42
42
|
* no `icons` renders byte-for-byte what it always did.
|
package/dist/grid-icons.js
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* Icons whose built-in form is a character rather than an SVG path. Kept as
|
|
3
|
-
* data so `<SvGrid>`, its footer and the
|
|
4
|
-
* the same defaults instead of three copies drifting apart.
|
|
3
|
+
* data so `<SvGrid>`, its footer and the row-group panel in @svgrid/enterprise
|
|
4
|
+
* render the same defaults instead of three copies drifting apart.
|
|
5
5
|
*
|
|
6
6
|
* Each is the exact character that shipped inline before, so a grid that sets
|
|
7
7
|
* no `icons` renders byte-for-byte what it always did.
|
package/dist/grid-messages.d.ts
CHANGED
|
@@ -74,8 +74,18 @@ export type GridChromeMessages = {
|
|
|
74
74
|
bulkEditCancel: string;
|
|
75
75
|
bulkEditNoFields: string;
|
|
76
76
|
chartRange: string;
|
|
77
|
+
rowLoadFailed: string;
|
|
78
|
+
rowLoadRetry: string;
|
|
79
|
+
expandGroup: string;
|
|
80
|
+
collapseGroup: string;
|
|
81
|
+
openDetail: string;
|
|
82
|
+
closeDetail: string;
|
|
77
83
|
pivotUpsellTitle: string;
|
|
78
84
|
pivotUpsellBody: string;
|
|
85
|
+
ganttUpsellTitle: string;
|
|
86
|
+
ganttUpsellBody: string;
|
|
87
|
+
/** Placeholder in the Gantt view's search box. */
|
|
88
|
+
ganttSearchPlaceholder: string;
|
|
79
89
|
/** Shared licensing line under every Enterprise upsell note. */
|
|
80
90
|
upsellLicense: string;
|
|
81
91
|
upsellLicenseLink: string;
|
package/dist/grid-messages.js
CHANGED
|
@@ -84,8 +84,17 @@ export const defaultGridMessages = {
|
|
|
84
84
|
opBefore: 'Before',
|
|
85
85
|
opAfter: 'After',
|
|
86
86
|
chartRange: 'Chart selected range',
|
|
87
|
+
rowLoadFailed: 'Could not load these rows.',
|
|
88
|
+
rowLoadRetry: 'Retry',
|
|
89
|
+
expandGroup: 'Expand group',
|
|
90
|
+
collapseGroup: 'Collapse group',
|
|
91
|
+
openDetail: 'Open details',
|
|
92
|
+
closeDetail: 'Close details',
|
|
87
93
|
pivotUpsellTitle: 'Pivot mode',
|
|
88
94
|
pivotUpsellBody: 'Pivot mode is an Enterprise feature. Install @svgrid/enterprise and call enablePivot() to use it.',
|
|
95
|
+
ganttUpsellTitle: 'Gantt view',
|
|
96
|
+
ganttUpsellBody: 'The Gantt view is an Enterprise feature. Install @svgrid/enterprise and call enableGanttView() to render it.',
|
|
97
|
+
ganttSearchPlaceholder: 'Search tasks...',
|
|
89
98
|
upsellLicense: 'A license key is required for production use. Without one the feature still works, but the grid renders an unlicensed watermark.',
|
|
90
99
|
upsellLicenseLink: 'View licensing',
|
|
91
100
|
};
|
package/dist/headless.d.ts
CHANGED
|
@@ -27,3 +27,8 @@ export { columnFilteringFeature, columnGroupingFeature, createCoreRowModel, crea
|
|
|
27
27
|
export { createGrid, createSvGrid, type SvelteGrid } from './createGrid.svelte.js';
|
|
28
28
|
export { createGridState, createSvGridState } from './createGridState.svelte.js';
|
|
29
29
|
export { subscribeGrid, subscribeSvGrid } from './subscribe.js';
|
|
30
|
+
export { createVirtualizer } from './virtualization/virtualizer.js';
|
|
31
|
+
export { createSvelteVirtualizer } from './virtualization/svelte-virtualizer.svelte.js';
|
|
32
|
+
export { createColumnVirtualizer } from './virtualization/column-virtualizer.js';
|
|
33
|
+
export type { VirtualItem, VirtualizerOptions, VirtualizerState } from './virtualization/types.js';
|
|
34
|
+
export { getGridCellDomId, getGridCellA11yProps, getGridHeaderA11yProps, getGridRootA11yProps, getGridRowA11yProps, type GridCellA11yInput, type GridColumnA11yInput, type GridSortDirection, } from './a11y.js';
|
package/dist/headless.js
CHANGED
|
@@ -27,3 +27,15 @@ export { columnFilteringFeature, columnGroupingFeature, createCoreRowModel, crea
|
|
|
27
27
|
export { createGrid, createSvGrid } from './createGrid.svelte.js';
|
|
28
28
|
export { createGridState, createSvGridState } from './createGridState.svelte.js';
|
|
29
29
|
export { subscribeGrid, subscribeSvGrid } from './subscribe.js';
|
|
30
|
+
// The virtualizers are pure window arithmetic (scroll offset in, visible
|
|
31
|
+
// range out) with no DOM of their own, and a custom renderer over 50k rows
|
|
32
|
+
// needs one. They were only on the barrel, so the Headless demos imported
|
|
33
|
+
// the barrel to reach them and paid for the whole thing.
|
|
34
|
+
export { createVirtualizer } from './virtualization/virtualizer.js';
|
|
35
|
+
export { createSvelteVirtualizer } from './virtualization/svelte-virtualizer.svelte.js';
|
|
36
|
+
export { createColumnVirtualizer } from './virtualization/column-virtualizer.js';
|
|
37
|
+
// The WAI-ARIA attribute factories: plain objects to spread onto your own
|
|
38
|
+
// markup (`role`, `aria-sort`, `aria-rowindex`, ...). No DOM is touched here
|
|
39
|
+
// either; a custom renderer that wants keyboard navigation reads
|
|
40
|
+
// `activeCell` from the store and spreads these.
|
|
41
|
+
export { getGridCellDomId, getGridCellA11yProps, getGridHeaderA11yProps, getGridRootA11yProps, getGridRowA11yProps, } from './a11y.js';
|
package/dist/history.d.ts
CHANGED
|
@@ -38,6 +38,15 @@ export type HistoryStep = {
|
|
|
38
38
|
undo: () => void;
|
|
39
39
|
redo: () => void;
|
|
40
40
|
};
|
|
41
|
+
/**
|
|
42
|
+
* The consumer's own mark on the step, copied from `api.setHistoryTag` at
|
|
43
|
+
* the moment it is recorded. The grid never reads it: it is there for a
|
|
44
|
+
* consumer that shows one of several data sets through the grid and has
|
|
45
|
+
* to know which one a step belongs to before it lets Ctrl+Z apply it (a
|
|
46
|
+
* workbook with several sheets, say). Kept as given, so an object tag
|
|
47
|
+
* compares by identity. Not serialised.
|
|
48
|
+
*/
|
|
49
|
+
tag?: unknown;
|
|
41
50
|
};
|
|
42
51
|
/** Ctx surface these helpers touch. The controller satisfies it structurally. */
|
|
43
52
|
type HistoryCtx = {
|
|
@@ -49,8 +58,20 @@ type HistoryCtx = {
|
|
|
49
58
|
* inside it joins that group, so a command does not have to thread a group
|
|
50
59
|
* id down through the writers it calls. */
|
|
51
60
|
historyGroupId: string | undefined;
|
|
61
|
+
/** Stamped on every step recorded while it is set; see `HistoryStep.tag`. */
|
|
62
|
+
historyTag?: unknown;
|
|
52
63
|
applyHistoryStep(step: HistoryStep, direction: 'undo' | 'redo'): void;
|
|
53
64
|
};
|
|
65
|
+
/** What the next undo would apply: the tag of the step Ctrl+Z takes next
|
|
66
|
+
* (a group carries one tag, so its last step's is the group's). Null when
|
|
67
|
+
* there is nothing to undo. */
|
|
68
|
+
export declare function peekUndoHistory(ctx: HistoryCtx): {
|
|
69
|
+
tag: unknown;
|
|
70
|
+
} | null;
|
|
71
|
+
/** The redo counterpart of `peekUndoHistory`. */
|
|
72
|
+
export declare function peekRedoHistory(ctx: HistoryCtx): {
|
|
73
|
+
tag: unknown;
|
|
74
|
+
} | null;
|
|
54
75
|
/** Undo one action. Returns false when there is nothing left to undo. */
|
|
55
76
|
export declare function undoHistory(ctx: HistoryCtx): boolean;
|
|
56
77
|
/** Redo one action. Returns false when there is nothing left to redo. */
|
package/dist/history.js
CHANGED
|
@@ -41,6 +41,34 @@ function groupEnd(history, start) {
|
|
|
41
41
|
i += 1;
|
|
42
42
|
return i;
|
|
43
43
|
}
|
|
44
|
+
/**
|
|
45
|
+
* The last `limit` ACTIONS of a history, whole groups kept. The cap used
|
|
46
|
+
* to count steps, and a sort of 5,000 rows is 20,000 steps in one group:
|
|
47
|
+
* it cut the group to its last 200 cells, so Ctrl+Z put a fifth of a
|
|
48
|
+
* column back and left the rest sorted. An action is one press of Ctrl+Z,
|
|
49
|
+
* so that is what the buffer counts; the steps inside are the cost of it.
|
|
50
|
+
*/
|
|
51
|
+
function lastActions(history, limit) {
|
|
52
|
+
let i = history.length;
|
|
53
|
+
let actions = 0;
|
|
54
|
+
while (i > 0 && actions < limit) {
|
|
55
|
+
i = groupStart(history, i - 1);
|
|
56
|
+
actions += 1;
|
|
57
|
+
}
|
|
58
|
+
return i === 0 ? history : history.slice(i);
|
|
59
|
+
}
|
|
60
|
+
/** What the next undo would apply: the tag of the step Ctrl+Z takes next
|
|
61
|
+
* (a group carries one tag, so its last step's is the group's). Null when
|
|
62
|
+
* there is nothing to undo. */
|
|
63
|
+
export function peekUndoHistory(ctx) {
|
|
64
|
+
const step = ctx.historyPtr >= 0 ? ctx.history[ctx.historyPtr] : undefined;
|
|
65
|
+
return step ? { tag: step.tag } : null;
|
|
66
|
+
}
|
|
67
|
+
/** The redo counterpart of `peekUndoHistory`. */
|
|
68
|
+
export function peekRedoHistory(ctx) {
|
|
69
|
+
const step = ctx.historyPtr < ctx.history.length - 1 ? ctx.history[ctx.historyPtr + 1] : undefined;
|
|
70
|
+
return step ? { tag: step.tag } : null;
|
|
71
|
+
}
|
|
44
72
|
/** Undo one action. Returns false when there is nothing left to undo. */
|
|
45
73
|
export function undoHistory(ctx) {
|
|
46
74
|
if (ctx.historyPtr < 0)
|
|
@@ -94,11 +122,13 @@ export function pushHistory(ctx, steps, groupId) {
|
|
|
94
122
|
// Outside one, a group of one is just a step. Tagging it would make undo do
|
|
95
123
|
// the same work through a slower path and would show up in serialized state.
|
|
96
124
|
const id = ctx.historyGroupId ?? (groupId && steps.length > 1 ? groupId : undefined);
|
|
125
|
+
const tag = ctx.historyTag;
|
|
97
126
|
let next = ctx.history.slice(0, ctx.historyPtr + 1);
|
|
98
|
-
for (const step of steps)
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
127
|
+
for (const step of steps) {
|
|
128
|
+
const stamped = tag === undefined ? step : { ...step, tag };
|
|
129
|
+
next.push(id ? { ...stamped, groupId: id } : stamped);
|
|
130
|
+
}
|
|
131
|
+
next = lastActions(next, ctx.UNDO_LIMIT);
|
|
102
132
|
ctx.history = next;
|
|
103
133
|
ctx.historyPtr = ctx.history.length - 1;
|
|
104
134
|
ctx.historyVersion += 1;
|
package/dist/index.d.ts
CHANGED
|
@@ -12,6 +12,8 @@ export * from './ai.js';
|
|
|
12
12
|
export { registerExportProvider, getExportProvider, type GridExportProvider, type GridExportRunOptions, } from './export-provider.js';
|
|
13
13
|
export type { SchedulerConfig, SchedulerDrawerConfig, SchedulerEventMoveEvent, SchedulerEventResizeEvent, SchedulerEventCommitEvent, SchedulerRangeSelection, SchedulerView, SchedulerResource, SchedulerCollisionMode, SchedulerException, SchedulerEditScope, SchedulerOccurrenceChangeEvent, } from './SvGrid.types.js';
|
|
14
14
|
export { registerSchedulerView, getSchedulerView, hasSchedulerView } from './scheduler-view.svelte.js';
|
|
15
|
+
export type { GanttConfig, GanttDrawerConfig, GanttTaskMoveEvent, GanttTaskResizeEvent, GanttProgressChangeEvent, GanttTaskCommitEvent, GanttDependency, GanttDependencyType, GanttZoom, } from './SvGrid.types.js';
|
|
16
|
+
export { registerGanttView, getGanttView, hasGanttView } from './gantt-view.svelte.js';
|
|
15
17
|
export { registerSelectionBarView, getSelectionBarView, hasSelectionBarView } from './selection-bar-view.svelte.js';
|
|
16
18
|
export type { ChartViewConfig } from './SvGrid.types.js';
|
|
17
19
|
export { registerChartView, getChartView, hasChartView } from './chart-view.svelte.js';
|
|
@@ -211,10 +213,9 @@ export { resolveColumnTypes, inferCellDataType, type CellDataType } from './colu
|
|
|
211
213
|
export { computeColumnGroupMeta, hiddenLeavesForCollapse, type ColumnGroupMeta, type ColumnGroupShow, } from './column-groups.js';
|
|
212
214
|
export { createHyperFormulaSheet, type HyperFormulaSheet, type HyperFormulaSheetConfig, type HyperFormulaInstance, } from './hyperformula-adapter.js';
|
|
213
215
|
export { createCollaboration, broadcastChannelTransport, type CollabUser, type CollabCell, type CollabPresence, type CollabMessage, type CollabTransport, type Collaboration, } from './collaboration.js';
|
|
214
|
-
export { createServerDataSource, type ServerDataSource, type ServerRequest, type ServerResult, type ServerController, type ServerState, type ServerSortModel, type ServerFilterModel, type ServerAggregation, type ServerGroupRow, type ServerLeafRow, type ServerMoreRow, type ServerFooterRow, type ServerSkeletonRow, type ServerDisplayRow, } from './server-data-source.js';
|
|
215
|
-
export {
|
|
216
|
-
export {
|
|
217
|
-
export { default as SvRowGroupPanel } from './SvRowGroupPanel.svelte';
|
|
216
|
+
export { createServerDataSource, type ServerDataSource, type ServerSelectionRule, type ServerRequest, type ServerResult, type ServerController, type ServerControllerOptions, type ServerState, type ServerSortModel, type ServerFilterModel, type ServerAggFn, type ServerAggregation, type ServerGroupRow, type ServerLeafRow, type ServerMoreRow, type ServerFooterRow, type ServerSkeletonRow, type ServerGrandTotalRow, type ServerPlaceholderRow, type ServerDisplayRow, type ServerDetailRow, } from './server-data-source.js';
|
|
217
|
+
export { createBlockCache, createRowPlaceholder, rowPlaceholderState, type BlockCache, type BlockCacheOptions, type BlockCacheState, type BlockFetchResult, type BlockState, } from './server-block-cache.js';
|
|
218
|
+
export { toServerFilterColumns, type GridRowModel, type GridFilterState, type GridRowModelSort, } from './row-model.js';
|
|
218
219
|
export { createNamedViews, memoryViews, localStorageViews, attachAutoSavedView, type SavedView, type ViewStorage, type NamedViews, type AutoSavedViewOptions, } from './named-views.js';
|
|
219
220
|
export { resolveCellFormat, computeColumnStat, lerpColor, rgba, contrastText, formatNeedsStats, formatsNeedingStats, type ConditionalFormat, type ConditionalFormatSpec, type ColorScaleFormat, type ColorScaleStop, type ScaleBounds, type DataBarFormat, type IconSetFormat, type RuleFormat, type ResolvedCellFormat, } from './conditional-formatting.js';
|
|
220
221
|
export { defaultGridMessages, resolveGridMessages, type GridMessages, type GridChromeMessages, } from './grid-messages.js';
|
package/dist/index.js
CHANGED
|
@@ -15,6 +15,7 @@ export { registerBoardView, getBoardView, hasBoardView } from './board-view.svel
|
|
|
15
15
|
export * from './ai.js';
|
|
16
16
|
export { registerExportProvider, getExportProvider, } from './export-provider.js';
|
|
17
17
|
export { registerSchedulerView, getSchedulerView, hasSchedulerView } from './scheduler-view.svelte.js';
|
|
18
|
+
export { registerGanttView, getGanttView, hasGanttView } from './gantt-view.svelte.js';
|
|
18
19
|
// Bulk-action bar over the row selection. Prop + types free, renderer Pro.
|
|
19
20
|
export { registerSelectionBarView, getSelectionBarView, hasSelectionBarView } from './selection-bar-view.svelte.js';
|
|
20
21
|
export { registerChartView, getChartView, hasChartView } from './chart-view.svelte.js';
|
|
@@ -253,9 +254,8 @@ export { computeColumnGroupMeta, hiddenLeavesForCollapse, } from './column-group
|
|
|
253
254
|
export { createHyperFormulaSheet, } from './hyperformula-adapter.js';
|
|
254
255
|
export { createCollaboration, broadcastChannelTransport, } from './collaboration.js';
|
|
255
256
|
export { createServerDataSource, } from './server-data-source.js';
|
|
256
|
-
export {
|
|
257
|
-
export {
|
|
258
|
-
export { default as SvRowGroupPanel } from './SvRowGroupPanel.svelte';
|
|
257
|
+
export { createBlockCache, createRowPlaceholder, rowPlaceholderState, } from './server-block-cache.js';
|
|
258
|
+
export { toServerFilterColumns, } from './row-model.js';
|
|
259
259
|
export { createNamedViews, memoryViews, localStorageViews, attachAutoSavedView, } from './named-views.js';
|
|
260
260
|
export { resolveCellFormat, computeColumnStat, lerpColor, rgba, contrastText, formatNeedsStats, formatsNeedingStats, } from './conditional-formatting.js';
|
|
261
261
|
export { defaultGridMessages, resolveGridMessages, } from './grid-messages.js';
|
|
@@ -166,6 +166,28 @@ export function createKeyboard(ctx) {
|
|
|
166
166
|
row.toggleExpanded?.();
|
|
167
167
|
return;
|
|
168
168
|
}
|
|
169
|
+
// The same key on a server-side tree: a group opens or closes, a leaf
|
|
170
|
+
// opens or closes its detail panel when the grid draws one.
|
|
171
|
+
const sg = ctx.props.serverGroup;
|
|
172
|
+
if (event.ctrlKey && sg && row) {
|
|
173
|
+
const data = row.original;
|
|
174
|
+
if (sg.isGroup(data)) {
|
|
175
|
+
sg.onToggle(data);
|
|
176
|
+
return;
|
|
177
|
+
}
|
|
178
|
+
if (sg.toggleDetail && ctx.props.renderDetailRow && (sg.hasDetail?.(data) ?? true)) {
|
|
179
|
+
sg.toggleDetail(data);
|
|
180
|
+
return;
|
|
181
|
+
}
|
|
182
|
+
}
|
|
183
|
+
// ...and on a client-side master-detail: the app's own toggle.
|
|
184
|
+
if (event.ctrlKey && row && ctx.props.onDetailToggle && ctx.props.renderDetailRow) {
|
|
185
|
+
const data = row.original;
|
|
186
|
+
if (!ctx.props.isDetailRow?.(data, current.rowIndex) && (ctx.props.hasDetail?.(data) ?? true)) {
|
|
187
|
+
ctx.props.onDetailToggle(data, current.rowIndex);
|
|
188
|
+
return;
|
|
189
|
+
}
|
|
190
|
+
}
|
|
169
191
|
if (column?.columnDef.editorType === "checkbox") {
|
|
170
192
|
ctx.toggleBooleanCell(current.rowIndex, current.colIndex);
|
|
171
193
|
return;
|
|
@@ -257,7 +279,8 @@ export function createKeyboard(ctx) {
|
|
|
257
279
|
ctx.setSelection(next.rowIndex, next.colIndex);
|
|
258
280
|
}
|
|
259
281
|
function onWindowKeydown(event) {
|
|
260
|
-
if (event.key === "Escape" &&
|
|
282
|
+
if (event.key === "Escape" &&
|
|
283
|
+
(ctx.columnMenuFor || ctx.operatorMenuFor || ctx.filterMenuFor || ctx.inSuggestFor || ctx.chooseColumnsPos)) {
|
|
261
284
|
ctx.closeMenus();
|
|
262
285
|
}
|
|
263
286
|
}
|
package/dist/keyboard.js
CHANGED
|
@@ -37,6 +37,10 @@ export function getKeyboardIntent(event) {
|
|
|
37
37
|
// Tab → move right (Shift+Tab → left), wraps at row boundaries
|
|
38
38
|
// Delete → clear contents of the selected cells
|
|
39
39
|
// F2 / Space → start editing the active cell
|
|
40
|
+
// Ctrl+Enter acts on the row rather than moving: a group opens or closes,
|
|
41
|
+
// a row with a detail panel shows or hides it (see the activate branch).
|
|
42
|
+
if (event.key === 'Enter' && (event.ctrlKey || event.metaKey))
|
|
43
|
+
return 'activate';
|
|
40
44
|
if (event.key === 'Enter')
|
|
41
45
|
return event.shiftKey ? 'moveUp' : 'moveDown';
|
|
42
46
|
if (event.key === 'Tab')
|
package/dist/row-drag-touch.d.ts
CHANGED
|
@@ -3,7 +3,7 @@ export type TouchDragDeps = {
|
|
|
3
3
|
ctx: any;
|
|
4
4
|
managed: () => boolean;
|
|
5
5
|
originalAt: (rowIndex: number) => unknown;
|
|
6
|
-
commitDropOnRow: (rowIndex: number, side: "before" | "after") => void;
|
|
6
|
+
commitDropOnRow: (rowIndex: number, side: "before" | "after" | "into") => void;
|
|
7
7
|
clearIndicators: () => void;
|
|
8
8
|
cancelPendingLeave: () => void;
|
|
9
9
|
/** Publish the dragged row on the shared cross-grid bus. */
|
package/dist/row-drag.js
CHANGED
|
@@ -98,7 +98,27 @@ export function createRowDrag(ctx) {
|
|
|
98
98
|
e.dataTransfer.dropEffect = "move";
|
|
99
99
|
const rect = e.currentTarget.getBoundingClientRect();
|
|
100
100
|
ctx.rowDropIndex = rowIndex;
|
|
101
|
-
ctx.rowDropSide =
|
|
101
|
+
ctx.rowDropSide = sideAt(rowIndex, rect, e.clientY);
|
|
102
|
+
}
|
|
103
|
+
/**
|
|
104
|
+
* Which edge the pointer is on. A custom drop handler also gets the middle
|
|
105
|
+
* of a group or tree row as "into" (the row becomes its child); the
|
|
106
|
+
* managed reorder only knows before and after.
|
|
107
|
+
*/
|
|
108
|
+
function sideAt(rowIndex, rect, y) {
|
|
109
|
+
const rel = (y - rect.top) / Math.max(rect.height, 1);
|
|
110
|
+
if (ctx.props.onRowDrop && rel >= 0.25 && rel <= 0.75 && canNest(rowIndex))
|
|
111
|
+
return "into";
|
|
112
|
+
return rel < 0.5 ? "before" : "after";
|
|
113
|
+
}
|
|
114
|
+
function canNest(rowIndex) {
|
|
115
|
+
const row = ctx.allRows[rowIndex];
|
|
116
|
+
if (!row)
|
|
117
|
+
return false;
|
|
118
|
+
const sg = ctx.props.serverGroup;
|
|
119
|
+
if (sg)
|
|
120
|
+
return !!sg.isGroup(row.original);
|
|
121
|
+
return typeof row.getCanExpand === "function" && row.getCanExpand();
|
|
102
122
|
}
|
|
103
123
|
function onRowDragLeave(rowIndex) {
|
|
104
124
|
// A leave from a row that is not the current target is already stale.
|
|
@@ -137,6 +157,15 @@ export function createRowDrag(ctx) {
|
|
|
137
157
|
const sourceGridId = bus.gridId;
|
|
138
158
|
const sameGrid = sourceGridId === gridId;
|
|
139
159
|
clearIndicators();
|
|
160
|
+
// A custom handler owns the drop: the grid reports it and leaves its
|
|
161
|
+
// data alone (a row model's rows are not the grid's to splice).
|
|
162
|
+
if (sameGrid && ctx.props.onRowDrop) {
|
|
163
|
+
bus = null;
|
|
164
|
+
ctx.props.onRowDrop({ row: dragged, target, targetIndex: rowIndex, side });
|
|
165
|
+
return;
|
|
166
|
+
}
|
|
167
|
+
if (side === "into")
|
|
168
|
+
side = "after";
|
|
140
169
|
const data = ctx.internalData.slice();
|
|
141
170
|
if (sameGrid) {
|
|
142
171
|
const from = data.indexOf(dragged);
|
|
@@ -183,6 +212,11 @@ export function createRowDrag(ctx) {
|
|
|
183
212
|
const sourceGridId = bus.gridId;
|
|
184
213
|
const sameGrid = sourceGridId === gridId;
|
|
185
214
|
clearIndicators();
|
|
215
|
+
if (sameGrid && ctx.props.onRowDrop) {
|
|
216
|
+
bus = null;
|
|
217
|
+
ctx.props.onRowDrop({ row: dragged, target: null, targetIndex: null, side: "after" });
|
|
218
|
+
return;
|
|
219
|
+
}
|
|
186
220
|
const data = ctx.internalData.slice();
|
|
187
221
|
if (sameGrid) {
|
|
188
222
|
const from = data.indexOf(dragged);
|
|
@@ -0,0 +1,139 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* `GridRowModel` - one prop instead of eleven.
|
|
3
|
+
*
|
|
4
|
+
* A grid backed by a server needs the same wiring every time: hand it the
|
|
5
|
+
* rows, tell it not to sort or filter locally, forward the sort and the filter
|
|
6
|
+
* to the backend, report which rows are on screen, say which rows have not
|
|
7
|
+
* loaded, and delegate selection. Written out by hand that is a dozen props
|
|
8
|
+
* and a filter-shape conversion that every app gets slightly differently:
|
|
9
|
+
*
|
|
10
|
+
* ```svelte
|
|
11
|
+
* <SvGrid data={s.rows} externalSort externalFilter loading={s.loading}
|
|
12
|
+
* onSortingChange={(x) => ctl.setSort(x)}
|
|
13
|
+
* onFiltersChange={(f) => ctl.setFilter({ global: f.global,
|
|
14
|
+
* columns: Object.fromEntries(f.columns.map((c) => [c.id, { ... }])) })}
|
|
15
|
+
* onVisibleRangeChange={(r) => ctl.setViewport(r.startIndex, r.endIndex)}
|
|
16
|
+
* ... />
|
|
17
|
+
* ```
|
|
18
|
+
*
|
|
19
|
+
* An object that implements this interface carries all of it, so the same grid
|
|
20
|
+
* becomes:
|
|
21
|
+
*
|
|
22
|
+
* ```svelte
|
|
23
|
+
* <SvGrid rowModel={ctl} {columns} />
|
|
24
|
+
* ```
|
|
25
|
+
*
|
|
26
|
+
* `createServerDataSource` returns one, and so does the Enterprise server row
|
|
27
|
+
* model - which is the point of the interface rather than a concrete type: the
|
|
28
|
+
* grid depends on the SHAPE, never on either implementation, and an app with
|
|
29
|
+
* its own fetching can satisfy it too.
|
|
30
|
+
*
|
|
31
|
+
* Every member except `subscribe` / `getRows` / `isLoading` is optional, and a
|
|
32
|
+
* prop written explicitly on `<SvGrid>` always wins over the model's answer -
|
|
33
|
+
* so adopting this is never all-or-nothing.
|
|
34
|
+
*/
|
|
35
|
+
import type { FilterOperator } from './SvGrid.types.js';
|
|
36
|
+
/** The filter state as the grid reports it, straight from `onFiltersChange`. */
|
|
37
|
+
export type GridFilterState = {
|
|
38
|
+
global: string;
|
|
39
|
+
columns: Array<{
|
|
40
|
+
id: string;
|
|
41
|
+
operator: FilterOperator;
|
|
42
|
+
value: string;
|
|
43
|
+
valueTo?: string;
|
|
44
|
+
selectedValues?: Array<string>;
|
|
45
|
+
}>;
|
|
46
|
+
};
|
|
47
|
+
/** The sort the grid hands a row model: column id and direction, in priority order. */
|
|
48
|
+
export type GridRowModelSort = Array<{
|
|
49
|
+
id: string;
|
|
50
|
+
desc: boolean;
|
|
51
|
+
}>;
|
|
52
|
+
/**
|
|
53
|
+
* What `<SvGrid rowModel>` consumes: rows, a loading flag, a change
|
|
54
|
+
* subscription, and whichever optional parts the model implements - sort,
|
|
55
|
+
* filter, viewport, placeholders, group accessors, selection, filter
|
|
56
|
+
* values, paging, pinned rows and pivot columns. `createServerDataSource`
|
|
57
|
+
* and the Enterprise `createServerRowModel` both satisfy it.
|
|
58
|
+
*/
|
|
59
|
+
export type GridRowModel<TData> = {
|
|
60
|
+
/**
|
|
61
|
+
* Register a callback for "something changed, re-read me". Returns an
|
|
62
|
+
* unsubscribe function, which the grid calls on unmount.
|
|
63
|
+
*/
|
|
64
|
+
subscribe(onChange: () => void): () => void;
|
|
65
|
+
/** The rows to render, including any placeholders for unloaded ones. */
|
|
66
|
+
getRows(): ReadonlyArray<TData>;
|
|
67
|
+
/** True while a fetch is in flight, for the loading overlay. */
|
|
68
|
+
isLoading(): boolean;
|
|
69
|
+
/** Stable row id. Required once selection or editing is involved. */
|
|
70
|
+
getRowId?(row: TData, index: number): string;
|
|
71
|
+
/** Sort on the server. Present means "do not sort locally". */
|
|
72
|
+
setSort?(sort: GridRowModelSort): void;
|
|
73
|
+
/** Filter on the server. Present means "do not filter locally". */
|
|
74
|
+
setFilter?(filters: GridFilterState): void;
|
|
75
|
+
/** Which rows are on screen, so a block-loading model knows what to fetch. */
|
|
76
|
+
setViewport?(startIndex: number, endIndex: number): void;
|
|
77
|
+
/** Why a row has no data yet, or null when it does. */
|
|
78
|
+
rowPlaceholder?(row: TData, rowIndex: number): 'loading' | 'failed' | null;
|
|
79
|
+
/** Retry the failed block a placeholder row belongs to. */
|
|
80
|
+
retryRow?(row: TData, rowIndex: number): void;
|
|
81
|
+
/** Group / tree accessors, for the grid's treegrid keyboard and ARIA. */
|
|
82
|
+
group?: {
|
|
83
|
+
isGroup: (row: TData) => boolean;
|
|
84
|
+
level: (row: TData) => number;
|
|
85
|
+
expanded?: (row: TData) => boolean;
|
|
86
|
+
onToggle: (row: TData) => void;
|
|
87
|
+
/** Open or close the detail panel under a leaf. Ctrl+Enter on a row calls it when `renderDetailRow` is set, and so does the `showDetailToggle` chevron. */
|
|
88
|
+
toggleDetail?: (row: TData) => void;
|
|
89
|
+
/** Whether the detail under a leaf is open: the chevron's direction. */
|
|
90
|
+
detailOpen?: (row: TData) => boolean;
|
|
91
|
+
/** Whether a row can open a detail; the chevron is left out where this is false. */
|
|
92
|
+
hasDetail?: (row: TData) => boolean;
|
|
93
|
+
};
|
|
94
|
+
/** Selection the grid does not own - see the `rowSelectionModel` prop. */
|
|
95
|
+
selection?: {
|
|
96
|
+
isSelected: (rowId: string, row: TData) => boolean;
|
|
97
|
+
headerState: () => 'none' | 'some' | 'all';
|
|
98
|
+
toggle: (rowId: string, row: TData, next: boolean) => void;
|
|
99
|
+
toggleAll: (next: boolean) => void;
|
|
100
|
+
selectedCount?: () => number | null;
|
|
101
|
+
bulkUpdate?: (patch: Record<string, unknown>) => Promise<number>;
|
|
102
|
+
};
|
|
103
|
+
/** Distinct values for a column's set filter, fetched from the server. */
|
|
104
|
+
filterValues?(columnId: string): Promise<Array<string>>;
|
|
105
|
+
/** Server-side paging. Omit it for infinite scrolling. */
|
|
106
|
+
pagination?: {
|
|
107
|
+
pageIndex: number;
|
|
108
|
+
pageSize: number;
|
|
109
|
+
rowCount: number;
|
|
110
|
+
setPage(pageIndex: number): void;
|
|
111
|
+
setPageSize(pageSize: number): void;
|
|
112
|
+
/** Choices for the footer's page-size selector. */
|
|
113
|
+
pageSizes?: number[];
|
|
114
|
+
/**
|
|
115
|
+
* Ask the grid for as many rows as its body fits: it measures and calls
|
|
116
|
+
* `setPageSize` whenever the fit changes.
|
|
117
|
+
*/
|
|
118
|
+
autoPageSize?: boolean;
|
|
119
|
+
};
|
|
120
|
+
/** Rows to pin above / below the scrolling body - a grand total, say. */
|
|
121
|
+
readonly pinnedTopRows?: ReadonlyArray<TData>;
|
|
122
|
+
readonly pinnedBottomRows?: ReadonlyArray<TData>;
|
|
123
|
+
/**
|
|
124
|
+
* Columns that replace the grid's `columns` while the model is in pivot
|
|
125
|
+
* mode, or null. Read after every change notification.
|
|
126
|
+
*/
|
|
127
|
+
readonly pivotResultColumns?: ReadonlyArray<unknown> | null;
|
|
128
|
+
};
|
|
129
|
+
/**
|
|
130
|
+
* Turn the grid's filter payload into the column-keyed map a `ServerRequest`
|
|
131
|
+
* carries. Exported because a hand-written `GridRowModel` needs exactly this
|
|
132
|
+
* conversion, and copying it is how the two shapes drift apart.
|
|
133
|
+
*/
|
|
134
|
+
export declare function toServerFilterColumns(filters: GridFilterState): Record<string, {
|
|
135
|
+
operator: string;
|
|
136
|
+
value: string;
|
|
137
|
+
valueTo?: string;
|
|
138
|
+
selectedValues?: Array<string>;
|
|
139
|
+
}>;
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Turn the grid's filter payload into the column-keyed map a `ServerRequest`
|
|
3
|
+
* carries. Exported because a hand-written `GridRowModel` needs exactly this
|
|
4
|
+
* conversion, and copying it is how the two shapes drift apart.
|
|
5
|
+
*/
|
|
6
|
+
export function toServerFilterColumns(filters) {
|
|
7
|
+
return Object.fromEntries(filters.columns.map((c) => [
|
|
8
|
+
c.id,
|
|
9
|
+
{
|
|
10
|
+
operator: c.operator,
|
|
11
|
+
value: c.value,
|
|
12
|
+
...(c.valueTo !== undefined ? { valueTo: c.valueTo } : {}),
|
|
13
|
+
...(c.selectedValues !== undefined ? { selectedValues: c.selectedValues } : {}),
|
|
14
|
+
},
|
|
15
|
+
]));
|
|
16
|
+
}
|
package/dist/row-resize.js
CHANGED
|
@@ -31,6 +31,19 @@ export function rowResize(node, opts) {
|
|
|
31
31
|
let drag = null;
|
|
32
32
|
/** The last press on a strip, for telling a double-click from two drags. */
|
|
33
33
|
let lastPress = null;
|
|
34
|
+
/**
|
|
35
|
+
* A focusable `role="separator"` is a splitter, and a splitter carries its
|
|
36
|
+
* position: axe's `aria-required-attr` fails one without `aria-valuenow`,
|
|
37
|
+
* and a screen reader reading the strip says nothing useful without it. The
|
|
38
|
+
* value is the row's height in pixels, between the action's min and max.
|
|
39
|
+
*/
|
|
40
|
+
function setStripValue(strip, height) {
|
|
41
|
+
const min = current.min ?? 20;
|
|
42
|
+
const max = current.max ?? 320;
|
|
43
|
+
strip.setAttribute('aria-valuemin', String(min));
|
|
44
|
+
strip.setAttribute('aria-valuemax', String(max));
|
|
45
|
+
strip.setAttribute('aria-valuenow', String(Math.round(Math.max(min, Math.min(max, height || min)))));
|
|
46
|
+
}
|
|
34
47
|
function rowIndexOf(tr) {
|
|
35
48
|
const dataRow = tr.querySelector('[data-svgrid-row]');
|
|
36
49
|
const val = dataRow?.dataset.svgridRow;
|
|
@@ -43,6 +56,7 @@ export function rowResize(node, opts) {
|
|
|
43
56
|
const max = current.max ?? 320;
|
|
44
57
|
const next = Math.max(min, Math.min(max, drag.startHeight + (e.clientY - drag.startY)));
|
|
45
58
|
drag.trEl.style.height = `${Math.round(next)}px`;
|
|
59
|
+
setStripValue(drag.strip, next);
|
|
46
60
|
current.onResizeMove?.(drag.rowIndex, Math.round(next));
|
|
47
61
|
}
|
|
48
62
|
function onPointerUp(e) {
|
|
@@ -94,6 +108,7 @@ export function rowResize(node, opts) {
|
|
|
94
108
|
const max = current.max ?? 320;
|
|
95
109
|
const next = Math.round(Math.max(min, Math.min(max, tr.getBoundingClientRect().height + delta)));
|
|
96
110
|
tr.style.height = `${next}px`;
|
|
111
|
+
setStripValue(t, next);
|
|
97
112
|
current.onResizeMove?.(rowIndex, next);
|
|
98
113
|
current.onResize(rowIndex, next);
|
|
99
114
|
}
|
|
@@ -164,8 +179,13 @@ export function rowResize(node, opts) {
|
|
|
164
179
|
: null);
|
|
165
180
|
if (!gutter)
|
|
166
181
|
continue;
|
|
167
|
-
|
|
182
|
+
const already = gutter.querySelector(`:scope > .${STRIP_CLASS}`);
|
|
183
|
+
if (already) {
|
|
184
|
+
// The row may have been resized from outside the action (a saved
|
|
185
|
+
// height, a double-click autofit); keep the separator's value honest.
|
|
186
|
+
setStripValue(already, tr.getBoundingClientRect().height);
|
|
168
187
|
continue;
|
|
188
|
+
}
|
|
169
189
|
// Anchor the strip to the gutter cell + allow it to overflow
|
|
170
190
|
// downward into the row gap so the hit-area straddles the
|
|
171
191
|
// row boundary the way Excel does.
|
|
@@ -180,6 +200,7 @@ export function rowResize(node, opts) {
|
|
|
180
200
|
// A separator used as an interactive splitter has to be focusable so
|
|
181
201
|
// keyboard-only users can reach it and drive `onKeyDown` (#79).
|
|
182
202
|
strip.tabIndex = 0;
|
|
203
|
+
setStripValue(strip, tr.getBoundingClientRect().height);
|
|
183
204
|
// Inline the geometry + pointer-events so the strip works even
|
|
184
205
|
// before SvGrid.css is parsed; the hover tint still comes from
|
|
185
206
|
// the stylesheet. We keep the strip fully inside the gutter
|
package/dist/selection.d.ts
CHANGED
|
@@ -1,9 +1,10 @@
|
|
|
1
1
|
import { type RowData, type TableFeatures } from "./index.js";
|
|
2
2
|
import "./sv-grid-scrollbar.js";
|
|
3
3
|
export declare function createSelection<TFeatures extends TableFeatures = TableFeatures, TData extends RowData = RowData>(ctx: any): {
|
|
4
|
-
isRowSelected: (rowId: string) =>
|
|
4
|
+
isRowSelected: (rowId: string) => any;
|
|
5
5
|
toggleRowSelectionById: (rowId: string) => void;
|
|
6
6
|
toggleSelectAllRows: () => void;
|
|
7
|
+
setSelectAllRows: (select: boolean) => void;
|
|
7
8
|
setActiveCell: (rowIndex: number, colIndex: number) => void;
|
|
8
9
|
scrollActiveCellIntoView: (rowIndex: number, colIndex: number) => void;
|
|
9
10
|
setSelection: (rowIndex: number, colIndex: number, additive?: boolean) => void;
|
package/dist/selection.js
CHANGED
|
@@ -7,14 +7,41 @@ import { getColumnBaseValue, isGroupRow, } from "./cell-values.js";
|
|
|
7
7
|
import { expandRectToMerges, originOf, endOf } from "./merges.js";
|
|
8
8
|
export function createSelection(ctx) {
|
|
9
9
|
function isRowSelected(rowId) {
|
|
10
|
+
const model = ctx.props.rowSelectionModel;
|
|
11
|
+
if (model) {
|
|
12
|
+
const row = ctx.allRows.find((r) => r.id === rowId);
|
|
13
|
+
return row ? model.isSelected(rowId, row.original) : false;
|
|
14
|
+
}
|
|
10
15
|
return Boolean(ctx.rowSelectionState[rowId]);
|
|
11
16
|
}
|
|
12
17
|
function toggleRowSelectionById(rowId) {
|
|
18
|
+
const model = ctx.props.rowSelectionModel;
|
|
19
|
+
if (model) {
|
|
20
|
+
const row = ctx.allRows.find((r) => r.id === rowId);
|
|
21
|
+
if (!row)
|
|
22
|
+
return;
|
|
23
|
+
model.toggle(rowId, row.original, !model.isSelected(rowId, row.original));
|
|
24
|
+
return;
|
|
25
|
+
}
|
|
13
26
|
ctx.grid.setRowSelection((prev) => ({ ...prev, [rowId]: !prev[rowId] }));
|
|
14
27
|
}
|
|
15
28
|
function toggleSelectAllRows() {
|
|
16
|
-
|
|
17
|
-
|
|
29
|
+
setSelectAllRows(ctx.headerSelectionState !== "all");
|
|
30
|
+
}
|
|
31
|
+
/**
|
|
32
|
+
* Select or clear every row, for the header checkbox and for
|
|
33
|
+
* `api.selectAllRows()`.
|
|
34
|
+
*/
|
|
35
|
+
function setSelectAllRows(select) {
|
|
36
|
+
// An external model decides what "all" means - possibly a million rows
|
|
37
|
+
// the grid has never seen - so it gets the intent, not a row list.
|
|
38
|
+
if (ctx.props.rowSelectionModel) {
|
|
39
|
+
ctx.props.rowSelectionModel.toggleAll(select);
|
|
40
|
+
return;
|
|
41
|
+
}
|
|
42
|
+
// Placeholder rows are excluded: there is no row there to select yet,
|
|
43
|
+
// and ticking one would leave a selected id that never resolves.
|
|
44
|
+
const selectable = ctx.allRows.filter((row) => !isGroupRow(row) && !ctx.placeholderStateOf(row));
|
|
18
45
|
ctx.grid.setRowSelection((prev) => {
|
|
19
46
|
const next = { ...prev };
|
|
20
47
|
for (const row of selectable) {
|
|
@@ -495,7 +522,7 @@ export function createSelection(ctx) {
|
|
|
495
522
|
// Also commit a fill-handle drag if one was in progress - the user
|
|
496
523
|
// released the mouse, time to apply the pattern.
|
|
497
524
|
if (ctx.fillDrag)
|
|
498
|
-
ctx.onFillPointerUp();
|
|
525
|
+
ctx.onFillPointerUp(event);
|
|
499
526
|
if (ctx.moveDrag)
|
|
500
527
|
ctx.onMovePointerUp(event);
|
|
501
528
|
}
|
|
@@ -646,6 +673,7 @@ export function createSelection(ctx) {
|
|
|
646
673
|
isRowSelected,
|
|
647
674
|
toggleRowSelectionById,
|
|
648
675
|
toggleSelectAllRows,
|
|
676
|
+
setSelectAllRows,
|
|
649
677
|
setActiveCell,
|
|
650
678
|
scrollActiveCellIntoView,
|
|
651
679
|
setSelection,
|