bolt-table 0.1.26 → 0.1.27

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.mjs CHANGED
@@ -90,6 +90,18 @@ var EyeOffIcon = ({ style, className }) => /* @__PURE__ */ jsxs("svg", { ...svgB
90
90
  /* @__PURE__ */ jsx("path", { d: "M6.61 6.61A13.526 13.526 0 0 0 2 12s3 7 10 7a9.74 9.74 0 0 0 5.39-1.61" }),
91
91
  /* @__PURE__ */ jsx("line", { x1: "2", x2: "22", y1: "2", y2: "22" })
92
92
  ] });
93
+ var SearchIcon = ({ style, className }) => /* @__PURE__ */ jsxs("svg", { ...svgBase, style, className, children: [
94
+ /* @__PURE__ */ jsx("circle", { cx: "11", cy: "11", r: "8" }),
95
+ /* @__PURE__ */ jsx("path", { d: "m21 21-4.3-4.3" })
96
+ ] });
97
+ var ColumnsIcon = ({ style, className }) => /* @__PURE__ */ jsxs("svg", { ...svgBase, style, className, children: [
98
+ /* @__PURE__ */ jsx("rect", { width: "18", height: "18", x: "3", y: "3", rx: "2", ry: "2" }),
99
+ /* @__PURE__ */ jsx("line", { x1: "12", x2: "12", y1: "3", y2: "21" })
100
+ ] });
101
+ var XIcon = ({ style, className }) => /* @__PURE__ */ jsxs("svg", { ...svgBase, style, className, children: [
102
+ /* @__PURE__ */ jsx("path", { d: "M18 6 6 18" }),
103
+ /* @__PURE__ */ jsx("path", { d: "m6 6 12 12" })
104
+ ] });
93
105
 
94
106
  // src/DraggableHeader.tsx
95
107
  import { Fragment, jsx as jsx2, jsxs as jsxs2 } from "react/jsx-runtime";
@@ -762,7 +774,13 @@ ResizeOverlay.displayName = "ResizeOverlay";
762
774
  var ResizeOverlay_default = ResizeOverlay;
763
775
 
764
776
  // src/TableBody.tsx
765
- import React3, { useCallback, useEffect as useEffect2, useMemo, useRef as useRef3, useState as useState2 } from "react";
777
+ import React3, {
778
+ useCallback,
779
+ useEffect as useEffect2,
780
+ useMemo,
781
+ useRef as useRef3,
782
+ useState as useState2
783
+ } from "react";
766
784
  import { Fragment as Fragment3, jsx as jsx4, jsxs as jsxs4 } from "react/jsx-runtime";
767
785
  var SHIMMER_WIDTHS = [55, 70, 45, 80, 60, 50, 75, 65];
768
786
  var EditableCell = ({
@@ -789,7 +807,15 @@ var EditableCell = ({
789
807
  onEdit(coerced, record, column.dataIndex, rowIndex);
790
808
  }
791
809
  onEditComplete();
792
- }, [draft, value, column.dataIndex, record, rowIndex, onEdit, onEditComplete]);
810
+ }, [
811
+ draft,
812
+ value,
813
+ column.dataIndex,
814
+ record,
815
+ rowIndex,
816
+ onEdit,
817
+ onEditComplete
818
+ ]);
793
819
  const cancel = useCallback(() => {
794
820
  onEditComplete();
795
821
  }, [onEditComplete]);
@@ -891,7 +917,11 @@ var Cell = React3.memo(
891
917
  rowSelection.onSelect?.(record, true, [record], e.nativeEvent);
892
918
  rowSelection.onChange?.([rawKey], [record], { type: "single" });
893
919
  },
894
- style: { cursor: "pointer", accentColor, backgroundColor: "#94A3B8" }
920
+ style: {
921
+ cursor: "pointer",
922
+ accentColor,
923
+ backgroundColor: "#94A3B8"
924
+ }
895
925
  }
896
926
  ) : /* @__PURE__ */ jsx4(
897
927
  "input",
@@ -917,7 +947,11 @@ var Cell = React3.memo(
917
947
  type: "multiple"
918
948
  });
919
949
  },
920
- style: { cursor: "pointer", accentColor, backgroundColor: "#94A3B8" }
950
+ style: {
951
+ cursor: "pointer",
952
+ accentColor,
953
+ backgroundColor: "#94A3B8"
954
+ }
921
955
  }
922
956
  );
923
957
  return /* @__PURE__ */ jsx4(
@@ -1053,6 +1087,33 @@ var MeasuredExpandedRow = React3.memo(
1053
1087
  }
1054
1088
  );
1055
1089
  MeasuredExpandedRow.displayName = "MeasuredExpandedRow";
