bolt-table 0.1.25 → 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.js CHANGED
@@ -124,6 +124,18 @@ var EyeOffIcon = ({ style, className }) => /* @__PURE__ */ (0, import_jsx_runtim
124
124
  /* @__PURE__ */ (0, import_jsx_runtime.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" }),
125
125
  /* @__PURE__ */ (0, import_jsx_runtime.jsx)("line", { x1: "2", x2: "22", y1: "2", y2: "22" })
126
126
  ] });
127
+ var SearchIcon = ({ style, className }) => /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("svg", { ...svgBase, style, className, children: [
128
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)("circle", { cx: "11", cy: "11", r: "8" }),
129
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)("path", { d: "m21 21-4.3-4.3" })
130
+ ] });
131
+ var ColumnsIcon = ({ style, className }) => /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("svg", { ...svgBase, style, className, children: [
132
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)("rect", { width: "18", height: "18", x: "3", y: "3", rx: "2", ry: "2" }),
133
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)("line", { x1: "12", x2: "12", y1: "3", y2: "21" })
134
+ ] });
135
+ var XIcon = ({ style, className }) => /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("svg", { ...svgBase, style, className, children: [
136
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)("path", { d: "M18 6 6 18" }),
137
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)("path", { d: "m6 6 12 12" })
138
+ ] });
127
139
 
128
140
  // src/DraggableHeader.tsx
129
141
  var import_jsx_runtime2 = require("react/jsx-runtime");
@@ -823,7 +835,15 @@ var EditableCell = ({
823
835
  onEdit(coerced, record, column.dataIndex, rowIndex);
824
836
  }
825
837
  onEditComplete();
826
- }, [draft, value, column.dataIndex, record, rowIndex, onEdit, onEditComplete]);
838
+ }, [
839
+ draft,
840
+ value,
841
+ column.dataIndex,
842
+ record,
843
+ rowIndex,
844
+ onEdit,
845
+ onEditComplete
846
+ ]);
827
847
  const cancel = (0, import_react3.useCallback)(() => {
828
848
  onEditComplete();
829
849
  }, [onEditComplete]);
@@ -925,7 +945,11 @@ var Cell = import_react3.default.memo(
925
945
  rowSelection.onSelect?.(record, true, [record], e.nativeEvent);
926
946
  rowSelection.onChange?.([rawKey], [record], { type: "single" });
927
947
  },
928
- style: { cursor: "pointer", accentColor }
948
+ style: {
949
+ cursor: "pointer",
950
+ accentColor,
951
+ backgroundColor: "#94A3B8"
952
+ }
929
953
  }
930
954
  ) : /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(
931
955
  "input",
@@ -951,7 +975,11 @@ var Cell = import_react3.default.memo(
951
975
  type: "multiple"
952
976
  });
953
977
  },
954
- style: { cursor: "pointer", accentColor, colorScheme: "light dark" }
978
+ style: {
979
+ cursor: "pointer",
980
+ accentColor,
981
+ backgroundColor: "#94A3B8"
982
+ }
955
983
  }
956
984
  );
957
985
  return /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(
@@ -1087,6 +1115,33 @@ var MeasuredExpandedRow = import_react3.default.memo(
1087
1115
  }
1088
1116
  );
1089
1117
  MeasuredExpandedRow.displayName = "MeasuredExpandedRow";
