UNPKG

@daimo/pay

Version:

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

130 lines (127 loc) 4.34 kB
import { jsx, Fragment, jsxs } from 'react/jsx-runtime'; import { useState, useRef, useEffect, useLayoutEffect } from 'react'; import useMeasure from 'react-use-measure'; import { usePayContext } from '../../../hooks/usePayContext.js'; import { TooltipWindow, TooltipContainer, TooltipTail } from './styles.js'; import { motion, AnimatePresence } from 'framer-motion'; import { ResetContainer } from '../../../styles/index.js'; import { useThemeContext } from '../../DaimoPayThemeProvider/DaimoPayThemeProvider.js'; import Portal from '../Portal/index.js'; const 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, // fix alignment initial state offsetSize: true, scroll: true }); const checkBounds = () => { let flag = false; const x = xOffset + bounds.left + bounds.width; const y = yOffset + bounds.top + bounds.height * 0.5; if (x > window.innerWidth || x < 0 || y > window.innerHeight || y < 0) { flag = true; } return flag; }; const useIsomorphicLayoutEffect = typeof window !== "undefined" ? useLayoutEffect : useEffect; 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) 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) setIsOpen(false); }, [context.open]); useEffect(() => { setIsOpen(!!open); }, [open]); if (context.options?.hideTooltips) return /* @__PURE__ */ jsx(Fragment, { children }); return /* @__PURE__ */ jsxs(Fragment, { children: [ /* @__PURE__ */ jsx( motion.div, { ref, style: open === void 0 ? { cursor: "help" } : {}, onHoverStart: () => setIsOpen(true), onHoverEnd: () => setIsOpen(false), onClick: () => setIsOpen(false), children } ), /* @__PURE__ */ jsx(Portal, { children: /* @__PURE__ */ jsx(AnimatePresence, { children: currentRoute === context.route && !outOfBounds && isOpen && /* @__PURE__ */ jsx( ResetContainer, { $useTheme: themeContext.theme, $useMode: themeContext.mode, $customTheme: themeContext.customTheme, children: /* @__PURE__ */ jsx(TooltipWindow, { children: /* @__PURE__ */ 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 ? delay : 0.5 } } }, children: [ message, /* @__PURE__ */ jsx(TooltipTail, { $size: size }) ] } ) }) } ) }) }) ] }); }; export { Tooltip as default }; //# sourceMappingURL=index.js.map