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