@jielga/tmdatagrid 2.0.0-beta.9 → 2.0.1

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 (157) hide show
  1. package/README.md +5 -212
  2. package/dist/index.d.ts +1281 -768
  3. package/dist/index.js +4607 -3250
  4. package/dist/index.js.map +1 -1
  5. package/dist/styles.css +1 -1
  6. package/docs/adding-rows.md +132 -0
  7. package/docs/anatomy.md +119 -0
  8. package/docs/card-view.md +108 -0
  9. package/docs/cell-selection.md +194 -0
  10. package/docs/column-layout.md +182 -0
  11. package/docs/column-menu.md +66 -0
  12. package/docs/columns.md +269 -0
  13. package/docs/components.md +311 -0
  14. package/docs/draft-store.md +242 -0
  15. package/docs/editing.md +303 -0
  16. package/docs/editors.md +250 -0
  17. package/docs/export.md +319 -0
  18. package/docs/filtering.md +362 -0
  19. package/docs/getting-started.md +123 -0
  20. package/docs/grouping.md +165 -0
  21. package/docs/loading-and-empty.md +92 -0
  22. package/docs/localization.md +79 -0
  23. package/docs/menu.md +143 -0
  24. package/docs/migrating-to-2.md +163 -0
  25. package/docs/pagination.md +144 -0
  26. package/docs/persistence.md +114 -0
  27. package/docs/portfolio-rebalancer.md +94 -0
  28. package/docs/query-builder.md +179 -0
  29. package/docs/quick-search.md +84 -0
  30. package/docs/row-details.md +115 -0
  31. package/docs/row-interaction.md +149 -0
  32. package/docs/row-pinning.md +132 -0
  33. package/docs/row-selection.md +136 -0
  34. package/docs/row-styling.md +133 -0
  35. package/docs/scrolling.md +112 -0
  36. package/docs/server-query.md +246 -0
  37. package/docs/server-side.md +206 -0
  38. package/docs/sorting.md +101 -0
  39. package/docs/styling.md +126 -0
  40. package/docs/summary-row.md +76 -0
  41. package/docs/testing.md +744 -0
  42. package/docs/toolbar.md +161 -0
  43. package/docs/use-tm-data-grid.md +361 -0
  44. package/package.json +22 -46
  45. package/skills/appearance/SKILL.md +72 -19
  46. package/skills/cell-selection/SKILL.md +49 -48
  47. package/skills/columns/SKILL.md +125 -70
  48. package/skills/columns/references/columns-api.md +59 -0
  49. package/skills/data/SKILL.md +112 -18
  50. package/skills/editing/SKILL.md +76 -42
  51. package/skills/editing/references/common-mistakes.md +77 -69
  52. package/skills/editing/references/editing-api.md +25 -20
  53. package/skills/editing/references/editors-and-validation.md +80 -18
  54. package/skills/filtering/SKILL.md +155 -41
  55. package/skills/getting-started/SKILL.md +116 -16
  56. package/skills/grouping/SKILL.md +31 -16
  57. package/skills/migrating-to-2/SKILL.md +244 -0
  58. package/skills/options/SKILL.md +24 -12
  59. package/skills/rows/SKILL.md +22 -18
  60. package/skills/rows/references/rows-api.md +10 -6
  61. package/skills/server-side/SKILL.md +170 -17
  62. package/skills/testing/SKILL.md +150 -32
  63. package/skills/testing-components/SKILL.md +230 -0
  64. package/skills/testing-editing/SKILL.md +240 -0
  65. package/src/{tmdatagrid/components → components}/TMDataGrid.tsx +38 -21
  66. package/src/{tmdatagrid/components → components}/TMDataGridCellEditor.tsx +54 -8
  67. package/src/{tmdatagrid/components → components}/TMDataGridColumnsPanel.module.css +5 -1
  68. package/src/{tmdatagrid/components → components}/TMDataGridColumnsPanel.tsx +47 -55
  69. package/src/{tmdatagrid/components → components}/TMDataGridDetailsColumn.tsx +5 -51
  70. package/src/{tmdatagrid/components → components}/TMDataGridDraftActions.tsx +41 -24
  71. package/src/{tmdatagrid/components → components}/TMDataGridEditColumn.tsx +12 -59
  72. package/src/{tmdatagrid/components → components}/TMDataGridEntryRows.tsx +164 -92
  73. package/src/components/TMDataGridExportPicker.module.css +77 -0
  74. package/src/components/TMDataGridExportPicker.tsx +234 -0
  75. package/src/components/TMDataGridFilterPanel.module.css +54 -0
  76. package/src/components/TMDataGridFilterPanel.tsx +348 -0
  77. package/src/{tmdatagrid/components → components}/TMDataGridFilterPills.tsx +15 -8
  78. package/src/components/TMDataGridFilterSurface.module.css +54 -0
  79. package/src/components/TMDataGridFilterSurface.tsx +167 -0
  80. package/src/{tmdatagrid/components → components}/TMDataGridFooter.tsx +53 -90
  81. package/src/{tmdatagrid/components → components}/TMDataGridGroupColumn.tsx +5 -69
  82. package/src/{tmdatagrid/components → components}/TMDataGridHeaderCell.module.css +12 -2
  83. package/src/{tmdatagrid/components → components}/TMDataGridHeaderCell.tsx +58 -21
  84. package/src/components/TMDataGridHeaderFilterRow.module.css +51 -0
  85. package/src/components/TMDataGridHeaderFilterRow.tsx +301 -0
  86. package/src/components/TMDataGridMenu.tsx +357 -0
  87. package/src/{tmdatagrid/components → components}/TMDataGridSelectColumn.tsx +11 -48
  88. package/src/{tmdatagrid/components → components}/TMDataGridTable.module.css +69 -56
  89. package/src/{tmdatagrid/components → components}/TMDataGridTable.tsx +240 -138
  90. package/src/{tmdatagrid/components → components}/TMDataGridToolbar.module.css +5 -0
  91. package/src/components/TMDataGridToolbar.tsx +181 -0
  92. package/src/{tmdatagrid/components → components}/editors/TMDataGridBooleanEditor.tsx +3 -3
  93. package/src/{tmdatagrid/components → components}/editors/TMDataGridDateEditor.tsx +3 -3
  94. package/src/{tmdatagrid/components → components}/editors/TMDataGridMultiSelectEditor.tsx +3 -3
  95. package/src/{tmdatagrid/components → components}/editors/TMDataGridNumberEditor.tsx +3 -3
  96. package/src/{tmdatagrid/components → components}/editors/TMDataGridSelectEditor.tsx +3 -3
  97. package/src/{tmdatagrid/components → components}/editors/TMDataGridStringEditor.tsx +3 -3
  98. package/src/{tmdatagrid/components → components}/editors/editorShared.ts +16 -2
  99. package/src/{tmdatagrid/components → components}/filters/DgAutocompleteFilter.tsx +5 -4
  100. package/src/{tmdatagrid/components → components}/filters/DgDateRangeFilter.tsx +22 -5
  101. package/src/{tmdatagrid/components → components}/filters/DgRangeSliderFilter.tsx +5 -1
  102. package/src/{tmdatagrid/components → components}/filters/DgTriStateFilter.tsx +5 -1
  103. package/src/{tmdatagrid/components → components}/filters/TMDataGridFilterValueInput.tsx +44 -28
  104. package/src/components/filters/controlLayout.ts +32 -0
  105. package/src/components/filters/filterControlFor.ts +65 -0
  106. package/src/components/generatedColumns.tsx +187 -0
  107. package/src/{tmdatagrid/components → components}/icons.ts +1 -0
  108. package/src/{tmdatagrid/components → components}/sticky.module.css +44 -0
  109. package/src/components/useHideableColumns.ts +52 -0
  110. package/src/{tmdatagrid/core → core}/autosize.ts +5 -2
  111. package/src/{tmdatagrid/core → core}/columnOptions.ts +60 -8
  112. package/src/{tmdatagrid/core → core}/columnOrdering.ts +33 -14
  113. package/src/{tmdatagrid/core → core}/columnUtils.ts +44 -5
  114. package/src/core/controlledStateSync.ts +108 -0
  115. package/src/core/deletedRows.ts +34 -0
  116. package/src/core/dom.ts +74 -0
  117. package/src/{tmdatagrid/core → core}/editEngine.ts +1107 -460
  118. package/src/core/export.ts +704 -0
  119. package/src/{tmdatagrid/core → core}/filterControls.ts +38 -1
  120. package/src/{tmdatagrid/core → core}/filterOperators.ts +64 -1
  121. package/src/core/filterSurface.ts +99 -0
  122. package/src/{tmdatagrid/core → core}/grouping.ts +21 -0
  123. package/src/{tmdatagrid/core → core}/labels.ts +51 -6
  124. package/src/{tmdatagrid/core → core}/labelsSv.ts +27 -6
  125. package/src/core/pageReset.ts +120 -0
  126. package/src/core/pagination.ts +81 -0
  127. package/src/{tmdatagrid/core → core}/persistence.ts +22 -5
  128. package/src/{tmdatagrid/core → core}/summary.ts +20 -4
  129. package/src/{tmdatagrid/index.ts → index.ts} +69 -35
  130. package/src/{tmdatagrid/useTMDataGrid.tsx → useTMDataGrid.tsx} +428 -109
  131. package/src/useTMDataGridExport.ts +78 -0
  132. package/src/tmdatagrid/components/TMDataGridFilterPanel.module.css +0 -35
  133. package/src/tmdatagrid/components/TMDataGridFilterPanel.tsx +0 -354
  134. package/src/tmdatagrid/components/TMDataGridToolbar.tsx +0 -161
  135. package/src/tmdatagrid/core/cellExport.ts +0 -320
  136. /package/src/{tmdatagrid/TMDataGridContext.ts → TMDataGridContext.ts} +0 -0
  137. /package/src/{tmdatagrid/components → components}/TMDataGrid.module.css +0 -0
  138. /package/src/{tmdatagrid/components → components}/TMDataGridDetailsColumn.module.css +0 -0
  139. /package/src/{tmdatagrid/components → components}/TMDataGridFilterPills.module.css +0 -0
  140. /package/src/{tmdatagrid/components → components}/TMDataGridFooter.module.css +0 -0
  141. /package/src/{tmdatagrid/components → components}/TMDataGridGroupColumn.module.css +0 -0
  142. /package/src/{tmdatagrid/components → components}/TMDataGridRowNumberColumn.tsx +0 -0
  143. /package/src/{tmdatagrid/components → components}/TMDataGridSearch.tsx +0 -0
  144. /package/src/{tmdatagrid/core → core}/capabilities.ts +0 -0
  145. /package/src/{tmdatagrid/core → core}/cellNavigation.ts +0 -0
  146. /package/src/{tmdatagrid/core → core}/cellRange.ts +0 -0
  147. /package/src/{tmdatagrid/core → core}/controlledState.ts +0 -0
  148. /package/src/{tmdatagrid/core → core}/draftCellContext.ts +0 -0
  149. /package/src/{tmdatagrid/core → core}/editorFocus.ts +0 -0
  150. /package/src/{tmdatagrid/core → core}/expanding.ts +0 -0
  151. /package/src/{tmdatagrid/core → core}/matchHighlight.ts +0 -0
  152. /package/src/{tmdatagrid/core → core}/quickSearch.ts +0 -0
  153. /package/src/{tmdatagrid/core → core}/resizePreview.ts +0 -0
  154. /package/src/{tmdatagrid/core → core}/rowPinning.ts +0 -0
  155. /package/src/{tmdatagrid/core → core}/rowSelection.ts +0 -0
  156. /package/src/{tmdatagrid/core → core}/sizes.ts +0 -0
  157. /package/src/{tmdatagrid/core → core}/useSettledTableState.ts +0 -0
