@helix-x/datagrid-ui - v0.1.2
    Preparing search index...

    @helix-x/datagrid-ui - v0.1.2

    @helix-x/datagrid-ui

    A dependency-free React data grid: virtualized rows, server-side paging / sorting / filtering, inline row editing, multi-select, CSV + clipboard export and persisted column preferences.

    Its only runtime requirement is React. Styling is plain Tailwind utility classes, so there is no CSS file to import and no theme engine to configure.

    A runnable Vite gallery with a mock stock-market API lives in example/:

    cd example
    npm install
    npm run dev

    Four examples, all against a real server-side backend:

    Server-side market data 480 symbols; paging, sorting and all four filter kinds resolved on the server, plus inline editing with server-side validation
    Images in rows company logos and analyst avatars, lazy-loaded with reserved boxes and error fallbacks
    Live updates an SSE feed patched in with api.updateRows() — no refetch, no lost scroll position
    Theme customization accent, density and dark mode driven entirely by CSS custom properties

    Each example sits behind a Preview / Code toggle — the running grid, or its real source — and is followed by a How it works section pairing the explanation with the code that implements it, deep-linked to the exact lines on GitHub. Every snippet is extracted from the source files at build time, so none of it can drift.

    The package is a standalone module — it can be installed from a registry, a tarball, a git URL, or a relative path:

    npm install @helix-x/datagrid-ui
    # or, consuming it from a checkout next to your app:
    npm install file:../helix-x-datagrid

    React 18 or 19 must already be present; it is a peer dependency and is never bundled into the output.

    The grid renders Tailwind utility classes. Tailwind only generates classes it can see, and it skips node_modules during automatic content detection, so point it at the shipped bundle explicitly:

    /* your Tailwind v4 entry point */
    @import "tailwindcss";
    @source "../node_modules/@helix-x/datagrid-ui/dist/index.js";

    On Tailwind v3, add the same path to content in tailwind.config.js, and define the four colour variables below as well. Row backgrounds (stripe, selection, editing, hover) are opaque colours mixed at runtime from var(--color-…), so the sticky checkbox column never shows the cells scrolling underneath it. v4 emits those variables for you; v3 emits none, and without them rows render with no background at all:

    /* Tailwind v3 only */
    :root {
    --color-white: theme(colors.white);
    --color-gray-50: theme(colors.gray.50);
    --color-gray-900: theme(colors.gray.900);
    --color-brand-500: theme(colors.brand.500);
    }

    The grid uses the brand, gray and error colour families and the class-based dark variant. If your project does not already define them:

    @custom-variant dark (&:is(.dark *));

    @theme {
    --color-brand-25: #f2f7ff;
    --color-brand-50: #ecf3ff;
    --color-brand-200: #c2d6ff;
    --color-brand-400: #7592ff;
    --color-brand-500: #465fff;
    --color-brand-600: #3641f5;

    --color-error-50: #fef3f2;
    --color-error-300: #fda29b;
    --color-error-500: #f04438;
    --color-error-600: #d92d20;
    --color-error-700: #b42318;
    }
    import { DataGrid, type ColumnDef, type GridApi } from '@helix-x/datagrid-ui';

    const columns: ColumnDef<Person, Ctx>[] = [
    { field: 'id', header: 'ID', width: 90, filter: 'number' },
    { field: 'name', header: 'Name', flex: 1, filter: 'text', editable: true },
    { field: 'status', header: 'Status', filter: 'set',
    filterParams: { values: ['ACTIVE', 'CLOSED'] },
    editable: true, editor: 'select',
    editorParams: { options: [{ label: 'Active', value: 'ACTIVE' }] } },
    ];

    <DataGrid
    columns={columns}
    getRowId={(row) => row.id}
    dataSource={{ getRows: (request, signal) => api.list(request, signal) }}
    storageKey="people"
    context={{ onEdit }}
    onRowCommit={async (draft) => {
    const parsed = schema.safeParse(draft);
    if (!parsed.success) return { ok: false, errors: toFieldErrors(parsed.error) };
    await api.save(draft);
    return { ok: true };
    }}
    apiRef={apiRef}
    />

    getRows receives a request that is structurally identical to ag-grid's server-side row model request, so an endpoint written for that model works unchanged:

    { startRow, endRow, sortModel: [{ colId, sort }], filterModel,
    rowGroupCols: [], valueCols: [], pivotCols: [], pivotMode: false, groupKeys: [] }

    and returns { rows, lastRow }. Filter models use the same four shapes (text, number, date, set) that ag-grid emits.

    Column definitions should be memoised on []. Anything volatile — in-flight ids, permission checks, event handlers — belongs in context, which is passed to every cellRenderer. Changing context re-renders cells without rebuilding a single column definition.

    Full generated reference: https://suryakand.github.io/datagrid-ui/

    Every exported symbol carries a doc comment — parameters, return values, defaults, and runnable examples on the types you actually write (ColumnDef, DataGridProps, HxDataSource, GridApi). The comments ship inside dist/index.d.ts too, so they appear on hover in any editor without visiting the site.

    Build it locally:

    npm run docs         # -> docs/
    npm run docs:watch

    The generator is TypeDoc, not JSDoc. It reads the same /** ... */ comments but takes parameter and return types from TypeScript itself, so signatures cannot drift from the code the way hand-written @param {Type} annotations do.

    typedoc.json turns on link, export and coverage validation, and CI builds with --treatWarningsAsErrors. A broken {@link}, a type referenced from the public API but never exported, or a new export with no doc comment fails the docs build rather than shipping a gap.

    npm install       # build toolchain only; React comes from the host app
    npm run build # dist/ — ESM, CJS and .d.ts
    npm run dev # rebuild on change
    npm run typecheck
    npm run docs # docs/ — generated API reference

    When an app consumes this package through a relative path or npm link, npm creates a symlink and Node can resolve a second copy of React from the package's own tree. Nothing here installs React (.npmrc sets legacy-peer-deps so the peer range is not auto-installed), but bundlers should still be told to dedupe:

    // vite.config.ts
    resolve: { dedupe: ['react', 'react-dom'] }

    Two workflows, deliberately separate:

    Workflow Trigger What it does
    .github/workflows/publish.yml push to main typecheck, build, write the release notes, publish to npm, tag v<version>, create the GitHub release with those notes, then commit the next version bump
    .github/workflows/docs.yml the publish workflow completing successfully rebuild the API reference at the released commit and deploy it to GitHub Pages

    The docs workflow keys off workflow_run rather than on: release. The publish job creates its release with the default GITHUB_TOKEN, and events raised by that token deliberately do not trigger further workflows — an on: release trigger would never fire. It also checks out the publish run's head_sha, so the documentation describes the code that was actually released rather than the version-bump commit pushed on top of it.

    Release notes are built from the commits since the previous v* tag by .github/scripts/release-notes.mjs, because main is pushed to directly and GitHub's own generated notes only list merged pull requests. Commits written as Conventional Commits are grouped into breaking changes, features and fixes; any other message is listed as written, so a commit subject is the line users will read. Preview the next release's notes with:

    node .github/scripts/release-notes.mjs
    

    Repository settings this needs: Pages source set to GitHub Actions (Settings → Pages), and an NPM_TOKEN secret for the publish workflow.

    npm pack produces an installable tarball; prepack rebuilds dist/ first, so the published artifact is never stale.

    Row grouping, pivoting, tree data, master/detail, variable row heights, and .xlsx output (CSV with a BOM opens natively in Excel).