{
  "$schema": "https://blode.co/ui/schema/registry-item.json",
  "name": "dropdown-menu",
  "title": "Dropdown Menu",
  "author": "Matthew Blode",
  "description": "A menu that opens from a trigger button, displaying a list of actions.",
  "dependencies": ["@base-ui/react"],
  "files": [
    {
      "path": "ui/dropdown-menu.tsx",
      "content": "\"use client\";\n\nimport { Menu as DropdownMenuPrimitive } from \"@base-ui/react/menu\";\nimport { CheckIcon, ChevronRightIcon } from \"blode-icons-react\";\nimport * as React from \"react\";\n\nimport { cn } from \"@/lib/utils\";\n\nconst DropdownMenu = ({ ...props }: DropdownMenuPrimitive.Root.Props) => (\n  <DropdownMenuPrimitive.Root data-slot=\"dropdown-menu\" {...props} />\n);\n\nconst DropdownMenuPortal = ({ ...props }: DropdownMenuPrimitive.Portal.Props) => (\n  <DropdownMenuPrimitive.Portal data-slot=\"dropdown-menu-portal\" {...props} />\n);\n\nconst DropdownMenuTrigger = ({\n  asChild,\n  children,\n  ...props\n}: DropdownMenuPrimitive.Trigger.Props & {\n  asChild?: boolean;\n}) => {\n  if (asChild && React.isValidElement(children)) {\n    return (\n      <DropdownMenuPrimitive.Trigger\n        data-slot=\"dropdown-menu-trigger\"\n        render={children}\n        {...props}\n      />\n    );\n  }\n\n  return (\n    <DropdownMenuPrimitive.Trigger data-slot=\"dropdown-menu-trigger\" {...props}>\n      {children}\n    </DropdownMenuPrimitive.Trigger>\n  );\n};\n\nconst DropdownMenuContent = ({\n  className,\n  align = \"start\",\n  alignOffset = 0,\n  side = \"bottom\",\n  sideOffset = 4,\n  children,\n  ...props\n}: DropdownMenuPrimitive.Popup.Props &\n  Pick<\n    DropdownMenuPrimitive.Positioner.Props,\n    \"align\" | \"alignOffset\" | \"side\" | \"sideOffset\"\n  >) => (\n  <DropdownMenuPrimitive.Portal>\n    <DropdownMenuPrimitive.Positioner\n      align={align}\n      alignOffset={alignOffset}\n      className=\"isolate z-50 outline-none\"\n      side={side}\n      sideOffset={sideOffset}\n    >\n      <DropdownMenuPrimitive.Popup\n        className={cn(\n          \"data-closed:fade-out-0 data-open:fade-in-0 data-closed:zoom-out-95 data-open:zoom-in-95 data-[side=bottom]:slide-in-from-top-2 data-[side=left]:slide-in-from-right-2 data-[side=right]:slide-in-from-left-2 data-[side=top]:slide-in-from-bottom-2 data-[side=inline-start]:slide-in-from-right-2 data-[side=inline-end]:slide-in-from-left-2 cn-menu-target z-50 w-(--anchor-width) min-w-32 origin-(--transform-origin) overflow-hidden rounded-lg bg-popover text-popover-foreground shadow-soft outline-none ring-1 ring-foreground/10 duration-100 data-closed:animate-out data-open:animate-in\",\n          className,\n        )}\n        data-slot=\"dropdown-menu-content\"\n        {...props}\n      >\n        <div className=\"scroll-fade max-h-(--available-height) overflow-x-hidden overflow-y-auto p-1\">\n          {children}\n        </div>\n      </DropdownMenuPrimitive.Popup>\n    </DropdownMenuPrimitive.Positioner>\n  </DropdownMenuPrimitive.Portal>\n);\n\nconst DropdownMenuGroup = ({ ...props }: DropdownMenuPrimitive.Group.Props) => (\n  <DropdownMenuPrimitive.Group data-slot=\"dropdown-menu-group\" {...props} />\n);\n\nconst DropdownMenuItem = ({\n  className,\n  inset,\n  variant = \"default\",\n  asChild,\n  children,\n  ...props\n}: DropdownMenuPrimitive.Item.Props & {\n  inset?: boolean;\n  variant?: \"default\" | \"destructive\";\n  asChild?: boolean;\n}) => {\n  if (asChild && React.isValidElement(children)) {\n    return (\n      <DropdownMenuPrimitive.Item\n        className={cn(\n          \"group/dropdown-menu-item relative flex cursor-default select-none items-center gap-1.5 rounded-md px-1.5 py-1 text-sm outline-hidden focus:bg-accent focus:text-accent-foreground not-data-[variant=destructive]:focus:**:text-accent-foreground data-disabled:pointer-events-none data-inset:pl-7 data-[variant=destructive]:text-destructive data-disabled:opacity-50 data-[variant=destructive]:focus:bg-destructive/10 data-[variant=destructive]:focus:text-destructive dark:data-[variant=destructive]:focus:bg-destructive/20 [&_svg:not([class*='size-'])]:size-4 [&_svg]:pointer-events-none [&_svg]:shrink-0 data-[variant=destructive]:*:[svg]:text-destructive\",\n          className,\n        )}\n        data-inset={inset}\n        data-slot=\"dropdown-menu-item\"\n        data-variant={variant}\n        render={children}\n        {...props}\n      />\n    );\n  }\n\n  return (\n    <DropdownMenuPrimitive.Item\n      className={cn(\n        \"group/dropdown-menu-item relative flex cursor-default select-none items-center gap-1.5 rounded-md px-1.5 py-1 text-sm outline-hidden focus:bg-accent focus:text-accent-foreground not-data-[variant=destructive]:focus:**:text-accent-foreground data-disabled:pointer-events-none data-inset:pl-7 data-[variant=destructive]:text-destructive data-disabled:opacity-50 data-[variant=destructive]:focus:bg-destructive/10 data-[variant=destructive]:focus:text-destructive dark:data-[variant=destructive]:focus:bg-destructive/20 [&_svg:not([class*='size-'])]:size-4 [&_svg]:pointer-events-none [&_svg]:shrink-0 data-[variant=destructive]:*:[svg]:text-destructive\",\n        className,\n      )}\n      data-inset={inset}\n      data-slot=\"dropdown-menu-item\"\n      data-variant={variant}\n      {...props}\n    >\n      {children}\n    </DropdownMenuPrimitive.Item>\n  );\n};\n\ntype DropdownMenuCheckedState = boolean | \"indeterminate\";\n\ntype DropdownMenuCheckboxItemProps = Omit<\n  DropdownMenuPrimitive.CheckboxItem.Props,\n  \"checked\" | \"defaultChecked\" | \"onCheckedChange\"\n> & {\n  checked?: DropdownMenuCheckedState;\n  defaultChecked?: DropdownMenuCheckedState;\n  onCheckedChange?: (\n    checked: DropdownMenuCheckedState,\n    eventDetails: DropdownMenuPrimitive.CheckboxItem.ChangeEventDetails,\n  ) => void;\n};\n\nconst DropdownMenuCheckboxItem = ({\n  className,\n  children,\n  checked,\n  defaultChecked,\n  onCheckedChange,\n  inset,\n  ...props\n}: DropdownMenuCheckboxItemProps & {\n  inset?: boolean;\n}) => (\n  <DropdownMenuPrimitive.CheckboxItem\n    checked={checked === \"indeterminate\" ? true : checked}\n    className={cn(\n      \"relative flex cursor-default select-none items-center gap-1.5 rounded-md py-1 pr-8 pl-1.5 text-sm outline-hidden focus:bg-accent focus:text-accent-foreground focus:**:text-accent-foreground data-disabled:pointer-events-none data-inset:pl-7 data-disabled:opacity-50 [&_svg:not([class*='size-'])]:size-4 [&_svg]:pointer-events-none [&_svg]:shrink-0\",\n      className,\n    )}\n    data-inset={inset}\n    data-slot=\"dropdown-menu-checkbox-item\"\n    defaultChecked={defaultChecked === \"indeterminate\" ? true : defaultChecked}\n    onCheckedChange={(value, eventDetails) => onCheckedChange?.(value, eventDetails)}\n    {...props}\n  >\n    <span\n      className=\"pointer-events-none absolute right-2 flex items-center justify-center\"\n      data-slot=\"dropdown-menu-checkbox-item-indicator\"\n    >\n      <DropdownMenuPrimitive.CheckboxItemIndicator>\n        <CheckIcon />\n      </DropdownMenuPrimitive.CheckboxItemIndicator>\n    </span>\n    {children}\n  </DropdownMenuPrimitive.CheckboxItem>\n);\n\nconst DropdownMenuRadioGroup = ({ ...props }: DropdownMenuPrimitive.RadioGroup.Props) => (\n  <DropdownMenuPrimitive.RadioGroup data-slot=\"dropdown-menu-radio-group\" {...props} />\n);\n\nconst DropdownMenuRadioItem = ({\n  className,\n  children,\n  inset,\n  ...props\n}: DropdownMenuPrimitive.RadioItem.Props & {\n  inset?: boolean;\n}) => (\n  <DropdownMenuPrimitive.RadioItem\n    className={cn(\n      \"relative flex cursor-default select-none items-center gap-1.5 rounded-md py-1 pr-8 pl-1.5 text-sm outline-hidden focus:bg-accent focus:text-accent-foreground focus:**:text-accent-foreground data-disabled:pointer-events-none data-inset:pl-7 data-disabled:opacity-50 [&_svg:not([class*='size-'])]:size-4 [&_svg]:pointer-events-none [&_svg]:shrink-0\",\n      className,\n    )}\n    data-inset={inset}\n    data-slot=\"dropdown-menu-radio-item\"\n    {...props}\n  >\n    <span\n      className=\"pointer-events-none absolute right-2 flex items-center justify-center\"\n      data-slot=\"dropdown-menu-radio-item-indicator\"\n    >\n      <DropdownMenuPrimitive.RadioItemIndicator>\n        <CheckIcon />\n      </DropdownMenuPrimitive.RadioItemIndicator>\n    </span>\n    {children}\n  </DropdownMenuPrimitive.RadioItem>\n);\n\nconst DropdownMenuLabel = ({\n  className,\n  inset,\n  ...props\n}: DropdownMenuPrimitive.GroupLabel.Props & {\n  inset?: boolean;\n}) => (\n  <DropdownMenuPrimitive.GroupLabel\n    className={cn(\n      \"px-1.5 py-1 font-medium text-muted-foreground text-xs data-inset:pl-7\",\n      className,\n    )}\n    data-inset={inset}\n    data-slot=\"dropdown-menu-label\"\n    {...props}\n  />\n);\n\nconst DropdownMenuSeparator = ({ className, ...props }: DropdownMenuPrimitive.Separator.Props) => (\n  <DropdownMenuPrimitive.Separator\n    className={cn(\"-mx-1 my-1 h-px bg-border\", className)}\n    data-slot=\"dropdown-menu-separator\"\n    {...props}\n  />\n);\n\nconst DropdownMenuShortcut = ({ className, ...props }: React.ComponentProps<\"span\">) => (\n  <span\n    className={cn(\n      \"ml-auto text-muted-foreground text-xs tracking-widest group-focus/dropdown-menu-item:text-accent-foreground\",\n      className,\n    )}\n    data-slot=\"dropdown-menu-shortcut\"\n    {...props}\n  />\n);\n\nconst DropdownMenuSub = ({ ...props }: DropdownMenuPrimitive.SubmenuRoot.Props) => (\n  <DropdownMenuPrimitive.SubmenuRoot data-slot=\"dropdown-menu-sub\" {...props} />\n);\n\nconst DropdownMenuSubTrigger = ({\n  className,\n  inset,\n  children,\n  ...props\n}: DropdownMenuPrimitive.SubmenuTrigger.Props & {\n  inset?: boolean;\n}) => (\n  <DropdownMenuPrimitive.SubmenuTrigger\n    className={cn(\n      \"flex cursor-default select-none items-center gap-1.5 rounded-md px-1.5 py-1 text-sm outline-hidden focus:bg-accent focus:text-accent-foreground not-data-[variant=destructive]:focus:**:text-accent-foreground data-open:bg-accent data-popup-open:bg-accent data-inset:pl-7 data-open:text-accent-foreground data-popup-open:text-accent-foreground [&_svg:not([class*='size-'])]:size-4 [&_svg]:pointer-events-none [&_svg]:shrink-0\",\n      className,\n    )}\n    data-inset={inset}\n    data-slot=\"dropdown-menu-sub-trigger\"\n    {...props}\n  >\n    {children}\n    <ChevronRightIcon className=\"cn-rtl-flip ml-auto\" />\n  </DropdownMenuPrimitive.SubmenuTrigger>\n);\n\nconst DropdownMenuSubContent = ({\n  align = \"start\",\n  alignOffset = -3,\n  side = \"right\",\n  sideOffset = 0,\n  className,\n  ...props\n}: React.ComponentProps<typeof DropdownMenuContent>) => (\n  <DropdownMenuContent\n    align={align}\n    alignOffset={alignOffset}\n    className={cn(\n      \"data-closed:fade-out-0 data-open:fade-in-0 data-closed:zoom-out-95 data-open:zoom-in-95 data-[side=bottom]:slide-in-from-top-2 data-[side=left]:slide-in-from-right-2 data-[side=right]:slide-in-from-left-2 data-[side=top]:slide-in-from-bottom-2 w-auto min-w-[96px] rounded-md bg-popover text-popover-foreground shadow-soft ring-1 ring-foreground/10 duration-100 data-closed:animate-out data-open:animate-in\",\n      className,\n    )}\n    data-slot=\"dropdown-menu-sub-content\"\n    side={side}\n    sideOffset={sideOffset}\n    {...props}\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",
      "target": ""
    }
  ],
  "type": "registry:ui"
}
