import { Menu, X } from "lucide-react"; import { useState, useEffect, useRef, isValidElement, cloneElement, } from "react"; // ---------------------- // Type Definitions // ---------------------- type MobileMenuProps = { rightItems?: React.ReactNode[]; navLinks?: React.ReactNode[]; }; // ---------------------- // Main Component // ---------------------- const MobileMenu = ({ rightItems = [], navLinks = [] }: MobileMenuProps) => { // ---------------------- // State & Refs // ---------------------- const [open, setOpen] = useState(false); const ref = useRef(null); // ---------------------- // Close menu when clicking outside // ---------------------- useEffect(() => { if (!open) return; const onDown = (e: MouseEvent) => ref.current && !ref.current.contains(e.target as Node) && setOpen(false); document.addEventListener("mousedown", onDown); return () => document.removeEventListener("mousedown", onDown); }, [open]); // ---------------------- // Normalize each nav or right-side item // Ensures mobile variant styling and behavior consistency // ---------------------- const normalize = (n: React.ReactNode) => { if (!isValidElement(n)) { // If it's plain text or something non-element, return as-is return { node: n, closeOnClick: true }; } const props: any = (n as any).props ?? {}; const hasDropdown = !!props.dropdown && Array.isArray(props.items) && props.items.length > 0; // Clone element with variant="mobile" to ensure mobile styling return { node: cloneElement(n as React.ReactElement<{ variant?: "mobile" }>, { variant: "mobile", }), closeOnClick: !hasDropdown, }; }; // ---------------------- // Combine and normalize all menu items // ---------------------- const items = [...rightItems.map(normalize), ...navLinks.map(normalize)]; // ---------------------- // Render Component // ---------------------- return (
{/* --- Menu Toggle Button (hamburger / close icons) --- */} {/* --- Dropdown Panel --- */} {open && (
{/* --- Render each menu item --- */} {items.map(({ node, closeOnClick }, i) => (
setOpen(false) : undefined} > {node}
))}
)}
); }; // ---------------------- // Export Component // ---------------------- export default MobileMenu;