@fusioni/client-sdk 1.1.10 → 1.1.12
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/components/ChatWidget.d.ts.map +1 -1
- package/dist/components/FloatingButton.d.ts.map +1 -1
- package/dist/components/Message.d.ts.map +1 -1
- package/dist/fusioni-sdk.umd.js +120 -51
- package/dist/fusioni-sdk.umd.js.map +1 -1
- package/dist/index.css +1 -1
- package/dist/index.esm.css +1 -1
- package/dist/index.esm.js +118 -49
- package/dist/index.esm.js.map +1 -1
- package/dist/index.js +118 -49
- package/dist/index.js.map +1 -1
- package/package.json +1 -1
package/dist/index.js
CHANGED
|
@@ -4959,11 +4959,12 @@ const DocumentVideoGrid = ({ videos, attachedVideosLabel, }) => {
|
|
|
4959
4959
|
// Module-level Set to track which message IDs have been animated
|
|
4960
4960
|
// This persists across component unmounts/remounts (e.g., when chat closes and reopens)
|
|
4961
4961
|
const animatedMessageIds = new Set();
|
|
4962
|
+
const TYPING_PREVIEW_CHARACTER_LIMIT = 200;
|
|
4962
4963
|
const Message = ({ message, showThoughts = false, fontSize = 'text-sm', onDelete, onConfirmation, enableButtons = true, apiBaseUrl, apiKey, agencyId, currentLanguage = 'en', onOpenGallery }) => {
|
|
4963
4964
|
const { t } = useTranslation(currentLanguage);
|
|
4964
4965
|
const [displayedContent, setDisplayedContent] = react.useState('');
|
|
4965
4966
|
const typingIntervalRef = react.useRef(null);
|
|
4966
|
-
const typingSpeed =
|
|
4967
|
+
const typingSpeed = 5; // milliseconds per character
|
|
4967
4968
|
const enhanceMessageContent = (content) => {
|
|
4968
4969
|
if (!content)
|
|
4969
4970
|
return content;
|
|
@@ -5113,6 +5114,7 @@ const Message = ({ message, showThoughts = false, fontSize = 'text-sm', onDelete
|
|
|
5113
5114
|
// Now animate through segments
|
|
5114
5115
|
let segmentIndex = 0;
|
|
5115
5116
|
let textIndex = 0;
|
|
5117
|
+
let typedCharacterCount = 0;
|
|
5116
5118
|
const nextTextStep = (text, index) => {
|
|
5117
5119
|
if (index >= text.length)
|
|
5118
5120
|
return { nextIndex: index, slice: '' };
|
|
@@ -5149,6 +5151,11 @@ const Message = ({ message, showThoughts = false, fontSize = 'text-sm', onDelete
|
|
|
5149
5151
|
typingIntervalRef.current = setTimeout(typeNextChar, 0);
|
|
5150
5152
|
}
|
|
5151
5153
|
else {
|
|
5154
|
+
if (typedCharacterCount >= TYPING_PREVIEW_CHARACTER_LIMIT) {
|
|
5155
|
+
setDisplayedContent(fullContent);
|
|
5156
|
+
animatedMessageIds.add(messageId);
|
|
5157
|
+
return;
|
|
5158
|
+
}
|
|
5152
5159
|
// Text segments are typed character by character
|
|
5153
5160
|
if (textIndex < segment.content.length) {
|
|
5154
5161
|
const step = nextTextStep(segment.content, textIndex);
|
|
@@ -5166,6 +5173,14 @@ const Message = ({ message, showThoughts = false, fontSize = 'text-sm', onDelete
|
|
|
5166
5173
|
content += step.slice;
|
|
5167
5174
|
setDisplayedContent(content);
|
|
5168
5175
|
textIndex = step.nextIndex;
|
|
5176
|
+
typedCharacterCount++;
|
|
5177
|
+
if (typedCharacterCount >= TYPING_PREVIEW_CHARACTER_LIMIT) {
|
|
5178
|
+
typingIntervalRef.current = setTimeout(() => {
|
|
5179
|
+
setDisplayedContent(fullContent);
|
|
5180
|
+
animatedMessageIds.add(messageId);
|
|
5181
|
+
}, typingSpeed);
|
|
5182
|
+
return;
|
|
5183
|
+
}
|
|
5169
5184
|
typingIntervalRef.current = setTimeout(typeNextChar, typingSpeed);
|
|
5170
5185
|
}
|
|
5171
5186
|
else {
|
|
@@ -5705,11 +5720,9 @@ const FloatingButton = ({ isOpen, onClick, position = 'bottom-right', primaryCol
|
|
|
5705
5720
|
const [showAttentionSequence, setShowAttentionSequence] = react.useState(false);
|
|
5706
5721
|
const [isAttentionActive, setIsAttentionActive] = react.useState(false);
|
|
5707
5722
|
react.useEffect(() => {
|
|
5708
|
-
// Sophisticated entrance animation
|
|
5709
5723
|
const entranceTimer = setTimeout(() => {
|
|
5710
5724
|
setIsVisible(true);
|
|
5711
5725
|
}, 200);
|
|
5712
|
-
// Periodic attention sequence (every 15 seconds)
|
|
5713
5726
|
const attentionInterval = setInterval(() => {
|
|
5714
5727
|
if (!isHovered && !isOpen) {
|
|
5715
5728
|
setShowAttentionSequence(true);
|
|
@@ -6093,6 +6106,33 @@ function useIsMobileLayout() {
|
|
|
6093
6106
|
return isMobile;
|
|
6094
6107
|
}
|
|
6095
6108
|
|
|
6109
|
+
const getStoredConversationIdKey = (agencyId) => `fusioni:selectedConversationId:${agencyId}`;
|
|
6110
|
+
const readStoredConversationId = (agencyId) => {
|
|
6111
|
+
if (typeof window === 'undefined')
|
|
6112
|
+
return null;
|
|
6113
|
+
try {
|
|
6114
|
+
return window.sessionStorage.getItem(getStoredConversationIdKey(agencyId));
|
|
6115
|
+
}
|
|
6116
|
+
catch {
|
|
6117
|
+
return null;
|
|
6118
|
+
}
|
|
6119
|
+
};
|
|
6120
|
+
const writeStoredConversationId = (agencyId, conversationId) => {
|
|
6121
|
+
if (typeof window === 'undefined')
|
|
6122
|
+
return;
|
|
6123
|
+
try {
|
|
6124
|
+
const key = getStoredConversationIdKey(agencyId);
|
|
6125
|
+
if (conversationId) {
|
|
6126
|
+
window.sessionStorage.setItem(key, conversationId);
|
|
6127
|
+
}
|
|
6128
|
+
else {
|
|
6129
|
+
window.sessionStorage.removeItem(key);
|
|
6130
|
+
}
|
|
6131
|
+
}
|
|
6132
|
+
catch {
|
|
6133
|
+
// Storage can be unavailable in restricted browser contexts.
|
|
6134
|
+
}
|
|
6135
|
+
};
|
|
6096
6136
|
const ChatWidget = react.forwardRef(function ChatWidget({ config, onMessageSent, onMessageReceived, onConversationCreated, onConversationDeleted, onError }, ref) {
|
|
6097
6137
|
const [languageOverride, setLanguageOverride] = react.useState(null);
|
|
6098
6138
|
const [isOpen, setIsOpen] = react.useState(false);
|
|
@@ -6107,12 +6147,15 @@ const ChatWidget = react.forwardRef(function ChatWidget({ config, onMessageSent,
|
|
|
6107
6147
|
const [isDeleteDialogOpen, setIsDeleteDialogOpen] = react.useState(false);
|
|
6108
6148
|
const [messageToDelete, setMessageToDelete] = react.useState(null);
|
|
6109
6149
|
const [isDeleteMessageDialogOpen, setIsDeleteMessageDialogOpen] = react.useState(false);
|
|
6150
|
+
const [hasLoadedConversations, setHasLoadedConversations] = react.useState(false);
|
|
6110
6151
|
// Refs
|
|
6111
6152
|
const floatingButtonRef = react.useRef(null);
|
|
6153
|
+
const restoredConversationIdRef = react.useRef(null);
|
|
6112
6154
|
const translationDefault = languageOverride ?? mergedConfig?.language ?? config.language ?? 'en';
|
|
6113
6155
|
// Translation and language management - use merged config or fallback to user config
|
|
6114
6156
|
const { t, currentLanguage, changeLanguage } = useTranslation(translationDefault);
|
|
6115
|
-
const
|
|
6157
|
+
const activeAgencyId = mergedConfig?.agencyId || config.agencyId;
|
|
6158
|
+
const { conversations, currentConversation, messages, streamMessages, setCurrentConversation, setStreamMessages, addMessage, updateMessage, removeMessage, removeOptimisticUserMessages, truncateMessagesAt, addConversation, updateConversation, removeConversation, loadConversations, loadMessages, clearMessages } = useChatState(activeAgencyId);
|
|
6116
6159
|
const { theme, toggleTheme, setTheme } = useTheme(mergedConfig?.theme || config.theme);
|
|
6117
6160
|
const isMobileLayout = useIsMobileLayout();
|
|
6118
6161
|
const handleLanguageChange = react.useCallback((language) => {
|
|
@@ -6179,12 +6222,22 @@ const ChatWidget = react.forwardRef(function ChatWidget({ config, onMessageSent,
|
|
|
6179
6222
|
}, [config, onError, t]);
|
|
6180
6223
|
// Load initial conversations
|
|
6181
6224
|
react.useEffect(() => {
|
|
6182
|
-
if (
|
|
6183
|
-
|
|
6225
|
+
if (activeAgencyId) {
|
|
6226
|
+
let isCancelled = false;
|
|
6227
|
+
restoredConversationIdRef.current = null;
|
|
6228
|
+
setHasLoadedConversations(false);
|
|
6229
|
+
loadConversations().finally(() => {
|
|
6230
|
+
if (!isCancelled) {
|
|
6231
|
+
setHasLoadedConversations(true);
|
|
6232
|
+
}
|
|
6233
|
+
});
|
|
6234
|
+
return () => {
|
|
6235
|
+
isCancelled = true;
|
|
6236
|
+
};
|
|
6184
6237
|
}
|
|
6185
|
-
}, [
|
|
6238
|
+
}, [activeAgencyId, loadConversations]);
|
|
6186
6239
|
// SSE connection for real-time updates - only when a chat panel is open
|
|
6187
|
-
useSSE(
|
|
6240
|
+
useSSE(activeAgencyId, (data) => {
|
|
6188
6241
|
// Same as fusioni-web chat.component: latest SSE line replaces stream (single loading row updates)
|
|
6189
6242
|
if (data?.data != null && String(data.data).trim() !== '') {
|
|
6190
6243
|
setStreamMessages([String(data.data)]);
|
|
@@ -6208,6 +6261,7 @@ const ChatWidget = react.forwardRef(function ChatWidget({ config, onMessageSent,
|
|
|
6208
6261
|
const handleCreateConversation = react.useCallback(() => {
|
|
6209
6262
|
if (!mergedConfig)
|
|
6210
6263
|
return;
|
|
6264
|
+
writeStoredConversationId(activeAgencyId, null);
|
|
6211
6265
|
// Create a new conversation with null ID - will be created on server when first message is sent
|
|
6212
6266
|
const newConversation = {
|
|
6213
6267
|
id: null,
|
|
@@ -6223,7 +6277,7 @@ const ChatWidget = react.forwardRef(function ChatWidget({ config, onMessageSent,
|
|
|
6223
6277
|
// Auto-hide conversation list when a new conversation is created
|
|
6224
6278
|
setIsConversationListOpen(false);
|
|
6225
6279
|
onConversationCreated?.(newConversation);
|
|
6226
|
-
}, [mergedConfig, addConversation, setCurrentConversation, clearMessages, onConversationCreated, t]);
|
|
6280
|
+
}, [activeAgencyId, mergedConfig, addConversation, setCurrentConversation, clearMessages, onConversationCreated, t]);
|
|
6227
6281
|
const handleSelectConversation = react.useCallback(async (conversation) => {
|
|
6228
6282
|
try {
|
|
6229
6283
|
setIsLoading(true);
|
|
@@ -6231,6 +6285,9 @@ const ChatWidget = react.forwardRef(function ChatWidget({ config, onMessageSent,
|
|
|
6231
6285
|
clearMessages();
|
|
6232
6286
|
setStreamMessages([]);
|
|
6233
6287
|
setCurrentConversation(conversation);
|
|
6288
|
+
if (conversation.id) {
|
|
6289
|
+
writeStoredConversationId(activeAgencyId, conversation.id);
|
|
6290
|
+
}
|
|
6234
6291
|
// Auto-hide conversation list when a conversation is selected
|
|
6235
6292
|
setIsConversationListOpen(false);
|
|
6236
6293
|
if (conversation.id) {
|
|
@@ -6245,7 +6302,51 @@ const ChatWidget = react.forwardRef(function ChatWidget({ config, onMessageSent,
|
|
|
6245
6302
|
finally {
|
|
6246
6303
|
setIsLoading(false);
|
|
6247
6304
|
}
|
|
6248
|
-
}, [setCurrentConversation, loadMessages, clearMessages, onError]);
|
|
6305
|
+
}, [activeAgencyId, setCurrentConversation, loadMessages, clearMessages, onError, t]);
|
|
6306
|
+
react.useEffect(() => {
|
|
6307
|
+
if (!hasLoadedConversations || !activeAgencyId || currentConversation) {
|
|
6308
|
+
return;
|
|
6309
|
+
}
|
|
6310
|
+
const storedConversationId = readStoredConversationId(activeAgencyId);
|
|
6311
|
+
if (!storedConversationId || restoredConversationIdRef.current === storedConversationId) {
|
|
6312
|
+
return;
|
|
6313
|
+
}
|
|
6314
|
+
restoredConversationIdRef.current = storedConversationId;
|
|
6315
|
+
let isCancelled = false;
|
|
6316
|
+
const restoreConversation = async () => {
|
|
6317
|
+
let storedConversation = conversations.find((conversation) => conversation.id === storedConversationId);
|
|
6318
|
+
if (!storedConversation) {
|
|
6319
|
+
try {
|
|
6320
|
+
storedConversation = await getConversationService().getConversation(storedConversationId);
|
|
6321
|
+
}
|
|
6322
|
+
catch {
|
|
6323
|
+
storedConversation = undefined;
|
|
6324
|
+
}
|
|
6325
|
+
}
|
|
6326
|
+
if (isCancelled) {
|
|
6327
|
+
return;
|
|
6328
|
+
}
|
|
6329
|
+
if (!storedConversation) {
|
|
6330
|
+
writeStoredConversationId(activeAgencyId, null);
|
|
6331
|
+
return;
|
|
6332
|
+
}
|
|
6333
|
+
if (!conversations.some((conversation) => conversation.id === storedConversation?.id)) {
|
|
6334
|
+
addConversation(storedConversation);
|
|
6335
|
+
}
|
|
6336
|
+
handleSelectConversation(storedConversation);
|
|
6337
|
+
};
|
|
6338
|
+
restoreConversation();
|
|
6339
|
+
return () => {
|
|
6340
|
+
isCancelled = true;
|
|
6341
|
+
};
|
|
6342
|
+
}, [
|
|
6343
|
+
addConversation,
|
|
6344
|
+
activeAgencyId,
|
|
6345
|
+
conversations,
|
|
6346
|
+
currentConversation,
|
|
6347
|
+
handleSelectConversation,
|
|
6348
|
+
hasLoadedConversations
|
|
6349
|
+
]);
|
|
6249
6350
|
const handleDeleteConversation = react.useCallback((conversationId) => {
|
|
6250
6351
|
setConversationToDelete(conversationId);
|
|
6251
6352
|
setIsDeleteDialogOpen(true);
|
|
@@ -6258,6 +6359,9 @@ const ChatWidget = react.forwardRef(function ChatWidget({ config, onMessageSent,
|
|
|
6258
6359
|
const conversationService = getConversationService();
|
|
6259
6360
|
await conversationService.deleteConversation(conversationToDelete);
|
|
6260
6361
|
removeConversation(conversationToDelete);
|
|
6362
|
+
if (readStoredConversationId(activeAgencyId) === conversationToDelete) {
|
|
6363
|
+
writeStoredConversationId(activeAgencyId, null);
|
|
6364
|
+
}
|
|
6261
6365
|
if (currentConversation?.id === conversationToDelete) {
|
|
6262
6366
|
setCurrentConversation(null);
|
|
6263
6367
|
clearMessages();
|
|
@@ -6279,7 +6383,7 @@ const ChatWidget = react.forwardRef(function ChatWidget({ config, onMessageSent,
|
|
|
6279
6383
|
finally {
|
|
6280
6384
|
setIsLoading(false);
|
|
6281
6385
|
}
|
|
6282
|
-
}, [conversationToDelete, removeConversation, currentConversation, setCurrentConversation, clearMessages, setStreamMessages, onConversationDeleted, onError, t]);
|
|
6386
|
+
}, [activeAgencyId, conversationToDelete, removeConversation, currentConversation, setCurrentConversation, clearMessages, setStreamMessages, onConversationDeleted, onError, t]);
|
|
6283
6387
|
const cancelDeleteConversation = react.useCallback(() => {
|
|
6284
6388
|
setIsDeleteDialogOpen(false);
|
|
6285
6389
|
setConversationToDelete(null);
|
|
@@ -6287,21 +6391,7 @@ const ChatWidget = react.forwardRef(function ChatWidget({ config, onMessageSent,
|
|
|
6287
6391
|
const handleSendMessage = react.useCallback(async (content, image, audio, messageId) => {
|
|
6288
6392
|
if (!mergedConfig)
|
|
6289
6393
|
return;
|
|
6290
|
-
// Debug logging for conversation state
|
|
6291
|
-
console.log('🔍 ChatWidget.handleSendMessage - Starting message send:', {
|
|
6292
|
-
currentConversation: currentConversation,
|
|
6293
|
-
conversationId: currentConversation?.id,
|
|
6294
|
-
content: content?.substring(0, 100) + (content?.length > 100 ? '...' : ''),
|
|
6295
|
-
hasImage: !!image,
|
|
6296
|
-
hasAudio: !!audio,
|
|
6297
|
-
agencyId: mergedConfig.agencyId
|
|
6298
|
-
});
|
|
6299
6394
|
if (!currentConversation || (!content.trim() && !audio)) {
|
|
6300
|
-
console.warn('⚠️ ChatWidget.handleSendMessage - Early return:', {
|
|
6301
|
-
hasCurrentConversation: !!currentConversation,
|
|
6302
|
-
hasContent: !!content?.trim(),
|
|
6303
|
-
hasAudio: !!audio
|
|
6304
|
-
});
|
|
6305
6395
|
return;
|
|
6306
6396
|
}
|
|
6307
6397
|
try {
|
|
@@ -6309,18 +6399,11 @@ const ChatWidget = react.forwardRef(function ChatWidget({ config, onMessageSent,
|
|
|
6309
6399
|
let conversationId = currentConversation.id;
|
|
6310
6400
|
// If this is a new conversation (null ID), create it on the server first
|
|
6311
6401
|
if (!conversationId) {
|
|
6312
|
-
console.log('🔍 ChatWidget.handleSendMessage - Creating server conversation for new conversation:', {
|
|
6313
|
-
agencyId: mergedConfig.agencyId
|
|
6314
|
-
});
|
|
6315
6402
|
const conversationService = getConversationService();
|
|
6316
6403
|
conversationId = await conversationService.createConversation({
|
|
6317
6404
|
title: t('chat.conversations.newConversation'),
|
|
6318
6405
|
agency_id: mergedConfig.agencyId,
|
|
6319
6406
|
});
|
|
6320
|
-
console.log('🔍 ChatWidget.handleSendMessage - Server conversation created:', {
|
|
6321
|
-
conversationId: conversationId,
|
|
6322
|
-
conversationIdType: typeof conversationId
|
|
6323
|
-
});
|
|
6324
6407
|
// Update the conversation with the real server ID
|
|
6325
6408
|
const updatedConversation = {
|
|
6326
6409
|
...currentConversation,
|
|
@@ -6329,10 +6412,7 @@ const ChatWidget = react.forwardRef(function ChatWidget({ config, onMessageSent,
|
|
|
6329
6412
|
// Update the conversation in the list and set as current
|
|
6330
6413
|
updateConversation(updatedConversation.id, updatedConversation);
|
|
6331
6414
|
setCurrentConversation(updatedConversation);
|
|
6332
|
-
|
|
6333
|
-
conversationId: conversationId,
|
|
6334
|
-
updatedConversation: updatedConversation
|
|
6335
|
-
});
|
|
6415
|
+
writeStoredConversationId(activeAgencyId, conversationId);
|
|
6336
6416
|
}
|
|
6337
6417
|
// Clear stream messages for new conversation
|
|
6338
6418
|
setStreamMessages([]);
|
|
@@ -6386,7 +6466,6 @@ const ChatWidget = react.forwardRef(function ChatWidget({ config, onMessageSent,
|
|
|
6386
6466
|
if (userMessage) {
|
|
6387
6467
|
onMessageSent?.(userMessage);
|
|
6388
6468
|
}
|
|
6389
|
-
// Debug logging before pipeline execution
|
|
6390
6469
|
const pipelineRequest = {
|
|
6391
6470
|
conversation_id: conversationId,
|
|
6392
6471
|
agency_id: mergedConfig.agencyId,
|
|
@@ -6395,14 +6474,6 @@ const ChatWidget = react.forwardRef(function ChatWidget({ config, onMessageSent,
|
|
|
6395
6474
|
audio,
|
|
6396
6475
|
message_id: messageId
|
|
6397
6476
|
};
|
|
6398
|
-
console.log('🔍 ChatWidget.handleSendMessage - About to call executePipeline:', {
|
|
6399
|
-
conversationId: conversationId,
|
|
6400
|
-
conversationIdType: typeof conversationId,
|
|
6401
|
-
conversationIdLength: conversationId?.length,
|
|
6402
|
-
isNewConversation: !conversationId,
|
|
6403
|
-
pipelineRequest: pipelineRequest,
|
|
6404
|
-
currentConversation: currentConversation
|
|
6405
|
-
});
|
|
6406
6477
|
// Execute pipeline - this calls /pipeline/${agency_id}/exec
|
|
6407
6478
|
const pipelineService = getPipelineService();
|
|
6408
6479
|
const response = await pipelineService.executePipeline(pipelineRequest);
|
|
@@ -6454,6 +6525,7 @@ const ChatWidget = react.forwardRef(function ChatWidget({ config, onMessageSent,
|
|
|
6454
6525
|
}
|
|
6455
6526
|
}, [
|
|
6456
6527
|
currentConversation,
|
|
6528
|
+
activeAgencyId,
|
|
6457
6529
|
mergedConfig,
|
|
6458
6530
|
messages,
|
|
6459
6531
|
addMessage,
|
|
@@ -6613,10 +6685,7 @@ const ChatWidget = react.forwardRef(function ChatWidget({ config, onMessageSent,
|
|
|
6613
6685
|
if (error) {
|
|
6614
6686
|
return (jsxRuntime.jsxs("div", { className: "fusioni-chat-error", children: [jsxRuntime.jsxs("p", { children: [t('common.error'), ": ", error] }), jsxRuntime.jsx("button", { onClick: () => setError(null), children: t('chat.errors.retry') })] }));
|
|
6615
6687
|
}
|
|
6616
|
-
|
|
6617
|
-
console.log('Primary color being applied:', mergedConfig.primaryColor || '#6366f1');
|
|
6618
|
-
console.log('Button variant being applied:', mergedConfig.buttonVariant || 'glass');
|
|
6619
|
-
return (jsxRuntime.jsxs("div", { className: `fusioni-chat-widget ${theme}`, style: { '--primary-color': mergedConfig.primaryColor || '#6366f1' }, children: [jsxRuntime.jsx(FloatingButton, { isOpen: isOpen, onClick: handleToggleChat, position: mergedConfig.position || 'bottom-right', primaryColor: mergedConfig.primaryColor, buttonRef: floatingButtonRef, variant: mergedConfig.buttonVariant || 'glass', shouldDisplay: !hasConfigError && (!isMobileLayout || !isOpen) }), isOpen && (jsxRuntime.jsx(ChatPanel, { isOpen: isOpen, onClose: () => setIsOpen(false), position: mergedConfig.position || 'bottom-right', isFullscreen: isFullscreen, floatingButtonRef: floatingButtonRef, children: jsxRuntime.jsxs("div", { className: "fusioni-chat-container", children: [mergedConfig.showConversationList !== false && (jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [jsxRuntime.jsx("div", { className: `fusioni-conversation-backdrop ${isConversationListOpen ? 'open' : ''}`, onClick: () => setIsConversationListOpen(false) }), jsxRuntime.jsx(ConversationList, { conversations: conversations, selectedConversationId: currentConversation?.id || undefined, onSelectConversation: handleSelectConversation, onDeleteConversation: handleDeleteConversation, onCreateConversation: handleCreateConversation, isOpen: isConversationListOpen, currentLanguage: currentLanguage })] })), jsxRuntime.jsxs("div", { className: "fusioni-chat-main", children: [jsxRuntime.jsxs("div", { className: "fusioni-chat-main-header", children: [mergedConfig.showConversationList !== false ? (jsxRuntime.jsxs("button", { type: "button", onClick: handleToggleConversationList, className: `fusioni-conversation-toggle ${isConversationListOpen ? 'open' : ''}`, children: [jsxRuntime.jsx("svg", { className: "fusioni-conversation-toggle-icon", viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "2", children: jsxRuntime.jsx("path", { d: "M3 12h18M3 6h18M3 18h18" }) }), t('chat.conversations.title')] })) : (jsxRuntime.jsx("span", { className: "fusioni-chat-main-header-title", children: t('chat.title') })), jsxRuntime.jsxs("div", { className: "fusioni-header-actions", children: [isMobileLayout && (jsxRuntime.jsx("button", { type: "button", onClick: () => setIsOpen(false), className: "fusioni-btn fusioni-btn-icon fusioni-chat-toolbar-close-mobile", title: t('common.close'), "aria-label": t('common.close'), children: jsxRuntime.jsx("svg", { width: "20", height: "20", viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "2", "aria-hidden": "true", children: jsxRuntime.jsx("path", { d: "M18 6L6 18M6 6L18 18", strokeLinecap: "round", strokeLinejoin: "round" }) }) })), mergedConfig.showThemeToggle !== false && (jsxRuntime.jsx("button", { type: "button", onClick: toggleTheme, className: "fusioni-btn fusioni-btn-icon", title: theme === 'dark' ? t('chat.theme.light') : t('chat.theme.dark'), children: theme === 'dark' ? (jsxRuntime.jsxs("svg", { width: "20", height: "20", viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "2", children: [jsxRuntime.jsx("circle", { cx: "12", cy: "12", r: "5" }), jsxRuntime.jsx("line", { x1: "12", y1: "1", x2: "12", y2: "3" }), jsxRuntime.jsx("line", { x1: "12", y1: "21", x2: "12", y2: "23" }), jsxRuntime.jsx("line", { x1: "4.22", y1: "4.22", x2: "5.64", y2: "5.64" }), jsxRuntime.jsx("line", { x1: "18.36", y1: "18.36", x2: "19.78", y2: "19.78" }), jsxRuntime.jsx("line", { x1: "1", y1: "12", x2: "3", y2: "12" }), jsxRuntime.jsx("line", { x1: "21", y1: "12", x2: "23", y2: "12" }), jsxRuntime.jsx("line", { x1: "4.22", y1: "19.78", x2: "5.64", y2: "18.36" }), jsxRuntime.jsx("line", { x1: "18.36", y1: "5.64", x2: "19.78", y2: "4.22" })] })) : (jsxRuntime.jsx("svg", { width: "20", height: "20", viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "2", children: jsxRuntime.jsx("path", { d: "M21 12.79A9 9 0 1 1 11.21 3 7 7 0 0 0 21 12.79z" }) })) })), mergedConfig.showFullscreenToggle !== false && (jsxRuntime.jsx("button", { type: "button", onClick: handleToggleFullscreen, className: "fusioni-btn fusioni-btn-icon", title: isFullscreen ? t('chat.fullscreen.exit') : t('chat.fullscreen.enter'), children: isFullscreen ? (jsxRuntime.jsx("svg", { width: "20", height: "20", viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "2", children: jsxRuntime.jsx("path", { d: "M8 3V5M8 3H5M8 3L3 8M16 3V5M16 3H19M16 3L21 8M8 21V19M8 21H5M8 21L3 16M16 21V19M16 21H19M16 21L21 16" }) })) : (jsxRuntime.jsx("svg", { width: "20", height: "20", viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "2", children: jsxRuntime.jsx("path", { d: "M8 3H5C4.46957 3 3.96086 3.21071 3.58579 3.58579C3.21071 3.96086 3 4.46957 3 5V8M21 8V5C21 4.46957 20.7893 3.96086 20.4142 3.58579C20.0391 3.21071 19.5304 3 19 3H16M16 21H19C19.5304 21 20.0391 20.7893 20.4142 20.4142C20.7893 20.0391 21 19.5304 21 19V16M3 16V19C3 19.5304 3.21071 20.0391 3.58579 20.4142C3.96086 20.7893 4.46957 21 5 21H8" }) })) })), mergedConfig.showLanguageSwitcher !== false && (jsxRuntime.jsx(LanguageSwitcher, { currentLanguage: currentLanguage, onLanguageChange: handleLanguageChange }))] })] }), currentConversation ? (jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [jsxRuntime.jsx(MessageList, { messages: messages, streamMessages: streamMessages, showThoughts: false, onDeleteMessage: handleDeleteMessage, onEditMessage: handleEditMessage, onConfirmation: handleConfirmation, enableButtons: !isLoading, apiBaseUrl: mergedConfig.apiBaseUrl, apiKey: mergedConfig.accessToken, agencyId: mergedConfig.agencyId, currentLanguage: currentLanguage, theme: theme }), jsxRuntime.jsx(ChatInput, { onSendMessage: handleSendMessage, onFileUpload: handleFileUpload, disabled: isLoading, placeholder: t('chat.input.placeholder'), enableAudioRecording: mergedConfig.enableAudioRecording !== false, enableFileUpload: mergedConfig.enableFileUpload !== false, maxFileSize: mergedConfig.maxFileSize || 10, allowedFileTypes: mergedConfig.allowedFileTypes || ['image/*'], currentLanguage: currentLanguage })] })) : (jsxRuntime.jsx("div", { className: "fusioni-chat-welcome", children: jsxRuntime.jsxs("div", { className: "fusioni-chat-welcome-content", children: [jsxRuntime.jsx("h3", { children: t('chat.welcome.title') }), jsxRuntime.jsx("p", { children: t('chat.welcome.description') }), jsxRuntime.jsx("button", { onClick: handleCreateConversation, disabled: isLoading, className: "fusioni-btn fusioni-btn-primary", children: isLoading ? t('chat.welcome.creating') : t('chat.welcome.startButton') })] }) }))] })] }) })), jsxRuntime.jsx(ConfirmationDialog, { isOpen: isDeleteDialogOpen, title: t('chat.conversations.deleteConfirm.title'), message: t('chat.conversations.deleteConfirm.message'), confirmText: t('chat.conversations.deleteConfirm.confirm'), cancelText: t('chat.conversations.deleteConfirm.cancel'), onConfirm: confirmDeleteConversation, onCancel: cancelDeleteConversation, currentLanguage: currentLanguage, variant: "danger" }), jsxRuntime.jsx(ConfirmationDialog, { isOpen: isDeleteMessageDialogOpen, title: t('chat.messages.deleteConfirm.title'), message: t('chat.messages.deleteConfirm.message'), confirmText: t('chat.messages.deleteConfirm.confirm'), cancelText: t('chat.messages.deleteConfirm.cancel'), onConfirm: confirmDeleteMessage, onCancel: cancelDeleteMessage, currentLanguage: currentLanguage, variant: "danger" })] }));
|
|
6688
|
+
return (jsxRuntime.jsxs("div", { className: `fusioni-chat-widget ${theme}`, style: { '--primary-color': mergedConfig.primaryColor || '#6366f1' }, children: [jsxRuntime.jsx(FloatingButton, { isOpen: isOpen, onClick: handleToggleChat, position: mergedConfig.position || 'bottom-right', primaryColor: mergedConfig.primaryColor, buttonRef: floatingButtonRef, variant: mergedConfig.buttonVariant || 'glass', shouldDisplay: !hasConfigError && (!isMobileLayout || !isOpen) }), isOpen && (jsxRuntime.jsx(ChatPanel, { isOpen: isOpen, onClose: () => setIsOpen(false), position: mergedConfig.position || 'bottom-right', isFullscreen: isFullscreen, floatingButtonRef: floatingButtonRef, children: jsxRuntime.jsxs("div", { className: "fusioni-chat-container", children: [mergedConfig.showConversationList !== false && (jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [jsxRuntime.jsx("div", { className: `fusioni-conversation-backdrop ${isConversationListOpen ? 'open' : ''}`, onClick: () => setIsConversationListOpen(false) }), jsxRuntime.jsx(ConversationList, { conversations: conversations, selectedConversationId: currentConversation?.id || undefined, onSelectConversation: handleSelectConversation, onDeleteConversation: handleDeleteConversation, onCreateConversation: handleCreateConversation, isOpen: isConversationListOpen, currentLanguage: currentLanguage })] })), jsxRuntime.jsxs("div", { className: "fusioni-chat-main", children: [jsxRuntime.jsxs("div", { className: "fusioni-chat-main-header", children: [mergedConfig.showConversationList !== false ? (jsxRuntime.jsxs("button", { type: "button", onClick: handleToggleConversationList, className: `fusioni-conversation-toggle ${isConversationListOpen ? 'open' : ''}`, children: [jsxRuntime.jsx("svg", { className: "fusioni-conversation-toggle-icon", viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "2", children: jsxRuntime.jsx("path", { d: "M3 12h18M3 6h18M3 18h18" }) }), t('chat.conversations.title')] })) : (jsxRuntime.jsx("span", { className: "fusioni-chat-main-header-title", children: t('chat.title') })), jsxRuntime.jsxs("div", { className: "fusioni-header-actions", children: [mergedConfig.showThemeToggle !== false && (jsxRuntime.jsx("button", { type: "button", onClick: toggleTheme, className: "fusioni-btn fusioni-btn-icon", title: theme === 'dark' ? t('chat.theme.light') : t('chat.theme.dark'), children: theme === 'dark' ? (jsxRuntime.jsxs("svg", { width: "20", height: "20", viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "2", children: [jsxRuntime.jsx("circle", { cx: "12", cy: "12", r: "5" }), jsxRuntime.jsx("line", { x1: "12", y1: "1", x2: "12", y2: "3" }), jsxRuntime.jsx("line", { x1: "12", y1: "21", x2: "12", y2: "23" }), jsxRuntime.jsx("line", { x1: "4.22", y1: "4.22", x2: "5.64", y2: "5.64" }), jsxRuntime.jsx("line", { x1: "18.36", y1: "18.36", x2: "19.78", y2: "19.78" }), jsxRuntime.jsx("line", { x1: "1", y1: "12", x2: "3", y2: "12" }), jsxRuntime.jsx("line", { x1: "21", y1: "12", x2: "23", y2: "12" }), jsxRuntime.jsx("line", { x1: "4.22", y1: "19.78", x2: "5.64", y2: "18.36" }), jsxRuntime.jsx("line", { x1: "18.36", y1: "5.64", x2: "19.78", y2: "4.22" })] })) : (jsxRuntime.jsx("svg", { width: "20", height: "20", viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "2", children: jsxRuntime.jsx("path", { d: "M21 12.79A9 9 0 1 1 11.21 3 7 7 0 0 0 21 12.79z" }) })) })), mergedConfig.showFullscreenToggle !== false && (jsxRuntime.jsx("button", { type: "button", onClick: handleToggleFullscreen, className: "fusioni-btn fusioni-btn-icon", title: isFullscreen ? t('chat.fullscreen.exit') : t('chat.fullscreen.enter'), children: isFullscreen ? (jsxRuntime.jsx("svg", { width: "20", height: "20", viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "2", children: jsxRuntime.jsx("path", { d: "M8 3V5M8 3H5M8 3L3 8M16 3V5M16 3H19M16 3L21 8M8 21V19M8 21H5M8 21L3 16M16 21V19M16 21H19M16 21L21 16" }) })) : (jsxRuntime.jsx("svg", { width: "20", height: "20", viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "2", children: jsxRuntime.jsx("path", { d: "M8 3H5C4.46957 3 3.96086 3.21071 3.58579 3.58579C3.21071 3.96086 3 4.46957 3 5V8M21 8V5C21 4.46957 20.7893 3.96086 20.4142 3.58579C20.0391 3.21071 19.5304 3 19 3H16M16 21H19C19.5304 21 20.0391 20.7893 20.4142 20.4142C20.7893 20.0391 21 19.5304 21 19V16M3 16V19C3 19.5304 3.21071 20.0391 3.58579 20.4142C3.96086 20.7893 4.46957 21 5 21H8" }) })) })), mergedConfig.showLanguageSwitcher !== false && (jsxRuntime.jsx(LanguageSwitcher, { currentLanguage: currentLanguage, onLanguageChange: handleLanguageChange })), jsxRuntime.jsx("button", { type: "button", onClick: () => setIsOpen(false), className: "fusioni-btn fusioni-btn-icon fusioni-chat-toolbar-close-mobile", title: t('common.close'), "aria-label": t('common.close'), children: jsxRuntime.jsx("svg", { width: "20", height: "20", viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "2", "aria-hidden": "true", children: jsxRuntime.jsx("path", { d: "M18 6L6 18M6 6L18 18", strokeLinecap: "round", strokeLinejoin: "round" }) }) })] })] }), currentConversation ? (jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [jsxRuntime.jsx(MessageList, { messages: messages, streamMessages: streamMessages, showThoughts: false, onDeleteMessage: handleDeleteMessage, onEditMessage: handleEditMessage, onConfirmation: handleConfirmation, enableButtons: !isLoading, apiBaseUrl: mergedConfig.apiBaseUrl, apiKey: mergedConfig.accessToken, agencyId: mergedConfig.agencyId, currentLanguage: currentLanguage, theme: theme }), jsxRuntime.jsx(ChatInput, { onSendMessage: handleSendMessage, onFileUpload: handleFileUpload, disabled: isLoading, placeholder: t('chat.input.placeholder'), enableAudioRecording: mergedConfig.enableAudioRecording !== false, enableFileUpload: mergedConfig.enableFileUpload !== false, maxFileSize: mergedConfig.maxFileSize || 10, allowedFileTypes: mergedConfig.allowedFileTypes || ['image/*'], currentLanguage: currentLanguage })] })) : (jsxRuntime.jsx("div", { className: "fusioni-chat-welcome", children: jsxRuntime.jsxs("div", { className: "fusioni-chat-welcome-content", children: [jsxRuntime.jsx("h3", { children: t('chat.welcome.title') }), jsxRuntime.jsx("p", { children: t('chat.welcome.description') }), jsxRuntime.jsx("button", { onClick: handleCreateConversation, disabled: isLoading, className: "fusioni-btn fusioni-btn-primary", children: isLoading ? t('chat.welcome.creating') : t('chat.welcome.startButton') })] }) }))] })] }) })), jsxRuntime.jsx(ConfirmationDialog, { isOpen: isDeleteDialogOpen, title: t('chat.conversations.deleteConfirm.title'), message: t('chat.conversations.deleteConfirm.message'), confirmText: t('chat.conversations.deleteConfirm.confirm'), cancelText: t('chat.conversations.deleteConfirm.cancel'), onConfirm: confirmDeleteConversation, onCancel: cancelDeleteConversation, currentLanguage: currentLanguage, variant: "danger" }), jsxRuntime.jsx(ConfirmationDialog, { isOpen: isDeleteMessageDialogOpen, title: t('chat.messages.deleteConfirm.title'), message: t('chat.messages.deleteConfirm.message'), confirmText: t('chat.messages.deleteConfirm.confirm'), cancelText: t('chat.messages.deleteConfirm.cancel'), onConfirm: confirmDeleteMessage, onCancel: cancelDeleteMessage, currentLanguage: currentLanguage, variant: "danger" })] }));
|
|
6620
6689
|
});
|
|
6621
6690
|
ChatWidget.displayName = 'ChatWidget';
|
|
6622
6691
|
|