npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2025 – Pkg Stats / Ryan Hefner

svelte-number-formatter

v1.2.1

Published

Simple reactive number formatter for Svelte + TypeScript inputs

Readme

🔢 svelte-number-formatter

A powerful, reactive number formatter utility for Svelte + TypeScript with comprehensive validation, real-time formatting, and extensive customization options.

✨ Features

  • Live number formatting for inputs (12,345.67, $1,000.00, 85%, etc.)
  • Input validation with custom error messages and warnings
  • Multiple formatting styles (decimal, currency, percentage)
  • Locale-aware formatting with automatic browser detection
  • Real-time reactive updates with Svelte store integration
  • Comprehensive input cleaning and sanitization
  • Min/max value validation with custom ranges
  • Prefix/suffix support for custom formatting
  • Strict mode for rejecting invalid input
  • Increment/decrement utilities for stepper controls
  • TypeScript support with full type definitions

📦 Installation

From npm (public)

npm install svelte-number-formatter

From GitHub Packages

npm install @dev-henen/svelte-number-formatter --registry=https://npm.pkg.github.com

📁 GitHub Repository: github.com/dev-henen/svelte-number-formatter


🚀 Getting Started

import { NumberFormatter } from 'svelte-number-formatter';

const formatter = new NumberFormatter();

✨ Basic Usage in a Svelte Component

<script lang="ts">
	import { NumberFormatter } from 'svelte-number-formatter';
	const formatter = new NumberFormatter();
</script>

<input bind:value={formatter.handler} />
<p>Raw: {formatter.raw}</p>
<p>Formatted: {formatter.formatted}</p>
<p>Numeric Value: {formatter.value}</p>

or, using a local value:

<script lang="ts">
	import { NumberFormatter } from 'svelte-number-formatter';
	const formatter = new NumberFormatter();
	let value = formatter.formatted;
	$: formatter.handler = value;
</script>

<input bind:value={value} />
<p>Raw: {formatter.raw}</p>
<p>Formatted: {formatter.formatted}</p>

🔧 Constructor

new NumberFormatter(initial?, options?)

Create a new formatter with optional initial value and formatting options.

const formatter = new NumberFormatter("1234.56", {
	style: 'currency',
	currency: 'USD',
	decimals: 2,
	useGrouping: true
});

📊 Properties

| Property | Type | Description | | ----------- | -------- | -------------------------------------------------- | | handler | string | Input setter that auto-updates raw + formatted | | raw | string | The numeric value stripped of symbols | | formatted | string | The value formatted for display (12,345.67) | | value | number | The parsed numeric value |

Reactive Stores

| Store | Type | Description | | -------------- | ----------------------- | ------------------------------------- | | validation | Readable<ValidationResult> | Current validation state | | isEditing | Readable<boolean> | Whether input is currently being edited | | numericValue | Readable<number> | Parsed numeric value as store |

🔁 Setting .handler = "12345" will automatically update .raw, .formatted, and .value.


⚙️ Configuration Options

setOptions(options: Partial<FormatOptions>)

Update formatting options dynamically:

formatter.setOptions({
	style: 'currency',
	currency: 'EUR',
	decimals: 2,
	min: 0,
	max: 10000
});

FormatOptions

type FormatOptions = {
	locale?: string;                           // e.g., "en-US", "de-DE"
	useGrouping?: boolean;                     // thousand separators (default: true)
	decimals?: number;                         // decimal places (default: 0)
	currency?: string;                         // e.g., "USD", "EUR"
	style?: "decimal" | "currency" | "percent"; // formatting style
	allowNegative?: boolean;                   // allow negative numbers (default: true)
	allowDecimal?: boolean;                    // allow decimal input (default: true)
	min?: number;                              // minimum value
	max?: number;                              // maximum value
	prefix?: string;                           // custom prefix
	suffix?: string;                           // custom suffix
	placeholder?: string;                      // placeholder for empty values
	strict?: boolean;                          // reject invalid input (default: false)
};

🎯 Methods

Core Methods

format(value: string | number): string

Format a raw number programmatically:

formatter.format("123456.789"); // → "123,456.79" or "$123,456.79"

setValue(value: string | number): void

Set the value programmatically:

formatter.setValue(1234.56);

reset(): void

Clear all values and reset validation state:

formatter.reset();

Validation Methods

isValid(): boolean

Check if current value is valid:

if (formatter.isValid()) {
	// proceed with valid value
}

getValidation(): ValidationResult

Get detailed validation information:

const validation = formatter.getValidation();
console.log(validation.isValid, validation.error, validation.warning);

Utility Methods

increment(step?: number): void

Increment the current value:

formatter.increment(1);    // +1
formatter.increment(10);   // +10

decrement(step?: number): void

Decrement the current value:

formatter.decrement(1);    // -1
formatter.decrement(5);    // -5

focus(): void / blur(): void

Simulate focus/blur for form integration:

formatter.focus();  // sets isEditing to true
formatter.blur();   // sets isEditing to false

📡 Subscription Methods

Enhanced Subscription

Subscribe to all formatter state changes:

const unsubscribe = formatter.subscribe(({ raw, formatted, value, validation, isEditing }) => {
	console.log("Raw:", raw);
	console.log("Formatted:", formatted);
	console.log("Value:", value);
	console.log("Valid:", validation.isValid);
	console.log("Editing:", isEditing);
});

