persian-number-input 4.3.4 → 4.5.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (45) hide show
  1. package/README.fa.md +231 -227
  2. package/README.md +198 -221
  3. package/dist/components/PersianNumberInput.d.ts +1 -1
  4. package/dist/components/PersianNumberInput.d.ts.map +1 -1
  5. package/dist/components/PersianNumberInput.js +22 -17
  6. package/dist/components/PersianNumberInput.js.map +1 -1
  7. package/dist/components/PersianNumberInput.test.js +24 -6
  8. package/dist/components/PersianNumberInput.test.js.map +1 -1
  9. package/dist/hooks/useCursorManager.d.ts +4 -0
  10. package/dist/hooks/useCursorManager.d.ts.map +1 -0
  11. package/dist/hooks/useCursorManager.js +19 -0
  12. package/dist/hooks/useCursorManager.js.map +1 -0
  13. package/dist/hooks/useNumberFormatter.d.ts +18 -0
  14. package/dist/hooks/useNumberFormatter.d.ts.map +1 -0
  15. package/dist/hooks/useNumberFormatter.js +29 -0
  16. package/dist/hooks/useNumberFormatter.js.map +1 -0
  17. package/dist/hooks/useNumberValidation.d.ts +11 -0
  18. package/dist/hooks/useNumberValidation.d.ts.map +1 -0
  19. package/dist/hooks/useNumberValidation.js +22 -0
  20. package/dist/hooks/useNumberValidation.js.map +1 -0
  21. package/dist/hooks/useNumericInputEvents.d.ts +18 -0
  22. package/dist/hooks/useNumericInputEvents.d.ts.map +1 -0
  23. package/dist/hooks/useNumericInputEvents.js +39 -0
  24. package/dist/hooks/useNumericInputEvents.js.map +1 -0
  25. package/dist/hooks/usePersianNumberInput.d.ts +7 -2
  26. package/dist/hooks/usePersianNumberInput.d.ts.map +1 -1
  27. package/dist/hooks/usePersianNumberInput.js +66 -63
  28. package/dist/hooks/usePersianNumberInput.js.map +1 -1
  29. package/dist/test-utils.d.ts +7 -0
  30. package/dist/test-utils.d.ts.map +1 -0
  31. package/dist/test-utils.js +27 -0
  32. package/dist/test-utils.js.map +1 -0
  33. package/dist/utils/digitUtils.d.ts +4 -0
  34. package/dist/utils/digitUtils.d.ts.map +1 -1
  35. package/dist/utils/digitUtils.js +44 -17
  36. package/dist/utils/digitUtils.js.map +1 -1
  37. package/dist/utils/keyFilter.d.ts +16 -0
  38. package/dist/utils/keyFilter.d.ts.map +1 -0
  39. package/dist/utils/keyFilter.js +31 -0
  40. package/dist/utils/keyFilter.js.map +1 -0
  41. package/dist/utils/validation.d.ts +22 -0
  42. package/dist/utils/validation.d.ts.map +1 -0
  43. package/dist/utils/validation.js +85 -0
  44. package/dist/utils/validation.js.map +1 -0
  45. package/package.json +15 -4
package/README.fa.md CHANGED
@@ -1,6 +1,8 @@
1
- # ورودی اعداد فارسی و عربی
1
+ # ورودی عدد فارسی برای React — تبدیل خودکار ارقام فارسی، عربی و RTL
2
2
 
3
- یک کتابخانه React سبک و قدرتمند برای مدیریت ورودی اعداد فارسی و عربی با تبدیل خودکار ارقام، فرمت‌دهی و پشتیبانی از چند زبان.
3
+ English | [فارسی](./README.fa.md)
4
+
5
+ یک کامپوننت React برای **ورودی اعداد فارسی و عربی** با تبدیل خودکار ارقام، جداکننده هزارگان، کنترل دقت اعشاری و پشتیبانی کامل از RTL. کاربر ارقام فارسی تایپ می‌کند، فرم شما عدد انگلیسی تمیز دریافت می‌کند — بدون هیچ تبدیل دستی.
4
6
 
