UNPKG

@daimo/pay

Version:

Seamless crypto payments. Onboard users from any chain, any coin into your app with one click.

336 lines (333 loc) 12.9 kB
import { jsx, jsxs, Fragment } from 'react/jsx-runtime'; import { AnimatePresence } from 'framer-motion'; import { useState, useEffect } from 'react'; import { Container, ConnectingContainer, ConnectingAnimation, RetryButton, RetryIconContainer, Content } from './styles.js'; import Alert from '../../Common/Alert/index.js'; import Button from '../../Common/Button/index.js'; import { PageContent, ModalHeading, ModalContent, ModalContentContainer, ModalH1, ModalBody } from '../../Common/Modal/styles.js'; import Tooltip from '../../Common/Tooltip/index.js'; import SquircleSpinner from '../../Spinners/SquircleSpinner/index.js'; import { RetryIconCircle, AlertIcon, ExternalLinkIcon, TickIcon } from '../../../assets/icons.js'; import { useConnect } from '../../../hooks/useConnect.js'; import useLocales from '../../../hooks/useLocales.js'; import { usePayContext } from '../../../hooks/usePayContext.js'; import { detectBrowser } from '../../../utils/index.js'; import { useWallet } from '../../../wallets/useWallets.js'; import BrowserIcon from '../../Common/BrowserIcon/index.js'; import CircleSpinner from '../../Spinners/CircleSpinner/index.js'; const states = { CONNECTED: "connected", CONNECTING: "connecting", EXPIRING: "expiring", FAILED: "failed", REJECTED: "rejected", NOTCONNECTED: "notconnected", UNAVAILABLE: "unavailable" }; const contentVariants = { initial: { willChange: "transform,opacity", position: "relative", opacity: 0, scale: 0.95 }, animate: { position: "relative", opacity: 1, scale: 1, transition: { ease: [0.16, 1, 0.3, 1], duration: 0.4, delay: 0.05, position: { delay: 0 } } }, exit: { position: "absolute", opacity: 0, scale: 0.95, transition: { ease: [0.16, 1, 0.3, 1], duration: 0.3 } } }; const ConnectWithInjector = ({ switchConnectMethod, forceState }) => { const { connect } = useConnect({ mutation: { onMutate: (connector) => { if (connector.connector) { setStatus(states.CONNECTING); } else { setStatus(states.UNAVAILABLE); } }, onError(err) { console.error(err); }, onSettled(data, error) { if (error) { setShowTryAgainTooltip(true); setTimeout(() => setShowTryAgainTooltip(false), 3500); if (error.code) { switch (error.code) { case -32002: setStatus(states.NOTCONNECTED); break; case 4001: setStatus(states.REJECTED); break; default: setStatus(states.FAILED); break; } } else { if (error.message) { switch (error.message) { case "User rejected request": setStatus(states.REJECTED); break; default: setStatus(states.FAILED); break; } } } } setTimeout(triggerResize, 100); } } }); const { triggerResize } = usePayContext(); const { pendingConnectorId } = usePayContext(); const wallet = useWallet(pendingConnectorId ?? ""); const walletInfo = { name: wallet?.name, shortName: wallet?.shortName ?? wallet?.name, icon: wallet?.iconConnector ?? wallet?.icon, iconShape: wallet?.iconShape ?? "circle", iconShouldShrink: wallet?.iconShouldShrink }; const [showTryAgainTooltip, setShowTryAgainTooltip] = useState(false); const browser = detectBrowser(); const extensionUrl = wallet?.downloadUrls?.[browser]; const suggestedExtension = wallet?.downloadUrls ? { name: Object.keys(wallet?.downloadUrls)[0], label: Object.keys(wallet?.downloadUrls)[0]?.charAt(0).toUpperCase() + Object.keys(wallet?.downloadUrls)[0]?.slice(1), // Capitalise first letter, but this might be better suited as a lookup table url: wallet?.downloadUrls[Object.keys(wallet?.downloadUrls)[0]] } : void 0; const [status, setStatus] = useState( forceState ? forceState : !wallet?.isInstalled ? states.UNAVAILABLE : states.CONNECTING ); const locales = useLocales({ CONNECTORNAME: walletInfo.name, CONNECTORSHORTNAME: walletInfo.shortName ?? walletInfo.name, SUGGESTEDEXTENSIONBROWSER: suggestedExtension?.label ?? "your browser" }); const runConnect = async () => { if (wallet?.isInstalled && wallet?.connector) { connect({ connector: wallet?.connector }); } else { setStatus(states.UNAVAILABLE); } }; useEffect(() => { if (status === states.UNAVAILABLE) return; const connectTimeout = setTimeout(runConnect, 600); return () => { clearTimeout(connectTimeout); }; }, []); if (!wallet) { return /* @__PURE__ */ jsx(PageContent, { children: /* @__PURE__ */ jsxs(Container, { children: [ /* @__PURE__ */ jsx(ModalHeading, { children: locales.invalidState_heading }), /* @__PURE__ */ jsx(ModalContent, { children: /* @__PURE__ */ jsx(Alert, { children: locales.invalidState_description }) }) ] }) }); } return /* @__PURE__ */ jsx(PageContent, { children: /* @__PURE__ */ jsxs(Container, { children: [ /* @__PURE__ */ jsx(ConnectingContainer, { children: /* @__PURE__ */ jsxs( ConnectingAnimation, { $shake: status === states.FAILED || status === states.REJECTED, $circle: walletInfo.iconShape === "circle", children: [ /* @__PURE__ */ jsx(AnimatePresence, { children: (status === states.FAILED || status === states.REJECTED) && /* @__PURE__ */ jsx( RetryButton, { "aria-label": locales.retry, initial: { opacity: 0, scale: 0.8 }, animate: { opacity: 1, scale: 1 }, exit: { opacity: 0, scale: 0.8 }, whileTap: { scale: 0.9 }, transition: { duration: 0.1 }, onClick: runConnect, children: /* @__PURE__ */ jsx(RetryIconContainer, { children: /* @__PURE__ */ jsx( Tooltip, { open: showTryAgainTooltip && (status === states.FAILED || status === states.REJECTED), message: locales.tryAgainQuestion, xOffset: -6, children: /* @__PURE__ */ jsx(RetryIconCircle, {}) } ) }) } ) }), walletInfo.iconShape === "circle" ? /* @__PURE__ */ jsx( CircleSpinner, { logo: status === states.UNAVAILABLE ? /* @__PURE__ */ jsx( "div", { style: { transform: "scale(1.14)", position: "relative", width: "100%" }, children: walletInfo.icon } ) : /* @__PURE__ */ jsx(Fragment, { children: walletInfo.icon }), smallLogo: walletInfo.iconShouldShrink, loading: status === states.CONNECTING, unavailable: status === states.UNAVAILABLE } ) : /* @__PURE__ */ jsx( SquircleSpinner, { logo: status === states.UNAVAILABLE ? /* @__PURE__ */ jsx( "div", { style: { transform: "scale(1.14)", position: "relative", width: "100%" }, children: walletInfo.icon } ) : /* @__PURE__ */ jsx(Fragment, { children: walletInfo.icon }), loading: status === states.CONNECTING } ) ] } ) }), /* @__PURE__ */ jsx(ModalContentContainer, { children: /* @__PURE__ */ jsxs(AnimatePresence, { initial: false, children: [ status === states.FAILED && /* @__PURE__ */ jsx( Content, { initial: "initial", animate: "animate", exit: "exit", variants: contentVariants, children: /* @__PURE__ */ jsxs(ModalContent, { children: [ /* @__PURE__ */ jsxs(ModalH1, { $error: true, children: [ /* @__PURE__ */ jsx(AlertIcon, {}), locales.injectionScreen_failed_h1 ] }), /* @__PURE__ */ jsx(ModalBody, { children: locales.injectionScreen_failed_p }) ] }) }, states.FAILED ), status === states.REJECTED && /* @__PURE__ */ jsx( Content, { initial: "initial", animate: "animate", exit: "exit", variants: contentVariants, children: /* @__PURE__ */ jsxs(ModalContent, { style: { paddingBottom: 28 }, children: [ /* @__PURE__ */ jsx(ModalH1, { children: locales.injectionScreen_rejected_h1 }), /* @__PURE__ */ jsx(ModalBody, { children: locales.injectionScreen_rejected_p }) ] }) }, states.REJECTED ), (status === states.CONNECTING || status === states.EXPIRING) && /* @__PURE__ */ jsx( Content, { initial: "initial", animate: "animate", exit: "exit", variants: contentVariants, children: /* @__PURE__ */ jsxs(ModalContent, { style: { paddingBottom: 28 }, children: [ /* @__PURE__ */ jsx(ModalH1, { children: wallet.connector?.id === "injected" ? locales.injectionScreen_connecting_injected_h1 : locales.injectionScreen_connecting_h1 }), /* @__PURE__ */ jsx(ModalBody, { children: wallet.connector?.id === "injected" ? locales.injectionScreen_connecting_injected_p : locales.injectionScreen_connecting_p }), /* @__PURE__ */ jsxs(Button, { icon: /* @__PURE__ */ jsx(ExternalLinkIcon, {}), onClick: runConnect, children: [ "Connect ", walletInfo.name ] }) ] }) }, states.CONNECTING ), status === states.CONNECTED && /* @__PURE__ */ jsx( Content, { initial: "initial", animate: "animate", exit: "exit", variants: contentVariants, children: /* @__PURE__ */ jsxs(ModalContent, { children: [ /* @__PURE__ */ jsxs(ModalH1, { $valid: true, children: [ /* @__PURE__ */ jsx(TickIcon, {}), " ", locales.injectionScreen_connected_h1 ] }), /* @__PURE__ */ jsx(ModalBody, { children: locales.injectionScreen_connected_p }) ] }) }, states.CONNECTED ), status === states.NOTCONNECTED && /* @__PURE__ */ jsx( Content, { initial: "initial", animate: "animate", exit: "exit", variants: contentVariants, children: /* @__PURE__ */ jsxs(ModalContent, { children: [ /* @__PURE__ */ jsx(ModalH1, { children: locales.injectionScreen_notconnected_h1 }), /* @__PURE__ */ jsx(ModalBody, { children: locales.injectionScreen_notconnected_p }) ] }) }, states.NOTCONNECTED ), status === states.UNAVAILABLE && /* @__PURE__ */ jsx( Content, { initial: "initial", animate: "animate", exit: "exit", variants: contentVariants, children: !extensionUrl ? /* @__PURE__ */ jsxs(Fragment, { children: [ /* @__PURE__ */ jsxs(ModalContent, { style: { paddingBottom: 12 }, children: [ /* @__PURE__ */ jsx(ModalH1, { children: locales.injectionScreen_unavailable_h1 }), /* @__PURE__ */ jsx(ModalBody, { children: locales.injectionScreen_unavailable_p }) ] }), !wallet.isInstalled && suggestedExtension && /* @__PURE__ */ jsxs( Button, { href: suggestedExtension?.url, icon: /* @__PURE__ */ jsx(BrowserIcon, { browser: suggestedExtension?.name }), children: [ "Install on ", suggestedExtension?.label ] } ) ] }) : /* @__PURE__ */ jsxs(Fragment, { children: [ /* @__PURE__ */ jsxs(ModalContent, { style: { paddingBottom: 18 }, children: [ /* @__PURE__ */ jsx(ModalH1, { children: locales.injectionScreen_install_h1 }), /* @__PURE__ */ jsx(ModalBody, { children: locales.injectionScreen_install_p }) ] }), !wallet.isInstalled && extensionUrl && /* @__PURE__ */ jsx(Button, { href: extensionUrl, icon: /* @__PURE__ */ jsx(BrowserIcon, {}), children: locales.installTheExtension }) ] }) }, states.UNAVAILABLE ) ] }) }) ] }) }); }; export { ConnectWithInjector as default, states }; //# sourceMappingURL=index.js.map