import clsx from 'clsx'; import React, { useEffect, useState } from 'react'; import { FiMinus, FiPlus } from 'react-icons/fi'; import { useTranslation } from '@/hooks/useTranslation'; interface NumberInputProps { className?: string; inputClassName?: string; label: string; iconSize?: number; value: number; min: number; max: number; step?: number; disabled?: boolean; onChange: (value: number) => void; 'data-setting-id'?: string; } const NumberInput: React.FC = ({ className, inputClassName, label, iconSize, value, onChange, min, max, step, disabled, 'data-setting-id': settingId, }) => { const _ = useTranslation(); const [displayValue, setDisplayValue] = useState(String(value)); const numberStep = step || 1; useEffect(() => { setDisplayValue(String(value)); }, [value]); const handleChange = (e: React.ChangeEvent) => { const raw = e.target.value; // Allow empty string or valid number fragments while typing if (raw === '' || /^[0-9]*\.?[0-9]*$/.test(raw)) { setDisplayValue(raw); } }; const commitValue = (v: number) => { const clamped = Math.round(Math.max(min, Math.min(max, v)) * 10) / 10; setDisplayValue(String(clamped)); onChange(clamped); }; const currentNumericValue = parseFloat(displayValue) || 0; const increment = () => commitValue(currentNumericValue + numberStep); const decrement = () => commitValue(currentNumericValue - numberStep); const handleOnBlur = () => commitValue(currentNumericValue); const handleSubmit = (e: React.FormEvent) => { e.preventDefault(); commitValue(currentNumericValue); (document.activeElement as HTMLElement)?.blur(); }; return (
{label} {iconSize && }
e.target.select()} />
); }; export default NumberInput;