UNPKG

@coin-voyage/paykit

Version:

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

83 lines (82 loc) 4.5 kB
import { jsx as _jsx, jsxs as _jsxs, Fragment as _Fragment } from "react/jsx-runtime"; import { useEffect, useRef, useState } from "react"; import useMeasure from "react-use-measure"; import usePayContext from "../../contexts/pay"; import { TooltipContainer, TooltipTail, TooltipWindow } from "./styles"; import { AnimatePresence, motion, useIsomorphicLayoutEffect } from "framer-motion"; import { useThemeContext } from "../../../providers/theme/provider"; import { ResetContainer } from "../../../styles"; import Portal from "../Portal"; export default function Tooltip({ children, message, open, xOffset = 0, yOffset = 0, delay }) { const context = usePayContext(); const themeContext = useThemeContext(); const [isOpen, setIsOpen] = useState(false); const [outOfBounds, setOutOfBounds] = useState(false); const [size, setSize] = useState("small"); const [ready, setReady] = useState(false); const [currentRoute] = useState(context.route); const targetRef = useRef(null); const [ref, bounds] = useMeasure({ debounce: !ready ? 220 : 0, offsetSize: true, scroll: true, }); const checkBounds = () => { const x = xOffset + bounds.left + bounds.width; const y = yOffset + bounds.top + bounds.height * 0.5; return x > window.innerWidth || x < 0 || y > window.innerHeight || y < 0; }; const refreshLayout = () => { if (!targetRef.current || bounds.top + bounds.bottom + bounds.left + bounds.right + bounds.height + bounds.width === 0) { return; } const x = xOffset + bounds.left + bounds.width; const y = yOffset + bounds.top + bounds.height * 0.5; if (!ready && x !== 0 && y !== 0) { window.requestAnimationFrame(() => setReady(true)); } targetRef.current.style.left = `${x}px`; targetRef.current.style.top = `${y}px`; setSize(targetRef.current.offsetHeight <= 40 ? "small" : "large"); setOutOfBounds(checkBounds()); }; useIsomorphicLayoutEffect(refreshLayout, [bounds, open, isOpen]); useEffect(() => { if (!context.open) { window.requestAnimationFrame(() => { setIsOpen(false); }); } }, [context.open]); useEffect(() => { window.requestAnimationFrame(() => { setIsOpen(!!open); }); }, [open]); const shouldRenderTooltip = !context.options?.hideTooltips; return (_jsxs(_Fragment, { children: [_jsx(motion.div, { ref: ref, style: open === undefined ? { cursor: "help" } : {}, onHoverStart: () => setIsOpen(true), onHoverEnd: () => setIsOpen(false), onClick: () => setIsOpen(false), children: children }), shouldRenderTooltip && (_jsx(Portal, { children: _jsx(AnimatePresence, { children: currentRoute === context.route && !outOfBounds && isOpen && (_jsx(ResetContainer, { "$useTheme": themeContext.theme, "$useMode": themeContext.mode, "$customTheme": themeContext.customTheme, children: _jsx(TooltipWindow, { children: _jsxs(TooltipContainer, { role: "tooltip", "$size": size, ref: targetRef, initial: "collapsed", animate: ready ? "open" : {}, exit: "collapsed", variants: { collapsed: { transformOrigin: "20px 50%", opacity: 0, scale: 0.9, z: 0.01, y: "-50%", x: 20, transition: { duration: 0.1 }, }, open: { willChange: "opacity,transform", opacity: 1, scale: 1, z: 0.01, y: "-50%", x: 20, transition: { ease: [0.76, 0, 0.24, 1], duration: 0.15, delay: delay ?? 0.5, }, }, }, children: [message, _jsx(TooltipTail, { "$size": size })] }) }) })) }) }))] })); }