@fusioni/client-sdk 1.1.5 → 1.1.8

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/index.esm.js CHANGED
@@ -1,7 +1,232 @@
1
1
  import { jsxs, jsx, Fragment } from 'react/jsx-runtime';
2
- import { useState, useEffect, useCallback, useMemo, useRef } from 'react';
2
+ import { useState, useEffect, useCallback, useMemo, useRef, forwardRef, useImperativeHandle } from 'react';
3
3
  import { createPortal } from 'react-dom';
4
4
 
5
+ const en = {
6
+ // Chat Interface
7
+ chat: {
8
+ title: 'Fusioni AI',
9
+ subtitle: 'AI Assistant',
10
+ welcome: {
11
+ title: 'Welcome to Fusioni',
12
+ description: 'Start a new conversation to begin chatting with AI',
13
+ startButton: 'Start New Conversation',
14
+ creating: 'Creating...'
15
+ },
16
+ input: {
17
+ placeholder: 'Type your message...',
18
+ send: 'Send',
19
+ upload: 'Upload',
20
+ record: 'Record'
21
+ },
22
+ conversations: {
23
+ title: 'Conversations',
24
+ search: 'Search conversations...',
25
+ newConversation: 'New Conversation',
26
+ noConversations: 'No conversations yet',
27
+ delete: 'Delete conversation',
28
+ newIndicator: 'New conversation - will be saved when you send a message',
29
+ deleteConfirm: {
30
+ title: 'Delete Conversation',
31
+ message: 'Are you sure you want to delete this conversation? This action cannot be undone.',
32
+ confirm: 'Delete',
33
+ cancel: 'Cancel'
34
+ }
35
+ },
36
+ attachedImages: 'Images',
37
+ attachedVideos: 'Videos',
38
+ messages: {
39
+ loading: 'Working on it...',
40
+ error: 'Oops! Something went wrong. Please try again later.',
41
+ delete: 'Delete message',
42
+ deleteConfirm: {
43
+ title: 'Delete Message',
44
+ message: 'Are you sure you want to delete this message? This action cannot be undone.',
45
+ confirm: 'Delete',
46
+ cancel: 'Cancel'
47
+ }
48
+ },
49
+ connection: {
50
+ connected: 'Real-time updates connected',
51
+ disconnected: 'Real-time updates disconnected'
52
+ },
53
+ fullscreen: {
54
+ enter: 'Enter fullscreen',
55
+ exit: 'Exit fullscreen'
56
+ },
57
+ theme: {
58
+ light: 'Switch to light theme',
59
+ dark: 'Switch to dark theme'
60
+ },
61
+ errors: {
62
+ failedToCreateConversation: 'Failed to create conversation',
63
+ failedToLoadConversation: 'Failed to load conversation',
64
+ failedToDeleteConversation: 'Failed to delete conversation',
65
+ failedToSendMessage: 'Failed to send message',
66
+ failedToDeleteMessage: 'Failed to delete message',
67
+ failedToUploadFile: 'Failed to upload file',
68
+ failedToInitialize: 'Failed to initialize chat service',
69
+ retry: 'Retry'
70
+ }
71
+ },
72
+ // Language Switcher
73
+ language: {
74
+ english: 'English',
75
+ greek: 'Ελληνικά',
76
+ switchLanguage: 'Switch Language'
77
+ },
78
+ // Common
79
+ common: {
80
+ close: 'Close',
81
+ open: 'Open',
82
+ cancel: 'Cancel',
83
+ confirm: 'Confirm',
84
+ save: 'Save',
85
+ delete: 'Delete',
86
+ edit: 'Edit',
87
+ search: 'Search',
88
+ clear: 'Clear',
89
+ loading: 'Loading...',
90
+ error: 'Error',
91
+ success: 'Success',
92
+ warning: 'Warning',
93
+ info: 'Info',
94
+ yes: 'Yes',
95
+ no: 'No'
96
+ }
97
+ };
98
+
99
+ const el = {
100
+ // Chat Interface
101
+ chat: {
102
+ title: 'Fusioni AI',
103
+ subtitle: 'AI Βοηθός',
104
+ welcome: {
105
+ title: 'Καλώς ήρθατε στο Fusioni AI',
106
+ description: 'Ξεκινήστε μια νέα συνομιλία για να αρχίσετε να συνομιλείτε με AI',
107
+ startButton: 'Ξεκινήστε Νέα Συνομιλία',
108
+ creating: 'Δημιουργία...'
109
+ },
110
+ input: {
111
+ placeholder: 'Πληκτρολογήστε το μήνυμά σας...',
112
+ send: 'Αποστολή',
113
+ upload: 'Ανέβασμα',
114
+ record: 'Εγγραφή'
115
+ },
116
+ conversations: {
117
+ title: 'Συνομιλίες',
118
+ search: 'Αναζήτηση συνομιλιών...',
119
+ newConversation: 'Νέα Συνομιλία',
120
+ noConversations: 'Δεν υπάρχουν συνομιλίες ακόμα',
121
+ delete: 'Διαγραφή συνομιλίας',
122
+ newIndicator: 'Νέα συνομιλία - θα αποθηκευτεί όταν στείλετε μήνυμα',
123
+ deleteConfirm: {
124
+ title: 'Διαγραφή Συνομιλίας',
125
+ message: 'Είστε σίγουροι ότι θέλετε να διαγράψετε αυτή τη συνομιλία; Αυτή η ενέργεια δεν μπορεί να αναιρεθεί.',
126
+ confirm: 'Διαγραφή',
127
+ cancel: 'Ακύρωση'
128
+ }
129
+ },
130
+ attachedImages: 'Εικόνες',
131
+ attachedVideos: 'Βίντεο',
132
+ messages: {
133
+ loading: 'Εργάζομαι...',
134
+ error: 'Ουπς! Κάτι πήγε στραβά. Παρακαλώ δοκιμάστε ξανά αργότερα.',
135
+ delete: 'Διαγραφή μηνύματος',
136
+ deleteConfirm: {
137
+ title: 'Διαγραφή Μηνύματος',
138
+ message: 'Είστε σίγουροι ότι θέλετε να διαγράψετε αυτό το μήνυμα; Αυτή η ενέργεια δεν μπορεί να αναιρεθεί.',
139
+ confirm: 'Διαγραφή',
140
+ cancel: 'Ακύρωση'
141
+ }
142
+ },
143
+ connection: {
144
+ connected: 'Συνδεδεμένο για ενημερώσεις σε πραγματικό χρόνο',
145
+ disconnected: 'Αποσυνδεδεμένο από ενημερώσεις σε πραγματικό χρόνο'
146
+ },
147
+ fullscreen: {
148
+ enter: 'Πλήρης οθόνη',
149
+ exit: 'Έξοδος από πλήρη οθόνη'
150
+ },
151
+ theme: {
152
+ light: 'Εναλλαγή σε φωτεινό θέμα',
153
+ dark: 'Εναλλαγή σε σκοτεινό θέμα'
154
+ },
155
+ errors: {
156
+ failedToCreateConversation: 'Αποτυχία δημιουργίας συνομιλίας',
157
+ failedToLoadConversation: 'Αποτυχία φόρτωσης συνομιλίας',
158
+ failedToDeleteConversation: 'Αποτυχία διαγραφής συνομιλίας',
159
+ failedToSendMessage: 'Αποτυχία αποστολής μηνύματος',
160
+ failedToDeleteMessage: 'Αποτυχία διαγραφής μηνύματος',
161
+ failedToUploadFile: 'Αποτυχία ανεβάσματος αρχείου',
162
+ failedToInitialize: 'Αποτυχία αρχικοποίησης υπηρεσίας συνομιλίας',
163
+ retry: 'Επανάληψη'
164
+ }
165
+ },
166
+ // Language Switcher
167
+ language: {
168
+ english: 'English',
169
+ greek: 'Ελληνικά',
170
+ switchLanguage: 'Αλλαγή Γλώσσας'
171
+ },
172
+ // Common
173
+ common: {
174
+ close: 'Κλείσιμο',
175
+ open: 'Άνοιγμα',
176
+ cancel: 'Ακύρωση',
177
+ confirm: 'Επιβεβαίωση',
178
+ save: 'Αποθήκευση',
179
+ delete: 'Διαγραφή',
180
+ edit: 'Επεξεργασία',
181
+ search: 'Αναζήτηση',
182
+ clear: 'Εκκαθάριση',
183
+ loading: 'Φόρτωση...',
184
+ error: 'Σφάλμα',
185
+ success: 'Επιτυχία',
186
+ warning: 'Προειδοποίηση',
187
+ info: 'Πληροφορία',
188
+ yes: 'Ναι',
189
+ no: 'Όχι'
190
+ }
191
+ };
192
+
193
+ const translations = {
194
+ en,
195
+ el
196
+ };
197
+ const getTranslation = (language, key) => {
198
+ const keys = key.split('.');
199
+ let value = translations[language];
200
+ for (const k of keys) {
201
+ if (value && typeof value === 'object' && k in value) {
202
+ value = value[k];
203
+ }
204
+ else {
205
+ // Fallback to English if key not found
206
+ value = translations.en;
207
+ for (const fallbackKey of keys) {
208
+ if (value && typeof value === 'object' && fallbackKey in value) {
209
+ value = value[fallbackKey];
210
+ }
211
+ else {
212
+ return key; // Return the key if not found in fallback
213
+ }
214
+ }
215
+ break;
216
+ }
217
+ }
218
+ return typeof value === 'string' ? value : key;
219
+ };
220
+ const getAvailableLanguages = () => {
221
+ return [
222
+ { code: 'en', name: 'English' },
223
+ { code: 'el', name: 'Ελληνικά' }
224
+ ];
225
+ };
226
+ const isValidLanguage = (language) => {
227
+ return language === 'en' || language === 'el';
228
+ };
229
+
5
230
  function bind(fn, thisArg) {
6
231
  return function wrap() {
7
232
  return fn.apply(thisArg, arguments);
@@ -1359,12 +1584,12 @@ const hasStandardBrowserWebWorkerEnv = (() => {
1359
1584
  const origin = hasBrowserEnv && window.location.href || 'http://localhost';
1360
1585
 
1361
1586
  var utils = /*#__PURE__*/Object.freeze({
1362
- __proto__: null,
1363
- hasBrowserEnv: hasBrowserEnv,
1364
- hasStandardBrowserEnv: hasStandardBrowserEnv,
1365
- hasStandardBrowserWebWorkerEnv: hasStandardBrowserWebWorkerEnv,
1366
- navigator: _navigator,
1367
- origin: origin
1587
+ __proto__: null,
1588
+ hasBrowserEnv: hasBrowserEnv,
1589
+ hasStandardBrowserEnv: hasStandardBrowserEnv,
1590
+ hasStandardBrowserWebWorkerEnv: hasStandardBrowserWebWorkerEnv,
1591
+ navigator: _navigator,
1592
+ origin: origin
1368
1593
  });
1369
1594
 
1370
1595
  var platform = {
@@ -4264,19 +4489,28 @@ class SDKClientService {
4264
4489
  theme: serverConfig.theme !== null && serverConfig.theme !== undefined
4265
4490
  ? serverConfig.theme
4266
4491
  : userConfig.theme,
4492
+ showThemeToggle: serverConfig.show_theme_toggle !== undefined
4493
+ ? serverConfig.show_theme_toggle
4494
+ : userConfig.showThemeToggle,
4495
+ showFullscreenToggle: serverConfig.show_fullscreen_toggle !== undefined
4496
+ ? serverConfig.show_fullscreen_toggle
4497
+ : userConfig.showFullscreenToggle,
4498
+ showLanguageSwitcher: serverConfig.show_language_switcher !== undefined
4499
+ ? serverConfig.show_language_switcher
4500
+ : userConfig.showLanguageSwitcher,
4267
4501
  position: serverConfig.position !== null && serverConfig.position !== undefined
4268
4502
  ? serverConfig.position
4269
4503
  : userConfig.position,
4270
4504
  primaryColor: serverConfig.primary_color !== null && serverConfig.primary_color !== undefined
4271
4505
  ? serverConfig.primary_color
4272
4506
  : userConfig.primaryColor,
4273
- showConversationList: serverConfig.show_conversation_list !== undefined
4507
+ showConversationList: typeof serverConfig.show_conversation_list === 'boolean'
4274
4508
  ? serverConfig.show_conversation_list
4275
4509
  : userConfig.showConversationList,
4276
- enableAudioRecording: serverConfig.enable_audio_recording !== undefined
4510
+ enableAudioRecording: typeof serverConfig.enable_audio_recording === 'boolean'
4277
4511
  ? serverConfig.enable_audio_recording
4278
4512
  : userConfig.enableAudioRecording,
4279
- enableFileUpload: serverConfig.enable_file_upload !== undefined
4513
+ enableFileUpload: typeof serverConfig.enable_file_upload === 'boolean'
4280
4514
  ? serverConfig.enable_file_upload
4281
4515
  : userConfig.enableFileUpload,
4282
4516
  maxFileSize: serverConfig.max_file_size !== null && serverConfig.max_file_size !== undefined
@@ -4303,231 +4537,6 @@ const getSDKClientService = () => {
4303
4537
  return sdkClientServiceInstance;
4304
4538
  };
4305
4539
 
4306
- const en = {
4307
- // Chat Interface
4308
- chat: {
4309
- title: 'Fusioni AI',
4310
- subtitle: 'AI Assistant',
4311
- welcome: {
4312
- title: 'Welcome to Fusioni',
4313
- description: 'Start a new conversation to begin chatting with AI',
4314
- startButton: 'Start New Conversation',
4315
- creating: 'Creating...'
4316
- },
4317
- input: {
4318
- placeholder: 'Type your message...',
4319
- send: 'Send',
4320
- upload: 'Upload',
4321
- record: 'Record'
4322
- },
4323
- conversations: {
4324
- title: 'Conversations',
4325
- search: 'Search conversations...',
4326
- newConversation: 'New Conversation',
4327
- noConversations: 'No conversations yet',
4328
- delete: 'Delete conversation',
4329
- newIndicator: 'New conversation - will be saved when you send a message',
4330
- deleteConfirm: {
4331
- title: 'Delete Conversation',
4332
- message: 'Are you sure you want to delete this conversation? This action cannot be undone.',
4333
- confirm: 'Delete',
4334
- cancel: 'Cancel'
4335
- }
4336
- },
4337
- attachedImages: 'Images',
4338
- attachedVideos: 'Videos',
4339
- messages: {
4340
- loading: 'Working on it...',
4341
- error: 'Oops! Something went wrong. Please try again later.',
4342
- delete: 'Delete message',
4343
- deleteConfirm: {
4344
- title: 'Delete Message',
4345
- message: 'Are you sure you want to delete this message? This action cannot be undone.',
4346
- confirm: 'Delete',
4347
- cancel: 'Cancel'
4348
- }
4349
- },
4350
- connection: {
4351
- connected: 'Real-time updates connected',
4352
- disconnected: 'Real-time updates disconnected'
4353
- },
4354
- fullscreen: {
4355
- enter: 'Enter fullscreen',
4356
- exit: 'Exit fullscreen'
4357
- },
4358
- theme: {
4359
- light: 'Switch to light theme',
4360
- dark: 'Switch to dark theme'
4361
- },
4362
- errors: {
4363
- failedToCreateConversation: 'Failed to create conversation',
4364
- failedToLoadConversation: 'Failed to load conversation',
4365
- failedToDeleteConversation: 'Failed to delete conversation',
4366
- failedToSendMessage: 'Failed to send message',
4367
- failedToDeleteMessage: 'Failed to delete message',
4368
- failedToUploadFile: 'Failed to upload file',
4369
- failedToInitialize: 'Failed to initialize chat service',
4370
- retry: 'Retry'
4371
- }
4372
- },
4373
- // Language Switcher
4374
- language: {
4375
- english: 'English',
4376
- greek: 'Ελληνικά',
4377
- switchLanguage: 'Switch Language'
4378
- },
4379
- // Common
4380
- common: {
4381
- close: 'Close',
4382
- open: 'Open',
4383
- cancel: 'Cancel',
4384
- confirm: 'Confirm',
4385
- save: 'Save',
4386
- delete: 'Delete',
4387
- edit: 'Edit',
4388
- search: 'Search',
4389
- clear: 'Clear',
4390
- loading: 'Loading...',
4391
- error: 'Error',
4392
- success: 'Success',
4393
- warning: 'Warning',
4394
- info: 'Info',
4395
- yes: 'Yes',
4396
- no: 'No'
4397
- }
4398
- };
4399
-
4400
- const el = {
4401
- // Chat Interface
4402
- chat: {
4403
- title: 'Fusioni AI',
4404
- subtitle: 'AI Βοηθός',
4405
- welcome: {
4406
- title: 'Καλώς ήρθατε στο Fusioni AI',
4407
- description: 'Ξεκινήστε μια νέα συνομιλία για να αρχίσετε να συνομιλείτε με AI',
4408
- startButton: 'Ξεκινήστε Νέα Συνομιλία',
4409
- creating: 'Δημιουργία...'
4410
- },
4411
- input: {
4412
- placeholder: 'Πληκτρολογήστε το μήνυμά σας...',
4413
- send: 'Αποστολή',
4414
- upload: 'Ανέβασμα',
4415
- record: 'Εγγραφή'
4416
- },
4417
- conversations: {
4418
- title: 'Συνομιλίες',
4419
- search: 'Αναζήτηση συνομιλιών...',
4420
- newConversation: 'Νέα Συνομιλία',
4421
- noConversations: 'Δεν υπάρχουν συνομιλίες ακόμα',
4422
- delete: 'Διαγραφή συνομιλίας',
4423
- newIndicator: 'Νέα συνομιλία - θα αποθηκευτεί όταν στείλετε μήνυμα',
4424
- deleteConfirm: {
4425
- title: 'Διαγραφή Συνομιλίας',
4426
- message: 'Είστε σίγουροι ότι θέλετε να διαγράψετε αυτή τη συνομιλία; Αυτή η ενέργεια δεν μπορεί να αναιρεθεί.',
4427
- confirm: 'Διαγραφή',
4428
- cancel: 'Ακύρωση'
4429
- }
4430
- },
4431
- attachedImages: 'Εικόνες',
4432
- attachedVideos: 'Βίντεο',
4433
- messages: {
4434
- loading: 'Εργάζομαι...',
4435
- error: 'Ουπς! Κάτι πήγε στραβά. Παρακαλώ δοκιμάστε ξανά αργότερα.',
4436
- delete: 'Διαγραφή μηνύματος',
4437
- deleteConfirm: {
4438
- title: 'Διαγραφή Μηνύματος',
4439
- message: 'Είστε σίγουροι ότι θέλετε να διαγράψετε αυτό το μήνυμα; Αυτή η ενέργεια δεν μπορεί να αναιρεθεί.',
4440
- confirm: 'Διαγραφή',
4441
- cancel: 'Ακύρωση'
4442
- }
4443
- },
4444
- connection: {
4445
- connected: 'Συνδεδεμένο για ενημερώσεις σε πραγματικό χρόνο',
4446
- disconnected: 'Αποσυνδεδεμένο από ενημερώσεις σε πραγματικό χρόνο'
4447
- },
4448
- fullscreen: {
4449
- enter: 'Πλήρης οθόνη',
4450
- exit: 'Έξοδος από πλήρη οθόνη'
4451
- },
4452
- theme: {
4453
- light: 'Εναλλαγή σε φωτεινό θέμα',
4454
- dark: 'Εναλλαγή σε σκοτεινό θέμα'
4455
- },
4456
- errors: {
4457
- failedToCreateConversation: 'Αποτυχία δημιουργίας συνομιλίας',
4458
- failedToLoadConversation: 'Αποτυχία φόρτωσης συνομιλίας',
4459
- failedToDeleteConversation: 'Αποτυχία διαγραφής συνομιλίας',
4460
- failedToSendMessage: 'Αποτυχία αποστολής μηνύματος',
4461
- failedToDeleteMessage: 'Αποτυχία διαγραφής μηνύματος',
4462
- failedToUploadFile: 'Αποτυχία ανεβάσματος αρχείου',
4463
- failedToInitialize: 'Αποτυχία αρχικοποίησης υπηρεσίας συνομιλίας',
4464
- retry: 'Επανάληψη'
4465
- }
4466
- },
4467
- // Language Switcher
4468
- language: {
4469
- english: 'English',
4470
- greek: 'Ελληνικά',
4471
- switchLanguage: 'Αλλαγή Γλώσσας'
4472
- },
4473
- // Common
4474
- common: {
4475
- close: 'Κλείσιμο',
4476
- open: 'Άνοιγμα',
4477
- cancel: 'Ακύρωση',
4478
- confirm: 'Επιβεβαίωση',
4479
- save: 'Αποθήκευση',
4480
- delete: 'Διαγραφή',
4481
- edit: 'Επεξεργασία',
4482
- search: 'Αναζήτηση',
4483
- clear: 'Εκκαθάριση',
4484
- loading: 'Φόρτωση...',
4485
- error: 'Σφάλμα',
4486
- success: 'Επιτυχία',
4487
- warning: 'Προειδοποίηση',
4488
- info: 'Πληροφορία',
4489
- yes: 'Ναι',
4490
- no: 'Όχι'
4491
- }
4492
- };
4493
-
4494
- const translations = {
4495
- en,
4496
- el
4497
- };
4498
- const getTranslation = (language, key) => {
4499
- const keys = key.split('.');
4500
- let value = translations[language];
4501
- for (const k of keys) {
4502
- if (value && typeof value === 'object' && k in value) {
4503
- value = value[k];
4504
- }
4505
- else {
4506
- // Fallback to English if key not found
4507
- value = translations.en;
4508
- for (const fallbackKey of keys) {
4509
- if (value && typeof value === 'object' && fallbackKey in value) {
4510
- value = value[fallbackKey];
4511
- }
4512
- else {
4513
- return key; // Return the key if not found in fallback
4514
- }
4515
- }
4516
- break;
4517
- }
4518
- }
4519
- return typeof value === 'string' ? value : key;
4520
- };
4521
- const getAvailableLanguages = () => {
4522
- return [
4523
- { code: 'en', name: 'English' },
4524
- { code: 'el', name: 'Ελληνικά' }
4525
- ];
4526
- };
4527
- const isValidLanguage = (language) => {
4528
- return language === 'en' || language === 'el';
4529
- };
4530
-
4531
4540
  const useTranslation = (defaultLanguage = 'en') => {
4532
4541
  const [currentLanguage, setCurrentLanguage] = useState(defaultLanguage);
4533
4542
  // Update internal language state when defaultLanguage prop changes
@@ -4938,7 +4947,7 @@ const DocumentVideoGrid = ({ videos, attachedVideosLabel, }) => {
4938
4947
  // Module-level Set to track which message IDs have been animated
4939
4948
  // This persists across component unmounts/remounts (e.g., when chat closes and reopens)
4940
4949
  const animatedMessageIds = new Set();
4941
- const Message = ({ message, showThoughts = false, fontSize = 'text-sm', onDelete, onConfirmation, enableButtons = true, streamLoading, apiBaseUrl, apiKey, agencyId, currentLanguage = 'en', onOpenGallery }) => {
4950
+ const Message = ({ message, showThoughts = false, fontSize = 'text-sm', onDelete, onConfirmation, enableButtons = true, apiBaseUrl, apiKey, agencyId, currentLanguage = 'en', onOpenGallery }) => {
4942
4951
  const { t } = useTranslation(currentLanguage);
4943
4952
  const [displayedContent, setDisplayedContent] = useState('');
4944
4953
  const typingIntervalRef = useRef(null);
@@ -5171,9 +5180,13 @@ const Message = ({ message, showThoughts = false, fontSize = 'text-sm', onDelete
5171
5180
  ? displayedContent
5172
5181
  : message.content;
5173
5182
  const extractedUrls = useMemo(() => extractUrlsFromContent(message.content), [message.content]);
5174
- return (jsxs("div", { className: getMessageClasses(), children: [message.content && !message.loading && (jsx("div", { className: "fusioni-message-text", dangerouslySetInnerHTML: {
5183
+ const hasVisibleWhileLoading = Boolean(message.extra_data) ||
5184
+ (showThoughts && Boolean(message.thoughts)) ||
5185
+ Boolean(message.has_error);
5186
+ const collapseEmptyLoadingBubble = Boolean(message.loading) && !hasVisibleWhileLoading;
5187
+ return (jsxs("div", { className: `${getMessageClasses()}${collapseEmptyLoadingBubble ? ' fusioni-message-bubble--loading-empty' : ''}`.trim(), children: [message.content && !message.loading && (jsx("div", { className: "fusioni-message-text", dangerouslySetInnerHTML: {
5175
5188
  __html: enhanceMessageContent(contentToDisplay)
5176
- } })), message.loading && streamLoading, !message.loading && extractedUrls.length > 0 && message.role !== 'user' && (jsx("div", { className: "fusioni-message-url-previews", children: extractedUrls.map((url) => (jsx(UrlPreview, { url: url, agencyId: agencyId, showCloseButton: false, compact: true, autoFetch: true, apiBaseUrl: apiBaseUrl, apiKey: apiKey }, url))) })), message.extra_data && (jsxs("div", { className: "fusioni-message-extra m2", children: [message.extra_data.document_images &&
5189
+ } })), !message.loading && extractedUrls.length > 0 && message.role !== 'user' && (jsx("div", { className: "fusioni-message-url-previews", children: extractedUrls.map((url) => (jsx(UrlPreview, { url: url, agencyId: agencyId, showCloseButton: false, compact: true, autoFetch: true, apiBaseUrl: apiBaseUrl, apiKey: apiKey }, url))) })), message.extra_data && (jsxs("div", { className: "fusioni-message-extra m2", children: [message.extra_data.document_images &&
5177
5190
  message.extra_data.document_images.length > 0 &&
5178
5191
  onOpenGallery && (jsx(DocumentImageGrid, { images: message.extra_data.document_images, onOpenGallery: onOpenGallery, attachedImagesLabel: t('chat.attachedImages') })), message.extra_data.document_videos &&
5179
5192
  message.extra_data.document_videos.length > 0 && (jsx(DocumentVideoGrid, { videos: message.extra_data.document_videos, attachedVideosLabel: t('chat.attachedVideos') })), message.extra_data.image && renderImage(message.extra_data.image), message.extra_data.image_ref && renderImage(message.extra_data.image_ref), message.extra_data.audio_ref && renderAudio(message.extra_data.audio_ref, message.extra_data.duration), message.extra_data.coordinates && renderMap(message.extra_data.coordinates), message.extra_data.map && (jsx("div", { className: "fusioni-message-map", children: jsx(Map$1, { lat: message.extra_data.map.lat, lng: message.extra_data.map.lng, zoom: message.extra_data.map.zoom, staticMap: true, width: 600, height: 400, apiBaseUrl: apiBaseUrl, apiKey: apiKey, agencyId: agencyId }) }))] })), message.extra_data?.widget === 'Confirmation' && (jsxs("div", { className: "fusioni-confirmation-widget", children: [jsx("button", { type: "button", disabled: !enableButtons, onClick: () => sendConfirmation('Confirmed', message.extra_data?.key), className: "fusioni-btn fusioni-btn-primary fusioni-btn-confirm", children: t('common.yes') }), jsx("button", { type: "button", disabled: !enableButtons, onClick: () => sendConfirmation('NotConfirmed', message.extra_data?.key), className: "fusioni-btn fusioni-btn-secondary fusioni-btn-cancel", children: t('common.no') })] })), showThoughts && message.thoughts && (jsx("div", { className: "fusioni-message-thoughts", children: jsxs("details", { children: [jsx("summary", { children: "AI Thoughts" }), jsx("p", { children: message.thoughts })] }) })), message.has_error && (jsxs("div", { className: "fusioni-message-error-indicator", children: [jsxs("svg", { width: "16", height: "16", viewBox: "0 0 24 24", fill: "none", children: [jsx("circle", { cx: "12", cy: "12", r: "10", stroke: "currentColor", strokeWidth: "2" }), jsx("line", { x1: "15", y1: "9", x2: "9", y2: "15", stroke: "currentColor", strokeWidth: "2" }), jsx("line", { x1: "9", y1: "9", x2: "15", y2: "15", stroke: "currentColor", strokeWidth: "2" })] }), jsx("span", { children: "Error occurred" })] }))] }));
@@ -5426,12 +5439,12 @@ const MessageList = ({ messages, streamMessages, showThoughts = false, onDeleteM
5426
5439
  const isLastMessage = index === messages.length - 1;
5427
5440
  const messageKey = message.id ??
5428
5441
  `msg-fallback-${index}-${message.role}-${message.created instanceof Date ? message.created.getTime() : 0}`;
5429
- return (jsx("div", { className: "fusioni-message-wrapper", children: jsxs("div", { className: `fusioni-message ${message.role}`, children: [jsx("div", { className: "fusioni-message-avatar", children: message.role === 'user' ? (jsxs("svg", { width: "20", height: "20", viewBox: "0 0 24 24", fill: "none", children: [jsx("path", { d: "M20 21V19C20 17.9391 19.5786 16.9217 18.8284 16.1716C18.0783 15.4214 17.0609 15 16 15H8C6.93913 15 5.92172 15.4214 5.17157 16.1716C4.42143 16.9217 4 17.9391 4 19V21", stroke: "currentColor", strokeWidth: "2", strokeLinecap: "round", strokeLinejoin: "round" }), jsx("circle", { cx: "12", cy: "7", r: "4", stroke: "currentColor", strokeWidth: "2" })] })) : (jsx("img", { src: FUSIONI_LOGO_BASE64, alt: "Fusioni Logo", width: "24", height: "24" })) }), jsxs("div", { className: "fusioni-message-content", children: [jsx("div", { className: "fusioni-message-body", children: message.role === 'user' && editingMessageId === message.id ? (jsx("div", { ref: editRef, className: "fusioni-message-text", contentEditable: true, suppressContentEditableWarning: true, spellCheck: true, onKeyDown: (event) => {
5442
+ return (jsx("div", { className: "fusioni-message-wrapper", children: jsxs("div", { className: `fusioni-message ${message.role}`, children: [!(message.role === 'assistant' && message.loading) && (jsx("div", { className: "fusioni-message-avatar", children: message.role === 'user' ? (jsxs("svg", { width: "20", height: "20", viewBox: "0 0 24 24", fill: "none", children: [jsx("path", { d: "M20 21V19C20 17.9391 19.5786 16.9217 18.8284 16.1716C18.0783 15.4214 17.0609 15 16 15H8C6.93913 15 5.92172 15.4214 5.17157 16.1716C4.42143 16.9217 4 17.9391 4 19V21", stroke: "currentColor", strokeWidth: "2", strokeLinecap: "round", strokeLinejoin: "round" }), jsx("circle", { cx: "12", cy: "7", r: "4", stroke: "currentColor", strokeWidth: "2" })] })) : (jsx("img", { src: FUSIONI_LOGO_BASE64, alt: "Fusioni Logo", width: "24", height: "24" })) })), jsxs("div", { className: "fusioni-message-content", children: [jsx("div", { className: "fusioni-message-body", children: message.role === 'user' && editingMessageId === message.id ? (jsx("div", { ref: editRef, className: "fusioni-message-text", contentEditable: true, suppressContentEditableWarning: true, spellCheck: true, onKeyDown: (event) => {
5430
5443
  if (event.key === 'Escape') {
5431
5444
  event.preventDefault();
5432
5445
  cancelEdit();
5433
5446
  }
5434
- } })) : (jsx(Message, { message: message, showThoughts: showThoughts, onDelete: onDeleteMessage, onConfirmation: onConfirmation, enableButtons: enableButtons && isLastMessage, streamLoading: message.loading ? (jsx(MessageStreamLoading, { streamMessages: streamMessages, loadingLabel: t('chat.messages.loading') })) : undefined, apiBaseUrl: apiBaseUrl, apiKey: apiKey, agencyId: agencyId, currentLanguage: currentLanguage, onOpenGallery: openGallery })) }), jsxs("div", { className: "fusioni-message-footer", children: [jsx("span", { className: "fusioni-message-time", children: formatDate(message.created) }), message.id && (onDeleteMessage || (message.role === 'user' && onEditMessage)) && (jsx("div", { className: "fusioni-message-actions", children: message.role === 'user' && editingMessageId === message.id ? (jsxs(Fragment, { children: [jsx("button", { onClick: confirmEdit, className: "fusioni-btn fusioni-btn-icon", title: "Save edit", children: jsx("svg", { width: "16", height: "16", viewBox: "0 0 24 24", fill: "none", children: jsx("polyline", { points: "20 6 9 17 4 12", stroke: "currentColor", strokeWidth: "2", strokeLinecap: "round", strokeLinejoin: "round" }) }) }), jsx("button", { onClick: cancelEdit, className: "fusioni-btn fusioni-btn-icon", title: "Cancel edit", children: jsxs("svg", { width: "16", height: "16", viewBox: "0 0 24 24", fill: "none", children: [jsx("line", { x1: "18", y1: "6", x2: "6", y2: "18", stroke: "currentColor", strokeWidth: "2", strokeLinecap: "round", strokeLinejoin: "round" }), jsx("line", { x1: "6", y1: "6", x2: "18", y2: "18", stroke: "currentColor", strokeWidth: "2", strokeLinecap: "round", strokeLinejoin: "round" })] }) })] })) : (jsxs(Fragment, { children: [message.role === 'user' && onEditMessage && (jsx("button", { onClick: () => startEdit(message), className: "fusioni-btn fusioni-btn-icon", title: "Edit message", children: jsxs("svg", { width: "16", height: "16", viewBox: "0 0 24 24", fill: "none", children: [jsx("path", { d: "M12 20H21", stroke: "currentColor", strokeWidth: "2", strokeLinecap: "round", strokeLinejoin: "round" }), jsx("path", { d: "M16.5 3.5C16.8978 3.10218 17.4374 2.87868 18 2.87868C18.5626 2.87868 19.1022 3.10218 19.5 3.5C19.8978 3.89782 20.1213 4.43739 20.1213 5C20.1213 5.56261 19.8978 6.10218 19.5 6.5L7 19L3 20L4 16L16.5 3.5Z", stroke: "currentColor", strokeWidth: "2", strokeLinecap: "round", strokeLinejoin: "round" })] }) })), onDeleteMessage && (jsx("button", { onClick: () => onDeleteMessage(message.id), className: "fusioni-btn fusioni-btn-icon", title: "Delete message", children: jsxs("svg", { width: "16", height: "16", viewBox: "0 0 24 24", fill: "none", children: [jsx("path", { d: "M3 6H5H21", stroke: "currentColor", strokeWidth: "2", strokeLinecap: "round", strokeLinejoin: "round" }), jsx("path", { d: "M8 6V4C8 3.46957 8.21071 2.96086 8.58579 2.58579C8.96086 2.21071 9.46957 2 10 2H14C14.5304 2 15.0391 2.21071 15.4142 2.58579C15.7893 2.96086 16 3.46957 16 4V6M19 6V20C19 20.5304 18.7893 21.0391 18.4142 21.4142C18.0391 21.7893 17.5304 22 17 22H7C6.46957 22 5.96086 21.7893 5.58579 21.4142C5.21071 21.0391 5 20.5304 5 20V6H19Z", stroke: "currentColor", strokeWidth: "2", strokeLinecap: "round", strokeLinejoin: "round" })] }) }))] })) }))] }), showThoughts && message.thoughts && (jsx("div", { className: "fusioni-message-thoughts", children: jsxs("details", { children: [jsx("summary", { children: "Thoughts" }), jsx("p", { children: message.thoughts })] }) }))] })] }) }, messageKey));
5447
+ } })) : (jsxs(Fragment, { children: [message.loading && (jsx(MessageStreamLoading, { streamMessages: streamMessages, loadingLabel: t('chat.messages.loading') })), !message.loading && (jsx(Message, { message: message, showThoughts: showThoughts, onDelete: onDeleteMessage, onConfirmation: onConfirmation, enableButtons: enableButtons && isLastMessage, apiBaseUrl: apiBaseUrl, apiKey: apiKey, agencyId: agencyId, currentLanguage: currentLanguage, onOpenGallery: openGallery }))] })) }), !message.loading && (jsxs("div", { className: "fusioni-message-footer", children: [jsx("span", { className: "fusioni-message-time", children: formatDate(message.created) }), message.id && (onDeleteMessage || (message.role === 'user' && onEditMessage)) && (jsx("div", { className: "fusioni-message-actions", children: message.role === 'user' && editingMessageId === message.id ? (jsxs(Fragment, { children: [jsx("button", { onClick: confirmEdit, className: "fusioni-btn fusioni-btn-icon", title: "Save edit", children: jsx("svg", { width: "16", height: "16", viewBox: "0 0 24 24", fill: "none", children: jsx("polyline", { points: "20 6 9 17 4 12", stroke: "currentColor", strokeWidth: "2", strokeLinecap: "round", strokeLinejoin: "round" }) }) }), jsx("button", { onClick: cancelEdit, className: "fusioni-btn fusioni-btn-icon", title: "Cancel edit", children: jsxs("svg", { width: "16", height: "16", viewBox: "0 0 24 24", fill: "none", children: [jsx("line", { x1: "18", y1: "6", x2: "6", y2: "18", stroke: "currentColor", strokeWidth: "2", strokeLinecap: "round", strokeLinejoin: "round" }), jsx("line", { x1: "6", y1: "6", x2: "18", y2: "18", stroke: "currentColor", strokeWidth: "2", strokeLinecap: "round", strokeLinejoin: "round" })] }) })] })) : (jsxs(Fragment, { children: [message.role === 'user' && onEditMessage && (jsx("button", { onClick: () => startEdit(message), className: "fusioni-btn fusioni-btn-icon", title: "Edit message", children: jsxs("svg", { width: "16", height: "16", viewBox: "0 0 24 24", fill: "none", children: [jsx("path", { d: "M12 20H21", stroke: "currentColor", strokeWidth: "2", strokeLinecap: "round", strokeLinejoin: "round" }), jsx("path", { d: "M16.5 3.5C16.8978 3.10218 17.4374 2.87868 18 2.87868C18.5626 2.87868 19.1022 3.10218 19.5 3.5C19.8978 3.89782 20.1213 4.43739 20.1213 5C20.1213 5.56261 19.8978 6.10218 19.5 6.5L7 19L3 20L4 16L16.5 3.5Z", stroke: "currentColor", strokeWidth: "2", strokeLinecap: "round", strokeLinejoin: "round" })] }) })), onDeleteMessage && (jsx("button", { onClick: () => onDeleteMessage(message.id), className: "fusioni-btn fusioni-btn-icon", title: "Delete message", children: jsxs("svg", { width: "16", height: "16", viewBox: "0 0 24 24", fill: "none", children: [jsx("path", { d: "M3 6H5H21", stroke: "currentColor", strokeWidth: "2", strokeLinecap: "round", strokeLinejoin: "round" }), jsx("path", { d: "M8 6V4C8 3.46957 8.21071 2.96086 8.58579 2.58579C8.96086 2.21071 9.46957 2 10 2H14C14.5304 2 15.0391 2.21071 15.4142 2.58579C15.7893 2.96086 16 3.46957 16 4V6M19 6V20C19 20.5304 18.7893 21.0391 18.4142 21.4142C18.0391 21.7893 17.5304 22 17 22H7C6.46957 22 5.96086 21.7893 5.58579 21.4142C5.21071 21.0391 5 20.5304 5 20V6H19Z", stroke: "currentColor", strokeWidth: "2", strokeLinecap: "round", strokeLinejoin: "round" })] }) }))] })) }))] })), showThoughts && message.thoughts && (jsx("div", { className: "fusioni-message-thoughts", children: jsxs("details", { children: [jsx("summary", { children: "Thoughts" }), jsx("p", { children: message.thoughts })] }) }))] })] }) }, messageKey));
5435
5448
  }) })), jsx("div", { ref: messagesEndRef })] }) }), gallerySession &&
5436
5449
  typeof document !== 'undefined' &&
5437
5450
  createPortal(jsx(ImageGallery, { images: gallerySession.images, initialIndex: gallerySession.index, theme: theme, onClose: () => setGallerySession(null) }, gallerySession.key), document.body)] }));
@@ -5949,56 +5962,90 @@ const useSSE = (agencyId, onMessage, isConnected = true, accessToken) => {
5949
5962
  };
5950
5963
 
5951
5964
  const THEME_STORAGE_KEY = 'fusioni-chat-theme';
5965
+ function resolveDisplayTheme(setting) {
5966
+ if (setting === 'auto') {
5967
+ return window.matchMedia('(prefers-color-scheme: dark)').matches ? 'dark' : 'light';
5968
+ }
5969
+ if (setting === 'dark' || setting === 'light') {
5970
+ return setting;
5971
+ }
5972
+ return 'light';
5973
+ }
5952
5974
  const useTheme = (initialTheme) => {
5953
5975
  const [currentTheme, setCurrentTheme] = useState('light');
5954
5976
  const [isManualOverride, setIsManualOverride] = useState(false);
5955
- // Load theme from localStorage on initialization
5977
+ const [programmaticTheme, setProgrammaticTheme] = useState(null);
5978
+ const persistThemeSetting = useCallback((setting) => {
5979
+ try {
5980
+ if (setting === 'auto') {
5981
+ localStorage.removeItem(THEME_STORAGE_KEY);
5982
+ }
5983
+ else {
5984
+ localStorage.setItem(THEME_STORAGE_KEY, setting);
5985
+ }
5986
+ }
5987
+ catch (error) {
5988
+ console.warn('Failed to persist theme to localStorage:', error);
5989
+ }
5990
+ }, []);
5991
+ const setTheme = useCallback((theme) => {
5992
+ setProgrammaticTheme(theme);
5993
+ setCurrentTheme(resolveDisplayTheme(theme));
5994
+ setIsManualOverride(true);
5995
+ persistThemeSetting(theme);
5996
+ }, [persistThemeSetting]);
5997
+ // Load theme from localStorage on initialization (unless SDK / caller already set a theme)
5956
5998
  useEffect(() => {
5999
+ if (programmaticTheme != null) {
6000
+ return;
6001
+ }
5957
6002
  try {
5958
6003
  const savedTheme = localStorage.getItem(THEME_STORAGE_KEY);
5959
6004
  if (savedTheme === 'light' || savedTheme === 'dark') {
5960
6005
  setCurrentTheme(savedTheme);
5961
6006
  setIsManualOverride(true);
5962
- return;
5963
6007
  }
5964
6008
  }
5965
6009
  catch (error) {
5966
6010
  console.warn('Failed to load theme from localStorage:', error);
5967
6011
  }
6012
+ }, [programmaticTheme]);
6013
+ const toggleTheme = useCallback(() => {
6014
+ setCurrentTheme((prev) => {
6015
+ const next = prev === 'light' ? 'dark' : 'light';
6016
+ setProgrammaticTheme(next);
6017
+ setIsManualOverride(true);
6018
+ try {
6019
+ localStorage.setItem(THEME_STORAGE_KEY, next);
6020
+ }
6021
+ catch (error) {
6022
+ console.warn('Failed to save theme to localStorage:', error);
6023
+ }
6024
+ return next;
6025
+ });
5968
6026
  }, []);
5969
- const toggleTheme = () => {
5970
- const newTheme = currentTheme === 'light' ? 'dark' : 'light';
5971
- setCurrentTheme(newTheme);
5972
- setIsManualOverride(true);
5973
- // Save to localStorage
5974
- try {
5975
- localStorage.setItem(THEME_STORAGE_KEY, newTheme);
5976
- }
5977
- catch (error) {
5978
- console.warn('Failed to save theme to localStorage:', error);
5979
- }
5980
- };
5981
6027
  useEffect(() => {
5982
- // Check if we have a saved theme first
6028
+ if (programmaticTheme != null) {
6029
+ if (programmaticTheme === 'auto') {
6030
+ const mediaQuery = window.matchMedia('(prefers-color-scheme: dark)');
6031
+ const handleChange = () => {
6032
+ setCurrentTheme(resolveDisplayTheme('auto'));
6033
+ };
6034
+ handleChange();
6035
+ mediaQuery.addEventListener('change', handleChange);
6036
+ return () => mediaQuery.removeEventListener('change', handleChange);
6037
+ }
6038
+ return;
6039
+ }
5983
6040
  const savedTheme = localStorage.getItem(THEME_STORAGE_KEY);
5984
6041
  if (savedTheme === 'light' || savedTheme === 'dark') {
5985
- return; // Don't override saved theme
6042
+ return;
6043
+ }
6044
+ if (isManualOverride) {
6045
+ return;
5986
6046
  }
5987
- if (isManualOverride)
5988
- return; // Don't auto-update if user manually changed theme
5989
6047
  const updateTheme = () => {
5990
- if (initialTheme === 'auto') {
5991
- // Check system preference
5992
- const prefersDark = window.matchMedia('(prefers-color-scheme: dark)').matches;
5993
- setCurrentTheme(prefersDark ? 'dark' : 'light');
5994
- }
5995
- else if (initialTheme === 'dark' || initialTheme === 'light') {
5996
- setCurrentTheme(initialTheme);
5997
- }
5998
- else {
5999
- // Default to light theme
6000
- setCurrentTheme('light');
6001
- }
6048
+ setCurrentTheme(resolveDisplayTheme(initialTheme));
6002
6049
  };
6003
6050
  updateTheme();
6004
6051
  if (initialTheme === 'auto') {
@@ -6007,11 +6054,12 @@ const useTheme = (initialTheme) => {
6007
6054
  mediaQuery.addEventListener('change', handleChange);
6008
6055
  return () => mediaQuery.removeEventListener('change', handleChange);
6009
6056
  }
6010
- }, [initialTheme, isManualOverride]);
6057
+ }, [initialTheme, isManualOverride, programmaticTheme]);
6011
6058
  return {
6012
6059
  theme: currentTheme,
6013
6060
  toggleTheme,
6014
- isManualOverride
6061
+ setTheme,
6062
+ isManualOverride,
6015
6063
  };
6016
6064
  };
6017
6065
 
@@ -6033,7 +6081,8 @@ function useIsMobileLayout() {
6033
6081
  return isMobile;
6034
6082
  }
6035
6083
 
6036
- const ChatWidget = ({ config, onMessageSent, onMessageReceived, onConversationCreated, onConversationDeleted, onError }) => {
6084
+ const ChatWidget = forwardRef(function ChatWidget({ config, onMessageSent, onMessageReceived, onConversationCreated, onConversationDeleted, onError }, ref) {
6085
+ const [languageOverride, setLanguageOverride] = useState(null);
6037
6086
  const [isOpen, setIsOpen] = useState(false);
6038
6087
  const [isLoading, setIsLoading] = useState(false);
6039
6088
  const [error, setError] = useState(null);
@@ -6048,11 +6097,26 @@ const ChatWidget = ({ config, onMessageSent, onMessageReceived, onConversationCr
6048
6097
  const [isDeleteMessageDialogOpen, setIsDeleteMessageDialogOpen] = useState(false);
6049
6098
  // Refs
6050
6099
  const floatingButtonRef = useRef(null);
6100
+ const translationDefault = languageOverride ?? mergedConfig?.language ?? config.language ?? 'en';
6051
6101
  // Translation and language management - use merged config or fallback to user config
6052
- const { t, currentLanguage, changeLanguage } = useTranslation(mergedConfig?.language || config.language || 'en');
6102
+ const { t, currentLanguage, changeLanguage } = useTranslation(translationDefault);
6053
6103
  const { conversations, currentConversation, messages, streamMessages, setCurrentConversation, setStreamMessages, addMessage, updateMessage, removeMessage, removeOptimisticUserMessages, truncateMessagesAt, addConversation, updateConversation, removeConversation, loadConversations, loadMessages, clearMessages } = useChatState(mergedConfig?.agencyId || config.agencyId);
6054
- const { theme, toggleTheme } = useTheme(mergedConfig?.theme || config.theme);
6104
+ const { theme, toggleTheme, setTheme } = useTheme(mergedConfig?.theme || config.theme);
6055
6105
  const isMobileLayout = useIsMobileLayout();
6106
+ const handleLanguageChange = useCallback((language) => {
6107
+ setLanguageOverride(language);
6108
+ changeLanguage(language);
6109
+ }, [changeLanguage]);
6110
+ useImperativeHandle(ref, () => ({
6111
+ setLanguage: (language) => {
6112
+ if (!isValidLanguage(language)) {
6113
+ return;
6114
+ }
6115
+ setLanguageOverride(language);
6116
+ changeLanguage(language);
6117
+ },
6118
+ setTheme,
6119
+ }), [changeLanguage, setTheme]);
6056
6120
  // Initialize API client and fetch server configuration
6057
6121
  useEffect(() => {
6058
6122
  const initializeAndFetchConfig = async () => {
@@ -6540,8 +6604,9 @@ const ChatWidget = ({ config, onMessageSent, onMessageReceived, onConversationCr
6540
6604
  // Debug: Log the primary color and button variant being applied
6541
6605
  console.log('Primary color being applied:', mergedConfig.primaryColor || '#6366f1');
6542
6606
  console.log('Button variant being applied:', mergedConfig.buttonVariant || 'glass');
6543
- return (jsxs("div", { className: `fusioni-chat-widget ${theme}`, style: { '--primary-color': mergedConfig.primaryColor || '#6366f1' }, children: [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 && (jsx(ChatPanel, { isOpen: isOpen, onClose: () => setIsOpen(false), position: mergedConfig.position || 'bottom-right', isFullscreen: isFullscreen, floatingButtonRef: floatingButtonRef, children: jsxs("div", { className: "fusioni-chat-container", children: [mergedConfig.showConversationList !== false && (jsxs(Fragment, { children: [jsx("div", { className: `fusioni-conversation-backdrop ${isConversationListOpen ? 'open' : ''}`, onClick: () => setIsConversationListOpen(false) }), jsx(ConversationList, { conversations: conversations, selectedConversationId: currentConversation?.id || undefined, onSelectConversation: handleSelectConversation, onDeleteConversation: handleDeleteConversation, onCreateConversation: handleCreateConversation, isOpen: isConversationListOpen, currentLanguage: currentLanguage })] })), jsxs("div", { className: "fusioni-chat-main", children: [jsxs("div", { className: "fusioni-chat-main-header", children: [mergedConfig.showConversationList !== false ? (jsxs("button", { type: "button", onClick: handleToggleConversationList, className: `fusioni-conversation-toggle ${isConversationListOpen ? 'open' : ''}`, children: [jsx("svg", { className: "fusioni-conversation-toggle-icon", viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "2", children: jsx("path", { d: "M3 12h18M3 6h18M3 18h18" }) }), t('chat.conversations.title')] })) : (jsx("span", { className: "fusioni-chat-main-header-title", children: t('chat.title') })), jsxs("div", { className: "fusioni-header-actions", children: [isMobileLayout && (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: jsx("svg", { width: "20", height: "20", viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "2", "aria-hidden": "true", children: jsx("path", { d: "M18 6L6 18M6 6L18 18", strokeLinecap: "round", strokeLinejoin: "round" }) }) })), 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' ? (jsxs("svg", { width: "20", height: "20", viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "2", children: [jsx("circle", { cx: "12", cy: "12", r: "5" }), jsx("line", { x1: "12", y1: "1", x2: "12", y2: "3" }), jsx("line", { x1: "12", y1: "21", x2: "12", y2: "23" }), jsx("line", { x1: "4.22", y1: "4.22", x2: "5.64", y2: "5.64" }), jsx("line", { x1: "18.36", y1: "18.36", x2: "19.78", y2: "19.78" }), jsx("line", { x1: "1", y1: "12", x2: "3", y2: "12" }), jsx("line", { x1: "21", y1: "12", x2: "23", y2: "12" }), jsx("line", { x1: "4.22", y1: "19.78", x2: "5.64", y2: "18.36" }), jsx("line", { x1: "18.36", y1: "5.64", x2: "19.78", y2: "4.22" })] })) : (jsx("svg", { width: "20", height: "20", viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "2", children: jsx("path", { d: "M21 12.79A9 9 0 1 1 11.21 3 7 7 0 0 0 21 12.79z" }) })) }), jsx("button", { type: "button", onClick: handleToggleFullscreen, className: "fusioni-btn fusioni-btn-icon", title: isFullscreen ? t('chat.fullscreen.exit') : t('chat.fullscreen.enter'), children: isFullscreen ? (jsx("svg", { width: "20", height: "20", viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "2", children: jsx("path", { d: "M8 3V5M8 3H5M8 3L3 8M16 3V5M16 3H19M16 3L21 8M8 21V19M8 21H5M8 21L3 16M16 21V19M16 21H19M16 21L21 16" }) })) : (jsx("svg", { width: "20", height: "20", viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "2", children: 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" }) })) }), jsx(LanguageSwitcher, { currentLanguage: currentLanguage, onLanguageChange: changeLanguage })] })] }), currentConversation ? (jsxs(Fragment, { children: [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 }), 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 })] })) : (jsx("div", { className: "fusioni-chat-welcome", children: jsxs("div", { className: "fusioni-chat-welcome-content", children: [jsx("h3", { children: t('chat.welcome.title') }), jsx("p", { children: t('chat.welcome.description') }), jsx("button", { onClick: handleCreateConversation, disabled: isLoading, className: "fusioni-btn fusioni-btn-primary", children: isLoading ? t('chat.welcome.creating') : t('chat.welcome.startButton') })] }) }))] })] }) })), 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" }), 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" })] }));
6544
- };
6607
+ return (jsxs("div", { className: `fusioni-chat-widget ${theme}`, style: { '--primary-color': mergedConfig.primaryColor || '#6366f1' }, children: [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 && (jsx(ChatPanel, { isOpen: isOpen, onClose: () => setIsOpen(false), position: mergedConfig.position || 'bottom-right', isFullscreen: isFullscreen, floatingButtonRef: floatingButtonRef, children: jsxs("div", { className: "fusioni-chat-container", children: [mergedConfig.showConversationList !== false && (jsxs(Fragment, { children: [jsx("div", { className: `fusioni-conversation-backdrop ${isConversationListOpen ? 'open' : ''}`, onClick: () => setIsConversationListOpen(false) }), jsx(ConversationList, { conversations: conversations, selectedConversationId: currentConversation?.id || undefined, onSelectConversation: handleSelectConversation, onDeleteConversation: handleDeleteConversation, onCreateConversation: handleCreateConversation, isOpen: isConversationListOpen, currentLanguage: currentLanguage })] })), jsxs("div", { className: "fusioni-chat-main", children: [jsxs("div", { className: "fusioni-chat-main-header", children: [mergedConfig.showConversationList !== false ? (jsxs("button", { type: "button", onClick: handleToggleConversationList, className: `fusioni-conversation-toggle ${isConversationListOpen ? 'open' : ''}`, children: [jsx("svg", { className: "fusioni-conversation-toggle-icon", viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "2", children: jsx("path", { d: "M3 12h18M3 6h18M3 18h18" }) }), t('chat.conversations.title')] })) : (jsx("span", { className: "fusioni-chat-main-header-title", children: t('chat.title') })), jsxs("div", { className: "fusioni-header-actions", children: [isMobileLayout && (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: jsx("svg", { width: "20", height: "20", viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "2", "aria-hidden": "true", children: jsx("path", { d: "M18 6L6 18M6 6L18 18", strokeLinecap: "round", strokeLinejoin: "round" }) }) })), mergedConfig.showThemeToggle !== false && (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' ? (jsxs("svg", { width: "20", height: "20", viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "2", children: [jsx("circle", { cx: "12", cy: "12", r: "5" }), jsx("line", { x1: "12", y1: "1", x2: "12", y2: "3" }), jsx("line", { x1: "12", y1: "21", x2: "12", y2: "23" }), jsx("line", { x1: "4.22", y1: "4.22", x2: "5.64", y2: "5.64" }), jsx("line", { x1: "18.36", y1: "18.36", x2: "19.78", y2: "19.78" }), jsx("line", { x1: "1", y1: "12", x2: "3", y2: "12" }), jsx("line", { x1: "21", y1: "12", x2: "23", y2: "12" }), jsx("line", { x1: "4.22", y1: "19.78", x2: "5.64", y2: "18.36" }), jsx("line", { x1: "18.36", y1: "5.64", x2: "19.78", y2: "4.22" })] })) : (jsx("svg", { width: "20", height: "20", viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "2", children: jsx("path", { d: "M21 12.79A9 9 0 1 1 11.21 3 7 7 0 0 0 21 12.79z" }) })) })), mergedConfig.showFullscreenToggle !== false && (jsx("button", { type: "button", onClick: handleToggleFullscreen, className: "fusioni-btn fusioni-btn-icon", title: isFullscreen ? t('chat.fullscreen.exit') : t('chat.fullscreen.enter'), children: isFullscreen ? (jsx("svg", { width: "20", height: "20", viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "2", children: jsx("path", { d: "M8 3V5M8 3H5M8 3L3 8M16 3V5M16 3H19M16 3L21 8M8 21V19M8 21H5M8 21L3 16M16 21V19M16 21H19M16 21L21 16" }) })) : (jsx("svg", { width: "20", height: "20", viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "2", children: 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 && (jsx(LanguageSwitcher, { currentLanguage: currentLanguage, onLanguageChange: handleLanguageChange }))] })] }), currentConversation ? (jsxs(Fragment, { children: [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 }), 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 })] })) : (jsx("div", { className: "fusioni-chat-welcome", children: jsxs("div", { className: "fusioni-chat-welcome-content", children: [jsx("h3", { children: t('chat.welcome.title') }), jsx("p", { children: t('chat.welcome.description') }), jsx("button", { onClick: handleCreateConversation, disabled: isLoading, className: "fusioni-btn fusioni-btn-primary", children: isLoading ? t('chat.welcome.creating') : t('chat.welcome.startButton') })] }) }))] })] }) })), 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" }), 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" })] }));
6608
+ });
6609
+ ChatWidget.displayName = 'ChatWidget';
6545
6610
 
6546
6611
  const FileUpload = ({ onFileSelect, accept = 'image/*', maxSize = 10, disabled = false, className = '' }) => {
6547
6612
  const fileInputRef = useRef(null);