@alaarab/ogrid-mcp 2.4.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +68 -0
- package/bundled-docs/api/README.md +94 -0
- package/bundled-docs/api/column-def.mdx +379 -0
- package/bundled-docs/api/components-column-chooser.mdx +310 -0
- package/bundled-docs/api/components-column-header-filter.mdx +363 -0
- package/bundled-docs/api/components-datagrid-table.mdx +316 -0
- package/bundled-docs/api/components-pagination-controls.mdx +344 -0
- package/bundled-docs/api/components-sidebar.mdx +427 -0
- package/bundled-docs/api/components-status-bar.mdx +309 -0
- package/bundled-docs/api/grid-api.mdx +299 -0
- package/bundled-docs/api/js-api.mdx +198 -0
- package/bundled-docs/api/ogrid-props.mdx +244 -0
- package/bundled-docs/api/types.mdx +640 -0
- package/bundled-docs/features/cell-references.mdx +225 -0
- package/bundled-docs/features/column-chooser.mdx +279 -0
- package/bundled-docs/features/column-groups.mdx +290 -0
- package/bundled-docs/features/column-pinning.mdx +282 -0
- package/bundled-docs/features/column-reordering.mdx +359 -0
- package/bundled-docs/features/column-types.mdx +181 -0
- package/bundled-docs/features/context-menu.mdx +216 -0
- package/bundled-docs/features/csv-export.mdx +227 -0
- package/bundled-docs/features/editing.mdx +377 -0
- package/bundled-docs/features/filtering.mdx +330 -0
- package/bundled-docs/features/formulas.mdx +381 -0
- package/bundled-docs/features/grid-api.mdx +311 -0
- package/bundled-docs/features/keyboard-navigation.mdx +236 -0
- package/bundled-docs/features/pagination.mdx +245 -0
- package/bundled-docs/features/performance.mdx +433 -0
- package/bundled-docs/features/row-selection.mdx +256 -0
- package/bundled-docs/features/server-side-data.mdx +291 -0
- package/bundled-docs/features/sidebar.mdx +234 -0
- package/bundled-docs/features/sorting.mdx +241 -0
- package/bundled-docs/features/spreadsheet-selection.mdx +201 -0
- package/bundled-docs/features/status-bar.mdx +205 -0
- package/bundled-docs/features/toolbar.mdx +284 -0
- package/bundled-docs/features/virtual-scrolling.mdx +624 -0
- package/bundled-docs/getting-started/installation.mdx +216 -0
- package/bundled-docs/getting-started/overview.mdx +151 -0
- package/bundled-docs/getting-started/quick-start.mdx +425 -0
- package/bundled-docs/getting-started/vanilla-js.mdx +191 -0
- package/bundled-docs/guides/accessibility.mdx +550 -0
- package/bundled-docs/guides/controlled-vs-uncontrolled.mdx +153 -0
- package/bundled-docs/guides/custom-cell-editors.mdx +201 -0
- package/bundled-docs/guides/framework-showcase.mdx +200 -0
- package/bundled-docs/guides/mcp-live-testing.mdx +291 -0
- package/bundled-docs/guides/mcp.mdx +172 -0
- package/bundled-docs/guides/migration-from-ag-grid.mdx +223 -0
- package/bundled-docs/guides/theming.mdx +211 -0
- package/dist/esm/bridge-client.d.ts +87 -0
- package/dist/esm/bridge-client.js +162 -0
- package/dist/esm/index.js +1060 -0
- package/package.json +43 -0
|
@@ -0,0 +1,172 @@
|
|
|
1
|
+
---
|
|
2
|
+
title: AI Integration (MCP)
|
|
3
|
+
description: Connect Claude, Cursor, and other AI assistants to OGrid documentation and your running grid.
|
|
4
|
+
sidebar_position: 1
|
|
5
|
+
---
|
|
6
|
+
|
|
7
|
+
# AI Integration (MCP)
|
|
8
|
+
|
|
9
|
+
`@alaarab/ogrid-mcp` is a standalone [Model Context Protocol (MCP)](https://modelcontextprotocol.io) server that gives AI assistants full access to OGrid documentation across all frameworks. It also includes a **live testing bridge** that lets the AI read and control a running OGrid instance in real time.
|
|
10
|
+
|
|
11
|
+
## Installation
|
|
12
|
+
|
|
13
|
+
The MCP server is published as `@alaarab/ogrid-mcp` and requires no configuration — docs are bundled into the package.
|
|
14
|
+
|
|
15
|
+
```bash
|
|
16
|
+
npm install -g @alaarab/ogrid-mcp
|
|
17
|
+
# or use npx directly (no install needed)
|
|
18
|
+
npx @alaarab/ogrid-mcp
|
|
19
|
+
```
|
|
20
|
+
|
|
21
|
+
---
|
|
22
|
+
|
|
23
|
+
## Connect to your AI assistant
|
|
24
|
+
|
|
25
|
+
### Claude Code
|
|
26
|
+
|
|
27
|
+
```bash
|
|
28
|
+
claude mcp add ogrid -- npx -y @alaarab/ogrid-mcp
|
|
29
|
+
```
|
|
30
|
+
|
|
31
|
+
### Claude Desktop
|
|
32
|
+
|
|
33
|
+
Add to your `claude_desktop_config.json`:
|
|
34
|
+
|
|
35
|
+
```json
|
|
36
|
+
{
|
|
37
|
+
"mcpServers": {
|
|
38
|
+
"ogrid": {
|
|
39
|
+
"command": "npx",
|
|
40
|
+
"args": ["-y", "@alaarab/ogrid-mcp"]
|
|
41
|
+
}
|
|
42
|
+
}
|
|
43
|
+
}
|
|
44
|
+
```
|
|
45
|
+
|
|
46
|
+
### Cursor
|
|
47
|
+
|
|
48
|
+
Add to your Cursor MCP settings:
|
|
49
|
+
|
|
50
|
+
```json
|
|
51
|
+
{
|
|
52
|
+
"ogrid": {
|
|
53
|
+
"command": "npx",
|
|
54
|
+
"args": ["-y", "@alaarab/ogrid-mcp"]
|
|
55
|
+
}
|
|
56
|
+
}
|
|
57
|
+
```
|
|
58
|
+
|
|
59
|
+
---
|
|
60
|
+
|
|
61
|
+
## What your AI can do
|
|
62
|
+
|
|
63
|
+
Once connected, the AI assistant has access to the full OGrid documentation for all frameworks. Example prompts:
|
|
64
|
+
|
|
65
|
+
```
|
|
66
|
+
Show me how to set up server-side pagination in React
|
|
67
|
+
How do I pin columns in Angular Material?
|
|
68
|
+
What's the difference between multiSelect and text filters?
|
|
69
|
+
How do I use the formula engine?
|
|
70
|
+
Help me migrate from AG Grid to OGrid
|
|
71
|
+
```
|
|
72
|
+
|
|
73
|
+
---
|
|
74
|
+
|
|
75
|
+
## MCP tools
|
|
76
|
+
|
|
77
|
+
### `search_docs`
|
|
78
|
+
|
|
79
|
+
Full-text search across all OGrid documentation.
|
|
80
|
+
|
|
81
|
+
```
|
|
82
|
+
search_docs query="server-side data" framework="react"
|
|
83
|
+
```
|
|
84
|
+
|
|
85
|
+
Parameters:
|
|
86
|
+
- `query` (required) — search terms
|
|
87
|
+
- `framework` (optional) — filter to `react`, `angular`, `vue`, or `js`
|
|
88
|
+
- `category` (optional) — filter to `features`, `getting-started`, `guides`, or `api`
|
|
89
|
+
|
|
90
|
+
### `list_docs`
|
|
91
|
+
|
|
92
|
+
Browse available documentation pages by category.
|
|
93
|
+
|
|
94
|
+
```
|
|
95
|
+
list_docs category="features"
|
|
96
|
+
```
|
|
97
|
+
|
|
98
|
+
### `get_docs`
|
|
99
|
+
|
|
100
|
+
Read a full documentation page by path.
|
|
101
|
+
|
|
102
|
+
```
|
|
103
|
+
get_docs path="features/filtering"
|
|
104
|
+
```
|
|
105
|
+
|
|
106
|
+
### `get_code_example`
|
|
107
|
+
|
|
108
|
+
Extract code snippets from a documentation page, optionally filtered by framework.
|
|
109
|
+
|
|
110
|
+
```
|
|
111
|
+
get_code_example path="features/editing" framework="angular"
|
|
112
|
+
```
|
|
113
|
+
|
|
114
|
+
### `detect_version`
|
|
115
|
+
|
|
116
|
+
Detect which OGrid packages are installed in the user's project by reading their `package.json`.
|
|
117
|
+
|
|
118
|
+
```
|
|
119
|
+
detect_version path="/path/to/project"
|
|
120
|
+
```
|
|
121
|
+
|
|
122
|
+
---
|
|
123
|
+
|
|
124
|
+
## MCP resources
|
|
125
|
+
|
|
126
|
+
Resources can be read directly by the AI assistant without calling a tool.
|
|
127
|
+
|
|
128
|
+
| Resource | Description |
|
|
129
|
+
|----------|-------------|
|
|
130
|
+
| `ogrid://quick-reference` | Key API overview — props, column definitions, IOGridApi, filter types |
|
|
131
|
+
| `ogrid://docs/{path}` | Any documentation page by path (e.g. `ogrid://docs/features/filtering`) |
|
|
132
|
+
| `ogrid://migration-guide` | Step-by-step guide for migrating from AG Grid to OGrid |
|
|
133
|
+
|
|
134
|
+
---
|
|
135
|
+
|
|
136
|
+
## MCP prompts
|
|
137
|
+
|
|
138
|
+
### `migrate-from-ag-grid`
|
|
139
|
+
|
|
140
|
+
Guides the AI through an AG Grid → OGrid migration. Provide your existing AG Grid code and the AI will produce equivalent OGrid code with explanations.
|
|
141
|
+
|
|
142
|
+
---
|
|
143
|
+
|
|
144
|
+
## Live testing bridge
|
|
145
|
+
|
|
146
|
+
For real-time AI-assisted development, the MCP server includes a bridge that connects to a running OGrid instance. This lets the AI:
|
|
147
|
+
|
|
148
|
+
- Read the current grid state (rows, columns, pagination, filters, sort)
|
|
149
|
+
- Update cell values
|
|
150
|
+
- Apply or clear filters
|
|
151
|
+
- Change sort order
|
|
152
|
+
- Navigate pages
|
|
153
|
+
|
|
154
|
+
See the **[MCP Live Testing Bridge](./mcp-live-testing)** guide for full setup instructions.
|
|
155
|
+
|
|
156
|
+
```bash
|
|
157
|
+
# Start with bridge enabled
|
|
158
|
+
npx @alaarab/ogrid-mcp --bridge
|
|
159
|
+
|
|
160
|
+
# Or with a custom port
|
|
161
|
+
OGRID_BRIDGE_PORT=7890 npx @alaarab/ogrid-mcp
|
|
162
|
+
```
|
|
163
|
+
|
|
164
|
+
---
|
|
165
|
+
|
|
166
|
+
## Version
|
|
167
|
+
|
|
168
|
+
The MCP server is published separately from the grid packages and versioned independently. Check the installed version:
|
|
169
|
+
|
|
170
|
+
```bash
|
|
171
|
+
npx @alaarab/ogrid-mcp --version
|
|
172
|
+
```
|
|
@@ -0,0 +1,223 @@
|
|
|
1
|
+
---
|
|
2
|
+
sidebar_position: 4
|
|
3
|
+
title: Migration from AG Grid
|
|
4
|
+
description: Side-by-side mapping from AG Grid to OGrid with equivalent APIs, props, and features.
|
|
5
|
+
---
|
|
6
|
+
|
|
7
|
+
# Migration from AG Grid
|
|
8
|
+
|
|
9
|
+
AG Grid is the industry standard for React data grids -- but its most useful features (range selection, clipboard, context menu, fill handle, status bar) are locked behind a $999/developer/year enterprise license. OGrid delivers all of these features under the MIT license, with zero cost, a smaller bundle, and a more React-idiomatic API.
|
|
10
|
+
|
|
11
|
+
This guide maps every major AG Grid concept to its OGrid equivalent, so you can migrate systematically.
|
|
12
|
+
|
|
13
|
+
## Installation
|
|
14
|
+
|
|
15
|
+
```bash
|
|
16
|
+
# Remove AG Grid
|
|
17
|
+
npm uninstall ag-grid-react ag-grid-community ag-grid-enterprise
|
|
18
|
+
|
|
19
|
+
# Install OGrid (pick your UI framework)
|
|
20
|
+
npm install @alaarab/ogrid-react-radix # Radix (lightweight, no framework dep)
|
|
21
|
+
npm install @alaarab/ogrid-react-fluent # Fluent UI v9
|
|
22
|
+
npm install @alaarab/ogrid-react-material # Material UI v7
|
|
23
|
+
```
|
|
24
|
+
|
|
25
|
+
## Component Mapping
|
|
26
|
+
|
|
27
|
+
AG Grid uses a single `<AgGridReact>` component. OGrid uses `<OGrid>` with the same pattern:
|
|
28
|
+
|
|
29
|
+
```tsx
|
|
30
|
+
// AG Grid
|
|
31
|
+
|
|
32
|
+
<AgGridReact
|
|
33
|
+
columnDefs={columnDefs}
|
|
34
|
+
rowData={rowData}
|
|
35
|
+
getRowId={(params) => params.data.id}
|
|
36
|
+
/>
|
|
37
|
+
|
|
38
|
+
// OGrid
|
|
39
|
+
|
|
40
|
+
<OGrid
|
|
41
|
+
columns={columns}
|
|
42
|
+
data={data}
|
|
43
|
+
getRowId={(item) => item.id}
|
|
44
|
+
/>
|
|
45
|
+
```
|
|
46
|
+
|
|
47
|
+
## Column Definition Mapping
|
|
48
|
+
|
|
49
|
+
| AG Grid (`colDef`) | OGrid (`IColumnDef`) | Notes |
|
|
50
|
+
|---|---|---|
|
|
51
|
+
| `field` | `columnId` | OGrid uses `columnId` as both the field key and unique identifier |
|
|
52
|
+
| `headerName` | `name` | Display name in the column header |
|
|
53
|
+
| `sortable: true` | `sortable: true` | Identical |
|
|
54
|
+
| `filter: true` | `filterable: { type: 'text' }` | OGrid uses a typed filter config object |
|
|
55
|
+
| `filter: 'agSetColumnFilter'` | `filterable: { type: 'multiSelect' }` | Multi-select filter with checkboxes |
|
|
56
|
+
| `cellRenderer` | `renderCell` | `(item) => ReactNode` instead of `(params) => ReactNode` |
|
|
57
|
+
| `valueGetter` | `valueGetter` | `(item) => unknown` instead of `(params) => unknown` |
|
|
58
|
+
| `valueFormatter` | `valueFormatter` | `(value, item) => string` instead of `(params) => string` |
|
|
59
|
+
| `editable: true` | `editable: true` | Also supports `(item) => boolean` for per-row |
|
|
60
|
+
| `cellEditor: 'agSelectCellEditor'` | `cellEditor: 'select'` | Built-in select editor |
|
|
61
|
+
| `cellEditor: 'agRichSelectCellEditor'` | `cellEditor: 'richSelect'` | Searchable dropdown |
|
|
62
|
+
| `cellEditorParams` | `cellEditorParams` | Same concept -- `{ values: [...] }` |
|
|
63
|
+
| `cellEditorPopup: true` | `cellEditorPopup: true` | Identical |
|
|
64
|
+
| `pinned: 'left'` | `pinned: 'left'` | Also supports `'right'` |
|
|
65
|
+
| `width` | `defaultWidth` | Initial column width |
|
|
66
|
+
| `minWidth` | `minWidth` | Minimum column width |
|
|
67
|
+
| `hide: true` | `defaultVisible: false` | Column hidden by default |
|
|
68
|
+
| `cellStyle` | `cellStyle` | Static object or `(item) => CSSProperties` |
|
|
69
|
+
|
|
70
|
+
### Column Definition Example
|
|
71
|
+
|
|
72
|
+
```tsx
|
|
73
|
+
// AG Grid
|
|
74
|
+
const columnDefs = [
|
|
75
|
+
{ field: 'name', headerName: 'Name', sortable: true, filter: true },
|
|
76
|
+
{ field: 'status', headerName: 'Status', filter: 'agSetColumnFilter',
|
|
77
|
+
cellEditor: 'agSelectCellEditor', editable: true,
|
|
78
|
+
cellEditorParams: { values: ['Active', 'Inactive'] } },
|
|
79
|
+
{ field: 'amount', headerName: 'Amount', valueFormatter: (p) => `$${p.value}` },
|
|
80
|
+
];
|
|
81
|
+
|
|
82
|
+
// OGrid
|
|
83
|
+
const columns = [
|
|
84
|
+
{ columnId: 'name', name: 'Name', sortable: true, filterable: { type: 'text' } },
|
|
85
|
+
{ columnId: 'status', name: 'Status', filterable: { type: 'multiSelect' },
|
|
86
|
+
cellEditor: 'select', editable: true,
|
|
87
|
+
cellEditorParams: { values: ['Active', 'Inactive'] } },
|
|
88
|
+
{ columnId: 'amount', name: 'Amount', type: 'numeric',
|
|
89
|
+
valueFormatter: (value) => `$${value}` },
|
|
90
|
+
];
|
|
91
|
+
```
|
|
92
|
+
|
|
93
|
+
## Grid Options Mapping
|
|
94
|
+
|
|
95
|
+
| AG Grid (`gridOptions`) | OGrid (`IOGridProps`) | Notes |
|
|
96
|
+
|---|---|---|
|
|
97
|
+
| `pagination: true` | Built-in, always available | Pagination is always included |
|
|
98
|
+
| `paginationPageSize: 25` | `defaultPageSize={25}` | Or controlled: `pageSize` + `onPageSizeChange` |
|
|
99
|
+
| `rowSelection: 'multiple'` | `rowSelection="multiple"` | Also `'single'` or `'none'` |
|
|
100
|
+
| `suppressRowClickSelection` | -- | OGrid uses checkbox column for selection |
|
|
101
|
+
| `rowData` | `data` | Client-side data array |
|
|
102
|
+
| `datasource` / `serverSideDatasource` | `dataSource` | `IDataSource<T>` with `fetchPage()` |
|
|
103
|
+
| `onSortChanged` | `onSortChange` | Controlled sort callback |
|
|
104
|
+
| `onFilterChanged` | `onFiltersChange` | Controlled filter callback |
|
|
105
|
+
| `onCellValueChanged` | `onCellValueChanged` | Same concept, different event shape |
|
|
106
|
+
| `defaultColDef.editable` | `editable` | Grid-level toggle |
|
|
107
|
+
| `statusBar` | `statusBar` | `true` or `IStatusBarProps` |
|
|
108
|
+
| `sideBar` | `sideBar` | `true` or `ISideBarDef` |
|
|
109
|
+
| `domLayout: 'autoHeight'` | `layoutMode="content"` | Grid sizes to content |
|
|
110
|
+
|
|
111
|
+
## API Mapping
|
|
112
|
+
|
|
113
|
+
AG Grid exposes an imperative API via `gridApi`. OGrid uses a ref:
|
|
114
|
+
|
|
115
|
+
```tsx
|
|
116
|
+
// AG Grid
|
|
117
|
+
const gridRef = useRef();
|
|
118
|
+
gridRef.current.api.setRowData(newData);
|
|
119
|
+
gridRef.current.api.getSelectedRows();
|
|
120
|
+
gridRef.current.api.exportDataAsCsv();
|
|
121
|
+
|
|
122
|
+
// OGrid
|
|
123
|
+
|
|
124
|
+
const gridRef = useRef<IOGridApi<MyRow>>(null);
|
|
125
|
+
gridRef.current?.setRowData(newData);
|
|
126
|
+
gridRef.current?.getSelectedRows();
|
|
127
|
+
exportToCsv(items, columns); // standalone utility function
|
|
128
|
+
```
|
|
129
|
+
|
|
130
|
+
| AG Grid API | OGrid API | Notes |
|
|
131
|
+
|---|---|---|
|
|
132
|
+
| `api.setRowData(data)` | `gridRef.current.setRowData(data)` | Client-side only |
|
|
133
|
+
| `api.getSelectedRows()` | `gridRef.current.getSelectedRows()` | Returns `RowId[]` |
|
|
134
|
+
| `api.selectAll()` | `gridRef.current.selectAll()` | Select all rows |
|
|
135
|
+
| `api.deselectAll()` | `gridRef.current.deselectAll()` | Deselect all rows |
|
|
136
|
+
| `api.setFilterModel(model)` | `gridRef.current.setFilterModel(filters)` | Uses `IFilters` type |
|
|
137
|
+
| `api.exportDataAsCsv()` | `exportToCsv(items, columns)` | Standalone utility, not on ref |
|
|
138
|
+
| `api.getColumnState()` | `gridRef.current.getColumnState()` | Returns `IGridColumnState` |
|
|
139
|
+
| `api.applyColumnState(state)` | `gridRef.current.applyColumnState(state)` | Bulk restore |
|
|
140
|
+
| `api.setLoading(true)` | `gridRef.current.setLoading(true)` | Show loading overlay |
|
|
141
|
+
|
|
142
|
+
## Enterprise Features -- Now Free
|
|
143
|
+
|
|
144
|
+
These features require an AG Grid Enterprise license ($999/dev/year). In OGrid, they are all included for free under the MIT license.
|
|
145
|
+
|
|
146
|
+
| Feature | AG Grid | OGrid |
|
|
147
|
+
|---------|---------|-------|
|
|
148
|
+
| Cell Range Selection | Enterprise | `cellSelection` (default `true`) |
|
|
149
|
+
| Clipboard (Copy/Paste) | Enterprise | Built-in (Ctrl+C / Ctrl+V) |
|
|
150
|
+
| Fill Handle | Enterprise | Built-in (drag corner of selection) |
|
|
151
|
+
| Context Menu | Enterprise | Built-in (right-click any cell) |
|
|
152
|
+
| Status Bar | Enterprise | `statusBar={true}` |
|
|
153
|
+
| Column State Persistence | Enterprise | `getColumnState()` / `applyColumnState()` |
|
|
154
|
+
| Undo/Redo | Enterprise | Built-in (Ctrl+Z / Ctrl+Y) |
|
|
155
|
+
| Rich Select Editor | Enterprise | `cellEditor: 'richSelect'` |
|
|
156
|
+
|
|
157
|
+
## Server-Side Data Source
|
|
158
|
+
|
|
159
|
+
```tsx
|
|
160
|
+
// AG Grid (server-side row model)
|
|
161
|
+
const datasource = {
|
|
162
|
+
getRows: (params) => {
|
|
163
|
+
fetch(`/api/data?start=${params.request.startRow}`)
|
|
164
|
+
.then(res => res.json())
|
|
165
|
+
.then(data => params.success({ rowData: data.rows, rowCount: data.total }));
|
|
166
|
+
}
|
|
167
|
+
};
|
|
168
|
+
|
|
169
|
+
// OGrid
|
|
170
|
+
const dataSource: IDataSource<MyRow> = {
|
|
171
|
+
fetchPage: async ({ page, pageSize, sort, filters }) => {
|
|
172
|
+
const res = await fetch(
|
|
173
|
+
`/api/data?page=${page}&size=${pageSize}&sort=${sort?.field}&dir=${sort?.direction}`
|
|
174
|
+
);
|
|
175
|
+
const json = await res.json();
|
|
176
|
+
return { items: json.rows, totalCount: json.total };
|
|
177
|
+
},
|
|
178
|
+
};
|
|
179
|
+
|
|
180
|
+
<OGrid columns={columns} dataSource={dataSource} getRowId={(item) => item.id} />
|
|
181
|
+
```
|
|
182
|
+
|
|
183
|
+
## Column Groups
|
|
184
|
+
|
|
185
|
+
```tsx
|
|
186
|
+
// AG Grid
|
|
187
|
+
const columnDefs = [
|
|
188
|
+
{
|
|
189
|
+
headerName: 'Contact Info',
|
|
190
|
+
children: [
|
|
191
|
+
{ field: 'email', headerName: 'Email' },
|
|
192
|
+
{ field: 'phone', headerName: 'Phone' },
|
|
193
|
+
],
|
|
194
|
+
},
|
|
195
|
+
];
|
|
196
|
+
|
|
197
|
+
// OGrid
|
|
198
|
+
const columns = [
|
|
199
|
+
{
|
|
200
|
+
headerName: 'Contact Info',
|
|
201
|
+
children: [
|
|
202
|
+
{ columnId: 'email', name: 'Email' },
|
|
203
|
+
{ columnId: 'phone', name: 'Phone' },
|
|
204
|
+
],
|
|
205
|
+
},
|
|
206
|
+
];
|
|
207
|
+
```
|
|
208
|
+
|
|
209
|
+
Column groups in OGrid render as multi-row headers, exactly like AG Grid.
|
|
210
|
+
|
|
211
|
+
## Step-by-Step Migration
|
|
212
|
+
|
|
213
|
+
1. **Install OGrid** and remove AG Grid packages.
|
|
214
|
+
2. **Rename column definitions:** `field` to `columnId`, `headerName` to `name`, `cellRenderer` to `renderCell`, `filter: true` to `filterable: { type: 'text' }`.
|
|
215
|
+
3. **Replace `<AgGridReact>`** with `<OGrid>`. Rename `rowData` to `data`, `columnDefs` to `columns`.
|
|
216
|
+
4. **Update API usage:** Replace `gridRef.current.api.*` with `gridRef.current.*`. Move `exportDataAsCsv` to the standalone `exportToCsv` function.
|
|
217
|
+
5. **Remove Enterprise license.** Delete AG Grid license keys and `LicenseManager.setLicenseKey()` calls.
|
|
218
|
+
6. **Remove AG Grid CSS imports.** OGrid handles its own styling through your UI framework's theme.
|
|
219
|
+
7. **Test.** OGrid's API is intentionally similar to AG Grid's, so most migrations are mechanical find-and-replace operations.
|
|
220
|
+
|
|
221
|
+
:::tip
|
|
222
|
+
OGrid works with the same React patterns as AG Grid (controlled/uncontrolled state, refs for imperative API, column definitions as plain objects). The migration is primarily a prop rename exercise, not an architecture change.
|
|
223
|
+
:::
|
|
@@ -0,0 +1,211 @@
|
|
|
1
|
+
---
|
|
2
|
+
sidebar_position: 3
|
|
3
|
+
title: Theming & CSS Variables
|
|
4
|
+
description: Customize OGrid's appearance with CSS variables, framework themes, and per-cell styles.
|
|
5
|
+
---
|
|
6
|
+
|
|
7
|
+
# Theming & CSS Variables
|
|
8
|
+
|
|
9
|
+
OGrid is designed to inherit your application's design system. Each UI package integrates with its framework's theming mechanism, and the core grid exposes CSS variables and props for fine-grained control.
|
|
10
|
+
|
|
11
|
+
## CSS Variables
|
|
12
|
+
|
|
13
|
+
OGrid exposes CSS custom properties that you can override to change the grid's appearance globally or per-instance.
|
|
14
|
+
|
|
15
|
+
| Variable | Default | Description |
|
|
16
|
+
|----------|---------|-------------|
|
|
17
|
+
| `--ogrid-selection` | `#217346` | Cell selection highlight color (active cell border, range background) |
|
|
18
|
+
|
|
19
|
+
Override globally:
|
|
20
|
+
|
|
21
|
+
```css
|
|
22
|
+
:root {
|
|
23
|
+
--ogrid-selection: #0066cc;
|
|
24
|
+
}
|
|
25
|
+
```
|
|
26
|
+
|
|
27
|
+
Or scope it to a specific grid instance using the `className` prop:
|
|
28
|
+
|
|
29
|
+
```css
|
|
30
|
+
.my-grid {
|
|
31
|
+
--ogrid-selection: #8b5cf6;
|
|
32
|
+
}
|
|
33
|
+
```
|
|
34
|
+
|
|
35
|
+
```tsx
|
|
36
|
+
<OGrid className="my-grid" columns={columns} data={data} getRowId={(item) => item.id} />
|
|
37
|
+
```
|
|
38
|
+
|
|
39
|
+
## Framework Theming
|
|
40
|
+
|
|
41
|
+
Each UI package inherits styles from its framework's theme system. OGrid does not fight your theme -- it builds on top of it.
|
|
42
|
+
|
|
43
|
+
### Radix UI (`@alaarab/ogrid-react-radix`)
|
|
44
|
+
|
|
45
|
+
Radix is the lightest implementation. It uses CSS Modules (`.module.scss`) for all grid styles. Override styles with standard CSS specificity or by targeting the grid's class names.
|
|
46
|
+
|
|
47
|
+
### Fluent UI (`@alaarab/ogrid-react-fluent`)
|
|
48
|
+
|
|
49
|
+
The Fluent implementation renders with Fluent UI v9 components, which inherit from `FluentProvider`. Wrap your app in a `FluentProvider` with your theme:
|
|
50
|
+
|
|
51
|
+
```tsx
|
|
52
|
+
|
|
53
|
+
function App() {
|
|
54
|
+
return (
|
|
55
|
+
<FluentProvider theme={webLightTheme}>
|
|
56
|
+
<OGrid columns={columns} data={data} getRowId={(item) => item.id} />
|
|
57
|
+
</FluentProvider>
|
|
58
|
+
);
|
|
59
|
+
}
|
|
60
|
+
```
|
|
61
|
+
|
|
62
|
+
Fluent also uses CSS Modules for grid-specific styles (cell selection, fill handle, etc.).
|
|
63
|
+
|
|
64
|
+
### Material UI (`@alaarab/ogrid-react-material`)
|
|
65
|
+
|
|
66
|
+
The Material implementation renders with MUI v7 components, which inherit from `ThemeProvider`. Wrap your app in a `ThemeProvider` with your theme:
|
|
67
|
+
|
|
68
|
+
```tsx
|
|
69
|
+
|
|
70
|
+
const theme = createTheme({
|
|
71
|
+
palette: {
|
|
72
|
+
primary: { main: '#1976d2' },
|
|
73
|
+
},
|
|
74
|
+
});
|
|
75
|
+
|
|
76
|
+
function App() {
|
|
77
|
+
return (
|
|
78
|
+
<ThemeProvider theme={theme}>
|
|
79
|
+
<OGrid columns={columns} data={data} getRowId={(item) => item.id} />
|
|
80
|
+
</ThemeProvider>
|
|
81
|
+
);
|
|
82
|
+
}
|
|
83
|
+
```
|
|
84
|
+
|
|
85
|
+
Material uses CSS-in-JS (inline styles) for grid-specific styling rather than CSS Modules.
|
|
86
|
+
|
|
87
|
+
## Layout Mode
|
|
88
|
+
|
|
89
|
+
The `layoutMode` prop controls how the grid sizes itself:
|
|
90
|
+
|
|
91
|
+
| Mode | Behavior |
|
|
92
|
+
|------|----------|
|
|
93
|
+
| `'fill'` (default) | Grid stretches to fill its parent container. The parent must have a defined height. |
|
|
94
|
+
| `'content'` | Grid sizes itself based on content. Width fits columns; height fits rows. |
|
|
95
|
+
|
|
96
|
+
```tsx
|
|
97
|
+
{/* Fill parent container */}
|
|
98
|
+
<div style={{ height: 600 }}>
|
|
99
|
+
<OGrid layoutMode="fill" columns={columns} data={data} getRowId={(item) => item.id} />
|
|
100
|
+
</div>
|
|
101
|
+
|
|
102
|
+
{/* Size to content */}
|
|
103
|
+
<OGrid layoutMode="content" columns={columns} data={data} getRowId={(item) => item.id} />
|
|
104
|
+
```
|
|
105
|
+
|
|
106
|
+
:::tip
|
|
107
|
+
When using `layoutMode="fill"`, make sure the grid's parent has a defined height (explicit px/vh/%, or flex layout). Without it, the grid will collapse to zero height.
|
|
108
|
+
:::
|
|
109
|
+
|
|
110
|
+
## Suppress Horizontal Scroll
|
|
111
|
+
|
|
112
|
+
To prevent horizontal scrolling (useful when all columns fit the viewport), set `suppressHorizontalScroll`:
|
|
113
|
+
|
|
114
|
+
```tsx
|
|
115
|
+
<OGrid suppressHorizontalScroll columns={columns} data={data} getRowId={(item) => item.id} />
|
|
116
|
+
```
|
|
117
|
+
|
|
118
|
+
This sets `overflow-x: hidden` on the grid's scroll container.
|
|
119
|
+
|
|
120
|
+
## Per-Cell Styles
|
|
121
|
+
|
|
122
|
+
Use `cellStyle` on a column definition to apply inline styles to individual cells. It accepts a static style object or a function for conditional styling:
|
|
123
|
+
|
|
124
|
+
### Static Style
|
|
125
|
+
|
|
126
|
+
```tsx
|
|
127
|
+
const columns = [
|
|
128
|
+
{
|
|
129
|
+
columnId: 'amount',
|
|
130
|
+
name: 'Amount',
|
|
131
|
+
type: 'numeric' as const,
|
|
132
|
+
cellStyle: { fontWeight: 600 },
|
|
133
|
+
},
|
|
134
|
+
];
|
|
135
|
+
```
|
|
136
|
+
|
|
137
|
+
### Dynamic Style (Per-Row)
|
|
138
|
+
|
|
139
|
+
```tsx
|
|
140
|
+
const columns = [
|
|
141
|
+
{
|
|
142
|
+
columnId: 'status',
|
|
143
|
+
name: 'Status',
|
|
144
|
+
cellStyle: (item) => ({
|
|
145
|
+
color: item.status === 'Active' ? '#16a34a' : '#dc2626',
|
|
146
|
+
fontWeight: 600,
|
|
147
|
+
}),
|
|
148
|
+
},
|
|
149
|
+
];
|
|
150
|
+
```
|
|
151
|
+
|
|
152
|
+
## Numeric Column Alignment
|
|
153
|
+
|
|
154
|
+
Set `type: 'numeric'` on a column to right-align cell content automatically:
|
|
155
|
+
|
|
156
|
+
```tsx
|
|
157
|
+
{
|
|
158
|
+
columnId: 'price',
|
|
159
|
+
name: 'Price',
|
|
160
|
+
type: 'numeric',
|
|
161
|
+
valueFormatter: (value) => `$${Number(value).toFixed(2)}`,
|
|
162
|
+
}
|
|
163
|
+
```
|
|
164
|
+
|
|
165
|
+
## Custom Wrapper Class
|
|
166
|
+
|
|
167
|
+
The `className` prop adds a CSS class to the grid's outermost wrapper element. Use it for scoped styling:
|
|
168
|
+
|
|
169
|
+
```tsx
|
|
170
|
+
<OGrid className="dashboard-grid" columns={columns} data={data} getRowId={(item) => item.id} />
|
|
171
|
+
```
|
|
172
|
+
|
|
173
|
+
```css
|
|
174
|
+
.dashboard-grid {
|
|
175
|
+
border: 1px solid #e5e7eb;
|
|
176
|
+
border-radius: 8px;
|
|
177
|
+
overflow: hidden;
|
|
178
|
+
}
|
|
179
|
+
```
|
|
180
|
+
|
|
181
|
+
## Column Width Control
|
|
182
|
+
|
|
183
|
+
Control column widths through the column definition:
|
|
184
|
+
|
|
185
|
+
| Prop | Description |
|
|
186
|
+
|------|-------------|
|
|
187
|
+
| `minWidth` | Minimum column width in pixels |
|
|
188
|
+
| `defaultWidth` | Initial column width in pixels |
|
|
189
|
+
| `idealWidth` | Preferred width (used for auto-sizing) |
|
|
190
|
+
|
|
191
|
+
```tsx
|
|
192
|
+
{
|
|
193
|
+
columnId: 'description',
|
|
194
|
+
name: 'Description',
|
|
195
|
+
minWidth: 150,
|
|
196
|
+
defaultWidth: 300,
|
|
197
|
+
}
|
|
198
|
+
```
|
|
199
|
+
|
|
200
|
+
Users can resize columns by dragging the column border. Listen for resize events with `onColumnResized`:
|
|
201
|
+
|
|
202
|
+
```tsx
|
|
203
|
+
<OGrid
|
|
204
|
+
columns={columns}
|
|
205
|
+
data={data}
|
|
206
|
+
getRowId={(item) => item.id}
|
|
207
|
+
onColumnResized={(columnId, width) => {
|
|
208
|
+
localStorage.setItem(`col-width-${columnId}`, String(width));
|
|
209
|
+
}}
|
|
210
|
+
/>
|
|
211
|
+
```
|
|
@@ -0,0 +1,87 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* OGrid MCP Bridge Client
|
|
3
|
+
*
|
|
4
|
+
* Include this in your dev app to connect a running OGrid instance to the
|
|
5
|
+
* MCP bridge server, enabling AI assistants (Claude, Cursor, etc.) to read
|
|
6
|
+
* grid state and send test commands in real time.
|
|
7
|
+
*
|
|
8
|
+
* Usage (React):
|
|
9
|
+
* import { connectGridToBridge } from '@alaarab/ogrid-mcp/bridge-client';
|
|
10
|
+
*
|
|
11
|
+
* useEffect(() => {
|
|
12
|
+
* const bridge = connectGridToBridge({
|
|
13
|
+
* gridId: 'my-grid',
|
|
14
|
+
* getData: () => filteredRows, // current displayed data
|
|
15
|
+
* getColumns: () => columns,
|
|
16
|
+
* api: gridApiRef.current, // IOGridApi (for filter/sort/page commands)
|
|
17
|
+
* onCellUpdate: (rowIndex, columnId, value) => {
|
|
18
|
+
* setData(prev => prev.map((row, i) =>
|
|
19
|
+
* i === rowIndex ? { ...row, [columnId]: value } : row
|
|
20
|
+
* ));
|
|
21
|
+
* },
|
|
22
|
+
* });
|
|
23
|
+
* return () => bridge.disconnect();
|
|
24
|
+
* }, []);
|
|
25
|
+
*
|
|
26
|
+
* This module contains NO Node.js-specific imports — safe to bundle in browsers.
|
|
27
|
+
*/
|
|
28
|
+
interface BridgeColumnInfo {
|
|
29
|
+
columnId: string;
|
|
30
|
+
headerName?: string;
|
|
31
|
+
type?: string;
|
|
32
|
+
}
|
|
33
|
+
interface BridgeCommand {
|
|
34
|
+
id: string;
|
|
35
|
+
type: 'update_cell' | 'set_filter' | 'clear_filters' | 'set_sort' | 'go_to_page';
|
|
36
|
+
payload: Record<string, unknown>;
|
|
37
|
+
}
|
|
38
|
+
/** Minimal subset of IOGridApi used by the bridge. */
|
|
39
|
+
interface BridgeGridApi {
|
|
40
|
+
updateSort?: (model: Array<{
|
|
41
|
+
columnId: string;
|
|
42
|
+
direction: 'asc' | 'desc';
|
|
43
|
+
}>) => void;
|
|
44
|
+
updateFilter?: (columnId: string, value: unknown) => void;
|
|
45
|
+
clearFilters?: () => void;
|
|
46
|
+
goToPage?: (page: number) => void;
|
|
47
|
+
getSelectedRows?: () => unknown[];
|
|
48
|
+
}
|
|
49
|
+
interface ConnectGridOptions {
|
|
50
|
+
/** Unique identifier for this grid instance (shown in list_grids). */
|
|
51
|
+
gridId: string;
|
|
52
|
+
/** Returns the currently displayed rows. Called on every state push. */
|
|
53
|
+
getData: () => unknown[];
|
|
54
|
+
/** Returns the current column definitions. */
|
|
55
|
+
getColumns: () => BridgeColumnInfo[];
|
|
56
|
+
/** Current pagination state. */
|
|
57
|
+
getPagination?: () => {
|
|
58
|
+
page: number;
|
|
59
|
+
pageSize: number;
|
|
60
|
+
totalCount: number;
|
|
61
|
+
pageCount: number;
|
|
62
|
+
};
|
|
63
|
+
/** Returns the current sort model. Called on every state push. */
|
|
64
|
+
getSort?: () => Array<{
|
|
65
|
+
columnId: string;
|
|
66
|
+
direction: 'asc' | 'desc';
|
|
67
|
+
}>;
|
|
68
|
+
/** Returns the current filter model. Called on every state push. */
|
|
69
|
+
getFilters?: () => Record<string, unknown>;
|
|
70
|
+
/** IOGridApi reference for filter/sort/page commands. */
|
|
71
|
+
api?: BridgeGridApi;
|
|
72
|
+
/** Called when the AI sends an update_cell command. */
|
|
73
|
+
onCellUpdate?: (rowIndex: number, columnId: string, value: unknown) => void;
|
|
74
|
+
/** Bridge server URL (default: http://localhost:7890). */
|
|
75
|
+
bridgeUrl?: string;
|
|
76
|
+
/** How often to push state and poll commands (ms, default: 500). */
|
|
77
|
+
pollIntervalMs?: number;
|
|
78
|
+
}
|
|
79
|
+
interface BridgeConnection {
|
|
80
|
+
/** Stop polling and disconnect. */
|
|
81
|
+
disconnect: () => void;
|
|
82
|
+
/** Manually push current state immediately. */
|
|
83
|
+
push: () => Promise<void>;
|
|
84
|
+
}
|
|
85
|
+
declare function connectGridToBridge(options: ConnectGridOptions): BridgeConnection;
|
|
86
|
+
|
|
87
|
+
export { type BridgeColumnInfo, type BridgeCommand, type BridgeConnection, type BridgeGridApi, type ConnectGridOptions, connectGridToBridge };
|