@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.
Files changed (45) hide show
  1. package/README.md +6 -51
  2. package/bundled-docs/api/README.md +11 -11
  3. package/bundled-docs/api/components-column-chooser.mdx +21 -21
  4. package/bundled-docs/api/components-column-header-filter.mdx +23 -23
  5. package/bundled-docs/api/components-datagrid-table.mdx +27 -27
  6. package/bundled-docs/api/components-pagination-controls.mdx +21 -21
  7. package/bundled-docs/api/components-sidebar.mdx +27 -27
  8. package/bundled-docs/api/components-status-bar.mdx +12 -12
  9. package/bundled-docs/api/js-api.mdx +13 -13
  10. package/bundled-docs/api/types.mdx +4 -4
  11. package/bundled-docs/features/column-chooser.mdx +4 -4
  12. package/bundled-docs/features/column-groups.mdx +4 -4
  13. package/bundled-docs/features/column-pinning.mdx +5 -5
  14. package/bundled-docs/features/column-reordering.mdx +5 -5
  15. package/bundled-docs/features/column-types.mdx +7 -7
  16. package/bundled-docs/features/context-menu.mdx +4 -4
  17. package/bundled-docs/features/csv-export.mdx +4 -4
  18. package/bundled-docs/features/editing.mdx +78 -68
  19. package/bundled-docs/features/filtering.mdx +83 -67
  20. package/bundled-docs/features/formulas.mdx +135 -139
  21. package/bundled-docs/features/grid-api.mdx +4 -4
  22. package/bundled-docs/features/keyboard-navigation.mdx +6 -6
  23. package/bundled-docs/features/mobile-touch.mdx +9 -9
  24. package/bundled-docs/features/pagination.mdx +4 -4
  25. package/bundled-docs/features/performance.mdx +97 -100
  26. package/bundled-docs/features/premium-inputs.mdx +579 -0
  27. package/bundled-docs/features/responsive-columns.mdx +1 -1
  28. package/bundled-docs/features/row-selection.mdx +8 -8
  29. package/bundled-docs/features/server-side-data.mdx +4 -4
  30. package/bundled-docs/features/sidebar.mdx +6 -6
  31. package/bundled-docs/features/sorting.mdx +87 -44
  32. package/bundled-docs/features/spreadsheet-selection.mdx +9 -9
  33. package/bundled-docs/features/status-bar.mdx +4 -4
  34. package/bundled-docs/features/toolbar.mdx +9 -9
  35. package/bundled-docs/features/virtual-scrolling.mdx +13 -13
  36. package/bundled-docs/getting-started/overview.mdx +9 -9
  37. package/bundled-docs/getting-started/quick-start.mdx +47 -47
  38. package/bundled-docs/getting-started/vanilla-js.mdx +98 -74
  39. package/bundled-docs/guides/accessibility.mdx +113 -421
  40. package/bundled-docs/guides/framework-showcase.mdx +98 -52
  41. package/bundled-docs/guides/mcp-live-testing.mdx +12 -12
  42. package/bundled-docs/guides/mcp.mdx +47 -46
  43. package/dist/esm/bridge-client.d.ts +3 -3
  44. package/dist/esm/index.js +9 -9
  45. 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`the framework-free data grid.
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 gridremoves DOM, listeners, and ResizeObservers. |
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[]` || Client-side data. Mutually exclusive with `dataSource`. |
47
- | `dataSource` | `IDataSource<T>` || Server-side data source. Mutually exclusive with `data`. |
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' }` || Initial sort state. |
56
- | `filters` | `IFilters` || Initial filter state. |
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'` || Row checkbox selection mode. |
65
- | `selectedRows` | `Set<RowId>` || Controlled selected row IDs. |
66
- | `pinnedColumns` | `Record<string, 'left' \| 'right'>` || Pin columns to left/right edges. |
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` || Show sidebar with columns/filters panels. |
75
+ | `sideBar` | `boolean \| ISideBarDef` | - | Show sidebar with columns/filters panels. |
76
76
  | `emptyMessage` | `string` | `'No data'` | Custom empty state text. |
77
- | `aria-label` | `string` || Accessible label for the grid. |
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 renderermutate the `<td>` DOM directly. |
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 versionsee [Column Definitions](./column-def).
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 (fieldFilterValue). |
311
+ | `filters` | `IFilters` | Active filters (field to FilterValue). |
312
312
 
313
313
  ### IPageResult&lt;T&gt;
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 IDwidth). |
541
- | `filters` | `IFilters` | Active filters (fieldFilterValue). |
542
- | `pinnedColumns` | `Record<string, 'left' \| 'right'>` | Pinned columns (column IDposition). |
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'`wrap in `<FluentProvider>`
68
- - **Material UI** (MUI v7): `from '@alaarab/ogrid-react-material'`wrap in `<ThemeProvider>`
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 standaloneno NgModule required.
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'`wrap in `<v-app>` for theming
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'`wrap in `<FluentProvider>`
78
- - **Material UI** (MUI v7): `from '@alaarab/ogrid-react-material'`wrap in `<ThemeProvider>`
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 standaloneno NgModule required.
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'`wrap in `<v-app>` for theming
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'`wrap in `<FluentProvider>`
71
- - **Material UI** (MUI v7): `from '@alaarab/ogrid-react-material'`wrap in `<ThemeProvider>`
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 standaloneno NgModule required.
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'`wrap in `<v-app>` for theming
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{ name: 'left' }
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'`wrap in `<FluentProvider>`
63
- - **Material UI** (MUI v7): `from '@alaarab/ogrid-react-material'`wrap in `<ThemeProvider>`
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 standaloneno NgModule required.
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'`wrap in `<v-app>` for theming
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['name', 'department', 'email', 'salary', 'status']
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 patternstext, numeric, date, and boolean.
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 || `True` / `False` |
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'`wrap in `<FluentProvider>`
66
- - **Material UI** (MUI v7): `from '@alaarab/ogrid-react-material'`wrap in `<ThemeProvider>`
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 standaloneno NgModule required.
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'`wrap in `<v-app>` for theming
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 optionalyou can filter by "after", "before", or a range.
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'`wrap in `<FluentProvider>`
54
- - **Material UI** (MUI v7): `from '@alaarab/ogrid-react-material'`wrap in `<ThemeProvider>`
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 standaloneno NgModule required.
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'`wrap in `<v-app>` for theming
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'`wrap in `<FluentProvider>`
51
- - **Material UI** (MUI v7): `from '@alaarab/ogrid-react-material'`wrap in `<ThemeProvider>`
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 standaloneno NgModule required.
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'`wrap in `<v-app>` for theming
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
- OGrid supports inline cell editing, clipboard copy/paste, drag-to-fill, and undo/redo -- all working together through `onCellValueChanged` and `valueParser`.
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. To see this feature with your framework's design system (Fluent UI, Material UI, Vuetify, PrimeNG, etc.), click **"Open in online demo"** below the demo.
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
- ## Quick Example
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 invalid
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
- The `OGrid` component has the same props across all React UI packages. To switch, just change the import:
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'`wrap in `<FluentProvider>`
86
- - **Material UI** (MUI v7): `from '@alaarab/ogrid-react-material'`wrap in `<ThemeProvider>`
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. To switch, just change the import:
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 component API across Vue packages. To switch, just change the import:
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'`wrap in `<v-app>` for theming
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
- This single setup gives you inline editing, clipboard paste, fill handle, and full undo/redo.
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
- ## Inline Editing
246
+ - **Enter** — saves and moves focus down
247
+ - **Tab** — saves and moves focus right
248
+ - **Escape** — cancels, restores the original value
244
249
 
