@opencorestack/opengridx 1.0.5 β†’ 1.0.6

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.
@@ -164,6 +164,59 @@ The main component for displaying and interacting with data.
164
164
 
165
165
  ---
166
166
 
167
+ ## πŸ› οΈ `GridToolbar`
168
+
169
+ The built-in toolbar component. Mount it via `slots={{ toolbar: GridToolbar }}`. All props below are passed through `slotProps.toolbar` (or directly when building a custom wrapper).
170
+
171
+ ### `GridToolbarProps`
172
+
173
+ | Prop | Type | Default | Description |
174
+ | :--- | :--- | :--- | :--- |
175
+ | `columns` | `GridColDef[]` | `[]` | Column definitions β€” injected automatically when used via `slots`. |
176
+ | `baseColumns` | `GridColDef[]` | β€” | Pre-pivot columns shown in the Pivot panel instead of synthetic pivot columns. |
177
+ | `aggregationModel` | `GridAggregationModel` | `{}` | Current aggregation configuration. |
178
+ | `onAggregationModelChange` | `(model: GridAggregationModel) => void` | β€” | Called when the user changes aggregation settings. |
179
+ | `pivotModel` | `GridPivotModel` | β€” | Current pivot configuration. Presence of this prop renders the Pivot button. |
180
+ | `onPivotModelChange` | `(model: GridPivotModel) => void` | β€” | Called when the user changes pivot settings. |
181
+ | `filterModel` | `GridFilterModel` | β€” | Current filter model. Presence of this prop renders the search bar and Filter button. |
182
+ | `onFilterModelChange` | `(model: GridFilterModel) => void` | β€” | Called when the user changes filters or the quick-search value. |
183
+ | `columnVisibilityModel` | `Record<string, boolean>` | `{}` | Current column visibility map. |
184
+ | `onColumnVisibilityModelChange` | `(model: Record<string, boolean>) => void` | β€” | Called when the user shows or hides a column. Presence renders the Columns button. |
185
+ | `onColumnReorder` | `(from: string, to: string) => void` | β€” | Called when the user drags a column in the Columns panel. |
186
+ | `onColumnOrderReset` | `() => void` | β€” | Called when the user clicks "Reset order" in the Columns panel. |
187
+ | `forceColumnsOpen` | `boolean` | β€” | Forces the Columns panel open (used internally by the column header context menu). |
188
+ | `onColumnsPanelClose` | `() => void` | β€” | Called when the Columns panel closes after a `forceColumnsOpen`. |
189
+ | `children` | `ReactNode` | β€” | Content rendered on the **left** side of the toolbar, before the spacer. |
190
+ | `rightContent` | `ReactNode` | β€” | Content rendered on the **right** side, after all built-in buttons. |
191
+ | `className` | `string` | β€” | Additional CSS class on the toolbar root `<div>`. Use for visual theme overrides. |
192
+ | `style` | `CSSProperties` | β€” | Inline styles on the toolbar root. |
193
+ | `renderColumnsButton` | `(props: ToolbarButtonRenderProps) => ReactNode` | β€” | Replace the built-in Columns toggle button. The Columns panel still functions normally. |
194
+ | `renderFilterButton` | `(props: ToolbarButtonRenderProps) => ReactNode` | β€” | Replace the built-in Filters toggle button. The Filter panel still functions normally. |
195
+ | `renderAggregationButton` | `(props: ToolbarButtonRenderProps) => ReactNode` | β€” | Replace the built-in Summaries toggle button. The Aggregation panel still functions normally. |
196
+ | `renderExportButton` | `() => ReactNode` | β€” | Inject an Export button after the Aggregation button. No built-in export button exists. |
197
+ | `renderQuickFilter` | `(props: ToolbarQuickFilterRenderProps) => ReactNode` | β€” | Replace the built-in `GlobalSearch` input with your own component. |
198
+
199
+ ### `ToolbarButtonRenderProps`
200
+
201
+ Passed to `renderColumnsButton`, `renderFilterButton`, and `renderAggregationButton`.
202
+
203
+ | Property | Type | Description |
204
+ | :--- | :--- | :--- |
205
+ | `onClick` | `() => void` | Toggle the associated panel open or closed. |
206
+ | `isOpen` | `boolean` | Whether the associated panel is currently open. |
207
+ | `activeCount` | `number` | Active items: hidden columns for Columns, applied filters for Filter, configured aggregations for Summaries. |
208
+
209
+ ### `ToolbarQuickFilterRenderProps`
210
+
211
+ Passed to `renderQuickFilter`.
212
+
213
+ | Property | Type | Description |
214
+ | :--- | :--- | :--- |
215
+ | `value` | `string` | Current search string. |
216
+ | `onChange` | `(value: string) => void` | Call with the updated string when the input changes. |
217
+
218
+ ---
219
+
167
220
  ## πŸ•ΉοΈ Imperative API (`GridApi`)
