@jielga/tmdatagrid 2.0.0-beta.9 → 2.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (154) 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 +268 -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 +46 -47
  47. package/skills/columns/SKILL.md +90 -34
  48. package/skills/data/SKILL.md +86 -16
  49. package/skills/editing/SKILL.md +67 -40
  50. package/skills/editing/references/common-mistakes.md +77 -69
  51. package/skills/editing/references/editing-api.md +22 -19
  52. package/skills/editing/references/editors-and-validation.md +24 -17
  53. package/skills/filtering/SKILL.md +148 -40
  54. package/skills/getting-started/SKILL.md +17 -15
  55. package/skills/grouping/SKILL.md +31 -16
  56. package/skills/options/SKILL.md +7 -7
  57. package/skills/rows/SKILL.md +22 -18
  58. package/skills/server-side/SKILL.md +170 -17
  59. package/skills/testing/SKILL.md +150 -32
  60. package/skills/testing-components/SKILL.md +230 -0
  61. package/skills/testing-editing/SKILL.md +240 -0
  62. package/src/{tmdatagrid/components → components}/TMDataGrid.tsx +38 -21
  63. package/src/{tmdatagrid/components → components}/TMDataGridCellEditor.tsx +54 -8
  64. package/src/{tmdatagrid/components → components}/TMDataGridColumnsPanel.module.css +5 -1
  65. package/src/{tmdatagrid/components → components}/TMDataGridColumnsPanel.tsx +47 -55
  66. package/src/{tmdatagrid/components → components}/TMDataGridDetailsColumn.tsx +5 -51
  67. package/src/{tmdatagrid/components → components}/TMDataGridDraftActions.tsx +41 -24
  68. package/src/{tmdatagrid/components → components}/TMDataGridEditColumn.tsx +12 -59
  69. package/src/{tmdatagrid/components → components}/TMDataGridEntryRows.tsx +164 -92
  70. package/src/components/TMDataGridExportPicker.module.css +77 -0
  71. package/src/components/TMDataGridExportPicker.tsx +234 -0
  72. package/src/components/TMDataGridFilterPanel.module.css +54 -0
  73. package/src/components/TMDataGridFilterPanel.tsx +348 -0
  74. package/src/{tmdatagrid/components → components}/TMDataGridFilterPills.tsx +15 -8
  75. package/src/components/TMDataGridFilterSurface.module.css +54 -0
  76. package/src/components/TMDataGridFilterSurface.tsx +167 -0
  77. package/src/{tmdatagrid/components → components}/TMDataGridFooter.tsx +53 -90
  78. package/src/{tmdatagrid/components → components}/TMDataGridGroupColumn.tsx +5 -69
  79. package/src/{tmdatagrid/components → components}/TMDataGridHeaderCell.module.css +12 -2
  80. package/src/{tmdatagrid/components → components}/TMDataGridHeaderCell.tsx +58 -21
  81. package/src/components/TMDataGridHeaderFilterRow.module.css +51 -0
  82. package/src/components/TMDataGridHeaderFilterRow.tsx +301 -0
  83. package/src/components/TMDataGridMenu.tsx +357 -0
  84. package/src/{tmdatagrid/components → components}/TMDataGridSelectColumn.tsx +11 -48
  85. package/src/{tmdatagrid/components → components}/TMDataGridTable.module.css +69 -56
  86. package/src/{tmdatagrid/components → components}/TMDataGridTable.tsx +240 -138
  87. package/src/{tmdatagrid/components → components}/TMDataGridToolbar.module.css +5 -0
  88. package/src/components/TMDataGridToolbar.tsx +181 -0
  89. package/src/{tmdatagrid/components → components}/editors/TMDataGridBooleanEditor.tsx +3 -3
  90. package/src/{tmdatagrid/components → components}/editors/TMDataGridDateEditor.tsx +3 -3
  91. package/src/{tmdatagrid/components → components}/editors/TMDataGridMultiSelectEditor.tsx +3 -3
  92. package/src/{tmdatagrid/components → components}/editors/TMDataGridNumberEditor.tsx +3 -3
  93. package/src/{tmdatagrid/components → components}/editors/TMDataGridSelectEditor.tsx +3 -3
  94. package/src/{tmdatagrid/components → components}/editors/TMDataGridStringEditor.tsx +3 -3
  95. package/src/{tmdatagrid/components → components}/editors/editorShared.ts +16 -2
  96. package/src/{tmdatagrid/components → components}/filters/DgAutocompleteFilter.tsx +5 -4
  97. package/src/{tmdatagrid/components → components}/filters/DgDateRangeFilter.tsx +22 -5
  98. package/src/{tmdatagrid/components → components}/filters/DgRangeSliderFilter.tsx +5 -1
  99. package/src/{tmdatagrid/components → components}/filters/DgTriStateFilter.tsx +5 -1
  100. package/src/{tmdatagrid/components → components}/filters/TMDataGridFilterValueInput.tsx +44 -28
  101. package/src/components/filters/controlLayout.ts +32 -0
  102. package/src/components/filters/filterControlFor.ts +65 -0
  103. package/src/components/generatedColumns.tsx +187 -0
  104. package/src/{tmdatagrid/components → components}/icons.ts +1 -0
  105. package/src/{tmdatagrid/components → components}/sticky.module.css +44 -0
  106. package/src/components/useHideableColumns.ts +52 -0
  107. package/src/{tmdatagrid/core → core}/autosize.ts +5 -2
  108. package/src/{tmdatagrid/core → core}/columnOptions.ts +60 -8
  109. package/src/{tmdatagrid/core → core}/columnOrdering.ts +33 -14
  110. package/src/{tmdatagrid/core → core}/columnUtils.ts +44 -5
  111. package/src/core/controlledStateSync.ts +108 -0
  112. package/src/core/deletedRows.ts +34 -0
  113. package/src/core/dom.ts +74 -0
  114. package/src/{tmdatagrid/core → core}/editEngine.ts +1107 -460
  115. package/src/core/export.ts +704 -0
  116. package/src/{tmdatagrid/core → core}/filterControls.ts +38 -1
  117. package/src/{tmdatagrid/core → core}/filterOperators.ts +64 -1
  118. package/src/core/filterSurface.ts +99 -0
  119. package/src/{tmdatagrid/core → core}/grouping.ts +21 -0
  120. package/src/{tmdatagrid/core → core}/labels.ts +51 -6
  121. package/src/{tmdatagrid/core → core}/labelsSv.ts +27 -6
  122. package/src/core/pageReset.ts +120 -0
  123. package/src/core/pagination.ts +81 -0
  124. package/src/{tmdatagrid/core → core}/persistence.ts +22 -5
  125. package/src/{tmdatagrid/core → core}/summary.ts +20 -4
  126. package/src/{tmdatagrid/index.ts → index.ts} +69 -35
  127. package/src/{tmdatagrid/useTMDataGrid.tsx → useTMDataGrid.tsx} +428 -109
  128. package/src/useTMDataGridExport.ts +78 -0
  129. package/src/tmdatagrid/components/TMDataGridFilterPanel.module.css +0 -35
  130. package/src/tmdatagrid/components/TMDataGridFilterPanel.tsx +0 -354
  131. package/src/tmdatagrid/components/TMDataGridToolbar.tsx +0 -161
  132. package/src/tmdatagrid/core/cellExport.ts +0 -320
  133. /package/src/{tmdatagrid/TMDataGridContext.ts → TMDataGridContext.ts} +0 -0
  134. /package/src/{tmdatagrid/components → components}/TMDataGrid.module.css +0 -0
  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}/capabilities.ts +0 -0
  142. /package/src/{tmdatagrid/core → core}/cellNavigation.ts +0 -0
  143. /package/src/{tmdatagrid/core → core}/cellRange.ts +0 -0
  144. /package/src/{tmdatagrid/core → core}/controlledState.ts +0 -0
  145. /package/src/{tmdatagrid/core → core}/draftCellContext.ts +0 -0
  146. /package/src/{tmdatagrid/core → core}/editorFocus.ts +0 -0
  147. /package/src/{tmdatagrid/core → core}/expanding.ts +0 -0
  148. /package/src/{tmdatagrid/core → core}/matchHighlight.ts +0 -0
  149. /package/src/{tmdatagrid/core → core}/quickSearch.ts +0 -0
  150. /package/src/{tmdatagrid/core → core}/resizePreview.ts +0 -0
  151. /package/src/{tmdatagrid/core → core}/rowPinning.ts +0 -0
  152. /package/src/{tmdatagrid/core → core}/rowSelection.ts +0 -0
  153. /package/src/{tmdatagrid/core → core}/sizes.ts +0 -0
  154. /package/src/{tmdatagrid/core → core}/useSettledTableState.ts +0 -0
