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