@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
@@ -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 useCellControlTabIndex for 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.2'
17
+ library_version: '2.0.0-beta.21'
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
@@ -70,29 +70,21 @@ a cell's contents own their own keys.
70
70
 
71
71
  ## One tab stop
72
72
 
73
- Tab from a cell leaves the grid. What makes that true is that controls inside
74
- body cells - the checkbox, the tree chevron, the details chevron - take
75
- `tabindex="-1"` while cell selection is on. Left tabbable, Tab would walk through
76
- one per mounted row, and how many that is depends on the scroll position.
73
+ The body is one tab stop in each direction. Tab from a cell leaves the grid and
74
+ Shift+Tab leaves it backwards, however many rows are mounted and whatever those
75
+ rows hold.
77
76
 
78
- They stay reachable: Enter or F2 steps in, Escape steps out, and Space ticks the
79
- row from any of its cells. Header controls are untouched - the header row is not
80
- part of cell navigation.
77
+ A control inside a body cell needs no `tabIndex`. Enter or F2 steps into the
78
+ cell and onto its first control, Escape steps back out to the cell, and Space
79
+ ticks the row from any of its cells without stepping in.
81
80
 
82
- A custom cell with a control in it wants the same treatment:
81
+ Once the focus is on a control, Tab walks the rest of that row's controls - its
82
+ open editors, the buttons in its cells, and on an open row the edit lane's save
83
+ and cancel. Past the row's last control the cursor moves to the next row's first
84
+ cell, and Shift+Tab before its first control moves to the previous row's last
85
+ cell; neither opens the row it lands on. From the last row, Tab leaves the grid.
83
86
 
84
- ```tsx
85
- import { useCellControlTabIndex } from "@jielga/tmdatagrid";
86
-
87
- const OpenButton = ({ row }) => (
88
- <Button tabIndex={useCellControlTabIndex()} onClick={() => open(row.id)}>
89
- Open
90
- </Button>
91
- );
92
- ```
93
-
94
- The hook returns `-1` while cell selection is on and `0` otherwise, so the same
95
- cell works either way.
87
+ Header controls are untouched - the header row is not part of cell navigation.
96
88
 
97
89
  ## Where the selection lives
98
90
 
@@ -123,57 +115,61 @@ Ctrl+C puts the block on the clipboard as tab-separated text with CRLF between
123
115
  rows, the format Excel, Sheets and Numbers all produce themselves. Values only:
124
116
  Excel's own copy carries no header row either.
125
117
 
126
- 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
127
119
  "Include headers" toggle. A right-click outside it moves the selection there
128
120
  first, the way a spreadsheet does. Your own `renderRowContextMenu` items are appended
129
121
  below a divider, so nothing is lost by turning cell selection on.
130
122
 
131
- The CSV is written for a Nordic Excel: a `sep=;` first line, a UTF-8 BOM, CRLF
132
- endings, semicolons between fields and a comma as the decimal mark. That
133
- 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`:
134
127
 
135
128
  ```tsx
136
- <TMDataGrid.Table
137
- cellExport={{ separator: ",", decimalComma: false, fileName: "employees" }}
138
- />
129
+ const grid = useTMDataGrid({
130
+ data,
131
+ columns,
132
+ cellSelection: "range",
133
+ exportOptions: { format: csvFormat(), fileName: "employees" },
134
+ });
139
135
  ```
140
136
 
141
- What gets written is the cell's **value**, not what it renders. Dates come out
142
- in the `sv-SE` form (`2026-07-31`), which Excel reads as a date.
143
-
144
- `exportGridToCsv({ table, options })` takes **every filtered row** instead of the
145
- selected block, with the same options and defaults. There is no built-in button
146
- for it:
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.
147
141
 
148
- ```tsx
149
- <Button onClick={() => exportGridToCsv({ table: grid.table })}>Export</Button>
150
- ```
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. The `cellExport` Table prop is
145
+ deprecated: it is converted and merged over `exportOptions` for this menu only.
151
146
 
152
147
  ## Common mistakes
153
148
 
154
- ### CRITICAL A custom cell control that breaks the single tab stop
149
+ ### CRITICAL A cell control given a tab index of its own
155
150
 
156
- A `<Button>` or `<Checkbox>` rendered in a body cell keeps its default tab index,
157
- so Tab walks through one per mounted row. How many that is depends on the scroll
158
- position, which makes the bug look intermittent.
151
+ The grid keeps every control in a body cell out of the page's tab order and
152
+ reaches them by stepping into the cell. A `<Button>` or `<Checkbox>` handed
153
+ `tabIndex={0}` puts one tab stop per mounted row back, and how many that is
154
+ depends on the scroll position, which makes the bug look intermittent.
159
155
 
160
156
  Wrong:
161
157
 
162
158
  ```tsx
