open-chat-studio-widget 0.6.0 → 0.7.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +27 -25
- package/dist/cjs/{index-CcvroTR_.js → index-CvB341El.js} +3 -3
- package/dist/cjs/{index-CcvroTR_.js.map → index-CvB341El.js.map} +1 -1
- package/dist/cjs/loader.cjs.js +2 -2
- package/dist/cjs/open-chat-studio-widget.cjs.entry.js +364 -142
- package/dist/cjs/open-chat-studio-widget.cjs.entry.js.map +1 -1
- package/dist/cjs/open-chat-studio-widget.cjs.js +2 -2
- package/dist/cjs/open-chat-studio-widget.entry.cjs.js.map +1 -1
- package/dist/collection/components/ocs-chat/icons.js +2 -2
- package/dist/collection/components/ocs-chat/icons.js.map +1 -1
- package/dist/collection/components/ocs-chat/ocs-chat.css +29 -34
- package/dist/collection/components/ocs-chat/ocs-chat.js +281 -78
- package/dist/collection/components/ocs-chat/ocs-chat.js.map +1 -1
- package/dist/collection/services/chat-session-service.js +4 -0
- package/dist/collection/services/chat-session-service.js.map +1 -1
- package/dist/collection/services/file-attachment-manager.js +4 -7
- package/dist/collection/services/file-attachment-manager.js.map +1 -1
- package/dist/collection/utils/cookies.js.map +1 -1
- package/dist/collection/utils/markdown.js +43 -17
- package/dist/collection/utils/markdown.js.map +1 -1
- package/dist/collection/utils/translations.js +1 -3
- package/dist/collection/utils/translations.js.map +1 -1
- package/dist/collection/utils/utils.js +2 -2
- package/dist/collection/utils/utils.js.map +1 -1
- package/dist/components/open-chat-studio-widget.js +369 -141
- package/dist/components/open-chat-studio-widget.js.map +1 -1
- package/dist/esm/{index-BKVXO_5E.js → index-C2QZK0Ui.js} +3 -3
- package/dist/esm/{index-BKVXO_5E.js.map → index-C2QZK0Ui.js.map} +1 -1
- package/dist/esm/loader.js +3 -3
- package/dist/esm/open-chat-studio-widget.entry.js +364 -142
- package/dist/esm/open-chat-studio-widget.entry.js.map +1 -1
- package/dist/esm/open-chat-studio-widget.js +3 -3
- package/dist/open-chat-studio-widget/open-chat-studio-widget.entry.esm.js.map +1 -1
- package/dist/open-chat-studio-widget/open-chat-studio-widget.esm.js +1 -1
- package/dist/open-chat-studio-widget/{p-BKVXO_5E.js → p-C2QZK0Ui.js} +2 -2
- package/dist/open-chat-studio-widget/{p-BKVXO_5E.js.map → p-C2QZK0Ui.js.map} +1 -1
- package/dist/open-chat-studio-widget/p-e87d4e31.entry.js +4 -0
- package/dist/open-chat-studio-widget/p-e87d4e31.entry.js.map +1 -0
- package/dist/types/components/ocs-chat/ocs-chat.d.ts +29 -1
- package/dist/types/components.d.ts +23 -2
- package/dist/types/services/chat-session-service.d.ts +1 -0
- package/dist/types/utils/markdown.d.ts +8 -0
- package/package.json +7 -2
- package/dist/open-chat-studio-widget/p-a0d04423.entry.js +0 -4
- package/dist/open-chat-studio-widget/p-a0d04423.entry.js.map +0 -1
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
// eslint-disable-next-line @typescript-eslint/no-unused-vars
|
|
2
2
|
import { Host, h, Env } from "@stencil/core";
|
|
3
|
-
import { XMarkIcon, GripDotsVerticalIcon, PlusWithCircleIcon, ArrowsPointingOutIcon, ArrowsPointingInIcon, PaperClipIcon, CheckDocumentIcon, XIcon, OcsWidgetAvatar } from "./icons";
|
|
3
|
+
import { XMarkIcon, GripDotsVerticalIcon, PlusWithCircleIcon, ArrowsPointingOutIcon, ArrowsPointingInIcon, PaperClipIcon, CheckDocumentIcon, XIcon, OcsWidgetAvatar, } from "./icons";
|
|
4
4
|
import { renderMarkdownSync as renderMarkdownComplete } from "../../utils/markdown";
|
|
5
5
|
import { varToPixels } from "../../utils/utils";
|
|
6
6
|
import { TranslationManager, defaultTranslations } from "../../utils/translations";
|
|
@@ -11,11 +11,23 @@ export class OcsChat {
|
|
|
11
11
|
/**
|
|
12
12
|
* The base URL for the API.
|
|
13
13
|
*/
|
|
14
|
-
this.apiBaseUrl =
|
|
14
|
+
this.apiBaseUrl = 'https://www.openchatstudio.com';
|
|
15
15
|
/**
|
|
16
16
|
* The shape of the chat button. 'round' makes it circular, 'square' keeps it rectangular.
|
|
17
17
|
*/
|
|
18
18
|
this.buttonShape = 'square';
|
|
19
|
+
/**
|
|
20
|
+
* Whether to show the launcher button. Set to false to hide the button
|
|
21
|
+
* and open the chat window programmatically via the `visible` property.
|
|
22
|
+
*/
|
|
23
|
+
this.showButton = true;
|
|
24
|
+
/**
|
|
25
|
+
* The operating mode of the widget.
|
|
26
|
+
* - 'standard': Default floating window with launcher button.
|
|
27
|
+
* - 'kiosk': Fills parent container, always visible, no header or launcher button.
|
|
28
|
+
* The parent element must establish a containing block (e.g. `position: relative`).
|
|
29
|
+
*/
|
|
30
|
+
this.mode = 'standard';
|
|
19
31
|
/**
|
|
20
32
|
* Whether the chat widget is visible on load.
|
|
21
33
|
*/
|
|
@@ -41,12 +53,13 @@ export class OcsChat {
|
|
|
41
53
|
* Allow the user to attach files to their messages.
|
|
42
54
|
*/
|
|
43
55
|
this.allowAttachments = false;
|
|
44
|
-
this.error =
|
|
56
|
+
this.error = '';
|
|
45
57
|
this.messages = [];
|
|
46
58
|
this.isLoading = false;
|
|
47
59
|
this.isTyping = false;
|
|
48
|
-
this.
|
|
49
|
-
this.
|
|
60
|
+
this.typingProgressMessage = '';
|
|
61
|
+
this.messageInput = '';
|
|
62
|
+
this.currentPollTaskId = '';
|
|
50
63
|
this.isDragging = false;
|
|
51
64
|
this.dragOffset = { x: 0, y: 0 };
|
|
52
65
|
this.windowPosition = { x: 0, y: 0 };
|
|
@@ -75,6 +88,7 @@ export class OcsChat {
|
|
|
75
88
|
this.chatWindowWidth = 450;
|
|
76
89
|
this.chatWindowFullscreenWidth = 1024;
|
|
77
90
|
this.positionInitialized = false;
|
|
91
|
+
this.sessionEpoch = 0;
|
|
78
92
|
this.handleMouseDown = (event) => {
|
|
79
93
|
if (!this.isFullscreen && window.innerWidth < OcsChat.MOBILE_BREAKPOINT)
|
|
80
94
|
return;
|
|
@@ -120,6 +134,8 @@ export class OcsChat {
|
|
|
120
134
|
};
|
|
121
135
|
this.handleWindowResize = () => {
|
|
122
136
|
var _a, _b;
|
|
137
|
+
if (this.isKioskMode())
|
|
138
|
+
return;
|
|
123
139
|
this.positionInitialized = false;
|
|
124
140
|
this.initializePosition();
|
|
125
141
|
// Revalidate button position after resize to keep it within viewport bounds
|
|
@@ -131,7 +147,7 @@ export class OcsChat {
|
|
|
131
147
|
const minPadding = 10;
|
|
132
148
|
this.buttonPosition = {
|
|
133
149
|
x: Math.max(minPadding, Math.min(this.buttonPosition.x, windowWidth - buttonWidth - minPadding)),
|
|
134
|
-
y: Math.max(minPadding, Math.min(this.buttonPosition.y, windowHeight - buttonHeight - minPadding))
|
|
150
|
+
y: Math.max(minPadding, Math.min(this.buttonPosition.y, windowHeight - buttonHeight - minPadding)),
|
|
135
151
|
};
|
|
136
152
|
this.updateHostPosition();
|
|
137
153
|
}
|
|
@@ -149,7 +165,7 @@ export class OcsChat {
|
|
|
149
165
|
const rect = this.host.getBoundingClientRect();
|
|
150
166
|
this.buttonDragOffset = {
|
|
151
167
|
x: pointer.clientX - rect.left,
|
|
152
|
-
y: pointer.clientY - rect.top
|
|
168
|
+
y: pointer.clientY - rect.top,
|
|
153
169
|
};
|
|
154
170
|
this.addButtonEventListeners();
|
|
155
171
|
};
|
|
@@ -166,7 +182,7 @@ export class OcsChat {
|
|
|
166
182
|
const rect = this.host.getBoundingClientRect();
|
|
167
183
|
this.buttonDragOffset = {
|
|
168
184
|
x: pointer.clientX - rect.left,
|
|
169
|
-
y: pointer.clientY - rect.top
|
|
185
|
+
y: pointer.clientY - rect.top,
|
|
170
186
|
};
|
|
171
187
|
this.addButtonEventListeners();
|
|
172
188
|
};
|
|
@@ -213,6 +229,9 @@ export class OcsChat {
|
|
|
213
229
|
this.error = 'Chatbot ID is required';
|
|
214
230
|
return;
|
|
215
231
|
}
|
|
232
|
+
if (this.isKioskMode()) {
|
|
233
|
+
this.visible = true;
|
|
234
|
+
}
|
|
216
235
|
await this.initializeTranslations();
|
|
217
236
|
// Always try to load existing session if localStorage is available
|
|
218
237
|
if (this.persistentSession && this.isLocalStorageAvailable()) {
|
|
@@ -235,11 +254,20 @@ export class OcsChat {
|
|
|
235
254
|
this.chatWindowWidth = varToPixels(windowWidthVar, window.innerWidth, this.chatWindowWidth);
|
|
236
255
|
this.chatWindowFullscreenWidth = varToPixels(fullscreenWidthVar, window.innerWidth, this.chatWindowFullscreenWidth);
|
|
237
256
|
// Initialize button position from computed styles
|
|
238
|
-
this.
|
|
239
|
-
|
|
257
|
+
if (this.showButton && !this.isKioskMode()) {
|
|
258
|
+
this.initializeButtonPosition();
|
|
259
|
+
}
|
|
260
|
+
// Defer state changes to avoid triggering them during componentDidLoad
|
|
240
261
|
setTimeout(() => {
|
|
262
|
+
// Restore visible state after dimensions are read so initializePosition
|
|
263
|
+
// uses the correct CSS-derived chatWindowWidth/chatWindowHeight.
|
|
264
|
+
if (!this.isKioskMode() && this.showButton && this.persistentSession && this.isLocalStorageAvailable()) {
|
|
265
|
+
this.restoreVisibleState();
|
|
266
|
+
}
|
|
241
267
|
if (this.visible) {
|
|
242
|
-
this.
|
|
268
|
+
if (!this.isKioskMode()) {
|
|
269
|
+
this.initializePosition();
|
|
270
|
+
}
|
|
243
271
|
}
|
|
244
272
|
// Resume polling for existing session (don't auto-start new sessions)
|
|
245
273
|
if (this.visible && this.sessionId) {
|
|
@@ -272,7 +300,7 @@ export class OcsChat {
|
|
|
272
300
|
created_at: new Date().toISOString(),
|
|
273
301
|
role: 'system',
|
|
274
302
|
content: `**Error:** ${errorText}\nPlease try again.`,
|
|
275
|
-
attachments: []
|
|
303
|
+
attachments: [],
|
|
276
304
|
};
|
|
277
305
|
this.messages = [...this.messages, errorMessage];
|
|
278
306
|
this.saveSessionToStorage();
|
|
@@ -322,7 +350,7 @@ export class OcsChat {
|
|
|
322
350
|
return;
|
|
323
351
|
}
|
|
324
352
|
if (typeof this.pageContext !== 'object' || Array.isArray(this.pageContext)) {
|
|
325
|
-
console.error(
|
|
353
|
+
console.error('pageContext is expected to be a plain JavaScript object.');
|
|
326
354
|
return;
|
|
327
355
|
}
|
|
328
356
|
this.internalPageContext = this.pageContext;
|
|
@@ -350,6 +378,7 @@ export class OcsChat {
|
|
|
350
378
|
this.currentPollTaskId = '';
|
|
351
379
|
}
|
|
352
380
|
async startSession() {
|
|
381
|
+
const epoch = this.sessionEpoch;
|
|
353
382
|
try {
|
|
354
383
|
this.isLoading = true;
|
|
355
384
|
const userId = this.getOrGenerateUserId();
|
|
@@ -357,19 +386,26 @@ export class OcsChat {
|
|
|
357
386
|
chatbot_id: this.chatbotId,
|
|
358
387
|
session_data: {
|
|
359
388
|
source: 'widget',
|
|
360
|
-
page_url: window.location.href
|
|
389
|
+
page_url: window.location.href,
|
|
361
390
|
},
|
|
362
|
-
participant_remote_id: userId
|
|
391
|
+
participant_remote_id: userId,
|
|
363
392
|
};
|
|
364
393
|
if (this.userName) {
|
|
365
394
|
requestBody.participant_name = this.userName;
|
|
366
395
|
}
|
|
396
|
+
if (this.versionNumber != null) {
|
|
397
|
+
requestBody.version_number = this.versionNumber;
|
|
398
|
+
}
|
|
367
399
|
const data = await this.getChatService().startSession(requestBody);
|
|
400
|
+
if (epoch !== this.sessionEpoch)
|
|
401
|
+
return;
|
|
368
402
|
this.sessionId = data.session_id;
|
|
369
403
|
this.saveSessionToStorage();
|
|
370
404
|
this.startMessagePolling();
|
|
371
405
|
}
|
|
372
406
|
catch (_error) {
|
|
407
|
+
if (epoch !== this.sessionEpoch)
|
|
408
|
+
return;
|
|
373
409
|
this.handleError('Failed to start chat session');
|
|
374
410
|
}
|
|
375
411
|
finally {
|
|
@@ -398,6 +434,7 @@ export class OcsChat {
|
|
|
398
434
|
async sendMessage(message) {
|
|
399
435
|
if (!message.trim())
|
|
400
436
|
return;
|
|
437
|
+
const epoch = this.sessionEpoch;
|
|
401
438
|
// Start session if we don't have one yet
|
|
402
439
|
if (!this.sessionId) {
|
|
403
440
|
// Prevent concurrent session initialization
|
|
@@ -431,7 +468,7 @@ export class OcsChat {
|
|
|
431
468
|
created_at: new Date(now.getTime() - (welcomeMessagesToAdd.length - index) * 1000).toISOString(),
|
|
432
469
|
role: 'assistant',
|
|
433
470
|
content: welcomeMsg,
|
|
434
|
-
attachments: []
|
|
471
|
+
attachments: [],
|
|
435
472
|
}));
|
|
436
473
|
this.messages = [...this.messages, ...welcomeMessages];
|
|
437
474
|
}
|
|
@@ -440,13 +477,15 @@ export class OcsChat {
|
|
|
440
477
|
created_at: new Date().toISOString(),
|
|
441
478
|
role: 'user',
|
|
442
479
|
content: message.trim(),
|
|
443
|
-
attachments: this.allowAttachments
|
|
444
|
-
|
|
445
|
-
|
|
446
|
-
|
|
447
|
-
|
|
448
|
-
|
|
449
|
-
|
|
480
|
+
attachments: this.allowAttachments
|
|
481
|
+
? this.selectedFiles
|
|
482
|
+
.filter(sf => !sf.error && sf.uploaded)
|
|
483
|
+
.map(sf => ({
|
|
484
|
+
name: sf.file.name,
|
|
485
|
+
content_type: sf.file.type,
|
|
486
|
+
size: sf.file.size,
|
|
487
|
+
}))
|
|
488
|
+
: [],
|
|
450
489
|
};
|
|
451
490
|
this.messages = [...this.messages, userMessage];
|
|
452
491
|
this.saveSessionToStorage();
|
|
@@ -462,7 +501,12 @@ export class OcsChat {
|
|
|
462
501
|
if (this.internalPageContext) {
|
|
463
502
|
requestBody.context = this.internalPageContext;
|
|
464
503
|
}
|
|
504
|
+
if (this.versionNumber != null) {
|
|
505
|
+
requestBody.version_number = this.versionNumber;
|
|
506
|
+
}
|
|
465
507
|
const data = await this.getChatService().sendMessage(this.sessionId, requestBody);
|
|
508
|
+
if (epoch !== this.sessionEpoch)
|
|
509
|
+
return;
|
|
466
510
|
if (data.status === 'error') {
|
|
467
511
|
throw new Error(data.error || 'Failed to send message');
|
|
468
512
|
}
|
|
@@ -470,6 +514,8 @@ export class OcsChat {
|
|
|
470
514
|
this.startTaskPolling(data.task_id);
|
|
471
515
|
}
|
|
472
516
|
catch (error) {
|
|
517
|
+
if (epoch !== this.sessionEpoch)
|
|
518
|
+
return;
|
|
473
519
|
const errorText = error instanceof Error ? error.message : 'Failed to send message';
|
|
474
520
|
this.handleError(errorText);
|
|
475
521
|
}
|
|
@@ -492,10 +538,10 @@ export class OcsChat {
|
|
|
492
538
|
const childRect = lastChild.getBoundingClientRect();
|
|
493
539
|
const currentScrollTop = this.messageListRef.scrollTop;
|
|
494
540
|
const childTopRelativeToParent = childRect.top - parentRect.top;
|
|
495
|
-
const targetScroll = currentScrollTop + childTopRelativeToParent -
|
|
541
|
+
const targetScroll = currentScrollTop + childTopRelativeToParent - parentRect.height / 2;
|
|
496
542
|
this.messageListRef.scrollTo({
|
|
497
543
|
top: targetScroll,
|
|
498
|
-
behavior: 'smooth'
|
|
544
|
+
behavior: 'smooth',
|
|
499
545
|
});
|
|
500
546
|
}
|
|
501
547
|
else {
|
|
@@ -540,10 +586,10 @@ export class OcsChat {
|
|
|
540
586
|
const k = 1024;
|
|
541
587
|
if (bytes < k * k) {
|
|
542
588
|
// Less than 1MB, show in KB
|
|
543
|
-
return Math.round(bytes / k * 100) / 100 + ' KB';
|
|
589
|
+
return Math.round((bytes / k) * 100) / 100 + ' KB';
|
|
544
590
|
}
|
|
545
591
|
else {
|
|
546
|
-
return Math.round(bytes / (k * k) * 100) / 100 + ' MB';
|
|
592
|
+
return Math.round((bytes / (k * k)) * 100) / 100 + ' MB';
|
|
547
593
|
}
|
|
548
594
|
}
|
|
549
595
|
formatTime(dateString) {
|
|
@@ -561,19 +607,30 @@ export class OcsChat {
|
|
|
561
607
|
pageContextHandler() {
|
|
562
608
|
this.loadInternalPageContext();
|
|
563
609
|
}
|
|
610
|
+
async chatbotConfigHandler() {
|
|
611
|
+
await this.clearSession();
|
|
612
|
+
}
|
|
564
613
|
/**
|
|
565
614
|
* Watch for changes to the `visible` attribute and update accordingly.
|
|
566
615
|
*
|
|
567
616
|
* @param visible - The new value for the field.
|
|
568
617
|
*/
|
|
569
618
|
async visibilityHandler(visible) {
|
|
619
|
+
// Kiosk mode is always visible
|
|
620
|
+
if (this.isKioskMode() && !visible) {
|
|
621
|
+
this.visible = true;
|
|
622
|
+
return;
|
|
623
|
+
}
|
|
624
|
+
this.saveVisibleState(visible);
|
|
570
625
|
if (this.isButtonDragging) {
|
|
571
626
|
this.isButtonDragging = false;
|
|
572
627
|
this.buttonWasDragged = false;
|
|
573
628
|
this.removeButtonEventListeners();
|
|
574
629
|
}
|
|
575
630
|
if (visible) {
|
|
576
|
-
this.
|
|
631
|
+
if (!this.isKioskMode()) {
|
|
632
|
+
this.initializePosition();
|
|
633
|
+
}
|
|
577
634
|
// Resume polling for existing session (don't auto-start new sessions)
|
|
578
635
|
if (this.sessionId) {
|
|
579
636
|
this.scrollToBottom(true);
|
|
@@ -594,37 +651,43 @@ export class OcsChat {
|
|
|
594
651
|
this.taskPollingHandle.cancel();
|
|
595
652
|
}
|
|
596
653
|
this.taskPollingHandle = this.getChatService().pollTask(this.sessionId, taskId, {
|
|
597
|
-
onMessage:
|
|
654
|
+
onMessage: message => {
|
|
598
655
|
this.messages = [...this.messages, message];
|
|
599
656
|
this.saveSessionToStorage();
|
|
600
657
|
this.scrollToBottom();
|
|
601
658
|
this.isTyping = false;
|
|
659
|
+
this.typingProgressMessage = '';
|
|
602
660
|
this.currentPollTaskId = '';
|
|
603
661
|
this.taskPollingHandle = undefined;
|
|
604
662
|
this.startMessagePolling();
|
|
605
663
|
this.focusInput();
|
|
606
664
|
},
|
|
665
|
+
onProgress: message => {
|
|
666
|
+
this.typingProgressMessage = message;
|
|
667
|
+
},
|
|
607
668
|
onTimeout: () => {
|
|
608
669
|
const timeoutMessage = {
|
|
609
670
|
created_at: new Date().toISOString(),
|
|
610
671
|
role: 'system',
|
|
611
672
|
content: 'The response is taking longer than expected. The system may be experiencing delays. Please try sending your message again.',
|
|
612
|
-
attachments: []
|
|
673
|
+
attachments: [],
|
|
613
674
|
};
|
|
614
675
|
this.messages = [...this.messages, timeoutMessage];
|
|
615
676
|
this.saveSessionToStorage();
|
|
616
677
|
this.scrollToBottom();
|
|
617
678
|
this.isTyping = false;
|
|
679
|
+
this.typingProgressMessage = '';
|
|
618
680
|
this.currentPollTaskId = '';
|
|
619
681
|
this.taskPollingHandle = undefined;
|
|
620
682
|
this.startMessagePolling();
|
|
621
683
|
this.focusInput();
|
|
622
684
|
},
|
|
623
|
-
onError:
|
|
685
|
+
onError: error => {
|
|
686
|
+
this.typingProgressMessage = '';
|
|
624
687
|
this.handleError(error.message);
|
|
625
688
|
this.taskPollingHandle = undefined;
|
|
626
689
|
this.startMessagePolling();
|
|
627
|
-
}
|
|
690
|
+
},
|
|
628
691
|
});
|
|
629
692
|
}
|
|
630
693
|
startMessagePolling() {
|
|
@@ -635,8 +698,8 @@ export class OcsChat {
|
|
|
635
698
|
return;
|
|
636
699
|
}
|
|
637
700
|
this.messagePollingHandle = this.getChatService().startMessagePolling(this.sessionId, {
|
|
638
|
-
getSince: () => { var _a; return this.messages.length > 0 ? (_a = this.messages.at(-1)) === null || _a === void 0 ? void 0 : _a.created_at : undefined; },
|
|
639
|
-
onMessages:
|
|
701
|
+
getSince: () => { var _a; return (this.messages.length > 0 ? (_a = this.messages.at(-1)) === null || _a === void 0 ? void 0 : _a.created_at : undefined); },
|
|
702
|
+
onMessages: messages => {
|
|
640
703
|
if (messages.length === 0)
|
|
641
704
|
return;
|
|
642
705
|
this.messages = [...this.messages, ...messages];
|
|
@@ -646,7 +709,7 @@ export class OcsChat {
|
|
|
646
709
|
},
|
|
647
710
|
onError: () => {
|
|
648
711
|
// Silently ignore polling errors to match previous behaviour
|
|
649
|
-
}
|
|
712
|
+
},
|
|
650
713
|
});
|
|
651
714
|
}
|
|
652
715
|
stopMessagePolling() {
|
|
@@ -665,6 +728,9 @@ export class OcsChat {
|
|
|
665
728
|
this.position = position;
|
|
666
729
|
}
|
|
667
730
|
getPositionClasses() {
|
|
731
|
+
if (this.isKioskMode()) {
|
|
732
|
+
return 'chat-window-kiosk';
|
|
733
|
+
}
|
|
668
734
|
if (this.isFullscreen) {
|
|
669
735
|
return 'chat-window-fullscreen';
|
|
670
736
|
}
|
|
@@ -680,6 +746,9 @@ export class OcsChat {
|
|
|
680
746
|
return { windowWidth, actualChatWidth, centeredX, maxOffset };
|
|
681
747
|
}
|
|
682
748
|
getPositionStyles() {
|
|
749
|
+
if (this.isKioskMode()) {
|
|
750
|
+
return {};
|
|
751
|
+
}
|
|
683
752
|
if (this.isFullscreen) {
|
|
684
753
|
const { centeredX } = this.getFullscreenBounds();
|
|
685
754
|
const finalX = centeredX + this.fullscreenPosition.x;
|
|
@@ -711,19 +780,19 @@ export class OcsChat {
|
|
|
711
780
|
case 'left':
|
|
712
781
|
this.windowPosition = {
|
|
713
782
|
x: OcsChat.WINDOW_MARGIN,
|
|
714
|
-
y: windowHeight - this.chatWindowHeight - OcsChat.WINDOW_MARGIN
|
|
783
|
+
y: windowHeight - this.chatWindowHeight - OcsChat.WINDOW_MARGIN,
|
|
715
784
|
};
|
|
716
785
|
break;
|
|
717
786
|
case 'right':
|
|
718
787
|
this.windowPosition = {
|
|
719
788
|
x: windowWidth - chatWidth - OcsChat.WINDOW_MARGIN,
|
|
720
|
-
y: windowHeight - this.chatWindowHeight - OcsChat.WINDOW_MARGIN
|
|
789
|
+
y: windowHeight - this.chatWindowHeight - OcsChat.WINDOW_MARGIN,
|
|
721
790
|
};
|
|
722
791
|
break;
|
|
723
792
|
case 'center':
|
|
724
793
|
this.windowPosition = {
|
|
725
794
|
x: (windowWidth - chatWidth) / 2,
|
|
726
|
-
y: (windowHeight - this.chatWindowHeight) / 2
|
|
795
|
+
y: (windowHeight - this.chatWindowHeight) / 2,
|
|
727
796
|
};
|
|
728
797
|
break;
|
|
729
798
|
}
|
|
@@ -746,14 +815,14 @@ export class OcsChat {
|
|
|
746
815
|
// For fullscreen, track relative to current position
|
|
747
816
|
this.dragOffset = {
|
|
748
817
|
x: pointer.clientX,
|
|
749
|
-
y: pointer.clientY
|
|
818
|
+
y: pointer.clientY,
|
|
750
819
|
};
|
|
751
820
|
}
|
|
752
821
|
else {
|
|
753
822
|
const rect = this.chatWindowRef.getBoundingClientRect();
|
|
754
823
|
this.dragOffset = {
|
|
755
824
|
x: pointer.clientX - rect.left,
|
|
756
|
-
y: pointer.clientY - rect.top
|
|
825
|
+
y: pointer.clientY - rect.top,
|
|
757
826
|
};
|
|
758
827
|
}
|
|
759
828
|
}
|
|
@@ -765,7 +834,7 @@ export class OcsChat {
|
|
|
765
834
|
const { maxOffset } = this.getFullscreenBounds();
|
|
766
835
|
const deltaX = pointer.clientX - this.dragOffset.x;
|
|
767
836
|
this.fullscreenPosition = {
|
|
768
|
-
x: Math.max(-maxOffset, Math.min(maxOffset, deltaX))
|
|
837
|
+
x: Math.max(-maxOffset, Math.min(maxOffset, deltaX)),
|
|
769
838
|
};
|
|
770
839
|
}
|
|
771
840
|
else {
|
|
@@ -778,7 +847,7 @@ export class OcsChat {
|
|
|
778
847
|
const chatHeight = this.chatWindowRef.offsetHeight;
|
|
779
848
|
this.windowPosition = {
|
|
780
849
|
x: Math.max(0, Math.min(newX, windowWidth - chatWidth)),
|
|
781
|
-
y: Math.max(0, Math.min(newY, windowHeight - chatHeight))
|
|
850
|
+
y: Math.max(0, Math.min(newY, windowHeight - chatHeight)),
|
|
782
851
|
};
|
|
783
852
|
}
|
|
784
853
|
}
|
|
@@ -825,7 +894,7 @@ export class OcsChat {
|
|
|
825
894
|
const verticalValue = this.buttonVerticalSide === 'top' ? resolvedTop : resolvedBottom;
|
|
826
895
|
this.buttonPosition = {
|
|
827
896
|
x: horizontalValue,
|
|
828
|
-
y: verticalValue
|
|
897
|
+
y: verticalValue,
|
|
829
898
|
};
|
|
830
899
|
// Apply the position to the host
|
|
831
900
|
this.updateHostPosition();
|
|
@@ -868,12 +937,8 @@ export class OcsChat {
|
|
|
868
937
|
const maxTop = windowHeight - buttonHeight - minPadding;
|
|
869
938
|
const constrainedLeft = Math.max(minLeft, Math.min(candidateLeft, maxLeft));
|
|
870
939
|
const constrainedTop = Math.max(minTop, Math.min(candidateTop, maxTop));
|
|
871
|
-
const newHorizontalValue = this.buttonHorizontalSide === 'left'
|
|
872
|
-
|
|
873
|
-
: Math.max(minPadding, windowWidth - (constrainedLeft + buttonWidth));
|
|
874
|
-
const newVerticalValue = this.buttonVerticalSide === 'top'
|
|
875
|
-
? constrainedTop
|
|
876
|
-
: Math.max(minPadding, windowHeight - (constrainedTop + buttonHeight));
|
|
940
|
+
const newHorizontalValue = this.buttonHorizontalSide === 'left' ? constrainedLeft : Math.max(minPadding, windowWidth - (constrainedLeft + buttonWidth));
|
|
941
|
+
const newVerticalValue = this.buttonVerticalSide === 'top' ? constrainedTop : Math.max(minPadding, windowHeight - (constrainedTop + buttonHeight));
|
|
877
942
|
if (newHorizontalValue !== this.buttonPosition.x || newVerticalValue !== this.buttonPosition.y) {
|
|
878
943
|
this.buttonWasDragged = true;
|
|
879
944
|
this.buttonPosition = { x: newHorizontalValue, y: newVerticalValue };
|
|
@@ -936,16 +1001,12 @@ export class OcsChat {
|
|
|
936
1001
|
return fallback;
|
|
937
1002
|
}
|
|
938
1003
|
getWelcomeMessages() {
|
|
939
|
-
const translated = this.translationManager.getArray(
|
|
940
|
-
return translated && translated.length > 0
|
|
941
|
-
? translated
|
|
942
|
-
: this.parsedWelcomeMessages;
|
|
1004
|
+
const translated = this.translationManager.getArray('content.welcomeMessages');
|
|
1005
|
+
return translated && translated.length > 0 ? translated : this.parsedWelcomeMessages;
|
|
943
1006
|
}
|
|
944
1007
|
getStarterQuestions() {
|
|
945
|
-
const translated = this.translationManager.getArray(
|
|
946
|
-
return translated && translated.length > 0
|
|
947
|
-
? translated
|
|
948
|
-
: this.parsedStarterQuestions;
|
|
1008
|
+
const translated = this.translationManager.getArray('content.starterQuestions');
|
|
1009
|
+
return translated && translated.length > 0 ? translated : this.parsedStarterQuestions;
|
|
949
1010
|
}
|
|
950
1011
|
getButtonClasses() {
|
|
951
1012
|
const buttonText = this.translationManager.get('branding.buttonText', this.buttonText);
|
|
@@ -956,6 +1017,9 @@ export class OcsChat {
|
|
|
956
1017
|
}
|
|
957
1018
|
renderButton() {
|
|
958
1019
|
var _a;
|
|
1020
|
+
if (!this.showButton || this.isKioskMode()) {
|
|
1021
|
+
return null;
|
|
1022
|
+
}
|
|
959
1023
|
const buttonText = this.translationManager.get('branding.buttonText', this.buttonText);
|
|
960
1024
|
const hasText = !!(buttonText && buttonText.trim());
|
|
961
1025
|
const hasCustomIcon = this.iconUrl && this.iconUrl.trim();
|
|
@@ -965,21 +1029,24 @@ export class OcsChat {
|
|
|
965
1029
|
const buttonAriaLabel = finalButtonText ? `${openLabel} - ${finalButtonText}` : openLabel;
|
|
966
1030
|
// Only show drag cursor if button is draggable
|
|
967
1031
|
const isDraggable = this.isButtonDraggable();
|
|
968
|
-
const buttonStyle = isDraggable
|
|
969
|
-
|
|
970
|
-
|
|
1032
|
+
const buttonStyle = isDraggable
|
|
1033
|
+
? {
|
|
1034
|
+
cursor: this.isButtonDragging ? 'grabbing' : 'grab',
|
|
1035
|
+
}
|
|
1036
|
+
: {};
|
|
971
1037
|
if (hasText) {
|
|
972
|
-
return (h("button", { ref:
|
|
1038
|
+
return (h("button", { ref: el => (this.buttonRef = el), class: buttonClasses, "aria-label": buttonAriaLabel, title: finalButtonText || openLabel, style: buttonStyle, onClick: () => this.handleButtonClick(), onMouseDown: e => this.handleButtonMouseDown(e), onTouchStart: e => this.handleButtonTouchStart(e), "aria-grabbed": this.isButtonDragging, "aria-describedby": isDraggable ? 'chat-button-drag-hint' : undefined }, hasCustomIcon ? h("img", { src: this.iconUrl, alt: "" }) : h(OcsWidgetAvatar, null), h("span", null, finalButtonText), isDraggable && (h("span", { id: "chat-button-drag-hint", style: { display: 'none' } }, "Draggable. Use mouse or touch to reposition."))));
|
|
973
1039
|
}
|
|
974
1040
|
else {
|
|
975
|
-
return (h("button", { ref:
|
|
1041
|
+
return (h("button", { ref: el => (this.buttonRef = el), class: buttonClasses, "aria-label": openLabel, title: openLabel, style: buttonStyle, onClick: () => this.handleButtonClick(), onMouseDown: e => this.handleButtonMouseDown(e), onTouchStart: e => this.handleButtonTouchStart(e), "aria-grabbed": this.isButtonDragging, "aria-describedby": isDraggable ? 'chat-button-drag-hint' : undefined }, hasCustomIcon ? h("img", { src: this.iconUrl, alt: "" }) : h(OcsWidgetAvatar, null), isDraggable && (h("span", { id: "chat-button-drag-hint", style: { display: 'none' } }, "Draggable. Use mouse or touch to reposition."))));
|
|
976
1042
|
}
|
|
977
1043
|
}
|
|
978
1044
|
getStorageKeys() {
|
|
979
1045
|
return {
|
|
980
1046
|
sessionId: `ocs-chat-session-${this.chatbotId}`,
|
|
981
1047
|
messages: `ocs-chat-messages-${this.chatbotId}`,
|
|
982
|
-
lastActivity: `ocs-chat-activity-${this.chatbotId}
|
|
1048
|
+
lastActivity: `ocs-chat-activity-${this.chatbotId}`,
|
|
1049
|
+
visible: `ocs-chat-visible-${this.chatbotId}`,
|
|
983
1050
|
};
|
|
984
1051
|
}
|
|
985
1052
|
saveSessionToStorage() {
|
|
@@ -1042,30 +1109,70 @@ export class OcsChat {
|
|
|
1042
1109
|
return this.generatedUserId;
|
|
1043
1110
|
}
|
|
1044
1111
|
const storageKey = `ocs-user-id`;
|
|
1045
|
-
|
|
1112
|
+
let stored = null;
|
|
1113
|
+
try {
|
|
1114
|
+
stored = localStorage.getItem(storageKey);
|
|
1115
|
+
}
|
|
1116
|
+
catch (_a) {
|
|
1117
|
+
// localStorage blocked; fall through to in-memory id generation
|
|
1118
|
+
}
|
|
1046
1119
|
if (stored) {
|
|
1047
1120
|
this.generatedUserId = stored;
|
|
1048
1121
|
return stored;
|
|
1049
1122
|
}
|
|
1050
1123
|
const array = new Uint8Array(9);
|
|
1051
1124
|
window.crypto.getRandomValues(array);
|
|
1052
|
-
const randomString = Array.from(array, byte => byte.toString(36))
|
|
1125
|
+
const randomString = Array.from(array, byte => byte.toString(36))
|
|
1126
|
+
.join('')
|
|
1127
|
+
.substr(0, 9);
|
|
1053
1128
|
const newUserId = `ocs:${Date.now()}_${randomString}`;
|
|
1054
1129
|
this.generatedUserId = newUserId;
|
|
1055
|
-
|
|
1130
|
+
try {
|
|
1131
|
+
localStorage.setItem(storageKey, newUserId);
|
|
1132
|
+
}
|
|
1133
|
+
catch (_b) {
|
|
1134
|
+
// localStorage blocked; the generated id lives in component state for this page
|
|
1135
|
+
}
|
|
1056
1136
|
return newUserId;
|
|
1057
1137
|
}
|
|
1138
|
+
saveVisibleState(visible) {
|
|
1139
|
+
if (!this.persistentSession)
|
|
1140
|
+
return;
|
|
1141
|
+
try {
|
|
1142
|
+
const keys = this.getStorageKeys();
|
|
1143
|
+
localStorage.setItem(keys.visible, visible ? '1' : '0');
|
|
1144
|
+
}
|
|
1145
|
+
catch (_a) {
|
|
1146
|
+
// ignore
|
|
1147
|
+
}
|
|
1148
|
+
}
|
|
1149
|
+
restoreVisibleState() {
|
|
1150
|
+
try {
|
|
1151
|
+
const keys = this.getStorageKeys();
|
|
1152
|
+
const stored = localStorage.getItem(keys.visible);
|
|
1153
|
+
if (stored === '1') {
|
|
1154
|
+
this.visible = true;
|
|
1155
|
+
}
|
|
1156
|
+
}
|
|
1157
|
+
catch (_a) {
|
|
1158
|
+
// ignore
|
|
1159
|
+
}
|
|
1160
|
+
}
|
|
1058
1161
|
clearSessionStorage() {
|
|
1059
1162
|
const keys = this.getStorageKeys();
|
|
1060
1163
|
try {
|
|
1061
1164
|
localStorage.removeItem(keys.sessionId);
|
|
1062
1165
|
localStorage.removeItem(keys.messages);
|
|
1063
1166
|
localStorage.removeItem(keys.lastActivity);
|
|
1167
|
+
localStorage.removeItem(keys.visible);
|
|
1064
1168
|
}
|
|
1065
1169
|
catch (error) {
|
|
1066
1170
|
console.warn('Failed to clear chat session from localStorage:', error);
|
|
1067
1171
|
}
|
|
1068
1172
|
}
|
|
1173
|
+
isKioskMode() {
|
|
1174
|
+
return this.mode === 'kiosk';
|
|
1175
|
+
}
|
|
1069
1176
|
isLocalStorageAvailable() {
|
|
1070
1177
|
try {
|
|
1071
1178
|
localStorage.setItem(OcsChat.LOCALSTORAGE_TEST_KEY, 'test');
|
|
@@ -1091,6 +1198,7 @@ export class OcsChat {
|
|
|
1091
1198
|
* will start when the user sends a message.
|
|
1092
1199
|
*/
|
|
1093
1200
|
async clearSession() {
|
|
1201
|
+
this.sessionEpoch += 1;
|
|
1094
1202
|
this.clearSessionStorage();
|
|
1095
1203
|
this.sessionId = undefined;
|
|
1096
1204
|
this.messages = [];
|
|
@@ -1111,18 +1219,12 @@ export class OcsChat {
|
|
|
1111
1219
|
if (this.error && !this.sessionId) {
|
|
1112
1220
|
return (h(Host, null, h("p", { class: "error-message" }, this.error)));
|
|
1113
1221
|
}
|
|
1114
|
-
return (h(Host, null, this.renderButton(), this.visible && (h("div", { ref:
|
|
1115
|
-
? 'message-bubble-user'
|
|
1116
|
-
: message.role === 'assistant'
|
|
1117
|
-
? 'message-bubble-assistant'
|
|
1118
|
-
: 'message-bubble-system'}` }, h("div", { class: "chat-markdown", innerHTML: renderMarkdownComplete(message.content) }), message.attachments && message.attachments.length > 0 && (h("div", { class: "message-attachments" }, message.attachments.map((attachment, attachmentIndex) => (h("div", { key: attachmentIndex, class: "flex items-center gap-[0.5em]" }, h("span", { class: "message-attachment-icon" }, h(PaperClipIcon, null)), h("span", { class: "message-attachment-name" }, attachment.name)))))), h("div", { class: "message-timestamp" }, this.formatTime(message.created_at)))))), this.isTyping && (h("div", null, h("div", { class: "typing-indicator" }, h("div", { class: "typing-progress" })), h("div", { class: "typing-text" }, h("span", null, this.translationManager.get('status.typing', this.typingIndicatorText)), h("span", { class: "typing-dots loading" })))))), this.messages.length === 0 && this.getStarterQuestions().length > 0 && (h("div", { class: "starter-questions" }, this.getStarterQuestions().map((question, index) => (h("div", { key: `starter-${index}`, class: "starter-question-row" }, h("button", { class: "starter-question", onClick: () => this.handleStarterQuestionClick(question) }, question)))))), this.allowAttachments && this.selectedFiles.length > 0 && (h("div", { class: "selected-files-container" }, h("div", { class: "space-y-[0.25em]" }, this.selectedFiles.map((selectedFile, index) => (h("div", { key: index, class: "selected-file-item" }, h("div", { class: "flex items-center gap-[0.5em]" }, h("span", { class: "selected-file-icon" }, h(PaperClipIcon, null)), h("span", null, selectedFile.file.name), h("span", { class: "selected-file-size" }, "(", this.formatFileSize(selectedFile.file.size), ")"), selectedFile.error && (h("span", { class: "selected-file-error" }, selectedFile.error)), selectedFile.uploaded && (h("span", { class: "selected-file-success-icon" }, h(CheckDocumentIcon, null)))), h("button", { onClick: () => this.removeSelectedFile(index), class: "selected-file-remove-button", "aria-label": this.translationManager.get('attach.remove') }, h(XIcon, null)))))))), h("div", { class: "input-area" }, h("div", { class: "input-container" }, h("textarea", { ref: (el) => this.textareaRef = el, class: "message-textarea", rows: 1, placeholder: this.translationManager.get('composer.placeholder'), value: this.messageInput, onInput: (e) => this.handleInputChange(e), onKeyPress: (e) => this.handleKeyPress(e), disabled: this.isTyping || this.isUploadingFiles || this.isLoading }), this.allowAttachments && (h("input", { ref: (el) => {
|
|
1222
|
+
return (h(Host, null, this.renderButton(), this.visible && (h("div", { ref: el => (this.chatWindowRef = el), id: "ocs-chat-window", class: this.getPositionClasses(), style: this.getPositionStyles() }, !this.isKioskMode() && (h("div", { class: `chat-header ${this.isDragging ? 'chat-header-dragging' : 'chat-header-draggable'}`, onMouseDown: this.handleMouseDown, onTouchStart: this.handleTouchStart }, h("div", { class: "drag-indicator" }, h("div", { class: "drag-dots header-button" }, h(GripDotsVerticalIcon, null))), h("div", { class: "header-text" }, this.translationManager.get('branding.headerText', this.headerText)), h("div", { class: "header-buttons" }, this.messages.length > 0 && (h("button", { class: "header-button", onClick: () => this.showConfirmationDialog(), title: this.translationManager.get('window.newChat'), "aria-label": this.translationManager.get('window.newChat') }, h(PlusWithCircleIcon, null))), this.allowFullScreen && (h("button", { class: "header-button fullscreen-button", onClick: () => this.toggleFullscreen(), title: this.isFullscreen ? this.translationManager.get('window.exitFullscreen') : this.translationManager.get('window.fullscreen'), "aria-label": this.isFullscreen ? this.translationManager.get('window.exitFullscreen') : this.translationManager.get('window.fullscreen') }, this.isFullscreen ? h(ArrowsPointingInIcon, null) : h(ArrowsPointingOutIcon, null))), h("button", { class: "header-button", onClick: () => (this.visible = false), "aria-label": this.translationManager.get('window.close') }, h(XMarkIcon, null))))), !this.isKioskMode() && this.showNewChatConfirmation && (h("div", { class: "confirmation-overlay" }, h("div", { class: "confirmation-dialog" }, h("div", { class: "confirmation-content" }, h("h3", { class: "confirmation-title" }, this.translationManager.get('modal.newChatTitle')), h("p", { class: "confirmation-message" }, this.translationManager.get('modal.newChatBody', this.newChatConfirmationMessage)), h("div", { class: "confirmation-buttons" }, h("button", { class: "confirmation-button confirmation-button-cancel", onClick: () => this.hideConfirmationDialog() }, this.translationManager.get('modal.cancel')), h("button", { class: "confirmation-button confirmation-button-confirm", onClick: () => this.confirmNewChat() }, this.translationManager.get('modal.confirm'))))))), h("div", { class: "chat-content" }, this.isLoading && !this.sessionId && (h("div", { class: "loading-container" }, h("div", { class: "loading-spinner" }), h("span", { class: "loading-text" }, this.translationManager.get('status.starting')))), h("div", { ref: el => (this.messageListRef = el), class: "messages-container" }, this.messages.length === 0 && this.getWelcomeMessages().length > 0 && (h("div", { class: "welcome-messages" }, this.getWelcomeMessages().map((message, index) => (h("div", { key: `welcome-${index}`, class: "message-row message-row-assistant" }, h("div", { class: "message-bubble message-bubble-assistant" }, h("div", { class: "chat-markdown", innerHTML: renderMarkdownComplete(message) }))))))), this.messages.map((message, index) => (h("div", { key: index, class: `message-row ${message.role === 'user' ? 'message-row-user' : 'message-row-assistant'}` }, h("div", { class: `message-bubble ${message.role === 'user' ? 'message-bubble-user' : message.role === 'assistant' ? 'message-bubble-assistant' : 'message-bubble-system'}` }, h("div", { class: "chat-markdown", innerHTML: renderMarkdownComplete(message.content) }), message.attachments && message.attachments.length > 0 && (h("div", { class: "message-attachments" }, message.attachments.map((attachment, attachmentIndex) => (h("div", { key: attachmentIndex, class: "flex items-center gap-[0.5em]" }, h("span", { class: "message-attachment-icon" }, h(PaperClipIcon, null)), h("span", { class: "message-attachment-name" }, attachment.name)))))), h("div", { class: "message-timestamp" }, this.formatTime(message.created_at)))))), this.isTyping && (h("div", null, h("div", { class: "typing-indicator" }, h("div", { class: "typing-progress" })), h("div", { class: "typing-text" }, h("span", null, this.typingProgressMessage || this.translationManager.get('status.typing', this.typingIndicatorText)), h("span", { class: "typing-dots loading" }))))), this.messages.length === 0 && this.getStarterQuestions().length > 0 && (h("div", { class: "starter-questions" }, this.getStarterQuestions().map((question, index) => (h("div", { key: `starter-${index}`, class: "starter-question-row" }, h("button", { class: "starter-question", onClick: () => this.handleStarterQuestionClick(question) }, question)))))), this.allowAttachments && this.selectedFiles.length > 0 && (h("div", { class: "selected-files-container" }, h("div", { class: "space-y-[0.25em]" }, this.selectedFiles.map((selectedFile, index) => (h("div", { key: index, class: "selected-file-item" }, h("div", { class: "flex items-center gap-[0.5em]" }, h("span", { class: "selected-file-icon" }, h(PaperClipIcon, null)), h("span", null, selectedFile.file.name), h("span", { class: "selected-file-size" }, "(", this.formatFileSize(selectedFile.file.size), ")"), selectedFile.error && h("span", { class: "selected-file-error" }, selectedFile.error), selectedFile.uploaded && (h("span", { class: "selected-file-success-icon" }, h(CheckDocumentIcon, null)))), h("button", { onClick: () => this.removeSelectedFile(index), class: "selected-file-remove-button", "aria-label": this.translationManager.get('attach.remove') }, h(XIcon, null)))))))), h("div", { class: "input-area" }, h("div", { class: "input-container" }, h("textarea", { ref: el => (this.textareaRef = el), class: "message-textarea", rows: 1, placeholder: this.translationManager.get('composer.placeholder'), value: this.messageInput, onInput: e => this.handleInputChange(e), onKeyPress: e => this.handleKeyPress(e), disabled: this.isTyping || this.isUploadingFiles || this.isLoading }), this.allowAttachments && (h("input", { ref: el => {
|
|
1119
1223
|
// Unclear why but after removing all attachments this is being set to `null`.
|
|
1120
1224
|
if (el) {
|
|
1121
1225
|
this.fileInputRef = el;
|
|
1122
1226
|
}
|
|
1123
|
-
}, id: "ocs-file-input", type: "file", multiple: true, accept: OcsChat.SUPPORTED_FILE_EXTENSIONS.join(',') + ',text/*', onChange:
|
|
1124
|
-
? 'send-button-enabled'
|
|
1125
|
-
: 'send-button-disabled'}`, onClick: () => this.sendMessage(this.messageInput), disabled: this.isTyping || this.isUploadingFiles || this.isLoading || !this.messageInput.trim() }, this.isUploadingFiles ? `${this.translationManager.get('status.uploading')}...` : this.translationManager.get('composer.send')))), h("div", { class: "flex items-center justify-center text-[0.8em] font-light w-full text-slate-500 py-[2px]" }, h("p", null, this.translationManager.get('branding.poweredBy'), ' ', " ", h("a", { class: "underline", href: "https://www.dimagi.com", target: "_blank" }, "Dimagi"))))))));
|
|
1227
|
+
}, id: "ocs-file-input", type: "file", multiple: true, accept: OcsChat.SUPPORTED_FILE_EXTENSIONS.join(',') + ',text/*', onChange: e => this.handleFileSelect(e), class: "hidden" })), this.allowAttachments && (h("button", { class: "file-attachment-button", onClick: () => { var _a; return (_a = this.fileInputRef) === null || _a === void 0 ? void 0 : _a.click(); }, disabled: this.isTyping || this.isUploadingFiles || this.isLoading, title: this.translationManager.get('attach.add'), "aria-label": this.translationManager.get('attach.add') }, h(PaperClipIcon, null))), h("button", { class: `send-button ${!this.isTyping && !this.isLoading && !!this.messageInput.trim() ? 'send-button-enabled' : 'send-button-disabled'}`, onClick: () => this.sendMessage(this.messageInput), disabled: this.isTyping || this.isUploadingFiles || this.isLoading || !this.messageInput.trim() }, this.isUploadingFiles ? `${this.translationManager.get('status.uploading')}...` : this.translationManager.get('composer.send')))), h("div", { class: "flex items-center justify-center text-[0.8em] font-light w-full text-slate-500 py-[2px]" }, h("p", null, this.translationManager.get('branding.poweredBy'), ' ', h("a", { class: "underline", href: "https://www.dimagi.com", target: "_blank", rel: "noopener noreferrer" }, "Dimagi"))))))));
|
|
1126
1228
|
}
|
|
1127
1229
|
static get is() { return "open-chat-studio-widget"; }
|
|
1128
1230
|
static get encapsulation() { return "shadow"; }
|
|
@@ -1175,7 +1277,7 @@ export class OcsChat {
|
|
|
1175
1277
|
"getter": false,
|
|
1176
1278
|
"setter": false,
|
|
1177
1279
|
"reflect": false,
|
|
1178
|
-
"defaultValue": "
|
|
1280
|
+
"defaultValue": "'https://www.openchatstudio.com'"
|
|
1179
1281
|
},
|
|
1180
1282
|
"buttonText": {
|
|
1181
1283
|
"type": "string",
|
|
@@ -1254,6 +1356,46 @@ export class OcsChat {
|
|
|
1254
1356
|
"reflect": false,
|
|
1255
1357
|
"defaultValue": "'square'"
|
|
1256
1358
|
},
|
|
1359
|
+
"showButton": {
|
|
1360
|
+
"type": "boolean",
|
|
1361
|
+
"attribute": "show-button",
|
|
1362
|
+
"mutable": false,
|
|
1363
|
+
"complexType": {
|
|
1364
|
+
"original": "boolean",
|
|
1365
|
+
"resolved": "boolean",
|
|
1366
|
+
"references": {}
|
|
1367
|
+
},
|
|
1368
|
+
"required": false,
|
|
1369
|
+
"optional": false,
|
|
1370
|
+
"docs": {
|
|
1371
|
+
"tags": [],
|
|
1372
|
+
"text": "Whether to show the launcher button. Set to false to hide the button\nand open the chat window programmatically via the `visible` property."
|
|
1373
|
+
},
|
|
1374
|
+
"getter": false,
|
|
1375
|
+
"setter": false,
|
|
1376
|
+
"reflect": false,
|
|
1377
|
+
"defaultValue": "true"
|
|
1378
|
+
},
|
|
1379
|
+
"mode": {
|
|
1380
|
+
"type": "string",
|
|
1381
|
+
"attribute": "mode",
|
|
1382
|
+
"mutable": false,
|
|
1383
|
+
"complexType": {
|
|
1384
|
+
"original": "'standard' | 'kiosk'",
|
|
1385
|
+
"resolved": "\"kiosk\" | \"standard\"",
|
|
1386
|
+
"references": {}
|
|
1387
|
+
},
|
|
1388
|
+
"required": false,
|
|
1389
|
+
"optional": false,
|
|
1390
|
+
"docs": {
|
|
1391
|
+
"tags": [],
|
|
1392
|
+
"text": "The operating mode of the widget.\n- 'standard': Default floating window with launcher button.\n- 'kiosk': Fills parent container, always visible, no header or launcher button.\n The parent element must establish a containing block (e.g. `position: relative`)."
|
|
1393
|
+
},
|
|
1394
|
+
"getter": false,
|
|
1395
|
+
"setter": false,
|
|
1396
|
+
"reflect": false,
|
|
1397
|
+
"defaultValue": "'standard'"
|
|
1398
|
+
},
|
|
1257
1399
|
"headerText": {
|
|
1258
1400
|
"type": "string",
|
|
1259
1401
|
"attribute": "header-text",
|
|
@@ -1567,6 +1709,28 @@ export class OcsChat {
|
|
|
1567
1709
|
},
|
|
1568
1710
|
"getter": false,
|
|
1569
1711
|
"setter": false
|
|
1712
|
+
},
|
|
1713
|
+
"versionNumber": {
|
|
1714
|
+
"type": "number",
|
|
1715
|
+
"attribute": "version-number",
|
|
1716
|
+
"mutable": false,
|
|
1717
|
+
"complexType": {
|
|
1718
|
+
"original": "number",
|
|
1719
|
+
"resolved": "number",
|
|
1720
|
+
"references": {}
|
|
1721
|
+
},
|
|
1722
|
+
"required": false,
|
|
1723
|
+
"optional": true,
|
|
1724
|
+
"docs": {
|
|
1725
|
+
"tags": [{
|
|
1726
|
+
"name": "internal",
|
|
1727
|
+
"text": "Optional version number of the chatbot to use. Requires authentication.\nThis is for internal use only and is not intended for public-facing widgets."
|
|
1728
|
+
}],
|
|
1729
|
+
"text": ""
|
|
1730
|
+
},
|
|
1731
|
+
"getter": false,
|
|
1732
|
+
"setter": false,
|
|
1733
|
+
"reflect": false
|
|
1570
1734
|
}
|
|
1571
1735
|
};
|
|
1572
1736
|
}
|
|
@@ -1577,6 +1741,7 @@ export class OcsChat {
|
|
|
1577
1741
|
"sessionId": {},
|
|
1578
1742
|
"isLoading": {},
|
|
1579
1743
|
"isTyping": {},
|
|
1744
|
+
"typingProgressMessage": {},
|
|
1580
1745
|
"messageInput": {},
|
|
1581
1746
|
"currentPollTaskId": {},
|
|
1582
1747
|
"isDragging": {},
|
|
@@ -1599,6 +1764,12 @@ export class OcsChat {
|
|
|
1599
1764
|
return [{
|
|
1600
1765
|
"propName": "pageContext",
|
|
1601
1766
|
"methodName": "pageContextHandler"
|
|
1767
|
+
}, {
|
|
1768
|
+
"propName": "chatbotId",
|
|
1769
|
+
"methodName": "chatbotConfigHandler"
|
|
1770
|
+
}, {
|
|
1771
|
+
"propName": "versionNumber",
|
|
1772
|
+
"methodName": "chatbotConfigHandler"
|
|
1602
1773
|
}, {
|
|
1603
1774
|
"propName": "visible",
|
|
1604
1775
|
"methodName": "visibilityHandler"
|
|
@@ -1615,7 +1786,39 @@ OcsChat.WINDOW_MARGIN = 20;
|
|
|
1615
1786
|
OcsChat.LOCALSTORAGE_TEST_KEY = '__ocs_test__';
|
|
1616
1787
|
OcsChat.MAX_FILE_SIZE_MB = 50;
|
|
1617
1788
|
OcsChat.MAX_TOTAL_SIZE_MB = 50;
|
|
1618
|
-
OcsChat.SUPPORTED_FILE_EXTENSIONS = [
|
|
1619
|
-
'.
|
|
1620
|
-
'.
|
|
1789
|
+
OcsChat.SUPPORTED_FILE_EXTENSIONS = [
|
|
1790
|
+
'.txt',
|
|
1791
|
+
'.pdf',
|
|
1792
|
+
'.doc',
|
|
1793
|
+
'.docx',
|
|
1794
|
+
'.xls',
|
|
1795
|
+
'.xlsx',
|
|
1796
|
+
'.csv',
|
|
1797
|
+
'.jpg',
|
|
1798
|
+
'.jpeg',
|
|
1799
|
+
'.png',
|
|
1800
|
+
'.gif',
|
|
1801
|
+
'.bmp',
|
|
1802
|
+
'.webp',
|
|
1803
|
+
'.svg',
|
|
1804
|
+
'.mp4',
|
|
1805
|
+
'.mov',
|
|
1806
|
+
'.avi',
|
|
1807
|
+
'.mp3',
|
|
1808
|
+
'.wav',
|
|
1809
|
+
'.html',
|
|
1810
|
+
'.htm',
|
|
1811
|
+
'.css',
|
|
1812
|
+
'.js',
|
|
1813
|
+
'.xml',
|
|
1814
|
+
'.md',
|
|
1815
|
+
'.ics',
|
|
1816
|
+
'.vcf',
|
|
1817
|
+
'.rtf',
|
|
1818
|
+
'.tsv',
|
|
1819
|
+
'.yaml',
|
|
1820
|
+
'.yml',
|
|
1821
|
+
'.py',
|
|
1822
|
+
'.c',
|
|
1823
|
+
];
|
|
1621
1824
|
//# sourceMappingURL=ocs-chat.js.map
|