5
7
  [![نسخه npm](https://img.shields.io/npm/v/persian-number-input.svg)](https://www.npmjs.com/package/persian-number-input)
6
8
  [![دانلودهای npm](https://img.shields.io/npm/dm/persian-number-input.svg)](https://www.npmjs.com/package/persian-number-input)
@@ -9,34 +11,40 @@
9
11
 
10
12
  ## 🚀 [دموی آنلاین](https://persian-number-input.netlify.app/)
11
13
 
12
- کامپوننت را به صورت زنده تجربه کنید!
13
-
14
14
  ---
15
15
 
16
- ## 📊 حجم باندل
16
+ ## چرا این پکیج؟
17
+
18
+ ساختن فرم برای کاربران فارسی‌زبان چالش‌های واقعی داره:
17
19
 
18
- این کتابخانه فوق‌العاده سبک است:
20
+ - کاربر `۱۲۳۴` تایپ می‌کنه — API شما `1234` می‌خواد
21
+ - `<input type="number">` اصلاً ارقام فارسی یا عربی رو قبول نمی‌کنه
22
+ - وقتی جداکننده هزارگان اضافه میشه، cursor جهش می‌کنه
23
+ - جداکننده اعشاری در فارسی `٫` هست نه `.`
24
+ - ورودی‌های RTL نیاز به تنظیمات خاص دارن
25
+
26
+ این پکیج همه اینا رو خودکار حل می‌کنه:
19
27
 
20
28
  ```
21
- persian-number-input: تنها ~1KB (فشرده شده)
29
+ کاربر تایپ می‌کند: ۱۲۳۴۵۶۷
30
+ نمایش داده می‌شود: ۱,۲۳۴,۵۶۷
31
+ فرم دریافت می‌کند: "1234567"
22
32
  ```
23
33
 
24
- ![مقایسه حجم باندل](./public/size.png)
25
-
26
34
  ---
27
35
 
28
36
  ## ✨ امکانات
29
37
 
30
- - 🔢 **تبدیل خودکار ارقام** - تبدیل یکپارچه ارقام فارسی (۰-۹) و عربی (٠-٩) به انگلیسی و بالعکس
31
- - 🌍 **پشتیبانی چندزبانه** - پشتیبانی داخلی از فارسی (fa)، عربی (ar) و انگلیسی (en)
32
- - 📊 **فرمت‌دهی اعداد** - جداکننده هزارگان خودکار با کاراکترهای قابل تنظیم
33
- - 💰 **آماده برای ارز** - امکان افزودن پیشوند، پسوند و جداکننده اعشاری سفارشی
34
- - ⚡ **سبک و سریع** - حجم بسیار کم با صفر وابستگی (به جز decimal.js برای دقت)
35
- - 🎯 **Type-Safe** - پشتیبانی کامل TypeScript با تعاریف تایپ کامل
36
- - **قابل دسترس** - پیروی از بهترین شیوه‌های دسترسی‌پذیری
37
- - 🎨 **قابل سفارشی‌سازی** - گزینه‌های پیکربندی گسترده برای هر نیازی
38
- - 🔄 **فرمت‌دهی لحظه‌ای** - فرمت کردن اعداد همزمان با تایپ کاربر با حفظ موقعیت مکان‌نما
39
- - **اعتبارسنجی** - کنترل داخلی مقادیر min/max و دقت اعشاری
38
+ - 🔢 **تبدیل خودکار ارقام** فارسی (۰-۹) و عربی (٠-٩) به انگلیسی و برعکس
39
+ - 🌍 **چند زبانه** فارسی (`fa`)، عربی (`ar`)، انگلیسی (`en`)
40
+ - 📊 **جداکننده هزارگان** قابل تنظیم با هر کاراکتری
41
+ - 💰 **آماده برای ارز** پشتیبانی از پسوند (تومان، ریال، ر.س) و جداکننده اعشاری سفارشی
42
+ - ⚡ **فقط کیلوبایت** بدون هیچ dependency اضافه
43
+ - 🎯 **TypeScript** تعریف تایپ کامل
44
+ - 🔄 **حفظ موقعیت cursor** بدون جهش هنگام فرمت‌دهی
45
+ - 📋 **مدیریت هوشمند paste** محتوای چسبانده شده خودکار پالایش و تبدیل می‌شود
46
+ - **اعتبارسنجی min/max** اعتبارسنجی نرم با `aria-invalid` و اعمال خودکار محدودیت در blur
47
+ - **دسترس‌پذیر** رعایت استانداردهای WCAG
40
48
 
41
49
  ---
42
50
 
@@ -44,22 +52,18 @@ persian-number-input: تنها ~1KB (فشرده شده)
44
52
 
45
53
  ```bash
46
54
  npm install persian-number-input
47
- ```
48
-
49
- ```bash
55
+ # یا
50
56
  yarn add persian-number-input
51
- ```
52
-
53
- ```bash
57
+ # یا
54
58
  pnpm add persian-number-input
55
59
  ```
56
60
 
61
+ > **نیازمندی‌ها:** React 16.8 به بالا — سازگار با Next.js، Vite، و CRA.
62
+
57
63
  ---
58
64
 
59
65
  ## 🎯 شروع سریع
60
66
 
61
- ### استفاده ساده
62
-
63
67
  ```tsx
64
68
  import { PersianNumberInput } from "persian-number-input";
65
69
 
@@ -68,19 +72,19 @@ function App() {
68
72
  <PersianNumberInput
69
73
  initialValue={1234567}
70
74
  locale="fa"
71
- onValueChange={(value) => console.log(value)}
75
+ onValueChange={(value) => console.log(value)} // "1234567"
72
76
  />
73
77
  );
74
78
  }
75
79
  ```
76
80
 
77
- **خروجی:** `۱,۲۳۴,۵۶۷`
81
+ خروجی نمایشی: `۱,۲۳۴,۵۶۷`
78
82
 
79
83
  ---
80
84
 
81
- ## 📚 نمونه‌های کاربردی
85
+ ## 📚 مثال‌های کاربردی
82
86
 
83
- ### ورودی مبلغ (تومان ایران)
87
+ ### ورودی مبلغ تومان
84
88
 
85
89
  ```tsx
86
90
  <PersianNumberInput
@@ -93,46 +97,44 @@ function App() {
93
97
  />
94
98
  ```
95
99
 
96
- **خروجی:** `۵,۰۰۰,۰۰۰ تومان`
100
+ خروجی: `۵,۰۰۰,۰۰۰ تومان`
97
101
 
98
102
  ---
99
103
 
100
- ### اعداد اعشاری با جداکننده سفارشی
104
+ ### ورودی ریال با اعتبارسنجی
101
105
 
102
106
  ```tsx
103
107
  <PersianNumberInput
104
- initialValue={1234.56}
108
+ initialValue={0}
105
109
  locale="fa"
106
- maxDecimals={2}
107
- decimalChar="٫"
108
- separatorChar=","
110
+ min={0}
111
+ max={999999999}
112
+ suffix="ریال"
113
+ showZero={true}
109
114
  onValueChange={(value) => console.log(value)}
110
115
  />
111
116
  ```
112
117
 
113
- **خروجی:** `۱,۲۳۴٫۵۶`
114
-
115
118
  ---
116
119
 
117
- ### ورودی قیمت با اعتبارسنجی
120
+ ### عدد اعشاری با جداکننده فارسی
118
121
 
119
122
  ```tsx
120
123
  <PersianNumberInput
121
- initialValue={0}
124
+ initialValue={1234.56}
122
125
  locale="fa"
123
- min={0}
124
- max={999999999}
125
- suffix="ریال"
126
- showZero={true}
126
+ maxDecimals={2}
127
+ decimalChar="٫"
128
+ separatorChar=","
127
129
  onValueChange={(value) => console.log(value)}
128
130
  />
129
131
  ```
130
132
 
131
- **خروجی:** `۰ ریال`
133
+ خروجی: `۱,۲۳۴٫۵۶`
132
134
 
133
135
  ---
134
136
 
135
- ### زبان عربی
137
+ ### زبان عربی (ریال سعودی)
136
138
 
137
139
  ```tsx
138
140
  <PersianNumberInput
@@ -144,7 +146,39 @@ function App() {
144
146
  />
145
147
  ```
146
148
 
147
- **خروجی:** `٩٨٧,٦٥٤ ر.س`
149
+ خروجی: `٩٨٧,٦٥٤ ر.س`
150
+
151
+ ---
152
+
153
+ ### استفاده با React Hook Form
154
+
155
+ ```tsx
156
+ import { useForm, Controller } from "react-hook-form";
157
+ import { PersianNumberInput } from "persian-number-input";
158
+
159
+ function ProductForm() {
160
+ const { control, handleSubmit } = useForm();
161
+
162
+ return (
163
+ <form onSubmit={handleSubmit(console.log)}>
164
+ <Controller
165
+ name="price"
166
+ control={control}
167
+ rules={{ required: true }}
168
+ render={({ field }) => (
169
+ <PersianNumberInput
170
+ locale="fa"
171
+ suffix="تومان"
172
+ onValueChange={field.onChange}
173
+ initialValue={field.value}
174
+ />
175
+ )}
176
+ />
177
+ <button type="submit">ثبت</button>
178
+ </form>
179
+ );
180
+ }
181
+ ```
148
182
 
149
183
  ---
150
184
 
@@ -161,10 +195,7 @@ function CustomInput() {
161
195
  maxDecimals: 2,
162
196
  min: 0,
163
197
  max: 1000000,
164
- onValueChange: (val) => {
165
- console.log("مقدار خام:", val); // "1000"
166
- console.log("مقدار نمایشی:", value); // "۱,۰۰۰"
167
- },
198
+ onValueChange: (val) => console.log("مقدار انگلیسی:", val),
168
199
  });
169
200
 
170
201
  return (
@@ -173,33 +204,77 @@ function CustomInput() {
173
204
  value={value}
174
205
  onChange={onChange}
175
206
  onBlur={onBlur}
176
- className="custom-input"
207
+ onPaste={onPaste}
208
+ dir="rtl"
177
209
  />
178
210
  );
179
211
  }
180
212
  ```
181
213
 
214
+ Hook همچنین `isInvalid` (boolean) رو وقتی مقدار از `max` بیشتر بشه برمی‌گردونه، و `onPaste` برای مدیریت رویداد paste.
215
+
216
+ ---
217
+
218
+ ### ماشین‌حساب وام
219
+
220
+ ```tsx
221
+ import { useState } from "react";
222
+ import { PersianNumberInput } from "persian-number-input";
223
+
224
+ function LoanCalculator() {
225
+ const [principal, setPrincipal] = useState<string>();
226
+ const [rate, setRate] = useState<string>();
227
+ const [years, setYears] = useState<string>();
228
+
229
+ const calculateMonthlyPayment = () => {
230
+ if (!principal || !rate || !years) return 0;
231
+ const p = parseFloat(principal);
232
+ const r = parseFloat(rate) / 100 / 12;
233
+ const n = parseFloat(years) * 12;
234
+ return (p * r * Math.pow(1 + r, n)) / (Math.pow(1 + r, n) - 1);
235
+ };
236
+
237
+ return (
238
+ <div className="space-y-4">
239
+ <div>
240
+ <label>مبلغ وام:</label>
241
+ <PersianNumberInput locale="fa" suffix="تومان" onValueChange={setPrincipal} min={0} />
242
+ </div>
243
+ <div>
244
+ <label>نرخ سود (٪):</label>
245
+ <PersianNumberInput locale="fa" maxDecimals={2} onValueChange={setRate} min={0} max={100} />
246
+ </div>
247
+ <div>
248
+ <label>مدت زمان (سال):</label>
249
+ <PersianNumberInput locale="fa" onValueChange={setYears} min={1} max={30} />
250
+ </div>
251
+ <p>پرداخت ماهیانه: {calculateMonthlyPayment().toLocaleString("fa-IR")} تومان</p>
252
+ </div>
253
+ );
254
+ }
255
+ ```
256
+
182
257
  ---
183
258
 
184
259
  ## 🛠️ مرجع API
185
260
 
186
- ### Props کامپوننت PersianNumberInput
261
+ ### Props کامپوننت `PersianNumberInput`
187
262
 
188
- | ویژگی | نوع | پیش‌فرض | توضیحات |
189
- | ---------------- | -------------------------------------- | ----------- | --------------------------------------------------------------- |
190
- | `initialValue` | `number \| string` | `undefined` | مقدار اولیه ورودی |
191
- | `locale` | `"fa" \| "ar" \| "en"` | `"fa"` | زبان برای تبدیل ارقام |
192
- | `separatorCount` | `number` | `3` | تعداد ارقام بین جداکننده‌ها |
193
- | `separatorChar` | `string` | `","` | کاراکتر جداکننده هزارگان |
194
- | `decimalChar` | `string` | خودکار | کاراکتر جداکننده اعشار |
195
- | `suffix` | `string` | `undefined` | متن پسوند (مثل واحد پول) |
196
- | `maxDecimals` | `number` | `undefined` | حداکثر رقم اعشار مجاز |
197
- | `min` | `number` | `undefined` | کمترین مقدار مجاز |
198
- | `max` | `number` | `undefined` | بیشترین مقدار مجاز |
199
- | `showZero` | `boolean` | `false` | نمایش صفر وقتی مقدار خالی است |
200
- | `onValueChange` | `(value: string \| undefined) => void` | `undefined` | تابع فراخوانی هنگام تغییر مقدار (ارقام انگلیسی خام برمی‌گرداند) |
263
+ | ویژگی | نوع | پیش‌فرض | توضیحات |
264
+ | ---------------- | -------------------------------------- | ----------- | ---------------------------------------------------------------- |
265
+ | `initialValue` | `number \| string` | `undefined` | مقدار اولیه ورودی |
266
+ | `locale` | `"fa" \| "ar" \| "en"` | `"fa"` | زبان فارسی، عربی یا انگلیسی |
267
+ | `separatorCount` | `number` | `3` | تعداد ارقام بین جداکننده‌ها (۳ = هزارگان) |
268
+ | `separatorChar` | `string` | `","` | کاراکتر جداکننده هزارگان |
269
+ | `decimalChar` | `string` | خودکار | جداکننده اعشار (`٫` برای fa، `.` برای en) |
270
+ | `suffix` | `string` | `undefined` | پسوند مثل `تومان`، `ریال` |
271
+ | `maxDecimals` | `number` | `undefined` | حداکثر رقم اعشار مجاز |
272
+ | `min` | `number` | `undefined` | کمترین مقدار مجاز |
273
+ | `max` | `number` | `undefined` | بیشترین مقدار مجاز — اعتبارسنجی نرم (علامت‌گذاری invalid، اعمال در blur) |
274
+ | `showZero` | `boolean` | `false` | نمایش صفر وقتی ورودی خالی است |
275
+ | `onValueChange` | `(value: string \| undefined) => void` | `undefined` | callback هنگام تغییر همیشه ارقام انگلیسی برمی‌گرداند |
201
276
 
202
- تمام props استاندارد HTML input نیز پشتیبانی می‌شوند.
277
+ تمام props استاندارد `<input>` مثل `onChange`، `onKeyDown`، `onPaste`، `className`، `style`، `placeholder`، `dir` و `disabled` هم پشتیبانی می‌شن.
203
278
 
204
279
  ---
205
280
 
@@ -207,252 +282,181 @@ function CustomInput() {
207
282
 
208
283
  #### `transformNumber(rawValue, options)`
209
284
 
210
- یک رشته عددی را بر اساس زبان و تنظیمات فرمت می‌کند.
285
+ فرمت‌دهی یک رشته عددی بر اساس زبان و تنظیمات:
211
286
 
212
287
  ```tsx
213
288
  import { transformNumber } from "persian-number-input";
214
289
 
215
- const formatted = transformNumber("1234567.89", {
290
+ transformNumber("1234567.89", {
216
291
  locale: "fa",
217
292
  separatorCount: 3,
218
293
  separatorChar: ",",
219
294
  maxDecimals: 2,
220
295
  suffix: "تومان",
221
296
  });
222
-
223
- console.log(formatted); // "۱,۲۳۴,۵۶۷٫۸۹ تومان"
297
+ // ← "۱,۲۳۴,۵۶۷٫۸۹ تومان"
224
298
  ```
225
299
 
226
300
  #### `toEnglishDigits(str, decimalChar?)`
227
301
 
228
- ارقام فارسی/عربی را به انگلیسی تبدیل می‌کند.
302
+ تبدیل ارقام فارسی یا عربی به انگلیسی:
229
303
 
230
304
  ```tsx
231
305
  import { toEnglishDigits } from "persian-number-input";
232
306
 
233
- console.log(toEnglishDigits("۱۲۳۴")); // "1234"
234
- console.log(toEnglishDigits("٩٨٧٦")); // "9876"
307
+ toEnglishDigits("۱۲۳۴"); // "1234"
308
+ toEnglishDigits("٩٨٧٦"); // "9876"
235
309
  ```
236
310
 
237
311
  #### `toLocalizedDigits(numStr, locale)`
238
312
 
239
- ارقام انگلیسی را به ارقام محلی تبدیل می‌کند.
313
+ تبدیل ارقام انگلیسی به زبان مقصد:
240
314
 
241
315
  ```tsx
242
316
  import { toLocalizedDigits } from "persian-number-input";
243
317
 
244
- console.log(toLocalizedDigits("1234", "fa")); // "۱۲۳۴"
245
- console.log(toLocalizedDigits("5678", "ar")); // "٥٦٧٨"
318
+ toLocalizedDigits("1234", "fa"); // "۱۲۳۴"
319
+ toLocalizedDigits("5678", "ar"); // "٥٦٧٨"
246
320
  ```
247
321
 
248
322
  #### `sanitizeNumericInput(value, maxDecimals?, decimalChar?)`
249
323
 
250
- ورودی عددی را پاکسازی و اعتبارسنجی می‌کند.
324
+ پاکسازی ورودی و اعمال محدودیت اعشار:
251
325
 
252
326
  ```tsx
253
327
  import { sanitizeNumericInput } from "persian-number-input";
254
328
 
255
- console.log(sanitizeNumericInput("۱۲۳abc۴۵۶", 2)); // "123456"
256
- console.log(sanitizeNumericInput("12.345.67", 2)); // "12.34"
329
+ sanitizeNumericInput("۱۲۳abc۴۵۶", 2); // "123456"
330
+ sanitizeNumericInput("12.345.67", 2); // "12.34"
257
331
  ```
258
332
 
259
- ---
260
-
261
- ## 🎨 استایل‌دهی
333
+ #### `stripNonNumeric(str)`
262
334
 
263
- کامپوننت تمام props استاندارد input را می‌پذیرد، از جمله `className` و `style`:
335
+ حذف همه کاراکترهای غیرعددی و غیر از نقطه:
264
336
 
265
337
  ```tsx
266
- <PersianNumberInput
267
- initialValue={1000}
268
- locale="fa"
269
- className="custom-input"
270
- style={{
271
- padding: "12px",
272
- fontSize: "16px",
273
- border: "2px solid #4F46E5",
274
- borderRadius: "8px",
275
- textAlign: "right",
276
- }}
277
- />
338
+ import { stripNonNumeric } from "persian-number-input";
339
+
340
+ stripNonNumeric("12abc34.56xyz"); // "1234.56"
278
341
  ```
279
342
 
280
- ### با Tailwind CSS
343
+ #### `normalizeDecimals(str)`
344
+
345
+ نگه داشتن فقط اولین نقطه اعشاری:
281
346
 
282
347
  ```tsx
283
- <PersianNumberInput
284
- initialValue={1000}
285
- locale="fa"
286
- 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"
287
- />
288
- ```
348
+ import { normalizeDecimals } from "persian-number-input";
289
349
 
290
- ---
350
+ normalizeDecimals("12.34.56"); // "12.3456"
351
+ ```
291
352
 
292
- ## 🌟 مثال‌های پیشرفته
353
+ #### `stripLeadingZeros(str)`
293
354
 
294
- ### ماشین حساب مالی
355
+ حذف صفرهای اضافه ابتدای عدد:
295
356
 
296
357
  ```tsx
297
- import { useState } from "react";
298
- import { PersianNumberInput } from "persian-number-input";
358
+ import { stripLeadingZeros } from "persian-number-input";
299
359
 
300
- function LoanCalculator() {
301
- const [principal, setPrincipal] = useState<string>();
302
- const [rate, setRate] = useState<string>();
303
- const [years, setYears] = useState<string>();
304
-
305
- const calculateMonthlyPayment = () => {
306
- if (!principal || !rate || !years) return 0;
307
- const p = parseFloat(principal);
308
- const r = parseFloat(rate) / 100 / 12;
309
- const n = parseFloat(years) * 12;
310
- return (p * r * Math.pow(1 + r, n)) / (Math.pow(1 + r, n) - 1);
311
- };
312
-
313
- return (
314
- <div className="space-y-4">
315
- <div>
316
- <label>مبلغ وام:</label>
317
- <PersianNumberInput
318
- locale="fa"
319
- suffix="تومان"
320
- onValueChange={setPrincipal}
321
- min={0}
322
- />
323
- </div>
324
- <div>
325
- <label>نرخ سود (٪):</label>
326
- <PersianNumberInput
327
- locale="fa"
328
- maxDecimals={2}
329
- onValueChange={setRate}
330
- min={0}
331
- max={100}
332
- />
333
- </div>
334
- <div>
335
- <label>مدت زمان (سال):</label>
336
- <PersianNumberInput
337
- locale="fa"
338
- onValueChange={setYears}
339
- min={1}
340
- max={30}
341
- />
342
- </div>
343
- <p>
344
- پرداخت ماهیانه: {calculateMonthlyPayment().toLocaleString("fa-IR")}{" "}
345
- تومان
346
- </p>
347
- </div>
348
- );
349
- }
360
+ stripLeadingZeros("001234.56"); // "1234.56"
350
361
  ```
351
362
 
352
- ---
363
+ #### `applyDecimalPrecision(str, maxDecimals?)`
353
364
 
354
- ### یکپارچگی با فرم
365
+ محدود کردن قسمت اعشار به تعداد رقم مشخص:
355
366
 
356
367
  ```tsx
357
- import { useForm, Controller } from "react-hook-form";
358
- import { PersianNumberInput } from "persian-number-input";
368
+ import { applyDecimalPrecision } from "persian-number-input";
359
369
 
360
- function ProductForm() {
361
- const { control, handleSubmit } = useForm();
370
+ applyDecimalPrecision("1234.5678", 2); // "1234.56"
371
+ ```
362
372
 
363
- const onSubmit = (data) => {
364
- console.log(data);
365
- };
373
+ #### `roundToDecimals(value, maxDecimals?)`
366
374
 
367
- return (
368
- <form onSubmit={handleSubmit(onSubmit)}>
369
- <Controller
370
- name="price"
371
- control={control}
372
- rules={{ required: true }}
373
- render={({ field }) => (
374
- <PersianNumberInput
375
- locale="fa"
376
- suffix="تومان"
377
- onValueChange={field.onChange}
378
- initialValue={field.value}
379
- />
380
- )}
381
- />
382
- <button type="submit">ثبت</button>
383
- </form>
384
- );
385
- }
375
+ مشابه `applyDecimalPrecision` — محدود کردن قسمت اعشار:
376
+
377
+ ```tsx
378
+ import { roundToDecimals } from "persian-number-input";
379
+
380
+ roundToDecimals("1234.5678", 2); // "1234.56"
386
381
  ```
387
382
 
388
383
  ---
389
384
 
390
- ## 🔍 چرا ورودی اعداد فارسی؟
385
+ ## 🎨 استایل‌دهی
391
386
 
392
- ### مشکل
387
+ ```tsx
388
+ <PersianNumberInput
389
+ locale="fa"
390
+ className="w-full px-4 py-3 text-lg border-2 border-indigo-500 rounded-lg text-right focus:outline-none focus:ring-2 focus:ring-indigo-600"
391
+ />
392
+ ```
393
393
 
394
- کار با ارقام فارسی و عربی در برنامه‌های وب چالش‌برانگیز است:
394
+ برای چیدمان RTL، `dir="rtl"` رو روی wrapper بذارید یا `style={{ textAlign: "right" }}` رو مستقیم پاس بدید.
395
395
 
396
- - کاربران با ارقام بومی خود تایپ می‌کنند، اما فرم‌ها ارقام انگلیسی انتظار دارند
397
- - فرمت‌دهی اعداد در زبان‌های مختلف متفاوت است
398
- - حفظ موقعیت مکان‌نما هنگام فرمت‌دهی پیچیده است
399
- - مدیریت دقت اعشاری نیاز به پیاده‌سازی دقیق دارد
396
+ ---
400
397
 
401
- ### راه‌حل
398
+ ## ❓ سوالات متداول
402
399
 
403
- ورودی اعداد فارسی تمام این پیچیدگی‌ها را به صورت خودکار مدیریت می‌کند:
400
+ **آیا با Next.js و App Router کار می‌کنه؟**
401
+ بله. چون کامپوننت client-side هست، `"use client"` رو بالای فایلت بذار.
404
402
 
405
- ```tsx
406
- // کاربر تایپ می‌کند: ۱۲۳۴۵۶۷
407
- // کامپوننت نمایش می‌دهد: ۱,۲۳۴,۵۶۷
408
- // فرم دریافت می‌کند: "1234567"
409
- ```
403
+ **مقدار برگشتی `onValueChange` چیه؟**
404
+ همیشه رشته‌ای از ارقام انگلیسی — مثلاً `"1234567"` — صرف‌نظر از اینکه چه locale‌ای نمایش داده میشه.
410
405
 
411
- ---
406
+ **آیا با `input` داخل یک فرم native کار می‌کنه؟**
407
+ از `onValueChange` برای ذخیره مقدار در state استفاده کن، بعد موقع submit از state بخون. یا از React Hook Form با Controller استفاده کن (مثال بالا).
412
408
 
413
- ## 🏆 مقایسه
409
+ **تفاوت `locale="fa"` و `locale="ar"` چیه؟**
410
+ `fa` از ارقام فارسی (۰–۹) و جداکننده `٫` استفاده می‌کنه. `ar` از ارقام عربی شرقی (٠–٩). هر دو مقدار انگلیسی به `onValueChange` برمی‌گردونن.
414
411
 
415
- | امکانات | ورودی اعداد فارسی | Input معمولی | کتابخانه‌های دیگر |
416
- | ------------------- | ----------------- | ------------ | ----------------- |
417
- | تبدیل خودکار ارقام | ✅ | ❌ | ⚠️ جزئی |
418
- | حفظ مکان‌نما | ✅ | ❌ | ⚠️ باگ‌دار |
419
- | پشتیبانی TypeScript | ✅ | ✅ | ⚠️ متغیر |
420
- | چند زبانه | ✅ | ❌ | ❌ |
421
- | حجم باندل | 🟢 کم | 🟢 - | 🔴 زیاد |
422
- | دقت اعشاری | ✅ | ❌ | ⚠️ محدود |
412
+ **آیا محدودیت عددی وجود داره؟**
413
+ نه. پکیج از مقایسه عددی مبتنی بر رشته استفاده می‌کنه و اعداد خیلی بزرگ یا با دقت اعشاری بالا رو بدون خطای floating-point پردازش می‌کنه.
423
414
 
424
415
  ---
425
416
 
426
- ## 🤝 مشارکت
417
+ ## 🏆 مقایسه با بقیه
427
418
 
428
- مشارکت شما استقبال می‌شود! لطفاً از ارسال Pull Request دریغ نکنید.
429
-
430
- 1. مخزن را Fork کنید
431
- 2. شاخه ویژگی خود را ایجاد کنید (`git checkout -b feature/AmazingFeature`)
432
- 3. تغییرات خود را Commit کنید (`git commit -m 'Add some AmazingFeature'`)
433
- 4. به شاخه Push کنید (`git push origin feature/AmazingFeature`)
434
- 5. یک Pull Request باز کنید
419
+ | امکانات | persian-number-input | `<input>` معمولی | کتابخانه‌های دیگر |
420
+ | ------------------------------ | :------------------: | :--------------: | :---------------: |
421
+ | ورودی ارقام فارسی و عربی | ✅ | ❌ | ⚠️ ناقص |
422
+ | حفظ موقعیت cursor هنگام فرمت | ✅ | ❌ | ⚠️ اغلب باگ‌دار |
423
+ | چند locale (fa / ar / en) | ✅ | ❌ | ❌ |
424
+ | جداکننده هزارگان | ✅ | ❌ | ⚠️ محدود |
425
+ | کنترل دقت اعشاری | ✅ | ❌ | ⚠️ محدود |
426
+ | اعتبارسنجی min/max | ✅ | جزئی | ⚠️ متغیر |
427
+ | TypeScript | ✅ | ✅ | ⚠️ متغیر |
428
+ | حجم باندل | 🟢 ~۱ کیلوبایت | 🟢 native | 🔴 ۵–۳۰ کیلوبایت |
435
429
 
436
430
  ---
437
431
 
438
- ## 📄 مجوز
432
+ ## 🤝 مشارکت در توسعه
433
+
434
+ خوشحال میشم مشارکت کنید!
439
435
 
440
- MIT © javad Sharifi
436
+ 1. مخزن رو Fork کنید
437
+ 2. شاخه feature بسازید: `git checkout -b feature/your-feature`
438
+ 3. تغییرات رو commit کنید: `git commit -m 'Add your feature'`
439
+ 4. push کنید: `git push origin feature/your-feature`
440
+ 5. Pull Request باز کنید
441
+
442
+ برای تغییرات بزرگ، لطفاً اول یه issue باز کنید تا با هم بررسی کنیم.
441
443
 
442
444
  ---
443
445
 
444
- ## 🙏 تشکرات
446
+ ## 📄 مجوز
445
447
 
446
- - ساخته شده با TypeScript و React
447
- - استفاده از [decimal.js](https://github.com/MikeMcl/decimal.js/) برای محاسبات دقیق اعشاری
448
- - الهام‌گرفته از نیازهای توسعه‌دهندگان فارسی و عربی‌زبان
448
+ MIT © [Javad Sharifi](https://github.com/javadSharifi)
449
449
 
450
450
  ---
451
451
 
452
452
  ## 📞 پشتیبانی
453
453
 
454
- - 📧 telegram: [Javad Sharifi](https://t.me/Javad_sharifi98)
455
- - 🐛 [گزارش مشکلات](https://github.com/javadSharifi/persian-number-input/issues)
454
+ - 💬 تلگرام: [@Javad_sharifi98](https://t.me/Javad_sharifi98)
455
+ - 🐛 [گزارش مشکل](https://github.com/javadSharifi/persian-number-input/issues)
456
456
  - 💬 [بحث و گفتگو](https://github.com/javadSharifi/persian-number-input/discussions)
457
457
 
458
+ ---
459
+
458
460
  **ساخته شده با ❤️ برای جامعه توسعه‌دهندگان فارسی و عربی‌زبان**
461
+
462
+ <!-- کلیدواژه‌ها: ورودی عدد فارسی ریکت، تبدیل اعداد فارسی به انگلیسی، کامپوننت ورودی فارسی، ورودی RTL، جداکننده هزارگان فارسی، ورودی اعداد عربی، persian number input react، farsi digit input، arabic number react -->