
Product
Introducing Reports: An Extensible Reporting Framework for Socket Data
Explore exportable charts for vulnerabilities, dependencies, and usage with Reports, Socket’s new extensible reporting framework.
persian-number-input
Advanced tools
React component for Persian, Indic, or English localized number input with customizable digit grouping
فارسی | English A lightweight, powerful React library for handling Persian (Farsi) and Arabic number inputs with automatic digit conversion, formatting, and localization support.
Experience the component in action with our interactive demo!
This library is extremely lightweight:
persian-number-input: ~1KB (minified + gzipped)

npm install persian-number-input
yarn add persian-number-input
pnpm add persian-number-input
import { PersianNumberInput } from "persian-number-input";
function App() {
return (
<PersianNumberInput
initialValue={1234567}
locale="fa"
onValueChange={(value) => console.log(value)}
/>
);
}
Output: ۱,۲۳۴,۵۶۷
<PersianNumberInput
initialValue={5000000}
locale="fa"
suffix="تومان"
separatorCount={3}
separatorChar=","
onValueChange={(value) => console.log(value)}
/>
Output: ۵,۰۰۰,۰۰۰ تومان
<PersianNumberInput
initialValue={1234.56}
locale="fa"
maxDecimals={2}
decimalChar="٫"
separatorChar=","
onValueChange={(value) => console.log(value)}
/>
Output: ۱,۲۳۴٫۵۶
<PersianNumberInput
initialValue={0}
locale="fa"
min={0}
max={999999999}
suffix="ریال"
showZero={true}
onValueChange={(value) => console.log(value)}
/>
Output: ۰ ریال
<PersianNumberInput
initialValue={987654}
locale="ar"
separatorChar=","
suffix="ر.س"
onValueChange={(value) => console.log(value)}
/>
Output: ٩٨٧,٦٥٤ ر.س
import { usePersianNumberInput } from "persian-number-input";
function CustomInput() {
const { value, onChange, onBlur, rawValue } = usePersianNumberInput({
initialValue: 1000,
locale: "fa",
separatorCount: 3,
maxDecimals: 2,
min: 0,
max: 1000000,
onValueChange: (val) => {
console.log("Raw value:", val); // "1000"
console.log("Displayed value:", value); // "۱,۰۰۰"
},
});
return (
<input
type="text"
value={value}
onChange={onChange}
onBlur={onBlur}
className="custom-input"
/>
);
}
| Prop | Type | Default | Description |
|---|---|---|---|
initialValue | number | string | undefined | Initial value of the input |
locale | "fa" | "ar" | "en" | "fa" | Locale for digit conversion |
separatorCount | number | 3 | Number of digits between separators |
separatorChar | string | "," | Character used for thousand separator |
decimalChar | string | Auto | Decimal separator character |
suffix | string | undefined | Suffix text (e.g., currency symbol) |
maxDecimals | number | undefined | Maximum decimal places allowed |
min | number | undefined | Minimum allowed value |
max | number | undefined | Maximum allowed value |
showZero | boolean | false | Show zero when value is empty |
onValueChange | (value: string | undefined) => void | undefined | Callback when value changes (returns raw English digits) |
All standard HTML input props are also supported.
transformNumber(rawValue, options)Formats a number string according to locale and options.
import { transformNumber } from "persian-number-input";
const formatted = transformNumber("1234567.89", {
locale: "fa",
separatorCount: 3,
separatorChar: ",",
maxDecimals: 2,
suffix: "تومان",
});
console.log(formatted); // "۱,۲۳۴,۵۶۷٫۸۹ تومان"
toEnglishDigits(str, decimalChar?)Converts Persian/Arabic digits to English digits.
import { toEnglishDigits } from "persian-number-input";
console.log(toEnglishDigits("۱۲۳۴")); // "1234"
console.log(toEnglishDigits("٩٨٧٦")); // "9876"
toLocalizedDigits(numStr, locale)Converts English digits to localized digits.
import { toLocalizedDigits } from "persian-number-input";
console.log(toLocalizedDigits("1234", "fa")); // "۱۲۳۴"
console.log(toLocalizedDigits("5678", "ar")); // "٥٦٧٨"
sanitizeNumericInput(value, maxDecimals?, decimalChar?)Cleans and validates numeric input.
import { sanitizeNumericInput } from "persian-number-input";
console.log(sanitizeNumericInput("۱۲۳abc۴۵۶", 2)); // "123456"
console.log(sanitizeNumericInput("12.345.67", 2)); // "12.34"
The component accepts all standard input props, including className and style:
<PersianNumberInput
initialValue={1000}
locale="fa"
className="custom-input"
style={{
padding: "12px",
fontSize: "16px",
border: "2px solid #4F46E5",
borderRadius: "8px",
textAlign: "right",
}}
/>
<PersianNumberInput
initialValue={1000}
locale="fa"
className="w-full px-4 py-3 text-lg border-2 border-indigo-500 rounded-lg focus:outline-none focus:ring-2 focus:ring-indigo-600 text-right"
/>
import { useState } from "react";
import { PersianNumberInput } from "persian-number-input";
function LoanCalculator() {
const [principal, setPrincipal] = useState<string>();
const [rate, setRate] = useState<string>();
const [years, setYears] = useState<string>();
const calculateMonthlyPayment = () => {
if (!principal || !rate || !years) return 0;
const p = parseFloat(principal);
const r = parseFloat(rate) / 100 / 12;
const n = parseFloat(years) * 12;
return (p * r * Math.pow(1 + r, n)) / (Math.pow(1 + r, n) - 1);
};
return (
<div className="space-y-4">
<div>
<label>مبلغ وام:</label>
<PersianNumberInput
locale="fa"
suffix="تومان"
onValueChange={setPrincipal}
min={0}
/>
</div>
<div>
<label>نرخ سود (٪):</label>
<PersianNumberInput
locale="fa"
maxDecimals={2}
onValueChange={setRate}
min={0}
max={100}
/>
</div>
<div>
<label>مدت زمان (سال):</label>
<PersianNumberInput
locale="fa"
onValueChange={setYears}
min={1}
max={30}
/>
</div>
<p>
پرداخت ماهیانه: {calculateMonthlyPayment().toLocaleString("fa-IR")}{" "}
تومان
</p>
</div>
);
}
import { useForm, Controller } from "react-hook-form";
import { PersianNumberInput } from "persian-number-input";
function ProductForm() {
const { control, handleSubmit } = useForm();
const onSubmit = (data) => {
console.log(data);
};
return (
<form onSubmit={handleSubmit(onSubmit)}>
<Controller
name="price"
control={control}
rules={{ required: true }}
render={({ field }) => (
<PersianNumberInput
locale="fa"
suffix="تومان"
onValueChange={field.onChange}
initialValue={field.value}
/>
)}
/>
<button type="submit">ثبت</button>
</form>
);
}
Working with Persian and Arabic numerals in web applications is challenging:
Persian Number Input handles all these complexities automatically:
// User types: ۱۲۳۴۵۶۷
// Component displays: ۱,۲۳۴,۵۶۷
// Form receives: "1234567"
| Feature | Persian Number Input | Native Input | Other Libraries |
|---|---|---|---|
| Auto digit conversion | ✅ | ❌ | ⚠️ Partial |
| Cursor preservation | ✅ | ❌ | ⚠️ Buggy |
| TypeScript support | ✅ | ✅ | ⚠️ Varies |
| Multi-locale | ✅ | ❌ | ❌ |
| Bundle size | 🟢 Small | 🟢 N/A | 🔴 Large |
| Decimal precision | ✅ | ❌ | ⚠️ Limited |
Contributions are welcome! Please feel free to submit a Pull Request.
git checkout -b feature/AmazingFeature)git commit -m 'Add some AmazingFeature')git push origin feature/AmazingFeature)MIT © javad Sharifi
Made with ❤️ for the Persian and Arabic developer community
FAQs
React component for Persian, Indic, or English localized number input with customizable digit grouping
The npm package persian-number-input receives a total of 17 weekly downloads. As such, persian-number-input popularity was classified as not popular.
We found that persian-number-input demonstrated a healthy version release cadence and project activity because the last version was released less than a year ago. It has 1 open source maintainer collaborating on the project.
Did you know?

Socket for GitHub automatically highlights issues in each pull request and monitors the health of all your open source dependencies. Discover the contents of your packages and block harmful activity before you install or update your dependencies.

Product
Explore exportable charts for vulnerabilities, dependencies, and usage with Reports, Socket’s new extensible reporting framework.

Product
Socket for Jira lets teams turn alerts into Jira tickets with manual creation, automated ticketing rules, and two-way sync.

Company News
Socket won two 2026 Reppy Awards from RepVue, ranking in the top 5% of all sales orgs. AE Alexandra Lister shares what it's like to grow a sales career here.