1090
+ var DynamicRowMeasurer = React3.memo(
1091
+ ({
1092
+ index,
1093
+ onHeightChange,
1094
+ children
1095
+ }) => {
1096
+ const ref = useRef3(null);
1097
+ const onHeightChangeRef = useRef3(onHeightChange);
1098
+ useEffect2(() => {
1099
+ onHeightChangeRef.current = onHeightChange;
1100
+ }, [onHeightChange]);
1101
+ useEffect2(() => {
1102
+ const el = ref.current;
1103
+ if (!el) return;
1104
+ const observer = new ResizeObserver((entries) => {
1105
+ const height = entries[0]?.borderBoxSize?.[0]?.blockSize;
1106
+ if (height != null && height > 0) {
1107
+ onHeightChangeRef.current(index, Math.ceil(height));
1108
+ }
1109
+ });
1110
+ observer.observe(el);
1111
+ return () => observer.disconnect();
1112
+ }, [index]);
1113
+ return /* @__PURE__ */ jsx4("div", { ref, children });
1114
+ }
1115
+ );
1116
+ DynamicRowMeasurer.displayName = "DynamicRowMeasurer";
1056
1117
  var TableBody = ({
1057
1118
  data,
1058
1119
  orderedColumns,
@@ -1082,11 +1143,16 @@ var TableBody = ({
1082
1143
  bodyGridRow = 2,
1083
1144
  onEdit,
1084
1145
  editingCell,
1085
- onEditComplete
1146
+ onEditComplete,
1147
+ enableDynamicRowHeight = false,
1148
+ onRowHeightChange
1086
1149
  }) => {
1087
1150
  const virtualItems = rowVirtualizer.getVirtualItems();
1088
1151
  const totalSize = rowVirtualizer.getTotalSize();
1089
- const selectedKeySet = useMemo(() => new Set(normalizedSelectedKeys), [normalizedSelectedKeys]);
1152
+ const selectedKeySet = useMemo(
1153
+ () => new Set(normalizedSelectedKeys),
1154
+ [normalizedSelectedKeys]
1155
+ );
1090
1156
  const safeData = data ?? [];
1091
1157
  const safeColumns = orderedColumns ?? [];
1092
1158
  const allDataForSelection = useMemo(() => {
@@ -1169,15 +1235,58 @@ var TableBody = ({
1169
1235
  top: `${virtualRow.start}px`,
1170
1236
  left: 0,
1171
1237
  right: 0,
1172
- height: `${virtualRow.size}px`,
1173
- ...rowSty
1238
+ height: enableDynamicRowHeight ? void 0 : `${virtualRow.size}px`,
1239
+ minHeight: enableDynamicRowHeight ? `${rowHeight}px` : void 0
1174
1240
  },
1175
- children: /* @__PURE__ */ jsx4(
1241
+ children: enableDynamicRowHeight && onRowHeightChange && colIndex === 0 ? /* @__PURE__ */ jsx4(
1242
+ DynamicRowMeasurer,
1243
+ {
1244
+ index: virtualRow.index,
1245
+ onHeightChange: onRowHeightChange,
1246
+ children: /* @__PURE__ */ jsx4(
1247
+ "div",
1248
+ {
1249
+ style: {
1250
+ minHeight: `${rowHeight}px`,
1251
+ position: "relative",
1252
+ ...rowSty
1253
+ },
1254
+ children: /* @__PURE__ */ jsx4(
1255
+ Cell,
1256
+ {
1257
+ value: cellValue,
1258
+ record: row,
1259
+ column: col,
1260
+ rowIndex: virtualRow.index,
1261
+ classNames,
1262
+ styles,
1263
+ isSelected,
1264
+ isExpanded,
1265
+ rowSelection,
1266
+ normalizedSelectedKeys,
1267
+ rowKey,
1268
+ allData: allDataForSelection,
1269
+ getRowKey,
1270
+ getRawRowKey,
1271
+ accentColor,
1272
+ isLoading: isRowShimmer,
1273
+ recordFingerprint,
1274
+ onEdit,
1275
+ isEditing: editingCell?.rowKey === rowKey && editingCell?.columnKey === col.key,
1276
+ onEditComplete
1277
+ }
1278
+ )
1279
+ }
1280
+ )
1281
+ }
1282
+ ) : /* @__PURE__ */ jsx4(
1176
1283
  "div",
1177
1284
  {
1178
1285
  style: {
1179
- height: `${rowHeight}px`,
1180
- position: "relative"
1286
+ height: enableDynamicRowHeight ? void 0 : `${rowHeight}px`,
1287
+ minHeight: enableDynamicRowHeight ? `${rowHeight}px` : void 0,
1288
+ position: "relative",
1289
+ ...rowSty
1181
1290
  },
1182
1291
  children: /* @__PURE__ */ jsx4(
1183
1292
  Cell,
@@ -1232,7 +1341,12 @@ var TableBody = ({
1232
1341
  if (!(resolvedExpandedKeys?.has(rk) ?? false)) return null;
1233
1342
  let expandedRenderResult = null;
1234
1343
  try {
1235
- expandedRenderResult = expandable.expandedRowRender(row, virtualRow.index, 0, true);
1344
+ expandedRenderResult = expandable.expandedRowRender(
1345
+ row,
1346
+ virtualRow.index,
1347
+ 0,
1348
+ true
1349
+ );
1236
1350
  } catch {
1237
1351
  }
1238
1352
  const expandedContent = /* @__PURE__ */ jsx4(
@@ -1600,7 +1714,14 @@ function BoltTable({
1600
1714
  onCopy,
1601
1715
  keepPinnedRowsAcrossPages,
1602
1716
  onEdit,
1603
- onRowClick
1717
+ onRowClick,
1718
+ enableColumnVirtualization = false,
1719
+ enableDynamicRowHeight = false,
1720
+ columnPersistence = false,
1721
+ showColumnSettings = true,
1722
+ hideGlobalSearch = false,
1723
+ globalSearchValue,
1724
+ onGlobalSearchChange
1604
1725
  }) {
1605
1726
  const data = useMemo2(() => {
1606
1727
  if (!Array.isArray(rawData)) return STABLE_EMPTY_DATA;
@@ -1608,7 +1729,8 @@ function BoltTable({
1608
1729
  return filtered.length > 0 ? filtered : STABLE_EMPTY_DATA;
1609
1730
  }, [rawData]);
1610
1731
  const initialColumns = useMemo2(() => {
1611
- if (!Array.isArray(rawInitialColumns)) return STABLE_EMPTY_COLS;
1732
+ if (!Array.isArray(rawInitialColumns))
1733
+ return STABLE_EMPTY_COLS;
1612
1734
  const safe = rawInitialColumns.filter(
1613
1735
  (col) => col != null && typeof col.key === "string"
1614
1736
  );
@@ -1673,6 +1795,106 @@ function BoltTable({
1673
1795
  () => /* @__PURE__ */ new Map()
1674
1796
  );
1675
1797
  const manuallyResizedRef = useRef4(/* @__PURE__ */ new Set());
1798
+ const persistenceAppliedRef = useRef4(false);
1799
+ React4.useEffect(() => {
1800
+ if (!columnPersistence || persistenceAppliedRef.current) return;
1801
+ persistenceAppliedRef.current = true;
1802
+ const {
1803
+ storageKey,
1804
+ persistOrder = true,
1805
+ persistWidths = true,
1806
+ persistVisibility = true,
1807
+ persistPinned = true
1808
+ } = columnPersistence;
1809
+ try {
1810
+ const raw = localStorage.getItem(`bt_${storageKey}`);
1811
+ if (!raw) return;
1812
+ const saved = JSON.parse(raw);
1813
+ if (persistOrder && saved.order) {
1814
+ setColumnOrder(saved.order);
1815
+ }
1816
+ if (persistWidths && saved.widths) {
1817
+ setColumnWidths(
1818
+ new Map(Object.entries(saved.widths).map(([k, v]) => [k, Number(v)]))
1819
+ );
1820
+ }
1821
+ if (persistVisibility && saved.hidden || persistPinned && saved.pinned) {
1822
+ setColumns(
1823
+ (prev) => prev.map((col) => {
1824
+ let updated = col;
1825
+ if (persistVisibility && saved.hidden && col.key in saved.hidden) {
1826
+ updated = { ...updated, hidden: saved.hidden[col.key] };
1827
+ }
1828
+ if (persistPinned && saved.pinned && col.key in saved.pinned) {
1829
+ updated = { ...updated, pinned: saved.pinned[col.key] };
1830
+ }
1831
+ return updated;
1832
+ })
1833
+ );
1834
+ }
1835
+ } catch {
1836
+ }
1837
+ }, [columnPersistence]);
1838
+ const persistColumnsToStorage = useCallback2(() => {
1839
+ if (!columnPersistence) return;
1840
+ const {
1841
+ storageKey,
1842
+ persistOrder = true,
1843
+ persistWidths = true,
1844
+ persistVisibility = true,
1845
+ persistPinned = true
1846
+ } = columnPersistence;
1847
+ try {
1848
+ const saved = {};
1849
+ if (persistOrder) saved.order = columnOrder;
1850
+ if (persistWidths) {
1851
+ const widths = {};
1852
+ columnWidths.forEach((v, k) => {
1853
+ widths[k] = v;
1854
+ });
1855
+ saved.widths = widths;
1856
+ }
1857
+ if (persistVisibility) {
1858
+ const hidden = {};
1859
+ columns.forEach((c) => {
1860
+ if (c.hidden) hidden[c.key] = true;
1861
+ });
1862
+ saved.hidden = hidden;
1863
+ }
1864
+ if (persistPinned) {
1865
+ const pinned = {};
1866
+ columns.forEach((c) => {
1867
+ if (c.pinned) pinned[c.key] = c.pinned;
1868
+ });
1869
+ saved.pinned = pinned;
1870
+ }
1871
+ localStorage.setItem(`bt_${storageKey}`, JSON.stringify(saved));
1872
+ } catch {
1873
+ }
1874
+ }, [columnPersistence, columnOrder, columnWidths, columns]);
1875
+ React4.useEffect(() => {
1876
+ if (!columnPersistence || !persistenceAppliedRef.current) return;
1877
+ persistColumnsToStorage();
1878
+ }, [columnPersistence, persistColumnsToStorage]);
1879
+ const [showColumnPicker, setShowColumnPicker] = useState3(false);
1880
+ const columnPickerRef = useRef4(null);
1881
+ React4.useEffect(() => {
1882
+ if (!showColumnPicker) return;
1883
+ const close = (e) => {
1884
+ if (columnPickerRef.current && !columnPickerRef.current.contains(e.target)) {
1885
+ setShowColumnPicker(false);
1886
+ }
1887
+ };
1888
+ const onKey = (e) => {
1889
+ if (e.key === "Escape") setShowColumnPicker(false);
1890
+ };
1891
+ document.addEventListener("mousedown", close);
1892
+ document.addEventListener("keydown", onKey);
1893
+ return () => {
1894
+ document.removeEventListener("mousedown", close);
1895
+ document.removeEventListener("keydown", onKey);
1896
+ };
1897
+ }, [showColumnPicker]);
1676
1898
  const columnsWithPersistedWidths = useMemo2(
1677
1899
  () => columns.map((col) => ({
1678
1900
  ...col,
@@ -1737,6 +1959,32 @@ function BoltTable({
1737
1959
  },
1738
1960
  [rowKey]
1739
1961
  );
1962
+ const deduplicatedRowKeys = useMemo2(() => {
1963
+ const seen = /* @__PURE__ */ new Map();
1964
+ return data.map((row, idx) => {
1965
+ const raw = getRowKey(row, idx);
1966
+ const count = seen.get(raw) ?? 0;
1967
+ seen.set(raw, count + 1);
1968
+ return count > 0 ? `${raw}__${idx}` : raw;
1969
+ });
1970
+ }, [data, getRowKey]);
1971
+ const hasDuplicateKeys = useMemo2(() => {
1972
+ const seen = /* @__PURE__ */ new Set();
1973
+ for (const row of data) {
1974
+ if (row == null) continue;
1975
+ const k = getRowKey(row, 0);
1976
+ if (seen.has(k)) return true;
1977
+ seen.add(k);
1978
+ }
1979
+ return false;
1980
+ }, [data, getRowKey]);
1981
+ const getSafeRowKey = useCallback2(
1982
+ (record, index) => {
1983
+ if (!hasDuplicateKeys) return getRowKey(record, index);
1984
+ return deduplicatedRowKeys[index] ?? getRowKey(record, index);
1985
+ },
1986
+ [getRowKey, hasDuplicateKeys, deduplicatedRowKeys]
1987
+ );
1740
1988
  const getRawRowKey = useCallback2(
1741
1989
  (record, index) => {
1742
1990
  if (record == null) return index;
@@ -1754,16 +2002,13 @@ function BoltTable({
1754
2002
  },
1755
2003
  [rowKey]
1756
2004
  );
1757
- const normalizedSelectedKeys = useMemo2(
1758
- () => {
1759
- const keys = rowSelection?.selectedRowKeys;
1760
- if (!Array.isArray(keys)) return [];
1761
- return keys.filter((k) => k != null).map((k) => String(k));
1762
- },
1763
- [rowSelection?.selectedRowKeys]
1764
- );
1765
- const getRowKeyRef = useRef4(getRowKey);
1766
- getRowKeyRef.current = getRowKey;
2005
+ const normalizedSelectedKeys = useMemo2(() => {
2006
+ const keys = rowSelection?.selectedRowKeys;
2007
+ if (!Array.isArray(keys)) return [];
2008
+ return keys.filter((k) => k != null).map((k) => String(k));
2009
+ }, [rowSelection?.selectedRowKeys]);
2010
+ const getRowKeyRef = useRef4(getSafeRowKey);
2011
+ getRowKeyRef.current = getSafeRowKey;
1767
2012
  const resolvedExpandedKeysRef = useRef4(resolvedExpandedKeys);
1768
2013
  resolvedExpandedKeysRef.current = resolvedExpandedKeys;
1769
2014
  const toggleExpandRef = useRef4(toggleExpand);
@@ -1946,7 +2191,9 @@ function BoltTable({
1946
2191
  }
1947
2192
  const scrollEl = tableAreaRef.current;
1948
2193
  if (!scrollEl) return;
1949
- const headers = scrollEl.querySelectorAll("[data-bt-header][data-column-key]");
2194
+ const headers = scrollEl.querySelectorAll(
2195
+ "[data-bt-header][data-column-key]"
2196
+ );
1950
2197
  let newOverId = null;
1951
2198
  headers.forEach((h) => {
1952
2199
  const key = h.dataset.columnKey;
@@ -1988,10 +2235,7 @@ function BoltTable({
1988
2235
  const newIndex = items.indexOf(currentOverId);
1989
2236
  if (oldIndex === -1 || newIndex === -1) return items;
1990
2237
  const newOrder = arrayMove(items, oldIndex, newIndex);
1991
- setTimeout(
1992
- () => onColumnOrderChangeRef.current?.(newOrder),
1993
- 0
1994
- );
2238
+ setTimeout(() => onColumnOrderChangeRef.current?.(newOrder), 0);
1995
2239
  return newOrder;
1996
2240
  });
1997
2241
  });
@@ -2091,9 +2335,7 @@ function BoltTable({
2091
2335
  [leftPinned, unpinned, rightPinned]
2092
2336
  );
2093
2337
  const freshOrderedColumns = useMemo2(() => {
2094
- const latestMap = new Map(
2095
- initialColumnsRef.current.map((c) => [c.key, c])
2096
- );
2338
+ const latestMap = new Map(initialColumnsRef.current.map((c) => [c.key, c]));
2097
2339
  return orderedColumns.map((col) => {
2098
2340
  if (col.key === "__select__" || col.key === "__expand__") return col;
2099
2341
  const latest = latestMap.get(col.key);
@@ -2150,22 +2392,27 @@ function BoltTable({
2150
2392
  };
2151
2393
  const [internalRowPinning, setInternalRowPinning] = useState3({ top: [], bottom: [] });
2152
2394
  const resolvedRowPinning = rowPinning === true ? internalRowPinning : rowPinning && typeof rowPinning === "object" ? rowPinning : void 0;
2153
- const handleRowPin = useCallback2((rk, pinned) => {
2154
- if (onRowPin) {
2155
- onRowPin(rk, pinned);
2156
- return;
2157
- }
2158
- if (rowPinning === true) {
2159
- setInternalRowPinning((prev) => {
2160
- const rkStr = String(rk);
2161
- const newTop = (prev.top ?? []).filter((k) => String(k) !== rkStr);
2162
- const newBottom = (prev.bottom ?? []).filter((k) => String(k) !== rkStr);
2163
- if (pinned === "top") newTop.push(rk);
2164
- else if (pinned === "bottom") newBottom.push(rk);
2165
- return { top: newTop, bottom: newBottom };
2166
- });
2167
- }
2168
- }, [onRowPin, rowPinning]);
2395
+ const handleRowPin = useCallback2(
2396
+ (rk, pinned) => {
2397
+ if (onRowPin) {
2398
+ onRowPin(rk, pinned);
2399
+ return;
2400
+ }
2401
+ if (rowPinning === true) {
2402
+ setInternalRowPinning((prev) => {
2403
+ const rkStr = String(rk);
2404
+ const newTop = (prev.top ?? []).filter((k) => String(k) !== rkStr);
2405
+ const newBottom = (prev.bottom ?? []).filter(
2406
+ (k) => String(k) !== rkStr
2407
+ );
2408
+ if (pinned === "top") newTop.push(rk);
2409
+ else if (pinned === "bottom") newBottom.push(rk);
2410
+ return { top: newTop, bottom: newBottom };
2411
+ });
2412
+ }
2413
+ },
2414
+ [onRowPin, rowPinning]
2415
+ );
2169
2416
  const onSortChangeRef = useRef4(onSortChange);
2170
2417
  onSortChangeRef.current = onSortChange;
2171
2418
  const [sortState, setSortState] = useState3({ key: "", direction: null });
@@ -2188,6 +2435,7 @@ function BoltTable({
2188
2435
  const [columnFilters, setColumnFilters] = useState3(
2189
2436
  {}
2190
2437
  );
2438
+ const [internalGlobalSearch, setInternalGlobalSearch] = useState3("");
2191
2439
  const handleColumnFilter = useCallback2(
2192
2440
  (columnKey, value) => {
2193
2441
  setColumnFilters((prev) => {
@@ -2212,6 +2460,20 @@ function BoltTable({
2212
2460
  columnsLookupRef.current = initialColumns;
2213
2461
  const processedData = useMemo2(() => {
2214
2462
  let result = data;
2463
+ const globalSearch = globalSearchValue ?? internalGlobalSearch;
2464
+ if (globalSearch) {
2465
+ const searchLower = globalSearch.toLowerCase();
2466
+ result = result.filter((row) => {
2467
+ if (row == null) return false;
2468
+ for (const key of Object.keys(row)) {
2469
+ const val = row[key];
2470
+ if (val != null && String(val).toLowerCase().includes(searchLower)) {
2471
+ return true;
2472
+ }
2473
+ }
2474
+ return false;
2475
+ });
2476
+ }
2215
2477
  if (!onFilterChangeRef.current) {
2216
2478
  const filterKeys = Object.keys(columnFilters);
2217
2479
  if (filterKeys.length > 0) {
@@ -2221,7 +2483,11 @@ function BoltTable({
2221
2483
  try {
2222
2484
  const col = columnsLookupRef.current.find((c) => c.key === key);
2223
2485
  if (typeof col?.filterFn === "function") {
2224
- return col.filterFn(columnFilters[key], row, col.dataIndex ?? key);
2486
+ return col.filterFn(
2487
+ columnFilters[key],
2488
+ row,
2489
+ col.dataIndex ?? key
2490
+ );
2225
2491
  }
2226
2492
  const cellVal = String(row[key] ?? "").toLowerCase();
2227
2493
  return cellVal.includes(columnFilters[key].toLowerCase());
@@ -2264,7 +2530,7 @@ function BoltTable({
2264
2530
  }
2265
2531
  }
2266
2532
  return result;
2267
- }, [data, sortState, columnFilters]);
2533
+ }, [data, sortState, columnFilters, globalSearchValue, internalGlobalSearch]);
2268
2534
  const pinnedRowCacheRef = useRef4(/* @__PURE__ */ new Map());
2269
2535
  const { pinnedTopRows, pinnedBottomRows, unpinnedProcessedData } = useMemo2(() => {
2270
2536
  if (!resolvedRowPinning || !resolvedRowPinning.top?.length && !resolvedRowPinning.bottom?.length) {
@@ -2276,19 +2542,23 @@ function BoltTable({
2276
2542
  };
2277
2543
  }
2278
2544
  const topKeySet = new Set((resolvedRowPinning.top ?? []).map(String));
2279
- const bottomKeySet = new Set((resolvedRowPinning.bottom ?? []).map(String));
2545
+ const bottomKeySet = new Set(
2546
+ (resolvedRowPinning.bottom ?? []).map(String)
2547
+ );
2280
2548
  const topMap = /* @__PURE__ */ new Map();
2281
2549
  const bottomMap = /* @__PURE__ */ new Map();
2282
2550
  const rest = [];
2283
2551
  processedData.forEach((row, idx) => {
2284
2552
  if (row == null) return;
2285
- const key = getRowKey(row, idx);
2553
+ const key = getSafeRowKey(row, idx);
2286
2554
  if (topKeySet.has(key)) {
2287
2555
  topMap.set(key, row);
2288
- if (keepPinnedRowsAcrossPages) pinnedRowCacheRef.current.set(key, row);
2556
+ if (keepPinnedRowsAcrossPages)
2557
+ pinnedRowCacheRef.current.set(key, row);
2289
2558
  } else if (bottomKeySet.has(key)) {
2290
2559
  bottomMap.set(key, row);
2291
- if (keepPinnedRowsAcrossPages) pinnedRowCacheRef.current.set(key, row);
2560
+ if (keepPinnedRowsAcrossPages)
2561
+ pinnedRowCacheRef.current.set(key, row);
2292
2562
  } else {
2293
2563
  rest.push(row);
2294
2564
  }
@@ -2306,7 +2576,8 @@ function BoltTable({
2306
2576
  }
2307
2577
  const allPinnedKeys = /* @__PURE__ */ new Set([...topKeySet, ...bottomKeySet]);
2308
2578
  for (const cachedKey of pinnedRowCacheRef.current.keys()) {
2309
- if (!allPinnedKeys.has(cachedKey)) pinnedRowCacheRef.current.delete(cachedKey);
2579
+ if (!allPinnedKeys.has(cachedKey))
2580
+ pinnedRowCacheRef.current.delete(cachedKey);
2310
2581
  }
2311
2582
  }
2312
2583
  const orderedTop = (resolvedRowPinning.top ?? []).map((k) => topMap.get(String(k))).filter((r) => r !== void 0);
@@ -2316,7 +2587,12 @@ function BoltTable({
2316
2587
  pinnedBottomRows: orderedBottom,
2317
2588
  unpinnedProcessedData: rest
2318
2589
  };
2319
- }, [processedData, resolvedRowPinning, getRowKey, keepPinnedRowsAcrossPages]);
2590
+ }, [
2591
+ processedData,
2592
+ resolvedRowPinning,
2593
+ getSafeRowKey,
2594
+ keepPinnedRowsAcrossPages
2595
+ ]);
2320
2596
  const pinnedTopHeight = pinnedTopRows.length * rowHeight;
2321
2597
  const pinnedBottomHeight = pinnedBottomRows.length * rowHeight;
2322
2598
  const pinnedTopKeySet = useMemo2(
@@ -2333,9 +2609,7 @@ function BoltTable({
2333
2609
  }, []);
2334
2610
  const [cellContextMenu, setCellContextMenu] = useState3(null);
2335
2611
  const cellMenuRef = useRef4(null);
2336
- const cellLongPressTimer = useRef4(
2337
- null
2338
- );
2612
+ const cellLongPressTimer = useRef4(null);
2339
2613
  const cellTouchStart = useRef4(null);
2340
2614
  const cancelCellLongPress = useCallback2(() => {
2341
2615
  if (cellLongPressTimer.current) {
@@ -2362,10 +2636,11 @@ function BoltTable({
2362
2636
  };
2363
2637
  }, [cellContextMenu]);
2364
2638
  const columnFiltersKey = Object.keys(columnFilters).sort().map((k) => `${k}:${columnFilters[k]}`).join("|");
2639
+ const activeGlobalSearch = globalSearchValue ?? internalGlobalSearch;
2365
2640
  React4.useEffect(() => {
2366
2641
  setInternalPage(1);
2367
2642
  tableAreaRef.current?.scrollTo({ top: 0 });
2368
- }, [columnFiltersKey]);
2643
+ }, [columnFiltersKey, activeGlobalSearch]);
2369
2644
  const DEFAULT_PAGE_SIZE = 15;
2370
2645
  const [internalPage, setInternalPage] = useState3(1);
2371
2646
  const [internalPageSize, setInternalPageSize] = useState3(DEFAULT_PAGE_SIZE);
@@ -2411,6 +2686,17 @@ function BoltTable({
2411
2686
  return paginatedData;
2412
2687
  }, [shimmerData, infiniteLoadingShimmer, paginatedData]);
2413
2688
  const measuredExpandedHeights = useRef4(/* @__PURE__ */ new Map());
2689
+ const measuredRowHeights = useRef4(/* @__PURE__ */ new Map());
2690
+ const handleRowHeightChange = useCallback2(
2691
+ (index, height) => {
2692
+ if (!enableDynamicRowHeight) return;
2693
+ const prev = measuredRowHeights.current.get(index);
2694
+ if (prev === height) return;
2695
+ measuredRowHeights.current.set(index, height);
2696
+ rowVirtualizerRef.current?.measure();
2697
+ },
2698
+ [enableDynamicRowHeight]
2699
+ );
2414
2700
  const expandedRowMeasureRafRef = useRef4(null);
2415
2701
  const handleExpandedRowResize = useCallback2(
2416
2702
  (rk, contentHeight) => {
@@ -2435,23 +2721,73 @@ function BoltTable({
2435
2721
  if (shimmerData) return rowHeight;
2436
2722
  const item = displayData[index];
2437
2723
  if (!item) return rowHeight;
2438
- const key = getRowKey(item, index);
2439
- if (!resolvedExpandedKeys.has(key)) return rowHeight;
2724
+ const baseHeight = enableDynamicRowHeight ? measuredRowHeights.current.get(index) ?? rowHeight : rowHeight;
2725
+ const key = getSafeRowKey(item, index);
2726
+ if (!resolvedExpandedKeys.has(key)) return baseHeight;
2440
2727
  const cached = measuredExpandedHeights.current.get(key);
2441
- return cached ? rowHeight + cached : rowHeight + expandedRowHeight;
2728
+ return cached ? baseHeight + cached : baseHeight + expandedRowHeight;
2442
2729
  },
2443
2730
  overscan: 5,
2444
2731
  getItemKey: (index) => {
2445
2732
  if (shimmerData) return `__shimmer_${index}__`;
2446
2733
  const item = displayData[index];
2447
2734
  if (!item) return `__fallback_${index}__`;
2448
- return getRowKey(item, index);
2735
+ return getSafeRowKey(item, index);
2449
2736
  },
2450
2737
  paddingStart: pinnedTopHeight,
2451
2738
  paddingEnd: pinnedBottomHeight
2452
2739
  });
2453
2740
  const rowVirtualizerRef = useRef4(rowVirtualizer);
2454
2741
  rowVirtualizerRef.current = rowVirtualizer;
2742
+ const scrollLeftRef = useRef4(0);
2743
+ const [visibleColumnRange, setVisibleColumnRange] = useState3(null);
2744
+ React4.useEffect(() => {
2745
+ if (!enableColumnVirtualization) return;
2746
+ const el = tableAreaRef.current;
2747
+ if (!el) return;
2748
+ const updateVisibleColumns = () => {
2749
+ const scrollLeft = el.scrollLeft;
2750
+ scrollLeftRef.current = scrollLeft;
2751
+ const viewportWidth = el.clientWidth;
2752
+ const viewStart = scrollLeft;
2753
+ const viewEnd = scrollLeft + viewportWidth;
2754
+ let cumWidth = 0;
2755
+ let startIdx = -1;
2756
+ let endIdx = orderedColumns.length - 1;
2757
+ for (let i = 0; i < orderedColumns.length; i++) {
2758
+ const col = orderedColumns[i];
2759
+ const colWidth = col.width ?? 150;
2760
+ const colStart = cumWidth;
2761
+ const colEnd = cumWidth + colWidth;
2762
+ cumWidth = colEnd;
2763
+ if (col.pinned) continue;
2764
+ if (startIdx === -1 && colEnd > viewStart) {
2765
+ startIdx = Math.max(0, i - 1);
2766
+ }
2767
+ if (colStart > viewEnd) {
2768
+ endIdx = Math.min(orderedColumns.length - 1, i + 1);
2769
+ break;
2770
+ }
2771
+ }
2772
+ if (startIdx === -1) startIdx = 0;
2773
+ setVisibleColumnRange((prev) => {
2774
+ if (prev && prev.start === startIdx && prev.end === endIdx) return prev;
2775
+ return { start: startIdx, end: endIdx };
2776
+ });
2777
+ };
2778
+ updateVisibleColumns();
2779
+ el.addEventListener("scroll", updateVisibleColumns, { passive: true });
2780
+ return () => el.removeEventListener("scroll", updateVisibleColumns);
2781
+ }, [enableColumnVirtualization, orderedColumns]);
2782
+ const virtualizedColumns = useMemo2(() => {
2783
+ if (!enableColumnVirtualization || !visibleColumnRange)
2784
+ return freshOrderedColumns;
2785
+ return freshOrderedColumns.filter((col, idx) => {
2786
+ if (col.pinned) return true;
2787
+ if (col.key === "__select__" || col.key === "__expand__") return true;
2788
+ return idx >= visibleColumnRange.start && idx <= visibleColumnRange.end;
2789
+ });
2790
+ }, [enableColumnVirtualization, visibleColumnRange, freshOrderedColumns]);
2455
2791
  const resolvedExpandedKeysFingerprint = Array.from(resolvedExpandedKeys).sort().join(",");
2456
2792
  React4.useLayoutEffect(() => {
2457
2793
  rowVirtualizer.measure();
@@ -2518,7 +2854,10 @@ function BoltTable({
2518
2854
  }, [pgCurrent, needsClientPagination]);
2519
2855
  const getPageNumbers = () => {
2520
2856
  if (totalPages <= 7)
2521
- return Array.from({ length: totalPages }, (_, i) => i + 1);
2857
+ return Array.from(
2858
+ { length: totalPages },
2859
+ (_, i) => i + 1
2860
+ );
2522
2861
  const leftSibling = Math.max(currentPage - 1, 2);
2523
2862
  const showLeftEllipsis = leftSibling > 2;
2524
2863
  const rightSibling = Math.min(currentPage + 1, totalPages - 1);
@@ -2529,7 +2868,10 @@ function BoltTable({
2529
2868
  return [
2530
2869
  1,
2531
2870
  "ellipsis-left",
2532
- ...Array.from({ length: 5 }, (_, i) => totalPages - 4 + i)
2871
+ ...Array.from(
2872
+ { length: 5 },
2873
+ (_, i) => totalPages - 4 + i
2874
+ )
2533
2875
  ];
2534
2876
  return [
2535
2877
  1,
@@ -2600,6 +2942,189 @@ function BoltTable({
2600
2942
  }
2601
2943
  ${onRowClick ? "[data-bt-cell] { cursor: pointer; }" : ""}
2602
2944
  ` }),
2945
+ (!hideGlobalSearch || showColumnSettings) && /* @__PURE__ */ jsxs5(
2946
+ "div",
2947
+ {
2948
+ style: {
2949
+ display: "flex",
2950
+ alignItems: "center",
2951
+ gap: 8,
2952
+ padding: "6px 8px",
2953
+ borderBottom: "1px solid rgba(128,128,128,0.2)",
2954
+ fontSize: 12,
2955
+ flexShrink: 0
2956
+ },
2957
+ children: [
2958
+ !hideGlobalSearch && /* @__PURE__ */ jsxs5(
2959
+ "div",
2960
+ {
2961
+ style: {
2962
+ display: "flex",
2963
+ alignItems: "center",
2964
+ gap: 4,
2965
+ flex: "1 1 0%",
2966
+ position: "relative"
2967
+ },
2968
+ children: [
2969
+ /* @__PURE__ */ jsx5(
2970
+ "span",
2971
+ {
2972
+ style: { display: "flex", color: "GrayText", flexShrink: 0 },
2973
+ children: icons?.search ?? /* @__PURE__ */ jsx5(SearchIcon, { style: { width: 14, height: 14 } })
2974
+ }
2975
+ ),
2976
+ /* @__PURE__ */ jsx5(
2977
+ "input",
2978
+ {
2979
+ type: "text",
2980
+ placeholder: "Search all columns...",
2981
+ value: globalSearchValue ?? internalGlobalSearch,
2982
+ onChange: (e) => {
2983
+ const v = e.target.value;
2984
+ if (onGlobalSearchChange) onGlobalSearchChange(v);
2985
+ else setInternalGlobalSearch(v);
2986
+ },
2987
+ style: {
2988
+ flex: "1 1 0%",
2989
+ border: "none",
2990
+ outline: "none",
2991
+ background: "transparent",
2992
+ font: "inherit",
2993
+ color: "inherit",
2994
+ padding: "4px 6px",
2995
+ minWidth: 0
2996
+ }
2997
+ }
2998
+ ),
2999
+ (globalSearchValue ?? internalGlobalSearch) && /* @__PURE__ */ jsx5(
3000
+ "button",
3001
+ {
3002
+ type: "button",
3003
+ onClick: () => {
3004
+ if (onGlobalSearchChange) onGlobalSearchChange("");
3005
+ else setInternalGlobalSearch("");
3006
+ },
3007
+ style: {
3008
+ display: "flex",
3009
+ alignItems: "center",
3010
+ justifyContent: "center",
3011
+ background: "none",
3012
+ border: "none",
3013
+ cursor: "pointer",
3014
+ padding: 2,
3015
+ color: "GrayText",
3016
+ flexShrink: 0
3017
+ },
3018
+ children: icons?.close ?? /* @__PURE__ */ jsx5(XIcon, { style: { width: 12, height: 12 } })
3019
+ }
3020
+ )
3021
+ ]
3022
+ }
3023
+ ),
3024
+ showColumnSettings && /* @__PURE__ */ jsxs5("div", { style: { position: "relative", flexShrink: 0 }, children: [
3025
+ /* @__PURE__ */ jsxs5(
3026
+ "button",
3027
+ {
3028
+ type: "button",
3029
+ onClick: () => setShowColumnPicker((p) => !p),
3030
+ style: {
3031
+ display: "flex",
3032
+ alignItems: "center",
3033
+ justifyContent: "center",
3034
+ background: "none",
3035
+ border: "1px solid rgba(128,128,128,0.2)",
3036
+ borderRadius: 4,
3037
+ cursor: "pointer",
3038
+ padding: "4px 6px",
3039
+ color: "inherit",
3040
+ gap: 4,
3041
+ fontSize: 12
3042
+ },
3043
+ title: "Column settings",
3044
+ children: [
3045
+ icons?.columns ?? /* @__PURE__ */ jsx5(ColumnsIcon, { style: { width: 14, height: 14 } }),
3046
+ /* @__PURE__ */ jsx5("span", { children: "Columns" })
3047
+ ]
3048
+ }
3049
+ ),
3050
+ showColumnPicker && /* @__PURE__ */ jsx5(
3051
+ "div",
3052
+ {
3053
+ ref: columnPickerRef,
3054
+ style: {
3055
+ position: "absolute",
3056
+ top: "100%",
3057
+ right: 0,
3058
+ zIndex: 99999,
3059
+ minWidth: 200,
3060
+ maxHeight: 320,
3061
+ overflowY: "auto",
3062
+ borderRadius: 8,
3063
+ border: "1px solid rgba(128,128,128,0.2)",
3064
+ boxShadow: "0 4px 24px rgba(0,0,0,0.12)",
3065
+ backdropFilter: "blur(16px)",
3066
+ WebkitBackdropFilter: "blur(16px)",
3067
+ backgroundColor: "rgba(128,128,128,0.08)",
3068
+ padding: "4px 0",
3069
+ marginTop: 4
3070
+ },
3071
+ children: initialColumns.filter(
3072
+ (c) => c.key !== "__select__" && c.key !== "__expand__"
3073
+ ).map((col) => {
3074
+ const current = columns.find((c) => c.key === col.key);
3075
+ const isHidden = current?.hidden ?? false;
3076
+ const isPinned = !!current?.pinned;
3077
+ return /* @__PURE__ */ jsxs5(
3078
+ "label",
3079
+ {
3080
+ style: {
3081
+ display: "flex",
3082
+ alignItems: "center",
3083
+ gap: 8,
3084
+ padding: "6px 12px",
3085
+ cursor: isPinned ? "not-allowed" : "pointer",
3086
+ opacity: isPinned ? 0.5 : 1,
3087
+ fontSize: 12
3088
+ },
3089
+ children: [
3090
+ /* @__PURE__ */ jsx5(
3091
+ "input",
3092
+ {
3093
+ type: "checkbox",
3094
+ checked: !isHidden,
3095
+ disabled: isPinned,
3096
+ onChange: () => {
3097
+ if (isPinned) return;
3098
+ handleToggleHide(col.key);
3099
+ },
3100
+ style: {
3101
+ cursor: isPinned ? "not-allowed" : "pointer",
3102
+ accentColor
3103
+ }
3104
+ }
3105
+ ),
3106
+ /* @__PURE__ */ jsx5(
3107
+ "span",
3108
+ {
3109
+ style: {
3110
+ overflow: "hidden",
3111
+ textOverflow: "ellipsis",
3112
+ whiteSpace: "nowrap"
3113
+ },
3114
+ children: typeof col.title === "string" ? col.title : col.key
3115
+ }
3116
+ )
3117
+ ]
3118
+ },
3119
+ col.key
3120
+ );
3121
+ })
3122
+ }
3123
+ )
3124
+ ] })
3125
+ ]
3126
+ }
3127
+ ),
2603
3128
  /* @__PURE__ */ jsx5(
2604
3129
  "div",
2605
3130
  {
@@ -2744,19 +3269,20 @@ function BoltTable({
2744
3269
  ...isEmpty ? { height: "100%" } : {}
2745
3270
  },
2746
3271
  onContextMenu: (e) => {
2747
- const cell = e.target.closest("[data-bt-cell]");
3272
+ const cell = e.target.closest(
3273
+ "[data-bt-cell]"
3274
+ );
2748
3275
  if (!cell) return;
2749
3276
  const rk = cell.dataset.rowKey;
2750
3277
  const ck = cell.dataset.columnKey;
2751
3278
  if (!rk || !ck) return;
2752
- const col = freshOrderedColumns.find(
2753
- (c) => c.key === ck
2754
- );
3279
+ const col = freshOrderedColumns.find((c) => c.key === ck);
2755
3280
  const hasCopy = !!col?.copy;
2756
3281
  const hasRowPin = !!rowPinning;
2757
3282
  const hasCellItems = col?.columnCellContextMenuItems && col.columnCellContextMenuItems.length > 0;
2758
3283
  const hasEdit = !!col?.editable && !col?.render && !!onEdit;
2759
- if (!hasCopy && !hasRowPin && !hasCellItems && !hasEdit) return;
3284
+ if (!hasCopy && !hasRowPin && !hasCellItems && !hasEdit)
3285
+ return;
2760
3286
  e.preventDefault();
2761
3287
  setCellContextMenu({
2762
3288
  x: Math.min(e.clientX, window.innerWidth - 200),
@@ -2767,7 +3293,9 @@ function BoltTable({
2767
3293
  },
2768
3294
  onTouchStart: (e) => {
2769
3295
  cancelCellLongPress();
2770
- const cell = e.target.closest("[data-bt-cell]");
3296
+ const cell = e.target.closest(
3297
+ "[data-bt-cell]"
3298
+ );
2771
3299
  if (!cell) return;
2772
3300
  const touch = e.touches[0];
2773
3301
  cellTouchStart.current = {
@@ -2779,14 +3307,13 @@ function BoltTable({
2779
3307
  cellLongPressTimer.current = setTimeout(() => {
2780
3308
  cellLongPressTimer.current = null;
2781
3309
  if (!rk || !ck) return;
2782
- const col = freshOrderedColumns.find(
2783
- (c) => c.key === ck
2784
- );
3310
+ const col = freshOrderedColumns.find((c) => c.key === ck);
2785
3311
  const hasCopy = !!col?.copy;
2786
3312
  const hasRowPin = !!rowPinning;
2787
3313
  const hasCellItems = col?.columnCellContextMenuItems && col.columnCellContextMenuItems.length > 0;
2788
3314
  const hasEdit = !!col?.editable && !col?.render && !!onEdit;
2789
- if (!hasCopy && !hasRowPin && !hasCellItems && !hasEdit) return;
3315
+ if (!hasCopy && !hasRowPin && !hasCellItems && !hasEdit)
3316
+ return;
2790
3317
  setCellContextMenu({
2791
3318
  x: Math.min(touch.clientX, window.innerWidth - 200),
2792
3319
  y: Math.min(touch.clientY, window.innerHeight - 200),
@@ -2807,7 +3334,8 @@ function BoltTable({
2807
3334
  onTouchCancel: cancelCellLongPress,
2808
3335
  onClick: onRowClick ? (e) => {
2809
3336
  const target = e.target;
2810
- if (target.closest("input, button, a, select, textarea")) return;
3337
+ if (target.closest("input, button, a, select, textarea"))
3338
+ return;
2811
3339
  const cell = target.closest("[data-bt-cell]");
2812
3340
  if (!cell) return;
2813
3341
  const rk = cell.dataset.rowKey;
@@ -2815,21 +3343,21 @@ function BoltTable({
2815
3343
  for (let i = 0; i < displayData.length; i++) {
2816
3344
  const row = displayData[i];
2817
3345
  if (row == null) continue;
2818
- if (getRowKey(row, i) === rk) {
3346
+ if (getSafeRowKey(row, i) === rk) {
2819
3347
  onRowClick(row, i, e);
2820
3348
  return;
2821
3349
  }
2822
3350
  }
2823
3351
  for (let i = 0; i < pinnedTopRows.length; i++) {
2824
3352
  if (pinnedTopRows[i] == null) continue;
2825
- if (getRowKey(pinnedTopRows[i], i) === rk) {
3353
+ if (getSafeRowKey(pinnedTopRows[i], i) === rk) {
2826
3354
  onRowClick(pinnedTopRows[i], i, e);
2827
3355
  return;
2828
3356
  }
2829
3357
  }
2830
3358
  for (let i = 0; i < pinnedBottomRows.length; i++) {
2831
3359
  if (pinnedBottomRows[i] == null) continue;
2832
- if (getRowKey(pinnedBottomRows[i], i) === rk) {
3360
+ if (getSafeRowKey(pinnedBottomRows[i], i) === rk) {
2833
3361
  onRowClick(pinnedBottomRows[i], i, e);
2834
3362
  return;
2835
3363
  }
@@ -2939,7 +3467,11 @@ function BoltTable({
2939
3467
  });
2940
3468
  }
2941
3469
  },
2942
- style: { cursor: "pointer", accentColor, backgroundColor: "#94A3B8" }
3470
+ style: {
3471
+ cursor: "pointer",
3472
+ accentColor,
3473
+ backgroundColor: "#94A3B8"
3474
+ }
2943
3475
  }
2944
3476
  )
2945
3477
  },
@@ -2999,7 +3531,10 @@ function BoltTable({
2999
3531
  filterValue: columnFilters[column.key] ?? "",
3000
3532
  onFilter: handleColumnFilter,
3001
3533
  onClearFilter: handleClearFilter,
3002
- customContextMenuItems: column.columnHeaderContextMenuItems ? [...columnContextMenuItems ?? [], ...column.columnHeaderContextMenuItems] : columnContextMenuItems,
3534
+ customContextMenuItems: column.columnHeaderContextMenuItems ? [
3535
+ ...columnContextMenuItems ?? [],
3536
+ ...column.columnHeaderContextMenuItems
3537
+ ] : columnContextMenuItems,
3003
3538
  disabledFilters,
3004
3539
  headerGridRow: leafGridRow,
3005
3540
  headerHeight: leafHeight,
@@ -3051,14 +3586,14 @@ function BoltTable({
3051
3586
  TableBody_default,
3052
3587
  {
3053
3588
  data: displayData,
3054
- orderedColumns: freshOrderedColumns,
3589
+ orderedColumns: virtualizedColumns,
3055
3590
  rowVirtualizer,
3056
3591
  columnOffsets,
3057
3592
  styles,
3058
3593
  classNames,
3059
3594
  rowSelection: !showShimmer ? rowSelection : void 0,
3060
3595
  normalizedSelectedKeys,
3061
- getRowKey,
3596
+ getRowKey: getSafeRowKey,
3062
3597
  getRawRowKey,
3063
3598
  expandable: !showShimmer ? expandable : void 0,
3064
3599
  resolvedExpandedKeys,
@@ -3079,7 +3614,9 @@ function BoltTable({
3079
3614
  bodyGridRow: hasColumnGroups ? 3 : 2,
3080
3615
  onEdit,
3081
3616
  editingCell,
3082
- onEditComplete: handleEditComplete
3617
+ onEditComplete: handleEditComplete,
3618
+ enableDynamicRowHeight,
3619
+ onRowHeightChange: handleRowHeightChange
3083
3620
  }
3084
3621
  )
3085
3622
  ]
@@ -3109,39 +3646,53 @@ function BoltTable({
3109
3646
  ...styles.pagination
3110
3647
  },
3111
3648
  children: [
3112
- /* @__PURE__ */ jsx5("div", { style: { display: "flex", flex: "1 1 0%", alignItems: "center" }, children: (() => {
3113
- const rangeStart = total > 0 ? (currentPage - 1) * pageSize + 1 : 0;
3114
- const rangeEnd = Math.min(currentPage * pageSize, total);
3115
- return typeof pagination === "object" && pagination?.showTotal ? /* @__PURE__ */ jsxs5(
3116
- "span",
3117
- {
3118
- className: classNames.paginationInfo ?? "",
3119
- style: { color: "GrayText", fontSize: 12, ...styles.paginationInfo },
3120
- children: [
3121
- "Showing",
3122
- " ",
3123
- pagination.showTotal(total, [rangeStart, rangeEnd]),
3124
- " of",
3125
- " ",
3126
- total,
3127
- " items"
3128
- ]
3129
- }
3130
- ) : /* @__PURE__ */ jsxs5(
3131
- "span",
3132
- {
3133
- className: classNames.paginationInfo ?? "",
3134
- style: { color: "GrayText", fontSize: 12, ...styles.paginationInfo },
3135
- children: [
3136
- rangeStart,
3137
- "\u2013",
3138
- rangeEnd,
3139
- " of ",
3140
- total
3141
- ]
3142
- }
3143
- );
3144
- })() }),
3649
+ /* @__PURE__ */ jsx5(
3650
+ "div",
3651
+ {
3652
+ style: { display: "flex", flex: "1 1 0%", alignItems: "center" },
3653
+ children: (() => {
3654
+ const rangeStart = total > 0 ? (currentPage - 1) * pageSize + 1 : 0;
3655
+ const rangeEnd = Math.min(currentPage * pageSize, total);
3656
+ return typeof pagination === "object" && pagination?.showTotal ? /* @__PURE__ */ jsxs5(
3657
+ "span",
3658
+ {
3659
+ className: classNames.paginationInfo ?? "",
3660
+ style: {
3661
+ color: "GrayText",
3662
+ fontSize: 12,
3663
+ ...styles.paginationInfo
3664
+ },
3665
+ children: [
3666
+ "Showing",
3667
+ " ",
3668
+ pagination.showTotal(total, [rangeStart, rangeEnd]),
3669
+ " of",
3670
+ " ",
3671
+ total,
3672
+ " items"
3673
+ ]
3674
+ }
3675
+ ) : /* @__PURE__ */ jsxs5(
3676
+ "span",
3677
+ {
3678
+ className: classNames.paginationInfo ?? "",
3679
+ style: {
3680
+ color: "GrayText",
3681
+ fontSize: 12,
3682
+ ...styles.paginationInfo
3683
+ },
3684
+ children: [
3685
+ rangeStart,
3686
+ "\u2013",
3687
+ rangeEnd,
3688
+ " of ",
3689
+ total
3690
+ ]
3691
+ }
3692
+ );
3693
+ })()
3694
+ }
3695
+ ),
3145
3696
  /* @__PURE__ */ jsxs5(
3146
3697
  "div",
3147
3698
  {
@@ -3424,9 +3975,7 @@ function BoltTable({
3424
3975
  (c) => c.key === cellContextMenu.columnKey
3425
3976
  );
3426
3977
  const isPinnedTop = pinnedTopKeySet.has(cellContextMenu.rowKey);
3427
- const isPinnedBottom = pinnedBottomKeySet.has(
3428
- cellContextMenu.rowKey
3429
- );
3978
+ const isPinnedBottom = pinnedBottomKeySet.has(cellContextMenu.rowKey);
3430
3979
  const hasCopy = !!menuCol?.copy;
3431
3980
  const hasRowPin = !!rowPinning;
3432
3981
  const hasEdit = !!menuCol?.editable && !menuCol?.render && !!onEdit;
@@ -3439,7 +3988,7 @@ function BoltTable({
3439
3988
  ];
3440
3989
  for (let i = 0; i < allRows.length; i++) {
3441
3990
  if (allRows[i] == null) continue;
3442
- const rk = getRowKey(allRows[i], i);
3991
+ const rk = getSafeRowKey(allRows[i], i);
3443
3992
  if (rk === cellContextMenu.rowKey) {
3444
3993
  menuRecord = allRows[i];
3445
3994
  menuRowIndex = i;
@@ -3641,7 +4190,20 @@ function BoltTable({
3641
4190
  setCellContextMenu(null);
3642
4191
  },
3643
4192
  children: [
3644
- item.icon && /* @__PURE__ */ jsx5("span", { style: { display: "flex", width: 14, height: 14, alignItems: "center", justifyContent: "center", flexShrink: 0 }, children: item.icon }),
4193
+ item.icon && /* @__PURE__ */ jsx5(
4194
+ "span",
4195
+ {
4196
+ style: {
4197
+ display: "flex",
4198
+ width: 14,
4199
+ height: 14,
4200
+ alignItems: "center",
4201
+ justifyContent: "center",
4202
+ flexShrink: 0
4203
+ },
4204
+ children: item.icon
4205
+ }
4206
+ ),
3645
4207
  item.label
3646
4208
  ]
3647
4209
  },