@copilotkit/react-ui 1.55.0-next.9 → 1.55.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.
@@ -0,0 +1,125 @@
1
+ import React from "react";
2
+ import type { Attachment } from "./props";
3
+ import {
4
+ formatFileSize,
5
+ getSourceUrl,
6
+ getDocumentIcon,
7
+ } from "@copilotkit/shared";
8
+
9
+ interface AttachmentQueueProps {
10
+ attachments: Attachment[];
11
+ onRemoveAttachment: (id: string) => void;
12
+ className?: string;
13
+ }
14
+
15
+ export const AttachmentQueue: React.FC<AttachmentQueueProps> = ({
16
+ attachments,
17
+ onRemoveAttachment,
18
+ className = "",
19
+ }) => {
20
+ if (attachments.length === 0) return null;
21
+
22
+ return (
23
+ <div className={`copilotKitAttachmentQueue ${className}`}>
24
+ {attachments.map((attachment) => (
25
+ <div
26
+ key={attachment.id}
27
+ className={`copilotKitAttachmentQueueItem copilotKitAttachmentQueueItem--${attachment.type}`}
28
+ >
29
+ {attachment.status === "uploading" && (
30
+ <div className="copilotKitAttachmentQueueOverlay">
31
+ <div className="copilotKitAttachmentQueueSpinner" />
32
+ </div>
33
+ )}
34
+ <AttachmentPreview attachment={attachment} />
35
+ <button
36
+ onClick={() => onRemoveAttachment(attachment.id)}
37
+ className="copilotKitAttachmentQueueRemoveButton"
38
+ aria-label="Remove attachment"
39
+ >
40
+
41
+ </button>
42
+ </div>
43
+ ))}
44
+ </div>
45
+ );
46
+ };
47
+
48
+ function AttachmentPreview({ attachment }: { attachment: Attachment }) {
49
+ if (attachment.status === "uploading") {
50
+ return <div className="copilotKitAttachmentQueuePreviewPlaceholder" />;
51
+ }
52
+
53
+ const src = getSourceUrl(attachment.source);
54
+
55
+ switch (attachment.type) {
56
+ case "image":
57
+ return (
58
+ <img
59
+ src={src}
60
+ alt={attachment.filename || "Image attachment"}
61
+ className="copilotKitAttachmentQueuePreviewImage"
62
+ />
63
+ );
64
+
65
+ case "audio":
66
+ return (
67
+ <div className="copilotKitAttachmentQueuePreviewAudio">
68
+ <audio src={src} controls preload="metadata" />
69
+ {attachment.filename && (
70
+ <span className="copilotKitAttachmentQueueFilename">
71
+ {attachment.filename}
72
+ </span>
73
+ )}
74
+ </div>
75
+ );
76
+
77
+ case "video":
78
+ return (
79
+ <div className="copilotKitAttachmentQueuePreviewVideo">
80
+ {attachment.thumbnail ? (
81
+ <img
82
+ src={attachment.thumbnail}
83
+ alt={attachment.filename || "Video thumbnail"}
84
+ className="copilotKitAttachmentQueuePreviewImage"
85
+ />
86
+ ) : (
87
+ <video
88
+ src={src}
89
+ preload="metadata"
90
+ muted
91
+ className="copilotKitAttachmentQueuePreviewImage"
92
+ />
93
+ )}
94
+ </div>
95
+ );
96
+
97
+ case "document":
98
+ return (
99
+ <div className="copilotKitAttachmentQueuePreviewDocument">
100
+ <div className="copilotKitAttachmentQueueDocIcon">
101
+ {getDocumentIcon(attachment.source.mimeType ?? "")}
102
+ </div>
103
+ <div className="copilotKitAttachmentQueueDocInfo">
104
+ <span className="copilotKitAttachmentQueueFilename">
105
+ {attachment.filename || "Document"}
106
+ </span>
107
+ {attachment.size != null && (
108
+ <span className="copilotKitAttachmentQueueFileSize">
109
+ {formatFileSize(attachment.size)}
110
+ </span>
111
+ )}
112
+ </div>
113
+ </div>
114
+ );
115
+ }
116
+ }
117
+
118
+ /**
119
+ * @deprecated Use `AttachmentQueue` from `@copilotkit/react-ui` instead.
120
+ * `ImageUploadQueue` only displayed image previews. `AttachmentQueue` supports
121
+ * images, audio, video, and documents.
122
+ * See https://docs.copilotkit.ai/migration-guides/migrate-attachments
123
+ * @since 1.56.0
124
+ */
125
+ export { AttachmentQueue as ImageUploadQueue };
@@ -0,0 +1,133 @@
1
+ import React, { memo, useState } from "react";
2
+ import type { InputContentSource } from "@copilotkit/shared";
3
+ import { getSourceUrl, getDocumentIcon } from "@copilotkit/shared";
4
+
5
+ interface AttachmentRendererProps {
6
+ type: "image" | "audio" | "video" | "document";
7
+ source: InputContentSource;
8
+ filename?: string;
9
+ className?: string;
10
+ }
11
+
12
+ const ImageAttachment = memo(function ImageAttachment({
13
+ src,
14
+ className,
15
+ }: {
16
+ src: string;
17
+ className?: string;
18
+ }) {
19
+ const [error, setError] = useState(false);
20
+
21
+ if (error) {
22
+ return (
23
+ <div
24
+ className={`copilotKitImageRendering copilotKitImageRenderingError ${className ?? ""}`}
25
+ >
26
+ <div className="copilotKitImageRenderingErrorMessage">
27
+ Failed to load image
28
+ </div>
29
+ </div>
30
+ );
31
+ }
32
+
33
+ return (
34
+ <div className={`copilotKitImageRendering ${className ?? ""}`}>
35
+ <img
36
+ src={src}
37
+ alt="Image attachment"
38
+ className="copilotKitImageRenderingImage"
39
+ onError={() => setError(true)}
40
+ />
41
+ </div>
42
+ );
43
+ });
44
+
45
+ const AudioAttachment = memo(function AudioAttachment({
46
+ src,
47
+ filename,
48
+ className,
49
+ }: {
50
+ src: string;
51
+ filename?: string;
52
+ className?: string;
53
+ }) {
54
+ return (
55
+ <div
56
+ className={`copilotKitAttachment copilotKitAttachmentAudio ${className ?? ""}`}
57
+ >
58
+ <audio src={src} controls preload="metadata" />
59
+ {filename && (
60
+ <span className="copilotKitAttachmentFilename">{filename}</span>
61
+ )}
62
+ </div>
63
+ );
64
+ });
65
+
66
+ const VideoAttachment = memo(function VideoAttachment({
67
+ src,
68
+ className,
69
+ }: {
70
+ src: string;
71
+ className?: string;
72
+ }) {
73
+ return (
74
+ <div
75
+ className={`copilotKitAttachment copilotKitAttachmentVideo ${className ?? ""}`}
76
+ >
77
+ <video src={src} controls preload="metadata" />
78
+ </div>
79
+ );
80
+ });
81
+
82
+ const DocumentAttachment = memo(function DocumentAttachment({
83
+ source,
84
+ filename,
85
+ className,
86
+ }: {
87
+ source: InputContentSource;
88
+ filename?: string;
89
+ className?: string;
90
+ }) {
91
+ return (
92
+ <div
93
+ className={`copilotKitAttachment copilotKitAttachmentDocument ${className ?? ""}`}
94
+ >
95
+ <div className="copilotKitAttachmentDocIcon">
96
+ {getDocumentIcon(source.mimeType ?? "")}
97
+ </div>
98
+ <div className="copilotKitAttachmentDocInfo">
99
+ <span className="copilotKitAttachmentDocName">
100
+ {filename || source.mimeType || "Unknown type"}
101
+ </span>
102
+ </div>
103
+ </div>
104
+ );
105
+ });
106
+
107
+ export const AttachmentRenderer: React.FC<AttachmentRendererProps> = ({
108
+ type,
109
+ source,
110
+ filename,
111
+ className,
112
+ }) => {
113
+ const src = getSourceUrl(source);
114
+
115
+ switch (type) {
116
+ case "image":
117
+ return <ImageAttachment src={src} className={className} />;
118
+ case "audio":
119
+ return (
120
+ <AudioAttachment src={src} filename={filename} className={className} />
121
+ );
122
+ case "video":
123
+ return <VideoAttachment src={src} className={className} />;
124
+ case "document":
125
+ return (
126
+ <DocumentAttachment
127
+ source={source}
128
+ filename={filename}
129
+ className={className}
130
+ />
131
+ );
132
+ }
133
+ };