@alaarab/ogrid-mcp 2.5.8 → 2.5.9
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/components-column-chooser.mdx +1 -1
- package/bundled-docs/api/components-column-header-filter.mdx +1 -1
- package/bundled-docs/api/components-datagrid-table.mdx +1 -1
- package/bundled-docs/api/components-pagination-controls.mdx +1 -1
- package/bundled-docs/api/components-sidebar.mdx +1 -1
- package/bundled-docs/api/components-status-bar.mdx +1 -1
- package/bundled-docs/features/cell-references.mdx +9 -9
- package/bundled-docs/features/column-chooser.mdx +1 -4
- package/bundled-docs/features/column-groups.mdx +3 -10
- package/bundled-docs/features/column-pinning.mdx +3 -7
- package/bundled-docs/features/column-reordering.mdx +4 -6
- package/bundled-docs/features/column-types.mdx +1 -1
- package/bundled-docs/features/context-menu.mdx +4 -8
- package/bundled-docs/features/csv-export.mdx +7 -7
- package/bundled-docs/features/editing.mdx +21 -21
- package/bundled-docs/features/filtering.mdx +15 -15
- package/bundled-docs/features/formulas.mdx +27 -27
- package/bundled-docs/features/grid-api.mdx +2 -2
- package/bundled-docs/features/keyboard-navigation.mdx +5 -5
- package/bundled-docs/features/pagination.mdx +1 -1
- package/bundled-docs/getting-started/overview.mdx +3 -6
- package/bundled-docs/getting-started/quick-start.mdx +11 -11
- package/bundled-docs/getting-started/vanilla-js.mdx +16 -16
- package/bundled-docs/guides/accessibility.mdx +11 -11
- package/bundled-docs/guides/framework-showcase.mdx +16 -16
- package/bundled-docs/guides/mcp.mdx +9 -9
- package/package.json +1 -1
|
@@ -226,7 +226,7 @@ The trigger button shows the current visibility count: `"Column Visibility (3 of
|
|
|
226
226
|
|
|
227
227
|
## Accessibility
|
|
228
228
|
|
|
229
|
-
`ColumnChooser`
|
|
229
|
+
`ColumnChooser` meets WCAG 2.1 AA with full keyboard and screen reader support.
|
|
230
230
|
|
|
231
231
|
### ARIA Attributes
|
|
232
232
|
|
|
@@ -258,7 +258,7 @@ const handleFilterChange = (values: string[]) => {
|
|
|
258
258
|
|
|
259
259
|
## Accessibility
|
|
260
260
|
|
|
261
|
-
`ColumnHeaderFilter`
|
|
261
|
+
`ColumnHeaderFilter` meets WCAG 2.1 AA with full keyboard and screen reader support.
|
|
262
262
|
|
|
263
263
|
### ARIA Attributes
|
|
264
264
|
|
|
@@ -183,7 +183,7 @@ In Vue Radix, `DataGridTable` uses individual props via `defineProps<IOGridProps
|
|
|
183
183
|
|
|
184
184
|
## Accessibility
|
|
185
185
|
|
|
186
|
-
`DataGridTable`
|
|
186
|
+
`DataGridTable` meets WCAG 2.1 AA with full keyboard navigation and screen reader support.
|
|
187
187
|
|
|
188
188
|
### ARIA Attributes
|
|
189
189
|
|
|
@@ -249,7 +249,7 @@ Showing {startItem} to {endItem} of {totalCount} {entityLabelPlural}
|
|
|
249
249
|
|
|
250
250
|
## Accessibility
|
|
251
251
|
|
|
252
|
-
`PaginationControls`
|
|
252
|
+
`PaginationControls` meets WCAG 2.1 AA with full keyboard and screen reader support.
|
|
253
253
|
|
|
254
254
|
### ARIA Attributes
|
|
255
255
|
|
|
@@ -303,7 +303,7 @@ The panel content area has a fixed width (240px) and scrollable content. The pan
|
|
|
303
303
|
|
|
304
304
|
## Accessibility
|
|
305
305
|
|
|
306
|
-
`SideBar`
|
|
306
|
+
`SideBar` meets WCAG 2.1 AA with full keyboard and screen reader support.
|
|
307
307
|
|
|
308
308
|
### ARIA Attributes
|
|
309
309
|
|
|
@@ -237,7 +237,7 @@ When `statusBar` is `true`, the grid automatically computes the counts from the
|
|
|
237
237
|
|
|
238
238
|
## Accessibility
|
|
239
239
|
|
|
240
|
-
`StatusBar`
|
|
240
|
+
`StatusBar` meets WCAG 2.1 AA with screen reader support for dynamic content announcements.
|
|
241
241
|
|
|
242
242
|
### ARIA Attributes
|
|
243
243
|
|
|
@@ -171,13 +171,13 @@ const grid = new OGrid(document.getElementById('grid'), {
|
|
|
171
171
|
</TabItem>
|
|
172
172
|
</Tabs>
|
|
173
173
|
|
|
174
|
-
## How
|
|
174
|
+
## How it works
|
|
175
175
|
|
|
176
|
-
|
|
176
|
+
`cellReferences` turns on three things at once:
|
|
177
177
|
|
|
178
|
-
### 1. Column
|
|
178
|
+
### 1. Column letter headers
|
|
179
179
|
|
|
180
|
-
A row of Excel-style column letters (A, B, C, ..., Z, AA, AB, ...) appears above the normal header row.
|
|
180
|
+
A row of Excel-style column letters (A, B, C, ..., Z, AA, AB, ...) appears above the normal header row. They use base-26 encoding:
|
|
181
181
|
|
|
182
182
|
| Columns | Letters |
|
|
183
183
|
|---------|---------|
|
|
@@ -186,9 +186,9 @@ A row of Excel-style column letters (A, B, C, ..., Z, AA, AB, ...) appears above
|
|
|
186
186
|
| 53--78 | BA--BZ |
|
|
187
187
|
| 703+ | AAA, AAB, ... |
|
|
188
188
|
|
|
189
|
-
### 2. Row
|
|
189
|
+
### 2. Row numbers
|
|
190
190
|
|
|
191
|
-
A numbered gutter column
|
|
191
|
+
A numbered gutter column on the left shows the absolute row number (1, 2, 3, ...). Numbers are consistent across pages -- page 2 with a page size of 25 starts at row 26, not row 1.
|
|
192
192
|
|
|
193
193
|
:::info Row numbers without cell references
|
|
194
194
|
You can show row numbers independently without the full cell references feature by using the `showRowNumbers` prop:
|
|
@@ -205,11 +205,11 @@ You can show row numbers independently without the full cell references feature
|
|
|
205
205
|
This gives you the numbered gutter column without column letters or the name box.
|
|
206
206
|
:::
|
|
207
207
|
|
|
208
|
-
### 3. Name
|
|
208
|
+
### 3. Name box
|
|
209
209
|
|
|
210
|
-
A
|
|
210
|
+
A read-only field in the toolbar shows the active cell reference (e.g. "A1", "C15"). It updates on click or keyboard navigation.
|
|
211
211
|
|
|
212
|
-
The name box uses the
|
|
212
|
+
The name box uses the absolute row number, so clicking the third column on row 5 of page 2 (page size 10) shows "C15", not "C5".
|
|
213
213
|
|
|
214
214
|
## Props
|
|
215
215
|
|
|
@@ -201,10 +201,7 @@ const grid = new OGrid(document.getElementById('grid'), {
|
|
|
201
201
|
</TabItem>
|
|
202
202
|
</Tabs>
|
|
203
203
|
|
|
204
|
-
|
|
205
|
-
- **Name** is always visible (cannot be unchecked because `required: true`).
|
|
206
|
-
- **Age** and **Start Date** are hidden by default but the user can enable them.
|
|
207
|
-
- **Email**, **Department**, and **Salary** are visible by default and can be toggled.
|
|
204
|
+
Name is always visible (`required: true` locks its checkbox). Age and Start Date are hidden by default but users can show them. Email, Department, and Salary are visible by default and can be toggled.
|
|
208
205
|
|
|
209
206
|
## How It Works
|
|
210
207
|
|
|
@@ -217,9 +217,9 @@ const grid = new OGrid(document.getElementById('grid'), {
|
|
|
217
217
|
|
|
218
218
|
This renders a two-row header: the first row shows "Personal Info" spanning three columns and "Employment" spanning three columns, with the individual column names in the second row.
|
|
219
219
|
|
|
220
|
-
## How
|
|
220
|
+
## How it works
|
|
221
221
|
|
|
222
|
-
Column groups use the `IColumnGroupDef<T>` type. A group has a `headerName`
|
|
222
|
+
Column groups use the `IColumnGroupDef<T>` type. A group has a `headerName` and a `children` array that can contain `IColumnDef` items or nested `IColumnGroupDef` items.
|
|
223
223
|
|
|
224
224
|
```tsx
|
|
225
225
|
// IColumnGroupDef<T>
|
|
@@ -267,14 +267,7 @@ Standalone `IColumnDef` items at the top level are valid alongside groups. They
|
|
|
267
267
|
|
|
268
268
|
## Group Header Behavior
|
|
269
269
|
|
|
270
|
-
Group headers are display-only
|
|
271
|
-
|
|
272
|
-
- **Not sortable.** Clicking a group header does nothing.
|
|
273
|
-
- **Not filterable.** No filter icon or popover appears on group headers.
|
|
274
|
-
- **Not resizable.** Group headers cannot be dragged to resize.
|
|
275
|
-
- **Centered text.** Group header labels are centered over their children by default.
|
|
276
|
-
|
|
277
|
-
Sorting, filtering, and resizing remain available on the leaf column headers beneath the groups.
|
|
270
|
+
Group headers are display-only. Clicking them does nothing -- no sort, no filter icon, no resize handle. Labels are centered over their children by default. Sorting, filtering, and resizing all work normally on the leaf column headers below.
|
|
278
271
|
|
|
279
272
|
## Props Reference
|
|
280
273
|
|
|
@@ -182,19 +182,15 @@ const grid = new OGrid(document.getElementById('grid'), {
|
|
|
182
182
|
|
|
183
183
|
The "Name" column stays fixed on the left while all other columns scroll normally.
|
|
184
184
|
|
|
185
|
-
## How
|
|
185
|
+
## How it works
|
|
186
186
|
|
|
187
|
-
Set `pinned: 'left'` on any `IColumnDef
|
|
187
|
+
Set `pinned: 'left'` on any `IColumnDef`. The grid uses CSS `position: sticky` with a calculated `left` offset so multiple pinned columns stack correctly.
|
|
188
188
|
|
|
189
189
|
```tsx
|
|
190
190
|
{ columnId: 'name', name: 'Name', pinned: 'left' }
|
|
191
191
|
```
|
|
192
192
|
|
|
193
|
-
Pinned columns:
|
|
194
|
-
|
|
195
|
-
- Use **sticky positioning** so they stay visible during horizontal scroll.
|
|
196
|
-
- Stack left-to-right in the order they appear in the `columns` array.
|
|
197
|
-
- Work with all grid features: sorting, filtering, editing, cell selection, and context menu.
|
|
193
|
+
Pinned columns use sticky positioning, stack in the order they appear in the `columns` array, and work with all features: sorting, filtering, editing, cell selection, and context menu.
|
|
198
194
|
|
|
199
195
|
### With Row Selection
|
|
200
196
|
|
|
@@ -170,9 +170,9 @@ const grid = new OGrid(document.getElementById('grid'), {
|
|
|
170
170
|
|
|
171
171
|
Drag any column header to rearrange it. A vertical indicator line shows where the column will be placed.
|
|
172
172
|
|
|
173
|
-
## How
|
|
173
|
+
## How it works
|
|
174
174
|
|
|
175
|
-
Set `columnReorder` to `true
|
|
175
|
+
Set `columnReorder` to `true`. When a user drags a column header at least 5 pixels horizontally, the grid enters reorder mode:
|
|
176
176
|
|
|
177
177
|
1. A vertical drop indicator appears between columns as the user drags.
|
|
178
178
|
2. On mouse-up, the column is moved to the target position.
|
|
@@ -300,11 +300,9 @@ const columns = [
|
|
|
300
300
|
|
|
301
301
|
In this example, "ID" and "Name" can be swapped with each other but cannot be dragged into the unpinned section. The unpinned columns ("Email", "Department", "Salary") can be freely rearranged among themselves.
|
|
302
302
|
|
|
303
|
-
### Edge
|
|
303
|
+
### Edge cases
|
|
304
304
|
|
|
305
|
-
|
|
306
|
-
- **Resize handle zone:** The rightmost 8 pixels of each header cell are reserved for column resizing. Dragging in that zone starts a resize, not a reorder.
|
|
307
|
-
- **Minimum drag distance:** A 5-pixel horizontal threshold prevents accidental reorders from clicks.
|
|
305
|
+
Group headers are not draggable -- only leaf columns with a `columnId` can be reordered. The rightmost 8 pixels of each header cell are reserved for column resizing, so dragging there starts a resize instead. The 5-pixel horizontal threshold prevents accidental reorders from ordinary clicks.
|
|
308
306
|
|
|
309
307
|
## Grid API
|
|
310
308
|
|
|
@@ -150,9 +150,9 @@ const grid = new OGrid(document.getElementById('grid'), {
|
|
|
150
150
|
|
|
151
151
|
Right-click a cell to see the context menu with all available actions.
|
|
152
152
|
|
|
153
|
-
## How
|
|
153
|
+
## How it works
|
|
154
154
|
|
|
155
|
-
The context menu is built in
|
|
155
|
+
The context menu is built in. It appears on data cell right-clicks -- no configuration needed.
|
|
156
156
|
|
|
157
157
|
### Built-in Menu Items
|
|
158
158
|
|
|
@@ -187,13 +187,9 @@ The Undo and Redo items reflect their availability through the `canUndo` and `ca
|
|
|
187
187
|
|
|
188
188
|
If `onUndo` and `onRedo` are not provided, the undo/redo items still appear but do nothing.
|
|
189
189
|
|
|
190
|
-
### Cell-
|
|
190
|
+
### Cell-only activation
|
|
191
191
|
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
- **Header right-click**: default browser context menu (no grid menu).
|
|
195
|
-
- **Empty space right-click**: default browser context menu.
|
|
196
|
-
- **Cell right-click**: grid context menu with actions scoped to the current selection.
|
|
192
|
+
Right-clicking a header or empty space shows the browser's default context menu. The grid menu only appears on data cell right-clicks, with actions scoped to the current selection.
|
|
197
193
|
|
|
198
194
|
### Copy/Cut Disabled State
|
|
199
195
|
|
|
@@ -156,9 +156,9 @@ document.getElementById('export-btn').addEventListener('click', () => {
|
|
|
156
156
|
</TabItem>
|
|
157
157
|
</Tabs>
|
|
158
158
|
|
|
159
|
-
## How
|
|
159
|
+
## How it works
|
|
160
160
|
|
|
161
|
-
### The `exportToCsv`
|
|
161
|
+
### The `exportToCsv` function
|
|
162
162
|
|
|
163
163
|
```tsx
|
|
164
164
|
exportToCsv<T>(
|
|
@@ -182,11 +182,11 @@ The function:
|
|
|
182
182
|
3. Escapes values containing commas, quotes, or newlines.
|
|
183
183
|
4. Triggers a browser download with the specified filename.
|
|
184
184
|
|
|
185
|
-
### Context
|
|
185
|
+
### Context menu
|
|
186
186
|
|
|
187
|
-
|
|
187
|
+
The context menu doesn't include an "Export to CSV" item. Use `exportToCsv` from a toolbar button or any other UI you control.
|
|
188
188
|
|
|
189
|
-
### Exporting
|
|
189
|
+
### Exporting visible columns only
|
|
190
190
|
|
|
191
191
|
Filter the columns array to only include visible columns before passing to `exportToCsv`.
|
|
192
192
|
|
|
@@ -201,9 +201,9 @@ exportToCsv(
|
|
|
201
201
|
);
|
|
202
202
|
```
|
|
203
203
|
|
|
204
|
-
###
|
|
204
|
+
### Matching display formatting
|
|
205
205
|
|
|
206
|
-
|
|
206
|
+
Apply `valueFormatter` in your `getValue` so the export matches what users see -- a currency column showing "$1,234.56" will export that same string.
|
|
207
207
|
|
|
208
208
|
```tsx
|
|
209
209
|
const getValue = (item: Row, columnId: string) => {
|
|
@@ -7,17 +7,17 @@ description: Inline editing, clipboard operations, fill handle, and undo/redo
|
|
|
7
7
|
|
|
8
8
|
# Editing & Clipboard
|
|
9
9
|
|
|
10
|
-
Double-click a cell to edit it.
|
|
10
|
+
Double-click a cell to edit it. Enter saves, Escape cancels. Clipboard paste, drag-to-fill, and full undo/redo are all included.
|
|
11
11
|
|
|
12
12
|
<CellEditingDemo />
|
|
13
13
|
|
|
14
14
|
:::tip Try it in your framework
|
|
15
|
-
The demo above uses Radix UI for styling. Each framework renders editors with its native components
|
|
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.
|
|
16
16
|
:::
|
|
17
17
|
|
|
18
18
|
## Get started in 5 minutes
|
|
19
19
|
|
|
20
|
-
Here's a realistic setup: an employee table with text, dropdown, and numeric columns
|
|
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>
|
|
@@ -79,7 +79,7 @@ function App() {
|
|
|
79
79
|
```
|
|
80
80
|
|
|
81
81
|
:::tip Switching UI libraries
|
|
82
|
-
Same props across all React packages
|
|
82
|
+
Same props across all React packages -- just change the import:
|
|
83
83
|
|
|
84
84
|
- **Radix** (lightweight, default): `from '@alaarab/ogrid-react-radix'`
|
|
85
85
|
- **Fluent UI** (Microsoft 365 / SPFx): `from '@alaarab/ogrid-react-fluent'` - wrap in `<FluentProvider>`
|
|
@@ -134,7 +134,7 @@ Same component API across Angular packages. Change the import:
|
|
|
134
134
|
- **Angular Material**: `from '@alaarab/ogrid-angular-material'`
|
|
135
135
|
- **PrimeNG**: `from '@alaarab/ogrid-angular-primeng'`
|
|
136
136
|
|
|
137
|
-
All components are standalone
|
|
137
|
+
All components are standalone, no NgModule required.
|
|
138
138
|
:::
|
|
139
139
|
|
|
140
140
|
</TabItem>
|
|
@@ -243,18 +243,18 @@ That single setup gives you inline editing, clipboard paste, fill handle, and fu
|
|
|
243
243
|
|
|
244
244
|
Double-click or press **F2** to open the editor. When you're done:
|
|
245
245
|
|
|
246
|
-
- **Enter**
|
|
247
|
-
- **Tab**
|
|
248
|
-
- **Escape**
|
|
246
|
+
- **Enter** -- saves and moves focus down
|
|
247
|
+
- **Tab** -- saves and moves focus right
|
|
248
|
+
- **Escape** -- cancels, restores the original value
|
|
249
249
|
|
|
250
250
|
### Which editor should I use?
|
|
251
251
|
|
|
252
252
|
| `cellEditor` | When to use it |
|
|
253
253
|
|--------------|----------------|
|
|
254
|
-
| `'text'` (default) | Freeform text
|
|
254
|
+
| `'text'` (default) | Freeform text -- names, notes, anything open-ended |
|
|
255
255
|
| `'select'` | Small, fixed list where the user picks exactly one value |
|
|
256
|
-
| `'richSelect'` | Longer list with keyboard search
|
|
257
|
-
| `'checkbox'` | Boolean toggle
|
|
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 |
|
|
258
258
|
|
|
259
259
|
### Searchable dropdown (richSelect)
|
|
260
260
|
|
|
@@ -280,7 +280,7 @@ Use a function for `editable` to make it conditional:
|
|
|
280
280
|
{ columnId: 'name', editable: (item) => item.status !== 'locked' }
|
|
281
281
|
```
|
|
282
282
|
|
|
283
|
-
The cell still renders normally
|
|
283
|
+
The cell still renders normally. It just won't open an editor when you click it.
|
|
284
284
|
|
|
285
285
|
### Custom editor (popup)
|
|
286
286
|
|
|
@@ -308,7 +308,7 @@ function DateEditor({ value, onValueChange, onCommit, onCancel }: ICellEditorPro
|
|
|
308
308
|
|
|
309
309
|
### Validating input with `valueParser`
|
|
310
310
|
|
|
311
|
-
`valueParser` runs on every edit, paste, fill, and delete. Return `undefined` to silently reject the value
|
|
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:
|
|
312
312
|
|
|
313
313
|
```tsx
|
|
314
314
|
{
|
|
@@ -323,14 +323,14 @@ function DateEditor({ value, onValueChange, onCommit, onCancel }: ICellEditorPro
|
|
|
323
323
|
```
|
|
324
324
|
|
|
325
325
|
:::tip Pro tip
|
|
326
|
-
`valueParser` is your single
|
|
326
|
+
`valueParser` is your single validation point -- it covers inline edits, clipboard paste, fill handle, and delete. You don't need separate logic for each.
|
|
327
327
|
:::
|
|
328
328
|
|
|
329
329
|
## Clipboard
|
|
330
330
|
|
|
331
331
|
<ClipboardDemo />
|
|
332
332
|
|
|
333
|
-
Standard shortcuts work on any selection
|
|
333
|
+
Standard shortcuts work on any selection with no configuration:
|
|
334
334
|
|
|
335
335
|
| Key | Action | Requires `editable` |
|
|
336
336
|
|-----|--------|-------------------|
|
|
@@ -339,13 +339,13 @@ Standard shortcuts work on any selection — no configuration needed:
|
|
|
339
339
|
| Ctrl+X / Cmd+X | Cut (copy then clear) | Yes |
|
|
340
340
|
| Delete / Backspace | Clear selected cells | Yes |
|
|
341
341
|
|
|
342
|
-
Copy respects `valueFormatter
|
|
342
|
+
Copy respects `valueFormatter`, so what you see is what ends up in the clipboard. Paste calls `valueParser` on each value, so bad data is rejected before it lands in your rows.
|
|
343
343
|
|
|
344
344
|
## Fill handle
|
|
345
345
|
|
|
346
346
|
<FillHandleDemo />
|
|
347
347
|
|
|
348
|
-
The small square in the bottom-right corner of a selection
|
|
348
|
+
The small square in the bottom-right corner of a selection. Drag it down to fill cells, just like Excel. Each filled cell goes through `valueParser`, so validation still applies.
|
|
349
349
|
|
|
350
350
|
:::tip Pro tip
|
|
351
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.
|
|
@@ -363,7 +363,7 @@ const { handleCellValueChanged, undo, redo, canUndo, canRedo } = useUndoRedo({
|
|
|
363
363
|
});
|
|
364
364
|
```
|
|
365
365
|
|
|
366
|
-
Pass `handleCellValueChanged` as `onCellValueChanged
|
|
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).
|
|
367
367
|
|
|
368
368
|
## Props reference
|
|
369
369
|
|
|
@@ -382,6 +382,6 @@ Pass `handleCellValueChanged` as `onCellValueChanged` — it intercepts changes
|
|
|
382
382
|
|
|
383
383
|
## Next steps
|
|
384
384
|
|
|
385
|
-
- [Spreadsheet Selection](./spreadsheet-selection)
|
|
386
|
-
- [Context Menu](./context-menu)
|
|
387
|
-
- [Formulas](./formulas)
|
|
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
|
|
@@ -7,12 +7,12 @@ description: Column-level filtering with text, multi-select, date, and people fi
|
|
|
7
7
|
|
|
8
8
|
# Filtering
|
|
9
9
|
|
|
10
|
-
You have 3,000 support tickets and need to find the ones assigned to Alice that were opened last week. Click the filter icon on "Assignee", pick Alice. Click the filter on "Created Date", set the range.
|
|
10
|
+
You have 3,000 support tickets and need to find the ones assigned to Alice that were opened last week. Click the filter icon on "Assignee", pick Alice. Click the filter on "Created Date", set the range. Two clicks, no code.
|
|
11
11
|
|
|
12
12
|
<FilteringDemo />
|
|
13
13
|
|
|
14
14
|
:::tip Framework-Specific Styling
|
|
15
|
-
The demo uses React Radix styling. Each framework renders filter UI with its native components
|
|
15
|
+
The demo uses React Radix styling. Each framework renders filter UI with its native components: dropdowns, date pickers, and inputs that match your design system.
|
|
16
16
|
:::
|
|
17
17
|
|
|
18
18
|
## Add filters to any column
|
|
@@ -61,7 +61,7 @@ function App() {
|
|
|
61
61
|
```
|
|
62
62
|
|
|
63
63
|
:::tip Switching UI libraries
|
|
64
|
-
Same props across all React packages
|
|
64
|
+
Same props across all React packages -- just change the import:
|
|
65
65
|
|
|
66
66
|
- **Radix** (lightweight, default): `from '@alaarab/ogrid-react-radix'`
|
|
67
67
|
- **Fluent UI** (Microsoft 365 / SPFx): `from '@alaarab/ogrid-react-fluent'` - wrap in `<FluentProvider>`
|
|
@@ -109,7 +109,7 @@ Same API across Angular packages. Change the import:
|
|
|
109
109
|
- **Angular Material**: `from '@alaarab/ogrid-angular-material'`
|
|
110
110
|
- **PrimeNG**: `from '@alaarab/ogrid-angular-primeng'`
|
|
111
111
|
|
|
112
|
-
All components are standalone
|
|
112
|
+
All components are standalone, no NgModule required.
|
|
113
113
|
:::
|
|
114
114
|
|
|
115
115
|
</TabItem>
|
|
@@ -203,7 +203,7 @@ Type "john" and it matches "John Smith", "Johnny", and "Johnathan".
|
|
|
203
203
|
|
|
204
204
|
### Multi-select filter
|
|
205
205
|
|
|
206
|
-
A checkbox list
|
|
206
|
+
A checkbox list. Users pick one or more values and the grid shows only matching rows. Has built-in "Select All" and "Clear All" buttons.
|
|
207
207
|
|
|
208
208
|
```tsx
|
|
209
209
|
{
|
|
@@ -223,8 +223,8 @@ A checkbox list — users pick one or more values, the grid shows only matching
|
|
|
223
223
|
| `optionsSource` | How it works |
|
|
224
224
|
|-----------------|----------|
|
|
225
225
|
| _(omitted)_ | Client-side: unique values extracted from your data. Server-side: calls your API. |
|
|
226
|
-
| `'static'` | Uses the `options` array you provide
|
|
227
|
-
| `'api'` | Calls `dataSource.fetchFilterOptions(field)`
|
|
226
|
+
| `'static'` | Uses the `options` array you provide -- great for known enums. |
|
|
227
|
+
| `'api'` | Calls `dataSource.fetchFilterOptions(field)` -- for dynamic option lists. |
|
|
228
228
|
| `'years'` | Auto-generates a year list from the current year down. |
|
|
229
229
|
|
|
230
230
|
### Date filter
|
|
@@ -241,7 +241,7 @@ A date range picker with "From" and "To" inputs. Shows only rows where the colum
|
|
|
241
241
|
```
|
|
242
242
|
|
|
243
243
|
:::tip
|
|
244
|
-
A column with `type: 'date'` automatically gets date formatting, chronological sorting, and a native date input editor
|
|
244
|
+
A column with `type: 'date'` automatically gets date formatting, chronological sorting, and a native date input editor. You don't need to configure those separately.
|
|
245
245
|
:::
|
|
246
246
|
|
|
247
247
|
### People filter
|
|
@@ -262,7 +262,7 @@ The people filter requires a `dataSource` with a `searchPeople` method that retu
|
|
|
262
262
|
|
|
263
263
|
## Keeping filter state outside the grid
|
|
264
264
|
|
|
265
|
-
By default the grid owns its filter state
|
|
265
|
+
By default the grid owns its filter state, and filters reset when the component unmounts. To persist them (URL sync, page reload survival), pass `filters` and `onFiltersChange`:
|
|
266
266
|
|
|
267
267
|
```tsx
|
|
268
268
|
function App() {
|
|
@@ -283,11 +283,11 @@ function App() {
|
|
|
283
283
|
}
|
|
284
284
|
```
|
|
285
285
|
|
|
286
|
-
Now you can serialize `filters` to the URL, localStorage, or a server
|
|
286
|
+
Now you can serialize `filters` to the URL, localStorage, or a server. The grid will restore the exact filter state when the user comes back.
|
|
287
287
|
|
|
288
288
|
## Server-side filtering
|
|
289
289
|
|
|
290
|
-
When you're using a `dataSource`, the grid
|
|
290
|
+
When you're using a `dataSource`, the grid passes filter values to your `fetchPage()` function. You decide what to do with them -- query params, request body, whatever your API expects:
|
|
291
291
|
|
|
292
292
|
```tsx
|
|
293
293
|
const dataSource: IDataSource<Task> = {
|
|
@@ -323,7 +323,7 @@ const dataSource: IDataSource<Task> = {
|
|
|
323
323
|
```
|
|
324
324
|
|
|
325
325
|
:::tip Pro tip
|
|
326
|
-
Server-side filtering pairs naturally with [pagination](./pagination). The `totalCount` in your `fetchPage` response tells the grid how many pages
|
|
326
|
+
Server-side filtering pairs naturally with [pagination](./pagination). The `totalCount` in your `fetchPage` response tells the grid how many pages exist, so pagination stays accurate even when filters narrow the result set.
|
|
327
327
|
:::
|
|
328
328
|
|
|
329
329
|
## Props reference
|
|
@@ -341,6 +341,6 @@ Server-side filtering pairs naturally with [pagination](./pagination). The `tota
|
|
|
341
341
|
|
|
342
342
|
## Next steps
|
|
343
343
|
|
|
344
|
-
- [Sorting](./sorting)
|
|
345
|
-
- [Pagination](./pagination)
|
|
346
|
-
- [Server-Side Data](./server-side-data)
|
|
344
|
+
- [Sorting](./sorting) -- sort filtered results by any column
|
|
345
|
+
- [Pagination](./pagination) -- paginate filtered results server-side or client-side
|
|
346
|
+
- [Server-Side Data](./server-side-data) -- move all filtering, sorting, and paging to the server
|
|
@@ -7,21 +7,21 @@ description: Excel-like formula support with 93 built-in functions, live recalcu
|
|
|
7
7
|
|
|
8
8
|
# Formulas
|
|
9
9
|
|
|
10
|
-
Type `=SUM(A1:A5)` into any editable cell and it evaluates instantly. Change a value in A1 and everything that depends on it recalculates.
|
|
10
|
+
Type `=SUM(A1:A5)` into any editable cell and it evaluates instantly. Change a value in A1 and everything that depends on it recalculates. No external library, no backend call, no wiring required.
|
|
11
11
|
|
|
12
|
-
The engine adds ~12KB gzipped and is completely
|
|
12
|
+
The engine adds ~12KB gzipped and is completely tree-shakeable. Grids without `formulas={true}` don't pay any cost.
|
|
13
13
|
|
|
14
14
|
## Live Demo
|
|
15
15
|
|
|
16
16
|
<FormulasDemo />
|
|
17
17
|
|
|
18
18
|
:::tip Try it in your framework
|
|
19
|
-
The demo uses Radix UI styling. The formula engine
|
|
19
|
+
The demo uses Radix UI styling. The formula engine is framework-agnostic -- same behavior in React, Angular, Vue, and Vanilla JS.
|
|
20
20
|
:::
|
|
21
21
|
|
|
22
22
|
## Why bother with in-grid formulas?
|
|
23
23
|
|
|
24
|
-
If you've ever had users copy grid data into Excel to calculate totals
|
|
24
|
+
If you've ever had users copy grid data into Excel to calculate totals, then paste it back, formulas solve that. Users build their own calculations directly in the table, results stay live, and you don't have to ship a calculator UI.
|
|
25
25
|
|
|
26
26
|
## Enable formulas
|
|
27
27
|
|
|
@@ -63,7 +63,7 @@ function App() {
|
|
|
63
63
|
```
|
|
64
64
|
|
|
65
65
|
:::tip Switching UI libraries
|
|
66
|
-
Same props across all React packages
|
|
66
|
+
Same props across all React packages -- just change the import:
|
|
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>`
|
|
@@ -106,7 +106,7 @@ Same API across Angular packages. Change the import:
|
|
|
106
106
|
- **Angular Material**: `from '@alaarab/ogrid-angular-material'`
|
|
107
107
|
- **PrimeNG**: `from '@alaarab/ogrid-angular-primeng'`
|
|
108
108
|
|
|
109
|
-
All components are standalone
|
|
109
|
+
All components are standalone, no NgModule required.
|
|
110
110
|
:::
|
|
111
111
|
|
|
112
112
|
</TabItem>
|
|
@@ -174,7 +174,7 @@ formulaState.setFormula(2, 0, '=A1+B1', grid.getApi().getDataAccessor());
|
|
|
174
174
|
|
|
175
175
|
## Entering formulas
|
|
176
176
|
|
|
177
|
-
Type any value starting with `=` into an editable cell. The engine parses and evaluates it, then shows the result. The formula string is stored separately from your data
|
|
177
|
+
Type any value starting with `=` into an editable cell. The engine parses and evaluates it, then shows the result. The formula string is stored separately from your data. Your `data[]` array is never modified by formulas.
|
|
178
178
|
|
|
179
179
|
```
|
|
180
180
|
=A1+B1 → adds two cells
|
|
@@ -185,7 +185,7 @@ Type any value starting with `=` into an editable cell. The engine parses and ev
|
|
|
185
185
|
|
|
186
186
|
## Pre-loading formulas
|
|
187
187
|
|
|
188
|
-
Use `initialFormulas` to seed formulas when the grid mounts
|
|
188
|
+
Use `initialFormulas` to seed formulas when the grid mounts, useful for reports with fixed summary rows:
|
|
189
189
|
|
|
190
190
|
```tsx
|
|
191
191
|
<OGrid
|
|
@@ -202,24 +202,24 @@ Coordinates are 0-based: `col` is the position in your flat columns array, `row`
|
|
|
202
202
|
|
|
203
203
|
## How recalculation works
|
|
204
204
|
|
|
205
|
-
The engine
|
|
205
|
+
The engine maintains a dependency graph. When A1 changes, it recalculates every formula that depends on it in topological order, including dependents of dependents. Circular references produce a `#CIRC!` error rather than an infinite loop.
|
|
206
206
|
|
|
207
207
|
## Formula-aware copy, paste, and fill
|
|
208
208
|
|
|
209
209
|
When `formulas` is enabled:
|
|
210
210
|
|
|
211
|
-
- **Copy**
|
|
212
|
-
- **Paste**
|
|
213
|
-
- **Fill handle**
|
|
211
|
+
- **Copy** -- copies the formula string (`=SUM(A1:A5)`), not the computed value
|
|
212
|
+
- **Paste** -- if the pasted value starts with `=`, it becomes a formula in the target cell
|
|
213
|
+
- **Fill handle** -- dragging a formula cell down adjusts relative references. `=A1+B1` dragged down becomes `=A2+B2`. Lock references with `$`: `=$A$1` never adjusts.
|
|
214
214
|
|
|
215
215
|
## Cell reference syntax
|
|
216
216
|
|
|
217
217
|
| Syntax | Example | What it means |
|
|
218
218
|
|--------|---------|---------|
|
|
219
|
-
| Relative | `A1` | Column A, Row 1
|
|
219
|
+
| Relative | `A1` | Column A, Row 1 -- adjusts when filled |
|
|
220
220
|
| Absolute column | `$A1` | Column A locked, row adjusts |
|
|
221
221
|
| Absolute row | `A$1` | Row 1 locked, column adjusts |
|
|
222
|
-
| Fully absolute | `$A$1` | Both locked
|
|
222
|
+
| Fully absolute | `$A$1` | Both locked -- never adjusts |
|
|
223
223
|
| Range | `A1:B5` | Rectangular block from A1 to B5 |
|
|
224
224
|
| Named range | `Revenue` | Resolves to a defined cell or range |
|
|
225
225
|
| Cross-sheet | `Sheet2!A1` | Cell A1 from another sheet |
|
|
@@ -238,7 +238,7 @@ Give meaningful names to cells or ranges you reference often:
|
|
|
238
238
|
/>
|
|
239
239
|
```
|
|
240
240
|
|
|
241
|
-
Now write `=SUM(Revenue)` or `=A1*TaxRate` instead of cryptic coordinates. Named ranges are case-insensitive
|
|
241
|
+
Now write `=SUM(Revenue)` or `=A1*TaxRate` instead of cryptic coordinates. Named ranges are case-insensitive -- `Revenue`, `revenue`, and `REVENUE` all resolve to the same range.
|
|
242
242
|
|
|
243
243
|
You can also manage them at runtime:
|
|
244
244
|
|
|
@@ -293,9 +293,9 @@ Reference cells from other grids by registering sheet accessors:
|
|
|
293
293
|
```
|
|
294
294
|
|
|
295
295
|
Then write:
|
|
296
|
-
- `=Sheet2!A1`
|
|
297
|
-
- `=SUM(Sheet2!A1:A10)`
|
|
298
|
-
- `='Sales Data'!B5`
|
|
296
|
+
- `=Sheet2!A1` -- single cell from Sheet2
|
|
297
|
+
- `=SUM(Sheet2!A1:A10)` -- range from Sheet2
|
|
298
|
+
- `='Sales Data'!B5` -- quoted name for sheets with spaces
|
|
299
299
|
|
|
300
300
|
Referencing an unregistered sheet produces a `#REF!` error.
|
|
301
301
|
|
|
@@ -320,15 +320,15 @@ Formula errors display in red (controlled by `--ogrid-formula-error-color`):
|
|
|
320
320
|
|-------|---------|
|
|
321
321
|
| `#REF!` | Cell reference points outside the grid, or unregistered sheet |
|
|
322
322
|
| `#DIV/0!` | Division by zero |
|
|
323
|
-
| `#VALUE!` | Wrong argument type
|
|
324
|
-
| `#NAME?` | Unknown function name
|
|
323
|
+
| `#VALUE!` | Wrong argument type -- text where a number was expected |
|
|
324
|
+
| `#NAME?` | Unknown function name -- check spelling |
|
|
325
325
|
| `#CIRC!` | Circular reference detected |
|
|
326
326
|
| `#N/A` | No match found (VLOOKUP, MATCH, XLOOKUP) |
|
|
327
|
-
| `#NUM!` | Invalid numeric argument
|
|
327
|
+
| `#NUM!` | Invalid numeric argument -- e.g., LARGE with k larger than the list |
|
|
328
328
|
| `#ERROR!` | General parse or eval error |
|
|
329
329
|
|
|
330
330
|
:::tip Pro tip
|
|
331
|
-
`#NAME?` is almost always a typo. Formula function names are case-insensitive
|
|
331
|
+
`#NAME?` is almost always a typo. Formula function names are case-insensitive (`sum`, `SUM`, and `Sum` all work), but `=SUMM(A1:A5)` gives `#NAME?`.
|
|
332
332
|
:::
|
|
333
333
|
|
|
334
334
|
## All 93 built-in functions
|
|
@@ -358,7 +358,7 @@ Formula errors display in red (controlled by `--ogrid-formula-error-color`):
|
|
|
358
358
|
|
|
359
359
|
| Prop | Type | Default | Description |
|
|
360
360
|
|------|------|---------|-------------|
|
|
361
|
-
| `formulas` | `boolean` | `false` | Enable formula support. Tree-shakeable
|
|
361
|
+
| `formulas` | `boolean` | `false` | Enable formula support. Tree-shakeable -- zero cost when not used. |
|
|
362
362
|
| `initialFormulas` | `Array<{ col, row, formula }>` | — | Pre-load formulas on mount (0-based col/row indices). |
|
|
363
363
|
| `onFormulaRecalc` | `(result: IRecalcResult) => void` | — | Called after each recalculation with the updated cell list. |
|
|
364
364
|
| `formulaFunctions` | `Record<string, IFormulaFunction>` | — | Custom functions to register alongside built-ins. |
|
|
@@ -367,10 +367,10 @@ Formula errors display in red (controlled by `--ogrid-formula-error-color`):
|
|
|
367
367
|
|
|
368
368
|
## Next steps
|
|
369
369
|
|
|
370
|
-
- [Editing & Clipboard](./editing)
|
|
371
|
-
- [Cell References](./cell-references)
|
|
372
|
-
- [CSV Export](./csv-export)
|
|
373
|
-
- [Status Bar](./status-bar)
|
|
370
|
+
- [Editing & Clipboard](./editing) -- formula-aware copy, paste, and fill handle
|
|
371
|
+
- [Cell References](./cell-references) -- Excel-style column letters and the name box
|
|
372
|
+
- [CSV Export](./csv-export) -- export formula strings or computed values
|
|
373
|
+
- [Status Bar](./status-bar) -- live SUM/AVERAGE/COUNT on selected cells
|
|
374
374
|
|
|
375
375
|
## Community
|
|
376
376
|
|
|
@@ -172,9 +172,9 @@ async function handleRefresh() {
|
|
|
172
172
|
</TabItem>
|
|
173
173
|
</Tabs>
|
|
174
174
|
|
|
175
|
-
##
|
|
175
|
+
## API reference
|
|
176
176
|
|
|
177
|
-
Pass a `ref` to
|
|
177
|
+
Pass a `ref` to `OGrid`. It exposes the `IOGridApi<T>` interface.
|
|
178
178
|
|
|
179
179
|
### API Methods
|
|
180
180
|
|
|
@@ -7,7 +7,7 @@ description: Full keyboard support for navigating, editing, selecting, and opera
|
|
|
7
7
|
|
|
8
8
|
# Keyboard Navigation
|
|
9
9
|
|
|
10
|
-
|
|
10
|
+
Navigate, edit, select, and operate on cells entirely from the keyboard. Click a cell to make it active, then use the shortcuts below.
|
|
11
11
|
|
|
12
12
|
## Live Demo
|
|
13
13
|
|
|
@@ -119,7 +119,7 @@ const grid = new OGrid(document.getElementById('grid'), {
|
|
|
119
119
|
</TabItem>
|
|
120
120
|
</Tabs>
|
|
121
121
|
|
|
122
|
-
Click
|
|
122
|
+
Click a cell to focus it, then use the keyboard to navigate and edit.
|
|
123
123
|
|
|
124
124
|
## Navigation
|
|
125
125
|
|
|
@@ -197,9 +197,9 @@ Copied data uses tab-separated format compatible with Excel and Google Sheets. M
|
|
|
197
197
|
|
|
198
198
|
Undo/redo requires the `onUndo`, `onRedo`, `canUndo`, and `canRedo` props to be wired up (typically via the `useUndoRedo` hook).
|
|
199
199
|
|
|
200
|
-
## How
|
|
200
|
+
## How it works
|
|
201
201
|
|
|
202
|
-
|
|
202
|
+
The `useKeyboardNavigation` hook fires automatically when `cellSelection` is enabled (the default). It listens for `keydown` events on the grid wrapper and translates them into cell movement, selection range changes, or editing actions.
|
|
203
203
|
|
|
204
204
|
### Disabling Cell Selection
|
|
205
205
|
|
|
@@ -233,4 +233,4 @@ On macOS, Ctrl is replaced by the Command key for all shortcuts (Cmd+C, Cmd+V, C
|
|
|
233
233
|
|
|
234
234
|
- [Context Menu](./context-menu) -- right-click menu mirrors keyboard shortcuts
|
|
235
235
|
- [Status Bar](./status-bar) -- shows aggregations for keyboard-selected ranges
|
|
236
|
-
- [Column Pinning](./column-pinning) -- navigation works
|
|
236
|
+
- [Column Pinning](./column-pinning) -- navigation works across pinned and scrollable columns
|
|
@@ -7,7 +7,7 @@ description: Built-in pagination with configurable page sizes for client-side an
|
|
|
7
7
|
|
|
8
8
|
# Pagination
|
|
9
9
|
|
|
10
|
-
OGrid includes a built-in pagination bar with page navigation buttons, page size selector, and a row count summary. It works
|
|
10
|
+
OGrid includes a built-in pagination bar with page navigation buttons, page size selector, and a row count summary. It works with both client-side data arrays and server-side data sources.
|
|
11
11
|
|
|
12
12
|
## Live Demo
|
|
13
13
|
|
|
@@ -6,11 +6,11 @@ description: What is OGrid and why use it
|
|
|
6
6
|
|
|
7
7
|
# Overview
|
|
8
8
|
|
|
9
|
-
OGrid is
|
|
9
|
+
OGrid is an open-source data grid with spreadsheet-grade features and no enterprise paywall. It ships React, Angular, and Vue adapters -- each with multiple UI library choices -- plus a vanilla JS package, all driven by a shared TypeScript core.
|
|
10
10
|
|
|
11
11
|
## Why OGrid?
|
|
12
12
|
|
|
13
|
-
Most production-grade
|
|
13
|
+
Most production-grade data grids are free but limited, or full-featured but expensive. OGrid is neither.
|
|
14
14
|
|
|
15
15
|
- **Free and MIT-licensed.** Every feature is included. No enterprise tier, no feature gating.
|
|
16
16
|
- **25+ built-in features.** Sorting, filtering, pagination, cell editing, clipboard, undo/redo, fill handle, row selection, cell range selection, column pinning, column groups, CSV export, context menu, keyboard navigation, cell references, virtual scrolling, status bar, sidebar, and more.
|
|
@@ -84,10 +84,7 @@ All packages within a framework export the same `OGrid` component with the same
|
|
|
84
84
|
|
|
85
85
|
### Why This Matters
|
|
86
86
|
|
|
87
|
-
|
|
88
|
-
- **Zero lock-in.** Migrate between React, Angular, and Vue without rewriting business logic.
|
|
89
|
-
- **Guaranteed parity.** Shared core ensures all packages behave identically.
|
|
90
|
-
- **Small surface area.** No duplicated state logic to drift out of sync.
|
|
87
|
+
A bug fix in core lands across all frameworks instantly. You can migrate between React, Angular, and Vue without touching business logic. All packages share the same core, so behavior is consistent by construction, not by convention. There's no duplicated state that can quietly fall out of sync.
|
|
91
88
|
|
|
92
89
|
## Packages
|
|
93
90
|
|
|
@@ -7,7 +7,7 @@ description: A sortable, filterable, editable data grid in under 50 lines
|
|
|
7
7
|
|
|
8
8
|
# Quick Start
|
|
9
9
|
|
|
10
|
-
Here's a grid in 60 seconds
|
|
10
|
+
Here's a grid in 60 seconds. Sorting, filtering, editing, pagination, and keyboard navigation all work out of the box.
|
|
11
11
|
|
|
12
12
|
## Install
|
|
13
13
|
|
|
@@ -213,7 +213,7 @@ All Angular packages share the same component API. Change one import:
|
|
|
213
213
|
- **Angular Material**: `from '@alaarab/ogrid-angular-material'`
|
|
214
214
|
- **PrimeNG**: `from '@alaarab/ogrid-angular-primeng'`
|
|
215
215
|
|
|
216
|
-
All components are standalone
|
|
216
|
+
All components are standalone, no NgModule required.
|
|
217
217
|
:::
|
|
218
218
|
|
|
219
219
|
</TabItem>
|
|
@@ -321,11 +321,11 @@ The JS package has a class-based imperative API. See the [Vanilla JS guide](./va
|
|
|
321
321
|
|
|
322
322
|
Paste those ~40 lines and you have:
|
|
323
323
|
|
|
324
|
-
- **Sorting**
|
|
325
|
-
- **Filtering**
|
|
326
|
-
- **Inline editing**
|
|
327
|
-
- **Currency formatting**
|
|
328
|
-
- **Pagination, keyboard nav, cell selection, status bar**
|
|
324
|
+
- **Sorting** -- click any column header, ascending/descending, shift-click for multi-sort
|
|
325
|
+
- **Filtering** -- the Department column gets a multi-select dropdown filter
|
|
326
|
+
- **Inline editing** -- double-click any salary cell to edit in place
|
|
327
|
+
- **Currency formatting** -- `valueFormatter` formats numbers on display without affecting stored values
|
|
328
|
+
- **Pagination, keyboard nav, cell selection, status bar** -- all there, no extra config
|
|
329
329
|
|
|
330
330
|
## Three concepts worth knowing
|
|
331
331
|
|
|
@@ -419,7 +419,7 @@ grid.destroy();
|
|
|
419
419
|
|
|
420
420
|
## What's next?
|
|
421
421
|
|
|
422
|
-
- [Sorting](../features/sorting), [Filtering](../features/filtering), [Editing](../features/editing)
|
|
423
|
-
- [Server-Side Data](../features/server-side-data)
|
|
424
|
-
- [Grid API](../api/js-api)
|
|
425
|
-
- [Column Definitions](../api/types)
|
|
422
|
+
- [Sorting](../features/sorting), [Filtering](../features/filtering), [Editing](../features/editing) -- dig into individual features
|
|
423
|
+
- [Server-Side Data](../features/server-side-data) -- connect to a REST API or GraphQL endpoint
|
|
424
|
+
- [Grid API](../api/js-api) -- full reference for programmatic control
|
|
425
|
+
- [Column Definitions](../api/types) -- every column option explained
|
|
@@ -1,13 +1,13 @@
|
|
|
1
1
|
---
|
|
2
2
|
sidebar_position: 4
|
|
3
3
|
title: Vanilla JS
|
|
4
|
-
description: OGrid without a framework
|
|
4
|
+
description: OGrid without a framework, pure JavaScript, class-based API
|
|
5
5
|
---
|
|
6
6
|
|
|
7
7
|
|
|
8
8
|
# Vanilla JS
|
|
9
9
|
|
|
10
|
-
You don't need React, Angular, or Vue to use OGrid. The `@alaarab/ogrid-js` package gives you a full-featured
|
|
10
|
+
You don't need React, Angular, or Vue to use OGrid. The `@alaarab/ogrid-js` package gives you a full-featured data grid using a class-based API: pass a container element and an options object.
|
|
11
11
|
|
|
12
12
|
It's a good fit if you're working on an internal tool, a dashboard that can't take on a framework, or you're embedding a grid inside an existing non-framework app.
|
|
13
13
|
|
|
@@ -27,7 +27,7 @@ Or drop it into an HTML file directly using a CDN (no build tools needed):
|
|
|
27
27
|
|
|
28
28
|
## Build a real example
|
|
29
29
|
|
|
30
|
-
Let's make an order management dashboard. It tracks orders by status, amount, and customer
|
|
30
|
+
Let's make an order management dashboard. It tracks orders by status, amount, and customer, with sorting, filtering, and inline editing.
|
|
31
31
|
|
|
32
32
|
```html
|
|
33
33
|
<div id="orders-grid" style="height: 500px;"></div>
|
|
@@ -88,15 +88,15 @@ Let's make an order management dashboard. It tracks orders by status, amount, an
|
|
|
88
88
|
|
|
89
89
|
## What you get out of the box
|
|
90
90
|
|
|
91
|
-
- **Sorting**
|
|
92
|
-
- **Filtering**
|
|
93
|
-
- **Inline editing**
|
|
94
|
-
- **Cell selection**
|
|
95
|
-
- **Keyboard navigation**
|
|
96
|
-
- **Clipboard**
|
|
97
|
-
- **Undo/redo**
|
|
98
|
-
- **Status bar**
|
|
99
|
-
- **Pagination**
|
|
91
|
+
- **Sorting** -- click column headers
|
|
92
|
+
- **Filtering** -- multi-select dropdown on the Status column
|
|
93
|
+
- **Inline editing** -- double-click any Amount cell to edit
|
|
94
|
+
- **Cell selection** -- click and drag to select ranges
|
|
95
|
+
- **Keyboard navigation** -- arrow keys, Tab, Home/End, Ctrl+Arrow
|
|
96
|
+
- **Clipboard** -- Ctrl+C/V/X works like a spreadsheet
|
|
97
|
+
- **Undo/redo** -- Ctrl+Z/Y
|
|
98
|
+
- **Status bar** -- row count and selection aggregations
|
|
99
|
+
- **Pagination** -- page controls at the bottom
|
|
100
100
|
|
|
101
101
|
## Constructor
|
|
102
102
|
|
|
@@ -104,7 +104,7 @@ Let's make an order management dashboard. It tracks orders by status, amount, an
|
|
|
104
104
|
const grid = new OGrid(containerElement, options);
|
|
105
105
|
```
|
|
106
106
|
|
|
107
|
-
The container element defines where the grid renders. OGrid fills it completely
|
|
107
|
+
The container element defines where the grid renders. OGrid fills it completely, so give it an explicit height (CSS or inline).
|
|
108
108
|
|
|
109
109
|
## Key options
|
|
110
110
|
|
|
@@ -210,6 +210,6 @@ grid.destroy();
|
|
|
210
210
|
|
|
211
211
|
## What's next?
|
|
212
212
|
|
|
213
|
-
- [JS API Reference](../api/js-api)
|
|
214
|
-
- [Features](../features/sorting)
|
|
215
|
-
- [Theming Guide](../guides/theming)
|
|
213
|
+
- [JS API Reference](../api/js-api) -- full method and options reference
|
|
214
|
+
- [Features](../features/sorting) -- all features work identically in the JS package
|
|
215
|
+
- [Theming Guide](../guides/theming) -- deep dive into CSS customization
|
|
@@ -5,21 +5,21 @@ title: Accessibility
|
|
|
5
5
|
|
|
6
6
|
# Accessibility
|
|
7
7
|
|
|
8
|
-
Good accessibility isn't just compliance
|
|
8
|
+
Good accessibility isn't just compliance. It's building software that works for everyone. A keyboard user in a tight workflow shouldn't have to reach for the mouse. A screen reader user deserves the same experience as anyone else.
|
|
9
9
|
|
|
10
|
-
OGrid is built with this in mind. Keyboard navigation, screen reader support, high contrast mode, and ARIA semantics are all baked in
|
|
10
|
+
OGrid is built with this in mind. Keyboard navigation, screen reader support, high contrast mode, and ARIA semantics are all baked in. You don't configure them; you just benefit from them.
|
|
11
11
|
|
|
12
12
|
## What's built in by default
|
|
13
13
|
|
|
14
14
|
You get all of this without any extra setup:
|
|
15
15
|
|
|
16
|
-
- Full keyboard navigation
|
|
16
|
+
- Full keyboard navigation: arrow keys, Tab, Home/End, Ctrl+Arrow, all working like a spreadsheet
|
|
17
17
|
- Screen reader announcements for sort, filter, edit, selection, and pagination changes
|
|
18
18
|
- Proper ARIA roles and attributes on the grid, rows, cells, and headers
|
|
19
19
|
- `:focus-visible` indicators so keyboard users always know where they are
|
|
20
20
|
- Focus trapping in dropdowns and popovers (Escape always gets you out)
|
|
21
21
|
- High contrast mode support via CSS custom properties with system color fallbacks
|
|
22
|
-
- Semantic HTML
|
|
22
|
+
- Semantic HTML: real `<table>`, `<thead>`, `<th>`, `<td>` elements that assistive tech understands
|
|
23
23
|
|
|
24
24
|
The one thing you do need to add: an `aria-label` on the grid. It's one prop.
|
|
25
25
|
|
|
@@ -113,7 +113,7 @@ Key attributes and what they do:
|
|
|
113
113
|
| `aria-expanded` | Open/closed state of filter dropdowns |
|
|
114
114
|
| `aria-current="page"` | Current page in pagination |
|
|
115
115
|
|
|
116
|
-
The status bar uses `role="status"` with `aria-live="polite"
|
|
116
|
+
The status bar uses `role="status"` with `aria-live="polite"`, so it announces changes without interrupting what the user is doing.
|
|
117
117
|
|
|
118
118
|
## Screen reader support
|
|
119
119
|
|
|
@@ -221,22 +221,22 @@ npm install --save-dev jest-axe
|
|
|
221
221
|
|
|
222
222
|
Automated tests catch structural issues but can't cover everything. Before shipping:
|
|
223
223
|
|
|
224
|
-
- [ ] Navigate the entire grid using only the keyboard
|
|
224
|
+
- [ ] Navigate the entire grid using only the keyboard (no mouse)
|
|
225
225
|
- [ ] Enable VoiceOver (`Cmd+F5`) or NVDA and navigate through sort, filter, edit
|
|
226
|
-
- [ ] Test at 200% zoom
|
|
227
|
-
- [ ] Toggle Windows High Contrast Mode
|
|
226
|
+
- [ ] Test at 200% zoom: nothing should overflow or become unusable
|
|
227
|
+
- [ ] Toggle Windows High Contrast Mode: all content should remain visible
|
|
228
228
|
- [ ] Verify `aria-label` is set on the grid (one of the most common misses)
|
|
229
229
|
|
|
230
230
|
## Known limitations
|
|
231
231
|
|
|
232
232
|
**Virtual scrolling:** When `virtualScroll.enabled` is true, only visible rows are in the DOM. Screen readers won't know the full dataset size unless you set `aria-rowcount` on the grid wrapper manually.
|
|
233
233
|
|
|
234
|
-
**Custom cell renderers:** If you use `renderCell` to render custom content inside cells, you're responsible for making that content accessible
|
|
234
|
+
**Custom cell renderers:** If you use `renderCell` to render custom content inside cells, you're responsible for making that content accessible: ARIA attributes, keyboard interaction, announcements. The grid provides the structure; your custom content needs to carry its own accessibility.
|
|
235
235
|
|
|
236
236
|
## Resources
|
|
237
237
|
|
|
238
|
-
- [ARIA Grid Pattern](https://www.w3.org/WAI/ARIA/apg/patterns/grid/)
|
|
238
|
+
- [ARIA Grid Pattern](https://www.w3.org/WAI/ARIA/apg/patterns/grid/) -- the spec OGrid follows
|
|
239
239
|
- [WCAG 2.1 Quick Reference](https://www.w3.org/WAI/WCAG21/quickref/)
|
|
240
|
-
- [axe DevTools Browser Extension](https://www.deque.com/axe/devtools/)
|
|
240
|
+
- [axe DevTools Browser Extension](https://www.deque.com/axe/devtools/) -- free in-browser auditing
|
|
241
241
|
|
|
242
242
|
Found an accessibility issue? [Open an issue](https://github.com/alaarab/ogrid/issues) and tag it `accessibility` with your browser, screen reader version, and reproduction steps.
|
|
@@ -7,9 +7,9 @@ description: OGrid in React, Angular, Vue, and Vanilla JS — same API, native c
|
|
|
7
7
|
|
|
8
8
|
# Framework Showcase
|
|
9
9
|
|
|
10
|
-
OGrid works with your existing design system
|
|
10
|
+
OGrid works with your existing design system, not against it. React, Angular, Vue, and Vanilla JS are all fully supported, and every framework shares the same headless core so features stay in sync across all of them.
|
|
11
11
|
|
|
12
|
-
Every grid below is live. Sort, filter, edit, select, copy-paste, undo
|
|
12
|
+
Every grid below is live. Sort, filter, edit, select, copy-paste, undo. It all works.
|
|
13
13
|
|
|
14
14
|
---
|
|
15
15
|
|
|
@@ -17,11 +17,11 @@ Every grid below is live. Sort, filter, edit, select, copy-paste, undo — it al
|
|
|
17
17
|
|
|
18
18
|
The short version:
|
|
19
19
|
|
|
20
|
-
- **Starting from scratch?** Pick the Radix variant for your framework
|
|
21
|
-
- **Already using a design system?** Pick the matching package
|
|
20
|
+
- **Starting from scratch?** Pick the Radix variant for your framework. It's the lightest, with no peer dependencies beyond the framework itself.
|
|
21
|
+
- **Already using a design system?** Pick the matching package (Fluent, Material, Angular Material, PrimeNG, Vuetify, or PrimeVue) and the grid components will use your existing components for buttons, inputs, and popovers.
|
|
22
22
|
- **No framework?** Use `@alaarab/ogrid-js` for a full-featured grid with just a CDN import.
|
|
23
23
|
|
|
24
|
-
Switching between UI libraries later is straightforward
|
|
24
|
+
Switching between UI libraries later is straightforward. You change the import and the wrapper provider if required. The grid configuration (columns, data, event handlers) doesn't change.
|
|
25
25
|
|
|
26
26
|
---
|
|
27
27
|
|
|
@@ -31,7 +31,7 @@ Three design systems, all sharing the same hooks from `@alaarab/ogrid-react`. Yo
|
|
|
31
31
|
|
|
32
32
|
### Radix UI — lightweight default
|
|
33
33
|
|
|
34
|
-
The default React package. Radix primitives are bundled in
|
|
34
|
+
The default React package. Radix primitives are bundled in, no separate peer dependency to install. It's a good starting point for new projects or when you want minimal overhead.
|
|
35
35
|
|
|
36
36
|
```bash
|
|
37
37
|
npm install @alaarab/ogrid-react-radix
|
|
@@ -53,7 +53,7 @@ export default function App() {
|
|
|
53
53
|
|
|
54
54
|
<ShowcaseRadixDemo />
|
|
55
55
|
|
|
56
|
-
### Fluent UI — Microsoft
|
|
56
|
+
### Fluent UI — Microsoft stack
|
|
57
57
|
|
|
58
58
|
If you're building for Microsoft Teams, SharePoint, or any Microsoft 365 integration, Fluent is your pick. The grid uses native Fluent components for headers, filters, and inputs so it blends naturally.
|
|
59
59
|
|
|
@@ -76,7 +76,7 @@ export default function App() {
|
|
|
76
76
|
|
|
77
77
|
### Material UI — Google's Material Design
|
|
78
78
|
|
|
79
|
-
If your app already uses MUI, this drops right in. The grid uses MUI components and respects your `ThemeProvider
|
|
79
|
+
If your app already uses MUI, this drops right in. The grid uses MUI components and respects your `ThemeProvider`, including custom palettes and typography.
|
|
80
80
|
|
|
81
81
|
```bash
|
|
82
82
|
npm install @alaarab/ogrid-react-material @mui/material @emotion/react @emotion/styled
|
|
@@ -101,7 +101,7 @@ export default function App() {
|
|
|
101
101
|
|
|
102
102
|
## Angular
|
|
103
103
|
|
|
104
|
-
Signals-based reactivity with standalone components
|
|
104
|
+
Signals-based reactivity with standalone components. No NgModule, no boilerplate. All three packages share the same services from `@alaarab/ogrid-angular`.
|
|
105
105
|
|
|
106
106
|
### Radix (Angular CDK) — lightweight default
|
|
107
107
|
|
|
@@ -137,7 +137,7 @@ npm install @alaarab/ogrid-angular-material @angular/material @angular/cdk
|
|
|
137
137
|
|
|
138
138
|
### PrimeNG
|
|
139
139
|
|
|
140
|
-
For teams
|
|
140
|
+
For teams already on PrimeFaces, the PrimeNG integration means dialogs, dropdowns, and inputs all look native.
|
|
141
141
|
|
|
142
142
|
```bash
|
|
143
143
|
npm install @alaarab/ogrid-angular-primeng primeng
|
|
@@ -155,7 +155,7 @@ Composition API composables built with `ref()` and `computed()`. All three packa
|
|
|
155
155
|
|
|
156
156
|
### Radix (Headless UI) — lightweight default
|
|
157
157
|
|
|
158
|
-
Headless UI Vue components bundled in
|
|
158
|
+
Headless UI Vue components bundled in, no peer dependencies beyond Vue 3. Good starting point for new Vue projects.
|
|
159
159
|
|
|
160
160
|
```bash
|
|
161
161
|
npm install @alaarab/ogrid-vue-radix
|
|
@@ -204,7 +204,7 @@ npm install @alaarab/ogrid-vue-primevue primevue
|
|
|
204
204
|
|
|
205
205
|
## Vanilla JS / TypeScript
|
|
206
206
|
|
|
207
|
-
No framework, no virtual DOM
|
|
207
|
+
No framework, no virtual DOM. Just a container element and a class constructor. A built-in CSS theme covers light and dark mode with CSS custom properties you can override.
|
|
208
208
|
|
|
209
209
|
```bash
|
|
210
210
|
npm install @alaarab/ogrid-js
|
|
@@ -240,7 +240,7 @@ See [Premium Inputs](../features/premium-inputs) for usage and the full list of
|
|
|
240
240
|
|
|
241
241
|
## Related
|
|
242
242
|
|
|
243
|
-
- [Quick Start](../getting-started/quick-start)
|
|
244
|
-
- [Vanilla JS Guide](../getting-started/vanilla-js)
|
|
245
|
-
- [Theming Guide](./theming)
|
|
246
|
-
- [Premium Inputs](../features/premium-inputs)
|
|
243
|
+
- [Quick Start](../getting-started/quick-start) -- get a grid running in 60 seconds
|
|
244
|
+
- [Vanilla JS Guide](../getting-started/vanilla-js) -- full JS API documentation
|
|
245
|
+
- [Theming Guide](./theming) -- customize colors and styling
|
|
246
|
+
- [Premium Inputs](../features/premium-inputs) -- advanced cell editors
|
|
@@ -6,7 +6,7 @@ sidebar_position: 1
|
|
|
6
6
|
|
|
7
7
|
# Editor Integration (MCP)
|
|
8
8
|
|
|
9
|
-
`@alaarab/ogrid-mcp` connects your AI coding assistant to OGrid documentation
|
|
9
|
+
`@alaarab/ogrid-mcp` connects your AI coding assistant to OGrid documentation. Instead of switching tabs to look things up, you can ask your editor while you code.
|
|
10
10
|
|
|
11
11
|
It also includes a **live testing bridge** that lets your editor read and control an OGrid instance running in your browser in real time.
|
|
12
12
|
|
|
@@ -18,7 +18,7 @@ MCP (Model Context Protocol) is a standard that lets editors like Claude Code an
|
|
|
18
18
|
- Pull up specific API references without leaving your editor
|
|
19
19
|
- Inspect and interact with a running grid during development
|
|
20
20
|
|
|
21
|
-
You don't need to understand the protocol to use it
|
|
21
|
+
You don't need to understand the protocol to use it. Run one command and your editor gains access.
|
|
22
22
|
|
|
23
23
|
## Connect to your editor
|
|
24
24
|
|
|
@@ -28,7 +28,7 @@ You don't need to understand the protocol to use it — just run one command and
|
|
|
28
28
|
claude mcp add ogrid -- npx -y @alaarab/ogrid-mcp
|
|
29
29
|
```
|
|
30
30
|
|
|
31
|
-
That's it. The docs are bundled in the package
|
|
31
|
+
That's it. The docs are bundled in the package, no config file needed.
|
|
32
32
|
|
|
33
33
|
### Claude Desktop
|
|
34
34
|
|
|
@@ -72,13 +72,13 @@ Show me how to use the formula engine in Vue.
|
|
|
72
72
|
Help me migrate from AG Grid to OGrid.
|
|
73
73
|
```
|
|
74
74
|
|
|
75
|
-
The MCP server searches through the full documentation
|
|
75
|
+
The MCP server searches through the full documentation (features, API references, getting started guides, and code examples) and returns the relevant sections along with your context.
|
|
76
76
|
|
|
77
77
|
---
|
|
78
78
|
|
|
79
79
|
## Available tools
|
|
80
80
|
|
|
81
|
-
These are what the MCP server provides to your editor. You don't call them directly
|
|
81
|
+
These are what the MCP server provides to your editor. You don't call them directly; your editor uses them automatically when you ask questions.
|
|
82
82
|
|
|
83
83
|
### `search_docs`
|
|
84
84
|
|
|
@@ -89,9 +89,9 @@ search_docs query="server-side data" framework="react"
|
|
|
89
89
|
```
|
|
90
90
|
|
|
91
91
|
Parameters:
|
|
92
|
-
- `query` (required)
|
|
93
|
-
- `framework` (optional)
|
|
94
|
-
- `category` (optional)
|
|
92
|
+
- `query` (required): what you're looking for
|
|
93
|
+
- `framework` (optional): `react`, `angular`, `vue`, or `js`
|
|
94
|
+
- `category` (optional): `features`, `getting-started`, `guides`, or `api`
|
|
95
95
|
|
|
96
96
|
### `list_docs`
|
|
97
97
|
|
|
@@ -133,7 +133,7 @@ Resources can be read by your editor without calling a tool explicitly.
|
|
|
133
133
|
|
|
134
134
|
| Resource | Description |
|
|
135
135
|
|----------|-------------|
|
|
136
|
-
| `ogrid://quick-reference` | Key API overview
|
|
136
|
+
| `ogrid://quick-reference` | Key API overview: props, column definitions, IOGridApi, filter types |
|
|
137
137
|
| `ogrid://docs/{path}` | Any documentation page by path (e.g. `ogrid://docs/features/filtering`) |
|
|
138
138
|
| `ogrid://migration-guide` | Step-by-step guide for migrating from AG Grid to OGrid |
|
|
139
139
|
|