@chemical-x/forms
| Install | |
|---|---|
npm install @chemical-x/forms |
|
| Latest Version: | 0.13.0 |
| Vue: | 3 |
| License: | MIT |
| Last Updated: | Oct 19, 2026 |
| Links: | GitHub · npm |
Chemical X Forms
A schema-driven form library for Vue 3 and Nuxt. Bring a Zod schema (or your own validator); useForm returns typed reads, writes, errors, and a submit handler. Every path, value, and error is inferred from the schema — no any, no string keys.
Installation
npm install @chemical-x/forms zod
Nuxt 3 / 4 — install the module:
// nuxt.config.ts
export default defineNuxtConfig({
modules: ['@chemical-x/forms/nuxt'],
})
Bare Vue 3 — install the plugin and the Vite plugin:
// main.ts
import { createApp } from 'vue'
import { createChemicalXForms } from '@chemical-x/forms'
createApp(App).use(createChemicalXForms()).mount('#app')
// vite.config.ts
import vue from '@vitejs/plugin-vue'
import { chemicalXForms } from '@chemical-x/forms/vite'
export default defineConfig({
plugins: [vue(), chemicalXForms()],
})
Quick start
<script setup lang="ts">
import { z } from 'zod'
import { useForm } from '@chemical-x/forms/zod' // zod v4; use /zod-v3 for v3
const schema = z.object({
email: z.email(),
password: z.string().min(8),
})
const form = useForm({ schema, key: 'signup' })
const onSubmit = form.handleSubmit(async (values) => {
await $fetch('/api/signup', { method: 'POST', body: JSON.stringify(values) })
})
</script>
<template>
<form @submit.prevent="onSubmit">
<input v-register="form.register('email')" placeholder="Email" />
<small v-if="form.errors.email?.[0]">{{ form.errors.email[0].message }}</small>
<input v-register="form.register('password')" type="password" placeholder="Password" />
<small v-if="form.errors.password?.[0]">{{ form.errors.password[0].message }}</small>
<button :disabled="form.state.isSubmitting">Sign up</button>
</form>
</template>
useForm({ schema, key }) returns a Pinia-style reactive object — read leaves directly, no .value:
form.values— current values.form.values.email,form.values.address.city.form.errors— per-field errors, keyed by dotted path.form.errors.email?.[0]?.message.form.fieldState— per-field flags (dirty,touched,errors,blank, …).form.fieldState.email.dirty.form.state— form-level flags (isSubmitting,isValid,canUndo, …).form.register(path)— typed two-way binding; pair withv-registeron<input>/<textarea>/<select>.form.handleSubmit(onValid, onInvalid?)— runs validation, dispatches. The valid callback receives the strict zod-inferred type.form.setValue(path, value),form.reset(), field-array helpers, undo / redo, persistence — see the API reference.
Features
- Schema-driven types — every path, value, and error is inferred from the schema; no
any. - Live validation — debounced
'change'by default;'blur'and'none'available; async refinements await before submit dispatches. - Field arrays —
append/prepend/insert/remove/swap/move/replace, fully typed at the call site. - Drafts + undo / redo — per-field opt-in persistence (
localStorage/sessionStorage/ IndexedDB / custom backend) and a bounded undo stack. - Server errors —
parseApiErrors(payload)normalises a{ message, code }[]wire format; pair withform.setFieldErrors(...). User errors survive schema revalidation. - Stable error codes — every
ValidationErrorcarriescode: string. Library codes (cx:) live on the exportedCxErrorCodeenum; adapter codes use azod:prefix; consumers pick their own (api:,auth:, …). - Clearable required fields — the
unsetsentinel marks a field displayed-empty while storage holds the schema's slim default. Submit fails with'No value supplied'for required schemas;.optional()/.nullable()/.default(N)opt out. - SSR — Nuxt handles the payload round-trip automatically; bare Vue uses
renderChemicalXState/hydrateChemicalXState(recipe).
Documentation
- API reference — every public export with signatures and return shapes
- Recipes — task-oriented walkthroughs for every feature above
- Troubleshooting — common gotchas and fixes
- Migration guides — per-release upgrade notes
- Performance — how it scales; when to worry
- Changelog — full release history
Status
Pre-1.0. SemVer applies from v1.0 onward; 0.x minor bumps may still include breaking changes, each documented under docs/migration/.
License
MIT — see LICENSE.
Related Packages
Fast and small library built on top of the native Vue.js API, providing a safe a...
A typed Vue 3 composable for synchronizing reactive values with Vue Router query...
Version History
| Version | Released | Vue | License |
|---|---|---|---|
| 0.13.0 | >=3.5.0 | MIT | |
| 0.12.1 | >=3.5.0 | MIT | |
| 0.12.0 | >=3.5.0 | MIT | |
| 0.11.1 | >=3.5.0 | MIT | |
| 0.11.0 | >=3.5.0 | MIT | |
| 0.10.0 | >=3.5.0 | MIT | |
| 0.9.0 | >=3.5.0 | MIT | |
| 0.8.3 | >=3.5.0 | MIT | |
| 0.8.2 | >=3.5.0 | MIT | |
| 0.8.1 | >=3.5.0 | MIT | |
| 0.8.0 | >=3.5.0 | MIT | |
| 0.7.2 | >=3.5.0 | MIT | |
| 0.7.1 | >=3.5.0 | MIT | |
| 0.7.0 | >=3.5.0 | MIT | |
| 0.6.0 | >=3.5.0 | MIT | |
| 0.5.1 | >=3.5.0 | MIT | |
| 0.5.0 | >=3.5.0 | MIT | |
| 0.4.1 | >=3.5.0 | MIT | |
| 0.4.0 | >=3.5.0 | MIT | |
| 0.3.29 | >=3.5.0 | MIT | |
| 0.3.28 | >=3.5.0 | MIT | |
| 0.3.27 | >=3.5.0 | MIT | |
| 0.3.26 | >=3.5.0 | MIT | |
| 0.3.25 | >=3.5.0 | MIT | |
| 0.3.24 | >=3.5.0 | MIT | |
| 0.3.23 | >=3.5.0 | MIT | |
| 0.3.22 | >=3.5.0 | MIT | |
| 0.3.21 | >=3.5.0 | MIT | |
| 0.3.20 | >=3.5.0 | MIT | |
| 0.3.19 | >=3.5.0 | MIT |
Showing the latest 30 of 79. See every release on npm