@opencorestack/opengridx 0.1.5 → 0.1.7
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 +27 -0
- package/README.md +9 -0
- package/dist/index.d.ts +6 -0
- package/dist/opengridx.css +1 -1
- package/dist/opengridx.es.js +319 -319
- package/dist/opengridx.es.js.map +1 -1
- package/dist/opengridx.umd.js +7 -7
- package/dist/opengridx.umd.js.map +1 -1
- package/docs/API_REFERENCE.md +177 -0
- package/docs/README.md +60 -0
- package/docs/components/cell.md +44 -0
- package/docs/components/column-group-header.md +57 -0
- package/docs/components/column-resize.md +63 -0
- package/docs/components/column-visibility.md +61 -0
- package/docs/components/datagrid.md +70 -0
- package/docs/components/filter-panel.md +26 -0
- package/docs/components/header.md +39 -0
- package/docs/components/pagination.md +34 -0
- package/docs/components/row.md +31 -0
- package/docs/components/toolbar.md +40 -0
- package/docs/components/tooltip.md +68 -0
- package/docs/customization/slots-api.md +227 -0
- package/docs/customization/theming.md +293 -0
- package/docs/features/aggregation-pivot.md +79 -0
- package/docs/features/cell-spanning.md +520 -0
- package/docs/features/clipboard.md +76 -0
- package/docs/features/custom-pagination.md +143 -0
- package/docs/features/data-source.md +72 -0
- package/docs/features/editing-reordering.md +99 -0
- package/docs/features/export-guide.md +434 -0
- package/docs/features/filtering.md +83 -0
- package/docs/features/infinite-scroll.md +87 -0
- package/docs/features/list-view.md +65 -0
- package/docs/features/loading-states.md +68 -0
- package/docs/features/master-detail.md +46 -0
- package/docs/features/pinning.md +67 -0
- package/docs/features/selection.md +70 -0
- package/docs/features/sorting-pagination.md +66 -0
- package/docs/features/state-persistence.md +67 -0
- package/docs/features/tree-data-grouping.md +67 -0
- package/docs/features/virtualization.md +188 -0
- package/docs/roadmap.md +71 -0
- package/lib/components/Cell/Cell.css +119 -0
- package/lib/components/Cell/Cell.tsx +264 -0
- package/lib/components/Cell/GridEditInputCell.css +62 -0
- package/lib/components/Cell/GridEditInputCell.tsx +152 -0
- package/lib/components/ColumnGroupHeader/ColumnGroupHeader.css +67 -0
- package/lib/components/ColumnGroupHeader/ColumnGroupHeader.tsx +220 -0
- package/lib/components/ColumnResizeHandle/ColumnResizeHandle.css +31 -0
- package/lib/components/ColumnResizeHandle/ColumnResizeHandle.tsx +85 -0
- package/lib/components/ColumnVisibilityPanel/ColumnVisibilityPanel.css +137 -0
- package/lib/components/ColumnVisibilityPanel/ColumnVisibilityPanel.tsx +190 -0
- package/lib/components/DataGrid/DataGrid.css +224 -0
- package/lib/components/DataGrid/DataGrid.tsx +2253 -0
- package/lib/components/DetailPanel/DetailPanel.css +36 -0
- package/lib/components/DetailPanel/DetailPanel.tsx +34 -0
- package/lib/components/FilterPanel/FilterPanel.css +196 -0
- package/lib/components/FilterPanel/FilterPanel.tsx +183 -0
- package/lib/components/FilterPanel/index.ts +1 -0
- package/lib/components/Header/ColumnMenu.css +68 -0
- package/lib/components/Header/ColumnMenu.tsx +249 -0
- package/lib/components/Header/Header.css +224 -0
- package/lib/components/Header/Header.tsx +516 -0
- package/lib/components/ListView/ListView.css +112 -0
- package/lib/components/ListView/ListViewRow.tsx +63 -0
- package/lib/components/Pagination/Pagination.css +91 -0
- package/lib/components/Pagination/Pagination.tsx +151 -0
- package/lib/components/QuickFilter/QuickFilter.css +23 -0
- package/lib/components/QuickFilter/QuickFilter.tsx +79 -0
- package/lib/components/Row/Row.css +126 -0
- package/lib/components/Row/Row.tsx +377 -0
- package/lib/components/Skeleton/Skeleton.css +55 -0
- package/lib/components/Skeleton/Skeleton.tsx +22 -0
- package/lib/components/SkeletonRow/SkeletonRow.css +32 -0
- package/lib/components/SkeletonRow/SkeletonRow.tsx +89 -0
- package/lib/components/SkeletonRow/index.ts +1 -0
- package/lib/components/Toolbar/GlobalSearch.css +113 -0
- package/lib/components/Toolbar/GlobalSearch.tsx +120 -0
- package/lib/components/Toolbar/GridToolbar.css +204 -0
- package/lib/components/Toolbar/GridToolbar.tsx +647 -0
- package/lib/components/Toolbar/PivotPanel.css +212 -0
- package/lib/components/Toolbar/PivotPanel.tsx +239 -0
- package/lib/components/Tooltip/Tooltip.css +59 -0
- package/lib/components/Tooltip/Tooltip.tsx +106 -0
- package/lib/components/ui/Button.css +89 -0
- package/lib/components/ui/Button.tsx +39 -0
- package/lib/components/ui/Checkbox.css +71 -0
- package/lib/components/ui/Checkbox.tsx +66 -0
- package/lib/components/ui/DragHandleIcon.css +19 -0
- package/lib/components/ui/DragHandleIcon.tsx +18 -0
- package/lib/components/ui/ExpandIcon.css +38 -0
- package/lib/components/ui/ExpandIcon.tsx +75 -0
- package/lib/components/ui/Input.css +59 -0
- package/lib/components/ui/Input.tsx +45 -0
- package/lib/components/ui/index.ts +15 -0
- package/lib/hooks/core/useDataGrid.ts +392 -0
- package/lib/hooks/core/useGridApiRef.ts +10 -0
- package/lib/hooks/features/useAggregation.ts +143 -0
- package/lib/hooks/features/useGridClipboard.ts +133 -0
- package/lib/hooks/features/useGridDataSource.ts +190 -0
- package/lib/hooks/features/useGridEditing.ts +100 -0
- package/lib/hooks/features/useGridSpanning.ts +349 -0
- package/lib/hooks/features/usePivot.ts +149 -0
- package/lib/hooks/useColumnReorder.ts +114 -0
- package/lib/hooks/useRowGrouping.ts +302 -0
- package/lib/hooks/useRowReorder.ts +83 -0
- package/lib/hooks/useTreeData.ts +323 -0
- package/lib/index.ts +106 -0
- package/lib/state/index.ts +17 -0
- package/lib/state/types.ts +48 -0
- package/lib/state/useGridStateStorage.ts +113 -0
- package/lib/styles/base/reset.css +21 -0
- package/lib/styles/base/variables.css +161 -0
- package/lib/styles/opengridx.css +27 -0
- package/lib/styles/opengridx.css.d.ts +4 -0
- package/lib/theme/DataGridThemeProvider.tsx +276 -0
- package/lib/theme/defaultStyles.ts +0 -0
- package/lib/theme/index.ts +21 -0
- package/lib/theme/presets.ts +148 -0
- package/lib/theme/types.ts +155 -0
- package/lib/types/index.ts +764 -0
- package/lib/utils/export/exportToExcelAdvanced.ts +516 -0
- package/lib/utils/export/index.ts +550 -0
- package/lib/utils/filtering/index.ts +240 -0
- package/lib/utils/pinning/index.ts +282 -0
- package/lib/utils/sorting/index.ts +55 -0
- package/lib/utils/virtualization/index.ts +106 -0
- package/lib/vite-env.d.ts +1 -0
- package/llms.txt +12 -2
- package/package.json +13 -4
|
@@ -0,0 +1,434 @@
|
|
|
1
|
+
# Export Functionality Guide
|
|
2
|
+
|
|
3
|
+
The DataGrid provides built-in export utilities for multiple formats. The standard exports (CSV, JSON, Print, basic Excel) have **zero dependencies**. The advanced Excel export uses [ExcelJS](https://github.com/exceljs/exceljs) loaded lazily.
|
|
4
|
+
|
|
5
|
+
## Available Export Formats
|
|
6
|
+
|
|
7
|
+
| Format | Function | Deps | Description |
|
|
8
|
+
|---|---|---|---|
|
|
9
|
+
| CSV | `exportToCsv` | none | Comma-separated values |
|
|
10
|
+
| Excel (basic) | `exportToExcel` | none | HTML-table `.xls` trick |
|
|
11
|
+
| **Excel (advanced)** | `exportToExcelAdvanced` | ExcelJS (lazy) | Real `.xlsx` with styles, types, multi-sheet |
|
|
12
|
+
| JSON | `exportToJson` | none | Structured JSON |
|
|
13
|
+
| Print | `printGrid` | none | Browser print dialog |
|
|
14
|
+
|
|
15
|
+
---
|
|
16
|
+
|
|
17
|
+
## Quick Start
|
|
18
|
+
|
|
19
|
+
```tsx
|
|
20
|
+
import { exportToCsv, exportToExcel, exportToExcelAdvanced, exportToJson, printGrid } from '@opencorestack/opengridx';
|
|
21
|
+
|
|
22
|
+
// CSV
|
|
23
|
+
exportToCsv(rows, columns, { fileName: 'data.csv' });
|
|
24
|
+
|
|
25
|
+
// Basic Excel (no deps)
|
|
26
|
+
exportToExcel(rows, columns, { fileName: 'data.xlsx' });
|
|
27
|
+
|
|
28
|
+
// Advanced Excel (ExcelJS, lazy-loaded)
|
|
29
|
+
await exportToExcelAdvanced(rows, columns, { fileName: 'data.xlsx' });
|
|
30
|
+
|
|
31
|
+
// JSON
|
|
32
|
+
exportToJson(rows, columns, { fileName: 'data.json', pretty: true });
|
|
33
|
+
|
|
34
|
+
// Print
|
|
35
|
+
printGrid(rows, columns, 'My Report');
|
|
36
|
+
```
|
|
37
|
+
|
|
38
|
+
---
|
|
39
|
+
|
|
40
|
+
## 1. `exportToCsv`
|
|
41
|
+
|
|
42
|
+
```tsx
|
|
43
|
+
import { exportToCsv } from '@opencorestack/opengridx';
|
|
44
|
+
|
|
45
|
+
exportToCsv(rows, columns, {
|
|
46
|
+
fileName: 'employees.csv',
|
|
47
|
+
includeHeaders: true,
|
|
48
|
+
delimiter: ',',
|
|
49
|
+
selectedRows: [1, 2, 3], // export only these IDs
|
|
50
|
+
aggregationResult: aggResult, // adds SUM/AVG totals row
|
|
51
|
+
aggregationModel: { salary: 'sum' },
|
|
52
|
+
});
|
|
53
|
+
```
|
|
54
|
+
|
|
55
|
+
**`CsvExportOptions`:**
|
|
56
|
+
|
|
57
|
+
| Option | Type | Default | Description |
|
|
58
|
+
|---|---|---|---|
|
|
59
|
+
| `fileName` | `string` | `'export.csv'` | Output filename |
|
|
60
|
+
| `includeHeaders` | `boolean` | `true` | Include column header row |
|
|
61
|
+
| `delimiter` | `string` | `','` | Field delimiter |
|
|
62
|
+
| `selectedRows` | `(string\|number)[]` | — | Export only these row IDs |
|
|
63
|
+
| `aggregationResult` | `object \| null` | — | Aggregation values row |
|
|
64
|
+
| `aggregationModel` | `object \| null` | — | Labels for aggregation row |
|
|
65
|
+
|
|
66
|
+
---
|
|
67
|
+
|
|
68
|
+
## 2. `exportToExcel` (basic)
|
|
69
|
+
|
|
70
|
+
HTML-table approach, no external libraries. Opens reliably in Excel and Numbers but as a legacy `.xls` format.
|
|
71
|
+
|
|
72
|
+
```tsx
|
|
73
|
+
import { exportToExcel } from '@opencorestack/opengridx';
|
|
74
|
+
|
|
75
|
+
exportToExcel(rows, columns, {
|
|
76
|
+
fileName: 'report.xls',
|
|
77
|
+
sheetName: 'Data',
|
|
78
|
+
includeHeaders: true,
|
|
79
|
+
aggregationResult: aggResult,
|
|
80
|
+
aggregationModel: { salary: 'sum' },
|
|
81
|
+
});
|
|
82
|
+
```
|
|
83
|
+
|
|
84
|
+
**`ExcelExportOptions`:**
|
|
85
|
+
|
|
86
|
+
| Option | Type | Default | Description |
|
|
87
|
+
|---|---|---|---|
|
|
88
|
+
| `fileName` | `string` | `'export.xlsx'` | Output filename |
|
|
89
|
+
| `sheetName` | `string` | `'Sheet1'` | Sheet tab name |
|
|
90
|
+
| `includeHeaders` | `boolean` | `true` | Include column header row |
|
|
91
|
+
| `selectedRows` | `(string\|number)[]` | — | Export only these row IDs |
|
|
92
|
+
| `aggregationResult` | `object \| null` | — | Aggregation values row |
|
|
93
|
+
| `aggregationModel` | `object \| null` | — | Labels for aggregation row |
|
|
94
|
+
|
|
95
|
+
---
|
|
96
|
+
|
|
97
|
+
## 3. `exportToExcelAdvanced` ⭐ (recommended)
|
|
98
|
+
|
|
99
|
+
Generates a **real `.xlsx`** file using ExcelJS, loaded lazily (zero bundle-size impact unless called).
|
|
100
|
+
|
|
101
|
+
```tsx
|
|
102
|
+
import { exportToExcelAdvanced } from '@opencorestack/opengridx';
|
|
103
|
+
|
|
104
|
+
// Simple — single sheet, all defaults
|
|
105
|
+
await exportToExcelAdvanced(rows, columns, {
|
|
106
|
+
fileName: 'employees.xlsx',
|
|
107
|
+
});
|
|
108
|
+
|
|
109
|
+
// Full options — multi-sheet, custom styles
|
|
110
|
+
await exportToExcelAdvanced(rows, columns, {
|
|
111
|
+
fileName: 'full-report.xlsx',
|
|
112
|
+
|
|
113
|
+
sheets: [
|
|
114
|
+
{
|
|
115
|
+
name: 'All Employees',
|
|
116
|
+
rows: 'all', // or 'selected'
|
|
117
|
+
includeHeaders: true,
|
|
118
|
+
includeSummary: true, // aggregation totals at bottom
|
|
119
|
+
autoFilter: true, // dropdown filter buttons in header
|
|
120
|
+
frozenHeader: true, // freeze row 1
|
|
121
|
+
alternateRowColor: '#f8fafc',
|
|
122
|
+
},
|
|
123
|
+
{
|
|
124
|
+
name: 'Selected Rows',
|
|
125
|
+
rows: 'selected',
|
|
126
|
+
includeHeaders: true,
|
|
127
|
+
},
|
|
128
|
+
{
|
|
129
|
+
type: 'summary', // standalone aggregation sheet
|
|
130
|
+
name: 'Aggregation',
|
|
131
|
+
},
|
|
132
|
+
],
|
|
133
|
+
|
|
134
|
+
columnStyles: {
|
|
135
|
+
salary: { numFmt: '$#,##0.00', alignment: 'right' },
|
|
136
|
+
bonus: { numFmt: '$#,##0.00', alignment: 'right' },
|
|
137
|
+
percent: { numFmt: '0.00%' },
|
|
138
|
+
joinDate:{ numFmt: 'yyyy-mm-dd' },
|
|
139
|
+
},
|
|
140
|
+
|
|
141
|
+
headerFillColor: '#1e3a5f', // header row background
|
|
142
|
+
headerTextColor: '#e2e8f0', // header row text
|
|
143
|
+
headerFontSize: 11,
|
|
144
|
+
bodyFontSize: 10,
|
|
145
|
+
|
|
146
|
+
aggregationResult: aggResult,
|
|
147
|
+
aggregationModel: { salary: 'sum', bonus: 'sum', score: 'avg' },
|
|
148
|
+
selectedRows: rowSelectionModel,
|
|
149
|
+
});
|
|
150
|
+
```
|
|
151
|
+
|
|
152
|
+
### `ExcelAdvancedExportOptions`
|
|
153
|
+
|
|
154
|
+
| Option | Type | Default | Description |
|
|
155
|
+
|---|---|---|---|
|
|
156
|
+
| `fileName` | `string` | `'export.xlsx'` | Output filename (`.xlsx` appended if missing) |
|
|
157
|
+
| `sheets` | `ExcelSheetDefinition[]` | `[{ name: 'Data', rows: 'all' }]` | Sheet definitions |
|
|
158
|
+
| `columnStyles` | `Record<string, ExcelColumnStyle>` | `{}` | Per-column style overrides |
|
|
159
|
+
| `headerFillColor` | `string` | `'#f1f5f9'` | Header row background (`#rrggbb`) |
|
|
160
|
+
| `headerTextColor` | `string` | `'#334155'` | Header row text color |
|
|
161
|
+
| `headerFontSize` | `number` | `10` | Header font size (pt) |
|
|
162
|
+
| `bodyFontSize` | `number` | `10` | Body font size (pt) |
|
|
163
|
+
| `aggregationResult` | `object \| null` | — | Aggregation totals |
|
|
164
|
+
| `aggregationModel` | `object \| null` | — | Aggregation function labels |
|
|
165
|
+
| `selectedRows` | `(string\|number)[]` | — | IDs for `rows: 'selected'` sheets |
|
|
166
|
+
|
|
167
|
+
### `ExcelSheetDefinition`
|
|
168
|
+
|
|
169
|
+
| Option | Type | Default | Description |
|
|
170
|
+
|---|---|---|---|
|
|
171
|
+
| `name` | `string` | — | Sheet tab name (max 31 chars) |
|
|
172
|
+
| `rows` | `'all' \| 'selected'` | `'all'` | Which rows to include |
|
|
173
|
+
| `includeHeaders` | `boolean` | `true` | Include column header row |
|
|
174
|
+
| `includeSummary` | `boolean` | `false` | Aggregation totals rows at bottom |
|
|
175
|
+
| `autoFilter` | `boolean` | `true` | Excel filter dropdowns on header |
|
|
176
|
+
| `frozenHeader` | `boolean` | `true` | Freeze row 1 |
|
|
177
|
+
| `alternateRowColor` | `string \| false` | `'#f8fafc'` | Odd-row fill. `false` to disable |
|
|
178
|
+
|
|
179
|
+
### `ExcelColumnStyle`
|
|
180
|
+
|
|
181
|
+
| Option | Type | Description |
|
|
182
|
+
|---|---|---|
|
|
183
|
+
| `numFmt` | `string` | Excel number format, e.g. `'$#,##0.00'`, `'0.00%'`, `'yyyy-mm-dd'` |
|
|
184
|
+
| `width` | `number` | Column width in characters (overrides auto) |
|
|
185
|
+
| `alignment` | `'left' \| 'center' \| 'right'` | Horizontal alignment |
|
|
186
|
+
| `embedImage` | `boolean` | If true, URL in cell is fetched and embedded as image |
|
|
187
|
+
| `imageWidth` | `number` | Width of embedded image (px, default: 40) |
|
|
188
|
+
| `imageHeight`| `number` | Height of embedded image (px, default: 40) |
|
|
189
|
+
|
|
190
|
+
### Summary Sheet
|
|
191
|
+
|
|
192
|
+
Pass `{ type: 'summary', name: 'My Sheet' }` in `sheets` to add a standalone aggregation sheet:
|
|
193
|
+
|
|
194
|
+
```
|
|
195
|
+
| Column | Function | Value |
|
|
196
|
+
|--------------|----------|-----------|
|
|
197
|
+
| Salary | SUM | $8,320,000|
|
|
198
|
+
| Bonus | SUM | $1,040,000|
|
|
199
|
+
| Perf. Score | AVG | 3.7 |
|
|
200
|
+
```
|
|
201
|
+
|
|
202
|
+
### Feature Comparison: Basic vs Advanced
|
|
203
|
+
|
|
204
|
+
| Feature | `exportToExcel` | `exportToExcelAdvanced` |
|
|
205
|
+
|---|---|---|
|
|
206
|
+
| True `.xlsx` format | ❌ HTML trick | ✅ |
|
|
207
|
+
| Native number cells | ❌ text | ✅ |
|
|
208
|
+
| Native date cells | ❌ text | ✅ |
|
|
209
|
+
| Native boolean cells | ❌ text | ✅ |
|
|
210
|
+
| Number format strings | ❌ | ✅ |
|
|
211
|
+
| Bold / colored header | ❌ CSS ignored | ✅ |
|
|
212
|
+
| Column widths | ❌ | ✅ auto from `colDef.width` |
|
|
213
|
+
| Frozen header row | ❌ | ✅ |
|
|
214
|
+
| Auto-filter dropdowns | ❌ | ✅ |
|
|
215
|
+
| Alternating row colors | ❌ | ✅ |
|
|
216
|
+
| Multi-sheet workbooks | ❌ | ✅ |
|
|
217
|
+
| Aggregation totals row | Inline text | ✅ styled |
|
|
218
|
+
| Standalone summary sheet | ❌ | ✅ |
|
|
219
|
+
| Bundle impact | Zero | Zero (lazy-loaded) |
|
|
220
|
+
|
|
221
|
+
---
|
|
222
|
+
|
|
223
|
+
## 4. `exportToJson`
|
|
224
|
+
|
|
225
|
+
```tsx
|
|
226
|
+
import { exportToJson } from '@opencorestack/opengridx';
|
|
227
|
+
|
|
228
|
+
exportToJson(rows, columns, {
|
|
229
|
+
fileName: 'data.json',
|
|
230
|
+
pretty: true,
|
|
231
|
+
aggregationResult: aggResult,
|
|
232
|
+
aggregationModel,
|
|
233
|
+
selectedRows: [1, 2, 3],
|
|
234
|
+
});
|
|
235
|
+
```
|
|
236
|
+
|
|
237
|
+
When `aggregationResult` is provided, output shape becomes:
|
|
238
|
+
```json
|
|
239
|
+
{
|
|
240
|
+
"data": [...],
|
|
241
|
+
"aggregation": {
|
|
242
|
+
"labels": { "salary": "SUM" },
|
|
243
|
+
"values": { "salary": 8320000 }
|
|
244
|
+
}
|
|
245
|
+
}
|
|
246
|
+
```
|
|
247
|
+
|
|
248
|
+
**`JsonExportOptions`:**
|
|
249
|
+
|
|
250
|
+
| Option | Type | Default | Description |
|
|
251
|
+
|---|---|---|---|
|
|
252
|
+
| `fileName` | `string` | `'export.json'` | Output filename |
|
|
253
|
+
| `pretty` | `boolean` | `true` | Pretty-print with indentation |
|
|
254
|
+
| `selectedRows` | `(string\|number)[]` | — | Export only these row IDs |
|
|
255
|
+
| `aggregationResult` | `object \| null` | — | Append aggregation object |
|
|
256
|
+
| `aggregationModel` | `object \| null` | — | Function labels |
|
|
257
|
+
|
|
258
|
+
---
|
|
259
|
+
|
|
260
|
+
## 5. `printGrid`
|
|
261
|
+
|
|
262
|
+
Opens a browser print dialog with a formatted table.
|
|
263
|
+
|
|
264
|
+
```tsx
|
|
265
|
+
import { printGrid } from '@opencorestack/opengridx';
|
|
266
|
+
|
|
267
|
+
// Simple
|
|
268
|
+
printGrid(rows, columns, 'Employee Report');
|
|
269
|
+
|
|
270
|
+
// With options
|
|
271
|
+
printGrid(rows, columns, {
|
|
272
|
+
title: 'Q1 Report',
|
|
273
|
+
selectedRows: [1, 2, 3],
|
|
274
|
+
aggregationResult: aggResult,
|
|
275
|
+
aggregationModel,
|
|
276
|
+
});
|
|
277
|
+
```
|
|
278
|
+
|
|
279
|
+
**`PrintOptions`:**
|
|
280
|
+
|
|
281
|
+
| Option | Type | Description |
|
|
282
|
+
|---|---|---|
|
|
283
|
+
| `title` | `string` | Print page title |
|
|
284
|
+
| `selectedRows` | `(string\|number)[]` | Print only these row IDs |
|
|
285
|
+
| `aggregationResult` | `object \| null` | Append totals |
|
|
286
|
+
| `aggregationModel` | `object \| null` | Label totals |
|
|
287
|
+
|
|
288
|
+
---
|
|
289
|
+
|
|
290
|
+
## Common Patterns
|
|
291
|
+
|
|
292
|
+
### Export with toolbar integration
|
|
293
|
+
|
|
294
|
+
```tsx
|
|
295
|
+
import { DataGrid, GridToolbar, exportToExcelAdvanced } from '@opencorestack/opengridx';
|
|
296
|
+
|
|
297
|
+
function MyGrid() {
|
|
298
|
+
const [rows, setRows] = useState([...]);
|
|
299
|
+
const [columns] = useState([...]);
|
|
300
|
+
const [selected, setSelected] = useState([]);
|
|
301
|
+
|
|
302
|
+
return (
|
|
303
|
+
<DataGrid
|
|
304
|
+
rows={rows}
|
|
305
|
+
columns={columns}
|
|
306
|
+
checkboxSelection
|
|
307
|
+
rowSelectionModel={selected}
|
|
308
|
+
onRowSelectionModelChange={setSelected}
|
|
309
|
+
slots={{ toolbar: GridToolbar }}
|
|
310
|
+
slotProps={{
|
|
311
|
+
toolbar: {
|
|
312
|
+
onExcelAdvanced: () => exportToExcelAdvanced(rows, columns, {
|
|
313
|
+
fileName: 'report.xlsx',
|
|
314
|
+
selectedRows: selected,
|
|
315
|
+
}),
|
|
316
|
+
},
|
|
317
|
+
}}
|
|
318
|
+
/>
|
|
319
|
+
);
|
|
320
|
+
}
|
|
321
|
+
```
|
|
322
|
+
|
|
323
|
+
### Multi-sheet with selection
|
|
324
|
+
|
|
325
|
+
```tsx
|
|
326
|
+
await exportToExcelAdvanced(rows, columns, {
|
|
327
|
+
fileName: 'report.xlsx',
|
|
328
|
+
sheets: [
|
|
329
|
+
{ name: 'All Data', rows: 'all', includeSummary: true },
|
|
330
|
+
{ name: 'Selected', rows: 'selected', includeSummary: false },
|
|
331
|
+
{ type: 'summary', name: 'Totals' },
|
|
332
|
+
],
|
|
333
|
+
selectedRows: rowSelectionModel,
|
|
334
|
+
aggregationResult: aggResult,
|
|
335
|
+
aggregationModel: { salary: 'sum', bonus: 'sum' },
|
|
336
|
+
});
|
|
337
|
+
```
|
|
338
|
+
|
|
339
|
+
### Respect `valueFormatter` for styled columns
|
|
340
|
+
|
|
341
|
+
The advanced export keeps **raw values** for typed columns (`number`, `date`, `boolean`) so Excel can format them natively with `numFmt`. For `string` columns, `valueFormatter` is applied before writing.
|
|
342
|
+
|
|
343
|
+
```tsx
|
|
344
|
+
const columns: GridColDef[] = [
|
|
345
|
+
{
|
|
346
|
+
field: 'salary',
|
|
347
|
+
type: 'number', // ← raw number written to Excel
|
|
348
|
+
valueFormatter: ({ value }) => `$${value.toLocaleString()}`, // used in CSV/print
|
|
349
|
+
},
|
|
350
|
+
];
|
|
351
|
+
|
|
352
|
+
await exportToExcelAdvanced(rows, columns, {
|
|
353
|
+
columnStyles: {
|
|
354
|
+
salary: { numFmt: '$#,##0.00' }, // ← Excel formats the native number
|
|
355
|
+
},
|
|
356
|
+
});
|
|
357
|
+
```
|
|
358
|
+
|
|
359
|
+
---
|
|
360
|
+
|
|
361
|
+
## Value Formatters
|
|
362
|
+
|
|
363
|
+
All export functions respect `valueFormatter` and `valueGetter`:
|
|
364
|
+
|
|
365
|
+
```tsx
|
|
366
|
+
const columns: GridColDef[] = [
|
|
367
|
+
{
|
|
368
|
+
field: 'fullName',
|
|
369
|
+
valueGetter: ({ row }) => `${row.firstName} ${row.lastName}`,
|
|
370
|
+
},
|
|
371
|
+
{
|
|
372
|
+
field: 'salary',
|
|
373
|
+
valueFormatter: ({ value }) => `$${value.toLocaleString()}`,
|
|
374
|
+
},
|
|
375
|
+
];
|
|
376
|
+
```
|
|
377
|
+
|
|
378
|
+
> **Note:** In `exportToExcelAdvanced`, `valueFormatter` is only applied for `string`-typed columns. For `number`/`date`/`boolean` columns, raw values are passed to Excel and formatted via `columnStyles.numFmt`.
|
|
379
|
+
|
|
380
|
+
---
|
|
381
|
+
|
|
382
|
+
## Excluding Columns
|
|
383
|
+
|
|
384
|
+
You can exclude specific columns (e.g., action buttons or menus) from all export formats using the `exportable` property in the column definition. System columns are also automatically excluded.
|
|
385
|
+
|
|
386
|
+
| Method | Description |
|
|
387
|
+
|---|---|
|
|
388
|
+
| `exportable: false` | Set in `GridColDef` to manually exclude any column |
|
|
389
|
+
| `__check__` | Native checkbox column (auto-excluded) |
|
|
390
|
+
| `__actions__` | Common field for action buttons (auto-excluded) |
|
|
391
|
+
| `isSpacer: true` | Spacer columns (auto-excluded) |
|
|
392
|
+
|
|
393
|
+
### Example
|
|
394
|
+
```tsx
|
|
395
|
+
const columns: GridColDef[] = [
|
|
396
|
+
{ field: 'id', headerName: 'ID' },
|
|
397
|
+
{ field: 'name', headerName: 'Name' },
|
|
398
|
+
{
|
|
399
|
+
field: 'actions',
|
|
400
|
+
headerName: 'Actions',
|
|
401
|
+
exportable: false // This column won't appear in CSV/Excel/JSON/Print
|
|
402
|
+
},
|
|
403
|
+
];
|
|
404
|
+
```
|
|
405
|
+
|
|
406
|
+
---
|
|
407
|
+
|
|
408
|
+
## Performance Notes
|
|
409
|
+
|
|
410
|
+
| Format | 10k rows | 100k rows |
|
|
411
|
+
|---|---|---|
|
|
412
|
+
| CSV | ~50ms | ~500ms |
|
|
413
|
+
| JSON | ~80ms | ~800ms |
|
|
414
|
+
| Excel (basic) | ~200ms | ~2s |
|
|
415
|
+
| Excel (advanced) | ~300ms | ~3s |
|
|
416
|
+
| Print | Best with paginated data | — |
|
|
417
|
+
|
|
418
|
+
---
|
|
419
|
+
|
|
420
|
+
## Browser Compatibility
|
|
421
|
+
|
|
422
|
+
All export functions work in:
|
|
423
|
+
- ✅ Chrome/Edge 90+
|
|
424
|
+
- ✅ Firefox 88+
|
|
425
|
+
- ✅ Safari 14+
|
|
426
|
+
|
|
427
|
+
---
|
|
428
|
+
|
|
429
|
+
## See Also
|
|
430
|
+
|
|
431
|
+
- [Demo: Export Data](../demo/examples/ExportDemo.tsx)
|
|
432
|
+
- [Demo: Advanced Excel Export](../demo/examples/AdvancedExcelExportDemo.tsx)
|
|
433
|
+
- [Slots API Reference](./SLOTS_API.md)
|
|
434
|
+
- [Theming Guide](./THEMING.md)
|
|
@@ -0,0 +1,83 @@
|
|
|
1
|
+
# 🔍 Filtering System
|
|
2
|
+
|
|
3
|
+
OpenGridX provides a robust filtering system with support for both client-side and server-side operations.
|
|
4
|
+
|
|
5
|
+
## 📑 Overview
|
|
6
|
+
- **Quick Filter**: Search across all columns simultaneously.
|
|
7
|
+
- **Column Filters**: Specific operators for different data types (string, number, date, etc.).
|
|
8
|
+
- **Multi-Filter Groups**: Support for `AND`/`OR` logic operators.
|
|
9
|
+
- **Server-Side Filtering**: Offload complex queries to your backend.
|
|
10
|
+
|
|
11
|
+
---
|
|
12
|
+
|
|
13
|
+
## 🛠️ Usage
|
|
14
|
+
|
|
15
|
+
### Client-Side Filtering (Default)
|
|
16
|
+
Simply define your columns with `filterable: true` (which is the default).
|
|
17
|
+
|
|
18
|
+
```tsx
|
|
19
|
+
<DataGrid
|
|
20
|
+
rows={rows}
|
|
21
|
+
columns={[
|
|
22
|
+
{ field: 'name', headerName: 'Name' },
|
|
23
|
+
{ field: 'age', headerName: 'Age', type: 'number' }
|
|
24
|
+
]}
|
|
25
|
+
/>
|
|
26
|
+
```
|
|
27
|
+
|
|
28
|
+
### Server-Side Filtering
|
|
29
|
+
Set `filterMode="server"` and handle the request in your `dataSource`.
|
|
30
|
+
|
|
31
|
+
```tsx
|
|
32
|
+
<DataGrid
|
|
33
|
+
filterMode="server"
|
|
34
|
+
onFilterModelChange={(model) => console.log('Current Filters:', model)}
|
|
35
|
+
dataSource={{
|
|
36
|
+
getRows: async (params) => {
|
|
37
|
+
// params.filterModel contains the items and logic operators
|
|
38
|
+
return fetchRowsFromBackend(params);
|
|
39
|
+
}
|
|
40
|
+
}}
|
|
41
|
+
/>
|
|
42
|
+
```
|
|
43
|
+
|
|
44
|
+
---
|
|
45
|
+
|
|
46
|
+
## ⚙️ Filter Model API
|
|
47
|
+
|
|
48
|
+
The `GridFilterModel` describes the current state of filters.
|
|
49
|
+
|
|
50
|
+
```typescript
|
|
51
|
+
interface GridFilterModel {
|
|
52
|
+
items: GridFilterItem[]; // Active filter items
|
|
53
|
+
logicOperator?: 'and' | 'or'; // How to combine items
|
|
54
|
+
quickFilterValues?: string[]; // Values for the global search
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
interface GridFilterItem {
|
|
58
|
+
field: string; // Column to filter
|
|
59
|
+
operator: GridFilterOperator;
|
|
60
|
+
value?: any; // Comparison value
|
|
61
|
+
}
|
|
62
|
+
```
|
|
63
|
+
|
|
64
|
+
### Supported Operators
|
|
65
|
+
| Type | Operators |
|
|
66
|
+
| :--- | :--- |
|
|
67
|
+
| **String** | `contains`, `equals`, `startsWith`, `endsWith`, `isEmpty`, `isNotEmpty` |
|
|
68
|
+
| **Number** | `=`, `!=`, `>`, `>=`, `<`, `<=`, `isEmpty`, `isNotEmpty` |
|
|
69
|
+
| **Date** | `is`, `not`, `after`, `before`, `isEmpty`, `isNotEmpty` |
|
|
70
|
+
| **Boolean** | `is` |
|
|
71
|
+
|
|
72
|
+
---
|
|
73
|
+
|
|
74
|
+
## 🎨 Customizing Filter Components
|
|
75
|
+
You can replace the default filter panel via the `slots` API:
|
|
76
|
+
|
|
77
|
+
```tsx
|
|
78
|
+
<DataGrid
|
|
79
|
+
slots={{
|
|
80
|
+
filterPanel: MyCustomFilterPanel
|
|
81
|
+
}}
|
|
82
|
+
/>
|
|
83
|
+
```
|
|
@@ -0,0 +1,87 @@
|
|
|
1
|
+
# Infinite Scroll
|
|
2
|
+
|
|
3
|
+
The OpenGridX DataGrid supports infinite scrolling (lazy loading), allowing you to load large datasets incrementally as the user scrolls.
|
|
4
|
+
|
|
5
|
+
## Concept
|
|
6
|
+
|
|
7
|
+
When infinite scroll is enabled, the grid:
|
|
8
|
+
1. Disables client-side slicing (pagination in the UI).
|
|
9
|
+
2. Uses `paginationModel` internally to track the current page and page size.
|
|
10
|
+
3. Triggers `onRowsScrollEnd` when the user scrolls near the bottom of the grid, signaling that more data should be fetched.
|
|
11
|
+
4. Data is typically **appended** to the existing rows, rather than replacing them.
|
|
12
|
+
|
|
13
|
+
## Usage
|
|
14
|
+
|
|
15
|
+
To enable infinite scrolling:
|
|
16
|
+
|
|
17
|
+
1. Set `pagination={false}` to disable UI pagination controls.
|
|
18
|
+
2. Set `paginationMode="infinite"`.
|
|
19
|
+
3. Implement `onRowsScrollEnd` to update your data fetching logic/state (e.g., increment page number).
|
|
20
|
+
4. Ensure your `dataSource` manages the loaded rows correctly (usually appending).
|
|
21
|
+
|
|
22
|
+
```tsx
|
|
23
|
+
import { DataGrid, GridDataSource } from '@opencorestack/opengridx';
|
|
24
|
+
|
|
25
|
+
// ... setup columns and mockApi ...
|
|
26
|
+
|
|
27
|
+
export default function InfiniteScrollDemo() {
|
|
28
|
+
const [paginationModel, setPaginationModel] = useState({
|
|
29
|
+
page: 0,
|
|
30
|
+
pageSize: 50
|
|
31
|
+
});
|
|
32
|
+
const [loading, setLoading] = useState(false);
|
|
33
|
+
const [allRows, setAllRows] = useState([]);
|
|
34
|
+
|
|
35
|
+
const dataSource: GridDataSource = useMemo(() => ({
|
|
36
|
+
getRows: async (params) => {
|
|
37
|
+
setLoading(true);
|
|
38
|
+
try {
|
|
39
|
+
// Fetch NEXT batch of rows from server
|
|
40
|
+
const response = await mockApi.getRows(params);
|
|
41
|
+
|
|
42
|
+
// CRITICAL: Append new rows to existing rows
|
|
43
|
+
// (Or ensure response.rows contains ONLY new rows and parent handles appending)
|
|
44
|
+
return response;
|
|
45
|
+
} finally {
|
|
46
|
+
setLoading(false);
|
|
47
|
+
}
|
|
48
|
+
}
|
|
49
|
+
}), []);
|
|
50
|
+
|
|
51
|
+
const handleScrollEnd = useCallback(() => {
|
|
52
|
+
if (!loading) {
|
|
53
|
+
// Increment page to fetch next batch
|
|
54
|
+
setPaginationModel(prev => ({
|
|
55
|
+
...prev,
|
|
56
|
+
page: prev.page + 1
|
|
57
|
+
}));
|
|
58
|
+
}
|
|
59
|
+
}, [loading]);
|
|
60
|
+
|
|
61
|
+
return (
|
|
62
|
+
<DataGrid
|
|
63
|
+
rows={[]} // Rows managed by dataSource
|
|
64
|
+
columns={columns}
|
|
65
|
+
dataSource={dataSource}
|
|
66
|
+
|
|
67
|
+
// KEY PROPS FOR INFINITE SCROLL
|
|
68
|
+
pagination={false}
|
|
69
|
+
paginationMode="infinite"
|
|
70
|
+
sortingMode="server"
|
|
71
|
+
|
|
72
|
+
paginationModel={paginationModel}
|
|
73
|
+
onPaginationModelChange={setPaginationModel}
|
|
74
|
+
|
|
75
|
+
onRowsScrollEnd={handleScrollEnd}
|
|
76
|
+
/>
|
|
77
|
+
);
|
|
78
|
+
}
|
|
79
|
+
```
|
|
80
|
+
|
|
81
|
+
## Implementation Details
|
|
82
|
+
|
|
83
|
+
* **`onRowsScrollEnd`**: Triggered when `scrollHeight - scrollTop - clientHeight < threshold` (default 100px).
|
|
84
|
+
* **Request Handling**: `useGridDataSource` includes logic to cancel stale requests if scrolling happens too quickly.
|
|
85
|
+
* **Appending vs Replacing**:
|
|
86
|
+
* In `infinite` mode, rows fetched for **new pages** are appended.
|
|
87
|
+
* Rows fetched due to **sorting/filtering changes** replace the entire dataset (resetting to page 0).
|
|
@@ -0,0 +1,65 @@
|
|
|
1
|
+
# 📱 List View
|
|
2
|
+
|
|
3
|
+
Switch from a multi-column grid to a single-column detailed list. Perfect for mobile responsiveness or card-based layouts.
|
|
4
|
+
|
|
5
|
+
---
|
|
6
|
+
|
|
7
|
+
## 🏗️ Usage
|
|
8
|
+
|
|
9
|
+
Enable List View by passing the `listView` prop. You must also provide a `listViewColumn` object which defines how each "Card" should be rendered.
|
|
10
|
+
|
|
11
|
+
```tsx
|
|
12
|
+
const listColDef: GridListViewColDef<Employee> = {
|
|
13
|
+
field: 'card',
|
|
14
|
+
renderCell: (params) => <MyEmployeeCard row={params.row} />
|
|
15
|
+
};
|
|
16
|
+
|
|
17
|
+
<DataGrid
|
|
18
|
+
listView={true}
|
|
19
|
+
listViewColumn={listColDef}
|
|
20
|
+
rows={rows}
|
|
21
|
+
columns={columns} // Fallback columns for standard grid view
|
|
22
|
+
/>
|
|
23
|
+
```
|
|
24
|
+
|
|
25
|
+
---
|
|
26
|
+
|
|
27
|
+
## 🎨 Styling
|
|
28
|
+
|
|
29
|
+
When `listView` is active:
|
|
30
|
+
- **Header is Hidden**: The standard column header row disappears.
|
|
31
|
+
- **Full Width**: The row container becomes a vertical stack where the `renderCell` output takes 100% of the available width.
|
|
32
|
+
- **Card Containers**: Each row maintains its standard selection and hover behaviors, but visually acts as a card.
|
|
33
|
+
|
|
34
|
+
### Custom Card Rendering
|
|
35
|
+
The `renderCell` function in `listViewColumn` receives all standard `GridRenderCellParams`, allowing you to build rich, complex UIs for each item.
|
|
36
|
+
|
|
37
|
+
```tsx
|
|
38
|
+
function MyEmployeeCard({ row }) {
|
|
39
|
+
return (
|
|
40
|
+
<div className="employee-card">
|
|
41
|
+
<Avatar src={row.avatar} />
|
|
42
|
+
<div className="info">
|
|
43
|
+
<h3>{row.name}</h3>
|
|
44
|
+
<p>{row.role}</p>
|
|
45
|
+
</div>
|
|
46
|
+
<div className="status">{row.status}</div>
|
|
47
|
+
</div>
|
|
48
|
+
);
|
|
49
|
+
}
|
|
50
|
+
```
|
|
51
|
+
|
|
52
|
+
---
|
|
53
|
+
|
|
54
|
+
## 📱 Responsive Toggle
|
|
55
|
+
|
|
56
|
+
A common pattern is to toggle List View based on screen width:
|
|
57
|
+
|
|
58
|
+
```tsx
|
|
59
|
+
const isMobile = window.innerWidth < 768;
|
|
60
|
+
|
|
61
|
+
<DataGrid
|
|
62
|
+
listView={isMobile}
|
|
63
|
+
// ...
|
|
64
|
+
/>
|
|
65
|
+
```
|