@copilotkit/react-ui 1.55.0-next.8 → 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.
- package/CHANGELOG.md +31 -3
- package/dist/index.cjs +429 -174
- package/dist/index.cjs.map +1 -1
- package/dist/index.css +334 -25
- package/dist/index.css.map +1 -1
- package/dist/index.d.cts +62 -6
- package/dist/index.d.cts.map +1 -1
- package/dist/index.d.mts +62 -6
- package/dist/index.d.mts.map +1 -1
- package/dist/index.mjs +430 -176
- package/dist/index.mjs.map +1 -1
- package/dist/index.umd.js +440 -179
- package/dist/index.umd.js.map +1 -1
- package/oxlint-rules/copilotkit-plugin.mjs +10 -0
- package/oxlint-rules/require-cpk-prefix.mjs +547 -0
- package/package.json +33 -34
- package/src/components/chat/AttachmentQueue.tsx +125 -0
- package/src/components/chat/AttachmentRenderer.tsx +133 -0
- package/src/components/chat/Chat.tsx +367 -149
- package/src/components/chat/Modal.tsx +1 -1
- package/src/components/chat/attachment-utils.ts +32 -0
- package/src/components/chat/index.tsx +1 -0
- package/src/components/chat/messages/ImageRenderer.tsx +20 -8
- package/src/components/chat/messages/UserMessage.tsx +42 -8
- package/src/components/chat/props.ts +25 -2
- package/src/css/attachments.css +227 -0
- package/src/css/colors.css +8 -4
- package/src/css/console.css +34 -9
- package/src/css/input.css +5 -2
- package/src/css/markdown.css +1 -1
- package/src/css/messages.css +11 -4
- package/src/css/popup.css +15 -3
- package/src/css/sidebar.css +28 -3
- package/src/css/suggestions.css +4 -2
- package/src/styles.css +2 -1
|
@@ -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
|
+
};
|