@cmnd-ai/chatbot-react 1.8.0 → 1.9.0

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.
@@ -1,15 +1,12 @@
1
1
  import { jsx as _jsx, Fragment as _Fragment, jsxs as _jsxs } from "react/jsx-runtime";
2
- import React, { useEffect, useState } from "react";
3
- import { MessageRole, } from "../type.js";
2
+ import React, { useEffect, useRef, useState } from "react";
4
3
  import postUserConversation from "../services/postUserConversation.js";
5
4
  import getChatBotById from "../services/getchatBotById.js";
6
5
  import patchChatbotConversationMemory from "../services/patchChatbotConversationMemory/index.js";
7
6
  import deleteChatbotConversationMemory from "../services/deleteChatbotConversationMemory/index.js";
8
7
  import parseUITools from "../utils/parseUITools.js";
9
8
  import getTools from "../utils/getTools/index.js";
10
- import saveConversationIdToLocalStorage from "../utils/saveConversationIdToLocalStorage/index.js";
11
- import { ConversationsPanel } from "../components/ConversationsPanel/index.js";
12
- import useMessagesScroll from "../hooks/use-messages-scroll.js";
9
+ import { ConversationsPanel, } from "../components/ConversationsPanel/index.js";
13
10
  let globalChatbotConversationId;
14
11
  let globalChatbotProps;
15
12
  export const ChatProviderContext = React.createContext(undefined);
@@ -57,9 +54,14 @@ function ChatProvider(props) {
57
54
  const [canContinue] = useState(false);
58
55
  const [isChatLoading, setIsChatLoading] = useState(false);
59
56
  const [canSendMessage, setCanSendMessage] = useState(true);
60
- const { messagesRef, resetMessagesScroll, isMessagesScrolledToBottom } = useMessagesScroll(messages);
61
57
  const [chatbotConversationId, setChatbotConversationId] = useState(undefined);
62
58
  const [enabledTools, setEnabledTools] = useState([]);
59
+ const [isSidebarCollapsed, setIsSidebarCollapsed] = useState(false);
60
+ const [selectedConversation, setSelectedConversation] = useState(null);
61
+ const inputRef = useRef(null);
62
+ const [shouldFocusInput, setShouldFocusInput] = useState(false);
63
+ const [pendingSendText, setPendingSendText] = useState(null);
64
+ const conversationsPanelRef = useRef(null);
63
65
  useEffect(() => {
64
66
  globalChatbotConversationId = chatbotConversationId;
65
67
  }, [chatbotConversationId]);
@@ -98,54 +100,48 @@ function ChatProvider(props) {
98
100
  onData,
99
101
  });
100
102
  };
