@svgrid/grid 2.6.20 → 2.6.22
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 +62 -0
- package/README.md +22 -0
- package/dist/GridMenus.svelte +17 -12
- package/dist/SvGrid.controller.svelte.d.ts +14 -8
- package/dist/SvGrid.controller.svelte.js +214 -74
- package/dist/SvGrid.css +1 -1
- package/dist/SvGrid.svelte +112 -57
- package/dist/SvGrid.types.d.ts +191 -1
- package/dist/ai.d.ts +28 -0
- package/dist/ai.js +6 -0
- package/dist/cdn/{GridMenus-B0F9iBrG.js → GridMenus-BuoBPqxx.js} +137 -132
- package/dist/cdn/GridMenus-n4llxoOI.js +494 -0
- package/dist/cdn/column-resize-DsfNXMom.js +102 -0
- package/dist/cdn/row-resize-BRcimkUT.js +95 -0
- package/dist/cdn/{src-Cd0tearp.js → src-C9Hihx1W.js} +3497 -3487
- package/dist/cdn/{src-B1TdiyS8.js → src-D1lXwq1l.js} +8258 -8248
- package/dist/cdn/svgrid.js +10 -8
- package/dist/cdn/svgrid.svelte-external.js +10 -8
- package/dist/cdn/validate-_CDJzgIo.js +75 -0
- package/dist/cell-formatting.d.ts +2 -0
- package/dist/cell-formatting.js +2 -0
- package/dist/chart-export.d.ts +1 -0
- package/dist/chart.d.ts +31 -5
- package/dist/chart.js +9 -3
- package/dist/column-groups.js +1 -1
- package/dist/column-resize.d.ts +46 -0
- package/dist/column-resize.js +205 -0
- package/dist/columns.d.ts +0 -3
- package/dist/columns.js +0 -57
- package/dist/core.d.ts +216 -4
- package/dist/core.js +532 -119
- package/dist/createTree.svelte.d.ts +3 -0
- package/dist/createTree.svelte.js +1 -0
- package/dist/datetime/date-core.d.ts +2 -0
- package/dist/datetime/date-restrict.d.ts +1 -0
- package/dist/datetime/timezone.d.ts +1 -0
- package/dist/dock-manager-model.d.ts +3 -0
- package/dist/dock-manager-model.js +1 -0
- package/dist/dock-model.d.ts +6 -0
- package/dist/dock-model.js +3 -0
- package/dist/editor-contract.d.ts +1 -0
- package/dist/filtering/excel-filters.js +28 -0
- package/dist/group-display.d.ts +1 -1
- package/dist/index.d.ts +2 -1
- package/dist/index.js +6 -0
- package/dist/list-option.d.ts +1 -0
- package/dist/menus.js +1 -1
- package/dist/positioning.d.ts +2 -0
- package/dist/row-resize.d.ts +11 -0
- package/dist/row-resize.js +7 -1
- package/dist/scheduler-ical.d.ts +1 -0
- package/dist/scheduler-model.d.ts +1 -0
- package/dist/selection.js +9 -0
- package/dist/spreadsheet.d.ts +1 -1
- package/dist/spreadsheet.js +1 -1
- package/dist/summaries.js +22 -0
- package/dist/svgrid-wrapper.types.d.ts +5 -0
- package/dist/toast-store.svelte.d.ts +4 -0
- package/dist/validate.d.ts +50 -0
- package/dist/validate.js +187 -0
- package/package.json +4 -1
- package/src/GridMenus.svelte +17 -12
- package/src/SvGrid.controller.svelte.ts +223 -76
- package/src/SvGrid.css +1 -1
- package/src/SvGrid.svelte +112 -57
- package/src/SvGrid.types.ts +191 -1
- package/src/ai.ts +28 -0
- package/src/cell-formatting.ts +2 -0
- package/src/chart-export.ts +1 -0
- package/src/chart.ts +31 -5
- package/src/column-groups.ts +1 -1
- package/src/column-resize.test.ts +381 -0
- package/src/column-resize.ts +227 -0
- package/src/columns.test.ts +0 -103
- package/src/columns.ts +0 -58
- package/src/core.aggregate.test.ts +134 -0
- package/src/core.filter.test.ts +156 -0
- package/src/core.grouping.test.ts +146 -0
- package/src/core.row-shape.test.ts +119 -0
- package/src/core.rowmodel-cache.test.ts +121 -0
- package/src/core.sort.test.ts +293 -0
- package/src/core.ts +723 -119
- package/src/createTree.svelte.ts +3 -0
- package/src/datetime/date-core.ts +2 -0
- package/src/datetime/date-restrict.ts +1 -0
- package/src/datetime/timezone.ts +1 -0
- package/src/dock-manager-model.ts +3 -0
- package/src/dock-model.ts +6 -0
- package/src/editor-contract.ts +1 -0
- package/src/filtering/excel-filters.ts +30 -0
- package/src/filtering/normalize-fast-path.test.ts +104 -0
- package/src/group-display.ts +1 -1
- package/src/index.ts +12 -1
- package/src/list-option.ts +1 -0
- package/src/menus.ts +1 -1
- package/src/positioning.ts +2 -0
- package/src/resize-props.test.ts +361 -0
- package/src/row-resize.test.ts +31 -0
- package/src/row-resize.ts +21 -3
- package/src/scheduler-ical.ts +1 -0
- package/src/scheduler-model.ts +1 -0
- package/src/selection.ts +9 -0
- package/src/spreadsheet.ts +1 -1
- package/src/summaries.ts +21 -0
- package/src/svgrid-wrapper.types.ts +5 -0
- package/src/svgrid.summaries.test.ts +217 -0
- package/src/toast-store.svelte.ts +4 -0
- package/src/validate.test.ts +207 -0
- package/src/validate.ts +269 -0
- package/dist/cdn/GridMenus-IHK_l7m6.js +0 -489
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import { applyGroupAggregate, applyRowPredicate, compileExcelFilter, getAdvancedFilterEngine, normalizeForFilter, createColumnVirtualizer, createCoreRowModel, createExpandedRowModel, createFilteredRowModel, createGroupedRowModel, createTreeRowModel, createSvelteVirtualizer, createSortedRowModel, createSvGrid, getGridCellDomId, sortFns, } from "./index.js";
|
|
2
2
|
import { createRowScrollScaling, resolveMaxDomHeight, } from "./virtualization/scroll-scaling.js";
|
|
3
3
|
import { buildPreMeasureItems } from "./virtualization/virtualizer.js";
|
|
4
|
+
import { DEV } from "esm-env";
|
|
4
5
|
import "./sv-grid-scrollbar.js";
|
|
5
6
|
import { computeColumnStat, formatsNeedingStats, formatNeedsStats, } from "./conditional-formatting.js";
|
|
6
7
|
import { rawToNumber, } from "./SvGrid.helpers.js";
|
|
@@ -274,9 +275,6 @@ export function createSvGridController(rawProps, domIdBase) {
|
|
|
274
275
|
let editorSelectAll = true;
|
|
275
276
|
/** Per-column width overrides set by the resize handles. */
|
|
276
277
|
let columnWidths = $state({});
|
|
277
|
-
let resizingColumnId = $state(null);
|
|
278
|
-
let resizeStartX = 0;
|
|
279
|
-
let resizeStartWidth = 0;
|
|
280
278
|
const MIN_COLUMN_WIDTH = 40;
|
|
281
279
|
/** Columns pinned to the left or right edge of the grid (sticky positioning).
|
|
282
280
|
* Seeded from `props.initialColumnPinning` so demos / tests can show the
|
|
@@ -293,7 +291,26 @@ export function createSvGridController(rawProps, domIdBase) {
|
|
|
293
291
|
let dataStateVersion = $state(0);
|
|
294
292
|
const selectionColumnWidth = 44;
|
|
295
293
|
const rowNumberColumnWidth = $derived(props.rowNumberWidth ?? 56);
|
|
296
|
-
|
|
294
|
+
// A per-row `rowHeight` function already supplies heights, so auto-measuring
|
|
295
|
+
// would fight it. Fixed numbers are fine - they become the pre-measure estimate.
|
|
296
|
+
const autoRowHeightOn = $derived(props.autoRowHeight === true && typeof props.rowHeight !== "function");
|
|
297
|
+
// Auto height measures the row from its content, so a dragged height would be
|
|
298
|
+
// overwritten on the next measurement pass. Let auto height win rather than
|
|
299
|
+
// having the two fight.
|
|
300
|
+
const rowResizeOn = $derived(props.rowResize === true && !autoRowHeightOn);
|
|
301
|
+
/**
|
|
302
|
+
* The row-number gutter. Explicit `showRowNumbers` always wins; otherwise
|
|
303
|
+
* `rowResize` brings it in, because a resizable row needs a row header to
|
|
304
|
+
* grab - that is where the drag strip lives, and it is where a spreadsheet
|
|
305
|
+
* puts it. Dragging the edge of a data cell instead works but reads as an
|
|
306
|
+
* accident.
|
|
307
|
+
*
|
|
308
|
+
* Both derived above are declared here rather than beside the rest of the
|
|
309
|
+
* row-resize state further down: a `$derived` referenced before its
|
|
310
|
+
* declaration in a .svelte.ts silently compiles to an empty getter, so this
|
|
311
|
+
* gate would have read `undefined` and the gutter would never appear.
|
|
312
|
+
*/
|
|
313
|
+
const showRowNumbersEffective = $derived(props.showRowNumbers ?? rowResizeOn);
|
|
297
314
|
let columnMenuFor = $state(null);
|
|
298
315
|
let columnMenuTab = $state("general");
|
|
299
316
|
let columnMenuPos = $state({ x: 0, y: 0 });
|
|
@@ -317,11 +334,11 @@ export function createSvGridController(rawProps, domIdBase) {
|
|
|
317
334
|
let commentEditFor = $state(null);
|
|
318
335
|
let commentDraft = $state("");
|
|
319
336
|
let valueFilters = $state({});
|
|
320
|
-
const viewportWidth = $derived.by(()
|
|
337
|
+
const viewportWidth = $derived.by(function viewportWidth_d() {
|
|
321
338
|
viewportVersion;
|
|
322
339
|
return scrollContainer ? scrollContainer.clientWidth : 0;
|
|
323
340
|
});
|
|
324
|
-
const viewportHeight = $derived.by(()
|
|
341
|
+
const viewportHeight = $derived.by(function viewportHeight_d() {
|
|
325
342
|
viewportVersion;
|
|
326
343
|
return scrollContainer ? scrollContainer.clientHeight : 0;
|
|
327
344
|
});
|
|
@@ -343,7 +360,7 @@ export function createSvGridController(rawProps, domIdBase) {
|
|
|
343
360
|
const hb = column.columnDef?.hideBelow;
|
|
344
361
|
return hb != null && viewportWidth > 0 && viewportWidth < hb;
|
|
345
362
|
}
|
|
346
|
-
const scrollMetrics = $derived.by(()
|
|
363
|
+
const scrollMetrics = $derived.by(function scrollMetrics_d() {
|
|
347
364
|
scrollVersion;
|
|
348
365
|
viewportVersion;
|
|
349
366
|
// Track the virtualizers' versions too so when data loads or row /
|
|
@@ -377,7 +394,7 @@ export function createSvGridController(rawProps, domIdBase) {
|
|
|
377
394
|
* - virtualizer.getTotalSize(): correct at initial load (before first paint)
|
|
378
395
|
* - scrollMetrics.scrollHeight: correct after detail rows expand (DOM is live,
|
|
379
396
|
* ResizeObserver on gridRootEl already bumps scrollVersion at that point) */
|
|
380
|
-
const hasVerticalOverflow = $derived.by(()
|
|
397
|
+
const hasVerticalOverflow = $derived.by(function hasVerticalOverflow_d() {
|
|
381
398
|
virtualizer.version;
|
|
382
399
|
const virtualizerSize = virtualizer.getTotalSize();
|
|
383
400
|
// scrollMetrics.scrollHeight is 0 before initial paint; once the table
|
|
@@ -407,6 +424,14 @@ export function createSvGridController(rawProps, domIdBase) {
|
|
|
407
424
|
props.enableCellSelection ??
|
|
408
425
|
((props.selectionMode ?? "both") === "cell" ||
|
|
409
426
|
(props.selectionMode ?? "both") === "both"));
|
|
427
|
+
// The aggregate footer row. `summary` is the shortcut alias, so it wins over
|
|
428
|
+
// the fine-grained prop - the same precedence `selectable` uses.
|
|
429
|
+
//
|
|
430
|
+
// It starts OFF. It used to default ON, which meant a plain
|
|
431
|
+
// `<SvGrid {data} {columns} />` grew a totals row nobody asked for, and every
|
|
432
|
+
// caller that did not want one had to say so: 375 call sites in this repo
|
|
433
|
+
// passed `enableRowSummaries={false}` against 6 that opted in.
|
|
434
|
+
const rowSummariesEnabled = $derived(props.summary ?? props.enableRowSummaries ?? false);
|
|
410
435
|
// Internal source-of-truth for data and column defs. Seeded from props and
|
|
411
436
|
// re-synced whenever the parent passes a new array; the imperative API
|
|
412
437
|
// mutates these so add/remove operations don't need a callback round-trip.
|
|
@@ -627,7 +652,7 @@ export function createSvGridController(rawProps, domIdBase) {
|
|
|
627
652
|
// Declared here rather than beside the other pagination/state derivations:
|
|
628
653
|
// the auto-group column pipeline below reads it, and a `const` used above its
|
|
629
654
|
// declaration is a type error even though `$derived` is lazy enough at runtime.
|
|
630
|
-
const groupingColumns = $derived.by(()
|
|
655
|
+
const groupingColumns = $derived.by(function groupingColumns_d() {
|
|
631
656
|
gridStateVersion;
|
|
632
657
|
return grid.getState().grouping ?? [];
|
|
633
658
|
});
|
|
@@ -648,7 +673,7 @@ export function createSvGridController(rawProps, domIdBase) {
|
|
|
648
673
|
* any other column. They carry no `field` - their cell content is resolved
|
|
649
674
|
* from the row's group state at render time.
|
|
650
675
|
*/
|
|
651
|
-
const autoGroupColumns = $derived.by(()
|
|
676
|
+
const autoGroupColumns = $derived.by(function autoGroupColumns_d() {
|
|
652
677
|
if (!groupColumnMode)
|
|
653
678
|
return [];
|
|
654
679
|
const sourceById = new Map(grid.getAllColumns().map((c) => [c.id, c]));
|
|
@@ -714,7 +739,7 @@ export function createSvGridController(rawProps, domIdBase) {
|
|
|
714
739
|
depth: columnId === "__autoGroup" ? depth : 0,
|
|
715
740
|
};
|
|
716
741
|
}
|
|
717
|
-
const allColumns = $derived.by(()
|
|
742
|
+
const allColumns = $derived.by(function allColumns_d() {
|
|
718
743
|
let raw = grid
|
|
719
744
|
.getAllColumns()
|
|
720
745
|
.filter((column) => !hiddenColumns[column.id] &&
|
|
@@ -762,7 +787,7 @@ export function createSvGridController(rawProps, domIdBase) {
|
|
|
762
787
|
return [...left, ...unpinned, ...right];
|
|
763
788
|
});
|
|
764
789
|
/** Header groups reordered to match {@link allColumns}. */
|
|
765
|
-
const headerGroups = $derived.by(()
|
|
790
|
+
const headerGroups = $derived.by(function headerGroups_d() {
|
|
766
791
|
const base = grid.getHeaderGroups();
|
|
767
792
|
if (!base.length)
|
|
768
793
|
return base;
|
|
@@ -788,7 +813,7 @@ export function createSvGridController(rawProps, domIdBase) {
|
|
|
788
813
|
}
|
|
789
814
|
return [{ id: base[0].id, headers }];
|
|
790
815
|
});
|
|
791
|
-
const groupHeaderRows = $derived.by(()
|
|
816
|
+
const groupHeaderRows = $derived.by(function groupHeaderRows_d() {
|
|
792
817
|
const userCols = props.columns ?? [];
|
|
793
818
|
// 1. Find max depth in the user-provided column tree.
|
|
794
819
|
function maxDepth(defs) {
|
|
@@ -896,7 +921,7 @@ export function createSvGridController(rawProps, domIdBase) {
|
|
|
896
921
|
return rows;
|
|
897
922
|
});
|
|
898
923
|
/** Cumulative pixel offsets for left- and right-pinned columns. */
|
|
899
|
-
const pinnedOffsets = $derived.by(()
|
|
924
|
+
const pinnedOffsets = $derived.by(function pinnedOffsets_d() {
|
|
900
925
|
const rowNumberWidth = showRowNumbersEffective ? rowNumberColumnWidth : 0;
|
|
901
926
|
const selectionWidth = showRowSelectionEffective ? selectionColumnWidth : 0;
|
|
902
927
|
const left = {};
|
|
@@ -941,7 +966,7 @@ export function createSvGridController(rawProps, domIdBase) {
|
|
|
941
966
|
const hasConditionalFormats = $derived((props.conditionalFormats?.length ?? 0) > 0);
|
|
942
967
|
// Per-column numeric min/max, needed only by colorScale / dataBar formats.
|
|
943
968
|
// Lazy: this derived never runs unless `conditionalFormats` is set.
|
|
944
|
-
const conditionalColumnStats = $derived.by(()
|
|
969
|
+
const conditionalColumnStats = $derived.by(function conditionalColumnStats_d() {
|
|
945
970
|
const map = new Map();
|
|
946
971
|
const formats = props.conditionalFormats;
|
|
947
972
|
if (!formats?.length || !formatsNeedingStats(formats))
|
|
@@ -981,14 +1006,14 @@ export function createSvGridController(rawProps, domIdBase) {
|
|
|
981
1006
|
}
|
|
982
1007
|
return map;
|
|
983
1008
|
});
|
|
984
|
-
const sortDirectionByColumn = $derived.by(()
|
|
1009
|
+
const sortDirectionByColumn = $derived.by(function sortDirectionByColumn_d() {
|
|
985
1010
|
gridStateVersion;
|
|
986
1011
|
const directions = {};
|
|
987
1012
|
for (const column of allColumns)
|
|
988
1013
|
directions[column.id] = column.getIsSorted();
|
|
989
1014
|
return directions;
|
|
990
1015
|
});
|
|
991
|
-
const paginationState = $derived.by(()
|
|
1016
|
+
const paginationState = $derived.by(function paginationState_d() {
|
|
992
1017
|
gridStateVersion;
|
|
993
1018
|
return grid.getState().pagination ?? { pageIndex: 0, pageSize: 10 };
|
|
994
1019
|
});
|
|
@@ -997,7 +1022,7 @@ export function createSvGridController(rawProps, domIdBase) {
|
|
|
997
1022
|
* compute the correct "X to Y of Z" range and total page count when
|
|
998
1023
|
* filters reduce the dataset.
|
|
999
1024
|
*/
|
|
1000
|
-
const allRowsBeforePagination = $derived.by(()
|
|
1025
|
+
const allRowsBeforePagination = $derived.by(function allRowsBeforePagination_d() {
|
|
1001
1026
|
// Depend on dataStateVersion (row-model-affecting store changes) NOT
|
|
1002
1027
|
// gridStateVersion - so moving the active cell / selection does not force
|
|
1003
1028
|
// this O(rows) pipeline to re-run. Filter-input state (globalFilter etc.)
|
|
@@ -1021,6 +1046,25 @@ export function createSvGridController(rawProps, domIdBase) {
|
|
|
1021
1046
|
.some((cell) => normalizeForFilter(String(cell.getValue() ?? ""), (props.filterLocale ?? props.localization?.locale))
|
|
1022
1047
|
.includes(needle)));
|
|
1023
1048
|
}
|
|
1049
|
+
/**
|
|
1050
|
+
* Resolve a column ONCE and return a reader for it.
|
|
1051
|
+
*
|
|
1052
|
+
* `getRowColumnValue` finds the column with a linear scan over every
|
|
1053
|
+
* column, which is fine for a one-off read and wrong inside a loop over
|
|
1054
|
+
* 100,000 rows - it made each filtered column cost O(rows x columns).
|
|
1055
|
+
* The id is fixed for the life of a filter, so the scan is hoisted here and
|
|
1056
|
+
* the row loop gets a closure that only reads.
|
|
1057
|
+
*
|
|
1058
|
+
* Falls back to the row's own accessor when the id names no column, which
|
|
1059
|
+
* is also what `getRowColumnValue` does - group rows override
|
|
1060
|
+
* `getCellValueByColumnId` to return their aggregate.
|
|
1061
|
+
*/
|
|
1062
|
+
const makeColumnReader = (columnId) => {
|
|
1063
|
+
const column = allColumns.find((entry) => entry.id === columnId);
|
|
1064
|
+
return column
|
|
1065
|
+
? (row) => getColumnBaseValue(row, column)
|
|
1066
|
+
: (row) => row.getCellValueByColumnId(columnId);
|
|
1067
|
+
};
|
|
1024
1068
|
// A single condition is "active" if it has the value(s) it needs.
|
|
1025
1069
|
const condActive = (op, value, valueTo) => {
|
|
1026
1070
|
if (op === "isBlank" || op === "isNotBlank")
|
|
@@ -1045,6 +1089,11 @@ export function createSvGridController(rawProps, domIdBase) {
|
|
|
1045
1089
|
// become compiled predicates before a single row is tested.
|
|
1046
1090
|
const compiledMenuFilters = menuFilters.map(([columnId, f]) => ({
|
|
1047
1091
|
columnId,
|
|
1092
|
+
// The column, resolved once. `getRowColumnValue` looks it up with a
|
|
1093
|
+
// linear scan of every column, and the id is fixed per filter, so
|
|
1094
|
+
// leaving that inside the row loop made it O(rows x columns) per
|
|
1095
|
+
// filtered column for no reason.
|
|
1096
|
+
readValue: makeColumnReader(columnId),
|
|
1048
1097
|
join: f.join,
|
|
1049
1098
|
a: condActive(f.operator, f.value, f.valueTo)
|
|
1050
1099
|
? compileCond(columnId, f.operator, f.value, f.valueTo)
|
|
@@ -1053,8 +1102,8 @@ export function createSvGridController(rawProps, domIdBase) {
|
|
|
1053
1102
|
? compileCond(columnId, f.operator2, f.value2 ?? "", f.valueTo2)
|
|
1054
1103
|
: null,
|
|
1055
1104
|
}));
|
|
1056
|
-
rows = rows.filter((row) => compiledMenuFilters.every(({
|
|
1057
|
-
const cellValue =
|
|
1105
|
+
rows = rows.filter((row) => compiledMenuFilters.every(({ readValue, join, a, b }) => {
|
|
1106
|
+
const cellValue = readValue(row);
|
|
1058
1107
|
const ra = a ? a(cellValue) : null;
|
|
1059
1108
|
const rb = b ? b(cellValue) : null;
|
|
1060
1109
|
if (ra === null)
|
|
@@ -1072,10 +1121,11 @@ export function createSvGridController(rawProps, domIdBase) {
|
|
|
1072
1121
|
const bucketEntries = valueFilterEntries.map(([columnId, allowed]) => ({
|
|
1073
1122
|
columnId,
|
|
1074
1123
|
allowed,
|
|
1124
|
+
readValue: makeColumnReader(columnId),
|
|
1075
1125
|
buckets: facetBucketsByColumn.get(columnId) ?? null,
|
|
1076
1126
|
}));
|
|
1077
|
-
rows = rows.filter((row) => bucketEntries.every(({
|
|
1078
|
-
const raw =
|
|
1127
|
+
rows = rows.filter((row) => bucketEntries.every(({ allowed, buckets, readValue }) => {
|
|
1128
|
+
const raw = readValue(row);
|
|
1079
1129
|
if (buckets) {
|
|
1080
1130
|
// Range-bucketed filter: find which bucket this row's value
|
|
1081
1131
|
// falls into and check whether that bucket's label is allowed.
|
|
@@ -1133,7 +1183,7 @@ export function createSvGridController(rawProps, domIdBase) {
|
|
|
1133
1183
|
* is active we page by DATA rows and reprint each page's ancestor banners.
|
|
1134
1184
|
* Null when grouping is off, so the flat path stays a cheap slice.
|
|
1135
1185
|
*/
|
|
1136
|
-
const groupedPage = $derived.by(()
|
|
1186
|
+
const groupedPage = $derived.by(function groupedPage_d() {
|
|
1137
1187
|
if (!paginationEnabled || externalPaginationEnabled)
|
|
1138
1188
|
return null;
|
|
1139
1189
|
if (!groupingColumns.length)
|
|
@@ -1202,7 +1252,7 @@ export function createSvGridController(rawProps, domIdBase) {
|
|
|
1202
1252
|
* the full dataset rather than the current page (see the comment above
|
|
1203
1253
|
* `_rowModels`).
|
|
1204
1254
|
*/
|
|
1205
|
-
const allRows = $derived.by(()
|
|
1255
|
+
const allRows = $derived.by(function allRows_d() {
|
|
1206
1256
|
const paged = (() => {
|
|
1207
1257
|
const rows = allRowsBeforePagination;
|
|
1208
1258
|
// External pagination: `data` already IS the current page - never slice.
|
|
@@ -1269,7 +1319,7 @@ export function createSvGridController(rawProps, domIdBase) {
|
|
|
1269
1319
|
const paginationTotalRows = $derived(externalPaginationEnabled ? (props.rowCount ?? 0) : paginatedRowTotal);
|
|
1270
1320
|
const paginationPageIndex = $derived(externalPaginationEnabled ? (props.pageIndex ?? 0) : paginationState.pageIndex);
|
|
1271
1321
|
const paginationPageSize = $derived(externalPaginationEnabled ? (props.pageSize ?? 10) : paginationState.pageSize);
|
|
1272
|
-
const rowSelectionState = $derived.by(()
|
|
1322
|
+
const rowSelectionState = $derived.by(function rowSelectionState_d() {
|
|
1273
1323
|
gridStateVersion;
|
|
1274
1324
|
return grid.getState().rowSelection ?? {};
|
|
1275
1325
|
});
|
|
@@ -1322,7 +1372,7 @@ export function createSvGridController(rawProps, domIdBase) {
|
|
|
1322
1372
|
const statusBarAggregates = $derived(typeof props.statusBar === "object" && props.statusBar.aggregates
|
|
1323
1373
|
? props.statusBar.aggregates
|
|
1324
1374
|
: ["count", "sum", "avg", "min", "max"]);
|
|
1325
|
-
const statusBarStats = $derived.by(()
|
|
1375
|
+
const statusBarStats = $derived.by(function statusBarStats_d() {
|
|
1326
1376
|
if (!statusBarEnabled)
|
|
1327
1377
|
return null;
|
|
1328
1378
|
const a = selectionRange.anchor;
|
|
@@ -1381,7 +1431,7 @@ export function createSvGridController(rawProps, domIdBase) {
|
|
|
1381
1431
|
const toolPanelEnabled = $derived(props.toolPanel === true);
|
|
1382
1432
|
// Every column (including hidden ones) in the user's current order, so the
|
|
1383
1433
|
// panel can toggle/reorder anything. Group columns are flagged live.
|
|
1384
|
-
const toolPanelColumns = $derived.by(()
|
|
1434
|
+
const toolPanelColumns = $derived.by(function toolPanelColumns_d() {
|
|
1385
1435
|
gridStateVersion;
|
|
1386
1436
|
const all = grid.getAllColumns();
|
|
1387
1437
|
if (!userColumnOrder.length)
|
|
@@ -1419,7 +1469,7 @@ export function createSvGridController(rawProps, domIdBase) {
|
|
|
1419
1469
|
// reveals. `a11y/grid-announcements.ts` documents what is deliberately left
|
|
1420
1470
|
// unsaid, and why saying it would make the grid talk over itself.
|
|
1421
1471
|
/** Data rows before any local filtering - the denominator in "12 of 250". */
|
|
1422
|
-
const unfilteredRowTotal = $derived.by(()
|
|
1472
|
+
const unfilteredRowTotal = $derived.by(function unfilteredRowTotal_d() {
|
|
1423
1473
|
dataStateVersion;
|
|
1424
1474
|
void internalData;
|
|
1425
1475
|
return grid.getRowModel().rows.length;
|
|
@@ -1497,7 +1547,7 @@ export function createSvGridController(rawProps, domIdBase) {
|
|
|
1497
1547
|
props.onPivotModeChange?.(next);
|
|
1498
1548
|
}
|
|
1499
1549
|
const pivotActive = $derived(!!pivotConfig && pivotModeOn && hasPivotEngine());
|
|
1500
|
-
const pivotResult = $derived.by(()
|
|
1550
|
+
const pivotResult = $derived.by(function pivotResult_d() {
|
|
1501
1551
|
if (!pivotActive || !pivotConfig)
|
|
1502
1552
|
return null;
|
|
1503
1553
|
const engine = getPivotEngine();
|
|
@@ -1575,7 +1625,7 @@ export function createSvGridController(rawProps, domIdBase) {
|
|
|
1575
1625
|
const h = col.columnDef.header;
|
|
1576
1626
|
return typeof h === "string" && h ? h : (col.columnDef.field ?? col.id);
|
|
1577
1627
|
};
|
|
1578
|
-
const chartableColumns = $derived.by(()
|
|
1628
|
+
const chartableColumns = $derived.by(function chartableColumns_d() {
|
|
1579
1629
|
const dims = [];
|
|
1580
1630
|
const measures = [];
|
|
1581
1631
|
for (const col of allColumns) {
|
|
@@ -1590,7 +1640,7 @@ export function createSvGridController(rawProps, domIdBase) {
|
|
|
1590
1640
|
}
|
|
1591
1641
|
return { dims, measures };
|
|
1592
1642
|
});
|
|
1593
|
-
const chartColumnDefaults = $derived.by(()
|
|
1643
|
+
const chartColumnDefaults = $derived.by(function chartColumnDefaults_d() {
|
|
1594
1644
|
const { dims, measures } = chartableColumns;
|
|
1595
1645
|
let dimId = dims[0]?.id ?? null;
|
|
1596
1646
|
let seriesId = null;
|
|
@@ -1963,7 +2013,7 @@ export function createSvGridController(rawProps, domIdBase) {
|
|
|
1963
2013
|
// the virtualizer's own (real) numbers take over.
|
|
1964
2014
|
const preMeasureRowHeight = $derived(typeof props.rowHeight === "number" ? props.rowHeight : 30);
|
|
1965
2015
|
const preMeasureViewport = $derived(typeof props.containerHeight === "number" ? props.containerHeight : 520);
|
|
1966
|
-
const virtualRows = $derived.by(()
|
|
2016
|
+
const virtualRows = $derived.by(function virtualRows_d() {
|
|
1967
2017
|
virtualizer.version;
|
|
1968
2018
|
const items = virtualizer.getVirtualItems();
|
|
1969
2019
|
if (items.length || allRows.length === 0)
|
|
@@ -1974,7 +2024,7 @@ export function createSvGridController(rawProps, domIdBase) {
|
|
|
1974
2024
|
// only, and it matches what the server produced, so hydration is clean.
|
|
1975
2025
|
return buildPreMeasureItems(allRows.length, preMeasureRowHeight, preMeasureViewport, props.overscan ?? 8);
|
|
1976
2026
|
});
|
|
1977
|
-
const virtualRowTotalSize = $derived.by(()
|
|
2027
|
+
const virtualRowTotalSize = $derived.by(function virtualRowTotalSize_d() {
|
|
1978
2028
|
virtualizer.version;
|
|
1979
2029
|
const size = virtualizer.getTotalSize();
|
|
1980
2030
|
// Keep the scroll height honest during the pre-measurement render, so the
|
|
@@ -2022,7 +2072,7 @@ export function createSvGridController(rawProps, domIdBase) {
|
|
|
2022
2072
|
// OWN committed scroll offset - not the live DOM scrollTop - so the spacer
|
|
2023
2073
|
// shift and the rendered window are always computed from the same state and
|
|
2024
2074
|
// can never skew by a frame (which would jitter at extreme scale).
|
|
2025
|
-
const rowOffsetAdjustment = $derived.by(()
|
|
2075
|
+
const rowOffsetAdjustment = $derived.by(function rowOffsetAdjustment_d() {
|
|
2026
2076
|
if (!rowScrollScalingActive)
|
|
2027
2077
|
return 0;
|
|
2028
2078
|
virtualizer.version;
|
|
@@ -2033,11 +2083,11 @@ export function createSvGridController(rawProps, domIdBase) {
|
|
|
2033
2083
|
// virtualRowStart / virtualRowBottomSpacer.
|
|
2034
2084
|
const rowTopSpacer = $derived(Math.max(virtualRowStart - rowOffsetAdjustment, 0));
|
|
2035
2085
|
const rowBottomSpacer = $derived(Math.max(rowDomTotalSize - (virtualRowEnd - rowOffsetAdjustment), 0));
|
|
2036
|
-
const virtualColumns = $derived.by(()
|
|
2086
|
+
const virtualColumns = $derived.by(function virtualColumns_d() {
|
|
2037
2087
|
columnVirtualizerVersion;
|
|
2038
2088
|
return columnVirtualizer.getVirtualItems();
|
|
2039
2089
|
});
|
|
2040
|
-
const virtualColumnTotalSize = $derived.by(()
|
|
2090
|
+
const virtualColumnTotalSize = $derived.by(function virtualColumnTotalSize_d() {
|
|
2041
2091
|
columnVirtualizerVersion;
|
|
2042
2092
|
return columnVirtualizer.getTotalSize();
|
|
2043
2093
|
});
|
|
@@ -2052,7 +2102,7 @@ export function createSvGridController(rawProps, domIdBase) {
|
|
|
2052
2102
|
return item;
|
|
2053
2103
|
});
|
|
2054
2104
|
};
|
|
2055
|
-
const renderedColumnItems = $derived.by(()
|
|
2105
|
+
const renderedColumnItems = $derived.by(function renderedColumnItems_d() {
|
|
2056
2106
|
if (!columnVirtualizationEnabled)
|
|
2057
2107
|
return allColumnItems();
|
|
2058
2108
|
// Column virtualization is ON by default and its virtualizer, like the row
|
|
@@ -2098,7 +2148,7 @@ export function createSvGridController(rawProps, domIdBase) {
|
|
|
2098
2148
|
const renderedColumns = $derived.by(() => renderedColumnItems
|
|
2099
2149
|
.map((item) => ({ item, column: allColumns[item.index] }))
|
|
2100
2150
|
.filter(hasRenderedColumn));
|
|
2101
|
-
const totalColumnWidth = $derived.by(()
|
|
2151
|
+
const totalColumnWidth = $derived.by(function totalColumnWidth_d() {
|
|
2102
2152
|
if (columnVirtualizationEnabled)
|
|
2103
2153
|
return virtualColumnTotalSize;
|
|
2104
2154
|
let total = 0;
|
|
@@ -2115,7 +2165,7 @@ export function createSvGridController(rawProps, domIdBase) {
|
|
|
2115
2165
|
* column instead is reactive to both `columnWidths` and
|
|
2116
2166
|
* `fittedColumnWidths`, so the overflow decision settles in the same
|
|
2117
2167
|
* render where fit-scaling lands - no race, no scrollbar flash. */
|
|
2118
|
-
const hasHorizontalOverflow = $derived.by(()
|
|
2168
|
+
const hasHorizontalOverflow = $derived.by(function hasHorizontalOverflow_d() {
|
|
2119
2169
|
const fixedCols = (showRowNumbersEffective ? rowNumberColumnWidth : 0) +
|
|
2120
2170
|
(showRowSelectionEffective ? selectionColumnWidth : 0);
|
|
2121
2171
|
let total = fixedCols;
|
|
@@ -2141,7 +2191,7 @@ export function createSvGridController(rawProps, domIdBase) {
|
|
|
2141
2191
|
* everything stays pixel-aligned. When virtualization is off this is a
|
|
2142
2192
|
* pass-through.
|
|
2143
2193
|
*/
|
|
2144
|
-
const groupHeaderRowsWindowed = $derived.by(()
|
|
2194
|
+
const groupHeaderRowsWindowed = $derived.by(function groupHeaderRowsWindowed_d() {
|
|
2145
2195
|
const base = groupHeaderRows;
|
|
2146
2196
|
if (!columnVirtualizationEnabled || base.length === 0)
|
|
2147
2197
|
return base;
|
|
@@ -2167,11 +2217,11 @@ export function createSvGridController(rawProps, domIdBase) {
|
|
|
2167
2217
|
return { ...row, cells };
|
|
2168
2218
|
});
|
|
2169
2219
|
});
|
|
2170
|
-
const activeCell = $derived.by(()
|
|
2220
|
+
const activeCell = $derived.by(function activeCell_d() {
|
|
2171
2221
|
gridStateVersion;
|
|
2172
2222
|
return (grid.getState().activeCell ?? { rowIndex: 0, colIndex: 0, cellId: null });
|
|
2173
2223
|
});
|
|
2174
|
-
const activeDescendantId = $derived.by(()
|
|
2224
|
+
const activeDescendantId = $derived.by(function activeDescendantId_d() {
|
|
2175
2225
|
const active = activeCell;
|
|
2176
2226
|
const inRows = active.rowIndex >= 0 && active.rowIndex < allRows.length;
|
|
2177
2227
|
const inCols = active.colIndex >= 0 && active.colIndex < allColumns.length;
|
|
@@ -2213,10 +2263,10 @@ export function createSvGridController(rawProps, domIdBase) {
|
|
|
2213
2263
|
* `null` above the cell limit - that case stays on the rAF-deferred effect,
|
|
2214
2264
|
* which keeps a huge grid painting before it totals.
|
|
2215
2265
|
*/
|
|
2216
|
-
const eagerSummaries = $derived.by(()
|
|
2266
|
+
const eagerSummaries = $derived.by(function eagerSummaries_d() {
|
|
2217
2267
|
if (!summarize)
|
|
2218
2268
|
return null;
|
|
2219
|
-
if (!
|
|
2269
|
+
if (!rowSummariesEnabled)
|
|
2220
2270
|
return null;
|
|
2221
2271
|
const rows = allRows;
|
|
2222
2272
|
const columns = allColumns;
|
|
@@ -2241,7 +2291,7 @@ export function createSvGridController(rawProps, domIdBase) {
|
|
|
2241
2291
|
void editedCellValues;
|
|
2242
2292
|
const rows = allRows;
|
|
2243
2293
|
const columns = allColumns;
|
|
2244
|
-
if (!
|
|
2294
|
+
if (!rowSummariesEnabled) {
|
|
2245
2295
|
deferredSummaries = {};
|
|
2246
2296
|
return;
|
|
2247
2297
|
}
|
|
@@ -2366,10 +2416,37 @@ export function createSvGridController(rawProps, domIdBase) {
|
|
|
2366
2416
|
// is the reactive signal instead, bumped only when a height actually changes.
|
|
2367
2417
|
const measuredRowHeights = new Map();
|
|
2368
2418
|
let autoRowHeightVersion = $state(0);
|
|
2369
|
-
// A per-row `rowHeight` function already supplies heights, so auto-measuring
|
|
2370
|
-
// would fight it. Fixed numbers are fine - they become the pre-measure estimate.
|
|
2371
|
-
const autoRowHeightOn = $derived(props.autoRowHeight === true && typeof props.rowHeight !== "function");
|
|
2372
2419
|
const autoRowHeightFallback = $derived(typeof props.rowHeight === "number" ? props.rowHeight : 30);
|
|
2420
|
+
// ----- Interactive row resize (`rowResize` prop) -----
|
|
2421
|
+
// Heights the user has dragged, by row index. A plain Map plus a version
|
|
2422
|
+
// counter, exactly like `measuredRowHeights` above and for the same reason:
|
|
2423
|
+
// the reset effect below has to read this collection to know whether there is
|
|
2424
|
+
// anything to clear, and if the collection were reactive that read would make
|
|
2425
|
+
// every resize re-trigger the reset and wipe the height it just stored.
|
|
2426
|
+
const rowResizeHeights = new Map();
|
|
2427
|
+
let rowResizeVersion = $state(0);
|
|
2428
|
+
function setRowResizeHeight(index, height) {
|
|
2429
|
+
if (!rowResizeOn || !Number.isFinite(index) || height <= 0)
|
|
2430
|
+
return;
|
|
2431
|
+
rowResizeHeights.set(index, Math.round(height));
|
|
2432
|
+
rowResizeVersion += 1;
|
|
2433
|
+
}
|
|
2434
|
+
/** A user-dragged height for this row, or undefined when it has not been
|
|
2435
|
+
* resized. Read by the view AND by the virtualizer's `estimateSize`. */
|
|
2436
|
+
function rowResizeHeightPx(index) {
|
|
2437
|
+
return rowResizeOn ? rowResizeHeights.get(index) : undefined;
|
|
2438
|
+
}
|
|
2439
|
+
// A row index means a different row once the data changes, so keeping the
|
|
2440
|
+
// heights would size new rows by the old ones - the same reasoning as the
|
|
2441
|
+
// measured-height reset below.
|
|
2442
|
+
$effect(() => {
|
|
2443
|
+
void allRows.length;
|
|
2444
|
+
void internalData;
|
|
2445
|
+
if (rowResizeHeights.size === 0)
|
|
2446
|
+
return;
|
|
2447
|
+
rowResizeHeights.clear();
|
|
2448
|
+
rowResizeVersion += 1;
|
|
2449
|
+
});
|
|
2373
2450
|
/** Report a row's measured height. Called by the view's measuring action.
|
|
2374
2451
|
* Sub-pixel churn is ignored so a fractional layout can't loop. */
|
|
2375
2452
|
function reportRowHeight(index, height) {
|
|
@@ -2441,11 +2518,19 @@ export function createSvGridController(rawProps, domIdBase) {
|
|
|
2441
2518
|
// the estimate for rows that have not rendered yet. Touch the version so a
|
|
2442
2519
|
// new measurement re-runs this effect (the Map itself is not reactive).
|
|
2443
2520
|
autoRowHeightVersion;
|
|
2444
|
-
|
|
2521
|
+
// Touch the version so a resize re-runs this effect: the virtualizer has to
|
|
2522
|
+
// know the new size or every row below the resized one is positioned
|
|
2523
|
+
// against a stale offset.
|
|
2524
|
+
rowResizeVersion;
|
|
2525
|
+
const base = autoRowHeightOn
|
|
2445
2526
|
? (index) => measuredRowHeights.get(index) ?? autoRowHeightFallback
|
|
2446
2527
|
: typeof rh === "function"
|
|
2447
2528
|
? rh
|
|
2448
2529
|
: (rh ?? 30);
|
|
2530
|
+
const estimateSize = rowResizeOn
|
|
2531
|
+
? (index) => rowResizeHeights.get(index) ??
|
|
2532
|
+
(typeof base === "function" ? base(index) : base)
|
|
2533
|
+
: base;
|
|
2449
2534
|
virtualizer.setOptions({
|
|
2450
2535
|
count: allRows.length,
|
|
2451
2536
|
estimateSize,
|
|
@@ -2543,7 +2628,7 @@ export function createSvGridController(rawProps, domIdBase) {
|
|
|
2543
2628
|
// Lets the resolver answer from cache without re-invoking the source, so an
|
|
2544
2629
|
// async source fires one request per row instead of one per render.
|
|
2545
2630
|
const asyncEditorColumns = new Set();
|
|
2546
|
-
const headerSelectionState = $derived.by(()
|
|
2631
|
+
const headerSelectionState = $derived.by(function headerSelectionState_d() {
|
|
2547
2632
|
gridStateVersion;
|
|
2548
2633
|
const selectable = allRows.filter((row) => !isGroupRow(row));
|
|
2549
2634
|
if (!selectable.length)
|
|
@@ -2576,7 +2661,7 @@ export function createSvGridController(rawProps, domIdBase) {
|
|
|
2576
2661
|
* Returns `null` when fit scaling is not in effect (off, no room, total
|
|
2577
2662
|
* already >= target). Callers then fall back to the base width.
|
|
2578
2663
|
*/
|
|
2579
|
-
const fittedColumnWidths = $derived.by(()
|
|
2664
|
+
const fittedColumnWidths = $derived.by(function fittedColumnWidths_d() {
|
|
2580
2665
|
// Track viewport size (not scrollVersion) so we don't recompute on
|
|
2581
2666
|
// every scroll - only when the container actually resizes.
|
|
2582
2667
|
viewportVersion;
|
|
@@ -2641,12 +2726,10 @@ export function createSvGridController(rawProps, domIdBase) {
|
|
|
2641
2726
|
widths[lastId] = Math.max(MIN_COLUMN_WIDTH, scalableTarget - runningSum);
|
|
2642
2727
|
return widths;
|
|
2643
2728
|
});
|
|
2644
|
-
let resizePendingWidth = 0;
|
|
2645
|
-
let resizeRaf = null;
|
|
2646
2729
|
/** Where the fill handle should render: the bottom-right cell of the
|
|
2647
2730
|
* selection range (or the active cell if there's no range). Returns
|
|
2648
2731
|
* null when cell selection is off or there is no anchored selection. */
|
|
2649
|
-
const fillHandleCell = $derived.by(()
|
|
2732
|
+
const fillHandleCell = $derived.by(function fillHandleCell_d() {
|
|
2650
2733
|
if (!(props.enableCellSelection ?? false))
|
|
2651
2734
|
return null;
|
|
2652
2735
|
const anchor = selectionRange.anchor;
|
|
@@ -2690,7 +2773,7 @@ export function createSvGridController(rawProps, domIdBase) {
|
|
|
2690
2773
|
* reused by both the facet UI and the row filter. Computing them lazily
|
|
2691
2774
|
* in a $derived means columns with no filter menu open and no active
|
|
2692
2775
|
* filter never pay the iteration cost. */
|
|
2693
|
-
const facetBucketsByColumn = $derived.by(()
|
|
2776
|
+
const facetBucketsByColumn = $derived.by(function facetBucketsByColumn_d() {
|
|
2694
2777
|
const map = new Map();
|
|
2695
2778
|
for (const column of allColumns) {
|
|
2696
2779
|
const meta = isBucketableColumn(column);
|
|
@@ -2777,7 +2860,7 @@ export function createSvGridController(rawProps, domIdBase) {
|
|
|
2777
2860
|
const EMPTY_FACETS = [];
|
|
2778
2861
|
const EMPTY_FACET_SET = new Set();
|
|
2779
2862
|
let facetCache = null;
|
|
2780
|
-
const columnMenuFacetValues = $derived.by(()
|
|
2863
|
+
const columnMenuFacetValues = $derived.by(function columnMenuFacetValues_d() {
|
|
2781
2864
|
// The funnel popover drives via `filterMenuFor`; the column menu's Filter
|
|
2782
2865
|
// tab drives via `columnMenuFor`. Support whichever is open.
|
|
2783
2866
|
const columnId = filterMenuFor ?? columnMenuFor;
|
|
@@ -2807,7 +2890,7 @@ export function createSvGridController(rawProps, domIdBase) {
|
|
|
2807
2890
|
if (!(filterMenuFor ?? columnMenuFor))
|
|
2808
2891
|
facetCache = null;
|
|
2809
2892
|
});
|
|
2810
|
-
const columnMenuVisibleFacets = $derived.by(()
|
|
2893
|
+
const columnMenuVisibleFacets = $derived.by(function columnMenuVisibleFacets_d() {
|
|
2811
2894
|
const query = columnMenuSearch.trim().toLowerCase();
|
|
2812
2895
|
if (!query)
|
|
2813
2896
|
return columnMenuFacetValues;
|
|
@@ -2823,7 +2906,7 @@ export function createSvGridController(rawProps, domIdBase) {
|
|
|
2823
2906
|
* "everything checked", so that case materializes the set once here rather
|
|
2824
2907
|
* than every consumer re-deriving it.
|
|
2825
2908
|
*/
|
|
2826
|
-
const columnMenuSelectedFacets = $derived.by(()
|
|
2909
|
+
const columnMenuSelectedFacets = $derived.by(function columnMenuSelectedFacets_d() {
|
|
2827
2910
|
const columnId = filterMenuFor ?? columnMenuFor;
|
|
2828
2911
|
if (!columnId)
|
|
2829
2912
|
return EMPTY_FACET_SET;
|
|
@@ -2833,7 +2916,7 @@ export function createSvGridController(rawProps, domIdBase) {
|
|
|
2833
2916
|
// active chip input, narrowed by whatever the user has typed. Uncapped - the
|
|
2834
2917
|
// dropdown windows its rows, so a high-cardinality column costs a list of
|
|
2835
2918
|
// strings, not thousands of nodes.
|
|
2836
|
-
const inSuggestValues = $derived.by(()
|
|
2919
|
+
const inSuggestValues = $derived.by(function inSuggestValues_d() {
|
|
2837
2920
|
if (!inSuggestFor)
|
|
2838
2921
|
return EMPTY_FACETS;
|
|
2839
2922
|
const query = inSuggestQuery.trim().toLowerCase();
|
|
@@ -2941,12 +3024,6 @@ export function createSvGridController(rawProps, domIdBase) {
|
|
|
2941
3024
|
set editorSelectAll(v) { editorSelectAll = v; },
|
|
2942
3025
|
get columnWidths() { return columnWidths; },
|
|
2943
3026
|
set columnWidths(v) { columnWidths = v; },
|
|
2944
|
-
get resizingColumnId() { return resizingColumnId; },
|
|
2945
|
-
set resizingColumnId(v) { resizingColumnId = v; },
|
|
2946
|
-
get resizeStartX() { return resizeStartX; },
|
|
2947
|
-
set resizeStartX(v) { resizeStartX = v; },
|
|
2948
|
-
get resizeStartWidth() { return resizeStartWidth; },
|
|
2949
|
-
set resizeStartWidth(v) { resizeStartWidth = v; },
|
|
2950
3027
|
get MIN_COLUMN_WIDTH() { return MIN_COLUMN_WIDTH; },
|
|
2951
3028
|
get columnPinning() { return columnPinning; },
|
|
2952
3029
|
set columnPinning(v) { columnPinning = v; },
|
|
@@ -3012,6 +3089,7 @@ export function createSvGridController(rawProps, domIdBase) {
|
|
|
3012
3089
|
get showColumnFiltersEffective() { return showColumnFiltersEffective; },
|
|
3013
3090
|
get showInlineColumnFilterEffective() { return showInlineColumnFilterEffective; },
|
|
3014
3091
|
get showRowSelectionEffective() { return showRowSelectionEffective; },
|
|
3092
|
+
get rowSummariesEnabled() { return rowSummariesEnabled; },
|
|
3015
3093
|
get enableCellSelectionEffective() { return enableCellSelectionEffective; },
|
|
3016
3094
|
get flushScheduledScrollSync() { return flushScheduledScrollSync; },
|
|
3017
3095
|
get scheduleScrollSync() { return scheduleScrollSync; },
|
|
@@ -3268,6 +3346,15 @@ export function createSvGridController(rawProps, domIdBase) {
|
|
|
3268
3346
|
autoRowHeightVersion;
|
|
3269
3347
|
return (index) => measuredRowHeights.get(index);
|
|
3270
3348
|
},
|
|
3349
|
+
/** True when the `rowResize` prop is on and nothing overrides it. */
|
|
3350
|
+
get rowResizeOn() { return rowResizeOn; },
|
|
3351
|
+
/** Record the height the user dragged a row to. */
|
|
3352
|
+
get setRowResizeHeight() { return setRowResizeHeight; },
|
|
3353
|
+
/** A row's dragged height, or undefined when it has not been resized. */
|
|
3354
|
+
get rowResizeHeightPx() {
|
|
3355
|
+
rowResizeVersion;
|
|
3356
|
+
return rowResizeHeightPx;
|
|
3357
|
+
},
|
|
3271
3358
|
get virtualRowTotalSize() { return virtualRowTotalSize; },
|
|
3272
3359
|
get virtualRowStart() { return virtualRowStart; },
|
|
3273
3360
|
get virtualRowEnd() { return virtualRowEnd; },
|
|
@@ -3330,13 +3417,6 @@ export function createSvGridController(rawProps, domIdBase) {
|
|
|
3330
3417
|
get getColumnBaseWidth() { return getColumnBaseWidth; },
|
|
3331
3418
|
get fittedColumnWidths() { return fittedColumnWidths; },
|
|
3332
3419
|
get getColumnWidth() { return getColumnWidth; },
|
|
3333
|
-
get resizePendingWidth() { return resizePendingWidth; },
|
|
3334
|
-
set resizePendingWidth(v) { resizePendingWidth = v; },
|
|
3335
|
-
get resizeRaf() { return resizeRaf; },
|
|
3336
|
-
set resizeRaf(v) { resizeRaf = v; },
|
|
3337
|
-
get startColumnResize() { return startColumnResize; },
|
|
3338
|
-
get onColumnResizeMove() { return onColumnResizeMove; },
|
|
3339
|
-
get endColumnResize() { return endColumnResize; },
|
|
3340
3420
|
get setSelection() { return setSelection; },
|
|
3341
3421
|
get extendSelection() { return extendSelection; },
|
|
3342
3422
|
get isCellInSelectedRange() { return isCellInSelectedRange; },
|
|
@@ -3346,6 +3426,15 @@ export function createSvGridController(rawProps, domIdBase) {
|
|
|
3346
3426
|
get isInFillPreview() { return isInFillPreview; },
|
|
3347
3427
|
get fillMarqueeEdges() { return fillMarqueeEdges; },
|
|
3348
3428
|
get findColumnById() { return findColumnById; },
|
|
3429
|
+
/**
|
|
3430
|
+
* Whether this column may be resized by the user, from its
|
|
3431
|
+
* `ColumnDef.resizable`. Defaults to true, so a column only opts out by
|
|
3432
|
+
* saying so; the grid-wide `columnResize` prop gates all of them above
|
|
3433
|
+
* this. Used by the resize action and by the column menu's Autosize item.
|
|
3434
|
+
*/
|
|
3435
|
+
columnResizable(columnId) {
|
|
3436
|
+
return findColumnById(columnId)?.columnDef?.resizable !== false;
|
|
3437
|
+
},
|
|
3349
3438
|
get readCellRaw() { return readCellRaw; },
|
|
3350
3439
|
get writeCellRaw() { return writeCellRaw; },
|
|
3351
3440
|
get applyFillPattern() { return applyFillPattern; },
|
|
@@ -3455,11 +3544,63 @@ export function createSvGridController(rawProps, domIdBase) {
|
|
|
3455
3544
|
const { cellConditionalFormat, computeRowClass, computeCellClass, computeCellTooltip, computeCellValidity, computeCellNote, getColumnEditorOptions, areEditorOptionsLoading, formatListCellValue, formatCellValue, formatPinnedValue, computePinnedCellClass } = createCellRender(ctx);
|
|
3456
3545
|
const { isCellEditable, isCellEditableAt, getRowColumnValue, getCellDisplayValue, startEditingWithChar, startEditing, stopEditing, startFullRowEdit, setFullRowDraft, commitFullRowEdit, cancelFullRowEdit, saveEditingCell, applyHistoryStep, updateEditingCellValue, onEditorKeyDown, commitAndMoveByTab, focusOnMount, onCellDoubleClick, pasteFromClipboard, onGridPaste } = createEditing(ctx);
|
|
3457
3546
|
const { isRowSelected, toggleRowSelectionById, toggleSelectAllRows, setActiveCell, scrollActiveCellIntoView, setSelection, extendSelection, isCellInSelectedRange, getCellRangeEdges, getSelectionRects, isInFillPreview, fillMarqueeEdges, findColumnById, onCellPointerDown, onCellPointerEnter, endDragSelection, onWindowPointerMove, onCellClick, emitCellDoubleClick } = createSelection(ctx);
|
|
3458
|
-
const { cellPinStyle, isColumnPinned, getCurrentColumnOrder, emitColumnOrder, setColumnOrderInternal, applyColumnDrop, onColumnHeaderDragStart, onColumnHeaderDragOver, onColumnHeaderDragLeave, onColumnHeaderDrop, onColumnHeaderDragEnd, pinColumnLeft, pinColumnRight, unpinColumn, toggleColumnVisibleInPanel, moveColumnInPanel, toggleGroupInPanel, getColumnBaseWidth, getColumnWidth,
|
|
3547
|
+
const { cellPinStyle, isColumnPinned, getCurrentColumnOrder, emitColumnOrder, setColumnOrderInternal, applyColumnDrop, onColumnHeaderDragStart, onColumnHeaderDragOver, onColumnHeaderDragLeave, onColumnHeaderDrop, onColumnHeaderDragEnd, pinColumnLeft, pinColumnRight, unpinColumn, toggleColumnVisibleInPanel, moveColumnInPanel, toggleGroupInPanel, getColumnBaseWidth, getColumnWidth, measureText, autosizeColumn, autosizeAllColumns, resetColumns } = createColumns(ctx);
|
|
3459
3548
|
const { onRowDragStart, onRowDragOver, onRowDragLeave, onRowDrop, onRowsContainerDragOver, onRowsContainerDrop, onRowDragEnd, onRowPointerDown, destroyRowDrag } = createRowDrag(ctx);
|
|
3460
3549
|
const { register: registerAlignedGrid, broadcastScroll: broadcastAlignedScroll, broadcastWidths: broadcastAlignedWidths } = createAlignedGrids(ctx);
|
|
3461
3550
|
const { buildApi } = createGridApi(ctx);
|
|
3462
3551
|
const { readCellRaw, writeCellRaw, applyFillPattern, clearSelectedCellValues, startFillDrag, onFillPointerMove, onFillPointerUp, toggleBooleanCell, copySelectionToClipboard, clearSelectedCells, cutSelectionToClipboard } = createClipboard(ctx);
|
|
3552
|
+
// Dev-time configuration checks. Silent misconfiguration was the grid's
|
|
3553
|
+
// biggest usability gap - a misspelled `field` rendered a column of blank
|
|
3554
|
+
// cells and printed nothing, and an inert `pageSize` was simply ignored.
|
|
3555
|
+
//
|
|
3556
|
+
// `validateGridConfig` is pure (see validate.ts) so it can be unit-tested;
|
|
3557
|
+
// this only decides when to run it, and prints each distinct message once.
|
|
3558
|
+
//
|
|
3559
|
+
// It is loaded with `import()` rather than a static import so the checks live
|
|
3560
|
+
// in a lazy chunk. The base bundle is size-budgeted and already sits at its
|
|
3561
|
+
// limit, so a static import cost ~1 KB gzip that a production app would carry
|
|
3562
|
+
// and never execute.
|
|
3563
|
+
//
|
|
3564
|
+
// `DEV` comes from `esm-env` because the alternatives do not work here:
|
|
3565
|
+
// `process.env.NODE_ENV` is undefined in Vite's browser runtime (the checks
|
|
3566
|
+
// silently never ran), and Vite's own flag makes svelte-package warn that it
|
|
3567
|
+
// only works for Vite consumers. esm-env resolves through export conditions,
|
|
3568
|
+
// so it is correct in dev and folds to `false` in a production build. It is
|
|
3569
|
+
// already a direct dependency of Svelte, so it adds nothing to an install.
|
|
3570
|
+
if (DEV) {
|
|
3571
|
+
const warnedConfig = new Set();
|
|
3572
|
+
$effect(() => {
|
|
3573
|
+
// Read the reactive values synchronously so the effect tracks them; the
|
|
3574
|
+
// module load below is async and would otherwise register no dependencies.
|
|
3575
|
+
const snapshot = {
|
|
3576
|
+
data: internalData,
|
|
3577
|
+
columns: internalColumns,
|
|
3578
|
+
features: resolveEffectiveFeatures(),
|
|
3579
|
+
sortable: props.sortable,
|
|
3580
|
+
pageable: props.pageable,
|
|
3581
|
+
showPagination: props.showPagination,
|
|
3582
|
+
pageSize: props.pageSize,
|
|
3583
|
+
groupBy: props.groupBy,
|
|
3584
|
+
treeData: props.treeData,
|
|
3585
|
+
initialColumnPinning: props.initialColumnPinning,
|
|
3586
|
+
columnVirtualization: props.columnVirtualization,
|
|
3587
|
+
externalPagination: props.externalPagination,
|
|
3588
|
+
rowCount: props.rowCount,
|
|
3589
|
+
externalSort: props.externalSort,
|
|
3590
|
+
onSortingChange: props.onSortingChange,
|
|
3591
|
+
externalFilter: props.externalFilter,
|
|
3592
|
+
onFiltersChange: props.onFiltersChange,
|
|
3593
|
+
};
|
|
3594
|
+
void import("./validate.js").then(({ validateGridConfig }) => {
|
|
3595
|
+
for (const message of validateGridConfig(snapshot)) {
|
|
3596
|
+
if (warnedConfig.has(message))
|
|
3597
|
+
continue;
|
|
3598
|
+
warnedConfig.add(message);
|
|
3599
|
+
console.warn(message);
|
|
3600
|
+
}
|
|
3601
|
+
});
|
|
3602
|
+
});
|
|
3603
|
+
}
|
|
3463
3604
|
// Aligned grids: register in the shared group on mount, and mirror column
|
|
3464
3605
|
// resizes to peers whenever columnWidths changes. Horizontal-scroll mirroring
|
|
3465
3606
|
// is driven from onBodyScroll (via ctx.broadcastAlignedScroll).
|
|
@@ -3479,7 +3620,6 @@ export function createSvGridController(rawProps, domIdBase) {
|
|
|
3479
3620
|
// this grid still owns (#68). Each of these is a no-op when idle.
|
|
3480
3621
|
$effect(() => {
|
|
3481
3622
|
return () => {
|
|
3482
|
-
endColumnResize();
|
|
3483
3623
|
hideTooltip();
|
|
3484
3624
|
destroyRowDrag();
|
|
3485
3625
|
};
|