import * as React from "react"; import { cva, type VariantProps } from "class-variance-authority"; import { cn } from "@/lib/utils"; import { Avatar, AvatarImage, AvatarFallback } from "@/components/ui/avatar"; import MessageLoading from "./message-loading"; import { Button, ButtonProps } from "../button"; // ChatBubble const chatBubbleVariant = cva( "flex gap-2 max-w-[60%] items-end relative group", { variants: { variant: { received: "self-start", sent: "self-end flex-row-reverse", }, layout: { default: "", ai: "max-w-full w-full items-center", }, }, defaultVariants: { variant: "received", layout: "default", }, }, ); interface ChatBubbleProps extends React.HTMLAttributes, VariantProps { } const ChatBubble = React.forwardRef( ({ className, variant, layout, children, ...props }, ref) => (
{React.Children.map(children, (child) => React.isValidElement(child) && typeof child.type !== "string" ? React.cloneElement(child, { variant, layout, } as React.ComponentProps) : child, )}
), ); ChatBubble.displayName = "ChatBubble"; // ChatBubbleAvatar interface ChatBubbleAvatarProps { src?: string; fallback?: string; className?: string; } const ChatBubbleAvatar: React.FC = ({ src, fallback, className, }) => ( {fallback} ); // ChatBubbleMessage const chatBubbleMessageVariants = cva("p-0", { variants: { variant: { received: "bg-secondary text-secondary-foreground rounded-r-lg rounded-tl-lg", sent: "bg-primary text-primary-foreground rounded-l-lg rounded-tr-lg", }, layout: { default: "", ai: "w-full rounded-none bg-transparent", }, }, defaultVariants: { variant: "received", layout: "default", }, }); interface ChatBubbleMessageProps extends React.HTMLAttributes, VariantProps { isLoading?: boolean; } const ChatBubbleMessage = React.forwardRef< HTMLDivElement, ChatBubbleMessageProps >( ( { className, variant, layout, isLoading = false, children, ...props }, ref, ) => (
{isLoading ? (
) : ( children )}
), ); ChatBubbleMessage.displayName = "ChatBubbleMessage"; // ChatBubbleTimestamp interface ChatBubbleTimestampProps extends React.HTMLAttributes { timestamp: string; } const ChatBubbleTimestamp: React.FC = ({ timestamp, className, ...props }) => (
{timestamp}
); // ChatBubbleAction type ChatBubbleActionProps = ButtonProps & { icon: React.ReactNode; }; const ChatBubbleAction: React.FC = ({ icon, onClick, className, variant = "ghost", size = "icon", ...props }) => ( ); interface ChatBubbleActionWrapperProps extends React.HTMLAttributes { variant?: "sent" | "received"; className?: string; } const ChatBubbleActionWrapper = React.forwardRef< HTMLDivElement, ChatBubbleActionWrapperProps >(({ variant, className, children, ...props }, ref) => (
{children}
)); ChatBubbleActionWrapper.displayName = "ChatBubbleActionWrapper"; export { ChatBubble, ChatBubbleAvatar, ChatBubbleMessage, ChatBubbleTimestamp, chatBubbleVariant, chatBubbleMessageVariants, ChatBubbleAction, ChatBubbleActionWrapper, };