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 🙏

© 2026 – Pkg Stats / Ryan Hefner

currency-fomatter

v1.4.4

Published

Currency toolkit for React — standalone format/parse utils, headless hook, and drop-in input component with ISO 4217 support, locale auto-detection, and compact notation

Readme

currency-fomatter

The currency toolkit for React — format, parse, and input currencies with zero config.

Unlike other formatting libraries that only give you a component, currency-fomatter gives you 3 layers you can use independently:

| Layer | What | Use case | |-------|------|----------| | formatCurrency() / parseCurrency() | Standalone functions | Node.js, SSR, any JS — no React needed | | useCurrencyInput() / useCurrencyFormat() | React hooks | Headless — bring your own UI | | <CurrencyFormat /> / <PatternFormat /> | React components | Drop-in input with full formatting |

Live Demo

npm install currency-fomatter

Why currency-fomatter?

| Feature | currency-fomatter | react-number-format | react-currency-input-field | |---------|:-:|:-:|:-:| | Standalone utils (no React) | Yes | No | No | | Format + Parse symmetry | Yes | No | No | | Compact format (1K, 1M, 1B) | Yes | No | No | | ISO 4217 currency database | Yes | No | No | | Auto locale detection (Intl) | Yes | No | Partial | | React hook (headless) | Yes | No | No | | IME support (CJK input) | Yes | No | No | | Mobile keyboard (inputMode) | Auto | Manual | Manual | | Accessibility (ARIA) | Built-in | No | No | | Pattern format (phone, card) | Yes | Yes | No | | Custom input component | Yes | Yes | Yes | | TypeScript | Yes | Yes | Yes | | Bundle size | ~8KB | ~7KB | ~10KB |

Quick Start

Just format a number (no React)

import { formatCurrency, parseCurrency } from "currency-fomatter";

formatCurrency(1234567.89, { prefix: "$", thousandSeparator: "," });
// → "$1,234,567.89"

parseCurrency("$1,234,567.89", { prefix: "$", thousandSeparator: "," });
// → { value: "1234567.89", floatValue: 1234567.89 }

Auto-config from currency code (ISO 4217)

import { getCurrencyConfig, formatCurrency } from "currency-fomatter";

const usd = getCurrencyConfig("USD"); // { prefix: "$", decimalScale: 2, ... }
const jpy = getCurrencyConfig("JPY"); // { prefix: "¥", decimalScale: 0, ... }
const vnd = getCurrencyConfig("VND"); // { suffix: " ₫", decimalScale: 0, ... }

formatCurrency(1234567, getCurrencyConfig("EUR"));
// → "1,234,567.00 €"

50+ currencies built-in. Unknown currencies fall back to Intl.NumberFormat.

React component

import { CurrencyFormat } from "currency-fomatter";

<CurrencyFormat
  value={1234.56}
  prefix="$"
  thousandSeparator=","
  decimalScale={2}
  fixedDecimalScale
  onValueChange={(values) => {
    console.log(values.floatValue); // 1234.56
  }}
/>

React hook — headless, works with ANY input

import { useCurrencyInput } from "currency-fomatter";

function PriceInput() {
  const { value, formattedValue, getInputProps } = useCurrencyInput({
    currency: "USD",     // Auto-configures $, 2 decimals
    initialValue: 1234.56,
  });

  // Works with plain <input>, Material UI, Chakra, Ant Design — anything
  return <input {...getInputProps()} />;
}

Pattern format (phone, card, date)

import { PatternFormat } from "currency-fomatter";

<PatternFormat format="+1 (###) ###-####" mask="_" />
// → +1 (555) 123-4567

<PatternFormat format="#### #### #### ####" mask="_" />
// → 4111 1111 1111 1111

Standalone Utilities

formatCurrency

import { formatCurrency } from "currency-fomatter";

// Basic
formatCurrency(1234567.89);
// → "1,234,567.89"

// With options
formatCurrency(1234567.89, {
  prefix: "$",
  decimalScale: 2,
  fixedDecimalScale: true,
  thousandSeparator: ",",
});
// → "$1,234,567.89"

// Indian number system
formatCurrency(1234567, { prefix: "₹", thousandSpacing: "2s" });
// → "₹12,34,567"

parseCurrency

Round-trip parsing — the inverse of formatCurrency:

import { parseCurrency } from "currency-fomatter";

parseCurrency("$1,234.56", { prefix: "$", thousandSeparator: "," });
// → { value: "1234.56", floatValue: 1234.56, formattedValue: "$1,234.56" }

// Euro format
parseCurrency("1.234,56€", {
  suffix: "€",
  thousandSeparator: ".",
  decimalSeparator: ",",
});
// → { floatValue: 1234.56 }

formatCompact / parseCompact

Compact number notation (1K, 1M, 1B) with full round-trip support:

import { formatCompact, parseCompact } from "currency-fomatter";

formatCompact(1234567);          // → "1.23M"
formatCompact(2500000000);       // → "2.5B"
formatCompact(1500000, { prefix: "$", decimalScale: 1 }); // → "$1.5M"

