@opencorestack/opengridx 2.0.4 → 3.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 (221) hide show
  1. package/CHANGELOG.md +408 -3
  2. package/README.md +93 -72
  3. package/dist/index.d.ts +611 -121
  4. package/dist/opengridx.css +1 -1
  5. package/dist/opengridx.es.js +7992 -5650
  6. package/dist/opengridx.es.js.map +1 -1
  7. package/dist/opengridx.umd.js +17 -23
  8. package/dist/opengridx.umd.js.map +1 -1
  9. package/docs/API_REFERENCE.md +348 -161
  10. package/docs/README.md +6 -1
  11. package/docs/architecture/datagrid-orchestration.md +81 -0
  12. package/docs/architecture/grid-row-meta.md +102 -0
  13. package/docs/architecture/use-grid-columns.md +128 -0
  14. package/docs/architecture/use-grid-controlled-state.md +157 -0
  15. package/docs/architecture/use-grid-row-pipeline.md +120 -0
  16. package/docs/architecture/use-grid-scroll-sync.md +111 -0
  17. package/docs/architecture/use-grid-state-snapshot.md +90 -0
  18. package/docs/architecture/use-grid-virtualization.md +115 -0
  19. package/docs/architecture/use-grid-visible-rows.md +85 -0
  20. package/docs/assets/banner-alt.png +0 -0
  21. package/docs/assets/banner.png +0 -0
  22. package/docs/assets/hero.png +0 -0
  23. package/docs/assets/logo.png +0 -0
  24. package/docs/components/aggregation-footer.md +15 -10
  25. package/docs/components/cell.md +16 -6
  26. package/docs/components/column-group-header.md +55 -28
  27. package/docs/components/column-resize.md +17 -13
  28. package/docs/components/column-visibility.md +45 -22
  29. package/docs/components/datagrid.md +14 -12
  30. package/docs/components/empty-state.md +2 -1
  31. package/docs/components/error-overlay.md +12 -7
  32. package/docs/components/filter-panel.md +28 -8
  33. package/docs/components/header.md +28 -9
  34. package/docs/components/pagination.md +14 -8
  35. package/docs/components/row.md +21 -5
  36. package/docs/components/toolbar.md +27 -9
  37. package/docs/components/tooltip.md +16 -7
  38. package/docs/customization/slots-api.md +100 -36
  39. package/docs/customization/theming.md +66 -18
  40. package/docs/features/aggregation-pivot.md +75 -9
  41. package/docs/features/cell-spanning.md +80 -125
  42. package/docs/features/clipboard.md +41 -16
  43. package/docs/features/custom-pagination.md +38 -18
  44. package/docs/features/data-source.md +36 -13
  45. package/docs/features/editing-reordering.md +125 -16
  46. package/docs/features/export-guide.md +147 -41
  47. package/docs/features/filtering.md +44 -6
  48. package/docs/features/infinite-scroll.md +54 -46
  49. package/docs/features/keyboard-navigation.md +83 -0
  50. package/docs/features/list-view.md +58 -5
  51. package/docs/features/loading-states.md +18 -20
  52. package/docs/features/master-detail.md +18 -5
  53. package/docs/features/pdf-export.md +56 -19
  54. package/docs/features/pinning.md +23 -5
  55. package/docs/features/selection.md +50 -10
  56. package/docs/features/sorting-pagination.md +66 -14
  57. package/docs/features/state-persistence.md +78 -10
  58. package/docs/features/toolbar-customization.md +26 -17
  59. package/docs/features/tree-data-grouping.md +44 -9
  60. package/docs/features/virtualization.md +64 -15
  61. package/docs/migration/v1-to-v2.md +115 -0
  62. package/docs/migration/v2-to-v3.md +1222 -0
  63. package/docs/performance.md +124 -0
  64. package/docs/roadmap.md +16 -10
  65. package/lib/components/Cell/Cell.css +13 -1
  66. package/lib/components/Cell/Cell.tsx +130 -57
  67. package/lib/components/Cell/CellErrorBoundary.tsx +12 -6
  68. package/lib/components/Cell/GridEditInputCell.tsx +114 -41
  69. package/lib/components/ColumnGroupHeader/ColumnGroupHeader.css +7 -1
  70. package/lib/components/ColumnResizeHandle/ColumnResizeHandle.css +11 -0
  71. package/lib/components/ColumnResizeHandle/ColumnResizeHandle.tsx +104 -38
  72. package/lib/components/ColumnResizeHandle/clampResizeWidth.ts +13 -0
  73. package/lib/components/ColumnVisibilityPanel/ColumnVisibilityPanel.css +6 -0
  74. package/lib/components/ColumnVisibilityPanel/ColumnVisibilityPanel.tsx +21 -13
  75. package/lib/components/DataGrid/DataGrid.css +84 -12
  76. package/lib/components/DataGrid/DataGrid.tsx +606 -872
  77. package/lib/components/DataGrid/GridAggregationFooter.tsx +53 -17
  78. package/lib/components/DataGrid/GridEmptyState.tsx +7 -1
  79. package/lib/components/DataGrid/GridErrorOverlay.tsx +15 -12
  80. package/lib/components/DataGrid/GridListView.tsx +166 -23
  81. package/lib/components/DataGrid/GridLiveRegion.tsx +31 -0
  82. package/lib/components/DataGrid/GridLoadingOverlay.tsx +27 -0
  83. package/lib/components/DataGrid/GridPaginationArea.tsx +44 -0
  84. package/lib/components/DataGrid/GridPinnedRows.tsx +65 -11
  85. package/lib/components/DataGrid/GridStandaloneColumnPanel.tsx +40 -38
  86. package/lib/components/DataGrid/GridToolbarSlot.tsx +51 -0
  87. package/lib/components/DataGrid/GridVirtualRows.tsx +48 -25
  88. package/lib/components/DetailPanel/DetailPanel.css +0 -6
  89. package/lib/components/DetailPanel/DetailPanel.tsx +34 -5
  90. package/lib/components/DetailPanel/DetailPanelContent.tsx +17 -0
  91. package/lib/components/FilterPanel/FilterPanel.css +13 -2
  92. package/lib/components/FilterPanel/FilterPanel.tsx +272 -99
  93. package/lib/components/Header/ColumnMenu.tsx +91 -39
  94. package/lib/components/Header/Header.css +3 -3
  95. package/lib/components/Header/Header.tsx +179 -160
  96. package/lib/components/ListView/ListView.css +25 -0
  97. package/lib/components/ListView/ListViewRow.tsx +79 -10
  98. package/lib/components/Pagination/Pagination.tsx +15 -7
  99. package/lib/components/Row/Row.tsx +185 -75
  100. package/lib/components/Toolbar/GlobalSearch.css +6 -3
  101. package/lib/components/Toolbar/GlobalSearch.tsx +26 -27
  102. package/lib/components/Toolbar/GridToolbar.css +12 -11
  103. package/lib/components/Toolbar/GridToolbar.tsx +133 -89
  104. package/lib/components/Toolbar/PivotPanel.tsx +89 -49
  105. package/lib/components/Tooltip/Tooltip.css +20 -0
  106. package/lib/components/Tooltip/Tooltip.tsx +68 -35
  107. package/lib/components/ui/Button.tsx +3 -0
  108. package/lib/components/ui/Checkbox.tsx +2 -1
  109. package/lib/components/ui/ExpandIcon.css +0 -9
  110. package/lib/components/ui/ExpandIcon.tsx +4 -1
  111. package/lib/hooks/core/gridApiPlaceholder.ts +34 -0
  112. package/lib/hooks/core/gridToolbarHostContext.ts +14 -0
  113. package/lib/hooks/core/useDataGrid.ts +115 -173
  114. package/lib/hooks/core/useGridAggregationApi.ts +72 -0
  115. package/lib/hooks/core/useGridApiMethods.ts +115 -0
  116. package/lib/hooks/core/useGridApiRef.ts +15 -3
  117. package/lib/hooks/core/useGridApiRefBinding.ts +18 -0
  118. package/lib/hooks/core/useGridAriaRows.ts +38 -0
  119. package/lib/hooks/core/useGridClipboardApi.ts +38 -0
  120. package/lib/hooks/core/useGridColumnLookup.ts +30 -0
  121. package/lib/hooks/core/useGridColumns.tsx +284 -76
  122. package/lib/hooks/core/useGridColumnsPanel.ts +77 -0
  123. package/lib/hooks/core/useGridControlledState.ts +99 -6
  124. package/lib/hooks/core/useGridDetailPanel.ts +51 -0
  125. package/lib/hooks/core/useGridDevWarnings.ts +123 -0
  126. package/lib/hooks/core/useGridFocusHandlers.ts +50 -0
  127. package/lib/hooks/core/useGridGroupingColumn.ts +62 -0
  128. package/lib/hooks/core/useGridHeaderHandlers.ts +92 -0
  129. package/lib/hooks/core/useGridHierarchy.ts +81 -0
  130. package/lib/hooks/core/useGridKeyboardNavigation.ts +452 -250
  131. package/lib/hooks/core/useGridLiveRowSelection.ts +67 -0
  132. package/lib/hooks/core/useGridPageCorrection.ts +55 -0
  133. package/lib/hooks/core/useGridRowIdOf.ts +32 -0
  134. package/lib/hooks/core/useGridRowInteractions.ts +81 -0
  135. package/lib/hooks/core/useGridRowPipeline.ts +69 -39
  136. package/lib/hooks/core/useGridRowSelection.ts +91 -0
  137. package/lib/hooks/core/useGridScrollSync.ts +80 -32
  138. package/lib/hooks/core/useGridScrollToIndexesApi.ts +45 -0
  139. package/lib/hooks/core/useGridStateSnapshot.ts +40 -5
  140. package/lib/hooks/core/useGridThemeDimensions.ts +49 -0
  141. package/lib/hooks/core/useGridToolbarProps.ts +97 -0
  142. package/lib/hooks/core/useGridViewport.ts +38 -0
  143. package/lib/hooks/core/useGridViewportSize.ts +26 -0
  144. package/lib/hooks/core/useGridVisibleRows.ts +20 -7
  145. package/lib/hooks/core/useLayout.ts +215 -195
  146. package/lib/hooks/core/useRowsScrollEndLatch.ts +41 -0
  147. package/lib/hooks/core/useStableColumns.ts +34 -0
  148. package/lib/hooks/features/useAggregation.ts +86 -90
  149. package/lib/hooks/features/useColumnGroupReorderGuard.ts +34 -0
  150. package/lib/hooks/features/useDetailPanelHeights.ts +29 -0
  151. package/lib/hooks/features/useGridClipboard.ts +133 -73
  152. package/lib/hooks/features/useGridDataSource.ts +354 -128
  153. package/lib/hooks/features/useGridEditing.ts +211 -51
  154. package/lib/hooks/features/useGridPivot.ts +92 -0
  155. package/lib/hooks/features/useGridSpanRenderWindow.ts +104 -0
  156. package/lib/hooks/features/useGridSpanning.ts +410 -306
  157. package/lib/hooks/features/usePivot.ts +0 -0
  158. package/lib/hooks/features/useServerTreeChildren.ts +50 -0
  159. package/lib/hooks/useColumnReorder.ts +38 -44
  160. package/lib/hooks/useRowGrouping.ts +335 -214
  161. package/lib/hooks/useRowReorder.ts +62 -31
  162. package/lib/hooks/useTreeData.ts +330 -262
  163. package/lib/index.ts +30 -2
  164. package/lib/state/index.ts +1 -0
  165. package/lib/state/types.ts +7 -1
  166. package/lib/state/useGridStateStorage.ts +88 -29
  167. package/lib/theme/DataGridThemeProvider.tsx +143 -38
  168. package/lib/theme/gridThemeContext.ts +5 -0
  169. package/lib/theme/index.ts +5 -0
  170. package/lib/theme/presets.ts +5 -4
  171. package/lib/theme/types.ts +40 -2
  172. package/lib/types/index.ts +311 -108
  173. package/lib/utils/aggregation/index.ts +157 -0
  174. package/lib/utils/aria/index.ts +40 -0
  175. package/lib/utils/columnGroups.ts +110 -0
  176. package/lib/utils/columnLookup.ts +33 -0
  177. package/lib/utils/columnWidth.ts +22 -0
  178. package/lib/utils/dataSource/index.ts +46 -0
  179. package/lib/utils/detailPanel.ts +66 -0
  180. package/lib/utils/dragData.ts +44 -0
  181. package/lib/utils/editing/index.ts +30 -0
  182. package/lib/utils/export/exportShared.ts +197 -0
  183. package/lib/utils/export/exportToExcelAdvanced.ts +344 -121
  184. package/lib/utils/export/exportToPdf.ts +143 -92
  185. package/lib/utils/export/groupLabel.ts +14 -0
  186. package/lib/utils/export/index.ts +278 -272
  187. package/lib/utils/export/pdfText.ts +50 -0
  188. package/lib/utils/filtering/index.ts +277 -148
  189. package/lib/utils/focus/index.ts +115 -0
  190. package/lib/utils/gridApiRows.ts +35 -0
  191. package/lib/utils/gridModes.ts +77 -0
  192. package/lib/utils/grouping/groupedExportRows.ts +91 -0
  193. package/lib/utils/pagination/index.ts +56 -0
  194. package/lib/utils/pinning/index.ts +77 -33
  195. package/lib/utils/pivot/index.ts +368 -0
  196. package/lib/utils/scroll/index.ts +78 -0
  197. package/lib/utils/scroll/scrollEnd.ts +18 -0
  198. package/lib/utils/sorting/index.ts +154 -30
  199. package/lib/utils/syntheticRows.ts +12 -0
  200. package/lib/utils/values.ts +206 -0
  201. package/lib/utils/viewport.ts +14 -0
  202. package/llms.txt +272 -166
  203. package/package.json +18 -6
  204. package/lib/components/ColumnGroupHeader/ColumnGroupHeader.tsx +0 -220
  205. package/lib/components/ColumnVisibilityPanel/ColumnVisibilityPanel.test.tsx +0 -85
  206. package/lib/components/DataGrid/DataGrid.regression.test.tsx +0 -132
  207. package/lib/components/DataGrid/DataGrid.smoke.test.tsx +0 -58
  208. package/lib/components/DataGrid/DataGrid.v2.test.tsx +0 -127
  209. package/lib/components/Header/Header.test.tsx +0 -135
  210. package/lib/components/Pagination/Pagination.test.tsx +0 -64
  211. package/lib/hooks/core/useDataGrid.regression.test.ts +0 -66
  212. package/lib/hooks/core/useGridControlledState.test.ts +0 -86
  213. package/lib/hooks/core/useGridKeyboardNavigation.test.ts +0 -176
  214. package/lib/hooks/core/useGridRowPipeline.test.ts +0 -117
  215. package/lib/hooks/features/useAggregation.test.ts +0 -175
  216. package/lib/hooks/features/usePivot.test.ts +0 -202
  217. package/lib/hooks/useRowGrouping.test.ts +0 -137
  218. package/lib/utils/export/exportToPdf.test.ts +0 -120
  219. package/lib/utils/export/groupedExport.test.ts +0 -144
  220. package/lib/utils/filtering/filtering.test.ts +0 -178
  221. package/lib/utils/sorting/sorting.test.ts +0 -88
