Svelte 5 · v2.2.0 · MIT

Numbers,
formatted right.

A reactive input component library for Svelte 5 with caret-stable formatting, two-way binding, and Intl-grade locale support. Four components, 15+ masks, zero glue code.

$npm i svelte-number-format
Quick start GitHub
NumericFormat en-US · currency
display $1,234.56 raw 1234.56
locale
currency
precision
~8.1 kB
Bundle size · gzipped
4
Components
15+
Mask patterns
200+
Locales · Intl
Features

Everything you need from a number input. Nothing you don't.

Four components — NumericFormat, PatternFormat, NumericText, and PatternText — cover the entire surface. The rest is just options.

01

Caret stable

Type, paste, delete from the middle. The caret never jumps to the end.

1,2|34.56
02

Two-way binding

bind:value works exactly like a native input. Programmatic updates re-format on the spot.

$ ↔ 99.99
03

Locale-aware

Built on Intl.NumberFormat. Switch between en-US, de-DE, ja-JP without re-mounting.

1,234 / 1.234 / 1 234
04

Currency, %, decimal

NumericFormat covers the three styles you actually use, with precision and grouping.

$ · % · #
05

15+ pattern masks

Phone, credit card, SSN, dates, IPs, MAC — drop in MaskPatterns.* and ship.

###-##-####
06

Svelte 5 native

Built for runes ($state, $derived). No legacy stores, no compat shims.

$state
07

TypeScript first

Strict types throughout. Autocomplete on every option, every mask.

<T>
08

SSR-safe display

NumericText and PatternText render formatted values server-side with no DOM.

<span> · SSR
NumericFormat

Three styles. Every locale. Zero glue code.

Pass a formatStyle, pick a precision, bind a value. The component takes care of grouping, separators, and currency symbols.

Currency USD
raw 99.99
Percent 0–1
raw 0.0875
Decimal en-US
raw 1234567.89
PatternFormat

Masks for the inputs you build over and over.

# for digits, A for letters, * for alphanumerics, anything else literal. 15+ ready-made patterns from MaskPatterns.

Phone (US) PHONE_US
format (###) ###-#### raw 4155550199
Credit Card CREDIT_CARD
format #### #### #### #### raw 4242424242424242
SSN SSN
format ###-##-#### raw 123456789
Date (US) DATE_US
format ##/##/#### raw 12252024
CPF · validated BRAZILIAN_CPF
format ###.###.###-## raw 14550200286
IPv4 IPV4
format ###.###.###.### raw 192168011
MAC Address MAC_ADDRESS
format ##:##:##:##:##:## raw a4c138ff0211
Locales

One number. Eight locales. No string concatenation.

Quick start

Two imports. One bind. Done.

If you've used react-number-format, this will feel immediately familiar — without the React.

Currency.svelte
<script lang="ts">  import { NumericFormat, NumberFormatStyle } from 'svelte-number-format'   let price = $state<number | null>(99.99)</script> <NumericFormat  bind:value={price}  locale="en-US"  options={{    formatStyle: NumberFormatStyle.Currency,    currency: 'USD', precision: 2  }}/><!-- User sees: $99.99 -->
Phone.svelte
<script lang="ts">  import { PatternFormat, MaskPatterns } from 'svelte-number-format'   let phone = $state<string | null>(null)</script> <PatternFormat  bind:value={phone}  format={MaskPatterns.PHONE_US}  placeholder="(555) 123-4567"/><!-- Display: (555) 123-4567 · raw: "5551234567" -->
FAQ

Questions, answered.

The short versions. The README has the long ones, with code.

How do I add a currency input in Svelte 5?

Install svelte-number-format and use NumericFormat with options={{ formatStyle: NumberFormatStyle.Currency, currency: 'USD', precision: 2 }}. It formats as you type, keeps the caret stable, and bind:value gives you the plain number — not the formatted string.

Does it work with Svelte 4?

No. The library is built on Svelte 5 runes and declares a svelte@^5 peer dependency. There is no Svelte 4 build.

How big is it?

PatternFormat is 4.6 kB gzipped with zero runtime dependencies; NumericFormat is ~8.1 kB gzipped including its only dependency, intl-number-input. Subpath imports let you load only what you use. Numbers are gzipped package source, pinned by size-limit budgets in CI.

How is it different from react-number-format?

Same NumericFormat and PatternFormat component names, same onValueChange payload, and the same # pattern token — plus A/* and custom regex tokens that react-number-format doesn't have. The API is idiomatic Svelte: bind:value instead of controlled-state wiring, and locale-driven separators instead of manual thousandSeparator/prefix props.

How is it different from svelte-currency-input?

svelte-currency-input is a focused, well-made currency-only field — if that's all you need, it's a fine choice. svelte-number-format covers currency plus percent and decimal inputs, pattern masks for phone, credit card and dates, display-only components, and mirrors react-number-format's API.

Does it work with Superforms, Formsnap, or Felte?

Yes — both inputs expose plain bind:value, so they drop into any Svelte form library. The demos on this site show worked integrations with Superforms, Formsnap, Felte, and Zod validation.

Is it SSR-safe with SvelteKit?

Yes. No browser APIs run at module evaluation; the default locale resolves lazily — navigator.language on the client, 'en-US' on the server. The input components render on the server and format on hydration; NumericText and PatternText render fully formatted markup during SSR.

Can I submit the raw value in a native form?

Yes — pass a name prop and a hidden input carries the raw value (1234.56, not $1,234.56) into FormData, form actions, and SvelteKit remote functions. The visible formatted input stays unnamed.

Install

Add it to your Svelte 5 project.

MIT licensed. ~8.1 kB gzipped. Zero config. Read the docs →

Live integration demos: Superforms · Formsnap · Felte · Zod 3 × 4

$npm i svelte-number-format