@copilotz/chat-ui 0.3.1 → 0.3.3
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/dist/index.cjs +16 -165
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +0 -3
- package/dist/index.d.ts +0 -3
- package/dist/index.js +16 -165
- package/dist/index.js.map +1 -1
- package/dist/styles.css +0 -12
- package/package.json +1 -1
package/dist/index.d.cts
CHANGED
|
@@ -131,8 +131,6 @@ interface ChatConfig {
|
|
|
131
131
|
stopGenerationTooltip?: string;
|
|
132
132
|
attachFiles?: string;
|
|
133
133
|
attachFileTooltip?: string;
|
|
134
|
-
recordAudio?: string;
|
|
135
|
-
recordAudioTooltip?: string;
|
|
136
134
|
voiceEnter?: string;
|
|
137
135
|
voiceExit?: string;
|
|
138
136
|
voiceTitle?: string;
|
|
@@ -216,7 +214,6 @@ interface ChatConfig {
|
|
|
216
214
|
};
|
|
217
215
|
markdown?: ChatMarkdownConfig;
|
|
218
216
|
voiceCompose?: {
|
|
219
|
-
enabled?: boolean;
|
|
220
217
|
defaultMode?: 'text' | 'voice';
|
|
221
218
|
reviewMode?: VoiceReviewMode;
|
|
222
219
|
autoSendDelayMs?: number;
|
package/dist/index.d.ts
CHANGED
|
@@ -131,8 +131,6 @@ interface ChatConfig {
|
|
|
131
131
|
stopGenerationTooltip?: string;
|
|
132
132
|
attachFiles?: string;
|
|
133
133
|
attachFileTooltip?: string;
|
|
134
|
-
recordAudio?: string;
|
|
135
|
-
recordAudioTooltip?: string;
|
|
136
134
|
voiceEnter?: string;
|
|
137
135
|
voiceExit?: string;
|
|
138
136
|
voiceTitle?: string;
|
|
@@ -216,7 +214,6 @@ interface ChatConfig {
|
|
|
216
214
|
};
|
|
217
215
|
markdown?: ChatMarkdownConfig;
|
|
218
216
|
voiceCompose?: {
|
|
219
|
-
enabled?: boolean;
|
|
220
217
|
defaultMode?: 'text' | 'voice';
|
|
221
218
|
reviewMode?: VoiceReviewMode;
|
|
222
219
|
autoSendDelayMs?: number;
|
package/dist/index.js
CHANGED
|
@@ -28,8 +28,6 @@ var defaultChatConfig = {
|
|
|
28
28
|
stopGenerationTooltip: "Stop generation",
|
|
29
29
|
attachFiles: "Attach Files",
|
|
30
30
|
attachFileTooltip: "Attach file",
|
|
31
|
-
recordAudio: "Record Audio",
|
|
32
|
-
recordAudioTooltip: "Record audio",
|
|
33
31
|
voiceEnter: "Voice input",
|
|
34
32
|
voiceExit: "Use keyboard",
|
|
35
33
|
voiceTitle: "Voice",
|
|
@@ -120,7 +118,6 @@ var defaultChatConfig = {
|
|
|
120
118
|
components: {}
|
|
121
119
|
},
|
|
122
120
|
voiceCompose: {
|
|
123
|
-
enabled: false,
|
|
124
121
|
defaultMode: "text",
|
|
125
122
|
reviewMode: "manual",
|
|
126
123
|
autoSendDelayMs: 5e3,
|
|
@@ -3845,61 +3842,6 @@ var AttachmentPreview = memo3(function AttachmentPreview2({ attachment, onRemove
|
|
|
3845
3842
|
attachment.fileName && attachment.kind !== "audio" && /* @__PURE__ */ jsx23("div", { className: "absolute bottom-0 left-0 right-0 bg-black/70 text-white text-xs p-1 rounded-b", children: /* @__PURE__ */ jsx23("p", { className: "truncate", children: attachment.fileName }) })
|
|
3846
3843
|
] }) });
|
|
3847
3844
|
});
|
|
3848
|
-
var AudioRecorder = memo3(function AudioRecorder2({ isRecording, onStartRecording, onStopRecording, onCancel, recordingDuration, config }) {
|
|
3849
|
-
const formatTime = (seconds) => {
|
|
3850
|
-
const mins = Math.floor(seconds / 60);
|
|
3851
|
-
const secs = seconds % 60;
|
|
3852
|
-
return `${mins}:${secs.toString().padStart(2, "0")}`;
|
|
3853
|
-
};
|
|
3854
|
-
if (!isRecording) {
|
|
3855
|
-
return /* @__PURE__ */ jsxs13(Tooltip, { children: [
|
|
3856
|
-
/* @__PURE__ */ jsx23(TooltipTrigger, { asChild: true, children: /* @__PURE__ */ jsx23(
|
|
3857
|
-
Button,
|
|
3858
|
-
{
|
|
3859
|
-
variant: "outline",
|
|
3860
|
-
size: "icon",
|
|
3861
|
-
onClick: onStartRecording,
|
|
3862
|
-
className: "h-10 w-10",
|
|
3863
|
-
children: /* @__PURE__ */ jsx23(Mic2, { className: "h-4 w-4" })
|
|
3864
|
-
}
|
|
3865
|
-
) }),
|
|
3866
|
-
/* @__PURE__ */ jsx23(TooltipContent, { children: config?.labels?.recordAudioTooltip })
|
|
3867
|
-
] });
|
|
3868
|
-
}
|
|
3869
|
-
return /* @__PURE__ */ jsx23(Card, { className: "border-red-200 bg-red-50 dark:border-red-800 dark:bg-red-950", children: /* @__PURE__ */ jsx23(CardContent, { className: "p-3", children: /* @__PURE__ */ jsxs13("div", { className: "flex items-center gap-3", children: [
|
|
3870
|
-
/* @__PURE__ */ jsxs13("div", { className: "flex items-center gap-2", children: [
|
|
3871
|
-
/* @__PURE__ */ jsx23("div", { className: "h-3 w-3 bg-red-500 rounded-full animate-pulse" }),
|
|
3872
|
-
/* @__PURE__ */ jsx23("span", { className: "text-sm font-medium text-red-700 dark:text-red-300", children: config?.labels?.voiceListening || "Recording" })
|
|
3873
|
-
] }),
|
|
3874
|
-
/* @__PURE__ */ jsx23(Badge, { variant: "outline", className: "text-xs", children: formatTime(recordingDuration) }),
|
|
3875
|
-
/* @__PURE__ */ jsxs13("div", { className: "flex gap-1 ml-auto", children: [
|
|
3876
|
-
/* @__PURE__ */ jsxs13(
|
|
3877
|
-
Button,
|
|
3878
|
-
{
|
|
3879
|
-
variant: "outline",
|
|
3880
|
-
size: "sm",
|
|
3881
|
-
onClick: onCancel,
|
|
3882
|
-
children: [
|
|
3883
|
-
/* @__PURE__ */ jsx23(X4, { className: "h-3 w-3 mr-1" }),
|
|
3884
|
-
config?.labels?.cancel || "Cancel"
|
|
3885
|
-
]
|
|
3886
|
-
}
|
|
3887
|
-
),
|
|
3888
|
-
/* @__PURE__ */ jsxs13(
|
|
3889
|
-
Button,
|
|
3890
|
-
{
|
|
3891
|
-
variant: "default",
|
|
3892
|
-
size: "sm",
|
|
3893
|
-
onClick: onStopRecording,
|
|
3894
|
-
children: [
|
|
3895
|
-
/* @__PURE__ */ jsx23(Square2, { className: "h-3 w-3 mr-1" }),
|
|
3896
|
-
config?.labels?.voiceStop || "Stop"
|
|
3897
|
-
]
|
|
3898
|
-
}
|
|
3899
|
-
)
|
|
3900
|
-
] })
|
|
3901
|
-
] }) }) });
|
|
3902
|
-
});
|
|
3903
3845
|
var resolveVoiceErrorMessage = (error, config) => {
|
|
3904
3846
|
if (error instanceof DOMException && error.name === "NotAllowedError") {
|
|
3905
3847
|
return config?.labels?.voicePermissionDenied || "Microphone access was denied.";
|
|
@@ -3932,7 +3874,6 @@ var ChatInput = memo3(function ChatInput2({
|
|
|
3932
3874
|
mentionAgents = [],
|
|
3933
3875
|
onTargetAgentChange
|
|
3934
3876
|
}) {
|
|
3935
|
-
const voiceComposeEnabled = config?.voiceCompose?.enabled === true;
|
|
3936
3877
|
const voiceDefaultMode = config?.voiceCompose?.defaultMode ?? "text";
|
|
3937
3878
|
const voiceReviewMode = config?.voiceCompose?.reviewMode ?? "manual";
|
|
3938
3879
|
const voiceAutoSendDelayMs = config?.voiceCompose?.autoSendDelayMs ?? 5e3;
|
|
@@ -3940,12 +3881,10 @@ var ChatInput = memo3(function ChatInput2({
|
|
|
3940
3881
|
const voiceShowTranscriptPreview = config?.voiceCompose?.showTranscriptPreview ?? true;
|
|
3941
3882
|
const voiceTranscriptMode = config?.voiceCompose?.transcriptMode ?? "final-only";
|
|
3942
3883
|
const voiceMaxRecordingMs = config?.voiceCompose?.maxRecordingMs;
|
|
3943
|
-
const [isRecording, setIsRecording] = useState6(false);
|
|
3944
3884
|
const { setContext } = useChatUserContext();
|
|
3945
|
-
const [recordingDuration, setRecordingDuration] = useState6(0);
|
|
3946
3885
|
const [uploadProgress, setUploadProgress] = useState6(/* @__PURE__ */ new Map());
|
|
3947
3886
|
const [isVoiceComposerOpen, setIsVoiceComposerOpen] = useState6(
|
|
3948
|
-
() =>
|
|
3887
|
+
() => enableAudioRecording && voiceDefaultMode === "voice"
|
|
3949
3888
|
);
|
|
3950
3889
|
const [voiceState, setVoiceState] = useState6("idle");
|
|
3951
3890
|
const [voiceDraft, setVoiceDraft] = useState6(null);
|
|
@@ -3959,10 +3898,6 @@ var ChatInput = memo3(function ChatInput2({
|
|
|
3959
3898
|
const [activeMentionIndex, setActiveMentionIndex] = useState6(0);
|
|
3960
3899
|
const textareaRef = useRef5(null);
|
|
3961
3900
|
const fileInputRef = useRef5(null);
|
|
3962
|
-
const mediaRecorderRef = useRef5(null);
|
|
3963
|
-
const recordingStartTime = useRef5(0);
|
|
3964
|
-
const recordingInterval = useRef5(null);
|
|
3965
|
-
const mediaStreamRef = useRef5(null);
|
|
3966
3901
|
const voiceProviderRef = useRef5(null);
|
|
3967
3902
|
const voiceDraftRef = useRef5(null);
|
|
3968
3903
|
const voiceAppendBaseRef = useRef5(null);
|
|
@@ -3998,12 +3933,6 @@ var ChatInput = memo3(function ChatInput2({
|
|
|
3998
3933
|
}, []);
|
|
3999
3934
|
useEffect9(() => {
|
|
4000
3935
|
return () => {
|
|
4001
|
-
if (mediaStreamRef.current) {
|
|
4002
|
-
mediaStreamRef.current.getTracks().forEach((track) => track.stop());
|
|
4003
|
-
}
|
|
4004
|
-
if (recordingInterval.current) {
|
|
4005
|
-
clearInterval(recordingInterval.current);
|
|
4006
|
-
}
|
|
4007
3936
|
if (voiceProviderRef.current) {
|
|
4008
3937
|
void voiceProviderRef.current.destroy();
|
|
4009
3938
|
voiceProviderRef.current = null;
|
|
@@ -4176,73 +4105,6 @@ var ChatInput = memo3(function ChatInput2({
|
|
|
4176
4105
|
const handleDragOver = useCallback3((e) => {
|
|
4177
4106
|
e.preventDefault();
|
|
4178
4107
|
}, []);
|
|
4179
|
-
const startRecording = async () => {
|
|
4180
|
-
try {
|
|
4181
|
-
const stream = await navigator.mediaDevices.getUserMedia({ audio: true });
|
|
4182
|
-
mediaStreamRef.current = stream;
|
|
4183
|
-
const mediaRecorder = new MediaRecorder(stream);
|
|
4184
|
-
mediaRecorderRef.current = mediaRecorder;
|
|
4185
|
-
const chunks = [];
|
|
4186
|
-
mediaRecorder.ondataavailable = (e) => {
|
|
4187
|
-
chunks.push(e.data);
|
|
4188
|
-
};
|
|
4189
|
-
mediaRecorder.onstop = async () => {
|
|
4190
|
-
const blob = new Blob(chunks, { type: "audio/webm" });
|
|
4191
|
-
const dataUrl = await new Promise((resolve, reject) => {
|
|
4192
|
-
const reader = new FileReader();
|
|
4193
|
-
reader.onload = () => resolve(reader.result);
|
|
4194
|
-
reader.onerror = reject;
|
|
4195
|
-
reader.readAsDataURL(blob);
|
|
4196
|
-
});
|
|
4197
|
-
const attachment = {
|
|
4198
|
-
kind: "audio",
|
|
4199
|
-
dataUrl,
|
|
4200
|
-
mimeType: blob.type,
|
|
4201
|
-
durationMs: recordingDuration * 1e3,
|
|
4202
|
-
fileName: `audio_${(/* @__PURE__ */ new Date()).toISOString().slice(0, 19)}.webm`,
|
|
4203
|
-
size: blob.size
|
|
4204
|
-
};
|
|
4205
|
-
onAttachmentsChange([...attachments, attachment]);
|
|
4206
|
-
if (mediaStreamRef.current) {
|
|
4207
|
-
mediaStreamRef.current.getTracks().forEach((track) => track.stop());
|
|
4208
|
-
mediaStreamRef.current = null;
|
|
4209
|
-
}
|
|
4210
|
-
};
|
|
4211
|
-
recordingStartTime.current = Date.now();
|
|
4212
|
-
setRecordingDuration(0);
|
|
4213
|
-
setIsRecording(true);
|
|
4214
|
-
mediaRecorder.start();
|
|
4215
|
-
recordingInterval.current = setInterval(() => {
|
|
4216
|
-
const duration = Math.floor((Date.now() - recordingStartTime.current) / 1e3);
|
|
4217
|
-
setRecordingDuration(duration);
|
|
4218
|
-
}, 1e3);
|
|
4219
|
-
} catch (error) {
|
|
4220
|
-
console.error("Error starting recording:", error);
|
|
4221
|
-
alert(config?.labels?.voicePermissionDenied || "Microphone access was denied.");
|
|
4222
|
-
}
|
|
4223
|
-
};
|
|
4224
|
-
const stopRecording = () => {
|
|
4225
|
-
if (mediaRecorderRef.current && isRecording) {
|
|
4226
|
-
mediaRecorderRef.current.stop();
|
|
4227
|
-
setIsRecording(false);
|
|
4228
|
-
if (recordingInterval.current) {
|
|
4229
|
-
clearInterval(recordingInterval.current);
|
|
4230
|
-
}
|
|
4231
|
-
}
|
|
4232
|
-
};
|
|
4233
|
-
const cancelRecording = () => {
|
|
4234
|
-
if (mediaRecorderRef.current && isRecording) {
|
|
4235
|
-
mediaRecorderRef.current.stop();
|
|
4236
|
-
setIsRecording(false);
|
|
4237
|
-
if (recordingInterval.current) {
|
|
4238
|
-
clearInterval(recordingInterval.current);
|
|
4239
|
-
}
|
|
4240
|
-
if (mediaStreamRef.current) {
|
|
4241
|
-
mediaStreamRef.current.getTracks().forEach((track) => track.stop());
|
|
4242
|
-
mediaStreamRef.current = null;
|
|
4243
|
-
}
|
|
4244
|
-
}
|
|
4245
|
-
};
|
|
4246
4108
|
const resetVoiceComposerState = useCallback3((nextState = "idle") => {
|
|
4247
4109
|
setVoiceState(nextState);
|
|
4248
4110
|
setVoiceDraft(null);
|
|
@@ -4527,7 +4389,7 @@ var ChatInput = memo3(function ChatInput2({
|
|
|
4527
4389
|
onAttachmentsChange(newAttachments);
|
|
4528
4390
|
};
|
|
4529
4391
|
const canAddMoreAttachments = attachments.length < maxAttachments;
|
|
4530
|
-
const showVoiceComposer =
|
|
4392
|
+
const showVoiceComposer = enableAudioRecording && isVoiceComposerOpen;
|
|
4531
4393
|
return /* @__PURE__ */ jsx23(TooltipProvider, { children: /* @__PURE__ */ jsx23("div", { className: `border-t py-0 bg-transparent ${className}`, children: /* @__PURE__ */ jsxs13("div", { className: "px-0 md:p-2 pb-1 space-y-4 bg-transparent", children: [
|
|
4532
4394
|
uploadProgress.size > 0 && /* @__PURE__ */ jsx23("div", { className: "space-y-2", children: Array.from(uploadProgress.entries()).map(([id, progress]) => /* @__PURE__ */ jsx23(
|
|
4533
4395
|
FileUploadItem,
|
|
@@ -4544,17 +4406,6 @@ var ChatInput = memo3(function ChatInput2({
|
|
|
4544
4406
|
},
|
|
4545
4407
|
id
|
|
4546
4408
|
)) }),
|
|
4547
|
-
isRecording && /* @__PURE__ */ jsx23(
|
|
4548
|
-
AudioRecorder,
|
|
4549
|
-
{
|
|
4550
|
-
isRecording,
|
|
4551
|
-
onStartRecording: startRecording,
|
|
4552
|
-
onStopRecording: stopRecording,
|
|
4553
|
-
onCancel: cancelRecording,
|
|
4554
|
-
recordingDuration,
|
|
4555
|
-
config
|
|
4556
|
-
}
|
|
4557
|
-
),
|
|
4558
4409
|
attachments.length > 0 && /* @__PURE__ */ jsx23("div", { className: "grid grid-cols-4 gap-2", children: attachments.map((attachment, index) => /* @__PURE__ */ jsx23(
|
|
4559
4410
|
AttachmentPreview,
|
|
4560
4411
|
{
|
|
@@ -4684,7 +4535,7 @@ var ChatInput = memo3(function ChatInput2({
|
|
|
4684
4535
|
agent.id
|
|
4685
4536
|
)) }) })
|
|
4686
4537
|
] }),
|
|
4687
|
-
enableAudioRecording &&
|
|
4538
|
+
enableAudioRecording && canAddMoreAttachments && !value.trim() && /* @__PURE__ */ jsxs13(Tooltip, { children: [
|
|
4688
4539
|
/* @__PURE__ */ jsx23(TooltipTrigger, { asChild: true, children: /* @__PURE__ */ jsx23(
|
|
4689
4540
|
Button,
|
|
4690
4541
|
{
|
|
@@ -4699,18 +4550,8 @@ var ChatInput = memo3(function ChatInput2({
|
|
|
4699
4550
|
children: /* @__PURE__ */ jsx23(Mic2, { className: "h-4 w-4" })
|
|
4700
4551
|
}
|
|
4701
4552
|
) }),
|
|
4702
|
-
/* @__PURE__ */ jsx23(TooltipContent, { children: config?.labels?.voiceEnter
|
|
4703
|
-
] })
|
|
4704
|
-
AudioRecorder,
|
|
4705
|
-
{
|
|
4706
|
-
isRecording,
|
|
4707
|
-
onStartRecording: startRecording,
|
|
4708
|
-
onStopRecording: stopRecording,
|
|
4709
|
-
onCancel: cancelRecording,
|
|
4710
|
-
recordingDuration,
|
|
4711
|
-
config
|
|
4712
|
-
}
|
|
4713
|
-
)),
|
|
4553
|
+
/* @__PURE__ */ jsx23(TooltipContent, { children: config?.labels?.voiceEnter })
|
|
4554
|
+
] }),
|
|
4714
4555
|
isGenerating ? /* @__PURE__ */ jsxs13(Tooltip, { children: [
|
|
4715
4556
|
/* @__PURE__ */ jsx23(TooltipTrigger, { asChild: true, children: /* @__PURE__ */ jsx23(
|
|
4716
4557
|
Button,
|
|
@@ -5225,6 +5066,16 @@ var UserProfile = ({
|
|
|
5225
5066
|
// src/components/chat/ChatUI.tsx
|
|
5226
5067
|
import { Sparkles, ArrowRight, MessageSquare, Lightbulb as Lightbulb2, Zap, HelpCircle } from "lucide-react";
|
|
5227
5068
|
import { jsx as jsx26, jsxs as jsxs16 } from "react/jsx-runtime";
|
|
5069
|
+
function getMessageSpeakerKey(message) {
|
|
5070
|
+
if (!message) return null;
|
|
5071
|
+
if (message.role === "assistant") {
|
|
5072
|
+
return message.senderAgentId ?? message.senderName ?? "assistant";
|
|
5073
|
+
}
|
|
5074
|
+
if (message.role === "user") {
|
|
5075
|
+
return "user";
|
|
5076
|
+
}
|
|
5077
|
+
return message.role;
|
|
5078
|
+
}
|
|
5228
5079
|
var ChatUI = ({
|
|
5229
5080
|
messages = [],
|
|
5230
5081
|
threads = [],
|
|
@@ -5670,7 +5521,7 @@ var ChatUI = ({
|
|
|
5670
5521
|
children: virtualizer.getVirtualItems().map((virtualRow) => {
|
|
5671
5522
|
const message = messages[virtualRow.index];
|
|
5672
5523
|
const prevMessage = virtualRow.index > 0 ? messages[virtualRow.index - 1] : null;
|
|
5673
|
-
const isGrouped = prevMessage !== null && prevMessage.role === message.role;
|
|
5524
|
+
const isGrouped = prevMessage !== null && prevMessage.role === message.role && getMessageSpeakerKey(prevMessage) === getMessageSpeakerKey(message);
|
|
5674
5525
|
return /* @__PURE__ */ jsx26(
|
|
5675
5526
|
"div",
|
|
5676
5527
|
{
|