@opencorestack/opengridx 1.0.1 → 1.0.3
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.
- package/CHANGELOG.md +15 -0
- package/README.md +36 -0
- package/docs/API_REFERENCE.md +965 -20
- package/package.json +1 -1
package/CHANGELOG.md
CHANGED
|
@@ -5,6 +5,21 @@
|
|
|
5
5
|
|
|
6
6
|
---
|
|
7
7
|
|
|
8
|
+
## [1.0.3] — July 30, 2026 📚
|
|
9
|
+
|
|
10
|
+
### Fixed
|
|
11
|
+
- **API reference expanded to full surface coverage**: `docs/API_REFERENCE.md` grew from 188 to 1,132 lines. Added 8 new top-level sections — server-side data source (`GridDataSource`, `GridGetRowsParams`, `GridGetRowsResponse`), all event callback param types (`GridRowParams`, `GridCellParams`, `GridColumnOrderChangeParams`, `GridRowOrderChangeParams`, `GridDetailPanelParams`), column and row pinning types, full filter model deep reference (per-type operator table, `GridFilterGroup` nesting), grid state and initial state slice reference, aggregation reference (all 6 built-in functions, `getAggregationPosition` semantics), row grouping, column group headers, and list view. DataGrid props section restructured into 13 feature-area sub-tables covering every previously undocumented prop. Developers building server-side sorting + aggregation + pinned columns no longer need to read TypeScript source.
|
|
12
|
+
|
|
13
|
+
---
|
|
14
|
+
|
|
15
|
+
## [1.0.2] — July 30, 2026 📚
|
|
16
|
+
|
|
17
|
+
### Fixed
|
|
18
|
+
- **`GridColDef` documentation**: Added all previously undocumented column properties — `flex`, `minWidth`, `maxWidth`, `align`, `headerAlign`, `description`, `editable`, `renderHeader`, `renderEditCell`, `cellClassName`, `headerClassName`, `disableColumnMenu`, `groupable`, `aggregable`, `availableAggregationFunctions`, `valueOptions` (for `singleSelect`), `colSpan`, `rowSpan`. Both `README.md` and `docs/API_REFERENCE.md` now carry the complete table.
|
|
19
|
+
- **Hooks documentation**: Expanded the stubs in `docs/API_REFERENCE.md` into full reference entries. `usePivot` (was entirely missing), `useGridStateStorage` (was one sentence — now has a full options + return table and code example), `useAggregation` (now has params/return tables and built-in function list), `useGridApiRef` (corrected description and added usage example).
|
|
20
|
+
|
|
21
|
+
---
|
|
22
|
+
|
|
8
23
|
## [1.0.1] — July 30, 2026 📚
|
|
9
24
|
|
|
10
25
|
### Fixed
|
package/README.md
CHANGED
|
@@ -118,6 +118,42 @@ This means that **Cursor**, **GitHub Copilot**, **Windsurf**, and other AI agent
|
|
|
118
118
|
| `className` | `string` | — | Custom CSS class on the grid container. |
|
|
119
119
|
| `style` | `React.CSSProperties` | — | Custom inline styles on the grid container. |
|
|
120
120
|
|
|
121
|
+
### Column Definitions (`GridColDef`)
|
|
122
|
+
|
|
123
|
+
| Property | Type | Default | Description |
|
|
124
|
+
| :--- | :--- | :--- | :--- |
|
|
125
|
+
| `field` | `string` | — | **Required.** Must match the row object key. |
|
|
126
|
+
| `headerName` | `string` | — | Header label text. |
|
|
127
|
+
| `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. |
|
|
132
|
+
| `align` | `'left' \| 'center' \| 'right'` | `'left'` | Cell content alignment. |
|
|
133
|
+
| `headerAlign` | `'left' \| 'center' \| 'right'` | `'left'` | Header content alignment. |
|
|
134
|
+
| `type` | `'string' \| 'number' \| 'date' \| 'boolean' \| 'singleSelect' \| 'image'` | `'string'` | Drives filter operators and default formatting. |
|
|
135
|
+
| `valueOptions` | `Array<string \| number \| { value, label }>` | — | Options list for `type: 'singleSelect'`. |
|
|
136
|
+
| `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). |
|
|
139
|
+
| `renderCell` | `(params) => ReactNode` | — | Fully custom cell renderer. |
|
|
140
|
+
| `renderHeader` | `(params) => ReactNode` | — | Custom header cell renderer. |
|
|
141
|
+
| `renderEditCell` | `(params) => ReactNode` | — | Custom editor rendered in edit mode. |
|
|
142
|
+
| `cellClassName` | `string \| ((params) => string)` | — | CSS class on every cell; use a function for conditional per-row styling. |
|
|
143
|
+
| `headerClassName` | `string` | — | CSS class on the header cell. |
|
|
144
|
+
| `colSpan` | `number \| ((params) => number)` | — | Merge cells horizontally. |
|
|
145
|
+
| `rowSpan` | `number \| ((params) => number)` | — | Merge cells vertically. |
|
|
146
|
+
| `sortable` | `boolean` | `true` | Enable/disable column sorting. |
|
|
147
|
+
| `filterable` | `boolean` | `true` | Enable/disable column filtering. |
|
|
148
|
+
| `resizable` | `boolean` | `true` | Allow drag-resize. |
|
|
149
|
+
| `hideable` | `boolean` | `true` | Allow hiding via the column panel. |
|
|
150
|
+
| `pinnable` | `boolean` | `true` | Allow pinning via the UI. |
|
|
151
|
+
| `disableColumnMenu` | `boolean` | `false` | Hide the column header context menu. |
|
|
152
|
+
| `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. |
|
|
155
|
+
| `availableAggregationFunctions` | `string[]` | all | Restrict which aggregation functions are offered. |
|
|
156
|
+
|
|
121
157
|
### Selection
|
|
122
158
|
|
|
123
159
|
| Prop | Type | Description |
|
package/docs/API_REFERENCE.md
CHANGED
|
@@ -39,6 +39,129 @@ The main component for displaying and interacting with data.
|
|
|
39
39
|
| `processRowUpdate` | `(new, old) => R \| Promise<R>` | — | Fired after a cell edit is committed. |
|
|
40
40
|
| `dataSource` | `GridDataSource` | — | Remote data provider interface. |
|
|
41
41
|
|
|
42
|
+
#### Sorting, Filtering & Pagination
|
|
43
|
+
|
|
44
|
+
| Prop | Type | Default | Description |
|
|
45
|
+
| :--- | :--- | :--- | :--- |
|
|
46
|
+
| `sortingMode` | `'client' \| 'server'` | `'client'` | Set to `'server'` when your backend handles sorting. The grid calls `onSortModelChange` but does not re-sort rows locally. |
|
|
47
|
+
| `filterMode` | `'client' \| 'server'` | `'client'` | Set to `'server'` when your backend handles filtering. The grid calls `onFilterModelChange` but does not re-filter rows locally. |
|
|
48
|
+
| `onSortModelChange` | `(model: GridSortItem[]) => void` | — | Fired when the active sort model changes. |
|
|
49
|
+
| `onFilterModelChange` | `(model: GridFilterModel) => void` | — | Fired when the active filter model changes. |
|
|
50
|
+
|
|
51
|
+
#### Row Selection
|
|
52
|
+
|
|
53
|
+
| Prop | Type | Default | Description |
|
|
54
|
+
| :--- | :--- | :--- | :--- |
|
|
55
|
+
| `rowSelectionModel` | `GridRowSelectionModel` | `[]` | Controlled selection state — array of selected row IDs. |
|
|
56
|
+
| `onRowSelectionModelChange` | `(model: GridRowSelectionModel) => void` | — | Fired when the selection changes. |
|
|
57
|
+
| `disableRowSelectionOnClick` | `boolean` | `false` | When `true`, clicking a row does not toggle its selection. |
|
|
58
|
+
| `disableMultipleRowSelection` | `boolean` | `false` | When `true`, at most one row can be selected at a time. |
|
|
59
|
+
|
|
60
|
+
#### Column Visibility
|
|
61
|
+
|
|
62
|
+
| Prop | Type | Default | Description |
|
|
63
|
+
| :--- | :--- | :--- | :--- |
|
|
64
|
+
| `columnVisibilityModel` | `GridColumnVisibilityModel` | — | Map of `field → boolean` controlling which columns are visible (`false` = hidden). |
|
|
65
|
+
| `onColumnVisibilityModelChange` | `(model: GridColumnVisibilityModel) => void` | — | Fired when the visibility of any column changes. |
|
|
66
|
+
|
|
67
|
+
#### Column & Row Reordering
|
|
68
|
+
|
|
69
|
+
| Prop | Type | Default | Description |
|
|
70
|
+
| :--- | :--- | :--- | :--- |
|
|
71
|
+
| `disableColumnReorder` | `boolean` | `false` | Disables drag-and-drop column reordering. |
|
|
72
|
+
| `columnOrder` | `GridColumnOrder` | — | Controlled ordered array of column field names. |
|
|
73
|
+
| `onColumnOrderChange` | `(params: GridColumnOrderChangeParams) => void` | — | Fired after a column is dragged to a new position. |
|
|
74
|
+
| `rowReordering` | `boolean` | `false` | Enables drag-and-drop row reordering. |
|
|
75
|
+
| `onRowOrderChange` | `(params: GridRowOrderChangeParams) => void` | — | Fired after a row is dragged to a new position. |
|
|
76
|
+
|
|
77
|
+
#### Pinning
|
|
78
|
+
|
|
79
|
+
| Prop | Type | Default | Description |
|
|
80
|
+
| :--- | :--- | :--- | :--- |
|
|
81
|
+
| `pinnedColumns` | `GridColumnPinning` | — | Columns pinned to the left or right viewport edges. See [Column & Row Pinning](#-column--row-pinning). |
|
|
82
|
+
| `onPinnedColumnsChange` | `(model: GridColumnPinning) => void` | — | Fired when column pinning changes. |
|
|
83
|
+
| `pinnedRows` | `GridRowPinning` | — | Row IDs pinned to the top or bottom of the viewport. |
|
|
84
|
+
| `onPinnedRowsChange` | `(model: GridRowPinning) => void` | — | Fired when row pinning changes. |
|
|
85
|
+
| `pinCheckboxColumn` | `boolean` | `false` | Keeps the checkbox column visible during horizontal scrolling. |
|
|
86
|
+
| `pinExpandColumn` | `boolean` | `false` | Keeps the Master-Detail expansion column visible during horizontal scrolling. |
|
|
87
|
+
|
|
88
|
+
#### Inline Editing
|
|
89
|
+
|
|
90
|
+
| Prop | Type | Default | Description |
|
|
91
|
+
| :--- | :--- | :--- | :--- |
|
|
92
|
+
| `isCellEditable` | `(params: GridCellParams) => boolean` | — | Per-cell predicate. Return `false` to make a specific cell read-only even when the column has `editable: true`. |
|
|
93
|
+
| `onProcessRowUpdateError` | `(error: unknown) => void` | — | Fired if `processRowUpdate` throws or returns a rejected Promise. Use to display validation errors or restore the previous row value. |
|
|
94
|
+
|
|
95
|
+
#### Master-Detail
|
|
96
|
+
|
|
97
|
+
| Prop | Type | Default | Description |
|
|
98
|
+
| :--- | :--- | :--- | :--- |
|
|
99
|
+
| `getDetailPanelContent` | `(params: GridDetailPanelParams) => ReactNode` | — | Returns the JSX content rendered inside the expandable detail panel. |
|
|
100
|
+
| `getDetailPanelHeight` | `(params: GridDetailPanelParams) => number \| 'auto'` | `'auto'` | Controls the panel height in pixels, or `'auto'` to fit content. |
|
|
101
|
+
| `detailPanelExpandedRowIds` | `Set<GridRowId>` | — | Controlled set of currently-expanded detail panel row IDs. |
|
|
102
|
+
| `onDetailPanelExpandedRowIdsChange` | `(ids: Set<GridRowId>) => void` | — | Fired when detail panels expand or collapse. |
|
|
103
|
+
|
|
104
|
+
#### Tree Data
|
|
105
|
+
|
|
106
|
+
| Prop | Type | Default | Description |
|
|
107
|
+
| :--- | :--- | :--- | :--- |
|
|
108
|
+
| `treeData` | `boolean` | `false` | Enables hierarchical tree data display. |
|
|
109
|
+
| `getTreeDataPath` | `(row: R) => string[]` | — | Returns the hierarchy path for a row (e.g. `['Engineering', 'Frontend']`). |
|
|
110
|
+
| `groupingColDef` | `GridColDef` | — | Overrides the auto-generated tree expand/collapse column definition. |
|
|
111
|
+
| `defaultGroupingExpansionDepth` | `number` | `0` | Number of tree levels expanded on initial render (`-1` = all). |
|
|
112
|
+
|
|
113
|
+
#### Row Grouping & Aggregation
|
|
114
|
+
|
|
115
|
+
| Prop | Type | Default | Description |
|
|
116
|
+
| :--- | :--- | :--- | :--- |
|
|
117
|
+
| `rowGroupingModel` | `GridRowGroupingModel` | `[]` | Array of field names to group rows by (e.g. `['department', 'team']`). See [Row Grouping](#️-row-grouping). |
|
|
118
|
+
| `onRowGroupingModelChange` | `(model: GridRowGroupingModel) => void` | — | Fired when the grouping model changes. |
|
|
119
|
+
| `aggregationModel` | `GridAggregationModel` | — | Map of `field → aggFn` (e.g. `{ salary: 'sum', age: 'avg' }`). See [Aggregation Reference](#-aggregation-reference). |
|
|
120
|
+
| `onAggregationModelChange` | `(model: GridAggregationModel) => void` | — | Fired when the aggregation model changes. |
|
|
121
|
+
| `getAggregationPosition` | `(groupNode: GridTreeNode \| null) => 'inline' \| 'footer' \| null` | — | Controls where aggregation results appear. `'inline'` = inside the group row, `'footer'` = a dedicated row below the group, `null` = hidden. Pass `null` groupNode = grand-total (root) position. |
|
|
122
|
+
|
|
123
|
+
#### Pivot
|
|
124
|
+
|
|
125
|
+
| Prop | Type | Default | Description |
|
|
126
|
+
| :--- | :--- | :--- | :--- |
|
|
127
|
+
| `pivotMode` | `boolean` | `false` | Switches the grid to multidimensional Pivot Mode. |
|
|
128
|
+
| `pivotModel` | `GridPivotModel` | — | Controlled pivot configuration (row fields, column fields, value fields). |
|
|
129
|
+
| `onPivotModelChange` | `(model: GridPivotModel) => void` | — | Fired when the pivot model changes. |
|
|
130
|
+
|
|
131
|
+
#### Scroll & Viewport
|
|
132
|
+
|
|
133
|
+
| Prop | Type | Default | Description |
|
|
134
|
+
| :--- | :--- | :--- | :--- |
|
|
135
|
+
| `onRowsScrollEnd` | `(params: GridRowScrollEndParams) => void` | — | Fired when the user scrolls to the bottom of the grid viewport. Use this to trigger the next page in infinite-scroll mode. |
|
|
136
|
+
|
|
137
|
+
#### Accessibility & Appearance
|
|
138
|
+
|
|
139
|
+
| Prop | Type | Default | Description |
|
|
140
|
+
| :--- | :--- | :--- | :--- |
|
|
141
|
+
| `ariaLabel` | `string` | — | ARIA label for the grid container element. |
|
|
142
|
+
| `noRowsLabel` | `string` | `'No rows'` | Message shown in the empty-state overlay when there are no rows. |
|
|
143
|
+
| `className` | `string` | — | Additional CSS class applied to the outermost grid wrapper element. |
|
|
144
|
+
| `style` | `React.CSSProperties` | — | Inline styles applied to the grid wrapper element. |
|
|
145
|
+
|
|
146
|
+
#### Imperative Ref
|
|
147
|
+
|
|
148
|
+
| Prop | Type | Default | Description |
|
|
149
|
+
| :--- | :--- | :--- | :--- |
|
|
150
|
+
| `apiRef` | `React.MutableRefObject<GridApi>` | — | Reactive ref to the imperative API. Create with `useGridApiRef()`. |
|
|
151
|
+
|
|
152
|
+
#### List View
|
|
153
|
+
|
|
154
|
+
| Prop | Type | Default | Description |
|
|
155
|
+
| :--- | :--- | :--- | :--- |
|
|
156
|
+
| `listView` | `boolean` | `false` | Renders the grid as a single-column list of cards. Designed for mobile and responsive layouts. |
|
|
157
|
+
| `listViewColumn` | `GridListViewColDef` | — | Column definition for list view mode. Must provide a `renderCell` function. The `field` value is used as a key. |
|
|
158
|
+
|
|
159
|
+
#### Column Group Headers
|
|
160
|
+
|
|
161
|
+
| Prop | Type | Default | Description |
|
|
162
|
+
| :--- | :--- | :--- | :--- |
|
|
163
|
+
| `columnGroupingModel` | `GridColumnGroupingModel` | — | Defines spanning header rows above the regular column headers. See [Column Group Headers](#️-column-group-headers). |
|
|
164
|
+
|
|
42
165
|
---
|
|
43
166
|
|
|
44
167
|
## 🕹️ Imperative API (`GridApi`)
|
|
@@ -91,21 +214,71 @@ Used in Tree Data and Row Grouping hierarchies.
|
|
|
91
214
|
### `GridColDef`
|
|
92
215
|
Defines the behavior and appearance of a single column.
|
|
93
216
|
|
|
217
|
+
#### Sizing & Layout
|
|
218
|
+
|
|
94
219
|
| Property | Type | Default | Description |
|
|
95
220
|
| :--- | :--- | :--- | :--- |
|
|
96
|
-
| `field` | `string` | — | Unique identifier
|
|
97
|
-
| `headerName` | `string` | — | Text
|
|
98
|
-
| `
|
|
99
|
-
| `
|
|
100
|
-
| `
|
|
101
|
-
| `
|
|
102
|
-
| `
|
|
103
|
-
| `
|
|
104
|
-
| `
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
|
221
|
+
| `field` | `string` | — | **Required.** Unique identifier matching the row object key. |
|
|
222
|
+
| `headerName` | `string` | — | Text shown in the column header cell. |
|
|
223
|
+
| `description` | `string` | — | Tooltip shown on header hover (accessibility label). |
|
|
224
|
+
| `width` | `number \| string` | `100` | Fixed width in pixels or a percentage string. |
|
|
225
|
+
| `minWidth` | `number` | — | Minimum width in pixels (enforced during resize). |
|
|
226
|
+
| `maxWidth` | `number` | — | Maximum width in pixels (enforced during resize). |
|
|
227
|
+
| `flex` | `number` | — | Flex grow factor — distributes remaining space proportionally. Mutually exclusive with a fixed `width`. |
|
|
228
|
+
| `align` | `'left' \| 'center' \| 'right'` | `'left'` | Horizontal alignment of cell content. |
|
|
229
|
+
| `headerAlign` | `'left' \| 'center' \| 'right'` | `'left'` | Horizontal alignment of the header cell content. |
|
|
230
|
+
|
|
231
|
+
#### Data & Type
|
|
232
|
+
|
|
233
|
+
| Property | Type | Default | Description |
|
|
234
|
+
| :--- | :--- | :--- | :--- |
|
|
235
|
+
| `type` | `'string' \| 'number' \| 'date' \| 'boolean' \| 'singleSelect' \| 'image'` | `'string'` | Data type — determines default filter operators and cell formatting. |
|
|
236
|
+
| `valueOptions` | `Array<string \| number \| { value: unknown; label: string }>` | — | Allowed values for `type: 'singleSelect'` — used in the filter dropdown and edit cell. |
|
|
237
|
+
| `valueGetter` | `(params: GridValueGetterParams) => unknown` | — | Derive a computed value from the row object. Runs before `valueFormatter` and `renderCell`. |
|
|
238
|
+
| `valueFormatter` | `(params: GridValueFormatterParams) => string` | — | Format the value into a display string (e.g. currency, dates). Does not affect editing or sorting. |
|
|
239
|
+
|
|
240
|
+
#### Rendering
|
|
241
|
+
|
|
242
|
+
| Property | Type | Description |
|
|
243
|
+
| :--- | :--- | :--- |
|
|
244
|
+
| `renderCell` | `(params: GridRenderCellParams) => ReactNode` | Fully custom cell renderer. Receives `value`, `row`, `field`, `rowIndex`, `colIndex`. |
|
|
245
|
+
| `renderHeader` | `(params: GridRenderHeaderParams) => ReactNode` | Custom header cell renderer. Use for icons, sort indicators, or rich headers. |
|
|
246
|
+
| `renderEditCell` | `(params: GridRenderCellParams) => ReactNode` | Custom editor rendered when the cell enters edit mode. Requires `editable: true`. |
|
|
247
|
+
|
|
248
|
+
#### Editing
|
|
249
|
+
|
|
250
|
+
| Property | Type | Default | Description |
|
|
251
|
+
| :--- | :--- | :--- | :--- |
|
|
252
|
+
| `editable` | `boolean` | `false` | Enables inline cell editing. Commit is handled by `DataGrid.processRowUpdate`. |
|
|
253
|
+
|
|
254
|
+
#### Spanning
|
|
255
|
+
|
|
256
|
+
| Property | Type | Description |
|
|
257
|
+
| :--- | :--- | :--- |
|
|
258
|
+
| `colSpan` | `number \| ((params: GridRenderCellParams) => number)` | Number of columns this cell merges horizontally. |
|
|
259
|
+
| `rowSpan` | `number \| ((params: GridRenderCellParams) => number)` | Number of rows this cell merges vertically. |
|
|
260
|
+
|
|
261
|
+
#### Styling
|
|
262
|
+
|
|
263
|
+
| Property | Type | Description |
|
|
264
|
+
| :--- | :--- | :--- |
|
|
265
|
+
| `cellClassName` | `string \| ((params: GridRenderCellParams) => string)` | CSS class applied to every cell in this column. Use a function for conditional per-row styling. |
|
|
266
|
+
| `headerClassName` | `string` | CSS class applied to the header cell. |
|
|
267
|
+
|
|
268
|
+
#### Feature Flags
|
|
269
|
+
|
|
270
|
+
| Property | Type | Default | Description |
|
|
271
|
+
| :--- | :--- | :--- | :--- |
|
|
272
|
+
| `sortable` | `boolean` | `true` | Enable/disable sorting for this column. |
|
|
273
|
+
| `filterable` | `boolean` | `true` | Enable/disable filtering for this column. |
|
|
274
|
+
| `resizable` | `boolean` | `true` | Allow the user to drag-resize this column. |
|
|
275
|
+
| `hideable` | `boolean` | `true` | Allow the user to hide this column via the panel. |
|
|
276
|
+
| `pinnable` | `boolean` | `true` | Allow this column to be pinned via the UI. |
|
|
277
|
+
| `disableColumnMenu` | `boolean` | `false` | Hide the column header kebab/context menu. |
|
|
278
|
+
| `exportable` | `boolean` | `true` | Set to `false` to exclude from CSV, Excel, JSON, and Print exports. |
|
|
279
|
+
| `groupable` | `boolean` | `true` | Allow this column to be used as a row grouping dimension. |
|
|
280
|
+
| `aggregable` | `boolean` | `true` | Allow this column to be aggregated. |
|
|
281
|
+
| `availableAggregationFunctions` | `string[]` | all built-ins | Restrict which aggregation functions are available for this column (e.g. `['sum', 'avg']`). |
|
|
109
282
|
|
|
110
283
|
---
|
|
111
284
|
|
|
@@ -136,17 +309,169 @@ Context provider for overriding the grid's visual system.
|
|
|
136
309
|
## 🛠️ Hooks
|
|
137
310
|
|
|
138
311
|
### `useGridApiRef()`
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
312
|
+
|
|
313
|
+
Creates a typed ref to pass to the `apiRef` prop. Gives you imperative access to the grid after mount.
|
|
314
|
+
|
|
315
|
+
```tsx
|
|
316
|
+
import { useGridApiRef } from '@opencorestack/opengridx';
|
|
317
|
+
|
|
318
|
+
const apiRef = useGridApiRef();
|
|
319
|
+
|
|
320
|
+
// Pass to the grid
|
|
321
|
+
<DataGrid apiRef={apiRef} rows={rows} columns={columns} />
|
|
322
|
+
|
|
323
|
+
// Then call methods imperiously
|
|
324
|
+
apiRef.current.scrollToIndexes({ rowIndex: 0 });
|
|
325
|
+
apiRef.current.setFilterModel({ items: [] });
|
|
326
|
+
```
|
|
327
|
+
|
|
328
|
+
See the [Imperative API (`GridApi`)](#%EF%B8%8F-imperative-api-gridapi) table above for the full method list.
|
|
329
|
+
|
|
330
|
+
---
|
|
143
331
|
|
|
144
332
|
### `useAggregation(params)`
|
|
145
|
-
|
|
146
|
-
|
|
333
|
+
|
|
334
|
+
Headless hook for computing column summaries outside of the built-in `aggregationModel` prop. Useful when you need aggregation results for a custom footer or external display.
|
|
335
|
+
|
|
336
|
+
```tsx
|
|
337
|
+
import { useAggregation } from '@opencorestack/opengridx';
|
|
338
|
+
|
|
339
|
+
const { aggregationResult, isLoading } = useAggregation({
|
|
340
|
+
rows,
|
|
341
|
+
aggregationModel: { salary: 'sum', age: 'avg' },
|
|
342
|
+
isServerSide: false,
|
|
343
|
+
});
|
|
344
|
+
```
|
|
345
|
+
|
|
346
|
+
#### Params (`UseAggregationParams`)
|
|
347
|
+
|
|
348
|
+
| Param | Type | Description |
|
|
349
|
+
| :--- | :--- | :--- |
|
|
350
|
+
| `rows` | `GridRowModel[]` | The rows to aggregate. |
|
|
351
|
+
| `aggregationModel` | `GridAggregationModel` | Map of `field → aggFn` (e.g. `{ salary: 'sum' }`). |
|
|
352
|
+
| `isServerSide` | `boolean` | If `true`, skips client computation and uses `serverAggregationResults`. |
|
|
353
|
+
| `filterModel` | `GridFilterModel` | Optional — restricts aggregation to filtered rows. |
|
|
354
|
+
| `sortModel` | `GridSortItem[]` | Optional — used when `dataSource` is provided. |
|
|
355
|
+
| `dataSource` | `GridDataSource` | Optional — server-side data adapter for async aggregation. |
|
|
356
|
+
| `serverAggregationResults` | `GridAggregationResult \| null` | Pre-fetched results when `isServerSide: true`. |
|
|
357
|
+
|
|
358
|
+
#### Return (`UseAggregationReturn`)
|
|
359
|
+
|
|
360
|
+
| Field | Type | Description |
|
|
361
|
+
| :--- | :--- | :--- |
|
|
362
|
+
| `aggregationResult` | `GridAggregationResult` | Map of `field → computed value`. |
|
|
363
|
+
| `isLoading` | `boolean` | `true` while a server-side fetch is in progress. |
|
|
364
|
+
| `error` | `unknown` | Set if the server-side fetch threw. |
|
|
365
|
+
|
|
366
|
+
**Built-in aggregation functions:** `sum`, `avg`, `min`, `max`, `count`, `unique`
|
|
367
|
+
|
|
368
|
+
You can also use `formatAggregationValue(value, fnName)` to produce a display string from a raw result.
|
|
369
|
+
|
|
370
|
+
---
|
|
371
|
+
|
|
372
|
+
### `usePivot(rawRows, rawCols, model, enabled)`
|
|
373
|
+
|
|
374
|
+
Headless hook that transforms a flat dataset into pivot rows and pivot column definitions. Pass the output directly to `<DataGrid rows={} columns={} />` when `pivotMode` is active.
|
|
375
|
+
|
|
376
|
+
```tsx
|
|
377
|
+
import { usePivot } from '@opencorestack/opengridx';
|
|
378
|
+
|
|
379
|
+
const { pivotRows, pivotColumns, isValid } = usePivot(
|
|
380
|
+
rows,
|
|
381
|
+
columns,
|
|
382
|
+
{
|
|
383
|
+
rowFields: ['department'],
|
|
384
|
+
columnFields: ['year'],
|
|
385
|
+
valueFields: [{ field: 'revenue', aggFn: 'sum' }],
|
|
386
|
+
},
|
|
387
|
+
isPivotEnabled,
|
|
388
|
+
);
|
|
389
|
+
|
|
390
|
+
<DataGrid
|
|
391
|
+
rows={isPivotEnabled ? pivotRows : rows}
|
|
392
|
+
columns={isPivotEnabled ? pivotColumns : columns}
|
|
393
|
+
/>
|
|
394
|
+
```
|
|
395
|
+
|
|
396
|
+
#### Parameters
|
|
397
|
+
|
|
398
|
+
| Param | Type | Description |
|
|
399
|
+
| :--- | :--- | :--- |
|
|
400
|
+
| `rawRows` | `GridRowModel[]` | Original flat dataset. |
|
|
401
|
+
| `rawCols` | `GridColDef[]` | Original column definitions. |
|
|
402
|
+
| `model` | `GridPivotModel` | Pivot configuration — `rowFields`, `columnFields`, `valueFields`. |
|
|
403
|
+
| `enabled` | `boolean` | When `false`, returns empty arrays immediately (no computation). |
|
|
404
|
+
|
|
405
|
+
#### Return (`UsePivotReturn`)
|
|
406
|
+
|
|
407
|
+
| Field | Type | Description |
|
|
408
|
+
| :--- | :--- | :--- |
|
|
409
|
+
| `pivotRows` | `GridRowModel[]` | Transformed rows ready for the grid. |
|
|
410
|
+
| `pivotColumns` | `GridColDef[]` | Generated column definitions for each pivot key. |
|
|
411
|
+
| `colKeys` | `string[]` | The distinct column pivot values used. |
|
|
412
|
+
| `isValid` | `boolean` | `false` if the model is incomplete (e.g. no `rowFields` or `valueFields`). |
|
|
413
|
+
|
|
414
|
+
#### `GridPivotModel`
|
|
415
|
+
|
|
416
|
+
```ts
|
|
417
|
+
interface GridPivotModel {
|
|
418
|
+
rowFields: string[]; // fields to group rows by
|
|
419
|
+
columnFields: string[]; // fields to spread as columns
|
|
420
|
+
valueFields: Array<{
|
|
421
|
+
field: string;
|
|
422
|
+
aggFn: 'sum' | 'avg' | 'count' | 'min' | 'max';
|
|
423
|
+
headerName?: string;
|
|
424
|
+
}>;
|
|
425
|
+
}
|
|
426
|
+
```
|
|
427
|
+
|
|
428
|
+
---
|
|
147
429
|
|
|
148
430
|
### `useGridStateStorage(options)`
|
|
149
|
-
|
|
431
|
+
|
|
432
|
+
Persists grid state (sort, filters, pagination, column visibility, etc.) to `localStorage` and restores it on mount. Pass the returned values directly to `DataGrid`.
|
|
433
|
+
|
|
434
|
+
```tsx
|
|
435
|
+
import { useGridStateStorage } from '@opencorestack/opengridx';
|
|
436
|
+
|
|
437
|
+
// Simple — just a storage key
|
|
438
|
+
const { initialState, onStateChange } = useGridStateStorage('my-grid');
|
|
439
|
+
|
|
440
|
+
// Advanced — with options
|
|
441
|
+
const { initialState, onStateChange, clearState } = useGridStateStorage({
|
|
442
|
+
key: 'my-grid',
|
|
443
|
+
debounceMs: 500, // default: 300
|
|
444
|
+
include: ['sorting', 'filter', 'pagination'], // persist only these slices
|
|
445
|
+
storage: sessionStorage, // default: localStorage
|
|
446
|
+
});
|
|
447
|
+
|
|
448
|
+
<DataGrid
|
|
449
|
+
rows={rows}
|
|
450
|
+
columns={columns}
|
|
451
|
+
initialState={initialState}
|
|
452
|
+
onStateChange={onStateChange}
|
|
453
|
+
/>
|
|
454
|
+
|
|
455
|
+
// Clear saved state (e.g. on a "Reset" button)
|
|
456
|
+
<button onClick={clearState}>Reset Grid</button>
|
|
457
|
+
```
|
|
458
|
+
|
|
459
|
+
#### Options (`UseGridStateStorageOptions`)
|
|
460
|
+
|
|
461
|
+
| Option | Type | Default | Description |
|
|
462
|
+
| :--- | :--- | :--- | :--- |
|
|
463
|
+
| `key` | `string` | — | **Required.** Storage key — use a unique value per grid instance. |
|
|
464
|
+
| `debounceMs` | `number` | `300` | Debounce delay in ms before writing to storage. |
|
|
465
|
+
| `include` | `(keyof GridState)[]` | all | Restrict which state slices are persisted. |
|
|
466
|
+
| `storage` | `Storage` | `localStorage` | Any object implementing `getItem`/`setItem`/`removeItem` (e.g. `sessionStorage` or a custom backend adapter). |
|
|
467
|
+
|
|
468
|
+
#### Return (`UseGridStateStorageReturn`)
|
|
469
|
+
|
|
470
|
+
| Field | Type | Description |
|
|
471
|
+
| :--- | :--- | :--- |
|
|
472
|
+
| `initialState` | `GridState \| undefined` | Restored state from storage — pass to `DataGrid.initialState`. |
|
|
473
|
+
| `onStateChange` | `(state: GridState) => void` | Callback to pass to `DataGrid.onStateChange`. |
|
|
474
|
+
| `clearState` | `() => void` | Removes the saved state from storage. |
|
|
150
475
|
|
|
151
476
|
---
|
|
152
477
|
|
|
@@ -185,3 +510,623 @@ interface GridPivotModel {
|
|
|
185
510
|
valueFields: { field: string; aggFn: string; headerName?: string }[];
|
|
186
511
|
}
|
|
187
512
|
```
|
|
513
|
+
|
|
514
|
+
---
|
|
515
|
+
|
|
516
|
+
## 📡 Event Callback Types
|
|
517
|
+
|
|
518
|
+
These interfaces describe the parameter objects passed to every event callback prop.
|
|
519
|
+
|
|
520
|
+
### `GridRowParams<R>`
|
|
521
|
+
Passed to `onRowClick`.
|
|
522
|
+
|
|
523
|
+
| Property | Type | Description |
|
|
524
|
+
| :--- | :--- | :--- |
|
|
525
|
+
| `row` | `R` | The full row data object. |
|
|
526
|
+
| `id` | `GridRowId` | Unique identifier of the row. |
|
|
527
|
+
| `rowIndex` | `number` | Zero-based index of the row in the visible dataset. |
|
|
528
|
+
|
|
529
|
+
### `GridCellParams<R>`
|
|
530
|
+
Passed to `onCellClick` and `isCellEditable`.
|
|
531
|
+
|
|
532
|
+
| Property | Type | Description |
|
|
533
|
+
| :--- | :--- | :--- |
|
|
534
|
+
| `row` | `R` | The full row data object. |
|
|
535
|
+
| `field` | `string` | The column field name. |
|
|
536
|
+
| `value` | `unknown` | The cell value (after `valueGetter`, before `valueFormatter`). |
|
|
537
|
+
| `colDef` | `GridColDef<R>` | The column definition. |
|
|
538
|
+
| `rowIndex` | `number` | Zero-based row index in the visible dataset. |
|
|
539
|
+
| `colIndex` | `number` | Zero-based column index. |
|
|
540
|
+
|
|
541
|
+
### `GridColumnOrderChangeParams`
|
|
542
|
+
Passed to `onColumnOrderChange`.
|
|
543
|
+
|
|
544
|
+
| Property | Type | Description |
|
|
545
|
+
| :--- | :--- | :--- |
|
|
546
|
+
| `column` | `GridColDef` | The column definition that was moved. |
|
|
547
|
+
| `oldIndex` | `number` | Previous column index. |
|
|
548
|
+
| `targetIndex` | `number` | New column index after the move. |
|
|
549
|
+
|
|
550
|
+
### `GridRowOrderChangeParams<R>`
|
|
551
|
+
Passed to `onRowOrderChange`.
|
|
552
|
+
|
|
553
|
+
| Property | Type | Description |
|
|
554
|
+
| :--- | :--- | :--- |
|
|
555
|
+
| `row` | `R` | The row data object that was moved. |
|
|
556
|
+
| `oldIndex` | `number` | Previous row index. |
|
|
557
|
+
| `targetIndex` | `number` | New row index after the move. |
|
|
558
|
+
|
|
559
|
+
### `GridRowScrollEndParams`
|
|
560
|
+
Passed to `onRowsScrollEnd`.
|
|
561
|
+
|
|
562
|
+
| Property | Type | Description |
|
|
563
|
+
| :--- | :--- | :--- |
|
|
564
|
+
| `visibleTop` | `number` | Pixel offset of the topmost visible row. |
|
|
565
|
+
| `visibleBottom` | `number` | Pixel offset of the bottommost visible row. |
|
|
566
|
+
| `viewportHeight` | `number` | Current height of the scroll viewport in pixels. |
|
|
567
|
+
|
|
568
|
+
### `GridDetailPanelParams<R>`
|
|
569
|
+
Passed to `getDetailPanelContent` and `getDetailPanelHeight`.
|
|
570
|
+
|
|
571
|
+
| Property | Type | Description |
|
|
572
|
+
| :--- | :--- | :--- |
|
|
573
|
+
| `row` | `R` | The full row data object. |
|
|
574
|
+
| `id` | `GridRowId` | Unique identifier of the row. |
|
|
575
|
+
| `rowIndex` | `number` | Zero-based index of the row in the visible dataset. |
|
|
576
|
+
|
|
577
|
+
---
|
|
578
|
+
|
|
579
|
+
## 🌐 Server-Side Data Source (`GridDataSource`)
|
|
580
|
+
|
|
581
|
+
The `dataSource` prop is the primary integration point for connecting the grid to a remote API. When set, the grid delegates data fetching — including pagination, sorting, filtering, and optionally aggregation — to your `getRows` function instead of processing the data locally.
|
|
582
|
+
|
|
583
|
+
### `GridDataSource<R>`
|
|
584
|
+
|
|
585
|
+
| Property | Type | Required | Description |
|
|
586
|
+
| :--- | :--- | :--- | :--- |
|
|
587
|
+
| `getRows` | `(params: GridGetRowsParams) => Promise<GridGetRowsResponse<R>>` | Yes | Called whenever the grid needs data. The promise must resolve with rows and optionally a total row count. |
|
|
588
|
+
| `getAggregations` | `(params: Omit<GridGetRowsParams, 'startRow' \| 'endRow'>) => Promise<Record<string, unknown>>` | No | Called to fetch aggregate values for the full dataset (e.g. column totals). If omitted, aggregation results from `getRows.aggregationResults` are used instead. |
|
|
589
|
+
|
|
590
|
+
### `GridGetRowsParams`
|
|
591
|
+
The object passed to `getRows` by the grid on every data fetch.
|
|
592
|
+
|
|
593
|
+
| Property | Type | Description |
|
|
594
|
+
| :--- | :--- | :--- |
|
|
595
|
+
| `startRow` | `number` | Zero-based index of the first row to fetch (based on `page * pageSize`). |
|
|
596
|
+
| `endRow` | `number` | Zero-based index of the last row to fetch (exclusive). |
|
|
597
|
+
| `sortModel` | `GridSortItem[]` | Active sort configuration. Empty array when no sort is applied. |
|
|
598
|
+
| `filterModel` | `GridFilterModel` | Active filter state. Has empty `items` when no filters are applied. |
|
|
599
|
+
| `groupKeys` | `string[]` | Path of grouping key values for the current group level (used in lazy-loaded tree/grouping). Empty array for the root level. |
|
|
600
|
+
| `aggregationModel` | `GridAggregationModel \| undefined` | Active aggregation configuration, forwarded so the server can compute column summaries. |
|
|
601
|
+
|
|
602
|
+
### `GridGetRowsResponse<R>`
|
|
603
|
+
The object your `getRows` function must resolve with.
|
|
604
|
+
|
|
605
|
+
| Property | Type | Required | Description |
|
|
606
|
+
| :--- | :--- | :--- | :--- |
|
|
607
|
+
| `rows` | `R[]` | Yes | The rows for the requested page/range. |
|
|
608
|
+
| `rowCount` | `number` | No | Total number of rows in the full dataset. Required for server-side pagination; optional for infinite scroll. |
|
|
609
|
+
| `aggregationResults` | `Record<string, unknown>` | No | Column aggregation values for this response (e.g. `{ salary: 84500, age: 34.2 }`). |
|
|
610
|
+
|
|
611
|
+
### Complete Server-Side Usage Example
|
|
612
|
+
|
|
613
|
+
```tsx
|
|
614
|
+
import {
|
|
615
|
+
DataGrid,
|
|
616
|
+
GridDataSource,
|
|
617
|
+
GridGetRowsParams,
|
|
618
|
+
GridGetRowsResponse,
|
|
619
|
+
GridRowModel,
|
|
620
|
+
GridColDef,
|
|
621
|
+
} from '@opencorestack/opengridx';
|
|
622
|
+
|
|
623
|
+
interface Employee extends GridRowModel {
|
|
624
|
+
id: number;
|
|
625
|
+
name: string;
|
|
626
|
+
department: string;
|
|
627
|
+
salary: number;
|
|
628
|
+
}
|
|
629
|
+
|
|
630
|
+
const columns: GridColDef<Employee>[] = [
|
|
631
|
+
{ field: 'name', headerName: 'Name', flex: 1 },
|
|
632
|
+
{ field: 'department', headerName: 'Department', width: 160 },
|
|
633
|
+
{ field: 'salary', headerName: 'Salary', type: 'number', width: 130 },
|
|
634
|
+
];
|
|
635
|
+
|
|
636
|
+
const dataSource: GridDataSource<Employee> = {
|
|
637
|
+
getRows: async (params: GridGetRowsParams): Promise<GridGetRowsResponse<Employee>> => {
|
|
638
|
+
const response = await fetch('/api/employees', {
|
|
639
|
+
method: 'POST',
|
|
640
|
+
headers: { 'Content-Type': 'application/json' },
|
|
641
|
+
body: JSON.stringify(params),
|
|
642
|
+
});
|
|
643
|
+
const data = await response.json();
|
|
644
|
+
// data must have shape { rows: Employee[], total: number }
|
|
645
|
+
return { rows: data.rows, rowCount: data.total };
|
|
646
|
+
},
|
|
647
|
+
|
|
648
|
+
getAggregations: async (params) => {
|
|
649
|
+
const response = await fetch('/api/employees/aggregations', {
|
|
650
|
+
method: 'POST',
|
|
651
|
+
headers: { 'Content-Type': 'application/json' },
|
|
652
|
+
body: JSON.stringify(params),
|
|
653
|
+
});
|
|
654
|
+
return response.json(); // e.g. { salary: 4250000 }
|
|
655
|
+
},
|
|
656
|
+
};
|
|
657
|
+
|
|
658
|
+
export default function EmployeeGrid() {
|
|
659
|
+
return (
|
|
660
|
+
<DataGrid<Employee>
|
|
661
|
+
rows={[]}
|
|
662
|
+
columns={columns}
|
|
663
|
+
dataSource={dataSource}
|
|
664
|
+
paginationMode="server"
|
|
665
|
+
sortingMode="server"
|
|
666
|
+
filterMode="server"
|
|
667
|
+
pagination
|
|
668
|
+
pageSizeOptions={[25, 50, 100]}
|
|
669
|
+
height={600}
|
|
670
|
+
/>
|
|
671
|
+
);
|
|
672
|
+
}
|
|
673
|
+
```
|
|
674
|
+
|
|
675
|
+
**How the grid decides when to call `getRows`:** The hook fires (with a 300 ms debounce) whenever `paginationMode`, `sortingMode`, or `filterMode` is set to `'server'` AND a `dataSource` is provided. Any change to `sortModel`, `filterModel`, or `paginationModel` re-triggers the fetch. Stale responses from superseded requests are silently discarded — only the latest request updates the grid.
|
|
676
|
+
|
|
677
|
+
---
|
|
678
|
+
|
|
679
|
+
## 📌 Column & Row Pinning
|
|
680
|
+
|
|
681
|
+
### `GridColumnPinning`
|
|
682
|
+
|
|
683
|
+
Pinned columns stay visible at the left or right edge of the grid during horizontal scrolling.
|
|
684
|
+
|
|
685
|
+
```typescript
|
|
686
|
+
interface GridColumnPinning {
|
|
687
|
+
left?: string[]; // field names pinned to the left edge
|
|
688
|
+
right?: string[]; // field names pinned to the right edge
|
|
689
|
+
}
|
|
690
|
+
```
|
|
691
|
+
|
|
692
|
+
### `GridRowPinning`
|
|
693
|
+
|
|
694
|
+
Pinned rows stay visible at the top or bottom of the viewport during vertical scrolling. The values are **row IDs**, not full row objects.
|
|
695
|
+
|
|
696
|
+
```typescript
|
|
697
|
+
interface GridRowPinning {
|
|
698
|
+
top?: GridRowId[]; // IDs of rows pinned to the top
|
|
699
|
+
bottom?: GridRowId[]; // IDs of rows pinned to the bottom
|
|
700
|
+
}
|
|
701
|
+
```
|
|
702
|
+
|
|
703
|
+
### Column-level pinning control
|
|
704
|
+
|
|
705
|
+
Set `pinnable: false` on a `GridColDef` to prevent that column from being pinned via the UI menu.
|
|
706
|
+
|
|
707
|
+
### Usage Example
|
|
708
|
+
|
|
709
|
+
```tsx
|
|
710
|
+
import { DataGrid, GridColumnPinning, GridRowPinning } from '@opencorestack/opengridx';
|
|
711
|
+
|
|
712
|
+
<DataGrid
|
|
713
|
+
rows={rows}
|
|
714
|
+
columns={columns}
|
|
715
|
+
// Pin 'name' to the left and 'actions' to the right
|
|
716
|
+
pinnedColumns={{ left: ['name'], right: ['actions'] }}
|
|
717
|
+
// Pin rows with id=1 to the top, id=99 to the bottom
|
|
718
|
+
pinnedRows={{ top: [1], bottom: [99] }}
|
|
719
|
+
// Checkbox and expand columns stay visible while scrolling horizontally
|
|
720
|
+
checkboxSelection
|
|
721
|
+
pinCheckboxColumn
|
|
722
|
+
pinExpandColumn
|
|
723
|
+
/>
|
|
724
|
+
```
|
|
725
|
+
|
|
726
|
+
---
|
|
727
|
+
|
|
728
|
+
## 🔍 Filter Model Deep Reference
|
|
729
|
+
|
|
730
|
+
### `GridFilterModel`
|
|
731
|
+
|
|
732
|
+
The top-level filter state passed to `filterModel` and `onFilterModelChange`.
|
|
733
|
+
|
|
734
|
+
```typescript
|
|
735
|
+
interface GridFilterModel {
|
|
736
|
+
items?: (GridFilterItem | GridFilterGroup)[];
|
|
737
|
+
logicOperator?: 'and' | 'or'; // default: 'and'
|
|
738
|
+
quickFilterValues?: string[]; // global search terms
|
|
739
|
+
}
|
|
740
|
+
```
|
|
741
|
+
|
|
742
|
+
| Property | Type | Default | Description |
|
|
743
|
+
| :--- | :--- | :--- | :--- |
|
|
744
|
+
| `items` | `(GridFilterItem \| GridFilterGroup)[]` | `[]` | Root-level filter conditions or nested groups. |
|
|
745
|
+
| `logicOperator` | `'and' \| 'or'` | `'and'` | How to combine the root `items`. |
|
|
746
|
+
| `quickFilterValues` | `string[]` | `[]` | Each string must match at least one field in the row (all strings must match). Applied before `items`. |
|
|
747
|
+
|
|
748
|
+
### `GridFilterItem`
|
|
749
|
+
|
|
750
|
+
A single column filter condition.
|
|
751
|
+
|
|
752
|
+
| Property | Type | Required | Description |
|
|
753
|
+
| :--- | :--- | :--- | :--- |
|
|
754
|
+
| `id` | `string \| number` | No | Optional stable identifier for this item (useful for controlled updates). |
|
|
755
|
+
| `field` | `string` | Yes | The column field to filter on. |
|
|
756
|
+
| `operator` | `GridFilterOperator` | Yes | The comparison operator to apply. |
|
|
757
|
+
| `value` | `unknown` | No | The value to compare against. Not required for `isEmpty` / `isNotEmpty`. |
|
|
758
|
+
|
|
759
|
+
### `GridFilterGroup`
|
|
760
|
+
|
|
761
|
+
A nested group of filter conditions combined with a logical operator. Groups can be nested arbitrarily.
|
|
762
|
+
|
|
763
|
+
| Property | Type | Required | Description |
|
|
764
|
+
| :--- | :--- | :--- | :--- |
|
|
765
|
+
| `id` | `string \| number` | No | Optional stable identifier. |
|
|
766
|
+
| `logicOperator` | `'and' \| 'or'` | Yes | How to combine the child `items` in this group. |
|
|
767
|
+
| `items` | `(GridFilterItem \| GridFilterGroup)[]` | Yes | Child conditions or nested groups. |
|
|
768
|
+
|
|
769
|
+
### `GridFilterOperator`
|
|
770
|
+
|
|
771
|
+
```typescript
|
|
772
|
+
type GridFilterOperator =
|
|
773
|
+
| 'contains' | 'equals' | 'startsWith' | 'endsWith'
|
|
774
|
+
| 'isEmpty' | 'isNotEmpty' | 'isAnyOf'
|
|
775
|
+
| '>' | '>=' | '<' | '<=' | '!='
|
|
776
|
+
| 'is' | 'not';
|
|
777
|
+
```
|
|
778
|
+
|
|
779
|
+
### Default Operators per Column Type
|
|
780
|
+
|
|
781
|
+
The filter panel shows only the operators relevant to each column's `type`. These are also the operators used when the grid applies client-side filtering.
|
|
782
|
+
|
|
783
|
+
| Column `type` | Default operator | Available operators |
|
|
784
|
+
| :--- | :--- | :--- |
|
|
785
|
+
| `string` (default) | `contains` | `contains`, `equals`, `startsWith`, `endsWith`, `isEmpty`, `isNotEmpty` |
|
|
786
|
+
| `number` | `=` (numeric eq.) | `=`, `!=`, `>`, `>=`, `<`, `<=`, `isEmpty`, `isNotEmpty` |
|
|
787
|
+
| `date` | `is` | `is`, `not`, `after`, `onOrAfter`, `before`, `onOrBefore`, `isEmpty`, `isNotEmpty` |
|
|
788
|
+
| `boolean` | `is` | `is` |
|
|
789
|
+
| `singleSelect` | `isAnyOf` | `isAnyOf`, `is`, `not` |
|
|
790
|
+
|
|
791
|
+
### Nested Group Example
|
|
792
|
+
|
|
793
|
+
```tsx
|
|
794
|
+
import { DataGrid, GridFilterModel } from '@opencorestack/opengridx';
|
|
795
|
+
|
|
796
|
+
const filterModel: GridFilterModel = {
|
|
797
|
+
logicOperator: 'and',
|
|
798
|
+
items: [
|
|
799
|
+
// Simple item: department equals Engineering
|
|
800
|
+
{ id: 1, field: 'department', operator: 'equals', value: 'Engineering' },
|
|
801
|
+
// Nested group: salary > 80000 OR title contains 'Lead'
|
|
802
|
+
{
|
|
803
|
+
id: 2,
|
|
804
|
+
logicOperator: 'or',
|
|
805
|
+
items: [
|
|
806
|
+
{ id: 3, field: 'salary', operator: '>', value: 80000 },
|
|
807
|
+
{ id: 4, field: 'title', operator: 'contains', value: 'Lead' },
|
|
808
|
+
],
|
|
809
|
+
},
|
|
810
|
+
],
|
|
811
|
+
};
|
|
812
|
+
|
|
813
|
+
<DataGrid rows={rows} columns={columns} filterModel={filterModel} filterMode="client" />
|
|
814
|
+
```
|
|
815
|
+
|
|
816
|
+
---
|
|
817
|
+
|
|
818
|
+
## 💾 `GridInitialState` and `GridState`
|
|
819
|
+
|
|
820
|
+
`GridInitialState` is a type alias for `GridState`. Pass it to `initialState` to restore persisted grid state on mount (e.g. from `localStorage`). Each key corresponds to a feature slice — all are optional.
|
|
821
|
+
|
|
822
|
+
```typescript
|
|
823
|
+
type GridInitialState = GridState;
|
|
824
|
+
|
|
825
|
+
interface GridState {
|
|
826
|
+
sorting?: GridSortingState;
|
|
827
|
+
filter?: GridFilterState;
|
|
828
|
+
pagination?: GridPaginationState;
|
|
829
|
+
columns?: GridColumnsState;
|
|
830
|
+
density?: GridDensityState;
|
|
831
|
+
dataSource?: GridDataSourceState;
|
|
832
|
+
}
|
|
833
|
+
```
|
|
834
|
+
|
|
835
|
+
### State Slices
|
|
836
|
+
|
|
837
|
+
| Slice key | Interface | Shape |
|
|
838
|
+
| :--- | :--- | :--- |
|
|
839
|
+
| `sorting` | `GridSortingState` | `{ sortModel: GridSortItem[] }` |
|
|
840
|
+
| `filter` | `GridFilterState` | `{ filterModel: GridFilterModel }` |
|
|
841
|
+
| `pagination` | `GridPaginationState` | `{ paginationModel: GridPaginationModel; rowCount?: number }` |
|
|
842
|
+
| `columns` | `GridColumnsState` | `{ columnWidths: Record<string, number>; columnOrder: string[]; pinnedColumns?: GridColumnPinning; columnVisibilityModel?: Record<string, boolean> }` |
|
|
843
|
+
| `density` | `GridDensityState` | `{ density: 'compact' \| 'standard' \| 'comfortable' }` |
|
|
844
|
+
| `dataSource` | `GridDataSourceState` | `{ loading: boolean; error?: unknown }` (read-only — not meaningful to restore) |
|
|
845
|
+
|
|
846
|
+
### Restoring State from `localStorage`
|
|
847
|
+
|
|
848
|
+
The recommended way is `useGridStateStorage` (see Hooks section), but you can also drive it manually:
|
|
849
|
+
|
|
850
|
+
```tsx
|
|
851
|
+
import { DataGrid, GridState, GridInitialState } from '@opencorestack/opengridx';
|
|
852
|
+
import { useState, useCallback } from 'react';
|
|
853
|
+
|
|
854
|
+
const STORAGE_KEY = 'my-grid-state';
|
|
855
|
+
|
|
856
|
+
function loadState(): GridInitialState | undefined {
|
|
857
|
+
try {
|
|
858
|
+
const raw = localStorage.getItem(STORAGE_KEY);
|
|
859
|
+
return raw ? (JSON.parse(raw) as GridInitialState) : undefined;
|
|
860
|
+
} catch {
|
|
861
|
+
return undefined;
|
|
862
|
+
}
|
|
863
|
+
}
|
|
864
|
+
|
|
865
|
+
export default function PersistentGrid() {
|
|
866
|
+
const [initialState] = useState<GridInitialState | undefined>(loadState);
|
|
867
|
+
|
|
868
|
+
const handleStateChange = useCallback((state: GridState) => {
|
|
869
|
+
localStorage.setItem(STORAGE_KEY, JSON.stringify(state));
|
|
870
|
+
}, []);
|
|
871
|
+
|
|
872
|
+
return (
|
|
873
|
+
<DataGrid
|
|
874
|
+
rows={rows}
|
|
875
|
+
columns={columns}
|
|
876
|
+
initialState={initialState}
|
|
877
|
+
onStateChange={handleStateChange}
|
|
878
|
+
/>
|
|
879
|
+
);
|
|
880
|
+
}
|
|
881
|
+
```
|
|
882
|
+
|
|
883
|
+
---
|
|
884
|
+
|
|
885
|
+
## ∑ Aggregation Reference
|
|
886
|
+
|
|
887
|
+
### `GridAggregationModel`
|
|
888
|
+
|
|
889
|
+
A plain object mapping column field names to aggregation function names.
|
|
890
|
+
|
|
891
|
+
```typescript
|
|
892
|
+
interface GridAggregationModel {
|
|
893
|
+
[field: string]: string; // e.g. { salary: 'sum', age: 'avg', name: 'count' }
|
|
894
|
+
}
|
|
895
|
+
```
|
|
896
|
+
|
|
897
|
+
### `GridAggregationResult`
|
|
898
|
+
|
|
899
|
+
The computed output, also a plain object mapping field names to their computed values.
|
|
900
|
+
|
|
901
|
+
```typescript
|
|
902
|
+
type GridAggregationResult = Record<string, unknown>;
|
|
903
|
+
// e.g. { salary: 420000, age: 34.2, name: 12 }
|
|
904
|
+
```
|
|
905
|
+
|
|
906
|
+
### Built-In Aggregation Functions
|
|
907
|
+
|
|
908
|
+
| Function | Input | Output | Description |
|
|
909
|
+
| :--- | :--- | :--- | :--- |
|
|
910
|
+
| `sum` | numeric values | `number` | Sum of all non-null numeric values in the group. |
|
|
911
|
+
| `avg` | numeric values | `number \| null` | Arithmetic mean. Returns `null` if there are no numeric values. |
|
|
912
|
+
| `min` | numeric values | `number \| null` | Smallest numeric value. Returns `null` if there are no numeric values. |
|
|
913
|
+
| `max` | numeric values | `number \| null` | Largest numeric value. Returns `null` if there are no numeric values. |
|
|
914
|
+
| `count` | any values | `number` | Count of non-null values. |
|
|
915
|
+
| `unique` | any values | `number` | Count of distinct non-null values (uses a `Set`). |
|
|
916
|
+
|
|
917
|
+
All built-in functions are exported as the `BuiltInAggFn` type: `'sum' | 'avg' | 'count' | 'min' | 'max' | 'unique'`.
|
|
918
|
+
|
|
919
|
+
Use `formatAggregationValue(value, fnName)` to turn a raw result into a display string. `avg` is formatted to 2 decimal places; all other numbers use `toLocaleString()`.
|
|
920
|
+
|
|
921
|
+
### `getAggregationPosition` Callback
|
|
922
|
+
|
|
923
|
+
```typescript
|
|
924
|
+
getAggregationPosition?: (groupNode: GridTreeNode | null) => 'inline' | 'footer' | null
|
|
925
|
+
```
|
|
926
|
+
|
|
927
|
+
Called once per group node (and once with `null` for the grand-total / root level) to decide where the aggregated row appears:
|
|
928
|
+
|
|
929
|
+
| Return value | Effect |
|
|
930
|
+
| :--- | :--- |
|
|
931
|
+
| `'inline'` | Aggregation values appear inside the group header row itself. |
|
|
932
|
+
| `'footer'` | A separate aggregation row is rendered below the group's last row. |
|
|
933
|
+
| `null` | Aggregation result is hidden for this group. |
|
|
934
|
+
|
|
935
|
+
### Aggregation + Row Grouping Example
|
|
936
|
+
|
|
937
|
+
```tsx
|
|
938
|
+
import {
|
|
939
|
+
DataGrid,
|
|
940
|
+
GridColDef,
|
|
941
|
+
GridRowModel,
|
|
942
|
+
GridTreeNode,
|
|
943
|
+
GridAggregationModel,
|
|
944
|
+
GridRowGroupingModel,
|
|
945
|
+
} from '@opencorestack/opengridx';
|
|
946
|
+
|
|
947
|
+
interface Employee extends GridRowModel {
|
|
948
|
+
id: number;
|
|
949
|
+
name: string;
|
|
950
|
+
department: string;
|
|
951
|
+
salary: number;
|
|
952
|
+
}
|
|
953
|
+
|
|
954
|
+
const columns: GridColDef<Employee>[] = [
|
|
955
|
+
{ field: 'name', headerName: 'Name', flex: 1 },
|
|
956
|
+
{ field: 'department', headerName: 'Department', width: 160, groupable: true },
|
|
957
|
+
{ field: 'salary', headerName: 'Salary', type: 'number', width: 130, aggregable: true },
|
|
958
|
+
];
|
|
959
|
+
|
|
960
|
+
const aggregationModel: GridAggregationModel = { salary: 'sum' };
|
|
961
|
+
const rowGroupingModel: GridRowGroupingModel = ['department'];
|
|
962
|
+
|
|
963
|
+
export default function GroupedGrid() {
|
|
964
|
+
return (
|
|
965
|
+
<DataGrid<Employee>
|
|
966
|
+
rows={rows}
|
|
967
|
+
columns={columns}
|
|
968
|
+
rowGroupingModel={rowGroupingModel}
|
|
969
|
+
aggregationModel={aggregationModel}
|
|
970
|
+
getAggregationPosition={(groupNode: GridTreeNode | null) => {
|
|
971
|
+
// Show grand total at the footer, group totals inline
|
|
972
|
+
return groupNode === null ? 'footer' : 'inline';
|
|
973
|
+
}}
|
|
974
|
+
/>
|
|
975
|
+
);
|
|
976
|
+
}
|
|
977
|
+
```
|
|
978
|
+
|
|
979
|
+
---
|
|
980
|
+
|
|
981
|
+
## 🗂️ Row Grouping
|
|
982
|
+
|
|
983
|
+
### `GridRowGroupingModel`
|
|
984
|
+
|
|
985
|
+
A simple array of field names that defines which columns the grid groups rows by, in order.
|
|
986
|
+
|
|
987
|
+
```typescript
|
|
988
|
+
type GridRowGroupingModel = string[];
|
|
989
|
+
// e.g. ['department'] → one level of grouping
|
|
990
|
+
// e.g. ['department', 'team'] → two levels (department → team → rows)
|
|
991
|
+
```
|
|
992
|
+
|
|
993
|
+
The referenced fields must have `groupable: true` (the default) on their `GridColDef`.
|
|
994
|
+
|
|
995
|
+
### Usage Example
|
|
996
|
+
|
|
997
|
+
```tsx
|
|
998
|
+
import { DataGrid, GridRowGroupingModel, GridAggregationModel } from '@opencorestack/opengridx';
|
|
999
|
+
import { useState } from 'react';
|
|
1000
|
+
|
|
1001
|
+
export default function GroupingExample() {
|
|
1002
|
+
const [rowGroupingModel, setRowGroupingModel] = useState<GridRowGroupingModel>(['department']);
|
|
1003
|
+
const [aggregationModel, setAggregationModel] = useState<GridAggregationModel>({
|
|
1004
|
+
salary: 'sum',
|
|
1005
|
+
age: 'avg',
|
|
1006
|
+
});
|
|
1007
|
+
|
|
1008
|
+
return (
|
|
1009
|
+
<DataGrid
|
|
1010
|
+
rows={rows}
|
|
1011
|
+
columns={columns}
|
|
1012
|
+
rowGroupingModel={rowGroupingModel}
|
|
1013
|
+
onRowGroupingModelChange={setRowGroupingModel}
|
|
1014
|
+
aggregationModel={aggregationModel}
|
|
1015
|
+
onAggregationModelChange={setAggregationModel}
|
|
1016
|
+
/>
|
|
1017
|
+
);
|
|
1018
|
+
}
|
|
1019
|
+
```
|
|
1020
|
+
|
|
1021
|
+
### Interaction with `aggregationModel`
|
|
1022
|
+
|
|
1023
|
+
When `rowGroupingModel` is set, the grid creates group nodes (see `GridTreeNode`). The `aggregationModel` controls which columns show summaries on those nodes. The `getAggregationPosition` callback gives per-group control over whether the summary appears inline (in the group header row) or as a footer row below the group. For server-side grouping, return aggregation values in `GridGetRowsResponse.aggregationResults`.
|
|
1024
|
+
|
|
1025
|
+
---
|
|
1026
|
+
|
|
1027
|
+
## 🗃️ Column Group Headers
|
|
1028
|
+
|
|
1029
|
+
Column groups render spanning header cells above the normal column header row, allowing multi-level column organisation.
|
|
1030
|
+
|
|
1031
|
+
### `GridColumnGroup`
|
|
1032
|
+
|
|
1033
|
+
```typescript
|
|
1034
|
+
interface GridColumnGroup {
|
|
1035
|
+
groupId: string; // unique identifier for this group
|
|
1036
|
+
headerName: string; // text shown in the spanning header cell
|
|
1037
|
+
headerClassName?: string; // optional CSS class for custom styling
|
|
1038
|
+
children: Array<string | GridColumnGroup>; // field names (leaf) or nested groups
|
|
1039
|
+
}
|
|
1040
|
+
|
|
1041
|
+
type GridColumnGroupingModel = GridColumnGroup[];
|
|
1042
|
+
```
|
|
1043
|
+
|
|
1044
|
+
The `children` array can contain:
|
|
1045
|
+
- **`string`** — a column `field` name, making this a leaf group that spans exactly those columns.
|
|
1046
|
+
- **`GridColumnGroup`** — a nested sub-group, enabling multi-level spanning headers.
|
|
1047
|
+
|
|
1048
|
+
### Usage Example
|
|
1049
|
+
|
|
1050
|
+
```tsx
|
|
1051
|
+
import { DataGrid, GridColumnGroup, GridColumnGroupingModel } from '@opencorestack/opengridx';
|
|
1052
|
+
|
|
1053
|
+
const columnGroupingModel: GridColumnGroupingModel = [
|
|
1054
|
+
{
|
|
1055
|
+
groupId: 'personal',
|
|
1056
|
+
headerName: 'Personal Info',
|
|
1057
|
+
children: ['firstName', 'lastName', 'age'],
|
|
1058
|
+
},
|
|
1059
|
+
{
|
|
1060
|
+
groupId: 'compensation',
|
|
1061
|
+
headerName: 'Compensation',
|
|
1062
|
+
children: [
|
|
1063
|
+
{ groupId: 'base', headerName: 'Base', children: ['salary', 'bonus'] },
|
|
1064
|
+
{ groupId: 'equity', headerName: 'Equity', children: ['options', 'rsu'] },
|
|
1065
|
+
],
|
|
1066
|
+
},
|
|
1067
|
+
];
|
|
1068
|
+
|
|
1069
|
+
export default function GroupedHeadersGrid() {
|
|
1070
|
+
return (
|
|
1071
|
+
<DataGrid
|
|
1072
|
+
rows={rows}
|
|
1073
|
+
columns={columns}
|
|
1074
|
+
columnGroupingModel={columnGroupingModel}
|
|
1075
|
+
/>
|
|
1076
|
+
);
|
|
1077
|
+
}
|
|
1078
|
+
```
|
|
1079
|
+
|
|
1080
|
+
The grid renders two header rows: the spanning group row on top, and the regular per-column header row below. Groups that are not referenced in `columnGroupingModel` are rendered without a spanning header.
|
|
1081
|
+
|
|
1082
|
+
---
|
|
1083
|
+
|
|
1084
|
+
## 📋 List View
|
|
1085
|
+
|
|
1086
|
+
List view renders the grid as a single-column list of cards, replacing all normal column layout. It is designed for narrow viewports and mobile layouts.
|
|
1087
|
+
|
|
1088
|
+
### `GridListViewColDef<R>`
|
|
1089
|
+
|
|
1090
|
+
```typescript
|
|
1091
|
+
interface GridListViewColDef<R extends GridRowModel = GridRowModel> {
|
|
1092
|
+
field: string;
|
|
1093
|
+
renderCell: (params: GridRenderCellParams<R>) => React.ReactNode;
|
|
1094
|
+
}
|
|
1095
|
+
```
|
|
1096
|
+
|
|
1097
|
+
The `renderCell` function receives the full `GridRenderCellParams` (including `row`), so you have access to every field of the row to build a rich card layout.
|
|
1098
|
+
|
|
1099
|
+
### Usage Example
|
|
1100
|
+
|
|
1101
|
+
```tsx
|
|
1102
|
+
import { DataGrid, GridListViewColDef, GridRenderCellParams } from '@opencorestack/opengridx';
|
|
1103
|
+
|
|
1104
|
+
interface Employee extends GridRowModel {
|
|
1105
|
+
id: number;
|
|
1106
|
+
name: string;
|
|
1107
|
+
department: string;
|
|
1108
|
+
salary: number;
|
|
1109
|
+
}
|
|
1110
|
+
|
|
1111
|
+
const listViewColumn: GridListViewColDef<Employee> = {
|
|
1112
|
+
field: 'card',
|
|
1113
|
+
renderCell: (params: GridRenderCellParams<Employee>) => (
|
|
1114
|
+
<div style={{ padding: '12px 16px' }}>
|
|
1115
|
+
<strong>{params.row.name}</strong>
|
|
1116
|
+
<span> — {params.row.department}</span>
|
|
1117
|
+
<div>${params.row.salary.toLocaleString()}</div>
|
|
1118
|
+
</div>
|
|
1119
|
+
),
|
|
1120
|
+
};
|
|
1121
|
+
|
|
1122
|
+
export default function MobileGrid() {
|
|
1123
|
+
return (
|
|
1124
|
+
<DataGrid<Employee>
|
|
1125
|
+
rows={rows}
|
|
1126
|
+
columns={columns}
|
|
1127
|
+
listView
|
|
1128
|
+
listViewColumn={listViewColumn}
|
|
1129
|
+
/>
|
|
1130
|
+
);
|
|
1131
|
+
}
|
|
1132
|
+
```
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@opencorestack/opengridx",
|
|
3
|
-
"version": "1.0.
|
|
3
|
+
"version": "1.0.3",
|
|
4
4
|
"description": "OpenGridX: High-performance React data infrastructure. Unlock advanced Row Grouping, Excel Export, and Column Pinning without the usual \"Pro\" gatekeeping. Built for speed, scale, and complete architectural freedom. Fully open, virtualization-ready, and feature-complete.",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "./dist/opengridx.umd.js",
|