'use client'; import * as React from 'react'; import { NumericFormat, type NumericFormatProps } from 'react-number-format'; import { Input } from '@/components/ui/input'; import { cn } from '@/lib/utils'; import { currencySymbol } from '@/lib/utils/currency'; interface CurrencyInputProps extends Omit< NumericFormatProps, 'value' | 'onChange' | 'customInput' > { /** Controlled raw numeric value. `null` / `undefined` render empty. */ value: number | string | null | undefined; /** Fires with a raw number (or `null` if cleared). */ onChange: (value: number | null) => void; /** ISO currency code; renders as a leading symbol prefix. */ currency?: string; className?: string; } /** * Numeric input pre-decorated with a currency symbol and thousand-separator * grouping (e.g. `3,528,000.50`). Built on react-number-format which handles * the inputMode/IME edge cases, decimal/group localisation, paste sanitization, * and selection caret preservation that hand-rolled parsers miss. * * Renders inside the shared `` shell via `customInput` so border / * focus-ring / dark-mode styles stay consistent with the rest of the kit. */ export const CurrencyInput = React.forwardRef( ({ value, onChange, currency = 'USD', className, ...props }, ref) => { const symbol = currencySymbol(currency); // react-number-format wants undefined (not null) to render empty. const formatValue = value === null || value === undefined || value === '' ? undefined : Number(value); return (
{symbol} { // floatValue is undefined when input is empty. onChange(values.floatValue ?? null); }} className={cn('pl-9 tabular-nums', className)} {...props} />
); }, ); CurrencyInput.displayName = 'CurrencyInput';