@alaarab/ogrid-mcp 2.9.0 → 2.11.1
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/bundled-docs/api/README.md +7 -32
- package/bundled-docs/api/column-def.mdx +1 -1
- package/bundled-docs/api/components-column-chooser.mdx +0 -96
- package/bundled-docs/api/components-column-header-filter.mdx +1 -83
- package/bundled-docs/api/components-datagrid-table.mdx +0 -63
- package/bundled-docs/api/components-pagination-controls.mdx +0 -94
- package/bundled-docs/api/components-sidebar.mdx +0 -76
- package/bundled-docs/api/components-status-bar.mdx +0 -66
- package/bundled-docs/api/headless-hooks.mdx +410 -0
- package/bundled-docs/api/ogrid-props.mdx +1 -1
- package/bundled-docs/api/types.mdx +1 -1
- package/bundled-docs/features/cell-references.mdx +2 -116
- package/bundled-docs/features/column-chooser.mdx +0 -131
- package/bundled-docs/features/column-groups.mdx +1 -136
- package/bundled-docs/features/column-pinning.mdx +1 -108
- package/bundled-docs/features/column-reordering.mdx +1 -168
- package/bundled-docs/features/column-types.mdx +0 -71
- package/bundled-docs/features/context-menu.mdx +1 -93
- package/bundled-docs/features/csv-export.mdx +1 -104
- package/bundled-docs/features/editing.mdx +0 -149
- package/bundled-docs/features/filtering.mdx +0 -119
- package/bundled-docs/features/formulas.mdx +2 -102
- package/bundled-docs/features/grid-api.mdx +1 -108
- package/bundled-docs/features/keyboard-navigation.mdx +1 -74
- package/bundled-docs/features/mobile-touch.mdx +0 -71
- package/bundled-docs/features/pagination.mdx +0 -105
- package/bundled-docs/features/performance.mdx +0 -191
- package/bundled-docs/features/premium-inputs.mdx +0 -311
- package/bundled-docs/features/responsive-columns.mdx +1 -76
- package/bundled-docs/features/row-selection.mdx +2 -106
- package/bundled-docs/features/server-side-data.mdx +1 -129
- package/bundled-docs/features/sidebar.mdx +1 -78
- package/bundled-docs/features/sorting.mdx +2 -108
- package/bundled-docs/features/spreadsheet-selection.mdx +2 -79
- package/bundled-docs/features/status-bar.mdx +1 -72
- package/bundled-docs/features/toolbar.mdx +1 -75
- package/bundled-docs/features/virtual-scrolling.mdx +1 -304
- package/bundled-docs/getting-started/headless-or-component.mdx +112 -0
- package/bundled-docs/getting-started/installation.mdx +11 -141
- package/bundled-docs/getting-started/overview.mdx +15 -55
- package/bundled-docs/getting-started/quick-start.mdx +4 -279
- package/bundled-docs/guides/browser-support-matrix.mdx +6 -17
- package/bundled-docs/guides/mcp-live-testing.mdx +0 -82
- package/bundled-docs/guides/mcp.mdx +4 -4
- package/bundled-docs/guides/migration-from-ag-grid.mdx +2 -3
- package/bundled-docs/guides/theming.mdx +50 -23
- package/dist/esm/index.js +9 -39
- package/package.json +5 -5
- package/bundled-docs/api/js-api.mdx +0 -198
- package/bundled-docs/getting-started/vanilla-js.mdx +0 -218
- package/bundled-docs/guides/framework-showcase.mdx +0 -246
|
@@ -19,7 +19,7 @@ OGrid supports two independent virtualization axes that can be combined:
|
|
|
19
19
|
<VirtualScrollingDemo />
|
|
20
20
|
|
|
21
21
|
:::tip Try it in your framework
|
|
22
|
-
The demo above uses Radix UI for styling. To see this feature with
|
|
22
|
+
The demo above uses Radix UI for styling. To see this feature with the Fluent UI implementation, click **"Open in online demo"** below the demo.
|
|
23
23
|
:::
|
|
24
24
|
|
|
25
25
|
## Quick Example
|
|
@@ -67,129 +67,8 @@ The `OGrid` component has the same props across all React UI packages. To switch
|
|
|
67
67
|
|
|
68
68
|
- **Radix** (lightweight, default): `from '@alaarab/ogrid-react-radix'`
|
|
69
69
|
- **Fluent UI** (Microsoft 365 / SPFx): `from '@alaarab/ogrid-react-fluent'` - wrap in `<FluentProvider>`
|
|
70
|
-
- **Material UI** (MUI v7): `from '@alaarab/ogrid-react-material'` - wrap in `<ThemeProvider>`
|
|
71
70
|
:::
|
|
72
71
|
|
|
73
|
-
</TabItem>
|
|
74
|
-
<TabItem value="angular" label="Angular">
|
|
75
|
-
|
|
76
|
-
```typescript
|
|
77
|
-
|
|
78
|
-
interface Row {
|
|
79
|
-
id: number;
|
|
80
|
-
name: string;
|
|
81
|
-
value: number;
|
|
82
|
-
}
|
|
83
|
-
|
|
84
|
-
const data: Row[] = Array.from({ length: 10_000 }, (_, i) => ({
|
|
85
|
-
id: i + 1,
|
|
86
|
-
name: `Row ${i + 1}`,
|
|
87
|
-
value: Math.round(Math.random() * 10000),
|
|
88
|
-
}));
|
|
89
|
-
|
|
90
|
-
@Component({
|
|
91
|
-
standalone: true,
|
|
92
|
-
imports: [OGridComponent],
|
|
93
|
-
template: `<ogrid [props]="gridProps" />`
|
|
94
|
-
})
|
|
95
|
-
export class GridComponent {
|
|
96
|
-
gridProps = {
|
|
97
|
-
columns: [
|
|
98
|
-
{ columnId: 'id', name: 'ID', type: 'numeric' },
|
|
99
|
-
{ columnId: 'name', name: 'Name' },
|
|
100
|
-
{ columnId: 'value', name: 'Value', type: 'numeric',
|
|
101
|
-
valueFormatter: (v: unknown) => `$${Number(v).toLocaleString()}` },
|
|
102
|
-
] as IColumnDef<Row>[],
|
|
103
|
-
data,
|
|
104
|
-
getRowId: (item: Row) => item.id,
|
|
105
|
-
virtualScroll: { enabled: true, rowHeight: 36 },
|
|
106
|
-
statusBar: true,
|
|
107
|
-
};
|
|
108
|
-
}
|
|
109
|
-
```
|
|
110
|
-
|
|
111
|
-
:::tip Switching UI libraries
|
|
112
|
-
Same component API across Angular packages. To switch, just change the import:
|
|
113
|
-
|
|
114
|
-
- **Radix (CDK)**: `from '@alaarab/ogrid-angular-radix'` *(default, lightweight)*
|
|
115
|
-
- **Angular Material**: `from '@alaarab/ogrid-angular-material'`
|
|
116
|
-
- **PrimeNG**: `from '@alaarab/ogrid-angular-primeng'`
|
|
117
|
-
|
|
118
|
-
All components are standalone - no NgModule required.
|
|
119
|
-
:::
|
|
120
|
-
|
|
121
|
-
</TabItem>
|
|
122
|
-
<TabItem value="vue" label="Vue">
|
|
123
|
-
|
|
124
|
-
```vue
|
|
125
|
-
<script setup lang="ts">
|
|
126
|
-
|
|
127
|
-
interface Row {
|
|
128
|
-
id: number;
|
|
129
|
-
name: string;
|
|
130
|
-
value: number;
|
|
131
|
-
}
|
|
132
|
-
|
|
133
|
-
const data: Row[] = Array.from({ length: 10_000 }, (_, i) => ({
|
|
134
|
-
id: i + 1,
|
|
135
|
-
name: `Row ${i + 1}`,
|
|
136
|
-
value: Math.round(Math.random() * 10000),
|
|
137
|
-
}));
|
|
138
|
-
|
|
139
|
-
const columns: IColumnDef<Row>[] = [
|
|
140
|
-
{ columnId: 'id', name: 'ID', type: 'numeric' },
|
|
141
|
-
{ columnId: 'name', name: 'Name' },
|
|
142
|
-
{ columnId: 'value', name: 'Value', type: 'numeric',
|
|
143
|
-
valueFormatter: (v) => `$${Number(v).toLocaleString()}` },
|
|
144
|
-
];
|
|
145
|
-
|
|
146
|
-
const gridProps = {
|
|
147
|
-
columns,
|
|
148
|
-
data,
|
|
149
|
-
getRowId: (item: Row) => item.id,
|
|
150
|
-
virtualScroll: { enabled: true, rowHeight: 36 },
|
|
151
|
-
statusBar: true,
|
|
152
|
-
};
|
|
153
|
-
</script>
|
|
154
|
-
|
|
155
|
-
<template>
|
|
156
|
-
<OGrid :gridProps="gridProps" />
|
|
157
|
-
</template>
|
|
158
|
-
```
|
|
159
|
-
|
|
160
|
-
:::tip Switching UI libraries
|
|
161
|
-
Same component API across Vue packages. To switch, just change the import:
|
|
162
|
-
|
|
163
|
-
- **Radix (Headless UI)**: `from '@alaarab/ogrid-vue-radix'` *(default, lightweight)*
|
|
164
|
-
- **Vuetify**: `from '@alaarab/ogrid-vue-vuetify'` - wrap in `<v-app>` for theming
|
|
165
|
-
- **PrimeVue**: `from '@alaarab/ogrid-vue-primevue'`
|
|
166
|
-
:::
|
|
167
|
-
|
|
168
|
-
</TabItem>
|
|
169
|
-
<TabItem value="js" label="Vanilla JS">
|
|
170
|
-
|
|
171
|
-
```js
|
|
172
|
-
|
|
173
|
-
const data = Array.from({ length: 10_000 }, (_, i) => ({
|
|
174
|
-
id: i + 1,
|
|
175
|
-
name: `Row ${i + 1}`,
|
|
176
|
-
value: Math.round(Math.random() * 10000),
|
|
177
|
-
}));
|
|
178
|
-
|
|
179
|
-
const grid = new OGrid(document.getElementById('grid'), {
|
|
180
|
-
columns: [
|
|
181
|
-
{ columnId: 'id', name: 'ID', type: 'numeric' },
|
|
182
|
-
{ columnId: 'name', name: 'Name' },
|
|
183
|
-
{ columnId: 'value', name: 'Value', type: 'numeric',
|
|
184
|
-
valueFormatter: (v) => `$${Number(v).toLocaleString()}` },
|
|
185
|
-
],
|
|
186
|
-
data,
|
|
187
|
-
getRowId: (r) => r.id,
|
|
188
|
-
virtualScroll: { enabled: true, rowHeight: 36 },
|
|
189
|
-
statusBar: true,
|
|
190
|
-
});
|
|
191
|
-
```
|
|
192
|
-
|
|
193
72
|
</TabItem>
|
|
194
73
|
</Tabs>
|
|
195
74
|
|
|
@@ -276,82 +155,6 @@ function App() {
|
|
|
276
155
|
</div>
|
|
277
156
|
);
|
|
278
157
|
}
|
|
279
|
-
```
|
|
280
|
-
|
|
281
|
-
</TabItem>
|
|
282
|
-
<TabItem value="angular" label="Angular">
|
|
283
|
-
|
|
284
|
-
```typescript
|
|
285
|
-
|
|
286
|
-
@Component({
|
|
287
|
-
standalone: true,
|
|
288
|
-
imports: [OGridComponent],
|
|
289
|
-
template: `
|
|
290
|
-
<button (click)="scrollToTop()">Scroll to Top</button>
|
|
291
|
-
<button (click)="scrollToMiddle()">Scroll to Row 5000</button>
|
|
292
|
-
<button (click)="scrollToBottom()">Scroll to Bottom</button>
|
|
293
|
-
<ogrid [props]="gridProps" />
|
|
294
|
-
`,
|
|
295
|
-
})
|
|
296
|
-
export class GridComponent {
|
|
297
|
-
constructor(private gridService: OGridService) {}
|
|
298
|
-
|
|
299
|
-
scrollToTop() { this.gridService.scrollToRow(0); }
|
|
300
|
-
scrollToMiddle() { this.gridService.scrollToRow(4999, { align: 'center' }); }
|
|
301
|
-
scrollToBottom() { this.gridService.scrollToRow(9999, { align: 'end' }); }
|
|
302
|
-
|
|
303
|
-
gridProps = {
|
|
304
|
-
columns,
|
|
305
|
-
data,
|
|
306
|
-
getRowId: (item: Row) => item.id,
|
|
307
|
-
virtualScroll: { enabled: true, rowHeight: 36 },
|
|
308
|
-
};
|
|
309
|
-
}
|
|
310
|
-
```
|
|
311
|
-
|
|
312
|
-
</TabItem>
|
|
313
|
-
<TabItem value="vue" label="Vue">
|
|
314
|
-
|
|
315
|
-
```vue
|
|
316
|
-
<script setup lang="ts">
|
|
317
|
-
|
|
318
|
-
const gridRef = ref<IOGridApi<Row> | null>(null);
|
|
319
|
-
|
|
320
|
-
const scrollToTop = () => gridRef.value?.scrollToRow(0);
|
|
321
|
-
const scrollToMiddle = () => gridRef.value?.scrollToRow(4999, { align: 'center' });
|
|
322
|
-
const scrollToBottom = () => gridRef.value?.scrollToRow(9999, { align: 'end' });
|
|
323
|
-
</script>
|
|
324
|
-
|
|
325
|
-
<template>
|
|
326
|
-
<button @click="scrollToTop">Scroll to Top</button>
|
|
327
|
-
<button @click="scrollToMiddle">Scroll to Row 5000</button>
|
|
328
|
-
<button @click="scrollToBottom">Scroll to Bottom</button>
|
|
329
|
-
<OGrid :gridProps="gridProps" />
|
|
330
|
-
</template>
|
|
331
|
-
```
|
|
332
|
-
|
|
333
|
-
</TabItem>
|
|
334
|
-
<TabItem value="js" label="Vanilla JS">
|
|
335
|
-
|
|
336
|
-
```js
|
|
337
|
-
|
|
338
|
-
const grid = new OGrid(document.getElementById('grid'), {
|
|
339
|
-
columns,
|
|
340
|
-
data,
|
|
341
|
-
getRowId: (r) => r.id,
|
|
342
|
-
virtualScroll: { enabled: true, rowHeight: 36 },
|
|
343
|
-
});
|
|
344
|
-
|
|
345
|
-
const api = grid.getApi();
|
|
346
|
-
|
|
347
|
-
// Scroll to the first row
|
|
348
|
-
api.scrollToRow(0);
|
|
349
|
-
|
|
350
|
-
// Scroll to row 5000, centered in the viewport
|
|
351
|
-
api.scrollToRow(4999, { align: 'center' });
|
|
352
|
-
|
|
353
|
-
// Scroll to the last row
|
|
354
|
-
api.scrollToRow(9999, { align: 'end' });
|
|
355
158
|
```
|
|
356
159
|
|
|
357
160
|
</TabItem>
|
|
@@ -447,114 +250,8 @@ The `OGrid` component has the same props across all React UI packages. To switch
|
|
|
447
250
|
|
|
448
251
|
- **Radix** (lightweight, default): `from '@alaarab/ogrid-react-radix'`
|
|
449
252
|
- **Fluent UI** (Microsoft 365 / SPFx): `from '@alaarab/ogrid-react-fluent'` - wrap in `<FluentProvider>`
|
|
450
|
-
- **Material UI** (MUI v7): `from '@alaarab/ogrid-react-material'` - wrap in `<ThemeProvider>`
|
|
451
|
-
:::
|
|
452
|
-
|
|
453
|
-
</TabItem>
|
|
454
|
-
<TabItem value="angular" label="Angular">
|
|
455
|
-
|
|
456
|
-
```typescript
|
|
457
|
-
|
|
458
|
-
interface Row {
|
|
459
|
-
id: number;
|
|
460
|
-
[key: string]: number | string;
|
|
461
|
-
}
|
|
462
|
-
|
|
463
|
-
@Component({
|
|
464
|
-
standalone: true,
|
|
465
|
-
imports: [OGridComponent],
|
|
466
|
-
template: `<ogrid [props]="gridProps" />`
|
|
467
|
-
})
|
|
468
|
-
export class GridComponent {
|
|
469
|
-
gridProps = {
|
|
470
|
-
columns: [
|
|
471
|
-
{ columnId: 'id', name: 'ID', type: 'numeric', pinned: 'left', defaultWidth: 80 },
|
|
472
|
-
...Array.from({ length: 49 }, (_, i) => ({
|
|
473
|
-
columnId: `col${i}`,
|
|
474
|
-
name: `Column ${i + 1}`,
|
|
475
|
-
type: 'numeric' as const,
|
|
476
|
-
})),
|
|
477
|
-
] as IColumnDef<Row>[],
|
|
478
|
-
data,
|
|
479
|
-
getRowId: (item: Row) => item.id,
|
|
480
|
-
virtualScroll: { enabled: true, rowHeight: 36, columns: true, columnOverscan: 2 },
|
|
481
|
-
};
|
|
482
|
-
}
|
|
483
|
-
```
|
|
484
|
-
|
|
485
|
-
:::tip Switching UI libraries
|
|
486
|
-
Same component API across Angular packages. To switch, just change the import:
|
|
487
|
-
|
|
488
|
-
- **Radix (CDK)**: `from '@alaarab/ogrid-angular-radix'` *(default, lightweight)*
|
|
489
|
-
- **Angular Material**: `from '@alaarab/ogrid-angular-material'`
|
|
490
|
-
- **PrimeNG**: `from '@alaarab/ogrid-angular-primeng'`
|
|
491
|
-
|
|
492
|
-
All components are standalone - no NgModule required.
|
|
493
|
-
:::
|
|
494
|
-
|
|
495
|
-
</TabItem>
|
|
496
|
-
<TabItem value="vue" label="Vue">
|
|
497
|
-
|
|
498
|
-
```vue
|
|
499
|
-
<script setup lang="ts">
|
|
500
|
-
|
|
501
|
-
interface Row {
|
|
502
|
-
id: number;
|
|
503
|
-
[key: string]: number | string;
|
|
504
|
-
}
|
|
505
|
-
|
|
506
|
-
const columns: IColumnDef<Row>[] = [
|
|
507
|
-
{ columnId: 'id', name: 'ID', type: 'numeric', pinned: 'left', defaultWidth: 80 },
|
|
508
|
-
...Array.from({ length: 49 }, (_, i) => ({
|
|
509
|
-
columnId: `col${i}`,
|
|
510
|
-
name: `Column ${i + 1}`,
|
|
511
|
-
type: 'numeric' as const,
|
|
512
|
-
})),
|
|
513
|
-
];
|
|
514
|
-
|
|
515
|
-
const gridProps = {
|
|
516
|
-
columns,
|
|
517
|
-
data,
|
|
518
|
-
getRowId: (item: Row) => item.id,
|
|
519
|
-
virtualScroll: { enabled: true, rowHeight: 36, columns: true, columnOverscan: 2 },
|
|
520
|
-
};
|
|
521
|
-
</script>
|
|
522
|
-
|
|
523
|
-
<template>
|
|
524
|
-
<OGrid :gridProps="gridProps" />
|
|
525
|
-
</template>
|
|
526
|
-
```
|
|
527
|
-
|
|
528
|
-
:::tip Switching UI libraries
|
|
529
|
-
Same component API across Vue packages. To switch, just change the import:
|
|
530
|
-
|
|
531
|
-
- **Radix (Headless UI)**: `from '@alaarab/ogrid-vue-radix'` *(default, lightweight)*
|
|
532
|
-
- **Vuetify**: `from '@alaarab/ogrid-vue-vuetify'` - wrap in `<v-app>` for theming
|
|
533
|
-
- **PrimeVue**: `from '@alaarab/ogrid-vue-primevue'`
|
|
534
253
|
:::
|
|
535
254
|
|
|
536
|
-
</TabItem>
|
|
537
|
-
<TabItem value="js" label="Vanilla JS">
|
|
538
|
-
|
|
539
|
-
```js
|
|
540
|
-
|
|
541
|
-
const columns = [
|
|
542
|
-
{ columnId: 'id', name: 'ID', type: 'numeric', pinned: 'left', defaultWidth: 80 },
|
|
543
|
-
...Array.from({ length: 49 }, (_, i) => ({
|
|
544
|
-
columnId: `col${i}`,
|
|
545
|
-
name: `Column ${i + 1}`,
|
|
546
|
-
type: 'numeric',
|
|
547
|
-
})),
|
|
548
|
-
];
|
|
549
|
-
|
|
550
|
-
const grid = new OGrid(document.getElementById('grid'), {
|
|
551
|
-
columns,
|
|
552
|
-
data,
|
|
553
|
-
getRowId: (r) => r.id,
|
|
554
|
-
virtualScroll: { enabled: true, rowHeight: 36, columns: true, columnOverscan: 2 },
|
|
555
|
-
});
|
|
556
|
-
```
|
|
557
|
-
|
|
558
255
|
</TabItem>
|
|
559
256
|
</Tabs>
|
|
560
257
|
|
|
@@ -0,0 +1,112 @@
|
|
|
1
|
+
---
|
|
2
|
+
sidebar_position: 5
|
|
3
|
+
title: Headless or component?
|
|
4
|
+
description: When to use the <OGrid> drop-in component vs the headless useHeadlessGrid hooks
|
|
5
|
+
---
|
|
6
|
+
|
|
7
|
+
# Headless or component?
|
|
8
|
+
|
|
9
|
+
OGrid ships **two equally-supported entry points**. Both are first-class.
|
|
10
|
+
Both are MIT. Both expose the same spreadsheet features. Pick the one that
|
|
11
|
+
fits the page you're building — you can mix them in the same app.
|
|
12
|
+
|
|
13
|
+
| | `<OGrid>` component | `useHeadlessGrid` + spreadsheet hooks |
|
|
14
|
+
|---|---|---|
|
|
15
|
+
| **What you write** | One JSX element | A handful of hook calls + your own `<table>` markup |
|
|
16
|
+
| **Time to first working grid** | ~5 lines | ~50-100 lines |
|
|
17
|
+
| **Customization ceiling** | High (theme tokens, slots) | Unlimited (you draw the chrome) |
|
|
18
|
+
| **Design-system fit** | Inherits via theme presets (shadcn, Fluent, Material) | Native — uses your chrome primitives directly |
|
|
19
|
+
| **Spreadsheet features** | Built-in | Composable from hooks |
|
|
20
|
+
| **Best for** | Standard list pages, admin tables, dashboards | Pages where chrome integration matters more than save-time |
|
|
21
|
+
|
|
22
|
+
## Use `<OGrid>` when…
|
|
23
|
+
|
|
24
|
+
- You want a complete grid in one element. Sort, filter, paginate, edit,
|
|
25
|
+
range select, fill handle, copy/paste, undo, keyboard nav — all wired.
|
|
26
|
+
- The default chrome (via your chosen UI variant — Radix / Fluent / Material)
|
|
27
|
+
is close enough to your design system that a theme preset (`preset-shadcn.css`)
|
|
28
|
+
can bridge the rest.
|
|
29
|
+
- You're prototyping or building admin pages where shipping fast matters
|
|
30
|
+
more than every pixel.
|
|
31
|
+
|
|
32
|
+
```tsx
|
|
33
|
+
|
|
34
|
+
const columns = [
|
|
35
|
+
{ columnId: "name", name: "Name", sortable: true, editable: true },
|
|
36
|
+
{ columnId: "salary", name: "Salary", type: "numeric", sortable: true },
|
|
37
|
+
];
|
|
38
|
+
|
|
39
|
+
<OGrid columns={columns} data={employees} getRowId={(e) => e.id} />;
|
|
40
|
+
```
|
|
41
|
+
|
|
42
|
+
## Use `useHeadlessGrid` + the spreadsheet hooks when…
|
|
43
|
+
|
|
44
|
+
- You want OGrid's logic but rendered with your own table chrome
|
|
45
|
+
(shadcn `<Table>`, Fluent `<DataGrid>`, Material `<TableRow>`, plain HTML —
|
|
46
|
+
anything).
|
|
47
|
+
- The chrome integration is non-negotiable: a specific design system,
|
|
48
|
+
custom row layouts, embedded widgets in cells, or shared `<TableRow>`
|
|
49
|
+
components from the rest of the app.
|
|
50
|
+
- You want to opt into spreadsheet features piece-by-piece. Add only
|
|
51
|
+
inline edit on this page; add range selection + clipboard on that one.
|
|
52
|
+
|
|
53
|
+
```tsx
|
|
54
|
+
useHeadlessGrid,
|
|
55
|
+
useInlineEdit,
|
|
56
|
+
useRangeSelection,
|
|
57
|
+
useFillHandle,
|
|
58
|
+
useCellClipboard,
|
|
59
|
+
useUndoRedo,
|
|
60
|
+
useGridFocus,
|
|
61
|
+
} from "@alaarab/ogrid-react-radix";
|
|
62
|
+
|
|
63
|
+
const grid = useHeadlessGrid({ columns, data, getRowId: (r) => r.id });
|
|
64
|
+
const range = useRangeSelection({ rowCount: grid.rows.length, colCount: grid.columns.length });
|
|
65
|
+
const undo = useUndoRedo({ onCellValueChanged: applyEdit });
|
|
66
|
+
const edit = useInlineEdit({ columns, getRowId: (r) => r.id, onCellEdit: undo.onCellValueChanged });
|
|
67
|
+
const fill = useFillHandle({ rangeSelection: range, rows: grid.rows, columns, onFillCells });
|
|
68
|
+
const clipboard = useCellClipboard({ rangeSelection: range, rows: grid.rows, columns, onCellEdit });
|
|
69
|
+
const focus = useGridFocus({ rowCount: grid.rows.length, colCount: grid.columns.length, rangeSelection: range });
|
|
70
|
+
|
|
71
|
+
return (
|
|
72
|
+
<Table>
|
|
73
|
+
<TableHeader>{/* render grid.columns + grid.toggleSort + grid.sortIndicator */}</TableHeader>
|
|
74
|
+
<TableBody>{/* render grid.rows + edit / range / fill / clipboard / focus glue */}</TableBody>
|
|
75
|
+
</Table>
|
|
76
|
+
);
|
|
77
|
+
```
|
|
78
|
+
|
|
79
|
+
The full integration code is the
|
|
80
|
+
[`SpreadsheetDemo` Storybook story in `react-radix`](https://github.com/alaarab/ogrid/blob/main/packages/react-radix/src/OGrid/SpreadsheetDemo.stories.tsx)
|
|
81
|
+
— ~200 lines, copy-paste as your starter template.
|
|
82
|
+
|
|
83
|
+
## Both at once — yes, in the same app
|
|
84
|
+
|
|
85
|
+
Mix freely. A typical pattern:
|
|
86
|
+
|
|
87
|
+
- 80% of admin / list pages → `<OGrid>` (fast to build, good enough chrome)
|
|
88
|
+
- 20% of "the data table is the product" pages → headless hooks (custom chrome wins)
|
|
89
|
+
|
|
90
|
+
Same package import. Same theme tokens. Same TypeScript types. The
|
|
91
|
+
spreadsheet features (inline edit, fill handle, clipboard, undo) work
|
|
92
|
+
identically across both paths because they share the same core utilities
|
|
93
|
+
(`processClientSideData`, `applyFillValues`, `formatSelectionAsTsv`,
|
|
94
|
+
`parseValue`, etc).
|
|
95
|
+
|
|
96
|
+
## What this means architecturally
|
|
97
|
+
|
|
98
|
+
`<OGrid>` is OGrid's **reference chrome** — a complete grid built on the
|
|
99
|
+
same headless primitives any consumer would use. The two paths share
|
|
100
|
+
underlying state machines (`useOGridSorting`, `useOGridFilters`,
|
|
101
|
+
`useOGridPagination`, `useOGridDataFetching`); the only difference is who
|
|
102
|
+
draws the table. That's why you can swap between them page-by-page
|
|
103
|
+
without losing behavior parity, and why the bug fixes in one path
|
|
104
|
+
automatically benefit the other.
|
|
105
|
+
|
|
106
|
+
## Migrating between modes
|
|
107
|
+
|
|
108
|
+
There's no migration boundary. `<OGrid>` accepts the same column defs
|
|
109
|
+
your headless code uses. Move a page from `<OGrid>` to headless by
|
|
110
|
+
replacing the JSX element with hook calls + your own table; the column
|
|
111
|
+
defs, the row data, the sort/filter/paginate behavior all stay identical.
|
|
112
|
+
Move back the same way.
|
|
@@ -6,7 +6,7 @@ description: Install OGrid for your framework
|
|
|
6
6
|
|
|
7
7
|
# Installation
|
|
8
8
|
|
|
9
|
-
OGrid ships as separate packages for each
|
|
9
|
+
OGrid ships as separate packages for each design system. Pick the one that matches your project.
|
|
10
10
|
|
|
11
11
|
## React
|
|
12
12
|
|
|
@@ -32,115 +32,19 @@ npm install @alaarab/ogrid-react-fluent @fluentui/react-components
|
|
|
32
32
|
|
|
33
33
|
**When to choose:** SharePoint Framework (SPFx) apps, Microsoft 365 integrations, or projects already using Fluent UI.
|
|
34
34
|
|
|
35
|
-
### Material UI
|
|
36
|
-
|
|
37
|
-
**Google's Material Design.** Requires MUI v7 and Emotion as peer dependencies.
|
|
38
|
-
|
|
39
|
-
```bash
|
|
40
|
-
npm install @alaarab/ogrid-react-material @mui/material @emotion/react @emotion/styled
|
|
41
|
-
```
|
|
42
|
-
|
|
43
|
-
**When to choose:** Projects using Material Design, or when you need MUI's extensive component ecosystem.
|
|
44
|
-
|
|
45
35
|
---
|
|
46
36
|
|
|
47
|
-
##
|
|
48
|
-
|
|
49
|
-
Choose one Angular UI package based on your design system:
|
|
50
|
-
|
|
51
|
-
### Radix (Angular CDK)
|
|
52
|
-
|
|
53
|
-
**Lightest option.** Uses Angular CDK for overlays -- no heavy UI framework dependencies.
|
|
54
|
-
|
|
55
|
-
```bash
|
|
56
|
-
npm install @alaarab/ogrid-angular-radix @angular/cdk
|
|
57
|
-
```
|
|
58
|
-
|
|
59
|
-
**When to choose:** New Angular projects, or when you want minimal bundle size and no design system lock-in.
|
|
60
|
-
|
|
61
|
-
### Angular Material
|
|
62
|
-
|
|
63
|
-
**Official Material Design for Angular.** Requires Angular v21, Angular Material, and CDK as peer dependencies.
|
|
64
|
-
|
|
65
|
-
```bash
|
|
66
|
-
npm install @alaarab/ogrid-angular-material @angular/material @angular/cdk
|
|
67
|
-
```
|
|
68
|
-
|
|
69
|
-
**When to choose:** Projects already using Angular Material, or when you need Material Design components.
|
|
70
|
-
|
|
71
|
-
### PrimeNG
|
|
72
|
-
|
|
73
|
-
**PrimeNG component library.** Requires Angular v21 and PrimeNG as peer dependencies.
|
|
74
|
-
|
|
75
|
-
```bash
|
|
76
|
-
npm install @alaarab/ogrid-angular-primeng primeng
|
|
77
|
-
```
|
|
78
|
-
|
|
79
|
-
**When to choose:** Projects already using PrimeNG, or when you prefer PrimeNG's component set.
|
|
80
|
-
|
|
81
|
-
---
|
|
82
|
-
|
|
83
|
-
## Vue
|
|
84
|
-
|
|
85
|
-
Choose one Vue UI package based on your design system:
|
|
86
|
-
|
|
87
|
-
### Radix (Headless UI)
|
|
88
|
-
|
|
89
|
-
**Lightest option.** Headless UI Vue components are bundled as regular dependencies -- no peer deps beyond Vue.
|
|
90
|
-
|
|
91
|
-
```bash
|
|
92
|
-
npm install @alaarab/ogrid-vue-radix
|
|
93
|
-
```
|
|
94
|
-
|
|
95
|
-
**When to choose:** New Vue projects, or when you want minimal bundle size and no design system lock-in.
|
|
96
|
-
|
|
97
|
-
### Vuetify
|
|
37
|
+
## Frozen adapters
|
|
98
38
|
|
|
99
|
-
|
|
39
|
+
The following adapters remain on npm at their last shipped version but no longer receive feature work or framework-major upgrades. Existing installs continue to work unchanged. Source for each lives on the `legacy/multiframework` branch of the repo.
|
|
100
40
|
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
**When to choose:** Projects already using Vuetify, or when you need Material Design components.
|
|
106
|
-
|
|
107
|
-
### PrimeVue
|
|
108
|
-
|
|
109
|
-
**PrimeVue component library.** Requires Vue 3 and PrimeVue as peer dependencies.
|
|
110
|
-
|
|
111
|
-
```bash
|
|
112
|
-
npm install @alaarab/ogrid-vue-primevue primevue
|
|
113
|
-
```
|
|
114
|
-
|
|
115
|
-
**When to choose:** Projects already using PrimeVue, or when you prefer PrimeVue's component set.
|
|
41
|
+
- **`@alaarab/ogrid-react-material`** — frozen at v2.9.1. MUI v7 (skipped v8, broke in v9).
|
|
42
|
+
- **`@alaarab/ogrid-js`** + **`@alaarab/ogrid-js-inputs`** — frozen at v2.9.1. The vanilla JS variant.
|
|
43
|
+
- **`@alaarab/ogrid-angular*`** — frozen at v2.9.0.
|
|
44
|
+
- **`@alaarab/ogrid-vue*`** — frozen at v2.9.0.
|
|
116
45
|
|
|
117
46
|
---
|
|
118
47
|
|
|
119
|
-
## Vanilla JS (No Framework)
|
|
120
|
-
|
|
121
|
-
**Framework-free data grid.** Class-based API with EventEmitter state management. Zero framework dependencies.
|
|
122
|
-
|
|
123
|
-
```bash
|
|
124
|
-
npm install @alaarab/ogrid-js
|
|
125
|
-
```
|
|
126
|
-
|
|
127
|
-
**When to choose:** Projects without React/Angular/Vue, legacy codebases, or when you want full control over rendering.
|
|
128
|
-
|
|
129
|
-
:::tip Theme CSS
|
|
130
|
-
The JS package ships a default theme with light and dark mode support:
|
|
131
|
-
|
|
132
|
-
```js
|
|
133
|
-
```
|
|
134
|
-
|
|
135
|
-
Or link it directly in HTML:
|
|
136
|
-
|
|
137
|
-
```html
|
|
138
|
-
<link rel="stylesheet" href="node_modules/@alaarab/ogrid-js/dist/styles/ogrid.css" />
|
|
139
|
-
```
|
|
140
|
-
|
|
141
|
-
You can override any `--ogrid-*` CSS variable to customize colors, or skip the default theme entirely and write your own CSS targeting the `ogrid-*` class names.
|
|
142
|
-
:::
|
|
143
|
-
|
|
144
48
|
## Core Only
|
|
145
49
|
|
|
146
50
|
If you want to build your own framework adapter on top of OGrid's types and utilities, install the core package directly.
|
|
@@ -155,19 +59,16 @@ You typically do not need to install `@alaarab/ogrid-core` separately. All React
|
|
|
155
59
|
|
|
156
60
|
## Requirements
|
|
157
61
|
|
|
158
|
-
|
|
|
62
|
+
| Dependency | Version |
|
|
159
63
|
|---|---|
|
|
160
64
|
| React | 17, 18, or 19 |
|
|
161
|
-
|
|
|
162
|
-
|
|
|
163
|
-
| TypeScript | 5.x recommended (not required) |
|
|
164
|
-
| Node.js | >= 18 (for development/build tooling) |
|
|
65
|
+
| TypeScript | 5.x or 6.x recommended (not required) |
|
|
66
|
+
| Node.js | >= 18 (for your build tooling) |
|
|
165
67
|
|
|
166
68
|
## Verifying the Installation
|
|
167
69
|
|
|
168
70
|
After installing, confirm everything is working by rendering a minimal grid.
|
|
169
71
|
|
|
170
|
-
**React:**
|
|
171
72
|
```tsx
|
|
172
73
|
|
|
173
74
|
type Row = { id: number; name: string };
|
|
@@ -178,39 +79,8 @@ function App() {
|
|
|
178
79
|
}
|
|
179
80
|
```
|
|
180
81
|
|
|
181
|
-
**Angular:**
|
|
182
|
-
```typescript
|
|
183
|
-
|
|
184
|
-
@Component({
|
|
185
|
-
standalone: true,
|
|
186
|
-
imports: [OGridComponent],
|
|
187
|
-
template: `<ogrid [props]="gridProps" />`
|
|
188
|
-
})
|
|
189
|
-
export class AppComponent {
|
|
190
|
-
gridProps = {
|
|
191
|
-
columns: [{ columnId: 'name', name: 'Name' }] as IColumnDef[],
|
|
192
|
-
data: [{ id: 1, name: 'Test' }],
|
|
193
|
-
getRowId: (row: any) => row.id,
|
|
194
|
-
};
|
|
195
|
-
}
|
|
196
|
-
```
|
|
197
|
-
|
|
198
|
-
**Vue:**
|
|
199
|
-
```vue
|
|
200
|
-
<script setup lang="ts">
|
|
201
|
-
|
|
202
|
-
const columns: IColumnDef[] = [{ columnId: 'name', name: 'Name' }];
|
|
203
|
-
const data = [{ id: 1, name: 'Test' }];
|
|
204
|
-
const getRowId = (row: any) => row.id;
|
|
205
|
-
</script>
|
|
206
|
-
|
|
207
|
-
<template>
|
|
208
|
-
<OGrid :gridProps="{ columns, data, getRowId }" />
|
|
209
|
-
</template>
|
|
210
|
-
```
|
|
211
|
-
|
|
212
82
|
If the grid renders with a single row showing "Test", your installation is correct.
|
|
213
83
|
|
|
214
84
|
## Next Steps
|
|
215
85
|
|
|
216
|
-
- [Quick Start](./quick-start) -- build a
|
|
86
|
+
- [Quick Start](./quick-start) -- build a working React grid
|