@@ -1,12 +1,14 @@
1
1
  # `<ColumnResizeHandle />` & Resizing
2
2
 
3
- OpenGridX supports dynamic column resizing, allowing users to adjust the width of any column on the fly for better visibility of data. This is facilitated by the `ColumnResizeHandle`, which sits invisibly between adjacent column headers.
3
+ OpenGridX supports dynamic column resizing, allowing users to adjust the width of any column on the fly for better visibility of data. This is facilitated by the `ColumnResizeHandle`, an internal component (not exported) that `<Header />` renders invisibly on the edge of each resizable column header.
4
4
 
5
5
  ## 📑 Overview
6
- - **Inter-Header Interaction**: A handle is placed on the right edge of each resizable column header.
7
- - **Visual Feedback**: On hover and during drag, the grid provides immediate visual cues.
8
- - **Constraints**: Supports `minWidth` and `maxWidth` values defined in your `GridColDef`.
9
- - **Double-Click Action**: Support for auto-sizing columns to fit their longest content is built-in.
6
+ - **Where the handle is**: on the right edge of each resizable column header. Right-pinned columns are anchored to the right edge of the grid and grow leftwards, so their handle is on their **left** edge, and the edge you grab follows the pointer.
7
+ - **Mouse, touch and pen**: the handle uses pointer events with pointer capture, so a resize keeps following the pointer outside the header and works on tablets and phones.
8
+ - **Keyboard**: with a column header focused, **Alt+ArrowRight** / **Alt+ArrowLeft** widen / narrow the column by 10px (hold **Shift** for 50px). The handle is a `role="separator"` that reports the width in `aria-valuenow` (and `aria-valuemin` / `aria-valuemax`).
9
+ - **Constraints**: `minWidth` and `maxWidth` from your `GridColDef` apply. Without `minWidth` a column can be narrowed to 50px; a column that is already narrower (a 30px icon column) is never snapped up to 50px. Without `maxWidth` there is no upper limit.
10
+ - **Clicks are not resizes**: pressing and releasing the handle without moving it changes nothing (a flex column stays flex), and ending a resize with the pointer over the header never sorts the column.
11
+ - **Double-click** does nothing (it is swallowed, so it does not sort). There is no auto-size to content.
10
12
 
