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; inputClassName?: string; align?: "right" | "center" | "left"; // تنظیم جهت متن و اعداد (پیش‌فرض: راست‌چین) showWords?: boolean; // نمایش معادل فارسی زیر input inputMode?: "numeric" | "decimal" | undefined; maxDecimals?: number; // حداکثر رقم اعشار disabled?: boolean; } // ورودی عددی با فرمت‌دهی خودکار (groupCommas) و نمایش کلمات فارسی export function NumberInput({ value, onChange, placeholder, className, inputClassName, align = "right", 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) : "")); 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); const alignClass = align === "center" ? "!text-center text-center" : align === "left" ? "!text-left text-left" : "!text-right text-right"; return (
{ const raw = e.target.value; 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)})
)}
); }