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