@copilotz/chat-ui 0.1.0 → 0.1.4
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/README.md +405 -13
- package/dist/index.cjs +467 -133
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +38 -1
- package/dist/index.d.ts +38 -1
- package/dist/index.js +511 -174
- package/dist/index.js.map +1 -1
- package/dist/styles.css +260 -72
- package/package.json +7 -2
package/dist/index.js
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
// src/components/chat/ChatUI.tsx
|
|
2
|
-
import { useState as useState8, useEffect as
|
|
2
|
+
import { useState as useState8, useEffect as useEffect10, useRef as useRef7, useCallback as useCallback4 } from "react";
|
|
3
3
|
|
|
4
4
|
// src/config/chatConfig.ts
|
|
5
5
|
var defaultChatConfig = {
|
|
@@ -9,6 +9,11 @@ var defaultChatConfig = {
|
|
|
9
9
|
title: "Chat Assistant",
|
|
10
10
|
subtitle: "How can I help you today?"
|
|
11
11
|
},
|
|
12
|
+
agentSelector: {
|
|
13
|
+
enabled: false,
|
|
14
|
+
label: "Select agent",
|
|
15
|
+
hideIfSingle: true
|
|
16
|
+
},
|
|
12
17
|
labels: {
|
|
13
18
|
inputPlaceholder: "Type your message...",
|
|
14
19
|
sendButton: "Send",
|
|
@@ -101,6 +106,10 @@ function mergeConfig(_baseConfig, userConfig) {
|
|
|
101
106
|
...defaultChatConfig.ui,
|
|
102
107
|
...userConfig.ui
|
|
103
108
|
},
|
|
109
|
+
agentSelector: {
|
|
110
|
+
...defaultChatConfig.agentSelector,
|
|
111
|
+
...userConfig.agentSelector
|
|
112
|
+
},
|
|
104
113
|
customComponent: userConfig.customComponent || defaultChatConfig.customComponent,
|
|
105
114
|
headerActions: userConfig.headerActions || defaultChatConfig.headerActions
|
|
106
115
|
};
|
|
@@ -228,9 +237,10 @@ var configUtils = {
|
|
|
228
237
|
};
|
|
229
238
|
|
|
230
239
|
// src/components/chat/Message.tsx
|
|
231
|
-
import { useState, useRef } from "react";
|
|
240
|
+
import { useState, useRef, memo, Component } from "react";
|
|
232
241
|
import ReactMarkdown from "react-markdown";
|
|
233
242
|
import remarkGfm from "remark-gfm";
|
|
243
|
+
import remarkBreaks from "remark-breaks";
|
|
234
244
|
import rehypeHighlight from "rehype-highlight";
|
|
235
245
|
|
|
236
246
|
// src/components/ui/button.tsx
|
|
@@ -521,7 +531,25 @@ import {
|
|
|
521
531
|
ChevronDown
|
|
522
532
|
} from "lucide-react";
|
|
523
533
|
import { Fragment, jsx as jsx7, jsxs as jsxs2 } from "react/jsx-runtime";
|
|
524
|
-
var
|
|
534
|
+
var MarkdownErrorBoundary = class extends Component {
|
|
535
|
+
constructor(props) {
|
|
536
|
+
super(props);
|
|
537
|
+
this.state = { hasError: false };
|
|
538
|
+
}
|
|
539
|
+
static getDerivedStateFromError(_error) {
|
|
540
|
+
return { hasError: true };
|
|
541
|
+
}
|
|
542
|
+
componentDidCatch(error, errorInfo) {
|
|
543
|
+
console.warn("[Markdown] Falling back to simple rendering due to:", error.message);
|
|
544
|
+
}
|
|
545
|
+
render() {
|
|
546
|
+
if (this.state.hasError) {
|
|
547
|
+
return this.props.fallback;
|
|
548
|
+
}
|
|
549
|
+
return this.props.children;
|
|
550
|
+
}
|
|
551
|
+
};
|
|
552
|
+
var ThinkingIndicator = memo(function ThinkingIndicator2({ label = "Thinking..." }) {
|
|
525
553
|
return /* @__PURE__ */ jsxs2("div", { className: "flex items-center gap-2 py-2", children: [
|
|
526
554
|
/* @__PURE__ */ jsxs2("div", { className: "flex gap-1", children: [
|
|
527
555
|
/* @__PURE__ */ jsx7(
|
|
@@ -548,36 +576,61 @@ var ThinkingIndicator = ({ label = "Thinking..." }) => {
|
|
|
548
576
|
] }),
|
|
549
577
|
/* @__PURE__ */ jsx7("span", { className: "text-sm text-muted-foreground animate-pulse", children: label })
|
|
550
578
|
] });
|
|
579
|
+
});
|
|
580
|
+
var markdownComponents = {
|
|
581
|
+
code: ({ node, className, children, ...props }) => {
|
|
582
|
+
const inline = props.inline;
|
|
583
|
+
const match = /language-(\w+)/.exec(className || "");
|
|
584
|
+
return !inline && match ? /* @__PURE__ */ jsx7("pre", { className: "relative", children: /* @__PURE__ */ jsx7("code", { className, ...props, children }) }) : /* @__PURE__ */ jsx7("code", { className: "bg-muted px-1 py-0.5 rounded text-sm", ...props, children });
|
|
585
|
+
}
|
|
551
586
|
};
|
|
552
|
-
var
|
|
587
|
+
var remarkPluginsWithGfm = [remarkGfm, remarkBreaks];
|
|
588
|
+
var remarkPluginsSimple = [remarkBreaks];
|
|
589
|
+
var rehypePluginsDefault = [rehypeHighlight];
|
|
590
|
+
var rehypePluginsEmpty = [];
|
|
591
|
+
var SimpleMarkdown = memo(function SimpleMarkdown2({
|
|
592
|
+
content,
|
|
593
|
+
isStreaming = false
|
|
594
|
+
}) {
|
|
595
|
+
return /* @__PURE__ */ jsx7(
|
|
596
|
+
ReactMarkdown,
|
|
597
|
+
{
|
|
598
|
+
remarkPlugins: remarkPluginsSimple,
|
|
599
|
+
rehypePlugins: isStreaming ? rehypePluginsEmpty : rehypePluginsDefault,
|
|
600
|
+
components: markdownComponents,
|
|
601
|
+
children: content
|
|
602
|
+
}
|
|
603
|
+
);
|
|
604
|
+
});
|
|
605
|
+
var FullMarkdown = memo(function FullMarkdown2({
|
|
606
|
+
content,
|
|
607
|
+
isStreaming = false
|
|
608
|
+
}) {
|
|
609
|
+
return /* @__PURE__ */ jsx7(
|
|
610
|
+
ReactMarkdown,
|
|
611
|
+
{
|
|
612
|
+
remarkPlugins: remarkPluginsWithGfm,
|
|
613
|
+
rehypePlugins: isStreaming ? rehypePluginsEmpty : rehypePluginsDefault,
|
|
614
|
+
components: markdownComponents,
|
|
615
|
+
children: content
|
|
616
|
+
}
|
|
617
|
+
);
|
|
618
|
+
});
|
|
619
|
+
var StreamingText = memo(function StreamingText2({
|
|
553
620
|
content,
|
|
554
621
|
isStreaming = false,
|
|
555
622
|
thinkingLabel = "Thinking..."
|
|
556
|
-
})
|
|
623
|
+
}) {
|
|
557
624
|
const hasContent = content.trim().length > 0;
|
|
558
625
|
return /* @__PURE__ */ jsxs2("div", { className: "prose prose-sm max-w-none dark:prose-invert", children: [
|
|
559
|
-
hasContent ? /* @__PURE__ */ jsx7(
|
|
560
|
-
ReactMarkdown,
|
|
561
|
-
{
|
|
562
|
-
remarkPlugins: [remarkGfm],
|
|
563
|
-
rehypePlugins: isStreaming ? [] : [rehypeHighlight],
|
|
564
|
-
components: {
|
|
565
|
-
code: ({ node, className, children, ...props }) => {
|
|
566
|
-
const inline = props.inline;
|
|
567
|
-
const match = /language-(\w+)/.exec(className || "");
|
|
568
|
-
return !inline && match ? /* @__PURE__ */ jsx7("pre", { className: "relative", children: /* @__PURE__ */ jsx7("code", { className, ...props, children }) }) : /* @__PURE__ */ jsx7("code", { className: "bg-muted px-1 py-0.5 rounded text-sm", ...props, children });
|
|
569
|
-
}
|
|
570
|
-
},
|
|
571
|
-
children: content
|
|
572
|
-
}
|
|
573
|
-
) : isStreaming ? (
|
|
626
|
+
hasContent ? /* @__PURE__ */ jsx7(MarkdownErrorBoundary, { fallback: /* @__PURE__ */ jsx7(SimpleMarkdown, { content, isStreaming }), children: /* @__PURE__ */ jsx7(FullMarkdown, { content, isStreaming }) }) : isStreaming ? (
|
|
574
627
|
// Show thinking indicator while waiting for first token
|
|
575
628
|
/* @__PURE__ */ jsx7(ThinkingIndicator, { label: thinkingLabel })
|
|
576
629
|
) : null,
|
|
577
630
|
isStreaming && hasContent && /* @__PURE__ */ jsx7("span", { className: "inline-block w-2 h-4 bg-primary animate-pulse ml-1" })
|
|
578
631
|
] });
|
|
579
|
-
};
|
|
580
|
-
var MediaRenderer = ({ attachment })
|
|
632
|
+
});
|
|
633
|
+
var MediaRenderer = memo(function MediaRenderer2({ attachment }) {
|
|
581
634
|
const [isPlaying, setIsPlaying] = useState(false);
|
|
582
635
|
const audioRef = useRef(null);
|
|
583
636
|
const videoRef = useRef(null);
|
|
@@ -651,8 +704,8 @@ var MediaRenderer = ({ attachment }) => {
|
|
|
651
704
|
default:
|
|
652
705
|
return null;
|
|
653
706
|
}
|
|
654
|
-
};
|
|
655
|
-
var ToolCallsDisplay = ({ toolCalls, label })
|
|
707
|
+
});
|
|
708
|
+
var ToolCallsDisplay = memo(function ToolCallsDisplay2({ toolCalls, label }) {
|
|
656
709
|
const [expandedCall, setExpandedCall] = useState(null);
|
|
657
710
|
const getStatusIcon = (status) => {
|
|
658
711
|
switch (status) {
|
|
@@ -721,8 +774,48 @@ var ToolCallsDisplay = ({ toolCalls, label }) => {
|
|
|
721
774
|
] }, call.id);
|
|
722
775
|
})
|
|
723
776
|
] });
|
|
777
|
+
});
|
|
778
|
+
var arePropsEqual = (prevProps, nextProps) => {
|
|
779
|
+
if (prevProps.message.id !== nextProps.message.id) return false;
|
|
780
|
+
if (prevProps.message.content !== nextProps.message.content) return false;
|
|
781
|
+
if (prevProps.message.isStreaming !== nextProps.message.isStreaming) return false;
|
|
782
|
+
if (prevProps.message.isComplete !== nextProps.message.isComplete) return false;
|
|
783
|
+
if (prevProps.message.isEdited !== nextProps.message.isEdited) return false;
|
|
784
|
+
if (prevProps.message.timestamp !== nextProps.message.timestamp) return false;
|
|
785
|
+
if (prevProps.message.toolCalls !== nextProps.message.toolCalls) {
|
|
786
|
+
const prevCalls = prevProps.message.toolCalls;
|
|
787
|
+
const nextCalls = nextProps.message.toolCalls;
|
|
788
|
+
if (!prevCalls || !nextCalls || prevCalls.length !== nextCalls.length) return false;
|
|
789
|
+
for (let i = 0; i < prevCalls.length; i++) {
|
|
790
|
+
if (prevCalls[i].id !== nextCalls[i].id || prevCalls[i].status !== nextCalls[i].status || prevCalls[i].result !== nextCalls[i].result) {
|
|
791
|
+
return false;
|
|
792
|
+
}
|
|
793
|
+
}
|
|
794
|
+
}
|
|
795
|
+
if (prevProps.message.attachments !== nextProps.message.attachments) {
|
|
796
|
+
const prevAtt = prevProps.message.attachments;
|
|
797
|
+
const nextAtt = nextProps.message.attachments;
|
|
798
|
+
if (!prevAtt || !nextAtt || prevAtt.length !== nextAtt.length) return false;
|
|
799
|
+
}
|
|
800
|
+
if (prevProps.isUser !== nextProps.isUser) return false;
|
|
801
|
+
if (prevProps.userAvatar !== nextProps.userAvatar) return false;
|
|
802
|
+
if (prevProps.userName !== nextProps.userName) return false;
|
|
803
|
+
if (prevProps.assistantName !== nextProps.assistantName) return false;
|
|
804
|
+
if (prevProps.showTimestamp !== nextProps.showTimestamp) return false;
|
|
805
|
+
if (prevProps.showAvatar !== nextProps.showAvatar) return false;
|
|
806
|
+
if (prevProps.enableCopy !== nextProps.enableCopy) return false;
|
|
807
|
+
if (prevProps.enableEdit !== nextProps.enableEdit) return false;
|
|
808
|
+
if (prevProps.enableRegenerate !== nextProps.enableRegenerate) return false;
|
|
809
|
+
if (prevProps.enableToolCallsDisplay !== nextProps.enableToolCallsDisplay) return false;
|
|
810
|
+
if (prevProps.compactMode !== nextProps.compactMode) return false;
|
|
811
|
+
if (prevProps.className !== nextProps.className) return false;
|
|
812
|
+
if (prevProps.toolUsedLabel !== nextProps.toolUsedLabel) return false;
|
|
813
|
+
if (prevProps.thinkingLabel !== nextProps.thinkingLabel) return false;
|
|
814
|
+
if (prevProps.isGrouped !== nextProps.isGrouped) return false;
|
|
815
|
+
if (prevProps.assistantAvatar !== nextProps.assistantAvatar) return false;
|
|
816
|
+
return true;
|
|
724
817
|
};
|
|
725
|
-
var Message = ({
|
|
818
|
+
var Message = memo(({
|
|
726
819
|
message,
|
|
727
820
|
isUser,
|
|
728
821
|
userAvatar,
|
|
@@ -739,7 +832,8 @@ var Message = ({
|
|
|
739
832
|
onAction,
|
|
740
833
|
className = "",
|
|
741
834
|
toolUsedLabel,
|
|
742
|
-
thinkingLabel = "Thinking..."
|
|
835
|
+
thinkingLabel = "Thinking...",
|
|
836
|
+
isGrouped = false
|
|
743
837
|
}) => {
|
|
744
838
|
const [isEditing, setIsEditing] = useState(false);
|
|
745
839
|
const [editContent, setEditContent] = useState(message.content);
|
|
@@ -789,7 +883,7 @@ var Message = ({
|
|
|
789
883
|
onMouseEnter: () => setShowActions(true),
|
|
790
884
|
onMouseLeave: () => setShowActions(false),
|
|
791
885
|
children: [
|
|
792
|
-
/* @__PURE__ */ jsxs2("div", { className: `flex gap-3 ${messageIsUser ? "flex-row-reverse" : "flex-row"} w-full mb-1`, children: [
|
|
886
|
+
!isGrouped && /* @__PURE__ */ jsxs2("div", { className: `flex gap-3 ${messageIsUser ? "flex-row-reverse" : "flex-row"} w-full mb-1`, children: [
|
|
793
887
|
showAvatar && /* @__PURE__ */ jsx7("div", { className: `flex-shrink-0 ${compactMode ? "mt-1" : "mt-0"}`, children: /* @__PURE__ */ jsx7(Avatar, { className: compactMode ? "h-6 w-6" : "h-8 w-8", children: messageIsUser ? /* @__PURE__ */ jsxs2(Fragment, { children: [
|
|
794
888
|
/* @__PURE__ */ jsx7(AvatarImage, { src: userAvatar, alt: userName }),
|
|
795
889
|
/* @__PURE__ */ jsx7(AvatarFallback, { className: "bg-primary text-primary-foreground", children: userName.charAt(0).toUpperCase() })
|
|
@@ -800,7 +894,7 @@ var Message = ({
|
|
|
800
894
|
message.isEdited && /* @__PURE__ */ jsx7(Badge, { variant: "outline", className: "text-xs", children: "editado" })
|
|
801
895
|
] })
|
|
802
896
|
] }),
|
|
803
|
-
/* @__PURE__ */ jsx7("div", { className: `flex-1 min-w-0 ${messageIsUser ? "text-right" : "text-left"}`, children: /* @__PURE__ */ jsxs2("div", { className: `relative inline-flex flex-col ${messageIsUser ? "rounded-lg p-3 bg-primary text-primary-foreground ml-auto max-w-[85%]" : "max-w-[85%]"}`, children: [
|
|
897
|
+
/* @__PURE__ */ jsx7("div", { className: `flex-1 min-w-0 ${messageIsUser ? "text-right" : "text-left"} ${isGrouped && showAvatar && !messageIsUser ? compactMode ? "ml-9" : "ml-11" : ""} ${isGrouped && showAvatar && messageIsUser ? compactMode ? "mr-9" : "mr-11" : ""}`, children: /* @__PURE__ */ jsxs2("div", { className: `relative inline-flex flex-col ${messageIsUser ? "rounded-lg p-3 bg-primary text-primary-foreground ml-auto max-w-[85%]" : "max-w-[85%]"}`, children: [
|
|
804
898
|
isEditing ? /* @__PURE__ */ jsxs2("div", { className: "space-y-2", children: [
|
|
805
899
|
/* @__PURE__ */ jsx7(
|
|
806
900
|
Textarea,
|
|
@@ -878,10 +972,10 @@ var Message = ({
|
|
|
878
972
|
]
|
|
879
973
|
}
|
|
880
974
|
) });
|
|
881
|
-
};
|
|
975
|
+
}, arePropsEqual);
|
|
882
976
|
|
|
883
977
|
// src/components/chat/Sidebar.tsx
|
|
884
|
-
import { useState as useState4, useRef as
|
|
978
|
+
import { useState as useState4, useRef as useRef5, useEffect as useEffect7 } from "react";
|
|
885
979
|
|
|
886
980
|
// src/components/ui/input.tsx
|
|
887
981
|
import { jsx as jsx8 } from "react/jsx-runtime";
|
|
@@ -903,7 +997,7 @@ function Input({ className, type, ...props }) {
|
|
|
903
997
|
}
|
|
904
998
|
|
|
905
999
|
// src/components/ui/sidebar.tsx
|
|
906
|
-
import * as
|
|
1000
|
+
import * as React4 from "react";
|
|
907
1001
|
import { Slot as Slot3 } from "@radix-ui/react-slot";
|
|
908
1002
|
import { cva as cva3 } from "class-variance-authority";
|
|
909
1003
|
import { PanelLeftIcon } from "lucide-react";
|
|
@@ -911,18 +1005,26 @@ import { PanelLeftIcon } from "lucide-react";
|
|
|
911
1005
|
// src/hooks/use-mobile.ts
|
|
912
1006
|
import * as React2 from "react";
|
|
913
1007
|
var MOBILE_BREAKPOINT = 768;
|
|
1008
|
+
function getInitialIsMobile() {
|
|
1009
|
+
if (typeof window === "undefined") return false;
|
|
1010
|
+
return window.innerWidth < MOBILE_BREAKPOINT;
|
|
1011
|
+
}
|
|
914
1012
|
function useIsMobile() {
|
|
915
|
-
const [isMobile, setIsMobile] = React2.useState(
|
|
1013
|
+
const [isMobile, setIsMobile] = React2.useState(getInitialIsMobile);
|
|
916
1014
|
React2.useEffect(() => {
|
|
917
1015
|
const mql = window.matchMedia(`(max-width: ${MOBILE_BREAKPOINT - 1}px)`);
|
|
918
1016
|
const onChange = () => {
|
|
919
1017
|
setIsMobile(window.innerWidth < MOBILE_BREAKPOINT);
|
|
920
1018
|
};
|
|
921
1019
|
mql.addEventListener("change", onChange);
|
|
1020
|
+
window.addEventListener("resize", onChange);
|
|
922
1021
|
setIsMobile(window.innerWidth < MOBILE_BREAKPOINT);
|
|
923
|
-
return () =>
|
|
1022
|
+
return () => {
|
|
1023
|
+
mql.removeEventListener("change", onChange);
|
|
1024
|
+
window.removeEventListener("resize", onChange);
|
|
1025
|
+
};
|
|
924
1026
|
}, []);
|
|
925
|
-
return
|
|
1027
|
+
return isMobile;
|
|
926
1028
|
}
|
|
927
1029
|
|
|
928
1030
|
// src/components/ui/separator.tsx
|
|
@@ -950,11 +1052,30 @@ function Separator({
|
|
|
950
1052
|
}
|
|
951
1053
|
|
|
952
1054
|
// src/components/ui/sheet.tsx
|
|
1055
|
+
import * as React3 from "react";
|
|
953
1056
|
import * as SheetPrimitive from "@radix-ui/react-dialog";
|
|
954
1057
|
import { XIcon } from "lucide-react";
|
|
955
1058
|
import { jsx as jsx10, jsxs as jsxs3 } from "react/jsx-runtime";
|
|
956
|
-
function
|
|
957
|
-
|
|
1059
|
+
function cleanupBodyStyles() {
|
|
1060
|
+
if (typeof document !== "undefined" && document.body.style.pointerEvents === "none") {
|
|
1061
|
+
document.body.style.pointerEvents = "";
|
|
1062
|
+
}
|
|
1063
|
+
}
|
|
1064
|
+
function Sheet({ open, onOpenChange, ...props }) {
|
|
1065
|
+
const prevOpenRef = React3.useRef(open);
|
|
1066
|
+
React3.useEffect(() => {
|
|
1067
|
+
if (prevOpenRef.current === true && open === false) {
|
|
1068
|
+
const timeout = setTimeout(cleanupBodyStyles, 350);
|
|
1069
|
+
return () => clearTimeout(timeout);
|
|
1070
|
+
}
|
|
1071
|
+
prevOpenRef.current = open;
|
|
1072
|
+
}, [open]);
|
|
1073
|
+
React3.useEffect(() => {
|
|
1074
|
+
return () => {
|
|
1075
|
+
cleanupBodyStyles();
|
|
1076
|
+
};
|
|
1077
|
+
}, []);
|
|
1078
|
+
return /* @__PURE__ */ jsx10(SheetPrimitive.Root, { "data-slot": "sheet", open, onOpenChange, ...props });
|
|
958
1079
|
}
|
|
959
1080
|
function SheetPortal({
|
|
960
1081
|
...props
|
|
@@ -970,7 +1091,10 @@ function SheetOverlay({
|
|
|
970
1091
|
{
|
|
971
1092
|
"data-slot": "sheet-overlay",
|
|
972
1093
|
className: cn(
|
|
973
|
-
"
|
|
1094
|
+
"fixed inset-0 z-50 bg-black/50",
|
|
1095
|
+
"data-[state=open]:animate-in data-[state=closed]:animate-out",
|
|
1096
|
+
"data-[state=closed]:fade-out-0 data-[state=open]:fade-in-0",
|
|
1097
|
+
"data-[state=closed]:pointer-events-none",
|
|
974
1098
|
className
|
|
975
1099
|
),
|
|
976
1100
|
...props
|
|
@@ -989,6 +1113,7 @@ function SheetContent({
|
|
|
989
1113
|
SheetPrimitive.Content,
|
|
990
1114
|
{
|
|
991
1115
|
"data-slot": "sheet-content",
|
|
1116
|
+
"aria-describedby": void 0,
|
|
992
1117
|
className: cn(
|
|
993
1118
|
"bg-background data-[state=open]:animate-in data-[state=closed]:animate-out fixed z-50 flex flex-col gap-4 shadow-lg transition ease-in-out data-[state=closed]:duration-300 data-[state=open]:duration-500",
|
|
994
1119
|
side === "right" && "data-[state=closed]:slide-out-to-right data-[state=open]:slide-in-from-right inset-y-0 right-0 h-full w-3/4 border-l sm:max-w-sm",
|
|
@@ -1054,9 +1179,9 @@ var SIDEBAR_WIDTH = "16rem";
|
|
|
1054
1179
|
var SIDEBAR_WIDTH_MOBILE = "18rem";
|
|
1055
1180
|
var SIDEBAR_WIDTH_ICON = "3rem";
|
|
1056
1181
|
var SIDEBAR_KEYBOARD_SHORTCUT = "b";
|
|
1057
|
-
var SidebarContext =
|
|
1182
|
+
var SidebarContext = React4.createContext(null);
|
|
1058
1183
|
function useSidebar() {
|
|
1059
|
-
const context =
|
|
1184
|
+
const context = React4.useContext(SidebarContext);
|
|
1060
1185
|
if (!context) {
|
|
1061
1186
|
throw new Error("useSidebar must be used within a SidebarProvider.");
|
|
1062
1187
|
}
|
|
@@ -1072,10 +1197,10 @@ function SidebarProvider({
|
|
|
1072
1197
|
...props
|
|
1073
1198
|
}) {
|
|
1074
1199
|
const isMobile = useIsMobile();
|
|
1075
|
-
const [openMobile, setOpenMobile] =
|
|
1076
|
-
const [_open, _setOpen] =
|
|
1200
|
+
const [openMobile, setOpenMobile] = React4.useState(false);
|
|
1201
|
+
const [_open, _setOpen] = React4.useState(defaultOpen);
|
|
1077
1202
|
const open = openProp ?? _open;
|
|
1078
|
-
const setOpen =
|
|
1203
|
+
const setOpen = React4.useCallback(
|
|
1079
1204
|
(value) => {
|
|
1080
1205
|
const openState = typeof value === "function" ? value(open) : value;
|
|
1081
1206
|
if (setOpenProp) {
|
|
@@ -1087,10 +1212,10 @@ function SidebarProvider({
|
|
|
1087
1212
|
},
|
|
1088
1213
|
[setOpenProp, open]
|
|
1089
1214
|
);
|
|
1090
|
-
const toggleSidebar =
|
|
1215
|
+
const toggleSidebar = React4.useCallback(() => {
|
|
1091
1216
|
return isMobile ? setOpenMobile((open2) => !open2) : setOpen((open2) => !open2);
|
|
1092
1217
|
}, [isMobile, setOpen, setOpenMobile]);
|
|
1093
|
-
|
|
1218
|
+
React4.useEffect(() => {
|
|
1094
1219
|
const handleKeyDown = (event) => {
|
|
1095
1220
|
if (event.key === SIDEBAR_KEYBOARD_SHORTCUT && (event.metaKey || event.ctrlKey)) {
|
|
1096
1221
|
event.preventDefault();
|
|
@@ -1101,7 +1226,7 @@ function SidebarProvider({
|
|
|
1101
1226
|
return () => window.removeEventListener("keydown", handleKeyDown);
|
|
1102
1227
|
}, [toggleSidebar]);
|
|
1103
1228
|
const state = open ? "expanded" : "collapsed";
|
|
1104
|
-
const contextValue =
|
|
1229
|
+
const contextValue = React4.useMemo(
|
|
1105
1230
|
() => ({
|
|
1106
1231
|
state,
|
|
1107
1232
|
open,
|
|
@@ -1176,12 +1301,29 @@ function Sidebar({
|
|
|
1176
1301
|
}
|
|
1177
1302
|
) });
|
|
1178
1303
|
}
|
|
1304
|
+
const isCollapsed = state === "collapsed";
|
|
1305
|
+
const currentCollapsible = isCollapsed ? collapsible : "";
|
|
1306
|
+
const getGapWidth = () => {
|
|
1307
|
+
if (currentCollapsible === "offcanvas") return "0px";
|
|
1308
|
+
if (currentCollapsible === "icon") return SIDEBAR_WIDTH_ICON;
|
|
1309
|
+
return SIDEBAR_WIDTH;
|
|
1310
|
+
};
|
|
1311
|
+
const getContainerWidth = () => {
|
|
1312
|
+
if (currentCollapsible === "icon") return SIDEBAR_WIDTH_ICON;
|
|
1313
|
+
return SIDEBAR_WIDTH;
|
|
1314
|
+
};
|
|
1315
|
+
const getContainerOffset = () => {
|
|
1316
|
+
if (currentCollapsible === "offcanvas") {
|
|
1317
|
+
return side === "left" ? `calc(${SIDEBAR_WIDTH} * -1)` : `calc(${SIDEBAR_WIDTH} * -1)`;
|
|
1318
|
+
}
|
|
1319
|
+
return "0";
|
|
1320
|
+
};
|
|
1179
1321
|
return /* @__PURE__ */ jsxs4(
|
|
1180
1322
|
"div",
|
|
1181
1323
|
{
|
|
1182
|
-
className: "group peer text-sidebar-foreground
|
|
1324
|
+
className: "group peer text-sidebar-foreground",
|
|
1183
1325
|
"data-state": state,
|
|
1184
|
-
"data-collapsible":
|
|
1326
|
+
"data-collapsible": currentCollapsible,
|
|
1185
1327
|
"data-variant": variant,
|
|
1186
1328
|
"data-side": side,
|
|
1187
1329
|
"data-slot": "sidebar",
|
|
@@ -1191,11 +1333,10 @@ function Sidebar({
|
|
|
1191
1333
|
{
|
|
1192
1334
|
"data-slot": "sidebar-gap",
|
|
1193
1335
|
className: cn(
|
|
1194
|
-
"relative
|
|
1195
|
-
"group-data-[
|
|
1196
|
-
|
|
1197
|
-
|
|
1198
|
-
)
|
|
1336
|
+
"relative bg-transparent transition-[width] duration-200 ease-linear",
|
|
1337
|
+
"group-data-[side=right]:rotate-180"
|
|
1338
|
+
),
|
|
1339
|
+
style: { width: getGapWidth() }
|
|
1199
1340
|
}
|
|
1200
1341
|
),
|
|
1201
1342
|
/* @__PURE__ */ jsx11(
|
|
@@ -1203,12 +1344,16 @@ function Sidebar({
|
|
|
1203
1344
|
{
|
|
1204
1345
|
"data-slot": "sidebar-container",
|
|
1205
1346
|
className: cn(
|
|
1206
|
-
"fixed inset-y-0 z-10
|
|
1207
|
-
side === "left" ? "left-0 group-data-[collapsible=offcanvas]:left-[calc(var(--sidebar-width)*-1)]" : "right-0 group-data-[collapsible=offcanvas]:right-[calc(var(--sidebar-width)*-1)]",
|
|
1347
|
+
"fixed inset-y-0 z-10 h-screen transition-[left,right,width] duration-200 ease-linear",
|
|
1208
1348
|
// Adjust the padding for floating and inset variants.
|
|
1209
|
-
variant === "floating" || variant === "inset" ? "p-2
|
|
1349
|
+
variant === "floating" || variant === "inset" ? "p-2" : side === "left" ? "border-r" : "border-l",
|
|
1210
1350
|
className
|
|
1211
1351
|
),
|
|
1352
|
+
style: {
|
|
1353
|
+
display: "flex",
|
|
1354
|
+
width: getContainerWidth(),
|
|
1355
|
+
[side === "left" ? "left" : "right"]: getContainerOffset()
|
|
1356
|
+
},
|
|
1212
1357
|
...props,
|
|
1213
1358
|
children: /* @__PURE__ */ jsx11(
|
|
1214
1359
|
"div",
|
|
@@ -1231,6 +1376,15 @@ function SidebarTrigger({
|
|
|
1231
1376
|
...props
|
|
1232
1377
|
}) {
|
|
1233
1378
|
const { toggleSidebar } = useSidebar();
|
|
1379
|
+
const handleActivation = React4.useCallback((event) => {
|
|
1380
|
+
if (event.type === "touchend") {
|
|
1381
|
+
event.preventDefault();
|
|
1382
|
+
}
|
|
1383
|
+
if ("onClick" in event && onClick) {
|
|
1384
|
+
onClick(event);
|
|
1385
|
+
}
|
|
1386
|
+
toggleSidebar();
|
|
1387
|
+
}, [onClick, toggleSidebar]);
|
|
1234
1388
|
return /* @__PURE__ */ jsxs4(
|
|
1235
1389
|
Button,
|
|
1236
1390
|
{
|
|
@@ -1239,10 +1393,8 @@ function SidebarTrigger({
|
|
|
1239
1393
|
variant: "ghost",
|
|
1240
1394
|
size: "icon",
|
|
1241
1395
|
className: cn("size-7", className),
|
|
1242
|
-
onClick:
|
|
1243
|
-
|
|
1244
|
-
toggleSidebar();
|
|
1245
|
-
},
|
|
1396
|
+
onClick: handleActivation,
|
|
1397
|
+
onTouchEnd: handleActivation,
|
|
1246
1398
|
...props,
|
|
1247
1399
|
children: [
|
|
1248
1400
|
/* @__PURE__ */ jsx11(PanelLeftIcon, {}),
|
|
@@ -1484,13 +1636,34 @@ function SidebarMenuAction({
|
|
|
1484
1636
|
}
|
|
1485
1637
|
|
|
1486
1638
|
// src/components/ui/dialog.tsx
|
|
1639
|
+
import * as React5 from "react";
|
|
1487
1640
|
import * as DialogPrimitive from "@radix-ui/react-dialog";
|
|
1488
1641
|
import { XIcon as XIcon2 } from "lucide-react";
|
|
1489
1642
|
import { jsx as jsx12, jsxs as jsxs5 } from "react/jsx-runtime";
|
|
1643
|
+
function cleanupBodyStyles2() {
|
|
1644
|
+
if (typeof document !== "undefined" && document.body.style.pointerEvents === "none") {
|
|
1645
|
+
document.body.style.pointerEvents = "";
|
|
1646
|
+
}
|
|
1647
|
+
}
|
|
1490
1648
|
function Dialog({
|
|
1649
|
+
open,
|
|
1650
|
+
onOpenChange,
|
|
1491
1651
|
...props
|
|
1492
1652
|
}) {
|
|
1493
|
-
|
|
1653
|
+
const prevOpenRef = React5.useRef(open);
|
|
1654
|
+
React5.useEffect(() => {
|
|
1655
|
+
if (prevOpenRef.current === true && open === false) {
|
|
1656
|
+
const timeout = setTimeout(cleanupBodyStyles2, 250);
|
|
1657
|
+
return () => clearTimeout(timeout);
|
|
1658
|
+
}
|
|
1659
|
+
prevOpenRef.current = open;
|
|
1660
|
+
}, [open]);
|
|
1661
|
+
React5.useEffect(() => {
|
|
1662
|
+
return () => {
|
|
1663
|
+
cleanupBodyStyles2();
|
|
1664
|
+
};
|
|
1665
|
+
}, []);
|
|
1666
|
+
return /* @__PURE__ */ jsx12(DialogPrimitive.Root, { "data-slot": "dialog", open, onOpenChange, ...props });
|
|
1494
1667
|
}
|
|
1495
1668
|
function DialogTrigger({
|
|
1496
1669
|
...props
|
|
@@ -1511,7 +1684,10 @@ function DialogOverlay({
|
|
|
1511
1684
|
{
|
|
1512
1685
|
"data-slot": "dialog-overlay",
|
|
1513
1686
|
className: cn(
|
|
1514
|
-
"
|
|
1687
|
+
"fixed inset-0 z-50 bg-black/50",
|
|
1688
|
+
"data-[state=open]:animate-in data-[state=closed]:animate-out",
|
|
1689
|
+
"data-[state=closed]:fade-out-0 data-[state=open]:fade-in-0",
|
|
1690
|
+
"data-[state=closed]:pointer-events-none",
|
|
1515
1691
|
className
|
|
1516
1692
|
),
|
|
1517
1693
|
...props
|
|
@@ -1530,6 +1706,7 @@ function DialogContent({
|
|
|
1530
1706
|
DialogPrimitive.Content,
|
|
1531
1707
|
{
|
|
1532
1708
|
"data-slot": "dialog-content",
|
|
1709
|
+
"aria-describedby": void 0,
|
|
1533
1710
|
className: cn(
|
|
1534
1711
|
"bg-background data-[state=open]:animate-in data-[state=closed]:animate-out data-[state=closed]:fade-out-0 data-[state=open]:fade-in-0 data-[state=closed]:zoom-out-95 data-[state=open]:zoom-in-95 fixed top-[50%] left-[50%] z-50 grid w-full max-w-[calc(100%-2rem)] translate-x-[-50%] translate-y-[-50%] gap-4 rounded-lg border p-6 shadow-lg duration-200 sm:max-w-lg",
|
|
1535
1712
|
className
|
|
@@ -1604,12 +1781,33 @@ function DialogDescription({
|
|
|
1604
1781
|
}
|
|
1605
1782
|
|
|
1606
1783
|
// src/components/ui/alert-dialog.tsx
|
|
1784
|
+
import * as React6 from "react";
|
|
1607
1785
|
import * as AlertDialogPrimitive from "@radix-ui/react-alert-dialog";
|
|
1608
1786
|
import { jsx as jsx13, jsxs as jsxs6 } from "react/jsx-runtime";
|
|
1787
|
+
function cleanupBodyStyles3() {
|
|
1788
|
+
if (typeof document !== "undefined" && document.body.style.pointerEvents === "none") {
|
|
1789
|
+
document.body.style.pointerEvents = "";
|
|
1790
|
+
}
|
|
1791
|
+
}
|
|
1609
1792
|
function AlertDialog({
|
|
1793
|
+
open,
|
|
1794
|
+
onOpenChange,
|
|
1610
1795
|
...props
|
|
1611
1796
|
}) {
|
|
1612
|
-
|
|
1797
|
+
const prevOpenRef = React6.useRef(open);
|
|
1798
|
+
React6.useEffect(() => {
|
|
1799
|
+
if (prevOpenRef.current === true && open === false) {
|
|
1800
|
+
const timeout = setTimeout(cleanupBodyStyles3, 250);
|
|
1801
|
+
return () => clearTimeout(timeout);
|
|
1802
|
+
}
|
|
1803
|
+
prevOpenRef.current = open;
|
|
1804
|
+
}, [open]);
|
|
1805
|
+
React6.useEffect(() => {
|
|
1806
|
+
return () => {
|
|
1807
|
+
cleanupBodyStyles3();
|
|
1808
|
+
};
|
|
1809
|
+
}, []);
|
|
1810
|
+
return /* @__PURE__ */ jsx13(AlertDialogPrimitive.Root, { "data-slot": "alert-dialog", open, onOpenChange, ...props });
|
|
1613
1811
|
}
|
|
1614
1812
|
function AlertDialogPortal({
|
|
1615
1813
|
...props
|
|
@@ -1625,7 +1823,10 @@ function AlertDialogOverlay({
|
|
|
1625
1823
|
{
|
|
1626
1824
|
"data-slot": "alert-dialog-overlay",
|
|
1627
1825
|
className: cn(
|
|
1628
|
-
"
|
|
1826
|
+
"fixed inset-0 z-50 bg-black/50",
|
|
1827
|
+
"data-[state=open]:animate-in data-[state=closed]:animate-out",
|
|
1828
|
+
"data-[state=closed]:fade-out-0 data-[state=open]:fade-in-0",
|
|
1829
|
+
"data-[state=closed]:pointer-events-none",
|
|
1629
1830
|
className
|
|
1630
1831
|
),
|
|
1631
1832
|
...props
|
|
@@ -1829,7 +2030,8 @@ import {
|
|
|
1829
2030
|
Trash2,
|
|
1830
2031
|
Archive,
|
|
1831
2032
|
Search,
|
|
1832
|
-
Filter
|
|
2033
|
+
Filter,
|
|
2034
|
+
Bot
|
|
1833
2035
|
} from "lucide-react";
|
|
1834
2036
|
|
|
1835
2037
|
// src/components/chat/UserMenu.tsx
|
|
@@ -2044,9 +2246,9 @@ var Sidebar2 = ({
|
|
|
2044
2246
|
const [deleteThreadId, setDeleteThreadId] = useState4(null);
|
|
2045
2247
|
const [editingThreadId, setEditingThreadId] = useState4(null);
|
|
2046
2248
|
const [editTitle, setEditTitle] = useState4("");
|
|
2047
|
-
const inputRef =
|
|
2249
|
+
const inputRef = useRef5(null);
|
|
2048
2250
|
const { setOpen } = useSidebar();
|
|
2049
|
-
|
|
2251
|
+
useEffect7(() => {
|
|
2050
2252
|
if (editingThreadId && inputRef.current) {
|
|
2051
2253
|
inputRef.current.focus();
|
|
2052
2254
|
inputRef.current.select();
|
|
@@ -2099,6 +2301,13 @@ var Sidebar2 = ({
|
|
|
2099
2301
|
};
|
|
2100
2302
|
return /* @__PURE__ */ jsxs9(Sidebar, { collapsible: "icon", ...props, children: [
|
|
2101
2303
|
/* @__PURE__ */ jsxs9(SidebarHeader, { children: [
|
|
2304
|
+
/* @__PURE__ */ jsxs9("div", { className: "flex items-center gap-3 px-2 py-3", children: [
|
|
2305
|
+
/* @__PURE__ */ jsx16("div", { className: "flex items-center justify-center shrink-0", children: config.branding?.logo || /* @__PURE__ */ jsx16(Avatar, { className: "h-8 w-8", children: /* @__PURE__ */ jsx16(AvatarFallback, { className: "bg-primary text-primary-foreground", children: /* @__PURE__ */ jsx16(Bot, { className: "h-4 w-4" }) }) }) }),
|
|
2306
|
+
/* @__PURE__ */ jsxs9("div", { className: "flex flex-col min-w-0 group-data-[collapsible=icon]:hidden", children: [
|
|
2307
|
+
/* @__PURE__ */ jsx16("span", { className: "text-sm font-semibold truncate", children: config.branding?.title || "Chat" }),
|
|
2308
|
+
config.branding?.subtitle && /* @__PURE__ */ jsx16("span", { className: "text-xs text-muted-foreground truncate", children: config.branding.subtitle })
|
|
2309
|
+
] })
|
|
2310
|
+
] }),
|
|
2102
2311
|
onCreateThread && /* @__PURE__ */ jsx16(
|
|
2103
2312
|
CreateThreadDialog,
|
|
2104
2313
|
{
|
|
@@ -2118,7 +2327,7 @@ var Sidebar2 = ({
|
|
|
2118
2327
|
) }) })
|
|
2119
2328
|
}
|
|
2120
2329
|
),
|
|
2121
|
-
/* @__PURE__ */ jsxs9("div", { className: "px-2 py-1 mt-
|
|
2330
|
+
/* @__PURE__ */ jsxs9("div", { className: "px-2 py-1 mt-4", children: [
|
|
2122
2331
|
/* @__PURE__ */ jsxs9("div", { className: "relative group-data-[collapsible=icon]:hidden", children: [
|
|
2123
2332
|
/* @__PURE__ */ jsx16(Search, { className: "pointer-events-none absolute left-2 top-1/2 size-4 -translate-y-1/2 select-none opacity-50" }),
|
|
2124
2333
|
/* @__PURE__ */ jsx16(
|
|
@@ -2233,7 +2442,7 @@ var Sidebar2 = ({
|
|
|
2233
2442
|
}
|
|
2234
2443
|
) }),
|
|
2235
2444
|
/* @__PURE__ */ jsx16(SidebarRail, {}),
|
|
2236
|
-
/* @__PURE__ */ jsx16(AlertDialog, { open: !!deleteThreadId, onOpenChange: () => setDeleteThreadId(null), children: /* @__PURE__ */ jsxs9(AlertDialogContent, { children: [
|
|
2445
|
+
deleteThreadId && /* @__PURE__ */ jsx16(AlertDialog, { open: !!deleteThreadId, onOpenChange: () => setDeleteThreadId(null), children: /* @__PURE__ */ jsxs9(AlertDialogContent, { children: [
|
|
2237
2446
|
/* @__PURE__ */ jsxs9(AlertDialogHeader, { children: [
|
|
2238
2447
|
/* @__PURE__ */ jsx16(AlertDialogTitle, { children: config.labels?.deleteConfirmTitle || "Delete Conversation" }),
|
|
2239
2448
|
/* @__PURE__ */ jsx16(AlertDialogDescription, { children: config.labels?.deleteConfirmDescription || "Are you sure you want to delete this conversation? This action cannot be undone." })
|
|
@@ -2254,9 +2463,9 @@ var Sidebar2 = ({
|
|
|
2254
2463
|
};
|
|
2255
2464
|
|
|
2256
2465
|
// src/components/chat/ChatHeader.tsx
|
|
2257
|
-
import
|
|
2466
|
+
import React8 from "react";
|
|
2258
2467
|
import {
|
|
2259
|
-
Bot,
|
|
2468
|
+
Bot as Bot2,
|
|
2260
2469
|
MoreVertical,
|
|
2261
2470
|
Download,
|
|
2262
2471
|
Upload,
|
|
@@ -2264,7 +2473,9 @@ import {
|
|
|
2264
2473
|
Plus as Plus2,
|
|
2265
2474
|
Menu,
|
|
2266
2475
|
Moon as Moon2,
|
|
2267
|
-
Sun as Sun2
|
|
2476
|
+
Sun as Sun2,
|
|
2477
|
+
ChevronDown as ChevronDown2,
|
|
2478
|
+
Check as Check2
|
|
2268
2479
|
} from "lucide-react";
|
|
2269
2480
|
import { Fragment as Fragment3, jsx as jsx17, jsxs as jsxs10 } from "react/jsx-runtime";
|
|
2270
2481
|
var ChatHeader = ({
|
|
@@ -2278,13 +2489,17 @@ var ChatHeader = ({
|
|
|
2278
2489
|
onClearAll,
|
|
2279
2490
|
showCustomComponentButton,
|
|
2280
2491
|
isMobile,
|
|
2492
|
+
showAgentSelector = false,
|
|
2493
|
+
agentOptions = [],
|
|
2494
|
+
selectedAgentId = null,
|
|
2495
|
+
onSelectAgent,
|
|
2281
2496
|
className = ""
|
|
2282
2497
|
}) => {
|
|
2283
|
-
const [isDarkMode, setIsDarkMode] =
|
|
2498
|
+
const [isDarkMode, setIsDarkMode] = React8.useState(() => {
|
|
2284
2499
|
if (typeof window === "undefined") return false;
|
|
2285
2500
|
return document.documentElement.classList.contains("dark");
|
|
2286
2501
|
});
|
|
2287
|
-
|
|
2502
|
+
React8.useEffect(() => {
|
|
2288
2503
|
const observer = new MutationObserver(() => {
|
|
2289
2504
|
setIsDarkMode(document.documentElement.classList.contains("dark"));
|
|
2290
2505
|
});
|
|
@@ -2328,22 +2543,64 @@ var ChatHeader = ({
|
|
|
2328
2543
|
};
|
|
2329
2544
|
input.click();
|
|
2330
2545
|
};
|
|
2546
|
+
const selectedAgent = agentOptions.find((agent) => agent.id === selectedAgentId) || null;
|
|
2547
|
+
const agentPlaceholder = config.agentSelector?.label || "Select agent";
|
|
2331
2548
|
return /* @__PURE__ */ jsx17(
|
|
2332
2549
|
Card,
|
|
2333
2550
|
{
|
|
2334
2551
|
"data-chat-header": true,
|
|
2335
2552
|
className: `py-0 border-b rounded-none relative z-10 bg-background/95 backdrop-blur supports-[backdrop-filter]:bg-background/80 ${className}`,
|
|
2336
2553
|
style: isMobile ? { paddingTop: "env(safe-area-inset-top)" } : void 0,
|
|
2337
|
-
children: /* @__PURE__ */ jsx17(CardHeader, { className: "p-2", children: /* @__PURE__ */ jsxs10("div", { className: "flex items-center justify-between", children: [
|
|
2338
|
-
/* @__PURE__ */
|
|
2339
|
-
/* @__PURE__ */
|
|
2340
|
-
|
|
2341
|
-
|
|
2342
|
-
|
|
2343
|
-
|
|
2344
|
-
|
|
2345
|
-
|
|
2554
|
+
children: /* @__PURE__ */ jsx17(CardHeader, { className: "p-2", children: /* @__PURE__ */ jsxs10("div", { className: "flex items-center justify-between gap-2", children: [
|
|
2555
|
+
/* @__PURE__ */ jsxs10("div", { className: "flex items-center gap-1", children: [
|
|
2556
|
+
/* @__PURE__ */ jsxs10(Tooltip, { children: [
|
|
2557
|
+
/* @__PURE__ */ jsx17(TooltipTrigger, { asChild: true, children: /* @__PURE__ */ jsx17(SidebarTrigger, { className: "-ml-1" }) }),
|
|
2558
|
+
/* @__PURE__ */ jsx17(TooltipContent, { children: config.labels?.sidebarToggle || "Toggle Sidebar" })
|
|
2559
|
+
] }),
|
|
2560
|
+
showAgentSelector && /* @__PURE__ */ jsxs10(DropdownMenu, { children: [
|
|
2561
|
+
/* @__PURE__ */ jsx17(DropdownMenuTrigger, { asChild: true, children: /* @__PURE__ */ jsxs10(
|
|
2562
|
+
Button,
|
|
2563
|
+
{
|
|
2564
|
+
variant: "ghost",
|
|
2565
|
+
className: "h-9 px-3 gap-1.5 font-medium text-base hover:bg-accent/50",
|
|
2566
|
+
children: [
|
|
2567
|
+
selectedAgent?.avatarUrl ? /* @__PURE__ */ jsxs10(Avatar, { className: "h-5 w-5", children: [
|
|
2568
|
+
/* @__PURE__ */ jsx17(AvatarImage, { src: selectedAgent.avatarUrl, alt: selectedAgent.name }),
|
|
2569
|
+
/* @__PURE__ */ jsx17(AvatarFallback, { className: "text-[10px]", children: selectedAgent.name.charAt(0).toUpperCase() })
|
|
2570
|
+
] }) : null,
|
|
2571
|
+
/* @__PURE__ */ jsx17("span", { className: "max-w-[200px] truncate", children: selectedAgent?.name || agentPlaceholder }),
|
|
2572
|
+
/* @__PURE__ */ jsx17(ChevronDown2, { className: "h-4 w-4 opacity-50" })
|
|
2573
|
+
]
|
|
2574
|
+
}
|
|
2575
|
+
) }),
|
|
2576
|
+
/* @__PURE__ */ jsx17(DropdownMenuContent, { align: "start", className: "w-[280px]", children: agentOptions.map((agent) => {
|
|
2577
|
+
const isSelected = agent.id === selectedAgentId;
|
|
2578
|
+
return /* @__PURE__ */ jsxs10(
|
|
2579
|
+
DropdownMenuItem,
|
|
2580
|
+
{
|
|
2581
|
+
onClick: () => onSelectAgent?.(agent.id),
|
|
2582
|
+
className: "flex items-start gap-3 p-3 cursor-pointer",
|
|
2583
|
+
children: [
|
|
2584
|
+
agent.avatarUrl ? /* @__PURE__ */ jsxs10(Avatar, { className: "h-6 w-6 mt-0.5 shrink-0", children: [
|
|
2585
|
+
/* @__PURE__ */ jsx17(AvatarImage, { src: agent.avatarUrl, alt: agent.name }),
|
|
2586
|
+
/* @__PURE__ */ jsx17(AvatarFallback, { className: "text-[10px]", children: agent.name.charAt(0).toUpperCase() })
|
|
2587
|
+
] }) : /* @__PURE__ */ jsx17("div", { className: "h-6 w-6 mt-0.5 shrink-0 flex items-center justify-center rounded-full bg-primary/10", children: /* @__PURE__ */ jsx17(Bot2, { className: "h-3.5 w-3.5 text-primary" }) }),
|
|
2588
|
+
/* @__PURE__ */ jsxs10("div", { className: "flex-1 min-w-0", children: [
|
|
2589
|
+
/* @__PURE__ */ jsxs10("div", { className: "flex items-center gap-2", children: [
|
|
2590
|
+
/* @__PURE__ */ jsx17("span", { className: "font-medium text-sm", children: agent.name }),
|
|
2591
|
+
isSelected && /* @__PURE__ */ jsx17(Check2, { className: "h-4 w-4 text-primary shrink-0" })
|
|
2592
|
+
] }),
|
|
2593
|
+
agent.description && /* @__PURE__ */ jsx17("p", { className: "text-xs text-muted-foreground mt-0.5 line-clamp-2", children: agent.description })
|
|
2594
|
+
] })
|
|
2595
|
+
]
|
|
2596
|
+
},
|
|
2597
|
+
agent.id
|
|
2598
|
+
);
|
|
2599
|
+
}) })
|
|
2600
|
+
] }),
|
|
2601
|
+
!showAgentSelector && isMobile && /* @__PURE__ */ jsx17("span", { className: "text-sm font-medium truncate max-w-[150px] ml-2", children: currentThreadTitle || config.branding?.title || "Chat" })
|
|
2346
2602
|
] }),
|
|
2603
|
+
/* @__PURE__ */ jsx17("div", { className: "flex-1" }),
|
|
2347
2604
|
/* @__PURE__ */ jsxs10("div", { className: "flex items-center gap-1", children: [
|
|
2348
2605
|
showCustomComponentButton && config.customComponent && /* @__PURE__ */ jsxs10(Tooltip, { children: [
|
|
2349
2606
|
/* @__PURE__ */ jsx17(TooltipTrigger, { asChild: true, children: /* @__PURE__ */ jsx17(
|
|
@@ -2408,10 +2665,10 @@ var ChatHeader = ({
|
|
|
2408
2665
|
};
|
|
2409
2666
|
|
|
2410
2667
|
// src/components/chat/ChatInput.tsx
|
|
2411
|
-
import { useState as useState6, useRef as
|
|
2668
|
+
import { useState as useState6, useRef as useRef6, useCallback as useCallback3, useEffect as useEffect9, memo as memo2 } from "react";
|
|
2412
2669
|
|
|
2413
2670
|
// src/components/chat/UserContext.tsx
|
|
2414
|
-
import { createContext as createContext2, useCallback as useCallback2, useContext as useContext2, useEffect as
|
|
2671
|
+
import { createContext as createContext2, useCallback as useCallback2, useContext as useContext2, useEffect as useEffect8, useMemo as useMemo2, useState as useState5 } from "react";
|
|
2415
2672
|
import { jsx as jsx18 } from "react/jsx-runtime";
|
|
2416
2673
|
var Ctx = createContext2(void 0);
|
|
2417
2674
|
var ChatUserContextProvider = ({ children, initial }) => {
|
|
@@ -2419,7 +2676,7 @@ var ChatUserContextProvider = ({ children, initial }) => {
|
|
|
2419
2676
|
updatedAt: Date.now(),
|
|
2420
2677
|
...initial ?? {}
|
|
2421
2678
|
}));
|
|
2422
|
-
|
|
2679
|
+
useEffect8(() => {
|
|
2423
2680
|
if (!initial) return;
|
|
2424
2681
|
setCtx((prev) => ({
|
|
2425
2682
|
...prev,
|
|
@@ -2490,7 +2747,7 @@ import {
|
|
|
2490
2747
|
Loader2
|
|
2491
2748
|
} from "lucide-react";
|
|
2492
2749
|
import { Fragment as Fragment4, jsx as jsx20, jsxs as jsxs11 } from "react/jsx-runtime";
|
|
2493
|
-
var FileUploadItem = ({ file, progress, onCancel })
|
|
2750
|
+
var FileUploadItem = memo2(function FileUploadItem2({ file, progress, onCancel }) {
|
|
2494
2751
|
const guessTypeFromName = (name) => {
|
|
2495
2752
|
const ext = (name || "").split(".").pop()?.toLowerCase();
|
|
2496
2753
|
switch (ext) {
|
|
@@ -2548,10 +2805,10 @@ var FileUploadItem = ({ file, progress, onCancel }) => {
|
|
|
2548
2805
|
}
|
|
2549
2806
|
)
|
|
2550
2807
|
] }) }) });
|
|
2551
|
-
};
|
|
2552
|
-
var AttachmentPreview = ({ attachment, onRemove })
|
|
2808
|
+
});
|
|
2809
|
+
var AttachmentPreview = memo2(function AttachmentPreview2({ attachment, onRemove }) {
|
|
2553
2810
|
const [isPlaying, setIsPlaying] = useState6(false);
|
|
2554
|
-
const audioRef =
|
|
2811
|
+
const audioRef = useRef6(null);
|
|
2555
2812
|
const handlePlayPause = () => {
|
|
2556
2813
|
if (audioRef.current) {
|
|
2557
2814
|
if (isPlaying) {
|
|
@@ -2649,8 +2906,8 @@ var AttachmentPreview = ({ attachment, onRemove }) => {
|
|
|
2649
2906
|
] }),
|
|
2650
2907
|
attachment.fileName && attachment.kind !== "audio" && /* @__PURE__ */ jsx20("div", { className: "absolute bottom-0 left-0 right-0 bg-black/70 text-white text-xs p-1 rounded-b", children: /* @__PURE__ */ jsx20("p", { className: "truncate", children: attachment.fileName }) })
|
|
2651
2908
|
] }) });
|
|
2652
|
-
};
|
|
2653
|
-
var AudioRecorder = ({ isRecording, onStartRecording, onStopRecording, onCancel, recordingDuration, config })
|
|
2909
|
+
});
|
|
2910
|
+
var AudioRecorder = memo2(function AudioRecorder2({ isRecording, onStartRecording, onStopRecording, onCancel, recordingDuration, config }) {
|
|
2654
2911
|
const formatTime = (seconds) => {
|
|
2655
2912
|
const mins = Math.floor(seconds / 60);
|
|
2656
2913
|
const secs = seconds % 60;
|
|
@@ -2704,8 +2961,8 @@ var AudioRecorder = ({ isRecording, onStartRecording, onStopRecording, onCancel,
|
|
|
2704
2961
|
)
|
|
2705
2962
|
] })
|
|
2706
2963
|
] }) }) });
|
|
2707
|
-
};
|
|
2708
|
-
var ChatInput = ({
|
|
2964
|
+
});
|
|
2965
|
+
var ChatInput = memo2(function ChatInput2({
|
|
2709
2966
|
value,
|
|
2710
2967
|
onChange,
|
|
2711
2968
|
onSubmit,
|
|
@@ -2723,18 +2980,18 @@ var ChatInput = ({
|
|
|
2723
2980
|
acceptedFileTypes = ["image/*", "video/*", "audio/*"],
|
|
2724
2981
|
className = "",
|
|
2725
2982
|
config
|
|
2726
|
-
})
|
|
2983
|
+
}) {
|
|
2727
2984
|
const [isRecording, setIsRecording] = useState6(false);
|
|
2728
2985
|
const { setContext } = useChatUserContext();
|
|
2729
2986
|
const [recordingDuration, setRecordingDuration] = useState6(0);
|
|
2730
2987
|
const [uploadProgress, setUploadProgress] = useState6(/* @__PURE__ */ new Map());
|
|
2731
|
-
const textareaRef =
|
|
2732
|
-
const fileInputRef =
|
|
2733
|
-
const mediaRecorderRef =
|
|
2734
|
-
const recordingStartTime =
|
|
2735
|
-
const recordingInterval =
|
|
2736
|
-
const mediaStreamRef =
|
|
2737
|
-
|
|
2988
|
+
const textareaRef = useRef6(null);
|
|
2989
|
+
const fileInputRef = useRef6(null);
|
|
2990
|
+
const mediaRecorderRef = useRef6(null);
|
|
2991
|
+
const recordingStartTime = useRef6(0);
|
|
2992
|
+
const recordingInterval = useRef6(null);
|
|
2993
|
+
const mediaStreamRef = useRef6(null);
|
|
2994
|
+
useEffect9(() => {
|
|
2738
2995
|
return () => {
|
|
2739
2996
|
if (mediaStreamRef.current) {
|
|
2740
2997
|
mediaStreamRef.current.getTracks().forEach((track) => track.stop());
|
|
@@ -3065,16 +3322,16 @@ var ChatInput = ({
|
|
|
3065
3322
|
] })
|
|
3066
3323
|
] })
|
|
3067
3324
|
] }) }) });
|
|
3068
|
-
};
|
|
3325
|
+
});
|
|
3069
3326
|
|
|
3070
3327
|
// src/components/chat/UserProfile.tsx
|
|
3071
3328
|
import { useState as useState7 } from "react";
|
|
3072
3329
|
|
|
3073
3330
|
// src/components/ui/scroll-area.tsx
|
|
3074
|
-
import * as
|
|
3331
|
+
import * as React11 from "react";
|
|
3075
3332
|
import * as ScrollAreaPrimitive from "@radix-ui/react-scroll-area";
|
|
3076
3333
|
import { jsx as jsx21, jsxs as jsxs12 } from "react/jsx-runtime";
|
|
3077
|
-
var ScrollArea =
|
|
3334
|
+
var ScrollArea = React11.forwardRef(({ className, children, viewportClassName, onScroll, onScrollCapture, ...props }, ref) => {
|
|
3078
3335
|
return /* @__PURE__ */ jsxs12(
|
|
3079
3336
|
ScrollAreaPrimitive.Root,
|
|
3080
3337
|
{
|
|
@@ -3154,9 +3411,9 @@ import {
|
|
|
3154
3411
|
Lightbulb,
|
|
3155
3412
|
Info,
|
|
3156
3413
|
Heart,
|
|
3157
|
-
Bot as
|
|
3414
|
+
Bot as Bot3,
|
|
3158
3415
|
Pencil,
|
|
3159
|
-
Check as
|
|
3416
|
+
Check as Check3,
|
|
3160
3417
|
X as X3
|
|
3161
3418
|
} from "lucide-react";
|
|
3162
3419
|
import { Fragment as Fragment5, jsx as jsx22, jsxs as jsxs13 } from "react/jsx-runtime";
|
|
@@ -3423,7 +3680,7 @@ var UserProfile = ({
|
|
|
3423
3680
|
{
|
|
3424
3681
|
className: "flex items-start gap-3 p-3 rounded-lg bg-muted/50 group",
|
|
3425
3682
|
children: [
|
|
3426
|
-
/* @__PURE__ */ jsx22("div", { className: "mt-0.5 shrink-0", children: memory.source === "agent" ? /* @__PURE__ */ jsx22(
|
|
3683
|
+
/* @__PURE__ */ jsx22("div", { className: "mt-0.5 shrink-0", children: memory.source === "agent" ? /* @__PURE__ */ jsx22(Bot3, { className: "h-4 w-4 text-primary" }) : getMemoryCategoryIcon(memory.category) }),
|
|
3427
3684
|
/* @__PURE__ */ jsxs13("div", { className: "flex-1 min-w-0", children: [
|
|
3428
3685
|
/* @__PURE__ */ jsxs13("div", { className: "flex items-center gap-2 mb-0.5", children: [
|
|
3429
3686
|
/* @__PURE__ */ jsx22("span", { className: "text-xs text-muted-foreground", children: getMemoryCategoryLabel(memory.category) }),
|
|
@@ -3470,7 +3727,7 @@ var UserProfile = ({
|
|
|
3470
3727
|
onClick: handleSaveEdit,
|
|
3471
3728
|
disabled: !editingMemoryContent.trim(),
|
|
3472
3729
|
children: [
|
|
3473
|
-
/* @__PURE__ */ jsx22(
|
|
3730
|
+
/* @__PURE__ */ jsx22(Check3, { className: "h-3.5 w-3.5 mr-1" }),
|
|
3474
3731
|
"Salvar"
|
|
3475
3732
|
]
|
|
3476
3733
|
}
|
|
@@ -3533,7 +3790,7 @@ var UserProfile = ({
|
|
|
3533
3790
|
};
|
|
3534
3791
|
|
|
3535
3792
|
// src/components/chat/ChatUI.tsx
|
|
3536
|
-
import { Sparkles } from "lucide-react";
|
|
3793
|
+
import { Sparkles, ArrowRight, MessageSquare, Lightbulb as Lightbulb2, Zap, HelpCircle } from "lucide-react";
|
|
3537
3794
|
import { jsx as jsx23, jsxs as jsxs14 } from "react/jsx-runtime";
|
|
3538
3795
|
var ChatUI = ({
|
|
3539
3796
|
messages = [],
|
|
@@ -3546,10 +3803,16 @@ var ChatUI = ({
|
|
|
3546
3803
|
user,
|
|
3547
3804
|
assistant,
|
|
3548
3805
|
suggestions = [],
|
|
3806
|
+
messageSuggestions = {},
|
|
3807
|
+
agentOptions = [],
|
|
3808
|
+
selectedAgentId = null,
|
|
3809
|
+
onSelectAgent,
|
|
3549
3810
|
className = "",
|
|
3550
3811
|
onAddMemory,
|
|
3551
3812
|
onUpdateMemory,
|
|
3552
|
-
onDeleteMemory
|
|
3813
|
+
onDeleteMemory,
|
|
3814
|
+
initialInput,
|
|
3815
|
+
onInitialInputConsumed
|
|
3553
3816
|
}) => {
|
|
3554
3817
|
const config = mergeConfig(defaultChatConfig, userConfig);
|
|
3555
3818
|
const [isMobile, setIsMobile] = useState8(false);
|
|
@@ -3567,9 +3830,9 @@ var ChatUI = ({
|
|
|
3567
3830
|
}
|
|
3568
3831
|
return false;
|
|
3569
3832
|
};
|
|
3833
|
+
const [inputValue, setInputValue] = useState8("");
|
|
3834
|
+
const [attachments, setAttachments] = useState8([]);
|
|
3570
3835
|
const [state, setState] = useState8({
|
|
3571
|
-
input: "",
|
|
3572
|
-
attachments: [],
|
|
3573
3836
|
isRecording: false,
|
|
3574
3837
|
selectedThreadId: currentThreadId,
|
|
3575
3838
|
isAtBottom: true,
|
|
@@ -3581,23 +3844,48 @@ var ChatUI = ({
|
|
|
3581
3844
|
isSidebarCollapsed: false
|
|
3582
3845
|
// No longer used for main sidebar
|
|
3583
3846
|
});
|
|
3584
|
-
|
|
3847
|
+
useEffect10(() => {
|
|
3585
3848
|
if (currentThreadId !== state.selectedThreadId) {
|
|
3586
3849
|
setState((prev) => ({ ...prev, selectedThreadId: currentThreadId }));
|
|
3587
3850
|
}
|
|
3588
3851
|
}, [currentThreadId]);
|
|
3589
|
-
const
|
|
3590
|
-
const
|
|
3852
|
+
const initialInputApplied = useRef7(false);
|
|
3853
|
+
const initialInputConsumedRef = useRef7(false);
|
|
3854
|
+
useEffect10(() => {
|
|
3855
|
+
if (initialInput && !initialInputApplied.current) {
|
|
3856
|
+
setInputValue(initialInput);
|
|
3857
|
+
initialInputApplied.current = true;
|
|
3858
|
+
}
|
|
3859
|
+
}, [initialInput]);
|
|
3860
|
+
const messagesEndRef = useRef7(null);
|
|
3861
|
+
const scrollAreaRef = useRef7(null);
|
|
3862
|
+
const stateRef = useRef7(state);
|
|
3863
|
+
const inputValueRef = useRef7(inputValue);
|
|
3864
|
+
const attachmentsRef = useRef7(attachments);
|
|
3865
|
+
useEffect10(() => {
|
|
3866
|
+
stateRef.current = state;
|
|
3867
|
+
}, [state]);
|
|
3868
|
+
useEffect10(() => {
|
|
3869
|
+
inputValueRef.current = inputValue;
|
|
3870
|
+
}, [inputValue]);
|
|
3871
|
+
useEffect10(() => {
|
|
3872
|
+
attachmentsRef.current = attachments;
|
|
3873
|
+
}, [attachments]);
|
|
3591
3874
|
const [isCustomMounted, setIsCustomMounted] = useState8(false);
|
|
3592
3875
|
const [isCustomVisible, setIsCustomVisible] = useState8(false);
|
|
3593
3876
|
const createStateCallback = useCallback4(
|
|
3594
3877
|
(setter) => ({
|
|
3595
3878
|
setState: (newState) => setter?.(newState),
|
|
3596
|
-
getState: () =>
|
|
3879
|
+
getState: () => ({
|
|
3880
|
+
...stateRef.current,
|
|
3881
|
+
input: inputValueRef.current,
|
|
3882
|
+
attachments: attachmentsRef.current
|
|
3883
|
+
})
|
|
3597
3884
|
}),
|
|
3598
|
-
[
|
|
3885
|
+
[]
|
|
3886
|
+
// No dependencies - uses refs for latest state
|
|
3599
3887
|
);
|
|
3600
|
-
|
|
3888
|
+
useEffect10(() => {
|
|
3601
3889
|
const checkMobile = () => {
|
|
3602
3890
|
setIsMobile(globalThis.innerWidth < 1024);
|
|
3603
3891
|
};
|
|
@@ -3605,7 +3893,7 @@ var ChatUI = ({
|
|
|
3605
3893
|
globalThis.addEventListener("resize", checkMobile);
|
|
3606
3894
|
return () => globalThis.removeEventListener("resize", checkMobile);
|
|
3607
3895
|
}, []);
|
|
3608
|
-
|
|
3896
|
+
useEffect10(() => {
|
|
3609
3897
|
if (!isMobile || !config.customComponent?.component) return;
|
|
3610
3898
|
if (state.showSidebar) {
|
|
3611
3899
|
setIsCustomMounted(true);
|
|
@@ -3616,7 +3904,7 @@ var ChatUI = ({
|
|
|
3616
3904
|
return () => clearTimeout(t);
|
|
3617
3905
|
}
|
|
3618
3906
|
}, [state.showSidebar, isMobile, config.customComponent]);
|
|
3619
|
-
|
|
3907
|
+
useEffect10(() => {
|
|
3620
3908
|
if (!state.isAtBottom) return;
|
|
3621
3909
|
const viewport = scrollAreaRef.current;
|
|
3622
3910
|
if (!viewport) return;
|
|
@@ -3632,15 +3920,16 @@ var ChatUI = ({
|
|
|
3632
3920
|
const isAtBottom = scrollHeight - scrollTop - clientHeight < 50;
|
|
3633
3921
|
setState((prev) => ({ ...prev, isAtBottom }));
|
|
3634
3922
|
}, []);
|
|
3635
|
-
const handleSendMessage = useCallback4((content,
|
|
3636
|
-
if (!content.trim() &&
|
|
3637
|
-
callbacks.onSendMessage?.(content,
|
|
3638
|
-
|
|
3639
|
-
|
|
3640
|
-
|
|
3641
|
-
|
|
3642
|
-
|
|
3643
|
-
|
|
3923
|
+
const handleSendMessage = useCallback4((content, messageAttachments = []) => {
|
|
3924
|
+
if (!content.trim() && messageAttachments.length === 0) return;
|
|
3925
|
+
callbacks.onSendMessage?.(content, messageAttachments, createStateCallback());
|
|
3926
|
+
if (initialInputApplied.current && !initialInputConsumedRef.current) {
|
|
3927
|
+
initialInputConsumedRef.current = true;
|
|
3928
|
+
onInitialInputConsumed?.();
|
|
3929
|
+
}
|
|
3930
|
+
setInputValue("");
|
|
3931
|
+
setAttachments([]);
|
|
3932
|
+
}, [callbacks, createStateCallback, onInitialInputConsumed]);
|
|
3644
3933
|
const handleMessageAction = useCallback4((event) => {
|
|
3645
3934
|
const { action, messageId, content } = event;
|
|
3646
3935
|
switch (action) {
|
|
@@ -3661,7 +3950,7 @@ var ChatUI = ({
|
|
|
3661
3950
|
}
|
|
3662
3951
|
}, [callbacks, createStateCallback]);
|
|
3663
3952
|
const handleCreateThread = useCallback4((title) => {
|
|
3664
|
-
callbacks.onCreateThread?.(title, createStateCallback(
|
|
3953
|
+
callbacks.onCreateThread?.(title, createStateCallback());
|
|
3665
3954
|
}, [callbacks, createStateCallback]);
|
|
3666
3955
|
const handleSelectThread = useCallback4((threadId) => {
|
|
3667
3956
|
callbacks.onSelectThread?.(threadId, createStateCallback());
|
|
@@ -3686,23 +3975,54 @@ var ChatUI = ({
|
|
|
3686
3975
|
}
|
|
3687
3976
|
return component;
|
|
3688
3977
|
}, [config?.customComponent?.component, closeSidebar, isMobile]);
|
|
3978
|
+
const SuggestionIconComponents = [MessageSquare, Lightbulb2, Zap, HelpCircle];
|
|
3689
3979
|
const renderSuggestions = () => {
|
|
3690
3980
|
if (messages.length > 0 || !suggestions.length) return null;
|
|
3691
|
-
return /* @__PURE__ */ jsxs14("div", { className: "
|
|
3692
|
-
/* @__PURE__ */
|
|
3693
|
-
|
|
3694
|
-
|
|
3695
|
-
|
|
3696
|
-
|
|
3981
|
+
return /* @__PURE__ */ jsxs14("div", { className: "flex flex-col items-center justify-center min-h-[60vh] py-8 px-4", children: [
|
|
3982
|
+
/* @__PURE__ */ jsxs14("div", { className: "text-center mb-8", children: [
|
|
3983
|
+
/* @__PURE__ */ jsx23("div", { className: "inline-flex items-center justify-center w-14 h-14 rounded-2xl bg-gradient-to-br from-primary/20 to-primary/5 mb-4 shadow-sm", children: /* @__PURE__ */ jsx23(Sparkles, { className: "w-7 h-7 text-primary" }) }),
|
|
3984
|
+
/* @__PURE__ */ jsx23("h2", { className: "text-xl font-semibold mb-2", children: config.branding.title }),
|
|
3985
|
+
/* @__PURE__ */ jsx23("p", { className: "text-muted-foreground text-sm max-w-md", children: config.branding.subtitle })
|
|
3986
|
+
] }),
|
|
3987
|
+
/* @__PURE__ */ jsx23("div", { className: "grid grid-cols-1 sm:grid-cols-2 gap-3 w-full max-w-2xl", children: suggestions.map((suggestion, index) => /* @__PURE__ */ jsxs14(
|
|
3988
|
+
"button",
|
|
3697
3989
|
{
|
|
3698
|
-
|
|
3990
|
+
type: "button",
|
|
3699
3991
|
onClick: () => handleSendMessage(suggestion),
|
|
3700
|
-
|
|
3992
|
+
className: "group relative flex items-start gap-3 p-4 text-left rounded-xl border bg-card hover:bg-accent/50 hover:border-accent transition-all duration-200 hover:shadow-sm",
|
|
3993
|
+
children: [
|
|
3994
|
+
(() => {
|
|
3995
|
+
const IconComponent = SuggestionIconComponents[index % SuggestionIconComponents.length];
|
|
3996
|
+
return /* @__PURE__ */ jsx23("div", { className: "flex items-center justify-center w-8 h-8 rounded-lg bg-primary/10 text-primary shrink-0 group-hover:bg-primary/15 transition-colors", children: /* @__PURE__ */ jsx23(IconComponent, { className: "h-4 w-4" }) });
|
|
3997
|
+
})(),
|
|
3998
|
+
/* @__PURE__ */ jsx23("div", { className: "flex-1 min-w-0 pr-6", children: /* @__PURE__ */ jsx23("p", { className: "text-sm font-medium leading-snug line-clamp-2", children: suggestion }) }),
|
|
3999
|
+
/* @__PURE__ */ jsx23(ArrowRight, { className: "absolute right-4 top-1/2 -translate-y-1/2 h-4 w-4 text-muted-foreground opacity-0 group-hover:opacity-100 transition-opacity" })
|
|
4000
|
+
]
|
|
3701
4001
|
},
|
|
3702
4002
|
index
|
|
3703
4003
|
)) })
|
|
3704
4004
|
] });
|
|
3705
4005
|
};
|
|
4006
|
+
const renderInlineSuggestions = (messageId) => {
|
|
4007
|
+
const items = messageSuggestions?.[messageId];
|
|
4008
|
+
if (!items || items.length === 0) return null;
|
|
4009
|
+
return /* @__PURE__ */ jsx23("div", { className: "flex flex-wrap gap-2 mt-2 ml-11", children: items.map((suggestion, index) => /* @__PURE__ */ jsxs14(
|
|
4010
|
+
"button",
|
|
4011
|
+
{
|
|
4012
|
+
type: "button",
|
|
4013
|
+
onClick: () => handleSendMessage(suggestion),
|
|
4014
|
+
className: "group inline-flex items-center gap-1.5 px-3 py-1.5 text-sm rounded-full border border-border bg-background hover:bg-accent hover:border-accent-foreground/20 transition-all duration-150 text-foreground/80 hover:text-foreground",
|
|
4015
|
+
children: [
|
|
4016
|
+
/* @__PURE__ */ jsx23(Sparkles, { className: "h-3 w-3 text-primary opacity-70 group-hover:opacity-100" }),
|
|
4017
|
+
/* @__PURE__ */ jsx23("span", { className: "max-w-[200px] truncate", children: suggestion })
|
|
4018
|
+
]
|
|
4019
|
+
},
|
|
4020
|
+
`${messageId}-suggestion-${index}`
|
|
4021
|
+
)) });
|
|
4022
|
+
};
|
|
4023
|
+
const shouldShowAgentSelector = Boolean(
|
|
4024
|
+
config.agentSelector?.enabled && onSelectAgent && agentOptions.length > 0 && (!config.agentSelector?.hideIfSingle || agentOptions.length > 1)
|
|
4025
|
+
);
|
|
3706
4026
|
return /* @__PURE__ */ jsx23(TooltipProvider, { children: /* @__PURE__ */ jsx23(SidebarProvider, { defaultOpen: true, children: /* @__PURE__ */ jsxs14("div", { className: `flex h-[100svh] md:h-screen bg-background w-full overflow-hidden ${className}`, children: [
|
|
3707
4027
|
/* @__PURE__ */ jsx23(
|
|
3708
4028
|
Sidebar2,
|
|
@@ -3743,7 +4063,11 @@ var ChatUI = ({
|
|
|
3743
4063
|
isMobile,
|
|
3744
4064
|
onCustomComponentToggle: () => setState((prev) => ({ ...prev, showSidebar: !prev.showSidebar })),
|
|
3745
4065
|
onNewThread: handleCreateThread,
|
|
3746
|
-
showCustomComponentButton: !!config?.customComponent?.component
|
|
4066
|
+
showCustomComponentButton: !!config?.customComponent?.component,
|
|
4067
|
+
showAgentSelector: shouldShowAgentSelector,
|
|
4068
|
+
agentOptions,
|
|
4069
|
+
selectedAgentId,
|
|
4070
|
+
onSelectAgent
|
|
3747
4071
|
}
|
|
3748
4072
|
),
|
|
3749
4073
|
/* @__PURE__ */ jsxs14("div", { className: "flex flex-1 flex-row min-h-0 overflow-hidden", children: [
|
|
@@ -3757,27 +4081,34 @@ var ChatUI = ({
|
|
|
3757
4081
|
onScrollCapture: handleScroll,
|
|
3758
4082
|
children: /* @__PURE__ */ jsxs14("div", { className: "max-w-4xl mx-auto space-y-4 pb-4", children: [
|
|
3759
4083
|
renderSuggestions(),
|
|
3760
|
-
messages.map((message) =>
|
|
3761
|
-
|
|
3762
|
-
|
|
3763
|
-
|
|
3764
|
-
|
|
3765
|
-
|
|
3766
|
-
|
|
3767
|
-
|
|
3768
|
-
|
|
3769
|
-
|
|
3770
|
-
|
|
3771
|
-
|
|
3772
|
-
|
|
3773
|
-
|
|
3774
|
-
|
|
3775
|
-
|
|
3776
|
-
|
|
3777
|
-
|
|
3778
|
-
|
|
3779
|
-
|
|
3780
|
-
|
|
4084
|
+
messages.map((message, index) => {
|
|
4085
|
+
const prevMessage = index > 0 ? messages[index - 1] : null;
|
|
4086
|
+
const isGrouped = prevMessage !== null && prevMessage.role === message.role;
|
|
4087
|
+
return /* @__PURE__ */ jsxs14("div", { className: isGrouped ? "space-y-1 -mt-2" : "space-y-2", children: [
|
|
4088
|
+
/* @__PURE__ */ jsx23(
|
|
4089
|
+
Message,
|
|
4090
|
+
{
|
|
4091
|
+
message,
|
|
4092
|
+
userAvatar: user?.avatar,
|
|
4093
|
+
userName: user?.name,
|
|
4094
|
+
assistantAvatar: assistant?.avatar,
|
|
4095
|
+
assistantName: assistant?.name,
|
|
4096
|
+
showTimestamp: config.ui.showTimestamps,
|
|
4097
|
+
showAvatar: config.ui.showAvatars,
|
|
4098
|
+
enableCopy: config.features.enableMessageCopy,
|
|
4099
|
+
enableEdit: config.features.enableMessageEditing,
|
|
4100
|
+
enableRegenerate: config.features.enableRegeneration,
|
|
4101
|
+
enableToolCallsDisplay: config.features.enableToolCallsDisplay,
|
|
4102
|
+
compactMode: config.ui.compactMode,
|
|
4103
|
+
onAction: handleMessageAction,
|
|
4104
|
+
toolUsedLabel: config.labels.toolUsed,
|
|
4105
|
+
thinkingLabel: config.labels.thinking,
|
|
4106
|
+
isGrouped
|
|
4107
|
+
}
|
|
4108
|
+
),
|
|
4109
|
+
message.role === "assistant" && renderInlineSuggestions(message.id)
|
|
4110
|
+
] }, message.id);
|
|
4111
|
+
}),
|
|
3781
4112
|
/* @__PURE__ */ jsx23("div", { ref: messagesEndRef })
|
|
3782
4113
|
] })
|
|
3783
4114
|
}
|
|
@@ -3785,11 +4116,17 @@ var ChatUI = ({
|
|
|
3785
4116
|
/* @__PURE__ */ jsx23("div", { className: "bg-background pb-[env(safe-area-inset-bottom)]", children: /* @__PURE__ */ jsx23(
|
|
3786
4117
|
ChatInput,
|
|
3787
4118
|
{
|
|
3788
|
-
value:
|
|
3789
|
-
onChange: (value) =>
|
|
4119
|
+
value: inputValue,
|
|
4120
|
+
onChange: (value) => {
|
|
4121
|
+
setInputValue(value);
|
|
4122
|
+
if (initialInputApplied.current && !initialInputConsumedRef.current) {
|
|
4123
|
+
initialInputConsumedRef.current = true;
|
|
4124
|
+
onInitialInputConsumed?.();
|
|
4125
|
+
}
|
|
4126
|
+
},
|
|
3790
4127
|
onSubmit: handleSendMessage,
|
|
3791
|
-
attachments
|
|
3792
|
-
onAttachmentsChange:
|
|
4128
|
+
attachments,
|
|
4129
|
+
onAttachmentsChange: setAttachments,
|
|
3793
4130
|
placeholder: config.labels.inputPlaceholder,
|
|
3794
4131
|
disabled: false,
|
|
3795
4132
|
isGenerating,
|
|
@@ -3829,7 +4166,7 @@ var ChatUI = ({
|
|
|
3829
4166
|
}
|
|
3830
4167
|
)
|
|
3831
4168
|
] }),
|
|
3832
|
-
/* @__PURE__ */ jsx23(
|
|
4169
|
+
isUserProfileOpen && /* @__PURE__ */ jsx23(
|
|
3833
4170
|
UserProfile,
|
|
3834
4171
|
{
|
|
3835
4172
|
isOpen: isUserProfileOpen,
|
|
@@ -3852,10 +4189,10 @@ var ChatUI = ({
|
|
|
3852
4189
|
};
|
|
3853
4190
|
|
|
3854
4191
|
// src/components/chat/ThreadManager.tsx
|
|
3855
|
-
import { useState as useState9, useRef as
|
|
4192
|
+
import { useState as useState9, useRef as useRef8, useEffect as useEffect11 } from "react";
|
|
3856
4193
|
import {
|
|
3857
4194
|
Plus as Plus4,
|
|
3858
|
-
MessageSquare,
|
|
4195
|
+
MessageSquare as MessageSquare2,
|
|
3859
4196
|
MoreVertical as MoreVertical2,
|
|
3860
4197
|
Edit2 as Edit22,
|
|
3861
4198
|
Trash2 as Trash24,
|
|
@@ -3865,14 +4202,14 @@ import {
|
|
|
3865
4202
|
Calendar as Calendar2,
|
|
3866
4203
|
Hash,
|
|
3867
4204
|
X as X4,
|
|
3868
|
-
Check as
|
|
4205
|
+
Check as Check4
|
|
3869
4206
|
} from "lucide-react";
|
|
3870
4207
|
import { Fragment as Fragment6, jsx as jsx24, jsxs as jsxs15 } from "react/jsx-runtime";
|
|
3871
4208
|
var ThreadItem = ({ thread, isActive, config, onSelect, onRename, onDelete, onArchive }) => {
|
|
3872
4209
|
const [isEditing, setIsEditing] = useState9(false);
|
|
3873
4210
|
const [editTitle, setEditTitle] = useState9(thread.title);
|
|
3874
|
-
const inputRef =
|
|
3875
|
-
|
|
4211
|
+
const inputRef = useRef8(null);
|
|
4212
|
+
useEffect11(() => {
|
|
3876
4213
|
if (isEditing && inputRef.current) {
|
|
3877
4214
|
inputRef.current.focus();
|
|
3878
4215
|
inputRef.current.select();
|
|
@@ -3910,7 +4247,7 @@ var ThreadItem = ({ thread, isActive, config, onSelect, onRename, onDelete, onAr
|
|
|
3910
4247
|
placeholder: config?.labels?.threadNamePlaceholder || "Conversation name"
|
|
3911
4248
|
}
|
|
3912
4249
|
),
|
|
3913
|
-
/* @__PURE__ */ jsx24(Button, { size: "sm", variant: "ghost", onClick: handleSaveEdit, children: /* @__PURE__ */ jsx24(
|
|
4250
|
+
/* @__PURE__ */ jsx24(Button, { size: "sm", variant: "ghost", onClick: handleSaveEdit, children: /* @__PURE__ */ jsx24(Check4, { className: "h-3 w-3" }) }),
|
|
3914
4251
|
/* @__PURE__ */ jsx24(Button, { size: "sm", variant: "ghost", onClick: handleCancelEdit, children: /* @__PURE__ */ jsx24(X4, { className: "h-3 w-3" }) })
|
|
3915
4252
|
] }) : /* @__PURE__ */ jsxs15(Fragment6, { children: [
|
|
3916
4253
|
/* @__PURE__ */ jsx24("h4", { className: "font-medium text-sm truncate mb-1", children: thread.title }),
|
|
@@ -4043,7 +4380,7 @@ var ThreadManager = ({
|
|
|
4043
4380
|
/* @__PURE__ */ jsxs15(CardHeader, { className: "border-b", children: [
|
|
4044
4381
|
/* @__PURE__ */ jsxs15("div", { className: "flex items-center justify-between", children: [
|
|
4045
4382
|
/* @__PURE__ */ jsxs15(CardTitle, { className: "flex items-center gap-2", children: [
|
|
4046
|
-
/* @__PURE__ */ jsx24(
|
|
4383
|
+
/* @__PURE__ */ jsx24(MessageSquare2, { className: "h-5 w-5" }),
|
|
4047
4384
|
config?.labels?.newChat || "Conversations"
|
|
4048
4385
|
] }),
|
|
4049
4386
|
/* @__PURE__ */ jsx24(Button, { variant: "ghost", size: "icon", onClick: onClose, children: /* @__PURE__ */ jsx24(X4, { className: "h-4 w-4" }) })
|
|
@@ -4086,7 +4423,7 @@ var ThreadManager = ({
|
|
|
4086
4423
|
/* @__PURE__ */ jsxs15(CardContent, { className: "p-0 flex-1", children: [
|
|
4087
4424
|
/* @__PURE__ */ jsx24("div", { className: "p-4", children: onCreateThread && /* @__PURE__ */ jsx24(CreateThreadDialog2, { onCreateThread, config }) }),
|
|
4088
4425
|
/* @__PURE__ */ jsx24(ScrollArea, { className: "h-[calc(100vh-280px)]", children: /* @__PURE__ */ jsx24("div", { className: "px-4 pb-4 space-y-4", children: Object.keys(groupedThreads).length === 0 ? /* @__PURE__ */ jsxs15("div", { className: "text-center py-8 text-muted-foreground", children: [
|
|
4089
|
-
/* @__PURE__ */ jsx24(
|
|
4426
|
+
/* @__PURE__ */ jsx24(MessageSquare2, { className: "h-12 w-12 mx-auto mb-3 opacity-50" }),
|
|
4090
4427
|
/* @__PURE__ */ jsx24("p", { className: "text-sm", children: searchQuery ? config?.labels?.noThreadsFound || "No conversations found" : config?.labels?.noThreadsYet || "No conversations yet" })
|
|
4091
4428
|
] }) : Object.entries(groupedThreads).map(([group, groupThreads]) => /* @__PURE__ */ jsxs15("div", { children: [
|
|
4092
4429
|
/* @__PURE__ */ jsx24("h3", { className: "text-sm font-medium text-muted-foreground mb-2 px-2", children: group }),
|
|
@@ -4106,7 +4443,7 @@ var ThreadManager = ({
|
|
|
4106
4443
|
] }, group)) }) })
|
|
4107
4444
|
] })
|
|
4108
4445
|
] }) }),
|
|
4109
|
-
/* @__PURE__ */ jsx24(AlertDialog, { open: !!deleteThreadId, onOpenChange: () => setDeleteThreadId(null), children: /* @__PURE__ */ jsxs15(AlertDialogContent, { children: [
|
|
4446
|
+
deleteThreadId && /* @__PURE__ */ jsx24(AlertDialog, { open: !!deleteThreadId, onOpenChange: () => setDeleteThreadId(null), children: /* @__PURE__ */ jsxs15(AlertDialogContent, { children: [
|
|
4110
4447
|
/* @__PURE__ */ jsxs15(AlertDialogHeader, { children: [
|
|
4111
4448
|
/* @__PURE__ */ jsx24(AlertDialogTitle, { children: config?.labels?.deleteConfirmTitle || "Delete Conversation" }),
|
|
4112
4449
|
/* @__PURE__ */ jsx24(AlertDialogDescription, { children: config?.labels?.deleteConfirmDescription || "Are you sure you want to delete this conversation? This action cannot be undone." })
|