Skip to content
Merged
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
2 changes: 1 addition & 1 deletion .vscode/settings.json
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@
"editor.formatOnSaveMode": "file",
"js/ts.experimental.useTsgo": true,
"js/ts.tsdk.path": "./node_modules/typescript",
// ESLint is only used for markdown; JS/TS is linted by the oxc extension
// ESLint is only used for Markdown; JS/TS is linted by the Oxc extension
"eslint.validate": ["markdown"],
"eslint.problems.shortenToSingleLine": true,
"files.readonlyInclude": {
Expand Down
20 changes: 10 additions & 10 deletions AGENTS.md
Original file line number Diff line number Diff line change
Expand Up @@ -9,11 +9,11 @@ src/
index.ts # public API surface; all exports go through here
DataGrid.tsx # main <DataGrid> component (generic: <R, SR, K>)
TreeDataGrid.tsx # wraps DataGrid, adds row grouping (role="treegrid")
types.ts # shared type definitions (e.g. Column, CalculatedColumn, render props, events)
types.ts # shared type definitions (e.g., Column, CalculatedColumn, render props, events)
hooks/ # shared custom React hooks
utils/ # pure utilities (e.g. keyboard, DOM, events, colSpan, style)
utils/ # pure utilities (e.g., keyboard, DOM, events, colSpan, style)
style/ # build-time CSS via ecij tagged templates; layers.css declares @layer order
cellRenderers/ # default cell renderers (e.g. checkbox, toggleGroup, value)
cellRenderers/ # default cell renderers (e.g., checkbox, toggleGroup, value)
editors/ # default editors (renderTextEditor)
test/
browser/ # vitest browser-mode tests (Playwright: Chromium, Firefox, WebKit)
Expand All @@ -30,10 +30,10 @@ website/ # demo site (Vite + TanStack Router)
- **TypeScript strict** with `exactOptionalPropertyTypes`, `verbatimModuleSyntax`, `erasableSyntaxOnly`. Distinguish missing properties from `undefined` values.
- **`Maybe<T>`** (`T | undefined | null`) — used for all nullable column/render props. Do not use bare `T | undefined`.
- **`NoInfer<>`** — wrap callback parameters to prevent reverse type inference into component generics.
- **CSS layers** — all styles live in nested `@layer rdg.<Name>` sub-layers (e.g. `rdg.Cell`, `rdg.Row`; declared in `src/style/layers.css`). Use `ecij` `css` tagged templates (build-time extraction, not runtime CSS-in-JS). Co-locate styles in component files; `src/style/` is for shared styles.
- **Dual classnames** — components apply both a semantic class (`rdg-cell`) and a generated hash. Preserve both.
- **CSS layers** — all styles live in nested `@layer rdg.<Name>` sub-layers (e.g., `rdg.Cell`, `rdg.Row`). When a sub-layer overrides another sub-layer's styles, declare both in `src/style/layers.css`, which sets their order; undeclared sub-layers come after the declared ones. Use `ecij` `css` tagged templates (build-time extraction, not runtime CSS-in-JS). Co-locate styles in component files; `src/style/` is for shared styles.
- **Dual class names** — components apply both a semantic class (`rdg-cell`) and a generated hash. Preserve both.
- **Light/dark mode** — handled via CSS `light-dark()` + `color-scheme`, not JS.
- **Accessibility first** — ARIA attributes (e.g. `aria-colindex`, `aria-rowindex`, `aria-selected`, roles) are required. Tests query by role.
- **Accessibility first** — ARIA attributes (e.g., `aria-colindex`, `aria-rowindex`, `aria-selected`, roles) are required. Tests query by role.
- **Build** — `vp pack` bundles the library to `lib/`, then lints the packed package with publint; `ecij` plugin prefixes classes with `rdg-{version}-` (dots→dashes) to avoid cross-version conflicts.
- **Workflows** — pin every action to a full commit SHA with its version in a comment (Dependabot updates both), pass expressions to `run` steps through `env` instead of inlining `${{ }}`, grant each job only the `permissions` it uses, and check out with `persist-credentials: false`. Jobs that install dependencies only get read permissions: publishing, pushing, and editing PRs happen in separate jobs that receive build output as artifacts and never install the project's dependencies.
- **Releases** — the header of `.github/workflows/publish.yml` explains how to publish. Its read-only `build` job hands `lib/` to the `publish` job, so the project's dependencies never run with the `id-token: write` permission that npm's trusted publishing relies on, and a separate `release` job creates the GitHub release.
Expand All @@ -43,14 +43,14 @@ website/ # demo site (Vite + TanStack Router)
- Browser tests use `vite-plus/test/browser` + Playwright. `test/setupBrowser.ts` configures `page.render()` via `vitest-browser-react` and registers custom locators via `locators.extend()` — prefer `page.getGrid()`, `page.getCell({ name })`, `page.getRow()`, `page.getHeaderCell()`, `page.getActiveCell()`, etc. over raw `page.getByRole()`.
- Test helpers in `test/browser/utils.tsx`: `setup()`, `getRowWithCell()`, `getCellsAtRowIndex()`, `validateCellPosition()`, `scrollGrid()`, `safeTab()`, `testCount()`, `testRowCount()`.
- `test/failOnConsole.ts` fails tests on unexpected console warnings/errors.
- **Never run visual regression tests** — screenshots are environment-dependent so visual regression tests must run in CI only.
- **Never run visual regression tests** — screenshots are environment-dependent, so visual regression tests must run in CI only.

## Tooling

The project uses [Vite+](https://viteplus.dev/guide/), whose global `vp` CLI wraps Vite, Rolldown, Vitest, tsdown, Oxlint, Oxfmt, and Vite Task. Run `vp` directly, not through `npx`. Its docs are in `node_modules/vite-plus/docs`.

- `vp <command>` runs a built-in command, e.g. `vp dev`, `vp check`, `vp test`, `vp pack`, `vp build`.
- `vp run <task>` runs a task from `vite.config.ts`, e.g. `vp run typecheck`, `vp run eslint`, `vp run ci`.
- `vp <command>` runs a built-in command, e.g., `vp dev`, `vp check`, `vp test`, `vp pack`, `vp build`.
- `vp run <task>` runs a task from `vite.config.ts`, e.g., `vp run typecheck`, `vp run eslint`, `vp run ci`.
- Run `vp install` after pulling changes.

## Validation
Expand All @@ -62,4 +62,4 @@ While iterating, run individual checks instead. The static checks take seconds,
- `vp run typecheck` type checks with `tsc --build`; `vp check` does not type check.
- `vp check --fix` formats and lints, fixing what it can. Without `--fix`, a formatting error stops it before linting.
- `vp run eslint` lints Markdown files.
- `vp test <files>` runs specific test files, e.g. `vp test test/browser/sorting.test.tsx`. Add `--project "browser (chromium)"` to test in a single browser, or `--project node` to run the SSR test. The full suite takes about a minute.
- `vp test <files>` runs specific test files, e.g., `vp test test/browser/sorting.test.tsx`. Add `--project "browser (chromium)"` to test in a single browser, or `--project node` to run the SSR test. The full suite takes about a minute.
Loading
Loading