react-glide-table 1.4.1 → 1.6.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.js CHANGED
@@ -5,7 +5,12 @@ var DEFAULT_DATA_TABLE_LABELS = {
5
5
  selection: (selectedCount) => selectedCount > 0 ? `\u2713 ${selectedCount} selected` : null,
6
6
  expandRow: "Expand row",
7
7
  collapseRow: "Collapse row",
8
- resizeColumn: "Resize column"
8
+ resizeColumn: "Resize column",
9
+ searchPlaceholder: "Search\u2026",
10
+ searchResultHint: "Type to search",
11
+ searchPrevious: "Previous result",
12
+ searchNext: "Next result",
13
+ searchClose: "Close search"
9
14
  };
10
15
  function resolveDataTableLabels(partial) {
11
16
  return {
@@ -29,11 +34,11 @@ import {
29
34
  useVirtualizer
30
35
  } from "@tanstack/react-virtual";
31
36
  import {
32
- useCallback as useCallback3,
33
- useEffect as useEffect4,
34
- useMemo as useMemo2,
35
- useRef as useRef4,
36
- useState as useState3
37
+ useCallback as useCallback4,
38
+ useEffect as useEffect5,
39
+ useMemo as useMemo3,
40
+ useRef as useRef5,
41
+ useState as useState4
37
42
  } from "react";
38
43
 
39
44
  // src/components/ui/table/constants.ts
@@ -199,6 +204,36 @@ function getCellSelectionBounds(start, end) {
199
204
  endCol: Math.max(start.col, end.col)
200
205
  };
201
206
  }
207
+ function getCellNavigationDelta(key) {
208
+ switch (key) {
209
+ case "ArrowUp":
210
+ case "w":
211
+ case "W":
212
+ return { row: -1, col: 0 };
213
+ case "ArrowDown":
214
+ case "s":
215
+ case "S":
216
+ return { row: 1, col: 0 };
217
+ case "ArrowLeft":
218
+ case "a":
219
+ case "A":
220
+ return { row: 0, col: -1 };
221
+ case "ArrowRight":
222
+ case "d":
223
+ case "D":
224
+ return { row: 0, col: 1 };
225
+ default:
226
+ return null;
227
+ }
228
+ }
229
+ function clampCellPosition(position, rowCount, columnCount) {
230
+ const maxRow = Math.max(rowCount - 1, 0);
231
+ const maxCol = Math.max(columnCount - 1, 0);
232
+ return {
233
+ row: Math.min(Math.max(position.row, 0), maxRow),
234
+ col: Math.min(Math.max(position.col, 0), maxCol)
235
+ };
236
+ }
202
237
  function measureMergedSpanRowHeights(rowIndex, rowSpan, cellElement) {
203
238
  if (rowSpan <= 1) return void 0;
204
239
  const tbody = cellElement?.closest("tbody") ?? (typeof document !== "undefined" ? document.querySelector("tbody.data-table-body") : null);
@@ -722,26 +757,44 @@ function useCellSelection({
722
757
  data,
723
758
  rows,
724
759
  enabled = true,
760
+ columnCount = 0,
725
761
  enableSubtreeCopy = false,
726
762
  enableInsertPaste = true,
727
763
  onDataChange,
728
764
  onBatchChange,
729
- onRowsPaste
765
+ onRowsPaste,
766
+ onCellNavigate
730
767
  }) {
731
768
  const [dragState, setDragState] = useState2(INITIAL_DRAG_STATE);
732
769
  const pendingPasteModeRef = useRef2(null);
770
+ const dragStateRef = useRef2(dragState);
771
+ const onCellNavigateRef = useRef2(onCellNavigate);
772
+ dragStateRef.current = dragState;
773
+ onCellNavigateRef.current = onCellNavigate;
733
774
  const cellSelectionBounds = getCellSelectionBounds(dragState.start, dragState.end);
734
775
  const activeSelectionBounds = enabled ? getActiveSelectionBounds(dragState, cellSelectionBounds) : null;
735
776
  const handleCellMouseDown = useCallback2(
736
- (rowIndex, colIndex) => {
777
+ (rowIndex, colIndex, options) => {
737
778
  if (!enabled) return;
738
- setDragState({
739
- isSelecting: true,
740
- isFillDragging: false,
741
- start: { row: rowIndex, col: colIndex },
742
- end: { row: rowIndex, col: colIndex },
743
- fillAnchor: null,
744
- fillEnd: null
779
+ setDragState((prev) => {
780
+ if (options?.shiftKey && prev.start) {
781
+ return {
782
+ ...prev,
783
+ isSelecting: true,
784
+ isFillDragging: false,
785
+ end: { row: rowIndex, col: colIndex },
786
+ fillAnchor: null,
787
+ fillEnd: null
788
+ };
789
+ }
790
+ return {
791
+ isSelecting: true,
792
+ isFillDragging: false,
793
+ start: { row: rowIndex, col: colIndex },
794
+ end: { row: rowIndex, col: colIndex },
795
+ fillAnchor: null,
796
+ fillEnd: null
797
+ };
745
798
  });
746
799
  },
747
800
  [enabled]
@@ -783,6 +836,53 @@ function useCellSelection({
783
836
  setDragState(INITIAL_DRAG_STATE);
784
837
  }
785
838
  }, [enabled]);
839
+ useEffect2(() => {
840
+ if (!enabled) return;
841
+ const handleKeyDown = (e) => {
842
+ if (e.ctrlKey || e.metaKey || e.altKey) return;
843
+ if (isEditablePasteTarget(e.target) || isEditablePasteTarget(document.activeElement)) {
844
+ return;
845
+ }
846
+ const delta = getCellNavigationDelta(e.key);
847
+ if (!delta) return;
848
+ const prev = dragStateRef.current;
849
+ if (!prev.start || !prev.end) return;
850
+ if (prev.isSelecting || prev.isFillDragging) return;
851
+ const rowCount = rows.length;
852
+ const resolvedColumnCount = columnCount > 0 ? columnCount : rows[0]?.getVisibleCells().length ?? 0;
853
+ if (rowCount <= 0 || resolvedColumnCount <= 0) return;
854
+ const nextEnd = clampCellPosition(
855
+ {
856
+ row: prev.end.row + delta.row,
857
+ col: prev.end.col + delta.col
858
+ },
859
+ rowCount,
860
+ resolvedColumnCount
861
+ );
862
+ if (nextEnd.row === prev.end.row && nextEnd.col === prev.end.col) return;
863
+ e.preventDefault();
864
+ const nextState = e.shiftKey ? {
865
+ ...prev,
866
+ isSelecting: false,
867
+ isFillDragging: false,
868
+ end: nextEnd,
869
+ fillAnchor: null,
870
+ fillEnd: null
871
+ } : {
872
+ isSelecting: false,
873
+ isFillDragging: false,
874
+ start: nextEnd,
875
+ end: nextEnd,
876
+ fillAnchor: null,
877
+ fillEnd: null
878
+ };
879
+ dragStateRef.current = nextState;
880
+ setDragState(nextState);
881
+ onCellNavigateRef.current?.(nextEnd);
882
+ };
883
+ window.addEventListener("keydown", handleKeyDown);
884
+ return () => window.removeEventListener("keydown", handleKeyDown);
885
+ }, [columnCount, enabled, rows]);
786
886
  const copySelection = useCallback2(
787
887
  async (options) => {
788
888
  if (!enabled || !activeSelectionBounds) return false;
@@ -1023,8 +1123,469 @@ function getColumnFreezeStyle(offset, options) {
1023
1123
  };
1024
1124
  }
1025
1125
 
1126
+ // src/components/ui/table/features/inline-search/inlineSearch.ts
1127
+ var INLINE_SEARCH_MAX_RESULTS = 1e3;
1128
+ var INLINE_SEARCH_TARGET_TICK_MS = 10;
1129
+ var INLINE_SEARCH_INITIAL_STRIDE = 10;
1130
+ function escapeSearchRegex(value) {
1131
+ return value.replace(/([$()*+.?[\\\]^{|}-])/g, "\\$1");
1132
+ }
1133
+ function createSearchRegex(query) {
1134
+ const trimmed = query.trim();
1135
+ if (!trimmed) return null;
1136
+ return new RegExp(escapeSearchRegex(trimmed), "i");
1137
+ }
1138
+ function cellValueToSearchText(value) {
1139
+ if (value == null) return void 0;
1140
+ if (typeof value === "string") return value;
1141
+ if (typeof value === "number" || typeof value === "boolean") {
1142
+ return String(value);
1143
+ }
1144
+ if (Array.isArray(value)) {
1145
+ return value.map((item) => cellValueToSearchText(item) ?? "").join(" ");
1146
+ }
1147
+ if (typeof value === "object") {
1148
+ try {
1149
+ return JSON.stringify(value);
1150
+ } catch {
1151
+ return String(value);
1152
+ }
1153
+ }
1154
+ return String(value);
1155
+ }
1156
+ function formatSearchResultLabel(status) {
1157
+ const countLabel = status.results >= INLINE_SEARCH_MAX_RESULTS ? `over ${INLINE_SEARCH_MAX_RESULTS}` : `${status.results} result${status.results !== 1 ? "s" : ""}`;
1158
+ if (status.selectedIndex >= 0 && status.results > 0) {
1159
+ return `${status.selectedIndex + 1} of ${countLabel}`;
1160
+ }
1161
+ return countLabel;
1162
+ }
1163
+ function nextSearchIndex(selectedIndex, results) {
1164
+ if (results <= 0) return -1;
1165
+ if (selectedIndex < 0) return 0;
1166
+ return (selectedIndex + 1) % results;
1167
+ }
1168
+ function previousSearchIndex(selectedIndex, results) {
1169
+ if (results <= 0) return -1;
1170
+ if (selectedIndex < 0) return results - 1;
1171
+ let next = (selectedIndex - 1) % results;
1172
+ if (next < 0) next += results;
1173
+ return next;
1174
+ }
1175
+ function buildSearchMatchKey(colIndex, rowIndex) {
1176
+ return `${colIndex}:${rowIndex}`;
1177
+ }
1178
+ function buildSearchMatchKeys(results) {
1179
+ const keys = /* @__PURE__ */ new Set();
1180
+ for (const [colIndex, rowIndex] of results) {
1181
+ keys.add(buildSearchMatchKey(colIndex, rowIndex));
1182
+ }
1183
+ return keys;
1184
+ }
1185
+ function collectSearchMatchesInRange(options) {
1186
+ const {
1187
+ query,
1188
+ startRow,
1189
+ rowCount,
1190
+ columnCount,
1191
+ getCellValue,
1192
+ maxResults = INLINE_SEARCH_MAX_RESULTS
1193
+ } = options;
1194
+ const regex = createSearchRegex(query);
1195
+ if (!regex || rowCount <= 0 || columnCount <= 0) return [];
1196
+ const matches = [];
1197
+ for (let rowOffset = 0; rowOffset < rowCount; rowOffset += 1) {
1198
+ const rowIndex = startRow + rowOffset;
1199
+ for (let colIndex = 0; colIndex < columnCount; colIndex += 1) {
1200
+ const text = cellValueToSearchText(getCellValue(rowIndex, colIndex));
1201
+ if (text !== void 0 && regex.test(text)) {
1202
+ matches.push([colIndex, rowIndex]);
1203
+ if (matches.length >= maxResults) {
1204
+ return matches;
1205
+ }
1206
+ }
1207
+ }
1208
+ }
1209
+ return matches;
1210
+ }
1211
+ function nextSearchStride(currentStride, elapsedMs, targetMs = INLINE_SEARCH_TARGET_TICK_MS) {
1212
+ const rounded = Math.max(elapsedMs, 1);
1213
+ const scalar = targetMs / rounded;
1214
+ return Math.max(1, Math.ceil(currentStride * scalar));
1215
+ }
1216
+ function buildFlatSearchCorpus(rows, getRowId) {
1217
+ return rows.map((data, index) => ({
1218
+ id: getRowId(data, index),
1219
+ data,
1220
+ ancestorToggleKeys: []
1221
+ }));
1222
+ }
1223
+ function buildTreeSearchCorpus(visibleRows, options) {
1224
+ const { toggleField, getRowId } = options;
1225
+ const corpus = [];
1226
+ const seen = /* @__PURE__ */ new Set();
1227
+ const walk = (node, ancestorToggleKeys) => {
1228
+ const id = getRowId(node, corpus.length);
1229
+ if (seen.has(id)) return;
1230
+ seen.add(id);
1231
+ corpus.push({
1232
+ id,
1233
+ data: node,
1234
+ ancestorToggleKeys
1235
+ });
1236
+ const children = node.children;
1237
+ if (!Array.isArray(children) || children.length === 0) return;
1238
+ const toggleValue = node[toggleField];
1239
+ const childAncestors = typeof toggleValue === "string" && toggleValue.length > 0 ? [...ancestorToggleKeys, toggleValue] : ancestorToggleKeys;
1240
+ for (const child of children) {
1241
+ if (child && typeof child === "object") {
1242
+ walk(child, childAncestors);
1243
+ }
1244
+ }
1245
+ };
1246
+ for (const row of visibleRows) {
1247
+ const level = row.level;
1248
+ if (level === 0 || level === void 0) {
1249
+ walk(row, []);
1250
+ }
1251
+ }
1252
+ for (const row of visibleRows) {
1253
+ const id = getRowId(row, corpus.length);
1254
+ if (seen.has(id)) continue;
1255
+ walk(row, []);
1256
+ }
1257
+ return corpus;
1258
+ }
1259
+ function mapSearchResultsToVisibleKeys(results, corpus, visibleRowIndexById) {
1260
+ const keys = /* @__PURE__ */ new Set();
1261
+ for (const [colIndex, corpusRowIndex] of results) {
1262
+ const corpusRow = corpus[corpusRowIndex];
1263
+ if (!corpusRow) continue;
1264
+ const visibleRowIndex = visibleRowIndexById.get(corpusRow.id);
1265
+ if (visibleRowIndex === void 0) continue;
1266
+ keys.add(buildSearchMatchKey(colIndex, visibleRowIndex));
1267
+ }
1268
+ return keys;
1269
+ }
1270
+ function mapSearchResultToVisibleItem(item, corpus, visibleRowIndexById) {
1271
+ const [colIndex, corpusRowIndex] = item;
1272
+ const corpusRow = corpus[corpusRowIndex];
1273
+ if (!corpusRow) return null;
1274
+ const visibleRowIndex = visibleRowIndexById.get(corpusRow.id);
1275
+ if (visibleRowIndex === void 0) return null;
1276
+ return [colIndex, visibleRowIndex];
1277
+ }
1278
+ function collectAncestorKeysToExpand(corpusRow, expandedRows) {
1279
+ return corpusRow.ancestorToggleKeys.filter((key) => !expandedRows.has(key));
1280
+ }
1281
+
1282
+ // src/components/ui/table/features/inline-search/useInlineSearch.ts
1283
+ import {
1284
+ useCallback as useCallback3,
1285
+ useEffect as useEffect3,
1286
+ useId,
1287
+ useMemo,
1288
+ useRef as useRef3,
1289
+ useState as useState3
1290
+ } from "react";
1291
+ var EMPTY_MATCH_KEYS = /* @__PURE__ */ new Set();
1292
+ function useInlineSearch({
1293
+ enabled = false,
1294
+ rowCount,
1295
+ columnCount,
1296
+ getCellValue,
1297
+ initialStartRow = 0,
1298
+ showSearch: controlledShowSearch,
1299
+ searchValue: controlledSearchValue,
1300
+ searchResults: controlledSearchResults,
1301
+ onSearchValueChange,
1302
+ onSearchClose,
1303
+ onSearchResultsChanged,
1304
+ onNavigateToResult,
1305
+ rootRef
1306
+ }) {
1307
+ const searchInputId = useId();
1308
+ const searchInputRef = useRef3(null);
1309
+ const [internalShowSearch, setInternalShowSearch] = useState3(false);
1310
+ const [internalSearchValue, setInternalSearchValue] = useState3("");
1311
+ const [internalResults, setInternalResults] = useState3(
1312
+ []
1313
+ );
1314
+ const [searchStatus, setSearchStatus] = useState3();
1315
+ const searchStatusRef = useRef3(searchStatus);
1316
+ searchStatusRef.current = searchStatus;
1317
+ const abortControllerRef = useRef3(null);
1318
+ const searchHandleRef = useRef3(void 0);
1319
+ const initialStartRowRef = useRef3(initialStartRow);
1320
+ initialStartRowRef.current = initialStartRow;
1321
+ const getCellValueRef = useRef3(getCellValue);
1322
+ getCellValueRef.current = getCellValue;
1323
+ const showSearch = controlledShowSearch ?? internalShowSearch;
1324
+ const searchValue = controlledSearchValue ?? internalSearchValue;
1325
+ const searchResults = controlledSearchResults ?? internalResults;
1326
+ const setSearchValue = useCallback3(
1327
+ (value) => {
1328
+ setInternalSearchValue(value);
1329
+ onSearchValueChange?.(value);
1330
+ },
1331
+ [onSearchValueChange]
1332
+ );
1333
+ const cancelSearch = useCallback3(() => {
1334
+ if (searchHandleRef.current !== void 0) {
1335
+ window.cancelAnimationFrame(searchHandleRef.current);
1336
+ searchHandleRef.current = void 0;
1337
+ }
1338
+ abortControllerRef.current?.abort();
1339
+ }, []);
1340
+ const emitResultsChanged = useCallback3(
1341
+ (results, navIndex) => {
1342
+ onSearchResultsChanged?.(results, navIndex);
1343
+ },
1344
+ [onSearchResultsChanged]
1345
+ );
1346
+ const navigateToIndex = useCallback3(
1347
+ (results, navIndex) => {
1348
+ if (onSearchResultsChanged) return;
1349
+ if (navIndex < 0 || navIndex >= results.length) return;
1350
+ const item = results[navIndex];
1351
+ if (!item) return;
1352
+ onNavigateToResult?.(item);
1353
+ },
1354
+ [onNavigateToResult, onSearchResultsChanged]
1355
+ );
1356
+ const beginSearch = useCallback3(
1357
+ (query) => {
1358
+ if (controlledSearchResults !== void 0) return;
1359
+ const totalRows = rowCount;
1360
+ if (totalRows === 0 || columnCount === 0) {
1361
+ setSearchStatus(void 0);
1362
+ setInternalResults([]);
1363
+ emitResultsChanged([], -1);
1364
+ return;
1365
+ }
1366
+ let startY = Math.min(
1367
+ Math.max(0, initialStartRowRef.current),
1368
+ totalRows - 1
1369
+ );
1370
+ let searchStride = Math.min(INLINE_SEARCH_INITIAL_STRIDE, totalRows);
1371
+ let rowsSearched = 0;
1372
+ const runningResult = [];
1373
+ setSearchStatus(void 0);
1374
+ setInternalResults([]);
1375
+ const tick = () => {
1376
+ if (abortControllerRef.current?.signal.aborted) return;
1377
+ const tStart = performance.now();
1378
+ const rowsLeft = totalRows - rowsSearched;
1379
+ const height = Math.min(searchStride, rowsLeft, totalRows - startY);
1380
+ if (height <= 0) {
1381
+ return;
1382
+ }
1383
+ const chunk = collectSearchMatchesInRange({
1384
+ query,
1385
+ startRow: startY,
1386
+ rowCount: height,
1387
+ columnCount,
1388
+ getCellValue: (rowIndex, colIndex) => getCellValueRef.current(rowIndex, colIndex),
1389
+ maxResults: INLINE_SEARCH_MAX_RESULTS - runningResult.length
1390
+ });
1391
+ if (chunk.length > 0) {
1392
+ runningResult.push(...chunk);
1393
+ setInternalResults([...runningResult]);
1394
+ }
1395
+ rowsSearched += height;
1396
+ const selectedIndex = searchStatusRef.current?.selectedIndex ?? -1;
1397
+ setSearchStatus({
1398
+ results: runningResult.length,
1399
+ rowsSearched,
1400
+ selectedIndex
1401
+ });
1402
+ emitResultsChanged(runningResult, selectedIndex);
1403
+ if (startY + height >= totalRows) {
1404
+ startY = 0;
1405
+ } else {
1406
+ startY += height;
1407
+ }
1408
+ searchStride = nextSearchStride(
1409
+ searchStride,
1410
+ performance.now() - tStart
1411
+ );
1412
+ if (rowsSearched < totalRows && runningResult.length < INLINE_SEARCH_MAX_RESULTS) {
1413
+ searchHandleRef.current = window.requestAnimationFrame(tick);
1414
+ }
1415
+ };
1416
+ cancelSearch();
1417
+ abortControllerRef.current = new AbortController();
1418
+ searchHandleRef.current = window.requestAnimationFrame(tick);
1419
+ },
1420
+ [
1421
+ cancelSearch,
1422
+ columnCount,
1423
+ controlledSearchResults,
1424
+ emitResultsChanged,
1425
+ rowCount
1426
+ ]
1427
+ );
1428
+ const openSearch = useCallback3(() => {
1429
+ if (controlledShowSearch === void 0) {
1430
+ setInternalShowSearch(true);
1431
+ }
1432
+ }, [controlledShowSearch]);
1433
+ const closeSearch = useCallback3(() => {
1434
+ if (controlledShowSearch === void 0) {
1435
+ setInternalShowSearch(false);
1436
+ }
1437
+ onSearchClose?.();
1438
+ setSearchStatus(void 0);
1439
+ setInternalResults([]);
1440
+ emitResultsChanged([], -1);
1441
+ cancelSearch();
1442
+ }, [
1443
+ cancelSearch,
1444
+ controlledShowSearch,
1445
+ emitResultsChanged,
1446
+ onSearchClose
1447
+ ]);
1448
+ const goToNext = useCallback3(() => {
1449
+ if (!searchStatus || searchStatus.results === 0) return;
1450
+ const newIndex = nextSearchIndex(
1451
+ searchStatus.selectedIndex,
1452
+ searchStatus.results
1453
+ );
1454
+ setSearchStatus({ ...searchStatus, selectedIndex: newIndex });
1455
+ emitResultsChanged(searchResults, newIndex);
1456
+ navigateToIndex(searchResults, newIndex);
1457
+ }, [emitResultsChanged, navigateToIndex, searchResults, searchStatus]);
1458
+ const goToPrevious = useCallback3(() => {
1459
+ if (!searchStatus || searchStatus.results === 0) return;
1460
+ const newIndex = previousSearchIndex(
1461
+ searchStatus.selectedIndex,
1462
+ searchStatus.results
1463
+ );
1464
+ setSearchStatus({ ...searchStatus, selectedIndex: newIndex });
1465
+ emitResultsChanged(searchResults, newIndex);
1466
+ navigateToIndex(searchResults, newIndex);
1467
+ }, [emitResultsChanged, navigateToIndex, searchResults, searchStatus]);
1468
+ useEffect3(() => {
1469
+ if (controlledSearchResults === void 0) return;
1470
+ if (controlledSearchResults.length > 0) {
1471
+ setSearchStatus((current) => ({
1472
+ rowsSearched: rowCount,
1473
+ results: controlledSearchResults.length,
1474
+ selectedIndex: current?.selectedIndex ?? -1
1475
+ }));
1476
+ } else {
1477
+ setSearchStatus(void 0);
1478
+ }
1479
+ }, [controlledSearchResults, rowCount]);
1480
+ useEffect3(() => {
1481
+ if (!enabled) return;
1482
+ setSearchStatus(void 0);
1483
+ setInternalResults([]);
1484
+ emitResultsChanged([], -1);
1485
+ if (showSearch) {
1486
+ queueMicrotask(() => {
1487
+ searchInputRef.current?.focus({ preventScroll: true });
1488
+ });
1489
+ } else {
1490
+ cancelSearch();
1491
+ }
1492
+ }, [enabled, showSearch]);
1493
+ useEffect3(() => {
1494
+ if (!enabled || !showSearch) return;
1495
+ if (controlledSearchResults !== void 0) return;
1496
+ if (searchValue.trim() === "") {
1497
+ setSearchStatus(void 0);
1498
+ setInternalResults([]);
1499
+ cancelSearch();
1500
+ emitResultsChanged([], -1);
1501
+ return;
1502
+ }
1503
+ beginSearch(searchValue);
1504
+ }, [
1505
+ beginSearch,
1506
+ cancelSearch,
1507
+ controlledSearchResults,
1508
+ emitResultsChanged,
1509
+ enabled,
1510
+ searchValue,
1511
+ showSearch
1512
+ ]);
1513
+ useEffect3(() => {
1514
+ if (!enabled) return;
1515
+ const handleKeyDown = (event) => {
1516
+ if (!(event.ctrlKey || event.metaKey)) return;
1517
+ if (event.key.toLowerCase() !== "f") return;
1518
+ const root = rootRef?.current;
1519
+ if (root) {
1520
+ const active = document.activeElement;
1521
+ const focusInside = active === root || active instanceof Node && root.contains(active);
1522
+ if (!focusInside && active !== document.body) {
1523
+ return;
1524
+ }
1525
+ }
1526
+ event.preventDefault();
1527
+ event.stopPropagation();
1528
+ if (showSearch) {
1529
+ searchInputRef.current?.focus({ preventScroll: true });
1530
+ searchInputRef.current?.select();
1531
+ return;
1532
+ }
1533
+ if (controlledShowSearch === void 0) {
1534
+ setInternalShowSearch(true);
1535
+ }
1536
+ };
1537
+ window.addEventListener("keydown", handleKeyDown, true);
1538
+ return () => window.removeEventListener("keydown", handleKeyDown, true);
1539
+ }, [controlledShowSearch, enabled, rootRef, showSearch]);
1540
+ useEffect3(() => () => cancelSearch(), [cancelSearch]);
1541
+ const searchMatchKeys = useMemo(
1542
+ () => buildSearchMatchKeys(searchResults),
1543
+ [searchResults]
1544
+ );
1545
+ const activeMatch = useMemo(() => {
1546
+ if (!searchStatus || searchStatus.selectedIndex < 0) return null;
1547
+ return searchResults[searchStatus.selectedIndex] ?? null;
1548
+ }, [searchResults, searchStatus]);
1549
+ if (!enabled) {
1550
+ return {
1551
+ enabled: false,
1552
+ showSearch: false,
1553
+ searchValue: "",
1554
+ searchResults: [],
1555
+ searchStatus: void 0,
1556
+ searchMatchKeys: EMPTY_MATCH_KEYS,
1557
+ activeMatch: null,
1558
+ searchInputRef,
1559
+ searchInputId,
1560
+ canClose: false,
1561
+ openSearch,
1562
+ closeSearch,
1563
+ setSearchValue,
1564
+ goToNext,
1565
+ goToPrevious
1566
+ };
1567
+ }
1568
+ return {
1569
+ enabled: true,
1570
+ showSearch,
1571
+ searchValue,
1572
+ searchResults,
1573
+ searchStatus,
1574
+ searchMatchKeys,
1575
+ activeMatch,
1576
+ searchInputRef,
1577
+ searchInputId,
1578
+ canClose: controlledShowSearch === void 0 || onSearchClose !== void 0,
1579
+ openSearch,
1580
+ closeSearch,
1581
+ setSearchValue,
1582
+ goToNext,
1583
+ goToPrevious
1584
+ };
1585
+ }
1586
+
1026
1587
  // src/components/ui/table/features/row-expand/row-expand.ts
1027
- import { useEffect as useEffect3, useMemo, useRef as useRef3 } from "react";
1588
+ import { useEffect as useEffect4, useMemo as useMemo2, useRef as useRef4 } from "react";
1028
1589
  function getFieldValue(row, key) {
1029
1590
  return row[key];
1030
1591
  }
@@ -1054,12 +1615,12 @@ var useConvertTreeData = ({
1054
1615
  expandedRows,
1055
1616
  onExpandedRowsChange
1056
1617
  }) => {
1057
- const onExpandedRowsChangeRef = useRef3(onExpandedRowsChange);
1058
- const hasInitializedRef = useRef3(false);
1059
- useEffect3(() => {
1618
+ const onExpandedRowsChangeRef = useRef4(onExpandedRowsChange);
1619
+ const hasInitializedRef = useRef4(false);
1620
+ useEffect4(() => {
1060
1621
  onExpandedRowsChangeRef.current = onExpandedRowsChange;
1061
1622
  }, [onExpandedRowsChange]);
1062
- useEffect3(() => {
1623
+ useEffect4(() => {
1063
1624
  if (!data || data.length === 0) {
1064
1625
  hasInitializedRef.current = false;
1065
1626
  return;
@@ -1069,7 +1630,7 @@ var useConvertTreeData = ({
1069
1630
  onExpandedRowsChangeRef.current?.(new Set(ids));
1070
1631
  hasInitializedRef.current = true;
1071
1632
  }, [enabled, data, toggleField]);
1072
- const processedData = useMemo(() => {
1633
+ const processedData = useMemo2(() => {
1073
1634
  if (!enabled || !data || data.length === 0) return [];
1074
1635
  const flattenedData = [];
1075
1636
  const flattenItems = (items) => {
@@ -1133,7 +1694,7 @@ var useConvertTreeData = ({
1133
1694
  });
1134
1695
  return rootItems;
1135
1696
  }, [enabled, data, toggleField, childField, flattenField]);
1136
- const flattenTree = useMemo(() => {
1697
+ const flattenTree = useMemo2(() => {
1137
1698
  if (!enabled) return [];
1138
1699
  const flatten = (nodes, result = [], level = 0) => {
1139
1700
  nodes.forEach((node, index) => {
@@ -1183,7 +1744,7 @@ var useConvertTreeData = ({
1183
1744
  preventExpand,
1184
1745
  expandedRows
1185
1746
  ]);
1186
- const sortedData = useMemo(() => {
1747
+ const sortedData = useMemo2(() => {
1187
1748
  if (!enabled) {
1188
1749
  return data ?? [];
1189
1750
  }
@@ -1289,6 +1850,7 @@ function collectRowSpanColumns(columns) {
1289
1850
 
1290
1851
  // src/core/useGlideTable.ts
1291
1852
  var EMPTY_COLUMN_FREEZE_OFFSETS = /* @__PURE__ */ new Map();
1853
+ var EMPTY_SEARCH_MATCH_KEYS = /* @__PURE__ */ new Set();
1292
1854
  function useGlideTable(options) {
1293
1855
  const {
1294
1856
  data,
@@ -1329,9 +1891,16 @@ function useGlideTable(options) {
1329
1891
  columnSizing: controlledColumnSizing,
1330
1892
  onColumnSizingChange,
1331
1893
  columnResizeMode = "onChange",
1332
- enableColumnFreeze = false
1894
+ enableColumnFreeze = false,
1895
+ enableInlineSearch = false,
1896
+ showSearch,
1897
+ searchValue,
1898
+ onSearchValueChange,
1899
+ onSearchClose,
1900
+ searchResults,
1901
+ onSearchResultsChanged
1333
1902
  } = options;
1334
- const labels = useMemo2(() => {
1903
+ const labels = useMemo3(() => {
1335
1904
  const resolved = resolveDataTableLabels(labelsProp);
1336
1905
  return {
1337
1906
  ...resolved,
@@ -1342,15 +1911,16 @@ function useGlideTable(options) {
1342
1911
  }, [labelsProp, emptyText, loadingText, selectionLabel]);
1343
1912
  const enableExpand = Boolean(toggleField);
1344
1913
  const resolvedEnableSubtreeCopy = enableSubtreeCopy ?? enableExpand;
1345
- const [internalRowSelection, setInternalRowSelection] = useState3({});
1346
- const [internalColumnSizing, setInternalColumnSizing] = useState3({});
1347
- const [internalExpandedRows, setInternalExpandedRows] = useState3(
1914
+ const [internalRowSelection, setInternalRowSelection] = useState4({});
1915
+ const [internalColumnSizing, setInternalColumnSizing] = useState4({});
1916
+ const [internalExpandedRows, setInternalExpandedRows] = useState4(
1348
1917
  () => /* @__PURE__ */ new Set()
1349
1918
  );
1350
- const [hoveredRowIndex, setHoveredRowIndex] = useState3(null);
1351
- const scrollRef = useRef4(null);
1919
+ const [hoveredRowIndex, setHoveredRowIndex] = useState4(null);
1920
+ const scrollRef = useRef5(null);
1921
+ const rootRef = useRef5(null);
1352
1922
  const shouldVirtualize = enableVirtualization && !enableRowSpan;
1353
- useEffect4(() => {
1923
+ useEffect5(() => {
1354
1924
  if (enableVirtualization && enableRowSpan) {
1355
1925
  console.warn(
1356
1926
  "[useGlideTable] enableRowSpan is on; virtualization is disabled to preserve cell merges."
@@ -1364,7 +1934,7 @@ function useGlideTable(options) {
1364
1934
  );
1365
1935
  const columnSizing = controlledColumnSizing ?? internalColumnSizing;
1366
1936
  const expandedRows = controlledExpandedRows ?? internalExpandedRows;
1367
- const handleExpandedRowsChange = useCallback3(
1937
+ const handleExpandedRowsChange = useCallback4(
1368
1938
  (next) => {
1369
1939
  if (onExpandedRowsChange) {
1370
1940
  onExpandedRowsChange(next);
@@ -1425,13 +1995,13 @@ function useGlideTable(options) {
1425
1995
  getCoreRowModel: getCoreRowModel(),
1426
1996
  getRowId: getRowId ? (originalRow, index) => getRowId(originalRow, index) : (_originalRow, index) => String(index)
1427
1997
  });
1428
- const rowSpanColumnKeys = useMemo2(() => {
1998
+ const rowSpanColumnKeys = useMemo3(() => {
1429
1999
  if (!enableRowSpan) return [];
1430
2000
  return collectRowSpanColumns(columns);
1431
2001
  }, [enableRowSpan, columns]);
1432
2002
  const primaryRowSpanKey = rowSpanColumnKeys[0]?.rowSpanKey;
1433
2003
  const primaryRowSpanColumnId = rowSpanColumnKeys[0]?.columnId;
1434
- const columnRowSpanMap = useMemo2(
2004
+ const columnRowSpanMap = useMemo3(
1435
2005
  () => buildColumnRowSpanMap(tableData, rowSpanColumnKeys),
1436
2006
  [tableData, rowSpanColumnKeys]
1437
2007
  );
@@ -1440,7 +2010,7 @@ function useGlideTable(options) {
1440
2010
  const rows = table.getRowModel().rows;
1441
2011
  const columnCount = table.getAllLeafColumns().length || 1;
1442
2012
  const visibleLeafColumns = table.getVisibleLeafColumns();
1443
- const columnFreezeOffsets = useMemo2(() => {
2013
+ const columnFreezeOffsets = useMemo3(() => {
1444
2014
  if (!enableColumnFreeze) return EMPTY_COLUMN_FREEZE_OFFSETS;
1445
2015
  return buildColumnFreezeOffsets(
1446
2016
  visibleLeafColumns.map((column) => ({
@@ -1460,13 +2030,46 @@ function useGlideTable(options) {
1460
2030
  const totalSize = rowVirtualizer.getTotalSize();
1461
2031
  const paddingTop = virtualRows.length > 0 ? virtualRows[0]?.start ?? 0 : 0;
1462
2032
  const paddingBottom = virtualRows.length > 0 ? totalSize - (virtualRows[virtualRows.length - 1]?.end ?? 0) : 0;
1463
- const selectedRowIndices = useMemo2(() => {
2033
+ const selectedRowIndices = useMemo3(() => {
1464
2034
  const indices = /* @__PURE__ */ new Set();
1465
2035
  for (const selectedRow of selectedRows) {
1466
2036
  indices.add(selectedRow.index);
1467
2037
  }
1468
2038
  return indices;
1469
2039
  }, [selectedRows]);
2040
+ const scrollCellIntoView = useCallback4(
2041
+ (rowIndex, colIndex, options2) => {
2042
+ const align = options2?.align ?? "nearest";
2043
+ const blockAlign = align === "center" ? "center" : "nearest";
2044
+ if (shouldVirtualize) {
2045
+ rowVirtualizer.scrollToIndex(rowIndex, {
2046
+ align: align === "nearest" ? "auto" : align
2047
+ });
2048
+ }
2049
+ const scrollElement = scrollRef.current;
2050
+ if (!scrollElement) return;
2051
+ const scrollToMatchedCell = () => {
2052
+ const cell = scrollElement.querySelector(
2053
+ `[data-row-index="${rowIndex}"][data-col-index="${colIndex}"]`
2054
+ );
2055
+ if (cell instanceof HTMLElement) {
2056
+ cell.scrollIntoView({ block: blockAlign, inline: "nearest" });
2057
+ }
2058
+ };
2059
+ if (shouldVirtualize) {
2060
+ requestAnimationFrame(scrollToMatchedCell);
2061
+ return;
2062
+ }
2063
+ scrollToMatchedCell();
2064
+ },
2065
+ [rowVirtualizer, shouldVirtualize]
2066
+ );
2067
+ const handleCellNavigate = useCallback4(
2068
+ (position) => {
2069
+ scrollCellIntoView(position.row, position.col, { align: "nearest" });
2070
+ },
2071
+ [scrollCellIntoView]
2072
+ );
1470
2073
  const {
1471
2074
  dragState,
1472
2075
  activeSelectionBounds,
@@ -1478,11 +2081,13 @@ function useGlideTable(options) {
1478
2081
  data: tableData,
1479
2082
  rows,
1480
2083
  enabled: enableCellSelection,
2084
+ columnCount: visibleLeafColumns.length,
1481
2085
  enableSubtreeCopy: resolvedEnableSubtreeCopy,
1482
2086
  enableInsertPaste: enableInsertPaste ?? true,
1483
2087
  onDataChange,
1484
2088
  onBatchChange,
1485
- onRowsPaste
2089
+ onRowsPaste,
2090
+ onCellNavigate: handleCellNavigate
1486
2091
  });
1487
2092
  const {
1488
2093
  editingCell,
@@ -1492,23 +2097,193 @@ function useGlideTable(options) {
1492
2097
  commitEdit,
1493
2098
  cancelEdit
1494
2099
  } = useCellEdit({ data: tableData, rows, onDataChange, onCellChange });
1495
- const handleCellMouseDownWithCommit = useCallback3(
1496
- (rowIndex, colIndex) => {
2100
+ const handleCellMouseDownWithCommit = useCallback4(
2101
+ (rowIndex, colIndex, options2) => {
1497
2102
  const isSameEditingCell = editingCell?.rowIndex === rowIndex && editingCell?.colIndex === colIndex;
1498
2103
  if (editingCell && !isSameEditingCell && !commitEdit()) {
1499
2104
  return;
1500
2105
  }
1501
- handleCellMouseDown(rowIndex, colIndex);
2106
+ handleCellMouseDown(rowIndex, colIndex, options2);
1502
2107
  },
1503
2108
  [commitEdit, editingCell, handleCellMouseDown]
1504
2109
  );
1505
- const clearHover = useCallback3(() => {
2110
+ const navigateToSearchResult = useCallback4(
2111
+ (item) => {
2112
+ const [colIndex, rowIndex] = item;
2113
+ handleCellMouseDownWithCommit(rowIndex, colIndex);
2114
+ scrollCellIntoView(rowIndex, colIndex, { align: "center" });
2115
+ },
2116
+ [handleCellMouseDownWithCommit, scrollCellIntoView]
2117
+ );
2118
+ const resolveSearchRowId = useCallback4(
2119
+ (row, index) => {
2120
+ if (getRowId) return getRowId(row, index);
2121
+ if (enableExpand) {
2122
+ const record = row;
2123
+ const idValue = record.id;
2124
+ if (idValue != null && String(idValue).length > 0) {
2125
+ return String(idValue);
2126
+ }
2127
+ const uniqueId = record.uniqueId;
2128
+ if (uniqueId != null && String(uniqueId).length > 0) {
2129
+ return String(uniqueId);
2130
+ }
2131
+ if (toggleField) {
2132
+ const toggleValue = record[toggleField];
2133
+ if (toggleValue != null && String(toggleValue).length > 0) {
2134
+ return String(toggleValue);
2135
+ }
2136
+ }
2137
+ }
2138
+ return String(index);
2139
+ },
2140
+ [enableExpand, getRowId, toggleField]
2141
+ );
2142
+ const searchCorpus = useMemo3(() => {
2143
+ if (!enableInlineSearch) return [];
2144
+ if (enableExpand && toggleField) {
2145
+ return buildTreeSearchCorpus(tableData, {
2146
+ toggleField,
2147
+ getRowId: resolveSearchRowId
2148
+ });
2149
+ }
2150
+ return buildFlatSearchCorpus(tableData, resolveSearchRowId);
2151
+ }, [
2152
+ enableExpand,
2153
+ enableInlineSearch,
2154
+ resolveSearchRowId,
2155
+ tableData,
2156
+ toggleField
2157
+ ]);
2158
+ const searchCorpusRef = useRef5(searchCorpus);
2159
+ searchCorpusRef.current = searchCorpus;
2160
+ const visibleRowIndexById = useMemo3(() => {
2161
+ const map = /* @__PURE__ */ new Map();
2162
+ for (const row of rows) {
2163
+ map.set(resolveSearchRowId(row.original, row.index), row.index);
2164
+ }
2165
+ return map;
2166
+ }, [resolveSearchRowId, rows]);
2167
+ const getSearchCellValue = useCallback4(
2168
+ (rowIndex, colIndex) => {
2169
+ const corpusRow = searchCorpusRef.current[rowIndex];
2170
+ const column = visibleLeafColumns[colIndex];
2171
+ if (!corpusRow || !column) return void 0;
2172
+ const visibleIndex = visibleRowIndexById.get(corpusRow.id);
2173
+ if (visibleIndex !== void 0) {
2174
+ const visibleRow = rows[visibleIndex];
2175
+ if (visibleRow) {
2176
+ return visibleRow.getValue(column.id);
2177
+ }
2178
+ }
2179
+ const columnDef = column.columnDef;
2180
+ if ("accessorFn" in columnDef && typeof columnDef.accessorFn === "function") {
2181
+ return columnDef.accessorFn(corpusRow.data, rowIndex);
2182
+ }
2183
+ if ("accessorKey" in columnDef && columnDef.accessorKey != null && columnDef.accessorKey !== "") {
2184
+ return corpusRow.data[String(columnDef.accessorKey)];
2185
+ }
2186
+ return corpusRow.data[column.id];
2187
+ },
2188
+ [rows, visibleLeafColumns, visibleRowIndexById]
2189
+ );
2190
+ const pendingSearchNavRef = useRef5(null);
2191
+ const focusSearchResult = useCallback4(
2192
+ (colIndex, visibleRowIndex) => {
2193
+ navigateToSearchResult([colIndex, visibleRowIndex]);
2194
+ },
2195
+ [navigateToSearchResult]
2196
+ );
2197
+ const navigateToCorpusSearchResult = useCallback4(
2198
+ (item) => {
2199
+ const [colIndex, corpusRowIndex] = item;
2200
+ const corpusRow = searchCorpusRef.current[corpusRowIndex];
2201
+ if (!corpusRow) return;
2202
+ const missingKeys = collectAncestorKeysToExpand(corpusRow, expandedRows);
2203
+ if (missingKeys.length > 0) {
2204
+ pendingSearchNavRef.current = {
2205
+ colIndex,
2206
+ rowId: corpusRow.id
2207
+ };
2208
+ const next = new Set(expandedRows);
2209
+ for (const key of corpusRow.ancestorToggleKeys) {
2210
+ next.add(key);
2211
+ }
2212
+ handleExpandedRowsChange(next);
2213
+ return;
2214
+ }
2215
+ const visibleItem = mapSearchResultToVisibleItem(
2216
+ item,
2217
+ searchCorpusRef.current,
2218
+ visibleRowIndexById
2219
+ );
2220
+ if (!visibleItem) return;
2221
+ focusSearchResult(visibleItem[0], visibleItem[1]);
2222
+ },
2223
+ [
2224
+ expandedRows,
2225
+ focusSearchResult,
2226
+ handleExpandedRowsChange,
2227
+ visibleRowIndexById
2228
+ ]
2229
+ );
2230
+ useEffect5(() => {
2231
+ const pending = pendingSearchNavRef.current;
2232
+ if (!pending) return;
2233
+ const visibleRowIndex = visibleRowIndexById.get(pending.rowId);
2234
+ if (visibleRowIndex === void 0) return;
2235
+ pendingSearchNavRef.current = null;
2236
+ focusSearchResult(pending.colIndex, visibleRowIndex);
2237
+ }, [focusSearchResult, rows, visibleRowIndexById]);
2238
+ const initialSearchStartRow = virtualRows[0]?.index ?? 0;
2239
+ const inlineSearch = useInlineSearch({
2240
+ enabled: enableInlineSearch,
2241
+ rowCount: searchCorpus.length,
2242
+ columnCount: visibleLeafColumns.length,
2243
+ getCellValue: getSearchCellValue,
2244
+ initialStartRow: initialSearchStartRow,
2245
+ showSearch,
2246
+ searchValue,
2247
+ searchResults,
2248
+ onSearchValueChange,
2249
+ onSearchClose,
2250
+ onSearchResultsChanged,
2251
+ onNavigateToResult: navigateToCorpusSearchResult,
2252
+ rootRef
2253
+ });
2254
+ const visibleSearchMatchKeys = useMemo3(() => {
2255
+ if (!enableInlineSearch) return EMPTY_SEARCH_MATCH_KEYS;
2256
+ return mapSearchResultsToVisibleKeys(
2257
+ inlineSearch.searchResults,
2258
+ searchCorpus,
2259
+ visibleRowIndexById
2260
+ );
2261
+ }, [
2262
+ enableInlineSearch,
2263
+ inlineSearch.searchResults,
2264
+ searchCorpus,
2265
+ visibleRowIndexById
2266
+ ]);
2267
+ const visibleActiveMatch = useMemo3(() => {
2268
+ if (!enableInlineSearch || !inlineSearch.activeMatch) return null;
2269
+ return mapSearchResultToVisibleItem(
2270
+ inlineSearch.activeMatch,
2271
+ searchCorpus,
2272
+ visibleRowIndexById
2273
+ );
2274
+ }, [
2275
+ enableInlineSearch,
2276
+ inlineSearch.activeMatch,
2277
+ searchCorpus,
2278
+ visibleRowIndexById
2279
+ ]);
2280
+ const clearHover = useCallback4(() => {
1506
2281
  setHoveredRowIndex(null);
1507
2282
  }, []);
1508
- const handleRowHover = useCallback3((rowIndex, _rowData) => {
2283
+ const handleRowHover = useCallback4((rowIndex, _rowData) => {
1509
2284
  setHoveredRowIndex(rowIndex);
1510
2285
  }, []);
1511
- const handleToggleSelect = useCallback3(
2286
+ const handleToggleSelect = useCallback4(
1512
2287
  (row) => {
1513
2288
  if (!row.getCanSelect()) return;
1514
2289
  if (preserveRowSelection && row.getIsSelected()) {
@@ -1518,14 +2293,14 @@ function useGlideTable(options) {
1518
2293
  },
1519
2294
  [preserveRowSelection]
1520
2295
  );
1521
- const handleToggleExpand = useCallback3(
2296
+ const handleToggleExpand = useCallback4(
1522
2297
  (rowKey) => {
1523
2298
  if (preventExpand) return;
1524
2299
  handleExpandedRowsChange(toggleExpandedRowId(rowKey, expandedRows));
1525
2300
  },
1526
2301
  [preventExpand, handleExpandedRowsChange, expandedRows]
1527
2302
  );
1528
- const rowContextValue = useMemo2(() => {
2303
+ const rowContextValue = useMemo3(() => {
1529
2304
  return {
1530
2305
  rowSpan: {
1531
2306
  enableRowSpan,
@@ -1573,6 +2348,11 @@ function useGlideTable(options) {
1573
2348
  columnFreeze: {
1574
2349
  enableColumnFreeze,
1575
2350
  offsets: columnFreezeOffsets
2351
+ },
2352
+ inlineSearch: {
2353
+ enabled: enableInlineSearch,
2354
+ matchKeys: visibleSearchMatchKeys,
2355
+ activeMatch: visibleActiveMatch
1576
2356
  }
1577
2357
  };
1578
2358
  }, [
@@ -1608,14 +2388,17 @@ function useGlideTable(options) {
1608
2388
  labels.collapseRow,
1609
2389
  enableColumnResize,
1610
2390
  enableColumnFreeze,
1611
- columnFreezeOffsets
2391
+ columnFreezeOffsets,
2392
+ enableInlineSearch,
2393
+ visibleSearchMatchKeys,
2394
+ visibleActiveMatch
1612
2395
  ]);
1613
- const copySelectionRef = useRef4(copySelection);
1614
- useEffect4(() => {
2396
+ const copySelectionRef = useRef5(copySelection);
2397
+ useEffect5(() => {
1615
2398
  copySelectionRef.current = copySelection;
1616
2399
  }, [copySelection]);
1617
- const stableCopySelection = useCallback3((options2) => copySelectionRef.current(options2), []);
1618
- useEffect4(() => {
2400
+ const stableCopySelection = useCallback4((options2) => copySelectionRef.current(options2), []);
2401
+ useEffect5(() => {
1619
2402
  onCopyActionsReady?.({ copySelection: stableCopySelection });
1620
2403
  }, [onCopyActionsReady, stableCopySelection]);
1621
2404
  return {
@@ -1631,8 +2414,10 @@ function useGlideTable(options) {
1631
2414
  enableCellSelection,
1632
2415
  enableColumnResize,
1633
2416
  enableColumnFreeze,
2417
+ enableInlineSearch,
1634
2418
  shouldVirtualize,
1635
2419
  scrollRef,
2420
+ rootRef,
1636
2421
  rowVirtualizer,
1637
2422
  virtualRows,
1638
2423
  paddingTop,
@@ -1640,7 +2425,21 @@ function useGlideTable(options) {
1640
2425
  rowContextValue,
1641
2426
  handleToggleSelect,
1642
2427
  clearHover,
1643
- copySelection: stableCopySelection
2428
+ copySelection: stableCopySelection,
2429
+ inlineSearch: {
2430
+ showSearch: inlineSearch.showSearch,
2431
+ searchValue: inlineSearch.searchValue,
2432
+ searchStatus: inlineSearch.searchStatus,
2433
+ searchInputRef: inlineSearch.searchInputRef,
2434
+ searchInputId: inlineSearch.searchInputId,
2435
+ canClose: inlineSearch.canClose,
2436
+ searchRowCount: searchCorpus.length,
2437
+ setSearchValue: inlineSearch.setSearchValue,
2438
+ closeSearch: inlineSearch.closeSearch,
2439
+ goToNext: inlineSearch.goToNext,
2440
+ goToPrevious: inlineSearch.goToPrevious,
2441
+ openSearch: inlineSearch.openSearch
2442
+ }
1644
2443
  };
1645
2444
  }
1646
2445
 
@@ -1659,11 +2458,11 @@ function getColumnSizeStyle(size, options) {
1659
2458
 
1660
2459
  // src/components/ui/table/components/DataTable/DataTable.tsx
1661
2460
  import { flexRender as flexRender2 } from "@tanstack/react-table";
1662
- import { useMemo as useMemo3 } from "react";
2461
+ import { useMemo as useMemo4 } from "react";
1663
2462
 
1664
2463
  // src/components/ui/table/components/DataTable/DataTableRow.tsx
1665
2464
  import { flexRender } from "@tanstack/react-table";
1666
- import { useEffect as useEffect5, useRef as useRef5 } from "react";
2465
+ import { useEffect as useEffect6, useRef as useRef6 } from "react";
1667
2466
 
1668
2467
  // src/components/ui/table/DataTableContext.tsx
1669
2468
  import { createContext, use } from "react";
@@ -1871,10 +2670,16 @@ function DataTableRow({
1871
2670
  cellEdit,
1872
2671
  expand,
1873
2672
  columnResize,
1874
- columnFreeze
2673
+ columnFreeze,
2674
+ inlineSearch
1875
2675
  } = useDataTableRowContext();
1876
2676
  const { enableColumnResize } = columnResize;
1877
2677
  const { enableColumnFreeze, offsets: freezeOffsets } = columnFreeze;
2678
+ const {
2679
+ enabled: enableInlineSearch,
2680
+ matchKeys: searchMatchKeys,
2681
+ activeMatch
2682
+ } = inlineSearch;
1878
2683
  const {
1879
2684
  enableRowSpan,
1880
2685
  primaryRowSpanColumnId,
@@ -1968,9 +2773,9 @@ function DataTableRow({
1968
2773
  const expandKey = toggleField && rowData[toggleField] !== null && rowData[toggleField] !== void 0 ? String(rowData[toggleField]) : null;
1969
2774
  const isExpanded = expandKey !== null && Boolean(expandedRows?.has(expandKey));
1970
2775
  const rowLevel = typeof rowData.level === "number" ? rowData.level : 0;
1971
- const editInputRef = useRef5(null);
2776
+ const editInputRef = useRef6(null);
1972
2777
  const isRowEditing = editingCell?.rowIndex === rowIndex;
1973
- useEffect5(() => {
2778
+ useEffect6(() => {
1974
2779
  if (!isRowEditing) return;
1975
2780
  editInputRef.current?.focus();
1976
2781
  editInputRef.current?.select();
@@ -2066,9 +2871,14 @@ function DataTableRow({
2066
2871
  ...freezeStyle,
2067
2872
  ...selectionEdgeStyle
2068
2873
  };
2874
+ const searchMatchKey = buildSearchMatchKey(cellIndex, rowIndex);
2875
+ const isSearchMatch = enableInlineSearch && searchMatchKeys.has(searchMatchKey);
2876
+ const isSearchActive = isSearchMatch && activeMatch !== null && activeMatch[0] === cellIndex && activeMatch[1] === rowIndex;
2069
2877
  return /* @__PURE__ */ jsxs2(
2070
2878
  "td",
2071
2879
  {
2880
+ "data-row-index": rowIndex,
2881
+ "data-col-index": cellIndex,
2072
2882
  rowSpan: rowSpanInfo && rowSpanInfo.rowSpan > 1 ? rowSpanInfo.rowSpan : void 0,
2073
2883
  "data-merged": isMerged && cellIndex > 0 ? "" : void 0,
2074
2884
  "data-merged-edge-right": showMergedRightEdge ? "" : void 0,
@@ -2078,6 +2888,8 @@ function DataTableRow({
2078
2888
  "data-group-hovered": enableRowSpan && showCellHover && !showCellSelected ? "" : void 0,
2079
2889
  "data-selection-fill": isCellDragSelected ? "" : void 0,
2080
2890
  "data-selection-edges": hasSelectionEdges ? "" : void 0,
2891
+ "data-search-match": isSearchMatch ? "" : void 0,
2892
+ "data-search-active": isSearchActive ? "" : void 0,
2081
2893
  "data-editable": editable ? "" : void 0,
2082
2894
  "data-editing": isEditing ? "" : void 0,
2083
2895
  "data-frozen": freezeOffset?.side,
@@ -2092,7 +2904,8 @@ function DataTableRow({
2092
2904
  event.preventDefault();
2093
2905
  onCellMouseDown(
2094
2906
  resolveCellRowIndex(event.clientY, event.currentTarget),
2095
- cellIndex
2907
+ cellIndex,
2908
+ { shiftKey: event.shiftKey }
2096
2909
  );
2097
2910
  },
2098
2911
  onMouseEnter: (event) => {
@@ -2129,6 +2942,8 @@ function DataTableRow({
2129
2942
  enableRowSpan && showCellHover && !showCellSelected && "is-group-hovered",
2130
2943
  isCellDragSelected && CELL_SELECTION_FILL_CLASS,
2131
2944
  hasSelectionEdges && CELL_SELECTION_EDGES_CLASS,
2945
+ isSearchMatch && "is-search-match",
2946
+ isSearchActive && "is-search-active",
2132
2947
  editable && "is-editable",
2133
2948
  classNames?.cell
2134
2949
  ),
@@ -2263,8 +3078,169 @@ function DataTableRow({
2263
3078
  );
2264
3079
  }
2265
3080
 
3081
+ // src/components/ui/table/components/DataTable/DataTableSearch.tsx
3082
+ import { jsx as jsx4, jsxs as jsxs3 } from "react/jsx-runtime";
3083
+ function SearchCloseIcon({ className }) {
3084
+ return /* @__PURE__ */ jsxs3(
3085
+ "svg",
3086
+ {
3087
+ className,
3088
+ "aria-hidden": true,
3089
+ width: "16",
3090
+ height: "16",
3091
+ viewBox: "0 0 24 24",
3092
+ fill: "none",
3093
+ stroke: "currentColor",
3094
+ strokeWidth: "2",
3095
+ strokeLinecap: "round",
3096
+ strokeLinejoin: "round",
3097
+ children: [
3098
+ /* @__PURE__ */ jsx4("path", { d: "M18 6 6 18" }),
3099
+ /* @__PURE__ */ jsx4("path", { d: "m6 6 12 12" })
3100
+ ]
3101
+ }
3102
+ );
3103
+ }
3104
+ function DataTableSearch({
3105
+ showSearch,
3106
+ searchValue,
3107
+ searchStatus,
3108
+ searchInputId,
3109
+ searchInputRef,
3110
+ canClose,
3111
+ placeholder,
3112
+ resultHint,
3113
+ previousLabel,
3114
+ nextLabel,
3115
+ closeLabel,
3116
+ rowsTotal,
3117
+ classNames,
3118
+ onSearchValueChange,
3119
+ onClose,
3120
+ onNext,
3121
+ onPrevious
3122
+ }) {
3123
+ if (!showSearch) return null;
3124
+ const resultString = searchStatus ? formatSearchResultLabel(searchStatus) : resultHint;
3125
+ const progress = rowsTotal > 0 ? Math.floor((searchStatus?.rowsSearched ?? 0) / rowsTotal * 100) : 0;
3126
+ const handleKeyDown = (event) => {
3127
+ if ((event.ctrlKey || event.metaKey) && event.code === "KeyF" || event.key === "Escape") {
3128
+ event.preventDefault();
3129
+ event.stopPropagation();
3130
+ if (canClose) {
3131
+ onClose();
3132
+ }
3133
+ return;
3134
+ }
3135
+ if (event.key === "ArrowDown" || event.key === "Enter" && !event.shiftKey) {
3136
+ event.preventDefault();
3137
+ onNext();
3138
+ return;
3139
+ }
3140
+ if (event.key === "ArrowUp" || event.key === "Enter" && event.shiftKey) {
3141
+ event.preventDefault();
3142
+ onPrevious();
3143
+ }
3144
+ };
3145
+ return /* @__PURE__ */ jsxs3(
3146
+ "div",
3147
+ {
3148
+ className: cn("data-table-search", classNames?.search),
3149
+ role: "search",
3150
+ onMouseDown: (event) => event.stopPropagation(),
3151
+ children: [
3152
+ /* @__PURE__ */ jsxs3("div", { className: "data-table-search-row", children: [
3153
+ /* @__PURE__ */ jsx4(
3154
+ "input",
3155
+ {
3156
+ ref: searchInputRef,
3157
+ id: searchInputId,
3158
+ type: "search",
3159
+ value: searchValue,
3160
+ placeholder,
3161
+ autoComplete: "off",
3162
+ spellCheck: false,
3163
+ "aria-label": placeholder,
3164
+ className: cn("data-table-search-input", classNames?.searchInput),
3165
+ onChange: (event) => onSearchValueChange(event.target.value),
3166
+ onKeyDown: handleKeyDown
3167
+ }
3168
+ ),
3169
+ /* @__PURE__ */ jsx4(
3170
+ "button",
3171
+ {
3172
+ type: "button",
3173
+ "aria-label": previousLabel,
3174
+ className: cn("data-table-search-button", classNames?.searchButton),
3175
+ onClick: (event) => {
3176
+ event.stopPropagation();
3177
+ onPrevious();
3178
+ },
3179
+ children: /* @__PURE__ */ jsx4(ChevronUp, { className: "data-table-search-icon" })
3180
+ }
3181
+ ),
3182
+ /* @__PURE__ */ jsx4(
3183
+ "button",
3184
+ {
3185
+ type: "button",
3186
+ "aria-label": nextLabel,
3187
+ className: cn("data-table-search-button", classNames?.searchButton),
3188
+ onClick: (event) => {
3189
+ event.stopPropagation();
3190
+ onNext();
3191
+ },
3192
+ children: /* @__PURE__ */ jsx4(ChevronDown, { className: "data-table-search-icon" })
3193
+ }
3194
+ ),
3195
+ canClose ? /* @__PURE__ */ jsx4(
3196
+ "button",
3197
+ {
3198
+ type: "button",
3199
+ "aria-label": closeLabel,
3200
+ className: cn("data-table-search-button", classNames?.searchButton),
3201
+ onClick: (event) => {
3202
+ event.stopPropagation();
3203
+ onClose();
3204
+ },
3205
+ children: /* @__PURE__ */ jsx4(SearchCloseIcon, { className: "data-table-search-icon" })
3206
+ }
3207
+ ) : null
3208
+ ] }),
3209
+ /* @__PURE__ */ jsx4(
3210
+ "div",
3211
+ {
3212
+ className: cn("data-table-search-status", classNames?.searchStatus),
3213
+ "aria-live": "polite",
3214
+ children: resultString
3215
+ }
3216
+ ),
3217
+ searchStatus !== void 0 ? /* @__PURE__ */ jsx4(
3218
+ "div",
3219
+ {
3220
+ className: cn(
3221
+ "data-table-search-progress",
3222
+ classNames?.searchProgress
3223
+ ),
3224
+ role: "progressbar",
3225
+ "aria-valuemin": 0,
3226
+ "aria-valuemax": 100,
3227
+ "aria-valuenow": progress,
3228
+ children: /* @__PURE__ */ jsx4(
3229
+ "div",
3230
+ {
3231
+ className: "data-table-search-progress-bar",
3232
+ style: { width: `${progress}%` }
3233
+ }
3234
+ )
3235
+ }
3236
+ ) : null
3237
+ ]
3238
+ }
3239
+ );
3240
+ }
3241
+
2266
3242
  // src/components/ui/table/components/DataTable/DataTableToolbar.tsx
2267
- import { Fragment, jsx as jsx4, jsxs as jsxs3 } from "react/jsx-runtime";
3243
+ import { Fragment, jsx as jsx5, jsxs as jsxs4 } from "react/jsx-runtime";
2268
3244
  function DataTableToolbar({
2269
3245
  filteredCount,
2270
3246
  totalCount,
@@ -2282,39 +3258,39 @@ function DataTableToolbar({
2282
3258
  const selectionContent = selectionLabel?.(selectedCount) ?? null;
2283
3259
  const hasSelectionContent = selectionContent !== null && selectionContent !== false && selectionContent !== void 0 && typeof selectionContent !== "boolean";
2284
3260
  if (!hasLeftContent && !hasToolbar && !hasSelectionContent) return null;
2285
- return /* @__PURE__ */ jsxs3("div", { className: cn("DataTableToolbarJSX", classNames?.toolbar, className), children: [
2286
- /* @__PURE__ */ jsxs3("div", { className: cn("toolbar-left", classNames?.toolbarLeft), children: [
2287
- hasCount && /* @__PURE__ */ jsx4("span", { className: cn("toolbar-count", classNames?.toolbarCount), children: displayFiltered !== void 0 && totalCount !== void 0 ? /* @__PURE__ */ jsxs3(Fragment, { children: [
2288
- /* @__PURE__ */ jsx4("span", { className: "toolbar-count-primary", children: displayFiltered }),
2289
- /* @__PURE__ */ jsxs3("span", { className: "toolbar-count-placeholder", children: [
3261
+ return /* @__PURE__ */ jsxs4("div", { className: cn("DataTableToolbarJSX", classNames?.toolbar, className), children: [
3262
+ /* @__PURE__ */ jsxs4("div", { className: cn("toolbar-left", classNames?.toolbarLeft), children: [
3263
+ hasCount && /* @__PURE__ */ jsx5("span", { className: cn("toolbar-count", classNames?.toolbarCount), children: displayFiltered !== void 0 && totalCount !== void 0 ? /* @__PURE__ */ jsxs4(Fragment, { children: [
3264
+ /* @__PURE__ */ jsx5("span", { className: "toolbar-count-primary", children: displayFiltered }),
3265
+ /* @__PURE__ */ jsxs4("span", { className: "toolbar-count-placeholder", children: [
2290
3266
  " / ",
2291
3267
  totalCount
2292
3268
  ] })
2293
- ] }) : /* @__PURE__ */ jsx4("span", { className: "toolbar-count-primary", children: displayFiltered ?? totalCount }) }),
3269
+ ] }) : /* @__PURE__ */ jsx5("span", { className: "toolbar-count-primary", children: displayFiltered ?? totalCount }) }),
2294
3270
  summary
2295
3271
  ] }),
2296
- /* @__PURE__ */ jsxs3("div", { className: cn("toolbar-right", classNames?.toolbarRight), children: [
2297
- hasSelectionContent && (typeof selectionContent === "string" || typeof selectionContent === "number" ? /* @__PURE__ */ jsx4("span", { className: cn("toolbar-selection", classNames?.toolbarSelection), children: selectionContent }) : selectionContent),
2298
- hasToolbar && /* @__PURE__ */ jsx4("div", { className: cn("toolbar-actions", classNames?.toolbarActions), children: toolbar })
3272
+ /* @__PURE__ */ jsxs4("div", { className: cn("toolbar-right", classNames?.toolbarRight), children: [
3273
+ hasSelectionContent && (typeof selectionContent === "string" || typeof selectionContent === "number" ? /* @__PURE__ */ jsx5("span", { className: cn("toolbar-selection", classNames?.toolbarSelection), children: selectionContent }) : selectionContent),
3274
+ hasToolbar && /* @__PURE__ */ jsx5("div", { className: cn("toolbar-actions", classNames?.toolbarActions), children: toolbar })
2299
3275
  ] })
2300
3276
  ] });
2301
3277
  }
2302
3278
 
2303
3279
  // src/components/ui/table/components/DataTable/DataTable.tsx
2304
- import { Fragment as Fragment2, jsx as jsx5, jsxs as jsxs4 } from "react/jsx-runtime";
3280
+ import { Fragment as Fragment2, jsx as jsx6, jsxs as jsxs5 } from "react/jsx-runtime";
2305
3281
  function DefaultScroll({
2306
3282
  scrollRef,
2307
3283
  children,
2308
3284
  className
2309
3285
  }) {
2310
- return /* @__PURE__ */ jsx5("div", { ref: scrollRef, className: cn("data-table-scroll", className), children });
3286
+ return /* @__PURE__ */ jsx6("div", { ref: scrollRef, className: cn("data-table-scroll", className), children });
2311
3287
  }
2312
3288
  function DefaultPending({
2313
3289
  loadingText,
2314
3290
  className,
2315
3291
  classNames
2316
3292
  }) {
2317
- return /* @__PURE__ */ jsx5(
3293
+ return /* @__PURE__ */ jsx6(
2318
3294
  "div",
2319
3295
  {
2320
3296
  className: cn(
@@ -2324,7 +3300,7 @@ function DefaultPending({
2324
3300
  classNames?.pending,
2325
3301
  className
2326
3302
  ),
2327
- children: /* @__PURE__ */ jsx5("span", { className: cn("data-table-loading-text", classNames?.loadingText), children: loadingText })
3303
+ children: /* @__PURE__ */ jsx6("span", { className: cn("data-table-loading-text", classNames?.loadingText), children: loadingText })
2328
3304
  }
2329
3305
  );
2330
3306
  }
@@ -2333,7 +3309,7 @@ function DefaultEmpty({
2333
3309
  columnCount,
2334
3310
  classNames
2335
3311
  }) {
2336
- return /* @__PURE__ */ jsx5("tr", { children: /* @__PURE__ */ jsx5(
3312
+ return /* @__PURE__ */ jsx6("tr", { children: /* @__PURE__ */ jsx6(
2337
3313
  "td",
2338
3314
  {
2339
3315
  colSpan: columnCount,
@@ -2366,15 +3342,18 @@ function DataTable({
2366
3342
  enableCellSelection,
2367
3343
  enableColumnResize,
2368
3344
  enableColumnFreeze,
3345
+ enableInlineSearch,
2369
3346
  shouldVirtualize,
2370
3347
  scrollRef,
3348
+ rootRef,
2371
3349
  rowVirtualizer,
2372
3350
  virtualRows,
2373
3351
  paddingTop,
2374
3352
  paddingBottom,
2375
3353
  rowContextValue,
2376
3354
  handleToggleSelect,
2377
- clearHover
3355
+ clearHover,
3356
+ inlineSearch
2378
3357
  } = useGlideTable(glideOptions);
2379
3358
  const ToolbarSlot = slots?.Toolbar ?? DataTableToolbar;
2380
3359
  const ScrollSlot = slots?.Scroll ?? DefaultScroll;
@@ -2382,12 +3361,12 @@ function DataTable({
2382
3361
  const PendingSlot = slots?.Pending ?? DefaultPending;
2383
3362
  const EmptySlot = slots?.Empty ?? DefaultEmpty;
2384
3363
  const freezeOffsets = rowContextValue.columnFreeze.offsets;
2385
- const contextValue = useMemo3(
3364
+ const contextValue = useMemo4(
2386
3365
  () => ({ ...rowContextValue, classNames }),
2387
3366
  [rowContextValue, classNames]
2388
3367
  );
2389
3368
  if (isPending) {
2390
- return /* @__PURE__ */ jsx5(
3369
+ return /* @__PURE__ */ jsx6(
2391
3370
  PendingSlot,
2392
3371
  {
2393
3372
  loadingText,
@@ -2396,19 +3375,21 @@ function DataTable({
2396
3375
  }
2397
3376
  );
2398
3377
  }
2399
- return /* @__PURE__ */ jsxs4(
3378
+ return /* @__PURE__ */ jsxs5(
2400
3379
  "div",
2401
3380
  {
3381
+ ref: rootRef,
2402
3382
  className: cn(
2403
3383
  "DataTableJSX",
2404
3384
  !enableCellSelection && "DataTableJSX--no-cell-selection",
2405
3385
  enableColumnResize && "DataTableJSX--column-resize",
2406
3386
  enableColumnFreeze && "DataTableJSX--column-freeze",
3387
+ enableInlineSearch && "DataTableJSX--inline-search",
2407
3388
  classNames?.root,
2408
3389
  className
2409
3390
  ),
2410
3391
  children: [
2411
- /* @__PURE__ */ jsx5(
3392
+ /* @__PURE__ */ jsx6(
2412
3393
  ToolbarSlot,
2413
3394
  {
2414
3395
  filteredCount: filteredCount ?? tableData.length,
@@ -2420,14 +3401,36 @@ function DataTable({
2420
3401
  classNames
2421
3402
  }
2422
3403
  ),
2423
- /* @__PURE__ */ jsx5(ScrollSlot, { scrollRef, className: classNames?.scroll, children: /* @__PURE__ */ jsxs4(
3404
+ enableInlineSearch ? /* @__PURE__ */ jsx6(
3405
+ DataTableSearch,
3406
+ {
3407
+ showSearch: inlineSearch.showSearch,
3408
+ searchValue: inlineSearch.searchValue,
3409
+ searchStatus: inlineSearch.searchStatus,
3410
+ searchInputId: inlineSearch.searchInputId,
3411
+ searchInputRef: inlineSearch.searchInputRef,
3412
+ canClose: inlineSearch.canClose,
3413
+ placeholder: labels.searchPlaceholder,
3414
+ resultHint: labels.searchResultHint,
3415
+ previousLabel: labels.searchPrevious,
3416
+ nextLabel: labels.searchNext,
3417
+ closeLabel: labels.searchClose,
3418
+ rowsTotal: inlineSearch.searchRowCount,
3419
+ classNames,
3420
+ onSearchValueChange: inlineSearch.setSearchValue,
3421
+ onClose: inlineSearch.closeSearch,
3422
+ onNext: inlineSearch.goToNext,
3423
+ onPrevious: inlineSearch.goToPrevious
3424
+ }
3425
+ ) : null,
3426
+ /* @__PURE__ */ jsx6(ScrollSlot, { scrollRef, className: classNames?.scroll, children: /* @__PURE__ */ jsxs5(
2424
3427
  "table",
2425
3428
  {
2426
3429
  className: cn("data-table", classNames?.table),
2427
3430
  style: enableColumnResize ? { width: table.getTotalSize() } : void 0,
2428
3431
  onDragStart: enableCellSelection ? (event) => event.preventDefault() : void 0,
2429
3432
  children: [
2430
- /* @__PURE__ */ jsx5("thead", { className: cn("data-table-head", classNames?.head), children: table.getHeaderGroups().map((headerGroup) => /* @__PURE__ */ jsx5(
3433
+ /* @__PURE__ */ jsx6("thead", { className: cn("data-table-head", classNames?.head), children: table.getHeaderGroups().map((headerGroup) => /* @__PURE__ */ jsx6(
2431
3434
  "tr",
2432
3435
  {
2433
3436
  className: cn("data-table-head-row", classNames?.headRow),
@@ -2447,7 +3450,7 @@ function DataTable({
2447
3450
  ...sizeStyle,
2448
3451
  ...freezeStyle
2449
3452
  };
2450
- return /* @__PURE__ */ jsxs4(
3453
+ return /* @__PURE__ */ jsxs5(
2451
3454
  "th",
2452
3455
  {
2453
3456
  "data-resizing": header.column.getIsResizing() ? "" : void 0,
@@ -2463,7 +3466,7 @@ function DataTable({
2463
3466
  ),
2464
3467
  children: [
2465
3468
  header.isPlaceholder ? null : flexRender2(header.column.columnDef.header, header.getContext()),
2466
- canResize ? /* @__PURE__ */ jsx5(
3469
+ canResize ? /* @__PURE__ */ jsx6(
2467
3470
  "div",
2468
3471
  {
2469
3472
  role: "separator",
@@ -2489,20 +3492,20 @@ function DataTable({
2489
3492
  },
2490
3493
  headerGroup.id
2491
3494
  )) }),
2492
- /* @__PURE__ */ jsx5(DataTableContextProvider, { value: contextValue, children: /* @__PURE__ */ jsx5(
3495
+ /* @__PURE__ */ jsx6(DataTableContextProvider, { value: contextValue, children: /* @__PURE__ */ jsx6(
2493
3496
  "tbody",
2494
3497
  {
2495
3498
  onMouseLeave: clearHover,
2496
3499
  className: cn("data-table-body", classNames?.body),
2497
- children: rows.length === 0 ? /* @__PURE__ */ jsx5(
3500
+ children: rows.length === 0 ? /* @__PURE__ */ jsx6(
2498
3501
  EmptySlot,
2499
3502
  {
2500
3503
  emptyText,
2501
3504
  columnCount,
2502
3505
  classNames
2503
3506
  }
2504
- ) : shouldVirtualize ? /* @__PURE__ */ jsxs4(Fragment2, { children: [
2505
- paddingTop > 0 && /* @__PURE__ */ jsx5(
3507
+ ) : shouldVirtualize ? /* @__PURE__ */ jsxs5(Fragment2, { children: [
3508
+ paddingTop > 0 && /* @__PURE__ */ jsx6(
2506
3509
  "tr",
2507
3510
  {
2508
3511
  "aria-hidden": true,
@@ -2510,7 +3513,7 @@ function DataTable({
2510
3513
  "data-table-virtual-spacer",
2511
3514
  classNames?.virtualSpacer
2512
3515
  ),
2513
- children: /* @__PURE__ */ jsx5(
3516
+ children: /* @__PURE__ */ jsx6(
2514
3517
  "td",
2515
3518
  {
2516
3519
  colSpan: columnCount,
@@ -2526,7 +3529,7 @@ function DataTable({
2526
3529
  virtualRows.map((virtualRow) => {
2527
3530
  const row = rows[virtualRow.index];
2528
3531
  if (!row) return null;
2529
- return /* @__PURE__ */ jsx5(
3532
+ return /* @__PURE__ */ jsx6(
2530
3533
  RowSlot,
2531
3534
  {
2532
3535
  row,
@@ -2537,7 +3540,7 @@ function DataTable({
2537
3540
  row.id
2538
3541
  );
2539
3542
  }),
2540
- paddingBottom > 0 && /* @__PURE__ */ jsx5(
3543
+ paddingBottom > 0 && /* @__PURE__ */ jsx6(
2541
3544
  "tr",
2542
3545
  {
2543
3546
  "aria-hidden": true,
@@ -2545,7 +3548,7 @@ function DataTable({
2545
3548
  "data-table-virtual-spacer",
2546
3549
  classNames?.virtualSpacer
2547
3550
  ),
2548
- children: /* @__PURE__ */ jsx5(
3551
+ children: /* @__PURE__ */ jsx6(
2549
3552
  "td",
2550
3553
  {
2551
3554
  colSpan: columnCount,
@@ -2558,7 +3561,7 @@ function DataTable({
2558
3561
  )
2559
3562
  }
2560
3563
  )
2561
- ] }) : rows.map((row) => /* @__PURE__ */ jsx5(
3564
+ ] }) : rows.map((row) => /* @__PURE__ */ jsx6(
2562
3565
  RowSlot,
2563
3566
  {
2564
3567
  row,
@@ -2577,10 +3580,10 @@ function DataTable({
2577
3580
  }
2578
3581
 
2579
3582
  // src/components/ui/table/components/Table/Table.tsx
2580
- import { useCallback as useCallback4, useMemo as useMemo4, useState as useState4 } from "react";
3583
+ import { useCallback as useCallback5, useMemo as useMemo5, useState as useState5 } from "react";
2581
3584
 
2582
3585
  // src/components/ui/table/components/Table/buildColumnDef.tsx
2583
- import { jsx as jsx6, jsxs as jsxs5 } from "react/jsx-runtime";
3586
+ import { jsx as jsx7, jsxs as jsxs6 } from "react/jsx-runtime";
2584
3587
  function SortableHeader({
2585
3588
  label,
2586
3589
  field,
@@ -2589,15 +3592,15 @@ function SortableHeader({
2589
3592
  }) {
2590
3593
  const isActive = sort?.field === field;
2591
3594
  const Icon = isActive ? sort.direction === "asc" ? ArrowUp : ArrowDown : ArrowUpDown;
2592
- return /* @__PURE__ */ jsxs5(
3595
+ return /* @__PURE__ */ jsxs6(
2593
3596
  "button",
2594
3597
  {
2595
3598
  type: "button",
2596
3599
  className: cn("SortableHeaderJSX", isActive ? "is-active" : "is-inactive"),
2597
3600
  onClick: () => onSort(field),
2598
3601
  children: [
2599
- /* @__PURE__ */ jsx6("span", { children: label }),
2600
- /* @__PURE__ */ jsx6(Icon, { className: "sortable-header-icon" })
3602
+ /* @__PURE__ */ jsx7("span", { children: label }),
3603
+ /* @__PURE__ */ jsx7(Icon, { className: "sortable-header-icon" })
2601
3604
  ]
2602
3605
  }
2603
3606
  );
@@ -2630,7 +3633,7 @@ function buildColumnDef(props, sort, onSort) {
2630
3633
  ...minWidth != null ? { minSize: minWidth } : {},
2631
3634
  ...maxWidth != null ? { maxSize: maxWidth } : {},
2632
3635
  ...resizable === false ? { enableResizing: false } : {},
2633
- header: sortable ? () => /* @__PURE__ */ jsx6(SortableHeader, { label: children, field, sort, onSort }) : (
3636
+ header: sortable ? () => /* @__PURE__ */ jsx7(SortableHeader, { label: children, field, sort, onSort }) : (
2634
3637
  // eslint-disable-next-line @typescript-eslint/promise-function-async
2635
3638
  () => children
2636
3639
  ),
@@ -2778,7 +3781,7 @@ function TableHeader(props) {
2778
3781
  TableHeader.displayName = TABLE_HEADER_DISPLAY_NAME;
2779
3782
 
2780
3783
  // src/components/ui/table/components/Table/TablePagination.tsx
2781
- import { jsx as jsx7, jsxs as jsxs6 } from "react/jsx-runtime";
3784
+ import { jsx as jsx8, jsxs as jsxs7 } from "react/jsx-runtime";
2782
3785
  function TablePagination({
2783
3786
  page,
2784
3787
  pageSize = 10,
@@ -2790,8 +3793,8 @@ function TablePagination({
2790
3793
  const safePage = Math.min(Math.max(1, page), totalPages);
2791
3794
  const canGoPrev = safePage > 1;
2792
3795
  const canGoNext = safePage < totalPages;
2793
- return /* @__PURE__ */ jsxs6("div", { className: cn("TablePaginationJSX", className), children: [
2794
- /* @__PURE__ */ jsx7(
3796
+ return /* @__PURE__ */ jsxs7("div", { className: cn("TablePaginationJSX", className), children: [
3797
+ /* @__PURE__ */ jsx8(
2795
3798
  "button",
2796
3799
  {
2797
3800
  type: "button",
@@ -2799,15 +3802,15 @@ function TablePagination({
2799
3802
  disabled: !canGoPrev,
2800
3803
  onClick: () => onChange(safePage - 1),
2801
3804
  "aria-label": "Previous page",
2802
- children: /* @__PURE__ */ jsx7(ChevronLeft, { className: "pagination-button-icon" })
3805
+ children: /* @__PURE__ */ jsx8(ChevronLeft, { className: "pagination-button-icon" })
2803
3806
  }
2804
3807
  ),
2805
- /* @__PURE__ */ jsxs6("span", { className: "pagination-label", children: [
3808
+ /* @__PURE__ */ jsxs7("span", { className: "pagination-label", children: [
2806
3809
  safePage,
2807
3810
  " / ",
2808
3811
  totalPages
2809
3812
  ] }),
2810
- /* @__PURE__ */ jsx7(
3813
+ /* @__PURE__ */ jsx8(
2811
3814
  "button",
2812
3815
  {
2813
3816
  type: "button",
@@ -2815,7 +3818,7 @@ function TablePagination({
2815
3818
  disabled: !canGoNext,
2816
3819
  onClick: () => onChange(safePage + 1),
2817
3820
  "aria-label": "Next page",
2818
- children: /* @__PURE__ */ jsx7(ChevronRight, { className: "pagination-button-icon" })
3821
+ children: /* @__PURE__ */ jsx8(ChevronRight, { className: "pagination-button-icon" })
2819
3822
  }
2820
3823
  )
2821
3824
  ] });
@@ -2823,7 +3826,7 @@ function TablePagination({
2823
3826
  TablePagination.displayName = TABLE_PAGINATION_DISPLAY_NAME;
2824
3827
 
2825
3828
  // src/components/ui/table/components/Table/Table.tsx
2826
- import { jsx as jsx8, jsxs as jsxs7 } from "react/jsx-runtime";
3829
+ import { jsx as jsx9, jsxs as jsxs8 } from "react/jsx-runtime";
2827
3830
  function TableRoot({
2828
3831
  data,
2829
3832
  children,
@@ -2832,12 +3835,12 @@ function TableRoot({
2832
3835
  filteredCount,
2833
3836
  ...dataTableProps
2834
3837
  }) {
2835
- const { header, pagination: paginationElement } = useMemo4(
3838
+ const { header, pagination: paginationElement } = useMemo5(
2836
3839
  () => parseTableChildren(children),
2837
3840
  [children]
2838
3841
  );
2839
- const [sort, setSort] = useState4(null);
2840
- const handleSort = useCallback4((field) => {
3842
+ const [sort, setSort] = useState5(null);
3843
+ const handleSort = useCallback5((field) => {
2841
3844
  setSort((previous) => {
2842
3845
  if (previous?.field !== field) {
2843
3846
  return { field, direction: "asc" };
@@ -2848,7 +3851,7 @@ function TableRoot({
2848
3851
  return null;
2849
3852
  });
2850
3853
  }, []);
2851
- const columns = useMemo4(() => {
3854
+ const columns = useMemo5(() => {
2852
3855
  return extractColumnElements(header).map(
2853
3856
  (columnElement) => buildColumnDef(columnElement.props, sort, handleSort)
2854
3857
  );
@@ -2857,7 +3860,7 @@ function TableRoot({
2857
3860
  const pageSize = paginationProps?.pageSize ?? 10;
2858
3861
  const page = paginationProps?.page ?? 1;
2859
3862
  const resolvedTotalCount = paginationProps?.totalCount ?? totalCount ?? data.length;
2860
- const tableData = useMemo4(() => {
3863
+ const tableData = useMemo5(() => {
2861
3864
  const sortedData = sortTableData(data, sort);
2862
3865
  if (!paginationProps) return sortedData;
2863
3866
  return paginateTableData(sortedData, page, pageSize);
@@ -2865,8 +3868,8 @@ function TableRoot({
2865
3868
  if (columns.length === 0) {
2866
3869
  console.warn("[Table] Declare at least one Table.Column inside Table.Header.");
2867
3870
  }
2868
- return /* @__PURE__ */ jsxs7("div", { className: "TableJSX", children: [
2869
- /* @__PURE__ */ jsx8(
3871
+ return /* @__PURE__ */ jsxs8("div", { className: "TableJSX", children: [
3872
+ /* @__PURE__ */ jsx9(
2870
3873
  DataTable,
2871
3874
  {
2872
3875
  ...dataTableProps,
@@ -2877,7 +3880,7 @@ function TableRoot({
2877
3880
  className: cn(className, paginationProps && "DataTableJSX--with-pagination")
2878
3881
  }
2879
3882
  ),
2880
- paginationProps && /* @__PURE__ */ jsx8(
3883
+ paginationProps && /* @__PURE__ */ jsx9(
2881
3884
  TablePagination,
2882
3885
  {
2883
3886
  page,
@@ -2897,7 +3900,7 @@ function createTable() {
2897
3900
  Column.displayName = TABLE_COLUMN_DISPLAY_NAME;
2898
3901
  return Object.assign(
2899
3902
  function BoundTable(props) {
2900
- return /* @__PURE__ */ jsx8(TableRoot, { ...props });
3903
+ return /* @__PURE__ */ jsx9(TableRoot, { ...props });
2901
3904
  },
2902
3905
  {
2903
3906
  Header: TableHeader,
@@ -2921,20 +3924,31 @@ export {
2921
3924
  DEFAULT_TREE_PARENT_ID_FIELD,
2922
3925
  DEFAULT_TREE_QTY_FIELD,
2923
3926
  DataTable,
3927
+ INLINE_SEARCH_MAX_RESULTS,
2924
3928
  Table,
2925
3929
  applyCellEdit,
2926
3930
  applyFillData,
2927
3931
  applySelectionUpdater,
2928
3932
  buildColumnFreezeOffsets,
2929
3933
  buildColumnRowSpanMap,
3934
+ buildFlatSearchCorpus,
2930
3935
  buildRowsPastePayload,
3936
+ buildSearchMatchKey,
3937
+ buildSearchMatchKeys,
3938
+ buildTreeSearchCorpus,
2931
3939
  canExpandRow,
3940
+ cellValueToSearchText,
3941
+ collectAncestorKeysToExpand,
2932
3942
  collectCopyRowEntries,
2933
3943
  collectCopyRows,
2934
3944
  collectFillChanges,
2935
3945
  collectRowSpanColumns,
3946
+ collectSearchMatchesInRange,
3947
+ createSearchRegex,
2936
3948
  createTable,
3949
+ escapeSearchRegex,
2937
3950
  flattenSubtreeRows,
3951
+ formatSearchResultLabel,
2938
3952
  getCellEditDraftValue,
2939
3953
  getCellSelectionEdgeStyle,
2940
3954
  getColumnEditType,
@@ -2946,10 +3960,15 @@ export {
2946
3960
  isCellInSelection,
2947
3961
  isColumnEditable,
2948
3962
  isEditablePasteTarget,
3963
+ mapSearchResultToVisibleItem,
3964
+ mapSearchResultsToVisibleKeys,
2949
3965
  measureMergedSpanRowHeights,
3966
+ nextSearchIndex,
3967
+ nextSearchStride,
2950
3968
  parseCellEditValue,
2951
3969
  parseClipboardTSV,
2952
3970
  parseClipboardTSVWithDepths,
3971
+ previousSearchIndex,
2953
3972
  resolveColumnFreezeSide,
2954
3973
  resolveDataTableLabels,
2955
3974
  resolvePasteColumnIds,
@@ -2963,5 +3982,6 @@ export {
2963
3982
  useCellSelection,
2964
3983
  useConvertTreeData,
2965
3984
  useGlideTable,
3985
+ useInlineSearch,
2966
3986
  writeSelectionToClipboard
2967
3987
  };