{
  "$schema": "https://ui.shadcn.com/schema/registry-item.json",
  "name": "context-menu",
  "type": "registry:ui",
  "title": "Context Menu",
  "description": "An accessible React context menu for Next.js: a right-click menu with a gliding highlight, shortcuts, checkbox and radio items and sub-menus, built on Radix.",
  "author": "FewTone <https://fewtone.com>",
  "dependencies": [
    "lucide-react@^1.52.0",
    "radix-ui@^1.7.0"
  ],
  "registryDependencies": [
    "https://ui.fewtone.com/r/tokens.json",
    "https://ui.fewtone.com/r/dropdown-menu.json"
  ],
  "files": [
    {
      "path": "registry/fewtone/ui/context-menu.tsx",
      "type": "registry:ui",
      "content": "\"use client\";\n\nimport {\n  MenuCheck,\n  MenuSubContext,\n  MenuSurface,\n  menuClasses,\n  menuItemVariants,\n  useMenuRow,\n  useMenuSub,\n} from \"@/components/ui/dropdown-menu\";\nimport { cn } from \"@/lib/utils\";\nimport { ChevronRightIcon } from \"lucide-react\";\nimport { ContextMenu as ContextMenuPrimitive, Slot } from \"radix-ui\";\nimport { type ComponentProps, useContext } from \"react\";\n\n/*\n * Context Menu, built on Radix Context Menu: a right-click (or a long-press on touch) opens it at the pointer.\n * On a focused trigger, the keyboard's context-menu key and Shift+F10 open it too. Inside, the keys are\n * Dropdown Menu's: arrow keys, Home/End, typeahead, sub-menus on the arrow keys, Escape.\n * - Dropdown Menu's twin: the surface, rows, gliding highlight and marks come from dropdown-menu.tsx, so the\n *   two menus never drift apart. Installing Context Menu brings Dropdown Menu with it.\n * - It grows from the pointer: Radix puts the transform origin at the corner by the pointer, and the popover\n *   keyframes scale from there through the blur.\n */\n\nfunction ContextMenu(props: ComponentProps<typeof ContextMenuPrimitive.Root>) {\n  return <ContextMenuPrimitive.Root data-slot=\"context-menu\" {...props} />;\n}\n\n/** The area that opens the menu. Make it focusable (tabIndex={0}) so keyboard users can open it too. */\nfunction ContextMenuTrigger({ className, ...props }: ComponentProps<typeof ContextMenuPrimitive.Trigger>) {\n  return (\n    <ContextMenuPrimitive.Trigger\n      data-slot=\"context-menu-trigger\"\n      className={cn(\n        \"outline-ring focus-visible:outline-(length:--focus-ring-width) focus-visible:outline-offset-(--focus-ring-offset)\",\n        className,\n      )}\n      {...props}\n    />\n  );\n}\n\nfunction ContextMenuPortal(props: ComponentProps<typeof ContextMenuPrimitive.Portal>) {\n  return <ContextMenuPrimitive.Portal data-slot=\"context-menu-portal\" {...props} />;\n}\n\nfunction ContextMenuContent({\n  className,\n  children,\n  ...props\n}: ComponentProps<typeof ContextMenuPrimitive.Content>) {\n  return (\n    <ContextMenuPrimitive.Portal>\n      <ContextMenuPrimitive.Content data-slot=\"context-menu-content\" {...props} asChild>\n        <MenuSurface\n          className={cn(\n            \"max-h-(--radix-context-menu-content-available-height) origin-(--radix-context-menu-content-transform-origin)\",\n            className,\n          )}\n        >\n          {children}\n        </MenuSurface>\n      </ContextMenuPrimitive.Content>\n    </ContextMenuPrimitive.Portal>\n  );\n}\n\nfunction ContextMenuGroup(props: ComponentProps<typeof ContextMenuPrimitive.Group>) {\n  return <ContextMenuPrimitive.Group data-slot=\"context-menu-group\" {...props} />;\n}\n\nfunction ContextMenuLabel({\n  className,\n  inset,\n  ...props\n}: ComponentProps<typeof ContextMenuPrimitive.Label> & { inset?: boolean }) {\n  return (\n    <ContextMenuPrimitive.Label\n      data-slot=\"context-menu-label\"\n      data-inset={inset || undefined}\n      className={cn(menuClasses.label, className)}\n      {...props}\n    />\n  );\n}\n\nfunction ContextMenuItem({\n  className,\n  inset,\n  variant = \"default\",\n  children,\n  onFocus,\n  onBlur,\n  ...props\n}: ComponentProps<typeof ContextMenuPrimitive.Item> & {\n  /** Lines the label up with items that start with an icon */\n  inset?: boolean;\n  /** Destructive is red, and tints the highlight red as it lands */\n  variant?: \"default\" | \"destructive\";\n}) {\n  const row = useMenuRow({ tone: variant, onFocus, onBlur });\n  return (\n    <ContextMenuPrimitive.Item\n      data-slot=\"context-menu-item\"\n      data-inset={inset || undefined}\n      data-variant={variant}\n      className={cn(menuItemVariants({ variant }), className)}\n      onFocus={row.onFocus}\n      onBlur={row.onBlur}\n      {...props}\n    >\n      {row.highlight}\n      {/* With asChild the child (a link) becomes the item and the highlight goes inside it */}\n      <Slot.Slottable>{children}</Slot.Slottable>\n    </ContextMenuPrimitive.Item>\n  );\n}\n\nfunction ContextMenuCheckboxItem({\n  className,\n  children,\n  checked,\n  onFocus,\n  onBlur,\n  ...props\n}: ComponentProps<typeof ContextMenuPrimitive.CheckboxItem>) {\n  const row = useMenuRow({ onFocus, onBlur });\n  return (\n    <ContextMenuPrimitive.CheckboxItem\n      data-slot=\"context-menu-checkbox-item\"\n      checked={checked}\n      className={cn(menuItemVariants(), menuClasses.choice, className)}\n      onFocus={row.onFocus}\n      onBlur={row.onBlur}\n      {...props}\n    >\n      {row.highlight}\n      <span className={menuClasses.indicator}>\n        <MenuCheck checked={checked} />\n      </span>\n      {children}\n    </ContextMenuPrimitive.CheckboxItem>\n  );\n}\n\nfunction ContextMenuRadioGroup(props: ComponentProps<typeof ContextMenuPrimitive.RadioGroup>) {\n  return <ContextMenuPrimitive.RadioGroup data-slot=\"context-menu-radio-group\" {...props} />;\n}\n\nfunction ContextMenuRadioItem({\n  className,\n  children,\n  onFocus,\n  onBlur,\n  ...props\n}: ComponentProps<typeof ContextMenuPrimitive.RadioItem>) {\n  const row = useMenuRow({ onFocus, onBlur });\n  return (\n    <ContextMenuPrimitive.RadioItem\n      data-slot=\"context-menu-radio-item\"\n      className={cn(menuItemVariants(), menuClasses.choice, className)}\n      onFocus={row.onFocus}\n      onBlur={row.onBlur}\n      {...props}\n    >\n      {row.highlight}\n      <span className={menuClasses.indicator}>\n        {/* Always mounted, so the dot can grow in and shrink away rather than appear */}\n        <ContextMenuPrimitive.ItemIndicator forceMount className={menuClasses.dot} />\n      </span>\n      {children}\n    </ContextMenuPrimitive.RadioItem>\n  );\n}\n\nfunction ContextMenuSeparator({\n  className,\n  ...props\n}: ComponentProps<typeof ContextMenuPrimitive.Separator>) {\n  return (\n    <ContextMenuPrimitive.Separator\n      data-slot=\"context-menu-separator\"\n      className={cn(menuClasses.separator, className)}\n      {...props}\n    />\n  );\n}\n\n/** A shortcut hint at the end of an item. It only shows the keys; binding them is up to you. */\nfunction ContextMenuShortcut({ className, ...props }: ComponentProps<\"span\">) {\n  return (\n    <span data-slot=\"context-menu-shortcut\" className={cn(menuClasses.shortcut, className)} {...props} />\n  );\n}\n\nfunction ContextMenuSub({\n  open,\n  defaultOpen,\n  onOpenChange,\n  ...props\n}: ComponentProps<typeof ContextMenuPrimitive.Sub>) {\n  const sub = useMenuSub({ open, defaultOpen, onOpenChange });\n  return (\n    <MenuSubContext.Provider value={sub.open}>\n      <ContextMenuPrimitive.Sub\n        data-slot=\"context-menu-sub\"\n        open={sub.open}\n        onOpenChange={sub.onOpenChange}\n        {...props}\n      />\n    </MenuSubContext.Provider>\n  );\n}\n\nfunction ContextMenuSubTrigger({\n  className,\n  inset,\n  children,\n  onFocus,\n  onBlur,\n  ...props\n}: ComponentProps<typeof ContextMenuPrimitive.SubTrigger> & { inset?: boolean }) {\n  const open = useContext(MenuSubContext);\n  const row = useMenuRow({ keep: open, onFocus, onBlur });\n  return (\n    <ContextMenuPrimitive.SubTrigger\n      data-slot=\"context-menu-sub-trigger\"\n      data-inset={inset || undefined}\n      className={cn(menuItemVariants(), menuClasses.subTrigger, className)}\n      onFocus={row.onFocus}\n      onBlur={row.onBlur}\n      {...props}\n    >\n      {row.highlight}\n      {children}\n      <ChevronRightIcon aria-hidden className={menuClasses.chevron} />\n    </ContextMenuPrimitive.SubTrigger>\n  );\n}\n\nfunction ContextMenuSubContent({\n  className,\n  sideOffset = 4,\n  // The surface's padding and border, so the sub-menu's first item lines up with its trigger\n  alignOffset = -5,\n  children,\n  ...props\n}: ComponentProps<typeof ContextMenuPrimitive.SubContent>) {\n  return (\n    // In a portal, so the menu's own scrolling and its keyframes' transform can't clip or carry it\n    <ContextMenuPrimitive.Portal>\n      <ContextMenuPrimitive.SubContent\n        data-slot=\"context-menu-sub-content\"\n        sideOffset={sideOffset}\n        alignOffset={alignOffset}\n        {...props}\n        asChild\n      >\n        <MenuSurface\n          className={cn(\n            \"max-h-(--radix-context-menu-content-available-height) origin-(--radix-context-menu-content-transform-origin) shadow-lg\",\n            className,\n          )}\n        >\n          {children}\n        </MenuSurface>\n      </ContextMenuPrimitive.SubContent>\n    </ContextMenuPrimitive.Portal>\n  );\n}\n\nexport {\n  ContextMenu,\n  ContextMenuCheckboxItem,\n  ContextMenuContent,\n  ContextMenuGroup,\n  ContextMenuItem,\n  ContextMenuLabel,\n  ContextMenuPortal,\n  ContextMenuRadioGroup,\n  ContextMenuRadioItem,\n  ContextMenuSeparator,\n  ContextMenuShortcut,\n  ContextMenuSub,\n  ContextMenuSubContent,\n  ContextMenuSubTrigger,\n  ContextMenuTrigger,\n};\n"
    }
  ],
  "categories": [
    "overlays"
  ],
  "docs": "Usage and examples: https://ui.fewtone.com/components/context-menu"
}