@@ -5,24 +5,27 @@ description: >
5
5
  xl) and what it drives, every --dg-* CSS variable for metrics, colours and the
6
6
  stacking ladder, the two stylesheets styles.css and styles.layer.css and why
7
7
  only one may be imported, the bounded-height layout rule with minHeight 0,
8
- toolbar composition through children and TMDataGrid.Spacer, writing a toolbar
8
+ toolbar composition through children and TMDataGrid.Spacer, Mantine BoxProps
9
+ (mb, px, hiddenFrom) and withBottomBorder on the toolbar, writing a toolbar
9
10
  button with useTMDataGridContext, hiding it the way the built-ins do with
10
11
  getGridCapabilities and getColumnCapabilities, why capabilities take a
11
12
  features argument under the React Compiler, and localization through the
12
13
  labels option, TMDATAGRID_LABELS_EN, TMDATAGRID_LABELS_SV, mergeLabels and
13
14
  grid.labels. Load when styling or theming the grid, choosing a density,
14
- building a toolbar, adding a button beside the built-in ones, or translating
15
- the interface.
15
+ building a toolbar, adding a button beside the built-in ones, filling the grid
16
+ menu (TMDataGrid.Menu, the column chooser as menu items), or translating the
17
+ interface.
16
18
  metadata:
17
19
  type: core
18
20
  library: '@jielga/tmdatagrid'
19
- library_version: '2.0.0-beta.9'
21
+ library_version: '2.0.0'
20
22
  sources:
