@jielga/tmdatagrid 2.0.0-beta.2 → 2.0.0-beta.21

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.
Files changed (150) hide show
  1. package/README.md +5 -212
  2. package/dist/index.d.ts +1664 -632
  3. package/dist/index.js +5226 -3223
  4. package/dist/index.js.map +1 -1
  5. package/dist/styles.css +1 -1
  6. package/docs/anatomy.md +102 -0
  7. package/docs/cell-selection.md +154 -0
  8. package/docs/column-layout.md +204 -0
  9. package/docs/columns.md +262 -0
  10. package/docs/components.md +304 -0
  11. package/docs/editing.md +603 -0
  12. package/docs/editors.md +250 -0
  13. package/docs/export.md +326 -0
  14. package/docs/filtering.md +358 -0
  15. package/docs/getting-started.md +123 -0
  16. package/docs/grouping.md +165 -0
  17. package/docs/loading-and-empty.md +92 -0
  18. package/docs/localization.md +79 -0
  19. package/docs/menu.md +143 -0
  20. package/docs/pagination.md +144 -0
  21. package/docs/persistence.md +111 -0
  22. package/docs/portfolio-rebalancer.md +94 -0
  23. package/docs/query-builder.md +175 -0
  24. package/docs/quick-search.md +83 -0
  25. package/docs/row-details.md +113 -0
  26. package/docs/row-interaction.md +148 -0
  27. package/docs/row-pinning.md +132 -0
  28. package/docs/row-selection.md +134 -0
  29. package/docs/row-styling.md +133 -0
  30. package/docs/scrolling.md +111 -0
  31. package/docs/server-query.md +246 -0
  32. package/docs/server-side.md +206 -0
  33. package/docs/sorting.md +101 -0
  34. package/docs/styling.md +126 -0
  35. package/docs/summary-row.md +76 -0
  36. package/docs/testing.md +309 -0
  37. package/docs/toolbar.md +161 -0
  38. package/docs/use-tm-data-grid.md +361 -0
  39. package/package.json +21 -45
  40. package/skills/appearance/SKILL.md +70 -17
  41. package/skills/cell-selection/SKILL.md +70 -76
  42. package/skills/columns/SKILL.md +131 -32
  43. package/skills/data/SKILL.md +100 -23
  44. package/skills/editing/SKILL.md +217 -96
  45. package/skills/editing/references/common-mistakes.md +111 -24
  46. package/skills/editing/references/editing-api.md +63 -39
  47. package/skills/editing/references/editors-and-validation.md +77 -19
  48. package/skills/filtering/SKILL.md +148 -40
  49. package/skills/getting-started/SKILL.md +18 -16
  50. package/skills/grouping/SKILL.md +32 -15
  51. package/skills/options/SKILL.md +39 -9
  52. package/skills/rows/SKILL.md +22 -18
  53. package/skills/server-side/SKILL.md +170 -17
  54. package/skills/testing/SKILL.md +10 -7
  55. package/src/{tmdatagrid/TMDataGridContext.ts → TMDataGridContext.ts} +7 -19
  56. package/src/{tmdatagrid/components → components}/TMDataGrid.module.css +7 -1
  57. package/src/{tmdatagrid/components → components}/TMDataGrid.tsx +39 -23
  58. package/src/{tmdatagrid/components → components}/TMDataGridCellEditor.tsx +106 -38
  59. package/src/{tmdatagrid/components → components}/TMDataGridColumnsPanel.module.css +5 -1
  60. package/src/{tmdatagrid/components → components}/TMDataGridColumnsPanel.tsx +47 -55
  61. package/src/{tmdatagrid/components → components}/TMDataGridDetailsColumn.tsx +4 -4
  62. package/src/components/TMDataGridDraftActions.tsx +307 -0
  63. package/src/{tmdatagrid/components → components}/TMDataGridEditColumn.tsx +58 -50
  64. package/src/{tmdatagrid/components → components}/TMDataGridEntryRows.tsx +150 -115
  65. package/src/components/TMDataGridExportPicker.module.css +77 -0
  66. package/src/components/TMDataGridExportPicker.tsx +234 -0
  67. package/src/components/TMDataGridFilterPanel.module.css +54 -0
  68. package/src/components/TMDataGridFilterPanel.tsx +348 -0
  69. package/src/{tmdatagrid/components → components}/TMDataGridFilterPills.tsx +7 -5
  70. package/src/components/TMDataGridFilterSurface.module.css +54 -0
  71. package/src/components/TMDataGridFilterSurface.tsx +167 -0
  72. package/src/{tmdatagrid/components → components}/TMDataGridFooter.tsx +53 -13
  73. package/src/{tmdatagrid/components → components}/TMDataGridGroupColumn.tsx +4 -3
  74. package/src/{tmdatagrid/components → components}/TMDataGridHeaderCell.module.css +10 -0
  75. package/src/{tmdatagrid/components → components}/TMDataGridHeaderCell.tsx +100 -28
  76. package/src/components/TMDataGridHeaderFilterRow.module.css +51 -0
  77. package/src/components/TMDataGridHeaderFilterRow.tsx +301 -0
  78. package/src/components/TMDataGridMenu.tsx +354 -0
  79. package/src/{tmdatagrid/components → components}/TMDataGridSelectColumn.tsx +12 -7
  80. package/src/{tmdatagrid/components → components}/TMDataGridTable.module.css +90 -67
  81. package/src/{tmdatagrid/components → components}/TMDataGridTable.tsx +678 -156
  82. package/src/components/TMDataGridToolbar.module.css +21 -0
  83. package/src/components/TMDataGridToolbar.tsx +181 -0
  84. package/src/{tmdatagrid/components → components}/editors/TMDataGridBooleanEditor.tsx +3 -3
  85. package/src/{tmdatagrid/components → components}/editors/TMDataGridDateEditor.tsx +3 -3
  86. package/src/{tmdatagrid/components → components}/editors/TMDataGridMultiSelectEditor.tsx +3 -3
  87. package/src/components/editors/TMDataGridNumberEditor.tsx +70 -0
  88. package/src/{tmdatagrid/components → components}/editors/TMDataGridSelectEditor.tsx +3 -3
  89. package/src/{tmdatagrid/components → components}/editors/TMDataGridStringEditor.tsx +3 -3
  90. package/src/{tmdatagrid/components → components}/editors/editorShared.ts +17 -31
  91. package/src/{tmdatagrid/components → components}/filters/DgAutocompleteFilter.tsx +5 -4
  92. package/src/{tmdatagrid/components → components}/filters/DgDateRangeFilter.tsx +22 -5
  93. package/src/{tmdatagrid/components → components}/filters/DgRangeSliderFilter.tsx +5 -1
  94. package/src/{tmdatagrid/components → components}/filters/DgTriStateFilter.tsx +5 -1
  95. package/src/{tmdatagrid/components → components}/filters/TMDataGridFilterValueInput.tsx +44 -28
  96. package/src/components/filters/controlLayout.ts +32 -0
  97. package/src/components/filters/filterControlFor.ts +65 -0
  98. package/src/{tmdatagrid/components → components}/icons.ts +1 -0
  99. package/src/{tmdatagrid/components → components}/sticky.module.css +44 -0
  100. package/src/components/useHideableColumns.ts +52 -0
  101. package/src/{tmdatagrid/core → core}/autosize.ts +5 -2
  102. package/src/{tmdatagrid/core → core}/capabilities.ts +14 -6
  103. package/src/{tmdatagrid/core → core}/columnOptions.ts +46 -0
  104. package/src/{tmdatagrid/core → core}/columnOrdering.ts +33 -14
  105. package/src/{tmdatagrid/core → core}/columnUtils.ts +44 -5
  106. package/src/core/controlledState.ts +179 -0
  107. package/src/core/controlledStateSync.ts +108 -0
  108. package/src/core/deletedRows.ts +34 -0
  109. package/src/core/dom.ts +74 -0
  110. package/src/core/editEngine.ts +2476 -0
  111. package/src/{tmdatagrid/core → core}/editorFocus.ts +8 -4
  112. package/src/core/export.ts +843 -0
  113. package/src/{tmdatagrid/core → core}/filterControls.ts +38 -1
  114. package/src/{tmdatagrid/core → core}/filterOperators.ts +64 -1
  115. package/src/core/filterSurface.ts +99 -0
  116. package/src/{tmdatagrid/core → core}/labels.ts +66 -8
  117. package/src/{tmdatagrid/core → core}/labelsSv.ts +26 -3
  118. package/src/core/pageReset.ts +120 -0
  119. package/src/{tmdatagrid/core → core}/persistence.ts +22 -5
  120. package/src/core/resizePreview.ts +141 -0
  121. package/src/core/summary.ts +59 -0
  122. package/src/core/useSettledTableState.ts +36 -0
  123. package/src/{tmdatagrid/index.ts → index.ts} +75 -12
  124. package/src/{tmdatagrid/useTMDataGrid.tsx → useTMDataGrid.tsx} +734 -135
  125. package/src/useTMDataGridExport.ts +78 -0
  126. package/src/tmdatagrid/components/TMDataGridEditActions.tsx +0 -162
  127. package/src/tmdatagrid/components/TMDataGridFilterPanel.module.css +0 -35
  128. package/src/tmdatagrid/components/TMDataGridFilterPanel.tsx +0 -354
  129. package/src/tmdatagrid/components/TMDataGridToolbar.module.css +0 -12
  130. package/src/tmdatagrid/components/TMDataGridToolbar.tsx +0 -162
  131. package/src/tmdatagrid/components/editors/TMDataGridNumberEditor.tsx +0 -40
  132. package/src/tmdatagrid/core/cellExport.ts +0 -320
  133. package/src/tmdatagrid/core/editEngine.ts +0 -1006
  134. package/src/tmdatagrid/core/summary.ts +0 -35
  135. /package/src/{tmdatagrid/components → components}/TMDataGridDetailsColumn.module.css +0 -0
  136. /package/src/{tmdatagrid/components → components}/TMDataGridFilterPills.module.css +0 -0
  137. /package/src/{tmdatagrid/components → components}/TMDataGridFooter.module.css +0 -0
  138. /package/src/{tmdatagrid/components → components}/TMDataGridGroupColumn.module.css +0 -0
  139. /package/src/{tmdatagrid/components → components}/TMDataGridRowNumberColumn.tsx +0 -0
  140. /package/src/{tmdatagrid/components → components}/TMDataGridSearch.tsx +0 -0
  141. /package/src/{tmdatagrid/core → core}/cellNavigation.ts +0 -0
  142. /package/src/{tmdatagrid/core → core}/cellRange.ts +0 -0
  143. /package/src/{tmdatagrid/core → core}/draftCellContext.ts +0 -0
  144. /package/src/{tmdatagrid/core → core}/expanding.ts +0 -0
  145. /package/src/{tmdatagrid/core → core}/grouping.ts +0 -0
  146. /package/src/{tmdatagrid/core → core}/matchHighlight.ts +0 -0
  147. /package/src/{tmdatagrid/core → core}/quickSearch.ts +0 -0
  148. /package/src/{tmdatagrid/core → core}/rowPinning.ts +0 -0
  149. /package/src/{tmdatagrid/core → core}/rowSelection.ts +0 -0
  150. /package/src/{tmdatagrid/core → core}/sizes.ts +0 -0
