@alaarab/ogrid-mcp 2.5.5 → 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
@@ -7,65 +7,63 @@ description: Automatic CSS containment, opt-in Web Worker sort/filter, and colum
7
7
 
8
8
  # Performance
9
9
 
10
- OGrid is built with performance as a first-class concern. Three complementary features cover the main bottlenecks in large data grids:
10
+ A grid that handles 100 rows fine but chokes at 50,000 isn't production-ready. OGrid ships with three complementary features to handle large datasets without framework-level heroics:
11
11
 
12
- | Feature | Opt-in? | Benefit |
12
+ | Feature | Opt-in? | What it does |
13
13
  |---------|---------|---------|
14
- | **CSS Containment** | No (automatic) | Isolates cell layout and paint prevents off-screen style recalculation |
14
+ | **CSS Containment** | No (automatic) | Browser skips layout and paint for off-screen cells |
15
15
  | **Column Virtualization** | Yes | Renders only visible columns — scales to hundreds of columns |
16
- | **Web Worker Sort/Filter** | Yes | Offloads sort and filter work to a background thread — keeps the UI thread free |
16
+ | **Web Worker Sort/Filter** | Yes | Sort and filter run in a background thread — UI stays responsive |
17
17
 
18
- For row virtualization (rendering only visible rows), see [Virtual Scrolling](./virtual-scrolling).
18
+ For rendering only visible rows (usually the most impactful optimization for tall datasets), see [Virtual Scrolling](./virtual-scrolling).
19
19
 
20
20
  ---
21
21
 
22
- ## CSS Containment (Automatic)
22
+ ## CSS Containment — you get this for free
23
23
 
24
- OGrid applies CSS containment automatically to every grid cell no configuration needed.
24
+ Every grid cell already has `contain: content` applied — you don't configure anything. This tells the browser that what happens inside a cell doesn't affect anything outside it, so it can skip layout and paint work for cells not visible in the viewport.
25
25
 
26
26
  ```css
27
27
  /* Applied automatically to every body cell */
28
28
  td.ogrid-cell {
29
- contain: content; /* isolate layout + paint + style */
29
+ contain: content; /* isolate layout + paint + style */
30
30
  }
31
31
 
32
- /* Pinned columns use position: sticky — containment is relaxed to avoid conflicts */
32
+ /* Pinned columns use position: sticky — containment relaxed to avoid conflicts */
33
33
  td.ogrid-cell[data-pinned] {
34
34
  contain: none;
35
35
  }
36
36
  ```
37
37
 
38
- The browser uses `contain: content` to skip layout and paint work for cells that are not visible in the viewport. Combined with `content-visibility: auto` on non-virtualized rows, the browser can skip off-screen row layout entirely:
38
+ Without row virtualization, OGrid also sets `content-visibility: auto` on rows, letting the browser skip off-screen row layout entirely:
39
39
 
40
40
  ```css
41
- /* Non-virtualized rows: browser skips layout for off-screen rows */
41
+ /* Browser skips layout for rows not in the viewport */
42
42
  tr[data-row]:not([data-virtual-scroll]) {
43
43
  content-visibility: auto;
44
44
  }
45
45
  ```
46
46
 
47
- The `data-virtual-scroll` attribute on the `<table>` element gates this behavior — when row virtualization is active, spacer rows already handle positioning, so `content-visibility` is not applied.
47
+ When row virtualization is active, spacer rows handle positioning instead — so `content-visibility` is not applied there. The `data-virtual-scroll` attribute on `<table>` controls this automatically.
48
48
 
49
- **You do not need to configure anything.** These rules are included in the default stylesheet for every framework package.
49
+ **Net result**: even without opting into anything, a 500-row grid renders measurably faster than without these rules.
50
50
 
51
51
  ---
52
52
 
53
- ## Web Worker Sort/Filter (Opt-in)
53
+ ## Web Worker Sort/Filter — keeps the UI responsive
54
54
 
55
- Enable background thread sorting and filtering by setting `workerSort: true` on the grid:
55
+ Sorting 50,000 rows on the main thread can freeze the UI for a visible moment. With `workerSort: true`, the work happens in a background thread — the grid stays interactive while it processes.
56
56
 
