bolt-table 0.1.19 → 0.1.20
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/index.d.mts +1 -1
- package/dist/index.d.ts +1 -1
- package/dist/index.js +209 -85
- package/dist/index.mjs +209 -85
- package/package.json +1 -1
package/dist/index.d.mts
CHANGED
|
@@ -281,7 +281,7 @@ interface StylesTypes {
|
|
|
281
281
|
/** CSS color string for pinned column cells and headers background. */
|
|
282
282
|
pinnedBg?: string;
|
|
283
283
|
}
|
|
284
|
-
declare function BoltTable<T extends DataRecord = DataRecord>({ columns:
|
|
284
|
+
declare function BoltTable<T extends DataRecord = DataRecord>({ columns: rawInitialColumns, data: rawData, rowHeight, expandedRowHeight, maxExpandedRowHeight, accentColor, className, classNames, styles, gripIcon, hideGripIcon, icons, pagination, onPaginationChange, onColumnResize, onColumnOrderChange, onColumnPin, onColumnHide, rowSelection, rowPinning, onRowPin, expandable, rowKey, onEndReached, onEndReachedThreshold, isLoading, onSortChange, onFilterChange, columnContextMenuItems, autoHeight, layoutLoading, emptyRenderer, rowClassName, rowStyle, }: BoltTableProps<T>): react_jsx_runtime.JSX.Element;
|
|
285
285
|
|
|
286
286
|
interface DraggableHeaderProps {
|
|
287
287
|
/** Column definition for this header cell. */
|
package/dist/index.d.ts
CHANGED
|
@@ -281,7 +281,7 @@ interface StylesTypes {
|
|
|
281
281
|
/** CSS color string for pinned column cells and headers background. */
|
|
282
282
|
pinnedBg?: string;
|
|
283
283
|
}
|
|
284
|
-
declare function BoltTable<T extends DataRecord = DataRecord>({ columns:
|
|
284
|
+
declare function BoltTable<T extends DataRecord = DataRecord>({ columns: rawInitialColumns, data: rawData, rowHeight, expandedRowHeight, maxExpandedRowHeight, accentColor, className, classNames, styles, gripIcon, hideGripIcon, icons, pagination, onPaginationChange, onColumnResize, onColumnOrderChange, onColumnPin, onColumnHide, rowSelection, rowPinning, onRowPin, expandable, rowKey, onEndReached, onEndReachedThreshold, isLoading, onSortChange, onFilterChange, columnContextMenuItems, autoHeight, layoutLoading, emptyRenderer, rowClassName, rowStyle, }: BoltTableProps<T>): react_jsx_runtime.JSX.Element;
|
|
285
285
|
|
|
286
286
|
interface DraggableHeaderProps {
|
|
287
287
|
/** Column definition for this header cell. */
|
package/dist/index.js
CHANGED
|
@@ -979,7 +979,16 @@ var Cell = import_react3.default.memo(
|
|
|
979
979
|
}
|
|
980
980
|
);
|
|
981
981
|
}
|
|
982
|
-
|
|
982
|
+
let content;
|
|
983
|
+
if (column.render) {
|
|
984
|
+
try {
|
|
985
|
+
content = column.render(value, record, rowIndex);
|
|
986
|
+
} catch {
|
|
987
|
+
content = String(value ?? "");
|
|
988
|
+
}
|
|
989
|
+
} else {
|
|
990
|
+
content = value ?? "";
|
|
991
|
+
}
|
|
983
992
|
const isSystem = column.key === "__select__" || column.key === "__expand__";
|
|
984
993
|
return /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(
|
|
985
994
|
"div",
|
|
@@ -1092,14 +1101,16 @@ var TableBody = ({
|
|
|
1092
1101
|
const virtualItems = rowVirtualizer.getVirtualItems();
|
|
1093
1102
|
const totalSize = rowVirtualizer.getTotalSize();
|
|
1094
1103
|
const selectedKeySet = (0, import_react3.useMemo)(() => new Set(normalizedSelectedKeys), [normalizedSelectedKeys]);
|
|
1104
|
+
const safeData = data ?? [];
|
|
1105
|
+
const safeColumns = orderedColumns ?? [];
|
|
1095
1106
|
const allDataForSelection = (0, import_react3.useMemo)(() => {
|
|
1096
1107
|
if (pinnedTopData.length === 0 && pinnedBottomData.length === 0)
|
|
1097
|
-
return
|
|
1098
|
-
return [...pinnedTopData, ...
|
|
1099
|
-
}, [pinnedTopData,
|
|
1108
|
+
return safeData;
|
|
1109
|
+
return [...pinnedTopData, ...safeData, ...pinnedBottomData];
|
|
1110
|
+
}, [pinnedTopData, safeData, pinnedBottomData]);
|
|
1100
1111
|
const pinnedRowBg = styles?.pinnedRowBg ?? styles?.pinnedBg;
|
|
1101
1112
|
const columnStyles = (0, import_react3.useMemo)(() => {
|
|
1102
|
-
return
|
|
1113
|
+
return safeColumns.map((col, colIndex) => {
|
|
1103
1114
|
const stickyOffset = columnOffsets.get(col.key);
|
|
1104
1115
|
const isPinned = Boolean(col.pinned);
|
|
1105
1116
|
let zIndex = 0;
|
|
@@ -1121,10 +1132,12 @@ var TableBody = ({
|
|
|
1121
1132
|
}
|
|
1122
1133
|
return { key: col.key, style, isPinned };
|
|
1123
1134
|
});
|
|
1124
|
-
}, [
|
|
1135
|
+
}, [safeColumns, columnOffsets, totalSize, styles]);
|
|
1136
|
+
if (safeData.length === 0 || safeColumns.length === 0) return null;
|
|
1125
1137
|
return /* @__PURE__ */ (0, import_jsx_runtime4.jsxs)(import_jsx_runtime4.Fragment, { children: [
|
|
1126
1138
|
columnStyles.map((colStyle, colIndex) => {
|
|
1127
|
-
const col =
|
|
1139
|
+
const col = safeColumns[colIndex];
|
|
1140
|
+
if (!col) return null;
|
|
1128
1141
|
const hasRender = !!col.render;
|
|
1129
1142
|
return /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(
|
|
1130
1143
|
"div",
|
|
@@ -1132,15 +1145,31 @@ var TableBody = ({
|
|
|
1132
1145
|
...colStyle.isPinned ? { "data-bt-pinned": "" } : {},
|
|
1133
1146
|
style: colStyle.style,
|
|
1134
1147
|
children: virtualItems.map((virtualRow) => {
|
|
1135
|
-
const row =
|
|
1148
|
+
const row = safeData[virtualRow.index];
|
|
1149
|
+
if (row == null) return null;
|
|
1136
1150
|
const rowKey = getRowKey ? getRowKey(row, virtualRow.index) : String(virtualRow.index);
|
|
1137
1151
|
const isSelected = selectedKeySet.has(rowKey);
|
|
1138
1152
|
const isExpanded = resolvedExpandedKeys?.has(rowKey) ?? false;
|
|
1139
1153
|
const cellValue = row[col.dataIndex];
|
|
1140
1154
|
const isRowShimmer = isLoading || rowKey.startsWith("__shimmer_");
|
|
1141
|
-
|
|
1142
|
-
|
|
1143
|
-
|
|
1155
|
+
let recordFingerprint;
|
|
1156
|
+
if (hasRender && !isRowShimmer) {
|
|
1157
|
+
try {
|
|
1158
|
+
recordFingerprint = JSON.stringify(row);
|
|
1159
|
+
} catch {
|
|
1160
|
+
recordFingerprint = rowKey;
|
|
1161
|
+
}
|
|
1162
|
+
}
|
|
1163
|
+
let rowCls = "";
|
|
1164
|
+
try {
|
|
1165
|
+
rowCls = rowClassName ? rowClassName(row, virtualRow.index) : "";
|
|
1166
|
+
} catch {
|
|
1167
|
+
}
|
|
1168
|
+
let rowSty;
|
|
1169
|
+
try {
|
|
1170
|
+
rowSty = rowStyle ? rowStyle(row, virtualRow.index) : void 0;
|
|
1171
|
+
} catch {
|
|
1172
|
+
}
|
|
1144
1173
|
return /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(
|
|
1145
1174
|
"div",
|
|
1146
1175
|
{
|
|
@@ -1207,9 +1236,15 @@ var TableBody = ({
|
|
|
1207
1236
|
pointerEvents: "none"
|
|
1208
1237
|
},
|
|
1209
1238
|
children: virtualItems.map((virtualRow) => {
|
|
1210
|
-
const row =
|
|
1239
|
+
const row = safeData[virtualRow.index];
|
|
1240
|
+
if (row == null) return null;
|
|
1211
1241
|
const rk = getRowKey ? getRowKey(row, virtualRow.index) : String(virtualRow.index);
|
|
1212
1242
|
if (!(resolvedExpandedKeys?.has(rk) ?? false)) return null;
|
|
1243
|
+
let expandedRenderResult = null;
|
|
1244
|
+
try {
|
|
1245
|
+
expandedRenderResult = expandable.expandedRowRender(row, virtualRow.index, 0, true);
|
|
1246
|
+
} catch {
|
|
1247
|
+
}
|
|
1213
1248
|
const expandedContent = /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(
|
|
1214
1249
|
"div",
|
|
1215
1250
|
{
|
|
@@ -1227,7 +1262,7 @@ var TableBody = ({
|
|
|
1227
1262
|
...maxExpandedRowHeight ? { maxHeight: `${maxExpandedRowHeight}px` } : void 0,
|
|
1228
1263
|
...styles?.expandedRow
|
|
1229
1264
|
},
|
|
1230
|
-
children:
|
|
1265
|
+
children: expandedRenderResult
|
|
1231
1266
|
}
|
|
1232
1267
|
);
|
|
1233
1268
|
return /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(
|
|
@@ -1274,11 +1309,20 @@ var TableBody = ({
|
|
|
1274
1309
|
boxShadow: "0 2px 6px -1px rgba(0,0,0,0.08)"
|
|
1275
1310
|
},
|
|
1276
1311
|
children: pinnedTopData.map((row, rowIdx) => {
|
|
1312
|
+
if (row == null) return null;
|
|
1277
1313
|
const rk = getRowKey ? getRowKey(row, rowIdx) : String(rowIdx);
|
|
1278
1314
|
const isSelected = selectedKeySet.has(rk);
|
|
1279
1315
|
const isExpanded = resolvedExpandedKeys?.has(rk) ?? false;
|
|
1280
|
-
|
|
1281
|
-
|
|
1316
|
+
let rowCls = "";
|
|
1317
|
+
try {
|
|
1318
|
+
rowCls = rowClassName ? rowClassName(row, rowIdx) : "";
|
|
1319
|
+
} catch {
|
|
1320
|
+
}
|
|
1321
|
+
let rowSty;
|
|
1322
|
+
try {
|
|
1323
|
+
rowSty = rowStyle ? rowStyle(row, rowIdx) : void 0;
|
|
1324
|
+
} catch {
|
|
1325
|
+
}
|
|
1282
1326
|
return /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(
|
|
1283
1327
|
"div",
|
|
1284
1328
|
{
|
|
@@ -1290,7 +1334,7 @@ var TableBody = ({
|
|
|
1290
1334
|
...styles?.pinnedRow,
|
|
1291
1335
|
...rowSty
|
|
1292
1336
|
},
|
|
1293
|
-
children:
|
|
1337
|
+
children: safeColumns.map((col) => {
|
|
1294
1338
|
const cellValue = row[col.dataIndex];
|
|
1295
1339
|
const stickyOffset = columnOffsets.get(col.key);
|
|
1296
1340
|
const isPinned = Boolean(col.pinned);
|
|
@@ -1298,7 +1342,14 @@ var TableBody = ({
|
|
|
1298
1342
|
if (col.key === "__select__" || col.key === "__expand__")
|
|
1299
1343
|
zIndex = 11;
|
|
1300
1344
|
else if (isPinned) zIndex = 2;
|
|
1301
|
-
|
|
1345
|
+
let recordFingerprint;
|
|
1346
|
+
if (col.render) {
|
|
1347
|
+
try {
|
|
1348
|
+
recordFingerprint = JSON.stringify(row);
|
|
1349
|
+
} catch {
|
|
1350
|
+
recordFingerprint = rk;
|
|
1351
|
+
}
|
|
1352
|
+
}
|
|
1302
1353
|
return /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(
|
|
1303
1354
|
"div",
|
|
1304
1355
|
{
|
|
@@ -1382,11 +1433,20 @@ var TableBody = ({
|
|
|
1382
1433
|
boxShadow: "0 -2px 6px -1px rgba(0,0,0,0.08)"
|
|
1383
1434
|
},
|
|
1384
1435
|
children: pinnedBottomData.map((row, rowIdx) => {
|
|
1436
|
+
if (row == null) return null;
|
|
1385
1437
|
const rk = getRowKey ? getRowKey(row, rowIdx) : String(rowIdx);
|
|
1386
1438
|
const isSelected = selectedKeySet.has(rk);
|
|
1387
1439
|
const isExpanded = resolvedExpandedKeys?.has(rk) ?? false;
|
|
1388
|
-
|
|
1389
|
-
|
|
1440
|
+
let rowCls = "";
|
|
1441
|
+
try {
|
|
1442
|
+
rowCls = rowClassName ? rowClassName(row, rowIdx) : "";
|
|
1443
|
+
} catch {
|
|
1444
|
+
}
|
|
1445
|
+
let rowSty;
|
|
1446
|
+
try {
|
|
1447
|
+
rowSty = rowStyle ? rowStyle(row, rowIdx) : void 0;
|
|
1448
|
+
} catch {
|
|
1449
|
+
}
|
|
1390
1450
|
return /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(
|
|
1391
1451
|
"div",
|
|
1392
1452
|
{
|
|
@@ -1398,7 +1458,7 @@ var TableBody = ({
|
|
|
1398
1458
|
...styles?.pinnedRow,
|
|
1399
1459
|
...rowSty
|
|
1400
1460
|
},
|
|
1401
|
-
children:
|
|
1461
|
+
children: safeColumns.map((col) => {
|
|
1402
1462
|
const cellValue = row[col.dataIndex];
|
|
1403
1463
|
const stickyOffset = columnOffsets.get(col.key);
|
|
1404
1464
|
const isPinned = Boolean(col.pinned);
|
|
@@ -1406,7 +1466,14 @@ var TableBody = ({
|
|
|
1406
1466
|
if (col.key === "__select__" || col.key === "__expand__")
|
|
1407
1467
|
zIndex = 11;
|
|
1408
1468
|
else if (isPinned) zIndex = 2;
|
|
1409
|
-
|
|
1469
|
+
let recordFingerprint;
|
|
1470
|
+
if (col.render) {
|
|
1471
|
+
try {
|
|
1472
|
+
recordFingerprint = JSON.stringify(row);
|
|
1473
|
+
} catch {
|
|
1474
|
+
recordFingerprint = rk;
|
|
1475
|
+
}
|
|
1476
|
+
}
|
|
1410
1477
|
return /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(
|
|
1411
1478
|
"div",
|
|
1412
1479
|
{
|
|
@@ -1482,9 +1549,11 @@ function arrayMove(arr, from, to) {
|
|
|
1482
1549
|
var SHIMMER_WIDTHS2 = [55, 70, 45, 80, 60, 50, 75, 65, 40, 72];
|
|
1483
1550
|
var EMPTY_CLASSNAMES = {};
|
|
1484
1551
|
var EMPTY_STYLES = {};
|
|
1552
|
+
var STABLE_EMPTY_DATA = [];
|
|
1553
|
+
var STABLE_EMPTY_COLS = [];
|
|
1485
1554
|
function BoltTable({
|
|
1486
|
-
columns:
|
|
1487
|
-
data,
|
|
1555
|
+
columns: rawInitialColumns,
|
|
1556
|
+
data: rawData,
|
|
1488
1557
|
rowHeight = 40,
|
|
1489
1558
|
expandedRowHeight = 200,
|
|
1490
1559
|
maxExpandedRowHeight,
|
|
@@ -1518,6 +1587,18 @@ function BoltTable({
|
|
|
1518
1587
|
rowClassName,
|
|
1519
1588
|
rowStyle
|
|
1520
1589
|
}) {
|
|
1590
|
+
const data = (0, import_react4.useMemo)(() => {
|
|
1591
|
+
if (!Array.isArray(rawData)) return STABLE_EMPTY_DATA;
|
|
1592
|
+
const filtered = rawData.filter((item) => item != null);
|
|
1593
|
+
return filtered.length > 0 ? filtered : STABLE_EMPTY_DATA;
|
|
1594
|
+
}, [rawData]);
|
|
1595
|
+
const initialColumns = (0, import_react4.useMemo)(() => {
|
|
1596
|
+
if (!Array.isArray(rawInitialColumns)) return STABLE_EMPTY_COLS;
|
|
1597
|
+
const filtered = rawInitialColumns.filter(
|
|
1598
|
+
(col) => col != null && typeof col.key === "string"
|
|
1599
|
+
);
|
|
1600
|
+
return filtered.length > 0 ? filtered : STABLE_EMPTY_COLS;
|
|
1601
|
+
}, [rawInitialColumns]);
|
|
1521
1602
|
const [columns, setColumns] = (0, import_react4.useState)(initialColumns);
|
|
1522
1603
|
const [columnOrder, setColumnOrder] = (0, import_react4.useState)(
|
|
1523
1604
|
() => initialColumns.map((c) => c.key)
|
|
@@ -1553,10 +1634,15 @@ function BoltTable({
|
|
|
1553
1634
|
[columns, columnWidths]
|
|
1554
1635
|
);
|
|
1555
1636
|
const [internalExpandedKeys, setInternalExpandedKeys] = (0, import_react4.useState)(() => {
|
|
1556
|
-
if (expandable?.defaultExpandAllRows) {
|
|
1637
|
+
if (expandable?.defaultExpandAllRows && data.length > 0) {
|
|
1557
1638
|
return new Set(
|
|
1558
1639
|
data.map((row, idx) => {
|
|
1559
|
-
if (
|
|
1640
|
+
if (row == null) return idx;
|
|
1641
|
+
try {
|
|
1642
|
+
if (typeof rowKey === "function") return rowKey(row);
|
|
1643
|
+
} catch {
|
|
1644
|
+
return idx;
|
|
1645
|
+
}
|
|
1560
1646
|
if (typeof rowKey === "string")
|
|
1561
1647
|
return row[rowKey] ?? idx;
|
|
1562
1648
|
return idx;
|
|
@@ -1590,21 +1676,39 @@ function BoltTable({
|
|
|
1590
1676
|
}, []);
|
|
1591
1677
|
const getRowKey = (0, import_react4.useCallback)(
|
|
1592
1678
|
(record, index) => {
|
|
1593
|
-
if (
|
|
1594
|
-
|
|
1595
|
-
|
|
1596
|
-
|
|
1679
|
+
if (record == null) return String(index);
|
|
1680
|
+
try {
|
|
1681
|
+
if (typeof rowKey === "function") return String(rowKey(record));
|
|
1682
|
+
if (typeof rowKey === "string") {
|
|
1683
|
+
const val = record[rowKey];
|
|
1684
|
+
return val != null ? String(val) : String(index);
|
|
1685
|
+
}
|
|
1686
|
+
} catch {
|
|
1687
|
+
return String(index);
|
|
1597
1688
|
}
|
|
1598
1689
|
return String(index);
|
|
1599
1690
|
},
|
|
1600
1691
|
[rowKey]
|
|
1601
1692
|
);
|
|
1602
1693
|
const normalizedSelectedKeys = (0, import_react4.useMemo)(
|
|
1603
|
-
() =>
|
|
1694
|
+
() => {
|
|
1695
|
+
const keys = rowSelection?.selectedRowKeys;
|
|
1696
|
+
if (!Array.isArray(keys)) return [];
|
|
1697
|
+
return keys.filter((k) => k != null).map((k) => String(k));
|
|
1698
|
+
},
|
|
1604
1699
|
[rowSelection?.selectedRowKeys]
|
|
1605
1700
|
);
|
|
1701
|
+
const getRowKeyRef = (0, import_react4.useRef)(getRowKey);
|
|
1702
|
+
getRowKeyRef.current = getRowKey;
|
|
1703
|
+
const resolvedExpandedKeysRef = (0, import_react4.useRef)(resolvedExpandedKeys);
|
|
1704
|
+
resolvedExpandedKeysRef.current = resolvedExpandedKeys;
|
|
1705
|
+
const toggleExpandRef = (0, import_react4.useRef)(toggleExpand);
|
|
1706
|
+
toggleExpandRef.current = toggleExpand;
|
|
1707
|
+
const iconsRef = (0, import_react4.useRef)(icons);
|
|
1708
|
+
iconsRef.current = icons;
|
|
1709
|
+
const hasExpandable = !!expandable?.rowExpandable;
|
|
1606
1710
|
const columnsWithExpand = (0, import_react4.useMemo)(() => {
|
|
1607
|
-
if (!
|
|
1711
|
+
if (!hasExpandable) return columnsWithPersistedWidths;
|
|
1608
1712
|
const expandColumn = {
|
|
1609
1713
|
key: "__expand__",
|
|
1610
1714
|
dataIndex: "__expand__",
|
|
@@ -1613,17 +1717,17 @@ function BoltTable({
|
|
|
1613
1717
|
pinned: "left",
|
|
1614
1718
|
hidden: false,
|
|
1615
1719
|
render: (_, record, index) => {
|
|
1616
|
-
const key =
|
|
1617
|
-
const canExpand =
|
|
1618
|
-
const isExpanded =
|
|
1720
|
+
const key = getRowKeyRef.current(record, index);
|
|
1721
|
+
const canExpand = expandableRef.current?.rowExpandable?.(record) ?? true;
|
|
1722
|
+
const isExpanded = resolvedExpandedKeysRef.current.has(key);
|
|
1619
1723
|
if (!canExpand)
|
|
1620
1724
|
return /* @__PURE__ */ (0, import_jsx_runtime5.jsx)("span", { style: { display: "inline-block", width: 16 } });
|
|
1621
|
-
if (typeof
|
|
1622
|
-
return
|
|
1725
|
+
if (typeof expandableRef.current?.expandIcon === "function") {
|
|
1726
|
+
return expandableRef.current.expandIcon({
|
|
1623
1727
|
expanded: isExpanded,
|
|
1624
1728
|
onExpand: (_2, e) => {
|
|
1625
1729
|
e.stopPropagation();
|
|
1626
|
-
|
|
1730
|
+
toggleExpandRef.current(key);
|
|
1627
1731
|
},
|
|
1628
1732
|
record
|
|
1629
1733
|
});
|
|
@@ -1633,7 +1737,7 @@ function BoltTable({
|
|
|
1633
1737
|
{
|
|
1634
1738
|
onClick: (e) => {
|
|
1635
1739
|
e.stopPropagation();
|
|
1636
|
-
|
|
1740
|
+
toggleExpandRef.current(key);
|
|
1637
1741
|
},
|
|
1638
1742
|
style: {
|
|
1639
1743
|
display: "flex",
|
|
@@ -1646,20 +1750,13 @@ function BoltTable({
|
|
|
1646
1750
|
borderRadius: "3px",
|
|
1647
1751
|
color: accentColor
|
|
1648
1752
|
},
|
|
1649
|
-
children: isExpanded ?
|
|
1753
|
+
children: isExpanded ? iconsRef.current?.chevronDown ?? /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(ChevronDownIcon, { style: { width: 14, height: 14 } }) : iconsRef.current?.chevronRight ?? /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(ChevronRightIcon, { style: { width: 14, height: 14 } })
|
|
1650
1754
|
}
|
|
1651
1755
|
);
|
|
1652
1756
|
}
|
|
1653
1757
|
};
|
|
1654
1758
|
return [expandColumn, ...columnsWithPersistedWidths];
|
|
1655
|
-
}, [
|
|
1656
|
-
expandable,
|
|
1657
|
-
columnsWithPersistedWidths,
|
|
1658
|
-
getRowKey,
|
|
1659
|
-
resolvedExpandedKeys,
|
|
1660
|
-
toggleExpand,
|
|
1661
|
-
accentColor
|
|
1662
|
-
]);
|
|
1759
|
+
}, [hasExpandable, columnsWithPersistedWidths, accentColor]);
|
|
1663
1760
|
const columnsWithSelection = (0, import_react4.useMemo)(() => {
|
|
1664
1761
|
if (!rowSelection) return columnsWithExpand;
|
|
1665
1762
|
const selectionColumn = {
|
|
@@ -2019,36 +2116,52 @@ function BoltTable({
|
|
|
2019
2116
|
if (!onFilterChangeRef.current) {
|
|
2020
2117
|
const filterKeys = Object.keys(columnFilters);
|
|
2021
2118
|
if (filterKeys.length > 0) {
|
|
2022
|
-
result = result.filter(
|
|
2023
|
-
(row
|
|
2024
|
-
|
|
2025
|
-
|
|
2026
|
-
|
|
2119
|
+
result = result.filter((row) => {
|
|
2120
|
+
if (row == null) return false;
|
|
2121
|
+
return filterKeys.every((key) => {
|
|
2122
|
+
try {
|
|
2123
|
+
const col = columnsLookupRef.current.find((c) => c.key === key);
|
|
2124
|
+
if (typeof col?.filterFn === "function") {
|
|
2125
|
+
return col.filterFn(columnFilters[key], row, col.dataIndex);
|
|
2126
|
+
}
|
|
2127
|
+
const cellVal = String(row[key] ?? "").toLowerCase();
|
|
2128
|
+
return cellVal.includes(columnFilters[key].toLowerCase());
|
|
2129
|
+
} catch {
|
|
2130
|
+
return true;
|
|
2027
2131
|
}
|
|
2028
|
-
|
|
2029
|
-
|
|
2030
|
-
})
|
|
2031
|
-
);
|
|
2132
|
+
});
|
|
2133
|
+
});
|
|
2032
2134
|
}
|
|
2033
2135
|
}
|
|
2034
2136
|
if (!onSortChangeRef.current && sortState.key && sortState.direction) {
|
|
2035
2137
|
const dir = sortState.direction === "asc" ? 1 : -1;
|
|
2036
2138
|
const key = sortState.key;
|
|
2037
2139
|
const col = columnsLookupRef.current.find((c) => c.key === key);
|
|
2038
|
-
|
|
2039
|
-
|
|
2040
|
-
|
|
2041
|
-
|
|
2042
|
-
|
|
2043
|
-
|
|
2044
|
-
|
|
2045
|
-
|
|
2046
|
-
|
|
2047
|
-
|
|
2048
|
-
|
|
2049
|
-
|
|
2050
|
-
|
|
2051
|
-
|
|
2140
|
+
try {
|
|
2141
|
+
if (typeof col?.sorter === "function") {
|
|
2142
|
+
const sorterFn = col.sorter;
|
|
2143
|
+
result = [...result].sort((a, b) => {
|
|
2144
|
+
if (a == null && b == null) return 0;
|
|
2145
|
+
if (a == null) return 1;
|
|
2146
|
+
if (b == null) return -1;
|
|
2147
|
+
return sorterFn(a, b) * dir;
|
|
2148
|
+
});
|
|
2149
|
+
} else {
|
|
2150
|
+
result = [...result].sort((a, b) => {
|
|
2151
|
+
if (a == null && b == null) return 0;
|
|
2152
|
+
if (a == null) return 1;
|
|
2153
|
+
if (b == null) return -1;
|
|
2154
|
+
const aVal = a[key];
|
|
2155
|
+
const bVal = b[key];
|
|
2156
|
+
if (aVal == null && bVal == null) return 0;
|
|
2157
|
+
if (aVal == null) return 1;
|
|
2158
|
+
if (bVal == null) return -1;
|
|
2159
|
+
if (typeof aVal === "number" && typeof bVal === "number")
|
|
2160
|
+
return (aVal - bVal) * dir;
|
|
2161
|
+
return String(aVal).localeCompare(String(bVal)) * dir;
|
|
2162
|
+
});
|
|
2163
|
+
}
|
|
2164
|
+
} catch {
|
|
2052
2165
|
}
|
|
2053
2166
|
}
|
|
2054
2167
|
return result;
|
|
@@ -2067,6 +2180,7 @@ function BoltTable({
|
|
|
2067
2180
|
const bottomMap = /* @__PURE__ */ new Map();
|
|
2068
2181
|
const rest = [];
|
|
2069
2182
|
processedData.forEach((row, idx) => {
|
|
2183
|
+
if (row == null) return;
|
|
2070
2184
|
const key = getRowKey(row, idx);
|
|
2071
2185
|
if (topKeySet.has(key)) topMap.set(key, row);
|
|
2072
2186
|
else if (bottomKeySet.has(key)) bottomMap.set(key, row);
|
|
@@ -2128,7 +2242,8 @@ function BoltTable({
|
|
|
2128
2242
|
const DEFAULT_PAGE_SIZE = 15;
|
|
2129
2243
|
const [internalPage, setInternalPage] = (0, import_react4.useState)(1);
|
|
2130
2244
|
const [internalPageSize, setInternalPageSize] = (0, import_react4.useState)(DEFAULT_PAGE_SIZE);
|
|
2131
|
-
const
|
|
2245
|
+
const dataLength = data.length;
|
|
2246
|
+
const autoPagination = pagination === void 0 && dataLength > DEFAULT_PAGE_SIZE;
|
|
2132
2247
|
const pgEnabled = pagination === false ? false : !!pagination || autoPagination;
|
|
2133
2248
|
const pgSize = pgEnabled && typeof pagination === "object" && pagination?.pageSize !== void 0 ? pagination.pageSize : internalPageSize;
|
|
2134
2249
|
const isControlledPagination = typeof pagination === "object" && pagination?.current !== void 0;
|
|
@@ -2141,26 +2256,27 @@ function BoltTable({
|
|
|
2141
2256
|
}, [unpinnedProcessedData, needsClientPagination, pgCurrent, pgSize]);
|
|
2142
2257
|
const shimmerCount = pgEnabled ? pgSize : 15;
|
|
2143
2258
|
const showShimmer = isLoading && processedData.length === 0;
|
|
2259
|
+
const shimmerRowKeyField = typeof rowKey === "string" ? rowKey : "id";
|
|
2144
2260
|
const shimmerData = (0, import_react4.useMemo)(() => {
|
|
2145
2261
|
if (!showShimmer) return null;
|
|
2146
2262
|
return Array.from(
|
|
2147
2263
|
{ length: shimmerCount },
|
|
2148
2264
|
(_, i) => ({
|
|
2149
|
-
[
|
|
2265
|
+
[shimmerRowKeyField]: `__shimmer_${i}__`
|
|
2150
2266
|
})
|
|
2151
2267
|
);
|
|
2152
|
-
}, [showShimmer, shimmerCount,
|
|
2268
|
+
}, [showShimmer, shimmerCount, shimmerRowKeyField]);
|
|
2153
2269
|
const INFINITE_SHIMMER_COUNT = 5;
|
|
2270
|
+
const showInfiniteShimmer = isLoading && paginatedData.length > 0 && !showShimmer && !pgEnabled;
|
|
2154
2271
|
const infiniteLoadingShimmer = (0, import_react4.useMemo)(() => {
|
|
2155
|
-
if (!
|
|
2156
|
-
if (pgEnabled) return null;
|
|
2272
|
+
if (!showInfiniteShimmer) return null;
|
|
2157
2273
|
return Array.from(
|
|
2158
2274
|
{ length: INFINITE_SHIMMER_COUNT },
|
|
2159
2275
|
(_, i) => ({
|
|
2160
|
-
[
|
|
2276
|
+
[shimmerRowKeyField]: `__shimmer_${i}__`
|
|
2161
2277
|
})
|
|
2162
2278
|
);
|
|
2163
|
-
}, [
|
|
2279
|
+
}, [showInfiniteShimmer, shimmerRowKeyField]);
|
|
2164
2280
|
const displayData = (0, import_react4.useMemo)(() => {
|
|
2165
2281
|
if (shimmerData) return shimmerData;
|
|
2166
2282
|
if (infiniteLoadingShimmer)
|
|
@@ -2190,13 +2306,20 @@ function BoltTable({
|
|
|
2190
2306
|
getScrollElement: () => tableAreaRef.current,
|
|
2191
2307
|
estimateSize: (index) => {
|
|
2192
2308
|
if (shimmerData) return rowHeight;
|
|
2193
|
-
const
|
|
2309
|
+
const item = displayData[index];
|
|
2310
|
+
if (!item) return rowHeight;
|
|
2311
|
+
const key = getRowKey(item, index);
|
|
2194
2312
|
if (!resolvedExpandedKeys.has(key)) return rowHeight;
|
|
2195
2313
|
const cached = measuredExpandedHeights.current.get(key);
|
|
2196
2314
|
return cached ? rowHeight + cached : rowHeight + expandedRowHeight;
|
|
2197
2315
|
},
|
|
2198
2316
|
overscan: 5,
|
|
2199
|
-
getItemKey: (index) =>
|
|
2317
|
+
getItemKey: (index) => {
|
|
2318
|
+
if (shimmerData) return `__shimmer_${index}__`;
|
|
2319
|
+
const item = displayData[index];
|
|
2320
|
+
if (!item) return `__fallback_${index}__`;
|
|
2321
|
+
return getRowKey(item, index);
|
|
2322
|
+
},
|
|
2200
2323
|
paddingStart: pinnedTopHeight,
|
|
2201
2324
|
paddingEnd: pinnedBottomHeight
|
|
2202
2325
|
});
|
|
@@ -2216,7 +2339,7 @@ function BoltTable({
|
|
|
2216
2339
|
endReachedFiredRef.current = false;
|
|
2217
2340
|
}, 200);
|
|
2218
2341
|
return () => clearTimeout(timer);
|
|
2219
|
-
}, [
|
|
2342
|
+
}, [dataLength, isLoading]);
|
|
2220
2343
|
import_react4.default.useEffect(() => {
|
|
2221
2344
|
const el = tableAreaRef.current;
|
|
2222
2345
|
if (!el) return;
|
|
@@ -2238,7 +2361,7 @@ function BoltTable({
|
|
|
2238
2361
|
const activeColumn = activeId ? orderedColumns.find((col) => col.key === activeId) : null;
|
|
2239
2362
|
const currentPage = pgCurrent;
|
|
2240
2363
|
const pageSize = pgSize;
|
|
2241
|
-
const rawTotal = pgEnabled ? (typeof pagination === "object" ? pagination?.total : void 0) ?? (needsClientPagination ? unpinnedProcessedData.length :
|
|
2364
|
+
const rawTotal = pgEnabled ? (typeof pagination === "object" ? pagination?.total : void 0) ?? (needsClientPagination ? unpinnedProcessedData.length : dataLength) : dataLength;
|
|
2242
2365
|
const lastKnownTotalRef = (0, import_react4.useRef)(0);
|
|
2243
2366
|
if (!isLoading || rawTotal > 0) {
|
|
2244
2367
|
lastKnownTotalRef.current = rawTotal;
|
|
@@ -2246,8 +2369,8 @@ function BoltTable({
|
|
|
2246
2369
|
const total = isLoading && lastKnownTotalRef.current > 0 ? lastKnownTotalRef.current : rawTotal;
|
|
2247
2370
|
const totalPages = Math.max(1, Math.ceil(total / pageSize));
|
|
2248
2371
|
import_react4.default.useEffect(() => {
|
|
2249
|
-
if (internalPage > totalPages) {
|
|
2250
|
-
setInternalPage(
|
|
2372
|
+
if (totalPages > 0 && internalPage > totalPages) {
|
|
2373
|
+
setInternalPage(totalPages);
|
|
2251
2374
|
}
|
|
2252
2375
|
}, [totalPages, internalPage]);
|
|
2253
2376
|
const handlePageChange = (p) => {
|
|
@@ -2582,10 +2705,10 @@ function BoltTable({
|
|
|
2582
2705
|
"input",
|
|
2583
2706
|
{
|
|
2584
2707
|
type: "checkbox",
|
|
2585
|
-
checked:
|
|
2708
|
+
checked: dataLength > 0 && normalizedSelectedKeys.length === dataLength,
|
|
2586
2709
|
ref: (input) => {
|
|
2587
2710
|
if (input) {
|
|
2588
|
-
input.indeterminate = normalizedSelectedKeys.length > 0 && normalizedSelectedKeys.length <
|
|
2711
|
+
input.indeterminate = normalizedSelectedKeys.length > 0 && normalizedSelectedKeys.length < dataLength;
|
|
2589
2712
|
}
|
|
2590
2713
|
},
|
|
2591
2714
|
onChange: (e) => {
|
|
@@ -3058,6 +3181,7 @@ function BoltTable({
|
|
|
3058
3181
|
...pinnedBottomRows
|
|
3059
3182
|
];
|
|
3060
3183
|
for (let i = 0; i < allRows.length; i++) {
|
|
3184
|
+
if (allRows[i] == null) continue;
|
|
3061
3185
|
const rk = getRowKey(allRows[i], i);
|
|
3062
3186
|
if (rk === cellContextMenu.rowKey) {
|
|
3063
3187
|
menuRecord = allRows[i];
|
package/dist/index.mjs
CHANGED
|
@@ -945,7 +945,16 @@ var Cell = React3.memo(
|
|
|
945
945
|
}
|
|
946
946
|
);
|
|
947
947
|
}
|
|
948
|
-
|
|
948
|
+
let content;
|
|
949
|
+
if (column.render) {
|
|
950
|
+
try {
|
|
951
|
+
content = column.render(value, record, rowIndex);
|
|
952
|
+
} catch {
|
|
953
|
+
content = String(value ?? "");
|
|
954
|
+
}
|
|
955
|
+
} else {
|
|
956
|
+
content = value ?? "";
|
|
957
|
+
}
|
|
949
958
|
const isSystem = column.key === "__select__" || column.key === "__expand__";
|
|
950
959
|
return /* @__PURE__ */ jsx4(
|
|
951
960
|
"div",
|
|
@@ -1058,14 +1067,16 @@ var TableBody = ({
|
|
|
1058
1067
|
const virtualItems = rowVirtualizer.getVirtualItems();
|
|
1059
1068
|
const totalSize = rowVirtualizer.getTotalSize();
|
|
1060
1069
|
const selectedKeySet = useMemo(() => new Set(normalizedSelectedKeys), [normalizedSelectedKeys]);
|
|
1070
|
+
const safeData = data ?? [];
|
|
1071
|
+
const safeColumns = orderedColumns ?? [];
|
|
1061
1072
|
const allDataForSelection = useMemo(() => {
|
|
1062
1073
|
if (pinnedTopData.length === 0 && pinnedBottomData.length === 0)
|
|
1063
|
-
return
|
|
1064
|
-
return [...pinnedTopData, ...
|
|
1065
|
-
}, [pinnedTopData,
|
|
1074
|
+
return safeData;
|
|
1075
|
+
return [...pinnedTopData, ...safeData, ...pinnedBottomData];
|
|
1076
|
+
}, [pinnedTopData, safeData, pinnedBottomData]);
|
|
1066
1077
|
const pinnedRowBg = styles?.pinnedRowBg ?? styles?.pinnedBg;
|
|
1067
1078
|
const columnStyles = useMemo(() => {
|
|
1068
|
-
return
|
|
1079
|
+
return safeColumns.map((col, colIndex) => {
|
|
1069
1080
|
const stickyOffset = columnOffsets.get(col.key);
|
|
1070
1081
|
const isPinned = Boolean(col.pinned);
|
|
1071
1082
|
let zIndex = 0;
|
|
@@ -1087,10 +1098,12 @@ var TableBody = ({
|
|
|
1087
1098
|
}
|
|
1088
1099
|
return { key: col.key, style, isPinned };
|
|
1089
1100
|
});
|
|
1090
|
-
}, [
|
|
1101
|
+
}, [safeColumns, columnOffsets, totalSize, styles]);
|
|
1102
|
+
if (safeData.length === 0 || safeColumns.length === 0) return null;
|
|
1091
1103
|
return /* @__PURE__ */ jsxs4(Fragment3, { children: [
|
|
1092
1104
|
columnStyles.map((colStyle, colIndex) => {
|
|
1093
|
-
const col =
|
|
1105
|
+
const col = safeColumns[colIndex];
|
|
1106
|
+
if (!col) return null;
|
|
1094
1107
|
const hasRender = !!col.render;
|
|
1095
1108
|
return /* @__PURE__ */ jsx4(
|
|
1096
1109
|
"div",
|
|
@@ -1098,15 +1111,31 @@ var TableBody = ({
|
|
|
1098
1111
|
...colStyle.isPinned ? { "data-bt-pinned": "" } : {},
|
|
1099
1112
|
style: colStyle.style,
|
|
1100
1113
|
children: virtualItems.map((virtualRow) => {
|
|
1101
|
-
const row =
|
|
1114
|
+
const row = safeData[virtualRow.index];
|
|
1115
|
+
if (row == null) return null;
|
|
1102
1116
|
const rowKey = getRowKey ? getRowKey(row, virtualRow.index) : String(virtualRow.index);
|
|
1103
1117
|
const isSelected = selectedKeySet.has(rowKey);
|
|
1104
1118
|
const isExpanded = resolvedExpandedKeys?.has(rowKey) ?? false;
|
|
1105
1119
|
const cellValue = row[col.dataIndex];
|
|
1106
1120
|
const isRowShimmer = isLoading || rowKey.startsWith("__shimmer_");
|
|
1107
|
-
|
|
1108
|
-
|
|
1109
|
-
|
|
1121
|
+
let recordFingerprint;
|
|
1122
|
+
if (hasRender && !isRowShimmer) {
|
|
1123
|
+
try {
|
|
1124
|
+
recordFingerprint = JSON.stringify(row);
|
|
1125
|
+
} catch {
|
|
1126
|
+
recordFingerprint = rowKey;
|
|
1127
|
+
}
|
|
1128
|
+
}
|
|
1129
|
+
let rowCls = "";
|
|
1130
|
+
try {
|
|
1131
|
+
rowCls = rowClassName ? rowClassName(row, virtualRow.index) : "";
|
|
1132
|
+
} catch {
|
|
1133
|
+
}
|
|
1134
|
+
let rowSty;
|
|
1135
|
+
try {
|
|
1136
|
+
rowSty = rowStyle ? rowStyle(row, virtualRow.index) : void 0;
|
|
1137
|
+
} catch {
|
|
1138
|
+
}
|
|
1110
1139
|
return /* @__PURE__ */ jsx4(
|
|
1111
1140
|
"div",
|
|
1112
1141
|
{
|
|
@@ -1173,9 +1202,15 @@ var TableBody = ({
|
|
|
1173
1202
|
pointerEvents: "none"
|
|
1174
1203
|
},
|
|
1175
1204
|
children: virtualItems.map((virtualRow) => {
|
|
1176
|
-
const row =
|
|
1205
|
+
const row = safeData[virtualRow.index];
|
|
1206
|
+
if (row == null) return null;
|
|
1177
1207
|
const rk = getRowKey ? getRowKey(row, virtualRow.index) : String(virtualRow.index);
|
|
1178
1208
|
if (!(resolvedExpandedKeys?.has(rk) ?? false)) return null;
|
|
1209
|
+
let expandedRenderResult = null;
|
|
1210
|
+
try {
|
|
1211
|
+
expandedRenderResult = expandable.expandedRowRender(row, virtualRow.index, 0, true);
|
|
1212
|
+
} catch {
|
|
1213
|
+
}
|
|
1179
1214
|
const expandedContent = /* @__PURE__ */ jsx4(
|
|
1180
1215
|
"div",
|
|
1181
1216
|
{
|
|
@@ -1193,7 +1228,7 @@ var TableBody = ({
|
|
|
1193
1228
|
...maxExpandedRowHeight ? { maxHeight: `${maxExpandedRowHeight}px` } : void 0,
|
|
1194
1229
|
...styles?.expandedRow
|
|
1195
1230
|
},
|
|
1196
|
-
children:
|
|
1231
|
+
children: expandedRenderResult
|
|
1197
1232
|
}
|
|
1198
1233
|
);
|
|
1199
1234
|
return /* @__PURE__ */ jsx4(
|
|
@@ -1240,11 +1275,20 @@ var TableBody = ({
|
|
|
1240
1275
|
boxShadow: "0 2px 6px -1px rgba(0,0,0,0.08)"
|
|
1241
1276
|
},
|
|
1242
1277
|
children: pinnedTopData.map((row, rowIdx) => {
|
|
1278
|
+
if (row == null) return null;
|
|
1243
1279
|
const rk = getRowKey ? getRowKey(row, rowIdx) : String(rowIdx);
|
|
1244
1280
|
const isSelected = selectedKeySet.has(rk);
|
|
1245
1281
|
const isExpanded = resolvedExpandedKeys?.has(rk) ?? false;
|
|
1246
|
-
|
|
1247
|
-
|
|
1282
|
+
let rowCls = "";
|
|
1283
|
+
try {
|
|
1284
|
+
rowCls = rowClassName ? rowClassName(row, rowIdx) : "";
|
|
1285
|
+
} catch {
|
|
1286
|
+
}
|
|
1287
|
+
let rowSty;
|
|
1288
|
+
try {
|
|
1289
|
+
rowSty = rowStyle ? rowStyle(row, rowIdx) : void 0;
|
|
1290
|
+
} catch {
|
|
1291
|
+
}
|
|
1248
1292
|
return /* @__PURE__ */ jsx4(
|
|
1249
1293
|
"div",
|
|
1250
1294
|
{
|
|
@@ -1256,7 +1300,7 @@ var TableBody = ({
|
|
|
1256
1300
|
...styles?.pinnedRow,
|
|
1257
1301
|
...rowSty
|
|
1258
1302
|
},
|
|
1259
|
-
children:
|
|
1303
|
+
children: safeColumns.map((col) => {
|
|
1260
1304
|
const cellValue = row[col.dataIndex];
|
|
1261
1305
|
const stickyOffset = columnOffsets.get(col.key);
|
|
1262
1306
|
const isPinned = Boolean(col.pinned);
|
|
@@ -1264,7 +1308,14 @@ var TableBody = ({
|
|
|
1264
1308
|
if (col.key === "__select__" || col.key === "__expand__")
|
|
1265
1309
|
zIndex = 11;
|
|
1266
1310
|
else if (isPinned) zIndex = 2;
|
|
1267
|
-
|
|
1311
|
+
let recordFingerprint;
|
|
1312
|
+
if (col.render) {
|
|
1313
|
+
try {
|
|
1314
|
+
recordFingerprint = JSON.stringify(row);
|
|
1315
|
+
} catch {
|
|
1316
|
+
recordFingerprint = rk;
|
|
1317
|
+
}
|
|
1318
|
+
}
|
|
1268
1319
|
return /* @__PURE__ */ jsx4(
|
|
1269
1320
|
"div",
|
|
1270
1321
|
{
|
|
@@ -1348,11 +1399,20 @@ var TableBody = ({
|
|
|
1348
1399
|
boxShadow: "0 -2px 6px -1px rgba(0,0,0,0.08)"
|
|
1349
1400
|
},
|
|
1350
1401
|
children: pinnedBottomData.map((row, rowIdx) => {
|
|
1402
|
+
if (row == null) return null;
|
|
1351
1403
|
const rk = getRowKey ? getRowKey(row, rowIdx) : String(rowIdx);
|
|
1352
1404
|
const isSelected = selectedKeySet.has(rk);
|
|
1353
1405
|
const isExpanded = resolvedExpandedKeys?.has(rk) ?? false;
|
|
1354
|
-
|
|
1355
|
-
|
|
1406
|
+
let rowCls = "";
|
|
1407
|
+
try {
|
|
1408
|
+
rowCls = rowClassName ? rowClassName(row, rowIdx) : "";
|
|
1409
|
+
} catch {
|
|
1410
|
+
}
|
|
1411
|
+
let rowSty;
|
|
1412
|
+
try {
|
|
1413
|
+
rowSty = rowStyle ? rowStyle(row, rowIdx) : void 0;
|
|
1414
|
+
} catch {
|
|
1415
|
+
}
|
|
1356
1416
|
return /* @__PURE__ */ jsx4(
|
|
1357
1417
|
"div",
|
|
1358
1418
|
{
|
|
@@ -1364,7 +1424,7 @@ var TableBody = ({
|
|
|
1364
1424
|
...styles?.pinnedRow,
|
|
1365
1425
|
...rowSty
|
|
1366
1426
|
},
|
|
1367
|
-
children:
|
|
1427
|
+
children: safeColumns.map((col) => {
|
|
1368
1428
|
const cellValue = row[col.dataIndex];
|
|
1369
1429
|
const stickyOffset = columnOffsets.get(col.key);
|
|
1370
1430
|
const isPinned = Boolean(col.pinned);
|
|
@@ -1372,7 +1432,14 @@ var TableBody = ({
|
|
|
1372
1432
|
if (col.key === "__select__" || col.key === "__expand__")
|
|
1373
1433
|
zIndex = 11;
|
|
1374
1434
|
else if (isPinned) zIndex = 2;
|
|
1375
|
-
|
|
1435
|
+
let recordFingerprint;
|
|
1436
|
+
if (col.render) {
|
|
1437
|
+
try {
|
|
1438
|
+
recordFingerprint = JSON.stringify(row);
|
|
1439
|
+
} catch {
|
|
1440
|
+
recordFingerprint = rk;
|
|
1441
|
+
}
|
|
1442
|
+
}
|
|
1376
1443
|
return /* @__PURE__ */ jsx4(
|
|
1377
1444
|
"div",
|
|
1378
1445
|
{
|
|
@@ -1448,9 +1515,11 @@ function arrayMove(arr, from, to) {
|
|
|
1448
1515
|
var SHIMMER_WIDTHS2 = [55, 70, 45, 80, 60, 50, 75, 65, 40, 72];
|
|
1449
1516
|
var EMPTY_CLASSNAMES = {};
|
|
1450
1517
|
var EMPTY_STYLES = {};
|
|
1518
|
+
var STABLE_EMPTY_DATA = [];
|
|
1519
|
+
var STABLE_EMPTY_COLS = [];
|
|
1451
1520
|
function BoltTable({
|
|
1452
|
-
columns:
|
|
1453
|
-
data,
|
|
1521
|
+
columns: rawInitialColumns,
|
|
1522
|
+
data: rawData,
|
|
1454
1523
|
rowHeight = 40,
|
|
1455
1524
|
expandedRowHeight = 200,
|
|
1456
1525
|
maxExpandedRowHeight,
|
|
@@ -1484,6 +1553,18 @@ function BoltTable({
|
|
|
1484
1553
|
rowClassName,
|
|
1485
1554
|
rowStyle
|
|
1486
1555
|
}) {
|
|
1556
|
+
const data = useMemo2(() => {
|
|
1557
|
+
if (!Array.isArray(rawData)) return STABLE_EMPTY_DATA;
|
|
1558
|
+
const filtered = rawData.filter((item) => item != null);
|
|
1559
|
+
return filtered.length > 0 ? filtered : STABLE_EMPTY_DATA;
|
|
1560
|
+
}, [rawData]);
|
|
1561
|
+
const initialColumns = useMemo2(() => {
|
|
1562
|
+
if (!Array.isArray(rawInitialColumns)) return STABLE_EMPTY_COLS;
|
|
1563
|
+
const filtered = rawInitialColumns.filter(
|
|
1564
|
+
(col) => col != null && typeof col.key === "string"
|
|
1565
|
+
);
|
|
1566
|
+
return filtered.length > 0 ? filtered : STABLE_EMPTY_COLS;
|
|
1567
|
+
}, [rawInitialColumns]);
|
|
1487
1568
|
const [columns, setColumns] = useState2(initialColumns);
|
|
1488
1569
|
const [columnOrder, setColumnOrder] = useState2(
|
|
1489
1570
|
() => initialColumns.map((c) => c.key)
|
|
@@ -1519,10 +1600,15 @@ function BoltTable({
|
|
|
1519
1600
|
[columns, columnWidths]
|
|
1520
1601
|
);
|
|
1521
1602
|
const [internalExpandedKeys, setInternalExpandedKeys] = useState2(() => {
|
|
1522
|
-
if (expandable?.defaultExpandAllRows) {
|
|
1603
|
+
if (expandable?.defaultExpandAllRows && data.length > 0) {
|
|
1523
1604
|
return new Set(
|
|
1524
1605
|
data.map((row, idx) => {
|
|
1525
|
-
if (
|
|
1606
|
+
if (row == null) return idx;
|
|
1607
|
+
try {
|
|
1608
|
+
if (typeof rowKey === "function") return rowKey(row);
|
|
1609
|
+
} catch {
|
|
1610
|
+
return idx;
|
|
1611
|
+
}
|
|
1526
1612
|
if (typeof rowKey === "string")
|
|
1527
1613
|
return row[rowKey] ?? idx;
|
|
1528
1614
|
return idx;
|
|
@@ -1556,21 +1642,39 @@ function BoltTable({
|
|
|
1556
1642
|
}, []);
|
|
1557
1643
|
const getRowKey = useCallback(
|
|
1558
1644
|
(record, index) => {
|
|
1559
|
-
if (
|
|
1560
|
-
|
|
1561
|
-
|
|
1562
|
-
|
|
1645
|
+
if (record == null) return String(index);
|
|
1646
|
+
try {
|
|
1647
|
+
if (typeof rowKey === "function") return String(rowKey(record));
|
|
1648
|
+
if (typeof rowKey === "string") {
|
|
1649
|
+
const val = record[rowKey];
|
|
1650
|
+
return val != null ? String(val) : String(index);
|
|
1651
|
+
}
|
|
1652
|
+
} catch {
|
|
1653
|
+
return String(index);
|
|
1563
1654
|
}
|
|
1564
1655
|
return String(index);
|
|
1565
1656
|
},
|
|
1566
1657
|
[rowKey]
|
|
1567
1658
|
);
|
|
1568
1659
|
const normalizedSelectedKeys = useMemo2(
|
|
1569
|
-
() =>
|
|
1660
|
+
() => {
|
|
1661
|
+
const keys = rowSelection?.selectedRowKeys;
|
|
1662
|
+
if (!Array.isArray(keys)) return [];
|
|
1663
|
+
return keys.filter((k) => k != null).map((k) => String(k));
|
|
1664
|
+
},
|
|
1570
1665
|
[rowSelection?.selectedRowKeys]
|
|
1571
1666
|
);
|
|
1667
|
+
const getRowKeyRef = useRef4(getRowKey);
|
|
1668
|
+
getRowKeyRef.current = getRowKey;
|
|
1669
|
+
const resolvedExpandedKeysRef = useRef4(resolvedExpandedKeys);
|
|
1670
|
+
resolvedExpandedKeysRef.current = resolvedExpandedKeys;
|
|
1671
|
+
const toggleExpandRef = useRef4(toggleExpand);
|
|
1672
|
+
toggleExpandRef.current = toggleExpand;
|
|
1673
|
+
const iconsRef = useRef4(icons);
|
|
1674
|
+
iconsRef.current = icons;
|
|
1675
|
+
const hasExpandable = !!expandable?.rowExpandable;
|
|
1572
1676
|
const columnsWithExpand = useMemo2(() => {
|
|
1573
|
-
if (!
|
|
1677
|
+
if (!hasExpandable) return columnsWithPersistedWidths;
|
|
1574
1678
|
const expandColumn = {
|
|
1575
1679
|
key: "__expand__",
|
|
1576
1680
|
dataIndex: "__expand__",
|
|
@@ -1579,17 +1683,17 @@ function BoltTable({
|
|
|
1579
1683
|
pinned: "left",
|
|
1580
1684
|
hidden: false,
|
|
1581
1685
|
render: (_, record, index) => {
|
|
1582
|
-
const key =
|
|
1583
|
-
const canExpand =
|
|
1584
|
-
const isExpanded =
|
|
1686
|
+
const key = getRowKeyRef.current(record, index);
|
|
1687
|
+
const canExpand = expandableRef.current?.rowExpandable?.(record) ?? true;
|
|
1688
|
+
const isExpanded = resolvedExpandedKeysRef.current.has(key);
|
|
1585
1689
|
if (!canExpand)
|
|
1586
1690
|
return /* @__PURE__ */ jsx5("span", { style: { display: "inline-block", width: 16 } });
|
|
1587
|
-
if (typeof
|
|
1588
|
-
return
|
|
1691
|
+
if (typeof expandableRef.current?.expandIcon === "function") {
|
|
1692
|
+
return expandableRef.current.expandIcon({
|
|
1589
1693
|
expanded: isExpanded,
|
|
1590
1694
|
onExpand: (_2, e) => {
|
|
1591
1695
|
e.stopPropagation();
|
|
1592
|
-
|
|
1696
|
+
toggleExpandRef.current(key);
|
|
1593
1697
|
},
|
|
1594
1698
|
record
|
|
1595
1699
|
});
|
|
@@ -1599,7 +1703,7 @@ function BoltTable({
|
|
|
1599
1703
|
{
|
|
1600
1704
|
onClick: (e) => {
|
|
1601
1705
|
e.stopPropagation();
|
|
1602
|
-
|
|
1706
|
+
toggleExpandRef.current(key);
|
|
1603
1707
|
},
|
|
1604
1708
|
style: {
|
|
1605
1709
|
display: "flex",
|
|
@@ -1612,20 +1716,13 @@ function BoltTable({
|
|
|
1612
1716
|
borderRadius: "3px",
|
|
1613
1717
|
color: accentColor
|
|
1614
1718
|
},
|
|
1615
|
-
children: isExpanded ?
|
|
1719
|
+
children: isExpanded ? iconsRef.current?.chevronDown ?? /* @__PURE__ */ jsx5(ChevronDownIcon, { style: { width: 14, height: 14 } }) : iconsRef.current?.chevronRight ?? /* @__PURE__ */ jsx5(ChevronRightIcon, { style: { width: 14, height: 14 } })
|
|
1616
1720
|
}
|
|
1617
1721
|
);
|
|
1618
1722
|
}
|
|
1619
1723
|
};
|
|
1620
1724
|
return [expandColumn, ...columnsWithPersistedWidths];
|
|
1621
|
-
}, [
|
|
1622
|
-
expandable,
|
|
1623
|
-
columnsWithPersistedWidths,
|
|
1624
|
-
getRowKey,
|
|
1625
|
-
resolvedExpandedKeys,
|
|
1626
|
-
toggleExpand,
|
|
1627
|
-
accentColor
|
|
1628
|
-
]);
|
|
1725
|
+
}, [hasExpandable, columnsWithPersistedWidths, accentColor]);
|
|
1629
1726
|
const columnsWithSelection = useMemo2(() => {
|
|
1630
1727
|
if (!rowSelection) return columnsWithExpand;
|
|
1631
1728
|
const selectionColumn = {
|
|
@@ -1985,36 +2082,52 @@ function BoltTable({
|
|
|
1985
2082
|
if (!onFilterChangeRef.current) {
|
|
1986
2083
|
const filterKeys = Object.keys(columnFilters);
|
|
1987
2084
|
if (filterKeys.length > 0) {
|
|
1988
|
-
result = result.filter(
|
|
1989
|
-
(row
|
|
1990
|
-
|
|
1991
|
-
|
|
1992
|
-
|
|
2085
|
+
result = result.filter((row) => {
|
|
2086
|
+
if (row == null) return false;
|
|
2087
|
+
return filterKeys.every((key) => {
|
|
2088
|
+
try {
|
|
2089
|
+
const col = columnsLookupRef.current.find((c) => c.key === key);
|
|
2090
|
+
if (typeof col?.filterFn === "function") {
|
|
2091
|
+
return col.filterFn(columnFilters[key], row, col.dataIndex);
|
|
2092
|
+
}
|
|
2093
|
+
const cellVal = String(row[key] ?? "").toLowerCase();
|
|
2094
|
+
return cellVal.includes(columnFilters[key].toLowerCase());
|
|
2095
|
+
} catch {
|
|
2096
|
+
return true;
|
|
1993
2097
|
}
|
|
1994
|
-
|
|
1995
|
-
|
|
1996
|
-
})
|
|
1997
|
-
);
|
|
2098
|
+
});
|
|
2099
|
+
});
|
|
1998
2100
|
}
|
|
1999
2101
|
}
|
|
2000
2102
|
if (!onSortChangeRef.current && sortState.key && sortState.direction) {
|
|
2001
2103
|
const dir = sortState.direction === "asc" ? 1 : -1;
|
|
2002
2104
|
const key = sortState.key;
|
|
2003
2105
|
const col = columnsLookupRef.current.find((c) => c.key === key);
|
|
2004
|
-
|
|
2005
|
-
|
|
2006
|
-
|
|
2007
|
-
|
|
2008
|
-
|
|
2009
|
-
|
|
2010
|
-
|
|
2011
|
-
|
|
2012
|
-
|
|
2013
|
-
|
|
2014
|
-
|
|
2015
|
-
|
|
2016
|
-
|
|
2017
|
-
|
|
2106
|
+
try {
|
|
2107
|
+
if (typeof col?.sorter === "function") {
|
|
2108
|
+
const sorterFn = col.sorter;
|
|
2109
|
+
result = [...result].sort((a, b) => {
|
|
2110
|
+
if (a == null && b == null) return 0;
|
|
2111
|
+
if (a == null) return 1;
|
|
2112
|
+
if (b == null) return -1;
|
|
2113
|
+
return sorterFn(a, b) * dir;
|
|
2114
|
+
});
|
|
2115
|
+
} else {
|
|
2116
|
+
result = [...result].sort((a, b) => {
|
|
2117
|
+
if (a == null && b == null) return 0;
|
|
2118
|
+
if (a == null) return 1;
|
|
2119
|
+
if (b == null) return -1;
|
|
2120
|
+
const aVal = a[key];
|
|
2121
|
+
const bVal = b[key];
|
|
2122
|
+
if (aVal == null && bVal == null) return 0;
|
|
2123
|
+
if (aVal == null) return 1;
|
|
2124
|
+
if (bVal == null) return -1;
|
|
2125
|
+
if (typeof aVal === "number" && typeof bVal === "number")
|
|
2126
|
+
return (aVal - bVal) * dir;
|
|
2127
|
+
return String(aVal).localeCompare(String(bVal)) * dir;
|
|
2128
|
+
});
|
|
2129
|
+
}
|
|
2130
|
+
} catch {
|
|
2018
2131
|
}
|
|
2019
2132
|
}
|
|
2020
2133
|
return result;
|
|
@@ -2033,6 +2146,7 @@ function BoltTable({
|
|
|
2033
2146
|
const bottomMap = /* @__PURE__ */ new Map();
|
|
2034
2147
|
const rest = [];
|
|
2035
2148
|
processedData.forEach((row, idx) => {
|
|
2149
|
+
if (row == null) return;
|
|
2036
2150
|
const key = getRowKey(row, idx);
|
|
2037
2151
|
if (topKeySet.has(key)) topMap.set(key, row);
|
|
2038
2152
|
else if (bottomKeySet.has(key)) bottomMap.set(key, row);
|
|
@@ -2094,7 +2208,8 @@ function BoltTable({
|
|
|
2094
2208
|
const DEFAULT_PAGE_SIZE = 15;
|
|
2095
2209
|
const [internalPage, setInternalPage] = useState2(1);
|
|
2096
2210
|
const [internalPageSize, setInternalPageSize] = useState2(DEFAULT_PAGE_SIZE);
|
|
2097
|
-
const
|
|
2211
|
+
const dataLength = data.length;
|
|
2212
|
+
const autoPagination = pagination === void 0 && dataLength > DEFAULT_PAGE_SIZE;
|
|
2098
2213
|
const pgEnabled = pagination === false ? false : !!pagination || autoPagination;
|
|
2099
2214
|
const pgSize = pgEnabled && typeof pagination === "object" && pagination?.pageSize !== void 0 ? pagination.pageSize : internalPageSize;
|
|
2100
2215
|
const isControlledPagination = typeof pagination === "object" && pagination?.current !== void 0;
|
|
@@ -2107,26 +2222,27 @@ function BoltTable({
|
|
|
2107
2222
|
}, [unpinnedProcessedData, needsClientPagination, pgCurrent, pgSize]);
|
|
2108
2223
|
const shimmerCount = pgEnabled ? pgSize : 15;
|
|
2109
2224
|
const showShimmer = isLoading && processedData.length === 0;
|
|
2225
|
+
const shimmerRowKeyField = typeof rowKey === "string" ? rowKey : "id";
|
|
2110
2226
|
const shimmerData = useMemo2(() => {
|
|
2111
2227
|
if (!showShimmer) return null;
|
|
2112
2228
|
return Array.from(
|
|
2113
2229
|
{ length: shimmerCount },
|
|
2114
2230
|
(_, i) => ({
|
|
2115
|
-
[
|
|
2231
|
+
[shimmerRowKeyField]: `__shimmer_${i}__`
|
|
2116
2232
|
})
|
|
2117
2233
|
);
|
|
2118
|
-
}, [showShimmer, shimmerCount,
|
|
2234
|
+
}, [showShimmer, shimmerCount, shimmerRowKeyField]);
|
|
2119
2235
|
const INFINITE_SHIMMER_COUNT = 5;
|
|
2236
|
+
const showInfiniteShimmer = isLoading && paginatedData.length > 0 && !showShimmer && !pgEnabled;
|
|
2120
2237
|
const infiniteLoadingShimmer = useMemo2(() => {
|
|
2121
|
-
if (!
|
|
2122
|
-
if (pgEnabled) return null;
|
|
2238
|
+
if (!showInfiniteShimmer) return null;
|
|
2123
2239
|
return Array.from(
|
|
2124
2240
|
{ length: INFINITE_SHIMMER_COUNT },
|
|
2125
2241
|
(_, i) => ({
|
|
2126
|
-
[
|
|
2242
|
+
[shimmerRowKeyField]: `__shimmer_${i}__`
|
|
2127
2243
|
})
|
|
2128
2244
|
);
|
|
2129
|
-
}, [
|
|
2245
|
+
}, [showInfiniteShimmer, shimmerRowKeyField]);
|
|
2130
2246
|
const displayData = useMemo2(() => {
|
|
2131
2247
|
if (shimmerData) return shimmerData;
|
|
2132
2248
|
if (infiniteLoadingShimmer)
|
|
@@ -2156,13 +2272,20 @@ function BoltTable({
|
|
|
2156
2272
|
getScrollElement: () => tableAreaRef.current,
|
|
2157
2273
|
estimateSize: (index) => {
|
|
2158
2274
|
if (shimmerData) return rowHeight;
|
|
2159
|
-
const
|
|
2275
|
+
const item = displayData[index];
|
|
2276
|
+
if (!item) return rowHeight;
|
|
2277
|
+
const key = getRowKey(item, index);
|
|
2160
2278
|
if (!resolvedExpandedKeys.has(key)) return rowHeight;
|
|
2161
2279
|
const cached = measuredExpandedHeights.current.get(key);
|
|
2162
2280
|
return cached ? rowHeight + cached : rowHeight + expandedRowHeight;
|
|
2163
2281
|
},
|
|
2164
2282
|
overscan: 5,
|
|
2165
|
-
getItemKey: (index) =>
|
|
2283
|
+
getItemKey: (index) => {
|
|
2284
|
+
if (shimmerData) return `__shimmer_${index}__`;
|
|
2285
|
+
const item = displayData[index];
|
|
2286
|
+
if (!item) return `__fallback_${index}__`;
|
|
2287
|
+
return getRowKey(item, index);
|
|
2288
|
+
},
|
|
2166
2289
|
paddingStart: pinnedTopHeight,
|
|
2167
2290
|
paddingEnd: pinnedBottomHeight
|
|
2168
2291
|
});
|
|
@@ -2182,7 +2305,7 @@ function BoltTable({
|
|
|
2182
2305
|
endReachedFiredRef.current = false;
|
|
2183
2306
|
}, 200);
|
|
2184
2307
|
return () => clearTimeout(timer);
|
|
2185
|
-
}, [
|
|
2308
|
+
}, [dataLength, isLoading]);
|
|
2186
2309
|
React4.useEffect(() => {
|
|
2187
2310
|
const el = tableAreaRef.current;
|
|
2188
2311
|
if (!el) return;
|
|
@@ -2204,7 +2327,7 @@ function BoltTable({
|
|
|
2204
2327
|
const activeColumn = activeId ? orderedColumns.find((col) => col.key === activeId) : null;
|
|
2205
2328
|
const currentPage = pgCurrent;
|
|
2206
2329
|
const pageSize = pgSize;
|
|
2207
|
-
const rawTotal = pgEnabled ? (typeof pagination === "object" ? pagination?.total : void 0) ?? (needsClientPagination ? unpinnedProcessedData.length :
|
|
2330
|
+
const rawTotal = pgEnabled ? (typeof pagination === "object" ? pagination?.total : void 0) ?? (needsClientPagination ? unpinnedProcessedData.length : dataLength) : dataLength;
|
|
2208
2331
|
const lastKnownTotalRef = useRef4(0);
|
|
2209
2332
|
if (!isLoading || rawTotal > 0) {
|
|
2210
2333
|
lastKnownTotalRef.current = rawTotal;
|
|
@@ -2212,8 +2335,8 @@ function BoltTable({
|
|
|
2212
2335
|
const total = isLoading && lastKnownTotalRef.current > 0 ? lastKnownTotalRef.current : rawTotal;
|
|
2213
2336
|
const totalPages = Math.max(1, Math.ceil(total / pageSize));
|
|
2214
2337
|
React4.useEffect(() => {
|
|
2215
|
-
if (internalPage > totalPages) {
|
|
2216
|
-
setInternalPage(
|
|
2338
|
+
if (totalPages > 0 && internalPage > totalPages) {
|
|
2339
|
+
setInternalPage(totalPages);
|
|
2217
2340
|
}
|
|
2218
2341
|
}, [totalPages, internalPage]);
|
|
2219
2342
|
const handlePageChange = (p) => {
|
|
@@ -2548,10 +2671,10 @@ function BoltTable({
|
|
|
2548
2671
|
"input",
|
|
2549
2672
|
{
|
|
2550
2673
|
type: "checkbox",
|
|
2551
|
-
checked:
|
|
2674
|
+
checked: dataLength > 0 && normalizedSelectedKeys.length === dataLength,
|
|
2552
2675
|
ref: (input) => {
|
|
2553
2676
|
if (input) {
|
|
2554
|
-
input.indeterminate = normalizedSelectedKeys.length > 0 && normalizedSelectedKeys.length <
|
|
2677
|
+
input.indeterminate = normalizedSelectedKeys.length > 0 && normalizedSelectedKeys.length < dataLength;
|
|
2555
2678
|
}
|
|
2556
2679
|
},
|
|
2557
2680
|
onChange: (e) => {
|
|
@@ -3024,6 +3147,7 @@ function BoltTable({
|
|
|
3024
3147
|
...pinnedBottomRows
|
|
3025
3148
|
];
|
|
3026
3149
|
for (let i = 0; i < allRows.length; i++) {
|
|
3150
|
+
if (allRows[i] == null) continue;
|
|
3027
3151
|
const rk = getRowKey(allRows[i], i);
|
|
3028
3152
|
if (rk === cellContextMenu.rowKey) {
|
|
3029
3153
|
menuRecord = allRows[i];
|
package/package.json
CHANGED