返回 presentation-ai
dropdown-menu.tsx
根目录 / src / components / plate / ui / dropdown-menu.tsx
1 "use client";
2
3 import * as DropdownMenuPrimitive from "@radix-ui/react-dropdown-menu";
4 import { CheckIcon, ChevronRightIcon, CircleIcon } from "lucide-react";
5 import type * as React from "react";
6
7 import { cn } from "@/lib/utils";
8
9 function DropdownMenu({
10 ...props
11 }: React.ComponentProps<typeof DropdownMenuPrimitive.Root>) {
12 return <DropdownMenuPrimitive.Root data-slot="dropdown-menu" {...props} />;
13 }
14
15 function DropdownMenuPortal({
16 ...props
17 }: React.ComponentProps<typeof DropdownMenuPrimitive.Portal>) {
18 return (
19 <DropdownMenuPrimitive.Portal data-slot="dropdown-menu-portal" {...props} />
20 );
21 }
22
23 function DropdownMenuTrigger({
24 ...props
25 }: React.ComponentProps<typeof DropdownMenuPrimitive.Trigger>) {
26 return (
27 <DropdownMenuPrimitive.Trigger
28 data-slot="dropdown-menu-trigger"
29 {...props}
30 />
31 );
32 }
33
34 function DropdownMenuContent({
35 className,
36 sideOffset = 4,
37 ...props
38 }: React.ComponentProps<typeof DropdownMenuPrimitive.Content>) {
39 return (
40 <DropdownMenuPrimitive.Portal>
41 <DropdownMenuPrimitive.Content
42 data-slot="dropdown-menu-content"
43 sideOffset={sideOffset}
44 className={cn(
45 "z-50 max-h-(--radix-dropdown-menu-content-available-height) min-w-32 origin-(--radix-dropdown-menu-content-transform-origin) overflow-x-hidden overflow-y-auto rounded-md border bg-popover p-1 text-popover-foreground shadow-md 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-[state=closed]:animate-out data-[state=closed]:fade-out-0 data-[state=closed]:zoom-out-95 data-[state=open]:animate-in data-[state=open]:fade-in-0 data-[state=open]:zoom-in-95",
46 className,
47 )}
48 {...props}
49 />
50 </DropdownMenuPrimitive.Portal>
51 );
52 }
53
54 function DropdownMenuGroup({
55 ...props
56 }: React.ComponentProps<typeof DropdownMenuPrimitive.Group>) {
57 return (
58 <DropdownMenuPrimitive.Group data-slot="dropdown-menu-group" {...props} />
59 );
60 }
61
62 function DropdownMenuItem({
63 className,
64 inset,
65 variant = "default",
66 ...props
67 }: React.ComponentProps<typeof DropdownMenuPrimitive.Item> & {
68 inset?: boolean;
69 variant?: "default" | "destructive";
70 }) {
71 return (
72 <DropdownMenuPrimitive.Item
73 data-slot="dropdown-menu-item"
74 data-inset={inset}
75 data-variant={variant}
76 className={cn(
77 "relative flex cursor-default items-center gap-2 rounded-sm px-2 py-1.5 text-sm outline-hidden select-none focus:bg-accent focus:text-accent-foreground data-disabled:pointer-events-none data-disabled:opacity-50 data-inset:pl-8 data-[variant=destructive]:text-destructive data-[variant=destructive]:focus:bg-destructive/10 data-[variant=destructive]:focus:text-destructive dark:data-[variant=destructive]:focus:bg-destructive/20 [&_svg]:pointer-events-none [&_svg]:shrink-0 [&_svg:not([class*='size-'])]:size-4 [&_svg:not([class*='text-'])]:text-muted-foreground [svg]:*:data-[variant=destructive]:text-destructive!",
78 className,
79 )}
80 {...props}
81 />
82 );
83 }
84
85 function DropdownMenuCheckboxItem({
86 className,
87 children,
88 checked,
89 ...props
90 }: React.ComponentProps<typeof DropdownMenuPrimitive.CheckboxItem>) {
91 return (
92 <DropdownMenuPrimitive.CheckboxItem
93 data-slot="dropdown-menu-checkbox-item"
94 className={cn(
95 "relative flex cursor-default items-center gap-2 rounded-sm py-1.5 pr-2 pl-8 text-sm outline-hidden select-none focus:bg-accent focus:text-accent-foreground data-[state=checked]:bg-accent data-[state=checked]:text-accent-foreground data-disabled:pointer-events-none data-disabled:opacity-50 [&_svg]:pointer-events-none [&_svg]:shrink-0 [&_svg:not([class*='size-'])]:size-4",
96 className,
97 )}
98 checked={checked}
99 {...props}
100 >
101 <span className="pointer-events-none absolute left-2 flex size-3.5 items-center justify-center">
102 <DropdownMenuPrimitive.ItemIndicator>
103 <CheckIcon className="size-4" />
104 </DropdownMenuPrimitive.ItemIndicator>
105 </span>
106 {children}
107 </DropdownMenuPrimitive.CheckboxItem>
108 );
109 }
110
111 function DropdownMenuRadioGroup({
112 ...props
113 }: React.ComponentProps<typeof DropdownMenuPrimitive.RadioGroup>) {
114 return (
115 <DropdownMenuPrimitive.RadioGroup
116 data-slot="dropdown-menu-radio-group"
117 {...props}
118 />
119 );
120 }
121
122 function DropdownMenuRadioItem({
123 className,
124 children,
125 ...props
126 }: React.ComponentProps<typeof DropdownMenuPrimitive.RadioItem>) {
127 return (
128 <DropdownMenuPrimitive.RadioItem
129 data-slot="dropdown-menu-radio-item"
130 className={cn(
131 "relative flex cursor-default items-center gap-2 rounded-sm py-1.5 pr-2 pl-8 text-sm outline-hidden select-none focus:bg-accent focus:text-accent-foreground data-[state=checked]:bg-accent data-[state=checked]:text-accent-foreground data-disabled:pointer-events-none data-disabled:opacity-50 [&_svg]:pointer-events-none [&_svg]:shrink-0 [&_svg:not([class*='size-'])]:size-4",
132 className,
133 )}
134 {...props}
135 >
136 <span className="pointer-events-none absolute left-2 flex size-3.5 items-center justify-center">
137 <DropdownMenuPrimitive.ItemIndicator>
138 <CircleIcon className="size-2 fill-current" />
139 </DropdownMenuPrimitive.ItemIndicator>
140 </span>
141 {children}
142 </DropdownMenuPrimitive.RadioItem>
143 );
144 }
145
146 function DropdownMenuLabel({
147 className,
148 inset,
149 ...props
150 }: React.ComponentProps<typeof DropdownMenuPrimitive.Label> & {
151 inset?: boolean;
152 }) {
153 return (
154 <DropdownMenuPrimitive.Label
155 data-slot="dropdown-menu-label"
156 data-inset={inset}
157 className={cn(
158 "px-2 py-1.5 text-sm font-medium data-inset:pl-8",
159 className,
160 )}
161 {...props}
162 />
163 );
164 }
165
166 function DropdownMenuSeparator({
167 className,
168 ...props
169 }: React.ComponentProps<typeof DropdownMenuPrimitive.Separator>) {
170 return (
171 <DropdownMenuPrimitive.Separator
172 data-slot="dropdown-menu-separator"
173 className={cn("-mx-1 my-1 h-px bg-border", className)}
174 {...props}
175 />
176 );
177 }
178
179 function DropdownMenuShortcut({
180 className,
181 ...props
182 }: React.ComponentProps<"span">) {
183 return (
184 <span
185 data-slot="dropdown-menu-shortcut"
186 className={cn(
187 "ml-auto text-xs tracking-widest text-muted-foreground",
188 className,
189 )}
190 {...props}
191 />
192 );
193 }
194
195 function DropdownMenuSub({
196 ...props
197 }: React.ComponentProps<typeof DropdownMenuPrimitive.Sub>) {
198 return <DropdownMenuPrimitive.Sub data-slot="dropdown-menu-sub" {...props} />;
199 }
200
201 function DropdownMenuSubTrigger({
202 className,
203 inset,
204 children,
205 ...props
206 }: React.ComponentProps<typeof DropdownMenuPrimitive.SubTrigger> & {
207 inset?: boolean;
208 }) {
209 return (
210 <DropdownMenuPrimitive.SubTrigger
211 data-slot="dropdown-menu-sub-trigger"
212 data-inset={inset}
213 className={cn(
214 "flex cursor-default items-center rounded-sm px-2 py-1.5 text-sm outline-hidden select-none focus:bg-accent focus:text-accent-foreground data-inset:pl-8 data-[state=open]:bg-accent data-[state=open]:text-accent-foreground",
215 className,
216 )}
217 {...props}
218 >
219 {children}
220 <ChevronRightIcon className="ml-auto size-4" />
221 </DropdownMenuPrimitive.SubTrigger>
222 );
223 }
224
225 function DropdownMenuSubContent({
226 className,
227 ...props
228 }: React.ComponentProps<typeof DropdownMenuPrimitive.SubContent>) {
229 return (
230 <DropdownMenuPrimitive.SubContent
231 data-slot="dropdown-menu-sub-content"
232 className={cn(
233 "z-50 min-w-32 origin-(--radix-dropdown-menu-content-transform-origin) overflow-hidden rounded-md border bg-popover p-1 text-popover-foreground shadow-lg 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-[state=closed]:animate-out data-[state=closed]:fade-out-0 data-[state=closed]:zoom-out-95 data-[state=open]:animate-in data-[state=open]:fade-in-0 data-[state=open]:zoom-in-95",
234 className,
235 )}
236 {...props}
237 />
238 );
239 }
240
241 export {
242 DropdownMenu,
243 DropdownMenuCheckboxItem,
244 DropdownMenuContent,
245 DropdownMenuGroup,
246 DropdownMenuItem,
247 DropdownMenuLabel,
248 DropdownMenuPortal,
249 DropdownMenuRadioGroup,
250 DropdownMenuRadioItem,
251 DropdownMenuSeparator,
252 DropdownMenuShortcut,
253 DropdownMenuSub,
254 DropdownMenuSubContent,
255 DropdownMenuSubTrigger,
256 DropdownMenuTrigger,
257 };
258
258 lines Plain Text