21
- - 'Jielga/TMDataGrid:src/docs/styling.md'
22
- - 'Jielga/TMDataGrid:src/docs/toolbar.md'
23
- - 'Jielga/TMDataGrid:src/docs/localization.md'
24
- - 'Jielga/TMDataGrid:src/tmdatagrid/core/capabilities.ts'
25
- - 'Jielga/TMDataGrid:src/tmdatagrid/core/labels.ts'
23
+ - 'Jielga/TMDataGrid:packages/tmdatagrid/docs/styling.md'
24
+ - 'Jielga/TMDataGrid:packages/tmdatagrid/docs/toolbar.md'
25
+ - 'Jielga/TMDataGrid:packages/tmdatagrid/docs/menu.md'
26
+ - 'Jielga/TMDataGrid:packages/tmdatagrid/docs/localization.md'
27
+ - 'Jielga/TMDataGrid:packages/tmdatagrid/src/core/capabilities.ts'
28
+ - 'Jielga/TMDataGrid:packages/tmdatagrid/src/core/labels.ts'
26
29
  ---
27
30
 
28
31
  # TMDataGrid - Appearance, toolbar and labels
@@ -118,7 +121,9 @@ element, and `TMDataGrid.Spacer` pushes what follows to the right.
118
121
  <TMDataGrid.LoadingIndicator />
119
122
  <ExportButton />
120
123
  <TMDataGrid.FilterButton />
121
- <TMDataGrid.ColumnsButton />
124
+ <TMDataGrid.Menu>
125
+ <TMDataGrid.Menu.Columns />
126
+ </TMDataGrid.Menu>
122
127
  </TMDataGrid.Toolbar>
123
128
  ```
124
129
 
@@ -126,12 +131,60 @@ Each built-in renders nothing when its feature is off, so a read-only grid needs
126
131
  no conditionals: `FilterButton` under `enableColumnFilters: false` renders
127
132
  nothing at all.
128
133
 
134
+ `TMDataGrid.Toolbar` and `TMDataGrid.Spacer` take Mantine's `BoxProps` - the
135
+ style props (`mb`, `px`, `h`, `hiddenFrom`), `className`, `style` and `mod` -
136
+ set on the element itself. `withBottomBorder` on the toolbar draws a 1px line in
137
+ the theme's default border colour under it, the same line the header draws;
138
+ default `false`. `TMDataGrid.Footer`, `FilterPanel`, `FilterPills` and
139
+ `ColumnsPanel` take the same `BoxProps` on top of their own props.
140
+
141
+ ```tsx
142
+ <TMDataGrid.Toolbar withBottomBorder px="sm" mb="xs">
143
+ <TMDataGrid.SummaryCount />
144
+ <TMDataGrid.Spacer hiddenFrom="sm" />
145
+ <TMDataGrid.FilterButton />
146
+ </TMDataGrid.Toolbar>
147
+ ```
148
+
149
+ ### The grid menu
150
+
151
+ `TMDataGrid.Menu` is the burger: a Mantine `Menu` whose children are the
152
+ dropdown, so your own `Menu.Item`s sit beside the built-in items. It takes
153
+ Mantine `MenuProps` (defaults `position="bottom-end"`, `shadow="md"`,
154
+ `width={260}`, `withinPortal`), `icon` and `label` (default `labels.menuButton`).
155
+
156
+ ```tsx
157
+ import { Menu } from "@mantine/core";
158
+
159
+ <TMDataGrid.Menu>
160
+ <Menu.Item onClick={exportReport}>Export report</Menu.Item>
161
+ <Menu.Divider />
162
+ <Menu.Label>Columns</Menu.Label>
163
+ <TMDataGrid.Menu.Columns />
164
+ </TMDataGrid.Menu>
165
+ ```
166
+
167
+ `TMDataGrid.Menu.Columns` is the column chooser as menu items: `Menu.Search`,
168
+ one checkbox item per hideable column, show/hide all and reset layout;
169
+ it renders nothing when no column can be hidden. Its pieces
170
+ `TMDataGrid.Menu.ColumnToggles` (`search` narrows the list),
171
+ `.ShowHideAll` and `.ResetLayout` are exported for menus that want only some of
172
+ them. Every piece needs a Mantine `Menu` around it and reads the grid from
173
+ context, so it works in any Mantine menu rendered inside `TMDataGrid`, and in a
174
+ `Menu.Sub` (pass `searchable={false}` there: `Menu.Search` registers on the
175
+ root menu and switches off its type-ahead and arrow keys).
176
+
177
+ The menu always renders, since it cannot see what its children render; a menu
178
+ holding only `Menu.Columns` should be hidden with `canHideAny` under
179
+ `enableHiding: false`. `TMDataGrid.ColumnsPanel` is the same chooser as plain
180
+ controls, for a Popover, a Drawer or an inline layout.
181
+
129
182
  A button of your own reads the grid from context, which returns
130
183
  `{ table, ui, features, labels, controlSize, resetSettings }`:
131
184
 
132
185
  ```tsx
133
186
  import {
134
- exportGridToCsv,
187
+ exportGrid,
135
188
  getGridCapabilities,
136
189
  useTMDataGridContext,
137
190
  } from "@jielga/tmdatagrid";