163
- const OpenButton = ({ row }) => <Button onClick={() => open(row.id)}>Open</Button>;
159
+ const OpenButton = ({ row }) => (
160
+ <Button tabIndex={0} onClick={() => open(row.id)}>
161
+ Open
162
+ </Button>
163
+ );
164
164
  ```
165
165
 
166
166
  Correct:
167
167
 
168
168
  ```tsx
169
- const OpenButton = ({ row }) => (
170
- <Button tabIndex={useCellControlTabIndex()} onClick={() => open(row.id)}>
171
- Open
172
- </Button>
173
- );
169
+ const OpenButton = ({ row }) => <Button onClick={() => open(row.id)}>Open</Button>;
174
170
  ```
175
171
 
176
- Source: `src/docs/cell-selection.md` (One tab stop).
172
+ Source: `packages/tmdatagrid/docs/cell-selection.md` (One tab stop).
177
173
 
178
174
  ### HIGH Selectors written for `table` / `cell` roles
179
175
 
@@ -181,7 +177,7 @@ The grid reports `grid` and `gridcell` once cell selection is on, so a test or a
181
177
  query written against `getByRole("cell")` stops resolving the moment the option
182
178
  is set - including when `editing` turns it on implicitly.
183
179
 
184
- Source: `src/docs/cell-selection.md`, and the `testing` skill.
180
+ Source: `packages/tmdatagrid/docs/cell-selection.md`, and the `testing` skill.
185
181
 
186
182
  ### HIGH Reading the selection as row and column indices
187
183
 
@@ -196,23 +192,23 @@ const row = grid.table.getRow(focusedCell.rowId);
196
192
  const value = row.getValue(focusedCell.columnId);
197
193
  ```
198
194
 
199
- Source: `src/docs/cell-selection.md` (Where the selection lives).
195
+ Source: `packages/tmdatagrid/docs/cell-selection.md` (Where the selection lives).
200
196
 
201
197
  ### MEDIUM Expecting the export to match what the cells show
202
198
 
203
199
  A cell renders React - often a badge, a link or a formatted string - and the
204
200
  export writes the underlying value. A currency cell showing `32 000 kr` exports
205
- `32000`. Format in the data, or post-process the matrix from `buildCellMatrix`,
206
- if the file must match the screen.
201
+ `32000`. Set `meta.exportValue` on the column, or post-process the data from
202
+ `buildExportData`, if the file must match the screen.
207
203
 
208
- Source: `src/docs/cell-selection.md` (The CSV).
204
+ Source: `packages/tmdatagrid/docs/cell-selection.md` (The file).
209
205
 
210
206
  ### MEDIUM Expecting headers in the clipboard
211
207
 
212
208
  Ctrl+C copies values only, matching Excel's own copy. Headers are an option of
213
- the export menu and of `cellExport`, not of the clipboard path.
209
+ the export menu and of `exportOptions`, not of the clipboard path.
214
210
 
215
- Source: `src/docs/cell-selection.md` (Copy and export).
211
+ Source: `packages/tmdatagrid/docs/cell-selection.md` (Copy and export).
216
212
 
217
213
  ## Reference
218
214
 
@@ -220,16 +216,14 @@ Source: `src/docs/cell-selection.md` (Copy and export).
220
216
  | --- | --- | --- | --- | --- |
221
217
  | `cellSelection` | Option | `"none" \| "single" \| "range"` | `"none"`, or `"single"` under `editing` | Turns the cursor, and the rectangle, on. |
