Form
A smart form wrapper that enables voice-powered form filling. In SMRT mode, users can speak to fill all fields at once. The Form component provides context to child inputs and manages the speech-to-text flow.
Installation
typescript
import { Form } from '@happyvertical/smrt-svelte';Basic Usage
Wrap your form inputs to enable voice filling.
svelte
<script lang="ts">
import { Form, TextInput } from '@happyvertical/smrt-svelte';
</script>
<Form showModeToggle showFormListen>
<TextInput name="firstName" label="First Name" />
<TextInput name="lastName" label="Last Name" />
<TextInput name="email" label="Email" type="email" />
</Form>How Voice Filling Works
- User clicks "Speak all fields" button
- User speaks naturally: "First name John, last name Smith, email john at example dot com"
- User says "done" or waits for silence timeout
- Form extracts field values and populates inputs
With Custom Submit Handler
Handle form submission with JavaScript.
svelte
<script lang="ts">
import { Form, TextInput, Button } from '@happyvertical/smrt-svelte';
function handleSubmit(data: Record<string, unknown>) {
console.log('Form data:', data);
// { firstName: 'John', lastName: 'Smith', email: 'john@example.com' }
}
</script>
<Form onsubmit={handleSubmit} showFormListen>
<TextInput name="firstName" label="First Name" />
<TextInput name="lastName" label="Last Name" />
<Button type="submit">Submit</Button>
</Form>With SvelteKit Form Actions
Works seamlessly with native form submissions.
svelte
<Form method="POST" action="?/save" showFormListen>
<TextInput name="name" label="Name" />
<Button type="submit">Save</Button>
</Form>STT Adapter Options
Choose between speech recognition backends.
svelte
<!-- Whisper WASM (default) - local, private, works offline -->
<Form sttAdapter="whisper-wasm" showFormListen>
...
</Form>
<!-- Browser Speech API - uses cloud services -->
<Form sttAdapter="browser-speech" showFormListen>
...
</Form>Props
| Prop | Type | Default | Description |
|---|---|---|---|
children * | Snippet | - | Form content (inputs and other elements) |
showModeToggle | boolean | false | Show Dumb/SMRT mode toggle button |
showFormListen | boolean | false | Show form-level "Speak all fields" button |
silenceTimeout | number | 5 | Seconds of silence before stopping listening |
sttAdapter | STTAdapterType | 'whisper-wasm' | Speech-to-text adapter type |
llmModel | LLMModelId | 'none' | LLM model for field extraction ('none' uses regex-only) |
onsubmit | (data: Record<string, unknown>) => void | undefined | Callback on form submit (prevents native submission) |
method | 'GET' | 'POST' | 'GET' | HTTP method for native form submission |
action | string | undefined | Form action URL for native submission |
TypeScript
typescript
import { Form } from '@happyvertical/smrt-svelte';
type STTAdapterType = 'whisper-wasm' | 'browser-speech';
type LLMModelId = 'none' | 'smollm' | 'llama-3.2-1B-Instruct' | string;
interface FormProps {
children: Snippet;
showModeToggle?: boolean;
showFormListen?: boolean;
silenceTimeout?: number;
sttAdapter?: STTAdapterType;
llmModel?: LLMModelId;
onsubmit?: (data: Record<string, unknown>) => void;
method?: 'GET' | 'POST';
action?: string;
}Form Context
Child inputs can access the form context to participate in voice filling.
typescript
// Inside a form input component
import { tryGetFormContext } from '@happyvertical/smrt-svelte';
const formContext = tryGetFormContext();
// Register field for voice extraction
formContext?.registerField({
name: 'email',
label: 'Email Address',
type: 'email',
getValue: () => value,
setValue: (v) => value = v
});Extraction Behavior
- Regex-based - Fast, reliable field matching using labels/names
- Email handling - "at" → @, "dot" → .
- Cleanup - Trailing punctuation and speech artifacts removed
- Done keyword - Say "done" to stop listening early