MeasurementInput

A measurement input component combining a numeric value with a unit selector. Perfect for physical quantities like height, weight, distance, temperature, and more.

Installation

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

Basic Usage - Height

Measure height with common units like centimeters, meters, inches, or feet.

svelte
<script lang="ts">
  const heightUnits = [
    { value: 'cm', label: 'Centimeters' },
    { value: 'm', label: 'Meters' },
    { value: 'in', label: 'Inches' },
    { value: 'ft', label: 'Feet' }
  ];

  let value = $state({ value: null, unit: 'cm' });
</script>

<MeasurementInput
  name="height"
  label="Height"
  units={heightUnits}
  bind:value
/>

Weight Measurement

Weight with default value and common units.

svelte
<MeasurementInput
  name="weight"
  label="Weight"
  units={weightUnits}
  value={{ value: 75, unit: 'kg' }}
/>

Temperature with Precision

Temperature measurement with 1 decimal place precision.

svelte
<MeasurementInput
  name="temperature"
  label="Temperature"
  units={temperatureUnits}
  decimals={1}
  min={-273.15}
  max={1000}
  bind:value
/>

Required Field

Add required to mark the field as required.

svelte
<MeasurementInput
  name="distance"
  label="Distance"
  units={distanceUnits}
  required
/>

Disabled State

Use disabled to prevent user interaction.

svelte
<MeasurementInput
  name="recorded"
  label="Recorded Weight"
  units={weightUnits}
  value={{ value: 68.5, unit: 'kg' }}
  disabled
/>

With Error

Display validation errors using the error prop.

Height seems unusually high. Please verify.
svelte
<MeasurementInput
  name="invalid"
  label="Height"
  units={heightUnits}
  value={{ value: 500, unit: 'cm' }}
  error="Height seems unusually high. Please verify."
/>

Voice Input (smrt Mode)

In smrt mode, users can speak measurements with units naturally:

  • "one hundred seventy five centimeters" → { value: 175, unit: 'cm' }
  • "five foot ten" → { value: 5.83, unit: 'ft' } (converts 5'10" to decimal)
  • "seventy five kilograms" → { value: 75, unit: 'kg' }
  • "twenty two point five degrees celsius" → { value: 22.5, unit: 'C' }
  • "ten miles" → { value: 10, unit: 'mi' }
svelte
<!-- Voice example: "one hundred seventy five centimeters" -->
<MeasurementInput
  name="voice"
  label="Height"
  description="A height measurement with units"
  units={heightUnits}
/>

Interactive Example

Enter a measurement to see the combined value and unit:

Value: (empty) m

svelte
<script lang="ts">
  let value = $state({ value: null, unit: 'm' });
</script>

<MeasurementInput
  name="interactive"
  label="Distance"
  units={distanceUnits}
  bind:value
/>
<p>Value: {value.value ?? '(empty)'} {value.unit}</p>

Props

PropTypeDefaultDescription
name *string-Field name for form submission
label stringundefinedField label displayed above the input
description stringundefinedDescription text for voice extraction context
value { value: number | null, unit: string }{ value: null, unit: "" }Current measurement with value and unit (bindable)
units *Array<{value: string, label: string}>-Available units for measurement type
min numberundefinedMinimum allowed value
max numberundefinedMaximum allowed value
decimals number2Number of decimal places
disabled booleanfalseDisables the input
required booleanfalseMarks field as required
error stringundefinedError message to display
onchange (value: { value: number | null, unit: string }) => voidundefinedCallback when value or unit changes

TypeScript

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

// Measurement value interface
interface MeasurementValue {
  value: number | null;
  unit: string;
}

// Unit option interface
interface Unit {
  value: string;
  label: string;
}

// Props interface
interface Props {
  name: string;
  label?: string;
  description?: string;
  value?: MeasurementValue;
  units: Unit[];
  min?: number;
  max?: number;
  decimals?: number;
  disabled?: boolean;
  required?: boolean;
  error?: string;
  onchange?: (value: MeasurementValue) => void;
}

Common Unit Sets

Pre-defined unit arrays for common measurement types:

typescript
// Length/Height
const heightUnits = [
  { value: 'cm', label: 'Centimeters' },
  { value: 'm', label: 'Meters' },
  { value: 'in', label: 'Inches' },
  { value: 'ft', label: 'Feet' }
];

// Weight/Mass
const weightUnits = [
  { value: 'kg', label: 'Kilograms' },
  { value: 'g', label: 'Grams' },
  { value: 'lb', label: 'Pounds' },
  { value: 'oz', label: 'Ounces' }
];

// Temperature
const temperatureUnits = [
  { value: 'C', label: '°C' },
  { value: 'F', label: '°F' },
  { value: 'K', label: 'Kelvin' }
];

// Distance
const distanceUnits = [
  { value: 'm', label: 'Meters' },
  { value: 'km', label: 'Kilometers' },
  { value: 'mi', label: 'Miles' },
  { value: 'ft', label: 'Feet' }
];

// Volume
const volumeUnits = [
  { value: 'ml', label: 'Milliliters' },
  { value: 'l', label: 'Liters' },
  { value: 'cup', label: 'Cups' },
  { value: 'gal', label: 'Gallons' }
];

Form Submission

The component submits two hidden fields for form integration:

  • {name}_value - The numeric value
  • {name}_unit - The selected unit

For example, name="height" creates height_value and height_unit fields.