@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,40 @@
|
|
|
1
|
+
# `<Toolbar />`
|
|
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.
|
|
4
|
+
|
|
5
|
+
## 🛠️ Provided Component: `GridToolbar`
|
|
6
|
+
|
|
7
|
+
OpenGridX includes a pre-built `GridToolbar` that bundles common actions.
|
|
8
|
+
|
|
9
|
+
### Usage
|
|
10
|
+
```tsx
|
|
11
|
+
import { DataGrid, GridToolbar } from '@opencorestack/opengridx';
|
|
12
|
+
|
|
13
|
+
<DataGrid
|
|
14
|
+
slots={{
|
|
15
|
+
toolbar: GridToolbar
|
|
16
|
+
}}
|
|
17
|
+
/>
|
|
18
|
+
```
|
|
19
|
+
|
|
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.
|
|
25
|
+
|
|
26
|
+
## 🎨 Custom Toolbar
|
|
27
|
+
|
|
28
|
+
You can provide your own component to the `toolbar` slot. It will receive props to interact with the grid state.
|
|
29
|
+
|
|
30
|
+
```tsx
|
|
31
|
+
const MyToolbar = () => {
|
|
32
|
+
return (
|
|
33
|
+
<div className="custom-toolbar">
|
|
34
|
+
<button onClick={...}>Custom Action</button>
|
|
35
|
+
</div>
|
|
36
|
+
);
|
|
37
|
+
};
|
|
38
|
+
|
|
39
|
+
<DataGrid slots={{ toolbar: MyToolbar }} />
|
|
40
|
+
```
|
|
@@ -0,0 +1,68 @@
|
|
|
1
|
+
# `<GridTooltip />`
|
|
2
|
+
|
|
3
|
+
The `GridTooltip` component provides a lightweight, accessible tooltip for any HTML or React element. It is commonly used within columns, actions, or toolbars to display extra information when a user hovers over a component.
|
|
4
|
+
|
|
5
|
+
## 📑 Overview
|
|
6
|
+
- **Portal Rendering**: Tooltips are rendered at the end of `document.body` for unobstructed positioning.
|
|
7
|
+
- **Dynamic Calculation**: Tooltips calculate their placement relative to the target element on hover.
|
|
8
|
+
- **Support for React Elements**: It wraps its child element to attach event listeners and calculate position.
|
|
9
|
+
- **Customizable Delays**: Support for `enterDelay` and `leaveDelay`.
|
|
10
|
+
|
|
11
|
+
---
|
|
12
|
+
|
|
13
|
+
## 🛠️ Usage
|
|
14
|
+
|
|
15
|
+
### Tooltip with a Button
|
|
16
|
+
Wrap any React element with the `GridTooltip` and provide a `title`.
|
|
17
|
+
|
|
18
|
+
```tsx
|
|
19
|
+
import { GridTooltip } from '@opencorestack/opengridx';
|
|
20
|
+
|
|
21
|
+
<GridTooltip title="Click to Export">
|
|
22
|
+
<button onClick={handleExport}>
|
|
23
|
+
Export as Excel
|
|
24
|
+
</button>
|
|
25
|
+
</GridTooltip>
|
|
26
|
+
```
|
|
27
|
+
|
|
28
|
+
### Tooltip with Custom Placement
|
|
29
|
+
You can choose from four different placements: `top`, `bottom`, `left`, or `right`.
|
|
30
|
+
|
|
31
|
+
```tsx
|
|
32
|
+
<GridTooltip title="Top Placement" placement="top">
|
|
33
|
+
<span>Hover me</span>
|
|
34
|
+
</GridTooltip>
|
|
35
|
+
|
|
36
|
+
<GridTooltip title="Bottom Placement" placement="bottom">
|
|
37
|
+
<span>Hover me</span>
|
|
38
|
+
</GridTooltip>
|
|
39
|
+
```
|
|
40
|
+
|
|
41
|
+
---
|
|
42
|
+
|
|
43
|
+
## ⚙️ Properties
|
|
44
|
+
|
|
45
|
+
| Property | Type | Default | Description |
|
|
46
|
+
| :--- | :--- | :--- | :--- |
|
|
47
|
+
| **`title`** | `React.ReactNode` | — | Content (text, JSX, etc.) to show inside the tooltip. |
|
|
48
|
+
| **`children`** | `React.ReactElement` | — | The target element the tooltip is attached to. |
|
|
49
|
+
| **`placement`** | `'top'`, `'bottom'`, `'left'`, `'right'` | `'top'` | Direction where the tooltip appears. |
|
|
50
|
+
| **`enterDelay`** | `number` | `200` | Delay (ms) before showing the tooltip. |
|
|
51
|
+
| **`leaveDelay`** | `number` | `0` | Delay (ms) before hiding the tooltip. |
|
|
52
|
+
|
|
53
|
+
---
|
|
54
|
+
|
|
55
|
+
## 🎨 Slot Implementation
|
|
56
|
+
In the DataGrid, specialized components like the Toolbar often use tooltips within their built-in actions. These can be customized or replaced using the slots API.
|
|
57
|
+
|
|
58
|
+
```tsx
|
|
59
|
+
<DataGrid
|
|
60
|
+
slots={{
|
|
61
|
+
tooltip: GridTooltip
|
|
62
|
+
}}
|
|
63
|
+
/>
|
|
64
|
+
```
|
|
65
|
+
|
|
66
|
+
## 📝 Accessibility
|
|
67
|
+
- Tooltips are triggered by mouse hover events (`onMouseEnter`/`onMouseLeave`).
|
|
68
|
+
- It is recommended to use descriptive `aria-label` tags on the child element for screen readers, as tooltips are visually focused.
|
|
@@ -0,0 +1,227 @@
|
|
|
1
|
+
# Slots API Reference
|
|
2
|
+
|
|
3
|
+
The Slots API allows you to replace any built-in component in the DataGrid with your own custom implementation.
|
|
4
|
+
|
|
5
|
+
## Available Slots
|
|
6
|
+
|
|
7
|
+
### 1. `toolbar`
|
|
8
|
+
Add a custom toolbar above the grid (commonly used for export buttons, filters, actions).
|
|
9
|
+
|
|
10
|
+
**Props received:**
|
|
11
|
+
```typescript
|
|
12
|
+
{
|
|
13
|
+
// Any props from slotProps.toolbar
|
|
14
|
+
}
|
|
15
|
+
```
|
|
16
|
+
|
|
17
|
+
**Example:**
|
|
18
|
+
```tsx
|
|
19
|
+
import { exportToCsv, exportToExcel } from '@opencorestack/opengridx';
|
|
20
|
+
|
|
21
|
+
function CustomToolbar({ rows, columns }) {
|
|
22
|
+
return (
|
|
23
|
+
<div style={{ padding: '12px', display: 'flex', gap: '8px' }}>
|
|
24
|
+
<button onClick={() => exportToCsv(rows, columns)}>
|
|
25
|
+
Export CSV
|
|
26
|
+
</button>
|
|
27
|
+
<button onClick={() => exportToExcel(rows, columns)}>
|
|
28
|
+
Export Excel
|
|
29
|
+
</button>
|
|
30
|
+
</div>
|
|
31
|
+
);
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
<DataGrid
|
|
35
|
+
slots={{ toolbar: CustomToolbar }}
|
|
36
|
+
slotProps={{ toolbar: { rows, columns } }}
|
|
37
|
+
/>
|
|
38
|
+
```
|
|
39
|
+
|
|
40
|
+
### 2. `pagination`
|
|
41
|
+
Replace the default pagination component.
|
|
42
|
+
|
|
43
|
+
**Props received:**
|
|
44
|
+
```typescript
|
|
45
|
+
{
|
|
46
|
+
page: number; // Current page (0-based)
|
|
47
|
+
pageSize: number; // Current page size
|
|
48
|
+
rowCount: number; // Total number of rows
|
|
49
|
+
pageSizeOptions: number[]; // Available page sizes
|
|
50
|
+
onPageChange: (page: number) => void;
|
|
51
|
+
onPageSizeChange: (size: number) => void;
|
|
52
|
+
}
|
|
53
|
+
```
|
|
54
|
+
|
|
55
|
+
**Example:**
|
|
56
|
+
```tsx
|
|
57
|
+
<DataGrid
|
|
58
|
+
slots={{ pagination: CustomPagination }}
|
|
59
|
+
slotProps={{ pagination: { customProp: 'value' } }}
|
|
60
|
+
/>
|
|
61
|
+
```
|
|
62
|
+
|
|
63
|
+
### 3. `noRowsOverlay`
|
|
64
|
+
Replace the empty state shown when there are no rows.
|
|
65
|
+
|
|
66
|
+
**Props received:**
|
|
67
|
+
```typescript
|
|
68
|
+
{
|
|
69
|
+
// Any props from slotProps.noRowsOverlay
|
|
70
|
+
}
|
|
71
|
+
```
|
|
72
|
+
|
|
73
|
+
**Example:**
|
|
74
|
+
```tsx
|
|
75
|
+
function CustomNoRows() {
|
|
76
|
+
return (
|
|
77
|
+
<div style={{ padding: '40px', textAlign: 'center' }}>
|
|
78
|
+
<h3>No data available</h3>
|
|
79
|
+
<p>Try adjusting your filters</p>
|
|
80
|
+
</div>
|
|
81
|
+
);
|
|
82
|
+
}
|
|
83
|
+
|
|
84
|
+
<DataGrid
|
|
85
|
+
slots={{ noRowsOverlay: CustomNoRows }}
|
|
86
|
+
/>
|
|
87
|
+
```
|
|
88
|
+
|
|
89
|
+
### 4. `loadingOverlay`
|
|
90
|
+
Replace the loading state overlay.
|
|
91
|
+
|
|
92
|
+
**Props received:**
|
|
93
|
+
```typescript
|
|
94
|
+
{
|
|
95
|
+
// Any props from slotProps.loadingOverlay
|
|
96
|
+
}
|
|
97
|
+
```
|
|
98
|
+
|
|
99
|
+
**Example:**
|
|
100
|
+
```tsx
|
|
101
|
+
function CustomLoader() {
|
|
102
|
+
return (
|
|
103
|
+
<div style={{ padding: '40px', textAlign: 'center' }}>
|
|
104
|
+
<Spin size="large" /> {/* Ant Design Spinner */}
|
|
105
|
+
<p>Loading data...</p>
|
|
106
|
+
</div>
|
|
107
|
+
);
|
|
108
|
+
}
|
|
109
|
+
|
|
110
|
+
<DataGrid
|
|
111
|
+
slots={{ loadingOverlay: CustomLoader }}
|
|
112
|
+
/>
|
|
113
|
+
```
|
|
114
|
+
|
|
115
|
+
### 5. `footer`
|
|
116
|
+
Replace the entire footer section (including pagination).
|
|
117
|
+
|
|
118
|
+
**Props received:**
|
|
119
|
+
```typescript
|
|
120
|
+
{
|
|
121
|
+
// Any props from slotProps.footer
|
|
122
|
+
}
|
|
123
|
+
```
|
|
124
|
+
|
|
125
|
+
**Example:**
|
|
126
|
+
```tsx
|
|
127
|
+
function CustomFooter() {
|
|
128
|
+
return (
|
|
129
|
+
<div style={{ padding: '12px', borderTop: '1px solid #e0e0e0' }}>
|
|
130
|
+
<span>Custom footer content</span>
|
|
131
|
+
</div>
|
|
132
|
+
);
|
|
133
|
+
}
|
|
134
|
+
|
|
135
|
+
<DataGrid
|
|
136
|
+
slots={{ footer: CustomFooter }}
|
|
137
|
+
/>
|
|
138
|
+
```
|
|
139
|
+
|
|
140
|
+
## Complete Example
|
|
141
|
+
|
|
142
|
+
```tsx
|
|
143
|
+
import { Select, Pagination, Spin, Empty } from 'antd';
|
|
144
|
+
import { DataGrid } from '@opencorestack/opengridx';
|
|
145
|
+
|
|
146
|
+
function AntdPagination(props) {
|
|
147
|
+
const { page, pageSize, rowCount, pageSizeOptions, onPageChange, onPageSizeChange } = props;
|
|
148
|
+
|
|
149
|
+
return (
|
|
150
|
+
<div style={{ display: 'flex', gap: '16px', padding: '12px 16px', justifyContent: 'flex-end' }}>
|
|
151
|
+
<Select
|
|
152
|
+
value={pageSize}
|
|
153
|
+
onChange={onPageSizeChange}
|
|
154
|
+
options={pageSizeOptions.map(s => ({ value: s, label: s }))}
|
|
155
|
+
/>
|
|
156
|
+
<Pagination
|
|
157
|
+
current={page + 1}
|
|
158
|
+
total={rowCount}
|
|
159
|
+
pageSize={pageSize}
|
|
160
|
+
onChange={(p) => onPageChange(p - 1)}
|
|
161
|
+
/>
|
|
162
|
+
</div>
|
|
163
|
+
);
|
|
164
|
+
}
|
|
165
|
+
|
|
166
|
+
function AntdNoRows() {
|
|
167
|
+
return <Empty description="No data available" />;
|
|
168
|
+
}
|
|
169
|
+
|
|
170
|
+
function AntdLoader() {
|
|
171
|
+
return (
|
|
172
|
+
<div style={{ padding: '40px', textAlign: 'center' }}>
|
|
173
|
+
<Spin size="large" />
|
|
174
|
+
</div>
|
|
175
|
+
);
|
|
176
|
+
}
|
|
177
|
+
|
|
178
|
+
function MyApp() {
|
|
179
|
+
return (
|
|
180
|
+
<DataGrid
|
|
181
|
+
rows={rows}
|
|
182
|
+
columns={columns}
|
|
183
|
+
pagination
|
|
184
|
+
loading={isLoading}
|
|
185
|
+
slots={{
|
|
186
|
+
pagination: AntdPagination,
|
|
187
|
+
noRowsOverlay: AntdNoRows,
|
|
188
|
+
loadingOverlay: AntdLoader
|
|
189
|
+
}}
|
|
190
|
+
slotProps={{
|
|
191
|
+
pagination: {
|
|
192
|
+
// Additional custom props if needed
|
|
193
|
+
}
|
|
194
|
+
}}
|
|
195
|
+
/>
|
|
196
|
+
);
|
|
197
|
+
}
|
|
198
|
+
```
|
|
199
|
+
|
|
200
|
+
## TypeScript Support
|
|
201
|
+
|
|
202
|
+
For full type safety, define your component props:
|
|
203
|
+
|
|
204
|
+
```typescript
|
|
205
|
+
import type { PaginationProps } from '@opencorestack/opengridx';
|
|
206
|
+
|
|
207
|
+
interface CustomPaginationProps extends PaginationProps {
|
|
208
|
+
customProp?: string;
|
|
209
|
+
}
|
|
210
|
+
|
|
211
|
+
const CustomPagination: React.FC<CustomPaginationProps> = (props) => {
|
|
212
|
+
// Your implementation
|
|
213
|
+
};
|
|
214
|
+
```
|
|
215
|
+
|
|
216
|
+
## Best Practices
|
|
217
|
+
|
|
218
|
+
1. **Maintain Functionality**: Ensure your custom component provides the same core functionality as the default.
|
|
219
|
+
2. **Accessibility**: Include proper ARIA labels and keyboard navigation.
|
|
220
|
+
3. **Responsive Design**: Make sure your component works on different screen sizes.
|
|
221
|
+
4. **Performance**: Avoid expensive operations in render; use memoization where appropriate.
|
|
222
|
+
5. **Consistent Styling**: Match your app's design system while maintaining usability.
|
|
223
|
+
|
|
224
|
+
## See Also
|
|
225
|
+
|
|
226
|
+
- [Custom Pagination Guide](./CUSTOM_PAGINATION.md) - Detailed examples with Ant Design and MUI
|
|
227
|
+
- [DataGrid Props](../src/OpenGridX/types/index.ts) - Full TypeScript definitions
|
|
@@ -0,0 +1,293 @@
|
|
|
1
|
+
# OpenGridX Theming Guide
|
|
2
|
+
|
|
3
|
+
OpenGridX ships with a complete design-token system built on CSS custom properties (`--ogx-*`). You can theme the grid in two ways:
|
|
4
|
+
|
|
5
|
+
1. **`DataGridThemeProvider`** — the recommended React API (maps a typed `GridTheme` object → CSS variables)
|
|
6
|
+
2. **Raw CSS override** — set any `--ogx-*` variable yourself on a wrapper element or `:root`
|
|
7
|
+
|
|
8
|
+
---
|
|
9
|
+
|
|
10
|
+
## Quick Start — `DataGridThemeProvider`
|
|
11
|
+
|
|
12
|
+
```tsx
|
|
13
|
+
import { DataGrid, DataGridThemeProvider } from '@opencorestack/opengridx';
|
|
14
|
+
|
|
15
|
+
const myTheme = {
|
|
16
|
+
colors: {
|
|
17
|
+
primary: '#7c3aed',
|
|
18
|
+
primaryDark: '#5b21b6',
|
|
19
|
+
primaryLight: '#ede9fe',
|
|
20
|
+
},
|
|
21
|
+
grid: {
|
|
22
|
+
background: '#fff',
|
|
23
|
+
headerBackground: '#f5f3ff',
|
|
24
|
+
rowHoverBackground: '#faf5ff',
|
|
25
|
+
rowSelectedBackground: '#ede9fe',
|
|
26
|
+
cellFocusBorder: '#7c3aed',
|
|
27
|
+
},
|
|
28
|
+
};
|
|
29
|
+
|
|
30
|
+
export default function App() {
|
|
31
|
+
return (
|
|
32
|
+
<DataGridThemeProvider theme={myTheme}>
|
|
33
|
+
<DataGrid rows={rows} columns={columns} />
|
|
34
|
+
</DataGridThemeProvider>
|
|
35
|
+
);
|
|
36
|
+
}
|
|
37
|
+
```
|
|
38
|
+
|
|
39
|
+
The `DataGridThemeProvider` resolves each key in the `GridTheme` object to its corresponding `--ogx-*` CSS variable and applies it as an inline style on a wrapper `div`. **No CSS-in-JS, no runtime overhead.**
|
|
40
|
+
|
|
41
|
+
---
|
|
42
|
+
|
|
43
|
+
## Dark Mode
|
|
44
|
+
|
|
45
|
+
The grid automatically switches to its dark palette via `@media (prefers-color-scheme: dark)`. If your app manages dark mode manually (e.g. via a `data-theme` attribute), override the dark tokens with:
|
|
46
|
+
|
|
47
|
+
```css
|
|
48
|
+
[data-theme="dark"] {
|
|
49
|
+
--ogx-grid-background: #0f172a;
|
|
50
|
+
--ogx-grid-header-background: #1e293b;
|
|
51
|
+
--ogx-grid-row-text: #cbd5e1;
|
|
52
|
+
--ogx-grid-border-color: #334155;
|
|
53
|
+
/* … etc */
|
|
54
|
+
}
|
|
55
|
+
```
|
|
56
|
+
|
|
57
|
+
---
|
|
58
|
+
|
|
59
|
+
## `GridTheme` Interface Reference
|
|
60
|
+
|
|
61
|
+
```ts
|
|
62
|
+
interface GridTheme {
|
|
63
|
+
colors?: GridThemeColors;
|
|
64
|
+
typography?: GridThemeTypography;
|
|
65
|
+
spacing?: GridThemeSpacing;
|
|
66
|
+
borders?: GridThemeBorders;
|
|
67
|
+
shadows?: GridThemeShadows;
|
|
68
|
+
grid?: GridThemeGrid;
|
|
69
|
+
toolbar?: GridThemeToolbar;
|
|
70
|
+
overlays?: GridThemeOverlays;
|
|
71
|
+
scrollbar?: GridThemeScrollbar;
|
|
72
|
+
skeleton?: GridThemeSkeleton;
|
|
73
|
+
transitions?: GridThemeTransitions;
|
|
74
|
+
}
|
|
75
|
+
```
|
|
76
|
+
|
|
77
|
+
---
|
|
78
|
+
|
|
79
|
+
## All CSS Tokens
|
|
80
|
+
|
|
81
|
+
### Colors
|
|
82
|
+
|
|
83
|
+
| Token | Default (light) | Dark override | Description |
|
|
84
|
+
|---|---|---|---|
|
|
85
|
+
| `--ogx-color-primary` | `#3b82f6` | `#60a5fa` | Brand / accent color |
|
|
86
|
+
| `--ogx-color-primary-dark` | `#2563eb` | `#3b82f6` | Hover / pressed primary |
|
|
87
|
+
| `--ogx-color-primary-light` | `#eff6ff` | `#1e3a5f` | Tinted backgrounds |
|
|
88
|
+
| `--ogx-color-primary-focus` | `rgba(59,130,246,0.5)` | `rgba(96,165,250,0.4)` | Focus ring color |
|
|
89
|
+
| `--ogx-color-secondary` | `#8b5cf6` | — | Secondary accent |
|
|
90
|
+
| `--ogx-color-secondary-dark` | `#7c3aed` | — | Hover secondary |
|
|
91
|
+
| `--ogx-color-secondary-light` | `#f5f3ff` | — | Tinted secondary backgrounds |
|
|
92
|
+
| `--ogx-color-success` | `#10b981` | — | Positive indicators |
|
|
93
|
+
| `--ogx-color-warning` | `#f59e0b` | — | Warning indicators |
|
|
94
|
+
| `--ogx-color-error` | `#ef4444` | — | Error / destructive |
|
|
95
|
+
| `--ogx-color-info` | `#0ea5e9` | — | Informational |
|
|
96
|
+
| `--ogx-color-white` | `#ffffff` | `#0f172a` | Pure white (inverted in dark) |
|
|
97
|
+
| `--ogx-color-black` | `#0f172a` | `#f8fafc` | Pure black (inverted in dark) |
|
|
98
|
+
| `--ogx-color-gray-50` | `#f8fafc` | `#1e293b` | Lightest gray |
|
|
99
|
+
| `--ogx-color-gray-100` | `#f1f5f9` | `#334155` | |
|
|
100
|
+
| `--ogx-color-gray-200` | `#e2e8f0` | `#475569` | Default borders |
|
|
101
|
+
| `--ogx-color-gray-300` | `#cbd5e1` | `#64748b` | |
|
|
102
|
+
| `--ogx-color-gray-400` | `#94a3b8` | `#94a3b8` | Muted text |
|
|
103
|
+
| `--ogx-color-gray-500` | `#64748b` | `#cbd5e1` | |
|
|
104
|
+
| `--ogx-color-gray-600` | `#475569` | `#e2e8f0` | |
|
|
105
|
+
| `--ogx-color-gray-700` | `#334155` | `#e2e8f0` | Header text default |
|
|
106
|
+
| `--ogx-color-gray-800` | `#1e293b` | `#f1f5f9` | Body text default |
|
|
107
|
+
| `--ogx-color-gray-900` | `#0f172a` | `#f8fafc` | Darkest gray |
|
|
108
|
+
|
|
109
|
+
### Typography
|
|
110
|
+
|
|
111
|
+
| Token | Default | Description |
|
|
112
|
+
|---|---|---|
|
|
113
|
+
| `--ogx-font-family` | `'Inter', system-ui, sans-serif` | Primary UI font |
|
|
114
|
+
| `--ogx-font-family-mono` | `'JetBrains Mono', 'Fira Code', monospace` | Monospace (code cells, IDs) |
|
|
115
|
+
| `--ogx-font-size-xs` | `0.75rem` (12px) | Extra-small |
|
|
116
|
+
| `--ogx-font-size-sm` | `0.875rem` (14px) | Small |
|
|
117
|
+
| `--ogx-font-size-md` | `1rem` (16px) | Medium |
|
|
118
|
+
| `--ogx-font-size-lg` | `1.125rem` (18px) | Large |
|
|
119
|
+
| `--ogx-font-size-xl` | `1.25rem` (20px) | Extra-large |
|
|
120
|
+
| `--ogx-font-weight-light` | `300` | |
|
|
121
|
+
| `--ogx-font-weight-regular` | `400` | |
|
|
122
|
+
| `--ogx-font-weight-medium` | `500` | |
|
|
123
|
+
| `--ogx-font-weight-semibold` | `600` | |
|
|
124
|
+
| `--ogx-font-weight-bold` | `700` | |
|
|
125
|
+
| `--ogx-line-height-tight` | `1.2` | |
|
|
126
|
+
| `--ogx-line-height-normal` | `1.5` | |
|
|
127
|
+
| `--ogx-line-height-relaxed` | `1.75` | |
|
|
128
|
+
|
|
129
|
+
### Spacing
|
|
130
|
+
|
|
131
|
+
| Token | Default | Description |
|
|
132
|
+
|---|---|---|
|
|
133
|
+
| `--ogx-spacing-xs` | `0.25rem` (4px) | |
|
|
134
|
+
| `--ogx-spacing-sm` | `0.5rem` (8px) | |
|
|
135
|
+
| `--ogx-spacing-md` | `1rem` (16px) | |
|
|
136
|
+
| `--ogx-spacing-lg` | `1.5rem` (24px) | |
|
|
137
|
+
| `--ogx-spacing-xl` | `2rem` (32px) | |
|
|
138
|
+
| `--ogx-spacing-xxl` | `3rem` (48px) | |
|
|
139
|
+
|
|
140
|
+
### Borders
|
|
141
|
+
|
|
142
|
+
| Token | Default | Description |
|
|
143
|
+
|---|---|---|
|
|
144
|
+
| `--ogx-border-width-thin` | `1px` | |
|
|
145
|
+
| `--ogx-border-width-medium` | `2px` | |
|
|
146
|
+
| `--ogx-border-width-thick` | `3px` | |
|
|
147
|
+
| `--ogx-border-radius-sm` | `4px` | |
|
|
148
|
+
| `--ogx-border-radius-md` | `8px` | |
|
|
149
|
+
| `--ogx-border-radius-lg` | `12px` | |
|
|
150
|
+
| `--ogx-border-radius-xl` | `16px` | |
|
|
151
|
+
| `--ogx-border-radius-round` | `50%` | Circular |
|
|
152
|
+
| `--ogx-border-color` | `var(--ogx-color-gray-200)` | Default border color |
|
|
153
|
+
| `--ogx-border-color-hover` | `var(--ogx-color-gray-300)` | Border on hover |
|
|
154
|
+
|
|
155
|
+
### Shadows
|
|
156
|
+
|
|
157
|
+
| Token | Default | Description |
|
|
158
|
+
|---|---|---|
|
|
159
|
+
| `--ogx-shadow-sm` | `0 1px 2px rgba(0,0,0,.05)` | Subtle lift |
|
|
160
|
+
| `--ogx-shadow-md` | `0 4px 6px -1px ...` | Card-level |
|
|
161
|
+
| `--ogx-shadow-lg` | `0 10px 15px -3px ...` | Overlay |
|
|
162
|
+
| `--ogx-shadow-xl` | `0 20px 25px -5px ...` | Modal |
|
|
163
|
+
|
|
164
|
+
### Grid Layout
|
|
165
|
+
|
|
166
|
+
| Token | Default | Description |
|
|
167
|
+
|---|---|---|
|
|
168
|
+
| `--ogx-row-height` | `52px` | Default row height |
|
|
169
|
+
| `--ogx-header-height` | `56px` | Column header row height |
|
|
170
|
+
| `--ogx-grid-row-height-compact` | `32px` | Compact density preset |
|
|
171
|
+
| `--ogx-grid-row-height-standard` | `52px` | Standard density preset |
|
|
172
|
+
| `--ogx-grid-row-height-comfortable` | `72px` | Comfortable density preset |
|
|
173
|
+
| `--ogx-grid-header-height` | `56px` | Header height (grid-specific) |
|
|
174
|
+
| `--ogx-grid-cell-padding-x` | `10px` | Horizontal cell padding |
|
|
175
|
+
| `--ogx-grid-cell-padding-y` | `8px` | Vertical cell padding |
|
|
176
|
+
| `--ogx-grid-cell-font-size` | `13px` | Body cell font size |
|
|
177
|
+
| `--ogx-grid-header-font-size` | `13px` | Header cell font size |
|
|
178
|
+
| `--ogx-grid-line-height` | `var(--ogx-line-height-normal)` | Row line height |
|
|
179
|
+
|
|
180
|
+
### Grid Colors
|
|
181
|
+
|
|
182
|
+
| Token | Default (light) | Dark override | Description |
|
|
183
|
+
|---|---|---|---|
|
|
184
|
+
| `--ogx-grid-background` | `#ffffff` | `#0f172a` | Grid body background |
|
|
185
|
+
| `--ogx-grid-border-color` | `#e2e8f0` | `#334155` | Cell border lines |
|
|
186
|
+
| `--ogx-grid-header-background` | `#f8fafc` | `#1e293b` | Header row background |
|
|
187
|
+
| `--ogx-grid-header-text` | `#334155` | `#e2e8f0` | Header label color |
|
|
188
|
+
| `--ogx-grid-header-hover-background` | `#f1f5f9` | `#334155` | Header hover state |
|
|
189
|
+
| `--ogx-grid-header-sorted-background` | `#f8fafc` | `#1e3a5f` | Sorted column header tint |
|
|
190
|
+
| `--ogx-grid-row-text` | `#1e293b` | `#cbd5e1` | Default body cell text |
|
|
191
|
+
| `--ogx-grid-row-hover-background` | `#f8fafc` | `#1e293b` | Row hover highlight |
|
|
192
|
+
| `--ogx-grid-row-alternate-background` | `var(--ogx-grid-background)` | `#162032` | Striped row alternate |
|
|
193
|
+
| `--ogx-grid-row-selected-background` | `#eff6ff` | `#1e3a5f` | Selected row fill |
|
|
194
|
+
| `--ogx-grid-row-selected-hover-background` | `#dbeafe` | `#1d4ed8` | Selected row hover |
|
|
195
|
+
| `--ogx-grid-cell-focus-border` | `#3b82f6` | `#60a5fa` | Keyboard focus ring |
|
|
196
|
+
| `--ogx-grid-pinned-left-shadow` | `4px 0 24px...` | (darker) | Shadow on left-pinned columns |
|
|
197
|
+
| `--ogx-grid-pinned-right-shadow` | `-4px 0 24px...` | (darker) | Shadow on right-pinned columns |
|
|
198
|
+
| `--ogx-checkbox-bg` | — | `#1e293b` | Checkbox background (dark only) |
|
|
199
|
+
| `--ogx-checkbox-border` | — | `#64748b` | Checkbox border (dark only) |
|
|
200
|
+
|
|
201
|
+
### Transitions
|
|
202
|
+
|
|
203
|
+
| Token | Default | Description |
|
|
204
|
+
|---|---|---|
|
|
205
|
+
| `--ogx-transition-duration-fast` | `150ms` | Quick micro-interactions |
|
|
206
|
+
| `--ogx-transition-duration-normal` | `250ms` | Standard UI transitions |
|
|
207
|
+
| `--ogx-transition-duration-slow` | `350ms` | Deliberate animations |
|
|
208
|
+
| `--ogx-transition-easing` | `cubic-bezier(0.4,0,0.2,1)` | Material easing curve |
|
|
209
|
+
|
|
210
|
+
### Z-index Scale
|
|
211
|
+
|
|
212
|
+
| Token | Default | Use |
|
|
213
|
+
|---|---|---|
|
|
214
|
+
| `--ogx-z-index-base` | `0` | |
|
|
215
|
+
| `--ogx-z-index-sticky` | `1020` | Sticky/pinned columns |
|
|
216
|
+
| `--ogx-z-index-fixed` | `1030` | Fixed elements |
|
|
217
|
+
| `--ogx-z-index-dropdown` | `1000` | Inline dropdowns |
|
|
218
|
+
| `--ogx-z-index-modal-backdrop` | `1040` | |
|
|
219
|
+
| `--ogx-z-index-modal` | `1050` | |
|
|
220
|
+
| `--ogx-z-index-popover` | `1060` | Column menus |
|
|
221
|
+
| `--ogx-z-index-tooltip` | `1070` | Tooltips |
|
|
222
|
+
|
|
223
|
+
---
|
|
224
|
+
|
|
225
|
+
## CSS-Only Override (no React)
|
|
226
|
+
|
|
227
|
+
You can theme the grid without the `DataGridThemeProvider` by overriding variables on any ancestor element:
|
|
228
|
+
|
|
229
|
+
```css
|
|
230
|
+
/* App-level override */
|
|
231
|
+
.my-grid-container {
|
|
232
|
+
--ogx-color-primary: #059669;
|
|
233
|
+
--ogx-color-primary-light: #d1fae5;
|
|
234
|
+
--ogx-grid-header-background: #f0fdf4;
|
|
235
|
+
--ogx-grid-row-selected-background: #d1fae5;
|
|
236
|
+
--ogx-grid-cell-focus-border: #059669;
|
|
237
|
+
}
|
|
238
|
+
```
|
|
239
|
+
|
|
240
|
+
```tsx
|
|
241
|
+
<div className="my-grid-container">
|
|
242
|
+
<DataGrid rows={rows} columns={columns} />
|
|
243
|
+
</div>
|
|
244
|
+
```
|
|
245
|
+
|
|
246
|
+
---
|
|
247
|
+
|
|
248
|
+
## Built-in Presets
|
|
249
|
+
|
|
250
|
+
OpenGridX ships with two presets accessible from `'opengridx'`:
|
|
251
|
+
|
|
252
|
+
```tsx
|
|
253
|
+
import { DataGridThemeProvider, themes } from '@opencorestack/opengridx';
|
|
254
|
+
|
|
255
|
+
// Available: themes.light, themes.dark, themes.compact, themes.comfortable
|
|
256
|
+
<DataGridThemeProvider theme={themes.dark}>
|
|
257
|
+
<DataGrid ... />
|
|
258
|
+
</DataGridThemeProvider>
|
|
259
|
+
```
|
|
260
|
+
|
|
261
|
+
---
|
|
262
|
+
|
|
263
|
+
## Example: Custom Purple Theme
|
|
264
|
+
|
|
265
|
+
```tsx
|
|
266
|
+
const purpleTheme: GridTheme = {
|
|
267
|
+
colors: {
|
|
268
|
+
primary: '#7c3aed',
|
|
269
|
+
primaryDark: '#5b21b6',
|
|
270
|
+
primaryLight: '#ede9fe',
|
|
271
|
+
primaryFocus: 'rgba(124,58,237,0.4)',
|
|
272
|
+
},
|
|
273
|
+
grid: {
|
|
274
|
+
headerBackground: '#f5f3ff',
|
|
275
|
+
headerText: '#4c1d95',
|
|
276
|
+
headerHoverBackground: '#ede9fe',
|
|
277
|
+
headerSortedBackground: '#ddd6fe',
|
|
278
|
+
rowSelectedBackground: '#ede9fe',
|
|
279
|
+
rowSelectedHoverBackground: '#ddd6fe',
|
|
280
|
+
cellFocusBorder: '#7c3aed',
|
|
281
|
+
},
|
|
282
|
+
};
|
|
283
|
+
```
|
|
284
|
+
|
|
285
|
+
---
|
|
286
|
+
|
|
287
|
+
## CSS Architecture Notes
|
|
288
|
+
|
|
289
|
+
- All tokens are defined in `lib/styles/base/variables.css`
|
|
290
|
+
- The dark mode overrides are in the same file under `@media (prefers-color-scheme: dark)`
|
|
291
|
+
- The CSS entry point for the entire library is `lib/styles/opengridx.css` (single barrel import)
|
|
292
|
+
- BEM class prefix: `ogx__` (e.g. `ogx__cell`, `ogx__header-cell`)
|
|
293
|
+
- Variable prefix: `--ogx-` (e.g. `--ogx-color-primary`)
|
|
@@ -0,0 +1,79 @@
|
|
|
1
|
+
# 📊 Aggregation & Pivot Mode
|
|
2
|
+
|
|
3
|
+
Transform raw data into meaningful insights with advanced grouping and summary features.
|
|
4
|
+
|
|
5
|
+
---
|
|
6
|
+
|
|
7
|
+
## 📈 Row Aggregation
|
|
8
|
+
|
|
9
|
+
Aggregation allows you to calculate summary values (Sum, Avg, etc.) for groups or the entire dataset.
|
|
10
|
+
|
|
11
|
+
### Usage
|
|
12
|
+
```tsx
|
|
13
|
+
<DataGrid
|
|
14
|
+
rows={rows}
|
|
15
|
+
columns={columns}
|
|
16
|
+
aggregationModel={{
|
|
17
|
+
salary: 'sum',
|
|
18
|
+
age: 'avg',
|
|
19
|
+
department: 'count'
|
|
20
|
+
}}
|
|
21
|
+
/>
|
|
22
|
+
```
|
|
23
|
+
|
|
24
|
+
### Configuration
|
|
25
|
+
You can control where the aggregation results appear:
|
|
26
|
+
- **`footer`**: A sticky row at the bottom of the grid.
|
|
27
|
+
- **`inline`**: Values displayed within group headers (when Row Grouping is active).
|
|
28
|
+
- **`both`**: Display in both locations.
|
|
29
|
+
|
|
30
|
+
```tsx
|
|
31
|
+
<DataGrid
|
|
32
|
+
aggregationModel={model}
|
|
33
|
+
getAggregationPosition={(groupNode) => 'both'}
|
|
34
|
+
/>
|
|
35
|
+
```
|
|
36
|
+
|
|
37
|
+
---
|
|
38
|
+
|
|
39
|
+
## 🔄 Pivot Mode
|
|
40
|
+
|
|
41
|
+
Pivot mode rotates your data, turning row values into dynamically generated columns.
|
|
42
|
+
|
|
43
|
+
### Defining a Pivot
|
|
44
|
+
```tsx
|
|
45
|
+
const pivotModel: GridPivotModel = {
|
|
46
|
+
rowFields: ['office'], // Dimensions on the Left
|
|
47
|
+
columnFields: ['year'], // Dimensions on the Top
|
|
48
|
+
valueFields: [ // Values to compute
|
|
49
|
+
{ field: 'revenue', aggFn: 'sum', headerName: 'Total Revenue' }
|
|
50
|
+
]
|
|
51
|
+
};
|
|
52
|
+
|
|
53
|
+
<DataGrid
|
|
54
|
+
pivotMode={true}
|
|
55
|
+
pivotModel={pivotModel}
|
|
56
|
+
/>
|
|
57
|
+
```
|
|
58
|
+
|
|
59
|
+
### Key Concepts
|
|
60
|
+
- **Row Fields**: These become the static vertical axis of your pivot table.
|
|
61
|
+
- **Column Fields**: Unique values in these fields become new columns.
|
|
62
|
+
- **Value Fields**: The data that gets summarized at the intersection of row and column fields.
|
|
63
|
+
|
|
64
|
+
---
|
|
65
|
+
|
|
66
|
+
## ⚙️ Aggregation Functions
|
|
67
|
+
|
|
68
|
+
Built-in functions available:
|
|
69
|
+
- `sum`: Total of numeric values.
|
|
70
|
+
- `avg`: Arithmetic mean.
|
|
71
|
+
- `min`: Smallest value.
|
|
72
|
+
- `max`: Largest value.
|
|
73
|
+
- `count`: Number of items.
|
|
74
|
+
- `unique`: Number of unique items.
|
|
75
|
+
|
|
76
|
+
---
|
|
77
|
+
|
|
78
|
+
## 🎨 Formatting Totals
|
|
79
|
+
Aggregation results automatically inherit the `valueFormatter` from their respective column definitions. If you need a specific format for aggregates only, use the `formatAggregationValue` utility.
|