forked from CopilotKit/CopilotKit
-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathCopilotChatAttachmentRenderer.tsx
More file actions
159 lines (149 loc) · 3.91 KB
/
Copy pathCopilotChatAttachmentRenderer.tsx
File metadata and controls
159 lines (149 loc) · 3.91 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
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 (
<div
className={cn(
"cpk:flex cpk:flex-col cpk:items-center cpk:justify-center cpk:rounded-lg cpk:bg-muted cpk:p-4 cpk:text-sm cpk:text-muted-foreground",
className,
)}
>
<span>Failed to load image</span>
</div>
);
}
return (
<>
<img
ref={thumbnailRef as React.Ref<HTMLImageElement>}
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 && (
<Lightbox onClose={closeLightbox}>
<img
style={{ viewTransitionName: vtName }}
src={src}
alt="Image attachment"
className="cpk:max-w-[90vw] cpk:max-h-[90vh] cpk:object-contain cpk:rounded-lg"
/>
</Lightbox>
)}
</>
);
});
const AudioAttachment = memo(function AudioAttachment({
src,
filename,
className,
}: {
src: string;
filename?: string;
className?: string;
}) {
return (
<div className={cn("cpk:flex cpk:flex-col cpk:gap-1", className)}>
<audio
src={src}
controls
preload="metadata"
className="cpk:max-w-[300px] cpk:w-full cpk:h-10"
/>
{filename && (
<span className="cpk:text-xs cpk:text-muted-foreground cpk:truncate cpk:max-w-[300px]">
{filename}
</span>
)}
</div>
);
});
const VideoAttachment = memo(function VideoAttachment({
src,
className,
}: {
src: string;
className?: string;
}) {
return (
<video
src={src}
controls
preload="metadata"
className={cn("cpk:max-w-[400px] cpk:w-full cpk:rounded-lg", className)}
/>
);
});
const DocumentAttachment = memo(function DocumentAttachment({
source,
filename,
className,
}: {
source: InputContentSource;
filename?: string;
className?: string;
}) {
return (
<div
className={cn(
"cpk:inline-flex cpk:items-center cpk:gap-2 cpk:px-3 cpk:py-2 cpk:border cpk:border-border cpk:rounded-lg cpk:bg-muted",
className,
)}
>
<span className="cpk:text-xs cpk:font-bold cpk:uppercase">
{getDocumentIcon(source.mimeType ?? "")}
</span>
<span className="cpk:text-sm cpk:text-muted-foreground cpk:truncate">
{filename || source.mimeType || "Unknown type"}
</span>
</div>
);
});
export const CopilotChatAttachmentRenderer: React.FC<
CopilotChatAttachmentRendererProps
> = ({ type, source, filename, className }) => {
const src = getSourceUrl(source);
switch (type) {
case "image":
return <ImageAttachment src={src} className={className} />;
case "audio":
return (
<AudioAttachment src={src} filename={filename} className={className} />
);
case "video":
return <VideoAttachment src={src} className={className} />;
case "document":
return (
<DocumentAttachment
source={source}
filename={filename}
className={className}
/>
);
}
};
export default CopilotChatAttachmentRenderer;