UNPKG

@coin-voyage/paykit

Version:

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

108 lines (106 loc) 3.86 kB
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime"; import { motion } from "framer-motion"; import { useEffect } from "react"; import { keyframes } from "styled-components"; import styled from "../../../styles/styled"; import usePayContext from "../../contexts/pay"; import { ScrollArea } from "../ScrollArea"; import { OptionButton, OptionIcon, OptionLabel, OptionSubtitle, OptionTitle, OptionsContainer } from "./styles"; export default function OptionsList({ options, isLoading, requiredSkeletons }) { const { triggerResize } = usePayContext(); const optionsLength = options.length; useEffect(() => { if (optionsLength > 0) { triggerResize(); } }, [optionsLength, triggerResize]); if (isLoading) { const skeletonCount = requiredSkeletons ? Math.max(requiredSkeletons - optionsLength, 0) : 0; return (_jsxs(OptionsContainer, { "$totalResults": options.length, children: [options.map((option) => (_jsx(OptionItem, { option: option }, option.id))), isLoading && Array.from({ length: skeletonCount }).map((_, index) => _jsx(SkeletonOptionItem, {}, index))] })); } return (_jsx(ScrollArea, { mobileDirection: "vertical", height: 300, children: _jsx(OptionsContainer, { "$totalResults": options.length, children: options.map((option) => (_jsx(OptionItem, { option: option }, option.id))) }) })); } const SkeletonOptionItem = () => { return (_jsxs(OptionButton, { type: "button", children: [_jsx(SkeletonIcon, {}), _jsx(SkeletonLabel, {})] })); }; const pulse = keyframes ` 0% { opacity: 0.6; } 50% { opacity: 1; } 100% { opacity: 0.6; } `; const SkeletonIcon = styled.div ` position: absolute; right: 20px; width: 32px; height: 32px; border-radius: 22.5%; background-color: rgba(0, 0, 0, 0.1); animation: ${pulse} 1.5s ease-in-out infinite; `; const SkeletonLabel = styled.div ` width: 100px; height: 16px; border-radius: 8px; background-color: rgba(0, 0, 0, 0.1); animation: ${pulse} 1.5s ease-in-out infinite; `; const OptionItem = ({ option }) => { const hydratedIcons = option.icons.map((icon) => { if (typeof icon === "string") { return _jsx("img", { src: icon, alt: "" }, icon); } return icon; }); const iconContent = (() => { if (hydratedIcons.length === 1) { return _jsx(OptionIcon, { "data-shape": option.iconShape, children: hydratedIcons[0] }); } return (_jsx(IconStackContainer, { children: hydratedIcons.map((icon, index) => (_jsx(IconStackItem, { "data-shape": option.iconShape, "$marginRight": index !== hydratedIcons.length - 1 ? -12 : 0, "$zIndex": hydratedIcons.length - index, children: icon }, index))) })); })(); return (_jsxs(OptionButton, { type: "button", onClick: option.onClick, disabled: option.disabled, children: [iconContent, _jsxs(OptionLabel, { children: [_jsx(OptionTitle, { children: option.title }), option.subtitle && _jsx(OptionSubtitle, { children: option.subtitle })] })] })); }; const IconStackContainer = styled(motion.div) ` position: absolute; right: 20px; display: flex; align-items: center; justify-content: center; `; const IconStackItem = styled(motion.div) ` display: block; overflow: hidden; user-select: none; display: flex; align-items: center; justify-content: center; margin-right: ${(props) => props.$marginRight || 0}px; z-index: ${(props) => props.$zIndex || 2}; width: 32px; height: 32px; overflow: hidden; svg, img { display: block; position: relative; pointer-events: none; overflow: hidden; width: 100%; height: 100%; } border-radius: 22.5%; &[data-shape="squircle"] { border-radius: 22.5%; } &[data-shape="circle"] { border-radius: 100%; } &[data-shape="square"] { border-radius: 0; } `;