@@ -4,26 +4,26 @@ description: >
4
4
  Define and arrange TMDataGrid columns. Covers createTMDataGridColumnHelper,
5
5
  every column meta field (label, type, options, flex, align, autoSize,
6
6
  enableOrdering, and the meta.filter and meta.edit namespaces holding
7
- defaultOperator, control, enabled, field, editor, validate and mapValue), the
8
- six column types, fluid minmax sizing versus fixed width with minSize /
9
- maxSize / size, autosizing and autosizeColumn, hiding through enableHiding and
10
- the columns panel, pinning and why a pinned column becomes fixed-width,
11
- ordering with enableColumnOrdering, meta.enableOrdering, moveColumn,
12
- moveColumnByStep, getStepTargetColumn and the pinned regions, resetSettings,
13
- sorting with multi-sort through isMultiSortEvent and a custom sortFn, and the
14
- generated lanes. Load when adding or changing columns, controlling widths,
15
- hiding, pinning, reordering or sorting them.
7
+ operators, defaultOperator, control, enabled, field, editor, validate and
8
+ mapValue), the six column types, fluid minmax sizing versus fixed width with
9
+ minSize / maxSize / size, autosizing and autosizeColumn, hiding through
10
+ enableHiding and the columns panel, pinning and why a pinned column becomes
11
+ fixed-width, ordering with enableColumnOrdering, meta.enableOrdering,
12
+ moveColumn, moveColumnByStep, getStepTargetColumn and the pinned regions,
13
+ resetSettings, sorting with multi-sort through isMultiSortEvent and a custom
14
+ sortFn, and the generated lanes. Load when adding or changing columns,
15
+ controlling widths, hiding, pinning, reordering or sorting them.
16
16
  metadata:
17
17
  type: core
18
18
  library: '@jielga/tmdatagrid'
19
- library_version: '2.0.0-beta.9'
19
+ library_version: '2.0.1'
20
20
  sources:
