analytica-frontend-lib
Version:
Repositório público dos componentes utilizados nas plataformas da Analytica Ensino
173 lines (171 loc) • 5.18 kB
JavaScript
import {
Text_default
} from "./chunk-IMCIR6TJ.mjs";
import {
cn
} from "./chunk-53ICLDGS.mjs";
// src/components/Tooltip/Tooltip.tsx
import {
useCallback,
useEffect,
useLayoutEffect,
useRef,
useState
} from "react";
import { createPortal } from "react-dom";
import { Fragment, jsx, jsxs } from "react/jsx-runtime";
var POSITION_CLASSES = {
top: "bottom-full left-1/2 -translate-x-1/2 mb-2",
bottom: "top-full left-1/2 -translate-x-1/2 mt-2",
left: "right-full top-1/2 -translate-y-1/2 mr-2",
right: "left-full top-1/2 -translate-y-1/2 ml-2"
};
var TOOLTIP_GAP_PX = 8;
var computePortalCoords = (triggerRect, position, tooltipRect) => {
switch (position) {
case "bottom":
return {
top: triggerRect.bottom + TOOLTIP_GAP_PX,
left: triggerRect.left + triggerRect.width / 2 - tooltipRect.width / 2
};
case "left":
return {
top: triggerRect.top + triggerRect.height / 2 - tooltipRect.height / 2,
left: triggerRect.left - tooltipRect.width - TOOLTIP_GAP_PX
};
case "right":
return {
top: triggerRect.top + triggerRect.height / 2 - tooltipRect.height / 2,
left: triggerRect.right + TOOLTIP_GAP_PX
};
case "top":
default:
return {
top: triggerRect.top - tooltipRect.height - TOOLTIP_GAP_PX,
left: triggerRect.left + triggerRect.width / 2 - tooltipRect.width / 2
};
}
};
var TOOLTIP_CONTENT_CLASSES = cn(
"whitespace-nowrap",
"px-4 py-2 rounded-lg",
"bg-background-dark text-white",
"text-sm font-medium",
"shadow-[0px_3px_10px_0px_rgba(38,38,38,0.2)]",
"transition-opacity duration-150"
);
function Tooltip({
content,
children,
position = "top",
className,
contentClassName,
disabled = false,
usePortal = false
}) {
const triggerRef = useRef(null);
const tooltipRef = useRef(null);
const [open, setOpen] = useState(false);
const [coords, setCoords] = useState({
top: 0,
left: 0
});
const updatePosition = useCallback(() => {
if (!triggerRef.current || !tooltipRef.current) return;
const triggerRect = triggerRef.current.getBoundingClientRect();
const tooltipRect = {
width: tooltipRef.current.offsetWidth,
height: tooltipRef.current.offsetHeight
};
setCoords(computePortalCoords(triggerRect, position, tooltipRect));
}, [position]);
useLayoutEffect(() => {
if (!usePortal || !open) return;
updatePosition();
const onViewportChange = () => updatePosition();
window.addEventListener("resize", onViewportChange);
window.addEventListener("scroll", onViewportChange, true);
return () => {
window.removeEventListener("resize", onViewportChange);
window.removeEventListener("scroll", onViewportChange, true);
};
}, [usePortal, open, updatePosition, content]);
useEffect(() => {
if (!usePortal) return;
const node = triggerRef.current;
if (!node) return;
const handleOpen = () => setOpen(true);
const handleClose = () => setOpen(false);
node.addEventListener("mouseenter", handleOpen);
node.addEventListener("mouseleave", handleClose);
node.addEventListener("focusin", handleOpen);
node.addEventListener("focusout", handleClose);
return () => {
node.removeEventListener("mouseenter", handleOpen);
node.removeEventListener("mouseleave", handleClose);
node.removeEventListener("focusin", handleOpen);
node.removeEventListener("focusout", handleClose);
};
}, [usePortal]);
if (disabled) {
return /* @__PURE__ */ jsx(Fragment, { children });
}
if (usePortal) {
return /* @__PURE__ */ jsxs(
Text_default,
{
as: "span",
ref: triggerRef,
className: cn("relative inline-flex", className),
"aria-describedby": open ? "tooltip-portal" : void 0,
children: [
children,
open && typeof document !== "undefined" && createPortal(
/* @__PURE__ */ jsx(
"div",
{
ref: tooltipRef,
id: "tooltip-portal",
role: "tooltip",
style: {
position: "fixed",
top: coords.top,
left: coords.left,
zIndex: 9999
},
className: cn(TOOLTIP_CONTENT_CLASSES, contentClassName),
children: content
}
),
document.body
)
]
}
);
}
return /* @__PURE__ */ jsxs("div", { className: cn("relative inline-flex group", className), children: [
children,
/* @__PURE__ */ jsx(
"div",
{
role: "tooltip",
className: cn(
"absolute z-50",
TOOLTIP_CONTENT_CLASSES,
"opacity-0 invisible",
"group-hover:opacity-100 group-hover:visible",
"group-focus-within:opacity-100 group-focus-within:visible",
POSITION_CLASSES[position],
contentClassName
),
children: content
}
)
] });
}
var Tooltip_default = Tooltip;
export {
Tooltip,
Tooltip_default
};
//# sourceMappingURL=chunk-QBKJAKGY.mjs.map