UNPKG

analytica-frontend-lib

Version:

Repositório público dos componentes utilizados nas plataformas da Analytica Ensino

173 lines (171 loc) 5.18 kB
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