101
- const handleSendClick = async () => {
102
- if (input.trim() === "" || !canSendMessage)
103
- return;
104
- const newUserMessage = {
105
- unuseful: false,
106
- hiddenFromUser: false,
107
- role: "user",
108
- message: canContinue ? "continue" : input,
109
- };
110
- const newMessages = [...messages, newUserMessage];
111
- setMessages(newMessages);
112
- setInput("");
113
- setIsChatLoading(true);
114
- try {
115
- const onData = async (data) => {
116
- if (data.finalResponseWithUsageData) {
117
- setIsChatLoading(false);
118
- setCanSendMessage(true);
119
- const { chatbotConversationId, messages } = data;
120
- if (chatbotConversationId) {
121
- setChatbotConversationId(chatbotConversationId);
122
- await saveConversationIdToLocalStorage({
123
- chatbotConversationId,
124
- chatbotId,
125
- organizationId,
126
- });
127
- }
128
- messages && setMessages(messages);
129
- }
130
- if (data.message) {
131
- setIsChatLoading(false);
132
- const newAssistantMessage = {
133
- unuseful: false,
134
- hiddenFromUser: false,
135
- role: MessageRole.ASSISTANT,
136
- message: data.message,
137
- };
138
- setMessages([...newMessages, newAssistantMessage]);
139
- }
140
- };
141
- setCanSendMessage(false);
142
- await postSessionMessage(newMessages, onData);
103
+ const toggleSidebar = () => {
104
+ setIsSidebarCollapsed((prev) => !prev);
105
+ };
106
+ const openSidePanel = () => {
107
+ setIsSidebarCollapsed(false);
108
+ };
109
+ const closeSidePanel = () => {
110
+ setIsSidebarCollapsed(true);
111
+ };
112
+ const createNewConversation = () => {
113
+ conversationsPanelRef.current?.handleNewChat();
114
+ };
115
+ const setMessageText = (text) => {
116
+ setInput(text);
117
+ setShouldFocusInput(true);
118
+ };
119
+ useEffect(() => {
120
+ if (shouldFocusInput) {
121
+ inputRef.current?.focus();
122
+ if (inputRef.current) {
123
+ const len = inputRef.current.value.length;
124
+ inputRef.current.setSelectionRange(len, len);
125
+ }
126
+ setShouldFocusInput(false);
127
+ }
128
+ }, [input, shouldFocusInput]);
129
+ const sendMessage = (text) => {
130
+ if (typeof text === "string") {
131
+ setInput(text);
132
+ setShouldFocusInput(true);
133
+ setPendingSendText(text);
143
134
  }
144
- catch (error) {
145
- console.error(error);
146
- setError("Error sending message");
135
+ else {
136
+ conversationsPanelRef.current?.handleSendClick();
147
137
  }
148
138
  };
139
+ useEffect(() => {
140
+ if (pendingSendText !== null && input === pendingSendText) {
141
+ conversationsPanelRef.current?.handleSendClick();
142
+ setPendingSendText(null);
143
+ }
144
+ }, [input, pendingSendText]);
149
145
  if (loading)
150
146
  return null;
151
147
  return (_jsx(ChatProviderContext.Provider, { value: {
@@ -169,9 +165,15 @@ function ChatProvider(props) {
169
165
  chatbotConversationId,
170
166
  UITools: parseUITools(UITools),
171
167
  },
172
- }, children: error ? (_jsx("div", { children: "An error occured" })) : (_jsxs(_Fragment, { children: [props.children, _jsx(ConversationsPanel, { organizationId: organizationId, chatbotId: chatbotId, baseUrl: baseUrl, theme: props.theme, enabledTools: getTools({
168
+ createNewConversation,
169
+ toggleSidebar,
170
+ openSidePanel,
171
+ closeSidePanel,
172
+ setMessageText,
173
+ sendMessage,
174
+ }, children: error ? (_jsx("div", { children: "An error occured" })) : (_jsxs(_Fragment, { children: [props.children, _jsx(ConversationsPanel, { ref: conversationsPanelRef, organizationId: organizationId, chatbotId: chatbotId, baseUrl: baseUrl, theme: props.theme, enabledTools: getTools({
173
175
  apiTools: enabledTools,
174
176
  uiTools: parseUITools(UITools),
175
- }), postSessionMessage: postSessionMessage, setChatbotConversationId: setChatbotConversationId, chatbotConversationId: chatbotConversationId, Components: Components, UITools: parseUITools(UITools), customStyles: props.customStyles })] })) }));
177
+ }), postSessionMessage: postSessionMessage, setChatbotConversationId: setChatbotConversationId, chatbotConversationId: chatbotConversationId, Components: Components, UITools: parseUITools(UITools), customStyles: props.customStyles, isSidebarCollapsed: isSidebarCollapsed, setIsSidebarCollapsed: setIsSidebarCollapsed, selectedConversation: selectedConversation, setSelectedConversation: setSelectedConversation, messages: messages, setMessages: setMessages, input: input, setInput: setInput, inputRef: inputRef })] })) }));
176
178
  }
177
179
  export default ChatProvider;
@@ -1,2 +1,2 @@
1
- declare const useChatContext: () => import("../type.js").CmndChatContext;
2
- export default useChatContext;
1
+ declare const useCMNDChatContext: () => import("../type.js").CmndChatContext;
2
+ export { useCMNDChatContext };
@@ -1,9 +1,9 @@
1
1
  import { useContext } from "react";
2
2
  import { ChatProviderContext } from "./index.js";
