create-ec-app 1.8.0 → 1.9.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/README.md +72 -17
  2. package/dist/cssScope.js +3 -5
  3. package/dist/cssScope.js.map +1 -1
  4. package/dist/index.d.ts +46 -1
  5. package/dist/index.d.ts.map +1 -1
  6. package/dist/index.js +129 -53
  7. package/dist/index.js.map +1 -1
  8. package/dist/libFunctions.d.ts +13 -6
  9. package/dist/libFunctions.d.ts.map +1 -1
  10. package/dist/libFunctions.js +24 -9
  11. package/dist/libFunctions.js.map +1 -1
  12. package/dist/pcf.d.ts.map +1 -1
  13. package/dist/pcf.js +4 -1
  14. package/dist/pcf.js.map +1 -1
  15. package/dist/portalContainers.js +7 -5
  16. package/dist/portalContainers.js.map +1 -1
  17. package/package.json +18 -11
  18. package/scripts/build-generated.mjs +59 -0
  19. package/scripts/refresh-shadcn-template.ts +406 -0
  20. package/scripts/smoke-scaffold.mjs +245 -0
  21. package/templates/base/eslint.config.js +1 -1
  22. package/templates/base/package-lock.json +380 -476
  23. package/templates/base/package.json +14 -19
  24. package/templates/pcf/base/package-lock.json +35 -53
  25. package/templates/targets/code-apps/AGENTS.md +1 -1
  26. package/templates/targets/code-apps/CLAUDE.md +1 -0
  27. package/templates/targets/code-apps/package.patch.json +1 -1
  28. package/templates/targets/power-pages/AGENTS.md +1 -1
  29. package/templates/targets/power-pages/CLAUDE.md +1 -0
  30. package/templates/targets/power-pages/README.md +22 -2
  31. package/templates/targets/power-pages/src/App.patch.tsx +3 -1
  32. package/templates/targets/power-pages/src/components/shared/AuthError.tsx +18 -0
  33. package/templates/targets/power-pages/src/context/AuthContext.tsx +0 -4
  34. package/templates/targets/swa/CLAUDE.md +1 -0
  35. package/templates/targets/webresource/AGENTS.md +5 -4
  36. package/templates/targets/webresource/CLAUDE.md +1 -0
  37. package/templates/targets/webresource/README.md +5 -5
  38. package/templates/ui/kendo/package.patch.json +2 -2
  39. package/templates/ui/shadcn-ui/SHADCN_TEMPLATE.md +20 -0
  40. package/templates/ui/shadcn-ui/package.patch.json +18 -9
  41. package/templates/ui/shadcn-ui/src/components/ui/accordion.tsx +79 -0
  42. package/templates/ui/shadcn-ui/src/components/ui/alert-dialog.tsx +199 -0
  43. package/templates/ui/shadcn-ui/src/components/ui/alert.tsx +76 -0
  44. package/templates/ui/shadcn-ui/src/components/ui/aspect-ratio.tsx +11 -0
  45. package/templates/ui/shadcn-ui/src/components/ui/attachment.tsx +206 -0
  46. package/templates/ui/shadcn-ui/src/components/ui/avatar.tsx +110 -0
  47. package/templates/ui/shadcn-ui/src/components/ui/badge.tsx +49 -0
  48. package/templates/ui/shadcn-ui/src/components/ui/breadcrumb.tsx +122 -0
  49. package/templates/ui/shadcn-ui/src/components/ui/bubble.tsx +125 -0
  50. package/templates/ui/shadcn-ui/src/components/ui/button-group.tsx +83 -0
  51. package/templates/ui/shadcn-ui/src/components/ui/button.tsx +67 -0
  52. package/templates/ui/shadcn-ui/src/components/ui/calendar.tsx +222 -0
  53. package/templates/ui/shadcn-ui/src/components/ui/card.tsx +103 -0
  54. package/templates/ui/shadcn-ui/src/components/ui/carousel.tsx +240 -0
  55. package/templates/ui/shadcn-ui/src/components/ui/chart.tsx +373 -0
  56. package/templates/ui/shadcn-ui/src/components/ui/checkbox.tsx +31 -0
  57. package/templates/ui/shadcn-ui/src/components/ui/collapsible.tsx +33 -0
  58. package/templates/ui/shadcn-ui/src/components/ui/combobox.tsx +299 -0
  59. package/templates/ui/shadcn-ui/src/components/ui/command.tsx +195 -0
  60. package/templates/ui/shadcn-ui/src/components/ui/context-menu.tsx +264 -0
  61. package/templates/ui/shadcn-ui/src/components/ui/dialog.tsx +170 -0
  62. package/templates/ui/shadcn-ui/src/components/ui/direction.tsx +22 -0
  63. package/templates/ui/shadcn-ui/src/components/ui/drawer.tsx +134 -0
  64. package/templates/ui/shadcn-ui/src/components/ui/dropdown-menu.tsx +272 -0
  65. package/templates/ui/shadcn-ui/src/components/ui/empty.tsx +104 -0
  66. package/templates/ui/shadcn-ui/src/components/ui/field.tsx +236 -0
  67. package/templates/ui/shadcn-ui/src/components/ui/hover-card.tsx +44 -0
  68. package/templates/ui/shadcn-ui/src/components/ui/input-group.tsx +156 -0
  69. package/templates/ui/shadcn-ui/src/components/ui/input-otp.tsx +87 -0
  70. package/templates/ui/shadcn-ui/src/components/ui/input.tsx +19 -0
  71. package/templates/ui/shadcn-ui/src/components/ui/item.tsx +196 -0
  72. package/templates/ui/shadcn-ui/src/components/ui/kbd.tsx +26 -0
  73. package/templates/ui/shadcn-ui/src/components/ui/label.tsx +22 -0
  74. package/templates/ui/shadcn-ui/src/components/ui/marker.tsx +69 -0
  75. package/templates/ui/shadcn-ui/src/components/ui/menubar.tsx +282 -0
  76. package/templates/ui/shadcn-ui/src/components/ui/message-scroller.tsx +129 -0
  77. package/templates/ui/shadcn-ui/src/components/ui/message.tsx +92 -0
  78. package/templates/ui/shadcn-ui/src/components/ui/native-select.tsx +61 -0
  79. package/templates/ui/shadcn-ui/src/components/ui/navigation-menu.tsx +164 -0
  80. package/templates/ui/shadcn-ui/src/components/ui/pagination.tsx +129 -0
  81. package/templates/ui/shadcn-ui/src/components/ui/popover.tsx +89 -0
  82. package/templates/ui/shadcn-ui/src/components/ui/progress.tsx +31 -0
  83. package/templates/ui/shadcn-ui/src/components/ui/radio-group.tsx +42 -0
  84. package/templates/ui/shadcn-ui/src/components/ui/resizable.tsx +50 -0
  85. package/templates/ui/shadcn-ui/src/components/ui/scroll-area.tsx +53 -0
  86. package/templates/ui/shadcn-ui/src/components/ui/select.tsx +194 -0
  87. package/templates/ui/shadcn-ui/src/components/ui/separator.tsx +26 -0
  88. package/templates/ui/shadcn-ui/src/components/ui/sheet.tsx +149 -0
  89. package/templates/ui/shadcn-ui/src/components/ui/sidebar.tsx +702 -0
  90. package/templates/ui/shadcn-ui/src/components/ui/skeleton.tsx +13 -0
  91. package/templates/ui/shadcn-ui/src/components/ui/slider.tsx +59 -0
  92. package/templates/ui/shadcn-ui/src/components/ui/sonner.tsx +47 -0
  93. package/templates/ui/shadcn-ui/src/components/ui/spinner.tsx +10 -0
  94. package/templates/ui/shadcn-ui/src/components/ui/switch.tsx +33 -0
  95. package/templates/ui/shadcn-ui/src/components/ui/table.tsx +114 -0
  96. package/templates/ui/shadcn-ui/src/components/ui/tabs.tsx +90 -0
  97. package/templates/ui/shadcn-ui/src/components/ui/textarea.tsx +18 -0
  98. package/templates/ui/shadcn-ui/src/components/ui/toggle-group.tsx +87 -0
  99. package/templates/ui/shadcn-ui/src/components/ui/toggle.tsx +45 -0
  100. package/templates/ui/shadcn-ui/src/components/ui/tooltip.tsx +59 -0
  101. package/templates/ui/shadcn-ui/src/index.patch.css +0 -118
  102. package/templates/ui/shadcn-ui/src/runtime/PortalContainer.ts +8 -0
  103. package/templates/base/biome.json +0 -54
