{
	"$schema": "https://shadcn-svelte.com/schema/registry-item.json",
	"name": "voice-form-01",
	"title": "Voice Form 01",
	"type": "registry:block",
	"description": "A form with a voice-fill button that cycles through idle/recording/processing/success states.",
	"registryDependencies": [
		"card",
		"input",
		"label",
		"https://sv11.ui.twango.dev/r/voice-button.json"
	],
	"files": [
		{
			"content": "<script lang=\"ts\">\n\timport {\n\t\tCard,\n\t\tCardContent,\n\t\tCardDescription,\n\t\tCardHeader,\n\t\tCardTitle,\n\t} from \"$UI$/card/index.js\";\n\timport { Input } from \"$UI$/input/index.js\";\n\timport { Label } from \"$UI$/label/index.js\";\n\timport { VoiceButton, type VoiceButtonState } from \"$UI$/voice-button/index.js\";\n\timport { validateExampleForm, type ExampleFormValues } from \"./schema.js\";\n\n\tlet values = $state<ExampleFormValues>({ firstName: \"\", lastName: \"\" });\n\tconst errors = $derived(validateExampleForm(values));\n\n\tlet voiceState = $state<VoiceButtonState>(\"idle\");\n\tlet cycleTimers: ReturnType<typeof setTimeout>[] = [];\n\n\tfunction clearTimers() {\n\t\tcycleTimers.forEach(clearTimeout);\n\t\tcycleTimers = [];\n\t}\n\n\tfunction handleVoiceToggle() {\n\t\tif (voiceState === \"recording\" || voiceState === \"processing\") {\n\t\t\tclearTimers();\n\t\t\tvoiceState = \"idle\";\n\t\t\treturn;\n\t\t}\n\t\tclearTimers();\n\t\tvoiceState = \"recording\";\n\t\tcycleTimers.push(\n\t\t\tsetTimeout(() => {\n\t\t\t\tvoiceState = \"processing\";\n\t\t\t}, 2000)\n\t\t);\n\t\tcycleTimers.push(\n\t\t\tsetTimeout(() => {\n\t\t\t\tvalues = { firstName: \"John\", lastName: \"Doe\" };\n\t\t\t\tvoiceState = \"success\";\n\t\t\t}, 3000)\n\t\t);\n\t\tcycleTimers.push(\n\t\t\tsetTimeout(() => {\n\t\t\t\tvoiceState = \"idle\";\n\t\t\t}, 5000)\n\t\t);\n\t}\n\n\t$effect(() => {\n\t\treturn () => clearTimers();\n\t});\n\n\tfunction onSubmit(event: SubmitEvent) {\n\t\tevent.preventDefault();\n\t}\n</script>\n\n<div class=\"mx-auto w-full\">\n\t<Card class=\"relative overflow-hidden\">\n\t\t<div class=\"flex flex-col gap-2\">\n\t\t\t<CardHeader>\n\t\t\t\t<div class=\"flex items-start justify-between\">\n\t\t\t\t\t<div class=\"space-y-1\">\n\t\t\t\t\t\t<CardTitle>Voice Fill</CardTitle>\n\t\t\t\t\t\t<CardDescription>Fill fields by voice</CardDescription>\n\t\t\t\t\t</div>\n\t\t\t\t\t<VoiceButton\n\t\t\t\t\t\tstate={voiceState}\n\t\t\t\t\t\tonPress={handleVoiceToggle}\n\t\t\t\t\t\tdisabled={voiceState === \"processing\"}\n\t\t\t\t\t\ttrailing=\"Voice Fill\"\n\t\t\t\t\t/>\n\t\t\t\t</div>\n\t\t\t</CardHeader>\n\t\t\t<CardContent>\n\t\t\t\t<form onsubmit={onSubmit} class=\"space-y-6\">\n\t\t\t\t\t<div class=\"grid grid-cols-1 gap-4 sm:grid-cols-2\">\n\t\t\t\t\t\t<div class=\"space-y-2\">\n\t\t\t\t\t\t\t<Label for=\"voice-form-01-first-name\">First Name *</Label>\n\t\t\t\t\t\t\t<Input\n\t\t\t\t\t\t\t\tid=\"voice-form-01-first-name\"\n\t\t\t\t\t\t\t\tplaceholder=\"John\"\n\t\t\t\t\t\t\t\tbind:value={values.firstName}\n\t\t\t\t\t\t\t\taria-invalid={errors.firstName ? \"true\" : undefined}\n\t\t\t\t\t\t\t\taria-describedby={errors.firstName ? \"voice-form-01-first-name-error\" : undefined}\n\t\t\t\t\t\t\t/>\n\t\t\t\t\t\t\t{#if errors.firstName}\n\t\t\t\t\t\t\t\t<p\n\t\t\t\t\t\t\t\t\tid=\"voice-form-01-first-name-error\"\n\t\t\t\t\t\t\t\t\tclass=\"text-destructive text-sm\"\n\t\t\t\t\t\t\t\t\trole=\"alert\"\n\t\t\t\t\t\t\t\t>\n\t\t\t\t\t\t\t\t\t{errors.firstName}\n\t\t\t\t\t\t\t\t</p>\n\t\t\t\t\t\t\t{/if}\n\t\t\t\t\t\t</div>\n\t\t\t\t\t\t<div class=\"space-y-2\">\n\t\t\t\t\t\t\t<Label for=\"voice-form-01-last-name\">Last Name *</Label>\n\t\t\t\t\t\t\t<Input\n\t\t\t\t\t\t\t\tid=\"voice-form-01-last-name\"\n\t\t\t\t\t\t\t\tplaceholder=\"Doe\"\n\t\t\t\t\t\t\t\tbind:value={values.lastName}\n\t\t\t\t\t\t\t\taria-invalid={errors.lastName ? \"true\" : undefined}\n\t\t\t\t\t\t\t\taria-describedby={errors.lastName ? \"voice-form-01-last-name-error\" : undefined}\n\t\t\t\t\t\t\t/>\n\t\t\t\t\t\t\t{#if errors.lastName}\n\t\t\t\t\t\t\t\t<p id=\"voice-form-01-last-name-error\" class=\"text-destructive text-sm\" role=\"alert\">\n\t\t\t\t\t\t\t\t\t{errors.lastName}\n\t\t\t\t\t\t\t\t</p>\n\t\t\t\t\t\t\t{/if}\n\t\t\t\t\t\t</div>\n\t\t\t\t\t</div>\n\t\t\t\t</form>\n\t\t\t</CardContent>\n\t\t</div>\n\t</Card>\n</div>\n",
			"type": "registry:block",
			"target": "components/blocks/voice-form-01/voice-form-01.svelte"
		},
		{
			"content": "export type ExampleFormValues = {\n\tfirstName: string;\n\tlastName: string;\n};\n\nexport type ExampleFormErrors = Partial<Record<keyof ExampleFormValues, string>>;\n\nexport function validateExampleForm(values: ExampleFormValues): ExampleFormErrors {\n\tconst errors: ExampleFormErrors = {};\n\tif (values.firstName.length > 0 && values.firstName.length < 2) {\n\t\terrors.firstName = \"First name must be at least 2 characters.\";\n\t}\n\tif (values.lastName.length > 0 && values.lastName.length < 2) {\n\t\terrors.lastName = \"Last name must be at least 2 characters.\";\n\t}\n\treturn errors;\n}\n",
			"type": "registry:block",
			"target": "components/blocks/voice-form-01/schema.ts"
		},
		{
			"content": "import VoiceForm01 from \"./voice-form-01.svelte\";\n\nexport { VoiceForm01, VoiceForm01 as default };\nexport { validateExampleForm } from \"./schema.js\";\nexport type { ExampleFormValues, ExampleFormErrors } from \"./schema.js\";\n",
			"type": "registry:block",
			"target": "components/blocks/voice-form-01/index.ts"
		}
	]
}