open-chat-studio-widget 0.5.3 → 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 -24
- package/dist/cjs/{index-D8A4RBzq.js → index-CvB341El.js} +3 -3
- package/dist/cjs/{index-D8A4RBzq.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 +387 -139
- 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 +329 -76
- 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 -6
- 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 +394 -138
- package/dist/components/open-chat-studio-widget.js.map +1 -1
- package/dist/esm/{index-C53whb-B.js → index-C2QZK0Ui.js} +3 -3
- package/dist/esm/{index-C53whb-B.js.map → index-C2QZK0Ui.js.map} +1 -1
- package/dist/esm/loader.js +3 -3
- package/dist/esm/open-chat-studio-widget.entry.js +387 -139
- 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-C53whb-B.js → p-C2QZK0Ui.js} +2 -2
- package/dist/open-chat-studio-widget/{p-C53whb-B.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 +41 -1
- package/dist/types/components.d.ts +31 -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-b9556259.entry.js +0 -4
- package/dist/open-chat-studio-widget/p-b9556259.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()) {
|
|
@@ -224,6 +243,7 @@ export class OcsChat {
|
|
|
224
243
|
}
|
|
225
244
|
this.parseWelcomeMessages();
|
|
226
245
|
this.parseStarterQuestions();
|
|
246
|
+
this.loadInternalPageContext();
|
|
227
247
|
}
|
|
228
248
|
componentDidLoad() {
|
|
229
249
|
const computedStyle = getComputedStyle(this.host);
|
|
@@ -234,11 +254,20 @@ export class OcsChat {
|
|
|
234
254
|
this.chatWindowWidth = varToPixels(windowWidthVar, window.innerWidth, this.chatWindowWidth);
|
|
235
255
|
this.chatWindowFullscreenWidth = varToPixels(fullscreenWidthVar, window.innerWidth, this.chatWindowFullscreenWidth);
|
|
236
256
|
// Initialize button position from computed styles
|
|
237
|
-
this.
|
|
238
|
-
|
|
257
|
+
if (this.showButton && !this.isKioskMode()) {
|
|
258
|
+
this.initializeButtonPosition();
|
|
259
|
+
}
|
|
260
|
+
// Defer state changes to avoid triggering them during componentDidLoad
|
|
239
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
|
+
}
|
|
240
267
|
if (this.visible) {
|
|
241
|
-
this.
|
|
268
|
+
if (!this.isKioskMode()) {
|
|
269
|
+
this.initializePosition();
|
|
270
|
+
}
|
|
242
271
|
}
|
|
243
272
|
// Resume polling for existing session (don't auto-start new sessions)
|
|
244
273
|
if (this.visible && this.sessionId) {
|
|
@@ -271,7 +300,7 @@ export class OcsChat {
|
|
|
271
300
|
created_at: new Date().toISOString(),
|
|
272
301
|
role: 'system',
|
|
273
302
|
content: `**Error:** ${errorText}\nPlease try again.`,
|
|
274
|
-
attachments: []
|
|
303
|
+
attachments: [],
|
|
275
304
|
};
|
|
276
305
|
this.messages = [...this.messages, errorMessage];
|
|
277
306
|
this.saveSessionToStorage();
|
|
@@ -316,6 +345,16 @@ export class OcsChat {
|
|
|
316
345
|
}
|
|
317
346
|
this.translationManager = new TranslationManager(this.language, customTranslationsObj);
|
|
318
347
|
}
|
|
348
|
+
loadInternalPageContext() {
|
|
349
|
+
if (this.pageContext === undefined || this.pageContext === null) {
|
|
350
|
+
return;
|
|
351
|
+
}
|
|
352
|
+
if (typeof this.pageContext !== 'object' || Array.isArray(this.pageContext)) {
|
|
353
|
+
console.error('pageContext is expected to be a plain JavaScript object.');
|
|
354
|
+
return;
|
|
355
|
+
}
|
|
356
|
+
this.internalPageContext = this.pageContext;
|
|
357
|
+
}
|
|
319
358
|
async loadTranslationsFromUrl(url) {
|
|
320
359
|
try {
|
|
321
360
|
const response = await fetch(url);
|
|
@@ -339,6 +378,7 @@ export class OcsChat {
|
|
|
339
378
|
this.currentPollTaskId = '';
|
|
340
379
|
}
|
|
341
380
|
async startSession() {
|
|
381
|
+
const epoch = this.sessionEpoch;
|
|
342
382
|
try {
|
|
343
383
|
this.isLoading = true;
|
|
344
384
|
const userId = this.getOrGenerateUserId();
|
|
@@ -346,19 +386,26 @@ export class OcsChat {
|
|
|
346
386
|
chatbot_id: this.chatbotId,
|
|
347
387
|
session_data: {
|
|
348
388
|
source: 'widget',
|
|
349
|
-
page_url: window.location.href
|
|
389
|
+
page_url: window.location.href,
|
|
350
390
|
},
|
|
351
|
-
participant_remote_id: userId
|
|
391
|
+
participant_remote_id: userId,
|
|
352
392
|
};
|
|
353
393
|
if (this.userName) {
|
|
354
394
|
requestBody.participant_name = this.userName;
|
|
355
395
|
}
|
|
396
|
+
if (this.versionNumber != null) {
|
|
397
|
+
requestBody.version_number = this.versionNumber;
|
|
398
|
+
}
|
|
356
399
|
const data = await this.getChatService().startSession(requestBody);
|
|
400
|
+
if (epoch !== this.sessionEpoch)
|
|
401
|
+
return;
|
|
357
402
|
this.sessionId = data.session_id;
|
|
358
403
|
this.saveSessionToStorage();
|
|
359
404
|
this.startMessagePolling();
|
|
360
405
|
}
|
|
361
406
|
catch (_error) {
|
|
407
|
+
if (epoch !== this.sessionEpoch)
|
|
408
|
+
return;
|
|
362
409
|
this.handleError('Failed to start chat session');
|
|
363
410
|
}
|
|
364
411
|
finally {
|
|
@@ -387,6 +434,7 @@ export class OcsChat {
|
|
|
387
434
|
async sendMessage(message) {
|
|
388
435
|
if (!message.trim())
|
|
389
436
|
return;
|
|
437
|
+
const epoch = this.sessionEpoch;
|
|
390
438
|
// Start session if we don't have one yet
|
|
391
439
|
if (!this.sessionId) {
|
|
392
440
|
// Prevent concurrent session initialization
|
|
@@ -420,7 +468,7 @@ export class OcsChat {
|
|
|
420
468
|
created_at: new Date(now.getTime() - (welcomeMessagesToAdd.length - index) * 1000).toISOString(),
|
|
421
469
|
role: 'assistant',
|
|
422
470
|
content: welcomeMsg,
|
|
423
|
-
attachments: []
|
|
471
|
+
attachments: [],
|
|
424
472
|
}));
|
|
425
473
|
this.messages = [...this.messages, ...welcomeMessages];
|
|
426
474
|
}
|
|
@@ -429,13 +477,15 @@ export class OcsChat {
|
|
|
429
477
|
created_at: new Date().toISOString(),
|
|
430
478
|
role: 'user',
|
|
431
479
|
content: message.trim(),
|
|
432
|
-
attachments: this.allowAttachments
|
|
433
|
-
|
|
434
|
-
|
|
435
|
-
|
|
436
|
-
|
|
437
|
-
|
|
438
|
-
|
|
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
|
+
: [],
|
|
439
489
|
};
|
|
440
490
|
this.messages = [...this.messages, userMessage];
|
|
441
491
|
this.saveSessionToStorage();
|
|
@@ -448,13 +498,24 @@ export class OcsChat {
|
|
|
448
498
|
if (this.allowAttachments && attachmentIds.length > 0) {
|
|
449
499
|
requestBody.attachment_ids = attachmentIds;
|
|
450
500
|
}
|
|
501
|
+
if (this.internalPageContext) {
|
|
502
|
+
requestBody.context = this.internalPageContext;
|
|
503
|
+
}
|
|
504
|
+
if (this.versionNumber != null) {
|
|
505
|
+
requestBody.version_number = this.versionNumber;
|
|
506
|
+
}
|
|
451
507
|
const data = await this.getChatService().sendMessage(this.sessionId, requestBody);
|
|
508
|
+
if (epoch !== this.sessionEpoch)
|
|
509
|
+
return;
|
|
452
510
|
if (data.status === 'error') {
|
|
453
511
|
throw new Error(data.error || 'Failed to send message');
|
|
454
512
|
}
|
|
513
|
+
this.internalPageContext = undefined;
|
|
455
514
|
this.startTaskPolling(data.task_id);
|
|
456
515
|
}
|
|
457
516
|
catch (error) {
|
|
517
|
+
if (epoch !== this.sessionEpoch)
|
|
518
|
+
return;
|
|
458
519
|
const errorText = error instanceof Error ? error.message : 'Failed to send message';
|
|
459
520
|
this.handleError(errorText);
|
|
460
521
|
}
|
|
@@ -477,10 +538,10 @@ export class OcsChat {
|
|
|
477
538
|
const childRect = lastChild.getBoundingClientRect();
|
|
478
539
|
const currentScrollTop = this.messageListRef.scrollTop;
|
|
479
540
|
const childTopRelativeToParent = childRect.top - parentRect.top;
|
|
480
|
-
const targetScroll = currentScrollTop + childTopRelativeToParent -
|
|
541
|
+
const targetScroll = currentScrollTop + childTopRelativeToParent - parentRect.height / 2;
|
|
481
542
|
this.messageListRef.scrollTo({
|
|
482
543
|
top: targetScroll,
|
|
483
|
-
behavior: 'smooth'
|
|
544
|
+
behavior: 'smooth',
|
|
484
545
|
});
|
|
485
546
|
}
|
|
486
547
|
else {
|
|
@@ -525,10 +586,10 @@ export class OcsChat {
|
|
|
525
586
|
const k = 1024;
|
|
526
587
|
if (bytes < k * k) {
|
|
527
588
|
// Less than 1MB, show in KB
|
|
528
|
-
return Math.round(bytes / k * 100) / 100 + ' KB';
|
|
589
|
+
return Math.round((bytes / k) * 100) / 100 + ' KB';
|
|
529
590
|
}
|
|
530
591
|
else {
|
|
531
|
-
return Math.round(bytes / (k * k) * 100) / 100 + ' MB';
|
|
592
|
+
return Math.round((bytes / (k * k)) * 100) / 100 + ' MB';
|
|
532
593
|
}
|
|
533
594
|
}
|
|
534
595
|
formatTime(dateString) {
|
|
@@ -538,19 +599,38 @@ export class OcsChat {
|
|
|
538
599
|
toggleWindowVisibility() {
|
|
539
600
|
this.visible = !this.visible;
|
|
540
601
|
}
|
|
602
|
+
/**
|
|
603
|
+
* Watch for changes to the `pageContext` prop and sync to internal variable.
|
|
604
|
+
*
|
|
605
|
+
* @param pageContext - The new value for the field.
|
|
606
|
+
*/
|
|
607
|
+
pageContextHandler() {
|
|
608
|
+
this.loadInternalPageContext();
|
|
609
|
+
}
|
|
610
|
+
async chatbotConfigHandler() {
|
|
611
|
+
await this.clearSession();
|
|
612
|
+
}
|
|
541
613
|
/**
|
|
542
614
|
* Watch for changes to the `visible` attribute and update accordingly.
|
|
543
615
|
*
|
|
544
616
|
* @param visible - The new value for the field.
|
|
545
617
|
*/
|
|
546
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);
|
|
547
625
|
if (this.isButtonDragging) {
|
|
548
626
|
this.isButtonDragging = false;
|
|
549
627
|
this.buttonWasDragged = false;
|
|
550
628
|
this.removeButtonEventListeners();
|
|
551
629
|
}
|
|
552
630
|
if (visible) {
|
|
553
|
-
this.
|
|
631
|
+
if (!this.isKioskMode()) {
|
|
632
|
+
this.initializePosition();
|
|
633
|
+
}
|
|
554
634
|
// Resume polling for existing session (don't auto-start new sessions)
|
|
555
635
|
if (this.sessionId) {
|
|
556
636
|
this.scrollToBottom(true);
|
|
@@ -571,37 +651,43 @@ export class OcsChat {
|
|
|
571
651
|
this.taskPollingHandle.cancel();
|
|
572
652
|
}
|
|
573
653
|
this.taskPollingHandle = this.getChatService().pollTask(this.sessionId, taskId, {
|
|
574
|
-
onMessage:
|
|
654
|
+
onMessage: message => {
|
|
575
655
|
this.messages = [...this.messages, message];
|
|
576
656
|
this.saveSessionToStorage();
|
|
577
657
|
this.scrollToBottom();
|
|
578
658
|
this.isTyping = false;
|
|
659
|
+
this.typingProgressMessage = '';
|
|
579
660
|
this.currentPollTaskId = '';
|
|
580
661
|
this.taskPollingHandle = undefined;
|
|
581
662
|
this.startMessagePolling();
|
|
582
663
|
this.focusInput();
|
|
583
664
|
},
|
|
665
|
+
onProgress: message => {
|
|
666
|
+
this.typingProgressMessage = message;
|
|
667
|
+
},
|
|
584
668
|
onTimeout: () => {
|
|
585
669
|
const timeoutMessage = {
|
|
586
670
|
created_at: new Date().toISOString(),
|
|
587
671
|
role: 'system',
|
|
588
672
|
content: 'The response is taking longer than expected. The system may be experiencing delays. Please try sending your message again.',
|
|
589
|
-
attachments: []
|
|
673
|
+
attachments: [],
|
|
590
674
|
};
|
|
591
675
|
this.messages = [...this.messages, timeoutMessage];
|
|
592
676
|
this.saveSessionToStorage();
|
|
593
677
|
this.scrollToBottom();
|
|
594
678
|
this.isTyping = false;
|
|
679
|
+
this.typingProgressMessage = '';
|
|
595
680
|
this.currentPollTaskId = '';
|
|
596
681
|
this.taskPollingHandle = undefined;
|
|
597
682
|
this.startMessagePolling();
|
|
598
683
|
this.focusInput();
|
|
599
684
|
},
|
|
600
|
-
onError:
|
|
685
|
+
onError: error => {
|
|
686
|
+
this.typingProgressMessage = '';
|
|
601
687
|
this.handleError(error.message);
|
|
602
688
|
this.taskPollingHandle = undefined;
|
|
603
689
|
this.startMessagePolling();
|
|
604
|
-
}
|
|
690
|
+
},
|
|
605
691
|
});
|
|
606
692
|
}
|
|
607
693
|
startMessagePolling() {
|
|
@@ -612,8 +698,8 @@ export class OcsChat {
|
|
|
612
698
|
return;
|
|
613
699
|
}
|
|
614
700
|
this.messagePollingHandle = this.getChatService().startMessagePolling(this.sessionId, {
|
|
615
|
-
getSince: () => { var _a; return this.messages.length > 0 ? (_a = this.messages.at(-1)) === null || _a === void 0 ? void 0 : _a.created_at : undefined; },
|
|
616
|
-
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 => {
|
|
617
703
|
if (messages.length === 0)
|
|
618
704
|
return;
|
|
619
705
|
this.messages = [...this.messages, ...messages];
|
|
@@ -623,7 +709,7 @@ export class OcsChat {
|
|
|
623
709
|
},
|
|
624
710
|
onError: () => {
|
|
625
711
|
// Silently ignore polling errors to match previous behaviour
|
|
626
|
-
}
|
|
712
|
+
},
|
|
627
713
|
});
|
|
628
714
|
}
|
|
629
715
|
stopMessagePolling() {
|
|
@@ -642,6 +728,9 @@ export class OcsChat {
|
|
|
642
728
|
this.position = position;
|
|
643
729
|
}
|
|
644
730
|
getPositionClasses() {
|
|
731
|
+
if (this.isKioskMode()) {
|
|
732
|
+
return 'chat-window-kiosk';
|
|
733
|
+
}
|
|
645
734
|
if (this.isFullscreen) {
|
|
646
735
|
return 'chat-window-fullscreen';
|
|
647
736
|
}
|
|
@@ -657,6 +746,9 @@ export class OcsChat {
|
|
|
657
746
|
return { windowWidth, actualChatWidth, centeredX, maxOffset };
|
|
658
747
|
}
|
|
659
748
|
getPositionStyles() {
|
|
749
|
+
if (this.isKioskMode()) {
|
|
750
|
+
return {};
|
|
751
|
+
}
|
|
660
752
|
if (this.isFullscreen) {
|
|
661
753
|
const { centeredX } = this.getFullscreenBounds();
|
|
662
754
|
const finalX = centeredX + this.fullscreenPosition.x;
|
|
@@ -688,19 +780,19 @@ export class OcsChat {
|
|
|
688
780
|
case 'left':
|
|
689
781
|
this.windowPosition = {
|
|
690
782
|
x: OcsChat.WINDOW_MARGIN,
|
|
691
|
-
y: windowHeight - this.chatWindowHeight - OcsChat.WINDOW_MARGIN
|
|
783
|
+
y: windowHeight - this.chatWindowHeight - OcsChat.WINDOW_MARGIN,
|
|
692
784
|
};
|
|
693
785
|
break;
|
|
694
786
|
case 'right':
|
|
695
787
|
this.windowPosition = {
|
|
696
788
|
x: windowWidth - chatWidth - OcsChat.WINDOW_MARGIN,
|
|
697
|
-
y: windowHeight - this.chatWindowHeight - OcsChat.WINDOW_MARGIN
|
|
789
|
+
y: windowHeight - this.chatWindowHeight - OcsChat.WINDOW_MARGIN,
|
|
698
790
|
};
|
|
699
791
|
break;
|
|
700
792
|
case 'center':
|
|
701
793
|
this.windowPosition = {
|
|
702
794
|
x: (windowWidth - chatWidth) / 2,
|
|
703
|
-
y: (windowHeight - this.chatWindowHeight) / 2
|
|
795
|
+
y: (windowHeight - this.chatWindowHeight) / 2,
|
|
704
796
|
};
|
|
705
797
|
break;
|
|
706
798
|
}
|
|
@@ -723,14 +815,14 @@ export class OcsChat {
|
|
|
723
815
|
// For fullscreen, track relative to current position
|
|
724
816
|
this.dragOffset = {
|
|
725
817
|
x: pointer.clientX,
|
|
726
|
-
y: pointer.clientY
|
|
818
|
+
y: pointer.clientY,
|
|
727
819
|
};
|
|
728
820
|
}
|
|
729
821
|
else {
|
|
730
822
|
const rect = this.chatWindowRef.getBoundingClientRect();
|
|
731
823
|
this.dragOffset = {
|
|
732
824
|
x: pointer.clientX - rect.left,
|
|
733
|
-
y: pointer.clientY - rect.top
|
|
825
|
+
y: pointer.clientY - rect.top,
|
|
734
826
|
};
|
|
735
827
|
}
|
|
736
828
|
}
|
|
@@ -742,7 +834,7 @@ export class OcsChat {
|
|
|
742
834
|
const { maxOffset } = this.getFullscreenBounds();
|
|
743
835
|
const deltaX = pointer.clientX - this.dragOffset.x;
|
|
744
836
|
this.fullscreenPosition = {
|
|
745
|
-
x: Math.max(-maxOffset, Math.min(maxOffset, deltaX))
|
|
837
|
+
x: Math.max(-maxOffset, Math.min(maxOffset, deltaX)),
|
|
746
838
|
};
|
|
747
839
|
}
|
|
748
840
|
else {
|
|
@@ -755,7 +847,7 @@ export class OcsChat {
|
|
|
755
847
|
const chatHeight = this.chatWindowRef.offsetHeight;
|
|
756
848
|
this.windowPosition = {
|
|
757
849
|
x: Math.max(0, Math.min(newX, windowWidth - chatWidth)),
|
|
758
|
-
y: Math.max(0, Math.min(newY, windowHeight - chatHeight))
|
|
850
|
+
y: Math.max(0, Math.min(newY, windowHeight - chatHeight)),
|
|
759
851
|
};
|
|
760
852
|
}
|
|
761
853
|
}
|
|
@@ -802,7 +894,7 @@ export class OcsChat {
|
|
|
802
894
|
const verticalValue = this.buttonVerticalSide === 'top' ? resolvedTop : resolvedBottom;
|
|
803
895
|
this.buttonPosition = {
|
|
804
896
|
x: horizontalValue,
|
|
805
|
-
y: verticalValue
|
|
897
|
+
y: verticalValue,
|
|
806
898
|
};
|
|
807
899
|
// Apply the position to the host
|
|
808
900
|
this.updateHostPosition();
|
|
@@ -845,12 +937,8 @@ export class OcsChat {
|
|
|
845
937
|
const maxTop = windowHeight - buttonHeight - minPadding;
|
|
846
938
|
const constrainedLeft = Math.max(minLeft, Math.min(candidateLeft, maxLeft));
|
|
847
939
|
const constrainedTop = Math.max(minTop, Math.min(candidateTop, maxTop));
|
|
848
|
-
const newHorizontalValue = this.buttonHorizontalSide === 'left'
|
|
849
|
-
|
|
850
|
-
: Math.max(minPadding, windowWidth - (constrainedLeft + buttonWidth));
|
|
851
|
-
const newVerticalValue = this.buttonVerticalSide === 'top'
|
|
852
|
-
? constrainedTop
|
|
853
|
-
: 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));
|
|
854
942
|
if (newHorizontalValue !== this.buttonPosition.x || newVerticalValue !== this.buttonPosition.y) {
|
|
855
943
|
this.buttonWasDragged = true;
|
|
856
944
|
this.buttonPosition = { x: newHorizontalValue, y: newVerticalValue };
|
|
@@ -913,16 +1001,12 @@ export class OcsChat {
|
|
|
913
1001
|
return fallback;
|
|
914
1002
|
}
|
|
915
1003
|
getWelcomeMessages() {
|
|
916
|
-
const translated = this.translationManager.getArray(
|
|
917
|
-
return translated && translated.length > 0
|
|
918
|
-
? translated
|
|
919
|
-
: this.parsedWelcomeMessages;
|
|
1004
|
+
const translated = this.translationManager.getArray('content.welcomeMessages');
|
|
1005
|
+
return translated && translated.length > 0 ? translated : this.parsedWelcomeMessages;
|
|
920
1006
|
}
|
|
921
1007
|
getStarterQuestions() {
|
|
922
|
-
const translated = this.translationManager.getArray(
|
|
923
|
-
return translated && translated.length > 0
|
|
924
|
-
? translated
|
|
925
|
-
: this.parsedStarterQuestions;
|
|
1008
|
+
const translated = this.translationManager.getArray('content.starterQuestions');
|
|
1009
|
+
return translated && translated.length > 0 ? translated : this.parsedStarterQuestions;
|
|
926
1010
|
}
|
|
927
1011
|
getButtonClasses() {
|
|
928
1012
|
const buttonText = this.translationManager.get('branding.buttonText', this.buttonText);
|
|
@@ -933,6 +1017,9 @@ export class OcsChat {
|
|
|
933
1017
|
}
|
|
934
1018
|
renderButton() {
|
|
935
1019
|
var _a;
|
|
1020
|
+
if (!this.showButton || this.isKioskMode()) {
|
|
1021
|
+
return null;
|
|
1022
|
+
}
|
|
936
1023
|
const buttonText = this.translationManager.get('branding.buttonText', this.buttonText);
|
|
937
1024
|
const hasText = !!(buttonText && buttonText.trim());
|
|
938
1025
|
const hasCustomIcon = this.iconUrl && this.iconUrl.trim();
|
|
@@ -942,21 +1029,24 @@ export class OcsChat {
|
|
|
942
1029
|
const buttonAriaLabel = finalButtonText ? `${openLabel} - ${finalButtonText}` : openLabel;
|
|
943
1030
|
// Only show drag cursor if button is draggable
|
|
944
1031
|
const isDraggable = this.isButtonDraggable();
|
|
945
|
-
const buttonStyle = isDraggable
|
|
946
|
-
|
|
947
|
-
|
|
1032
|
+
const buttonStyle = isDraggable
|
|
1033
|
+
? {
|
|
1034
|
+
cursor: this.isButtonDragging ? 'grabbing' : 'grab',
|
|
1035
|
+
}
|
|
1036
|
+
: {};
|
|
948
1037
|
if (hasText) {
|
|
949
|
-
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."))));
|
|
950
1039
|
}
|
|
951
1040
|
else {
|
|
952
|
-
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."))));
|
|
953
1042
|
}
|
|
954
1043
|
}
|
|
955
1044
|
getStorageKeys() {
|
|
956
1045
|
return {
|
|
957
1046
|
sessionId: `ocs-chat-session-${this.chatbotId}`,
|
|
958
1047
|
messages: `ocs-chat-messages-${this.chatbotId}`,
|
|
959
|
-
lastActivity: `ocs-chat-activity-${this.chatbotId}
|
|
1048
|
+
lastActivity: `ocs-chat-activity-${this.chatbotId}`,
|
|
1049
|
+
visible: `ocs-chat-visible-${this.chatbotId}`,
|
|
960
1050
|
};
|
|
961
1051
|
}
|
|
962
1052
|
saveSessionToStorage() {
|
|
@@ -1019,30 +1109,70 @@ export class OcsChat {
|
|
|
1019
1109
|
return this.generatedUserId;
|
|
1020
1110
|
}
|
|
1021
1111
|
const storageKey = `ocs-user-id`;
|
|
1022
|
-
|
|
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
|
+
}
|
|
1023
1119
|
if (stored) {
|
|
1024
1120
|
this.generatedUserId = stored;
|
|
1025
1121
|
return stored;
|
|
1026
1122
|
}
|
|
1027
1123
|
const array = new Uint8Array(9);
|
|
1028
1124
|
window.crypto.getRandomValues(array);
|
|
1029
|
-
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);
|
|
1030
1128
|
const newUserId = `ocs:${Date.now()}_${randomString}`;
|
|
1031
1129
|
this.generatedUserId = newUserId;
|
|
1032
|
-
|
|
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
|
+
}
|
|
1033
1136
|
return newUserId;
|
|
1034
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
|
+
}
|
|
1035
1161
|
clearSessionStorage() {
|
|
1036
1162
|
const keys = this.getStorageKeys();
|
|
1037
1163
|
try {
|
|
1038
1164
|
localStorage.removeItem(keys.sessionId);
|
|
1039
1165
|
localStorage.removeItem(keys.messages);
|
|
1040
1166
|
localStorage.removeItem(keys.lastActivity);
|
|
1167
|
+
localStorage.removeItem(keys.visible);
|
|
1041
1168
|
}
|
|
1042
1169
|
catch (error) {
|
|
1043
1170
|
console.warn('Failed to clear chat session from localStorage:', error);
|
|
1044
1171
|
}
|
|
1045
1172
|
}
|
|
1173
|
+
isKioskMode() {
|
|
1174
|
+
return this.mode === 'kiosk';
|
|
1175
|
+
}
|
|
1046
1176
|
isLocalStorageAvailable() {
|
|
1047
1177
|
try {
|
|
1048
1178
|
localStorage.setItem(OcsChat.LOCALSTORAGE_TEST_KEY, 'test');
|
|
@@ -1068,6 +1198,7 @@ export class OcsChat {
|
|
|
1068
1198
|
* will start when the user sends a message.
|
|
1069
1199
|
*/
|
|
1070
1200
|
async clearSession() {
|
|
1201
|
+
this.sessionEpoch += 1;
|
|
1071
1202
|
this.clearSessionStorage();
|
|
1072
1203
|
this.sessionId = undefined;
|
|
1073
1204
|
this.messages = [];
|
|
@@ -1088,18 +1219,12 @@ export class OcsChat {
|
|
|
1088
1219
|
if (this.error && !this.sessionId) {
|
|
1089
1220
|
return (h(Host, null, h("p", { class: "error-message" }, this.error)));
|
|
1090
1221
|
}
|
|
1091
|
-
return (h(Host, null, this.renderButton(), this.visible && (h("div", { ref:
|
|
1092
|
-
? 'message-bubble-user'
|
|
1093
|
-
: message.role === 'assistant'
|
|
1094
|
-
? 'message-bubble-assistant'
|
|
1095
|
-
: '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 => {
|
|
1096
1223
|
// Unclear why but after removing all attachments this is being set to `null`.
|
|
1097
1224
|
if (el) {
|
|
1098
1225
|
this.fileInputRef = el;
|
|
1099
1226
|
}
|
|
1100
|
-
}, id: "ocs-file-input", type: "file", multiple: true, accept: OcsChat.SUPPORTED_FILE_EXTENSIONS.join(','), onChange:
|
|
1101
|
-
? 'send-button-enabled'
|
|
1102
|
-
: '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"))))))));
|
|
1103
1228
|
}
|
|
1104
1229
|
static get is() { return "open-chat-studio-widget"; }
|
|
1105
1230
|
static get encapsulation() { return "shadow"; }
|
|
@@ -1152,7 +1277,7 @@ export class OcsChat {
|
|
|
1152
1277
|
"getter": false,
|
|
1153
1278
|
"setter": false,
|
|
1154
1279
|
"reflect": false,
|
|
1155
|
-
"defaultValue": "
|
|
1280
|
+
"defaultValue": "'https://www.openchatstudio.com'"
|
|
1156
1281
|
},
|
|
1157
1282
|
"buttonText": {
|
|
1158
1283
|
"type": "string",
|
|
@@ -1231,6 +1356,46 @@ export class OcsChat {
|
|
|
1231
1356
|
"reflect": false,
|
|
1232
1357
|
"defaultValue": "'square'"
|
|
1233
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
|
+
},
|
|
1234
1399
|
"headerText": {
|
|
1235
1400
|
"type": "string",
|
|
1236
1401
|
"attribute": "header-text",
|
|
@@ -1521,6 +1686,51 @@ export class OcsChat {
|
|
|
1521
1686
|
"getter": false,
|
|
1522
1687
|
"setter": false,
|
|
1523
1688
|
"reflect": false
|
|
1689
|
+
},
|
|
1690
|
+
"pageContext": {
|
|
1691
|
+
"type": "unknown",
|
|
1692
|
+
"attribute": "page-context",
|
|
1693
|
+
"mutable": true,
|
|
1694
|
+
"complexType": {
|
|
1695
|
+
"original": "Record<string, any>",
|
|
1696
|
+
"resolved": "{ [x: string]: any; }",
|
|
1697
|
+
"references": {
|
|
1698
|
+
"Record": {
|
|
1699
|
+
"location": "global",
|
|
1700
|
+
"id": "global::Record"
|
|
1701
|
+
}
|
|
1702
|
+
}
|
|
1703
|
+
},
|
|
1704
|
+
"required": false,
|
|
1705
|
+
"optional": true,
|
|
1706
|
+
"docs": {
|
|
1707
|
+
"tags": [],
|
|
1708
|
+
"text": "Optional context object to send with each message. This provides page-specific context to the bot."
|
|
1709
|
+
},
|
|
1710
|
+
"getter": false,
|
|
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
|
|
1524
1734
|
}
|
|
1525
1735
|
};
|
|
1526
1736
|
}
|
|
@@ -1531,6 +1741,7 @@ export class OcsChat {
|
|
|
1531
1741
|
"sessionId": {},
|
|
1532
1742
|
"isLoading": {},
|
|
1533
1743
|
"isTyping": {},
|
|
1744
|
+
"typingProgressMessage": {},
|
|
1534
1745
|
"messageInput": {},
|
|
1535
1746
|
"currentPollTaskId": {},
|
|
1536
1747
|
"isDragging": {},
|
|
@@ -1551,6 +1762,15 @@ export class OcsChat {
|
|
|
1551
1762
|
static get elementRef() { return "host"; }
|
|
1552
1763
|
static get watchers() {
|
|
1553
1764
|
return [{
|
|
1765
|
+
"propName": "pageContext",
|
|
1766
|
+
"methodName": "pageContextHandler"
|
|
1767
|
+
}, {
|
|
1768
|
+
"propName": "chatbotId",
|
|
1769
|
+
"methodName": "chatbotConfigHandler"
|
|
1770
|
+
}, {
|
|
1771
|
+
"propName": "versionNumber",
|
|
1772
|
+
"methodName": "chatbotConfigHandler"
|
|
1773
|
+
}, {
|
|
1554
1774
|
"propName": "visible",
|
|
1555
1775
|
"methodName": "visibilityHandler"
|
|
1556
1776
|
}];
|
|
@@ -1566,6 +1786,39 @@ OcsChat.WINDOW_MARGIN = 20;
|
|
|
1566
1786
|
OcsChat.LOCALSTORAGE_TEST_KEY = '__ocs_test__';
|
|
1567
1787
|
OcsChat.MAX_FILE_SIZE_MB = 50;
|
|
1568
1788
|
OcsChat.MAX_TOTAL_SIZE_MB = 50;
|
|
1569
|
-
OcsChat.SUPPORTED_FILE_EXTENSIONS = [
|
|
1570
|
-
'.
|
|
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
|
+
];
|
|
1571
1824
|
//# sourceMappingURL=ocs-chat.js.map
|