Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
22 changes: 12 additions & 10 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -184,6 +184,8 @@ This means that **Cursor**, **GitHub Copilot**, **Windsurf**, and other AI agent
| `cellSelection` | `boolean` | Spreadsheet-style cell range selection; Ctrl/Cmd+C then copies the range (v3.3). |
| `cellSelectionModel` / `onCellSelectionModelChange` | `GridCellSelectionModel` / `(model, { reason }) => void` | Controlled cell range. |
| `showCellSelectionStats` | `boolean` | Status bar with count, sum and average of the range. |
| `undoRedo` | `boolean \| GridUndoRedoOptions` | Undo / redo of edits, paste, range clear and fill (Ctrl/Cmd+Z, Ctrl/Cmd+Shift+Z, Ctrl+Y); `{ limit }` sets the history size (v3.4). |
| `aiAssistant` | `GridAiAssistantOptions` | Ask AI panel in the toolbar; your `onPrompt` calls your model. Also `onAiAssistantApply` / `onAiAssistantError` (v3.5). See [AI toolkit](docs/features/ai-toolkit.md). |

### Sorting & Filtering

Expand Down Expand Up @@ -450,7 +452,7 @@ exportToExcelAdvanced(rows, columns, {
});
exportToJson(rows, columns, { fileName: 'data.json' });
await exportToPdf(rows, columns, { fileName: 'data', title: 'Report Title' });
printGrid(rows, columns, 'Report Title');
await printGrid(rows, columns, 'Report Title');
```

> **Optional peer dependencies:** `exportToExcelAdvanced` requires ExcelJS (`npm install exceljs`); `exportToPdf` requires `npm install jspdf jspdf-autotable`.
Expand Down Expand Up @@ -492,20 +494,20 @@ Built-in themes: `darkTheme`, `roseTheme`, `emeraldTheme`, `amberTheme`, `compac

| Artifact | Size | Gzipped | Notes |
| :--- | :--- | :--- | :--- |
| **What an app ships for `DataGrid`** (your bundler minifies) | 271 KB | **87 KB** | Measured v3.9.0: esbuild, minified, React external, `DataGrid` only |
| **Core ES Module** (`opengridx.es.js`, as published) | 493 KB | 130 KB | Unminified with readable names; use this — tree-shakeable |
| **Core UMD** (`opengridx.umd.js`) | 357 KB | 112 KB | CommonJS / CDN compat |
| **What an app ships for `DataGrid`** (your bundler minifies) | 271 KB | **87 KB** | Measured v3.10.1 (86.6 KB gzipped; CI fails above 92 KB): esbuild, minified, React external, `DataGrid` only |
| **Core ES Module** (`opengridx.es.js`, as published) | 497 KB | 132 KB | Unminified with readable names; use this — tree-shakeable |
| **Core UMD** (`opengridx.umd.js`) | 360 KB | 113 KB | CommonJS / CDN compat |
| **Styles** (`opengridx.css`) | 81 KB | **12 KB** | `import '@opencorestack/opengridx/styles'` |
| **AI toolkit** (`/ai`, optional import) | 20 KB | **7 KB** | Adds nothing unless imported |
| **ExcelJS** (optional peer dep) | — | — | `npm install exceljs` |
| **jsPDF** (optional peer dep) | — | — | `npm install jspdf jspdf-autotable` |
| **npm package download** | — | **~2.5 MB** | Compressed tarball (includes `lib/` source, docs and source maps; 7.8 MB unpacked) |
| **npm package download** | — | **~2.6 MB** | Compressed tarball (includes `lib/` source, docs and source maps; about 8 MB unpacked) |

