@coin-voyage/paykit
Version:
Seamless crypto payments. Onboard users from any chain, any coin into your app with one click.
138 lines (137 loc) • 5.43 kB
JavaScript
import { jsx as _jsx, jsxs as _jsxs, Fragment as _Fragment } from "react/jsx-runtime";
import { useAccount } from "@coin-voyage/crypto/hooks";
import { truncateAddress } from "@coin-voyage/shared/common";
import { motion } from "framer-motion";
import { Arbitrum, Bitcoin, Ethereum, Optimism, Solana, Sui } from "../../../assets/chains";
import { USDC } from "../../../assets/coins";
import defaultTheme from "../../../lib/config/default-theme";
import styled from "../../../styles/styled";
import usePayContext from "../../contexts/pay";
export const OrderHeader = ({ minified = false, showConnectedWallet = false }) => {
const { paymentState } = usePayContext();
const { senderEnsName, selectedWallet, connectorChainType, payOrder } = paymentState;
const { account } = useAccount({
selectedWallet,
chainType: connectorChainType,
});
const renderIcon = (icon, name, size = 32) => {
if (!icon) {
return null;
}
return (_jsx(LogoContainer, { "$size": size, "$zIndex": 1, style: { borderRadius: "22.5%" }, children: typeof icon === "string" ? (_jsx("img", { src: icon, alt: name || "wallet", style: { maxWidth: "100%", maxHeight: "100%" } })) : (icon) }));
};
if (minified) {
return (_jsxs(MinifiedContainer, { children: [_jsx(MinifiedTitleAmount, { children: _jsx(TitleAmountContent, { fulfillment: payOrder?.fulfillment }) }), showConnectedWallet ? (_jsx(ConnectedWallet, { account: account, senderEnsName: senderEnsName, renderIcon: renderIcon })) : (_jsx(CoinLogos, { "$size": 32 }))] }));
}
return (_jsxs(_Fragment, { children: [_jsx(TitleAmount, { children: _jsx(TitleAmountContent, { fulfillment: payOrder?.fulfillment }) }), _jsxs(AnyChainAnyCoinContainer, { children: [showConnectedWallet ? (_jsx(ConnectedWallet, { account: account, senderEnsName: senderEnsName, renderIcon: renderIcon })) : (_jsx(CoinLogos, {})), _jsx(Subtitle, { children: "1000+ tokens accepted" })] })] }));
};
const TitleAmountContent = ({ fulfillment }) => {
if (!fulfillment)
return null;
return (_jsx("span", { children: fulfillment.fiat ? (_jsx(_Fragment, { children: new Intl.NumberFormat("en-US", {
style: "currency",
currency: fulfillment.fiat,
}).format(fulfillment.amount.value_usd) })) : (_jsxs(_Fragment, { children: [fulfillment.amount.ui_amount_display, " ", fulfillment.asset?.ticker] })) }));
};
const ConnectedWallet = ({ account, senderEnsName, renderIcon }) => {
if (!account?.address)
return null;
return (_jsxs(SubtitleContainer, { children: [_jsx(Subtitle, { children: senderEnsName ?? truncateAddress(account.address) }), renderIcon(account.connector?.icon, account.connector?.name)] }));
};
const TitleAmount = styled(motion.h1) `
margin: 0;
padding: 0;
line-height: 50px;
font-size: 48px;
font-weight: var(--ck-modal-h1-font-weight, 600);
color: ${(props) => {
if (props.$error) {
return "var(--ck-body-color-danger)";
}
if (props.$valid) {
return "var(--ck-body-color-valid)";
}
return "var(--ck-body-color)";
}};
@media only screen and (max-width: ${defaultTheme.mobileWidth}px) {
font-size: 64px;
}
display: flex;
align-items: center;
justify-content: center;
gap: 8px;
`;
const Subtitle = styled(motion.div) `
font-size: 18px;
font-weight: 500;
line-height: 21px;
color: var(--ck-body-color-muted);
`;
const MinifiedTitleAmount = styled(motion.div) `
font-size: 32px;
font-weight: var(--ck-modal-h1-font-weight, 600);
line-height: 36px;
color: var(--ck-body-color);
display: flex;
align-items: center;
justify-content: start;
gap: 8px;
`;
const MinifiedContainer = styled(motion.div) `
display: flex;
align-items: center;
justify-content: space-between;
width: 100%;
margin-bottom: 24px;
`;
const AnyChainAnyCoinContainer = styled(motion.div) `
display: flex;
vertical-align: middle;
align-items: center;
justify-content: center;
text-align: center;
gap: 8px;
margin: 24px 0;
`;
const LogoContainer = styled(motion.div) `
display: block;
overflow: hidden;
user-select: none;
display: flex;
align-items: center;
justify-content: center;
margin-left: ${(props) => props.$marginLeft || 0}px;
z-index: ${(props) => props.$zIndex || 2};
width: ${(props) => props.$size}px;
height: ${(props) => props.$size}px;
border-radius: 9999px;
svg {
display: block;
width: 100%;
height: auto;
}
`;
const Logos = styled(motion.div) `
display: flex;
align-items: center;
justify-content: center;
`;
const SubtitleContainer = styled.div `
display: flex;
align-items: center;
justify-content: flex-end;
gap: 8px;
`;
const CoinLogos = ({ $size = 24 }) => {
const logos = [
_jsx(Bitcoin, {}, "bit"),
_jsx(Ethereum, { style: { backgroundColor: "#627EEA" } }, "eth"),
_jsx(Solana, {}, "sol"),
_jsx(Sui, {}, "sui"),
_jsx(USDC, {}, "usdc"),
_jsx(Optimism, {}, "opt"),
_jsx(Arbitrum, {}, "arb"),
];
const logoBlock = (element, index) => (_jsx(LogoContainer, { "$marginLeft": index !== 0 ? -($size / 3) : 0, "$zIndex": logos.length - index, "$size": $size, transition: { duration: 0.5, ease: [0.175, 0.885, 0.32, 0.98] }, children: element }, index));
return _jsx(Logos, { children: logos.map((element, index) => logoBlock(element, index)) });
};