ورودی عدد بومی (NumberInputLocale)
ورودی عددی بومیساز — ارقام فارسی، عربی یا لاتین را میپذیرد، ارقام فارسی را با قابلیت ss01 قلم نمایش میدهد و همیشه یک عدد جاوااسکریپتی تمیز به فرم تحویل میدهد.
معرفی
NumberInputLocale یک ورودی عددی است که ارقام تایپشده با هر صفحهکلیدی (فارسی، عربی یا لاتین) را میپذیرد، آنها را به رقم لاتین نرمال میکند و از طریق onValueChange همیشه یک number استاندارد جاوااسکریپت — یا null برای فیلد خالی — به فرم تحویل میدهد.
مقدار داخل input همیشه با ارقام لاتین نگهداری میشود؛ شکل فارسی ارقام را قابلیت ss01 قلم «یکان بخ» هنگام رندر
میسازد. به این ترتیب کپیبرداری، جستوجوی درونصفحه (Ctrl+F) و ارسال بومی فرم (name) همچنان یک عدد ماشینخوان تحویل
میدهند، در حالی که کاربر ارقام فارسی میبیند.
چه زمانی استفاده کنیم:
- هر فیلد عددی در فرمهای فارسی/عربی که کاربر ممکن است با صفحهکلید بومی تایپ کند (بودجه کمپین تخفیف فصلی، سقف هزینه، تعداد پست)
- وقتی نمایش باید ارقام بومی و جداکننده هزارگان داشته باشد اما مقدار ذخیرهشده و ارسالی باید عدد خام بماند
- فیلدهای دارای واحد (تومان، درصد، نفر) که واحد باید داخل خود ورودی دیده شود
چه زمانی استفاده نکنیم:
- برای متن آزاد یا رشتههایی که فقط شبیه عدد هستند (شماره تلفن، کد پستی) — از
Inputاستفاده کنید؛ صفر ابتدای این مقادیر نباید حذف شود - برای انتخاب بصری یک عدد در بازه بسته و کوچک — از
Sliderاستفاده کنید - برای کد تأیید چندرقمی — از
InputOTPاستفاده کنید
مقدار عددی خروجی: 2500000
استفاده
import { NumberInputLocale } from '@partodata/ui'const [budget, setBudget] = React.useState<number | null>(null)
<NumberInputLocale
value={budget}
onValueChange={setBudget}
unit="تومان"
min={0}
allowNegative={false}
placeholder="مبلغ را وارد کنید"
/>رفتار نمایش دو مرحلهای است: تا وقتی فیلد فوکوس دارد، همان متن تایپشده کاربر (بدون جداکننده هزارگان) نمایش داده میشود تا مکاننما هنگام ویرایش وسط عدد نپرد؛ با خروج فوکوس (blur) مقدار به بازه min و max محدود شده و با جداکننده هزارگان و تعداد اعشار مشخصشده بازنویسی میشود. onValueChange در حین تایپ نیز بهصورت زنده صدا زده میشود تا اعتبارسنجی فرم عقب نماند.
حالتها و انواع
زبان ارقام (locale)
سه مقدار fa، ar و en پشتیبانی میشود. ورودی کاربر با هر مجموعه رقمی پذیرفته و پیش از پارس به لاتین نرمال میشود. locale شکل ارقام را عوض نمیکند — مقدار input در هر سه حالت لاتین است و ظاهر فارسی از ss01 قلم میآید؛ این مقدار روی ریشه بهصورت data-locale منتشر میشود تا کد مصرفکننده و CSS به آن دسترسی داشته باشند.
<NumberInputLocale locale="fa" defaultValue={1250000} unit="بازدید" />
<NumberInputLocale locale="ar" defaultValue={1250000} unit="نفر" />
<NumberInputLocale locale="en" defaultValue={4.8} decimals={1} unit="%" />واحد (unit) و پیشوند (prefix)
unit واحدی است که بعد از عدد خوانده میشود: «250,000 تومان». در فارسی و عربی سمت چپ عدد مینشیند و در انگلیسی سمت
راست آن («250,000 USD»)، و عدد به سمت واحد چیده میشود تا این دو کنار هم خوانده شوند. prefix نمادی است که قبل از عدد
خوانده میشود — علامتهای پولی مثل «$» در انگلیسی. «تومان»، «ریال» و «٪» فارسی همیشه unit هستند، نه prefix.
هر دو جزیرهی جهتدار جداگانهای (bdi) به زبان فیلد هستند؛ خود عدد همیشه یک رشتهی چپبهراست میماند تا علامت منفی و
جداکنندهها جابهجا نشوند. فاصلهی متن تا واحد اندازهگیری میشود، پس واحد بلند هم روی ارقام نمیافتد.
زمین بازی
<NumberInputLocale unit="تومان" min={0} allowNegative={false} />
<NumberInputLocale locale="en" prefix="$" defaultValue={1250} decimals={2} />
<NumberInputLocale locale="en" unit="USD" defaultValue={250000} />محدوده مجاز (min و max)
مقادیر min و max شامل خود کران هستند و فقط هنگام blur اعمال میشوند — وسط تایپ مقدار کاربر دستکاری نمیشود. اگر مقدار پس از blur تغییر کند، onValueChange یک بار دیگر با مقدار محدودشده فراخوانی میشود.
<NumberInputLocale min={0} max={100} decimals={1} unit="٪" />اعشار و جداکننده هزارگان
پیشفرض ورودی عدد صحیح است (decimals={0}). با مقدار بزرگتر، عدد حداکثر همان تعداد رقم اعشار را میپذیرد؛ مقدار مجاز هنگام blur صفرپر میشود. اعشار اضافی حذف، قطع یا گرد نمیشود: مقدار واقعی مرئی میماند، aria-invalid فعال میشود و اعتبارسنجی بومی فرم آن را رد میکند. برای نمونه، 1.5 در حالت صحیح به 15 تبدیل نمیشود و 12.345 با decimals={2} بهصورت 12.35 پنهان نمیشود. مقدار مجاز 0.29 با دو رقم اعشار معتبر است.
جداکنندهٔ اعشار فارسی/عربی ٫ به نقطه و جداکنندهٔ هزارگان ٬ به رشتهٔ خالی نرمال میشود؛ ورودی با ارقام فارسی یا عربی، همان مقدار عددی را به callback میفرستد. جداکننده هزارگان نمایشی بهصورت پیشفرض فعال است و با thousandSeparator={false} خاموش میشود.
<NumberInputLocale decimals={2} thousandSeparator={false} />onValueChange عدد واقعی را حتی در حالت precision نامعتبر به مصرفکننده میدهد؛ null به معنای پاکشدن فیلد است. پیش از ذخیره، اعتبار فرم و قواعد دامنهٔ محصول را بررسی کنید. ارسال بومی فرم مقدار نامعتبر را متوقف میکند؛ دکمهٔ بیرون فرم یا ارسال دستی باید checkValidity() یا reportValidity() فیلد و guard عددی مناسب را صریحاً بررسی کند.
اعداد منفی
بهصورت پیشفرض علامت منفی پذیرفته میشود. با allowNegative={false} مقدار منفی مرئی و نامعتبر میماند و callback همان عدد منفی را میفرستد؛ علامت منفی حذف نمیشود تا -5 به مبلغ دیگری مانند 5 تبدیل نشود. اگر min={0} هم داده شود، محدودسازی صریح هنگام blur طبق معمول مقدار را به 0 میرساند:
<NumberInputLocale allowNegative={false} min={0} />کنترلشده و کنترلنشده
مانند سایر ورودیها هر دو حالت پشتیبانی میشود: با value و onValueChange کنترلشده، و با defaultValue کنترلنشده. مقدار null در هر دو حالت به معنای فیلد خالی است.
// کنترلنشده — فقط مقدار اولیه
<NumberInputLocale defaultValue={5000} onValueChange={(next) => console.log(next)} />راهنمای استفاده
بکنید
- مقدار را همیشه بهصورت
numberیاnullنگه دارید و ازonValueChangeبخوانید — پارس و نرمالسازی ارقام کار خود کامپوننت است. - برای رد مقدار منفی ازallowNegative={false}استفاده کنید؛min={0}را تنها وقتی بدهید که محدودسازی مقدار به صفر در blur رفتار موردنظر فرم است. قواعد دامنهٔ محصول را پیش از ارسال جداگانه بررسی کنید. - واحد فیلد را با propunitنشان دهید و همان واحد را درLabelیاaria-labelهم تکرار کنید تا برای صفحهخوانها نیز روشن باشد. - برای فرمهای چندزبانه،localeرا از تنظیمات زبان کاربر بگیرید؛ شکل ارقام از قلم میآید، پس نیازی به تبدیل دستی رقم در کد مصرفکننده نیست.
نکنید
- از این کامپوننت برای شماره تلفن، کد ملی یا کد پستی استفاده نکنید — این مقادیر رشته هستند و صفر ابتدایشان نباید حذف
شود؛ از
Inputاستفاده کنید. - مقدار نمایشی داخل فیلد را خودتان دوباره فرمت نکنید (مثلاً با افزودن جداکننده درonValueChange) — چرخه فرمتمجدد، مکاننمای کاربر را میپراند. - انتظار نداشته باشیدminوmaxوسط تایپ اعمال شوند — محدودسازی عمداً به blur موکول شده تا ویرایش نیمهکاره خراب نشود؛ اعتبارسنجی لحظهای فرم را جداگانه انجام دهید. - واحد را بهصورت متن داخل
placeholderیا بعد از فیلد تکرار نکنید وقتیunitتنظیم شده — دو بار نمایش واحد گیجکننده است.
Props
کامپوننت علاوه بر موارد زیر، همه ویژگیهای بومی input (مانند id، placeholder، disabled، readOnly و صفات aria-*) را میپذیرد؛ فقط type، value، defaultValue، onChange و size بومی کنار گذاشته شدهاند. ref نیز مستقیماً به المنت input میرسد.
دسترسیپذیری
- از یک
inputبومی باtype="text"وinputMode="decimal"استفاده میکند — موبایلها صفحهکلید عددی نشان میدهند بدون رفتارهای ناخواستهtype="number"مرورگر. - جهت فیلد همیشه
dir="ltr"با تراز انتهایی است تا عدد در فرمهای RTL هم به شکل طبیعی خوانده شود. - کاربر با هر صفحهکلیدی (فارسی، عربی، لاتین) میتواند تایپ کند؛ نرمالسازی ارقام خودکار است و خطای «رقم نامعتبر» رخ نمیدهد.
- پسوند
unitیک عنصر تزئینی است و بهصورت برنامهای به فیلد متصل نیست — واحد را درLabelمتصل باhtmlForیا درaria-labelهم ذکر کنید. - همه صفات بومی از جمله
aria-invalidعبور داده میشوند. اعشار اضافی یا منفیِ نامجاز، خودکارaria-invalidو custom validity را فعال میکند؛ با اصلاح یا پاککردن مقدار خطای داخلی پاک میشود و وضعیت خطای مصرفکننده همچنان حفظ میشود. استایل حالت خطا ازInputپایه به ارث میرسد. - این کامپوننت spinbutton نیست: دکمه افزایش/کاهش و کلیدهای جهتنما برای تغییر مقدار ندارد؛ تعامل همان تایپ آزاد است.
تعامل با کیبورد
Tab: انتقال فوکوس به فیلد؛ با ورود فوکوس، جداکنندههای هزارگان حذف میشوند تا ویرایش سادهتر شود - خروج فوکوس: محدودسازی به بازه مجاز و بازنویسی نمایش با جداکننده هزارگان - در حالتdisabledفیلد از ترتیب فوکوس خارج میشود
کامپوننتهای مرتبط
- Input — اگر مقدار در واقع رشته است (شماره تلفن، کد پستی، متن آزاد) و نباید به عدد تبدیل شود
- Input — اگر ورودی به واحد، آیکون یا دکمه کنارش نیاز دارد (
startAdornment/endAdornment) - Slider — اگر انتخاب عدد در یک بازه بسته و کوچک است و بازخورد بصری مهمتر از تایپ دقیق است
- InputOTP — اگر ورودی یک کد عددی چندرقمی با خانههای جدا است، نه یک مقدار عددی