222
218
  | `onFocusedCellChange` | Callback | `(cell \| null) => void` | – | Follows the cursor. |
223
- | `cellExport` | Table prop | `TMDataGridCellExportOptions` | Nordic Excel | Separator, decimal mark, headers, file name. |
219
+ | `exportOptions` | Option | `TMDataGridExportOptions` | `DEFAULT_EXPORT_OPTIONS` | Format, file name and header row of the Export cells item. |
224
220
  | `ui.state.focusedCell` | UI state | `{ rowId, columnId } \| null` | `null` | The cursor. |
225
221
  | `ui.state.cellRange` | UI state | `{ anchor, focus } \| null` | `null` | The rectangle's two corners. |
226
222
  | `ui.actions.setFocusedCell` · `setCellRange` | UI actions | – | – | Move either from your own code. |
227
- | `useCellControlTabIndex` | Hook | `() => 0 \| -1` | – | The tab index a control inside a body cell wants. |
228
- | `exportGridToCsv` | Export | `({ table, options? }) => void` | – | Downloads every filtered row as CSV. |
229
- | `buildGridCellMatrix` · `buildCellMatrix` | Exports | – | – | The value matrix behind the file, for post-processing. |
230
- | `toClipboardText` · `toExcelCsv` · `writeClipboardText` · `downloadTextFile` | Exports | – | – | The pieces behind Ctrl+C and the file. |
231
- | `formatExportValue` | Export | `(value, options) => string` | – | One value, formatted as the export would. |
232
- | `DEFAULT_CELL_EXPORT_OPTIONS` | Export | object | – | The Nordic Excel defaults, to spread over. |
223
+ | `buildExportData` | Export | `({ table, rows, bounds }) => TMDataGridExportData` | – | The rectangle's values, with `bounds`; the whole grid without. |
224
+ | `toClipboardText` · `writeClipboardText` | Exports | – | – | The pieces behind Ctrl+C. |
225
+ | `formatExportValue` | Export | `(value, options) => string` | – | One value, formatted as the text formats would. |
226
+ | `cellExport` | Table prop | `TMDataGridCellExportOptions` | – | Deprecated; merged over `exportOptions` for the cell-range menu only. |
233
227
  | `isSameCell` · `resolveCellMove` | Exports | – | – | The cursor arithmetic, for a custom navigator. |
234
228
  | `resolveRangeBounds` · `isWithinBounds` · `boundsEdges` · `boundsCellCount` | Exports | – | – | The rectangle arithmetic. |
235
229
  | `data-focused` | Data attribute | – | – | On the focused cell. |
