@lifi/widget 4.1.0 → 4.2.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/AppDefault.js +14 -0
- package/dist/esm/AppDefault.js.map +1 -1
- package/dist/esm/components/AmountInput/AmountInput.js +2 -1
- package/dist/esm/components/AmountInput/AmountInput.js.map +1 -1
- package/dist/esm/components/AmountInput/AmountInputEndAdornment.js +4 -2
- package/dist/esm/components/AmountInput/AmountInputEndAdornment.js.map +1 -1
- package/dist/esm/components/AmountInput/AmountInputEndAdornment.style.js +1 -1
- package/dist/esm/components/AmountInput/AmountInputEndAdornment.style.js.map +1 -1
- package/dist/esm/components/AmountInput/PriceFormHelperText.js +4 -2
- package/dist/esm/components/AmountInput/PriceFormHelperText.js.map +1 -1
- package/dist/esm/components/AmountInputCard/AmountInputCard.style.js +98 -0
- package/dist/esm/components/AmountInputCard/AmountInputCard.style.js.map +1 -0
- package/dist/esm/components/AmountInputCard/AmountInputCardPair.js +25 -0
- package/dist/esm/components/AmountInputCard/AmountInputCardPair.js.map +1 -0
- package/dist/esm/components/AmountInputCard/BalanceDisplay.js +35 -0
- package/dist/esm/components/AmountInputCard/BalanceDisplay.js.map +1 -0
- package/dist/esm/components/AmountInputCard/BalanceDisplay.style.js +11 -0
- package/dist/esm/components/AmountInputCard/BalanceDisplay.style.js.map +1 -0
- package/dist/esm/components/AmountInputCard/FiatValueToggle.js +41 -0
- package/dist/esm/components/AmountInputCard/FiatValueToggle.js.map +1 -0
- package/dist/esm/components/AmountInputCard/PercentageChips.js +80 -0
- package/dist/esm/components/AmountInputCard/PercentageChips.js.map +1 -0
- package/dist/esm/components/AmountInputCard/PercentageChips.style.js +43 -0
- package/dist/esm/components/AmountInputCard/PercentageChips.style.js.map +1 -0
- package/dist/esm/components/AmountInputCard/ReceiveAmountCard.js +137 -0
- package/dist/esm/components/AmountInputCard/ReceiveAmountCard.js.map +1 -0
- package/dist/esm/components/AmountInputCard/SendAmountCard.js +102 -0
- package/dist/esm/components/AmountInputCard/SendAmountCard.js.map +1 -0
- package/dist/esm/components/Avatar/Avatar.js +12 -3
- package/dist/esm/components/Avatar/Avatar.js.map +1 -1
- package/dist/esm/components/Chains/VirtualizedChainList.js +2 -1
- package/dist/esm/components/Chains/VirtualizedChainList.js.map +1 -1
- package/dist/esm/components/Header/HeaderNavigationTabs.js +14 -1
- package/dist/esm/components/Header/HeaderNavigationTabs.js.map +1 -1
- package/dist/esm/components/IconCircle/IconCircle.style.js +1 -1
- package/dist/esm/components/LimitOrderSettings/LimitOrderSettings.js +99 -0
- package/dist/esm/components/LimitOrderSettings/LimitOrderSettings.js.map +1 -0
- package/dist/esm/components/LimitOrderSettings/LimitOrderSettings.style.js +52 -0
- package/dist/esm/components/LimitOrderSettings/LimitOrderSettings.style.js.map +1 -0
- package/dist/esm/components/LimitPriceCard/LimitPriceCard.js +115 -0
- package/dist/esm/components/LimitPriceCard/LimitPriceCard.js.map +1 -0
- package/dist/esm/components/LimitPriceCard/LimitPriceCard.style.js +89 -0
- package/dist/esm/components/LimitPriceCard/LimitPriceCard.style.js.map +1 -0
- package/dist/esm/components/LimitPriceCard/LimitPricePresets.js +91 -0
- package/dist/esm/components/LimitPriceCard/LimitPricePresets.js.map +1 -0
- package/dist/esm/components/RouteCard/RouteProviderCard.js +118 -0
- package/dist/esm/components/RouteCard/RouteProviderCard.js.map +1 -0
- package/dist/esm/components/Routes/LimitOrderRoutes.js +34 -0
- package/dist/esm/components/Routes/LimitOrderRoutes.js.map +1 -0
- package/dist/esm/components/Routes/Routes.js +2 -2
- package/dist/esm/components/Routes/Routes.js.map +1 -1
- package/dist/esm/components/SettingsPanel/SettingsPanel.js +51 -0
- package/dist/esm/components/SettingsPanel/SettingsPanel.js.map +1 -0
- package/dist/esm/components/SettingsPanel/SettingsPanel.style.js +33 -0
- package/dist/esm/components/SettingsPanel/SettingsPanel.style.js.map +1 -0
- package/dist/esm/components/SettingsPanel/utils.js +14 -0
- package/dist/esm/components/SettingsPanel/utils.js.map +1 -0
- package/dist/esm/components/SwapButton/SwapButton.js +50 -0
- package/dist/esm/components/SwapButton/SwapButton.js.map +1 -0
- package/dist/esm/components/SwapButton/SwapButton.style.js +24 -0
- package/dist/esm/components/SwapButton/SwapButton.style.js.map +1 -0
- package/dist/esm/components/TokenPillButton/TokenPillButton.js +52 -0
- package/dist/esm/components/TokenPillButton/TokenPillButton.js.map +1 -0
- package/dist/esm/components/TokenPillButton/TokenPillButton.style.js +39 -0
- package/dist/esm/components/TokenPillButton/TokenPillButton.style.js.map +1 -0
- 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/useChainSearch.js +2 -1
- package/dist/esm/hooks/useChainSearch.js.map +1 -1
- package/dist/esm/hooks/useLimitMarketRate.js +24 -0
- package/dist/esm/hooks/useLimitMarketRate.js.map +1 -0
- package/dist/esm/hooks/useLinkedLimitFields.js +49 -0
- package/dist/esm/hooks/useLinkedLimitFields.js.map +1 -0
- package/dist/esm/hooks/useRoutes.js +23 -6
- package/dist/esm/hooks/useRoutes.js.map +1 -1
- package/dist/esm/hooks/useTokens.js +16 -14
- package/dist/esm/hooks/useTokens.js.map +1 -1
- package/dist/esm/hooks/useWideVariant.js +5 -2
- package/dist/esm/hooks/useWideVariant.js.map +1 -1
- package/dist/esm/i18n/en.json +22 -0
- package/dist/esm/index.d.ts +2 -2
- package/dist/esm/pages/MainPage/LimitPageContent.js +23 -0
- package/dist/esm/pages/MainPage/LimitPageContent.js.map +1 -0
- package/dist/esm/pages/MainPage/MainPage.js +19 -22
- package/dist/esm/pages/MainPage/MainPage.js.map +1 -1
- package/dist/esm/pages/MainPage/MainPageActions.js +28 -0
- package/dist/esm/pages/MainPage/MainPageActions.js.map +1 -0
- package/dist/esm/pages/MainPage/ReviewButton.js +9 -2
- package/dist/esm/pages/MainPage/ReviewButton.js.map +1 -1
- package/dist/esm/pages/RoutePriorityPage.js +48 -0
- package/dist/esm/pages/RoutePriorityPage.js.map +1 -0
- package/dist/esm/pages/SettingsPage/BridgeAndExchangeSettings.js +2 -2
- package/dist/esm/pages/SettingsPage/BridgeAndExchangeSettings.js.map +1 -1
- package/dist/esm/pages/SettingsPage/RoutePrioritySettings.js +12 -27
- package/dist/esm/pages/SettingsPage/RoutePrioritySettings.js.map +1 -1
- package/dist/esm/pages/SettingsPage/SlippageSettings/SlippagePage.js +133 -0
- package/dist/esm/pages/SettingsPage/SlippageSettings/SlippagePage.js.map +1 -0
- package/dist/esm/pages/SettingsPage/SlippageSettings/SlippageSettings.js +14 -72
- package/dist/esm/pages/SettingsPage/SlippageSettings/SlippageSettings.js.map +1 -1
- package/dist/esm/pages/SettingsPage/SlippageSettings/SlippageSettings.style.js +26 -14
- package/dist/esm/pages/SettingsPage/SlippageSettings/SlippageSettings.style.js.map +1 -1
- package/dist/esm/pages/SettingsPage/ThemeSettings.js +4 -0
- package/dist/esm/pages/SettingsPage/ThemeSettings.js.map +1 -1
- package/dist/esm/pages/TransactionPage/TransactionReview.js +4 -1
- package/dist/esm/pages/TransactionPage/TransactionReview.js.map +1 -1
- package/dist/esm/providers/I18nProvider/I18nProvider.js +1 -1
- package/dist/esm/providers/I18nProvider/enResource.d.ts +1 -1
- package/dist/esm/providers/I18nProvider/enResource.js +1 -1
- package/dist/esm/providers/I18nProvider/types.d.ts +2 -2
- package/dist/esm/providers/SDKClientProvider.js +25 -24
- package/dist/esm/providers/SDKClientProvider.js.map +1 -1
- package/dist/esm/providers/WidgetProvider/WidgetProvider.js +22 -21
- package/dist/esm/providers/WidgetProvider/WidgetProvider.js.map +1 -1
- package/dist/esm/stores/form/URLSearchParamsBuilder.js +14 -3
- package/dist/esm/stores/form/URLSearchParamsBuilder.js.map +1 -1
- package/dist/esm/stores/form/createFormStore.js +6 -2
- package/dist/esm/stores/form/createFormStore.js.map +1 -1
- package/dist/esm/stores/form/getDefaultValuesFromQueryString.js +3 -0
- package/dist/esm/stores/form/getDefaultValuesFromQueryString.js.map +1 -1
- package/dist/esm/stores/form/types.d.ts +9 -1
- package/dist/esm/stores/form/types.d.ts.map +1 -1
- package/dist/esm/stores/form/types.js.map +1 -1
- package/dist/esm/stores/form/useClearAmountFields.js +1 -0
- package/dist/esm/stores/form/useClearAmountFields.js.map +1 -1
- package/dist/esm/stores/navigationTabs/useNavigationTabsStore.js +4 -2
- package/dist/esm/stores/navigationTabs/useNavigationTabsStore.js.map +1 -1
- package/dist/esm/stores/navigationTabs/utils.js +38 -8
- package/dist/esm/stores/navigationTabs/utils.js.map +1 -1
- package/dist/esm/types/events.d.ts +10 -1
- package/dist/esm/types/events.d.ts.map +1 -1
- package/dist/esm/types/events.js +2 -0
- package/dist/esm/types/events.js.map +1 -1
- package/dist/esm/types/widget.d.ts +9 -0
- package/dist/esm/types/widget.d.ts.map +1 -1
- package/dist/esm/types/widget.js.map +1 -1
- package/dist/esm/utils/format.d.ts +1 -1
- package/dist/esm/utils/format.d.ts.map +1 -1
- package/dist/esm/utils/format.js +2 -2
- package/dist/esm/utils/format.js.map +1 -1
- package/dist/esm/utils/limitOrder.js +61 -0
- package/dist/esm/utils/limitOrder.js.map +1 -0
- package/dist/esm/utils/navigationRoutes.d.ts +2 -0
- package/dist/esm/utils/navigationRoutes.d.ts.map +1 -1
- package/dist/esm/utils/navigationRoutes.js +6 -0
- package/dist/esm/utils/navigationRoutes.js.map +1 -1
- package/package.json +11 -11
- package/src/AppDefault.tsx +16 -0
- package/src/components/AmountInput/AmountInputEndAdornment.style.ts +1 -1
- package/src/components/AmountInput/AmountInputEndAdornment.tsx +5 -2
- package/src/components/AmountInputCard/AmountInputCard.style.tsx +157 -0
- package/src/components/AmountInputCard/AmountInputCardPair.tsx +25 -0
- package/src/components/AmountInputCard/BalanceDisplay.style.tsx +9 -0
- package/src/components/AmountInputCard/BalanceDisplay.tsx +46 -0
- package/src/components/AmountInputCard/FiatValueToggle.tsx +55 -0
- package/src/components/AmountInputCard/PercentageChips.style.tsx +60 -0
- package/src/components/AmountInputCard/PercentageChips.tsx +100 -0
- package/src/components/AmountInputCard/ReceiveAmountCard.tsx +219 -0
- package/src/components/AmountInputCard/SendAmountCard.tsx +179 -0
- package/src/components/Avatar/Avatar.tsx +8 -3
- package/src/components/Header/HeaderNavigationTabs.tsx +19 -2
- package/src/components/LimitOrderSettings/LimitOrderSettings.style.tsx +69 -0
- package/src/components/LimitOrderSettings/LimitOrderSettings.tsx +124 -0
- package/src/components/LimitPriceCard/LimitPriceCard.style.tsx +103 -0
- package/src/components/LimitPriceCard/LimitPriceCard.tsx +153 -0
- package/src/components/LimitPriceCard/LimitPricePresets.tsx +139 -0
- package/src/components/RouteCard/RouteProviderCard.tsx +113 -0
- package/src/components/Routes/LimitOrderRoutes.tsx +64 -0
- package/src/components/Routes/Routes.tsx +3 -2
- package/src/components/SettingsPanel/SettingsPanel.style.tsx +41 -0
- package/src/components/SettingsPanel/SettingsPanel.tsx +73 -0
- package/src/components/SettingsPanel/utils.ts +27 -0
- package/src/components/SwapButton/SwapButton.style.tsx +28 -0
- package/src/components/SwapButton/SwapButton.tsx +71 -0
- package/src/components/TokenPillButton/TokenPillButton.style.tsx +50 -0
- package/src/components/TokenPillButton/TokenPillButton.tsx +81 -0
- package/src/config/version.ts +1 -1
- package/src/hooks/useLimitMarketRate.ts +39 -0
- package/src/hooks/useLinkedLimitFields.ts +74 -0
- package/src/hooks/useRoutes.ts +45 -4
- package/src/hooks/useWideVariant.ts +8 -2
- package/src/pages/MainPage/LimitPageContent.tsx +18 -0
- package/src/pages/MainPage/MainPage.tsx +43 -30
- package/src/pages/MainPage/MainPageActions.tsx +35 -0
- package/src/pages/MainPage/ReviewButton.tsx +13 -1
- package/src/pages/RoutePriorityPage.tsx +55 -0
- package/src/pages/SettingsPage/RoutePrioritySettings.tsx +14 -38
- package/src/pages/SettingsPage/SlippageSettings/SlippagePage.tsx +176 -0
- package/src/pages/SettingsPage/SlippageSettings/SlippageSettings.style.tsx +32 -25
- package/src/pages/SettingsPage/SlippageSettings/SlippageSettings.tsx +14 -128
- package/src/pages/SettingsPage/ThemeSettings.tsx +4 -0
- package/src/stores/form/URLSearchParamsBuilder.tsx +25 -3
- package/src/stores/form/createFormStore.ts +7 -3
- package/src/stores/form/getDefaultValuesFromQueryString.ts +11 -0
- package/src/stores/form/types.ts +14 -1
- package/src/stores/form/useClearAmountFields.ts +1 -0
- package/src/stores/navigationTabs/types.ts +6 -0
- package/src/stores/navigationTabs/useNavigationTabsStore.tsx +8 -3
- package/src/stores/navigationTabs/utils.ts +67 -5
- package/src/types/events.ts +12 -0
- package/src/types/widget.ts +9 -0
- package/src/utils/format.ts +6 -2
- package/src/utils/limitOrder.ts +88 -0
- package/src/utils/navigationRoutes.ts +6 -0
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
import { useFieldActions } from "../../stores/form/useFieldActions.js";
|
|
2
|
+
import { useFieldValues } from "../../stores/form/useFieldValues.js";
|
|
3
|
+
import { useRoutes } from "../../hooks/useRoutes.js";
|
|
4
|
+
import { useToAddressRequirements } from "../../hooks/useToAddressRequirements.js";
|
|
5
|
+
import { RouteNotFoundCard } from "../RouteCard/RouteNotFoundCard.js";
|
|
6
|
+
import { RouteProviderCard, RouteProviderCardSkeleton } from "../RouteCard/RouteProviderCard.js";
|
|
7
|
+
import { Stack } from "@mui/material";
|
|
8
|
+
import { jsx } from "react/jsx-runtime";
|
|
9
|
+
//#region src/components/Routes/LimitOrderRoutes.tsx
|
|
10
|
+
const LimitOrderRoutes = (props) => {
|
|
11
|
+
const { routes, isLoading, isFetching, isFetched } = useRoutes();
|
|
12
|
+
const [toAddress, selectedRouteId] = useFieldValues("toAddress", "selectedRouteId");
|
|
13
|
+
const { setFieldValue } = useFieldActions();
|
|
14
|
+
const { requiredToAddress } = useToAddressRequirements();
|
|
15
|
+
const currentRoute = routes?.[0];
|
|
16
|
+
if (!currentRoute && !isLoading && !isFetching && !isFetched) return null;
|
|
17
|
+
const allowInteraction = !(currentRoute && requiredToAddress && !toAddress);
|
|
18
|
+
const activeRouteId = routes?.find((route) => route.id === selectedRouteId)?.id ?? currentRoute?.id;
|
|
19
|
+
return /* @__PURE__ */ jsx(Stack, {
|
|
20
|
+
direction: "column",
|
|
21
|
+
spacing: 1,
|
|
22
|
+
sx: props.sx,
|
|
23
|
+
className: props.className,
|
|
24
|
+
children: isLoading && !currentRoute ? Array.from({ length: 2 }).map((_, index) => /* @__PURE__ */ jsx(RouteProviderCardSkeleton, {}, index)) : !currentRoute ? /* @__PURE__ */ jsx(RouteNotFoundCard, {}) : routes?.map((route) => /* @__PURE__ */ jsx(RouteProviderCard, {
|
|
25
|
+
route,
|
|
26
|
+
active: route.id === activeRouteId,
|
|
27
|
+
onClick: allowInteraction ? () => setFieldValue("selectedRouteId", route.id) : void 0
|
|
28
|
+
}, route.id))
|
|
29
|
+
});
|
|
30
|
+
};
|
|
31
|
+
//#endregion
|
|
32
|
+
export { LimitOrderRoutes };
|
|
33
|
+
|
|
34
|
+
//# sourceMappingURL=LimitOrderRoutes.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"LimitOrderRoutes.js","names":[],"sources":["../../../../src/components/Routes/LimitOrderRoutes.tsx"],"sourcesContent":["import { Stack } from '@mui/material'\nimport { useRoutes } from '../../hooks/useRoutes.js'\nimport { useToAddressRequirements } from '../../hooks/useToAddressRequirements.js'\nimport { useFieldActions } from '../../stores/form/useFieldActions.js'\nimport { useFieldValues } from '../../stores/form/useFieldValues.js'\nimport type { CardProps } from '../Card/Card.js'\nimport { RouteNotFoundCard } from '../RouteCard/RouteNotFoundCard.js'\nimport {\n RouteProviderCard,\n RouteProviderCardSkeleton,\n} from '../RouteCard/RouteProviderCard.js'\n\nexport const LimitOrderRoutes: React.FC<CardProps> = (props) => {\n const { routes, isLoading, isFetching, isFetched } = useRoutes()\n const [toAddress, selectedRouteId] = useFieldValues(\n 'toAddress',\n 'selectedRouteId'\n )\n const { setFieldValue } = useFieldActions()\n const { requiredToAddress } = useToAddressRequirements()\n\n const currentRoute = routes?.[0]\n\n if (!currentRoute && !isLoading && !isFetching && !isFetched) {\n return null\n }\n\n const toAddressUnsatisfied = currentRoute && requiredToAddress && !toAddress\n const allowInteraction = !toAddressUnsatisfied\n\n const activeRouteId =\n routes?.find((route) => route.id === selectedRouteId)?.id ??\n currentRoute?.id\n\n return (\n <Stack\n direction=\"column\"\n spacing={1}\n sx={props.sx}\n className={props.className}\n >\n {isLoading && !currentRoute ? (\n Array.from({ length: 2 }).map((_, index) => (\n <RouteProviderCardSkeleton key={index} />\n ))\n ) : !currentRoute ? (\n <RouteNotFoundCard />\n ) : (\n routes?.map((route) => (\n <RouteProviderCard\n key={route.id}\n route={route}\n active={route.id === activeRouteId}\n onClick={\n allowInteraction\n ? () => setFieldValue('selectedRouteId', route.id)\n : undefined\n }\n />\n ))\n )}\n </Stack>\n )\n}\n"],"mappings":";;;;;;;;;AAYA,MAAa,oBAAyC,UAAU;CAC9D,MAAM,EAAE,QAAQ,WAAW,YAAY,cAAc,UAAU;CAC/D,MAAM,CAAC,WAAW,mBAAmB,eACnC,aACA,iBACF;CACA,MAAM,EAAE,kBAAkB,gBAAgB;CAC1C,MAAM,EAAE,sBAAsB,yBAAyB;CAEvD,MAAM,eAAe,SAAS;CAE9B,IAAI,CAAC,gBAAgB,CAAC,aAAa,CAAC,cAAc,CAAC,WACjD,OAAO;CAIT,MAAM,mBAAmB,EADI,gBAAgB,qBAAqB,CAAC;CAGnE,MAAM,gBACJ,QAAQ,MAAM,UAAU,MAAM,OAAO,eAAe,CAAC,EAAE,MACvD,cAAc;CAEhB,OACE,oBAAC,OAAD;EACE,WAAU;EACV,SAAS;EACT,IAAI,MAAM;EACV,WAAW,MAAM;YAEhB,aAAa,CAAC,eACb,MAAM,KAAK,EAAE,QAAQ,EAAE,CAAC,CAAC,CAAC,KAAK,GAAG,UAChC,oBAAC,2BAAD,CAAwC,GAAR,KAAQ,CACzC,IACC,CAAC,eACH,oBAAC,mBAAD,CAAoB,CAAA,IAEpB,QAAQ,KAAK,UACX,oBAAC,mBAAD;GAES;GACP,QAAQ,MAAM,OAAO;GACrB,SACE,yBACU,cAAc,mBAAmB,MAAM,EAAE,IAC/C,KAAA;EAEP,GARM,MAAM,EAQZ,CACF;CAEE,CAAA;AAEX"}
|
|
@@ -16,7 +16,7 @@ import { useTranslation } from "react-i18next";
|
|
|
16
16
|
const Routes = (props) => {
|
|
17
17
|
const { t } = useTranslation();
|
|
18
18
|
const navigate = useNavigate();
|
|
19
|
-
const { mode, modeOptions, showSingleRoute } = useWidgetConfig();
|
|
19
|
+
const { mode, modeOptions, showSingleRoute, defaultUI } = useWidgetConfig();
|
|
20
20
|
const { routes, isLoading, isFetching, isFetched, dataUpdatedAt, refetchTime, refetch } = useRoutes();
|
|
21
21
|
const currentRoute = routes?.[0];
|
|
22
22
|
if (!currentRoute && !isLoading && !isFetching && !isFetched) return null;
|
|
@@ -28,7 +28,7 @@ const Routes = (props) => {
|
|
|
28
28
|
return /* @__PURE__ */ jsxs(Card$1, {
|
|
29
29
|
...props,
|
|
30
30
|
children: [
|
|
31
|
-
/* @__PURE__ */ jsx(CardTitle, { children: title }),
|
|
31
|
+
defaultUI?.layout === "cards" ? null : /* @__PURE__ */ jsx(CardTitle, { children: title }),
|
|
32
32
|
/* @__PURE__ */ jsx(ProgressToNextUpdate, {
|
|
33
33
|
updatedAt: dataUpdatedAt || Date.now(),
|
|
34
34
|
timeToUpdate: refetchTime,
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"Routes.js","names":["Card"],"sources":["../../../../src/components/Routes/Routes.tsx"],"sourcesContent":["import { Box, Collapse } from '@mui/material'\nimport { useNavigate } from '@tanstack/react-router'\nimport { useTranslation } from 'react-i18next'\nimport { useRoutes } from '../../hooks/useRoutes.js'\nimport { useWidgetConfig } from '../../providers/WidgetProvider/WidgetProvider.js'\nimport { navigationRoutes } from '../../utils/navigationRoutes.js'\nimport { ButtonTertiary } from '../ButtonTertiary.js'\nimport type { CardProps } from '../Card/Card.js'\nimport { Card } from '../Card/Card.js'\nimport { CardTitle } from '../Card/CardTitle.js'\nimport { ProgressToNextUpdate } from '../ProgressToNextUpdate.js'\nimport { RouteCard } from '../RouteCard/RouteCard.js'\nimport { RouteCardSkeleton } from '../RouteCard/RouteCardSkeleton.js'\nimport { RouteNotFoundCard } from '../RouteCard/RouteNotFoundCard.js'\n\nexport const Routes: React.FC<CardProps> = (props) => {\n const { t } = useTranslation()\n const navigate = useNavigate()\n const { mode, modeOptions, showSingleRoute } = useWidgetConfig()\n const {\n routes,\n isLoading,\n isFetching,\n isFetched,\n dataUpdatedAt,\n refetchTime,\n refetch,\n } = useRoutes()\n\n const currentRoute = routes?.[0]\n\n if (!currentRoute && !isLoading && !isFetching && !isFetched) {\n return null\n }\n\n const handleCardClick = () => {\n navigate({ to: navigationRoutes.routes })\n }\n\n const routeNotFound = !currentRoute && !isLoading && !isFetching\n const onlySingleRoute = mode === 'refuel' || showSingleRoute\n const showAll =\n !onlySingleRoute && !routeNotFound && (routes?.length ?? 0) > 1\n\n const title =\n mode === 'custom'\n ? modeOptions?.custom?.type === 'deposit'\n ? t('header.receive')\n : t('header.youPay')\n : t('header.receive')\n\n return (\n <Card {...props}>\n <CardTitle>{title}</CardTitle
|
|
1
|
+
{"version":3,"file":"Routes.js","names":["Card"],"sources":["../../../../src/components/Routes/Routes.tsx"],"sourcesContent":["import { Box, Collapse } from '@mui/material'\nimport { useNavigate } from '@tanstack/react-router'\nimport { useTranslation } from 'react-i18next'\nimport { useRoutes } from '../../hooks/useRoutes.js'\nimport { useWidgetConfig } from '../../providers/WidgetProvider/WidgetProvider.js'\nimport { navigationRoutes } from '../../utils/navigationRoutes.js'\nimport { ButtonTertiary } from '../ButtonTertiary.js'\nimport type { CardProps } from '../Card/Card.js'\nimport { Card } from '../Card/Card.js'\nimport { CardTitle } from '../Card/CardTitle.js'\nimport { ProgressToNextUpdate } from '../ProgressToNextUpdate.js'\nimport { RouteCard } from '../RouteCard/RouteCard.js'\nimport { RouteCardSkeleton } from '../RouteCard/RouteCardSkeleton.js'\nimport { RouteNotFoundCard } from '../RouteCard/RouteNotFoundCard.js'\n\nexport const Routes: React.FC<CardProps> = (props) => {\n const { t } = useTranslation()\n const navigate = useNavigate()\n const { mode, modeOptions, showSingleRoute, defaultUI } = useWidgetConfig()\n const {\n routes,\n isLoading,\n isFetching,\n isFetched,\n dataUpdatedAt,\n refetchTime,\n refetch,\n } = useRoutes()\n\n const currentRoute = routes?.[0]\n\n if (!currentRoute && !isLoading && !isFetching && !isFetched) {\n return null\n }\n\n const handleCardClick = () => {\n navigate({ to: navigationRoutes.routes })\n }\n\n const routeNotFound = !currentRoute && !isLoading && !isFetching\n const onlySingleRoute = mode === 'refuel' || showSingleRoute\n const showAll =\n !onlySingleRoute && !routeNotFound && (routes?.length ?? 0) > 1\n\n const title =\n mode === 'custom'\n ? modeOptions?.custom?.type === 'deposit'\n ? t('header.receive')\n : t('header.youPay')\n : t('header.receive')\n\n return (\n <Card {...props}>\n {/* The cards layout's Receive card already carries this header. */}\n {defaultUI?.layout === 'cards' ? null : <CardTitle>{title}</CardTitle>}\n <ProgressToNextUpdate\n updatedAt={dataUpdatedAt || Date.now()}\n timeToUpdate={refetchTime}\n isLoading={isFetching}\n onClick={() => refetch()}\n sx={{\n position: 'absolute',\n top: 8,\n right: 8,\n }}\n />\n <Box\n sx={{\n p: 2,\n }}\n >\n {isLoading && !currentRoute ? (\n <RouteCardSkeleton variant=\"cardless\" />\n ) : !currentRoute ? (\n <RouteNotFoundCard />\n ) : (\n <RouteCard route={currentRoute} variant=\"cardless\" active />\n )}\n\n <Collapse timeout={225} in={showAll} unmountOnExit mountOnEnter>\n <Box\n sx={{\n mt: 2,\n }}\n >\n <ButtonTertiary onClick={handleCardClick} fullWidth>\n {t('button.showAll')}\n </ButtonTertiary>\n </Box>\n </Collapse>\n </Box>\n </Card>\n )\n}\n"],"mappings":";;;;;;;;;;;;;;;AAeA,MAAa,UAA+B,UAAU;CACpD,MAAM,EAAE,MAAM,eAAe;CAC7B,MAAM,WAAW,YAAY;CAC7B,MAAM,EAAE,MAAM,aAAa,iBAAiB,cAAc,gBAAgB;CAC1E,MAAM,EACJ,QACA,WACA,YACA,WACA,eACA,aACA,YACE,UAAU;CAEd,MAAM,eAAe,SAAS;CAE9B,IAAI,CAAC,gBAAgB,CAAC,aAAa,CAAC,cAAc,CAAC,WACjD,OAAO;CAGT,MAAM,wBAAwB;EAC5B,SAAS,EAAE,IAAI,iBAAiB,OAAO,CAAC;CAC1C;CAIA,MAAM,UACJ,EAFsB,SAAS,YAAY,oBAEvB,EAHA,CAAC,gBAAgB,CAAC,aAAa,CAAC,gBAGb,QAAQ,UAAU,KAAK;CAEhE,MAAM,QACJ,SAAS,WACL,aAAa,QAAQ,SAAS,YAC5B,EAAE,gBAAgB,IAClB,EAAE,eAAe,IACnB,EAAE,gBAAgB;CAExB,OACE,qBAACA,QAAD;EAAM,GAAI;YAAV;GAEG,WAAW,WAAW,UAAU,OAAO,oBAAC,WAAD,EAAA,UAAY,MAAiB,CAAA;GACrE,oBAAC,sBAAD;IACE,WAAW,iBAAiB,KAAK,IAAI;IACrC,cAAc;IACd,WAAW;IACX,eAAe,QAAQ;IACvB,IAAI;KACF,UAAU;KACV,KAAK;KACL,OAAO;IACT;GACD,CAAA;GACD,qBAAC,KAAD;IACE,IAAI,EACF,GAAG,EACL;cAHF,CAKG,aAAa,CAAC,eACb,oBAAC,mBAAD,EAAmB,SAAQ,WAAY,CAAA,IACrC,CAAC,eACH,oBAAC,mBAAD,CAAoB,CAAA,IAEpB,oBAAC,WAAD;KAAW,OAAO;KAAc,SAAQ;KAAW,QAAA;IAAQ,CAAA,GAG7D,oBAAC,UAAD;KAAU,SAAS;KAAK,IAAI;KAAS,eAAA;KAAc,cAAA;eACjD,oBAAC,KAAD;MACE,IAAI,EACF,IAAI,EACN;gBAEA,oBAAC,gBAAD;OAAgB,SAAS;OAAiB,WAAA;iBACvC,EAAE,gBAAgB;MACL,CAAA;KACb,CAAA;IACG,CAAA,CACP;;EACD;;AAEV"}
|
|
@@ -0,0 +1,51 @@
|
|
|
1
|
+
import { useSettingsStore } from "../../stores/settings/SettingsStore.js";
|
|
2
|
+
import { navigationRoutes } from "../../utils/navigationRoutes.js";
|
|
3
|
+
import { useSplitMode } from "../../stores/navigationTabs/useNavigationTabsStore.js";
|
|
4
|
+
import { Card } from "../Card/Card.js";
|
|
5
|
+
import { useSettings } from "../../stores/settings/useSettings.js";
|
|
6
|
+
import { SettingsPanelButton, SettingsPanelContainer, SettingsPanelTitle, SettingsPanelValue } from "./SettingsPanel.style.js";
|
|
7
|
+
import { bridgeSettingsPanelKeys, swapSettingsPanelKeys } from "./utils.js";
|
|
8
|
+
import { useNavigate } from "@tanstack/react-router";
|
|
9
|
+
import { jsx, jsxs } from "react/jsx-runtime";
|
|
10
|
+
import { useTranslation } from "react-i18next";
|
|
11
|
+
//#region src/components/SettingsPanel/SettingsPanel.tsx
|
|
12
|
+
const SettingsPanel = (props) => {
|
|
13
|
+
const { t } = useTranslation();
|
|
14
|
+
const navigate = useNavigate();
|
|
15
|
+
const splitMode = useSplitMode();
|
|
16
|
+
const { slippage, routePriority } = useSettings(["slippage", "routePriority"]);
|
|
17
|
+
const [enabledBridges, totalBridges, enabledExchanges, totalExchanges] = useSettingsStore((state) => [
|
|
18
|
+
Object.values(state._enabledBridges).filter(Boolean).length,
|
|
19
|
+
Object.values(state._enabledBridges).length,
|
|
20
|
+
Object.values(state._enabledExchanges).filter(Boolean).length,
|
|
21
|
+
Object.values(state._enabledExchanges).length
|
|
22
|
+
]);
|
|
23
|
+
const rows = splitMode === "bridge" ? bridgeSettingsPanelKeys : swapSettingsPanelKeys;
|
|
24
|
+
const labelByKey = {
|
|
25
|
+
routePriority: t("settings.routePriority"),
|
|
26
|
+
exchanges: t("settings.enabledExchanges"),
|
|
27
|
+
bridges: t("settings.enabledBridges"),
|
|
28
|
+
slippage: t("settings.slippage")
|
|
29
|
+
};
|
|
30
|
+
const valueByKey = {
|
|
31
|
+
routePriority: routePriority === "FASTEST" ? t("settings.routePriorityOptions.fastest.title") : t("settings.routePriorityOptions.cheapest.title"),
|
|
32
|
+
exchanges: `${enabledExchanges}/${totalExchanges}`,
|
|
33
|
+
bridges: `${enabledBridges}/${totalBridges}`,
|
|
34
|
+
slippage: slippage ? `${slippage}%` : t("button.auto")
|
|
35
|
+
};
|
|
36
|
+
const handleClick = (key) => {
|
|
37
|
+
navigate({ to: `/${navigationRoutes.settings}/${navigationRoutes[key]}` });
|
|
38
|
+
};
|
|
39
|
+
return /* @__PURE__ */ jsx(SettingsPanelContainer, {
|
|
40
|
+
...props,
|
|
41
|
+
children: rows.map((key) => /* @__PURE__ */ jsx(Card, { children: /* @__PURE__ */ jsxs(SettingsPanelButton, {
|
|
42
|
+
onClick: () => handleClick(key),
|
|
43
|
+
disableRipple: true,
|
|
44
|
+
children: [/* @__PURE__ */ jsx(SettingsPanelTitle, { children: labelByKey[key] }), /* @__PURE__ */ jsx(SettingsPanelValue, { children: valueByKey[key] })]
|
|
45
|
+
}) }, key))
|
|
46
|
+
});
|
|
47
|
+
};
|
|
48
|
+
//#endregion
|
|
49
|
+
export { SettingsPanel };
|
|
50
|
+
|
|
51
|
+
//# sourceMappingURL=SettingsPanel.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"SettingsPanel.js","names":[],"sources":["../../../../src/components/SettingsPanel/SettingsPanel.tsx"],"sourcesContent":["import type { BoxProps } from '@mui/material'\nimport { useNavigate } from '@tanstack/react-router'\nimport type { JSX } from 'react'\nimport { useTranslation } from 'react-i18next'\nimport { useSplitMode } from '../../stores/navigationTabs/useNavigationTabsStore.js'\nimport { useSettingsStore } from '../../stores/settings/SettingsStore.js'\nimport { useSettings } from '../../stores/settings/useSettings.js'\nimport { navigationRoutes } from '../../utils/navigationRoutes.js'\nimport { Card } from '../Card/Card.js'\nimport {\n SettingsPanelButton,\n SettingsPanelContainer,\n SettingsPanelTitle,\n SettingsPanelValue,\n} from './SettingsPanel.style.js'\nimport {\n bridgeSettingsPanelKeys,\n type SettingsPanelKey,\n swapSettingsPanelKeys,\n} from './utils.js'\n\nexport const SettingsPanel: React.FC<BoxProps> = (props): JSX.Element => {\n const { t } = useTranslation()\n const navigate = useNavigate()\n const splitMode = useSplitMode()\n const { slippage, routePriority } = useSettings(['slippage', 'routePriority'])\n const [enabledBridges, totalBridges, enabledExchanges, totalExchanges] =\n useSettingsStore((state) => [\n Object.values(state._enabledBridges).filter(Boolean).length,\n Object.values(state._enabledBridges).length,\n Object.values(state._enabledExchanges).filter(Boolean).length,\n Object.values(state._enabledExchanges).length,\n ])\n\n const rows =\n splitMode === 'bridge' ? bridgeSettingsPanelKeys : swapSettingsPanelKeys\n\n const labelByKey: Record<SettingsPanelKey, string> = {\n routePriority: t('settings.routePriority'),\n exchanges: t('settings.enabledExchanges'),\n bridges: t('settings.enabledBridges'),\n slippage: t('settings.slippage'),\n }\n\n const valueByKey: Record<SettingsPanelKey, string> = {\n routePriority:\n routePriority === 'FASTEST'\n ? t('settings.routePriorityOptions.fastest.title')\n : t('settings.routePriorityOptions.cheapest.title'),\n exchanges: `${enabledExchanges}/${totalExchanges}`,\n bridges: `${enabledBridges}/${totalBridges}`,\n slippage: slippage ? `${slippage}%` : t('button.auto'),\n }\n\n const handleClick = (key: SettingsPanelKey) => {\n navigate({\n to: `/${navigationRoutes.settings}/${navigationRoutes[key]}`,\n })\n }\n\n return (\n <SettingsPanelContainer {...props}>\n {rows.map((key) => (\n <Card key={key}>\n <SettingsPanelButton onClick={() => handleClick(key)} disableRipple>\n <SettingsPanelTitle>{labelByKey[key]}</SettingsPanelTitle>\n <SettingsPanelValue>{valueByKey[key]}</SettingsPanelValue>\n </SettingsPanelButton>\n </Card>\n ))}\n </SettingsPanelContainer>\n )\n}\n"],"mappings":";;;;;;;;;;;AAqBA,MAAa,iBAAqC,UAAuB;CACvE,MAAM,EAAE,MAAM,eAAe;CAC7B,MAAM,WAAW,YAAY;CAC7B,MAAM,YAAY,aAAa;CAC/B,MAAM,EAAE,UAAU,kBAAkB,YAAY,CAAC,YAAY,eAAe,CAAC;CAC7E,MAAM,CAAC,gBAAgB,cAAc,kBAAkB,kBACrD,kBAAkB,UAAU;EAC1B,OAAO,OAAO,MAAM,eAAe,CAAC,CAAC,OAAO,OAAO,CAAC,CAAC;EACrD,OAAO,OAAO,MAAM,eAAe,CAAC,CAAC;EACrC,OAAO,OAAO,MAAM,iBAAiB,CAAC,CAAC,OAAO,OAAO,CAAC,CAAC;EACvD,OAAO,OAAO,MAAM,iBAAiB,CAAC,CAAC;CACzC,CAAC;CAEH,MAAM,OACJ,cAAc,WAAW,0BAA0B;CAErD,MAAM,aAA+C;EACnD,eAAe,EAAE,wBAAwB;EACzC,WAAW,EAAE,2BAA2B;EACxC,SAAS,EAAE,yBAAyB;EACpC,UAAU,EAAE,mBAAmB;CACjC;CAEA,MAAM,aAA+C;EACnD,eACE,kBAAkB,YACd,EAAE,6CAA6C,IAC/C,EAAE,8CAA8C;EACtD,WAAW,GAAG,iBAAiB,GAAG;EAClC,SAAS,GAAG,eAAe,GAAG;EAC9B,UAAU,WAAW,GAAG,SAAS,KAAK,EAAE,aAAa;CACvD;CAEA,MAAM,eAAe,QAA0B;EAC7C,SAAS,EACP,IAAI,IAAI,iBAAiB,SAAS,GAAG,iBAAiB,OACxD,CAAC;CACH;CAEA,OACE,oBAAC,wBAAD;EAAwB,GAAI;YACzB,KAAK,KAAK,QACT,oBAAC,MAAD,EAAA,UACE,qBAAC,qBAAD;GAAqB,eAAe,YAAY,GAAG;GAAG,eAAA;aAAtD,CACE,oBAAC,oBAAD,EAAA,UAAqB,WAAW,KAAyB,CAAA,GACzD,oBAAC,oBAAD,EAAA,UAAqB,WAAW,KAAyB,CAAA,CACtC;KACjB,GALK,GAKL,CACP;CACqB,CAAA;AAE5B"}
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
import { Box, ButtonBase, Typography, styled } from "@mui/material";
|
|
2
|
+
//#region src/components/SettingsPanel/SettingsPanel.style.tsx
|
|
3
|
+
const SettingsPanelContainer = styled(Box)(({ theme }) => ({
|
|
4
|
+
display: "flex",
|
|
5
|
+
flexDirection: "column",
|
|
6
|
+
gap: theme.spacing(1)
|
|
7
|
+
}));
|
|
8
|
+
const SettingsPanelButton = styled(ButtonBase)(({ theme }) => ({
|
|
9
|
+
display: "flex",
|
|
10
|
+
width: "100%",
|
|
11
|
+
justifyContent: "space-between",
|
|
12
|
+
alignItems: "center",
|
|
13
|
+
gap: theme.spacing(1),
|
|
14
|
+
padding: theme.spacing(2),
|
|
15
|
+
borderRadius: theme.vars.shape.borderRadius
|
|
16
|
+
}));
|
|
17
|
+
const SettingsPanelTitle = styled(Typography)(({ theme }) => ({
|
|
18
|
+
fontSize: 14,
|
|
19
|
+
lineHeight: 1,
|
|
20
|
+
fontWeight: 700,
|
|
21
|
+
color: theme.vars.palette.text.primary
|
|
22
|
+
}));
|
|
23
|
+
const SettingsPanelValue = styled(Typography)(({ theme }) => ({
|
|
24
|
+
fontSize: 14,
|
|
25
|
+
lineHeight: 1,
|
|
26
|
+
fontWeight: 500,
|
|
27
|
+
color: theme.vars.palette.text.secondary,
|
|
28
|
+
whiteSpace: "nowrap"
|
|
29
|
+
}));
|
|
30
|
+
//#endregion
|
|
31
|
+
export { SettingsPanelButton, SettingsPanelContainer, SettingsPanelTitle, SettingsPanelValue };
|
|
32
|
+
|
|
33
|
+
//# sourceMappingURL=SettingsPanel.style.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"SettingsPanel.style.js","names":[],"sources":["../../../../src/components/SettingsPanel/SettingsPanel.style.tsx"],"sourcesContent":["import { Box, ButtonBase, styled, Typography } from '@mui/material'\nimport type React from 'react'\n\nexport const SettingsPanelContainer: React.FC<\n React.ComponentProps<typeof Box>\n> = styled(Box)(({ theme }) => ({\n display: 'flex',\n flexDirection: 'column',\n gap: theme.spacing(1),\n}))\n\nexport const SettingsPanelButton: React.FC<\n React.ComponentProps<typeof ButtonBase>\n> = styled(ButtonBase)(({ theme }) => ({\n display: 'flex',\n width: '100%',\n justifyContent: 'space-between',\n alignItems: 'center',\n gap: theme.spacing(1),\n padding: theme.spacing(2),\n borderRadius: theme.vars.shape.borderRadius,\n}))\n\nexport const SettingsPanelTitle: React.FC<\n React.ComponentProps<typeof Typography>\n> = styled(Typography)(({ theme }) => ({\n fontSize: 14,\n lineHeight: 1,\n fontWeight: 700,\n color: theme.vars.palette.text.primary,\n}))\n\nexport const SettingsPanelValue: React.FC<\n React.ComponentProps<typeof Typography>\n> = styled(Typography)(({ theme }) => ({\n fontSize: 14,\n lineHeight: 1,\n fontWeight: 500,\n color: theme.vars.palette.text.secondary,\n whiteSpace: 'nowrap',\n}))\n"],"mappings":";;AAGA,MAAa,yBAET,OAAO,GAAG,CAAC,EAAE,EAAE,aAAa;CAC9B,SAAS;CACT,eAAe;CACf,KAAK,MAAM,QAAQ,CAAC;AACtB,EAAE;AAEF,MAAa,sBAET,OAAO,UAAU,CAAC,EAAE,EAAE,aAAa;CACrC,SAAS;CACT,OAAO;CACP,gBAAgB;CAChB,YAAY;CACZ,KAAK,MAAM,QAAQ,CAAC;CACpB,SAAS,MAAM,QAAQ,CAAC;CACxB,cAAc,MAAM,KAAK,MAAM;AACjC,EAAE;AAEF,MAAa,qBAET,OAAO,UAAU,CAAC,EAAE,EAAE,aAAa;CACrC,UAAU;CACV,YAAY;CACZ,YAAY;CACZ,OAAO,MAAM,KAAK,QAAQ,KAAK;AACjC,EAAE;AAEF,MAAa,qBAET,OAAO,UAAU,CAAC,EAAE,EAAE,aAAa;CACrC,UAAU;CACV,YAAY;CACZ,YAAY;CACZ,OAAO,MAAM,KAAK,QAAQ,KAAK;CAC/B,YAAY;AACd,EAAE"}
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
//#region src/components/SettingsPanel/utils.ts
|
|
2
|
+
/** Navigation tabs that surface the settings panel on the main page. */
|
|
3
|
+
const advancedNavigationTabKeys = ["swap-advanced", "bridge-advanced"];
|
|
4
|
+
const swapSettingsPanelKeys = ["slippage", "exchanges"];
|
|
5
|
+
const bridgeSettingsPanelKeys = [
|
|
6
|
+
"routePriority",
|
|
7
|
+
"slippage",
|
|
8
|
+
"bridges",
|
|
9
|
+
"exchanges"
|
|
10
|
+
];
|
|
11
|
+
//#endregion
|
|
12
|
+
export { advancedNavigationTabKeys, bridgeSettingsPanelKeys, swapSettingsPanelKeys };
|
|
13
|
+
|
|
14
|
+
//# sourceMappingURL=utils.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"utils.js","names":[],"sources":["../../../../src/components/SettingsPanel/utils.ts"],"sourcesContent":["import type { NavigationTabKey } from '../../types/widget.js'\n\nexport type SettingsPanelKey =\n | 'routePriority'\n | 'exchanges'\n | 'bridges'\n | 'slippage'\n\n/** Navigation tabs that surface the settings panel on the main page. */\nexport const advancedNavigationTabKeys: NavigationTabKey[] = [\n 'swap-advanced',\n 'bridge-advanced',\n]\n\n// Keys are ordered to match the settings page layout.\n// Swap is same-chain, so route priority and bridges are not relevant.\nexport const swapSettingsPanelKeys: SettingsPanelKey[] = [\n 'slippage',\n 'exchanges',\n]\n\nexport const bridgeSettingsPanelKeys: SettingsPanelKey[] = [\n 'routePriority',\n 'slippage',\n 'bridges',\n 'exchanges',\n]\n"],"mappings":";;AASA,MAAa,4BAAgD,CAC3D,iBACA,iBACF;AAIA,MAAa,wBAA4C,CACvD,YACA,WACF;AAEA,MAAa,0BAA8C;CACzD;CACA;CACA;CACA;AACF"}
|
|
@@ -0,0 +1,50 @@
|
|
|
1
|
+
import { useWidgetConfig } from "../../providers/WidgetProvider/WidgetProvider.js";
|
|
2
|
+
import { useAvailableChains } from "../../hooks/useAvailableChains.js";
|
|
3
|
+
import { useFieldActions } from "../../stores/form/useFieldActions.js";
|
|
4
|
+
import { useToAddressReset } from "../../hooks/useToAddressReset.js";
|
|
5
|
+
import { useToAddressAutoPopulate } from "../../hooks/useToAddressAutoPopulate.js";
|
|
6
|
+
import { SwapButtonContainer, SwapIconCard } from "./SwapButton.style.js";
|
|
7
|
+
import { jsx } from "react/jsx-runtime";
|
|
8
|
+
import { useTranslation } from "react-i18next";
|
|
9
|
+
import ArrowDownwardIcon from "@mui/icons-material/ArrowDownward";
|
|
10
|
+
//#region src/components/SwapButton/SwapButton.tsx
|
|
11
|
+
const SwapButton = ({ sx, ...props }) => {
|
|
12
|
+
const { t } = useTranslation();
|
|
13
|
+
const { mode } = useWidgetConfig();
|
|
14
|
+
const { setFieldValue, getFieldValues } = useFieldActions();
|
|
15
|
+
const { getChainById } = useAvailableChains();
|
|
16
|
+
const { tryResetToAddress } = useToAddressReset();
|
|
17
|
+
const autoPopulateToAddress = useToAddressAutoPopulate();
|
|
18
|
+
const handleClick = () => {
|
|
19
|
+
const [fromChainId, fromToken, toChainId, toToken, toAddress, toAmount] = getFieldValues("fromChain", "fromToken", "toChain", "toToken", "toAddress", "toAmount");
|
|
20
|
+
setFieldValue("fromAmount", mode === "limit" && toAmount ? toAmount : "", { isTouched: true });
|
|
21
|
+
setFieldValue("fromChain", toChainId, { isTouched: true });
|
|
22
|
+
setFieldValue("fromToken", toToken, { isTouched: true });
|
|
23
|
+
setFieldValue("toChain", fromChainId, { isTouched: true });
|
|
24
|
+
setFieldValue("toToken", fromToken, { isTouched: true });
|
|
25
|
+
if (autoPopulateToAddress({
|
|
26
|
+
formType: "from",
|
|
27
|
+
selectedToAddress: toAddress,
|
|
28
|
+
selectedChainId: toChainId,
|
|
29
|
+
selectedOppositeChainId: fromChainId,
|
|
30
|
+
selectedOppositeTokenAddress: fromToken
|
|
31
|
+
})) return;
|
|
32
|
+
const toChain = getChainById(fromChainId);
|
|
33
|
+
if (toChain) tryResetToAddress(toChain);
|
|
34
|
+
};
|
|
35
|
+
return /* @__PURE__ */ jsx(SwapButtonContainer, {
|
|
36
|
+
sx,
|
|
37
|
+
...props,
|
|
38
|
+
children: /* @__PURE__ */ jsx(SwapIconCard, {
|
|
39
|
+
component: "button",
|
|
40
|
+
onClick: handleClick,
|
|
41
|
+
"aria-label": t("button.swap"),
|
|
42
|
+
"data-testid": "widget-swap-tokens-button",
|
|
43
|
+
children: /* @__PURE__ */ jsx(ArrowDownwardIcon, { fontSize: "inherit" })
|
|
44
|
+
})
|
|
45
|
+
});
|
|
46
|
+
};
|
|
47
|
+
//#endregion
|
|
48
|
+
export { SwapButton };
|
|
49
|
+
|
|
50
|
+
//# sourceMappingURL=SwapButton.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"SwapButton.js","names":["ArrowDownward"],"sources":["../../../../src/components/SwapButton/SwapButton.tsx"],"sourcesContent":["import ArrowDownward from '@mui/icons-material/ArrowDownward'\nimport type { BoxProps } from '@mui/material'\nimport type { JSX } from 'react'\nimport { useTranslation } from 'react-i18next'\nimport { useAvailableChains } from '../../hooks/useAvailableChains.js'\nimport { useToAddressAutoPopulate } from '../../hooks/useToAddressAutoPopulate.js'\nimport { useToAddressReset } from '../../hooks/useToAddressReset.js'\nimport { useWidgetConfig } from '../../providers/WidgetProvider/WidgetProvider.js'\nimport { useFieldActions } from '../../stores/form/useFieldActions.js'\nimport { SwapButtonContainer, SwapIconCard } from './SwapButton.style.js'\n\nexport const SwapButton: React.FC<BoxProps> = ({\n sx,\n ...props\n}): JSX.Element => {\n const { t } = useTranslation()\n const { mode } = useWidgetConfig()\n const { setFieldValue, getFieldValues } = useFieldActions()\n const { getChainById } = useAvailableChains()\n const { tryResetToAddress } = useToAddressReset()\n const autoPopulateToAddress = useToAddressAutoPopulate()\n\n const handleClick = (): void => {\n const [fromChainId, fromToken, toChainId, toToken, toAddress, toAmount] =\n getFieldValues(\n 'fromChain',\n 'fromToken',\n 'toChain',\n 'toToken',\n 'toAddress',\n 'toAmount'\n )\n const newFromAmount =\n mode === 'limit' && toAmount ? (toAmount as string) : ''\n setFieldValue('fromAmount', newFromAmount, { isTouched: true })\n setFieldValue('fromChain', toChainId, { isTouched: true })\n setFieldValue('fromToken', toToken, { isTouched: true })\n setFieldValue('toChain', fromChainId, { isTouched: true })\n setFieldValue('toToken', fromToken, { isTouched: true })\n\n const autoPopulatedToAddress = autoPopulateToAddress({\n formType: 'from',\n selectedToAddress: toAddress,\n selectedChainId: toChainId,\n selectedOppositeChainId: fromChainId,\n selectedOppositeTokenAddress: fromToken,\n })\n\n if (autoPopulatedToAddress) {\n return\n }\n\n const toChain = getChainById(fromChainId)\n if (toChain) {\n tryResetToAddress(toChain)\n }\n }\n\n return (\n <SwapButtonContainer sx={sx} {...props}>\n <SwapIconCard\n component=\"button\"\n onClick={handleClick}\n aria-label={t('button.swap')}\n data-testid=\"widget-swap-tokens-button\"\n >\n <ArrowDownward fontSize=\"inherit\" />\n </SwapIconCard>\n </SwapButtonContainer>\n )\n}\n"],"mappings":";;;;;;;;;;AAWA,MAAa,cAAkC,EAC7C,IACA,GAAG,YACc;CACjB,MAAM,EAAE,MAAM,eAAe;CAC7B,MAAM,EAAE,SAAS,gBAAgB;CACjC,MAAM,EAAE,eAAe,mBAAmB,gBAAgB;CAC1D,MAAM,EAAE,iBAAiB,mBAAmB;CAC5C,MAAM,EAAE,sBAAsB,kBAAkB;CAChD,MAAM,wBAAwB,yBAAyB;CAEvD,MAAM,oBAA0B;EAC9B,MAAM,CAAC,aAAa,WAAW,WAAW,SAAS,WAAW,YAC5D,eACE,aACA,aACA,WACA,WACA,aACA,UACF;EAGF,cAAc,cADZ,SAAS,WAAW,WAAY,WAAsB,IACb,EAAE,WAAW,KAAK,CAAC;EAC9D,cAAc,aAAa,WAAW,EAAE,WAAW,KAAK,CAAC;EACzD,cAAc,aAAa,SAAS,EAAE,WAAW,KAAK,CAAC;EACvD,cAAc,WAAW,aAAa,EAAE,WAAW,KAAK,CAAC;EACzD,cAAc,WAAW,WAAW,EAAE,WAAW,KAAK,CAAC;EAUvD,IAR+B,sBAAsB;GACnD,UAAU;GACV,mBAAmB;GACnB,iBAAiB;GACjB,yBAAyB;GACzB,8BAA8B;EAChC,CAEyB,GACvB;EAGF,MAAM,UAAU,aAAa,WAAW;EACxC,IAAI,SACF,kBAAkB,OAAO;CAE7B;CAEA,OACE,oBAAC,qBAAD;EAAyB;EAAI,GAAI;YAC/B,oBAAC,cAAD;GACE,WAAU;GACV,SAAS;GACT,cAAY,EAAE,aAAa;GAC3B,eAAY;aAEZ,oBAACA,mBAAD,EAAe,UAAS,UAAW,CAAA;EACvB,CAAA;CACK,CAAA;AAEzB"}
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
import { Card as Card$1 } from "../Card/Card.js";
|
|
2
|
+
import { Box, styled } from "@mui/material";
|
|
3
|
+
//#region src/components/SwapButton/SwapButton.style.tsx
|
|
4
|
+
const swapButtonZIndex = 1110;
|
|
5
|
+
const SwapIconCard = styled(Card$1)(({ theme }) => ({
|
|
6
|
+
height: 32,
|
|
7
|
+
width: 32,
|
|
8
|
+
fontSize: 16,
|
|
9
|
+
display: "flex",
|
|
10
|
+
alignItems: "center",
|
|
11
|
+
justifyContent: "center",
|
|
12
|
+
borderRadius: theme.vars.shape.borderRadiusTertiary,
|
|
13
|
+
zIndex: swapButtonZIndex
|
|
14
|
+
}));
|
|
15
|
+
const SwapButtonContainer = styled(Box)(({ theme }) => ({
|
|
16
|
+
display: "flex",
|
|
17
|
+
justifyContent: "center",
|
|
18
|
+
alignItems: "center",
|
|
19
|
+
margin: theme.spacing(-1.5)
|
|
20
|
+
}));
|
|
21
|
+
//#endregion
|
|
22
|
+
export { SwapButtonContainer, SwapIconCard };
|
|
23
|
+
|
|
24
|
+
//# sourceMappingURL=SwapButton.style.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"SwapButton.style.js","names":["Card"],"sources":["../../../../src/components/SwapButton/SwapButton.style.tsx"],"sourcesContent":["import { Box, styled } from '@mui/material'\nimport type React from 'react'\nimport { Card } from '../Card/Card.js'\n\n// Sits just above MUI's appBar layer (1100) so the swap icon stays on top of the\n// two overlapping amount cards it bridges.\nconst swapButtonZIndex = 1110\n\nexport const SwapIconCard: React.FC<React.ComponentProps<typeof Card>> = styled(\n Card\n)(({ theme }) => ({\n height: 32,\n width: 32,\n fontSize: 16,\n display: 'flex',\n alignItems: 'center',\n justifyContent: 'center',\n borderRadius: theme.vars.shape.borderRadiusTertiary,\n zIndex: swapButtonZIndex,\n}))\n\nexport const SwapButtonContainer: React.FC<React.ComponentProps<typeof Box>> =\n styled(Box)(({ theme }) => ({\n display: 'flex',\n justifyContent: 'center',\n alignItems: 'center',\n margin: theme.spacing(-1.5),\n }))\n"],"mappings":";;;AAMA,MAAM,mBAAmB;AAEzB,MAAa,eAA4D,OACvEA,MACF,CAAC,EAAE,EAAE,aAAa;CAChB,QAAQ;CACR,OAAO;CACP,UAAU;CACV,SAAS;CACT,YAAY;CACZ,gBAAgB;CAChB,cAAc,MAAM,KAAK,MAAM;CAC/B,QAAQ;AACV,EAAE;AAEF,MAAa,sBACX,OAAO,GAAG,CAAC,EAAE,EAAE,aAAa;CAC1B,SAAS;CACT,gBAAgB;CAChB,YAAY;CACZ,QAAQ,MAAM,QAAQ,IAAI;AAC5B,EAAE"}
|
|
@@ -0,0 +1,52 @@
|
|
|
1
|
+
import { useWidgetConfig } from "../../providers/WidgetProvider/WidgetProvider.js";
|
|
2
|
+
import { navigationRoutes } from "../../utils/navigationRoutes.js";
|
|
3
|
+
import { FormKeyHelper } from "../../stores/form/types.js";
|
|
4
|
+
import { useFieldValues } from "../../stores/form/useFieldValues.js";
|
|
5
|
+
import { useChain } from "../../hooks/useChain.js";
|
|
6
|
+
import { useToken } from "../../hooks/useToken.js";
|
|
7
|
+
import { AvatarBadgedDefault } from "../Avatar/Avatar.js";
|
|
8
|
+
import { TokenAvatar } from "../Avatar/TokenAvatar.js";
|
|
9
|
+
import { TokenPill, TokenPillLabel, TokenPillSymbol, TokenSelectPill } from "./TokenPillButton.style.js";
|
|
10
|
+
import { useNavigate } from "@tanstack/react-router";
|
|
11
|
+
import { jsx, jsxs } from "react/jsx-runtime";
|
|
12
|
+
import { useTranslation } from "react-i18next";
|
|
13
|
+
//#region src/components/TokenPillButton/TokenPillButton.tsx
|
|
14
|
+
const TokenPillButton = ({ formType }) => {
|
|
15
|
+
const { t } = useTranslation();
|
|
16
|
+
const navigate = useNavigate();
|
|
17
|
+
const { disabledUI, mode } = useWidgetConfig();
|
|
18
|
+
const tokenKey = FormKeyHelper.getTokenKey(formType);
|
|
19
|
+
const [chainId, tokenAddress] = useFieldValues(FormKeyHelper.getChainKey(formType), tokenKey);
|
|
20
|
+
const { chain } = useChain(chainId);
|
|
21
|
+
const { token } = useToken(chainId, tokenAddress);
|
|
22
|
+
const isSelected = !!(chain && token);
|
|
23
|
+
const handleClick = () => {
|
|
24
|
+
navigate({ to: formType === "from" ? navigationRoutes.fromToken : mode === "refuel" ? navigationRoutes.toTokenNative : navigationRoutes.toToken });
|
|
25
|
+
};
|
|
26
|
+
const isDisabled = !!disabledUI?.[tokenKey];
|
|
27
|
+
const testId = `widget-${formType}-token-button`;
|
|
28
|
+
if (isSelected) return /* @__PURE__ */ jsxs(TokenPill, {
|
|
29
|
+
onClick: isDisabled ? void 0 : handleClick,
|
|
30
|
+
disabled: isDisabled,
|
|
31
|
+
"data-testid": testId,
|
|
32
|
+
children: [/* @__PURE__ */ jsx(TokenAvatar, {
|
|
33
|
+
token,
|
|
34
|
+
chain,
|
|
35
|
+
tokenAvatarSize: 24,
|
|
36
|
+
chainAvatarSize: 12
|
|
37
|
+
}), /* @__PURE__ */ jsx(TokenPillSymbol, { children: token.symbol })]
|
|
38
|
+
});
|
|
39
|
+
return /* @__PURE__ */ jsxs(TokenSelectPill, {
|
|
40
|
+
onClick: isDisabled ? void 0 : handleClick,
|
|
41
|
+
"data-testid": testId,
|
|
42
|
+
children: [/* @__PURE__ */ jsx(AvatarBadgedDefault, {
|
|
43
|
+
chain,
|
|
44
|
+
avatarSize: 24,
|
|
45
|
+
badgeSize: 12
|
|
46
|
+
}), /* @__PURE__ */ jsx(TokenPillLabel, { children: t("main.select") })]
|
|
47
|
+
});
|
|
48
|
+
};
|
|
49
|
+
//#endregion
|
|
50
|
+
export { TokenPillButton };
|
|
51
|
+
|
|
52
|
+
//# sourceMappingURL=TokenPillButton.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"TokenPillButton.js","names":[],"sources":["../../../../src/components/TokenPillButton/TokenPillButton.tsx"],"sourcesContent":["import { useNavigate } from '@tanstack/react-router'\nimport type { JSX } from 'react'\nimport { useTranslation } from 'react-i18next'\nimport { useChain } from '../../hooks/useChain.js'\nimport { useToken } from '../../hooks/useToken.js'\nimport { useWidgetConfig } from '../../providers/WidgetProvider/WidgetProvider.js'\nimport type { FormTypeProps } from '../../stores/form/types.js'\nimport { FormKeyHelper } from '../../stores/form/types.js'\nimport { useFieldValues } from '../../stores/form/useFieldValues.js'\nimport type { DisabledUIConfig } from '../../types/widget.js'\nimport { navigationRoutes } from '../../utils/navigationRoutes.js'\nimport { AvatarBadgedDefault } from '../Avatar/Avatar.js'\nimport { TokenAvatar } from '../Avatar/TokenAvatar.js'\nimport {\n TokenPill,\n TokenPillLabel,\n TokenPillSymbol,\n TokenSelectPill,\n} from './TokenPillButton.style.js'\n\nexport const TokenPillButton: React.FC<FormTypeProps> = ({\n formType,\n}): JSX.Element => {\n const { t } = useTranslation()\n const navigate = useNavigate()\n const { disabledUI, mode } = useWidgetConfig()\n\n const tokenKey = FormKeyHelper.getTokenKey(formType)\n const [chainId, tokenAddress] = useFieldValues(\n FormKeyHelper.getChainKey(formType),\n tokenKey\n )\n\n const { chain } = useChain(chainId)\n const { token } = useToken(chainId, tokenAddress)\n\n const isSelected = !!(chain && token)\n\n const handleClick = (): void => {\n navigate({\n to:\n formType === 'from'\n ? navigationRoutes.fromToken\n : mode === 'refuel'\n ? navigationRoutes.toTokenNative\n : navigationRoutes.toToken,\n })\n }\n\n const isDisabled = !!disabledUI?.[tokenKey as keyof DisabledUIConfig]\n\n const testId = `widget-${formType}-token-button`\n\n if (isSelected) {\n return (\n <TokenPill\n onClick={isDisabled ? undefined : handleClick}\n disabled={isDisabled}\n data-testid={testId}\n >\n <TokenAvatar\n token={token}\n chain={chain}\n tokenAvatarSize={24}\n chainAvatarSize={12}\n />\n <TokenPillSymbol>{token.symbol}</TokenPillSymbol>\n </TokenPill>\n )\n }\n\n return (\n <TokenSelectPill\n onClick={isDisabled ? undefined : handleClick}\n data-testid={testId}\n >\n <AvatarBadgedDefault chain={chain} avatarSize={24} badgeSize={12} />\n <TokenPillLabel>{t('main.select')}</TokenPillLabel>\n </TokenSelectPill>\n )\n}\n"],"mappings":";;;;;;;;;;;;;AAoBA,MAAa,mBAA4C,EACvD,eACiB;CACjB,MAAM,EAAE,MAAM,eAAe;CAC7B,MAAM,WAAW,YAAY;CAC7B,MAAM,EAAE,YAAY,SAAS,gBAAgB;CAE7C,MAAM,WAAW,cAAc,YAAY,QAAQ;CACnD,MAAM,CAAC,SAAS,gBAAgB,eAC9B,cAAc,YAAY,QAAQ,GAClC,QACF;CAEA,MAAM,EAAE,UAAU,SAAS,OAAO;CAClC,MAAM,EAAE,UAAU,SAAS,SAAS,YAAY;CAEhD,MAAM,aAAa,CAAC,EAAE,SAAS;CAE/B,MAAM,oBAA0B;EAC9B,SAAS,EACP,IACE,aAAa,SACT,iBAAiB,YACjB,SAAS,WACP,iBAAiB,gBACjB,iBAAiB,QAC3B,CAAC;CACH;CAEA,MAAM,aAAa,CAAC,CAAC,aAAa;CAElC,MAAM,SAAS,UAAU,SAAS;CAElC,IAAI,YACF,OACE,qBAAC,WAAD;EACE,SAAS,aAAa,KAAA,IAAY;EAClC,UAAU;EACV,eAAa;YAHf,CAKE,oBAAC,aAAD;GACS;GACA;GACP,iBAAiB;GACjB,iBAAiB;EAClB,CAAA,GACD,oBAAC,iBAAD,EAAA,UAAkB,MAAM,OAAwB,CAAA,CACvC;;CAIf,OACE,qBAAC,iBAAD;EACE,SAAS,aAAa,KAAA,IAAY;EAClC,eAAa;YAFf,CAIE,oBAAC,qBAAD;GAA4B;GAAO,YAAY;GAAI,WAAW;EAAK,CAAA,GACnE,oBAAC,gBAAD,EAAA,UAAiB,EAAE,aAAa,EAAkB,CAAA,CACnC;;AAErB"}
|
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
import { Button, Typography, styled } from "@mui/material";
|
|
2
|
+
//#region src/components/TokenPillButton/TokenPillButton.style.tsx
|
|
3
|
+
const pillLayout = (theme) => ({
|
|
4
|
+
height: 36,
|
|
5
|
+
borderRadius: theme.vars.shape.borderRadiusSecondary,
|
|
6
|
+
padding: theme.spacing(.5, 1),
|
|
7
|
+
display: "flex",
|
|
8
|
+
alignItems: "center",
|
|
9
|
+
gap: theme.spacing(1),
|
|
10
|
+
whiteSpace: "nowrap",
|
|
11
|
+
flexShrink: 0
|
|
12
|
+
});
|
|
13
|
+
const TokenPill = styled(Button)(({ theme }) => ({
|
|
14
|
+
...pillLayout(theme),
|
|
15
|
+
backgroundColor: `color-mix(in srgb, ${theme.vars.palette.common.onBackground} 4%, transparent)`,
|
|
16
|
+
border: "1px solid transparent",
|
|
17
|
+
transition: theme.transitions.create(["background-color"], { duration: theme.transitions.duration.short }),
|
|
18
|
+
"&:hover": { backgroundColor: `color-mix(in srgb, ${theme.vars.palette.common.onBackground} 8%, transparent)` }
|
|
19
|
+
}));
|
|
20
|
+
const TokenSelectPill = styled(TokenPill)({ minWidth: 0 });
|
|
21
|
+
const TokenPillSymbol = styled(Typography)(({ theme }) => ({
|
|
22
|
+
fontSize: 14,
|
|
23
|
+
fontWeight: 700,
|
|
24
|
+
lineHeight: "18px",
|
|
25
|
+
overflow: "hidden",
|
|
26
|
+
textOverflow: "ellipsis",
|
|
27
|
+
whiteSpace: "nowrap",
|
|
28
|
+
color: theme.vars.palette.text.primary
|
|
29
|
+
}));
|
|
30
|
+
const TokenPillLabel = styled(Typography)(({ theme }) => ({
|
|
31
|
+
fontSize: 16,
|
|
32
|
+
fontWeight: 700,
|
|
33
|
+
lineHeight: "20px",
|
|
34
|
+
color: theme.vars.palette.text.secondary
|
|
35
|
+
}));
|
|
36
|
+
//#endregion
|
|
37
|
+
export { TokenPill, TokenPillLabel, TokenPillSymbol, TokenSelectPill };
|
|
38
|
+
|
|
39
|
+
//# sourceMappingURL=TokenPillButton.style.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"TokenPillButton.style.js","names":[],"sources":["../../../../src/components/TokenPillButton/TokenPillButton.style.tsx"],"sourcesContent":["import { Button, styled, type Theme, Typography } from '@mui/material'\nimport type React from 'react'\n\nconst pillLayout = (theme: Theme) => ({\n height: 36,\n borderRadius: theme.vars.shape.borderRadiusSecondary,\n padding: theme.spacing(0.5, 1),\n display: 'flex',\n alignItems: 'center',\n gap: theme.spacing(1),\n whiteSpace: 'nowrap',\n flexShrink: 0,\n})\n\nexport const TokenPill: React.FC<React.ComponentProps<typeof Button>> = styled(\n Button\n)(({ theme }) => ({\n ...pillLayout(theme),\n backgroundColor: `color-mix(in srgb, ${theme.vars.palette.common.onBackground} 4%, transparent)`,\n border: '1px solid transparent',\n transition: theme.transitions.create(['background-color'], {\n duration: theme.transitions.duration.short,\n }),\n '&:hover': {\n backgroundColor: `color-mix(in srgb, ${theme.vars.palette.common.onBackground} 8%, transparent)`,\n },\n}))\n\nexport const TokenSelectPill: React.FC<React.ComponentProps<typeof Button>> =\n styled(TokenPill)({ minWidth: 0 })\n\nexport const TokenPillSymbol: React.FC<\n React.ComponentProps<typeof Typography>\n> = styled(Typography)(({ theme }) => ({\n fontSize: 14,\n fontWeight: 700,\n lineHeight: '18px',\n overflow: 'hidden',\n textOverflow: 'ellipsis',\n whiteSpace: 'nowrap',\n color: theme.vars.palette.text.primary,\n}))\n\nexport const TokenPillLabel: React.FC<React.ComponentProps<typeof Typography>> =\n styled(Typography)(({ theme }) => ({\n fontSize: 16,\n fontWeight: 700,\n lineHeight: '20px',\n color: theme.vars.palette.text.secondary,\n }))\n"],"mappings":";;AAGA,MAAM,cAAc,WAAkB;CACpC,QAAQ;CACR,cAAc,MAAM,KAAK,MAAM;CAC/B,SAAS,MAAM,QAAQ,IAAK,CAAC;CAC7B,SAAS;CACT,YAAY;CACZ,KAAK,MAAM,QAAQ,CAAC;CACpB,YAAY;CACZ,YAAY;AACd;AAEA,MAAa,YAA2D,OACtE,MACF,CAAC,EAAE,EAAE,aAAa;CAChB,GAAG,WAAW,KAAK;CACnB,iBAAiB,sBAAsB,MAAM,KAAK,QAAQ,OAAO,aAAa;CAC9E,QAAQ;CACR,YAAY,MAAM,YAAY,OAAO,CAAC,kBAAkB,GAAG,EACzD,UAAU,MAAM,YAAY,SAAS,MACvC,CAAC;CACD,WAAW,EACT,iBAAiB,sBAAsB,MAAM,KAAK,QAAQ,OAAO,aAAa,mBAChF;AACF,EAAE;AAEF,MAAa,kBACX,OAAO,SAAS,CAAC,CAAC,EAAE,UAAU,EAAE,CAAC;AAEnC,MAAa,kBAET,OAAO,UAAU,CAAC,EAAE,EAAE,aAAa;CACrC,UAAU;CACV,YAAY;CACZ,YAAY;CACZ,UAAU;CACV,cAAc;CACd,YAAY;CACZ,OAAO,MAAM,KAAK,QAAQ,KAAK;AACjC,EAAE;AAEF,MAAa,iBACX,OAAO,UAAU,CAAC,EAAE,EAAE,aAAa;CACjC,UAAU;CACV,YAAY;CACZ,YAAY;CACZ,OAAO,MAAM,KAAK,QAAQ,KAAK;AACjC,EAAE"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"version.js","names":[],"sources":["../../../src/config/version.ts"],"sourcesContent":["export const name = '@lifi/widget'\nexport const version = '4.
|
|
1
|
+
{"version":3,"file":"version.js","names":[],"sources":["../../../src/config/version.ts"],"sourcesContent":["export const name = '@lifi/widget'\nexport const version = '4.2.0'\n"],"mappings":";AAAA,MAAa,OAAO;AACpB,MAAa,UAAU"}
|
|
@@ -24,7 +24,8 @@ function useChainSearch(formType, listRef, inputRef) {
|
|
|
24
24
|
setCurrentChain(chain.id);
|
|
25
25
|
}, [setCurrentChain]),
|
|
26
26
|
onChange: useCallback(() => {
|
|
27
|
-
|
|
27
|
+
const value = inputRef.current?.value || "";
|
|
28
|
+
debouncedFilterChains(value);
|
|
28
29
|
}, [debouncedFilterChains, inputRef]),
|
|
29
30
|
onClear: useCallback(() => {
|
|
30
31
|
if (inputRef.current) inputRef.current.value = "";
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"useChainSearch.js","names":[],"sources":["../../../src/hooks/useChainSearch.ts"],"sourcesContent":["import type { ExtendedChain } from '@lifi/sdk'\nimport { debounce } from '@mui/material'\nimport type { RefObject } from 'react'\nimport { useCallback, useMemo, useState } from 'react'\nimport { useChainSelect } from '../components/ChainSelect/useChainSelect.js'\nimport { FormKeyHelper, type FormType } from '../stores/form/types.js'\nimport { useFieldValues } from '../stores/form/useFieldValues.js'\n\nexport function useChainSearch(\n formType: FormType,\n listRef: RefObject<HTMLDivElement | null>,\n inputRef: RefObject<HTMLInputElement | null>\n): {\n filteredChains: ExtendedChain[]\n isLoading: boolean\n selectedChainId: number | undefined\n onSelectChainFallback: (chain: ExtendedChain) => void\n onChange: () => void\n onClear: () => void\n} {\n const { chains, isLoading, setCurrentChain } = useChainSelect(formType)\n const [selectedChainId] = useFieldValues(FormKeyHelper.getChainKey(formType))\n const [debouncedSearchValue, setDebouncedSearchValue] = useState('')\n\n const filteredChains = useMemo(() => {\n const value = debouncedSearchValue.toLowerCase()\n return value\n ? (chains?.filter((chain) => chain.name.toLowerCase().includes(value)) ??\n [])\n : (chains ?? [])\n }, [chains, debouncedSearchValue])\n\n const debouncedFilterChains = useMemo(\n () =>\n debounce((value: string) => {\n setDebouncedSearchValue(value)\n listRef.current?.scrollTo(0, 0)\n }, 250),\n [listRef]\n )\n\n const onSelectChainFallback = useCallback(\n (chain: ExtendedChain) => {\n setCurrentChain(chain.id)\n },\n [setCurrentChain]\n )\n\n const onChange = useCallback(() => {\n const value = inputRef.current?.value || ''\n debouncedFilterChains(value)\n }, [debouncedFilterChains, inputRef])\n\n const onClear = useCallback(() => {\n if (inputRef.current) {\n inputRef.current.value = ''\n }\n setDebouncedSearchValue('')\n listRef.current?.scrollTo(0, 0)\n }, [inputRef, listRef])\n\n return {\n filteredChains,\n isLoading,\n selectedChainId,\n onSelectChainFallback,\n onChange,\n onClear,\n }\n}\n"],"mappings":";;;;;;AAQA,SAAgB,eACd,UACA,SACA,UAQA;CACA,MAAM,EAAE,QAAQ,WAAW,oBAAoB,eAAe,QAAQ;CACtE,MAAM,CAAC,mBAAmB,eAAe,cAAc,YAAY,QAAQ,CAAC;CAC5E,MAAM,CAAC,sBAAsB,2BAA2B,SAAS,EAAE;CAEnE,MAAM,iBAAiB,cAAc;EACnC,MAAM,QAAQ,qBAAqB,YAAY;EAC/C,OAAO,QACF,QAAQ,QAAQ,UAAU,MAAM,KAAK,YAAY,CAAC,CAAC,SAAS,KAAK,CAAC,KACjE,CAAC,IACF,UAAU,CAAC;CAClB,GAAG,CAAC,QAAQ,oBAAoB,CAAC;CAEjC,MAAM,wBAAwB,cAE1B,UAAU,UAAkB;EAC1B,wBAAwB,KAAK;EAC7B,QAAQ,SAAS,SAAS,GAAG,CAAC;CAChC,GAAG,GAAG,GACR,CAAC,OAAO,CACV;CAsBA,OAAO;EACL;EACA;EACA;EACA,uBAxB4B,aAC3B,UAAyB;GACxB,gBAAgB,MAAM,EAAE;EAC1B,GACA,CAAC,eAAe,CAoBI;EACpB,UAlBe,kBAAkB;
|
|
1
|
+
{"version":3,"file":"useChainSearch.js","names":[],"sources":["../../../src/hooks/useChainSearch.ts"],"sourcesContent":["import type { ExtendedChain } from '@lifi/sdk'\nimport { debounce } from '@mui/material'\nimport type { RefObject } from 'react'\nimport { useCallback, useMemo, useState } from 'react'\nimport { useChainSelect } from '../components/ChainSelect/useChainSelect.js'\nimport { FormKeyHelper, type FormType } from '../stores/form/types.js'\nimport { useFieldValues } from '../stores/form/useFieldValues.js'\n\nexport function useChainSearch(\n formType: FormType,\n listRef: RefObject<HTMLDivElement | null>,\n inputRef: RefObject<HTMLInputElement | null>\n): {\n filteredChains: ExtendedChain[]\n isLoading: boolean\n selectedChainId: number | undefined\n onSelectChainFallback: (chain: ExtendedChain) => void\n onChange: () => void\n onClear: () => void\n} {\n const { chains, isLoading, setCurrentChain } = useChainSelect(formType)\n const [selectedChainId] = useFieldValues(FormKeyHelper.getChainKey(formType))\n const [debouncedSearchValue, setDebouncedSearchValue] = useState('')\n\n const filteredChains = useMemo(() => {\n const value = debouncedSearchValue.toLowerCase()\n return value\n ? (chains?.filter((chain) => chain.name.toLowerCase().includes(value)) ??\n [])\n : (chains ?? [])\n }, [chains, debouncedSearchValue])\n\n const debouncedFilterChains = useMemo(\n () =>\n debounce((value: string) => {\n setDebouncedSearchValue(value)\n listRef.current?.scrollTo(0, 0)\n }, 250),\n [listRef]\n )\n\n const onSelectChainFallback = useCallback(\n (chain: ExtendedChain) => {\n setCurrentChain(chain.id)\n },\n [setCurrentChain]\n )\n\n const onChange = useCallback(() => {\n const value = inputRef.current?.value || ''\n debouncedFilterChains(value)\n }, [debouncedFilterChains, inputRef])\n\n const onClear = useCallback(() => {\n if (inputRef.current) {\n inputRef.current.value = ''\n }\n setDebouncedSearchValue('')\n listRef.current?.scrollTo(0, 0)\n }, [inputRef, listRef])\n\n return {\n filteredChains,\n isLoading,\n selectedChainId,\n onSelectChainFallback,\n onChange,\n onClear,\n }\n}\n"],"mappings":";;;;;;AAQA,SAAgB,eACd,UACA,SACA,UAQA;CACA,MAAM,EAAE,QAAQ,WAAW,oBAAoB,eAAe,QAAQ;CACtE,MAAM,CAAC,mBAAmB,eAAe,cAAc,YAAY,QAAQ,CAAC;CAC5E,MAAM,CAAC,sBAAsB,2BAA2B,SAAS,EAAE;CAEnE,MAAM,iBAAiB,cAAc;EACnC,MAAM,QAAQ,qBAAqB,YAAY;EAC/C,OAAO,QACF,QAAQ,QAAQ,UAAU,MAAM,KAAK,YAAY,CAAC,CAAC,SAAS,KAAK,CAAC,KACjE,CAAC,IACF,UAAU,CAAC;CAClB,GAAG,CAAC,QAAQ,oBAAoB,CAAC;CAEjC,MAAM,wBAAwB,cAE1B,UAAU,UAAkB;EAC1B,wBAAwB,KAAK;EAC7B,QAAQ,SAAS,SAAS,GAAG,CAAC;CAChC,GAAG,GAAG,GACR,CAAC,OAAO,CACV;CAsBA,OAAO;EACL;EACA;EACA;EACA,uBAxB4B,aAC3B,UAAyB;GACxB,gBAAgB,MAAM,EAAE;EAC1B,GACA,CAAC,eAAe,CAoBI;EACpB,UAlBe,kBAAkB;GACjC,MAAM,QAAQ,SAAS,SAAS,SAAS;GACzC,sBAAsB,KAAK;EAC7B,GAAG,CAAC,uBAAuB,QAAQ,CAe1B;EACP,SAdc,kBAAkB;GAChC,IAAI,SAAS,SACX,SAAS,QAAQ,QAAQ;GAE3B,wBAAwB,EAAE;GAC1B,QAAQ,SAAS,SAAS,GAAG,CAAC;EAChC,GAAG,CAAC,UAAU,OAAO,CAQb;CACR;AACF"}
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
import { FormKeyHelper } from "../stores/form/types.js";
|
|
2
|
+
import { useFieldValues } from "../stores/form/useFieldValues.js";
|
|
3
|
+
import { useToken } from "./useToken.js";
|
|
4
|
+
//#region src/hooks/useLimitMarketRate.ts
|
|
5
|
+
/**
|
|
6
|
+
* Canonical limit-order market rate (receive token per send token), derived
|
|
7
|
+
* from the tokens' USD prices: 1 send token ≈ sendPrice / receivePrice receive
|
|
8
|
+
* tokens. This is the spot ratio — what the price card's "Market" reference and
|
|
9
|
+
* proximity indicator compare against. Returns `undefined` until both token
|
|
10
|
+
* prices are known.
|
|
11
|
+
*/
|
|
12
|
+
const useLimitMarketRate = () => {
|
|
13
|
+
const [fromChainId, fromTokenAddress, toChainId, toTokenAddress] = useFieldValues(FormKeyHelper.getChainKey("from"), FormKeyHelper.getTokenKey("from"), FormKeyHelper.getChainKey("to"), FormKeyHelper.getTokenKey("to"));
|
|
14
|
+
const { token: fromToken } = useToken(fromChainId, fromTokenAddress);
|
|
15
|
+
const { token: toToken } = useToken(toChainId, toTokenAddress);
|
|
16
|
+
const fromPrice = Number(fromToken?.priceUSD);
|
|
17
|
+
const toPrice = Number(toToken?.priceUSD);
|
|
18
|
+
if (!fromPrice || !toPrice || Number.isNaN(fromPrice) || Number.isNaN(toPrice)) return;
|
|
19
|
+
return fromPrice / toPrice;
|
|
20
|
+
};
|
|
21
|
+
//#endregion
|
|
22
|
+
export { useLimitMarketRate };
|
|
23
|
+
|
|
24
|
+
//# sourceMappingURL=useLimitMarketRate.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"useLimitMarketRate.js","names":[],"sources":["../../../src/hooks/useLimitMarketRate.ts"],"sourcesContent":["import { FormKeyHelper } from '../stores/form/types.js'\nimport { useFieldValues } from '../stores/form/useFieldValues.js'\nimport { useToken } from './useToken.js'\n\n/**\n * Canonical limit-order market rate (receive token per send token), derived\n * from the tokens' USD prices: 1 send token ≈ sendPrice / receivePrice receive\n * tokens. This is the spot ratio — what the price card's \"Market\" reference and\n * proximity indicator compare against. Returns `undefined` until both token\n * prices are known.\n */\nexport const useLimitMarketRate = (): number | undefined => {\n const [fromChainId, fromTokenAddress, toChainId, toTokenAddress] =\n useFieldValues(\n FormKeyHelper.getChainKey('from'),\n FormKeyHelper.getTokenKey('from'),\n FormKeyHelper.getChainKey('to'),\n FormKeyHelper.getTokenKey('to')\n )\n const { token: fromToken } = useToken(fromChainId, fromTokenAddress)\n const { token: toToken } = useToken(toChainId, toTokenAddress)\n\n const fromPrice = Number(fromToken?.priceUSD)\n const toPrice = Number(toToken?.priceUSD)\n\n // A `priceUSD` of `\"0\"` (or missing) means the price is unknown — there's no\n // meaningful spot ratio to derive, and dividing by a zero `toPrice` would be\n // `Infinity`, so the falsy guard intentionally suppresses the rate here.\n if (\n !fromPrice ||\n !toPrice ||\n Number.isNaN(fromPrice) ||\n Number.isNaN(toPrice)\n ) {\n return undefined\n }\n\n return fromPrice / toPrice\n}\n"],"mappings":";;;;;;;;;;;AAWA,MAAa,2BAA+C;CAC1D,MAAM,CAAC,aAAa,kBAAkB,WAAW,kBAC/C,eACE,cAAc,YAAY,MAAM,GAChC,cAAc,YAAY,MAAM,GAChC,cAAc,YAAY,IAAI,GAC9B,cAAc,YAAY,IAAI,CAChC;CACF,MAAM,EAAE,OAAO,cAAc,SAAS,aAAa,gBAAgB;CACnE,MAAM,EAAE,OAAO,YAAY,SAAS,WAAW,cAAc;CAE7D,MAAM,YAAY,OAAO,WAAW,QAAQ;CAC5C,MAAM,UAAU,OAAO,SAAS,QAAQ;CAKxC,IACE,CAAC,aACD,CAAC,WACD,OAAO,MAAM,SAAS,KACtB,OAAO,MAAM,OAAO,GAEpB;CAGF,OAAO,YAAY;AACrB"}
|
|
@@ -0,0 +1,49 @@
|
|
|
1
|
+
import { useFieldActions } from "../stores/form/useFieldActions.js";
|
|
2
|
+
import { FormKeyHelper } from "../stores/form/types.js";
|
|
3
|
+
import { useFieldValues } from "../stores/form/useFieldValues.js";
|
|
4
|
+
import { useToken } from "./useToken.js";
|
|
5
|
+
import { deriveLimitPrice, deriveReceiveAmount } from "../utils/limitOrder.js";
|
|
6
|
+
//#region src/hooks/useLinkedLimitFields.ts
|
|
7
|
+
/**
|
|
8
|
+
* Implements the linked-field derivation for limit orders:
|
|
9
|
+
* - `limitPrice = receiveAmount / sendAmount`
|
|
10
|
+
* - editing sendAmount recomputes receiveAmount, holding the current price
|
|
11
|
+
* - editing limitPrice (with a send amount set) recomputes receiveAmount
|
|
12
|
+
* - sendAmount never changes without an explicit user edit
|
|
13
|
+
*
|
|
14
|
+
* The receive amount (`toAmount`) is read-only in the UI — it is derived here
|
|
15
|
+
* from the send amount and limit price, then sent to the routes request; the
|
|
16
|
+
* receive card only displays the resulting quote.
|
|
17
|
+
*
|
|
18
|
+
* The limit price is NOT stored: it is purely a function of the `fromAmount`
|
|
19
|
+
* and `toAmount` form fields (canonical receive-per-send). The UI layer handles
|
|
20
|
+
* base/quote display inversion. Because it's derived, editing the send amount
|
|
21
|
+
* only has to preserve the pre-edit price.
|
|
22
|
+
*/
|
|
23
|
+
const useLinkedLimitFields = () => {
|
|
24
|
+
const { setFieldValue } = useFieldActions();
|
|
25
|
+
const [toChainId, toTokenAddress, sendAmount, receiveAmount] = useFieldValues(FormKeyHelper.getChainKey("to"), FormKeyHelper.getTokenKey("to"), FormKeyHelper.getAmountKey("from"), FormKeyHelper.getAmountKey("to"));
|
|
26
|
+
const { token: toToken } = useToken(toChainId, toTokenAddress);
|
|
27
|
+
const limitPrice = deriveLimitPrice(sendAmount, receiveAmount);
|
|
28
|
+
const setSendAmount = (value) => {
|
|
29
|
+
setFieldValue("fromAmount", value, {
|
|
30
|
+
isDirty: true,
|
|
31
|
+
isTouched: true
|
|
32
|
+
});
|
|
33
|
+
const nextReceive = deriveReceiveAmount(value, limitPrice, toToken?.decimals);
|
|
34
|
+
if (nextReceive) setFieldValue("toAmount", nextReceive, { isDirty: true });
|
|
35
|
+
};
|
|
36
|
+
const setLimitPrice = (value) => {
|
|
37
|
+
const nextReceive = deriveReceiveAmount(sendAmount, value, toToken?.decimals);
|
|
38
|
+
setFieldValue("toAmount", nextReceive, { isDirty: true });
|
|
39
|
+
};
|
|
40
|
+
return {
|
|
41
|
+
limitPrice,
|
|
42
|
+
setSendAmount,
|
|
43
|
+
setLimitPrice
|
|
44
|
+
};
|
|
45
|
+
};
|
|
46
|
+
//#endregion
|
|
47
|
+
export { useLinkedLimitFields };
|
|
48
|
+
|
|
49
|
+
//# sourceMappingURL=useLinkedLimitFields.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"useLinkedLimitFields.js","names":[],"sources":["../../../src/hooks/useLinkedLimitFields.ts"],"sourcesContent":["import { FormKeyHelper } from '../stores/form/types.js'\nimport { useFieldActions } from '../stores/form/useFieldActions.js'\nimport { useFieldValues } from '../stores/form/useFieldValues.js'\nimport { deriveLimitPrice, deriveReceiveAmount } from '../utils/limitOrder.js'\nimport { useToken } from './useToken.js'\n\nexport interface LinkedLimitFields {\n limitPrice: string\n /** Set the send amount (explicit user edit); derives receiveAmount when a price is set. */\n setSendAmount: (value: string) => void\n /** Set the limit price (canonical: receive per send); derives receiveAmount when a send amount is set. */\n setLimitPrice: (value: string) => void\n}\n\n/**\n * Implements the linked-field derivation for limit orders:\n * - `limitPrice = receiveAmount / sendAmount`\n * - editing sendAmount recomputes receiveAmount, holding the current price\n * - editing limitPrice (with a send amount set) recomputes receiveAmount\n * - sendAmount never changes without an explicit user edit\n *\n * The receive amount (`toAmount`) is read-only in the UI — it is derived here\n * from the send amount and limit price, then sent to the routes request; the\n * receive card only displays the resulting quote.\n *\n * The limit price is NOT stored: it is purely a function of the `fromAmount`\n * and `toAmount` form fields (canonical receive-per-send). The UI layer handles\n * base/quote display inversion. Because it's derived, editing the send amount\n * only has to preserve the pre-edit price.\n */\nexport const useLinkedLimitFields = (): LinkedLimitFields => {\n const { setFieldValue } = useFieldActions()\n const [toChainId, toTokenAddress, sendAmount, receiveAmount] = useFieldValues(\n FormKeyHelper.getChainKey('to'),\n FormKeyHelper.getTokenKey('to'),\n FormKeyHelper.getAmountKey('from'),\n FormKeyHelper.getAmountKey('to')\n )\n const { token: toToken } = useToken(toChainId, toTokenAddress)\n\n const limitPrice = deriveLimitPrice(sendAmount, receiveAmount)\n\n const setSendAmount = (value: string): void => {\n // Hold the pre-edit price (derived from the current fields) so changing the\n // send amount rescales the receive amount instead of moving the price.\n setFieldValue('fromAmount', value, { isDirty: true, isTouched: true })\n const nextReceive = deriveReceiveAmount(\n value,\n limitPrice,\n toToken?.decimals\n )\n if (nextReceive) {\n setFieldValue('toAmount', nextReceive, { isDirty: true })\n }\n }\n\n const setLimitPrice = (value: string): void => {\n // Write unconditionally (including '') so the receive amount tracks the\n // price both ways — clearing the price clears the derived receive amount\n // instead of leaving a stale value that re-derives the old price.\n const nextReceive = deriveReceiveAmount(\n sendAmount,\n value,\n toToken?.decimals\n )\n setFieldValue('toAmount', nextReceive, { isDirty: true })\n }\n\n return {\n limitPrice,\n setSendAmount,\n setLimitPrice,\n }\n}\n"],"mappings":";;;;;;;;;;;;;;;;;;;;;;AA8BA,MAAa,6BAAgD;CAC3D,MAAM,EAAE,kBAAkB,gBAAgB;CAC1C,MAAM,CAAC,WAAW,gBAAgB,YAAY,iBAAiB,eAC7D,cAAc,YAAY,IAAI,GAC9B,cAAc,YAAY,IAAI,GAC9B,cAAc,aAAa,MAAM,GACjC,cAAc,aAAa,IAAI,CACjC;CACA,MAAM,EAAE,OAAO,YAAY,SAAS,WAAW,cAAc;CAE7D,MAAM,aAAa,iBAAiB,YAAY,aAAa;CAE7D,MAAM,iBAAiB,UAAwB;EAG7C,cAAc,cAAc,OAAO;GAAE,SAAS;GAAM,WAAW;EAAK,CAAC;EACrE,MAAM,cAAc,oBAClB,OACA,YACA,SAAS,QACX;EACA,IAAI,aACF,cAAc,YAAY,aAAa,EAAE,SAAS,KAAK,CAAC;CAE5D;CAEA,MAAM,iBAAiB,UAAwB;EAI7C,MAAM,cAAc,oBAClB,YACA,OACA,SAAS,QACX;EACA,cAAc,YAAY,aAAa,EAAE,SAAS,KAAK,CAAC;CAC1D;CAEA,OAAO;EACL;EACA;EACA;CACF;AACF"}
|