UNPKG

@lifi/widget

Version:

LI.FI Widget for cross-chain bridging and swapping. It will drive your multi-chain strategy and attract new users from everywhere.

118 lines 7.5 kB
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime"; import { ChainType } from '@lifi/sdk'; import InfoOutlinedIcon from '@mui/icons-material/InfoOutlined'; import { Avatar, Box, ListItemAvatar, ListItemText, Skeleton, Slide, Typography, } from '@mui/material'; import { memo, useRef, useState } from 'react'; import { useTranslation } from 'react-i18next'; import { useLongPress } from '../../hooks/useLongPress.js'; import { formatTokenAmount, formatTokenPrice } from '../../utils/format.js'; import { shortenAddress } from '../../utils/wallet.js'; import { ListItemButton } from '../ListItem/ListItemButton.js'; import { IconButton, ListItem } from './TokenList.style.js'; export const TokenListItem = memo(({ onClick, size, start, token, chain, accountAddress, isBalanceLoading, startAdornment, endAdornment, selected, onShowTokenDetails, }) => { const handleClick = (e) => { e.stopPropagation(); onClick?.(token.address, chain?.id); }; return (_jsxs(ListItem, { style: { height: `${size}px`, transform: `translateY(${start}px)`, padding: 0, }, children: [startAdornment, _jsx(TokenListItemButton, { token: token, chain: chain, accountAddress: accountAddress, isBalanceLoading: isBalanceLoading, onClick: handleClick, selected: selected, onShowTokenDetails: onShowTokenDetails }), endAdornment] })); }); export const TokenListItemAvatar = ({ token, }) => { const [isImageLoading, setIsImageLoading] = useState(true); return (_jsx(Avatar, { src: token.logoURI, alt: token.symbol, sx: (theme) => isImageLoading ? { bgcolor: theme.vars.palette.grey[300] } : null, onLoad: () => setIsImageLoading(false), children: token.symbol?.[0] })); }; const OpenTokenDetailsButton = ({ tokenAddress, withoutContractAddress, onClick, }) => { if (!tokenAddress) { return null; } return (_jsx(IconButton, { size: "small", onClick: (e) => { e.stopPropagation(); onClick(tokenAddress, withoutContractAddress); }, children: _jsx(InfoOutlinedIcon, {}) })); }; export const TokenListItemButton = ({ onClick, token, chain, accountAddress, isBalanceLoading, selected, onShowTokenDetails, }) => { const { t } = useTranslation(); const container = useRef(null); const timeoutId = useRef(undefined); const [showAddress, setShowAddress] = useState(false); const withoutContractAddress = chain?.chainType === ChainType.UTXO; const onMouseEnter = () => { timeoutId.current = setTimeout(() => { if (token.address) { setShowAddress(true); } }, 350); }; const onMouseLeave = () => { clearTimeout(timeoutId.current); if (showAddress) { setShowAddress(false); } }; const tokenAmount = formatTokenAmount(token.amount, token.decimals); const tokenPrice = formatTokenPrice(token.amount, token.priceUSD, token.decimals); const longPressEvents = useLongPress(() => onShowTokenDetails(token.address, withoutContractAddress)); return (_jsxs(ListItemButton, { onClick: onClick, onMouseEnter: onMouseEnter, onMouseLeave: onMouseLeave, ...longPressEvents, dense: true, selected: selected, sx: { height: 60, marginBottom: '4px', }, children: [_jsx(ListItemAvatar, { children: _jsx(TokenListItemAvatar, { token: token }) }), _jsx(ListItemText, { primary: token.symbol, slotProps: { secondary: { component: 'div', }, }, secondary: withoutContractAddress ? (_jsxs(Box, { ref: container, sx: { height: 20, display: 'flex', }, children: [_jsx(Box, { sx: { pt: 0.25, }, children: token.name }), _jsx(Box, { sx: { position: 'relative', }, children: _jsx(Slide, { direction: "up", in: showAddress, container: container.current, style: { position: 'absolute', }, appear: false, mountOnEnter: true, children: _jsx(Box, { sx: { display: 'flex', }, children: _jsx(OpenTokenDetailsButton, { tokenAddress: token.address, withoutContractAddress: withoutContractAddress, onClick: onShowTokenDetails }) }) }) })] })) : (_jsxs(Box, { ref: container, sx: { position: 'relative', height: 20, }, children: [_jsx(Slide, { direction: "down", in: !showAddress, container: container.current, style: { position: 'absolute', }, appear: false, children: _jsx(Box, { sx: { pt: 0.25, }, children: token.name }) }), _jsx(Slide, { direction: "up", in: showAddress, container: container.current, style: { position: 'absolute', }, appear: false, mountOnEnter: true, children: _jsxs(Box, { sx: { display: 'flex', }, children: [_jsx(Box, { sx: { display: 'flex', alignItems: 'center', pt: 0.125, }, children: shortenAddress(token.address) }), _jsx(OpenTokenDetailsButton, { tokenAddress: token.address, withoutContractAddress: withoutContractAddress, onClick: onShowTokenDetails })] }) })] })) }), accountAddress ? (isBalanceLoading ? (_jsx(TokenAmountSkeleton, {})) : (_jsxs(Box, { sx: { textAlign: 'right' }, children: [token.amount ? (_jsx(Typography, { noWrap: true, sx: { fontWeight: 600, }, title: tokenAmount, children: t('format.tokenAmount', { value: tokenAmount, }) })) : null, tokenPrice ? (_jsx(Typography, { "data-price": token.priceUSD, sx: { fontWeight: 500, fontSize: 12, color: 'text.secondary', }, children: t('format.currency', { value: tokenPrice, }) })) : null] }))) : null] })); }; export const TokenListItemSkeleton = () => { return (_jsxs(ListItem, { secondaryAction: _jsx(TokenAmountSkeleton, {}), disablePadding: true, sx: { position: 'relative', flexDirection: 'row', alignItems: 'center', padding: 0, }, children: [_jsx(ListItemAvatar, { children: _jsx(Skeleton, { variant: "circular", width: 40, height: 40, sx: { marginLeft: 1.5, marginRight: 2 } }) }), _jsx(ListItemText, { primary: _jsx(Skeleton, { variant: "text", width: 56, height: 24 }), secondary: _jsx(Skeleton, { variant: "text", width: 96, height: 16 }) })] })); }; export const TokenAmountSkeleton = () => { return (_jsxs(Box, { sx: { display: 'flex', flexDirection: 'column', alignItems: 'flex-end', }, children: [_jsx(Skeleton, { variant: "text", width: 56, height: 24 }), _jsx(Skeleton, { variant: "text", width: 48, height: 16 })] })); }; //# sourceMappingURL=TokenListItem.js.map