create-deesse-app 0.2.3 → 0.4.0

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 (103) hide show
  1. package/dist/src/copy.d.ts +1 -1
  2. package/dist/src/copy.d.ts.map +1 -1
  3. package/dist/src/copy.js +50 -71
  4. package/dist/src/copy.js.map +1 -1
  5. package/dist/src/index.js +3 -2
  6. package/dist/src/index.js.map +1 -1
  7. package/dist/tsconfig.tsbuildinfo +1 -1
  8. package/package.json +4 -5
  9. package/templates/default/.agents/skills/shadcn/SKILL.md +242 -0
  10. package/templates/default/.agents/skills/shadcn/agents/openai.yml +5 -0
  11. package/templates/default/.agents/skills/shadcn/assets/shadcn-small.png +0 -0
  12. package/templates/default/.agents/skills/shadcn/assets/shadcn.png +0 -0
  13. package/templates/default/.agents/skills/shadcn/cli.md +257 -0
  14. package/templates/default/.agents/skills/shadcn/customization.md +202 -0
  15. package/templates/default/.agents/skills/shadcn/evals/evals.json +47 -0
  16. package/templates/default/.agents/skills/shadcn/mcp.md +94 -0
  17. package/templates/default/.agents/skills/shadcn/rules/base-vs-radix.md +306 -0
  18. package/templates/default/.agents/skills/shadcn/rules/composition.md +195 -0
  19. package/templates/default/.agents/skills/shadcn/rules/forms.md +192 -0
  20. package/templates/default/.agents/skills/shadcn/rules/icons.md +101 -0
  21. package/templates/default/.agents/skills/shadcn/rules/styling.md +162 -0
  22. package/templates/default/AGENTS.md +5 -0
  23. package/templates/default/CLAUDE.md +1 -0
  24. package/templates/default/README.md +28 -0
  25. package/templates/default/components.json +25 -0
  26. package/templates/default/eslint.config.mjs +18 -0
  27. package/templates/default/next.config.ts +7 -0
  28. package/templates/default/package.json +50 -0
  29. package/templates/default/postcss.config.mjs +7 -0
  30. package/templates/default/public/file.svg +1 -0
  31. package/templates/default/public/globe.svg +1 -0
  32. package/templates/default/public/nesalia.svg +50 -0
  33. package/templates/default/public/window.svg +1 -0
  34. package/templates/default/skills-lock.json +10 -0
  35. package/templates/default/src/app/(deesse)/admin/[[...slug]]/page.tsx +20 -0
  36. package/templates/default/src/app/(deesse)/admin/layout.tsx +7 -0
  37. package/templates/default/src/app/(frontend)/page.tsx +50 -0
  38. package/templates/default/src/app/globals.css +130 -0
  39. package/templates/default/src/app/icon.svg +109 -0
  40. package/templates/default/src/app/layout.tsx +33 -0
  41. package/templates/default/src/app/page.tsx +50 -0
  42. package/templates/default/src/components/providers/index.tsx +9 -0
  43. package/templates/default/src/components/providers/theme-provider.tsx +11 -0
  44. package/templates/default/src/components/ui/accordion.tsx +81 -0
  45. package/templates/default/src/components/ui/alert-dialog.tsx +199 -0
  46. package/templates/default/src/components/ui/alert.tsx +76 -0
  47. package/templates/default/src/components/ui/aspect-ratio.tsx +11 -0
  48. package/templates/default/src/components/ui/avatar.tsx +112 -0
  49. package/templates/default/src/components/ui/badge.tsx +49 -0
  50. package/templates/default/src/components/ui/breadcrumb.tsx +122 -0
  51. package/templates/default/src/components/ui/button-group.tsx +83 -0
  52. package/templates/default/src/components/ui/button.tsx +67 -0
  53. package/templates/default/src/components/ui/calendar.tsx +222 -0
  54. package/templates/default/src/components/ui/card.tsx +103 -0
  55. package/templates/default/src/components/ui/carousel.tsx +242 -0
  56. package/templates/default/src/components/ui/chart.tsx +373 -0
  57. package/templates/default/src/components/ui/checkbox.tsx +33 -0
  58. package/templates/default/src/components/ui/collapsible.tsx +33 -0
  59. package/templates/default/src/components/ui/combobox.tsx +299 -0
  60. package/templates/default/src/components/ui/command.tsx +195 -0
  61. package/templates/default/src/components/ui/context-menu.tsx +263 -0
  62. package/templates/default/src/components/ui/dialog.tsx +168 -0
  63. package/templates/default/src/components/ui/direction.tsx +22 -0
  64. package/templates/default/src/components/ui/drawer.tsx +134 -0
  65. package/templates/default/src/components/ui/dropdown-menu.tsx +269 -0
  66. package/templates/default/src/components/ui/empty.tsx +104 -0
  67. package/templates/default/src/components/ui/field.tsx +238 -0
  68. package/templates/default/src/components/ui/hover-card.tsx +44 -0
  69. package/templates/default/src/components/ui/input-group.tsx +156 -0
  70. package/templates/default/src/components/ui/input-otp.tsx +87 -0
  71. package/templates/default/src/components/ui/input.tsx +19 -0
  72. package/templates/default/src/components/ui/item.tsx +196 -0
  73. package/templates/default/src/components/ui/kbd.tsx +26 -0
  74. package/templates/default/src/components/ui/label.tsx +24 -0
  75. package/templates/default/src/components/ui/menubar.tsx +280 -0
  76. package/templates/default/src/components/ui/native-select.tsx +52 -0
  77. package/templates/default/src/components/ui/navigation-menu.tsx +164 -0
  78. package/templates/default/src/components/ui/pagination.tsx +129 -0
  79. package/templates/default/src/components/ui/popover.tsx +89 -0
  80. package/templates/default/src/components/ui/progress.tsx +31 -0
  81. package/templates/default/src/components/ui/radio-group.tsx +44 -0
  82. package/templates/default/src/components/ui/resizable.tsx +50 -0
  83. package/templates/default/src/components/ui/scroll-area.tsx +55 -0
  84. package/templates/default/src/components/ui/select.tsx +192 -0
  85. package/templates/default/src/components/ui/separator.tsx +28 -0
  86. package/templates/default/src/components/ui/sheet.tsx +147 -0
  87. package/templates/default/src/components/ui/sidebar.tsx +702 -0
  88. package/templates/default/src/components/ui/skeleton.tsx +13 -0
  89. package/templates/default/src/components/ui/slider.tsx +59 -0
  90. package/templates/default/src/components/ui/sonner.tsx +49 -0
  91. package/templates/default/src/components/ui/spinner.tsx +10 -0
  92. package/templates/default/src/components/ui/switch.tsx +33 -0
  93. package/templates/default/src/components/ui/table.tsx +116 -0
  94. package/templates/default/src/components/ui/tabs.tsx +90 -0
  95. package/templates/default/src/components/ui/textarea.tsx +18 -0
  96. package/templates/default/src/components/ui/toggle-group.tsx +89 -0
  97. package/templates/default/src/components/ui/toggle.tsx +46 -0
  98. package/templates/default/src/components/ui/tooltip.tsx +57 -0
  99. package/templates/default/src/deesse.config.ts +11 -0
  100. package/templates/default/src/hooks/use-mobile.ts +19 -0
  101. package/templates/default/src/lib/utils.ts +6 -0
  102. package/templates/default/tsconfig.json +35 -0
  103. package/templates/minimal/.gitkeep +0 -0
