persian-number-input 4.0.6 → 4.0.7
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/dist/hooks/usePersianNumberInput.d.ts +0 -6
- package/dist/hooks/usePersianNumberInput.d.ts.map +1 -1
- package/dist/hooks/usePersianNumberInput.js +63 -67
- package/dist/hooks/usePersianNumberInput.js.map +1 -1
- package/dist/utils/transformNumber.d.ts +6 -9
- package/dist/utils/transformNumber.d.ts.map +1 -1
- package/dist/utils/transformNumber.js +75 -52
- package/dist/utils/transformNumber.js.map +1 -1
- package/package.json +1 -1
|
@@ -5,19 +5,13 @@ interface UsePersianNumberInputProps extends Omit<TransformNumberOptions, 'maxDe
|
|
|
5
5
|
onValueChange?: (value: string | undefined) => void;
|
|
6
6
|
min?: number;
|
|
7
7
|
max?: number;
|
|
8
|
-
/** حداکثر تعداد ارقام اعشار مجاز. undefined یعنی نامحدود. */
|
|
9
8
|
maxDecimals?: number;
|
|
10
|
-
/** کاراکتری که کاربر برای وارد کردن اعشار استفاده میکند (مثلا '.' یا '/') */
|
|
11
9
|
inputDecimalSeparator?: string;
|
|
12
10
|
}
|
|
13
11
|
interface UsePersianNumberInputReturn {
|
|
14
|
-
/** مقدار فرمت شده برای نمایش در input */
|
|
15
12
|
value: string;
|
|
16
|
-
/** هندلر onChange برای input */
|
|
17
13
|
onChange: (event: React.ChangeEvent<HTMLInputElement>) => void;
|
|
18
|
-
/** تابعی برای تنظیم مقدار به صورت برنامهنویسی */
|
|
19
14
|
setValue: (newValue: number | string | undefined) => void;
|
|
20
|
-
/** مقدار عددی خام (رشته انگلیسی بدون جداکننده گروه) */
|
|
21
15
|
rawValue: string | undefined;
|
|
22
16
|
}
|
|
23
17
|
export declare const usePersianNumberInput: ({ initialValue, separatorCount, separatorChar, locale, showZero, onValueChange, min, max, maxDecimals, inputDecimalSeparator, }?: UsePersianNumberInputProps) => UsePersianNumberInputReturn;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"usePersianNumberInput.d.ts","sourceRoot":"","sources":["../../src/hooks/usePersianNumberInput.ts"],"names":[],"mappings":"AACA,OAAO,KAAoD,MAAM,OAAO,CAAC;AAEzE,OAAO,EAAmB,sBAAsB,EAAE,MAAM,0BAA0B,CAAC;AAGnF,UAAU,0BAA2B,SAAQ,IAAI,CAAC,sBAAsB,EAAE,aAAa,CAAC;IACtF,YAAY,CAAC,EAAE,MAAM,GAAG,MAAM,CAAC;IAC/B,aAAa,CAAC,EAAE,CAAC,KAAK,EAAE,MAAM,GAAG,SAAS,KAAK,IAAI,CAAC;IACpD,GAAG,CAAC,EAAE,MAAM,CAAC;IACb,GAAG,CAAC,EAAE,MAAM,CAAC;IACb,
|
|
1
|
+
{"version":3,"file":"usePersianNumberInput.d.ts","sourceRoot":"","sources":["../../src/hooks/usePersianNumberInput.ts"],"names":[],"mappings":"AACA,OAAO,KAAoD,MAAM,OAAO,CAAC;AAEzE,OAAO,EAAmB,sBAAsB,EAAE,MAAM,0BAA0B,CAAC;AAGnF,UAAU,0BAA2B,SAAQ,IAAI,CAAC,sBAAsB,EAAE,aAAa,CAAC;IACtF,YAAY,CAAC,EAAE,MAAM,GAAG,MAAM,CAAC;IAC/B,aAAa,CAAC,EAAE,CAAC,KAAK,EAAE,MAAM,GAAG,SAAS,KAAK,IAAI,CAAC;IACpD,GAAG,CAAC,EAAE,MAAM,CAAC;IACb,GAAG,CAAC,EAAE,MAAM,CAAC;IACb,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,qBAAqB,CAAC,EAAE,MAAM,CAAC;CAChC;AAED,UAAU,2BAA2B;IACnC,KAAK,EAAE,MAAM,CAAC;IACd,QAAQ,EAAE,CAAC,KAAK,EAAE,KAAK,CAAC,WAAW,CAAC,gBAAgB,CAAC,KAAK,IAAI,CAAC;IAC/D,QAAQ,EAAE,CAAC,QAAQ,EAAE,MAAM,GAAG,MAAM,GAAG,SAAS,KAAK,IAAI,CAAC;IAC1D,QAAQ,EAAE,MAAM,GAAG,SAAS,CAAC;CAC9B;AAED,eAAO,MAAM,qBAAqB,GAAI,kIAWnC,0BAA+B,KAAG,2BAoHpC,CAAC"}
|
|
@@ -6,104 +6,99 @@ Object.defineProperty(exports, "__esModule", { value: true });
|
|
|
6
6
|
exports.usePersianNumberInput = void 0;
|
|
7
7
|
// hooks/usePersianNumberInput.ts
|
|
8
8
|
const react_1 = require("react");
|
|
9
|
-
const decimal_js_1 = __importDefault(require("decimal.js"));
|
|
9
|
+
const decimal_js_1 = __importDefault(require("decimal.js"));
|
|
10
10
|
const transformNumber_1 = require("../utils/transformNumber");
|
|
11
|
-
const digitUtils_1 = require("../utils/digitUtils");
|
|
12
|
-
const usePersianNumberInput = ({ initialValue, separatorCount = 3, separatorChar = ',', locale = 'fa', showZero = false, onValueChange, min, max, maxDecimals,
|
|
13
|
-
inputDecimalSeparator = '.', // پیشفرض نقطه است
|
|
14
|
-
} = {}) => {
|
|
11
|
+
const digitUtils_1 = require("../utils/digitUtils");
|
|
12
|
+
const usePersianNumberInput = ({ initialValue, separatorCount = 3, separatorChar = ',', locale = 'fa', showZero = false, onValueChange, min, max, maxDecimals, inputDecimalSeparator = '.', } = {}) => {
|
|
15
13
|
const getSanitizedAndRoundedValue = (0, react_1.useCallback)((val) => {
|
|
16
14
|
if (val === null || val === undefined)
|
|
17
15
|
return undefined;
|
|
18
16
|
let sanitized = (0, digitUtils_1.sanitizeNumericInput)(String(val), inputDecimalSeparator);
|
|
19
|
-
//
|
|
17
|
+
// مقادیر بینابینی '-', '.', '-.' را فعلا نگه دار
|
|
20
18
|
if (sanitized === '-' || sanitized === '.' || sanitized === '-.') {
|
|
21
|
-
//
|
|
22
|
-
//
|
|
19
|
+
// این مقادیر نباید به عنوان مقدار نهایی باقی بمانند اگر showZero=false
|
|
20
|
+
// در انتها بررسی میشود
|
|
23
21
|
}
|
|
24
|
-
else if (sanitized) {
|
|
22
|
+
else if (sanitized) { // اگر رشته خالی یا فقط بینابینی نیست
|
|
25
23
|
try {
|
|
26
|
-
|
|
27
|
-
//
|
|
28
|
-
if (
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
24
|
+
const numericValue = new decimal_js_1.default(sanitized);
|
|
25
|
+
// ****** اصلاح مشکل ۲: Clamp کردن مقدار ******
|
|
26
|
+
if (min !== undefined && numericValue.lt(min)) {
|
|
27
|
+
console.warn(`Value ${sanitized} is less than min ${min}. Clamping to min.`);
|
|
28
|
+
// مقدار را به min محدود کن: min را به رشته تبدیل، sanitize و round کن
|
|
29
|
+
const minStr = (0, digitUtils_1.sanitizeNumericInput)(String(min), '.'); // min را با نقطه استاندارد sanitize کن
|
|
30
|
+
sanitized = (0, digitUtils_1.roundToDecimals)(minStr, maxDecimals);
|
|
31
|
+
}
|
|
32
|
+
else if (max !== undefined && numericValue.gt(max)) {
|
|
33
|
+
console.warn(`Value ${sanitized} exceeds max ${max}. Clamping to max.`);
|
|
34
|
+
// مقدار را به max محدود کن: max را به رشته تبدیل، sanitize و round کن
|
|
35
|
+
const maxStr = (0, digitUtils_1.sanitizeNumericInput)(String(max), '.'); // max را با نقطه استاندارد sanitize کن
|
|
36
|
+
sanitized = (0, digitUtils_1.roundToDecimals)(maxStr, maxDecimals);
|
|
37
|
+
}
|
|
38
|
+
else {
|
|
39
|
+
// اگر در محدوده بود، فقط مقدار اصلی sanitize شده را گرد کن
|
|
40
|
+
sanitized = (0, digitUtils_1.roundToDecimals)(sanitized, maxDecimals);
|
|
37
41
|
}
|
|
38
|
-
// حالا گرد کردن را انجام بده
|
|
39
|
-
// نکته: roundToDecimals باید بعد از چک کردن min/max باشد
|
|
40
|
-
sanitized = (0, digitUtils_1.roundToDecimals)(sanitized, maxDecimals);
|
|
41
42
|
}
|
|
42
43
|
catch (error) {
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
return undefined;
|
|
47
|
-
// در غیر اینصورت، خود '-' یا '.' را موقتا نگه دار
|
|
44
|
+
// اگر در تبدیل به Decimal خطا رخ داد (مثلا برای مقادیر بینابینی نامعتبر)
|
|
45
|
+
console.warn(`Error processing sanitized value: ${sanitized}`, error);
|
|
46
|
+
return undefined; // مقدار نامعتبر است
|
|
48
47
|
}
|
|
49
48
|
}
|
|
50
49
|
else {
|
|
51
|
-
// اگر
|
|
50
|
+
// اگر sanitizeNumericInput رشته خالی برگرداند
|
|
52
51
|
return undefined;
|
|
53
52
|
}
|
|
54
|
-
// مدیریت showZero
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
//
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
53
|
+
// مدیریت showZero برای مقدار نهایی (بعد از clamp و round)
|
|
54
|
+
if (!showZero) {
|
|
55
|
+
// اگر مقادیر بینابینی هستند، آنها را به undefined تبدیل کن
|
|
56
|
+
if (sanitized === '-' || sanitized === '.' || sanitized === '-.') {
|
|
57
|
+
return undefined;
|
|
58
|
+
}
|
|
59
|
+
// اگر مقدار عددی صفر است (و صرفا نقطه انتهایی ندارد)
|
|
60
|
+
try {
|
|
61
|
+
if (sanitized && new decimal_js_1.default(sanitized).isZero() && !sanitized.endsWith('.')) {
|
|
62
|
+
return undefined;
|
|
63
|
+
}
|
|
64
|
+
}
|
|
65
|
+
catch ( /* نادیده گرفتن خطا */_a) { /* نادیده گرفتن خطا */ }
|
|
66
66
|
}
|
|
67
|
-
|
|
67
|
+
// در نهایت، اگر رشته خالی شده، undefined برگردان
|
|
68
|
+
return sanitized === '' ? undefined : sanitized;
|
|
68
69
|
}, [inputDecimalSeparator, min, max, maxDecimals, showZero]);
|
|
69
70
|
const [rawValue, setRawValue] = (0, react_1.useState)(() => getSanitizedAndRoundedValue(initialValue));
|
|
70
|
-
// برای همگامسازی با initialValue در صورت تغییر خارجی
|
|
71
71
|
(0, react_1.useEffect)(() => {
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
if (
|
|
77
|
-
//
|
|
78
|
-
// transformNumber خودش showZero را هندل میکند
|
|
79
|
-
return (0, transformNumber_1.transformNumber)(rawValue, options);
|
|
80
|
-
}
|
|
81
|
-
// اگر rawValue فقط نقطه است (مثلا '.') یا '-.'
|
|
82
|
-
if (rawValue === '.' || rawValue === '-.') {
|
|
83
|
-
// نمایش مناسب بده (مثلا ۰٫ یا -۰٫)
|
|
84
|
-
const base = rawValue.startsWith('-') ? '-0' : '0';
|
|
85
|
-
// transformNumber خودش به درستی نقطه را محلی میکند
|
|
86
|
-
return (0, transformNumber_1.transformNumber)(`${base}.`, options);
|
|
72
|
+
// فقط اگر initialValue واقعا تغییر کرده، rawValue را آپدیت کن
|
|
73
|
+
// این از بازنشانی ناخواسته جلوگیری میکند
|
|
74
|
+
const newSanitized = getSanitizedAndRoundedValue(initialValue);
|
|
75
|
+
// مقایسه دقیق لازم است
|
|
76
|
+
if (newSanitized !== rawValue) {
|
|
77
|
+
// setRawValue(newSanitized); // آیا این لازم است؟ شاید باعث رفتار ناخواسته شود
|
|
87
78
|
}
|
|
79
|
+
// TODO: بررسی دقیق رفتار useEffect با initialValue
|
|
80
|
+
}, [initialValue]); // getSanitizedAndRoundedValue را از وابستگی حذف کردیم تا از لوپ جلوگیری شود
|
|
81
|
+
const displayValue = (0, react_1.useMemo)(() => {
|
|
82
|
+
const options = { separatorCount, separatorChar, locale, showZero, maxDecimals };
|
|
83
|
+
// تابع transformNumber حالا باید بتواند rawValue های مختلف را به درستی نمایش دهد
|
|
88
84
|
return (0, transformNumber_1.transformNumber)(rawValue, options);
|
|
89
85
|
}, [rawValue, separatorCount, separatorChar, locale, showZero, maxDecimals]);
|
|
90
86
|
const handleChange = (0, react_1.useCallback)((event) => {
|
|
91
87
|
const inputValue = event.target.value;
|
|
92
88
|
const newRawValue = getSanitizedAndRoundedValue(inputValue);
|
|
93
|
-
// فقط اگر مقدار خام
|
|
94
|
-
// این مقایسه مهم است تا از لوپهای آپدیت ناخواسته جلوگیری شود
|
|
89
|
+
// فقط اگر مقدار خام جدید با مقدار قبلی متفاوت است، آپدیت کن
|
|
95
90
|
if (newRawValue !== rawValue) {
|
|
96
91
|
setRawValue(newRawValue);
|
|
97
92
|
if (onValueChange) {
|
|
98
93
|
onValueChange(newRawValue);
|
|
99
94
|
}
|
|
100
95
|
}
|
|
101
|
-
//
|
|
102
|
-
//
|
|
103
|
-
//
|
|
104
|
-
//
|
|
105
|
-
|
|
106
|
-
|
|
96
|
+
// نکته: اگر کاربر کاراکتری وارد کند که باعث clamp شدن شود (مثلا در max)،
|
|
97
|
+
// newRawValue ممکن است با rawValue قبلی *متفاوت* باشد (برابر با max)،
|
|
98
|
+
// ولی با چیزی که کاربر تایپ کرده متفاوت است. input باید آپدیت شود تا مقدار clamp شده را نشان دهد.
|
|
99
|
+
// منطق فعلی این کار را انجام میدهد.
|
|
100
|
+
}, [rawValue, getSanitizedAndRoundedValue, onValueChange] // getSanitizedAndRoundedValue اینجا لازم است
|
|
101
|
+
);
|
|
107
102
|
const handleSetValue = (0, react_1.useCallback)((newValue) => {
|
|
108
103
|
const newRawValue = getSanitizedAndRoundedValue(newValue);
|
|
109
104
|
if (newRawValue !== rawValue) {
|
|
@@ -112,7 +107,8 @@ inputDecimalSeparator = '.', // پیشفرض نقطه است
|
|
|
112
107
|
onValueChange(newRawValue);
|
|
113
108
|
}
|
|
114
109
|
}
|
|
115
|
-
}, [rawValue, getSanitizedAndRoundedValue, onValueChange]
|
|
110
|
+
}, [rawValue, getSanitizedAndRoundedValue, onValueChange] // getSanitizedAndRoundedValue اینجا لازم است
|
|
111
|
+
);
|
|
116
112
|
return { value: displayValue, onChange: handleChange, setValue: handleSetValue, rawValue };
|
|
117
113
|
};
|
|
118
114
|
exports.usePersianNumberInput = usePersianNumberInput;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"usePersianNumberInput.js","sourceRoot":"","sources":["../../src/hooks/usePersianNumberInput.ts"],"names":[],"mappings":";;;;;;AAAA,iCAAiC;AACjC,iCAAyE;AACzE,4DAAiC
|
|
1
|
+
{"version":3,"file":"usePersianNumberInput.js","sourceRoot":"","sources":["../../src/hooks/usePersianNumberInput.ts"],"names":[],"mappings":"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"}
|
|
@@ -1,21 +1,18 @@
|
|
|
1
1
|
export interface TransformNumberOptions {
|
|
2
|
-
/** تعداد ارقام در هر گروه برای جداسازی (مثلا 3). 0 یا کمتر یعنی بدون جداسازی. */
|
|
3
2
|
separatorCount?: number;
|
|
4
|
-
/** کاراکتر جداکننده گروه ها (پیش فرض ','). */
|
|
5
3
|
separatorChar?: string;
|
|
6
|
-
/** کد زبان برای نمایش ارقام ('fa', 'en', ...). پیش فرض 'fa'. */
|
|
7
4
|
locale?: 'fa' | 'en' | string;
|
|
8
|
-
/** حداکثر تعداد ارقام اعشار مجاز. 0 یعنی بدون اعشار. */
|
|
9
5
|
maxDecimals?: number;
|
|
10
|
-
/** اگر true باشد، حتی اگر مقدار ورودی 0 باشد، آن را نمایش بده. پیش فرض false */
|
|
11
6
|
showZero?: boolean;
|
|
12
7
|
}
|
|
13
8
|
/**
|
|
14
|
-
*
|
|
9
|
+
* رشته عددی خام (انگلیسی، با نقطه استاندارد) را به فرمت نمایشی تبدیل میکند.
|
|
10
|
+
* فرض میشود ورودی از rawValue هوک آمده و قبلا sanitize و round شده است.
|
|
15
11
|
*
|
|
16
|
-
* @param
|
|
12
|
+
* @param rawValue رشته عددی خام (مثلا "1234.5", "15.", "-0.1", "-", ".") یا undefined.
|
|
17
13
|
* @param options تنظیمات قالب بندی.
|
|
18
|
-
* @returns رشته قالب بندی شده
|
|
14
|
+
* @returns رشته قالب بندی شده برای نمایش.
|
|
19
15
|
*/
|
|
20
|
-
export declare const transformNumber: (
|
|
16
|
+
export declare const transformNumber: (rawValue: string | undefined, // تغییر ورودی به string | undefined برای وضوح
|
|
17
|
+
options?: TransformNumberOptions) => string;
|
|
21
18
|
//# sourceMappingURL=transformNumber.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"transformNumber.d.ts","sourceRoot":"","sources":["../../src/utils/transformNumber.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"transformNumber.d.ts","sourceRoot":"","sources":["../../src/utils/transformNumber.ts"],"names":[],"mappings":"AAYA,MAAM,WAAW,sBAAsB;IACrC,cAAc,CAAC,EAAE,MAAM,CAAC;IACxB,aAAa,CAAC,EAAE,MAAM,CAAC;IACvB,MAAM,CAAC,EAAE,IAAI,GAAG,IAAI,GAAG,MAAM,CAAC;IAC9B,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,QAAQ,CAAC,EAAE,OAAO,CAAC;CACpB;AAED;;;;;;;GAOG;AACH,eAAO,MAAM,eAAe,GAC1B,UAAU,MAAM,GAAG,SAAS,EAAE,8CAA8C;AAC5E,UAAU,sBAAsB,KAC/B,MA8FF,CAAC"}
|
|
@@ -1,75 +1,98 @@
|
|
|
1
1
|
"use strict";
|
|
2
|
+
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
3
|
+
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
4
|
+
};
|
|
2
5
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
6
|
exports.transformNumber = void 0;
|
|
4
7
|
// utils/transformNumber.ts
|
|
5
8
|
const digitUtils_1 = require("./digitUtils");
|
|
9
|
+
const decimal_js_1 = __importDefault(require("decimal.js")); // برای بررسی دقیق صفر
|
|
6
10
|
/**
|
|
7
|
-
*
|
|
11
|
+
* رشته عددی خام (انگلیسی، با نقطه استاندارد) را به فرمت نمایشی تبدیل میکند.
|
|
12
|
+
* فرض میشود ورودی از rawValue هوک آمده و قبلا sanitize و round شده است.
|
|
8
13
|
*
|
|
9
|
-
* @param
|
|
14
|
+
* @param rawValue رشته عددی خام (مثلا "1234.5", "15.", "-0.1", "-", ".") یا undefined.
|
|
10
15
|
* @param options تنظیمات قالب بندی.
|
|
11
|
-
* @returns رشته قالب بندی شده
|
|
16
|
+
* @returns رشته قالب بندی شده برای نمایش.
|
|
12
17
|
*/
|
|
13
|
-
const transformNumber = (
|
|
14
|
-
|
|
15
|
-
separatorChar = ',', locale = 'fa', maxDecimals
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
// 1. تبدیل ورودی به رشته و سپس به ارقام انگلیسی و پاکسازی اولیه
|
|
21
|
-
// توجه: در استفاده با input، بهتر است sanitizeNumericInput روی مقدار input *قبل* از پاس دادن به این تابع اجرا شود.
|
|
22
|
-
// اما برای اطمینان، اینجا هم یک تبدیل اولیه انجام می دهیم.
|
|
23
|
-
let str = (0, digitUtils_1.convertToEnglishDigits)(String(input));
|
|
24
|
-
// 2. بررسی اولیه برای معتبر بودن فرمت عددی (اختیاری اما مفید)
|
|
25
|
-
// این regex اجازه یک منفی در ابتدا و یک نقطه اعشار را می دهد.
|
|
26
|
-
if (!/^-?\d*(\.\d*)?$/.test(str)) {
|
|
27
|
-
// اگر فرمت پایه عددی نیست (بعد از تبدیل به انگلیسی)، یا خالی برگردان یا خود ورودی اصلی
|
|
28
|
-
// تصمیم: فعلا خالی بر میگردانیم یا صفر اگر showZero فعال باشد
|
|
29
|
-
console.warn(`Invalid numeric string after conversion: "${str}" from input: "${input}"`);
|
|
18
|
+
const transformNumber = (rawValue, // تغییر ورودی به string | undefined برای وضوح
|
|
19
|
+
options) => {
|
|
20
|
+
const { separatorCount = 3, separatorChar = ',', locale = 'fa', maxDecimals, // ممکن است برای نمایش لازم باشد (اگرچه round در هوک انجام شده)
|
|
21
|
+
showZero = false, } = options || {};
|
|
22
|
+
// 1. مدیریت ورودیهای null/undefined/empty
|
|
23
|
+
if (rawValue === null || rawValue === undefined || rawValue === "") {
|
|
24
|
+
// نکته: تبدیل صفر به لوکال '۰' در صورت نیاز
|
|
30
25
|
return showZero ? (0, digitUtils_1.toLocalizedDigits)("0", locale) : "";
|
|
31
26
|
}
|
|
32
|
-
//
|
|
33
|
-
if (
|
|
34
|
-
|
|
27
|
+
// 2. مدیریت حالتهای خاص که ممکن است rawValue باشند
|
|
28
|
+
if (rawValue === "-") {
|
|
29
|
+
// اگر فقط منفی است، و showZero فعال است، شاید بهتر باشد "-0" نمایش دهیم؟
|
|
30
|
+
// فعلا خود "-" را برمیگردانیم یا اگر showZero=false خالی؟ سازگاری مهم است.
|
|
31
|
+
// اجازه دهید نمایش "-" را بدهیم.
|
|
32
|
+
return "-"; // یا بر اساس showZero تصمیم بگیرید
|
|
35
33
|
}
|
|
36
|
-
|
|
37
|
-
|
|
34
|
+
if (rawValue === ".") {
|
|
35
|
+
// نمایش "۰٫" یا فقط "٫" ؟ نمایش "۰٫" خواناتر است.
|
|
36
|
+
const display = showZero ? "0." : ".";
|
|
37
|
+
const localizedDisplay = (0, digitUtils_1.localizeDecimalSeparator)(display, locale);
|
|
38
|
+
return (0, digitUtils_1.toLocalizedDigits)(localizedDisplay, locale);
|
|
38
39
|
}
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
40
|
+
if (rawValue === "-.") {
|
|
41
|
+
const display = showZero ? "-0." : "-.";
|
|
42
|
+
const localizedDisplay = (0, digitUtils_1.localizeDecimalSeparator)(display, locale);
|
|
43
|
+
return (0, digitUtils_1.toLocalizedDigits)(localizedDisplay, locale);
|
|
44
|
+
}
|
|
45
|
+
// 3. اطمینان از معتبر بودن فرمت (اختیاری، چون rawValue باید معتبر باشد)
|
|
46
|
+
// این regex نقطه انتهایی را هم قبول میکند
|
|
47
|
+
if (!/^-?\d*(\.\d*)?$/.test(rawValue)) {
|
|
48
|
+
console.warn(`Invalid rawValue passed to transformNumber: "${rawValue}"`);
|
|
49
|
+
return showZero ? (0, digitUtils_1.toLocalizedDigits)("0", locale) : "";
|
|
42
50
|
}
|
|
43
|
-
//
|
|
44
|
-
let
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
fractionalPart = fractionalPart.slice(0, maxDecimals);
|
|
49
|
-
// اگر بعد از بریدن، قسمت اعشاری خالی شد، آن را حذف کن
|
|
50
|
-
str = fractionalPart ? `${integerPart}.${fractionalPart}` : integerPart;
|
|
51
|
+
// 4. بررسی صفر بودن مقدار (با دقت Decimal.js)
|
|
52
|
+
let isEffectivelyZero = false;
|
|
53
|
+
try {
|
|
54
|
+
if (rawValue !== '-' && rawValue !== '.' && rawValue !== '-.') { // از Decimal با این مقادیر جلوگیری کن
|
|
55
|
+
isEffectivelyZero = new decimal_js_1.default(rawValue).isZero();
|
|
51
56
|
}
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
57
|
+
}
|
|
58
|
+
catch ( /* خطا در تبدیل به Decimal نادیده گرفته شود */_a) { /* خطا در تبدیل به Decimal نادیده گرفته شود */ }
|
|
59
|
+
if (isEffectivelyZero && !showZero) {
|
|
60
|
+
// اگر مقدار صفر است و نباید نمایش داده شود
|
|
61
|
+
// مگر اینکه کاربر در حال تایپ نقطه بعد از صفر باشد (مثل '0.')
|
|
62
|
+
if (!rawValue.endsWith('.')) {
|
|
63
|
+
return "";
|
|
55
64
|
}
|
|
56
65
|
}
|
|
57
|
-
|
|
58
|
-
|
|
66
|
+
// 5. جدا کردن قسمت صحیح و اعشاری
|
|
67
|
+
// rawValue باید از قبل round شده باشد، پس نیازی به roundToDecimals مجدد نیست.
|
|
68
|
+
let [integerPart, fractionalPart] = rawValue.split('.');
|
|
69
|
+
// بررسی وجود نقطه انتهایی (وقتی fractionalPart بعد از split کردن undefined است ولی نقطه در رشته بود)
|
|
70
|
+
const hasTrailingDot = rawValue.endsWith('.') && fractionalPart === undefined;
|
|
71
|
+
// رسیدگی به حالتهایی مثل ".5" که integerPart خالی است
|
|
72
|
+
if (integerPart === "" || integerPart === "-") {
|
|
73
|
+
// اگر فقط "-" بود یا خالی، با صفر جایگزین کن (اگر قرار است چیزی نمایش داده شود)
|
|
74
|
+
integerPart = rawValue.startsWith('-') ? "-0" : "0";
|
|
75
|
+
}
|
|
76
|
+
// 6. گروهبندی ارقام قسمت صحیح
|
|
77
|
+
const sign = integerPart.startsWith('-') ? '-' : '';
|
|
78
|
+
const absIntPart = integerPart.startsWith('-') ? integerPart.substring(1) : integerPart;
|
|
79
|
+
const groupedAbsInt = (0, digitUtils_1.groupDigits)(absIntPart, separatorCount, separatorChar);
|
|
80
|
+
const groupedInt = sign + groupedAbsInt;
|
|
81
|
+
// 7. بازسازی رشته نهایی (با در نظر گرفتن نقطه انتهایی)
|
|
82
|
+
let finalStr = groupedInt;
|
|
83
|
+
if (fractionalPart !== undefined) { // اگر قسمت اعشاری وجود دارد
|
|
84
|
+
finalStr = `${groupedInt}.${fractionalPart}`;
|
|
85
|
+
}
|
|
86
|
+
else if (hasTrailingDot) { // ****** این قسمت اصلاح شده ******
|
|
87
|
+
// اگر قسمت اعشاری وجود ندارد ولی رشته اصلی با نقطه تمام شده بود
|
|
88
|
+
finalStr = `${groupedInt}.`;
|
|
59
89
|
}
|
|
60
|
-
//
|
|
61
|
-
// دوباره استخراج بخش صحیح و اعشاری چون ممکن است در مرحله 3 تغییر کرده باشد
|
|
62
|
-
[integerPart, fractionalPart] = str.split('.');
|
|
63
|
-
integerPart = integerPart || "0"; // اطمینان مجدد برای حالت "."
|
|
64
|
-
const groupedInt = (0, digitUtils_1.groupDigits)(integerPart, separatorCount, separatorChar);
|
|
65
|
-
// 5. ترکیب مجدد قسمت صحیح و اعشاری (اگر وجود دارد)
|
|
66
|
-
let finalStr = fractionalPart !== undefined ? `${groupedInt}.${fractionalPart}` : groupedInt;
|
|
67
|
-
// 6. محلی سازی (اگر locale انگلیسی نیست)
|
|
90
|
+
// 8. محلی سازی (ارقام و جداکننده اعشار)
|
|
68
91
|
if (locale && locale !== 'en') {
|
|
69
|
-
//
|
|
92
|
+
// اول جداکننده نقطه را به محلی تبدیل کن
|
|
70
93
|
finalStr = (0, digitUtils_1.localizeDecimalSeparator)(finalStr, locale);
|
|
71
|
-
//
|
|
72
|
-
finalStr = (0, digitUtils_1.toLocalizedDigits)(finalStr, locale);
|
|
94
|
+
// سپس ارقام انگلیسی را به محلی تبدیل کن
|
|
95
|
+
finalStr = (0, digitUtils_1.toLocalizedDigits)(finalStr, locale);
|
|
73
96
|
}
|
|
74
97
|
return finalStr;
|
|
75
98
|
};
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"transformNumber.js","sourceRoot":"","sources":["../../src/utils/transformNumber.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"transformNumber.js","sourceRoot":"","sources":["../../src/utils/transformNumber.ts"],"names":[],"mappings":"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"}
|
package/package.json
CHANGED