s-m-r-t

MoneyInput

A monetary input component that stores values in cents for precision. Supports CAD and USD currencies with voice input for natural language amounts in smrt mode.

Installation

typescript
import { MoneyInput } from '@happyvertical/smrt-svelte';

Basic Usage

A simple money input. The value is stored in cents (e.g., 15000 = $150.00).

CA$ CAD
svelte
<script lang="ts">
  let value = $state<number | null>(null);
</script>

<MoneyInput
  name="amount"
  label="Amount"
  bind:value
/>

Currency Selection

Use currency to switch between CAD (default) and USD.

US$ USD
svelte
<MoneyInput
  name="usd-amount"
  label="Price (USD)"
  currency="USD"
  value={15000}
/>

With Constraints

Use min and max to constrain the value range (in cents).

CA$ CAD
svelte
<MoneyInput
  name="donation"
  label="Donation Amount"
  min={500}
  max={100000}
  description="Between $5.00 and $1,000.00"
/>

Required Field

Add required to mark the field as required.

CA$ CAD
svelte
<MoneyInput
  name="payment"
  label="Payment Amount"
  required
/>

Disabled State

Use disabled to prevent user interaction.

CA$ CAD
svelte
<MoneyInput
  name="total"
  label="Order Total"
  value={24999}
  disabled
/>

With Error

Display validation errors using the error prop.

CA$ CAD
Budget exceeds available funds
svelte
<MoneyInput
  name="budget"
  label="Budget"
  error="Budget exceeds available funds"
  value={500000}
/>

Voice Input (smrt Mode)

In smrt mode, users can speak monetary amounts naturally. The component parses phrases like:

  • "one hundred fifty dollars" = 15000 cents
  • "twenty five fifty" = 2550 cents ($25.50)
  • "fifty cents" = 50 cents
  • "a thousand bucks" = 100000 cents
svelte
<!-- Voice example: "one hundred fifty dollars" -->
<MoneyInput
  name="voice"
  label="Enter Amount"
  description="A monetary amount in dollars"
/>

Interactive Example

Enter an amount to see the cents value:

CA$ CAD

Value in cents: null

Display: (empty)

svelte
<script lang="ts">
  let value = $state<number | null>(null);
</script>

<MoneyInput
  name="interactive"
  label="Enter Price"
  bind:value
/>
<p>Value in cents: {value ?? 'null'}</p>
<p>Display: {value ? '$' + (value / 100).toFixed(2) : '(empty)'}</p>

Props

PropTypeDefaultDescription
name *string-Field name for form submission
label stringundefinedField label displayed above the input
description stringundefinedDescription text for voice extraction context
placeholder string'0.00'Placeholder text shown when empty
value number | nullnullCurrent value in cents (bindable)
currency 'CAD' | 'USD''CAD'Currency code for display
min numberundefinedMinimum value in cents
max numberundefinedMaximum value in cents
disabled booleanfalseDisables the input
required booleanfalseMarks field as required
error stringundefinedError message to display
onchange (cents: number | null) => voidundefinedCallback when value changes

TypeScript

typescript
import { MoneyInput } from '@happyvertical/smrt-svelte';

// Props interface
interface Props {
  name: string;
  label?: string;
  description?: string;
  placeholder?: string;
  value?: number | null; // Value in cents
  currency?: 'CAD' | 'USD';
  min?: number; // In cents
  max?: number; // In cents
  disabled?: boolean;
  required?: boolean;
  error?: string;
  onchange?: (cents: number | null) => void;
}

Value Format

The component stores values in cents to avoid floating-point precision issues common with monetary calculations:

  • $150.00 is stored as 15000
  • $25.50 is stored as 2550
  • $0.99 is stored as 99

A hidden input {name}_cents is included for form submission with the cents value.