21
- - 'Jielga/TMDataGrid:src/docs/columns.md'
22
- - 'Jielga/TMDataGrid:src/docs/column-layout.md'
23
- - 'Jielga/TMDataGrid:src/docs/sorting.md'
24
- - 'Jielga/TMDataGrid:src/tmdatagrid/core/columnUtils.ts'
25
- - 'Jielga/TMDataGrid:src/tmdatagrid/core/columnOrdering.ts'
26
- - 'Jielga/TMDataGrid:src/tmdatagrid/core/autosize.ts'
21
+ - 'Jielga/TMDataGrid:packages/tmdatagrid/docs/columns.md'
22
+ - 'Jielga/TMDataGrid:packages/tmdatagrid/docs/column-layout.md'
23
+ - 'Jielga/TMDataGrid:packages/tmdatagrid/docs/sorting.md'
24
+ - 'Jielga/TMDataGrid:packages/tmdatagrid/src/core/columnUtils.ts'
25
+ - 'Jielga/TMDataGrid:packages/tmdatagrid/src/core/columnOrdering.ts'
26
+ - 'Jielga/TMDataGrid:packages/tmdatagrid/src/core/autosize.ts'
27
27
  ---
28
28
 
29
29
  # TMDataGrid - Columns
@@ -93,22 +93,9 @@ What the column **is** stays flat; what the filter panel and the edit engine do
93
93
  with it sits in their namespaces. `type` and `options` are read by both stages,
94
94
  which is why they are in neither.
95
95
 
96
- `meta.filter`:
97
-
98
- | Field | Type | Default | What it does |
99
- | --- | --- | --- | --- |
100
- | `defaultOperator` | `TMDataGridFilterOperator` | The type's default | The operator a fresh filter on this column starts with. |
101
- | `control` | `TMDataGridFilterControlComponent` | By `meta.type` | Replaces the value control in this column's filter row. Module scope. |
102
-
103
- `meta.edit`:
104
-
105
- | Field | Type | Default | What it does |
106
- | --- | --- | --- | --- |
107
- | `enabled` | `boolean \| ((row) => boolean)` | editable where a field maps | Whether this column's cells edit. |
108
- | `field` | `string` | The `accessorKey` | The data path an edit writes to. The only way an `accessorFn` column edits. |
109
- | `editor` | `TMDataGridEditorComponent` | By `meta.type` | Replaces the cell editor. Module scope. |
110
- | `validate` | `TMDataGridFieldValidate` | – | Field-level validation. A bare schema means `onChange`. |
111
- | `mapValue` | `TMDataGridEditValueMap` | – | Maps each value an editor writes, on every keystroke. |
96
+ `meta.filter` holds `operators`, `defaultOperator` and `control`; `meta.edit`
97
+ holds `enabled`, `field`, `editor`, `validate` and `mapValue`. Their fields are
98
+ in [references/columns-api.md](references/columns-api.md).
112
99
 
113
100
  ```tsx
114
101
  meta: {
@@ -118,6 +105,14 @@ meta: {
118
105
  }
119
106
  ```
120
107
 
108
+ The type of `meta` is `TMDataGridColumnMeta<TData>`. On a column declared with
109
+ `createTMDataGridColumnHelper<TData>()`, the `row` that a `meta.options`
110
+ function and a `meta.edit.enabled` function receive is
111
+ `Row<TMDataGridFeatures, TData>`, so `row.original` needs no cast and no
112
+ annotation. A column written without the helper keeps the untyped row,
113
+ `Row<TMDataGridFeatures, TMDataGridRowData>`, where `row.original` is
114
+ `Record<string, unknown>`.
115
+
121
116
  `enableOrdering` lives in `meta` because column ordering is the one feature
122
117
  TanStack defines no column option for. `meta.edit` only acts once `editing` is
123
118
  set: see the `editing` skill. `meta.filter` belongs to the `filtering` skill.
