bolt-table 0.1.12 → 0.1.14
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +228 -2
- package/dist/index.d.mts +120 -2
- package/dist/index.d.ts +120 -2
- package/dist/index.js +567 -20
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +567 -20
- package/dist/index.mjs.map +1 -1
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -25,7 +25,10 @@ A high-performance, zero-dependency\* React table component. Only the rows visib
|
|
|
25
25
|
- **Infinite scroll** — `onEndReached` callback with configurable threshold
|
|
26
26
|
- **Empty state** — custom renderer or default "No data" message
|
|
27
27
|
- **Auto height** — table shrinks/grows to fit rows, capped at 10 rows by default
|
|
28
|
+
- **Row pinning** — pin rows to the top or bottom of the table, sticky during vertical scroll
|
|
29
|
+
- **Cell context menu** — right-click (or long-press on mobile) any cell to pin rows or copy values
|
|
28
30
|
- **Right-click context menu** — sort, filter, pin, hide, plus custom items
|
|
31
|
+
- **Mobile-friendly context menus** — long-press (touch-and-hold) triggers context menus on touch devices
|
|
29
32
|
- **Theme-agnostic** — works in light and dark mode out of the box, no CSS variables needed
|
|
30
33
|
- **Custom icons** — override any built-in icon via the `icons` prop
|
|
31
34
|
|
|
@@ -111,7 +114,7 @@ import type { BoltTableIcons } from 'bolt-table';
|
|
|
111
114
|
/>
|
|
112
115
|
```
|
|
113
116
|
|
|
114
|
-
Available icon keys: `gripVertical`, `sortAsc`, `sortDesc`, `filter`, `filterClear`, `pin`, `pinOff`, `eyeOff`, `chevronDown`, `chevronLeft`, `chevronRight`, `chevronsLeft`, `chevronsRight`.
|
|
117
|
+
Available icon keys: `gripVertical`, `sortAsc`, `sortDesc`, `filter`, `filterClear`, `pin`, `pinOff`, `eyeOff`, `chevronDown`, `chevronLeft`, `chevronRight`, `chevronsLeft`, `chevronsRight`, `copy`.
|
|
115
118
|
|
|
116
119
|
---
|
|
117
120
|
|
|
@@ -141,6 +144,8 @@ Available icon keys: `gripVertical`, `sortAsc`, `sortDesc`, `filter`, `filterCle
|
|
|
141
144
|
| `onColumnPin` | `(columnKey, pinned) => void` | — | Called when a column is pinned/unpinned |
|
|
142
145
|
| `onColumnHide` | `(columnKey, hidden) => void` | — | Called when a column is hidden/shown |
|
|
143
146
|
| `rowSelection` | `RowSelectionConfig<T>` | — | Row selection config |
|
|
147
|
+
| `rowPinning` | `RowPinningConfig` | — | Row pinning config (`{ top?: Key[], bottom?: Key[] }`) |
|
|
148
|
+
| `onRowPin` | `(rowKey, pinned) => void` | — | Called when a row is pinned/unpinned via cell context menu |
|
|
144
149
|
| `expandable` | `ExpandableConfig<T>` | — | Expandable row config |
|
|
145
150
|
| `onEndReached` | `() => void` | — | Called when scrolled near the bottom (infinite scroll) |
|
|
146
151
|
| `onEndReachedThreshold` | `number` | `5` | Rows from end to trigger `onEndReached` |
|
|
@@ -172,6 +177,7 @@ Available icon keys: `gripVertical`, `sortAsc`, `sortDesc`, `filter`, `filterCle
|
|
|
172
177
|
| `pinned` | `'left' \| 'right' \| false` | `false` | Pin this column to an edge |
|
|
173
178
|
| `className` | `string` | — | Class applied to all cells in this column |
|
|
174
179
|
| `style` | `CSSProperties` | — | Styles applied to all cells in this column |
|
|
180
|
+
| `copy` | `boolean \| (value, record, index) => string` | — | Enable "Copy" in cell context menu; function customizes what's copied |
|
|
175
181
|
|
|
176
182
|
---
|
|
177
183
|
|
|
@@ -372,6 +378,67 @@ Users can also pin/unpin columns at runtime via the right-click context menu.
|
|
|
372
378
|
|
|
373
379
|
---
|
|
374
380
|
|
|
381
|
+
### Row pinning
|
|
382
|
+
|
|
383
|
+
Pin rows to the top or bottom of the table so they stay visible while scrolling vertically. Pinned rows transcend pagination — they are always visible regardless of which page the user is on.
|
|
384
|
+
|
|
385
|
+
```tsx
|
|
386
|
+
const [rowPinning, setRowPinning] = useState({ top: [], bottom: [] });
|
|
387
|
+
|
|
388
|
+
<BoltTable
|
|
389
|
+
columns={columns}
|
|
390
|
+
data={data}
|
|
391
|
+
rowKey="id"
|
|
392
|
+
rowPinning={rowPinning}
|
|
393
|
+
onRowPin={(key, pinned) => {
|
|
394
|
+
setRowPinning(prev => {
|
|
395
|
+
const top = (prev.top ?? []).filter(k => String(k) !== String(key));
|
|
396
|
+
const bottom = (prev.bottom ?? []).filter(k => String(k) !== String(key));
|
|
397
|
+
if (pinned === 'top') top.push(key);
|
|
398
|
+
if (pinned === 'bottom') bottom.push(key);
|
|
399
|
+
return { top, bottom };
|
|
400
|
+
});
|
|
401
|
+
}}
|
|
402
|
+
styles={{ pinnedRowBg: 'rgba(255, 255, 255, 0.95)' }}
|
|
403
|
+
/>
|
|
404
|
+
```
|
|
405
|
+
|
|
406
|
+
Users can also pin/unpin rows at runtime via the right-click context menu on any body cell (when `onRowPin` is provided).
|
|
407
|
+
|
|
408
|
+
Pinned rows use `position: sticky` with `backdropFilter: blur(12px)` and a subtle box-shadow to visually separate them from scrolling content. Customize with `classNames.pinnedRow`, `styles.pinnedRow`, and `styles.pinnedRowBg`.
|
|
409
|
+
|
|
410
|
+
---
|
|
411
|
+
|
|
412
|
+
### Cell context menu & copy
|
|
413
|
+
|
|
414
|
+
Right-click (or long-press on mobile) any body cell to see a context menu with:
|
|
415
|
+
|
|
416
|
+
- **Pin to Top / Unpin from Top** — shown when `onRowPin` is provided
|
|
417
|
+
- **Pin to Bottom / Unpin from Bottom** — shown when `onRowPin` is provided
|
|
418
|
+
- **Copy** — shown when the column has `copy: true` or a copy function
|
|
419
|
+
|
|
420
|
+
```tsx
|
|
421
|
+
const columns: ColumnType<User>[] = [
|
|
422
|
+
{
|
|
423
|
+
key: 'name',
|
|
424
|
+
dataIndex: 'name',
|
|
425
|
+
title: 'Name',
|
|
426
|
+
copy: true, // copies the raw cell value
|
|
427
|
+
},
|
|
428
|
+
{
|
|
429
|
+
key: 'email',
|
|
430
|
+
dataIndex: 'email',
|
|
431
|
+
title: 'Email',
|
|
432
|
+
// Custom copy — control exactly what goes to the clipboard
|
|
433
|
+
copy: (value, record) => `${record.name} <${value}>`,
|
|
434
|
+
},
|
|
435
|
+
];
|
|
436
|
+
```
|
|
437
|
+
|
|
438
|
+
The cell context menu only appears when there is at least one action available (either `onRowPin` or `column.copy`). Otherwise, the browser's default context menu is used.
|
|
439
|
+
|
|
440
|
+
---
|
|
441
|
+
|
|
375
442
|
### Styling overrides
|
|
376
443
|
|
|
377
444
|
```tsx
|
|
@@ -427,6 +494,8 @@ A complete guide to every feature in BoltTable. Each section explains the concep
|
|
|
427
494
|
- [Row Selection](#row-selection-in-depth)
|
|
428
495
|
- [Expandable Rows](#expandable-rows-in-depth)
|
|
429
496
|
- [Column Interactions](#column-interactions)
|
|
497
|
+
- [Row Pinning](#row-pinning-in-depth)
|
|
498
|
+
- [Cell Context Menu & Copy](#cell-context-menu--copy-1)
|
|
430
499
|
- [Loading States](#loading-states)
|
|
431
500
|
- [Infinite Scroll](#infinite-scroll-in-depth)
|
|
432
501
|
- [Empty States](#empty-states)
|
|
@@ -499,6 +568,7 @@ Columns are the backbone of BoltTable. Each column is an object conforming to `C
|
|
|
499
568
|
| `sorter` | `boolean \| (a: T, b: T) => number` | — | `true` uses the default comparator. A function gives you full control. |
|
|
500
569
|
| `filterable` | `boolean` | `true` | Whether filter controls appear in the context menu. |
|
|
501
570
|
| `filterFn` | `(value: string, record: T, dataIndex: string) => boolean` | — | Custom filter predicate. Falls back to case-insensitive substring match. |
|
|
571
|
+
| `copy` | `boolean \| (value, record, index) => string` | — | `true` enables default copy. A function customizes the copied text. |
|
|
502
572
|
|
|
503
573
|
#### Custom rendering
|
|
504
574
|
|
|
@@ -1291,6 +1361,7 @@ CSS class overrides per table region. These are appended to (not replacing) the
|
|
|
1291
1361
|
| `pinnedCell` | Pinned column body cells (in addition to `cell`). |
|
|
1292
1362
|
| `dragHeader` | The floating ghost column shown while dragging. |
|
|
1293
1363
|
| `expandedRow` | The expanded content panel below each row. |
|
|
1364
|
+
| `pinnedRow` | Each pinned row's wrapper div. |
|
|
1294
1365
|
|
|
1295
1366
|
#### Layer 3: `styles`
|
|
1296
1367
|
|
|
@@ -1324,6 +1395,8 @@ Inline CSS overrides with the highest specificity:
|
|
|
1324
1395
|
| `rowSelected` | `CSSProperties` | Applied when a row is selected. |
|
|
1325
1396
|
| `dragHeader` | `CSSProperties` | The ghost column while dragging. |
|
|
1326
1397
|
| `expandedRow` | `CSSProperties` | Expanded content panel. |
|
|
1398
|
+
| `pinnedRow` | `CSSProperties` | Pinned row wrapper. |
|
|
1399
|
+
| `pinnedRowBg` | `string` | **CSS color** for pinned row cell backgrounds (falls back to `pinnedBg`). |
|
|
1327
1400
|
|
|
1328
1401
|
#### Per-column styling
|
|
1329
1402
|
|
|
@@ -1343,7 +1416,11 @@ Each column can also have its own `className` and `style`:
|
|
|
1343
1416
|
|
|
1344
1417
|
### Context Menu
|
|
1345
1418
|
|
|
1346
|
-
|
|
1419
|
+
BoltTable has two context menus — one for **column headers** and one for **body cells**. Both are accessible via right-click on desktop and **long-press (touch-and-hold ~500ms)** on mobile.
|
|
1420
|
+
|
|
1421
|
+
#### Column header context menu
|
|
1422
|
+
|
|
1423
|
+
Right-click (or long-press) any column header:
|
|
1347
1424
|
|
|
1348
1425
|
1. **Sort Ascending** / **Sort Descending** — if `sortable` is not `false`
|
|
1349
1426
|
2. **Filter Column** / **Clear Filter** — if `filterable` is not `false`
|
|
@@ -1399,6 +1476,152 @@ const customMenuItems: ColumnContextMenuItem[] = [
|
|
|
1399
1476
|
| `disabled` | `boolean` | Grays out the item; click handler not called. |
|
|
1400
1477
|
| `onClick` | `(columnKey: string) => void` | Called with the column's key when clicked. |
|
|
1401
1478
|
|
|
1479
|
+
#### Cell context menu
|
|
1480
|
+
|
|
1481
|
+
Right-click (or long-press) any body cell to see a context menu with row pinning and copy actions. This menu only appears when at least one action is available.
|
|
1482
|
+
|
|
1483
|
+
| Action | Shown when |
|
|
1484
|
+
|--------|-----------|
|
|
1485
|
+
| Pin to Top / Unpin from Top | `onRowPin` prop is provided |
|
|
1486
|
+
| Pin to Bottom / Unpin from Bottom | `onRowPin` prop is provided |
|
|
1487
|
+
| Copy | Column has `copy: true` or a copy function |
|
|
1488
|
+
|
|
1489
|
+
```tsx
|
|
1490
|
+
<BoltTable
|
|
1491
|
+
columns={[
|
|
1492
|
+
{ key: 'name', dataIndex: 'name', title: 'Name', copy: true },
|
|
1493
|
+
{
|
|
1494
|
+
key: 'email', dataIndex: 'email', title: 'Email',
|
|
1495
|
+
copy: (value, record) => `${record.name} <${value}>`,
|
|
1496
|
+
},
|
|
1497
|
+
]}
|
|
1498
|
+
data={data}
|
|
1499
|
+
rowKey="id"
|
|
1500
|
+
rowPinning={rowPinning}
|
|
1501
|
+
onRowPin={(key, pinned) => updatePinning(key, pinned)}
|
|
1502
|
+
/>
|
|
1503
|
+
```
|
|
1504
|
+
|
|
1505
|
+
#### Mobile support
|
|
1506
|
+
|
|
1507
|
+
Both context menus work on touch devices via **long-press** (touch-and-hold for ~500ms):
|
|
1508
|
+
|
|
1509
|
+
- Touch a header or cell and hold for 500ms → the context menu appears at the touch position
|
|
1510
|
+
- If you move your finger more than 10px before the timer fires, the long-press is cancelled (you're scrolling, not long-pressing)
|
|
1511
|
+
- Lifting your finger before 500ms cancels the long-press
|
|
1512
|
+
|
|
1513
|
+
No additional configuration is needed — mobile support is built in.
|
|
1514
|
+
|
|
1515
|
+
---
|
|
1516
|
+
|
|
1517
|
+
### Row Pinning In-Depth
|
|
1518
|
+
|
|
1519
|
+
Row pinning freezes specific rows at the top or bottom of the table body. Pinned rows remain visible while the user scrolls vertically — useful for summary rows, totals, or important records.
|
|
1520
|
+
|
|
1521
|
+
#### Basic usage
|
|
1522
|
+
|
|
1523
|
+
```tsx
|
|
1524
|
+
<BoltTable
|
|
1525
|
+
columns={columns}
|
|
1526
|
+
data={data}
|
|
1527
|
+
rowKey="id"
|
|
1528
|
+
rowPinning={{
|
|
1529
|
+
top: ['total-row', 'header-row'], // always visible at top
|
|
1530
|
+
bottom: ['footer-row'], // always visible at bottom
|
|
1531
|
+
}}
|
|
1532
|
+
/>
|
|
1533
|
+
```
|
|
1534
|
+
|
|
1535
|
+
#### Controlled pinning with context menu
|
|
1536
|
+
|
|
1537
|
+
When you provide `onRowPin`, users can pin/unpin rows via the cell right-click context menu:
|
|
1538
|
+
|
|
1539
|
+
```tsx
|
|
1540
|
+
const [rowPinning, setRowPinning] = useState<RowPinningConfig>({
|
|
1541
|
+
top: [],
|
|
1542
|
+
bottom: [],
|
|
1543
|
+
});
|
|
1544
|
+
|
|
1545
|
+
<BoltTable
|
|
1546
|
+
columns={columns}
|
|
1547
|
+
data={data}
|
|
1548
|
+
rowKey="id"
|
|
1549
|
+
rowPinning={rowPinning}
|
|
1550
|
+
onRowPin={(key, pinned) => {
|
|
1551
|
+
setRowPinning(prev => {
|
|
1552
|
+
const top = (prev.top ?? []).filter(k => String(k) !== String(key));
|
|
1553
|
+
const bottom = (prev.bottom ?? []).filter(k => String(k) !== String(key));
|
|
1554
|
+
if (pinned === 'top') top.push(key);
|
|
1555
|
+
if (pinned === 'bottom') bottom.push(key);
|
|
1556
|
+
return { top, bottom };
|
|
1557
|
+
});
|
|
1558
|
+
}}
|
|
1559
|
+
/>
|
|
1560
|
+
```
|
|
1561
|
+
|
|
1562
|
+
#### Key behaviors
|
|
1563
|
+
|
|
1564
|
+
- **Transcends pagination**: pinned rows are always visible regardless of which page the user is on
|
|
1565
|
+
- **Respects filtering**: if a pinned row's key doesn't match any row in the filtered data, it won't appear
|
|
1566
|
+
- **Column pinning**: column pinning (sticky left/right) works within pinned rows
|
|
1567
|
+
- **Selection & hover**: row selection and hover styles work on pinned rows
|
|
1568
|
+
- **Backdrop blur**: pinned rows have `backdropFilter: blur(12px)` by default
|
|
1569
|
+
|
|
1570
|
+
#### Styling pinned rows
|
|
1571
|
+
|
|
1572
|
+
```tsx
|
|
1573
|
+
<BoltTable
|
|
1574
|
+
classNames={{
|
|
1575
|
+
pinnedRow: 'border-b-2 border-blue-300',
|
|
1576
|
+
}}
|
|
1577
|
+
styles={{
|
|
1578
|
+
pinnedRow: { fontWeight: 600 },
|
|
1579
|
+
pinnedRowBg: 'rgba(239, 246, 255, 0.95)',
|
|
1580
|
+
}}
|
|
1581
|
+
/>
|
|
1582
|
+
```
|
|
1583
|
+
|
|
1584
|
+
#### `RowPinningConfig` reference
|
|
1585
|
+
|
|
1586
|
+
| Field | Type | Description |
|
|
1587
|
+
|-------|------|-------------|
|
|
1588
|
+
| `top` | `React.Key[]` | Row keys pinned to the top. Order is preserved. |
|
|
1589
|
+
| `bottom` | `React.Key[]` | Row keys pinned to the bottom. Order is preserved. |
|
|
1590
|
+
|
|
1591
|
+
---
|
|
1592
|
+
|
|
1593
|
+
### Cell Context Menu & Copy
|
|
1594
|
+
|
|
1595
|
+
The cell context menu provides per-cell actions triggered by right-click (desktop) or long-press (mobile).
|
|
1596
|
+
|
|
1597
|
+
#### The `copy` column option
|
|
1598
|
+
|
|
1599
|
+
Add `copy` to any column to enable the "Copy" action in the cell context menu:
|
|
1600
|
+
|
|
1601
|
+
```tsx
|
|
1602
|
+
const columns: ColumnType<User>[] = [
|
|
1603
|
+
{
|
|
1604
|
+
key: 'id',
|
|
1605
|
+
dataIndex: 'id',
|
|
1606
|
+
title: 'ID',
|
|
1607
|
+
copy: true, // copies String(value) to clipboard
|
|
1608
|
+
},
|
|
1609
|
+
{
|
|
1610
|
+
key: 'fullName',
|
|
1611
|
+
dataIndex: 'firstName',
|
|
1612
|
+
title: 'Full Name',
|
|
1613
|
+
// Custom copy function — like sorter, you control what gets copied
|
|
1614
|
+
copy: (value, record, index) => `${record.firstName} ${record.lastName}`,
|
|
1615
|
+
},
|
|
1616
|
+
];
|
|
1617
|
+
```
|
|
1618
|
+
|
|
1619
|
+
The `copy` field works like `sorter`:
|
|
1620
|
+
- `true` → default behavior (copies `String(cellValue)`)
|
|
1621
|
+
- A function `(value, record, index) => string` → you decide what string is copied
|
|
1622
|
+
|
|
1623
|
+
The copy action uses `navigator.clipboard.writeText()`.
|
|
1624
|
+
|
|
1402
1625
|
---
|
|
1403
1626
|
|
|
1404
1627
|
### Auto Height vs Fixed Height
|
|
@@ -1481,6 +1704,7 @@ const icons: BoltTableIcons = {
|
|
|
1481
1704
|
| `chevronRight` | Pagination: next page |
|
|
1482
1705
|
| `chevronsLeft` | Pagination: first page |
|
|
1483
1706
|
| `chevronsRight` | Pagination: last page |
|
|
1707
|
+
| `copy` | Copy action in cell context menu |
|
|
1484
1708
|
|
|
1485
1709
|
To hide the grip icon entirely:
|
|
1486
1710
|
|
|
@@ -1541,6 +1765,7 @@ import type {
|
|
|
1541
1765
|
DataRecord, // Base row type (Record<string, unknown>)
|
|
1542
1766
|
ExpandableConfig, // Expandable rows configuration
|
|
1543
1767
|
PaginationType, // Pagination configuration
|
|
1768
|
+
RowPinningConfig, // Row pinning configuration ({ top?, bottom? })
|
|
1544
1769
|
RowSelectionConfig, // Row selection configuration
|
|
1545
1770
|
SortDirection, // 'asc' | 'desc' | null
|
|
1546
1771
|
} from 'bolt-table';
|
|
@@ -1744,6 +1969,7 @@ import type {
|
|
|
1744
1969
|
ColumnType,
|
|
1745
1970
|
ColumnContextMenuItem,
|
|
1746
1971
|
RowSelectionConfig,
|
|
1972
|
+
RowPinningConfig,
|
|
1747
1973
|
ExpandableConfig,
|
|
1748
1974
|
PaginationType,
|
|
1749
1975
|
SortDirection,
|
package/dist/index.d.mts
CHANGED
|
@@ -29,6 +29,7 @@ interface BoltTableIcons {
|
|
|
29
29
|
chevronRight?: React$1.ReactNode;
|
|
30
30
|
chevronsLeft?: React$1.ReactNode;
|
|
31
31
|
chevronsRight?: React$1.ReactNode;
|
|
32
|
+
copy?: React$1.ReactNode;
|
|
32
33
|
}
|
|
33
34
|
|
|
34
35
|
/**
|
|
@@ -240,6 +241,23 @@ interface ColumnType<T = unknown> {
|
|
|
240
241
|
* style: { textAlign: 'right', fontFamily: 'monospace' }
|
|
241
242
|
*/
|
|
242
243
|
style?: React.CSSProperties;
|
|
244
|
+
/**
|
|
245
|
+
* Enables the "Copy" action in the cell right-click context menu.
|
|
246
|
+
*
|
|
247
|
+
* - `true` — copies the raw cell value as a string via `String(value)`
|
|
248
|
+
* - A function — called with `(value, record, index)` to produce the
|
|
249
|
+
* string that is copied to the clipboard. Similar to `sorter`.
|
|
250
|
+
*
|
|
251
|
+
* When omitted or `false`, no "Copy" option appears in the cell menu.
|
|
252
|
+
*
|
|
253
|
+
* @example
|
|
254
|
+
* // Default copy
|
|
255
|
+
* copy: true
|
|
256
|
+
*
|
|
257
|
+
* // Custom copy — combine fields
|
|
258
|
+
* copy: (value, record) => `${record.firstName} ${record.lastName}`
|
|
259
|
+
*/
|
|
260
|
+
copy?: boolean | ((value: unknown, record: T, index: number) => string);
|
|
243
261
|
}
|
|
244
262
|
/**
|
|
245
263
|
* A single item in the column header context menu (right-click menu).
|
|
@@ -569,6 +587,38 @@ interface PaginationType {
|
|
|
569
587
|
*/
|
|
570
588
|
showTotal?: (total: number, range: [number, number]) => ReactNode;
|
|
571
589
|
}
|
|
590
|
+
/**
|
|
591
|
+
* Configuration for row pinning.
|
|
592
|
+
* When provided, the specified rows are rendered as sticky rows at the top
|
|
593
|
+
* and/or bottom of the table body, remaining visible during vertical scroll.
|
|
594
|
+
*
|
|
595
|
+
* Pinned rows are excluded from pagination — they are always visible regardless
|
|
596
|
+
* of which page the user is on. Filtering still applies: if a pinned row's key
|
|
597
|
+
* doesn't exist in the (filtered) data, it simply won't appear.
|
|
598
|
+
*
|
|
599
|
+
* @example
|
|
600
|
+
* // Pin two rows to the top and one to the bottom
|
|
601
|
+
* rowPinning={{ top: ['row-1', 'row-3'], bottom: ['row-10'] }}
|
|
602
|
+
*
|
|
603
|
+
* @example
|
|
604
|
+
* // Controlled pinning — manage pinned keys in parent state
|
|
605
|
+
* const [pinning, setPinning] = useState<RowPinningConfig>({ top: ['header-row'] });
|
|
606
|
+
* <BoltTable rowPinning={pinning} ... />
|
|
607
|
+
*/
|
|
608
|
+
interface RowPinningConfig {
|
|
609
|
+
/**
|
|
610
|
+
* Row keys to pin at the top of the table.
|
|
611
|
+
* These rows stick below the column headers during vertical scroll.
|
|
612
|
+
* Order is preserved — rows are rendered in the order listed here.
|
|
613
|
+
*/
|
|
614
|
+
top?: React.Key[];
|
|
615
|
+
/**
|
|
616
|
+
* Row keys to pin at the bottom of the table.
|
|
617
|
+
* These rows stick to the bottom of the visible area during vertical scroll.
|
|
618
|
+
* Order is preserved — rows are rendered in the order listed here.
|
|
619
|
+
*/
|
|
620
|
+
bottom?: React.Key[];
|
|
621
|
+
}
|
|
572
622
|
/**
|
|
573
623
|
* The base type for a row record in BoltTable.
|
|
574
624
|
* All row data objects must be indexable by string keys.
|
|
@@ -910,6 +960,36 @@ interface BoltTableProps<T extends DataRecord = DataRecord> {
|
|
|
910
960
|
* }}
|
|
911
961
|
*/
|
|
912
962
|
readonly rowSelection?: RowSelectionConfig<T>;
|
|
963
|
+
/**
|
|
964
|
+
* Row pinning configuration. When provided, the specified rows are rendered
|
|
965
|
+
* as sticky rows at the top and/or bottom of the table body.
|
|
966
|
+
*
|
|
967
|
+
* Pinned rows transcend pagination — they are always visible regardless of
|
|
968
|
+
* which page the user is on. Filtering still applies.
|
|
969
|
+
*
|
|
970
|
+
* @example
|
|
971
|
+
* rowPinning={{ top: ['row-1', 'row-3'], bottom: ['row-10'] }}
|
|
972
|
+
*/
|
|
973
|
+
readonly rowPinning?: RowPinningConfig;
|
|
974
|
+
/**
|
|
975
|
+
* Called when the user pins or unpins a row via the cell right-click context menu.
|
|
976
|
+
* Update your `rowPinning` state in this callback.
|
|
977
|
+
*
|
|
978
|
+
* @param rowKey - The key of the row whose pin state changed
|
|
979
|
+
* @param pinned - `'top'`, `'bottom'`, or `false` (unpinned)
|
|
980
|
+
*
|
|
981
|
+
* @example
|
|
982
|
+
* onRowPin={(key, pinned) => {
|
|
983
|
+
* setRowPinning(prev => {
|
|
984
|
+
* const top = (prev.top ?? []).filter(k => String(k) !== String(key));
|
|
985
|
+
* const bottom = (prev.bottom ?? []).filter(k => String(k) !== String(key));
|
|
986
|
+
* if (pinned === 'top') top.push(key);
|
|
987
|
+
* if (pinned === 'bottom') bottom.push(key);
|
|
988
|
+
* return { top, bottom };
|
|
989
|
+
* });
|
|
990
|
+
* }}
|
|
991
|
+
*/
|
|
992
|
+
readonly onRowPin?: (rowKey: React$1.Key, pinned: 'top' | 'bottom' | false) => void;
|
|
913
993
|
/**
|
|
914
994
|
* Called when the user scrolls near the bottom of the table.
|
|
915
995
|
* Use this for infinite scroll / load-more behavior.
|
|
@@ -1106,6 +1186,11 @@ interface ClassNamesTypes {
|
|
|
1106
1186
|
* Does not affect the row itself, only the expanded panel.
|
|
1107
1187
|
*/
|
|
1108
1188
|
expandedRow?: string;
|
|
1189
|
+
/**
|
|
1190
|
+
* Applied to each pinned row's wrapper div (the grid row containing all cells).
|
|
1191
|
+
* Use this to add a border, background, or separator for pinned rows.
|
|
1192
|
+
*/
|
|
1193
|
+
pinnedRow?: string;
|
|
1109
1194
|
}
|
|
1110
1195
|
/**
|
|
1111
1196
|
* Inline style overrides for specific regions of BoltTable.
|
|
@@ -1146,6 +1231,17 @@ interface StylesTypes {
|
|
|
1146
1231
|
pinnedCell?: CSSProperties;
|
|
1147
1232
|
/** Inline styles for the expanded row content panel */
|
|
1148
1233
|
expandedRow?: CSSProperties;
|
|
1234
|
+
/** Inline styles for pinned row wrappers (the grid row containing all cells) */
|
|
1235
|
+
pinnedRow?: CSSProperties;
|
|
1236
|
+
/**
|
|
1237
|
+
* CSS color string for the background of pinned row cells.
|
|
1238
|
+
* Should be opaque so that scrolling content behind pinned rows is hidden.
|
|
1239
|
+
* Falls back to `pinnedBg` if not set.
|
|
1240
|
+
*
|
|
1241
|
+
* @example
|
|
1242
|
+
* pinnedRowBg: 'rgba(255, 255, 255, 0.98)'
|
|
1243
|
+
*/
|
|
1244
|
+
pinnedRowBg?: string;
|
|
1149
1245
|
/**
|
|
1150
1246
|
* CSS color string applied as the background of hovered rows.
|
|
1151
1247
|
* Defaults to `hsl(var(--muted) / 0.5)` if omitted.
|
|
@@ -1210,7 +1306,7 @@ interface StylesTypes {
|
|
|
1210
1306
|
* autoHeight={false}
|
|
1211
1307
|
* />
|
|
1212
1308
|
*/
|
|
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;
|
|
1309
|
+
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, onRowPin, expandable, rowKey, onEndReached, onEndReachedThreshold, isLoading, onSortChange, onFilterChange, columnContextMenuItems, autoHeight, layoutLoading, emptyRenderer, }: BoltTableProps<T>): react_jsx_runtime.JSX.Element;
|
|
1214
1310
|
|
|
1215
1311
|
/**
|
|
1216
1312
|
* Props for the DraggableHeader component.
|
|
@@ -1569,6 +1665,28 @@ interface TableBodyProps {
|
|
|
1569
1665
|
* maxExpandedRowHeight={300}
|
|
1570
1666
|
*/
|
|
1571
1667
|
maxExpandedRowHeight?: number;
|
|
1668
|
+
/**
|
|
1669
|
+
* Rows pinned to the top of the table body.
|
|
1670
|
+
* Rendered as non-virtualized sticky rows below the column headers.
|
|
1671
|
+
*/
|
|
1672
|
+
pinnedTopData?: DataRecord[];
|
|
1673
|
+
/**
|
|
1674
|
+
* Rows pinned to the bottom of the table body.
|
|
1675
|
+
* Rendered as non-virtualized sticky rows at the bottom of the visible area.
|
|
1676
|
+
*/
|
|
1677
|
+
pinnedBottomData?: DataRecord[];
|
|
1678
|
+
/**
|
|
1679
|
+
* The CSS `gridTemplateColumns` string matching the parent grid.
|
|
1680
|
+
* Needed for pinned row sub-grids to align with the main column layout.
|
|
1681
|
+
*/
|
|
1682
|
+
gridTemplateColumns?: string;
|
|
1683
|
+
/**
|
|
1684
|
+
* Height of the column header row in pixels.
|
|
1685
|
+
* Used to position the sticky top pinned rows below the headers.
|
|
1686
|
+
*
|
|
1687
|
+
* @default 36
|
|
1688
|
+
*/
|
|
1689
|
+
headerHeight?: number;
|
|
1572
1690
|
}
|
|
1573
1691
|
/**
|
|
1574
1692
|
* TableBody — the virtualized body renderer for BoltTable.
|
|
@@ -1590,4 +1708,4 @@ interface TableBodyProps {
|
|
|
1590
1708
|
*/
|
|
1591
1709
|
declare const TableBody: React$1.FC<TableBodyProps>;
|
|
1592
1710
|
|
|
1593
|
-
export { BoltTable, type BoltTableIcons, type ColumnContextMenuItem, type ColumnType, type DataRecord, DraggableHeader, type ExpandableConfig, type PaginationType, ResizeOverlay, type RowSelectionConfig, type SortDirection, TableBody };
|
|
1711
|
+
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
|
@@ -29,6 +29,7 @@ interface BoltTableIcons {
|
|
|
29
29
|
chevronRight?: React$1.ReactNode;
|
|
30
30
|
chevronsLeft?: React$1.ReactNode;
|
|
31
31
|
chevronsRight?: React$1.ReactNode;
|
|
32
|
+
copy?: React$1.ReactNode;
|
|
32
33
|
}
|
|
33
34
|
|
|
34
35
|
/**
|
|
@@ -240,6 +241,23 @@ interface ColumnType<T = unknown> {
|
|
|
240
241
|
* style: { textAlign: 'right', fontFamily: 'monospace' }
|
|
241
242
|
*/
|
|
242
243
|
style?: React.CSSProperties;
|
|
244
|
+
/**
|
|
245
|
+
* Enables the "Copy" action in the cell right-click context menu.
|
|
246
|
+
*
|
|
247
|
+
* - `true` — copies the raw cell value as a string via `String(value)`
|
|
248
|
+
* - A function — called with `(value, record, index)` to produce the
|
|
249
|
+
* string that is copied to the clipboard. Similar to `sorter`.
|
|
250
|
+
*
|
|
251
|
+
* When omitted or `false`, no "Copy" option appears in the cell menu.
|
|
252
|
+
*
|
|
253
|
+
* @example
|
|
254
|
+
* // Default copy
|
|
255
|
+
* copy: true
|
|
256
|
+
*
|
|
257
|
+
* // Custom copy — combine fields
|
|
258
|
+
* copy: (value, record) => `${record.firstName} ${record.lastName}`
|
|
259
|
+
*/
|
|
260
|
+
copy?: boolean | ((value: unknown, record: T, index: number) => string);
|
|
243
261
|
}
|
|
244
262
|
/**
|
|
245
263
|
* A single item in the column header context menu (right-click menu).
|
|
@@ -569,6 +587,38 @@ interface PaginationType {
|
|
|
569
587
|
*/
|
|
570
588
|
showTotal?: (total: number, range: [number, number]) => ReactNode;
|
|
571
589
|
}
|
|
590
|
+
/**
|
|
591
|
+
* Configuration for row pinning.
|
|
592
|
+
* When provided, the specified rows are rendered as sticky rows at the top
|
|
593
|
+
* and/or bottom of the table body, remaining visible during vertical scroll.
|
|
594
|
+
*
|
|
595
|
+
* Pinned rows are excluded from pagination — they are always visible regardless
|
|
596
|
+
* of which page the user is on. Filtering still applies: if a pinned row's key
|
|
597
|
+
* doesn't exist in the (filtered) data, it simply won't appear.
|
|
598
|
+
*
|
|
599
|
+
* @example
|
|
600
|
+
* // Pin two rows to the top and one to the bottom
|
|
601
|
+
* rowPinning={{ top: ['row-1', 'row-3'], bottom: ['row-10'] }}
|
|
602
|
+
*
|
|
603
|
+
* @example
|
|
604
|
+
* // Controlled pinning — manage pinned keys in parent state
|
|
605
|
+
* const [pinning, setPinning] = useState<RowPinningConfig>({ top: ['header-row'] });
|
|
606
|
+
* <BoltTable rowPinning={pinning} ... />
|
|
607
|
+
*/
|
|
608
|
+
interface RowPinningConfig {
|
|
609
|
+
/**
|
|
610
|
+
* Row keys to pin at the top of the table.
|
|
611
|
+
* These rows stick below the column headers during vertical scroll.
|
|
612
|
+
* Order is preserved — rows are rendered in the order listed here.
|
|
613
|
+
*/
|
|
614
|
+
top?: React.Key[];
|
|
615
|
+
/**
|
|
616
|
+
* Row keys to pin at the bottom of the table.
|
|
617
|
+
* These rows stick to the bottom of the visible area during vertical scroll.
|
|
618
|
+
* Order is preserved — rows are rendered in the order listed here.
|
|
619
|
+
*/
|
|
620
|
+
bottom?: React.Key[];
|
|
621
|
+
}
|
|
572
622
|
/**
|
|
573
623
|
* The base type for a row record in BoltTable.
|
|
574
624
|
* All row data objects must be indexable by string keys.
|
|
@@ -910,6 +960,36 @@ interface BoltTableProps<T extends DataRecord = DataRecord> {
|
|
|
910
960
|
* }}
|
|
911
961
|
*/
|
|
912
962
|
readonly rowSelection?: RowSelectionConfig<T>;
|
|
963
|
+
/**
|
|
964
|
+
* Row pinning configuration. When provided, the specified rows are rendered
|
|
965
|
+
* as sticky rows at the top and/or bottom of the table body.
|
|
966
|
+
*
|
|
967
|
+
* Pinned rows transcend pagination — they are always visible regardless of
|
|
968
|
+
* which page the user is on. Filtering still applies.
|
|
969
|
+
*
|
|
970
|
+
* @example
|
|
971
|
+
* rowPinning={{ top: ['row-1', 'row-3'], bottom: ['row-10'] }}
|
|
972
|
+
*/
|
|
973
|
+
readonly rowPinning?: RowPinningConfig;
|
|
974
|
+
/**
|
|
975
|
+
* Called when the user pins or unpins a row via the cell right-click context menu.
|
|
976
|
+
* Update your `rowPinning` state in this callback.
|
|
977
|
+
*
|
|
978
|
+
* @param rowKey - The key of the row whose pin state changed
|
|
979
|
+
* @param pinned - `'top'`, `'bottom'`, or `false` (unpinned)
|
|
980
|
+
*
|
|
981
|
+
* @example
|
|
982
|
+
* onRowPin={(key, pinned) => {
|
|
983
|
+
* setRowPinning(prev => {
|
|
984
|
+
* const top = (prev.top ?? []).filter(k => String(k) !== String(key));
|
|
985
|
+
* const bottom = (prev.bottom ?? []).filter(k => String(k) !== String(key));
|
|
986
|
+
* if (pinned === 'top') top.push(key);
|
|
987
|
+
* if (pinned === 'bottom') bottom.push(key);
|
|
988
|
+
* return { top, bottom };
|
|
989
|
+
* });
|
|
990
|
+
* }}
|
|
991
|
+
*/
|
|
992
|
+
readonly onRowPin?: (rowKey: React$1.Key, pinned: 'top' | 'bottom' | false) => void;
|
|
913
993
|
/**
|
|
914
994
|
* Called when the user scrolls near the bottom of the table.
|
|
915
995
|
* Use this for infinite scroll / load-more behavior.
|
|
@@ -1106,6 +1186,11 @@ interface ClassNamesTypes {
|
|
|
1106
1186
|
* Does not affect the row itself, only the expanded panel.
|
|
1107
1187
|
*/
|
|
1108
1188
|
expandedRow?: string;
|
|
1189
|
+
/**
|
|
1190
|
+
* Applied to each pinned row's wrapper div (the grid row containing all cells).
|
|
1191
|
+
* Use this to add a border, background, or separator for pinned rows.
|
|
1192
|
+
*/
|
|
1193
|
+
pinnedRow?: string;
|
|
1109
1194
|
}
|
|
1110
1195
|
/**
|
|
1111
1196
|
* Inline style overrides for specific regions of BoltTable.
|
|
@@ -1146,6 +1231,17 @@ interface StylesTypes {
|
|
|
1146
1231
|
pinnedCell?: CSSProperties;
|
|
1147
1232
|
/** Inline styles for the expanded row content panel */
|
|
1148
1233
|
expandedRow?: CSSProperties;
|
|
1234
|
+
/** Inline styles for pinned row wrappers (the grid row containing all cells) */
|
|
1235
|
+
pinnedRow?: CSSProperties;
|
|
1236
|
+
/**
|
|
1237
|
+
* CSS color string for the background of pinned row cells.
|
|
1238
|
+
* Should be opaque so that scrolling content behind pinned rows is hidden.
|
|
1239
|
+
* Falls back to `pinnedBg` if not set.
|
|
1240
|
+
*
|
|
1241
|
+
* @example
|
|
1242
|
+
* pinnedRowBg: 'rgba(255, 255, 255, 0.98)'
|
|
1243
|
+
*/
|
|
1244
|
+
pinnedRowBg?: string;
|
|
1149
1245
|
/**
|
|
1150
1246
|
* CSS color string applied as the background of hovered rows.
|
|
1151
1247
|
* Defaults to `hsl(var(--muted) / 0.5)` if omitted.
|
|
@@ -1210,7 +1306,7 @@ interface StylesTypes {
|
|
|
1210
1306
|
* autoHeight={false}
|
|
1211
1307
|
* />
|
|
1212
1308
|
*/
|
|
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;
|
|
1309
|
+
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, onRowPin, expandable, rowKey, onEndReached, onEndReachedThreshold, isLoading, onSortChange, onFilterChange, columnContextMenuItems, autoHeight, layoutLoading, emptyRenderer, }: BoltTableProps<T>): react_jsx_runtime.JSX.Element;
|
|
1214
1310
|
|
|
1215
1311
|
/**
|
|
1216
1312
|
* Props for the DraggableHeader component.
|
|
@@ -1569,6 +1665,28 @@ interface TableBodyProps {
|
|
|
1569
1665
|
* maxExpandedRowHeight={300}
|
|
1570
1666
|
*/
|
|
1571
1667
|
maxExpandedRowHeight?: number;
|
|
1668
|
+
/**
|
|
1669
|
+
* Rows pinned to the top of the table body.
|
|
1670
|
+
* Rendered as non-virtualized sticky rows below the column headers.
|
|
1671
|
+
*/
|
|
1672
|
+
pinnedTopData?: DataRecord[];
|
|
1673
|
+
/**
|
|
1674
|
+
* Rows pinned to the bottom of the table body.
|
|
1675
|
+
* Rendered as non-virtualized sticky rows at the bottom of the visible area.
|
|
1676
|
+
*/
|
|
1677
|
+
pinnedBottomData?: DataRecord[];
|
|
1678
|
+
/**
|
|
1679
|
+
* The CSS `gridTemplateColumns` string matching the parent grid.
|
|
1680
|
+
* Needed for pinned row sub-grids to align with the main column layout.
|
|
1681
|
+
*/
|
|
1682
|
+
gridTemplateColumns?: string;
|
|
1683
|
+
/**
|
|
1684
|
+
* Height of the column header row in pixels.
|
|
1685
|
+
* Used to position the sticky top pinned rows below the headers.
|
|
1686
|
+
*
|
|
1687
|
+
* @default 36
|
|
1688
|
+
*/
|
|
1689
|
+
headerHeight?: number;
|
|
1572
1690
|
}
|
|
1573
1691
|
/**
|
|
1574
1692
|
* TableBody — the virtualized body renderer for BoltTable.
|
|
@@ -1590,4 +1708,4 @@ interface TableBodyProps {
|
|
|
1590
1708
|
*/
|
|
1591
1709
|
declare const TableBody: React$1.FC<TableBodyProps>;
|
|
1592
1710
|
|
|
1593
|
-
export { BoltTable, type BoltTableIcons, type ColumnContextMenuItem, type ColumnType, type DataRecord, DraggableHeader, type ExpandableConfig, type PaginationType, ResizeOverlay, type RowSelectionConfig, type SortDirection, TableBody };
|
|
1711
|
+
export { BoltTable, type BoltTableIcons, type ColumnContextMenuItem, type ColumnType, type DataRecord, DraggableHeader, type ExpandableConfig, type PaginationType, ResizeOverlay, type RowPinningConfig, type RowSelectionConfig, type SortDirection, TableBody };
|