@alaarab/ogrid-mcp 2.4.0

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 (52) hide show
  1. package/README.md +68 -0
  2. package/bundled-docs/api/README.md +94 -0
  3. package/bundled-docs/api/column-def.mdx +379 -0
  4. package/bundled-docs/api/components-column-chooser.mdx +310 -0
  5. package/bundled-docs/api/components-column-header-filter.mdx +363 -0
  6. package/bundled-docs/api/components-datagrid-table.mdx +316 -0
  7. package/bundled-docs/api/components-pagination-controls.mdx +344 -0
  8. package/bundled-docs/api/components-sidebar.mdx +427 -0
  9. package/bundled-docs/api/components-status-bar.mdx +309 -0
  10. package/bundled-docs/api/grid-api.mdx +299 -0
  11. package/bundled-docs/api/js-api.mdx +198 -0
  12. package/bundled-docs/api/ogrid-props.mdx +244 -0
  13. package/bundled-docs/api/types.mdx +640 -0
  14. package/bundled-docs/features/cell-references.mdx +225 -0
  15. package/bundled-docs/features/column-chooser.mdx +279 -0
  16. package/bundled-docs/features/column-groups.mdx +290 -0
  17. package/bundled-docs/features/column-pinning.mdx +282 -0
  18. package/bundled-docs/features/column-reordering.mdx +359 -0
  19. package/bundled-docs/features/column-types.mdx +181 -0
  20. package/bundled-docs/features/context-menu.mdx +216 -0
  21. package/bundled-docs/features/csv-export.mdx +227 -0
  22. package/bundled-docs/features/editing.mdx +377 -0
  23. package/bundled-docs/features/filtering.mdx +330 -0
  24. package/bundled-docs/features/formulas.mdx +381 -0
  25. package/bundled-docs/features/grid-api.mdx +311 -0
  26. package/bundled-docs/features/keyboard-navigation.mdx +236 -0
  27. package/bundled-docs/features/pagination.mdx +245 -0
  28. package/bundled-docs/features/performance.mdx +433 -0
  29. package/bundled-docs/features/row-selection.mdx +256 -0
  30. package/bundled-docs/features/server-side-data.mdx +291 -0
  31. package/bundled-docs/features/sidebar.mdx +234 -0
  32. package/bundled-docs/features/sorting.mdx +241 -0
  33. package/bundled-docs/features/spreadsheet-selection.mdx +201 -0
  34. package/bundled-docs/features/status-bar.mdx +205 -0
  35. package/bundled-docs/features/toolbar.mdx +284 -0
  36. package/bundled-docs/features/virtual-scrolling.mdx +624 -0
  37. package/bundled-docs/getting-started/installation.mdx +216 -0
  38. package/bundled-docs/getting-started/overview.mdx +151 -0
  39. package/bundled-docs/getting-started/quick-start.mdx +425 -0
  40. package/bundled-docs/getting-started/vanilla-js.mdx +191 -0
  41. package/bundled-docs/guides/accessibility.mdx +550 -0
  42. package/bundled-docs/guides/controlled-vs-uncontrolled.mdx +153 -0
  43. package/bundled-docs/guides/custom-cell-editors.mdx +201 -0
  44. package/bundled-docs/guides/framework-showcase.mdx +200 -0
  45. package/bundled-docs/guides/mcp-live-testing.mdx +291 -0
  46. package/bundled-docs/guides/mcp.mdx +172 -0
  47. package/bundled-docs/guides/migration-from-ag-grid.mdx +223 -0
  48. package/bundled-docs/guides/theming.mdx +211 -0
  49. package/dist/esm/bridge-client.d.ts +87 -0
  50. package/dist/esm/bridge-client.js +162 -0
  51. package/dist/esm/index.js +1060 -0
  52. package/package.json +43 -0