@@ -140,6 +135,28 @@ columnHelper.accessor("department", {
140
135
  Dates travel as ISO `YYYY-MM-DD` strings and booleans as `"true"` / `"false"`,
141
136
  so the filter model stays plain JSON whatever the type.
142
137
 
138
+ ### meta.options
139
+
140
+ `meta.options` is a list of `TMDataGridOption`s
141
+ (`{ value, label?, color?, disabled?, group? }`) or bare strings, `"faceted"`
142
+ for the distinct values in the data, or a function of `TMDataGridOptionsArgs`
143
+ (`{ table, column, row? }`). `row` is set when a cell editor asks and absent for
144
+ the filter panel:
145
+
146
+ ```tsx
147
+ meta: {
148
+ type: "select",
149
+ options: ({ row }) => (row ? citiesFor(row.original.country) : allCities),
150
+ }
151
+ ```
152
+
153
+ `resolveColumnOptions({ table, column, row? })` normalises all three forms into
154
+ `Array<TMDataGridOption>` for a custom control, and `optionsToComboboxData`
155
+ turns that list into Mantine `Select` / `MultiSelect` data. A select column with
156
+ no options still filters, on the faceted values.
157
+
158
+ Source: `packages/tmdatagrid/docs/columns.md` (Options).
159
+
143
160
  ## Sizing
144
161
 
145
162
  Columns are fluid. Each track is `minmax(minSize, flex fr)`.
@@ -174,21 +191,26 @@ consumer code.
174
191
 
175
192
  All three write state that persists together, so a grid comes back arranged the
176
193
  way it was left. `resetSettings()` from the hook clears visibility, order,
177
- pinning and widths in one go, and the columns panel offers it as **Reset
194
+ pinning and widths in one go, and the column chooser offers it as **Reset
178
195
  layout**.
179
196
 
180
197
  **Hiding** is `columnVisibility`, driven by "Hide column" in a column menu and by
181
- `TMDataGrid.ColumnsButton` with the panel behind it.
198
+ the column chooser: `TMDataGrid.Menu.Columns` in the grid menu, **Manage
199
+ columns** as a submenu of every column menu, and `TMDataGrid.ColumnsPanel` as
200
+ plain controls for a host that is not a menu. See the `appearance` skill.
182
201
 
183
202
  **Pinning** is "Pin to left" / "Pin to right" in the column menu. A pinned
184
203
  column also becomes fixed-width: sticky offsets are computed from `getSize()`,
185
204
  which cannot resolve an `fr` value, so the grid stores the rendered width in
186
- `columnSizing` at the moment it is pinned and nothing jumps.
205
+ `columnSizing` at the moment it is pinned and nothing jumps. A column pinned
206
+ from `initialState.columnPinning` has no rendered width to store, so it takes
207
+ its `size` - TanStack's default of `150` where none is set - and `minSize`
208
+ does not apply.
187
209
 
188
210
  **Ordering** is header dragging plus "Move left" / "Move right". A column can
189
211
  only move **within its own pinned region** - pinning splits the grid into left,
190
212
  centre and right, then `columnOrder` sequences the centre while
191
- `columnPinning.left` and `.right` sequence the pinned lanes. Unpin a column
213
+ `columnPinning.start` and `.end` sequence the pinned lanes. Unpin a column
192
214
  first to move it out of one. A neighbour that cannot move acts as a wall rather
193
215
  than being stepped over, and columns inside a header group are not movable in
194
216
  either direction, because `columnOrder` sequences leaf columns.
@@ -244,7 +266,7 @@ Standard TanStack column options. Each also removes the corresponding interface.
244
266
  | Option | Effect when `false` |
245
267
  | --- | --- |
246
268
  | `enableSorting` | No sort indicator, no sort menu items, no click-to-sort. |
247
- | `enableColumnFilter` | No filter menu item. Excluded from the filter panel's column list. |
269
+ | `enableColumnFilter` | No filter menu item. Excluded from the filter panel's column list, and its header filter cell is empty. |
248
270
  | `enableHiding` | No hide menu item. Checkbox disabled in the column manager. |
249
271
  | `enablePinning` | No pin menu items. |
250
272
  | `enableResizing` | The divider is displayed but cannot be dragged. |
@@ -270,7 +292,7 @@ asks for it.
270
292
 
271
293
  They are structural: fixed width, no column menu, and they cannot be sorted,
272
294
  filtered, resized, re-pinned or moved. The checkbox lane anchors the left pinned
273
- region, so no column can be placed in front of it. `isControlColumn(column)`
295
+ region, so no column can be placed in front of it. `isControlColumn(columnId)`
274
296
  identifies them.
275
297
 
276
298
  ## Common mistakes
@@ -299,7 +321,33 @@ columnHelper.accessor("email", {
299
321
  });
300
322
  ```
301
323
 
302
- Source: `src/docs/column-layout.md` (Sizing).
324
+ The corollary is that a pinned column is fixed-width and does use `size`, so a
325
+ column that is pinned needs one.
326
+
327
+ Source: `packages/tmdatagrid/docs/column-layout.md` (Sizing).
328
+
329
+ ### HIGH Pinning a column at mount without size
330
+
331
+ A column pinned interactively keeps the width it was rendering, which the grid
332
+ writes into `columnSizing`. A column pinned from `initialState.columnPinning`
333
+ has no rendered width, so it takes `size` - TanStack's default of `150` where
334
+ none is set - and `minSize` does not apply.
335
+
336
+ Wrong:
337
+
338
+ ```tsx
339
+ columnHelper.accessor("name", { header: "Name", minSize: 220 });
340
+ initialState: { columnPinning: { start: ["name"], end: [] } },
341
+ ```
342
+
343
+ Correct:
344
+
345
+ ```tsx
346
+ columnHelper.accessor("name", { header: "Name", minSize: 220, size: 220 });
347
+ initialState: { columnPinning: { start: ["name"], end: [] } },
348
+ ```
349
+
350
+ Source: `packages/tmdatagrid/docs/column-layout.md` (Pinning).
303
351
 
304
352
  ### HIGH Addressing a dotted column by its accessor key
305
353
 
@@ -321,7 +369,7 @@ initialState: { columnVisibility: { address_city: false } },
321
369
  The edit path is the exception: `meta.edit.field` and validation issue paths
322
370
  stay dotted, because they address the data, not the column.
323
371
 
324
- Source: `src/docs/columns.md` (The column helper).
372
+ Source: `packages/tmdatagrid/docs/columns.md` (The column helper).
325
373
 
326
374
  ### CRITICAL A component header without `meta.label`
327
375
 
@@ -344,7 +392,7 @@ columnHelper.accessor("fullName", {
344
392
  });
345
393
  ```
346
394
 
347
- Source: `src/tmdatagrid/core/columnUtils.ts`.
395
+ Source: `packages/tmdatagrid/src/core/columnUtils.ts`.
348
396
 
349
397
  ### HIGH A numeric column without `meta.type`
350
398
 
@@ -353,7 +401,7 @@ Source: `src/tmdatagrid/core/columnUtils.ts`.
353
401
  as text - `"9"` above `"10"`. The column still sorts and filters, which is why
354
402
  it is easy to miss.
355
403
 
356
- Source: `src/tmdatagrid/core/filterOperators.ts`.
404
+ Source: `packages/tmdatagrid/src/core/filterOperators.ts`.
357
405
 
358
406
  ### HIGH Expecting a move across pinned regions to work
359
407
 
@@ -368,7 +416,7 @@ table.getColumn("salary")?.pin(false);
368
416
  moveColumn({ table, columnId: "salary", targetId: "age", side: "before" });
369
417
  ```
370
418
 
371
- Source: `src/docs/column-layout.md` (Regions).
419
+ Source: `packages/tmdatagrid/docs/column-layout.md` (Regions).
372
420
 
373
421
  ### HIGH Reaching for the v8 name of a v9 option
374
422
 
@@ -390,7 +438,7 @@ columnHelper.accessor("priority", { header: "Priority", sortFn: byRank });
390
438
  ```
391
439
 
392
440
  Source: `@tanstack/table-core` `rowSortingFeature.types.d.ts`, and
393
- `src/tmdatagrid/useTMDataGrid.tsx` (the registered `sortFns`).
441
+ `packages/tmdatagrid/src/useTMDataGrid.tsx` (the registered `sortFns`).
394
442
 
395
443
  ### MEDIUM Expecting autosize to measure every row
396
444
 
@@ -398,7 +446,7 @@ Autosizing fits the **mounted** rows plus overscan, not every row, because
398
446
  virtualization leaves the rest with no DOM to measure. A column autosized at the
399
447
  top of a long list can be too narrow for a value further down.
400
448
 
401
- Source: `src/docs/column-layout.md` (Autosizing).
449
+ Source: `packages/tmdatagrid/docs/column-layout.md` (Autosizing).
402
450
 
403
451
  ### MEDIUM Reordering a column inside a header group
404
452
 
@@ -407,31 +455,38 @@ the group header spanning columns that no longer belong to it. Grouped-header
407
455
  columns are therefore immovable in both directions, whatever `meta.enableOrdering`
408
456
  says.
409
457
 
410
- Source: `src/docs/column-layout.md` (Regions).
411
-
412
- ## Reference
413
-
414
- | Name | Kind | Type | Default | What it does |
415
- | --- | --- | --- | --- | --- |
416
- | `createTMDataGridColumnHelper` | Export | `<TData>() => helper` | – | The typed column helper. |
417
- | `minSize` / `maxSize` / `size` | Column options | `number` | `80` / – / – | Width bounds, and the fixed width once one applies. |
418
- | `enableSorting` · `enableColumnFilter` · `enableHiding` · `enablePinning` · `enableResizing` · `enableGrouping` | Column options | `boolean` | `true` | Per-column switches, each removing its interface. |
419
- | `enableColumnOrdering` | Option | `boolean` | `true` | Header dragging and the move menu items. Grid-defined. |
420
- | `enableMultiSort` · `maxMultiSortColCount` · `isMultiSortEvent` | Table options | – | Shift held | Multi-column sorting. |
421
- | `sortFn` | Column option | name or `(rowA, rowB, columnId) => number` | `"auto"` | The comparator for one column. Not v8's `sortingFn`. |
422
- | `initialState.columnOrder` · `.columnPinning` · `.columnVisibility` · `.columnSizing` | Table options | – | – | Layout at mount. Settings slices, persisted under `settingsKey`. |
423
- | `initialState.sorting` | Table option | `Array<{ id, desc }>` | `[]` | Sort at mount. A data slice, persisted under `dataKey`. |
424
- | `resetSettings` | Hook return | `() => void` | – | Clears visibility, order, pinning and widths. |
425
- | `moveColumn` | Export | `({ table, columnId, targetId, side }) => void` | – | Moves a column beside another. |
426
- | `moveColumnByStep` | Export | `({ table, columnId, direction }) => void` | – | Moves it one place. |
427
- | `getStepTargetColumn` | Export | `(args) => Column \| null` | – | What a step would swap with, or `null` at a region edge. |
428
- | `getColumnRegion` | Export | `(column) => "left" \| "center" \| "right"` | – | Which pinned region a column is in. |
429
- | `isColumnReorderable` | Export | `(column, features) => boolean` | – | Whether this column may move at all. |
430
- | `autosizeColumn` | Export | `({ table, columnId, container }) => void` | – | Fits a column to its mounted content. |
431
- | `measureColumnContentWidth` | Export | `(args) => number` | – | The measurement behind it. |
432
- | `getColumnLabel` · `getColumnType` · `getColumnDefaultOperator` · `isControlColumn` | Exports | – | – | What the built-in controls read off a column. |
433
- | `SELECT_COLUMN_ID` · `GROUP_COLUMN_ID` · `DETAILS_COLUMN_ID` · `EDIT_COLUMN_ID` · `ROW_NUMBER_COLUMN_ID` | Exports | ids | – | The generated lanes. |
434
- | `TMDataGrid.ColumnsButton` · `TMDataGrid.ColumnsPanel` | Components | – | – | Manage columns, and Reset layout. |
458
+ Source: `packages/tmdatagrid/docs/column-layout.md` (Regions).
459
+
460
+ ### MEDIUM Computing a cross-row value in accessorFn
461
+
462
+ `accessorFn` is handed one row, so a share of a total, a rank or a running
463
+ total has nothing to compute against. Derive the collection once and give the
464
+ grid the finished shape.
465
+
466
+ Wrong:
467
+
468
+ ```tsx
469
+ columnHelper.accessor((row) => (row.value / total) * 100, { id: "pctOfTotal" });
470
+ ```
471
+
472
+ Correct:
473
+
474
+ ```tsx
475
+ const rows = useMemo(() => {
476
+ const total = holdings.reduce((sum, h) => sum + h.value, 0);
477
+ return holdings.map((h) => ({ ...h, pctOfTotal: (h.value / total) * 100 }));
478
+ }, [holdings]);
479
+
480
+ columnHelper.accessor("pctOfTotal", { header: "Share" });
481
+ ```
482
+
483
+ Source: `packages/tmdatagrid/docs/columns.md` (Columns derived from the other rows).
484
+
485
+ ## References
486
+
487
+ - [Columns API](references/columns-api.md) - every column option, column meta
488
+ field, export and type belonging to defining, sizing, hiding, pinning,
489
+ ordering and sorting columns.
435
490
 
436
491
  See also: the `filtering` skill for operators and filter controls, the `editing`
437
492
  skill for the editing meta fields, and the `grouping` skill for what grouping
@@ -0,0 +1,59 @@
1
+ # Columns API
2
+
3
+ Reference for the `columns` skill.
4
+
5
+ ## meta.filter and meta.edit
6
+
7
+ `meta.filter` belongs to the `filtering` skill:
8
+
9
+ | Field | Type | Default | What it does |
10
+ | --- | --- | --- | --- |
11
+ | `operators` | `readonly TMDataGridFilterOperator[]` | The type's list | The operators this column offers, a subset of its type's. For a backend that answers only some. |
12
+ | `defaultOperator` | `TMDataGridFilterOperator` | The type's default, else the first offered | The operator a fresh filter on this column starts with. |
13
+ | `control` | `TMDataGridFilterControlComponent` | By `meta.type` | Replaces the value control in this column's filter row. Module scope. |
14
+
15
+ `meta.edit` belongs to the `editing` skill, and only acts once `editing` is set:
16
+
17
+ | Field | Type | Default | What it does |
18
+ | --- | --- | --- | --- |
19
+ | `enabled` | `boolean \| ((row) => boolean)` | editable where a field maps | Whether this column's cells edit. `row` is typed by the column helper. |
20
+ | `field` | `string` | The `accessorKey` | The data path an edit writes to. The only way an `accessorFn` column edits. |
21
+ | `editor` | `TMDataGridEditorComponent` | By `meta.type` | Replaces the cell editor. Module scope. |
22
+ | `validate` | `TMDataGridFieldValidate` | – | Field-level validation. A bare schema means `onChange`. |
23
+ | `mapValue` | `TMDataGridEditValueMap` | – | Maps each value an editor writes, on every keystroke. |
24
+
25
+ ## Exports and options
26
+
27
+ | Name | Kind | Type | Default | What it does |
28
+ | --- | --- | --- | --- | --- |
29
+ | `createTMDataGridColumnHelper` | Export | `<TData>() => TMDataGridColumnHelper<TData>` | – | The typed column helper. `meta` callbacks receive `Row<TMDataGridFeatures, TData>`. |
30
+ | `TMDataGridColumnHelper` | Type | – | – | The helper's type. |
31
+ | `TMDataGridColumnMeta` | Type | `TMDataGridColumnMeta<TData = TMDataGridRowData>` | – | The type of `meta`. Typed against the row when the column is declared with the helper. |
32
+ | `meta.options` | Column meta | `TMDataGridOptionsSource`: array \| `"faceted"` \| `(args: TMDataGridOptionsArgs) => …` | – | The choices of a `select` / `multiSelect` column. |
33
+ | `TMDataGridOption` | Type | `{ value, label?, color?, disabled?, group? }` | – | One choice. A bare string is shorthand for `{ value }`. |
34
+ | `TMDataGridOptionsArgs` | Type | `{ table, column, row? }` | – | What a `meta.options` function receives. `row` is absent when the filter panel asks. |
35
+ | `resolveColumnOptions` | Export | `({ table, column, row?, fallback? }) => Array<TMDataGridOption>` | – | Normalises all three `meta.options` forms. Empty when the column declares none. |
36
+ | `optionsToComboboxData` | Export | `(options) => ComboboxData` | – | Options as Mantine `Select` / `MultiSelect` data, groups folded in. |
37
+ | `minSize` / `maxSize` / `size` | Column options | `number` | `80` / – / – | Width bounds, and the fixed width once one applies. |
38
+ | `enableSorting` · `enableColumnFilter` · `enableHiding` · `enablePinning` · `enableResizing` · `enableGrouping` | Column options | `boolean` | `true` | Per-column switches, each removing its interface. |
39
+ | `enableColumnOrdering` | Option | `boolean` | `true` | Header dragging and the move menu items. Grid-defined. |
40
+ | `enableMultiSort` · `maxMultiSortColCount` · `isMultiSortEvent` | Table options | – | Shift held | Multi-column sorting. |
41
+ | `sortFn` | Column option | name or `(rowA, rowB, columnId) => number` | `"auto"` | The comparator for one column. Not v8's `sortingFn`. |
42
+ | `initialState.columnOrder` · `.columnPinning` · `.columnVisibility` · `.columnSizing` | Table options | – | – | Layout at mount. Settings slices, persisted under `settingsKey`. |
43
+ | `initialState.sorting` | Table option | `Array<{ id, desc }>` | `[]` | Sort at mount. A data slice, persisted under `dataKey`. |
44
+ | `resetSettings` | Hook return | `() => void` | – | Clears visibility, order, pinning and widths. |
45
+ | `moveColumn` | Export | `({ table, columnId, targetId, side }) => void` | – | Moves a column beside another. |
46
+ | `moveColumnByStep` | Export | `({ table, columnId, direction }) => void` | – | Moves it one place. `direction` is `-1` or `1`. |
47
+ | `MoveColumnArgs` · `ColumnStepArgs` | Types | – | – | What `moveColumn` takes, and what `moveColumnByStep` and `getStepTargetColumn` take. |
48
+ | `TMDataGridDropSide` | Type | `"before" \| "after"` | – | The `side` of `MoveColumnArgs`: which edge of the target column the moved column lands on. |
49
+ | `getStepTargetColumn` | Export | `(args) => Column \| null` | – | What a step would swap with, or `null` at a region edge. |
50
+ | `getColumnRegion` | Export | `(columnPinning, columnId) => TMDataGridColumnRegion` | – | Which pinned region a column is in. |
51
+ | `TMDataGridColumnRegion` | Type | `"start" \| "center" \| "end"` | – | What `getColumnRegion` returns. |
52
+ | `keepGeneratedColumnsOutermost` | Export | `(columnPinning) => ColumnPinningState` | – | Puts the generated lanes back on the outside of both pinned lanes. The grid runs it after every pin; call it on a `columnPinning` you write yourself. |
53
+ | `getColumnCapabilities(column, features).canReorder` | Export | `boolean` | – | Whether this column may move at all. |
54
+ | `autosizeColumn` | Export | `({ table, columnId, container }) => void` | – | Fits a column to its mounted content. |
55
+ | `getColumnLabel` · `getColumnType` · `getColumnDefaultOperator` · `isControlColumn` | Exports | – | – | What the built-in controls read off a column. |
56
+ | `isGeneratedColumn` | Export | `(columnId) => boolean` | – | Whether the grid generated the column - the four control lanes plus the tree column. |
57
+ | `SELECT_COLUMN_ID` · `GROUP_COLUMN_ID` · `DETAILS_COLUMN_ID` · `EDIT_COLUMN_ID` · `ROW_NUMBER_COLUMN_ID` | Exports | ids | – | The generated lanes. |
58
+ | `TMDataGrid.Menu.Columns` · `TMDataGrid.ColumnsPanel` | Components | `searchable` · Mantine `BoxProps` | – | The column chooser, as menu items and as plain controls. Style props set on the panel. |
59
+ | `TMDataGridColumnSearchable` | Type | `boolean \| "auto"` | `"auto"` | The `searchable` prop of both: a search box from six hideable columns under `"auto"`, `true` always, `false` never. |
@@ -10,17 +10,23 @@ description: >
10
10
  onReachEnd is better for loading more, the header and pinned-lane depth
11
11
  shadows, and the four empty states in precedence order with meta.loading,
12
12
  renderEmptyState, hasActiveFilters, TMDataGrid.LoadingIndicator and
13
- TMDataGrid.SummaryCount. Load when adding a pager, tuning scrolling, scrolling
14
- to a row, or deciding what an empty grid should say.
13
+ TMDataGrid.SummaryCount, and export: TMDataGrid.Menu.Export and
14
+ Menu.ExportSelected, useTMDataGridExport, exportGrid, exportOptions, the
15
+ csvExcel / csv / tsv / json formats, meta.exportValue and meta.enableExport.
16
+ Load when adding a pager, tuning scrolling, scrolling to a row, deciding what
17
+ an empty grid should say, or exporting rows to Excel or CSV.
15
18
  metadata:
16
19
  type: core
17
20
  library: '@jielga/tmdatagrid'
18
- library_version: '2.0.0-beta.9'
21
+ library_version: '2.0.1'
19
22
  sources:
20
- - 'Jielga/TMDataGrid:src/docs/pagination.md'
21
- - 'Jielga/TMDataGrid:src/docs/scrolling.md'
22
- - 'Jielga/TMDataGrid:src/docs/loading-and-empty.md'
23
- - 'Jielga/TMDataGrid:src/tmdatagrid/components/TMDataGridFooter.tsx'
23
+ - 'Jielga/TMDataGrid:packages/tmdatagrid/docs/pagination.md'
24
+ - 'Jielga/TMDataGrid:packages/tmdatagrid/docs/scrolling.md'
25
+ - 'Jielga/TMDataGrid:packages/tmdatagrid/docs/loading-and-empty.md'
26
+ - 'Jielga/TMDataGrid:packages/tmdatagrid/docs/export.md'
27
+ - 'Jielga/TMDataGrid:packages/tmdatagrid/src/components/TMDataGridFooter.tsx'
28
+ - 'Jielga/TMDataGrid:packages/tmdatagrid/src/core/pagination.ts'
29
+ - 'Jielga/TMDataGrid:packages/tmdatagrid/src/core/export.ts'
24
30
  ---
25
31
 
26
32
  # TMDataGrid - Pagination, scrolling and empty states
@@ -77,7 +83,10 @@ pieces, already wired.
77
83
  `Controls.PageSize`, `Controls.Range` and `Controls.Pager` are what the default
78
84
  footer renders, in that order, so a custom layout can keep the parts it wants
79
85
  instead of rebuilding them. They behave exactly as before, including greying out
80
- under a suspended pager.
86
+ under a suspended pager. `Controls.PageNumber` - the "Page 3 of 200" label a
87
+ server-paged grid usually shows in place of a row range - is a fourth control,
88
+ not in the default footer; put it in through the slot rather than writing it by
89
+ hand.
81
90
 
82
91
  `state` carries `pageIndex`, `pageSize`, `pageCount`, `rowCount`,
83
92
  `canPreviousPage`, `canNextPage`, `from`, `to` and `isPagingActive`. `actions`
@@ -178,6 +187,67 @@ server-driven grid refetching with rows still on screen keeps showing them.
178
187
  total, where the total is `meta.totalRowCount` when provided and the pre-filtered
179
188
  count otherwise.
180
189
 
190
+ ## Export
191
+
192
+ Every filtered and sorted row across every page, or the selected rows, as a
193
+ file. The built-in entry points are menu items; a button of your own uses the
194
+ hook.
195
+
196
+ ```tsx
197
+ const grid = useTMDataGrid({
198
+ data,
199
+ columns,
200
+ exportOptions: { format: csvFormat(), fileName: "employees" },
201
+ });
202
+
203
+ <TMDataGrid.Menu>
204
+ <TMDataGrid.Menu.Export />
205
+ <TMDataGrid.Menu.ExportSelected />
206
+ </TMDataGrid.Menu>
207
+ ```
208
+
209
+ ```tsx
210
+ function ExportButton() {
211
+ const { exportAll, exportSelected, selectedCount, canExportSelected } =
212
+ useTMDataGridExport();
213
+ return <Button onClick={() => void exportAll()}>Export</Button>;
214
+ }
215
+ ```
216
+
217
+ What is written: the data columns in render order (never the generated lanes,
218
+ never a column with `meta.enableExport: false`), every row after filtering and
219
+ sorting (a grouped grid writes the records under every group, never the group
220
+ rows), and each cell's **value** rather than what it renders -
221
+ `meta.exportValue: ({ value, row, column }) => unknown` substitutes one.
222
+ `columns` on `exportOptions`, the items and the functions is `"visible"` (the
223
+ default), `"all"` (hidden columns too) or a list of ids; `columns="custom"` on
224
+ a menu item opens a picker instead - every exportable column, the visible ones
225
+ ticked, Export and Cancel - driven by `ui.state.exportPicker` and
226
+ `ui.actions.openExportPicker`. `TMDataGrid.Menu.ExportSelected` counts and
227
+ writes the ticked rows of the current view, in grid order; it renders nothing
228
+ when row selection is off.
229
+
230
+ Formats, each a `TMDataGridExportFormat` from a factory:
231
+
232
+ | Factory | Writes |
233
+ | --- | --- |
234
+ | `csvExcelFormat()` (default) | BOM, `sep=;` line, CRLF, `;` fields, `,` decimal - opens straight into columns in Excel. `separator`, `decimalComma` for another locale. |
235
+ | `csvFormat()` | RFC 4180: `,` fields, `.` decimal, BOM, no `sep=` line - for Google Sheets, Numbers and tooling. |
236
+ | `tsvFormat()` | Tab-separated, the clipboard shape as a file. |
237
+ | `jsonFormat()` | One object per row keyed by column label, numbers as numbers, dates as ISO strings. |
238
+ | `xlsxFormat()` | Excel workbook, from the separate `@jielga/tmdatagrid-xlsx` package. |
239
+
240
+ The text formats guard against formula injection by default: a value starting
241
+ with `=`, `+`, `-` or `@` that is not a number is prefixed with `'`.
242
+ `escapeFormulas: false` on the format turns that off.
243
+
244
+ `exportGrid({ table, rows: "all" | "selected" | rows, options })` is the same
245
+ export for code outside a component; `buildExportData` is the step before the
246
+ file. A format of your own is `{ id, extension, mimeType, write(data, { includeHeaders }) }`
247
+ returning a string, a `Blob`, or a promise of either.
248
+
249
+ Source: `packages/tmdatagrid/docs/export.md`.
250
+
181
251
  ## Common mistakes
182
252
 
183
253
  ### CRITICAL Turning pagination on to make a large grid fast
@@ -186,7 +256,7 @@ Virtualization is already unconditional, so paging a 200 000-row grid changes
186
256
  nothing about rendering cost. It only changes how users navigate. Enable it when
187
257
  they should move page by page, not for performance.
188
258
 
189
- Source: `src/docs/pagination.md`, `src/docs/scrolling.md`.
259
+ Source: `packages/tmdatagrid/docs/pagination.md`, `packages/tmdatagrid/docs/scrolling.md`.
190
260
 
191
261
  ### CRITICAL A variable row height
192
262
 
@@ -207,7 +277,7 @@ Correct:
207
277
  useTMDataGrid({ data, columns, meta: { rowHeight: 64 } });
208
278
  ```
209
279
 
210
- Source: `src/docs/scrolling.md` (Row height).
280
+ Source: `packages/tmdatagrid/docs/scrolling.md` (Row height).
211
281
 
212
282
  ### HIGH `scrollIntoView` on a row that is not mounted
213
283
 
@@ -223,7 +293,7 @@ grid.scrollToRow({ rowId: "4000", align: "center" });
223
293
  `scrollToRow` returns `false` when the row is not in the current view (filtered
224
294
  out, on another page, or an id matching no row) and nothing scrolled.
225
295
 
226
- Source: `src/docs/scrolling.md` (Scrolling to a row).
296
+ Source: `packages/tmdatagrid/docs/scrolling.md` (Scrolling to a row).
227
297
 
228
298
  ### HIGH Loading more rows from `onScrollToBottom`
229
299
 
@@ -231,7 +301,7 @@ It fires at the very bottom, so the user waits at the end of the list for the
231
301
  fetch. `onReachEnd` fires a number of rows earlier and latches per row count, so
232
302
  a pending fetch is not requested twice.
233
303
 
234
- Source: `src/docs/scrolling.md` (Edge callbacks).
304
+ Source: `packages/tmdatagrid/docs/scrolling.md` (Edge callbacks).
235
305
 
236
306
  ### HIGH `SummaryCount` reporting the page under manual pagination
237
307
 
@@ -250,7 +320,7 @@ useTMDataGrid({
250
320
  });
251
321
  ```
252
322
 
253
- Source: `src/docs/loading-and-empty.md` (Counting what is there).
323
+ Source: `packages/tmdatagrid/docs/loading-and-empty.md` (Counting what is there).
254
324
 
255
325
  ### MEDIUM Rendering an empty message while data is loading
256
326
 
@@ -264,7 +334,7 @@ Correct:
264
334
  useTMDataGrid({ data, columns, meta: { loading: isFetching } });
265
335
  ```
266
336
 
267
- Source: `src/docs/loading-and-empty.md` (What wins).
337
+ Source: `packages/tmdatagrid/docs/loading-and-empty.md` (What wins).
268
338
 
269
339
  ### MEDIUM Trusting the pager while grouped
270
340
 
@@ -272,7 +342,7 @@ Source: `src/docs/loading-and-empty.md` (What wins).
272
342
  grid is rendering the whole tree. A custom pager must read
273
343
  `isPagingActive(table, features)` rather than the page count.
274
344
 
275
- Source: `src/docs/pagination.md` (Grouping suspends it).
345
+ Source: `packages/tmdatagrid/docs/pagination.md` (Grouping suspends it).
276
346
 
277
347
  ## Reference
278
348
 
@@ -283,14 +353,18 @@ Source: `src/docs/pagination.md` (Grouping suspends it).
283
353
  | `rowCount` | Table option | `number` | – | The true total, required under `manualPagination`. |
284
354
  | `initialState.pagination` | Table option | `{ pageIndex, pageSize }` | `{ 0, 25 }` | Where paging starts. A `data` slice, so it persists. |
285
355
  | `onPaginationChange` | Table option | `OnChangeFn` | – | Controls the pagination state. |
286
- | `TMDataGrid.Footer` | Component | `pageSizeOptions`, `pagination` | `[10, 25, 50, 100]` | The footer bar. Renders nothing when paging is off. |
287
- | `Footer` `renderPagination` | Slot | `({ state, actions, Controls }) => ReactNode` | Built-in pager | Replaces the pager, and hands over its pieces. |
288
- | `getTMDataGridPaginationApi` | Export | `(table) => { state, actions }` | – | The pager API, outside the Footer. |
356
+ | `TMDataGrid.Footer` | Component | `pageSizeOptions`, `renderPagination`, Mantine `BoxProps` | `[10, 25, 50, 100]` | The footer bar. Renders nothing when paging is off. Style props set on the bar. |
357
+ | `TMDataGridFooterProps` | Type | – | – | The props of `TMDataGrid.Footer`. |
358
+ | `Footer` `renderPagination` | Slot | `(args: TMDataGridPaginationSlotArgs) => ReactNode` | Built-in pager | Replaces the pager, and hands over its pieces. |
359
+ | `TMDataGridPaginationSlotArgs` | Type | `TMDataGridPaginationApi & { Controls }` | – | What `renderPagination` receives: `{ state, actions, Controls }`. |
360
+ | `getTMDataGridPaginationApi` | Export | `(table, isPaging?) => TMDataGridPaginationApi` | `isPaging`: `true` | The pager API, outside the Footer. |
361
+ | `TMDataGridPaginationApi` | Type | `{ state, actions }` | – | What `getTMDataGridPaginationApi` returns. |
289
362
  | `TMDataGridPaginationState` · `TMDataGridPaginationActions` · `TMDataGridPaginationControls` | Exports | types | – | The three parts of the slot argument. |
290
363
  | `isPagingActive` | Export | `(table, features) => boolean` | – | Whether the pager is slicing anything right now. |
291
364
  | `overscan` | Option | `number` | `6` | Rows kept mounted beyond each edge of the viewport. |
292
365
  | `meta.rowHeight` | Option | `number` | From `size` | Row height in pixels. The virtualizer needs a number. |
293
366
  | `scrollToRow` | Hook return | `({ rowId, align? }) => boolean` | `align: "auto"` | Scrolls a row into view, mounted or not. |
367
+ | `TMDataGridScrollToRowArgs` | Export | `{ rowId, align? }` | – | What `scrollToRow` takes. |
294
368
  | `onScrollToTop` · `onScrollToBottom` · `onScrollToLeft` · `onScrollToRight` | Table props | `() => void` | – | Fire once on arriving at that edge. |
295
369
  | `TMDataGridScrollAlign` | Export | `"start" \| "center" \| "end" \| "auto"` | – | The `align` argument. |
296
370
  | `meta.loading` | Option | `boolean` | `false` | A fetch is in flight. Takes precedence over every empty message. |
@@ -301,6 +375,26 @@ Source: `src/docs/pagination.md` (Grouping suspends it).
301
375
  | `TMDataGrid.SummaryCount` | Component | `children` replaces the text | – | Visible rows out of total. |
302
376
  | `--dg-header-shadow-color` | CSS variable | colour | Themed | The shadow under the sticky header. |
303
377
  | `--dg-sticky-edge-range` | CSS variable | length | `20px` | How far the pinned-lane band takes to fade in. |
378
+ | `exportOptions` | Option | `TMDataGridExportOptions` | `DEFAULT_EXPORT_OPTIONS` | Format, file name and header row for every export of the grid. |
379
+ | `meta.enableExport` | Column meta | `boolean` | `true` | `false` leaves the column out of every export and of Ctrl+C. |
380
+ | `meta.exportValue` | Column meta | `TMDataGridExportValueGetter`: `({ value, row, column }) => unknown` | – | The value written in place of `row.getValue`. |
381
+ | `TMDataGrid.Menu.Export` · `TMDataGrid.Menu.ExportSelected` | Components | `TMDataGridMenuExportProps` | – | Menu items: every filtered row, and the selected rows. `columns="custom"` opens the picker. |
382
+ | `ui.state.exportPicker` | UI state | `TMDataGridExportPickerRequest \| null` | `null` | The column picker while open: `{ rows, options }`. |
383
+ | `getExportableColumns` | Export | `(table) => Array<Column>` | – | Every column an export could take, hidden ones included. The list the picker shows. |
384
+ | `useTMDataGridExport` | Hook | `(overrides?) => TMDataGridExportApi` | – | `exportAll`, `exportSelected`, `selectedCount`, `canExportSelected`. |
385
+ | `exportGrid` | Export | `(args: ExportGridArgs) => Promise<void>` | – | Downloads the grid from outside a component. `ExportGridArgs` is `{ table, rows?, options? }`. |
386
+ | `buildExportData` | Export | `(args: BuildExportDataArgs) => TMDataGridExportData` | – | The columns, labels and values a format writes. `BuildExportDataArgs` is `{ table, rows?, columns?, bounds? }`. |
387
+ | `TMDataGridExportRows` · `TMDataGridExportColumns` | Types | `"all" \| "selected" \| rows` · `"visible" \| "all" \| ReadonlyArray<string>` | `"all"` · `"visible"` | Which rows and which columns an export takes. |
388
+ | `writeExportFile` | Export | `(data, settings) => Promise<void>` | – | Writes export data in a format and downloads it. |
389
+ | `downloadFile` | Export | `({ fileName, content, mimeType }) => void` | – | Downloads a string or a `Blob`. |
390
+ | `csvExcelFormat` · `csvFormat` · `tsvFormat` · `jsonFormat` | Exports | `(options?) => TMDataGridExportFormat` | – | The built-in formats. |
391
+ | `TMDataGridCsvFormatOptions` · `TMDataGridTsvFormatOptions` · `TMDataGridJsonFormatOptions` | Types | – | – | The options of `csvExcelFormat` and `csvFormat`, of `tsvFormat`, and of `jsonFormat`. |
392
+ | `TMDataGridExportWriteOptions` | Type | `{ includeHeaders }` | – | The second argument of a format's `write`. |
393
+ | `guardFormula` · `formatExportValue` | Exports | `(text) => string` · – | – | The formula guard and the text rule, for a format of your own. |
394
+ | `resolveExportOptions` | Export | `(...overrides) => TMDataGridExportSettings` | – | The defaults with overrides folded over, `undefined` fields skipped. |
395
+ | `countSelectedExportRows` | Export | `(table) => number` | – | How many rows `"selected"` would write. |
396
+ | `DEFAULT_EXPORT_OPTIONS` | Constant | `TMDataGridExportSettings` | – | The defaults `exportOptions` merges over. |
397
+ | `TMDataGridExportSettings` | Type | `Required<TMDataGridExportOptions>` | – | Export options with every field set. |
304
398
 
305
399
  See also: the `server-side` skill for `manualPagination` and `onReachEnd`, and
306
400
  the `grouping` skill for why the pager suspends.