Convenience Subscriptions

subscribeFormatted(run: Subscriber<string>): Unsubscriber

const unsubscribe = formatter.subscribeFormatted(formatted => {
	console.log("Formatted:", formatted);
});

subscribeRaw(run: Subscriber<string>): Unsubscriber

const unsubscribe = formatter.subscribeRaw(raw => {
	console.log("Raw:", raw);
});

subscribeValue(run: Subscriber<number>): Unsubscriber

const unsubscribe = formatter.subscribeValue(value => {
	console.log("Value:", value);
});

🔍 Validation System

The formatter includes a comprehensive validation system:

ValidationResult Type

type ValidationResult = {
	isValid: boolean;
	error?: string;     // Validation error message
	warning?: string;   // Warning message (non-blocking)
};

Example with Validation

<script lang="ts">
	import { NumberFormatter } from 'svelte-number-formatter';
	
	const formatter = new NumberFormatter("", {
		min: 0,
		max: 100,
		decimals: 2,
		strict: true
	});
	
	let validation = formatter.getValidation();
	$: validation = $formatter.validation;
</script>

<input bind:value={formatter.handler} />

{#if !validation.isValid}
	<p class="error">{validation.error}</p>
{/if}

{#if validation.warning}
	<p class="warning">{validation.warning}</p>
{/if}

🌍 Localization Examples

Currency Formatting

// US Dollar
const usdFormatter = new NumberFormatter("1234.56", {
	style: 'currency',
	currency: 'USD',
	locale: 'en-US'
});
// → "$1,234.56"

// Euro
const eurFormatter = new NumberFormatter("1234.56", {
	style: 'currency',
	currency: 'EUR',
	locale: 'de-DE'
});
// → "1.234,56 €"

Percentage Formatting

const percentFormatter = new NumberFormatter("0.85", {
	style: 'percent',
	decimals: 1
});
// → "85.0%"

Custom Prefix/Suffix

const customFormatter = new NumberFormatter("42", {
	prefix: "Score: ",
	suffix: " pts",
	useGrouping: false
});
// → "Score: 42 pts"

🎛️ Advanced Usage Examples

Stepper Input Component

<script lang="ts">
	import { NumberFormatter } from 'svelte-number-formatter';
	
	const formatter = new NumberFormatter("0", {
		min: 0,
		max: 100,
		decimals: 0
	});
</script>

<div class="stepper">
	<button on:click={() => formatter.decrement()}>-</button>
	<input bind:value={formatter.handler} />
	<button on:click={() => formatter.increment()}>+</button>
</div>

<p>Value: {formatter.value}</p>

Form Integration with Validation

<script lang="ts">
	import { NumberFormatter } from 'svelte-number-formatter';
	
	const priceFormatter = new NumberFormatter("", {
		style: 'currency',
		currency: 'USD',
		decimals: 2,
		min: 0,
		max: 999999,
		strict: true
	});
	
	$: isValid = $priceFormatter.validation.isValid;
</script>

<form>
	<label>
		Price:
		<input 
			bind:value={priceFormatter.handler}
			class:invalid={!isValid}
		/>
	</label>
	
	{#if !isValid}
		<span class="error">{$priceFormatter.validation.error}</span>
	{/if}
	
	<button type="submit" disabled={!isValid}>
		Submit
	</button>
</form>

🔧 Static Utility Methods

NumberFormatter.formatValue(value, options?): string

Format a value without creating a formatter instance:

const formatted = NumberFormatter.formatValue(1234.56, {
	style: 'currency',
	currency: 'USD'
});
// → "$1,234.56"

NumberFormatter.parseValue(formattedValue): number

Parse a formatted value back to a number:

const value = NumberFormatter.parseValue("$1,234.56");
// → 1234.56

📚 Common Use Cases

1. Financial Applications

const moneyFormatter = new NumberFormatter("", {
	style: 'currency',
	currency: 'USD',
	decimals: 2,
	min: 0
});

2. Percentage Inputs

const percentFormatter = new NumberFormatter("", {
	style: 'percent',
	decimals: 1,
	min: 0,
	max: 1
});

3. Quantity Inputs

const quantityFormatter = new NumberFormatter("1", {
	decimals: 0,
	min: 1,
	max: 999,
	useGrouping: false
});

4. Scientific Notation

const scientificFormatter = new NumberFormatter("", {
	decimals: 3,
	useGrouping: false,
	allowNegative: true
});

🌐 Browser Compatibility

  • Locale Detection: Automatically detects browser locale via navigator.language
  • SSR Support: Defaults to "en-US" in server-side environments
  • Modern Browsers: Uses Intl.NumberFormat for reliable formatting
  • Fallback: Graceful degradation if formatting fails

🧠 Notes

  • handler acts as a two-way reactive setter for <input> elements
  • Validation runs automatically on every input change
  • Strict mode (strict: true) rejects invalid input entirely
  • Non-strict mode allows invalid input but marks it as invalid
  • Locale is automatically detected from browser settings
  • All stores are reactive and integrate seamlessly with Svelte's reactivity system

🔗 Links


📜 License

MIT © dev-henen


🙌 Contributing

Contributions are welcome! Please feel free to submit a Pull Request.