@svgrid/grid 2.6.21 → 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 +13 -8
- package/dist/SvGrid.controller.svelte.js +150 -72
- package/dist/SvGrid.css +1 -1
- package/dist/SvGrid.svelte +110 -56
- package/dist/SvGrid.types.d.ts +41 -1
- package/dist/cdn/{GridMenus-BfTAKn84.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-BYq-qyrp.js → src-C9Hihx1W.js} +3456 -3459
- package/dist/cdn/{src-DBel9wRZ.js → src-D1lXwq1l.js} +8283 -8286
- package/dist/cdn/svgrid.js +10 -8
- package/dist/cdn/svgrid.svelte-external.js +10 -8
- 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 +19 -4
- package/dist/core.js +460 -119
- 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/menus.js +1 -1
- package/dist/row-resize.d.ts +11 -0
- package/dist/row-resize.js +7 -1
- package/dist/selection.js +9 -0
- package/dist/spreadsheet.d.ts +1 -1
- package/dist/spreadsheet.js +1 -1
- package/package.json +1 -1
- package/src/GridMenus.svelte +17 -12
- package/src/SvGrid.controller.svelte.ts +155 -74
- package/src/SvGrid.css +1 -1
- package/src/SvGrid.svelte +110 -56
- package/src/SvGrid.types.ts +41 -1
- 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 +516 -119
- 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/menus.ts +1 -1
- 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/selection.ts +9 -0
- package/src/spreadsheet.ts +1 -1
- package/dist/cdn/GridMenus-C3bJd7w8.js +0 -489
|
@@ -275,9 +275,6 @@ export function createSvGridController(rawProps, domIdBase) {
|
|
|
275
275
|
let editorSelectAll = true;
|
|
276
276
|
/** Per-column width overrides set by the resize handles. */
|
|
277
277
|
let columnWidths = $state({});
|
|
278
|
-
let resizingColumnId = $state(null);
|
|
279
|
-
let resizeStartX = 0;
|
|
280
|
-
let resizeStartWidth = 0;
|
|
281
278
|
const MIN_COLUMN_WIDTH = 40;
|
|
282
279
|
/** Columns pinned to the left or right edge of the grid (sticky positioning).
|
|
283
280
|
* Seeded from `props.initialColumnPinning` so demos / tests can show the
|
|
@@ -294,7 +291,26 @@ export function createSvGridController(rawProps, domIdBase) {
|
|
|
294
291
|
let dataStateVersion = $state(0);
|
|
295
292
|
const selectionColumnWidth = 44;
|
|
296
293
|
const rowNumberColumnWidth = $derived(props.rowNumberWidth ?? 56);
|
|
297
|
-
|
|
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);
|
|
298
314
|
let columnMenuFor = $state(null);
|
|
299
315
|
let columnMenuTab = $state("general");
|
|
300
316
|
let columnMenuPos = $state({ x: 0, y: 0 });
|
|
@@ -318,11 +334,11 @@ export function createSvGridController(rawProps, domIdBase) {
|
|
|
318
334
|
let commentEditFor = $state(null);
|
|
319
335
|
let commentDraft = $state("");
|
|
320
336
|
let valueFilters = $state({});
|
|
321
|
-
const viewportWidth = $derived.by(()
|
|
337
|
+
const viewportWidth = $derived.by(function viewportWidth_d() {
|
|
322
338
|
viewportVersion;
|
|
323
339
|
return scrollContainer ? scrollContainer.clientWidth : 0;
|
|
324
340
|
});
|
|
325
|
-
const viewportHeight = $derived.by(()
|
|
341
|
+
const viewportHeight = $derived.by(function viewportHeight_d() {
|
|
326
342
|
viewportVersion;
|
|
327
343
|
return scrollContainer ? scrollContainer.clientHeight : 0;
|
|
328
344
|
});
|
|
@@ -344,7 +360,7 @@ export function createSvGridController(rawProps, domIdBase) {
|
|
|
344
360
|
const hb = column.columnDef?.hideBelow;
|
|
345
361
|
return hb != null && viewportWidth > 0 && viewportWidth < hb;
|
|
346
362
|
}
|
|
347
|
-
const scrollMetrics = $derived.by(()
|
|
363
|
+
const scrollMetrics = $derived.by(function scrollMetrics_d() {
|
|
348
364
|
scrollVersion;
|
|
349
365
|
viewportVersion;
|
|
350
366
|
// Track the virtualizers' versions too so when data loads or row /
|
|
@@ -378,7 +394,7 @@ export function createSvGridController(rawProps, domIdBase) {
|
|
|
378
394
|
* - virtualizer.getTotalSize(): correct at initial load (before first paint)
|
|
379
395
|
* - scrollMetrics.scrollHeight: correct after detail rows expand (DOM is live,
|
|
380
396
|
* ResizeObserver on gridRootEl already bumps scrollVersion at that point) */
|
|
381
|
-
const hasVerticalOverflow = $derived.by(()
|
|
397
|
+
const hasVerticalOverflow = $derived.by(function hasVerticalOverflow_d() {
|
|
382
398
|
virtualizer.version;
|
|
383
399
|
const virtualizerSize = virtualizer.getTotalSize();
|
|
384
400
|
// scrollMetrics.scrollHeight is 0 before initial paint; once the table
|
|
@@ -636,7 +652,7 @@ export function createSvGridController(rawProps, domIdBase) {
|
|
|
636
652
|
// Declared here rather than beside the other pagination/state derivations:
|
|
637
653
|
// the auto-group column pipeline below reads it, and a `const` used above its
|
|
638
654
|
// declaration is a type error even though `$derived` is lazy enough at runtime.
|
|
639
|
-
const groupingColumns = $derived.by(()
|
|
655
|
+
const groupingColumns = $derived.by(function groupingColumns_d() {
|
|
640
656
|
gridStateVersion;
|
|
641
657
|
return grid.getState().grouping ?? [];
|
|
642
658
|
});
|
|
@@ -657,7 +673,7 @@ export function createSvGridController(rawProps, domIdBase) {
|
|
|
657
673
|
* any other column. They carry no `field` - their cell content is resolved
|
|
658
674
|
* from the row's group state at render time.
|
|
659
675
|
*/
|
|
660
|
-
const autoGroupColumns = $derived.by(()
|
|
676
|
+
const autoGroupColumns = $derived.by(function autoGroupColumns_d() {
|
|
661
677
|
if (!groupColumnMode)
|
|
662
678
|
return [];
|
|
663
679
|
const sourceById = new Map(grid.getAllColumns().map((c) => [c.id, c]));
|
|
@@ -723,7 +739,7 @@ export function createSvGridController(rawProps, domIdBase) {
|
|
|
723
739
|
depth: columnId === "__autoGroup" ? depth : 0,
|
|
724
740
|
};
|
|
725
741
|
}
|
|
726
|
-
const allColumns = $derived.by(()
|
|
742
|
+
const allColumns = $derived.by(function allColumns_d() {
|
|
727
743
|
let raw = grid
|
|
728
744
|
.getAllColumns()
|
|
729
745
|
.filter((column) => !hiddenColumns[column.id] &&
|
|
@@ -771,7 +787,7 @@ export function createSvGridController(rawProps, domIdBase) {
|
|
|
771
787
|
return [...left, ...unpinned, ...right];
|
|
772
788
|
});
|
|
773
789
|
/** Header groups reordered to match {@link allColumns}. */
|
|
774
|
-
const headerGroups = $derived.by(()
|
|
790
|
+
const headerGroups = $derived.by(function headerGroups_d() {
|
|
775
791
|
const base = grid.getHeaderGroups();
|
|
776
792
|
if (!base.length)
|
|
777
793
|
return base;
|
|
@@ -797,7 +813,7 @@ export function createSvGridController(rawProps, domIdBase) {
|
|
|
797
813
|
}
|
|
798
814
|
return [{ id: base[0].id, headers }];
|
|
799
815
|
});
|
|
800
|
-
const groupHeaderRows = $derived.by(()
|
|
816
|
+
const groupHeaderRows = $derived.by(function groupHeaderRows_d() {
|
|
801
817
|
const userCols = props.columns ?? [];
|
|
802
818
|
// 1. Find max depth in the user-provided column tree.
|
|
803
819
|
function maxDepth(defs) {
|
|
@@ -905,7 +921,7 @@ export function createSvGridController(rawProps, domIdBase) {
|
|
|
905
921
|
return rows;
|
|
906
922
|
});
|
|
907
923
|
/** Cumulative pixel offsets for left- and right-pinned columns. */
|
|
908
|
-
const pinnedOffsets = $derived.by(()
|
|
924
|
+
const pinnedOffsets = $derived.by(function pinnedOffsets_d() {
|
|
909
925
|
const rowNumberWidth = showRowNumbersEffective ? rowNumberColumnWidth : 0;
|
|
910
926
|
const selectionWidth = showRowSelectionEffective ? selectionColumnWidth : 0;
|
|
911
927
|
const left = {};
|
|
@@ -950,7 +966,7 @@ export function createSvGridController(rawProps, domIdBase) {
|
|
|
950
966
|
const hasConditionalFormats = $derived((props.conditionalFormats?.length ?? 0) > 0);
|
|
951
967
|
// Per-column numeric min/max, needed only by colorScale / dataBar formats.
|
|
952
968
|
// Lazy: this derived never runs unless `conditionalFormats` is set.
|
|
953
|
-
const conditionalColumnStats = $derived.by(()
|
|
969
|
+
const conditionalColumnStats = $derived.by(function conditionalColumnStats_d() {
|
|
954
970
|
const map = new Map();
|
|
955
971
|
const formats = props.conditionalFormats;
|
|
956
972
|
if (!formats?.length || !formatsNeedingStats(formats))
|
|
@@ -990,14 +1006,14 @@ export function createSvGridController(rawProps, domIdBase) {
|
|
|
990
1006
|
}
|
|
991
1007
|
return map;
|
|
992
1008
|
});
|
|
993
|
-
const sortDirectionByColumn = $derived.by(()
|
|
1009
|
+
const sortDirectionByColumn = $derived.by(function sortDirectionByColumn_d() {
|
|
994
1010
|
gridStateVersion;
|
|
995
1011
|
const directions = {};
|
|
996
1012
|
for (const column of allColumns)
|
|
997
1013
|
directions[column.id] = column.getIsSorted();
|
|
998
1014
|
return directions;
|
|
999
1015
|
});
|
|
1000
|
-
const paginationState = $derived.by(()
|
|
1016
|
+
const paginationState = $derived.by(function paginationState_d() {
|
|
1001
1017
|
gridStateVersion;
|
|
1002
1018
|
return grid.getState().pagination ?? { pageIndex: 0, pageSize: 10 };
|
|
1003
1019
|
});
|
|
@@ -1006,7 +1022,7 @@ export function createSvGridController(rawProps, domIdBase) {
|
|
|
1006
1022
|
* compute the correct "X to Y of Z" range and total page count when
|
|
1007
1023
|
* filters reduce the dataset.
|
|
1008
1024
|
*/
|
|
1009
|
-
const allRowsBeforePagination = $derived.by(()
|
|
1025
|
+
const allRowsBeforePagination = $derived.by(function allRowsBeforePagination_d() {
|
|
1010
1026
|
// Depend on dataStateVersion (row-model-affecting store changes) NOT
|
|
1011
1027
|
// gridStateVersion - so moving the active cell / selection does not force
|
|
1012
1028
|
// this O(rows) pipeline to re-run. Filter-input state (globalFilter etc.)
|
|
@@ -1030,6 +1046,25 @@ export function createSvGridController(rawProps, domIdBase) {
|
|
|
1030
1046
|
.some((cell) => normalizeForFilter(String(cell.getValue() ?? ""), (props.filterLocale ?? props.localization?.locale))
|
|
1031
1047
|
.includes(needle)));
|
|
1032
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
|
+
};
|
|
1033
1068
|
// A single condition is "active" if it has the value(s) it needs.
|
|
1034
1069
|
const condActive = (op, value, valueTo) => {
|
|
1035
1070
|
if (op === "isBlank" || op === "isNotBlank")
|
|
@@ -1054,6 +1089,11 @@ export function createSvGridController(rawProps, domIdBase) {
|
|
|
1054
1089
|
// become compiled predicates before a single row is tested.
|
|
1055
1090
|
const compiledMenuFilters = menuFilters.map(([columnId, f]) => ({
|
|
1056
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),
|
|
1057
1097
|
join: f.join,
|
|
1058
1098
|
a: condActive(f.operator, f.value, f.valueTo)
|
|
1059
1099
|
? compileCond(columnId, f.operator, f.value, f.valueTo)
|
|
@@ -1062,8 +1102,8 @@ export function createSvGridController(rawProps, domIdBase) {
|
|
|
1062
1102
|
? compileCond(columnId, f.operator2, f.value2 ?? "", f.valueTo2)
|
|
1063
1103
|
: null,
|
|
1064
1104
|
}));
|
|
1065
|
-
rows = rows.filter((row) => compiledMenuFilters.every(({
|
|
1066
|
-
const cellValue =
|
|
1105
|
+
rows = rows.filter((row) => compiledMenuFilters.every(({ readValue, join, a, b }) => {
|
|
1106
|
+
const cellValue = readValue(row);
|
|
1067
1107
|
const ra = a ? a(cellValue) : null;
|
|
1068
1108
|
const rb = b ? b(cellValue) : null;
|
|
1069
1109
|
if (ra === null)
|
|
@@ -1081,10 +1121,11 @@ export function createSvGridController(rawProps, domIdBase) {
|
|
|
1081
1121
|
const bucketEntries = valueFilterEntries.map(([columnId, allowed]) => ({
|
|
1082
1122
|
columnId,
|
|
1083
1123
|
allowed,
|
|
1124
|
+
readValue: makeColumnReader(columnId),
|
|
1084
1125
|
buckets: facetBucketsByColumn.get(columnId) ?? null,
|
|
1085
1126
|
}));
|
|
1086
|
-
rows = rows.filter((row) => bucketEntries.every(({
|
|
1087
|
-
const raw =
|
|
1127
|
+
rows = rows.filter((row) => bucketEntries.every(({ allowed, buckets, readValue }) => {
|
|
1128
|
+
const raw = readValue(row);
|
|
1088
1129
|
if (buckets) {
|
|
1089
1130
|
// Range-bucketed filter: find which bucket this row's value
|
|
1090
1131
|
// falls into and check whether that bucket's label is allowed.
|
|
@@ -1142,7 +1183,7 @@ export function createSvGridController(rawProps, domIdBase) {
|
|
|
1142
1183
|
* is active we page by DATA rows and reprint each page's ancestor banners.
|
|
1143
1184
|
* Null when grouping is off, so the flat path stays a cheap slice.
|
|
1144
1185
|
*/
|
|
1145
|
-
const groupedPage = $derived.by(()
|
|
1186
|
+
const groupedPage = $derived.by(function groupedPage_d() {
|
|
1146
1187
|
if (!paginationEnabled || externalPaginationEnabled)
|
|
1147
1188
|
return null;
|
|
1148
1189
|
if (!groupingColumns.length)
|
|
@@ -1211,7 +1252,7 @@ export function createSvGridController(rawProps, domIdBase) {
|
|
|
1211
1252
|
* the full dataset rather than the current page (see the comment above
|
|
1212
1253
|
* `_rowModels`).
|
|
1213
1254
|
*/
|
|
1214
|
-
const allRows = $derived.by(()
|
|
1255
|
+
const allRows = $derived.by(function allRows_d() {
|
|
1215
1256
|
const paged = (() => {
|
|
1216
1257
|
const rows = allRowsBeforePagination;
|
|
1217
1258
|
// External pagination: `data` already IS the current page - never slice.
|
|
@@ -1278,7 +1319,7 @@ export function createSvGridController(rawProps, domIdBase) {
|
|
|
1278
1319
|
const paginationTotalRows = $derived(externalPaginationEnabled ? (props.rowCount ?? 0) : paginatedRowTotal);
|
|
1279
1320
|
const paginationPageIndex = $derived(externalPaginationEnabled ? (props.pageIndex ?? 0) : paginationState.pageIndex);
|
|
1280
1321
|
const paginationPageSize = $derived(externalPaginationEnabled ? (props.pageSize ?? 10) : paginationState.pageSize);
|
|
1281
|
-
const rowSelectionState = $derived.by(()
|
|
1322
|
+
const rowSelectionState = $derived.by(function rowSelectionState_d() {
|
|
1282
1323
|
gridStateVersion;
|
|
1283
1324
|
return grid.getState().rowSelection ?? {};
|
|
1284
1325
|
});
|
|
@@ -1331,7 +1372,7 @@ export function createSvGridController(rawProps, domIdBase) {
|
|
|
1331
1372
|
const statusBarAggregates = $derived(typeof props.statusBar === "object" && props.statusBar.aggregates
|
|
1332
1373
|
? props.statusBar.aggregates
|
|
1333
1374
|
: ["count", "sum", "avg", "min", "max"]);
|
|
1334
|
-
const statusBarStats = $derived.by(()
|
|
1375
|
+
const statusBarStats = $derived.by(function statusBarStats_d() {
|
|
1335
1376
|
if (!statusBarEnabled)
|
|
1336
1377
|
return null;
|
|
1337
1378
|
const a = selectionRange.anchor;
|
|
@@ -1390,7 +1431,7 @@ export function createSvGridController(rawProps, domIdBase) {
|
|
|
1390
1431
|
const toolPanelEnabled = $derived(props.toolPanel === true);
|
|
1391
1432
|
// Every column (including hidden ones) in the user's current order, so the
|
|
1392
1433
|
// panel can toggle/reorder anything. Group columns are flagged live.
|
|
1393
|
-
const toolPanelColumns = $derived.by(()
|
|
1434
|
+
const toolPanelColumns = $derived.by(function toolPanelColumns_d() {
|
|
1394
1435
|
gridStateVersion;
|
|
1395
1436
|
const all = grid.getAllColumns();
|
|
1396
1437
|
if (!userColumnOrder.length)
|
|
@@ -1428,7 +1469,7 @@ export function createSvGridController(rawProps, domIdBase) {
|
|
|
1428
1469
|
// reveals. `a11y/grid-announcements.ts` documents what is deliberately left
|
|
1429
1470
|
// unsaid, and why saying it would make the grid talk over itself.
|
|
1430
1471
|
/** Data rows before any local filtering - the denominator in "12 of 250". */
|
|
1431
|
-
const unfilteredRowTotal = $derived.by(()
|
|
1472
|
+
const unfilteredRowTotal = $derived.by(function unfilteredRowTotal_d() {
|
|
1432
1473
|
dataStateVersion;
|
|
1433
1474
|
void internalData;
|
|
1434
1475
|
return grid.getRowModel().rows.length;
|
|
@@ -1506,7 +1547,7 @@ export function createSvGridController(rawProps, domIdBase) {
|
|
|
1506
1547
|
props.onPivotModeChange?.(next);
|
|
1507
1548
|
}
|
|
1508
1549
|
const pivotActive = $derived(!!pivotConfig && pivotModeOn && hasPivotEngine());
|
|
1509
|
-
const pivotResult = $derived.by(()
|
|
1550
|
+
const pivotResult = $derived.by(function pivotResult_d() {
|
|
1510
1551
|
if (!pivotActive || !pivotConfig)
|
|
1511
1552
|
return null;
|
|
1512
1553
|
const engine = getPivotEngine();
|
|
@@ -1584,7 +1625,7 @@ export function createSvGridController(rawProps, domIdBase) {
|
|
|
1584
1625
|
const h = col.columnDef.header;
|
|
1585
1626
|
return typeof h === "string" && h ? h : (col.columnDef.field ?? col.id);
|
|
1586
1627
|
};
|
|
1587
|
-
const chartableColumns = $derived.by(()
|
|
1628
|
+
const chartableColumns = $derived.by(function chartableColumns_d() {
|
|
1588
1629
|
const dims = [];
|
|
1589
1630
|
const measures = [];
|
|
1590
1631
|
for (const col of allColumns) {
|
|
@@ -1599,7 +1640,7 @@ export function createSvGridController(rawProps, domIdBase) {
|
|
|
1599
1640
|
}
|
|
1600
1641
|
return { dims, measures };
|
|
1601
1642
|
});
|
|
1602
|
-
const chartColumnDefaults = $derived.by(()
|
|
1643
|
+
const chartColumnDefaults = $derived.by(function chartColumnDefaults_d() {
|
|
1603
1644
|
const { dims, measures } = chartableColumns;
|
|
1604
1645
|
let dimId = dims[0]?.id ?? null;
|
|
1605
1646
|
let seriesId = null;
|
|
@@ -1972,7 +2013,7 @@ export function createSvGridController(rawProps, domIdBase) {
|
|
|
1972
2013
|
// the virtualizer's own (real) numbers take over.
|
|
1973
2014
|
const preMeasureRowHeight = $derived(typeof props.rowHeight === "number" ? props.rowHeight : 30);
|
|
1974
2015
|
const preMeasureViewport = $derived(typeof props.containerHeight === "number" ? props.containerHeight : 520);
|
|
1975
|
-
const virtualRows = $derived.by(()
|
|
2016
|
+
const virtualRows = $derived.by(function virtualRows_d() {
|
|
1976
2017
|
virtualizer.version;
|
|
1977
2018
|
const items = virtualizer.getVirtualItems();
|
|
1978
2019
|
if (items.length || allRows.length === 0)
|
|
@@ -1983,7 +2024,7 @@ export function createSvGridController(rawProps, domIdBase) {
|
|
|
1983
2024
|
// only, and it matches what the server produced, so hydration is clean.
|
|
1984
2025
|
return buildPreMeasureItems(allRows.length, preMeasureRowHeight, preMeasureViewport, props.overscan ?? 8);
|
|
1985
2026
|
});
|
|
1986
|
-
const virtualRowTotalSize = $derived.by(()
|
|
2027
|
+
const virtualRowTotalSize = $derived.by(function virtualRowTotalSize_d() {
|
|
1987
2028
|
virtualizer.version;
|
|
1988
2029
|
const size = virtualizer.getTotalSize();
|
|
1989
2030
|
// Keep the scroll height honest during the pre-measurement render, so the
|
|
@@ -2031,7 +2072,7 @@ export function createSvGridController(rawProps, domIdBase) {
|
|
|
2031
2072
|
// OWN committed scroll offset - not the live DOM scrollTop - so the spacer
|
|
2032
2073
|
// shift and the rendered window are always computed from the same state and
|
|
2033
2074
|
// can never skew by a frame (which would jitter at extreme scale).
|
|
2034
|
-
const rowOffsetAdjustment = $derived.by(()
|
|
2075
|
+
const rowOffsetAdjustment = $derived.by(function rowOffsetAdjustment_d() {
|
|
2035
2076
|
if (!rowScrollScalingActive)
|
|
2036
2077
|
return 0;
|
|
2037
2078
|
virtualizer.version;
|
|
@@ -2042,11 +2083,11 @@ export function createSvGridController(rawProps, domIdBase) {
|
|
|
2042
2083
|
// virtualRowStart / virtualRowBottomSpacer.
|
|
2043
2084
|
const rowTopSpacer = $derived(Math.max(virtualRowStart - rowOffsetAdjustment, 0));
|
|
2044
2085
|
const rowBottomSpacer = $derived(Math.max(rowDomTotalSize - (virtualRowEnd - rowOffsetAdjustment), 0));
|
|
2045
|
-
const virtualColumns = $derived.by(()
|
|
2086
|
+
const virtualColumns = $derived.by(function virtualColumns_d() {
|
|
2046
2087
|
columnVirtualizerVersion;
|
|
2047
2088
|
return columnVirtualizer.getVirtualItems();
|
|
2048
2089
|
});
|
|
2049
|
-
const virtualColumnTotalSize = $derived.by(()
|
|
2090
|
+
const virtualColumnTotalSize = $derived.by(function virtualColumnTotalSize_d() {
|
|
2050
2091
|
columnVirtualizerVersion;
|
|
2051
2092
|
return columnVirtualizer.getTotalSize();
|
|
2052
2093
|
});
|
|
@@ -2061,7 +2102,7 @@ export function createSvGridController(rawProps, domIdBase) {
|
|
|
2061
2102
|
return item;
|
|
2062
2103
|
});
|
|
2063
2104
|
};
|
|
2064
|
-
const renderedColumnItems = $derived.by(()
|
|
2105
|
+
const renderedColumnItems = $derived.by(function renderedColumnItems_d() {
|
|
2065
2106
|
if (!columnVirtualizationEnabled)
|
|
2066
2107
|
return allColumnItems();
|
|
2067
2108
|
// Column virtualization is ON by default and its virtualizer, like the row
|
|
@@ -2107,7 +2148,7 @@ export function createSvGridController(rawProps, domIdBase) {
|
|
|
2107
2148
|
const renderedColumns = $derived.by(() => renderedColumnItems
|
|
2108
2149
|
.map((item) => ({ item, column: allColumns[item.index] }))
|
|
2109
2150
|
.filter(hasRenderedColumn));
|
|
2110
|
-
const totalColumnWidth = $derived.by(()
|
|
2151
|
+
const totalColumnWidth = $derived.by(function totalColumnWidth_d() {
|
|
2111
2152
|
if (columnVirtualizationEnabled)
|
|
2112
2153
|
return virtualColumnTotalSize;
|
|
2113
2154
|
let total = 0;
|
|
@@ -2124,7 +2165,7 @@ export function createSvGridController(rawProps, domIdBase) {
|
|
|
2124
2165
|
* column instead is reactive to both `columnWidths` and
|
|
2125
2166
|
* `fittedColumnWidths`, so the overflow decision settles in the same
|
|
2126
2167
|
* render where fit-scaling lands - no race, no scrollbar flash. */
|
|
2127
|
-
const hasHorizontalOverflow = $derived.by(()
|
|
2168
|
+
const hasHorizontalOverflow = $derived.by(function hasHorizontalOverflow_d() {
|
|
2128
2169
|
const fixedCols = (showRowNumbersEffective ? rowNumberColumnWidth : 0) +
|
|
2129
2170
|
(showRowSelectionEffective ? selectionColumnWidth : 0);
|
|
2130
2171
|
let total = fixedCols;
|
|
@@ -2150,7 +2191,7 @@ export function createSvGridController(rawProps, domIdBase) {
|
|
|
2150
2191
|
* everything stays pixel-aligned. When virtualization is off this is a
|
|
2151
2192
|
* pass-through.
|
|
2152
2193
|
*/
|
|
2153
|
-
const groupHeaderRowsWindowed = $derived.by(()
|
|
2194
|
+
const groupHeaderRowsWindowed = $derived.by(function groupHeaderRowsWindowed_d() {
|
|
2154
2195
|
const base = groupHeaderRows;
|
|
2155
2196
|
if (!columnVirtualizationEnabled || base.length === 0)
|
|
2156
2197
|
return base;
|
|
@@ -2176,11 +2217,11 @@ export function createSvGridController(rawProps, domIdBase) {
|
|
|
2176
2217
|
return { ...row, cells };
|
|
2177
2218
|
});
|
|
2178
2219
|
});
|
|
2179
|
-
const activeCell = $derived.by(()
|
|
2220
|
+
const activeCell = $derived.by(function activeCell_d() {
|
|
2180
2221
|
gridStateVersion;
|
|
2181
2222
|
return (grid.getState().activeCell ?? { rowIndex: 0, colIndex: 0, cellId: null });
|
|
2182
2223
|
});
|
|
2183
|
-
const activeDescendantId = $derived.by(()
|
|
2224
|
+
const activeDescendantId = $derived.by(function activeDescendantId_d() {
|
|
2184
2225
|
const active = activeCell;
|
|
2185
2226
|
const inRows = active.rowIndex >= 0 && active.rowIndex < allRows.length;
|
|
2186
2227
|
const inCols = active.colIndex >= 0 && active.colIndex < allColumns.length;
|
|
@@ -2222,7 +2263,7 @@ export function createSvGridController(rawProps, domIdBase) {
|
|
|
2222
2263
|
* `null` above the cell limit - that case stays on the rAF-deferred effect,
|
|
2223
2264
|
* which keeps a huge grid painting before it totals.
|
|
2224
2265
|
*/
|
|
2225
|
-
const eagerSummaries = $derived.by(()
|
|
2266
|
+
const eagerSummaries = $derived.by(function eagerSummaries_d() {
|
|
2226
2267
|
if (!summarize)
|
|
2227
2268
|
return null;
|
|
2228
2269
|
if (!rowSummariesEnabled)
|
|
@@ -2375,10 +2416,37 @@ export function createSvGridController(rawProps, domIdBase) {
|
|
|
2375
2416
|
// is the reactive signal instead, bumped only when a height actually changes.
|
|
2376
2417
|
const measuredRowHeights = new Map();
|
|
2377
2418
|
let autoRowHeightVersion = $state(0);
|
|
2378
|
-
// A per-row `rowHeight` function already supplies heights, so auto-measuring
|
|
2379
|
-
// would fight it. Fixed numbers are fine - they become the pre-measure estimate.
|
|
2380
|
-
const autoRowHeightOn = $derived(props.autoRowHeight === true && typeof props.rowHeight !== "function");
|
|
2381
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
|
+
});
|
|
2382
2450
|
/** Report a row's measured height. Called by the view's measuring action.
|
|
2383
2451
|
* Sub-pixel churn is ignored so a fractional layout can't loop. */
|
|
2384
2452
|
function reportRowHeight(index, height) {
|
|
@@ -2450,11 +2518,19 @@ export function createSvGridController(rawProps, domIdBase) {
|
|
|
2450
2518
|
// the estimate for rows that have not rendered yet. Touch the version so a
|
|
2451
2519
|
// new measurement re-runs this effect (the Map itself is not reactive).
|
|
2452
2520
|
autoRowHeightVersion;
|
|
2453
|
-
|
|
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
|
|
2454
2526
|
? (index) => measuredRowHeights.get(index) ?? autoRowHeightFallback
|
|
2455
2527
|
: typeof rh === "function"
|
|
2456
2528
|
? rh
|
|
2457
2529
|
: (rh ?? 30);
|
|
2530
|
+
const estimateSize = rowResizeOn
|
|
2531
|
+
? (index) => rowResizeHeights.get(index) ??
|
|
2532
|
+
(typeof base === "function" ? base(index) : base)
|
|
2533
|
+
: base;
|
|
2458
2534
|
virtualizer.setOptions({
|
|
2459
2535
|
count: allRows.length,
|
|
2460
2536
|
estimateSize,
|
|
@@ -2552,7 +2628,7 @@ export function createSvGridController(rawProps, domIdBase) {
|
|
|
2552
2628
|
// Lets the resolver answer from cache without re-invoking the source, so an
|
|
2553
2629
|
// async source fires one request per row instead of one per render.
|
|
2554
2630
|
const asyncEditorColumns = new Set();
|
|
2555
|
-
const headerSelectionState = $derived.by(()
|
|
2631
|
+
const headerSelectionState = $derived.by(function headerSelectionState_d() {
|
|
2556
2632
|
gridStateVersion;
|
|
2557
2633
|
const selectable = allRows.filter((row) => !isGroupRow(row));
|
|
2558
2634
|
if (!selectable.length)
|
|
@@ -2585,7 +2661,7 @@ export function createSvGridController(rawProps, domIdBase) {
|
|
|
2585
2661
|
* Returns `null` when fit scaling is not in effect (off, no room, total
|
|
2586
2662
|
* already >= target). Callers then fall back to the base width.
|
|
2587
2663
|
*/
|
|
2588
|
-
const fittedColumnWidths = $derived.by(()
|
|
2664
|
+
const fittedColumnWidths = $derived.by(function fittedColumnWidths_d() {
|
|
2589
2665
|
// Track viewport size (not scrollVersion) so we don't recompute on
|
|
2590
2666
|
// every scroll - only when the container actually resizes.
|
|
2591
2667
|
viewportVersion;
|
|
@@ -2650,12 +2726,10 @@ export function createSvGridController(rawProps, domIdBase) {
|
|
|
2650
2726
|
widths[lastId] = Math.max(MIN_COLUMN_WIDTH, scalableTarget - runningSum);
|
|
2651
2727
|
return widths;
|
|
2652
2728
|
});
|
|
2653
|
-
let resizePendingWidth = 0;
|
|
2654
|
-
let resizeRaf = null;
|
|
2655
2729
|
/** Where the fill handle should render: the bottom-right cell of the
|
|
2656
2730
|
* selection range (or the active cell if there's no range). Returns
|
|
2657
2731
|
* null when cell selection is off or there is no anchored selection. */
|
|
2658
|
-
const fillHandleCell = $derived.by(()
|
|
2732
|
+
const fillHandleCell = $derived.by(function fillHandleCell_d() {
|
|
2659
2733
|
if (!(props.enableCellSelection ?? false))
|
|
2660
2734
|
return null;
|
|
2661
2735
|
const anchor = selectionRange.anchor;
|
|
@@ -2699,7 +2773,7 @@ export function createSvGridController(rawProps, domIdBase) {
|
|
|
2699
2773
|
* reused by both the facet UI and the row filter. Computing them lazily
|
|
2700
2774
|
* in a $derived means columns with no filter menu open and no active
|
|
2701
2775
|
* filter never pay the iteration cost. */
|
|
2702
|
-
const facetBucketsByColumn = $derived.by(()
|
|
2776
|
+
const facetBucketsByColumn = $derived.by(function facetBucketsByColumn_d() {
|
|
2703
2777
|
const map = new Map();
|
|
2704
2778
|
for (const column of allColumns) {
|
|
2705
2779
|
const meta = isBucketableColumn(column);
|
|
@@ -2786,7 +2860,7 @@ export function createSvGridController(rawProps, domIdBase) {
|
|
|
2786
2860
|
const EMPTY_FACETS = [];
|
|
2787
2861
|
const EMPTY_FACET_SET = new Set();
|
|
2788
2862
|
let facetCache = null;
|
|
2789
|
-
const columnMenuFacetValues = $derived.by(()
|
|
2863
|
+
const columnMenuFacetValues = $derived.by(function columnMenuFacetValues_d() {
|
|
2790
2864
|
// The funnel popover drives via `filterMenuFor`; the column menu's Filter
|
|
2791
2865
|
// tab drives via `columnMenuFor`. Support whichever is open.
|
|
2792
2866
|
const columnId = filterMenuFor ?? columnMenuFor;
|
|
@@ -2816,7 +2890,7 @@ export function createSvGridController(rawProps, domIdBase) {
|
|
|
2816
2890
|
if (!(filterMenuFor ?? columnMenuFor))
|
|
2817
2891
|
facetCache = null;
|
|
2818
2892
|
});
|
|
2819
|
-
const columnMenuVisibleFacets = $derived.by(()
|
|
2893
|
+
const columnMenuVisibleFacets = $derived.by(function columnMenuVisibleFacets_d() {
|
|
2820
2894
|
const query = columnMenuSearch.trim().toLowerCase();
|
|
2821
2895
|
if (!query)
|
|
2822
2896
|
return columnMenuFacetValues;
|
|
@@ -2832,7 +2906,7 @@ export function createSvGridController(rawProps, domIdBase) {
|
|
|
2832
2906
|
* "everything checked", so that case materializes the set once here rather
|
|
2833
2907
|
* than every consumer re-deriving it.
|
|
2834
2908
|
*/
|
|
2835
|
-
const columnMenuSelectedFacets = $derived.by(()
|
|
2909
|
+
const columnMenuSelectedFacets = $derived.by(function columnMenuSelectedFacets_d() {
|
|
2836
2910
|
const columnId = filterMenuFor ?? columnMenuFor;
|
|
2837
2911
|
if (!columnId)
|
|
2838
2912
|
return EMPTY_FACET_SET;
|
|
@@ -2842,7 +2916,7 @@ export function createSvGridController(rawProps, domIdBase) {
|
|
|
2842
2916
|
// active chip input, narrowed by whatever the user has typed. Uncapped - the
|
|
2843
2917
|
// dropdown windows its rows, so a high-cardinality column costs a list of
|
|
2844
2918
|
// strings, not thousands of nodes.
|
|
2845
|
-
const inSuggestValues = $derived.by(()
|
|
2919
|
+
const inSuggestValues = $derived.by(function inSuggestValues_d() {
|
|
2846
2920
|
if (!inSuggestFor)
|
|
2847
2921
|
return EMPTY_FACETS;
|
|
2848
2922
|
const query = inSuggestQuery.trim().toLowerCase();
|
|
@@ -2950,12 +3024,6 @@ export function createSvGridController(rawProps, domIdBase) {
|
|
|
2950
3024
|
set editorSelectAll(v) { editorSelectAll = v; },
|
|
2951
3025
|
get columnWidths() { return columnWidths; },
|
|
2952
3026
|
set columnWidths(v) { columnWidths = v; },
|
|
2953
|
-
get resizingColumnId() { return resizingColumnId; },
|
|
2954
|
-
set resizingColumnId(v) { resizingColumnId = v; },
|
|
2955
|
-
get resizeStartX() { return resizeStartX; },
|
|
2956
|
-
set resizeStartX(v) { resizeStartX = v; },
|
|
2957
|
-
get resizeStartWidth() { return resizeStartWidth; },
|
|
2958
|
-
set resizeStartWidth(v) { resizeStartWidth = v; },
|
|
2959
3027
|
get MIN_COLUMN_WIDTH() { return MIN_COLUMN_WIDTH; },
|
|
2960
3028
|
get columnPinning() { return columnPinning; },
|
|
2961
3029
|
set columnPinning(v) { columnPinning = v; },
|
|
@@ -3278,6 +3346,15 @@ export function createSvGridController(rawProps, domIdBase) {
|
|
|
3278
3346
|
autoRowHeightVersion;
|
|
3279
3347
|
return (index) => measuredRowHeights.get(index);
|
|
3280
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
|
+
},
|
|
3281
3358
|
get virtualRowTotalSize() { return virtualRowTotalSize; },
|
|
3282
3359
|
get virtualRowStart() { return virtualRowStart; },
|
|
3283
3360
|
get virtualRowEnd() { return virtualRowEnd; },
|
|
@@ -3340,13 +3417,6 @@ export function createSvGridController(rawProps, domIdBase) {
|
|
|
3340
3417
|
get getColumnBaseWidth() { return getColumnBaseWidth; },
|
|
3341
3418
|
get fittedColumnWidths() { return fittedColumnWidths; },
|
|
3342
3419
|
get getColumnWidth() { return getColumnWidth; },
|
|
3343
|
-
get resizePendingWidth() { return resizePendingWidth; },
|
|
3344
|
-
set resizePendingWidth(v) { resizePendingWidth = v; },
|
|
3345
|
-
get resizeRaf() { return resizeRaf; },
|
|
3346
|
-
set resizeRaf(v) { resizeRaf = v; },
|
|
3347
|
-
get startColumnResize() { return startColumnResize; },
|
|
3348
|
-
get onColumnResizeMove() { return onColumnResizeMove; },
|
|
3349
|
-
get endColumnResize() { return endColumnResize; },
|
|
3350
3420
|
get setSelection() { return setSelection; },
|
|
3351
3421
|
get extendSelection() { return extendSelection; },
|
|
3352
3422
|
get isCellInSelectedRange() { return isCellInSelectedRange; },
|
|
@@ -3356,6 +3426,15 @@ export function createSvGridController(rawProps, domIdBase) {
|
|
|
3356
3426
|
get isInFillPreview() { return isInFillPreview; },
|
|
3357
3427
|
get fillMarqueeEdges() { return fillMarqueeEdges; },
|
|
3358
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
|
+
},
|
|
3359
3438
|
get readCellRaw() { return readCellRaw; },
|
|
3360
3439
|
get writeCellRaw() { return writeCellRaw; },
|
|
3361
3440
|
get applyFillPattern() { return applyFillPattern; },
|
|
@@ -3465,7 +3544,7 @@ export function createSvGridController(rawProps, domIdBase) {
|
|
|
3465
3544
|
const { cellConditionalFormat, computeRowClass, computeCellClass, computeCellTooltip, computeCellValidity, computeCellNote, getColumnEditorOptions, areEditorOptionsLoading, formatListCellValue, formatCellValue, formatPinnedValue, computePinnedCellClass } = createCellRender(ctx);
|
|
3466
3545
|
const { isCellEditable, isCellEditableAt, getRowColumnValue, getCellDisplayValue, startEditingWithChar, startEditing, stopEditing, startFullRowEdit, setFullRowDraft, commitFullRowEdit, cancelFullRowEdit, saveEditingCell, applyHistoryStep, updateEditingCellValue, onEditorKeyDown, commitAndMoveByTab, focusOnMount, onCellDoubleClick, pasteFromClipboard, onGridPaste } = createEditing(ctx);
|
|
3467
3546
|
const { isRowSelected, toggleRowSelectionById, toggleSelectAllRows, setActiveCell, scrollActiveCellIntoView, setSelection, extendSelection, isCellInSelectedRange, getCellRangeEdges, getSelectionRects, isInFillPreview, fillMarqueeEdges, findColumnById, onCellPointerDown, onCellPointerEnter, endDragSelection, onWindowPointerMove, onCellClick, emitCellDoubleClick } = createSelection(ctx);
|
|
3468
|
-
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);
|
|
3469
3548
|
const { onRowDragStart, onRowDragOver, onRowDragLeave, onRowDrop, onRowsContainerDragOver, onRowsContainerDrop, onRowDragEnd, onRowPointerDown, destroyRowDrag } = createRowDrag(ctx);
|
|
3470
3549
|
const { register: registerAlignedGrid, broadcastScroll: broadcastAlignedScroll, broadcastWidths: broadcastAlignedWidths } = createAlignedGrids(ctx);
|
|
3471
3550
|
const { buildApi } = createGridApi(ctx);
|
|
@@ -3541,7 +3620,6 @@ export function createSvGridController(rawProps, domIdBase) {
|
|
|
3541
3620
|
// this grid still owns (#68). Each of these is a no-op when idle.
|
|
3542
3621
|
$effect(() => {
|
|
3543
3622
|
return () => {
|
|
3544
|
-
endColumnResize();
|
|
3545
3623
|
hideTooltip();
|
|
3546
3624
|
destroyRowDrag();
|
|
3547
3625
|
};
|
package/dist/SvGrid.css
CHANGED
|
@@ -1573,7 +1573,7 @@ select.sv-grid-fr-editor {
|
|
|
1573
1573
|
position: relative;
|
|
1574
1574
|
}
|
|
1575
1575
|
/* Declarative cell validation (column `validate` hook). Invalid cells get a
|
|
1576
|
-
* soft red wash and a red inset ring -
|
|
1576
|
+
* soft red wash and a red inset ring - the conventional spreadsheet invalid-cell look. The
|
|
1577
1577
|
* value keeps rendering as-is; the message (if any) shows as the tooltip. */
|
|
1578
1578
|
.sv-grid-cell-invalid {
|
|
1579
1579
|
background-color: var(--sg-invalid-bg, rgba(239, 68, 68, 0.14)) !important;
|