@copilotz/chat-ui 0.3.2 → 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 CHANGED
@@ -85,8 +85,6 @@ var defaultChatConfig = {
85
85
  stopGenerationTooltip: "Stop generation",
86
86
  attachFiles: "Attach Files",
87
87
  attachFileTooltip: "Attach file",
88
- recordAudio: "Record Audio",
89
- recordAudioTooltip: "Record audio",
90
88
  voiceEnter: "Voice input",
91
89
  voiceExit: "Use keyboard",
92
90
  voiceTitle: "Voice",
@@ -177,7 +175,6 @@ var defaultChatConfig = {
177
175
  components: {}
178
176
  },
179
177
  voiceCompose: {
180
- enabled: false,
181
178
  defaultMode: "text",
182
179
  reviewMode: "manual",
183
180
  autoSendDelayMs: 5e3,
@@ -3850,61 +3847,6 @@ var AttachmentPreview = (0, import_react6.memo)(function AttachmentPreview2({ at
3850
3847
  attachment.fileName && attachment.kind !== "audio" && /* @__PURE__ */ (0, import_jsx_runtime23.jsx)("div", { className: "absolute bottom-0 left-0 right-0 bg-black/70 text-white text-xs p-1 rounded-b", children: /* @__PURE__ */ (0, import_jsx_runtime23.jsx)("p", { className: "truncate", children: attachment.fileName }) })
3851
3848
  ] }) });
3852
3849
  });
