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

116 lines (113 loc) 4.21 kB
import { j as jsxRuntimeExports } from './index46.mjs'; import * as React from 'react'; import { createPortal } from 'react-dom'; import { cn } from './index38.mjs'; const PopoverContext = React.createContext(null); const Popover = ({ children, open: controlledOpen, onOpenChange }) => { const [uncontrolledOpen, setUncontrolledOpen] = React.useState(false); const open = controlledOpen ?? uncontrolledOpen; const setOpen = onOpenChange ?? setUncontrolledOpen; const triggerRef = React.useRef(null); const contentRef = React.useRef(null); React.useEffect(() => { const handleClickOutside = (event) => { if (contentRef.current && triggerRef.current && !contentRef.current.contains(event.target) && !triggerRef.current.contains(event.target)) { setOpen(false); } }; const handleEscape = (event) => { if (event.key === "Escape") { setOpen(false); } }; if (open) { document.addEventListener("mousedown", handleClickOutside); document.addEventListener("keydown", handleEscape); } return () => { document.removeEventListener("mousedown", handleClickOutside); document.removeEventListener("keydown", handleEscape); }; }, [open, setOpen]); return /* @__PURE__ */ jsxRuntimeExports.jsx(PopoverContext.Provider, { value: { open, setOpen, triggerRef, contentRef }, children }); }; const PopoverTrigger = React.forwardRef( ({ children, className, asChild, ...props }, forwardedRef) => { const context = React.useContext(PopoverContext); if (!context) throw new Error("PopoverTrigger must be used within Popover"); const { open, setOpen, triggerRef } = context; const ref = React.useCallback( (node) => { if (node) { triggerRef.current = node; if (typeof forwardedRef === "function") forwardedRef(node); else if (forwardedRef) forwardedRef.current = node; } }, [forwardedRef, triggerRef] ); const Element = asChild ? React.Fragment : "button"; const elementProps = asChild ? {} : { ref, className: cn("inline-flex items-center justify-center", className), onClick: () => setOpen(!open), "aria-expanded": open, "aria-haspopup": true, ...props }; return /* @__PURE__ */ jsxRuntimeExports.jsx(Element, { ...elementProps, children }); } ); const PopoverContent = React.forwardRef( ({ children, className, ...props }, forwardedRef) => { const context = React.useContext(PopoverContext); if (!context) throw new Error("PopoverContent must be used within Popover"); const { open, contentRef, triggerRef } = context; const [position, setPosition] = React.useState({ top: 0, left: 0 }); React.useEffect(() => { if (open && triggerRef.current) { const rect = triggerRef.current.getBoundingClientRect(); setPosition({ top: rect.bottom + window.scrollY + 8, left: rect.left + window.scrollX }); } }, [open]); 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; }, style: { position: "absolute", top: position.top, left: position.left }, className: cn( "z-50 min-w-[8rem] overflow-hidden rounded-md", "border border-[oklch(var(--theme-border))]", "bg-[oklch(var(--theme-background))]", "text-[oklch(var(--theme-foreground))]", "shadow-md outline-none", "animate-in fade-in-0 zoom-in-95", className ), role: "dialog", "aria-modal": "true", tabIndex: -1, ...props, children } ), document.body ); } ); PopoverTrigger.displayName = "PopoverTrigger"; PopoverContent.displayName = "PopoverContent"; export { Popover, PopoverContent, PopoverTrigger };