{
  "$schema": "https://ui.shadcn.com/schema/registry-item.json",
  "name": "glass-menu",
  "title": "Glass Menu",
  "description": "A dropdown menu on glass with shortcuts, checkbox and radio items, and submenus.",
  "dependencies": [
    "@radix-ui/react-dropdown-menu",
    "clsx"
  ],
  "registryDependencies": [
    "@glassyui/glass-panel"
  ],
  "files": [
    {
      "path": "registry/glassyui/glass-menu.tsx",
      "content": "'use client';\n\nimport * as MenuPrimitive from '@radix-ui/react-dropdown-menu';\nimport clsx from 'clsx';\nimport { forwardRef, useMemo, useRef } from 'react';\nimport type { HTMLAttributes } from 'react';\nimport { mergeRefs } from './lib/merge-refs';\nimport { GlassPanel } from './glass-panel';\n\n/**\n * Menus are non-modal by default, like the WAI-ARIA menu button: the page stays in the\n * accessibility tree and keeps its scroll, while Radix still blocks Tab inside the open\n * menu and closes it when focus leaves. Pass `modal` to lock the page instead.\n */\nexport function GlassMenu({\n  modal = false,\n  ...props\n}: React.ComponentProps<typeof MenuPrimitive.Root>) {\n  return <MenuPrimitive.Root modal={modal} {...props} />;\n}\n\nexport const GlassMenuTrigger = MenuPrimitive.Trigger;\n\nexport const GlassMenuGroup = MenuPrimitive.Group;\n\nexport const GlassMenuRadioGroup = MenuPrimitive.RadioGroup;\n\nexport const GlassMenuSub = MenuPrimitive.Sub;\n\nexport type GlassMenuContentProps = React.ComponentPropsWithoutRef<typeof MenuPrimitive.Content> & {\n  /** How thick the glass is, as a multiple of regular. See GlassSurface. */\n  thickness?: number;\n};\n\nexport const GlassMenuContent = forwardRef<HTMLDivElement, GlassMenuContentProps>(\n  ({ children, className, onInteractOutside, sideOffset = 8, ...props }, forwardedRef) => {\n    const contentRef = useRef<HTMLDivElement | null>(null);\n    const ref = useMemo(() => mergeRefs(contentRef, forwardedRef), [forwardedRef]);\n\n    return (\n      <MenuPrimitive.Portal>\n        <MenuPrimitive.Content\n          ref={ref}\n          sideOffset={sideOffset}\n          {...props}\n          onInteractOutside={(event) => {\n            onInteractOutside?.(event);\n\n            const content = contentRef.current;\n            const triggerId = content?.getAttribute('aria-labelledby');\n\n            if (!content || !triggerId) return;\n\n            const trigger = content.ownerDocument.getElementById(triggerId);\n\n            // The trigger already toggles the menu. Its closing layer stays mounted for the\n            // exit animation and must not dismiss the same pointer click that reopens it.\n            if (event.target instanceof Node && trigger?.contains(event.target)) {\n              event.preventDefault();\n            }\n          }}\n          asChild\n        >\n          <GlassPanel\n            elevation=\"raised\"\n            lens\n            preset=\"prominent\"\n            refraction=\"none\"\n            variant=\"card\"\n            className={clsx('lg-menu-content', className)}\n          >\n            {children}\n          </GlassPanel>\n        </MenuPrimitive.Content>\n      </MenuPrimitive.Portal>\n    );\n  },\n);\n\nGlassMenuContent.displayName = 'GlassMenuContent';\n\nexport type GlassMenuItemProps = React.ComponentPropsWithoutRef<typeof MenuPrimitive.Item> & {\n  /** Leaves room for a check or radio indicator so labels line up. */\n  inset?: boolean;\n  tone?: 'default' | 'destructive';\n};\n\nexport const GlassMenuItem = forwardRef<HTMLDivElement, GlassMenuItemProps>(\n  ({ className, inset = false, tone = 'default', ...props }, forwardedRef) => (\n    <MenuPrimitive.Item\n      ref={forwardedRef}\n      data-tone={tone}\n      className={clsx('lg-menu-item', inset && 'lg-menu-item--inset', className)}\n      {...props}\n    />\n  ),\n);\n\nGlassMenuItem.displayName = 'GlassMenuItem';\n\nexport const GlassMenuCheckboxItem = forwardRef<\n  HTMLDivElement,\n  React.ComponentPropsWithoutRef<typeof MenuPrimitive.CheckboxItem>\n>(({ children, className, ...props }, forwardedRef) => (\n  <MenuPrimitive.CheckboxItem\n    ref={forwardedRef}\n    className={clsx('lg-menu-item lg-menu-item--inset', className)}\n    {...props}\n  >\n    <MenuPrimitive.ItemIndicator className=\"lg-menu-indicator\">\n      <svg viewBox=\"0 0 16 16\" aria-hidden>\n        <path\n          d=\"M3.5 8.5l3 3 6-7\"\n          fill=\"none\"\n          stroke=\"currentColor\"\n          strokeLinecap=\"round\"\n          strokeLinejoin=\"round\"\n          strokeWidth=\"1.8\"\n        />\n      </svg>\n    </MenuPrimitive.ItemIndicator>\n    {children}\n  </MenuPrimitive.CheckboxItem>\n));\n\nGlassMenuCheckboxItem.displayName = 'GlassMenuCheckboxItem';\n\nexport const GlassMenuRadioItem = forwardRef<\n  HTMLDivElement,\n  React.ComponentPropsWithoutRef<typeof MenuPrimitive.RadioItem>\n>(({ children, className, ...props }, forwardedRef) => (\n  <MenuPrimitive.RadioItem\n    ref={forwardedRef}\n    className={clsx('lg-menu-item lg-menu-item--inset', className)}\n    {...props}\n  >\n    <MenuPrimitive.ItemIndicator className=\"lg-menu-indicator\">\n      <svg viewBox=\"0 0 16 16\" aria-hidden>\n        <circle cx=\"8\" cy=\"8\" r=\"3.25\" fill=\"currentColor\" />\n      </svg>\n    </MenuPrimitive.ItemIndicator>\n    {children}\n  </MenuPrimitive.RadioItem>\n));\n\nGlassMenuRadioItem.displayName = 'GlassMenuRadioItem';\n\nexport const GlassMenuLabel = forwardRef<\n  HTMLDivElement,\n  React.ComponentPropsWithoutRef<typeof MenuPrimitive.Label>\n>(({ className, ...props }, forwardedRef) => (\n  <MenuPrimitive.Label ref={forwardedRef} className={clsx('lg-menu-label', className)} {...props} />\n));\n\nGlassMenuLabel.displayName = 'GlassMenuLabel';\n\nexport const GlassMenuSeparator = forwardRef<\n  HTMLDivElement,\n  React.ComponentPropsWithoutRef<typeof MenuPrimitive.Separator>\n>(({ className, ...props }, forwardedRef) => (\n  <MenuPrimitive.Separator\n    ref={forwardedRef}\n    className={clsx('lg-menu-separator', className)}\n    {...props}\n  />\n));\n\nGlassMenuSeparator.displayName = 'GlassMenuSeparator';\n\nexport function GlassMenuShortcut({ className, ...props }: HTMLAttributes<HTMLSpanElement>) {\n  return <span className={clsx('lg-menu-shortcut', className)} {...props} />;\n}\n\nexport const GlassMenuSubTrigger = forwardRef<\n  HTMLDivElement,\n  React.ComponentPropsWithoutRef<typeof MenuPrimitive.SubTrigger> & { inset?: boolean }\n>(({ children, className, inset = false, ...props }, forwardedRef) => (\n  <MenuPrimitive.SubTrigger\n    ref={forwardedRef}\n    className={clsx('lg-menu-item', inset && 'lg-menu-item--inset', className)}\n    {...props}\n  >\n    {children}\n    <svg viewBox=\"0 0 16 16\" aria-hidden className=\"lg-menu-chevron\">\n      <path\n        d=\"M6 3.5 10.5 8 6 12.5\"\n        fill=\"none\"\n        stroke=\"currentColor\"\n        strokeLinecap=\"round\"\n        strokeLinejoin=\"round\"\n        strokeWidth=\"1.6\"\n      />\n    </svg>\n  </MenuPrimitive.SubTrigger>\n));\n\nGlassMenuSubTrigger.displayName = 'GlassMenuSubTrigger';\n\nexport const GlassMenuSubContent = forwardRef<\n  HTMLDivElement,\n  React.ComponentPropsWithoutRef<typeof MenuPrimitive.SubContent>\n>(({ alignOffset = -6, children, className, sideOffset = 6, ...props }, forwardedRef) => (\n  <MenuPrimitive.Portal>\n    <MenuPrimitive.SubContent\n      ref={forwardedRef}\n      alignOffset={alignOffset}\n      sideOffset={sideOffset}\n      {...props}\n      asChild\n    >\n      <GlassPanel\n        elevation=\"raised\"\n        preset=\"prominent\"\n        refraction=\"none\"\n        variant=\"card\"\n        className={clsx('lg-menu-content', className)}\n      >\n        {children}\n      </GlassPanel>\n    </MenuPrimitive.SubContent>\n  </MenuPrimitive.Portal>\n));\n\nGlassMenuSubContent.displayName = 'GlassMenuSubContent';\n",
      "type": "registry:ui",
      "target": "components/glassyui/glass-menu.tsx"
    }
  ],
  "meta": {
    "sourceModules": [
      "menu"
    ]
  },
  "type": "registry:ui"
}