168
221
 
169
222
  Access these methods via the `apiRef` prop.
@@ -1,40 +1,221 @@
1
- # `<Toolbar />`
1
+ # `GridToolbar`
2
2
 
3
- The toolbar is an optional component rendered at the top of the grid. It typically contains global actions like exporting, filtering, and column management.
3
+ The toolbar is an optional component rendered at the top of the grid. It provides global search, column visibility management, advanced filters, aggregation configuration, and pivot mode β€” all in one composable component.
4
4
 
5
- ## πŸ› οΈ Provided Component: `GridToolbar`
5
+ ## Basic usage
6
6
 
7
- OpenGridX includes a pre-built `GridToolbar` that bundles common actions.
8
-
9
- ### Usage
10
7
  ```tsx
11
8
  import { DataGrid, GridToolbar } from '@opencorestack/opengridx';
12
9
 
13
10
  <DataGrid
14
- slots={{
15
- toolbar: GridToolbar
11
+ rows={rows}
12
+ columns={columns}
13
+ filterModel={filterModel}
14
+ onFilterModelChange={setFilterModel}
15
+ columnVisibilityModel={columnVisibilityModel}
16
+ onColumnVisibilityModelChange={setColumnVisibilityModel}
17
+ aggregationModel={aggregationModel}
18
+ onAggregationModelChange={setAggregationModel}
19
+ slots={{ toolbar: GridToolbar }}
20
+ />
21
+ ```
22
+
23
+ `GridToolbar` automatically hides buttons for features whose callbacks are not wired. For example, if you don't pass `onFilterModelChange` the search bar and filter button are not rendered.
24
+
25
+ ---
26
+
27
+ ## `GridToolbarProps`
28
+
29
+ | Prop | Type | Default | Description |
30
+ |------|------|---------|-------------|
31
+ | `columns` | `GridColDef[]` | `[]` | Column definitions (injected automatically when used via `slots`). |
32
+ | `baseColumns` | `GridColDef[]` | β€” | Pre-pivot column definitions, used by the Pivot panel to avoid showing synthetic columns. |
33
+ | `aggregationModel` | `GridAggregationModel` | `{}` | Current aggregation configuration. |
34
+ | `onAggregationModelChange` | `(model) => void` | β€” | Called when the user changes aggregation settings. |
35
+ | `pivotModel` | `GridPivotModel` | β€” | Current pivot configuration. |
36
+ | `onPivotModelChange` | `(model) => void` | β€” | Called when the user changes pivot settings. Presence of this prop shows the Pivot button. |
37
+ | `filterModel` | `GridFilterModel` | β€” | Current filter model. Presence of this prop shows the search bar and Filter button. |
38
+ | `onFilterModelChange` | `(model) => void` | β€” | Called when the user changes filters or the search query. |
39
+ | `columnVisibilityModel` | `Record<string, boolean>` | `{}` | Current column visibility state. |
40
+ | `onColumnVisibilityModelChange` | `(model) => void` | β€” | Called when the user shows/hides columns. Presence shows the Columns button. |
41
+ | `onColumnReorder` | `(from, to) => void` | β€” | Called when the user drags a column in the Columns panel. |
42
+ | `onColumnOrderReset` | `() => void` | β€” | Called when the user clicks "Reset order" in the Columns panel. |
43
+ | `forceColumnsOpen` | `boolean` | β€” | When `true`, opens the Columns panel immediately (used internally by the column header menu). |
44
+ | `onColumnsPanelClose` | `() => void` | β€” | Called when the Columns panel closes after a `forceColumnsOpen`. |
45
+ | `children` | `ReactNode` | β€” | Content rendered in the **left** side of the toolbar (before the spacer). |
46
+ | `rightContent` | `ReactNode` | β€” | Content rendered in the **right** side of the toolbar (after all built-in buttons). |
47
+ | `className` | `string` | β€” | Additional CSS class applied to the toolbar root `<div>`. Use for visual overrides without replacing the component. |
48
+ | `style` | `CSSProperties` | β€” | Inline style applied to the toolbar root `<div>`. |
49
+ | `renderColumnsButton` | `(props: ToolbarButtonRenderProps) => ReactNode` | β€” | Replace the built-in Columns button. The Columns panel still opens and closes normally. |
50
+ | `renderFilterButton` | `(props: ToolbarButtonRenderProps) => ReactNode` | β€” | Replace the built-in Filters button. The Filter panel still opens and closes normally. |
51
+ | `renderAggregationButton` | `(props: ToolbarButtonRenderProps) => ReactNode` | β€” | Replace the built-in Summaries button. The Aggregation panel still opens and closes normally. |
52
+ | `renderExportButton` | `() => ReactNode` | β€” | Inject an Export button after the Aggregation button. No built-in export button exists β€” this is the slot for it. |
53
+ | `renderQuickFilter` | `(props: ToolbarQuickFilterRenderProps) => ReactNode` | β€” | Replace the built-in quick-filter search input with your own component. |
54
+
55
+ ---
56
+
57
+ ## Render prop types
58
+
59
+ ### `ToolbarButtonRenderProps`
60
+
61
+ Passed to `renderColumnsButton`, `renderFilterButton`, and `renderAggregationButton`.
62
+
63
+ ```ts
64
+ interface ToolbarButtonRenderProps {
65
+ onClick: () => void; // Toggle the associated panel open/closed
66
+ isOpen: boolean; // Whether the panel is currently open
67
+ activeCount: number; // Active items (hidden columns, applied filters, etc.)
68
+ }
69
+ ```
70
+
71
+ ### `ToolbarQuickFilterRenderProps`
72
+
73
+ Passed to `renderQuickFilter`.
74
+
75
+ ```ts
76
+ interface ToolbarQuickFilterRenderProps {
77
+ value: string; // Current search string
78
+ onChange: (value: string) => void; // Call with new string on input change
79
+ }
80
+ ```
81
+
82
+ ---
83
+
84
+ ## Customization patterns
85
+
86
+ ### Add content to left or right sides
87
+
88
+ Use `children` (left) and `rightContent` (right) to inject elements without touching the built-in buttons:
89
+
90
+ ```tsx
91
+ <DataGrid
92
+ slots={{ toolbar: GridToolbar }}
93
+ slotProps={{
94
+ toolbar: {
95
+ children: <span style={{ fontWeight: 600 }}>My Grid</span>,
96
+ rightContent: (
97
+ <button onClick={handleExport}>Export CSV</button>
98
+ ),
99
+ },
100
+ }}
101
+ />
102
+ ```
103
+
104
+ ### Custom search bar
105
+
106
+ Replace only the search input while keeping the rest of the toolbar intact:
107
+
108
+ ```tsx
109
+ function MySearchBar({ value, onChange }: ToolbarQuickFilterRenderProps) {
110
+ return (
111
+ <input
112
+ className="my-search"
113
+ value={value}
114
+ onChange={e => onChange(e.target.value)}
115
+ placeholder="Search…"
116
+ />
117
+ );
118
+ }
119
+
120
+ <DataGrid
121
+ slots={{ toolbar: GridToolbar }}
122
+ slotProps={{
123
+ toolbar: {
124
+ renderQuickFilter: (props) => <MySearchBar {...props} />,
125
+ },
16
126
  }}
17
127
  />
18
128
  ```
