bolt-table 0.1.22 → 0.1.23

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 CHANGED
@@ -238,6 +238,10 @@ interface BoltTableProps<T extends DataRecord = DataRecord> {
238
238
  readonly rowStyle?: (record: T, index: number) => React$1.CSSProperties;
239
239
  /** When true, removes the filter option from all header column context menus. */
240
240
  readonly disabledFilters?: boolean;
241
+ /** Called after a cell value is copied to the clipboard via the context menu. */
242
+ readonly onCopy?: (text: string, columnKey: string, record: T, rowIndex: number) => void;
243
+ /** When true, pinned rows remain visible even after navigating to a different page. */
244
+ readonly keepPinnedRowsAcrossPages?: boolean;
241
245
  }
242
246
  interface ClassNamesTypes {
243
247
  /** Applied to all non-pinned column header cells. */
@@ -285,7 +289,7 @@ interface StylesTypes {
285
289
  /** Inline styles applied to built-in context menu items (sort, filter, pin, copy, etc.). */
286
290
  contextMenuItem?: CSSProperties;
287
291
  }
288
- 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, disabledFilters, }: BoltTableProps<T>): react_jsx_runtime.JSX.Element;
292
+ 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, disabledFilters, onCopy, keepPinnedRowsAcrossPages, }: BoltTableProps<T>): react_jsx_runtime.JSX.Element;
289
293
 
290
294
  interface DraggableHeaderProps {
291
295
  /** Column definition for this header cell. */
package/dist/index.d.ts CHANGED
@@ -238,6 +238,10 @@ interface BoltTableProps<T extends DataRecord = DataRecord> {
238
238
  readonly rowStyle?: (record: T, index: number) => React$1.CSSProperties;
239
239
  /** When true, removes the filter option from all header column context menus. */
240
240
  readonly disabledFilters?: boolean;
241
+ /** Called after a cell value is copied to the clipboard via the context menu. */
242
+ readonly onCopy?: (text: string, columnKey: string, record: T, rowIndex: number) => void;
243
+ /** When true, pinned rows remain visible even after navigating to a different page. */
244
+ readonly keepPinnedRowsAcrossPages?: boolean;
241
245
  }
242
246
  interface ClassNamesTypes {
243
247
  /** Applied to all non-pinned column header cells. */
@@ -285,7 +289,7 @@ interface StylesTypes {
285
289
  /** Inline styles applied to built-in context menu items (sort, filter, pin, copy, etc.). */
286
290
  contextMenuItem?: CSSProperties;
287
291
  }
288
- 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, disabledFilters, }: BoltTableProps<T>): react_jsx_runtime.JSX.Element;
292
+ 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, disabledFilters, onCopy, keepPinnedRowsAcrossPages, }: BoltTableProps<T>): react_jsx_runtime.JSX.Element;
289
293
 
