@copilotz/chat-ui 0.1.21 → 0.1.22

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.js CHANGED
@@ -1,5 +1,5 @@
1
1
  // src/components/chat/ChatUI.tsx
2
- import { useState as useState8, useEffect as useEffect10, useRef as useRef6, useCallback as useCallback4, useMemo as useMemo4 } from "react";
2
+ import { useState as useState8, useEffect as useEffect10, useRef as useRef7, useCallback as useCallback4, useMemo as useMemo4 } from "react";
3
3
  import { useVirtualizer } from "@tanstack/react-virtual";
4
4
 
5
5
  // src/config/chatConfig.ts
@@ -245,7 +245,7 @@ var configUtils = {
245
245
  };
246
246
 
247
247
  // src/components/chat/Message.tsx
248
- import React, { useState, useMemo, useEffect, memo } from "react";
248
+ import React, { useState, useMemo, useEffect, useRef, memo } from "react";
249
249
  import ReactMarkdown from "react-markdown";
250
250
  import remarkGfm from "remark-gfm";
251
251
  import rehypeHighlight from "rehype-highlight";
@@ -587,17 +587,29 @@ var ThinkingIndicator = memo(function ThinkingIndicator2({ label = "Thinking..."
587
587
  });
588
588
  var ThinkingBlock = memo(function ThinkingBlock2({ content, isStreaming = false, label = "Thinking", chunkSize = 12e3 }) {
589
589
  const [open, setOpen] = useState(isStreaming);
590
+ const [thinkingActive, setThinkingActive] = useState(false);
591
+ const contentLenRef = useRef(0);
590
592
  useEffect(() => {
591
- if (isStreaming) setOpen(true);
592
- }, [isStreaming]);
593
- useEffect(() => {
594
- if (!isStreaming && open) {
595
- const timer = setTimeout(() => setOpen(false), 600);
596
- return () => clearTimeout(timer);
593
+ if (!isStreaming) {
594
+ setThinkingActive(false);
595
+ contentLenRef.current = 0;
596
+ return;
597
+ }
598
+ if (content.length > contentLenRef.current) {
599
+ contentLenRef.current = content.length;
600
+ setThinkingActive(true);
597
601
  }
598
- }, [isStreaming, open]);
602
+ }, [content.length, isStreaming]);
603
+ useEffect(() => {
604
+ if (!thinkingActive || !isStreaming) return;
605
+ const timer = setTimeout(() => setThinkingActive(false), 1e3);
606
+ return () => clearTimeout(timer);
607
+ }, [thinkingActive, isStreaming, content.length]);
608
+ useEffect(() => {
609
+ if (isStreaming && content.length > 0) setOpen(true);
610
+ }, [isStreaming, content.length]);
599
611
  return /* @__PURE__ */ jsxs2("div", { className: "mb-3 relative rounded-lg overflow-hidden", children: [
600
- isStreaming && /* @__PURE__ */ jsx7(
612
+ thinkingActive && /* @__PURE__ */ jsx7(
601
613
  "div",
602
614
  {
603
615
  className: "absolute inset-0 rounded-lg pointer-events-none",
@@ -612,8 +624,8 @@ var ThinkingBlock = memo(function ThinkingBlock2({ content, isStreaming = false,
612
624
  /* @__PURE__ */ jsxs2(
613
625
  "div",
614
626
  {
615
- className: `relative rounded-lg border bg-muted/30 ${isStreaming ? "border-transparent" : "border-muted-foreground/20"}`,
616
- style: isStreaming ? { margin: "1px" } : void 0,
627
+ className: `relative rounded-lg border bg-muted/30 ${thinkingActive ? "border-transparent" : "border-muted-foreground/20"}`,
628
+ style: thinkingActive ? { margin: "1px" } : void 0,
617
629
  children: [
618
630
  /* @__PURE__ */ jsxs2(
619
631
  "button",
@@ -622,10 +634,10 @@ var ThinkingBlock = memo(function ThinkingBlock2({ content, isStreaming = false,
622
634
  className: "flex w-full items-center gap-2 px-3 py-2 text-left text-xs font-medium text-muted-foreground hover:text-foreground/70 transition-colors",
623
635
  onClick: () => setOpen((v) => !v),
624
636
  children: [
625
- /* @__PURE__ */ jsx7(BrainCircuit, { className: `h-3.5 w-3.5 flex-shrink-0 ${isStreaming ? "animate-pulse text-primary" : ""}` }),
637
+ /* @__PURE__ */ jsx7(BrainCircuit, { className: `h-3.5 w-3.5 flex-shrink-0 ${thinkingActive ? "animate-pulse text-primary" : ""}` }),
626
638
  /* @__PURE__ */ jsxs2("span", { className: "flex-1", children: [
627
- isStreaming ? label : `${label}`,
628
- isStreaming && /* @__PURE__ */ jsxs2("span", { className: "ml-1 inline-flex gap-0.5", children: [
639
+ label,
640
+ thinkingActive && /* @__PURE__ */ jsxs2("span", { className: "ml-1 inline-flex gap-0.5", children: [
629
641
  /* @__PURE__ */ jsx7("span", { className: "inline-block w-1 h-1 bg-current rounded-full animate-bounce", style: { animationDelay: "0ms" } }),
630
642
  /* @__PURE__ */ jsx7("span", { className: "inline-block w-1 h-1 bg-current rounded-full animate-bounce", style: { animationDelay: "150ms" } }),
631
643
  /* @__PURE__ */ jsx7("span", { className: "inline-block w-1 h-1 bg-current rounded-full animate-bounce", style: { animationDelay: "300ms" } })
@@ -644,7 +656,7 @@ var ThinkingBlock = memo(function ThinkingBlock2({ content, isStreaming = false,
644
656
  chunkSize
645
657
  }
646
658
  ),
647
- isStreaming && /* @__PURE__ */ jsx7("span", { className: "inline-block w-1.5 h-3 bg-muted-foreground/40 animate-pulse ml-0.5" })
659
+ thinkingActive && /* @__PURE__ */ jsx7("span", { className: "inline-block w-1.5 h-3 bg-muted-foreground/40 animate-pulse ml-0.5" })
648
660
  ] }) })
649
661
  ]
650
662
  }
@@ -1130,7 +1142,7 @@ var Message = memo(({
1130
1142
  }, arePropsEqual);
1131
1143
 
1132
1144
  // src/components/chat/Sidebar.tsx
1133
- import { useState as useState4, useRef as useRef4, useEffect as useEffect7 } from "react";
1145
+ import { useState as useState4, useRef as useRef5, useEffect as useEffect7 } from "react";
1134
1146
 
1135
1147
  // src/components/ui/input.tsx
1136
1148
  import { jsx as jsx8 } from "react/jsx-runtime";
@@ -2379,7 +2391,7 @@ var Sidebar2 = ({
2379
2391
  const [deleteThreadId, setDeleteThreadId] = useState4(null);
2380
2392
  const [editingThreadId, setEditingThreadId] = useState4(null);
2381
2393
  const [editTitle, setEditTitle] = useState4("");
2382
- const inputRef = useRef4(null);
2394
+ const inputRef = useRef5(null);
2383
2395
  const { setOpen } = useSidebar();
2384
2396
  useEffect7(() => {
2385
2397
  if (editingThreadId && inputRef.current) {
@@ -2798,7 +2810,7 @@ var ChatHeader = ({
2798
2810
  };
2799
2811
 
2800
2812
  // src/components/chat/ChatInput.tsx
2801
- import { useState as useState6, useRef as useRef5, useCallback as useCallback3, useEffect as useEffect9, memo as memo2 } from "react";
2813
+ import { useState as useState6, useRef as useRef6, useCallback as useCallback3, useEffect as useEffect9, memo as memo2 } from "react";
2802
2814
 
2803
2815
  // src/components/chat/UserContext.tsx
2804
2816
  import { createContext as createContext2, useCallback as useCallback2, useContext as useContext2, useEffect as useEffect8, useMemo as useMemo3, useState as useState5 } from "react";
@@ -2942,7 +2954,7 @@ var FileUploadItem = memo2(function FileUploadItem2({ file, progress, onCancel }
2942
2954
  var AttachmentPreview = memo2(function AttachmentPreview2({ attachment, onRemove }) {
2943
2955
  const [isPlaying, setIsPlaying] = useState6(false);
2944
2956
  const [audioPlaybackSrc, setAudioPlaybackSrc] = useState6(attachment.dataUrl);
2945
- const audioRef = useRef5(null);
2957
+ const audioRef = useRef6(null);
2946
2958
  useEffect9(() => {
2947
2959
  if (attachment.kind !== "audio" || !attachment.dataUrl.startsWith("data:")) {
2948
2960
  setAudioPlaybackSrc(attachment.dataUrl);
@@ -3135,12 +3147,12 @@ var ChatInput = memo2(function ChatInput2({
3135
3147
  const { setContext } = useChatUserContext();
3136
3148
  const [recordingDuration, setRecordingDuration] = useState6(0);
3137
3149
  const [uploadProgress, setUploadProgress] = useState6(/* @__PURE__ */ new Map());
3138
- const textareaRef = useRef5(null);
3139
- const fileInputRef = useRef5(null);
3140
- const mediaRecorderRef = useRef5(null);
3141
- const recordingStartTime = useRef5(0);
3142
- const recordingInterval = useRef5(null);
3143
- const mediaStreamRef = useRef5(null);
3150
+ const textareaRef = useRef6(null);
3151
+ const fileInputRef = useRef6(null);
3152
+ const mediaRecorderRef = useRef6(null);
3153
+ const recordingStartTime = useRef6(0);
3154
+ const recordingInterval = useRef6(null);
3155
+ const mediaStreamRef = useRef6(null);
3144
3156
  useEffect9(() => {
3145
3157
  return () => {
3146
3158
  if (mediaStreamRef.current) {
@@ -4004,18 +4016,18 @@ var ChatUI = ({
4004
4016
  setState((prev) => ({ ...prev, selectedThreadId: currentThreadId }));
4005
4017
  }
4006
4018
  }, [currentThreadId]);
4007
- const initialInputApplied = useRef6(false);
4008
- const initialInputConsumedRef = useRef6(false);
4019
+ const initialInputApplied = useRef7(false);
4020
+ const initialInputConsumedRef = useRef7(false);
4009
4021
  useEffect10(() => {
4010
4022
  if (initialInput && !initialInputApplied.current) {
4011
4023
  setInputValue(initialInput);
4012
4024
  initialInputApplied.current = true;
4013
4025
  }
4014
4026
  }, [initialInput]);
4015
- const scrollAreaRef = useRef6(null);
4016
- const stateRef = useRef6(state);
4017
- const inputValueRef = useRef6(inputValue);
4018
- const attachmentsRef = useRef6(attachments);
4027
+ const scrollAreaRef = useRef7(null);
4028
+ const stateRef = useRef7(state);
4029
+ const inputValueRef = useRef7(inputValue);
4030
+ const attachmentsRef = useRef7(attachments);
4019
4031
  useEffect10(() => {
4020
4032
  stateRef.current = state;
4021
4033
  }, [state]);
@@ -4064,7 +4076,7 @@ var ChatUI = ({
4064
4076
  return () => clearTimeout(t);
4065
4077
  }
4066
4078
  }, [state.showSidebar, isMobile, config.customComponent]);
4067
- const prevMessageCountRef = useRef6(0);
4079
+ const prevMessageCountRef = useRef7(0);
4068
4080
  useEffect10(() => {
4069
4081
  if (messages.length === 0) {
4070
4082
  prevMessageCountRef.current = 0;
@@ -4477,7 +4489,7 @@ var ChatUI = ({
4477
4489
  };
4478
4490
 
4479
4491
  // src/components/chat/ThreadManager.tsx
4480
- import { useState as useState9, useRef as useRef7, useEffect as useEffect11 } from "react";
4492
+ import { useState as useState9, useRef as useRef8, useEffect as useEffect11 } from "react";
4481
4493
  import {
4482
4494
  Plus as Plus4,
4483
4495
  MessageSquare as MessageSquare2,
@@ -4496,7 +4508,7 @@ import { Fragment as Fragment6, jsx as jsx25, jsxs as jsxs15 } from "react/jsx-r
4496
4508
  var ThreadItem = ({ thread, isActive, config, onSelect, onRename, onDelete, onArchive }) => {
4497
4509
  const [isEditing, setIsEditing] = useState9(false);
4498
4510
  const [editTitle, setEditTitle] = useState9(thread.title);
4499
- const inputRef = useRef7(null);
4511
+ const inputRef = useRef8(null);
4500
4512
  useEffect11(() => {
4501
4513
  if (isEditing && inputRef.current) {
4502
4514
  inputRef.current.focus();