@svgrid/grid 3.0.5 → 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 +28 -7
- package/dist/GridMenus.svelte +34 -4
- package/dist/SvGrid.controller.svelte.d.ts +21 -3
- package/dist/SvGrid.controller.svelte.js +205 -50
- package/dist/SvGrid.css +127 -2
- package/dist/SvGrid.svelte +223 -38
- package/dist/SvGrid.types.d.ts +77 -4
- 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 +81 -31
- package/dist/cdn/{GridMenus-CID62rlI.js → GridMenus-C-NtjlrJ.js} +150 -141
- 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-CGoWz-87.js → server-block-cache-DIqb3VZn.js} +4 -0
- package/dist/cdn/{src-jcFMkBnN.js → src-CgoeSM8k.js} +4697 -4131
- package/dist/cdn/{src-Bklofsad.js → src-DfwxB1TH.js} +4727 -4161
- package/dist/cdn/svgrid.js +17 -17
- package/dist/cdn/svgrid.svelte-external.js +17 -17
- package/dist/cdn/{validate-C7Rn_Bns.js → validate-AZoD8BoR.js} +6 -2
- 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 +365 -25
- package/dist/editing.js +24 -0
- package/dist/grid-messages.d.ts +4 -0
- package/dist/grid-messages.js +4 -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 +1 -1
- 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 +6 -0
- package/dist/row-resize.js +22 -1
- package/dist/selection.js +1 -1
- package/dist/server-block-cache.d.ts +5 -0
- package/dist/server-block-cache.js +8 -0
- package/dist/server-data-source.d.ts +35 -3
- package/dist/server-data-source.js +11 -2
- package/dist/server.d.ts +1 -1
- package/dist/sparkline.js +7 -5
- package/dist/svgrid-wrapper.types.d.ts +33 -0
- package/dist/validate.js +9 -1
- package/package.json +6 -1
- package/src/GridMenus.svelte +34 -4
- package/src/SvGrid.controller.svelte.ts +206 -53
- package/src/SvGrid.css +127 -2
- package/src/SvGrid.svelte +223 -38
- package/src/SvGrid.types.ts +77 -4
- 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 +85 -27
- 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.tick-repair.test.ts +287 -0
- package/src/core.ts +374 -26
- package/src/editing.test.ts +52 -0
- package/src/editing.ts +25 -0
- package/src/grid-messages.test.ts +7 -0
- package/src/grid-messages.ts +10 -0
- package/src/headless.ts +24 -0
- package/src/history.test.ts +49 -1
- package/src/history.ts +48 -2
- package/src/index.ts +2 -0
- 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 +6 -0
- package/src/row-resize.ts +24 -1
- package/src/selection.ts +1 -1
- package/src/server-block-cache.test.ts +27 -0
- package/src/server-block-cache.ts +13 -0
- package/src/server-data-source.infinite.test.ts +62 -0
- package/src/server-data-source.test.ts +19 -0
- package/src/server-data-source.ts +48 -4
- package/src/server.ts +2 -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 +1 -1
- 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-seam.svelte.test.ts +16 -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 +1 -1
- package/src/test-setup.ts +12 -0
- package/src/transaction.test.ts +58 -0
- package/src/validate.ts +7 -1
- package/dist/cdn/GridMenus-DLL-qZeu.js +0 -635
package/README.md
CHANGED
|
@@ -17,7 +17,7 @@
|
|
|
17
17
|
<p align="center">
|
|
18
18
|
<a href="https://svgrid.com">Website</a> ·
|
|
19
19
|
<a href="https://svgrid.com/docs/">Docs</a> ·
|
|
20
|
-
<a href="https://svgrid.com/demos/">
|
|
20
|
+
<a href="https://svgrid.com/demos/">400+ Demos</a> ·
|
|
21
21
|
<a href="https://svgrid.com/pricing/">Pricing</a> ·
|
|
22
22
|
<a href="https://svgrid.com/roadmap/">Roadmap</a>
|
|
23
23
|
</p>
|
|
@@ -78,7 +78,7 @@ all wire up the moment you turn on the matching prop.
|
|
|
78
78
|
|---|---|
|
|
79
79
|
| **License** | MIT, free for commercial use |
|
|
80
80
|
| **Requires** | `svelte@^5` (peer dependency), Node 16+ |
|
|
81
|
-
| **Bundle (gzip)** | ~2 KB headless core, ~
|
|
81
|
+
| **Bundle (gzip)** | ~2.7 KB headless core, ~98 KB full `<SvGrid>` + ~10 KB CSS; charts, date pickers, menus and export load as separate chunks on first use |
|
|
82
82
|
| **Types** | Bundled, no `@types/` package needed |
|
|
83
83
|
| **Module format** | ESM, plus a CDN build at `@svgrid/grid/cdn` |
|
|
84
84
|
| **SSR** | Works under SvelteKit SSR and static builds |
|
|
@@ -90,7 +90,10 @@ all wire up the moment you turn on the matching prop.
|
|
|
90
90
|
- **Filtering** - Excel-style filter menu, inline filter row, set / value-list filter, locale-aware matching, between operators.
|
|
91
91
|
- **Editing** - 15 built-in `editorType`s (text, number, date, datetime, time, select, rich-select with typeahead, autocomplete, textarea, color, checkbox, list, chips, rating, password), plus `date-native` / `datetime-native` / `time-native` to opt out of the rich pickers, and a `cellEditor` snippet slot for anything custom.
|
|
92
92
|
- **Selection** - cell-range click+drag and Shift+arrows, copy/paste as TSV, Excel-style fill handle, row selection.
|
|
93
|
-
- **Views** - row grouping with aggregation, tree data, master/detail, full-width detail rows,
|
|
93
|
+
- **Views** - row grouping with aggregation, tree data, master/detail, full-width detail rows, and a
|
|
94
|
+
spreadsheet layout mode (merged cells, per-cell borders). Formula cells here go through an adapter
|
|
95
|
+
seam you point at your own `hyperformula` install; the built-in formula engine and `<SvSheet>` are
|
|
96
|
+
in the Suite edition of `@svgrid/enterprise`.
|
|
94
97
|
- **Layout** - row + column pinning, sticky header + first column, header drag-to-reorder, autosize, keyboard-accessible column sizing, zebra rows, responsive mode.
|
|
95
98
|
- **Data operations** - find in grid (Ctrl+F), undo / redo, transaction API, optimistic updates, server-side data with sort / filter / paging / infinite-scroll pushdown (lazy grouping, tree, pivot and transactions on the server are in `@svgrid/enterprise`).
|
|
96
99
|
- **AI helpers, free** - natural-language filter, smart fill, summarize, classify, anomaly detection, and "chart this". Model-agnostic: register one provider, nothing is bundled.
|
|
@@ -131,7 +134,7 @@ import {
|
|
|
131
134
|
```
|
|
132
135
|
|
|
133
136
|
- **Headless** - drive `createSvGrid` and the row-model factories, render your own markup.
|
|
134
|
-
`getGrid*A11yProps` helpers keep custom markup accessible. About 2 KB gzipped.
|
|
137
|
+
`getGrid*A11yProps` helpers keep custom markup accessible. About 2.7 KB gzipped.
|
|
135
138
|
- **Render-ready** - `<SvGrid />` is a complete, accessible, themeable grid you configure with props.
|
|
136
139
|
|
|
137
140
|
Compatibility aliases are provided for the framework-neutral names: `createGrid`, `createGridState`,
|
|
@@ -141,7 +144,7 @@ Compatibility aliases are provided for the framework-neutral names: `createGrid`
|
|
|
141
144
|
|
|
142
145
|
SvGrid publishes an [MCP server](https://www.npmjs.com/package/@svgrid/mcp) plus
|
|
143
146
|
[llms.txt](https://svgrid.com/llms.txt) and [llms-full.txt](https://svgrid.com/llms-full.txt), so Claude,
|
|
144
|
-
Cursor, and Zed answer with accurate, version-pinned APIs and all
|
|
147
|
+
Cursor, and Zed answer with accurate, version-pinned APIs and all 400+ demo sources as context rather
|
|
145
148
|
than hallucinated methods.
|
|
146
149
|
|
|
147
150
|
```bash
|
|
@@ -158,12 +161,30 @@ editing, virtualization, **server-side data** (paging, infinite block scroll, so
|
|
|
158
161
|
**AI helpers** all ship in the free package. The optional [`@svgrid/enterprise`](https://www.npmjs.com/package/@svgrid/enterprise) pack layers
|
|
159
162
|
on the export- and analytics-heavy features teams tend to need last:
|
|
160
163
|
|
|
164
|
+
The pack sells in two editions, both covering unlimited production apps.
|
|
165
|
+
|
|
166
|
+
**Grid edition:**
|
|
167
|
+
|
|
161
168
|
- **Excel / PDF / CSV / TSV / HTML export** plus paginated print.
|
|
162
169
|
- **Excel / CSV / TSV / JSON import** with auto-mapping and per-row validation.
|
|
163
170
|
- **Pivot tables** with a drag-and-drop pivot Designer.
|
|
164
171
|
- **Kanban board, scheduler / calendar and Gantt renderers** for the `board`, `scheduler` and `gantt` props.
|
|
172
|
+
- **Server-side row model** for lazy grouping, tree, pivot and transactions.
|
|
173
|
+
|
|
174
|
+
**Suite edition** adds everything above plus:
|
|
175
|
+
|
|
176
|
+
- **A real spreadsheet.** `<SvSheet>` and the `<sv-sheet>` element over a built-in formula engine
|
|
177
|
+
with cross-sheet references, named ranges, dynamic arrays and spill, iterative calculation, and
|
|
178
|
+
dependency-graph recalculation. No `hyperformula` needed, and no runtime dependency.
|
|
179
|
+
- **Spreadsheet file formats.** Read and write `.xlsx`, `.xls`, `.ods` and `.csv`, with formulas,
|
|
180
|
+
merges, frozen panes, named ranges and charts surviving the round trip.
|
|
181
|
+
- **SvGrid Studio.** The designer, the code generator and the SQL data sources.
|
|
182
|
+
|
|
183
|
+
Both editions come with a 30-day evaluation period: every feature runs without a key, and under a
|
|
184
|
+
key that does not cover it, with a watermark and a console message about the Enterprise package. `licenseCovers('spreadsheet')` tells you which
|
|
185
|
+
side of the line the current key is on, if you would rather hide an entry point than let it nudge.
|
|
165
186
|
|
|
166
|
-
OSS projects receive
|
|
187
|
+
OSS projects receive a Suite key free. See [Pricing](https://svgrid.com/pricing/).
|
|
167
188
|
|
|
168
189
|
## Also in the box
|
|
169
190
|
|
|
@@ -203,7 +224,7 @@ Full detail: [SvGrid vs AG Grid vs TanStack Table](https://svgrid.com/docs/help/
|
|
|
203
224
|
## Documentation
|
|
204
225
|
|
|
205
226
|
- [Getting started](https://svgrid.com/docs/getting-started/) - end-to-end walkthrough.
|
|
206
|
-
- [
|
|
227
|
+
- [400+ live demos](https://svgrid.com/demos/) - copy-paste recipes for every feature.
|
|
207
228
|
- [Why headless?](https://svgrid.com/docs/why-headless/) - when to compose vs. drop in.
|
|
208
229
|
- [Theming and Tailwind](https://svgrid.com/docs/help/tailwind/) - re-skin via `--sg-*` tokens and dark mode.
|
|
209
230
|
- [Accessibility](https://svgrid.com/docs/help/accessibility/) - the WAI-ARIA grid pattern as implemented.
|
package/dist/GridMenus.svelte
CHANGED
|
@@ -214,6 +214,19 @@
|
|
|
214
214
|
});
|
|
215
215
|
}
|
|
216
216
|
|
|
217
|
+
/**
|
|
218
|
+
* Whether a column's active filter operator is one of the set operators,
|
|
219
|
+
* read at event time from component state: the condition input's focus
|
|
220
|
+
* and blur handlers cannot depend on a template `@const`, because blur
|
|
221
|
+
* also fires while the popover is being torn down, after that const's
|
|
222
|
+
* effect is gone.
|
|
223
|
+
*/
|
|
224
|
+
function isSetOperatorFor(colId: string): boolean {
|
|
225
|
+
const column = allColumns.find((c) => c.id === colId);
|
|
226
|
+
const op = filterMenuValues[colId]?.operator ?? defaultOperatorFor(column);
|
|
227
|
+
return op === "in" || op === "notIn";
|
|
228
|
+
}
|
|
229
|
+
|
|
217
230
|
/** Enter anywhere in the panel means "done" - filtering is already live. */
|
|
218
231
|
function onFilterPanelKeydown(event: KeyboardEvent) {
|
|
219
232
|
if (event.key !== "Enter" || event.shiftKey) return;
|
|
@@ -286,8 +299,23 @@
|
|
|
286
299
|
const saveComment = $derived(ctrl.saveComment);
|
|
287
300
|
const removeComment = $derived(ctrl.removeComment);
|
|
288
301
|
const closeCommentEditor = $derived(ctrl.closeCommentEditor);
|
|
302
|
+
|
|
303
|
+
function onContextMenuKeydown(event: KeyboardEvent) {
|
|
304
|
+
// Escape closes the context menu, the way every spreadsheet and desktop
|
|
305
|
+
// app does. The backdrop closes it on a click, but a keyboard user who
|
|
306
|
+
// opened it (Shift+F10, the Menu key) otherwise has no way out, and the
|
|
307
|
+
// menu sits over the sheet swallowing every other key. Handled at the
|
|
308
|
+
// window so it works whatever holds focus while the menu is open.
|
|
309
|
+
if (contextMenuFor && (event.key === "Escape" || event.key === "Esc")) {
|
|
310
|
+
event.preventDefault();
|
|
311
|
+
event.stopPropagation();
|
|
312
|
+
closeContextMenu();
|
|
313
|
+
}
|
|
314
|
+
}
|
|
289
315
|
</script>
|
|
290
316
|
|
|
317
|
+
<svelte:window onkeydown={onContextMenuKeydown} />
|
|
318
|
+
|
|
291
319
|
{#if tooltip}
|
|
292
320
|
<!-- Custom hover tooltip. Floats above the grid; positioned by
|
|
293
321
|
showTooltipFor(). Notes and column tooltips both surface here. -->
|
|
@@ -396,10 +424,12 @@
|
|
|
396
424
|
: menuActiveOperator === "regex"
|
|
397
425
|
? "Pattern..."
|
|
398
426
|
: "Filter value..."}
|
|
399
|
-
onfocus={
|
|
400
|
-
|
|
401
|
-
|
|
402
|
-
onblur={
|
|
427
|
+
onfocus={(event) => {
|
|
428
|
+
if (isSetOperatorFor(colId)) onSetOpFilterFocus(event.currentTarget as HTMLInputElement, colId);
|
|
429
|
+
}}
|
|
430
|
+
onblur={() => {
|
|
431
|
+
if (isSetOperatorFor(colId)) closeInSuggest();
|
|
432
|
+
}}
|
|
403
433
|
oninput={(event) => {
|
|
404
434
|
const input = event.currentTarget as HTMLInputElement;
|
|
405
435
|
updateFilterMenuValue(colId, input.value);
|
|
@@ -78,6 +78,7 @@ export declare function createSvGridController<TFeatures extends TableFeatures =
|
|
|
78
78
|
history: SharedHistoryStep[];
|
|
79
79
|
historyPtr: number;
|
|
80
80
|
historyGroupId: string | undefined;
|
|
81
|
+
historyTag: unknown;
|
|
81
82
|
historyVersion: number;
|
|
82
83
|
tooltip: {
|
|
83
84
|
text: string;
|
|
@@ -116,6 +117,14 @@ export declare function createSvGridController<TFeatures extends TableFeatures =
|
|
|
116
117
|
columnVirtualizerVersion: number;
|
|
117
118
|
gridStateVersion: number;
|
|
118
119
|
readonly selectionColumnWidth: number;
|
|
120
|
+
readonly detailToggleColumnWidth: number;
|
|
121
|
+
readonly detailToggleColumnLeft: number;
|
|
122
|
+
readonly showDetailToggleEffective: boolean;
|
|
123
|
+
readonly systemColumnsWidth: number;
|
|
124
|
+
readonly detailToggleOf: (row: Row<TData>, rowIndex: number) => {
|
|
125
|
+
open: boolean;
|
|
126
|
+
toggle: () => void;
|
|
127
|
+
} | null;
|
|
119
128
|
readonly rowNumberColumnWidth: number;
|
|
120
129
|
readonly showRowNumbersEffective: boolean;
|
|
121
130
|
readonly filterOperatorOptions: import("./SvGrid.types.js").FilterOption[];
|
|
@@ -241,7 +250,7 @@ export declare function createSvGridController<TFeatures extends TableFeatures =
|
|
|
241
250
|
colDropSide: "before" | "after" | null;
|
|
242
251
|
rowDragActive: boolean;
|
|
243
252
|
rowDropIndex: number | null;
|
|
244
|
-
rowDropSide: "before" | "after" | null;
|
|
253
|
+
rowDropSide: "before" | "after" | "into" | null;
|
|
245
254
|
readonly onRowDragStart: (e: DragEvent, rowIndex: number) => void;
|
|
246
255
|
readonly onRowDragOver: (e: DragEvent, rowIndex: number) => void;
|
|
247
256
|
readonly onRowDragLeave: (rowIndex: number) => void;
|
|
@@ -525,6 +534,13 @@ export declare function createSvGridController<TFeatures extends TableFeatures =
|
|
|
525
534
|
readonly frozenRowList: Row<TData>[];
|
|
526
535
|
readonly frozenBandHeight: number;
|
|
527
536
|
readonly frozenRowTop: (i: number) => number;
|
|
537
|
+
readonly stickyGroupRows: {
|
|
538
|
+
row: Row<TData>;
|
|
539
|
+
rowIndex: number;
|
|
540
|
+
top: number;
|
|
541
|
+
size: number;
|
|
542
|
+
}[];
|
|
543
|
+
readonly stickyTopOfRow: (rowIndex: number) => number | undefined;
|
|
528
544
|
/** Record the height the user dragged a row to. */
|
|
529
545
|
readonly setRowResizeHeight: (index: number, height: number | null) => void;
|
|
530
546
|
readonly isRowCollapsed: (index: number) => boolean;
|
|
@@ -534,6 +550,8 @@ export declare function createSvGridController<TFeatures extends TableFeatures =
|
|
|
534
550
|
readonly autosizeColumnByUser: (columnId: string) => void;
|
|
535
551
|
/** A row's dragged height, or undefined when it has not been resized. */
|
|
536
552
|
readonly rowResizeHeightPx: (index: number) => number | undefined;
|
|
553
|
+
/** The height row i is drawn at: dragged, measured, detail, declared or default. */
|
|
554
|
+
readonly rowSizePxOf: (i: number) => number;
|
|
537
555
|
readonly virtualRowTotalSize: number;
|
|
538
556
|
readonly virtualRowStart: number;
|
|
539
557
|
readonly virtualRowEnd: number;
|
|
@@ -672,11 +690,11 @@ export declare function createSvGridController<TFeatures extends TableFeatures =
|
|
|
672
690
|
columnResizable(columnId: string): boolean;
|
|
673
691
|
readonly readCellRaw: (rowIndex: number, columnId: string) => unknown;
|
|
674
692
|
readonly writeCellRaw: (rowIndex: number, columnId: string, value: unknown) => void;
|
|
675
|
-
readonly applyFillPattern: () => void;
|
|
693
|
+
readonly applyFillPattern: (toggled?: boolean) => void;
|
|
676
694
|
readonly clearSelectedCellValues: () => void;
|
|
677
695
|
readonly startFillDrag: (event: PointerEvent, rowIndex: number, colIndex: number) => void;
|
|
678
696
|
readonly onFillPointerMove: (event: PointerEvent) => void;
|
|
679
|
-
readonly onFillPointerUp: () => void;
|
|
697
|
+
readonly onFillPointerUp: (event?: PointerEvent) => void;
|
|
680
698
|
readonly fillDownToNeighbour: () => void;
|
|
681
699
|
readonly isOnMoveGrabStrip: (cell: HTMLElement, rowIndex: number, colIndex: number, clientX: number, clientY: number) => boolean;
|
|
682
700
|
readonly startMoveDrag: (event: PointerEvent, rowIndex: number, colIndex: number) => boolean;
|
|
@@ -327,7 +327,11 @@ export function createSvGridController(rawProps, domIdBase) {
|
|
|
327
327
|
// grows with rows x columns and a Map lookup per cell per render.
|
|
328
328
|
let editedCellValues = $state.raw({});
|
|
329
329
|
const UNDO_LIMIT = 200;
|
|
330
|
-
|
|
330
|
+
// Raw: pushHistory always assigns a fresh array and nothing renders from a
|
|
331
|
+
// step, so deep proxies would cost 200 wrapped objects for nothing. It also
|
|
332
|
+
// keeps a consumer's `tag` the object it passed, which a proxy would not be:
|
|
333
|
+
// the sheet shell compares tags by identity.
|
|
334
|
+
let history = $state.raw([]);
|
|
331
335
|
/** Index in `history` of the LAST applied step. -1 means "nothing applied".
|
|
332
336
|
* undo() decrements; redo() increments. New edits truncate everything
|
|
333
337
|
* past the pointer (the classic "you can't redo after editing" rule). */
|
|
@@ -340,6 +344,9 @@ export function createSvGridController(rawProps, domIdBase) {
|
|
|
340
344
|
* $state: it is written and read synchronously inside a single call and
|
|
341
345
|
* nothing renders from it. */
|
|
342
346
|
let historyGroupId = undefined;
|
|
347
|
+
/** The consumer's mark for the steps recorded from now on (`api.setHistoryTag`);
|
|
348
|
+
* not $state for the same reason. */
|
|
349
|
+
let historyTag = undefined;
|
|
343
350
|
let tooltip = $state(null);
|
|
344
351
|
let tooltipTimer = null;
|
|
345
352
|
// ---- Find-in-grid ----------------------------------------------------
|
|
@@ -410,7 +417,28 @@ export function createSvGridController(rawProps, domIdBase) {
|
|
|
410
417
|
// catch-all gridStateVersion, so navigation doesn't rebuild 1M rows.
|
|
411
418
|
let dataStateVersion = $state(0);
|
|
412
419
|
const selectionColumnWidth = 44;
|
|
420
|
+
const detailToggleColumnWidth = 36;
|
|
413
421
|
const rowNumberColumnWidth = $derived(props.rowNumberWidth ?? 56);
|
|
422
|
+
const showDetailToggleEffective = $derived(props.showDetailToggle === true);
|
|
423
|
+
/**
|
|
424
|
+
* What the chevron on a row does, or null when the row has no detail to
|
|
425
|
+
* open: a detail row itself, a group or placeholder on a server model, a
|
|
426
|
+
* row `hasDetail` rules out, or a grid with nothing to call.
|
|
427
|
+
*/
|
|
428
|
+
function detailToggleOf(row, rowIndex) {
|
|
429
|
+
const data = row.original;
|
|
430
|
+
if (props.isDetailRow?.(data, rowIndex))
|
|
431
|
+
return null;
|
|
432
|
+
const sg = props.serverGroup;
|
|
433
|
+
if (sg) {
|
|
434
|
+
if (!sg.toggleDetail || sg.isGroup(data) || (sg.hasDetail && !sg.hasDetail(data)))
|
|
435
|
+
return null;
|
|
436
|
+
return { open: sg.detailOpen?.(data) ?? false, toggle: () => sg.toggleDetail(data) };
|
|
437
|
+
}
|
|
438
|
+
if (!props.onDetailToggle || (props.hasDetail && !props.hasDetail(data)))
|
|
439
|
+
return null;
|
|
440
|
+
return { open: props.isDetailOpen?.(data) ?? false, toggle: () => props.onDetailToggle(data, rowIndex) };
|
|
441
|
+
}
|
|
414
442
|
// A per-row `rowHeight` function already supplies heights, so auto-measuring
|
|
415
443
|
// would fight it. Fixed numbers are fine - they become the pre-measure estimate.
|
|
416
444
|
const autoRowHeightOn = $derived(props.autoRowHeight === true && typeof props.rowHeight !== "function");
|
|
@@ -563,6 +591,12 @@ export function createSvGridController(rawProps, domIdBase) {
|
|
|
563
591
|
const showRowSelectionEffective = $derived(props.showRowSelection ??
|
|
564
592
|
((props.selectionMode ?? "both") === "row" ||
|
|
565
593
|
(props.selectionMode ?? "both") === "both"));
|
|
594
|
+
/** The system columns to the left of the data: row numbers, selection, the detail toggle. */
|
|
595
|
+
const systemColumnsWidth = $derived((showRowNumbersEffective ? rowNumberColumnWidth : 0) +
|
|
596
|
+
(showRowSelectionEffective ? selectionColumnWidth : 0) +
|
|
597
|
+
(showDetailToggleEffective ? detailToggleColumnWidth : 0));
|
|
598
|
+
/** Where the detail-toggle column sticks: after the row numbers and the selection column. */
|
|
599
|
+
const detailToggleColumnLeft = $derived((showRowNumbersEffective ? rowNumberColumnWidth : 0) + (showRowSelectionEffective ? selectionColumnWidth : 0));
|
|
566
600
|
// `selectable` is the shortcut alias, so it wins over the fine-grained prop,
|
|
567
601
|
// which in turn wins over `selectionMode` - the same precedence the other
|
|
568
602
|
// shortcuts use. Unlike them it starts ON (selectionMode defaults to 'both'),
|
|
@@ -661,35 +695,41 @@ export function createSvGridController(rawProps, domIdBase) {
|
|
|
661
695
|
// the row-model pipeline is read before any later prop change could apply.
|
|
662
696
|
// svelte-ignore state_referenced_locally
|
|
663
697
|
const treeDataConfig = props.treeData;
|
|
698
|
+
// Pagination is intentionally NOT in the grid's row-model pipeline. The
|
|
699
|
+
// wrapper applies its own filters (filterMenuValues, globalFilter,
|
|
700
|
+
// valueFilters) on top of `grid.getRowModel().rows`. If pagination ran
|
|
701
|
+
// first, those filters would only see the visible page. Instead the wrapper
|
|
702
|
+
// paginates last - see `allRows` below.
|
|
703
|
+
//
|
|
704
|
+
// Built ONCE. Both inputs are captured at mount, and the stages keep state
|
|
705
|
+
// between runs: the sorted and filtered stages hold their last output so a
|
|
706
|
+
// data tick can repair it instead of recomputing (core.ts, `replacedRowsOf`).
|
|
707
|
+
// This used to be a getter that built fresh stages on every read, which
|
|
708
|
+
// threw that cache away on each run - a live feed re-sorted 100k rows on
|
|
709
|
+
// every tick and the row-model memo's `cachedPipeline` never matched.
|
|
710
|
+
const rowModels = {
|
|
711
|
+
coreRowModel: createCoreRowModel(),
|
|
712
|
+
filteredRowModel: createFilteredRowModel(),
|
|
713
|
+
// External-sort mode: pass the rows through untouched so the consumer
|
|
714
|
+
// controls ordering (e.g. tree data that must preserve hierarchy).
|
|
715
|
+
sortedRowModel: externalSortEnabled
|
|
716
|
+
? passthroughSortedRowModel
|
|
717
|
+
: createSortedRowModel(sortFns),
|
|
718
|
+
// Tree nesting replaces grouping when `treeData` is set - a row cannot
|
|
719
|
+
// be both a hierarchy node and bucketed under a group banner.
|
|
720
|
+
groupedRowModel: treeDataConfig
|
|
721
|
+
? createTreeRowModel({
|
|
722
|
+
parentField: treeDataConfig.parentField,
|
|
723
|
+
idField: treeDataConfig.idField,
|
|
724
|
+
})
|
|
725
|
+
: createGroupedRowModel(),
|
|
726
|
+
expandedRowModel: createExpandedRowModel(),
|
|
727
|
+
};
|
|
664
728
|
const grid = createSvGrid({
|
|
665
729
|
get _features() {
|
|
666
730
|
return resolveEffectiveFeatures();
|
|
667
731
|
},
|
|
668
|
-
|
|
669
|
-
// Pagination is intentionally NOT in the grid's row-model pipeline.
|
|
670
|
-
// The wrapper applies its own filters (filterMenuValues, globalFilter,
|
|
671
|
-
// valueFilters) on top of `grid.getRowModel().rows`. If pagination
|
|
672
|
-
// ran first, those filters would only see the visible page. Instead
|
|
673
|
-
// the wrapper paginates last - see `allRows` below.
|
|
674
|
-
return {
|
|
675
|
-
coreRowModel: createCoreRowModel(),
|
|
676
|
-
filteredRowModel: createFilteredRowModel(),
|
|
677
|
-
// External-sort mode: pass the rows through untouched so the consumer
|
|
678
|
-
// controls ordering (e.g. tree data that must preserve hierarchy).
|
|
679
|
-
sortedRowModel: externalSortEnabled
|
|
680
|
-
? passthroughSortedRowModel
|
|
681
|
-
: createSortedRowModel(sortFns),
|
|
682
|
-
// Tree nesting replaces grouping when `treeData` is set - a row cannot
|
|
683
|
-
// be both a hierarchy node and bucketed under a group banner.
|
|
684
|
-
groupedRowModel: treeDataConfig
|
|
685
|
-
? createTreeRowModel({
|
|
686
|
-
parentField: treeDataConfig.parentField,
|
|
687
|
-
idField: treeDataConfig.idField,
|
|
688
|
-
})
|
|
689
|
-
: createGroupedRowModel(),
|
|
690
|
-
expandedRowModel: createExpandedRowModel(),
|
|
691
|
-
};
|
|
692
|
-
},
|
|
732
|
+
_rowModels: rowModels,
|
|
693
733
|
get columns() {
|
|
694
734
|
return internalColumns;
|
|
695
735
|
},
|
|
@@ -1091,10 +1131,8 @@ export function createSvGridController(rawProps, domIdBase) {
|
|
|
1091
1131
|
});
|
|
1092
1132
|
/** Cumulative pixel offsets for left- and right-pinned columns. */
|
|
1093
1133
|
const pinnedOffsets = $derived.by(function pinnedOffsets_d() {
|
|
1094
|
-
const rowNumberWidth = showRowNumbersEffective ? rowNumberColumnWidth : 0;
|
|
1095
|
-
const selectionWidth = showRowSelectionEffective ? selectionColumnWidth : 0;
|
|
1096
1134
|
const left = {};
|
|
1097
|
-
let leftAcc =
|
|
1135
|
+
let leftAcc = systemColumnsWidth;
|
|
1098
1136
|
for (const id of effectivePinning.left) {
|
|
1099
1137
|
// Hidden pinned columns don't render, so they must contribute neither an
|
|
1100
1138
|
// offset entry nor width - otherwise the next visible pinned column is
|
|
@@ -1611,16 +1649,13 @@ export function createSvGridController(rawProps, domIdBase) {
|
|
|
1611
1649
|
// so consumers don't see spurious callbacks during re-renders.
|
|
1612
1650
|
let lastCellRangeSerialized = "";
|
|
1613
1651
|
$effect(() => {
|
|
1614
|
-
|
|
1615
|
-
|
|
1616
|
-
|
|
1617
|
-
|
|
1618
|
-
|
|
1619
|
-
|
|
1620
|
-
|
|
1621
|
-
Math.max(a.colIndex, f.colIndex),
|
|
1622
|
-
]]
|
|
1623
|
-
: [];
|
|
1652
|
+
// Every rectangle, the committed ones a Ctrl+click added and the
|
|
1653
|
+
// active one last, the order getSelectionRects gives: a consumer's
|
|
1654
|
+
// status bar and shading cover the whole selection, not only its last
|
|
1655
|
+
// range. Depend on selectionRanges so a change to the committed set
|
|
1656
|
+
// re-runs this too.
|
|
1657
|
+
void selectionRanges;
|
|
1658
|
+
const ranges = getSelectionRects().map((r) => [r.minRow, r.minCol, r.maxRow, r.maxCol]);
|
|
1624
1659
|
const serialized = JSON.stringify(ranges);
|
|
1625
1660
|
if (serialized === lastCellRangeSerialized)
|
|
1626
1661
|
return;
|
|
@@ -2651,6 +2686,16 @@ export function createSvGridController(rawProps, domIdBase) {
|
|
|
2651
2686
|
return total;
|
|
2652
2687
|
});
|
|
2653
2688
|
/** The declared or dragged height of one row; measured under auto height. */
|
|
2689
|
+
/** A detail row's declared height, or null when the row is not one (or none is declared). */
|
|
2690
|
+
function detailRowHeightPx(i) {
|
|
2691
|
+
const dh = props.detailRowHeight;
|
|
2692
|
+
if (dh == null || !props.isDetailRow)
|
|
2693
|
+
return null;
|
|
2694
|
+
const row = allRows[i];
|
|
2695
|
+
if (!row || !props.isDetailRow(row.original, i))
|
|
2696
|
+
return null;
|
|
2697
|
+
return typeof dh === "function" ? dh(row.original) : dh;
|
|
2698
|
+
}
|
|
2654
2699
|
function rowSizePxOf(i) {
|
|
2655
2700
|
if (isRowCollapsed(i))
|
|
2656
2701
|
return 0;
|
|
@@ -2659,6 +2704,9 @@ export function createSvGridController(rawProps, domIdBase) {
|
|
|
2659
2704
|
const own = rowResizeHeightPx(i);
|
|
2660
2705
|
if (own != null)
|
|
2661
2706
|
return own;
|
|
2707
|
+
const detail = detailRowHeightPx(i);
|
|
2708
|
+
if (detail != null)
|
|
2709
|
+
return detail;
|
|
2662
2710
|
const rh = props.rowHeight;
|
|
2663
2711
|
return typeof rh === "function" ? rh(i) : (rh ?? 30);
|
|
2664
2712
|
}
|
|
@@ -2669,10 +2717,91 @@ export function createSvGridController(rawProps, domIdBase) {
|
|
|
2669
2717
|
top += rowSizePxOf(k);
|
|
2670
2718
|
return top;
|
|
2671
2719
|
}
|
|
2720
|
+
const NO_STICKY = [];
|
|
2721
|
+
/** Whether a row is a group and how deep it sits, for any of the three tree sources. */
|
|
2722
|
+
function rowGroupLevel(row) {
|
|
2723
|
+
const sg = props.serverGroup;
|
|
2724
|
+
if (sg) {
|
|
2725
|
+
const data = row.original;
|
|
2726
|
+
return { group: sg.isGroup(data), level: sg.level(data) };
|
|
2727
|
+
}
|
|
2728
|
+
// Client grouping and tree data: an expandable row is the group (a tree
|
|
2729
|
+
// row is a data row too, which is why isGroupRow() excludes it, but for
|
|
2730
|
+
// the band it is the parent its children scroll under).
|
|
2731
|
+
if (typeof row.getCanExpand === "function" && row.getCanExpand())
|
|
2732
|
+
return { group: true, level: row.depth ?? 0 };
|
|
2733
|
+
return { group: false, level: row.depth ?? 0 };
|
|
2734
|
+
}
|
|
2735
|
+
/** The first row whose bottom edge is under the header, in row-index space. */
|
|
2736
|
+
const firstRowUnderHeader = $derived.by(function firstRowUnderHeader_d() {
|
|
2737
|
+
if (allRows.length === 0)
|
|
2738
|
+
return -1;
|
|
2739
|
+
if (rowVirtualizationEnabled) {
|
|
2740
|
+
virtualizer.version;
|
|
2741
|
+
const offset = virtualizer.getState().scrollOffset;
|
|
2742
|
+
const hit = virtualRows.find((it) => it.end > offset);
|
|
2743
|
+
return hit ? hit.index : -1;
|
|
2744
|
+
}
|
|
2745
|
+
rowResizeVersion;
|
|
2746
|
+
autoRowHeightVersion;
|
|
2747
|
+
const top = scrollMetrics.scrollTop;
|
|
2748
|
+
let acc = 0;
|
|
2749
|
+
let i = 0;
|
|
2750
|
+
while (i < allRows.length - 1 && acc + rowSizePxOf(i) <= top) {
|
|
2751
|
+
acc += rowSizePxOf(i);
|
|
2752
|
+
i += 1;
|
|
2753
|
+
}
|
|
2754
|
+
return i;
|
|
2755
|
+
});
|
|
2756
|
+
const stickyGroupRows = $derived.by(function stickyGroupRows_d() {
|
|
2757
|
+
if (!props.stickyGroupRows)
|
|
2758
|
+
return NO_STICKY;
|
|
2759
|
+
const first = firstRowUnderHeader;
|
|
2760
|
+
if (first < 0)
|
|
2761
|
+
return NO_STICKY;
|
|
2762
|
+
const head = allRows[first];
|
|
2763
|
+
if (!head)
|
|
2764
|
+
return NO_STICKY;
|
|
2765
|
+
// A group row at level L, or a leaf at level L, has its ancestors at
|
|
2766
|
+
// levels L-1 .. 0, each the nearest group row above at that level.
|
|
2767
|
+
let want = rowGroupLevel(head).level - 1;
|
|
2768
|
+
if (want < 0)
|
|
2769
|
+
return NO_STICKY;
|
|
2770
|
+
const found = [];
|
|
2771
|
+
for (let i = first - 1; i >= frozenRowCount && want >= 0; i -= 1) {
|
|
2772
|
+
const row = allRows[i];
|
|
2773
|
+
const info = rowGroupLevel(row);
|
|
2774
|
+
if (info.group && info.level === want) {
|
|
2775
|
+
found.push({ row, rowIndex: i });
|
|
2776
|
+
want -= 1;
|
|
2777
|
+
}
|
|
2778
|
+
}
|
|
2779
|
+
if (found.length === 0)
|
|
2780
|
+
return NO_STICKY;
|
|
2781
|
+
found.reverse();
|
|
2782
|
+
rowResizeVersion;
|
|
2783
|
+
autoRowHeightVersion;
|
|
2784
|
+
let top = headerHeight + frozenBandHeight;
|
|
2785
|
+
return found.map((f) => {
|
|
2786
|
+
const at = top;
|
|
2787
|
+
const size = rowSizePxOf(f.rowIndex);
|
|
2788
|
+
top += size;
|
|
2789
|
+
return { ...f, top: at, size };
|
|
2790
|
+
});
|
|
2791
|
+
});
|
|
2792
|
+
/** The band's height under virtualization, taken off the top spacer. */
|
|
2793
|
+
const stickyBandHeight = $derived(rowVirtualizationEnabled ? stickyGroupRows.reduce((sum, s) => sum + s.size, 0) : 0);
|
|
2794
|
+
/** Without virtualization the real row sticks: its top, or undefined. */
|
|
2795
|
+
function stickyTopOfRow(rowIndex) {
|
|
2796
|
+
if (rowVirtualizationEnabled || stickyGroupRows.length === 0)
|
|
2797
|
+
return undefined;
|
|
2798
|
+
return stickyGroupRows.find((s) => s.rowIndex === rowIndex)?.top;
|
|
2799
|
+
}
|
|
2672
2800
|
// Spacer heights in DOM space. With scaling inert these equal the original
|
|
2673
|
-
// virtualRowStart / virtualRowBottomSpacer. The frozen band
|
|
2674
|
-
// before the spacer whatever the window shows,
|
|
2675
|
-
|
|
2801
|
+
// virtualRowStart / virtualRowBottomSpacer. The frozen band and the sticky
|
|
2802
|
+
// group band are in the flow before the spacer whatever the window shows,
|
|
2803
|
+
// so they come off the spacer.
|
|
2804
|
+
const rowTopSpacer = $derived(Math.max(virtualRowStart - rowOffsetAdjustment - frozenBandHeight - stickyBandHeight, 0));
|
|
2676
2805
|
const rowBottomSpacer = $derived(Math.max(rowDomTotalSize - (virtualRowEnd - rowOffsetAdjustment), 0));
|
|
2677
2806
|
const virtualColumns = $derived.by(function virtualColumns_d() {
|
|
2678
2807
|
columnVirtualizerVersion;
|
|
@@ -2757,9 +2886,7 @@ export function createSvGridController(rawProps, domIdBase) {
|
|
|
2757
2886
|
* `fittedColumnWidths`, so the overflow decision settles in the same
|
|
2758
2887
|
* render where fit-scaling lands - no race, no scrollbar flash. */
|
|
2759
2888
|
const hasHorizontalOverflow = $derived.by(function hasHorizontalOverflow_d() {
|
|
2760
|
-
|
|
2761
|
-
(showRowSelectionEffective ? selectionColumnWidth : 0);
|
|
2762
|
-
let total = fixedCols;
|
|
2889
|
+
let total = systemColumnsWidth;
|
|
2763
2890
|
for (const column of allColumns)
|
|
2764
2891
|
total += getColumnWidth(column.id);
|
|
2765
2892
|
// +1 to tolerate sub-pixel rounding residue from `fitColumns`.
|
|
@@ -3208,8 +3335,12 @@ export function createSvGridController(rawProps, domIdBase) {
|
|
|
3208
3335
|
: typeof rh === "function"
|
|
3209
3336
|
? rh
|
|
3210
3337
|
: (rh ?? 30);
|
|
3211
|
-
|
|
3338
|
+
// Detail rows have their own height; only when the props say so does
|
|
3339
|
+
// the per-index lookup replace the uniform fast path.
|
|
3340
|
+
const detailOn = props.detailRowHeight != null && !!props.isDetailRow;
|
|
3341
|
+
const estimateSize = rowResizeHeights.size > 0 || collapsedRows.size > 0 || detailOn
|
|
3212
3342
|
? (index) => rowResizeHeightPx(index) ??
|
|
3343
|
+
detailRowHeightPx(index) ??
|
|
3213
3344
|
(typeof base === "function" ? base(index) : base)
|
|
3214
3345
|
: base;
|
|
3215
3346
|
virtualizer.setOptions({
|
|
@@ -3320,6 +3451,18 @@ export function createSvGridController(rawProps, domIdBase) {
|
|
|
3320
3451
|
// onto a server.
|
|
3321
3452
|
if (props.rowSelectionModel)
|
|
3322
3453
|
return props.rowSelectionModel.headerState();
|
|
3454
|
+
// Nothing checked is the common case and needs no walk: this derived
|
|
3455
|
+
// re-runs on every data change, and on a 100k-row live feed the filter
|
|
3456
|
+
// below was 30 ms per tick spent to conclude "none".
|
|
3457
|
+
let anyChecked = false;
|
|
3458
|
+
for (const id in rowSelectionState) {
|
|
3459
|
+
if (rowSelectionState[id]) {
|
|
3460
|
+
anyChecked = true;
|
|
3461
|
+
break;
|
|
3462
|
+
}
|
|
3463
|
+
}
|
|
3464
|
+
if (!anyChecked)
|
|
3465
|
+
return "none";
|
|
3323
3466
|
const selectable = allRows.filter((row) => !isGroupRow(row) && !placeholderStateOf(row));
|
|
3324
3467
|
if (!selectable.length)
|
|
3325
3468
|
return "none";
|
|
@@ -3367,8 +3510,6 @@ export function createSvGridController(rawProps, domIdBase) {
|
|
|
3367
3510
|
const cols = grid.getAllColumns().filter((c) => !hiddenColumns[c.id] && !hiddenByGroupCollapse[c.id] && !collapsedColumns[c.id]);
|
|
3368
3511
|
if (!cols.length)
|
|
3369
3512
|
return null;
|
|
3370
|
-
const rowNumberWidth = showRowNumbersEffective ? rowNumberColumnWidth : 0;
|
|
3371
|
-
const selectionWidth = showRowSelectionEffective ? selectionColumnWidth : 0;
|
|
3372
3513
|
// Reserve the custom vertical scrollbar's width when it's visible. It
|
|
3373
3514
|
// overlays the right 16px of the viewport (absolute, z-index 40) and
|
|
3374
3515
|
// does NOT shrink clientWidth, so without this the last fitted column
|
|
@@ -3376,8 +3517,7 @@ export function createSvGridController(rawProps, domIdBase) {
|
|
|
3376
3517
|
// is hidden behind the opaque scrollbar.
|
|
3377
3518
|
const scrollbarWidth = hasVerticalOverflow ? 16 : 0;
|
|
3378
3519
|
const target = (scrollContainer?.clientWidth ?? 0) -
|
|
3379
|
-
|
|
3380
|
-
selectionWidth -
|
|
3520
|
+
systemColumnsWidth -
|
|
3381
3521
|
scrollbarWidth;
|
|
3382
3522
|
if (target <= 0)
|
|
3383
3523
|
return null;
|
|
@@ -3779,6 +3919,8 @@ export function createSvGridController(rawProps, domIdBase) {
|
|
|
3779
3919
|
set historyPtr(v) { historyPtr = v; },
|
|
3780
3920
|
get historyGroupId() { return historyGroupId; },
|
|
3781
3921
|
set historyGroupId(v) { historyGroupId = v; },
|
|
3922
|
+
get historyTag() { return historyTag; },
|
|
3923
|
+
set historyTag(v) { historyTag = v; },
|
|
3782
3924
|
get historyVersion() { return historyVersion; },
|
|
3783
3925
|
set historyVersion(v) { historyVersion = v; },
|
|
3784
3926
|
get tooltip() { return tooltip; },
|
|
@@ -3815,6 +3957,11 @@ export function createSvGridController(rawProps, domIdBase) {
|
|
|
3815
3957
|
get gridStateVersion() { return gridStateVersion; },
|
|
3816
3958
|
set gridStateVersion(v) { gridStateVersion = v; },
|
|
3817
3959
|
get selectionColumnWidth() { return selectionColumnWidth; },
|
|
3960
|
+
get detailToggleColumnWidth() { return detailToggleColumnWidth; },
|
|
3961
|
+
get detailToggleColumnLeft() { return detailToggleColumnLeft; },
|
|
3962
|
+
get showDetailToggleEffective() { return showDetailToggleEffective; },
|
|
3963
|
+
get systemColumnsWidth() { return systemColumnsWidth; },
|
|
3964
|
+
get detailToggleOf() { return detailToggleOf; },
|
|
3818
3965
|
get rowNumberColumnWidth() { return rowNumberColumnWidth; },
|
|
3819
3966
|
get showRowNumbersEffective() { return showRowNumbersEffective; },
|
|
3820
3967
|
get filterOperatorOptions() { return filterOperatorOptions; },
|
|
@@ -4234,6 +4381,8 @@ export function createSvGridController(rawProps, domIdBase) {
|
|
|
4234
4381
|
get frozenRowList() { return frozenRowList; },
|
|
4235
4382
|
get frozenBandHeight() { return frozenBandHeight; },
|
|
4236
4383
|
get frozenRowTop() { return frozenRowTop; },
|
|
4384
|
+
get stickyGroupRows() { return stickyGroupRows; },
|
|
4385
|
+
get stickyTopOfRow() { return stickyTopOfRow; },
|
|
4237
4386
|
/** Record the height the user dragged a row to. */
|
|
4238
4387
|
get setRowResizeHeight() { return setRowResizeHeight; },
|
|
4239
4388
|
get isRowCollapsed() { return isRowCollapsed; },
|
|
@@ -4246,6 +4395,12 @@ export function createSvGridController(rawProps, domIdBase) {
|
|
|
4246
4395
|
rowResizeVersion;
|
|
4247
4396
|
return rowResizeHeightPx;
|
|
4248
4397
|
},
|
|
4398
|
+
/** The height row i is drawn at: dragged, measured, detail, declared or default. */
|
|
4399
|
+
get rowSizePxOf() {
|
|
4400
|
+
rowResizeVersion;
|
|
4401
|
+
autoRowHeightVersion;
|
|
4402
|
+
return rowSizePxOf;
|
|
4403
|
+
},
|
|
4249
4404
|
get virtualRowTotalSize() { return virtualRowTotalSize; },
|
|
4250
4405
|
get virtualRowStart() { return virtualRowStart; },
|
|
4251
4406
|
get virtualRowEnd() { return virtualRowEnd; },
|