"use client"; import { forwardRef, useState, useRef, useEffect } from "react"; import { createPortal } from "react-dom"; import { cn } from "@/lib/utils"; import { ChevronRight } from "lucide-react"; interface Position { x: number; y: number; } interface ContextMenuProps { isOpen: boolean; position: Position; onClose: () => void; children: React.ReactNode; } export const ContextMenu = forwardRef( ({ isOpen, position, onClose: _onClose, children }, ref) => { const [mounted, setMounted] = useState(false); useEffect(() => { setMounted(true); }, []); if (!mounted || !isOpen) return null; return createPortal(
{children}
, document.body ); } ); ContextMenu.displayName = "ContextMenu"; interface ContextMenuItemProps { icon?: React.ComponentType<{ className?: string }>; label: string; onClick: () => void; disabled?: boolean; destructive?: boolean; shortcut?: string; } export function ContextMenuItem({ icon: Icon, label, onClick, disabled = false, destructive = false, shortcut, }: ContextMenuItemProps) { return ( ); } export function ContextMenuSeparator() { return
; } interface ContextMenuSubMenuProps { icon?: React.ComponentType<{ className?: string }>; label: string; children: React.ReactNode; } export function ContextMenuSubMenu({ icon: Icon, label, children, }: ContextMenuSubMenuProps) { const [isOpen, setIsOpen] = useState(false); const [subMenuPosition, setSubMenuPosition] = useState<"right" | "left">("right"); const itemRef = useRef(null); const subMenuRef = useRef(null); useEffect(() => { if (isOpen && itemRef.current) { const rect = itemRef.current.getBoundingClientRect(); const viewportWidth = window.innerWidth; // Check if submenu would overflow right edge if (rect.right + 200 > viewportWidth - 10) { setSubMenuPosition("left"); } else { setSubMenuPosition("right"); } } }, [isOpen]); return (
setIsOpen(true)} onMouseLeave={() => setIsOpen(false)} >
{Icon && } {label}
{isOpen && (
{children}
)}
); } interface ContextMenuHeaderProps { children: React.ReactNode; } export function ContextMenuHeader({ children }: ContextMenuHeaderProps) { return (
{children}
); }