react-glide-table 1.4.1 → 1.7.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/compound.cjs CHANGED
@@ -28,7 +28,7 @@ module.exports = __toCommonJS(compound_exports);
28
28
 
29
29
  // src/components/ui/table/components/DataTable/DataTable.tsx
30
30
  var import_react_table3 = require("@tanstack/react-table");
31
- var import_react7 = require("react");
31
+ var import_react8 = require("react");
32
32
 
33
33
  // src/components/ui/table/components/DataTable/DataTableRow.tsx
34
34
  var import_react_table = require("@tanstack/react-table");
@@ -44,6 +44,7 @@ var ROW_HOVER_CLASS = "row-hoverable";
44
44
  var ROW_HOVERED_BG_CLASS = "row-hovered";
45
45
  var CELL_SELECTION_FILL_CLASS = "cell-selection-fill";
46
46
  var DATA_TABLE_ROW_HEIGHT = 44;
47
+ var DATA_TABLE_HEADER_ROW_HEIGHT = 40;
47
48
  var DATA_TABLE_VIRTUAL_OVERSCAN = 8;
48
49
  var DATA_TABLE_COLUMN_SIZE = 150;
49
50
  var DATA_TABLE_COLUMN_MIN_SIZE = 40;
@@ -131,6 +132,36 @@ function getCellSelectionBounds(start, end) {
131
132
  endCol: Math.max(start.col, end.col)
132
133
  };
133
134
  }
135
+ function getCellNavigationDelta(key) {
136
+ switch (key) {
137
+ case "ArrowUp":
138
+ case "w":
139
+ case "W":
140
+ return { row: -1, col: 0 };
141
+ case "ArrowDown":
142
+ case "s":
143
+ case "S":
144
+ return { row: 1, col: 0 };
145
+ case "ArrowLeft":
146
+ case "a":
147
+ case "A":
148
+ return { row: 0, col: -1 };
149
+ case "ArrowRight":
150
+ case "d":
151
+ case "D":
152
+ return { row: 0, col: 1 };
153
+ default:
154
+ return null;
155
+ }
156
+ }
157
+ function clampCellPosition(position, rowCount, columnCount) {
158
+ const maxRow = Math.max(rowCount - 1, 0);
159
+ const maxCol = Math.max(columnCount - 1, 0);
160
+ return {
161
+ row: Math.min(Math.max(position.row, 0), maxRow),
162
+ col: Math.min(Math.max(position.col, 0), maxCol)
163
+ };
164
+ }
134
165
  function measureMergedSpanRowHeights(rowIndex, rowSpan, cellElement) {
135
166
  if (rowSpan <= 1) return void 0;
136
167
  const tbody = cellElement?.closest("tbody") ?? (typeof document !== "undefined" ? document.querySelector("tbody.data-table-body") : null);
@@ -467,7 +498,7 @@ function getColumnFreezeStyle(offset, options) {
467
498
  position: "sticky",
468
499
  ...offset.side === "left" ? { left: offset.offset } : { right: offset.offset },
469
500
  zIndex: zBase + offset.stack,
470
- ...options?.isHeader ? { top: 0 } : {}
501
+ ...options?.isHeader ? { top: options.headerTop ?? 0 } : {}
471
502
  };
472
503
  }
473
504
 
@@ -484,6 +515,162 @@ function getColumnSizeStyle(size, options) {
484
515
  };
485
516
  }
486
517
 
518
+ // src/components/ui/table/features/inline-search/inlineSearch.ts
519
+ var INLINE_SEARCH_MAX_RESULTS = 1e3;
520
+ var INLINE_SEARCH_TARGET_TICK_MS = 10;
521
+ var INLINE_SEARCH_INITIAL_STRIDE = 10;
522
+ function escapeSearchRegex(value) {
523
+ return value.replace(/([$()*+.?[\\\]^{|}-])/g, "\\$1");
524
+ }
525
+ function createSearchRegex(query) {
526
+ const trimmed = query.trim();
527
+ if (!trimmed) return null;
528
+ return new RegExp(escapeSearchRegex(trimmed), "i");
529
+ }
530
+ function cellValueToSearchText(value) {
531
+ if (value == null) return void 0;
532
+ if (typeof value === "string") return value;
533
+ if (typeof value === "number" || typeof value === "boolean") {
534
+ return String(value);
535
+ }
536
+ if (Array.isArray(value)) {
537
+ return value.map((item) => cellValueToSearchText(item) ?? "").join(" ");
538
+ }
539
+ if (typeof value === "object") {
540
+ try {
541
+ return JSON.stringify(value);
542
+ } catch {
543
+ return String(value);
544
+ }
545
+ }
546
+ return String(value);
547
+ }
548
+ function formatSearchResultLabel(status) {
549
+ const countLabel = status.results >= INLINE_SEARCH_MAX_RESULTS ? `over ${INLINE_SEARCH_MAX_RESULTS}` : `${status.results} result${status.results !== 1 ? "s" : ""}`;
550
+ if (status.selectedIndex >= 0 && status.results > 0) {
551
+ return `${status.selectedIndex + 1} of ${countLabel}`;
552
+ }
553
+ return countLabel;
554
+ }
555
+ function nextSearchIndex(selectedIndex, results) {
556
+ if (results <= 0) return -1;
557
+ if (selectedIndex < 0) return 0;
558
+ return (selectedIndex + 1) % results;
559
+ }
560
+ function previousSearchIndex(selectedIndex, results) {
561
+ if (results <= 0) return -1;
562
+ if (selectedIndex < 0) return results - 1;
563
+ let next = (selectedIndex - 1) % results;
564
+ if (next < 0) next += results;
565
+ return next;
566
+ }
567
+ function buildSearchMatchKey(colIndex, rowIndex) {
568
+ return `${colIndex}:${rowIndex}`;
569
+ }
570
+ function buildSearchMatchKeys(results) {
571
+ const keys = /* @__PURE__ */ new Set();
572
+ for (const [colIndex, rowIndex] of results) {
573
+ keys.add(buildSearchMatchKey(colIndex, rowIndex));
574
+ }
575
+ return keys;
576
+ }
577
+ function collectSearchMatchesInRange(options) {
578
+ const {
579
+ query,
580
+ startRow,
581
+ rowCount,
582
+ columnCount,
583
+ getCellValue,
584
+ maxResults = INLINE_SEARCH_MAX_RESULTS
585
+ } = options;
586
+ const regex = createSearchRegex(query);
587
+ if (!regex || rowCount <= 0 || columnCount <= 0) return [];
588
+ const matches = [];
589
+ for (let rowOffset = 0; rowOffset < rowCount; rowOffset += 1) {
590
+ const rowIndex = startRow + rowOffset;
591
+ for (let colIndex = 0; colIndex < columnCount; colIndex += 1) {
592
+ const text = cellValueToSearchText(getCellValue(rowIndex, colIndex));
593
+ if (text !== void 0 && regex.test(text)) {
594
+ matches.push([colIndex, rowIndex]);
595
+ if (matches.length >= maxResults) {
596
+ return matches;
597
+ }
598
+ }
599
+ }
600
+ }
601
+ return matches;
602
+ }
603
+ function nextSearchStride(currentStride, elapsedMs, targetMs = INLINE_SEARCH_TARGET_TICK_MS) {
604
+ const rounded = Math.max(elapsedMs, 1);
605
+ const scalar = targetMs / rounded;
606
+ return Math.max(1, Math.ceil(currentStride * scalar));
607
+ }
608
+ function buildFlatSearchCorpus(rows, getRowId) {
609
+ return rows.map((data, index) => ({
610
+ id: getRowId(data, index),
611
+ data,
612
+ ancestorToggleKeys: []
613
+ }));
614
+ }
615
+ function buildTreeSearchCorpus(visibleRows, options) {
616
+ const { toggleField, getRowId } = options;
617
+ const corpus = [];
618
+ const seen = /* @__PURE__ */ new Set();
619
+ const walk = (node, ancestorToggleKeys) => {
620
+ const id = getRowId(node, corpus.length);
621
+ if (seen.has(id)) return;
622
+ seen.add(id);
623
+ corpus.push({
624
+ id,
625
+ data: node,
626
+ ancestorToggleKeys
627
+ });
628
+ const children = node.children;
629
+ if (!Array.isArray(children) || children.length === 0) return;
630
+ const toggleValue = node[toggleField];
631
+ const childAncestors = typeof toggleValue === "string" && toggleValue.length > 0 ? [...ancestorToggleKeys, toggleValue] : ancestorToggleKeys;
632
+ for (const child of children) {
633
+ if (child && typeof child === "object") {
634
+ walk(child, childAncestors);
635
+ }
636
+ }
637
+ };
638
+ for (const row of visibleRows) {
639
+ const level = row.level;
640
+ if (level === 0 || level === void 0) {
641
+ walk(row, []);
642
+ }
643
+ }
644
+ for (const row of visibleRows) {
645
+ const id = getRowId(row, corpus.length);
646
+ if (seen.has(id)) continue;
647
+ walk(row, []);
648
+ }
649
+ return corpus;
650
+ }
651
+ function mapSearchResultsToVisibleKeys(results, corpus, visibleRowIndexById) {
652
+ const keys = /* @__PURE__ */ new Set();
653
+ for (const [colIndex, corpusRowIndex] of results) {
654
+ const corpusRow = corpus[corpusRowIndex];
655
+ if (!corpusRow) continue;
656
+ const visibleRowIndex = visibleRowIndexById.get(corpusRow.id);
657
+ if (visibleRowIndex === void 0) continue;
658
+ keys.add(buildSearchMatchKey(colIndex, visibleRowIndex));
659
+ }
660
+ return keys;
661
+ }
662
+ function mapSearchResultToVisibleItem(item, corpus, visibleRowIndexById) {
663
+ const [colIndex, corpusRowIndex] = item;
664
+ const corpusRow = corpus[corpusRowIndex];
665
+ if (!corpusRow) return null;
666
+ const visibleRowIndex = visibleRowIndexById.get(corpusRow.id);
667
+ if (visibleRowIndex === void 0) return null;
668
+ return [colIndex, visibleRowIndex];
669
+ }
670
+ function collectAncestorKeysToExpand(corpusRow, expandedRows) {
671
+ return corpusRow.ancestorToggleKeys.filter((key) => !expandedRows.has(key));
672
+ }
673
+
487
674
  // src/components/ui/table/features/row-expand/row-expand.ts
488
675
  var import_react2 = require("react");
489
676
 
