{
  "$schema": "https://ui.shadcn.com/schema/registry-item.json",
  "name": "dropdown-menu",
  "title": "Ninaero dropdown-menu",
  "dependencies": [
    "@base-ui/react@^1.9.0",
    "cn@^0.4.0"
  ],
  "registryDependencies": [
    "https://ninaero.pages.dev/r/theme.json",
    "https://ninaero.pages.dev/r/icons.json",
    "https://ninaero.pages.dev/r/sound-provider.json"
  ],
  "files": [
    {
      "path": "registry/ninaero/ui/dropdown-menu.tsx",
      "content": "\"use client\";\n\nimport { useDirection } from \"@base-ui/react/direction-provider\";\nimport { Menu as MenuPrimitive } from \"@base-ui/react/menu\";\nimport { cn } from \"cn\";\nimport type * as React from \"react\";\n\nimport { CheckIcon, ChevronRightIcon } from \"@/lib/icons\";\n\nimport { HighlightSound, SoundGroup, useControlSound, HoverSound } from \"./sound-feedback\";\n\nfunction DropdownMenu({ sound = true, ...props }: MenuPrimitive.Root.Props & { sound?: boolean }) {\n  return (\n    <SoundGroup sound={sound}>\n      <MenuPrimitive.Root data-slot=\"dropdown-menu\" {...props} />\n    </SoundGroup>\n  );\n}\n\nfunction DropdownMenuPortal({ ...props }: MenuPrimitive.Portal.Props) {\n  return <MenuPrimitive.Portal data-slot=\"dropdown-menu-portal\" {...props} />;\n}\n\nfunction DropdownMenuTrigger({\n  sound = true,\n  ...props\n}: MenuPrimitive.Trigger.Props & { sound?: boolean }) {\n  return (\n    <HoverSound sound={sound}>\n      <MenuPrimitive.Trigger data-slot=\"dropdown-menu-trigger\" {...props} />\n    </HoverSound>\n  );\n}\n\nfunction DropdownMenuContent({\n  align = \"start\",\n  alignOffset = 0,\n  side = \"bottom\",\n  sideOffset = 4,\n  className,\n  ...props\n}: MenuPrimitive.Popup.Props &\n  Pick<MenuPrimitive.Positioner.Props, \"align\" | \"alignOffset\" | \"side\" | \"sideOffset\">) {\n  const direction = useDirection();\n  return (\n    <MenuPrimitive.Portal>\n      <MenuPrimitive.Positioner\n        className=\"isolate z-50 outline-none\"\n        align={align}\n        alignOffset={alignOffset}\n        side={side}\n        sideOffset={sideOffset}\n      >\n        <MenuPrimitive.Popup\n          data-slot=\"dropdown-menu-content\"\n          dir={direction}\n          className={cn(\n            \"ninaero-popover ninaero-dropdown-menu-content relative isolate z-50 max-h-(--available-height) w-(--anchor-width) min-w-[min(8rem,var(--available-width))] max-w-(--available-width) overflow-x-hidden overflow-y-auto p-2 outline-none\",\n            className,\n          )}\n          {...props}\n        />\n      </MenuPrimitive.Positioner>\n    </MenuPrimitive.Portal>\n  );\n}\n\nfunction DropdownMenuGroup({ ...props }: MenuPrimitive.Group.Props) {\n  return <MenuPrimitive.Group data-slot=\"dropdown-menu-group\" {...props} />;\n}\n\nfunction DropdownMenuLabel({\n  className,\n  inset,\n  ...props\n}: MenuPrimitive.GroupLabel.Props & {\n  inset?: boolean;\n}) {\n  return (\n    <MenuPrimitive.GroupLabel\n      data-slot=\"dropdown-menu-label\"\n      data-inset={inset}\n      className={cn(\n        \"px-3 py-1 text-xs font-medium text-muted-foreground data-inset:ps-9\",\n        className,\n      )}\n      {...props}\n    />\n  );\n}\n\nfunction DropdownMenuItem({\n  className,\n  inset,\n  variant = \"default\",\n  render,\n  onClick,\n  sound = true,\n  ...props\n}: MenuPrimitive.Item.Props & {\n  inset?: boolean;\n  variant?: \"default\" | \"destructive\";\n  sound?: boolean;\n}) {\n  const { play } = useControlSound(sound);\n  return (\n    <MenuPrimitive.Item\n      data-slot=\"dropdown-menu-item\"\n      data-inset={inset}\n      data-variant={variant}\n      className={cn(\n        \"ninaero-dropdown-menu-item group/dropdown-menu-item relative flex min-h-8 cursor-default items-center gap-2 rounded-md px-3 py-1 text-sm select-none data-inset:ps-9 data-disabled:pointer-events-none [&_svg]:pointer-events-none [&_svg]:shrink-0 [&_svg:not([class*='size-'])]:size-4\",\n        className,\n      )}\n      {...props}\n      render={(elementProps, state) => (\n        <HighlightSound elementProps={elementProps} state={state} render={render} sound={sound} />\n      )}\n      onClick={(event) => {\n        onClick?.(event);\n        if (!event.defaultPrevented && !event.baseUIHandlerPrevented && !props.disabled)\n          play(\"tap\");\n      }}\n    />\n  );\n}\n\nfunction DropdownMenuSub({ ...props }: MenuPrimitive.SubmenuRoot.Props) {\n  return <MenuPrimitive.SubmenuRoot data-slot=\"dropdown-menu-sub\" {...props} />;\n}\n\nfunction DropdownMenuSubTrigger({\n  className,\n  inset,\n  children,\n  sound = true,\n  ...props\n}: MenuPrimitive.SubmenuTrigger.Props & {\n  inset?: boolean;\n} & { sound?: boolean }) {\n  return (\n    <HoverSound sound={sound}>\n      <MenuPrimitive.SubmenuTrigger\n        data-slot=\"dropdown-menu-sub-trigger\"\n        data-inset={inset}\n        className={cn(\n          \"ninaero-dropdown-menu-item flex min-h-8 cursor-default items-center gap-2 rounded-md px-3 py-1 text-sm select-none data-inset:ps-9 data-disabled:pointer-events-none [&_svg]:pointer-events-none [&_svg]:shrink-0 [&_svg:not([class*='size-'])]:size-4\",\n          className,\n        )}\n        {...props}\n      >\n        {children}\n        <ChevronRightIcon className=\"ms-auto rtl:rotate-180\" />\n      </MenuPrimitive.SubmenuTrigger>\n    </HoverSound>\n  );\n}\n\nfunction DropdownMenuSubContent({\n  align = \"start\",\n  alignOffset = -3,\n  side = \"inline-end\",\n  sideOffset = 0,\n  className,\n  ...props\n}: React.ComponentProps<typeof DropdownMenuContent>) {\n  return (\n    <DropdownMenuContent\n      data-slot=\"dropdown-menu-sub-content\"\n      className={cn(\"w-auto min-w-[min(6rem,var(--available-width))]\", className)}\n      align={align}\n      alignOffset={alignOffset}\n      side={side}\n      sideOffset={sideOffset}\n      {...props}\n    />\n  );\n}\n\nfunction DropdownMenuCheckboxItem({\n  className,\n  children,\n  checked,\n  inset,\n  render,\n  onCheckedChange,\n  sound = true,\n  ...props\n}: MenuPrimitive.CheckboxItem.Props & {\n  inset?: boolean;\n  sound?: boolean;\n}) {\n  const { play } = useControlSound(sound);\n  return (\n    <MenuPrimitive.CheckboxItem\n      data-slot=\"dropdown-menu-checkbox-item\"\n      data-inset={inset}\n      className={cn(\n        \"ninaero-dropdown-menu-item relative flex min-h-8 cursor-default items-center gap-2 rounded-md py-1 pe-9 ps-3 text-sm select-none data-inset:ps-9 data-disabled:pointer-events-none [&_svg]:pointer-events-none [&_svg]:shrink-0 [&_svg:not([class*='size-'])]:size-4\",\n        className,\n      )}\n      checked={checked}\n      {...props}\n      render={(elementProps, state) => (\n        <HighlightSound elementProps={elementProps} state={state} render={render} sound={sound} />\n      )}\n      onCheckedChange={(value, details) => {\n        onCheckedChange?.(value, details);\n        if (!details.isCanceled && details.event.type !== \"reset\") play(\"tap\");\n      }}\n    >\n      <span\n        className=\"pointer-events-none absolute end-3 flex items-center justify-center\"\n        data-slot=\"dropdown-menu-checkbox-item-indicator\"\n      >\n        <MenuPrimitive.CheckboxItemIndicator>\n          <CheckIcon />\n        </MenuPrimitive.CheckboxItemIndicator>\n      </span>\n      {children}\n    </MenuPrimitive.CheckboxItem>\n  );\n}\n\nfunction DropdownMenuRadioGroup({\n  sound = true,\n  onValueChange,\n  ...props\n}: MenuPrimitive.RadioGroup.Props & { sound?: boolean }) {\n  const { play } = useControlSound(sound);\n  return (\n    <SoundGroup sound={sound}>\n      <MenuPrimitive.RadioGroup\n        data-slot=\"dropdown-menu-radio-group\"\n        {...props}\n        onValueChange={(value, details) => {\n          onValueChange?.(value, details);\n          if (!details.isCanceled && details.event.type !== \"reset\") play(\"tap\");\n        }}\n      />\n    </SoundGroup>\n  );\n}\n\nfunction DropdownMenuRadioItem({\n  className,\n  children,\n  inset,\n  render,\n  ...props\n}: MenuPrimitive.RadioItem.Props & {\n  inset?: boolean;\n}) {\n  return (\n    <MenuPrimitive.RadioItem\n      data-slot=\"dropdown-menu-radio-item\"\n      data-inset={inset}\n      className={cn(\n        \"ninaero-dropdown-menu-item relative flex min-h-8 cursor-default items-center gap-2 rounded-md py-1 pe-9 ps-3 text-sm select-none data-inset:ps-9 data-disabled:pointer-events-none [&_svg]:pointer-events-none [&_svg]:shrink-0 [&_svg:not([class*='size-'])]:size-4\",\n        className,\n      )}\n      {...props}\n      render={(elementProps, state) => (\n        <HighlightSound elementProps={elementProps} state={state} render={render} />\n      )}\n    >\n      <span\n        className=\"pointer-events-none absolute end-3 flex items-center justify-center\"\n        data-slot=\"dropdown-menu-radio-item-indicator\"\n      >\n        <MenuPrimitive.RadioItemIndicator>\n          <CheckIcon />\n        </MenuPrimitive.RadioItemIndicator>\n      </span>\n      {children}\n    </MenuPrimitive.RadioItem>\n  );\n}\n\nfunction DropdownMenuSeparator({ className, ...props }: MenuPrimitive.Separator.Props) {\n  return (\n    <MenuPrimitive.Separator\n      data-slot=\"dropdown-menu-separator\"\n      className={cn(\"mx-1 my-1 h-px bg-border\", className)}\n      {...props}\n    />\n  );\n}\n\nfunction DropdownMenuShortcut({ className, ...props }: React.ComponentProps<\"span\">) {\n  return (\n    <span\n      data-slot=\"dropdown-menu-shortcut\"\n      className={cn(\"ninaero-dropdown-menu-shortcut ms-auto text-xs tracking-widest\", className)}\n      {...props}\n    />\n  );\n}\n\nexport {\n  DropdownMenu,\n  DropdownMenuPortal,\n  DropdownMenuTrigger,\n  DropdownMenuContent,\n  DropdownMenuGroup,\n  DropdownMenuLabel,\n  DropdownMenuItem,\n  DropdownMenuCheckboxItem,\n  DropdownMenuRadioGroup,\n  DropdownMenuRadioItem,\n  DropdownMenuSeparator,\n  DropdownMenuShortcut,\n  DropdownMenuSub,\n  DropdownMenuSubTrigger,\n  DropdownMenuSubContent,\n};\n",
      "type": "registry:ui"
    }
  ],
  "type": "registry:ui"
}