@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
package/README.md CHANGED
@@ -6,6 +6,8 @@
6
6
 
7
7
  👉 **[Live Demo & Docs](https://opencorestack.github.io/OpenGridX/)** — Interactive showcase with full API documentation
8
8
 
9
+ > **Upgrading from 2.x?** 3.0.0 changes formatted text, exported files, callback indices and request ranges. See the **[v2 → v3 migration guide](https://github.com/OpenCoreStack/OpenGridX/blob/main/docs/migration/v2-to-v3.md)** first: it starts with a table that maps what your app uses to the sections you need.
10
+
9
11
  ---
10
12
 
11
13
  ## 🛠️ Getting Started
@@ -18,14 +20,10 @@ npm install @opencorestack/opengridx
18
20
 
19
21
  ```tsx
20
22
  import { DataGrid } from '@opencorestack/opengridx';
23
+ import '@opencorestack/opengridx/styles';
21
24
  ```
22
25
 
23
- > **Styles:** The CSS is bundled as a separate file (`opengridx.css`) alongside the JS. It is imported automatically via the package barrel in most setups.
24
- > However, **if your grid appears unstyled** (Vite, Next.js App Router, or SSR environments sometimes skip side-effect CSS auto-detection), add this explicit import once — typically in your app's root file (`main.tsx` / `layout.tsx`):
25
- >
26
- > ```tsx
27
- > import '@opencorestack/opengridx/styles';
28
- > ```
26
+ > **Import the styles.** The CSS ships as a separate file (`dist/opengridx.css`) and the JavaScript bundle does **not** load it. Import `@opencorestack/opengridx/styles` once, typically in your app's root file (`main.tsx`, `App.tsx` or Next.js `layout.tsx`). Without it the grid is unstyled and, because the viewport's scrolling comes from the stylesheet, it grows to fit every row and virtualization stops working. Development builds log a one-time `[OpenGridX] The grid stylesheet is not loaded` warning when this happens.
29
27
 
30
28
  ---
31
29
 
@@ -33,7 +31,8 @@ import { DataGrid } from '@opencorestack/opengridx';
33
31
  ## ⚡ Basic Example
34
32
 
35
33
  ```tsx
36
- import { DataGrid, GridColDef } from '@opencorestack/opengridx';
34
+ import { DataGrid, type GridColDef } from '@opencorestack/opengridx';
35
+ import '@opencorestack/opengridx/styles';
37
36
 
38
37
  const columns: GridColDef[] = [
39
38
  { field: 'id', headerName: 'ID', width: 70 },
@@ -63,23 +62,25 @@ export default function App() {
63
62
  }
64
63
  ```
65
64
 
65
+ Give the grid a bounded height (`height`, or a parent with a definite height; a flex child needs `min-height: 0`). In an unbounded container every row is rendered.
66
+
66
67
  ---
67
68
 
68
69
  ## 🚀 Key Features
69
70
 
70
- - **High-Performance Virtualization**: Custom-built engine handling 100,000+ rows at 60fps.
71
+ - **High-Performance Virtualization**: Row and column virtualization for 100,000+ rows. (Browsers cap an element's height, so a single scrolling grid reaches about 645,000 rows at the default 52 px row height; page or stream larger datasets.)
71
72
  - **Advanced Layouts**: Native support for **Row & Column Spanning**, Grouping, and Tree Data.
72
- - **Data Orchestration**: 11+ filter operators, multi-column sorting, and robust pagination.
73
+ - **Data Orchestration**: 19 filter operators across string, number, date, boolean and select columns, AND/OR filter groups, multi-column sorting, and client or server pagination.
73
74
  - **Zero UI Dependencies**: 100% vanilla CSS (BEM) and pure React/TypeScript logic.
74
- - **Skeleton Loader**: Built-in animated loading states with smart column detection.
75
+ - **Skeleton Loader**: Built-in animated skeleton rows that follow the current columns.
75
76
  - **Fully Customizable**: Slots system for replacing any component (pagination, overlays, toolbar).
76
- - **Export Functionality**: Built-in CSV, Excel, JSON, and Print export.
77
- - **Clipboard**: `Ctrl+C` / `Cmd+C` copies selected rows as TSV for Excel/Sheets.
77
+ - **Export Functionality**: Built-in CSV, Excel (HTML `.xls`, or real `.xlsx` with the optional ExcelJS peer), JSON, PDF (optional jsPDF peer) and Print export.
78
+ - **Clipboard**: `Ctrl+C` / `Cmd+C` copies the selected rows' visible columns as TSV for Excel/Sheets.
78
79
  - **Accessibility**: WCAG 2.1 AA — full ARIA roles and keyboard navigation.
79
- - **Theming**: CSS variable API with 5 built-in themes + custom theme support.
80
+ - **Theming**: CSS variable API, `DataGridThemeProvider` with 5 built-in themes (`darkTheme`, `roseTheme`, `emeraldTheme`, `amberTheme`, `compactTheme`) and custom themes.
80
81
  - **Column & Row Reordering**: Drag-and-drop column reordering and row reordering.
81
82
  - **Inline Cell Editing**: Full inline editing with `processRowUpdate` validation.
82
- - **State Persistence**: Save and restore grid state (sort, filter, columns) via `useGridStateStorage`.
83
+ - **State Persistence**: Save and restore grid state (sort, filter, pagination, columns, density) via `useGridStateStorage`.
83
84
  - **AI-Native Integration**: Shipped with raw `lib/` source and `docs/` inside the npm package, allowing AI agents (Cursor, Copilot, Windsurf) to flawlessly implement features by "seeing" the internal logic.
84
85
 
85
86
  ---
@@ -100,21 +101,27 @@ This means that **Cursor**, **GitHub Copilot**, **Windsurf**, and other AI agent
100
101
 
101
102
  | Prop | Type | Default | Description |
102
103
  | :--- | :--- | :--- | :--- |
103
- | `rows` | `GridRowModel[]` | — | **Required.** Array of data rows. |
104
+ | `rows` | `GridRowModel[]` | — | **Required.** Array of data rows. The grid never modifies or copies them. |
104
105
  | `columns` | `GridColDef[]` | — | **Required.** Column definitions. |
105
- | `height` | `number \| string` | `500` | Grid height in pixels or CSS string (e.g. `'100%'`). |
106
- | `autoHeight` | `boolean` | `false` | Expands grid height to fit all rows. |
107
- | `loading` | `boolean` | `false` | Shows skeleton loader when `true`. |
108
- | `density` | `'compact' \| 'standard' \| 'comfortable'` | `'standard'` | Visual row density. |
106
+ | `height` | `number \| string` | — | Grid height in pixels or a CSS string (e.g. `'100%'`). No default: without it the grid takes its container's height, and needs a bounded container to virtualize. |
107
+ | `autoHeight` | `boolean` | `false` | Grows the grid to fit all rows (renders every row). |
108
+ | `loading` | `boolean` | `false` | With no rows, shows skeleton rows (or `slots.loadingOverlay`). With rows shown, keeps them and runs a progress bar along the top (or shows `slots.loadingOverlay` over them). Works in list view too. |
109
+ | `density` | `'compact' \| 'standard' \| 'comfortable'` | `'standard'` | Row height preset: 32 px, `rowHeight`, 72 px. |
110
+ | `overscanRowCount` | `number` | `3` | Minimum rows rendered outside the viewport; raised automatically while scrolling fast. |
109
111
  | `checkboxSelection` | `boolean` | `false` | Enables checkbox column for row selection. |
110
- | `pagination` | `boolean` | `false` | Enables client-side pagination. |
111
- | `paginationModel` | `{ page: number; pageSize: number }` | — | Controlled pagination state. |
112
+ | `pagination` | `boolean` | `false` | Enables the pager. Ignored under row grouping and with `paginationMode="infinite"`. |
113
+ | `paginationModel` | `{ page: number; pageSize: number }` | — | Controlled pagination state (pair with `onPaginationModelChange`). |
112
114
  | `onPaginationModelChange` | `(model) => void` | — | Fires on page or page size change. |
113
- | `pageSizeOptions` | `number[]` | `[10, 25, 50]` | Available page size options. |
115
+ | `pageSizeOptions` | `number[]` | `[10, 25, 50, 100]` | Available page size options. |
114
116
  | `getRowId` | `(row) => GridRowId` | `row.id` | Custom row ID accessor. |
115
117
  | `rowHeight` | `number` | `52` | Row height in pixels. |
116
118
  | `headerHeight` | `number` | `56` | Header height in pixels. |
117
- | `noRowsLabel` | `string` | — | Custom empty-state message. |
119
+ | `noRowsLabel` | `string` | `'No Data'` | Custom empty-state message. |
120
+ | `localeText` | `GridLocaleText` | — | Overrides for the pager and empty-state strings (i18n). |
121
+ | `ariaLabel` | `string` | — | Accessible name for the grid. |
122
+ | `initialState` | `GridInitialState` | — | Starting sort, filter, pagination, column and density state (uncontrolled). |
123
+ | `onStateChange` | `(state: GridState) => void` | — | Fires when sort, filter, pagination, columns or density change. |
124
+ | `apiRef` | `MutableRefObject<GridApi>` | — | Imperative API; create it with `useGridApiRef()`. |
118
125
  | `className` | `string` | — | Custom CSS class on the grid container. |
119
126
  | `style` | `React.CSSProperties` | — | Custom inline styles on the grid container. |
120
127
 
@@ -125,22 +132,24 @@ This means that **Cursor**, **GitHub Copilot**, **Windsurf**, and other AI agent
125
132
  | `field` | `string` | — | **Required.** Must match the row object key. |
126
133
  | `headerName` | `string` | — | Header label text. |
127
134
  | `description` | `string` | — | Tooltip on header hover. |
128
- | `width` | `number \| string` | `100` | Fixed width in px. |
129
- | `flex` | `number` | — | Flex-grow weight — fills remaining space. Cannot be combined with `width`. |
130
- | `minWidth` | `number` | — | Minimum width in px, enforced during resize. |
131
- | `maxWidth` | `number` | — | Maximum width in px, enforced during resize. |
135
+ | `width` | `number \| string` | — | Width in px, or a percentage string such as `'20%'`. A column with neither `width` nor `flex` behaves like `flex: 1`. |
136
+ | `flex` | `number` | — | Flex-grow weight — shares the space left after fixed and percentage columns. When set, `width` is ignored. |
137
+ | `minWidth` | `number` | — | Minimum width in px (layout and resizing; resizing defaults to 50). |
138
+ | `maxWidth` | `number` | — | Maximum width in px (layout and resizing). |
132
139
  | `align` | `'left' \| 'center' \| 'right'` | `'left'` | Cell content alignment. |
133
140
  | `headerAlign` | `'left' \| 'center' \| 'right'` | `'left'` | Header content alignment. |
134
- | `type` | `'string' \| 'number' \| 'date' \| 'boolean' \| 'singleSelect' \| 'image'` | `'string'` | Drives filter operators and default formatting. |
141
+ | `type` | `'string' \| 'number' \| 'date' \| 'boolean' \| 'singleSelect' \| 'image'` | `'string'` | Drives filter operators and, without a `valueFormatter`, the cell text: local date, Yes / No, `singleSelect` label, `<img>` for `image`. |
135
142
  | `valueOptions` | `Array<string \| number \| { value, label }>` | — | Options list for `type: 'singleSelect'`. |
136
143
  | `editable` | `boolean` | `false` | Enables inline cell editing. Pair with `processRowUpdate`. |
137
- | `valueGetter` | `(params) => unknown` | — | Derive a computed cell value from the row. |
138
- | `valueFormatter` | `(params) => string` | — | Format the display string (does not affect edit or sort). |
144
+ | `valueGetter` | `(params) => unknown` | — | Derive a computed cell value from the row. Sorting, filtering, quick search, aggregation, copy and export use it. |
145
+ | `valueSetter` | `(params) => row` | — | Maps an edited value back onto the row, for editable `valueGetter` columns. |
146
+ | `valueFormatter` | `(params) => string` | — | Format the display string (does not affect edit or sort; quick search also matches it). |
139
147
  | `renderCell` | `(params) => ReactNode` | — | Fully custom cell renderer. |
140
148
  | `renderHeader` | `(params) => ReactNode` | — | Custom header cell renderer. |
141
149
  | `renderEditCell` | `(params) => ReactNode` | — | Custom editor rendered in edit mode. |
142
150
  | `cellClassName` | `string \| ((params) => string)` | — | CSS class on every cell; use a function for conditional per-row styling. |
143
151
  | `headerClassName` | `string` | — | CSS class on the header cell. |
152
+ | `groupingValueFormatter` | `({ field, value }) => string` | — | Label for group rows when grouping by this column (default `"field: value"`). |
144
153
  | `colSpan` | `number \| ((params) => number)` | — | Merge cells horizontally. |
145
154
  | `rowSpan` | `number \| ((params) => number)` | — | Merge cells vertically. |
146
155
  | `sortable` | `boolean` | `true` | Enable/disable column sorting. |
@@ -150,8 +159,8 @@ This means that **Cursor**, **GitHub Copilot**, **Windsurf**, and other AI agent
150
159
  | `pinnable` | `boolean` | `true` | Allow pinning via the UI. |
151
160
  | `disableColumnMenu` | `boolean` | `false` | Hide the column header context menu. |
152
161
  | `exportable` | `boolean` | `true` | Set to `false` to exclude from all exports. |
153
- | `groupable` | `boolean` | `true` | Allow as a row grouping dimension. |
154
- | `aggregable` | `boolean` | `true` | Allow aggregation on this column. |
162
+ | `groupable` | `boolean` | `true` | Set to `false` to skip this column in `rowGroupingModel` and the pivot panel. |
163
+ | `aggregable` | `boolean` | — | `false` keeps the column out of aggregation. The Summaries panel offers `number` columns, plus any column with `aggregable: true`. |
155
164
  | `availableAggregationFunctions` | `string[]` | all | Restrict which aggregation functions are offered. |
156
165
 
157
166
  ### Selection
@@ -162,7 +171,8 @@ This means that **Cursor**, **GitHub Copilot**, **Windsurf**, and other AI agent
162
171
  | `onRowSelectionModelChange` | `(model: GridRowId[]) => void` | Fires on selection change. |
163
172
  | `disableRowSelectionOnClick` | `boolean` | Prevent row click from toggling selection. |
164
173
  | `disableMultipleRowSelection` | `boolean` | Restrict to single-row selection. |
165
- | `pinCheckboxColumn` | `boolean` | Keeps the checkbox column visible during horizontal scroll. |
174
+ | `pinCheckboxColumn` | `boolean` | Keeps the checkbox column visible during horizontal scroll. Default `true`. |
175
+ | `disableClipboardCopy` | `boolean` | Turns off the grid's Ctrl/Cmd+C copy (`apiRef.current.copySelectedRows()` still works). |
166
176
 
167
177
  ### Sorting & Filtering
168
178
 
@@ -172,7 +182,7 @@ This means that **Cursor**, **GitHub Copilot**, **Windsurf**, and other AI agent
172
182
  | `onSortModelChange` | `(model: GridSortItem[]) => void` | Fires on sort change. |
173
183
  | `filterModel` | `GridFilterModel` | Controlled filter model. |
174
184
  | `onFilterModelChange` | `(model: GridFilterModel) => void` | Fires on filter change. |
175
- | `disableColumnFilter` | `boolean` | Disables column-level filtering. |
185
+ | `multiSort` | `boolean` | Every header click adds to the sort instead of replacing it (Shift+click always does). |
176
186
 
177
187
  ### Columns
178
188
 
@@ -181,16 +191,18 @@ This means that **Cursor**, **GitHub Copilot**, **Windsurf**, and other AI agent
181
191
  | `columnVisibilityModel` | `GridColumnVisibilityModel` | Controlled column visibility. |
182
192
  | `onColumnVisibilityModelChange` | `(model) => void` | Fires when column visibility changes. |
183
193
  | `columnOrder` | `string[]` | Controlled column field order. |
184
- | `onColumnOrderChange` | `(params) => void` | Fires when columns are reordered. |
194
+ | `onColumnOrderChange` | `(params) => void` | Fires when the user moves a column. |
195
+ | `onColumnOrderModelChange` | `(columnOrder) => void` | Fires with the whole new column order (also for the Columns panel's Reset). |
185
196
  | `disableColumnReorder` | `boolean` | Disables drag-and-drop column reordering. |
186
197
 
187
198
  ### Events
188
199
 
189
200
  | Prop | Type | Description |
190
201
  | :--- | :--- | :--- |
191
- | `onRowClick` | `(params: GridRowParams) => void` | Fires when a row is clicked. |
202
+ | `onRowClick` | `(params: GridRowParams) => void` | Fires when a row is clicked (or Enter is pressed on a non-editable cell). |
203
+ | `onRowDoubleClick` | `(params: GridRowParams) => void` | Fires when a row is double-clicked. |
192
204
  | `onCellClick` | `(params: GridCellParams) => void` | Fires when a cell is clicked. |
193
- | `onRowsScrollEnd` | `(params: GridRowScrollEndParams) => void` | Fires when scrolling reaches the bottom. |
205
+ | `onRowsScrollEnd` | `(params: GridRowScrollEndParams) => void` | Fires once each time scrolling reaches the bottom. |
194
206
 
195
207
  ### Server-Side
196
208
 
@@ -200,7 +212,7 @@ This means that **Cursor**, **GitHub Copilot**, **Windsurf**, and other AI agent
200
212
  | `sortingMode` | `'client' \| 'server'` | Where sorting is applied. |
201
213
  | `filterMode` | `'client' \| 'server'` | Where filtering is applied. |
202
214
  | `dataSource` | `GridDataSource` | Server-side data adapter. |
203
- | `rowCount` | `number` | Total rows for server-side pagination. |
215
+ | `rowCount` | `number` | Total rows for `paginationMode="server"` without a `dataSource` (with one, the response's `rowCount` wins). |
204
216
 
205
217
  ### Pinning
206
218
 
@@ -208,8 +220,7 @@ This means that **Cursor**, **GitHub Copilot**, **Windsurf**, and other AI agent
208
220
  | :--- | :--- | :--- |
209
221
  | `pinnedColumns` | `GridColumnPinning` | Pin columns to `left` or `right`. |
210
222
  | `onPinnedColumnsChange` | `(model) => void` | Fires when column pinning changes. |
211
- | `pinnedRows` | `GridRowPinning` | Pin rows to `top` or `bottom`. |
212
- | `onPinnedRowsChange` | `(model) => void` | Fires when row pinning changes. |
223
+ | `pinnedRows` | `GridRowPinning` | Pin rows (by id) to `top` or `bottom`. Ignored under tree data and row grouping. |
213
224
 
214
225
  ### Inline Editing
215
226
 
@@ -217,14 +228,14 @@ This means that **Cursor**, **GitHub Copilot**, **Windsurf**, and other AI agent
217
228
  | :--- | :--- | :--- |
218
229
  | `isCellEditable` | `(params: GridCellParams) => boolean` | Per-cell editability predicate. |
219
230
  | `processRowUpdate` | `(newRow, oldRow) => R \| Promise<R>` | Handles row save; supports async validation. |
220
- | `onProcessRowUpdateError` | `(error: unknown) => void` | Fires if `processRowUpdate` throws. |
231
+ | `onProcessRowUpdateError` | `(error: unknown) => void` | Fires if `processRowUpdate` throws, rejects or returns no row. |
221
232
 
222
233
  ### Row Reordering
223
234
 
224
235
  | Prop | Type | Description |
225
236
  | :--- | :--- | :--- |
226
237
  | `rowReordering` | `boolean` | Enables drag-and-drop row reordering. |
227
- | `onRowOrderChange` | `(params) => void` | Fires when rows are reordered. |
238
+ | `onRowOrderChange` | `(params) => void` | Fires when a row is dropped; `oldIndex` / `targetIndex` are positions in the `rows` prop. |
228
239
 
229
240
  ### Advanced Features
230
241
 
@@ -232,12 +243,12 @@ This means that **Cursor**, **GitHub Copilot**, **Windsurf**, and other AI agent
232
243
  | :--- | :--- | :--- |
233
244
  | `treeData` | `boolean` | Enables hierarchical tree data display. |
234
245
  | `getTreeDataPath` | `(row) => string[]` | Returns the path array for each row in tree mode. |
235
- | `groupingColDef` | `GridColDef` | Overrides the auto-generated grouping column. |
236
- | `defaultGroupingExpansionDepth` | `number` | Initial expansion depth for tree data. |
237
- | `rowGroupingModel` | `GridRowGroupingModel` | Controlled row grouping state. |
238
- | `onRowGroupingModelChange` | `(model) => void` | Fires when grouping changes. |
246
+ | `groupingColDef` | `Partial<GridColDef>` | With `rowGroupingModel` or `treeData`, adds a dedicated `__group__` column, pinned left (`field` not needed). |
247
+ | `defaultGroupingExpansionDepth` | `number` | Initial expansion depth for tree data and row grouping. Default `0` (collapsed); `-1` expands everything. |
248
+ | `rowGroupingModel` | `GridRowGroupingModel` | Fields to group rows by (e.g. `['department']`). |
239
249
  | `aggregationModel` | `GridAggregationModel` | Controlled aggregation state (e.g. `{ salary: 'sum' }`). |
240
250
  | `onAggregationModelChange` | `(model) => void` | Fires when aggregation changes. |
251
+ | `getAggregationPosition` | `(groupNode) => 'inline' \| 'footer' \| null` | Where group and grand totals appear. |
241
252
  | `pivotMode` | `boolean` | Switches the grid to multidimensional pivot mode. |
242
253
  | `pivotModel` | `GridPivotModel` | Controlled pivot configuration (rows, columns, values). |
243
254
  | `onPivotModelChange` | `(model) => void` | Fires when pivot model changes. |
@@ -247,7 +258,7 @@ This means that **Cursor**, **GitHub Copilot**, **Windsurf**, and other AI agent
247
258
  | Prop | Type | Description |
248
259
  | :--- | :--- | :--- |
249
260
  | `getDetailPanelContent` | `(params) => ReactNode` | Renders the expandable detail panel. |
250
- | `getDetailPanelHeight` | `(params) => number \| 'auto'` | Controls detail panel height. |
261
+ | `getDetailPanelHeight` | `(params) => number \| 'auto'` | Detail panel height in px, or `'auto'` to measure the content. Default 200. |
251
262
  | `detailPanelExpandedRowIds` | `Set<GridRowId>` | Controlled expanded rows. |
252
263
  | `onDetailPanelExpandedRowIdsChange` | `(ids) => void` | Fires when expanded rows change. |
253
264
 
@@ -256,10 +267,11 @@ This means that **Cursor**, **GitHub Copilot**, **Windsurf**, and other AI agent
256
267
  | Prop | Type | Description |
257
268
  | :--- | :--- | :--- |
258
269
  | `slots` | `GridSlots` | Replace built-in components (toolbar, pagination, overlays, footer). |
259
- | `slotProps` | `GridSlotProps` | Pass custom props to slot components. |
260
- | `getRowClassName` | `(params) => string` | Add custom CSS class to rows. |
261
- | `getCellClassName` | `(params) => string` | Add custom CSS class to cells. |
262
- | `theme` | `GridTheme` | Apply a custom theme object. |
270
+ | `slotProps` | `object` | Pass custom props to slot components. |
271
+ | `listView` / `listViewColumn` | `boolean` / `GridListViewColDef` | Render rows as cards (mobile layouts). Honours loading, overlays and `slots.footer`; keyboard navigable; tree/group parents get an expand chevron. |
272
+ | `columnGroupingModel` | `GridColumnGroupingModel` | Multi-level column group headers. |
273
+
274
+ Per-cell styling uses `GridColDef.cellClassName` / `headerClassName`; themes are applied with `<DataGridThemeProvider theme={…}>` (see Theming below).
263
275
 
264
276
  ### `apiRef` — Imperative API
265
277
 
@@ -270,12 +282,14 @@ const apiRef = useGridApiRef();
270
282
  // Rows
271
283
  apiRef.current.getRow(id) // → GridRowModel | null
272
284
  apiRef.current.getAllRows() // → GridRowModel[]
273
- apiRef.current.getVisibleRows() // → GridRowModel[] (post-filter/sort)
285
+ apiRef.current.getVisibleRows() // → GridRowModel[] (rows on screen: current page + pinned rows)
286
+ apiRef.current.getAllFilteredRows() // → GridRowModel[] (every filtered + sorted row, all pages)
287
+ apiRef.current.getGroupedExportRows() // → GridGroupedExportRow[] | null (row grouping only)
274
288
 
275
289
  // Columns
276
290
  apiRef.current.getColumn(field) // → GridColDef | null
277
291
  apiRef.current.getAllColumns() // → GridColDef[]
278
- apiRef.current.getVisibleColumns() // → GridColDef[]
292
+ apiRef.current.getVisibleColumns() // → GridColDef[] (visible columns, display order)
279
293
 
280
294
  // Selection
281
295
  apiRef.current.selectRow(id, true)
@@ -283,7 +297,7 @@ apiRef.current.selectRows([id1, id2], true)
283
297
  apiRef.current.getSelectedRows() // → GridRowId[]
284
298
 
285
299
  // Sorting
286
- apiRef.current.sortColumn('name', 'asc')
300
+ apiRef.current.sortColumn('name', 'asc') // null removes the column's sort
287
301
  apiRef.current.getSortModel() // → GridSortItem[]
288
302
 
289
303
  // Filtering
@@ -298,7 +312,7 @@ apiRef.current.setPageSize(50)
298
312
  apiRef.current.scrollToIndexes({ rowIndex: 100, colIndex: 3 })
299
313
 
300
314
  // Clipboard
301
- apiRef.current.copySelectedRows() // → Promise<void>
315
+ apiRef.current.copySelectedRows() // → Promise<void>, rejects if the clipboard write fails
302
316
 
303
317
  // Aggregation
304
318
  apiRef.current.getAggregationResult() // → Record<string, unknown> | null
@@ -347,7 +361,7 @@ import { DataGrid, GridToolbar } from '@opencorestack/opengridx';
347
361
  />
348
362
  ```
349
363
 
350
- `GridToolbar` provides global search, column visibility management, advanced filters, and aggregation controls. Each feature button is automatically hidden if its callback prop is not provided.
364
+ `GridToolbar` provides global search, column visibility management, advanced filters, and aggregation (Summaries) controls, plus a Pivot button when pivot mode is configured. Mounted through `slots.toolbar`, every control works without any filter or visibility props: the grid keeps that state itself, and the props above only make it controlled. Rendered on its own, outside a grid, `GridToolbar` hides each button whose callback prop (`onFilterModelChange`, `onColumnVisibilityModelChange`, `onAggregationModelChange`, `onPivotModelChange`) is not passed.
351
365
 
352
366
  #### Customizing individual toolbar controls
353
367
 
@@ -369,6 +383,8 @@ import { GridToolbar, exportToCsv, useGridApiRef,
369
383
  const apiRef = useGridApiRef();
370
384
 
371
385
  <DataGrid
386
+ rows={rows}
387
+ columns={columns}
372
388
  apiRef={apiRef}
373
389
  slots={{ toolbar: GridToolbar }}
374
390
  slotProps={{
@@ -383,7 +399,7 @@ const apiRef = useGridApiRef();
383
399
  </button>
384
400
  ),
385
401
  renderExportButton: () => (
386
- <button onClick={() => exportToCsv(apiRef.current.getAllRows(), columns)}>
402
+ <button onClick={() => exportToCsv(apiRef.current.getAllFilteredRows(), apiRef.current.getVisibleColumns())}>
387
403
  Export CSV
388
404
  </button>
389
405
  ),
@@ -402,30 +418,31 @@ import {
402
418
  exportToExcel, // ✅ built-in, zero deps
403
419
  exportToExcelAdvanced, // ✅ rich .xlsx — requires: npm install exceljs
404
420
  exportToJson,
421
+ exportToPdf, // ✅ PDF — requires: npm install jspdf jspdf-autotable
405
422
  printGrid
406
423
  } from '@opencorestack/opengridx';
407
424
 
408
425
  exportToCsv(rows, columns, { fileName: 'data.csv' });
409
- exportToExcel(rows, columns, { fileName: 'data.xlsx' });
426
+ exportToExcel(rows, columns, { fileName: 'data.xls' }); // HTML table, opened by Excel as .xls
410
427
  exportToExcelAdvanced(rows, columns, {
411
428
  fileName: 'data.xlsx',
412
429
  columnStyles: { avatar: { embedImage: true, imageWidth: 40, imageHeight: 40 } }
413
430
  });
414
431
  exportToJson(rows, columns, { fileName: 'data.json' });
432
+ await exportToPdf(rows, columns, { fileName: 'data', title: 'Report Title' });
415
433
  printGrid(rows, columns, 'Report Title');
416
434
  ```
417
435
 
418
- > **Optional peer dependency:** `exportToExcelAdvanced` requires ExcelJS:
419
- > ```bash
420
- > npm install exceljs
421
- > ```
436
+ > **Optional peer dependencies:** `exportToExcelAdvanced` requires ExcelJS (`npm install exceljs`); `exportToPdf` requires `npm install jspdf jspdf-autotable`.
437
+
438
+ CSV and HTML-Excel exports neutralise spreadsheet formulas (text starting with `=`, `+`, `-`, `@`, a tab or a carriage return gets a leading `'`; opt out with `escapeFormulas: false`), and CSV starts with a UTF-8 BOM (`bom: false` omits it). `exportToExcel` writes an HTML table, so a `.xlsx` file name is saved as `.xls`. To export what the grid shows, pass `apiRef.current.getAllFilteredRows()` and `apiRef.current.getVisibleColumns()`; with a custom `getRowId`, also pass `getRowId` in the options so `selectedRows` match. See the [Export Guide](docs/features/export-guide.md).
422
439
 
423
440
  ### State Persistence
424
441
 
425
442
  ```tsx
426
443
  import { useGridStateStorage } from '@opencorestack/opengridx';
427
444
 
428
- const { initialState, onStateChange } = useGridStateStorage('my-grid-key');
445
+ const { initialState, onStateChange, clearState } = useGridStateStorage('my-grid-key');
429
446
 
430
447
  <DataGrid
431
448
  rows={rows}
@@ -445,24 +462,25 @@ import { DataGridThemeProvider, darkTheme } from '@opencorestack/opengridx';
445
462
  </DataGridThemeProvider>
446
463
  ```
447
464
 
448
- Built-in themes: `darkTheme`, `roseTheme`, `emeraldTheme`, `amberTheme`, `compactTheme`
465
+ Built-in themes: `darkTheme`, `roseTheme`, `emeraldTheme`, `amberTheme`, `compactTheme`. The provider pins a complete light or dark palette (`theme.mode`), whatever the operating system's colour scheme.
449
466
 
450
467
  ---
451
468
 
452
469
  ## ⚡ Performance & Bundle Size
453
470
 
454
- | Artifact | Minified | Gzipped | Notes |
471
+ | Artifact | Size | Gzipped | Notes |
455
472
  | :--- | :--- | :--- | :--- |
456
- | **Core ES Module** (`opengridx.es.js`) | 242 KB | **58 KB** | Use this — tree-shakeable |
457
- | **Core UMD** (`opengridx.umd.js`) | 164 KB | **48 KB** | CommonJS / CDN compat |
458
- | **Styles** (`opengridx.css`) | 62 KB | **10 KB** | Auto-included |
473
+ | **Core ES Module** (`opengridx.es.js`) | 331 KB | **86 KB** | Use this — tree-shakeable |
474
+ | **Core UMD** (`opengridx.umd.js`) | 233 KB | **73 KB** | CommonJS / CDN compat |
475
+ | **Styles** (`opengridx.css`) | 65 KB | **10 KB** | `import '@opencorestack/opengridx/styles'` |
459
476
  | **ExcelJS** (optional peer dep) | — | — | `npm install exceljs` |
460
- | **npm package download** | — | **613 KB** | Total compressed tarball |
477
+ | **jsPDF** (optional peer dep) | — | — | `npm install jspdf jspdf-autotable` |
478
+ | **npm package download** | — | **~1.1 MB** | Compressed tarball (includes `lib/` source, docs and source maps) |
461
479
 
462
480
  - **Tree-shaking Ready**: ES Module build — bundlers (Vite, Webpack) only include what you use.
463
481
  - **Zero UI Dependencies**: No MUI, Ant Design, or Radix. Pure React + vanilla CSS.
464
- - **Lazy Advanced Export**: ExcelJS is an optional peer dep — not bundled, only used if you install it.
465
- - **Efficient Rendering**: Custom virtualization handles 100k+ rows with zero DOM churn.
482
+ - **Lazy Advanced Export**: ExcelJS and jsPDF are optional peer deps — not bundled, loaded only when you call `exportToExcelAdvanced` / `exportToPdf`.
483
+ - **Efficient Rendering**: Row and column virtualization keeps the DOM small for 100k+ rows (needs a bounded grid height).
466
484
 
467
485
  ---
468
486
 
@@ -485,7 +503,10 @@ Full documentation at 👉 **[opencorestack.github.io/OpenGridX](https://opencor
485
503
  - **[Pinning](docs/features/pinning.md)** — Sticky columns and rows
486
504
  - **[State Persistence](docs/features/state-persistence.md)** — Save/Restore grid state
487
505
  - **[Infinite Scroll](docs/features/infinite-scroll.md)** — Seamless lazy-loading
488
- - **[Export Guide](docs/features/export-guide.md)** — Excel, CSV, and Print
506
+ - **[Export Guide](docs/features/export-guide.md)** — Excel, CSV, JSON, and Print
507
+ - **[PDF Export](docs/features/pdf-export.md)** — Branded PDF reports
508
+ - **[Clipboard](docs/features/clipboard.md)** — Copy rows as TSV
509
+ - **[Keyboard & Accessibility](docs/features/keyboard-navigation.md)** — Keys, focus and ARIA
489
510
  - **[Data Source](docs/features/data-source.md)** — Server-side integration
490
511
  - **[Loading States](docs/features/loading-states.md)** — Skeleton and shimmer overlays
491
512