57
57
  ```tsx
58
58
  <OGrid
59
59
  columns={columns}
60
- data={data}
60
+ data={largeDataset} // 50,000 rows
61
61
  getRowId={(r) => r.id}
62
62
  workerSort={true}
63
63
  />
64
64
  ```
65
65
 
66
- When enabled, sort and filter operations run in an inline Web Worker (created from a `Blob` URL) instead of on the main thread. The UI remains fully interactive while the worker processes the data.
67
-
68
- ### Quick Example
66
+ ### Full example
69
67
 
70
68
  <Tabs groupId="framework">
71
69
  <TabItem value="react" label="React" default>
@@ -90,7 +88,7 @@ function App() {
90
88
  return (
91
89
  <OGrid
92
90
  columns={columns}
93
- data={largeDataset} // e.g. 50,000 rows
91
+ data={largeDataset} // e.g. 50,000 rows
94
92
  getRowId={(r) => r.id}
95
93
  workerSort={true}
96
94
  statusBar
@@ -100,11 +98,11 @@ function App() {
100
98
  ```
101
99
 
102
100
  :::tip Switching UI libraries
103
- The `OGrid` component has the same props across all React UI packages. To switch, just change the import:
101
+ Same props across all React packages just change the import:
104
102
 
105
103
  - **Radix** (lightweight, default): `from '@alaarab/ogrid-react-radix'`
106
- - **Fluent UI** (Microsoft 365 / SPFx): `from '@alaarab/ogrid-react-fluent'`wrap in `<FluentProvider>`
107
- - **Material UI** (MUI v7): `from '@alaarab/ogrid-react-material'`wrap in `<ThemeProvider>`
104
+ - **Fluent UI** (Microsoft 365 / SPFx): `from '@alaarab/ogrid-react-fluent'` - wrap in `<FluentProvider>`
105
+ - **Material UI** (MUI v7): `from '@alaarab/ogrid-react-material'` - wrap in `<ThemeProvider>`
108
106
  :::
109
107
 
110
108
  </TabItem>
@@ -141,7 +139,7 @@ export class GridComponent {
141
139
  ```
142
140
 
143
141
  :::tip Switching UI libraries
144
- Same component API across Angular packages. To switch, just change the import:
142
+ Same API across Angular packages. Change the import:
145
143
 
146
144
  - **Radix (CDK)**: `from '@alaarab/ogrid-angular-radix'` *(default, lightweight)*
147
145
  - **Angular Material**: `from '@alaarab/ogrid-angular-material'`
@@ -185,10 +183,10 @@ const gridProps = {
185
183
  ```
186
184
 
187
185
  :::tip Switching UI libraries
188
- Same component API across Vue packages. To switch, just change the import:
186
+ Same API across Vue packages. Change the import:
189
187
 
190
188
  - **Radix (Headless UI)**: `from '@alaarab/ogrid-vue-radix'` *(default, lightweight)*
191
- - **Vuetify**: `from '@alaarab/ogrid-vue-vuetify'`wrap in `<v-app>` for theming
189
+ - **Vuetify**: `from '@alaarab/ogrid-vue-vuetify'` - wrap in `<v-app>` for theming
192
190
  - **PrimeVue**: `from '@alaarab/ogrid-vue-primevue'`
193
191
  :::
194
192
 
@@ -214,59 +212,52 @@ const grid = new OGrid(document.getElementById('grid'), {
214
212
  </TabItem>
215
213
  </Tabs>
216
214
 
217
- ### `'auto'` Mode
215
+ ### Not sure about your data size? Use `'auto'`
218
216
 
219
- Set `workerSort: 'auto'` to let the grid decide. The worker is used only when the dataset exceeds **5,000 rows**; smaller datasets use synchronous processing:
217
+ `workerSort: 'auto'` uses the worker only when your dataset exceeds 5,000 rows. For smaller datasets it runs synchronously — no overhead, no complexity:
220
218
 
221
219
  ```tsx
222
- <OGrid
223
- workerSort="auto"
224
- // ...
225
- />
220
+ <OGrid workerSort="auto" ... />
226
221
  ```
227
222
 
228
- This is the safest choice if you do not know the data size ahead of time.
223
+ This is the right default if you're not sure how large your data will get.
229
224
 
230
- ### How It Works
225
+ ### How it works under the hood
231
226
 
232
- 1. Before sorting or filtering, the grid extracts a flat value matrix from the row data.
233
- 2. The matrix is transferred to an inline `Blob` Web Worker via `postMessage`.
234
- 3. The worker performs the sort and filter computation and returns the sorted/filtered row indices.
235
- 4. The grid uses those indices to re-render the visible rows — no data is copied back, only indices.
227
+ 1. Before sort/filter, the grid extracts a flat value matrix from your row data.
228
+ 2. The matrix is sent to an inline Blob Web Worker via `postMessage`.
229
+ 3. The worker sorts/filters and returns the resulting row indices.
230
+ 4. The grid re-renders using those indices — no row data is ever copied back, only the index array.
236
231
 
237
- The worker is created once and reused for subsequent sort/filter operations in the same grid instance.
232
+ The worker is created once per grid instance and reused for all subsequent sort/filter operations.
238
233
 
239
- ### Automatic Fallback
234
+ ### When the worker falls back to sync
240
235
 
241
- The worker is bypassed automatically in situations where it cannot run:
236
+ The worker can't run in every situation. It falls back silently in these cases:
242
237
 
243
- | Situation | Behavior |
244
- |-----------|----------|
245
- | Custom `compare` function on a column | Falls back to synchronous sort (custom functions cannot cross the worker boundary) |
246
- | `people` filter type | Falls back to synchronous filter (requires rich object comparison) |
247
- | `Worker` API unavailable (e.g. old browser or sandboxed iframe) | Falls back to synchronous processing silently |
238
+ | Situation | Why |
239
+ |-----------|-----|
240
+ | Column has a custom `compare` function | Functions can't cross the worker boundary |
241
+ | `people` filter type | Requires rich object comparison |
242
+ | `Worker` API unavailable (old browser, sandboxed iframe) | No Worker API to use |
248
243
 
249
- The fallback is transparent — the grid sorts and filters correctly in all cases.
244
+ In all cases, the grid sorts and filters correctly just on the main thread.
250
245
 
251
- ### Content Security Policy (CSP)
246
+ ### CSP gotcha
252
247
 
253
- The worker is created from an inline `Blob` URL. If your application enforces a `Content-Security-Policy` header, you must allow `blob:` in the `worker-src` directive:
248
+ The worker uses an inline `Blob` URL. If your app has a `Content-Security-Policy` header, add `blob:` to `worker-src`:
254
249
 
255
250
  ```
256
251
  Content-Security-Policy: worker-src 'self' blob:;
257
252
  ```
258
253
 
259
- Without this directive, the browser will block the worker and the grid will fall back to synchronous processing automatically.
260
-
261
- :::caution
262
- If your CSP does not permit `blob:` and you require worker-based processing, contact your security team about the CSP configuration before enabling `workerSort`.
263
- :::
254
+ Without it, the browser blocks the worker and the grid falls back to synchronous processing. If you can't change the CSP, `workerSort` still works — it just runs on the main thread.
264
255
 
265
256
  ---
266
257
 
267
- ## Combining All Three Features
258
+ ## Putting it all together
268
259
 
269
- Row virtualization, column virtualization, and worker sort/filter are fully compatible and can be enabled together for maximum throughput on very wide, very tall datasets:
260
+ Row virtualization, column virtualization, and worker sort/filter stack together cleanly. For a 100-column, 100,000-row dataset, enable all three:
270
261
 
271
262
  <Tabs groupId="framework">
272
263
  <TabItem value="react" label="React" default>
@@ -276,17 +267,17 @@ Row virtualization, column virtualization, and worker sort/filter are fully comp
276
267
  function App() {
277
268
  return (
278
269
  <OGrid
279
- columns={columns} // e.g. 100 columns
280
- data={data} // e.g. 100,000 rows
270
+ columns={columns} // 100 columns
271
+ data={data} // 100,000 rows
281
272
  getRowId={(r) => r.id}
282
273
  virtualScroll={{
283
- enabled: true, // row virtualization: renders ~30 rows instead of 100,000
274
+ enabled: true, // renders ~30 rows instead of 100,000
284
275
  rowHeight: 36,
285
276
  overscan: 5,
286
- columns: true, // column virtualization: renders only visible columns
277
+ columns: true, // renders only visible columns
287
278
  columnOverscan: 2,
288
279
  }}
289
- workerSort={true} // keeps the UI thread free during sort/filter
280
+ workerSort={true} // sort/filter off the main thread
290
281
  statusBar
291
282
  />
292
283
  );
@@ -294,11 +285,11 @@ function App() {
294
285
  ```
295
286
 
296
287
  :::tip Switching UI libraries
297
- The `OGrid` component has the same props across all React UI packages. To switch, just change the import:
288
+ Same props across all React packages just change the import:
298
289
 
299
290
  - **Radix** (lightweight, default): `from '@alaarab/ogrid-react-radix'`
300
- - **Fluent UI** (Microsoft 365 / SPFx): `from '@alaarab/ogrid-react-fluent'`wrap in `<FluentProvider>`
301
- - **Material UI** (MUI v7): `from '@alaarab/ogrid-react-material'`wrap in `<ThemeProvider>`
291
+ - **Fluent UI** (Microsoft 365 / SPFx): `from '@alaarab/ogrid-react-fluent'` - wrap in `<FluentProvider>`
292
+ - **Material UI** (MUI v7): `from '@alaarab/ogrid-react-material'` - wrap in `<ThemeProvider>`
302
293
  :::
303
294
 
304
295
  </TabItem>
@@ -306,8 +297,8 @@ The `OGrid` component has the same props across all React UI packages. To switch
306
297
 
307
298
  ```typescript
308
299
  gridProps = {
309
- columns, // e.g. 100 columns
310
- data: largeData, // e.g. 100,000 rows
300
+ columns, // 100 columns
301
+ data: largeData, // 100,000 rows
311
302
  getRowId: (item: Row) => item.id,
312
303
  virtualScroll: {
313
304
  enabled: true,
@@ -322,7 +313,7 @@ gridProps = {
322
313
  ```
323
314
 
324
315
  :::tip Switching UI libraries
325
- Same component API across Angular packages. To switch, just change the import:
316
+ Same API across Angular packages. Change the import:
326
317
 
327
318
  - **Radix (CDK)**: `from '@alaarab/ogrid-angular-radix'` *(default, lightweight)*
328
319
  - **Angular Material**: `from '@alaarab/ogrid-angular-material'`
@@ -337,8 +328,8 @@ All components are standalone — no NgModule required.
337
328
  ```vue
338
329
  <script setup lang="ts">
339
330
  const gridProps = {
340
- columns, // e.g. 100 columns
341
- data: largeData, // e.g. 100,000 rows
331
+ columns, // 100 columns
332
+ data: largeData, // 100,000 rows
342
333
  getRowId: (item: Row) => item.id,
343
334
  virtualScroll: {
344
335
  enabled: true,
@@ -358,10 +349,10 @@ const gridProps = {
358
349
  ```
359
350
 
360
351
  :::tip Switching UI libraries
361
- Same component API across Vue packages. To switch, just change the import:
352
+ Same API across Vue packages. Change the import:
362
353
 
363
354
  - **Radix (Headless UI)**: `from '@alaarab/ogrid-vue-radix'` *(default, lightweight)*
364
- - **Vuetify**: `from '@alaarab/ogrid-vue-vuetify'`wrap in `<v-app>` for theming
355
+ - **Vuetify**: `from '@alaarab/ogrid-vue-vuetify'` - wrap in `<v-app>` for theming
365
356
  - **PrimeVue**: `from '@alaarab/ogrid-vue-primevue'`
366
357
  :::
367
358
 
@@ -371,8 +362,8 @@ Same component API across Vue packages. To switch, just change the import:
371
362
  ```js
372
363
 
373
364
  const grid = new OGrid(document.getElementById('grid'), {
374
- columns, // e.g. 100 columns
375
- data: largeData, // e.g. 100,000 rows
365
+ columns, // 100 columns
366
+ data: largeData, // 100,000 rows
376
367
  getRowId: (r) => r.id,
377
368
  virtualScroll: {
378
369
  enabled: true,
@@ -391,43 +382,49 @@ const grid = new OGrid(document.getElementById('grid'), {
391
382
 
392
383
  ---
393
384
 
394
- ## Props Reference
385
+ ## Which features do I actually need?
386
+
387
+ Start here, add as needed:
388
+
389
+ | Dataset | Recommended setup |
390
+ |---|---|
391
+ | < 1,000 rows, < 20 columns | Nothing — CSS containment handles it automatically. |
392
+ | 1,000 – 10,000 rows | Add row virtualization: `virtualScroll: { enabled: true, rowHeight: 36 }`. |
393
+ | > 10,000 rows | Row virtualization + `workerSort: 'auto'`. |
394
+ | > 30 columns with horizontal scroll | Add `columns: true` to the `virtualScroll` config. |
395
+ | Very large + very wide | All three: row virtualization, column virtualization, and `workerSort: true`. |
396
+
397
+ :::tip Pro tip
398
+ If you're unsure whether you need column virtualization, open DevTools and look at how many `<td>` elements render in a single row. If it's more than you can count comfortably, add `columns: true`.
399
+ :::
400
+
401
+ ---
402
+
403
+ ## Props reference
395
404
 
396
405
  ### `workerSort`
397
406
 
398
- | Value | Behavior |
407
+ | Value | When to use it |
399
408
  |-------|----------|
400
- | `false` (default) | Synchronous sort/filter on the main thread |
401
- | `true` | Always use Web Worker for sort and filter |
402
- | `'auto'` | Use Web Worker only when `data.length > 5000` |
409
+ | `false` (default) | Small datasets, or when you have custom `compare` functions |
410
+ | `true` | Large datasets where you want the worker always active |
411
+ | `'auto'` | You don't know the data size ahead of time — use this as the safe default |
403
412
 
404
- ### `virtualScroll` (Performance Fields)
413
+ ### Column virtualization fields (inside `virtualScroll`)
405
414
 
406
415
  | Field | Type | Default | Description |
407
416
  |-------|------|---------|-------------|
408
- | `columns` | `boolean` | `false` | Enable column virtualization alongside row virtualization |
409
- | `columnOverscan` | `number` | `2` | Extra columns rendered beyond the visible horizontal range on each side |
410
-
411
- For the full `virtualScroll` props table, see [Virtual Scrolling — Props Reference](./virtual-scrolling#props-reference).
417
+ | `columns` | `boolean` | `false` | Enable column virtualization. Requires row virtualization to also be enabled. |
418
+ | `columnOverscan` | `number` | `2` | Extra columns rendered beyond the visible range on each side (prevents blank flash on fast scroll). |
412
419
 
413
- ---
414
-
415
- ## When to Use Each Feature
416
-
417
- | Dataset Size | Recommendation |
418
- |---|---|
419
- | < 1,000 rows, < 20 columns | No performance features needed. CSS containment applies automatically. |
420
- | 1,000 – 10,000 rows | Enable row virtualization (`virtualScroll: { enabled: true, rowHeight: 36 }`). |
421
- | > 10,000 rows | Row virtualization + `workerSort: 'auto'` or `workerSort: true`. |
422
- | > 30 columns with horizontal scroll | Add `columns: true` to the `virtualScroll` config. |
423
- | All of the above | Combine all three: row + column virtualization and `workerSort: true`. |
420
+ For the full `virtualScroll` API, see [Virtual Scrolling — Props Reference](./virtual-scrolling#props-reference).
424
421
 
425
422
  ---
426
423
 
427
- ## Related
424
+ ## Next steps
428
425
 
429
- - [Virtual Scrolling](./virtual-scrolling) -- row virtualization, programmatic scrolling, and the full `virtualScroll` API
430
- - [Sorting](./sorting) -- configure sortable columns and custom comparators
431
- - [Filtering](./filtering) -- filter types and server-side filtering
432
- - [Server-Side Data](./server-side-data) -- move sort and filter to the server entirely
433
- - [Column Pinning](./column-pinning) -- pinned columns always render regardless of column virtualization
426
+ - [Virtual Scrolling](./virtual-scrolling) row virtualization, scroll-to-row, and the full virtualScroll API
427
+ - [Sorting](./sorting) configure sortable columns and custom comparators
428
+ - [Filtering](./filtering) filter types and server-side filtering
429
+ - [Server-Side Data](./server-side-data) skip client-side processing entirely for the largest datasets
430
+ - [Column Pinning](./column-pinning) pinned columns always render regardless of column virtualization