19
129
 
20
- ### Features
21
- - **Quick Search**: Search across all visible columns.
22
- - **Export Menu**: Download data as CSV, Print, or [Advanced Excel](../features/export-guide.md).
23
- - **Column Visibility**: Toggle which columns are shown via a dropdown [Visibility Panel](column-visibility.md).
24
- - **Density**: Switch between Compact, Standard, and Comfortable row heights.
130
+ ### Custom action buttons (panels still work)
25
131
 
26
- ## 🎨 Custom Toolbar
132
+ Replace individual trigger buttons while keeping their panels fully functional:
27
133
 
28
- You can provide your own component to the `toolbar` slot. It will receive props to interact with the grid state.
134
+ ```tsx
135
+ function MyFilterButton({ onClick, isOpen, activeCount }: ToolbarButtonRenderProps) {
136
+ return (
137
+ <button
138
+ className={`my-btn ${isOpen ? 'my-btn--active' : ''}`}
139
+ onClick={onClick}
140
+ >
141
+ Filters {activeCount > 0 && <span className="badge">{activeCount}</span>}
142
+ </button>
143
+ );
144
+ }
145
+
146
+ <DataGrid
147
+ slots={{ toolbar: GridToolbar }}
148
+ slotProps={{
149
+ toolbar: {
150
+ renderFilterButton: (props) => <MyFilterButton {...props} />,
151
+ renderColumnsButton: (props) => <MyColumnsButton {...props} />,
152
+ renderAggregationButton: (props) => <MyAggButton {...props} />,
153
+ },
154
+ }}
155
+ />
156
+ ```
157
+
158
+ ### Add an Export button
159
+
160
+ There is no built-in export button in the toolbar. Use `renderExportButton` to add one:
29
161
 
