import type { CardProps } from '@mui/material' import type { ChangeEvent, JSX } from 'react' import { useLayoutEffect, useRef, useState } from 'react' import { useTranslation } from 'react-i18next' import { useLinkedLimitFields } from '../../hooks/useLinkedLimitFields.js' import { useToken } from '../../hooks/useToken.js' import { useWidgetConfig } from '../../providers/WidgetProvider/WidgetProvider.js' import { FormKeyHelper } from '../../stores/form/types.js' import { useFieldActions } from '../../stores/form/useFieldActions.js' import { useFieldValues } from '../../stores/form/useFieldValues.js' import { useInputModeStore } from '../../stores/inputMode/useInputModeStore.js' import { formatInputAmount, formatTokenPrice, priceToTokenAmount, usdDecimals, } from '../../utils/format.js' import { fitInputText } from '../../utils/input.js' import { CardTitle } from '../Card/CardTitle.js' import { TokenPillButton } from '../TokenPillButton/TokenPillButton.js' import { AmountCard, CardBodyRow, CardFooterRow, CardHeaderRow, LargeInput, maxInputFontSize, minInputFontSize, } from './AmountInputCard.style.js' import { BalanceDisplay } from './BalanceDisplay.js' import { FiatValueToggle } from './FiatValueToggle.js' import { PercentageChips } from './PercentageChips.js' export const SendAmountCard: React.FC = ( props ): JSX.Element => { const { t } = useTranslation() const { disabledUI, mode, modeOptions } = useWidgetConfig() const ref = useRef(null) const isEditingRef = useRef(false) const [formattedPriceInput, setFormattedPriceInput] = useState('') const formType = 'from' as const const [chainId, tokenAddress, value] = useFieldValues( FormKeyHelper.getChainKey(formType), FormKeyHelper.getTokenKey(formType), FormKeyHelper.getAmountKey(formType) ) const { token } = useToken(chainId, tokenAddress) const { setFieldValue } = useFieldActions() const { inputMode } = useInputModeStore() const { setSendAmount } = useLinkedLimitFields() const currentInputMode = inputMode[formType] const disabled = disabledUI?.fromAmount // In limit mode the send amount drives the linked receive amount; otherwise // it is a plain form-field write. const applyFromAmount = (value: string): void => { if (mode === 'limit') { setSendAmount(value) } else { setFieldValue('fromAmount', value, { isDirty: true, isTouched: true }) } } const title = mode === 'limit' ? t('header.sell') : mode === 'custom' && modeOptions?.custom?.type === 'deposit' ? t('header.deposit') : t('header.send') let displayValue: string if (isEditingRef.current) { if (currentInputMode === 'price') { displayValue = formattedPriceInput } else { displayValue = value as string } } else { if (currentInputMode === 'price') { const priceValue = formatTokenPrice(value as string, token?.priceUSD) displayValue = formatInputAmount( priceValue.toFixed(usdDecimals), usdDecimals ) } else { displayValue = value as string } } const handleChange = ( event: ChangeEvent ): void => { const { value: inputValue } = event.target isEditingRef.current = true if (currentInputMode === 'price') { const cleanInputValue = inputValue.replace('$', '') const formattedValue = formatInputAmount( cleanInputValue, usdDecimals, true ) const tokenValue = priceToTokenAmount(formattedValue, token?.priceUSD) setFormattedPriceInput(formattedValue) applyFromAmount(tokenValue) } else { const formattedValue = formatInputAmount( inputValue, token?.decimals, true ) applyFromAmount(formattedValue) } } const handleBlur = ( event: ChangeEvent ): void => { const { value: inputValue } = event.target isEditingRef.current = false if (currentInputMode === 'price') { const cleanInputValue = inputValue.replace('$', '') const formattedValue = formatInputAmount(cleanInputValue, usdDecimals) const tokenValue = priceToTokenAmount(formattedValue, token?.priceUSD) const formattedAmount = formatInputAmount(tokenValue, token?.decimals) applyFromAmount(formattedAmount) } else { const formattedValue = formatInputAmount(inputValue, token?.decimals) applyFromAmount(formattedValue) } } // biome-ignore lint/correctness/useExhaustiveDependencies: effect must run on value change useLayoutEffect(() => { if (ref.current) { fitInputText(maxInputFontSize, minInputFontSize, ref.current) } }, [displayValue]) return ( {title} ) }