// Vietnamese
formatCompact(1500000000, {
  compactDisplay: { thousand: " nghìn", million: " triệu", billion: " tỷ" },
  suffix: " ₫",
});
// → "1.5 tỷ ₫"

// Parse back
parseCompact("2.5M"); // → { value: "2500000", floatValue: 2500000 }

getCurrencyConfig

Auto-configure formatting from ISO 4217 currency codes:

import { getCurrencyConfig } from "currency-fomatter";

getCurrencyConfig("USD");
// → { prefix: "$", decimalScale: 2, fixedDecimalScale: true, thousandSeparator: ",", decimalSeparator: "." }

getCurrencyConfig("JPY");
// → { prefix: "¥", decimalScale: 0, ... }

getCurrencyConfig("VND");
// → { suffix: " ₫", decimalScale: 0, ... }

// Use with component
<CurrencyFormat value={1234.56} {...getCurrencyConfig("GBP")} />
// → £1,234.56

Locale Support

Auto-detect from browser

import { getAutoLocaleConfig } from "currency-fomatter";

// Detects user's browser locale automatically
const config = getAutoLocaleConfig("USD");
<CurrencyFormat value={1234.56} {...config} />

Any locale via Intl.NumberFormat

import { detectLocaleFormat, createLocaleConfig, formatWithIntl } from "currency-fomatter";

// Thai
detectLocaleFormat("th-TH", "THB");
// → { thousandSeparator: ",", decimalSeparator: ".", prefix: "฿", ... }

// Arabic
detectLocaleFormat("ar-SA", "SAR");

// Direct Intl formatting
formatWithIntl(1234567.89, "de-DE", { style: "currency", currency: "EUR" });
// → "1.234.567,89 €"

Static presets

Pre-configured: en-US, vi-VN, de-DE, ja-JP, en-IN, fr-FR, zh-CN, ko-KR, pt-BR, en-GB

import { getLocaleConfig, getFormatOptionsFromLocale } from "currency-fomatter";

<CurrencyFormat value={1234567} {...getFormatOptionsFromLocale("vi-VN")} />
// → 1.234.567 ₫

Custom locale registry

import { registerLocale, unregisterLocale } from "currency-fomatter";

registerLocale("bitcoin", {
  locale: "bitcoin",
  prefix: "₿ ",
  thousandSeparator: " ",
  decimalSeparator: ".",
  decimalScale: 8,
});

// Use it anywhere
<CurrencyFormat value={0.00123456} {...getFormatOptionsFromLocale("bitcoin")} />

unregisterLocale("bitcoin");

Hooks

useCurrencyInput (Headless)

A truly headless hook that works with any <input> element. No dependency on <CurrencyFormat />.

import { useCurrencyInput } from "currency-fomatter";

function PriceInput() {
  const { value, formattedValue, getInputProps, setValue, reset, clear } = useCurrencyInput({
    currency: "USD",         // Auto-configures prefix, decimals from ISO 4217
    initialValue: 1000,
    onValueChange: (values) => console.log(values.floatValue),
  });

  return (
    <div>
      <input {...getInputProps()} />
      <p>Raw: {value} | Display: {formattedValue}</p>
      <button onClick={() => setValue(2000)}>Set $2000</button>
      <button onClick={reset}>Reset</button>
      <button onClick={clear}>Clear</button>
    </div>
  );
}

Works with any UI library:

// Material UI
<TextField {...getInputProps()} label="Price" />

// Chakra UI
<Input {...getInputProps()} />

// Ant Design
<AntInput {...getInputProps()} />

Options: currency, locale, initialValue, onValueChange, plus all FormatCurrencyOptions (prefix, suffix, decimalScale, etc.). Direct props override currency/locale defaults.

useCurrencyFormat

Higher-level hook that returns props for the <CurrencyFormat /> component:

import { useCurrencyFormat, CurrencyFormat } from "currency-fomatter";

function PriceInput() {
  const { value, formattedValue, inputProps, reset, clear } = useCurrencyFormat({
    locale: "en-US",
    initialValue: 1000,
  });

  return (
    <div>
      <CurrencyFormat {...inputProps} />
      <p>Raw: {value} | Display: {formattedValue}</p>
    </div>
  );
}

PatternFormat

A focused component for pattern-based formatting (phone, card, date). Cleaner API than using CurrencyFormat with format prop.

import { PatternFormat } from "currency-fomatter";

// Phone number
<PatternFormat format="+1 (###) ###-####" mask="_" />

// Credit card
<PatternFormat format="#### #### #### ####" mask="_" />

// Date with per-position masks
<PatternFormat format="##/##/####" mask={["D","D","M","M","Y","Y","Y","Y"]} />

// Show mask on empty
<PatternFormat format="+1 (###) ###-####" mask="_" allowEmptyFormatting />
// → +1 (___) ___-____

PatternFormat accepts: format, mask, allowEmptyFormatting, value, defaultValue, onValueChange, displayType, customInput, and all standard input props.

Component API

Props

