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