3
- const useChatContext = () => {
3
+ const useCMNDChatContext = () => {
4
4
  const context = useContext(ChatProviderContext);
5
5
  if (!context)
6
6
  throw new Error("Cmnd chat context must be wrapped in a provider");
7
7
  return context;
8
8
  };
9
- export default useChatContext;
9
+ export { useCMNDChatContext };
@@ -3,6 +3,7 @@ interface ChatInputBoxProps {
3
3
  input: string;
4
4
  setInput: (input: string) => void;
5
5
  handleSendClick: () => void;
6
+ inputRef?: React.RefObject<HTMLInputElement>;
6
7
  }
7
- declare const ChatInputBox: ({ input, setInput, handleSendClick }: ChatInputBoxProps) => JSX.Element;
8
+ declare const ChatInputBox: ({ input, setInput, handleSendClick, inputRef, }: ChatInputBoxProps) => JSX.Element;
8
9
  export default ChatInputBox;
@@ -1,9 +1,9 @@
1
1
  import { jsx as _jsx } from "react/jsx-runtime";
2
- const ChatInputBox = ({ input, setInput, handleSendClick }) => {
3
- return (_jsx("div", { className: "cmnd-input-wrapper", children: _jsx("input", { autoFocus: true, id: "cmnd-input", className: "cmnd-input", onKeyDown: e => {
2
+ const ChatInputBox = ({ input, setInput, handleSendClick, inputRef, }) => {
3
+ return (_jsx("div", { className: "cmnd-input-wrapper", children: _jsx("input", { ref: inputRef, autoFocus: true, id: "cmnd-input", className: "cmnd-input", onKeyDown: (e) => {
4
4
  if (e.key === "Enter") {
5
5
  handleSendClick();
6
6
  }
7
- }, autoComplete: "off", value: input, onChange: e => setInput(e.target.value), type: "text", placeholder: "Type something..." }) }));
7
+ }, autoComplete: "off", value: input, onChange: (e) => setInput(e.target.value), type: "text", placeholder: "Type something..." }) }));
8
8
  };
9
9
  export default ChatInputBox;
@@ -29,6 +29,7 @@ export interface ConversationProps {
29
29
  organizationId: number;
30
30
  isMessagesScrolledToBottom?: boolean;
31
31
  resetMessagesScroll?: () => void;
32
+ inputRef?: React.RefObject<HTMLInputElement>;
32
33
  }
33
- declare const Conversation: ({ messages, handleSendClick, isChatLoading, error, messagesRef, enabledTools, postSessionMessage, setMessages, setChatbotConversationId, setIsChatLoading, setCanSendMessage, canSendMessage, setInput, input, theme, Components, UITools, customStyles, chatbotId, organizationId, isMessagesScrolledToBottom, resetMessagesScroll, }: ConversationProps) => JSX.Element;
34
+ declare const Conversation: ({ messages, handleSendClick, isChatLoading, error, messagesRef, enabledTools, postSessionMessage, setMessages, setChatbotConversationId, setIsChatLoading, setCanSendMessage, canSendMessage, setInput, input, theme, Components, UITools, customStyles, chatbotId, organizationId, isMessagesScrolledToBottom, resetMessagesScroll, inputRef, }: ConversationProps) => JSX.Element;
34
35
  export default Conversation;
@@ -3,8 +3,8 @@ import Chatbubble from "./Chatbubble.js";
3
3
  import LoadingBubble from "./LoadingBubble.js";
4
4
  import ScrollToBottomButton from "./ScrollToBottomButton.js";
5
5
  import ChatInputBox from "./ChatInputBox.js";
6
- const Conversation = ({ messages, handleSendClick, isChatLoading, error, messagesRef, enabledTools, postSessionMessage, setMessages, setChatbotConversationId, setIsChatLoading, setCanSendMessage, canSendMessage, setInput, input, theme, Components, UITools, customStyles, chatbotId, organizationId, isMessagesScrolledToBottom = true, resetMessagesScroll, }) => {
7
- return (_jsxs("div", { className: "cmnd-conversations", children: [_jsxs("div", { ref: messagesRef, id: "messages", className: "cmnd-conversations-messages", children: [error, messages.map((m, i) => (_jsx(Chatbubble, { chatbotId: chatbotId, organizationId: organizationId, customStyles: customStyles, hide: m.hiddenFromUser, message: m.message, role: m.role, toolCallDetails: m.tool, tools: enabledTools, postSessionMessage: postSessionMessage, messages: messages, setMessages: setMessages, id: m.id, setChatbotConversationId: setChatbotConversationId, setIsChatLoading: setIsChatLoading, setCanSendMessage: setCanSendMessage, UITools: UITools, theme: theme, Components: Components }, i))), isChatLoading ? (_jsx(LoadingBubble, { customStyles: customStyles, chatbotId: chatbotId, organizationId: organizationId, theme: theme, Components: Components })) : null] }), _jsx(ScrollToBottomButton, { onClick: resetMessagesScroll || (() => { }), isVisible: !isMessagesScrolledToBottom && messages.length > 0, theme: theme, customStyles: customStyles }), _jsxs("div", { id: "cmnd-input-div", className: "cmnd-input-div", children: [Components?.InputField ? (_jsx(Components.InputField, { ...{ input, setInput, canSendMessage, handleSendClick } })) : (_jsx(ChatInputBox, { input: input, setInput: setInput, handleSendClick: handleSendClick })), Components?.SendButton ? (_jsx(Components.SendButton, { ...{
6
+ const Conversation = ({ messages, handleSendClick, isChatLoading, error, messagesRef, enabledTools, postSessionMessage, setMessages, setChatbotConversationId, setIsChatLoading, setCanSendMessage, canSendMessage, setInput, input, theme, Components, UITools, customStyles, chatbotId, organizationId, isMessagesScrolledToBottom = true, resetMessagesScroll, inputRef, }) => {
7
+ return (_jsxs("div", { className: "cmnd-conversations", children: [_jsxs("div", { ref: messagesRef, id: "messages", className: "cmnd-conversations-messages", children: [error, messages.map((m, i) => (_jsx(Chatbubble, { chatbotId: chatbotId, organizationId: organizationId, customStyles: customStyles, hide: m.hiddenFromUser, message: m.message, role: m.role, toolCallDetails: m.tool, tools: enabledTools, postSessionMessage: postSessionMessage, messages: messages, setMessages: setMessages, id: m.id, setChatbotConversationId: setChatbotConversationId, setIsChatLoading: setIsChatLoading, setCanSendMessage: setCanSendMessage, UITools: UITools, theme: theme, Components: Components }, i))), isChatLoading ? (_jsx(LoadingBubble, { customStyles: customStyles, chatbotId: chatbotId, organizationId: organizationId, theme: theme, Components: Components })) : null] }), _jsx(ScrollToBottomButton, { onClick: resetMessagesScroll || (() => { }), isVisible: !isMessagesScrolledToBottom && messages.length > 0, theme: theme, customStyles: customStyles }), _jsxs("div", { id: "cmnd-input-div", className: "cmnd-input-div", children: [Components?.InputField ? (_jsx(Components.InputField, { ...{ input, setInput, canSendMessage, handleSendClick, inputRef } })) : (_jsx(ChatInputBox, { input: input, setInput: setInput, handleSendClick: handleSendClick, inputRef: inputRef })), Components?.SendButton ? (_jsx(Components.SendButton, { ...{
8
8
  canSendMessage,
9
9
  handleSendClick,
10
10
  } })) : (_jsx("button", { className: "cmnd-send-button", onClick: handleSendClick, children: "Send" }))] })] }));
@@ -1,5 +1,5 @@
1
1
  import React, { Dispatch, SetStateAction } from "react";
2
- import { InputFieldProps, SendButtonProps } from "../../type.js";
2
+ import { ChatbotConversation, InputFieldProps, SendButtonProps } from "../../type.js";
3
3
  interface ConversationsPanelProps {
4
4
  organizationId: number;
5
5
  chatbotId: number;
@@ -28,6 +28,19 @@ interface ConversationsPanelProps {
28
28
  dateStyle?: React.CSSProperties;
29
29
  deleteButtonStyle?: React.CSSProperties;
30
30
  };
31
+ isSidebarCollapsed?: boolean;
32
+ setIsSidebarCollapsed?: React.Dispatch<React.SetStateAction<boolean>>;
33
+ selectedConversation: ChatbotConversation | null;
34
+ setSelectedConversation: React.Dispatch<React.SetStateAction<ChatbotConversation | null>>;
35
+ messages: any[];
36
+ setMessages: React.Dispatch<React.SetStateAction<any[]>>;
37
+ input: string;
38
+ setInput: React.Dispatch<React.SetStateAction<string>>;
39
+ inputRef: React.RefObject<HTMLInputElement>;
31
40
  }
32
- export declare const ConversationsPanel: React.FC<ConversationsPanelProps>;
41
+ export interface ConversationsPanelRef {
42
+ handleSendClick: () => void;
43
+ handleNewChat: () => void;
44
+ }
45
+ export declare const ConversationsPanel: React.ForwardRefExoticComponent<ConversationsPanelProps & React.RefAttributes<ConversationsPanelRef>>;
33
46
  export {};
@@ -1,5 +1,5 @@
1
1
  import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
2
- import React, { useState, useEffect, } from "react";
2
+ import React, { useState, useEffect, forwardRef, useImperativeHandle, } from "react";
3
3
  import useFetchData from "../../hooks/use-fetch-data.js";
4
4
  import getChatBotConversationsList from "../../services/getChatBotConversationsList/index.js";
5
5
  import Conversation from "../Conversation.js";
@@ -10,14 +10,17 @@ import getConversationLocalStorageKey from "../../utils/getConversationLocalStor
10
10
  import saveConversationIdToLocalStorage from "../../utils/saveConversationIdToLocalStorage/index.js";
11
11
  import getUTCDateTime from "../../utils/getUTCDateTime/index.js";
12
12
  import useMessagesScroll from "../../hooks/use-messages-scroll.js";
13
- export const ConversationsPanel = ({ organizationId, chatbotId, baseUrl, theme = "light", enabledTools = [], setChatbotConversationId, chatbotConversationId, postSessionMessage, Components, UITools, customStyles, }) => {
14
- const [selectedConversation, setSelectedConversation] = useState(null);
15
- const [messages, setMessages] = useState([]);
16
- const [input, setInput] = useState("");
13
+ export const ConversationsPanel = forwardRef(({ organizationId, chatbotId, baseUrl, theme = "light", enabledTools = [], setChatbotConversationId, chatbotConversationId, postSessionMessage, Components, UITools, customStyles, isSidebarCollapsed, setIsSidebarCollapsed, selectedConversation, setSelectedConversation, messages, setMessages, input, setInput, inputRef, }, ref) => {
17
14
  const [isChatLoading, setIsChatLoading] = useState(false);
18
15
  const [canSendMessage, setCanSendMessage] = useState(true);
19
16
  const [conversationIds, setConversationIds] = useState([]);
20
- const [isSidebarCollapsed, setIsSidebarCollapsed] = useState(false);
17
+ const isSidebarCollapsedProp = typeof isSidebarCollapsed === "boolean" ? isSidebarCollapsed : false;
18
+ const setIsSidebarCollapsedProp = setIsSidebarCollapsed;
19
+ const [internalSidebarCollapsed, setInternalSidebarCollapsed] = useState(false);
20
+ const isSidebarCollapsedFinal = typeof isSidebarCollapsed === "boolean"
21
+ ? isSidebarCollapsed
22
+ : internalSidebarCollapsed;
23
+ const setIsSidebarCollapsedFinal = setIsSidebarCollapsedProp || setInternalSidebarCollapsed;
21
24
  const { messagesRef, resetMessagesScroll, isMessagesScrolledToBottom } = useMessagesScroll(messages);
22
25
  const themeColors = {
23
26
  light: {
@@ -72,23 +75,27 @@ export const ConversationsPanel = ({ organizationId, chatbotId, baseUrl, theme =
72
75
  setConversationIds([]);
73
76
  }
74
77
  };
75
- const { data, loading, error, refetch } = useFetchData(() => {
78
+ const { data, loading, error, refetch } = useFetchData(async () => {
76
79
  // Only fetch if we have conversation IDs
77
80
  if (conversationIds.length === 0) {
78
- return Promise.resolve({
79
- data: { chatbotConversations: [] },
80
- status: 200,
81
- statusText: "OK",
82
- headers: {},
83
- config: {},
81
+ return { chatbotConversations: [] };
82
+ }
83
+ try {
84
+ return await getChatBotConversationsList({
85
+ organizationId,
86
+ chatbotId,
87
+ conversationIds,
88
+ baseUrl,
89
+ }).catch((error) => {
90
+ // Ignore any error from axios and return an empty list
91
+ console.error("Error fetching conversations (ignored):", error);
92
+ return { chatbotConversations: [] };
84
93
  });
85
94
  }
86
- return getChatBotConversationsList({
87
- organizationId,
88
- chatbotId,
89
- conversationIds,
90
- baseUrl,
91
- });
95
+ catch (error) {
96
+ console.error("Error fetching conversations (sync):", error);
97
+ return { chatbotConversations: [] };
98
+ }
92
99
  }, [organizationId, chatbotId, conversationIds, baseUrl]);
93
100
  const handleSendClick = () => {
94
101
  if (!input.trim() || !canSendMessage)
@@ -119,7 +126,8 @@ export const ConversationsPanel = ({ organizationId, chatbotId, baseUrl, theme =
119
126
  });
120
127
  refetchConversationIds();
121
128
  if (selectedConversation &&
122
- selectedConversation.chatbotConversationTitle === "New Conversation") {
129
+ selectedConversation.chatbotConversationTitle ===
130
+ "New Conversation") {
123
131
  setSelectedConversation({
124
132
  ...selectedConversation,
125
133
  chatbotConversationId: newConversationId,
@@ -213,6 +221,10 @@ export const ConversationsPanel = ({ organizationId, chatbotId, baseUrl, theme =
213
221
  return dateB.getTime() - dateA.getTime();
214
222
  });
215
223
  }, [data?.chatbotConversations, selectedConversation]);
224
+ useImperativeHandle(ref, () => ({
225
+ handleSendClick,
226
+ handleNewChat,
227
+ }));
216
228
  return (_jsxs("div", { className: "cmnd-conversations-panel", style: {
217
229
  display: "flex",
218
230
  height: "100%",
@@ -220,7 +232,7 @@ export const ConversationsPanel = ({ organizationId, chatbotId, baseUrl, theme =
220
232
  color: colors.text,
221
233
  ...customStyles?.panelStyle,
222
234
  }, children: [_jsxs("div", { className: "cmnd-conversations-sidebar", style: {
223
- width: isSidebarCollapsed ? "50px" : "300px",
235
+ width: isSidebarCollapsedFinal ? "50px" : "300px",
224
236
  borderRight: `1px solid ${colors.border}`,
225
237
  display: "flex",
226
238
  flexDirection: "column",
@@ -228,15 +240,17 @@ export const ConversationsPanel = ({ organizationId, chatbotId, baseUrl, theme =
228
240
  transition: "width 0.3s ease",
229
241
  ...customStyles?.sidebarStyle,
230
242
  }, children: [_jsxs("div", { className: "cmnd-conversations-header", style: {
231
- padding: isSidebarCollapsed ? "12px 8px" : "16px",
243
+ padding: isSidebarCollapsedFinal ? "12px 8px" : "16px",
232
244
  borderBottom: `1px solid ${colors.border}`,
233
245
  display: "flex",
234
- justifyContent: isSidebarCollapsed ? "center" : "space-between",
246
+ justifyContent: isSidebarCollapsedFinal
247
+ ? "center"
248
+ : "space-between",
235
249
  alignItems: "center",
236
- flexDirection: isSidebarCollapsed ? "column" : "row",
237
- gap: isSidebarCollapsed ? "8px" : "0",
250
+ flexDirection: isSidebarCollapsedFinal ? "column" : "row",
251
+ gap: isSidebarCollapsedFinal ? "8px" : "0",
238
252
  ...customStyles?.headerStyle,
239
- }, children: [!isSidebarCollapsed && (_jsx("h3", { style: {
253
+ }, children: [!isSidebarCollapsedFinal && (_jsx("h3", { style: {
240
254
  margin: 0,
241
255
  fontSize: "16px",
242
256
  fontWeight: "600",
@@ -244,8 +258,10 @@ export const ConversationsPanel = ({ organizationId, chatbotId, baseUrl, theme =
244
258
  }, children: "Conversations" })), _jsxs("div", { style: {
245
259
  display: "flex",
246
260
  gap: "8px",
247
- flexDirection: isSidebarCollapsed ? "column" : "row",
248
- }, children: [_jsx("button", { className: "cmnd-toggle-sidebar-button", onClick: () => setIsSidebarCollapsed(!isSidebarCollapsed), title: isSidebarCollapsed ? "Expand Sidebar" : "Collapse Sidebar", style: {
261
+ flexDirection: isSidebarCollapsedFinal ? "column" : "row",
262
+ }, children: [_jsx("button", { className: "cmnd-toggle-sidebar-button", onClick: () => setIsSidebarCollapsedFinal((prev) => !prev), title: isSidebarCollapsedFinal
263
+ ? "Expand Sidebar"
264
+ : "Collapse Sidebar", style: {
249
265
  background: colors.button,
250
266
  border: "none",
251
267
  color: theme === "light" ? "#ffffff" : colors.text,
@@ -282,7 +298,7 @@ export const ConversationsPanel = ({ organizationId, chatbotId, baseUrl, theme =
282
298
  overflowY: "auto",
283
299
  padding: "12px",
284
300
  ...customStyles?.conversationListStyle,
285
- }, children: isSidebarCollapsed ? (_jsx("div", { style: {
301
+ }, children: isSidebarCollapsedFinal ? (_jsx("div", { style: {
286
302
  textAlign: "center",
287
303
  padding: "8px",
288
304
  color: colors.secondaryText,
@@ -291,19 +307,25 @@ export const ConversationsPanel = ({ organizationId, chatbotId, baseUrl, theme =
291
307
  textAlign: "center",
292
308
  padding: "20px",
293
309
  color: colors.secondaryText,
294
- }, children: "Loading conversations..." })) : error && allConversations.length === 0 ? (_jsx("div", { style: { textAlign: "center", padding: "20px", color: "#ff6b6b" }, children: "Error loading conversations" })) : allConversations.length === 0 ? (_jsx("div", { style: {
310
+ }, children: "Loading conversations..." })) : error && allConversations.length === 0 ? (_jsx("div", { style: {
311
+ textAlign: "center",
312
+ padding: "20px",
313
+ color: "#ff6b6b",
314
+ }, children: "Error loading conversations" })) : allConversations.length === 0 ? (_jsx("div", { style: {
295
315
  textAlign: "center",
296
316
  padding: "20px",
297
317
  color: colors.secondaryText,
298
318
  }, children: "No conversations yet" })) : (allConversations.map((conversation) => (_jsx(ConversationCard, { conversation: conversation, isActive: selectedConversation?.chatbotConversationId ===
299
319
  conversation.chatbotConversationId, onClick: () => {
300
- if (conversation.chatbotConversationTitle === "New Conversation") {
320
+ if (conversation.chatbotConversationTitle ===
321
+ "New Conversation") {
301
322
  }
302
323
  else {
303
324
  handleConversationSelect(conversation);
304
325
  }
305
326
  }, onDelete: () => {
306
- if (conversation.chatbotConversationTitle === "New Conversation") {
327
+ if (conversation.chatbotConversationTitle ===
328
+ "New Conversation") {
307
329
  setSelectedConversation(null);
308
330
  setMessages([]);
309
331
  }
@@ -329,5 +351,5 @@ export const ConversationsPanel = ({ organizationId, chatbotId, baseUrl, theme =
329
351
  fontSize: "16px",
330
352
  textAlign: "center",
331
353
  padding: "20px",
332
- }, children: _jsx("div", { children: _jsx("div", { children: "Select a conversation or start a new one" }) }) })) : (_jsx(Conversation, { messages: messages, setMessages: setMessages, handleSendClick: handleSendClick, input: input, setInput: setInput, isChatLoading: isChatLoading, error: error ? "Error loading conversations" : null, messagesRef: messagesRef, setChatbotConversationId: setChatbotConversationId, chatbotConversationId: chatbotConversationId, setIsChatLoading: setIsChatLoading, setCanSendMessage: setCanSendMessage, canSendMessage: canSendMessage, enabledTools: enabledTools, postSessionMessage: postSessionMessage, theme: theme, Components: Components, UITools: UITools, customStyles: customStyles, setCurrentConversationMemory: setCurrentConversationMemory, chatbotId: chatbotId, organizationId: organizationId, isMessagesScrolledToBottom: isMessagesScrolledToBottom, resetMessagesScroll: resetMessagesScroll })) })] }));
333
- };
354
+ }, children: _jsx("div", { children: _jsx("div", { children: "Select a conversation or start a new one" }) }) })) : (_jsx(Conversation, { messages: messages, setMessages: setMessages, handleSendClick: handleSendClick, input: input, setInput: setInput, isChatLoading: isChatLoading, error: error ? "Error loading conversations" : null, messagesRef: messagesRef, setChatbotConversationId: setChatbotConversationId, chatbotConversationId: chatbotConversationId, setIsChatLoading: setIsChatLoading, setCanSendMessage: setCanSendMessage, canSendMessage: canSendMessage, enabledTools: enabledTools, postSessionMessage: postSessionMessage, theme: theme, Components: Components, UITools: UITools, customStyles: customStyles, setCurrentConversationMemory: setCurrentConversationMemory, chatbotId: chatbotId, organizationId: organizationId, isMessagesScrolledToBottom: isMessagesScrolledToBottom, resetMessagesScroll: resetMessagesScroll, inputRef: inputRef })) })] }));
355
+ });
@@ -1,9 +1,8 @@
1
- import { AxiosPromise } from "axios";
2
1
  type UseFetchDataResult<T = any> = {
3
2
  loading: boolean;
4
3
  error: boolean;
5
4
  data: T;
6
5
  refetch: () => void;
7
6
  };
8
- declare const useFetchData: <T = any>(apiCallFn: () => AxiosPromise<T>, deps?: any[]) => UseFetchDataResult<T>;
7
+ declare const useFetchData: <T = any>(apiCallFn: () => Promise<T>, deps?: any[]) => UseFetchDataResult<T>;
9
8
  export default useFetchData;
@@ -10,7 +10,7 @@ const useFetchData = (apiCallFn, deps = []) => {
10
10
  setError(false);
11
11
  try {
12
12
  const response = await apiCallFn();
13
- setData(response.data);
13
+ setData(response);
14
14
  }
15
15
  catch {
16
16
  setError(true);
package/dist/index.d.ts CHANGED
@@ -2,3 +2,4 @@ export { default as ChatProvider } from "./ChatProvider/index.js";
2
2
  export { ConversationsPanel } from "./components/ConversationsPanel/index.js";
3
3
  export { CmndChatContext, InputFieldProps, SendButtonProps, CustomStyles, CMNDChatMemory, ChatbotConversation, ChatbotConversationsResponse, } from "./type.js";
4
4
  export { setCurrentConversationMemory, deleteCurrentConversationMemory, } from "./ChatProvider/index.js";
5
+ export { useCMNDChatContext } from "./ChatProvider/useChatContext.js";
package/dist/index.js CHANGED
@@ -1,3 +1,4 @@
1
1
  export { default as ChatProvider } from "./ChatProvider/index.js";
2
2
  export { ConversationsPanel } from "./components/ConversationsPanel/index.js";
3
3
  export { setCurrentConversationMemory, deleteCurrentConversationMemory, } from "./ChatProvider/index.js";
4
+ export { useCMNDChatContext } from "./ChatProvider/useChatContext.js";
@@ -3,5 +3,5 @@ declare const getChatBotConversationsList: ({ organizationId, chatbotId, convers
3
3
  chatbotId: number;
4
4
  conversationIds: number[];
5
5
  baseUrl: string;
6
- }) => Promise<import("axios").AxiosResponse<any, any>>;
6
+ }) => Promise<any>;
7
7
  export default getChatBotConversationsList;
@@ -1,11 +1,12 @@
1
1
  import axios from "axios";
2
2
  import { chatbot } from "../../constants/endpoints.js";
3
- const getChatBotConversationsList = ({ organizationId, chatbotId, conversationIds, baseUrl, }) => {
3
+ const getChatBotConversationsList = async ({ organizationId, chatbotId, conversationIds, baseUrl, }) => {
4
4
  const endpoint = chatbot.getChatBotConversationsList({
5
5
  organizationId,
6
6
  chatbotId,
7
7
  conversationIds,
8
8
  });
9
- return axios.get(`${baseUrl}${endpoint}`);
9
+ const response = await axios.get(`${baseUrl}${endpoint}`);
10
+ return response.data;
10
11
  };
11
12
  export default getChatBotConversationsList;
package/dist/type.d.ts CHANGED
@@ -2,12 +2,37 @@ import { CSSProperties } from "react";
2
2
  import { ConversationProps } from "./components/Conversation.js";
3
3
  export interface CmndChatContext {
4
4
  props: Partial<ConversationProps>;
5
+ /**
6
+ * Create a new conversation (resets state, starts a new chat thread)
7
+ */
8
+ createNewConversation: () => void;
9
+ /**
10
+ * Toggle the sidebar open/collapsed state
11
+ */
12
+ toggleSidebar: () => void;
13
+ /**
14
+ * Open the sidebar (set collapsed to false)
15
+ */
16
+ openSidePanel: () => void;
17
+ /**
18
+ * Close the sidebar (set collapsed to true)
19
+ */
20
+ closeSidePanel: () => void;
21
+ /**
22
+ * Set the message text in the input box
23
+ */
24
+ setMessageText: (text: string) => void;
25
+ /**
26
+ * Send the current message, or set and send if text is provided
27
+ */
28
+ sendMessage: (text?: string) => void;
5
29
  }
6
30
  export interface InputFieldProps {
7
31
  input: string;
8
32
  setInput: (input: string) => void;
9
33
  canSendMessage: boolean;
10
34
  handleSendClick: () => void;
35
+ inputRef?: React.RefObject<HTMLInputElement> | React.RefObject<HTMLTextAreaElement> | React.RefObject<HTMLTextAreaElement>;
11
36
  }
12
37
  export interface SendButtonProps {
13
38
  handleSendClick: () => void;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@cmnd-ai/chatbot-react",
3
- "version": "1.8.0",
3
+ "version": "1.9.0",
4
4
  "main": "dist/index.js",
5
5
  "description": "",
6
6
  "type": "module",