@@ -0,0 +1,269 @@
1
+ "use client"
2
+
3
+ import * as React from "react"
4
+ import { DropdownMenu as DropdownMenuPrimitive } from "radix-ui"
5
+
6
+ import { cn } from "@/lib/utils"
7
+ import { CheckIcon, ChevronRightIcon } from "lucide-react"
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
+ align = "start",
37
+ sideOffset = 4,
38
+ ...props
39
+ }: React.ComponentProps<typeof DropdownMenuPrimitive.Content>) {
40
+ return (
41
+ <DropdownMenuPrimitive.Portal>
42
+ <DropdownMenuPrimitive.Content
43
+ data-slot="dropdown-menu-content"
44
+ sideOffset={sideOffset}
45
+ align={align}
46
+ className={cn("z-50 max-h-(--radix-dropdown-menu-content-available-height) w-(--radix-dropdown-menu-trigger-width) min-w-32 origin-(--radix-dropdown-menu-content-transform-origin) overflow-x-hidden overflow-y-auto rounded-lg bg-popover p-1 text-popover-foreground shadow-md ring-1 ring-foreground/10 duration-100 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]:overflow-hidden data-open:animate-in data-open:fade-in-0 data-open:zoom-in-95 data-closed:animate-out data-closed:fade-out-0 data-closed:zoom-out-95", className )}
47
+ {...props}
48
+ />
49
+ </DropdownMenuPrimitive.Portal>
50
+ )
51
+ }
52
+
53
+ function DropdownMenuGroup({
54
+ ...props
55
+ }: React.ComponentProps<typeof DropdownMenuPrimitive.Group>) {
56
+ return (
57
+ <DropdownMenuPrimitive.Group data-slot="dropdown-menu-group" {...props} />
58
+ )
59
+ }
60
+
61
+ function DropdownMenuItem({
62
+ className,
63
+ inset,
64
+ variant = "default",
65
+ ...props
66
+ }: React.ComponentProps<typeof DropdownMenuPrimitive.Item> & {
67
+ inset?: boolean
68
+ variant?: "default" | "destructive"
69
+ }) {
70
+ return (
71
+ <DropdownMenuPrimitive.Item
72
+ data-slot="dropdown-menu-item"
73
+ data-inset={inset}
74
+ data-variant={variant}
75
+ className={cn(
76
+ "group/dropdown-menu-item relative flex cursor-default items-center gap-1.5 rounded-md px-1.5 py-1 text-sm outline-hidden select-none focus:bg-accent focus:text-accent-foreground not-data-[variant=destructive]:focus:**:text-accent-foreground data-inset:pl-7 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 data-disabled:pointer-events-none data-disabled:opacity-50 [&_svg]:pointer-events-none [&_svg]:shrink-0 [&_svg:not([class*='size-'])]:size-4 data-[variant=destructive]:*:[svg]:text-destructive",
77
+ className
78
+ )}
79
+ {...props}
80
+ />
81
+ )
82
+ }
83
+
84
+ function DropdownMenuCheckboxItem({
85
+ className,
86
+ children,
87
+ checked,
88
+ inset,
89
+ ...props
90
+ }: React.ComponentProps<typeof DropdownMenuPrimitive.CheckboxItem> & {
91
+ inset?: boolean
92
+ }) {
93
+ return (
94
+ <DropdownMenuPrimitive.CheckboxItem
95
+ data-slot="dropdown-menu-checkbox-item"
96
+ data-inset={inset}
97
+ className={cn(
98
+ "relative flex cursor-default items-center gap-1.5 rounded-md py-1 pr-8 pl-1.5 text-sm outline-hidden select-none focus:bg-accent focus:text-accent-foreground focus:**:text-accent-foreground data-inset:pl-7 data-disabled:pointer-events-none data-disabled:opacity-50 [&_svg]:pointer-events-none [&_svg]:shrink-0 [&_svg:not([class*='size-'])]:size-4",
99
+ className
100
+ )}
101
+ checked={checked}
102
+ {...props}
103
+ >
104
+ <span
105
+ className="pointer-events-none absolute right-2 flex items-center justify-center"
106
+ data-slot="dropdown-menu-checkbox-item-indicator"
107
+ >
108
+ <DropdownMenuPrimitive.ItemIndicator>
109
+ <CheckIcon
110
+ />
111
+ </DropdownMenuPrimitive.ItemIndicator>
112
+ </span>
113
+ {children}
114
+ </DropdownMenuPrimitive.CheckboxItem>
115
+ )
116
+ }
117
+
118
+ function DropdownMenuRadioGroup({
119
+ ...props
120
+ }: React.ComponentProps<typeof DropdownMenuPrimitive.RadioGroup>) {
121
+ return (
122
+ <DropdownMenuPrimitive.RadioGroup
123
+ data-slot="dropdown-menu-radio-group"
124
+ {...props}
125
+ />
126
+ )
127
+ }
128
+
129
+ function DropdownMenuRadioItem({
130
+ className,
131
+ children,
132
+ inset,
133
+ ...props
134
+ }: React.ComponentProps<typeof DropdownMenuPrimitive.RadioItem> & {
135
+ inset?: boolean
136
+ }) {
137
+ return (
138
+ <DropdownMenuPrimitive.RadioItem
139
+ data-slot="dropdown-menu-radio-item"
140
+ data-inset={inset}
141
+ className={cn(
142
+ "relative flex cursor-default items-center gap-1.5 rounded-md py-1 pr-8 pl-1.5 text-sm outline-hidden select-none focus:bg-accent focus:text-accent-foreground focus:**:text-accent-foreground data-inset:pl-7 data-disabled:pointer-events-none data-disabled:opacity-50 [&_svg]:pointer-events-none [&_svg]:shrink-0 [&_svg:not([class*='size-'])]:size-4",
143
+ className
144
+ )}
145
+ {...props}
146
+ >
147
+ <span
148
+ className="pointer-events-none absolute right-2 flex items-center justify-center"
149
+ data-slot="dropdown-menu-radio-item-indicator"
150
+ >
151
+ <DropdownMenuPrimitive.ItemIndicator>
152
+ <CheckIcon
153
+ />
154
+ </DropdownMenuPrimitive.ItemIndicator>
155
+ </span>
156
+ {children}
157
+ </DropdownMenuPrimitive.RadioItem>
158
+ )
159
+ }
160
+
161
+ function DropdownMenuLabel({
162
+ className,
163
+ inset,
164
+ ...props
165
+ }: React.ComponentProps<typeof DropdownMenuPrimitive.Label> & {
166
+ inset?: boolean
167
+ }) {
168
+ return (
169
+ <DropdownMenuPrimitive.Label
170
+ data-slot="dropdown-menu-label"
171
+ data-inset={inset}
172
+ className={cn(
173
+ "px-1.5 py-1 text-xs font-medium text-muted-foreground data-inset:pl-7",
174
+ className
175
+ )}
176
+ {...props}
177
+ />
178
+ )
179
+ }
180
+
181
+ function DropdownMenuSeparator({
182
+ className,
183
+ ...props
184
+ }: React.ComponentProps<typeof DropdownMenuPrimitive.Separator>) {
185
+ return (
186
+ <DropdownMenuPrimitive.Separator
187
+ data-slot="dropdown-menu-separator"
188
+ className={cn("-mx-1 my-1 h-px bg-border", className)}
189
+ {...props}
190
+ />
191
+ )
192
+ }
193
+
194
+ function DropdownMenuShortcut({
195
+ className,
196
+ ...props
197
+ }: React.ComponentProps<"span">) {
198
+ return (
199
+ <span
200
+ data-slot="dropdown-menu-shortcut"
201
+ className={cn(
202
+ "ml-auto text-xs tracking-widest text-muted-foreground group-focus/dropdown-menu-item:text-accent-foreground",
203
+ className
204
+ )}
205
+ {...props}
206
+ />
207
+ )
208
+ }
209
+
210
+ function DropdownMenuSub({
211
+ ...props
212
+ }: React.ComponentProps<typeof DropdownMenuPrimitive.Sub>) {
213
+ return <DropdownMenuPrimitive.Sub data-slot="dropdown-menu-sub" {...props} />
214
+ }
215
+
216
+ function DropdownMenuSubTrigger({
217
+ className,
218
+ inset,
219
+ children,
220
+ ...props
221
+ }: React.ComponentProps<typeof DropdownMenuPrimitive.SubTrigger> & {
222
+ inset?: boolean
223
+ }) {
224
+ return (
225
+ <DropdownMenuPrimitive.SubTrigger
226
+ data-slot="dropdown-menu-sub-trigger"
227
+ data-inset={inset}
228
+ className={cn(
229
+ "flex cursor-default items-center gap-1.5 rounded-md px-1.5 py-1 text-sm outline-hidden select-none focus:bg-accent focus:text-accent-foreground not-data-[variant=destructive]:focus:**:text-accent-foreground data-inset:pl-7 data-open:bg-accent data-open:text-accent-foreground [&_svg]:pointer-events-none [&_svg]:shrink-0 [&_svg:not([class*='size-'])]:size-4",
230
+ className
231
+ )}
232
+ {...props}
233
+ >
234
+ {children}
235
+ <ChevronRightIcon className="ml-auto" />
236
+ </DropdownMenuPrimitive.SubTrigger>
237
+ )
238
+ }
239
+
240
+ function DropdownMenuSubContent({
241
+ className,
242
+ ...props
243
+ }: React.ComponentProps<typeof DropdownMenuPrimitive.SubContent>) {
244
+ return (
245
+ <DropdownMenuPrimitive.SubContent
246
+ data-slot="dropdown-menu-sub-content"
247
+ className={cn("z-50 min-w-[96px] origin-(--radix-dropdown-menu-content-transform-origin) overflow-hidden rounded-lg bg-popover p-1 text-popover-foreground shadow-lg ring-1 ring-foreground/10 duration-100 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-open:animate-in data-open:fade-in-0 data-open:zoom-in-95 data-closed:animate-out data-closed:fade-out-0 data-closed:zoom-out-95", className )}
248
+ {...props}
249
+ />
250
+ )
251
+ }
252
+
253
+ export {
254
+ DropdownMenu,
255
+ DropdownMenuPortal,
256
+ DropdownMenuTrigger,
257
+ DropdownMenuContent,
258
+ DropdownMenuGroup,
259
+ DropdownMenuLabel,
260
+ DropdownMenuItem,
261
+ DropdownMenuCheckboxItem,
262
+ DropdownMenuRadioGroup,
263
+ DropdownMenuRadioItem,
264
+ DropdownMenuSeparator,
265
+ DropdownMenuShortcut,
266
+ DropdownMenuSub,
267
+ DropdownMenuSubTrigger,
268
+ DropdownMenuSubContent,
269
+ }
@@ -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 w-full min-w-0 flex-1 flex-col items-center justify-center gap-4 rounded-xl border-dashed p-6 text-center text-balance",
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("flex max-w-sm flex-col items-center gap-2", className)}
23
+ {...props}
24
+ />
25
+ )
26
+ }
27
+
28
+ const emptyMediaVariants = cva(
29
+ "mb-2 flex shrink-0 items-center justify-center [&_svg]:pointer-events-none [&_svg]:shrink-0",
30
+ {
31
+ variants: {
32
+ variant: {
33
+ default: "bg-transparent",
34
+ icon: "flex size-8 shrink-0 items-center justify-center rounded-lg bg-muted text-foreground [&_svg:not([class*='size-'])]:size-4",
35
+ },
36
+ },
37
+ defaultVariants: {
38
+ variant: "default",
39
+ },
40
+ }
41
+ )
42
+
43
+ function EmptyMedia({
44
+ className,
45
+ variant = "default",
46
+ ...props
47
+ }: React.ComponentProps<"div"> & VariantProps<typeof emptyMediaVariants>) {
48
+ return (
49
+ <div
50
+ data-slot="empty-icon"
51
+ data-variant={variant}
52
+ className={cn(emptyMediaVariants({ variant, className }))}
53
+ {...props}
54
+ />
55
+ )
56
+ }
57
+
58
+ function EmptyTitle({ className, ...props }: React.ComponentProps<"div">) {
59
+ return (
60
+ <div
61
+ data-slot="empty-title"
62
+ className={cn(
63
+ "font-heading text-sm font-medium tracking-tight",
64
+ className
65
+ )}
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-sm/relaxed text-muted-foreground [&>a]:underline [&>a]:underline-offset-4 [&>a:hover]:text-primary",
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.5 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
+ }
@@ -0,0 +1,238 @@
1
+ "use client"
2
+
3
+ import { useMemo } from "react"
4
+ import { cva, type VariantProps } from "class-variance-authority"
5
+
6
+ import { cn } from "@/lib/utils"
7
+ import { Label } from "@/components/ui/label"
8
+ import { Separator } from "@/components/ui/separator"
9
+
10
+ function FieldSet({ className, ...props }: React.ComponentProps<"fieldset">) {
11
+ return (
12
+ <fieldset
13
+ data-slot="field-set"
14
+ className={cn(
15
+ "flex flex-col gap-4 has-[>[data-slot=checkbox-group]]:gap-3 has-[>[data-slot=radio-group]]:gap-3",
16
+ className
17
+ )}
18
+ {...props}
19
+ />
20
+ )
21
+ }
22
+
23
+ function FieldLegend({
24
+ className,
25
+ variant = "legend",
26
+ ...props
27
+ }: React.ComponentProps<"legend"> & { variant?: "legend" | "label" }) {
28
+ return (
29
+ <legend
30
+ data-slot="field-legend"
31
+ data-variant={variant}
32
+ className={cn(
33
+ "mb-1.5 font-medium data-[variant=label]:text-sm data-[variant=legend]:text-base",
34
+ className
35
+ )}
36
+ {...props}
37
+ />
38
+ )
39
+ }
40
+
41
+ function FieldGroup({ className, ...props }: React.ComponentProps<"div">) {
42
+ return (
43
+ <div
44
+ data-slot="field-group"
45
+ className={cn(
46
+ "group/field-group @container/field-group flex w-full flex-col gap-5 data-[slot=checkbox-group]:gap-3 *:data-[slot=field-group]:gap-4",
47
+ className
48
+ )}
49
+ {...props}
50
+ />
51
+ )
52
+ }
53
+
54
+ const fieldVariants = cva(
55
+ "group/field flex w-full gap-2 data-[invalid=true]:text-destructive",
56
+ {
57
+ variants: {
58
+ orientation: {
59
+ vertical: "flex-col *:w-full [&>.sr-only]:w-auto",
60
+ horizontal:
61
+ "flex-row items-center has-[>[data-slot=field-content]]:items-start *:data-[slot=field-label]:flex-auto has-[>[data-slot=field-content]]:[&>[role=checkbox],[role=radio]]:mt-px",
62
+ responsive:
63
+ "flex-col *:w-full @md/field-group:flex-row @md/field-group:items-center @md/field-group:*:w-auto @md/field-group:has-[>[data-slot=field-content]]:items-start @md/field-group:*:data-[slot=field-label]:flex-auto [&>.sr-only]:w-auto @md/field-group:has-[>[data-slot=field-content]]:[&>[role=checkbox],[role=radio]]:mt-px",
64
+ },
65
+ },
66
+ defaultVariants: {
67
+ orientation: "vertical",
68
+ },
69
+ }
70
+ )
71
+
72
+ function Field({
73
+ className,
74
+ orientation = "vertical",
75
+ ...props
76
+ }: React.ComponentProps<"div"> & VariantProps<typeof fieldVariants>) {
77
+ return (
78
+ <div
79
+ role="group"
80
+ data-slot="field"
81
+ data-orientation={orientation}
82
+ className={cn(fieldVariants({ orientation }), className)}
83
+ {...props}
84
+ />
85
+ )
86
+ }
87
+
88
+ function FieldContent({ className, ...props }: React.ComponentProps<"div">) {
89
+ return (
90
+ <div
91
+ data-slot="field-content"
92
+ className={cn(
93
+ "group/field-content flex flex-1 flex-col gap-0.5 leading-snug",
94
+ className
95
+ )}
96
+ {...props}
97
+ />
98
+ )
99
+ }
100
+
101
+ function FieldLabel({
102
+ className,
103
+ ...props
104
+ }: React.ComponentProps<typeof Label>) {
105
+ return (
106
+ <Label
107
+ data-slot="field-label"
108
+ className={cn(
109
+ "group/field-label peer/field-label flex w-fit gap-2 leading-snug group-data-[disabled=true]/field:opacity-50 has-data-checked:border-primary/30 has-data-checked:bg-primary/5 has-[>[data-slot=field]]:rounded-lg has-[>[data-slot=field]]:border *:data-[slot=field]:p-2.5 dark:has-data-checked:border-primary/20 dark:has-data-checked:bg-primary/10",
110
+ "has-[>[data-slot=field]]:w-full has-[>[data-slot=field]]:flex-col",
111
+ className
112
+ )}
113
+ {...props}
114
+ />
115
+ )
116
+ }
117
+
118
+ function FieldTitle({ className, ...props }: React.ComponentProps<"div">) {
119
+ return (
120
+ <div
121
+ data-slot="field-label"
122
+ className={cn(
123
+ "flex w-fit items-center gap-2 text-sm leading-snug font-medium group-data-[disabled=true]/field:opacity-50",
124
+ className
125
+ )}
126
+ {...props}
127
+ />
128
+ )
129
+ }
130
+
131
+ function FieldDescription({ className, ...props }: React.ComponentProps<"p">) {
132
+ return (
133
+ <p
134
+ data-slot="field-description"
135
+ className={cn(
136
+ "text-left text-sm leading-normal font-normal text-muted-foreground group-has-data-horizontal/field:text-balance [[data-variant=legend]+&]:-mt-1.5",
137
+ "last:mt-0 nth-last-2:-mt-1",
138
+ "[&>a]:underline [&>a]:underline-offset-4 [&>a:hover]:text-primary",
139
+ className
140
+ )}
141
+ {...props}
142
+ />
143
+ )
144
+ }
145
+
146
+ function FieldSeparator({
147
+ children,
148
+ className,
149
+ ...props
150
+ }: React.ComponentProps<"div"> & {
151
+ children?: React.ReactNode
152
+ }) {
153
+ return (
154
+ <div
155
+ data-slot="field-separator"
156
+ data-content={!!children}
157
+ className={cn(
158
+ "relative -my-2 h-5 text-sm group-data-[variant=outline]/field-group:-mb-2",
159
+ className
160
+ )}
161
+ {...props}
162
+ >
163
+ <Separator className="absolute inset-0 top-1/2" />
164
+ {children && (
165
+ <span
166
+ className="relative mx-auto block w-fit bg-background px-2 text-muted-foreground"
167
+ data-slot="field-separator-content"
168
+ >
169
+ {children}
170
+ </span>
171
+ )}
172
+ </div>
173
+ )
174
+ }
175
+
176
+ function FieldError({
177
+ className,
178
+ children,
179
+ errors,
180
+ ...props
181
+ }: React.ComponentProps<"div"> & {
182
+ errors?: Array<{ message?: string } | undefined>
183
+ }) {
184
+ const content = useMemo(() => {
185
+ if (children) {
186
+ return children
187
+ }
188
+
189
+ if (!errors?.length) {
190
+ return null
191
+ }
192
+
193
+ const uniqueErrors = [
194
+ ...new Map(errors.map((error) => [error?.message, error])).values(),
195
+ ]
196
+
197
+ if (uniqueErrors?.length == 1) {
198
+ return uniqueErrors[0]?.message
199
+ }
200
+
201
+ return (
202
+ <ul className="ml-4 flex list-disc flex-col gap-1">
203
+ {uniqueErrors.map(
204
+ (error, index) =>
205
+ error?.message && <li key={index}>{error.message}</li>
206
+ )}
207
+ </ul>
208
+ )
209
+ }, [children, errors])
210
+
211
+ if (!content) {
212
+ return null
213
+ }
214
+
215
+ return (
216
+ <div
217
+ role="alert"
218
+ data-slot="field-error"
219
+ className={cn("text-sm font-normal text-destructive", className)}
220
+ {...props}
221
+ >
222
+ {content}
223
+ </div>
224
+ )
225
+ }
226
+
227
+ export {
228
+ Field,
229
+ FieldLabel,
230
+ FieldDescription,
231
+ FieldError,
232
+ FieldGroup,
233
+ FieldLegend,
234
+ FieldSeparator,
235
+ FieldSet,
236
+ FieldContent,
237
+ FieldTitle,
238
+ }
@@ -0,0 +1,44 @@
1
+ "use client"
2
+
3
+ import * as React from "react"
4
+ import { HoverCard as HoverCardPrimitive } from "radix-ui"
5
+
6
+ import { cn } from "@/lib/utils"
7
+
8
+ function HoverCard({
9
+ ...props
10
+ }: React.ComponentProps<typeof HoverCardPrimitive.Root>) {
11
+ return <HoverCardPrimitive.Root data-slot="hover-card" {...props} />
12
+ }
13
+
14
+ function HoverCardTrigger({
15
+ ...props
16
+ }: React.ComponentProps<typeof HoverCardPrimitive.Trigger>) {
17
+ return (
18
+ <HoverCardPrimitive.Trigger data-slot="hover-card-trigger" {...props} />
19
+ )
20
+ }
21
+
22
+ function HoverCardContent({
23
+ className,
24
+ align = "center",
25
+ sideOffset = 4,
26
+ ...props
27
+ }: React.ComponentProps<typeof HoverCardPrimitive.Content>) {
28
+ return (
29
+ <HoverCardPrimitive.Portal data-slot="hover-card-portal">
30
+ <HoverCardPrimitive.Content
31
+ data-slot="hover-card-content"
32
+ align={align}
33
+ sideOffset={sideOffset}
34
+ className={cn(
35
+ "z-50 w-64 origin-(--radix-hover-card-content-transform-origin) rounded-lg bg-popover p-2.5 text-sm text-popover-foreground shadow-md ring-1 ring-foreground/10 outline-hidden duration-100 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-open:animate-in data-open:fade-in-0 data-open:zoom-in-95 data-closed:animate-out data-closed:fade-out-0 data-closed:zoom-out-95",
36
+ className
37
+ )}
38
+ {...props}
39
+ />
40
+ </HoverCardPrimitive.Portal>
41
+ )
42
+ }
43
+
44
+ export { HoverCard, HoverCardTrigger, HoverCardContent }