@jielga/tmdatagrid 2.0.0-beta.8 → 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 (155) hide show
  1. package/README.md +5 -212
  2. package/dist/index.d.ts +1323 -796
  3. package/dist/index.js +4719 -3193
  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 +69 -78
  47. package/skills/columns/SKILL.md +90 -34
  48. package/skills/data/SKILL.md +86 -16
  49. package/skills/editing/SKILL.md +83 -50
  50. package/skills/editing/references/common-mistakes.md +77 -69
  51. package/skills/editing/references/editing-api.md +31 -23
  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 +8 -8
  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/TMDataGridContext.ts → TMDataGridContext.ts} +7 -19
  63. package/src/{tmdatagrid/components → components}/TMDataGrid.module.css +7 -1
  64. package/src/{tmdatagrid/components → components}/TMDataGrid.tsx +38 -21
  65. package/src/{tmdatagrid/components → components}/TMDataGridCellEditor.tsx +73 -7
  66. package/src/{tmdatagrid/components → components}/TMDataGridColumnsPanel.module.css +5 -1
  67. package/src/{tmdatagrid/components → components}/TMDataGridColumnsPanel.tsx +47 -55
  68. package/src/{tmdatagrid/components → components}/TMDataGridDetailsColumn.tsx +9 -55
  69. package/src/{tmdatagrid/components → components}/TMDataGridDraftActions.tsx +41 -24
  70. package/src/{tmdatagrid/components → components}/TMDataGridEditColumn.tsx +23 -63
  71. package/src/components/TMDataGridEntryRows.tsx +354 -0
  72. package/src/components/TMDataGridExportPicker.module.css +77 -0
  73. package/src/components/TMDataGridExportPicker.tsx +234 -0
  74. package/src/components/TMDataGridFilterPanel.module.css +54 -0
  75. package/src/components/TMDataGridFilterPanel.tsx +348 -0
  76. package/src/{tmdatagrid/components → components}/TMDataGridFilterPills.tsx +15 -8
  77. package/src/components/TMDataGridFilterSurface.module.css +54 -0
  78. package/src/components/TMDataGridFilterSurface.tsx +167 -0
  79. package/src/{tmdatagrid/components → components}/TMDataGridFooter.tsx +53 -90
  80. package/src/{tmdatagrid/components → components}/TMDataGridGroupColumn.tsx +9 -72
  81. package/src/{tmdatagrid/components → components}/TMDataGridHeaderCell.module.css +12 -2
  82. package/src/{tmdatagrid/components → components}/TMDataGridHeaderCell.tsx +58 -21
  83. package/src/components/TMDataGridHeaderFilterRow.module.css +51 -0
  84. package/src/components/TMDataGridHeaderFilterRow.tsx +301 -0
  85. package/src/components/TMDataGridMenu.tsx +357 -0
  86. package/src/{tmdatagrid/components → components}/TMDataGridSelectColumn.tsx +15 -53
  87. package/src/{tmdatagrid/components → components}/TMDataGridTable.module.css +88 -65
  88. package/src/{tmdatagrid/components → components}/TMDataGridTable.tsx +579 -165
  89. package/src/{tmdatagrid/components → components}/TMDataGridToolbar.module.css +5 -0
  90. package/src/components/TMDataGridToolbar.tsx +181 -0
  91. package/src/{tmdatagrid/components → components}/editors/TMDataGridBooleanEditor.tsx +3 -3
  92. package/src/{tmdatagrid/components → components}/editors/TMDataGridDateEditor.tsx +3 -3
  93. package/src/{tmdatagrid/components → components}/editors/TMDataGridMultiSelectEditor.tsx +3 -3
  94. package/src/{tmdatagrid/components → components}/editors/TMDataGridNumberEditor.tsx +3 -3
  95. package/src/{tmdatagrid/components → components}/editors/TMDataGridSelectEditor.tsx +3 -3
  96. package/src/{tmdatagrid/components → components}/editors/TMDataGridStringEditor.tsx +3 -3
  97. package/src/{tmdatagrid/components → components}/editors/editorShared.ts +16 -2
  98. package/src/{tmdatagrid/components → components}/filters/DgAutocompleteFilter.tsx +5 -4
  99. package/src/{tmdatagrid/components → components}/filters/DgDateRangeFilter.tsx +22 -5
  100. package/src/{tmdatagrid/components → components}/filters/DgRangeSliderFilter.tsx +5 -1
  101. package/src/{tmdatagrid/components → components}/filters/DgTriStateFilter.tsx +5 -1
  102. package/src/{tmdatagrid/components → components}/filters/TMDataGridFilterValueInput.tsx +44 -28
  103. package/src/components/filters/controlLayout.ts +32 -0
  104. package/src/components/filters/filterControlFor.ts +65 -0
  105. package/src/components/generatedColumns.tsx +187 -0
  106. package/src/{tmdatagrid/components → components}/icons.ts +1 -0
  107. package/src/{tmdatagrid/components → components}/sticky.module.css +44 -0
  108. package/src/components/useHideableColumns.ts +52 -0
  109. package/src/{tmdatagrid/core → core}/autosize.ts +5 -2
  110. package/src/{tmdatagrid/core → core}/capabilities.ts +5 -5
  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 +1172 -388
  118. package/src/{tmdatagrid/core → core}/editorFocus.ts +8 -4
  119. package/src/core/export.ts +704 -0
  120. package/src/{tmdatagrid/core → core}/filterControls.ts +38 -1
  121. package/src/{tmdatagrid/core → core}/filterOperators.ts +64 -1
  122. package/src/core/filterSurface.ts +99 -0
  123. package/src/{tmdatagrid/core → core}/grouping.ts +21 -0
  124. package/src/{tmdatagrid/core → core}/labels.ts +51 -6
  125. package/src/{tmdatagrid/core → core}/labelsSv.ts +27 -6
  126. package/src/core/pageReset.ts +120 -0
  127. package/src/core/pagination.ts +81 -0
  128. package/src/{tmdatagrid/core → core}/persistence.ts +22 -5
  129. package/src/{tmdatagrid/core → core}/summary.ts +20 -4
  130. package/src/{tmdatagrid/index.ts → index.ts} +70 -36
  131. package/src/{tmdatagrid/useTMDataGrid.tsx → useTMDataGrid.tsx} +534 -123
  132. package/src/useTMDataGridExport.ts +78 -0
  133. package/src/tmdatagrid/components/TMDataGridEntryRows.tsx +0 -298
  134. package/src/tmdatagrid/components/TMDataGridFilterPanel.module.css +0 -35
  135. package/src/tmdatagrid/components/TMDataGridFilterPanel.tsx +0 -354
  136. package/src/tmdatagrid/components/TMDataGridToolbar.tsx +0 -161
  137. package/src/tmdatagrid/core/cellExport.ts +0 -320
  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}/cellNavigation.ts +0 -0
  145. /package/src/{tmdatagrid/core → core}/cellRange.ts +0 -0
  146. /package/src/{tmdatagrid/core → core}/controlledState.ts +0 -0
  147. /package/src/{tmdatagrid/core → core}/draftCellContext.ts +0 -0
  148. /package/src/{tmdatagrid/core → core}/expanding.ts +0 -0
  149. /package/src/{tmdatagrid/core → core}/matchHighlight.ts +0 -0
  150. /package/src/{tmdatagrid/core → core}/quickSearch.ts +0 -0
  151. /package/src/{tmdatagrid/core → core}/resizePreview.ts +0 -0
  152. /package/src/{tmdatagrid/core → core}/rowPinning.ts +0 -0
  153. /package/src/{tmdatagrid/core → core}/rowSelection.ts +0 -0
  154. /package/src/{tmdatagrid/core → core}/sizes.ts +0 -0
  155. /package/src/{tmdatagrid/core → core}/useSettledTableState.ts +0 -0
