@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.cjs
CHANGED
|
@@ -64,6 +64,11 @@ var defaultChatConfig = {
|
|
|
64
64
|
title: "Chat Assistant",
|
|
65
65
|
subtitle: "How can I help you today?"
|
|
66
66
|
},
|
|
67
|
+
agentSelector: {
|
|
68
|
+
enabled: false,
|
|
69
|
+
label: "Select agent",
|
|
70
|
+
hideIfSingle: true
|
|
71
|
+
},
|
|
67
72
|
labels: {
|
|
68
73
|
inputPlaceholder: "Type your message...",
|
|
69
74
|
sendButton: "Send",
|
|
@@ -156,6 +161,10 @@ function mergeConfig(_baseConfig, userConfig) {
|
|
|
156
161
|
...defaultChatConfig.ui,
|
|
157
162
|
...userConfig.ui
|
|
158
163
|
},
|
|
164
|
+
agentSelector: {
|
|
165
|
+
...defaultChatConfig.agentSelector,
|
|
166
|
+
...userConfig.agentSelector
|
|
167
|
+
},
|
|
159
168
|
customComponent: userConfig.customComponent || defaultChatConfig.customComponent,
|
|
160
169
|
headerActions: userConfig.headerActions || defaultChatConfig.headerActions
|
|
161
170
|
};
|
|
@@ -286,6 +295,7 @@ var configUtils = {
|
|
|
286
295
|
var import_react = require("react");
|
|
287
296
|
var import_react_markdown = __toESM(require("react-markdown"), 1);
|
|
288
297
|
var import_remark_gfm = __toESM(require("remark-gfm"), 1);
|
|
298
|
+
var import_remark_breaks = __toESM(require("remark-breaks"), 1);
|
|
289
299
|
var import_rehype_highlight = __toESM(require("rehype-highlight"), 1);
|
|
290
300
|
|
|
291
301
|
// src/components/ui/button.tsx
|
|
@@ -566,7 +576,25 @@ function TooltipContent({
|
|
|
566
576
|
// src/components/chat/Message.tsx
|
|
567
577
|
var import_lucide_react = require("lucide-react");
|
|
568
578
|
var import_jsx_runtime7 = require("react/jsx-runtime");
|
|
569
|
-
var
|
|
579
|
+
var MarkdownErrorBoundary = class extends import_react.Component {
|
|
580
|
+
constructor(props) {
|
|
581
|
+
super(props);
|
|
582
|
+
this.state = { hasError: false };
|
|
583
|
+
}
|
|
584
|
+
static getDerivedStateFromError(_error) {
|
|
585
|
+
return { hasError: true };
|
|
586
|
+
}
|
|
587
|
+
componentDidCatch(error, errorInfo) {
|
|
588
|
+
console.warn("[Markdown] Falling back to simple rendering due to:", error.message);
|
|
589
|
+
}
|
|
590
|
+
render() {
|
|
591
|
+
if (this.state.hasError) {
|
|
592
|
+
return this.props.fallback;
|
|
593
|
+
}
|
|
594
|
+
return this.props.children;
|
|
595
|
+
}
|
|
596
|
+
};
|
|
597
|
+
var ThinkingIndicator = (0, import_react.memo)(function ThinkingIndicator2({ label = "Thinking..." }) {
|
|
570
598
|
return /* @__PURE__ */ (0, import_jsx_runtime7.jsxs)("div", { className: "flex items-center gap-2 py-2", children: [
|
|
571
599
|
/* @__PURE__ */ (0, import_jsx_runtime7.jsxs)("div", { className: "flex gap-1", children: [
|
|
572
600
|
/* @__PURE__ */ (0, import_jsx_runtime7.jsx)(
|
|
@@ -593,36 +621,61 @@ var ThinkingIndicator = ({ label = "Thinking..." }) => {
|
|
|
593
621
|
] }),
|
|
594
622
|
/* @__PURE__ */ (0, import_jsx_runtime7.jsx)("span", { className: "text-sm text-muted-foreground animate-pulse", children: label })
|
|
595
623
|
] });
|
|
624
|
+
});
|
|
625
|
+
var markdownComponents = {
|
|
626
|
+
code: ({ node, className, children, ...props }) => {
|
|
627
|
+
const inline = props.inline;
|
|
628
|
+
const match = /language-(\w+)/.exec(className || "");
|
|
629
|
+
return !inline && match ? /* @__PURE__ */ (0, import_jsx_runtime7.jsx)("pre", { className: "relative", children: /* @__PURE__ */ (0, import_jsx_runtime7.jsx)("code", { className, ...props, children }) }) : /* @__PURE__ */ (0, import_jsx_runtime7.jsx)("code", { className: "bg-muted px-1 py-0.5 rounded text-sm", ...props, children });
|
|
630
|
+
}
|
|
596
631
|
};
|
|
597
|
-
var
|
|
632
|
+
var remarkPluginsWithGfm = [import_remark_gfm.default, import_remark_breaks.default];
|
|
633
|
+
var remarkPluginsSimple = [import_remark_breaks.default];
|
|
634
|
+
var rehypePluginsDefault = [import_rehype_highlight.default];
|
|
635
|
+
var rehypePluginsEmpty = [];
|
|
636
|
+
var SimpleMarkdown = (0, import_react.memo)(function SimpleMarkdown2({
|
|
637
|
+
content,
|
|
638
|
+
isStreaming = false
|
|
639
|
+
}) {
|
|
640
|
+
return /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(
|
|
641
|
+
import_react_markdown.default,
|
|
642
|
+
{
|
|
643
|
+
remarkPlugins: remarkPluginsSimple,
|
|
644
|
+
rehypePlugins: isStreaming ? rehypePluginsEmpty : rehypePluginsDefault,
|
|
645
|
+
components: markdownComponents,
|
|
646
|
+
children: content
|
|
647
|
+
}
|
|
648
|
+
);
|
|
649
|
+
});
|
|
650
|
+
var FullMarkdown = (0, import_react.memo)(function FullMarkdown2({
|
|
651
|
+
content,
|
|
652
|
+
isStreaming = false
|
|
653
|
+
}) {
|
|
654
|
+
return /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(
|
|
655
|
+
import_react_markdown.default,
|
|
656
|
+
{
|
|
657
|
+
remarkPlugins: remarkPluginsWithGfm,
|
|
658
|
+
rehypePlugins: isStreaming ? rehypePluginsEmpty : rehypePluginsDefault,
|
|
659
|
+
components: markdownComponents,
|
|
660
|
+
children: content
|
|
661
|
+
}
|
|
662
|
+
);
|
|
663
|
+
});
|
|
664
|
+
var StreamingText = (0, import_react.memo)(function StreamingText2({
|
|
598
665
|
content,
|
|
599
666
|
isStreaming = false,
|
|
600
667
|
thinkingLabel = "Thinking..."
|
|
601
|
-
})
|
|
668
|
+
}) {
|
|
602
669
|
const hasContent = content.trim().length > 0;
|
|
603
670
|
return /* @__PURE__ */ (0, import_jsx_runtime7.jsxs)("div", { className: "prose prose-sm max-w-none dark:prose-invert", children: [
|
|
604
|
-
hasContent ? /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(
|
|
605
|
-
import_react_markdown.default,
|
|
606
|
-
{
|
|
607
|
-
remarkPlugins: [import_remark_gfm.default],
|
|
608
|
-
rehypePlugins: isStreaming ? [] : [import_rehype_highlight.default],
|
|
609
|
-
components: {
|
|
610
|
-
code: ({ node, className, children, ...props }) => {
|
|
611
|
-
const inline = props.inline;
|
|
612
|
-
const match = /language-(\w+)/.exec(className || "");
|
|
613
|
-
return !inline && match ? /* @__PURE__ */ (0, import_jsx_runtime7.jsx)("pre", { className: "relative", children: /* @__PURE__ */ (0, import_jsx_runtime7.jsx)("code", { className, ...props, children }) }) : /* @__PURE__ */ (0, import_jsx_runtime7.jsx)("code", { className: "bg-muted px-1 py-0.5 rounded text-sm", ...props, children });
|
|
614
|
-
}
|
|
615
|
-
},
|
|
616
|
-
children: content
|
|
617
|
-
}
|
|
618
|
-
) : isStreaming ? (
|
|
671
|
+
hasContent ? /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(MarkdownErrorBoundary, { fallback: /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(SimpleMarkdown, { content, isStreaming }), children: /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(FullMarkdown, { content, isStreaming }) }) : isStreaming ? (
|
|
619
672
|
// Show thinking indicator while waiting for first token
|
|
620
673
|
/* @__PURE__ */ (0, import_jsx_runtime7.jsx)(ThinkingIndicator, { label: thinkingLabel })
|
|
621
674
|
) : null,
|
|
622
675
|
isStreaming && hasContent && /* @__PURE__ */ (0, import_jsx_runtime7.jsx)("span", { className: "inline-block w-2 h-4 bg-primary animate-pulse ml-1" })
|
|
623
676
|
] });
|
|
624
|
-
};
|
|
625
|
-
var MediaRenderer = ({ attachment })
|
|
677
|
+
});
|
|
678
|
+
var MediaRenderer = (0, import_react.memo)(function MediaRenderer2({ attachment }) {
|
|
626
679
|
const [isPlaying, setIsPlaying] = (0, import_react.useState)(false);
|
|
627
680
|
const audioRef = (0, import_react.useRef)(null);
|
|
628
681
|
const videoRef = (0, import_react.useRef)(null);
|
|
@@ -696,8 +749,8 @@ var MediaRenderer = ({ attachment }) => {
|
|
|
696
749
|
default:
|
|
697
750
|
return null;
|
|
698
751
|
}
|
|
699
|
-
};
|
|
700
|
-
var ToolCallsDisplay = ({ toolCalls, label })
|
|
752
|
+
});
|
|
753
|
+
var ToolCallsDisplay = (0, import_react.memo)(function ToolCallsDisplay2({ toolCalls, label }) {
|
|
701
754
|
const [expandedCall, setExpandedCall] = (0, import_react.useState)(null);
|
|
702
755
|
const getStatusIcon = (status) => {
|
|
703
756
|
switch (status) {
|
|
@@ -766,8 +819,48 @@ var ToolCallsDisplay = ({ toolCalls, label }) => {
|
|
|
766
819
|
] }, call.id);
|
|
767
820
|
})
|
|
768
821
|
] });
|
|
822
|
+
});
|
|
823
|
+
var arePropsEqual = (prevProps, nextProps) => {
|
|
824
|
+
if (prevProps.message.id !== nextProps.message.id) return false;
|
|
825
|
+
if (prevProps.message.content !== nextProps.message.content) return false;
|
|
826
|
+
if (prevProps.message.isStreaming !== nextProps.message.isStreaming) return false;
|
|
827
|
+
if (prevProps.message.isComplete !== nextProps.message.isComplete) return false;
|
|
828
|
+
if (prevProps.message.isEdited !== nextProps.message.isEdited) return false;
|
|
829
|
+
if (prevProps.message.timestamp !== nextProps.message.timestamp) return false;
|
|
830
|
+
if (prevProps.message.toolCalls !== nextProps.message.toolCalls) {
|
|
831
|
+
const prevCalls = prevProps.message.toolCalls;
|
|
832
|
+
const nextCalls = nextProps.message.toolCalls;
|
|
833
|
+
if (!prevCalls || !nextCalls || prevCalls.length !== nextCalls.length) return false;
|
|
834
|
+
for (let i = 0; i < prevCalls.length; i++) {
|
|
835
|
+
if (prevCalls[i].id !== nextCalls[i].id || prevCalls[i].status !== nextCalls[i].status || prevCalls[i].result !== nextCalls[i].result) {
|
|
836
|
+
return false;
|
|
837
|
+
}
|
|
838
|
+
}
|
|
839
|
+
}
|
|
840
|
+
if (prevProps.message.attachments !== nextProps.message.attachments) {
|
|
841
|
+
const prevAtt = prevProps.message.attachments;
|
|
842
|
+
const nextAtt = nextProps.message.attachments;
|
|
843
|
+
if (!prevAtt || !nextAtt || prevAtt.length !== nextAtt.length) return false;
|
|
844
|
+
}
|
|
845
|
+
if (prevProps.isUser !== nextProps.isUser) return false;
|
|
846
|
+
if (prevProps.userAvatar !== nextProps.userAvatar) return false;
|
|
847
|
+
if (prevProps.userName !== nextProps.userName) return false;
|
|
848
|
+
if (prevProps.assistantName !== nextProps.assistantName) return false;
|
|
849
|
+
if (prevProps.showTimestamp !== nextProps.showTimestamp) return false;
|
|
850
|
+
if (prevProps.showAvatar !== nextProps.showAvatar) return false;
|
|
851
|
+
if (prevProps.enableCopy !== nextProps.enableCopy) return false;
|
|
852
|
+
if (prevProps.enableEdit !== nextProps.enableEdit) return false;
|
|
853
|
+
if (prevProps.enableRegenerate !== nextProps.enableRegenerate) return false;
|
|
854
|
+
if (prevProps.enableToolCallsDisplay !== nextProps.enableToolCallsDisplay) return false;
|
|
855
|
+
if (prevProps.compactMode !== nextProps.compactMode) return false;
|
|
856
|
+
if (prevProps.className !== nextProps.className) return false;
|
|
857
|
+
if (prevProps.toolUsedLabel !== nextProps.toolUsedLabel) return false;
|
|
858
|
+
if (prevProps.thinkingLabel !== nextProps.thinkingLabel) return false;
|
|
859
|
+
if (prevProps.isGrouped !== nextProps.isGrouped) return false;
|
|
860
|
+
if (prevProps.assistantAvatar !== nextProps.assistantAvatar) return false;
|
|
861
|
+
return true;
|
|
769
862
|
};
|
|
770
|
-
var Message = ({
|
|
863
|
+
var Message = (0, import_react.memo)(({
|
|
771
864
|
message,
|
|
772
865
|
isUser,
|
|
773
866
|
userAvatar,
|
|
@@ -784,7 +877,8 @@ var Message = ({
|
|
|
784
877
|
onAction,
|
|
785
878
|
className = "",
|
|
786
879
|
toolUsedLabel,
|
|
787
|
-
thinkingLabel = "Thinking..."
|
|
880
|
+
thinkingLabel = "Thinking...",
|
|
881
|
+
isGrouped = false
|
|
788
882
|
}) => {
|
|
789
883
|
const [isEditing, setIsEditing] = (0, import_react.useState)(false);
|
|
790
884
|
const [editContent, setEditContent] = (0, import_react.useState)(message.content);
|
|
@@ -834,7 +928,7 @@ var Message = ({
|
|
|
834
928
|
onMouseEnter: () => setShowActions(true),
|
|
835
929
|
onMouseLeave: () => setShowActions(false),
|
|
836
930
|
children: [
|
|
837
|
-
/* @__PURE__ */ (0, import_jsx_runtime7.jsxs)("div", { className: `flex gap-3 ${messageIsUser ? "flex-row-reverse" : "flex-row"} w-full mb-1`, children: [
|
|
931
|
+
!isGrouped && /* @__PURE__ */ (0, import_jsx_runtime7.jsxs)("div", { className: `flex gap-3 ${messageIsUser ? "flex-row-reverse" : "flex-row"} w-full mb-1`, children: [
|
|
838
932
|
showAvatar && /* @__PURE__ */ (0, import_jsx_runtime7.jsx)("div", { className: `flex-shrink-0 ${compactMode ? "mt-1" : "mt-0"}`, children: /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(Avatar, { className: compactMode ? "h-6 w-6" : "h-8 w-8", children: messageIsUser ? /* @__PURE__ */ (0, import_jsx_runtime7.jsxs)(import_jsx_runtime7.Fragment, { children: [
|
|
839
933
|
/* @__PURE__ */ (0, import_jsx_runtime7.jsx)(AvatarImage, { src: userAvatar, alt: userName }),
|
|
840
934
|
/* @__PURE__ */ (0, import_jsx_runtime7.jsx)(AvatarFallback, { className: "bg-primary text-primary-foreground", children: userName.charAt(0).toUpperCase() })
|
|
@@ -845,7 +939,7 @@ var Message = ({
|
|
|
845
939
|
message.isEdited && /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(Badge, { variant: "outline", className: "text-xs", children: "editado" })
|
|
846
940
|
] })
|
|
847
941
|
] }),
|
|
848
|
-
/* @__PURE__ */ (0, import_jsx_runtime7.jsx)("div", { className: `flex-1 min-w-0 ${messageIsUser ? "text-right" : "text-left"}`, children: /* @__PURE__ */ (0, import_jsx_runtime7.jsxs)("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: [
|
|
942
|
+
/* @__PURE__ */ (0, import_jsx_runtime7.jsx)("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__ */ (0, import_jsx_runtime7.jsxs)("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: [
|
|
849
943
|
isEditing ? /* @__PURE__ */ (0, import_jsx_runtime7.jsxs)("div", { className: "space-y-2", children: [
|
|
850
944
|
/* @__PURE__ */ (0, import_jsx_runtime7.jsx)(
|
|
851
945
|
Textarea,
|
|
@@ -923,7 +1017,7 @@ var Message = ({
|
|
|
923
1017
|
]
|
|
924
1018
|
}
|
|
925
1019
|
) });
|
|
926
|
-
};
|
|
1020
|
+
}, arePropsEqual);
|
|
927
1021
|
|
|
928
1022
|
// src/components/chat/Sidebar.tsx
|
|
929
1023
|
var import_react2 = require("react");
|
|
@@ -948,7 +1042,7 @@ function Input({ className, type, ...props }) {
|
|
|
948
1042
|
}
|
|
949
1043
|
|
|
950
1044
|
// src/components/ui/sidebar.tsx
|
|
951
|
-
var
|
|
1045
|
+
var React4 = __toESM(require("react"), 1);
|
|
952
1046
|
var import_react_slot3 = require("@radix-ui/react-slot");
|
|
953
1047
|
var import_class_variance_authority3 = require("class-variance-authority");
|
|
954
1048
|
var import_lucide_react3 = require("lucide-react");
|
|
@@ -956,18 +1050,26 @@ var import_lucide_react3 = require("lucide-react");
|
|
|
956
1050
|
// src/hooks/use-mobile.ts
|
|
957
1051
|
var React2 = __toESM(require("react"), 1);
|
|
958
1052
|
var MOBILE_BREAKPOINT = 768;
|
|
1053
|
+
function getInitialIsMobile() {
|
|
1054
|
+
if (typeof window === "undefined") return false;
|
|
1055
|
+
return window.innerWidth < MOBILE_BREAKPOINT;
|
|
1056
|
+
}
|
|
959
1057
|
function useIsMobile() {
|
|
960
|
-
const [isMobile, setIsMobile] = React2.useState(
|
|
1058
|
+
const [isMobile, setIsMobile] = React2.useState(getInitialIsMobile);
|
|
961
1059
|
React2.useEffect(() => {
|
|
962
1060
|
const mql = window.matchMedia(`(max-width: ${MOBILE_BREAKPOINT - 1}px)`);
|
|
963
1061
|
const onChange = () => {
|
|
964
1062
|
setIsMobile(window.innerWidth < MOBILE_BREAKPOINT);
|
|
965
1063
|
};
|
|
966
1064
|
mql.addEventListener("change", onChange);
|
|
1065
|
+
window.addEventListener("resize", onChange);
|
|
967
1066
|
setIsMobile(window.innerWidth < MOBILE_BREAKPOINT);
|
|
968
|
-
return () =>
|
|
1067
|
+
return () => {
|
|
1068
|
+
mql.removeEventListener("change", onChange);
|
|
1069
|
+
window.removeEventListener("resize", onChange);
|
|
1070
|
+
};
|
|
969
1071
|
}, []);
|
|
970
|
-
return
|
|
1072
|
+
return isMobile;
|
|
971
1073
|
}
|
|
972
1074
|
|
|
973
1075
|
// src/components/ui/separator.tsx
|
|
@@ -995,11 +1097,30 @@ function Separator({
|
|
|
995
1097
|
}
|
|
996
1098
|
|
|
997
1099
|
// src/components/ui/sheet.tsx
|
|
1100
|
+
var React3 = __toESM(require("react"), 1);
|
|
998
1101
|
var SheetPrimitive = __toESM(require("@radix-ui/react-dialog"), 1);
|
|
999
1102
|
var import_lucide_react2 = require("lucide-react");
|
|
1000
1103
|
var import_jsx_runtime10 = require("react/jsx-runtime");
|
|
1001
|
-
function
|
|
1002
|
-
|
|
1104
|
+
function cleanupBodyStyles() {
|
|
1105
|
+
if (typeof document !== "undefined" && document.body.style.pointerEvents === "none") {
|
|
1106
|
+
document.body.style.pointerEvents = "";
|
|
1107
|
+
}
|
|
1108
|
+
}
|
|
1109
|
+
function Sheet({ open, onOpenChange, ...props }) {
|
|
1110
|
+
const prevOpenRef = React3.useRef(open);
|
|
1111
|
+
React3.useEffect(() => {
|
|
1112
|
+
if (prevOpenRef.current === true && open === false) {
|
|
1113
|
+
const timeout = setTimeout(cleanupBodyStyles, 350);
|
|
1114
|
+
return () => clearTimeout(timeout);
|
|
1115
|
+
}
|
|
1116
|
+
prevOpenRef.current = open;
|
|
1117
|
+
}, [open]);
|
|
1118
|
+
React3.useEffect(() => {
|
|
1119
|
+
return () => {
|
|
1120
|
+
cleanupBodyStyles();
|
|
1121
|
+
};
|
|
1122
|
+
}, []);
|
|
1123
|
+
return /* @__PURE__ */ (0, import_jsx_runtime10.jsx)(SheetPrimitive.Root, { "data-slot": "sheet", open, onOpenChange, ...props });
|
|
1003
1124
|
}
|
|
1004
1125
|
function SheetPortal({
|
|
1005
1126
|
...props
|
|
@@ -1015,7 +1136,10 @@ function SheetOverlay({
|
|
|
1015
1136
|
{
|
|
1016
1137
|
"data-slot": "sheet-overlay",
|
|
1017
1138
|
className: cn(
|
|
1018
|
-
"
|
|
1139
|
+
"fixed inset-0 z-50 bg-black/50",
|
|
1140
|
+
"data-[state=open]:animate-in data-[state=closed]:animate-out",
|
|
1141
|
+
"data-[state=closed]:fade-out-0 data-[state=open]:fade-in-0",
|
|
1142
|
+
"data-[state=closed]:pointer-events-none",
|
|
1019
1143
|
className
|
|
1020
1144
|
),
|
|
1021
1145
|
...props
|
|
@@ -1034,6 +1158,7 @@ function SheetContent({
|
|
|
1034
1158
|
SheetPrimitive.Content,
|
|
1035
1159
|
{
|
|
1036
1160
|
"data-slot": "sheet-content",
|
|
1161
|
+
"aria-describedby": void 0,
|
|
1037
1162
|
className: cn(
|
|
1038
1163
|
"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",
|
|
1039
1164
|
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",
|
|
@@ -1099,9 +1224,9 @@ var SIDEBAR_WIDTH = "16rem";
|
|
|
1099
1224
|
var SIDEBAR_WIDTH_MOBILE = "18rem";
|
|
1100
1225
|
var SIDEBAR_WIDTH_ICON = "3rem";
|
|
1101
1226
|
var SIDEBAR_KEYBOARD_SHORTCUT = "b";
|
|
1102
|
-
var SidebarContext =
|
|
1227
|
+
var SidebarContext = React4.createContext(null);
|
|
1103
1228
|
function useSidebar() {
|
|
1104
|
-
const context =
|
|
1229
|
+
const context = React4.useContext(SidebarContext);
|
|
1105
1230
|
if (!context) {
|
|
1106
1231
|
throw new Error("useSidebar must be used within a SidebarProvider.");
|
|
1107
1232
|
}
|
|
@@ -1117,10 +1242,10 @@ function SidebarProvider({
|
|
|
1117
1242
|
...props
|
|
1118
1243
|
}) {
|
|
1119
1244
|
const isMobile = useIsMobile();
|
|
1120
|
-
const [openMobile, setOpenMobile] =
|
|
1121
|
-
const [_open, _setOpen] =
|
|
1245
|
+
const [openMobile, setOpenMobile] = React4.useState(false);
|
|
1246
|
+
const [_open, _setOpen] = React4.useState(defaultOpen);
|
|
1122
1247
|
const open = openProp ?? _open;
|
|
1123
|
-
const setOpen =
|
|
1248
|
+
const setOpen = React4.useCallback(
|
|
1124
1249
|
(value) => {
|
|
1125
1250
|
const openState = typeof value === "function" ? value(open) : value;
|
|
1126
1251
|
if (setOpenProp) {
|
|
@@ -1132,10 +1257,10 @@ function SidebarProvider({
|
|
|
1132
1257
|
},
|
|
1133
1258
|
[setOpenProp, open]
|
|
1134
1259
|
);
|
|
1135
|
-
const toggleSidebar =
|
|
1260
|
+
const toggleSidebar = React4.useCallback(() => {
|
|
1136
1261
|
return isMobile ? setOpenMobile((open2) => !open2) : setOpen((open2) => !open2);
|
|
1137
1262
|
}, [isMobile, setOpen, setOpenMobile]);
|
|
1138
|
-
|
|
1263
|
+
React4.useEffect(() => {
|
|
1139
1264
|
const handleKeyDown = (event) => {
|
|
1140
1265
|
if (event.key === SIDEBAR_KEYBOARD_SHORTCUT && (event.metaKey || event.ctrlKey)) {
|
|
1141
1266
|
event.preventDefault();
|
|
@@ -1146,7 +1271,7 @@ function SidebarProvider({
|
|
|
1146
1271
|
return () => window.removeEventListener("keydown", handleKeyDown);
|
|
1147
1272
|
}, [toggleSidebar]);
|
|
1148
1273
|
const state = open ? "expanded" : "collapsed";
|
|
1149
|
-
const contextValue =
|
|
1274
|
+
const contextValue = React4.useMemo(
|
|
1150
1275
|
() => ({
|
|
1151
1276
|
state,
|
|
1152
1277
|
open,
|
|
@@ -1221,12 +1346,29 @@ function Sidebar({
|
|
|
1221
1346
|
}
|
|
1222
1347
|
) });
|
|
1223
1348
|
}
|
|
1349
|
+
const isCollapsed = state === "collapsed";
|
|
1350
|
+
const currentCollapsible = isCollapsed ? collapsible : "";
|
|
1351
|
+
const getGapWidth = () => {
|
|
1352
|
+
if (currentCollapsible === "offcanvas") return "0px";
|
|
1353
|
+
if (currentCollapsible === "icon") return SIDEBAR_WIDTH_ICON;
|
|
1354
|
+
return SIDEBAR_WIDTH;
|
|
1355
|
+
};
|
|
1356
|
+
const getContainerWidth = () => {
|
|
1357
|
+
if (currentCollapsible === "icon") return SIDEBAR_WIDTH_ICON;
|
|
1358
|
+
return SIDEBAR_WIDTH;
|
|
1359
|
+
};
|
|
1360
|
+
const getContainerOffset = () => {
|
|
1361
|
+
if (currentCollapsible === "offcanvas") {
|
|
1362
|
+
return side === "left" ? `calc(${SIDEBAR_WIDTH} * -1)` : `calc(${SIDEBAR_WIDTH} * -1)`;
|
|
1363
|
+
}
|
|
1364
|
+
return "0";
|
|
1365
|
+
};
|
|
1224
1366
|
return /* @__PURE__ */ (0, import_jsx_runtime11.jsxs)(
|
|
1225
1367
|
"div",
|
|
1226
1368
|
{
|
|
1227
|
-
className: "group peer text-sidebar-foreground
|
|
1369
|
+
className: "group peer text-sidebar-foreground",
|
|
1228
1370
|
"data-state": state,
|
|
1229
|
-
"data-collapsible":
|
|
1371
|
+
"data-collapsible": currentCollapsible,
|
|
1230
1372
|
"data-variant": variant,
|
|
1231
1373
|
"data-side": side,
|
|
1232
1374
|
"data-slot": "sidebar",
|
|
@@ -1236,11 +1378,10 @@ function Sidebar({
|
|
|
1236
1378
|
{
|
|
1237
1379
|
"data-slot": "sidebar-gap",
|
|
1238
1380
|
className: cn(
|
|
1239
|
-
"relative
|
|
1240
|
-
"group-data-[
|
|
1241
|
-
|
|
1242
|
-
|
|
1243
|
-
)
|
|
1381
|
+
"relative bg-transparent transition-[width] duration-200 ease-linear",
|
|
1382
|
+
"group-data-[side=right]:rotate-180"
|
|
1383
|
+
),
|
|
1384
|
+
style: { width: getGapWidth() }
|
|
1244
1385
|
}
|
|
1245
1386
|
),
|
|
1246
1387
|
/* @__PURE__ */ (0, import_jsx_runtime11.jsx)(
|
|
@@ -1248,12 +1389,16 @@ function Sidebar({
|
|
|
1248
1389
|
{
|
|
1249
1390
|
"data-slot": "sidebar-container",
|
|
1250
1391
|
className: cn(
|
|
1251
|
-
"fixed inset-y-0 z-10
|
|
1252
|
-
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)]",
|
|
1392
|
+
"fixed inset-y-0 z-10 h-screen transition-[left,right,width] duration-200 ease-linear",
|
|
1253
1393
|
// Adjust the padding for floating and inset variants.
|
|
1254
|
-
variant === "floating" || variant === "inset" ? "p-2
|
|
1394
|
+
variant === "floating" || variant === "inset" ? "p-2" : side === "left" ? "border-r" : "border-l",
|
|
1255
1395
|
className
|
|
1256
1396
|
),
|
|
1397
|
+
style: {
|
|
1398
|
+
display: "flex",
|
|
1399
|
+
width: getContainerWidth(),
|
|
1400
|
+
[side === "left" ? "left" : "right"]: getContainerOffset()
|
|
1401
|
+
},
|
|
1257
1402
|
...props,
|
|
1258
1403
|
children: /* @__PURE__ */ (0, import_jsx_runtime11.jsx)(
|
|
1259
1404
|
"div",
|
|
@@ -1276,6 +1421,15 @@ function SidebarTrigger({
|
|
|
1276
1421
|
...props
|
|
1277
1422
|
}) {
|
|
1278
1423
|
const { toggleSidebar } = useSidebar();
|
|
1424
|
+
const handleActivation = React4.useCallback((event) => {
|
|
1425
|
+
if (event.type === "touchend") {
|
|
1426
|
+
event.preventDefault();
|
|
1427
|
+
}
|
|
1428
|
+
if ("onClick" in event && onClick) {
|
|
1429
|
+
onClick(event);
|
|
1430
|
+
}
|
|
1431
|
+
toggleSidebar();
|
|
1432
|
+
}, [onClick, toggleSidebar]);
|
|
1279
1433
|
return /* @__PURE__ */ (0, import_jsx_runtime11.jsxs)(
|
|
1280
1434
|
Button,
|
|
1281
1435
|
{
|
|
@@ -1284,10 +1438,8 @@ function SidebarTrigger({
|
|
|
1284
1438
|
variant: "ghost",
|
|
1285
1439
|
size: "icon",
|
|
1286
1440
|
className: cn("size-7", className),
|
|
1287
|
-
onClick:
|
|
1288
|
-
|
|
1289
|
-
toggleSidebar();
|
|
1290
|
-
},
|
|
1441
|
+
onClick: handleActivation,
|
|
1442
|
+
onTouchEnd: handleActivation,
|
|
1291
1443
|
...props,
|
|
1292
1444
|
children: [
|
|
1293
1445
|
/* @__PURE__ */ (0, import_jsx_runtime11.jsx)(import_lucide_react3.PanelLeftIcon, {}),
|
|
@@ -1529,13 +1681,34 @@ function SidebarMenuAction({
|
|
|
1529
1681
|
}
|
|
1530
1682
|
|
|
1531
1683
|
// src/components/ui/dialog.tsx
|
|
1684
|
+
var React5 = __toESM(require("react"), 1);
|
|
1532
1685
|
var DialogPrimitive = __toESM(require("@radix-ui/react-dialog"), 1);
|
|
1533
1686
|
var import_lucide_react4 = require("lucide-react");
|
|
1534
1687
|
var import_jsx_runtime12 = require("react/jsx-runtime");
|
|
1688
|
+
function cleanupBodyStyles2() {
|
|
1689
|
+
if (typeof document !== "undefined" && document.body.style.pointerEvents === "none") {
|
|
1690
|
+
document.body.style.pointerEvents = "";
|
|
1691
|
+
}
|
|
1692
|
+
}
|
|
1535
1693
|
function Dialog({
|
|
1694
|
+
open,
|
|
1695
|
+
onOpenChange,
|
|
1536
1696
|
...props
|
|
1537
1697
|
}) {
|
|
1538
|
-
|
|
1698
|
+
const prevOpenRef = React5.useRef(open);
|
|
1699
|
+
React5.useEffect(() => {
|
|
1700
|
+
if (prevOpenRef.current === true && open === false) {
|
|
1701
|
+
const timeout = setTimeout(cleanupBodyStyles2, 250);
|
|
1702
|
+
return () => clearTimeout(timeout);
|
|
1703
|
+
}
|
|
1704
|
+
prevOpenRef.current = open;
|
|
1705
|
+
}, [open]);
|
|
1706
|
+
React5.useEffect(() => {
|
|
1707
|
+
return () => {
|
|
1708
|
+
cleanupBodyStyles2();
|
|
1709
|
+
};
|
|
1710
|
+
}, []);
|
|
1711
|
+
return /* @__PURE__ */ (0, import_jsx_runtime12.jsx)(DialogPrimitive.Root, { "data-slot": "dialog", open, onOpenChange, ...props });
|
|
1539
1712
|
}
|
|
1540
1713
|
function DialogTrigger({
|
|
1541
1714
|
...props
|
|
@@ -1556,7 +1729,10 @@ function DialogOverlay({
|
|
|
1556
1729
|
{
|
|
1557
1730
|
"data-slot": "dialog-overlay",
|
|
1558
1731
|
className: cn(
|
|
1559
|
-
"
|
|
1732
|
+
"fixed inset-0 z-50 bg-black/50",
|
|
1733
|
+
"data-[state=open]:animate-in data-[state=closed]:animate-out",
|
|
1734
|
+
"data-[state=closed]:fade-out-0 data-[state=open]:fade-in-0",
|
|
1735
|
+
"data-[state=closed]:pointer-events-none",
|
|
1560
1736
|
className
|
|
1561
1737
|
),
|
|
1562
1738
|
...props
|
|
@@ -1575,6 +1751,7 @@ function DialogContent({
|
|
|
1575
1751
|
DialogPrimitive.Content,
|
|
1576
1752
|
{
|
|
1577
1753
|
"data-slot": "dialog-content",
|
|
1754
|
+
"aria-describedby": void 0,
|
|
1578
1755
|
className: cn(
|
|
1579
1756
|
"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",
|
|
1580
1757
|
className
|
|
@@ -1649,12 +1826,33 @@ function DialogDescription({
|
|
|
1649
1826
|
}
|
|
1650
1827
|
|
|
1651
1828
|
// src/components/ui/alert-dialog.tsx
|
|
1829
|
+
var React6 = __toESM(require("react"), 1);
|
|
1652
1830
|
var AlertDialogPrimitive = __toESM(require("@radix-ui/react-alert-dialog"), 1);
|
|
1653
1831
|
var import_jsx_runtime13 = require("react/jsx-runtime");
|
|
1832
|
+
function cleanupBodyStyles3() {
|
|
1833
|
+
if (typeof document !== "undefined" && document.body.style.pointerEvents === "none") {
|
|
1834
|
+
document.body.style.pointerEvents = "";
|
|
1835
|
+
}
|
|
1836
|
+
}
|
|
1654
1837
|
function AlertDialog({
|
|
1838
|
+
open,
|
|
1839
|
+
onOpenChange,
|
|
1655
1840
|
...props
|
|
1656
1841
|
}) {
|
|
1657
|
-
|
|
1842
|
+
const prevOpenRef = React6.useRef(open);
|
|
1843
|
+
React6.useEffect(() => {
|
|
1844
|
+
if (prevOpenRef.current === true && open === false) {
|
|
1845
|
+
const timeout = setTimeout(cleanupBodyStyles3, 250);
|
|
1846
|
+
return () => clearTimeout(timeout);
|
|
1847
|
+
}
|
|
1848
|
+
prevOpenRef.current = open;
|
|
1849
|
+
}, [open]);
|
|
1850
|
+
React6.useEffect(() => {
|
|
1851
|
+
return () => {
|
|
1852
|
+
cleanupBodyStyles3();
|
|
1853
|
+
};
|
|
1854
|
+
}, []);
|
|
1855
|
+
return /* @__PURE__ */ (0, import_jsx_runtime13.jsx)(AlertDialogPrimitive.Root, { "data-slot": "alert-dialog", open, onOpenChange, ...props });
|
|
1658
1856
|
}
|
|
1659
1857
|
function AlertDialogPortal({
|
|
1660
1858
|
...props
|
|
@@ -1670,7 +1868,10 @@ function AlertDialogOverlay({
|
|
|
1670
1868
|
{
|
|
1671
1869
|
"data-slot": "alert-dialog-overlay",
|
|
1672
1870
|
className: cn(
|
|
1673
|
-
"
|
|
1871
|
+
"fixed inset-0 z-50 bg-black/50",
|
|
1872
|
+
"data-[state=open]:animate-in data-[state=closed]:animate-out",
|
|
1873
|
+
"data-[state=closed]:fade-out-0 data-[state=open]:fade-in-0",
|
|
1874
|
+
"data-[state=closed]:pointer-events-none",
|
|
1674
1875
|
className
|
|
1675
1876
|
),
|
|
1676
1877
|
...props
|
|
@@ -2128,6 +2329,13 @@ var Sidebar2 = ({
|
|
|
2128
2329
|
};
|
|
2129
2330
|
return /* @__PURE__ */ (0, import_jsx_runtime16.jsxs)(Sidebar, { collapsible: "icon", ...props, children: [
|
|
2130
2331
|
/* @__PURE__ */ (0, import_jsx_runtime16.jsxs)(SidebarHeader, { children: [
|
|
2332
|
+
/* @__PURE__ */ (0, import_jsx_runtime16.jsxs)("div", { className: "flex items-center gap-3 px-2 py-3", children: [
|
|
2333
|
+
/* @__PURE__ */ (0, import_jsx_runtime16.jsx)("div", { className: "flex items-center justify-center shrink-0", children: config.branding?.logo || /* @__PURE__ */ (0, import_jsx_runtime16.jsx)(Avatar, { className: "h-8 w-8", children: /* @__PURE__ */ (0, import_jsx_runtime16.jsx)(AvatarFallback, { className: "bg-primary text-primary-foreground", children: /* @__PURE__ */ (0, import_jsx_runtime16.jsx)(import_lucide_react7.Bot, { className: "h-4 w-4" }) }) }) }),
|
|
2334
|
+
/* @__PURE__ */ (0, import_jsx_runtime16.jsxs)("div", { className: "flex flex-col min-w-0 group-data-[collapsible=icon]:hidden", children: [
|
|
2335
|
+
/* @__PURE__ */ (0, import_jsx_runtime16.jsx)("span", { className: "text-sm font-semibold truncate", children: config.branding?.title || "Chat" }),
|
|
2336
|
+
config.branding?.subtitle && /* @__PURE__ */ (0, import_jsx_runtime16.jsx)("span", { className: "text-xs text-muted-foreground truncate", children: config.branding.subtitle })
|
|
2337
|
+
] })
|
|
2338
|
+
] }),
|
|
2131
2339
|
onCreateThread && /* @__PURE__ */ (0, import_jsx_runtime16.jsx)(
|
|
2132
2340
|
CreateThreadDialog,
|
|
2133
2341
|
{
|
|
@@ -2147,7 +2355,7 @@ var Sidebar2 = ({
|
|
|
2147
2355
|
) }) })
|
|
2148
2356
|
}
|
|
2149
2357
|
),
|
|
2150
|
-
/* @__PURE__ */ (0, import_jsx_runtime16.jsxs)("div", { className: "px-2 py-1 mt-
|
|
2358
|
+
/* @__PURE__ */ (0, import_jsx_runtime16.jsxs)("div", { className: "px-2 py-1 mt-4", children: [
|
|
2151
2359
|
/* @__PURE__ */ (0, import_jsx_runtime16.jsxs)("div", { className: "relative group-data-[collapsible=icon]:hidden", children: [
|
|
2152
2360
|
/* @__PURE__ */ (0, import_jsx_runtime16.jsx)(import_lucide_react7.Search, { className: "pointer-events-none absolute left-2 top-1/2 size-4 -translate-y-1/2 select-none opacity-50" }),
|
|
2153
2361
|
/* @__PURE__ */ (0, import_jsx_runtime16.jsx)(
|
|
@@ -2262,7 +2470,7 @@ var Sidebar2 = ({
|
|
|
2262
2470
|
}
|
|
2263
2471
|
) }),
|
|
2264
2472
|
/* @__PURE__ */ (0, import_jsx_runtime16.jsx)(SidebarRail, {}),
|
|
2265
|
-
/* @__PURE__ */ (0, import_jsx_runtime16.jsx)(AlertDialog, { open: !!deleteThreadId, onOpenChange: () => setDeleteThreadId(null), children: /* @__PURE__ */ (0, import_jsx_runtime16.jsxs)(AlertDialogContent, { children: [
|
|
2473
|
+
deleteThreadId && /* @__PURE__ */ (0, import_jsx_runtime16.jsx)(AlertDialog, { open: !!deleteThreadId, onOpenChange: () => setDeleteThreadId(null), children: /* @__PURE__ */ (0, import_jsx_runtime16.jsxs)(AlertDialogContent, { children: [
|
|
2266
2474
|
/* @__PURE__ */ (0, import_jsx_runtime16.jsxs)(AlertDialogHeader, { children: [
|
|
2267
2475
|
/* @__PURE__ */ (0, import_jsx_runtime16.jsx)(AlertDialogTitle, { children: config.labels?.deleteConfirmTitle || "Delete Conversation" }),
|
|
2268
2476
|
/* @__PURE__ */ (0, import_jsx_runtime16.jsx)(AlertDialogDescription, { children: config.labels?.deleteConfirmDescription || "Are you sure you want to delete this conversation? This action cannot be undone." })
|
|
@@ -2297,6 +2505,10 @@ var ChatHeader = ({
|
|
|
2297
2505
|
onClearAll,
|
|
2298
2506
|
showCustomComponentButton,
|
|
2299
2507
|
isMobile,
|
|
2508
|
+
showAgentSelector = false,
|
|
2509
|
+
agentOptions = [],
|
|
2510
|
+
selectedAgentId = null,
|
|
2511
|
+
onSelectAgent,
|
|
2300
2512
|
className = ""
|
|
2301
2513
|
}) => {
|
|
2302
2514
|
const [isDarkMode, setIsDarkMode] = import_react3.default.useState(() => {
|
|
@@ -2347,22 +2559,64 @@ var ChatHeader = ({
|
|
|
2347
2559
|
};
|
|
2348
2560
|
input.click();
|
|
2349
2561
|
};
|
|
2562
|
+
const selectedAgent = agentOptions.find((agent) => agent.id === selectedAgentId) || null;
|
|
2563
|
+
const agentPlaceholder = config.agentSelector?.label || "Select agent";
|
|
2350
2564
|
return /* @__PURE__ */ (0, import_jsx_runtime17.jsx)(
|
|
2351
2565
|
Card,
|
|
2352
2566
|
{
|
|
2353
2567
|
"data-chat-header": true,
|
|
2354
2568
|
className: `py-0 border-b rounded-none relative z-10 bg-background/95 backdrop-blur supports-[backdrop-filter]:bg-background/80 ${className}`,
|
|
2355
2569
|
style: isMobile ? { paddingTop: "env(safe-area-inset-top)" } : void 0,
|
|
2356
|
-
children: /* @__PURE__ */ (0, import_jsx_runtime17.jsx)(CardHeader, { className: "p-2", children: /* @__PURE__ */ (0, import_jsx_runtime17.jsxs)("div", { className: "flex items-center justify-between", children: [
|
|
2357
|
-
/* @__PURE__ */ (0, import_jsx_runtime17.
|
|
2358
|
-
/* @__PURE__ */ (0, import_jsx_runtime17.
|
|
2359
|
-
|
|
2360
|
-
|
|
2361
|
-
|
|
2362
|
-
|
|
2363
|
-
|
|
2364
|
-
|
|
2570
|
+
children: /* @__PURE__ */ (0, import_jsx_runtime17.jsx)(CardHeader, { className: "p-2", children: /* @__PURE__ */ (0, import_jsx_runtime17.jsxs)("div", { className: "flex items-center justify-between gap-2", children: [
|
|
2571
|
+
/* @__PURE__ */ (0, import_jsx_runtime17.jsxs)("div", { className: "flex items-center gap-1", children: [
|
|
2572
|
+
/* @__PURE__ */ (0, import_jsx_runtime17.jsxs)(Tooltip, { children: [
|
|
2573
|
+
/* @__PURE__ */ (0, import_jsx_runtime17.jsx)(TooltipTrigger, { asChild: true, children: /* @__PURE__ */ (0, import_jsx_runtime17.jsx)(SidebarTrigger, { className: "-ml-1" }) }),
|
|
2574
|
+
/* @__PURE__ */ (0, import_jsx_runtime17.jsx)(TooltipContent, { children: config.labels?.sidebarToggle || "Toggle Sidebar" })
|
|
2575
|
+
] }),
|
|
2576
|
+
showAgentSelector && /* @__PURE__ */ (0, import_jsx_runtime17.jsxs)(DropdownMenu, { children: [
|
|
2577
|
+
/* @__PURE__ */ (0, import_jsx_runtime17.jsx)(DropdownMenuTrigger, { asChild: true, children: /* @__PURE__ */ (0, import_jsx_runtime17.jsxs)(
|
|
2578
|
+
Button,
|
|
2579
|
+
{
|
|
2580
|
+
variant: "ghost",
|
|
2581
|
+
className: "h-9 px-3 gap-1.5 font-medium text-base hover:bg-accent/50",
|
|
2582
|
+
children: [
|
|
2583
|
+
selectedAgent?.avatarUrl ? /* @__PURE__ */ (0, import_jsx_runtime17.jsxs)(Avatar, { className: "h-5 w-5", children: [
|
|
2584
|
+
/* @__PURE__ */ (0, import_jsx_runtime17.jsx)(AvatarImage, { src: selectedAgent.avatarUrl, alt: selectedAgent.name }),
|
|
2585
|
+
/* @__PURE__ */ (0, import_jsx_runtime17.jsx)(AvatarFallback, { className: "text-[10px]", children: selectedAgent.name.charAt(0).toUpperCase() })
|
|
2586
|
+
] }) : null,
|
|
2587
|
+
/* @__PURE__ */ (0, import_jsx_runtime17.jsx)("span", { className: "max-w-[200px] truncate", children: selectedAgent?.name || agentPlaceholder }),
|
|
2588
|
+
/* @__PURE__ */ (0, import_jsx_runtime17.jsx)(import_lucide_react8.ChevronDown, { className: "h-4 w-4 opacity-50" })
|
|
2589
|
+
]
|
|
2590
|
+
}
|
|
2591
|
+
) }),
|
|
2592
|
+
/* @__PURE__ */ (0, import_jsx_runtime17.jsx)(DropdownMenuContent, { align: "start", className: "w-[280px]", children: agentOptions.map((agent) => {
|
|
2593
|
+
const isSelected = agent.id === selectedAgentId;
|
|
2594
|
+
return /* @__PURE__ */ (0, import_jsx_runtime17.jsxs)(
|
|
2595
|
+
DropdownMenuItem,
|
|
2596
|
+
{
|
|
2597
|
+
onClick: () => onSelectAgent?.(agent.id),
|
|
2598
|
+
className: "flex items-start gap-3 p-3 cursor-pointer",
|
|
2599
|
+
children: [
|
|
2600
|
+
agent.avatarUrl ? /* @__PURE__ */ (0, import_jsx_runtime17.jsxs)(Avatar, { className: "h-6 w-6 mt-0.5 shrink-0", children: [
|
|
2601
|
+
/* @__PURE__ */ (0, import_jsx_runtime17.jsx)(AvatarImage, { src: agent.avatarUrl, alt: agent.name }),
|
|
2602
|
+
/* @__PURE__ */ (0, import_jsx_runtime17.jsx)(AvatarFallback, { className: "text-[10px]", children: agent.name.charAt(0).toUpperCase() })
|
|
2603
|
+
] }) : /* @__PURE__ */ (0, import_jsx_runtime17.jsx)("div", { className: "h-6 w-6 mt-0.5 shrink-0 flex items-center justify-center rounded-full bg-primary/10", children: /* @__PURE__ */ (0, import_jsx_runtime17.jsx)(import_lucide_react8.Bot, { className: "h-3.5 w-3.5 text-primary" }) }),
|
|
2604
|
+
/* @__PURE__ */ (0, import_jsx_runtime17.jsxs)("div", { className: "flex-1 min-w-0", children: [
|
|
2605
|
+
/* @__PURE__ */ (0, import_jsx_runtime17.jsxs)("div", { className: "flex items-center gap-2", children: [
|
|
2606
|
+
/* @__PURE__ */ (0, import_jsx_runtime17.jsx)("span", { className: "font-medium text-sm", children: agent.name }),
|
|
2607
|
+
isSelected && /* @__PURE__ */ (0, import_jsx_runtime17.jsx)(import_lucide_react8.Check, { className: "h-4 w-4 text-primary shrink-0" })
|
|
2608
|
+
] }),
|
|
2609
|
+
agent.description && /* @__PURE__ */ (0, import_jsx_runtime17.jsx)("p", { className: "text-xs text-muted-foreground mt-0.5 line-clamp-2", children: agent.description })
|
|
2610
|
+
] })
|
|
2611
|
+
]
|
|
2612
|
+
},
|
|
2613
|
+
agent.id
|
|
2614
|
+
);
|
|
2615
|
+
}) })
|
|
2616
|
+
] }),
|
|
2617
|
+
!showAgentSelector && isMobile && /* @__PURE__ */ (0, import_jsx_runtime17.jsx)("span", { className: "text-sm font-medium truncate max-w-[150px] ml-2", children: currentThreadTitle || config.branding?.title || "Chat" })
|
|
2365
2618
|
] }),
|
|
2619
|
+
/* @__PURE__ */ (0, import_jsx_runtime17.jsx)("div", { className: "flex-1" }),
|
|
2366
2620
|
/* @__PURE__ */ (0, import_jsx_runtime17.jsxs)("div", { className: "flex items-center gap-1", children: [
|
|
2367
2621
|
showCustomComponentButton && config.customComponent && /* @__PURE__ */ (0, import_jsx_runtime17.jsxs)(Tooltip, { children: [
|
|
2368
2622
|
/* @__PURE__ */ (0, import_jsx_runtime17.jsx)(TooltipTrigger, { asChild: true, children: /* @__PURE__ */ (0, import_jsx_runtime17.jsx)(
|
|
@@ -2497,7 +2751,7 @@ function Progress({
|
|
|
2497
2751
|
// src/components/chat/ChatInput.tsx
|
|
2498
2752
|
var import_lucide_react9 = require("lucide-react");
|
|
2499
2753
|
var import_jsx_runtime20 = require("react/jsx-runtime");
|
|
2500
|
-
var FileUploadItem = ({ file, progress, onCancel })
|
|
2754
|
+
var FileUploadItem = (0, import_react5.memo)(function FileUploadItem2({ file, progress, onCancel }) {
|
|
2501
2755
|
const guessTypeFromName = (name) => {
|
|
2502
2756
|
const ext = (name || "").split(".").pop()?.toLowerCase();
|
|
2503
2757
|
switch (ext) {
|
|
@@ -2555,8 +2809,8 @@ var FileUploadItem = ({ file, progress, onCancel }) => {
|
|
|
2555
2809
|
}
|
|
2556
2810
|
)
|
|
2557
2811
|
] }) }) });
|
|
2558
|
-
};
|
|
2559
|
-
var AttachmentPreview = ({ attachment, onRemove })
|
|
2812
|
+
});
|
|
2813
|
+
var AttachmentPreview = (0, import_react5.memo)(function AttachmentPreview2({ attachment, onRemove }) {
|
|
2560
2814
|
const [isPlaying, setIsPlaying] = (0, import_react5.useState)(false);
|
|
2561
2815
|
const audioRef = (0, import_react5.useRef)(null);
|
|
2562
2816
|
const handlePlayPause = () => {
|
|
@@ -2656,8 +2910,8 @@ var AttachmentPreview = ({ attachment, onRemove }) => {
|
|
|
2656
2910
|
] }),
|
|
2657
2911
|
attachment.fileName && attachment.kind !== "audio" && /* @__PURE__ */ (0, import_jsx_runtime20.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_runtime20.jsx)("p", { className: "truncate", children: attachment.fileName }) })
|
|
2658
2912
|
] }) });
|
|
2659
|
-
};
|
|
2660
|
-
var AudioRecorder = ({ isRecording, onStartRecording, onStopRecording, onCancel, recordingDuration, config })
|
|
2913
|
+
});
|
|
2914
|
+
var AudioRecorder = (0, import_react5.memo)(function AudioRecorder2({ isRecording, onStartRecording, onStopRecording, onCancel, recordingDuration, config }) {
|
|
2661
2915
|
const formatTime = (seconds) => {
|
|
2662
2916
|
const mins = Math.floor(seconds / 60);
|
|
2663
2917
|
const secs = seconds % 60;
|
|
@@ -2711,8 +2965,8 @@ var AudioRecorder = ({ isRecording, onStartRecording, onStopRecording, onCancel,
|
|
|
2711
2965
|
)
|
|
2712
2966
|
] })
|
|
2713
2967
|
] }) }) });
|
|
2714
|
-
};
|
|
2715
|
-
var ChatInput = ({
|
|
2968
|
+
});
|
|
2969
|
+
var ChatInput = (0, import_react5.memo)(function ChatInput2({
|
|
2716
2970
|
value,
|
|
2717
2971
|
onChange,
|
|
2718
2972
|
onSubmit,
|
|
@@ -2730,7 +2984,7 @@ var ChatInput = ({
|
|
|
2730
2984
|
acceptedFileTypes = ["image/*", "video/*", "audio/*"],
|
|
2731
2985
|
className = "",
|
|
2732
2986
|
config
|
|
2733
|
-
})
|
|
2987
|
+
}) {
|
|
2734
2988
|
const [isRecording, setIsRecording] = (0, import_react5.useState)(false);
|
|
2735
2989
|
const { setContext } = useChatUserContext();
|
|
2736
2990
|
const [recordingDuration, setRecordingDuration] = (0, import_react5.useState)(0);
|
|
@@ -3072,16 +3326,16 @@ var ChatInput = ({
|
|
|
3072
3326
|
] })
|
|
3073
3327
|
] })
|
|
3074
3328
|
] }) }) });
|
|
3075
|
-
};
|
|
3329
|
+
});
|
|
3076
3330
|
|
|
3077
3331
|
// src/components/chat/UserProfile.tsx
|
|
3078
3332
|
var import_react6 = require("react");
|
|
3079
3333
|
|
|
3080
3334
|
// src/components/ui/scroll-area.tsx
|
|
3081
|
-
var
|
|
3335
|
+
var React11 = __toESM(require("react"), 1);
|
|
3082
3336
|
var ScrollAreaPrimitive = __toESM(require("@radix-ui/react-scroll-area"), 1);
|
|
3083
3337
|
var import_jsx_runtime21 = require("react/jsx-runtime");
|
|
3084
|
-
var ScrollArea =
|
|
3338
|
+
var ScrollArea = React11.forwardRef(({ className, children, viewportClassName, onScroll, onScrollCapture, ...props }, ref) => {
|
|
3085
3339
|
return /* @__PURE__ */ (0, import_jsx_runtime21.jsxs)(
|
|
3086
3340
|
ScrollAreaPrimitive.Root,
|
|
3087
3341
|
{
|
|
@@ -3527,10 +3781,16 @@ var ChatUI = ({
|
|
|
3527
3781
|
user,
|
|
3528
3782
|
assistant,
|
|
3529
3783
|
suggestions = [],
|
|
3784
|
+
messageSuggestions = {},
|
|
3785
|
+
agentOptions = [],
|
|
3786
|
+
selectedAgentId = null,
|
|
3787
|
+
onSelectAgent,
|
|
3530
3788
|
className = "",
|
|
3531
3789
|
onAddMemory,
|
|
3532
3790
|
onUpdateMemory,
|
|
3533
|
-
onDeleteMemory
|
|
3791
|
+
onDeleteMemory,
|
|
3792
|
+
initialInput,
|
|
3793
|
+
onInitialInputConsumed
|
|
3534
3794
|
}) => {
|
|
3535
3795
|
const config = mergeConfig(defaultChatConfig, userConfig);
|
|
3536
3796
|
const [isMobile, setIsMobile] = (0, import_react7.useState)(false);
|
|
@@ -3548,9 +3808,9 @@ var ChatUI = ({
|
|
|
3548
3808
|
}
|
|
3549
3809
|
return false;
|
|
3550
3810
|
};
|
|
3811
|
+
const [inputValue, setInputValue] = (0, import_react7.useState)("");
|
|
3812
|
+
const [attachments, setAttachments] = (0, import_react7.useState)([]);
|
|
3551
3813
|
const [state, setState] = (0, import_react7.useState)({
|
|
3552
|
-
input: "",
|
|
3553
|
-
attachments: [],
|
|
3554
3814
|
isRecording: false,
|
|
3555
3815
|
selectedThreadId: currentThreadId,
|
|
3556
3816
|
isAtBottom: true,
|
|
@@ -3567,16 +3827,41 @@ var ChatUI = ({
|
|
|
3567
3827
|
setState((prev) => ({ ...prev, selectedThreadId: currentThreadId }));
|
|
3568
3828
|
}
|
|
3569
3829
|
}, [currentThreadId]);
|
|
3830
|
+
const initialInputApplied = (0, import_react7.useRef)(false);
|
|
3831
|
+
const initialInputConsumedRef = (0, import_react7.useRef)(false);
|
|
3832
|
+
(0, import_react7.useEffect)(() => {
|
|
3833
|
+
if (initialInput && !initialInputApplied.current) {
|
|
3834
|
+
setInputValue(initialInput);
|
|
3835
|
+
initialInputApplied.current = true;
|
|
3836
|
+
}
|
|
3837
|
+
}, [initialInput]);
|
|
3570
3838
|
const messagesEndRef = (0, import_react7.useRef)(null);
|
|
3571
3839
|
const scrollAreaRef = (0, import_react7.useRef)(null);
|
|
3840
|
+
const stateRef = (0, import_react7.useRef)(state);
|
|
3841
|
+
const inputValueRef = (0, import_react7.useRef)(inputValue);
|
|
3842
|
+
const attachmentsRef = (0, import_react7.useRef)(attachments);
|
|
3843
|
+
(0, import_react7.useEffect)(() => {
|
|
3844
|
+
stateRef.current = state;
|
|
3845
|
+
}, [state]);
|
|
3846
|
+
(0, import_react7.useEffect)(() => {
|
|
3847
|
+
inputValueRef.current = inputValue;
|
|
3848
|
+
}, [inputValue]);
|
|
3849
|
+
(0, import_react7.useEffect)(() => {
|
|
3850
|
+
attachmentsRef.current = attachments;
|
|
3851
|
+
}, [attachments]);
|
|
3572
3852
|
const [isCustomMounted, setIsCustomMounted] = (0, import_react7.useState)(false);
|
|
3573
3853
|
const [isCustomVisible, setIsCustomVisible] = (0, import_react7.useState)(false);
|
|
3574
3854
|
const createStateCallback = (0, import_react7.useCallback)(
|
|
3575
3855
|
(setter) => ({
|
|
3576
3856
|
setState: (newState) => setter?.(newState),
|
|
3577
|
-
getState: () =>
|
|
3857
|
+
getState: () => ({
|
|
3858
|
+
...stateRef.current,
|
|
3859
|
+
input: inputValueRef.current,
|
|
3860
|
+
attachments: attachmentsRef.current
|
|
3861
|
+
})
|
|
3578
3862
|
}),
|
|
3579
|
-
[
|
|
3863
|
+
[]
|
|
3864
|
+
// No dependencies - uses refs for latest state
|
|
3580
3865
|
);
|
|
3581
3866
|
(0, import_react7.useEffect)(() => {
|
|
3582
3867
|
const checkMobile = () => {
|
|
@@ -3613,15 +3898,16 @@ var ChatUI = ({
|
|
|
3613
3898
|
const isAtBottom = scrollHeight - scrollTop - clientHeight < 50;
|
|
3614
3899
|
setState((prev) => ({ ...prev, isAtBottom }));
|
|
3615
3900
|
}, []);
|
|
3616
|
-
const handleSendMessage = (0, import_react7.useCallback)((content,
|
|
3617
|
-
if (!content.trim() &&
|
|
3618
|
-
callbacks.onSendMessage?.(content,
|
|
3619
|
-
|
|
3620
|
-
|
|
3621
|
-
|
|
3622
|
-
|
|
3623
|
-
|
|
3624
|
-
|
|
3901
|
+
const handleSendMessage = (0, import_react7.useCallback)((content, messageAttachments = []) => {
|
|
3902
|
+
if (!content.trim() && messageAttachments.length === 0) return;
|
|
3903
|
+
callbacks.onSendMessage?.(content, messageAttachments, createStateCallback());
|
|
3904
|
+
if (initialInputApplied.current && !initialInputConsumedRef.current) {
|
|
3905
|
+
initialInputConsumedRef.current = true;
|
|
3906
|
+
onInitialInputConsumed?.();
|
|
3907
|
+
}
|
|
3908
|
+
setInputValue("");
|
|
3909
|
+
setAttachments([]);
|
|
3910
|
+
}, [callbacks, createStateCallback, onInitialInputConsumed]);
|
|
3625
3911
|
const handleMessageAction = (0, import_react7.useCallback)((event) => {
|
|
3626
3912
|
const { action, messageId, content } = event;
|
|
3627
3913
|
switch (action) {
|
|
@@ -3642,7 +3928,7 @@ var ChatUI = ({
|
|
|
3642
3928
|
}
|
|
3643
3929
|
}, [callbacks, createStateCallback]);
|
|
3644
3930
|
const handleCreateThread = (0, import_react7.useCallback)((title) => {
|
|
3645
|
-
callbacks.onCreateThread?.(title, createStateCallback(
|
|
3931
|
+
callbacks.onCreateThread?.(title, createStateCallback());
|
|
3646
3932
|
}, [callbacks, createStateCallback]);
|
|
3647
3933
|
const handleSelectThread = (0, import_react7.useCallback)((threadId) => {
|
|
3648
3934
|
callbacks.onSelectThread?.(threadId, createStateCallback());
|
|
@@ -3667,23 +3953,54 @@ var ChatUI = ({
|
|
|
3667
3953
|
}
|
|
3668
3954
|
return component;
|
|
3669
3955
|
}, [config?.customComponent?.component, closeSidebar, isMobile]);
|
|
3956
|
+
const SuggestionIconComponents = [import_lucide_react11.MessageSquare, import_lucide_react11.Lightbulb, import_lucide_react11.Zap, import_lucide_react11.HelpCircle];
|
|
3670
3957
|
const renderSuggestions = () => {
|
|
3671
3958
|
if (messages.length > 0 || !suggestions.length) return null;
|
|
3672
|
-
return /* @__PURE__ */ (0, import_jsx_runtime23.jsxs)("div", { className: "
|
|
3673
|
-
/* @__PURE__ */ (0, import_jsx_runtime23.
|
|
3674
|
-
|
|
3675
|
-
|
|
3676
|
-
|
|
3677
|
-
|
|
3959
|
+
return /* @__PURE__ */ (0, import_jsx_runtime23.jsxs)("div", { className: "flex flex-col items-center justify-center min-h-[60vh] py-8 px-4", children: [
|
|
3960
|
+
/* @__PURE__ */ (0, import_jsx_runtime23.jsxs)("div", { className: "text-center mb-8", children: [
|
|
3961
|
+
/* @__PURE__ */ (0, import_jsx_runtime23.jsx)("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__ */ (0, import_jsx_runtime23.jsx)(import_lucide_react11.Sparkles, { className: "w-7 h-7 text-primary" }) }),
|
|
3962
|
+
/* @__PURE__ */ (0, import_jsx_runtime23.jsx)("h2", { className: "text-xl font-semibold mb-2", children: config.branding.title }),
|
|
3963
|
+
/* @__PURE__ */ (0, import_jsx_runtime23.jsx)("p", { className: "text-muted-foreground text-sm max-w-md", children: config.branding.subtitle })
|
|
3964
|
+
] }),
|
|
3965
|
+
/* @__PURE__ */ (0, import_jsx_runtime23.jsx)("div", { className: "grid grid-cols-1 sm:grid-cols-2 gap-3 w-full max-w-2xl", children: suggestions.map((suggestion, index) => /* @__PURE__ */ (0, import_jsx_runtime23.jsxs)(
|
|
3966
|
+
"button",
|
|
3678
3967
|
{
|
|
3679
|
-
|
|
3968
|
+
type: "button",
|
|
3680
3969
|
onClick: () => handleSendMessage(suggestion),
|
|
3681
|
-
|
|
3970
|
+
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",
|
|
3971
|
+
children: [
|
|
3972
|
+
(() => {
|
|
3973
|
+
const IconComponent = SuggestionIconComponents[index % SuggestionIconComponents.length];
|
|
3974
|
+
return /* @__PURE__ */ (0, import_jsx_runtime23.jsx)("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__ */ (0, import_jsx_runtime23.jsx)(IconComponent, { className: "h-4 w-4" }) });
|
|
3975
|
+
})(),
|
|
3976
|
+
/* @__PURE__ */ (0, import_jsx_runtime23.jsx)("div", { className: "flex-1 min-w-0 pr-6", children: /* @__PURE__ */ (0, import_jsx_runtime23.jsx)("p", { className: "text-sm font-medium leading-snug line-clamp-2", children: suggestion }) }),
|
|
3977
|
+
/* @__PURE__ */ (0, import_jsx_runtime23.jsx)(import_lucide_react11.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" })
|
|
3978
|
+
]
|
|
3682
3979
|
},
|
|
3683
3980
|
index
|
|
3684
3981
|
)) })
|
|
3685
3982
|
] });
|
|
3686
3983
|
};
|
|
3984
|
+
const renderInlineSuggestions = (messageId) => {
|
|
3985
|
+
const items = messageSuggestions?.[messageId];
|
|
3986
|
+
if (!items || items.length === 0) return null;
|
|
3987
|
+
return /* @__PURE__ */ (0, import_jsx_runtime23.jsx)("div", { className: "flex flex-wrap gap-2 mt-2 ml-11", children: items.map((suggestion, index) => /* @__PURE__ */ (0, import_jsx_runtime23.jsxs)(
|
|
3988
|
+
"button",
|
|
3989
|
+
{
|
|
3990
|
+
type: "button",
|
|
3991
|
+
onClick: () => handleSendMessage(suggestion),
|
|
3992
|
+
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",
|
|
3993
|
+
children: [
|
|
3994
|
+
/* @__PURE__ */ (0, import_jsx_runtime23.jsx)(import_lucide_react11.Sparkles, { className: "h-3 w-3 text-primary opacity-70 group-hover:opacity-100" }),
|
|
3995
|
+
/* @__PURE__ */ (0, import_jsx_runtime23.jsx)("span", { className: "max-w-[200px] truncate", children: suggestion })
|
|
3996
|
+
]
|
|
3997
|
+
},
|
|
3998
|
+
`${messageId}-suggestion-${index}`
|
|
3999
|
+
)) });
|
|
4000
|
+
};
|
|
4001
|
+
const shouldShowAgentSelector = Boolean(
|
|
4002
|
+
config.agentSelector?.enabled && onSelectAgent && agentOptions.length > 0 && (!config.agentSelector?.hideIfSingle || agentOptions.length > 1)
|
|
4003
|
+
);
|
|
3687
4004
|
return /* @__PURE__ */ (0, import_jsx_runtime23.jsx)(TooltipProvider, { children: /* @__PURE__ */ (0, import_jsx_runtime23.jsx)(SidebarProvider, { defaultOpen: true, children: /* @__PURE__ */ (0, import_jsx_runtime23.jsxs)("div", { className: `flex h-[100svh] md:h-screen bg-background w-full overflow-hidden ${className}`, children: [
|
|
3688
4005
|
/* @__PURE__ */ (0, import_jsx_runtime23.jsx)(
|
|
3689
4006
|
Sidebar2,
|
|
@@ -3724,7 +4041,11 @@ var ChatUI = ({
|
|
|
3724
4041
|
isMobile,
|
|
3725
4042
|
onCustomComponentToggle: () => setState((prev) => ({ ...prev, showSidebar: !prev.showSidebar })),
|
|
3726
4043
|
onNewThread: handleCreateThread,
|
|
3727
|
-
showCustomComponentButton: !!config?.customComponent?.component
|
|
4044
|
+
showCustomComponentButton: !!config?.customComponent?.component,
|
|
4045
|
+
showAgentSelector: shouldShowAgentSelector,
|
|
4046
|
+
agentOptions,
|
|
4047
|
+
selectedAgentId,
|
|
4048
|
+
onSelectAgent
|
|
3728
4049
|
}
|
|
3729
4050
|
),
|
|
3730
4051
|
/* @__PURE__ */ (0, import_jsx_runtime23.jsxs)("div", { className: "flex flex-1 flex-row min-h-0 overflow-hidden", children: [
|
|
@@ -3738,27 +4059,34 @@ var ChatUI = ({
|
|
|
3738
4059
|
onScrollCapture: handleScroll,
|
|
3739
4060
|
children: /* @__PURE__ */ (0, import_jsx_runtime23.jsxs)("div", { className: "max-w-4xl mx-auto space-y-4 pb-4", children: [
|
|
3740
4061
|
renderSuggestions(),
|
|
3741
|
-
messages.map((message) =>
|
|
3742
|
-
|
|
3743
|
-
|
|
3744
|
-
|
|
3745
|
-
|
|
3746
|
-
|
|
3747
|
-
|
|
3748
|
-
|
|
3749
|
-
|
|
3750
|
-
|
|
3751
|
-
|
|
3752
|
-
|
|
3753
|
-
|
|
3754
|
-
|
|
3755
|
-
|
|
3756
|
-
|
|
3757
|
-
|
|
3758
|
-
|
|
3759
|
-
|
|
3760
|
-
|
|
3761
|
-
|
|
4062
|
+
messages.map((message, index) => {
|
|
4063
|
+
const prevMessage = index > 0 ? messages[index - 1] : null;
|
|
4064
|
+
const isGrouped = prevMessage !== null && prevMessage.role === message.role;
|
|
4065
|
+
return /* @__PURE__ */ (0, import_jsx_runtime23.jsxs)("div", { className: isGrouped ? "space-y-1 -mt-2" : "space-y-2", children: [
|
|
4066
|
+
/* @__PURE__ */ (0, import_jsx_runtime23.jsx)(
|
|
4067
|
+
Message,
|
|
4068
|
+
{
|
|
4069
|
+
message,
|
|
4070
|
+
userAvatar: user?.avatar,
|
|
4071
|
+
userName: user?.name,
|
|
4072
|
+
assistantAvatar: assistant?.avatar,
|
|
4073
|
+
assistantName: assistant?.name,
|
|
4074
|
+
showTimestamp: config.ui.showTimestamps,
|
|
4075
|
+
showAvatar: config.ui.showAvatars,
|
|
4076
|
+
enableCopy: config.features.enableMessageCopy,
|
|
4077
|
+
enableEdit: config.features.enableMessageEditing,
|
|
4078
|
+
enableRegenerate: config.features.enableRegeneration,
|
|
4079
|
+
enableToolCallsDisplay: config.features.enableToolCallsDisplay,
|
|
4080
|
+
compactMode: config.ui.compactMode,
|
|
4081
|
+
onAction: handleMessageAction,
|
|
4082
|
+
toolUsedLabel: config.labels.toolUsed,
|
|
4083
|
+
thinkingLabel: config.labels.thinking,
|
|
4084
|
+
isGrouped
|
|
4085
|
+
}
|
|
4086
|
+
),
|
|
4087
|
+
message.role === "assistant" && renderInlineSuggestions(message.id)
|
|
4088
|
+
] }, message.id);
|
|
4089
|
+
}),
|
|
3762
4090
|
/* @__PURE__ */ (0, import_jsx_runtime23.jsx)("div", { ref: messagesEndRef })
|
|
3763
4091
|
] })
|
|
3764
4092
|
}
|
|
@@ -3766,11 +4094,17 @@ var ChatUI = ({
|
|
|
3766
4094
|
/* @__PURE__ */ (0, import_jsx_runtime23.jsx)("div", { className: "bg-background pb-[env(safe-area-inset-bottom)]", children: /* @__PURE__ */ (0, import_jsx_runtime23.jsx)(
|
|
3767
4095
|
ChatInput,
|
|
3768
4096
|
{
|
|
3769
|
-
value:
|
|
3770
|
-
onChange: (value) =>
|
|
4097
|
+
value: inputValue,
|
|
4098
|
+
onChange: (value) => {
|
|
4099
|
+
setInputValue(value);
|
|
4100
|
+
if (initialInputApplied.current && !initialInputConsumedRef.current) {
|
|
4101
|
+
initialInputConsumedRef.current = true;
|
|
4102
|
+
onInitialInputConsumed?.();
|
|
4103
|
+
}
|
|
4104
|
+
},
|
|
3771
4105
|
onSubmit: handleSendMessage,
|
|
3772
|
-
attachments
|
|
3773
|
-
onAttachmentsChange:
|
|
4106
|
+
attachments,
|
|
4107
|
+
onAttachmentsChange: setAttachments,
|
|
3774
4108
|
placeholder: config.labels.inputPlaceholder,
|
|
3775
4109
|
disabled: false,
|
|
3776
4110
|
isGenerating,
|
|
@@ -3810,7 +4144,7 @@ var ChatUI = ({
|
|
|
3810
4144
|
}
|
|
3811
4145
|
)
|
|
3812
4146
|
] }),
|
|
3813
|
-
/* @__PURE__ */ (0, import_jsx_runtime23.jsx)(
|
|
4147
|
+
isUserProfileOpen && /* @__PURE__ */ (0, import_jsx_runtime23.jsx)(
|
|
3814
4148
|
UserProfile,
|
|
3815
4149
|
{
|
|
3816
4150
|
isOpen: isUserProfileOpen,
|
|
@@ -4074,7 +4408,7 @@ var ThreadManager = ({
|
|
|
4074
4408
|
] }, group)) }) })
|
|
4075
4409
|
] })
|
|
4076
4410
|
] }) }),
|
|
4077
|
-
/* @__PURE__ */ (0, import_jsx_runtime24.jsx)(AlertDialog, { open: !!deleteThreadId, onOpenChange: () => setDeleteThreadId(null), children: /* @__PURE__ */ (0, import_jsx_runtime24.jsxs)(AlertDialogContent, { children: [
|
|
4411
|
+
deleteThreadId && /* @__PURE__ */ (0, import_jsx_runtime24.jsx)(AlertDialog, { open: !!deleteThreadId, onOpenChange: () => setDeleteThreadId(null), children: /* @__PURE__ */ (0, import_jsx_runtime24.jsxs)(AlertDialogContent, { children: [
|
|
4078
4412
|
/* @__PURE__ */ (0, import_jsx_runtime24.jsxs)(AlertDialogHeader, { children: [
|
|
4079
4413
|
/* @__PURE__ */ (0, import_jsx_runtime24.jsx)(AlertDialogTitle, { children: config?.labels?.deleteConfirmTitle || "Delete Conversation" }),
|
|
4080
4414
|
/* @__PURE__ */ (0, import_jsx_runtime24.jsx)(AlertDialogDescription, { children: config?.labels?.deleteConfirmDescription || "Are you sure you want to delete this conversation? This action cannot be undone." })
|