@lark-apaas/coding-template-react-standard-webapp 0.1.0-alpha.20260827082008

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (89) hide show
  1. package/LICENSE +13 -0
  2. package/README.md +25 -0
  3. package/hooks/after-install.mjs +3 -0
  4. package/hooks/after-render.mjs +3 -0
  5. package/hooks/before-render.mjs +3 -0
  6. package/package.json +35 -0
  7. package/template/README.md +105 -0
  8. package/template/_gitignore +64 -0
  9. package/template/_npmrc +1 -0
  10. package/template/components.json +21 -0
  11. package/template/eslint.config.mjs +27 -0
  12. package/template/index.html +13 -0
  13. package/template/miaoda.json +11 -0
  14. package/template/package-lock.json +7685 -0
  15. package/template/package.json +89 -0
  16. package/template/public/favicon.svg +1 -0
  17. package/template/public/icons.svg +24 -0
  18. package/template/src/app.tsx +15 -0
  19. package/template/src/components/ErrorFallback.tsx +19 -0
  20. package/template/src/components/Layout.tsx +7 -0
  21. package/template/src/components/ui/accordion.tsx +66 -0
  22. package/template/src/components/ui/alert-dialog.tsx +157 -0
  23. package/template/src/components/ui/alert.tsx +71 -0
  24. package/template/src/components/ui/aspect-ratio.tsx +11 -0
  25. package/template/src/components/ui/avatar.tsx +53 -0
  26. package/template/src/components/ui/badge.tsx +42 -0
  27. package/template/src/components/ui/breadcrumb.tsx +109 -0
  28. package/template/src/components/ui/button-group.tsx +83 -0
  29. package/template/src/components/ui/button.tsx +69 -0
  30. package/template/src/components/ui/calendar.tsx +213 -0
  31. package/template/src/components/ui/card.tsx +82 -0
  32. package/template/src/components/ui/carousel.tsx +241 -0
  33. package/template/src/components/ui/chart.tsx +357 -0
  34. package/template/src/components/ui/checkbox.tsx +32 -0
  35. package/template/src/components/ui/collapsible.tsx +33 -0
  36. package/template/src/components/ui/command.tsx +208 -0
  37. package/template/src/components/ui/context-menu.tsx +324 -0
  38. package/template/src/components/ui/dialog.tsx +143 -0
  39. package/template/src/components/ui/drawer.tsx +135 -0
  40. package/template/src/components/ui/dropdown-menu.tsx +329 -0
  41. package/template/src/components/ui/empty.tsx +104 -0
  42. package/template/src/components/ui/field.tsx +248 -0
  43. package/template/src/components/ui/form.tsx +167 -0
  44. package/template/src/components/ui/hover-card.tsx +44 -0
  45. package/template/src/components/ui/image.tsx +183 -0
  46. package/template/src/components/ui/input-group.tsx +166 -0
  47. package/template/src/components/ui/input-otp.tsx +77 -0
  48. package/template/src/components/ui/input.tsx +21 -0
  49. package/template/src/components/ui/item.tsx +193 -0
  50. package/template/src/components/ui/kbd.tsx +28 -0
  51. package/template/src/components/ui/label.tsx +24 -0
  52. package/template/src/components/ui/menubar.tsx +348 -0
  53. package/template/src/components/ui/native-select.tsx +48 -0
  54. package/template/src/components/ui/navigation-menu.tsx +168 -0
  55. package/template/src/components/ui/pagination.tsx +127 -0
  56. package/template/src/components/ui/popover.tsx +48 -0
  57. package/template/src/components/ui/progress.tsx +31 -0
  58. package/template/src/components/ui/radio-group.tsx +45 -0
  59. package/template/src/components/ui/resizable.tsx +56 -0
  60. package/template/src/components/ui/scroll-area.tsx +58 -0
  61. package/template/src/components/ui/select.tsx +243 -0
  62. package/template/src/components/ui/separator.tsx +28 -0
  63. package/template/src/components/ui/sheet.tsx +139 -0
  64. package/template/src/components/ui/sidebar.tsx +727 -0
  65. package/template/src/components/ui/skeleton.tsx +13 -0
  66. package/template/src/components/ui/slider.tsx +87 -0
  67. package/template/src/components/ui/sonner.tsx +67 -0
  68. package/template/src/components/ui/spinner.tsx +16 -0
  69. package/template/src/components/ui/switch.tsx +31 -0
  70. package/template/src/components/ui/table.tsx +116 -0
  71. package/template/src/components/ui/tabs.tsx +66 -0
  72. package/template/src/components/ui/textarea.tsx +18 -0
  73. package/template/src/components/ui/toggle-group.tsx +83 -0
  74. package/template/src/components/ui/toggle.tsx +47 -0
  75. package/template/src/components/ui/tooltip.tsx +61 -0
  76. package/template/src/hooks/use-mobile.ts +20 -0
  77. package/template/src/index.css +4 -0
  78. package/template/src/index.tsx +17 -0
  79. package/template/src/lib/utils.ts +6 -0
  80. package/template/src/pages/ExamplePage/ExamplePage.tsx +37 -0
  81. package/template/src/pages/HomePage/HomePage.tsx +10 -0
  82. package/template/src/pages/NotFoundPage/NotFoundPage.tsx +11 -0
  83. package/template/src/tailwind-theme.css +258 -0
  84. package/template/src/typography.css +41 -0
  85. package/template/src/vite-env.d.ts +5 -0
  86. package/template/tsconfig.app.json +29 -0
  87. package/template/tsconfig.json +10 -0
  88. package/template/tsconfig.node.json +26 -0
  89. package/template/vite.config.ts +97 -0
