From 2bf9e66da55096ea8dacb45f294f948fc8797c6c Mon Sep 17 00:00:00 2001 From: Jared Vu Date: Tue, 5 Dec 2023 16:22:41 -0800 Subject: [PATCH] Fix inputs for comma locales (#171) * Fix for comma decimal separator locales * Accept tickSizeDecimals 0 * Use FloatValue as value for Size Input * Use formattedValue to handle prefix/suffix * Use MustBigNumber.toString() --- src/components/Input.tsx | 48 +++++++++++-------- src/hooks/useTradeFormInputs.ts | 9 ++-- src/views/forms/TradeForm.tsx | 4 +- src/views/forms/TradeForm/TradeSizeInputs.tsx | 28 +++++++---- 4 files changed, 53 insertions(+), 36 deletions(-) diff --git a/src/components/Input.tsx b/src/components/Input.tsx index b74e4f8..a1bcc88 100644 --- a/src/components/Input.tsx +++ b/src/components/Input.tsx @@ -10,7 +10,7 @@ import { USD_DECIMALS, } from '@/constants/numbers'; -import { BIG_NUMBERS, MustBigNumber } from '@/lib/numbers'; +import { BIG_NUMBERS } from '@/lib/numbers'; import { useLocaleSeparators } from '@/hooks'; export enum InputType { @@ -29,31 +29,38 @@ type StyleProps = { type ElementProps = { type?: InputType; value?: string | number | null; - - allowNegative?: boolean; - decimals?: number; disabled?: boolean; id?: string; - max?: number; onBlur?: () => void; - onChange?: - | Dispatch> - | React.ReactEventHandler - | ((values: NumberFormatValues, e: SourceInfo) => void); onFocus?: () => void; - onInput?: ({ - value, - floatValue, - formattedValue, - }: { - value: string; - floatValue?: number; - formattedValue: string; - }) => void; placeholder?: string; }; -export type InputProps = ElementProps & StyleProps; +type ConditionalProps = + | { + allowNegative?: boolean; + decimals?: number; + max?: number; + onChange?: (values: NumberFormatValues, e: SourceInfo) => void; + onInput?: ({ + value, + floatValue, + formattedValue, + }: { + value: string; + floatValue?: number; + formattedValue: string; + }) => void; + } + | { + allowNegative?: never; + decimals?: never; + max?: never; + onChange?: Dispatch> | React.ReactEventHandler; + onInput?: (e: SyntheticInputEvent) => void; + }; + +export type InputProps = ElementProps & StyleProps & ConditionalProps; export const Input = forwardRef( ( @@ -138,6 +145,7 @@ export const Input = forwardRef( ref={ref as React.Ref>} id={id} // NumericFormat + valueIsNumericString allowNegative={allowNegative} decimalScale={decimals} decimalSeparator={LOCALE_DECIMAL_SEPARATOR} @@ -161,7 +169,7 @@ export const Input = forwardRef( ? undefined : Number(formattedValue.replace(',', '.')); - onInput?.({ value, floatValue, formattedValue }); + onInput?.({ value, floatValue, formattedValue, ...e }); }} // Native disabled={disabled} diff --git a/src/hooks/useTradeFormInputs.ts b/src/hooks/useTradeFormInputs.ts index 39ff5b5..fa36827 100644 --- a/src/hooks/useTradeFormInputs.ts +++ b/src/hooks/useTradeFormInputs.ts @@ -11,22 +11,19 @@ export const useTradeFormInputs = () => { const { limitPriceInput, triggerPriceInput, trailingPercentInput } = tradeFormInputValues; useEffect(() => { - const floatValue = parseFloat(triggerPriceInput); abacusStateManager.setTradeValue({ - value: floatValue, + value: triggerPriceInput, field: TradeInputField.triggerPrice, }); }, [triggerPriceInput]); useEffect(() => { - const floatValue = parseFloat(limitPriceInput); - abacusStateManager.setTradeValue({ value: floatValue, field: TradeInputField.limitPrice }); + abacusStateManager.setTradeValue({ value: limitPriceInput, field: TradeInputField.limitPrice }); }, [limitPriceInput]); useEffect(() => { - const floatValue = parseFloat(trailingPercentInput); abacusStateManager.setTradeValue({ - value: floatValue, + value: trailingPercentInput, field: TradeInputField.trailingPercent, }); }, [trailingPercentInput]); diff --git a/src/views/forms/TradeForm.tsx b/src/views/forms/TradeForm.tsx index 68a96b3..78f5759 100644 --- a/src/views/forms/TradeForm.tsx +++ b/src/views/forms/TradeForm.tsx @@ -206,7 +206,7 @@ export const TradeForm = ({ dispatch(setTradeFormInputs({ triggerPriceInput: value })); }, value: triggerPriceInput ?? '', - decimals: tickSizeDecimals || USD_DECIMALS, + decimals: tickSizeDecimals ?? USD_DECIMALS, }); } @@ -226,7 +226,7 @@ export const TradeForm = ({ dispatch(setTradeFormInputs({ limitPriceInput: value })); }, value: limitPriceInput, - decimals: tickSizeDecimals || USD_DECIMALS, + decimals: tickSizeDecimals ?? USD_DECIMALS, }); } diff --git a/src/views/forms/TradeForm/TradeSizeInputs.tsx b/src/views/forms/TradeForm/TradeSizeInputs.tsx index 51120df..fa6c8ca 100644 --- a/src/views/forms/TradeForm/TradeSizeInputs.tsx +++ b/src/views/forms/TradeForm/TradeSizeInputs.tsx @@ -49,7 +49,7 @@ export const TradeSizeInputs = () => { useSelector(getCurrentMarketConfig, shallowEqual) || {}; const { size, usdcSize, leverage, input: lastEditedInput } = inputTradeSizeData || {}; const { needsLeverage } = currentTradeInputOptions || {}; - const decimals = stepSizeDecimals || TOKEN_DECIMALS; + const decimals = stepSizeDecimals ?? TOKEN_DECIMALS; const { amountInput, usdAmountInput, leverageInput } = useSelector( getTradeFormInputs, @@ -70,22 +70,34 @@ export const TradeSizeInputs = () => { } }, [size, usdcSize, leverage, lastEditedInput]); - const onSizeInput = ({ value, floatValue }: { value: string; floatValue?: number }) => { - dispatch(setTradeFormInputs({ amountInput: value })); + const onSizeInput = ({ + floatValue, + formattedValue, + }: { + floatValue?: number; + formattedValue: string; + }) => { + dispatch(setTradeFormInputs({ amountInput: MustBigNumber(floatValue).toString() })); const newAmount = MustBigNumber(floatValue).toFixed(decimals); abacusStateManager.setTradeValue({ - value: value === '' || newAmount === 'NaN' ? null : newAmount, + value: formattedValue === '' || newAmount === 'NaN' ? null : newAmount, field: TradeInputField.size, }); }; - const onUSDCInput = ({ value, floatValue }: { value: string; floatValue?: number }) => { - dispatch(setTradeFormInputs({ usdAmountInput: value })); - const newUsdcAmount = MustBigNumber(floatValue).toFixed(); + const onUSDCInput = ({ + floatValue, + formattedValue, + }: { + floatValue?: number; + formattedValue: string; + }) => { + dispatch(setTradeFormInputs({ usdAmountInput: MustBigNumber(floatValue).toString() })); + const newUsdcAmount = MustBigNumber(floatValue).toFixed(tickSizeDecimals || USD_DECIMALS); abacusStateManager.setTradeValue({ - value: value === '' || newUsdcAmount === 'NaN' ? null : newUsdcAmount, + value: formattedValue === '' || newUsdcAmount === 'NaN' ? null : newUsdcAmount, field: TradeInputField.usdcSize, }); };