@copilotz/chat-ui 0.1.0 → 0.1.1
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 +369 -110
- 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 +413 -151
- package/dist/index.js.map +1 -1
- package/dist/styles.css +237 -18
- package/package.json +6 -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
|
};
|
|
@@ -566,7 +575,7 @@ function TooltipContent({
|
|
|
566
575
|
// src/components/chat/Message.tsx
|
|
567
576
|
var import_lucide_react = require("lucide-react");
|
|
568
577
|
var import_jsx_runtime7 = require("react/jsx-runtime");
|
|
569
|
-
var ThinkingIndicator = ({ label = "Thinking..." })
|
|
578
|
+
var ThinkingIndicator = (0, import_react.memo)(function ThinkingIndicator2({ label = "Thinking..." }) {
|
|
570
579
|
return /* @__PURE__ */ (0, import_jsx_runtime7.jsxs)("div", { className: "flex items-center gap-2 py-2", children: [
|
|
571
580
|
/* @__PURE__ */ (0, import_jsx_runtime7.jsxs)("div", { className: "flex gap-1", children: [
|
|
572
581
|
/* @__PURE__ */ (0, import_jsx_runtime7.jsx)(
|
|
@@ -593,26 +602,30 @@ var ThinkingIndicator = ({ label = "Thinking..." }) => {
|
|
|
593
602
|
] }),
|
|
594
603
|
/* @__PURE__ */ (0, import_jsx_runtime7.jsx)("span", { className: "text-sm text-muted-foreground animate-pulse", children: label })
|
|
595
604
|
] });
|
|
605
|
+
});
|
|
606
|
+
var markdownComponents = {
|
|
607
|
+
code: ({ node, className, children, ...props }) => {
|
|
608
|
+
const inline = props.inline;
|
|
609
|
+
const match = /language-(\w+)/.exec(className || "");
|
|
610
|
+
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 });
|
|
611
|
+
}
|
|
596
612
|
};
|
|
597
|
-
var
|
|
613
|
+
var remarkPluginsDefault = [import_remark_gfm.default];
|
|
614
|
+
var rehypePluginsDefault = [import_rehype_highlight.default];
|
|
615
|
+
var rehypePluginsEmpty = [];
|
|
616
|
+
var StreamingText = (0, import_react.memo)(function StreamingText2({
|
|
598
617
|
content,
|
|
599
618
|
isStreaming = false,
|
|
600
619
|
thinkingLabel = "Thinking..."
|
|
601
|
-
})
|
|
620
|
+
}) {
|
|
602
621
|
const hasContent = content.trim().length > 0;
|
|
603
622
|
return /* @__PURE__ */ (0, import_jsx_runtime7.jsxs)("div", { className: "prose prose-sm max-w-none dark:prose-invert", children: [
|
|
604
623
|
hasContent ? /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(
|
|
605
624
|
import_react_markdown.default,
|
|
606
625
|
{
|
|
607
|
-
remarkPlugins:
|
|
608
|
-
rehypePlugins: isStreaming ?
|
|
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
|
-
},
|
|
626
|
+
remarkPlugins: remarkPluginsDefault,
|
|
627
|
+
rehypePlugins: isStreaming ? rehypePluginsEmpty : rehypePluginsDefault,
|
|
628
|
+
components: markdownComponents,
|
|
616
629
|
children: content
|
|
617
630
|
}
|
|
618
631
|
) : isStreaming ? (
|
|
@@ -621,8 +634,8 @@ var StreamingText = ({
|
|
|
621
634
|
) : null,
|
|
622
635
|
isStreaming && hasContent && /* @__PURE__ */ (0, import_jsx_runtime7.jsx)("span", { className: "inline-block w-2 h-4 bg-primary animate-pulse ml-1" })
|
|
623
636
|
] });
|
|
624
|
-
};
|
|
625
|
-
var MediaRenderer = ({ attachment })
|
|
637
|
+
});
|
|
638
|
+
var MediaRenderer = (0, import_react.memo)(function MediaRenderer2({ attachment }) {
|
|
626
639
|
const [isPlaying, setIsPlaying] = (0, import_react.useState)(false);
|
|
627
640
|
const audioRef = (0, import_react.useRef)(null);
|
|
628
641
|
const videoRef = (0, import_react.useRef)(null);
|
|
@@ -696,8 +709,8 @@ var MediaRenderer = ({ attachment }) => {
|
|
|
696
709
|
default:
|
|
697
710
|
return null;
|
|
698
711
|
}
|
|
699
|
-
};
|
|
700
|
-
var ToolCallsDisplay = ({ toolCalls, label })
|
|
712
|
+
});
|
|
713
|
+
var ToolCallsDisplay = (0, import_react.memo)(function ToolCallsDisplay2({ toolCalls, label }) {
|
|
701
714
|
const [expandedCall, setExpandedCall] = (0, import_react.useState)(null);
|
|
702
715
|
const getStatusIcon = (status) => {
|
|
703
716
|
switch (status) {
|
|
@@ -766,8 +779,48 @@ var ToolCallsDisplay = ({ toolCalls, label }) => {
|
|
|
766
779
|
] }, call.id);
|
|
767
780
|
})
|
|
768
781
|
] });
|
|
782
|
+
});
|
|
783
|
+
var arePropsEqual = (prevProps, nextProps) => {
|
|
784
|
+
if (prevProps.message.id !== nextProps.message.id) return false;
|
|
785
|
+
if (prevProps.message.content !== nextProps.message.content) return false;
|
|
786
|
+
if (prevProps.message.isStreaming !== nextProps.message.isStreaming) return false;
|
|
787
|
+
if (prevProps.message.isComplete !== nextProps.message.isComplete) return false;
|
|
788
|
+
if (prevProps.message.isEdited !== nextProps.message.isEdited) return false;
|
|
789
|
+
if (prevProps.message.timestamp !== nextProps.message.timestamp) return false;
|
|
790
|
+
if (prevProps.message.toolCalls !== nextProps.message.toolCalls) {
|
|
791
|
+
const prevCalls = prevProps.message.toolCalls;
|
|
792
|
+
const nextCalls = nextProps.message.toolCalls;
|
|
793
|
+
if (!prevCalls || !nextCalls || prevCalls.length !== nextCalls.length) return false;
|
|
794
|
+
for (let i = 0; i < prevCalls.length; i++) {
|
|
795
|
+
if (prevCalls[i].id !== nextCalls[i].id || prevCalls[i].status !== nextCalls[i].status || prevCalls[i].result !== nextCalls[i].result) {
|
|
796
|
+
return false;
|
|
797
|
+
}
|
|
798
|
+
}
|
|
799
|
+
}
|
|
800
|
+
if (prevProps.message.attachments !== nextProps.message.attachments) {
|
|
801
|
+
const prevAtt = prevProps.message.attachments;
|
|
802
|
+
const nextAtt = nextProps.message.attachments;
|
|
803
|
+
if (!prevAtt || !nextAtt || prevAtt.length !== nextAtt.length) return false;
|
|
804
|
+
}
|
|
805
|
+
if (prevProps.isUser !== nextProps.isUser) return false;
|
|
806
|
+
if (prevProps.userAvatar !== nextProps.userAvatar) return false;
|
|
807
|
+
if (prevProps.userName !== nextProps.userName) return false;
|
|
808
|
+
if (prevProps.assistantName !== nextProps.assistantName) return false;
|
|
809
|
+
if (prevProps.showTimestamp !== nextProps.showTimestamp) return false;
|
|
810
|
+
if (prevProps.showAvatar !== nextProps.showAvatar) return false;
|
|
811
|
+
if (prevProps.enableCopy !== nextProps.enableCopy) return false;
|
|
812
|
+
if (prevProps.enableEdit !== nextProps.enableEdit) return false;
|
|
813
|
+
if (prevProps.enableRegenerate !== nextProps.enableRegenerate) return false;
|
|
814
|
+
if (prevProps.enableToolCallsDisplay !== nextProps.enableToolCallsDisplay) return false;
|
|
815
|
+
if (prevProps.compactMode !== nextProps.compactMode) return false;
|
|
816
|
+
if (prevProps.className !== nextProps.className) return false;
|
|
817
|
+
if (prevProps.toolUsedLabel !== nextProps.toolUsedLabel) return false;
|
|
818
|
+
if (prevProps.thinkingLabel !== nextProps.thinkingLabel) return false;
|
|
819
|
+
if (prevProps.isGrouped !== nextProps.isGrouped) return false;
|
|
820
|
+
if (prevProps.assistantAvatar !== nextProps.assistantAvatar) return false;
|
|
821
|
+
return true;
|
|
769
822
|
};
|
|
770
|
-
var Message = ({
|
|
823
|
+
var Message = (0, import_react.memo)(({
|
|
771
824
|
message,
|
|
772
825
|
isUser,
|
|
773
826
|
userAvatar,
|
|
@@ -784,7 +837,8 @@ var Message = ({
|
|
|
784
837
|
onAction,
|
|
785
838
|
className = "",
|
|
786
839
|
toolUsedLabel,
|
|
787
|
-
thinkingLabel = "Thinking..."
|
|
840
|
+
thinkingLabel = "Thinking...",
|
|
841
|
+
isGrouped = false
|
|
788
842
|
}) => {
|
|
789
843
|
const [isEditing, setIsEditing] = (0, import_react.useState)(false);
|
|
790
844
|
const [editContent, setEditContent] = (0, import_react.useState)(message.content);
|
|
@@ -834,7 +888,7 @@ var Message = ({
|
|
|
834
888
|
onMouseEnter: () => setShowActions(true),
|
|
835
889
|
onMouseLeave: () => setShowActions(false),
|
|
836
890
|
children: [
|
|
837
|
-
/* @__PURE__ */ (0, import_jsx_runtime7.jsxs)("div", { className: `flex gap-3 ${messageIsUser ? "flex-row-reverse" : "flex-row"} w-full mb-1`, children: [
|
|
891
|
+
!isGrouped && /* @__PURE__ */ (0, import_jsx_runtime7.jsxs)("div", { className: `flex gap-3 ${messageIsUser ? "flex-row-reverse" : "flex-row"} w-full mb-1`, children: [
|
|
838
892
|
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
893
|
/* @__PURE__ */ (0, import_jsx_runtime7.jsx)(AvatarImage, { src: userAvatar, alt: userName }),
|
|
840
894
|
/* @__PURE__ */ (0, import_jsx_runtime7.jsx)(AvatarFallback, { className: "bg-primary text-primary-foreground", children: userName.charAt(0).toUpperCase() })
|
|
@@ -845,7 +899,7 @@ var Message = ({
|
|
|
845
899
|
message.isEdited && /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(Badge, { variant: "outline", className: "text-xs", children: "editado" })
|
|
846
900
|
] })
|
|
847
901
|
] }),
|
|
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: [
|
|
902
|
+
/* @__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
903
|
isEditing ? /* @__PURE__ */ (0, import_jsx_runtime7.jsxs)("div", { className: "space-y-2", children: [
|
|
850
904
|
/* @__PURE__ */ (0, import_jsx_runtime7.jsx)(
|
|
851
905
|
Textarea,
|
|
@@ -923,7 +977,7 @@ var Message = ({
|
|
|
923
977
|
]
|
|
924
978
|
}
|
|
925
979
|
) });
|
|
926
|
-
};
|
|
980
|
+
}, arePropsEqual);
|
|
927
981
|
|
|
928
982
|
// src/components/chat/Sidebar.tsx
|
|
929
983
|
var import_react2 = require("react");
|
|
@@ -948,7 +1002,7 @@ function Input({ className, type, ...props }) {
|
|
|
948
1002
|
}
|
|
949
1003
|
|
|
950
1004
|
// src/components/ui/sidebar.tsx
|
|
951
|
-
var
|
|
1005
|
+
var React4 = __toESM(require("react"), 1);
|
|
952
1006
|
var import_react_slot3 = require("@radix-ui/react-slot");
|
|
953
1007
|
var import_class_variance_authority3 = require("class-variance-authority");
|
|
954
1008
|
var import_lucide_react3 = require("lucide-react");
|
|
@@ -995,11 +1049,30 @@ function Separator({
|
|
|
995
1049
|
}
|
|
996
1050
|
|
|
997
1051
|
// src/components/ui/sheet.tsx
|
|
1052
|
+
var React3 = __toESM(require("react"), 1);
|
|
998
1053
|
var SheetPrimitive = __toESM(require("@radix-ui/react-dialog"), 1);
|
|
999
1054
|
var import_lucide_react2 = require("lucide-react");
|
|
1000
1055
|
var import_jsx_runtime10 = require("react/jsx-runtime");
|
|
1001
|
-
function
|
|
1002
|
-
|
|
1056
|
+
function cleanupBodyStyles() {
|
|
1057
|
+
if (typeof document !== "undefined" && document.body.style.pointerEvents === "none") {
|
|
1058
|
+
document.body.style.pointerEvents = "";
|
|
1059
|
+
}
|
|
1060
|
+
}
|
|
1061
|
+
function Sheet({ open, onOpenChange, ...props }) {
|
|
1062
|
+
const prevOpenRef = React3.useRef(open);
|
|
1063
|
+
React3.useEffect(() => {
|
|
1064
|
+
if (prevOpenRef.current === true && open === false) {
|
|
1065
|
+
const timeout = setTimeout(cleanupBodyStyles, 350);
|
|
1066
|
+
return () => clearTimeout(timeout);
|
|
1067
|
+
}
|
|
1068
|
+
prevOpenRef.current = open;
|
|
1069
|
+
}, [open]);
|
|
1070
|
+
React3.useEffect(() => {
|
|
1071
|
+
return () => {
|
|
1072
|
+
cleanupBodyStyles();
|
|
1073
|
+
};
|
|
1074
|
+
}, []);
|
|
1075
|
+
return /* @__PURE__ */ (0, import_jsx_runtime10.jsx)(SheetPrimitive.Root, { "data-slot": "sheet", open, onOpenChange, ...props });
|
|
1003
1076
|
}
|
|
1004
1077
|
function SheetPortal({
|
|
1005
1078
|
...props
|
|
@@ -1015,7 +1088,10 @@ function SheetOverlay({
|
|
|
1015
1088
|
{
|
|
1016
1089
|
"data-slot": "sheet-overlay",
|
|
1017
1090
|
className: cn(
|
|
1018
|
-
"
|
|
1091
|
+
"fixed inset-0 z-50 bg-black/50",
|
|
1092
|
+
"data-[state=open]:animate-in data-[state=closed]:animate-out",
|
|
1093
|
+
"data-[state=closed]:fade-out-0 data-[state=open]:fade-in-0",
|
|
1094
|
+
"data-[state=closed]:pointer-events-none",
|
|
1019
1095
|
className
|
|
1020
1096
|
),
|
|
1021
1097
|
...props
|
|
@@ -1034,6 +1110,7 @@ function SheetContent({
|
|
|
1034
1110
|
SheetPrimitive.Content,
|
|
1035
1111
|
{
|
|
1036
1112
|
"data-slot": "sheet-content",
|
|
1113
|
+
"aria-describedby": void 0,
|
|
1037
1114
|
className: cn(
|
|
1038
1115
|
"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
1116
|
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 +1176,9 @@ var SIDEBAR_WIDTH = "16rem";
|
|
|
1099
1176
|
var SIDEBAR_WIDTH_MOBILE = "18rem";
|
|
1100
1177
|
var SIDEBAR_WIDTH_ICON = "3rem";
|
|
1101
1178
|
var SIDEBAR_KEYBOARD_SHORTCUT = "b";
|
|
1102
|
-
var SidebarContext =
|
|
1179
|
+
var SidebarContext = React4.createContext(null);
|
|
1103
1180
|
function useSidebar() {
|
|
1104
|
-
const context =
|
|
1181
|
+
const context = React4.useContext(SidebarContext);
|
|
1105
1182
|
if (!context) {
|
|
1106
1183
|
throw new Error("useSidebar must be used within a SidebarProvider.");
|
|
1107
1184
|
}
|
|
@@ -1117,10 +1194,10 @@ function SidebarProvider({
|
|
|
1117
1194
|
...props
|
|
1118
1195
|
}) {
|
|
1119
1196
|
const isMobile = useIsMobile();
|
|
1120
|
-
const [openMobile, setOpenMobile] =
|
|
1121
|
-
const [_open, _setOpen] =
|
|
1197
|
+
const [openMobile, setOpenMobile] = React4.useState(false);
|
|
1198
|
+
const [_open, _setOpen] = React4.useState(defaultOpen);
|
|
1122
1199
|
const open = openProp ?? _open;
|
|
1123
|
-
const setOpen =
|
|
1200
|
+
const setOpen = React4.useCallback(
|
|
1124
1201
|
(value) => {
|
|
1125
1202
|
const openState = typeof value === "function" ? value(open) : value;
|
|
1126
1203
|
if (setOpenProp) {
|
|
@@ -1132,10 +1209,10 @@ function SidebarProvider({
|
|
|
1132
1209
|
},
|
|
1133
1210
|
[setOpenProp, open]
|
|
1134
1211
|
);
|
|
1135
|
-
const toggleSidebar =
|
|
1212
|
+
const toggleSidebar = React4.useCallback(() => {
|
|
1136
1213
|
return isMobile ? setOpenMobile((open2) => !open2) : setOpen((open2) => !open2);
|
|
1137
1214
|
}, [isMobile, setOpen, setOpenMobile]);
|
|
1138
|
-
|
|
1215
|
+
React4.useEffect(() => {
|
|
1139
1216
|
const handleKeyDown = (event) => {
|
|
1140
1217
|
if (event.key === SIDEBAR_KEYBOARD_SHORTCUT && (event.metaKey || event.ctrlKey)) {
|
|
1141
1218
|
event.preventDefault();
|
|
@@ -1146,7 +1223,7 @@ function SidebarProvider({
|
|
|
1146
1223
|
return () => window.removeEventListener("keydown", handleKeyDown);
|
|
1147
1224
|
}, [toggleSidebar]);
|
|
1148
1225
|
const state = open ? "expanded" : "collapsed";
|
|
1149
|
-
const contextValue =
|
|
1226
|
+
const contextValue = React4.useMemo(
|
|
1150
1227
|
() => ({
|
|
1151
1228
|
state,
|
|
1152
1229
|
open,
|
|
@@ -1529,13 +1606,34 @@ function SidebarMenuAction({
|
|
|
1529
1606
|
}
|
|
1530
1607
|
|
|
1531
1608
|
// src/components/ui/dialog.tsx
|
|
1609
|
+
var React5 = __toESM(require("react"), 1);
|
|
1532
1610
|
var DialogPrimitive = __toESM(require("@radix-ui/react-dialog"), 1);
|
|
1533
1611
|
var import_lucide_react4 = require("lucide-react");
|
|
1534
1612
|
var import_jsx_runtime12 = require("react/jsx-runtime");
|
|
1613
|
+
function cleanupBodyStyles2() {
|
|
1614
|
+
if (typeof document !== "undefined" && document.body.style.pointerEvents === "none") {
|
|
1615
|
+
document.body.style.pointerEvents = "";
|
|
1616
|
+
}
|
|
1617
|
+
}
|
|
1535
1618
|
function Dialog({
|
|
1619
|
+
open,
|
|
1620
|
+
onOpenChange,
|
|
1536
1621
|
...props
|
|
1537
1622
|
}) {
|
|
1538
|
-
|
|
1623
|
+
const prevOpenRef = React5.useRef(open);
|
|
1624
|
+
React5.useEffect(() => {
|
|
1625
|
+
if (prevOpenRef.current === true && open === false) {
|
|
1626
|
+
const timeout = setTimeout(cleanupBodyStyles2, 250);
|
|
1627
|
+
return () => clearTimeout(timeout);
|
|
1628
|
+
}
|
|
1629
|
+
prevOpenRef.current = open;
|
|
1630
|
+
}, [open]);
|
|
1631
|
+
React5.useEffect(() => {
|
|
1632
|
+
return () => {
|
|
1633
|
+
cleanupBodyStyles2();
|
|
1634
|
+
};
|
|
1635
|
+
}, []);
|
|
1636
|
+
return /* @__PURE__ */ (0, import_jsx_runtime12.jsx)(DialogPrimitive.Root, { "data-slot": "dialog", open, onOpenChange, ...props });
|
|
1539
1637
|
}
|
|
1540
1638
|
function DialogTrigger({
|
|
1541
1639
|
...props
|
|
@@ -1556,7 +1654,10 @@ function DialogOverlay({
|
|
|
1556
1654
|
{
|
|
1557
1655
|
"data-slot": "dialog-overlay",
|
|
1558
1656
|
className: cn(
|
|
1559
|
-
"
|
|
1657
|
+
"fixed inset-0 z-50 bg-black/50",
|
|
1658
|
+
"data-[state=open]:animate-in data-[state=closed]:animate-out",
|
|
1659
|
+
"data-[state=closed]:fade-out-0 data-[state=open]:fade-in-0",
|
|
1660
|
+
"data-[state=closed]:pointer-events-none",
|
|
1560
1661
|
className
|
|
1561
1662
|
),
|
|
1562
1663
|
...props
|
|
@@ -1575,6 +1676,7 @@ function DialogContent({
|
|
|
1575
1676
|
DialogPrimitive.Content,
|
|
1576
1677
|
{
|
|
1577
1678
|
"data-slot": "dialog-content",
|
|
1679
|
+
"aria-describedby": void 0,
|
|
1578
1680
|
className: cn(
|
|
1579
1681
|
"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
1682
|
className
|
|
@@ -1649,12 +1751,33 @@ function DialogDescription({
|
|
|
1649
1751
|
}
|
|
1650
1752
|
|
|
1651
1753
|
// src/components/ui/alert-dialog.tsx
|
|
1754
|
+
var React6 = __toESM(require("react"), 1);
|
|
1652
1755
|
var AlertDialogPrimitive = __toESM(require("@radix-ui/react-alert-dialog"), 1);
|
|
1653
1756
|
var import_jsx_runtime13 = require("react/jsx-runtime");
|
|
1757
|
+
function cleanupBodyStyles3() {
|
|
1758
|
+
if (typeof document !== "undefined" && document.body.style.pointerEvents === "none") {
|
|
1759
|
+
document.body.style.pointerEvents = "";
|
|
1760
|
+
}
|
|
1761
|
+
}
|
|
1654
1762
|
function AlertDialog({
|
|
1763
|
+
open,
|
|
1764
|
+
onOpenChange,
|
|
1655
1765
|
...props
|
|
1656
1766
|
}) {
|
|
1657
|
-
|
|
1767
|
+
const prevOpenRef = React6.useRef(open);
|
|
1768
|
+
React6.useEffect(() => {
|
|
1769
|
+
if (prevOpenRef.current === true && open === false) {
|
|
1770
|
+
const timeout = setTimeout(cleanupBodyStyles3, 250);
|
|
1771
|
+
return () => clearTimeout(timeout);
|
|
1772
|
+
}
|
|
1773
|
+
prevOpenRef.current = open;
|
|
1774
|
+
}, [open]);
|
|
1775
|
+
React6.useEffect(() => {
|
|
1776
|
+
return () => {
|
|
1777
|
+
cleanupBodyStyles3();
|
|
1778
|
+
};
|
|
1779
|
+
}, []);
|
|
1780
|
+
return /* @__PURE__ */ (0, import_jsx_runtime13.jsx)(AlertDialogPrimitive.Root, { "data-slot": "alert-dialog", open, onOpenChange, ...props });
|
|
1658
1781
|
}
|
|
1659
1782
|
function AlertDialogPortal({
|
|
1660
1783
|
...props
|
|
@@ -1670,7 +1793,10 @@ function AlertDialogOverlay({
|
|
|
1670
1793
|
{
|
|
1671
1794
|
"data-slot": "alert-dialog-overlay",
|
|
1672
1795
|
className: cn(
|
|
1673
|
-
"
|
|
1796
|
+
"fixed inset-0 z-50 bg-black/50",
|
|
1797
|
+
"data-[state=open]:animate-in data-[state=closed]:animate-out",
|
|
1798
|
+
"data-[state=closed]:fade-out-0 data-[state=open]:fade-in-0",
|
|
1799
|
+
"data-[state=closed]:pointer-events-none",
|
|
1674
1800
|
className
|
|
1675
1801
|
),
|
|
1676
1802
|
...props
|
|
@@ -2128,6 +2254,13 @@ var Sidebar2 = ({
|
|
|
2128
2254
|
};
|
|
2129
2255
|
return /* @__PURE__ */ (0, import_jsx_runtime16.jsxs)(Sidebar, { collapsible: "icon", ...props, children: [
|
|
2130
2256
|
/* @__PURE__ */ (0, import_jsx_runtime16.jsxs)(SidebarHeader, { children: [
|
|
2257
|
+
/* @__PURE__ */ (0, import_jsx_runtime16.jsxs)("div", { className: "flex items-center gap-3 px-2 py-3", children: [
|
|
2258
|
+
/* @__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" }) }) }) }),
|
|
2259
|
+
/* @__PURE__ */ (0, import_jsx_runtime16.jsxs)("div", { className: "flex flex-col min-w-0 group-data-[collapsible=icon]:hidden", children: [
|
|
2260
|
+
/* @__PURE__ */ (0, import_jsx_runtime16.jsx)("span", { className: "text-sm font-semibold truncate", children: config.branding?.title || "Chat" }),
|
|
2261
|
+
config.branding?.subtitle && /* @__PURE__ */ (0, import_jsx_runtime16.jsx)("span", { className: "text-xs text-muted-foreground truncate", children: config.branding.subtitle })
|
|
2262
|
+
] })
|
|
2263
|
+
] }),
|
|
2131
2264
|
onCreateThread && /* @__PURE__ */ (0, import_jsx_runtime16.jsx)(
|
|
2132
2265
|
CreateThreadDialog,
|
|
2133
2266
|
{
|
|
@@ -2147,7 +2280,7 @@ var Sidebar2 = ({
|
|
|
2147
2280
|
) }) })
|
|
2148
2281
|
}
|
|
2149
2282
|
),
|
|
2150
|
-
/* @__PURE__ */ (0, import_jsx_runtime16.jsxs)("div", { className: "px-2 py-1 mt-
|
|
2283
|
+
/* @__PURE__ */ (0, import_jsx_runtime16.jsxs)("div", { className: "px-2 py-1 mt-4", children: [
|
|
2151
2284
|
/* @__PURE__ */ (0, import_jsx_runtime16.jsxs)("div", { className: "relative group-data-[collapsible=icon]:hidden", children: [
|
|
2152
2285
|
/* @__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
2286
|
/* @__PURE__ */ (0, import_jsx_runtime16.jsx)(
|
|
@@ -2262,7 +2395,7 @@ var Sidebar2 = ({
|
|
|
2262
2395
|
}
|
|
2263
2396
|
) }),
|
|
2264
2397
|
/* @__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: [
|
|
2398
|
+
deleteThreadId && /* @__PURE__ */ (0, import_jsx_runtime16.jsx)(AlertDialog, { open: !!deleteThreadId, onOpenChange: () => setDeleteThreadId(null), children: /* @__PURE__ */ (0, import_jsx_runtime16.jsxs)(AlertDialogContent, { children: [
|
|
2266
2399
|
/* @__PURE__ */ (0, import_jsx_runtime16.jsxs)(AlertDialogHeader, { children: [
|
|
2267
2400
|
/* @__PURE__ */ (0, import_jsx_runtime16.jsx)(AlertDialogTitle, { children: config.labels?.deleteConfirmTitle || "Delete Conversation" }),
|
|
2268
2401
|
/* @__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 +2430,10 @@ var ChatHeader = ({
|
|
|
2297
2430
|
onClearAll,
|
|
2298
2431
|
showCustomComponentButton,
|
|
2299
2432
|
isMobile,
|
|
2433
|
+
showAgentSelector = false,
|
|
2434
|
+
agentOptions = [],
|
|
2435
|
+
selectedAgentId = null,
|
|
2436
|
+
onSelectAgent,
|
|
2300
2437
|
className = ""
|
|
2301
2438
|
}) => {
|
|
2302
2439
|
const [isDarkMode, setIsDarkMode] = import_react3.default.useState(() => {
|
|
@@ -2347,22 +2484,64 @@ var ChatHeader = ({
|
|
|
2347
2484
|
};
|
|
2348
2485
|
input.click();
|
|
2349
2486
|
};
|
|
2487
|
+
const selectedAgent = agentOptions.find((agent) => agent.id === selectedAgentId) || null;
|
|
2488
|
+
const agentPlaceholder = config.agentSelector?.label || "Select agent";
|
|
2350
2489
|
return /* @__PURE__ */ (0, import_jsx_runtime17.jsx)(
|
|
2351
2490
|
Card,
|
|
2352
2491
|
{
|
|
2353
2492
|
"data-chat-header": true,
|
|
2354
2493
|
className: `py-0 border-b rounded-none relative z-10 bg-background/95 backdrop-blur supports-[backdrop-filter]:bg-background/80 ${className}`,
|
|
2355
2494
|
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
|
-
|
|
2495
|
+
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: [
|
|
2496
|
+
/* @__PURE__ */ (0, import_jsx_runtime17.jsxs)("div", { className: "flex items-center gap-1", children: [
|
|
2497
|
+
/* @__PURE__ */ (0, import_jsx_runtime17.jsxs)(Tooltip, { children: [
|
|
2498
|
+
/* @__PURE__ */ (0, import_jsx_runtime17.jsx)(TooltipTrigger, { asChild: true, children: /* @__PURE__ */ (0, import_jsx_runtime17.jsx)(SidebarTrigger, { className: "-ml-1" }) }),
|
|
2499
|
+
/* @__PURE__ */ (0, import_jsx_runtime17.jsx)(TooltipContent, { children: config.labels?.sidebarToggle || "Toggle Sidebar" })
|
|
2500
|
+
] }),
|
|
2501
|
+
showAgentSelector && /* @__PURE__ */ (0, import_jsx_runtime17.jsxs)(DropdownMenu, { children: [
|
|
2502
|
+
/* @__PURE__ */ (0, import_jsx_runtime17.jsx)(DropdownMenuTrigger, { asChild: true, children: /* @__PURE__ */ (0, import_jsx_runtime17.jsxs)(
|
|
2503
|
+
Button,
|
|
2504
|
+
{
|
|
2505
|
+
variant: "ghost",
|
|
2506
|
+
className: "h-9 px-3 gap-1.5 font-medium text-base hover:bg-accent/50",
|
|
2507
|
+
children: [
|
|
2508
|
+
selectedAgent?.avatarUrl ? /* @__PURE__ */ (0, import_jsx_runtime17.jsxs)(Avatar, { className: "h-5 w-5", children: [
|
|
2509
|
+
/* @__PURE__ */ (0, import_jsx_runtime17.jsx)(AvatarImage, { src: selectedAgent.avatarUrl, alt: selectedAgent.name }),
|
|
2510
|
+
/* @__PURE__ */ (0, import_jsx_runtime17.jsx)(AvatarFallback, { className: "text-[10px]", children: selectedAgent.name.charAt(0).toUpperCase() })
|
|
2511
|
+
] }) : null,
|
|
2512
|
+
/* @__PURE__ */ (0, import_jsx_runtime17.jsx)("span", { className: "max-w-[200px] truncate", children: selectedAgent?.name || agentPlaceholder }),
|
|
2513
|
+
/* @__PURE__ */ (0, import_jsx_runtime17.jsx)(import_lucide_react8.ChevronDown, { className: "h-4 w-4 opacity-50" })
|
|
2514
|
+
]
|
|
2515
|
+
}
|
|
2516
|
+
) }),
|
|
2517
|
+
/* @__PURE__ */ (0, import_jsx_runtime17.jsx)(DropdownMenuContent, { align: "start", className: "w-[280px]", children: agentOptions.map((agent) => {
|
|
2518
|
+
const isSelected = agent.id === selectedAgentId;
|
|
2519
|
+
return /* @__PURE__ */ (0, import_jsx_runtime17.jsxs)(
|
|
2520
|
+
DropdownMenuItem,
|
|
2521
|
+
{
|
|
2522
|
+
onClick: () => onSelectAgent?.(agent.id),
|
|
2523
|
+
className: "flex items-start gap-3 p-3 cursor-pointer",
|
|
2524
|
+
children: [
|
|
2525
|
+
agent.avatarUrl ? /* @__PURE__ */ (0, import_jsx_runtime17.jsxs)(Avatar, { className: "h-6 w-6 mt-0.5 shrink-0", children: [
|
|
2526
|
+
/* @__PURE__ */ (0, import_jsx_runtime17.jsx)(AvatarImage, { src: agent.avatarUrl, alt: agent.name }),
|
|
2527
|
+
/* @__PURE__ */ (0, import_jsx_runtime17.jsx)(AvatarFallback, { className: "text-[10px]", children: agent.name.charAt(0).toUpperCase() })
|
|
2528
|
+
] }) : /* @__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" }) }),
|
|
2529
|
+
/* @__PURE__ */ (0, import_jsx_runtime17.jsxs)("div", { className: "flex-1 min-w-0", children: [
|
|
2530
|
+
/* @__PURE__ */ (0, import_jsx_runtime17.jsxs)("div", { className: "flex items-center gap-2", children: [
|
|
2531
|
+
/* @__PURE__ */ (0, import_jsx_runtime17.jsx)("span", { className: "font-medium text-sm", children: agent.name }),
|
|
2532
|
+
isSelected && /* @__PURE__ */ (0, import_jsx_runtime17.jsx)(import_lucide_react8.Check, { className: "h-4 w-4 text-primary shrink-0" })
|
|
2533
|
+
] }),
|
|
2534
|
+
agent.description && /* @__PURE__ */ (0, import_jsx_runtime17.jsx)("p", { className: "text-xs text-muted-foreground mt-0.5 line-clamp-2", children: agent.description })
|
|
2535
|
+
] })
|
|
2536
|
+
]
|
|
2537
|
+
},
|
|
2538
|
+
agent.id
|
|
2539
|
+
);
|
|
2540
|
+
}) })
|
|
2541
|
+
] }),
|
|
2542
|
+
!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
2543
|
] }),
|
|
2544
|
+
/* @__PURE__ */ (0, import_jsx_runtime17.jsx)("div", { className: "flex-1" }),
|
|
2366
2545
|
/* @__PURE__ */ (0, import_jsx_runtime17.jsxs)("div", { className: "flex items-center gap-1", children: [
|
|
2367
2546
|
showCustomComponentButton && config.customComponent && /* @__PURE__ */ (0, import_jsx_runtime17.jsxs)(Tooltip, { children: [
|
|
2368
2547
|
/* @__PURE__ */ (0, import_jsx_runtime17.jsx)(TooltipTrigger, { asChild: true, children: /* @__PURE__ */ (0, import_jsx_runtime17.jsx)(
|
|
@@ -2497,7 +2676,7 @@ function Progress({
|
|
|
2497
2676
|
// src/components/chat/ChatInput.tsx
|
|
2498
2677
|
var import_lucide_react9 = require("lucide-react");
|
|
2499
2678
|
var import_jsx_runtime20 = require("react/jsx-runtime");
|
|
2500
|
-
var FileUploadItem = ({ file, progress, onCancel })
|
|
2679
|
+
var FileUploadItem = (0, import_react5.memo)(function FileUploadItem2({ file, progress, onCancel }) {
|
|
2501
2680
|
const guessTypeFromName = (name) => {
|
|
2502
2681
|
const ext = (name || "").split(".").pop()?.toLowerCase();
|
|
2503
2682
|
switch (ext) {
|
|
@@ -2555,8 +2734,8 @@ var FileUploadItem = ({ file, progress, onCancel }) => {
|
|
|
2555
2734
|
}
|
|
2556
2735
|
)
|
|
2557
2736
|
] }) }) });
|
|
2558
|
-
};
|
|
2559
|
-
var AttachmentPreview = ({ attachment, onRemove })
|
|
2737
|
+
});
|
|
2738
|
+
var AttachmentPreview = (0, import_react5.memo)(function AttachmentPreview2({ attachment, onRemove }) {
|
|
2560
2739
|
const [isPlaying, setIsPlaying] = (0, import_react5.useState)(false);
|
|
2561
2740
|
const audioRef = (0, import_react5.useRef)(null);
|
|
2562
2741
|
const handlePlayPause = () => {
|
|
@@ -2656,8 +2835,8 @@ var AttachmentPreview = ({ attachment, onRemove }) => {
|
|
|
2656
2835
|
] }),
|
|
2657
2836
|
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
2837
|
] }) });
|
|
2659
|
-
};
|
|
2660
|
-
var AudioRecorder = ({ isRecording, onStartRecording, onStopRecording, onCancel, recordingDuration, config })
|
|
2838
|
+
});
|
|
2839
|
+
var AudioRecorder = (0, import_react5.memo)(function AudioRecorder2({ isRecording, onStartRecording, onStopRecording, onCancel, recordingDuration, config }) {
|
|
2661
2840
|
const formatTime = (seconds) => {
|
|
2662
2841
|
const mins = Math.floor(seconds / 60);
|
|
2663
2842
|
const secs = seconds % 60;
|
|
@@ -2711,8 +2890,8 @@ var AudioRecorder = ({ isRecording, onStartRecording, onStopRecording, onCancel,
|
|
|
2711
2890
|
)
|
|
2712
2891
|
] })
|
|
2713
2892
|
] }) }) });
|
|
2714
|
-
};
|
|
2715
|
-
var ChatInput = ({
|
|
2893
|
+
});
|
|
2894
|
+
var ChatInput = (0, import_react5.memo)(function ChatInput2({
|
|
2716
2895
|
value,
|
|
2717
2896
|
onChange,
|
|
2718
2897
|
onSubmit,
|
|
@@ -2730,7 +2909,7 @@ var ChatInput = ({
|
|
|
2730
2909
|
acceptedFileTypes = ["image/*", "video/*", "audio/*"],
|
|
2731
2910
|
className = "",
|
|
2732
2911
|
config
|
|
2733
|
-
})
|
|
2912
|
+
}) {
|
|
2734
2913
|
const [isRecording, setIsRecording] = (0, import_react5.useState)(false);
|
|
2735
2914
|
const { setContext } = useChatUserContext();
|
|
2736
2915
|
const [recordingDuration, setRecordingDuration] = (0, import_react5.useState)(0);
|
|
@@ -3072,16 +3251,16 @@ var ChatInput = ({
|
|
|
3072
3251
|
] })
|
|
3073
3252
|
] })
|
|
3074
3253
|
] }) }) });
|
|
3075
|
-
};
|
|
3254
|
+
});
|
|
3076
3255
|
|
|
3077
3256
|
// src/components/chat/UserProfile.tsx
|
|
3078
3257
|
var import_react6 = require("react");
|
|
3079
3258
|
|
|
3080
3259
|
// src/components/ui/scroll-area.tsx
|
|
3081
|
-
var
|
|
3260
|
+
var React11 = __toESM(require("react"), 1);
|
|
3082
3261
|
var ScrollAreaPrimitive = __toESM(require("@radix-ui/react-scroll-area"), 1);
|
|
3083
3262
|
var import_jsx_runtime21 = require("react/jsx-runtime");
|
|
3084
|
-
var ScrollArea =
|
|
3263
|
+
var ScrollArea = React11.forwardRef(({ className, children, viewportClassName, onScroll, onScrollCapture, ...props }, ref) => {
|
|
3085
3264
|
return /* @__PURE__ */ (0, import_jsx_runtime21.jsxs)(
|
|
3086
3265
|
ScrollAreaPrimitive.Root,
|
|
3087
3266
|
{
|
|
@@ -3527,10 +3706,16 @@ var ChatUI = ({
|
|
|
3527
3706
|
user,
|
|
3528
3707
|
assistant,
|
|
3529
3708
|
suggestions = [],
|
|
3709
|
+
messageSuggestions = {},
|
|
3710
|
+
agentOptions = [],
|
|
3711
|
+
selectedAgentId = null,
|
|
3712
|
+
onSelectAgent,
|
|
3530
3713
|
className = "",
|
|
3531
3714
|
onAddMemory,
|
|
3532
3715
|
onUpdateMemory,
|
|
3533
|
-
onDeleteMemory
|
|
3716
|
+
onDeleteMemory,
|
|
3717
|
+
initialInput,
|
|
3718
|
+
onInitialInputConsumed
|
|
3534
3719
|
}) => {
|
|
3535
3720
|
const config = mergeConfig(defaultChatConfig, userConfig);
|
|
3536
3721
|
const [isMobile, setIsMobile] = (0, import_react7.useState)(false);
|
|
@@ -3548,9 +3733,9 @@ var ChatUI = ({
|
|
|
3548
3733
|
}
|
|
3549
3734
|
return false;
|
|
3550
3735
|
};
|
|
3736
|
+
const [inputValue, setInputValue] = (0, import_react7.useState)("");
|
|
3737
|
+
const [attachments, setAttachments] = (0, import_react7.useState)([]);
|
|
3551
3738
|
const [state, setState] = (0, import_react7.useState)({
|
|
3552
|
-
input: "",
|
|
3553
|
-
attachments: [],
|
|
3554
3739
|
isRecording: false,
|
|
3555
3740
|
selectedThreadId: currentThreadId,
|
|
3556
3741
|
isAtBottom: true,
|
|
@@ -3567,16 +3752,41 @@ var ChatUI = ({
|
|
|
3567
3752
|
setState((prev) => ({ ...prev, selectedThreadId: currentThreadId }));
|
|
3568
3753
|
}
|
|
3569
3754
|
}, [currentThreadId]);
|
|
3755
|
+
const initialInputApplied = (0, import_react7.useRef)(false);
|
|
3756
|
+
const initialInputConsumedRef = (0, import_react7.useRef)(false);
|
|
3757
|
+
(0, import_react7.useEffect)(() => {
|
|
3758
|
+
if (initialInput && !initialInputApplied.current) {
|
|
3759
|
+
setInputValue(initialInput);
|
|
3760
|
+
initialInputApplied.current = true;
|
|
3761
|
+
}
|
|
3762
|
+
}, [initialInput]);
|
|
3570
3763
|
const messagesEndRef = (0, import_react7.useRef)(null);
|
|
3571
3764
|
const scrollAreaRef = (0, import_react7.useRef)(null);
|
|
3765
|
+
const stateRef = (0, import_react7.useRef)(state);
|
|
3766
|
+
const inputValueRef = (0, import_react7.useRef)(inputValue);
|
|
3767
|
+
const attachmentsRef = (0, import_react7.useRef)(attachments);
|
|
3768
|
+
(0, import_react7.useEffect)(() => {
|
|
3769
|
+
stateRef.current = state;
|
|
3770
|
+
}, [state]);
|
|
3771
|
+
(0, import_react7.useEffect)(() => {
|
|
3772
|
+
inputValueRef.current = inputValue;
|
|
3773
|
+
}, [inputValue]);
|
|
3774
|
+
(0, import_react7.useEffect)(() => {
|
|
3775
|
+
attachmentsRef.current = attachments;
|
|
3776
|
+
}, [attachments]);
|
|
3572
3777
|
const [isCustomMounted, setIsCustomMounted] = (0, import_react7.useState)(false);
|
|
3573
3778
|
const [isCustomVisible, setIsCustomVisible] = (0, import_react7.useState)(false);
|
|
3574
3779
|
const createStateCallback = (0, import_react7.useCallback)(
|
|
3575
3780
|
(setter) => ({
|
|
3576
3781
|
setState: (newState) => setter?.(newState),
|
|
3577
|
-
getState: () =>
|
|
3782
|
+
getState: () => ({
|
|
3783
|
+
...stateRef.current,
|
|
3784
|
+
input: inputValueRef.current,
|
|
3785
|
+
attachments: attachmentsRef.current
|
|
3786
|
+
})
|
|
3578
3787
|
}),
|
|
3579
|
-
[
|
|
3788
|
+
[]
|
|
3789
|
+
// No dependencies - uses refs for latest state
|
|
3580
3790
|
);
|
|
3581
3791
|
(0, import_react7.useEffect)(() => {
|
|
3582
3792
|
const checkMobile = () => {
|
|
@@ -3613,15 +3823,16 @@ var ChatUI = ({
|
|
|
3613
3823
|
const isAtBottom = scrollHeight - scrollTop - clientHeight < 50;
|
|
3614
3824
|
setState((prev) => ({ ...prev, isAtBottom }));
|
|
3615
3825
|
}, []);
|
|
3616
|
-
const handleSendMessage = (0, import_react7.useCallback)((content,
|
|
3617
|
-
if (!content.trim() &&
|
|
3618
|
-
callbacks.onSendMessage?.(content,
|
|
3619
|
-
|
|
3620
|
-
|
|
3621
|
-
|
|
3622
|
-
|
|
3623
|
-
|
|
3624
|
-
|
|
3826
|
+
const handleSendMessage = (0, import_react7.useCallback)((content, messageAttachments = []) => {
|
|
3827
|
+
if (!content.trim() && messageAttachments.length === 0) return;
|
|
3828
|
+
callbacks.onSendMessage?.(content, messageAttachments, createStateCallback());
|
|
3829
|
+
if (initialInputApplied.current && !initialInputConsumedRef.current) {
|
|
3830
|
+
initialInputConsumedRef.current = true;
|
|
3831
|
+
onInitialInputConsumed?.();
|
|
3832
|
+
}
|
|
3833
|
+
setInputValue("");
|
|
3834
|
+
setAttachments([]);
|
|
3835
|
+
}, [callbacks, createStateCallback, onInitialInputConsumed]);
|
|
3625
3836
|
const handleMessageAction = (0, import_react7.useCallback)((event) => {
|
|
3626
3837
|
const { action, messageId, content } = event;
|
|
3627
3838
|
switch (action) {
|
|
@@ -3642,7 +3853,7 @@ var ChatUI = ({
|
|
|
3642
3853
|
}
|
|
3643
3854
|
}, [callbacks, createStateCallback]);
|
|
3644
3855
|
const handleCreateThread = (0, import_react7.useCallback)((title) => {
|
|
3645
|
-
callbacks.onCreateThread?.(title, createStateCallback(
|
|
3856
|
+
callbacks.onCreateThread?.(title, createStateCallback());
|
|
3646
3857
|
}, [callbacks, createStateCallback]);
|
|
3647
3858
|
const handleSelectThread = (0, import_react7.useCallback)((threadId) => {
|
|
3648
3859
|
callbacks.onSelectThread?.(threadId, createStateCallback());
|
|
@@ -3667,23 +3878,54 @@ var ChatUI = ({
|
|
|
3667
3878
|
}
|
|
3668
3879
|
return component;
|
|
3669
3880
|
}, [config?.customComponent?.component, closeSidebar, isMobile]);
|
|
3881
|
+
const SuggestionIconComponents = [import_lucide_react11.MessageSquare, import_lucide_react11.Lightbulb, import_lucide_react11.Zap, import_lucide_react11.HelpCircle];
|
|
3670
3882
|
const renderSuggestions = () => {
|
|
3671
3883
|
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
|
-
|
|
3884
|
+
return /* @__PURE__ */ (0, import_jsx_runtime23.jsxs)("div", { className: "flex flex-col items-center justify-center min-h-[60vh] py-8 px-4", children: [
|
|
3885
|
+
/* @__PURE__ */ (0, import_jsx_runtime23.jsxs)("div", { className: "text-center mb-8", children: [
|
|
3886
|
+
/* @__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" }) }),
|
|
3887
|
+
/* @__PURE__ */ (0, import_jsx_runtime23.jsx)("h2", { className: "text-xl font-semibold mb-2", children: config.branding.title }),
|
|
3888
|
+
/* @__PURE__ */ (0, import_jsx_runtime23.jsx)("p", { className: "text-muted-foreground text-sm max-w-md", children: config.branding.subtitle })
|
|
3889
|
+
] }),
|
|
3890
|
+
/* @__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)(
|
|
3891
|
+
"button",
|
|
3678
3892
|
{
|
|
3679
|
-
|
|
3893
|
+
type: "button",
|
|
3680
3894
|
onClick: () => handleSendMessage(suggestion),
|
|
3681
|
-
|
|
3895
|
+
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",
|
|
3896
|
+
children: [
|
|
3897
|
+
(() => {
|
|
3898
|
+
const IconComponent = SuggestionIconComponents[index % SuggestionIconComponents.length];
|
|
3899
|
+
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" }) });
|
|
3900
|
+
})(),
|
|
3901
|
+
/* @__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 }) }),
|
|
3902
|
+
/* @__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" })
|
|
3903
|
+
]
|
|
3682
3904
|
},
|
|
3683
3905
|
index
|
|
3684
3906
|
)) })
|
|
3685
3907
|
] });
|
|
3686
3908
|
};
|
|
3909
|
+
const renderInlineSuggestions = (messageId) => {
|
|
3910
|
+
const items = messageSuggestions?.[messageId];
|
|
3911
|
+
if (!items || items.length === 0) return null;
|
|
3912
|
+
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)(
|
|
3913
|
+
"button",
|
|
3914
|
+
{
|
|
3915
|
+
type: "button",
|
|
3916
|
+
onClick: () => handleSendMessage(suggestion),
|
|
3917
|
+
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",
|
|
3918
|
+
children: [
|
|
3919
|
+
/* @__PURE__ */ (0, import_jsx_runtime23.jsx)(import_lucide_react11.Sparkles, { className: "h-3 w-3 text-primary opacity-70 group-hover:opacity-100" }),
|
|
3920
|
+
/* @__PURE__ */ (0, import_jsx_runtime23.jsx)("span", { className: "max-w-[200px] truncate", children: suggestion })
|
|
3921
|
+
]
|
|
3922
|
+
},
|
|
3923
|
+
`${messageId}-suggestion-${index}`
|
|
3924
|
+
)) });
|
|
3925
|
+
};
|
|
3926
|
+
const shouldShowAgentSelector = Boolean(
|
|
3927
|
+
config.agentSelector?.enabled && onSelectAgent && agentOptions.length > 0 && (!config.agentSelector?.hideIfSingle || agentOptions.length > 1)
|
|
3928
|
+
);
|
|
3687
3929
|
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
3930
|
/* @__PURE__ */ (0, import_jsx_runtime23.jsx)(
|
|
3689
3931
|
Sidebar2,
|
|
@@ -3724,7 +3966,11 @@ var ChatUI = ({
|
|
|
3724
3966
|
isMobile,
|
|
3725
3967
|
onCustomComponentToggle: () => setState((prev) => ({ ...prev, showSidebar: !prev.showSidebar })),
|
|
3726
3968
|
onNewThread: handleCreateThread,
|
|
3727
|
-
showCustomComponentButton: !!config?.customComponent?.component
|
|
3969
|
+
showCustomComponentButton: !!config?.customComponent?.component,
|
|
3970
|
+
showAgentSelector: shouldShowAgentSelector,
|
|
3971
|
+
agentOptions,
|
|
3972
|
+
selectedAgentId,
|
|
3973
|
+
onSelectAgent
|
|
3728
3974
|
}
|
|
3729
3975
|
),
|
|
3730
3976
|
/* @__PURE__ */ (0, import_jsx_runtime23.jsxs)("div", { className: "flex flex-1 flex-row min-h-0 overflow-hidden", children: [
|
|
@@ -3738,27 +3984,34 @@ var ChatUI = ({
|
|
|
3738
3984
|
onScrollCapture: handleScroll,
|
|
3739
3985
|
children: /* @__PURE__ */ (0, import_jsx_runtime23.jsxs)("div", { className: "max-w-4xl mx-auto space-y-4 pb-4", children: [
|
|
3740
3986
|
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
|
-
|
|
3987
|
+
messages.map((message, index) => {
|
|
3988
|
+
const prevMessage = index > 0 ? messages[index - 1] : null;
|
|
3989
|
+
const isGrouped = prevMessage !== null && prevMessage.role === message.role;
|
|
3990
|
+
return /* @__PURE__ */ (0, import_jsx_runtime23.jsxs)("div", { className: isGrouped ? "space-y-1 -mt-2" : "space-y-2", children: [
|
|
3991
|
+
/* @__PURE__ */ (0, import_jsx_runtime23.jsx)(
|
|
3992
|
+
Message,
|
|
3993
|
+
{
|
|
3994
|
+
message,
|
|
3995
|
+
userAvatar: user?.avatar,
|
|
3996
|
+
userName: user?.name,
|
|
3997
|
+
assistantAvatar: assistant?.avatar,
|
|
3998
|
+
assistantName: assistant?.name,
|
|
3999
|
+
showTimestamp: config.ui.showTimestamps,
|
|
4000
|
+
showAvatar: config.ui.showAvatars,
|
|
4001
|
+
enableCopy: config.features.enableMessageCopy,
|
|
4002
|
+
enableEdit: config.features.enableMessageEditing,
|
|
4003
|
+
enableRegenerate: config.features.enableRegeneration,
|
|
4004
|
+
enableToolCallsDisplay: config.features.enableToolCallsDisplay,
|
|
4005
|
+
compactMode: config.ui.compactMode,
|
|
4006
|
+
onAction: handleMessageAction,
|
|
4007
|
+
toolUsedLabel: config.labels.toolUsed,
|
|
4008
|
+
thinkingLabel: config.labels.thinking,
|
|
4009
|
+
isGrouped
|
|
4010
|
+
}
|
|
4011
|
+
),
|
|
4012
|
+
message.role === "assistant" && renderInlineSuggestions(message.id)
|
|
4013
|
+
] }, message.id);
|
|
4014
|
+
}),
|
|
3762
4015
|
/* @__PURE__ */ (0, import_jsx_runtime23.jsx)("div", { ref: messagesEndRef })
|
|
3763
4016
|
] })
|
|
3764
4017
|
}
|
|
@@ -3766,11 +4019,17 @@ var ChatUI = ({
|
|
|
3766
4019
|
/* @__PURE__ */ (0, import_jsx_runtime23.jsx)("div", { className: "bg-background pb-[env(safe-area-inset-bottom)]", children: /* @__PURE__ */ (0, import_jsx_runtime23.jsx)(
|
|
3767
4020
|
ChatInput,
|
|
3768
4021
|
{
|
|
3769
|
-
value:
|
|
3770
|
-
onChange: (value) =>
|
|
4022
|
+
value: inputValue,
|
|
4023
|
+
onChange: (value) => {
|
|
4024
|
+
setInputValue(value);
|
|
4025
|
+
if (initialInputApplied.current && !initialInputConsumedRef.current) {
|
|
4026
|
+
initialInputConsumedRef.current = true;
|
|
4027
|
+
onInitialInputConsumed?.();
|
|
4028
|
+
}
|
|
4029
|
+
},
|
|
3771
4030
|
onSubmit: handleSendMessage,
|
|
3772
|
-
attachments
|
|
3773
|
-
onAttachmentsChange:
|
|
4031
|
+
attachments,
|
|
4032
|
+
onAttachmentsChange: setAttachments,
|
|
3774
4033
|
placeholder: config.labels.inputPlaceholder,
|
|
3775
4034
|
disabled: false,
|
|
3776
4035
|
isGenerating,
|
|
@@ -3810,7 +4069,7 @@ var ChatUI = ({
|
|
|
3810
4069
|
}
|
|
3811
4070
|
)
|
|
3812
4071
|
] }),
|
|
3813
|
-
/* @__PURE__ */ (0, import_jsx_runtime23.jsx)(
|
|
4072
|
+
isUserProfileOpen && /* @__PURE__ */ (0, import_jsx_runtime23.jsx)(
|
|
3814
4073
|
UserProfile,
|
|
3815
4074
|
{
|
|
3816
4075
|
isOpen: isUserProfileOpen,
|
|
@@ -4074,7 +4333,7 @@ var ThreadManager = ({
|
|
|
4074
4333
|
] }, group)) }) })
|
|
4075
4334
|
] })
|
|
4076
4335
|
] }) }),
|
|
4077
|
-
/* @__PURE__ */ (0, import_jsx_runtime24.jsx)(AlertDialog, { open: !!deleteThreadId, onOpenChange: () => setDeleteThreadId(null), children: /* @__PURE__ */ (0, import_jsx_runtime24.jsxs)(AlertDialogContent, { children: [
|
|
4336
|
+
deleteThreadId && /* @__PURE__ */ (0, import_jsx_runtime24.jsx)(AlertDialog, { open: !!deleteThreadId, onOpenChange: () => setDeleteThreadId(null), children: /* @__PURE__ */ (0, import_jsx_runtime24.jsxs)(AlertDialogContent, { children: [
|
|
4078
4337
|
/* @__PURE__ */ (0, import_jsx_runtime24.jsxs)(AlertDialogHeader, { children: [
|
|
4079
4338
|
/* @__PURE__ */ (0, import_jsx_runtime24.jsx)(AlertDialogTitle, { children: config?.labels?.deleteConfirmTitle || "Delete Conversation" }),
|
|
4080
4339
|
/* @__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." })
|