@@ -0,0 +1,135 @@
1
+ "use client"
2
+
3
+ import * as React from "react"
4
+ import { Drawer as DrawerPrimitive } from "vaul"
5
+
6
+ import { cn } from "@/lib/utils"
7
+
8
+ function Drawer({
9
+ ...props
10
+ }: React.ComponentProps<typeof DrawerPrimitive.Root>) {
11
+ return <DrawerPrimitive.Root data-slot="drawer" {...props} />
12
+ }
13
+
14
+ function DrawerTrigger({
15
+ ...props
16
+ }: React.ComponentProps<typeof DrawerPrimitive.Trigger>) {
17
+ return <DrawerPrimitive.Trigger data-slot="drawer-trigger" {...props} />
18
+ }
19
+
20
+ function DrawerPortal({
21
+ ...props
22
+ }: React.ComponentProps<typeof DrawerPrimitive.Portal>) {
23
+ return <DrawerPrimitive.Portal data-slot="drawer-portal" {...props} />
24
+ }
25
+
26
+ function DrawerClose({
27
+ ...props
28
+ }: React.ComponentProps<typeof DrawerPrimitive.Close>) {
29
+ return <DrawerPrimitive.Close data-slot="drawer-close" {...props} />
30
+ }
31
+
32
+ function DrawerOverlay({
33
+ className,
34
+ ...props
35
+ }: React.ComponentProps<typeof DrawerPrimitive.Overlay>) {
36
+ return (
37
+ <DrawerPrimitive.Overlay
38
+ data-slot="drawer-overlay"
39
+ className={cn(
40
+ "data-[state=open]:animate-in data-[state=closed]:animate-out data-[state=closed]:fade-out-0 data-[state=open]:fade-in-0 fixed inset-0 z-50 bg-black/50",
41
+ className
42
+ )}
43
+ {...props}
44
+ />
45
+ )
46
+ }
47
+
48
+ function DrawerContent({
49
+ className,
50
+ children,
51
+ ...props
52
+ }: React.ComponentProps<typeof DrawerPrimitive.Content>) {
53
+ return (
54
+ <DrawerPortal data-slot="drawer-portal">
55
+ <DrawerOverlay />
56
+ <DrawerPrimitive.Content
57
+ data-slot="drawer-content"
58
+ className={cn(
59
+ "group/drawer-content bg-background fixed z-50 flex h-auto flex-col",
60
+ "data-[vaul-drawer-direction=top]:inset-x-0 data-[vaul-drawer-direction=top]:top-0 data-[vaul-drawer-direction=top]:mb-24 data-[vaul-drawer-direction=top]:max-h-[80vh] data-[vaul-drawer-direction=top]:rounded-b-lg data-[vaul-drawer-direction=top]:border-b",
61
+ "data-[vaul-drawer-direction=bottom]:inset-x-0 data-[vaul-drawer-direction=bottom]:bottom-0 data-[vaul-drawer-direction=bottom]:mt-24 data-[vaul-drawer-direction=bottom]:max-h-[80vh] data-[vaul-drawer-direction=bottom]:rounded-t-lg data-[vaul-drawer-direction=bottom]:border-t",
62
+ "data-[vaul-drawer-direction=right]:inset-y-0 data-[vaul-drawer-direction=right]:right-0 data-[vaul-drawer-direction=right]:w-3/4 data-[vaul-drawer-direction=right]:border-l data-[vaul-drawer-direction=right]:sm:max-w-sm",
63
+ "data-[vaul-drawer-direction=left]:inset-y-0 data-[vaul-drawer-direction=left]:left-0 data-[vaul-drawer-direction=left]:w-3/4 data-[vaul-drawer-direction=left]:border-r data-[vaul-drawer-direction=left]:sm:max-w-sm",
64
+ className
65
+ )}
66
+ {...props}
67
+ >
68
+ <div className="bg-muted mx-auto mt-4 hidden h-2 w-[100px] shrink-0 rounded-full group-data-[vaul-drawer-direction=bottom]/drawer-content:block" />
69
+ {children}
70
+ </DrawerPrimitive.Content>
71
+ </DrawerPortal>
72
+ )
73
+ }
74
+
75
+ function DrawerHeader({ className, ...props }: React.ComponentProps<"div">) {
76
+ return (
77
+ <div
78
+ data-slot="drawer-header"
79
+ className={cn(
80
+ "flex flex-col gap-0.5 p-4 group-data-[vaul-drawer-direction=bottom]/drawer-content:text-center group-data-[vaul-drawer-direction=top]/drawer-content:text-center md:gap-1.5 md:text-left",
81
+ className
82
+ )}
83
+ {...props}
84
+ />
85
+ )
86
+ }
87
+
88
+ function DrawerFooter({ className, ...props }: React.ComponentProps<"div">) {
89
+ return (
90
+ <div
91
+ data-slot="drawer-footer"
92
+ className={cn("mt-auto flex flex-col gap-2 p-4", className)}
93
+ {...props}
94
+ />
95
+ )
96
+ }
97
+
98
+ function DrawerTitle({
99
+ className,
100
+ ...props
101
+ }: React.ComponentProps<typeof DrawerPrimitive.Title>) {
102
+ return (
103
+ <DrawerPrimitive.Title
104
+ data-slot="drawer-title"
105
+ className={cn("text-foreground font-semibold", className)}
106
+ {...props}
107
+ />
108
+ )
109
+ }
110
+
111
+ function DrawerDescription({
112
+ className,
113
+ ...props
114
+ }: React.ComponentProps<typeof DrawerPrimitive.Description>) {
115
+ return (
116
+ <DrawerPrimitive.Description
117
+ data-slot="drawer-description"
118
+ className={cn("text-muted-foreground text-sm", className)}
119
+ {...props}
120
+ />
121
+ )
122
+ }
123
+
124
+ export {
125
+ Drawer,
126
+ DrawerPortal,
127
+ DrawerOverlay,
128
+ DrawerTrigger,
129
+ DrawerClose,
130
+ DrawerContent,
131
+ DrawerHeader,
132
+ DrawerFooter,
133
+ DrawerTitle,
134
+ DrawerDescription,
135
+ }
@@ -0,0 +1,329 @@
1
+ "use client"
2
+
3
+ import * as React from "react"
4
+ import * as DropdownMenuPrimitive from "@radix-ui/react-dropdown-menu"
5
+ import { CheckIcon, ChevronRightIcon, CircleIcon } from "lucide-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
+ "bg-popover text-popover-foreground 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 z-50 max-h-(--radix-dropdown-menu-content-available-height) min-w-[8rem] origin-(--radix-dropdown-menu-content-transform-origin) overflow-x-hidden overflow-y-auto rounded-md border p-1 shadow-md",
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
+ disabled,
67
+ onClick,
68
+ onMouseDown,
69
+ onKeyDown,
70
+ onKeyUp,
71
+ onPointerDown,
72
+ ...props
73
+ }: React.ComponentProps<typeof DropdownMenuPrimitive.Item> & {
74
+ inset?: boolean
75
+ variant?: "default" | "destructive"
76
+ }) {
77
+ return (
78
+ <DropdownMenuPrimitive.Item
79
+ data-slot="dropdown-menu-item"
80
+ data-inset={inset}
81
+ data-variant={variant}
82
+ className={cn(
83
+ "focus:bg-accent focus:text-accent-foreground data-[variant=destructive]:text-destructive data-[variant=destructive]:focus:bg-destructive/10 dark:data-[variant=destructive]:focus:bg-destructive/20 data-[variant=destructive]:focus:text-destructive data-[variant=destructive]:*:[svg]:!text-destructive relative flex cursor-default items-center gap-2 rounded-sm px-2 py-1.5 text-sm outline-hidden select-none data-[disabled]:cursor-not-allowed data-[disabled]:opacity-50 data-[inset]:pl-8 [&_svg]:pointer-events-none [&_svg]:shrink-0 [&_svg:not([class*='size-'])]:size-4",
84
+ className
85
+ )}
86
+ disabled={disabled}
87
+ onClick={(event) => {
88
+ if (disabled) {
89
+ event.preventDefault()
90
+ return
91
+ }
92
+ onClick?.(event)
93
+ }}
94
+ onMouseDown={disabled ? undefined : onMouseDown}
95
+ onKeyDown={disabled ? undefined : onKeyDown}
96
+ onKeyUp={disabled ? undefined : onKeyUp}
97
+ onPointerDown={(event) => {
98
+ if (disabled) {
99
+ event.preventDefault()
100
+ return
101
+ }
102
+ onPointerDown?.(event)
103
+ }}
104
+ {...props}
105
+ />
106
+ )
107
+ }
108
+
109
+ function DropdownMenuCheckboxItem({
110
+ className,
111
+ children,
112
+ checked,
113
+ disabled,
114
+ onClick,
115
+ onMouseDown,
116
+ onKeyDown,
117
+ onKeyUp,
118
+ onPointerDown,
119
+ ...props
120
+ }: React.ComponentProps<typeof DropdownMenuPrimitive.CheckboxItem>) {
121
+ return (
122
+ <DropdownMenuPrimitive.CheckboxItem
123
+ data-slot="dropdown-menu-checkbox-item"
124
+ className={cn(
125
+ "focus:bg-accent focus:text-accent-foreground relative flex cursor-default items-center gap-2 rounded-sm py-1.5 pr-2 pl-8 text-sm outline-hidden select-none data-[disabled]:cursor-not-allowed data-[disabled]:opacity-50 [&_svg]:pointer-events-none [&_svg]:shrink-0 [&_svg:not([class*='size-'])]:size-4",
126
+ className
127
+ )}
128
+ checked={checked}
129
+ disabled={disabled}
130
+ onClick={(event) => {
131
+ if (disabled) {
132
+ event.preventDefault()
133
+ return
134
+ }
135
+ onClick?.(event)
136
+ }}
137
+ onMouseDown={disabled ? undefined : onMouseDown}
138
+ onKeyDown={disabled ? undefined : onKeyDown}
139
+ onKeyUp={disabled ? undefined : onKeyUp}
140
+ onPointerDown={(event) => {
141
+ if (disabled) {
142
+ event.preventDefault()
143
+ return
144
+ }
145
+ onPointerDown?.(event)
146
+ }}
147
+ {...props}
148
+ >
149
+ <span className="pointer-events-none absolute left-2 flex size-3.5 items-center justify-center">
150
+ <DropdownMenuPrimitive.ItemIndicator>
151
+ <CheckIcon className="size-4" />
152
+ </DropdownMenuPrimitive.ItemIndicator>
153
+ </span>
154
+ {children}
155
+ </DropdownMenuPrimitive.CheckboxItem>
156
+ )
157
+ }
158
+
159
+ function DropdownMenuRadioGroup({
160
+ ...props
161
+ }: React.ComponentProps<typeof DropdownMenuPrimitive.RadioGroup>) {
162
+ return (
163
+ <DropdownMenuPrimitive.RadioGroup
164
+ data-slot="dropdown-menu-radio-group"
165
+ {...props}
166
+ />
167
+ )
168
+ }
169
+
170
+ function DropdownMenuRadioItem({
171
+ className,
172
+ children,
173
+ disabled,
174
+ onClick,
175
+ onMouseDown,
176
+ onKeyDown,
177
+ onKeyUp,
178
+ onPointerDown,
179
+ ...props
180
+ }: React.ComponentProps<typeof DropdownMenuPrimitive.RadioItem>) {
181
+ return (
182
+ <DropdownMenuPrimitive.RadioItem
183
+ data-slot="dropdown-menu-radio-item"
184
+ className={cn(
185
+ "focus:bg-accent focus:text-accent-foreground relative flex cursor-default items-center gap-2 rounded-sm py-1.5 pr-2 pl-8 text-sm outline-hidden select-none data-[disabled]:cursor-not-allowed data-[disabled]:opacity-50 [&_svg]:pointer-events-none [&_svg]:shrink-0 [&_svg:not([class*='size-'])]:size-4",
186
+ className
187
+ )}
188
+ disabled={disabled}
189
+ onClick={(event) => {
190
+ if (disabled) {
191
+ event.preventDefault()
192
+ return
193
+ }
194
+ onClick?.(event)
195
+ }}
196
+ onMouseDown={disabled ? undefined : onMouseDown}
197
+ onKeyDown={disabled ? undefined : onKeyDown}
198
+ onKeyUp={disabled ? undefined : onKeyUp}
199
+ onPointerDown={(event) => {
200
+ if (disabled) {
201
+ event.preventDefault()
202
+ return
203
+ }
204
+ onPointerDown?.(event)
205
+ }}
206
+ {...props}
207
+ >
208
+ <span className="pointer-events-none absolute left-2 flex size-3.5 items-center justify-center">
209
+ <DropdownMenuPrimitive.ItemIndicator>
210
+ <CircleIcon className="size-2 fill-current" />
211
+ </DropdownMenuPrimitive.ItemIndicator>
212
+ </span>
213
+ {children}
214
+ </DropdownMenuPrimitive.RadioItem>
215
+ )
216
+ }
217
+
218
+ function DropdownMenuLabel({
219
+ className,
220
+ inset,
221
+ ...props
222
+ }: React.ComponentProps<typeof DropdownMenuPrimitive.Label> & {
223
+ inset?: boolean
224
+ }) {
225
+ return (
226
+ <DropdownMenuPrimitive.Label
227
+ data-slot="dropdown-menu-label"
228
+ data-inset={inset}
229
+ className={cn(
230
+ "px-2 py-1.5 text-sm font-medium data-[inset]:pl-8",
231
+ className
232
+ )}
233
+ {...props}
234
+ />
235
+ )
236
+ }
237
+
238
+ function DropdownMenuSeparator({
239
+ className,
240
+ ...props
241
+ }: React.ComponentProps<typeof DropdownMenuPrimitive.Separator>) {
242
+ return (
243
+ <DropdownMenuPrimitive.Separator
244
+ data-slot="dropdown-menu-separator"
245
+ className={cn("bg-border -mx-1 my-1 h-px", className)}
246
+ {...props}
247
+ />
248
+ )
249
+ }
250
+
251
+ function DropdownMenuShortcut({
252
+ className,
253
+ ...props
254
+ }: React.ComponentProps<"span">) {
255
+ return (
256
+ <span
257
+ data-slot="dropdown-menu-shortcut"
258
+ className={cn(
259
+ "text-muted-foreground ml-auto text-xs tracking-widest",
260
+ className
261
+ )}
262
+ {...props}
263
+ />
264
+ )
265
+ }
266
+
267
+ function DropdownMenuSub({
268
+ ...props
269
+ }: React.ComponentProps<typeof DropdownMenuPrimitive.Sub>) {
270
+ return <DropdownMenuPrimitive.Sub data-slot="dropdown-menu-sub" {...props} />
271
+ }
272
+
273
+ function DropdownMenuSubTrigger({
274
+ className,
275
+ inset,
276
+ children,
277
+ ...props
278
+ }: React.ComponentProps<typeof DropdownMenuPrimitive.SubTrigger> & {
279
+ inset?: boolean
280
+ }) {
281
+ return (
282
+ <DropdownMenuPrimitive.SubTrigger
283
+ data-slot="dropdown-menu-sub-trigger"
284
+ data-inset={inset}
285
+ className={cn(
286
+ "focus:bg-accent focus:text-accent-foreground data-[state=open]:bg-accent data-[state=open]:text-accent-foreground [&_svg:not([class*='text-'])]:text-muted-foreground flex cursor-default items-center gap-2 rounded-sm px-2 py-1.5 text-sm outline-hidden select-none data-[inset]:pl-8 [&_svg]:pointer-events-none [&_svg]:shrink-0 [&_svg:not([class*='size-'])]:size-4",
287
+ className
288
+ )}
289
+ {...props}
290
+ >
291
+ {children}
292
+ <ChevronRightIcon className="ml-auto size-4" />
293
+ </DropdownMenuPrimitive.SubTrigger>
294
+ )
295
+ }
296
+
297
+ function DropdownMenuSubContent({
298
+ className,
299
+ ...props
300
+ }: React.ComponentProps<typeof DropdownMenuPrimitive.SubContent>) {
301
+ return (
302
+ <DropdownMenuPrimitive.SubContent
303
+ data-slot="dropdown-menu-sub-content"
304
+ className={cn(
305
+ "bg-popover text-popover-foreground 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 z-50 min-w-[8rem] origin-(--radix-dropdown-menu-content-transform-origin) overflow-hidden rounded-md border p-1 shadow-lg",
306
+ className
307
+ )}
308
+ {...props}
309
+ />
310
+ )
311
+ }
312
+
313
+ export {
314
+ DropdownMenu,
315
+ DropdownMenuPortal,
316
+ DropdownMenuTrigger,
317
+ DropdownMenuContent,
318
+ DropdownMenuGroup,
319
+ DropdownMenuLabel,
320
+ DropdownMenuItem,
321
+ DropdownMenuCheckboxItem,
322
+ DropdownMenuRadioGroup,
323
+ DropdownMenuRadioItem,
324
+ DropdownMenuSeparator,
325
+ DropdownMenuShortcut,
326
+ DropdownMenuSub,
327
+ DropdownMenuSubTrigger,
328
+ DropdownMenuSubContent,
329
+ }
@@ -0,0 +1,104 @@
1
+ import { cva, type VariantProps } from "class-variance-authority"
2
+
3
+ import { cn } from "@/lib/utils"
4
+
5
+ function Empty({ className, ...props }: React.ComponentProps<"div">) {
6
+ return (
7
+ <div
8
+ data-slot="empty"
9
+ className={cn(
10
+ "flex min-w-0 flex-1 flex-col items-center justify-center gap-4 rounded-lg border-dashed p-6 text-center text-balance md:p-12",
11
+ className
12
+ )}
13
+ {...props}
14
+ />
15
+ )
16
+ }
17
+
18
+ function EmptyHeader({ className, ...props }: React.ComponentProps<"div">) {
19
+ return (
20
+ <div
21
+ data-slot="empty-header"
22
+ className={cn(
23
+ "flex max-w-sm flex-col items-center gap-1 text-center",
24
+ className
25
+ )}
26
+ {...props}
27
+ />
28
+ )
29
+ }
30
+
31
+ const emptyMediaVariants = cva(
32
+ "flex shrink-0 items-center justify-center mb-3 [&_svg]:pointer-events-none [&_svg]:shrink-0",
33
+ {
34
+ variants: {
35
+ variant: {
36
+ default: "bg-transparent",
37
+ icon: "bg-muted text-foreground flex size-10 shrink-0 items-center justify-center rounded-lg [&_svg:not([class*='size-'])]:size-6",
38
+ },
39
+ },
40
+ defaultVariants: {
41
+ variant: "default",
42
+ },
43
+ }
44
+ )
45
+
46
+ function EmptyMedia({
47
+ className,
48
+ variant = "default",
49
+ ...props
50
+ }: React.ComponentProps<"div"> & VariantProps<typeof emptyMediaVariants>) {
51
+ return (
52
+ <div
53
+ data-slot="empty-icon"
54
+ data-variant={variant}
55
+ className={cn(emptyMediaVariants({ variant, className }))}
56
+ {...props}
57
+ />
58
+ )
59
+ }
60
+
61
+ function EmptyTitle({ className, ...props }: React.ComponentProps<"div">) {
62
+ return (
63
+ <div
64
+ data-slot="empty-title"
65
+ className={cn("text-base font-medium tracking-tight", className)}
66
+ {...props}
67
+ />
68
+ )
69
+ }
70
+
71
+ function EmptyDescription({ className, ...props }: React.ComponentProps<"p">) {
72
+ return (
73
+ <div
74
+ data-slot="empty-description"
75
+ className={cn(
76
+ "text-muted-foreground [&>a:hover]:text-primary text-sm/relaxed [&>a]:underline [&>a]:underline-offset-4",
77
+ className
78
+ )}
79
+ {...props}
80
+ />
81
+ )
82
+ }
83
+
84
+ function EmptyContent({ className, ...props }: React.ComponentProps<"div">) {
85
+ return (
86
+ <div
87
+ data-slot="empty-content"
88
+ className={cn(
89
+ "flex w-full max-w-sm min-w-0 flex-col items-center gap-2 text-sm text-balance",
90
+ className
91
+ )}
92
+ {...props}
93
+ />
94
+ )
95
+ }
96
+
97
+ export {
98
+ Empty,
99
+ EmptyHeader,
100
+ EmptyTitle,
101
+ EmptyDescription,
102
+ EmptyContent,
103
+ EmptyMedia,
104
+ }