@daimo/pay
Version:
Seamless crypto payments. Onboard users from any chain, any coin into your app with one click.
98 lines (95 loc) • 4.85 kB
JavaScript
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 jsx(Fragment, { children: children });
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 }), 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 ? delay : 0.5,
},
},
}, children: [message, jsx(TooltipTail, { "$size": size })] }) }) })) }) })] }));
};
export { Tooltip as default };
//# sourceMappingURL=index.js.map