@@ -0,0 +1,199 @@
1
+ import * as React from "react"
2
+ import { AlertDialog as AlertDialogPrimitive } from "radix-ui"
3
+
4
+ import { cn } from "@/lib/utils"
5
+ import { Button } from "@/components/ui/button"
6
+ import { usePortalContainer } from "@/runtime/PortalContainer"
7
+
8
+ function AlertDialog({
9
+ ...props
10
+ }: React.ComponentProps<typeof AlertDialogPrimitive.Root>) {
11
+ return <AlertDialogPrimitive.Root data-slot="alert-dialog" {...props} />
12
+ }
13
+
14
+ function AlertDialogTrigger({
15
+ ...props
16
+ }: React.ComponentProps<typeof AlertDialogPrimitive.Trigger>) {
17
+ return (
18
+ <AlertDialogPrimitive.Trigger data-slot="alert-dialog-trigger" {...props} />
19
+ )
20
+ }
21
+
22
+ function AlertDialogPortal({
23
+ ...props
24
+ }: React.ComponentProps<typeof AlertDialogPrimitive.Portal>) {
25
+ const portalContainer = usePortalContainer()
26
+ return (
27
+ <AlertDialogPrimitive.Portal container={portalContainer ?? undefined} data-slot="alert-dialog-portal" {...props} />
28
+ )
29
+ }
30
+
31
+ function AlertDialogOverlay({
32
+ className,
33
+ ...props
34
+ }: React.ComponentProps<typeof AlertDialogPrimitive.Overlay>) {
35
+ return (
36
+ <AlertDialogPrimitive.Overlay
37
+ data-slot="alert-dialog-overlay"
38
+ className={cn(
39
+ "fixed inset-0 z-50 bg-black/10 duration-100 supports-backdrop-filter:backdrop-blur-xs data-open:animate-in data-open:fade-in-0 data-closed:animate-out data-closed:fade-out-0",
40
+ className
41
+ )}
42
+ {...props}
43
+ />
44
+ )
45
+ }
46
+
47
+ function AlertDialogContent({
48
+ className,
49
+ size = "default",
50
+ ...props
51
+ }: React.ComponentProps<typeof AlertDialogPrimitive.Content> & {
52
+ size?: "default" | "sm"
53
+ }) {
54
+ return (
55
+ <AlertDialogPortal>
56
+ <AlertDialogOverlay />
57
+ <AlertDialogPrimitive.Content
58
+ data-slot="alert-dialog-content"
59
+ data-size={size}
60
+ className={cn(
61
+ "group/alert-dialog-content fixed top-1/2 left-1/2 z-50 grid w-full -translate-x-1/2 -translate-y-1/2 gap-4 rounded-xl bg-popover p-4 text-popover-foreground ring-1 ring-foreground/10 duration-100 outline-none data-[size=default]:max-w-xs data-[size=sm]:max-w-xs data-[size=default]:sm:max-w-sm 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",
62
+ className
63
+ )}
64
+ {...props}
65
+ />
66
+ </AlertDialogPortal>
67
+ )
68
+ }
69
+
70
+ function AlertDialogHeader({
71
+ className,
72
+ ...props
73
+ }: React.ComponentProps<"div">) {
74
+ return (
75
+ <div
76
+ data-slot="alert-dialog-header"
77
+ className={cn(
78
+ "grid grid-rows-[auto_1fr] place-items-center gap-1.5 text-center has-data-[slot=alert-dialog-media]:grid-rows-[auto_auto_1fr] has-data-[slot=alert-dialog-media]:gap-x-4 sm:group-data-[size=default]/alert-dialog-content:place-items-start sm:group-data-[size=default]/alert-dialog-content:text-left sm:group-data-[size=default]/alert-dialog-content:has-data-[slot=alert-dialog-media]:grid-rows-[auto_1fr]",
79
+ className
80
+ )}
81
+ {...props}
82
+ />
83
+ )
84
+ }
85
+
86
+ function AlertDialogFooter({
87
+ className,
88
+ ...props
89
+ }: React.ComponentProps<"div">) {
90
+ return (
91
+ <div
92
+ data-slot="alert-dialog-footer"
93
+ className={cn(
94
+ "-mx-4 -mb-4 flex flex-col-reverse gap-2 rounded-b-xl border-t bg-muted/50 p-4 group-data-[size=sm]/alert-dialog-content:grid group-data-[size=sm]/alert-dialog-content:grid-cols-2 sm:flex-row sm:justify-end",
95
+ className
96
+ )}
97
+ {...props}
98
+ />
99
+ )
100
+ }
101
+
102
+ function AlertDialogMedia({
103
+ className,
104
+ ...props
105
+ }: React.ComponentProps<"div">) {
106
+ return (
107
+ <div
108
+ data-slot="alert-dialog-media"
109
+ className={cn(
110
+ "mb-2 inline-flex size-10 items-center justify-center rounded-md bg-muted sm:group-data-[size=default]/alert-dialog-content:row-span-2 *:[svg:not([class*='size-'])]:size-6",
111
+ className
112
+ )}
113
+ {...props}
114
+ />
115
+ )
116
+ }
117
+
118
+ function AlertDialogTitle({
119
+ className,
120
+ ...props
121
+ }: React.ComponentProps<typeof AlertDialogPrimitive.Title>) {
122
+ return (
123
+ <AlertDialogPrimitive.Title
124
+ data-slot="alert-dialog-title"
125
+ className={cn(
126
+ "text-base font-medium sm:group-data-[size=default]/alert-dialog-content:group-has-data-[slot=alert-dialog-media]/alert-dialog-content:col-start-2",
127
+ className
128
+ )}
129
+ {...props}
130
+ />
131
+ )
132
+ }
133
+
134
+ function AlertDialogDescription({
135
+ className,
136
+ ...props
137
+ }: React.ComponentProps<typeof AlertDialogPrimitive.Description>) {
138
+ return (
139
+ <AlertDialogPrimitive.Description
140
+ data-slot="alert-dialog-description"
141
+ className={cn(
142
+ "text-sm text-balance text-muted-foreground md:text-pretty *:[a]:underline *:[a]:underline-offset-3 *:[a]:hover:text-foreground",
143
+ className
144
+ )}
145
+ {...props}
146
+ />
147
+ )
148
+ }
149
+
150
+ function AlertDialogAction({
151
+ className,
152
+ variant = "default",
153
+ size = "default",
154
+ ...props
155
+ }: React.ComponentProps<typeof AlertDialogPrimitive.Action> &
156
+ Pick<React.ComponentProps<typeof Button>, "variant" | "size">) {
157
+ return (
158
+ <Button variant={variant} size={size} asChild>
159
+ <AlertDialogPrimitive.Action
160
+ data-slot="alert-dialog-action"
161
+ className={cn(className)}
162
+ {...props}
163
+ />
164
+ </Button>
165
+ )
166
+ }
167
+
168
+ function AlertDialogCancel({
169
+ className,
170
+ variant = "outline",
171
+ size = "default",
172
+ ...props
173
+ }: React.ComponentProps<typeof AlertDialogPrimitive.Cancel> &
174
+ Pick<React.ComponentProps<typeof Button>, "variant" | "size">) {
175
+ return (
176
+ <Button variant={variant} size={size} asChild>
177
+ <AlertDialogPrimitive.Cancel
178
+ data-slot="alert-dialog-cancel"
179
+ className={cn(className)}
180
+ {...props}
181
+ />
182
+ </Button>
183
+ )
184
+ }
185
+
186
+ export {
187
+ AlertDialog,
188
+ AlertDialogAction,
189
+ AlertDialogCancel,
190
+ AlertDialogContent,
191
+ AlertDialogDescription,
192
+ AlertDialogFooter,
193
+ AlertDialogHeader,
194
+ AlertDialogMedia,
195
+ AlertDialogOverlay,
196
+ AlertDialogPortal,
197
+ AlertDialogTitle,
198
+ AlertDialogTrigger,
199
+ }
@@ -0,0 +1,76 @@
1
+ import * as React from "react"
2
+ import { cva, type VariantProps } from "class-variance-authority"
3
+
4
+ import { cn } from "@/lib/utils"
5
+
6
+ const alertVariants = cva(
7
+ "group/alert relative grid w-full gap-0.5 rounded-lg border px-2.5 py-2 text-left text-sm has-data-[slot=alert-action]:relative has-data-[slot=alert-action]:pr-18 has-[>svg]:grid-cols-[auto_1fr] has-[>svg]:gap-x-2 *:[svg]:row-span-2 *:[svg]:translate-y-0.5 *:[svg]:text-current *:[svg:not([class*='size-'])]:size-4",
8
+ {
9
+ variants: {
10
+ variant: {
11
+ default: "bg-card text-card-foreground",
12
+ destructive:
13
+ "bg-card text-destructive *:data-[slot=alert-description]:text-destructive/90 *:[svg]:text-current",
14
+ },
15
+ },
16
+ defaultVariants: {
17
+ variant: "default",
18
+ },
19
+ }
20
+ )
21
+
22
+ function Alert({
23
+ className,
24
+ variant,
25
+ ...props
26
+ }: React.ComponentProps<"div"> & VariantProps<typeof alertVariants>) {
27
+ return (
28
+ <div
29
+ data-slot="alert"
30
+ role="alert"
31
+ className={cn(alertVariants({ variant }), className)}
32
+ {...props}
33
+ />
34
+ )
35
+ }
36
+
37
+ function AlertTitle({ className, ...props }: React.ComponentProps<"div">) {
38
+ return (
39
+ <div
40
+ data-slot="alert-title"
41
+ className={cn(
42
+ "font-medium group-has-[>svg]/alert:col-start-2 [&_a]:underline [&_a]:underline-offset-3 [&_a]:hover:text-foreground",
43
+ className
44
+ )}
45
+ {...props}
46
+ />
47
+ )
48
+ }
49
+
50
+ function AlertDescription({
51
+ className,
52
+ ...props
53
+ }: React.ComponentProps<"div">) {
54
+ return (
55
+ <div
56
+ data-slot="alert-description"
57
+ className={cn(
58
+ "text-sm text-balance text-muted-foreground md:text-pretty [&_a]:underline [&_a]:underline-offset-3 [&_a]:hover:text-foreground [&_p:not(:last-child)]:mb-4",
59
+ className
60
+ )}
61
+ {...props}
62
+ />
63
+ )
64
+ }
65
+
66
+ function AlertAction({ className, ...props }: React.ComponentProps<"div">) {
67
+ return (
68
+ <div
69
+ data-slot="alert-action"
70
+ className={cn("absolute top-2 right-2", className)}
71
+ {...props}
72
+ />
73
+ )
74
+ }
75
+
76
+ export { Alert, AlertTitle, AlertDescription, AlertAction }
@@ -0,0 +1,11 @@
1
+ "use client"
2
+
3
+ import { AspectRatio as AspectRatioPrimitive } from "radix-ui"
4
+
5
+ function AspectRatio({
6
+ ...props
7
+ }: React.ComponentProps<typeof AspectRatioPrimitive.Root>) {
8
+ return <AspectRatioPrimitive.Root data-slot="aspect-ratio" {...props} />
9
+ }
10
+
11
+ export { AspectRatio }
@@ -0,0 +1,206 @@
1
+ import * as React from "react"
2
+ import { cva, type VariantProps } from "class-variance-authority"
3
+ import { Slot } from "radix-ui"
4
+
5
+ import { cn } from "@/lib/utils"
6
+ import { Button } from "@/components/ui/button"
7
+
8
+ const attachmentVariants = cva(
9
+ "group/attachment relative flex w-fit max-w-full min-w-0 shrink-0 flex-wrap rounded-xl border bg-card text-card-foreground transition-colors focus-within:ring-1 focus-within:ring-ring/50 has-[>a,>button]:hover:bg-muted/50 data-[state=error]:border-destructive/30 data-[state=idle]:border-dashed",
10
+ {
11
+ variants: {
12
+ size: {
13
+ default:
14
+ "gap-2 text-sm has-data-[slot=attachment-content]:px-2.5 has-data-[slot=attachment-content]:py-2 has-data-[slot=attachment-media]:p-2",
15
+ sm: "gap-2.5 text-xs has-data-[slot=attachment-content]:px-2 has-data-[slot=attachment-content]:py-1.5 has-data-[slot=attachment-media]:p-1.5",
16
+ xs: "gap-1.5 rounded-lg text-xs has-data-[slot=attachment-content]:px-1.5 has-data-[slot=attachment-content]:py-1 has-data-[slot=attachment-media]:p-1",
17
+ },
18
+ orientation: {
19
+ horizontal: "min-w-40 items-center",
20
+ vertical: "w-24 flex-col has-data-[slot=attachment-content]:w-30",
21
+ },
22
+ },
23
+ }
24
+ )
25
+
26
+ function Attachment({
27
+ className,
28
+ state = "done",
29
+ size = "default",
30
+ orientation = "horizontal",
31
+ ...props
32
+ }: React.ComponentProps<"div"> &
33
+ VariantProps<typeof attachmentVariants> & {
34
+ state?: "idle" | "uploading" | "processing" | "error" | "done"
35
+ }) {
36
+ const resolvedOrientation = orientation ?? "horizontal"
37
+
38
+ return (
39
+ <div
40
+ data-slot="attachment"
41
+ data-state={state}
42
+ data-size={size}
43
+ data-orientation={resolvedOrientation}
44
+ className={cn(attachmentVariants({ size, orientation }), className)}
45
+ {...props}
46
+ />
47
+ )
48
+ }
49
+
50
+ const attachmentMediaVariants = cva(
51
+ "relative flex aspect-square w-10 shrink-0 items-center justify-center overflow-hidden rounded-lg bg-muted text-foreground group-data-[orientation=vertical]/attachment:w-full group-data-[size=sm]/attachment:w-8 group-data-[size=xs]/attachment:w-7 group-data-[size=xs]/attachment:rounded-md group-data-[state=error]/attachment:bg-destructive/10 group-data-[state=error]/attachment:text-destructive group-data-[orientation=vertical]/attachment:*:data-[slot=spinner]:size-6! [&_svg]:pointer-events-none [&_svg:not([class*='size-'])]:size-4 group-data-[orientation=vertical]/attachment:[&_svg:not([class*='size-'])]:size-6 group-data-[size=xs]/attachment:[&_svg:not([class*='size-'])]:size-3.5",
52
+ {
53
+ variants: {
54
+ variant: {
55
+ icon: "",
56
+ image:
57
+ "opacity-60 group-data-[state=done]/attachment:opacity-100 group-data-[state=idle]/attachment:opacity-100 *:[img]:aspect-square *:[img]:w-full *:[img]:object-cover",
58
+ },
59
+ },
60
+ defaultVariants: {
61
+ variant: "icon",
62
+ },
63
+ }
64
+ )
65
+
66
+ function AttachmentMedia({
67
+ className,
68
+ variant = "icon",
69
+ ...props
70
+ }: React.ComponentProps<"div"> & VariantProps<typeof attachmentMediaVariants>) {
71
+ return (
72
+ <div
73
+ data-slot="attachment-media"
74
+ data-variant={variant}
75
+ className={cn(attachmentMediaVariants({ variant }), className)}
76
+ {...props}
77
+ />
78
+ )
79
+ }
80
+
81
+ function AttachmentContent({
82
+ className,
83
+ ...props
84
+ }: React.ComponentProps<"div">) {
85
+ return (
86
+ <div
87
+ data-slot="attachment-content"
88
+ className={cn(
89
+ "max-w-full min-w-0 flex-1 leading-tight group-data-[orientation=vertical]/attachment:px-1",
90
+ className
91
+ )}
92
+ {...props}
93
+ />
94
+ )
95
+ }
96
+
97
+ function AttachmentTitle({
98
+ className,
99
+ ...props
100
+ }: React.ComponentProps<"span">) {
101
+ return (
102
+ <span
103
+ data-slot="attachment-title"
104
+ className={cn(
105
+ "block max-w-full min-w-0 truncate font-medium group-data-[state=processing]/attachment:shimmer group-data-[state=uploading]/attachment:shimmer",
106
+ className
107
+ )}
108
+ {...props}
109
+ />
110
+ )
111
+ }
112
+
113
+ function AttachmentDescription({
114
+ className,
115
+ ...props
116
+ }: React.ComponentProps<"span">) {
117
+ return (
118
+ <span
119
+ data-slot="attachment-description"
120
+ className={cn(
121
+ "mt-0.5 block min-w-0 truncate text-xs text-muted-foreground group-data-[state=error]/attachment:text-destructive/80",
122
+ "max-w-full",
123
+ className
124
+ )}
125
+ {...props}
126
+ />
127
+ )
128
+ }
129
+
130
+ function AttachmentActions({
131
+ className,
132
+ ...props
133
+ }: React.ComponentProps<"div">) {
134
+ return (
135
+ <div
136
+ data-slot="attachment-actions"
137
+ className={cn(
138
+ "relative z-20 flex shrink-0 items-center group-data-[orientation=vertical]/attachment:absolute group-data-[orientation=vertical]/attachment:top-3 group-data-[orientation=vertical]/attachment:right-3 group-data-[orientation=vertical]/attachment:gap-1",
139
+ className
140
+ )}
141
+ {...props}
142
+ />
143
+ )
144
+ }
145
+
146
+ function AttachmentAction({
147
+ className,
148
+ variant,
149
+ size = "icon-xs",
150
+ ...props
151
+ }: React.ComponentProps<typeof Button>) {
152
+ return (
153
+ <Button
154
+ data-slot="attachment-action"
155
+ variant={variant ?? "ghost"}
156
+ size={size}
157
+ className={cn(className)}
158
+ {...props}
159
+ />
160
+ )
161
+ }
162
+
163
+ function AttachmentTrigger({
164
+ className,
165
+ asChild = false,
166
+ type,
167
+ ...props
168
+ }: React.ComponentProps<"button"> & {
169
+ asChild?: boolean
170
+ }) {
171
+ const Comp = asChild ? Slot.Root : "button"
172
+
173
+ return (
174
+ <Comp
175
+ data-slot="attachment-trigger"
176
+ type={asChild ? undefined : (type ?? "button")}
177
+ className={cn("absolute inset-0 z-10 outline-none", className)}
178
+ {...props}
179
+ />
180
+ )
181
+ }
182
+
183
+ function AttachmentGroup({ className, ...props }: React.ComponentProps<"div">) {
184
+ return (
185
+ <div
186
+ data-slot="attachment-group"
187
+ className={cn(
188
+ "flex min-w-0 scroll-fade-x snap-x snap-mandatory scroll-px-1 scrollbar-none gap-3 overflow-x-auto overscroll-x-contain py-1 *:data-[slot=attachment]:flex-none *:data-[slot=attachment]:snap-start",
189
+ className
190
+ )}
191
+ {...props}
192
+ />
193
+ )
194
+ }
195
+
196
+ export {
197
+ Attachment,
198
+ AttachmentGroup,
199
+ AttachmentMedia,
200
+ AttachmentContent,
201
+ AttachmentTitle,
202
+ AttachmentDescription,
203
+ AttachmentActions,
204
+ AttachmentAction,
205
+ AttachmentTrigger,
206
+ }
@@ -0,0 +1,110 @@
1
+ import * as React from "react"
2
+ import { Avatar as AvatarPrimitive } from "radix-ui"
3
+
4
+ import { cn } from "@/lib/utils"
5
+
6
+ function Avatar({
7
+ className,
8
+ size = "default",
9
+ ...props
10
+ }: React.ComponentProps<typeof AvatarPrimitive.Root> & {
11
+ size?: "default" | "sm" | "lg"
12
+ }) {
13
+ return (
14
+ <AvatarPrimitive.Root
15
+ data-slot="avatar"
16
+ data-size={size}
17
+ className={cn(
18
+ "group/avatar relative flex size-8 shrink-0 rounded-full select-none after:absolute after:inset-0 after:rounded-full after:border after:border-border after:mix-blend-darken data-[size=lg]:size-10 data-[size=sm]:size-6 dark:after:mix-blend-lighten",
19
+ className
20
+ )}
21
+ {...props}
22
+ />
23
+ )
24
+ }
25
+
26
+ function AvatarImage({
27
+ className,
28
+ ...props
29
+ }: React.ComponentProps<typeof AvatarPrimitive.Image>) {
30
+ return (
31
+ <AvatarPrimitive.Image
32
+ data-slot="avatar-image"
33
+ className={cn(
34
+ "aspect-square size-full rounded-full object-cover",
35
+ className
36
+ )}
37
+ {...props}
38
+ />
39
+ )
40
+ }
41
+
42
+ function AvatarFallback({
43
+ className,
44
+ ...props
45
+ }: React.ComponentProps<typeof AvatarPrimitive.Fallback>) {
46
+ return (
47
+ <AvatarPrimitive.Fallback
48
+ data-slot="avatar-fallback"
49
+ className={cn(
50
+ "flex size-full items-center justify-center rounded-full bg-muted text-sm text-muted-foreground group-data-[size=sm]/avatar:text-xs",
51
+ className
52
+ )}
53
+ {...props}
54
+ />
55
+ )
56
+ }
57
+
58
+ function AvatarBadge({ className, ...props }: React.ComponentProps<"span">) {
59
+ return (
60
+ <span
61
+ data-slot="avatar-badge"
62
+ className={cn(
63
+ "absolute right-0 bottom-0 z-10 inline-flex items-center justify-center rounded-full bg-primary text-primary-foreground bg-blend-color ring-2 ring-background select-none",
64
+ "group-data-[size=sm]/avatar:size-2 group-data-[size=sm]/avatar:[&>svg]:hidden",
65
+ "group-data-[size=default]/avatar:size-2.5 group-data-[size=default]/avatar:[&>svg]:size-2",
66
+ "group-data-[size=lg]/avatar:size-3 group-data-[size=lg]/avatar:[&>svg]:size-2",
67
+ className
68
+ )}
69
+ {...props}
70
+ />
71
+ )
72
+ }
73
+
74
+ function AvatarGroup({ className, ...props }: React.ComponentProps<"div">) {
75
+ return (
76
+ <div
77
+ data-slot="avatar-group"
78
+ className={cn(
79
+ "group/avatar-group flex -space-x-2 *:data-[slot=avatar]:ring-2 *:data-[slot=avatar]:ring-background",
80
+ className
81
+ )}
82
+ {...props}
83
+ />
84
+ )
85
+ }
86
+
87
+ function AvatarGroupCount({
88
+ className,
89
+ ...props
90
+ }: React.ComponentProps<"div">) {
91
+ return (
92
+ <div
93
+ data-slot="avatar-group-count"
94
+ className={cn(
95
+ "relative flex size-8 shrink-0 items-center justify-center rounded-full bg-muted text-sm text-muted-foreground ring-2 ring-background group-has-data-[size=lg]/avatar-group:size-10 group-has-data-[size=sm]/avatar-group:size-6 [&>svg]:size-4 group-has-data-[size=lg]/avatar-group:[&>svg]:size-5 group-has-data-[size=sm]/avatar-group:[&>svg]:size-3",
96
+ className
97
+ )}
98
+ {...props}
99
+ />
100
+ )
101
+ }
102
+
103
+ export {
104
+ Avatar,
105
+ AvatarImage,
106
+ AvatarFallback,
107
+ AvatarGroup,
108
+ AvatarGroupCount,
109
+ AvatarBadge,
110
+ }
@@ -0,0 +1,49 @@
1
+ import * as React from "react"
2
+ import { cva, type VariantProps } from "class-variance-authority"
3
+ import { Slot } from "radix-ui"
4
+
5
+ import { cn } from "@/lib/utils"
6
+
7
+ const badgeVariants = cva(
8
+ "group/badge inline-flex h-5 w-fit shrink-0 items-center justify-center gap-1 overflow-hidden rounded-4xl border border-transparent px-2 py-0.5 text-xs font-medium whitespace-nowrap transition-all focus-visible:border-ring focus-visible:ring-[3px] focus-visible:ring-ring/50 has-data-[icon=inline-end]:pr-1.5 has-data-[icon=inline-start]:pl-1.5 aria-invalid:border-destructive aria-invalid:ring-destructive/20 dark:aria-invalid:ring-destructive/40 [&>svg]:pointer-events-none [&>svg]:size-3!",
9
+ {
10
+ variants: {
11
+ variant: {
12
+ default: "bg-primary text-primary-foreground [a]:hover:bg-primary/80",
13
+ secondary:
14
+ "bg-secondary text-secondary-foreground [a]:hover:bg-secondary/80",
15
+ destructive:
16
+ "bg-destructive/10 text-destructive focus-visible:ring-destructive/20 dark:bg-destructive/20 dark:focus-visible:ring-destructive/40 [a]:hover:bg-destructive/20",
17
+ outline:
18
+ "border-border text-foreground [a]:hover:bg-muted [a]:hover:text-muted-foreground",
19
+ ghost:
20
+ "hover:bg-muted hover:text-muted-foreground dark:hover:bg-muted/50",
21
+ link: "text-primary underline-offset-4 hover:underline",
22
+ },
23
+ },
24
+ defaultVariants: {
25
+ variant: "default",
26
+ },
27
+ }
28
+ )
29
+
30
+ function Badge({
31
+ className,
32
+ variant = "default",
33
+ asChild = false,
34
+ ...props
35
+ }: React.ComponentProps<"span"> &
36
+ VariantProps<typeof badgeVariants> & { asChild?: boolean }) {
37
+ const Comp = asChild ? Slot.Root : "span"
38
+
39
+ return (
40
+ <Comp
41
+ data-slot="badge"
42
+ data-variant={variant}
43
+ className={cn(badgeVariants({ variant }), className)}
44
+ {...props}
45
+ />
46
+ )
47
+ }
48
+
49
+ export { Badge, badgeVariants }