@@ -143,7 +196,7 @@ function ExportButton() {
143
196
  if (!canFilterAny) return null;
144
197
 
145
198
  return (
146
- <Button size={controlSize} onClick={() => exportGridToCsv({ table })}>
199
+ <Button size={controlSize} onClick={() => void exportGrid({ table })}>
147
200
  Export
148
201
  </Button>
149
202
  );
@@ -206,7 +259,7 @@ own uses the same strings as the built-in parts.
206
259
  so an application that ordered its layers to put the grid underneath its own
207
260
  overrides silently gets the opposite.
208
261
 
209
- Source: `src/docs/styling.md` (The stylesheet).
262
+ Source: `packages/tmdatagrid/docs/styling.md` (The stylesheet).
210
263
 
211
264
  ### CRITICAL A grid with no bounded height
212
265
 
@@ -226,7 +279,7 @@ Correct:
226
279
  <TMDataGrid {...grid} style={{ flex: 1, minHeight: 0 }} />
227
280
  ```
228
281
 
229
- Source: `src/docs/styling.md` (Layout).
282
+ Source: `packages/tmdatagrid/docs/styling.md` (Layout).
230
283
 
231
284
  ### HIGH Setting `--dg-row-height` to change density
232
285
 
@@ -241,7 +294,7 @@ Correct:
241
294
  useTMDataGrid({ data, columns, meta: { rowHeight: 64 } });
242
295
  ```
243
296
 
244
- Source: `src/docs/styling.md` (The size scale).
297
+ Source: `packages/tmdatagrid/docs/styling.md` (The size scale).
245
298
 
246
299
  ### HIGH A capability check without `features`
247
300
 
@@ -264,7 +317,7 @@ const { canSort } = getColumnCapabilities(column, features);
264
317
  if (!canSort) return null;
265
318
  ```
266
319
 
267
- Source: `src/docs/toolbar.md` (Why `features` is a second argument).
320
+ Source: `packages/tmdatagrid/docs/toolbar.md` (Why `features` is a second argument).
268
321
 
269
322
  ### MEDIUM An inline `labels` object
270
323
 
@@ -286,7 +339,7 @@ const labels = { noResults: "Inga träffar" } satisfies TMDataGridLabelsOverride
286
339
  useTMDataGrid({ data, columns, labels });
287
340
  ```
288
341
 
289
- Source: `src/docs/localization.md` (Keep the object stable).
342
+ Source: `packages/tmdatagrid/docs/localization.md` (Keep the object stable).
290
343
 
291
344
  ### MEDIUM Conditionally rendering built-in toolbar parts
292
345
 
@@ -294,7 +347,7 @@ Each built-in already renders nothing when its feature is off. Wrapping them in
294
347
  your own checks duplicates the capability logic, and the two drift apart the
295
348
  first time an option changes.
296
349
 
297
- Source: `src/docs/toolbar.md` (The built-in parts).
350
+ Source: `packages/tmdatagrid/docs/toolbar.md` (The built-in parts).
298
351
 
299
352
  ## Reference
300
353
 
@@ -306,7 +359,7 @@ Source: `src/docs/toolbar.md` (The built-in parts).
306
359
  | `SIZE_ROW_HEIGHT` | Export | `Record<MantineSize, number>` | – | The row heights the scale table lists. |
307
360
  | `SIZE_CONTROL_SIZE` | Export | `Record<MantineSize, MantineSize>` | – | Which control size each grid size uses. |
308
361
  | `DEFAULT_TMDATAGRID_SIZE` | Export | `"md"` | – | The default size. |
309
- | `TMDataGrid.Toolbar` · `Spacer` | Components | `children` | – | The flex row, and the push-right. |
362
+ | `TMDataGrid.Toolbar` · `Spacer` | Components | `children`, `withBottomBorder`, Mantine `BoxProps` | `withBottomBorder: false` | The flex row, and the push-right. Style props set on the element. |
310
363
  | `useTMDataGridContext` | Hook | `() => TMDataGridContextValue` | – | `{ table, ui, features, labels, controlSize, resetSettings }`. |
311
364
  | `getGridCapabilities` | Export | `(table, features) => TMDataGridCapabilities` | – | What this grid can do, reactively. |
312
365
  | `getColumnCapabilities` | Export | `(column, features) => TMDataGridColumnCapabilities` | – | The same for one column. |
@@ -1,25 +1,25 @@
1
1
  ---
2
2
  name: cell-selection
3
3
  description: >
4
- Cell cursor, ranges, clipboard and CSV export in TMDataGrid. Covers the
5
- cellSelection option and its none / single / range modes, the keyboard map
6
- (arrows, Shift+arrows, PageUp/PageDown, Home/End, Enter, F2, Escape, Space,
7
- Ctrl+C), the one-tab-stop rule and the in-row Tab walk over controls inside
8
- cells, the role flip from table/cell to grid/gridcell, ui.state.focusedCell
9
- and ui.state.cellRange keyed by id, onFocusedCellChange, the copy and export
10
- context menu, the cellExport options and their Nordic Excel defaults, and
11
- exportGridToCsv over every filtered row. Load when adding keyboard cell
12
- navigation, selecting blocks of cells, copying to a spreadsheet, exporting
13
- CSV, or when Tab walks through controls inside the grid body.
4
+ Cell cursor, ranges and the clipboard in TMDataGrid. Covers the cellSelection
5
+ option and its none / single / range modes, the keyboard map (arrows,
6
+ Shift+arrows, PageUp/PageDown, Home/End, Enter, F2, Escape, Space, Ctrl+C),
7
+ the one-tab-stop rule and the in-row Tab walk over controls inside cells, the
8
+ role flip from table/cell to grid/gridcell, ui.state.focusedCell and
9
+ ui.state.cellRange keyed by id, onFocusedCellChange, and the Copy / Export
10
+ cells / Include headers context menu that writes the rectangle in the grid's
11
+ exportOptions format. Load when adding keyboard cell navigation, selecting
12
+ blocks of cells, copying to a spreadsheet, or when Tab walks through controls
13
+ inside the grid body. Exporting whole rows is the data skill.
14
14
  metadata:
15
15
  type: core
16
16
  library: '@jielga/tmdatagrid'
17
- library_version: '2.0.0-beta.9'
17
+ library_version: '2.0.0'
18
18
  sources:
19
- - 'Jielga/TMDataGrid:src/docs/cell-selection.md'
20
- - 'Jielga/TMDataGrid:src/tmdatagrid/core/cellNavigation.ts'
21
- - 'Jielga/TMDataGrid:src/tmdatagrid/core/cellRange.ts'
22
- - 'Jielga/TMDataGrid:src/tmdatagrid/core/cellExport.ts'
19
+ - 'Jielga/TMDataGrid:packages/tmdatagrid/docs/cell-selection.md'
20
+ - 'Jielga/TMDataGrid:packages/tmdatagrid/src/core/cellNavigation.ts'
21
+ - 'Jielga/TMDataGrid:packages/tmdatagrid/src/core/cellRange.ts'
22
+ - 'Jielga/TMDataGrid:packages/tmdatagrid/src/core/export.ts'
23
23
  ---
24
24
 
25
25
  # TMDataGrid - Cell selection
@@ -115,31 +115,33 @@ Ctrl+C puts the block on the clipboard as tab-separated text with CRLF between
115
115
  rows, the format Excel, Sheets and Numbers all produce themselves. Values only:
116
116
  Excel's own copy carries no header row either.
117
117
 
118
- Right-clicking inside the selection opens Copy, "Export as CSV for Excel" and an
118
+ Right-clicking inside the selection opens Copy, "Export cells" and an
119
119
  "Include headers" toggle. A right-click outside it moves the selection there
120
120
  first, the way a spreadsheet does. Your own `renderRowContextMenu` items are appended
121
121
  below a divider, so nothing is lost by turning cell selection on.
122
122
 
123
- The CSV is written for a Nordic Excel: a `sep=;` first line, a UTF-8 BOM, CRLF
124
- endings, semicolons between fields and a comma as the decimal mark. That
125
- combination opens straight into columns with å ä ö intact.
123
+ "Export cells" writes the rectangle in the grid's export format - by default a
124
+ CSV for a Nordic Excel: a `sep=;` first line, a UTF-8 BOM, CRLF endings,
125
+ semicolons between fields and a comma as the decimal mark. The format, the file
126
+ name and the header row are the grid's `exportOptions`:
126
127
 
127
128
  ```tsx
128
- <TMDataGrid.Table
129
- cellExport={{ separator: ",", decimalComma: false, fileName: "employees" }}
130
- />
129
+ const grid = useTMDataGrid({
130
+ data,
131
+ columns,
132
+ cellSelection: "range",
133
+ exportOptions: { format: csvFormat(), fileName: "employees" },
134
+ });
131
135
  ```
132
136
 
133
- What gets written is the cell's **value**, not what it renders. Dates come out
134
- in the `sv-SE` form (`2026-07-31`), which Excel reads as a date.
137
+ What gets written is the cell's **value**, not what it renders, for the file and
138
+ for Ctrl+C alike; `meta.exportValue` substitutes a value and
139
+ `meta.enableExport: false` drops a column from both. Ctrl+C writes numbers with
140
+ the format's decimal mark, so what is pasted matches what is exported.
135
141
 
136
- `exportGridToCsv({ table, options })` takes **every filtered row** instead of the
137
- selected block, with the same options and defaults. There is no built-in button
138
- for it:
139
-
140
- ```tsx
141
- <Button onClick={() => exportGridToCsv({ table: grid.table })}>Export</Button>
142
- ```
142
+ Exporting every filtered row rather than the rectangle is
143
+ `TMDataGrid.Menu.Export`, `TMDataGrid.Menu.ExportSelected` and
144
+ `useTMDataGridExport`, covered by the data skill.
143
145
 
144
146
  ## Common mistakes
145
147
 
@@ -166,7 +168,7 @@ Correct:
166
168
  const OpenButton = ({ row }) => <Button onClick={() => open(row.id)}>Open</Button>;
167
169
  ```
168
170
 
169
- Source: `src/docs/cell-selection.md` (One tab stop).
171
+ Source: `packages/tmdatagrid/docs/cell-selection.md` (One tab stop).
170
172
 
171
173
  ### HIGH Selectors written for `table` / `cell` roles
172
174
 
@@ -174,7 +176,7 @@ The grid reports `grid` and `gridcell` once cell selection is on, so a test or a
174
176
  query written against `getByRole("cell")` stops resolving the moment the option
175
177
  is set - including when `editing` turns it on implicitly.
176
178
 
177
- Source: `src/docs/cell-selection.md`, and the `testing` skill.
179
+ Source: `packages/tmdatagrid/docs/cell-selection.md`, and the `testing` skill.
178
180
 
179
181
  ### HIGH Reading the selection as row and column indices
180
182
 
@@ -189,23 +191,23 @@ const row = grid.table.getRow(focusedCell.rowId);
189
191
  const value = row.getValue(focusedCell.columnId);
190
192
  ```
191
193
 
192
- Source: `src/docs/cell-selection.md` (Where the selection lives).
194
+ Source: `packages/tmdatagrid/docs/cell-selection.md` (Where the selection lives).
193
195
 
194
196
  ### MEDIUM Expecting the export to match what the cells show
195
197
 
196
198
  A cell renders React - often a badge, a link or a formatted string - and the
197
199
  export writes the underlying value. A currency cell showing `32 000 kr` exports
198
- `32000`. Format in the data, or post-process the matrix from `buildCellMatrix`,
199
- if the file must match the screen.
200
+ `32000`. Set `meta.exportValue` on the column, or post-process the data from
201
+ `buildExportData`, if the file must match the screen.
200
202
 
201
- Source: `src/docs/cell-selection.md` (The CSV).
203
+ Source: `packages/tmdatagrid/docs/cell-selection.md` (The file).
202
204
 
203
205
  ### MEDIUM Expecting headers in the clipboard
204
206
 
205
207
  Ctrl+C copies values only, matching Excel's own copy. Headers are an option of
206
- the export menu and of `cellExport`, not of the clipboard path.
208
+ the export menu and of `exportOptions`, not of the clipboard path.
207
209
 
208
- Source: `src/docs/cell-selection.md` (Copy and export).
210
+ Source: `packages/tmdatagrid/docs/cell-selection.md` (Copy and export).
209
211
 
210
212
  ## Reference
211
213
 
@@ -213,17 +215,14 @@ Source: `src/docs/cell-selection.md` (Copy and export).
213
215
  | --- | --- | --- | --- | --- |
214
216
  | `cellSelection` | Option | `"none" \| "single" \| "range"` | `"none"`, or `"single"` under `editing` | Turns the cursor, and the rectangle, on. |
215
217
  | `onFocusedCellChange` | Callback | `(cell \| null) => void` | – | Follows the cursor. |
216
- | `cellExport` | Table prop | `TMDataGridCellExportOptions` | Nordic Excel | Separator, decimal mark, headers, file name. |
218
+ | `exportOptions` | Option | `TMDataGridExportOptions` | `DEFAULT_EXPORT_OPTIONS` | Format, file name and header row of the Export cells item. |
217
219
  | `ui.state.focusedCell` | UI state | `{ rowId, columnId } \| null` | `null` | The cursor. |
218
220
  | `ui.state.cellRange` | UI state | `{ anchor, focus } \| null` | `null` | The rectangle's two corners. |
219
221
  | `ui.actions.setFocusedCell` · `setCellRange` | UI actions | – | – | Move either from your own code. |
220
- | `exportGridToCsv` | Export | `({ table, options? }) => void` | – | Downloads every filtered row as CSV. |
221
- | `buildGridCellMatrix` · `buildCellMatrix` | Exports | – | – | The value matrix behind the file, for post-processing. |
222
- | `toClipboardText` · `toExcelCsv` · `writeClipboardText` · `downloadTextFile` | Exports | – | – | The pieces behind Ctrl+C and the file. |
223
- | `formatExportValue` | Export | `(value, options) => string` | – | One value, formatted as the export would. |
224
- | `DEFAULT_CELL_EXPORT_OPTIONS` | Export | object | – | The Nordic Excel defaults, to spread over. |
225
- | `isSameCell` · `resolveCellMove` | Exports | – | – | The cursor arithmetic, for a custom navigator. |
226
- | `resolveRangeBounds` · `isWithinBounds` · `boundsEdges` · `boundsCellCount` | Exports | – | – | The rectangle arithmetic. |
222
+ | `buildExportData` | Export | `({ table, rows, bounds }) => TMDataGridExportData` | – | The rectangle's values, with `bounds`; the whole grid without. |
223
+ | `toClipboardText` · `writeClipboardText` | Exports | – | – | The pieces behind Ctrl+C. |
224
+ | `formatExportValue` | Export | `(value, options) => string` | – | One value, formatted as the text formats would. |
225
+ | `resolveRangeBounds` | Export | `({ range, rowIndexOf, columnIndexOf }) => TMDataGridRangeBounds \| null` | – | The range as row and column indices - the `bounds` for `buildExportData`, over `getDisplayedRows`. |
227
226
  | `data-focused` | Data attribute | – | – | On the focused cell. |
228
227
  | `data-edge-top` · `-bottom` · `-left` · `-right` | Data attributes | – | – | On cells at the rectangle's border. |
229
228
 
@@ -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.0'
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
@@ -97,7 +97,8 @@ which is why they are in neither.
97
97
 
98
98
  | Field | Type | Default | What it does |
99
99
  | --- | --- | --- | --- |
100
- | `defaultOperator` | `TMDataGridFilterOperator` | The type's default | The operator a fresh filter on this column starts with. |
100
+ | `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. |
101
+ | `defaultOperator` | `TMDataGridFilterOperator` | The type's default, else the first offered | The operator a fresh filter on this column starts with. |
101
102
  | `control` | `TMDataGridFilterControlComponent` | By `meta.type` | Replaces the value control in this column's filter row. Module scope. |
102
103
 
103
104
  `meta.edit`:
@@ -174,21 +175,26 @@ consumer code.
174
175
 
175
176
  All three write state that persists together, so a grid comes back arranged the
176
177
  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
178
+ pinning and widths in one go, and the column chooser offers it as **Reset
178
179
  layout**.
179
180
 
180
181
  **Hiding** is `columnVisibility`, driven by "Hide column" in a column menu and by
181
- `TMDataGrid.ColumnsButton` with the panel behind it.
182
+ the column chooser: `TMDataGrid.Menu.Columns` in the grid menu, **Manage
183
+ columns** as a submenu of every column menu, and `TMDataGrid.ColumnsPanel` as
184
+ plain controls for a host that is not a menu. See the `appearance` skill.
182
185
 
183
186
  **Pinning** is "Pin to left" / "Pin to right" in the column menu. A pinned
184
187
  column also becomes fixed-width: sticky offsets are computed from `getSize()`,
185
188
  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.
189
+ `columnSizing` at the moment it is pinned and nothing jumps. A column pinned
190
+ from `initialState.columnPinning` has no rendered width to store, so it takes
191
+ its `size` - TanStack's default of `150` where none is set - and `minSize`
192
+ does not apply.
187
193
 
188
194
  **Ordering** is header dragging plus "Move left" / "Move right". A column can
189
195
  only move **within its own pinned region** - pinning splits the grid into left,
190
196
  centre and right, then `columnOrder` sequences the centre while
191
- `columnPinning.left` and `.right` sequence the pinned lanes. Unpin a column
197
+ `columnPinning.start` and `.end` sequence the pinned lanes. Unpin a column
192
198
  first to move it out of one. A neighbour that cannot move acts as a wall rather
193
199
  than being stepped over, and columns inside a header group are not movable in
194
200
  either direction, because `columnOrder` sequences leaf columns.
@@ -244,7 +250,7 @@ Standard TanStack column options. Each also removes the corresponding interface.
244
250
  | Option | Effect when `false` |
245
251
  | --- | --- |
246
252
  | `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. |
253
+ | `enableColumnFilter` | No filter menu item. Excluded from the filter panel's column list, and its header filter cell is empty. |
248
254
  | `enableHiding` | No hide menu item. Checkbox disabled in the column manager. |
249
255
  | `enablePinning` | No pin menu items. |
250
256
  | `enableResizing` | The divider is displayed but cannot be dragged. |
@@ -299,7 +305,33 @@ columnHelper.accessor("email", {
299
305
  });
300
306
  ```
301
307
 
302
- Source: `src/docs/column-layout.md` (Sizing).
308
+ The corollary is that a pinned column is fixed-width and does use `size`, so a
309
+ column that is pinned needs one.
310
+
311
+ Source: `packages/tmdatagrid/docs/column-layout.md` (Sizing).
312
+
313
+ ### HIGH Pinning a column at mount without size
314
+
315
+ A column pinned interactively keeps the width it was rendering, which the grid
316
+ writes into `columnSizing`. A column pinned from `initialState.columnPinning`
317
+ has no rendered width, so it takes `size` - TanStack's default of `150` where
318
+ none is set - and `minSize` does not apply.
319
+
320
+ Wrong:
321
+
322
+ ```tsx
323
+ columnHelper.accessor("name", { header: "Name", minSize: 220 });
324
+ initialState: { columnPinning: { start: ["name"], end: [] } },
325
+ ```
326
+
327
+ Correct:
328
+
329
+ ```tsx
330
+ columnHelper.accessor("name", { header: "Name", minSize: 220, size: 220 });
331
+ initialState: { columnPinning: { start: ["name"], end: [] } },
332
+ ```
333
+
334
+ Source: `packages/tmdatagrid/docs/column-layout.md` (Pinning).
303
335
 
304
336
  ### HIGH Addressing a dotted column by its accessor key
305
337
 
@@ -321,7 +353,7 @@ initialState: { columnVisibility: { address_city: false } },
321
353
  The edit path is the exception: `meta.edit.field` and validation issue paths
322
354
  stay dotted, because they address the data, not the column.
323
355
 
324
- Source: `src/docs/columns.md` (The column helper).
356
+ Source: `packages/tmdatagrid/docs/columns.md` (The column helper).
325
357
 
326
358
  ### CRITICAL A component header without `meta.label`
327
359
 
@@ -344,7 +376,7 @@ columnHelper.accessor("fullName", {
344
376
  });
345
377
  ```
346
378
 
347
- Source: `src/tmdatagrid/core/columnUtils.ts`.
379
+ Source: `packages/tmdatagrid/src/core/columnUtils.ts`.
348
380
 
349
381
  ### HIGH A numeric column without `meta.type`
350
382
 
@@ -353,7 +385,7 @@ Source: `src/tmdatagrid/core/columnUtils.ts`.
353
385
  as text - `"9"` above `"10"`. The column still sorts and filters, which is why
354
386
  it is easy to miss.
355
387
 
356
- Source: `src/tmdatagrid/core/filterOperators.ts`.
388
+ Source: `packages/tmdatagrid/src/core/filterOperators.ts`.
357
389
 
358
390
  ### HIGH Expecting a move across pinned regions to work
359
391
 
@@ -368,7 +400,7 @@ table.getColumn("salary")?.pin(false);
368
400
  moveColumn({ table, columnId: "salary", targetId: "age", side: "before" });
369
401
  ```
370
402
 
371
- Source: `src/docs/column-layout.md` (Regions).
403
+ Source: `packages/tmdatagrid/docs/column-layout.md` (Regions).
372
404
 
373
405
  ### HIGH Reaching for the v8 name of a v9 option
374
406
 
@@ -390,7 +422,7 @@ columnHelper.accessor("priority", { header: "Priority", sortFn: byRank });
390
422
  ```
391
423
 
392
424
  Source: `@tanstack/table-core` `rowSortingFeature.types.d.ts`, and
393
- `src/tmdatagrid/useTMDataGrid.tsx` (the registered `sortFns`).
425
+ `packages/tmdatagrid/src/useTMDataGrid.tsx` (the registered `sortFns`).
394
426
 
395
427
  ### MEDIUM Expecting autosize to measure every row
396
428
 
@@ -398,7 +430,7 @@ Autosizing fits the **mounted** rows plus overscan, not every row, because
398
430
  virtualization leaves the rest with no DOM to measure. A column autosized at the
399
431
  top of a long list can be too narrow for a value further down.
400
432
 
401
- Source: `src/docs/column-layout.md` (Autosizing).
433
+ Source: `packages/tmdatagrid/docs/column-layout.md` (Autosizing).
402
434
 
403
435
  ### MEDIUM Reordering a column inside a header group
404
436
 
@@ -407,7 +439,32 @@ the group header spanning columns that no longer belong to it. Grouped-header
407
439
  columns are therefore immovable in both directions, whatever `meta.enableOrdering`
408
440
  says.
409
441
 
410
- Source: `src/docs/column-layout.md` (Regions).
442
+ Source: `packages/tmdatagrid/docs/column-layout.md` (Regions).
443
+
444
+ ### MEDIUM Computing a cross-row value in accessorFn
445
+
446
+ `accessorFn` is handed one row, so a share of a total, a rank or a running
447
+ total has nothing to compute against. Derive the collection once and give the
448
+ grid the finished shape.
449
+
450
+ Wrong:
451
+
452
+ ```tsx
453
+ columnHelper.accessor((row) => (row.value / total) * 100, { id: "pctOfTotal" });
454
+ ```
455
+
456
+ Correct:
457
+
458
+ ```tsx
459
+ const rows = useMemo(() => {
460
+ const total = holdings.reduce((sum, h) => sum + h.value, 0);
461
+ return holdings.map((h) => ({ ...h, pctOfTotal: (h.value / total) * 100 }));
462
+ }, [holdings]);
463
+
464
+ columnHelper.accessor("pctOfTotal", { header: "Share" });
465
+ ```
466
+
467
+ Source: `packages/tmdatagrid/docs/columns.md` (Columns derived from the other rows).
411
468
 
412
469
  ## Reference
413
470
 
@@ -425,13 +482,12 @@ Source: `src/docs/column-layout.md` (Regions).
425
482
  | `moveColumn` | Export | `({ table, columnId, targetId, side }) => void` | – | Moves a column beside another. |
426
483
  | `moveColumnByStep` | Export | `({ table, columnId, direction }) => void` | – | Moves it one place. |
427
484
  | `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. |
485
+ | `getColumnRegion` | Export | `(columnPinning, columnId) => "start" \| "center" \| "end"` | – | Which pinned region a column is in. |
486
+ | `getColumnCapabilities(column, features).canReorder` | Export | `boolean` | – | Whether this column may move at all. |
430
487
  | `autosizeColumn` | Export | `({ table, columnId, container }) => void` | – | Fits a column to its mounted content. |
431
- | `measureColumnContentWidth` | Export | `(args) => number` | – | The measurement behind it. |
432
488
  | `getColumnLabel` · `getColumnType` · `getColumnDefaultOperator` · `isControlColumn` | Exports | – | – | What the built-in controls read off a column. |
433
489
  | `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. |
490
+ | `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. |
435
491
 
436
492
  See also: the `filtering` skill for operators and filter controls, the `editing`
437
493
  skill for the editing meta fields, and the `grouping` skill for what grouping