290
294
  interface DraggableHeaderProps {
291
295
  /** Column definition for this header cell. */
package/dist/index.js CHANGED
@@ -1511,7 +1511,9 @@ function BoltTable({
1511
1511
  emptyRenderer,
1512
1512
  rowClassName,
1513
1513
  rowStyle,
1514
- disabledFilters
1514
+ disabledFilters,
1515
+ onCopy,
1516
+ keepPinnedRowsAcrossPages
1515
1517
  }) {
1516
1518
  const data = (0, import_react4.useMemo)(() => {
1517
1519
  if (!Array.isArray(rawData)) return STABLE_EMPTY_DATA;
@@ -2126,8 +2128,10 @@ function BoltTable({
2126
2128
  }
2127
2129
  return result;
2128
2130
  }, [data, sortState, columnFilters]);
2131
+ const pinnedRowCacheRef = (0, import_react4.useRef)(/* @__PURE__ */ new Map());
2129
2132
  const { pinnedTopRows, pinnedBottomRows, unpinnedProcessedData } = (0, import_react4.useMemo)(() => {
2130
2133
  if (!resolvedRowPinning || !resolvedRowPinning.top?.length && !resolvedRowPinning.bottom?.length) {
2134
+ if (keepPinnedRowsAcrossPages) pinnedRowCacheRef.current.clear();
2131
2135
  return {
2132
2136
  pinnedTopRows: [],
2133
2137
  pinnedBottomRows: [],
@@ -2142,10 +2146,32 @@ function BoltTable({
2142
2146
  processedData.forEach((row, idx) => {
2143
2147
  if (row == null) return;
2144
2148
  const key = getRowKey(row, idx);
2145
- if (topKeySet.has(key)) topMap.set(key, row);
2146
- else if (bottomKeySet.has(key)) bottomMap.set(key, row);
2147
- else rest.push(row);
2149
+ if (topKeySet.has(key)) {
2150
+ topMap.set(key, row);
2151
+ if (keepPinnedRowsAcrossPages) pinnedRowCacheRef.current.set(key, row);
2152
+ } else if (bottomKeySet.has(key)) {
2153
+ bottomMap.set(key, row);
2154
+ if (keepPinnedRowsAcrossPages) pinnedRowCacheRef.current.set(key, row);
2155
+ } else {
2156
+ rest.push(row);
2157
+ }
2148
2158
  });
2159
+ if (keepPinnedRowsAcrossPages) {
2160
+ for (const k of topKeySet) {
2161
+ if (!topMap.has(k) && pinnedRowCacheRef.current.has(k)) {
2162
+ topMap.set(k, pinnedRowCacheRef.current.get(k));
2163
+ }
2164
+ }
2165
+ for (const k of bottomKeySet) {
2166
+ if (!bottomMap.has(k) && pinnedRowCacheRef.current.has(k)) {
2167
+ bottomMap.set(k, pinnedRowCacheRef.current.get(k));
2168
+ }
2169
+ }
2170
+ const allPinnedKeys = /* @__PURE__ */ new Set([...topKeySet, ...bottomKeySet]);
2171
+ for (const cachedKey of pinnedRowCacheRef.current.keys()) {
2172
+ if (!allPinnedKeys.has(cachedKey)) pinnedRowCacheRef.current.delete(cachedKey);
2173
+ }
2174
+ }
2149
2175
  const orderedTop = (resolvedRowPinning.top ?? []).map((k) => topMap.get(String(k))).filter((r) => r !== void 0);
2150
2176
  const orderedBottom = (resolvedRowPinning.bottom ?? []).map((k) => bottomMap.get(String(k))).filter((r) => r !== void 0);
2151
2177
  return {
@@ -2153,7 +2179,7 @@ function BoltTable({
2153
2179
  pinnedBottomRows: orderedBottom,
2154
2180
  unpinnedProcessedData: rest
2155
2181
  };
2156
- }, [processedData, resolvedRowPinning, getRowKey]);
2182
+ }, [processedData, resolvedRowPinning, getRowKey, keepPinnedRowsAcrossPages]);
2157
2183
  const pinnedTopHeight = pinnedTopRows.length * rowHeight;
2158
2184
  const pinnedBottomHeight = pinnedBottomRows.length * rowHeight;
2159
2185
  const pinnedTopKeySet = (0, import_react4.useMemo)(
@@ -3267,6 +3293,7 @@ function BoltTable({
3267
3293
  onClick: () => {
3268
3294
  const text = typeof menuCol.copy === "function" ? menuCol.copy(menuValue, menuRecord, menuRowIndex) : String(menuValue ?? "");
3269
3295
  navigator.clipboard?.writeText(text);
3296
+ onCopy?.(text, menuCol.key, menuRecord, menuRowIndex);
3270
3297
  setCellContextMenu(null);
3271
3298
  },
3272
3299
  children: [
package/dist/index.mjs CHANGED
@@ -1477,7 +1477,9 @@ function BoltTable({
1477
1477
  emptyRenderer,
1478
1478
  rowClassName,
1479
1479
  rowStyle,
1480
- disabledFilters
1480
+ disabledFilters,
1481
+ onCopy,
1482
+ keepPinnedRowsAcrossPages
1481
1483
  }) {
1482
1484
  const data = useMemo2(() => {
1483
1485
  if (!Array.isArray(rawData)) return STABLE_EMPTY_DATA;
@@ -2092,8 +2094,10 @@ function BoltTable({
2092
2094
  }
2093
2095
  return result;
2094
2096
  }, [data, sortState, columnFilters]);
2097
+ const pinnedRowCacheRef = useRef4(/* @__PURE__ */ new Map());
2095
2098
  const { pinnedTopRows, pinnedBottomRows, unpinnedProcessedData } = useMemo2(() => {
2096
2099
  if (!resolvedRowPinning || !resolvedRowPinning.top?.length && !resolvedRowPinning.bottom?.length) {
2100
+ if (keepPinnedRowsAcrossPages) pinnedRowCacheRef.current.clear();
2097
2101
  return {
2098
2102
  pinnedTopRows: [],
2099
2103
  pinnedBottomRows: [],
@@ -2108,10 +2112,32 @@ function BoltTable({
2108
2112
  processedData.forEach((row, idx) => {
2109
2113
  if (row == null) return;
2110
2114
  const key = getRowKey(row, idx);
2111
- if (topKeySet.has(key)) topMap.set(key, row);
2112
- else if (bottomKeySet.has(key)) bottomMap.set(key, row);
2113
- else rest.push(row);
2115
+ if (topKeySet.has(key)) {
2116
+ topMap.set(key, row);
2117
+ if (keepPinnedRowsAcrossPages) pinnedRowCacheRef.current.set(key, row);
2118
+ } else if (bottomKeySet.has(key)) {
2119
+ bottomMap.set(key, row);
2120
+ if (keepPinnedRowsAcrossPages) pinnedRowCacheRef.current.set(key, row);
2121
+ } else {
2122
+ rest.push(row);
2123
+ }
2114
2124
  });
2125
+ if (keepPinnedRowsAcrossPages) {
2126
+ for (const k of topKeySet) {
2127
+ if (!topMap.has(k) && pinnedRowCacheRef.current.has(k)) {
2128
+ topMap.set(k, pinnedRowCacheRef.current.get(k));
2129
+ }
2130
+ }
2131
+ for (const k of bottomKeySet) {
2132
+ if (!bottomMap.has(k) && pinnedRowCacheRef.current.has(k)) {
2133
+ bottomMap.set(k, pinnedRowCacheRef.current.get(k));
2134
+ }
2135
+ }
2136
+ const allPinnedKeys = /* @__PURE__ */ new Set([...topKeySet, ...bottomKeySet]);
2137
+ for (const cachedKey of pinnedRowCacheRef.current.keys()) {
2138
+ if (!allPinnedKeys.has(cachedKey)) pinnedRowCacheRef.current.delete(cachedKey);
2139
+ }
2140
+ }
2115
2141
  const orderedTop = (resolvedRowPinning.top ?? []).map((k) => topMap.get(String(k))).filter((r) => r !== void 0);
2116
2142
  const orderedBottom = (resolvedRowPinning.bottom ?? []).map((k) => bottomMap.get(String(k))).filter((r) => r !== void 0);
2117
2143
  return {
@@ -2119,7 +2145,7 @@ function BoltTable({
2119
2145
  pinnedBottomRows: orderedBottom,
2120
2146
  unpinnedProcessedData: rest
2121
2147
  };
2122
- }, [processedData, resolvedRowPinning, getRowKey]);
2148
+ }, [processedData, resolvedRowPinning, getRowKey, keepPinnedRowsAcrossPages]);
2123
2149
  const pinnedTopHeight = pinnedTopRows.length * rowHeight;
2124
2150
  const pinnedBottomHeight = pinnedBottomRows.length * rowHeight;
2125
2151
  const pinnedTopKeySet = useMemo2(
@@ -3233,6 +3259,7 @@ function BoltTable({
3233
3259
  onClick: () => {
3234
3260
  const text = typeof menuCol.copy === "function" ? menuCol.copy(menuValue, menuRecord, menuRowIndex) : String(menuValue ?? "");
3235
3261
  navigator.clipboard?.writeText(text);
3262
+ onCopy?.(text, menuCol.key, menuRecord, menuRowIndex);
3236
3263
  setCellContextMenu(null);
3237
3264
  },
3238
3265
  children: [
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "bolt-table",
3
- "version": "0.1.22",
3
+ "version": "0.1.23",
4
4
  "description": "Virtualized React table with column drag & drop, pinning, resizing, sorting, filtering, and pagination.",
5
5
  "license": "MIT",
6
6
  "main": "./dist/index.js",