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/README.md +780 -1
- package/dist/index.d.mts +43 -9
- package/dist/index.d.ts +43 -9
- package/dist/index.js +679 -122
- package/dist/index.mjs +686 -123
- package/package.json +1 -1
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
|
-
}, [
|
|
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: {
|
|
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: {
|
|
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)(
|
|
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
|
-
|
|
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
|
-
|
|
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(
|
|
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))
|
|
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
|
-
|
|
1794
|
-
|
|
1795
|
-
|
|
1796
|
-
|
|
1797
|
-
|
|
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(
|
|
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)(
|
|
2188
|
-
|
|
2189
|
-
onRowPin
|
|
2190
|
-
|
|
2191
|
-
|
|
2192
|
-
|
|
2193
|
-
|
|
2194
|
-
|
|
2195
|
-
|
|
2196
|
-
|
|
2197
|
-
|
|
2198
|
-
|
|
2199
|
-
|
|
2200
|
-
|
|
2201
|
-
|
|
2202
|
-
|
|
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(
|
|
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(
|
|
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 =
|
|
2581
|
+
const key = getSafeRowKey(row, idx);
|
|
2320
2582
|
if (topKeySet.has(key)) {
|
|
2321
2583
|
topMap.set(key, row);
|
|
2322
|
-
if (keepPinnedRowsAcrossPages)
|
|
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)
|
|
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))
|
|
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
|
-
}, [
|
|
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
|
|
2473
|
-
|
|
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 ?
|
|
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
|
|
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(
|
|
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(
|
|
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(
|
|
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)
|
|
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(
|
|
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)
|
|
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"))
|
|
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 (
|
|
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 (
|
|
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 (
|
|
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: {
|
|
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 ? [
|
|
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:
|
|
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)(
|
|
3146
|
-
|
|
3147
|
-
|
|
3148
|
-
|
|
3149
|
-
|
|
3150
|
-
|
|
3151
|
-
|
|
3152
|
-
|
|
3153
|
-
|
|
3154
|
-
|
|
3155
|
-
|
|
3156
|
-
|
|
3157
|
-
|
|
3158
|
-
|
|
3159
|
-
|
|
3160
|
-
|
|
3161
|
-
|
|
3162
|
-
|
|
3163
|
-
|
|
3164
|
-
|
|
3165
|
-
|
|
3166
|
-
|
|
3167
|
-
|
|
3168
|
-
|
|
3169
|
-
|
|
3170
|
-
|
|
3171
|
-
|
|
3172
|
-
"
|
|
3173
|
-
|
|
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 =
|
|
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)(
|
|
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
|
},
|