30
162
  ```tsx
31
- const MyToolbar = () => {
163
+ import { exportToCsv, useGridApiRef } from '@opencorestack/opengridx';
164
+
165
+ const apiRef = useGridApiRef();
166
+
167
+ <DataGrid
168
+ apiRef={apiRef}
169
+ slots={{ toolbar: GridToolbar }}
170
+ slotProps={{
171
+ toolbar: {
172
+ renderExportButton: () => (
173
+ <button onClick={() => exportToCsv(apiRef.current.getAllRows(), columns)}>
174
+ Export CSV
175
+ </button>
176
+ ),
177
+ },
178
+ }}
179
+ />
180
+ ```
181
+
182
+ ### Theme override via `className`
183
+
184
+ Style the toolbar to match your brand without replacing the component:
185
+
186
+ ```css
187
+ /* your-styles.css */
188
+ .my-toolbar {
189
+ background: linear-gradient(135deg, #1e1b4b, #312e81);
190
+ border-bottom: none;
191
+ border-radius: 8px 8px 0 0;
192
+ padding: 10px 16px;
193
+ }
194
+ ```
195
+
196
+ ```tsx
197
+ <DataGrid
198
+ slots={{ toolbar: GridToolbar }}
199
+ slotProps={{ toolbar: { className: 'my-toolbar' } }}
200
+ />
201
+ ```
202
+
203
+ ---
204
+
205
+ ## Fully custom toolbar
206
+
207
+ If the render props don't give you enough control, replace the entire toolbar via `slots.toolbar`:
208
+
209
+ ```tsx
210
+ function MyToolbar() {
32
211
  return (
33
- <div className="custom-toolbar">
34
- <button onClick={...}>Custom Action</button>
212
+ <div className="my-toolbar-root">
213
+ <span>Custom toolbar</span>
35
214
  </div>
36
215
  );
37
- };
216
+ }
38
217
 
39
218
  <DataGrid slots={{ toolbar: MyToolbar }} />
40
219
  ```
