@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
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 /* @__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