UNPKG

nextuiq

Version:

NextUIQ is a modern, lightweight, and developer-friendly UI component library for React and Next.js. Built with TypeScript and Tailwind CSS, it offers customizable, accessible, and performance-optimized components with built-in dark mode, theme customizat

151 lines (148 loc) 5.26 kB
import { j as jsxRuntimeExports } from './index46.mjs'; import * as React from 'react'; import { createPortal } from 'react-dom'; import { cn } from './index38.mjs'; const TooltipContext = React.createContext(null); function Tooltip({ children, content, disabled = false, delayDuration = 700, side = "top", // Add side prop align = "center" // Add align prop }) { const [open, setOpen] = React.useState(false); const triggerRef = React.useRef(null); const contentRef = React.useRef(null); const timeoutRef = React.useRef(void 0); const showTooltip = React.useCallback(() => { if (disabled) return; timeoutRef.current = window.setTimeout(() => setOpen(true), delayDuration); }, [disabled, delayDuration]); const hideTooltip = React.useCallback(() => { if (timeoutRef.current) clearTimeout(timeoutRef.current); setOpen(false); }, []); React.useEffect(() => { return () => { if (timeoutRef.current) clearTimeout(timeoutRef.current); }; }, []); return /* @__PURE__ */ jsxRuntimeExports.jsxs(TooltipContext.Provider, { value: { open, setOpen, triggerRef, contentRef, content }, children: [ /* @__PURE__ */ jsxRuntimeExports.jsx( "div", { ref: triggerRef, onMouseEnter: showTooltip, onMouseLeave: hideTooltip, onFocus: showTooltip, onBlur: hideTooltip, children } ), /* @__PURE__ */ jsxRuntimeExports.jsx(TooltipContent, { side, align, children: content }) ] }); } const TooltipContent = React.forwardRef( ({ children, className, side = "top", align = "center", ...props }, forwardedRef) => { const context = React.useContext(TooltipContext); if (!context) throw new Error("TooltipContent must be used within Tooltip"); const { open, contentRef, triggerRef, content } = context; const [position, setPosition] = React.useState({ top: 0, left: 0 }); React.useEffect(() => { if (open && triggerRef.current) { const updatePosition = () => { const rect = triggerRef.current?.getBoundingClientRect(); if (!rect) return; const contentRect = contentRef.current?.getBoundingClientRect(); if (!contentRect) return; const viewportWidth = window.innerWidth; const viewportHeight = window.innerHeight; let top = 0; let left = 0; switch (side) { case "top": top = rect.top - contentRect.height - 8; left = rect.left + (rect.width - contentRect.width) / 2; if (top < 0) { top = rect.bottom + 8; } break; case "bottom": top = rect.bottom + 8; left = rect.left + (rect.width - contentRect.width) / 2; if (top + contentRect.height > viewportHeight) { top = rect.top - contentRect.height - 8; } break; case "left": top = rect.top + (rect.height - contentRect.height) / 2; left = rect.left - contentRect.width - 8; if (left < 0) { left = rect.right + 8; } break; case "right": top = rect.top + (rect.height - contentRect.height) / 2; left = rect.right + 8; if (left + contentRect.width > viewportWidth) { left = rect.left - contentRect.width - 8; } break; } left = Math.max(8, Math.min(left, viewportWidth - contentRect.width - 8)); setPosition({ top: top + window.scrollY, left: left + window.scrollX }); }; const handleScroll = () => { requestAnimationFrame(updatePosition); }; updatePosition(); window.addEventListener("resize", updatePosition); window.addEventListener("scroll", handleScroll, true); return () => { window.removeEventListener("resize", updatePosition); window.removeEventListener("scroll", handleScroll, true); }; } }, [open, side, align]); if (!open || typeof document === "undefined") return null; return createPortal( /* @__PURE__ */ jsxRuntimeExports.jsx( "div", { ref: (node) => { contentRef.current = node; if (typeof forwardedRef === "function") forwardedRef(node); else if (forwardedRef) forwardedRef.current = node; }, role: "tooltip", style: { position: "absolute", top: position.top, left: position.left }, className: cn( "z-[9999] max-w-xs overflow-hidden rounded-md", // Updated z-index "bg-[oklch(var(--theme-popover))]", "px-3 py-1.5", "text-sm text-[oklch(var(--theme-popover-foreground))]", "shadow-md", "animate-in fade-in-0 zoom-in-95", className ), ...props, children: children || content } ), document.body ); } ); TooltipContent.displayName = "TooltipContent"; export { Tooltip, TooltipContent };