@lifi/widget 4.4.0 → 4.6.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/esm/App.js.map +1 -1
- package/dist/esm/AppDrawer.js +2 -1
- package/dist/esm/AppDrawer.js.map +1 -1
- package/dist/esm/AppLayout.js.map +1 -1
- package/dist/esm/AppProvider.js.map +1 -1
- package/dist/esm/components/ActionRow/ActionRow.js.map +1 -1
- package/dist/esm/components/AmountInput/AmountInput.js +13 -7
- package/dist/esm/components/AmountInput/AmountInput.js.map +1 -1
- package/dist/esm/components/AmountInput/AmountInputEndAdornment.js +2 -13
- package/dist/esm/components/AmountInput/AmountInputEndAdornment.js.map +1 -1
- package/dist/esm/components/AmountInput/PriceFormHelperText.js.map +1 -1
- package/dist/esm/components/AmountInputCard/AmountInputCardPair.js.map +1 -1
- package/dist/esm/components/AmountInputCard/BalanceDisplay.js.map +1 -1
- package/dist/esm/components/AmountInputCard/FiatValueToggle.js.map +1 -1
- package/dist/esm/components/AmountInputCard/PercentageChips.js +2 -13
- package/dist/esm/components/AmountInputCard/PercentageChips.js.map +1 -1
- package/dist/esm/components/AmountInputCard/PercentageChips.style.js +1 -1
- package/dist/esm/components/AmountInputCard/PercentageChips.style.js.map +1 -1
- package/dist/esm/components/AmountInputCard/ReceiveAmountCard.js.map +1 -1
- package/dist/esm/components/AmountInputCard/SendAmountCard.js +13 -6
- package/dist/esm/components/AmountInputCard/SendAmountCard.js.map +1 -1
- package/dist/esm/components/AppContainer.js.map +1 -1
- package/dist/esm/components/Avatar/AccountAvatar.js.map +1 -1
- package/dist/esm/components/Avatar/Avatar.js.map +1 -1
- package/dist/esm/components/Avatar/ChainBadgeContent.js.map +1 -1
- package/dist/esm/components/Avatar/TokenAvatar.js.map +1 -1
- package/dist/esm/components/BaseTransactionButton/BaseTransactionButton.js.map +1 -1
- package/dist/esm/components/Card/CardButton.js.map +1 -1
- package/dist/esm/components/ChainSelect/ChainSelect.js.map +1 -1
- package/dist/esm/components/Chains/AllChainsAvatar.js +7 -1
- package/dist/esm/components/Chains/AllChainsAvatar.js.map +1 -1
- package/dist/esm/components/Chains/ChainList.js.map +1 -1
- package/dist/esm/components/Chains/ChainListItem.js.map +1 -1
- package/dist/esm/components/Chains/ChainsExpanded.js.map +1 -1
- package/dist/esm/components/Chains/PinChainButton.js.map +1 -1
- package/dist/esm/components/Chains/SelectChainExpansionContent.js.map +1 -1
- package/dist/esm/components/Chains/SelectChainPageContent.js.map +1 -1
- package/dist/esm/components/Chains/VirtualizedChainList.js.map +1 -1
- package/dist/esm/components/ContextMenu.js.map +1 -1
- package/dist/esm/components/ContractComponent/NFT/NFTBase.js.map +1 -1
- package/dist/esm/components/Dialog/Dialog.js +2 -1
- package/dist/esm/components/Dialog/Dialog.js.map +1 -1
- package/dist/esm/components/ExecutionStatusCard/ExecutionChecklist.js.map +1 -1
- package/dist/esm/components/ExecutionStatusCard/ExecutionStatusCard.js.map +1 -1
- package/dist/esm/components/ExecutionStatusCard/StaggeredRevealTypography.js.map +1 -1
- package/dist/esm/components/ExecutionStatusCard/StatusIcon.js.map +1 -1
- package/dist/esm/components/Expansion/Expansion.js +4 -3
- package/dist/esm/components/Expansion/Expansion.js.map +1 -1
- package/dist/esm/components/Expansion/ExpansionTransition.js.map +1 -1
- package/dist/esm/components/FeeBreakdownTooltip.js.map +1 -1
- package/dist/esm/components/Header/ActivitiesButton.js.map +1 -1
- package/dist/esm/components/Header/BackButton.js.map +1 -1
- package/dist/esm/components/Header/CloseDrawerButton.js.map +1 -1
- package/dist/esm/components/Header/DisconnectIconButton.js.map +1 -1
- package/dist/esm/components/Header/HeaderTabs.js.map +1 -1
- package/dist/esm/components/Header/NavigationHeader.js.map +1 -1
- package/dist/esm/components/Header/SettingsButton.js +2 -1
- package/dist/esm/components/Header/SettingsButton.js.map +1 -1
- package/dist/esm/components/Header/WalletHeader.js.map +1 -1
- package/dist/esm/components/Header/WalletMenu.js.map +1 -1
- package/dist/esm/components/IconCircle/IconCircle.js +2 -1
- package/dist/esm/components/IconCircle/IconCircle.js.map +1 -1
- package/dist/esm/components/LimitOrderSettings/LimitOrderSettings.js.map +1 -1
- package/dist/esm/components/LimitPriceCard/LimitPriceCard.js.map +1 -1
- package/dist/esm/components/LimitPriceCard/LimitPricePresets.js.map +1 -1
- package/dist/esm/components/Messages/AccountDeployedMessage.js.map +1 -1
- package/dist/esm/components/Messages/AccountNotDeployedMessage.js.map +1 -1
- package/dist/esm/components/Messages/AlertMessage.js.map +1 -1
- package/dist/esm/components/Messages/FundsSufficiencyMessage.js.map +1 -1
- package/dist/esm/components/Messages/GasRefuelMessage.js.map +1 -1
- package/dist/esm/components/Messages/GasSufficiencyMessage.js.map +1 -1
- package/dist/esm/components/Messages/MinFromAmountUSDMessage.js.map +1 -1
- package/dist/esm/components/Messages/MissingRouteRequiredAccountMessage.js.map +1 -1
- package/dist/esm/components/Messages/UnsupportedToAddressMessage.js +27 -0
- package/dist/esm/components/Messages/UnsupportedToAddressMessage.js.map +1 -0
- package/dist/esm/components/Messages/WarningMessages.d.ts.map +1 -1
- package/dist/esm/components/Messages/WarningMessages.js +2 -0
- package/dist/esm/components/Messages/WarningMessages.js.map +1 -1
- package/dist/esm/components/Messages/useMessageQueue.js +6 -1
- package/dist/esm/components/Messages/useMessageQueue.js.map +1 -1
- package/dist/esm/components/NotFound.js.map +1 -1
- package/dist/esm/components/PoweredBy/PoweredBy.js.map +1 -1
- package/dist/esm/components/ProgressToNextUpdate.js.map +1 -1
- package/dist/esm/components/ReverseTokensButton/ReverseTokensButton.js.map +1 -1
- package/dist/esm/components/RouteCard/RouteCard.js.map +1 -1
- package/dist/esm/components/RouteCard/RouteCardEssentials.js.map +1 -1
- package/dist/esm/components/RouteCard/RouteCardSkeleton.js.map +1 -1
- package/dist/esm/components/RouteCard/RouteDetails.js +2 -1
- package/dist/esm/components/RouteCard/RouteDetails.js.map +1 -1
- package/dist/esm/components/RouteCard/RouteNotFoundCard.js.map +1 -1
- package/dist/esm/components/RouteCard/RouteProviderCard.js.map +1 -1
- package/dist/esm/components/RouteCard/RouteToken.js.map +1 -1
- package/dist/esm/components/RouteCard/RouteTokens.js.map +1 -1
- package/dist/esm/components/Routes/LimitOrderRoutes.js +2 -2
- package/dist/esm/components/Routes/LimitOrderRoutes.js.map +1 -1
- package/dist/esm/components/Routes/Routes.js.map +1 -1
- package/dist/esm/components/Routes/RoutesContent.js +2 -2
- package/dist/esm/components/Routes/RoutesContent.js.map +1 -1
- package/dist/esm/components/Routes/RoutesExpanded.js.map +1 -1
- package/dist/esm/components/Search/SearchInput.js.map +1 -1
- package/dist/esm/components/SelectChainAndToken.js.map +1 -1
- package/dist/esm/components/SelectTokenButton/SelectTokenButton.js.map +1 -1
- package/dist/esm/components/SendToWallet/SendToWalletButton.js.map +1 -1
- package/dist/esm/components/SendToWallet/SendToWalletExpandButton.js +2 -2
- package/dist/esm/components/SendToWallet/SendToWalletExpandButton.js.map +1 -1
- package/dist/esm/components/SettingsPanel/SettingsPanel.js.map +1 -1
- package/dist/esm/components/Skeleton/WidgetSkeleton.js +2 -1
- package/dist/esm/components/Skeleton/WidgetSkeleton.js.map +1 -1
- package/dist/esm/components/Step/StepActions.js +18 -16
- package/dist/esm/components/Step/StepActions.js.map +1 -1
- package/dist/esm/components/StepActions/SentToWalletRow.js.map +1 -1
- package/dist/esm/components/StepActions/StepActionRow.js +2 -1
- package/dist/esm/components/StepActions/StepActionRow.js.map +1 -1
- package/dist/esm/components/StepActions/StepActionsList.js.map +1 -1
- package/dist/esm/components/SwapButton/SwapButton.js.map +1 -1
- package/dist/esm/components/Switch.js +1 -1
- package/dist/esm/components/Switch.js.map +1 -1
- package/dist/esm/components/Tabs/Tabs.style.js +4 -2
- package/dist/esm/components/Tabs/Tabs.style.js.map +1 -1
- package/dist/esm/components/TextFitter/TextFitter.js.map +1 -1
- package/dist/esm/components/Timer/StepStatusTimer.js.map +1 -1
- package/dist/esm/components/Token/Token.js.map +1 -1
- package/dist/esm/components/TokenList/PinTokenButton.js.map +1 -1
- package/dist/esm/components/TokenList/TokenDetailsSheet.js.map +1 -1
- package/dist/esm/components/TokenList/TokenDetailsSheetContent.js.map +1 -1
- package/dist/esm/components/TokenList/TokenList.js.map +1 -1
- package/dist/esm/components/TokenList/TokenListItem.js +46 -8
- package/dist/esm/components/TokenList/TokenListItem.js.map +1 -1
- package/dist/esm/components/TokenList/VirtualizedTokenList.js +22 -9
- package/dist/esm/components/TokenList/VirtualizedTokenList.js.map +1 -1
- package/dist/esm/components/TokenPillButton/TokenPillButton.js.map +1 -1
- package/dist/esm/components/TokenRate/TokenRate.js +2 -1
- package/dist/esm/components/TokenRate/TokenRate.js.map +1 -1
- package/dist/esm/components/Tools/ToolItem.js.map +1 -1
- package/dist/esm/components/Tools/Tools.js.map +1 -1
- package/dist/esm/components/TransactionCard/ActiveTransactionCard.js +22 -21
- package/dist/esm/components/TransactionCard/ActiveTransactionCard.js.map +1 -1
- package/dist/esm/components/TransactionCard/TransactionCard.js.map +1 -1
- package/dist/esm/components/TransactionCard/TransactionCardSkeleton.js.map +1 -1
- package/dist/esm/config/version.d.ts +1 -1
- package/dist/esm/config/version.js +1 -1
- package/dist/esm/config/version.js.map +1 -1
- package/dist/esm/hooks/timer/time.js +2 -2
- package/dist/esm/hooks/timer/time.js.map +1 -1
- package/dist/esm/hooks/useAccountsBalancesData.js +1 -14
- package/dist/esm/hooks/useAccountsBalancesData.js.map +1 -1
- package/dist/esm/hooks/useAvailableChains.d.ts.map +1 -1
- package/dist/esm/hooks/useAvailableChains.js +2 -1
- package/dist/esm/hooks/useAvailableChains.js.map +1 -1
- package/dist/esm/hooks/useExplorer.d.ts.map +1 -1
- package/dist/esm/hooks/useExplorer.js +4 -0
- package/dist/esm/hooks/useExplorer.js.map +1 -1
- package/dist/esm/hooks/useFlaggedTokenGuard.js +28 -0
- package/dist/esm/hooks/useFlaggedTokenGuard.js.map +1 -0
- package/dist/esm/hooks/useGasSufficiency.js +3 -1
- package/dist/esm/hooks/useGasSufficiency.js.map +1 -1
- package/dist/esm/hooks/useMaxSendAmount.js +15 -0
- package/dist/esm/hooks/useMaxSendAmount.js.map +1 -0
- package/dist/esm/hooks/usePacedRouteExecution.js +3 -2
- package/dist/esm/hooks/usePacedRouteExecution.js.map +1 -1
- package/dist/esm/hooks/useRouteExecutionMessage.js +3 -2
- package/dist/esm/hooks/useRouteExecutionMessage.js.map +1 -1
- package/dist/esm/hooks/useRoutes.d.ts.map +1 -1
- package/dist/esm/hooks/useRoutes.js +3 -1
- package/dist/esm/hooks/useRoutes.js.map +1 -1
- package/dist/esm/hooks/useToAddressAutoPopulate.js.map +1 -1
- package/dist/esm/hooks/useToAddressRequirements.d.ts +2 -0
- package/dist/esm/hooks/useToAddressRequirements.d.ts.map +1 -1
- package/dist/esm/hooks/useToAddressRequirements.js +7 -1
- package/dist/esm/hooks/useToAddressRequirements.js.map +1 -1
- package/dist/esm/hooks/useTokenBalances.d.ts.map +1 -1
- package/dist/esm/hooks/useTokenBalances.js +7 -2
- package/dist/esm/hooks/useTokenBalances.js.map +1 -1
- package/dist/esm/hooks/useTokenBalancesQueries.js +32 -29
- package/dist/esm/hooks/useTokenBalancesQueries.js.map +1 -1
- package/dist/esm/hooks/useTokenSearch.js +3 -5
- package/dist/esm/hooks/useTokenSearch.js.map +1 -1
- package/dist/esm/hooks/useTokens.js +14 -10
- package/dist/esm/hooks/useTokens.js.map +1 -1
- package/dist/esm/hooks/useWideVariant.js +2 -1
- package/dist/esm/hooks/useWideVariant.js.map +1 -1
- package/dist/esm/i18n/bn.json +3 -1
- package/dist/esm/i18n/de.json +3 -1
- package/dist/esm/i18n/en.json +12 -3
- package/dist/esm/i18n/es.json +3 -1
- package/dist/esm/i18n/fr.json +3 -1
- package/dist/esm/i18n/hi.json +3 -1
- package/dist/esm/i18n/id.json +3 -1
- package/dist/esm/i18n/it.json +3 -1
- package/dist/esm/i18n/ja.json +3 -1
- package/dist/esm/i18n/ko.json +3 -1
- package/dist/esm/i18n/pl.json +3 -1
- package/dist/esm/i18n/pt.json +3 -1
- package/dist/esm/i18n/th.json +3 -1
- package/dist/esm/i18n/tr.json +3 -1
- package/dist/esm/i18n/uk.json +3 -1
- package/dist/esm/i18n/vi.json +3 -1
- package/dist/esm/i18n/zh.json +3 -1
- package/dist/esm/pages/ActivitiesPage/ActivitiesPage.js.map +1 -1
- package/dist/esm/pages/ActivitiesPage/ActivitiesPageMenuButton.js.map +1 -1
- package/dist/esm/pages/LanguagesPage.js.map +1 -1
- package/dist/esm/pages/MainPage/LimitPageContent.js.map +1 -1
- package/dist/esm/pages/MainPage/MainPage.js +2 -1
- package/dist/esm/pages/MainPage/MainPage.js.map +1 -1
- package/dist/esm/pages/MainPage/MainPageActions.js.map +1 -1
- package/dist/esm/pages/MainPage/ReviewButton.js +2 -2
- package/dist/esm/pages/MainPage/ReviewButton.js.map +1 -1
- package/dist/esm/pages/RoutePriorityPage.js.map +1 -1
- package/dist/esm/pages/RoutesPage/RoutesPage.js +2 -2
- package/dist/esm/pages/RoutesPage/RoutesPage.js.map +1 -1
- package/dist/esm/pages/SelectChainPage/SelectChainPage.js +13 -12
- package/dist/esm/pages/SelectChainPage/SelectChainPage.js.map +1 -1
- package/dist/esm/pages/SelectEnabledToolsPage.js +8 -5
- package/dist/esm/pages/SelectEnabledToolsPage.js.map +1 -1
- package/dist/esm/pages/SelectTokenPage/SelectTokenPage.js +2 -1
- package/dist/esm/pages/SelectTokenPage/SelectTokenPage.js.map +1 -1
- package/dist/esm/pages/SendToWallet/BookmarkAddressSheet.js.map +1 -1
- package/dist/esm/pages/SendToWallet/BookmarksPage.js.map +1 -1
- package/dist/esm/pages/SendToWallet/ConfirmAddressSheet.js.map +1 -1
- package/dist/esm/pages/SendToWallet/ConnectedWalletsPage.js.map +1 -1
- package/dist/esm/pages/SendToWallet/RecentWalletsPage.js.map +1 -1
- package/dist/esm/pages/SendToWallet/SendToConfiguredWalletPage.js.map +1 -1
- package/dist/esm/pages/SendToWallet/SendToWalletPage.js.map +1 -1
- package/dist/esm/pages/SettingsPage/BridgeAndExchangeSettings.js.map +1 -1
- package/dist/esm/pages/SettingsPage/GasPriceSettings.js.map +1 -1
- package/dist/esm/pages/SettingsPage/LanguageSetting.js.map +1 -1
- package/dist/esm/pages/SettingsPage/ResetSettingsButton.js.map +1 -1
- package/dist/esm/pages/SettingsPage/RoutePrioritySettings.js.map +1 -1
- package/dist/esm/pages/SettingsPage/SettingsCard/BadgedValue.js.map +1 -1
- package/dist/esm/pages/SettingsPage/SettingsCard/SettingCardExpandable.js.map +1 -1
- package/dist/esm/pages/SettingsPage/SettingsPage.js.map +1 -1
- package/dist/esm/pages/SettingsPage/SlippageSettings/SlippagePage.js.map +1 -1
- package/dist/esm/pages/SettingsPage/SlippageSettings/SlippageSettings.js.map +1 -1
- package/dist/esm/pages/SettingsPage/SmallBalanceFilterSettings.js +2 -1
- package/dist/esm/pages/SettingsPage/SmallBalanceFilterSettings.js.map +1 -1
- package/dist/esm/pages/SettingsPage/ThemeSettings.js.map +1 -1
- package/dist/esm/pages/TransactionDetailsPage/ContactSupportButton.js +2 -1
- package/dist/esm/pages/TransactionDetailsPage/ContactSupportButton.js.map +1 -1
- package/dist/esm/pages/TransactionDetailsPage/ReceiptsCard.js.map +1 -1
- package/dist/esm/pages/TransactionDetailsPage/TransactionDetailsPage.js +2 -1
- package/dist/esm/pages/TransactionDetailsPage/TransactionDetailsPage.js.map +1 -1
- package/dist/esm/pages/TransactionDetailsPage/TransactionDetailsSkeleton.js.map +1 -1
- package/dist/esm/pages/TransactionDetailsPage/TransferIdCard.js.map +1 -1
- package/dist/esm/pages/TransactionPage/ConfirmToAddressSheet.js.map +1 -1
- package/dist/esm/pages/TransactionPage/ExchangeRateBottomSheet.js.map +1 -1
- package/dist/esm/pages/TransactionPage/ExecutionDoneCard.js.map +1 -1
- package/dist/esm/pages/TransactionPage/StartTransactionButton.js +4 -3
- package/dist/esm/pages/TransactionPage/StartTransactionButton.js.map +1 -1
- package/dist/esm/pages/TransactionPage/TokenValueBottomSheet.js.map +1 -1
- package/dist/esm/pages/TransactionPage/TokenVerificationBottomSheet.js +64 -0
- package/dist/esm/pages/TransactionPage/TokenVerificationBottomSheet.js.map +1 -0
- package/dist/esm/pages/TransactionPage/TransactionDoneButtons.js.map +1 -1
- package/dist/esm/pages/TransactionPage/TransactionExecutionContent.js +19 -16
- package/dist/esm/pages/TransactionPage/TransactionExecutionContent.js.map +1 -1
- package/dist/esm/pages/TransactionPage/TransactionFailedButtons.js +3 -1
- package/dist/esm/pages/TransactionPage/TransactionFailedButtons.js.map +1 -1
- package/dist/esm/pages/TransactionPage/TransactionPage.js.map +1 -1
- package/dist/esm/pages/TransactionPage/TransactionReview.js +24 -2
- package/dist/esm/pages/TransactionPage/TransactionReview.js.map +1 -1
- package/dist/esm/providers/I18nProvider/I18nProvider.js +37 -36
- package/dist/esm/providers/I18nProvider/I18nProvider.js.map +1 -1
- package/dist/esm/providers/I18nProvider/types.d.ts.map +1 -1
- package/dist/esm/providers/ThemeProvider/ThemeProvider.js +2 -1
- package/dist/esm/providers/ThemeProvider/ThemeProvider.js.map +1 -1
- package/dist/esm/providers/WalletProvider/WalletProvider.js +10 -9
- package/dist/esm/providers/WalletProvider/WalletProvider.js.map +1 -1
- package/dist/esm/providers/WalletProvider/useExternalWalletProvider.js +7 -3
- package/dist/esm/providers/WalletProvider/useExternalWalletProvider.js.map +1 -1
- package/dist/esm/stores/StoreProvider.js.map +1 -1
- package/dist/esm/stores/form/FormStore.js.map +1 -1
- package/dist/esm/stores/form/FormUpdater.js.map +1 -1
- package/dist/esm/stores/navigationTabs/useNavigationTabsStore.js.map +1 -1
- package/dist/esm/stores/routes/useRouteExecutionIndicator.js +4 -3
- package/dist/esm/stores/routes/useRouteExecutionIndicator.js.map +1 -1
- package/dist/esm/types/token.d.ts +4 -1
- package/dist/esm/types/token.d.ts.map +1 -1
- package/dist/esm/utils/compactNumberFormatter.js +1 -3
- package/dist/esm/utils/compactNumberFormatter.js.map +1 -1
- package/dist/esm/utils/customReceiver.js +7 -0
- package/dist/esm/utils/customReceiver.js.map +1 -0
- package/dist/esm/utils/gas.js +24 -0
- package/dist/esm/utils/gas.js.map +1 -0
- package/dist/esm/utils/getErrorMessage.js +0 -1
- package/dist/esm/utils/getErrorMessage.js.map +1 -1
- package/dist/esm/utils/limitOrder.js +1 -1
- package/dist/esm/utils/limitOrder.js.map +1 -1
- package/dist/esm/utils/token.js +21 -4
- package/dist/esm/utils/token.js.map +1 -1
- package/dist/esm/utils/tokenList.js +37 -23
- package/dist/esm/utils/tokenList.js.map +1 -1
- package/package.json +15 -15
- package/src/components/AmountInput/AmountInputEndAdornment.tsx +2 -21
- package/src/components/AmountInputCard/PercentageChips.tsx +2 -18
- package/src/components/Chains/AllChainsAvatar.tsx +7 -1
- package/src/components/Messages/UnsupportedToAddressMessage.tsx +24 -0
- package/src/components/Messages/WarningMessages.tsx +3 -0
- package/src/components/Messages/useMessageQueue.ts +9 -0
- package/src/components/Routes/LimitOrderRoutes.tsx +5 -2
- package/src/components/Routes/RoutesContent.tsx +5 -2
- package/src/components/SendToWallet/SendToWalletExpandButton.tsx +2 -1
- package/src/components/TokenList/TokenListItem.tsx +68 -9
- package/src/components/TokenList/VirtualizedTokenList.tsx +33 -9
- package/src/components/TokenList/types.ts +4 -0
- package/src/config/version.ts +1 -1
- package/src/hooks/useAccountsBalancesData.ts +4 -31
- package/src/hooks/useAvailableChains.ts +1 -0
- package/src/hooks/useExplorer.ts +2 -0
- package/src/hooks/useFlaggedTokenGuard.ts +33 -0
- package/src/hooks/useGasSufficiency.ts +9 -1
- package/src/hooks/useMaxSendAmount.ts +21 -0
- package/src/hooks/useRoutes.ts +7 -0
- package/src/hooks/useToAddressRequirements.ts +17 -1
- package/src/hooks/useTokenBalances.ts +18 -2
- package/src/hooks/useTokenBalancesQueries.ts +12 -4
- package/src/hooks/useTokenSearch.ts +1 -5
- package/src/hooks/useTokens.ts +28 -13
- package/src/pages/MainPage/ReviewButton.tsx +6 -2
- package/src/pages/RoutesPage/RoutesPage.tsx +5 -2
- package/src/pages/TransactionPage/TokenVerificationBottomSheet.tsx +93 -0
- package/src/pages/TransactionPage/TransactionReview.tsx +28 -1
- package/src/providers/WalletProvider/useExternalWalletProvider.ts +9 -1
- package/src/types/token.ts +6 -3
- package/src/utils/customReceiver.ts +7 -0
- package/src/utils/gas.ts +41 -0
- package/src/utils/token.ts +53 -9
- package/src/utils/tokenList.ts +27 -7
- package/dist/esm/hooks/useFilteredByTokenBalances.js +0 -74
- package/dist/esm/hooks/useFilteredByTokenBalances.js.map +0 -1
- package/src/hooks/useFilteredByTokenBalances.ts +0 -145
package/dist/esm/App.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"App.js","names":[],"sources":["../../src/App.tsx"],"sourcesContent":["'use client'\nimport type { JSX, Ref } from 'react'\nimport { useMemo } from 'react'\nimport { AppDefault } from './AppDefault.js'\nimport type { WidgetDrawer } from './AppDrawer.js'\nimport { AppDrawer } from './AppDrawer.js'\nimport { AppProvider } from './AppProvider.js'\nimport type { WidgetConfig, WidgetProps } from './types/widget.js'\n\nexport const App = (\n props: WidgetProps & { ref?: Ref<WidgetDrawer> }\n): JSX.Element => {\n const config: WidgetConfig = useMemo(() => {\n const config = { ...props, ...props.config }\n if (config.variant === 'drawer') {\n config.theme = {\n ...config.theme,\n container: {\n height: '100%',\n ...config.theme?.container,\n },\n }\n }\n return config\n }, [props])\n\n if (config.variant === 'drawer') {\n return (\n <AppProvider config={config} formRef={props.formRef}>\n <AppDrawer\n ref={props.ref}\n elementRef={props.elementRef}\n config={config}\n open={props.open}\n onClose={props.onClose}\n >\n <AppDefault />\n </AppDrawer>\n </AppProvider>\n )\n }\n\n return (\n <AppProvider config={config} formRef={props.formRef}>\n <AppDefault />\n </AppProvider>\n )\n}\n"],"mappings":";;;;;;;AASA,MAAa,OACX,UACgB;CAChB,MAAM,SAAuB,cAAc;EACzC,MAAM,SAAS;GAAE,GAAG;GAAO,GAAG,MAAM;EAAO;EAC3C,IAAI,OAAO,YAAY,UACrB,OAAO,QAAQ;GACb,GAAG,OAAO;GACV,WAAW;IACT,QAAQ;IACR,GAAG,OAAO,OAAO;GACnB;EACF;EAEF,OAAO;CACT,GAAG,CAAC,KAAK,CAAC;CAEV,IAAI,OAAO,YAAY,UACrB,OACE,oBAAC,aAAD;EAAqB;EAAQ,SAAS,MAAM;
|
|
1
|
+
{"version":3,"file":"App.js","names":[],"sources":["../../src/App.tsx"],"sourcesContent":["'use client'\nimport type { JSX, Ref } from 'react'\nimport { useMemo } from 'react'\nimport { AppDefault } from './AppDefault.js'\nimport type { WidgetDrawer } from './AppDrawer.js'\nimport { AppDrawer } from './AppDrawer.js'\nimport { AppProvider } from './AppProvider.js'\nimport type { WidgetConfig, WidgetProps } from './types/widget.js'\n\nexport const App = (\n props: WidgetProps & { ref?: Ref<WidgetDrawer> }\n): JSX.Element => {\n const config: WidgetConfig = useMemo(() => {\n const config = { ...props, ...props.config }\n if (config.variant === 'drawer') {\n config.theme = {\n ...config.theme,\n container: {\n height: '100%',\n ...config.theme?.container,\n },\n }\n }\n return config\n }, [props])\n\n if (config.variant === 'drawer') {\n return (\n <AppProvider config={config} formRef={props.formRef}>\n <AppDrawer\n ref={props.ref}\n elementRef={props.elementRef}\n config={config}\n open={props.open}\n onClose={props.onClose}\n >\n <AppDefault />\n </AppDrawer>\n </AppProvider>\n )\n }\n\n return (\n <AppProvider config={config} formRef={props.formRef}>\n <AppDefault />\n </AppProvider>\n )\n}\n"],"mappings":";;;;;;;AASA,MAAa,OACX,UACgB;CAChB,MAAM,SAAuB,cAAc;EACzC,MAAM,SAAS;GAAE,GAAG;GAAO,GAAG,MAAM;EAAO;EAC3C,IAAI,OAAO,YAAY,UACrB,OAAO,QAAQ;GACb,GAAG,OAAO;GACV,WAAW;IACT,QAAQ;IACR,GAAG,OAAO,OAAO;GACnB;EACF;EAEF,OAAO;CACT,GAAG,CAAC,KAAK,CAAC;CAEV,IAAI,OAAO,YAAY,UACrB,OACE,oBAAC,aAAD;EAAqB;EAAQ,SAAS,MAAM;EAC1C,UAAA,oBAAC,WAAD;GACE,KAAK,MAAM;GACX,YAAY,MAAM;GACV;GACR,MAAM,MAAM;GACZ,SAAS,MAAM;GAEf,UAAA,oBAAC,YAAD,CAAa,CAAA;EACJ,CAAA;CACA,CAAA;CAIjB,OACE,oBAAC,aAAD;EAAqB;EAAQ,SAAS,MAAM;EAC1C,UAAA,oBAAC,YAAD,CAAa,CAAA;CACF,CAAA;AAEjB"}
|
package/dist/esm/AppDrawer.js
CHANGED
|
@@ -32,8 +32,9 @@ const AppDrawer = ({ elementRef, open, onClose, children, ref }) => {
|
|
|
32
32
|
openDrawer,
|
|
33
33
|
toggleDrawer
|
|
34
34
|
]);
|
|
35
|
+
const drawerContext = useMemo(() => ({ closeDrawer }), [closeDrawer]);
|
|
35
36
|
return /* @__PURE__ */ jsx(DrawerContext, {
|
|
36
|
-
value:
|
|
37
|
+
value: drawerContext,
|
|
37
38
|
children: /* @__PURE__ */ jsx(Drawer, {
|
|
38
39
|
ref: elementRef,
|
|
39
40
|
anchor: "right",
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"AppDrawer.js","names":[],"sources":["../../src/AppDrawer.tsx"],"sourcesContent":["import { Drawer } from '@mui/material'\nimport type { JSX, PropsWithChildren, Ref } from 'react'\nimport {\n useCallback,\n useImperativeHandle,\n useMemo,\n useRef,\n useState,\n} from 'react'\nimport type { WidgetDrawerContext } from './AppDrawerContext.js'\nimport { DrawerContext } from './AppDrawerContext.js'\nimport type { WidgetDrawerProps } from './types/widget.js'\n\nexport interface WidgetDrawer {\n isOpen(): void\n toggleDrawer(): void\n openDrawer(): void\n closeDrawer(): void\n}\n\nexport const AppDrawer = ({\n elementRef,\n open,\n onClose,\n children,\n ref,\n}: PropsWithChildren<WidgetDrawerProps> & {\n ref?: Ref<WidgetDrawer>\n}): JSX.Element => {\n const openRef = useRef(Boolean(open))\n const [drawerOpen, setDrawerOpen] = useState(Boolean(open))\n\n const toggleDrawer = useCallback(() => {\n setDrawerOpen((open) => {\n openRef.current = !open\n return openRef.current\n })\n if (!openRef.current) {\n onClose?.()\n }\n }, [onClose])\n\n const openDrawer = useCallback(() => {\n setDrawerOpen(true)\n openRef.current = true\n }, [])\n\n const closeDrawer = useCallback(() => {\n setDrawerOpen(false)\n openRef.current = false\n onClose?.()\n }, [onClose])\n\n useImperativeHandle(\n ref,\n () => ({\n isOpen: () => openRef.current,\n toggleDrawer,\n openDrawer,\n closeDrawer,\n }),\n [closeDrawer, openDrawer, toggleDrawer]\n )\n\n const drawerContext: WidgetDrawerContext = useMemo(\n () => ({\n closeDrawer,\n }),\n [closeDrawer]\n )\n\n return (\n <DrawerContext value={drawerContext}>\n <Drawer\n ref={elementRef}\n anchor=\"right\"\n open={drawerOpen}\n onClose={closeDrawer}\n slotProps={{\n paper: {\n sx: (theme) => ({\n background: theme.vars.palette.background.default,\n width: theme?.container?.width ?? '100%',\n minWidth:\n theme?.container?.minWidth ?? theme.breakpoints.values.xs,\n maxWidth:\n theme?.container?.maxWidth ?? theme.breakpoints.values.sm,\n }),\n },\n backdrop: {\n sx: {\n backgroundColor: 'rgb(0 0 0 / 48%)',\n backdropFilter: 'blur(3px)',\n },\n },\n }}\n keepMounted\n >\n {children}\n </Drawer>\n </DrawerContext>\n )\n}\n"],"mappings":";;;;;AAoBA,MAAa,aAAa,EACxB,YACA,MACA,SACA,UACA,UAGiB;CACjB,MAAM,UAAU,OAAO,QAAQ,IAAI,CAAC;CACpC,MAAM,CAAC,YAAY,iBAAiB,SAAS,QAAQ,IAAI,CAAC;CAE1D,MAAM,eAAe,kBAAkB;EACrC,eAAe,SAAS;GACtB,QAAQ,UAAU,CAAC;GACnB,OAAO,QAAQ;EACjB,CAAC;EACD,IAAI,CAAC,QAAQ,SACX,UAAU;CAEd,GAAG,CAAC,OAAO,CAAC;CAEZ,MAAM,aAAa,kBAAkB;EACnC,cAAc,IAAI;EAClB,QAAQ,UAAU;CACpB,GAAG,CAAC,CAAC;CAEL,MAAM,cAAc,kBAAkB;EACpC,cAAc,KAAK;EACnB,QAAQ,UAAU;EAClB,UAAU;CACZ,GAAG,CAAC,OAAO,CAAC;CAEZ,oBACE,YACO;EACL,cAAc,QAAQ;EACtB;EACA;EACA;CACF,IACA;EAAC;EAAa;EAAY;CAAY,CACxC;
|
|
1
|
+
{"version":3,"file":"AppDrawer.js","names":[],"sources":["../../src/AppDrawer.tsx"],"sourcesContent":["import { Drawer } from '@mui/material'\nimport type { JSX, PropsWithChildren, Ref } from 'react'\nimport {\n useCallback,\n useImperativeHandle,\n useMemo,\n useRef,\n useState,\n} from 'react'\nimport type { WidgetDrawerContext } from './AppDrawerContext.js'\nimport { DrawerContext } from './AppDrawerContext.js'\nimport type { WidgetDrawerProps } from './types/widget.js'\n\nexport interface WidgetDrawer {\n isOpen(): void\n toggleDrawer(): void\n openDrawer(): void\n closeDrawer(): void\n}\n\nexport const AppDrawer = ({\n elementRef,\n open,\n onClose,\n children,\n ref,\n}: PropsWithChildren<WidgetDrawerProps> & {\n ref?: Ref<WidgetDrawer>\n}): JSX.Element => {\n const openRef = useRef(Boolean(open))\n const [drawerOpen, setDrawerOpen] = useState(Boolean(open))\n\n const toggleDrawer = useCallback(() => {\n setDrawerOpen((open) => {\n openRef.current = !open\n return openRef.current\n })\n if (!openRef.current) {\n onClose?.()\n }\n }, [onClose])\n\n const openDrawer = useCallback(() => {\n setDrawerOpen(true)\n openRef.current = true\n }, [])\n\n const closeDrawer = useCallback(() => {\n setDrawerOpen(false)\n openRef.current = false\n onClose?.()\n }, [onClose])\n\n useImperativeHandle(\n ref,\n () => ({\n isOpen: () => openRef.current,\n toggleDrawer,\n openDrawer,\n closeDrawer,\n }),\n [closeDrawer, openDrawer, toggleDrawer]\n )\n\n const drawerContext: WidgetDrawerContext = useMemo(\n () => ({\n closeDrawer,\n }),\n [closeDrawer]\n )\n\n return (\n <DrawerContext value={drawerContext}>\n <Drawer\n ref={elementRef}\n anchor=\"right\"\n open={drawerOpen}\n onClose={closeDrawer}\n slotProps={{\n paper: {\n sx: (theme) => ({\n background: theme.vars.palette.background.default,\n width: theme?.container?.width ?? '100%',\n minWidth:\n theme?.container?.minWidth ?? theme.breakpoints.values.xs,\n maxWidth:\n theme?.container?.maxWidth ?? theme.breakpoints.values.sm,\n }),\n },\n backdrop: {\n sx: {\n backgroundColor: 'rgb(0 0 0 / 48%)',\n backdropFilter: 'blur(3px)',\n },\n },\n }}\n keepMounted\n >\n {children}\n </Drawer>\n </DrawerContext>\n )\n}\n"],"mappings":";;;;;AAoBA,MAAa,aAAa,EACxB,YACA,MACA,SACA,UACA,UAGiB;CACjB,MAAM,UAAU,OAAO,QAAQ,IAAI,CAAC;CACpC,MAAM,CAAC,YAAY,iBAAiB,SAAS,QAAQ,IAAI,CAAC;CAE1D,MAAM,eAAe,kBAAkB;EACrC,eAAe,SAAS;GACtB,QAAQ,UAAU,CAAC;GACnB,OAAO,QAAQ;EACjB,CAAC;EACD,IAAI,CAAC,QAAQ,SACX,UAAU;CAEd,GAAG,CAAC,OAAO,CAAC;CAEZ,MAAM,aAAa,kBAAkB;EACnC,cAAc,IAAI;EAClB,QAAQ,UAAU;CACpB,GAAG,CAAC,CAAC;CAEL,MAAM,cAAc,kBAAkB;EACpC,cAAc,KAAK;EACnB,QAAQ,UAAU;EAClB,UAAU;CACZ,GAAG,CAAC,OAAO,CAAC;CAEZ,oBACE,YACO;EACL,cAAc,QAAQ;EACtB;EACA;EACA;CACF,IACA;EAAC;EAAa;EAAY;CAAY,CACxC;CAEA,MAAM,gBAAqC,eAClC,EACL,YACF,IACA,CAAC,WAAW,CACd;CAEA,OACE,oBAAC,eAAD;EAAe,OAAO;EACpB,UAAA,oBAAC,QAAD;GACE,KAAK;GACL,QAAO;GACP,MAAM;GACN,SAAS;GACT,WAAW;IACT,OAAO,EACL,KAAK,WAAW;KACd,YAAY,MAAM,KAAK,QAAQ,WAAW;KAC1C,OAAO,OAAO,WAAW,SAAS;KAClC,UACE,OAAO,WAAW,YAAY,MAAM,YAAY,OAAO;KACzD,UACE,OAAO,WAAW,YAAY,MAAM,YAAY,OAAO;IAC3D,GACF;IACA,UAAU,EACR,IAAI;KACF,iBAAiB;KACjB,gBAAgB;IAClB,EACF;GACF;GACA,aAAA;GAEC;EACK,CAAA;CACK,CAAA;AAEnB"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"AppLayout.js","names":[],"sources":["../../src/AppLayout.tsx"],"sourcesContent":["'use client'\nimport { Outlet } from '@tanstack/react-router'\nimport {\n AppContainer,\n AppExpandedContainer,\n} from './components/AppContainer.js'\nimport { Expansion } from './components/Expansion/Expansion.js'\nimport { Header } from './components/Header/Header.js'\nimport { Initializer } from './components/Initializer.js'\nimport { PageEntered } from './components/PageEntered.js'\nimport { version } from './config/version.js'\nimport { useWideVariant } from './hooks/useWideVariant.js'\nimport { useWidgetConfig } from './providers/WidgetProvider/WidgetProvider.js'\nimport { URLSearchParamsBuilder } from './stores/form/URLSearchParamsBuilder.js'\nimport { createElementId, ElementId } from './utils/elements.js'\n\nexport const AppLayout: React.FC = () => {\n const { elementId, buildUrl } = useWidgetConfig()\n const wideVariant = useWideVariant()\n\n return (\n <AppExpandedContainer\n id={createElementId(ElementId.AppExpandedContainer, elementId)}\n data-version={version}\n >\n <AppContainer>\n <Header />\n <Initializer />\n {buildUrl ? <URLSearchParamsBuilder /> : null}\n <PageEntered />\n <Outlet />\n </AppContainer>\n {wideVariant && <Expansion />}\n </AppExpandedContainer>\n )\n}\n"],"mappings":";;;;;;;;;;;;;;AAgBA,MAAa,kBAA4B;CACvC,MAAM,EAAE,WAAW,aAAa,gBAAgB;CAChD,MAAM,cAAc,eAAe;CAEnC,OACE,qBAAC,sBAAD;EACE,IAAI,gBAAA,iCAAgD,SAAS;EAC7D,gBAAc;
|
|
1
|
+
{"version":3,"file":"AppLayout.js","names":[],"sources":["../../src/AppLayout.tsx"],"sourcesContent":["'use client'\nimport { Outlet } from '@tanstack/react-router'\nimport {\n AppContainer,\n AppExpandedContainer,\n} from './components/AppContainer.js'\nimport { Expansion } from './components/Expansion/Expansion.js'\nimport { Header } from './components/Header/Header.js'\nimport { Initializer } from './components/Initializer.js'\nimport { PageEntered } from './components/PageEntered.js'\nimport { version } from './config/version.js'\nimport { useWideVariant } from './hooks/useWideVariant.js'\nimport { useWidgetConfig } from './providers/WidgetProvider/WidgetProvider.js'\nimport { URLSearchParamsBuilder } from './stores/form/URLSearchParamsBuilder.js'\nimport { createElementId, ElementId } from './utils/elements.js'\n\nexport const AppLayout: React.FC = () => {\n const { elementId, buildUrl } = useWidgetConfig()\n const wideVariant = useWideVariant()\n\n return (\n <AppExpandedContainer\n id={createElementId(ElementId.AppExpandedContainer, elementId)}\n data-version={version}\n >\n <AppContainer>\n <Header />\n <Initializer />\n {buildUrl ? <URLSearchParamsBuilder /> : null}\n <PageEntered />\n <Outlet />\n </AppContainer>\n {wideVariant && <Expansion />}\n </AppExpandedContainer>\n )\n}\n"],"mappings":";;;;;;;;;;;;;;AAgBA,MAAa,kBAA4B;CACvC,MAAM,EAAE,WAAW,aAAa,gBAAgB;CAChD,MAAM,cAAc,eAAe;CAEnC,OACE,qBAAC,sBAAD;EACE,IAAI,gBAAA,iCAAgD,SAAS;EAC7D,gBAAc;EAFhB,UAAA,CAIE,qBAAC,cAAD,EAAA,UAAA;GACE,oBAAC,QAAD,CAAS,CAAA;GACT,oBAAC,aAAD,CAAc,CAAA;GACb,WAAW,oBAAC,wBAAD,CAAyB,CAAA,IAAI;GACzC,oBAAC,aAAD,CAAc,CAAA;GACd,oBAAC,QAAD,CAAS,CAAA;EACG,EAAA,CAAA,GACb,eAAe,oBAAC,WAAD,CAAY,CAAA,CACR;;AAE1B"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"AppProvider.js","names":[],"sources":["../../src/AppProvider.tsx"],"sourcesContent":["import type { PropsWithChildren } from 'react'\nimport { I18nProvider } from './providers/I18nProvider/I18nProvider.js'\nimport { QueryClientProvider } from './providers/QueryClientProvider.js'\nimport { SDKClientProvider } from './providers/SDKClientProvider.js'\nimport { ThemeProvider } from './providers/ThemeProvider/ThemeProvider.js'\nimport { WalletProvider } from './providers/WalletProvider/WalletProvider.js'\nimport { WidgetProvider } from './providers/WidgetProvider/WidgetProvider.js'\nimport { StoreProvider } from './stores/StoreProvider.js'\nimport { SettingsStoreProvider } from './stores/settings/SettingsStore.js'\nimport type { WidgetConfigProps } from './types/widget.js'\n\nexport const AppProvider: React.FC<PropsWithChildren<WidgetConfigProps>> = ({\n children,\n config,\n formRef,\n}) => {\n return (\n <QueryClientProvider>\n <SettingsStoreProvider config={config}>\n <WidgetProvider config={config}>\n <I18nProvider>\n <ThemeProvider>\n <SDKClientProvider>\n <WalletProvider providers={config.providers ?? []}>\n <StoreProvider config={config} formRef={formRef}>\n {children}\n </StoreProvider>\n </WalletProvider>\n </SDKClientProvider>\n </ThemeProvider>\n </I18nProvider>\n </WidgetProvider>\n </SettingsStoreProvider>\n </QueryClientProvider>\n )\n}\n"],"mappings":";;;;;;;;;;AAWA,MAAa,eAA+D,EAC1E,UACA,QACA,cACI;CACJ,OACE,oBAAC,qBAAD,EAAA,UACE,oBAAC,uBAAD;EAA+B;
|
|
1
|
+
{"version":3,"file":"AppProvider.js","names":[],"sources":["../../src/AppProvider.tsx"],"sourcesContent":["import type { PropsWithChildren } from 'react'\nimport { I18nProvider } from './providers/I18nProvider/I18nProvider.js'\nimport { QueryClientProvider } from './providers/QueryClientProvider.js'\nimport { SDKClientProvider } from './providers/SDKClientProvider.js'\nimport { ThemeProvider } from './providers/ThemeProvider/ThemeProvider.js'\nimport { WalletProvider } from './providers/WalletProvider/WalletProvider.js'\nimport { WidgetProvider } from './providers/WidgetProvider/WidgetProvider.js'\nimport { StoreProvider } from './stores/StoreProvider.js'\nimport { SettingsStoreProvider } from './stores/settings/SettingsStore.js'\nimport type { WidgetConfigProps } from './types/widget.js'\n\nexport const AppProvider: React.FC<PropsWithChildren<WidgetConfigProps>> = ({\n children,\n config,\n formRef,\n}) => {\n return (\n <QueryClientProvider>\n <SettingsStoreProvider config={config}>\n <WidgetProvider config={config}>\n <I18nProvider>\n <ThemeProvider>\n <SDKClientProvider>\n <WalletProvider providers={config.providers ?? []}>\n <StoreProvider config={config} formRef={formRef}>\n {children}\n </StoreProvider>\n </WalletProvider>\n </SDKClientProvider>\n </ThemeProvider>\n </I18nProvider>\n </WidgetProvider>\n </SettingsStoreProvider>\n </QueryClientProvider>\n )\n}\n"],"mappings":";;;;;;;;;;AAWA,MAAa,eAA+D,EAC1E,UACA,QACA,cACI;CACJ,OACE,oBAAC,qBAAD,EAAA,UACE,oBAAC,uBAAD;EAA+B;EAC7B,UAAA,oBAAC,gBAAD;GAAwB;GACtB,UAAA,oBAAC,cAAD,EAAA,UACE,oBAAC,eAAD,EAAA,UACE,oBAAC,mBAAD,EAAA,UACE,oBAAC,gBAAD;IAAgB,WAAW,OAAO,aAAa,CAAC;IAC9C,UAAA,oBAAC,eAAD;KAAuB;KAAiB;KACrC;IACY,CAAA;GACD,CAAA,EACC,CAAA,EACN,CAAA,EACH,CAAA;EACA,CAAA;CACK,CAAA,EACJ,CAAA;AAEzB"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"ActionRow.js","names":[],"sources":["../../../../src/components/ActionRow/ActionRow.tsx"],"sourcesContent":["import type { SxProps, Theme } from '@mui/material'\nimport type { FC, ReactNode } from 'react'\nimport { ActionRowContainer, ActionRowLabel } from './ActionRow.style.js'\n\ninterface ActionRowProps {\n message: string\n startAdornment: ReactNode\n endAdornment?: ReactNode\n sx?: SxProps<Theme>\n}\n\nexport const ActionRow: FC<ActionRowProps> = ({\n message,\n startAdornment,\n endAdornment,\n sx,\n}) => {\n return (\n <ActionRowContainer sx={sx}>\n {startAdornment}\n <ActionRowLabel>{message}</ActionRowLabel>\n {endAdornment}\n </ActionRowContainer>\n )\n}\n"],"mappings":";;;AAWA,MAAa,aAAiC,EAC5C,SACA,gBACA,cACA,SACI;CACJ,OACE,qBAAC,oBAAD;EAAwB;
|
|
1
|
+
{"version":3,"file":"ActionRow.js","names":[],"sources":["../../../../src/components/ActionRow/ActionRow.tsx"],"sourcesContent":["import type { SxProps, Theme } from '@mui/material'\nimport type { FC, ReactNode } from 'react'\nimport { ActionRowContainer, ActionRowLabel } from './ActionRow.style.js'\n\ninterface ActionRowProps {\n message: string\n startAdornment: ReactNode\n endAdornment?: ReactNode\n sx?: SxProps<Theme>\n}\n\nexport const ActionRow: FC<ActionRowProps> = ({\n message,\n startAdornment,\n endAdornment,\n sx,\n}) => {\n return (\n <ActionRowContainer sx={sx}>\n {startAdornment}\n <ActionRowLabel>{message}</ActionRowLabel>\n {endAdornment}\n </ActionRowContainer>\n )\n}\n"],"mappings":";;;AAWA,MAAa,aAAiC,EAC5C,SACA,gBACA,cACA,SACI;CACJ,OACE,qBAAC,oBAAD;EAAwB;EAAxB,UAAA;GACG;GACD,oBAAC,gBAAD,EAAA,UAAiB,QAAwB,CAAA;GACxC;EACiB;;AAExB"}
|
|
@@ -40,16 +40,20 @@ const AmountInputBase = ({ formType, token, startAdornment, bottomAdornment, dis
|
|
|
40
40
|
const { inputMode } = useInputModeStore();
|
|
41
41
|
const currentInputMode = inputMode[formType];
|
|
42
42
|
let displayValue;
|
|
43
|
-
if (isEditingRef.current)
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
else
|
|
43
|
+
if (isEditingRef.current) {
|
|
44
|
+
if (currentInputMode === "price") displayValue = formattedPriceInput;
|
|
45
|
+
else displayValue = value;
|
|
46
|
+
} else if (currentInputMode === "price") {
|
|
47
|
+
const priceValue = formatTokenPrice(value, token?.priceUSD);
|
|
48
|
+
displayValue = formatInputAmount(priceValue.toFixed(2), 2);
|
|
49
|
+
} else displayValue = value;
|
|
47
50
|
const handleChange = (event) => {
|
|
48
51
|
const { value: inputValue } = event.target;
|
|
49
52
|
isEditingRef.current = true;
|
|
50
53
|
let formattedValue;
|
|
51
54
|
if (currentInputMode === "price") {
|
|
52
|
-
|
|
55
|
+
const cleanInputValue = inputValue.replace("$", "");
|
|
56
|
+
formattedValue = formatInputAmount(cleanInputValue, 2, true);
|
|
53
57
|
const tokenValue = priceToTokenAmount(formattedValue, token?.priceUSD);
|
|
54
58
|
setFormattedPriceInput(formattedValue);
|
|
55
59
|
setFieldValue(amountKey, tokenValue, {
|
|
@@ -69,8 +73,10 @@ const AmountInputBase = ({ formType, token, startAdornment, bottomAdornment, dis
|
|
|
69
73
|
isEditingRef.current = false;
|
|
70
74
|
let formattedValue;
|
|
71
75
|
if (currentInputMode === "price") {
|
|
72
|
-
|
|
73
|
-
|
|
76
|
+
const cleanInputValue = inputValue.replace("$", "");
|
|
77
|
+
formattedValue = formatInputAmount(cleanInputValue, 2);
|
|
78
|
+
const tokenValue = priceToTokenAmount(formattedValue, token?.priceUSD);
|
|
79
|
+
const formattedAmount = formatInputAmount(tokenValue, token?.decimals);
|
|
74
80
|
setFieldValue(amountKey, formattedAmount, {
|
|
75
81
|
isDirty: true,
|
|
76
82
|
isTouched: true
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"AmountInput.js","names":[],"sources":["../../../../src/components/AmountInput/AmountInput.tsx"],"sourcesContent":["import type { Token } from '@lifi/sdk'\nimport type { CardProps } from '@mui/material'\nimport type { ChangeEvent, ReactNode } from 'react'\nimport { useLayoutEffect, useRef, useState } from 'react'\nimport { useTranslation } from 'react-i18next'\nimport { useToken } from '../../hooks/useToken.js'\nimport { useWidgetConfig } from '../../providers/WidgetProvider/WidgetProvider.js'\nimport { FormKeyHelper, type FormTypeProps } from '../../stores/form/types.js'\nimport { useFieldActions } from '../../stores/form/useFieldActions.js'\nimport { useFieldValues } from '../../stores/form/useFieldValues.js'\nimport { useInputModeStore } from '../../stores/inputMode/useInputModeStore.js'\nimport {\n formatInputAmount,\n formatTokenPrice,\n priceToTokenAmount,\n usdDecimals,\n} from '../../utils/format.js'\nimport { fitInputText } from '../../utils/input.js'\nimport { InputCard } from '../Card/InputCard.js'\nimport {\n AmountInputCardHeader,\n AmountInputCardTitle,\n FormContainer,\n FormControl,\n Input,\n maxInputFontSize,\n minInputFontSize,\n} from './AmountInput.style.js'\nimport { AmountInputEndAdornment } from './AmountInputEndAdornment.js'\nimport { AmountInputStartAdornment } from './AmountInputStartAdornment.js'\nimport { PriceFormHelperText } from './PriceFormHelperText.js'\n\nexport const AmountInput: React.FC<FormTypeProps & CardProps> = ({\n formType,\n ...props\n}) => {\n const { disabledUI } = useWidgetConfig()\n\n const [chainId, tokenAddress] = useFieldValues(\n FormKeyHelper.getChainKey(formType),\n FormKeyHelper.getTokenKey(formType)\n )\n\n const { token } = useToken(chainId, tokenAddress)\n\n const disabled = disabledUI?.fromAmount\n return (\n <AmountInputBase\n formType={formType}\n token={token}\n bottomAdornment={<PriceFormHelperText formType={formType} />}\n disabled={disabled}\n {...props}\n />\n )\n}\n\nconst AmountInputBase: React.FC<\n FormTypeProps &\n CardProps & {\n token?: Token\n startAdornment?: ReactNode\n bottomAdornment?: ReactNode\n disabled?: boolean\n }\n> = ({\n formType,\n token,\n startAdornment,\n bottomAdornment,\n disabled,\n ...props\n}) => {\n const { t } = useTranslation()\n const { mode, modeOptions } = useWidgetConfig()\n const ref = useRef<HTMLInputElement>(null)\n\n const isEditingRef = useRef(false)\n const [formattedPriceInput, setFormattedPriceInput] = useState('')\n\n const amountKey = FormKeyHelper.getAmountKey(formType)\n const [value] = useFieldValues(amountKey)\n const { setFieldValue } = useFieldActions()\n const { inputMode } = useInputModeStore()\n\n const currentInputMode = inputMode[formType]\n let displayValue: string\n if (isEditingRef.current) {\n if (currentInputMode === 'price') {\n displayValue = formattedPriceInput\n } else {\n displayValue = value as string\n }\n } else {\n if (currentInputMode === 'price') {\n const priceValue = formatTokenPrice(value as string, token?.priceUSD)\n displayValue = formatInputAmount(\n priceValue.toFixed(usdDecimals),\n usdDecimals\n )\n } else {\n displayValue = value as string\n }\n }\n\n const handleChange = (\n event: ChangeEvent<HTMLInputElement | HTMLTextAreaElement>\n ) => {\n const { value: inputValue } = event.target\n isEditingRef.current = true\n\n let formattedValue: string\n if (currentInputMode === 'price') {\n const cleanInputValue = inputValue.replace('$', '')\n formattedValue = formatInputAmount(cleanInputValue, usdDecimals, true)\n const tokenValue = priceToTokenAmount(formattedValue, token?.priceUSD)\n setFormattedPriceInput(formattedValue)\n setFieldValue(amountKey, tokenValue, { isDirty: true, isTouched: true })\n } else {\n formattedValue = formatInputAmount(inputValue, token?.decimals, true)\n setFieldValue(amountKey, formattedValue, {\n isDirty: true,\n isTouched: true,\n })\n }\n }\n\n const handleBlur = (\n event: ChangeEvent<HTMLInputElement | HTMLTextAreaElement>\n ) => {\n const { value: inputValue } = event.target\n isEditingRef.current = false\n\n let formattedValue: string\n if (currentInputMode === 'price') {\n const cleanInputValue = inputValue.replace('$', '')\n formattedValue = formatInputAmount(cleanInputValue, usdDecimals)\n const tokenValue = priceToTokenAmount(formattedValue, token?.priceUSD)\n const formattedAmount = formatInputAmount(tokenValue, token?.decimals)\n setFieldValue(amountKey, formattedAmount, {\n isDirty: true,\n isTouched: true,\n })\n } else {\n formattedValue = formatInputAmount(inputValue, token?.decimals)\n setFieldValue(amountKey, formattedValue, {\n isDirty: true,\n isTouched: true,\n })\n }\n }\n\n // biome-ignore lint/correctness/useExhaustiveDependencies: we need run effect on value change\n useLayoutEffect(() => {\n if (ref.current) {\n fitInputText(maxInputFontSize, minInputFontSize, ref.current)\n }\n }, [displayValue])\n\n const title =\n mode === 'custom'\n ? modeOptions?.custom?.type === 'deposit'\n ? t('header.amount')\n : t('header.youPay')\n : t('header.send')\n\n return (\n <InputCard {...props}>\n <AmountInputCardHeader>\n <AmountInputCardTitle>{title}</AmountInputCardTitle>\n </AmountInputCardHeader>\n <FormContainer>\n <AmountInputStartAdornment formType={formType} />\n <FormControl fullWidth>\n <Input\n inputRef={ref}\n size=\"small\"\n autoComplete=\"off\"\n placeholder={currentInputMode === 'price' ? '$0' : '0'}\n startAdornment={startAdornment}\n inputProps={{\n inputMode: 'decimal',\n }}\n onChange={handleChange}\n onBlur={handleBlur}\n value={\n currentInputMode === 'price'\n ? displayValue\n ? `$${displayValue}`\n : ''\n : displayValue\n }\n name={amountKey}\n disabled={disabled}\n required\n />\n {bottomAdornment}\n </FormControl>\n </FormContainer>\n {!disabled && <AmountInputEndAdornment formType={formType} />}\n </InputCard>\n )\n}\n"],"mappings":";;;;;;;;;;;;;;;;;AAgCA,MAAa,eAAoD,EAC/D,UACA,GAAG,YACC;CACJ,MAAM,EAAE,eAAe,gBAAgB;CAEvC,MAAM,CAAC,SAAS,gBAAgB,eAC9B,cAAc,YAAY,QAAQ,GAClC,cAAc,YAAY,QAAQ,CACpC;CAEA,MAAM,EAAE,UAAU,SAAS,SAAS,YAAY;CAEhD,MAAM,WAAW,YAAY;CAC7B,OACE,oBAAC,iBAAD;EACY;EACH;EACP,iBAAiB,oBAAC,qBAAD,EAA+B,SAAW,CAAA;EACjD;EACV,GAAI;CACL,CAAA;AAEL;AAEA,MAAM,mBAQD,EACH,UACA,OACA,gBACA,iBACA,UACA,GAAG,YACC;CACJ,MAAM,EAAE,MAAM,eAAe;CAC7B,MAAM,EAAE,MAAM,gBAAgB,gBAAgB;CAC9C,MAAM,MAAM,OAAyB,IAAI;CAEzC,MAAM,eAAe,OAAO,KAAK;CACjC,MAAM,CAAC,qBAAqB,0BAA0B,SAAS,EAAE;CAEjE,MAAM,YAAY,cAAc,aAAa,QAAQ;CACrD,MAAM,CAAC,SAAS,eAAe,SAAS;CACxC,MAAM,EAAE,kBAAkB,gBAAgB;CAC1C,MAAM,EAAE,cAAc,kBAAkB;CAExC,MAAM,mBAAmB,UAAU;CACnC,IAAI;CACJ,IAAI,aAAa,
|
|
1
|
+
{"version":3,"file":"AmountInput.js","names":[],"sources":["../../../../src/components/AmountInput/AmountInput.tsx"],"sourcesContent":["import type { Token } from '@lifi/sdk'\nimport type { CardProps } from '@mui/material'\nimport type { ChangeEvent, ReactNode } from 'react'\nimport { useLayoutEffect, useRef, useState } from 'react'\nimport { useTranslation } from 'react-i18next'\nimport { useToken } from '../../hooks/useToken.js'\nimport { useWidgetConfig } from '../../providers/WidgetProvider/WidgetProvider.js'\nimport { FormKeyHelper, type FormTypeProps } from '../../stores/form/types.js'\nimport { useFieldActions } from '../../stores/form/useFieldActions.js'\nimport { useFieldValues } from '../../stores/form/useFieldValues.js'\nimport { useInputModeStore } from '../../stores/inputMode/useInputModeStore.js'\nimport {\n formatInputAmount,\n formatTokenPrice,\n priceToTokenAmount,\n usdDecimals,\n} from '../../utils/format.js'\nimport { fitInputText } from '../../utils/input.js'\nimport { InputCard } from '../Card/InputCard.js'\nimport {\n AmountInputCardHeader,\n AmountInputCardTitle,\n FormContainer,\n FormControl,\n Input,\n maxInputFontSize,\n minInputFontSize,\n} from './AmountInput.style.js'\nimport { AmountInputEndAdornment } from './AmountInputEndAdornment.js'\nimport { AmountInputStartAdornment } from './AmountInputStartAdornment.js'\nimport { PriceFormHelperText } from './PriceFormHelperText.js'\n\nexport const AmountInput: React.FC<FormTypeProps & CardProps> = ({\n formType,\n ...props\n}) => {\n const { disabledUI } = useWidgetConfig()\n\n const [chainId, tokenAddress] = useFieldValues(\n FormKeyHelper.getChainKey(formType),\n FormKeyHelper.getTokenKey(formType)\n )\n\n const { token } = useToken(chainId, tokenAddress)\n\n const disabled = disabledUI?.fromAmount\n return (\n <AmountInputBase\n formType={formType}\n token={token}\n bottomAdornment={<PriceFormHelperText formType={formType} />}\n disabled={disabled}\n {...props}\n />\n )\n}\n\nconst AmountInputBase: React.FC<\n FormTypeProps &\n CardProps & {\n token?: Token\n startAdornment?: ReactNode\n bottomAdornment?: ReactNode\n disabled?: boolean\n }\n> = ({\n formType,\n token,\n startAdornment,\n bottomAdornment,\n disabled,\n ...props\n}) => {\n const { t } = useTranslation()\n const { mode, modeOptions } = useWidgetConfig()\n const ref = useRef<HTMLInputElement>(null)\n\n const isEditingRef = useRef(false)\n const [formattedPriceInput, setFormattedPriceInput] = useState('')\n\n const amountKey = FormKeyHelper.getAmountKey(formType)\n const [value] = useFieldValues(amountKey)\n const { setFieldValue } = useFieldActions()\n const { inputMode } = useInputModeStore()\n\n const currentInputMode = inputMode[formType]\n let displayValue: string\n if (isEditingRef.current) {\n if (currentInputMode === 'price') {\n displayValue = formattedPriceInput\n } else {\n displayValue = value as string\n }\n } else {\n if (currentInputMode === 'price') {\n const priceValue = formatTokenPrice(value as string, token?.priceUSD)\n displayValue = formatInputAmount(\n priceValue.toFixed(usdDecimals),\n usdDecimals\n )\n } else {\n displayValue = value as string\n }\n }\n\n const handleChange = (\n event: ChangeEvent<HTMLInputElement | HTMLTextAreaElement>\n ) => {\n const { value: inputValue } = event.target\n isEditingRef.current = true\n\n let formattedValue: string\n if (currentInputMode === 'price') {\n const cleanInputValue = inputValue.replace('$', '')\n formattedValue = formatInputAmount(cleanInputValue, usdDecimals, true)\n const tokenValue = priceToTokenAmount(formattedValue, token?.priceUSD)\n setFormattedPriceInput(formattedValue)\n setFieldValue(amountKey, tokenValue, { isDirty: true, isTouched: true })\n } else {\n formattedValue = formatInputAmount(inputValue, token?.decimals, true)\n setFieldValue(amountKey, formattedValue, {\n isDirty: true,\n isTouched: true,\n })\n }\n }\n\n const handleBlur = (\n event: ChangeEvent<HTMLInputElement | HTMLTextAreaElement>\n ) => {\n const { value: inputValue } = event.target\n isEditingRef.current = false\n\n let formattedValue: string\n if (currentInputMode === 'price') {\n const cleanInputValue = inputValue.replace('$', '')\n formattedValue = formatInputAmount(cleanInputValue, usdDecimals)\n const tokenValue = priceToTokenAmount(formattedValue, token?.priceUSD)\n const formattedAmount = formatInputAmount(tokenValue, token?.decimals)\n setFieldValue(amountKey, formattedAmount, {\n isDirty: true,\n isTouched: true,\n })\n } else {\n formattedValue = formatInputAmount(inputValue, token?.decimals)\n setFieldValue(amountKey, formattedValue, {\n isDirty: true,\n isTouched: true,\n })\n }\n }\n\n // biome-ignore lint/correctness/useExhaustiveDependencies: we need run effect on value change\n useLayoutEffect(() => {\n if (ref.current) {\n fitInputText(maxInputFontSize, minInputFontSize, ref.current)\n }\n }, [displayValue])\n\n const title =\n mode === 'custom'\n ? modeOptions?.custom?.type === 'deposit'\n ? t('header.amount')\n : t('header.youPay')\n : t('header.send')\n\n return (\n <InputCard {...props}>\n <AmountInputCardHeader>\n <AmountInputCardTitle>{title}</AmountInputCardTitle>\n </AmountInputCardHeader>\n <FormContainer>\n <AmountInputStartAdornment formType={formType} />\n <FormControl fullWidth>\n <Input\n inputRef={ref}\n size=\"small\"\n autoComplete=\"off\"\n placeholder={currentInputMode === 'price' ? '$0' : '0'}\n startAdornment={startAdornment}\n inputProps={{\n inputMode: 'decimal',\n }}\n onChange={handleChange}\n onBlur={handleBlur}\n value={\n currentInputMode === 'price'\n ? displayValue\n ? `$${displayValue}`\n : ''\n : displayValue\n }\n name={amountKey}\n disabled={disabled}\n required\n />\n {bottomAdornment}\n </FormControl>\n </FormContainer>\n {!disabled && <AmountInputEndAdornment formType={formType} />}\n </InputCard>\n )\n}\n"],"mappings":"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"}
|
|
@@ -2,8 +2,8 @@ import { useAvailableChains } from "../../hooks/useAvailableChains.js";
|
|
|
2
2
|
import { useFieldActions } from "../../stores/form/useFieldActions.js";
|
|
3
3
|
import { FormKeyHelper } from "../../stores/form/types.js";
|
|
4
4
|
import { useFieldValues } from "../../stores/form/useFieldValues.js";
|
|
5
|
-
import { useGasRecommendation } from "../../hooks/useGasRecommendation.js";
|
|
6
5
|
import { useTokenAddressBalance } from "../../hooks/useTokenAddressBalance.js";
|
|
6
|
+
import { useMaxSendAmount } from "../../hooks/useMaxSendAmount.js";
|
|
7
7
|
import { AmountInputButton, ButtonContainer } from "./AmountInputEndAdornment.style.js";
|
|
8
8
|
import { formatUnits } from "@lifi/sdk";
|
|
9
9
|
import { memo } from "react";
|
|
@@ -18,26 +18,15 @@ const AmountInputEndAdornment = memo(({ formType }) => {
|
|
|
18
18
|
const [chainId, tokenAddress] = useFieldValues(FormKeyHelper.getChainKey(formType), FormKeyHelper.getTokenKey(formType));
|
|
19
19
|
const chain = getChainById(chainId);
|
|
20
20
|
const { account } = useAccount({ chainType: chain?.chainType });
|
|
21
|
-
const { data } = useGasRecommendation(chainId);
|
|
22
21
|
const { token } = useTokenAddressBalance(chainId, tokenAddress);
|
|
23
|
-
const
|
|
24
|
-
if (!token?.amount) return 0n;
|
|
25
|
-
let maxAmount = token.amount;
|
|
26
|
-
if (chain?.nativeToken.address === tokenAddress && data?.recommended) {
|
|
27
|
-
const recommendedAmount = BigInt(data.recommended.amount);
|
|
28
|
-
if (token.amount > recommendedAmount) maxAmount = token.amount - recommendedAmount;
|
|
29
|
-
}
|
|
30
|
-
return maxAmount;
|
|
31
|
-
};
|
|
22
|
+
const maxAmount = useMaxSendAmount(chainId, tokenAddress);
|
|
32
23
|
const handlePercentage = (percentage) => {
|
|
33
|
-
const maxAmount = getMaxAmount();
|
|
34
24
|
if (maxAmount && token?.decimals) {
|
|
35
25
|
const percentageAmount = maxAmount * BigInt(percentage) / 100n;
|
|
36
26
|
setFieldValue(FormKeyHelper.getAmountKey(formType), formatUnits(percentageAmount, token.decimals), { isTouched: true });
|
|
37
27
|
}
|
|
38
28
|
};
|
|
39
29
|
const handleMax = () => {
|
|
40
|
-
const maxAmount = getMaxAmount();
|
|
41
30
|
if (maxAmount && token?.decimals) setFieldValue(FormKeyHelper.getAmountKey(formType), formatUnits(maxAmount, token.decimals), { isTouched: true });
|
|
42
31
|
};
|
|
43
32
|
if (formType !== "from" || !token || !account?.isConnected) return null;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"AmountInputEndAdornment.js","names":[],"sources":["../../../../src/components/AmountInput/AmountInputEndAdornment.tsx"],"sourcesContent":["import { formatUnits } from '@lifi/sdk'\nimport { useAccount } from '@lifi/wallet-management'\nimport type React from 'react'\nimport { type JSX, memo } from 'react'\nimport { useTranslation } from 'react-i18next'\nimport { useAvailableChains } from '../../hooks/useAvailableChains.js'\nimport {
|
|
1
|
+
{"version":3,"file":"AmountInputEndAdornment.js","names":[],"sources":["../../../../src/components/AmountInput/AmountInputEndAdornment.tsx"],"sourcesContent":["import { formatUnits } from '@lifi/sdk'\nimport { useAccount } from '@lifi/wallet-management'\nimport type React from 'react'\nimport { type JSX, memo } from 'react'\nimport { useTranslation } from 'react-i18next'\nimport { useAvailableChains } from '../../hooks/useAvailableChains.js'\nimport { useMaxSendAmount } from '../../hooks/useMaxSendAmount.js'\nimport { useTokenAddressBalance } from '../../hooks/useTokenAddressBalance.js'\nimport type { FormTypeProps } from '../../stores/form/types.js'\nimport { FormKeyHelper } from '../../stores/form/types.js'\nimport { useFieldActions } from '../../stores/form/useFieldActions.js'\nimport { useFieldValues } from '../../stores/form/useFieldValues.js'\nimport {\n AmountInputButton,\n ButtonContainer,\n} from './AmountInputEndAdornment.style.js'\n\nexport const AmountInputEndAdornment: React.NamedExoticComponent<FormTypeProps> =\n memo(({ formType }: FormTypeProps): JSX.Element | null => {\n const { t } = useTranslation()\n const { getChainById } = useAvailableChains()\n const { setFieldValue } = useFieldActions()\n\n const [chainId, tokenAddress] = useFieldValues(\n FormKeyHelper.getChainKey(formType),\n FormKeyHelper.getTokenKey(formType)\n )\n\n const chain = getChainById(chainId)\n const { account } = useAccount({ chainType: chain?.chainType })\n\n const { token } = useTokenAddressBalance(chainId, tokenAddress)\n const maxAmount = useMaxSendAmount(chainId, tokenAddress)\n\n const handlePercentage = (percentage: number) => {\n if (maxAmount && token?.decimals) {\n const percentageAmount = (maxAmount * BigInt(percentage)) / 100n\n setFieldValue(\n FormKeyHelper.getAmountKey(formType),\n formatUnits(percentageAmount, token.decimals),\n {\n isTouched: true,\n }\n )\n }\n }\n\n const handleMax = () => {\n if (maxAmount && token?.decimals) {\n setFieldValue(\n FormKeyHelper.getAmountKey(formType),\n formatUnits(maxAmount, token.decimals),\n {\n isTouched: true,\n }\n )\n }\n }\n\n if (formType !== 'from' || !token || !account?.isConnected) {\n return null\n }\n\n return (\n <ButtonContainer>\n <AmountInputButton onClick={() => handlePercentage(25)}>\n 25%\n </AmountInputButton>\n <AmountInputButton onClick={() => handlePercentage(50)}>\n 50%\n </AmountInputButton>\n <AmountInputButton onClick={() => handlePercentage(75)}>\n 75%\n </AmountInputButton>\n <AmountInputButton onClick={handleMax}>\n {t('button.max')}\n </AmountInputButton>\n </ButtonContainer>\n )\n })\n"],"mappings":";;;;;;;;;;;;;AAiBA,MAAa,0BACX,MAAM,EAAE,eAAkD;CACxD,MAAM,EAAE,MAAM,eAAe;CAC7B,MAAM,EAAE,iBAAiB,mBAAmB;CAC5C,MAAM,EAAE,kBAAkB,gBAAgB;CAE1C,MAAM,CAAC,SAAS,gBAAgB,eAC9B,cAAc,YAAY,QAAQ,GAClC,cAAc,YAAY,QAAQ,CACpC;CAEA,MAAM,QAAQ,aAAa,OAAO;CAClC,MAAM,EAAE,YAAY,WAAW,EAAE,WAAW,OAAO,UAAU,CAAC;CAE9D,MAAM,EAAE,UAAU,uBAAuB,SAAS,YAAY;CAC9D,MAAM,YAAY,iBAAiB,SAAS,YAAY;CAExD,MAAM,oBAAoB,eAAuB;EAC/C,IAAI,aAAa,OAAO,UAAU;GAChC,MAAM,mBAAoB,YAAY,OAAO,UAAU,IAAK;GAC5D,cACE,cAAc,aAAa,QAAQ,GACnC,YAAY,kBAAkB,MAAM,QAAQ,GAC5C,EACE,WAAW,KACb,CACF;EACF;CACF;CAEA,MAAM,kBAAkB;EACtB,IAAI,aAAa,OAAO,UACtB,cACE,cAAc,aAAa,QAAQ,GACnC,YAAY,WAAW,MAAM,QAAQ,GACrC,EACE,WAAW,KACb,CACF;CAEJ;CAEA,IAAI,aAAa,UAAU,CAAC,SAAS,CAAC,SAAS,aAC7C,OAAO;CAGT,OACE,qBAAC,iBAAD,EAAA,UAAA;EACE,oBAAC,mBAAD;GAAmB,eAAe,iBAAiB,EAAE;GAAG,UAAA;EAErC,CAAA;EACnB,oBAAC,mBAAD;GAAmB,eAAe,iBAAiB,EAAE;GAAG,UAAA;EAErC,CAAA;EACnB,oBAAC,mBAAD;GAAmB,eAAe,iBAAiB,EAAE;GAAG,UAAA;EAErC,CAAA;EACnB,oBAAC,mBAAD;GAAmB,SAAS;GACzB,UAAA,EAAE,YAAY;EACE,CAAA;CACJ,EAAA,CAAA;AAErB,CAAC"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"PriceFormHelperText.js","names":[],"sources":["../../../../src/components/AmountInput/PriceFormHelperText.tsx"],"sourcesContent":["import type { TokenAmount } from '@lifi/sdk'\nimport SwapVertIcon from '@mui/icons-material/SwapVert'\nimport { FormHelperText, Skeleton, Typography } from '@mui/material'\nimport type React from 'react'\nimport { memo } from 'react'\nimport { useTranslation } from 'react-i18next'\nimport { useTokenAddressBalance } from '../../hooks/useTokenAddressBalance.js'\nimport type { FormTypeProps } from '../../stores/form/types.js'\nimport { FormKeyHelper } from '../../stores/form/types.js'\nimport { useFieldValues } from '../../stores/form/useFieldValues.js'\nimport { useInputModeStore } from '../../stores/inputMode/useInputModeStore.js'\nimport { formatTokenAmount, formatTokenPrice } from '../../utils/format.js'\nimport { InputPriceButton } from './PriceFormHelperText.style.js'\n\nexport const PriceFormHelperText: React.NamedExoticComponent<FormTypeProps> =\n memo<FormTypeProps>(({ formType }) => {\n const [chainId, tokenAddress] = useFieldValues(\n FormKeyHelper.getChainKey(formType),\n FormKeyHelper.getTokenKey(formType)\n )\n const { token, isLoading } = useTokenAddressBalance(chainId, tokenAddress)\n\n return (\n <PriceFormHelperTextBase\n formType={formType}\n isLoading={isLoading}\n tokenAddress={tokenAddress}\n token={token}\n />\n )\n })\n\nconst PriceFormHelperTextBase: React.FC<\n FormTypeProps & {\n isLoading?: boolean\n tokenAddress?: string\n token?: TokenAmount\n }\n> = ({ formType, isLoading, tokenAddress, token }) => {\n const { t } = useTranslation()\n const [amount] = useFieldValues(FormKeyHelper.getAmountKey(formType))\n const { inputMode, toggleInputMode } = useInputModeStore()\n\n const currentInputMode = inputMode[formType]\n\n const tokenAmount = token\n ? formatTokenAmount(token.amount, token.decimals)\n : '0'\n\n const getPriceAmountDisplayValue = () => {\n if (currentInputMode === 'amount') {\n const tokenPrice = formatTokenPrice(\n amount,\n token?.priceUSD,\n token?.decimals\n )\n return t('format.currency', { value: tokenPrice })\n } else {\n return t('format.tokenAmount', { value: amount || '0' })\n }\n }\n\n const handleToggleMode = (e: React.MouseEvent) => {\n e.stopPropagation()\n toggleInputMode(formType)\n }\n\n return (\n <FormHelperText\n component=\"div\"\n sx={{\n display: 'flex',\n justifyContent: 'space-between',\n alignItems: 'center',\n margin: 0,\n marginLeft: 1.25,\n marginTop: 0.5,\n }}\n >\n <InputPriceButton\n onClick={token?.priceUSD ? handleToggleMode : undefined}\n >\n <Typography\n sx={{\n color: 'text.secondary',\n fontWeight: 500,\n fontSize: 12,\n lineHeight: 1,\n marginRight: 0.25,\n maxWidth: 136,\n overflow: 'hidden',\n textOverflow: 'ellipsis',\n whiteSpace: 'nowrap',\n }}\n >\n {getPriceAmountDisplayValue()}\n </Typography>\n {currentInputMode === 'price' && token?.symbol ? (\n <Typography\n sx={{\n color: 'text.secondary',\n fontWeight: 500,\n fontSize: 12,\n lineHeight: 1,\n wordBreak: 'break-word',\n overflowWrap: 'break-word',\n marginRight: 0.25,\n }}\n >\n {token.symbol}\n </Typography>\n ) : null}\n {token?.priceUSD && <SwapVertIcon sx={{ fontSize: 14 }} />}\n </InputPriceButton>\n {isLoading && tokenAddress ? (\n <Skeleton variant=\"text\" width={56} height={16} />\n ) : token?.amount ? (\n <Typography\n sx={{\n fontWeight: 500,\n fontSize: 12,\n color: 'text.secondary',\n lineHeight: 1,\n paddingLeft: 0.25,\n }}\n title={tokenAmount}\n >\n {`/ ${t('format.tokenAmount', {\n value: tokenAmount,\n })}`}\n </Typography>\n ) : null}\n </FormHelperText>\n )\n}\n"],"mappings":";;;;;;;;;;;;AAcA,MAAa,sBACX,MAAqB,EAAE,eAAe;CACpC,MAAM,CAAC,SAAS,gBAAgB,eAC9B,cAAc,YAAY,QAAQ,GAClC,cAAc,YAAY,QAAQ,CACpC;CACA,MAAM,EAAE,OAAO,cAAc,uBAAuB,SAAS,YAAY;CAEzE,OACE,oBAAC,yBAAD;EACY;EACC;EACG;EACP;CACR,CAAA;AAEL,CAAC;AAEH,MAAM,2BAMD,EAAE,UAAU,WAAW,cAAc,YAAY;CACpD,MAAM,EAAE,MAAM,eAAe;CAC7B,MAAM,CAAC,UAAU,eAAe,cAAc,aAAa,QAAQ,CAAC;CACpE,MAAM,EAAE,WAAW,oBAAoB,kBAAkB;CAEzD,MAAM,mBAAmB,UAAU;CAEnC,MAAM,cAAc,QAChB,kBAAkB,MAAM,QAAQ,MAAM,QAAQ,IAC9C;CAEJ,MAAM,mCAAmC;EACvC,IAAI,qBAAqB,UAAU;GACjC,MAAM,aAAa,iBACjB,QACA,OAAO,UACP,OAAO,QACT;GACA,OAAO,EAAE,mBAAmB,EAAE,OAAO,WAAW,CAAC;EACnD,OACE,OAAO,EAAE,sBAAsB,EAAE,OAAO,UAAU,IAAI,CAAC;CAE3D;CAEA,MAAM,oBAAoB,MAAwB;EAChD,EAAE,gBAAgB;EAClB,gBAAgB,QAAQ;CAC1B;CAEA,OACE,qBAAC,gBAAD;EACE,WAAU;EACV,IAAI;GACF,SAAS;GACT,gBAAgB;GAChB,YAAY;GACZ,QAAQ;GACR,YAAY;GACZ,WAAW;EACb;
|
|
1
|
+
{"version":3,"file":"PriceFormHelperText.js","names":[],"sources":["../../../../src/components/AmountInput/PriceFormHelperText.tsx"],"sourcesContent":["import type { TokenAmount } from '@lifi/sdk'\nimport SwapVertIcon from '@mui/icons-material/SwapVert'\nimport { FormHelperText, Skeleton, Typography } from '@mui/material'\nimport type React from 'react'\nimport { memo } from 'react'\nimport { useTranslation } from 'react-i18next'\nimport { useTokenAddressBalance } from '../../hooks/useTokenAddressBalance.js'\nimport type { FormTypeProps } from '../../stores/form/types.js'\nimport { FormKeyHelper } from '../../stores/form/types.js'\nimport { useFieldValues } from '../../stores/form/useFieldValues.js'\nimport { useInputModeStore } from '../../stores/inputMode/useInputModeStore.js'\nimport { formatTokenAmount, formatTokenPrice } from '../../utils/format.js'\nimport { InputPriceButton } from './PriceFormHelperText.style.js'\n\nexport const PriceFormHelperText: React.NamedExoticComponent<FormTypeProps> =\n memo<FormTypeProps>(({ formType }) => {\n const [chainId, tokenAddress] = useFieldValues(\n FormKeyHelper.getChainKey(formType),\n FormKeyHelper.getTokenKey(formType)\n )\n const { token, isLoading } = useTokenAddressBalance(chainId, tokenAddress)\n\n return (\n <PriceFormHelperTextBase\n formType={formType}\n isLoading={isLoading}\n tokenAddress={tokenAddress}\n token={token}\n />\n )\n })\n\nconst PriceFormHelperTextBase: React.FC<\n FormTypeProps & {\n isLoading?: boolean\n tokenAddress?: string\n token?: TokenAmount\n }\n> = ({ formType, isLoading, tokenAddress, token }) => {\n const { t } = useTranslation()\n const [amount] = useFieldValues(FormKeyHelper.getAmountKey(formType))\n const { inputMode, toggleInputMode } = useInputModeStore()\n\n const currentInputMode = inputMode[formType]\n\n const tokenAmount = token\n ? formatTokenAmount(token.amount, token.decimals)\n : '0'\n\n const getPriceAmountDisplayValue = () => {\n if (currentInputMode === 'amount') {\n const tokenPrice = formatTokenPrice(\n amount,\n token?.priceUSD,\n token?.decimals\n )\n return t('format.currency', { value: tokenPrice })\n } else {\n return t('format.tokenAmount', { value: amount || '0' })\n }\n }\n\n const handleToggleMode = (e: React.MouseEvent) => {\n e.stopPropagation()\n toggleInputMode(formType)\n }\n\n return (\n <FormHelperText\n component=\"div\"\n sx={{\n display: 'flex',\n justifyContent: 'space-between',\n alignItems: 'center',\n margin: 0,\n marginLeft: 1.25,\n marginTop: 0.5,\n }}\n >\n <InputPriceButton\n onClick={token?.priceUSD ? handleToggleMode : undefined}\n >\n <Typography\n sx={{\n color: 'text.secondary',\n fontWeight: 500,\n fontSize: 12,\n lineHeight: 1,\n marginRight: 0.25,\n maxWidth: 136,\n overflow: 'hidden',\n textOverflow: 'ellipsis',\n whiteSpace: 'nowrap',\n }}\n >\n {getPriceAmountDisplayValue()}\n </Typography>\n {currentInputMode === 'price' && token?.symbol ? (\n <Typography\n sx={{\n color: 'text.secondary',\n fontWeight: 500,\n fontSize: 12,\n lineHeight: 1,\n wordBreak: 'break-word',\n overflowWrap: 'break-word',\n marginRight: 0.25,\n }}\n >\n {token.symbol}\n </Typography>\n ) : null}\n {token?.priceUSD && <SwapVertIcon sx={{ fontSize: 14 }} />}\n </InputPriceButton>\n {isLoading && tokenAddress ? (\n <Skeleton variant=\"text\" width={56} height={16} />\n ) : token?.amount ? (\n <Typography\n sx={{\n fontWeight: 500,\n fontSize: 12,\n color: 'text.secondary',\n lineHeight: 1,\n paddingLeft: 0.25,\n }}\n title={tokenAmount}\n >\n {`/ ${t('format.tokenAmount', {\n value: tokenAmount,\n })}`}\n </Typography>\n ) : null}\n </FormHelperText>\n )\n}\n"],"mappings":";;;;;;;;;;;;AAcA,MAAa,sBACX,MAAqB,EAAE,eAAe;CACpC,MAAM,CAAC,SAAS,gBAAgB,eAC9B,cAAc,YAAY,QAAQ,GAClC,cAAc,YAAY,QAAQ,CACpC;CACA,MAAM,EAAE,OAAO,cAAc,uBAAuB,SAAS,YAAY;CAEzE,OACE,oBAAC,yBAAD;EACY;EACC;EACG;EACP;CACR,CAAA;AAEL,CAAC;AAEH,MAAM,2BAMD,EAAE,UAAU,WAAW,cAAc,YAAY;CACpD,MAAM,EAAE,MAAM,eAAe;CAC7B,MAAM,CAAC,UAAU,eAAe,cAAc,aAAa,QAAQ,CAAC;CACpE,MAAM,EAAE,WAAW,oBAAoB,kBAAkB;CAEzD,MAAM,mBAAmB,UAAU;CAEnC,MAAM,cAAc,QAChB,kBAAkB,MAAM,QAAQ,MAAM,QAAQ,IAC9C;CAEJ,MAAM,mCAAmC;EACvC,IAAI,qBAAqB,UAAU;GACjC,MAAM,aAAa,iBACjB,QACA,OAAO,UACP,OAAO,QACT;GACA,OAAO,EAAE,mBAAmB,EAAE,OAAO,WAAW,CAAC;EACnD,OACE,OAAO,EAAE,sBAAsB,EAAE,OAAO,UAAU,IAAI,CAAC;CAE3D;CAEA,MAAM,oBAAoB,MAAwB;EAChD,EAAE,gBAAgB;EAClB,gBAAgB,QAAQ;CAC1B;CAEA,OACE,qBAAC,gBAAD;EACE,WAAU;EACV,IAAI;GACF,SAAS;GACT,gBAAgB;GAChB,YAAY;GACZ,QAAQ;GACR,YAAY;GACZ,WAAW;EACb;EATF,UAAA,CAWE,qBAAC,kBAAD;GACE,SAAS,OAAO,WAAW,mBAAmB,KAAA;GADhD,UAAA;IAGE,oBAAC,YAAD;KACE,IAAI;MACF,OAAO;MACP,YAAY;MACZ,UAAU;MACV,YAAY;MACZ,aAAa;MACb,UAAU;MACV,UAAU;MACV,cAAc;MACd,YAAY;KACd;KAEC,UAAA,2BAA2B;IAClB,CAAA;IACX,qBAAqB,WAAW,OAAO,SACtC,oBAAC,YAAD;KACE,IAAI;MACF,OAAO;MACP,YAAY;MACZ,UAAU;MACV,YAAY;MACZ,WAAW;MACX,cAAc;MACd,aAAa;KACf;KAEC,UAAA,MAAM;IACG,CAAA,IACV;IACH,OAAO,YAAY,oBAAC,cAAD,EAAc,IAAI,EAAE,UAAU,GAAG,EAAI,CAAA;GACzC;EACjB,CAAA,GAAA,aAAa,eACZ,oBAAC,UAAD;GAAU,SAAQ;GAAO,OAAO;GAAI,QAAQ;EAAK,CAAA,IAC/C,OAAO,SACT,oBAAC,YAAD;GACE,IAAI;IACF,YAAY;IACZ,UAAU;IACV,OAAO;IACP,YAAY;IACZ,aAAa;GACf;GACA,OAAO;GAEN,UAAA,KAAK,EAAE,sBAAsB,EAC5B,OAAO,YACT,CAAC;EACS,CAAA,IACV,IACU;;AAEpB"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"AmountInputCardPair.js","names":[],"sources":["../../../../src/components/AmountInputCard/AmountInputCardPair.tsx"],"sourcesContent":["import type { BoxProps } from '@mui/material'\nimport type React from 'react'\nimport type { JSX } from 'react'\nimport { useWidgetConfig } from '../../providers/WidgetProvider/WidgetProvider.js'\nimport { LimitPriceCard } from '../LimitPriceCard/LimitPriceCard.js'\nimport { SwapButton } from '../SwapButton/SwapButton.js'\nimport { CardContainer } from './AmountInputCard.style.js'\nimport { ReceiveAmountCard } from './ReceiveAmountCard.js'\nimport { SendAmountCard } from './SendAmountCard.js'\n\nexport const AmountInputCardPair: React.FC<BoxProps> = (props): JSX.Element => {\n // Refuel's destination is fixed to native gas, so reversing from/to is\n // meaningless — hide the swap button (and the notch mask it sits in).\n const { mode } = useWidgetConfig()\n const showSwapButton = mode !== 'refuel'\n\n return (\n <CardContainer {...props}>\n {mode === 'limit' ? <LimitPriceCard sx={{ marginBottom: 1 }} /> : null}\n <SendAmountCard mask={showSwapButton} />\n <SwapButton sx={{ visibility: showSwapButton ? 'visible' : 'hidden' }} />\n <ReceiveAmountCard mask={showSwapButton} />\n </CardContainer>\n )\n}\n"],"mappings":";;;;;;;;AAUA,MAAa,uBAA2C,UAAuB;CAG7E,MAAM,EAAE,SAAS,gBAAgB;CACjC,MAAM,iBAAiB,SAAS;CAEhC,OACE,qBAAC,eAAD;EAAe,GAAI;
|
|
1
|
+
{"version":3,"file":"AmountInputCardPair.js","names":[],"sources":["../../../../src/components/AmountInputCard/AmountInputCardPair.tsx"],"sourcesContent":["import type { BoxProps } from '@mui/material'\nimport type React from 'react'\nimport type { JSX } from 'react'\nimport { useWidgetConfig } from '../../providers/WidgetProvider/WidgetProvider.js'\nimport { LimitPriceCard } from '../LimitPriceCard/LimitPriceCard.js'\nimport { SwapButton } from '../SwapButton/SwapButton.js'\nimport { CardContainer } from './AmountInputCard.style.js'\nimport { ReceiveAmountCard } from './ReceiveAmountCard.js'\nimport { SendAmountCard } from './SendAmountCard.js'\n\nexport const AmountInputCardPair: React.FC<BoxProps> = (props): JSX.Element => {\n // Refuel's destination is fixed to native gas, so reversing from/to is\n // meaningless — hide the swap button (and the notch mask it sits in).\n const { mode } = useWidgetConfig()\n const showSwapButton = mode !== 'refuel'\n\n return (\n <CardContainer {...props}>\n {mode === 'limit' ? <LimitPriceCard sx={{ marginBottom: 1 }} /> : null}\n <SendAmountCard mask={showSwapButton} />\n <SwapButton sx={{ visibility: showSwapButton ? 'visible' : 'hidden' }} />\n <ReceiveAmountCard mask={showSwapButton} />\n </CardContainer>\n )\n}\n"],"mappings":";;;;;;;;AAUA,MAAa,uBAA2C,UAAuB;CAG7E,MAAM,EAAE,SAAS,gBAAgB;CACjC,MAAM,iBAAiB,SAAS;CAEhC,OACE,qBAAC,eAAD;EAAe,GAAI;EAAnB,UAAA;GACG,SAAS,UAAU,oBAAC,gBAAD,EAAgB,IAAI,EAAE,cAAc,EAAE,EAAI,CAAA,IAAI;GAClE,oBAAC,gBAAD,EAAgB,MAAM,eAAiB,CAAA;GACvC,oBAAC,YAAD,EAAY,IAAI,EAAE,YAAY,iBAAiB,YAAY,SAAS,EAAI,CAAA;GACxE,oBAAC,mBAAD,EAAmB,MAAM,eAAiB,CAAA;EAC7B;;AAEnB"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"BalanceDisplay.js","names":[],"sources":["../../../../src/components/AmountInputCard/BalanceDisplay.tsx"],"sourcesContent":["import AccountBalanceWalletOutlinedIcon from '@mui/icons-material/AccountBalanceWalletOutlined'\nimport { Skeleton } from '@mui/material'\nimport { type JSX, memo } from 'react'\nimport { useTranslation } from 'react-i18next'\nimport { useTokenAddressBalance } from '../../hooks/useTokenAddressBalance.js'\nimport type { FormTypeProps } from '../../stores/form/types.js'\nimport { FormKeyHelper } from '../../stores/form/types.js'\nimport { useFieldValues } from '../../stores/form/useFieldValues.js'\nimport { formatTokenAmount } from '../../utils/format.js'\nimport { FooterText, footerFontSize } from './AmountInputCard.style.js'\nimport { BalanceContainer } from './BalanceDisplay.style.js'\n\nexport const BalanceDisplay: React.NamedExoticComponent<FormTypeProps> = memo(\n ({ formType }: FormTypeProps): JSX.Element | null => {\n const { t } = useTranslation()\n const [chainId, tokenAddress] = useFieldValues(\n FormKeyHelper.getChainKey(formType),\n FormKeyHelper.getTokenKey(formType)\n )\n\n const { token, isLoading } = useTokenAddressBalance(chainId, tokenAddress)\n\n if (isLoading && tokenAddress) {\n return (\n <Skeleton variant=\"text\" width={72} sx={{ fontSize: footerFontSize }} />\n )\n }\n\n if (!token?.amount) {\n return null\n }\n\n const tokenAmount = formatTokenAmount(token.amount, token.decimals)\n\n return (\n <BalanceContainer>\n <FooterText title={tokenAmount}>\n {t('format.tokenAmount', { value: tokenAmount })}\n </FooterText>\n <AccountBalanceWalletOutlinedIcon\n sx={{ fontSize: 16, color: 'text.secondary' }}\n />\n </BalanceContainer>\n )\n }\n)\n"],"mappings":";;;;;;;;;;;;AAYA,MAAa,iBAA4D,MACtE,EAAE,eAAkD;CACnD,MAAM,EAAE,MAAM,eAAe;CAC7B,MAAM,CAAC,SAAS,gBAAgB,eAC9B,cAAc,YAAY,QAAQ,GAClC,cAAc,YAAY,QAAQ,CACpC;CAEA,MAAM,EAAE,OAAO,cAAc,uBAAuB,SAAS,YAAY;CAEzE,IAAI,aAAa,cACf,OACE,oBAAC,UAAD;EAAU,SAAQ;EAAO,OAAO;EAAI,IAAI,EAAE,UAAA,GAAyB;CAAI,CAAA;CAI3E,IAAI,CAAC,OAAO,QACV,OAAO;CAGT,MAAM,cAAc,kBAAkB,MAAM,QAAQ,MAAM,QAAQ;CAElE,OACE,qBAAC,kBAAD,EAAA,UAAA,CACE,oBAAC,YAAD;EAAY,OAAO;
|
|
1
|
+
{"version":3,"file":"BalanceDisplay.js","names":[],"sources":["../../../../src/components/AmountInputCard/BalanceDisplay.tsx"],"sourcesContent":["import AccountBalanceWalletOutlinedIcon from '@mui/icons-material/AccountBalanceWalletOutlined'\nimport { Skeleton } from '@mui/material'\nimport { type JSX, memo } from 'react'\nimport { useTranslation } from 'react-i18next'\nimport { useTokenAddressBalance } from '../../hooks/useTokenAddressBalance.js'\nimport type { FormTypeProps } from '../../stores/form/types.js'\nimport { FormKeyHelper } from '../../stores/form/types.js'\nimport { useFieldValues } from '../../stores/form/useFieldValues.js'\nimport { formatTokenAmount } from '../../utils/format.js'\nimport { FooterText, footerFontSize } from './AmountInputCard.style.js'\nimport { BalanceContainer } from './BalanceDisplay.style.js'\n\nexport const BalanceDisplay: React.NamedExoticComponent<FormTypeProps> = memo(\n ({ formType }: FormTypeProps): JSX.Element | null => {\n const { t } = useTranslation()\n const [chainId, tokenAddress] = useFieldValues(\n FormKeyHelper.getChainKey(formType),\n FormKeyHelper.getTokenKey(formType)\n )\n\n const { token, isLoading } = useTokenAddressBalance(chainId, tokenAddress)\n\n if (isLoading && tokenAddress) {\n return (\n <Skeleton variant=\"text\" width={72} sx={{ fontSize: footerFontSize }} />\n )\n }\n\n if (!token?.amount) {\n return null\n }\n\n const tokenAmount = formatTokenAmount(token.amount, token.decimals)\n\n return (\n <BalanceContainer>\n <FooterText title={tokenAmount}>\n {t('format.tokenAmount', { value: tokenAmount })}\n </FooterText>\n <AccountBalanceWalletOutlinedIcon\n sx={{ fontSize: 16, color: 'text.secondary' }}\n />\n </BalanceContainer>\n )\n }\n)\n"],"mappings":";;;;;;;;;;;;AAYA,MAAa,iBAA4D,MACtE,EAAE,eAAkD;CACnD,MAAM,EAAE,MAAM,eAAe;CAC7B,MAAM,CAAC,SAAS,gBAAgB,eAC9B,cAAc,YAAY,QAAQ,GAClC,cAAc,YAAY,QAAQ,CACpC;CAEA,MAAM,EAAE,OAAO,cAAc,uBAAuB,SAAS,YAAY;CAEzE,IAAI,aAAa,cACf,OACE,oBAAC,UAAD;EAAU,SAAQ;EAAO,OAAO;EAAI,IAAI,EAAE,UAAA,GAAyB;CAAI,CAAA;CAI3E,IAAI,CAAC,OAAO,QACV,OAAO;CAGT,MAAM,cAAc,kBAAkB,MAAM,QAAQ,MAAM,QAAQ;CAElE,OACE,qBAAC,kBAAD,EAAA,UAAA,CACE,oBAAC,YAAD;EAAY,OAAO;EAChB,UAAA,EAAE,sBAAsB,EAAE,OAAO,YAAY,CAAC;CACrC,CAAA,GACZ,oBAAC,kCAAD,EACE,IAAI;EAAE,UAAU;EAAI,OAAO;CAAiB,EAC7C,CAAA,CACe,EAAA,CAAA;AAEtB,CACF"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"FiatValueToggle.js","names":[],"sources":["../../../../src/components/AmountInputCard/FiatValueToggle.tsx"],"sourcesContent":["import SwapVertIcon from '@mui/icons-material/SwapVert'\nimport { type JSX, memo } from 'react'\nimport { useTranslation } from 'react-i18next'\nimport { useToken } from '../../hooks/useToken.js'\nimport type { FormTypeProps } from '../../stores/form/types.js'\nimport { FormKeyHelper } from '../../stores/form/types.js'\nimport { useFieldValues } from '../../stores/form/useFieldValues.js'\nimport { useInputModeStore } from '../../stores/inputMode/useInputModeStore.js'\nimport { formatTokenPrice } from '../../utils/format.js'\nimport { FooterText, ToggleButton } from './AmountInputCard.style.js'\n\nexport const FiatValueToggle: React.NamedExoticComponent<FormTypeProps> = memo(\n ({ formType }: FormTypeProps): JSX.Element => {\n const { t } = useTranslation()\n const [chainId, tokenAddress, amount] = useFieldValues(\n FormKeyHelper.getChainKey(formType),\n FormKeyHelper.getTokenKey(formType),\n FormKeyHelper.getAmountKey(formType)\n )\n\n const { token } = useToken(chainId, tokenAddress)\n const { inputMode, toggleInputMode } = useInputModeStore()\n const currentInputMode = inputMode[formType]\n\n const handleToggle = (e: React.MouseEvent): void => {\n e.stopPropagation()\n toggleInputMode(formType)\n }\n\n const canToggle = !!token?.priceUSD\n\n const displayValue =\n currentInputMode === 'amount'\n ? t('format.currency', {\n value: formatTokenPrice(amount, token?.priceUSD, token?.decimals),\n })\n : t('format.tokenAmount', { value: amount || '0' })\n\n return (\n <ToggleButton\n clickable={canToggle}\n onClick={canToggle ? handleToggle : undefined}\n aria-label={canToggle ? 'Toggle fiat value' : undefined}\n >\n <FooterText>{displayValue}</FooterText>\n {currentInputMode === 'price' && token?.symbol ? (\n <FooterText>{token.symbol}</FooterText>\n ) : null}\n {canToggle ? (\n <SwapVertIcon sx={{ fontSize: 14, color: 'text.secondary' }} />\n ) : null}\n </ToggleButton>\n )\n }\n)\n"],"mappings":";;;;;;;;;;;AAWA,MAAa,kBAA6D,MACvE,EAAE,eAA2C;CAC5C,MAAM,EAAE,MAAM,eAAe;CAC7B,MAAM,CAAC,SAAS,cAAc,UAAU,eACtC,cAAc,YAAY,QAAQ,GAClC,cAAc,YAAY,QAAQ,GAClC,cAAc,aAAa,QAAQ,CACrC;CAEA,MAAM,EAAE,UAAU,SAAS,SAAS,YAAY;CAChD,MAAM,EAAE,WAAW,oBAAoB,kBAAkB;CACzD,MAAM,mBAAmB,UAAU;CAEnC,MAAM,gBAAgB,MAA8B;EAClD,EAAE,gBAAgB;EAClB,gBAAgB,QAAQ;CAC1B;CAEA,MAAM,YAAY,CAAC,CAAC,OAAO;CAE3B,MAAM,eACJ,qBAAqB,WACjB,EAAE,mBAAmB,EACnB,OAAO,iBAAiB,QAAQ,OAAO,UAAU,OAAO,QAAQ,EAClE,CAAC,IACD,EAAE,sBAAsB,EAAE,OAAO,UAAU,IAAI,CAAC;CAEtD,OACE,qBAAC,cAAD;EACE,WAAW;EACX,SAAS,YAAY,eAAe,KAAA;EACpC,cAAY,YAAY,sBAAsB,KAAA;
|
|
1
|
+
{"version":3,"file":"FiatValueToggle.js","names":[],"sources":["../../../../src/components/AmountInputCard/FiatValueToggle.tsx"],"sourcesContent":["import SwapVertIcon from '@mui/icons-material/SwapVert'\nimport { type JSX, memo } from 'react'\nimport { useTranslation } from 'react-i18next'\nimport { useToken } from '../../hooks/useToken.js'\nimport type { FormTypeProps } from '../../stores/form/types.js'\nimport { FormKeyHelper } from '../../stores/form/types.js'\nimport { useFieldValues } from '../../stores/form/useFieldValues.js'\nimport { useInputModeStore } from '../../stores/inputMode/useInputModeStore.js'\nimport { formatTokenPrice } from '../../utils/format.js'\nimport { FooterText, ToggleButton } from './AmountInputCard.style.js'\n\nexport const FiatValueToggle: React.NamedExoticComponent<FormTypeProps> = memo(\n ({ formType }: FormTypeProps): JSX.Element => {\n const { t } = useTranslation()\n const [chainId, tokenAddress, amount] = useFieldValues(\n FormKeyHelper.getChainKey(formType),\n FormKeyHelper.getTokenKey(formType),\n FormKeyHelper.getAmountKey(formType)\n )\n\n const { token } = useToken(chainId, tokenAddress)\n const { inputMode, toggleInputMode } = useInputModeStore()\n const currentInputMode = inputMode[formType]\n\n const handleToggle = (e: React.MouseEvent): void => {\n e.stopPropagation()\n toggleInputMode(formType)\n }\n\n const canToggle = !!token?.priceUSD\n\n const displayValue =\n currentInputMode === 'amount'\n ? t('format.currency', {\n value: formatTokenPrice(amount, token?.priceUSD, token?.decimals),\n })\n : t('format.tokenAmount', { value: amount || '0' })\n\n return (\n <ToggleButton\n clickable={canToggle}\n onClick={canToggle ? handleToggle : undefined}\n aria-label={canToggle ? 'Toggle fiat value' : undefined}\n >\n <FooterText>{displayValue}</FooterText>\n {currentInputMode === 'price' && token?.symbol ? (\n <FooterText>{token.symbol}</FooterText>\n ) : null}\n {canToggle ? (\n <SwapVertIcon sx={{ fontSize: 14, color: 'text.secondary' }} />\n ) : null}\n </ToggleButton>\n )\n }\n)\n"],"mappings":";;;;;;;;;;;AAWA,MAAa,kBAA6D,MACvE,EAAE,eAA2C;CAC5C,MAAM,EAAE,MAAM,eAAe;CAC7B,MAAM,CAAC,SAAS,cAAc,UAAU,eACtC,cAAc,YAAY,QAAQ,GAClC,cAAc,YAAY,QAAQ,GAClC,cAAc,aAAa,QAAQ,CACrC;CAEA,MAAM,EAAE,UAAU,SAAS,SAAS,YAAY;CAChD,MAAM,EAAE,WAAW,oBAAoB,kBAAkB;CACzD,MAAM,mBAAmB,UAAU;CAEnC,MAAM,gBAAgB,MAA8B;EAClD,EAAE,gBAAgB;EAClB,gBAAgB,QAAQ;CAC1B;CAEA,MAAM,YAAY,CAAC,CAAC,OAAO;CAE3B,MAAM,eACJ,qBAAqB,WACjB,EAAE,mBAAmB,EACnB,OAAO,iBAAiB,QAAQ,OAAO,UAAU,OAAO,QAAQ,EAClE,CAAC,IACD,EAAE,sBAAsB,EAAE,OAAO,UAAU,IAAI,CAAC;CAEtD,OACE,qBAAC,cAAD;EACE,WAAW;EACX,SAAS,YAAY,eAAe,KAAA;EACpC,cAAY,YAAY,sBAAsB,KAAA;EAHhD,UAAA;GAKE,oBAAC,YAAD,EAAA,UAAa,aAAyB,CAAA;GACrC,qBAAqB,WAAW,OAAO,SACtC,oBAAC,YAAD,EAAA,UAAa,MAAM,OAAmB,CAAA,IACpC;GACH,YACC,oBAAC,cAAD,EAAc,IAAI;IAAE,UAAU;IAAI,OAAO;GAAiB,EAAI,CAAA,IAC5D;EACQ;;AAElB,CACF"}
|
|
@@ -3,8 +3,8 @@ import { useAvailableChains } from "../../hooks/useAvailableChains.js";
|
|
|
3
3
|
import { useFieldActions } from "../../stores/form/useFieldActions.js";
|
|
4
4
|
import { FormKeyHelper } from "../../stores/form/types.js";
|
|
5
5
|
import { useFieldValues } from "../../stores/form/useFieldValues.js";
|
|
6
|
-
import { useGasRecommendation } from "../../hooks/useGasRecommendation.js";
|
|
7
6
|
import { useTokenAddressBalance } from "../../hooks/useTokenAddressBalance.js";
|
|
7
|
+
import { useMaxSendAmount } from "../../hooks/useMaxSendAmount.js";
|
|
8
8
|
import { useLinkedLimitFields } from "../../hooks/useLinkedLimitFields.js";
|
|
9
9
|
import { Chip, ChipContainer } from "./PercentageChips.style.js";
|
|
10
10
|
import { formatUnits } from "@lifi/sdk";
|
|
@@ -24,30 +24,19 @@ const PercentageChips = memo(({ formType }) => {
|
|
|
24
24
|
const [chainId, tokenAddress] = useFieldValues(FormKeyHelper.getChainKey(formType), FormKeyHelper.getTokenKey(formType));
|
|
25
25
|
const chain = getChainById(chainId);
|
|
26
26
|
const { account } = useAccount({ chainType: chain?.chainType });
|
|
27
|
-
const { data } = useGasRecommendation(chainId);
|
|
28
27
|
const { token } = useTokenAddressBalance(chainId, tokenAddress);
|
|
29
|
-
const
|
|
30
|
-
if (!token?.amount) return 0n;
|
|
31
|
-
let maxAmount = token.amount;
|
|
32
|
-
if (chain?.nativeToken.address === tokenAddress && data?.recommended) {
|
|
33
|
-
const recommendedAmount = BigInt(data.recommended.amount);
|
|
34
|
-
if (token.amount > recommendedAmount) maxAmount = token.amount - recommendedAmount;
|
|
35
|
-
}
|
|
36
|
-
return maxAmount;
|
|
37
|
-
};
|
|
28
|
+
const maxAmount = useMaxSendAmount(chainId, tokenAddress);
|
|
38
29
|
const applyAmount = (value) => {
|
|
39
30
|
if (mode === "limit") setSendAmount(value);
|
|
40
31
|
else setFieldValue(amountKey, value, { isTouched: true });
|
|
41
32
|
};
|
|
42
33
|
const handlePercentage = (percentage) => {
|
|
43
|
-
const maxAmount = getMaxAmount();
|
|
44
34
|
if (maxAmount && token?.decimals) {
|
|
45
35
|
const percentageAmount = maxAmount * BigInt(percentage) / 100n;
|
|
46
36
|
applyAmount(formatUnits(percentageAmount, token.decimals));
|
|
47
37
|
}
|
|
48
38
|
};
|
|
49
39
|
const handleMax = () => {
|
|
50
|
-
const maxAmount = getMaxAmount();
|
|
51
40
|
if (maxAmount && token?.decimals) applyAmount(formatUnits(maxAmount, token.decimals));
|
|
52
41
|
};
|
|
53
42
|
if (formType !== "from" || isDisabled || !token || !account?.isConnected) return null;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"PercentageChips.js","names":[],"sources":["../../../../src/components/AmountInputCard/PercentageChips.tsx"],"sourcesContent":["import { formatUnits } from '@lifi/sdk'\nimport { useAccount } from '@lifi/wallet-management'\nimport { type JSX, memo } from 'react'\nimport { useTranslation } from 'react-i18next'\nimport { useAvailableChains } from '../../hooks/useAvailableChains.js'\nimport {
|
|
1
|
+
{"version":3,"file":"PercentageChips.js","names":[],"sources":["../../../../src/components/AmountInputCard/PercentageChips.tsx"],"sourcesContent":["import { formatUnits } from '@lifi/sdk'\nimport { useAccount } from '@lifi/wallet-management'\nimport { type JSX, memo } from 'react'\nimport { useTranslation } from 'react-i18next'\nimport { useAvailableChains } from '../../hooks/useAvailableChains.js'\nimport { useLinkedLimitFields } from '../../hooks/useLinkedLimitFields.js'\nimport { useMaxSendAmount } from '../../hooks/useMaxSendAmount.js'\nimport { useTokenAddressBalance } from '../../hooks/useTokenAddressBalance.js'\nimport { useWidgetConfig } from '../../providers/WidgetProvider/WidgetProvider.js'\nimport type { FormTypeProps } from '../../stores/form/types.js'\nimport { FormKeyHelper } from '../../stores/form/types.js'\nimport { useFieldActions } from '../../stores/form/useFieldActions.js'\nimport { useFieldValues } from '../../stores/form/useFieldValues.js'\nimport type { DisabledUIConfig } from '../../types/widget.js'\nimport { Chip, ChipContainer } from './PercentageChips.style.js'\n\nexport const PercentageChips: React.NamedExoticComponent<FormTypeProps> = memo(\n ({ formType }: FormTypeProps): JSX.Element | null => {\n const { t } = useTranslation()\n const { getChainById } = useAvailableChains()\n const { setFieldValue } = useFieldActions()\n const { disabledUI, mode } = useWidgetConfig()\n const { setSendAmount } = useLinkedLimitFields()\n\n const amountKey = FormKeyHelper.getAmountKey(formType)\n const isDisabled = !!disabledUI?.[amountKey as keyof DisabledUIConfig]\n\n const [chainId, tokenAddress] = useFieldValues(\n FormKeyHelper.getChainKey(formType),\n FormKeyHelper.getTokenKey(formType)\n )\n\n const chain = getChainById(chainId)\n const { account } = useAccount({ chainType: chain?.chainType })\n\n const { token } = useTokenAddressBalance(chainId, tokenAddress)\n const maxAmount = useMaxSendAmount(chainId, tokenAddress)\n\n // In limit mode the send amount must flow through the linked-field\n // derivation so the receive amount recomputes; otherwise it is a plain\n // form-field write.\n const applyAmount = (value: string): void => {\n if (mode === 'limit') {\n setSendAmount(value)\n } else {\n setFieldValue(amountKey, value, { isTouched: true })\n }\n }\n\n const handlePercentage = (percentage: number): void => {\n if (maxAmount && token?.decimals) {\n const percentageAmount = (maxAmount * BigInt(percentage)) / 100n\n applyAmount(formatUnits(percentageAmount, token.decimals))\n }\n }\n\n const handleMax = (): void => {\n if (maxAmount && token?.decimals) {\n applyAmount(formatUnits(maxAmount, token.decimals))\n }\n }\n\n if (formType !== 'from' || isDisabled || !token || !account?.isConnected) {\n return null\n }\n\n return (\n <ChipContainer>\n <Chip data-delay=\"0\" onClick={() => handlePercentage(25)}>\n 25%\n </Chip>\n <Chip data-delay=\"1\" onClick={() => handlePercentage(50)}>\n 50%\n </Chip>\n <Chip data-delay=\"2\" onClick={() => handlePercentage(75)}>\n 75%\n </Chip>\n <Chip data-delay=\"3\" onClick={handleMax}>\n {t('button.max')}\n </Chip>\n </ChipContainer>\n )\n }\n)\n"],"mappings":";;;;;;;;;;;;;;;AAgBA,MAAa,kBAA6D,MACvE,EAAE,eAAkD;CACnD,MAAM,EAAE,MAAM,eAAe;CAC7B,MAAM,EAAE,iBAAiB,mBAAmB;CAC5C,MAAM,EAAE,kBAAkB,gBAAgB;CAC1C,MAAM,EAAE,YAAY,SAAS,gBAAgB;CAC7C,MAAM,EAAE,kBAAkB,qBAAqB;CAE/C,MAAM,YAAY,cAAc,aAAa,QAAQ;CACrD,MAAM,aAAa,CAAC,CAAC,aAAa;CAElC,MAAM,CAAC,SAAS,gBAAgB,eAC9B,cAAc,YAAY,QAAQ,GAClC,cAAc,YAAY,QAAQ,CACpC;CAEA,MAAM,QAAQ,aAAa,OAAO;CAClC,MAAM,EAAE,YAAY,WAAW,EAAE,WAAW,OAAO,UAAU,CAAC;CAE9D,MAAM,EAAE,UAAU,uBAAuB,SAAS,YAAY;CAC9D,MAAM,YAAY,iBAAiB,SAAS,YAAY;CAKxD,MAAM,eAAe,UAAwB;EAC3C,IAAI,SAAS,SACX,cAAc,KAAK;OAEnB,cAAc,WAAW,OAAO,EAAE,WAAW,KAAK,CAAC;CAEvD;CAEA,MAAM,oBAAoB,eAA6B;EACrD,IAAI,aAAa,OAAO,UAAU;GAChC,MAAM,mBAAoB,YAAY,OAAO,UAAU,IAAK;GAC5D,YAAY,YAAY,kBAAkB,MAAM,QAAQ,CAAC;EAC3D;CACF;CAEA,MAAM,kBAAwB;EAC5B,IAAI,aAAa,OAAO,UACtB,YAAY,YAAY,WAAW,MAAM,QAAQ,CAAC;CAEtD;CAEA,IAAI,aAAa,UAAU,cAAc,CAAC,SAAS,CAAC,SAAS,aAC3D,OAAO;CAGT,OACE,qBAAC,eAAD,EAAA,UAAA;EACE,oBAAC,MAAD;GAAM,cAAW;GAAI,eAAe,iBAAiB,EAAE;GAAG,UAAA;EAEpD,CAAA;EACN,oBAAC,MAAD;GAAM,cAAW;GAAI,eAAe,iBAAiB,EAAE;GAAG,UAAA;EAEpD,CAAA;EACN,oBAAC,MAAD;GAAM,cAAW;GAAI,eAAe,iBAAiB,EAAE;GAAG,UAAA;EAEpD,CAAA;EACN,oBAAC,MAAD;GAAM,cAAW;GAAI,SAAS;GAC3B,UAAA,EAAE,YAAY;EACX,CAAA;CACO,EAAA,CAAA;AAEnB,CACF"}
|
|
@@ -8,7 +8,7 @@ const revealStagger = Object.fromEntries(Array.from({ length: chipCount }, (_, i
|
|
|
8
8
|
opacity: 1,
|
|
9
9
|
transform: "scale(1) translateX(0)",
|
|
10
10
|
pointerEvents: "auto",
|
|
11
|
-
transitionDelay: `${(
|
|
11
|
+
transitionDelay: `${(3 - index) * staggerStepMs}ms`
|
|
12
12
|
},
|
|
13
13
|
[`.${cardClasses.root}:not(:hover) &`]: { transitionDelay: `${index * staggerStepMs}ms` }
|
|
14
14
|
}]));
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"PercentageChips.style.js","names":[],"sources":["../../../../src/components/AmountInputCard/PercentageChips.style.tsx"],"sourcesContent":["import { Box, Button, styled } from '@mui/material'\nimport { cardClasses } from '@mui/material/Card'\nimport type React from 'react'\n\nconst chipCount = 4\nconst staggerStepMs = 25\n\nconst revealStagger = Object.fromEntries(\n Array.from({ length: chipCount }, (_, index) => [\n `&[data-delay=\"${index}\"]`,\n {\n [`.${cardClasses.root}:hover &`]: {\n opacity: 1,\n transform: 'scale(1) translateX(0)',\n pointerEvents: 'auto',\n transitionDelay: `${(chipCount - 1 - index) * staggerStepMs}ms`,\n },\n [`.${cardClasses.root}:not(:hover) &`]: {\n transitionDelay: `${index * staggerStepMs}ms`,\n },\n },\n ])\n)\n\nexport const ChipContainer: React.FC<React.ComponentProps<typeof Box>> = styled(\n Box\n)(({ theme }) => ({\n display: 'flex',\n gap: theme.spacing(0.5),\n}))\n\nexport const Chip: React.FC<React.ComponentProps<typeof Button>> = styled(\n Button\n)(({ theme }) => ({\n minWidth: 0,\n padding: theme.spacing(0.5, 1.5),\n fontSize: 12,\n fontWeight: 700,\n lineHeight: 1.3334,\n backgroundColor: `color-mix(in srgb, ${theme.vars.palette.common.onBackground} 4%, transparent)`,\n color: theme.vars.palette.text.primary,\n transition:\n 'opacity 200ms cubic-bezier(0.4, 0, 0.2, 1), transform 200ms cubic-bezier(0.4, 0, 0.2, 1), background-color 200ms ease',\n '&:hover': {\n backgroundColor: `color-mix(in srgb, ${theme.vars.palette.common.onBackground} 8%, transparent)`,\n },\n // Reveal-on-hover — only on devices that support hover. On touch there is no\n // hover, so the chips stay permanently visible (the default above) instead of\n // becoming an unreachable dead row.\n '@media (hover: hover)': {\n opacity: 0,\n transform: 'scale(0.85) translateX(10px)',\n pointerEvents: 'none',\n ...revealStagger,\n '@media (prefers-reduced-motion: reduce)': {\n transform: 'none !important',\n transitionDelay: '0ms !important',\n },\n },\n}))\n"],"mappings":";;;AAIA,MAAM,YAAY;AAClB,MAAM,gBAAgB;AAEtB,MAAM,gBAAgB,OAAO,YAC3B,MAAM,KAAK,EAAE,QAAQ,UAAU,IAAI,GAAG,UAAU,CAC9C,iBAAiB,MAAM,KACvB;EACG,IAAI,YAAY,KAAK,YAAY;EAChC,SAAS;EACT,WAAW;EACX,eAAe;EACf,iBAAiB,IAAI,
|
|
1
|
+
{"version":3,"file":"PercentageChips.style.js","names":[],"sources":["../../../../src/components/AmountInputCard/PercentageChips.style.tsx"],"sourcesContent":["import { Box, Button, styled } from '@mui/material'\nimport { cardClasses } from '@mui/material/Card'\nimport type React from 'react'\n\nconst chipCount = 4\nconst staggerStepMs = 25\n\nconst revealStagger = Object.fromEntries(\n Array.from({ length: chipCount }, (_, index) => [\n `&[data-delay=\"${index}\"]`,\n {\n [`.${cardClasses.root}:hover &`]: {\n opacity: 1,\n transform: 'scale(1) translateX(0)',\n pointerEvents: 'auto',\n transitionDelay: `${(chipCount - 1 - index) * staggerStepMs}ms`,\n },\n [`.${cardClasses.root}:not(:hover) &`]: {\n transitionDelay: `${index * staggerStepMs}ms`,\n },\n },\n ])\n)\n\nexport const ChipContainer: React.FC<React.ComponentProps<typeof Box>> = styled(\n Box\n)(({ theme }) => ({\n display: 'flex',\n gap: theme.spacing(0.5),\n}))\n\nexport const Chip: React.FC<React.ComponentProps<typeof Button>> = styled(\n Button\n)(({ theme }) => ({\n minWidth: 0,\n padding: theme.spacing(0.5, 1.5),\n fontSize: 12,\n fontWeight: 700,\n lineHeight: 1.3334,\n backgroundColor: `color-mix(in srgb, ${theme.vars.palette.common.onBackground} 4%, transparent)`,\n color: theme.vars.palette.text.primary,\n transition:\n 'opacity 200ms cubic-bezier(0.4, 0, 0.2, 1), transform 200ms cubic-bezier(0.4, 0, 0.2, 1), background-color 200ms ease',\n '&:hover': {\n backgroundColor: `color-mix(in srgb, ${theme.vars.palette.common.onBackground} 8%, transparent)`,\n },\n // Reveal-on-hover — only on devices that support hover. On touch there is no\n // hover, so the chips stay permanently visible (the default above) instead of\n // becoming an unreachable dead row.\n '@media (hover: hover)': {\n opacity: 0,\n transform: 'scale(0.85) translateX(10px)',\n pointerEvents: 'none',\n ...revealStagger,\n '@media (prefers-reduced-motion: reduce)': {\n transform: 'none !important',\n transitionDelay: '0ms !important',\n },\n },\n}))\n"],"mappings":";;;AAIA,MAAM,YAAY;AAClB,MAAM,gBAAgB;AAEtB,MAAM,gBAAgB,OAAO,YAC3B,MAAM,KAAK,EAAE,QAAQ,UAAU,IAAI,GAAG,UAAU,CAC9C,iBAAiB,MAAM,KACvB;EACG,IAAI,YAAY,KAAK,YAAY;EAChC,SAAS;EACT,WAAW;EACX,eAAe;EACf,iBAAiB,IAAI,IAAgB,SAAS,cAAc;CAC9D;EACC,IAAI,YAAY,KAAK,kBAAkB,EACtC,iBAAiB,GAAG,QAAQ,cAAc,IAC5C;AACF,CACF,CAAC,CACH;AAEA,MAAa,gBAA4D,OACvE,GACF,CAAC,EAAE,EAAE,aAAa;CAChB,SAAS;CACT,KAAK,MAAM,QAAQ,EAAG;AACxB,EAAE;AAEF,MAAa,OAAsD,OACjE,MACF,CAAC,EAAE,EAAE,aAAa;CAChB,UAAU;CACV,SAAS,MAAM,QAAQ,IAAK,GAAG;CAC/B,UAAU;CACV,YAAY;CACZ,YAAY;CACZ,iBAAiB,sBAAsB,MAAM,KAAK,QAAQ,OAAO,aAAa;CAC9E,OAAO,MAAM,KAAK,QAAQ,KAAK;CAC/B,YACE;CACF,WAAW,EACT,iBAAiB,sBAAsB,MAAM,KAAK,QAAQ,OAAO,aAAa,mBAChF;CAIA,yBAAyB;EACvB,SAAS;EACT,WAAW;EACX,eAAe;EACf,GAAG;EACH,2CAA2C;GACzC,WAAW;GACX,iBAAiB;EACnB;CACF;AACF,EAAE"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"ReceiveAmountCard.js","names":["InfoOutlinedIcon"],"sources":["../../../../src/components/AmountInputCard/ReceiveAmountCard.tsx"],"sourcesContent":["import type { Route } from '@lifi/sdk'\nimport InfoOutlinedIcon from '@mui/icons-material/InfoOutlined'\nimport SwapVertIcon from '@mui/icons-material/SwapVert'\nimport type { CardProps } from '@mui/material'\nimport { Box, Skeleton, Tooltip } from '@mui/material'\nimport { type JSX, type ReactNode, useLayoutEffect, useRef } from 'react'\nimport { useTranslation } from 'react-i18next'\nimport { useRoutes } from '../../hooks/useRoutes.js'\nimport { useWidgetConfig } from '../../providers/WidgetProvider/WidgetProvider.js'\nimport { useFieldValues } from '../../stores/form/useFieldValues.js'\nimport { useInputModeStore } from '../../stores/inputMode/useInputModeStore.js'\nimport { formatTokenAmount, formatTokenPrice } from '../../utils/format.js'\nimport { getPriceImpact } from '../../utils/getPriceImpact.js'\nimport { fitInputText } from '../../utils/input.js'\nimport { CardTitle } from '../Card/CardTitle.js'\nimport { ProgressToNextUpdate } from '../ProgressToNextUpdate.js'\nimport { TokenPillButton } from '../TokenPillButton/TokenPillButton.js'\nimport {\n AmountCard,\n AmountDisplay,\n amountHeight,\n CardBodyRow,\n CardFooterRow,\n CardHeaderRow,\n FooterText,\n footerFontSize,\n maxInputFontSize,\n minInputFontSize,\n ToggleButton,\n} from './AmountInputCard.style.js'\n\nconst formType = 'to' as const\n\ntype ReceiveCardProps = CardProps & { mask?: boolean }\n\nconst ReceiveAmountCardLayout = ({\n cardProps,\n title,\n headerEnd,\n amount,\n footerStart,\n footerEnd,\n}: {\n cardProps: ReceiveCardProps\n title: string\n headerEnd?: ReactNode\n amount: ReactNode\n footerStart: ReactNode\n footerEnd?: ReactNode\n}): JSX.Element => (\n <AmountCard {...cardProps} formType={formType}>\n <CardHeaderRow>\n <CardTitle sx={{ padding: 0 }}>{title}</CardTitle>\n {headerEnd}\n </CardHeaderRow>\n <CardBodyRow>\n {amount}\n <TokenPillButton formType={formType} />\n </CardBodyRow>\n <CardFooterRow>\n {footerStart}\n {footerEnd}\n </CardFooterRow>\n </AmountCard>\n)\n\nconst PriceImpactBadge = ({\n priceImpact,\n}: {\n priceImpact: number | undefined\n}): JSX.Element | null => {\n const { t } = useTranslation()\n if (priceImpact === undefined) {\n return null\n }\n return (\n <Box sx={{ display: 'flex', alignItems: 'center', gap: 0.5 }}>\n <FooterText>\n {t('format.percent', { value: priceImpact, usePlusSign: true })}\n </FooterText>\n <Tooltip title={t('tooltip.priceImpact')}>\n <InfoOutlinedIcon\n sx={{ fontSize: 16, color: 'text.secondary', cursor: 'help' }}\n />\n </Tooltip>\n </Box>\n )\n}\n\nconst useReceivePriceImpact = (\n route: Route | undefined\n): number | undefined => {\n const { hiddenUI } = useWidgetConfig()\n if (!route || hiddenUI?.routeCardPriceImpact) {\n return undefined\n }\n return getPriceImpact({\n fromAmount: BigInt(route.fromAmount),\n toAmount: BigInt(route.toAmount),\n fromToken: route.fromToken,\n toToken: route.toToken,\n })\n}\n\n/**\n * The receive amount is a read-only quote derived from the best route, with a\n * fiat/token toggle and price impact in the footer. In limit mode the amount is\n * still the quote for the current limit (the limit price drives it via the\n * dedicated price card); it is never edited here, and the header shows the\n * refetch progress indicator with a \"Buy\" title.\n */\nexport const ReceiveAmountCard: React.FC<ReceiveCardProps> = (\n props\n): JSX.Element => {\n const { t } = useTranslation()\n const amountRef = useRef<HTMLSpanElement>(null)\n const { inputMode, toggleInputMode } = useInputModeStore()\n const showFiat = inputMode[formType] === 'price'\n const { hiddenUI, mode } = useWidgetConfig()\n const isLimit = mode === 'limit'\n\n const [selectedRouteId] = useFieldValues('selectedRouteId')\n const { routes, isFetching, dataUpdatedAt, refetchTime, refetch } =\n useRoutes()\n // Reflect the route the user selected in the routes list (falling back to the\n // best route), so the buy amount matches the highlighted provider card.\n const route = routes?.find((r) => r.id === selectedRouteId) ?? routes?.[0]\n const priceImpact = useReceivePriceImpact(route)\n const showPriceImpact = !hiddenUI?.routeCardPriceImpact\n\n const receiveAmount = route?.toAmount\n ? formatTokenAmount(BigInt(route.toAmount), route.toToken.decimals)\n : undefined\n // Only show skeletons on the initial fetch.\n const showSkeleton = isFetching && !receiveAmount\n\n const fiatValue =\n receiveAmount && route?.toToken.priceUSD\n ? formatTokenPrice(receiveAmount, route.toToken.priceUSD)\n : 0\n const canToggle = !!receiveAmount && !!route?.toToken.priceUSD\n\n const mainDisplay = showFiat\n ? t('format.currency', { value: fiatValue })\n : t('format.tokenAmount', { value: receiveAmount || '0' })\n const footerDisplay = showFiat\n ? t('format.tokenAmount', { value: receiveAmount || '0' })\n : t('format.currency', { value: fiatValue })\n\n // biome-ignore lint/correctness/useExhaustiveDependencies: effect must run on value change\n useLayoutEffect(() => {\n if (amountRef.current) {\n fitInputText(maxInputFontSize, minInputFontSize, amountRef.current)\n }\n }, [mainDisplay])\n\n return (\n <ReceiveAmountCardLayout\n cardProps={props}\n title={isLimit ? t('header.buy') : t('header.receive')}\n headerEnd={\n isLimit && (isFetching || routes?.length) ? (\n <ProgressToNextUpdate\n updatedAt={dataUpdatedAt || Date.now()}\n timeToUpdate={refetchTime}\n isLoading={isFetching}\n onClick={() => refetch()}\n sx={{ padding: 0 }}\n />\n ) : undefined\n }\n amount={\n showSkeleton ? (\n <Skeleton variant=\"rounded\" height={amountHeight} sx={{ flex: 1 }} />\n ) : (\n <AmountDisplay\n ref={amountRef}\n sx={{ color: 'text.primary', opacity: receiveAmount ? 1 : 0.5 }}\n >\n {mainDisplay}\n </AmountDisplay>\n )\n }\n footerStart={\n showSkeleton ? (\n <Skeleton\n variant=\"text\"\n width={72}\n sx={{ fontSize: footerFontSize }}\n />\n ) : (\n <ToggleButton\n clickable={canToggle}\n onClick={canToggle ? () => toggleInputMode(formType) : undefined}\n aria-label={canToggle ? 'Toggle fiat value' : undefined}\n >\n <FooterText>{footerDisplay}</FooterText>\n {canToggle ? (\n <SwapVertIcon sx={{ fontSize: 14, color: 'text.secondary' }} />\n ) : null}\n </ToggleButton>\n )\n }\n footerEnd={\n showSkeleton ? (\n showPriceImpact ? (\n <Skeleton\n variant=\"text\"\n width={56}\n sx={{ fontSize: footerFontSize }}\n />\n ) : null\n ) : (\n <PriceImpactBadge priceImpact={priceImpact} />\n )\n }\n />\n )\n}\n"],"mappings":";;;;;;;;;;;;;;;;;;AA+BA,MAAM,WAAW;AAIjB,MAAM,2BAA2B,EAC/B,WACA,OACA,WACA,QACA,aACA,gBASA,qBAAC,YAAD;CAAY,GAAI;CAAqB;WAArC;EACE,qBAAC,eAAD,EAAA,UAAA,CACE,oBAAC,WAAD;GAAW,IAAI,EAAE,SAAS,EAAE;aAAI;EAAiB,CAAA,GAChD,SACY,EAAA,CAAA;EACf,qBAAC,aAAD,EAAA,UAAA,CACG,QACD,oBAAC,iBAAD,EAA2B,SAAW,CAAA,CAC3B,EAAA,CAAA;EACb,qBAAC,eAAD,EAAA,UAAA,CACG,aACA,SACY,EAAA,CAAA;CACL;;AAGd,MAAM,oBAAoB,EACxB,kBAGwB;CACxB,MAAM,EAAE,MAAM,eAAe;CAC7B,IAAI,gBAAgB,KAAA,GAClB,OAAO;CAET,OACE,qBAAC,KAAD;EAAK,IAAI;GAAE,SAAS;GAAQ,YAAY;GAAU,KAAK;EAAI;YAA3D,CACE,oBAAC,YAAD,EAAA,UACG,EAAE,kBAAkB;GAAE,OAAO;GAAa,aAAa;EAAK,CAAC,EACpD,CAAA,GACZ,oBAAC,SAAD;GAAS,OAAO,EAAE,qBAAqB;aACrC,oBAACA,cAAD,EACE,IAAI;IAAE,UAAU;IAAI,OAAO;IAAkB,QAAQ;GAAO,EAC7D,CAAA;EACM,CAAA,CACN;;AAET;AAEA,MAAM,yBACJ,UACuB;CACvB,MAAM,EAAE,aAAa,gBAAgB;CACrC,IAAI,CAAC,SAAS,UAAU,sBACtB;CAEF,OAAO,eAAe;EACpB,YAAY,OAAO,MAAM,UAAU;EACnC,UAAU,OAAO,MAAM,QAAQ;EAC/B,WAAW,MAAM;EACjB,SAAS,MAAM;CACjB,CAAC;AACH;;;;;;;;AASA,MAAa,qBACX,UACgB;CAChB,MAAM,EAAE,MAAM,eAAe;CAC7B,MAAM,YAAY,OAAwB,IAAI;CAC9C,MAAM,EAAE,WAAW,oBAAoB,kBAAkB;CACzD,MAAM,WAAW,UAAU,cAAc;CACzC,MAAM,EAAE,UAAU,SAAS,gBAAgB;CAC3C,MAAM,UAAU,SAAS;CAEzB,MAAM,CAAC,mBAAmB,eAAe,iBAAiB;CAC1D,MAAM,EAAE,QAAQ,YAAY,eAAe,aAAa,YACtD,UAAU;CAGZ,MAAM,QAAQ,QAAQ,MAAM,MAAM,EAAE,OAAO,eAAe,KAAK,SAAS;CACxE,MAAM,cAAc,sBAAsB,KAAK;CAC/C,MAAM,kBAAkB,CAAC,UAAU;CAEnC,MAAM,gBAAgB,OAAO,WACzB,kBAAkB,OAAO,MAAM,QAAQ,GAAG,MAAM,QAAQ,QAAQ,IAChE,KAAA;CAEJ,MAAM,eAAe,cAAc,CAAC;CAEpC,MAAM,YACJ,iBAAiB,OAAO,QAAQ,WAC5B,iBAAiB,eAAe,MAAM,QAAQ,QAAQ,IACtD;CACN,MAAM,YAAY,CAAC,CAAC,iBAAiB,CAAC,CAAC,OAAO,QAAQ;CAEtD,MAAM,cAAc,WAChB,EAAE,mBAAmB,EAAE,OAAO,UAAU,CAAC,IACzC,EAAE,sBAAsB,EAAE,OAAO,iBAAiB,IAAI,CAAC;CAC3D,MAAM,gBAAgB,WAClB,EAAE,sBAAsB,EAAE,OAAO,iBAAiB,IAAI,CAAC,IACvD,EAAE,mBAAmB,EAAE,OAAO,UAAU,CAAC;CAG7C,sBAAsB;EACpB,IAAI,UAAU,SACZ,aAAA,IAAA,IAAiD,UAAU,OAAO;CAEtE,GAAG,CAAC,WAAW,CAAC;CAEhB,OACE,oBAAC,yBAAD;EACE,WAAW;EACX,OAAO,UAAU,EAAE,YAAY,IAAI,EAAE,gBAAgB;EACrD,WACE,YAAY,cAAc,QAAQ,UAChC,oBAAC,sBAAD;GACE,WAAW,iBAAiB,KAAK,IAAI;GACrC,cAAc;GACd,WAAW;GACX,eAAe,QAAQ;GACvB,IAAI,EAAE,SAAS,EAAE;EAClB,CAAA,IACC,KAAA;EAEN,QACE,eACE,oBAAC,UAAD;GAAU,SAAQ;GAAU,QAAA;GAAsB,IAAI,EAAE,MAAM,EAAE;EAAI,CAAA,IAEpE,oBAAC,eAAD;GACE,KAAK;GACL,IAAI;IAAE,OAAO;IAAgB,SAAS,gBAAgB,IAAI;GAAI;aAE7D;EACY,CAAA;EAGnB,aACE,eACE,oBAAC,UAAD;GACE,SAAQ;GACR,OAAO;GACP,IAAI,EAAE,UAAA,GAAyB;EAChC,CAAA,IAED,qBAAC,cAAD;GACE,WAAW;GACX,SAAS,kBAAkB,gBAAgB,QAAQ,IAAI,KAAA;GACvD,cAAY,YAAY,sBAAsB,KAAA;aAHhD,CAKE,oBAAC,YAAD,EAAA,UAAa,cAA0B,CAAA,GACtC,YACC,oBAAC,cAAD,EAAc,IAAI;IAAE,UAAU;IAAI,OAAO;GAAiB,EAAI,CAAA,IAC5D,IACQ;;EAGlB,WACE,eACE,kBACE,oBAAC,UAAD;GACE,SAAQ;GACR,OAAO;GACP,IAAI,EAAE,UAAA,GAAyB;EAChC,CAAA,IACC,OAEJ,oBAAC,kBAAD,EAA+B,YAAc,CAAA;CAGlD,CAAA;AAEL"}
|
|
1
|
+
{"version":3,"file":"ReceiveAmountCard.js","names":["InfoOutlinedIcon"],"sources":["../../../../src/components/AmountInputCard/ReceiveAmountCard.tsx"],"sourcesContent":["import type { Route } from '@lifi/sdk'\nimport InfoOutlinedIcon from '@mui/icons-material/InfoOutlined'\nimport SwapVertIcon from '@mui/icons-material/SwapVert'\nimport type { CardProps } from '@mui/material'\nimport { Box, Skeleton, Tooltip } from '@mui/material'\nimport { type JSX, type ReactNode, useLayoutEffect, useRef } from 'react'\nimport { useTranslation } from 'react-i18next'\nimport { useRoutes } from '../../hooks/useRoutes.js'\nimport { useWidgetConfig } from '../../providers/WidgetProvider/WidgetProvider.js'\nimport { useFieldValues } from '../../stores/form/useFieldValues.js'\nimport { useInputModeStore } from '../../stores/inputMode/useInputModeStore.js'\nimport { formatTokenAmount, formatTokenPrice } from '../../utils/format.js'\nimport { getPriceImpact } from '../../utils/getPriceImpact.js'\nimport { fitInputText } from '../../utils/input.js'\nimport { CardTitle } from '../Card/CardTitle.js'\nimport { ProgressToNextUpdate } from '../ProgressToNextUpdate.js'\nimport { TokenPillButton } from '../TokenPillButton/TokenPillButton.js'\nimport {\n AmountCard,\n AmountDisplay,\n amountHeight,\n CardBodyRow,\n CardFooterRow,\n CardHeaderRow,\n FooterText,\n footerFontSize,\n maxInputFontSize,\n minInputFontSize,\n ToggleButton,\n} from './AmountInputCard.style.js'\n\nconst formType = 'to' as const\n\ntype ReceiveCardProps = CardProps & { mask?: boolean }\n\nconst ReceiveAmountCardLayout = ({\n cardProps,\n title,\n headerEnd,\n amount,\n footerStart,\n footerEnd,\n}: {\n cardProps: ReceiveCardProps\n title: string\n headerEnd?: ReactNode\n amount: ReactNode\n footerStart: ReactNode\n footerEnd?: ReactNode\n}): JSX.Element => (\n <AmountCard {...cardProps} formType={formType}>\n <CardHeaderRow>\n <CardTitle sx={{ padding: 0 }}>{title}</CardTitle>\n {headerEnd}\n </CardHeaderRow>\n <CardBodyRow>\n {amount}\n <TokenPillButton formType={formType} />\n </CardBodyRow>\n <CardFooterRow>\n {footerStart}\n {footerEnd}\n </CardFooterRow>\n </AmountCard>\n)\n\nconst PriceImpactBadge = ({\n priceImpact,\n}: {\n priceImpact: number | undefined\n}): JSX.Element | null => {\n const { t } = useTranslation()\n if (priceImpact === undefined) {\n return null\n }\n return (\n <Box sx={{ display: 'flex', alignItems: 'center', gap: 0.5 }}>\n <FooterText>\n {t('format.percent', { value: priceImpact, usePlusSign: true })}\n </FooterText>\n <Tooltip title={t('tooltip.priceImpact')}>\n <InfoOutlinedIcon\n sx={{ fontSize: 16, color: 'text.secondary', cursor: 'help' }}\n />\n </Tooltip>\n </Box>\n )\n}\n\nconst useReceivePriceImpact = (\n route: Route | undefined\n): number | undefined => {\n const { hiddenUI } = useWidgetConfig()\n if (!route || hiddenUI?.routeCardPriceImpact) {\n return undefined\n }\n return getPriceImpact({\n fromAmount: BigInt(route.fromAmount),\n toAmount: BigInt(route.toAmount),\n fromToken: route.fromToken,\n toToken: route.toToken,\n })\n}\n\n/**\n * The receive amount is a read-only quote derived from the best route, with a\n * fiat/token toggle and price impact in the footer. In limit mode the amount is\n * still the quote for the current limit (the limit price drives it via the\n * dedicated price card); it is never edited here, and the header shows the\n * refetch progress indicator with a \"Buy\" title.\n */\nexport const ReceiveAmountCard: React.FC<ReceiveCardProps> = (\n props\n): JSX.Element => {\n const { t } = useTranslation()\n const amountRef = useRef<HTMLSpanElement>(null)\n const { inputMode, toggleInputMode } = useInputModeStore()\n const showFiat = inputMode[formType] === 'price'\n const { hiddenUI, mode } = useWidgetConfig()\n const isLimit = mode === 'limit'\n\n const [selectedRouteId] = useFieldValues('selectedRouteId')\n const { routes, isFetching, dataUpdatedAt, refetchTime, refetch } =\n useRoutes()\n // Reflect the route the user selected in the routes list (falling back to the\n // best route), so the buy amount matches the highlighted provider card.\n const route = routes?.find((r) => r.id === selectedRouteId) ?? routes?.[0]\n const priceImpact = useReceivePriceImpact(route)\n const showPriceImpact = !hiddenUI?.routeCardPriceImpact\n\n const receiveAmount = route?.toAmount\n ? formatTokenAmount(BigInt(route.toAmount), route.toToken.decimals)\n : undefined\n // Only show skeletons on the initial fetch.\n const showSkeleton = isFetching && !receiveAmount\n\n const fiatValue =\n receiveAmount && route?.toToken.priceUSD\n ? formatTokenPrice(receiveAmount, route.toToken.priceUSD)\n : 0\n const canToggle = !!receiveAmount && !!route?.toToken.priceUSD\n\n const mainDisplay = showFiat\n ? t('format.currency', { value: fiatValue })\n : t('format.tokenAmount', { value: receiveAmount || '0' })\n const footerDisplay = showFiat\n ? t('format.tokenAmount', { value: receiveAmount || '0' })\n : t('format.currency', { value: fiatValue })\n\n // biome-ignore lint/correctness/useExhaustiveDependencies: effect must run on value change\n useLayoutEffect(() => {\n if (amountRef.current) {\n fitInputText(maxInputFontSize, minInputFontSize, amountRef.current)\n }\n }, [mainDisplay])\n\n return (\n <ReceiveAmountCardLayout\n cardProps={props}\n title={isLimit ? t('header.buy') : t('header.receive')}\n headerEnd={\n isLimit && (isFetching || routes?.length) ? (\n <ProgressToNextUpdate\n updatedAt={dataUpdatedAt || Date.now()}\n timeToUpdate={refetchTime}\n isLoading={isFetching}\n onClick={() => refetch()}\n sx={{ padding: 0 }}\n />\n ) : undefined\n }\n amount={\n showSkeleton ? (\n <Skeleton variant=\"rounded\" height={amountHeight} sx={{ flex: 1 }} />\n ) : (\n <AmountDisplay\n ref={amountRef}\n sx={{ color: 'text.primary', opacity: receiveAmount ? 1 : 0.5 }}\n >\n {mainDisplay}\n </AmountDisplay>\n )\n }\n footerStart={\n showSkeleton ? (\n <Skeleton\n variant=\"text\"\n width={72}\n sx={{ fontSize: footerFontSize }}\n />\n ) : (\n <ToggleButton\n clickable={canToggle}\n onClick={canToggle ? () => toggleInputMode(formType) : undefined}\n aria-label={canToggle ? 'Toggle fiat value' : undefined}\n >\n <FooterText>{footerDisplay}</FooterText>\n {canToggle ? (\n <SwapVertIcon sx={{ fontSize: 14, color: 'text.secondary' }} />\n ) : null}\n </ToggleButton>\n )\n }\n footerEnd={\n showSkeleton ? (\n showPriceImpact ? (\n <Skeleton\n variant=\"text\"\n width={56}\n sx={{ fontSize: footerFontSize }}\n />\n ) : null\n ) : (\n <PriceImpactBadge priceImpact={priceImpact} />\n )\n }\n />\n )\n}\n"],"mappings":"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"}
|
|
@@ -40,15 +40,19 @@ const SendAmountCard = (props) => {
|
|
|
40
40
|
};
|
|
41
41
|
const title = mode === "limit" ? t("header.sell") : mode === "custom" && modeOptions?.custom?.type === "deposit" ? t("header.deposit") : t("header.send");
|
|
42
42
|
let displayValue;
|
|
43
|
-
if (isEditingRef.current)
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
else
|
|
43
|
+
if (isEditingRef.current) {
|
|
44
|
+
if (currentInputMode === "price") displayValue = formattedPriceInput;
|
|
45
|
+
else displayValue = value;
|
|
46
|
+
} else if (currentInputMode === "price") {
|
|
47
|
+
const priceValue = formatTokenPrice(value, token?.priceUSD);
|
|
48
|
+
displayValue = formatInputAmount(priceValue.toFixed(2), 2);
|
|
49
|
+
} else displayValue = value;
|
|
47
50
|
const handleChange = (event) => {
|
|
48
51
|
const { value: inputValue } = event.target;
|
|
49
52
|
isEditingRef.current = true;
|
|
50
53
|
if (currentInputMode === "price") {
|
|
51
|
-
const
|
|
54
|
+
const cleanInputValue = inputValue.replace("$", "");
|
|
55
|
+
const formattedValue = formatInputAmount(cleanInputValue, 2, true);
|
|
52
56
|
const tokenValue = priceToTokenAmount(formattedValue, token?.priceUSD);
|
|
53
57
|
setFormattedPriceInput(formattedValue);
|
|
54
58
|
applyFromAmount(tokenValue);
|
|
@@ -61,7 +65,10 @@ const SendAmountCard = (props) => {
|
|
|
61
65
|
const { value: inputValue } = event.target;
|
|
62
66
|
isEditingRef.current = false;
|
|
63
67
|
if (currentInputMode === "price") {
|
|
64
|
-
const
|
|
68
|
+
const cleanInputValue = inputValue.replace("$", "");
|
|
69
|
+
const formattedValue = formatInputAmount(cleanInputValue, 2);
|
|
70
|
+
const tokenValue = priceToTokenAmount(formattedValue, token?.priceUSD);
|
|
71
|
+
const formattedAmount = formatInputAmount(tokenValue, token?.decimals);
|
|
65
72
|
applyFromAmount(formattedAmount);
|
|
66
73
|
} else {
|
|
67
74
|
const formattedValue = formatInputAmount(inputValue, token?.decimals);
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"SendAmountCard.js","names":[],"sources":["../../../../src/components/AmountInputCard/SendAmountCard.tsx"],"sourcesContent":["import type { CardProps } from '@mui/material'\nimport type { ChangeEvent, JSX } from 'react'\nimport { useLayoutEffect, useRef, useState } from 'react'\nimport { useTranslation } from 'react-i18next'\nimport { useLinkedLimitFields } from '../../hooks/useLinkedLimitFields.js'\nimport { useToken } from '../../hooks/useToken.js'\nimport { useWidgetConfig } from '../../providers/WidgetProvider/WidgetProvider.js'\nimport { FormKeyHelper } from '../../stores/form/types.js'\nimport { useFieldActions } from '../../stores/form/useFieldActions.js'\nimport { useFieldValues } from '../../stores/form/useFieldValues.js'\nimport { useInputModeStore } from '../../stores/inputMode/useInputModeStore.js'\nimport {\n formatInputAmount,\n formatTokenPrice,\n priceToTokenAmount,\n usdDecimals,\n} from '../../utils/format.js'\nimport { fitInputText } from '../../utils/input.js'\nimport { CardTitle } from '../Card/CardTitle.js'\nimport { TokenPillButton } from '../TokenPillButton/TokenPillButton.js'\nimport {\n AmountCard,\n CardBodyRow,\n CardFooterRow,\n CardHeaderRow,\n LargeInput,\n maxInputFontSize,\n minInputFontSize,\n} from './AmountInputCard.style.js'\nimport { BalanceDisplay } from './BalanceDisplay.js'\nimport { FiatValueToggle } from './FiatValueToggle.js'\nimport { PercentageChips } from './PercentageChips.js'\n\nexport const SendAmountCard: React.FC<CardProps & { mask?: boolean }> = (\n props\n): JSX.Element => {\n const { t } = useTranslation()\n const { disabledUI, mode, modeOptions } = useWidgetConfig()\n const ref = useRef<HTMLInputElement>(null)\n const isEditingRef = useRef(false)\n const [formattedPriceInput, setFormattedPriceInput] = useState('')\n\n const formType = 'from' as const\n\n const [chainId, tokenAddress, value] = useFieldValues(\n FormKeyHelper.getChainKey(formType),\n FormKeyHelper.getTokenKey(formType),\n FormKeyHelper.getAmountKey(formType)\n )\n\n const { token } = useToken(chainId, tokenAddress)\n const { setFieldValue } = useFieldActions()\n const { inputMode } = useInputModeStore()\n const { setSendAmount } = useLinkedLimitFields()\n const currentInputMode = inputMode[formType]\n const disabled = disabledUI?.fromAmount\n\n // In limit mode the send amount drives the linked receive amount; otherwise\n // it is a plain form-field write.\n const applyFromAmount = (value: string): void => {\n if (mode === 'limit') {\n setSendAmount(value)\n } else {\n setFieldValue('fromAmount', value, { isDirty: true, isTouched: true })\n }\n }\n\n const title =\n mode === 'limit'\n ? t('header.sell')\n : mode === 'custom' && modeOptions?.custom?.type === 'deposit'\n ? t('header.deposit')\n : t('header.send')\n\n let displayValue: string\n if (isEditingRef.current) {\n if (currentInputMode === 'price') {\n displayValue = formattedPriceInput\n } else {\n displayValue = value as string\n }\n } else {\n if (currentInputMode === 'price') {\n const priceValue = formatTokenPrice(value as string, token?.priceUSD)\n displayValue = formatInputAmount(\n priceValue.toFixed(usdDecimals),\n usdDecimals\n )\n } else {\n displayValue = value as string\n }\n }\n\n const handleChange = (\n event: ChangeEvent<HTMLInputElement | HTMLTextAreaElement>\n ): void => {\n const { value: inputValue } = event.target\n isEditingRef.current = true\n\n if (currentInputMode === 'price') {\n const cleanInputValue = inputValue.replace('$', '')\n const formattedValue = formatInputAmount(\n cleanInputValue,\n usdDecimals,\n true\n )\n const tokenValue = priceToTokenAmount(formattedValue, token?.priceUSD)\n setFormattedPriceInput(formattedValue)\n applyFromAmount(tokenValue)\n } else {\n const formattedValue = formatInputAmount(\n inputValue,\n token?.decimals,\n true\n )\n applyFromAmount(formattedValue)\n }\n }\n\n const handleBlur = (\n event: ChangeEvent<HTMLInputElement | HTMLTextAreaElement>\n ): void => {\n const { value: inputValue } = event.target\n isEditingRef.current = false\n\n if (currentInputMode === 'price') {\n const cleanInputValue = inputValue.replace('$', '')\n const formattedValue = formatInputAmount(cleanInputValue, usdDecimals)\n const tokenValue = priceToTokenAmount(formattedValue, token?.priceUSD)\n const formattedAmount = formatInputAmount(tokenValue, token?.decimals)\n applyFromAmount(formattedAmount)\n } else {\n const formattedValue = formatInputAmount(inputValue, token?.decimals)\n applyFromAmount(formattedValue)\n }\n }\n\n // biome-ignore lint/correctness/useExhaustiveDependencies: effect must run on value change\n useLayoutEffect(() => {\n if (ref.current) {\n fitInputText(maxInputFontSize, minInputFontSize, ref.current)\n }\n }, [displayValue])\n\n return (\n <AmountCard {...props} formType={formType}>\n <CardHeaderRow>\n <CardTitle sx={{ padding: 0 }}>{title}</CardTitle>\n <PercentageChips formType={formType} />\n </CardHeaderRow>\n <CardBodyRow>\n <LargeInput\n inputRef={ref}\n size=\"small\"\n autoComplete=\"off\"\n placeholder={currentInputMode === 'price' ? '$0' : '0'}\n inputProps={{ inputMode: 'decimal' }}\n onChange={handleChange}\n onBlur={handleBlur}\n value={\n currentInputMode === 'price'\n ? displayValue\n ? `$${displayValue}`\n : ''\n : displayValue\n }\n name=\"fromAmount\"\n disabled={disabled}\n required\n />\n <TokenPillButton formType={formType} />\n </CardBodyRow>\n <CardFooterRow>\n <FiatValueToggle formType={formType} />\n <BalanceDisplay formType={formType} />\n </CardFooterRow>\n </AmountCard>\n )\n}\n"],"mappings":";;;;;;;;;;;;;;;;;;;AAiCA,MAAa,kBACX,UACgB;CAChB,MAAM,EAAE,MAAM,eAAe;CAC7B,MAAM,EAAE,YAAY,MAAM,gBAAgB,gBAAgB;CAC1D,MAAM,MAAM,OAAyB,IAAI;CACzC,MAAM,eAAe,OAAO,KAAK;CACjC,MAAM,CAAC,qBAAqB,0BAA0B,SAAS,EAAE;CAEjE,MAAM,WAAW;CAEjB,MAAM,CAAC,SAAS,cAAc,SAAS,eACrC,cAAc,YAAY,QAAQ,GAClC,cAAc,YAAY,QAAQ,GAClC,cAAc,aAAa,QAAQ,CACrC;CAEA,MAAM,EAAE,UAAU,SAAS,SAAS,YAAY;CAChD,MAAM,EAAE,kBAAkB,gBAAgB;CAC1C,MAAM,EAAE,cAAc,kBAAkB;CACxC,MAAM,EAAE,kBAAkB,qBAAqB;CAC/C,MAAM,mBAAmB,UAAU;CACnC,MAAM,WAAW,YAAY;CAI7B,MAAM,mBAAmB,UAAwB;EAC/C,IAAI,SAAS,SACX,cAAc,KAAK;OAEnB,cAAc,cAAc,OAAO;GAAE,SAAS;GAAM,WAAW;EAAK,CAAC;CAEzE;CAEA,MAAM,QACJ,SAAS,UACL,EAAE,aAAa,IACf,SAAS,YAAY,aAAa,QAAQ,SAAS,YACjD,EAAE,gBAAgB,IAClB,EAAE,aAAa;CAEvB,IAAI;CACJ,IAAI,aAAa,
|
|
1
|
+
{"version":3,"file":"SendAmountCard.js","names":[],"sources":["../../../../src/components/AmountInputCard/SendAmountCard.tsx"],"sourcesContent":["import type { CardProps } from '@mui/material'\nimport type { ChangeEvent, JSX } from 'react'\nimport { useLayoutEffect, useRef, useState } from 'react'\nimport { useTranslation } from 'react-i18next'\nimport { useLinkedLimitFields } from '../../hooks/useLinkedLimitFields.js'\nimport { useToken } from '../../hooks/useToken.js'\nimport { useWidgetConfig } from '../../providers/WidgetProvider/WidgetProvider.js'\nimport { FormKeyHelper } from '../../stores/form/types.js'\nimport { useFieldActions } from '../../stores/form/useFieldActions.js'\nimport { useFieldValues } from '../../stores/form/useFieldValues.js'\nimport { useInputModeStore } from '../../stores/inputMode/useInputModeStore.js'\nimport {\n formatInputAmount,\n formatTokenPrice,\n priceToTokenAmount,\n usdDecimals,\n} from '../../utils/format.js'\nimport { fitInputText } from '../../utils/input.js'\nimport { CardTitle } from '../Card/CardTitle.js'\nimport { TokenPillButton } from '../TokenPillButton/TokenPillButton.js'\nimport {\n AmountCard,\n CardBodyRow,\n CardFooterRow,\n CardHeaderRow,\n LargeInput,\n maxInputFontSize,\n minInputFontSize,\n} from './AmountInputCard.style.js'\nimport { BalanceDisplay } from './BalanceDisplay.js'\nimport { FiatValueToggle } from './FiatValueToggle.js'\nimport { PercentageChips } from './PercentageChips.js'\n\nexport const SendAmountCard: React.FC<CardProps & { mask?: boolean }> = (\n props\n): JSX.Element => {\n const { t } = useTranslation()\n const { disabledUI, mode, modeOptions } = useWidgetConfig()\n const ref = useRef<HTMLInputElement>(null)\n const isEditingRef = useRef(false)\n const [formattedPriceInput, setFormattedPriceInput] = useState('')\n\n const formType = 'from' as const\n\n const [chainId, tokenAddress, value] = useFieldValues(\n FormKeyHelper.getChainKey(formType),\n FormKeyHelper.getTokenKey(formType),\n FormKeyHelper.getAmountKey(formType)\n )\n\n const { token } = useToken(chainId, tokenAddress)\n const { setFieldValue } = useFieldActions()\n const { inputMode } = useInputModeStore()\n const { setSendAmount } = useLinkedLimitFields()\n const currentInputMode = inputMode[formType]\n const disabled = disabledUI?.fromAmount\n\n // In limit mode the send amount drives the linked receive amount; otherwise\n // it is a plain form-field write.\n const applyFromAmount = (value: string): void => {\n if (mode === 'limit') {\n setSendAmount(value)\n } else {\n setFieldValue('fromAmount', value, { isDirty: true, isTouched: true })\n }\n }\n\n const title =\n mode === 'limit'\n ? t('header.sell')\n : mode === 'custom' && modeOptions?.custom?.type === 'deposit'\n ? t('header.deposit')\n : t('header.send')\n\n let displayValue: string\n if (isEditingRef.current) {\n if (currentInputMode === 'price') {\n displayValue = formattedPriceInput\n } else {\n displayValue = value as string\n }\n } else {\n if (currentInputMode === 'price') {\n const priceValue = formatTokenPrice(value as string, token?.priceUSD)\n displayValue = formatInputAmount(\n priceValue.toFixed(usdDecimals),\n usdDecimals\n )\n } else {\n displayValue = value as string\n }\n }\n\n const handleChange = (\n event: ChangeEvent<HTMLInputElement | HTMLTextAreaElement>\n ): void => {\n const { value: inputValue } = event.target\n isEditingRef.current = true\n\n if (currentInputMode === 'price') {\n const cleanInputValue = inputValue.replace('$', '')\n const formattedValue = formatInputAmount(\n cleanInputValue,\n usdDecimals,\n true\n )\n const tokenValue = priceToTokenAmount(formattedValue, token?.priceUSD)\n setFormattedPriceInput(formattedValue)\n applyFromAmount(tokenValue)\n } else {\n const formattedValue = formatInputAmount(\n inputValue,\n token?.decimals,\n true\n )\n applyFromAmount(formattedValue)\n }\n }\n\n const handleBlur = (\n event: ChangeEvent<HTMLInputElement | HTMLTextAreaElement>\n ): void => {\n const { value: inputValue } = event.target\n isEditingRef.current = false\n\n if (currentInputMode === 'price') {\n const cleanInputValue = inputValue.replace('$', '')\n const formattedValue = formatInputAmount(cleanInputValue, usdDecimals)\n const tokenValue = priceToTokenAmount(formattedValue, token?.priceUSD)\n const formattedAmount = formatInputAmount(tokenValue, token?.decimals)\n applyFromAmount(formattedAmount)\n } else {\n const formattedValue = formatInputAmount(inputValue, token?.decimals)\n applyFromAmount(formattedValue)\n }\n }\n\n // biome-ignore lint/correctness/useExhaustiveDependencies: effect must run on value change\n useLayoutEffect(() => {\n if (ref.current) {\n fitInputText(maxInputFontSize, minInputFontSize, ref.current)\n }\n }, [displayValue])\n\n return (\n <AmountCard {...props} formType={formType}>\n <CardHeaderRow>\n <CardTitle sx={{ padding: 0 }}>{title}</CardTitle>\n <PercentageChips formType={formType} />\n </CardHeaderRow>\n <CardBodyRow>\n <LargeInput\n inputRef={ref}\n size=\"small\"\n autoComplete=\"off\"\n placeholder={currentInputMode === 'price' ? '$0' : '0'}\n inputProps={{ inputMode: 'decimal' }}\n onChange={handleChange}\n onBlur={handleBlur}\n value={\n currentInputMode === 'price'\n ? displayValue\n ? `$${displayValue}`\n : ''\n : displayValue\n }\n name=\"fromAmount\"\n disabled={disabled}\n required\n />\n <TokenPillButton formType={formType} />\n </CardBodyRow>\n <CardFooterRow>\n <FiatValueToggle formType={formType} />\n <BalanceDisplay formType={formType} />\n </CardFooterRow>\n </AmountCard>\n )\n}\n"],"mappings":"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"}
|