@@ -0,0 +1,433 @@
1
+ ---
2
+ sidebar_position: 20
3
+ title: Performance
4
+ description: Automatic CSS containment, opt-in Web Worker sort/filter, and column virtualization for large datasets
5
+ ---
6
+
7
+
8
+ # Performance
9
+
10
+ OGrid is built with performance as a first-class concern. Three complementary features cover the main bottlenecks in large data grids:
11
+
12
+ | Feature | Opt-in? | Benefit |
13
+ |---------|---------|---------|
14
+ | **CSS Containment** | No (automatic) | Isolates cell layout and paint — prevents off-screen style recalculation |
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 |
17
+
18
+ For row virtualization (rendering only visible rows), see [Virtual Scrolling](./virtual-scrolling).
19
+
20
+ ---
21
+
22
+ ## CSS Containment (Automatic)
23
+
24
+ OGrid applies CSS containment automatically to every grid cell — no configuration needed.
25
+
26
+ ```css
27
+ /* Applied automatically to every body cell */
28
+ td.ogrid-cell {
29
+ contain: content; /* isolate layout + paint + style */
30
+ }
31
+
32
+ /* Pinned columns use position: sticky — containment is relaxed to avoid conflicts */
33
+ td.ogrid-cell[data-pinned] {
34
+ contain: none;
35
+ }
36
+ ```
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:
39
+
40
+ ```css
41
+ /* Non-virtualized rows: browser skips layout for off-screen rows */
42
+ tr[data-row]:not([data-virtual-scroll]) {
43
+ content-visibility: auto;
44
+ }
45
+ ```
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.
48
+
49
+ **You do not need to configure anything.** These rules are included in the default stylesheet for every framework package.
50
+
51
+ ---
52
+
53
+ ## Web Worker Sort/Filter (Opt-in)
54
+
55
+ Enable background thread sorting and filtering by setting `workerSort: true` on the grid:
56
+
57
+ ```tsx
58
+ <OGrid
59
+ columns={columns}
60
+ data={data}
61
+ getRowId={(r) => r.id}
62
+ workerSort={true}
63
+ />
64
+ ```
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
69
+
70
+ <Tabs groupId="framework">
71
+ <TabItem value="react" label="React" default>
72
+
73
+ ```tsx
74
+
75
+ interface Row {
76
+ id: number;
77
+ name: string;
78
+ revenue: number;
79
+ region: string;
80
+ }
81
+
82
+ const columns: IColumnDef<Row>[] = [
83
+ { columnId: 'id', name: 'ID', type: 'numeric' },
84
+ { columnId: 'name', name: 'Name', sortable: true },
85
+ { columnId: 'revenue', name: 'Revenue', type: 'numeric', sortable: true },
86
+ { columnId: 'region', name: 'Region', sortable: true },
87
+ ];
88
+
89
+ function App() {
90
+ return (
91
+ <OGrid
92
+ columns={columns}
93
+ data={largeDataset} // e.g. 50,000 rows
94
+ getRowId={(r) => r.id}
95
+ workerSort={true}
96
+ statusBar
97
+ />
98
+ );
99
+ }
100
+ ```
101
+
102
+ :::tip Switching UI libraries
103
+ The `OGrid` component has the same props across all React UI packages. To switch, just change the import:
104
+
105
+ - **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>`
108
+ :::
109
+
110
+ </TabItem>
111
+ <TabItem value="angular" label="Angular">
112
+
113
+ ```typescript
114
+
115
+ interface Row {
116
+ id: number;
117
+ name: string;
118
+ revenue: number;
119
+ region: string;
120
+ }
121
+
122
+ @Component({
123
+ standalone: true,
124
+ imports: [OGridComponent],
125
+ template: `<ogrid [props]="gridProps" />`
126
+ })
127
+ export class GridComponent {
128
+ gridProps = {
129
+ columns: [
130
+ { columnId: 'id', name: 'ID', type: 'numeric' },
131
+ { columnId: 'name', name: 'Name', sortable: true },
132
+ { columnId: 'revenue', name: 'Revenue', type: 'numeric', sortable: true },
133
+ { columnId: 'region', name: 'Region', sortable: true },
134
+ ] as IColumnDef<Row>[],
135
+ data: largeDataset, // e.g. 50,000 rows
136
+ getRowId: (item: Row) => item.id,
137
+ workerSort: true,
138
+ statusBar: true,
139
+ };
140
+ }
141
+ ```
142
+
143
+ :::tip Switching UI libraries
144
+ Same component API across Angular packages. To switch, just change the import:
145
+
146
+ - **Radix (CDK)**: `from '@alaarab/ogrid-angular-radix'` *(default, lightweight)*
147
+ - **Angular Material**: `from '@alaarab/ogrid-angular-material'`
148
+ - **PrimeNG**: `from '@alaarab/ogrid-angular-primeng'`
149
+
150
+ All components are standalone — no NgModule required.
151
+ :::
152
+
153
+ </TabItem>
154
+ <TabItem value="vue" label="Vue">
155
+
156
+ ```vue
157
+ <script setup lang="ts">
158
+
159
+ interface Row {
160
+ id: number;
161
+ name: string;
162
+ revenue: number;
163
+ region: string;
164
+ }
165
+
166
+ const columns: IColumnDef<Row>[] = [
167
+ { columnId: 'id', name: 'ID', type: 'numeric' },
168
+ { columnId: 'name', name: 'Name', sortable: true },
169
+ { columnId: 'revenue', name: 'Revenue', type: 'numeric', sortable: true },
170
+ { columnId: 'region', name: 'Region', sortable: true },
171
+ ];
172
+
173
+ const gridProps = {
174
+ columns,
175
+ data: largeDataset, // e.g. 50,000 rows
176
+ getRowId: (item: Row) => item.id,
177
+ workerSort: true,
178
+ statusBar: true,
179
+ };
180
+ </script>
181
+
182
+ <template>
183
+ <OGrid :gridProps="gridProps" />
184
+ </template>
185
+ ```
186
+
187
+ :::tip Switching UI libraries
188
+ Same component API across Vue packages. To switch, just change the import:
189
+
190
+ - **Radix (Headless UI)**: `from '@alaarab/ogrid-vue-radix'` *(default, lightweight)*
191
+ - **Vuetify**: `from '@alaarab/ogrid-vue-vuetify'` — wrap in `<v-app>` for theming
192
+ - **PrimeVue**: `from '@alaarab/ogrid-vue-primevue'`
193
+ :::
194
+
195
+ </TabItem>
196
+ <TabItem value="js" label="Vanilla JS">
197
+
198
+ ```js
199
+
200
+ const grid = new OGrid(document.getElementById('grid'), {
201
+ columns: [
202
+ { columnId: 'id', name: 'ID', type: 'numeric' },
203
+ { columnId: 'name', name: 'Name', sortable: true },
204
+ { columnId: 'revenue', name: 'Revenue', type: 'numeric', sortable: true },
205
+ { columnId: 'region', name: 'Region', sortable: true },
206
+ ],
207
+ data: largeDataset, // e.g. 50,000 rows
208
+ getRowId: (r) => r.id,
209
+ workerSort: true,
210
+ statusBar: true,
211
+ });
212
+ ```
213
+
214
+ </TabItem>
215
+ </Tabs>
216
+
217
+ ### `'auto'` Mode
218
+
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:
220
+
221
+ ```tsx
222
+ <OGrid
223
+ workerSort="auto"
224
+ // ...
225
+ />
226
+ ```
227
+
228
+ This is the safest choice if you do not know the data size ahead of time.
229
+
230
+ ### How It Works
231
+
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.
236
+
237
+ The worker is created once and reused for subsequent sort/filter operations in the same grid instance.
238
+
239
+ ### Automatic Fallback
240
+
241
+ The worker is bypassed automatically in situations where it cannot run:
242
+
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 |
248
+
249
+ The fallback is transparent — the grid sorts and filters correctly in all cases.
250
+
251
+ ### Content Security Policy (CSP)
252
+
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:
254
+
255
+ ```
256
+ Content-Security-Policy: worker-src 'self' blob:;
257
+ ```
258
+
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
+ :::
264
+
265
+ ---
266
+
267
+ ## Combining All Three Features
268
+
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:
270
+
271
+ <Tabs groupId="framework">
272
+ <TabItem value="react" label="React" default>
273
+
274
+ ```tsx
275
+
276
+ function App() {
277
+ return (
278
+ <OGrid
279
+ columns={columns} // e.g. 100 columns
280
+ data={data} // e.g. 100,000 rows
281
+ getRowId={(r) => r.id}
282
+ virtualScroll={{
283
+ enabled: true, // row virtualization: renders ~30 rows instead of 100,000
284
+ rowHeight: 36,
285
+ overscan: 5,
286
+ columns: true, // column virtualization: renders only visible columns
287
+ columnOverscan: 2,
288
+ }}
289
+ workerSort={true} // keeps the UI thread free during sort/filter
290
+ statusBar
291
+ />
292
+ );
293
+ }
294
+ ```
295
+
296
+ :::tip Switching UI libraries
297
+ The `OGrid` component has the same props across all React UI packages. To switch, just change the import:
298
+
299
+ - **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>`
302
+ :::
303
+
304
+ </TabItem>
305
+ <TabItem value="angular" label="Angular">
306
+
307
+ ```typescript
308
+ gridProps = {
309
+ columns, // e.g. 100 columns
310
+ data: largeData, // e.g. 100,000 rows
311
+ getRowId: (item: Row) => item.id,
312
+ virtualScroll: {
313
+ enabled: true,
314
+ rowHeight: 36,
315
+ overscan: 5,
316
+ columns: true,
317
+ columnOverscan: 2,
318
+ },
319
+ workerSort: true,
320
+ statusBar: true,
321
+ };
322
+ ```
323
+
324
+ :::tip Switching UI libraries
325
+ Same component API across Angular packages. To switch, just change the import:
326
+
327
+ - **Radix (CDK)**: `from '@alaarab/ogrid-angular-radix'` *(default, lightweight)*
328
+ - **Angular Material**: `from '@alaarab/ogrid-angular-material'`
329
+ - **PrimeNG**: `from '@alaarab/ogrid-angular-primeng'`
330
+
331
+ All components are standalone — no NgModule required.
332
+ :::
333
+
334
+ </TabItem>
335
+ <TabItem value="vue" label="Vue">
336
+
337
+ ```vue
338
+ <script setup lang="ts">
339
+ const gridProps = {
340
+ columns, // e.g. 100 columns
341
+ data: largeData, // e.g. 100,000 rows
342
+ getRowId: (item: Row) => item.id,
343
+ virtualScroll: {
344
+ enabled: true,
345
+ rowHeight: 36,
346
+ overscan: 5,
347
+ columns: true,
348
+ columnOverscan: 2,
349
+ },
350
+ workerSort: true,
351
+ statusBar: true,
352
+ };
353
+ </script>
354
+
355
+ <template>
356
+ <OGrid :gridProps="gridProps" />
357
+ </template>
358
+ ```
359
+
360
+ :::tip Switching UI libraries
361
+ Same component API across Vue packages. To switch, just change the import:
362
+
363
+ - **Radix (Headless UI)**: `from '@alaarab/ogrid-vue-radix'` *(default, lightweight)*
364
+ - **Vuetify**: `from '@alaarab/ogrid-vue-vuetify'` — wrap in `<v-app>` for theming
365
+ - **PrimeVue**: `from '@alaarab/ogrid-vue-primevue'`
366
+ :::
367
+
368
+ </TabItem>
369
+ <TabItem value="js" label="Vanilla JS">
370
+
371
+ ```js
372
+
373
+ const grid = new OGrid(document.getElementById('grid'), {
374
+ columns, // e.g. 100 columns
375
+ data: largeData, // e.g. 100,000 rows
376
+ getRowId: (r) => r.id,
377
+ virtualScroll: {
378
+ enabled: true,
379
+ rowHeight: 36,
380
+ overscan: 5,
381
+ columns: true,
382
+ columnOverscan: 2,
383
+ },
384
+ workerSort: true,
385
+ statusBar: true,
386
+ });
387
+ ```
388
+
389
+ </TabItem>
390
+ </Tabs>
391
+
392
+ ---
393
+
394
+ ## Props Reference
395
+
396
+ ### `workerSort`
397
+
398
+ | Value | Behavior |
399
+ |-------|----------|
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` |
403
+
404
+ ### `virtualScroll` (Performance Fields)
405
+
406
+ | Field | Type | Default | Description |
407
+ |-------|------|---------|-------------|
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).
412
+
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`. |
424
+
425
+ ---
426
+
427
+ ## Related
428
+
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
@@ -0,0 +1,256 @@
1
+ ---
2
+ sidebar_position: 7
3
+ title: Row Selection
4
+ description: Single and multi-row selection with checkboxes, keyboard support, and imperative API.
5
+ ---
6
+
7
+
8
+ # Row Selection
9
+
10
+ Select entire rows with checkboxes (multiple mode) or radio-button-style selection (single mode). Access selected rows programmatically via the grid API ref.
11
+
12
+ ## Live Demo
13
+
14
+ <RowSelectionDemo />
15
+
16
+ :::tip Framework-Specific Styling
17
+ The live demo above shows **React Radix UI** styling (lightweight default). To see how row selection looks in your framework's design system, click the framework buttons above the demo to open online demo:
18
+ - **React** — Radix UI checkboxes
19
+ - **Angular** — Angular Material checkboxes
20
+ - **Vue** — Vuetify checkboxes
21
+ - **JS** — Vanilla JS default theme
22
+
23
+ Each framework renders with its native checkbox components, so the styling matches your design system.
24
+ :::
25
+
26
+ ## Quick Example
27
+
28
+ <Tabs groupId="framework">
29
+ <TabItem value="react" label="React" default>
30
+
31
+ ```tsx
32
+
33
+ function App() {
34
+ const gridRef = useRef<IOGridApi<Person>>(null);
35
+
36
+ const handleExport = () => {
37
+ const selectedIds = gridRef.current?.getSelectedRows() ?? [];
38
+ console.log('Selected:', selectedIds);
39
+ };
40
+
41
+ return (
42
+ <>
43
+ <button onClick={handleExport}>Export Selected</button>
44
+ <OGrid
45
+ ref={gridRef}
46
+ columns={columns}
47
+ data={people}
48
+ getRowId={(item) => item.id}
49
+ rowSelection="multiple"
50
+ onSelectionChange={(event) => {
51
+ console.log(`${event.selectedItems.length} rows selected`);
52
+ }}
53
+ />
54
+ </>
55
+ );
56
+ }
57
+ ```
58
+
59
+ :::tip Switching UI libraries
60
+ The `OGrid` component has the same props across all React UI packages. To switch, just change the import:
61
+
62
+ - **Radix** (lightweight, default): `from '@alaarab/ogrid-react-radix'`
63
+ - **Fluent UI** (Microsoft 365 / SPFx): `from '@alaarab/ogrid-react-fluent'` — wrap in `<FluentProvider>`
64
+ - **Material UI** (MUI v7): `from '@alaarab/ogrid-react-material'` — wrap in `<ThemeProvider>`
65
+ :::
66
+
67
+ </TabItem>
68
+ <TabItem value="angular" label="Angular">
69
+
70
+ ```typescript
71
+
72
+ @Component({
73
+ standalone: true,
74
+ imports: [OGridComponent],
75
+ template: `
76
+ <button (click)="handleExport()">Export Selected</button>
77
+ <ogrid [props]="gridProps" />
78
+ `
79
+ })
80
+ export class GridComponent {
81
+ constructor(private gridService: OGridService) {}
82
+
83
+ handleExport() {
84
+ const selectedIds = this.gridService.getSelectedRows();
85
+ console.log('Selected:', selectedIds);
86
+ }
87
+
88
+ gridProps = {
89
+ columns,
90
+ data: people,
91
+ getRowId: (item: Person) => item.id,
92
+ rowSelection: 'multiple' as const,
93
+ onSelectionChange: (event: any) => {
94
+ console.log(`${event.selectedItems.length} rows selected`);
95
+ },
96
+ };
97
+ }
98
+ ```
99
+
100
+ :::tip Switching UI libraries
101
+ Same component API across Angular packages. To switch, just change the import:
102
+
103
+ - **Radix (CDK)**: `from '@alaarab/ogrid-angular-radix'` *(default, lightweight)*
104
+ - **Angular Material**: `from '@alaarab/ogrid-angular-material'`
105
+ - **PrimeNG**: `from '@alaarab/ogrid-angular-primeng'`
106
+
107
+ All components are standalone — no NgModule required.
108
+ :::
109
+
110
+ </TabItem>
111
+ <TabItem value="vue" label="Vue">
112
+
113
+ ```vue
114
+ <script setup lang="ts">
115
+
116
+ const gridProps = {
117
+ columns,
118
+ data: people,
119
+ getRowId: (item) => item.id,
120
+ rowSelection: 'multiple',
121
+ onSelectionChange: (event) => {
122
+ console.log(`${event.selectedItems.length} rows selected`);
123
+ },
124
+ };
125
+ </script>
126
+
127
+ <template>
128
+ <OGrid :gridProps="gridProps" />
129
+ </template>
130
+ ```
131
+
132
+ :::tip Switching UI libraries
133
+ Same component API across Vue packages. To switch, just change the import:
134
+
135
+ - **Radix (Headless UI)**: `from '@alaarab/ogrid-vue-radix'` *(default, lightweight)*
136
+ - **Vuetify**: `from '@alaarab/ogrid-vue-vuetify'` — wrap in `<v-app>` for theming
137
+ - **PrimeVue**: `from '@alaarab/ogrid-vue-primevue'`
138
+ :::
139
+
140
+ </TabItem>
141
+ <TabItem value="js" label="Vanilla JS">
142
+
143
+ ```js
144
+
145
+ const grid = new OGrid(document.getElementById('grid'), {
146
+ columns: columns,
147
+ data: people,
148
+ getRowId: (item) => item.id,
149
+ rowSelection: 'multiple',
150
+ });
151
+
152
+ grid.on('selectionChange', ({ selectedRows }) => {
153
+ console.log(`${selectedRows.length} rows selected`);
154
+ });
155
+
156
+ // Programmatic access
157
+ document.getElementById('export-btn').addEventListener('click', () => {
158
+ const selected = grid.api.getSelectedRows();
159
+ console.log('Selected:', selected);
160
+ });
161
+ ```
162
+
163
+ </TabItem>
164
+ </Tabs>
165
+
166
+ ## How It Works
167
+
168
+ Set `rowSelection` on the `OGrid` component to enable row selection:
169
+
170
+ | Mode | Behavior |
171
+ |------|----------|
172
+ | `'none'` | No row selection (default). |
173
+ | `'single'` | One row at a time. Clicking a row selects it and deselects the previous. |
174
+ | `'multiple'` | Checkbox column appears. Click checkboxes to toggle. Shift+click for range select. Header checkbox toggles all. |
175
+
176
+ :::info Row Selection vs Cell Selection
177
+ **Row selection** (this page) selects entire rows using checkboxes. The header checkbox selects or deselects **all rows** at once.
178
+
179
+ This is separate from **cell selection** ([Spreadsheet Selection](./spreadsheet-selection)), which selects individual cells using click/drag. Cell selection's **Ctrl+A** shortcut selects all **cells** in the grid, not rows.
180
+
181
+ You can use both features together -- row selection and cell selection are independent.
182
+ :::
183
+
184
+ ### Multiple Selection
185
+
186
+ In `'multiple'` mode, a checkbox column is prepended to the grid:
187
+
188
+ - Click a checkbox to toggle that row.
189
+ - Click the header checkbox to select or deselect all visible rows.
190
+ - Hold **Shift** and click a checkbox to select a range of rows from the last clicked row.
191
+
192
+ ### Controlled Mode
193
+
194
+ For full control, pass `selectedRows` and `onSelectionChange`:
195
+
196
+ ```tsx
197
+ function App() {
198
+ const [selectedRows, setSelectedRows] = useState<Set<RowId>>(new Set());
199
+
200
+ return (
201
+ <OGrid
202
+ columns={columns}
203
+ data={people}
204
+ getRowId={(item) => item.id}
205
+ rowSelection="multiple"
206
+ selectedRows={selectedRows}
207
+ onSelectionChange={(event) => {
208
+ setSelectedRows(new Set(event.selectedRowIds));
209
+ }}
210
+ />
211
+ );
212
+ }
213
+ ```
214
+
215
+ ### Imperative API
216
+
217
+ Use the grid ref to programmatically control selection:
218
+
219
+ ```tsx
220
+ const gridRef = useRef<IOGridApi<Person>>(null);
221
+
222
+ // Get selected row IDs
223
+ gridRef.current?.getSelectedRows();
224
+
225
+ // Set selection programmatically
226
+ gridRef.current?.setSelectedRows([1, 2, 3]);
227
+
228
+ // Select all rows (row selection, not cells)
229
+ gridRef.current?.selectAll();
230
+
231
+ // Deselect all rows
232
+ gridRef.current?.deselectAll();
233
+ ```
234
+
235
+ ## Props
236
+
237
+ | Prop | Type | Default | Description |
238
+ |------|------|---------|-------------|
239
+ | `rowSelection` | `'none' \| 'single' \| 'multiple'` | `'none'` | Row selection mode. |
240
+ | `selectedRows` | `Set<RowId>` | -- | Controlled set of selected row IDs. |
241
+ | `onSelectionChange` | `(event: IRowSelectionChangeEvent<T>) => void` | -- | Called when selection changes. Event contains `selectedRowIds` and `selectedItems`. |
242
+
243
+ ## API Methods
244
+
245
+ | Method | Signature | Description |
246
+ |--------|-----------|-------------|
247
+ | `getSelectedRows` | `() => RowId[]` | Returns currently selected row IDs. |
248
+ | `setSelectedRows` | `(rowIds: RowId[]) => void` | Sets selected rows programmatically. |
249
+ | `selectAll` | `() => void` | Selects all rows. |
250
+ | `deselectAll` | `() => void` | Deselects all rows. |
251
+
252
+ ## Related
253
+
254
+ - [Spreadsheet Selection](./spreadsheet-selection) -- cell-level selection
255
+ - [Sorting](./sorting) -- sort rows before selection
256
+ - [Filtering](./filtering) -- filter rows before selection