@@ -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.2'
19
+ library_version: '2.0.0-beta.21'
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
@@ -55,6 +55,26 @@ const columns = columnHelper.columns([
55
55
  Define columns at module scope. A new array on every render rebuilds the table's
56
56
  column model.
57
57
 
58
+ A dotted `accessorKey` reads a nested field, and the column id it derives
59
+ replaces the dots: `accessorKey: "address.city"` makes column id
60
+ `address_city`, while the edit path stays `"address.city"`. Anything that
61
+ addresses the column by id - `initialState`, `editing.columns`, `moveColumn`,
62
+ a test selector - takes the underscore form.
63
+
64
+ `columnHelper.group` nests columns under a shared header; `columns` takes
65
+ another `columnHelper.columns` call, not a bare array:
66
+
67
+ ```tsx
68
+ columnHelper.group({
69
+ id: "person",
70
+ header: "Person",
71
+ columns: columnHelper.columns([
72
+ columnHelper.accessor("firstName", { header: "First" }),
73
+ columnHelper.accessor("lastName", { header: "Last" }),
74
+ ]),
75
+ });
76
+ ```
77
+
58
78
  ## meta
59
79
 
60
80
  | Field | Type | Default | Description |
@@ -77,7 +97,8 @@ which is why they are in neither.
77
97
 
78
98
  | Field | Type | Default | What it does |
79
99
  | --- | --- | --- | --- |
80
- | `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. |
81
102
  | `control` | `TMDataGridFilterControlComponent` | By `meta.type` | Replaces the value control in this column's filter row. Module scope. |
82
103
 
83
104
  `meta.edit`:
@@ -154,21 +175,26 @@ consumer code.
154
175
 
155
176
  All three write state that persists together, so a grid comes back arranged the
156
177
  way it was left. `resetSettings()` from the hook clears visibility, order,
157
- 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
158
179
  layout**.
159
180
 
160
181
  **Hiding** is `columnVisibility`, driven by "Hide column" in a column menu and by
161
- `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.
162
185
 
163
186
  **Pinning** is "Pin to left" / "Pin to right" in the column menu. A pinned
164
187
  column also becomes fixed-width: sticky offsets are computed from `getSize()`,
165
188
  which cannot resolve an `fr` value, so the grid stores the rendered width in
166
- `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.
167
193
 
168
194
  **Ordering** is header dragging plus "Move left" / "Move right". A column can
169
195
  only move **within its own pinned region** - pinning splits the grid into left,
170
196
  centre and right, then `columnOrder` sequences the centre while
171
- `columnPinning.left` and `.right` sequence the pinned lanes. Unpin a column
197
+ `columnPinning.start` and `.end` sequence the pinned lanes. Unpin a column
172
198
  first to move it out of one. A neighbour that cannot move acts as a wall rather
173
199
  than being stepped over, and columns inside a header group are not movable in
174
200
  either direction, because `columnOrder` sequences leaf columns.
@@ -224,7 +250,7 @@ Standard TanStack column options. Each also removes the corresponding interface.
224
250
  | Option | Effect when `false` |
225
251
  | --- | --- |
226
252
  | `enableSorting` | No sort indicator, no sort menu items, no click-to-sort. |
227
- | `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. |
228
254
  | `enableHiding` | No hide menu item. Checkbox disabled in the column manager. |
229
255
  | `enablePinning` | No pin menu items. |
230
256
  | `enableResizing` | The divider is displayed but cannot be dragged. |
@@ -246,7 +272,7 @@ asks for it.
246
272
  | Checkbox | `SELECT_COLUMN_ID` | Selection is on and the mode has checkboxes |
247
273
  | Tree | `GROUP_COLUMN_ID` | A column is grouped |
248
274
  | Details | `DETAILS_COLUMN_ID` | `renderDetails` is set |
249
- | Edit | `EDIT_COLUMN_ID` | Row mode, draft mode, or `editing.onRowDelete` |
275
+ | Edit | `EDIT_COLUMN_ID` | Row mode, `editing.draft`, or `editing.onRowDelete` |
250
276
 
251
277
  They are structural: fixed width, no column menu, and they cannot be sorted,
252
278
  filtered, resized, re-pinned or moved. The checkbox lane anchors the left pinned
@@ -279,7 +305,55 @@ columnHelper.accessor("email", {
279
305
  });
280
306
  ```
281
307
 
282
- 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).
335
+
336
+ ### HIGH Addressing a dotted column by its accessor key
337
+
338
+ A dotted `accessorKey` produces a column id with underscores, so state and
339
+ calls keyed by column id silently match nothing when given the dotted form.
340
+
341
+ Wrong:
342
+
343
+ ```tsx
344
+ initialState: { columnVisibility: { "address.city": false } },
345
+ ```
346
+
347
+ Correct:
348
+
349
+ ```tsx
350
+ initialState: { columnVisibility: { address_city: false } },
351
+ ```
352
+
353
+ The edit path is the exception: `meta.edit.field` and validation issue paths
354
+ stay dotted, because they address the data, not the column.
355
+
356
+ Source: `packages/tmdatagrid/docs/columns.md` (The column helper).
283
357
 
284
358
  ### CRITICAL A component header without `meta.label`
285
359
 
@@ -302,7 +376,7 @@ columnHelper.accessor("fullName", {
302
376
  });
303
377
  ```
304
378
 
305
- Source: `src/tmdatagrid/core/columnUtils.ts`.
379
+ Source: `packages/tmdatagrid/src/core/columnUtils.ts`.
306
380
 
307
381
  ### HIGH A numeric column without `meta.type`
308
382
 
@@ -311,7 +385,7 @@ Source: `src/tmdatagrid/core/columnUtils.ts`.
311
385
  as text - `"9"` above `"10"`. The column still sorts and filters, which is why
312
386
  it is easy to miss.
313
387
 
314
- Source: `src/tmdatagrid/core/filterOperators.ts`.
388
+ Source: `packages/tmdatagrid/src/core/filterOperators.ts`.
315
389
 
316
390
  ### HIGH Expecting a move across pinned regions to work
317
391
 
@@ -326,7 +400,7 @@ table.getColumn("salary")?.pin(false);
326
400
  moveColumn({ table, columnId: "salary", targetId: "age", side: "before" });
327
401
  ```
328
402
 
329
- Source: `src/docs/column-layout.md` (Regions).
403
+ Source: `packages/tmdatagrid/docs/column-layout.md` (Regions).
330
404
 
331
405
  ### HIGH Reaching for the v8 name of a v9 option
332
406
 
@@ -348,7 +422,7 @@ columnHelper.accessor("priority", { header: "Priority", sortFn: byRank });
348
422
  ```
349
423
 
350
424
  Source: `@tanstack/table-core` `rowSortingFeature.types.d.ts`, and
351
- `src/tmdatagrid/useTMDataGrid.tsx` (the registered `sortFns`).
425
+ `packages/tmdatagrid/src/useTMDataGrid.tsx` (the registered `sortFns`).
352
426
 
353
427
  ### MEDIUM Expecting autosize to measure every row
354
428
 
@@ -356,7 +430,7 @@ Autosizing fits the **mounted** rows plus overscan, not every row, because
356
430
  virtualization leaves the rest with no DOM to measure. A column autosized at the
357
431
  top of a long list can be too narrow for a value further down.
358
432
 
359
- Source: `src/docs/column-layout.md` (Autosizing).
433
+ Source: `packages/tmdatagrid/docs/column-layout.md` (Autosizing).
360
434
 
361
435
  ### MEDIUM Reordering a column inside a header group
362
436
 
@@ -365,7 +439,32 @@ the group header spanning columns that no longer belong to it. Grouped-header
365
439
  columns are therefore immovable in both directions, whatever `meta.enableOrdering`
366
440
  says.
367
441
 
368
- 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).
369
468
 
370
469
  ## Reference
371
470
 
@@ -383,13 +482,13 @@ Source: `src/docs/column-layout.md` (Regions).
383
482
  | `moveColumn` | Export | `({ table, columnId, targetId, side }) => void` | – | Moves a column beside another. |
384
483
  | `moveColumnByStep` | Export | `({ table, columnId, direction }) => void` | – | Moves it one place. |
385
484
  | `getStepTargetColumn` | Export | `(args) => Column \| null` | – | What a step would swap with, or `null` at a region edge. |
386
- | `getColumnRegion` | Export | `(column) => "left" \| "center" \| "right"` | – | Which pinned region a column is in. |
485
+ | `getColumnRegion` | Export | `(column) => "start" \| "center" \| "end"` | – | Which pinned region a column is in. |
387
486
  | `isColumnReorderable` | Export | `(column, features) => boolean` | – | Whether this column may move at all. |
388
487
  | `autosizeColumn` | Export | `({ table, columnId, container }) => void` | – | Fits a column to its mounted content. |
389
488
  | `measureColumnContentWidth` | Export | `(args) => number` | – | The measurement behind it. |
390
489
  | `getColumnLabel` · `getColumnType` · `getColumnDefaultOperator` · `isControlColumn` | Exports | – | – | What the built-in controls read off a column. |
391
490
  | `SELECT_COLUMN_ID` · `GROUP_COLUMN_ID` · `DETAILS_COLUMN_ID` · `EDIT_COLUMN_ID` · `ROW_NUMBER_COLUMN_ID` | Exports | ids | – | The generated lanes. |
392
- | `TMDataGrid.ColumnsButton` · `TMDataGrid.ColumnsPanel` | Components | – | – | Manage columns, and Reset layout. |
491
+ | `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. |
393
492
 
394
493
  See also: the `filtering` skill for operators and filter controls, the `editing`
395
494
  skill for the editing meta fields, and the `grouping` skill for what grouping