A lightweight React data grid with the essentials other grids gate behind a paid enterprise
licence — row grouping, aggregates, inline editing and Excel-compatible export — fully MIT. The
React port of @inandu-solutions/grid-angular,
kept in sync feature-for-feature by hand (and with its Vue sibling,
@inandu-solutions/grid-vue).
Live free-text search on the demo grid. Try every feature →
npm install @inandu-solutions/grid-reactimport { InanduGrid } from '@inandu-solutions/grid-react';
import '@inandu-solutions/grid-react/style.css';
const rows = [{ name: 'Ada', age: 36 }, { name: 'Alan', age: 41 }];
const columns = [{ field: 'name', headerText: 'Name' }, { field: 'age', headerText: 'Age', type: 'number' as const }];
export default function App() {
return <InanduGrid rows={rows} columns={columns} pageSize={25} />; // sorting + filtering are on by default
}▶️ Live demo — try every feature in the browser.- ⚡ Edit in StackBlitz —
installs
@inandu-solutions/grid-reactfrom npm; editsrc/App.tsxand it updates live (source). - 📦
@inandu-solutions/grid-reacton npm (MIT) —0.xwhile the API settles; expect breaking changes between minors until1.0.0.
- CRUD / business apps that need sortable, filterable, editable tables without pulling in a full enterprise grid framework.
- Admin dashboards that need grouping, aggregates and CSV/Excel/PDF export out of the box.
- Data-heavy React apps that need virtual scroll, or server-side sort / filter / paging against a backend (see Server-side data), without the bundle size of a kitchen-sink grid.
When not to use it: if you need pivot tables or integrated charting built into the grid itself, this isn't that — see Not included below.
inandu-grid is the original, feature-complete,
MIT-licensed Angular grid this repo is ported from — same feature set, same core logic, adapted for
Angular signals/standalone components instead of React hooks.
inandu-grid-vue is the Vue 3 port
(@inandu-solutions/grid-vue) — same feature set again, adapted for Vue's composition API.
Deliberately not a kitchen sink: no pivoting and no integrated charts — those stay out of scope so the core stays small and auditable. Everything else on this page (grouping, aggregates, editing, export, virtual scroll, paged server-side mode) is included, free, no enterprise tier. If you need pivot tables or built-in charts, a heavier framework is the right tool; if you want a focused, free, lightweight grid, this is it.
@inandu-solutions/grid-pro-react (private, paid, not released yet) — the React port of
@inandu-solutions/grid-pro, depends on this package the same way grid-pro depends on grid-angular.
Grouping and live free-text search — running in the demo, which also has tabs for inline editing and tree data.
Feature-complete with grid-angular and grid-vue. The framework-agnostic core (sorting, filtering,
aggregation, export, i18n) is ported from grid-angular's
core/
folder and kept in sync by hand across the three repos. The React-specific layer — the
<InanduGrid> component and the useInanduGrid() headless hook —
covers:
- Sorting — single-column, or multi-column via shift-click
- Free-text search and per-column filtering, plus an
extraRowFilterescape hatch for your own predicates - Pagination, single-column grouping with aggregates, row selection
- CSV / Excel (
.xls) / PDF export, and print - i18n — 5 built-in languages via a
langprop - Inline row editing, creation and deletion, with validation (required / min / max / pattern / custom / async)
- Excel-style Ctrl+C / Ctrl+V clipboard copy/paste
- Runtime column show/hide, sticky (pinned left/right) columns, drag-reorder
- Column resize (drag a header's handle) and autosize (double-click it to fit content)
- Row drag-reorder
- Tree data (
treeChildrenKey) — display and expand only, no inline editing/drag/clipboard on tree rows, same restriction as grid-angular - Master-detail (
renderDetail) - Custom cell / header / edit-control rendering per column (
renderCell/renderHeader/renderEditor) — drop in your own component in place of the built-in formatted text, header label, or edit-mode input, without losing sorting, resizing, or validation - Excel-style cell range selection (
cellRangeSelection,multiRange) — click-and-drag or shift-click across cells to select a rectangular block;Ctrl+Ccopies the whole range as TSV whenclipboardis also on - Row virtualization (
virtualScroll) for large datasets - Server-side sort / search / filter / paging (
serverSide+useInanduGridServer) — paged only; grid-angular's server-side infinite scroll isn't ported. See Server-side data
Two things work slightly differently from grid-angular because they need a real browser layout
engine that a unit-test environment can't provide: virtual scroll's row height isn't
auto-measured — pass virtualRowHeight explicitly — and autosize's content measurement itself is
trusted (ported verbatim, same DOM APIs) rather than end-to-end tested; see
measureColumn.ts's doc comment for exactly what its test suite does
and doesn't cover.
import { InanduGrid, useInanduGrid } from '@inandu-solutions/grid-react';
import '@inandu-solutions/grid-react/style.css'; // optional default styling — skip it and bring your own
// Component: batteries-included table.
<InanduGrid rows={rows} columns={columns} />;
// Hook: headless — bring your own markup.
const { visibleRows, filteredRowCount, sortCriteria, setSort, filterValues, setFilterValue, page, setPage, pageCount } =
useInanduGrid({ rows, columns, pageSize: 25 });For tables too big to load whole, let the backend sort, filter and page, and keep the grid's UI unchanged:
import { InanduGrid, useInanduGridServer } from '@inandu-solutions/grid-react';
const server = useInanduGridServer({ url: '/api/products' });
<InanduGrid
rows={server.rows}
columns={columns}
pageSize={25}
serverSide={{ totalItems: server.total }}
onQueryChange={server.setQuery}
/>;useInanduGridServer turns the grid's page / sort / search / column filters into a query string
(?page=2&pageSize=25&sort=-price&q=cable&price_gte=20), aborts superseded requests, debounces typing,
and keeps the previous page on screen while the next loads. It expects { data: [...], total: n }.
That is exactly what Inandu.Grid.Extensions
(.NET / EF Core) returns from one ToInanduGrid() call — request contract —
but any backend that speaks the same params works. Runnable example: examples/server-side.
In serverSide mode grouping, tree data, virtual scroll, extraRowFilter and column aggregate
totals are off (they would only ever see one page), and a column's Excel-style value checklist lists
the values on the current page. Use buildInanduGridQuery(query) if you'd rather do the fetching
yourself, and fetcher / init on the hook for auth headers or a custom client.
npm install
npm run dev # Vite dev server
npm test # Vitest + React Testing Library
npm run build # library build (dist/)Issues and PRs welcome. Please read CONTRIBUTING.md first, and note the
Code of Conduct. Security reports: .github/SECURITY.md.
MIT © Inandu SAS

