praxis-kit
v1.0.2
Published
Praxis Kit — HTML semantics, ARIA requirements, and component composition rules as executable contracts, shared across every framework adapter. The single npm package for all adapters and tooling.
Maintainers
Readme
praxis-kit (packages/kit)
The single published package. Everything users install comes from here; every other workspace in the repo is private and gets bundled into this package's entry points at build time.
pnpm add praxis-kitStatus
Built (tsdown). The public exports surface, the framework-neutral entry files (contract.ts /
guards.ts / html.ts / utils.ts — thin re-exports of @praxis-kit/core, primitive, and
diagnostics), and Changesets (this is the only package it versions) are all in place. All 7
framework adapters are ready, including Solid and Svelte's declaration file — both formerly deferred
gaps, now resolved (see below). Not yet published (private: true) — pending review of the
build itself and the release-process wiring (CI release job, private: false flip, first tag), not
on any remaining source gap.
| Entry | Bundles | State |
| ----------------------------------------- | -------------------------- | ------------------------------------------------------------------------------------------------------------------------- |
| praxis-kit/react (+ /react/legacy) | adapters/react | ✅ ready |
| praxis-kit/preact | adapters/preact | ✅ ready |
| praxis-kit/vue | adapters/vue | ✅ ready |
| praxis-kit/solid | adapters/solid | ✅ ready — real Solid JSX transform via unplugin-solid/rolldown |
| praxis-kit/svelte | adapters/svelte | ✅ ready — declarations generate correctly as of rolldown-plugin-dts@^0.28.5 (via tsdown 0.23.0) |
| praxis-kit/lit | adapters/lit | ✅ ready |
| praxis-kit/web | adapters/web | ✅ ready |
| praxis-kit/tailwind (+ .css) | lib/tailwind | ✅ ready |
| praxis-kit/eslint | plugins/eslint | ✅ ready |
| praxis-kit/ts-plugin | plugins/typescript (CJS) | ✅ ready |
| praxis-kit/vite-plugin | plugins/vite | ✅ ready — requires the consumer's own typescript at runtime (real import ts from 'typescript', not a build artifact) |
| praxis-kit/codemod | tooling/codemod | ✅ ready — fully self-contained; ts-morph vendors its own TypeScript, no peer needed |
| praxis-kit/{contract,guards,html,utils} | this folder | ✅ ready |
Formerly-deferred gaps, now resolved
- Solid. No rolldown-native Solid JSX transform was known to exist in this workspace when this
build was first written.
unplugin-solid/rolldown(backed bybabel-preset-solid, the same compileresbuild-plugin-solidwraps for../pk's tsup build) fills that gap — confirmed via tsdown's own documented Solid recipe. - Svelte's type declarations.
svelte's own shipped types use an ambientdeclare module 'svelte' { ... }augmentation rather than plain top-levelexports, which[email protected]couldn't bundle through. Fixed upstream inrolldown-plugin-dts@^0.28.5("treat script-style ambient declarations as modules"), pulled in via atsdownbump to0.23.0.
Build
tsdown.config.ts (this folder) — one entry per published subpath, plus a shared
_shared/diagnostics chunk. Two invariants scripts/postbuild.ts enforces after the build:
- No unpublished names in output. JS bundles internal
@praxis-kit/*packages directly (deps.neverBundleopts out only each entry's framework peer and@praxis-kit/diagnostics); declarations resolve@praxis-kit/*sources viadts.compilerOptions.paths.publintchecks the packed result (pnpm lint:pkg). - Single
Diagnosticsidentity.@praxis-kit/diagnosticsis built once intodist/_shared/diagnostics.*and every other entry's external@praxis-kit/diagnosticsspecifier is rewritten to a relative import into it — a class with private members bundled per entry would be a different type and a different runtime class in each.
Framework packages (react, vue, preact, solid-js, lit, svelte) stay optional peer
dependencies. typescript is an optional peer too, for vite-plugin specifically — codemod needs
none (see above), and no other entry touches it.
Verifying a release candidate
publint and a workspace typecheck check dist/ shape and source types — neither installs the
published package the way a real consumer would. pnpm --filter praxis-kit test:pack does: builds
fresh, packs, installs the tarball plus every framework peer into an isolated fixture (outside this
repo's own pnpm workspace, so nothing resolves via hoisting), imports every plain-JS public entry,
resolves types for every typed entry, and runs praxis-codemod through its real .bin symlink —
the exact sequence that caught two real bugs no amount of publint/typecheck/lint surfaced (see
DECISIONS.md). Wired into prepublishOnly, so a real npm publish can't skip it.
See DECISIONS.md ("packages/kit — real build (tsup → tsdown)") for the full writeup, including
why this isn't a straight port of ../pk's tsup config.
