import { useEffect, useState } from "react"; import { groupCommas, parseNum, toWords } from "../lib/numutil"; import { cn } from "../lib/utils"; export interface NumberInputProps { value: number | null; onChange: (n: number | null) => void; placeholder?: string; className?: string; showWords?: boolean; // نمایش معادل فارسی زیر input inputMode?: "numeric" | "decimal" | undefined; maxDecimals?: number; // حداکثر رقم اعشار (مثلاً ۲ برای قیمت واحد) disabled?: boolean; } // ورودی عددی با فرمت‌دهی خودکار (groupCommas) و نمایش کلمات فارسی export function NumberInput({ value, onChange, placeholder, className, showWords = false, inputMode = "numeric", maxDecimals, disabled = false, }: NumberInputProps) { // فرمت با رعایت حداکثر اعشار (گرد کردن) const formatValue = (n: number): string => { let v = n; if (maxDecimals != null) { const f = Math.pow(10, maxDecimals); v = Math.round(n * f) / f; } return groupCommas(v, false); }; const [text, setText] = useState(() => (value != null ? formatValue(value) : "")); // همگام‌سازی وقتی value از بیرون عوض می‌شود (مثلاً محاسبه‌ی خودکار قیمت کل). // null از بیرون متن کاربر را پاک نمی‌کند — تا تایپ میانی مثل «0.» از بین نرود. useEffect(() => { const cur = parseNum(text); if (value != null && value !== cur) { setText(formatValue(value)); } // eslint-disable-next-line react-hooks/exhaustive-deps }, [value]); const commit = (raw: string) => { const n = parseNum(raw); if (n != null) { const formatted = formatValue(n); setText(formatted); onChange(n); } else { setText(raw); onChange(null); } }; const n = parseNum(text); return (
{ const raw = e.target.value; // فرمت‌دهی خودکار هنگام تایپ — اما جداکننده‌ی اعشارِ وسط تایپ // («0.» یا «1.») دست‌نخورده می‌ماند تا کاربر بتواند اعشار بزند const parsed = parseNum(raw); const trailingSep = /[.,،/٬٫]$/.test(raw); if (parsed != null && !trailingSep) { setText(formatValue(parsed)); onChange(parsed); } else { setText(raw); onChange(parsed); } }} onBlur={() => commit(text)} /> {showWords && ( {n != null ? ( <> {groupCommas(n, true)} ({toWords(n)}) ) : ( "" )} )}
); }