bolt-table 0.1.11 → 0.1.13
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 +83 -2
- package/dist/index.d.ts +83 -2
- package/dist/index.js +257 -13
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +257 -13
- package/dist/index.mjs.map +1 -1
- package/package.json +1 -1
package/dist/index.d.mts
CHANGED
|
@@ -569,6 +569,38 @@ interface PaginationType {
|
|
|
569
569
|
*/
|
|
570
570
|
showTotal?: (total: number, range: [number, number]) => ReactNode;
|
|
571
571
|
}
|
|
572
|
+
/**
|
|
573
|
+
* Configuration for row pinning.
|
|
574
|
+
* When provided, the specified rows are rendered as sticky rows at the top
|
|
575
|
+
* and/or bottom of the table body, remaining visible during vertical scroll.
|
|
576
|
+
*
|
|
577
|
+
* Pinned rows are excluded from pagination — they are always visible regardless
|
|
578
|
+
* of which page the user is on. Filtering still applies: if a pinned row's key
|
|
579
|
+
* doesn't exist in the (filtered) data, it simply won't appear.
|
|
580
|
+
*
|
|
581
|
+
* @example
|
|
582
|
+
* // Pin two rows to the top and one to the bottom
|
|
583
|
+
* rowPinning={{ top: ['row-1', 'row-3'], bottom: ['row-10'] }}
|
|
584
|
+
*
|
|
585
|
+
* @example
|
|
586
|
+
* // Controlled pinning — manage pinned keys in parent state
|
|
587
|
+
* const [pinning, setPinning] = useState<RowPinningConfig>({ top: ['header-row'] });
|
|
588
|
+
* <BoltTable rowPinning={pinning} ... />
|
|
589
|
+
*/
|
|
590
|
+
interface RowPinningConfig {
|
|
591
|
+
/**
|
|
592
|
+
* Row keys to pin at the top of the table.
|
|
593
|
+
* These rows stick below the column headers during vertical scroll.
|
|
594
|
+
* Order is preserved — rows are rendered in the order listed here.
|
|
595
|
+
*/
|
|
596
|
+
top?: React.Key[];
|
|
597
|
+
/**
|
|
598
|
+
* Row keys to pin at the bottom of the table.
|
|
599
|
+
* These rows stick to the bottom of the visible area during vertical scroll.
|
|
600
|
+
* Order is preserved — rows are rendered in the order listed here.
|
|
601
|
+
*/
|
|
602
|
+
bottom?: React.Key[];
|
|
603
|
+
}
|
|
572
604
|
/**
|
|
573
605
|
* The base type for a row record in BoltTable.
|
|
574
606
|
* All row data objects must be indexable by string keys.
|
|
@@ -910,6 +942,17 @@ interface BoltTableProps<T extends DataRecord = DataRecord> {
|
|
|
910
942
|
* }}
|
|
911
943
|
*/
|
|
912
944
|
readonly rowSelection?: RowSelectionConfig<T>;
|
|
945
|
+
/**
|
|
946
|
+
* Row pinning configuration. When provided, the specified rows are rendered
|
|
947
|
+
* as sticky rows at the top and/or bottom of the table body.
|
|
948
|
+
*
|
|
949
|
+
* Pinned rows transcend pagination — they are always visible regardless of
|
|
950
|
+
* which page the user is on. Filtering still applies.
|
|
951
|
+
*
|
|
952
|
+
* @example
|
|
953
|
+
* rowPinning={{ top: ['row-1', 'row-3'], bottom: ['row-10'] }}
|
|
954
|
+
*/
|
|
955
|
+
readonly rowPinning?: RowPinningConfig;
|
|
913
956
|
/**
|
|
914
957
|
* Called when the user scrolls near the bottom of the table.
|
|
915
958
|
* Use this for infinite scroll / load-more behavior.
|
|
@@ -1106,6 +1149,11 @@ interface ClassNamesTypes {
|
|
|
1106
1149
|
* Does not affect the row itself, only the expanded panel.
|
|
1107
1150
|
*/
|
|
1108
1151
|
expandedRow?: string;
|
|
1152
|
+
/**
|
|
1153
|
+
* Applied to each pinned row's wrapper div (the grid row containing all cells).
|
|
1154
|
+
* Use this to add a border, background, or separator for pinned rows.
|
|
1155
|
+
*/
|
|
1156
|
+
pinnedRow?: string;
|
|
1109
1157
|
}
|
|
1110
1158
|
/**
|
|
1111
1159
|
* Inline style overrides for specific regions of BoltTable.
|
|
@@ -1146,6 +1194,17 @@ interface StylesTypes {
|
|
|
1146
1194
|
pinnedCell?: CSSProperties;
|
|
1147
1195
|
/** Inline styles for the expanded row content panel */
|
|
1148
1196
|
expandedRow?: CSSProperties;
|
|
1197
|
+
/** Inline styles for pinned row wrappers (the grid row containing all cells) */
|
|
1198
|
+
pinnedRow?: CSSProperties;
|
|
1199
|
+
/**
|
|
1200
|
+
* CSS color string for the background of pinned row cells.
|
|
1201
|
+
* Should be opaque so that scrolling content behind pinned rows is hidden.
|
|
1202
|
+
* Falls back to `pinnedBg` if not set.
|
|
1203
|
+
*
|
|
1204
|
+
* @example
|
|
1205
|
+
* pinnedRowBg: 'rgba(255, 255, 255, 0.98)'
|
|
1206
|
+
*/
|
|
1207
|
+
pinnedRowBg?: string;
|
|
1149
1208
|
/**
|
|
1150
1209
|
* CSS color string applied as the background of hovered rows.
|
|
1151
1210
|
* Defaults to `hsl(var(--muted) / 0.5)` if omitted.
|
|
@@ -1210,7 +1269,7 @@ interface StylesTypes {
|
|
|
1210
1269
|
* autoHeight={false}
|
|
1211
1270
|
* />
|
|
1212
1271
|
*/
|
|
1213
|
-
declare function BoltTable<T extends DataRecord = DataRecord>({ columns: initialColumns, data, rowHeight, expandedRowHeight, maxExpandedRowHeight, accentColor, className, classNames, styles, gripIcon, hideGripIcon, icons, pagination, onPaginationChange, onColumnResize, onColumnOrderChange, onColumnPin, onColumnHide, rowSelection, expandable, rowKey, onEndReached, onEndReachedThreshold, isLoading, onSortChange, onFilterChange, columnContextMenuItems, autoHeight, layoutLoading, emptyRenderer, }: BoltTableProps<T>): react_jsx_runtime.JSX.Element;
|
|
1272
|
+
declare function BoltTable<T extends DataRecord = DataRecord>({ columns: initialColumns, data, rowHeight, expandedRowHeight, maxExpandedRowHeight, accentColor, className, classNames, styles, gripIcon, hideGripIcon, icons, pagination, onPaginationChange, onColumnResize, onColumnOrderChange, onColumnPin, onColumnHide, rowSelection, rowPinning, expandable, rowKey, onEndReached, onEndReachedThreshold, isLoading, onSortChange, onFilterChange, columnContextMenuItems, autoHeight, layoutLoading, emptyRenderer, }: BoltTableProps<T>): react_jsx_runtime.JSX.Element;
|
|
1214
1273
|
|
|
1215
1274
|
/**
|
|
1216
1275
|
* Props for the DraggableHeader component.
|
|
@@ -1569,6 +1628,28 @@ interface TableBodyProps {
|
|
|
1569
1628
|
* maxExpandedRowHeight={300}
|
|
1570
1629
|
*/
|
|
1571
1630
|
maxExpandedRowHeight?: number;
|
|
1631
|
+
/**
|
|
1632
|
+
* Rows pinned to the top of the table body.
|
|
1633
|
+
* Rendered as non-virtualized sticky rows below the column headers.
|
|
1634
|
+
*/
|
|
1635
|
+
pinnedTopData?: DataRecord[];
|
|
1636
|
+
/**
|
|
1637
|
+
* Rows pinned to the bottom of the table body.
|
|
1638
|
+
* Rendered as non-virtualized sticky rows at the bottom of the visible area.
|
|
1639
|
+
*/
|
|
1640
|
+
pinnedBottomData?: DataRecord[];
|
|
1641
|
+
/**
|
|
1642
|
+
* The CSS `gridTemplateColumns` string matching the parent grid.
|
|
1643
|
+
* Needed for pinned row sub-grids to align with the main column layout.
|
|
1644
|
+
*/
|
|
1645
|
+
gridTemplateColumns?: string;
|
|
1646
|
+
/**
|
|
1647
|
+
* Height of the column header row in pixels.
|
|
1648
|
+
* Used to position the sticky top pinned rows below the headers.
|
|
1649
|
+
*
|
|
1650
|
+
* @default 36
|
|
1651
|
+
*/
|
|
1652
|
+
headerHeight?: number;
|
|
1572
1653
|
}
|
|
1573
1654
|
/**
|
|
1574
1655
|
* TableBody — the virtualized body renderer for BoltTable.
|
|
@@ -1590,4 +1671,4 @@ interface TableBodyProps {
|
|
|
1590
1671
|
*/
|
|
1591
1672
|
declare const TableBody: React$1.FC<TableBodyProps>;
|
|
1592
1673
|
|
|
1593
|
-
export { BoltTable, type BoltTableIcons, type ColumnContextMenuItem, type ColumnType, type DataRecord, DraggableHeader, type ExpandableConfig, type PaginationType, ResizeOverlay, type RowSelectionConfig, type SortDirection, TableBody };
|
|
1674
|
+
export { BoltTable, type BoltTableIcons, type ColumnContextMenuItem, type ColumnType, type DataRecord, DraggableHeader, type ExpandableConfig, type PaginationType, ResizeOverlay, type RowPinningConfig, type RowSelectionConfig, type SortDirection, TableBody };
|
package/dist/index.d.ts
CHANGED
|
@@ -569,6 +569,38 @@ interface PaginationType {
|
|
|
569
569
|
*/
|
|
570
570
|
showTotal?: (total: number, range: [number, number]) => ReactNode;
|
|
571
571
|
}
|
|
572
|
+
/**
|
|
573
|
+
* Configuration for row pinning.
|
|
574
|
+
* When provided, the specified rows are rendered as sticky rows at the top
|
|
575
|
+
* and/or bottom of the table body, remaining visible during vertical scroll.
|
|
576
|
+
*
|
|
577
|
+
* Pinned rows are excluded from pagination — they are always visible regardless
|
|
578
|
+
* of which page the user is on. Filtering still applies: if a pinned row's key
|
|
579
|
+
* doesn't exist in the (filtered) data, it simply won't appear.
|
|
580
|
+
*
|
|
581
|
+
* @example
|
|
582
|
+
* // Pin two rows to the top and one to the bottom
|
|
583
|
+
* rowPinning={{ top: ['row-1', 'row-3'], bottom: ['row-10'] }}
|
|
584
|
+
*
|
|
585
|
+
* @example
|
|
586
|
+
* // Controlled pinning — manage pinned keys in parent state
|
|
587
|
+
* const [pinning, setPinning] = useState<RowPinningConfig>({ top: ['header-row'] });
|
|
588
|
+
* <BoltTable rowPinning={pinning} ... />
|
|
589
|
+
*/
|
|
590
|
+
interface RowPinningConfig {
|
|
591
|
+
/**
|
|
592
|
+
* Row keys to pin at the top of the table.
|
|
593
|
+
* These rows stick below the column headers during vertical scroll.
|
|
594
|
+
* Order is preserved — rows are rendered in the order listed here.
|
|
595
|
+
*/
|
|
596
|
+
top?: React.Key[];
|
|
597
|
+
/**
|
|
598
|
+
* Row keys to pin at the bottom of the table.
|
|
599
|
+
* These rows stick to the bottom of the visible area during vertical scroll.
|
|
600
|
+
* Order is preserved — rows are rendered in the order listed here.
|
|
601
|
+
*/
|
|
602
|
+
bottom?: React.Key[];
|
|
603
|
+
}
|
|
572
604
|
/**
|
|
573
605
|
* The base type for a row record in BoltTable.
|
|
574
606
|
* All row data objects must be indexable by string keys.
|
|
@@ -910,6 +942,17 @@ interface BoltTableProps<T extends DataRecord = DataRecord> {
|
|
|
910
942
|
* }}
|
|
911
943
|
*/
|
|
912
944
|
readonly rowSelection?: RowSelectionConfig<T>;
|
|
945
|
+
/**
|
|
946
|
+
* Row pinning configuration. When provided, the specified rows are rendered
|
|
947
|
+
* as sticky rows at the top and/or bottom of the table body.
|
|
948
|
+
*
|
|
949
|
+
* Pinned rows transcend pagination — they are always visible regardless of
|
|
950
|
+
* which page the user is on. Filtering still applies.
|
|
951
|
+
*
|
|
952
|
+
* @example
|
|
953
|
+
* rowPinning={{ top: ['row-1', 'row-3'], bottom: ['row-10'] }}
|
|
954
|
+
*/
|
|
955
|
+
readonly rowPinning?: RowPinningConfig;
|
|
913
956
|
/**
|
|
914
957
|
* Called when the user scrolls near the bottom of the table.
|
|
915
958
|
* Use this for infinite scroll / load-more behavior.
|
|
@@ -1106,6 +1149,11 @@ interface ClassNamesTypes {
|
|
|
1106
1149
|
* Does not affect the row itself, only the expanded panel.
|
|
1107
1150
|
*/
|
|
1108
1151
|
expandedRow?: string;
|
|
1152
|
+
/**
|
|
1153
|
+
* Applied to each pinned row's wrapper div (the grid row containing all cells).
|
|
1154
|
+
* Use this to add a border, background, or separator for pinned rows.
|
|
1155
|
+
*/
|
|
1156
|
+
pinnedRow?: string;
|
|
1109
1157
|
}
|
|
1110
1158
|
/**
|
|
1111
1159
|
* Inline style overrides for specific regions of BoltTable.
|
|
@@ -1146,6 +1194,17 @@ interface StylesTypes {
|
|
|
1146
1194
|
pinnedCell?: CSSProperties;
|
|
1147
1195
|
/** Inline styles for the expanded row content panel */
|
|
1148
1196
|
expandedRow?: CSSProperties;
|
|
1197
|
+
/** Inline styles for pinned row wrappers (the grid row containing all cells) */
|
|
1198
|
+
pinnedRow?: CSSProperties;
|
|
1199
|
+
/**
|
|
1200
|
+
* CSS color string for the background of pinned row cells.
|
|
1201
|
+
* Should be opaque so that scrolling content behind pinned rows is hidden.
|
|
1202
|
+
* Falls back to `pinnedBg` if not set.
|
|
1203
|
+
*
|
|
1204
|
+
* @example
|
|
1205
|
+
* pinnedRowBg: 'rgba(255, 255, 255, 0.98)'
|
|
1206
|
+
*/
|
|
1207
|
+
pinnedRowBg?: string;
|
|
1149
1208
|
/**
|
|
1150
1209
|
* CSS color string applied as the background of hovered rows.
|
|
1151
1210
|
* Defaults to `hsl(var(--muted) / 0.5)` if omitted.
|
|
@@ -1210,7 +1269,7 @@ interface StylesTypes {
|
|
|
1210
1269
|
* autoHeight={false}
|
|
1211
1270
|
* />
|
|
1212
1271
|
*/
|
|
1213
|
-
declare function BoltTable<T extends DataRecord = DataRecord>({ columns: initialColumns, data, rowHeight, expandedRowHeight, maxExpandedRowHeight, accentColor, className, classNames, styles, gripIcon, hideGripIcon, icons, pagination, onPaginationChange, onColumnResize, onColumnOrderChange, onColumnPin, onColumnHide, rowSelection, expandable, rowKey, onEndReached, onEndReachedThreshold, isLoading, onSortChange, onFilterChange, columnContextMenuItems, autoHeight, layoutLoading, emptyRenderer, }: BoltTableProps<T>): react_jsx_runtime.JSX.Element;
|
|
1272
|
+
declare function BoltTable<T extends DataRecord = DataRecord>({ columns: initialColumns, data, rowHeight, expandedRowHeight, maxExpandedRowHeight, accentColor, className, classNames, styles, gripIcon, hideGripIcon, icons, pagination, onPaginationChange, onColumnResize, onColumnOrderChange, onColumnPin, onColumnHide, rowSelection, rowPinning, expandable, rowKey, onEndReached, onEndReachedThreshold, isLoading, onSortChange, onFilterChange, columnContextMenuItems, autoHeight, layoutLoading, emptyRenderer, }: BoltTableProps<T>): react_jsx_runtime.JSX.Element;
|
|
1214
1273
|
|
|
1215
1274
|
/**
|
|
1216
1275
|
* Props for the DraggableHeader component.
|
|
@@ -1569,6 +1628,28 @@ interface TableBodyProps {
|
|
|
1569
1628
|
* maxExpandedRowHeight={300}
|
|
1570
1629
|
*/
|
|
1571
1630
|
maxExpandedRowHeight?: number;
|
|
1631
|
+
/**
|
|
1632
|
+
* Rows pinned to the top of the table body.
|
|
1633
|
+
* Rendered as non-virtualized sticky rows below the column headers.
|
|
1634
|
+
*/
|
|
1635
|
+
pinnedTopData?: DataRecord[];
|
|
1636
|
+
/**
|
|
1637
|
+
* Rows pinned to the bottom of the table body.
|
|
1638
|
+
* Rendered as non-virtualized sticky rows at the bottom of the visible area.
|
|
1639
|
+
*/
|
|
1640
|
+
pinnedBottomData?: DataRecord[];
|
|
1641
|
+
/**
|
|
1642
|
+
* The CSS `gridTemplateColumns` string matching the parent grid.
|
|
1643
|
+
* Needed for pinned row sub-grids to align with the main column layout.
|
|
1644
|
+
*/
|
|
1645
|
+
gridTemplateColumns?: string;
|
|
1646
|
+
/**
|
|
1647
|
+
* Height of the column header row in pixels.
|
|
1648
|
+
* Used to position the sticky top pinned rows below the headers.
|
|
1649
|
+
*
|
|
1650
|
+
* @default 36
|
|
1651
|
+
*/
|
|
1652
|
+
headerHeight?: number;
|
|
1572
1653
|
}
|
|
1573
1654
|
/**
|
|
1574
1655
|
* TableBody — the virtualized body renderer for BoltTable.
|
|
@@ -1590,4 +1671,4 @@ interface TableBodyProps {
|
|
|
1590
1671
|
*/
|
|
1591
1672
|
declare const TableBody: React$1.FC<TableBodyProps>;
|
|
1592
1673
|
|
|
1593
|
-
export { BoltTable, type BoltTableIcons, type ColumnContextMenuItem, type ColumnType, type DataRecord, DraggableHeader, type ExpandableConfig, type PaginationType, ResizeOverlay, type RowSelectionConfig, type SortDirection, TableBody };
|
|
1674
|
+
export { BoltTable, type BoltTableIcons, type ColumnContextMenuItem, type ColumnType, type DataRecord, DraggableHeader, type ExpandableConfig, type PaginationType, ResizeOverlay, type RowPinningConfig, type RowSelectionConfig, type SortDirection, TableBody };
|
package/dist/index.js
CHANGED
|
@@ -986,7 +986,9 @@ var Cell = import_react3.default.memo(
|
|
|
986
986
|
return prev.isExpanded === next.isExpanded;
|
|
987
987
|
}
|
|
988
988
|
if (prev.column.render) {
|
|
989
|
-
|
|
989
|
+
if (prev.recordFingerprint !== next.recordFingerprint) return false;
|
|
990
|
+
if (prev.rowIndex !== next.rowIndex) return false;
|
|
991
|
+
return prev.column.render === next.column.render;
|
|
990
992
|
}
|
|
991
993
|
return prev.value === next.value && prev.rowIndex === next.rowIndex && prev.column.key === next.column.key;
|
|
992
994
|
}
|
|
@@ -1032,15 +1034,26 @@ var TableBody = ({
|
|
|
1032
1034
|
expandable,
|
|
1033
1035
|
resolvedExpandedKeys,
|
|
1034
1036
|
rowHeight = 40,
|
|
1037
|
+
totalTableWidth,
|
|
1035
1038
|
scrollAreaWidth,
|
|
1036
1039
|
accentColor,
|
|
1037
1040
|
isLoading = false,
|
|
1038
1041
|
onExpandedRowResize,
|
|
1039
|
-
maxExpandedRowHeight
|
|
1042
|
+
maxExpandedRowHeight,
|
|
1043
|
+
pinnedTopData = [],
|
|
1044
|
+
pinnedBottomData = [],
|
|
1045
|
+
gridTemplateColumns,
|
|
1046
|
+
headerHeight = 36
|
|
1040
1047
|
}) => {
|
|
1041
1048
|
const virtualItems = rowVirtualizer.getVirtualItems();
|
|
1042
1049
|
const totalSize = rowVirtualizer.getTotalSize();
|
|
1043
1050
|
const selectedKeySet = (0, import_react3.useMemo)(() => new Set(normalizedSelectedKeys), [normalizedSelectedKeys]);
|
|
1051
|
+
const allDataForSelection = (0, import_react3.useMemo)(() => {
|
|
1052
|
+
if (pinnedTopData.length === 0 && pinnedBottomData.length === 0)
|
|
1053
|
+
return data;
|
|
1054
|
+
return [...pinnedTopData, ...data, ...pinnedBottomData];
|
|
1055
|
+
}, [pinnedTopData, data, pinnedBottomData]);
|
|
1056
|
+
const pinnedRowBg = styles?.pinnedRowBg ?? styles?.pinnedBg;
|
|
1044
1057
|
const columnStyles = (0, import_react3.useMemo)(() => {
|
|
1045
1058
|
return orderedColumns.map((col, colIndex) => {
|
|
1046
1059
|
const stickyOffset = columnOffsets.get(col.key);
|
|
@@ -1069,6 +1082,7 @@ var TableBody = ({
|
|
|
1069
1082
|
return /* @__PURE__ */ (0, import_jsx_runtime4.jsxs)(import_jsx_runtime4.Fragment, { children: [
|
|
1070
1083
|
columnStyles.map((colStyle, colIndex) => {
|
|
1071
1084
|
const col = orderedColumns[colIndex];
|
|
1085
|
+
const hasRender = !!col.render;
|
|
1072
1086
|
return /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(
|
|
1073
1087
|
"div",
|
|
1074
1088
|
{
|
|
@@ -1080,6 +1094,7 @@ var TableBody = ({
|
|
|
1080
1094
|
const isExpanded = resolvedExpandedKeys?.has(rowKey) ?? false;
|
|
1081
1095
|
const cellValue = row[col.dataIndex];
|
|
1082
1096
|
const isRowShimmer = isLoading || rowKey.startsWith("__shimmer_");
|
|
1097
|
+
const recordFingerprint = hasRender && !isRowShimmer ? JSON.stringify(row) : void 0;
|
|
1083
1098
|
return (
|
|
1084
1099
|
/*
|
|
1085
1100
|
* Row wrapper div:
|
|
@@ -1124,10 +1139,11 @@ var TableBody = ({
|
|
|
1124
1139
|
rowSelection,
|
|
1125
1140
|
normalizedSelectedKeys,
|
|
1126
1141
|
rowKey,
|
|
1127
|
-
allData:
|
|
1142
|
+
allData: allDataForSelection,
|
|
1128
1143
|
getRowKey,
|
|
1129
1144
|
accentColor,
|
|
1130
|
-
isLoading: isRowShimmer
|
|
1145
|
+
isLoading: isRowShimmer,
|
|
1146
|
+
recordFingerprint
|
|
1131
1147
|
}
|
|
1132
1148
|
)
|
|
1133
1149
|
}
|
|
@@ -1201,6 +1217,181 @@ var TableBody = ({
|
|
|
1201
1217
|
);
|
|
1202
1218
|
})
|
|
1203
1219
|
}
|
|
1220
|
+
),
|
|
1221
|
+
pinnedTopData.length > 0 && /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(
|
|
1222
|
+
"div",
|
|
1223
|
+
{
|
|
1224
|
+
style: {
|
|
1225
|
+
gridColumn: "1 / -1",
|
|
1226
|
+
gridRow: 2,
|
|
1227
|
+
position: "sticky",
|
|
1228
|
+
top: headerHeight,
|
|
1229
|
+
zIndex: 20,
|
|
1230
|
+
boxShadow: "0 2px 6px -1px rgba(0,0,0,0.08)"
|
|
1231
|
+
},
|
|
1232
|
+
children: pinnedTopData.map((row, rowIdx) => {
|
|
1233
|
+
const rk = getRowKey ? getRowKey(row, rowIdx) : String(rowIdx);
|
|
1234
|
+
const isSelected = selectedKeySet.has(rk);
|
|
1235
|
+
const isExpanded = resolvedExpandedKeys?.has(rk) ?? false;
|
|
1236
|
+
return /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(
|
|
1237
|
+
"div",
|
|
1238
|
+
{
|
|
1239
|
+
className: classNames?.pinnedRow ?? "",
|
|
1240
|
+
style: {
|
|
1241
|
+
display: "grid",
|
|
1242
|
+
gridTemplateColumns: gridTemplateColumns ?? "",
|
|
1243
|
+
minWidth: totalTableWidth ? `${totalTableWidth}px` : void 0,
|
|
1244
|
+
...styles?.pinnedRow
|
|
1245
|
+
},
|
|
1246
|
+
children: orderedColumns.map((col) => {
|
|
1247
|
+
const cellValue = row[col.dataIndex];
|
|
1248
|
+
const stickyOffset = columnOffsets.get(col.key);
|
|
1249
|
+
const isPinned = Boolean(col.pinned);
|
|
1250
|
+
let zIndex = 0;
|
|
1251
|
+
if (col.key === "__select__" || col.key === "__expand__")
|
|
1252
|
+
zIndex = 11;
|
|
1253
|
+
else if (isPinned) zIndex = 2;
|
|
1254
|
+
const recordFingerprint = col.render ? JSON.stringify(row) : void 0;
|
|
1255
|
+
return /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(
|
|
1256
|
+
"div",
|
|
1257
|
+
{
|
|
1258
|
+
"data-row-key": rk,
|
|
1259
|
+
"data-selected": isSelected || void 0,
|
|
1260
|
+
style: {
|
|
1261
|
+
position: isPinned ? "sticky" : "relative",
|
|
1262
|
+
...col.pinned === "left" && stickyOffset !== void 0 ? { left: `${stickyOffset}px` } : {},
|
|
1263
|
+
...col.pinned === "right" && stickyOffset !== void 0 ? { right: `${stickyOffset}px` } : {},
|
|
1264
|
+
zIndex,
|
|
1265
|
+
backgroundColor: pinnedRowBg,
|
|
1266
|
+
...isPinned && styles?.pinnedCell ? styles.pinnedCell : {}
|
|
1267
|
+
},
|
|
1268
|
+
children: /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(
|
|
1269
|
+
"div",
|
|
1270
|
+
{
|
|
1271
|
+
style: {
|
|
1272
|
+
height: `${rowHeight}px`,
|
|
1273
|
+
position: "relative"
|
|
1274
|
+
},
|
|
1275
|
+
children: /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(
|
|
1276
|
+
Cell,
|
|
1277
|
+
{
|
|
1278
|
+
value: cellValue,
|
|
1279
|
+
record: row,
|
|
1280
|
+
column: col,
|
|
1281
|
+
rowIndex: rowIdx,
|
|
1282
|
+
classNames,
|
|
1283
|
+
styles,
|
|
1284
|
+
isSelected,
|
|
1285
|
+
isExpanded,
|
|
1286
|
+
rowSelection,
|
|
1287
|
+
normalizedSelectedKeys,
|
|
1288
|
+
rowKey: rk,
|
|
1289
|
+
allData: allDataForSelection,
|
|
1290
|
+
getRowKey,
|
|
1291
|
+
accentColor,
|
|
1292
|
+
isLoading: false,
|
|
1293
|
+
recordFingerprint
|
|
1294
|
+
}
|
|
1295
|
+
)
|
|
1296
|
+
}
|
|
1297
|
+
)
|
|
1298
|
+
},
|
|
1299
|
+
col.key
|
|
1300
|
+
);
|
|
1301
|
+
})
|
|
1302
|
+
},
|
|
1303
|
+
`pinned-top-${rk}`
|
|
1304
|
+
);
|
|
1305
|
+
})
|
|
1306
|
+
}
|
|
1307
|
+
),
|
|
1308
|
+
pinnedBottomData.length > 0 && /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(
|
|
1309
|
+
"div",
|
|
1310
|
+
{
|
|
1311
|
+
style: {
|
|
1312
|
+
gridColumn: "1 / -1",
|
|
1313
|
+
gridRow: 2,
|
|
1314
|
+
position: "sticky",
|
|
1315
|
+
bottom: 0,
|
|
1316
|
+
alignSelf: "end",
|
|
1317
|
+
zIndex: 20,
|
|
1318
|
+
boxShadow: "0 -2px 6px -1px rgba(0,0,0,0.08)"
|
|
1319
|
+
},
|
|
1320
|
+
children: pinnedBottomData.map((row, rowIdx) => {
|
|
1321
|
+
const rk = getRowKey ? getRowKey(row, rowIdx) : String(rowIdx);
|
|
1322
|
+
const isSelected = selectedKeySet.has(rk);
|
|
1323
|
+
const isExpanded = resolvedExpandedKeys?.has(rk) ?? false;
|
|
1324
|
+
return /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(
|
|
1325
|
+
"div",
|
|
1326
|
+
{
|
|
1327
|
+
className: classNames?.pinnedRow ?? "",
|
|
1328
|
+
style: {
|
|
1329
|
+
display: "grid",
|
|
1330
|
+
gridTemplateColumns: gridTemplateColumns ?? "",
|
|
1331
|
+
minWidth: totalTableWidth ? `${totalTableWidth}px` : void 0,
|
|
1332
|
+
...styles?.pinnedRow
|
|
1333
|
+
},
|
|
1334
|
+
children: orderedColumns.map((col) => {
|
|
1335
|
+
const cellValue = row[col.dataIndex];
|
|
1336
|
+
const stickyOffset = columnOffsets.get(col.key);
|
|
1337
|
+
const isPinned = Boolean(col.pinned);
|
|
1338
|
+
let zIndex = 0;
|
|
1339
|
+
if (col.key === "__select__" || col.key === "__expand__")
|
|
1340
|
+
zIndex = 11;
|
|
1341
|
+
else if (isPinned) zIndex = 2;
|
|
1342
|
+
const recordFingerprint = col.render ? JSON.stringify(row) : void 0;
|
|
1343
|
+
return /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(
|
|
1344
|
+
"div",
|
|
1345
|
+
{
|
|
1346
|
+
"data-row-key": rk,
|
|
1347
|
+
"data-selected": isSelected || void 0,
|
|
1348
|
+
style: {
|
|
1349
|
+
position: isPinned ? "sticky" : "relative",
|
|
1350
|
+
...col.pinned === "left" && stickyOffset !== void 0 ? { left: `${stickyOffset}px` } : {},
|
|
1351
|
+
...col.pinned === "right" && stickyOffset !== void 0 ? { right: `${stickyOffset}px` } : {},
|
|
1352
|
+
zIndex,
|
|
1353
|
+
backgroundColor: pinnedRowBg,
|
|
1354
|
+
...isPinned && styles?.pinnedCell ? styles.pinnedCell : {}
|
|
1355
|
+
},
|
|
1356
|
+
children: /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(
|
|
1357
|
+
"div",
|
|
1358
|
+
{
|
|
1359
|
+
style: {
|
|
1360
|
+
height: `${rowHeight}px`,
|
|
1361
|
+
position: "relative"
|
|
1362
|
+
},
|
|
1363
|
+
children: /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(
|
|
1364
|
+
Cell,
|
|
1365
|
+
{
|
|
1366
|
+
value: cellValue,
|
|
1367
|
+
record: row,
|
|
1368
|
+
column: col,
|
|
1369
|
+
rowIndex: rowIdx,
|
|
1370
|
+
classNames,
|
|
1371
|
+
styles,
|
|
1372
|
+
isSelected,
|
|
1373
|
+
isExpanded,
|
|
1374
|
+
rowSelection,
|
|
1375
|
+
normalizedSelectedKeys,
|
|
1376
|
+
rowKey: rk,
|
|
1377
|
+
allData: allDataForSelection,
|
|
1378
|
+
getRowKey,
|
|
1379
|
+
accentColor,
|
|
1380
|
+
isLoading: false,
|
|
1381
|
+
recordFingerprint
|
|
1382
|
+
}
|
|
1383
|
+
)
|
|
1384
|
+
}
|
|
1385
|
+
)
|
|
1386
|
+
},
|
|
1387
|
+
col.key
|
|
1388
|
+
);
|
|
1389
|
+
})
|
|
1390
|
+
},
|
|
1391
|
+
`pinned-bottom-${rk}`
|
|
1392
|
+
);
|
|
1393
|
+
})
|
|
1394
|
+
}
|
|
1204
1395
|
)
|
|
1205
1396
|
] });
|
|
1206
1397
|
};
|
|
@@ -1236,6 +1427,7 @@ function BoltTable({
|
|
|
1236
1427
|
onColumnPin,
|
|
1237
1428
|
onColumnHide,
|
|
1238
1429
|
rowSelection,
|
|
1430
|
+
rowPinning,
|
|
1239
1431
|
expandable,
|
|
1240
1432
|
rowKey = "id",
|
|
1241
1433
|
onEndReached,
|
|
@@ -1634,6 +1826,23 @@ function BoltTable({
|
|
|
1634
1826
|
() => [...leftPinned, ...unpinned, ...rightPinned],
|
|
1635
1827
|
[leftPinned, unpinned, rightPinned]
|
|
1636
1828
|
);
|
|
1829
|
+
const freshOrderedColumns = (0, import_react4.useMemo)(() => {
|
|
1830
|
+
const latestMap = new Map(
|
|
1831
|
+
initialColumnsRef.current.map((c) => [c.key, c])
|
|
1832
|
+
);
|
|
1833
|
+
return orderedColumns.map((col) => {
|
|
1834
|
+
if (col.key === "__select__" || col.key === "__expand__") return col;
|
|
1835
|
+
const latest = latestMap.get(col.key);
|
|
1836
|
+
if (!latest) return col;
|
|
1837
|
+
if (col.render === latest.render && col.shimmerRender === latest.shimmerRender)
|
|
1838
|
+
return col;
|
|
1839
|
+
return {
|
|
1840
|
+
...col,
|
|
1841
|
+
render: latest.render,
|
|
1842
|
+
shimmerRender: latest.shimmerRender
|
|
1843
|
+
};
|
|
1844
|
+
});
|
|
1845
|
+
}, [orderedColumns, initialColumns]);
|
|
1637
1846
|
const totalTableWidth = (0, import_react4.useMemo)(
|
|
1638
1847
|
() => orderedColumns.slice(0, -1).reduce((sum, col) => sum + (col.width ?? 150), 0) + (orderedColumns.at(-1)?.width ?? 150),
|
|
1639
1848
|
[orderedColumns]
|
|
@@ -1759,6 +1968,35 @@ function BoltTable({
|
|
|
1759
1968
|
}
|
|
1760
1969
|
return result;
|
|
1761
1970
|
}, [data, sortState, columnFilters]);
|
|
1971
|
+
const { pinnedTopRows, pinnedBottomRows, unpinnedProcessedData } = (0, import_react4.useMemo)(() => {
|
|
1972
|
+
if (!rowPinning || !rowPinning.top?.length && !rowPinning.bottom?.length) {
|
|
1973
|
+
return {
|
|
1974
|
+
pinnedTopRows: [],
|
|
1975
|
+
pinnedBottomRows: [],
|
|
1976
|
+
unpinnedProcessedData: processedData
|
|
1977
|
+
};
|
|
1978
|
+
}
|
|
1979
|
+
const topKeySet = new Set((rowPinning.top ?? []).map(String));
|
|
1980
|
+
const bottomKeySet = new Set((rowPinning.bottom ?? []).map(String));
|
|
1981
|
+
const topMap = /* @__PURE__ */ new Map();
|
|
1982
|
+
const bottomMap = /* @__PURE__ */ new Map();
|
|
1983
|
+
const rest = [];
|
|
1984
|
+
processedData.forEach((row, idx) => {
|
|
1985
|
+
const key = getRowKey(row, idx);
|
|
1986
|
+
if (topKeySet.has(key)) topMap.set(key, row);
|
|
1987
|
+
else if (bottomKeySet.has(key)) bottomMap.set(key, row);
|
|
1988
|
+
else rest.push(row);
|
|
1989
|
+
});
|
|
1990
|
+
const orderedTop = (rowPinning.top ?? []).map((k) => topMap.get(String(k))).filter((r) => r !== void 0);
|
|
1991
|
+
const orderedBottom = (rowPinning.bottom ?? []).map((k) => bottomMap.get(String(k))).filter((r) => r !== void 0);
|
|
1992
|
+
return {
|
|
1993
|
+
pinnedTopRows: orderedTop,
|
|
1994
|
+
pinnedBottomRows: orderedBottom,
|
|
1995
|
+
unpinnedProcessedData: rest
|
|
1996
|
+
};
|
|
1997
|
+
}, [processedData, rowPinning, getRowKey]);
|
|
1998
|
+
const pinnedTopHeight = pinnedTopRows.length * rowHeight;
|
|
1999
|
+
const pinnedBottomHeight = pinnedBottomRows.length * rowHeight;
|
|
1762
2000
|
const columnFiltersKey = Object.keys(columnFilters).sort().map((k) => `${k}:${columnFilters[k]}`).join("|");
|
|
1763
2001
|
import_react4.default.useEffect(() => {
|
|
1764
2002
|
tableAreaRef.current?.scrollTo({ top: 0 });
|
|
@@ -1766,12 +2004,12 @@ function BoltTable({
|
|
|
1766
2004
|
const pgEnabled = pagination !== false && !!pagination;
|
|
1767
2005
|
const pgSize = pgEnabled ? pagination.pageSize ?? 10 : 10;
|
|
1768
2006
|
const pgCurrent = pgEnabled ? Number(pagination.current ?? 1) : 1;
|
|
1769
|
-
const needsClientPagination = pgEnabled &&
|
|
2007
|
+
const needsClientPagination = pgEnabled && unpinnedProcessedData.length > pgSize;
|
|
1770
2008
|
const paginatedData = (0, import_react4.useMemo)(() => {
|
|
1771
|
-
if (!needsClientPagination) return
|
|
2009
|
+
if (!needsClientPagination) return unpinnedProcessedData;
|
|
1772
2010
|
const start = (pgCurrent - 1) * pgSize;
|
|
1773
|
-
return
|
|
1774
|
-
}, [
|
|
2011
|
+
return unpinnedProcessedData.slice(start, start + pgSize);
|
|
2012
|
+
}, [unpinnedProcessedData, needsClientPagination, pgCurrent, pgSize]);
|
|
1775
2013
|
const shimmerCount = pgEnabled ? pgSize : 15;
|
|
1776
2014
|
const showShimmer = isLoading && processedData.length === 0;
|
|
1777
2015
|
const shimmerData = (0, import_react4.useMemo)(() => {
|
|
@@ -1829,8 +2067,9 @@ function BoltTable({
|
|
|
1829
2067
|
return cached ? rowHeight + cached : rowHeight + expandedRowHeight;
|
|
1830
2068
|
},
|
|
1831
2069
|
overscan: 5,
|
|
1832
|
-
|
|
1833
|
-
|
|
2070
|
+
getItemKey: (index) => shimmerData ? `__shimmer_${index}__` : getRowKey(displayData[index], index),
|
|
2071
|
+
paddingStart: pinnedTopHeight,
|
|
2072
|
+
paddingEnd: pinnedBottomHeight
|
|
1834
2073
|
});
|
|
1835
2074
|
const rowVirtualizerRef = (0, import_react4.useRef)(rowVirtualizer);
|
|
1836
2075
|
rowVirtualizerRef.current = rowVirtualizer;
|
|
@@ -1870,7 +2109,7 @@ function BoltTable({
|
|
|
1870
2109
|
const activeColumn = activeId ? orderedColumns.find((col) => col.key === activeId) : null;
|
|
1871
2110
|
const currentPage = pgCurrent;
|
|
1872
2111
|
const pageSize = pgSize;
|
|
1873
|
-
const rawTotal = pgEnabled ? pagination.total ?? (needsClientPagination ?
|
|
2112
|
+
const rawTotal = pgEnabled ? pagination.total ?? (needsClientPagination ? unpinnedProcessedData.length : data.length) : data.length;
|
|
1874
2113
|
const lastKnownTotalRef = (0, import_react4.useRef)(0);
|
|
1875
2114
|
if (!isLoading || rawTotal > 0) {
|
|
1876
2115
|
lastKnownTotalRef.current = rawTotal;
|
|
@@ -2290,7 +2529,7 @@ function BoltTable({
|
|
|
2290
2529
|
TableBody_default,
|
|
2291
2530
|
{
|
|
2292
2531
|
data: displayData,
|
|
2293
|
-
orderedColumns,
|
|
2532
|
+
orderedColumns: freshOrderedColumns,
|
|
2294
2533
|
rowVirtualizer,
|
|
2295
2534
|
columnOffsets,
|
|
2296
2535
|
styles,
|
|
@@ -2307,7 +2546,11 @@ function BoltTable({
|
|
|
2307
2546
|
scrollContainerRef: tableAreaRef,
|
|
2308
2547
|
isLoading: showShimmer,
|
|
2309
2548
|
onExpandedRowResize: handleExpandedRowResize,
|
|
2310
|
-
maxExpandedRowHeight
|
|
2549
|
+
maxExpandedRowHeight,
|
|
2550
|
+
pinnedTopData: pinnedTopRows,
|
|
2551
|
+
pinnedBottomData: pinnedBottomRows,
|
|
2552
|
+
gridTemplateColumns,
|
|
2553
|
+
headerHeight: HEADER_HEIGHT
|
|
2311
2554
|
}
|
|
2312
2555
|
)
|
|
2313
2556
|
)
|
|
@@ -2556,6 +2799,7 @@ function BoltTable({
|
|
|
2556
2799
|
position: "fixed",
|
|
2557
2800
|
zIndex: 99999,
|
|
2558
2801
|
height: 36,
|
|
2802
|
+
fontSize: 12,
|
|
2559
2803
|
alignItems: "center",
|
|
2560
2804
|
overflow: "hidden",
|
|
2561
2805
|
textOverflow: "ellipsis",
|