@@ -0,0 +1,182 @@
1
+ # Visibility, pinning, ordering and size
2
+
3
+ Four things a user can change about the layout of the grid, and one button that
4
+ resets them. All four write state that
5
+ [persists](/docs/use-tm-data-grid#persist) together, so a grid comes back
6
+ arranged the way it was left. Each is also an item in the
7
+ [column header menu](/docs/column-menu).
8
+
9
+ ```demo
10
+ file: columns/ColumnLayout.tsx
11
+ hint: Drag a header to reorder · pin or hide from a column menu · drag a divider to resize, or double-click it to fit the content.
12
+ ```
13
+
14
+ ## Hiding
15
+
16
+ **Hide column** in any column menu, and the column chooser for the whole list at once: a search field, one checkbox per column, show/hide all, and **Reset layout**.
17
+ The chooser is `TMDataGrid.Menu.Columns` in the [grid menu](/docs/menu), **Manage columns** in every column menu (a submenu of the same items), and `TMDataGrid.ColumnsPanel` as plain controls for a host that is not a menu.
18
+
19
+ `enableHiding: false` removes all of it; on a column it removes that column's
20
+ menu item and leaves it out of the panel, which lists what can be hidden and
21
+ nothing else. Show/hide all covers the same list, so a column switched off this
22
+ way keeps whatever visibility it was given. The state is TanStack's
23
+ `columnVisibility`.
24
+
25
+ The generated lanes are all `enableHiding: false` and never appear in the
26
+ panel. Each follows the feature that adds it rather than a setting of its own.
27
+
28
+ ## Pinning
29
+
30
+ **Pin to left** and **Pin to right** are in each column menu. The current
31
+ position is marked, and choosing it again unpins. Pinned columns are sticky
32
+ within the scroll container. The boundary is marked with a divider and a short
33
+ gradient band, which fades in only while it is covering content.
34
+
35
+ Headers, cells and grid tracks are ordered left, centre, right from the same
36
+ source, so pinning does not change a column's position relative to its group.
37
+
38
+ A pinned column also becomes fixed-width, since sticky offsets cannot be
39
+ computed from an `fr` value. The grid writes the column's rendered width into
40
+ `columnSizing` as it is pinned, so nothing jumps.
41
+
42
+ To start pinned, set `initialState.columnPinning`. The slice is TanStack's
43
+ full `ColumnPinningState`, so a partial does not compile - name both sides.
44
+ A column pinned at mount has no rendered width to store, so it takes its
45
+ `size` - TanStack's default of `150` where none is set - and `minSize` does
46
+ not apply. Give such a column an explicit `size`:
47
+
48
+ ```tsx
49
+ columnHelper.accessor("registration", { header: "Registration", size: 220 });
50
+
51
+ initialState: { columnPinning: { start: ["registration"], end: [] } }
52
+ ```
53
+
54
+ The generated lanes stay outside both pinned lanes: pinning a column right puts
55
+ it to the left of the edit lane, so the row's Save, Cancel and Delete remain
56
+ last in the row.
57
+
58
+ ## Ordering
59
+
60
+ Drag a column header sideways to move it. The header being dragged dims, and a
61
+ bar marks the edge the column will land against. **Move left** and **Move
62
+ right** in the column menu do the same one step at a time, without a pointer.
63
+ Both move the header, its cells and its filter entry together.
64
+
65
+ ```tsx
66
+ const grid = useTMDataGrid({ data, columns, enableColumnOrdering: false });
67
+ ```
68
+
69
+ `enableColumnOrdering` is defined by the grid rather than by TanStack, which
70
+ ships the ordering state and APIs but no `enable` option. The per-column form is
71
+ `meta.enableOrdering`.
72
+
73
+ ### Regions
74
+
75
+ A column can only move **within its own pinned region**; a header in another
76
+ region does not accept the drop. This follows TanStack's ordering pipeline:
77
+ pinning splits the grid into left, centre and right, then `columnOrder`
78
+ sequences the centre while `columnPinning.start` and `.end` sequence the
79
+ pinned lanes. Unpin a column first to move it out of one.
80
+
81
+ A neighbour that cannot be moved blocks the move; it is not stepped over. The
82
+ checkbox column sets `meta.enableOrdering: false`, so nothing can be placed in
83
+ front of it.
84
+
85
+ Columns inside a header group cannot be moved either, in either direction:
86
+ `columnOrder` sequences leaf columns, so moving one would leave the group header
87
+ spanning columns that no longer belong to it.
88
+
89
+ ### Moving from your own code
90
+
91
+ ```tsx
92
+ import { moveColumn, moveColumnByStep } from "@jielga/tmdatagrid";
93
+
94
+ moveColumn({ table, columnId: "salary", targetId: "age", side: "before" });
95
+ moveColumnByStep({ table, columnId: "salary", direction: 1 });
96
+ ```
97
+
98
+ Both are no-ops for a move that is not allowed, including one across regions.
99
+ `getStepTargetColumn({ table, columnId, direction })` returns the column a step
100
+ would swap with, or `null` at the edge of a region. The menu items use it to
101
+ decide whether to disable themselves.
102
+
103
+ ### State
104
+
105
+ Ordering writes `columnOrder` as the **complete** leaf order, including hidden
106
+ and pinned columns, so a column keeps its position when it is later shown or
107
+ unpinned. Moving a pinned column also rewrites its `columnPinning` array. A
108
+ column added to the definitions later is not in the stored order and is appended
109
+ at the end until it is moved.
110
+
111
+ ## Sizing
112
+
113
+ Columns are fluid by default. Each track is `minmax(minSize, flex fr)`.
114
+
115
+ | Column option | Effect |
116
+ | --- | --- |
117
+ | `minSize` | Minimum width, and the column's contribution to the grid minimum width. Defaults to `80`. |
118
+ | `meta.flex` | Share of the remaining width. Defaults to `1`. |
119
+ | `minSize === maxSize` | Fixed width. The column is never fluid. |
120
+ | `size` | Applied once the column becomes fixed by resizing or pinning. |
121
+
122
+ Drag a divider to resize. A column switches to a fixed pixel width the moment
123
+ it is resized or pinned, and the width is stored in `columnSizing`. The drag
124
+ starts from the width the column is rendered with, and the grid paints it on
125
+ its own column tracks while the pointer moves; the width reaches `columnSizing`
126
+ when the pointer is released. `columnResizeMode: "onChange"` publishes it on
127
+ every move instead, at the cost of a render of the grid for each one.
128
+
129
+ ### Autosizing
130
+
131
+ Double-click a column's resize divider to size it to its widest mounted
132
+ content. **Autosize column** in the column menu does the same without a
133
+ pointer, and `meta.autoSize: true` runs it once after the first rows render,
134
+ unless a persisted or user-set width already applies to the column.
135
+
136
+ **Mounted content only.** Under virtualization the unmounted rows cannot be
137
+ measured, so the width fits the visible window plus overscan. The result is
138
+ clamped to `minSize`/`maxSize` and written into `columnSizing`, so it persists
139
+ with the other widths and a later drag overrides it.
140
+
141
+ `meta.autoSize` waits for content: on a grid whose rows are fetched, the first
142
+ render has a header and no cells, so the column is sized on the render its
143
+ first cells appear in.
144
+
145
+ `autosizeColumn({ table, columnId, container })` is exported for menus and
146
+ consumer code; `container` is the grid's scroll container, or any ancestor of
147
+ the column's cells.
148
+
149
+ ## Reset the layout
150
+
151
+ `resetSettings()` from the hook clears visibility, order, pinning and widths in
152
+ one call. The columns panel offers it as **Reset layout**.
153
+
154
+ ```tsx
155
+ const { resetSettings } = useTMDataGrid({ data, columns });
156
+ ```
157
+
158
+ ## Reference
159
+
160
+ | Name | Kind | Type | Default | What it does |
161
+ | --- | --- | --- | --- | --- |
162
+ | `enableHiding` | Table option | `boolean` | `true` | Also a column option. `false` removes hiding entirely. |
163
+ | `enableColumnPinning` | Table option | `boolean` | `true` | `false` removes the pin menu items. |
164
+ | `enablePinning` | Column option | `boolean` | `true` | `false` for one column. |
165
+ | `enableColumnOrdering` | Option | `boolean` | `true` | Header dragging and the move menu items. Grid-defined. |
166
+ | `meta.enableOrdering` | Column meta | `boolean` | `true` | `false` keeps one column where it is. |
167
+ | `enableColumnResizing` | Table option | `boolean` | `true` | `false` leaves the divider as a separator only. |
168
+ | `enableResizing` | Column option | `boolean` | `true` | `false` for one column. |
169
+ | `meta.flex` | Column meta | `number` | `1` | Share of the remaining width. |
170
+ | `meta.autoSize` | Column meta | `boolean` | `false` | Autosize once, on the render the column's first cells appear in. |
171
+ | `minSize` / `maxSize` / `size` | Column options | `number` | `80` / – / – | Width bounds, and the fixed width once one applies. |
172
+ | `resetSettings` | Hook return | `() => void` | – | Clears visibility, order, pinning and widths. |
173
+ | `moveColumn` | Export | `({ table, columnId, targetId, side }) => void` | – | Moves a column beside another. |
174
+ | `moveColumnByStep` | Export | `({ table, columnId, direction }) => void` | – | Moves it one place. |
175
+ | `MoveColumnArgs` · `ColumnStepArgs` | Types | – | – | What `moveColumn` takes, and what `moveColumnByStep` and `getStepTargetColumn` take. |
176
+ | `TMDataGridDropSide` | Type | `"before" \| "after"` | – | The `side` of `MoveColumnArgs`: which edge of the target column the moved column lands on. |
177
+ | `getStepTargetColumn` | Export | `(args) => Column \| null` | – | What a step would swap with, or `null` at a region edge. |
178
+ | `keepGeneratedColumnsOutermost` | Export | `(columnPinning) => ColumnPinningState` | – | Puts the generated lanes back on the outside of both pinned lanes. The grid runs it after every pin. |
179
+ | `getColumnRegion` | Export | `(columnPinning, columnId) => "start" \| "center" \| "end"` | – | Which pinned region a column is in. |
180
+ | `TMDataGridColumnRegion` | Type | `"start" \| "center" \| "end"` | – | What `getColumnRegion` returns. |
181
+ | `autosizeColumn` | Export | `({ table, columnId, container }) => void` | – | Fits a column to its mounted content. |
182
+ | `TMDataGrid.Menu.Columns` · `TMDataGrid.ColumnsPanel` | Components | – | – | The column chooser, as menu items and as plain controls. See [Grid menu](/docs/menu). |
@@ -0,0 +1,66 @@
1
+ # Column header menu
2
+
3
+ The menu on every column header.
4
+ It opens from the header's menu button and from a right-click on the header.
5
+
6
+ ```demo
7
+ file: columns/ColumnMenuItems.tsx
8
+ hint: The ID column has no menu; every other menu ends with Column statistics.
9
+ ```
10
+
11
+ ## Items
12
+
13
+ The menu shows each group only when the column supports it:
14
+
15
+ | Item | Shown when |
16
+ | --- | --- |
17
+ | Sort by ASC · Sort by DESC | The column can sort. See [Sorting](/docs/sorting) |
18
+ | Filter | The column can filter and `filters.inHeader` is off. See [Filtering](/docs/filtering) |
19
+ | Group by · Ungroup | The column can group. See [Grouping](/docs/grouping) |
20
+ | Expand all groups · Collapse all groups | Grouping is active |
21
+ | Pin to left · Pin to right · Unpin | The column can pin. Unpin only on a pinned column. See [Column layout](/docs/column-layout#pinning) |
22
+ | Move left · Move right | The column can be reordered and has a neighbour in its region. See [Column layout](/docs/column-layout#ordering) |
23
+ | Autosize column | The column can resize. See [Column layout](/docs/column-layout#autosizing) |
24
+ | Hide column | The column can hide |
25
+ | Manage columns | Any column can hide |
26
+
27
+ A divider separates the groups.
28
+ Each option that turns a feature off also removes its items; the full list is in [What each switch removes](/docs/use-tm-data-grid#what-each-switch-removes).
29
+ A column whose menu would be empty has no menu button.
30
+ Group headers and the generated columns (checkbox, details, edit, row number) have no menu.
31
+ The item texts come from `labels`; see [Localization](/docs/localization).
32
+
33
+ ## Change the items
34
+
35
+ `renderColumnMenuItems` on `TMDataGrid.Table` sets the contents of every column's menu.
36
+ It receives the items the grid would render and returns the list to render:
37
+
38
+ ```tsx
39
+ <TMDataGrid.Table<Employee>
40
+ renderColumnMenuItems={({ column, internalItems }) => [
41
+ ...internalItems,
42
+ <Menu.Divider key="stats-divider" />,
43
+ <Menu.Item key="stats" onClick={() => showStats(column.id)}>
44
+ Column statistics
45
+ </Menu.Item>,
46
+ ]}
47
+ />
48
+ ```
49
+
50
+ - `internalItems` - the built-in items in order, dividers included
51
+ - return `internalItems` unchanged to keep the default menu
52
+ - add items around it to extend the menu
53
+ - return other items to replace it
54
+ - return `[]` to remove the menu button
55
+
56
+ The function runs for every column that has a menu; branch on `column.id` for a per-column menu.
57
+ A trailing divider is dropped.
58
+ Give every item a `key`.
59
+
60
+ ## Reference
61
+
62
+ | Name | Kind | Type | Default | What it does |
63
+ | --- | --- | --- | --- | --- |
64
+ | `renderColumnMenuItems` | Table prop | `TMDataGridColumnMenuItemsRenderer` | – | Sets the column menu's contents. An empty list removes the menu button. |
65
+ | `TMDataGridColumnMenuItemsRenderer` | Type | `(args: TMDataGridColumnMenuItemsArgs) => ReactNode[]` | – | The function `renderColumnMenuItems` takes. |
66
+ | `TMDataGridColumnMenuItemsArgs` | Type | `{ column, table, internalItems }` | – | What the function receives. |
@@ -0,0 +1,268 @@
1
+ # Defining columns
2
+
3
+ A column declares where its value comes from, what kind of value it is, and how
4
+ to render it. Which filter operators it offers, which editor it opens and how
5
+ it sorts all follow from `meta.type`.
6
+
7
+ ## The column helper
8
+
9
+ `createTMDataGridColumnHelper<TData>()` returns a TanStack column helper bound
10
+ to the grid's feature set, so that `meta` and `filterFn` are correctly typed.
11
+ The `meta.options` and `meta.edit.enabled` callbacks receive rows typed as
12
+ `TData`, so `row.original` needs no cast.
13
+
14
+ ```tsx
15
+ const columnHelper = createTMDataGridColumnHelper<Employee>();
16
+
17
+ const columns = columnHelper.columns([
18
+ columnHelper.accessor("salary", {
19
+ header: "Salary",
20
+ minSize: 130,
21
+ meta: { type: "number", align: "right" },
22
+ cell: (info) => formatSek(info.getValue()),
23
+ }),
24
+ columnHelper.accessor((row) => `${row.firstName} ${row.lastName}`, {
25
+ id: "fullName",
26
+ header: "Full name",
27
+ meta: { label: "Full name" },
28
+ }),
29
+ ]);
30
+ ```
31
+
32
+ **Define columns at module scope.** A new array on every render rebuilds the
33
+ table's column model and discards the user's column widths and order.
34
+
35
+ ```demo
36
+ file: getting-started/ColumnDefinitions.tsx
37
+ ```
38
+
39
+ An accessor may be a key of the row or a function over it. A function needs an
40
+ explicit `id`, and a `meta.label` for the name shown in menus and the columns
41
+ panel.
42
+
43
+ A dotted `accessorKey` reads a nested field, and the column id it derives
44
+ replaces the dots: `accessorKey: "address.city"` makes column id
45
+ `address_city`, while the edit path stays `"address.city"`. Anything that
46
+ addresses the column by id - `initialState`, `editing.columns`, `moveColumn`,
47
+ a test selector - takes the underscore form; the dotted form silently matches
48
+ nothing.
49
+
50
+ ### Columns derived from the other rows
51
+
52
+ `accessorFn` is handed one row, so a value that depends on the rest - a share
53
+ of a total, a rank, a running total - cannot be an accessor. Derive the
54
+ collection once and hand the grid the finished shape; the column is then a
55
+ plain `accessorKey`:
56
+
57
+ ```tsx
58
+ const rows = useMemo(() => {
59
+ const total = holdings.reduce((sum, holding) => sum + holding.value, 0);
60
+
61
+ return holdings.map((holding) => ({
62
+ ...holding,
63
+ pctOfTotal: (holding.value / total) * 100,
64
+ }));
65
+ }, [holdings]);
66
+
67
+ columnHelper.accessor("pctOfTotal", {
68
+ header: "Share",
69
+ meta: { type: "number", align: "right" },
70
+ cell: (info) => `${info.getValue().toFixed(1)}%`,
71
+ });
72
+ ```
73
+
74
+ [A portfolio rebalancer](/docs/portfolio-rebalancer) works one through, from
75
+ the derived rows to a validator that reads them all.
76
+
77
+ ## meta
78
+
79
+ `meta` carries what a TanStack column definition has no field for. What the
80
+ column is sits at the top level; what the filter panel and the edit engine do
81
+ with it sits in the `filter` and `edit` namespaces.
82
+ Its type is `TMDataGridColumnMeta`.
83
+
84
+ | Field | Type | Default | Description |
85
+ | --- | --- | --- | --- |
86
+ | `label` | `string` | String header, or column id | Name used in menus and the column manager. Required when `header` is a component. |
87
+ | `type` | `"string" \| "number" \| "boolean" \| "date" \| "select" \| "multiSelect"` | `"string"` | What the values are. Selects the filter operators, the filter control and the cell editor. |
88
+ | `options` | `TMDataGridOptionsSource` | - | The choices of a `select` / `multiSelect` column. See [Options](#options). |
89
+ | `flex` | `number` | `1` | Share of the remaining width. |
90
+ | `align` | `"left" \| "right" \| "center"` | `"left"` | Alignment, applied to both header and cells. |
91
+ | `autoSize` | `boolean` | `false` | Fit the column to its content once, on the render its first cells appear in. |
92
+ | `enableOrdering` | `boolean` | `true` | `false` keeps the column where it is. |
93
+ | `filter` | `TMDataGridColumnFilterOptions` | - | How this column filters. See [meta.filter](#metafilter). |
94
+ | `edit` | `TMDataGridColumnEditOptions` | - | How this column is edited. See [meta.edit](#metaedit). |
95
+
96
+ ### meta.filter
97
+
98
+ | Field | Type | Default | Description |
99
+ | --- | --- | --- | --- |
100
+ | `defaultOperator` | `TMDataGridFilterOperator` | The type's default | The operator a fresh filter starts with. See [Filtering](/docs/filtering#operators). |
101
+ | `control` | `TMDataGridFilterControlComponent` | By type and operator | Replaces the filter panel's value control. See [Filtering](/docs/filtering#replacing-the-value-control). |
102
+
103
+ ```tsx
104
+ meta: {
105
+ type: "number",
106
+ filter: { defaultOperator: "between", control: DgRangeSliderFilter },
107
+ }
108
+ ```
109
+
110
+ ### meta.edit
111
+
112
+ | Field | Type | Default | Description |
113
+ | --- | --- | --- | --- |
114
+ | `enabled` | `boolean \| (row) => boolean` | `true` | Whether cells in this column may be edited. See [Editing](/docs/editing#which-cells-edit). |
115
+ | `field` | `string` | The `accessorKey` | The data path an edit writes to, for a column built on `accessorFn`. |
116
+ | `editor` | `TMDataGridEditorComponent` | By `type` | Replaces the cell editor. See [Editors](/docs/editors#writing-your-own). |
117
+ | `validate` | `TMDataGridFieldValidate` | - | Per-cell validation. See [Validation](/docs/editors#validation). |
118
+ | `mapValue` | `TMDataGridEditValueMap` | - | Maps each value an editor writes. See [Mapping the value](/docs/editors#mapping-the-value-as-it-is-typed). |
119
+
120
+ ```tsx
121
+ meta: {
122
+ type: "string",
123
+ edit: {
124
+ enabled: (row) => row.original.status !== "Terminated",
125
+ validate: z.string().min(2, "At least two characters"),
126
+ mapValue: ({ value }) =>
127
+ typeof value === "string" ? value.toUpperCase() : value,
128
+ },
129
+ }
130
+ ```
131
+
132
+ Omit both namespaces to get the defaults: any column mapping to a data path is
133
+ editable once `editing` is set, and every column filters by its type.
134
+
135
+ ## Column types
136
+
137
+ `meta.type` declares what a column's values are. The filter panel offers that
138
+ type's operators and renders a matching value control: a date input for `date`,
139
+ a Yes/No dropdown for `boolean`, a multi-select of the column's options for
140
+ `select` and `multiSelect`. With editing on, the same declaration picks the
141
+ editor.
142
+
143
+ Dates may be `Date` instances or ISO `YYYY-MM-DD` strings in the data; the
144
+ comparison is by calendar day either way, and filter values always travel as ISO
145
+ strings. The date control is the native `<input type="date">`; `@mantine/dates`
146
+ is not used.
147
+
148
+ A column whose value is none of the six types - an object such as a
149
+ `{ from, to }` range - renders through its own `cell`, but sorting, the filter
150
+ panel and quick search operate on the raw value. Set `enableSorting`,
151
+ `enableColumnFilter` and `enableGlobalFilter` to `false` on such a column.
152
+
153
+ ### Options
154
+
155
+ `select` and `multiSelect` columns declare their choices once, in `meta.options`,
156
+ and every consumer of them (the filter panel, the cell editor) reads the same
157
+ source:
158
+
159
+ ```tsx
160
+ // A fixed set, strings or full options:
161
+ meta: {
162
+ type: "select",
163
+ options: [
164
+ "Pending",
165
+ { value: "Paid", label: "Paid in full", color: "green" },
166
+ ],
167
+ }
168
+
169
+ // The distinct values present in the data (low-cardinality columns):
170
+ meta: { type: "select", options: "faceted" }
171
+
172
+ // Computed. `row` is set when a cell editor asks and absent for the filter
173
+ // panel, so row-dependent options can branch on it:
174
+ meta: {
175
+ type: "select",
176
+ options: ({ row }) => (row ? citiesFor(row.original.country) : allCities),
177
+ }
178
+ ```
179
+
180
+ `resolveColumnOptions({ table, column, row? })` normalises all three forms and is
181
+ exported for custom controls; `optionsToComboboxData` turns the result into what
182
+ Mantine's `Select` and `MultiSelect` take, `group` fields included.
183
+
184
+ A select column that declares no options still filters: the panel falls back to
185
+ the faceted values. Mantine's dropdowns are not virtualized, so use the function
186
+ form for very large sets.
187
+
188
+ ## Header groups
189
+
190
+ `columnHelper.group` nests columns under a shared header. The group is a header
191
+ row, not a column - the leaves keep all the behaviour. `columns` takes another
192
+ `columnHelper.columns` call, not a bare array:
193
+
194
+ ```tsx
195
+ columnHelper.group({
196
+ id: "person",
197
+ header: "Person",
198
+ columns: columnHelper.columns([
199
+ columnHelper.accessor("firstName", { header: "First" }),
200
+ columnHelper.accessor("lastName", { header: "Last" }),
201
+ ]),
202
+ });
203
+ ```
204
+
205
+ ```demo
206
+ file: getting-started/HeaderGroups.tsx
207
+ hint: Sort, filter and resize the leaves; the group header follows them.
208
+ ```
209
+
210
+ Columns inside a group cannot be reordered, regardless of `meta.enableOrdering`:
211
+ `columnOrder` sequences leaf columns, so moving one would leave the group header
212
+ spanning columns that no longer belong to it.
213
+
214
+ ## Per-column feature switches
215
+
216
+ Standard TanStack column options. Each removes the corresponding interface for
217
+ that column alone.
218
+
219
+ | Option | Effect when `false` |
220
+ | --- | --- |
221
+ | `enableSorting` | No sort indicator and no sort menu items. See [Sorting](/docs/sorting). |
222
+ | `enableColumnFilter` | No filter menu item, and no entry in the panel's column list. |
223
+ | `enableHiding` | No hide menu item, and no checkbox in the column manager. |
224
+ | `enablePinning` | No pin menu items. |
225
+ | `enableResizing` | The divider stays as a separator but cannot be dragged. |
226
+ | `meta.enableOrdering` | No header dragging and no move menu items. |
227
+
228
+ Sizing, pinning, ordering and visibility are covered on
229
+ [Visibility, pinning, ordering and size](/docs/column-layout).
230
+
231
+ ## The generated columns
232
+
233
+ Five lanes the grid adds when a feature needs them. All are **system lanes**:
234
+ fixed width, no column menu, no resize handle, never exported, never hidden and
235
+ never listed in the columns panel.
236
+
237
+ | Id | Appears when | Where |
238
+ | --- | --- | --- |
239
+ | `ROW_NUMBER_COLUMN_ID` | `enableRowNumbers` | Outermost left, before everything. See [Row pinning and numbering](/docs/row-pinning#numbering-rows). |
240
+ | `SELECT_COLUMN_ID` | A checkbox selection mode | First, pinned left. See [Row selection](/docs/row-selection). |
241
+ | `GROUP_COLUMN_ID` | A column is grouped | Front, beside the checkbox lane. See [Grouping](/docs/grouping). |
242
+ | `DETAILS_COLUMN_ID` | `renderDetails` is set | Left, after checkbox and tree. See [Row details](/docs/row-details). |
243
+ | `EDIT_COLUMN_ID` | `editing.mode: "row"`, `editing.draft`, or `editing.onRowDelete` | Appended, pinned right, and stays outside anything the user pins right. See [Editing](/docs/editing). |
244
+
245
+ The checkbox lane cannot be moved: it anchors the left pinned region, and no
246
+ column can be placed in front of it.
247
+
248
+ ## Reference
249
+
250
+ | Name | Kind | Type | Default | What it does |
251
+ | --- | --- | --- | --- | --- |
252
+ | `createTMDataGridColumnHelper` | Export | `<TData>() => TMDataGridColumnHelper<TData>` | – | A TanStack column helper typed against the grid's features, with `meta` callbacks typed against `TData`. |
253
+ | `TMDataGridColumnHelper` | Type | – | – | The helper's type. |
254
+ | `TMDataGridColumnMeta` | Type | – | – | The type of `meta`. Typed against the row when the column is declared with `createTMDataGridColumnHelper`. |
255
+ | `TMDataGridRowData` | Type | `Record<string, unknown>` | – | The row type where none is given: the default `TData` of the column meta types, and the rows `useTMDataGridContext` returns. |
256
+ | `meta.label` | Column meta | `string` | Header or id | Name in menus and the columns panel. |
257
+ | `meta.type` | Column meta | six types | `"string"` | What the values are; drives filters and editors. |
258
+ | `TMDataGridColumnType` | Type | – | – | The six values of `meta.type`. |
259
+ | `meta.options` | Column meta | array \| `"faceted"` \| `(args) => …` | – | The choices of an option column. |
260
+ | `TMDataGridOptionsArgs` | Type | – | – | What a `meta.options` function receives: `{ table, column, row? }`. `row` is absent when the filter panel asks. |
261
+ | `meta.align` | Column meta | `"left" \| "right" \| "center"` | `"left"` | Header and cell alignment. |
262
+ | `meta.filter` | Column meta | `TMDataGridColumnFilterOptions` | – | How the column filters: `defaultOperator`, `control`. |
263
+ | `meta.edit` | Column meta | `TMDataGridColumnEditOptions` | – | How the column edits: `enabled`, `field`, `editor`, `validate`, `mapValue`. |
264
+ | `resolveColumnOptions` | Export | `({ table, column, row? }) => options` | – | Normalises all three `meta.options` forms. |
265
+ | `optionsToComboboxData` | Export | `(options) => ComboboxData` | – | Options as Mantine `Select` data. |
266
+ | `getColumnLabel` · `getColumnType` · `isControlColumn` | Exports | `(column) => …` | – | How the built-in controls read a column. |
267
+ | `isGeneratedColumn` | Export | `(columnId) => boolean` | – | Whether the grid generated the column - the four control lanes plus the tree column. |
268
+ | `SELECT_COLUMN_ID` · `GROUP_COLUMN_ID` · `DETAILS_COLUMN_ID` · `EDIT_COLUMN_ID` · `ROW_NUMBER_COLUMN_ID` | Exports | `string` | – | Ids of the five generated lanes. |