react-glide-table 1.4.0 → 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,17 +2871,25 @@ 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,
2075
2885
  "data-merged-row-first": isMerged && cellIndex === 0 && showMergedRightEdge ? "" : void 0,
2886
+ "data-selected": !enableRowSpan && showCellSelected ? "" : void 0,
2076
2887
  "data-group-selected": enableRowSpan && showCellSelected ? "" : void 0,
2077
2888
  "data-group-hovered": enableRowSpan && showCellHover && !showCellSelected ? "" : void 0,
2078
2889
  "data-selection-fill": isCellDragSelected ? "" : void 0,
2079
2890
  "data-selection-edges": hasSelectionEdges ? "" : void 0,
2891
+ "data-search-match": isSearchMatch ? "" : void 0,
2892
+ "data-search-active": isSearchActive ? "" : void 0,
2080
2893
  "data-editable": editable ? "" : void 0,
2081
2894
  "data-editing": isEditing ? "" : void 0,
2082
2895
  "data-frozen": freezeOffset?.side,
@@ -2091,7 +2904,8 @@ function DataTableRow({
2091
2904
  event.preventDefault();
2092
2905
  onCellMouseDown(
2093
2906
  resolveCellRowIndex(event.clientY, event.currentTarget),
2094
- cellIndex
2907
+ cellIndex,
2908
+ { shiftKey: event.shiftKey }
2095
2909
  );
2096
2910
  },
2097
2911
  onMouseEnter: (event) => {
@@ -2128,6 +2942,8 @@ function DataTableRow({
2128
2942
  enableRowSpan && showCellHover && !showCellSelected && "is-group-hovered",
2129
2943
  isCellDragSelected && CELL_SELECTION_FILL_CLASS,
2130
2944
  hasSelectionEdges && CELL_SELECTION_EDGES_CLASS,
2945
+ isSearchMatch && "is-search-match",
2946
+ isSearchActive && "is-search-active",
2131
2947
  editable && "is-editable",
2132
2948
  classNames?.cell
2133
2949
  ),
@@ -2262,8 +3078,169 @@ function DataTableRow({
2262
3078
  );
2263
3079
  }
2264
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
+
2265
3242
  // src/components/ui/table/components/DataTable/DataTableToolbar.tsx
2266
- 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";
2267
3244
  function DataTableToolbar({
2268
3245
  filteredCount,
2269
3246
  totalCount,
@@ -2281,39 +3258,39 @@ function DataTableToolbar({
2281
3258
  const selectionContent = selectionLabel?.(selectedCount) ?? null;
2282
3259
  const hasSelectionContent = selectionContent !== null && selectionContent !== false && selectionContent !== void 0 && typeof selectionContent !== "boolean";
2283
3260
  if (!hasLeftContent && !hasToolbar && !hasSelectionContent) return null;
2284
- return /* @__PURE__ */ jsxs3("div", { className: cn("DataTableToolbarJSX", classNames?.toolbar, className), children: [
2285
- /* @__PURE__ */ jsxs3("div", { className: cn("toolbar-left", classNames?.toolbarLeft), children: [
2286
- hasCount && /* @__PURE__ */ jsx4("span", { className: cn("toolbar-count", classNames?.toolbarCount), children: displayFiltered !== void 0 && totalCount !== void 0 ? /* @__PURE__ */ jsxs3(Fragment, { children: [
2287
- /* @__PURE__ */ jsx4("span", { className: "toolbar-count-primary", children: displayFiltered }),
2288
- /* @__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: [
2289
3266
  " / ",
2290
3267
  totalCount
2291
3268
  ] })
2292
- ] }) : /* @__PURE__ */ jsx4("span", { className: "toolbar-count-primary", children: displayFiltered ?? totalCount }) }),
3269
+ ] }) : /* @__PURE__ */ jsx5("span", { className: "toolbar-count-primary", children: displayFiltered ?? totalCount }) }),
2293
3270
  summary
2294
3271
  ] }),
2295
- /* @__PURE__ */ jsxs3("div", { className: cn("toolbar-right", classNames?.toolbarRight), children: [
2296
- hasSelectionContent && (typeof selectionContent === "string" || typeof selectionContent === "number" ? /* @__PURE__ */ jsx4("span", { className: cn("toolbar-selection", classNames?.toolbarSelection), children: selectionContent }) : selectionContent),
2297
- 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 })
2298
3275
  ] })
2299
3276
  ] });
2300
3277
  }
2301
3278
 
2302
3279
  // src/components/ui/table/components/DataTable/DataTable.tsx
2303
- 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";
2304
3281
  function DefaultScroll({
2305
3282
  scrollRef,
2306
3283
  children,
2307
3284
  className
2308
3285
  }) {
2309
- 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 });
2310
3287
  }