1118
+ var DynamicRowMeasurer = import_react3.default.memo(
1119
+ ({
1120
+ index,
1121
+ onHeightChange,
1122
+ children
1123
+ }) => {
1124
+ const ref = (0, import_react3.useRef)(null);
1125
+ const onHeightChangeRef = (0, import_react3.useRef)(onHeightChange);
1126
+ (0, import_react3.useEffect)(() => {
1127
+ onHeightChangeRef.current = onHeightChange;
1128
+ }, [onHeightChange]);
1129
+ (0, import_react3.useEffect)(() => {
1130
+ const el = ref.current;
1131
+ if (!el) return;
1132
+ const observer = new ResizeObserver((entries) => {
1133
+ const height = entries[0]?.borderBoxSize?.[0]?.blockSize;
1134
+ if (height != null && height > 0) {
1135
+ onHeightChangeRef.current(index, Math.ceil(height));
1136
+ }
1137
+ });
1138
+ observer.observe(el);
1139
+ return () => observer.disconnect();
1140
+ }, [index]);
1141
+ return /* @__PURE__ */ (0, import_jsx_runtime4.jsx)("div", { ref, children });
1142
+ }
1143
+ );
1144
+ DynamicRowMeasurer.displayName = "DynamicRowMeasurer";
1090
1145
  var TableBody = ({
1091
1146
  data,
1092
1147
  orderedColumns,
@@ -1116,11 +1171,16 @@ var TableBody = ({
1116
1171
  bodyGridRow = 2,
1117
1172
  onEdit,
1118
1173
  editingCell,
1119
- onEditComplete
1174
+ onEditComplete,
1175
+ enableDynamicRowHeight = false,
1176
+ onRowHeightChange
1120
1177
  }) => {
1121
1178
  const virtualItems = rowVirtualizer.getVirtualItems();
1122
1179
  const totalSize = rowVirtualizer.getTotalSize();
1123
- const selectedKeySet = (0, import_react3.useMemo)(() => new Set(normalizedSelectedKeys), [normalizedSelectedKeys]);
1180
+ const selectedKeySet = (0, import_react3.useMemo)(
1181
+ () => new Set(normalizedSelectedKeys),
1182
+ [normalizedSelectedKeys]
1183
+ );
1124
1184
  const safeData = data ?? [];
1125
1185
  const safeColumns = orderedColumns ?? [];
1126
1186
  const allDataForSelection = (0, import_react3.useMemo)(() => {
@@ -1203,15 +1263,58 @@ var TableBody = ({
1203
1263
  top: `${virtualRow.start}px`,
1204
1264
  left: 0,
1205
1265
  right: 0,
1206
- height: `${virtualRow.size}px`,
1207
- ...rowSty
1266
+ height: enableDynamicRowHeight ? void 0 : `${virtualRow.size}px`,
1267
+ minHeight: enableDynamicRowHeight ? `${rowHeight}px` : void 0
1208
1268
  },
1209
- children: /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(
1269
+ children: enableDynamicRowHeight && onRowHeightChange && colIndex === 0 ? /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(
1270
+ DynamicRowMeasurer,
1271
+ {
1272
+ index: virtualRow.index,
1273
+ onHeightChange: onRowHeightChange,
1274
+ children: /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(
1275
+ "div",
1276
+ {
1277
+ style: {
1278
+ minHeight: `${rowHeight}px`,
1279
+ position: "relative",
1280
+ ...rowSty
1281
+ },
1282
+ children: /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(
1283
+ Cell,
1284
+ {
1285
+ value: cellValue,
1286
+ record: row,
1287
+ column: col,
1288
+ rowIndex: virtualRow.index,
1289
+ classNames,
1290
+ styles,
1291
+ isSelected,
1292
+ isExpanded,
1293
+ rowSelection,
1294
+ normalizedSelectedKeys,
1295
+ rowKey,
1296
+ allData: allDataForSelection,
1297
+ getRowKey,
1298
+ getRawRowKey,
1299
+ accentColor,
1300
+ isLoading: isRowShimmer,
1301
+ recordFingerprint,
1302
+ onEdit,
1303
+ isEditing: editingCell?.rowKey === rowKey && editingCell?.columnKey === col.key,
1304
+ onEditComplete
1305
+ }
1306
+ )
1307
+ }
1308
+ )
1309
+ }
1310
+ ) : /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(
1210
1311
  "div",
1211
1312
  {
1212
1313
  style: {
1213
- height: `${rowHeight}px`,
1214
- position: "relative"
1314
+ height: enableDynamicRowHeight ? void 0 : `${rowHeight}px`,
1315
+ minHeight: enableDynamicRowHeight ? `${rowHeight}px` : void 0,
1316
+ position: "relative",
1317
+ ...rowSty
1215
1318
  },
1216
1319
  children: /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(
1217
1320
  Cell,
@@ -1266,7 +1369,12 @@ var TableBody = ({
1266
1369
  if (!(resolvedExpandedKeys?.has(rk) ?? false)) return null;
1267
1370
  let expandedRenderResult = null;
1268
1371
  try {
1269
- expandedRenderResult = expandable.expandedRowRender(row, virtualRow.index, 0, true);
1372
+ expandedRenderResult = expandable.expandedRowRender(
1373
+ row,
1374
+ virtualRow.index,
1375
+ 0,
1376
+ true
1377
+ );
1270
1378
  } catch {
1271
1379
  }
1272
1380
  const expandedContent = /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(
@@ -1634,7 +1742,14 @@ function BoltTable({
1634
1742
  onCopy,
1635
1743
  keepPinnedRowsAcrossPages,
1636
1744
  onEdit,
1637
- onRowClick
1745
+ onRowClick,
1746
+ enableColumnVirtualization = false,
1747
+ enableDynamicRowHeight = false,
1748
+ columnPersistence = false,
1749
+ showColumnSettings = true,
1750
+ hideGlobalSearch = false,
1751
+ globalSearchValue,
1752
+ onGlobalSearchChange
1638
1753
  }) {
1639
1754
  const data = (0, import_react4.useMemo)(() => {
1640
1755
  if (!Array.isArray(rawData)) return STABLE_EMPTY_DATA;
@@ -1642,7 +1757,8 @@ function BoltTable({
1642
1757
  return filtered.length > 0 ? filtered : STABLE_EMPTY_DATA;
1643
1758
  }, [rawData]);
1644
1759
  const initialColumns = (0, import_react4.useMemo)(() => {
1645
- if (!Array.isArray(rawInitialColumns)) return STABLE_EMPTY_COLS;
1760
+ if (!Array.isArray(rawInitialColumns))
1761
+ return STABLE_EMPTY_COLS;
1646
1762
  const safe = rawInitialColumns.filter(
1647
1763
  (col) => col != null && typeof col.key === "string"
1648
1764
  );
@@ -1707,6 +1823,106 @@ function BoltTable({
1707
1823
  () => /* @__PURE__ */ new Map()
1708
1824
  );
1709
1825
  const manuallyResizedRef = (0, import_react4.useRef)(/* @__PURE__ */ new Set());
1826
+ const persistenceAppliedRef = (0, import_react4.useRef)(false);
1827
+ import_react4.default.useEffect(() => {
1828
+ if (!columnPersistence || persistenceAppliedRef.current) return;
1829
+ persistenceAppliedRef.current = true;
1830
+ const {
1831
+ storageKey,
1832
+ persistOrder = true,
1833
+ persistWidths = true,
1834
+ persistVisibility = true,
1835
+ persistPinned = true
1836
+ } = columnPersistence;
1837
+ try {
1838
+ const raw = localStorage.getItem(`bt_${storageKey}`);
1839
+ if (!raw) return;
1840
+ const saved = JSON.parse(raw);
1841
+ if (persistOrder && saved.order) {
1842
+ setColumnOrder(saved.order);
1843
+ }
1844
+ if (persistWidths && saved.widths) {
1845
+ setColumnWidths(
1846
+ new Map(Object.entries(saved.widths).map(([k, v]) => [k, Number(v)]))
1847
+ );
1848
+ }
1849
+ if (persistVisibility && saved.hidden || persistPinned && saved.pinned) {
1850
+ setColumns(
1851
+ (prev) => prev.map((col) => {
1852
+ let updated = col;
1853
+ if (persistVisibility && saved.hidden && col.key in saved.hidden) {
1854
+ updated = { ...updated, hidden: saved.hidden[col.key] };
1855
+ }
1856
+ if (persistPinned && saved.pinned && col.key in saved.pinned) {
1857
+ updated = { ...updated, pinned: saved.pinned[col.key] };
1858
+ }
1859
+ return updated;
1860
+ })
1861
+ );
1862
+ }
1863
+ } catch {
1864
+ }
1865
+ }, [columnPersistence]);
1866
+ const persistColumnsToStorage = (0, import_react4.useCallback)(() => {
1867
+ if (!columnPersistence) return;
1868
+ const {
1869
+ storageKey,
1870
+ persistOrder = true,
1871
+ persistWidths = true,
1872
+ persistVisibility = true,
1873
+ persistPinned = true
1874
+ } = columnPersistence;
1875
+ try {
1876
+ const saved = {};
1877
+ if (persistOrder) saved.order = columnOrder;
1878
+ if (persistWidths) {
1879
+ const widths = {};
1880
+ columnWidths.forEach((v, k) => {
1881
+ widths[k] = v;
1882
+ });
1883
+ saved.widths = widths;
1884
+ }
1885
+ if (persistVisibility) {
1886
+ const hidden = {};
1887
+ columns.forEach((c) => {
1888
+ if (c.hidden) hidden[c.key] = true;
1889
+ });
1890
+ saved.hidden = hidden;
1891
+ }
1892
+ if (persistPinned) {
1893
+ const pinned = {};
1894
+ columns.forEach((c) => {
1895
+ if (c.pinned) pinned[c.key] = c.pinned;
1896
+ });
1897
+ saved.pinned = pinned;
1898
+ }
1899
+ localStorage.setItem(`bt_${storageKey}`, JSON.stringify(saved));
1900
+ } catch {
1901
+ }
1902
+ }, [columnPersistence, columnOrder, columnWidths, columns]);
1903
+ import_react4.default.useEffect(() => {
1904
+ if (!columnPersistence || !persistenceAppliedRef.current) return;
1905
+ persistColumnsToStorage();
1906
+ }, [columnPersistence, persistColumnsToStorage]);
1907
+ const [showColumnPicker, setShowColumnPicker] = (0, import_react4.useState)(false);
1908
+ const columnPickerRef = (0, import_react4.useRef)(null);
1909
+ import_react4.default.useEffect(() => {
1910
+ if (!showColumnPicker) return;
1911
+ const close = (e) => {
1912
+ if (columnPickerRef.current && !columnPickerRef.current.contains(e.target)) {
1913
+ setShowColumnPicker(false);
1914
+ }
1915
+ };
1916
+ const onKey = (e) => {
1917
+ if (e.key === "Escape") setShowColumnPicker(false);
1918
+ };
1919
+ document.addEventListener("mousedown", close);
1920
+ document.addEventListener("keydown", onKey);
1921
+ return () => {
1922
+ document.removeEventListener("mousedown", close);
1923
+ document.removeEventListener("keydown", onKey);
1924
+ };
1925
+ }, [showColumnPicker]);
1710
1926
  const columnsWithPersistedWidths = (0, import_react4.useMemo)(
1711
1927
  () => columns.map((col) => ({
1712
1928
  ...col,
@@ -1771,6 +1987,32 @@ function BoltTable({
1771
1987
  },
1772
1988
  [rowKey]
1773
1989
  );
1990
+ const deduplicatedRowKeys = (0, import_react4.useMemo)(() => {
1991
+ const seen = /* @__PURE__ */ new Map();
1992
+ return data.map((row, idx) => {
1993
+ const raw = getRowKey(row, idx);
1994
+ const count = seen.get(raw) ?? 0;
1995
+ seen.set(raw, count + 1);
1996
+ return count > 0 ? `${raw}__${idx}` : raw;
1997
+ });
1998
+ }, [data, getRowKey]);
1999
+ const hasDuplicateKeys = (0, import_react4.useMemo)(() => {
2000
+ const seen = /* @__PURE__ */ new Set();
2001
+ for (const row of data) {
2002
+ if (row == null) continue;
2003
+ const k = getRowKey(row, 0);
2004
+ if (seen.has(k)) return true;
2005
+ seen.add(k);
2006
+ }
2007
+ return false;
2008
+ }, [data, getRowKey]);
2009
+ const getSafeRowKey = (0, import_react4.useCallback)(
2010
+ (record, index) => {
2011
+ if (!hasDuplicateKeys) return getRowKey(record, index);
2012
+ return deduplicatedRowKeys[index] ?? getRowKey(record, index);
2013
+ },
2014
+ [getRowKey, hasDuplicateKeys, deduplicatedRowKeys]
2015
+ );
1774
2016
  const getRawRowKey = (0, import_react4.useCallback)(
1775
2017
  (record, index) => {
1776
2018
  if (record == null) return index;
@@ -1788,16 +2030,13 @@ function BoltTable({
1788
2030
  },
1789
2031
  [rowKey]
1790
2032
  );
1791
- const normalizedSelectedKeys = (0, import_react4.useMemo)(
1792
- () => {
1793
- const keys = rowSelection?.selectedRowKeys;
1794
- if (!Array.isArray(keys)) return [];
1795
- return keys.filter((k) => k != null).map((k) => String(k));
1796
- },
1797
- [rowSelection?.selectedRowKeys]
1798
- );
1799
- const getRowKeyRef = (0, import_react4.useRef)(getRowKey);
1800
- getRowKeyRef.current = getRowKey;
2033
+ const normalizedSelectedKeys = (0, import_react4.useMemo)(() => {
2034
+ const keys = rowSelection?.selectedRowKeys;
2035
+ if (!Array.isArray(keys)) return [];
2036
+ return keys.filter((k) => k != null).map((k) => String(k));
2037
+ }, [rowSelection?.selectedRowKeys]);
2038
+ const getRowKeyRef = (0, import_react4.useRef)(getSafeRowKey);
2039
+ getRowKeyRef.current = getSafeRowKey;
1801
2040
  const resolvedExpandedKeysRef = (0, import_react4.useRef)(resolvedExpandedKeys);
1802
2041
  resolvedExpandedKeysRef.current = resolvedExpandedKeys;
1803
2042
  const toggleExpandRef = (0, import_react4.useRef)(toggleExpand);
@@ -1980,7 +2219,9 @@ function BoltTable({
1980
2219
  }
1981
2220
  const scrollEl = tableAreaRef.current;
1982
2221
  if (!scrollEl) return;
1983
- const headers = scrollEl.querySelectorAll("[data-bt-header][data-column-key]");
2222
+ const headers = scrollEl.querySelectorAll(
2223
+ "[data-bt-header][data-column-key]"
2224
+ );
1984
2225
  let newOverId = null;
1985
2226
  headers.forEach((h) => {
1986
2227
  const key = h.dataset.columnKey;
@@ -2022,10 +2263,7 @@ function BoltTable({
2022
2263
  const newIndex = items.indexOf(currentOverId);
2023
2264
  if (oldIndex === -1 || newIndex === -1) return items;
2024
2265
  const newOrder = arrayMove(items, oldIndex, newIndex);
2025
- setTimeout(
2026
- () => onColumnOrderChangeRef.current?.(newOrder),
2027
- 0
2028
- );
2266
+ setTimeout(() => onColumnOrderChangeRef.current?.(newOrder), 0);
2029
2267
  return newOrder;
2030
2268
  });
2031
2269
  });
@@ -2125,9 +2363,7 @@ function BoltTable({
2125
2363
  [leftPinned, unpinned, rightPinned]
2126
2364
  );
2127
2365
  const freshOrderedColumns = (0, import_react4.useMemo)(() => {
2128
- const latestMap = new Map(
2129
- initialColumnsRef.current.map((c) => [c.key, c])
2130
- );
2366
+ const latestMap = new Map(initialColumnsRef.current.map((c) => [c.key, c]));
2131
2367
  return orderedColumns.map((col) => {
2132
2368
  if (col.key === "__select__" || col.key === "__expand__") return col;
2133
2369
  const latest = latestMap.get(col.key);
@@ -2184,22 +2420,27 @@ function BoltTable({
2184
2420
  };
2185
2421
  const [internalRowPinning, setInternalRowPinning] = (0, import_react4.useState)({ top: [], bottom: [] });
2186
2422
  const resolvedRowPinning = rowPinning === true ? internalRowPinning : rowPinning && typeof rowPinning === "object" ? rowPinning : void 0;
2187
- const handleRowPin = (0, import_react4.useCallback)((rk, pinned) => {
2188
- if (onRowPin) {
2189
- onRowPin(rk, pinned);
2190
- return;
2191
- }
2192
- if (rowPinning === true) {
2193
- setInternalRowPinning((prev) => {
2194
- const rkStr = String(rk);
2195
- const newTop = (prev.top ?? []).filter((k) => String(k) !== rkStr);
2196
- const newBottom = (prev.bottom ?? []).filter((k) => String(k) !== rkStr);
2197
- if (pinned === "top") newTop.push(rk);
2198
- else if (pinned === "bottom") newBottom.push(rk);
2199
- return { top: newTop, bottom: newBottom };
2200
- });
2201
- }
2202
- }, [onRowPin, rowPinning]);
2423
+ const handleRowPin = (0, import_react4.useCallback)(
2424
+ (rk, pinned) => {
2425
+ if (onRowPin) {
2426
+ onRowPin(rk, pinned);
2427
+ return;
2428
+ }
2429
+ if (rowPinning === true) {
2430
+ setInternalRowPinning((prev) => {
2431
+ const rkStr = String(rk);
2432
+ const newTop = (prev.top ?? []).filter((k) => String(k) !== rkStr);
2433
+ const newBottom = (prev.bottom ?? []).filter(
2434
+ (k) => String(k) !== rkStr
2435
+ );
2436
+ if (pinned === "top") newTop.push(rk);
2437
+ else if (pinned === "bottom") newBottom.push(rk);
2438
+ return { top: newTop, bottom: newBottom };
2439
+ });
2440
+ }
2441
+ },
2442
+ [onRowPin, rowPinning]
2443
+ );
2203
2444
  const onSortChangeRef = (0, import_react4.useRef)(onSortChange);
2204
2445
  onSortChangeRef.current = onSortChange;
2205
2446
  const [sortState, setSortState] = (0, import_react4.useState)({ key: "", direction: null });
@@ -2222,6 +2463,7 @@ function BoltTable({
2222
2463
  const [columnFilters, setColumnFilters] = (0, import_react4.useState)(
2223
2464
  {}
2224
2465
  );
2466
+ const [internalGlobalSearch, setInternalGlobalSearch] = (0, import_react4.useState)("");
2225
2467
  const handleColumnFilter = (0, import_react4.useCallback)(
2226
2468
  (columnKey, value) => {
2227
2469
  setColumnFilters((prev) => {
@@ -2246,6 +2488,20 @@ function BoltTable({
2246
2488
  columnsLookupRef.current = initialColumns;
2247
2489
  const processedData = (0, import_react4.useMemo)(() => {
2248
2490
  let result = data;
2491
+ const globalSearch = globalSearchValue ?? internalGlobalSearch;
2492
+ if (globalSearch) {
2493
+ const searchLower = globalSearch.toLowerCase();
2494
+ result = result.filter((row) => {
2495
+ if (row == null) return false;
2496
+ for (const key of Object.keys(row)) {
2497
+ const val = row[key];
2498
+ if (val != null && String(val).toLowerCase().includes(searchLower)) {
2499
+ return true;
2500
+ }
2501
+ }
2502
+ return false;
2503
+ });
2504
+ }
2249
2505
  if (!onFilterChangeRef.current) {
2250
2506
  const filterKeys = Object.keys(columnFilters);
2251
2507
  if (filterKeys.length > 0) {
@@ -2255,7 +2511,11 @@ function BoltTable({
2255
2511
  try {
2256
2512
  const col = columnsLookupRef.current.find((c) => c.key === key);
2257
2513
  if (typeof col?.filterFn === "function") {
2258
- return col.filterFn(columnFilters[key], row, col.dataIndex ?? key);
2514
+ return col.filterFn(
2515
+ columnFilters[key],
2516
+ row,
2517
+ col.dataIndex ?? key
2518
+ );
2259
2519
  }
2260
2520
  const cellVal = String(row[key] ?? "").toLowerCase();
2261
2521
  return cellVal.includes(columnFilters[key].toLowerCase());
@@ -2298,7 +2558,7 @@ function BoltTable({
2298
2558
  }
2299
2559
  }
2300
2560
  return result;
2301
- }, [data, sortState, columnFilters]);
2561
+ }, [data, sortState, columnFilters, globalSearchValue, internalGlobalSearch]);
2302
2562
  const pinnedRowCacheRef = (0, import_react4.useRef)(/* @__PURE__ */ new Map());
2303
2563
  const { pinnedTopRows, pinnedBottomRows, unpinnedProcessedData } = (0, import_react4.useMemo)(() => {
2304
2564
  if (!resolvedRowPinning || !resolvedRowPinning.top?.length && !resolvedRowPinning.bottom?.length) {
@@ -2310,19 +2570,23 @@ function BoltTable({
2310
2570
  };
2311
2571
  }
2312
2572
  const topKeySet = new Set((resolvedRowPinning.top ?? []).map(String));
2313
- const bottomKeySet = new Set((resolvedRowPinning.bottom ?? []).map(String));
2573
+ const bottomKeySet = new Set(
2574
+ (resolvedRowPinning.bottom ?? []).map(String)
2575
+ );
2314
2576
  const topMap = /* @__PURE__ */ new Map();
2315
2577
  const bottomMap = /* @__PURE__ */ new Map();
2316
2578
  const rest = [];
2317
2579
  processedData.forEach((row, idx) => {
2318
2580
  if (row == null) return;
2319
- const key = getRowKey(row, idx);
2581
+ const key = getSafeRowKey(row, idx);
2320
2582
  if (topKeySet.has(key)) {
2321
2583
  topMap.set(key, row);
2322
- if (keepPinnedRowsAcrossPages) pinnedRowCacheRef.current.set(key, row);
2584
+ if (keepPinnedRowsAcrossPages)
2585
+ pinnedRowCacheRef.current.set(key, row);
2323
2586
  } else if (bottomKeySet.has(key)) {
2324
2587
  bottomMap.set(key, row);
2325
- if (keepPinnedRowsAcrossPages) pinnedRowCacheRef.current.set(key, row);
2588
+ if (keepPinnedRowsAcrossPages)
2589
+ pinnedRowCacheRef.current.set(key, row);
2326
2590
  } else {
2327
2591
  rest.push(row);
2328
2592
  }
@@ -2340,7 +2604,8 @@ function BoltTable({
2340
2604
  }
2341
2605
  const allPinnedKeys = /* @__PURE__ */ new Set([...topKeySet, ...bottomKeySet]);
2342
2606
  for (const cachedKey of pinnedRowCacheRef.current.keys()) {
2343
- if (!allPinnedKeys.has(cachedKey)) pinnedRowCacheRef.current.delete(cachedKey);
2607
+ if (!allPinnedKeys.has(cachedKey))
2608
+ pinnedRowCacheRef.current.delete(cachedKey);
2344
2609
  }
2345
2610
  }
2346
2611
  const orderedTop = (resolvedRowPinning.top ?? []).map((k) => topMap.get(String(k))).filter((r) => r !== void 0);
@@ -2350,7 +2615,12 @@ function BoltTable({
2350
2615
  pinnedBottomRows: orderedBottom,
2351
2616
  unpinnedProcessedData: rest
2352
2617
  };
2353
- }, [processedData, resolvedRowPinning, getRowKey, keepPinnedRowsAcrossPages]);
2618
+ }, [
2619
+ processedData,
2620
+ resolvedRowPinning,
2621
+ getSafeRowKey,
2622
+ keepPinnedRowsAcrossPages
2623
+ ]);
2354
2624
  const pinnedTopHeight = pinnedTopRows.length * rowHeight;
2355
2625
  const pinnedBottomHeight = pinnedBottomRows.length * rowHeight;
2356
2626
  const pinnedTopKeySet = (0, import_react4.useMemo)(
@@ -2367,9 +2637,7 @@ function BoltTable({
2367
2637
  }, []);
2368
2638
  const [cellContextMenu, setCellContextMenu] = (0, import_react4.useState)(null);
2369
2639
  const cellMenuRef = (0, import_react4.useRef)(null);
2370
- const cellLongPressTimer = (0, import_react4.useRef)(
2371
- null
2372
- );
2640
+ const cellLongPressTimer = (0, import_react4.useRef)(null);
2373
2641
  const cellTouchStart = (0, import_react4.useRef)(null);
2374
2642
  const cancelCellLongPress = (0, import_react4.useCallback)(() => {
2375
2643
  if (cellLongPressTimer.current) {
@@ -2396,10 +2664,11 @@ function BoltTable({
2396
2664
  };
2397
2665
  }, [cellContextMenu]);
2398
2666
  const columnFiltersKey = Object.keys(columnFilters).sort().map((k) => `${k}:${columnFilters[k]}`).join("|");
2667
+ const activeGlobalSearch = globalSearchValue ?? internalGlobalSearch;
2399
2668
  import_react4.default.useEffect(() => {
2400
2669
  setInternalPage(1);
2401
2670
  tableAreaRef.current?.scrollTo({ top: 0 });
2402
- }, [columnFiltersKey]);
2671
+ }, [columnFiltersKey, activeGlobalSearch]);
2403
2672
  const DEFAULT_PAGE_SIZE = 15;
2404
2673
  const [internalPage, setInternalPage] = (0, import_react4.useState)(1);
2405
2674
  const [internalPageSize, setInternalPageSize] = (0, import_react4.useState)(DEFAULT_PAGE_SIZE);
@@ -2445,6 +2714,17 @@ function BoltTable({
2445
2714
  return paginatedData;
2446
2715
  }, [shimmerData, infiniteLoadingShimmer, paginatedData]);
2447
2716
  const measuredExpandedHeights = (0, import_react4.useRef)(/* @__PURE__ */ new Map());
2717
+ const measuredRowHeights = (0, import_react4.useRef)(/* @__PURE__ */ new Map());
2718
+ const handleRowHeightChange = (0, import_react4.useCallback)(
2719
+ (index, height) => {
2720
+ if (!enableDynamicRowHeight) return;
2721
+ const prev = measuredRowHeights.current.get(index);
2722
+ if (prev === height) return;
2723
+ measuredRowHeights.current.set(index, height);
2724
+ rowVirtualizerRef.current?.measure();
2725
+ },
2726
+ [enableDynamicRowHeight]
2727
+ );
2448
2728
  const expandedRowMeasureRafRef = (0, import_react4.useRef)(null);
2449
2729
  const handleExpandedRowResize = (0, import_react4.useCallback)(
2450
2730
  (rk, contentHeight) => {
@@ -2469,23 +2749,73 @@ function BoltTable({
2469
2749
  if (shimmerData) return rowHeight;
2470
2750
  const item = displayData[index];
2471
2751
  if (!item) return rowHeight;
2472
- const key = getRowKey(item, index);
2473
- if (!resolvedExpandedKeys.has(key)) return rowHeight;
2752
+ const baseHeight = enableDynamicRowHeight ? measuredRowHeights.current.get(index) ?? rowHeight : rowHeight;
2753
+ const key = getSafeRowKey(item, index);
2754
+ if (!resolvedExpandedKeys.has(key)) return baseHeight;
2474
2755
  const cached = measuredExpandedHeights.current.get(key);
2475
- return cached ? rowHeight + cached : rowHeight + expandedRowHeight;
2756
+ return cached ? baseHeight + cached : baseHeight + expandedRowHeight;
2476
2757
  },
2477
2758
  overscan: 5,
2478
2759
  getItemKey: (index) => {
2479
2760
  if (shimmerData) return `__shimmer_${index}__`;
2480
2761
  const item = displayData[index];
2481
2762
  if (!item) return `__fallback_${index}__`;
2482
- return getRowKey(item, index);
2763
+ return getSafeRowKey(item, index);
2483
2764
  },
2484
2765
  paddingStart: pinnedTopHeight,
2485
2766
  paddingEnd: pinnedBottomHeight
2486
2767
  });
2487
2768
  const rowVirtualizerRef = (0, import_react4.useRef)(rowVirtualizer);
2488
2769
  rowVirtualizerRef.current = rowVirtualizer;
2770
+ const scrollLeftRef = (0, import_react4.useRef)(0);
2771
+ const [visibleColumnRange, setVisibleColumnRange] = (0, import_react4.useState)(null);
2772
+ import_react4.default.useEffect(() => {
2773
+ if (!enableColumnVirtualization) return;
2774
+ const el = tableAreaRef.current;
2775
+ if (!el) return;
2776
+ const updateVisibleColumns = () => {
2777
+ const scrollLeft = el.scrollLeft;
2778
+ scrollLeftRef.current = scrollLeft;
2779
+ const viewportWidth = el.clientWidth;
2780
+ const viewStart = scrollLeft;
2781
+ const viewEnd = scrollLeft + viewportWidth;
2782
+ let cumWidth = 0;
2783
+ let startIdx = -1;
2784
+ let endIdx = orderedColumns.length - 1;
2785
+ for (let i = 0; i < orderedColumns.length; i++) {
2786
+ const col = orderedColumns[i];
2787
+ const colWidth = col.width ?? 150;
2788
+ const colStart = cumWidth;
2789
+ const colEnd = cumWidth + colWidth;
2790
+ cumWidth = colEnd;
2791
+ if (col.pinned) continue;
2792
+ if (startIdx === -1 && colEnd > viewStart) {
2793
+ startIdx = Math.max(0, i - 1);
2794
+ }
2795
+ if (colStart > viewEnd) {
2796
+ endIdx = Math.min(orderedColumns.length - 1, i + 1);
2797
+ break;
2798
+ }
2799
+ }
2800
+ if (startIdx === -1) startIdx = 0;
2801
+ setVisibleColumnRange((prev) => {
2802
+ if (prev && prev.start === startIdx && prev.end === endIdx) return prev;
2803
+ return { start: startIdx, end: endIdx };
2804
+ });
2805
+ };
2806
+ updateVisibleColumns();
2807
+ el.addEventListener("scroll", updateVisibleColumns, { passive: true });
2808
+ return () => el.removeEventListener("scroll", updateVisibleColumns);
2809
+ }, [enableColumnVirtualization, orderedColumns]);
2810
+ const virtualizedColumns = (0, import_react4.useMemo)(() => {
2811
+ if (!enableColumnVirtualization || !visibleColumnRange)
2812
+ return freshOrderedColumns;
2813
+ return freshOrderedColumns.filter((col, idx) => {
2814
+ if (col.pinned) return true;
2815
+ if (col.key === "__select__" || col.key === "__expand__") return true;
2816
+ return idx >= visibleColumnRange.start && idx <= visibleColumnRange.end;
2817
+ });
2818
+ }, [enableColumnVirtualization, visibleColumnRange, freshOrderedColumns]);
2489
2819
  const resolvedExpandedKeysFingerprint = Array.from(resolvedExpandedKeys).sort().join(",");
2490
2820
  import_react4.default.useLayoutEffect(() => {
2491
2821
  rowVirtualizer.measure();
@@ -2552,7 +2882,10 @@ function BoltTable({
2552
2882
  }, [pgCurrent, needsClientPagination]);
2553
2883
  const getPageNumbers = () => {
2554
2884
  if (totalPages <= 7)
2555
- return Array.from({ length: totalPages }, (_, i) => i + 1);
2885
+ return Array.from(
2886
+ { length: totalPages },
2887
+ (_, i) => i + 1
2888
+ );
2556
2889
  const leftSibling = Math.max(currentPage - 1, 2);
2557
2890
  const showLeftEllipsis = leftSibling > 2;
2558
2891
  const rightSibling = Math.min(currentPage + 1, totalPages - 1);
@@ -2563,7 +2896,10 @@ function BoltTable({
2563
2896
  return [
2564
2897
  1,
2565
2898
  "ellipsis-left",
2566
- ...Array.from({ length: 5 }, (_, i) => totalPages - 4 + i)
2899
+ ...Array.from(
2900
+ { length: 5 },
2901
+ (_, i) => totalPages - 4 + i
2902
+ )
2567
2903
  ];
2568
2904
  return [
2569
2905
  1,
@@ -2634,6 +2970,189 @@ function BoltTable({
2634
2970
  }
2635
2971
  ${onRowClick ? "[data-bt-cell] { cursor: pointer; }" : ""}
2636
2972
  ` }),
2973
+ (!hideGlobalSearch || showColumnSettings) && /* @__PURE__ */ (0, import_jsx_runtime5.jsxs)(
2974
+ "div",
2975
+ {
2976
+ style: {
2977
+ display: "flex",
2978
+ alignItems: "center",
2979
+ gap: 8,
2980
+ padding: "6px 8px",
2981
+ borderBottom: "1px solid rgba(128,128,128,0.2)",
2982
+ fontSize: 12,
2983
+ flexShrink: 0
2984
+ },
2985
+ children: [
2986
+ !hideGlobalSearch && /* @__PURE__ */ (0, import_jsx_runtime5.jsxs)(
2987
+ "div",
2988
+ {
2989
+ style: {
2990
+ display: "flex",
2991
+ alignItems: "center",
2992
+ gap: 4,
2993
+ flex: "1 1 0%",
2994
+ position: "relative"
2995
+ },
2996
+ children: [
2997
+ /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(
2998
+ "span",
2999
+ {
3000
+ style: { display: "flex", color: "GrayText", flexShrink: 0 },
3001
+ children: icons?.search ?? /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(SearchIcon, { style: { width: 14, height: 14 } })
3002
+ }
3003
+ ),
3004
+ /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(
3005
+ "input",
3006
+ {
3007
+ type: "text",
3008
+ placeholder: "Search all columns...",
3009
+ value: globalSearchValue ?? internalGlobalSearch,
3010
+ onChange: (e) => {
3011
+ const v = e.target.value;
3012
+ if (onGlobalSearchChange) onGlobalSearchChange(v);
3013
+ else setInternalGlobalSearch(v);
3014
+ },
3015
+ style: {
3016
+ flex: "1 1 0%",
3017
+ border: "none",
3018
+ outline: "none",
3019
+ background: "transparent",
3020
+ font: "inherit",
3021
+ color: "inherit",
3022
+ padding: "4px 6px",
3023
+ minWidth: 0
3024
+ }
3025
+ }
3026
+ ),
3027
+ (globalSearchValue ?? internalGlobalSearch) && /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(
3028
+ "button",
3029
+ {
3030
+ type: "button",
3031
+ onClick: () => {
3032
+ if (onGlobalSearchChange) onGlobalSearchChange("");
3033
+ else setInternalGlobalSearch("");
3034
+ },
3035
+ style: {
3036
+ display: "flex",
3037
+ alignItems: "center",
3038
+ justifyContent: "center",
3039
+ background: "none",
3040
+ border: "none",
3041
+ cursor: "pointer",
3042
+ padding: 2,
3043
+ color: "GrayText",
3044
+ flexShrink: 0
3045
+ },
3046
+ children: icons?.close ?? /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(XIcon, { style: { width: 12, height: 12 } })
3047
+ }
3048
+ )
3049
+ ]
3050
+ }
3051
+ ),
3052
+ showColumnSettings && /* @__PURE__ */ (0, import_jsx_runtime5.jsxs)("div", { style: { position: "relative", flexShrink: 0 }, children: [
3053
+ /* @__PURE__ */ (0, import_jsx_runtime5.jsxs)(
3054
+ "button",
3055
+ {
3056
+ type: "button",
3057
+ onClick: () => setShowColumnPicker((p) => !p),
3058
+ style: {
3059
+ display: "flex",
3060
+ alignItems: "center",
3061
+ justifyContent: "center",
3062
+ background: "none",
3063
+ border: "1px solid rgba(128,128,128,0.2)",
3064
+ borderRadius: 4,
3065
+ cursor: "pointer",
3066
+ padding: "4px 6px",
3067
+ color: "inherit",
3068
+ gap: 4,
3069
+ fontSize: 12
3070
+ },
3071
+ title: "Column settings",
3072
+ children: [
3073
+ icons?.columns ?? /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(ColumnsIcon, { style: { width: 14, height: 14 } }),
3074
+ /* @__PURE__ */ (0, import_jsx_runtime5.jsx)("span", { children: "Columns" })
3075
+ ]
3076
+ }
3077
+ ),
3078
+ showColumnPicker && /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(
3079
+ "div",
3080
+ {
3081
+ ref: columnPickerRef,
3082
+ style: {
3083
+ position: "absolute",
3084
+ top: "100%",
3085
+ right: 0,
3086
+ zIndex: 99999,
3087
+ minWidth: 200,
3088
+ maxHeight: 320,
3089
+ overflowY: "auto",
3090
+ borderRadius: 8,
3091
+ border: "1px solid rgba(128,128,128,0.2)",
3092
+ boxShadow: "0 4px 24px rgba(0,0,0,0.12)",
3093
+ backdropFilter: "blur(16px)",
3094
+ WebkitBackdropFilter: "blur(16px)",
3095
+ backgroundColor: "rgba(128,128,128,0.08)",
3096
+ padding: "4px 0",
3097
+ marginTop: 4
3098
+ },
3099
+ children: initialColumns.filter(
3100
+ (c) => c.key !== "__select__" && c.key !== "__expand__"
3101
+ ).map((col) => {
3102
+ const current = columns.find((c) => c.key === col.key);
3103
+ const isHidden = current?.hidden ?? false;
3104
+ const isPinned = !!current?.pinned;
3105
+ return /* @__PURE__ */ (0, import_jsx_runtime5.jsxs)(
3106
+ "label",
3107
+ {
3108
+ style: {
3109
+ display: "flex",
3110
+ alignItems: "center",
3111
+ gap: 8,
3112
+ padding: "6px 12px",
3113
+ cursor: isPinned ? "not-allowed" : "pointer",
3114
+ opacity: isPinned ? 0.5 : 1,
3115
+ fontSize: 12
3116
+ },
3117
+ children: [
3118
+ /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(
3119
+ "input",
3120
+ {
3121
+ type: "checkbox",
3122
+ checked: !isHidden,
3123
+ disabled: isPinned,
3124
+ onChange: () => {
3125
+ if (isPinned) return;
3126
+ handleToggleHide(col.key);
3127
+ },
3128
+ style: {
3129
+ cursor: isPinned ? "not-allowed" : "pointer",
3130
+ accentColor
3131
+ }
3132
+ }
3133
+ ),
3134
+ /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(
3135
+ "span",
3136
+ {
3137
+ style: {
3138
+ overflow: "hidden",
3139
+ textOverflow: "ellipsis",
3140
+ whiteSpace: "nowrap"
3141
+ },
3142
+ children: typeof col.title === "string" ? col.title : col.key
3143
+ }
3144
+ )
3145
+ ]
3146
+ },
3147
+ col.key
3148
+ );
3149
+ })
3150
+ }
3151
+ )
3152
+ ] })
3153
+ ]
3154
+ }
3155
+ ),
2637
3156
  /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(
2638
3157
  "div",
2639
3158
  {
@@ -2778,19 +3297,20 @@ function BoltTable({
2778
3297
  ...isEmpty ? { height: "100%" } : {}
2779
3298
  },
2780
3299
  onContextMenu: (e) => {
2781
- const cell = e.target.closest("[data-bt-cell]");
3300
+ const cell = e.target.closest(
3301
+ "[data-bt-cell]"
3302
+ );
2782
3303
  if (!cell) return;
2783
3304
  const rk = cell.dataset.rowKey;
2784
3305
  const ck = cell.dataset.columnKey;
2785
3306
  if (!rk || !ck) return;
2786
- const col = freshOrderedColumns.find(
2787
- (c) => c.key === ck
2788
- );
3307
+ const col = freshOrderedColumns.find((c) => c.key === ck);
2789
3308
  const hasCopy = !!col?.copy;
2790
3309
  const hasRowPin = !!rowPinning;
2791
3310
  const hasCellItems = col?.columnCellContextMenuItems && col.columnCellContextMenuItems.length > 0;
2792
3311
  const hasEdit = !!col?.editable && !col?.render && !!onEdit;
2793
- if (!hasCopy && !hasRowPin && !hasCellItems && !hasEdit) return;
3312
+ if (!hasCopy && !hasRowPin && !hasCellItems && !hasEdit)
3313
+ return;
2794
3314
  e.preventDefault();
2795
3315
  setCellContextMenu({
2796
3316
  x: Math.min(e.clientX, window.innerWidth - 200),
@@ -2801,7 +3321,9 @@ function BoltTable({
2801
3321
  },
2802
3322
  onTouchStart: (e) => {
2803
3323
  cancelCellLongPress();
2804
- const cell = e.target.closest("[data-bt-cell]");
3324
+ const cell = e.target.closest(
3325
+ "[data-bt-cell]"
3326
+ );
2805
3327
  if (!cell) return;
2806
3328
  const touch = e.touches[0];
2807
3329
  cellTouchStart.current = {
@@ -2813,14 +3335,13 @@ function BoltTable({
2813
3335
  cellLongPressTimer.current = setTimeout(() => {
2814
3336
  cellLongPressTimer.current = null;
2815
3337
  if (!rk || !ck) return;
2816
- const col = freshOrderedColumns.find(
2817
- (c) => c.key === ck
2818
- );
3338
+ const col = freshOrderedColumns.find((c) => c.key === ck);
2819
3339
  const hasCopy = !!col?.copy;
2820
3340
  const hasRowPin = !!rowPinning;
2821
3341
  const hasCellItems = col?.columnCellContextMenuItems && col.columnCellContextMenuItems.length > 0;
2822
3342
  const hasEdit = !!col?.editable && !col?.render && !!onEdit;
2823
- if (!hasCopy && !hasRowPin && !hasCellItems && !hasEdit) return;
3343
+ if (!hasCopy && !hasRowPin && !hasCellItems && !hasEdit)
3344
+ return;
2824
3345
  setCellContextMenu({
2825
3346
  x: Math.min(touch.clientX, window.innerWidth - 200),
2826
3347
  y: Math.min(touch.clientY, window.innerHeight - 200),
@@ -2841,7 +3362,8 @@ function BoltTable({
2841
3362
  onTouchCancel: cancelCellLongPress,
2842
3363
  onClick: onRowClick ? (e) => {
2843
3364
  const target = e.target;
2844
- if (target.closest("input, button, a, select, textarea")) return;
3365
+ if (target.closest("input, button, a, select, textarea"))
3366
+ return;
2845
3367
  const cell = target.closest("[data-bt-cell]");
2846
3368
  if (!cell) return;
2847
3369
  const rk = cell.dataset.rowKey;
@@ -2849,21 +3371,21 @@ function BoltTable({
2849
3371
  for (let i = 0; i < displayData.length; i++) {
2850
3372
  const row = displayData[i];
2851
3373
  if (row == null) continue;
2852
- if (getRowKey(row, i) === rk) {
3374
+ if (getSafeRowKey(row, i) === rk) {
2853
3375
  onRowClick(row, i, e);
2854
3376
  return;
2855
3377
  }
2856
3378
  }
2857
3379
  for (let i = 0; i < pinnedTopRows.length; i++) {
2858
3380
  if (pinnedTopRows[i] == null) continue;
2859
- if (getRowKey(pinnedTopRows[i], i) === rk) {
3381
+ if (getSafeRowKey(pinnedTopRows[i], i) === rk) {
2860
3382
  onRowClick(pinnedTopRows[i], i, e);
2861
3383
  return;
2862
3384
  }
2863
3385
  }
2864
3386
  for (let i = 0; i < pinnedBottomRows.length; i++) {
2865
3387
  if (pinnedBottomRows[i] == null) continue;
2866
- if (getRowKey(pinnedBottomRows[i], i) === rk) {
3388
+ if (getSafeRowKey(pinnedBottomRows[i], i) === rk) {
2867
3389
  onRowClick(pinnedBottomRows[i], i, e);
2868
3390
  return;
2869
3391
  }
@@ -2973,7 +3495,11 @@ function BoltTable({
2973
3495
  });
2974
3496
  }
2975
3497
  },
2976
- style: { cursor: "pointer", accentColor, colorScheme: "light dark" }
3498
+ style: {
3499
+ cursor: "pointer",
3500
+ accentColor,
3501
+ backgroundColor: "#94A3B8"
3502
+ }
2977
3503
  }
2978
3504
  )
2979
3505
  },
@@ -3001,6 +3527,7 @@ function BoltTable({
3001
3527
  top: 0,
3002
3528
  zIndex: 13,
3003
3529
  width: "40px",
3530
+ backgroundColor: styles.pinnedBg,
3004
3531
  gridRow: leafGridRow,
3005
3532
  ...styles.header,
3006
3533
  ...styles.pinnedHeader
@@ -3032,7 +3559,10 @@ function BoltTable({
3032
3559
  filterValue: columnFilters[column.key] ?? "",
3033
3560
  onFilter: handleColumnFilter,
3034
3561
  onClearFilter: handleClearFilter,
3035
- customContextMenuItems: column.columnHeaderContextMenuItems ? [...columnContextMenuItems ?? [], ...column.columnHeaderContextMenuItems] : columnContextMenuItems,
3562
+ customContextMenuItems: column.columnHeaderContextMenuItems ? [
3563
+ ...columnContextMenuItems ?? [],
3564
+ ...column.columnHeaderContextMenuItems
3565
+ ] : columnContextMenuItems,
3036
3566
  disabledFilters,
3037
3567
  headerGridRow: leafGridRow,
3038
3568
  headerHeight: leafHeight,
@@ -3084,14 +3614,14 @@ function BoltTable({
3084
3614
  TableBody_default,
3085
3615
  {
3086
3616
  data: displayData,
3087
- orderedColumns: freshOrderedColumns,
3617
+ orderedColumns: virtualizedColumns,
3088
3618
  rowVirtualizer,
3089
3619
  columnOffsets,
3090
3620
  styles,
3091
3621
  classNames,
3092
3622
  rowSelection: !showShimmer ? rowSelection : void 0,
3093
3623
  normalizedSelectedKeys,
3094
- getRowKey,
3624
+ getRowKey: getSafeRowKey,
3095
3625
  getRawRowKey,
3096
3626
  expandable: !showShimmer ? expandable : void 0,
3097
3627
  resolvedExpandedKeys,
@@ -3112,7 +3642,9 @@ function BoltTable({
3112
3642
  bodyGridRow: hasColumnGroups ? 3 : 2,
3113
3643
  onEdit,
3114
3644
  editingCell,
3115
- onEditComplete: handleEditComplete
3645
+ onEditComplete: handleEditComplete,
3646
+ enableDynamicRowHeight,
3647
+ onRowHeightChange: handleRowHeightChange
3116
3648
  }
3117
3649
  )
3118
3650
  ]
@@ -3142,39 +3674,53 @@ function BoltTable({
3142
3674
  ...styles.pagination
3143
3675
  },
3144
3676
  children: [
3145
- /* @__PURE__ */ (0, import_jsx_runtime5.jsx)("div", { style: { display: "flex", flex: "1 1 0%", alignItems: "center" }, children: (() => {
3146
- const rangeStart = total > 0 ? (currentPage - 1) * pageSize + 1 : 0;
3147
- const rangeEnd = Math.min(currentPage * pageSize, total);
3148
- return typeof pagination === "object" && pagination?.showTotal ? /* @__PURE__ */ (0, import_jsx_runtime5.jsxs)(
3149
- "span",
3150
- {
3151
- className: classNames.paginationInfo ?? "",
3152
- style: { color: "GrayText", fontSize: 12, ...styles.paginationInfo },
3153
- children: [
3154
- "Showing",
3155
- " ",
3156
- pagination.showTotal(total, [rangeStart, rangeEnd]),
3157
- " of",
3158
- " ",
3159
- total,
3160
- " items"
3161
- ]
3162
- }
3163
- ) : /* @__PURE__ */ (0, import_jsx_runtime5.jsxs)(
3164
- "span",
3165
- {
3166
- className: classNames.paginationInfo ?? "",
3167
- style: { color: "GrayText", fontSize: 12, ...styles.paginationInfo },
3168
- children: [
3169
- rangeStart,
3170
- "\u2013",
3171
- rangeEnd,
3172
- " of ",
3173
- total
3174
- ]
3175
- }
3176
- );
3177
- })() }),
3677
+ /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(
3678
+ "div",
3679
+ {
3680
+ style: { display: "flex", flex: "1 1 0%", alignItems: "center" },
3681
+ children: (() => {
3682
+ const rangeStart = total > 0 ? (currentPage - 1) * pageSize + 1 : 0;
3683
+ const rangeEnd = Math.min(currentPage * pageSize, total);
3684
+ return typeof pagination === "object" && pagination?.showTotal ? /* @__PURE__ */ (0, import_jsx_runtime5.jsxs)(
3685
+ "span",
3686
+ {
3687
+ className: classNames.paginationInfo ?? "",
3688
+ style: {
3689
+ color: "GrayText",
3690
+ fontSize: 12,
3691
+ ...styles.paginationInfo
3692
+ },
3693
+ children: [
3694
+ "Showing",
3695
+ " ",
3696
+ pagination.showTotal(total, [rangeStart, rangeEnd]),
3697
+ " of",
3698
+ " ",
3699
+ total,
3700
+ " items"
3701
+ ]
3702
+ }
3703
+ ) : /* @__PURE__ */ (0, import_jsx_runtime5.jsxs)(
3704
+ "span",
3705
+ {
3706
+ className: classNames.paginationInfo ?? "",
3707
+ style: {
3708
+ color: "GrayText",
3709
+ fontSize: 12,
3710
+ ...styles.paginationInfo
3711
+ },
3712
+ children: [
3713
+ rangeStart,
3714
+ "\u2013",
3715
+ rangeEnd,
3716
+ " of ",
3717
+ total
3718
+ ]
3719
+ }
3720
+ );
3721
+ })()
3722
+ }
3723
+ ),
3178
3724
  /* @__PURE__ */ (0, import_jsx_runtime5.jsxs)(
3179
3725
  "div",
3180
3726
  {
@@ -3457,9 +4003,7 @@ function BoltTable({
3457
4003
  (c) => c.key === cellContextMenu.columnKey
3458
4004
  );
3459
4005
  const isPinnedTop = pinnedTopKeySet.has(cellContextMenu.rowKey);
3460
- const isPinnedBottom = pinnedBottomKeySet.has(
3461
- cellContextMenu.rowKey
3462
- );
4006
+ const isPinnedBottom = pinnedBottomKeySet.has(cellContextMenu.rowKey);
3463
4007
  const hasCopy = !!menuCol?.copy;
3464
4008
  const hasRowPin = !!rowPinning;
3465
4009
  const hasEdit = !!menuCol?.editable && !menuCol?.render && !!onEdit;
@@ -3472,7 +4016,7 @@ function BoltTable({
3472
4016
  ];
3473
4017
  for (let i = 0; i < allRows.length; i++) {
3474
4018
  if (allRows[i] == null) continue;
3475
- const rk = getRowKey(allRows[i], i);
4019
+ const rk = getSafeRowKey(allRows[i], i);
3476
4020
  if (rk === cellContextMenu.rowKey) {
3477
4021
  menuRecord = allRows[i];
3478
4022
  menuRowIndex = i;
@@ -3674,7 +4218,20 @@ function BoltTable({
3674
4218
  setCellContextMenu(null);
3675
4219
  },
3676
4220
  children: [
3677
- item.icon && /* @__PURE__ */ (0, import_jsx_runtime5.jsx)("span", { style: { display: "flex", width: 14, height: 14, alignItems: "center", justifyContent: "center", flexShrink: 0 }, children: item.icon }),
4221
+ item.icon && /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(
4222
+ "span",
4223
+ {
4224
+ style: {
4225
+ display: "flex",
4226
+ width: 14,
4227
+ height: 14,
4228
+ alignItems: "center",
4229
+ justifyContent: "center",
4230
+ flexShrink: 0
4231
+ },
4232
+ children: item.icon
4233
+ }
4234
+ ),
3678
4235
  item.label
3679
4236
  ]
3680
4237
  },