diff --git a/apps/v4/public/r/styles/new-york-v4/attachment.json b/apps/v4/public/r/styles/new-york-v4/attachment.json new file mode 100644 index 0000000000..f784d44aee --- /dev/null +++ b/apps/v4/public/r/styles/new-york-v4/attachment.json @@ -0,0 +1,18 @@ +{ + "$schema": "https://ui.shadcn.com/schema/registry-item.json", + "name": "attachment", + "dependencies": [ + "radix-ui" + ], + "registryDependencies": [ + "button" + ], + "files": [ + { + "path": "registry/new-york-v4/ui/attachment.tsx", + "content": "import * as React from \"react\"\nimport { cva, type VariantProps } from \"class-variance-authority\"\nimport { Slot } from \"radix-ui\"\n\nimport { cn } from \"@/lib/utils\"\nimport { Button } from \"@/registry/new-york-v4/ui/button\"\n\nconst attachmentVariants = cva(\n \"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\",\n {\n variants: {\n size: {\n default:\n \"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\",\n 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\",\n 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\",\n },\n orientation: {\n horizontal: \"min-w-40 items-center\",\n vertical: \"w-24 flex-col has-data-[slot=attachment-content]:w-30\",\n },\n },\n }\n)\n\nfunction Attachment({\n className,\n state = \"done\",\n size = \"default\",\n orientation = \"horizontal\",\n ...props\n}: React.ComponentProps<\"div\"> &\n VariantProps & {\n state?: \"idle\" | \"uploading\" | \"processing\" | \"error\" | \"done\"\n }) {\n const resolvedOrientation = orientation ?? \"horizontal\"\n\n return (\n \n )\n}\n\nconst attachmentMediaVariants = cva(\n \"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\",\n {\n variants: {\n variant: {\n icon: \"\",\n image:\n \"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\",\n },\n },\n defaultVariants: {\n variant: \"icon\",\n },\n }\n)\n\nfunction AttachmentMedia({\n className,\n variant = \"icon\",\n ...props\n}: React.ComponentProps<\"div\"> & VariantProps) {\n return (\n \n )\n}\n\nfunction AttachmentContent({\n className,\n ...props\n}: React.ComponentProps<\"div\">) {\n return (\n \n )\n}\n\nfunction AttachmentTitle({\n className,\n ...props\n}: React.ComponentProps<\"span\">) {\n return (\n \n )\n}\n\nfunction AttachmentDescription({\n className,\n ...props\n}: React.ComponentProps<\"span\">) {\n return (\n \n )\n}\n\nfunction AttachmentActions({\n className,\n ...props\n}: React.ComponentProps<\"div\">) {\n return (\n \n )\n}\n\nfunction AttachmentAction({\n className,\n variant,\n size = \"icon-xs\",\n ...props\n}: React.ComponentProps) {\n return (\n \n )\n}\n\nfunction AttachmentTrigger({\n className,\n asChild = false,\n type,\n ...props\n}: React.ComponentProps<\"button\"> & {\n asChild?: boolean\n}) {\n const Comp = asChild ? Slot.Root : \"button\"\n\n return (\n \n )\n}\n\nfunction AttachmentGroup({ className, ...props }: React.ComponentProps<\"div\">) {\n return (\n \n )\n}\n\nexport {\n Attachment,\n AttachmentGroup,\n AttachmentMedia,\n AttachmentContent,\n AttachmentTitle,\n AttachmentDescription,\n AttachmentActions,\n AttachmentAction,\n AttachmentTrigger,\n}\n", + "type": "registry:ui" + } + ], + "type": "registry:ui" +} \ No newline at end of file diff --git a/apps/v4/public/r/styles/new-york-v4/bubble.json b/apps/v4/public/r/styles/new-york-v4/bubble.json new file mode 100644 index 0000000000..ba3e34ea6b --- /dev/null +++ b/apps/v4/public/r/styles/new-york-v4/bubble.json @@ -0,0 +1,15 @@ +{ + "$schema": "https://ui.shadcn.com/schema/registry-item.json", + "name": "bubble", + "dependencies": [ + "radix-ui" + ], + "files": [ + { + "path": "registry/new-york-v4/ui/bubble.tsx", + "content": "import * as React from \"react\"\nimport { cva, type VariantProps } from \"class-variance-authority\"\nimport { Slot } from \"radix-ui\"\n\nimport { cn } from \"@/lib/utils\"\n\nfunction BubbleGroup({ className, ...props }: React.ComponentProps<\"div\">) {\n return (\n \n )\n}\n\nconst bubbleVariants = cva(\n \"group/bubble relative flex w-fit max-w-[80%] min-w-0 flex-col gap-1 group-data-[align=end]/message:self-end data-[align=end]:self-end data-[variant=ghost]:max-w-full\",\n {\n variants: {\n variant: {\n default:\n \"*:data-[slot=bubble-content]:bg-primary *:data-[slot=bubble-content]:text-primary-foreground [&>[data-slot=bubble-content]:is(button,a):hover]:bg-primary/80\",\n secondary:\n \"*:data-[slot=bubble-content]:bg-secondary *:data-[slot=bubble-content]:text-secondary-foreground [&>[data-slot=bubble-content]:is(button,a):hover]:bg-[color-mix(in_oklch,var(--secondary),var(--foreground)_5%)]\",\n muted:\n \"*:data-[slot=bubble-content]:bg-muted [&>[data-slot=bubble-content]:is(button,a):hover]:bg-[color-mix(in_oklch,var(--muted),var(--foreground)_5%)]\",\n tinted:\n \"*:data-[slot=bubble-content]:bg-[oklch(from_var(--primary)_0.93_calc(c*0.4)_h)] *:data-[slot=bubble-content]:text-foreground dark:*:data-[slot=bubble-content]:bg-[oklch(from_var(--primary)_0.3_calc(c*0.4)_h)] [&>[data-slot=bubble-content]:is(button,a):hover]:bg-[oklch(from_var(--primary)_0.88_calc(c*0.5)_h)] dark:[&>[data-slot=bubble-content]:is(button,a):hover]:bg-[oklch(from_var(--primary)_0.35_calc(c*0.5)_h)]\",\n outline:\n \"*:data-[slot=bubble-content]:border-border *:data-[slot=bubble-content]:bg-background [&>[data-slot=bubble-content]:is(button,a):hover]:bg-muted [&>[data-slot=bubble-content]:is(button,a):hover]:text-foreground dark:[&>[data-slot=bubble-content]:is(button,a):hover]:bg-input/30\",\n ghost:\n \"border-none *:data-[slot=bubble-content]:rounded-none *:data-[slot=bubble-content]:bg-transparent *:data-[slot=bubble-content]:p-0 [&>[data-slot=bubble-content]:is(button,a):hover]:bg-muted [&>[data-slot=bubble-content]:is(button,a):hover]:text-foreground dark:[&>[data-slot=bubble-content]:is(button,a):hover]:bg-muted/50\",\n destructive:\n \"*:data-[slot=bubble-content]:bg-destructive/10 *:data-[slot=bubble-content]:text-destructive dark:*:data-[slot=bubble-content]:bg-destructive/20 [&>[data-slot=bubble-content]:is(button,a):hover]:bg-destructive/20 dark:[&>[data-slot=bubble-content]:is(button,a):hover]:bg-destructive/30\",\n },\n },\n defaultVariants: {\n variant: \"default\",\n },\n }\n)\n\nfunction Bubble({\n variant = \"default\",\n align = \"start\",\n className,\n ...props\n}: React.ComponentProps<\"div\"> &\n VariantProps & {\n align?: \"start\" | \"end\"\n }) {\n return (\n \n )\n}\n\nfunction BubbleContent({\n asChild = false,\n className,\n ...props\n}: React.ComponentProps<\"div\"> & {\n asChild?: boolean\n}) {\n const Comp = asChild ? Slot.Root : \"div\"\n\n return (\n \n )\n}\n\nconst bubbleReactionsVariants = cva(\n \"absolute z-10 flex w-fit shrink-0 items-center justify-center gap-1 rounded-full bg-muted px-1.5 py-0.5 text-sm ring-3 ring-card has-[button]:p-0\",\n {\n variants: {\n side: {\n top: \"top-0 -translate-y-3/4\",\n bottom: \"bottom-0 translate-y-3/4\",\n },\n align: {\n start: \"left-3\",\n end: \"right-3\",\n },\n },\n defaultVariants: {\n side: \"bottom\",\n align: \"end\",\n },\n }\n)\n\nfunction BubbleReactions({\n side = \"bottom\",\n align = \"end\",\n className,\n ...props\n}: React.ComponentProps<\"div\"> & {\n align?: \"start\" | \"end\"\n side?: \"top\" | \"bottom\"\n}) {\n return (\n \n )\n}\n\nexport { BubbleGroup, Bubble, BubbleContent, BubbleReactions }\n", + "type": "registry:ui" + } + ], + "type": "registry:ui" +} \ No newline at end of file diff --git a/apps/v4/public/r/styles/new-york-v4/marker.json b/apps/v4/public/r/styles/new-york-v4/marker.json new file mode 100644 index 0000000000..6ae1e9a08a --- /dev/null +++ b/apps/v4/public/r/styles/new-york-v4/marker.json @@ -0,0 +1,15 @@ +{ + "$schema": "https://ui.shadcn.com/schema/registry-item.json", + "name": "marker", + "dependencies": [ + "radix-ui" + ], + "files": [ + { + "path": "registry/new-york-v4/ui/marker.tsx", + "content": "import * as React from \"react\"\nimport { cva, type VariantProps } from \"class-variance-authority\"\nimport { Slot } from \"radix-ui\"\n\nimport { cn } from \"@/lib/utils\"\n\nconst markerVariants = cva(\n \"group/marker relative flex min-h-4 w-full items-center gap-2 text-left text-sm text-muted-foreground [&_svg:not([class*='size-'])]:size-4 [a]:underline [a]:underline-offset-3 [a]:hover:text-foreground\",\n {\n variants: {\n variant: {\n default: \"\",\n separator:\n \"before:mr-1 before:h-px before:min-w-0 before:flex-1 before:bg-border after:ml-1 after:h-px after:min-w-0 after:flex-1 after:bg-border\",\n border: \"border-b border-border pb-2\",\n },\n },\n }\n)\n\nfunction Marker({\n className,\n variant = \"default\",\n asChild = false,\n ...props\n}: React.ComponentProps<\"div\"> &\n VariantProps & {\n asChild?: boolean\n }) {\n const Comp = asChild ? Slot.Root : \"div\"\n\n return (\n \n )\n}\n\nfunction MarkerIcon({ className, ...props }: React.ComponentProps<\"span\">) {\n return (\n \n )\n}\n\nfunction MarkerContent({ className, ...props }: React.ComponentProps<\"span\">) {\n return (\n \n )\n}\n\nexport { Marker, MarkerIcon, MarkerContent, markerVariants }\n", + "type": "registry:ui" + } + ], + "type": "registry:ui" +} \ No newline at end of file diff --git a/apps/v4/public/r/styles/new-york-v4/message-scroller.json b/apps/v4/public/r/styles/new-york-v4/message-scroller.json new file mode 100644 index 0000000000..fc9456c0a2 --- /dev/null +++ b/apps/v4/public/r/styles/new-york-v4/message-scroller.json @@ -0,0 +1,18 @@ +{ + "$schema": "https://ui.shadcn.com/schema/registry-item.json", + "name": "message-scroller", + "dependencies": [ + "@shadcn/react" + ], + "registryDependencies": [ + "button" + ], + "files": [ + { + "path": "registry/new-york-v4/ui/message-scroller.tsx", + "content": "\"use client\"\n\nimport * as React from \"react\"\nimport {\n MessageScroller as MessageScrollerPrimitive,\n useMessageScroller,\n useMessageScrollerScrollable,\n useMessageScrollerVisibility,\n} from \"@shadcn/react/message-scroller\"\nimport { ArrowDownIcon } from \"lucide-react\"\n\nimport { cn } from \"@/lib/utils\"\nimport { Button } from \"@/registry/new-york-v4/ui/button\"\n\nfunction MessageScrollerProvider(\n props: React.ComponentProps\n) {\n return \n}\n\nfunction MessageScroller({\n className,\n ...props\n}: React.ComponentProps) {\n return (\n \n )\n}\n\nfunction MessageScrollerViewport({\n className,\n ...props\n}: React.ComponentProps) {\n return (\n \n )\n}\n\nfunction MessageScrollerContent({\n className,\n ...props\n}: React.ComponentProps) {\n return (\n \n )\n}\n\nfunction MessageScrollerItem({\n className,\n scrollAnchor = false,\n ...props\n}: React.ComponentProps) {\n return (\n \n )\n}\n\nfunction MessageScrollerButton({\n direction = \"end\",\n className,\n children,\n render,\n variant = \"secondary\",\n size = \"icon-sm\",\n ...props\n}: React.ComponentProps &\n Pick, \"variant\" | \"size\">) {\n return (\n }\n {...props}\n >\n {children ?? (\n <>\n \n \n {direction === \"end\" ? \"Scroll to end\" : \"Scroll to start\"}\n \n \n )}\n \n )\n}\n\nexport {\n MessageScrollerProvider,\n MessageScroller,\n MessageScrollerViewport,\n MessageScrollerContent,\n MessageScrollerItem,\n MessageScrollerButton,\n useMessageScroller,\n useMessageScrollerScrollable,\n useMessageScrollerVisibility,\n}\n", + "type": "registry:ui" + } + ], + "type": "registry:ui" +} \ No newline at end of file diff --git a/apps/v4/public/r/styles/new-york-v4/message.json b/apps/v4/public/r/styles/new-york-v4/message.json new file mode 100644 index 0000000000..7bfdff4ebb --- /dev/null +++ b/apps/v4/public/r/styles/new-york-v4/message.json @@ -0,0 +1,12 @@ +{ + "$schema": "https://ui.shadcn.com/schema/registry-item.json", + "name": "message", + "files": [ + { + "path": "registry/new-york-v4/ui/message.tsx", + "content": "import * as React from \"react\"\n\nimport { cn } from \"@/lib/utils\"\n\nfunction MessageGroup({ className, ...props }: React.ComponentProps<\"div\">) {\n return (\n \n )\n}\n\nfunction Message({\n className,\n align = \"start\",\n ...props\n}: React.ComponentProps<\"div\"> & { align?: \"start\" | \"end\" }) {\n return (\n \n )\n}\n\nfunction MessageAvatar({ className, ...props }: React.ComponentProps<\"div\">) {\n return (\n \n )\n}\n\nfunction MessageContent({ className, ...props }: React.ComponentProps<\"div\">) {\n return (\n \n )\n}\n\nfunction MessageHeader({ className, ...props }: React.ComponentProps<\"div\">) {\n return (\n \n )\n}\n\nfunction MessageFooter({ className, ...props }: React.ComponentProps<\"div\">) {\n return (\n \n )\n}\n\nexport {\n MessageGroup,\n Message,\n MessageAvatar,\n MessageContent,\n MessageFooter,\n MessageHeader,\n}\n", + "type": "registry:ui" + } + ], + "type": "registry:ui" +} \ No newline at end of file diff --git a/apps/v4/public/r/styles/new-york-v4/registry.json b/apps/v4/public/r/styles/new-york-v4/registry.json index 59c0114c2e..8dabc7828d 100644 --- a/apps/v4/public/r/styles/new-york-v4/registry.json +++ b/apps/v4/public/r/styles/new-york-v4/registry.json @@ -716,6 +716,62 @@ ], "type": "registry:ui" }, + { + "name": "attachment", + "dependencies": ["radix-ui"], + "registryDependencies": ["button"], + "files": [ + { + "path": "registry/new-york-v4/ui/attachment.tsx", + "type": "registry:ui" + } + ], + "type": "registry:ui" + }, + { + "name": "bubble", + "dependencies": ["radix-ui"], + "files": [ + { + "path": "registry/new-york-v4/ui/bubble.tsx", + "type": "registry:ui" + } + ], + "type": "registry:ui" + }, + { + "name": "marker", + "dependencies": ["radix-ui"], + "files": [ + { + "path": "registry/new-york-v4/ui/marker.tsx", + "type": "registry:ui" + } + ], + "type": "registry:ui" + }, + { + "name": "message", + "files": [ + { + "path": "registry/new-york-v4/ui/message.tsx", + "type": "registry:ui" + } + ], + "type": "registry:ui" + }, + { + "name": "message-scroller", + "dependencies": ["@shadcn/react"], + "registryDependencies": ["button"], + "files": [ + { + "path": "registry/new-york-v4/ui/message-scroller.tsx", + "type": "registry:ui" + } + ], + "type": "registry:ui" + }, { "name": "dashboard-01", "description": "A dashboard with sidebar, charts and data table.", diff --git a/apps/v4/registry/__components__.tsx b/apps/v4/registry/__components__.tsx index 474b628b1f..1b9ea9d309 100644 --- a/apps/v4/registry/__components__.tsx +++ b/apps/v4/registry/__components__.tsx @@ -511,6 +511,51 @@ export const Components: Record> = { ) || "direction" return { default: mod.default || mod[exportName] } }), + attachment: React.lazy(async () => { + const mod = await import("@/registry/new-york-v4/ui/attachment") + const exportName = + Object.keys(mod).find( + (key) => + typeof mod[key] === "function" || typeof mod[key] === "object" + ) || "attachment" + return { default: mod.default || mod[exportName] } + }), + bubble: React.lazy(async () => { + const mod = await import("@/registry/new-york-v4/ui/bubble") + const exportName = + Object.keys(mod).find( + (key) => + typeof mod[key] === "function" || typeof mod[key] === "object" + ) || "bubble" + return { default: mod.default || mod[exportName] } + }), + marker: React.lazy(async () => { + const mod = await import("@/registry/new-york-v4/ui/marker") + const exportName = + Object.keys(mod).find( + (key) => + typeof mod[key] === "function" || typeof mod[key] === "object" + ) || "marker" + return { default: mod.default || mod[exportName] } + }), + message: React.lazy(async () => { + const mod = await import("@/registry/new-york-v4/ui/message") + const exportName = + Object.keys(mod).find( + (key) => + typeof mod[key] === "function" || typeof mod[key] === "object" + ) || "message" + return { default: mod.default || mod[exportName] } + }), + "message-scroller": React.lazy(async () => { + const mod = await import("@/registry/new-york-v4/ui/message-scroller") + const exportName = + Object.keys(mod).find( + (key) => + typeof mod[key] === "function" || typeof mod[key] === "object" + ) || "message-scroller" + return { default: mod.default || mod[exportName] } + }), "dashboard-01": React.lazy(async () => { const mod = await import( "@/registry/new-york-v4/blocks/dashboard-01/page" diff --git a/apps/v4/registry/__index__.tsx b/apps/v4/registry/__index__.tsx index 42613ab6f1..7bfb073255 100644 --- a/apps/v4/registry/__index__.tsx +++ b/apps/v4/registry/__index__.tsx @@ -909,6 +909,86 @@ export const Index: Record> = { categories: undefined, meta: undefined, }, + attachment: { + name: "attachment", + title: "undefined", + description: "", + type: "registry:ui", + registryDependencies: ["button"], + files: [ + { + path: "registry/new-york-v4/ui/attachment.tsx", + type: "registry:ui", + target: "", + }, + ], + categories: undefined, + meta: undefined, + }, + bubble: { + name: "bubble", + title: "undefined", + description: "", + type: "registry:ui", + registryDependencies: undefined, + files: [ + { + path: "registry/new-york-v4/ui/bubble.tsx", + type: "registry:ui", + target: "", + }, + ], + categories: undefined, + meta: undefined, + }, + marker: { + name: "marker", + title: "undefined", + description: "", + type: "registry:ui", + registryDependencies: undefined, + files: [ + { + path: "registry/new-york-v4/ui/marker.tsx", + type: "registry:ui", + target: "", + }, + ], + categories: undefined, + meta: undefined, + }, + message: { + name: "message", + title: "undefined", + description: "", + type: "registry:ui", + registryDependencies: undefined, + files: [ + { + path: "registry/new-york-v4/ui/message.tsx", + type: "registry:ui", + target: "", + }, + ], + categories: undefined, + meta: undefined, + }, + "message-scroller": { + name: "message-scroller", + title: "undefined", + description: "", + type: "registry:ui", + registryDependencies: ["button"], + files: [ + { + path: "registry/new-york-v4/ui/message-scroller.tsx", + type: "registry:ui", + target: "", + }, + ], + categories: undefined, + meta: undefined, + }, "dashboard-01": { name: "dashboard-01", title: "undefined", diff --git a/apps/v4/registry/new-york-v4/ui/_registry.ts b/apps/v4/registry/new-york-v4/ui/_registry.ts index b31e372ede..0514b24750 100644 --- a/apps/v4/registry/new-york-v4/ui/_registry.ts +++ b/apps/v4/registry/new-york-v4/ui/_registry.ts @@ -702,4 +702,60 @@ export default function RootLayout({ children }: { children: React.ReactNode }) }, ], }, + { + name: "attachment", + type: "registry:ui", + dependencies: ["radix-ui"], + registryDependencies: ["button"], + files: [ + { + path: "ui/attachment.tsx", + type: "registry:ui", + }, + ], + }, + { + name: "bubble", + type: "registry:ui", + dependencies: ["radix-ui"], + files: [ + { + path: "ui/bubble.tsx", + type: "registry:ui", + }, + ], + }, + { + name: "marker", + type: "registry:ui", + dependencies: ["radix-ui"], + files: [ + { + path: "ui/marker.tsx", + type: "registry:ui", + }, + ], + }, + { + name: "message", + type: "registry:ui", + files: [ + { + path: "ui/message.tsx", + type: "registry:ui", + }, + ], + }, + { + name: "message-scroller", + type: "registry:ui", + dependencies: ["@shadcn/react"], + registryDependencies: ["button"], + files: [ + { + path: "ui/message-scroller.tsx", + type: "registry:ui", + }, + ], + }, ] diff --git a/apps/v4/registry/new-york-v4/ui/attachment.tsx b/apps/v4/registry/new-york-v4/ui/attachment.tsx new file mode 100644 index 0000000000..49278ef3e4 --- /dev/null +++ b/apps/v4/registry/new-york-v4/ui/attachment.tsx @@ -0,0 +1,209 @@ +import * as React from "react" +import { cva, type VariantProps } from "class-variance-authority" +import { Slot } from "radix-ui" + +import { cn } from "@/lib/utils" +import { Button } from "@/registry/new-york-v4/ui/button" + +const attachmentVariants = cva( + "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", + { + variants: { + size: { + default: + "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", + 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", + 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", + }, + orientation: { + horizontal: "min-w-40 items-center", + vertical: "w-24 flex-col has-data-[slot=attachment-content]:w-30", + }, + }, + } +) + +function Attachment({ + className, + state = "done", + size = "default", + orientation = "horizontal", + ...props +}: React.ComponentProps<"div"> & + VariantProps & { + state?: "idle" | "uploading" | "processing" | "error" | "done" + }) { + const resolvedOrientation = orientation ?? "horizontal" + + return ( +
+ ) +} + +const attachmentMediaVariants = cva( + "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", + { + variants: { + variant: { + icon: "", + image: + "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", + }, + }, + defaultVariants: { + variant: "icon", + }, + } +) + +function AttachmentMedia({ + className, + variant = "icon", + ...props +}: React.ComponentProps<"div"> & VariantProps) { + return ( +
+ ) +} + +function AttachmentContent({ + className, + ...props +}: React.ComponentProps<"div">) { + return ( +
+ ) +} + +function AttachmentTitle({ + className, + ...props +}: React.ComponentProps<"span">) { + return ( + + ) +} + +function AttachmentDescription({ + className, + ...props +}: React.ComponentProps<"span">) { + return ( + + ) +} + +function AttachmentActions({ + className, + ...props +}: React.ComponentProps<"div">) { + return ( +
+ ) +} + +function AttachmentAction({ + className, + variant, + size = "icon-xs", + ...props +}: React.ComponentProps) { + return ( +