2311
3288
  function DefaultPending({
2312
3289
  loadingText,
2313
3290
  className,
2314
3291
  classNames
2315
3292
  }) {
2316
- return /* @__PURE__ */ jsx5(
3293
+ return /* @__PURE__ */ jsx6(
2317
3294
  "div",
2318
3295
  {
2319
3296
  className: cn(
@@ -2323,7 +3300,7 @@ function DefaultPending({
2323
3300
  classNames?.pending,
2324
3301
  className
2325
3302
  ),
2326
- 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 })
2327
3304
  }
2328
3305
  );
2329
3306
  }
@@ -2332,7 +3309,7 @@ function DefaultEmpty({
2332
3309
  columnCount,
2333
3310
  classNames
2334
3311
  }) {
2335
- return /* @__PURE__ */ jsx5("tr", { children: /* @__PURE__ */ jsx5(
3312
+ return /* @__PURE__ */ jsx6("tr", { children: /* @__PURE__ */ jsx6(
2336
3313
  "td",
2337
3314
  {
2338
3315
  colSpan: columnCount,
@@ -2365,15 +3342,18 @@ function DataTable({
2365
3342
  enableCellSelection,
2366
3343
  enableColumnResize,
2367
3344
  enableColumnFreeze,
3345
+ enableInlineSearch,
2368
3346
  shouldVirtualize,
2369
3347
  scrollRef,
3348
+ rootRef,
2370
3349
  rowVirtualizer,
2371
3350
  virtualRows,
2372
3351
  paddingTop,
2373
3352
  paddingBottom,
2374
3353
  rowContextValue,
2375
3354
  handleToggleSelect,
2376
- clearHover
3355
+ clearHover,
3356
+ inlineSearch
2377
3357
  } = useGlideTable(glideOptions);
2378
3358
  const ToolbarSlot = slots?.Toolbar ?? DataTableToolbar;
2379
3359
  const ScrollSlot = slots?.Scroll ?? DefaultScroll;
@@ -2381,12 +3361,12 @@ function DataTable({
2381
3361
  const PendingSlot = slots?.Pending ?? DefaultPending;
2382
3362
  const EmptySlot = slots?.Empty ?? DefaultEmpty;
2383
3363
  const freezeOffsets = rowContextValue.columnFreeze.offsets;
2384
- const contextValue = useMemo3(
3364
+ const contextValue = useMemo4(
2385
3365
  () => ({ ...rowContextValue, classNames }),
2386
3366
  [rowContextValue, classNames]
2387
3367
  );
2388
3368
  if (isPending) {
2389
- return /* @__PURE__ */ jsx5(
3369
+ return /* @__PURE__ */ jsx6(
2390
3370
  PendingSlot,
2391
3371
  {
2392
3372
  loadingText,
@@ -2395,19 +3375,21 @@ function DataTable({
2395
3375
  }
2396
3376
  );
2397
3377
  }
2398
- return /* @__PURE__ */ jsxs4(
3378
+ return /* @__PURE__ */ jsxs5(
2399
3379
  "div",
2400
3380
  {
3381
+ ref: rootRef,
2401
3382
  className: cn(
2402
3383
  "DataTableJSX",
2403
3384
  !enableCellSelection && "DataTableJSX--no-cell-selection",
2404
3385
  enableColumnResize && "DataTableJSX--column-resize",
2405
3386
  enableColumnFreeze && "DataTableJSX--column-freeze",
3387
+ enableInlineSearch && "DataTableJSX--inline-search",
2406
3388
  classNames?.root,
2407
3389
  className
2408
3390
  ),
2409
3391
  children: [
2410
- /* @__PURE__ */ jsx5(
3392
+ /* @__PURE__ */ jsx6(
2411
3393
  ToolbarSlot,
2412
3394
  {
2413
3395
  filteredCount: filteredCount ?? tableData.length,
@@ -2419,14 +3401,36 @@ function DataTable({
2419
3401
  classNames
2420
3402
  }
2421
3403
  ),
2422
- /* @__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(
2423
3427
  "table",
2424
3428
  {
2425
3429
  className: cn("data-table", classNames?.table),
2426
3430
  style: enableColumnResize ? { width: table.getTotalSize() } : void 0,
2427
3431
  onDragStart: enableCellSelection ? (event) => event.preventDefault() : void 0,
2428
3432
  children: [
2429
- /* @__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(
2430
3434
  "tr",
2431
3435
  {
2432
3436
  className: cn("data-table-head-row", classNames?.headRow),
@@ -2446,7 +3450,7 @@ function DataTable({
2446
3450
  ...sizeStyle,
2447
3451
  ...freezeStyle
2448
3452
  };
2449
- return /* @__PURE__ */ jsxs4(
3453
+ return /* @__PURE__ */ jsxs5(
2450
3454
  "th",
2451
3455
  {
2452
3456
  "data-resizing": header.column.getIsResizing() ? "" : void 0,
@@ -2462,7 +3466,7 @@ function DataTable({
2462
3466
  ),
2463
3467
  children: [
2464
3468
  header.isPlaceholder ? null : flexRender2(header.column.columnDef.header, header.getContext()),
2465
- canResize ? /* @__PURE__ */ jsx5(
3469
+ canResize ? /* @__PURE__ */ jsx6(
2466
3470
  "div",
2467
3471
  {
2468
3472
  role: "separator",
@@ -2488,20 +3492,20 @@ function DataTable({
2488
3492
  },
2489
3493
  headerGroup.id
2490
3494
  )) }),
2491
- /* @__PURE__ */ jsx5(DataTableContextProvider, { value: contextValue, children: /* @__PURE__ */ jsx5(
3495
+ /* @__PURE__ */ jsx6(DataTableContextProvider, { value: contextValue, children: /* @__PURE__ */ jsx6(
2492
3496
  "tbody",
2493
3497
  {
2494
3498
  onMouseLeave: clearHover,
2495
3499
  className: cn("data-table-body", classNames?.body),
2496
- children: rows.length === 0 ? /* @__PURE__ */ jsx5(
3500
+ children: rows.length === 0 ? /* @__PURE__ */ jsx6(
2497
3501
  EmptySlot,
2498
3502
  {
2499
3503
  emptyText,
2500
3504
  columnCount,
2501
3505
  classNames
2502
3506
  }
2503
- ) : shouldVirtualize ? /* @__PURE__ */ jsxs4(Fragment2, { children: [
2504
- paddingTop > 0 && /* @__PURE__ */ jsx5(
3507
+ ) : shouldVirtualize ? /* @__PURE__ */ jsxs5(Fragment2, { children: [
3508
+ paddingTop > 0 && /* @__PURE__ */ jsx6(
2505
3509
  "tr",
2506
3510
  {
2507
3511
  "aria-hidden": true,
@@ -2509,7 +3513,7 @@ function DataTable({
2509
3513
  "data-table-virtual-spacer",
2510
3514
  classNames?.virtualSpacer
2511
3515
  ),
2512
- children: /* @__PURE__ */ jsx5(
3516
+ children: /* @__PURE__ */ jsx6(
2513
3517
  "td",
2514
3518
  {
2515
3519
  colSpan: columnCount,
@@ -2525,7 +3529,7 @@ function DataTable({
2525
3529
  virtualRows.map((virtualRow) => {
2526
3530
  const row = rows[virtualRow.index];
2527
3531
  if (!row) return null;
2528
- return /* @__PURE__ */ jsx5(
3532
+ return /* @__PURE__ */ jsx6(
2529
3533
  RowSlot,
2530
3534
  {
2531
3535
  row,
@@ -2536,7 +3540,7 @@ function DataTable({
2536
3540
  row.id
2537
3541
  );
2538
3542
  }),
2539
- paddingBottom > 0 && /* @__PURE__ */ jsx5(
3543
+ paddingBottom > 0 && /* @__PURE__ */ jsx6(
2540
3544
  "tr",
2541
3545
  {
2542
3546
  "aria-hidden": true,
@@ -2544,7 +3548,7 @@ function DataTable({
2544
3548
  "data-table-virtual-spacer",
2545
3549
  classNames?.virtualSpacer
2546
3550
  ),
2547
- children: /* @__PURE__ */ jsx5(
3551
+ children: /* @__PURE__ */ jsx6(
2548
3552
  "td",
2549
3553
  {
2550
3554
  colSpan: columnCount,
@@ -2557,7 +3561,7 @@ function DataTable({
2557
3561
  )
2558
3562
  }
2559
3563
  )
2560
- ] }) : rows.map((row) => /* @__PURE__ */ jsx5(
3564
+ ] }) : rows.map((row) => /* @__PURE__ */ jsx6(
2561
3565
  RowSlot,
2562
3566
  {
2563
3567
  row,
@@ -2576,10 +3580,10 @@ function DataTable({
2576
3580
  }
2577
3581
 
2578
3582
  // src/components/ui/table/components/Table/Table.tsx
2579
- 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";
2580
3584
 
2581
3585
  // src/components/ui/table/components/Table/buildColumnDef.tsx
2582
- import { jsx as jsx6, jsxs as jsxs5 } from "react/jsx-runtime";
3586
+ import { jsx as jsx7, jsxs as jsxs6 } from "react/jsx-runtime";
2583
3587
  function SortableHeader({
2584
3588
  label,
2585
3589
  field,
@@ -2588,15 +3592,15 @@ function SortableHeader({
2588
3592
  }) {
2589
3593
  const isActive = sort?.field === field;
2590
3594
  const Icon = isActive ? sort.direction === "asc" ? ArrowUp : ArrowDown : ArrowUpDown;
2591
- return /* @__PURE__ */ jsxs5(
3595
+ return /* @__PURE__ */ jsxs6(
2592
3596
  "button",
2593
3597
  {
2594
3598
  type: "button",
2595
3599
  className: cn("SortableHeaderJSX", isActive ? "is-active" : "is-inactive"),
2596
3600
  onClick: () => onSort(field),
2597
3601
  children: [
2598
- /* @__PURE__ */ jsx6("span", { children: label }),
2599
- /* @__PURE__ */ jsx6(Icon, { className: "sortable-header-icon" })
3602
+ /* @__PURE__ */ jsx7("span", { children: label }),
3603
+ /* @__PURE__ */ jsx7(Icon, { className: "sortable-header-icon" })
2600
3604
  ]
2601
3605
  }
2602
3606
  );
@@ -2629,7 +3633,7 @@ function buildColumnDef(props, sort, onSort) {
2629
3633
  ...minWidth != null ? { minSize: minWidth } : {},
2630
3634
  ...maxWidth != null ? { maxSize: maxWidth } : {},
2631
3635
  ...resizable === false ? { enableResizing: false } : {},
2632
- header: sortable ? () => /* @__PURE__ */ jsx6(SortableHeader, { label: children, field, sort, onSort }) : (
3636
+ header: sortable ? () => /* @__PURE__ */ jsx7(SortableHeader, { label: children, field, sort, onSort }) : (
2633
3637
  // eslint-disable-next-line @typescript-eslint/promise-function-async
2634
3638
  () => children
2635
3639
  ),
@@ -2777,7 +3781,7 @@ function TableHeader(props) {
2777
3781
  TableHeader.displayName = TABLE_HEADER_DISPLAY_NAME;
2778
3782
 
2779
3783
  // src/components/ui/table/components/Table/TablePagination.tsx
2780
- import { jsx as jsx7, jsxs as jsxs6 } from "react/jsx-runtime";
3784
+ import { jsx as jsx8, jsxs as jsxs7 } from "react/jsx-runtime";
2781
3785
  function TablePagination({
2782
3786
  page,
2783
3787
  pageSize = 10,
@@ -2789,8 +3793,8 @@ function TablePagination({
2789
3793
  const safePage = Math.min(Math.max(1, page), totalPages);
2790
3794
  const canGoPrev = safePage > 1;
2791
3795
  const canGoNext = safePage < totalPages;
2792
- return /* @__PURE__ */ jsxs6("div", { className: cn("TablePaginationJSX", className), children: [
2793
- /* @__PURE__ */ jsx7(
3796
+ return /* @__PURE__ */ jsxs7("div", { className: cn("TablePaginationJSX", className), children: [
3797
+ /* @__PURE__ */ jsx8(
2794
3798
  "button",
2795
3799
  {
2796
3800
  type: "button",
@@ -2798,15 +3802,15 @@ function TablePagination({
2798
3802
  disabled: !canGoPrev,
2799
3803
  onClick: () => onChange(safePage - 1),
2800
3804
  "aria-label": "Previous page",
2801
- children: /* @__PURE__ */ jsx7(ChevronLeft, { className: "pagination-button-icon" })
3805
+ children: /* @__PURE__ */ jsx8(ChevronLeft, { className: "pagination-button-icon" })
2802
3806
  }
2803
3807
  ),
2804
- /* @__PURE__ */ jsxs6("span", { className: "pagination-label", children: [
3808
+ /* @__PURE__ */ jsxs7("span", { className: "pagination-label", children: [
2805
3809
  safePage,
2806
3810
  " / ",
2807
3811
  totalPages
2808
3812
  ] }),
2809
- /* @__PURE__ */ jsx7(
3813
+ /* @__PURE__ */ jsx8(
2810
3814
  "button",
2811
3815
  {
2812
3816
  type: "button",
@@ -2814,7 +3818,7 @@ function TablePagination({
2814
3818
  disabled: !canGoNext,
2815
3819
  onClick: () => onChange(safePage + 1),
2816
3820
  "aria-label": "Next page",
2817
- children: /* @__PURE__ */ jsx7(ChevronRight, { className: "pagination-button-icon" })
3821
+ children: /* @__PURE__ */ jsx8(ChevronRight, { className: "pagination-button-icon" })
2818
3822
  }
2819
3823
  )
2820
3824
  ] });
@@ -2822,7 +3826,7 @@ function TablePagination({
2822
3826
  TablePagination.displayName = TABLE_PAGINATION_DISPLAY_NAME;
2823
3827
 
2824
3828
  // src/components/ui/table/components/Table/Table.tsx
2825
- import { jsx as jsx8, jsxs as jsxs7 } from "react/jsx-runtime";
3829
+ import { jsx as jsx9, jsxs as jsxs8 } from "react/jsx-runtime";
2826
3830
  function TableRoot({
2827
3831
  data,
2828
3832
  children,
@@ -2831,12 +3835,12 @@ function TableRoot({
2831
3835
  filteredCount,
2832
3836
  ...dataTableProps
2833
3837
  }) {
2834
- const { header, pagination: paginationElement } = useMemo4(
3838
+ const { header, pagination: paginationElement } = useMemo5(
2835
3839
  () => parseTableChildren(children),
2836
3840
  [children]
2837
3841
  );
2838
- const [sort, setSort] = useState4(null);
2839
- const handleSort = useCallback4((field) => {
3842
+ const [sort, setSort] = useState5(null);
3843
+ const handleSort = useCallback5((field) => {
2840
3844
  setSort((previous) => {
2841
3845
  if (previous?.field !== field) {
2842
3846
  return { field, direction: "asc" };
@@ -2847,7 +3851,7 @@ function TableRoot({
2847
3851
  return null;
2848
3852
  });
2849
3853
  }, []);
2850
- const columns = useMemo4(() => {
3854
+ const columns = useMemo5(() => {
2851
3855
  return extractColumnElements(header).map(
2852
3856
  (columnElement) => buildColumnDef(columnElement.props, sort, handleSort)
2853
3857
  );
@@ -2856,7 +3860,7 @@ function TableRoot({
2856
3860
  const pageSize = paginationProps?.pageSize ?? 10;
2857
3861
  const page = paginationProps?.page ?? 1;
2858
3862
  const resolvedTotalCount = paginationProps?.totalCount ?? totalCount ?? data.length;
2859
- const tableData = useMemo4(() => {
3863
+ const tableData = useMemo5(() => {
2860
3864
  const sortedData = sortTableData(data, sort);
2861
3865
  if (!paginationProps) return sortedData;
2862
3866
  return paginateTableData(sortedData, page, pageSize);
@@ -2864,8 +3868,8 @@ function TableRoot({
2864
3868
  if (columns.length === 0) {
2865
3869
  console.warn("[Table] Declare at least one Table.Column inside Table.Header.");
2866
3870
  }
2867
- return /* @__PURE__ */ jsxs7("div", { className: "TableJSX", children: [
2868
- /* @__PURE__ */ jsx8(
3871
+ return /* @__PURE__ */ jsxs8("div", { className: "TableJSX", children: [
3872
+ /* @__PURE__ */ jsx9(
2869
3873
  DataTable,
2870
3874
  {
2871
3875
  ...dataTableProps,
@@ -2876,7 +3880,7 @@ function TableRoot({
2876
3880
  className: cn(className, paginationProps && "DataTableJSX--with-pagination")
2877
3881
  }
2878
3882
  ),
2879
- paginationProps && /* @__PURE__ */ jsx8(
3883
+ paginationProps && /* @__PURE__ */ jsx9(
2880
3884
  TablePagination,
2881
3885
  {
2882
3886
  page,
@@ -2896,7 +3900,7 @@ function createTable() {
2896
3900
  Column.displayName = TABLE_COLUMN_DISPLAY_NAME;
2897
3901
  return Object.assign(
2898
3902
  function BoundTable(props) {
2899
- return /* @__PURE__ */ jsx8(TableRoot, { ...props });
3903
+ return /* @__PURE__ */ jsx9(TableRoot, { ...props });
2900
3904
  },
2901
3905
  {
2902
3906
  Header: TableHeader,
@@ -2920,20 +3924,31 @@ export {
2920
3924
  DEFAULT_TREE_PARENT_ID_FIELD,
2921
3925
  DEFAULT_TREE_QTY_FIELD,
2922
3926
  DataTable,
3927
+ INLINE_SEARCH_MAX_RESULTS,
2923
3928
  Table,
2924
3929
  applyCellEdit,
2925
3930
  applyFillData,
2926
3931
  applySelectionUpdater,
2927
3932
  buildColumnFreezeOffsets,
2928
3933
  buildColumnRowSpanMap,
3934
+ buildFlatSearchCorpus,
2929
3935
  buildRowsPastePayload,
3936
+ buildSearchMatchKey,
3937
+ buildSearchMatchKeys,
3938
+ buildTreeSearchCorpus,
2930
3939
  canExpandRow,
3940
+ cellValueToSearchText,
3941
+ collectAncestorKeysToExpand,
2931
3942
  collectCopyRowEntries,
2932
3943
  collectCopyRows,
2933
3944
  collectFillChanges,
2934
3945
  collectRowSpanColumns,
3946
+ collectSearchMatchesInRange,
3947
+ createSearchRegex,
2935
3948
  createTable,
3949
+ escapeSearchRegex,
2936
3950
  flattenSubtreeRows,
3951
+ formatSearchResultLabel,
2937
3952
  getCellEditDraftValue,
2938
3953
  getCellSelectionEdgeStyle,
2939
3954
  getColumnEditType,
@@ -2945,10 +3960,15 @@ export {
2945
3960
  isCellInSelection,
2946
3961
  isColumnEditable,
2947
3962
  isEditablePasteTarget,
3963
+ mapSearchResultToVisibleItem,
3964
+ mapSearchResultsToVisibleKeys,
2948
3965
  measureMergedSpanRowHeights,
3966
+ nextSearchIndex,
3967
+ nextSearchStride,
2949
3968
  parseCellEditValue,
2950
3969
  parseClipboardTSV,
2951
3970
  parseClipboardTSVWithDepths,
3971
+ previousSearchIndex,
2952
3972
  resolveColumnFreezeSide,
2953
3973
  resolveDataTableLabels,
2954
3974
  resolvePasteColumnIds,
@@ -2962,5 +3982,6 @@ export {
2962
3982
  useCellSelection,
2963
3983
  useConvertTreeData,
2964
3984
  useGlideTable,
3985
+ useInlineSearch,
2965
3986
  writeSelectionToClipboard
2966
3987
  };