# Forms
`@rokkit/forms` builds complex forms from a JSON-Schema-shaped
spec. Define fields, validation rules, and dependencies
declaratively — the form builder handles rendering, validation,
dirty tracking, dynamic lookups, and submit.
## Schema-driven
```svelte
```
The renderer picks the right input per type: string → text,
boolean → toggle, enum → radio / segmented, number → number,
date → date picker.
## Auto-derived schema
Skip the schema and Rokkit infers one from the data:
```svelte
```
Useful for editable-record scenarios where the shape comes from
an API response and you just want a quick edit form.
## Validation modes
The `validateOn` prop controls when validation runs:
- `'submit'` — only on form submit (default).
- `'change'` — after every field change.
- `'blur'` — when a field loses focus.
Errors render under each field; the submit button stays
disabled while errors exist (override via `onsubmit`).
## Lookups — async + dependent fields
`createLookup` wires a field to a remote (or computed) option
list, with support for cascading dependencies:
```js
import { createLookup } from '@rokkit/forms'
const cities = createLookup({
url: '/api/cities?country={country}', // {country} = form value
enableOn: ['country'] // disabled until country set
})
```
Mount via the `lookups` prop on FormRenderer. When the parent
field (`country`) changes, dependent fields (`city`) clear and
refetch.
## Field dependencies
Fields can declare `show: { field, equals }` or
`enabled: { field, equals }` rules — the renderer recomputes
visibility / enablement on every value change without you
plumbing `$derived` flows by hand.
```js
const layout = {
type: 'vertical',
elements: [
{ scope: '#/role' },
{ scope: '#/admin_only_field', show: { field: 'role', equals: 'admin' } }
]
}
```
## FormBuilder — programmatic construction
For dynamic forms where the schema is built at runtime,
`FormBuilder` exposes an imperative API: `addField`,
`removeField`, `updateField`, `isFieldDisabled`,
`refreshLookup`. Mounts the same FormRenderer under the hood.
## Custom field renderers
Register custom renderers per type or per scope:
```svelte
```
Renderers receive the field's name, value, schema, error, and
an `onchange` callback — full control over how a field draws.
## Submit + actions
The default action bar carries Reset + Submit; both are themable
or can be hidden via `hideActions`. `onsubmit` fires with the
current data when validation passes; `onreset` clears to
defaults.