@jielga/tmdatagrid 2.1.4 → 2.3.0
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.ts +78 -5
- package/dist/index.js +2194 -1992
- package/dist/index.js.map +1 -1
- package/dist/styles.css +1 -1
- package/docs/cell-selection.md +1 -1
- package/docs/column-layout.md +13 -8
- package/docs/columns.md +59 -3
- package/docs/components.md +1 -0
- package/docs/export.md +2 -2
- package/docs/filtering.md +108 -15
- package/docs/getting-started.md +40 -0
- package/docs/grouping.md +9 -6
- package/docs/loading-and-empty.md +29 -9
- package/docs/localization.md +130 -3
- package/docs/menu.md +1 -1
- package/docs/pagination.md +26 -7
- package/docs/persistence.md +101 -2
- package/docs/row-details.md +41 -4
- package/docs/row-interaction.md +2 -2
- package/docs/row-selection.md +6 -7
- package/docs/row-styling.md +17 -0
- package/docs/scrolling.md +1 -1
- package/docs/server-side.md +3 -1
- package/docs/testing.md +18 -0
- package/docs/use-tm-data-grid.md +75 -36
- package/package.json +1 -1
- package/skills/appearance/SKILL.md +6 -4
- package/skills/appearance/references/labels.md +126 -0
- package/skills/cell-selection/SKILL.md +2 -2
- package/skills/columns/SKILL.md +44 -43
- package/skills/columns/references/columns-api.md +16 -1
- package/skills/data/SKILL.md +77 -50
- package/skills/editing/SKILL.md +1 -1
- package/skills/filtering/SKILL.md +94 -60
- package/skills/filtering/references/custom-filters.md +118 -0
- package/skills/getting-started/SKILL.md +37 -2
- package/skills/grouping/SKILL.md +16 -9
- package/skills/migrating-to-2/SKILL.md +1 -1
- package/skills/options/SKILL.md +206 -55
- package/skills/rows/SKILL.md +70 -39
- package/skills/server-side/SKILL.md +1 -1
- package/skills/testing/SKILL.md +12 -1
- package/skills/testing-components/SKILL.md +1 -1
- package/skills/testing-editing/SKILL.md +1 -1
- package/src/components/TMDataGridFilterPills.module.css +9 -7
- package/src/components/TMDataGridTable.module.css +15 -6
- package/src/components/TMDataGridTable.tsx +253 -41
- package/src/components/sticky.module.css +27 -7
- package/src/core/autosize.ts +19 -7
- package/src/core/cellRange.ts +11 -2
- package/src/core/colSpan.ts +78 -0
- package/src/core/columnUtils.ts +7 -0
- package/src/core/filterControls.ts +8 -0
- package/src/core/filterOperators.ts +29 -1
- package/src/core/persistence.ts +322 -26
- package/src/index.ts +5 -0
- package/src/useTMDataGrid.tsx +133 -14
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
# Loading and empty states
|
|
2
2
|
|
|
3
|
-
A grid can have nothing to show for
|
|
3
|
+
A grid can have nothing to show for five different reasons, and the body says
|
|
4
4
|
which one it is: still fetching, emptied by a filter, or holding no data.
|
|
5
5
|
|
|
6
6
|
```demo
|
|
@@ -18,9 +18,29 @@ An empty body shows exactly one thing, decided in this order:
|
|
|
18
18
|
2. **Entry rows** - an open entry row from `edit.addRow()`: the entry block
|
|
19
19
|
only, with no message beside the form.
|
|
20
20
|
3. **`renderEmptyState`** - your node, centred where the message would be.
|
|
21
|
-
4. **Filtered-empty** - a filter
|
|
22
|
-
`labels.noResults` ("No rows
|
|
23
|
-
|
|
21
|
+
4. **Filtered-empty** - a column filter is active (`isFilterActive`) or the
|
|
22
|
+
quick search is not blank: a search icon and `labels.noResults` ("No rows
|
|
23
|
+
match your filters").
|
|
24
|
+
5. **Truly-empty** - no column filter is active and the quick search is blank:
|
|
25
|
+
`labels.noRows` ("No rows to show").
|
|
26
|
+
|
|
27
|
+
"Empty" means no displayed row and no pinned row: the current page under
|
|
28
|
+
pagination, otherwise every filtered row. States 4 and 5 are decided by the
|
|
29
|
+
filter state alone, so an empty `data` array shows `noResults` while a filter is
|
|
30
|
+
active. A half-typed filter, such as `{ operator: "contains", value: "" }`, is
|
|
31
|
+
not active, so it does not count.
|
|
32
|
+
|
|
33
|
+
## While data loads
|
|
34
|
+
|
|
35
|
+
The loader shows only while `meta.loading` is `true` and the view is empty. It
|
|
36
|
+
is the only "no data yet" signal the grid has, so set `meta.loading` during the
|
|
37
|
+
first fetch as well; without it the empty message shows until the rows arrive.
|
|
38
|
+
|
|
39
|
+
`renderEmptyState` is called only once `meta.loading` is not `true`. During a
|
|
40
|
+
refetch that returns no rows, the loader mounts when `loading` turns `true`,
|
|
41
|
+
`renderEmptyState` mounts when it turns `false`, and it unmounts again on the
|
|
42
|
+
next refetch; the two branches never render together. Rows on screen stay on
|
|
43
|
+
screen until `data` changes, whatever `loading` says.
|
|
24
44
|
|
|
25
45
|
## Replacing the message
|
|
26
46
|
|
|
@@ -70,8 +90,8 @@ typically after `Spacer`.
|
|
|
70
90
|
|
|
71
91
|
`TMDataGrid.SummaryCount` shows visible rows out of the total. The total is
|
|
72
92
|
`meta.totalRowCount` when you provide it, and the pre-filtered row count
|
|
73
|
-
otherwise. A [server-side](/docs/server-side) grid
|
|
74
|
-
|
|
93
|
+
otherwise. A [server-side](/docs/server-side) grid holds one page, so without
|
|
94
|
+
`meta.totalRowCount` it shows the shown count alone, with no total.
|
|
75
95
|
|
|
76
96
|
```tsx
|
|
77
97
|
<TMDataGrid.SummaryCount>
|
|
@@ -83,10 +103,10 @@ client only holds one page.
|
|
|
83
103
|
|
|
84
104
|
| Name | Kind | Type | Default | What it does |
|
|
85
105
|
| --- | --- | --- | --- | --- |
|
|
86
|
-
| `meta.loading` | Option | `boolean` | `false` | A fetch is in flight.
|
|
106
|
+
| `meta.loading` | Option | `boolean` | `false` | A fetch is in flight. While `true` and the view is empty, the loader replaces every empty message and `renderEmptyState` is not called. |
|
|
87
107
|
| `meta.noResultsLabel` | Option | `string` | `labels.noResults` | The filtered-empty message, without a render prop. |
|
|
88
|
-
| `meta.totalRowCount` | Option | `number` | Pre-filtered count | The total `SummaryCount` reports. |
|
|
89
|
-
| `renderEmptyState` | Table prop | `({ hasActiveFilters, table }) => ReactNode` | – | Replaces both built-in empty messages. |
|
|
108
|
+
| `meta.totalRowCount` | Option | `number` | Pre-filtered count; none on a server-driven grid | The total `SummaryCount` reports. |
|
|
109
|
+
| `renderEmptyState` | Table prop | `({ hasActiveFilters, table }) => ReactNode` | – | Replaces both built-in empty messages. `hasActiveFilters` is `true` when a column filter is active (`isFilterActive`) or the quick search is not blank. |
|
|
90
110
|
| `TMDataGrid.LoadingIndicator` | Component | – | – | Spinner while `meta.loading`, for when the body has rows. |
|
|
91
111
|
| `TMDataGrid.SummaryCount` | Component | `children` replaces the text | – | Visible rows out of total. |
|
|
92
112
|
| `labels.noRows` · `labels.noResults` | Labels | `string` | English defaults | The two built-in messages. See [Localization](/docs/localization). |
|
package/docs/localization.md
CHANGED
|
@@ -59,12 +59,139 @@ context as `useTMDataGridContext().labels`, so a
|
|
|
59
59
|
[toolbar component of your own](/docs/toolbar) uses the same strings as the
|
|
60
60
|
built-in parts, in whatever language is configured.
|
|
61
61
|
|
|
62
|
-
`mergeLabels(
|
|
63
|
-
|
|
62
|
+
`mergeLabels(override)` is the merge itself: it folds a partial override over
|
|
63
|
+
the English defaults, `operators` included, and returns the full dictionary.
|
|
64
|
+
Called without an argument, it returns `TMDATAGRID_LABELS_EN` itself.
|
|
64
65
|
|
|
65
66
|
`meta.noResultsLabel` remains as a per-instance override of
|
|
66
67
|
`labels.noResults`.
|
|
67
68
|
|
|
69
|
+
## Label keys
|
|
70
|
+
|
|
71
|
+
Every key of `TMDataGridLabels`, with its English default and where the grid
|
|
72
|
+
shows it; a function label shows its template:
|
|
73
|
+
|
|
74
|
+
| Key | Default | Where it shows |
|
|
75
|
+
| --- | --- | --- |
|
|
76
|
+
| `operators.contains` | `contains` | The operator select of `TMDataGrid.FilterPanel`, the text of a filter pill, and the operator button of a header filter. |
|
|
77
|
+
| `operators.equals` | `equals` | The operator select of `TMDataGrid.FilterPanel`, the text of a filter pill, and the operator button of a header filter. |
|
|
78
|
+
| `operators.notEquals` | `does not equal` | The operator select of `TMDataGrid.FilterPanel`, the text of a filter pill, and the operator button of a header filter. |
|
|
79
|
+
| `operators.startsWith` | `starts with` | The operator select of `TMDataGrid.FilterPanel`, the text of a filter pill, and the operator button of a header filter. |
|
|
80
|
+
| `operators.endsWith` | `ends with` | The operator select of `TMDataGrid.FilterPanel`, the text of a filter pill, and the operator button of a header filter. |
|
|
81
|
+
| `operators.greaterThan` | `is greater than` | The operator select of `TMDataGrid.FilterPanel`, the text of a filter pill, and the operator button of a header filter. |
|
|
82
|
+
| `operators.greaterThanOrEqual` | `is greater than or equal to` | The operator select of `TMDataGrid.FilterPanel`, the text of a filter pill, and the operator button of a header filter. |
|
|
83
|
+
| `operators.lessThan` | `is less than` | The operator select of `TMDataGrid.FilterPanel`, the text of a filter pill, and the operator button of a header filter. |
|
|
84
|
+
| `operators.lessThanOrEqual` | `is less than or equal to` | The operator select of `TMDataGrid.FilterPanel`, the text of a filter pill, and the operator button of a header filter. |
|
|
85
|
+
| `operators.between` | `is between` | The operator select of `TMDataGrid.FilterPanel`, the text of a filter pill, and the operator button of a header filter. |
|
|
86
|
+
| `operators.before` | `is before` | The operator select of `TMDataGrid.FilterPanel`, the text of a filter pill, and the operator button of a header filter. |
|
|
87
|
+
| `operators.after` | `is after` | The operator select of `TMDataGrid.FilterPanel`, the text of a filter pill, and the operator button of a header filter. |
|
|
88
|
+
| `operators.onOrBefore` | `is on or before` | The operator select of `TMDataGrid.FilterPanel`, the text of a filter pill, and the operator button of a header filter. |
|
|
89
|
+
| `operators.onOrAfter` | `is on or after` | The operator select of `TMDataGrid.FilterPanel`, the text of a filter pill, and the operator button of a header filter. |
|
|
90
|
+
| `operators.isAnyOf` | `is any of` | The operator select of `TMDataGrid.FilterPanel`, the text of a filter pill, and the operator button of a header filter. |
|
|
91
|
+
| `operators.isNoneOf` | `is none of` | The operator select of `TMDataGrid.FilterPanel`, the text of a filter pill, and the operator button of a header filter. |
|
|
92
|
+
| `operators.isEmpty` | `is empty` | The operator select of `TMDataGrid.FilterPanel`, the text of a filter pill, and the operator button of a header filter. |
|
|
93
|
+
| `operators.isNotEmpty` | `is not empty` | The operator select of `TMDataGrid.FilterPanel`, the text of a filter pill, and the operator button of a header filter. |
|
|
94
|
+
| `filters` | `Filters` | Tooltip and `aria-label` of `TMDataGrid.FilterButton`, the title and `aria-label` of the filter popup and sidebar, and the `aria-label` of `TMDataGrid.FilterPanel`. |
|
|
95
|
+
| `searchPlaceholder` | `Search` | Placeholder of `TMDataGrid.Search`. Its `placeholder` prop wins. |
|
|
96
|
+
| `searchLabel` | `Search rows` | `aria-label` of the `TMDataGrid.Search` input. |
|
|
97
|
+
| `clearSearch` | `Clear search` | `aria-label` of the clear button in `TMDataGrid.Search`. |
|
|
98
|
+
| `menuButton` | `Menu` | Tooltip and `aria-label` of the `TMDataGrid.Menu` trigger. Its `label` prop wins. |
|
|
99
|
+
| `manageColumns` | `Manage columns` | Column menu: the submenu that lists the columns. |
|
|
100
|
+
| `columnsSearchPlaceholder` | `Search` | Search box of `TMDataGrid.ColumnsPanel`, `TMDataGrid.Menu.Columns` and the export column picker. |
|
|
101
|
+
| `columnsNoMatch` | `` `No columns match “${search}”` `` | The same three lists, when the search matches no column. |
|
|
102
|
+
| `columnsShowHideAll` | `Show/Hide All` | `TMDataGrid.ColumnsPanel` and `TMDataGrid.Menu.ShowHideAll`. |
|
|
103
|
+
| `columnsReset` | `Reset layout` | `TMDataGrid.ColumnsPanel` and `TMDataGrid.Menu.ResetLayout`. |
|
|
104
|
+
| `columnsResetHint` | `Resets column visibility, order, widths, pinning and grouping` | Tooltip of the reset button in `TMDataGrid.ColumnsPanel`. |
|
|
105
|
+
| `rowNumberColumnLabel` | `Row number` | `meta.label` of the generated row-number lane. |
|
|
106
|
+
| `noRows` | `No rows to show` | Body, when the view is empty, no column filter is active (`isFilterActive`) and the quick search is blank. |
|
|
107
|
+
| `filterColumn` | `Column` | Label of the column field in `TMDataGrid.FilterPanel`. |
|
|
108
|
+
| `filterOperator` | `Operator` | Label of the operator field in `TMDataGrid.FilterPanel`. |
|
|
109
|
+
| `filterValue` | `Value` | Label of the value field in `TMDataGrid.FilterPanel`. |
|
|
110
|
+
| `filterValuePlaceholder` | `Filter value` | Placeholder of the filter value input. |
|
|
111
|
+
| `filterFrom` | `From` | The lower bound of a `between` filter: its input, or its slider thumb. |
|
|
112
|
+
| `filterTo` | `To` | The upper bound of a `between` filter: its input, or its slider thumb. |
|
|
113
|
+
| `filterAll` | `All` | The no-filter segment of the tri-state filter. |
|
|
114
|
+
| `booleanTrue` | `Yes` | The `true` choice of a boolean filter value control and of the tri-state filter. |
|
|
115
|
+
| `booleanFalse` | `No` | The `false` choice of a boolean filter value control and of the tri-state filter. |
|
|
116
|
+
| `addFilter` | `Add filter` | Button in `TMDataGrid.FilterPanel`. |
|
|
117
|
+
| `clearAllFilters` | `Clear all` | Button in `TMDataGrid.FilterPanel` and in `TMDataGrid.FilterPills`. |
|
|
118
|
+
| `closeFilters` | `Close filters` | `aria-label` of the close button of the filter popup and sidebar. |
|
|
119
|
+
| `removeFilter` | `Remove filter` | `aria-label` of the remove button on a filter row in `TMDataGrid.FilterPanel`. |
|
|
120
|
+
| `filterOperatorFor` | `` `${column} filter operator` `` | `aria-label` of the operator button of a header filter. |
|
|
121
|
+
| `activeFilters` | `Active filters` | `aria-label` of the `TMDataGrid.FilterPills` group. |
|
|
122
|
+
| `clearFilter` | `` `Clear ${column} filter` `` | `aria-label` of the remove button on a filter pill. |
|
|
123
|
+
| `sortAsc` | `Sort ascending` | Column menu item. |
|
|
124
|
+
| `sortDesc` | `Sort descending` | Column menu item. |
|
|
125
|
+
| `filterMenuItem` | `Filter` | Column menu item. |
|
|
126
|
+
| `groupBy` | `` `Group by ${column}` `` | Column menu item. |
|
|
127
|
+
| `ungroup` | `` `Ungroup ${column}` `` | Column menu item. |
|
|
128
|
+
| `expandAllGroups` | `Expand all groups` | Column menu item. |
|
|
129
|
+
| `collapseAllGroups` | `Collapse all groups` | Column menu item. |
|
|
130
|
+
| `pinLeft` | `Pin to left` | Column menu item. |
|
|
131
|
+
| `pinRight` | `Pin to right` | Column menu item. |
|
|
132
|
+
| `unpin` | `Unpin` | Column menu item. |
|
|
133
|
+
| `moveLeft` | `Move left` | Column menu item. |
|
|
134
|
+
| `moveRight` | `Move right` | Column menu item. |
|
|
135
|
+
| `autosizeColumn` | `Autosize column` | Column menu item. |
|
|
136
|
+
| `hideColumn` | `Hide column` | Column menu item. |
|
|
137
|
+
| `filterOn` | `` `Filter on ${column}` `` | `aria-label` of the header filter button, of a header filter cell, and of the value control in it. |
|
|
138
|
+
| `sortColumn` | `` `Sort ${column}` `` | `aria-label` of the header sort button. |
|
|
139
|
+
| `columnMenu` | `` `${column} column menu` `` | `aria-label` of the column menu trigger. |
|
|
140
|
+
| `rowsPerPage` | `Rows per page:` | `TMDataGrid.Footer`: the text before the page size select. |
|
|
141
|
+
| `pageRange` | `` `${from}–${to} of ${total}` `` | `TMDataGrid.Footer`: the range of rows on the page. |
|
|
142
|
+
| `pageNumber` | `` `Page ${page} of ${pageCount}` ``, or `` `Page ${page}` `` when `pageCount` is `-1` | `TMDataGrid.Footer`: the page number. |
|
|
143
|
+
| `groupedAllRows` | `` `Grouped · all ${total} rows` `` | `TMDataGrid.Footer`: in place of the range and the page number while the rows are grouped. |
|
|
144
|
+
| `pagingSuspendedHint` | `Paging is off while the rows are grouped, and every row is shown. Ungroup to page again.` | `TMDataGrid.Footer`: tooltip of the pager while the rows are grouped. |
|
|
145
|
+
| `previousPage` | `Previous page` | `TMDataGrid.Footer`: `aria-label` of the previous page button. |
|
|
146
|
+
| `nextPage` | `Next page` | `TMDataGrid.Footer`: `aria-label` of the next page button. |
|
|
147
|
+
| `noResults` | `No rows match your filters` | Body, when the view is empty and a column filter is active (`isFilterActive`) or the quick search is not blank. `meta.noResultsLabel` overrides it. |
|
|
148
|
+
| `loading` | `Loading` | `aria-label` of the body loader, of `TMDataGrid.LoadingIndicator`, and of the edit lane spinner while a row saves. |
|
|
149
|
+
| `editCell` | `` `Edit ${column}` `` | `aria-label` of an open cell editor. |
|
|
150
|
+
| `confirmEdit` | `Save` | `aria-label` of the ✓ button beside a cell editor. |
|
|
151
|
+
| `cancelEdit` | `Cancel` | `aria-label` of the ✕ button beside a cell editor. |
|
|
152
|
+
| `editColumnLabel` | `Edit` | `meta.label` of the generated edit lane. |
|
|
153
|
+
| `editRow` | `Edit row` | Edit lane: tooltip and `aria-label` of the pencil button. |
|
|
154
|
+
| `saveRow` | `Save row` | Edit lane: tooltip and `aria-label` of the ✓ button while a row edit is open. |
|
|
155
|
+
| `cancelRowEdit` | `Cancel edit` | Edit lane: tooltip and `aria-label` of the ✕ button while a row edit is open. |
|
|
156
|
+
| `editRowErrors` | `Fix the marked cells` | Edit lane: tooltip of the save button when field errors block the row and the row has no message of its own. |
|
|
157
|
+
| `saveAllEdits` | `"Save 1 row"` when `rows` is 1, else `` `Save ${rows} rows` `` | `TMDataGrid.DraftActions`: the save button. |
|
|
158
|
+
| `discardAllEdits` | `Discard` | `TMDataGrid.DraftActions`: the discard button. |
|
|
159
|
+
| `editRowsStillOpen` | `"1 row still being edited"` when `rows` is 1, else `` `${rows} rows still being edited` `` | `TMDataGrid.DraftActions`: the note shown while rows are still open in an edit. |
|
|
160
|
+
| `confirmNewRow` | `Add row` | Edit lane: tooltip and `aria-label` of the ✓ button on the entry row. |
|
|
161
|
+
| `discardNewRow` | `Discard new row` | Edit lane: tooltip and `aria-label` of the ✕ button on the entry row. |
|
|
162
|
+
| `deleteRow` | `Delete row` | Edit lane: tooltip and `aria-label` of the trash button. |
|
|
163
|
+
| `restoreRow` | `Restore row` | Edit lane: tooltip and `aria-label` of the undo button on a row marked for deletion. |
|
|
164
|
+
| `revertRow` | `Revert changes` | Edit lane: tooltip and `aria-label` of the undo button on a row with a draft. |
|
|
165
|
+
| `rowStateNew` | `New row` | Edit lane: the row-state marker of a confirmed entry row. |
|
|
166
|
+
| `rowStateEdited` | `Edited row` | Edit lane: the row-state marker of a row with a draft. |
|
|
167
|
+
| `rowStateDeleted` | `Marked for deletion` | Edit lane: the row-state marker of a row marked for deletion. |
|
|
168
|
+
| `cellCount` | `"1 cell"` when `count` is 1, else `` `${count} cells` `` | Cell-selection context menu: its heading. |
|
|
169
|
+
| `copy` | `Copy` | Cell-selection context menu item. |
|
|
170
|
+
| `exportCells` | `Export cells` | Cell-selection context menu item. |
|
|
171
|
+
| `includeHeaders` | `Include headers` | Cell-selection context menu: the checkbox. |
|
|
172
|
+
| `exportAll` | `Export all rows` | `TMDataGrid.Menu.Export`. Its `label` prop wins. |
|
|
173
|
+
| `exportSelected` | `"Export 1 selected row"` when `count` is 1, else `` `Export ${count} selected rows` `` | `TMDataGrid.Menu.ExportSelected`. Its `label` prop wins. |
|
|
174
|
+
| `exportPickerTitle` | `` `Export as ${format}` `` | Export column picker: the title. `format` is the file extension in upper case. |
|
|
175
|
+
| `exportPickerHint` | `"Select the columns to export"` when `selected` is `null`, `"Select the columns to export for the selected row"` when it is 1, else `` `Select the columns to export for the ${selected} selected rows` `` | Export column picker: the line under the title. |
|
|
176
|
+
| `exportPickerConfirm` | `Export` | Export column picker: the confirm button. |
|
|
177
|
+
| `exportPickerCancel` | `Cancel` | Export column picker: the cancel button. |
|
|
178
|
+
| `exportPickerSelectAll` | `Select all` | Export column picker: the select-all checkbox over the list. |
|
|
179
|
+
| `exportPickerCount` | `` `${checked} of ${total}` `` | Export column picker: the count beside the select-all checkbox. |
|
|
180
|
+
| `exportPickerHidden` | `Hidden` | Export column picker: the mark on a column the grid hides. |
|
|
181
|
+
| `selectColumnLabel` | `Checkbox selection` | `meta.label` of the generated checkbox lane. |
|
|
182
|
+
| `selectAllRows` | `Select all rows` | `aria-label` of the header checkbox. |
|
|
183
|
+
| `selectRow` | `Select row` | `aria-label` of a row checkbox. |
|
|
184
|
+
| `selectGroup` | `Select group` | `aria-label` of a group row checkbox. |
|
|
185
|
+
| `detailsColumnLabel` | `Details` | `meta.label` of the generated details lane. |
|
|
186
|
+
| `showDetails` | `Show details` | `aria-label` of a collapsed row's details toggle. |
|
|
187
|
+
| `hideDetails` | `Hide details` | `aria-label` of an expanded row's details toggle. |
|
|
188
|
+
| `expandAllDetails` | `Expand all details` | `aria-label` of the details lane's header toggle while some row is collapsed. |
|
|
189
|
+
| `collapseAllDetails` | `Collapse all details` | `aria-label` of the details lane's header toggle while every row is expanded. |
|
|
190
|
+
| `groupColumnLabel` | `Group` | `meta.label` of the generated tree lane, and its header text while nothing is grouped. |
|
|
191
|
+
| `blankGroupValue` | `(Blank)` | Group row text for an empty group key. |
|
|
192
|
+
| `expandGroup` | `` `Expand ${label}` `` | `aria-label` of a collapsed group row's toggle. |
|
|
193
|
+
| `collapseGroup` | `` `Collapse ${label}` `` | `aria-label` of an expanded group row's toggle. |
|
|
194
|
+
|
|
68
195
|
## Reference
|
|
69
196
|
|
|
70
197
|
| Name | Kind | Type | Default | What it does |
|
|
@@ -75,5 +202,5 @@ dictionaries before passing one in.
|
|
|
75
202
|
| `TMDATAGRID_LABELS_SV` | Export | `TMDataGridLabels` | – | A complete Swedish dictionary. |
|
|
76
203
|
| `TMDataGridLabels` | Export | type | – | The full dictionary. What a new translation must cover. |
|
|
77
204
|
| `TMDataGridLabelsOverride` | Export | type | – | A partial dictionary. |
|
|
78
|
-
| `mergeLabels` | Export | `(
|
|
205
|
+
| `mergeLabels` | Export | `(override?: TMDataGridLabelsOverride) => TMDataGridLabels` | – | Folds a partial override over the English defaults. Returns `TMDATAGRID_LABELS_EN` itself without an argument. |
|
|
79
206
|
| `meta.noResultsLabel` | Option | `string` | `labels.noResults` | Per-instance override of the filtered-empty message. |
|
package/docs/menu.md
CHANGED
|
@@ -54,7 +54,7 @@ The pieces it is made of are exported for menus that want only some of them.
|
|
|
54
54
|
| `TMDataGrid.Menu.Columns` | `Menu.Search`, the toggles, a divider, show/hide all and reset layout. By default the search box shows from six columns; `searchable` shows it always and `searchable={false}` never. |
|
|
55
55
|
| `TMDataGrid.Menu.ColumnToggles` | One item per hideable column, with a checkbox that shows both states. `search` narrows the list to the labels containing it. |
|
|
56
56
|
| `TMDataGrid.Menu.ShowHideAll` | One checkbox item over the same list. An indeterminate box marks a partial state, and a click then shows all. |
|
|
57
|
-
| `TMDataGrid.Menu.ResetLayout` | One item calling `resetSettings()`: visibility, order, pinning and
|
|
57
|
+
| `TMDataGrid.Menu.ResetLayout` | One item calling `resetSettings()`: visibility, order, pinning, widths and grouping. |
|
|
58
58
|
|
|
59
59
|
Each of them needs a Mantine `Menu` around it and reads the grid from context, so they work in any Mantine menu rendered inside `TMDataGrid`, not only in the burger:
|
|
60
60
|
|
package/docs/pagination.md
CHANGED
|
@@ -21,6 +21,18 @@ its pager. Initial page size is 25, configurable through
|
|
|
21
21
|
const grid = useTMDataGrid({ data, columns, enablePagination: true });
|
|
22
22
|
```
|
|
23
23
|
|
|
24
|
+
The Footer renders a rows-per-page select, the range (`1–25 of 300`, from
|
|
25
|
+
`table.getRowCount()`) and previous and next buttons. The select offers
|
|
26
|
+
`pageSizeOptions`, by default `[10, 25, 50, 100]`, with the current size folded
|
|
27
|
+
in when it is not in the list. Pass a module-scope array: the select is
|
|
28
|
+
memoized on it, and an inline literal remounts it on every render.
|
|
29
|
+
|
|
30
|
+
```tsx
|
|
31
|
+
const PAGE_SIZES = [10, 20, 50];
|
|
32
|
+
|
|
33
|
+
<TMDataGrid.Footer pageSizeOptions={PAGE_SIZES} />
|
|
34
|
+
```
|
|
35
|
+
|
|
24
36
|
**Manual pagination** - the server pages, and the grid stops.
|
|
25
37
|
`manualPagination: true` implies `enablePagination`, so no extra flag is
|
|
26
38
|
needed. See [Server-side data](/docs/server-side).
|
|
@@ -102,15 +114,20 @@ It reads `pageCount`, so a grid declaring `pageCount: -1` shows "Page 3" alone.
|
|
|
102
114
|
and `isPagingActive`. `actions` carries `setPageIndex`, `setPageSize`,
|
|
103
115
|
`previousPage`, `nextPage`, `firstPage` and `lastPage`.
|
|
104
116
|
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
117
|
+
Outside the Footer,
|
|
118
|
+
`getTMDataGridPaginationApi(table, isPagingActive(table, grid.features))`
|
|
119
|
+
returns the same `{ state, actions }`, for a pager that lives elsewhere on the
|
|
120
|
+
page. Without the second argument `state.isPagingActive` is `true`, also while
|
|
121
|
+
the rows are grouped. `Controls` is not included: those components are bound to
|
|
122
|
+
the grid's context and work only inside the slot.
|
|
109
123
|
|
|
110
124
|
## Grouping
|
|
111
125
|
|
|
112
126
|
While a column is grouped the pager greys itself out and the range is replaced
|
|
113
|
-
with `Grouped · all N rows`.
|
|
127
|
+
with `Grouped · all N rows`. The default footer also carries
|
|
128
|
+
`data-paging-suspended` on its bar and shows `labels.pagingSuspendedHint` as a
|
|
129
|
+
tooltip; a footer with `renderPagination` has neither. The body shows every filtered
|
|
130
|
+
row. There is no option to keep the built-in pager active while grouped. See
|
|
114
131
|
[Grouping](/docs/grouping#grouping-and-pagination).
|
|
115
132
|
|
|
116
133
|
A custom pager can grey itself out the same way:
|
|
@@ -134,11 +151,13 @@ paging is switched on at all. The two differ while a grouping is active.
|
|
|
134
151
|
| `enablePagination` | Option | `boolean` | `false` | Client-side paging and the Footer's pager. Grid-defined. |
|
|
135
152
|
| `manualPagination` | Table option | `boolean` | `false` | The server pages. Implies `enablePagination`. |
|
|
136
153
|
| `rowCount` | Table option | `number` | – | The true total, required under `manualPagination`. |
|
|
137
|
-
| `initialState.pagination` | Table option | `{ pageIndex, pageSize }` | `{ 0, 25 }` | Where paging starts. A data slice, so it persists. |
|
|
154
|
+
| `initialState.pagination` | Table option | `{ pageIndex, pageSize }` | `{ pageIndex: 0, pageSize: 25 }` | Where paging starts. A data slice, so it persists. |
|
|
138
155
|
| `onPaginationChange` | Table option | `OnChangeFn` | – | Controls the pagination state. |
|
|
139
156
|
| `resetPageOnQueryChange` | Option | `boolean` | `true` | Back to page 1 when a filter, the quick search, the sort or the grouping changes. `false` keeps the page. See [Server-side data](/docs/server-side#the-page-index). |
|
|
140
157
|
| `TMDataGrid.Footer` | Component | – | – | The footer bar. Renders nothing when paging is off. |
|
|
158
|
+
| `Footer` `pageSizeOptions` | Prop | `ReadonlyArray<number>` | `[10, 25, 50, 100]` | The rows-per-page choices. Keep the array referentially stable. |
|
|
141
159
|
| `Footer` `renderPagination` | Slot | `({ state, actions, Controls }) => ReactNode` | Built-in pager | Replaces the pager, and hands over its pieces. |
|
|
142
|
-
| `
|
|
160
|
+
| `data-paging-suspended` | Data attribute | – | – | On the default footer bar while grouping suspends paging. |
|
|
161
|
+
| `getTMDataGridPaginationApi` | Export | `(table, isPaging?) => { state, actions }` | `isPaging`: `true` | The pager API, outside the Footer. Pass `isPagingActive(table, features)` as `isPaging`. |
|
|
143
162
|
| `TMDataGridPaginationState` · `TMDataGridPaginationActions` · `TMDataGridPaginationControls` | Exports | types | – | The three parts of the slot's argument. |
|
|
144
163
|
| `isPagingActive` | Export | `(table, features) => boolean` | – | Whether the pager is slicing anything right now. |
|
package/docs/persistence.md
CHANGED
|
@@ -6,7 +6,8 @@ return to the grid as they left it.
|
|
|
6
6
|
State is split across **two keys**: `settingsKey` for the column layout, which
|
|
7
7
|
stays valid indefinitely, and `dataKey` for filters, sorting and pagination,
|
|
8
8
|
which go stale as the data underneath them changes. Either can be cleared
|
|
9
|
-
without touching the other.
|
|
9
|
+
without touching the other. A third key, `urlKey`, keeps data slices in the
|
|
10
|
+
page URL instead, as a [deep link](#deep-links).
|
|
10
11
|
|
|
11
12
|
```tsx
|
|
12
13
|
// Module scope: the object is a dependency of the write subscription.
|
|
@@ -32,6 +33,7 @@ extraSources: data/employeeColumns.tsx
|
|
|
32
33
|
| Group | Slices | Lifetime |
|
|
33
34
|
| --- | --- | --- |
|
|
34
35
|
| `dataKey` | `columnFilters`, `globalFilter`, `sorting`, `pagination`, `expanded` | As long as the data means the same thing |
|
|
36
|
+
| `urlKey` | The data slices. A slice listed here is taken out of `dataKey` | As long as the link is opened. See [Deep links](#deep-links) |
|
|
35
37
|
| `settingsKey` | `columnVisibility`, `columnSizing`, `columnOrder`, `columnPinning`, `grouping` | Indefinite. This is the user's layout |
|
|
36
38
|
|
|
37
39
|
`DATA_STATE_SLICES` and `SETTINGS_STATE_SLICES` are exported with the same
|
|
@@ -57,6 +59,99 @@ const persist = {
|
|
|
57
59
|
Only the selected slices are read back, so a payload written before you narrowed
|
|
58
60
|
the selection cannot reintroduce slices you have since opted out of.
|
|
59
61
|
|
|
62
|
+
## Deep links
|
|
63
|
+
|
|
64
|
+
`urlKey` keeps data slices in one URL search param, so a link to the page opens
|
|
65
|
+
the grid on the same filters. The string is the param name, and the slices
|
|
66
|
+
follow the same rules as `dataKey`: a bare key takes every data slice, a tuple a
|
|
67
|
+
subset. A slice lives in one group, so a slice listed under `urlKey` is taken
|
|
68
|
+
out of `dataKey`:
|
|
69
|
+
|
|
70
|
+
```tsx
|
|
71
|
+
const persist = {
|
|
72
|
+
settingsKey: "employees.settings",
|
|
73
|
+
// Sorting is remembered per browser; the filters travel in the link.
|
|
74
|
+
dataKey: ["employees.data", ["sorting"]],
|
|
75
|
+
urlKey: ["employees", ["columnFilters", "globalFilter"]],
|
|
76
|
+
} satisfies TMDataGridPersistence;
|
|
77
|
+
```
|
|
78
|
+
|
|
79
|
+
```demo
|
|
80
|
+
file: data/DeepLinks.tsx
|
|
81
|
+
hint: Filter a column, then copy the address bar into a new tab. The Location filter stays out of the link.
|
|
82
|
+
extraSources: data/employeeColumns.tsx
|
|
83
|
+
```
|
|
84
|
+
|
|
85
|
+
The param carries only the slices whose value differs from the initial state,
|
|
86
|
+
`initialState` merged over the grid defaults, and only the column filters that
|
|
87
|
+
are active. When nothing differs, the param is removed. A link without the
|
|
88
|
+
param, or without a slice, opens on the initial state; a URL slice never falls
|
|
89
|
+
back to storage.
|
|
90
|
+
|
|
91
|
+
Writes use `history.replaceState`, so a filter change never adds a history
|
|
92
|
+
entry. Only the grid's own param changes; the path, the hash, other params and
|
|
93
|
+
`history.state` are kept. Two grids on one page use two keys.
|
|
94
|
+
|
|
95
|
+
The URL payload carries no version stamp, because a bookmarked link has to
|
|
96
|
+
survive a release. The shape guards and the realignment against existing
|
|
97
|
+
columns apply as they do to storage, and so do `serialize` and `deserialize`.
|
|
98
|
+
|
|
99
|
+
Note that a bare `dataKey` hands the URL slices over silently, while a
|
|
100
|
+
`dataKey` tuple that names a slice `urlKey` also lists is reported with
|
|
101
|
+
`console.error` on mount; `urlKey` handles the slice either way.
|
|
102
|
+
|
|
103
|
+
### Keeping a column out of the link
|
|
104
|
+
|
|
105
|
+
Set `meta.filter.url` to `false` on a column whose filter should not travel
|
|
106
|
+
with the link:
|
|
107
|
+
|
|
108
|
+
```tsx
|
|
109
|
+
columnHelper.accessor("owner", {
|
|
110
|
+
header: "Owner",
|
|
111
|
+
meta: { filter: { url: false } },
|
|
112
|
+
});
|
|
113
|
+
```
|
|
114
|
+
|
|
115
|
+
The column's filter is then not persisted anywhere. A filter on it in
|
|
116
|
+
`initialState` still applies when a link is opened. The flag has no effect
|
|
117
|
+
unless `urlKey` carries `columnFilters`.
|
|
118
|
+
|
|
119
|
+
### Routers that own the URL
|
|
120
|
+
|
|
121
|
+
`urlStorage` replaces the default read and write of the param, for a router
|
|
122
|
+
that validates its search params and would not see a `replaceState` call.
|
|
123
|
+
`get` returns the param's string or `null`; `set` receives the string, or
|
|
124
|
+
`null` to remove the param. Keep `persist` referentially stable here too:
|
|
125
|
+
react-router rebuilds `setSearchParams` on every URL change, so read it
|
|
126
|
+
through a ref rather than listing it as a dependency:
|
|
127
|
+
|
|
128
|
+
```tsx
|
|
129
|
+
// react-router: let the router do the replace.
|
|
130
|
+
const [, setSearchParams] = useSearchParams();
|
|
131
|
+
const setSearchParamsRef = useRef(setSearchParams);
|
|
132
|
+
setSearchParamsRef.current = setSearchParams;
|
|
133
|
+
|
|
134
|
+
const persist = useMemo(
|
|
135
|
+
() =>
|
|
136
|
+
({
|
|
137
|
+
urlKey: ["employees", ["columnFilters"]],
|
|
138
|
+
urlStorage: {
|
|
139
|
+
get: (name) => new URLSearchParams(window.location.search).get(name),
|
|
140
|
+
set: (name, value) =>
|
|
141
|
+
setSearchParamsRef.current(
|
|
142
|
+
(prev) => {
|
|
143
|
+
if (value === null) prev.delete(name);
|
|
144
|
+
else prev.set(name, value);
|
|
145
|
+
return prev;
|
|
146
|
+
},
|
|
147
|
+
{ replace: true },
|
|
148
|
+
),
|
|
149
|
+
},
|
|
150
|
+
}) satisfies TMDataGridPersistence,
|
|
151
|
+
[],
|
|
152
|
+
);
|
|
153
|
+
```
|
|
154
|
+
|
|
60
155
|
## Behaviour
|
|
61
156
|
|
|
62
157
|
**Restoring happens once**, on mount, through `initialState`. Writing is a
|
|
@@ -103,7 +198,11 @@ its `StorageType`.
|
|
|
103
198
|
| `persist` | Option | `TMDataGridPersistence` | – | The whole configuration. Keep it referentially stable. |
|
|
104
199
|
| `dataKey` | persist field | `string \| [string, DataSlice[]]` | – | Storage key for the data group. |
|
|
105
200
|
| `settingsKey` | persist field | `string \| [string, SettingsSlice[]]` | – | Storage key for the settings group. |
|
|
106
|
-
| `
|
|
201
|
+
| `urlKey` | persist field | `string \| [string, DataSlice[]]` | – | Search param for data slices kept in the URL. See [Deep links](#deep-links). |
|
|
202
|
+
| `urlStorage` | persist field | `TMDataGridUrlStorage` | `location.search` and `history.replaceState` | Reads and writes the URL param. |
|
|
203
|
+
| `TMDataGridUrlStorage` | Type | `{ get(name): string \| null; set(name, value: string \| null): void }` | – | The type of `urlStorage`. |
|
|
204
|
+
| `meta.filter.url` | Column meta | `boolean` | `true` | Determines whether the column's filter is written to the URL under `urlKey`. |
|
|
205
|
+
| `TMDataGridPersistKey` | Type | `string \| [string, slices]` | – | The type of `dataKey`, `settingsKey` and `urlKey`. |
|
|
107
206
|
| `storageMode` | persist field | `"localStorage" \| "sessionStorage"` | `"localStorage"` | Storage area. `"sessionStorage"` is per tab. |
|
|
108
207
|
| `TMDataGridStorageMode` | Type | `"localStorage" \| "sessionStorage"` | – | The type of `storageMode`. |
|
|
109
208
|
| `serialize` | persist field | `(value) => string` | `JSON.stringify` | Serializes a payload before storing. |
|
package/docs/row-details.md
CHANGED
|
@@ -19,10 +19,13 @@ hint: Expand a few rows - the panels differ in height, and each one is measured.
|
|
|
19
19
|
height: 460
|
|
20
20
|
```
|
|
21
21
|
|
|
22
|
-
The panel
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
22
|
+
The panel opens below the row's cells, which stay where they are; there is no
|
|
23
|
+
mode in which a panel replaces the row. The panel is as tall as whatever it
|
|
24
|
+
renders. The grid measures each one, so they need not be uniform.
|
|
25
|
+
`renderDetailsEstHeight` (default `160`) is what the virtualizer assumes for a
|
|
26
|
+
panel it has not measured yet, which keeps the scrollbar accurate for rows that
|
|
27
|
+
open off screen. Set it to the typical panel height; the estimate only decides
|
|
28
|
+
how far the scrollbar is off until the panel has mounted.
|
|
26
29
|
|
|
27
30
|
## The details lane
|
|
28
31
|
|
|
@@ -87,6 +90,12 @@ Because it is the standard state, `table.toggleAllRowsExpanded()`,
|
|
|
87
90
|
> `autoResetExpanded: false`; pass `autoResetExpanded: true` to have a new
|
|
88
91
|
> `data` array close the panels.
|
|
89
92
|
|
|
93
|
+
## A wider cell on an open row
|
|
94
|
+
|
|
95
|
+
To have an open row show something wider in the row itself - a title across
|
|
96
|
+
the columns, say - give that column a `meta.colSpan` that depends on
|
|
97
|
+
`row.getIsExpanded()`. See [Spanning columns](/docs/columns#spanning-columns).
|
|
98
|
+
|
|
90
99
|
## The two kinds of expanding
|
|
91
100
|
|
|
92
101
|
TanStack keeps one `expanded` state, and the grid uses it for two unrelated
|
|
@@ -119,8 +128,36 @@ not select or highlight the row underneath. It carries
|
|
|
119
128
|
`data-dg-part="details"` with the row's `data-row-id`. See
|
|
120
129
|
[Testing](/docs/testing).
|
|
121
130
|
|
|
131
|
+
The panel has no padding. Its content starts at the row's left edge and ends at
|
|
132
|
+
its right edge, so a nested grid, a tab strip or an image fills the row. Give
|
|
133
|
+
content that should line up with the cell text `padding: var(--dg-padding)`,
|
|
134
|
+
the [cell padding](/docs/styling#css-variables) of the grid's `size`.
|
|
135
|
+
|
|
122
136
|
Group rows have no panel. Expanding one opens its children.
|
|
123
137
|
|
|
138
|
+
Rows are virtualized. A row that leaves the viewport and the `overscan`
|
|
139
|
+
unmounts, and its panel unmounts with it, so state held inside the panel is
|
|
140
|
+
lost. Keep such state outside the grid, keyed by `row.id`. Rows pinned to an
|
|
141
|
+
edge never unmount.
|
|
142
|
+
|
|
143
|
+
`renderDetails` runs on every render of the body. Give a heavy panel a memoized
|
|
144
|
+
component and pass it the record, not the row:
|
|
145
|
+
|
|
146
|
+
```tsx
|
|
147
|
+
const EmployeeDetails = memo(function EmployeeDetails({ employee }: { employee: Employee }) {
|
|
148
|
+
return <EmployeeCard employee={employee} />;
|
|
149
|
+
});
|
|
150
|
+
|
|
151
|
+
const grid = useTMDataGrid({
|
|
152
|
+
data,
|
|
153
|
+
columns,
|
|
154
|
+
renderDetails: ({ row }) => <EmployeeDetails employee={row.original} />,
|
|
155
|
+
});
|
|
156
|
+
```
|
|
157
|
+
|
|
158
|
+
Key a stateful child by `row.id`; that is stable only when `getRowId` returns
|
|
159
|
+
the entity id.
|
|
160
|
+
|
|
124
161
|
## Reference
|
|
125
162
|
|
|
126
163
|
| Name | Kind | Type | Default | What it does |
|
package/docs/row-interaction.md
CHANGED
|
@@ -22,7 +22,7 @@ hint: Click, double-click and right-click anywhere in the body.
|
|
|
22
22
|
|
|
23
23
|
| Prop | Argument | Notes |
|
|
24
24
|
| --- | --- | --- |
|
|
25
|
-
| `onRowClick` | `row` | Rows show a pointer cursor when set. |
|
|
25
|
+
| `onRowClick` | `row` | Rows show a pointer cursor and the [hover tint](/docs/row-styling#hover) when set. |
|
|
26
26
|
| `onCellClick` | `{ cell, row, column, event }` | The cell cursor still moves. |
|
|
27
27
|
| `onCellDoubleClick` | same | A double-click that opens an editor still does. |
|
|
28
28
|
| `onCellContextMenu` | same | `renderRowContextMenu` and the cell-selection menu still open. |
|
|
@@ -100,7 +100,7 @@ copy and export items too. By default they appear above a divider and yours
|
|
|
100
100
|
below, which is what happens when the render prop does not use `internalItems`.
|
|
101
101
|
See [Cell selection](/docs/cell-selection#copy-and-export).
|
|
102
102
|
|
|
103
|
-
`internalItems`
|
|
103
|
+
`internalItems` holds those built-in items. **Using it takes over the
|
|
104
104
|
composition**: the menu becomes exactly what you return, in the order you
|
|
105
105
|
return it.
|
|
106
106
|
|
package/docs/row-selection.md
CHANGED
|
@@ -18,8 +18,7 @@ file: rows/SelectionModes.tsx
|
|
|
18
18
|
## The four modes
|
|
19
19
|
|
|
20
20
|
`selectionMode` sets what selecting looks like and what a bare row click does.
|
|
21
|
-
A click
|
|
22
|
-
are one option rather than two.
|
|
21
|
+
A bare click either toggles the selection or moves the highlight, never both.
|
|
23
22
|
|
|
24
23
|
| Mode | Checkbox column | Row click |
|
|
25
24
|
| ---- | --------------- | --------- |
|
|
@@ -28,8 +27,8 @@ are one option rather than two.
|
|
|
28
27
|
| `"checkboxAndHighlight"` | yes, multi-select | highlights one row |
|
|
29
28
|
| `"highlight"` | no | highlights one row - no selection at all |
|
|
30
29
|
|
|
31
|
-
The first two write to TanStack's `rowSelection`, so
|
|
32
|
-
`
|
|
30
|
+
The first two write to TanStack's `rowSelection`, so `getSelectedRowModel()`
|
|
31
|
+
and `onRowSelectionChange` behave the same either way.
|
|
33
32
|
|
|
34
33
|
Under `"row"` the click follows the usual desktop-list conventions: a plain
|
|
35
34
|
click replaces the selection with this row, Ctrl/Cmd toggles it and leaves the
|
|
@@ -71,9 +70,9 @@ For a panel that opens under the row instead of beside the grid, see
|
|
|
71
70
|
|
|
72
71
|
Read the selection through the table store with TanStack Store's
|
|
73
72
|
[`useSelector`](https://tanstack.com/store/latest/docs/framework/react/reference), rather
|
|
74
|
-
than by calling a method directly.
|
|
75
|
-
|
|
76
|
-
|
|
73
|
+
than by calling a method directly. A bare read is stale in any component that
|
|
74
|
+
does not call `useTMDataGrid` itself, and under the React Compiler also in the
|
|
75
|
+
one that does; `useSelector` subscribes either way.
|
|
77
76
|
|
|
78
77
|
```tsx
|
|
79
78
|
const selected = useSelector(
|
package/docs/row-styling.md
CHANGED
|
@@ -95,6 +95,21 @@ virtualization rather than sticking to particular records.
|
|
|
95
95
|
|
|
96
96
|
Pinned rows are not striped: they have left the scrolling order.
|
|
97
97
|
|
|
98
|
+
## Hover
|
|
99
|
+
|
|
100
|
+
A row takes the hover tint under the pointer when the row itself answers a
|
|
101
|
+
gesture: `selectionMode: "row"` or a highlight mode, `onRowClick`, or
|
|
102
|
+
`renderRowContextMenu`. A grid with none of those shows no hover tint, and a
|
|
103
|
+
group row never does, since it sits out those gestures.
|
|
104
|
+
|
|
105
|
+
`highlightOnHover` overrides that: `true` tints every row, `false` none.
|
|
106
|
+
|
|
107
|
+
```tsx
|
|
108
|
+
<TMDataGrid.Table highlightOnHover={false} />
|
|
109
|
+
```
|
|
110
|
+
|
|
111
|
+
A row carries `data-highlight-on-hover="true"` while the tint applies.
|
|
112
|
+
|
|
98
113
|
## Styling by state
|
|
99
114
|
|
|
100
115
|
Rows carry data attributes for their state, so a stylesheet can target any of
|
|
@@ -108,6 +123,7 @@ it without a callback:
|
|
|
108
123
|
| `data-grouped` | Group rows |
|
|
109
124
|
| `data-depth` | Every row. The nesting level |
|
|
110
125
|
| `data-context-menu` | The row whose context menu is open |
|
|
126
|
+
| `data-highlight-on-hover` | Rows that take the hover tint. See [Hover](#hover) |
|
|
111
127
|
| `data-row-id` | Every row. Its id, which [tests](/docs/testing) key off |
|
|
112
128
|
|
|
113
129
|
The state attributes are present, with the value `"true"`, only on the rows
|
|
@@ -127,6 +143,7 @@ they apply to, so the bare attribute and the value match the same rows:
|
|
|
127
143
|
| `rowStyle` | Table prop | `TMDataGridRowStyle \| (row) => TMDataGridRowStyle` | – | Inline style for a body row. |
|
|
128
144
|
| `rowClassName` | Table prop | `string \| (row) => string \| undefined` | – | Class for a body row, added after the grid's own. |
|
|
129
145
|
| `striped` | Table prop | `boolean` | `false` | Every second row takes `--dg-row-striped-bg`. |
|
|
146
|
+
| `highlightOnHover` | Table prop | `boolean` | On for rows that answer a click or a right-click | Whether a body row takes the hover tint. |
|
|
130
147
|
| `TMDataGridRowStyle` | Export | type | – | `CSSProperties` or an object of `--*` custom properties. |
|
|
131
148
|
| `--row-bg` | CSS variable | colour | – | The row's own background, composed over the body colour and under hover, selection and range. |
|
|
132
149
|
| `--dg-row-striped-bg` | CSS variable | colour | Themed | The stripe colour. |
|
package/docs/scrolling.md
CHANGED
|
@@ -103,7 +103,7 @@ boundary and the pinned band is always on.
|
|
|
103
103
|
| Name | Kind | Type | Default | What it does |
|
|
104
104
|
| --- | --- | --- | --- | --- |
|
|
105
105
|
| `overscan` | Option | `number` | `6` | Rows kept mounted beyond each edge of the viewport. |
|
|
106
|
-
| `meta.rowHeight` | Option | `number` |
|
|
106
|
+
| `meta.rowHeight` | Option | `number` | `52` at the default `md` size; see [the size scale](/docs/styling#the-size-scale) | Row height, in pixels. The virtualizer needs a number. |
|
|
107
107
|
| `scrollToRow` | Hook return | `({ rowId, align? }) => boolean` | `align: "auto"` | Scrolls a row into view, mounted or not. Answers whether it could be reached. |
|
|
108
108
|
| `TMDataGridScrollToRowArgs` | Type | `{ rowId, align? }` | – | What `scrollToRow` takes. |
|
|
109
109
|
| `onScrollToTop` · `onScrollToBottom` · `onScrollToLeft` · `onScrollToRight` | Table props | `() => void` | – | Fire once on arriving at that edge. |
|
package/docs/server-side.md
CHANGED
|
@@ -64,7 +64,7 @@ column manager behave identically in both modes.
|
|
|
64
64
|
|
|
65
65
|
## The page index
|
|
66
66
|
|
|
67
|
-
A column filter, the quick search or a
|
|
67
|
+
A column filter, the quick search, a sort or a grouping changes what page 3 means.
|
|
68
68
|
The result set is a different one, and it may not have a page 3 at all - so the grid resets `pageIndex` to 0 whenever the query changes, on every grid.
|
|
69
69
|
The reset is applied in the same event as the change, so one request goes out, for the first page of the new query.
|
|
70
70
|
|
|
@@ -139,6 +139,8 @@ even though they are no longer mounted. Read the state rather than the row
|
|
|
139
139
|
models:
|
|
140
140
|
|
|
141
141
|
```ts
|
|
142
|
+
// In an event handler. In render, subscribe instead:
|
|
143
|
+
// useSelector(grid.table.store, (state) => Object.keys(state.rowSelection))
|
|
142
144
|
const selectedIds = Object.keys(grid.table.store.state.rowSelection);
|
|
143
145
|
```
|
|
144
146
|
|
package/docs/testing.md
CHANGED
|
@@ -66,6 +66,24 @@ const cell = orders.locator(
|
|
|
66
66
|
Body cells carry no `data-dg-part`; the coordinate pair identifies them.
|
|
67
67
|
The `editor` part of an open cell carries the same pair, so `:not([data-dg-part])` keeps the locator on the cell while the cell is being edited.
|
|
68
68
|
|
|
69
|
+
The generated lanes are columns like any other, with exported ids:
|
|
70
|
+
|
|
71
|
+
| Constant | `data-column-id` | Lane |
|
|
72
|
+
| --- | --- | --- |
|
|
73
|
+
| `ROW_NUMBER_COLUMN_ID` | `__rowNumber__` | Row numbers |
|
|
74
|
+
| `SELECT_COLUMN_ID` | `__select__` | Selection checkboxes |
|
|
75
|
+
| `GROUP_COLUMN_ID` | `__group__` | The grouping tree |
|
|
76
|
+
| `DETAILS_COLUMN_ID` | `__details__` | Details toggles |
|
|
77
|
+
| `EDIT_COLUMN_ID` | `__edit__` | Row editing |
|
|
78
|
+
|
|
79
|
+
A lane's header is `[data-dg-part="header"][data-column-id="__select__"]` and
|
|
80
|
+
a lane cell `[data-row-id="42"][data-column-id="__select__"]:not([data-dg-part])`.
|
|
81
|
+
The control inside a lane cell has a part of its own, keyed by the row:
|
|
82
|
+
`select-row`, `details-toggle`, `group-toggle` and the edit lane's buttons (see
|
|
83
|
+
[Keyed by `data-row-id`](#keyed-by-data-row-id)); `select-all` and
|
|
84
|
+
`details-toggle-all` sit in the lane headers. The checkbox parts are on the
|
|
85
|
+
`<input>` itself, so `check()` works on them directly.
|
|
86
|
+
|
|
69
87
|
**The body scrolls inside the scroll container.** The element carrying
|
|
70
88
|
`data-dg-scroll-container` is the one to scroll in a test, whether to load the
|
|
71
89
|
next page of an infinite-scroll grid or to move the virtualizer without the api:
|