react-glide-table 1.4.1 → 1.7.0

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.cjs CHANGED
@@ -27,20 +27,31 @@ __export(src_exports, {
27
27
  DEFAULT_TREE_PARENT_ID_FIELD: () => DEFAULT_TREE_PARENT_ID_FIELD,
28
28
  DEFAULT_TREE_QTY_FIELD: () => DEFAULT_TREE_QTY_FIELD,
29
29
  DataTable: () => DataTable,
30
+ INLINE_SEARCH_MAX_RESULTS: () => INLINE_SEARCH_MAX_RESULTS,
30
31
  Table: () => Table,
31
32
  applyCellEdit: () => applyCellEdit,
32
33
  applyFillData: () => applyFillData,
33
34
  applySelectionUpdater: () => applySelectionUpdater,
34
35
  buildColumnFreezeOffsets: () => buildColumnFreezeOffsets,
35
36
  buildColumnRowSpanMap: () => buildColumnRowSpanMap,
37
+ buildFlatSearchCorpus: () => buildFlatSearchCorpus,
36
38
  buildRowsPastePayload: () => buildRowsPastePayload,
39
+ buildSearchMatchKey: () => buildSearchMatchKey,
40
+ buildSearchMatchKeys: () => buildSearchMatchKeys,
41
+ buildTreeSearchCorpus: () => buildTreeSearchCorpus,
37
42
  canExpandRow: () => canExpandRow,
43
+ cellValueToSearchText: () => cellValueToSearchText,
44
+ collectAncestorKeysToExpand: () => collectAncestorKeysToExpand,
38
45
  collectCopyRowEntries: () => collectCopyRowEntries,
39
46
  collectCopyRows: () => collectCopyRows,
40
47
  collectFillChanges: () => collectFillChanges,
41
48
  collectRowSpanColumns: () => collectRowSpanColumns,
49
+ collectSearchMatchesInRange: () => collectSearchMatchesInRange,
50
+ createSearchRegex: () => createSearchRegex,
42
51
  createTable: () => createTable,
52
+ escapeSearchRegex: () => escapeSearchRegex,
43
53
  flattenSubtreeRows: () => flattenSubtreeRows,
54
+ formatSearchResultLabel: () => formatSearchResultLabel,
44
55
  getCellEditDraftValue: () => getCellEditDraftValue,
45
56
  getCellSelectionEdgeStyle: () => getCellSelectionEdgeStyle,
46
57
  getColumnEditType: () => getColumnEditType,
@@ -52,10 +63,15 @@ __export(src_exports, {
52
63
  isCellInSelection: () => isCellInSelection,
53
64
  isColumnEditable: () => isColumnEditable,
54
65
  isEditablePasteTarget: () => isEditablePasteTarget,
66
+ mapSearchResultToVisibleItem: () => mapSearchResultToVisibleItem,
67
+ mapSearchResultsToVisibleKeys: () => mapSearchResultsToVisibleKeys,
55
68
  measureMergedSpanRowHeights: () => measureMergedSpanRowHeights,
69
+ nextSearchIndex: () => nextSearchIndex,
70
+ nextSearchStride: () => nextSearchStride,
56
71
  parseCellEditValue: () => parseCellEditValue,
57
72
  parseClipboardTSV: () => parseClipboardTSV,
58
73
  parseClipboardTSVWithDepths: () => parseClipboardTSVWithDepths,
74
+ previousSearchIndex: () => previousSearchIndex,
59
75
  resolveColumnFreezeSide: () => resolveColumnFreezeSide,
60
76
  resolveDataTableLabels: () => resolveDataTableLabels,
61
77
  resolvePasteColumnIds: () => resolvePasteColumnIds,
@@ -69,6 +85,7 @@ __export(src_exports, {
69
85
  useCellSelection: () => useCellSelection,
70
86
  useConvertTreeData: () => useConvertTreeData,
71
87
  useGlideTable: () => useGlideTable,
88
+ useInlineSearch: () => useInlineSearch,
72
89
  writeSelectionToClipboard: () => writeSelectionToClipboard
73
90
  });
74
91
  module.exports = __toCommonJS(src_exports);
@@ -80,7 +97,12 @@ var DEFAULT_DATA_TABLE_LABELS = {
80
97
  selection: (selectedCount) => selectedCount > 0 ? `\u2713 ${selectedCount} selected` : null,
81
98
  expandRow: "Expand row",
82
99
  collapseRow: "Collapse row",
83
- resizeColumn: "Resize column"
100
+ resizeColumn: "Resize column",
101
+ searchPlaceholder: "Search\u2026",
102
+ searchResultHint: "Type to search",
103
+ searchPrevious: "Previous result",
104
+ searchNext: "Next result",
105
+ searchClose: "Close search"
84
106
  };
85
107
  function resolveDataTableLabels(partial) {
86
108
  return {
@@ -98,7 +120,7 @@ var DEFAULT_TREE_QTY_FIELD = "qty";
98
120
  // src/core/useGlideTable.ts
99
121
  var import_react_table = require("@tanstack/react-table");
100
122
  var import_react_virtual = require("@tanstack/react-virtual");
101
- var import_react4 = require("react");
123
+ var import_react5 = require("react");
102
124
 
103
125
  // src/components/ui/table/constants.ts
104
126
  var CELL_ALIGN_CLASS = {
@@ -110,6 +132,7 @@ var ROW_HOVER_CLASS = "row-hoverable";
110
132
  var ROW_HOVERED_BG_CLASS = "row-hovered";
111
133
  var CELL_SELECTION_FILL_CLASS = "cell-selection-fill";
112
134
  var DATA_TABLE_ROW_HEIGHT = 44;
135
+ var DATA_TABLE_HEADER_ROW_HEIGHT = 40;
113
136
  var DATA_TABLE_VIRTUAL_OVERSCAN = 8;
114
137
  var DATA_TABLE_COLUMN_SIZE = 150;
115
138
  var DATA_TABLE_COLUMN_MIN_SIZE = 40;
@@ -263,6 +286,36 @@ function getCellSelectionBounds(start, end) {
263
286
  endCol: Math.max(start.col, end.col)
264
287
  };
265
288
  }
289
+ function getCellNavigationDelta(key) {
290
+ switch (key) {
291
+ case "ArrowUp":
292
+ case "w":
293
+ case "W":
294
+ return { row: -1, col: 0 };
295
+ case "ArrowDown":
296
+ case "s":
297
+ case "S":
298
+ return { row: 1, col: 0 };
299
+ case "ArrowLeft":
300
+ case "a":
301
+ case "A":
302
+ return { row: 0, col: -1 };
303
+ case "ArrowRight":
304
+ case "d":
305
+ case "D":
306
+ return { row: 0, col: 1 };
307
+ default:
308
+ return null;
309
+ }
310
+ }
311
+ function clampCellPosition(position, rowCount, columnCount) {
312
+ const maxRow = Math.max(rowCount - 1, 0);
313
+ const maxCol = Math.max(columnCount - 1, 0);
314
+ return {
315
+ row: Math.min(Math.max(position.row, 0), maxRow),
316
+ col: Math.min(Math.max(position.col, 0), maxCol)
317
+ };
318
+ }
266
319
  function measureMergedSpanRowHeights(rowIndex, rowSpan, cellElement) {
267
320
  if (rowSpan <= 1) return void 0;
268
321
  const tbody = cellElement?.closest("tbody") ?? (typeof document !== "undefined" ? document.querySelector("tbody.data-table-body") : null);
@@ -786,26 +839,44 @@ function useCellSelection({
786
839
  data,
787
840
  rows,
788
841
  enabled = true,
842
+ columnCount = 0,
789
843
  enableSubtreeCopy = false,
790
844
  enableInsertPaste = true,
791
845
  onDataChange,
792
846
  onBatchChange,
793
- onRowsPaste
847
+ onRowsPaste,
848
+ onCellNavigate
794
849
  }) {
795
850
  const [dragState, setDragState] = (0, import_react2.useState)(INITIAL_DRAG_STATE);
796
851
  const pendingPasteModeRef = (0, import_react2.useRef)(null);
852
+ const dragStateRef = (0, import_react2.useRef)(dragState);
853
+ const onCellNavigateRef = (0, import_react2.useRef)(onCellNavigate);
854
+ dragStateRef.current = dragState;
855
+ onCellNavigateRef.current = onCellNavigate;
797
856
  const cellSelectionBounds = getCellSelectionBounds(dragState.start, dragState.end);
798
857
  const activeSelectionBounds = enabled ? getActiveSelectionBounds(dragState, cellSelectionBounds) : null;
799
858
  const handleCellMouseDown = (0, import_react2.useCallback)(
800
- (rowIndex, colIndex) => {
859
+ (rowIndex, colIndex, options) => {
801
860
  if (!enabled) return;
802
- setDragState({
803
- isSelecting: true,
804
- isFillDragging: false,
805
- start: { row: rowIndex, col: colIndex },
806
- end: { row: rowIndex, col: colIndex },
807
- fillAnchor: null,
808
- fillEnd: null
861
+ setDragState((prev) => {
862
+ if (options?.shiftKey && prev.start) {
863
+ return {
864
+ ...prev,
865
+ isSelecting: true,
866
+ isFillDragging: false,
867
+ end: { row: rowIndex, col: colIndex },
868
+ fillAnchor: null,
869
+ fillEnd: null
870
+ };
871
+ }
872
+ return {
873
+ isSelecting: true,
874
+ isFillDragging: false,
875
+ start: { row: rowIndex, col: colIndex },
876
+ end: { row: rowIndex, col: colIndex },
877
+ fillAnchor: null,
878
+ fillEnd: null
879
+ };
809
880
  });
810
881
  },
811
882
  [enabled]
@@ -847,6 +918,53 @@ function useCellSelection({
847
918
  setDragState(INITIAL_DRAG_STATE);
848
919
  }
849
920
  }, [enabled]);
921
+ (0, import_react2.useEffect)(() => {
922
+ if (!enabled) return;
923
+ const handleKeyDown = (e) => {
924
+ if (e.ctrlKey || e.metaKey || e.altKey) return;
925
+ if (isEditablePasteTarget(e.target) || isEditablePasteTarget(document.activeElement)) {
926
+ return;
927
+ }
928
+ const delta = getCellNavigationDelta(e.key);
929
+ if (!delta) return;
930
+ const prev = dragStateRef.current;
931
+ if (!prev.start || !prev.end) return;
932
+ if (prev.isSelecting || prev.isFillDragging) return;
933
+ const rowCount = rows.length;
934
+ const resolvedColumnCount = columnCount > 0 ? columnCount : rows[0]?.getVisibleCells().length ?? 0;
935
+ if (rowCount <= 0 || resolvedColumnCount <= 0) return;
936
+ const nextEnd = clampCellPosition(
937
+ {
938
+ row: prev.end.row + delta.row,
939
+ col: prev.end.col + delta.col
940
+ },
941
+ rowCount,
942
+ resolvedColumnCount
943
+ );
944
+ if (nextEnd.row === prev.end.row && nextEnd.col === prev.end.col) return;
945
+ e.preventDefault();
946
+ const nextState = e.shiftKey ? {
947
+ ...prev,
948
+ isSelecting: false,
949
+ isFillDragging: false,
950
+ end: nextEnd,
951
+ fillAnchor: null,
952
+ fillEnd: null
953
+ } : {
954
+ isSelecting: false,
955
+ isFillDragging: false,
956
+ start: nextEnd,
957
+ end: nextEnd,
958
+ fillAnchor: null,
959
+ fillEnd: null
960
+ };
961
+ dragStateRef.current = nextState;
962
+ setDragState(nextState);
963
+ onCellNavigateRef.current?.(nextEnd);
964
+ };
965
+ window.addEventListener("keydown", handleKeyDown);
966
+ return () => window.removeEventListener("keydown", handleKeyDown);
967
+ }, [columnCount, enabled, rows]);
850
968
  const copySelection = (0, import_react2.useCallback)(
851
969
  async (options) => {
852
970
  if (!enabled || !activeSelectionBounds) return false;
@@ -1083,12 +1201,466 @@ function getColumnFreezeStyle(offset, options) {
1083
1201
  position: "sticky",
1084
1202
  ...offset.side === "left" ? { left: offset.offset } : { right: offset.offset },
1085
1203
  zIndex: zBase + offset.stack,
1086
- ...options?.isHeader ? { top: 0 } : {}
1204
+ ...options?.isHeader ? { top: options.headerTop ?? 0 } : {}
1087
1205
  };
1088
1206
  }
1089
1207
 
1090
- // src/components/ui/table/features/row-expand/row-expand.ts
1208
+ // src/components/ui/table/features/inline-search/inlineSearch.ts
1209
+ var INLINE_SEARCH_MAX_RESULTS = 1e3;
1210
+ var INLINE_SEARCH_TARGET_TICK_MS = 10;
1211
+ var INLINE_SEARCH_INITIAL_STRIDE = 10;
1212
+ function escapeSearchRegex(value) {
1213
+ return value.replace(/([$()*+.?[\\\]^{|}-])/g, "\\$1");
1214
+ }
1215
+ function createSearchRegex(query) {
1216
+ const trimmed = query.trim();
1217
+ if (!trimmed) return null;
1218
+ return new RegExp(escapeSearchRegex(trimmed), "i");
1219
+ }
1220
+ function cellValueToSearchText(value) {
1221
+ if (value == null) return void 0;
1222
+ if (typeof value === "string") return value;
1223
+ if (typeof value === "number" || typeof value === "boolean") {
1224
+ return String(value);
1225
+ }
1226
+ if (Array.isArray(value)) {
1227
+ return value.map((item) => cellValueToSearchText(item) ?? "").join(" ");
1228
+ }
1229
+ if (typeof value === "object") {
1230
+ try {
1231
+ return JSON.stringify(value);
1232
+ } catch {
1233
+ return String(value);
1234
+ }
1235
+ }
1236
+ return String(value);
1237
+ }
1238
+ function formatSearchResultLabel(status) {
1239
+ const countLabel = status.results >= INLINE_SEARCH_MAX_RESULTS ? `over ${INLINE_SEARCH_MAX_RESULTS}` : `${status.results} result${status.results !== 1 ? "s" : ""}`;
1240
+ if (status.selectedIndex >= 0 && status.results > 0) {
1241
+ return `${status.selectedIndex + 1} of ${countLabel}`;
1242
+ }
1243
+ return countLabel;
1244
+ }
1245
+ function nextSearchIndex(selectedIndex, results) {
1246
+ if (results <= 0) return -1;
1247
+ if (selectedIndex < 0) return 0;
1248
+ return (selectedIndex + 1) % results;
1249
+ }
1250
+ function previousSearchIndex(selectedIndex, results) {
1251
+ if (results <= 0) return -1;
1252
+ if (selectedIndex < 0) return results - 1;
1253
+ let next = (selectedIndex - 1) % results;
1254
+ if (next < 0) next += results;
1255
+ return next;
1256
+ }
1257
+ function buildSearchMatchKey(colIndex, rowIndex) {
1258
+ return `${colIndex}:${rowIndex}`;
1259
+ }
1260
+ function buildSearchMatchKeys(results) {
1261
+ const keys = /* @__PURE__ */ new Set();
1262
+ for (const [colIndex, rowIndex] of results) {
1263
+ keys.add(buildSearchMatchKey(colIndex, rowIndex));
1264
+ }
1265
+ return keys;
1266
+ }
1267
+ function collectSearchMatchesInRange(options) {
1268
+ const {
1269
+ query,
1270
+ startRow,
1271
+ rowCount,
1272
+ columnCount,
1273
+ getCellValue,
1274
+ maxResults = INLINE_SEARCH_MAX_RESULTS
1275
+ } = options;
1276
+ const regex = createSearchRegex(query);
1277
+ if (!regex || rowCount <= 0 || columnCount <= 0) return [];
1278
+ const matches = [];
1279
+ for (let rowOffset = 0; rowOffset < rowCount; rowOffset += 1) {
1280
+ const rowIndex = startRow + rowOffset;
1281
+ for (let colIndex = 0; colIndex < columnCount; colIndex += 1) {
1282
+ const text = cellValueToSearchText(getCellValue(rowIndex, colIndex));
1283
+ if (text !== void 0 && regex.test(text)) {
1284
+ matches.push([colIndex, rowIndex]);
1285
+ if (matches.length >= maxResults) {
1286
+ return matches;
1287
+ }
1288
+ }
1289
+ }
1290
+ }
1291
+ return matches;
1292
+ }
1293
+ function nextSearchStride(currentStride, elapsedMs, targetMs = INLINE_SEARCH_TARGET_TICK_MS) {
1294
+ const rounded = Math.max(elapsedMs, 1);
1295
+ const scalar = targetMs / rounded;
1296
+ return Math.max(1, Math.ceil(currentStride * scalar));
1297
+ }
1298
+ function buildFlatSearchCorpus(rows, getRowId) {
1299
+ return rows.map((data, index) => ({
1300
+ id: getRowId(data, index),
1301
+ data,
1302
+ ancestorToggleKeys: []
1303
+ }));
1304
+ }
1305
+ function buildTreeSearchCorpus(visibleRows, options) {
1306
+ const { toggleField, getRowId } = options;
1307
+ const corpus = [];
1308
+ const seen = /* @__PURE__ */ new Set();
1309
+ const walk = (node, ancestorToggleKeys) => {
1310
+ const id = getRowId(node, corpus.length);
1311
+ if (seen.has(id)) return;
1312
+ seen.add(id);
1313
+ corpus.push({
1314
+ id,
1315
+ data: node,
1316
+ ancestorToggleKeys
1317
+ });
1318
+ const children = node.children;
1319
+ if (!Array.isArray(children) || children.length === 0) return;
1320
+ const toggleValue = node[toggleField];
1321
+ const childAncestors = typeof toggleValue === "string" && toggleValue.length > 0 ? [...ancestorToggleKeys, toggleValue] : ancestorToggleKeys;
1322
+ for (const child of children) {
1323
+ if (child && typeof child === "object") {
1324
+ walk(child, childAncestors);
1325
+ }
1326
+ }
1327
+ };
1328
+ for (const row of visibleRows) {
1329
+ const level = row.level;
1330
+ if (level === 0 || level === void 0) {
1331
+ walk(row, []);
1332
+ }
1333
+ }
1334
+ for (const row of visibleRows) {
1335
+ const id = getRowId(row, corpus.length);
1336
+ if (seen.has(id)) continue;
1337
+ walk(row, []);
1338
+ }
1339
+ return corpus;
1340
+ }
1341
+ function mapSearchResultsToVisibleKeys(results, corpus, visibleRowIndexById) {
1342
+ const keys = /* @__PURE__ */ new Set();
1343
+ for (const [colIndex, corpusRowIndex] of results) {
1344
+ const corpusRow = corpus[corpusRowIndex];
1345
+ if (!corpusRow) continue;
1346
+ const visibleRowIndex = visibleRowIndexById.get(corpusRow.id);
1347
+ if (visibleRowIndex === void 0) continue;
1348
+ keys.add(buildSearchMatchKey(colIndex, visibleRowIndex));
1349
+ }
1350
+ return keys;
1351
+ }
1352
+ function mapSearchResultToVisibleItem(item, corpus, visibleRowIndexById) {
1353
+ const [colIndex, corpusRowIndex] = item;
1354
+ const corpusRow = corpus[corpusRowIndex];
1355
+ if (!corpusRow) return null;
1356
+ const visibleRowIndex = visibleRowIndexById.get(corpusRow.id);
1357
+ if (visibleRowIndex === void 0) return null;
1358
+ return [colIndex, visibleRowIndex];
1359
+ }
1360
+ function collectAncestorKeysToExpand(corpusRow, expandedRows) {
1361
+ return corpusRow.ancestorToggleKeys.filter((key) => !expandedRows.has(key));
1362
+ }
1363
+
1364
+ // src/components/ui/table/features/inline-search/useInlineSearch.ts
1091
1365
  var import_react3 = require("react");
1366
+ var EMPTY_MATCH_KEYS = /* @__PURE__ */ new Set();
1367
+ function useInlineSearch({
1368
+ enabled = false,
1369
+ rowCount,
1370
+ columnCount,
1371
+ getCellValue,
1372
+ initialStartRow = 0,
1373
+ showSearch: controlledShowSearch,
1374
+ searchValue: controlledSearchValue,
1375
+ searchResults: controlledSearchResults,
1376
+ onSearchValueChange,
1377
+ onSearchClose,
1378
+ onSearchResultsChanged,
1379
+ onNavigateToResult,
1380
+ rootRef
1381
+ }) {
1382
+ const searchInputId = (0, import_react3.useId)();
1383
+ const searchInputRef = (0, import_react3.useRef)(null);
1384
+ const [internalShowSearch, setInternalShowSearch] = (0, import_react3.useState)(false);
1385
+ const [internalSearchValue, setInternalSearchValue] = (0, import_react3.useState)("");
1386
+ const [internalResults, setInternalResults] = (0, import_react3.useState)(
1387
+ []
1388
+ );
1389
+ const [searchStatus, setSearchStatus] = (0, import_react3.useState)();
1390
+ const searchStatusRef = (0, import_react3.useRef)(searchStatus);
1391
+ searchStatusRef.current = searchStatus;
1392
+ const abortControllerRef = (0, import_react3.useRef)(null);
1393
+ const searchHandleRef = (0, import_react3.useRef)(void 0);
1394
+ const initialStartRowRef = (0, import_react3.useRef)(initialStartRow);
1395
+ initialStartRowRef.current = initialStartRow;
1396
+ const getCellValueRef = (0, import_react3.useRef)(getCellValue);
1397
+ getCellValueRef.current = getCellValue;
1398
+ const showSearch = controlledShowSearch ?? internalShowSearch;
1399
+ const searchValue = controlledSearchValue ?? internalSearchValue;
1400
+ const searchResults = controlledSearchResults ?? internalResults;
1401
+ const setSearchValue = (0, import_react3.useCallback)(
1402
+ (value) => {
1403
+ setInternalSearchValue(value);
1404
+ onSearchValueChange?.(value);
1405
+ },
1406
+ [onSearchValueChange]
1407
+ );
1408
+ const cancelSearch = (0, import_react3.useCallback)(() => {
1409
+ if (searchHandleRef.current !== void 0) {
1410
+ window.cancelAnimationFrame(searchHandleRef.current);
1411
+ searchHandleRef.current = void 0;
1412
+ }
1413
+ abortControllerRef.current?.abort();
1414
+ }, []);
1415
+ const emitResultsChanged = (0, import_react3.useCallback)(
1416
+ (results, navIndex) => {
1417
+ onSearchResultsChanged?.(results, navIndex);
1418
+ },
1419
+ [onSearchResultsChanged]
1420
+ );
1421
+ const navigateToIndex = (0, import_react3.useCallback)(
1422
+ (results, navIndex) => {
1423
+ if (onSearchResultsChanged) return;
1424
+ if (navIndex < 0 || navIndex >= results.length) return;
1425
+ const item = results[navIndex];
1426
+ if (!item) return;
1427
+ onNavigateToResult?.(item);
1428
+ },
1429
+ [onNavigateToResult, onSearchResultsChanged]
1430
+ );
1431
+ const beginSearch = (0, import_react3.useCallback)(
1432
+ (query) => {
1433
+ if (controlledSearchResults !== void 0) return;
1434
+ const totalRows = rowCount;
1435
+ if (totalRows === 0 || columnCount === 0) {
1436
+ setSearchStatus(void 0);
1437
+ setInternalResults([]);
1438
+ emitResultsChanged([], -1);
1439
+ return;
1440
+ }
1441
+ let startY = Math.min(
1442
+ Math.max(0, initialStartRowRef.current),
1443
+ totalRows - 1
1444
+ );
1445
+ let searchStride = Math.min(INLINE_SEARCH_INITIAL_STRIDE, totalRows);
1446
+ let rowsSearched = 0;
1447
+ const runningResult = [];
1448
+ setSearchStatus(void 0);
1449
+ setInternalResults([]);
1450
+ const tick = () => {
1451
+ if (abortControllerRef.current?.signal.aborted) return;
1452
+ const tStart = performance.now();
1453
+ const rowsLeft = totalRows - rowsSearched;
1454
+ const height = Math.min(searchStride, rowsLeft, totalRows - startY);
1455
+ if (height <= 0) {
1456
+ return;
1457
+ }
1458
+ const chunk = collectSearchMatchesInRange({
1459
+ query,
1460
+ startRow: startY,
1461
+ rowCount: height,
1462
+ columnCount,
1463
+ getCellValue: (rowIndex, colIndex) => getCellValueRef.current(rowIndex, colIndex),
1464
+ maxResults: INLINE_SEARCH_MAX_RESULTS - runningResult.length
1465
+ });
1466
+ if (chunk.length > 0) {
1467
+ runningResult.push(...chunk);
1468
+ setInternalResults([...runningResult]);
1469
+ }
1470
+ rowsSearched += height;
1471
+ const selectedIndex = searchStatusRef.current?.selectedIndex ?? -1;
1472
+ setSearchStatus({
1473
+ results: runningResult.length,
1474
+ rowsSearched,
1475
+ selectedIndex
1476
+ });
1477
+ emitResultsChanged(runningResult, selectedIndex);
1478
+ if (startY + height >= totalRows) {
1479
+ startY = 0;
1480
+ } else {
1481
+ startY += height;
1482
+ }
1483
+ searchStride = nextSearchStride(
1484
+ searchStride,
1485
+ performance.now() - tStart
1486
+ );
1487
+ if (rowsSearched < totalRows && runningResult.length < INLINE_SEARCH_MAX_RESULTS) {
1488
+ searchHandleRef.current = window.requestAnimationFrame(tick);
1489
+ }
1490
+ };
1491
+ cancelSearch();
1492
+ abortControllerRef.current = new AbortController();
1493
+ searchHandleRef.current = window.requestAnimationFrame(tick);
1494
+ },
1495
+ [
1496
+ cancelSearch,
1497
+ columnCount,
1498
+ controlledSearchResults,
1499
+ emitResultsChanged,
1500
+ rowCount
1501
+ ]
1502
+ );
1503
+ const openSearch = (0, import_react3.useCallback)(() => {
1504
+ if (controlledShowSearch === void 0) {
1505
+ setInternalShowSearch(true);
1506
+ }
1507
+ }, [controlledShowSearch]);
1508
+ const closeSearch = (0, import_react3.useCallback)(() => {
1509
+ if (controlledShowSearch === void 0) {
1510
+ setInternalShowSearch(false);
1511
+ }
1512
+ onSearchClose?.();
1513
+ setSearchStatus(void 0);
1514
+ setInternalResults([]);
1515
+ emitResultsChanged([], -1);
1516
+ cancelSearch();
1517
+ }, [
1518
+ cancelSearch,
1519
+ controlledShowSearch,
1520
+ emitResultsChanged,
1521
+ onSearchClose
1522
+ ]);
1523
+ const goToNext = (0, import_react3.useCallback)(() => {
1524
+ if (!searchStatus || searchStatus.results === 0) return;
1525
+ const newIndex = nextSearchIndex(
1526
+ searchStatus.selectedIndex,
1527
+ searchStatus.results
1528
+ );
1529
+ setSearchStatus({ ...searchStatus, selectedIndex: newIndex });
1530
+ emitResultsChanged(searchResults, newIndex);
1531
+ navigateToIndex(searchResults, newIndex);
1532
+ }, [emitResultsChanged, navigateToIndex, searchResults, searchStatus]);
1533
+ const goToPrevious = (0, import_react3.useCallback)(() => {
1534
+ if (!searchStatus || searchStatus.results === 0) return;
1535
+ const newIndex = previousSearchIndex(
1536
+ searchStatus.selectedIndex,
1537
+ searchStatus.results
1538
+ );
1539
+ setSearchStatus({ ...searchStatus, selectedIndex: newIndex });
1540
+ emitResultsChanged(searchResults, newIndex);
1541
+ navigateToIndex(searchResults, newIndex);
1542
+ }, [emitResultsChanged, navigateToIndex, searchResults, searchStatus]);
1543
+ (0, import_react3.useEffect)(() => {
1544
+ if (controlledSearchResults === void 0) return;
1545
+ if (controlledSearchResults.length > 0) {
1546
+ setSearchStatus((current) => ({
1547
+ rowsSearched: rowCount,
1548
+ results: controlledSearchResults.length,
1549
+ selectedIndex: current?.selectedIndex ?? -1
1550
+ }));
1551
+ } else {
1552
+ setSearchStatus(void 0);
1553
+ }
1554
+ }, [controlledSearchResults, rowCount]);
1555
+ (0, import_react3.useEffect)(() => {
1556
+ if (!enabled) return;
1557
+ setSearchStatus(void 0);
1558
+ setInternalResults([]);
1559
+ emitResultsChanged([], -1);
1560
+ if (showSearch) {
1561
+ queueMicrotask(() => {
1562
+ searchInputRef.current?.focus({ preventScroll: true });
1563
+ });
1564
+ } else {
1565
+ cancelSearch();
1566
+ }
1567
+ }, [enabled, showSearch]);
1568
+ (0, import_react3.useEffect)(() => {
1569
+ if (!enabled || !showSearch) return;
1570
+ if (controlledSearchResults !== void 0) return;
1571
+ if (searchValue.trim() === "") {
1572
+ setSearchStatus(void 0);
1573
+ setInternalResults([]);
1574
+ cancelSearch();
1575
+ emitResultsChanged([], -1);
1576
+ return;
1577
+ }
1578
+ beginSearch(searchValue);
1579
+ }, [
1580
+ beginSearch,
1581
+ cancelSearch,
1582
+ controlledSearchResults,
1583
+ emitResultsChanged,
1584
+ enabled,
1585
+ searchValue,
1586
+ showSearch
1587
+ ]);
1588
+ (0, import_react3.useEffect)(() => {
1589
+ if (!enabled) return;
1590
+ const handleKeyDown = (event) => {
1591
+ if (!(event.ctrlKey || event.metaKey)) return;
1592
+ if (event.key.toLowerCase() !== "f") return;
1593
+ const root = rootRef?.current;
1594
+ if (root) {
1595
+ const active = document.activeElement;
1596
+ const focusInside = active === root || active instanceof Node && root.contains(active);
1597
+ if (!focusInside && active !== document.body) {
1598
+ return;
1599
+ }
1600
+ }
1601
+ event.preventDefault();
1602
+ event.stopPropagation();
1603
+ if (showSearch) {
1604
+ searchInputRef.current?.focus({ preventScroll: true });
1605
+ searchInputRef.current?.select();
1606
+ return;
1607
+ }
1608
+ if (controlledShowSearch === void 0) {
1609
+ setInternalShowSearch(true);
1610
+ }
1611
+ };
1612
+ window.addEventListener("keydown", handleKeyDown, true);
1613
+ return () => window.removeEventListener("keydown", handleKeyDown, true);
1614
+ }, [controlledShowSearch, enabled, rootRef, showSearch]);
1615
+ (0, import_react3.useEffect)(() => () => cancelSearch(), [cancelSearch]);
1616
+ const searchMatchKeys = (0, import_react3.useMemo)(
1617
+ () => buildSearchMatchKeys(searchResults),
1618
+ [searchResults]
1619
+ );
1620
+ const activeMatch = (0, import_react3.useMemo)(() => {
1621
+ if (!searchStatus || searchStatus.selectedIndex < 0) return null;
1622
+ return searchResults[searchStatus.selectedIndex] ?? null;
1623
+ }, [searchResults, searchStatus]);
1624
+ if (!enabled) {
1625
+ return {
1626
+ enabled: false,
1627
+ showSearch: false,
1628
+ searchValue: "",
1629
+ searchResults: [],
1630
+ searchStatus: void 0,
1631
+ searchMatchKeys: EMPTY_MATCH_KEYS,
1632
+ activeMatch: null,
1633
+ searchInputRef,
1634
+ searchInputId,
1635
+ canClose: false,
1636
+ openSearch,
1637
+ closeSearch,
1638
+ setSearchValue,
1639
+ goToNext,
1640
+ goToPrevious
1641
+ };
1642
+ }
1643
+ return {
1644
+ enabled: true,
1645
+ showSearch,
1646
+ searchValue,
1647
+ searchResults,
1648
+ searchStatus,
1649
+ searchMatchKeys,
1650
+ activeMatch,
1651
+ searchInputRef,
1652
+ searchInputId,
1653
+ canClose: controlledShowSearch === void 0 || onSearchClose !== void 0,
1654
+ openSearch,
1655
+ closeSearch,
1656
+ setSearchValue,
1657
+ goToNext,
1658
+ goToPrevious
1659
+ };
1660
+ }
1661
+
1662
+ // src/components/ui/table/features/row-expand/row-expand.ts
1663
+ var import_react4 = require("react");
1092
1664
  function getFieldValue(row, key) {
1093
1665
  return row[key];
1094
1666
  }
@@ -1118,12 +1690,12 @@ var useConvertTreeData = ({
1118
1690
  expandedRows,
1119
1691
  onExpandedRowsChange
1120
1692
  }) => {
1121
- const onExpandedRowsChangeRef = (0, import_react3.useRef)(onExpandedRowsChange);
1122
- const hasInitializedRef = (0, import_react3.useRef)(false);
1123
- (0, import_react3.useEffect)(() => {
1693
+ const onExpandedRowsChangeRef = (0, import_react4.useRef)(onExpandedRowsChange);
1694
+ const hasInitializedRef = (0, import_react4.useRef)(false);
1695
+ (0, import_react4.useEffect)(() => {
1124
1696
  onExpandedRowsChangeRef.current = onExpandedRowsChange;
1125
1697
  }, [onExpandedRowsChange]);
1126
- (0, import_react3.useEffect)(() => {
1698
+ (0, import_react4.useEffect)(() => {
1127
1699
  if (!data || data.length === 0) {
1128
1700
  hasInitializedRef.current = false;
1129
1701
  return;
@@ -1133,7 +1705,7 @@ var useConvertTreeData = ({
1133
1705
  onExpandedRowsChangeRef.current?.(new Set(ids));
1134
1706
  hasInitializedRef.current = true;
1135
1707
  }, [enabled, data, toggleField]);
1136
- const processedData = (0, import_react3.useMemo)(() => {
1708
+ const processedData = (0, import_react4.useMemo)(() => {
1137
1709
  if (!enabled || !data || data.length === 0) return [];
1138
1710
  const flattenedData = [];
1139
1711
  const flattenItems = (items) => {
@@ -1197,7 +1769,7 @@ var useConvertTreeData = ({
1197
1769
  });
1198
1770
  return rootItems;
1199
1771
  }, [enabled, data, toggleField, childField, flattenField]);
1200
- const flattenTree = (0, import_react3.useMemo)(() => {
1772
+ const flattenTree = (0, import_react4.useMemo)(() => {
1201
1773
  if (!enabled) return [];
1202
1774
  const flatten = (nodes, result = [], level = 0) => {
1203
1775
  nodes.forEach((node, index) => {
@@ -1247,7 +1819,7 @@ var useConvertTreeData = ({
1247
1819
  preventExpand,
1248
1820
  expandedRows
1249
1821
  ]);
1250
- const sortedData = (0, import_react3.useMemo)(() => {
1822
+ const sortedData = (0, import_react4.useMemo)(() => {
1251
1823
  if (!enabled) {
1252
1824
  return data ?? [];
1253
1825
  }
@@ -1353,6 +1925,7 @@ function collectRowSpanColumns(columns) {
1353
1925
 
1354
1926
  // src/core/useGlideTable.ts
1355
1927
  var EMPTY_COLUMN_FREEZE_OFFSETS = /* @__PURE__ */ new Map();
1928
+ var EMPTY_SEARCH_MATCH_KEYS = /* @__PURE__ */ new Set();
1356
1929
  function useGlideTable(options) {
1357
1930
  const {
1358
1931
  data,
@@ -1393,9 +1966,16 @@ function useGlideTable(options) {
1393
1966
  columnSizing: controlledColumnSizing,
1394
1967
  onColumnSizingChange,
1395
1968
  columnResizeMode = "onChange",
1396
- enableColumnFreeze = false
1969
+ enableColumnFreeze = false,
1970
+ enableInlineSearch = false,
1971
+ showSearch,
1972
+ searchValue,
1973
+ onSearchValueChange,
1974
+ onSearchClose,
1975
+ searchResults,
1976
+ onSearchResultsChanged
1397
1977
  } = options;
1398
- const labels = (0, import_react4.useMemo)(() => {
1978
+ const labels = (0, import_react5.useMemo)(() => {
1399
1979
  const resolved = resolveDataTableLabels(labelsProp);
1400
1980
  return {
1401
1981
  ...resolved,
@@ -1406,15 +1986,16 @@ function useGlideTable(options) {
1406
1986
  }, [labelsProp, emptyText, loadingText, selectionLabel]);
1407
1987
  const enableExpand = Boolean(toggleField);
1408
1988
  const resolvedEnableSubtreeCopy = enableSubtreeCopy ?? enableExpand;
1409
- const [internalRowSelection, setInternalRowSelection] = (0, import_react4.useState)({});
1410
- const [internalColumnSizing, setInternalColumnSizing] = (0, import_react4.useState)({});
1411
- const [internalExpandedRows, setInternalExpandedRows] = (0, import_react4.useState)(
1989
+ const [internalRowSelection, setInternalRowSelection] = (0, import_react5.useState)({});
1990
+ const [internalColumnSizing, setInternalColumnSizing] = (0, import_react5.useState)({});
1991
+ const [internalExpandedRows, setInternalExpandedRows] = (0, import_react5.useState)(
1412
1992
  () => /* @__PURE__ */ new Set()
1413
1993
  );
1414
- const [hoveredRowIndex, setHoveredRowIndex] = (0, import_react4.useState)(null);
1415
- const scrollRef = (0, import_react4.useRef)(null);
1994
+ const [hoveredRowIndex, setHoveredRowIndex] = (0, import_react5.useState)(null);
1995
+ const scrollRef = (0, import_react5.useRef)(null);
1996
+ const rootRef = (0, import_react5.useRef)(null);
1416
1997
  const shouldVirtualize = enableVirtualization && !enableRowSpan;
1417
- (0, import_react4.useEffect)(() => {
1998
+ (0, import_react5.useEffect)(() => {
1418
1999
  if (enableVirtualization && enableRowSpan) {
1419
2000
  console.warn(
1420
2001
  "[useGlideTable] enableRowSpan is on; virtualization is disabled to preserve cell merges."
@@ -1428,7 +2009,7 @@ function useGlideTable(options) {
1428
2009
  );
1429
2010
  const columnSizing = controlledColumnSizing ?? internalColumnSizing;
1430
2011
  const expandedRows = controlledExpandedRows ?? internalExpandedRows;
1431
- const handleExpandedRowsChange = (0, import_react4.useCallback)(
2012
+ const handleExpandedRowsChange = (0, import_react5.useCallback)(
1432
2013
  (next) => {
1433
2014
  if (onExpandedRowsChange) {
1434
2015
  onExpandedRowsChange(next);
@@ -1489,13 +2070,13 @@ function useGlideTable(options) {
1489
2070
  getCoreRowModel: (0, import_react_table.getCoreRowModel)(),
1490
2071
  getRowId: getRowId ? (originalRow, index) => getRowId(originalRow, index) : (_originalRow, index) => String(index)
1491
2072
  });
1492
- const rowSpanColumnKeys = (0, import_react4.useMemo)(() => {
2073
+ const rowSpanColumnKeys = (0, import_react5.useMemo)(() => {
1493
2074
  if (!enableRowSpan) return [];
1494
2075
  return collectRowSpanColumns(columns);
1495
2076
  }, [enableRowSpan, columns]);
1496
2077
  const primaryRowSpanKey = rowSpanColumnKeys[0]?.rowSpanKey;
1497
2078
  const primaryRowSpanColumnId = rowSpanColumnKeys[0]?.columnId;
1498
- const columnRowSpanMap = (0, import_react4.useMemo)(
2079
+ const columnRowSpanMap = (0, import_react5.useMemo)(
1499
2080
  () => buildColumnRowSpanMap(tableData, rowSpanColumnKeys),
1500
2081
  [tableData, rowSpanColumnKeys]
1501
2082
  );
@@ -1504,7 +2085,7 @@ function useGlideTable(options) {
1504
2085
  const rows = table.getRowModel().rows;
1505
2086
  const columnCount = table.getAllLeafColumns().length || 1;
1506
2087
  const visibleLeafColumns = table.getVisibleLeafColumns();
1507
- const columnFreezeOffsets = (0, import_react4.useMemo)(() => {
2088
+ const columnFreezeOffsets = (0, import_react5.useMemo)(() => {
1508
2089
  if (!enableColumnFreeze) return EMPTY_COLUMN_FREEZE_OFFSETS;
1509
2090
  return buildColumnFreezeOffsets(
1510
2091
  visibleLeafColumns.map((column) => ({
@@ -1524,13 +2105,46 @@ function useGlideTable(options) {
1524
2105
  const totalSize = rowVirtualizer.getTotalSize();
1525
2106
  const paddingTop = virtualRows.length > 0 ? virtualRows[0]?.start ?? 0 : 0;
1526
2107
  const paddingBottom = virtualRows.length > 0 ? totalSize - (virtualRows[virtualRows.length - 1]?.end ?? 0) : 0;
1527
- const selectedRowIndices = (0, import_react4.useMemo)(() => {
2108
+ const selectedRowIndices = (0, import_react5.useMemo)(() => {
1528
2109
  const indices = /* @__PURE__ */ new Set();
1529
2110
  for (const selectedRow of selectedRows) {
1530
2111
  indices.add(selectedRow.index);
1531
2112
  }
1532
2113
  return indices;
1533
2114
  }, [selectedRows]);
2115
+ const scrollCellIntoView = (0, import_react5.useCallback)(
2116
+ (rowIndex, colIndex, options2) => {
2117
+ const align = options2?.align ?? "nearest";
2118
+ const blockAlign = align === "center" ? "center" : "nearest";
2119
+ if (shouldVirtualize) {
2120
+ rowVirtualizer.scrollToIndex(rowIndex, {
2121
+ align: align === "nearest" ? "auto" : align
2122
+ });
2123
+ }
2124
+ const scrollElement = scrollRef.current;
2125
+ if (!scrollElement) return;
2126
+ const scrollToMatchedCell = () => {
2127
+ const cell = scrollElement.querySelector(
2128
+ `[data-row-index="${rowIndex}"][data-col-index="${colIndex}"]`
2129
+ );
2130
+ if (cell instanceof HTMLElement) {
2131
+ cell.scrollIntoView({ block: blockAlign, inline: "nearest" });
2132
+ }
2133
+ };
2134
+ if (shouldVirtualize) {
2135
+ requestAnimationFrame(scrollToMatchedCell);
2136
+ return;
2137
+ }
2138
+ scrollToMatchedCell();
2139
+ },
2140
+ [rowVirtualizer, shouldVirtualize]
2141
+ );
2142
+ const handleCellNavigate = (0, import_react5.useCallback)(
2143
+ (position) => {
2144
+ scrollCellIntoView(position.row, position.col, { align: "nearest" });
2145
+ },
2146
+ [scrollCellIntoView]
2147
+ );
1534
2148
  const {
1535
2149
  dragState,
1536
2150
  activeSelectionBounds,
@@ -1542,11 +2156,13 @@ function useGlideTable(options) {
1542
2156
  data: tableData,
1543
2157
  rows,
1544
2158
  enabled: enableCellSelection,
2159
+ columnCount: visibleLeafColumns.length,
1545
2160
  enableSubtreeCopy: resolvedEnableSubtreeCopy,
1546
2161
  enableInsertPaste: enableInsertPaste ?? true,
1547
2162
  onDataChange,
1548
2163
  onBatchChange,
1549
- onRowsPaste
2164
+ onRowsPaste,
2165
+ onCellNavigate: handleCellNavigate
1550
2166
  });
1551
2167
  const {
1552
2168
  editingCell,
@@ -1556,23 +2172,193 @@ function useGlideTable(options) {
1556
2172
  commitEdit,
1557
2173
  cancelEdit
1558
2174
  } = useCellEdit({ data: tableData, rows, onDataChange, onCellChange });
1559
- const handleCellMouseDownWithCommit = (0, import_react4.useCallback)(
1560
- (rowIndex, colIndex) => {
2175
+ const handleCellMouseDownWithCommit = (0, import_react5.useCallback)(
2176
+ (rowIndex, colIndex, options2) => {
1561
2177
  const isSameEditingCell = editingCell?.rowIndex === rowIndex && editingCell?.colIndex === colIndex;
1562
2178
  if (editingCell && !isSameEditingCell && !commitEdit()) {
1563
2179
  return;
1564
2180
  }
1565
- handleCellMouseDown(rowIndex, colIndex);
2181
+ handleCellMouseDown(rowIndex, colIndex, options2);
1566
2182
  },
1567
2183
  [commitEdit, editingCell, handleCellMouseDown]
1568
2184
  );
1569
- const clearHover = (0, import_react4.useCallback)(() => {
2185
+ const navigateToSearchResult = (0, import_react5.useCallback)(
2186
+ (item) => {
2187
+ const [colIndex, rowIndex] = item;
2188
+ handleCellMouseDownWithCommit(rowIndex, colIndex);
2189
+ scrollCellIntoView(rowIndex, colIndex, { align: "center" });
2190
+ },
2191
+ [handleCellMouseDownWithCommit, scrollCellIntoView]
2192
+ );
2193
+ const resolveSearchRowId = (0, import_react5.useCallback)(
2194
+ (row, index) => {
2195
+ if (getRowId) return getRowId(row, index);
2196
+ if (enableExpand) {
2197
+ const record = row;
2198
+ const idValue = record.id;
2199
+ if (idValue != null && String(idValue).length > 0) {
2200
+ return String(idValue);
2201
+ }
2202
+ const uniqueId = record.uniqueId;
2203
+ if (uniqueId != null && String(uniqueId).length > 0) {
2204
+ return String(uniqueId);
2205
+ }
2206
+ if (toggleField) {
2207
+ const toggleValue = record[toggleField];
2208
+ if (toggleValue != null && String(toggleValue).length > 0) {
2209
+ return String(toggleValue);
2210
+ }
2211
+ }
2212
+ }
2213
+ return String(index);
2214
+ },
2215
+ [enableExpand, getRowId, toggleField]
2216
+ );
2217
+ const searchCorpus = (0, import_react5.useMemo)(() => {
2218
+ if (!enableInlineSearch) return [];
2219
+ if (enableExpand && toggleField) {
2220
+ return buildTreeSearchCorpus(tableData, {
2221
+ toggleField,
2222
+ getRowId: resolveSearchRowId
2223
+ });
2224
+ }
2225
+ return buildFlatSearchCorpus(tableData, resolveSearchRowId);
2226
+ }, [
2227
+ enableExpand,
2228
+ enableInlineSearch,
2229
+ resolveSearchRowId,
2230
+ tableData,
2231
+ toggleField
2232
+ ]);
2233
+ const searchCorpusRef = (0, import_react5.useRef)(searchCorpus);
2234
+ searchCorpusRef.current = searchCorpus;
2235
+ const visibleRowIndexById = (0, import_react5.useMemo)(() => {
2236
+ const map = /* @__PURE__ */ new Map();
2237
+ for (const row of rows) {
2238
+ map.set(resolveSearchRowId(row.original, row.index), row.index);
2239
+ }
2240
+ return map;
2241
+ }, [resolveSearchRowId, rows]);
2242
+ const getSearchCellValue = (0, import_react5.useCallback)(
2243
+ (rowIndex, colIndex) => {
2244
+ const corpusRow = searchCorpusRef.current[rowIndex];
2245
+ const column = visibleLeafColumns[colIndex];
2246
+ if (!corpusRow || !column) return void 0;
2247
+ const visibleIndex = visibleRowIndexById.get(corpusRow.id);
2248
+ if (visibleIndex !== void 0) {
2249
+ const visibleRow = rows[visibleIndex];
2250
+ if (visibleRow) {
2251
+ return visibleRow.getValue(column.id);
2252
+ }
2253
+ }
2254
+ const columnDef = column.columnDef;
2255
+ if ("accessorFn" in columnDef && typeof columnDef.accessorFn === "function") {
2256
+ return columnDef.accessorFn(corpusRow.data, rowIndex);
2257
+ }
2258
+ if ("accessorKey" in columnDef && columnDef.accessorKey != null && columnDef.accessorKey !== "") {
2259
+ return corpusRow.data[String(columnDef.accessorKey)];
2260
+ }
2261
+ return corpusRow.data[column.id];
2262
+ },
2263
+ [rows, visibleLeafColumns, visibleRowIndexById]
2264
+ );
2265
+ const pendingSearchNavRef = (0, import_react5.useRef)(null);
2266
+ const focusSearchResult = (0, import_react5.useCallback)(
2267
+ (colIndex, visibleRowIndex) => {
2268
+ navigateToSearchResult([colIndex, visibleRowIndex]);
2269
+ },
2270
+ [navigateToSearchResult]
2271
+ );
2272
+ const navigateToCorpusSearchResult = (0, import_react5.useCallback)(
2273
+ (item) => {
2274
+ const [colIndex, corpusRowIndex] = item;
2275
+ const corpusRow = searchCorpusRef.current[corpusRowIndex];
2276
+ if (!corpusRow) return;
2277
+ const missingKeys = collectAncestorKeysToExpand(corpusRow, expandedRows);
2278
+ if (missingKeys.length > 0) {
2279
+ pendingSearchNavRef.current = {
2280
+ colIndex,
2281
+ rowId: corpusRow.id
2282
+ };
2283
+ const next = new Set(expandedRows);
2284
+ for (const key of corpusRow.ancestorToggleKeys) {
2285
+ next.add(key);
2286
+ }
2287
+ handleExpandedRowsChange(next);
2288
+ return;
2289
+ }
2290
+ const visibleItem = mapSearchResultToVisibleItem(
2291
+ item,
2292
+ searchCorpusRef.current,
2293
+ visibleRowIndexById
2294
+ );
2295
+ if (!visibleItem) return;
2296
+ focusSearchResult(visibleItem[0], visibleItem[1]);
2297
+ },
2298
+ [
2299
+ expandedRows,
2300
+ focusSearchResult,
2301
+ handleExpandedRowsChange,
2302
+ visibleRowIndexById
2303
+ ]
2304
+ );
2305
+ (0, import_react5.useEffect)(() => {
2306
+ const pending = pendingSearchNavRef.current;
2307
+ if (!pending) return;
2308
+ const visibleRowIndex = visibleRowIndexById.get(pending.rowId);
2309
+ if (visibleRowIndex === void 0) return;
2310
+ pendingSearchNavRef.current = null;
2311
+ focusSearchResult(pending.colIndex, visibleRowIndex);
2312
+ }, [focusSearchResult, rows, visibleRowIndexById]);
2313
+ const initialSearchStartRow = virtualRows[0]?.index ?? 0;
2314
+ const inlineSearch = useInlineSearch({
2315
+ enabled: enableInlineSearch,
2316
+ rowCount: searchCorpus.length,
2317
+ columnCount: visibleLeafColumns.length,
2318
+ getCellValue: getSearchCellValue,
2319
+ initialStartRow: initialSearchStartRow,
2320
+ showSearch,
2321
+ searchValue,
2322
+ searchResults,
2323
+ onSearchValueChange,
2324
+ onSearchClose,
2325
+ onSearchResultsChanged,
2326
+ onNavigateToResult: navigateToCorpusSearchResult,
2327
+ rootRef
2328
+ });
2329
+ const visibleSearchMatchKeys = (0, import_react5.useMemo)(() => {
2330
+ if (!enableInlineSearch) return EMPTY_SEARCH_MATCH_KEYS;
2331
+ return mapSearchResultsToVisibleKeys(
2332
+ inlineSearch.searchResults,
2333
+ searchCorpus,
2334
+ visibleRowIndexById
2335
+ );
2336
+ }, [
2337
+ enableInlineSearch,
2338
+ inlineSearch.searchResults,
2339
+ searchCorpus,
2340
+ visibleRowIndexById
2341
+ ]);
2342
+ const visibleActiveMatch = (0, import_react5.useMemo)(() => {
2343
+ if (!enableInlineSearch || !inlineSearch.activeMatch) return null;
2344
+ return mapSearchResultToVisibleItem(
2345
+ inlineSearch.activeMatch,
2346
+ searchCorpus,
2347
+ visibleRowIndexById
2348
+ );
2349
+ }, [
2350
+ enableInlineSearch,
2351
+ inlineSearch.activeMatch,
2352
+ searchCorpus,
2353
+ visibleRowIndexById
2354
+ ]);
2355
+ const clearHover = (0, import_react5.useCallback)(() => {
1570
2356
  setHoveredRowIndex(null);
1571
2357
  }, []);
1572
- const handleRowHover = (0, import_react4.useCallback)((rowIndex, _rowData) => {
2358
+ const handleRowHover = (0, import_react5.useCallback)((rowIndex, _rowData) => {
1573
2359
  setHoveredRowIndex(rowIndex);
1574
2360
  }, []);
1575
- const handleToggleSelect = (0, import_react4.useCallback)(
2361
+ const handleToggleSelect = (0, import_react5.useCallback)(
1576
2362
  (row) => {
1577
2363
  if (!row.getCanSelect()) return;
1578
2364
  if (preserveRowSelection && row.getIsSelected()) {
@@ -1582,14 +2368,14 @@ function useGlideTable(options) {
1582
2368
  },
1583
2369
  [preserveRowSelection]
1584
2370
  );
1585
- const handleToggleExpand = (0, import_react4.useCallback)(
2371
+ const handleToggleExpand = (0, import_react5.useCallback)(
1586
2372
  (rowKey) => {
1587
2373
  if (preventExpand) return;
1588
2374
  handleExpandedRowsChange(toggleExpandedRowId(rowKey, expandedRows));
1589
2375
  },
1590
2376
  [preventExpand, handleExpandedRowsChange, expandedRows]
1591
2377
  );
1592
- const rowContextValue = (0, import_react4.useMemo)(() => {
2378
+ const rowContextValue = (0, import_react5.useMemo)(() => {
1593
2379
  return {
1594
2380
  rowSpan: {
1595
2381
  enableRowSpan,
@@ -1637,6 +2423,11 @@ function useGlideTable(options) {
1637
2423
  columnFreeze: {
1638
2424
  enableColumnFreeze,
1639
2425
  offsets: columnFreezeOffsets
2426
+ },
2427
+ inlineSearch: {
2428
+ enabled: enableInlineSearch,
2429
+ matchKeys: visibleSearchMatchKeys,
2430
+ activeMatch: visibleActiveMatch
1640
2431
  }
1641
2432
  };
1642
2433
  }, [
@@ -1672,14 +2463,17 @@ function useGlideTable(options) {
1672
2463
  labels.collapseRow,
1673
2464
  enableColumnResize,
1674
2465
  enableColumnFreeze,
1675
- columnFreezeOffsets
2466
+ columnFreezeOffsets,
2467
+ enableInlineSearch,
2468
+ visibleSearchMatchKeys,
2469
+ visibleActiveMatch
1676
2470
  ]);
1677
- const copySelectionRef = (0, import_react4.useRef)(copySelection);
1678
- (0, import_react4.useEffect)(() => {
2471
+ const copySelectionRef = (0, import_react5.useRef)(copySelection);
2472
+ (0, import_react5.useEffect)(() => {
1679
2473
  copySelectionRef.current = copySelection;
1680
2474
  }, [copySelection]);
1681
- const stableCopySelection = (0, import_react4.useCallback)((options2) => copySelectionRef.current(options2), []);
1682
- (0, import_react4.useEffect)(() => {
2475
+ const stableCopySelection = (0, import_react5.useCallback)((options2) => copySelectionRef.current(options2), []);
2476
+ (0, import_react5.useEffect)(() => {
1683
2477
  onCopyActionsReady?.({ copySelection: stableCopySelection });
1684
2478
  }, [onCopyActionsReady, stableCopySelection]);
1685
2479
  return {
@@ -1695,8 +2489,10 @@ function useGlideTable(options) {
1695
2489
  enableCellSelection,
1696
2490
  enableColumnResize,
1697
2491
  enableColumnFreeze,
2492
+ enableInlineSearch,
1698
2493
  shouldVirtualize,
1699
2494
  scrollRef,
2495
+ rootRef,
1700
2496
  rowVirtualizer,
1701
2497
  virtualRows,
1702
2498
  paddingTop,
@@ -1704,7 +2500,21 @@ function useGlideTable(options) {
1704
2500
  rowContextValue,
1705
2501
  handleToggleSelect,
1706
2502
  clearHover,
1707
- copySelection: stableCopySelection
2503
+ copySelection: stableCopySelection,
2504
+ inlineSearch: {
2505
+ showSearch: inlineSearch.showSearch,
2506
+ searchValue: inlineSearch.searchValue,
2507
+ searchStatus: inlineSearch.searchStatus,
2508
+ searchInputRef: inlineSearch.searchInputRef,
2509
+ searchInputId: inlineSearch.searchInputId,
2510
+ canClose: inlineSearch.canClose,
2511
+ searchRowCount: searchCorpus.length,
2512
+ setSearchValue: inlineSearch.setSearchValue,
2513
+ closeSearch: inlineSearch.closeSearch,
2514
+ goToNext: inlineSearch.goToNext,
2515
+ goToPrevious: inlineSearch.goToPrevious,
2516
+ openSearch: inlineSearch.openSearch
2517
+ }
1708
2518
  };
1709
2519
  }
1710
2520
 
@@ -1723,18 +2533,18 @@ function getColumnSizeStyle(size, options) {
1723
2533
 
1724
2534
  // src/components/ui/table/components/DataTable/DataTable.tsx
1725
2535
  var import_react_table3 = require("@tanstack/react-table");
1726
- var import_react7 = require("react");
2536
+ var import_react8 = require("react");
1727
2537
 
1728
2538
  // src/components/ui/table/components/DataTable/DataTableRow.tsx
1729
2539
  var import_react_table2 = require("@tanstack/react-table");
1730
- var import_react6 = require("react");
2540
+ var import_react7 = require("react");
1731
2541
 
1732
2542
  // src/components/ui/table/DataTableContext.tsx
1733
- var import_react5 = require("react");
2543
+ var import_react6 = require("react");
1734
2544
  var import_jsx_runtime = require("react/jsx-runtime");
1735
- var DataTableContext = (0, import_react5.createContext)(null);
2545
+ var DataTableContext = (0, import_react6.createContext)(null);
1736
2546
  function useDataTableRowContext() {
1737
- const context = (0, import_react5.use)(DataTableContext);
2547
+ const context = (0, import_react6.use)(DataTableContext);
1738
2548
  if (!context) {
1739
2549
  throw new Error("useDataTableRowContext must be used within a DataTableContextProvider");
1740
2550
  }
@@ -1935,10 +2745,16 @@ function DataTableRow({
1935
2745
  cellEdit,
1936
2746
  expand,
1937
2747
  columnResize,
1938
- columnFreeze
2748
+ columnFreeze,
2749
+ inlineSearch
1939
2750
  } = useDataTableRowContext();
1940
2751
  const { enableColumnResize } = columnResize;
1941
2752
  const { enableColumnFreeze, offsets: freezeOffsets } = columnFreeze;
2753
+ const {
2754
+ enabled: enableInlineSearch,
2755
+ matchKeys: searchMatchKeys,
2756
+ activeMatch
2757
+ } = inlineSearch;
1942
2758
  const {
1943
2759
  enableRowSpan,
1944
2760
  primaryRowSpanColumnId,
@@ -2032,9 +2848,9 @@ function DataTableRow({
2032
2848
  const expandKey = toggleField && rowData[toggleField] !== null && rowData[toggleField] !== void 0 ? String(rowData[toggleField]) : null;
2033
2849
  const isExpanded = expandKey !== null && Boolean(expandedRows?.has(expandKey));
2034
2850
  const rowLevel = typeof rowData.level === "number" ? rowData.level : 0;
2035
- const editInputRef = (0, import_react6.useRef)(null);
2851
+ const editInputRef = (0, import_react7.useRef)(null);
2036
2852
  const isRowEditing = editingCell?.rowIndex === rowIndex;
2037
- (0, import_react6.useEffect)(() => {
2853
+ (0, import_react7.useEffect)(() => {
2038
2854
  if (!isRowEditing) return;
2039
2855
  editInputRef.current?.focus();
2040
2856
  editInputRef.current?.select();
@@ -2130,9 +2946,14 @@ function DataTableRow({
2130
2946
  ...freezeStyle,
2131
2947
  ...selectionEdgeStyle
2132
2948
  };
2949
+ const searchMatchKey = buildSearchMatchKey(cellIndex, rowIndex);
2950
+ const isSearchMatch = enableInlineSearch && searchMatchKeys.has(searchMatchKey);
2951
+ const isSearchActive = isSearchMatch && activeMatch !== null && activeMatch[0] === cellIndex && activeMatch[1] === rowIndex;
2133
2952
  return /* @__PURE__ */ (0, import_jsx_runtime3.jsxs)(
2134
2953
  "td",
2135
2954
  {
2955
+ "data-row-index": rowIndex,
2956
+ "data-col-index": cellIndex,
2136
2957
  rowSpan: rowSpanInfo && rowSpanInfo.rowSpan > 1 ? rowSpanInfo.rowSpan : void 0,
2137
2958
  "data-merged": isMerged && cellIndex > 0 ? "" : void 0,
2138
2959
  "data-merged-edge-right": showMergedRightEdge ? "" : void 0,
@@ -2142,6 +2963,8 @@ function DataTableRow({
2142
2963
  "data-group-hovered": enableRowSpan && showCellHover && !showCellSelected ? "" : void 0,
2143
2964
  "data-selection-fill": isCellDragSelected ? "" : void 0,
2144
2965
  "data-selection-edges": hasSelectionEdges ? "" : void 0,
2966
+ "data-search-match": isSearchMatch ? "" : void 0,
2967
+ "data-search-active": isSearchActive ? "" : void 0,
2145
2968
  "data-editable": editable ? "" : void 0,
2146
2969
  "data-editing": isEditing ? "" : void 0,
2147
2970
  "data-frozen": freezeOffset?.side,
@@ -2156,7 +2979,8 @@ function DataTableRow({
2156
2979
  event.preventDefault();
2157
2980
  onCellMouseDown(
2158
2981
  resolveCellRowIndex(event.clientY, event.currentTarget),
2159
- cellIndex
2982
+ cellIndex,
2983
+ { shiftKey: event.shiftKey }
2160
2984
  );
2161
2985
  },
2162
2986
  onMouseEnter: (event) => {
@@ -2193,6 +3017,8 @@ function DataTableRow({
2193
3017
  enableRowSpan && showCellHover && !showCellSelected && "is-group-hovered",
2194
3018
  isCellDragSelected && CELL_SELECTION_FILL_CLASS,
2195
3019
  hasSelectionEdges && CELL_SELECTION_EDGES_CLASS,
3020
+ isSearchMatch && "is-search-match",
3021
+ isSearchActive && "is-search-active",
2196
3022
  editable && "is-editable",
2197
3023
  classNames?.cell
2198
3024
  ),
@@ -2327,8 +3153,169 @@ function DataTableRow({
2327
3153
  );
2328
3154
  }
2329
3155
 
2330
- // src/components/ui/table/components/DataTable/DataTableToolbar.tsx
3156
+ // src/components/ui/table/components/DataTable/DataTableSearch.tsx
2331
3157
  var import_jsx_runtime4 = require("react/jsx-runtime");
3158
+ function SearchCloseIcon({ className }) {
3159
+ return /* @__PURE__ */ (0, import_jsx_runtime4.jsxs)(
3160
+ "svg",
3161
+ {
3162
+ className,
3163
+ "aria-hidden": true,
3164
+ width: "16",
3165
+ height: "16",
3166
+ viewBox: "0 0 24 24",
3167
+ fill: "none",
3168
+ stroke: "currentColor",
3169
+ strokeWidth: "2",
3170
+ strokeLinecap: "round",
3171
+ strokeLinejoin: "round",
3172
+ children: [
3173
+ /* @__PURE__ */ (0, import_jsx_runtime4.jsx)("path", { d: "M18 6 6 18" }),
3174
+ /* @__PURE__ */ (0, import_jsx_runtime4.jsx)("path", { d: "m6 6 12 12" })
3175
+ ]
3176
+ }
3177
+ );
3178
+ }
3179
+ function DataTableSearch({
3180
+ showSearch,
3181
+ searchValue,
3182
+ searchStatus,
3183
+ searchInputId,
3184
+ searchInputRef,
3185
+ canClose,
3186
+ placeholder,
3187
+ resultHint,
3188
+ previousLabel,
3189
+ nextLabel,
3190
+ closeLabel,
3191
+ rowsTotal,
3192
+ classNames,
3193
+ onSearchValueChange,
3194
+ onClose,
3195
+ onNext,
3196
+ onPrevious
3197
+ }) {
3198
+ if (!showSearch) return null;
3199
+ const resultString = searchStatus ? formatSearchResultLabel(searchStatus) : resultHint;
3200
+ const progress = rowsTotal > 0 ? Math.floor((searchStatus?.rowsSearched ?? 0) / rowsTotal * 100) : 0;
3201
+ const handleKeyDown = (event) => {
3202
+ if ((event.ctrlKey || event.metaKey) && event.code === "KeyF" || event.key === "Escape") {
3203
+ event.preventDefault();
3204
+ event.stopPropagation();
3205
+ if (canClose) {
3206
+ onClose();
3207
+ }
3208
+ return;
3209
+ }
3210
+ if (event.key === "ArrowDown" || event.key === "Enter" && !event.shiftKey) {
3211
+ event.preventDefault();
3212
+ onNext();
3213
+ return;
3214
+ }
3215
+ if (event.key === "ArrowUp" || event.key === "Enter" && event.shiftKey) {
3216
+ event.preventDefault();
3217
+ onPrevious();
3218
+ }
3219
+ };
3220
+ return /* @__PURE__ */ (0, import_jsx_runtime4.jsxs)(
3221
+ "div",
3222
+ {
3223
+ className: cn("data-table-search", classNames?.search),
3224
+ role: "search",
3225
+ onMouseDown: (event) => event.stopPropagation(),
3226
+ children: [
3227
+ /* @__PURE__ */ (0, import_jsx_runtime4.jsxs)("div", { className: "data-table-search-row", children: [
3228
+ /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(
3229
+ "input",
3230
+ {
3231
+ ref: searchInputRef,
3232
+ id: searchInputId,
3233
+ type: "search",
3234
+ value: searchValue,
3235
+ placeholder,
3236
+ autoComplete: "off",
3237
+ spellCheck: false,
3238
+ "aria-label": placeholder,
3239
+ className: cn("data-table-search-input", classNames?.searchInput),
3240
+ onChange: (event) => onSearchValueChange(event.target.value),
3241
+ onKeyDown: handleKeyDown
3242
+ }
3243
+ ),
3244
+ /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(
3245
+ "button",
3246
+ {
3247
+ type: "button",
3248
+ "aria-label": previousLabel,
3249
+ className: cn("data-table-search-button", classNames?.searchButton),
3250
+ onClick: (event) => {
3251
+ event.stopPropagation();
3252
+ onPrevious();
3253
+ },
3254
+ children: /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(ChevronUp, { className: "data-table-search-icon" })
3255
+ }
3256
+ ),
3257
+ /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(
3258
+ "button",
3259
+ {
3260
+ type: "button",
3261
+ "aria-label": nextLabel,
3262
+ className: cn("data-table-search-button", classNames?.searchButton),
3263
+ onClick: (event) => {
3264
+ event.stopPropagation();
3265
+ onNext();
3266
+ },
3267
+ children: /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(ChevronDown, { className: "data-table-search-icon" })
3268
+ }
3269
+ ),
3270
+ canClose ? /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(
3271
+ "button",
3272
+ {
3273
+ type: "button",
3274
+ "aria-label": closeLabel,
3275
+ className: cn("data-table-search-button", classNames?.searchButton),
3276
+ onClick: (event) => {
3277
+ event.stopPropagation();
3278
+ onClose();
3279
+ },
3280
+ children: /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(SearchCloseIcon, { className: "data-table-search-icon" })
3281
+ }
3282
+ ) : null
3283
+ ] }),
3284
+ /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(
3285
+ "div",
3286
+ {
3287
+ className: cn("data-table-search-status", classNames?.searchStatus),
3288
+ "aria-live": "polite",
3289
+ children: resultString
3290
+ }
3291
+ ),
3292
+ searchStatus !== void 0 ? /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(
3293
+ "div",
3294
+ {
3295
+ className: cn(
3296
+ "data-table-search-progress",
3297
+ classNames?.searchProgress
3298
+ ),
3299
+ role: "progressbar",
3300
+ "aria-valuemin": 0,
3301
+ "aria-valuemax": 100,
3302
+ "aria-valuenow": progress,
3303
+ children: /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(
3304
+ "div",
3305
+ {
3306
+ className: "data-table-search-progress-bar",
3307
+ style: { width: `${progress}%` }
3308
+ }
3309
+ )
3310
+ }
3311
+ ) : null
3312
+ ]
3313
+ }
3314
+ );
3315
+ }
3316
+
3317
+ // src/components/ui/table/components/DataTable/DataTableToolbar.tsx
3318
+ var import_jsx_runtime5 = require("react/jsx-runtime");
2332
3319
  function DataTableToolbar({
2333
3320
  filteredCount,
2334
3321
  totalCount,
@@ -2346,39 +3333,71 @@ function DataTableToolbar({
2346
3333
  const selectionContent = selectionLabel?.(selectedCount) ?? null;
2347
3334
  const hasSelectionContent = selectionContent !== null && selectionContent !== false && selectionContent !== void 0 && typeof selectionContent !== "boolean";
2348
3335
  if (!hasLeftContent && !hasToolbar && !hasSelectionContent) return null;
2349
- return /* @__PURE__ */ (0, import_jsx_runtime4.jsxs)("div", { className: cn("DataTableToolbarJSX", classNames?.toolbar, className), children: [
2350
- /* @__PURE__ */ (0, import_jsx_runtime4.jsxs)("div", { className: cn("toolbar-left", classNames?.toolbarLeft), children: [
2351
- hasCount && /* @__PURE__ */ (0, import_jsx_runtime4.jsx)("span", { className: cn("toolbar-count", classNames?.toolbarCount), children: displayFiltered !== void 0 && totalCount !== void 0 ? /* @__PURE__ */ (0, import_jsx_runtime4.jsxs)(import_jsx_runtime4.Fragment, { children: [
2352
- /* @__PURE__ */ (0, import_jsx_runtime4.jsx)("span", { className: "toolbar-count-primary", children: displayFiltered }),
2353
- /* @__PURE__ */ (0, import_jsx_runtime4.jsxs)("span", { className: "toolbar-count-placeholder", children: [
3336
+ return /* @__PURE__ */ (0, import_jsx_runtime5.jsxs)("div", { className: cn("DataTableToolbarJSX", classNames?.toolbar, className), children: [
3337
+ /* @__PURE__ */ (0, import_jsx_runtime5.jsxs)("div", { className: cn("toolbar-left", classNames?.toolbarLeft), children: [
3338
+ hasCount && /* @__PURE__ */ (0, import_jsx_runtime5.jsx)("span", { className: cn("toolbar-count", classNames?.toolbarCount), children: displayFiltered !== void 0 && totalCount !== void 0 ? /* @__PURE__ */ (0, import_jsx_runtime5.jsxs)(import_jsx_runtime5.Fragment, { children: [
3339
+ /* @__PURE__ */ (0, import_jsx_runtime5.jsx)("span", { className: "toolbar-count-primary", children: displayFiltered }),
3340
+ /* @__PURE__ */ (0, import_jsx_runtime5.jsxs)("span", { className: "toolbar-count-placeholder", children: [
2354
3341
  " / ",
2355
3342
  totalCount
2356
3343
  ] })
2357
- ] }) : /* @__PURE__ */ (0, import_jsx_runtime4.jsx)("span", { className: "toolbar-count-primary", children: displayFiltered ?? totalCount }) }),
3344
+ ] }) : /* @__PURE__ */ (0, import_jsx_runtime5.jsx)("span", { className: "toolbar-count-primary", children: displayFiltered ?? totalCount }) }),
2358
3345
  summary
2359
3346
  ] }),
2360
- /* @__PURE__ */ (0, import_jsx_runtime4.jsxs)("div", { className: cn("toolbar-right", classNames?.toolbarRight), children: [
2361
- hasSelectionContent && (typeof selectionContent === "string" || typeof selectionContent === "number" ? /* @__PURE__ */ (0, import_jsx_runtime4.jsx)("span", { className: cn("toolbar-selection", classNames?.toolbarSelection), children: selectionContent }) : selectionContent),
2362
- hasToolbar && /* @__PURE__ */ (0, import_jsx_runtime4.jsx)("div", { className: cn("toolbar-actions", classNames?.toolbarActions), children: toolbar })
3347
+ /* @__PURE__ */ (0, import_jsx_runtime5.jsxs)("div", { className: cn("toolbar-right", classNames?.toolbarRight), children: [
3348
+ hasSelectionContent && (typeof selectionContent === "string" || typeof selectionContent === "number" ? /* @__PURE__ */ (0, import_jsx_runtime5.jsx)("span", { className: cn("toolbar-selection", classNames?.toolbarSelection), children: selectionContent }) : selectionContent),
3349
+ hasToolbar && /* @__PURE__ */ (0, import_jsx_runtime5.jsx)("div", { className: cn("toolbar-actions", classNames?.toolbarActions), children: toolbar })
2363
3350
  ] })
2364
3351
  ] });
2365
3352
  }
2366
3353
 
3354
+ // src/components/ui/table/features/column-groups/mergeHeaderGroups.ts
3355
+ function getMergedHeaderGroups(headerGroups) {
3356
+ if (headerGroups.length <= 1) {
3357
+ return headerGroups.map((group) => ({
3358
+ ...group,
3359
+ headers: group.headers.map((header) => ({
3360
+ ...header,
3361
+ mergedRowSpan: 1
3362
+ }))
3363
+ }));
3364
+ }
3365
+ const seenColumnIds = /* @__PURE__ */ new Set();
3366
+ const fullDepth = headerGroups.length;
3367
+ return headerGroups.map((group, depth) => ({
3368
+ ...group,
3369
+ headers: group.headers.filter((header) => !seenColumnIds.has(header.column.id)).map((header) => {
3370
+ seenColumnIds.add(header.column.id);
3371
+ if (header.isPlaceholder) {
3372
+ return {
3373
+ ...header,
3374
+ isPlaceholder: false,
3375
+ mergedRowSpan: fullDepth - depth
3376
+ };
3377
+ }
3378
+ return {
3379
+ ...header,
3380
+ mergedRowSpan: 1
3381
+ };
3382
+ })
3383
+ }));
3384
+ }
3385
+
2367
3386
  // src/components/ui/table/components/DataTable/DataTable.tsx
2368
- var import_jsx_runtime5 = require("react/jsx-runtime");
3387
+ var import_jsx_runtime6 = require("react/jsx-runtime");
2369
3388
  function DefaultScroll({
2370
3389
  scrollRef,
2371
3390
  children,
2372
3391
  className
2373
3392
  }) {
2374
- return /* @__PURE__ */ (0, import_jsx_runtime5.jsx)("div", { ref: scrollRef, className: cn("data-table-scroll", className), children });
3393
+ return /* @__PURE__ */ (0, import_jsx_runtime6.jsx)("div", { ref: scrollRef, className: cn("data-table-scroll", className), children });
2375
3394
  }
2376
3395
  function DefaultPending({
2377
3396
  loadingText,
2378
3397
  className,
2379
3398
  classNames
2380
3399
  }) {
2381
- return /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(
3400
+ return /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(
2382
3401
  "div",
2383
3402
  {
2384
3403
  className: cn(
@@ -2388,7 +3407,7 @@ function DefaultPending({
2388
3407
  classNames?.pending,
2389
3408
  className
2390
3409
  ),
2391
- children: /* @__PURE__ */ (0, import_jsx_runtime5.jsx)("span", { className: cn("data-table-loading-text", classNames?.loadingText), children: loadingText })
3410
+ children: /* @__PURE__ */ (0, import_jsx_runtime6.jsx)("span", { className: cn("data-table-loading-text", classNames?.loadingText), children: loadingText })
2392
3411
  }
2393
3412
  );
2394
3413
  }
@@ -2397,7 +3416,7 @@ function DefaultEmpty({
2397
3416
  columnCount,
2398
3417
  classNames
2399
3418
  }) {
2400
- return /* @__PURE__ */ (0, import_jsx_runtime5.jsx)("tr", { children: /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(
3419
+ return /* @__PURE__ */ (0, import_jsx_runtime6.jsx)("tr", { children: /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(
2401
3420
  "td",
2402
3421
  {
2403
3422
  colSpan: columnCount,
@@ -2430,15 +3449,18 @@ function DataTable({
2430
3449
  enableCellSelection,
2431
3450
  enableColumnResize,
2432
3451
  enableColumnFreeze,
3452
+ enableInlineSearch,
2433
3453
  shouldVirtualize,
2434
3454
  scrollRef,
3455
+ rootRef,
2435
3456
  rowVirtualizer,
2436
3457
  virtualRows,
2437
3458
  paddingTop,
2438
3459
  paddingBottom,
2439
3460
  rowContextValue,
2440
3461
  handleToggleSelect,
2441
- clearHover
3462
+ clearHover,
3463
+ inlineSearch
2442
3464
  } = useGlideTable(glideOptions);
2443
3465
  const ToolbarSlot = slots?.Toolbar ?? DataTableToolbar;
2444
3466
  const ScrollSlot = slots?.Scroll ?? DefaultScroll;
@@ -2446,12 +3468,13 @@ function DataTable({
2446
3468
  const PendingSlot = slots?.Pending ?? DefaultPending;
2447
3469
  const EmptySlot = slots?.Empty ?? DefaultEmpty;
2448
3470
  const freezeOffsets = rowContextValue.columnFreeze.offsets;
2449
- const contextValue = (0, import_react7.useMemo)(
3471
+ const headerGroups = getMergedHeaderGroups(table.getHeaderGroups());
3472
+ const contextValue = (0, import_react8.useMemo)(
2450
3473
  () => ({ ...rowContextValue, classNames }),
2451
3474
  [rowContextValue, classNames]
2452
3475
  );
2453
3476
  if (isPending) {
2454
- return /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(
3477
+ return /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(
2455
3478
  PendingSlot,
2456
3479
  {
2457
3480
  loadingText,
@@ -2460,19 +3483,21 @@ function DataTable({
2460
3483
  }
2461
3484
  );
2462
3485
  }
2463
- return /* @__PURE__ */ (0, import_jsx_runtime5.jsxs)(
3486
+ return /* @__PURE__ */ (0, import_jsx_runtime6.jsxs)(
2464
3487
  "div",
2465
3488
  {
3489
+ ref: rootRef,
2466
3490
  className: cn(
2467
3491
  "DataTableJSX",
2468
3492
  !enableCellSelection && "DataTableJSX--no-cell-selection",
2469
3493
  enableColumnResize && "DataTableJSX--column-resize",
2470
3494
  enableColumnFreeze && "DataTableJSX--column-freeze",
3495
+ enableInlineSearch && "DataTableJSX--inline-search",
2471
3496
  classNames?.root,
2472
3497
  className
2473
3498
  ),
2474
3499
  children: [
2475
- /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(
3500
+ /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(
2476
3501
  ToolbarSlot,
2477
3502
  {
2478
3503
  filteredCount: filteredCount ?? tableData.length,
@@ -2484,14 +3509,36 @@ function DataTable({
2484
3509
  classNames
2485
3510
  }
2486
3511
  ),
2487
- /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(ScrollSlot, { scrollRef, className: classNames?.scroll, children: /* @__PURE__ */ (0, import_jsx_runtime5.jsxs)(
3512
+ enableInlineSearch ? /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(
3513
+ DataTableSearch,
3514
+ {
3515
+ showSearch: inlineSearch.showSearch,
3516
+ searchValue: inlineSearch.searchValue,
3517
+ searchStatus: inlineSearch.searchStatus,
3518
+ searchInputId: inlineSearch.searchInputId,
3519
+ searchInputRef: inlineSearch.searchInputRef,
3520
+ canClose: inlineSearch.canClose,
3521
+ placeholder: labels.searchPlaceholder,
3522
+ resultHint: labels.searchResultHint,
3523
+ previousLabel: labels.searchPrevious,
3524
+ nextLabel: labels.searchNext,
3525
+ closeLabel: labels.searchClose,
3526
+ rowsTotal: inlineSearch.searchRowCount,
3527
+ classNames,
3528
+ onSearchValueChange: inlineSearch.setSearchValue,
3529
+ onClose: inlineSearch.closeSearch,
3530
+ onNext: inlineSearch.goToNext,
3531
+ onPrevious: inlineSearch.goToPrevious
3532
+ }
3533
+ ) : null,
3534
+ /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(ScrollSlot, { scrollRef, className: classNames?.scroll, children: /* @__PURE__ */ (0, import_jsx_runtime6.jsxs)(
2488
3535
  "table",
2489
3536
  {
2490
3537
  className: cn("data-table", classNames?.table),
2491
3538
  style: enableColumnResize ? { width: table.getTotalSize() } : void 0,
2492
3539
  onDragStart: enableCellSelection ? (event) => event.preventDefault() : void 0,
2493
3540
  children: [
2494
- /* @__PURE__ */ (0, import_jsx_runtime5.jsx)("thead", { className: cn("data-table-head", classNames?.head), children: table.getHeaderGroups().map((headerGroup) => /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(
3541
+ /* @__PURE__ */ (0, import_jsx_runtime6.jsx)("thead", { className: cn("data-table-head", classNames?.head), children: headerGroups.map((headerGroup) => /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(
2495
3542
  "tr",
2496
3543
  {
2497
3544
  className: cn("data-table-head-row", classNames?.headRow),
@@ -2505,15 +3552,18 @@ function DataTable({
2505
3552
  });
2506
3553
  const freezeOffset = enableColumnFreeze ? freezeOffsets.get(header.column.id) : void 0;
2507
3554
  const freezeStyle = getColumnFreezeStyle(freezeOffset, {
2508
- isHeader: true
3555
+ isHeader: true,
3556
+ headerTop: header.depth * DATA_TABLE_HEADER_ROW_HEIGHT
2509
3557
  });
2510
3558
  const headerStyle = {
2511
3559
  ...sizeStyle,
2512
3560
  ...freezeStyle
2513
3561
  };
2514
- return /* @__PURE__ */ (0, import_jsx_runtime5.jsxs)(
3562
+ return /* @__PURE__ */ (0, import_jsx_runtime6.jsxs)(
2515
3563
  "th",
2516
3564
  {
3565
+ colSpan: header.colSpan,
3566
+ rowSpan: header.mergedRowSpan,
2517
3567
  "data-resizing": header.column.getIsResizing() ? "" : void 0,
2518
3568
  "data-frozen": freezeOffset?.side,
2519
3569
  "data-freeze-edge": getColumnFreezeEdgeAttr(freezeOffset),
@@ -2527,7 +3577,7 @@ function DataTable({
2527
3577
  ),
2528
3578
  children: [
2529
3579
  header.isPlaceholder ? null : (0, import_react_table3.flexRender)(header.column.columnDef.header, header.getContext()),
2530
- canResize ? /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(
3580
+ canResize ? /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(
2531
3581
  "div",
2532
3582
  {
2533
3583
  role: "separator",
@@ -2553,20 +3603,20 @@ function DataTable({
2553
3603
  },
2554
3604
  headerGroup.id
2555
3605
  )) }),
2556
- /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(DataTableContextProvider, { value: contextValue, children: /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(
3606
+ /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(DataTableContextProvider, { value: contextValue, children: /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(
2557
3607
  "tbody",
2558
3608
  {
2559
3609
  onMouseLeave: clearHover,
2560
3610
  className: cn("data-table-body", classNames?.body),
2561
- children: rows.length === 0 ? /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(
3611
+ children: rows.length === 0 ? /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(
2562
3612
  EmptySlot,
2563
3613
  {
2564
3614
  emptyText,
2565
3615
  columnCount,
2566
3616
  classNames
2567
3617
  }
2568
- ) : shouldVirtualize ? /* @__PURE__ */ (0, import_jsx_runtime5.jsxs)(import_jsx_runtime5.Fragment, { children: [
2569
- paddingTop > 0 && /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(
3618
+ ) : shouldVirtualize ? /* @__PURE__ */ (0, import_jsx_runtime6.jsxs)(import_jsx_runtime6.Fragment, { children: [
3619
+ paddingTop > 0 && /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(
2570
3620
  "tr",
2571
3621
  {
2572
3622
  "aria-hidden": true,
@@ -2574,7 +3624,7 @@ function DataTable({
2574
3624
  "data-table-virtual-spacer",
2575
3625
  classNames?.virtualSpacer
2576
3626
  ),
2577
- children: /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(
3627
+ children: /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(
2578
3628
  "td",
2579
3629
  {
2580
3630
  colSpan: columnCount,
@@ -2590,7 +3640,7 @@ function DataTable({
2590
3640
  virtualRows.map((virtualRow) => {
2591
3641
  const row = rows[virtualRow.index];
2592
3642
  if (!row) return null;
2593
- return /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(
3643
+ return /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(
2594
3644
  RowSlot,
2595
3645
  {
2596
3646
  row,
@@ -2601,7 +3651,7 @@ function DataTable({
2601
3651
  row.id
2602
3652
  );
2603
3653
  }),
2604
- paddingBottom > 0 && /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(
3654
+ paddingBottom > 0 && /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(
2605
3655
  "tr",
2606
3656
  {
2607
3657
  "aria-hidden": true,
@@ -2609,7 +3659,7 @@ function DataTable({
2609
3659
  "data-table-virtual-spacer",
2610
3660
  classNames?.virtualSpacer
2611
3661
  ),
2612
- children: /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(
3662
+ children: /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(
2613
3663
  "td",
2614
3664
  {
2615
3665
  colSpan: columnCount,
@@ -2622,7 +3672,7 @@ function DataTable({
2622
3672
  )
2623
3673
  }
2624
3674
  )
2625
- ] }) : rows.map((row) => /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(
3675
+ ] }) : rows.map((row) => /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(
2626
3676
  RowSlot,
2627
3677
  {
2628
3678
  row,
@@ -2641,10 +3691,10 @@ function DataTable({
2641
3691
  }
2642
3692
 
2643
3693
  // src/components/ui/table/components/Table/Table.tsx
2644
- var import_react10 = require("react");
3694
+ var import_react11 = require("react");
2645
3695
 
2646
3696
  // src/components/ui/table/components/Table/buildColumnDef.tsx
2647
- var import_jsx_runtime6 = require("react/jsx-runtime");
3697
+ var import_jsx_runtime7 = require("react/jsx-runtime");
2648
3698
  function SortableHeader({
2649
3699
  label,
2650
3700
  field,
@@ -2653,15 +3703,15 @@ function SortableHeader({
2653
3703
  }) {
2654
3704
  const isActive = sort?.field === field;
2655
3705
  const Icon = isActive ? sort.direction === "asc" ? ArrowUp : ArrowDown : ArrowUpDown;
2656
- return /* @__PURE__ */ (0, import_jsx_runtime6.jsxs)(
3706
+ return /* @__PURE__ */ (0, import_jsx_runtime7.jsxs)(
2657
3707
  "button",
2658
3708
  {
2659
3709
  type: "button",
2660
3710
  className: cn("SortableHeaderJSX", isActive ? "is-active" : "is-inactive"),
2661
3711
  onClick: () => onSort(field),
2662
3712
  children: [
2663
- /* @__PURE__ */ (0, import_jsx_runtime6.jsx)("span", { children: label }),
2664
- /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(Icon, { className: "sortable-header-icon" })
3713
+ /* @__PURE__ */ (0, import_jsx_runtime7.jsx)("span", { children: label }),
3714
+ /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(Icon, { className: "sortable-header-icon" })
2665
3715
  ]
2666
3716
  }
2667
3717
  );
@@ -2694,7 +3744,7 @@ function buildColumnDef(props, sort, onSort) {
2694
3744
  ...minWidth != null ? { minSize: minWidth } : {},
2695
3745
  ...maxWidth != null ? { maxSize: maxWidth } : {},
2696
3746
  ...resizable === false ? { enableResizing: false } : {},
2697
- header: sortable ? () => /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(SortableHeader, { label: children, field, sort, onSort }) : (
3747
+ header: sortable ? () => /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(SortableHeader, { label: children, field, sort, onSort }) : (
2698
3748
  // eslint-disable-next-line @typescript-eslint/promise-function-async
2699
3749
  () => children
2700
3750
  ),
@@ -2719,15 +3769,56 @@ function buildColumnDef(props, sort, onSort) {
2719
3769
  }
2720
3770
  };
2721
3771
  }
3772
+ function resolveGroupId(props, index) {
3773
+ if (props.id) return props.id;
3774
+ if (typeof props.header === "string" || typeof props.header === "number") {
3775
+ return `group:${props.header}:${index}`;
3776
+ }
3777
+ return `group:${index}`;
3778
+ }
3779
+ function buildColumnDefsFromTree(nodes, sort, onSort) {
3780
+ return nodes.map((node, index) => {
3781
+ if (node.type === "leaf") {
3782
+ return buildColumnDef(node.props, sort, onSort);
3783
+ }
3784
+ const childDefs = buildColumnDefsFromTree(node.columns, sort, onSort);
3785
+ const { header, align, headerClassName } = node.props;
3786
+ return {
3787
+ id: resolveGroupId(node.props, index),
3788
+ header: (
3789
+ // eslint-disable-next-line @typescript-eslint/promise-function-async
3790
+ () => header
3791
+ ),
3792
+ columns: childDefs,
3793
+ enableResizing: false,
3794
+ meta: {
3795
+ align,
3796
+ headerClassName
3797
+ }
3798
+ };
3799
+ });
3800
+ }
3801
+ function countLeafColumns(nodes) {
3802
+ let count = 0;
3803
+ for (const node of nodes) {
3804
+ if (node.type === "leaf") {
3805
+ count += 1;
3806
+ } else {
3807
+ count += countLeafColumns(node.columns);
3808
+ }
3809
+ }
3810
+ return count;
3811
+ }
2722
3812
 
2723
3813
  // src/components/ui/table/components/Table/parseTableChildren.ts
2724
- var import_react9 = require("react");
3814
+ var import_react10 = require("react");
2725
3815
 
2726
3816
  // src/components/ui/table/components/Table/tableChildTypes.ts
2727
- var import_react8 = require("react");
3817
+ var import_react9 = require("react");
2728
3818
  var TABLE_HEADER_DISPLAY_NAME = "Table.Header";
2729
3819
  var TABLE_BODY_DISPLAY_NAME = "Table.Body";
2730
3820
  var TABLE_COLUMN_DISPLAY_NAME = "Table.Column";
3821
+ var TABLE_COLUMN_GROUP_DISPLAY_NAME = "Table.ColumnGroup";
2731
3822
  var TABLE_PAGINATION_DISPLAY_NAME = "Table.Pagination";
2732
3823
  function getComponentDisplayName(type) {
2733
3824
  if (typeof type === "function" || typeof type === "object" && type !== null) {
@@ -2736,16 +3827,19 @@ function getComponentDisplayName(type) {
2736
3827
  return void 0;
2737
3828
  }
2738
3829
  function isTableHeaderElement(child) {
2739
- return (0, import_react8.isValidElement)(child) && getComponentDisplayName(child.type) === TABLE_HEADER_DISPLAY_NAME;
3830
+ return (0, import_react9.isValidElement)(child) && getComponentDisplayName(child.type) === TABLE_HEADER_DISPLAY_NAME;
2740
3831
  }
2741
3832
  function isTableBodyElement(child) {
2742
- return (0, import_react8.isValidElement)(child) && getComponentDisplayName(child.type) === TABLE_BODY_DISPLAY_NAME;
3833
+ return (0, import_react9.isValidElement)(child) && getComponentDisplayName(child.type) === TABLE_BODY_DISPLAY_NAME;
2743
3834
  }
2744
3835
  function isTableColumnElement(child) {
2745
- return (0, import_react8.isValidElement)(child) && getComponentDisplayName(child.type) === TABLE_COLUMN_DISPLAY_NAME;
3836
+ return (0, import_react9.isValidElement)(child) && getComponentDisplayName(child.type) === TABLE_COLUMN_DISPLAY_NAME;
3837
+ }
3838
+ function isTableColumnGroupElement(child) {
3839
+ return (0, import_react9.isValidElement)(child) && getComponentDisplayName(child.type) === TABLE_COLUMN_GROUP_DISPLAY_NAME;
2746
3840
  }
2747
3841
  function isTablePaginationElement(child) {
2748
- return (0, import_react8.isValidElement)(child) && getComponentDisplayName(child.type) === TABLE_PAGINATION_DISPLAY_NAME;
3842
+ return (0, import_react9.isValidElement)(child) && getComponentDisplayName(child.type) === TABLE_PAGINATION_DISPLAY_NAME;
2749
3843
  }
2750
3844
 
2751
3845
  // src/components/ui/table/components/Table/parseTableChildren.ts
@@ -2755,7 +3849,7 @@ function parseTableChildren(children) {
2755
3849
  body: null,
2756
3850
  pagination: null
2757
3851
  };
2758
- for (const child of import_react9.Children.toArray(children)) {
3852
+ for (const child of import_react10.Children.toArray(children)) {
2759
3853
  if (isTableHeaderElement(child)) {
2760
3854
  slots.header = child;
2761
3855
  continue;
@@ -2770,26 +3864,38 @@ function parseTableChildren(children) {
2770
3864
  }
2771
3865
  return slots;
2772
3866
  }
2773
- function flattenColumnElements(children) {
3867
+ function walkColumnTreeNodes(children) {
2774
3868
  const result = [];
2775
- for (const child of import_react9.Children.toArray(children)) {
3869
+ for (const child of import_react10.Children.toArray(children)) {
2776
3870
  if (isTableColumnElement(child)) {
2777
- result.push(child);
3871
+ result.push({
3872
+ type: "leaf",
3873
+ props: child.props
3874
+ });
2778
3875
  continue;
2779
3876
  }
2780
- if ((0, import_react9.isValidElement)(child)) {
3877
+ if (isTableColumnGroupElement(child)) {
3878
+ const groupProps = child.props;
3879
+ result.push({
3880
+ type: "group",
3881
+ props: groupProps,
3882
+ columns: walkColumnTreeNodes(groupProps.children)
3883
+ });
3884
+ continue;
3885
+ }
3886
+ if ((0, import_react10.isValidElement)(child)) {
2781
3887
  const nested = child.props.children;
2782
3888
  if (nested != null) {
2783
- result.push(...flattenColumnElements(nested));
3889
+ result.push(...walkColumnTreeNodes(nested));
2784
3890
  }
2785
3891
  }
2786
3892
  }
2787
3893
  return result;
2788
3894
  }
2789
- function extractColumnElements(header) {
3895
+ function extractColumnTree(header) {
2790
3896
  if (!header) return [];
2791
3897
  const { children } = header.props;
2792
- return flattenColumnElements(children);
3898
+ return walkColumnTreeNodes(children);
2793
3899
  }
2794
3900
 
2795
3901
  // src/components/ui/table/components/Table/TableBody.tsx
@@ -2805,6 +3911,13 @@ function TableColumn(props) {
2805
3911
  }
2806
3912
  TableColumn.displayName = TABLE_COLUMN_DISPLAY_NAME;
2807
3913
 
3914
+ // src/components/ui/table/components/Table/TableColumnGroup.tsx
3915
+ function TableColumnGroup(props) {
3916
+ void props;
3917
+ return null;
3918
+ }
3919
+ TableColumnGroup.displayName = TABLE_COLUMN_GROUP_DISPLAY_NAME;
3920
+
2808
3921
  // src/components/ui/table/components/Table/tableDataPipeline.ts
2809
3922
  function sortTableData(data, sort) {
2810
3923
  if (!sort) return data;
@@ -2842,7 +3955,7 @@ function TableHeader(props) {
2842
3955
  TableHeader.displayName = TABLE_HEADER_DISPLAY_NAME;
2843
3956
 
2844
3957
  // src/components/ui/table/components/Table/TablePagination.tsx
2845
- var import_jsx_runtime7 = require("react/jsx-runtime");
3958
+ var import_jsx_runtime8 = require("react/jsx-runtime");
2846
3959
  function TablePagination({
2847
3960
  page,
2848
3961
  pageSize = 10,
@@ -2854,8 +3967,8 @@ function TablePagination({
2854
3967
  const safePage = Math.min(Math.max(1, page), totalPages);
2855
3968
  const canGoPrev = safePage > 1;
2856
3969
  const canGoNext = safePage < totalPages;
2857
- return /* @__PURE__ */ (0, import_jsx_runtime7.jsxs)("div", { className: cn("TablePaginationJSX", className), children: [
2858
- /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(
3970
+ return /* @__PURE__ */ (0, import_jsx_runtime8.jsxs)("div", { className: cn("TablePaginationJSX", className), children: [
3971
+ /* @__PURE__ */ (0, import_jsx_runtime8.jsx)(
2859
3972
  "button",
2860
3973
  {
2861
3974
  type: "button",
@@ -2863,15 +3976,15 @@ function TablePagination({
2863
3976
  disabled: !canGoPrev,
2864
3977
  onClick: () => onChange(safePage - 1),
2865
3978
  "aria-label": "Previous page",
2866
- children: /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(ChevronLeft, { className: "pagination-button-icon" })
3979
+ children: /* @__PURE__ */ (0, import_jsx_runtime8.jsx)(ChevronLeft, { className: "pagination-button-icon" })
2867
3980
  }
2868
3981
  ),
2869
- /* @__PURE__ */ (0, import_jsx_runtime7.jsxs)("span", { className: "pagination-label", children: [
3982
+ /* @__PURE__ */ (0, import_jsx_runtime8.jsxs)("span", { className: "pagination-label", children: [
2870
3983
  safePage,
2871
3984
  " / ",
2872
3985
  totalPages
2873
3986
  ] }),
2874
- /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(
3987
+ /* @__PURE__ */ (0, import_jsx_runtime8.jsx)(
2875
3988
  "button",
2876
3989
  {
2877
3990
  type: "button",
@@ -2879,7 +3992,7 @@ function TablePagination({
2879
3992
  disabled: !canGoNext,
2880
3993
  onClick: () => onChange(safePage + 1),
2881
3994
  "aria-label": "Next page",
2882
- children: /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(ChevronRight, { className: "pagination-button-icon" })
3995
+ children: /* @__PURE__ */ (0, import_jsx_runtime8.jsx)(ChevronRight, { className: "pagination-button-icon" })
2883
3996
  }
2884
3997
  )
2885
3998
  ] });
@@ -2887,7 +4000,7 @@ function TablePagination({
2887
4000
  TablePagination.displayName = TABLE_PAGINATION_DISPLAY_NAME;
2888
4001
 
2889
4002
  // src/components/ui/table/components/Table/Table.tsx
2890
- var import_jsx_runtime8 = require("react/jsx-runtime");
4003
+ var import_jsx_runtime9 = require("react/jsx-runtime");
2891
4004
  function TableRoot({
2892
4005
  data,
2893
4006
  children,
@@ -2896,12 +4009,12 @@ function TableRoot({
2896
4009
  filteredCount,
2897
4010
  ...dataTableProps
2898
4011
  }) {
2899
- const { header, pagination: paginationElement } = (0, import_react10.useMemo)(
4012
+ const { header, pagination: paginationElement } = (0, import_react11.useMemo)(
2900
4013
  () => parseTableChildren(children),
2901
4014
  [children]
2902
4015
  );
2903
- const [sort, setSort] = (0, import_react10.useState)(null);
2904
- const handleSort = (0, import_react10.useCallback)((field) => {
4016
+ const [sort, setSort] = (0, import_react11.useState)(null);
4017
+ const handleSort = (0, import_react11.useCallback)((field) => {
2905
4018
  setSort((previous) => {
2906
4019
  if (previous?.field !== field) {
2907
4020
  return { field, direction: "asc" };
@@ -2912,25 +4025,25 @@ function TableRoot({
2912
4025
  return null;
2913
4026
  });
2914
4027
  }, []);
2915
- const columns = (0, import_react10.useMemo)(() => {
2916
- return extractColumnElements(header).map(
2917
- (columnElement) => buildColumnDef(columnElement.props, sort, handleSort)
2918
- );
2919
- }, [header, sort, handleSort]);
4028
+ const columnTree = (0, import_react11.useMemo)(() => extractColumnTree(header), [header]);
4029
+ const columns = (0, import_react11.useMemo)(
4030
+ () => buildColumnDefsFromTree(columnTree, sort, handleSort),
4031
+ [columnTree, sort, handleSort]
4032
+ );
2920
4033
  const paginationProps = paginationElement?.props;
2921
4034
  const pageSize = paginationProps?.pageSize ?? 10;
2922
4035
  const page = paginationProps?.page ?? 1;
2923
4036
  const resolvedTotalCount = paginationProps?.totalCount ?? totalCount ?? data.length;
2924
- const tableData = (0, import_react10.useMemo)(() => {
4037
+ const tableData = (0, import_react11.useMemo)(() => {
2925
4038
  const sortedData = sortTableData(data, sort);
2926
4039
  if (!paginationProps) return sortedData;
2927
4040
  return paginateTableData(sortedData, page, pageSize);
2928
4041
  }, [data, sort, paginationProps, page, pageSize]);
2929
- if (columns.length === 0) {
4042
+ if (countLeafColumns(columnTree) === 0) {
2930
4043
  console.warn("[Table] Declare at least one Table.Column inside Table.Header.");
2931
4044
  }
2932
- return /* @__PURE__ */ (0, import_jsx_runtime8.jsxs)("div", { className: "TableJSX", children: [
2933
- /* @__PURE__ */ (0, import_jsx_runtime8.jsx)(
4045
+ return /* @__PURE__ */ (0, import_jsx_runtime9.jsxs)("div", { className: "TableJSX", children: [
4046
+ /* @__PURE__ */ (0, import_jsx_runtime9.jsx)(
2934
4047
  DataTable,
2935
4048
  {
2936
4049
  ...dataTableProps,
@@ -2941,7 +4054,7 @@ function TableRoot({
2941
4054
  className: cn(className, paginationProps && "DataTableJSX--with-pagination")
2942
4055
  }
2943
4056
  ),
2944
- paginationProps && /* @__PURE__ */ (0, import_jsx_runtime8.jsx)(
4057
+ paginationProps && /* @__PURE__ */ (0, import_jsx_runtime9.jsx)(
2945
4058
  TablePagination,
2946
4059
  {
2947
4060
  page,
@@ -2959,13 +4072,19 @@ function createTable() {
2959
4072
  return null;
2960
4073
  }
2961
4074
  Column.displayName = TABLE_COLUMN_DISPLAY_NAME;
4075
+ function ColumnGroup(props) {
4076
+ void props;
4077
+ return null;
4078
+ }
4079
+ ColumnGroup.displayName = TABLE_COLUMN_GROUP_DISPLAY_NAME;
2962
4080
  return Object.assign(
2963
4081
  function BoundTable(props) {
2964
- return /* @__PURE__ */ (0, import_jsx_runtime8.jsx)(TableRoot, { ...props });
4082
+ return /* @__PURE__ */ (0, import_jsx_runtime9.jsx)(TableRoot, { ...props });
2965
4083
  },
2966
4084
  {
2967
4085
  Header: TableHeader,
2968
4086
  Column,
4087
+ ColumnGroup,
2969
4088
  Body: TableBody,
2970
4089
  Pagination: TablePagination
2971
4090
  }
@@ -2974,6 +4093,7 @@ function createTable() {
2974
4093
  var Table = Object.assign(TableRoot, {
2975
4094
  Header: TableHeader,
2976
4095
  Column: TableColumn,
4096
+ ColumnGroup: TableColumnGroup,
2977
4097
  Body: TableBody,
2978
4098
  Pagination: TablePagination
2979
4099
  });
@@ -2986,20 +4106,31 @@ var Table = Object.assign(TableRoot, {
2986
4106
  DEFAULT_TREE_PARENT_ID_FIELD,
2987
4107
  DEFAULT_TREE_QTY_FIELD,
2988
4108
  DataTable,
4109
+ INLINE_SEARCH_MAX_RESULTS,
2989
4110
  Table,
2990
4111
  applyCellEdit,
2991
4112
  applyFillData,
2992
4113
  applySelectionUpdater,
2993
4114
  buildColumnFreezeOffsets,
2994
4115
  buildColumnRowSpanMap,
4116
+ buildFlatSearchCorpus,
2995
4117
  buildRowsPastePayload,
4118
+ buildSearchMatchKey,
4119
+ buildSearchMatchKeys,
4120
+ buildTreeSearchCorpus,
2996
4121
  canExpandRow,
4122
+ cellValueToSearchText,
4123
+ collectAncestorKeysToExpand,
2997
4124
  collectCopyRowEntries,
2998
4125
  collectCopyRows,
2999
4126
  collectFillChanges,
3000
4127
  collectRowSpanColumns,
4128
+ collectSearchMatchesInRange,
4129
+ createSearchRegex,
3001
4130
  createTable,
4131
+ escapeSearchRegex,
3002
4132
  flattenSubtreeRows,
4133
+ formatSearchResultLabel,
3003
4134
  getCellEditDraftValue,
3004
4135
  getCellSelectionEdgeStyle,
3005
4136
  getColumnEditType,
@@ -3011,10 +4142,15 @@ var Table = Object.assign(TableRoot, {
3011
4142
  isCellInSelection,
3012
4143
  isColumnEditable,
3013
4144
  isEditablePasteTarget,
4145
+ mapSearchResultToVisibleItem,
4146
+ mapSearchResultsToVisibleKeys,
3014
4147
  measureMergedSpanRowHeights,
4148
+ nextSearchIndex,
4149
+ nextSearchStride,
3015
4150
  parseCellEditValue,
3016
4151
  parseClipboardTSV,
3017
4152
  parseClipboardTSVWithDepths,
4153
+ previousSearchIndex,
3018
4154
  resolveColumnFreezeSide,
3019
4155
  resolveDataTableLabels,
3020
4156
  resolvePasteColumnIds,
@@ -3028,5 +4164,6 @@ var Table = Object.assign(TableRoot, {
3028
4164
  useCellSelection,
3029
4165
  useConvertTreeData,
3030
4166
  useGlideTable,
4167
+ useInlineSearch,
3031
4168
  writeSelectionToClipboard
3032
4169
  });