zaf (Zod as Form Field)
Augment Zod schemas with form metadata like labels, descriptions, and custom components.
Basic Usage
import { zaf } from '@repo/form'
import { z } from 'zod/v4'
const schema = z.object({
role: zaf(z.enum(['admin', 'user']), {
label: 'User Role',
description: 'Select permission level'
}),
internal: zaf(z.string(), { skip: true }) // hide field
})
Options
| Option | Type | Description |
|---|---|---|
label | string | Display label |
description | string | Help text |
component | SvelteComponent | Custom input component |
props | object | Props passed to component |
group | string | Group fields together |
skip | boolean | Hide field from form |
Custom Components
Pass a custom component to override the default input.
import CustomRating from './CustomRating.svelte'
const schema = z.object({
rating: zaf(z.number(), {
component: CustomRating,
props: { max: 5 }
})
})
Building a Custom Component
<!-- CustomRating.svelte -->
<script lang="ts">
let { value = $bindable(), max = 5 }: { value: number; max?: number } = $props()
</script>
<div class="flex gap-1">
{#each Array(max) as _, i}
<button type="button" onclick={() => value = i + 1}>
{i < value ? '★' : '☆'}
</button>
{/each}
</div>
Auto-mapped Input Types
Without zaf, fields map automatically based on Zod type.
| Zod Type | Input |
|---|---|
z.string() | TextInput |
z.string().email() | TextInput (type=email) |
z.number() | TextInput (type=number) |
z.boolean() | CheckboxInput |
z.enum() | SelectInput |
z.date() | DateInput |
z.object() | NestedInput |
z.array(z.object()) | TableInput |