UNPKG

lightswind

Version:

A collection of beautifully crafted React Components, Blocks & Templates for Modern Developers. Create stunning web applications effortlessly by using our 160+ professional and animated react components.

76 lines (75 loc) 4.42 kB
// @ts-nocheck "use client"; import { jsx as _jsx } from "react/jsx-runtime"; import * as React from "react"; import { cn } from "../../lib/utils"; import { motion, AnimatePresence } from "framer-motion"; const MenubarContext = React.createContext(undefined); function useMenubarContext() { const context = React.useContext(MenubarContext); if (!context) { throw new Error("useMenubarContext must be used within a MenubarProvider"); } return context; } function Menubar({ className, children, ...props }) { const [openMenu, setOpenMenu] = React.useState(null); // close menu when clicking outside React.useEffect(() => { const handleClickOutside = (e) => { const target = e.target; const insideMenubar = target.closest('[role="menubar"], [role="menu"]'); if (openMenu && !insideMenubar) { setOpenMenu(null); } }; document.addEventListener("mousedown", handleClickOutside); return () => document.removeEventListener("mousedown", handleClickOutside); }, [openMenu]); return (_jsx(MenubarContext.Provider, { value: { openMenu, setOpenMenu }, children: _jsx("div", { className: cn("flex h-12 items-center space-x-1 rounded-md border bg-background px-2 md:px-4 shadow-sm", className), role: "menubar", ...props, children: children }) })); } function MenubarMenu({ value, children }) { const generatedId = React.useId(); const menuId = value ?? generatedId; return (_jsx("div", { className: "relative", "data-value": menuId, children: children })); } function MenubarTrigger({ className, children, ...props }) { const { openMenu, setOpenMenu } = useMenubarContext(); const triggerRef = React.useRef(null); const [menuId, setMenuId] = React.useState(""); React.useEffect(() => { if (triggerRef.current) { setMenuId(triggerRef.current.parentElement?.getAttribute("data-value") || ""); } }, []); const isOpen = openMenu === menuId; const handleClick = (e) => { e.stopPropagation(); setOpenMenu(isOpen ? null : menuId); }; return (_jsx("button", { ref: triggerRef, type: "button", role: "menuitem", className: cn("flex cursor-pointer select-none items-center rounded-md px-3 py-2 text-sm font-medium transition-colors", "hover:bg-accent hover:text-accent-foreground", "focus:outline-none focus:ring-2 focus:ring-accent focus:ring-offset-2", isOpen && "bg-accent text-accent-foreground", className), "aria-expanded": isOpen, "data-state": isOpen ? "open" : "closed", onClick: handleClick, ...props, children: children })); } function MenubarContent({ className, children, ...props }) { const { openMenu } = useMenubarContext(); const contentRef = React.useRef(null); const [menuId, setMenuId] = React.useState(null); React.useEffect(() => { if (contentRef.current) { const parentDataValue = contentRef.current.parentElement?.getAttribute("data-value"); setMenuId(parentDataValue || null); } }, []); const isOpen = openMenu === menuId; return (_jsx(AnimatePresence, { children: isOpen && (_jsx(motion.div, { ref: contentRef, initial: { opacity: 0, y: -5, scale: 0.95 }, animate: { opacity: 1, y: 0, scale: 1 }, exit: { opacity: 0, y: -5, scale: 0.95 }, transition: { duration: 0.15, ease: "easeOut" }, className: cn("absolute left-0 top-full z-50 mt-2 min-w-[10rem] flex flex-col rounded-md border bg-popover p-1 text-popover-foreground shadow-lg", "md:min-w-[12rem]", // larger menus on bigger screens className), role: "menu", ...props, children: children })) })); } function MenubarItem({ className, inset, children, ...props }) { const { setOpenMenu } = useMenubarContext(); const handleClick = (e) => { e.stopPropagation(); setOpenMenu(null); props.onClick?.(e); }; return (_jsx("div", { role: "menuitem", onClick: handleClick, className: cn("relative flex cursor-pointer select-none items-center rounded-sm px-2 py-1.5 text-sm transition-colors", "hover:bg-accent hover:text-accent-foreground", "focus:outline-none focus:bg-accent focus:text-accent-foreground", "data-[disabled]:pointer-events-none data-[disabled]:opacity-50", inset && "pl-8", className), ...props, children: children })); } export { Menubar, MenubarMenu, MenubarTrigger, MenubarContent, MenubarItem };