Skip to main content

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

OptionTypeDescription
labelstringDisplay label
descriptionstringHelp text
componentSvelteComponentCustom input component
propsobjectProps passed to component
groupstringGroup fields together
skipbooleanHide 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 TypeInput
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