11
13
  ---
12
14
 
@@ -36,12 +38,10 @@ const columns: GridColDef[] = [
36
38
 
37
39
  ## ⚙️ How it Works
38
40
 
39
- 1. **Handle Deployment**: At the end of each `Header` component, a `ColumnResizeHandle` is mounted.
40
- 2. **Drag Event Processing**: When the handle is dragged:
41
- - It calculates the change in horizontal position (`deltaX`).
42
- - It applies this change to the column's current width in the grid's state.
43
- 3. **Boundaries Enforcement**: If the new width is less than `minWidth` (default 50px) or more than `maxWidth`, the change is rejected.
44
- 4. **Finalization**: On mouse up, the new column width is persisted to the grid's `columnVisibilityModel` equivalents.
41
+ 1. **Handle Deployment**: every resizable header cell renders a `ColumnResizeHandle`.
42
+ 2. **Pointer processing**: on `pointerdown` the handle captures the pointer and remembers the column's current width. Each `pointermove` (throttled to one update per frame) sets the width to that start width plus the horizontal distance moved (minus it for a right-pinned column).
43
+ 3. **Boundaries Enforcement**: the width is clamped to the column's `minWidth` / `maxWidth` (see above).
44
+ 4. **Finalization**: on `pointerup` the final width is stored in the grid's `columnWidths` state (part of the `onStateChange` snapshot and of `initialState.columns.columnWidths`). A cancelled pointer (the browser took the gesture over) keeps the last width shown.
45
45
 
46
46
  ---
47
47
 
@@ -50,13 +50,17 @@ const columns: GridColDef[] = [
50
50
  The resize handle is not replaceable via the slots API. Style it through CSS:
51
51
 
52
52
  ```css
53
- .ogx__resize-handle {
53
+ .ogx-column-resize-handle__line {
54
54
  width: 4px;
55
55
  background: #6366f1;
56
56
  }
57
+ /* The handle of a right-pinned column, on its left edge */
58
+ .ogx-column-resize-handle--start { }
59
+ /* While a resize is in progress */
60
+ .ogx-column-resize-handle--dragging { }
57
61
  ```
58
62
 
59
63
  ## 📝 Best Practices
60
- - **Define Min Widths**: Always set a reasonable `minWidth` so columns don't accidentally become 0px wide.
64
+ - **Define Min Widths**: set a `minWidth` that fits your column's content.
61
65
  - **Persistence**: Use `onStateChange` to capture the current `columnWidths` from the state snapshot and save the user's preferred layout for their next visit.
62
66
  - **Content Fit**: Remember that large data values might hide behind narrow columns; use tooltips for overflow coverage.
@@ -6,48 +6,71 @@ The `ColumnVisibilityPanel` provides an interactive list for users to toggle the
6
6
  - **Auto-Generating List**: It automatically builds a list of all togglable columns from the grid's state.
7
7
  - **Searchable Interface**: Includes a quick search to find specific columns in grids with many fields.
8
8
  - **Toggle State**: Synchronizes instantly with the grid's `columnVisibilityModel`.
9
- - **Exclusion Logic**: Automatically hides special internal columns (e.g., checkboxes) and columns marked with `hideable: false`.
9
+ - **Exclusion Logic**: Lists only the columns it is given, leaving out those marked `hideable: false` (unless `showNonHideableColumns`). The grid's system columns (checkbox, expand, drag handle) are not columns, and its row-grouping `__group__` column is `hideable: false`, so neither appears.
10
+ - **Accessible names**: Each checkbox is labelled with its column's `headerName` (or `field`), and the footer checkbox with "Show/Hide All"; clicking the name toggles the column.
10
11
 
11
12
  ---
12
13
 
13
14
  ## 🛠️ Usage
14
15
 
15
- ### Toolbar Integration
16
- The most common way to use the visibility panel is within a dropdown menu in the grid's toolbar.
16
+ The grid's toolbar and header menu already include this panel. The column menu's **Manage columns** opens the toolbar's Columns panel when `slots.toolbar` renders a `GridToolbar` that receives the grid's slot props; otherwise (no toolbar, or a custom toolbar without `GridToolbar`) it opens a standalone panel at the grid's top-right corner. Both close on Escape or a click outside. Import it yourself (exported since v2.1) only when you want the list somewhere else, such as a sidebar or modal. It is a controlled component: you own the visibility model and pass it in.
17
17
 
18
18
  ```tsx
19
- import { ColumnVisibilityPanel } from '@opencorestack/opengridx';
20
-
21
- // In your Toolbar component
22
- <Dropdown content={<ColumnVisibilityPanel />}>
23
- <button>Columns</button>
24
- </Dropdown>
19
+ import { useMemo, useState } from 'react';
20
+ import { DataGrid, ColumnVisibilityPanel } from '@opencorestack/opengridx';
21
+ import type { GridColDef } from '@opencorestack/opengridx';
22
+
23
+ function Report({ rows, columns }: { rows: Row[]; columns: GridColDef<Row>[] }) {
24
+ const [visibility, setVisibility] = useState<Record<string, boolean>>({});
25
+ const visibleColumns = useMemo(
26
+ () => new Set(columns.filter(c => visibility[c.field] !== false).map(c => c.field)),
27
+ [columns, visibility],
28
+ );
29
+ const setAll = (visible: boolean) =>
30
+ setVisibility(Object.fromEntries(columns.filter(c => c.hideable !== false).map(c => [c.field, visible])));
31
+
32
+ return (
33
+ <div style={{ display: 'flex' }}>
34
+ <aside className="my-column-sidebar">
35
+ <ColumnVisibilityPanel
36
+ columns={columns}
37
+ visibleColumns={visibleColumns}
38
+ onVisibilityChange={(field, isVisible) => setVisibility(v => ({ ...v, [field]: isVisible }))}
39
+ onShowAll={() => setAll(true)}
40
+ onHideAll={() => setAll(false)}
41
+ />
42
+ </aside>
43
+ <DataGrid rows={rows} columns={columns} columnVisibilityModel={visibility} onColumnVisibilityModelChange={setVisibility} />
44
+ </div>
45
+ );
46
+ }
25
47
  ```
26
48
 
27
- ### Direct Integration
28
- You can also render it persistently beside the grid or within a custom modal.
49
+ ### Props (`ColumnVisibilityPanelProps`)
29
50
 
30
- ```tsx
31
- <div className="my-column-sidebar">
32
- <ColumnVisibilityPanel />
33
- </div>
34
- ```
51
+ | Prop | Type | Description |
52
+ | :--- | :--- | :--- |
53
+ | `columns` | `GridColDef[]` | Columns to list |
54
+ | `visibleColumns` | `Set<string>` | Fields currently visible |
55
+ | `onVisibilityChange` | `(field, isVisible) => void` | Toggle one column |
56
+ | `onShowAll` / `onHideAll` | `() => void` | Bulk actions (only `hideable` columns are affected) |
57
+ | `onColumnReorder` | `(fromField, toField) => void` | Optional — enables drag-to-reorder in the list |
58
+ | `onColumnOrderReset` | `() => void` | Optional — shows a reset-order action |
59
+ | `showNonHideableColumns` | `boolean` | Show `hideable: false` columns as disabled rows. Default `false` |
35
60
 
36
61
  ---
37
62
 
38
63
  ## ⚙️ How it Works
39
64
 
40
- 1. **Column Resolution**: The panel retrieves all columns defined in the `DataGrid`.
41
- 2. **Filtration**: It ignores columns that should not be visible in the list:
42
- - Columns starting with `__` (internal types).
43
- - Columns explicitly marked as `hideable: false` in the `GridColDef`.
44
- 3. **State Management**: When a user toggles a switch, it triggers an update to the grid's `columnVisibilityModel`, causing the grid to re-render only the affected columns.
65
+ 1. **Column Resolution**: The panel lists the `columns` it receives, in that order (the grid passes its current column order).
66
+ 2. **Filtration**: It leaves out columns marked `hideable: false`, unless `showNonHideableColumns` is set (then they are shown as disabled rows). There is no filtering by field name: a field starting with `__` is listed like any other.
67
+ 3. **State Management**: Toggling a checkbox calls `onVisibilityChange(field, isVisible)`; inside the grid that updates `columnVisibilityModel` and fires `onColumnVisibilityModelChange`.
45
68
 
46
69
  ---
47
70
 
48
71
  ## 🎨 Controlling Visibility Programmatically
49
72
 
50
- The column visibility panel is an internal component; it cannot be replaced via the slots API. Use the controlled props to drive visibility from outside:
73
+ The built-in panel cannot be replaced through the slots API. To drive visibility from outside, use the controlled props, optionally together with a standalone `ColumnVisibilityPanel` as shown above:
51
74
 
52
75
  ```tsx
53
76
  <DataGrid
@@ -22,19 +22,20 @@ function MyGrid() {
22
22
 
23
23
  | Prop | Type | Default | Description |
24
24
  | :--- | :--- | :--- | :--- |
25
- | `rows` | `R[]` | `[]` | The dataset to display. |
26
- | `columns` | `GridColDef[]` | `[]` | Column definitions. |
27
- | `getRowId` | `(row: R) => GridRowId` | `row.id` | Unique ID for each row. |
25
+ | `rows` | `R[]` | — | **Required.** The dataset to display (`[]` when a `dataSource` supplies the rows). |
26
+ | `columns` | `GridColDef<R>[]` | — | **Required.** Column definitions. |
27
+ | `getRowId` | `(row: R) => GridRowId` | `row.id` | Unique ID for each row. Only keys the grid's store; row objects are never copied or given an `id` (v3.0+). Duplicate ids keep the first row and log a development warning. |
28
28
  | `height` | `number \| string` | `undefined` | Height of the grid container. |
29
29
  | `loading` | `boolean` | `false` | Displays a loading skeleton/shimmer. |
30
- | `density` | `'compact' \| 'standard' \| 'comfortable'` | `'standard'` | Row height preset: compact = 32 px, standard = `rowHeight`, comfortable = 72 px. |
30
+ | `density` | `'compact' \| 'standard' \| 'comfortable'` | `'standard'` | Row height preset: compact = 32 px, standard = `rowHeight`, comfortable = 72 px. Inside a `DataGridThemeProvider`, the theme's `grid.rowHeightCompact` / `rowHeightStandard` / `rowHeightComfortable` replace these defaults (an explicit `rowHeight` still wins for standard). |
31
31
  | `checkboxSelection` | `boolean` | `false` | Enable row checkboxes. |
32
32
  | `disableRowSelectionOnClick` | `boolean` | `false` | When `true`, clicking a row does not toggle its selection. |
33
33
  | `disableMultipleRowSelection` | `boolean` | `false` | When `true`, at most one row can be selected at a time. |
34
+ | `disableClipboardCopy` | `boolean` | `false` | When `true`, Ctrl+C / Cmd+C does not copy the selected rows. `apiRef.current.copySelectedRows()` still works. |
34
35
  | `pagination` | `boolean` | `false` | Enable/Disable bottom pagination bar. |
35
36
  | `paginationModel` | `GridPaginationModel` | — | Controlled pagination state (`{ page, pageSize }`). Omit for uncontrolled; use `initialState` to set the initial page/pageSize. |
36
37
  | `pageSizeOptions` | `number[]` | `[10, 25, 50, 100]` | Available page size options. |
37
- | `initialState` | `GridInitialState` | `undefined` | Initial configuration (sorting, columns, pagination, etc). |
38
+ | `initialState` | `GridInitialState` | `undefined` | Initial configuration (sorting, filter, columns, pagination, density), read on mount. |
38
39
  | `overscanRowCount` | `number` | `3` | Minimum rows rendered outside the visible viewport. The grid adapts this upward automatically based on scroll velocity — this prop sets the floor. |
39
40
 
40
41
  ## 🔃 Sorting
@@ -50,21 +51,22 @@ function MyGrid() {
50
51
  | Prop | Type | Default | Description |
51
52
  | :--- | :--- | :--- | :--- |
52
53
  | `rowGroupingModel` | `string[]` | `[]` | Fields to group by (in order). |
53
- | `groupingColDef` | `GridColDef` | — | Config for the dedicated `__group__` column created at position 0, auto-pinned left, when grouping is active. |
54
+ | `groupingColDef` | `Partial<GridColDef<R>>` | — | Config for the dedicated `__group__` column created at position 0, auto-pinned left, when row grouping or tree data is active. Every key is optional; `field` is always `'__group__'`. |
54
55
 
55
56
  ## 🖱️ Interaction & Events
56
57
 
57
58
  | Prop | Type | Description |
58
59
  | :--- | :--- | :--- |
59
- | `onRowClick` | `(params) => void` | Fired when clicking a row body. |
60
- | `onCellClick` | `(params) => void` | Fired when clicking a specific cell. |
60
+ | `onRowClick` | `(params: GridRowParams) => void` | Fired when clicking a row body (not for synthetic group rows, which toggle instead). |
61
+ | `onRowDoubleClick` | `(params: GridRowParams) => void` | Fired when double-clicking a row. |
62
+ | `onCellClick` | `(params: GridCellParams) => void` | Fired when clicking a specific cell. |
61
63
  | `onPaginationModelChange` | `(model: GridPaginationModel) => void` | Fired when page or page size changes. |
62
- | `onStateChange` | `(state) => void` | Fired on any internal state update. |
63
- | `processRowUpdate` | `(new, old) => R \| Promise<R>` | Fired after a cell edit is committed. |
64
+ | `onStateChange` | `(state: GridState) => void` | Fired on mount and whenever the value of the sort, filter, pagination, column or density state changes. |
65
+ | `processRowUpdate` | `(new, old) => R \| Promise<R>` | Called once per committed cell edit; return the row to store (or a Promise of it). See [Editing](../features/editing-reordering.md#commit-and-cancel). |
64
66
 
65
67
  ## 📦 Slots
66
68
 
67
- Customize internal components using the `slots` prop.
69
+ Customize internal components using the `slots` prop (`GridSlots`: `toolbar`, `pagination`, `noRowsOverlay`, `loadingOverlay`, `footer`) and pass them props with `slotProps`. See [`GridSlots`](../API_REFERENCE.md#gridslots-and-gridslotprops).
68
70
 
69
71
  ```tsx
70
72
  <DataGrid
@@ -87,7 +89,7 @@ Customize internal components using the `slots` prop.
87
89
  - [Pagination](pagination.md)
88
90
  - [Tooltip](tooltip.md)
89
91
  - [Column Visibility](column-visibility.md)
90
- - [Column Grouping](column-group-header.md)
92
+ - [Column Group Headers](column-group-header.md)
91
93
  - [Column Resizing](column-resize.md)
92
94
  - [Empty State](empty-state.md)
93
95
  - [Error Overlay](error-overlay.md)
@@ -8,10 +8,11 @@ Internal component rendered when the grid has no rows to display. Replaces the r
8
8
  | :--- | :--- | :--- |
9
9
  | `noRowsLabel` | `string` | Text shown beneath the empty-state icon. Controlled by the `noRowsLabel` DataGrid prop. |
10
10
  | `width` | `number` | Pixel width of the empty-state container, matched to the grid's total column width. |
11
+ | `overlay` | `ReactNode` | The rendered `noRowsOverlay` slot, shown instead of the icon and label. |
11
12
 
12
13
  ## 🔄 When it renders
13
14
 
14
- `GridEmptyState` renders when `allRenderableRows.length === 0` and the grid is not in a loading state. The loading skeleton takes precedence — if `loading={true}` the skeleton rows are shown instead.
15
+ `GridEmptyState` renders when no row passes the filter, the grid is not loading and no data-source error is shown. The loading state takes precedence — while `loading` (or a `dataSource` request) is pending the skeleton rows (or the `loadingOverlay` slot) are shown instead, and a `dataSource` error shows the error overlay.
15
16
 
16
17
  ## 🎨 Customizing via slot
17
18
 
@@ -1,30 +1,35 @@
1
1
  # `<GridErrorOverlay />`
2
2
 
3
- Internal component rendered when a `GridDataSource` fetch fails. Displays an error icon, a human-readable message, and a **Retry** button that calls `window.location.reload()`.
3
+ Internal component rendered when a `GridDataSource` fetch fails. Displays an error icon, a human-readable message, and a **Retry** button that runs the failed `getRows` request again (v3.0+; it used to reload the whole page).
4
4
 
5
5
  ## ⚙️ Props
6
6
 
7
7
  | Prop | Type | Description |
8
8
  | :--- | :--- | :--- |
9
- | `error` | `{ message?: string } \| null` | The error object from `state.dataSource.error`. When `null` the component renders nothing (`null` return). |
9
+ | `error` | `unknown` | The value the fetch rejected with (`state.dataSource.error`). When falsy the component renders nothing. |
10
+ | `onRetry` | `() => void` | Re-runs the request. DataGrid passes it whenever a `dataSource` is set; without it the Retry button is not shown. |
10
11
 
11
12
  ## 🔄 When it renders
12
13
 
13
- `GridErrorOverlay` only appears when using a server-side `dataSource` prop. When a fetch throws, DataGrid catches the error and stores it in internal state. The overlay replaces the row viewport until the user retries.
14
+ `GridErrorOverlay` only appears when using a server-side `dataSource` prop. When a fetch throws, DataGrid catches the error and stores it in internal state. The overlay replaces the row viewport until a request succeeds: **Retry**, or any change that refetches (page, sort, filter). A failed children request of a server-side tree node does not show it.
14
15
 
15
16
  ```tsx
16
17
  <DataGrid
17
18
  dataSource={{
18
- getRows: async ({ filterModel, sortModel, paginationModel }) => {
19
- const res = await fetch('/api/employees');
19
+ getRows: async ({ startRow, endRow, sortModel, filterModel }) => {
20
+ const res = await fetch('/api/employees', {
21
+ method: 'POST',
22
+ headers: { 'Content-Type': 'application/json' },
23
+ body: JSON.stringify({ startRow, endRow, sortModel, filterModel }),
24
+ });
20
25
  if (!res.ok) throw new Error(`HTTP ${res.status}`);
21
- return res.json();
26
+ return res.json(); // { rows, rowCount }
22
27
  }
23
28
  }}
24
29
  />
25
30
  ```
26
31
 
27
- If `getRows` throws, the overlay renders with the thrown error's `message`.
32
+ If `getRows` throws, the overlay renders the rejection's `message`: an `Error`, a string, or any object with a string `message` (such as an HTTP-client error). Otherwise it shows a generic message.
28
33
 
29
34
  ## ♿ Accessibility
30
35
 
@@ -24,16 +24,36 @@ renderCell: (params) => {
24
24
 
25
25
  ## 🔌 Integration
26
26
 
27
- The `<DataGrid />` manages the visibility of the Filter Panel via its internal state. It is usually triggered from the Column Menu or the Toolbar.
27
+ Inside the grid, the Filter Panel opens from the toolbar's **Filters** button (`slots={{ toolbar: GridToolbar }}`). `FilterPanel` and `FilterPanelProps` are also exported, to host the editor yourself:
28
+
29
+ | Prop | Type | Description |
30
+ | :--- | :--- | :--- |
31
+ | `filterModel` | `GridFilterModel` | The model to edit. |
32
+ | `columns` | `GridColDef[]` | The columns offered (those with `filterable: false` are left out). |
33
+ | `onFilterModelChange` | `(model: GridFilterModel) => void` | Called with the edited model. |
28
34
 
29
35
  ## 📝 Configuration
30
36
 
31
- Filter operators are automatically determined based on the column's `type`:
32
- - `string`: contains, equals, startsWith, endsWith, isAnyOf.
33
- - `number`: =, !=, >, >=, <, <=.
34
- - `date` / `dateTime`: is, isNot, isAfter, isBefore.
35
- - `boolean`: isTrue, isFalse.
37
+ The panel shows one row per column with `filterable !== false` (the synthetic row-grouping column is not filterable). Operators and the value control depend on the column's `type`:
38
+
39
+ | `type` | Operators (first = default) | Value control |
40
+ | :--- | :--- | :--- |
41
+ | `string` (default) | `contains`, `equals`, `startsWith`, `endsWith`, `isEmpty`, `isNotEmpty` | Text input |
42
+ | `number` | `=`, `!=`, `>`, `>=`, `<`, `<=`, `isEmpty`, `isNotEmpty` | Text input |
43
+ | `date` | `is`, `not`, `after`, `onOrAfter`, `before`, `onOrBefore`, `isEmpty`, `isNotEmpty` | Date input (`YYYY-MM-DD`) |
44
+ | `boolean` | `is` | Select: **Any** (no filter), `true`, `false` |
45
+ | `singleSelect` | `isAnyOf`, `is`, `not` | Built from `valueOptions`: a multi-select for `isAnyOf` (the value is an array of option values), a select with **Any** for `is` / `not`. Option values keep their type, labels are shown. Without `valueOptions`, a text input (comma-separated for `isAnyOf`). |
46
+
47
+ `isEmpty` / `isNotEmpty` hide the value control. An item whose operator the column type does not list (set programmatically) is shown with that operator.
48
+
49
+ ## 🔄 How edits reach the model
50
+
51
+ - Typing is debounced by 300 ms before `onFilterModelChange` fires. Opening the panel never emits anything and never rewrites existing values (arrays, numbers and dates stay as they are).
52
+ - Changing the operator right after typing keeps the typed text.
53
+ - Each row edits the **first** root-level item for its column and replaces it in place. Filter groups (`GridFilterGroup`) and further items for the same column are passed through untouched; the panel notes how many such conditions it does not show.
54
+ - Picking an operator without typing, or clearing the input, leaves an item with an empty value, which does not filter. The row's **×** button removes the item.
55
+ - If the model is changed from outside the panel (the toolbar's **Clear all**, or your own code) while typing is still pending, the pending text is dropped instead of being re-applied.
36
56
 
37
- ## 🎨 Slot Usage
57
+ ## 🎨 Customizing
38
58
 
39
- While the Filter Panel is a complex internal component, its appearance can be influenced by CSS variables or by providing a custom implementation to the `filterPanel` slot in advanced use cases.
59
+ There is no slot for the Filter Panel. Restyle it with CSS (its classes start with `ogx-filter`) and the theme's overlay colours, replace only the toolbar's trigger with `renderFilterButton`, or render your own editor that writes a `GridFilterModel` to the grid's `filterModel` prop.
@@ -4,21 +4,29 @@ Manages the column headers, sorting triggers, column resizing, and column groupi
4
4
 
5
5
  ## ⚙️ Props
6
6
 
7
+ `Header` and its props type `HeaderProps` are exported. The main props:
8
+
7
9
  | Prop | Type | Description |
8
10
  | :--- | :--- | :--- |
9
11
  | `columns` | `GridColDef[]` | Column definitions for the visible viewport. |
12
+ | `allColumns` | `GridColDef[]` | Every rendered data column in render order (left-pinned, unpinned, right-pinned) with its resolved `width`. Column group rows are laid out over these. Defaults to `columns`. |
10
13
  | `columnGroupingModel` | `GridColumnGroupingModel` | Hierarchy for multi-level header spanning. |
11
- | `sortModel` | `GridSortModel` | Current sorting state for highlight and icons. |
14
+ | `sortModel` | `GridSortItem[]` | Current sorting state for highlight, icons and priority badges. |
12
15
  | `onSort` | `(field, direction) => void` | Callback triggered on a plain click — replaces the sort model with a single key. |
13
- | `onSortAdd` | `(field, direction) => void` | Callback triggered on Shift+click or when `multiSort` is active — appends/cycles the key without replacing others. |
16
+ | `onSortAdd` | `(field, direction) => void` | Callback triggered on Shift+click or when `multiSort` is active — appends/cycles the key without replacing others (an existing key keeps its priority). Also used by the column menu for **Unsort** and for a direction change on an already-sorted column. |
14
17
  | `multiSort` | `boolean` | When `true`, every click routes to `onSortAdd` instead of `onSort`. Wired from the `multiSort` prop on `<DataGrid>`. |
15
- | `onColumnResize` | `Function` | Callback for manual column width changes. |
18
+ | `onColumnResize` | `(field: string, newWidth: number) => void` | Callback for manual column width changes. Without it, headers are not resizable. |
19
+ | `onHideColumn` / `onPinColumn` / `onManageColumns` | `(field) => void` / `(field, side \| null) => void` / `() => void` | Column menu actions. |
16
20
  | `pinnedColumns` | `GridColumnPinning` | Coordinates sticky positioning for headers. |
17
- | `checkboxSelection` | `boolean` | Renders the "Select All" checkbox. |
21
+ | `checkboxSelection` | `boolean` | Reserves the checkbox column. The "Select All" checkbox is rendered only when `onSelectAll` is also passed (the grid omits it with `disableMultipleRowSelection`). |
22
+ | `onSelectAll` | `(isSelected: boolean) => void` | Called by the "Select All" checkbox. |
23
+ | `allSelected` / `someSelected` | `boolean` | Checked / indeterminate state of the "Select All" checkbox. |
24
+ | `focusedCell` | `{ id: GridRowId \| null; field: string } \| null` | The grid's focus position. `id: null` means the header cell of `field` is focused (v3.0; it used to be the string `'HEADER'`, which a real row id could collide with). DOM focus is moved by the grid, not by `<Header />`. |
25
+ | `columnIndexMap` | `Map<string, number>` | Position of each visible data column in render order. Used for `aria-colindex` and the `colIndex` passed to `renderHeader`, so they match the body cells and do not change with horizontal scrolling. |
18
26
 
19
27
  ## 📐 Column Grouping
20
28
 
21
- The `<Header />` dynamically calculates the nesting depth of your `columnGroupingModel` and renders additional [Column Group Headers](column-group-header.md) above the main column headers.
29
+ The `<Header />` dynamically calculates the nesting depth of your `columnGroupingModel` and renders one group row per level above the main column headers. Group cells are sized from `allColumns`, so they match their member columns' resolved widths; cells over pinned columns are sticky. See [Column Group Headers](../API_REFERENCE.md#️-column-group-headers) for the full behaviour.
22
30
 
23
31
  ```tsx
24
32
  const columnGroupingModel = [
@@ -35,7 +43,18 @@ const columnGroupingModel = [
35
43
  Unless `disableColumnMenu` is set to `true` in a column's `GridColDef`, each header cell renders a menu icon. In addition, the header facilitates manual [Column Resizing](column-resize.md).
36
44
 
37
45
  Clicking the menu icon opens a popover with actions to:
38
- - Sort Asc/Desc
39
- - Pin Left/Right/None
40
- - Hide Column
41
- - Manage Columns (Open [Visibility Panel](column-visibility.md))
46
+ - Sort Asc/Desc/Unsort (acts on that column only; other sort keys are kept)
47
+ - Pin Left/Right/None (left out for columns with `pinnable: false`)
48
+ - Hide Column (left out for columns with `hideable: false`)
49
+ - Manage Columns (opens the toolbar's Columns panel when `slots.toolbar` renders `GridToolbar`, otherwise the standalone [Visibility Panel](column-visibility.md))
50
+
51
+ **Keyboard** (v3.0): with a header cell focused, **Alt+ArrowDown** or **Ctrl+Enter** / **Cmd+Enter** opens its menu. Focus moves to the first item (also when the menu is opened with the mouse); **ArrowUp** / **ArrowDown** / **Home** / **End** move between items, and **Escape**, **Tab** or choosing an item closes the menu and returns focus to the header cell. See [Keyboard & Accessibility](../features/keyboard-navigation.md).
52
+
53
+ **Alt+ArrowRight** / **Alt+ArrowLeft** on a focused header widen / narrow its column by 10px (**Shift** for 50px), unless the column has `resizable: false`.
54
+
55
+ **Drag-reorder**: unpinned headers are draggable. Pinned headers (and the row-grouping column) are not, and are not drop targets.
56
+
57
+ ## ♿ Accessibility
58
+
59
+ - Header rows carry `aria-rowindex` (column-group rows first). Header cells carry `aria-colindex`, matching the body cells of the same column; the system columns (reorder, detail-panel toggle, select-all) come first and are focusable from the keyboard.
60
+ - Only the primary sort column has `aria-sort="ascending"` / `"descending"`; other sortable headers have `aria-sort="none"`. With multi-sort each sorted header also has an `aria-description` such as "Sorted descending, sort priority 2 of 2".
@@ -1,26 +1,32 @@
1
1
  # `<Pagination />`
2
2
 
3
- Handles row limit selection and page navigation. Compatible with both client-side and server-side data modes.
3
+ Handles row limit selection and page navigation. Compatible with both client-side and server-side data modes. `DataGrid` renders it when `pagination` is set. `Pagination` and `PaginationProps` are exported (v3.0+), so a `pagination` slot can wrap or restyle it; the slot receives the same props.
4
4
 
5
5
  ## ⚙️ Props
6
6
 
7
7
  | Prop | Type | Default | Description |
8
8
  | :--- | :--- | :--- | :--- |
9
- | `page` | `number` | `0` | The current active page (0-indexed). |
10
- | `pageSize` | `number` | `100` | Number of rows per page. |
11
- | `rowCount` | `number` | `0` | Total number of rows (used to calculate page count). |
12
- | `pageSizeOptions` | `number[]` | `[10, 25, 50, 100]` | Options for the "Rows per page" dropdown. |
9
+ | `page` | `number` | — | **Required.** The current active page (0-indexed). |
10
+ | `pageSize` | `number` | — | **Required.** Number of rows per page. |
11
+ | `rowCount` | `number` | — | **Required.** Total number of rows (used to calculate page count). |
12
+ | `onPageChange` | `(page: number) => void` | — | **Required.** Called with the new page. |
13
+ | `onPageSizeChange` | `(pageSize: number) => void` | — | **Required.** Called with the new page size (the grid then goes to page 0). |
14
+ | `pageSizeOptions` | `number[]` | `[10, 25, 50, 100]` | Options for the "Rows per page" dropdown. When `pageSize` is not one of them it is added as an extra option, so the select always shows the size in use. |
15
+ | `showFirstButton` / `showLastButton` | `boolean` | `true` | Show the first-page / last-page buttons. |
16
+ | `localeText` | `Pick<GridLocaleText, 'paginationRowsPerPage' \| 'paginationOf' \| 'paginationPage'>` | — | Label overrides (see below). |
17
+
18
+ A `page` outside `0 … pageCount - 1` is displayed as the nearest valid page (the last page for a page past the end), and Previous/Next move from the displayed page. A `pageSize` below 1 (0, negative, `NaN`) is treated as 1.
13
19
 
14
20
  ## 🕹️ Interaction
15
21
 
16
22
  The pagination component communicates state changes back to the `<DataGrid />` via:
17
- - `onPageChange`: Triggered when clicking Next/Prev or a page number.
23
+ - `onPageChange`: Triggered by the first / previous / next / last buttons.
18
24
  - `onPageSizeChange`: Triggered when changing the rows-per-page limit.
19
25
 
20
26
  ## 🔄 Modes
21
27
 
22
28
  - **Client-side**: Pagination happens automatically on the local `rows` array.
23
- - **Server-side**: Pagination state is passed to the `GridDataSource` to fetch new chunks of data.
29
+ - **Server-side**: With `paginationMode="server"`, page changes are passed to the `GridDataSource` (or to your `onPaginationModelChange`) to fetch the page; `rowCount` is the server total.
24
30
 
25
31
  ## 🎨 Customizing
26
32
  You can replace the internal pagination UI using the `pagination` slot:
@@ -35,7 +41,7 @@ You can replace the internal pagination UI using the `pagination` slot:
35
41
 
36
42
  ## 🌍 Internationalisation
37
43
 
38
- Pass `localeText` on `<DataGrid />` to override the text labels in the Pagination component (rows-per-page, range, and page-counter labels). Note: ARIA labels (`aria-label="Pagination"`, `aria-label="Rows per page"`) and button titles (`title="Previous page"`, `title="Next page"`) are currently hardcoded and not overrideable via `localeText`.
44
+ Pass `localeText` on `<DataGrid />` to override the text labels in the Pagination component (rows-per-page, range, and page-counter labels). The rows-per-page select takes its accessible name from the `paginationRowsPerPage` label. The navigation landmark label (`aria-label="Pagination"`) and the button labels and titles (`Go to next page`, `Next page`, …) are hardcoded and not overrideable via `localeText`.
39
45
 
40
46
  | Key | Type | Default |
41
47
  | :--- | :--- | :--- |
@@ -4,9 +4,12 @@ Manages a horizontal collection of cells. Includes support for selection, expans
4
4
 
5
5
  ## ⚙️ Props
6
6
 
7
+ `Row` and its props type `RowProps` are exported. The main props (see `RowProps` for the rest, such as the drag, edit and spanning callbacks the grid wires):
8
+
7
9
  | Prop | Type | Description |
8
10
  | :--- | :--- | :--- |
9
11
  | `row` | `GridRowModel` | The data object for this row. |
12
+ | `rowId` | `GridRowId` | The row's id (from the grid's `getRowId`). Defaults to `row.id`; the grid always passes it (v3.0+). |
10
13
  | `columns` | `GridColDef[]` | Columns currently visible in the viewport. |
11
14
  | `rowIndex` | `number` | Index used for virtualization and alternating colors. |
12
15
  | `isSelected` | `boolean` | Checkbox / Selection state. |
@@ -15,6 +18,19 @@ Manages a horizontal collection of cells. Includes support for selection, expans
15
18
  | `isDetailPanelExpanded` | `boolean` | Current expansion state. |
16
19
  | `rowReordering` | `boolean` | Enables the drag handle for reordering rows. |
17
20
  | `rowHeight` | `number` | Height in pixels (default: 52). |
21
+ | `rowMeta` | `GridRowMeta` | Hierarchy metadata for the row (tree data / row grouping), passed to cells as `params.rowMeta`. |
22
+ | `onRowClick` / `onRowDoubleClick` | `(params: GridRowParams) => void` | Row click handlers. |
23
+ | `onCellClick` | `(params: GridCellParams) => void` | Cell click handler. |
24
+ | `onSelectionChange` | `(rowId: GridRowId, isSelected: boolean) => void` | Called by the row's checkbox. |
25
+ | `isCellEditable` | `(params: GridCellParams) => boolean` | Per-cell editability predicate, combined with `colDef.editable` and the row's `rowMeta` to decide each cell's `isEditable`. |
26
+ | `columnIndexMap` | `Map<string, number>` | Position of each visible data column in render order. Gives cells their `colIndex` / `aria-colindex` independently of the horizontal render window. |
27
+ | `ariaRowIndex` | `number` | 1-based `aria-rowindex` in the whole grid (header rows and earlier pages included). Defaults to `rowIndex + 2`. |
28
+
29
+ ## ♿ Accessibility
30
+
31
+ - `aria-rowindex` (from `ariaRowIndex`), `aria-selected`; with tree data or row grouping, `aria-level` (depth + 1) and, on rows with children, `aria-expanded`.
32
+ - The reorder handle, detail-panel toggle and checkbox cells have `data-field` (`__reorder_col__`, `__expand_col__`, `__checkbox_col__`), `tabIndex={-1}` and `aria-colindex`, so they are keyboard focus stops like data cells.
33
+ - The detail panel is rendered as a `role="row"` with one `role="gridcell"` spanning every column, referenced by the expand cell's `aria-controls` while open.
18
34
 
19
35
  ## 📐 Row Pinning
20
36
 
@@ -30,18 +46,18 @@ The grid supports "Zebra" striping via CSS:
30
46
 
31
47
  When `getDetailPanelContent` is provided, the `<Row />` renders an expandable container below itself to show supplemental data.
32
48
 
33
- ## ⚠️ v2.0 — Runtime `_*` hierarchy fields removed
49
+ ## ⚠️ v3.0 — Runtime `_*` hierarchy fields removed
34
50
 
35
- The internal hierarchy fields (`_hasChildren`, `_treeDepth`, `_isExpanded`, `_groupingField`, `_groupingValue`, `_descendantCount`, `_isGroupRow`) are no longer injected onto the runtime row object as of v2.0. Use `params.rowMeta` instead:
51
+ Up to v2.x the grid copied tree-data and row-grouping rows and added hierarchy fields to the copies (`_hasChildren`, `_treeDepth`, `_isExpanded`, `_groupingField`, `_groupingValue`, `_descendantCount`, `_isGroupRow`). Since v3.0 nothing is added: `params.row` is your own row object, unchanged. Read the hierarchy from `params.rowMeta` instead:
36
52
 
37
53
  ```tsx
38
- // ❌ v1 shim — no longer works in v2:
54
+ // ❌ v2.x — the field is undefined in v3.0:
39
55
  renderCell: (params) => {
40
56
  const hasChildren = (params.row as Record<string, unknown>)._hasChildren;
41
57
  return hasChildren ? <GroupIcon /> : params.value;
42
58
  }
43
59
 
44
- // ✅ v2:
60
+ // ✅ v1.1+ (the only way since v3.0):
45
61
  renderCell: (params) => {
46
62
  const hasChildren = params.rowMeta?.hasChildren;
47
63
  return hasChildren ? <GroupIcon /> : params.value;
@@ -49,4 +65,4 @@ renderCell: (params) => {
49
65
  ```
50
66
 
51
67
  `params.rowMeta` is `undefined` for flat rows with no active tree-data or row-grouping.
52
- See [`GridRowMeta` architecture doc](../architecture/grid-row-meta.md) for the full data flow.
68
+ See [`GridRowMeta` architecture doc](../architecture/grid-row-meta.md) for the full data flow and the [v2 → v3 migration guide](../migration/v2-to-v3.md).
@@ -20,7 +20,11 @@ import { DataGrid, GridToolbar } from '@opencorestack/opengridx';
20
20
  />
21
21
  ```
22
22
 
23
- `GridToolbar` automatically hides buttons for features whose callbacks are not wired. For example, if you don't pass `onFilterModelChange` the search bar and filter button are not rendered.
23
+ `GridToolbar` hides the buttons whose callbacks it does not receive: no `onFilterModelChange`, no search bar and Filters button; no `onColumnVisibilityModelChange`, no Columns button; no `onAggregationModelChange`, no Summaries button; no `onPivotModelChange`, no Pivot button. Mounted through `slots.toolbar`, the grid always passes the filter, column-visibility and aggregation callbacks, and the pivot ones when `pivotMode`, `pivotModel` or `onPivotModelChange` is set, so those buttons show without further props. A standalone `<GridToolbar />` shows only what you wire.
24
+
25
+ One panel is open at a time. Every panel closes on Escape; the Columns, Summaries and Pivot panels also close on a click outside them. Each trigger button has `aria-haspopup="dialog"` and an `aria-expanded` state.
26
+
27
+ The Summaries panel lists each aggregable column with the functions it allows: its `availableAggregationFunctions` when set, otherwise every built-in function (`sum`, `avg`, `count`, `min`, `max`, `unique`). Names that are not built-in functions are not offered.
24
28
 
25
29
  ---
26
30
 
@@ -29,19 +33,20 @@ import { DataGrid, GridToolbar } from '@opencorestack/opengridx';
29
33
  | Prop | Type | Default | Description |
30
34
  |------|------|---------|-------------|
31
35
  | `columns` | `GridColDef[]` | `[]` | Column definitions (injected automatically when used via `slots`). |
32
- | `baseColumns` | `GridColDef[]` | — | Pre-pivot column definitions, used by the Pivot panel to avoid showing synthetic columns. |
36
+ | `baseColumns` | `GridColDef[]` | — | Pre-pivot column definitions. The Pivot panel lists these instead of the generated pivot columns, and the Summaries panel only offers columns that are among them (a summary on a generated pivot column would do nothing). |
33
37
  | `aggregationModel` | `GridAggregationModel` | `{}` | Current aggregation configuration. |
34
- | `onAggregationModelChange` | `(model) => void` | — | Called when the user changes aggregation settings. |
38
+ | `onAggregationModelChange` | `(model) => void` | — | Called when the user changes aggregation settings. Presence of this prop shows the Summaries button. |
35
39
  | `pivotModel` | `GridPivotModel` | — | Current pivot configuration. |
36
40
  | `onPivotModelChange` | `(model) => void` | — | Called when the user changes pivot settings. Presence of this prop shows the Pivot button. |
37
- | `filterModel` | `GridFilterModel` | — | Current filter model. Presence of this prop shows the search bar and Filter button. |
38
- | `onFilterModelChange` | `(model) => void` | — | Called when the user changes filters or the search query. |
41
+ | `filterModel` | `GridFilterModel` | — | Current filter model. |
42
+ | `onFilterModelChange` | `(model) => void` | — | Called when the user changes filters or the search query. Presence of this prop shows the search bar and Filters button. |
39
43
  | `columnVisibilityModel` | `Record<string, boolean>` | `{}` | Current column visibility state. |
40
44
  | `onColumnVisibilityModelChange` | `(model) => void` | — | Called when the user shows/hides columns. Presence shows the Columns button. |
41
45
  | `onColumnReorder` | `(from, to) => void` | — | Called when the user drags a column in the Columns panel. |
42
46
  | `onColumnOrderReset` | `() => void` | — | Called when the user clicks "Reset order" in the Columns panel. |
43
- | `forceColumnsOpen` | `boolean` | — | When `true`, opens the Columns panel immediately (used internally by the column header menu). |
44
- | `onColumnsPanelClose` | `() => void` | — | Called when the Columns panel closes after a `forceColumnsOpen`. |
47
+ | `forceColumnsOpen` | `boolean` | — | When it becomes `true`, opens the Columns panel. `DataGrid` sets it for the column menu's **Manage columns**. A `GridToolbar` that receives it from the grid (spread the slot props into it) shows the panel; when no such toolbar is rendered, the grid opens its standalone Columns panel instead. |
48
+ | `onColumnsPanelClose` | `() => void` | — | Called whenever the Columns panel closes: its button, a custom `renderColumnsButton`, another panel opening, click-outside or Escape. |
49
+ | `showNonHideableColumns` | `boolean` | `false` | Show `hideable: false` columns in the Columns panel as disabled rows. |
45
50
  | `children` | `ReactNode` | — | Content rendered in the **left** side of the toolbar (before the spacer). |
46
51
  | `rightContent` | `ReactNode` | — | Content rendered in the **right** side of the toolbar (after all built-in buttons). |
47
52
  | `className` | `string` | — | Additional CSS class applied to the toolbar root `<div>`. Use for visual overrides without replacing the component. |
@@ -74,11 +79,13 @@ Passed to `renderQuickFilter`.
74
79
 
75
80
  ```ts
76
81
  interface ToolbarQuickFilterRenderProps {
77
- value: string; // Current search string
82
+ value: string; // Current search string (quickFilterValues joined with spaces)
78
83
  onChange: (value: string) => void; // Call with new string on input change
79
84
  }
80
85
  ```
81
86
 
87
+ The toolbar splits the string passed to `onChange` on whitespace, so each word becomes one `quickFilterValues` term and a row matches when every term is found in some visible column (`john london` matches first name John, city London). See [Quick Filter](../features/filtering.md#quick-filter).
88
+
82
89
  ---
83
90
 
84
91
  ## Customization patterns
@@ -218,4 +225,15 @@ function MyToolbar() {
218
225
  <DataGrid slots={{ toolbar: MyToolbar }} />
219
226
  ```
220
227
 
221
- The custom component receives all `GridToolbarProps` via `slotProps.toolbar`.
228
+ The custom component receives the toolbar props the grid owns (`columns`, `baseColumns`, the filter / visibility / aggregation / pivot models and their change handlers, `onColumnReorder`, `onColumnOrderReset`, `forceColumnsOpen`, `onColumnsPanelClose`) plus `apiRef`, with `slotProps.toolbar` spread over them. Spread them into a `GridToolbar` to keep the built-in buttons:
229
+
230
+ ```tsx
231
+ import { GridToolbar } from '@opencorestack/opengridx';
232
+ import type { GridToolbarProps } from '@opencorestack/opengridx';
233
+
234
+ function MyToolbar(props: GridToolbarProps) {
235
+ return <GridToolbar {...props} rightContent={<span>Custom</span>} />;
236
+ }
237
+ ```
238
+
239
+ `slotProps.toolbar` is typed as `GridToolbarProps` plus any extra keys (v3.0+), so the render props above get their parameter types inferred and a misspelt built-in key with a wrong value type is a type error.