bolt-table 0.1.18 → 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 +10 -2
- package/dist/index.d.ts +10 -2
- package/dist/index.js +227 -87
- package/dist/index.mjs +227 -87
- package/package.json +1 -1
package/dist/index.d.mts
CHANGED
|
@@ -232,6 +232,10 @@ interface BoltTableProps<T extends DataRecord = DataRecord> {
|
|
|
232
232
|
readonly layoutLoading?: boolean;
|
|
233
233
|
/** Custom React node to render when the table has no data and is not loading. */
|
|
234
234
|
readonly emptyRenderer?: React$1.ReactNode;
|
|
235
|
+
/** Returns a CSS class name for a given row based on its record and index. Useful for Tailwind or any CSS class-based conditional row styling. */
|
|
236
|
+
readonly rowClassName?: (record: T, index: number) => string;
|
|
237
|
+
/** Returns inline CSS styles for a given row based on its record and index. Useful for dynamic per-row styling. */
|
|
238
|
+
readonly rowStyle?: (record: T, index: number) => React$1.CSSProperties;
|
|
235
239
|
}
|
|
236
240
|
interface ClassNamesTypes {
|
|
237
241
|
/** Applied to all non-pinned column header cells. */
|
|
@@ -277,7 +281,7 @@ interface StylesTypes {
|
|
|
277
281
|
/** CSS color string for pinned column cells and headers background. */
|
|
278
282
|
pinnedBg?: string;
|
|
279
283
|
}
|
|
280
|
-
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;
|
|
281
285
|
|
|
282
286
|
interface DraggableHeaderProps {
|
|
283
287
|
/** Column definition for this header cell. */
|
|
@@ -381,7 +385,11 @@ interface TableBodyProps {
|
|
|
381
385
|
gridTemplateColumns?: string;
|
|
382
386
|
/** Height of the column header row in pixels */
|
|
383
387
|
headerHeight?: number;
|
|
388
|
+
/** Returns a CSS class name for a given row based on its record and index */
|
|
389
|
+
rowClassName?: (record: DataRecord, index: number) => string;
|
|
390
|
+
/** Returns inline CSS styles for a given row based on its record and index */
|
|
391
|
+
rowStyle?: (record: DataRecord, index: number) => React$1.CSSProperties;
|
|
384
392
|
}
|
|
385
393
|
declare const TableBody: React$1.FC<TableBodyProps>;
|
|
386
394
|
|
|
387
|
-
export { BoltTable, type BoltTableIcons, type CellContextMenuItem, type ColumnContextMenuItem, type ColumnType, type DataRecord, DraggableHeader, type ExpandableConfig, type PaginationType, ResizeOverlay, type RowPinningConfig, type RowSelectionConfig, type SortDirection, TableBody };
|
|
395
|
+
export { BoltTable, type BoltTableIcons, type CellContextMenuItem, type ClassNamesTypes, type ColumnContextMenuItem, type ColumnType, type DataRecord, DraggableHeader, type ExpandableConfig, type PaginationType, ResizeOverlay, type RowPinningConfig, type RowSelectionConfig, type SortDirection, type StylesTypes, TableBody };
|
package/dist/index.d.ts
CHANGED
|
@@ -232,6 +232,10 @@ interface BoltTableProps<T extends DataRecord = DataRecord> {
|
|
|
232
232
|
readonly layoutLoading?: boolean;
|
|
233
233
|
/** Custom React node to render when the table has no data and is not loading. */
|
|
234
234
|
readonly emptyRenderer?: React$1.ReactNode;
|
|
235
|
+
/** Returns a CSS class name for a given row based on its record and index. Useful for Tailwind or any CSS class-based conditional row styling. */
|
|
236
|
+
readonly rowClassName?: (record: T, index: number) => string;
|
|
237
|
+
/** Returns inline CSS styles for a given row based on its record and index. Useful for dynamic per-row styling. */
|
|
238
|
+
readonly rowStyle?: (record: T, index: number) => React$1.CSSProperties;
|
|
235
239
|
}
|
|
236
240
|
interface ClassNamesTypes {
|
|
237
241
|
/** Applied to all non-pinned column header cells. */
|
|
@@ -277,7 +281,7 @@ interface StylesTypes {
|
|
|
277
281
|
/** CSS color string for pinned column cells and headers background. */
|
|
278
282
|
pinnedBg?: string;
|
|
279
283
|
}
|
|
280
|
-
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;
|
|
281
285
|
|
|
282
286
|
interface DraggableHeaderProps {
|
|
283
287
|
/** Column definition for this header cell. */
|
|
@@ -381,7 +385,11 @@ interface TableBodyProps {
|
|
|
381
385
|
gridTemplateColumns?: string;
|
|
382
386
|
/** Height of the column header row in pixels */
|
|
383
387
|
headerHeight?: number;
|
|
388
|
+
/** Returns a CSS class name for a given row based on its record and index */
|
|
389
|
+
rowClassName?: (record: DataRecord, index: number) => string;
|
|
390
|
+
/** Returns inline CSS styles for a given row based on its record and index */
|
|
391
|
+
rowStyle?: (record: DataRecord, index: number) => React$1.CSSProperties;
|
|
384
392
|
}
|
|
385
393
|
declare const TableBody: React$1.FC<TableBodyProps>;
|
|
386
394
|
|
|
387
|
-
export { BoltTable, type BoltTableIcons, type CellContextMenuItem, type ColumnContextMenuItem, type ColumnType, type DataRecord, DraggableHeader, type ExpandableConfig, type PaginationType, ResizeOverlay, type RowPinningConfig, type RowSelectionConfig, type SortDirection, TableBody };
|
|
395
|
+
export { BoltTable, type BoltTableIcons, type CellContextMenuItem, type ClassNamesTypes, type ColumnContextMenuItem, type ColumnType, type DataRecord, DraggableHeader, type ExpandableConfig, type PaginationType, ResizeOverlay, type RowPinningConfig, type RowSelectionConfig, type SortDirection, type StylesTypes, TableBody };
|
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",
|
|
@@ -1085,19 +1094,23 @@ var TableBody = ({
|
|
|
1085
1094
|
pinnedTopData = [],
|
|
1086
1095
|
pinnedBottomData = [],
|
|
1087
1096
|
gridTemplateColumns,
|
|
1088
|
-
headerHeight = 36
|
|
1097
|
+
headerHeight = 36,
|
|
1098
|
+
rowClassName,
|
|
1099
|
+
rowStyle
|
|
1089
1100
|
}) => {
|
|
1090
1101
|
const virtualItems = rowVirtualizer.getVirtualItems();
|
|
1091
1102
|
const totalSize = rowVirtualizer.getTotalSize();
|
|
1092
1103
|
const selectedKeySet = (0, import_react3.useMemo)(() => new Set(normalizedSelectedKeys), [normalizedSelectedKeys]);
|
|
1104
|
+
const safeData = data ?? [];
|
|
1105
|
+
const safeColumns = orderedColumns ?? [];
|
|
1093
1106
|
const allDataForSelection = (0, import_react3.useMemo)(() => {
|
|
1094
1107
|
if (pinnedTopData.length === 0 && pinnedBottomData.length === 0)
|
|
1095
|
-
return
|
|
1096
|
-
return [...pinnedTopData, ...
|
|
1097
|
-
}, [pinnedTopData,
|
|
1108
|
+
return safeData;
|
|
1109
|
+
return [...pinnedTopData, ...safeData, ...pinnedBottomData];
|
|
1110
|
+
}, [pinnedTopData, safeData, pinnedBottomData]);
|
|
1098
1111
|
const pinnedRowBg = styles?.pinnedRowBg ?? styles?.pinnedBg;
|
|
1099
1112
|
const columnStyles = (0, import_react3.useMemo)(() => {
|
|
1100
|
-
return
|
|
1113
|
+
return safeColumns.map((col, colIndex) => {
|
|
1101
1114
|
const stickyOffset = columnOffsets.get(col.key);
|
|
1102
1115
|
const isPinned = Boolean(col.pinned);
|
|
1103
1116
|
let zIndex = 0;
|
|
@@ -1119,10 +1132,12 @@ var TableBody = ({
|
|
|
1119
1132
|
}
|
|
1120
1133
|
return { key: col.key, style, isPinned };
|
|
1121
1134
|
});
|
|
1122
|
-
}, [
|
|
1135
|
+
}, [safeColumns, columnOffsets, totalSize, styles]);
|
|
1136
|
+
if (safeData.length === 0 || safeColumns.length === 0) return null;
|
|
1123
1137
|
return /* @__PURE__ */ (0, import_jsx_runtime4.jsxs)(import_jsx_runtime4.Fragment, { children: [
|
|
1124
1138
|
columnStyles.map((colStyle, colIndex) => {
|
|
1125
|
-
const col =
|
|
1139
|
+
const col = safeColumns[colIndex];
|
|
1140
|
+
if (!col) return null;
|
|
1126
1141
|
const hasRender = !!col.render;
|
|
1127
1142
|
return /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(
|
|
1128
1143
|
"div",
|
|
@@ -1130,13 +1145,31 @@ var TableBody = ({
|
|
|
1130
1145
|
...colStyle.isPinned ? { "data-bt-pinned": "" } : {},
|
|
1131
1146
|
style: colStyle.style,
|
|
1132
1147
|
children: virtualItems.map((virtualRow) => {
|
|
1133
|
-
const row =
|
|
1148
|
+
const row = safeData[virtualRow.index];
|
|
1149
|
+
if (row == null) return null;
|
|
1134
1150
|
const rowKey = getRowKey ? getRowKey(row, virtualRow.index) : String(virtualRow.index);
|
|
1135
1151
|
const isSelected = selectedKeySet.has(rowKey);
|
|
1136
1152
|
const isExpanded = resolvedExpandedKeys?.has(rowKey) ?? false;
|
|
1137
1153
|
const cellValue = row[col.dataIndex];
|
|
1138
1154
|
const isRowShimmer = isLoading || rowKey.startsWith("__shimmer_");
|
|
1139
|
-
|
|
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
|
+
}
|
|
1140
1173
|
return /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(
|
|
1141
1174
|
"div",
|
|
1142
1175
|
{
|
|
@@ -1144,12 +1177,14 @@ var TableBody = ({
|
|
|
1144
1177
|
"data-column-key": col.key,
|
|
1145
1178
|
"data-bt-cell": "",
|
|
1146
1179
|
"data-selected": isSelected || void 0,
|
|
1180
|
+
className: rowCls || void 0,
|
|
1147
1181
|
style: {
|
|
1148
1182
|
position: "absolute",
|
|
1149
1183
|
top: `${virtualRow.start}px`,
|
|
1150
1184
|
left: 0,
|
|
1151
1185
|
right: 0,
|
|
1152
|
-
height: `${virtualRow.size}px
|
|
1186
|
+
height: `${virtualRow.size}px`,
|
|
1187
|
+
...rowSty
|
|
1153
1188
|
},
|
|
1154
1189
|
children: /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(
|
|
1155
1190
|
"div",
|
|
@@ -1201,9 +1236,15 @@ var TableBody = ({
|
|
|
1201
1236
|
pointerEvents: "none"
|
|
1202
1237
|
},
|
|
1203
1238
|
children: virtualItems.map((virtualRow) => {
|
|
1204
|
-
const row =
|
|
1239
|
+
const row = safeData[virtualRow.index];
|
|
1240
|
+
if (row == null) return null;
|
|
1205
1241
|
const rk = getRowKey ? getRowKey(row, virtualRow.index) : String(virtualRow.index);
|
|
1206
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
|
+
}
|
|
1207
1248
|
const expandedContent = /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(
|
|
1208
1249
|
"div",
|
|
1209
1250
|
{
|
|
@@ -1221,7 +1262,7 @@ var TableBody = ({
|
|
|
1221
1262
|
...maxExpandedRowHeight ? { maxHeight: `${maxExpandedRowHeight}px` } : void 0,
|
|
1222
1263
|
...styles?.expandedRow
|
|
1223
1264
|
},
|
|
1224
|
-
children:
|
|
1265
|
+
children: expandedRenderResult
|
|
1225
1266
|
}
|
|
1226
1267
|
);
|
|
1227
1268
|
return /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(
|
|
@@ -1268,20 +1309,32 @@ var TableBody = ({
|
|
|
1268
1309
|
boxShadow: "0 2px 6px -1px rgba(0,0,0,0.08)"
|
|
1269
1310
|
},
|
|
1270
1311
|
children: pinnedTopData.map((row, rowIdx) => {
|
|
1312
|
+
if (row == null) return null;
|
|
1271
1313
|
const rk = getRowKey ? getRowKey(row, rowIdx) : String(rowIdx);
|
|
1272
1314
|
const isSelected = selectedKeySet.has(rk);
|
|
1273
1315
|
const isExpanded = resolvedExpandedKeys?.has(rk) ?? false;
|
|
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
|
+
}
|
|
1274
1326
|
return /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(
|
|
1275
1327
|
"div",
|
|
1276
1328
|
{
|
|
1277
|
-
className: classNames?.pinnedRow ?? "",
|
|
1329
|
+
className: `${classNames?.pinnedRow ?? ""} ${rowCls}`.trim() || void 0,
|
|
1278
1330
|
style: {
|
|
1279
1331
|
display: "grid",
|
|
1280
1332
|
gridTemplateColumns: gridTemplateColumns ?? "",
|
|
1281
1333
|
minWidth: totalTableWidth ? `${totalTableWidth}px` : void 0,
|
|
1282
|
-
...styles?.pinnedRow
|
|
1334
|
+
...styles?.pinnedRow,
|
|
1335
|
+
...rowSty
|
|
1283
1336
|
},
|
|
1284
|
-
children:
|
|
1337
|
+
children: safeColumns.map((col) => {
|
|
1285
1338
|
const cellValue = row[col.dataIndex];
|
|
1286
1339
|
const stickyOffset = columnOffsets.get(col.key);
|
|
1287
1340
|
const isPinned = Boolean(col.pinned);
|
|
@@ -1289,7 +1342,14 @@ var TableBody = ({
|
|
|
1289
1342
|
if (col.key === "__select__" || col.key === "__expand__")
|
|
1290
1343
|
zIndex = 11;
|
|
1291
1344
|
else if (isPinned) zIndex = 2;
|
|
1292
|
-
|
|
1345
|
+
let recordFingerprint;
|
|
1346
|
+
if (col.render) {
|
|
1347
|
+
try {
|
|
1348
|
+
recordFingerprint = JSON.stringify(row);
|
|
1349
|
+
} catch {
|
|
1350
|
+
recordFingerprint = rk;
|
|
1351
|
+
}
|
|
1352
|
+
}
|
|
1293
1353
|
return /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(
|
|
1294
1354
|
"div",
|
|
1295
1355
|
{
|
|
@@ -1373,20 +1433,32 @@ var TableBody = ({
|
|
|
1373
1433
|
boxShadow: "0 -2px 6px -1px rgba(0,0,0,0.08)"
|
|
1374
1434
|
},
|
|
1375
1435
|
children: pinnedBottomData.map((row, rowIdx) => {
|
|
1436
|
+
if (row == null) return null;
|
|
1376
1437
|
const rk = getRowKey ? getRowKey(row, rowIdx) : String(rowIdx);
|
|
1377
1438
|
const isSelected = selectedKeySet.has(rk);
|
|
1378
1439
|
const isExpanded = resolvedExpandedKeys?.has(rk) ?? false;
|
|
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
|
+
}
|
|
1379
1450
|
return /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(
|
|
1380
1451
|
"div",
|
|
1381
1452
|
{
|
|
1382
|
-
className: classNames?.pinnedRow ?? "",
|
|
1453
|
+
className: `${classNames?.pinnedRow ?? ""} ${rowCls}`.trim() || void 0,
|
|
1383
1454
|
style: {
|
|
1384
1455
|
display: "grid",
|
|
1385
1456
|
gridTemplateColumns: gridTemplateColumns ?? "",
|
|
1386
1457
|
minWidth: totalTableWidth ? `${totalTableWidth}px` : void 0,
|
|
1387
|
-
...styles?.pinnedRow
|
|
1458
|
+
...styles?.pinnedRow,
|
|
1459
|
+
...rowSty
|
|
1388
1460
|
},
|
|
1389
|
-
children:
|
|
1461
|
+
children: safeColumns.map((col) => {
|
|
1390
1462
|
const cellValue = row[col.dataIndex];
|
|
1391
1463
|
const stickyOffset = columnOffsets.get(col.key);
|
|
1392
1464
|
const isPinned = Boolean(col.pinned);
|
|
@@ -1394,7 +1466,14 @@ var TableBody = ({
|
|
|
1394
1466
|
if (col.key === "__select__" || col.key === "__expand__")
|
|
1395
1467
|
zIndex = 11;
|
|
1396
1468
|
else if (isPinned) zIndex = 2;
|
|
1397
|
-
|
|
1469
|
+
let recordFingerprint;
|
|
1470
|
+
if (col.render) {
|
|
1471
|
+
try {
|
|
1472
|
+
recordFingerprint = JSON.stringify(row);
|
|
1473
|
+
} catch {
|
|
1474
|
+
recordFingerprint = rk;
|
|
1475
|
+
}
|
|
1476
|
+
}
|
|
1398
1477
|
return /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(
|
|
1399
1478
|
"div",
|
|
1400
1479
|
{
|
|
@@ -1470,9 +1549,11 @@ function arrayMove(arr, from, to) {
|
|
|
1470
1549
|
var SHIMMER_WIDTHS2 = [55, 70, 45, 80, 60, 50, 75, 65, 40, 72];
|
|
1471
1550
|
var EMPTY_CLASSNAMES = {};
|
|
1472
1551
|
var EMPTY_STYLES = {};
|
|
1552
|
+
var STABLE_EMPTY_DATA = [];
|
|
1553
|
+
var STABLE_EMPTY_COLS = [];
|
|
1473
1554
|
function BoltTable({
|
|
1474
|
-
columns:
|
|
1475
|
-
data,
|
|
1555
|
+
columns: rawInitialColumns,
|
|
1556
|
+
data: rawData,
|
|
1476
1557
|
rowHeight = 40,
|
|
1477
1558
|
expandedRowHeight = 200,
|
|
1478
1559
|
maxExpandedRowHeight,
|
|
@@ -1502,8 +1583,22 @@ function BoltTable({
|
|
|
1502
1583
|
columnContextMenuItems,
|
|
1503
1584
|
autoHeight = true,
|
|
1504
1585
|
layoutLoading,
|
|
1505
|
-
emptyRenderer
|
|
1586
|
+
emptyRenderer,
|
|
1587
|
+
rowClassName,
|
|
1588
|
+
rowStyle
|
|
1506
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]);
|
|
1507
1602
|
const [columns, setColumns] = (0, import_react4.useState)(initialColumns);
|
|
1508
1603
|
const [columnOrder, setColumnOrder] = (0, import_react4.useState)(
|
|
1509
1604
|
() => initialColumns.map((c) => c.key)
|
|
@@ -1539,10 +1634,15 @@ function BoltTable({
|
|
|
1539
1634
|
[columns, columnWidths]
|
|
1540
1635
|
);
|
|
1541
1636
|
const [internalExpandedKeys, setInternalExpandedKeys] = (0, import_react4.useState)(() => {
|
|
1542
|
-
if (expandable?.defaultExpandAllRows) {
|
|
1637
|
+
if (expandable?.defaultExpandAllRows && data.length > 0) {
|
|
1543
1638
|
return new Set(
|
|
1544
1639
|
data.map((row, idx) => {
|
|
1545
|
-
if (
|
|
1640
|
+
if (row == null) return idx;
|
|
1641
|
+
try {
|
|
1642
|
+
if (typeof rowKey === "function") return rowKey(row);
|
|
1643
|
+
} catch {
|
|
1644
|
+
return idx;
|
|
1645
|
+
}
|
|
1546
1646
|
if (typeof rowKey === "string")
|
|
1547
1647
|
return row[rowKey] ?? idx;
|
|
1548
1648
|
return idx;
|
|
@@ -1576,21 +1676,39 @@ function BoltTable({
|
|
|
1576
1676
|
}, []);
|
|
1577
1677
|
const getRowKey = (0, import_react4.useCallback)(
|
|
1578
1678
|
(record, index) => {
|
|
1579
|
-
if (
|
|
1580
|
-
|
|
1581
|
-
|
|
1582
|
-
|
|
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);
|
|
1583
1688
|
}
|
|
1584
1689
|
return String(index);
|
|
1585
1690
|
},
|
|
1586
1691
|
[rowKey]
|
|
1587
1692
|
);
|
|
1588
1693
|
const normalizedSelectedKeys = (0, import_react4.useMemo)(
|
|
1589
|
-
() =>
|
|
1694
|
+
() => {
|
|
1695
|
+
const keys = rowSelection?.selectedRowKeys;
|
|
1696
|
+
if (!Array.isArray(keys)) return [];
|
|
1697
|
+
return keys.filter((k) => k != null).map((k) => String(k));
|
|
1698
|
+
},
|
|
1590
1699
|
[rowSelection?.selectedRowKeys]
|
|
1591
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;
|
|
1592
1710
|
const columnsWithExpand = (0, import_react4.useMemo)(() => {
|
|
1593
|
-
if (!
|
|
1711
|
+
if (!hasExpandable) return columnsWithPersistedWidths;
|
|
1594
1712
|
const expandColumn = {
|
|
1595
1713
|
key: "__expand__",
|
|
1596
1714
|
dataIndex: "__expand__",
|
|
@@ -1599,17 +1717,17 @@ function BoltTable({
|
|
|
1599
1717
|
pinned: "left",
|
|
1600
1718
|
hidden: false,
|
|
1601
1719
|
render: (_, record, index) => {
|
|
1602
|
-
const key =
|
|
1603
|
-
const canExpand =
|
|
1604
|
-
const isExpanded =
|
|
1720
|
+
const key = getRowKeyRef.current(record, index);
|
|
1721
|
+
const canExpand = expandableRef.current?.rowExpandable?.(record) ?? true;
|
|
1722
|
+
const isExpanded = resolvedExpandedKeysRef.current.has(key);
|
|
1605
1723
|
if (!canExpand)
|
|
1606
1724
|
return /* @__PURE__ */ (0, import_jsx_runtime5.jsx)("span", { style: { display: "inline-block", width: 16 } });
|
|
1607
|
-
if (typeof
|
|
1608
|
-
return
|
|
1725
|
+
if (typeof expandableRef.current?.expandIcon === "function") {
|
|
1726
|
+
return expandableRef.current.expandIcon({
|
|
1609
1727
|
expanded: isExpanded,
|
|
1610
1728
|
onExpand: (_2, e) => {
|
|
1611
1729
|
e.stopPropagation();
|
|
1612
|
-
|
|
1730
|
+
toggleExpandRef.current(key);
|
|
1613
1731
|
},
|
|
1614
1732
|
record
|
|
1615
1733
|
});
|
|
@@ -1619,7 +1737,7 @@ function BoltTable({
|
|
|
1619
1737
|
{
|
|
1620
1738
|
onClick: (e) => {
|
|
1621
1739
|
e.stopPropagation();
|
|
1622
|
-
|
|
1740
|
+
toggleExpandRef.current(key);
|
|
1623
1741
|
},
|
|
1624
1742
|
style: {
|
|
1625
1743
|
display: "flex",
|
|
@@ -1632,20 +1750,13 @@ function BoltTable({
|
|
|
1632
1750
|
borderRadius: "3px",
|
|
1633
1751
|
color: accentColor
|
|
1634
1752
|
},
|
|
1635
|
-
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 } })
|
|
1636
1754
|
}
|
|
1637
1755
|
);
|
|
1638
1756
|
}
|
|
1639
1757
|
};
|
|
1640
1758
|
return [expandColumn, ...columnsWithPersistedWidths];
|
|
1641
|
-
}, [
|
|
1642
|
-
expandable,
|
|
1643
|
-
columnsWithPersistedWidths,
|
|
1644
|
-
getRowKey,
|
|
1645
|
-
resolvedExpandedKeys,
|
|
1646
|
-
toggleExpand,
|
|
1647
|
-
accentColor
|
|
1648
|
-
]);
|
|
1759
|
+
}, [hasExpandable, columnsWithPersistedWidths, accentColor]);
|
|
1649
1760
|
const columnsWithSelection = (0, import_react4.useMemo)(() => {
|
|
1650
1761
|
if (!rowSelection) return columnsWithExpand;
|
|
1651
1762
|
const selectionColumn = {
|
|
@@ -2005,36 +2116,52 @@ function BoltTable({
|
|
|
2005
2116
|
if (!onFilterChangeRef.current) {
|
|
2006
2117
|
const filterKeys = Object.keys(columnFilters);
|
|
2007
2118
|
if (filterKeys.length > 0) {
|
|
2008
|
-
result = result.filter(
|
|
2009
|
-
(row
|
|
2010
|
-
|
|
2011
|
-
|
|
2012
|
-
|
|
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;
|
|
2013
2131
|
}
|
|
2014
|
-
|
|
2015
|
-
|
|
2016
|
-
})
|
|
2017
|
-
);
|
|
2132
|
+
});
|
|
2133
|
+
});
|
|
2018
2134
|
}
|
|
2019
2135
|
}
|
|
2020
2136
|
if (!onSortChangeRef.current && sortState.key && sortState.direction) {
|
|
2021
2137
|
const dir = sortState.direction === "asc" ? 1 : -1;
|
|
2022
2138
|
const key = sortState.key;
|
|
2023
2139
|
const col = columnsLookupRef.current.find((c) => c.key === key);
|
|
2024
|
-
|
|
2025
|
-
|
|
2026
|
-
|
|
2027
|
-
|
|
2028
|
-
|
|
2029
|
-
|
|
2030
|
-
|
|
2031
|
-
|
|
2032
|
-
|
|
2033
|
-
|
|
2034
|
-
|
|
2035
|
-
|
|
2036
|
-
|
|
2037
|
-
|
|
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 {
|
|
2038
2165
|
}
|
|
2039
2166
|
}
|
|
2040
2167
|
return result;
|
|
@@ -2053,6 +2180,7 @@ function BoltTable({
|
|
|
2053
2180
|
const bottomMap = /* @__PURE__ */ new Map();
|
|
2054
2181
|
const rest = [];
|
|
2055
2182
|
processedData.forEach((row, idx) => {
|
|
2183
|
+
if (row == null) return;
|
|
2056
2184
|
const key = getRowKey(row, idx);
|
|
2057
2185
|
if (topKeySet.has(key)) topMap.set(key, row);
|
|
2058
2186
|
else if (bottomKeySet.has(key)) bottomMap.set(key, row);
|
|
@@ -2114,7 +2242,8 @@ function BoltTable({
|
|
|
2114
2242
|
const DEFAULT_PAGE_SIZE = 15;
|
|
2115
2243
|
const [internalPage, setInternalPage] = (0, import_react4.useState)(1);
|
|
2116
2244
|
const [internalPageSize, setInternalPageSize] = (0, import_react4.useState)(DEFAULT_PAGE_SIZE);
|
|
2117
|
-
const
|
|
2245
|
+
const dataLength = data.length;
|
|
2246
|
+
const autoPagination = pagination === void 0 && dataLength > DEFAULT_PAGE_SIZE;
|
|
2118
2247
|
const pgEnabled = pagination === false ? false : !!pagination || autoPagination;
|
|
2119
2248
|
const pgSize = pgEnabled && typeof pagination === "object" && pagination?.pageSize !== void 0 ? pagination.pageSize : internalPageSize;
|
|
2120
2249
|
const isControlledPagination = typeof pagination === "object" && pagination?.current !== void 0;
|
|
@@ -2127,26 +2256,27 @@ function BoltTable({
|
|
|
2127
2256
|
}, [unpinnedProcessedData, needsClientPagination, pgCurrent, pgSize]);
|
|
2128
2257
|
const shimmerCount = pgEnabled ? pgSize : 15;
|
|
2129
2258
|
const showShimmer = isLoading && processedData.length === 0;
|
|
2259
|
+
const shimmerRowKeyField = typeof rowKey === "string" ? rowKey : "id";
|
|
2130
2260
|
const shimmerData = (0, import_react4.useMemo)(() => {
|
|
2131
2261
|
if (!showShimmer) return null;
|
|
2132
2262
|
return Array.from(
|
|
2133
2263
|
{ length: shimmerCount },
|
|
2134
2264
|
(_, i) => ({
|
|
2135
|
-
[
|
|
2265
|
+
[shimmerRowKeyField]: `__shimmer_${i}__`
|
|
2136
2266
|
})
|
|
2137
2267
|
);
|
|
2138
|
-
}, [showShimmer, shimmerCount,
|
|
2268
|
+
}, [showShimmer, shimmerCount, shimmerRowKeyField]);
|
|
2139
2269
|
const INFINITE_SHIMMER_COUNT = 5;
|
|
2270
|
+
const showInfiniteShimmer = isLoading && paginatedData.length > 0 && !showShimmer && !pgEnabled;
|
|
2140
2271
|
const infiniteLoadingShimmer = (0, import_react4.useMemo)(() => {
|
|
2141
|
-
if (!
|
|
2142
|
-
if (pgEnabled) return null;
|
|
2272
|
+
if (!showInfiniteShimmer) return null;
|
|
2143
2273
|
return Array.from(
|
|
2144
2274
|
{ length: INFINITE_SHIMMER_COUNT },
|
|
2145
2275
|
(_, i) => ({
|
|
2146
|
-
[
|
|
2276
|
+
[shimmerRowKeyField]: `__shimmer_${i}__`
|
|
2147
2277
|
})
|
|
2148
2278
|
);
|
|
2149
|
-
}, [
|
|
2279
|
+
}, [showInfiniteShimmer, shimmerRowKeyField]);
|
|
2150
2280
|
const displayData = (0, import_react4.useMemo)(() => {
|
|
2151
2281
|
if (shimmerData) return shimmerData;
|
|
2152
2282
|
if (infiniteLoadingShimmer)
|
|
@@ -2176,13 +2306,20 @@ function BoltTable({
|
|
|
2176
2306
|
getScrollElement: () => tableAreaRef.current,
|
|
2177
2307
|
estimateSize: (index) => {
|
|
2178
2308
|
if (shimmerData) return rowHeight;
|
|
2179
|
-
const
|
|
2309
|
+
const item = displayData[index];
|
|
2310
|
+
if (!item) return rowHeight;
|
|
2311
|
+
const key = getRowKey(item, index);
|
|
2180
2312
|
if (!resolvedExpandedKeys.has(key)) return rowHeight;
|
|
2181
2313
|
const cached = measuredExpandedHeights.current.get(key);
|
|
2182
2314
|
return cached ? rowHeight + cached : rowHeight + expandedRowHeight;
|
|
2183
2315
|
},
|
|
2184
2316
|
overscan: 5,
|
|
2185
|
-
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
|
+
},
|
|
2186
2323
|
paddingStart: pinnedTopHeight,
|
|
2187
2324
|
paddingEnd: pinnedBottomHeight
|
|
2188
2325
|
});
|
|
@@ -2202,7 +2339,7 @@ function BoltTable({
|
|
|
2202
2339
|
endReachedFiredRef.current = false;
|
|
2203
2340
|
}, 200);
|
|
2204
2341
|
return () => clearTimeout(timer);
|
|
2205
|
-
}, [
|
|
2342
|
+
}, [dataLength, isLoading]);
|
|
2206
2343
|
import_react4.default.useEffect(() => {
|
|
2207
2344
|
const el = tableAreaRef.current;
|
|
2208
2345
|
if (!el) return;
|
|
@@ -2224,7 +2361,7 @@ function BoltTable({
|
|
|
2224
2361
|
const activeColumn = activeId ? orderedColumns.find((col) => col.key === activeId) : null;
|
|
2225
2362
|
const currentPage = pgCurrent;
|
|
2226
2363
|
const pageSize = pgSize;
|
|
2227
|
-
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;
|
|
2228
2365
|
const lastKnownTotalRef = (0, import_react4.useRef)(0);
|
|
2229
2366
|
if (!isLoading || rawTotal > 0) {
|
|
2230
2367
|
lastKnownTotalRef.current = rawTotal;
|
|
@@ -2232,8 +2369,8 @@ function BoltTable({
|
|
|
2232
2369
|
const total = isLoading && lastKnownTotalRef.current > 0 ? lastKnownTotalRef.current : rawTotal;
|
|
2233
2370
|
const totalPages = Math.max(1, Math.ceil(total / pageSize));
|
|
2234
2371
|
import_react4.default.useEffect(() => {
|
|
2235
|
-
if (internalPage > totalPages) {
|
|
2236
|
-
setInternalPage(
|
|
2372
|
+
if (totalPages > 0 && internalPage > totalPages) {
|
|
2373
|
+
setInternalPage(totalPages);
|
|
2237
2374
|
}
|
|
2238
2375
|
}, [totalPages, internalPage]);
|
|
2239
2376
|
const handlePageChange = (p) => {
|
|
@@ -2568,10 +2705,10 @@ function BoltTable({
|
|
|
2568
2705
|
"input",
|
|
2569
2706
|
{
|
|
2570
2707
|
type: "checkbox",
|
|
2571
|
-
checked:
|
|
2708
|
+
checked: dataLength > 0 && normalizedSelectedKeys.length === dataLength,
|
|
2572
2709
|
ref: (input) => {
|
|
2573
2710
|
if (input) {
|
|
2574
|
-
input.indeterminate = normalizedSelectedKeys.length > 0 && normalizedSelectedKeys.length <
|
|
2711
|
+
input.indeterminate = normalizedSelectedKeys.length > 0 && normalizedSelectedKeys.length < dataLength;
|
|
2575
2712
|
}
|
|
2576
2713
|
},
|
|
2577
2714
|
onChange: (e) => {
|
|
@@ -2719,7 +2856,9 @@ function BoltTable({
|
|
|
2719
2856
|
pinnedTopData: pinnedTopRows,
|
|
2720
2857
|
pinnedBottomData: pinnedBottomRows,
|
|
2721
2858
|
gridTemplateColumns,
|
|
2722
|
-
headerHeight: HEADER_HEIGHT
|
|
2859
|
+
headerHeight: HEADER_HEIGHT,
|
|
2860
|
+
rowClassName,
|
|
2861
|
+
rowStyle
|
|
2723
2862
|
}
|
|
2724
2863
|
)
|
|
2725
2864
|
]
|
|
@@ -3042,6 +3181,7 @@ function BoltTable({
|
|
|
3042
3181
|
...pinnedBottomRows
|
|
3043
3182
|
];
|
|
3044
3183
|
for (let i = 0; i < allRows.length; i++) {
|
|
3184
|
+
if (allRows[i] == null) continue;
|
|
3045
3185
|
const rk = getRowKey(allRows[i], i);
|
|
3046
3186
|
if (rk === cellContextMenu.rowKey) {
|
|
3047
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",
|
|
@@ -1051,19 +1060,23 @@ var TableBody = ({
|
|
|
1051
1060
|
pinnedTopData = [],
|
|
1052
1061
|
pinnedBottomData = [],
|
|
1053
1062
|
gridTemplateColumns,
|
|
1054
|
-
headerHeight = 36
|
|
1063
|
+
headerHeight = 36,
|
|
1064
|
+
rowClassName,
|
|
1065
|
+
rowStyle
|
|
1055
1066
|
}) => {
|
|
1056
1067
|
const virtualItems = rowVirtualizer.getVirtualItems();
|
|
1057
1068
|
const totalSize = rowVirtualizer.getTotalSize();
|
|
1058
1069
|
const selectedKeySet = useMemo(() => new Set(normalizedSelectedKeys), [normalizedSelectedKeys]);
|
|
1070
|
+
const safeData = data ?? [];
|
|
1071
|
+
const safeColumns = orderedColumns ?? [];
|
|
1059
1072
|
const allDataForSelection = useMemo(() => {
|
|
1060
1073
|
if (pinnedTopData.length === 0 && pinnedBottomData.length === 0)
|
|
1061
|
-
return
|
|
1062
|
-
return [...pinnedTopData, ...
|
|
1063
|
-
}, [pinnedTopData,
|
|
1074
|
+
return safeData;
|
|
1075
|
+
return [...pinnedTopData, ...safeData, ...pinnedBottomData];
|
|
1076
|
+
}, [pinnedTopData, safeData, pinnedBottomData]);
|
|
1064
1077
|
const pinnedRowBg = styles?.pinnedRowBg ?? styles?.pinnedBg;
|
|
1065
1078
|
const columnStyles = useMemo(() => {
|
|
1066
|
-
return
|
|
1079
|
+
return safeColumns.map((col, colIndex) => {
|
|
1067
1080
|
const stickyOffset = columnOffsets.get(col.key);
|
|
1068
1081
|
const isPinned = Boolean(col.pinned);
|
|
1069
1082
|
let zIndex = 0;
|
|
@@ -1085,10 +1098,12 @@ var TableBody = ({
|
|
|
1085
1098
|
}
|
|
1086
1099
|
return { key: col.key, style, isPinned };
|
|
1087
1100
|
});
|
|
1088
|
-
}, [
|
|
1101
|
+
}, [safeColumns, columnOffsets, totalSize, styles]);
|
|
1102
|
+
if (safeData.length === 0 || safeColumns.length === 0) return null;
|
|
1089
1103
|
return /* @__PURE__ */ jsxs4(Fragment3, { children: [
|
|
1090
1104
|
columnStyles.map((colStyle, colIndex) => {
|
|
1091
|
-
const col =
|
|
1105
|
+
const col = safeColumns[colIndex];
|
|
1106
|
+
if (!col) return null;
|
|
1092
1107
|
const hasRender = !!col.render;
|
|
1093
1108
|
return /* @__PURE__ */ jsx4(
|
|
1094
1109
|
"div",
|
|
@@ -1096,13 +1111,31 @@ var TableBody = ({
|
|
|
1096
1111
|
...colStyle.isPinned ? { "data-bt-pinned": "" } : {},
|
|
1097
1112
|
style: colStyle.style,
|
|
1098
1113
|
children: virtualItems.map((virtualRow) => {
|
|
1099
|
-
const row =
|
|
1114
|
+
const row = safeData[virtualRow.index];
|
|
1115
|
+
if (row == null) return null;
|
|
1100
1116
|
const rowKey = getRowKey ? getRowKey(row, virtualRow.index) : String(virtualRow.index);
|
|
1101
1117
|
const isSelected = selectedKeySet.has(rowKey);
|
|
1102
1118
|
const isExpanded = resolvedExpandedKeys?.has(rowKey) ?? false;
|
|
1103
1119
|
const cellValue = row[col.dataIndex];
|
|
1104
1120
|
const isRowShimmer = isLoading || rowKey.startsWith("__shimmer_");
|
|
1105
|
-
|
|
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
|
+
}
|
|
1106
1139
|
return /* @__PURE__ */ jsx4(
|
|
1107
1140
|
"div",
|
|
1108
1141
|
{
|
|
@@ -1110,12 +1143,14 @@ var TableBody = ({
|
|
|
1110
1143
|
"data-column-key": col.key,
|
|
1111
1144
|
"data-bt-cell": "",
|
|
1112
1145
|
"data-selected": isSelected || void 0,
|
|
1146
|
+
className: rowCls || void 0,
|
|
1113
1147
|
style: {
|
|
1114
1148
|
position: "absolute",
|
|
1115
1149
|
top: `${virtualRow.start}px`,
|
|
1116
1150
|
left: 0,
|
|
1117
1151
|
right: 0,
|
|
1118
|
-
height: `${virtualRow.size}px
|
|
1152
|
+
height: `${virtualRow.size}px`,
|
|
1153
|
+
...rowSty
|
|
1119
1154
|
},
|
|
1120
1155
|
children: /* @__PURE__ */ jsx4(
|
|
1121
1156
|
"div",
|
|
@@ -1167,9 +1202,15 @@ var TableBody = ({
|
|
|
1167
1202
|
pointerEvents: "none"
|
|
1168
1203
|
},
|
|
1169
1204
|
children: virtualItems.map((virtualRow) => {
|
|
1170
|
-
const row =
|
|
1205
|
+
const row = safeData[virtualRow.index];
|
|
1206
|
+
if (row == null) return null;
|
|
1171
1207
|
const rk = getRowKey ? getRowKey(row, virtualRow.index) : String(virtualRow.index);
|
|
1172
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
|
+
}
|
|
1173
1214
|
const expandedContent = /* @__PURE__ */ jsx4(
|
|
1174
1215
|
"div",
|
|
1175
1216
|
{
|
|
@@ -1187,7 +1228,7 @@ var TableBody = ({
|
|
|
1187
1228
|
...maxExpandedRowHeight ? { maxHeight: `${maxExpandedRowHeight}px` } : void 0,
|
|
1188
1229
|
...styles?.expandedRow
|
|
1189
1230
|
},
|
|
1190
|
-
children:
|
|
1231
|
+
children: expandedRenderResult
|
|
1191
1232
|
}
|
|
1192
1233
|
);
|
|
1193
1234
|
return /* @__PURE__ */ jsx4(
|
|
@@ -1234,20 +1275,32 @@ var TableBody = ({
|
|
|
1234
1275
|
boxShadow: "0 2px 6px -1px rgba(0,0,0,0.08)"
|
|
1235
1276
|
},
|
|
1236
1277
|
children: pinnedTopData.map((row, rowIdx) => {
|
|
1278
|
+
if (row == null) return null;
|
|
1237
1279
|
const rk = getRowKey ? getRowKey(row, rowIdx) : String(rowIdx);
|
|
1238
1280
|
const isSelected = selectedKeySet.has(rk);
|
|
1239
1281
|
const isExpanded = resolvedExpandedKeys?.has(rk) ?? false;
|
|
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
|
+
}
|
|
1240
1292
|
return /* @__PURE__ */ jsx4(
|
|
1241
1293
|
"div",
|
|
1242
1294
|
{
|
|
1243
|
-
className: classNames?.pinnedRow ?? "",
|
|
1295
|
+
className: `${classNames?.pinnedRow ?? ""} ${rowCls}`.trim() || void 0,
|
|
1244
1296
|
style: {
|
|
1245
1297
|
display: "grid",
|
|
1246
1298
|
gridTemplateColumns: gridTemplateColumns ?? "",
|
|
1247
1299
|
minWidth: totalTableWidth ? `${totalTableWidth}px` : void 0,
|
|
1248
|
-
...styles?.pinnedRow
|
|
1300
|
+
...styles?.pinnedRow,
|
|
1301
|
+
...rowSty
|
|
1249
1302
|
},
|
|
1250
|
-
children:
|
|
1303
|
+
children: safeColumns.map((col) => {
|
|
1251
1304
|
const cellValue = row[col.dataIndex];
|
|
1252
1305
|
const stickyOffset = columnOffsets.get(col.key);
|
|
1253
1306
|
const isPinned = Boolean(col.pinned);
|
|
@@ -1255,7 +1308,14 @@ var TableBody = ({
|
|
|
1255
1308
|
if (col.key === "__select__" || col.key === "__expand__")
|
|
1256
1309
|
zIndex = 11;
|
|
1257
1310
|
else if (isPinned) zIndex = 2;
|
|
1258
|
-
|
|
1311
|
+
let recordFingerprint;
|
|
1312
|
+
if (col.render) {
|
|
1313
|
+
try {
|
|
1314
|
+
recordFingerprint = JSON.stringify(row);
|
|
1315
|
+
} catch {
|
|
1316
|
+
recordFingerprint = rk;
|
|
1317
|
+
}
|
|
1318
|
+
}
|
|
1259
1319
|
return /* @__PURE__ */ jsx4(
|
|
1260
1320
|
"div",
|
|
1261
1321
|
{
|
|
@@ -1339,20 +1399,32 @@ var TableBody = ({
|
|
|
1339
1399
|
boxShadow: "0 -2px 6px -1px rgba(0,0,0,0.08)"
|
|
1340
1400
|
},
|
|
1341
1401
|
children: pinnedBottomData.map((row, rowIdx) => {
|
|
1402
|
+
if (row == null) return null;
|
|
1342
1403
|
const rk = getRowKey ? getRowKey(row, rowIdx) : String(rowIdx);
|
|
1343
1404
|
const isSelected = selectedKeySet.has(rk);
|
|
1344
1405
|
const isExpanded = resolvedExpandedKeys?.has(rk) ?? false;
|
|
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
|
+
}
|
|
1345
1416
|
return /* @__PURE__ */ jsx4(
|
|
1346
1417
|
"div",
|
|
1347
1418
|
{
|
|
1348
|
-
className: classNames?.pinnedRow ?? "",
|
|
1419
|
+
className: `${classNames?.pinnedRow ?? ""} ${rowCls}`.trim() || void 0,
|
|
1349
1420
|
style: {
|
|
1350
1421
|
display: "grid",
|
|
1351
1422
|
gridTemplateColumns: gridTemplateColumns ?? "",
|
|
1352
1423
|
minWidth: totalTableWidth ? `${totalTableWidth}px` : void 0,
|
|
1353
|
-
...styles?.pinnedRow
|
|
1424
|
+
...styles?.pinnedRow,
|
|
1425
|
+
...rowSty
|
|
1354
1426
|
},
|
|
1355
|
-
children:
|
|
1427
|
+
children: safeColumns.map((col) => {
|
|
1356
1428
|
const cellValue = row[col.dataIndex];
|
|
1357
1429
|
const stickyOffset = columnOffsets.get(col.key);
|
|
1358
1430
|
const isPinned = Boolean(col.pinned);
|
|
@@ -1360,7 +1432,14 @@ var TableBody = ({
|
|
|
1360
1432
|
if (col.key === "__select__" || col.key === "__expand__")
|
|
1361
1433
|
zIndex = 11;
|
|
1362
1434
|
else if (isPinned) zIndex = 2;
|
|
1363
|
-
|
|
1435
|
+
let recordFingerprint;
|
|
1436
|
+
if (col.render) {
|
|
1437
|
+
try {
|
|
1438
|
+
recordFingerprint = JSON.stringify(row);
|
|
1439
|
+
} catch {
|
|
1440
|
+
recordFingerprint = rk;
|
|
1441
|
+
}
|
|
1442
|
+
}
|
|
1364
1443
|
return /* @__PURE__ */ jsx4(
|
|
1365
1444
|
"div",
|
|
1366
1445
|
{
|
|
@@ -1436,9 +1515,11 @@ function arrayMove(arr, from, to) {
|
|
|
1436
1515
|
var SHIMMER_WIDTHS2 = [55, 70, 45, 80, 60, 50, 75, 65, 40, 72];
|
|
1437
1516
|
var EMPTY_CLASSNAMES = {};
|
|
1438
1517
|
var EMPTY_STYLES = {};
|
|
1518
|
+
var STABLE_EMPTY_DATA = [];
|
|
1519
|
+
var STABLE_EMPTY_COLS = [];
|
|
1439
1520
|
function BoltTable({
|
|
1440
|
-
columns:
|
|
1441
|
-
data,
|
|
1521
|
+
columns: rawInitialColumns,
|
|
1522
|
+
data: rawData,
|
|
1442
1523
|
rowHeight = 40,
|
|
1443
1524
|
expandedRowHeight = 200,
|
|
1444
1525
|
maxExpandedRowHeight,
|
|
@@ -1468,8 +1549,22 @@ function BoltTable({
|
|
|
1468
1549
|
columnContextMenuItems,
|
|
1469
1550
|
autoHeight = true,
|
|
1470
1551
|
layoutLoading,
|
|
1471
|
-
emptyRenderer
|
|
1552
|
+
emptyRenderer,
|
|
1553
|
+
rowClassName,
|
|
1554
|
+
rowStyle
|
|
1472
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]);
|
|
1473
1568
|
const [columns, setColumns] = useState2(initialColumns);
|
|
1474
1569
|
const [columnOrder, setColumnOrder] = useState2(
|
|
1475
1570
|
() => initialColumns.map((c) => c.key)
|
|
@@ -1505,10 +1600,15 @@ function BoltTable({
|
|
|
1505
1600
|
[columns, columnWidths]
|
|
1506
1601
|
);
|
|
1507
1602
|
const [internalExpandedKeys, setInternalExpandedKeys] = useState2(() => {
|
|
1508
|
-
if (expandable?.defaultExpandAllRows) {
|
|
1603
|
+
if (expandable?.defaultExpandAllRows && data.length > 0) {
|
|
1509
1604
|
return new Set(
|
|
1510
1605
|
data.map((row, idx) => {
|
|
1511
|
-
if (
|
|
1606
|
+
if (row == null) return idx;
|
|
1607
|
+
try {
|
|
1608
|
+
if (typeof rowKey === "function") return rowKey(row);
|
|
1609
|
+
} catch {
|
|
1610
|
+
return idx;
|
|
1611
|
+
}
|
|
1512
1612
|
if (typeof rowKey === "string")
|
|
1513
1613
|
return row[rowKey] ?? idx;
|
|
1514
1614
|
return idx;
|
|
@@ -1542,21 +1642,39 @@ function BoltTable({
|
|
|
1542
1642
|
}, []);
|
|
1543
1643
|
const getRowKey = useCallback(
|
|
1544
1644
|
(record, index) => {
|
|
1545
|
-
if (
|
|
1546
|
-
|
|
1547
|
-
|
|
1548
|
-
|
|
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);
|
|
1549
1654
|
}
|
|
1550
1655
|
return String(index);
|
|
1551
1656
|
},
|
|
1552
1657
|
[rowKey]
|
|
1553
1658
|
);
|
|
1554
1659
|
const normalizedSelectedKeys = useMemo2(
|
|
1555
|
-
() =>
|
|
1660
|
+
() => {
|
|
1661
|
+
const keys = rowSelection?.selectedRowKeys;
|
|
1662
|
+
if (!Array.isArray(keys)) return [];
|
|
1663
|
+
return keys.filter((k) => k != null).map((k) => String(k));
|
|
1664
|
+
},
|
|
1556
1665
|
[rowSelection?.selectedRowKeys]
|
|
1557
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;
|
|
1558
1676
|
const columnsWithExpand = useMemo2(() => {
|
|
1559
|
-
if (!
|
|
1677
|
+
if (!hasExpandable) return columnsWithPersistedWidths;
|
|
1560
1678
|
const expandColumn = {
|
|
1561
1679
|
key: "__expand__",
|
|
1562
1680
|
dataIndex: "__expand__",
|
|
@@ -1565,17 +1683,17 @@ function BoltTable({
|
|
|
1565
1683
|
pinned: "left",
|
|
1566
1684
|
hidden: false,
|
|
1567
1685
|
render: (_, record, index) => {
|
|
1568
|
-
const key =
|
|
1569
|
-
const canExpand =
|
|
1570
|
-
const isExpanded =
|
|
1686
|
+
const key = getRowKeyRef.current(record, index);
|
|
1687
|
+
const canExpand = expandableRef.current?.rowExpandable?.(record) ?? true;
|
|
1688
|
+
const isExpanded = resolvedExpandedKeysRef.current.has(key);
|
|
1571
1689
|
if (!canExpand)
|
|
1572
1690
|
return /* @__PURE__ */ jsx5("span", { style: { display: "inline-block", width: 16 } });
|
|
1573
|
-
if (typeof
|
|
1574
|
-
return
|
|
1691
|
+
if (typeof expandableRef.current?.expandIcon === "function") {
|
|
1692
|
+
return expandableRef.current.expandIcon({
|
|
1575
1693
|
expanded: isExpanded,
|
|
1576
1694
|
onExpand: (_2, e) => {
|
|
1577
1695
|
e.stopPropagation();
|
|
1578
|
-
|
|
1696
|
+
toggleExpandRef.current(key);
|
|
1579
1697
|
},
|
|
1580
1698
|
record
|
|
1581
1699
|
});
|
|
@@ -1585,7 +1703,7 @@ function BoltTable({
|
|
|
1585
1703
|
{
|
|
1586
1704
|
onClick: (e) => {
|
|
1587
1705
|
e.stopPropagation();
|
|
1588
|
-
|
|
1706
|
+
toggleExpandRef.current(key);
|
|
1589
1707
|
},
|
|
1590
1708
|
style: {
|
|
1591
1709
|
display: "flex",
|
|
@@ -1598,20 +1716,13 @@ function BoltTable({
|
|
|
1598
1716
|
borderRadius: "3px",
|
|
1599
1717
|
color: accentColor
|
|
1600
1718
|
},
|
|
1601
|
-
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 } })
|
|
1602
1720
|
}
|
|
1603
1721
|
);
|
|
1604
1722
|
}
|
|
1605
1723
|
};
|
|
1606
1724
|
return [expandColumn, ...columnsWithPersistedWidths];
|
|
1607
|
-
}, [
|
|
1608
|
-
expandable,
|
|
1609
|
-
columnsWithPersistedWidths,
|
|
1610
|
-
getRowKey,
|
|
1611
|
-
resolvedExpandedKeys,
|
|
1612
|
-
toggleExpand,
|
|
1613
|
-
accentColor
|
|
1614
|
-
]);
|
|
1725
|
+
}, [hasExpandable, columnsWithPersistedWidths, accentColor]);
|
|
1615
1726
|
const columnsWithSelection = useMemo2(() => {
|
|
1616
1727
|
if (!rowSelection) return columnsWithExpand;
|
|
1617
1728
|
const selectionColumn = {
|
|
@@ -1971,36 +2082,52 @@ function BoltTable({
|
|
|
1971
2082
|
if (!onFilterChangeRef.current) {
|
|
1972
2083
|
const filterKeys = Object.keys(columnFilters);
|
|
1973
2084
|
if (filterKeys.length > 0) {
|
|
1974
|
-
result = result.filter(
|
|
1975
|
-
(row
|
|
1976
|
-
|
|
1977
|
-
|
|
1978
|
-
|
|
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;
|
|
1979
2097
|
}
|
|
1980
|
-
|
|
1981
|
-
|
|
1982
|
-
})
|
|
1983
|
-
);
|
|
2098
|
+
});
|
|
2099
|
+
});
|
|
1984
2100
|
}
|
|
1985
2101
|
}
|
|
1986
2102
|
if (!onSortChangeRef.current && sortState.key && sortState.direction) {
|
|
1987
2103
|
const dir = sortState.direction === "asc" ? 1 : -1;
|
|
1988
2104
|
const key = sortState.key;
|
|
1989
2105
|
const col = columnsLookupRef.current.find((c) => c.key === key);
|
|
1990
|
-
|
|
1991
|
-
|
|
1992
|
-
|
|
1993
|
-
|
|
1994
|
-
|
|
1995
|
-
|
|
1996
|
-
|
|
1997
|
-
|
|
1998
|
-
|
|
1999
|
-
|
|
2000
|
-
|
|
2001
|
-
|
|
2002
|
-
|
|
2003
|
-
|
|
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 {
|
|
2004
2131
|
}
|
|
2005
2132
|
}
|
|
2006
2133
|
return result;
|
|
@@ -2019,6 +2146,7 @@ function BoltTable({
|
|
|
2019
2146
|
const bottomMap = /* @__PURE__ */ new Map();
|
|
2020
2147
|
const rest = [];
|
|
2021
2148
|
processedData.forEach((row, idx) => {
|
|
2149
|
+
if (row == null) return;
|
|
2022
2150
|
const key = getRowKey(row, idx);
|
|
2023
2151
|
if (topKeySet.has(key)) topMap.set(key, row);
|
|
2024
2152
|
else if (bottomKeySet.has(key)) bottomMap.set(key, row);
|
|
@@ -2080,7 +2208,8 @@ function BoltTable({
|
|
|
2080
2208
|
const DEFAULT_PAGE_SIZE = 15;
|
|
2081
2209
|
const [internalPage, setInternalPage] = useState2(1);
|
|
2082
2210
|
const [internalPageSize, setInternalPageSize] = useState2(DEFAULT_PAGE_SIZE);
|
|
2083
|
-
const
|
|
2211
|
+
const dataLength = data.length;
|
|
2212
|
+
const autoPagination = pagination === void 0 && dataLength > DEFAULT_PAGE_SIZE;
|
|
2084
2213
|
const pgEnabled = pagination === false ? false : !!pagination || autoPagination;
|
|
2085
2214
|
const pgSize = pgEnabled && typeof pagination === "object" && pagination?.pageSize !== void 0 ? pagination.pageSize : internalPageSize;
|
|
2086
2215
|
const isControlledPagination = typeof pagination === "object" && pagination?.current !== void 0;
|
|
@@ -2093,26 +2222,27 @@ function BoltTable({
|
|
|
2093
2222
|
}, [unpinnedProcessedData, needsClientPagination, pgCurrent, pgSize]);
|
|
2094
2223
|
const shimmerCount = pgEnabled ? pgSize : 15;
|
|
2095
2224
|
const showShimmer = isLoading && processedData.length === 0;
|
|
2225
|
+
const shimmerRowKeyField = typeof rowKey === "string" ? rowKey : "id";
|
|
2096
2226
|
const shimmerData = useMemo2(() => {
|
|
2097
2227
|
if (!showShimmer) return null;
|
|
2098
2228
|
return Array.from(
|
|
2099
2229
|
{ length: shimmerCount },
|
|
2100
2230
|
(_, i) => ({
|
|
2101
|
-
[
|
|
2231
|
+
[shimmerRowKeyField]: `__shimmer_${i}__`
|
|
2102
2232
|
})
|
|
2103
2233
|
);
|
|
2104
|
-
}, [showShimmer, shimmerCount,
|
|
2234
|
+
}, [showShimmer, shimmerCount, shimmerRowKeyField]);
|
|
2105
2235
|
const INFINITE_SHIMMER_COUNT = 5;
|
|
2236
|
+
const showInfiniteShimmer = isLoading && paginatedData.length > 0 && !showShimmer && !pgEnabled;
|
|
2106
2237
|
const infiniteLoadingShimmer = useMemo2(() => {
|
|
2107
|
-
if (!
|
|
2108
|
-
if (pgEnabled) return null;
|
|
2238
|
+
if (!showInfiniteShimmer) return null;
|
|
2109
2239
|
return Array.from(
|
|
2110
2240
|
{ length: INFINITE_SHIMMER_COUNT },
|
|
2111
2241
|
(_, i) => ({
|
|
2112
|
-
[
|
|
2242
|
+
[shimmerRowKeyField]: `__shimmer_${i}__`
|
|
2113
2243
|
})
|
|
2114
2244
|
);
|
|
2115
|
-
}, [
|
|
2245
|
+
}, [showInfiniteShimmer, shimmerRowKeyField]);
|
|
2116
2246
|
const displayData = useMemo2(() => {
|
|
2117
2247
|
if (shimmerData) return shimmerData;
|
|
2118
2248
|
if (infiniteLoadingShimmer)
|
|
@@ -2142,13 +2272,20 @@ function BoltTable({
|
|
|
2142
2272
|
getScrollElement: () => tableAreaRef.current,
|
|
2143
2273
|
estimateSize: (index) => {
|
|
2144
2274
|
if (shimmerData) return rowHeight;
|
|
2145
|
-
const
|
|
2275
|
+
const item = displayData[index];
|
|
2276
|
+
if (!item) return rowHeight;
|
|
2277
|
+
const key = getRowKey(item, index);
|
|
2146
2278
|
if (!resolvedExpandedKeys.has(key)) return rowHeight;
|
|
2147
2279
|
const cached = measuredExpandedHeights.current.get(key);
|
|
2148
2280
|
return cached ? rowHeight + cached : rowHeight + expandedRowHeight;
|
|
2149
2281
|
},
|
|
2150
2282
|
overscan: 5,
|
|
2151
|
-
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
|
+
},
|
|
2152
2289
|
paddingStart: pinnedTopHeight,
|
|
2153
2290
|
paddingEnd: pinnedBottomHeight
|
|
2154
2291
|
});
|
|
@@ -2168,7 +2305,7 @@ function BoltTable({
|
|
|
2168
2305
|
endReachedFiredRef.current = false;
|
|
2169
2306
|
}, 200);
|
|
2170
2307
|
return () => clearTimeout(timer);
|
|
2171
|
-
}, [
|
|
2308
|
+
}, [dataLength, isLoading]);
|
|
2172
2309
|
React4.useEffect(() => {
|
|
2173
2310
|
const el = tableAreaRef.current;
|
|
2174
2311
|
if (!el) return;
|
|
@@ -2190,7 +2327,7 @@ function BoltTable({
|
|
|
2190
2327
|
const activeColumn = activeId ? orderedColumns.find((col) => col.key === activeId) : null;
|
|
2191
2328
|
const currentPage = pgCurrent;
|
|
2192
2329
|
const pageSize = pgSize;
|
|
2193
|
-
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;
|
|
2194
2331
|
const lastKnownTotalRef = useRef4(0);
|
|
2195
2332
|
if (!isLoading || rawTotal > 0) {
|
|
2196
2333
|
lastKnownTotalRef.current = rawTotal;
|
|
@@ -2198,8 +2335,8 @@ function BoltTable({
|
|
|
2198
2335
|
const total = isLoading && lastKnownTotalRef.current > 0 ? lastKnownTotalRef.current : rawTotal;
|
|
2199
2336
|
const totalPages = Math.max(1, Math.ceil(total / pageSize));
|
|
2200
2337
|
React4.useEffect(() => {
|
|
2201
|
-
if (internalPage > totalPages) {
|
|
2202
|
-
setInternalPage(
|
|
2338
|
+
if (totalPages > 0 && internalPage > totalPages) {
|
|
2339
|
+
setInternalPage(totalPages);
|
|
2203
2340
|
}
|
|
2204
2341
|
}, [totalPages, internalPage]);
|
|
2205
2342
|
const handlePageChange = (p) => {
|
|
@@ -2534,10 +2671,10 @@ function BoltTable({
|
|
|
2534
2671
|
"input",
|
|
2535
2672
|
{
|
|
2536
2673
|
type: "checkbox",
|
|
2537
|
-
checked:
|
|
2674
|
+
checked: dataLength > 0 && normalizedSelectedKeys.length === dataLength,
|
|
2538
2675
|
ref: (input) => {
|
|
2539
2676
|
if (input) {
|
|
2540
|
-
input.indeterminate = normalizedSelectedKeys.length > 0 && normalizedSelectedKeys.length <
|
|
2677
|
+
input.indeterminate = normalizedSelectedKeys.length > 0 && normalizedSelectedKeys.length < dataLength;
|
|
2541
2678
|
}
|
|
2542
2679
|
},
|
|
2543
2680
|
onChange: (e) => {
|
|
@@ -2685,7 +2822,9 @@ function BoltTable({
|
|
|
2685
2822
|
pinnedTopData: pinnedTopRows,
|
|
2686
2823
|
pinnedBottomData: pinnedBottomRows,
|
|
2687
2824
|
gridTemplateColumns,
|
|
2688
|
-
headerHeight: HEADER_HEIGHT
|
|
2825
|
+
headerHeight: HEADER_HEIGHT,
|
|
2826
|
+
rowClassName,
|
|
2827
|
+
rowStyle
|
|
2689
2828
|
}
|
|
2690
2829
|
)
|
|
2691
2830
|
]
|
|
@@ -3008,6 +3147,7 @@ function BoltTable({
|
|
|
3008
3147
|
...pinnedBottomRows
|
|
3009
3148
|
];
|
|
3010
3149
|
for (let i = 0; i < allRows.length; i++) {
|
|
3150
|
+
if (allRows[i] == null) continue;
|
|
3011
3151
|
const rk = getRowKey(allRows[i], i);
|
|
3012
3152
|
if (rk === cellContextMenu.rowKey) {
|
|
3013
3153
|
menuRecord = allRows[i];
|
package/package.json
CHANGED