245
- Double-click or press **F2** to edit. **Enter** commits and moves down, **Tab** commits and moves right, **Escape** cancels.
250
+ ### Which editor should I use?
246
251
 
247
- ### Built-in Editors
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
- | `cellEditor` | Description |
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
- ### Rich Select
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
- ### Per-Row Editability
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
- ### Custom Editor
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
- Pass a component to `cellEditor`. Use `cellEditorPopup: true` for a popover:
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
- ### Value Parsing
309
+ ### Validating input with `valueParser`
301
310
 
302
- `valueParser` validates input for editing, paste, fill, and delete. Return `undefined` to reject:
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
- { columnId: 'age', editable: true, type: 'numeric',
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 keyboard shortcuts on selected cells:
333
+ Standard shortcuts work on any selection — no configuration needed:
318
334
 
319
335
  | Key | Action | Requires `editable` |
320
336
  |-----|--------|-------------------|
321
- | Ctrl+C (Cmd+C) | Copy as tab-delimited text | No |
322
- | Ctrl+V (Cmd+V) | Paste into cells | Yes |
323
- | Ctrl+X (Cmd+X) | Cut (copy + clear) | Yes |
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
- - **Copy** uses `valueFormatter` so copied values match the display.
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 Handle
344
+ ## Fill handle
330
345
 
331
346
  <FillHandleDemo />
332
347
 
333
- A small square at the bottom-right of the selection. Drag it down to fill cells with the source value (like Excel).
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
- - Requires `editable={true}` and `cellSelection={true}` (default).
336
- - Calls `valueParser` per cell -- return `undefined` to skip.
337
- - Each filled cell fires `onCellValueChanged`.
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 edit history (including paste, fill, and delete). See the quick example above.
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
- | Hook Output | Type | Description |
351
- |-------------|------|-------------|
352
- | `handleCellValueChanged` | `(event) => void` | Wraps edits onto the undo stack |
353
- | `undo` / `redo` | `() => void` | Revert / re-apply |
354
- | `canUndo` / `canRedo` | `boolean` | Stack status |
358
+ ```tsx
359
+ const { handleCellValueChanged, undo, redo, canUndo, canRedo } = useUndoRedo({
360
+ data,
361
+ setData,
362
+ getRowId: (item) => item.id,
363
+ });
364
+ ```
355
365
 
356
- **Shortcuts:** Ctrl+Z (undo), Ctrl+Y (redo). Also available in the right-click [context menu](./context-menu).
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 Summary
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 type |
365
- | `cellEditorPopup` | `boolean` | Render custom editor in a popover |
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/paste/fill/delete. Return `undefined` to reject. |
368
- | `valueFormatter` | `(value, item) => string` | Format display & copy output |
369
- | `onCellValueChanged` | `(event) => void` | Fired after any cell value change |
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
- ## Related
383
+ ## Next steps
374
384
 
375
- - [Spreadsheet Selection](./spreadsheet-selection) -- select cells for editing
376
- - [Context Menu](./context-menu) -- right-click menu with undo/redo
377
- - [Custom Cell Editors](../guides/custom-cell-editors) -- advanced editor guide
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