Skip to content

Core Utilities

raqam/core exposes the formatter/parser engine underneath the React APIs. raqam/server is an alias of the same entrypoint, useful when you want to make the server-safe intent explicit in RSC, SSR, or Edge code.

import {
createFormatter,
createParser,
normalizeDigits,
registerLocale,
getCaretBoundary,
computeNewCursorPosition,
presets,
} from "raqam/core";
// Equivalent server-focused import:
import { createFormatter } from "raqam/server";

Build a cached Intl.NumberFormat wrapper with optional affixes and fraction digit overrides.

const formatter = createFormatter({
locale: "en-US",
formatOptions: { style: "currency", currency: "USD" },
maximumFractionDigits: 2,
fixedDecimalScale: true,
});
formatter.format(1234.5);
// "$1,234.50"

Returned API:

MethodDescription
format(value)Returns the formatted string.
formatToParts(value)Returns Intl.NumberFormatPart[].
formatResult(value)Returns { formatted, parts }.
getLocaleInfo()Returns separators, minus sign, zero digit, and RTL info.

Create a locale-aware parser that accepts the same locale, affix, and sign/decimal constraints used by the formatter.

const parser = createParser({
locale: "fa-IR",
suffix: " تومان",
});
parser.parse("۱۲۳٬۴۵۶ تومان").value;
// 123456

Returned API:

MethodDescription
parse(input)Returns { value, isValid, isIntermediate }.
isIntermediate(input)Detects incomplete-but-valid editing states like "-" or "1.".
getLocaleInfo()Returns locale metadata used by the parser.

Converts registered non-Latin digits to ASCII without touching other characters.

normalizeDigits("۱2٣");
// "123"

Use this when you need normalized digits before your own validation or storage logic.

Add support for another digit block.

registerLocale({
digitBlocks: [[0xff10, 0xff19]],
});
normalizeDigits("123");
// "123"

Use this only for scripts not already covered by the built-in locale plugins. For Persian, Arabic, Hindi, Bengali, and Thai, prefer the ready-made modules in raqam/locales/*.

These power the live-formatting cursor behavior and are useful only when you build your own custom input pipeline.

getCaretBoundary(formattedValue, localeInfo)

Section titled “getCaretBoundary(formattedValue, localeInfo)”

Returns a boolean[] showing which positions in a formatted string are valid caret stops.

computeNewCursorPosition(oldInput, oldCursor, newFormatted, localeInfo)

Section titled “computeNewCursorPosition(oldInput, oldCursor, newFormatted, localeInfo)”

Maps the caret from the pre-format string to the new formatted string after an edit.

const formatter = createFormatter({ locale: "en-US" });
const info = formatter.getLocaleInfo();
computeNewCursorPosition("1234", 4, "1,234", info);
// 5

presets is also available from raqam/core and raqam/server, so you can share formatting options between client and server code.

import { createFormatter, presets } from "raqam/server";
const formatter = createFormatter({
locale: "en-US",
formatOptions: presets.currency("USD"),
});