3853
- var AudioRecorder = (0, import_react6.memo)(function AudioRecorder2({ isRecording, onStartRecording, onStopRecording, onCancel, recordingDuration, config }) {
3854
- const formatTime = (seconds) => {
3855
- const mins = Math.floor(seconds / 60);
3856
- const secs = seconds % 60;
3857
- return `${mins}:${secs.toString().padStart(2, "0")}`;
3858
- };
3859
- if (!isRecording) {
3860
- return /* @__PURE__ */ (0, import_jsx_runtime23.jsxs)(Tooltip, { children: [
3861
- /* @__PURE__ */ (0, import_jsx_runtime23.jsx)(TooltipTrigger, { asChild: true, children: /* @__PURE__ */ (0, import_jsx_runtime23.jsx)(
3862
- Button,
3863
- {
3864
- variant: "outline",
3865
- size: "icon",
3866
- onClick: onStartRecording,
3867
- className: "h-10 w-10",
3868
- children: /* @__PURE__ */ (0, import_jsx_runtime23.jsx)(import_lucide_react11.Mic, { className: "h-4 w-4" })
3869
- }
3870
- ) }),
3871
- /* @__PURE__ */ (0, import_jsx_runtime23.jsx)(TooltipContent, { children: config?.labels?.recordAudioTooltip })
3872
- ] });
3873
- }
3874
- return /* @__PURE__ */ (0, import_jsx_runtime23.jsx)(Card, { className: "border-red-200 bg-red-50 dark:border-red-800 dark:bg-red-950", children: /* @__PURE__ */ (0, import_jsx_runtime23.jsx)(CardContent, { className: "p-3", children: /* @__PURE__ */ (0, import_jsx_runtime23.jsxs)("div", { className: "flex items-center gap-3", children: [
3875
- /* @__PURE__ */ (0, import_jsx_runtime23.jsxs)("div", { className: "flex items-center gap-2", children: [
3876
- /* @__PURE__ */ (0, import_jsx_runtime23.jsx)("div", { className: "h-3 w-3 bg-red-500 rounded-full animate-pulse" }),
3877
- /* @__PURE__ */ (0, import_jsx_runtime23.jsx)("span", { className: "text-sm font-medium text-red-700 dark:text-red-300", children: config?.labels?.voiceListening || "Recording" })
3878
- ] }),
3879
- /* @__PURE__ */ (0, import_jsx_runtime23.jsx)(Badge, { variant: "outline", className: "text-xs", children: formatTime(recordingDuration) }),
3880
- /* @__PURE__ */ (0, import_jsx_runtime23.jsxs)("div", { className: "flex gap-1 ml-auto", children: [
3881
- /* @__PURE__ */ (0, import_jsx_runtime23.jsxs)(
3882
- Button,
3883
- {
3884
- variant: "outline",
3885
- size: "sm",
3886
- onClick: onCancel,
3887
- children: [
3888
- /* @__PURE__ */ (0, import_jsx_runtime23.jsx)(import_lucide_react11.X, { className: "h-3 w-3 mr-1" }),
3889
- config?.labels?.cancel || "Cancel"
3890
- ]
3891
- }
3892
- ),
3893
- /* @__PURE__ */ (0, import_jsx_runtime23.jsxs)(
3894
- Button,
3895
- {
3896
- variant: "default",
3897
- size: "sm",
3898
- onClick: onStopRecording,
3899
- children: [
3900
- /* @__PURE__ */ (0, import_jsx_runtime23.jsx)(import_lucide_react11.Square, { className: "h-3 w-3 mr-1" }),
3901
- config?.labels?.voiceStop || "Stop"
3902
- ]
3903
- }
3904
- )
3905
- ] })
3906
- ] }) }) });
3907
- });
3908
3850
  var resolveVoiceErrorMessage = (error, config) => {
3909
3851
  if (error instanceof DOMException && error.name === "NotAllowedError") {
3910
3852
  return config?.labels?.voicePermissionDenied || "Microphone access was denied.";
@@ -3937,7 +3879,6 @@ var ChatInput = (0, import_react6.memo)(function ChatInput2({
3937
3879
  mentionAgents = [],
3938
3880
  onTargetAgentChange
3939
3881
  }) {
3940
- const voiceComposeEnabled = config?.voiceCompose?.enabled === true;
3941
3882
  const voiceDefaultMode = config?.voiceCompose?.defaultMode ?? "text";
3942
3883
  const voiceReviewMode = config?.voiceCompose?.reviewMode ?? "manual";
3943
3884
  const voiceAutoSendDelayMs = config?.voiceCompose?.autoSendDelayMs ?? 5e3;
@@ -3945,12 +3886,10 @@ var ChatInput = (0, import_react6.memo)(function ChatInput2({
3945
3886
  const voiceShowTranscriptPreview = config?.voiceCompose?.showTranscriptPreview ?? true;
3946
3887
  const voiceTranscriptMode = config?.voiceCompose?.transcriptMode ?? "final-only";
3947
3888
  const voiceMaxRecordingMs = config?.voiceCompose?.maxRecordingMs;
3948
- const [isRecording, setIsRecording] = (0, import_react6.useState)(false);
3949
3889
  const { setContext } = useChatUserContext();
3950
- const [recordingDuration, setRecordingDuration] = (0, import_react6.useState)(0);
3951
3890
  const [uploadProgress, setUploadProgress] = (0, import_react6.useState)(/* @__PURE__ */ new Map());
3952
3891
  const [isVoiceComposerOpen, setIsVoiceComposerOpen] = (0, import_react6.useState)(
3953
- () => voiceComposeEnabled && voiceDefaultMode === "voice"
3892
+ () => enableAudioRecording && voiceDefaultMode === "voice"
3954
3893
  );
3955
3894
  const [voiceState, setVoiceState] = (0, import_react6.useState)("idle");
3956
3895
  const [voiceDraft, setVoiceDraft] = (0, import_react6.useState)(null);
@@ -3964,10 +3903,6 @@ var ChatInput = (0, import_react6.memo)(function ChatInput2({
3964
3903
  const [activeMentionIndex, setActiveMentionIndex] = (0, import_react6.useState)(0);
3965
3904
  const textareaRef = (0, import_react6.useRef)(null);
3966
3905
  const fileInputRef = (0, import_react6.useRef)(null);
3967
- const mediaRecorderRef = (0, import_react6.useRef)(null);
3968
- const recordingStartTime = (0, import_react6.useRef)(0);
3969
- const recordingInterval = (0, import_react6.useRef)(null);
3970
- const mediaStreamRef = (0, import_react6.useRef)(null);
3971
3906
  const voiceProviderRef = (0, import_react6.useRef)(null);
3972
3907
  const voiceDraftRef = (0, import_react6.useRef)(null);
3973
3908
  const voiceAppendBaseRef = (0, import_react6.useRef)(null);
@@ -4003,12 +3938,6 @@ var ChatInput = (0, import_react6.memo)(function ChatInput2({
4003
3938
  }, []);
4004
3939
  (0, import_react6.useEffect)(() => {
4005
3940
  return () => {
4006
- if (mediaStreamRef.current) {
4007
- mediaStreamRef.current.getTracks().forEach((track) => track.stop());
4008
- }
4009
- if (recordingInterval.current) {
4010
- clearInterval(recordingInterval.current);
4011
- }
4012
3941
  if (voiceProviderRef.current) {
4013
3942
  void voiceProviderRef.current.destroy();
4014
3943
  voiceProviderRef.current = null;
@@ -4181,73 +4110,6 @@ var ChatInput = (0, import_react6.memo)(function ChatInput2({
4181
4110
  const handleDragOver = (0, import_react6.useCallback)((e) => {
4182
4111
  e.preventDefault();
4183
4112
  }, []);
4184
- const startRecording = async () => {
4185
- try {
4186
- const stream = await navigator.mediaDevices.getUserMedia({ audio: true });
4187
- mediaStreamRef.current = stream;
4188
- const mediaRecorder = new MediaRecorder(stream);
4189
- mediaRecorderRef.current = mediaRecorder;
4190
- const chunks = [];
4191
- mediaRecorder.ondataavailable = (e) => {
4192
- chunks.push(e.data);
4193
- };
4194
- mediaRecorder.onstop = async () => {
4195
- const blob = new Blob(chunks, { type: "audio/webm" });
4196
- const dataUrl = await new Promise((resolve, reject) => {
4197
- const reader = new FileReader();
4198
- reader.onload = () => resolve(reader.result);
4199
- reader.onerror = reject;
4200
- reader.readAsDataURL(blob);
4201
- });
4202
- const attachment = {
4203
- kind: "audio",
4204
- dataUrl,
4205
- mimeType: blob.type,
4206
- durationMs: recordingDuration * 1e3,
4207
- fileName: `audio_${(/* @__PURE__ */ new Date()).toISOString().slice(0, 19)}.webm`,
4208
- size: blob.size
4209
- };
4210
- onAttachmentsChange([...attachments, attachment]);
4211
- if (mediaStreamRef.current) {
4212
- mediaStreamRef.current.getTracks().forEach((track) => track.stop());
4213
- mediaStreamRef.current = null;
4214
- }
4215
- };
4216
- recordingStartTime.current = Date.now();
4217
- setRecordingDuration(0);
4218
- setIsRecording(true);
4219
- mediaRecorder.start();
4220
- recordingInterval.current = setInterval(() => {
4221
- const duration = Math.floor((Date.now() - recordingStartTime.current) / 1e3);
4222
- setRecordingDuration(duration);
4223
- }, 1e3);
4224
- } catch (error) {
4225
- console.error("Error starting recording:", error);
4226
- alert(config?.labels?.voicePermissionDenied || "Microphone access was denied.");
4227
- }
4228
- };
4229
- const stopRecording = () => {
4230
- if (mediaRecorderRef.current && isRecording) {
4231
- mediaRecorderRef.current.stop();
4232
- setIsRecording(false);
4233
- if (recordingInterval.current) {
4234
- clearInterval(recordingInterval.current);
4235
- }
4236
- }
4237
- };
4238
- const cancelRecording = () => {
4239
- if (mediaRecorderRef.current && isRecording) {
4240
- mediaRecorderRef.current.stop();
4241
- setIsRecording(false);
4242
- if (recordingInterval.current) {
4243
- clearInterval(recordingInterval.current);
4244
- }
4245
- if (mediaStreamRef.current) {
4246
- mediaStreamRef.current.getTracks().forEach((track) => track.stop());
4247
- mediaStreamRef.current = null;
4248
- }
4249
- }
4250
- };
4251
4113
  const resetVoiceComposerState = (0, import_react6.useCallback)((nextState = "idle") => {
4252
4114
  setVoiceState(nextState);
4253
4115
  setVoiceDraft(null);
@@ -4532,7 +4394,7 @@ var ChatInput = (0, import_react6.memo)(function ChatInput2({
4532
4394
  onAttachmentsChange(newAttachments);
4533
4395
  };
4534
4396
  const canAddMoreAttachments = attachments.length < maxAttachments;
4535
- const showVoiceComposer = voiceComposeEnabled && isVoiceComposerOpen;
4397
+ const showVoiceComposer = enableAudioRecording && isVoiceComposerOpen;
4536
4398
  return /* @__PURE__ */ (0, import_jsx_runtime23.jsx)(TooltipProvider, { children: /* @__PURE__ */ (0, import_jsx_runtime23.jsx)("div", { className: `border-t py-0 bg-transparent ${className}`, children: /* @__PURE__ */ (0, import_jsx_runtime23.jsxs)("div", { className: "px-0 md:p-2 pb-1 space-y-4 bg-transparent", children: [
4537
4399
  uploadProgress.size > 0 && /* @__PURE__ */ (0, import_jsx_runtime23.jsx)("div", { className: "space-y-2", children: Array.from(uploadProgress.entries()).map(([id, progress]) => /* @__PURE__ */ (0, import_jsx_runtime23.jsx)(
4538
4400
  FileUploadItem,
@@ -4549,17 +4411,6 @@ var ChatInput = (0, import_react6.memo)(function ChatInput2({
4549
4411
  },
4550
4412
  id
4551
4413
  )) }),
4552
- isRecording && /* @__PURE__ */ (0, import_jsx_runtime23.jsx)(
4553
- AudioRecorder,
4554
- {
4555
- isRecording,
4556
- onStartRecording: startRecording,
4557
- onStopRecording: stopRecording,
4558
- onCancel: cancelRecording,
4559
- recordingDuration,
4560
- config
4561
- }
4562
- ),
4563
4414
  attachments.length > 0 && /* @__PURE__ */ (0, import_jsx_runtime23.jsx)("div", { className: "grid grid-cols-4 gap-2", children: attachments.map((attachment, index) => /* @__PURE__ */ (0, import_jsx_runtime23.jsx)(
4564
4415
  AttachmentPreview,
4565
4416
  {
@@ -4689,7 +4540,7 @@ var ChatInput = (0, import_react6.memo)(function ChatInput2({
4689
4540
  agent.id
4690
4541
  )) }) })
4691
4542
  ] }),
4692
- enableAudioRecording && !isRecording && canAddMoreAttachments && !value.trim() && (voiceComposeEnabled ? /* @__PURE__ */ (0, import_jsx_runtime23.jsxs)(Tooltip, { children: [
4543
+ enableAudioRecording && canAddMoreAttachments && !value.trim() && /* @__PURE__ */ (0, import_jsx_runtime23.jsxs)(Tooltip, { children: [
4693
4544
  /* @__PURE__ */ (0, import_jsx_runtime23.jsx)(TooltipTrigger, { asChild: true, children: /* @__PURE__ */ (0, import_jsx_runtime23.jsx)(
4694
4545
  Button,
4695
4546
  {
@@ -4704,18 +4555,8 @@ var ChatInput = (0, import_react6.memo)(function ChatInput2({
4704
4555
  children: /* @__PURE__ */ (0, import_jsx_runtime23.jsx)(import_lucide_react11.Mic, { className: "h-4 w-4" })
4705
4556
  }
4706
4557
  ) }),
4707
- /* @__PURE__ */ (0, import_jsx_runtime23.jsx)(TooltipContent, { children: config?.labels?.voiceEnter || config?.labels?.recordAudioTooltip })
4708
- ] }) : /* @__PURE__ */ (0, import_jsx_runtime23.jsx)(
4709
- AudioRecorder,
4710
- {
4711
- isRecording,
4712
- onStartRecording: startRecording,
4713
- onStopRecording: stopRecording,
4714
- onCancel: cancelRecording,
4715
- recordingDuration,
4716
- config
4717
- }
4718
- )),
4558
+ /* @__PURE__ */ (0, import_jsx_runtime23.jsx)(TooltipContent, { children: config?.labels?.voiceEnter })
4559
+ ] }),
4719
4560
  isGenerating ? /* @__PURE__ */ (0, import_jsx_runtime23.jsxs)(Tooltip, { children: [
4720
4561
  /* @__PURE__ */ (0, import_jsx_runtime23.jsx)(TooltipTrigger, { asChild: true, children: /* @__PURE__ */ (0, import_jsx_runtime23.jsx)(
4721
4562
  Button,