Getting Started
Install
sh
npx jsr add @kin-form/core
pnpm add jsr:@kin-form/core
yarn add jsr:@kin-form/core
deno add jsr:@kin-form/coresh
npx jsr add @kin-form/react
pnpm add jsr:@kin-form/react
yarn add jsr:@kin-form/react
deno add jsr:@kin-form/react@kin-form/react includes @kin-form/core.
To add common validators or the schema validation adapter:
sh
npx jsr add @kin-form/validatorssh
pnpm add jsr:@kin-form/validatorssh
yarn add jsr:@kin-form/validatorssh
deno add jsr:@kin-form/validatorsQuick start
ts
import { FormApi } from "@kin-form/core/index.ts";
import { email, required } from "@kin-form/validators/index.ts";
const form = new FormApi({
initialValue: { email: "", password: "" },
onSubmit: async (form) => {
await login(form.value);
},
});
const emailField = form.field("email", {
validators: [required("Email is required"), email("Enter a valid email")],
});
emailInput.addEventListener(
"input",
(e) => emailField.handleChange((e.target as HTMLInputElement).value),
);
emailInput.addEventListener("blur", emailField.handleBlur);
formEl.addEventListener("submit", form.handleSubmit);tsx
import { useForm, Watch } from "@kin-form/react/index.ts";
import { email, required } from "@kin-form/validators/index.ts";
function LoginForm() {
const form = useForm({
initialValue: { email: "", password: "" },
onSubmit: async (form) => {
await login(form.value);
},
onSubmitError: () => toast.error("Failed to log in"),
});
return (
<form onSubmit={form.handleSubmit}>
<Watch
api={form.field("email", {
validators: [
required("Email is required"),
email("Enter a valid email"),
],
})}
>
{(field) => (
<>
<input
value={field.value}
onBlur={field.handleBlur}
onChange={(e) => field.handleChange(e.target.value)}
/>
{field.invalid && field.touched && <span>{field.error}</span>}
</>
)}
</Watch>
<Watch api={form} select={(f) => f.submitting}>
{(_form, submitting) => (
<button type="submit" disabled={submitting}>Log in</button>
)}
</Watch>
</form>
);
}What's next
- Concepts — the tree model, shared state, and typed paths
- Basic — building
TextFieldfromWatch, the pattern the rest of these guides lean on - Per-node Validation — validators, debouncing, and running validation explicitly
- Nested Objects and Dynamic Arrays
- Validators —
required,email,minLength, atoSchemaValidator()adapter for zod/valibot, and more