@aptos-labs/wallet-adapter-mui-design
Version:
Aptos Wallet Adapter mui design
718 lines (710 loc) • 23.7 kB
JavaScript
// src/WalletConnector.tsx
import { useState as useState4 } from "react";
// src/WalletButton.tsx
import { truncateAddress, useWallet as useWallet2 } from "@aptos-labs/wallet-adapter-react";
import { AccountBalanceWalletOutlined as AccountBalanceWalletOutlinedIcon } from "@mui/icons-material";
import { Avatar, Button, Typography } from "@mui/material";
import { useState as useState2 } from "react";
// src/WalletMenu.tsx
import { useWallet } from "@aptos-labs/wallet-adapter-react";
import {
List,
ListItem,
ListItemButton,
ListItemText,
Popover,
Tooltip
} from "@mui/material";
import { useState } from "react";
import { jsx, jsxs } from "react/jsx-runtime";
function WalletMenu({
popoverAnchor,
handlePopoverClose,
handleNavigate
}) {
const { account, disconnect } = useWallet();
const popoverOpen = Boolean(popoverAnchor);
const id = popoverOpen ? "wallet-popover" : void 0;
const onAccountOptionClicked = () => {
handleNavigate?.();
handlePopoverClose();
};
const handleLogout = () => {
disconnect();
handlePopoverClose();
};
const [tooltipOpen, setTooltipOpen] = useState(false);
const copyAddress = async () => {
await navigator.clipboard.writeText(account?.address?.toString() ?? "");
setTooltipOpen(true);
setTimeout(() => {
setTooltipOpen(false);
}, 2e3);
};
return /* @__PURE__ */ jsx(
Popover,
{
id,
open: popoverOpen,
anchorEl: popoverAnchor,
onClose: handlePopoverClose,
anchorOrigin: {
vertical: "bottom",
horizontal: "left"
},
children: /* @__PURE__ */ jsxs(List, { children: [
/* @__PURE__ */ jsx(
Tooltip,
{
title: "Copied",
placement: "bottom-end",
open: tooltipOpen,
disableFocusListener: true,
disableHoverListener: true,
disableTouchListener: true,
children: /* @__PURE__ */ jsx(ListItem, { disablePadding: true, children: /* @__PURE__ */ jsx(ListItemButton, { onClick: copyAddress, children: /* @__PURE__ */ jsx(ListItemText, { primary: "Copy Address" }) }) })
}
),
!!handleNavigate && /* @__PURE__ */ jsx(ListItem, { disablePadding: true, children: /* @__PURE__ */ jsx(ListItemButton, { onClick: onAccountOptionClicked, children: /* @__PURE__ */ jsx(ListItemText, { primary: "Account" }) }) }),
/* @__PURE__ */ jsx(ListItem, { disablePadding: true, children: /* @__PURE__ */ jsx(ListItemButton, { onClick: handleLogout, children: /* @__PURE__ */ jsx(ListItemText, { primary: "Logout" }) }) })
] })
}
);
}
// src/WalletButton.tsx
import { Fragment, jsx as jsx2, jsxs as jsxs2 } from "react/jsx-runtime";
function WalletButton({
handleModalOpen,
handleNavigate
}) {
const { connected, account, wallet } = useWallet2();
const [popoverAnchor, setPopoverAnchor] = useState2(
null
);
const handleClick = (event) => {
setPopoverAnchor(event.currentTarget);
};
const handlePopoverClose = () => {
setPopoverAnchor(null);
};
const onConnectWalletClick = () => {
handlePopoverClose();
handleModalOpen();
};
return /* @__PURE__ */ jsxs2(Fragment, { children: [
/* @__PURE__ */ jsx2(
Button,
{
size: "large",
variant: "contained",
onClick: connected ? handleClick : onConnectWalletClick,
className: "wallet-button",
sx: { borderRadius: "10px" },
children: connected ? /* @__PURE__ */ jsxs2(Fragment, { children: [
/* @__PURE__ */ jsx2(
Avatar,
{
alt: wallet?.name,
src: wallet?.icon,
sx: { width: 24, height: 24 }
}
),
/* @__PURE__ */ jsx2(Typography, { noWrap: true, ml: 2, children: account?.ansName || truncateAddress(account?.address?.toString()) || "Unknown" })
] }) : /* @__PURE__ */ jsxs2(Fragment, { children: [
/* @__PURE__ */ jsx2(AccountBalanceWalletOutlinedIcon, { sx: { marginRight: 1 } }),
/* @__PURE__ */ jsx2(Typography, { noWrap: true, children: "Connect Wallet" })
] })
}
),
/* @__PURE__ */ jsx2(
WalletMenu,
{
popoverAnchor,
handlePopoverClose,
handleNavigate
}
)
] });
}
// src/WalletModel.tsx
import {
AboutAptosConnect,
AptosPrivacyPolicy,
groupAndSortWallets,
isInstallRequired,
useWallet as useWallet3,
WalletItem
} from "@aptos-labs/wallet-adapter-react";
import {
ArrowBack,
ArrowForward,
Close as CloseIcon,
ExpandMore,
LanOutlined as LanOutlinedIcon
} from "@mui/icons-material";
import {
Box,
Button as Button2,
Collapse,
Dialog,
Divider,
IconButton,
ListItem as ListItem2,
ListItemText as ListItemText2,
Stack,
Tab,
Tabs,
Typography as Typography2,
useTheme
} from "@mui/material";
import { useState as useState3 } from "react";
// src/aptosColorPalette.ts
var grey = {
50: "#fafafa",
100: "#f4f4f5",
200: "#e4e4e7",
300: "#d4d4d8",
400: "#a1a1aa",
450: "#909099",
500: "#4f5352",
600: "#363a39",
700: "#272b2a",
800: "#1b1f1e",
900: "#121615"
};
// src/WalletModel.tsx
import { Fragment as Fragment2, jsx as jsx3, jsxs as jsxs3 } from "react/jsx-runtime";
function WalletsModal({
handleClose,
modalOpen,
networkSupport,
modalMaxWidth,
crossChainWallets,
...walletSortingOptions
}) {
const theme = useTheme();
const [expanded, setExpanded] = useState3(false);
const [tabValue, setTabValue] = useState3(0);
const handleTabChange = (_event, newValue) => {
setTabValue(newValue);
};
const { wallets = [], notDetectedWallets = [] } = useWallet3();
const { aptosConnectWallets, availableWallets, installableWallets } = groupAndSortWallets(
[...wallets, ...notDetectedWallets],
walletSortingOptions
);
const hasAptosConnectWallets = !!aptosConnectWallets.length;
const crossChainMode = crossChainWallets && (crossChainWallets.evm || crossChainWallets.solana);
const { evmWallets, solanaWallets, aptosWallets } = crossChainMode ? availableWallets.reduce(
(acc, wallet) => {
if (wallet.name.includes("Ethereum")) {
acc.evmWallets.push(wallet);
} else if (wallet.name.includes("Solana")) {
acc.solanaWallets.push(wallet);
} else {
acc.aptosWallets.push(wallet);
}
return acc;
},
{ evmWallets: [], solanaWallets: [], aptosWallets: [] }
) : { evmWallets: [], solanaWallets: [], aptosWallets: availableWallets };
const {
evmInstallableWallets,
solanaInstallableWallets,
aptosInstallableWallets
} = crossChainMode ? installableWallets.reduce(
(acc, wallet) => {
if (wallet.name.includes("Ethereum")) {
acc.evmInstallableWallets.push(wallet);
} else if (wallet.name.includes("Solana")) {
acc.solanaInstallableWallets.push(wallet);
} else {
acc.aptosInstallableWallets.push(wallet);
}
return acc;
},
{
evmInstallableWallets: [],
solanaInstallableWallets: [],
aptosInstallableWallets: []
}
) : {
evmInstallableWallets: [],
solanaInstallableWallets: [],
aptosInstallableWallets: installableWallets
};
const tabsConfig = crossChainMode ? [
{ key: "aptos", label: "Aptos", enabled: true },
{ key: "solana", label: "Solana", enabled: crossChainWallets.solana },
{ key: "evm", label: "Ethereum", enabled: crossChainWallets.evm }
].filter((tab) => tab.enabled) : [];
const getTabIndex = (key) => tabsConfig.findIndex((tab) => tab.key === key);
const renderWalletList = (wallets2, installableWallets2) => /* @__PURE__ */ jsxs3(Fragment2, { children: [
wallets2.map((wallet) => /* @__PURE__ */ jsx3(WalletRow, { wallet, onConnect: handleClose }, wallet.name)),
!!installableWallets2.length && /* @__PURE__ */ jsxs3(Fragment2, { children: [
/* @__PURE__ */ jsx3(
Button2,
{
variant: "text",
size: "small",
onClick: () => setExpanded((prev) => !prev),
endIcon: /* @__PURE__ */ jsx3(ExpandMore, { sx: { height: "20px", width: "20px" } }),
children: "More Wallets"
}
),
/* @__PURE__ */ jsx3(Collapse, { in: expanded, timeout: "auto", unmountOnExit: true, children: /* @__PURE__ */ jsx3(Stack, { sx: { gap: 1 }, children: installableWallets2.map((wallet) => /* @__PURE__ */ jsx3(
WalletRow,
{
wallet,
onConnect: handleClose
},
wallet.name
)) }) })
] })
] });
return /* @__PURE__ */ jsx3(
Dialog,
{
open: modalOpen,
onClose: handleClose,
"aria-label": "wallet selector modal",
sx: { borderRadius: `${theme.shape.borderRadius}px` },
maxWidth: modalMaxWidth ?? "xs",
fullWidth: true,
children: /* @__PURE__ */ jsxs3(
Stack,
{
sx: {
top: "50%",
left: "50%",
bgcolor: "background.paper",
boxShadow: 24,
p: 3,
gap: 2
},
children: [
/* @__PURE__ */ jsx3(
IconButton,
{
onClick: handleClose,
sx: {
position: "absolute",
right: 12,
top: 12,
color: grey[450]
},
children: /* @__PURE__ */ jsx3(CloseIcon, {})
}
),
/* @__PURE__ */ jsxs3(AboutAptosConnect, { renderEducationScreen, children: [
/* @__PURE__ */ jsx3(
Typography2,
{
align: "center",
variant: "h5",
component: "h2",
pt: 2,
sx: {
display: "flex",
flexDirection: "column"
},
children: hasAptosConnectWallets ? /* @__PURE__ */ jsxs3(Fragment2, { children: [
/* @__PURE__ */ jsx3("span", { children: "Log in or sign up" }),
/* @__PURE__ */ jsx3("span", { children: "with Social + Petra Web" })
] }) : "Connect Wallet"
}
),
networkSupport && /* @__PURE__ */ jsxs3(
Box,
{
sx: {
display: "flex",
gap: 0.5,
alignItems: "center",
justifyContent: "center"
},
children: [
/* @__PURE__ */ jsx3(
LanOutlinedIcon,
{
sx: {
fontSize: "0.9rem",
color: grey[400]
}
}
),
/* @__PURE__ */ jsxs3(
Typography2,
{
sx: {
display: "inline-flex",
fontSize: "0.9rem",
color: grey[400]
},
align: "center",
children: [
networkSupport,
" only"
]
}
)
]
}
),
hasAptosConnectWallets && /* @__PURE__ */ jsxs3(Stack, { gap: 1, children: [
aptosConnectWallets.map((wallet) => /* @__PURE__ */ jsx3(
AptosConnectWalletRow,
{
wallet,
onConnect: handleClose
},
wallet.name
)),
/* @__PURE__ */ jsxs3(
Typography2,
{
component: "p",
fontSize: "14px",
sx: {
display: "flex",
gap: 0.5,
justifyContent: "center",
alignItems: "center",
color: grey[400]
},
children: [
"Learn more about",
" ",
/* @__PURE__ */ jsxs3(
Box,
{
component: AboutAptosConnect.Trigger,
sx: {
background: "none",
border: "none",
fontFamily: "inherit",
fontSize: "inherit",
cursor: "pointer",
display: "flex",
gap: 0.5,
px: 0,
py: 1.5,
alignItems: "center",
color: theme.palette.text.primary,
appearance: "none"
},
children: [
"Petra Web ",
/* @__PURE__ */ jsx3(ArrowForward, { sx: { height: 16, width: 16 } })
]
}
)
]
}
),
/* @__PURE__ */ jsxs3(
Stack,
{
component: AptosPrivacyPolicy,
alignItems: "center",
py: 0.5,
children: [
/* @__PURE__ */ jsxs3(Typography2, { component: "p", fontSize: "12px", lineHeight: "20px", children: [
/* @__PURE__ */ jsx3(AptosPrivacyPolicy.Disclaimer, {}),
" ",
/* @__PURE__ */ jsx3(
Box,
{
component: AptosPrivacyPolicy.Link,
sx: {
color: grey[400],
textDecoration: "underline",
textUnderlineOffset: "4px"
}
}
),
/* @__PURE__ */ jsx3("span", { children: "." })
] }),
/* @__PURE__ */ jsx3(
Box,
{
component: AptosPrivacyPolicy.PoweredBy,
sx: {
display: "flex",
alignItems: "center",
gap: 0.75,
fontSize: "12px",
lineHeight: "20px",
color: grey[400]
}
}
)
]
}
),
/* @__PURE__ */ jsx3(Divider, { sx: { color: grey[400], pt: 2 }, children: "Or" })
] }),
crossChainMode ? /* @__PURE__ */ jsxs3(Fragment2, { children: [
/* @__PURE__ */ jsx3(
Tabs,
{
value: tabValue,
onChange: handleTabChange,
textColor: "secondary",
indicatorColor: "secondary",
variant: "fullWidth",
"aria-label": "cross chain wallets tabs",
children: tabsConfig.map((tab, index) => /* @__PURE__ */ jsx3(Tab, { label: tab.label, ...a11yProps(index) }, tab.key))
}
),
/* @__PURE__ */ jsx3(TabPanel, { value: tabValue, index: getTabIndex("aptos"), children: renderWalletList(aptosWallets, aptosInstallableWallets) }),
crossChainWallets.solana && /* @__PURE__ */ jsx3(TabPanel, { value: tabValue, index: getTabIndex("solana"), children: renderWalletList(solanaWallets, solanaInstallableWallets) }),
crossChainWallets.evm && /* @__PURE__ */ jsx3(TabPanel, { value: tabValue, index: getTabIndex("evm"), children: renderWalletList(evmWallets, evmInstallableWallets) })
] }) : (
// Simple list mode (original WalletModel behavior)
/* @__PURE__ */ jsx3(Stack, { sx: { gap: 1 }, children: renderWalletList(availableWallets, installableWallets) })
)
] })
]
}
)
}
);
}
function WalletRow({ wallet, onConnect }) {
const theme = useTheme();
return /* @__PURE__ */ jsx3(WalletItem, { wallet, onConnect, asChild: true, children: /* @__PURE__ */ jsx3(ListItem2, { disablePadding: true, children: /* @__PURE__ */ jsxs3(
Box,
{
sx: {
display: "flex",
alignItems: "center",
width: "100%",
px: 2,
py: 1.5,
gap: 2,
border: "solid 1px",
borderColor: theme.palette.mode === "dark" ? grey[700] : grey[200],
borderRadius: `${theme.shape.borderRadius}px`
},
children: [
/* @__PURE__ */ jsx3(Box, { component: WalletItem.Icon, sx: { width: 32, height: 32 } }),
/* @__PURE__ */ jsx3(
ListItemText2,
{
primary: wallet.name,
primaryTypographyProps: { fontSize: "1.125rem" }
}
),
isInstallRequired(wallet) ? /* @__PURE__ */ jsx3(WalletItem.InstallLink, { asChild: true, children: /* @__PURE__ */ jsx3(
Button2,
{
LinkComponent: "a",
size: "small",
className: "wallet-connect-install",
children: "Install"
}
) }) : /* @__PURE__ */ jsx3(WalletItem.ConnectButton, { asChild: true, children: /* @__PURE__ */ jsx3(
Button2,
{
variant: "contained",
size: "small",
className: "wallet-connect-button",
children: "Connect"
}
) })
]
}
) }) });
}
function AptosConnectWalletRow({ wallet, onConnect }) {
return /* @__PURE__ */ jsx3(WalletItem, { wallet, onConnect, asChild: true, children: /* @__PURE__ */ jsx3(WalletItem.ConnectButton, { asChild: true, children: /* @__PURE__ */ jsxs3(
Button2,
{
size: "large",
variant: "outlined",
sx: { display: "flex", alignItems: "center", gap: 1.5 },
children: [
/* @__PURE__ */ jsx3(Box, { component: WalletItem.Icon, sx: { width: 20, height: 20 } }),
/* @__PURE__ */ jsx3(WalletItem.Name, {})
]
}
) }) });
}
function renderEducationScreen(screen) {
return /* @__PURE__ */ jsxs3(Fragment2, { children: [
/* @__PURE__ */ jsxs3(
Box,
{
sx: {
display: "grid",
gridTemplateColumns: "1fr 4fr 1fr",
alignItems: "center",
justifyItems: "start"
},
children: [
/* @__PURE__ */ jsx3(IconButton, { onClick: screen.cancel, children: /* @__PURE__ */ jsx3(ArrowBack, {}) }),
/* @__PURE__ */ jsx3(Typography2, { variant: "body1", component: "h2", width: "100%", align: "center", children: "About Petra Web" })
]
}
),
/* @__PURE__ */ jsx3(
Box,
{
sx: {
display: "flex",
pb: 1.5,
alignItems: "end",
justifyContent: "center",
height: "162px"
},
children: /* @__PURE__ */ jsx3(screen.Graphic, {})
}
),
/* @__PURE__ */ jsxs3(Stack, { sx: { gap: 1, textAlign: "center", pb: 2 }, children: [
/* @__PURE__ */ jsx3(Typography2, { component: screen.Title, variant: "h6" }),
/* @__PURE__ */ jsx3(
Typography2,
{
component: screen.Description,
variant: "body2",
color: (theme) => theme.palette.text.secondary,
sx: {
"&>a": {
color: (theme) => theme.palette.text.primary,
textDecoration: "underline",
textUnderlineOffset: "4px"
}
}
}
)
] }),
/* @__PURE__ */ jsxs3(
Box,
{
sx: {
display: "grid",
gridTemplateColumns: "repeat(3, minmax(0, 1fr))",
alignItems: "center"
},
children: [
/* @__PURE__ */ jsx3(
Button2,
{
size: "small",
variant: "text",
onClick: screen.back,
sx: { justifySelf: "start" },
children: "Back"
}
),
/* @__PURE__ */ jsx3(
Box,
{
sx: {
display: "flex",
alignItems: "center",
gap: 1,
placeSelf: "center"
},
children: screen.screenIndicators.map((ScreenIndicator, i) => /* @__PURE__ */ jsx3(
Box,
{
component: ScreenIndicator,
sx: {
px: 0,
py: 2,
background: "none",
border: "none",
cursor: "pointer"
},
children: /* @__PURE__ */ jsx3(
Box,
{
sx: {
height: "2px",
width: "24px",
bgcolor: (theme) => theme.palette.text.disabled,
"[data-active]>&": {
bgcolor: (theme) => theme.palette.text.primary
}
}
}
)
},
i
))
}
),
/* @__PURE__ */ jsx3(
Button2,
{
size: "small",
variant: "text",
onClick: screen.next,
sx: { justifySelf: "end" },
endIcon: /* @__PURE__ */ jsx3(ArrowForward, { sx: { height: 16, width: 16 } }),
children: screen.screenIndex === screen.totalScreens - 1 ? "Finish" : "Next"
}
)
]
}
)
] });
}
function TabPanel(props) {
const { children, value, index, ...other } = props;
return /* @__PURE__ */ jsx3(
"div",
{
role: "tabpanel",
hidden: value !== index,
id: `simple-tabpanel-${index}`,
"aria-labelledby": `simple-tab-${index}`,
...other,
children: value === index && /* @__PURE__ */ jsx3(Stack, { sx: { gap: 1 }, children })
}
);
}
function a11yProps(index) {
return {
id: `simple-tab-${index}`,
"aria-controls": `simple-tabpanel-${index}`
};
}
// src/WalletConnector.tsx
import { Fragment as Fragment3, jsx as jsx4, jsxs as jsxs4 } from "react/jsx-runtime";
function WalletConnector({
networkSupport,
handleNavigate,
modalMaxWidth,
crossChainWallets,
...walletSortingOptions
}) {
const [modalOpen, setModalOpen] = useState4(false);
const handleModalOpen = () => setModalOpen(true);
const handleClose = () => setModalOpen(false);
return /* @__PURE__ */ jsxs4(Fragment3, { children: [
/* @__PURE__ */ jsx4(
WalletButton,
{
handleModalOpen,
handleNavigate
}
),
/* @__PURE__ */ jsx4(
WalletsModal,
{
handleClose,
modalOpen,
networkSupport,
modalMaxWidth,
crossChainWallets,
...walletSortingOptions
}
)
] });
}
export {
WalletConnector
};