1import * as React from "react"
2import * as DropdownMenuPrimitive from "@radix-ui/react-dropdown-menu"
3import { Check, ChevronRight, Circle } from "lucide-react"
4
5import { cn } from "@/lib/utils"
6
7const DropdownMenu = DropdownMenuPrimitive.Root
8
9const DropdownMenuTrigger = DropdownMenuPrimitive.Trigger
10
11const DropdownMenuGroup = DropdownMenuPrimitive.Group
12
13const DropdownMenuPortal = DropdownMenuPrimitive.Portal
14
15const DropdownMenuSub = DropdownMenuPrimitive.Sub
16
17const DropdownMenuRadioGroup = DropdownMenuPrimitive.RadioGroup
18
19const DropdownMenuSubTrigger = React.forwardRef<
20 React.ElementRef<typeof DropdownMenuPrimitive.SubTrigger>,
21 React.ComponentPropsWithoutRef<typeof DropdownMenuPrimitive.SubTrigger> & {
22 inset?: boolean
23 }
24>(({ className, inset, children, ...props }, ref) => (
25 <DropdownMenuPrimitive.SubTrigger
26 ref={ref}
27 className={cn(
28 "flex cursor-default select-none items-center rounded-sm px-2 py-1.5 text-sm outline-hidden focus:bg-accent data-[state=open]:bg-accent",
29 inset && "pl-8",
30 className
31 )}
32 {...props}
33 >
34 {children}
35 <ChevronRight className="ml-auto h-4 w-4" />
36 </DropdownMenuPrimitive.SubTrigger>
37))
38DropdownMenuSubTrigger.displayName =
39 DropdownMenuPrimitive.SubTrigger.displayName
40
41const DropdownMenuSubContent = React.forwardRef<
42 React.ElementRef<typeof DropdownMenuPrimitive.SubContent>,
43 React.ComponentPropsWithoutRef<typeof DropdownMenuPrimitive.SubContent>
44>(({ className, ...props }, ref) => (
45 <DropdownMenuPrimitive.SubContent
46 ref={ref}
47 className={cn(
48 "z-50 min-w-32 overflow-hidden rounded-md border bg-popover p-1 text-popover-foreground shadow-lg data-[state=open]:animate-in data-[state=closed]:animate-out data-[state=closed]:fade-out-0 data-[state=open]:fade-in-0 data-[state=closed]:zoom-out-95 data-[state=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",
49 className
50 )}
51 {...props}
52 />
53))
54DropdownMenuSubContent.displayName =
55 DropdownMenuPrimitive.SubContent.displayName
56
57const DropdownMenuContent = React.forwardRef<
58 React.ElementRef<typeof DropdownMenuPrimitive.Content>,
59 React.ComponentPropsWithoutRef<typeof DropdownMenuPrimitive.Content>
60>(({ className, sideOffset = 4, ...props }, ref) => (
61 <DropdownMenuPrimitive.Portal>
62 <DropdownMenuPrimitive.Content
63 ref={ref}
64 sideOffset={sideOffset}
65 className={cn(
66 "z-50 min-w-32 overflow-hidden rounded-md border bg-popover p-1 text-popover-foreground shadow-md data-[state=open]:animate-in data-[state=closed]:animate-out data-[state=closed]:fade-out-0 data-[state=open]:fade-in-0 data-[state=closed]:zoom-out-95 data-[state=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",
67 className
68 )}
69 {...props}
70 />
71 </DropdownMenuPrimitive.Portal>
72))
73DropdownMenuContent.displayName = DropdownMenuPrimitive.Content.displayName
74
75const DropdownMenuItem = React.forwardRef<
76 React.ElementRef<typeof DropdownMenuPrimitive.Item>,
77 React.ComponentPropsWithoutRef<typeof DropdownMenuPrimitive.Item> & {
78 inset?: boolean
79 }
80>(({ className, inset, ...props }, ref) => (
81 <DropdownMenuPrimitive.Item
82 ref={ref}
83 className={cn(
84 "relative flex cursor-default select-none items-center rounded-sm px-2 py-1.5 text-sm outline-hidden transition-colors focus:bg-accent focus:text-accent-foreground data-disabled:pointer-events-none data-disabled:opacity-50",
85 inset && "pl-8",
86 className
87 )}
88 {...props}
89 />
90))
91DropdownMenuItem.displayName = DropdownMenuPrimitive.Item.displayName
92
93const DropdownMenuCheckboxItem = React.forwardRef<
94 React.ElementRef<typeof DropdownMenuPrimitive.CheckboxItem>,
95 React.ComponentPropsWithoutRef<typeof DropdownMenuPrimitive.CheckboxItem>
96>(({ className, children, checked, ...props }, ref) => (
97 <DropdownMenuPrimitive.CheckboxItem
98 ref={ref}
99 className={cn(
100 "relative flex cursor-default select-none items-center rounded-sm py-1.5 pl-8 pr-2 text-sm outline-hidden transition-colors focus:bg-accent focus:text-accent-foreground data-disabled:pointer-events-none data-disabled:opacity-50",
101 className
102 )}
103 checked={checked}
104 {...props}
105 >
106 <span className="absolute left-2 flex h-3.5 w-3.5 items-center justify-center">
107 <DropdownMenuPrimitive.ItemIndicator>
108 <Check className="h-4 w-4" />
109 </DropdownMenuPrimitive.ItemIndicator>
110 </span>
111 {children}
112 </DropdownMenuPrimitive.CheckboxItem>
113))
114DropdownMenuCheckboxItem.displayName =
115 DropdownMenuPrimitive.CheckboxItem.displayName
116
117const DropdownMenuRadioItem = React.forwardRef<
118 React.ElementRef<typeof DropdownMenuPrimitive.RadioItem>,
119 React.ComponentPropsWithoutRef<typeof DropdownMenuPrimitive.RadioItem>
120>(({ className, children, ...props }, ref) => (
121 <DropdownMenuPrimitive.RadioItem
122 ref={ref}
123 className={cn(
124 "relative flex cursor-default select-none items-center rounded-sm py-1.5 pl-8 pr-2 text-sm outline-hidden transition-colors focus:bg-accent focus:text-accent-foreground data-disabled:pointer-events-none data-disabled:opacity-50",
125 className
126 )}
127 {...props}
128 >
129 <span className="absolute left-2 flex h-3.5 w-3.5 items-center justify-center">
130 <DropdownMenuPrimitive.ItemIndicator>
131 <Circle className="h-2 w-2 fill-current" />
132 </DropdownMenuPrimitive.ItemIndicator>
133 </span>
134 {children}
135 </DropdownMenuPrimitive.RadioItem>
136))
137DropdownMenuRadioItem.displayName = DropdownMenuPrimitive.RadioItem.displayName
138
139const DropdownMenuLabel = React.forwardRef<
140 React.ElementRef<typeof DropdownMenuPrimitive.Label>,
141 React.ComponentPropsWithoutRef<typeof DropdownMenuPrimitive.Label> & {
142 inset?: boolean
143 }
144>(({ className, inset, ...props }, ref) => (
145 <DropdownMenuPrimitive.Label
146 ref={ref}
147 className={cn(
148 "px-2 py-1.5 text-sm font-semibold",
149 inset && "pl-8",
150 className
151 )}
152 {...props}
153 />
154))
155DropdownMenuLabel.displayName = DropdownMenuPrimitive.Label.displayName
156
157const DropdownMenuSeparator = React.forwardRef<
158 React.ElementRef<typeof DropdownMenuPrimitive.Separator>,
159 React.ComponentPropsWithoutRef<typeof DropdownMenuPrimitive.Separator>
160>(({ className, ...props }, ref) => (
161 <DropdownMenuPrimitive.Separator
162 ref={ref}
163 className={cn("-mx-1 my-1 h-px bg-muted", className)}
164 {...props}
165 />
166))
167DropdownMenuSeparator.displayName = DropdownMenuPrimitive.Separator.displayName
168
169const DropdownMenuShortcut = ({
170 className,
171 ...props
172}: React.HTMLAttributes<HTMLSpanElement>) => {
173 return (
174 <span
175 className={cn("ml-auto text-xs tracking-widest opacity-60", className)}
176 {...props}
177 />
178 )
179}
180DropdownMenuShortcut.displayName = "DropdownMenuShortcut"
181
182export {
183 DropdownMenu,
184 DropdownMenuTrigger,
185 DropdownMenuContent,
186 DropdownMenuItem,
187 DropdownMenuCheckboxItem,
188 DropdownMenuRadioItem,
189 DropdownMenuLabel,
190 DropdownMenuSeparator,
191 DropdownMenuShortcut,
192 DropdownMenuGroup,
193 DropdownMenuPortal,
194 DropdownMenuSub,
195 DropdownMenuSubContent,
196 DropdownMenuSubTrigger,
197 DropdownMenuRadioGroup,
198}