220
+
221
+ The custom component receives all `GridToolbarProps` via `slotProps.toolbar`.
@@ -0,0 +1,205 @@
1
+ # Toolbar Customization
2
+
3
+ **Available from:** `@opencorestack/opengridx` v1.0.6
4
+
5
+ Replace individual toolbar controls β€” search bar, column button, filter button, aggregation button β€” without replacing the entire toolbar. All panels (columns, filters, aggregation) continue to work; only the trigger elements change.
6
+
7
+ ---
8
+
9
+ ## Quick start
10
+
11
+ ```tsx
12
+ import {
13
+ DataGrid,
14
+ GridToolbar,
15
+ type ToolbarButtonRenderProps,
16
+ type ToolbarQuickFilterRenderProps,
17
+ } from '@opencorestack/opengridx';
18
+
19
+ <DataGrid
20
+ rows={rows}
21
+ columns={columns}
22
+ filterModel={filterModel}
23
+ onFilterModelChange={setFilterModel}
24
+ columnVisibilityModel={columnVisibilityModel}
25
+ onColumnVisibilityModelChange={setColumnVisibilityModel}
26
+ slots={{ toolbar: GridToolbar }}
27
+ slotProps={{
28
+ toolbar: {
29
+ renderQuickFilter: ({ value, onChange }: ToolbarQuickFilterRenderProps) => (
30
+ <input
31
+ className="my-search"
32
+ value={value}
33
+ onChange={e => onChange(e.target.value)}
34
+ placeholder="Search…"
35
+ />
36
+ ),
37
+ },
38
+ }}
39
+ />
40
+ ```
41
+
42
+ ---
43
+
44
+ ## New props on `GridToolbarProps`
45
+
46
+ | Prop | Type | Description |
47
+ |------|------|-------------|
48
+ | `renderColumnsButton` | `(props: ToolbarButtonRenderProps) => ReactNode` | Replace the Columns toggle button. The Columns panel still opens and closes normally. |
49
+ | `renderFilterButton` | `(props: ToolbarButtonRenderProps) => ReactNode` | Replace the Filters toggle button. The Filter panel still opens and closes normally. |
50
+ | `renderAggregationButton` | `(props: ToolbarButtonRenderProps) => ReactNode` | Replace the Summaries toggle button. The Aggregation panel still opens and closes normally. |
51
+ | `renderExportButton` | `() => ReactNode` | Insert an Export button after the Aggregation button. No built-in export button exists β€” this is the slot for it. |
52
+ | `renderQuickFilter` | `(props: ToolbarQuickFilterRenderProps) => ReactNode` | Replace the built-in search input with your own component. |
53
+ | `className` | `string` | Additional CSS class on the toolbar root `<div>` for theme overrides. |
54
+
55
+ ---
56
+
57
+ ## Render prop types
58
+
59
+ ### `ToolbarButtonRenderProps`
60
+
61
+ ```ts
62
+ interface ToolbarButtonRenderProps {
63
+ onClick: () => void; // toggle the panel
64
+ isOpen: boolean; // whether the panel is open
65
+ activeCount: number; // hidden columns / applied filters / active aggregations
66
+ }
67
+ ```
68
+
69
+ ### `ToolbarQuickFilterRenderProps`
70
+
71
+ ```ts
72
+ interface ToolbarQuickFilterRenderProps {
73
+ value: string;
74
+ onChange: (value: string) => void;
75
+ }
76
+ ```
77
+
78
+ Both types are exported from the package:
79
+
80
+ ```ts
81
+ import type { ToolbarButtonRenderProps, ToolbarQuickFilterRenderProps } from '@opencorestack/opengridx';
82
+ ```
83
+
84
+ ---
85
+
86
+ ## Examples
87
+
88
+ ### Custom search bar
89
+
90
+ ```tsx
91
+ function MySearchBar({ value, onChange }: ToolbarQuickFilterRenderProps) {
92
+ return (
93
+ <div className="search-wrap">
94
+ <SearchIcon />
95
+ <input
96
+ value={value}
97
+ onChange={e => onChange(e.target.value)}
98
+ placeholder="Search…"
99
+ />
100
+ {value && <button onClick={() => onChange('')}>βœ•</button>}
101
+ </div>
102
+ );
103
+ }
104
+
105
+ slotProps={{
106
+ toolbar: {
107
+ renderQuickFilter: (props) => <MySearchBar {...props} />,
108
+ },
109
+ }}
110
+ ```
111
+
112
+ ### Custom filter button with active-count badge
113
+
114
+ ```tsx
115
+ function MyFilterBtn({ onClick, isOpen, activeCount }: ToolbarButtonRenderProps) {
116
+ return (
117
+ <button
118
+ className={`btn ${isOpen ? 'btn--active' : ''}`}
119
+ onClick={onClick}
120
+ >
121
+ Filters
122
+ {activeCount > 0 && <span className="badge">{activeCount}</span>}
123
+ </button>
124
+ );
125
+ }
126
+
127
+ slotProps={{
128
+ toolbar: {
129
+ renderFilterButton: (props) => <MyFilterBtn {...props} />,
130
+ },
131
+ }}
132
+ ```
133
+
134
+ ### Export button wired to `apiRef`
135
+
136
+ ```tsx
137
+ import { exportToCsv, useGridApiRef } from '@opencorestack/opengridx';
138
+
139
+ const apiRef = useGridApiRef();
140
+
141
+ <DataGrid
142
+ apiRef={apiRef}
143
+ slots={{ toolbar: GridToolbar }}
144
+ slotProps={{
145
+ toolbar: {
146
+ renderExportButton: () => (
147
+ <button onClick={() => exportToCsv(apiRef.current.getAllRows(), columns, { filename: 'export' })}>
148
+ Export CSV
149
+ </button>
150
+ ),
151
+ },
152
+ }}
153
+ />
154
+ ```
155
+
156
+ ### Replacing all buttons at once
157
+
158
+ ```tsx
159
+ slotProps={{
160
+ toolbar: {
161
+ renderQuickFilter: (props) => <MySearch {...props} />,
162
+ renderColumnsButton: (props) => <MyColumnsBtn {...props} />,
163
+ renderFilterButton: (props) => <MyFilterBtn {...props} />,
164
+ renderAggregationButton: (props) => <MyAggBtn {...props} />,
165
+ renderExportButton: () => <MyExportBtn />,
166
+ },
167
+ }}
168
+ ```
169
+
170
+ ### Theme override via `className`
171
+
172
+ ```css
173
+ /* your-styles.css */
174
+ .toolbar-dark {
175
+ background: linear-gradient(135deg, #1e1b4b, #312e81);
176
+ border-bottom: none;
177
+ padding: 10px 16px;
178
+ }
179
+ ```
180
+
181
+ ```tsx
182
+ slotProps={{
183
+ toolbar: { className: 'toolbar-dark' },
184
+ }}
185
+ ```
186
+
187
+ ---
188
+
189
+ ## How panels stay functional
190
+
191
+ When you provide a custom button, the toolbar renders your element as the trigger but keeps its own open/close state. The panel (Columns, Filters, or Aggregation) is positioned relative to the wrapper `<div>` surrounding your custom button, so placement is automatic β€” you don't need to pass any refs.
192
+
193
+ Panel close behaviour is unchanged: Escape key closes, click-outside closes (except the Filter panel, which requires an explicit Close button to let users type without it dismissing).
194
+
195
+ ---
196
+
197
+ ## What is NOT replaced
198
+
199
+ These built-in features are unaffected regardless of which render props you provide:
200
+
201
+ - Column panel content (drag-to-reorder, show/hide toggles)
202
+ - Filter panel content (operators, values, logic operator)
203
+ - Aggregation panel content (per-column function pills)
204
+ - Pivot panel (if `onPivotModelChange` is wired)
205
+ - `children` / `rightContent` slot behaviour