@jielga/tmdatagrid 1.0.1 → 1.0.2
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/package.json +1 -1
- package/skills/appearance/SKILL.md +322 -0
- package/skills/cell-selection/SKILL.md +240 -0
- package/skills/columns/SKILL.md +260 -85
- package/skills/data/SKILL.md +289 -0
- package/skills/editing/SKILL.md +492 -0
- package/skills/editing/references/editing-api.md +124 -0
- package/skills/editing/references/editors-and-validation.md +198 -0
- package/skills/filtering/SKILL.md +344 -0
- package/skills/getting-started/SKILL.md +33 -12
- package/skills/grouping/SKILL.md +264 -0
- package/skills/options/SKILL.md +24 -13
- package/skills/rows/SKILL.md +369 -0
- package/skills/rows/references/rows-api.md +117 -0
- package/skills/server-side/SKILL.md +1 -1
- package/skills/testing/SKILL.md +1 -1
- package/skills/features/SKILL.md +0 -352
|
@@ -0,0 +1,369 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: rows
|
|
3
|
+
description: >
|
|
4
|
+
Everything a TMDataGrid row does beyond holding cells. Covers selectionMode
|
|
5
|
+
and its four modes (checkbox, row, checkboxAndHighlight, highlight), the
|
|
6
|
+
highlight as state of its own with defaultHighlightedRowId and
|
|
7
|
+
onHighlightedRowChange, showSelectedBackground and --dg-row-selected-bg,
|
|
8
|
+
reading a selection through the table store, onRowClick / onCellClick /
|
|
9
|
+
onCellDoubleClick / onCellContextMenu, the rowContextMenu render prop and
|
|
10
|
+
rowContextMenuProps, per-row styling with rowStyle, rowClassName, striped and
|
|
11
|
+
the --row-bg rule, the row details panel through renderDetails and
|
|
12
|
+
DETAILS_COLUMN_ID, row pinning with enableRowPinning and row.pin, and the
|
|
13
|
+
row-number gutter through enableRowNumbers. Load when selecting rows, reacting
|
|
14
|
+
to a click, opening a detail panel, colouring rows by their data, pinning rows
|
|
15
|
+
to an edge, or numbering them.
|
|
16
|
+
metadata:
|
|
17
|
+
type: core
|
|
18
|
+
library: '@jielga/tmdatagrid'
|
|
19
|
+
library_version: '1.0.2'
|
|
20
|
+
sources:
|
|
21
|
+
- 'Jielga/TMDataGrid:src/docs/row-selection.md'
|
|
22
|
+
- 'Jielga/TMDataGrid:src/docs/row-interaction.md'
|
|
23
|
+
- 'Jielga/TMDataGrid:src/docs/row-styling.md'
|
|
24
|
+
- 'Jielga/TMDataGrid:src/docs/row-details.md'
|
|
25
|
+
- 'Jielga/TMDataGrid:src/docs/row-pinning.md'
|
|
26
|
+
- 'Jielga/TMDataGrid:src/tmdatagrid/core/rowSelection.ts'
|
|
27
|
+
---
|
|
28
|
+
|
|
29
|
+
# TMDataGrid - Rows
|
|
30
|
+
|
|
31
|
+
Selecting rows, reacting to clicks, colouring them, opening a panel under one,
|
|
32
|
+
and pinning or numbering them. Column-side concerns are the `columns` skill;
|
|
33
|
+
cell cursors and ranges are `cell-selection`.
|
|
34
|
+
|
|
35
|
+
## Selection
|
|
36
|
+
|
|
37
|
+
`selectionMode` sets what selecting looks like **and** what a bare row click
|
|
38
|
+
does. One option rather than two, because a click can either toggle a
|
|
39
|
+
multi-selection or move a highlight, never both.
|
|
40
|
+
|
|
41
|
+
| Mode | Checkbox column | Row click |
|
|
42
|
+
| --- | --- | --- |
|
|
43
|
+
| `"checkbox"` (default) | yes, multi-select | nothing |
|
|
44
|
+
| `"row"` | no | selects, with the usual modifiers |
|
|
45
|
+
| `"checkboxAndHighlight"` | yes, multi-select | highlights one row |
|
|
46
|
+
| `"highlight"` | no | highlights one row, no selection at all |
|
|
47
|
+
|
|
48
|
+
```tsx
|
|
49
|
+
const grid = useTMDataGrid({ data, columns, selectionMode: "row" });
|
|
50
|
+
```
|
|
51
|
+
|
|
52
|
+
The first two write to TanStack's `rowSelection`, so everything downstream - the
|
|
53
|
+
toolbar count, `getSelectedRowModel()`, persistence - is unaffected by the
|
|
54
|
+
choice. Under `"row"` the click follows desktop-list conventions: a plain click
|
|
55
|
+
makes the selection this row, Ctrl/Cmd toggles it and leaves the rest, Shift
|
|
56
|
+
selects the range from the anchor, Ctrl+Shift adds that range. Rows are
|
|
57
|
+
focusable in this mode, and Space or Enter toggles the focused row.
|
|
58
|
+
|
|
59
|
+
`enableRowSelection: false` removes the selection half whatever the mode.
|
|
60
|
+
|
|
61
|
+
### The highlight is not a selection
|
|
62
|
+
|
|
63
|
+
The highlight is state of its own, not a slice of `rowSelection` - which is what
|
|
64
|
+
lets `"checkboxAndHighlight"` run both at once: tick rows for a bulk action,
|
|
65
|
+
click one to open its record beside the grid.
|
|
66
|
+
|
|
67
|
+
```tsx
|
|
68
|
+
const grid = useTMDataGrid({
|
|
69
|
+
data,
|
|
70
|
+
columns,
|
|
71
|
+
selectionMode: "highlight",
|
|
72
|
+
defaultHighlightedRowId: routeId,
|
|
73
|
+
onHighlightedRowChange: (rowId) =>
|
|
74
|
+
navigate({ to: "/employees/$id", params: { id: rowId ?? "" } }),
|
|
75
|
+
});
|
|
76
|
+
```
|
|
77
|
+
|
|
78
|
+
### Reading a selection
|
|
79
|
+
|
|
80
|
+
Read it through the table store, never by calling the method bare. `table` keeps
|
|
81
|
+
one identity across renders, so the React Compiler caches a bare
|
|
82
|
+
`getSelectedRowModel()` and the reader stops updating.
|
|
83
|
+
|
|
84
|
+
```tsx
|
|
85
|
+
import { useSelector } from "@tanstack/react-store";
|
|
86
|
+
|
|
87
|
+
const selected = useSelector(grid.table.store, () =>
|
|
88
|
+
grid.table.getSelectedRowModel().rows,
|
|
89
|
+
);
|
|
90
|
+
```
|
|
91
|
+
|
|
92
|
+
### The background
|
|
93
|
+
|
|
94
|
+
`showSelectedBackground` follows the mode: on for `"row"`, where the background
|
|
95
|
+
is the only feedback a click gives, off for `"checkbox"`, where the box already
|
|
96
|
+
says so. Set it to override either way. The colour is `--dg-row-selected-bg`,
|
|
97
|
+
changed on the grid element rather than through the flag:
|
|
98
|
+
|
|
99
|
+
```tsx
|
|
100
|
+
<TMDataGrid
|
|
101
|
+
{...grid}
|
|
102
|
+
style={{ "--dg-row-selected-bg": "var(--mantine-color-blue-0)" }}
|
|
103
|
+
/>
|
|
104
|
+
```
|
|
105
|
+
|
|
106
|
+
A group row's checkbox selects every record under it at any depth, shows a tick
|
|
107
|
+
once all are selected and a dash while only some are, and writes only the
|
|
108
|
+
records to `rowSelection`.
|
|
109
|
+
|
|
110
|
+
## Clicks and context menus
|
|
111
|
+
|
|
112
|
+
Every handler **composes** with what the click already does. `onRowClick` does
|
|
113
|
+
not replace selection or the highlight; yours runs in addition.
|
|
114
|
+
|
|
115
|
+
| Handler | Argument | Notes |
|
|
116
|
+
| --- | --- | --- |
|
|
117
|
+
| `onRowClick` | `row` | Rows show a pointer cursor when set |
|
|
118
|
+
| `onCellClick` | `{ cell, row, column, event }` | The cell cursor still moves |
|
|
119
|
+
| `onCellDoubleClick` | same | A double-click that opens an editor still does |
|
|
120
|
+
| `onCellContextMenu` | same | `rowContextMenu` still opens |
|
|
121
|
+
|
|
122
|
+
```tsx
|
|
123
|
+
<TMDataGrid.Table<Employee> onRowClick={(row) => open(row.original.id)} />
|
|
124
|
+
```
|
|
125
|
+
|
|
126
|
+
Pass the row type, as above, and `row.original` is typed. Group rows sit out all
|
|
127
|
+
four: TanStack builds a group row on top of its first child's record, so a
|
|
128
|
+
handler would receive a real-looking row that is the wrong one.
|
|
129
|
+
|
|
130
|
+
`rowContextMenu` is a render prop saying what goes inside the menu. The grid
|
|
131
|
+
owns the Mantine `Menu`, opening it at the pointer and closing it on Escape, an
|
|
132
|
+
outside click, a body scroll and after an item is picked.
|
|
133
|
+
|
|
134
|
+
```tsx
|
|
135
|
+
<TMDataGrid.Table<Employee>
|
|
136
|
+
rowContextMenu={({ table, row, cell }) => (
|
|
137
|
+
<>
|
|
138
|
+
<Menu.Label>{row.original.firstName}</Menu.Label>
|
|
139
|
+
<Menu.Item onClick={() => open(row.original.id)}>Open</Menu.Item>
|
|
140
|
+
<Menu.Item
|
|
141
|
+
onClick={() =>
|
|
142
|
+
navigator.clipboard.writeText(String(cell?.getValue() ?? ""))
|
|
143
|
+
}
|
|
144
|
+
>
|
|
145
|
+
Copy cell value
|
|
146
|
+
</Menu.Item>
|
|
147
|
+
</>
|
|
148
|
+
)}
|
|
149
|
+
rowContextMenuProps={{ width: 260, position: "right-start" }}
|
|
150
|
+
/>
|
|
151
|
+
```
|
|
152
|
+
|
|
153
|
+
It is called **during render**, only for the row whose menu is open, so keep it
|
|
154
|
+
a pure function of its arguments and do the work in the item handlers. Return
|
|
155
|
+
`null` to leave a row without a menu. Right-clicking does not select: it marks
|
|
156
|
+
the row with `data-context-menu` while its menu is open, so an action meant for
|
|
157
|
+
a multi-selection reads `table` and falls back to the clicked row.
|
|
158
|
+
|
|
159
|
+
## Row styling
|
|
160
|
+
|
|
161
|
+
```tsx
|
|
162
|
+
<TMDataGrid.Table<Employee>
|
|
163
|
+
striped
|
|
164
|
+
rowStyle={(row) =>
|
|
165
|
+
row.original.status === "Terminated"
|
|
166
|
+
? { "--row-bg": "var(--mantine-color-red-0)" }
|
|
167
|
+
: undefined
|
|
168
|
+
}
|
|
169
|
+
rowClassName={(row) => (row.original.overdue ? classes.overdue : undefined)}
|
|
170
|
+
/>
|
|
171
|
+
```
|
|
172
|
+
|
|
173
|
+
A row is a strip of cells, some sticky in pinned lanes, and hover, selection,
|
|
174
|
+
the highlight, the cell range and striping all paint on top of it. `--row-bg`
|
|
175
|
+
feeds the variable those layers compose against; `background` wins over all of
|
|
176
|
+
them and kills them. `striped` follows position in the view, so it survives
|
|
177
|
+
sorting and filtering rather than sticking to records, and pinned rows sit it
|
|
178
|
+
out.
|
|
179
|
+
|
|
180
|
+
Rows carry `data-selected`, `data-selected-bg`, `data-highlighted`,
|
|
181
|
+
`data-grouped`, `data-depth`, `data-context-menu` and `data-row-id`, so a
|
|
182
|
+
stylesheet can reach any of it without a callback.
|
|
183
|
+
|
|
184
|
+
## The details panel
|
|
185
|
+
|
|
186
|
+
Setting `renderDetails` turns the lane on. There is no flag.
|
|
187
|
+
|
|
188
|
+
```tsx
|
|
189
|
+
const grid = useTMDataGrid({
|
|
190
|
+
data,
|
|
191
|
+
columns,
|
|
192
|
+
renderDetails: ({ row }) => <EmployeeCard employee={row.original} />,
|
|
193
|
+
});
|
|
194
|
+
```
|
|
195
|
+
|
|
196
|
+
Each panel is measured, so heights need not be uniform;
|
|
197
|
+
`renderDetailsEstHeight` (default `160`) is only what the virtualizer assumes
|
|
198
|
+
for one it has not seen. A generated chevron column, `DETAILS_COLUMN_ID`, is
|
|
199
|
+
prepended and pinned left after the checkbox and tree lanes; it cannot be
|
|
200
|
+
hidden, moved, resized or unpinned, and its header opens and closes every panel.
|
|
201
|
+
|
|
202
|
+
Which rows are open is TanStack's own `expanded` state, so anything can open
|
|
203
|
+
one - `row.toggleExpanded()` from a menu item, `initialState.expanded`,
|
|
204
|
+
`table.toggleAllRowsExpanded()` - and it persists as a `data` slice. The panel
|
|
205
|
+
is a cell spanning the row, not a row: `aria-rowcount` still counts records, and
|
|
206
|
+
a click inside it stops there rather than selecting the row underneath. Group
|
|
207
|
+
rows have no panel; expanding one opens its children.
|
|
208
|
+
|
|
209
|
+
## Pinning and numbering
|
|
210
|
+
|
|
211
|
+
Two independent lanes at the edges.
|
|
212
|
+
|
|
213
|
+
```tsx
|
|
214
|
+
const grid = useTMDataGrid({
|
|
215
|
+
data,
|
|
216
|
+
columns,
|
|
217
|
+
enableRowPinning: true,
|
|
218
|
+
enableRowNumbers: true,
|
|
219
|
+
});
|
|
220
|
+
```
|
|
221
|
+
|
|
222
|
+
There is no built-in pin gesture - pin from wherever suits, most naturally the
|
|
223
|
+
row context menu, through TanStack's own `row.pin("top" | "bottom" | false)`,
|
|
224
|
+
`row.getIsPinned()` and `row.getCanPin()`. Pinned rows leave the scrolling order
|
|
225
|
+
and render in sticky blocks: top under the header, bottom above the summary row.
|
|
226
|
+
|
|
227
|
+
Pinned rows are still body rows - selection, editing, details, the context menu
|
|
228
|
+
and per-row styling all behave normally. What they sit out are the statements
|
|
229
|
+
about scrolling order: striping, the cell range, and the number gutter. A pinned
|
|
230
|
+
row stays at its edge even when a filter or the pager would have dropped it, and
|
|
231
|
+
**group rows never pin**.
|
|
232
|
+
|
|
233
|
+
`enableRowNumbers` adds a gutter outermost left that numbers the current view -
|
|
234
|
+
sorted, filtered, continuing across pages. It answers "where am I in what I am
|
|
235
|
+
looking at", not "which record is this"; a stable identifier is a column of your
|
|
236
|
+
own over the record's id.
|
|
237
|
+
|
|
238
|
+
## Common mistakes
|
|
239
|
+
|
|
240
|
+
### CRITICAL Setting `background` in `rowStyle`
|
|
241
|
+
|
|
242
|
+
A coloured row stops responding to hover, selection, the highlight and the cell
|
|
243
|
+
range, because `background` paints over every layer composed on top of the row.
|
|
244
|
+
Nothing errors; the row simply goes inert.
|
|
245
|
+
|
|
246
|
+
Wrong:
|
|
247
|
+
|
|
248
|
+
```tsx
|
|
249
|
+
rowStyle={() => ({ background: "pink" })}
|
|
250
|
+
```
|
|
251
|
+
|
|
252
|
+
Correct:
|
|
253
|
+
|
|
254
|
+
```tsx
|
|
255
|
+
rowStyle={() => ({ "--row-bg": "pink" })}
|
|
256
|
+
```
|
|
257
|
+
|
|
258
|
+
Source: `src/docs/row-styling.md` (Set `--row-bg`, not `background`).
|
|
259
|
+
|
|
260
|
+
### CRITICAL Reading the selection without subscribing
|
|
261
|
+
|
|
262
|
+
`table` keeps one identity for the life of the grid, so the React Compiler
|
|
263
|
+
memoizes a bare `getSelectedRowModel()` against it. The count renders once and
|
|
264
|
+
then never changes, which reads as a broken toolbar rather than a missing
|
|
265
|
+
subscription.
|
|
266
|
+
|
|
267
|
+
Wrong:
|
|
268
|
+
|
|
269
|
+
```tsx
|
|
270
|
+
const selected = grid.table.getSelectedRowModel().rows;
|
|
271
|
+
```
|
|
272
|
+
|
|
273
|
+
Correct:
|
|
274
|
+
|
|
275
|
+
```tsx
|
|
276
|
+
const selected = useSelector(grid.table.store, () =>
|
|
277
|
+
grid.table.getSelectedRowModel().rows,
|
|
278
|
+
);
|
|
279
|
+
```
|
|
280
|
+
|
|
281
|
+
Source: `src/docs/row-selection.md` (Acting on a selection).
|
|
282
|
+
|
|
283
|
+
### HIGH Looking for the highlight in `rowSelection`
|
|
284
|
+
|
|
285
|
+
The highlight is separate state, which is what lets
|
|
286
|
+
`"checkboxAndHighlight"` run both at once. It never appears in `rowSelection`,
|
|
287
|
+
`getSelectedRowModel()` or the persisted selection slice.
|
|
288
|
+
|
|
289
|
+
Wrong:
|
|
290
|
+
|
|
291
|
+
```tsx
|
|
292
|
+
// Always empty under selectionMode: "highlight".
|
|
293
|
+
const current = Object.keys(grid.table.store.state.rowSelection)[0];
|
|
294
|
+
```
|
|
295
|
+
|
|
296
|
+
Correct:
|
|
297
|
+
|
|
298
|
+
```tsx
|
|
299
|
+
const current = useSelector(grid.ui, (state) => state.highlightedRowId);
|
|
300
|
+
```
|
|
301
|
+
|
|
302
|
+
Source: `src/docs/row-selection.md` (The highlight is not a selection).
|
|
303
|
+
|
|
304
|
+
### HIGH Expecting a click handler to replace the built-in behaviour
|
|
305
|
+
|
|
306
|
+
`onRowClick` composes. Under `selectionMode: "row"` a click both selects and
|
|
307
|
+
runs the handler, so a handler that navigates away will also have changed the
|
|
308
|
+
selection on the way out.
|
|
309
|
+
|
|
310
|
+
Correct, when the click should only navigate:
|
|
311
|
+
|
|
312
|
+
```tsx
|
|
313
|
+
// "highlight" moves a marker and selects nothing.
|
|
314
|
+
useTMDataGrid({ data, columns, selectionMode: "highlight" });
|
|
315
|
+
```
|
|
316
|
+
|
|
317
|
+
Source: `src/docs/row-interaction.md`.
|
|
318
|
+
|
|
319
|
+
### HIGH Reading `row.getIsExpanded()` in a cell without subscribing
|
|
320
|
+
|
|
321
|
+
Same mechanism as the selection above: the compiler caches the call against the
|
|
322
|
+
`row` identity, so a custom expand control renders its initial state forever.
|
|
323
|
+
|
|
324
|
+
Correct:
|
|
325
|
+
|
|
326
|
+
```tsx
|
|
327
|
+
const expanded = useSelector(row.table.store, () => row.getIsExpanded());
|
|
328
|
+
```
|
|
329
|
+
|
|
330
|
+
Source: `src/docs/row-details.md` (Opening a row from elsewhere).
|
|
331
|
+
|
|
332
|
+
### MEDIUM Assuming group rows behave like data rows
|
|
333
|
+
|
|
334
|
+
Group rows are built on their first child's record. They sit out `onRowClick`,
|
|
335
|
+
`onCellClick`, `onCellDoubleClick` and `onCellContextMenu`, they never pin, they
|
|
336
|
+
take no row number, and they have no details panel. A handler written as though
|
|
337
|
+
every row reaches it will silently skip them.
|
|
338
|
+
|
|
339
|
+
Source: `src/docs/row-interaction.md`, `src/docs/row-pinning.md`.
|
|
340
|
+
|
|
341
|
+
### MEDIUM Open panels closing when `data` is replaced
|
|
342
|
+
|
|
343
|
+
TanStack resets `expanded` when the row structure changes, so a refetch collapses
|
|
344
|
+
every open panel.
|
|
345
|
+
|
|
346
|
+
Correct:
|
|
347
|
+
|
|
348
|
+
```tsx
|
|
349
|
+
useTMDataGrid({ data, columns, renderDetails, autoResetExpanded: false });
|
|
350
|
+
```
|
|
351
|
+
|
|
352
|
+
Source: `src/docs/row-details.md`.
|
|
353
|
+
|
|
354
|
+
### MEDIUM Expecting pinned rows to persist
|
|
355
|
+
|
|
356
|
+
`rowPinning` is deliberately left out of `settingsKey`: row ids are data, and a
|
|
357
|
+
layout store outlives any one data set. A pinned id whose row leaves `data` is
|
|
358
|
+
simply not shown, and returns to its edge if the data comes back.
|
|
359
|
+
|
|
360
|
+
Source: `src/docs/row-pinning.md`.
|
|
361
|
+
|
|
362
|
+
## References
|
|
363
|
+
|
|
364
|
+
- [Rows API](references/rows-api.md) - every option, table prop, callback,
|
|
365
|
+
export, CSS variable and data attribute these five topics own.
|
|
366
|
+
|
|
367
|
+
See also: the `grouping` skill for group rows and the tree lane, the
|
|
368
|
+
`cell-selection` skill for the cell cursor and ranges, and the `appearance`
|
|
369
|
+
skill for the CSS variables named here.
|
|
@@ -0,0 +1,117 @@
|
|
|
1
|
+
# Rows API
|
|
2
|
+
|
|
3
|
+
Reference for the `rows` skill.
|
|
4
|
+
|
|
5
|
+
## Selection
|
|
6
|
+
|
|
7
|
+
| Name | Kind | Type | Default | What it does |
|
|
8
|
+
| --- | --- | --- | --- | --- |
|
|
9
|
+
| `selectionMode` | Option | `"checkbox" \| "row" \| "checkboxAndHighlight" \| "highlight"` | `"checkbox"` | What selecting looks like and what a row click does. |
|
|
10
|
+
| `enableRowSelection` | Table option | `boolean \| ((row) => boolean)` | `true` | `false` removes the checkbox column and row-click selection. |
|
|
11
|
+
| `enableMultiRowSelection` | Table option | `boolean` | `true` | `false` limits the selection to one row and drops group checkboxes. |
|
|
12
|
+
| `showSelectedBackground` | Option | `boolean` | Follows the mode | Whether selected rows take a background tint. |
|
|
13
|
+
| `defaultHighlightedRowId` | Option | `string \| null` | `null` | Row highlighted at mount. |
|
|
14
|
+
| `onHighlightedRowChange` | Callback | `(rowId: string \| null) => void` | – | Fires when the highlight moves. |
|
|
15
|
+
| `SELECT_COLUMN_ID` | Export | `"__select__"` | – | Id of the generated checkbox column. |
|
|
16
|
+
| `getSelectableRowIds` | Export | `(table) => string[]` | – | Ids the header checkbox would select. |
|
|
17
|
+
| `resolveRowSelectionClick` | Export | `(args) => ResolvedRowSelection` | – | The desktop-list click rules, for a custom surface. |
|
|
18
|
+
| `getDisplayedRows` | Export | `(table) => Row[]` | – | The rows currently on screen, paging respected. |
|
|
19
|
+
| `isPagingActive` | Export | `(table) => boolean` | – | Whether a pager is in play. |
|
|
20
|
+
|
|
21
|
+
The highlight lives on the ui store, not in `rowSelection`:
|
|
22
|
+
`useSelector(grid.ui, (state) => state.highlightedRowId)`.
|
|
23
|
+
|
|
24
|
+
## Clicks and context menus
|
|
25
|
+
|
|
26
|
+
All are props of `TMDataGrid.Table`, not hook options.
|
|
27
|
+
|
|
28
|
+
| Name | Type | What it does |
|
|
29
|
+
| --- | --- | --- |
|
|
30
|
+
| `onRowClick` | `(row) => void` | Row click. Adds a pointer cursor. |
|
|
31
|
+
| `onCellClick` | `(args) => void` | Cell click. `args` is `TMDataGridCellEventArgs`. |
|
|
32
|
+
| `onCellDoubleClick` | `(args) => void` | Cell double-click. |
|
|
33
|
+
| `onCellContextMenu` | `(args) => void` | Cell right-click. |
|
|
34
|
+
| `rowContextMenu` | `({ table, row, cell, close }) => ReactNode` | Contents of the row's context menu. `null` for no menu. |
|
|
35
|
+
| `rowContextMenuProps` | `MenuProps` | Passed to the Mantine `Menu` untouched apart from its open state. |
|
|
36
|
+
|
|
37
|
+
`TMDataGridCellEventArgs` is `{ cell, row, column, event }`. The context-menu
|
|
38
|
+
render prop's `cell` is `null` only when a custom cell renderer stopped the
|
|
39
|
+
event. One `Menu` serves the whole body: a closed Mantine `Popover` still runs
|
|
40
|
+
its hooks on every render, and the virtualized body re-renders every scroll
|
|
41
|
+
frame.
|
|
42
|
+
|
|
43
|
+
On touch devices a long press (500 ms) opens the same menu. Mantine sets
|
|
44
|
+
`user-select: none` on the element it hangs a context menu off, so body cell
|
|
45
|
+
text stops being mouse-selectable in a grid that has one.
|
|
46
|
+
|
|
47
|
+
## Styling
|
|
48
|
+
|
|
49
|
+
| Name | Kind | Type | Default | What it does |
|
|
50
|
+
| --- | --- | --- | --- | --- |
|
|
51
|
+
| `rowStyle` | Table prop | `TMDataGridRowStyle \| ((row) => TMDataGridRowStyle)` | – | Inline style for a body row. |
|
|
52
|
+
| `rowClassName` | Table prop | `string \| ((row) => string \| undefined)` | – | Class added after the grid's own. |
|
|
53
|
+
| `striped` | Table prop | `boolean` | `false` | Every second row takes `--dg-row-striped-bg`. |
|
|
54
|
+
| `TMDataGridRowStyle` | Export | type | – | `CSSProperties` or an object of `--*` custom properties. |
|
|
55
|
+
| `--row-bg` | CSS variable | colour | – | The row's own background, composed under hover, selection and range. |
|
|
56
|
+
| `--dg-row-striped-bg` | CSS variable | colour | Themed | The stripe colour. |
|
|
57
|
+
| `--dg-row-selected-bg` | CSS variable | colour | `--mantine-primary-color-light` | Selected row background. |
|
|
58
|
+
| `--dg-row-highlight-bg` | CSS variable | colour | Themed | Highlighted row background. |
|
|
59
|
+
| `--dg-row-height` | CSS variable | length | From `size` | Row height. `meta.rowHeight` is the supported way to change it. |
|
|
60
|
+
|
|
61
|
+
Row data attributes:
|
|
62
|
+
|
|
63
|
+
| Attribute | On |
|
|
64
|
+
| --- | --- |
|
|
65
|
+
| `data-selected` | Selected rows |
|
|
66
|
+
| `data-selected-bg` | Selected rows that also take the background |
|
|
67
|
+
| `data-highlighted` | The highlighted row |
|
|
68
|
+
| `data-grouped` | Group rows |
|
|
69
|
+
| `data-depth` | Every row - the nesting level |
|
|
70
|
+
| `data-context-menu` | The row whose context menu is open |
|
|
71
|
+
| `data-deleted` | Rows marked for deletion under batch editing |
|
|
72
|
+
| `data-row-id` | Every row - its id |
|
|
73
|
+
|
|
74
|
+
## Details
|
|
75
|
+
|
|
76
|
+
| Name | Kind | Type | Default | What it does |
|
|
77
|
+
| --- | --- | --- | --- | --- |
|
|
78
|
+
| `renderDetails` | Option | `({ row, table }) => ReactNode` | – | Contents of the panel. Setting it adds the lane. |
|
|
79
|
+
| `renderDetailsEstHeight` | Option | `number` | `160` | Height the virtualizer assumes for an unmeasured panel. |
|
|
80
|
+
| `initialState.expanded` | Table option | `ExpandedState` | `{}` | Rows open at mount. A `data` slice, so it persists. |
|
|
81
|
+
| `autoResetExpanded` | Table option | `boolean` | `true` | `false` keeps panels open when `data` changes. |
|
|
82
|
+
| `DETAILS_COLUMN_ID` | Export | `"__details__"` | – | Id of the generated chevron column. |
|
|
83
|
+
| `resolveExpandAll` | Export | `(args) => ExpandedState` | – | Expand or collapse every group, or every panel, but not both. |
|
|
84
|
+
| `areAllRowsExpanded` | Export | `(args) => boolean` | – | Whether every row of one target is open. |
|
|
85
|
+
| `data-dg-part="details"` | Data attribute | – | – | The panel element, carrying the row's `data-row-id`. |
|
|
86
|
+
|
|
87
|
+
One `expanded` state opens two unrelated things - a group row into its children,
|
|
88
|
+
a data row into its panel. The controls stay apart: the details header only
|
|
89
|
+
opens panels, "Expand all groups" only unfolds the tree.
|
|
90
|
+
`table.toggleAllRowsExpanded()` is the one that does not distinguish them, which
|
|
91
|
+
is what `resolveExpandAll({ rows, expanded, target, expand })` exists to avoid:
|
|
92
|
+
|
|
93
|
+
```tsx
|
|
94
|
+
table.setExpanded(
|
|
95
|
+
resolveExpandAll({
|
|
96
|
+
rows: table.getPrePaginatedRowModel().flatRows,
|
|
97
|
+
expanded: table.store.state.expanded,
|
|
98
|
+
target: "details",
|
|
99
|
+
expand: true,
|
|
100
|
+
}),
|
|
101
|
+
);
|
|
102
|
+
```
|
|
103
|
+
|
|
104
|
+
## Pinning and numbering
|
|
105
|
+
|
|
106
|
+
| Name | Kind | Type | Default | What it does |
|
|
107
|
+
| --- | --- | --- | --- | --- |
|
|
108
|
+
| `enableRowPinning` | Table option | `boolean \| ((row) => boolean)` | `false` | Whether rows can be pinned. |
|
|
109
|
+
| `initialState.rowPinning` | Table option | `{ top: string[], bottom: string[] }` | empty | Rows pinned at mount. Not persisted. |
|
|
110
|
+
| `enableRowNumbers` | Option | `boolean` | `false` | Adds the row-number gutter, outermost left. |
|
|
111
|
+
| `row.pin` | Row method | `("top" \| "bottom" \| false) => void` | – | Pins or unpins one row. |
|
|
112
|
+
| `row.getIsPinned` | Row method | `() => "top" \| "bottom" \| false` | – | Where a row is pinned. |
|
|
113
|
+
| `row.getCanPin` | Row method | `() => boolean` | – | Whether this row may pin. |
|
|
114
|
+
| `ROW_NUMBER_COLUMN_ID` | Export | `"__rowNumber__"` | – | Id of the generated number gutter. |
|
|
115
|
+
|
|
116
|
+
Lane order, left to right: row number, checkbox, tree, details, your columns,
|
|
117
|
+
edit.
|
package/skills/testing/SKILL.md
CHANGED