@@ -929,10 +1116,16 @@ function DataTableRow({
929
1116
  cellEdit,
930
1117
  expand,
931
1118
  columnResize,
932
- columnFreeze
1119
+ columnFreeze,
1120
+ inlineSearch
933
1121
  } = useDataTableRowContext();
934
1122
  const { enableColumnResize } = columnResize;
935
1123
  const { enableColumnFreeze, offsets: freezeOffsets } = columnFreeze;
1124
+ const {
1125
+ enabled: enableInlineSearch,
1126
+ matchKeys: searchMatchKeys,
1127
+ activeMatch
1128
+ } = inlineSearch;
936
1129
  const {
937
1130
  enableRowSpan,
938
1131
  primaryRowSpanColumnId,
@@ -1124,9 +1317,14 @@ function DataTableRow({
1124
1317
  ...freezeStyle,
1125
1318
  ...selectionEdgeStyle
1126
1319
  };
1320
+ const searchMatchKey = buildSearchMatchKey(cellIndex, rowIndex);
1321
+ const isSearchMatch = enableInlineSearch && searchMatchKeys.has(searchMatchKey);
1322
+ const isSearchActive = isSearchMatch && activeMatch !== null && activeMatch[0] === cellIndex && activeMatch[1] === rowIndex;
1127
1323
  return /* @__PURE__ */ (0, import_jsx_runtime3.jsxs)(
1128
1324
  "td",
1129
1325
  {
1326
+ "data-row-index": rowIndex,
1327
+ "data-col-index": cellIndex,
1130
1328
  rowSpan: rowSpanInfo && rowSpanInfo.rowSpan > 1 ? rowSpanInfo.rowSpan : void 0,
1131
1329
  "data-merged": isMerged && cellIndex > 0 ? "" : void 0,
1132
1330
  "data-merged-edge-right": showMergedRightEdge ? "" : void 0,
@@ -1136,6 +1334,8 @@ function DataTableRow({
1136
1334
  "data-group-hovered": enableRowSpan && showCellHover && !showCellSelected ? "" : void 0,
1137
1335
  "data-selection-fill": isCellDragSelected ? "" : void 0,
1138
1336
  "data-selection-edges": hasSelectionEdges ? "" : void 0,
1337
+ "data-search-match": isSearchMatch ? "" : void 0,
1338
+ "data-search-active": isSearchActive ? "" : void 0,
1139
1339
  "data-editable": editable ? "" : void 0,
1140
1340
  "data-editing": isEditing ? "" : void 0,
1141
1341
  "data-frozen": freezeOffset?.side,
@@ -1150,7 +1350,8 @@ function DataTableRow({
1150
1350
  event.preventDefault();
1151
1351
  onCellMouseDown(
1152
1352
  resolveCellRowIndex(event.clientY, event.currentTarget),
1153
- cellIndex
1353
+ cellIndex,
1354
+ { shiftKey: event.shiftKey }
1154
1355
  );
1155
1356
  },
1156
1357
  onMouseEnter: (event) => {
@@ -1187,6 +1388,8 @@ function DataTableRow({
1187
1388
  enableRowSpan && showCellHover && !showCellSelected && "is-group-hovered",
1188
1389
  isCellDragSelected && CELL_SELECTION_FILL_CLASS,
1189
1390
  hasSelectionEdges && CELL_SELECTION_EDGES_CLASS,
1391
+ isSearchMatch && "is-search-match",
1392
+ isSearchActive && "is-search-active",
1190
1393
  editable && "is-editable",
1191
1394
  classNames?.cell
1192
1395
  ),
@@ -1321,8 +1524,169 @@ function DataTableRow({
1321
1524
  );
1322
1525
  }
1323
1526
 
1324
- // src/components/ui/table/components/DataTable/DataTableToolbar.tsx
1527
+ // src/components/ui/table/components/DataTable/DataTableSearch.tsx
1325
1528
  var import_jsx_runtime4 = require("react/jsx-runtime");
1529
+ function SearchCloseIcon({ className }) {
1530
+ return /* @__PURE__ */ (0, import_jsx_runtime4.jsxs)(
1531
+ "svg",
1532
+ {
1533
+ className,
1534
+ "aria-hidden": true,
1535
+ width: "16",
1536
+ height: "16",
1537
+ viewBox: "0 0 24 24",
1538
+ fill: "none",
1539
+ stroke: "currentColor",
1540
+ strokeWidth: "2",
1541
+ strokeLinecap: "round",
1542
+ strokeLinejoin: "round",
1543
+ children: [
1544
+ /* @__PURE__ */ (0, import_jsx_runtime4.jsx)("path", { d: "M18 6 6 18" }),
1545
+ /* @__PURE__ */ (0, import_jsx_runtime4.jsx)("path", { d: "m6 6 12 12" })
1546
+ ]
1547
+ }
1548
+ );
1549
+ }
1550
+ function DataTableSearch({
1551
+ showSearch,
1552
+ searchValue,
1553
+ searchStatus,
1554
+ searchInputId,
1555
+ searchInputRef,
1556
+ canClose,
1557
+ placeholder,
1558
+ resultHint,
1559
+ previousLabel,
1560
+ nextLabel,
1561
+ closeLabel,
1562
+ rowsTotal,
1563
+ classNames,
1564
+ onSearchValueChange,
1565
+ onClose,
1566
+ onNext,
1567
+ onPrevious
1568
+ }) {
1569
+ if (!showSearch) return null;
1570
+ const resultString = searchStatus ? formatSearchResultLabel(searchStatus) : resultHint;
1571
+ const progress = rowsTotal > 0 ? Math.floor((searchStatus?.rowsSearched ?? 0) / rowsTotal * 100) : 0;
1572
+ const handleKeyDown = (event) => {
1573
+ if ((event.ctrlKey || event.metaKey) && event.code === "KeyF" || event.key === "Escape") {
1574
+ event.preventDefault();
1575
+ event.stopPropagation();
1576
+ if (canClose) {
1577
+ onClose();
1578
+ }
1579
+ return;
1580
+ }
1581
+ if (event.key === "ArrowDown" || event.key === "Enter" && !event.shiftKey) {
1582
+ event.preventDefault();
1583
+ onNext();
1584
+ return;
1585
+ }
1586
+ if (event.key === "ArrowUp" || event.key === "Enter" && event.shiftKey) {
1587
+ event.preventDefault();
1588
+ onPrevious();
1589
+ }
1590
+ };
1591
+ return /* @__PURE__ */ (0, import_jsx_runtime4.jsxs)(
1592
+ "div",
1593
+ {
1594
+ className: cn("data-table-search", classNames?.search),
1595
+ role: "search",
1596
+ onMouseDown: (event) => event.stopPropagation(),
1597
+ children: [
1598
+ /* @__PURE__ */ (0, import_jsx_runtime4.jsxs)("div", { className: "data-table-search-row", children: [
1599
+ /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(
1600
+ "input",
1601
+ {
1602
+ ref: searchInputRef,
1603
+ id: searchInputId,
1604
+ type: "search",
1605
+ value: searchValue,
1606
+ placeholder,
1607
+ autoComplete: "off",
1608
+ spellCheck: false,
1609
+ "aria-label": placeholder,
1610
+ className: cn("data-table-search-input", classNames?.searchInput),
1611
+ onChange: (event) => onSearchValueChange(event.target.value),
1612
+ onKeyDown: handleKeyDown
1613
+ }
1614
+ ),
1615
+ /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(
1616
+ "button",
1617
+ {
1618
+ type: "button",
1619
+ "aria-label": previousLabel,
1620
+ className: cn("data-table-search-button", classNames?.searchButton),
1621
+ onClick: (event) => {
1622
+ event.stopPropagation();
1623
+ onPrevious();
1624
+ },
1625
+ children: /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(ChevronUp, { className: "data-table-search-icon" })
1626
+ }
1627
+ ),
1628
+ /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(
1629
+ "button",
1630
+ {
1631
+ type: "button",
1632
+ "aria-label": nextLabel,
1633
+ className: cn("data-table-search-button", classNames?.searchButton),
1634
+ onClick: (event) => {
1635
+ event.stopPropagation();
1636
+ onNext();
1637
+ },
1638
+ children: /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(ChevronDown, { className: "data-table-search-icon" })
1639
+ }
1640
+ ),
1641
+ canClose ? /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(
1642
+ "button",
1643
+ {
1644
+ type: "button",
1645
+ "aria-label": closeLabel,
1646
+ className: cn("data-table-search-button", classNames?.searchButton),
1647
+ onClick: (event) => {
1648
+ event.stopPropagation();
1649
+ onClose();
1650
+ },
1651
+ children: /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(SearchCloseIcon, { className: "data-table-search-icon" })
1652
+ }
1653
+ ) : null
1654
+ ] }),
1655
+ /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(
1656
+ "div",
1657
+ {
1658
+ className: cn("data-table-search-status", classNames?.searchStatus),
1659
+ "aria-live": "polite",
1660
+ children: resultString
1661
+ }
1662
+ ),
1663
+ searchStatus !== void 0 ? /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(
1664
+ "div",
1665
+ {
1666
+ className: cn(
1667
+ "data-table-search-progress",
1668
+ classNames?.searchProgress
1669
+ ),
1670
+ role: "progressbar",
1671
+ "aria-valuemin": 0,
1672
+ "aria-valuemax": 100,
1673
+ "aria-valuenow": progress,
1674
+ children: /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(
1675
+ "div",
1676
+ {
1677
+ className: "data-table-search-progress-bar",
1678
+ style: { width: `${progress}%` }
1679
+ }
1680
+ )
1681
+ }
1682
+ ) : null
1683
+ ]
1684
+ }
1685
+ );
1686
+ }
1687
+
1688
+ // src/components/ui/table/components/DataTable/DataTableToolbar.tsx
1689
+ var import_jsx_runtime5 = require("react/jsx-runtime");
1326
1690
  function DataTableToolbar({
1327
1691
  filteredCount,
1328
1692
  totalCount,
@@ -1340,28 +1704,60 @@ function DataTableToolbar({
1340
1704
  const selectionContent = selectionLabel?.(selectedCount) ?? null;
1341
1705
  const hasSelectionContent = selectionContent !== null && selectionContent !== false && selectionContent !== void 0 && typeof selectionContent !== "boolean";
1342
1706
  if (!hasLeftContent && !hasToolbar && !hasSelectionContent) return null;
1343
- return /* @__PURE__ */ (0, import_jsx_runtime4.jsxs)("div", { className: cn("DataTableToolbarJSX", classNames?.toolbar, className), children: [
1344
- /* @__PURE__ */ (0, import_jsx_runtime4.jsxs)("div", { className: cn("toolbar-left", classNames?.toolbarLeft), children: [
1345
- hasCount && /* @__PURE__ */ (0, import_jsx_runtime4.jsx)("span", { className: cn("toolbar-count", classNames?.toolbarCount), children: displayFiltered !== void 0 && totalCount !== void 0 ? /* @__PURE__ */ (0, import_jsx_runtime4.jsxs)(import_jsx_runtime4.Fragment, { children: [
1346
- /* @__PURE__ */ (0, import_jsx_runtime4.jsx)("span", { className: "toolbar-count-primary", children: displayFiltered }),
1347
- /* @__PURE__ */ (0, import_jsx_runtime4.jsxs)("span", { className: "toolbar-count-placeholder", children: [
1707
+ return /* @__PURE__ */ (0, import_jsx_runtime5.jsxs)("div", { className: cn("DataTableToolbarJSX", classNames?.toolbar, className), children: [
1708
+ /* @__PURE__ */ (0, import_jsx_runtime5.jsxs)("div", { className: cn("toolbar-left", classNames?.toolbarLeft), children: [
1709
+ hasCount && /* @__PURE__ */ (0, import_jsx_runtime5.jsx)("span", { className: cn("toolbar-count", classNames?.toolbarCount), children: displayFiltered !== void 0 && totalCount !== void 0 ? /* @__PURE__ */ (0, import_jsx_runtime5.jsxs)(import_jsx_runtime5.Fragment, { children: [
1710
+ /* @__PURE__ */ (0, import_jsx_runtime5.jsx)("span", { className: "toolbar-count-primary", children: displayFiltered }),
1711
+ /* @__PURE__ */ (0, import_jsx_runtime5.jsxs)("span", { className: "toolbar-count-placeholder", children: [
1348
1712
  " / ",
1349
1713
  totalCount
1350
1714
  ] })
1351
- ] }) : /* @__PURE__ */ (0, import_jsx_runtime4.jsx)("span", { className: "toolbar-count-primary", children: displayFiltered ?? totalCount }) }),
1715
+ ] }) : /* @__PURE__ */ (0, import_jsx_runtime5.jsx)("span", { className: "toolbar-count-primary", children: displayFiltered ?? totalCount }) }),
1352
1716
  summary
1353
1717
  ] }),
1354
- /* @__PURE__ */ (0, import_jsx_runtime4.jsxs)("div", { className: cn("toolbar-right", classNames?.toolbarRight), children: [
1355
- hasSelectionContent && (typeof selectionContent === "string" || typeof selectionContent === "number" ? /* @__PURE__ */ (0, import_jsx_runtime4.jsx)("span", { className: cn("toolbar-selection", classNames?.toolbarSelection), children: selectionContent }) : selectionContent),
1356
- hasToolbar && /* @__PURE__ */ (0, import_jsx_runtime4.jsx)("div", { className: cn("toolbar-actions", classNames?.toolbarActions), children: toolbar })
1718
+ /* @__PURE__ */ (0, import_jsx_runtime5.jsxs)("div", { className: cn("toolbar-right", classNames?.toolbarRight), children: [
1719
+ hasSelectionContent && (typeof selectionContent === "string" || typeof selectionContent === "number" ? /* @__PURE__ */ (0, import_jsx_runtime5.jsx)("span", { className: cn("toolbar-selection", classNames?.toolbarSelection), children: selectionContent }) : selectionContent),
1720
+ hasToolbar && /* @__PURE__ */ (0, import_jsx_runtime5.jsx)("div", { className: cn("toolbar-actions", classNames?.toolbarActions), children: toolbar })
1357
1721
  ] })
1358
1722
  ] });
1359
1723
  }
1360
1724
 
1725
+ // src/components/ui/table/features/column-groups/mergeHeaderGroups.ts
1726
+ function getMergedHeaderGroups(headerGroups) {
1727
+ if (headerGroups.length <= 1) {
1728
+ return headerGroups.map((group) => ({
1729
+ ...group,
1730
+ headers: group.headers.map((header) => ({
1731
+ ...header,
1732
+ mergedRowSpan: 1
1733
+ }))
1734
+ }));
1735
+ }
1736
+ const seenColumnIds = /* @__PURE__ */ new Set();
1737
+ const fullDepth = headerGroups.length;
1738
+ return headerGroups.map((group, depth) => ({
1739
+ ...group,
1740
+ headers: group.headers.filter((header) => !seenColumnIds.has(header.column.id)).map((header) => {
1741
+ seenColumnIds.add(header.column.id);
1742
+ if (header.isPlaceholder) {
1743
+ return {
1744
+ ...header,
1745
+ isPlaceholder: false,
1746
+ mergedRowSpan: fullDepth - depth
1747
+ };
1748
+ }
1749
+ return {
1750
+ ...header,
1751
+ mergedRowSpan: 1
1752
+ };
1753
+ })
1754
+ }));
1755
+ }
1756
+
1361
1757
  // src/core/useGlideTable.ts
1362
1758
  var import_react_table2 = require("@tanstack/react-table");
1363
1759
  var import_react_virtual = require("@tanstack/react-virtual");
1364
- var import_react6 = require("react");
1760
+ var import_react7 = require("react");
1365
1761
 
1366
1762
  // src/components/ui/table/features/cell-edit/useCellEdit.ts
1367
1763
  var import_react4 = require("react");
@@ -1689,26 +2085,44 @@ function useCellSelection({
1689
2085
  data,
1690
2086
  rows,
1691
2087
  enabled = true,
2088
+ columnCount = 0,
1692
2089
  enableSubtreeCopy = false,
1693
2090
  enableInsertPaste = true,
1694
2091
  onDataChange,
1695
2092
  onBatchChange,
1696
- onRowsPaste
2093
+ onRowsPaste,
2094
+ onCellNavigate
1697
2095
  }) {
1698
2096
  const [dragState, setDragState] = (0, import_react5.useState)(INITIAL_DRAG_STATE);
1699
2097
  const pendingPasteModeRef = (0, import_react5.useRef)(null);
2098
+ const dragStateRef = (0, import_react5.useRef)(dragState);
2099
+ const onCellNavigateRef = (0, import_react5.useRef)(onCellNavigate);
2100
+ dragStateRef.current = dragState;
2101
+ onCellNavigateRef.current = onCellNavigate;
1700
2102
  const cellSelectionBounds = getCellSelectionBounds(dragState.start, dragState.end);
1701
2103
  const activeSelectionBounds = enabled ? getActiveSelectionBounds(dragState, cellSelectionBounds) : null;
1702
2104
  const handleCellMouseDown = (0, import_react5.useCallback)(
1703
- (rowIndex, colIndex) => {
2105
+ (rowIndex, colIndex, options) => {
1704
2106
  if (!enabled) return;
1705
- setDragState({
1706
- isSelecting: true,
1707
- isFillDragging: false,
1708
- start: { row: rowIndex, col: colIndex },
1709
- end: { row: rowIndex, col: colIndex },
1710
- fillAnchor: null,
1711
- fillEnd: null
2107
+ setDragState((prev) => {
2108
+ if (options?.shiftKey && prev.start) {
2109
+ return {
2110
+ ...prev,
2111
+ isSelecting: true,
2112
+ isFillDragging: false,
2113
+ end: { row: rowIndex, col: colIndex },
2114
+ fillAnchor: null,
2115
+ fillEnd: null
2116
+ };
2117
+ }
2118
+ return {
2119
+ isSelecting: true,
2120
+ isFillDragging: false,
2121
+ start: { row: rowIndex, col: colIndex },
2122
+ end: { row: rowIndex, col: colIndex },
2123
+ fillAnchor: null,
2124
+ fillEnd: null
2125
+ };
1712
2126
  });
1713
2127
  },
1714
2128
  [enabled]
@@ -1750,6 +2164,53 @@ function useCellSelection({
1750
2164
  setDragState(INITIAL_DRAG_STATE);
1751
2165
  }
1752
2166
  }, [enabled]);
2167
+ (0, import_react5.useEffect)(() => {
2168
+ if (!enabled) return;
2169
+ const handleKeyDown = (e) => {
2170
+ if (e.ctrlKey || e.metaKey || e.altKey) return;
2171
+ if (isEditablePasteTarget(e.target) || isEditablePasteTarget(document.activeElement)) {
2172
+ return;
2173
+ }
2174
+ const delta = getCellNavigationDelta(e.key);
2175
+ if (!delta) return;
2176
+ const prev = dragStateRef.current;
2177
+ if (!prev.start || !prev.end) return;
2178
+ if (prev.isSelecting || prev.isFillDragging) return;
2179
+ const rowCount = rows.length;
2180
+ const resolvedColumnCount = columnCount > 0 ? columnCount : rows[0]?.getVisibleCells().length ?? 0;
2181
+ if (rowCount <= 0 || resolvedColumnCount <= 0) return;
2182
+ const nextEnd = clampCellPosition(
2183
+ {
2184
+ row: prev.end.row + delta.row,
2185
+ col: prev.end.col + delta.col
2186
+ },
2187
+ rowCount,
2188
+ resolvedColumnCount
2189
+ );
2190
+ if (nextEnd.row === prev.end.row && nextEnd.col === prev.end.col) return;
2191
+ e.preventDefault();
2192
+ const nextState = e.shiftKey ? {
2193
+ ...prev,
2194
+ isSelecting: false,
2195
+ isFillDragging: false,
2196
+ end: nextEnd,
2197
+ fillAnchor: null,
2198
+ fillEnd: null
2199
+ } : {
2200
+ isSelecting: false,
2201
+ isFillDragging: false,
2202
+ start: nextEnd,
2203
+ end: nextEnd,
2204
+ fillAnchor: null,
2205
+ fillEnd: null
2206
+ };
2207
+ dragStateRef.current = nextState;
2208
+ setDragState(nextState);
2209
+ onCellNavigateRef.current?.(nextEnd);
2210
+ };
2211
+ window.addEventListener("keydown", handleKeyDown);
2212
+ return () => window.removeEventListener("keydown", handleKeyDown);
2213
+ }, [columnCount, enabled, rows]);
1753
2214
  const copySelection = (0, import_react5.useCallback)(
1754
2215
  async (options) => {
1755
2216
  if (!enabled || !activeSelectionBounds) return false;
@@ -1907,6 +2368,304 @@ function useCellSelection({
1907
2368
  };
1908
2369
  }
1909
2370
 
2371
+ // src/components/ui/table/features/inline-search/useInlineSearch.ts
2372
+ var import_react6 = require("react");
2373
+ var EMPTY_MATCH_KEYS = /* @__PURE__ */ new Set();
2374
+ function useInlineSearch({
2375
+ enabled = false,
2376
+ rowCount,
2377
+ columnCount,
2378
+ getCellValue,
2379
+ initialStartRow = 0,
2380
+ showSearch: controlledShowSearch,
2381
+ searchValue: controlledSearchValue,
2382
+ searchResults: controlledSearchResults,
2383
+ onSearchValueChange,
2384
+ onSearchClose,
2385
+ onSearchResultsChanged,
2386
+ onNavigateToResult,
2387
+ rootRef
2388
+ }) {
2389
+ const searchInputId = (0, import_react6.useId)();
2390
+ const searchInputRef = (0, import_react6.useRef)(null);
2391
+ const [internalShowSearch, setInternalShowSearch] = (0, import_react6.useState)(false);
2392
+ const [internalSearchValue, setInternalSearchValue] = (0, import_react6.useState)("");
2393
+ const [internalResults, setInternalResults] = (0, import_react6.useState)(
2394
+ []
2395
+ );
2396
+ const [searchStatus, setSearchStatus] = (0, import_react6.useState)();
2397
+ const searchStatusRef = (0, import_react6.useRef)(searchStatus);
2398
+ searchStatusRef.current = searchStatus;
2399
+ const abortControllerRef = (0, import_react6.useRef)(null);
2400
+ const searchHandleRef = (0, import_react6.useRef)(void 0);
2401
+ const initialStartRowRef = (0, import_react6.useRef)(initialStartRow);
2402
+ initialStartRowRef.current = initialStartRow;
2403
+ const getCellValueRef = (0, import_react6.useRef)(getCellValue);
2404
+ getCellValueRef.current = getCellValue;
2405
+ const showSearch = controlledShowSearch ?? internalShowSearch;
2406
+ const searchValue = controlledSearchValue ?? internalSearchValue;
2407
+ const searchResults = controlledSearchResults ?? internalResults;
2408
+ const setSearchValue = (0, import_react6.useCallback)(
2409
+ (value) => {
2410
+ setInternalSearchValue(value);
2411
+ onSearchValueChange?.(value);
2412
+ },
2413
+ [onSearchValueChange]
2414
+ );
2415
+ const cancelSearch = (0, import_react6.useCallback)(() => {
2416
+ if (searchHandleRef.current !== void 0) {
2417
+ window.cancelAnimationFrame(searchHandleRef.current);
2418
+ searchHandleRef.current = void 0;
2419
+ }
2420
+ abortControllerRef.current?.abort();
2421
+ }, []);
2422
+ const emitResultsChanged = (0, import_react6.useCallback)(
2423
+ (results, navIndex) => {
2424
+ onSearchResultsChanged?.(results, navIndex);
2425
+ },
2426
+ [onSearchResultsChanged]
2427
+ );
2428
+ const navigateToIndex = (0, import_react6.useCallback)(
2429
+ (results, navIndex) => {
2430
+ if (onSearchResultsChanged) return;
2431
+ if (navIndex < 0 || navIndex >= results.length) return;
2432
+ const item = results[navIndex];
2433
+ if (!item) return;
2434
+ onNavigateToResult?.(item);
2435
+ },
2436
+ [onNavigateToResult, onSearchResultsChanged]
2437
+ );
2438
+ const beginSearch = (0, import_react6.useCallback)(
2439
+ (query) => {
2440
+ if (controlledSearchResults !== void 0) return;
2441
+ const totalRows = rowCount;
2442
+ if (totalRows === 0 || columnCount === 0) {
2443
+ setSearchStatus(void 0);
2444
+ setInternalResults([]);
2445
+ emitResultsChanged([], -1);
2446
+ return;
2447
+ }
2448
+ let startY = Math.min(
2449
+ Math.max(0, initialStartRowRef.current),
2450
+ totalRows - 1
2451
+ );
2452
+ let searchStride = Math.min(INLINE_SEARCH_INITIAL_STRIDE, totalRows);
2453
+ let rowsSearched = 0;
2454
+ const runningResult = [];
2455
+ setSearchStatus(void 0);
2456
+ setInternalResults([]);
2457
+ const tick = () => {
2458
+ if (abortControllerRef.current?.signal.aborted) return;
2459
+ const tStart = performance.now();
2460
+ const rowsLeft = totalRows - rowsSearched;
2461
+ const height = Math.min(searchStride, rowsLeft, totalRows - startY);
2462
+ if (height <= 0) {
2463
+ return;
2464
+ }
2465
+ const chunk = collectSearchMatchesInRange({
2466
+ query,
2467
+ startRow: startY,
2468
+ rowCount: height,
2469
+ columnCount,
2470
+ getCellValue: (rowIndex, colIndex) => getCellValueRef.current(rowIndex, colIndex),
2471
+ maxResults: INLINE_SEARCH_MAX_RESULTS - runningResult.length
2472
+ });
2473
+ if (chunk.length > 0) {
2474
+ runningResult.push(...chunk);
2475
+ setInternalResults([...runningResult]);
2476
+ }
2477
+ rowsSearched += height;
2478
+ const selectedIndex = searchStatusRef.current?.selectedIndex ?? -1;
2479
+ setSearchStatus({
2480
+ results: runningResult.length,
2481
+ rowsSearched,
2482
+ selectedIndex
2483
+ });
2484
+ emitResultsChanged(runningResult, selectedIndex);
2485
+ if (startY + height >= totalRows) {
2486
+ startY = 0;
2487
+ } else {
2488
+ startY += height;
2489
+ }
2490
+ searchStride = nextSearchStride(
2491
+ searchStride,
2492
+ performance.now() - tStart
2493
+ );
2494
+ if (rowsSearched < totalRows && runningResult.length < INLINE_SEARCH_MAX_RESULTS) {
2495
+ searchHandleRef.current = window.requestAnimationFrame(tick);
2496
+ }
2497
+ };
2498
+ cancelSearch();
2499
+ abortControllerRef.current = new AbortController();
2500
+ searchHandleRef.current = window.requestAnimationFrame(tick);
2501
+ },
2502
+ [
2503
+ cancelSearch,
2504
+ columnCount,
2505
+ controlledSearchResults,
2506
+ emitResultsChanged,
2507
+ rowCount
2508
+ ]
2509
+ );
2510
+ const openSearch = (0, import_react6.useCallback)(() => {
2511
+ if (controlledShowSearch === void 0) {
2512
+ setInternalShowSearch(true);
2513
+ }
2514
+ }, [controlledShowSearch]);
2515
+ const closeSearch = (0, import_react6.useCallback)(() => {
2516
+ if (controlledShowSearch === void 0) {
2517
+ setInternalShowSearch(false);
2518
+ }
2519
+ onSearchClose?.();
2520
+ setSearchStatus(void 0);
2521
+ setInternalResults([]);
2522
+ emitResultsChanged([], -1);
2523
+ cancelSearch();
2524
+ }, [
2525
+ cancelSearch,
2526
+ controlledShowSearch,
2527
+ emitResultsChanged,
2528
+ onSearchClose
2529
+ ]);
2530
+ const goToNext = (0, import_react6.useCallback)(() => {
2531
+ if (!searchStatus || searchStatus.results === 0) return;
2532
+ const newIndex = nextSearchIndex(
2533
+ searchStatus.selectedIndex,
2534
+ searchStatus.results
2535
+ );
2536
+ setSearchStatus({ ...searchStatus, selectedIndex: newIndex });
2537
+ emitResultsChanged(searchResults, newIndex);
2538
+ navigateToIndex(searchResults, newIndex);
2539
+ }, [emitResultsChanged, navigateToIndex, searchResults, searchStatus]);
2540
+ const goToPrevious = (0, import_react6.useCallback)(() => {
2541
+ if (!searchStatus || searchStatus.results === 0) return;
2542
+ const newIndex = previousSearchIndex(
2543
+ searchStatus.selectedIndex,
2544
+ searchStatus.results
2545
+ );
2546
+ setSearchStatus({ ...searchStatus, selectedIndex: newIndex });
2547
+ emitResultsChanged(searchResults, newIndex);
2548
+ navigateToIndex(searchResults, newIndex);
2549
+ }, [emitResultsChanged, navigateToIndex, searchResults, searchStatus]);
2550
+ (0, import_react6.useEffect)(() => {
2551
+ if (controlledSearchResults === void 0) return;
2552
+ if (controlledSearchResults.length > 0) {
2553
+ setSearchStatus((current) => ({
2554
+ rowsSearched: rowCount,
2555
+ results: controlledSearchResults.length,
2556
+ selectedIndex: current?.selectedIndex ?? -1
2557
+ }));
2558
+ } else {
2559
+ setSearchStatus(void 0);
2560
+ }
2561
+ }, [controlledSearchResults, rowCount]);
2562
+ (0, import_react6.useEffect)(() => {
2563
+ if (!enabled) return;
2564
+ setSearchStatus(void 0);
2565
+ setInternalResults([]);
2566
+ emitResultsChanged([], -1);
2567
+ if (showSearch) {
2568
+ queueMicrotask(() => {
2569
+ searchInputRef.current?.focus({ preventScroll: true });
2570
+ });
2571
+ } else {
2572
+ cancelSearch();
2573
+ }
2574
+ }, [enabled, showSearch]);
2575
+ (0, import_react6.useEffect)(() => {
2576
+ if (!enabled || !showSearch) return;
2577
+ if (controlledSearchResults !== void 0) return;
2578
+ if (searchValue.trim() === "") {
2579
+ setSearchStatus(void 0);
2580
+ setInternalResults([]);
2581
+ cancelSearch();
2582
+ emitResultsChanged([], -1);
2583
+ return;
2584
+ }
2585
+ beginSearch(searchValue);
2586
+ }, [
2587
+ beginSearch,
2588
+ cancelSearch,
2589
+ controlledSearchResults,
2590
+ emitResultsChanged,
2591
+ enabled,
2592
+ searchValue,
2593
+ showSearch
2594
+ ]);
2595
+ (0, import_react6.useEffect)(() => {
2596
+ if (!enabled) return;
2597
+ const handleKeyDown = (event) => {
2598
+ if (!(event.ctrlKey || event.metaKey)) return;
2599
+ if (event.key.toLowerCase() !== "f") return;
2600
+ const root = rootRef?.current;
2601
+ if (root) {
2602
+ const active = document.activeElement;
2603
+ const focusInside = active === root || active instanceof Node && root.contains(active);
2604
+ if (!focusInside && active !== document.body) {
2605
+ return;
2606
+ }
2607
+ }
2608
+ event.preventDefault();
2609
+ event.stopPropagation();
2610
+ if (showSearch) {
2611
+ searchInputRef.current?.focus({ preventScroll: true });
2612
+ searchInputRef.current?.select();
2613
+ return;
2614
+ }
2615
+ if (controlledShowSearch === void 0) {
2616
+ setInternalShowSearch(true);
2617
+ }
2618
+ };
2619
+ window.addEventListener("keydown", handleKeyDown, true);
2620
+ return () => window.removeEventListener("keydown", handleKeyDown, true);
2621
+ }, [controlledShowSearch, enabled, rootRef, showSearch]);
2622
+ (0, import_react6.useEffect)(() => () => cancelSearch(), [cancelSearch]);
2623
+ const searchMatchKeys = (0, import_react6.useMemo)(
2624
+ () => buildSearchMatchKeys(searchResults),
2625
+ [searchResults]
2626
+ );
2627
+ const activeMatch = (0, import_react6.useMemo)(() => {
2628
+ if (!searchStatus || searchStatus.selectedIndex < 0) return null;
2629
+ return searchResults[searchStatus.selectedIndex] ?? null;
2630
+ }, [searchResults, searchStatus]);
2631
+ if (!enabled) {
2632
+ return {
2633
+ enabled: false,
2634
+ showSearch: false,
2635
+ searchValue: "",
2636
+ searchResults: [],
2637
+ searchStatus: void 0,
2638
+ searchMatchKeys: EMPTY_MATCH_KEYS,
2639
+ activeMatch: null,
2640
+ searchInputRef,
2641
+ searchInputId,
2642
+ canClose: false,
2643
+ openSearch,
2644
+ closeSearch,
2645
+ setSearchValue,
2646
+ goToNext,
2647
+ goToPrevious
2648
+ };
2649
+ }
2650
+ return {
2651
+ enabled: true,
2652
+ showSearch,
2653
+ searchValue,
2654
+ searchResults,
2655
+ searchStatus,
2656
+ searchMatchKeys,
2657
+ activeMatch,
2658
+ searchInputRef,
2659
+ searchInputId,
2660
+ canClose: controlledShowSearch === void 0 || onSearchClose !== void 0,
2661
+ openSearch,
2662
+ closeSearch,
2663
+ setSearchValue,
2664
+ goToNext,
2665
+ goToPrevious
2666
+ };
2667
+ }
2668
+
1910
2669
  // src/components/ui/table/features/row-selection/rowSelection.ts
1911
2670
  function resolveRowSelection(mode, controlledSelection, internalSelection) {
1912
2671
  if (mode === "none") return {};
@@ -1929,7 +2688,12 @@ var DEFAULT_DATA_TABLE_LABELS = {
1929
2688
  selection: (selectedCount) => selectedCount > 0 ? `\u2713 ${selectedCount} selected` : null,
1930
2689
  expandRow: "Expand row",
1931
2690
  collapseRow: "Collapse row",
1932
- resizeColumn: "Resize column"
2691
+ resizeColumn: "Resize column",
2692
+ searchPlaceholder: "Search\u2026",
2693
+ searchResultHint: "Type to search",
2694
+ searchPrevious: "Previous result",
2695
+ searchNext: "Next result",
2696
+ searchClose: "Close search"
1933
2697
  };
1934
2698
  function resolveDataTableLabels(partial) {
1935
2699
  return {
@@ -1940,6 +2704,7 @@ function resolveDataTableLabels(partial) {
1940
2704
 
1941
2705
  // src/core/useGlideTable.ts
1942
2706
  var EMPTY_COLUMN_FREEZE_OFFSETS = /* @__PURE__ */ new Map();
2707
+ var EMPTY_SEARCH_MATCH_KEYS = /* @__PURE__ */ new Set();
1943
2708
  function useGlideTable(options) {
1944
2709
  const {
1945
2710
  data,
@@ -1980,9 +2745,16 @@ function useGlideTable(options) {
1980
2745
  columnSizing: controlledColumnSizing,
1981
2746
  onColumnSizingChange,
1982
2747
  columnResizeMode = "onChange",
1983
- enableColumnFreeze = false
2748
+ enableColumnFreeze = false,
2749
+ enableInlineSearch = false,
2750
+ showSearch,
2751
+ searchValue,
2752
+ onSearchValueChange,
2753
+ onSearchClose,
2754
+ searchResults,
2755
+ onSearchResultsChanged
1984
2756
  } = options;
1985
- const labels = (0, import_react6.useMemo)(() => {
2757
+ const labels = (0, import_react7.useMemo)(() => {
1986
2758
  const resolved = resolveDataTableLabels(labelsProp);
1987
2759
  return {
1988
2760
  ...resolved,
@@ -1993,15 +2765,16 @@ function useGlideTable(options) {
1993
2765
  }, [labelsProp, emptyText, loadingText, selectionLabel]);
1994
2766
  const enableExpand = Boolean(toggleField);
1995
2767
  const resolvedEnableSubtreeCopy = enableSubtreeCopy ?? enableExpand;
1996
- const [internalRowSelection, setInternalRowSelection] = (0, import_react6.useState)({});
1997
- const [internalColumnSizing, setInternalColumnSizing] = (0, import_react6.useState)({});
1998
- const [internalExpandedRows, setInternalExpandedRows] = (0, import_react6.useState)(
2768
+ const [internalRowSelection, setInternalRowSelection] = (0, import_react7.useState)({});
2769
+ const [internalColumnSizing, setInternalColumnSizing] = (0, import_react7.useState)({});
2770
+ const [internalExpandedRows, setInternalExpandedRows] = (0, import_react7.useState)(
1999
2771
  () => /* @__PURE__ */ new Set()
2000
2772
  );
2001
- const [hoveredRowIndex, setHoveredRowIndex] = (0, import_react6.useState)(null);
2002
- const scrollRef = (0, import_react6.useRef)(null);
2773
+ const [hoveredRowIndex, setHoveredRowIndex] = (0, import_react7.useState)(null);
2774
+ const scrollRef = (0, import_react7.useRef)(null);
2775
+ const rootRef = (0, import_react7.useRef)(null);
2003
2776
  const shouldVirtualize = enableVirtualization && !enableRowSpan;
2004
- (0, import_react6.useEffect)(() => {
2777
+ (0, import_react7.useEffect)(() => {
2005
2778
  if (enableVirtualization && enableRowSpan) {
2006
2779
  console.warn(
2007
2780
  "[useGlideTable] enableRowSpan is on; virtualization is disabled to preserve cell merges."
@@ -2015,7 +2788,7 @@ function useGlideTable(options) {
2015
2788
  );
2016
2789
  const columnSizing = controlledColumnSizing ?? internalColumnSizing;
2017
2790
  const expandedRows = controlledExpandedRows ?? internalExpandedRows;
2018
- const handleExpandedRowsChange = (0, import_react6.useCallback)(
2791
+ const handleExpandedRowsChange = (0, import_react7.useCallback)(
2019
2792
  (next) => {
2020
2793
  if (onExpandedRowsChange) {
2021
2794
  onExpandedRowsChange(next);
@@ -2076,13 +2849,13 @@ function useGlideTable(options) {
2076
2849
  getCoreRowModel: (0, import_react_table2.getCoreRowModel)(),
2077
2850
  getRowId: getRowId ? (originalRow, index) => getRowId(originalRow, index) : (_originalRow, index) => String(index)
2078
2851
  });
2079
- const rowSpanColumnKeys = (0, import_react6.useMemo)(() => {
2852
+ const rowSpanColumnKeys = (0, import_react7.useMemo)(() => {
2080
2853
  if (!enableRowSpan) return [];
2081
2854
  return collectRowSpanColumns(columns);
2082
2855
  }, [enableRowSpan, columns]);
2083
2856
  const primaryRowSpanKey = rowSpanColumnKeys[0]?.rowSpanKey;
2084
2857
  const primaryRowSpanColumnId = rowSpanColumnKeys[0]?.columnId;
2085
- const columnRowSpanMap = (0, import_react6.useMemo)(
2858
+ const columnRowSpanMap = (0, import_react7.useMemo)(
2086
2859
  () => buildColumnRowSpanMap(tableData, rowSpanColumnKeys),
2087
2860
  [tableData, rowSpanColumnKeys]
2088
2861
  );
@@ -2091,7 +2864,7 @@ function useGlideTable(options) {
2091
2864
  const rows = table.getRowModel().rows;
2092
2865
  const columnCount = table.getAllLeafColumns().length || 1;
2093
2866
  const visibleLeafColumns = table.getVisibleLeafColumns();
2094
- const columnFreezeOffsets = (0, import_react6.useMemo)(() => {
2867
+ const columnFreezeOffsets = (0, import_react7.useMemo)(() => {
2095
2868
  if (!enableColumnFreeze) return EMPTY_COLUMN_FREEZE_OFFSETS;
2096
2869
  return buildColumnFreezeOffsets(
2097
2870
  visibleLeafColumns.map((column) => ({
@@ -2111,13 +2884,46 @@ function useGlideTable(options) {
2111
2884
  const totalSize = rowVirtualizer.getTotalSize();
2112
2885
  const paddingTop = virtualRows.length > 0 ? virtualRows[0]?.start ?? 0 : 0;
2113
2886
  const paddingBottom = virtualRows.length > 0 ? totalSize - (virtualRows[virtualRows.length - 1]?.end ?? 0) : 0;
2114
- const selectedRowIndices = (0, import_react6.useMemo)(() => {
2887
+ const selectedRowIndices = (0, import_react7.useMemo)(() => {
2115
2888
  const indices = /* @__PURE__ */ new Set();
2116
2889
  for (const selectedRow of selectedRows) {
2117
2890
  indices.add(selectedRow.index);
2118
2891
  }
2119
2892
  return indices;
2120
2893
  }, [selectedRows]);
2894
+ const scrollCellIntoView = (0, import_react7.useCallback)(
2895
+ (rowIndex, colIndex, options2) => {
2896
+ const align = options2?.align ?? "nearest";
2897
+ const blockAlign = align === "center" ? "center" : "nearest";
2898
+ if (shouldVirtualize) {
2899
+ rowVirtualizer.scrollToIndex(rowIndex, {
2900
+ align: align === "nearest" ? "auto" : align
2901
+ });
2902
+ }
2903
+ const scrollElement = scrollRef.current;
2904
+ if (!scrollElement) return;
2905
+ const scrollToMatchedCell = () => {
2906
+ const cell = scrollElement.querySelector(
2907
+ `[data-row-index="${rowIndex}"][data-col-index="${colIndex}"]`
2908
+ );
2909
+ if (cell instanceof HTMLElement) {
2910
+ cell.scrollIntoView({ block: blockAlign, inline: "nearest" });
2911
+ }
2912
+ };
2913
+ if (shouldVirtualize) {
2914
+ requestAnimationFrame(scrollToMatchedCell);
2915
+ return;
2916
+ }
2917
+ scrollToMatchedCell();
2918
+ },
2919
+ [rowVirtualizer, shouldVirtualize]
2920
+ );
2921
+ const handleCellNavigate = (0, import_react7.useCallback)(
2922
+ (position) => {
2923
+ scrollCellIntoView(position.row, position.col, { align: "nearest" });
2924
+ },
2925
+ [scrollCellIntoView]
2926
+ );
2121
2927
  const {
2122
2928
  dragState,
2123
2929
  activeSelectionBounds,
@@ -2129,11 +2935,13 @@ function useGlideTable(options) {
2129
2935
  data: tableData,
2130
2936
  rows,
2131
2937
  enabled: enableCellSelection,
2938
+ columnCount: visibleLeafColumns.length,
2132
2939
  enableSubtreeCopy: resolvedEnableSubtreeCopy,
2133
2940
  enableInsertPaste: enableInsertPaste ?? true,
2134
2941
  onDataChange,
2135
2942
  onBatchChange,
2136
- onRowsPaste
2943
+ onRowsPaste,
2944
+ onCellNavigate: handleCellNavigate
2137
2945
  });
2138
2946
  const {
2139
2947
  editingCell,
@@ -2143,23 +2951,193 @@ function useGlideTable(options) {
2143
2951
  commitEdit,
2144
2952
  cancelEdit
2145
2953
  } = useCellEdit({ data: tableData, rows, onDataChange, onCellChange });
2146
- const handleCellMouseDownWithCommit = (0, import_react6.useCallback)(
2147
- (rowIndex, colIndex) => {
2954
+ const handleCellMouseDownWithCommit = (0, import_react7.useCallback)(
2955
+ (rowIndex, colIndex, options2) => {
2148
2956
  const isSameEditingCell = editingCell?.rowIndex === rowIndex && editingCell?.colIndex === colIndex;
2149
2957
  if (editingCell && !isSameEditingCell && !commitEdit()) {
2150
2958
  return;
2151
2959
  }
2152
- handleCellMouseDown(rowIndex, colIndex);
2960
+ handleCellMouseDown(rowIndex, colIndex, options2);
2153
2961
  },
2154
2962
  [commitEdit, editingCell, handleCellMouseDown]
2155
2963
  );
2156
- const clearHover = (0, import_react6.useCallback)(() => {
2964
+ const navigateToSearchResult = (0, import_react7.useCallback)(
2965
+ (item) => {
2966
+ const [colIndex, rowIndex] = item;
2967
+ handleCellMouseDownWithCommit(rowIndex, colIndex);
2968
+ scrollCellIntoView(rowIndex, colIndex, { align: "center" });
2969
+ },
2970
+ [handleCellMouseDownWithCommit, scrollCellIntoView]
2971
+ );
2972
+ const resolveSearchRowId = (0, import_react7.useCallback)(
2973
+ (row, index) => {
2974
+ if (getRowId) return getRowId(row, index);
2975
+ if (enableExpand) {
2976
+ const record = row;
2977
+ const idValue = record.id;
2978
+ if (idValue != null && String(idValue).length > 0) {
2979
+ return String(idValue);
2980
+ }
2981
+ const uniqueId = record.uniqueId;
2982
+ if (uniqueId != null && String(uniqueId).length > 0) {
2983
+ return String(uniqueId);
2984
+ }
2985
+ if (toggleField) {
2986
+ const toggleValue = record[toggleField];
2987
+ if (toggleValue != null && String(toggleValue).length > 0) {
2988
+ return String(toggleValue);
2989
+ }
2990
+ }
2991
+ }
2992
+ return String(index);
2993
+ },
2994
+ [enableExpand, getRowId, toggleField]
2995
+ );
2996
+ const searchCorpus = (0, import_react7.useMemo)(() => {
2997
+ if (!enableInlineSearch) return [];
2998
+ if (enableExpand && toggleField) {
2999
+ return buildTreeSearchCorpus(tableData, {
3000
+ toggleField,
3001
+ getRowId: resolveSearchRowId
3002
+ });
3003
+ }
3004
+ return buildFlatSearchCorpus(tableData, resolveSearchRowId);
3005
+ }, [
3006
+ enableExpand,
3007
+ enableInlineSearch,
3008
+ resolveSearchRowId,
3009
+ tableData,
3010
+ toggleField
3011
+ ]);
3012
+ const searchCorpusRef = (0, import_react7.useRef)(searchCorpus);
3013
+ searchCorpusRef.current = searchCorpus;
3014
+ const visibleRowIndexById = (0, import_react7.useMemo)(() => {
3015
+ const map = /* @__PURE__ */ new Map();
3016
+ for (const row of rows) {
3017
+ map.set(resolveSearchRowId(row.original, row.index), row.index);
3018
+ }
3019
+ return map;
3020
+ }, [resolveSearchRowId, rows]);
3021
+ const getSearchCellValue = (0, import_react7.useCallback)(
3022
+ (rowIndex, colIndex) => {
3023
+ const corpusRow = searchCorpusRef.current[rowIndex];
3024
+ const column = visibleLeafColumns[colIndex];
3025
+ if (!corpusRow || !column) return void 0;
3026
+ const visibleIndex = visibleRowIndexById.get(corpusRow.id);
3027
+ if (visibleIndex !== void 0) {
3028
+ const visibleRow = rows[visibleIndex];
3029
+ if (visibleRow) {
3030
+ return visibleRow.getValue(column.id);
3031
+ }
3032
+ }
3033
+ const columnDef = column.columnDef;
3034
+ if ("accessorFn" in columnDef && typeof columnDef.accessorFn === "function") {
3035
+ return columnDef.accessorFn(corpusRow.data, rowIndex);
3036
+ }
3037
+ if ("accessorKey" in columnDef && columnDef.accessorKey != null && columnDef.accessorKey !== "") {
3038
+ return corpusRow.data[String(columnDef.accessorKey)];
3039
+ }
3040
+ return corpusRow.data[column.id];
3041
+ },
3042
+ [rows, visibleLeafColumns, visibleRowIndexById]
3043
+ );
3044
+ const pendingSearchNavRef = (0, import_react7.useRef)(null);
3045
+ const focusSearchResult = (0, import_react7.useCallback)(
3046
+ (colIndex, visibleRowIndex) => {
3047
+ navigateToSearchResult([colIndex, visibleRowIndex]);
3048
+ },
3049
+ [navigateToSearchResult]
3050
+ );
3051
+ const navigateToCorpusSearchResult = (0, import_react7.useCallback)(
3052
+ (item) => {
3053
+ const [colIndex, corpusRowIndex] = item;
3054
+ const corpusRow = searchCorpusRef.current[corpusRowIndex];
3055
+ if (!corpusRow) return;
3056
+ const missingKeys = collectAncestorKeysToExpand(corpusRow, expandedRows);
3057
+ if (missingKeys.length > 0) {
3058
+ pendingSearchNavRef.current = {
3059
+ colIndex,
3060
+ rowId: corpusRow.id
3061
+ };
3062
+ const next = new Set(expandedRows);
3063
+ for (const key of corpusRow.ancestorToggleKeys) {
3064
+ next.add(key);
3065
+ }
3066
+ handleExpandedRowsChange(next);
3067
+ return;
3068
+ }
3069
+ const visibleItem = mapSearchResultToVisibleItem(
3070
+ item,
3071
+ searchCorpusRef.current,
3072
+ visibleRowIndexById
3073
+ );
3074
+ if (!visibleItem) return;
3075
+ focusSearchResult(visibleItem[0], visibleItem[1]);
3076
+ },
3077
+ [
3078
+ expandedRows,
3079
+ focusSearchResult,
3080
+ handleExpandedRowsChange,
3081
+ visibleRowIndexById
3082
+ ]
3083
+ );
3084
+ (0, import_react7.useEffect)(() => {
3085
+ const pending = pendingSearchNavRef.current;
3086
+ if (!pending) return;
3087
+ const visibleRowIndex = visibleRowIndexById.get(pending.rowId);
3088
+ if (visibleRowIndex === void 0) return;
3089
+ pendingSearchNavRef.current = null;
3090
+ focusSearchResult(pending.colIndex, visibleRowIndex);
3091
+ }, [focusSearchResult, rows, visibleRowIndexById]);
3092
+ const initialSearchStartRow = virtualRows[0]?.index ?? 0;
3093
+ const inlineSearch = useInlineSearch({
3094
+ enabled: enableInlineSearch,
3095
+ rowCount: searchCorpus.length,
3096
+ columnCount: visibleLeafColumns.length,
3097
+ getCellValue: getSearchCellValue,
3098
+ initialStartRow: initialSearchStartRow,
3099
+ showSearch,
3100
+ searchValue,
3101
+ searchResults,
3102
+ onSearchValueChange,
3103
+ onSearchClose,
3104
+ onSearchResultsChanged,
3105
+ onNavigateToResult: navigateToCorpusSearchResult,
3106
+ rootRef
3107
+ });
3108
+ const visibleSearchMatchKeys = (0, import_react7.useMemo)(() => {
3109
+ if (!enableInlineSearch) return EMPTY_SEARCH_MATCH_KEYS;
3110
+ return mapSearchResultsToVisibleKeys(
3111
+ inlineSearch.searchResults,
3112
+ searchCorpus,
3113
+ visibleRowIndexById
3114
+ );
3115
+ }, [
3116
+ enableInlineSearch,
3117
+ inlineSearch.searchResults,
3118
+ searchCorpus,
3119
+ visibleRowIndexById
3120
+ ]);
3121
+ const visibleActiveMatch = (0, import_react7.useMemo)(() => {
3122
+ if (!enableInlineSearch || !inlineSearch.activeMatch) return null;
3123
+ return mapSearchResultToVisibleItem(
3124
+ inlineSearch.activeMatch,
3125
+ searchCorpus,
3126
+ visibleRowIndexById
3127
+ );
3128
+ }, [
3129
+ enableInlineSearch,
3130
+ inlineSearch.activeMatch,
3131
+ searchCorpus,
3132
+ visibleRowIndexById
3133
+ ]);
3134
+ const clearHover = (0, import_react7.useCallback)(() => {
2157
3135
  setHoveredRowIndex(null);
2158
3136
  }, []);
2159
- const handleRowHover = (0, import_react6.useCallback)((rowIndex, _rowData) => {
3137
+ const handleRowHover = (0, import_react7.useCallback)((rowIndex, _rowData) => {
2160
3138
  setHoveredRowIndex(rowIndex);
2161
3139
  }, []);
2162
- const handleToggleSelect = (0, import_react6.useCallback)(
3140
+ const handleToggleSelect = (0, import_react7.useCallback)(
2163
3141
  (row) => {
2164
3142
  if (!row.getCanSelect()) return;
2165
3143
  if (preserveRowSelection && row.getIsSelected()) {
@@ -2169,14 +3147,14 @@ function useGlideTable(options) {
2169
3147
  },
2170
3148
  [preserveRowSelection]
2171
3149
  );
2172
- const handleToggleExpand = (0, import_react6.useCallback)(
3150
+ const handleToggleExpand = (0, import_react7.useCallback)(
2173
3151
  (rowKey) => {
2174
3152
  if (preventExpand) return;
2175
3153
  handleExpandedRowsChange(toggleExpandedRowId(rowKey, expandedRows));
2176
3154
  },
2177
3155
  [preventExpand, handleExpandedRowsChange, expandedRows]
2178
3156
  );
2179
- const rowContextValue = (0, import_react6.useMemo)(() => {
3157
+ const rowContextValue = (0, import_react7.useMemo)(() => {
2180
3158
  return {
2181
3159
  rowSpan: {
2182
3160
  enableRowSpan,
@@ -2224,6 +3202,11 @@ function useGlideTable(options) {
2224
3202
  columnFreeze: {
2225
3203
  enableColumnFreeze,
2226
3204
  offsets: columnFreezeOffsets
3205
+ },
3206
+ inlineSearch: {
3207
+ enabled: enableInlineSearch,
3208
+ matchKeys: visibleSearchMatchKeys,
3209
+ activeMatch: visibleActiveMatch
2227
3210
  }
2228
3211
  };
2229
3212
  }, [
@@ -2259,14 +3242,17 @@ function useGlideTable(options) {
2259
3242
  labels.collapseRow,
2260
3243
  enableColumnResize,
2261
3244
  enableColumnFreeze,
2262
- columnFreezeOffsets
3245
+ columnFreezeOffsets,
3246
+ enableInlineSearch,
3247
+ visibleSearchMatchKeys,
3248
+ visibleActiveMatch
2263
3249
  ]);
2264
- const copySelectionRef = (0, import_react6.useRef)(copySelection);
2265
- (0, import_react6.useEffect)(() => {
3250
+ const copySelectionRef = (0, import_react7.useRef)(copySelection);
3251
+ (0, import_react7.useEffect)(() => {
2266
3252
  copySelectionRef.current = copySelection;
2267
3253
  }, [copySelection]);
2268
- const stableCopySelection = (0, import_react6.useCallback)((options2) => copySelectionRef.current(options2), []);
2269
- (0, import_react6.useEffect)(() => {
3254
+ const stableCopySelection = (0, import_react7.useCallback)((options2) => copySelectionRef.current(options2), []);
3255
+ (0, import_react7.useEffect)(() => {
2270
3256
  onCopyActionsReady?.({ copySelection: stableCopySelection });
2271
3257
  }, [onCopyActionsReady, stableCopySelection]);
2272
3258
  return {
@@ -2282,8 +3268,10 @@ function useGlideTable(options) {
2282
3268
  enableCellSelection,
2283
3269
  enableColumnResize,
2284
3270
  enableColumnFreeze,
3271
+ enableInlineSearch,
2285
3272
  shouldVirtualize,
2286
3273
  scrollRef,
3274
+ rootRef,
2287
3275
  rowVirtualizer,
2288
3276
  virtualRows,
2289
3277
  paddingTop,
@@ -2291,25 +3279,39 @@ function useGlideTable(options) {
2291
3279
  rowContextValue,
2292
3280
  handleToggleSelect,
2293
3281
  clearHover,
2294
- copySelection: stableCopySelection
3282
+ copySelection: stableCopySelection,
3283
+ inlineSearch: {
3284
+ showSearch: inlineSearch.showSearch,
3285
+ searchValue: inlineSearch.searchValue,
3286
+ searchStatus: inlineSearch.searchStatus,
3287
+ searchInputRef: inlineSearch.searchInputRef,
3288
+ searchInputId: inlineSearch.searchInputId,
3289
+ canClose: inlineSearch.canClose,
3290
+ searchRowCount: searchCorpus.length,
3291
+ setSearchValue: inlineSearch.setSearchValue,
3292
+ closeSearch: inlineSearch.closeSearch,
3293
+ goToNext: inlineSearch.goToNext,
3294
+ goToPrevious: inlineSearch.goToPrevious,
3295
+ openSearch: inlineSearch.openSearch
3296
+ }
2295
3297
  };
2296
3298
  }
2297
3299
 
2298
3300
  // src/components/ui/table/components/DataTable/DataTable.tsx
2299
- var import_jsx_runtime5 = require("react/jsx-runtime");
3301
+ var import_jsx_runtime6 = require("react/jsx-runtime");
2300
3302
  function DefaultScroll({
2301
3303
  scrollRef,
2302
3304
  children,
2303
3305
  className
2304
3306
  }) {
2305
- return /* @__PURE__ */ (0, import_jsx_runtime5.jsx)("div", { ref: scrollRef, className: cn("data-table-scroll", className), children });
3307
+ return /* @__PURE__ */ (0, import_jsx_runtime6.jsx)("div", { ref: scrollRef, className: cn("data-table-scroll", className), children });
2306
3308
  }
2307
3309
  function DefaultPending({
2308
3310
  loadingText,
2309
3311
  className,
2310
3312
  classNames
2311
3313
  }) {
2312
- return /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(
3314
+ return /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(
2313
3315
  "div",
2314
3316
  {
2315
3317
  className: cn(
@@ -2319,7 +3321,7 @@ function DefaultPending({
2319
3321
  classNames?.pending,
2320
3322
  className
2321
3323
  ),
2322
- children: /* @__PURE__ */ (0, import_jsx_runtime5.jsx)("span", { className: cn("data-table-loading-text", classNames?.loadingText), children: loadingText })
3324
+ children: /* @__PURE__ */ (0, import_jsx_runtime6.jsx)("span", { className: cn("data-table-loading-text", classNames?.loadingText), children: loadingText })
2323
3325
  }
2324
3326
  );
2325
3327
  }
@@ -2328,7 +3330,7 @@ function DefaultEmpty({
2328
3330
  columnCount,
2329
3331
  classNames
2330
3332
  }) {
2331
- return /* @__PURE__ */ (0, import_jsx_runtime5.jsx)("tr", { children: /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(
3333
+ return /* @__PURE__ */ (0, import_jsx_runtime6.jsx)("tr", { children: /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(
2332
3334
  "td",
2333
3335
  {
2334
3336
  colSpan: columnCount,
@@ -2361,15 +3363,18 @@ function DataTable({
2361
3363
  enableCellSelection,
2362
3364
  enableColumnResize,
2363
3365
  enableColumnFreeze,
3366
+ enableInlineSearch,
2364
3367
  shouldVirtualize,
2365
3368
  scrollRef,
3369
+ rootRef,
2366
3370
  rowVirtualizer,
2367
3371
  virtualRows,
2368
3372
  paddingTop,
2369
3373
  paddingBottom,
2370
3374
  rowContextValue,
2371
3375
  handleToggleSelect,
2372
- clearHover
3376
+ clearHover,
3377
+ inlineSearch
2373
3378
  } = useGlideTable(glideOptions);
2374
3379
  const ToolbarSlot = slots?.Toolbar ?? DataTableToolbar;
2375
3380
  const ScrollSlot = slots?.Scroll ?? DefaultScroll;
@@ -2377,12 +3382,13 @@ function DataTable({
2377
3382
  const PendingSlot = slots?.Pending ?? DefaultPending;
2378
3383
  const EmptySlot = slots?.Empty ?? DefaultEmpty;
2379
3384
  const freezeOffsets = rowContextValue.columnFreeze.offsets;
2380
- const contextValue = (0, import_react7.useMemo)(
3385
+ const headerGroups = getMergedHeaderGroups(table.getHeaderGroups());
3386
+ const contextValue = (0, import_react8.useMemo)(
2381
3387
  () => ({ ...rowContextValue, classNames }),
2382
3388
  [rowContextValue, classNames]
2383
3389
  );
2384
3390
  if (isPending) {
2385
- return /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(
3391
+ return /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(
2386
3392
  PendingSlot,
2387
3393
  {
2388
3394
  loadingText,
@@ -2391,19 +3397,21 @@ function DataTable({
2391
3397
  }
2392
3398
  );
2393
3399
  }
2394
- return /* @__PURE__ */ (0, import_jsx_runtime5.jsxs)(
3400
+ return /* @__PURE__ */ (0, import_jsx_runtime6.jsxs)(
2395
3401
  "div",
2396
3402
  {
3403
+ ref: rootRef,
2397
3404
  className: cn(
2398
3405
  "DataTableJSX",
2399
3406
  !enableCellSelection && "DataTableJSX--no-cell-selection",
2400
3407
  enableColumnResize && "DataTableJSX--column-resize",
2401
3408
  enableColumnFreeze && "DataTableJSX--column-freeze",
3409
+ enableInlineSearch && "DataTableJSX--inline-search",
2402
3410
  classNames?.root,
2403
3411
  className
2404
3412
  ),
2405
3413
  children: [
2406
- /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(
3414
+ /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(
2407
3415
  ToolbarSlot,
2408
3416
  {
2409
3417
  filteredCount: filteredCount ?? tableData.length,
@@ -2415,14 +3423,36 @@ function DataTable({
2415
3423
  classNames
2416
3424
  }
2417
3425
  ),
2418
- /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(ScrollSlot, { scrollRef, className: classNames?.scroll, children: /* @__PURE__ */ (0, import_jsx_runtime5.jsxs)(
3426
+ enableInlineSearch ? /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(
3427
+ DataTableSearch,
3428
+ {
3429
+ showSearch: inlineSearch.showSearch,
3430
+ searchValue: inlineSearch.searchValue,
3431
+ searchStatus: inlineSearch.searchStatus,
3432
+ searchInputId: inlineSearch.searchInputId,
3433
+ searchInputRef: inlineSearch.searchInputRef,
3434
+ canClose: inlineSearch.canClose,
3435
+ placeholder: labels.searchPlaceholder,
3436
+ resultHint: labels.searchResultHint,
3437
+ previousLabel: labels.searchPrevious,
3438
+ nextLabel: labels.searchNext,
3439
+ closeLabel: labels.searchClose,
3440
+ rowsTotal: inlineSearch.searchRowCount,
3441
+ classNames,
3442
+ onSearchValueChange: inlineSearch.setSearchValue,
3443
+ onClose: inlineSearch.closeSearch,
3444
+ onNext: inlineSearch.goToNext,
3445
+ onPrevious: inlineSearch.goToPrevious
3446
+ }
3447
+ ) : null,
3448
+ /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(ScrollSlot, { scrollRef, className: classNames?.scroll, children: /* @__PURE__ */ (0, import_jsx_runtime6.jsxs)(
2419
3449
  "table",
2420
3450
  {
2421
3451
  className: cn("data-table", classNames?.table),
2422
3452
  style: enableColumnResize ? { width: table.getTotalSize() } : void 0,
2423
3453
  onDragStart: enableCellSelection ? (event) => event.preventDefault() : void 0,
2424
3454
  children: [
2425
- /* @__PURE__ */ (0, import_jsx_runtime5.jsx)("thead", { className: cn("data-table-head", classNames?.head), children: table.getHeaderGroups().map((headerGroup) => /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(
3455
+ /* @__PURE__ */ (0, import_jsx_runtime6.jsx)("thead", { className: cn("data-table-head", classNames?.head), children: headerGroups.map((headerGroup) => /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(
2426
3456
  "tr",
2427
3457
  {
2428
3458
  className: cn("data-table-head-row", classNames?.headRow),
@@ -2436,15 +3466,18 @@ function DataTable({
2436
3466
  });
2437
3467
  const freezeOffset = enableColumnFreeze ? freezeOffsets.get(header.column.id) : void 0;
2438
3468
  const freezeStyle = getColumnFreezeStyle(freezeOffset, {
2439
- isHeader: true
3469
+ isHeader: true,
3470
+ headerTop: header.depth * DATA_TABLE_HEADER_ROW_HEIGHT
2440
3471
  });
2441
3472
  const headerStyle = {
2442
3473
  ...sizeStyle,
2443
3474
  ...freezeStyle
2444
3475
  };
2445
- return /* @__PURE__ */ (0, import_jsx_runtime5.jsxs)(
3476
+ return /* @__PURE__ */ (0, import_jsx_runtime6.jsxs)(
2446
3477
  "th",
2447
3478
  {
3479
+ colSpan: header.colSpan,
3480
+ rowSpan: header.mergedRowSpan,
2448
3481
  "data-resizing": header.column.getIsResizing() ? "" : void 0,
2449
3482
  "data-frozen": freezeOffset?.side,
2450
3483
  "data-freeze-edge": getColumnFreezeEdgeAttr(freezeOffset),
@@ -2458,7 +3491,7 @@ function DataTable({
2458
3491
  ),
2459
3492
  children: [
2460
3493
  header.isPlaceholder ? null : (0, import_react_table3.flexRender)(header.column.columnDef.header, header.getContext()),
2461
- canResize ? /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(
3494
+ canResize ? /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(
2462
3495
  "div",
2463
3496
  {
2464
3497
  role: "separator",
@@ -2484,20 +3517,20 @@ function DataTable({
2484
3517
  },
2485
3518
  headerGroup.id
2486
3519
  )) }),
2487
- /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(DataTableContextProvider, { value: contextValue, children: /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(
3520
+ /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(DataTableContextProvider, { value: contextValue, children: /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(
2488
3521
  "tbody",
2489
3522
  {
2490
3523
  onMouseLeave: clearHover,
2491
3524
  className: cn("data-table-body", classNames?.body),
2492
- children: rows.length === 0 ? /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(
3525
+ children: rows.length === 0 ? /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(
2493
3526
  EmptySlot,
2494
3527
  {
2495
3528
  emptyText,
2496
3529
  columnCount,
2497
3530
  classNames
2498
3531
  }
2499
- ) : shouldVirtualize ? /* @__PURE__ */ (0, import_jsx_runtime5.jsxs)(import_jsx_runtime5.Fragment, { children: [
2500
- paddingTop > 0 && /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(
3532
+ ) : shouldVirtualize ? /* @__PURE__ */ (0, import_jsx_runtime6.jsxs)(import_jsx_runtime6.Fragment, { children: [
3533
+ paddingTop > 0 && /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(
2501
3534
  "tr",
2502
3535
  {
2503
3536
  "aria-hidden": true,
@@ -2505,7 +3538,7 @@ function DataTable({
2505
3538
  "data-table-virtual-spacer",
2506
3539
  classNames?.virtualSpacer
2507
3540
  ),
2508
- children: /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(
3541
+ children: /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(
2509
3542
  "td",
2510
3543
  {
2511
3544
  colSpan: columnCount,
@@ -2521,7 +3554,7 @@ function DataTable({
2521
3554
  virtualRows.map((virtualRow) => {
2522
3555
  const row = rows[virtualRow.index];
2523
3556
  if (!row) return null;
2524
- return /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(
3557
+ return /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(
2525
3558
  RowSlot,
2526
3559
  {
2527
3560
  row,
@@ -2532,7 +3565,7 @@ function DataTable({
2532
3565
  row.id
2533
3566
  );
2534
3567
  }),
2535
- paddingBottom > 0 && /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(
3568
+ paddingBottom > 0 && /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(
2536
3569
  "tr",
2537
3570
  {
2538
3571
  "aria-hidden": true,
@@ -2540,7 +3573,7 @@ function DataTable({
2540
3573
  "data-table-virtual-spacer",
2541
3574
  classNames?.virtualSpacer
2542
3575
  ),
2543
- children: /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(
3576
+ children: /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(
2544
3577
  "td",
2545
3578
  {
2546
3579
  colSpan: columnCount,
@@ -2553,7 +3586,7 @@ function DataTable({
2553
3586
  )
2554
3587
  }
2555
3588
  )
2556
- ] }) : rows.map((row) => /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(
3589
+ ] }) : rows.map((row) => /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(
2557
3590
  RowSlot,
2558
3591
  {
2559
3592
  row,
@@ -2572,10 +3605,10 @@ function DataTable({
2572
3605
  }
2573
3606
 
2574
3607
  // src/components/ui/table/components/Table/Table.tsx
2575
- var import_react10 = require("react");
3608
+ var import_react11 = require("react");
2576
3609
 
2577
3610
  // src/components/ui/table/components/Table/buildColumnDef.tsx
2578
- var import_jsx_runtime6 = require("react/jsx-runtime");
3611
+ var import_jsx_runtime7 = require("react/jsx-runtime");
2579
3612
  function SortableHeader({
2580
3613
  label,
2581
3614
  field,
@@ -2584,15 +3617,15 @@ function SortableHeader({
2584
3617
  }) {
2585
3618
  const isActive = sort?.field === field;
2586
3619
  const Icon = isActive ? sort.direction === "asc" ? ArrowUp : ArrowDown : ArrowUpDown;
2587
- return /* @__PURE__ */ (0, import_jsx_runtime6.jsxs)(
3620
+ return /* @__PURE__ */ (0, import_jsx_runtime7.jsxs)(
2588
3621
  "button",
2589
3622
  {
2590
3623
  type: "button",
2591
3624
  className: cn("SortableHeaderJSX", isActive ? "is-active" : "is-inactive"),
2592
3625
  onClick: () => onSort(field),
2593
3626
  children: [
2594
- /* @__PURE__ */ (0, import_jsx_runtime6.jsx)("span", { children: label }),
2595
- /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(Icon, { className: "sortable-header-icon" })
3627
+ /* @__PURE__ */ (0, import_jsx_runtime7.jsx)("span", { children: label }),
3628
+ /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(Icon, { className: "sortable-header-icon" })
2596
3629
  ]
2597
3630
  }
2598
3631
  );
@@ -2625,7 +3658,7 @@ function buildColumnDef(props, sort, onSort) {
2625
3658
  ...minWidth != null ? { minSize: minWidth } : {},
2626
3659
  ...maxWidth != null ? { maxSize: maxWidth } : {},
2627
3660
  ...resizable === false ? { enableResizing: false } : {},
2628
- header: sortable ? () => /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(SortableHeader, { label: children, field, sort, onSort }) : (
3661
+ header: sortable ? () => /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(SortableHeader, { label: children, field, sort, onSort }) : (
2629
3662
  // eslint-disable-next-line @typescript-eslint/promise-function-async
2630
3663
  () => children
2631
3664
  ),
@@ -2650,15 +3683,56 @@ function buildColumnDef(props, sort, onSort) {
2650
3683
  }
2651
3684
  };
2652
3685
  }
3686
+ function resolveGroupId(props, index) {
3687
+ if (props.id) return props.id;
3688
+ if (typeof props.header === "string" || typeof props.header === "number") {
3689
+ return `group:${props.header}:${index}`;
3690
+ }
3691
+ return `group:${index}`;
3692
+ }
3693
+ function buildColumnDefsFromTree(nodes, sort, onSort) {
3694
+ return nodes.map((node, index) => {
3695
+ if (node.type === "leaf") {
3696
+ return buildColumnDef(node.props, sort, onSort);
3697
+ }
3698
+ const childDefs = buildColumnDefsFromTree(node.columns, sort, onSort);
3699
+ const { header, align, headerClassName } = node.props;
3700
+ return {
3701
+ id: resolveGroupId(node.props, index),
3702
+ header: (
3703
+ // eslint-disable-next-line @typescript-eslint/promise-function-async
3704
+ () => header
3705
+ ),
3706
+ columns: childDefs,
3707
+ enableResizing: false,
3708
+ meta: {
3709
+ align,
3710
+ headerClassName
3711
+ }
3712
+ };
3713
+ });
3714
+ }
3715
+ function countLeafColumns(nodes) {
3716
+ let count = 0;
3717
+ for (const node of nodes) {
3718
+ if (node.type === "leaf") {
3719
+ count += 1;
3720
+ } else {
3721
+ count += countLeafColumns(node.columns);
3722
+ }
3723
+ }
3724
+ return count;
3725
+ }
2653
3726
 
2654
3727
  // src/components/ui/table/components/Table/parseTableChildren.ts
2655
- var import_react9 = require("react");
3728
+ var import_react10 = require("react");
2656
3729
 
2657
3730
  // src/components/ui/table/components/Table/tableChildTypes.ts
2658
- var import_react8 = require("react");
3731
+ var import_react9 = require("react");
2659
3732
  var TABLE_HEADER_DISPLAY_NAME = "Table.Header";
2660
3733
  var TABLE_BODY_DISPLAY_NAME = "Table.Body";
2661
3734
  var TABLE_COLUMN_DISPLAY_NAME = "Table.Column";
3735
+ var TABLE_COLUMN_GROUP_DISPLAY_NAME = "Table.ColumnGroup";
2662
3736
  var TABLE_PAGINATION_DISPLAY_NAME = "Table.Pagination";
2663
3737
  function getComponentDisplayName(type) {
2664
3738
  if (typeof type === "function" || typeof type === "object" && type !== null) {
@@ -2667,16 +3741,19 @@ function getComponentDisplayName(type) {
2667
3741
  return void 0;
2668
3742
  }
2669
3743
  function isTableHeaderElement(child) {
2670
- return (0, import_react8.isValidElement)(child) && getComponentDisplayName(child.type) === TABLE_HEADER_DISPLAY_NAME;
3744
+ return (0, import_react9.isValidElement)(child) && getComponentDisplayName(child.type) === TABLE_HEADER_DISPLAY_NAME;
2671
3745
  }
2672
3746
  function isTableBodyElement(child) {
2673
- return (0, import_react8.isValidElement)(child) && getComponentDisplayName(child.type) === TABLE_BODY_DISPLAY_NAME;
3747
+ return (0, import_react9.isValidElement)(child) && getComponentDisplayName(child.type) === TABLE_BODY_DISPLAY_NAME;
2674
3748
  }
2675
3749
  function isTableColumnElement(child) {
2676
- return (0, import_react8.isValidElement)(child) && getComponentDisplayName(child.type) === TABLE_COLUMN_DISPLAY_NAME;
3750
+ return (0, import_react9.isValidElement)(child) && getComponentDisplayName(child.type) === TABLE_COLUMN_DISPLAY_NAME;
3751
+ }
3752
+ function isTableColumnGroupElement(child) {
3753
+ return (0, import_react9.isValidElement)(child) && getComponentDisplayName(child.type) === TABLE_COLUMN_GROUP_DISPLAY_NAME;
2677
3754
  }
2678
3755
  function isTablePaginationElement(child) {
2679
- return (0, import_react8.isValidElement)(child) && getComponentDisplayName(child.type) === TABLE_PAGINATION_DISPLAY_NAME;
3756
+ return (0, import_react9.isValidElement)(child) && getComponentDisplayName(child.type) === TABLE_PAGINATION_DISPLAY_NAME;
2680
3757
  }
2681
3758
 
2682
3759
  // src/components/ui/table/components/Table/parseTableChildren.ts
@@ -2686,7 +3763,7 @@ function parseTableChildren(children) {
2686
3763
  body: null,
2687
3764
  pagination: null
2688
3765
  };
2689
- for (const child of import_react9.Children.toArray(children)) {
3766
+ for (const child of import_react10.Children.toArray(children)) {
2690
3767
  if (isTableHeaderElement(child)) {
2691
3768
  slots.header = child;
2692
3769
  continue;
@@ -2701,26 +3778,38 @@ function parseTableChildren(children) {
2701
3778
  }
2702
3779
  return slots;
2703
3780
  }
2704
- function flattenColumnElements(children) {
3781
+ function walkColumnTreeNodes(children) {
2705
3782
  const result = [];
2706
- for (const child of import_react9.Children.toArray(children)) {
3783
+ for (const child of import_react10.Children.toArray(children)) {
2707
3784
  if (isTableColumnElement(child)) {
2708
- result.push(child);
3785
+ result.push({
3786
+ type: "leaf",
3787
+ props: child.props
3788
+ });
2709
3789
  continue;
2710
3790
  }
2711
- if ((0, import_react9.isValidElement)(child)) {
3791
+ if (isTableColumnGroupElement(child)) {
3792
+ const groupProps = child.props;
3793
+ result.push({
3794
+ type: "group",
3795
+ props: groupProps,
3796
+ columns: walkColumnTreeNodes(groupProps.children)
3797
+ });
3798
+ continue;
3799
+ }
3800
+ if ((0, import_react10.isValidElement)(child)) {
2712
3801
  const nested = child.props.children;
2713
3802
  if (nested != null) {
2714
- result.push(...flattenColumnElements(nested));
3803
+ result.push(...walkColumnTreeNodes(nested));
2715
3804
  }
2716
3805
  }
2717
3806
  }
2718
3807
  return result;
2719
3808
  }
2720
- function extractColumnElements(header) {
3809
+ function extractColumnTree(header) {
2721
3810
  if (!header) return [];
2722
3811
  const { children } = header.props;
2723
- return flattenColumnElements(children);
3812
+ return walkColumnTreeNodes(children);
2724
3813
  }
2725
3814
 
2726
3815
  // src/components/ui/table/components/Table/TableBody.tsx
@@ -2736,6 +3825,13 @@ function TableColumn(props) {
2736
3825
  }
2737
3826
  TableColumn.displayName = TABLE_COLUMN_DISPLAY_NAME;
2738
3827
 
3828
+ // src/components/ui/table/components/Table/TableColumnGroup.tsx
3829
+ function TableColumnGroup(props) {
3830
+ void props;
3831
+ return null;
3832
+ }
3833
+ TableColumnGroup.displayName = TABLE_COLUMN_GROUP_DISPLAY_NAME;
3834
+
2739
3835
  // src/components/ui/table/components/Table/tableDataPipeline.ts
2740
3836
  function sortTableData(data, sort) {
2741
3837
  if (!sort) return data;
@@ -2773,7 +3869,7 @@ function TableHeader(props) {
2773
3869
  TableHeader.displayName = TABLE_HEADER_DISPLAY_NAME;
2774
3870
 
2775
3871
  // src/components/ui/table/components/Table/TablePagination.tsx
2776
- var import_jsx_runtime7 = require("react/jsx-runtime");
3872
+ var import_jsx_runtime8 = require("react/jsx-runtime");
2777
3873
  function TablePagination({
2778
3874
  page,
2779
3875
  pageSize = 10,
@@ -2785,8 +3881,8 @@ function TablePagination({
2785
3881
  const safePage = Math.min(Math.max(1, page), totalPages);
2786
3882
  const canGoPrev = safePage > 1;
2787
3883
  const canGoNext = safePage < totalPages;
2788
- return /* @__PURE__ */ (0, import_jsx_runtime7.jsxs)("div", { className: cn("TablePaginationJSX", className), children: [
2789
- /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(
3884
+ return /* @__PURE__ */ (0, import_jsx_runtime8.jsxs)("div", { className: cn("TablePaginationJSX", className), children: [
3885
+ /* @__PURE__ */ (0, import_jsx_runtime8.jsx)(
2790
3886
  "button",
2791
3887
  {
2792
3888
  type: "button",
@@ -2794,15 +3890,15 @@ function TablePagination({
2794
3890
  disabled: !canGoPrev,
2795
3891
  onClick: () => onChange(safePage - 1),
2796
3892
  "aria-label": "Previous page",
2797
- children: /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(ChevronLeft, { className: "pagination-button-icon" })
3893
+ children: /* @__PURE__ */ (0, import_jsx_runtime8.jsx)(ChevronLeft, { className: "pagination-button-icon" })
2798
3894
  }
2799
3895
  ),
2800
- /* @__PURE__ */ (0, import_jsx_runtime7.jsxs)("span", { className: "pagination-label", children: [
3896
+ /* @__PURE__ */ (0, import_jsx_runtime8.jsxs)("span", { className: "pagination-label", children: [
2801
3897
  safePage,
2802
3898
  " / ",
2803
3899
  totalPages
2804
3900
  ] }),
2805
- /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(
3901
+ /* @__PURE__ */ (0, import_jsx_runtime8.jsx)(
2806
3902
  "button",
2807
3903
  {
2808
3904
  type: "button",
@@ -2810,7 +3906,7 @@ function TablePagination({
2810
3906
  disabled: !canGoNext,
2811
3907
  onClick: () => onChange(safePage + 1),
2812
3908
  "aria-label": "Next page",
2813
- children: /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(ChevronRight, { className: "pagination-button-icon" })
3909
+ children: /* @__PURE__ */ (0, import_jsx_runtime8.jsx)(ChevronRight, { className: "pagination-button-icon" })
2814
3910
  }
2815
3911
  )
2816
3912
  ] });
@@ -2818,7 +3914,7 @@ function TablePagination({
2818
3914
  TablePagination.displayName = TABLE_PAGINATION_DISPLAY_NAME;
2819
3915
 
2820
3916
  // src/components/ui/table/components/Table/Table.tsx
2821
- var import_jsx_runtime8 = require("react/jsx-runtime");
3917
+ var import_jsx_runtime9 = require("react/jsx-runtime");
2822
3918
  function TableRoot({
2823
3919
  data,
2824
3920
  children,
@@ -2827,12 +3923,12 @@ function TableRoot({
2827
3923
  filteredCount,
2828
3924
  ...dataTableProps
2829
3925
  }) {
2830
- const { header, pagination: paginationElement } = (0, import_react10.useMemo)(
3926
+ const { header, pagination: paginationElement } = (0, import_react11.useMemo)(
2831
3927
  () => parseTableChildren(children),
2832
3928
  [children]
2833
3929
  );
2834
- const [sort, setSort] = (0, import_react10.useState)(null);
2835
- const handleSort = (0, import_react10.useCallback)((field) => {
3930
+ const [sort, setSort] = (0, import_react11.useState)(null);
3931
+ const handleSort = (0, import_react11.useCallback)((field) => {
2836
3932
  setSort((previous) => {
2837
3933
  if (previous?.field !== field) {
2838
3934
  return { field, direction: "asc" };
@@ -2843,25 +3939,25 @@ function TableRoot({
2843
3939
  return null;
2844
3940
  });
2845
3941
  }, []);
2846
- const columns = (0, import_react10.useMemo)(() => {
2847
- return extractColumnElements(header).map(
2848
- (columnElement) => buildColumnDef(columnElement.props, sort, handleSort)
2849
- );
2850
- }, [header, sort, handleSort]);
3942
+ const columnTree = (0, import_react11.useMemo)(() => extractColumnTree(header), [header]);
3943
+ const columns = (0, import_react11.useMemo)(
3944
+ () => buildColumnDefsFromTree(columnTree, sort, handleSort),
3945
+ [columnTree, sort, handleSort]
3946
+ );
2851
3947
  const paginationProps = paginationElement?.props;
2852
3948
  const pageSize = paginationProps?.pageSize ?? 10;
2853
3949
  const page = paginationProps?.page ?? 1;
2854
3950
  const resolvedTotalCount = paginationProps?.totalCount ?? totalCount ?? data.length;
2855
- const tableData = (0, import_react10.useMemo)(() => {
3951
+ const tableData = (0, import_react11.useMemo)(() => {
2856
3952
  const sortedData = sortTableData(data, sort);
2857
3953
  if (!paginationProps) return sortedData;
2858
3954
  return paginateTableData(sortedData, page, pageSize);
2859
3955
  }, [data, sort, paginationProps, page, pageSize]);
2860
- if (columns.length === 0) {
3956
+ if (countLeafColumns(columnTree) === 0) {
2861
3957
  console.warn("[Table] Declare at least one Table.Column inside Table.Header.");
2862
3958
  }
2863
- return /* @__PURE__ */ (0, import_jsx_runtime8.jsxs)("div", { className: "TableJSX", children: [
2864
- /* @__PURE__ */ (0, import_jsx_runtime8.jsx)(
3959
+ return /* @__PURE__ */ (0, import_jsx_runtime9.jsxs)("div", { className: "TableJSX", children: [
3960
+ /* @__PURE__ */ (0, import_jsx_runtime9.jsx)(
2865
3961
  DataTable,
2866
3962
  {
2867
3963
  ...dataTableProps,
@@ -2872,7 +3968,7 @@ function TableRoot({
2872
3968
  className: cn(className, paginationProps && "DataTableJSX--with-pagination")
2873
3969
  }
2874
3970
  ),
2875
- paginationProps && /* @__PURE__ */ (0, import_jsx_runtime8.jsx)(
3971
+ paginationProps && /* @__PURE__ */ (0, import_jsx_runtime9.jsx)(
2876
3972
  TablePagination,
2877
3973
  {
2878
3974
  page,
@@ -2890,13 +3986,19 @@ function createTable() {
2890
3986
  return null;
2891
3987
  }
2892
3988
  Column.displayName = TABLE_COLUMN_DISPLAY_NAME;
3989
+ function ColumnGroup(props) {
3990
+ void props;
3991
+ return null;
3992
+ }
3993
+ ColumnGroup.displayName = TABLE_COLUMN_GROUP_DISPLAY_NAME;
2893
3994
  return Object.assign(
2894
3995
  function BoundTable(props) {
2895
- return /* @__PURE__ */ (0, import_jsx_runtime8.jsx)(TableRoot, { ...props });
3996
+ return /* @__PURE__ */ (0, import_jsx_runtime9.jsx)(TableRoot, { ...props });
2896
3997
  },
2897
3998
  {
2898
3999
  Header: TableHeader,
2899
4000
  Column,
4001
+ ColumnGroup,
2900
4002
  Body: TableBody,
2901
4003
  Pagination: TablePagination
2902
4004
  }
@@ -2905,6 +4007,7 @@ function createTable() {
2905
4007
  var Table = Object.assign(TableRoot, {
2906
4008
  Header: TableHeader,
2907
4009
  Column: TableColumn,
4010
+ ColumnGroup: TableColumnGroup,
2908
4011
  Body: TableBody,
2909
4012
  Pagination: TablePagination
2910
4013
  });