@alaarab/ogrid-mcp 2.5.4 → 2.5.8
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 +6 -51
- package/bundled-docs/api/README.md +11 -11
- package/bundled-docs/api/components-column-chooser.mdx +21 -21
- package/bundled-docs/api/components-column-header-filter.mdx +23 -23
- package/bundled-docs/api/components-datagrid-table.mdx +27 -27
- package/bundled-docs/api/components-pagination-controls.mdx +21 -21
- package/bundled-docs/api/components-sidebar.mdx +27 -27
- package/bundled-docs/api/components-status-bar.mdx +12 -12
- package/bundled-docs/api/js-api.mdx +13 -13
- package/bundled-docs/api/types.mdx +4 -4
- package/bundled-docs/features/column-chooser.mdx +4 -4
- package/bundled-docs/features/column-groups.mdx +4 -4
- package/bundled-docs/features/column-pinning.mdx +5 -5
- package/bundled-docs/features/column-reordering.mdx +5 -5
- package/bundled-docs/features/column-types.mdx +7 -7
- package/bundled-docs/features/context-menu.mdx +4 -4
- package/bundled-docs/features/csv-export.mdx +4 -4
- package/bundled-docs/features/editing.mdx +78 -68
- package/bundled-docs/features/filtering.mdx +83 -67
- package/bundled-docs/features/formulas.mdx +135 -139
- package/bundled-docs/features/grid-api.mdx +4 -4
- package/bundled-docs/features/keyboard-navigation.mdx +6 -6
- package/bundled-docs/features/mobile-touch.mdx +9 -9
- package/bundled-docs/features/pagination.mdx +4 -4
- package/bundled-docs/features/performance.mdx +97 -100
- package/bundled-docs/features/premium-inputs.mdx +579 -0
- package/bundled-docs/features/responsive-columns.mdx +1 -1
- package/bundled-docs/features/row-selection.mdx +8 -8
- package/bundled-docs/features/server-side-data.mdx +4 -4
- package/bundled-docs/features/sidebar.mdx +6 -6
- package/bundled-docs/features/sorting.mdx +87 -44
- package/bundled-docs/features/spreadsheet-selection.mdx +9 -9
- package/bundled-docs/features/status-bar.mdx +4 -4
- package/bundled-docs/features/toolbar.mdx +9 -9
- package/bundled-docs/features/virtual-scrolling.mdx +13 -13
- package/bundled-docs/getting-started/overview.mdx +9 -9
- package/bundled-docs/getting-started/quick-start.mdx +47 -47
- package/bundled-docs/getting-started/vanilla-js.mdx +98 -74
- package/bundled-docs/guides/accessibility.mdx +113 -421
- package/bundled-docs/guides/framework-showcase.mdx +98 -52
- package/bundled-docs/guides/mcp-live-testing.mdx +12 -12
- package/bundled-docs/guides/mcp.mdx +47 -46
- package/dist/esm/bridge-client.d.ts +3 -3
- package/dist/esm/index.js +9 -9
- package/package.json +3 -2
|
@@ -6,7 +6,7 @@ description: Full API reference for @alaarab/ogrid-js
|
|
|
6
6
|
|
|
7
7
|
# Vanilla JS API
|
|
8
8
|
|
|
9
|
-
Complete reference for `@alaarab/ogrid-js`
|
|
9
|
+
Complete reference for `@alaarab/ogrid-js` - the framework-free data grid.
|
|
10
10
|
|
|
11
11
|
## OGrid Class
|
|
12
12
|
|
|
@@ -29,7 +29,7 @@ const grid = new OGrid(container, options);
|
|
|
29
29
|
| `grid.api` | The imperative API object (see [API Methods](#api-methods) below). |
|
|
30
30
|
| `grid.on(event, handler)` | Subscribe to a grid event. Returns `void`. |
|
|
31
31
|
| `grid.off(event, handler)` | Unsubscribe from a grid event. |
|
|
32
|
-
| `grid.destroy()` | Tear down the grid
|
|
32
|
+
| `grid.destroy()` | Tear down the grid - removes DOM, listeners, and ResizeObservers. |
|
|
33
33
|
|
|
34
34
|
---
|
|
35
35
|
|
|
@@ -43,8 +43,8 @@ All configuration is passed to the constructor.
|
|
|
43
43
|
|--------|------|---------|-------------|
|
|
44
44
|
| `columns` | `(IColumnDef<T> \| IColumnGroupDef<T>)[]` | **required** | Column definitions. |
|
|
45
45
|
| `getRowId` | `(item: T) => RowId` | **required** | Returns a unique `string \| number` per row. |
|
|
46
|
-
| `data` | `T[]` |
|
|
47
|
-
| `dataSource` | `IDataSource<T>` |
|
|
46
|
+
| `data` | `T[]` | - | Client-side data. Mutually exclusive with `dataSource`. |
|
|
47
|
+
| `dataSource` | `IDataSource<T>` | - | Server-side data source. Mutually exclusive with `data`. |
|
|
48
48
|
|
|
49
49
|
### Pagination & Sorting
|
|
50
50
|
|
|
@@ -52,8 +52,8 @@ All configuration is passed to the constructor.
|
|
|
52
52
|
|--------|------|---------|-------------|
|
|
53
53
|
| `page` | `number` | `1` | Initial page (1-based). |
|
|
54
54
|
| `pageSize` | `number` | `20` | Rows per page. |
|
|
55
|
-
| `sort` | `{ field: string; direction: 'asc' \| 'desc' }` |
|
|
56
|
-
| `filters` | `IFilters` |
|
|
55
|
+
| `sort` | `{ field: string; direction: 'asc' \| 'desc' }` | - | Initial sort state. |
|
|
56
|
+
| `filters` | `IFilters` | - | Initial filter state. |
|
|
57
57
|
|
|
58
58
|
### Interaction
|
|
59
59
|
|
|
@@ -61,9 +61,9 @@ All configuration is passed to the constructor.
|
|
|
61
61
|
|--------|------|---------|-------------|
|
|
62
62
|
| `editable` | `boolean` | `false` | Enable inline cell editing. |
|
|
63
63
|
| `cellSelection` | `boolean` | `false` | Enable spreadsheet-style cell/range selection. |
|
|
64
|
-
| `rowSelection` | `'single' \| 'multiple'` |
|
|
65
|
-
| `selectedRows` | `Set<RowId>` |
|
|
66
|
-
| `pinnedColumns` | `Record<string, 'left' \| 'right'>` |
|
|
64
|
+
| `rowSelection` | `'single' \| 'multiple'` | - | Row checkbox selection mode. |
|
|
65
|
+
| `selectedRows` | `Set<RowId>` | - | Controlled selected row IDs. |
|
|
66
|
+
| `pinnedColumns` | `Record<string, 'left' \| 'right'>` | - | Pin columns to left/right edges. |
|
|
67
67
|
| `visibleColumns` | `Set<string>` | all | Initially visible column IDs. |
|
|
68
68
|
|
|
69
69
|
### Layout
|
|
@@ -72,9 +72,9 @@ All configuration is passed to the constructor.
|
|
|
72
72
|
|--------|------|---------|-------------|
|
|
73
73
|
| `layoutMode` | `'fill' \| 'content'` | `'fill'` | `'fill'` stretches to container; `'content'` sizes to data. |
|
|
74
74
|
| `suppressHorizontalScroll` | `boolean` | `false` | Prevent horizontal scrollbar. |
|
|
75
|
-
| `sideBar` | `boolean \| ISideBarDef` |
|
|
75
|
+
| `sideBar` | `boolean \| ISideBarDef` | - | Show sidebar with columns/filters panels. |
|
|
76
76
|
| `emptyMessage` | `string` | `'No data'` | Custom empty state text. |
|
|
77
|
-
| `aria-label` | `string` |
|
|
77
|
+
| `aria-label` | `string` | - | Accessible label for the grid. |
|
|
78
78
|
|
|
79
79
|
### Callbacks
|
|
80
80
|
|
|
@@ -173,11 +173,11 @@ The JS package extends the core `IColumnDef<T>` with DOM-aware fields:
|
|
|
173
173
|
|
|
174
174
|
| Field | Type | Description |
|
|
175
175
|
|-------|------|-------------|
|
|
176
|
-
| `renderCell` | `(cell: HTMLTableCellElement, item: T, value: unknown) => void` | Custom cell renderer
|
|
176
|
+
| `renderCell` | `(cell: HTMLTableCellElement, item: T, value: unknown) => void` | Custom cell renderer - mutate the `<td>` DOM directly. |
|
|
177
177
|
| `cellStyle` | `Partial<CSSStyleDeclaration>` | Inline styles applied to each cell. |
|
|
178
178
|
| `cellEditor` | `string \| (container: HTMLElement, params: object) => { getValue: () => unknown; destroy: () => void }` | Built-in editor name (`'text'`, `'select'`, `'richSelect'`, `'checkbox'`, `'date'`) or a factory function for custom editors. |
|
|
179
179
|
|
|
180
|
-
All other `IColumnDef` fields (`columnId`, `name`, `sortable`, `filterable`, `type`, `editable`, `valueFormatter`, `valueGetter`, `valueParser`, `minWidth`, `defaultWidth`, `idealWidth`, `pinned`, `required`, `defaultVisible`) are identical to the React version
|
|
180
|
+
All other `IColumnDef` fields (`columnId`, `name`, `sortable`, `filterable`, `type`, `editable`, `valueFormatter`, `valueGetter`, `valueParser`, `minWidth`, `defaultWidth`, `idealWidth`, `pinned`, `required`, `defaultVisible`) are identical to the React version - see [Column Definitions](./column-def).
|
|
181
181
|
|
|
182
182
|
---
|
|
183
183
|
|
|
@@ -308,7 +308,7 @@ interface IFetchParams {
|
|
|
308
308
|
| `page` | `number` | Current page number (1-indexed). |
|
|
309
309
|
| `pageSize` | `number` | Number of items per page. |
|
|
310
310
|
| `sort` | `{ field, direction }` | Active sort (field name + direction). Omit if no sort. |
|
|
311
|
-
| `filters` | `IFilters` | Active filters (field
|
|
311
|
+
| `filters` | `IFilters` | Active filters (field to FilterValue). |
|
|
312
312
|
|
|
313
313
|
### IPageResult<T>
|
|
314
314
|
|
|
@@ -537,9 +537,9 @@ interface IGridColumnState {
|
|
|
537
537
|
| `visibleColumns` | `string[]` | Array of visible column IDs. |
|
|
538
538
|
| `sort` | `{ field, direction }` | Active sort (field name + direction). |
|
|
539
539
|
| `columnOrder` | `string[]` | Column display order (array of column IDs). |
|
|
540
|
-
| `columnWidths` | `Record<string, number>` | Column widths in pixels (column ID
|
|
541
|
-
| `filters` | `IFilters` | Active filters (field
|
|
542
|
-
| `pinnedColumns` | `Record<string, 'left' \| 'right'>` | Pinned columns (column ID
|
|
540
|
+
| `columnWidths` | `Record<string, number>` | Column widths in pixels (column ID to width). |
|
|
541
|
+
| `filters` | `IFilters` | Active filters (field to FilterValue). |
|
|
542
|
+
| `pinnedColumns` | `Record<string, 'left' \| 'right'>` | Pinned columns (column ID to position). |
|
|
543
543
|
|
|
544
544
|
### Usage Example
|
|
545
545
|
|
|
@@ -64,8 +64,8 @@ function App() {
|
|
|
64
64
|
The `OGrid` component has the same props across all React UI packages. To switch, just change the import:
|
|
65
65
|
|
|
66
66
|
- **Radix** (lightweight, default): `from '@alaarab/ogrid-react-radix'`
|
|
67
|
-
- **Fluent UI** (Microsoft 365 / SPFx): `from '@alaarab/ogrid-react-fluent'`
|
|
68
|
-
- **Material UI** (MUI v7): `from '@alaarab/ogrid-react-material'`
|
|
67
|
+
- **Fluent UI** (Microsoft 365 / SPFx): `from '@alaarab/ogrid-react-fluent'` - wrap in `<FluentProvider>`
|
|
68
|
+
- **Material UI** (MUI v7): `from '@alaarab/ogrid-react-material'` - wrap in `<ThemeProvider>`
|
|
69
69
|
:::
|
|
70
70
|
|
|
71
71
|
</TabItem>
|
|
@@ -119,7 +119,7 @@ Same component API across Angular packages. To switch, just change the import:
|
|
|
119
119
|
- **Angular Material**: `from '@alaarab/ogrid-angular-material'`
|
|
120
120
|
- **PrimeNG**: `from '@alaarab/ogrid-angular-primeng'`
|
|
121
121
|
|
|
122
|
-
All components are standalone
|
|
122
|
+
All components are standalone - no NgModule required.
|
|
123
123
|
:::
|
|
124
124
|
|
|
125
125
|
</TabItem>
|
|
@@ -169,7 +169,7 @@ const gridProps = {
|
|
|
169
169
|
Same component API across Vue packages. To switch, just change the import:
|
|
170
170
|
|
|
171
171
|
- **Radix (Headless UI)**: `from '@alaarab/ogrid-vue-radix'` *(default, lightweight)*
|
|
172
|
-
- **Vuetify**: `from '@alaarab/ogrid-vue-vuetify'`
|
|
172
|
+
- **Vuetify**: `from '@alaarab/ogrid-vue-vuetify'` - wrap in `<v-app>` for theming
|
|
173
173
|
- **PrimeVue**: `from '@alaarab/ogrid-vue-primevue'`
|
|
174
174
|
:::
|
|
175
175
|
|
|
@@ -74,8 +74,8 @@ function App() {
|
|
|
74
74
|
The `OGrid` component has the same props across all React UI packages. To switch, just change the import:
|
|
75
75
|
|
|
76
76
|
- **Radix** (lightweight, default): `from '@alaarab/ogrid-react-radix'`
|
|
77
|
-
- **Fluent UI** (Microsoft 365 / SPFx): `from '@alaarab/ogrid-react-fluent'`
|
|
78
|
-
- **Material UI** (MUI v7): `from '@alaarab/ogrid-react-material'`
|
|
77
|
+
- **Fluent UI** (Microsoft 365 / SPFx): `from '@alaarab/ogrid-react-fluent'` - wrap in `<FluentProvider>`
|
|
78
|
+
- **Material UI** (MUI v7): `from '@alaarab/ogrid-react-material'` - wrap in `<ThemeProvider>`
|
|
79
79
|
:::
|
|
80
80
|
|
|
81
81
|
</TabItem>
|
|
@@ -125,7 +125,7 @@ Same component API across Angular packages. To switch, just change the import:
|
|
|
125
125
|
- **Angular Material**: `from '@alaarab/ogrid-angular-material'`
|
|
126
126
|
- **PrimeNG**: `from '@alaarab/ogrid-angular-primeng'`
|
|
127
127
|
|
|
128
|
-
All components are standalone
|
|
128
|
+
All components are standalone - no NgModule required.
|
|
129
129
|
:::
|
|
130
130
|
|
|
131
131
|
</TabItem>
|
|
@@ -173,7 +173,7 @@ const gridProps = {
|
|
|
173
173
|
Same component API across Vue packages. To switch, just change the import:
|
|
174
174
|
|
|
175
175
|
- **Radix (Headless UI)**: `from '@alaarab/ogrid-vue-radix'` *(default, lightweight)*
|
|
176
|
-
- **Vuetify**: `from '@alaarab/ogrid-vue-vuetify'`
|
|
176
|
+
- **Vuetify**: `from '@alaarab/ogrid-vue-vuetify'` - wrap in `<v-app>` for theming
|
|
177
177
|
- **PrimeVue**: `from '@alaarab/ogrid-vue-primevue'`
|
|
178
178
|
:::
|
|
179
179
|
|
|
@@ -67,8 +67,8 @@ function App() {
|
|
|
67
67
|
The `OGrid` component has the same props across all React UI packages. To switch, just change the import:
|
|
68
68
|
|
|
69
69
|
- **Radix** (lightweight, default): `from '@alaarab/ogrid-react-radix'`
|
|
70
|
-
- **Fluent UI** (Microsoft 365 / SPFx): `from '@alaarab/ogrid-react-fluent'`
|
|
71
|
-
- **Material UI** (MUI v7): `from '@alaarab/ogrid-react-material'`
|
|
70
|
+
- **Fluent UI** (Microsoft 365 / SPFx): `from '@alaarab/ogrid-react-fluent'` - wrap in `<FluentProvider>`
|
|
71
|
+
- **Material UI** (MUI v7): `from '@alaarab/ogrid-react-material'` - wrap in `<ThemeProvider>`
|
|
72
72
|
:::
|
|
73
73
|
|
|
74
74
|
</TabItem>
|
|
@@ -108,7 +108,7 @@ Same component API across Angular packages. To switch, just change the import:
|
|
|
108
108
|
- **Angular Material**: `from '@alaarab/ogrid-angular-material'`
|
|
109
109
|
- **PrimeNG**: `from '@alaarab/ogrid-angular-primeng'`
|
|
110
110
|
|
|
111
|
-
All components are standalone
|
|
111
|
+
All components are standalone - no NgModule required.
|
|
112
112
|
:::
|
|
113
113
|
|
|
114
114
|
</TabItem>
|
|
@@ -146,7 +146,7 @@ const gridProps = {
|
|
|
146
146
|
Same component API across Vue packages. To switch, just change the import:
|
|
147
147
|
|
|
148
148
|
- **Radix (Headless UI)**: `from '@alaarab/ogrid-vue-radix'` *(default, lightweight)*
|
|
149
|
-
- **Vuetify**: `from '@alaarab/ogrid-vue-vuetify'`
|
|
149
|
+
- **Vuetify**: `from '@alaarab/ogrid-vue-vuetify'` - wrap in `<v-app>` for theming
|
|
150
150
|
- **PrimeVue**: `from '@alaarab/ogrid-vue-primevue'`
|
|
151
151
|
:::
|
|
152
152
|
|
|
@@ -235,7 +235,7 @@ const gridRef = useRef<IOGridApi<Row>>(null);
|
|
|
235
235
|
|
|
236
236
|
// Save pin state (e.g. to localStorage)
|
|
237
237
|
const state = gridRef.current.getColumnState();
|
|
238
|
-
// state.pinnedColumns
|
|
238
|
+
// state.pinnedColumns to { name: 'left' }
|
|
239
239
|
localStorage.setItem('gridState', JSON.stringify(state));
|
|
240
240
|
|
|
241
241
|
// Restore pin state on mount
|
|
@@ -59,8 +59,8 @@ function App() {
|
|
|
59
59
|
The `OGrid` component has the same props across all React UI packages. To switch, just change the import:
|
|
60
60
|
|
|
61
61
|
- **Radix** (lightweight, default): `from '@alaarab/ogrid-react-radix'`
|
|
62
|
-
- **Fluent UI** (Microsoft 365 / SPFx): `from '@alaarab/ogrid-react-fluent'`
|
|
63
|
-
- **Material UI** (MUI v7): `from '@alaarab/ogrid-react-material'`
|
|
62
|
+
- **Fluent UI** (Microsoft 365 / SPFx): `from '@alaarab/ogrid-react-fluent'` - wrap in `<FluentProvider>`
|
|
63
|
+
- **Material UI** (MUI v7): `from '@alaarab/ogrid-react-material'` - wrap in `<ThemeProvider>`
|
|
64
64
|
:::
|
|
65
65
|
|
|
66
66
|
</TabItem>
|
|
@@ -99,7 +99,7 @@ Same component API across Angular packages. To switch, just change the import:
|
|
|
99
99
|
- **Angular Material**: `from '@alaarab/ogrid-angular-material'`
|
|
100
100
|
- **PrimeNG**: `from '@alaarab/ogrid-angular-primeng'`
|
|
101
101
|
|
|
102
|
-
All components are standalone
|
|
102
|
+
All components are standalone - no NgModule required.
|
|
103
103
|
:::
|
|
104
104
|
|
|
105
105
|
</TabItem>
|
|
@@ -136,7 +136,7 @@ const gridProps = {
|
|
|
136
136
|
Same component API across Vue packages. To switch, just change the import:
|
|
137
137
|
|
|
138
138
|
- **Radix (Headless UI)**: `from '@alaarab/ogrid-vue-radix'` *(default, lightweight)*
|
|
139
|
-
- **Vuetify**: `from '@alaarab/ogrid-vue-vuetify'`
|
|
139
|
+
- **Vuetify**: `from '@alaarab/ogrid-vue-vuetify'` - wrap in `<v-app>` for theming
|
|
140
140
|
- **PrimeVue**: `from '@alaarab/ogrid-vue-primevue'`
|
|
141
141
|
:::
|
|
142
142
|
|
|
@@ -322,7 +322,7 @@ gridRef.current.setColumnOrder(['department', 'name', 'email', 'salary', 'status
|
|
|
322
322
|
|
|
323
323
|
// Save and restore via column state
|
|
324
324
|
const state = gridRef.current.getColumnState();
|
|
325
|
-
// state.columnOrder
|
|
325
|
+
// state.columnOrder to ['name', 'department', 'email', 'salary', 'status']
|
|
326
326
|
localStorage.setItem('gridState', JSON.stringify(state));
|
|
327
327
|
|
|
328
328
|
// Restore on mount
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
sidebar_position: 12.5
|
|
3
3
|
title: Column Types
|
|
4
|
-
description: Built-in column types for common data patterns
|
|
4
|
+
description: Built-in column types for common data patterns - text, numeric, date, and boolean.
|
|
5
5
|
---
|
|
6
6
|
|
|
7
7
|
|
|
@@ -16,7 +16,7 @@ OGrid provides built-in column types that automatically configure alignment, dis
|
|
|
16
16
|
| `'text'` | Left (default) | Text input | Text search | `String()` |
|
|
17
17
|
| `'numeric'` | Right | Text input | Text search | `String()` |
|
|
18
18
|
| `'date'` | Left | Date picker | Date range (from/to) | `toLocaleDateString()` |
|
|
19
|
-
| `'boolean'` | Center | Checkbox |
|
|
19
|
+
| `'boolean'` | Center | Checkbox | - | `True` / `False` |
|
|
20
20
|
|
|
21
21
|
## Quick Example
|
|
22
22
|
|
|
@@ -62,8 +62,8 @@ function App() {
|
|
|
62
62
|
The `OGrid` component has the same props across all React UI packages. To switch, just change the import:
|
|
63
63
|
|
|
64
64
|
- **Radix** (lightweight, default): `from '@alaarab/ogrid-react-radix'`
|
|
65
|
-
- **Fluent UI** (Microsoft 365 / SPFx): `from '@alaarab/ogrid-react-fluent'`
|
|
66
|
-
- **Material UI** (MUI v7): `from '@alaarab/ogrid-react-material'`
|
|
65
|
+
- **Fluent UI** (Microsoft 365 / SPFx): `from '@alaarab/ogrid-react-fluent'` - wrap in `<FluentProvider>`
|
|
66
|
+
- **Material UI** (MUI v7): `from '@alaarab/ogrid-react-material'` - wrap in `<ThemeProvider>`
|
|
67
67
|
:::
|
|
68
68
|
|
|
69
69
|
</TabItem>
|
|
@@ -93,7 +93,7 @@ Same component API across Angular packages. To switch, just change the import:
|
|
|
93
93
|
- **Angular Material**: `from '@alaarab/ogrid-angular-material'`
|
|
94
94
|
- **PrimeNG**: `from '@alaarab/ogrid-angular-primeng'`
|
|
95
95
|
|
|
96
|
-
All components are standalone
|
|
96
|
+
All components are standalone - no NgModule required.
|
|
97
97
|
:::
|
|
98
98
|
|
|
99
99
|
</TabItem>
|
|
@@ -119,7 +119,7 @@ const gridProps = {
|
|
|
119
119
|
Same component API across Vue packages. To switch, just change the import:
|
|
120
120
|
|
|
121
121
|
- **Radix (Headless UI)**: `from '@alaarab/ogrid-vue-radix'` *(default, lightweight)*
|
|
122
|
-
- **Vuetify**: `from '@alaarab/ogrid-vue-vuetify'`
|
|
122
|
+
- **Vuetify**: `from '@alaarab/ogrid-vue-vuetify'` - wrap in `<v-app>` for theming
|
|
123
123
|
- **PrimeVue**: `from '@alaarab/ogrid-vue-primevue'`
|
|
124
124
|
:::
|
|
125
125
|
|
|
@@ -146,7 +146,7 @@ Setting `type: 'date'` provides:
|
|
|
146
146
|
- **Display**: Values are automatically formatted via `toLocaleDateString()` (unless you provide a custom `valueFormatter` or `renderCell`).
|
|
147
147
|
- **Sorting**: Dates are compared chronologically via `Date.getTime()`, not alphabetically.
|
|
148
148
|
- **Cell editor**: Uses `<input type="date">` (native browser date picker) by default.
|
|
149
|
-
- **Filter**: When `filterable: { type: 'date' }` is set, the column header filter shows **From** and **To** date inputs. Both are optional
|
|
149
|
+
- **Filter**: When `filterable: { type: 'date' }` is set, the column header filter shows **From** and **To** date inputs. Both are optional - you can filter by "after", "before", or a range.
|
|
150
150
|
|
|
151
151
|
### Date Filter Values
|
|
152
152
|
|
|
@@ -50,8 +50,8 @@ function App() {
|
|
|
50
50
|
The `OGrid` component has the same props across all React UI packages. To switch, just change the import:
|
|
51
51
|
|
|
52
52
|
- **Radix** (lightweight, default): `from '@alaarab/ogrid-react-radix'`
|
|
53
|
-
- **Fluent UI** (Microsoft 365 / SPFx): `from '@alaarab/ogrid-react-fluent'`
|
|
54
|
-
- **Material UI** (MUI v7): `from '@alaarab/ogrid-react-material'`
|
|
53
|
+
- **Fluent UI** (Microsoft 365 / SPFx): `from '@alaarab/ogrid-react-fluent'` - wrap in `<FluentProvider>`
|
|
54
|
+
- **Material UI** (MUI v7): `from '@alaarab/ogrid-react-material'` - wrap in `<ThemeProvider>`
|
|
55
55
|
:::
|
|
56
56
|
|
|
57
57
|
</TabItem>
|
|
@@ -89,7 +89,7 @@ Same component API across Angular packages. To switch, just change the import:
|
|
|
89
89
|
- **Angular Material**: `from '@alaarab/ogrid-angular-material'`
|
|
90
90
|
- **PrimeNG**: `from '@alaarab/ogrid-angular-primeng'`
|
|
91
91
|
|
|
92
|
-
All components are standalone
|
|
92
|
+
All components are standalone - no NgModule required.
|
|
93
93
|
:::
|
|
94
94
|
|
|
95
95
|
</TabItem>
|
|
@@ -125,7 +125,7 @@ const gridProps = {
|
|
|
125
125
|
Same component API across Vue packages. To switch, just change the import:
|
|
126
126
|
|
|
127
127
|
- **Radix (Headless UI)**: `from '@alaarab/ogrid-vue-radix'` *(default, lightweight)*
|
|
128
|
-
- **Vuetify**: `from '@alaarab/ogrid-vue-vuetify'`
|
|
128
|
+
- **Vuetify**: `from '@alaarab/ogrid-vue-vuetify'` - wrap in `<v-app>` for theming
|
|
129
129
|
- **PrimeVue**: `from '@alaarab/ogrid-vue-primevue'`
|
|
130
130
|
:::
|
|
131
131
|
|
|
@@ -47,8 +47,8 @@ function ExportButton({ data, columns }: { data: Row[]; columns: IColumnDef<Row>
|
|
|
47
47
|
The `OGrid` component has the same props across all React UI packages. To switch, just change the import:
|
|
48
48
|
|
|
49
49
|
- **Radix** (lightweight, default): `from '@alaarab/ogrid-react-radix'`
|
|
50
|
-
- **Fluent UI** (Microsoft 365 / SPFx): `from '@alaarab/ogrid-react-fluent'`
|
|
51
|
-
- **Material UI** (MUI v7): `from '@alaarab/ogrid-react-material'`
|
|
50
|
+
- **Fluent UI** (Microsoft 365 / SPFx): `from '@alaarab/ogrid-react-fluent'` - wrap in `<FluentProvider>`
|
|
51
|
+
- **Material UI** (MUI v7): `from '@alaarab/ogrid-react-material'` - wrap in `<ThemeProvider>`
|
|
52
52
|
:::
|
|
53
53
|
|
|
54
54
|
</TabItem>
|
|
@@ -87,7 +87,7 @@ Same component API across Angular packages. To switch, just change the import:
|
|
|
87
87
|
- **Angular Material**: `from '@alaarab/ogrid-angular-material'`
|
|
88
88
|
- **PrimeNG**: `from '@alaarab/ogrid-angular-primeng'`
|
|
89
89
|
|
|
90
|
-
All components are standalone
|
|
90
|
+
All components are standalone - no NgModule required.
|
|
91
91
|
:::
|
|
92
92
|
|
|
93
93
|
</TabItem>
|
|
@@ -122,7 +122,7 @@ function handleExport() {
|
|
|
122
122
|
Same component API across Vue packages. To switch, just change the import:
|
|
123
123
|
|
|
124
124
|
- **Radix (Headless UI)**: `from '@alaarab/ogrid-vue-radix'` *(default, lightweight)*
|
|
125
|
-
- **Vuetify**: `from '@alaarab/ogrid-vue-vuetify'`
|
|
125
|
+
- **Vuetify**: `from '@alaarab/ogrid-vue-vuetify'` - wrap in `<v-app>` for theming
|
|
126
126
|
- **PrimeVue**: `from '@alaarab/ogrid-vue-primevue'`
|
|
127
127
|
:::
|
|
128
128
|
|
|
@@ -7,17 +7,17 @@ description: Inline editing, clipboard operations, fill handle, and undo/redo
|
|
|
7
7
|
|
|
8
8
|
# Editing & Clipboard
|
|
9
9
|
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
## Live Demo
|
|
10
|
+
Double-click a cell to edit it. Hit Enter to save, Escape to cancel. It feels like a spreadsheet because it's built to work like one — with clipboard paste, drag-to-fill, and full undo/redo out of the box.
|
|
13
11
|
|
|
14
12
|
<CellEditingDemo />
|
|
15
13
|
|
|
16
14
|
:::tip Try it in your framework
|
|
17
|
-
The demo above uses Radix UI for styling.
|
|
15
|
+
The demo above uses Radix UI for styling. Each framework renders editors with its native components — dropdowns, date pickers, and inputs that match your design system.
|
|
18
16
|
:::
|
|
19
17
|
|
|
20
|
-
##
|
|
18
|
+
## Get started in 5 minutes
|
|
19
|
+
|
|
20
|
+
Here's a realistic setup: an employee table with text, dropdown, and numeric columns — including validation that rejects bad salary values before they're saved.
|
|
21
21
|
|
|
22
22
|
<Tabs groupId="framework">
|
|
23
23
|
<TabItem value="react" label="React" default>
|
|
@@ -50,7 +50,7 @@ const columns = [
|
|
|
50
50
|
type: 'numeric',
|
|
51
51
|
valueParser: ({ newValue }) => {
|
|
52
52
|
const num = Number(newValue);
|
|
53
|
-
return isNaN(num) || num < 0 ? undefined : num; // reject
|
|
53
|
+
return isNaN(num) || num < 0 ? undefined : num; // undefined = reject
|
|
54
54
|
},
|
|
55
55
|
valueFormatter: (v) => `$${Number(v).toLocaleString()}`,
|
|
56
56
|
},
|
|
@@ -79,11 +79,11 @@ function App() {
|
|
|
79
79
|
```
|
|
80
80
|
|
|
81
81
|
:::tip Switching UI libraries
|
|
82
|
-
|
|
82
|
+
Same props across all React packages — just change the import:
|
|
83
83
|
|
|
84
84
|
- **Radix** (lightweight, default): `from '@alaarab/ogrid-react-radix'`
|
|
85
|
-
- **Fluent UI** (Microsoft 365 / SPFx): `from '@alaarab/ogrid-react-fluent'`
|
|
86
|
-
- **Material UI** (MUI v7): `from '@alaarab/ogrid-react-material'`
|
|
85
|
+
- **Fluent UI** (Microsoft 365 / SPFx): `from '@alaarab/ogrid-react-fluent'` - wrap in `<FluentProvider>`
|
|
86
|
+
- **Material UI** (MUI v7): `from '@alaarab/ogrid-react-material'` - wrap in `<ThemeProvider>`
|
|
87
87
|
:::
|
|
88
88
|
|
|
89
89
|
</TabItem>
|
|
@@ -128,7 +128,7 @@ export class GridComponent {
|
|
|
128
128
|
```
|
|
129
129
|
|
|
130
130
|
:::tip Switching UI libraries
|
|
131
|
-
Same component API across Angular packages.
|
|
131
|
+
Same component API across Angular packages. Change the import:
|
|
132
132
|
|
|
133
133
|
- **Radix (CDK)**: `from '@alaarab/ogrid-angular-radix'` *(default, lightweight)*
|
|
134
134
|
- **Angular Material**: `from '@alaarab/ogrid-angular-material'`
|
|
@@ -180,10 +180,10 @@ const gridProps = {
|
|
|
180
180
|
```
|
|
181
181
|
|
|
182
182
|
:::tip Switching UI libraries
|
|
183
|
-
Same
|
|
183
|
+
Same API across Vue packages. Change the import:
|
|
184
184
|
|
|
185
185
|
- **Radix (Headless UI)**: `from '@alaarab/ogrid-vue-radix'` *(default, lightweight)*
|
|
186
|
-
- **Vuetify**: `from '@alaarab/ogrid-vue-vuetify'`
|
|
186
|
+
- **Vuetify**: `from '@alaarab/ogrid-vue-vuetify'` - wrap in `<v-app>` for theming
|
|
187
187
|
- **PrimeVue**: `from '@alaarab/ogrid-vue-primevue'`
|
|
188
188
|
:::
|
|
189
189
|
|
|
@@ -229,7 +229,6 @@ const grid = new OGrid(document.getElementById('grid'), {
|
|
|
229
229
|
editable: true,
|
|
230
230
|
});
|
|
231
231
|
|
|
232
|
-
// Listen for cell edits
|
|
233
232
|
grid.on('cellValueChanged', (event) => {
|
|
234
233
|
console.log(`${event.columnId} changed to ${event.newValue}`);
|
|
235
234
|
});
|
|
@@ -238,22 +237,28 @@ grid.on('cellValueChanged', (event) => {
|
|
|
238
237
|
</TabItem>
|
|
239
238
|
</Tabs>
|
|
240
239
|
|
|
241
|
-
|
|
240
|
+
That single setup gives you inline editing, clipboard paste, fill handle, and full undo/redo.
|
|
241
|
+
|
|
242
|
+
## Editing a cell
|
|
243
|
+
|
|
244
|
+
Double-click or press **F2** to open the editor. When you're done:
|
|
242
245
|
|
|
243
|
-
|
|
246
|
+
- **Enter** — saves and moves focus down
|
|
247
|
+
- **Tab** — saves and moves focus right
|
|
248
|
+
- **Escape** — cancels, restores the original value
|
|
244
249
|
|
|
245
|
-
|
|
250
|
+
### Which editor should I use?
|
|
246
251
|
|
|
247
|
-
|
|
252
|
+
| `cellEditor` | When to use it |
|
|
253
|
+
|--------------|----------------|
|
|
254
|
+
| `'text'` (default) | Freeform text — names, notes, anything open-ended |
|
|
255
|
+
| `'select'` | Small, fixed list where the user picks exactly one value |
|
|
256
|
+
| `'richSelect'` | Longer list with keyboard search — much nicer UX than a plain dropdown |
|
|
257
|
+
| `'checkbox'` | Boolean toggle — renders as a checkbox, commits on click |
|
|
248
258
|
|
|
249
|
-
|
|
250
|
-
|--------------|-------------|
|
|
251
|
-
| `'text'` (default) | Standard text input |
|
|
252
|
-
| `'select'` | Dropdown from `cellEditorParams.values` |
|
|
253
|
-
| `'checkbox'` | Toggle boolean |
|
|
254
|
-
| `'richSelect'` | Searchable dropdown with keyboard nav |
|
|
259
|
+
### Searchable dropdown (richSelect)
|
|
255
260
|
|
|
256
|
-
|
|
261
|
+
When your list gets longer than about 8 items, switch to `richSelect`. It adds a search box and full keyboard navigation:
|
|
257
262
|
|
|
258
263
|
```tsx
|
|
259
264
|
{
|
|
@@ -261,21 +266,25 @@ Double-click or press **F2** to edit. **Enter** commits and moves down, **Tab**
|
|
|
261
266
|
editable: true,
|
|
262
267
|
cellEditor: 'richSelect',
|
|
263
268
|
cellEditorParams: {
|
|
264
|
-
values: ['Engineering', 'Design', 'Marketing', 'Sales'],
|
|
265
|
-
formatValue: (v) => `Dept: ${v}`,
|
|
269
|
+
values: ['Engineering', 'Design', 'Marketing', 'Sales', 'Legal', 'Finance'],
|
|
270
|
+
formatValue: (v) => `Dept: ${v}`, // optional display formatting
|
|
266
271
|
},
|
|
267
272
|
}
|
|
268
273
|
```
|
|
269
274
|
|
|
270
|
-
###
|
|
275
|
+
### Lock specific rows from editing
|
|
276
|
+
|
|
277
|
+
Use a function for `editable` to make it conditional:
|
|
271
278
|
|
|
272
279
|
```tsx
|
|
273
280
|
{ columnId: 'name', editable: (item) => item.status !== 'locked' }
|
|
274
281
|
```
|
|
275
282
|
|
|
276
|
-
|
|
283
|
+
The cell still renders normally — it just won't open an editor when you click it.
|
|
284
|
+
|
|
285
|
+
### Custom editor (popup)
|
|
277
286
|
|
|
278
|
-
|
|
287
|
+
For date pickers, color pickers, or any custom UI, pass your own component. Set `cellEditorPopup: true` to render it in a floating popover instead of inline:
|
|
279
288
|
|
|
280
289
|
```tsx
|
|
281
290
|
function DateEditor({ value, onValueChange, onCommit, onCancel }: ICellEditorProps<Task>) {
|
|
@@ -297,12 +306,15 @@ function DateEditor({ value, onValueChange, onCommit, onCancel }: ICellEditorPro
|
|
|
297
306
|
{ columnId: 'dueDate', editable: true, cellEditor: DateEditor, cellEditorPopup: true }
|
|
298
307
|
```
|
|
299
308
|
|
|
300
|
-
###
|
|
309
|
+
### Validating input with `valueParser`
|
|
301
310
|
|
|
302
|
-
`valueParser`
|
|
311
|
+
`valueParser` runs on every edit, paste, fill, and delete. Return `undefined` to silently reject the value — the cell snaps back to its previous state:
|
|
303
312
|
|
|
304
313
|
```tsx
|
|
305
|
-
{
|
|
314
|
+
{
|
|
315
|
+
columnId: 'age',
|
|
316
|
+
editable: true,
|
|
317
|
+
type: 'numeric',
|
|
306
318
|
valueParser: ({ newValue }) => {
|
|
307
319
|
const num = Number(newValue);
|
|
308
320
|
return isNaN(num) || num < 0 || num > 150 ? undefined : num;
|
|
@@ -310,68 +322,66 @@ function DateEditor({ value, onValueChange, onCommit, onCancel }: ICellEditorPro
|
|
|
310
322
|
}
|
|
311
323
|
```
|
|
312
324
|
|
|
325
|
+
:::tip Pro tip
|
|
326
|
+
`valueParser` is your single source of truth for validation — it runs on inline edits, clipboard paste, fill handle, and delete. You don't need separate logic for each.
|
|
327
|
+
:::
|
|
328
|
+
|
|
313
329
|
## Clipboard
|
|
314
330
|
|
|
315
331
|
<ClipboardDemo />
|
|
316
332
|
|
|
317
|
-
Standard
|
|
333
|
+
Standard shortcuts work on any selection — no configuration needed:
|
|
318
334
|
|
|
319
335
|
| Key | Action | Requires `editable` |
|
|
320
336
|
|-----|--------|-------------------|
|
|
321
|
-
| Ctrl+C
|
|
322
|
-
| Ctrl+V
|
|
323
|
-
| Ctrl+X
|
|
337
|
+
| Ctrl+C / Cmd+C | Copy as tab-separated text | No |
|
|
338
|
+
| Ctrl+V / Cmd+V | Paste into cells | Yes |
|
|
339
|
+
| Ctrl+X / Cmd+X | Cut (copy then clear) | Yes |
|
|
324
340
|
| Delete / Backspace | Clear selected cells | Yes |
|
|
325
341
|
|
|
326
|
-
|
|
327
|
-
- **Paste** calls `valueParser` on each value and fires `onCellValueChanged` per cell.
|
|
342
|
+
Copy respects `valueFormatter` — what you see is what you get in the clipboard. Paste calls `valueParser` on each value, so bad data is rejected before it lands in your rows.
|
|
328
343
|
|
|
329
|
-
## Fill
|
|
344
|
+
## Fill handle
|
|
330
345
|
|
|
331
346
|
<FillHandleDemo />
|
|
332
347
|
|
|
333
|
-
|
|
348
|
+
The small square in the bottom-right corner of a selection — drag it down to fill cells. Works exactly like Excel. Each filled cell goes through `valueParser`, so validation still applies.
|
|
334
349
|
|
|
335
|
-
|
|
336
|
-
|
|
337
|
-
|
|
338
|
-
- Uses `requestAnimationFrame` for smooth drag performance.
|
|
350
|
+
:::tip Pro tip
|
|
351
|
+
Select a range of cells before dragging the fill handle to populate multiple columns at once. The fill handle uses `requestAnimationFrame` internally, so it stays smooth even on large selections.
|
|
352
|
+
:::
|
|
339
353
|
|
|
340
354
|
## Undo / Redo
|
|
341
355
|
|
|
342
|
-
The `useUndoRedo` hook tracks
|
|
343
|
-
|
|
344
|
-
| Hook Input | Type | Description |
|
|
345
|
-
|------------|------|-------------|
|
|
346
|
-
| `data` | `T[]` | Current data array |
|
|
347
|
-
| `setData` | `(data: T[]) => void` | State setter |
|
|
348
|
-
| `getRowId` | `(item: T) => RowId` | Row identifier |
|
|
356
|
+
The `useUndoRedo` hook (React) tracks everything: inline edits, paste, fill, and delete. Ctrl+Z / Ctrl+Y work out of the box, and you can wire up buttons too:
|
|
349
357
|
|
|
350
|
-
|
|
351
|
-
|
|
352
|
-
|
|
353
|
-
|
|
354
|
-
|
|
358
|
+
```tsx
|
|
359
|
+
const { handleCellValueChanged, undo, redo, canUndo, canRedo } = useUndoRedo({
|
|
360
|
+
data,
|
|
361
|
+
setData,
|
|
362
|
+
getRowId: (item) => item.id,
|
|
363
|
+
});
|
|
364
|
+
```
|
|
355
365
|
|
|
356
|
-
|
|
366
|
+
Pass `handleCellValueChanged` as `onCellValueChanged` — it intercepts changes and pushes them onto the undo stack before updating your state. Undo/redo are also available in the right-click [context menu](./context-menu).
|
|
357
367
|
|
|
358
|
-
## Props
|
|
368
|
+
## Props reference
|
|
359
369
|
|
|
360
370
|
| Prop | Type | Description |
|
|
361
371
|
|------|------|-------------|
|
|
362
372
|
| `editable` | `boolean` | Enable editing grid-wide (on `OGrid`) |
|
|
363
|
-
| `editable` | `boolean \| (item: T) => boolean` | Per-column/row (on `IColumnDef`) |
|
|
364
|
-
| `cellEditor` | `'text' \| 'select' \| 'checkbox' \| 'richSelect' \| ComponentType` | Editor
|
|
365
|
-
| `cellEditorPopup` | `boolean` | Render
|
|
373
|
+
| `editable` | `boolean \| (item: T) => boolean` | Per-column/row editability (on `IColumnDef`) |
|
|
374
|
+
| `cellEditor` | `'text' \| 'select' \| 'checkbox' \| 'richSelect' \| ComponentType` | Editor to use |
|
|
375
|
+
| `cellEditorPopup` | `boolean` | Render editor in a floating popover |
|
|
366
376
|
| `cellEditorParams` | `CellEditorParams` | Editor parameters (e.g., `{ values: [...] }`) |
|
|
367
|
-
| `valueParser` | `(params) => unknown` | Validate on edit
|
|
368
|
-
| `valueFormatter` | `(value, item) => string` | Format display
|
|
369
|
-
| `onCellValueChanged` | `(event) => void` |
|
|
377
|
+
| `valueParser` | `(params) => unknown` | Validate/transform on edit, paste, fill, delete. Return `undefined` to reject. |
|
|
378
|
+
| `valueFormatter` | `(value, item) => string` | Format value for display and clipboard copy |
|
|
379
|
+
| `onCellValueChanged` | `(event) => void` | Fires after any cell value change |
|
|
370
380
|
| `onUndo` / `onRedo` | `() => void` | Undo/redo callbacks |
|
|
371
381
|
| `canUndo` / `canRedo` | `boolean` | Enable/disable undo/redo in context menu |
|
|
372
382
|
|
|
373
|
-
##
|
|
383
|
+
## Next steps
|
|
374
384
|
|
|
375
|
-
- [Spreadsheet Selection](./spreadsheet-selection)
|
|
376
|
-
- [Context Menu](./context-menu)
|
|
377
|
-
- [
|
|
385
|
+
- [Spreadsheet Selection](./spreadsheet-selection) — select ranges before editing or pasting
|
|
386
|
+
- [Context Menu](./context-menu) — right-click to undo, copy, and more
|
|
387
|
+
- [Formulas](./formulas) — formula-aware editing with `=SUM(A1:A5)` syntax
|