import React, { memo, useState } from "react";
import type { InputContentSource } from "@copilotkit/shared";
import { getSourceUrl, getDocumentIcon } from "@copilotkit/shared";
import { cn } from "../../lib/utils";
import { Lightbox, useLightbox } from "./Lightbox";
interface CopilotChatAttachmentRendererProps {
type: "image" | "audio" | "video" | "document";
source: InputContentSource;
filename?: string;
className?: string;
}
const ImageAttachment = memo(function ImageAttachment({
src,
className,
}: {
src: string;
className?: string;
}) {
const [error, setError] = useState(false);
const { thumbnailRef, vtName, open, openLightbox, closeLightbox } =
useLightbox();
if (error) {
return (
Failed to load image
);
}
return (
<>
}
src={src}
alt="Image attachment"
className={cn(
"cpk:max-w-[80px] cpk:max-h-[80px] cpk:w-auto cpk:h-auto cpk:rounded-xl cpk:object-cover cpk:cursor-pointer cpk:bg-muted",
className,
)}
onClick={openLightbox}
onError={() => setError(true)}
/>
{open && (
)}
>
);
});
const AudioAttachment = memo(function AudioAttachment({
src,
filename,
className,
}: {
src: string;
filename?: string;
className?: string;
}) {
return (
{filename && (
{filename}
)}
);
});
const VideoAttachment = memo(function VideoAttachment({
src,
className,
}: {
src: string;
className?: string;
}) {
return (
);
});
const DocumentAttachment = memo(function DocumentAttachment({
source,
filename,
className,
}: {
source: InputContentSource;
filename?: string;
className?: string;
}) {
return (
{getDocumentIcon(source.mimeType ?? "")}
{filename || source.mimeType || "Unknown type"}
);
});
export const CopilotChatAttachmentRenderer: React.FC<
CopilotChatAttachmentRendererProps
> = ({ type, source, filename, className }) => {
const src = getSourceUrl(source);
switch (type) {
case "image":
return ;
case "audio":
return (
);
case "video":
return ;
case "document":
return (
);
}
};
export default CopilotChatAttachmentRenderer;