@rozie-ui/data-table-solid 0.2.5 → 0.3.1

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/dist/index.mjs CHANGED
@@ -4,6 +4,163 @@ import { __rozieInjectStyle, createControllableSignal, parseInlineStyle, rozieAt
4
4
  import Popover from "@rozie-ui/popover-solid";
5
5
  import { createTable, getCoreRowModel, getExpandedRowModel, getFacetedMinMaxValues, getFacetedRowModel, getFacetedUniqueValues, getFilteredRowModel, getGroupedRowModel, getPaginationRowModel, getSortedRowModel } from "@tanstack/table-core";
6
6
  import { Virtualizer, elementScroll, measureElement, observeElementOffset, observeElementRect } from "@tanstack/virtual-core";
7
+ //#region src/helpers/columnDefUtils.ts
8
+ const isSafeKey = (k) => k !== "__proto__" && k !== "constructor" && k !== "prototype";
9
+ const wrapAggregationFn = (fn) => {
10
+ if (typeof fn === "string") return fn;
11
+ if (typeof fn !== "function") return void 0;
12
+ return (columnId, leafRows, childRows) => {
13
+ try {
14
+ return fn(columnId, leafRows, childRows);
15
+ } catch (err) {
16
+ return;
17
+ }
18
+ };
19
+ };
20
+ //#endregion
21
+ //#region src/helpers/indexMath.ts
22
+ const clamp = (v, lo, hi) => v < lo ? lo : v > hi ? hi : v;
23
+ const focusables = (cellEl) => {
24
+ if (!cellEl || !cellEl.querySelectorAll) return [];
25
+ return Array.prototype.slice.call(cellEl.querySelectorAll("button,[href],input,select,textarea,[tabindex]:not([tabindex=\"-1\"])")).filter((n) => !n.disabled);
26
+ };
27
+ const applyUpdater = (updater, current) => typeof updater === "function" ? updater(current) : updater;
28
+ //#endregion
29
+ //#region src/helpers/tsvGrid.ts
30
+ const escapeTsvField = (s) => {
31
+ if (s.indexOf(" ") >= 0 || s.indexOf("\n") >= 0 || s.indexOf("\r") >= 0 || s.indexOf("\"") >= 0) return "\"" + s.replace(/"/g, "\"\"") + "\"";
32
+ return s;
33
+ };
34
+ const parseTsv = (text) => {
35
+ const str = text != null ? String(text) : "";
36
+ if (str === "" || str.length > 2e6) return [];
37
+ const rows = [];
38
+ let row = [];
39
+ let field = "";
40
+ let inQuotes = false;
41
+ let i = 0;
42
+ const n = str.length;
43
+ while (i < n) {
44
+ const ch = str[i];
45
+ if (inQuotes) {
46
+ if (ch === "\"") {
47
+ if (i + 1 < n && str[i + 1] === "\"") {
48
+ field = field + "\"";
49
+ i = i + 2;
50
+ continue;
51
+ }
52
+ inQuotes = false;
53
+ i = i + 1;
54
+ continue;
55
+ }
56
+ field = field + ch;
57
+ i = i + 1;
58
+ continue;
59
+ }
60
+ if (ch === "\"" && field === "") {
61
+ inQuotes = true;
62
+ i = i + 1;
63
+ continue;
64
+ }
65
+ if (ch === " ") {
66
+ row.push(field);
67
+ field = "";
68
+ i = i + 1;
69
+ continue;
70
+ }
71
+ if (ch === "\r") {
72
+ if (i + 1 < n && str[i + 1] === "\n") i = i + 1;
73
+ row.push(field);
74
+ field = "";
75
+ rows.push(row);
76
+ row = [];
77
+ i = i + 1;
78
+ continue;
79
+ }
80
+ if (ch === "\n") {
81
+ row.push(field);
82
+ field = "";
83
+ rows.push(row);
84
+ row = [];
85
+ i = i + 1;
86
+ continue;
87
+ }
88
+ field = field + ch;
89
+ i = i + 1;
90
+ }
91
+ row.push(field);
92
+ rows.push(row);
93
+ if (rows.length > 1) {
94
+ const last = rows[rows.length - 1];
95
+ if (last.length === 1 && last[0] === "") rows.pop();
96
+ }
97
+ return rows;
98
+ };
99
+ const tileGridToBox = (grid, box) => {
100
+ const srcRows = grid.length;
101
+ let srcCols = 0;
102
+ for (let i = 0; i < srcRows; i++) {
103
+ const w = grid[i] && grid[i].length ? grid[i].length : 0;
104
+ if (w > srcCols) srcCols = w;
105
+ }
106
+ if (srcRows <= 0 || srcCols <= 0) return grid;
107
+ const boxRows = box.r1 - box.r0 + 1;
108
+ const boxCols = box.c1 - box.c0 + 1;
109
+ const rows = boxRows > srcRows ? boxRows : srcRows;
110
+ const cols = boxCols > srcCols ? boxCols : srcCols;
111
+ const out = [];
112
+ for (let r = 0; r < rows; r++) {
113
+ const srcLine = grid[r % srcRows] || [];
114
+ const line = [];
115
+ for (let c = 0; c < cols; c++) {
116
+ const v = srcLine[c % srcCols];
117
+ line.push(v != null ? v : "");
118
+ }
119
+ out.push(line);
120
+ }
121
+ return out;
122
+ };
123
+ const tileIndex = (i, lo, hi) => {
124
+ const span = hi - lo + 1;
125
+ if (span <= 1) return lo;
126
+ let k = (i - lo) % span;
127
+ if (k < 0) k = k + span;
128
+ return lo + k;
129
+ };
130
+ //#endregion
131
+ //#region src/helpers/rowValueUtils.ts
132
+ const replaceRowValue = (rows, rowIndex, field, value) => {
133
+ const src = rows || [];
134
+ const out = [];
135
+ for (let i = 0; i < src.length; i++) if (i === rowIndex) out.push({
136
+ ...src[i] || {},
137
+ [field]: value
138
+ });
139
+ else out.push(src[i]);
140
+ return out;
141
+ };
142
+ const replaceRowValues = (rows, rowIndex, fieldValues) => {
143
+ const src = rows || [];
144
+ const fv = fieldValues || {};
145
+ const out = [];
146
+ for (let i = 0; i < src.length; i++) if (i === rowIndex) out.push({
147
+ ...src[i] || {},
148
+ ...fv
149
+ });
150
+ else out.push(src[i]);
151
+ return out;
152
+ };
153
+ const indexOfRowIn = (rows, rowOriginal, rowId) => {
154
+ const list = rows || [];
155
+ for (let i = 0; i < list.length; i++) {
156
+ const r = list[i];
157
+ if (!r) continue;
158
+ if (rowId != null && r.id === rowId) return i;
159
+ if (rowOriginal != null && r.original === rowOriginal) return i;
160
+ }
161
+ return -1;
162
+ };
163
+ //#endregion
7
164
  //#region src/DataTable.tsx
8
165
  __rozieInjectStyle("DataTable-d5dcab4c", `.rozie-data-table[data-rozie-s-d5dcab4c] {
9
166
  border-collapse: collapse;
@@ -11,6 +168,13 @@ __rozieInjectStyle("DataTable-d5dcab4c", `.rozie-data-table[data-rozie-s-d5dcab4
11
168
  font: var(--rdt-font, 14px system-ui, sans-serif);
12
169
  color: var(--rdt-color, inherit);
13
170
  }
171
+ .rozie-data-table.rdt-col-windowed[data-rozie-s-d5dcab4c] {
172
+ table-layout: fixed;
173
+ }
174
+ .rozie-data-table.rdt-col-windowed[data-rozie-s-d5dcab4c] .rdt-th[data-rozie-s-d5dcab4c],
175
+ .rozie-data-table.rdt-col-windowed[data-rozie-s-d5dcab4c] .rdt-td[data-rozie-s-d5dcab4c] {
176
+ box-sizing: border-box;
177
+ }
14
178
  .rdt-sr-live[data-rozie-s-d5dcab4c] {
15
179
  position: absolute;
16
180
  width: 1px;
@@ -328,6 +492,7 @@ function DataTable(_props) {
328
492
  undoLimit: 100,
329
493
  virtual: false,
330
494
  estimateRowHeight: 40,
495
+ autoMeasure: false,
331
496
  maxHeight: ""
332
497
  }, _props), [
333
498
  "data",
@@ -357,6 +522,7 @@ function DataTable(_props) {
357
522
  "undoLimit",
358
523
  "virtual",
359
524
  "estimateRowHeight",
525
+ "autoMeasure",
360
526
  "maxHeight",
361
527
  "children",
362
528
  "ref",
@@ -531,10 +697,11 @@ function DataTable(_props) {
531
697
  setRows(nextRows);
532
698
  setHeaderGroups(nextGroups);
533
699
  setRowModelVer(rowModelVer() + 1);
534
- if (local.virtual && virtualizer) {
700
+ if (rowsWindowed() && virtualizer) {
535
701
  virtualizer.setOptions(virtualizerOptions());
536
702
  virtualizer._willUpdate();
537
703
  }
704
+ remeasureColumnWindow();
538
705
  const nextRowCount = nextRows.length;
539
706
  clampActiveCell(nextRowCount, nextRows.length ? nextRows[0].getVisibleCells().length : nextGroups.length ? (nextGroups[nextGroups.length - 1].headers || []).length : 0);
540
707
  const pgState = table.getState().pagination;
@@ -555,17 +722,28 @@ function DataTable(_props) {
555
722
  };
556
723
  refreshRowModel();
557
724
  gridRoot = __rozieRootRef ? __rozieRootRef.querySelector(".rozie-data-table") : null;
558
- if (local.virtual) {
559
- gridScrollEl = __rozieRootRef ? __rozieRootRef.querySelector(".rdt-scroll") : null;
725
+ if (isWindowed()) gridScrollEl = __rozieRootRef ? __rozieRootRef.querySelector(".rdt-scroll") : null;
726
+ if (rowsWindowed()) {
560
727
  virtualizer = new Virtualizer(virtualizerOptions());
561
728
  virtualizerCleanup = virtualizer._didMount();
562
- setWindowVer(windowVer() + 1);
729
+ }
730
+ if (colsWindowed()) {
731
+ colVirtualizer = new Virtualizer(columnVirtualizerOptions());
732
+ colVirtualizerCleanup = colVirtualizer._didMount();
733
+ }
734
+ if (isWindowed()) setWindowVer(windowVer() + 1);
735
+ if (isWindowed()) {
563
736
  const afterFirstFrame = () => {
564
- remeasureWindow();
565
- if (!(gridScrollEl ? gridScrollEl.clientHeight : 0)) console.warn("[rozie-data-table] virtual is on but the scroll container has no bounded height; set maxHeight or --rozie-data-table-max-height");
566
- const pg = pagination();
567
- const pgConfigured = pg != null && !(pg.pageIndex === 0 && pg.pageSize === 10);
568
- if (local.manual !== true && pgConfigured) console.warn("[rozie-data-table] virtual+pagination: client pagination is configured but virtual windowing replaces it — the pagination chrome is auto-suppressed. Remove the pagination prop or set manual to silence this.");
737
+ if (rowsWindowed()) {
738
+ remeasureWindow();
739
+ if (!(gridScrollEl ? gridScrollEl.clientHeight : 0)) console.warn("[rozie-data-table] virtual is on but the scroll container has no bounded height; set maxHeight or --rozie-data-table-max-height");
740
+ const pg = pagination();
741
+ const pgConfigured = pg != null && !(pg.pageIndex === 0 && pg.pageSize === 10);
742
+ if (local.manual !== true && pgConfigured) console.warn("[rozie-data-table] virtual+pagination: client pagination is configured but virtual windowing replaces it — the pagination chrome is auto-suppressed. Remove the pagination prop or set manual to silence this.");
743
+ }
744
+ if (colsWindowed()) {
745
+ if (!(gridScrollEl ? gridScrollEl.clientWidth : 0)) console.warn("[rozie-data-table] virtual is on for columns but the scroll container has no bounded width; set a CSS width on an ancestor so the column window can be measured");
746
+ }
569
747
  };
570
748
  if (typeof requestAnimationFrame === "function") requestAnimationFrame(() => requestAnimationFrame(afterFirstFrame));
571
749
  else setTimeout(afterFirstFrame, 0);
@@ -576,6 +754,9 @@ function DataTable(_props) {
576
754
  });
577
755
  onCleanup(() => {
578
756
  if (virtualizerCleanup) virtualizerCleanup();
757
+ if (colVirtualizerCleanup) colVirtualizerCleanup();
758
+ teardownColRtlWatch();
759
+ teardownRemeasure();
579
760
  teardownFillDrag();
580
761
  teardownRangeDrag();
581
762
  });
@@ -630,7 +811,11 @@ function DataTable(_props) {
630
811
  let virtualizer = null;
631
812
  let virtualizerCleanup = null;
632
813
  let gridScrollEl = null;
814
+ let colVirtualizer = null;
815
+ let colVirtualizerCleanup = null;
633
816
  let remeasurePending = false;
817
+ let remeasureRaf = null;
818
+ let remeasureDisposed = false;
634
819
  const GRID_PAGE_STEP = 10;
635
820
  let gridRoot = null;
636
821
  let programmatic = 0;
@@ -674,20 +859,6 @@ function DataTable(_props) {
674
859
  function currentData() {
675
860
  return data() != null ? data() : dataDefault();
676
861
  }
677
- function isSafeKey(k) {
678
- return k !== "__proto__" && k !== "constructor" && k !== "prototype";
679
- }
680
- function wrapAggregationFn(fn) {
681
- if (typeof fn === "string") return fn;
682
- if (typeof fn !== "function") return void 0;
683
- return (columnId, leafRows, childRows) => {
684
- try {
685
- return fn(columnId, leafRows, childRows);
686
- } catch (err) {
687
- return;
688
- }
689
- };
690
- }
691
862
  function buildConfigDef(c) {
692
863
  if (!c) return null;
693
864
  if (Array.isArray(c.columns)) {
@@ -732,10 +903,15 @@ function DataTable(_props) {
732
903
  }
733
904
  };
734
905
  }
906
+ let columnDefsCache = null;
907
+ let columnDefsCacheColumnsRef = void 0;
908
+ let columnDefsCacheColRegRef = void 0;
735
909
  function columnDefs() {
910
+ const cfg = local.columns || [];
911
+ const reg = colReg() || {};
912
+ if (columnDefsCache && local.columns === columnDefsCacheColumnsRef && colReg() === columnDefsCacheColRegRef) return columnDefsCache;
736
913
  const byId = Object.create(null);
737
914
  const order = [];
738
- const cfg = local.columns || [];
739
915
  for (const c of cfg) {
740
916
  const def = buildConfigDef(c);
741
917
  if (!def) continue;
@@ -743,7 +919,6 @@ function DataTable(_props) {
743
919
  if (!(id in byId)) order.push(id);
744
920
  byId[id] = def;
745
921
  }
746
- const reg = colReg() || {};
747
922
  for (const id in reg) {
748
923
  if (!isSafeKey(id)) continue;
749
924
  const spec = reg[id];
@@ -771,6 +946,9 @@ function DataTable(_props) {
771
946
  }
772
947
  const out = [];
773
948
  for (const id of order) if (byId[id]) out.push(byId[id]);
949
+ columnDefsCache = out;
950
+ columnDefsCacheColumnsRef = local.columns;
951
+ columnDefsCacheColRegRef = colReg();
774
952
  return out;
775
953
  }
776
954
  const SELECT_COL_ID = "__rdt_select";
@@ -811,9 +989,6 @@ function DataTable(_props) {
811
989
  _props.onSortChange?.(next);
812
990
  programmatic--;
813
991
  }
814
- function applyUpdater(updater, current) {
815
- return typeof updater === "function" ? updater(current) : updater;
816
- }
817
992
  function writeExpanded(next) {
818
993
  if (programmatic) return;
819
994
  programmatic++;
@@ -1021,12 +1196,71 @@ function DataTable(_props) {
1021
1196
  const next = applyUpdater(updater, columnSizingInfo());
1022
1197
  setColumnSizingInfo(next != null ? next : columnSizingInfo());
1023
1198
  }
1199
+ function resolveVirtual() {
1200
+ const v = local.virtual;
1201
+ if (typeof v === "string") {
1202
+ if (v === "rows") return "rows";
1203
+ if (v === "columns") return "columns";
1204
+ if (v === "both") return "both";
1205
+ return "off";
1206
+ }
1207
+ return v === true ? "rows" : "off";
1208
+ }
1209
+ function rowsWindowed() {
1210
+ const s = resolveVirtual();
1211
+ return s === "rows" || s === "both";
1212
+ }
1213
+ function colsWindowed() {
1214
+ const s = resolveVirtual();
1215
+ return s === "columns" || s === "both";
1216
+ }
1217
+ function isWindowed() {
1218
+ return rowsWindowed() || colsWindowed();
1219
+ }
1220
+ function autoMeasureOn() {
1221
+ return local.autoMeasure === true;
1222
+ }
1223
+ function columnCount() {
1224
+ return visibleColCount();
1225
+ }
1226
+ function columnSize(i) {
1227
+ if (!table || !table.getVisibleLeafColumns) return 150;
1228
+ const c = table.getVisibleLeafColumns()[i];
1229
+ return c && typeof c.getSize === "function" ? c.getSize() : 150;
1230
+ }
1231
+ function forcedColumns() {
1232
+ if (!colsWindowed()) return [];
1233
+ const out = [];
1234
+ if (table && table.getVisibleLeafColumns) {
1235
+ const cols = table.getVisibleLeafColumns();
1236
+ for (let i = 0; i < cols.length; i++) {
1237
+ const c = cols[i];
1238
+ if (c && c.getIsPinned && c.getIsPinned()) out.push(i);
1239
+ }
1240
+ }
1241
+ if (!activeIsHeader() && activeColIndex() >= 0 && out.indexOf(activeColIndex()) === -1) out.push(activeColIndex());
1242
+ if (editingRow() >= 0 && editingCol() >= 0 && out.indexOf(editingCol()) === -1) out.push(editingCol());
1243
+ return out;
1244
+ }
1245
+ function windowedCells(row) {
1246
+ windowVer();
1247
+ const cells = visibleCellsFor(row);
1248
+ if (!colsWindowed()) return cells;
1249
+ const idx = windowedColIndices();
1250
+ const out = [];
1251
+ for (let i = 0; i < idx.length; i++) {
1252
+ const cell = cells[idx[i]];
1253
+ if (cell) out.push(cell);
1254
+ }
1255
+ return out;
1256
+ }
1024
1257
  function windowSource() {
1025
1258
  if (!table) return [];
1026
- if (local.virtual) return table.getPrePaginationRowModel().rows;
1259
+ if (rowsWindowed()) return table.getPrePaginationRowModel().rows;
1027
1260
  return table.getRowModel().rows;
1028
1261
  }
1029
1262
  function scheduleRemeasure() {
1263
+ if (remeasureDisposed) return;
1030
1264
  if (remeasurePending) return;
1031
1265
  remeasurePending = true;
1032
1266
  let ranMicro = false;
@@ -1034,6 +1268,7 @@ function DataTable(_props) {
1034
1268
  remeasureWindow();
1035
1269
  };
1036
1270
  const rafPass = () => {
1271
+ remeasureRaf = null;
1037
1272
  remeasurePending = false;
1038
1273
  remeasureWindow();
1039
1274
  };
@@ -1041,9 +1276,18 @@ function DataTable(_props) {
1041
1276
  ranMicro = true;
1042
1277
  queueMicrotask(microPass);
1043
1278
  }
1044
- if (typeof requestAnimationFrame === "function") requestAnimationFrame(rafPass);
1279
+ if (typeof requestAnimationFrame === "function") remeasureRaf = requestAnimationFrame(rafPass);
1045
1280
  else if (ranMicro) remeasurePending = false;
1046
- else setTimeout(rafPass, 0);
1281
+ else remeasureRaf = setTimeout(rafPass, 0);
1282
+ }
1283
+ function teardownRemeasure() {
1284
+ remeasureDisposed = true;
1285
+ if (remeasureRaf != null) {
1286
+ if (typeof requestAnimationFrame === "function") cancelAnimationFrame(remeasureRaf);
1287
+ else clearTimeout(remeasureRaf);
1288
+ remeasureRaf = null;
1289
+ }
1290
+ remeasurePending = false;
1047
1291
  }
1048
1292
  function pinnedEditIndex() {
1049
1293
  if (editingRow() >= 0) return editingRow();
@@ -1056,20 +1300,124 @@ function DataTable(_props) {
1056
1300
  return ms && ms[pin] ? ms[pin] : null;
1057
1301
  }
1058
1302
  function remeasureWindow() {
1303
+ if (remeasureDisposed) return;
1059
1304
  if (!virtualizer || !gridRoot) return;
1060
1305
  if (virtualizer.scrollState) return;
1061
1306
  const trs = gridRoot.querySelectorAll("tbody.rdt-tbody > tr[data-index]");
1062
1307
  for (const tr of trs) virtualizer.measureElement(tr);
1308
+ if (afterRowRemeasure) afterRowRemeasure();
1063
1309
  }
1064
1310
  function virtualItemKey(i) {
1065
1311
  const src = windowSource();
1066
1312
  return src && src[i] ? src[i].id : void 0;
1067
1313
  }
1314
+ const COL_OVERSCAN = 3;
1315
+ let colRtlObserver = null;
1316
+ let colRtlObserverEl = null;
1317
+ function isColRtl() {
1318
+ if (!gridScrollEl || typeof getComputedStyle !== "function") return false;
1319
+ return getComputedStyle(gridScrollEl).direction === "rtl";
1320
+ }
1321
+ function ensureColRtlWatch() {
1322
+ if (!gridScrollEl || colRtlObserverEl === gridScrollEl || typeof MutationObserver !== "function") return;
1323
+ if (colRtlObserver) colRtlObserver.disconnect();
1324
+ colRtlObserver = new MutationObserver(() => {
1325
+ if (colVirtualizer) colVirtualizer.setOptions({
1326
+ ...colVirtualizer.options,
1327
+ isRtl: isColRtl()
1328
+ });
1329
+ });
1330
+ colRtlObserver.observe(gridScrollEl, {
1331
+ attributes: true,
1332
+ attributeFilter: ["dir"]
1333
+ });
1334
+ colRtlObserverEl = gridScrollEl;
1335
+ }
1336
+ function teardownColRtlWatch() {
1337
+ if (colRtlObserver) colRtlObserver.disconnect();
1338
+ colRtlObserver = null;
1339
+ colRtlObserverEl = null;
1340
+ }
1341
+ function columnVirtualizerOptions() {
1342
+ ensureColRtlWatch();
1343
+ return {
1344
+ count: columnCount(),
1345
+ getScrollElement: () => gridScrollEl,
1346
+ estimateSize: (i) => columnSize(i),
1347
+ horizontal: true,
1348
+ isRtl: isColRtl(),
1349
+ observeElementRect,
1350
+ observeElementOffset,
1351
+ scrollToFn: elementScroll,
1352
+ measureElement,
1353
+ overscan: COL_OVERSCAN,
1354
+ onChange: () => {
1355
+ setWindowVer(windowVer() + 1);
1356
+ }
1357
+ };
1358
+ }
1359
+ let measuredRowTotal = 0;
1360
+ let measuredRowCount = 0;
1361
+ let lastFedRowEstimate = 0;
1362
+ let foldedRowHeights = {};
1363
+ let windowVerBumpPending = false;
1364
+ function bumpWindowVer() {
1365
+ if (windowVerBumpPending) return;
1366
+ windowVerBumpPending = true;
1367
+ const flush = () => {
1368
+ windowVerBumpPending = false;
1369
+ setWindowVer(windowVer() + 1);
1370
+ };
1371
+ if (typeof queueMicrotask !== "undefined") queueMicrotask(flush);
1372
+ else setTimeout(flush, 0);
1373
+ }
1374
+ const ESTIMATE_REFEED_DELTA_PX = 4;
1375
+ function estimateRowSize(i) {
1376
+ if (!autoMeasureOn()) return local.estimateRowHeight;
1377
+ if (measuredRowCount === 0) return local.estimateRowHeight;
1378
+ return Math.round(measuredRowTotal / measuredRowCount);
1379
+ }
1380
+ function foldMeasuredRow(index, height) {
1381
+ const prev = foldedRowHeights[index];
1382
+ if (prev === height) return;
1383
+ if (prev == null) {
1384
+ measuredRowTotal = measuredRowTotal + height;
1385
+ measuredRowCount = measuredRowCount + 1;
1386
+ } else measuredRowTotal = measuredRowTotal - prev + height;
1387
+ foldedRowHeights[index] = height;
1388
+ }
1389
+ function refineRowEstimate() {
1390
+ if (!autoMeasureOn() || !virtualizer) return;
1391
+ const items = virtualizer.getVirtualItems();
1392
+ const measurements = virtualizer.getMeasurements();
1393
+ for (let i = 0; i < items.length; i++) {
1394
+ const idx = items[i].index;
1395
+ const m = measurements && measurements[idx];
1396
+ if (m) foldMeasuredRow(idx, m.size);
1397
+ }
1398
+ if (virtualizer.scrollState) return;
1399
+ const est = estimateRowSize(0);
1400
+ if (Math.abs(est - lastFedRowEstimate) < ESTIMATE_REFEED_DELTA_PX) return;
1401
+ const anchorIndex = items.length ? items[0].index : -1;
1402
+ const anchorStart = items.length ? items[0].start : 0;
1403
+ virtualizer.setOptions(virtualizerOptions());
1404
+ virtualizer._willUpdate();
1405
+ lastFedRowEstimate = est;
1406
+ if (anchorIndex >= 0 && gridScrollEl) {
1407
+ const freshMeasurements = virtualizer.getMeasurements();
1408
+ const fresh = freshMeasurements && freshMeasurements[anchorIndex];
1409
+ if (fresh) {
1410
+ const delta = fresh.start - anchorStart;
1411
+ if (delta !== 0) gridScrollEl.scrollTop = gridScrollEl.scrollTop + delta;
1412
+ }
1413
+ }
1414
+ bumpWindowVer();
1415
+ }
1068
1416
  function virtualizerOptions() {
1069
1417
  return {
1070
1418
  count: windowSource().length,
1071
1419
  getScrollElement: () => gridScrollEl,
1072
- estimateSize: () => local.estimateRowHeight,
1420
+ estimateSize: (i) => estimateRowSize(i),
1073
1421
  observeElementRect,
1074
1422
  observeElementOffset,
1075
1423
  scrollToFn: elementScroll,
@@ -1077,7 +1425,7 @@ function DataTable(_props) {
1077
1425
  overscan: 8,
1078
1426
  getItemKey: virtualItemKey,
1079
1427
  onChange: () => {
1080
- setWindowVer(windowVer() + 1);
1428
+ bumpWindowVer();
1081
1429
  scheduleRemeasure();
1082
1430
  }
1083
1431
  };
@@ -1089,8 +1437,8 @@ function DataTable(_props) {
1089
1437
  windowVer();
1090
1438
  editVer();
1091
1439
  if (!virtualizer) {
1092
- if (!local.virtual) return (rows() || []).map((r) => ({
1093
- vi: null,
1440
+ if (!rowsWindowed()) return (rows() || []).map((r, i) => ({
1441
+ vi: { index: i },
1094
1442
  row: r
1095
1443
  }));
1096
1444
  return [];
@@ -1126,7 +1474,7 @@ function DataTable(_props) {
1126
1474
  function padTop() {
1127
1475
  windowVer();
1128
1476
  editVer();
1129
- if (!local.virtual || !virtualizer) return 0;
1477
+ if (!rowsWindowed() || !virtualizer) return 0;
1130
1478
  const items = virtualizer.getVirtualItems();
1131
1479
  let pad = items.length ? items[0].start : 0;
1132
1480
  const pin = pinnedEditIndex();
@@ -1140,7 +1488,7 @@ function DataTable(_props) {
1140
1488
  function padBottom() {
1141
1489
  windowVer();
1142
1490
  editVer();
1143
- if (!local.virtual || !virtualizer) return 0;
1491
+ if (!rowsWindowed() || !virtualizer) return 0;
1144
1492
  const items = virtualizer.getVirtualItems();
1145
1493
  if (!items.length) return 0;
1146
1494
  let pad = virtualizer.getTotalSize() - items[items.length - 1].end;
@@ -1161,11 +1509,59 @@ function DataTable(_props) {
1161
1509
  return false;
1162
1510
  }
1163
1511
  function rowIsOutsideWindow(r) {
1164
- if (!local.virtual || !virtualizer) return false;
1512
+ if (!rowsWindowed() || !virtualizer) return false;
1165
1513
  const items = virtualizer.getVirtualItems();
1166
1514
  for (const it of items) if (it.index === r) return false;
1167
1515
  return true;
1168
1516
  }
1517
+ function windowedColIndices() {
1518
+ windowVer();
1519
+ editVer();
1520
+ if (!colsWindowed()) {
1521
+ const n = columnCount();
1522
+ const out = [];
1523
+ for (let i = 0; i < n; i++) out.push(i);
1524
+ return out;
1525
+ }
1526
+ if (!colVirtualizer) return [];
1527
+ const idx = colVirtualizer.getVirtualItems().map((it) => it.index);
1528
+ const forced = forcedColumns();
1529
+ for (let i = 0; i < forced.length; i++) if (idx.indexOf(forced[i]) === -1) idx.push(forced[i]);
1530
+ idx.sort((a, b) => a - b);
1531
+ return idx;
1532
+ }
1533
+ function colPadLeft() {
1534
+ windowVer();
1535
+ editVer();
1536
+ if (!colsWindowed() || !colVirtualizer) return 0;
1537
+ const items = colVirtualizer.getVirtualItems();
1538
+ let pad = items.length ? items[0].start : 0;
1539
+ if (items.length) {
1540
+ const firstIdx = items[0].index;
1541
+ const forced = forcedColumns();
1542
+ for (let i = 0; i < forced.length; i++) if (forced[i] < firstIdx) pad = pad - columnSize(forced[i]);
1543
+ }
1544
+ return pad < 0 ? 0 : pad;
1545
+ }
1546
+ function colPadRight() {
1547
+ windowVer();
1548
+ editVer();
1549
+ if (!colsWindowed() || !colVirtualizer) return 0;
1550
+ const items = colVirtualizer.getVirtualItems();
1551
+ if (!items.length) return 0;
1552
+ let pad = colVirtualizer.getTotalSize() - items[items.length - 1].end;
1553
+ const lastIdx = items[items.length - 1].index;
1554
+ const forced = forcedColumns();
1555
+ for (let i = 0; i < forced.length; i++) if (forced[i] > lastIdx) pad = pad - columnSize(forced[i]);
1556
+ return pad < 0 ? 0 : pad;
1557
+ }
1558
+ function colIsOutsideWindow(c) {
1559
+ if (!colsWindowed() || !colVirtualizer) return false;
1560
+ const items = colVirtualizer.getVirtualItems();
1561
+ for (const it of items) if (it.index === c) return false;
1562
+ return true;
1563
+ }
1564
+ let afterRowRemeasure = refineRowEstimate;
1169
1565
  const announceState = {
1170
1566
  sorting: null,
1171
1567
  columnFilters: null,
@@ -1582,7 +1978,7 @@ function DataTable(_props) {
1582
1978
  }
1583
1979
  function getRowIndexRelativeToPage(absRow) {
1584
1980
  const abs = absRow == null ? toAbsRow(activeRow()) : Math.trunc(Number(absRow)) || 0;
1585
- if (local.virtual) return abs;
1981
+ if (rowsWindowed()) return abs;
1586
1982
  return abs - pageRowOffset();
1587
1983
  }
1588
1984
  function cut() {
@@ -1607,14 +2003,14 @@ function DataTable(_props) {
1607
2003
  return (hg && hg.headers ? hg.headers : []).indexOf(header);
1608
2004
  }
1609
2005
  function pageRowOffset() {
1610
- if (!isGrid() || local.virtual) return 0;
2006
+ if (!isGrid() || rowsWindowed()) return 0;
1611
2007
  return pageIndex() * pageSize();
1612
2008
  }
1613
2009
  function toAbsRow(localRow) {
1614
2010
  return localRow + pageRowOffset();
1615
2011
  }
1616
2012
  function prePaginationRowCount() {
1617
- if (!table || local.virtual) return bodyRowCount();
2013
+ if (!table || rowsWindowed()) return bodyRowCount();
1618
2014
  const pm = table.getPrePaginationRowModel();
1619
2015
  return pm && pm.rows ? pm.rows.length : bodyRowCount();
1620
2016
  }
@@ -1649,8 +2045,11 @@ function DataTable(_props) {
1649
2045
  const c = nextCol == null ? activeColIndex() : nextCol;
1650
2046
  const lvl = nextLevel == null ? activeHeaderLevel() : nextLevel;
1651
2047
  const header = nextIsHeader == null ? activeIsHeader() : nextIsHeader;
1652
- if (local.virtual && virtualizer && !header && rowIsOutsideWindow(r)) {
1653
- virtualizer.scrollToIndex(r, { align: "center" });
2048
+ const rowOut = rowsWindowed() && virtualizer && rowIsOutsideWindow(r);
2049
+ const colOut = colsWindowed() && colVirtualizer && colIsOutsideWindow(c);
2050
+ if (!header && (rowOut || colOut)) {
2051
+ if (rowOut) virtualizer.scrollToIndex(r, { align: "center" });
2052
+ if (colOut) colVirtualizer.scrollToIndex(c, { align: "center" });
1654
2053
  let focusAttempts = 0;
1655
2054
  const myEpoch = focusIntentEpoch;
1656
2055
  const focusWhenReady = () => {
@@ -1698,9 +2097,6 @@ function DataTable(_props) {
1698
2097
  function bodyRowCount() {
1699
2098
  return (rows() || []).length;
1700
2099
  }
1701
- function clamp(v, lo, hi) {
1702
- return v < lo ? lo : v > hi ? hi : v;
1703
- }
1704
2100
  function headerLeafLevel() {
1705
2101
  const hg = headerGroups() || [];
1706
2102
  return hg.length ? hg.length - 1 : 0;
@@ -1863,10 +2259,6 @@ function DataTable(_props) {
1863
2259
  function currentCellEl() {
1864
2260
  return resolveCellEl(activeIsHeader() ? "__header" : String(activeRow()), activeColIndex(), activeIsHeader() ? activeHeaderLevel() : null);
1865
2261
  }
1866
- function focusables(cellEl) {
1867
- if (!cellEl || !cellEl.querySelectorAll) return [];
1868
- return Array.prototype.slice.call(cellEl.querySelectorAll("button,[href],input,select,textarea,[tabindex]:not([tabindex=\"-1\"])")).filter((n) => !n.disabled);
1869
- }
1870
2262
  function enterControl() {
1871
2263
  const list = focusables(currentCellEl());
1872
2264
  if (!list.length) return;
@@ -2269,6 +2661,40 @@ function DataTable(_props) {
2269
2661
  recoverGridFocus(String(recRow), recCol, null);
2270
2662
  }
2271
2663
  }
2664
+ function windowedHeadersFor(hg, hgLevel) {
2665
+ const headers = hg && hg.headers || [];
2666
+ if (!colsWindowed()) return headers.map((h) => ({
2667
+ header: h,
2668
+ span: h && h.colSpan > 1 ? h.colSpan : 1
2669
+ }));
2670
+ const idx = windowedColIndices();
2671
+ const idxSet = {};
2672
+ for (let i = 0; i < idx.length; i++) idxSet[idx[i]] = true;
2673
+ let cursor = 0;
2674
+ const out = [];
2675
+ for (let i = 0; i < headers.length; i++) {
2676
+ const h = headers[i];
2677
+ const leafCount = h && h.colSpan ? h.colSpan : 1;
2678
+ const start = cursor;
2679
+ const end = cursor + leafCount;
2680
+ cursor = end;
2681
+ let span = 0;
2682
+ for (let c = start; c < end; c++) if (idxSet[c]) span = span + 1;
2683
+ if (span > 0) out.push({
2684
+ header: h,
2685
+ span
2686
+ });
2687
+ }
2688
+ return out;
2689
+ }
2690
+ function windowedColSpan() {
2691
+ return colsWindowed() ? windowedColIndices().length + 2 : visibleColCount();
2692
+ }
2693
+ function remeasureColumnWindow() {
2694
+ if (!colsWindowed() || !colVirtualizer) return;
2695
+ colVirtualizer.setOptions(columnVirtualizerOptions());
2696
+ colVirtualizer._willUpdate();
2697
+ }
2272
2698
  let gridEmptyFallback = false;
2273
2699
  let rangeTransition = false;
2274
2700
  let rangeClickPending = false;
@@ -2451,10 +2877,6 @@ function DataTable(_props) {
2451
2877
  c1: ac > fc ? ac : fc
2452
2878
  };
2453
2879
  }
2454
- function escapeTsvField(s) {
2455
- if (s.indexOf(" ") >= 0 || s.indexOf("\n") >= 0 || s.indexOf("\r") >= 0 || s.indexOf("\"") >= 0) return "\"" + s.replace(/"/g, "\"\"") + "\"";
2456
- return s;
2457
- }
2458
2880
  function rangeToTsv() {
2459
2881
  const box = normalizedRange();
2460
2882
  const r0 = box ? box.r0 : activeRow();
@@ -2472,71 +2894,6 @@ function DataTable(_props) {
2472
2894
  }
2473
2895
  return lines.join("\n");
2474
2896
  }
2475
- function parseTsv(text) {
2476
- const str = text != null ? String(text) : "";
2477
- if (str === "" || str.length > 2e6) return [];
2478
- const rows = [];
2479
- let row = [];
2480
- let field = "";
2481
- let inQuotes = false;
2482
- let i = 0;
2483
- const n = str.length;
2484
- while (i < n) {
2485
- const ch = str[i];
2486
- if (inQuotes) {
2487
- if (ch === "\"") {
2488
- if (i + 1 < n && str[i + 1] === "\"") {
2489
- field = field + "\"";
2490
- i = i + 2;
2491
- continue;
2492
- }
2493
- inQuotes = false;
2494
- i = i + 1;
2495
- continue;
2496
- }
2497
- field = field + ch;
2498
- i = i + 1;
2499
- continue;
2500
- }
2501
- if (ch === "\"" && field === "") {
2502
- inQuotes = true;
2503
- i = i + 1;
2504
- continue;
2505
- }
2506
- if (ch === " ") {
2507
- row.push(field);
2508
- field = "";
2509
- i = i + 1;
2510
- continue;
2511
- }
2512
- if (ch === "\r") {
2513
- if (i + 1 < n && str[i + 1] === "\n") i = i + 1;
2514
- row.push(field);
2515
- field = "";
2516
- rows.push(row);
2517
- row = [];
2518
- i = i + 1;
2519
- continue;
2520
- }
2521
- if (ch === "\n") {
2522
- row.push(field);
2523
- field = "";
2524
- rows.push(row);
2525
- row = [];
2526
- i = i + 1;
2527
- continue;
2528
- }
2529
- field = field + ch;
2530
- i = i + 1;
2531
- }
2532
- row.push(field);
2533
- rows.push(row);
2534
- if (rows.length > 1) {
2535
- const last = rows[rows.length - 1];
2536
- if (last.length === 1 && last[0] === "") rows.pop();
2537
- }
2538
- return rows;
2539
- }
2540
2897
  function copyRange() {
2541
2898
  if (!clipboardActiveAllowed()) return;
2542
2899
  if (typeof navigator === "undefined" || !navigator.clipboard || !navigator.clipboard.writeText) return;
@@ -2603,30 +2960,6 @@ function DataTable(_props) {
2603
2960
  const row = (rows() || [])[rowIndex];
2604
2961
  return row ? row.id : null;
2605
2962
  }
2606
- function tileGridToBox(grid, box) {
2607
- const srcRows = grid.length;
2608
- let srcCols = 0;
2609
- for (let i = 0; i < srcRows; i++) {
2610
- const w = grid[i] && grid[i].length ? grid[i].length : 0;
2611
- if (w > srcCols) srcCols = w;
2612
- }
2613
- if (srcRows <= 0 || srcCols <= 0) return grid;
2614
- const boxRows = box.r1 - box.r0 + 1;
2615
- const boxCols = box.c1 - box.c0 + 1;
2616
- const rows = boxRows > srcRows ? boxRows : srcRows;
2617
- const cols = boxCols > srcCols ? boxCols : srcCols;
2618
- const out = [];
2619
- for (let r = 0; r < rows; r++) {
2620
- const srcLine = grid[r % srcRows] || [];
2621
- const line = [];
2622
- for (let c = 0; c < cols; c++) {
2623
- const v = srcLine[c % srcCols];
2624
- line.push(v != null ? v : "");
2625
- }
2626
- out.push(line);
2627
- }
2628
- return out;
2629
- }
2630
2963
  function pasteRange() {
2631
2964
  if (!clipboardActiveAllowed()) return;
2632
2965
  if (typeof navigator === "undefined" || !navigator.clipboard || !navigator.clipboard.readText) return;
@@ -2686,13 +3019,6 @@ function DataTable(_props) {
2686
3019
  }
2687
3020
  applyGridToRange(grid, r0, c0);
2688
3021
  }
2689
- function tileIndex(i, lo, hi) {
2690
- const span = hi - lo + 1;
2691
- if (span <= 1) return lo;
2692
- let k = (i - lo) % span;
2693
- if (k < 0) k = k + span;
2694
- return lo + k;
2695
- }
2696
3022
  function fillRange(sourceBox, endCell) {
2697
3023
  let box;
2698
3024
  if (sourceBox && sourceBox.r0 != null && endCell) {
@@ -2732,6 +3058,30 @@ function DataTable(_props) {
2732
3058
  let fillDragging = false;
2733
3059
  let fillDragMove = null;
2734
3060
  let fillDragUp = null;
3061
+ let fillEdgeScrollRaf = null;
3062
+ const FILL_EDGE_SCROLL_PX = 24;
3063
+ const FILL_EDGE_SCROLL_STEP = 16;
3064
+ function edgeDelta(clientX, clientY) {
3065
+ if (!gridScrollEl) return {
3066
+ dx: 0,
3067
+ dy: 0
3068
+ };
3069
+ const rect = gridScrollEl.getBoundingClientRect();
3070
+ let dx = 0;
3071
+ let dy = 0;
3072
+ if (colsWindowed()) {
3073
+ if (clientX - rect.left < FILL_EDGE_SCROLL_PX) dx = -FILL_EDGE_SCROLL_STEP;
3074
+ else if (rect.right - clientX < FILL_EDGE_SCROLL_PX) dx = FILL_EDGE_SCROLL_STEP;
3075
+ }
3076
+ if (rowsWindowed()) {
3077
+ if (clientY - rect.top < FILL_EDGE_SCROLL_PX) dy = -FILL_EDGE_SCROLL_STEP;
3078
+ else if (rect.bottom - clientY < FILL_EDGE_SCROLL_PX) dy = FILL_EDGE_SCROLL_STEP;
3079
+ }
3080
+ return {
3081
+ dx,
3082
+ dy
3083
+ };
3084
+ }
2735
3085
  function teardownFillDrag() {
2736
3086
  if (typeof document !== "undefined") {
2737
3087
  if (fillDragMove) document.removeEventListener("pointermove", fillDragMove);
@@ -2740,6 +3090,10 @@ function DataTable(_props) {
2740
3090
  fillDragMove = null;
2741
3091
  fillDragUp = null;
2742
3092
  fillDragging = false;
3093
+ if (fillEdgeScrollRaf != null) {
3094
+ if (typeof cancelAnimationFrame === "function") cancelAnimationFrame(fillEdgeScrollRaf);
3095
+ fillEdgeScrollRaf = null;
3096
+ }
2743
3097
  }
2744
3098
  function cellIndexFromPoint(clientX, clientY) {
2745
3099
  if (typeof document === "undefined" || !document.elementFromPoint) return null;
@@ -2774,14 +3128,42 @@ function DataTable(_props) {
2774
3128
  r: sourceBox.r1,
2775
3129
  c: sourceBox.c1
2776
3130
  } : null;
2777
- const move = (ev) => {
2778
- if (!fillDragging) return;
2779
- const cell = cellIndexFromPoint(ev.clientX, ev.clientY);
3131
+ let lastClientX = 0;
3132
+ let lastClientY = 0;
3133
+ const applyPointAt = (clientX, clientY) => {
3134
+ const cell = cellIndexFromPoint(clientX, clientY);
2780
3135
  if (cell && (!lastCell || cell.r !== lastCell.r || cell.c !== lastCell.c)) {
2781
3136
  lastCell = cell;
2782
3137
  setRangeFocus$local(cell.r, cell.c);
2783
3138
  }
2784
3139
  };
3140
+ const scrollStep = () => {
3141
+ if (!fillDragging) {
3142
+ fillEdgeScrollRaf = null;
3143
+ return;
3144
+ }
3145
+ const d = edgeDelta(lastClientX, lastClientY);
3146
+ if (d.dx === 0 && d.dy === 0) {
3147
+ fillEdgeScrollRaf = null;
3148
+ return;
3149
+ }
3150
+ if (gridScrollEl) {
3151
+ if (d.dx !== 0) gridScrollEl.scrollLeft = gridScrollEl.scrollLeft + d.dx;
3152
+ if (d.dy !== 0) gridScrollEl.scrollTop = gridScrollEl.scrollTop + d.dy;
3153
+ }
3154
+ applyPointAt(lastClientX, lastClientY);
3155
+ fillEdgeScrollRaf = requestAnimationFrame(scrollStep);
3156
+ };
3157
+ const move = (ev) => {
3158
+ if (!fillDragging) return;
3159
+ lastClientX = ev.clientX;
3160
+ lastClientY = ev.clientY;
3161
+ applyPointAt(ev.clientX, ev.clientY);
3162
+ if (fillEdgeScrollRaf == null && typeof requestAnimationFrame === "function") {
3163
+ const d = edgeDelta(ev.clientX, ev.clientY);
3164
+ if (d.dx !== 0 || d.dy !== 0) fillEdgeScrollRaf = requestAnimationFrame(scrollStep);
3165
+ }
3166
+ };
2785
3167
  const up = () => {
2786
3168
  teardownFillDrag();
2787
3169
  if (lastCell && sourceBox && (lastCell.r !== sourceBox.r1 || lastCell.c !== sourceBox.c1)) fillRange(sourceBox, lastCell);
@@ -2872,16 +3254,6 @@ function DataTable(_props) {
2872
3254
  function setInvalid(msg) {
2873
3255
  setInvalidMsg(msg != null ? msg : "");
2874
3256
  }
2875
- function replaceRowValue(rows, rowIndex, field, value) {
2876
- const src = rows || [];
2877
- const out = [];
2878
- for (let i = 0; i < src.length; i++) if (i === rowIndex) out.push({
2879
- ...src[i] || {},
2880
- [field]: value
2881
- });
2882
- else out.push(src[i]);
2883
- return out;
2884
- }
2885
3257
  function sourceIndexOfRow(visibleRowIndex) {
2886
3258
  const row = (rows() || [])[visibleRowIndex];
2887
3259
  if (!row) return visibleRowIndex;
@@ -2988,16 +3360,6 @@ function DataTable(_props) {
2988
3360
  if (typeof requestAnimationFrame === "function") requestAnimationFrame(tryFocus);
2989
3361
  else setTimeout(tryFocus, 0);
2990
3362
  }
2991
- function indexOfRowIn(rows, rowOriginal, rowId) {
2992
- const list = rows || [];
2993
- for (let i = 0; i < list.length; i++) {
2994
- const r = list[i];
2995
- if (!r) continue;
2996
- if (rowId != null && r.id === rowId) return i;
2997
- if (rowOriginal != null && r.original === rowOriginal) return i;
2998
- }
2999
- return -1;
3000
- }
3001
3363
  function endEdit() {
3002
3364
  setEditingRow(-1);
3003
3365
  setEditingCol(-1);
@@ -3252,17 +3614,6 @@ function DataTable(_props) {
3252
3614
  editTransition = false;
3253
3615
  focusCellWhenReady(focusRow, focusCol);
3254
3616
  }
3255
- function replaceRowValues(rows, rowIndex, fieldValues) {
3256
- const src = rows || [];
3257
- const fv = fieldValues || {};
3258
- const out = [];
3259
- for (let i = 0; i < src.length; i++) if (i === rowIndex) out.push({
3260
- ...src[i] || {},
3261
- ...fv
3262
- });
3263
- else out.push(src[i]);
3264
- return out;
3265
- }
3266
3617
  function nextEditableCell(fromRow, fromCol) {
3267
3618
  const rowList = rows() || [];
3268
3619
  const rowCount = rowList.length;
@@ -3513,8 +3864,9 @@ function DataTable(_props) {
3513
3864
  const absLast = prePaginationRowCount() - 1;
3514
3865
  const absRow = clamp(Math.trunc(Number(rowIndex)) || 0, 0, absLast < 0 ? 0 : absLast);
3515
3866
  const prevAbs = toAbsRow(activeRow());
3867
+ const prevCol = activeColIndex();
3516
3868
  const prevIsHeader = activeIsHeader();
3517
- if (local.virtual) {
3869
+ if (rowsWindowed()) {
3518
3870
  setActiveIsHeader(false);
3519
3871
  setActiveInControl(false);
3520
3872
  setActiveRow(absRow);
@@ -3533,7 +3885,7 @@ function DataTable(_props) {
3533
3885
  if (switched) focusAbsCellWhenReady(absRow, localRow, c);
3534
3886
  else focusActiveCell(localRow, c, false);
3535
3887
  }
3536
- if (absRow !== prevAbs || prevIsHeader) _props.onActivecellChange?.({
3888
+ if (absRow !== prevAbs || c !== prevCol || prevIsHeader) _props.onActivecellChange?.({
3537
3889
  rowIndex: absRow,
3538
3890
  colIndex: c
3539
3891
  });
@@ -3649,7 +4001,7 @@ function DataTable(_props) {
3649
4001
  applyGrouping,
3650
4002
  clearGrouping
3651
4003
  }) ?? <Key each={groupingKeys()} by={(gk) => gk}>{(gk) => <span class={"rdt-group-token"} data-group-token="" data-rozie-s-d5dcab4c="">{rozieDisplay(gk())}</span>}</Key>}
3652
- </div></Show>}{<Show when={local.virtual} fallback={<table aria-rowcount={rozieAttr(gridAriaRowCount())} class={"rozie-data-table " + rozieClass({ "rdt-sticky": local.stickyHeader })} role={rozieAttr(tableRole())} onKeyDown={($event) => {
4004
+ </div></Show>}{<Show when={isWindowed()} fallback={<table aria-rowcount={rozieAttr(gridAriaRowCount())} class={"rozie-data-table " + rozieClass({ "rdt-sticky": local.stickyHeader })} role={rozieAttr(tableRole())} onKeyDown={($event) => {
3653
4005
  onGridKeyDown($event);
3654
4006
  }} onFocusIn={($event) => {
3655
4007
  syncActiveFromEvent($event);
@@ -3836,8 +4188,11 @@ function DataTable(_props) {
3836
4188
  </td>
3837
4189
  </tr></Show>}</>}</Key>
3838
4190
  </tbody>
3839
- </table>}><div class={"rdt-scroll"} style={parseInlineStyle(local.maxHeight ? "max-height:" + local.maxHeight + ";overflow:auto;--rozie-data-table-max-height:" + local.maxHeight : "overflow:auto")} data-rozie-s-d5dcab4c="">
3840
- <table aria-rowcount={rozieAttr(gridAriaRowCount())} class={"rozie-data-table " + rozieClass({ "rdt-sticky": local.stickyHeader })} role={rozieAttr(tableRole())} onKeyDown={($event) => {
4191
+ </table>}><div class={"rdt-scroll"} style={parseInlineStyle(rowsWindowed() && local.maxHeight ? "max-height:" + local.maxHeight + ";overflow:auto;--rozie-data-table-max-height:" + local.maxHeight : "overflow:auto")} data-rozie-s-d5dcab4c="">
4192
+ <table aria-rowcount={rozieAttr(gridAriaRowCount())} class={"rozie-data-table " + rozieClass({
4193
+ "rdt-sticky": local.stickyHeader,
4194
+ "rdt-col-windowed": colsWindowed()
4195
+ })} role={rozieAttr(tableRole())} onKeyDown={($event) => {
3841
4196
  onGridKeyDown($event);
3842
4197
  }} onFocusIn={($event) => {
3843
4198
  syncActiveFromEvent($event);
@@ -3852,53 +4207,54 @@ function DataTable(_props) {
3852
4207
  }} data-rozie-s-d5dcab4c="">
3853
4208
  <thead class={"rdt-thead"} role="rowgroup" data-rozie-s-d5dcab4c="">
3854
4209
  <Key each={headerGroups()} by={(hg) => hg.id}>{(hg, hgLevel) => <tr class={"rdt-tr"} role="row" aria-rowindex={rozieAttr(hgLevel() + 1)} data-rozie-s-d5dcab4c="">
3855
- <Key each={hg().headers} by={(header) => header.id}>{(header) => <th class={"rdt-th " + rozieClass({
3856
- "rdt-select-th": isSelectColumn(header().column.id),
3857
- "rdt-expander-th": isExpanderColumn(header().column.id),
3858
- "rdt-th-resizing": columnIsResizing(header().column.id),
3859
- "rdt-cell-active": isActiveCell("__header", headerColIndexOf(hg(), header()), hgLevel())
3860
- })} role="columnheader" data-col={rozieAttr(header().column.id)} data-grid-cell="" data-row="__header" data-header-level={rozieAttr(hgLevel())} colSpan={rozieAttr(header().colSpan > 1 ? header().colSpan : null)} data-col-index={rozieAttr(headerColIndexOf(hg(), header()))} tabIndex={rozieAttr(cellTabindex("__header", headerColIndexOf(hg(), header()), hgLevel()))} aria-sort={rozieAttr(ariaSortFor(header().column.id))} style={parseInlineStyle(thStyle(header().column.id))} data-rozie-s-d5dcab4c="">
3861
- {<Show when={isSelectColumn(header().column.id)} fallback={<Show when={isExpanderColumn(header().column.id)} fallback={<span style={{ display: "contents" }} data-rozie-s-d5dcab4c="">
3862
- {<Show when={header().column.getCanSort && header().column.getCanSort()} fallback={<span style={{ display: "contents" }} data-rozie-s-d5dcab4c="">
4210
+
4211
+ {<Show when={colsWindowed()}><th class={"rdt-col-spacer"} aria-hidden="true" style={parseInlineStyle("width:" + colPadLeft() + "px;padding:0;border:0")} data-rozie-s-d5dcab4c="" /></Show>}<Key each={windowedHeadersFor(hg(), hgLevel())} by={(wh) => wh.header.id}>{(wh) => <th class={"rdt-th " + rozieClass({
4212
+ "rdt-select-th": isSelectColumn(wh().header.column.id),
4213
+ "rdt-expander-th": isExpanderColumn(wh().header.column.id),
4214
+ "rdt-th-resizing": columnIsResizing(wh().header.column.id),
4215
+ "rdt-cell-active": isActiveCell("__header", headerColIndexOf(hg(), wh().header), hgLevel())
4216
+ })} role="columnheader" data-col={rozieAttr(wh().header.column.id)} data-grid-cell="" data-row="__header" data-header-level={rozieAttr(hgLevel())} colSpan={rozieAttr(wh().span > 1 ? wh().span : null)} data-col-index={rozieAttr(headerColIndexOf(hg(), wh().header))} tabIndex={rozieAttr(cellTabindex("__header", headerColIndexOf(hg(), wh().header), hgLevel()))} aria-sort={rozieAttr(ariaSortFor(wh().header.column.id))} style={parseInlineStyle(thStyle(wh().header.column.id))} data-rozie-s-d5dcab4c="">
4217
+ {<Show when={isSelectColumn(wh().header.column.id)} fallback={<Show when={isExpanderColumn(wh().header.column.id)} fallback={<span style={{ display: "contents" }} data-rozie-s-d5dcab4c="">
4218
+ {<Show when={wh().header.column.getCanSort && wh().header.column.getCanSort()} fallback={<span style={{ display: "contents" }} data-rozie-s-d5dcab4c="">
3863
4219
  <span class={"rdt-header-label"} data-rozie-s-d5dcab4c="">
3864
4220
  {(_props.colHeaderSlot ?? _props.slots?.["colHeader"])?.({
3865
- columnId: header().column.id,
3866
- column: header().column,
3867
- label: headerLabel(header().column.id)
3868
- }) ?? rozieDisplay(headerLabel(header().column.id))}
4221
+ columnId: wh().header.column.id,
4222
+ column: wh().header.column,
4223
+ label: headerLabel(wh().header.column.id)
4224
+ }) ?? rozieDisplay(headerLabel(wh().header.column.id))}
3869
4225
  </span>
3870
4226
  </span>}><button type="button" class={"rdt-sort-btn"} onClick={($event) => {
3871
- onHeaderSort(header().column.id, $event);
4227
+ onHeaderSort(wh().header.column.id, $event);
3872
4228
  }} data-rozie-s-d5dcab4c="">
3873
4229
  <span class={"rdt-header-label"} data-rozie-s-d5dcab4c="">
3874
4230
  {(_props.colHeaderSlot ?? _props.slots?.["colHeader"])?.({
3875
- columnId: header().column.id,
3876
- column: header().column,
3877
- label: headerLabel(header().column.id)
3878
- }) ?? rozieDisplay(headerLabel(header().column.id))}
4231
+ columnId: wh().header.column.id,
4232
+ column: wh().header.column,
4233
+ label: headerLabel(wh().header.column.id)
4234
+ }) ?? rozieDisplay(headerLabel(wh().header.column.id))}
3879
4235
  </span>
3880
- <span class={"rdt-sort-ind"} aria-hidden="true" data-rozie-s-d5dcab4c="">{rozieDisplay(sortIndicator(header().column.id))}</span>
4236
+ <span class={"rdt-sort-ind"} aria-hidden="true" data-rozie-s-d5dcab4c="">{rozieDisplay(sortIndicator(wh().header.column.id))}</span>
3881
4237
  </button></Show>}<Popover trigger="click" placement="bottom-end" strategy="fixed" offset={4} data-rozie-s-d5dcab4c="" anchorSlot={() => <>
3882
- <button type="button" class={"rdt-col-menu-trigger"} aria-label={rozieAttr("Column options for " + headerLabel(header().column.id))} data-rozie-s-d5dcab4c="">⋯</button>
4238
+ <button type="button" class={"rdt-col-menu-trigger"} aria-label={rozieAttr("Column options for " + headerLabel(wh().header.column.id))} data-rozie-s-d5dcab4c="">⋯</button>
3883
4239
  </>}><div class={"rdt-col-menu"} role="menu" data-rozie-s-d5dcab4c="">
3884
- <button type="button" role="menuitem" aria-pressed={columnPinSide(header().column.id) === "left"} class={"rdt-col-menu-item"} onClick={($event) => {
3885
- onPinColumn(header().column.id, "left", $event);
4240
+ <button type="button" role="menuitem" aria-pressed={columnPinSide(wh().header.column.id) === "left"} class={"rdt-col-menu-item"} onClick={($event) => {
4241
+ onPinColumn(wh().header.column.id, "left", $event);
3886
4242
  }} data-rozie-s-d5dcab4c="">Pin left</button>
3887
- <button type="button" role="menuitem" aria-pressed={columnPinSide(header().column.id) === "right"} class={"rdt-col-menu-item"} onClick={($event) => {
3888
- onPinColumn(header().column.id, "right", $event);
4243
+ <button type="button" role="menuitem" aria-pressed={columnPinSide(wh().header.column.id) === "right"} class={"rdt-col-menu-item"} onClick={($event) => {
4244
+ onPinColumn(wh().header.column.id, "right", $event);
3889
4245
  }} data-rozie-s-d5dcab4c="">Pin right</button>
3890
- <button type="button" role="menuitem" aria-pressed={!columnPinSide(header().column.id)} class={"rdt-col-menu-item"} onClick={($event) => {
3891
- onPinColumn(header().column.id, false, $event);
4246
+ <button type="button" role="menuitem" aria-pressed={!columnPinSide(wh().header.column.id)} class={"rdt-col-menu-item"} onClick={($event) => {
4247
+ onPinColumn(wh().header.column.id, false, $event);
3892
4248
  }} data-rozie-s-d5dcab4c="">Unpin</button>
3893
4249
  <hr class={"rdt-col-menu-sep"} data-rozie-s-d5dcab4c="" />
3894
4250
  <button type="button" role="menuitem" class={"rdt-col-menu-item"} onClick={($event) => {
3895
- onHideColumn(header().column.id, $event);
4251
+ onHideColumn(wh().header.column.id, $event);
3896
4252
  }} data-rozie-s-d5dcab4c="">Hide column</button>
3897
4253
  </div></Popover>
3898
- <button type="button" aria-label={rozieAttr("Resize " + headerLabel(header().column.id))} class={"rdt-resize-handle"} onPointerDown={($event) => {
3899
- onResizeStart(header().column.id, $event);
4254
+ <button type="button" aria-label={rozieAttr("Resize " + headerLabel(wh().header.column.id))} class={"rdt-resize-handle"} onPointerDown={($event) => {
4255
+ onResizeStart(wh().header.column.id, $event);
3900
4256
  }} onTouchStart={($event) => {
3901
- onResizeStart(header().column.id, $event);
4257
+ onResizeStart(wh().header.column.id, $event);
3902
4258
  }} data-rozie-s-d5dcab4c=""><span class={"rdt-resize-grip"} aria-hidden="true" data-rozie-s-d5dcab4c="" /></button>
3903
4259
  </span>}><span style={{ display: "contents" }} data-rozie-s-d5dcab4c="" /></Show>}><span style={{ display: "contents" }} data-rozie-s-d5dcab4c="">
3904
4260
  {(_props.selectAllSlot ?? _props.slots?.["selectAll"])?.({
@@ -3909,30 +4265,31 @@ function DataTable(_props) {
3909
4265
  onToggleAllRows($event);
3910
4266
  }} data-rozie-s-d5dcab4c="" /></Show>}
3911
4267
  </span></Show>}</th>}</Key>
3912
- </tr>}</Key>
4268
+
4269
+ {<Show when={colsWindowed()}><th class={"rdt-col-spacer"} aria-hidden="true" style={parseInlineStyle("width:" + colPadRight() + "px;padding:0;border:0")} data-rozie-s-d5dcab4c="" /></Show>}</tr>}</Key>
3913
4270
 
3914
4271
  {<Show when={hasAnyFilterableColumn()}><tr class={"rdt-filter-row"} data-rozie-s-d5dcab4c="">
3915
- <Key each={headerGroups()[headerGroups().length - 1].headers} by={(header) => header.id}>{(header) => <th class={"rdt-filter-cell"} role="presentation" style={parseInlineStyle(pinStyle(header().column.id))} data-rozie-s-d5dcab4c="">
3916
- {<Show when={isSelectColumn(header().column.id)} fallback={<Show when={isExpanderColumn(header().column.id)} fallback={<span style={{ display: "contents" }} data-rozie-s-d5dcab4c="">
3917
- {<Show when={columnIsFilterable(header().column.id) && !hasFilterSlot()}><input type="text" aria-label={rozieAttr("Filter " + headerLabel(header().column.id))} class={"rdt-col-filter"} value={columnFilterValue(header().column.id)} onInput={($event) => {
3918
- onColumnFilterInput(header().column.id, $event);
4272
+ {<Show when={colsWindowed()}><th class={"rdt-col-spacer"} aria-hidden="true" style={parseInlineStyle("width:" + colPadLeft() + "px;padding:0;border:0")} data-rozie-s-d5dcab4c="" /></Show>}<Key each={windowedHeadersFor(headerGroups()[headerGroups().length - 1], headerGroups().length - 1)} by={(wh) => wh.header.id}>{(wh) => <th class={"rdt-filter-cell"} role="presentation" data-col={rozieAttr(wh().header.column.id)} style={parseInlineStyle(pinStyle(wh().header.column.id))} data-rozie-s-d5dcab4c="">
4273
+ {<Show when={isSelectColumn(wh().header.column.id)} fallback={<Show when={isExpanderColumn(wh().header.column.id)} fallback={<span style={{ display: "contents" }} data-rozie-s-d5dcab4c="">
4274
+ {<Show when={columnIsFilterable(wh().header.column.id) && !hasFilterSlot()}><input type="text" aria-label={rozieAttr("Filter " + headerLabel(wh().header.column.id))} class={"rdt-col-filter"} value={columnFilterValue(wh().header.column.id)} onInput={($event) => {
4275
+ onColumnFilterInput(wh().header.column.id, $event);
3919
4276
  }} onClick={($event) => {
3920
4277
  stopEvent($event);
3921
- }} data-rozie-s-d5dcab4c="" /></Show>}{<Show when={columnIsFilterable(header().column.id)}><span style={{ display: "contents" }} data-rozie-s-d5dcab4c="">
4278
+ }} data-rozie-s-d5dcab4c="" /></Show>}{<Show when={columnIsFilterable(wh().header.column.id)}><span style={{ display: "contents" }} data-rozie-s-d5dcab4c="">
3922
4279
  {(_props.filterSlot ?? _props.slots?.["filter"])?.({
3923
- columnId: header().column.id,
3924
- value: columnFilterValue(header().column.id),
3925
- uniqueValues: getFacetedUniqueValues$1(header().column.id),
3926
- minMax: getFacetedMinMaxValues$1(header().column.id),
4280
+ columnId: wh().header.column.id,
4281
+ value: columnFilterValue(wh().header.column.id),
4282
+ uniqueValues: getFacetedUniqueValues$1(wh().header.column.id),
4283
+ minMax: getFacetedMinMaxValues$1(wh().header.column.id),
3927
4284
  setFilter: setColumnFilter
3928
4285
  })}
3929
4286
  </span></Show>}</span>}><span style={{ display: "contents" }} data-rozie-s-d5dcab4c="" /></Show>}><span style={{ display: "contents" }} data-rozie-s-d5dcab4c="" /></Show>}</th>}</Key>
3930
- </tr></Show>}</thead>
4287
+ {<Show when={colsWindowed()}><th class={"rdt-col-spacer"} aria-hidden="true" style={parseInlineStyle("width:" + colPadRight() + "px;padding:0;border:0")} data-rozie-s-d5dcab4c="" /></Show>}</tr></Show>}</thead>
3931
4288
 
3932
4289
  <tbody class={"rdt-tbody"} role="rowgroup" data-rozie-s-d5dcab4c="">
3933
4290
 
3934
4291
  <tr class={"rdt-spacer"} aria-hidden="true" data-rozie-s-d5dcab4c="">
3935
- <td colSpan={rozieAttr(visibleColCount())} style={parseInlineStyle("height:" + padTop() + "px;padding:0;border:0")} data-rozie-s-d5dcab4c="" />
4292
+ <td colSpan={rozieAttr(windowedColSpan())} style={parseInlineStyle("height:" + padTop() + "px;padding:0;border:0")} data-rozie-s-d5dcab4c="" />
3936
4293
  </tr>
3937
4294
 
3938
4295
  <Key each={windowedRows()} by={(wr) => wr.row.id}>{(wr) => <>
@@ -3940,7 +4297,8 @@ function DataTable(_props) {
3940
4297
  "rdt-group-header": rowIsGrouped(wr().row),
3941
4298
  "rdt-row-pinned": wr().pinned
3942
4299
  })} role="row" data-row={rozieAttr(wr().vi.index)} aria-rowindex={rozieAttr(headerRowCount() + wr().vi.index + 1)} data-index={rozieAttr(wr().vi.index)} data-pinned={rozieAttr(wr().pinned ? "true" : null)} data-depth={rozieAttr(wr().row.depth)} data-group-header={rozieAttr(rowIsGrouped(wr().row) ? wr().row.id : null)} data-group-leaf={rozieAttr(groupingActive() && !rowIsGrouped(wr().row) ? wr().row.id : null)} aria-expanded={(rowIsGrouped(wr().row) ? !!rowIsExpanded(wr().row) : null) ?? void 0} aria-selected={(local.selectionMode !== "none" ? !!rowIsSelected(wr().row) : null) ?? void 0} aria-level={rozieAttr(groupingActive() ? wr().row.depth + 1 : null)} data-rozie-s-d5dcab4c="">
3943
- <Key each={visibleCellsFor(wr().row)} by={(cell) => cell.id}>{(cell) => <td class={"rdt-td " + rozieClass({
4300
+
4301
+ {<Show when={colsWindowed()}><td class={"rdt-col-spacer"} aria-hidden="true" style={parseInlineStyle("width:" + colPadLeft() + "px;padding:0;border:0")} data-rozie-s-d5dcab4c="" /></Show>}<Key each={windowedCells(wr().row)} by={(cell) => cell.id}>{(cell) => <td class={"rdt-td " + rozieClass({
3944
4302
  "rdt-select-td": isSelectColumn(cell().column.id),
3945
4303
  "rdt-expander-td": isExpanderColumn(cell().column.id),
3946
4304
  "rdt-in-range": inRange(wr().vi.index, colIndexOf(wr().row, cell())),
@@ -4018,20 +4376,21 @@ function DataTable(_props) {
4018
4376
  }} data-rozie-s-d5dcab4c="">{rozieDisplay(rowIsExpanded(wr().row) ? "▾" : "▸")}</button></Show>}</span></Show>}{<Show when={isFillHandleCell(wr().vi.index, colIndexOf(wr().row, cell()))}><span data-fill-handle="" data-testid="fill-handle" aria-hidden="true" class={"rdt-fill-handle"} onPointerDown={($event) => {
4019
4377
  onFillHandlePointerDown($event);
4020
4378
  }} data-rozie-s-d5dcab4c="" /></Show>}</td>}</Key>
4021
- </tr>
4379
+
4380
+ {<Show when={colsWindowed()}><td class={"rdt-col-spacer"} aria-hidden="true" style={parseInlineStyle("width:" + colPadRight() + "px;padding:0;border:0")} data-rozie-s-d5dcab4c="" /></Show>}</tr>
4022
4381
 
4023
4382
  {<Show when={rowShowsDetail(wr().row)}><tr class={"rdt-detail-row"} role="row" data-detail-row={rozieAttr(wr().row.id)} data-rozie-s-d5dcab4c="">
4024
- <td class={"rdt-detail-cell"} colSpan={rozieAttr(visibleColCount())} data-rozie-s-d5dcab4c="">
4383
+ <td class={"rdt-detail-cell"} colSpan={rozieAttr(windowedColSpan())} data-rozie-s-d5dcab4c="">
4025
4384
  {(_props.detailSlot ?? _props.slots?.["detail"])?.({ row: wr().row.original })}
4026
4385
  </td>
4027
4386
  </tr></Show>}</>}</Key>
4028
4387
 
4029
4388
  <tr class={"rdt-spacer"} aria-hidden="true" data-rozie-s-d5dcab4c="">
4030
- <td colSpan={rozieAttr(visibleColCount())} style={parseInlineStyle("height:" + padBottom() + "px;padding:0;border:0")} data-rozie-s-d5dcab4c="" />
4389
+ <td colSpan={rozieAttr(windowedColSpan())} style={parseInlineStyle("height:" + padBottom() + "px;padding:0;border:0")} data-rozie-s-d5dcab4c="" />
4031
4390
  </tr>
4032
4391
  </tbody>
4033
4392
  </table>
4034
- </div></Show>}{<Show when={!local.virtual}><div class={"rdt-pagination"} role="group" aria-label="Pagination" data-rozie-s-d5dcab4c="">
4393
+ </div></Show>}{<Show when={!rowsWindowed()}><div class={"rdt-pagination"} role="group" aria-label="Pagination" data-rozie-s-d5dcab4c="">
4035
4394
  <button type="button" class={"rdt-page-btn rdt-page-prev"} disabled={!canPrevPage()} onClick={($event) => {
4036
4395
  onPrevPage();
4037
4396
  }} data-rozie-s-d5dcab4c="">Prev</button>