https://github.com/fmaclen/svelte-currency-input
A masked form input that converts numbers to localized currency formats as you type
https://github.com/fmaclen/svelte-currency-input
currency i18n input svelte
Last synced: 6 months ago
JSON representation
A masked form input that converts numbers to localized currency formats as you type
- Host: GitHub
- URL: https://github.com/fmaclen/svelte-currency-input
- Owner: fmaclen
- License: mit
- Created: 2022-09-15T04:25:38.000Z (almost 4 years ago)
- Default Branch: main
- Last Pushed: 2024-11-01T21:04:47.000Z (over 1 year ago)
- Last Synced: 2025-03-16T23:42:34.125Z (over 1 year ago)
- Topics: currency, i18n, input, svelte
- Language: TypeScript
- Homepage: https://svelte-currency-input.fernando.is
- Size: 396 KB
- Stars: 42
- Watchers: 4
- Forks: 5
- Open Issues: 9
-
Metadata Files:
- Readme: README.md
- License: LICENSE
Awesome Lists containing this project
README
# svelte-currency-input
A fully-featured currency input component for Svelte 5 that handles formatting, localization, and validation as you type.

👩💻 Play with it in the live demo
---
- [Features](#features)
- [Installation](#installation)
- [Usage](#usage)
- [How it works](#how-it-works)
- [API](#api)
- [Examples](#examples)
- [Styling](#styling)
- [Exported utilities](#exported-utilities)
- [Svelte 4 / migration guide](#svelte-4)
- [Contributing](#contributing)
## Features
- Formats **positive** and **negative** values
- Leverages [`Intl.NumberFormat`](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Intl/NumberFormat) for **localizing** currency denominations
- Supports **abbreviations** (k, m, b) for quick input
- Configurable **decimal precision** with multiple control options
- **Min/max constraints** with arrow key stepping
- Custom **prefix** and **suffix** support
- **Zero built-in styles** — works with Tailwind, vanilla CSS, or any framework
- Simple, single `` element (no wrapper)
- Full **TypeScript** support
- **Lightweight** — ~3.6KB gzipped with no runtime dependencies
- API and logic heavily inspired by [@cchanxzy](https://github.com/cchanxzy)'s [react-currency-input-field](https://github.com/cchanxzy/react-currency-input-field)
## Installation
```bash
# bun
bun add @canutin/svelte-currency-input
# pnpm
pnpm add @canutin/svelte-currency-input
# npm
npm install @canutin/svelte-currency-input
# yarn
yarn add @canutin/svelte-currency-input
```
## Usage
```svelte
import { CurrencyInput } from '@canutin/svelte-currency-input';
let value = $state('1234.56');
```
The input displays `$1,234.56` while `value` contains the raw string `"1234.56"`.
## How it works
The component renders a single `` element. The `value` prop is a **string** representing the unformatted number:
- `""` = empty input
- `"0"` = zero
- `"1234.56"` = the number 1234.56
The formatted display (e.g., `$1,234.56`) is handled internally. For form submissions where you need the raw value, you can add a hidden input:
```svelte
```
## API
### Props
| Prop | Type | Default | Description |
| ------------------------ | --------------------------------------- | ----------- | ------------------------------------------------------------------------------- |
| `value` | `string` | `''` | Bindable raw value (e.g., `"1234.56"`) |
| `intlConfig` | `IntlConfig` | `undefined` | Locale and currency configuration |
| `prefix` | `string` | From locale | Override the currency prefix |
| `suffix` | `string` | `''` | Override the currency suffix |
| `decimalSeparator` | `string` | From locale | Override the decimal separator |
| `groupSeparator` | `string` | From locale | Override the grouping separator |
| `disableGroupSeparators` | `boolean` | `false` | Disable thousand separators |
| `allowDecimals` | `boolean` | `true` | Allow decimal values |
| `decimalsLimit` | `number` | `2` | Max decimal digits while typing |
| `decimalScale` | `number` | `undefined` | Pad/trim decimals on blur |
| `fixedDecimalLength` | `number` | `undefined` | Fixed decimal input (e.g., `2`: typing `123` → `1.23`) |
| `allowNegativeValue` | `boolean` | `true` | Allow negative values |
| `min` | `number` | `undefined` | Minimum value (enforced on arrow key step) |
| `max` | `number` | `undefined` | Maximum value (enforced on arrow key step) |
| `maxLength` | `number` | `undefined` | Max characters (excluding formatting) |
| `step` | `number` | `undefined` | Arrow key increment/decrement |
| `disableAbbreviations` | `boolean` | `false` | Disable k/m/b abbreviations |
| `formatValueOnBlur` | `boolean` | `true` | Apply formatting when input loses focus |
| `transformRawValue` | `(value: string) => string` | `undefined` | Transform the raw value before processing |
| `oninputvalue` | `(values: CurrencyInputValues) => void` | `undefined` | Callback on every input change |
| `onchangevalue` | `(values: CurrencyInputValues) => void` | `undefined` | Callback on blur/commit |
| `ref` | `HTMLInputElement \| null` | `null` | Bindable reference to the input element |
| `class` | `string` | `undefined` | CSS class(es) for the input |
| `...restProps` | `HTMLInputAttributes` | — | All standard input attributes (id, name, placeholder, disabled, required, etc.) |
### Types
```typescript
interface IntlConfig {
locale: string;
currency?: string;
// Also accepts other Intl.NumberFormatOptions
}
interface CurrencyInputValues {
float: number | null; // Parsed number or null if empty
formatted: string; // Display value: "$1,234.56"
value: string; // Raw value: "1234.56"
}
```
## Examples
### International currencies
```svelte
```
### Decimal precision
```svelte
```
### Min, max, and step
```svelte
```
### Custom prefix and suffix
```svelte
```
### Abbreviations
Type `1k`, `2.5m`, or `1b` to quickly enter large numbers:
```svelte
```
### Callbacks
```svelte
{
console.log('On input:', { float, formatted, value });
}}
onchangevalue={({ float, formatted, value }) => {
console.log('On blur:', { float, formatted, value });
}}
/>
```
### Input element reference
```svelte
let inputRef = $state(null);
function focusInput() {
inputRef?.focus();
}
Focus
```
## Styling
The component renders a single `` element with no built-in styles. You can use the `class` prop to style it:
```svelte
```
For dynamic styling based on value (positive/negative/zero), use the callback:
```svelte
let value = $state('');
let colorClass = $state('');
function updateStyle({ float }) {
if (float === null || float === 0) colorClass = 'text-gray-500';
else if (float > 0) colorClass = 'text-green-600';
else colorClass = 'text-red-600';
}
```
## Exported utilities
The package exports utility functions for use outside the component:
```typescript
import {
formatValue,
getLocaleConfig,
cleanValue,
parseAbbrValue,
abbrValue
} from '@canutin/svelte-currency-input';
// Format a value with locale
const formatted = formatValue({
value: '1234.56',
intlConfig: { locale: 'en-US', currency: 'USD' }
});
// → "$1,234.56"
// Get locale configuration
const config = getLocaleConfig({ locale: 'de-DE', currency: 'EUR' });
// → { decimalSeparator: ',', groupSeparator: '.', prefix: '', suffix: ' €', ... }
// Parse abbreviations
const expanded = parseAbbrValue('2.5m', 'en-US');
// → "2500000"
```
## Svelte 4
For Svelte 4 support, use the [0.x version](https://github.com/fmaclen/svelte-currency-input/tree/v0.13.0):
```bash
npm install @canutin/svelte-currency-input@0
```
If you're upgrading from v0.x, see the [migration guide](./MIGRATION.md).
## Contributing
See [CONTRIBUTING.md](./CONTRIBUTING.md) for development setup, testing, and contribution guidelines.
## License
[MIT](./LICENSE)