import { ChevronDown, ChevronUp } from 'lucide-react' import { forwardRef, useCallback, useEffect, useState } from 'react' import { NumericFormat, NumericFormatProps } from 'react-number-format' import Button from '@/components/ui/Button' import Input from '@/components/ui/Input' import { cn } from '@/lib/utils' export interface NumberInputProps extends Omit { stepper?: number thousandSeparator?: string placeholder?: string defaultValue?: number min?: number max?: number value?: number // Controlled value suffix?: string prefix?: string onValueChange?: (value: number | undefined) => void fixedDecimalScale?: boolean decimalScale?: number } const NumberInput = forwardRef( ( { stepper, thousandSeparator, placeholder, defaultValue, min = -Infinity, max = Infinity, onValueChange, fixedDecimalScale = false, decimalScale = 0, className = undefined, suffix, prefix, value: controlledValue, ...props }, ref ) => { const [value, setValue] = useState(controlledValue ?? defaultValue) const handleIncrement = useCallback(() => { setValue((prev) => prev === undefined ? (stepper ?? 1) : Math.min(prev + (stepper ?? 1), max) ) }, [stepper, max]) const handleDecrement = useCallback(() => { setValue((prev) => prev === undefined ? -(stepper ?? 1) : Math.max(prev - (stepper ?? 1), min) ) }, [stepper, min]) useEffect(() => { if (controlledValue !== undefined) { setValue(controlledValue) } }, [controlledValue]) const handleChange = (values: { value: string; floatValue: number | undefined }) => { const newValue = values.floatValue === undefined ? undefined : values.floatValue setValue(newValue) if (onValueChange) { onValueChange(newValue) } } const handleBlur = () => { if (value !== undefined) { if (value < min) { setValue(min) ;(ref as React.RefObject).current!.value = String(min) } else if (value > max) { setValue(max) ;(ref as React.RefObject).current!.value = String(max) } } } return (
} placeholder={placeholder} className="[appearance:textfield] [&::-webkit-inner-spin-button]:appearance-none [&::-webkit-outer-spin-button]:appearance-none" getInputRef={ref} {...props} />
) } ) NumberInput.displayName = 'NumberInput' export default NumberInput