{"$schema":"https://ui.shadcn.com/schema/registry-item.json","author":"Eduardo Calvo <educlopez93@gmail.com>","css":{},"dependencies":["motion"],"description":"An animated Context Menu component for SmoothUI with spring animations, nested submenus, and keyboard navigation.","devDependencies":[],"files":[{"content":"\"use client\";\n\nimport {\n  ContextMenuContent,\n  ContextMenuGroup,\n  ContextMenuItem,\n  ContextMenuLabel,\n  ContextMenu as ContextMenuRoot,\n  ContextMenuSeparator,\n  ContextMenuShortcut,\n  ContextMenuSub,\n  ContextMenuSubContent,\n  ContextMenuSubTrigger,\n  ContextMenuTrigger,\n} from \"@/components/ui/context-menu\";\nimport { cn } from \"@/lib/utils\";\nimport { motion, useReducedMotion } from \"motion/react\";\nimport type React from \"react\";\nimport { SPRING_DEFAULT } from \"@/components/smoothui/lib/animation\";\n\nexport interface ContextMenuProps {\n  /** The trigger element that opens the context menu on right-click */\n  children: React.ReactNode;\n  /** Optional CSS class for the content container */\n  className?: string;\n  /** Menu items to render */\n  items: ContextMenuItemConfig[];\n}\n\nexport interface ContextMenuItemConfig {\n  /** Nested submenu items */\n  children?: ContextMenuItemConfig[];\n  /** Whether the item is disabled */\n  disabled?: boolean;\n  /** Renders a group label instead of an item */\n  groupLabel?: string;\n  /** Optional icon to display before the label */\n  icon?: React.ReactNode;\n  /** Unique key for the item */\n  key: string;\n  /** Display label */\n  label: string;\n  /** Callback when item is selected */\n  onSelect?: () => void;\n  /** Renders a separator instead of an item */\n  separator?: boolean;\n  /** Optional keyboard shortcut text to display */\n  shortcut?: string;\n  /** Destructive variant styling */\n  variant?: \"default\" | \"destructive\";\n}\n\nexport default function ContextMenu({\n  children,\n  items,\n  className,\n}: ContextMenuProps) {\n  const shouldReduceMotion = useReducedMotion();\n\n  const renderItem = (item: ContextMenuItemConfig, index: number) => {\n    if (item.separator) {\n      return <ContextMenuSeparator key={item.key} />;\n    }\n\n    if (item.groupLabel) {\n      return (\n        <ContextMenuLabel key={item.key}>{item.groupLabel}</ContextMenuLabel>\n      );\n    }\n\n    if (item.children && item.children.length > 0) {\n      return (\n        <ContextMenuSub key={item.key}>\n          <ContextMenuSubTrigger disabled={item.disabled}>\n            {item.icon ? <span className=\"mr-2\">{item.icon}</span> : null}\n            {item.label}\n          </ContextMenuSubTrigger>\n          <ContextMenuSubContent>\n            {item.children.map((child, childIndex) =>\n              renderItem(child, childIndex)\n            )}\n          </ContextMenuSubContent>\n        </ContextMenuSub>\n      );\n    }\n\n    return (\n      <motion.div\n        animate={shouldReduceMotion ? { opacity: 1 } : { opacity: 1, y: 0 }}\n        initial={shouldReduceMotion ? { opacity: 1 } : { opacity: 0, y: -4 }}\n        key={item.key}\n        transition={\n          shouldReduceMotion\n            ? { duration: 0 }\n            : { ...SPRING_DEFAULT, delay: index * 0.02 }\n        }\n      >\n        <ContextMenuItem\n          disabled={item.disabled}\n          onSelect={item.onSelect}\n          variant={item.variant}\n        >\n          {item.icon ? <span className=\"mr-2\">{item.icon}</span> : null}\n          {item.label}\n          {item.shortcut ? (\n            <ContextMenuShortcut>{item.shortcut}</ContextMenuShortcut>\n          ) : null}\n        </ContextMenuItem>\n      </motion.div>\n    );\n  };\n\n  return (\n    <ContextMenuRoot>\n      <ContextMenuTrigger asChild>{children}</ContextMenuTrigger>\n      <ContextMenuContent className={cn(\"origin-top\", className)}>\n        <motion.div\n          animate={\n            shouldReduceMotion ? { opacity: 1 } : { opacity: 1, scale: 1, y: 0 }\n          }\n          initial={\n            shouldReduceMotion\n              ? { opacity: 1 }\n              : { opacity: 0, scale: 0.95, y: -4 }\n          }\n          transition={shouldReduceMotion ? { duration: 0 } : SPRING_DEFAULT}\n        >\n          <ContextMenuGroup>\n            {items.map((item, index) => renderItem(item, index))}\n          </ContextMenuGroup>\n        </motion.div>\n      </ContextMenuContent>\n    </ContextMenuRoot>\n  );\n}\n","path":"index.tsx","target":"components/smoothui/context-menu/index.tsx","type":"registry:ui"}],"name":"context-menu","registryDependencies":["context-menu","https://smoothui.dev/r/lib.json"],"title":"Context Menu","type":"registry:ui"}