@lifi/widget
Version:
LI.FI Widget for cross-chain bridging and swapping. It will drive your multi-chain strategy and attract new users from everywhere.
115 lines • 6.15 kB
JavaScript
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
import { useLayoutEffect, useRef, useState } from 'react';
import { useTranslation } from 'react-i18next';
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 { DisabledUI } from '../../types/widget.js';
import { formatInputAmount, formatTokenPrice, priceToTokenAmount, } from '../../utils/format.js';
import { fitInputText } from '../../utils/input.js';
import { InputCard } from '../Card/InputCard.js';
import { AmountInputCardHeader, AmountInputCardTitle, FormContainer, FormControl, Input, maxInputFontSize, minInputFontSize, } from './AmountInput.style.js';
import { AmountInputEndAdornment } from './AmountInputEndAdornment.js';
import { AmountInputStartAdornment } from './AmountInputStartAdornment.js';
import { PriceFormHelperText } from './PriceFormHelperText.js';
const USD_DECIMALS = 2;
export const AmountInput = ({ formType, ...props }) => {
const { disabledUI } = useWidgetConfig();
const [chainId, tokenAddress] = useFieldValues(FormKeyHelper.getChainKey(formType), FormKeyHelper.getTokenKey(formType));
const { token } = useToken(chainId, tokenAddress);
const disabled = disabledUI?.includes(DisabledUI.FromAmount);
return (_jsx(AmountInputBase, { formType: formType, token: token, endAdornment: !disabled ? _jsx(AmountInputEndAdornment, { formType: formType }) : undefined, bottomAdornment: _jsx(PriceFormHelperText, { formType: formType }), disabled: disabled, ...props }));
};
export const AmountInputBase = ({ formType, token, startAdornment, endAdornment, bottomAdornment, disabled, ...props }) => {
const { t } = useTranslation();
const { subvariant, subvariantOptions } = useWidgetConfig();
const ref = useRef(null);
const isEditingRef = useRef(false);
const [formattedPriceInput, setFormattedPriceInput] = useState('');
const amountKey = FormKeyHelper.getAmountKey(formType);
const [value] = useFieldValues(amountKey);
const { setFieldValue } = useFieldActions();
const { inputMode } = useInputModeStore();
const currentInputMode = inputMode[formType];
let displayValue;
if (isEditingRef.current) {
if (currentInputMode === 'price') {
displayValue = formattedPriceInput;
}
else {
displayValue = value;
}
}
else {
if (currentInputMode === 'price') {
const priceValue = formatTokenPrice(value, token?.priceUSD);
displayValue = formatInputAmount(priceValue.toFixed(USD_DECIMALS), USD_DECIMALS);
}
else {
displayValue = value;
}
}
const handleChange = (event) => {
const { value: inputValue } = event.target;
isEditingRef.current = true;
let formattedValue;
if (currentInputMode === 'price') {
const cleanInputValue = inputValue.replace('$', '');
formattedValue = formatInputAmount(cleanInputValue, USD_DECIMALS, true);
const tokenValue = priceToTokenAmount(formattedValue, token?.priceUSD);
setFormattedPriceInput(formattedValue);
setFieldValue(amountKey, tokenValue, { isDirty: true, isTouched: true });
}
else {
formattedValue = formatInputAmount(inputValue, token?.decimals, true);
setFieldValue(amountKey, formattedValue, {
isDirty: true,
isTouched: true,
});
}
};
const handleBlur = (event) => {
const { value: inputValue } = event.target;
isEditingRef.current = false;
let formattedValue;
if (currentInputMode === 'price') {
const cleanInputValue = inputValue.replace('$', '');
formattedValue = formatInputAmount(cleanInputValue, USD_DECIMALS);
const tokenValue = priceToTokenAmount(formattedValue, token?.priceUSD);
const formattedAmount = formatInputAmount(tokenValue, token?.decimals);
setFieldValue(amountKey, formattedAmount, {
isDirty: true,
isTouched: true,
});
}
else {
formattedValue = formatInputAmount(inputValue, token?.decimals);
setFieldValue(amountKey, formattedValue, {
isDirty: true,
isTouched: true,
});
}
};
// biome-ignore lint/correctness/useExhaustiveDependencies: we need run effect on value change
useLayoutEffect(() => {
if (ref.current) {
fitInputText(maxInputFontSize, minInputFontSize, ref.current);
}
}, [displayValue]);
const title = subvariant === 'custom'
? subvariantOptions?.custom === 'deposit'
? t('header.amount')
: t('header.youPay')
: t('header.send');
return (_jsxs(InputCard, { ...props, children: [_jsxs(AmountInputCardHeader, { children: [_jsx(AmountInputCardTitle, { children: title }), endAdornment] }), _jsxs(FormContainer, { children: [_jsx(AmountInputStartAdornment, { formType: formType }), _jsxs(FormControl, { fullWidth: true, children: [_jsx(Input, { inputRef: ref, size: "small", autoComplete: "off", placeholder: currentInputMode === 'price' ? '$0' : '0', startAdornment: startAdornment, inputProps: {
inputMode: 'decimal',
}, onChange: handleChange, onBlur: handleBlur, value: currentInputMode === 'price'
? displayValue
? `$${displayValue}`
: ''
: displayValue, name: amountKey, disabled: disabled, required: true }), bottomAdornment] })] })] }));
};
//# sourceMappingURL=AmountInput.js.map