@coreify/taka
v1.0.0
Published
A modern toolkit for formatting and rendering Bangladeshi Taka in JavaScript, TypeScript, and React apps.
Maintainers
Readme
@coreify/taka
A modern toolkit for formatting and rendering Bangladeshi Taka (BDT) in JavaScript, TypeScript, and React.
Built for Bangladesh-first products that need predictable BDT formatting, localized digits, compact amounts, poisha helpers, and small React components without a heavyweight i18n stack.
Why this package
- Correct ৳ symbol, BDT code, and Taka / টাকা display modes
- en-BD and bn-BD via
Intl.NumberFormat - Compact notation: South Asian K / L / Cr, international K / M / B, and Bengali localized phrasing (কোটি / লাখ / হাজার)
- Parse user-facing currency strings (symbol, code, name; glued tokens; optional scientific notation with a currency token)
- Poisha conversion (100 poisha = 1 taka)
bigintand boxedNumberwhere noted- SSR-friendly React helpers on a separate entry (
@coreify/taka/react)
Installation
npm install @coreify/takaRequires Node.js 18+ (uses Intl.NumberFormat).
For React:
npm install @coreify/taka reactQuick start
import { formatTaka, formatTakaCompact, parseTaka } from "@coreify/taka";
formatTaka(1250);
// => "৳1,250"
formatTaka(1250, { decimals: 2, trailingZeros: true });
// => "৳1,250.00"
formatTakaCompact(125000);
// => "৳1.25L"
parseTaka("৳1,250.50");
// => 1250.5
parseTaka("not money");
// => nullFormatting
formatTaka accepts a finite number, numeric string, bigint in the safe integer range, or boxed Number.
import { formatTaka } from "@coreify/taka";
formatTaka(2499);
// => "৳2,499"
formatTaka(2499, { currency: "code" });
// => "BDT 2,499"
formatTaka(2499, { style: "name" });
// => "2,499 Taka"
formatTaka(2499, { currencyPosition: "after", space: true });
// => "2,499 ৳"
formatTaka(-2499, { negativeStyle: "accounting" });
// => "(৳2,499)"
formatTaka(0, { zeroFormat: "Free" });
// => "Free"
formatTaka(1234567, { useGrouping: false });
// => "৳1234567"useGroupingdefaults totrue.zeroFormat: when the coerced amount is exactly 0 (including -0), that string is returned instead of a normal format.- String inputs: US / Indian / European-style separators are normalized (see tests). Hex strings (including fullwidth lookalikes such as
0x10) throwTypeError. Out-of-safe-range values throwRangeError. allowScientificNotation: whentrue, strings like"1e3"are accepted for formatting (no currency token required).allowLooseCommaGrouping: whentrue, ambiguous comma patterns may be collapsed if the result is a safe plain number (use with care).
Bengali locale
import {
formatTaka,
getTakaName,
toBanglaDigits,
toEnglishDigits
} from "@coreify/taka";
formatTaka(2499, { locale: "en-BD" });
// => "৳2,499"
formatTaka(2499, { locale: "bn-BD" });
// => "৳২,৪৯৯"
formatTaka(2499, { locale: "bn-BD", style: "name" });
// => "২,৪৯৯ টাকা"
getTakaName("bn");
// => "টাকা"
getTakaName("bn-BD");
// => "টাকা"
getTakaName("bn-IN"); // any "bn-*" subtag → Bengali name
// => "টাকা"
toBanglaDigits("1250.50");
// => "১২৫০.৫০"
toEnglishDigits("১,২৫০.৫০");
// => "1,250.50"Compact formatting
Short suffixes (K / L / Cr or K / M / B) use scaled decimals. For locale: "bn-BD" with compactLabelStyle: "localized", the amount is instead written with কোটি / লাখ / হাজার so values match how people read them (e.g. 1,250,000 → ১২ লাখ ৫০ হাজার, not ১.২৫ লাখ which would read like 1.25 lakh = 125,000, and not ১.২৫ মিলিয়ন alone).
import { formatTakaCompact } from "@coreify/taka";
formatTakaCompact(1200);
// => "৳1.2K"
formatTakaCompact(125000);
// => "৳1.25L"
formatTakaCompact(10000000);
// => "৳1Cr"
formatTakaCompact(1500000, { compactStyle: "international" });
// => "৳1.5M"
formatTakaCompact(125000, { locale: "bn-BD" });
// => "৳১.২৫L" (short suffix; Bengali digits)
formatTakaCompact(125000, {
locale: "bn-BD",
compactLabelStyle: "localized"
});
// => "৳১ লাখ ২৫ হাজার"
formatTakaCompact(1250000, {
locale: "bn-BD",
compactLabelStyle: "localized"
});
// => "৳১২ লাখ ৫০ হাজার"
formatTakaCompact(1500000, {
compactStyle: "international",
compactLabelStyle: "localized"
});
// => "৳1.5 million" (default English locale)
formatTakaCompact(1000000000, {
compactStyle: "international",
compactLabelStyle: "localized",
locale: "bn-BD"
});
// => "৳১০০ কোটি" (1 billion → 100 crore; not "১ বিলিয়ন")In JavaScript, 1000000000 and 1_000_000_000 are the same value; underscores are optional and only help readability.
Values with Math.abs(amount) < 1000 use full formatTaka output. For bn-BD + localized, compactStyle (South Asian vs international) does not apply: the Bengali word ladder is always কোটি → লাখ → হাজার.
Poisha (subunits)
ISO 4217 minor units for BDT: 100 poisha = 1 taka.
import {
formatTaka,
fromPoisha,
TAKA_POISHA_PER_TAKA,
toPoisha
} from "@coreify/taka";
TAKA_POISHA_PER_TAKA;
// => 100
toPoisha(12.5);
// => 1250 (integer poisha)
fromPoisha(1250);
// => 12.5
formatTaka(fromPoisha(toPoisha(12.5)));
// => "৳12.5" (default fraction rules for non-integers)
// Unsafe integer poisha throws RangeErrorParsing
import { isTakaString, normalizeTakaInput, parseTaka } from "@coreify/taka";
parseTaka("৳1,250");
// => 1250
parseTaka("BDT 1,250.50");
// => 1250.5
parseTaka("BDT100");
// => 100 (glued code)
parseTaka("১,২৫০ টাকা");
// => 1250
normalizeTakaInput("৳ ১,২৫০.৫০");
// => "1250.50"
isTakaString("৳1,250");
// => true
parseTaka("(৳1,250)");
// => -1250
parseTaka("(1,250)", { allowParentheses: false });
// => nullRules:
- Returns
nullfor unparseable input; throwsTypeErrorif the string contains a hex literal (same rule asformatTakafor string coercion). allowScientificNotation: whentrue, scientific forms are allowed only if a Taka token is present (e.g."৳1e3","BDT1e3"). Bare"1e3"is still rejected.allowLooseCommaGrouping: same idea as formatting; opt-in for ambiguous comma groupings.- More than one ৳ (U+09F3) in the input is rejected (
null). - Safe range: amounts beyond
Number.MAX_SAFE_INTEGERround-tripping rules returnnull(no silent rounding).
normalizeTakaInput: strips currency markers and normalizes grouping for further processing; does not throw on hex (use parseTaka / formatTaka for strict hex rejection).
Advanced: formatCoercedAmount
If you already coerced a value with the same options object shape (e.g. after parseTaka), format the number without parsing again:
import { formatCoercedAmount, formatTaka } from "@coreify/taka";
const amount = 1250;
formatCoercedAmount(amount, { locale: "bn-BD", style: "name" });
// same result as formatTaka(amount, { ... }) for that amountformatTaka is implemented as coerce-then-formatCoercedAmount.
React
Helpers live under @coreify/taka/react so the core bundle stays React-free. The published dist/react.js / dist/react.cjs files are built so a top-level "use client" directive remains present after minification (Next.js App Router / RSC client boundaries).
import { TakaAmount, TakaSymbol, TakaText } from "@coreify/taka/react";
function PriceCard() {
return (
<div>
<p>
<TakaSymbol srLabel="Taka" />
</p>
<p>
<TakaAmount value={1250} />
</p>
<p>
<TakaText value={1250} locale="bn-BD" />
</p>
</div>
);
}TakaSymbol,TakaAmount,TakaText:forwardRefto the rootspan. DOM props matchReact.ComponentPropsWithoutRef<"span">, exceptchildrenis omitted (content comes from formatting or the symbol).TakaSymbol: renders ৳. Defaultaria-label:"Bangladeshi Taka"; override withsrLabeloraria-label.TakaAmount: default display aligns withformatTaka(symbol style). Acceptsvariant/currency/styleplusdecimals,trailingZeros,useGrouping,currencyPosition,space,negativeStyle,zeroFormat,allowScientificNotation,allowLooseCommaGrouping,locale. Formatting options are not forwarded as DOM attributes.TakaText: same props asTakaAmount, defaulting to name style (e.g."1,250 Taka"/ Bengali equivalent withlocale). Usevariant="symbol"for symbol output.srLabelwins over a spreadaria-label. If neither is set,TakaAmount/TakaTextderive an accessible name from a name-style format of the same numeric options.
API reference
Core
| Export | Description |
| ----------------------------------------------------------- | ---------------------------------------------------------------------------------------------------------------------------------- |
| formatTaka(value, options?) | Format BDT per TakaFormatOptions. |
| formatCoercedAmount(amount, options?) | Format an already-coerced number. |
| formatTakaCompact(value, options?) | Compact form; TakaCompactOptions. |
| parseTaka(input, options?) | number \| null; ParseTakaOptions. |
| normalizeTakaInput(input, options?) | Stripped/normalized numeric string. |
| isTakaString(input, options?) | boolean; false for hex or multiple ৳. |
| toBanglaDigits / toEnglishDigits | Digit scripts. |
| toPoisha / fromPoisha | Poisha conversion; throws if non-finite or unsafe integer poisha. |
| TAKA_POISHA_PER_TAKA | 100 |
| getTakaSymbol / getTakaCode / getTakaName | Constants helpers; name resolves bn, bn-BD, bn-*, en, en-BD, en-*; otherwise English Taka. |
Constants
TAKA_SYMBOL (৳), TAKA_CODE (BDT), TAKA_NAME_EN, TAKA_NAME_BN.
Types
TakaLocale, TakaLanguage, TakaCurrencyDisplay, TakaCurrencyPosition, TakaCompactStyle, TakaCompactLabelStyle, TakaNegativeStyle, TakaNumericInput, TakaFormatOptions, TakaCompactOptions, ParseTakaOptions.
TypeScript
Strict TypeScript, declaration files for @coreify/taka and @coreify/taka/react. Core types do not import React, so non-React apps need not add react for the main entry.
License
MIT