- **Tree-shaking Ready**: ES Module build — bundlers (Vite, Webpack) only include what you use.
- **Zero UI Dependencies**: No MUI, Ant Design, or Radix. Pure React + vanilla CSS.
- **Lazy Advanced Export**: ExcelJS and jsPDF are optional peer deps — not bundled, loaded only when you call `exportToExcelAdvanced` / `exportToPdf`.
- **Efficient Rendering**: Row and column virtualization keeps the DOM small (needs a bounded grid height): about 19 rows at rest and under 90 while scrolling fast, at 10k or 1M rows.
- **[Benchmarks](docs/performance.md#benchmarks)** (`npm run bench`, Apple M1, Chromium, production build): at 100k rows the grid mounts in 89 ms, sorts in 102–160 ms, filters in 28–33 ms and groups with a sum in 87 ms; at 1M rows mount takes 0.7 s and a sort 1.1–1.3 s. Scrolling missed no frames at any size in Chromium. Past the browser's height cap (645,277 rows at 52 px in Chromium and Safari, about 344,000 in Firefox) rows cannot be scrolled to; page or stream larger datasets.
- **[Benchmarks](docs/performance.md#benchmarks)** (`npm run bench`, Apple M1, Chromium, production build): at 100k rows the grid mounts in 75 ms, sorts in 49–66 ms, filters in 16–20 ms and groups with a sum in 74 ms; at 1M rows mount takes 0.6 s and a sort about 0.47 s. Scrolling stayed under 1 % slow frames at every size in Chromium. At 1M rows a cell edit commits in about 35 ms, select-all takes 60–90 ms and grouping about 190 ms (v3.8–3.10). Past the browser's height cap (645,277 rows at 52 px in Chromium and Safari, about 344,000 in Firefox) rows cannot be scrolled to; page or stream larger datasets.

---

Expand Down Expand Up @@ -565,11 +567,11 @@ Most React grids gatekeep essential features like **Row Grouping**, **Excel Expo
| Tree Data | ❌ | ✅ | ✅ | ✅ |
| Master-Detail | ❌ | ✅ | ✅ | ✅ |
| Excel Export | ❌ | ✅ | ❌ | ✅ |
| Advanced Filtering | ❌ | ✅ | ❌ | ✅ |
| Advanced Filtering | ❌ | ✅ | ✅ | ✅ |
| Aggregation | ❌ | ✅ | ❌ | ✅ |
| Pivot Mode | ❌ | ✅ | ❌ | ✅ |
| Inline Cell Editing | ❌ | ✅ | ✅ | ✅ |
| State Persistence | ❌ | ✅ | ❌ | ✅ |
| Inline Cell Editing | ✅ | ✅ | ✅ | ✅ |
| State Persistence | ✅ | ✅ | ❌ | ✅ |
| **Price** | Free | **$$$** | Free (limited) | **Free** |

---
Expand All @@ -583,7 +585,7 @@ See [CONTRIBUTING.md](https://github.com/OpenCoreStack/OpenGridX/blob/main/CONTR
```bash
npm test # unit tests (jsdom)
npm run test:browser # real Chromium, Firefox and WebKit
npm run test:smoke # pack the library, install it into React 18/19 apps, run Playwright
npm run test:smoke # pack the library, install it into React 18/19, webpack and Next.js apps, run Playwright
```

Which layer to use, and how the package smoke suite works: [docs/contributing/testing.md](https://github.com/OpenCoreStack/OpenGridX/blob/main/docs/contributing/testing.md).
Expand Down
45 changes: 41 additions & 4 deletions opengridx-ai-context.md
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ that uses the `@opencorestack/opengridx` library. Read it in full before writing
## What this library is

`@opencorestack/opengridx` is a zero-dependency, high-performance React DataGrid component.
Current version: **3.7.0**. It is a full custom implementation — not a wrapper around MUI or any
Current version: **3.10.1**. It is a full custom implementation — not a wrapper around MUI or any
other library.

---
Expand Down Expand Up @@ -331,6 +331,41 @@ apiRef.current.autosizeColumn('name');
apiRef.current.autosizeColumns(); // all columns
```

### Translating the UI: `localeText` (3.9.0+)

```tsx
// Every built-in string is an optional key (about 200); leave one out and the English default is used.
// Some keys are functions of their arguments.
<DataGrid
localeText={{
toolbarSearchPlaceholder: 'Rechercher…',
columnMenuSortAscending: 'Trier par ordre croissant',
aiAssistantChipSort: (field, direction) => `Tri : ${field} (${direction})`, // 3.10.0+
}}
/>
```

Look up key names in the `GridLocaleText` type rather than guessing them. An inline object of strings is fine:
the grid compares it shallowly. Function keys get a new identity on every render, so when you use them, keep
the object stable (a module constant or `useMemo`).

### Theme keys added in 3.9.0

`grid.checkboxCheckedBackground`, `grid.checkboxCheckmark`, `grid.expandIconColor`, `grid.expandIconHoverColor`,
`overlays.itemIndicatorColor`, `overlays.itemSelectedIcon`, `overlays.iconColor`, `overlays.sectionLabelText`,
`overlays.dividerColor`. Each one defaults to the look of earlier versions. The demo's Theme Builder edits them.

### Large datasets (3.8.0–3.10.1)

Edits, paste, fill, undo, select-all and row grouping are fast at 1M rows, with no API change; numbers are in
`docs/performance.md`. To keep them fast:
- **Keep handler props stable** (`useCallback`), as well as `slotProps` and function-valued `localeText` keys. Rows are memoised,
so a prop that changes identity on every render re-renders every visible row.
- **Commit edits through `processRowUpdate`** and return the updated row. The grid then patches only that row
instead of re-processing all of them.
- **Sorting takes about 0.4–0.5 s at 1M rows, and the first quick-filter search about 1.6–2 s.** For larger or
slower data, use server-side sorting and filtering.

---

## v2 → v3 migration (if this project was on v2)
Expand Down Expand Up @@ -428,9 +463,11 @@ const hasChildren = params.rowMeta?.hasChildren;
- **Import the stylesheet** — `import '@opencorestack/opengridx/styles'` once in the app root.
- **Next.js App Router: column functions stay in the client file** — render the grid from a `'use client'`
component and pass server-fetched rows as props; `valueFormatter` / `renderCell` cannot be passed from a
Server Component. Install or alias `exceljs` / `jspdf` / `jspdf-autotable` or `next build` fails. See `docs/features/nextjs.md`.
- **Don't pin columns in right-to-left grids** — `dir="rtl"` works for unpinned grids (3.6+), but pinned
columns use physical sticky offsets and scroll away. See `docs/features/rtl.md`.
Server Component. The optional peers `exceljs` / `jspdf` / `jspdf-autotable` are needed only for
`exportToExcelAdvanced` / `exportToPdf`; without them `next build` still succeeds (3.6+, no `next.config` alias).
See `docs/features/nextjs.md`.
- **Right-to-left grids** — `dir="rtl"` works, including pinned columns (3.6+): `pinnedColumns.left` / `right`
mean inline start / end, so in RTL `left` pins to the right edge. See `docs/features/rtl.md`.
- **Controlled props need their callback** — `paginationModel` without `onPaginationModelChange` (or `sortModel`
without `onSortModelChange`) freezes that state. Leave both out to let the grid own it.
- **Give the grid a bounded height** — without a `height` prop the grid fills its container (3.0.1+); in a flex layout wrap it in `<div style={{ flex: 1, minHeight: 0 }}>`.
Expand Down
5 changes: 4 additions & 1 deletion scripts/check-versions.mjs
Original file line number Diff line number Diff line change
Expand Up @@ -16,10 +16,13 @@ if (read('demo/public/llms.txt') !== llms) problems.push('demo/public/llms.txt d
const claudeVersion = read('CLAUDE.md').match(/\*\*Current version:\*\* (\S+)/)?.[1];
if (claudeVersion !== version) problems.push(`CLAUDE.md says "Current version: ${claudeVersion}"`);

const contextVersion = read('opengridx-ai-context.md').match(/Current version: \*\*(\S+?)\*\*/)?.[1];
if (contextVersion !== version) problems.push(`opengridx-ai-context.md says "Current version: ${contextVersion}"`);

if (!read('CHANGELOG.md').includes(`## [${version}]`)) problems.push(`CHANGELOG.md has no "## [${version}]" entry`);

if (problems.length > 0) {
console.error(`check:versions: package.json is ${version}, but:\n - ${problems.join('\n - ')}`);
process.exit(1);
}
console.log(`check:versions: ${version} everywhere (llms.txt, demo copy, CLAUDE.md, CHANGELOG)`);
console.log(`check:versions: ${version} everywhere (llms.txt, demo copy, CLAUDE.md, opengridx-ai-context.md, CHANGELOG)`);
Loading