| Prop | Type | Default | Description | |------|------|---------|-------------| | value | string \| number | — | Controlled input value | | defaultValue | string \| number | — | Uncontrolled initial value | | format | string \| Function | — | Pattern ("+1 (###) ###-####") or custom format function | | decimalScale | number | — | Max decimal places | | decimalSeparator | string | "." | Decimal separator | | thousandSeparator | string \| boolean | "," | Thousand separator (true = ",") | | thousandSpacing | "2" \| "2s" \| "3" \| "4" | "3" | Grouping pattern | | thousandsGroupStyle | "thousand" \| "lakh" \| "wan" \| "none" | — | Human-readable grouping alias | | mask | string \| string[] | " " | Mask for empty format positions | | prefix | string | "" | Text before number ("$") | | suffix | string | "" | Text after number ("%") | | allowNegative | boolean | true | Allow negative values | | allowEmptyFormatting | boolean | false | Show prefix/suffix when empty | | allowedDecimalSeparators | string[] | — | Extra keys treated as decimal separator | | fixedDecimalScale | boolean | false | Always show decimal places | | isNumericString | boolean | false | Treat value as numeric string | | isAllowed | (values) => boolean | — | Custom validation | | onValueChange | (values, sourceInfo) => void | — | Value change callback | | inputMode | "numeric" \| "decimal" \| "text" | auto | Mobile keyboard type (auto-detected) | | displayType | "input" \| "text" | "input" | Render mode | | customInput | ComponentType | — | Custom input component | | renderText | (value, props) => ReactNode | — | Custom text renderer | | type | "text" \| "tel" | "text" | Input type | | name | string | — | Field name | | getInputRef | (el) => void | — | Get input element ref |

thousandsGroupStyle

Human-readable alias for thousandSpacing:

| Style | Equivalent | Example | |-------|-----------|---------| | "thousand" | "3" | 1,234,567 | | "lakh" | "2s" | 12,34,567 | | "wan" | "4" | 123,4567 | | "none" | — | 1234567 |

allowedDecimalSeparators

Accept multiple keys as decimal input (useful for European keyboards):

<CurrencyFormat
  decimalSeparator=","
  allowedDecimalSeparators={[",", "."]}
  // User can press either . or , to type a decimal
/>

ValueObject

interface ValueObject {
  formattedValue: string;  // "$1,234.56"
  value: string;           // "1234.56"
  floatValue: number;      // 1234.56
  name?: string;           // Field name if provided
}

onValueChange sourceInfo

onValueChange={(values, sourceInfo) => {
  // sourceInfo.source: "event" (user typed) | "prop" (value prop changed)
  // sourceInfo.event: the original DOM event (when source is "event")
  if (sourceInfo?.source === "event") {
    // Only react to user input, not programmatic changes
  }
}}

Examples

Phone number

<PatternFormat format="+1 (###) ###-####" mask="_" />
// → +1 (555) 123-4567

Credit card

<PatternFormat format="#### #### #### ####" mask="_" />
// → 4111 1111 1111 1111

Percentage with max

<CurrencyFormat
  suffix="%"
  decimalScale={2}
  isAllowed={(values) => (values.floatValue ?? 0) <= 100}
/>

Display as text

<CurrencyFormat
  value={9999.99}
  displayType="text"
  thousandSeparator=","
  prefix="$"
/>
// Renders: <span role="status" aria-live="polite">$9,999.99</span>

Custom input (Material UI, etc.)

<CurrencyFormat
  value={1000}
  customInput={TextField}
  thousandSeparator=","
  prefix="$"
/>

Form Library Integration

react-hook-form

import { useForm } from "react-hook-form";
import { CurrencyFormat } from "currency-fomatter";

function MyForm() {
  const { register, handleSubmit, setValue } = useForm();

  return (
    <form onSubmit={handleSubmit(onSubmit)}>
      <CurrencyFormat
        {...register("price")}
        thousandSeparator=","
        prefix="$"
        onValueChange={(values, sourceInfo) => {
          if (sourceInfo?.source === "event") {
            setValue("price", values.floatValue);
          }
        }}
      />
    </form>
  );
}

Accessibility

  • inputMode auto-detected for mobile keyboards (numeric/decimal)
  • displayType="text" renders with role="status" and aria-live="polite"
  • All aria-* props passed through to the input element
  • IME composition support for CJK (Chinese, Japanese, Korean) input
  • Home/End keys respect prefix/suffix boundaries
  • Disabled/readOnly states properly handled

TypeScript

Full type exports available:

import type {
  CurrencyFormatProps,
  PatternFormatProps,
  ThousandsGroupStyle,
  ValueObject,
  ThousandSpacing,
  FormatCurrencyOptions,
  ParseCurrencyOptions,
  CompactDisplayOptions,
  FormatCompactOptions,
  UseCurrencyFormatOptions,
  UseCurrencyFormatReturn,
  UseCurrencyInputOptions,
  UseCurrencyInputReturn,
  LocaleConfig,
  CurrencyInfo,
  FormatFunction,
  RemoveFormattingFunction,
  IsAllowedFunction,
  OnValueChangeFunction,
  RenderTextFunction,
} from "currency-fomatter";

License

MIT