@@ -0,0 +1,262 @@
1
+ # Defining columns
2
+
3
+ A column declares where its value comes from, what kind of value it is, and how
4
+ to render it. Which filter operators it offers, which editor it opens and how
5
+ it sorts all follow from `meta.type`.
6
+
7
+ ## The column helper
8
+
9
+ `createTMDataGridColumnHelper<TData>()` returns a TanStack column helper bound
10
+ to the grid's feature set, so that `meta` and `filterFn` are correctly typed.
11
+
12
+ ```tsx
13
+ const columnHelper = createTMDataGridColumnHelper<Employee>();
14
+
15
+ const columns = columnHelper.columns([
16
+ columnHelper.accessor("salary", {
17
+ header: "Salary",
18
+ minSize: 130,
19
+ meta: { type: "number", align: "right" },
20
+ cell: (info) => formatSek(info.getValue()),
21
+ }),
22
+ columnHelper.accessor((row) => `${row.firstName} ${row.lastName}`, {
23
+ id: "fullName",
24
+ header: "Full name",
25
+ meta: { label: "Full name" },
26
+ }),
27
+ ]);
28
+ ```
29
+
30
+ **Define columns at module scope.** A new array on every render rebuilds the
31
+ table's column model and discards the user's column widths and order.
32
+
33
+ ```demo
34
+ file: getting-started/ColumnDefinitions.tsx
35
+ ```
36
+
37
+ An accessor may be a key of the row or a function over it. A function needs an
38
+ explicit `id`, and a `meta.label` for the name shown in menus and the columns
39
+ panel.
40
+
41
+ A dotted `accessorKey` reads a nested field, and the column id it derives
42
+ replaces the dots: `accessorKey: "address.city"` makes column id
43
+ `address_city`, while the edit path stays `"address.city"`. Anything that
44
+ addresses the column by id - `initialState`, `editing.columns`, `moveColumn`,
45
+ a test selector - takes the underscore form; the dotted form silently matches
46
+ nothing.
47
+
48
+ ### Columns derived from the other rows
49
+
50
+ `accessorFn` is handed one row, so a value that depends on the rest - a share
51
+ of a total, a rank, a running total - cannot be an accessor. Derive the
52
+ collection once and hand the grid the finished shape; the column is then a
53
+ plain `accessorKey`:
54
+
55
+ ```tsx
56
+ const rows = useMemo(() => {
57
+ const total = holdings.reduce((sum, holding) => sum + holding.value, 0);
58
+
59
+ return holdings.map((holding) => ({
60
+ ...holding,
61
+ pctOfTotal: (holding.value / total) * 100,
62
+ }));
63
+ }, [holdings]);
64
+
65
+ columnHelper.accessor("pctOfTotal", {
66
+ header: "Share",
67
+ meta: { type: "number", align: "right" },
68
+ cell: (info) => `${info.getValue().toFixed(1)}%`,
69
+ });
70
+ ```
71
+
72
+ [A portfolio rebalancer](/docs/portfolio-rebalancer) works one through, from
73
+ the derived rows to a validator that reads them all.
74
+
75
+ ## meta
76
+
77
+ `meta` carries what a TanStack column definition has no field for. What the
78
+ column is sits at the top level; what the filter panel and the edit engine do
79
+ with it sits in the `filter` and `edit` namespaces.
80
+
81
+ | Field | Type | Default | Description |
82
+ | --- | --- | --- | --- |
83
+ | `label` | `string` | String header, or column id | Name used in menus and the column manager. Required when `header` is a component. |
84
+ | `type` | `"string" \| "number" \| "boolean" \| "date" \| "select" \| "multiSelect"` | `"string"` | What the values are. Selects the filter operators, the filter control and the cell editor. |
85
+ | `options` | `TMDataGridOptionsSource` | - | The choices of a `select` / `multiSelect` column. See [Options](#options). |
86
+ | `flex` | `number` | `1` | Share of the remaining width. |
87
+ | `align` | `"left" \| "right" \| "center"` | `"left"` | Alignment, applied to both header and cells. |
88
+ | `autoSize` | `boolean` | `false` | Fit the column to its content once, on the render its first cells appear in. |
89
+ | `enableOrdering` | `boolean` | `true` | `false` keeps the column where it is. |
90
+ | `filter` | `TMDataGridColumnFilterOptions` | - | How this column filters. See [meta.filter](#metafilter). |
91
+ | `edit` | `TMDataGridColumnEditOptions` | - | How this column is edited. See [meta.edit](#metaedit). |
92
+
93
+ ### meta.filter
94
+
95
+ | Field | Type | Default | Description |
96
+ | --- | --- | --- | --- |
97
+ | `defaultOperator` | `TMDataGridFilterOperator` | The type's default | The operator a fresh filter starts with. See [Filtering](/docs/filtering#operators). |
98
+ | `control` | `TMDataGridFilterControlComponent` | By type and operator | Replaces the filter panel's value control. See [Filtering](/docs/filtering#replacing-the-value-control). |
99
+
100
+ ```tsx
101
+ meta: {
102
+ type: "number",
103
+ filter: { defaultOperator: "between", control: DgRangeSliderFilter },
104
+ }
105
+ ```
106
+
107
+ ### meta.edit
108
+
109
+ | Field | Type | Default | Description |
110
+ | --- | --- | --- | --- |
111
+ | `enabled` | `boolean \| (row) => boolean` | `true` | Whether cells in this column may be edited. See [Editing](/docs/editing#which-cells-edit). |
112
+ | `field` | `string` | The `accessorKey` | The data path an edit writes to, for a column built on `accessorFn`. |
113
+ | `editor` | `TMDataGridEditorComponent` | By `type` | Replaces the cell editor. See [Editors](/docs/editors#writing-your-own). |
114
+ | `validate` | `TMDataGridFieldValidate` | - | Per-cell validation. See [Validation](/docs/editors#validation). |
115
+ | `mapValue` | `TMDataGridEditValueMap` | - | Maps each value an editor writes. See [Mapping the value](/docs/editors#mapping-the-value-as-it-is-typed). |
116
+
117
+ ```tsx
118
+ meta: {
119
+ type: "string",
120
+ edit: {
121
+ enabled: (row) => row.original.status !== "Terminated",
122
+ validate: z.string().min(2, "At least two characters"),
123
+ mapValue: ({ value }) =>
124
+ typeof value === "string" ? value.toUpperCase() : value,
125
+ },
126
+ }
127
+ ```
128
+
129
+ Omit both namespaces to get the defaults: any column mapping to a data path is
130
+ editable once `editing` is set, and every column filters by its type.
131
+
132
+ ## Column types
133
+
134
+ `meta.type` declares what a column's values are. The filter panel offers that
135
+ type's operators and renders a matching value control: a date input for `date`,
136
+ a Yes/No dropdown for `boolean`, a multi-select of the column's options for
137
+ `select` and `multiSelect`. With editing on, the same declaration picks the
138
+ editor.
139
+
140
+ Dates may be `Date` instances or ISO `YYYY-MM-DD` strings in the data; the
141
+ comparison is by calendar day either way, and filter values always travel as ISO
142
+ strings. The date control is the native `<input type="date">`; `@mantine/dates`
143
+ is not used.
144
+
145
+ A column whose value is none of the six types - an object such as a
146
+ `{ from, to }` range - renders through its own `cell`, but sorting, the filter
147
+ panel and quick search operate on the raw value. Set `enableSorting`,
148
+ `enableColumnFilter` and `enableGlobalFilter` to `false` on such a column.
149
+
150
+ ### Options
151
+
152
+ `select` and `multiSelect` columns declare their choices once, in `meta.options`,
153
+ and every consumer of them (the filter panel, the cell editor) reads the same
154
+ source:
155
+
156
+ ```tsx
157
+ // A fixed set, strings or full options:
158
+ meta: {
159
+ type: "select",
160
+ options: [
161
+ "Pending",
162
+ { value: "Paid", label: "Paid in full", color: "green" },
163
+ ],
164
+ }
165
+
166
+ // The distinct values present in the data (low-cardinality columns):
167
+ meta: { type: "select", options: "faceted" }
168
+
169
+ // Computed. `row` is set when a cell editor asks and absent for the filter
170
+ // panel, so row-dependent options can branch on it. `row.original` is
171
+ // `unknown` here - cast it to the row type:
172
+ meta: {
173
+ type: "select",
174
+ options: ({ row }) =>
175
+ row ? citiesFor((row.original as Employee).country) : allCities,
176
+ }
177
+ ```
178
+
179
+ `resolveColumnOptions({ table, column, row? })` normalises all three forms and is
180
+ exported for custom controls; `optionsToComboboxData` turns the result into what
181
+ Mantine's `Select` and `MultiSelect` take, `group` fields included.
182
+
183
+ A select column that declares no options still filters: the panel falls back to
184
+ the faceted values. Mantine's dropdowns are not virtualized, so use the function
185
+ form for very large sets.
186
+
187
+ ## Header groups
188
+
189
+ `columnHelper.group` nests columns under a shared header. The group is a header
190
+ row, not a column - the leaves keep all the behaviour. `columns` takes another
191
+ `columnHelper.columns` call, not a bare array:
192
+
193
+ ```tsx
194
+ columnHelper.group({
195
+ id: "person",
196
+ header: "Person",
197
+ columns: columnHelper.columns([
198
+ columnHelper.accessor("firstName", { header: "First" }),
199
+ columnHelper.accessor("lastName", { header: "Last" }),
200
+ ]),
201
+ });
202
+ ```
203
+
204
+ ```demo
205
+ file: getting-started/HeaderGroups.tsx
206
+ hint: Sort, filter and resize the leaves; the group header follows them.
207
+ ```
208
+
209
+ Columns inside a group cannot be reordered, regardless of `meta.enableOrdering`:
210
+ `columnOrder` sequences leaf columns, so moving one would leave the group header
211
+ spanning columns that no longer belong to it.
212
+
213
+ ## Per-column feature switches
214
+
215
+ Standard TanStack column options. Each removes the corresponding interface for
216
+ that column alone.
217
+
218
+ | Option | Effect when `false` |
219
+ | --- | --- |
220
+ | `enableSorting` | No sort indicator and no sort menu items. See [Sorting](/docs/sorting). |
221
+ | `enableColumnFilter` | No filter menu item, and no entry in the panel's column list. |
222
+ | `enableHiding` | No hide menu item, and no checkbox in the column manager. |
223
+ | `enablePinning` | No pin menu items. |
224
+ | `enableResizing` | The divider stays as a separator but cannot be dragged. |
225
+ | `meta.enableOrdering` | No header dragging and no move menu items. |
226
+
227
+ Sizing, pinning, ordering and visibility are covered on
228
+ [Visibility, pinning, ordering and size](/docs/column-layout).
229
+
230
+ ## The generated columns
231
+
232
+ Five lanes the grid adds when a feature needs them. All are **system lanes**:
233
+ fixed width, no column menu, no resize handle, never exported, never hidden and
234
+ never listed in the columns panel.
235
+
236
+ | Id | Appears when | Where |
237
+ | --- | --- | --- |
238
+ | `ROW_NUMBER_COLUMN_ID` | `enableRowNumbers` | Outermost left, before everything. See [Row pinning and numbering](/docs/row-pinning#numbering-rows). |
239
+ | `SELECT_COLUMN_ID` | A checkbox selection mode | First, pinned left. See [Row selection](/docs/row-selection). |
240
+ | `GROUP_COLUMN_ID` | A column is grouped | Front, beside the checkbox lane. See [Grouping](/docs/grouping). |
241
+ | `DETAILS_COLUMN_ID` | `renderDetails` is set | Left, after checkbox and tree. See [Row details](/docs/row-details). |
242
+ | `EDIT_COLUMN_ID` | `editing.mode: "row"`, `editing.draft`, or `editing.onRowDelete` | Appended, pinned right, and stays outside anything the user pins right. See [Editing](/docs/editing). |
243
+
244
+ The checkbox lane cannot be moved: it anchors the left pinned region, and no
245
+ column can be placed in front of it.
246
+
247
+ ## Reference
248
+
249
+ | Name | Kind | Type | Default | What it does |
250
+ | --- | --- | --- | --- | --- |
251
+ | `createTMDataGridColumnHelper` | Export | `<TData>() => helper` | – | A TanStack column helper typed against the grid's features. |
252
+ | `meta.label` | Column meta | `string` | Header or id | Name in menus and the columns panel. |
253
+ | `meta.type` | Column meta | six types | `"string"` | What the values are; drives filters and editors. |
254
+ | `meta.options` | Column meta | array \| `"faceted"` \| `(args) => …` | – | The choices of an option column. |
255
+ | `meta.align` | Column meta | `"left" \| "right" \| "center"` | `"left"` | Header and cell alignment. |
256
+ | `meta.filter` | Column meta | `TMDataGridColumnFilterOptions` | – | How the column filters: `defaultOperator`, `control`. |
257
+ | `meta.edit` | Column meta | `TMDataGridColumnEditOptions` | – | How the column edits: `enabled`, `field`, `editor`, `validate`, `mapValue`. |
258
+ | `resolveColumnOptions` | Export | `({ table, column, row? }) => options` | – | Normalises all three `meta.options` forms. |
259
+ | `optionsToComboboxData` | Export | `(options) => ComboboxData` | – | Options as Mantine `Select` data. |
260
+ | `getColumnLabel` · `getColumnType` · `isControlColumn` | Exports | `(column) => …` | – | How the built-in controls read a column. |
261
+ | `isGeneratedColumn` | Export | `(columnId) => boolean` | – | Whether the grid generated the column - the four control lanes plus the tree column. |
262
+ | `SELECT_COLUMN_ID` · `GROUP_COLUMN_ID` · `DETAILS_COLUMN_ID` · `EDIT_COLUMN_ID` · `ROW_NUMBER_COLUMN_ID` | Exports | `string` | – | Ids of the five generated lanes. |
@@ -0,0 +1,304 @@
1
+ # Components and hooks
2
+
3
+ Every hook and component the package exports.
4
+ A part whose props belong to one topic is documented on that topic's page, and listed here with a link; everything else - the root, the Table, and the parts whose props scatter across every topic - is written up in full below.
5
+ The options `useTMDataGrid` takes are on [useTMDataGrid](/docs/use-tm-data-grid).
6
+
7
+ ```tsx
8
+ import { TMDataGrid, useTMDataGrid } from "@jielga/tmdatagrid";
9
+ ```
10
+
11
+ The parts of the grid are reached through the `TMDataGrid` object.
12
+ `TMDataGridSearch`, `TMDataGridFilterPills`, `TMDataGridDraftActions`, the editors and the filter controls are also exported by name; the remaining parts are available only as `TMDataGrid.Part`.
13
+
14
+ ## useTMDataGrid
15
+
16
+ Creates the table instance, the UI store and the edit engine.
17
+ Spread its result onto `TMDataGrid`:
18
+
19
+ ```tsx
20
+ const grid = useTMDataGrid({ data, columns });
21
+
22
+ <TMDataGrid {...grid}>
23
+ <TMDataGrid.Table />
24
+ </TMDataGrid>;
25
+ ```
26
+
27
+ `useTMDataGrid<TData>(options: UseTMDataGridOptions<TData>): TMDataGridApi<TData>`
28
+
29
+ | Field | Type | What it is |
30
+ | --- | --- | --- |
31
+ | `table` | `TMDataGridTable<TData>` | The TanStack table instance. State lives in `table.store`. |
32
+ | `ui` | `TMDataGridUiStore` | Panels, drag state, focused cell and cell range. |
33
+ | `edit` | `TMDataGridEditApi` | The [editing engine](/docs/editing). Inert until `editing` is set. |
34
+ | `features` | `TMDataGridFeatureFlags` | Feature switches, re-read from the options on every render. |
35
+ | `labels` | `TMDataGridLabels` | The [dictionary](/docs/localization), merged over the English defaults. |
36
+ | `renderDetails` | `TMDataGridDetailsRenderer<TData> \| undefined` | The [details renderer](/docs/row-details), passed through to the Table. |
37
+ | `renderDetailsEstHeight` | `number` | The option, or `160`. |
38
+ | `overscan` | `number` | The option, or `6`. |
39
+ | `resetSettings` | `() => void` | Puts visibility, order, widths, pinning and grouping back to a first visit. |
40
+ | `scrollToRow` | `({ rowId, align? }) => boolean` | Scrolls a row into view. Returns `false` when the row is not in the current view. |
41
+
42
+ ## useTMDataGridContext
43
+
44
+ Returns the grid from inside a component rendered under `TMDataGrid`.
45
+ It throws when called outside one.
46
+
47
+ ```tsx
48
+ const { table, labels, controlSize } = useTMDataGridContext();
49
+ ```
50
+
51
+ The value carries every field `useTMDataGrid` returns, plus three resolved from `size`:
52
+
53
+ | Field | Type | What it is |
54
+ | --- | --- | --- |
55
+ | `size` | `TMDataGridSize` | The `size` prop set on `TMDataGrid`. |
56
+ | `rowHeight` | `number` | Row height in pixels, from `size` and `meta.rowHeight`. |
57
+ | `controlSize` | `TMDataGridSize` | The Mantine control size that pairs with `size`. |
58
+
59
+ ## TMDataGrid
60
+
61
+ The root element.
62
+ It provides the grid to every part through context, and takes every field `useTMDataGrid` returns alongside these props:
63
+
64
+ | Prop | Type | Default | Description |
65
+ | --- | --- | --- | --- |
66
+ | `children` | `ReactNode` | – | The grid's parts, in render order. |
67
+ | `size` | `TMDataGridSize` | `"md"` | The [size scale](/docs/styling#the-size-scale). |
68
+ | `className` · `style` · `id` | `string` · `CSSProperties` · `string` | – | Set on the root element. Give the grid a bounded height - see [Layout](/docs/styling#layout). |
69
+ | `data-testid` | `string` | – | Names the grid for [tests](/docs/testing). Set it when a page holds more than one grid. |
70
+
71
+ ## TMDataGrid.Table
72
+
73
+ The scrollable surface: the header, the virtualized body and the filter panel.
74
+ Pass the row type so the handlers are typed:
75
+
76
+ ```tsx
77
+ <TMDataGrid.Table<Employee> onRowClick={(row) => open(row.original.id)} />
78
+ ```
79
+
80
+ | Prop | Type | Default | Description |
81
+ | --- | --- | --- | --- |
82
+ | `onRowClick` | `(row) => void` | – | Called when a body row is clicked. Rows show a pointer cursor when set. See [Clicks and context menus](/docs/row-interaction). |
83
+ | `onCellClick` · `onCellDoubleClick` · `onCellContextMenu` | `(args: TMDataGridCellEventArgs) => void` | – | Called on cell click, double-click and right-click. Receive `{ cell, row, column, event }`. See [Clicks and context menus](/docs/row-interaction). |
84
+ | `renderRowContextMenu` | `TMDataGridRowContextMenuRenderer` | – | Contents of a row's context menu. Receives `{ table, row, cell, close, internalItems }`. See [Context menus](/docs/row-interaction#context-menus). |
85
+ | `rowContextMenuProps` | `Omit<MenuProps, "opened" \| "onChange" \| "children">` | – | Props passed to the Mantine `Menu` behind the context menu. |
86
+ | `renderColumnMenuItems` | `TMDataGridColumnMenuItemsRenderer` | – | Contents of a column's menu. Returning an empty array leaves the column with no menu button. See [The column menu](/docs/column-layout#the-column-menu). |
87
+ | `rowClassName` | `string \| (row) => string` | – | Class for a body row. See [Row styling](/docs/row-styling). |
88
+ | `rowStyle` | `TMDataGridRowStyle \| (row) => TMDataGridRowStyle` | – | Inline style for a body row. Set `--row-bg` rather than `background`. See [Row styling](/docs/row-styling#set-the-row-background). |
89
+ | `striped` | `boolean` | `false` | If set, every second row takes `--dg-row-striped-bg`. See [Striping](/docs/row-styling#striping). |
90
+ | `onScrollToTop` · `onScrollToBottom` · `onScrollToLeft` · `onScrollToRight` | `() => void` | – | Called once on arriving at that edge, not on mount and not per scroll event. See [Edge callbacks](/docs/scrolling#edge-callbacks). |
91
+ | `onReachEnd` | `() => void` | – | Called as the scroll nears the last row, once per row count. Sorting and filtering must be server-side. See [Infinite scroll](/docs/server-side#infinite-scroll). |
92
+ | `reachEndThreshold` | `number` | `10` | Rows before the end at which `onReachEnd` fires. |
93
+ | `renderEmptyState` | `({ hasActiveFilters, table }) => ReactNode` | – | Replaces both built-in empty messages. See [Loading and empty states](/docs/loading-and-empty). |
94
+ | `cellExport` | `TMDataGridCellExportOptions` | – | Deprecated. Set `exportOptions` on `useTMDataGrid` instead; until it goes, it is merged over that for the cell-range menu only. See [Export](/docs/export). |
95
+ | `aria-label` · `aria-labelledby` | `string` | – | The grid's accessible name, announced on entry and matched by `getByRole("grid", { name })`. |
96
+
97
+ Note that `onReachEnd` and `enablePagination` slice the same scroll: the pager caps the rows, so the end reached is the page's.
98
+ Setting both logs a warning.
99
+
100
+ ## TMDataGrid.Toolbar
101
+
102
+ A flex row above the grid. See [Toolbar](/docs/toolbar).
103
+
104
+ | Prop | Type | Default | Description |
105
+ | --- | --- | --- | --- |
106
+ | `children` | `ReactNode` | – | The toolbar's contents, in render order. |
107
+ | `withBottomBorder` | `boolean` | `false` | A 1px bottom border in the theme's default border colour, the line the header draws under itself. |
108
+ | Mantine `BoxProps` | | – | Style props (`mb`, `px`, `hiddenFrom`, …), `className`, `style` and `mod`, set on the row. |
109
+
110
+ ## TMDataGrid.Spacer
111
+
112
+ Pushes the toolbar items after it to the right.
113
+
114
+ | Prop | Type | Default | Description |
115
+ | --- | --- | --- | --- |
116
+ | Mantine `BoxProps` | | – | Style props, `className` and `style`, set on the spacer. |
117
+
118
+ ## TMDataGrid.Search
119
+
120
+ A debounced quick-search input that writes the grid's global filter.
121
+ It renders nothing when no column is searchable. See [Quick search](/docs/quick-search).
122
+
123
+ | Prop | Type | Default | Description |
124
+ | --- | --- | --- | --- |
125
+ | `placeholder` | `string` | `labels.searchPlaceholder` | Placeholder text. |
126
+ | `debounce` | `number` | `250` | Milliseconds between the last keystroke and the filter being written. |
127
+ | `w` | `number \| string` | `220` | Width of the input. |
128
+
129
+ ## The filter parts
130
+
131
+ Filtering owns these three, so their props are on that page rather than repeated here.
132
+
133
+ | Component | What it is | Props |
134
+ | --- | --- | --- |
135
+ | `TMDataGrid.FilterButton` | Toggles the filter surface, tinted with the count of active filters. Renders nothing when no column can be filtered, and nothing under `filters.surface: "none"`. | None. [Filtering](/docs/filtering#tmdatagridfilterbutton) |
136
+ | `TMDataGrid.FilterPanel` | The filter rows, as a plain block with no title, no close button and no open state - the popup and sidebar [surfaces](/docs/filtering#the-filters-option) wrap it. | `layout`, Mantine `BoxProps`. [Filtering](/docs/filtering#tmdatagridfilterpanel) |
137
+ | `TMDataGrid.FilterPills` · `TMDataGridFilterPills` | One pill per active filter. Takes the grid as an `api` prop rather than from context, so it renders anywhere on the page. | `api`, `size`, `showClearAll`, `onPillClick`, `className`. [Filtering](/docs/filtering#tmdatagridfilterpills) |
138
+
139
+ `openColumnFilter(api, columnId)` sends the user to a column's filter control; it is documented with them, on [Filtering](/docs/filtering#opencolumnfilter).
140
+
141
+ ## TMDataGrid.Menu
142
+
143
+ The burger at the end of the toolbar and the Mantine `Menu` it opens.
144
+ Its children are the dropdown. See [Grid menu](/docs/menu).
145
+
146
+ | Prop | Type | Default | Description |
147
+ | --- | --- | --- | --- |
148
+ | `children` | `ReactNode` | – | The dropdown: your own `Menu.Item`s and the `TMDataGrid.Menu.*` items. |
149
+ | `icon` | `ReactNode` | The burger | The trigger's icon. |
150
+ | `label` | `string` | `labels.menuButton` | The trigger's tooltip and `aria-label`. |
151
+ | Mantine `MenuProps` | | `position="bottom-end"`, `shadow="md"`, `width={260}`, `withinPortal` | Passed to the `Menu`. |
152
+
153
+ `TMDataGrid.Menu.Columns`, `.ColumnToggles`, `.ShowHideAll` and `.ResetLayout` are the column chooser as menu items, for this menu or any Mantine `Menu` inside the grid.
154
+ `Columns` takes `searchable` (default `"auto"`, a search box from six columns), `ColumnToggles` takes `search`; the other two take no props.
155
+
156
+ ## TMDataGrid.ColumnsPanel
157
+
158
+ The column chooser as plain controls: a checkbox list of the hideable columns, a search box once there are six of them, a show-all toggle and a reset button.
159
+ For a Popover, a Drawer or an inline layout; `TMDataGrid.Menu.Columns` is the same thing as menu items.
160
+
161
+ | Prop | Type | Default | Description |
162
+ | --- | --- | --- | --- |
163
+ | `searchable` | `boolean \| "auto"` | `"auto"` | The search box over the list. `"auto"` shows it from six columns, `true` always, `false` never. |
164
+ | Mantine `BoxProps` | | – | Style props (`w`, `p`, …), `className` and `style`, set on the panel block. |
165
+
166
+ ## TMDataGrid.LoadingIndicator
167
+
168
+ A spinner, shown while `meta.loading` is `true`. See [Loading and empty states](/docs/loading-and-empty).
169
+
170
+ No props.
171
+
172
+ ## TMDataGrid.SummaryCount
173
+
174
+ The row count, as shown over total.
175
+ The total comes from `meta.totalRowCount` when set, and from the unfiltered row count otherwise.
176
+ While a column is grouped the shown count includes the group rows and the total keeps counting records, so `42 / 42` reads `48 / 42` under six groups; pass `children` to show a count of your own.
177
+
178
+ | Prop | Type | Default | Description |
179
+ | --- | --- | --- | --- |
180
+ | `children` | `ReactNode` | – | Replaces the count with your own text. |
181
+
182
+ ## TMDataGrid.DraftActions
183
+
184
+ Save and Discard for pending edits.
185
+ It renders nothing unless `editing` is set. See [Editing](/docs/editing).
186
+
187
+ | Prop | Type | Default | Description |
188
+ | --- | --- | --- | --- |
189
+ | `renderActions` | `(args: TMDataGridDraftActionsSlotArgs) => ReactNode` | – | Replaces both buttons. Receives `{ state, actions, Controls }`. |
190
+
191
+ The slot argument carries the state, the operations and the built-in pieces:
192
+
193
+ | Field | Type | What it is |
194
+ | --- | --- | --- |
195
+ | `state.draftCount` | `number` | Rows in the draft store: committed edits, committed entry rows and deletion marks. This is what Save sends. |
196
+ | `state.openCount` | `number` | Rows still open, so not part of the save. |
197
+ | `state.openRowIds` | `ReadonlyArray<string>` | The ids behind `openCount`, in the order the grid opened them. An entered row appears as its `tempId`. |
198
+ | `state.pendingCount` | `number` | **Deprecated.** Reads as `draftCount + openCount`. |
199
+ | `state.isSubmitting` | `boolean` | `true` while any open row is submitting. Not the save; see `state.isSaving`. |
200
+ | `state.isSaving` | `boolean` | `true` while `saveDrafts` is in flight, until the consumer's callbacks settle. The built-in Save shows it as its loading state. |
201
+ | `actions.save` | `() => Promise<boolean>` | Sends the draft store. Open rows are left alone. |
202
+ | `actions.commitAll` | `() => Promise<boolean>` | Submits every open row, committing the ones that validate. |
203
+ | `actions.discard` | `() => void` | Drops open form state and the draft store alike. |
204
+ | `actions.scrollToRow` | `({ rowId, align? }) => boolean` | [`scrollToRow`](/docs/scrolling#scrolling-to-a-row), passed through. |
205
+ | `actions.scrollToFirstOpenRow` | `(align?) => boolean` | Scrolls to the first open row in display order. `false` when none could be reached. |
206
+ | `Controls.Save` · `Controls.Discard` · `Controls.OpenRowsNote` | `() => ReactNode` | The built-in pieces, to place in your own layout. |
207
+
208
+ The two orderings differ: `openRowIds` is the order the grid opened the rows,
209
+ while `scrollToFirstOpenRow` takes "first" in display order, so it follows the
210
+ current sort, filter and page. `openRowIds[0]` need not be the row it reaches.
211
+
212
+ ## TMDataGrid.Footer
213
+
214
+ The pager bar: rows per page, the current range, and previous and next.
215
+ It renders nothing when pagination is off. See [Pagination](/docs/pagination).
216
+
217
+ | Prop | Type | Default | Description |
218
+ | --- | --- | --- | --- |
219
+ | `pageSizeOptions` | `ReadonlyArray<number>` | `[10, 25, 50, 100]` | The choices in the rows-per-page select. |
220
+ | `renderPagination` | `(args: TMDataGridPaginationSlotArgs) => ReactNode` | – | Replaces the pager. Receives `{ state, actions, Controls }`. |
221
+ | Mantine `BoxProps` | | – | Style props (`mt`, `px`, …), `className` and `style`, set on the footer bar. |
222
+
223
+ The slot argument holds the paging state, its operations and the built-in controls:
224
+
225
+ | Field | Type | What it is |
226
+ | --- | --- | --- |
227
+ | `state` | `TMDataGridPaginationState` | `pageIndex`, `pageSize`, `pageCount`, `rowCount`, `canPreviousPage`, `canNextPage`, `isPagingActive`, and the 1-based `from` and `to`. |
228
+ | `actions` | `TMDataGridPaginationActions` | `setPageIndex`, `setPageSize`, `previousPage`, `nextPage`, `firstPage`, `lastPage`. |
229
+ | `Controls.PageSize` · `Controls.Range` · `Controls.Pager` | `() => ReactNode` | The three built-in controls, to place in your own layout. |
230
+
231
+ `pageCount` is `-1` when a manual grid declares an unknown total, and `isPagingActive` is `false` while a grouping suspends paging.
232
+ `getTMDataGridPaginationApi(table, isPaging?)` returns the same `state` and `actions` for a pager built outside the grid.
233
+
234
+ ## Editors
235
+
236
+ The control a cell opens for editing.
237
+ The grid picks one from the column's `meta.type`, and `meta.edit.editor` replaces it. See [Editors and validation](/docs/editors).
238
+
239
+ | Component | Renders | Used for `meta.type` |
240
+ | --- | --- | --- |
241
+ | `TMDataGridStringEditor` | Mantine `TextInput` | `"string"` |
242
+ | `TMDataGridNumberEditor` | `NumberInput`, writing `null` for an empty cell | `"number"` |
243
+ | `TMDataGridBooleanEditor` | `Checkbox` | `"boolean"` |
244
+ | `TMDataGridDateEditor` | `TextInput` with `type="date"` | `"date"` |
245
+ | `TMDataGridSelectEditor` | `Select`, committing on pick in `"cell"` mode | `"select"` |
246
+ | `TMDataGridMultiSelectEditor` | `MultiSelect`, committing on Enter or blur | `"multiSelect"` |
247
+
248
+ Every editor takes the same argument object, `TMDataGridEditorArgs`, so a custom editor can wrap a built-in rather than replace it:
249
+
250
+ | Field | Type | What it is |
251
+ | --- | --- | --- |
252
+ | `field` | `TMDataGridEditField` | The TanStack Form field for this cell. |
253
+ | `form` | `TMDataGridRowEditForm` | The whole row form, for an editor that reads sibling fields. |
254
+ | `cell` · `row` · `column` · `table` | TanStack instances | The cell being edited and its surroundings. |
255
+ | `commit` | `() => Promise<boolean>` | Commits the edit, as Enter would. |
256
+ | `cancel` | `() => void` | Drops the draft, as Escape would. |
257
+ | `size` | `TMDataGridSize` | The grid's resolved control size. |
258
+ | `seedText` | `string \| undefined` | Set when typing opened the editor. |
259
+
260
+ ## Filter controls
261
+
262
+ The value control in a filter row.
263
+ The grid picks one from the column's `meta.type` and the current operator, and `meta.filter.control` replaces it. See [Filtering](/docs/filtering).
264
+
265
+ | Component | Renders | Suits |
266
+ | --- | --- | --- |
267
+ | `TMDataGridFilterValueInput` | A text input, a multi-select, a boolean select or a from/to pair, by operator | Every column. This is the default. |
268
+ | `DgRangeSliderFilter` | `RangeSlider` bounded by the values in the data | `number` columns with `between` |
269
+ | `DgDateRangeFilter` | Two `type="date"` inputs | `date` columns with `between` |
270
+ | `DgAutocompleteFilter` | `Autocomplete` over the column's values | Text columns with a scalar operator |
271
+ | `DgTriStateFilter` | `SegmentedControl` of all, true and false | `boolean` columns |
272
+
273
+ Each of the four specialised controls falls back to `TMDataGridFilterValueInput` for the operators it does not handle.
274
+ Every control takes the same argument object, `TMDataGridFilterControlArgs`:
275
+
276
+ | Field | Type | What it is |
277
+ | --- | --- | --- |
278
+ | `column` · `table` | TanStack instances | The column being filtered, and the table. |
279
+ | `operator` | `TMDataGridFilterOperator` | The row's selected operator. A control reads it and never writes it. |
280
+ | `value` | `string \| ReadonlyArray<string>` | The bare filter value, never the `{ operator, value }` wrapper. |
281
+ | `onChange` | `(next: string \| ReadonlyArray<string>) => void` | Writes the bare value. The grid pairs it with the current operator. |
282
+ | `options` | `ReadonlyArray<TMDataGridOption>` | The column's options, resolved for a column declaring `meta.options` or a select type. Empty otherwise. |
283
+ | `size` | `TMDataGridSize` | The grid's resolved control size. |
284
+ | `labels` | `TMDataGridLabels` | The resolved dictionary. |
285
+
286
+ ## Reference
287
+
288
+ | Name | Kind | Type | Default | What it does |
289
+ | --- | --- | --- | --- | --- |
290
+ | `useTMDataGrid` | Hook | `(options) => TMDataGridApi` | – | Creates the table, UI store and edit engine. |
291
+ | `useTMDataGridContext` | Hook | `() => TMDataGridContextValue` | – | The grid, from inside any part. Throws outside `TMDataGrid`. |
292
+ | `TMDataGrid` | Component | – | – | The root element. Provides the grid through context. |
293
+ | `TMDataGrid.Table` | Component | – | – | Header, virtualized body and filter panel. |
294
+ | `TMDataGrid.Toolbar` · `.Spacer` | Components | – | – | The toolbar row, and the gap that pushes items right. |
295
+ | `TMDataGrid.Search` | Component | – | – | Quick search input. Also `TMDataGridSearch`. |
296
+ | `TMDataGrid.FilterButton` · `.FilterPanel` | Components | – | – | The filter UI. Props on [Filtering](/docs/filtering). |
297
+ | `TMDataGrid.Menu` · `.ColumnsPanel` | Components | – | – | The burger menu, and the column chooser as plain controls. |
298
+ | `TMDataGrid.LoadingIndicator` · `.SummaryCount` | Components | – | – | Fetch spinner, and the row count. |
299
+ | `TMDataGrid.DraftActions` | Component | – | – | Save and Discard. Also `TMDataGridDraftActions`. |
300
+ | `TMDataGrid.Footer` | Component | – | – | The pager bar. |
301
+ | `TMDataGrid.FilterPills` | Component | – | – | Active filters as pills. Also `TMDataGridFilterPills`. Props on [Filtering](/docs/filtering). |
302
+ | `openColumnFilter` | Export | `(api, columnId) => void` | – | Sends the user to a column's filter control. See [Filtering](/docs/filtering#opencolumnfilter). |
303
+ | `getTMDataGridPaginationApi` | Function | `(table, isPaging?) => TMDataGridPaginationApi` | `isPaging`: `true` | Paging state and actions for a pager of your own. |
304
+ | `DEFAULT_EXPORT_OPTIONS` | Constant | `TMDataGridExportSettings` | – | The export defaults `exportOptions` merges over. See [Export](/docs/export). |