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

  1. User clicks "Speak all fields" button
  2. User speaks naturally: "First name John, last name Smith, email john at example dot com"
  3. User says "done" or waits for silence timeout
  4. 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

PropTypeDefaultDescription
children *Snippet-Form content (inputs and other elements)
showModeToggle booleanfalseShow Dumb/SMRT mode toggle button
showFormListen booleanfalseShow form-level "Speak all fields" button
silenceTimeout number5Seconds 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>) => voidundefinedCallback on form submit (prevents native submission)
method 'GET' | 'POST''GET'HTTP method for native form submission
action stringundefinedForm 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