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.
- package/README.fa.md +231 -227
- package/README.md +198 -221
- package/dist/components/PersianNumberInput.d.ts +1 -1
- package/dist/components/PersianNumberInput.d.ts.map +1 -1
- package/dist/components/PersianNumberInput.js +22 -17
- package/dist/components/PersianNumberInput.js.map +1 -1
- package/dist/components/PersianNumberInput.test.js +24 -6
- package/dist/components/PersianNumberInput.test.js.map +1 -1
- package/dist/hooks/useCursorManager.d.ts +4 -0
- package/dist/hooks/useCursorManager.d.ts.map +1 -0
- package/dist/hooks/useCursorManager.js +19 -0
- package/dist/hooks/useCursorManager.js.map +1 -0
- package/dist/hooks/useNumberFormatter.d.ts +18 -0
- package/dist/hooks/useNumberFormatter.d.ts.map +1 -0
- package/dist/hooks/useNumberFormatter.js +29 -0
- package/dist/hooks/useNumberFormatter.js.map +1 -0
- package/dist/hooks/useNumberValidation.d.ts +11 -0
- package/dist/hooks/useNumberValidation.d.ts.map +1 -0
- package/dist/hooks/useNumberValidation.js +22 -0
- package/dist/hooks/useNumberValidation.js.map +1 -0
- package/dist/hooks/useNumericInputEvents.d.ts +18 -0
- package/dist/hooks/useNumericInputEvents.d.ts.map +1 -0
- package/dist/hooks/useNumericInputEvents.js +39 -0
- package/dist/hooks/useNumericInputEvents.js.map +1 -0
- package/dist/hooks/usePersianNumberInput.d.ts +7 -2
- package/dist/hooks/usePersianNumberInput.d.ts.map +1 -1
- package/dist/hooks/usePersianNumberInput.js +66 -63
- package/dist/hooks/usePersianNumberInput.js.map +1 -1
- package/dist/test-utils.d.ts +7 -0
- package/dist/test-utils.d.ts.map +1 -0
- package/dist/test-utils.js +27 -0
- package/dist/test-utils.js.map +1 -0
- package/dist/utils/digitUtils.d.ts +4 -0
- package/dist/utils/digitUtils.d.ts.map +1 -1
- package/dist/utils/digitUtils.js +44 -17
- package/dist/utils/digitUtils.js.map +1 -1
- package/dist/utils/keyFilter.d.ts +16 -0
- package/dist/utils/keyFilter.d.ts.map +1 -0
- package/dist/utils/keyFilter.js +31 -0
- package/dist/utils/keyFilter.js.map +1 -0
- package/dist/utils/validation.d.ts +22 -0
- package/dist/utils/validation.d.ts.map +1 -0
- package/dist/utils/validation.js +85 -0
- package/dist/utils/validation.js.map +1 -0
- package/package.json +15 -4
package/README.fa.md
CHANGED
|
@@ -1,6 +1,8 @@
|
|
|
1
|
-
# ورودی
|
|
1
|
+
# ورودی عدد فارسی برای React — تبدیل خودکار ارقام فارسی، عربی و RTL
|
|
2
2
|
|
|
3
|
-
|
|
3
|
+
English | [فارسی](./README.fa.md)
|
|
4
|
+
|
|
5
|
+
یک کامپوننت React برای **ورودی اعداد فارسی و عربی** با تبدیل خودکار ارقام، جداکننده هزارگان، کنترل دقت اعشاری و پشتیبانی کامل از RTL. کاربر ارقام فارسی تایپ میکند، فرم شما عدد انگلیسی تمیز دریافت میکند — بدون هیچ تبدیل دستی.
|
|
4
6
|
|
|
5
7
|
[](https://www.npmjs.com/package/persian-number-input)
|
|
6
8
|
[](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
|
-
|
|
29
|
+
کاربر تایپ میکند: ۱۲۳۴۵۶۷
|
|
30
|
+
نمایش داده میشود: ۱,۲۳۴,۵۶۷
|
|
31
|
+
فرم دریافت میکند: "1234567"
|
|
22
32
|
```
|
|
23
33
|
|
|
24
|
-

|
|
25
|
-
|
|
26
34
|
---
|
|
27
35
|
|
|
28
36
|
## ✨ امکانات
|
|
29
37
|
|
|
30
|
-
- 🔢 **تبدیل خودکار ارقام**
|
|
31
|
-
- 🌍
|
|
32
|
-
- 📊
|
|
33
|
-
- 💰 **آماده برای ارز**
|
|
34
|
-
- ⚡
|
|
35
|
-
- 🎯 **
|
|
36
|
-
-
|
|
37
|
-
-
|
|
38
|
-
-
|
|
39
|
-
-
|
|
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={
|
|
108
|
+
initialValue={0}
|
|
105
109
|
locale="fa"
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
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={
|
|
124
|
+
initialValue={1234.56}
|
|
122
125
|
locale="fa"
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
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
|
-
|
|
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 استاندارد
|
|
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
|
-
|
|
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
|
-
|
|
234
|
-
|
|
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
|
-
|
|
245
|
-
|
|
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
|
-
|
|
256
|
-
|
|
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
|
-
|
|
335
|
+
حذف همه کاراکترهای غیرعددی و غیر از نقطه:
|
|
264
336
|
|
|
265
337
|
```tsx
|
|
266
|
-
|
|
267
|
-
|
|
268
|
-
|
|
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
|
-
|
|
343
|
+
#### `normalizeDecimals(str)`
|
|
344
|
+
|
|
345
|
+
نگه داشتن فقط اولین نقطه اعشاری:
|
|
281
346
|
|
|
282
347
|
```tsx
|
|
283
|
-
|
|
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 {
|
|
298
|
-
import { PersianNumberInput } from "persian-number-input";
|
|
358
|
+
import { stripLeadingZeros } from "persian-number-input";
|
|
299
359
|
|
|
300
|
-
|
|
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 {
|
|
358
|
-
import { PersianNumberInput } from "persian-number-input";
|
|
368
|
+
import { applyDecimalPrecision } from "persian-number-input";
|
|
359
369
|
|
|
360
|
-
|
|
361
|
-
|
|
370
|
+
applyDecimalPrecision("1234.5678", 2); // "1234.56"
|
|
371
|
+
```
|
|
362
372
|
|
|
363
|
-
|
|
364
|
-
console.log(data);
|
|
365
|
-
};
|
|
373
|
+
#### `roundToDecimals(value, maxDecimals?)`
|
|
366
374
|
|
|
367
|
-
|
|
368
|
-
|
|
369
|
-
|
|
370
|
-
|
|
371
|
-
|
|
372
|
-
|
|
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
|
-
|
|
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
|
-
|
|
416
|
-
|
|
417
|
-
| تبدیل خودکار ارقام | ✅ | ❌ | ⚠️ جزئی |
|
|
418
|
-
| حفظ مکاننما | ✅ | ❌ | ⚠️ باگدار |
|
|
419
|
-
| پشتیبانی TypeScript | ✅ | ✅ | ⚠️ متغیر |
|
|
420
|
-
| چند زبانه | ✅ | ❌ | ❌ |
|
|
421
|
-
| حجم باندل | 🟢 کم | 🟢 - | 🔴 زیاد |
|
|
422
|
-
| دقت اعشاری | ✅ | ❌ | ⚠️ محدود |
|
|
412
|
+
**آیا محدودیت عددی وجود داره؟**
|
|
413
|
+
نه. پکیج از مقایسه عددی مبتنی بر رشته استفاده میکنه و اعداد خیلی بزرگ یا با دقت اعشاری بالا رو بدون خطای floating-point پردازش میکنه.
|
|
423
414
|
|
|
424
415
|
---
|
|
425
416
|
|
|
426
|
-
##
|
|
417
|
+
## 🏆 مقایسه با بقیه
|
|
427
418
|
|
|
428
|
-
|
|
429
|
-
|
|
430
|
-
|
|
431
|
-
|
|
432
|
-
|
|
433
|
-
|
|
434
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
-
|
|
455
|
-
- 🐛 [گزارش
|
|
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 -->
|