/** * MUI Amount Input Component * * Reusable amount input component with currency symbol support * Can be used in AmountField or standalone * * Two modes, dispatched on the `format` prop to two independent internal * implementations (each with a single value contract): * - Native (format omitted): native number input, v0.11.0 contract - onChange * emits parsed numbers, min/max/step are float bounds. * - Formatted (format set): text input with inputMode="decimal", live * thousands-separator grouping, and a decimal-string value contract: * onChange emits the raw string with separators stripped, and min/max clamp * via exact decimal string comparison. * * Precision: formatted-mode USER INPUT and STRING-valued props (value/min/ * max) are never converted through JavaScript numbers. Externally supplied * number values retain normal JS float precision limits - pass strings for * high-precision values. * * `format` is immutable configuration. Changing between native and formatted * mode swaps the internal implementation and remounts the input, rebuilding * the display from the committed value (the parent must supply a value * compatible with the new mode's contract). Changing between formatted * variants ('standard' <-> 'compact') is unsupported while the input is * mounted - it does NOT remount (both variants currently edit identically). * * Formatted-mode controlled contract: the parent must commit emitted values * synchronously and round-trip them as the SAME string (react-final-form and * the DSL runtime do). Echo detection is exact - a parent that normalizes the * value (e.g. converts it to a number) immediately canonicalizes the display, * which makes any precision loss visible instead of silent. */ import type { AmountFormat, CurrencyDisplay } from '@galaxy-dev/metadsl-core'; interface AmountInputBaseProps { name?: string; /** id of the underlying input element (e.g. to link a label via htmlFor) */ id?: string; /** id(s) of the element(s) describing this input (e.g. helper text) */ 'aria-describedby'?: string; onBlur?: (e: React.FocusEvent) => void; onFocus?: (e: React.FocusEvent) => void; currency?: string; currencyDisplay?: CurrencyDisplay; placeholder?: string; size?: 'small' | 'medium'; disabled?: boolean; readOnly?: boolean; className?: string; style?: React.CSSProperties; suffix?: React.ReactNode; /** Show a clear (×) button when the input has a value (default: false) */ clearable?: boolean; /** Custom clear button icon (already rendered as ReactNode) */ clearIcon?: React.ReactNode; /** * Custom renderer for currency symbol * @param currency - Currency code (e.g., 'USD', 'EUR') * @returns ReactNode to display as currency symbol * @default Uses getCurrencySymbol utility based on currencyDisplay */ renderCurrency?: (currency: string) => React.ReactNode; } /** Native number mode (legacy v0.11.0 contract) */ export interface NativeAmountInputProps extends AmountInputBaseProps { format?: undefined; value?: number | string; /** Emits parsed numbers while typing, '' when empty - never other strings */ onChange?: (value: number | '') => void; /** Float bounds, re-applied on blur */ min?: number; max?: number; /** Step for the native spinner only (not validated) */ step?: number; } /** Formatted (grouped) mode with a decimal-string value contract */ export interface FormattedAmountInputProps extends AmountInputBaseProps { /** * Enables the formatted display mode. While editing, 'standard' and * 'compact' behave identically (grouped digits) - compact notation * (e.g. 12.5K) is not editable and is reserved for future read-only use. * Treat `format` as immutable configuration: switching to/from native mode * remounts the input and rebuilds the display from the committed value; * switching between formatted variants while mounted is unsupported. */ format: AmountFormat; /** * Committed value. Strings are used verbatim (precision-safe); numbers * (e.g. quick-amount pushes) are converted to their plain decimal * representation and carry normal JS float precision limits. */ value?: number | string; /** * Emits the raw decimal STRING with separators stripped ('8000.51', '-5', * in-progress '8000.'); inputs without any digit emit ''. Values are passed * through verbatim (no float parsing). The parent must commit synchronously * and round-trip the same string. */ onChange?: (value: string) => void; /** * Bounds, re-applied on blur via EXACT decimal string comparison. Pass * strings for bounds beyond float precision (e.g. '9007199254740993'). */ min?: number | string; max?: number | string; /** * Max fractional digits accepted while TYPING (an input restriction - * excess digits are dropped, never rounded). Committed external values are * displayed as-is. */ decimals?: number; /** Not supported in formatted mode - use validation rules instead */ step?: undefined; } export type AmountInputProps = NativeAmountInputProps | FormattedAmountInputProps; export declare function AmountInput(props: AmountInputProps): import("react/jsx-runtime").JSX.Element; export {}; //# sourceMappingURL=AmountInput.d.ts.map