open-chat-studio-widget 0.4.1 → 0.4.3
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 +78 -9
- package/dist/cjs/{index-b700441a.js → index-bcb28089.js} +3 -1
- package/dist/cjs/index-bcb28089.js.map +1 -0
- package/dist/cjs/loader.cjs.js +2 -2
- package/dist/cjs/open-chat-studio-widget.cjs.entry.js +97 -38
- 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/collection/components/ocs-chat/ocs-chat.css +569 -386
- package/dist/collection/components/ocs-chat/ocs-chat.js +105 -36
- package/dist/collection/components/ocs-chat/ocs-chat.js.map +1 -1
- package/dist/collection/utils/utils.js +30 -0
- package/dist/collection/utils/utils.js.map +1 -0
- package/dist/components/open-chat-studio-widget.js +99 -37
- package/dist/components/open-chat-studio-widget.js.map +1 -1
- package/dist/esm/{index-b188b488.js → index-205c77bc.js} +3 -2
- package/dist/{open-chat-studio-widget/p-a0fbe1b4.js.map → esm/index-205c77bc.js.map} +1 -1
- package/dist/esm/loader.js +3 -3
- package/dist/esm/open-chat-studio-widget.entry.js +97 -38
- 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.esm.js +1 -1
- package/dist/open-chat-studio-widget/open-chat-studio-widget.esm.js.map +1 -1
- package/dist/open-chat-studio-widget/p-6c3059b7.entry.js +3 -0
- package/dist/open-chat-studio-widget/p-6c3059b7.entry.js.map +1 -0
- package/dist/open-chat-studio-widget/p-78d09c6b.js +3 -0
- package/dist/open-chat-studio-widget/p-78d09c6b.js.map +1 -0
- package/dist/types/components/ocs-chat/ocs-chat.d.ts +14 -3
- package/dist/types/components.d.ts +16 -0
- package/dist/types/utils/utils.d.ts +7 -0
- package/package.json +3 -2
- package/dist/cjs/index-b700441a.js.map +0 -1
- package/dist/esm/index-b188b488.js.map +0 -1
- package/dist/open-chat-studio-widget/p-a0fbe1b4.js +0 -3
- package/dist/open-chat-studio-widget/p-eb89e6d7.entry.js +0 -3
- package/dist/open-chat-studio-widget/p-eb89e6d7.entry.js.map +0 -1
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import { Host, h } from "@stencil/core";
|
|
2
2
|
import { XMarkIcon, GripDotsVerticalIcon, PencilSquare, ArrowsPointingOutIcon, ArrowsPointingInIcon, } from "./heroicons";
|
|
3
3
|
import { renderMarkdownSync as renderMarkdownComplete } from "../../utils/markdown";
|
|
4
|
+
import { varToPixels } from "../../utils/utils";
|
|
4
5
|
export class OcsChat {
|
|
5
6
|
constructor() {
|
|
6
7
|
/**
|
|
@@ -47,6 +48,9 @@ export class OcsChat {
|
|
|
47
48
|
this.parsedWelcomeMessages = [];
|
|
48
49
|
this.parsedStarterQuestions = [];
|
|
49
50
|
this.isFullscreen = false;
|
|
51
|
+
this.chatWindowHeight = 600;
|
|
52
|
+
this.chatWindowWidth = 450;
|
|
53
|
+
this.chatWindowFullscreenWidth = 1024;
|
|
50
54
|
this.handleMouseDown = (event) => {
|
|
51
55
|
if (!this.isFullscreen && window.innerWidth < OcsChat.MOBILE_BREAKPOINT)
|
|
52
56
|
return;
|
|
@@ -121,6 +125,13 @@ export class OcsChat {
|
|
|
121
125
|
// Resume polling for existing session
|
|
122
126
|
this.startPolling();
|
|
123
127
|
}
|
|
128
|
+
const computedStyle = getComputedStyle(this.host);
|
|
129
|
+
const windowHeightVar = computedStyle.getPropertyValue('--chat-window-height');
|
|
130
|
+
const windowWidthVar = computedStyle.getPropertyValue('--chat-window-width');
|
|
131
|
+
const fullscreenWidthVar = computedStyle.getPropertyValue('--chat-window-fullscreen-width');
|
|
132
|
+
this.chatWindowHeight = varToPixels(windowHeightVar, window.innerHeight, this.chatWindowHeight);
|
|
133
|
+
this.chatWindowWidth = varToPixels(windowWidthVar, window.innerWidth, this.chatWindowWidth);
|
|
134
|
+
this.chatWindowFullscreenWidth = varToPixels(fullscreenWidthVar, window.innerWidth, this.chatWindowFullscreenWidth);
|
|
124
135
|
this.initializePosition();
|
|
125
136
|
window.addEventListener('resize', this.handleWindowResize);
|
|
126
137
|
}
|
|
@@ -166,18 +177,24 @@ export class OcsChat {
|
|
|
166
177
|
try {
|
|
167
178
|
this.isLoading = true;
|
|
168
179
|
this.error = '';
|
|
180
|
+
const userId = this.getOrGenerateUserId();
|
|
181
|
+
const requestBody = {
|
|
182
|
+
chatbot_id: this.chatbotId,
|
|
183
|
+
session_data: {
|
|
184
|
+
source: 'widget',
|
|
185
|
+
page_url: window.location.href
|
|
186
|
+
},
|
|
187
|
+
participant_remote_id: userId
|
|
188
|
+
};
|
|
189
|
+
if (this.userName) {
|
|
190
|
+
requestBody.participant_name = this.userName;
|
|
191
|
+
}
|
|
169
192
|
const response = await fetch(`${this.getApiBaseUrl()}/api/chat/start/`, {
|
|
170
193
|
method: 'POST',
|
|
171
194
|
headers: {
|
|
172
195
|
'Content-Type': 'application/json',
|
|
173
196
|
},
|
|
174
|
-
body: JSON.stringify(
|
|
175
|
-
chatbot_id: this.chatbotId,
|
|
176
|
-
session_data: {
|
|
177
|
-
source: 'widget',
|
|
178
|
-
page_url: window.location.href
|
|
179
|
-
}
|
|
180
|
-
})
|
|
197
|
+
body: JSON.stringify(requestBody)
|
|
181
198
|
});
|
|
182
199
|
if (!response.ok) {
|
|
183
200
|
throw new Error(`Failed to start session: ${response.statusText}`);
|
|
@@ -402,13 +419,15 @@ export class OcsChat {
|
|
|
402
419
|
}
|
|
403
420
|
getPositionClasses() {
|
|
404
421
|
if (this.isFullscreen) {
|
|
405
|
-
return
|
|
422
|
+
return 'chat-window-fullscreen';
|
|
406
423
|
}
|
|
407
|
-
|
|
424
|
+
const baseClasses = 'chat-window-normal';
|
|
425
|
+
const draggingClass = this.isDragging ? ' chat-window-dragging' : '';
|
|
426
|
+
return baseClasses + draggingClass;
|
|
408
427
|
}
|
|
409
428
|
getFullscreenBounds() {
|
|
410
429
|
const windowWidth = window.innerWidth;
|
|
411
|
-
const actualChatWidth = Math.min(windowWidth,
|
|
430
|
+
const actualChatWidth = Math.min(windowWidth, this.chatWindowFullscreenWidth);
|
|
412
431
|
const centeredX = (windowWidth - actualChatWidth) / 2;
|
|
413
432
|
const maxOffset = (windowWidth - actualChatWidth) / 2;
|
|
414
433
|
return { windowWidth, actualChatWidth, centeredX, maxOffset };
|
|
@@ -431,8 +450,7 @@ export class OcsChat {
|
|
|
431
450
|
initializePosition() {
|
|
432
451
|
const windowWidth = window.innerWidth;
|
|
433
452
|
const windowHeight = window.innerHeight;
|
|
434
|
-
const chatWidth = windowWidth < OcsChat.MOBILE_BREAKPOINT ? windowWidth :
|
|
435
|
-
const chatHeight = windowHeight * OcsChat.CHAT_HEIGHT_EXPANDED_RATIO;
|
|
453
|
+
const chatWidth = windowWidth < OcsChat.MOBILE_BREAKPOINT ? windowWidth : this.chatWindowWidth;
|
|
436
454
|
const isMobile = windowWidth < OcsChat.MOBILE_BREAKPOINT;
|
|
437
455
|
if (isMobile) {
|
|
438
456
|
this.windowPosition = { x: 0, y: 0 };
|
|
@@ -442,19 +460,19 @@ export class OcsChat {
|
|
|
442
460
|
case 'left':
|
|
443
461
|
this.windowPosition = {
|
|
444
462
|
x: OcsChat.WINDOW_MARGIN,
|
|
445
|
-
y: windowHeight -
|
|
463
|
+
y: windowHeight - this.chatWindowHeight - OcsChat.WINDOW_MARGIN
|
|
446
464
|
};
|
|
447
465
|
break;
|
|
448
466
|
case 'right':
|
|
449
467
|
this.windowPosition = {
|
|
450
468
|
x: windowWidth - chatWidth - OcsChat.WINDOW_MARGIN,
|
|
451
|
-
y: windowHeight -
|
|
469
|
+
y: windowHeight - this.chatWindowHeight - OcsChat.WINDOW_MARGIN
|
|
452
470
|
};
|
|
453
471
|
break;
|
|
454
472
|
case 'center':
|
|
455
473
|
this.windowPosition = {
|
|
456
474
|
x: (windowWidth - chatWidth) / 2,
|
|
457
|
-
y: (windowHeight -
|
|
475
|
+
y: (windowHeight - this.chatWindowHeight) / 2
|
|
458
476
|
};
|
|
459
477
|
break;
|
|
460
478
|
}
|
|
@@ -505,8 +523,8 @@ export class OcsChat {
|
|
|
505
523
|
// Constrain chatbox to window
|
|
506
524
|
const windowWidth = window.innerWidth;
|
|
507
525
|
const windowHeight = window.innerHeight;
|
|
508
|
-
const chatWidth = windowWidth < OcsChat.MOBILE_BREAKPOINT ? windowWidth :
|
|
509
|
-
const chatHeight =
|
|
526
|
+
const chatWidth = windowWidth < OcsChat.MOBILE_BREAKPOINT ? windowWidth : this.chatWindowWidth;
|
|
527
|
+
const chatHeight = this.chatWindowRef.offsetHeight;
|
|
510
528
|
this.windowPosition = {
|
|
511
529
|
x: Math.max(0, Math.min(newX, windowWidth - chatWidth)),
|
|
512
530
|
y: Math.max(0, Math.min(newY, windowHeight - chatHeight))
|
|
@@ -609,6 +627,27 @@ export class OcsChat {
|
|
|
609
627
|
return { messages: [] };
|
|
610
628
|
}
|
|
611
629
|
}
|
|
630
|
+
getOrGenerateUserId() {
|
|
631
|
+
if (this.userId) {
|
|
632
|
+
return this.userId;
|
|
633
|
+
}
|
|
634
|
+
if (this.generatedUserId) {
|
|
635
|
+
return this.generatedUserId;
|
|
636
|
+
}
|
|
637
|
+
const storageKey = `ocs-user-id`;
|
|
638
|
+
const stored = localStorage.getItem(storageKey);
|
|
639
|
+
if (stored) {
|
|
640
|
+
this.generatedUserId = stored;
|
|
641
|
+
return stored;
|
|
642
|
+
}
|
|
643
|
+
const array = new Uint8Array(9);
|
|
644
|
+
window.crypto.getRandomValues(array);
|
|
645
|
+
const randomString = Array.from(array, byte => byte.toString(36)).join('').substr(0, 9);
|
|
646
|
+
const newUserId = `ocs:${Date.now()}_${randomString}`;
|
|
647
|
+
this.generatedUserId = newUserId;
|
|
648
|
+
localStorage.setItem(storageKey, newUserId);
|
|
649
|
+
return newUserId;
|
|
650
|
+
}
|
|
612
651
|
clearSessionStorage() {
|
|
613
652
|
const keys = this.getStorageKeys();
|
|
614
653
|
try {
|
|
@@ -647,22 +686,15 @@ export class OcsChat {
|
|
|
647
686
|
}
|
|
648
687
|
render() {
|
|
649
688
|
if (this.error) {
|
|
650
|
-
return (h(Host, null, h("p", { class: "
|
|
651
|
-
}
|
|
652
|
-
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() }, h("div", { class: `
|
|
653
|
-
'
|
|
654
|
-
|
|
655
|
-
|
|
656
|
-
|
|
657
|
-
'
|
|
658
|
-
'
|
|
659
|
-
'bg-gray-200 text-gray-800': message.role === 'assistant',
|
|
660
|
-
'bg-gray-100 text-gray-600 text-sm': message.role === 'system'
|
|
661
|
-
} }, h("div", { class: "chat-markdown", innerHTML: renderMarkdownComplete(message.content) }), message.attachments && message.attachments.length > 0 && (h("div", { class: "mt-2 space-y-1" }, message.attachments.map((attachment, attachmentIndex) => (h("a", { key: attachmentIndex, href: attachment.content_url, target: "_blank", rel: "noopener noreferrer", class: "block text-sm underline hover:no-underline" }, "\uD83D\uDCCE ", attachment.name))))), h("div", { class: "text-xs opacity-70 mt-1" }, this.formatTime(message.created_at)))))), this.isTyping && (h("div", null, h("div", { class: "h-1.5 w-full overflow-hidden" }, h("div", { class: "animate-progress w-full h-full bg-blue-200 origin-left-right rounded-lg" })), h("div", { class: "w-full text-xs opacity-70 justify-center" }, h("span", null, "Preparing response"), h("span", { class: "loading animate-dots" })))))), this.sessionId && this.showStarterQuestions && this.messages.length === 0 && !this.isTyping && (h("div", { class: "p-4 space-y-2" }, this.parsedStarterQuestions.map((question, index) => (h("div", { key: `starter-${index}`, class: "flex justify-end" }, h("button", { class: "starter-question", onClick: () => this.handleStarterQuestionClick(question) }, question)))))), this.sessionId && (h("div", { class: "border-t border-gray-200 p-4 text-sm" }, h("div", { class: "flex gap-2" }, h("textarea", { ref: (el) => this.textareaRef = el, class: "flex-grow px-3 py-2 border border-gray-300 rounded-md resize-none focus:outline-none focus:ring-2 focus:ring-blue-500 focus:border-transparent", rows: 1, placeholder: "Type your message...", value: this.messageInput, onInput: (e) => this.handleInputChange(e), onKeyPress: (e) => this.handleKeyPress(e), disabled: this.isTyping }), h("button", { class: {
|
|
662
|
-
'px-4 py-2 rounded-md font-medium transition-colors duration-200': true,
|
|
663
|
-
'bg-blue-500 hover:bg-blue-600 text-white': !this.isTyping && !!this.messageInput.trim(),
|
|
664
|
-
'bg-gray-300 text-gray-500 cursor-not-allowed': this.isTyping || !this.messageInput.trim()
|
|
665
|
-
}, onClick: () => this.sendMessage(this.messageInput), disabled: this.isTyping || !this.messageInput.trim() }, "Send")))))))));
|
|
689
|
+
return (h(Host, null, h("p", { class: "error-message" }, this.error)));
|
|
690
|
+
}
|
|
691
|
+
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() }, 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" }, h(GripDotsVerticalIcon, null))), h("div", { class: "drag-spacer" }), h("div", { class: "header-buttons" }, this.allowFullScreen && h("button", { class: "header-button fullscreen-button", onClick: () => this.toggleFullscreen(), title: this.isFullscreen ? "Exit fullscreen" : "Enter fullscreen", "aria-label": this.isFullscreen ? "Exit fullscreen" : "Enter fullscreen" }, this.isFullscreen ? h(ArrowsPointingInIcon, null) : h(ArrowsPointingOutIcon, null)), this.sessionId && this.messages.length > 0 && (h("button", { class: "header-button", onClick: () => this.startNewChat(), title: "Start new chat", "aria-label": "Start new chat" }, h(PencilSquare, null))), h("button", { class: "header-button", onClick: () => this.visible = false, "aria-label": "Close" }, h(XMarkIcon, null)))), h("div", { class: "chat-content" }, this.isLoading && !this.sessionId && (h("div", { class: "loading-container" }, h("div", { class: "loading-spinner" }), h("span", { class: "loading-text" }, "Starting chat..."))), this.sessionId && (h("div", { ref: (el) => this.messageListRef = el, class: "messages-container" }, this.messages.length === 0 && !this.isTyping && this.parsedWelcomeMessages.length > 0 && (h("div", { class: "welcome-messages" }, this.parsedWelcomeMessages.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'
|
|
692
|
+
? 'message-bubble-user'
|
|
693
|
+
: message.role === 'assistant'
|
|
694
|
+
? 'message-bubble-assistant'
|
|
695
|
+
: '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("a", { key: attachmentIndex, href: attachment.content_url, target: "_blank", rel: "noopener noreferrer", class: "attachment-link" }, "\uD83D\uDCCE ", 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, "Preparing response"), h("span", { class: "typing-dots" })))))), this.sessionId && this.showStarterQuestions && this.messages.length === 0 && !this.isTyping && (h("div", { class: "starter-questions" }, this.parsedStarterQuestions.map((question, index) => (h("div", { key: `starter-${index}`, class: "starter-question-row" }, h("button", { class: "starter-question", onClick: () => this.handleStarterQuestionClick(question) }, question)))))), this.sessionId && (h("div", { class: "input-area" }, h("div", { class: "input-container" }, h("textarea", { ref: (el) => this.textareaRef = el, class: "message-textarea", rows: 1, placeholder: "Type your message...", value: this.messageInput, onInput: (e) => this.handleInputChange(e), onKeyPress: (e) => this.handleKeyPress(e), disabled: this.isTyping }), h("button", { class: `send-button ${!this.isTyping && !!this.messageInput.trim()
|
|
696
|
+
? 'send-button-enabled'
|
|
697
|
+
: 'send-button-disabled'}`, onClick: () => this.sendMessage(this.messageInput), disabled: this.isTyping || !this.messageInput.trim() }, "Send")))))))));
|
|
666
698
|
}
|
|
667
699
|
static get is() { return "open-chat-studio-widget"; }
|
|
668
700
|
static get encapsulation() { return "shadow"; }
|
|
@@ -853,6 +885,44 @@ export class OcsChat {
|
|
|
853
885
|
"attribute": "starter-questions",
|
|
854
886
|
"reflect": false
|
|
855
887
|
},
|
|
888
|
+
"userId": {
|
|
889
|
+
"type": "string",
|
|
890
|
+
"mutable": false,
|
|
891
|
+
"complexType": {
|
|
892
|
+
"original": "string",
|
|
893
|
+
"resolved": "string",
|
|
894
|
+
"references": {}
|
|
895
|
+
},
|
|
896
|
+
"required": false,
|
|
897
|
+
"optional": true,
|
|
898
|
+
"docs": {
|
|
899
|
+
"tags": [],
|
|
900
|
+
"text": "Used to associate chat sessions with a specific user across multiple visits/sessions"
|
|
901
|
+
},
|
|
902
|
+
"getter": false,
|
|
903
|
+
"setter": false,
|
|
904
|
+
"attribute": "user-id",
|
|
905
|
+
"reflect": false
|
|
906
|
+
},
|
|
907
|
+
"userName": {
|
|
908
|
+
"type": "string",
|
|
909
|
+
"mutable": false,
|
|
910
|
+
"complexType": {
|
|
911
|
+
"original": "string",
|
|
912
|
+
"resolved": "string",
|
|
913
|
+
"references": {}
|
|
914
|
+
},
|
|
915
|
+
"required": false,
|
|
916
|
+
"optional": true,
|
|
917
|
+
"docs": {
|
|
918
|
+
"tags": [],
|
|
919
|
+
"text": "Display name for the user."
|
|
920
|
+
},
|
|
921
|
+
"getter": false,
|
|
922
|
+
"setter": false,
|
|
923
|
+
"attribute": "user-name",
|
|
924
|
+
"reflect": false
|
|
925
|
+
},
|
|
856
926
|
"persistentSession": {
|
|
857
927
|
"type": "boolean",
|
|
858
928
|
"mutable": false,
|
|
@@ -934,18 +1004,17 @@ export class OcsChat {
|
|
|
934
1004
|
"showStarterQuestions": {},
|
|
935
1005
|
"parsedWelcomeMessages": {},
|
|
936
1006
|
"parsedStarterQuestions": {},
|
|
1007
|
+
"generatedUserId": {},
|
|
937
1008
|
"isFullscreen": {}
|
|
938
1009
|
};
|
|
939
1010
|
}
|
|
1011
|
+
static get elementRef() { return "host"; }
|
|
940
1012
|
}
|
|
941
1013
|
OcsChat.TASK_POLLING_MAX_ATTEMPTS = 30;
|
|
942
1014
|
OcsChat.TASK_POLLING_INTERVAL_MS = 1000;
|
|
943
1015
|
OcsChat.MESSAGE_POLLING_INTERVAL_MS = 30000;
|
|
944
1016
|
OcsChat.SCROLL_DELAY_MS = 100;
|
|
945
1017
|
OcsChat.FOCUS_DELAY_MS = 100;
|
|
946
|
-
OcsChat.CHAT_WIDTH_DESKTOP = 450;
|
|
947
|
-
OcsChat.CHAT_MAX_WIDTH = 1024;
|
|
948
|
-
OcsChat.CHAT_HEIGHT_EXPANDED_RATIO = 0.83; // 83% of window height (h-5/6)
|
|
949
1018
|
OcsChat.MOBILE_BREAKPOINT = 640;
|
|
950
1019
|
OcsChat.WINDOW_MARGIN = 20;
|
|
951
1020
|
OcsChat.LOCALSTORAGE_TEST_KEY = '__ocs_test__';
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"ocs-chat.js","sourceRoot":"","sources":["../../../src/components/ocs-chat/ocs-chat.tsx"],"names":[],"mappings":"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","sourcesContent":["import { Component, Host, h, Prop, State } from '@stencil/core';\nimport {\n XMarkIcon,\n GripDotsVerticalIcon, PencilSquare, ArrowsPointingOutIcon, ArrowsPointingInIcon,\n} from './heroicons';\nimport { renderMarkdownSync as renderMarkdownComplete } from '../../utils/markdown';\n\ninterface ChatMessage {\n created_at: string;\n role: 'system' | 'user' | 'assistant';\n content: string;\n metadata?: any;\n attachments?: ChatAttachment[];\n}\n\ninterface ChatAttachment {\n name: string;\n content_type: string;\n size: number;\n content_url: string;\n}\n\ninterface ChatStartSessionResponse {\n session_id: string;\n chatbot: any;\n participant: any;\n seed_message_task_id?: string;\n}\n\ninterface ChatSendMessageResponse {\n task_id: string;\n status: 'processing' | 'completed' | 'error';\n error?: string;\n}\n\ninterface ChatTaskPollResponse {\n message?: ChatMessage;\n status: 'processing' | 'complete';\n error?: string;\n}\n\ninterface ChatPollResponse {\n messages: ChatMessage[];\n has_more: boolean;\n session_status: 'active' | 'ended';\n}\n\ninterface PointerEvent {\n clientX: number;\n clientY: number;\n}\n\ninterface SessionStorageData {\n sessionId?: string;\n messages: ChatMessage[];\n}\n\n@Component({\n tag: 'open-chat-studio-widget',\n styleUrl: 'ocs-chat.css',\n shadow: true,\n})\nexport class OcsChat {\n\n private static readonly TASK_POLLING_MAX_ATTEMPTS = 30;\n private static readonly TASK_POLLING_INTERVAL_MS = 1000;\n private static readonly MESSAGE_POLLING_INTERVAL_MS = 30000;\n\n private static readonly SCROLL_DELAY_MS = 100;\n private static readonly FOCUS_DELAY_MS = 100;\n\n private static readonly CHAT_WIDTH_DESKTOP = 450;\n private static readonly CHAT_MAX_WIDTH = 1024;\n private static readonly CHAT_HEIGHT_EXPANDED_RATIO = 0.83; // 83% of window height (h-5/6)\n private static readonly MOBILE_BREAKPOINT = 640;\n private static readonly WINDOW_MARGIN = 20;\n\n private static readonly LOCALSTORAGE_TEST_KEY = '__ocs_test__';\n\n /**\n * The ID of the chatbot to connect to.\n */\n @Prop() chatbotId!: string;\n\n /**\n * The base URL for the API (defaults to current origin).\n */\n @Prop() apiBaseUrl?: string = \"https://chatbots.dimagi.com\";\n\n /**\n * The text to display on the button.\n */\n @Prop() buttonText?: string;\n\n /**\n * URL of the icon to display on the button. If not provided, uses the default OCS logo.\n */\n @Prop() iconUrl?: string;\n\n /**\n * The shape of the chat button. 'round' makes it circular, 'square' keeps it rectangular.\n */\n @Prop() buttonShape: 'round' | 'square' = 'square';\n\n /**\n * Whether the chat widget is visible on load.\n */\n @Prop({ mutable: true }) visible: boolean = false;\n\n /**\n * The initial position of the chat widget on the screen.\n */\n @Prop({ mutable: true }) position: 'left' | 'center' | 'right' = 'right';\n\n /**\n * Welcome messages to display above starter questions (JSON array of strings)\n */\n @Prop() welcomeMessages?: string;\n\n /**\n * Array of starter questions that users can click to send (JSON array of strings)\n */\n @Prop() starterQuestions?: string;\n\n /**\n * Whether to persist session data to local storage to allow resuming previous conversations after page reload.\n */\n @Prop() persistentSession: boolean = true;\n\n /**\n * Minutes since the most recent message after which the session data in local storage will expire. Set this to\n * `0` to never expire.\n */\n @Prop() persistentSessionExpire: number = 60 * 24;\n\n /**\n * Allow the user to make the chat window full screen.\n */\n @Prop() allowFullScreen: boolean = true;\n\n @State() loaded: boolean = false;\n @State() error: string = \"\";\n @State() messages: ChatMessage[] = [];\n @State() sessionId?: string;\n @State() isLoading: boolean = false;\n @State() isTyping: boolean = false;\n @State() messageInput: string = \"\";\n @State() pollingInterval?: any;\n @State() lastPollTime?: Date;\n @State() isTaskPolling: boolean = false;\n @State() isDragging: boolean = false;\n @State() dragOffset: { x: number; y: number } = { x: 0, y: 0 };\n @State() windowPosition: { x: number; y: number } = { x: 0, y: 0 };\n @State() fullscreenPosition: { x: number } = { x: 0 };\n @State() showStarterQuestions: boolean = true;\n @State() parsedWelcomeMessages: string[] = [];\n @State() parsedStarterQuestions: string[] = [];\n @State() isFullscreen: boolean = false;\n\n private messageListRef?: HTMLDivElement;\n private textareaRef?: HTMLTextAreaElement;\n private chatWindowRef?: HTMLDivElement;\n\n\n componentWillLoad() {\n this.loaded = this.visible;\n if (!this.chatbotId) {\n this.error = 'Chatbot ID is required';\n return;\n }\n // Always try to load existing session if localStorage is available\n if (this.persistentSession && this.isLocalStorageAvailable()) {\n const { sessionId, messages } = this.loadSessionFromStorage();\n if (sessionId && messages) {\n this.sessionId = sessionId;\n this.messages = messages;\n this.showStarterQuestions = messages.length === 0;\n }\n }\n this.parseWelcomeMessages();\n this.parseStarterQuestions();\n }\n\n componentDidLoad() {\n // Only auto-start session if we don't have an existing one\n if (this.visible && !this.sessionId) {\n this.startSession();\n } else if (this.visible && this.sessionId) {\n // Resume polling for existing session\n this.startPolling();\n }\n this.initializePosition();\n window.addEventListener('resize', this.handleWindowResize);\n }\n\n disconnectedCallback() {\n this.cleanup();\n this.removeEventListeners();\n window.removeEventListener('resize', this.handleWindowResize);\n }\n\n private parseJSONProp(propValue: string | undefined, propName: string): string[] {\n try {\n if (propValue) {\n try {\n return JSON.parse(propValue);\n } catch {\n const fixedValue = propValue.replace(/'/g, '\"');\n return JSON.parse(fixedValue);\n }\n }\n } catch (error) {\n console.warn(`Failed to parse ${propName}:`, error);\n }\n return [];\n }\n\n private parseWelcomeMessages() {\n this.parsedWelcomeMessages = this.parseJSONProp(this.welcomeMessages, 'welcome messages');\n }\n\n private parseStarterQuestions() {\n this.parsedStarterQuestions = this.parseJSONProp(this.starterQuestions, 'starter questions');\n }\n\n private cleanup() {\n if (this.pollingInterval) {\n clearInterval(this.pollingInterval);\n this.pollingInterval = undefined;\n }\n this.isTaskPolling = false;\n }\n\n private getApiBaseUrl(): string {\n return this.apiBaseUrl || window.location.origin;\n }\n\n private async startSession(): Promise<void> {\n try {\n this.isLoading = true;\n this.error = '';\n\n const response = await fetch(`${this.getApiBaseUrl()}/api/chat/start/`, {\n method: 'POST',\n headers: {\n 'Content-Type': 'application/json',\n },\n body: JSON.stringify({\n chatbot_id: this.chatbotId,\n session_data: {\n source: 'widget',\n page_url: window.location.href\n }\n })\n });\n\n if (!response.ok) {\n throw new Error(`Failed to start session: ${response.statusText}`);\n }\n\n const data: ChatStartSessionResponse = await response.json();\n this.sessionId = data.session_id;\n this.saveSessionToStorage();\n\n // Handle seed message if present\n if (data.seed_message_task_id) {\n this.isTyping = true; // Show typing indicator for seed message\n await this.pollTaskResponse(data.seed_message_task_id);\n }\n\n // Start polling for messages\n this.startPolling();\n } catch (error) {\n this.error = error instanceof Error ? error.message : 'Failed to start chat session';\n } finally {\n this.isLoading = false;\n }\n }\n\n private async sendMessage(message: string): Promise<void> {\n if (!this.sessionId || !message.trim()) return;\n\n // Hide starter questions on any user interaction\n this.showStarterQuestions = false;\n\n try {\n // If this is the first user message and there are welcome messages,\n // add them to chat history as assistant messages\n if (this.messages.length === 0 && this.parsedWelcomeMessages.length > 0) {\n const now = new Date();\n const welcomeMessages: ChatMessage[] = this.parsedWelcomeMessages.map((welcomeMsg, index) => ({\n created_at: new Date(now.getTime() - (this.parsedWelcomeMessages.length - index) * 1000).toISOString(),\n role: 'assistant' as const,\n content: welcomeMsg,\n attachments: []\n }));\n this.messages = [...this.messages, ...welcomeMessages];\n }\n // Add user message immediately\n const userMessage: ChatMessage = {\n created_at: new Date().toISOString(),\n role: 'user',\n content: message.trim(),\n attachments: []\n };\n this.messages = [...this.messages, userMessage];\n this.saveSessionToStorage();\n this.messageInput = '';\n this.scrollToBottom();\n\n // Start typing indicator - it will stay on during task polling\n this.isTyping = true;\n\n const response = await fetch(`${this.getApiBaseUrl()}/api/chat/${this.sessionId}/message/`, {\n method: 'POST',\n headers: {\n 'Content-Type': 'application/json',\n },\n body: JSON.stringify({ message: message.trim() })\n });\n\n if (!response.ok) {\n throw new Error(`Failed to send message: ${response.statusText}`);\n }\n\n const data: ChatSendMessageResponse = await response.json();\n\n if (data.status === 'error') {\n throw new Error(data.error || 'Failed to send message');\n }\n\n // Poll for the response - typing indicator will be managed in pollTaskResponse\n await this.pollTaskResponse(data.task_id);\n } catch (error) {\n this.error = error instanceof Error ? error.message : 'Failed to send message';\n // Clear typing indicator on error\n this.isTyping = false;\n }\n }\n\n private handleStarterQuestionClick(question: string): void {\n this.sendMessage(question);\n }\n\n private async pollTaskResponse(taskId: string): Promise<void> {\n if (!this.sessionId) return;\n\n // Stop message polling while task polling is active\n this.isTaskPolling = true;\n this.pauseMessagePolling();\n\n let attempts = 0;\n\n const poll = async (): Promise<void> => {\n try {\n const response = await fetch(`${this.getApiBaseUrl()}/api/chat/${this.sessionId}/${taskId}/poll/`);\n\n if (!response.ok) {\n throw new Error(`Failed to poll task: ${response.statusText}`);\n }\n\n const data: ChatTaskPollResponse = await response.json();\n\n if (data.error) {\n throw new Error(data.error);\n }\n\n if (data.status === 'complete' && data.message) {\n this.messages = [...this.messages, data.message];\n this.saveSessionToStorage();\n this.scrollToBottom();\n // Task polling complete, clear typing indicator and resume message polling\n this.isTyping = false;\n this.isTaskPolling = false;\n this.resumeMessagePolling();\n this.focusInput();\n return;\n }\n\n if (data.status === 'processing' && attempts < OcsChat.TASK_POLLING_MAX_ATTEMPTS) {\n attempts++;\n setTimeout(poll, OcsChat.TASK_POLLING_INTERVAL_MS);\n } else if (attempts >= OcsChat.TASK_POLLING_MAX_ATTEMPTS) {\n // Task polling timed out, clear typing indicator and resume message polling\n this.isTyping = false;\n this.isTaskPolling = false;\n this.resumeMessagePolling();\n }\n } catch (error) {\n this.error = error instanceof Error ? error.message : 'Failed to get response';\n // Error in task polling, clear typing indicator and resume message polling\n this.isTyping = false;\n this.isTaskPolling = false;\n this.resumeMessagePolling();\n }\n };\n\n await poll();\n }\n\n private startPolling(): void {\n if (this.pollingInterval) return;\n\n this.pollingInterval = setInterval(async () => {\n // Only poll for messages if not currently polling for a task\n if (!this.isTaskPolling) {\n await this.pollForMessages();\n }\n }, OcsChat.MESSAGE_POLLING_INTERVAL_MS);\n }\n\n private pauseMessagePolling(): void {\n if (this.pollingInterval) {\n clearInterval(this.pollingInterval);\n this.pollingInterval = undefined;\n }\n }\n\n private resumeMessagePolling(): void {\n // Resume message polling after task polling is complete\n this.startPolling();\n }\n\n private async pollForMessages(): Promise<void> {\n if (!this.sessionId) return;\n\n try {\n const url = new URL(`${this.getApiBaseUrl()}/api/chat/${this.sessionId}/poll/`);\n if (this.messages && this.messages.length > 0) {\n url.searchParams.set('since', this.messages.at(-1).created_at);\n }\n\n const response = await fetch(url.toString());\n\n if (!response.ok) return; // Silently fail for polling\n\n const data: ChatPollResponse = await response.json();\n\n if (data.messages.length > 0) {\n this.messages = [...this.messages, ...data.messages];\n this.saveSessionToStorage();\n this.scrollToBottom();\n this.focusInput();\n }\n\n this.lastPollTime = new Date();\n } catch (error) {\n // Silently fail for polling\n }\n }\n\n private clearError() {\n this.error = '';\n }\n\n private scrollToBottom(): void {\n setTimeout(() => {\n if (this.messageListRef) {\n this.messageListRef.scrollTop = this.messageListRef.scrollHeight;\n }\n }, OcsChat.SCROLL_DELAY_MS);\n }\n\n private focusInput(): void {\n setTimeout(() => {\n if (this.textareaRef && !this.isTyping) {\n this.textareaRef.focus();\n }\n }, OcsChat.FOCUS_DELAY_MS);\n }\n\n private handleKeyPress(event: KeyboardEvent): void {\n if (event.key === 'Enter' && !event.shiftKey) {\n event.preventDefault();\n this.sendMessage(this.messageInput);\n }\n }\n\n private handleInputChange(event: Event): void {\n this.messageInput = (event.target as HTMLTextAreaElement).value;\n // Hide starter questions when user starts typing\n if (this.messageInput.trim().length > 0) {\n this.showStarterQuestions = false;\n }\n }\n\n private formatTime(dateString: string): string {\n const date = new Date(dateString);\n return date.toLocaleTimeString([], { hour: '2-digit', minute: '2-digit' });\n }\n\n async load() {\n this.visible = !this.visible;\n this.loaded = true;\n\n if (this.visible && !this.sessionId) {\n this.clearError();\n await this.startSession();\n } else if (!this.visible) {\n // Don't reset session when closing, allow resume\n }\n }\n\n setPosition(position: 'left' | 'center' | 'right') {\n if (position === this.position) return;\n this.position = position;\n }\n\n getPositionClasses() {\n if (this.isFullscreen) {\n return `fixed inset-0 w-full h-full max-w-screen-lg max-h-full bg-white border-0 shadow-lg transition-shadow duration-200 rounded-none overflow-hidden flex flex-col z-[9999]`;\n }\n return `fixed w-full sm:w-[450px] max-w-screen-lg h-5/6 bg-white border border-gray-200 ${this.isDragging ? 'shadow-2xl cursor-grabbing' : 'shadow-lg transition-shadow duration-200'} rounded-lg overflow-hidden flex flex-col`;\n }\n\n private getFullscreenBounds() {\n const windowWidth = window.innerWidth;\n const actualChatWidth = Math.min(windowWidth, OcsChat.CHAT_MAX_WIDTH);\n const centeredX = (windowWidth - actualChatWidth) / 2;\n const maxOffset = (windowWidth - actualChatWidth) / 2;\n\n return { windowWidth, actualChatWidth, centeredX, maxOffset };\n }\n\n getPositionStyles() {\n if (this.isFullscreen) {\n const { centeredX } = this.getFullscreenBounds();\n const finalX = centeredX + this.fullscreenPosition.x;\n\n return {\n left: `${finalX}px`,\n top: '0px',\n transform: 'none',\n };\n }\n return {\n left: `${this.windowPosition.x}px`,\n top: `${this.windowPosition.y}px`,\n };\n }\n\n private initializePosition(): void {\n const windowWidth = window.innerWidth;\n const windowHeight = window.innerHeight;\n const chatWidth = windowWidth < OcsChat.MOBILE_BREAKPOINT ? windowWidth : OcsChat.CHAT_WIDTH_DESKTOP;\n const chatHeight = windowHeight * OcsChat.CHAT_HEIGHT_EXPANDED_RATIO;\n const isMobile = windowWidth < OcsChat.MOBILE_BREAKPOINT;\n\n if (isMobile) {\n this.windowPosition = { x: 0, y: 0 };\n return;\n }\n\n switch (this.position) {\n case 'left':\n this.windowPosition = {\n x: OcsChat.WINDOW_MARGIN,\n y: windowHeight - chatHeight - OcsChat.WINDOW_MARGIN\n };\n break;\n case 'right':\n this.windowPosition = {\n x: windowWidth - chatWidth - OcsChat.WINDOW_MARGIN,\n y: windowHeight - chatHeight - OcsChat.WINDOW_MARGIN\n };\n break;\n case 'center':\n this.windowPosition = {\n x: (windowWidth - chatWidth) / 2,\n y: (windowHeight - chatHeight) / 2\n };\n break;\n }\n }\n\n private getPointerCoordinates(event: MouseEvent | TouchEvent): PointerEvent | null {\n if (event instanceof MouseEvent) {\n return { clientX: event.clientX, clientY: event.clientY };\n } else if (event instanceof TouchEvent && event.touches.length === 1) {\n const touch = event.touches[0];\n return { clientX: touch.clientX, clientY: touch.clientY };\n }\n return null;\n }\n\n private startDrag(pointer: PointerEvent): void {\n if (!this.chatWindowRef) return;\n\n this.isDragging = true;\n\n if (this.isFullscreen) {\n // For fullscreen, track relative to current position\n this.dragOffset = {\n x: pointer.clientX,\n y: pointer.clientY\n };\n } else {\n const rect = this.chatWindowRef.getBoundingClientRect();\n this.dragOffset = {\n x: pointer.clientX - rect.left,\n y: pointer.clientY - rect.top\n };\n }\n }\n\n private updateDragPosition(pointer: PointerEvent): void {\n if (!this.isDragging) return;\n\n if (this.isFullscreen) {\n // In fullscreen, only allow horizontal dragging\n const { maxOffset } = this.getFullscreenBounds();\n\n const deltaX = pointer.clientX - this.dragOffset.x;\n this.fullscreenPosition = {\n x: Math.max(-maxOffset, Math.min(maxOffset, deltaX))\n };\n } else {\n const newX = pointer.clientX - this.dragOffset.x;\n const newY = pointer.clientY - this.dragOffset.y;\n\n // Constrain chatbox to window\n const windowWidth = window.innerWidth;\n const windowHeight = window.innerHeight;\n const chatWidth = windowWidth < OcsChat.MOBILE_BREAKPOINT ? windowWidth : OcsChat.CHAT_WIDTH_DESKTOP;\n const chatHeight = windowHeight * OcsChat.CHAT_HEIGHT_EXPANDED_RATIO;\n\n this.windowPosition = {\n x: Math.max(0, Math.min(newX, windowWidth - chatWidth)),\n y: Math.max(0, Math.min(newY, windowHeight - chatHeight))\n };\n }\n }\n\n private endDrag(): void {\n this.isDragging = false;\n this.removeEventListeners();\n }\n\n private addEventListeners(): void {\n document.addEventListener('mousemove', this.handleMouseMove);\n document.addEventListener('mouseup', this.handleMouseUp);\n document.addEventListener('touchmove', this.handleTouchMove, { passive: false });\n document.addEventListener('touchend', this.handleTouchEnd);\n }\n\n private removeEventListeners(): void {\n document.removeEventListener('mousemove', this.handleMouseMove);\n document.removeEventListener('mouseup', this.handleMouseUp);\n document.removeEventListener('touchmove', this.handleTouchMove);\n document.removeEventListener('touchend', this.handleTouchEnd);\n }\n\n private handleMouseDown = (event: MouseEvent): void => {\n if (!this.isFullscreen && window.innerWidth < OcsChat.MOBILE_BREAKPOINT) return;\n if ((event.target as HTMLElement).closest('button')) return;\n\n const pointer = this.getPointerCoordinates(event);\n if (!pointer) return;\n\n this.startDrag(pointer);\n this.addEventListeners();\n event.preventDefault();\n };\n\n private handleMouseMove = (event: MouseEvent): void => {\n const pointer = this.getPointerCoordinates(event);\n if (!pointer) return;\n\n this.updateDragPosition(pointer);\n };\n\n private handleMouseUp = (): void => {\n this.endDrag();\n };\n\n private handleTouchStart = (event: TouchEvent): void => {\n if ((event.target as HTMLElement).closest('button')) return;\n if (!this.chatWindowRef) return;\n\n const pointer = this.getPointerCoordinates(event);\n if (!pointer) return;\n\n this.startDrag(pointer);\n this.addEventListeners();\n event.preventDefault();\n };\n\n private handleTouchMove = (event: TouchEvent): void => {\n const pointer = this.getPointerCoordinates(event);\n if (!pointer) return;\n\n this.updateDragPosition(pointer);\n event.preventDefault();\n };\n\n private handleTouchEnd = (): void => {\n this.endDrag();\n };\n\n private handleWindowResize = (): void => {\n this.initializePosition();\n };\n\n private getDefaultIconUrl(): string {\n return `${this.getApiBaseUrl()}/static/images/favicons/favicon.svg`;\n }\n\n private getButtonClasses(): string {\n const hasText = this.buttonText && this.buttonText.trim();\n const baseClass = hasText ? 'chat-btn-text' : 'chat-btn-icon';\n const shapeClass = this.buttonShape === 'round' ? 'round' : '';\n return `${baseClass} ${shapeClass}`.trim();\n }\n\n private renderButton() {\n const hasText = this.buttonText && this.buttonText.trim();\n const hasCustomIcon = this.iconUrl && this.iconUrl.trim();\n const iconSrc = hasCustomIcon ? this.iconUrl : this.getDefaultIconUrl();\n const buttonClasses = this.getButtonClasses();\n\n if (hasText) {\n return (\n <button\n class={buttonClasses}\n onClick={() => this.load()}\n aria-label={`Open chat - ${this.buttonText}`}\n title={this.buttonText}\n >\n <img src={iconSrc} alt=\"\" />\n <span>{this.buttonText}</span>\n </button>\n );\n } else {\n return (\n <button\n class={buttonClasses}\n onClick={() => this.load()}\n aria-label=\"Open chat\"\n title=\"Open chat\"\n >\n <img src={iconSrc} alt=\"Chat\" />\n </button>\n );\n }\n }\n\n private getStorageKeys() {\n return {\n sessionId: `ocs-chat-session-${this.chatbotId}`,\n messages: `ocs-chat-messages-${this.chatbotId}`,\n lastActivity: `ocs-chat-activity-${this.chatbotId}`\n };\n }\n\n private saveSessionToStorage(): void {\n if (!this.persistentSession) {\n return\n }\n const keys = this.getStorageKeys();\n try {\n if (this.sessionId) {\n localStorage.setItem(keys.sessionId, this.sessionId);\n localStorage.setItem(keys.lastActivity, new Date().toISOString());\n }\n localStorage.setItem(keys.messages, JSON.stringify(this.messages));\n } catch (error) {\n console.warn('Failed to save chat session to localStorage:', error);\n }\n }\n\n private loadSessionFromStorage(): SessionStorageData {\n const keys = this.getStorageKeys();\n try {\n if (this.persistentSessionExpire > 0) {\n const lastActivity = localStorage.getItem(keys.lastActivity);\n if (lastActivity) {\n const lastActivityDate = new Date(lastActivity);\n const minutesSinceActivity = (Date.now() - lastActivityDate.getTime()) / (1000 * 60);\n if (minutesSinceActivity > this.persistentSessionExpire) {\n this.clearSessionStorage();\n return {messages: []};\n }\n }\n }\n\n const storedSessionId = localStorage.getItem(keys.sessionId);\n const sessionId = storedSessionId ? storedSessionId : undefined;\n\n const messagesJson = localStorage.getItem(keys.messages);\n let messages: ChatMessage[] = [];\n\n if (messagesJson) {\n try {\n const parsedMessages = JSON.parse(messagesJson);\n messages = Array.isArray(parsedMessages) ? parsedMessages : [];\n } catch (parseError) {\n console.warn('Failed to parse messages from localStorage:', parseError);\n messages = [];\n }\n }\n\n return { sessionId, messages };\n } catch (error) {\n // fall back to starting a new session\n console.warn('Failed to load chat session from localStorage, starting new session:', error);\n return { messages: [] };\n }\n }\n\n private clearSessionStorage(): void {\n const keys = this.getStorageKeys();\n try {\n localStorage.removeItem(keys.sessionId);\n localStorage.removeItem(keys.messages);\n localStorage.removeItem(keys.lastActivity);\n } catch (error) {\n console.warn('Failed to clear chat session from localStorage:', error);\n }\n }\n\n private isLocalStorageAvailable(): boolean {\n try {\n localStorage.setItem(OcsChat.LOCALSTORAGE_TEST_KEY, 'test');\n localStorage.removeItem(OcsChat.LOCALSTORAGE_TEST_KEY);\n return true;\n } catch {\n return false;\n }\n }\n\n private async startNewChat(): Promise<void> {\n this.clearSessionStorage();\n this.sessionId = undefined;\n this.messages = [];\n this.showStarterQuestions = true;\n this.isTyping = false;\n this.error = '';\n this.cleanup();\n\n await this.startSession();\n }\n\n private toggleFullscreen(): void {\n this.isFullscreen = !this.isFullscreen;\n // Reset fullscreen position when toggling\n this.fullscreenPosition = { x: 0 };\n }\n\n render() {\n if (this.error) {\n return (\n <Host>\n <p class=\"text-red-500 p-2\">{this.error}</p>\n </Host>\n );\n }\n\n return (\n <Host>\n {this.renderButton()}\n {this.visible && (\n <div\n ref={(el) => this.chatWindowRef = el}\n id=\"ocs-chat-window\"\n class={this.getPositionClasses()}\n style={this.getPositionStyles()}\n >\n {/* Header */}\n <div\n class={`flex justify-between items-center px-2 py-2 border-b border-gray-100 ${this.isDragging ? 'cursor-grabbing' : 'cursor-grab'} active:bg-gray-50 hover:bg-gray-25 transition-colors duration-150`}\n onMouseDown={this.handleMouseDown}\n onTouchStart={this.handleTouchStart}\n >\n {/* Drag indicator */}\n <div class=\"hidden sm:flex gap-1\">\n <div class=\"flex gap-0.5 ml-2 pointer-events-none\">\n <GripDotsVerticalIcon/>\n </div>\n </div>\n <div class=\"sm:hidden\"></div>\n <div class=\"flex gap-1 items-center\">\n {/* Fullscreen toggle button */}\n {this.allowFullScreen && <button\n class=\"hidden sm:block p-1.5 rounded-md transition-colors duration-200 hover:bg-gray-100 text-gray-500\"\n onClick={() => this.toggleFullscreen()}\n title={this.isFullscreen ? \"Exit fullscreen\" : \"Enter fullscreen\"}\n aria-label={this.isFullscreen ? \"Exit fullscreen\" : \"Enter fullscreen\"}\n >\n {this.isFullscreen ? <ArrowsPointingInIcon/> : <ArrowsPointingOutIcon/>}\n </button>}\n {/* New Chat button */}\n {this.sessionId && this.messages.length > 0 && (\n <button\n class=\"p-1.5 rounded-md transition-colors duration-200 hover:bg-gray-100 text-gray-500\"\n onClick={() => this.startNewChat()}\n title=\"Start new chat\"\n aria-label=\"Start new chat\"\n >\n <PencilSquare/>\n </button>\n )}\n <button\n class=\"p-1.5 hover:bg-gray-100 rounded-md transition-colors duration-200 text-gray-500\"\n onClick={() => this.visible = false}\n aria-label=\"Close\"\n >\n <XMarkIcon/>\n </button>\n </div>\n </div>\n\n {/* Chat Content */}\n <div class=\"flex flex-col flex-grow overflow-hidden\">\n {/* Loading State */}\n {this.isLoading && !this.sessionId && (\n <div class=\"flex items-center justify-center flex-grow\">\n <div class=\"loading-spinner\"></div>\n <span class=\"ml-2 text-gray-500\">Starting chat...</span>\n </div>\n )}\n\n {/* Messages */}\n {this.sessionId && (\n <div\n ref={(el) => this.messageListRef = el}\n class=\"flex-grow overflow-y-auto p-4 space-y-2\"\n >\n {this.messages.length === 0 && !this.isTyping && this.parsedWelcomeMessages.length > 0 && (\n <div class=\"space-y-2\">\n {/* Welcome Messages */}\n {this.parsedWelcomeMessages.map((message, index) => (\n <div key={`welcome-${index}`} class=\"flex justify-start\">\n <div class=\"bg-gray-200 text-gray-800 max-w-xs lg:max-w-md px-4 py-2 rounded-lg\">\n <div\n class=\"chat-markdown\"\n innerHTML={renderMarkdownComplete(message)}\n ></div>\n </div>\n </div>\n ))}\n </div>\n )}\n {/* Regular Chat Messages */}\n {this.messages.map((message, index) => (\n <div\n key={index}\n class={{\n 'flex': true,\n 'justify-end': message.role === 'user',\n 'justify-start': message.role !== 'user'\n }}\n >\n <div\n class={{\n 'max-w-xs lg:max-w-md px-4 py-2 rounded-lg': true,\n 'bg-blue-500 text-white': message.role === 'user',\n 'bg-gray-200 text-gray-800': message.role === 'assistant',\n 'bg-gray-100 text-gray-600 text-sm': message.role === 'system'\n }}\n >\n <div\n class=\"chat-markdown\"\n innerHTML={renderMarkdownComplete(message.content)}\n ></div>\n {message.attachments && message.attachments.length > 0 && (\n <div class=\"mt-2 space-y-1\">\n {message.attachments.map((attachment, attachmentIndex) => (\n <a\n key={attachmentIndex}\n href={attachment.content_url}\n target=\"_blank\"\n rel=\"noopener noreferrer\"\n class=\"block text-sm underline hover:no-underline\"\n >\n 📎 {attachment.name}\n </a>\n ))}\n </div>\n )}\n <div class=\"text-xs opacity-70 mt-1\">\n {this.formatTime(message.created_at)}\n </div>\n </div>\n </div>\n ))}\n {/* Typing Indicator */}\n {this.isTyping && (\n <div>\n <div class=\"h-1.5 w-full overflow-hidden\">\n <div class=\"animate-progress w-full h-full bg-blue-200 origin-left-right rounded-lg\"></div>\n </div>\n <div class=\"w-full text-xs opacity-70 justify-center\">\n <span>Preparing response</span>\n <span class=\"loading animate-dots\"></span>\n </div>\n </div>\n )}\n </div>\n )}\n\n {/* Starter Questions */}\n {this.sessionId && this.showStarterQuestions && this.messages.length === 0 && !this.isTyping && (\n <div class=\"p-4 space-y-2\">\n {this.parsedStarterQuestions.map((question, index) => (\n <div key={`starter-${index}`} class=\"flex justify-end\">\n <button\n class=\"starter-question\"\n onClick={() => this.handleStarterQuestionClick(question)}\n >\n {question}\n </button>\n </div>\n ))}\n </div>\n )}\n\n {/* Input Area */}\n {this.sessionId && (\n <div class=\"border-t border-gray-200 p-4 text-sm\">\n <div class=\"flex gap-2\">\n <textarea\n ref={(el) => this.textareaRef = el}\n class=\"flex-grow px-3 py-2 border border-gray-300 rounded-md resize-none focus:outline-none focus:ring-2 focus:ring-blue-500 focus:border-transparent\"\n rows={1}\n placeholder=\"Type your message...\"\n value={this.messageInput}\n onInput={(e) => this.handleInputChange(e)}\n onKeyPress={(e) => this.handleKeyPress(e)}\n disabled={this.isTyping}\n ></textarea>\n <button\n class={{\n 'px-4 py-2 rounded-md font-medium transition-colors duration-200': true,\n 'bg-blue-500 hover:bg-blue-600 text-white': !this.isTyping && !!this.messageInput.trim(),\n 'bg-gray-300 text-gray-500 cursor-not-allowed': this.isTyping || !this.messageInput.trim()\n }}\n onClick={() => this.sendMessage(this.messageInput)}\n disabled={this.isTyping || !this.messageInput.trim()}\n >\n Send\n </button>\n </div>\n </div>\n )}\n </div>\n </div>\n )}\n </Host>\n );\n }\n}\n"]}
|
|
1
|
+
{"version":3,"file":"ocs-chat.js","sourceRoot":"","sources":["../../../src/components/ocs-chat/ocs-chat.tsx"],"names":[],"mappings":"AAAA,OAAO,EAAE,SAAS,EAAE,IAAI,EAAE,CAAC,EAAE,IAAI,EAAE,KAAK,EAAE,OAAO,EAAE,MAAM,eAAe,CAAC;AACzE,OAAO,EACL,SAAS,EACT,oBAAoB,EAAE,YAAY,EAAE,qBAAqB,EAAE,oBAAoB,GAChF,MAAM,aAAa,CAAC;AACrB,OAAO,EAAE,kBAAkB,IAAI,sBAAsB,EAAE,MAAM,sBAAsB,CAAC;AACpF,OAAO,EAAE,WAAW,EAAE,MAAM,mBAAmB,CAAC;AAyDhD,MAAM,OAAO,OAAO;IALpB;QAwBE;;WAEG;QACK,eAAU,GAAY,6BAA6B,CAAC;QAY5D;;WAEG;QACK,gBAAW,GAAuB,QAAQ,CAAC;QAEnD;;WAEG;QACsB,YAAO,GAAY,KAAK,CAAC;QAElD;;WAEG;QACsB,aAAQ,GAAgC,OAAO,CAAC;QAoBzE;;WAEG;QACK,sBAAiB,GAAY,IAAI,CAAC;QAE1C;;;WAGG;QACK,4BAAuB,GAAW,EAAE,GAAG,EAAE,CAAC;QAElD;;WAEG;QACK,oBAAe,GAAY,IAAI,CAAC;QAE/B,WAAM,GAAY,KAAK,CAAC;QACxB,UAAK,GAAW,EAAE,CAAC;QACnB,aAAQ,GAAkB,EAAE,CAAC;QAE7B,cAAS,GAAY,KAAK,CAAC;QAC3B,aAAQ,GAAY,KAAK,CAAC;QAC1B,iBAAY,GAAW,EAAE,CAAC;QAG1B,kBAAa,GAAY,KAAK,CAAC;QAC/B,eAAU,GAAY,KAAK,CAAC;QAC5B,eAAU,GAA6B,EAAE,CAAC,EAAE,CAAC,EAAE,CAAC,EAAE,CAAC,EAAE,CAAC;QACtD,mBAAc,GAA6B,EAAE,CAAC,EAAE,CAAC,EAAE,CAAC,EAAE,CAAC,EAAE,CAAC;QAC1D,uBAAkB,GAAkB,EAAE,CAAC,EAAE,CAAC,EAAE,CAAC;QAC7C,yBAAoB,GAAY,IAAI,CAAC;QACrC,0BAAqB,GAAa,EAAE,CAAC;QACrC,2BAAsB,GAAa,EAAE,CAAC;QAEtC,iBAAY,GAAY,KAAK,CAAC;QAK/B,qBAAgB,GAAW,GAAG,CAAC;QAC/B,oBAAe,GAAW,GAAG,CAAC;QAC9B,8BAAyB,GAAW,IAAI,CAAC;QA6fzC,oBAAe,GAAG,CAAC,KAAiB,EAAQ,EAAE;YACpD,IAAI,CAAC,IAAI,CAAC,YAAY,IAAI,MAAM,CAAC,UAAU,GAAG,OAAO,CAAC,iBAAiB;gBAAE,OAAO;YAChF,IAAK,KAAK,CAAC,MAAsB,CAAC,OAAO,CAAC,QAAQ,CAAC;gBAAE,OAAO;YAE5D,MAAM,OAAO,GAAG,IAAI,CAAC,qBAAqB,CAAC,KAAK,CAAC,CAAC;YAClD,IAAI,CAAC,OAAO;gBAAE,OAAO;YAErB,IAAI,CAAC,SAAS,CAAC,OAAO,CAAC,CAAC;YACxB,IAAI,CAAC,iBAAiB,EAAE,CAAC;YACzB,KAAK,CAAC,cAAc,EAAE,CAAC;QACzB,CAAC,CAAC;QAEM,oBAAe,GAAG,CAAC,KAAiB,EAAQ,EAAE;YACpD,MAAM,OAAO,GAAG,IAAI,CAAC,qBAAqB,CAAC,KAAK,CAAC,CAAC;YAClD,IAAI,CAAC,OAAO;gBAAE,OAAO;YAErB,IAAI,CAAC,kBAAkB,CAAC,OAAO,CAAC,CAAC;QACnC,CAAC,CAAC;QAEM,kBAAa,GAAG,GAAS,EAAE;YACjC,IAAI,CAAC,OAAO,EAAE,CAAC;QACjB,CAAC,CAAC;QAEM,qBAAgB,GAAG,CAAC,KAAiB,EAAQ,EAAE;YACrD,IAAK,KAAK,CAAC,MAAsB,CAAC,OAAO,CAAC,QAAQ,CAAC;gBAAE,OAAO;YAC5D,IAAI,CAAC,IAAI,CAAC,aAAa;gBAAE,OAAO;YAEhC,MAAM,OAAO,GAAG,IAAI,CAAC,qBAAqB,CAAC,KAAK,CAAC,CAAC;YAClD,IAAI,CAAC,OAAO;gBAAE,OAAO;YAErB,IAAI,CAAC,SAAS,CAAC,OAAO,CAAC,CAAC;YACxB,IAAI,CAAC,iBAAiB,EAAE,CAAC;YACzB,KAAK,CAAC,cAAc,EAAE,CAAC;QACzB,CAAC,CAAC;QAEM,oBAAe,GAAG,CAAC,KAAiB,EAAQ,EAAE;YACpD,MAAM,OAAO,GAAG,IAAI,CAAC,qBAAqB,CAAC,KAAK,CAAC,CAAC;YAClD,IAAI,CAAC,OAAO;gBAAE,OAAO;YAErB,IAAI,CAAC,kBAAkB,CAAC,OAAO,CAAC,CAAC;YACjC,KAAK,CAAC,cAAc,EAAE,CAAC;QACzB,CAAC,CAAC;QAEM,mBAAc,GAAG,GAAS,EAAE;YAClC,IAAI,CAAC,OAAO,EAAE,CAAC;QACjB,CAAC,CAAC;QAEM,uBAAkB,GAAG,GAAS,EAAE;YACtC,IAAI,CAAC,kBAAkB,EAAE,CAAC;QAC5B,CAAC,CAAC;KAsXH;IAh6BC,iBAAiB;QACf,IAAI,CAAC,MAAM,GAAG,IAAI,CAAC,OAAO,CAAC;QAC3B,IAAI,CAAC,IAAI,CAAC,SAAS,EAAE,CAAC;YACpB,IAAI,CAAC,KAAK,GAAG,wBAAwB,CAAC;YACtC,OAAO;QACT,CAAC;QACD,mEAAmE;QACnE,IAAI,IAAI,CAAC,iBAAiB,IAAI,IAAI,CAAC,uBAAuB,EAAE,EAAE,CAAC;YAC7D,MAAM,EAAE,SAAS,EAAE,QAAQ,EAAE,GAAG,IAAI,CAAC,sBAAsB,EAAE,CAAC;YAC9D,IAAI,SAAS,IAAI,QAAQ,EAAE,CAAC;gBAC1B,IAAI,CAAC,SAAS,GAAG,SAAS,CAAC;gBAC3B,IAAI,CAAC,QAAQ,GAAG,QAAQ,CAAC;gBACzB,IAAI,CAAC,oBAAoB,GAAG,QAAQ,CAAC,MAAM,KAAK,CAAC,CAAC;YACpD,CAAC;QACH,CAAC;QACD,IAAI,CAAC,oBAAoB,EAAE,CAAC;QAC5B,IAAI,CAAC,qBAAqB,EAAE,CAAC;IAC/B,CAAC;IAED,gBAAgB;QACd,2DAA2D;QAC3D,IAAI,IAAI,CAAC,OAAO,IAAI,CAAC,IAAI,CAAC,SAAS,EAAE,CAAC;YACpC,IAAI,CAAC,YAAY,EAAE,CAAC;QACtB,CAAC;aAAM,IAAI,IAAI,CAAC,OAAO,IAAI,IAAI,CAAC,SAAS,EAAE,CAAC;YAC1C,sCAAsC;YACtC,IAAI,CAAC,YAAY,EAAE,CAAC;QACtB,CAAC;QACD,MAAM,aAAa,GAAG,gBAAgB,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;QAClD,MAAM,eAAe,GAAG,aAAa,CAAC,gBAAgB,CAAC,sBAAsB,CAAC,CAAC;QAC/E,MAAM,cAAc,GAAG,aAAa,CAAC,gBAAgB,CAAC,qBAAqB,CAAC,CAAC;QAC7E,MAAM,kBAAkB,GAAG,aAAa,CAAC,gBAAgB,CAAC,gCAAgC,CAAC,CAAC;QAC5F,IAAI,CAAC,gBAAgB,GAAG,WAAW,CAAC,eAAe,EAAE,MAAM,CAAC,WAAW,EAAE,IAAI,CAAC,gBAAgB,CAAC,CAAC;QAChG,IAAI,CAAC,eAAe,GAAG,WAAW,CAAC,cAAc,EAAE,MAAM,CAAC,UAAU,EAAE,IAAI,CAAC,eAAe,CAAC,CAAC;QAC5F,IAAI,CAAC,yBAAyB,GAAG,WAAW,CAAC,kBAAkB,EAAE,MAAM,CAAC,UAAU,EAAE,IAAI,CAAC,yBAAyB,CAAC,CAAC;QACpH,IAAI,CAAC,kBAAkB,EAAE,CAAC;QAC1B,MAAM,CAAC,gBAAgB,CAAC,QAAQ,EAAE,IAAI,CAAC,kBAAkB,CAAC,CAAC;IAC7D,CAAC;IAED,oBAAoB;QAClB,IAAI,CAAC,OAAO,EAAE,CAAC;QACf,IAAI,CAAC,oBAAoB,EAAE,CAAC;QAC5B,MAAM,CAAC,mBAAmB,CAAC,QAAQ,EAAE,IAAI,CAAC,kBAAkB,CAAC,CAAC;IAChE,CAAC;IAEO,aAAa,CAAC,SAA6B,EAAE,QAAgB;QACnE,IAAI,CAAC;YACH,IAAI,SAAS,EAAE,CAAC;gBACd,IAAI,CAAC;oBACH,OAAO,IAAI,CAAC,KAAK,CAAC,SAAS,CAAC,CAAC;gBAC/B,CAAC;gBAAC,WAAM,CAAC;oBACP,MAAM,UAAU,GAAG,SAAS,CAAC,OAAO,CAAC,IAAI,EAAE,GAAG,CAAC,CAAC;oBAChD,OAAO,IAAI,CAAC,KAAK,CAAC,UAAU,CAAC,CAAC;gBAChC,CAAC;YACH,CAAC;QACH,CAAC;QAAC,OAAO,KAAK,EAAE,CAAC;YACf,OAAO,CAAC,IAAI,CAAC,mBAAmB,QAAQ,GAAG,EAAE,KAAK,CAAC,CAAC;QACtD,CAAC;QACD,OAAO,EAAE,CAAC;IACZ,CAAC;IAEO,oBAAoB;QAC1B,IAAI,CAAC,qBAAqB,GAAG,IAAI,CAAC,aAAa,CAAC,IAAI,CAAC,eAAe,EAAE,kBAAkB,CAAC,CAAC;IAC5F,CAAC;IAEO,qBAAqB;QAC3B,IAAI,CAAC,sBAAsB,GAAG,IAAI,CAAC,aAAa,CAAC,IAAI,CAAC,gBAAgB,EAAE,mBAAmB,CAAC,CAAC;IAC/F,CAAC;IAEO,OAAO;QACb,IAAI,IAAI,CAAC,eAAe,EAAE,CAAC;YACzB,aAAa,CAAC,IAAI,CAAC,eAAe,CAAC,CAAC;YACpC,IAAI,CAAC,eAAe,GAAG,SAAS,CAAC;QACnC,CAAC;QACD,IAAI,CAAC,aAAa,GAAG,KAAK,CAAC;IAC7B,CAAC;IAEO,aAAa;QACnB,OAAO,IAAI,CAAC,UAAU,IAAI,MAAM,CAAC,QAAQ,CAAC,MAAM,CAAC;IACnD,CAAC;IAEO,KAAK,CAAC,YAAY;QACxB,IAAI,CAAC;YACH,IAAI,CAAC,SAAS,GAAG,IAAI,CAAC;YACtB,IAAI,CAAC,KAAK,GAAG,EAAE,CAAC;YAEhB,MAAM,MAAM,GAAG,IAAI,CAAC,mBAAmB,EAAE,CAAC;YAE1C,MAAM,WAAW,GAAQ;gBACvB,UAAU,EAAE,IAAI,CAAC,SAAS;gBAC1B,YAAY,EAAE;oBACZ,MAAM,EAAE,QAAQ;oBAChB,QAAQ,EAAE,MAAM,CAAC,QAAQ,CAAC,IAAI;iBAC/B;gBACD,qBAAqB,EAAE,MAAM;aAC9B,CAAC;YAEF,IAAI,IAAI,CAAC,QAAQ,EAAE,CAAC;gBAClB,WAAW,CAAC,gBAAgB,GAAG,IAAI,CAAC,QAAQ,CAAC;YAC/C,CAAC;YAED,MAAM,QAAQ,GAAG,MAAM,KAAK,CAAC,GAAG,IAAI,CAAC,aAAa,EAAE,kBAAkB,EAAE;gBACtE,MAAM,EAAE,MAAM;gBACd,OAAO,EAAE;oBACP,cAAc,EAAE,kBAAkB;iBACnC;gBACD,IAAI,EAAE,IAAI,CAAC,SAAS,CAAC,WAAW,CAAC;aAClC,CAAC,CAAC;YAEH,IAAI,CAAC,QAAQ,CAAC,EAAE,EAAE,CAAC;gBACjB,MAAM,IAAI,KAAK,CAAC,4BAA4B,QAAQ,CAAC,UAAU,EAAE,CAAC,CAAC;YACrE,CAAC;YAED,MAAM,IAAI,GAA6B,MAAM,QAAQ,CAAC,IAAI,EAAE,CAAC;YAC7D,IAAI,CAAC,SAAS,GAAG,IAAI,CAAC,UAAU,CAAC;YACjC,IAAI,CAAC,oBAAoB,EAAE,CAAC;YAE5B,iCAAiC;YACjC,IAAI,IAAI,CAAC,oBAAoB,EAAE,CAAC;gBAC9B,IAAI,CAAC,QAAQ,GAAG,IAAI,CAAC,CAAE,yCAAyC;gBAChE,MAAM,IAAI,CAAC,gBAAgB,CAAC,IAAI,CAAC,oBAAoB,CAAC,CAAC;YACzD,CAAC;YAED,6BAA6B;YAC7B,IAAI,CAAC,YAAY,EAAE,CAAC;QACtB,CAAC;QAAC,OAAO,KAAK,EAAE,CAAC;YACf,IAAI,CAAC,KAAK,GAAG,KAAK,YAAY,KAAK,CAAC,CAAC,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC,CAAC,8BAA8B,CAAC;QACvF,CAAC;gBAAS,CAAC;YACT,IAAI,CAAC,SAAS,GAAG,KAAK,CAAC;QACzB,CAAC;IACH,CAAC;IAEO,KAAK,CAAC,WAAW,CAAC,OAAe;QACvC,IAAI,CAAC,IAAI,CAAC,SAAS,IAAI,CAAC,OAAO,CAAC,IAAI,EAAE;YAAE,OAAO;QAE/C,iDAAiD;QACjD,IAAI,CAAC,oBAAoB,GAAG,KAAK,CAAC;QAElC,IAAI,CAAC;YACH,oEAAoE;YACpE,iDAAiD;YACjD,IAAI,IAAI,CAAC,QAAQ,CAAC,MAAM,KAAK,CAAC,IAAI,IAAI,CAAC,qBAAqB,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;gBACxE,MAAM,GAAG,GAAG,IAAI,IAAI,EAAE,CAAC;gBACvB,MAAM,eAAe,GAAkB,IAAI,CAAC,qBAAqB,CAAC,GAAG,CAAC,CAAC,UAAU,EAAE,KAAK,EAAE,EAAE,CAAC,CAAC;oBAC5F,UAAU,EAAE,IAAI,IAAI,CAAC,GAAG,CAAC,OAAO,EAAE,GAAG,CAAC,IAAI,CAAC,qBAAqB,CAAC,MAAM,GAAG,KAAK,CAAC,GAAG,IAAI,CAAC,CAAC,WAAW,EAAE;oBACtG,IAAI,EAAE,WAAoB;oBAC1B,OAAO,EAAE,UAAU;oBACnB,WAAW,EAAE,EAAE;iBAChB,CAAC,CAAC,CAAC;gBACJ,IAAI,CAAC,QAAQ,GAAG,CAAC,GAAG,IAAI,CAAC,QAAQ,EAAE,GAAG,eAAe,CAAC,CAAC;YACzD,CAAC;YACD,+BAA+B;YAC/B,MAAM,WAAW,GAAgB;gBAC/B,UAAU,EAAE,IAAI,IAAI,EAAE,CAAC,WAAW,EAAE;gBACpC,IAAI,EAAE,MAAM;gBACZ,OAAO,EAAE,OAAO,CAAC,IAAI,EAAE;gBACvB,WAAW,EAAE,EAAE;aAChB,CAAC;YACF,IAAI,CAAC,QAAQ,GAAG,CAAC,GAAG,IAAI,CAAC,QAAQ,EAAE,WAAW,CAAC,CAAC;YAChD,IAAI,CAAC,oBAAoB,EAAE,CAAC;YAC5B,IAAI,CAAC,YAAY,GAAG,EAAE,CAAC;YACvB,IAAI,CAAC,cAAc,EAAE,CAAC;YAEtB,+DAA+D;YAC/D,IAAI,CAAC,QAAQ,GAAG,IAAI,CAAC;YAErB,MAAM,QAAQ,GAAG,MAAM,KAAK,CAAC,GAAG,IAAI,CAAC,aAAa,EAAE,aAAa,IAAI,CAAC,SAAS,WAAW,EAAE;gBAC1F,MAAM,EAAE,MAAM;gBACd,OAAO,EAAE;oBACP,cAAc,EAAE,kBAAkB;iBACnC;gBACD,IAAI,EAAE,IAAI,CAAC,SAAS,CAAC,EAAE,OAAO,EAAE,OAAO,CAAC,IAAI,EAAE,EAAE,CAAC;aAClD,CAAC,CAAC;YAEH,IAAI,CAAC,QAAQ,CAAC,EAAE,EAAE,CAAC;gBACjB,MAAM,IAAI,KAAK,CAAC,2BAA2B,QAAQ,CAAC,UAAU,EAAE,CAAC,CAAC;YACpE,CAAC;YAED,MAAM,IAAI,GAA4B,MAAM,QAAQ,CAAC,IAAI,EAAE,CAAC;YAE5D,IAAI,IAAI,CAAC,MAAM,KAAK,OAAO,EAAE,CAAC;gBAC5B,MAAM,IAAI,KAAK,CAAC,IAAI,CAAC,KAAK,IAAI,wBAAwB,CAAC,CAAC;YAC1D,CAAC;YAED,+EAA+E;YAC/E,MAAM,IAAI,CAAC,gBAAgB,CAAC,IAAI,CAAC,OAAO,CAAC,CAAC;QAC5C,CAAC;QAAC,OAAO,KAAK,EAAE,CAAC;YACf,IAAI,CAAC,KAAK,GAAG,KAAK,YAAY,KAAK,CAAC,CAAC,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC,CAAC,wBAAwB,CAAC;YAC/E,kCAAkC;YAClC,IAAI,CAAC,QAAQ,GAAG,KAAK,CAAC;QACxB,CAAC;IACH,CAAC;IAEO,0BAA0B,CAAC,QAAgB;QACjD,IAAI,CAAC,WAAW,CAAC,QAAQ,CAAC,CAAC;IAC7B,CAAC;IAEO,KAAK,CAAC,gBAAgB,CAAC,MAAc;QAC3C,IAAI,CAAC,IAAI,CAAC,SAAS;YAAE,OAAO;QAE5B,oDAAoD;QACpD,IAAI,CAAC,aAAa,GAAG,IAAI,CAAC;QAC1B,IAAI,CAAC,mBAAmB,EAAE,CAAC;QAE3B,IAAI,QAAQ,GAAG,CAAC,CAAC;QAEjB,MAAM,IAAI,GAAG,KAAK,IAAmB,EAAE;YACrC,IAAI,CAAC;gBACH,MAAM,QAAQ,GAAG,MAAM,KAAK,CAAC,GAAG,IAAI,CAAC,aAAa,EAAE,aAAa,IAAI,CAAC,SAAS,IAAI,MAAM,QAAQ,CAAC,CAAC;gBAEnG,IAAI,CAAC,QAAQ,CAAC,EAAE,EAAE,CAAC;oBACjB,MAAM,IAAI,KAAK,CAAC,wBAAwB,QAAQ,CAAC,UAAU,EAAE,CAAC,CAAC;gBACjE,CAAC;gBAED,MAAM,IAAI,GAAyB,MAAM,QAAQ,CAAC,IAAI,EAAE,CAAC;gBAEzD,IAAI,IAAI,CAAC,KAAK,EAAE,CAAC;oBACf,MAAM,IAAI,KAAK,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC;gBAC9B,CAAC;gBAED,IAAI,IAAI,CAAC,MAAM,KAAK,UAAU,IAAI,IAAI,CAAC,OAAO,EAAE,CAAC;oBAC/C,IAAI,CAAC,QAAQ,GAAG,CAAC,GAAG,IAAI,CAAC,QAAQ,EAAE,IAAI,CAAC,OAAO,CAAC,CAAC;oBACjD,IAAI,CAAC,oBAAoB,EAAE,CAAC;oBAC5B,IAAI,CAAC,cAAc,EAAE,CAAC;oBACtB,2EAA2E;oBAC3E,IAAI,CAAC,QAAQ,GAAG,KAAK,CAAC;oBACtB,IAAI,CAAC,aAAa,GAAG,KAAK,CAAC;oBAC3B,IAAI,CAAC,oBAAoB,EAAE,CAAC;oBAC5B,IAAI,CAAC,UAAU,EAAE,CAAC;oBAClB,OAAO;gBACT,CAAC;gBAED,IAAI,IAAI,CAAC,MAAM,KAAK,YAAY,IAAI,QAAQ,GAAG,OAAO,CAAC,yBAAyB,EAAE,CAAC;oBACjF,QAAQ,EAAE,CAAC;oBACX,UAAU,CAAC,IAAI,EAAE,OAAO,CAAC,wBAAwB,CAAC,CAAC;gBACrD,CAAC;qBAAM,IAAI,QAAQ,IAAI,OAAO,CAAC,yBAAyB,EAAE,CAAC;oBACzD,4EAA4E;oBAC5E,IAAI,CAAC,QAAQ,GAAG,KAAK,CAAC;oBACtB,IAAI,CAAC,aAAa,GAAG,KAAK,CAAC;oBAC3B,IAAI,CAAC,oBAAoB,EAAE,CAAC;gBAC9B,CAAC;YACH,CAAC;YAAC,OAAO,KAAK,EAAE,CAAC;gBACf,IAAI,CAAC,KAAK,GAAG,KAAK,YAAY,KAAK,CAAC,CAAC,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC,CAAC,wBAAwB,CAAC;gBAC/E,2EAA2E;gBAC3E,IAAI,CAAC,QAAQ,GAAG,KAAK,CAAC;gBACtB,IAAI,CAAC,aAAa,GAAG,KAAK,CAAC;gBAC3B,IAAI,CAAC,oBAAoB,EAAE,CAAC;YAC9B,CAAC;QACH,CAAC,CAAC;QAEF,MAAM,IAAI,EAAE,CAAC;IACf,CAAC;IAEO,YAAY;QAClB,IAAI,IAAI,CAAC,eAAe;YAAE,OAAO;QAEjC,IAAI,CAAC,eAAe,GAAG,WAAW,CAAC,KAAK,IAAI,EAAE;YAC5C,6DAA6D;YAC7D,IAAI,CAAC,IAAI,CAAC,aAAa,EAAE,CAAC;gBACxB,MAAM,IAAI,CAAC,eAAe,EAAE,CAAC;YAC/B,CAAC;QACH,CAAC,EAAE,OAAO,CAAC,2BAA2B,CAAC,CAAC;IAC1C,CAAC;IAEO,mBAAmB;QACzB,IAAI,IAAI,CAAC,eAAe,EAAE,CAAC;YACzB,aAAa,CAAC,IAAI,CAAC,eAAe,CAAC,CAAC;YACpC,IAAI,CAAC,eAAe,GAAG,SAAS,CAAC;QACnC,CAAC;IACH,CAAC;IAEO,oBAAoB;QAC1B,wDAAwD;QACxD,IAAI,CAAC,YAAY,EAAE,CAAC;IACtB,CAAC;IAEO,KAAK,CAAC,eAAe;QAC3B,IAAI,CAAC,IAAI,CAAC,SAAS;YAAE,OAAO;QAE5B,IAAI,CAAC;YACH,MAAM,GAAG,GAAG,IAAI,GAAG,CAAC,GAAG,IAAI,CAAC,aAAa,EAAE,aAAa,IAAI,CAAC,SAAS,QAAQ,CAAC,CAAC;YAChF,IAAI,IAAI,CAAC,QAAQ,IAAI,IAAI,CAAC,QAAQ,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;gBAC9C,GAAG,CAAC,YAAY,CAAC,GAAG,CAAC,OAAO,EAAE,IAAI,CAAC,QAAQ,CAAC,EAAE,CAAC,CAAC,CAAC,CAAC,CAAC,UAAU,CAAC,CAAC;YACjE,CAAC;YAED,MAAM,QAAQ,GAAG,MAAM,KAAK,CAAC,GAAG,CAAC,QAAQ,EAAE,CAAC,CAAC;YAE7C,IAAI,CAAC,QAAQ,CAAC,EAAE;gBAAE,OAAO,CAAC,4BAA4B;YAEtD,MAAM,IAAI,GAAqB,MAAM,QAAQ,CAAC,IAAI,EAAE,CAAC;YAErD,IAAI,IAAI,CAAC,QAAQ,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;gBAC7B,IAAI,CAAC,QAAQ,GAAG,CAAC,GAAG,IAAI,CAAC,QAAQ,EAAE,GAAG,IAAI,CAAC,QAAQ,CAAC,CAAC;gBACrD,IAAI,CAAC,oBAAoB,EAAE,CAAC;gBAC5B,IAAI,CAAC,cAAc,EAAE,CAAC;gBACtB,IAAI,CAAC,UAAU,EAAE,CAAC;YACpB,CAAC;YAED,IAAI,CAAC,YAAY,GAAG,IAAI,IAAI,EAAE,CAAC;QACjC,CAAC;QAAC,OAAO,KAAK,EAAE,CAAC;YACf,4BAA4B;QAC9B,CAAC;IACH,CAAC;IAEO,UAAU;QAChB,IAAI,CAAC,KAAK,GAAG,EAAE,CAAC;IAClB,CAAC;IAEO,cAAc;QACpB,UAAU,CAAC,GAAG,EAAE;YACd,IAAI,IAAI,CAAC,cAAc,EAAE,CAAC;gBACxB,IAAI,CAAC,cAAc,CAAC,SAAS,GAAG,IAAI,CAAC,cAAc,CAAC,YAAY,CAAC;YACnE,CAAC;QACH,CAAC,EAAE,OAAO,CAAC,eAAe,CAAC,CAAC;IAC9B,CAAC;IAEO,UAAU;QAChB,UAAU,CAAC,GAAG,EAAE;YACd,IAAI,IAAI,CAAC,WAAW,IAAI,CAAC,IAAI,CAAC,QAAQ,EAAE,CAAC;gBACvC,IAAI,CAAC,WAAW,CAAC,KAAK,EAAE,CAAC;YAC3B,CAAC;QACH,CAAC,EAAE,OAAO,CAAC,cAAc,CAAC,CAAC;IAC7B,CAAC;IAEO,cAAc,CAAC,KAAoB;QACzC,IAAI,KAAK,CAAC,GAAG,KAAK,OAAO,IAAI,CAAC,KAAK,CAAC,QAAQ,EAAE,CAAC;YAC7C,KAAK,CAAC,cAAc,EAAE,CAAC;YACvB,IAAI,CAAC,WAAW,CAAC,IAAI,CAAC,YAAY,CAAC,CAAC;QACtC,CAAC;IACH,CAAC;IAEO,iBAAiB,CAAC,KAAY;QACpC,IAAI,CAAC,YAAY,GAAI,KAAK,CAAC,MAA8B,CAAC,KAAK,CAAC;QAChE,iDAAiD;QACjD,IAAI,IAAI,CAAC,YAAY,CAAC,IAAI,EAAE,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;YACxC,IAAI,CAAC,oBAAoB,GAAG,KAAK,CAAC;QACpC,CAAC;IACH,CAAC;IAEO,UAAU,CAAC,UAAkB;QACnC,MAAM,IAAI,GAAG,IAAI,IAAI,CAAC,UAAU,CAAC,CAAC;QAClC,OAAO,IAAI,CAAC,kBAAkB,CAAC,EAAE,EAAE,EAAE,IAAI,EAAE,SAAS,EAAE,MAAM,EAAE,SAAS,EAAE,CAAC,CAAC;IAC7E,CAAC;IAED,KAAK,CAAC,IAAI;QACR,IAAI,CAAC,OAAO,GAAG,CAAC,IAAI,CAAC,OAAO,CAAC;QAC7B,IAAI,CAAC,MAAM,GAAG,IAAI,CAAC;QAEnB,IAAI,IAAI,CAAC,OAAO,IAAI,CAAC,IAAI,CAAC,SAAS,EAAE,CAAC;YACpC,IAAI,CAAC,UAAU,EAAE,CAAC;YAClB,MAAM,IAAI,CAAC,YAAY,EAAE,CAAC;QAC5B,CAAC;aAAM,IAAI,CAAC,IAAI,CAAC,OAAO,EAAE,CAAC;YACzB,iDAAiD;QACnD,CAAC;IACH,CAAC;IAED,WAAW,CAAC,QAAqC;QAC/C,IAAI,QAAQ,KAAK,IAAI,CAAC,QAAQ;YAAE,OAAO;QACvC,IAAI,CAAC,QAAQ,GAAG,QAAQ,CAAC;IAC3B,CAAC;IAED,kBAAkB;QAChB,IAAI,IAAI,CAAC,YAAY,EAAE,CAAC;YACtB,OAAO,wBAAwB,CAAC;QAClC,CAAC;QACD,MAAM,WAAW,GAAG,oBAAoB,CAAC;QACzC,MAAM,aAAa,GAAG,IAAI,CAAC,UAAU,CAAC,CAAC,CAAC,uBAAuB,CAAC,CAAC,CAAC,EAAE,CAAC;QACrE,OAAO,WAAW,GAAG,aAAa,CAAC;IACrC,CAAC;IAEO,mBAAmB;QACzB,MAAM,WAAW,GAAG,MAAM,CAAC,UAAU,CAAC;QACtC,MAAM,eAAe,GAAG,IAAI,CAAC,GAAG,CAAC,WAAW,EAAE,IAAI,CAAC,yBAAyB,CAAC,CAAC;QAC9E,MAAM,SAAS,GAAG,CAAC,WAAW,GAAG,eAAe,CAAC,GAAG,CAAC,CAAC;QACtD,MAAM,SAAS,GAAG,CAAC,WAAW,GAAG,eAAe,CAAC,GAAG,CAAC,CAAC;QAEtD,OAAO,EAAE,WAAW,EAAE,eAAe,EAAE,SAAS,EAAE,SAAS,EAAE,CAAC;IAChE,CAAC;IAED,iBAAiB;QACf,IAAI,IAAI,CAAC,YAAY,EAAE,CAAC;YACtB,MAAM,EAAE,SAAS,EAAE,GAAG,IAAI,CAAC,mBAAmB,EAAE,CAAC;YACjD,MAAM,MAAM,GAAG,SAAS,GAAG,IAAI,CAAC,kBAAkB,CAAC,CAAC,CAAC;YAErD,OAAO;gBACL,IAAI,EAAE,GAAG,MAAM,IAAI;gBACnB,GAAG,EAAE,KAAK;gBACV,SAAS,EAAE,MAAM;aAClB,CAAC;QACJ,CAAC;QACD,OAAO;YACL,IAAI,EAAE,GAAG,IAAI,CAAC,cAAc,CAAC,CAAC,IAAI;YAClC,GAAG,EAAE,GAAG,IAAI,CAAC,cAAc,CAAC,CAAC,IAAI;SAClC,CAAC;IACJ,CAAC;IAEO,kBAAkB;QACxB,MAAM,WAAW,GAAG,MAAM,CAAC,UAAU,CAAC;QACtC,MAAM,YAAY,GAAG,MAAM,CAAC,WAAW,CAAC;QACxC,MAAM,SAAS,GAAG,WAAW,GAAG,OAAO,CAAC,iBAAiB,CAAC,CAAC,CAAC,WAAW,CAAC,CAAC,CAAC,IAAI,CAAC,eAAe,CAAC;QAC/F,MAAM,QAAQ,GAAG,WAAW,GAAG,OAAO,CAAC,iBAAiB,CAAC;QAEzD,IAAI,QAAQ,EAAE,CAAC;YACb,IAAI,CAAC,cAAc,GAAG,EAAE,CAAC,EAAE,CAAC,EAAE,CAAC,EAAE,CAAC,EAAE,CAAC;YACrC,OAAO;QACT,CAAC;QAED,QAAQ,IAAI,CAAC,QAAQ,EAAE,CAAC;YACtB,KAAK,MAAM;gBACT,IAAI,CAAC,cAAc,GAAG;oBACpB,CAAC,EAAE,OAAO,CAAC,aAAa;oBACxB,CAAC,EAAE,YAAY,GAAG,IAAI,CAAC,gBAAgB,GAAG,OAAO,CAAC,aAAa;iBAChE,CAAC;gBACF,MAAM;YACR,KAAK,OAAO;gBACV,IAAI,CAAC,cAAc,GAAG;oBACpB,CAAC,EAAE,WAAW,GAAG,SAAS,GAAG,OAAO,CAAC,aAAa;oBAClD,CAAC,EAAE,YAAY,GAAG,IAAI,CAAC,gBAAgB,GAAG,OAAO,CAAC,aAAa;iBAChE,CAAC;gBACF,MAAM;YACR,KAAK,QAAQ;gBACX,IAAI,CAAC,cAAc,GAAG;oBACpB,CAAC,EAAE,CAAC,WAAW,GAAG,SAAS,CAAC,GAAG,CAAC;oBAChC,CAAC,EAAE,CAAC,YAAY,GAAG,IAAI,CAAC,gBAAgB,CAAC,GAAG,CAAC;iBAC9C,CAAC;gBACF,MAAM;QACV,CAAC;IACH,CAAC;IAEO,qBAAqB,CAAC,KAA8B;QAC1D,IAAI,KAAK,YAAY,UAAU,EAAE,CAAC;YAChC,OAAO,EAAE,OAAO,EAAE,KAAK,CAAC,OAAO,EAAE,OAAO,EAAE,KAAK,CAAC,OAAO,EAAE,CAAC;QAC5D,CAAC;aAAM,IAAI,KAAK,YAAY,UAAU,IAAI,KAAK,CAAC,OAAO,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;YACrE,MAAM,KAAK,GAAG,KAAK,CAAC,OAAO,CAAC,CAAC,CAAC,CAAC;YAC/B,OAAO,EAAE,OAAO,EAAE,KAAK,CAAC,OAAO,EAAE,OAAO,EAAE,KAAK,CAAC,OAAO,EAAE,CAAC;QAC5D,CAAC;QACD,OAAO,IAAI,CAAC;IACd,CAAC;IAEO,SAAS,CAAC,OAAqB;QACrC,IAAI,CAAC,IAAI,CAAC,aAAa;YAAE,OAAO;QAEhC,IAAI,CAAC,UAAU,GAAG,IAAI,CAAC;QAEvB,IAAI,IAAI,CAAC,YAAY,EAAE,CAAC;YACtB,qDAAqD;YACrD,IAAI,CAAC,UAAU,GAAG;gBAChB,CAAC,EAAE,OAAO,CAAC,OAAO;gBAClB,CAAC,EAAE,OAAO,CAAC,OAAO;aACnB,CAAC;QACJ,CAAC;aAAM,CAAC;YACN,MAAM,IAAI,GAAG,IAAI,CAAC,aAAa,CAAC,qBAAqB,EAAE,CAAC;YACxD,IAAI,CAAC,UAAU,GAAG;gBAChB,CAAC,EAAE,OAAO,CAAC,OAAO,GAAG,IAAI,CAAC,IAAI;gBAC9B,CAAC,EAAE,OAAO,CAAC,OAAO,GAAG,IAAI,CAAC,GAAG;aAC9B,CAAC;QACJ,CAAC;IACH,CAAC;IAEO,kBAAkB,CAAC,OAAqB;QAC9C,IAAI,CAAC,IAAI,CAAC,UAAU;YAAE,OAAO;QAE7B,IAAI,IAAI,CAAC,YAAY,EAAE,CAAC;YACtB,gDAAgD;YAChD,MAAM,EAAE,SAAS,EAAE,GAAG,IAAI,CAAC,mBAAmB,EAAE,CAAC;YAEjD,MAAM,MAAM,GAAG,OAAO,CAAC,OAAO,GAAG,IAAI,CAAC,UAAU,CAAC,CAAC,CAAC;YACnD,IAAI,CAAC,kBAAkB,GAAG;gBACxB,CAAC,EAAE,IAAI,CAAC,GAAG,CAAC,CAAC,SAAS,EAAE,IAAI,CAAC,GAAG,CAAC,SAAS,EAAE,MAAM,CAAC,CAAC;aACrD,CAAC;QACJ,CAAC;aAAM,CAAC;YACN,MAAM,IAAI,GAAG,OAAO,CAAC,OAAO,GAAG,IAAI,CAAC,UAAU,CAAC,CAAC,CAAC;YACjD,MAAM,IAAI,GAAG,OAAO,CAAC,OAAO,GAAG,IAAI,CAAC,UAAU,CAAC,CAAC,CAAC;YAEjD,8BAA8B;YAC9B,MAAM,WAAW,GAAG,MAAM,CAAC,UAAU,CAAC;YACtC,MAAM,YAAY,GAAG,MAAM,CAAC,WAAW,CAAC;YACxC,MAAM,SAAS,GAAG,WAAW,GAAG,OAAO,CAAC,iBAAiB,CAAC,CAAC,CAAC,WAAW,CAAC,CAAC,CAAC,IAAI,CAAC,eAAe,CAAC;YAC/F,MAAM,UAAU,GAAG,IAAI,CAAC,aAAa,CAAC,YAAY,CAAC;YAEnD,IAAI,CAAC,cAAc,GAAG;gBACpB,CAAC,EAAE,IAAI,CAAC,GAAG,CAAC,CAAC,EAAE,IAAI,CAAC,GAAG,CAAC,IAAI,EAAE,WAAW,GAAG,SAAS,CAAC,CAAC;gBACvD,CAAC,EAAE,IAAI,CAAC,GAAG,CAAC,CAAC,EAAE,IAAI,CAAC,GAAG,CAAC,IAAI,EAAE,YAAY,GAAG,UAAU,CAAC,CAAC;aAC1D,CAAC;QACJ,CAAC;IACH,CAAC;IAEO,OAAO;QACb,IAAI,CAAC,UAAU,GAAG,KAAK,CAAC;QACxB,IAAI,CAAC,oBAAoB,EAAE,CAAC;IAC9B,CAAC;IAEO,iBAAiB;QACvB,QAAQ,CAAC,gBAAgB,CAAC,WAAW,EAAE,IAAI,CAAC,eAAe,CAAC,CAAC;QAC7D,QAAQ,CAAC,gBAAgB,CAAC,SAAS,EAAE,IAAI,CAAC,aAAa,CAAC,CAAC;QACzD,QAAQ,CAAC,gBAAgB,CAAC,WAAW,EAAE,IAAI,CAAC,eAAe,EAAE,EAAE,OAAO,EAAE,KAAK,EAAE,CAAC,CAAC;QACjF,QAAQ,CAAC,gBAAgB,CAAC,UAAU,EAAE,IAAI,CAAC,cAAc,CAAC,CAAC;IAC7D,CAAC;IAEO,oBAAoB;QAC1B,QAAQ,CAAC,mBAAmB,CAAC,WAAW,EAAE,IAAI,CAAC,eAAe,CAAC,CAAC;QAChE,QAAQ,CAAC,mBAAmB,CAAC,SAAS,EAAE,IAAI,CAAC,aAAa,CAAC,CAAC;QAC5D,QAAQ,CAAC,mBAAmB,CAAC,WAAW,EAAE,IAAI,CAAC,eAAe,CAAC,CAAC;QAChE,QAAQ,CAAC,mBAAmB,CAAC,UAAU,EAAE,IAAI,CAAC,cAAc,CAAC,CAAC;IAChE,CAAC;IAqDO,iBAAiB;QACvB,OAAO,GAAG,IAAI,CAAC,aAAa,EAAE,qCAAqC,CAAC;IACtE,CAAC;IAEO,gBAAgB;QACtB,MAAM,OAAO,GAAG,IAAI,CAAC,UAAU,IAAI,IAAI,CAAC,UAAU,CAAC,IAAI,EAAE,CAAC;QAC1D,MAAM,SAAS,GAAG,OAAO,CAAC,CAAC,CAAC,eAAe,CAAC,CAAC,CAAC,eAAe,CAAC;QAC9D,MAAM,UAAU,GAAG,IAAI,CAAC,WAAW,KAAK,OAAO,CAAC,CAAC,CAAC,OAAO,CAAC,CAAC,CAAC,EAAE,CAAC;QAC/D,OAAO,GAAG,SAAS,IAAI,UAAU,EAAE,CAAC,IAAI,EAAE,CAAC;IAC7C,CAAC;IAEO,YAAY;QAClB,MAAM,OAAO,GAAG,IAAI,CAAC,UAAU,IAAI,IAAI,CAAC,UAAU,CAAC,IAAI,EAAE,CAAC;QAC1D,MAAM,aAAa,GAAG,IAAI,CAAC,OAAO,IAAI,IAAI,CAAC,OAAO,CAAC,IAAI,EAAE,CAAC;QAC1D,MAAM,OAAO,GAAG,aAAa,CAAC,CAAC,CAAC,IAAI,CAAC,OAAO,CAAC,CAAC,CAAC,IAAI,CAAC,iBAAiB,EAAE,CAAC;QACxE,MAAM,aAAa,GAAG,IAAI,CAAC,gBAAgB,EAAE,CAAC;QAE9C,IAAI,OAAO,EAAE,CAAC;YACZ,OAAO,CACL,cACE,KAAK,EAAE,aAAa,EACpB,OAAO,EAAE,GAAG,EAAE,CAAC,IAAI,CAAC,IAAI,EAAE,gBACd,eAAe,IAAI,CAAC,UAAU,EAAE,EAC5C,KAAK,EAAE,IAAI,CAAC,UAAU;gBAEtB,WAAK,GAAG,EAAE,OAAO,EAAE,GAAG,EAAC,EAAE,GAAG;gBAC5B,gBAAO,IAAI,CAAC,UAAU,CAAQ,CACvB,CACV,CAAC;QACJ,CAAC;aAAM,CAAC;YACN,OAAO,CACL,cACE,KAAK,EAAE,aAAa,EACpB,OAAO,EAAE,GAAG,EAAE,CAAC,IAAI,CAAC,IAAI,EAAE,gBACf,WAAW,EACtB,KAAK,EAAC,WAAW;gBAEjB,WAAK,GAAG,EAAE,OAAO,EAAE,GAAG,EAAC,MAAM,GAAG,CACzB,CACV,CAAC;QACJ,CAAC;IACH,CAAC;IAEO,cAAc;QACpB,OAAO;YACL,SAAS,EAAE,oBAAoB,IAAI,CAAC,SAAS,EAAE;YAC/C,QAAQ,EAAE,qBAAqB,IAAI,CAAC,SAAS,EAAE;YAC/C,YAAY,EAAE,qBAAqB,IAAI,CAAC,SAAS,EAAE;SACpD,CAAC;IACJ,CAAC;IAEO,oBAAoB;QAC1B,IAAI,CAAC,IAAI,CAAC,iBAAiB,EAAE,CAAC;YAC5B,OAAM;QACR,CAAC;QACD,MAAM,IAAI,GAAG,IAAI,CAAC,cAAc,EAAE,CAAC;QACnC,IAAI,CAAC;YACH,IAAI,IAAI,CAAC,SAAS,EAAE,CAAC;gBACnB,YAAY,CAAC,OAAO,CAAC,IAAI,CAAC,SAAS,EAAE,IAAI,CAAC,SAAS,CAAC,CAAC;gBACrD,YAAY,CAAC,OAAO,CAAC,IAAI,CAAC,YAAY,EAAE,IAAI,IAAI,EAAE,CAAC,WAAW,EAAE,CAAC,CAAC;YACpE,CAAC;YACD,YAAY,CAAC,OAAO,CAAC,IAAI,CAAC,QAAQ,EAAE,IAAI,CAAC,SAAS,CAAC,IAAI,CAAC,QAAQ,CAAC,CAAC,CAAC;QACrE,CAAC;QAAC,OAAO,KAAK,EAAE,CAAC;YACf,OAAO,CAAC,IAAI,CAAC,8CAA8C,EAAE,KAAK,CAAC,CAAC;QACtE,CAAC;IACH,CAAC;IAEO,sBAAsB;QAC5B,MAAM,IAAI,GAAG,IAAI,CAAC,cAAc,EAAE,CAAC;QACnC,IAAI,CAAC;YACH,IAAI,IAAI,CAAC,uBAAuB,GAAG,CAAC,EAAE,CAAC;gBACrC,MAAM,YAAY,GAAG,YAAY,CAAC,OAAO,CAAC,IAAI,CAAC,YAAY,CAAC,CAAC;gBAC7D,IAAI,YAAY,EAAE,CAAC;oBACjB,MAAM,gBAAgB,GAAG,IAAI,IAAI,CAAC,YAAY,CAAC,CAAC;oBAChD,MAAM,oBAAoB,GAAG,CAAC,IAAI,CAAC,GAAG,EAAE,GAAG,gBAAgB,CAAC,OAAO,EAAE,CAAC,GAAG,CAAC,IAAI,GAAG,EAAE,CAAC,CAAC;oBACrF,IAAI,oBAAoB,GAAG,IAAI,CAAC,uBAAuB,EAAE,CAAC;wBACxD,IAAI,CAAC,mBAAmB,EAAE,CAAC;wBAC3B,OAAO,EAAC,QAAQ,EAAE,EAAE,EAAC,CAAC;oBACxB,CAAC;gBACH,CAAC;YACH,CAAC;YAED,MAAM,eAAe,GAAG,YAAY,CAAC,OAAO,CAAC,IAAI,CAAC,SAAS,CAAC,CAAC;YAC7D,MAAM,SAAS,GAAG,eAAe,CAAC,CAAC,CAAC,eAAe,CAAC,CAAC,CAAC,SAAS,CAAC;YAEhE,MAAM,YAAY,GAAG,YAAY,CAAC,OAAO,CAAC,IAAI,CAAC,QAAQ,CAAC,CAAC;YACzD,IAAI,QAAQ,GAAkB,EAAE,CAAC;YAEjC,IAAI,YAAY,EAAE,CAAC;gBACjB,IAAI,CAAC;oBACH,MAAM,cAAc,GAAG,IAAI,CAAC,KAAK,CAAC,YAAY,CAAC,CAAC;oBAChD,QAAQ,GAAG,KAAK,CAAC,OAAO,CAAC,cAAc,CAAC,CAAC,CAAC,CAAC,cAAc,CAAC,CAAC,CAAC,EAAE,CAAC;gBACjE,CAAC;gBAAC,OAAO,UAAU,EAAE,CAAC;oBACpB,OAAO,CAAC,IAAI,CAAC,6CAA6C,EAAE,UAAU,CAAC,CAAC;oBACxE,QAAQ,GAAG,EAAE,CAAC;gBAChB,CAAC;YACH,CAAC;YAED,OAAO,EAAE,SAAS,EAAE,QAAQ,EAAE,CAAC;QACjC,CAAC;QAAC,OAAO,KAAK,EAAE,CAAC;YACf,sCAAsC;YACtC,OAAO,CAAC,IAAI,CAAC,sEAAsE,EAAE,KAAK,CAAC,CAAC;YAC5F,OAAO,EAAE,QAAQ,EAAE,EAAE,EAAE,CAAC;QAC1B,CAAC;IACH,CAAC;IAEO,mBAAmB;QACzB,IAAI,IAAI,CAAC,MAAM,EAAE,CAAC;YAChB,OAAO,IAAI,CAAC,MAAM,CAAC;QACrB,CAAC;QAED,IAAI,IAAI,CAAC,eAAe,EAAE,CAAC;YACzB,OAAO,IAAI,CAAC,eAAe,CAAC;QAC9B,CAAC;QAED,MAAM,UAAU,GAAG,aAAa,CAAC;QACjC,MAAM,MAAM,GAAG,YAAY,CAAC,OAAO,CAAC,UAAU,CAAC,CAAC;QAChD,IAAI,MAAM,EAAE,CAAC;YACX,IAAI,CAAC,eAAe,GAAG,MAAM,CAAC;YAC9B,OAAO,MAAM,CAAC;QAChB,CAAC;QAED,MAAM,KAAK,GAAG,IAAI,UAAU,CAAC,CAAC,CAAC,CAAC;QAChC,MAAM,CAAC,MAAM,CAAC,eAAe,CAAC,KAAK,CAAC,CAAC;QACrC,MAAM,YAAY,GAAG,KAAK,CAAC,IAAI,CAAC,KAAK,EAAE,IAAI,CAAC,EAAE,CAAC,IAAI,CAAC,QAAQ,CAAC,EAAE,CAAC,CAAC,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC,MAAM,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC;QACxF,MAAM,SAAS,GAAG,OAAO,IAAI,CAAC,GAAG,EAAE,IAAI,YAAY,EAAE,CAAC;QACtD,IAAI,CAAC,eAAe,GAAG,SAAS,CAAC;QACjC,YAAY,CAAC,OAAO,CAAC,UAAU,EAAE,SAAS,CAAC,CAAC;QAE5C,OAAO,SAAS,CAAC;IACnB,CAAC;IAEO,mBAAmB;QACzB,MAAM,IAAI,GAAG,IAAI,CAAC,cAAc,EAAE,CAAC;QACnC,IAAI,CAAC;YACH,YAAY,CAAC,UAAU,CAAC,IAAI,CAAC,SAAS,CAAC,CAAC;YACxC,YAAY,CAAC,UAAU,CAAC,IAAI,CAAC,QAAQ,CAAC,CAAC;YACvC,YAAY,CAAC,UAAU,CAAC,IAAI,CAAC,YAAY,CAAC,CAAC;QAC7C,CAAC;QAAC,OAAO,KAAK,EAAE,CAAC;YACf,OAAO,CAAC,IAAI,CAAC,iDAAiD,EAAE,KAAK,CAAC,CAAC;QACzE,CAAC;IACH,CAAC;IAEO,uBAAuB;QAC7B,IAAI,CAAC;YACH,YAAY,CAAC,OAAO,CAAC,OAAO,CAAC,qBAAqB,EAAE,MAAM,CAAC,CAAC;YAC5D,YAAY,CAAC,UAAU,CAAC,OAAO,CAAC,qBAAqB,CAAC,CAAC;YACvD,OAAO,IAAI,CAAC;QACd,CAAC;QAAC,WAAM,CAAC;YACP,OAAO,KAAK,CAAC;QACf,CAAC;IACH,CAAC;IAEO,KAAK,CAAC,YAAY;QACxB,IAAI,CAAC,mBAAmB,EAAE,CAAC;QAC3B,IAAI,CAAC,SAAS,GAAG,SAAS,CAAC;QAC3B,IAAI,CAAC,QAAQ,GAAG,EAAE,CAAC;QACnB,IAAI,CAAC,oBAAoB,GAAG,IAAI,CAAC;QACjC,IAAI,CAAC,QAAQ,GAAG,KAAK,CAAC;QACtB,IAAI,CAAC,KAAK,GAAG,EAAE,CAAC;QAChB,IAAI,CAAC,OAAO,EAAE,CAAC;QAEf,MAAM,IAAI,CAAC,YAAY,EAAE,CAAC;IAC5B,CAAC;IAEO,gBAAgB;QACtB,IAAI,CAAC,YAAY,GAAG,CAAC,IAAI,CAAC,YAAY,CAAC;QACvC,0CAA0C;QAC1C,IAAI,CAAC,kBAAkB,GAAG,EAAE,CAAC,EAAE,CAAC,EAAE,CAAC;IACrC,CAAC;IAED,MAAM;QACJ,IAAI,IAAI,CAAC,KAAK,EAAE,CAAC;YACf,OAAO,CACL,EAAC,IAAI;gBACH,SAAG,KAAK,EAAC,eAAe,IAAE,IAAI,CAAC,KAAK,CAAK,CACpC,CACR,CAAC;QACJ,CAAC;QAED,OAAO,CACL,EAAC,IAAI;YACF,IAAI,CAAC,YAAY,EAAE;YACnB,IAAI,CAAC,OAAO,IAAI,CACf,WACE,GAAG,EAAE,CAAC,EAAE,EAAE,EAAE,CAAC,IAAI,CAAC,aAAa,GAAG,EAAE,EACpC,EAAE,EAAC,iBAAiB,EACpB,KAAK,EAAE,IAAI,CAAC,kBAAkB,EAAE,EAChC,KAAK,EAAE,IAAI,CAAC,iBAAiB,EAAE;gBAG/B,WACE,KAAK,EAAE,eAAe,IAAI,CAAC,UAAU,CAAC,CAAC,CAAC,sBAAsB,CAAC,CAAC,CAAC,uBAAuB,EAAE,EAC1F,WAAW,EAAE,IAAI,CAAC,eAAe,EACjC,YAAY,EAAE,IAAI,CAAC,gBAAgB;oBAGnC,WAAK,KAAK,EAAC,gBAAgB;wBACzB,WAAK,KAAK,EAAC,WAAW;4BACpB,EAAC,oBAAoB,OAAE,CACnB,CACF;oBACN,WAAK,KAAK,EAAC,aAAa,GAAO;oBAC/B,WAAK,KAAK,EAAC,gBAAgB;wBAExB,IAAI,CAAC,eAAe,IAAI,cACvB,KAAK,EAAC,iCAAiC,EACvC,OAAO,EAAE,GAAG,EAAE,CAAC,IAAI,CAAC,gBAAgB,EAAE,EACtC,KAAK,EAAE,IAAI,CAAC,YAAY,CAAC,CAAC,CAAC,iBAAiB,CAAC,CAAC,CAAC,kBAAkB,gBACrD,IAAI,CAAC,YAAY,CAAC,CAAC,CAAC,iBAAiB,CAAC,CAAC,CAAC,kBAAkB,IAErE,IAAI,CAAC,YAAY,CAAC,CAAC,CAAC,EAAC,oBAAoB,OAAE,CAAC,CAAC,CAAC,EAAC,qBAAqB,OAAE,CAChE;wBAER,IAAI,CAAC,SAAS,IAAI,IAAI,CAAC,QAAQ,CAAC,MAAM,GAAG,CAAC,IAAI,CAC7C,cACE,KAAK,EAAC,eAAe,EACrB,OAAO,EAAE,GAAG,EAAE,CAAC,IAAI,CAAC,YAAY,EAAE,EAClC,KAAK,EAAC,gBAAgB,gBACX,gBAAgB;4BAE3B,EAAC,YAAY,OAAE,CACR,CACV;wBACD,cACE,KAAK,EAAC,eAAe,EACrB,OAAO,EAAE,GAAG,EAAE,CAAC,IAAI,CAAC,OAAO,GAAG,KAAK,gBACxB,OAAO;4BAElB,EAAC,SAAS,OAAE,CACL,CACL,CACF;gBAGN,WAAK,KAAK,EAAC,cAAc;oBAEtB,IAAI,CAAC,SAAS,IAAI,CAAC,IAAI,CAAC,SAAS,IAAI,CACpC,WAAK,KAAK,EAAC,mBAAmB;wBAC5B,WAAK,KAAK,EAAC,iBAAiB,GAAO;wBACnC,YAAM,KAAK,EAAC,cAAc,uBAAwB,CAC9C,CACP;oBAGA,IAAI,CAAC,SAAS,IAAI,CACjB,WACE,GAAG,EAAE,CAAC,EAAE,EAAE,EAAE,CAAC,IAAI,CAAC,cAAc,GAAG,EAAE,EACrC,KAAK,EAAC,oBAAoB;wBAEzB,IAAI,CAAC,QAAQ,CAAC,MAAM,KAAK,CAAC,IAAI,CAAC,IAAI,CAAC,QAAQ,IAAI,IAAI,CAAC,qBAAqB,CAAC,MAAM,GAAG,CAAC,IAAI,CACxF,WAAK,KAAK,EAAC,kBAAkB,IAE1B,IAAI,CAAC,qBAAqB,CAAC,GAAG,CAAC,CAAC,OAAO,EAAE,KAAK,EAAE,EAAE,CAAC,CAClD,WAAK,GAAG,EAAE,WAAW,KAAK,EAAE,EAAE,KAAK,EAAC,mCAAmC;4BACrE,WAAK,KAAK,EAAC,yCAAyC;gCAClD,WACE,KAAK,EAAC,eAAe,EACrB,SAAS,EAAE,sBAAsB,CAAC,OAAO,CAAC,GACrC,CACH,CACF,CACP,CAAC,CACE,CACP;wBAEA,IAAI,CAAC,QAAQ,CAAC,GAAG,CAAC,CAAC,OAAO,EAAE,KAAK,EAAE,EAAE,CAAC,CACrC,WACE,GAAG,EAAE,KAAK,EACV,KAAK,EAAE,eACL,OAAO,CAAC,IAAI,KAAK,MAAM,CAAC,CAAC,CAAC,kBAAkB,CAAC,CAAC,CAAC,uBACjD,EAAE;4BAEF,WACE,KAAK,EAAE,kBACL,OAAO,CAAC,IAAI,KAAK,MAAM;oCACrB,CAAC,CAAC,qBAAqB;oCACvB,CAAC,CAAC,OAAO,CAAC,IAAI,KAAK,WAAW;wCAC9B,CAAC,CAAC,0BAA0B;wCAC5B,CAAC,CAAC,uBACN,EAAE;gCAEF,WACE,KAAK,EAAC,eAAe,EACrB,SAAS,EAAE,sBAAsB,CAAC,OAAO,CAAC,OAAO,CAAC,GAC7C;gCACN,OAAO,CAAC,WAAW,IAAI,OAAO,CAAC,WAAW,CAAC,MAAM,GAAG,CAAC,IAAI,CACxD,WAAK,KAAK,EAAC,qBAAqB,IAC7B,OAAO,CAAC,WAAW,CAAC,GAAG,CAAC,CAAC,UAAU,EAAE,eAAe,EAAE,EAAE,CAAC,CACxD,SACE,GAAG,EAAE,eAAe,EACpB,IAAI,EAAE,UAAU,CAAC,WAAW,EAC5B,MAAM,EAAC,QAAQ,EACf,GAAG,EAAC,qBAAqB,EACzB,KAAK,EAAC,iBAAiB;;oCAEnB,UAAU,CAAC,IAAI,CACjB,CACL,CAAC,CACE,CACP;gCACD,WAAK,KAAK,EAAC,mBAAmB,IAC3B,IAAI,CAAC,UAAU,CAAC,OAAO,CAAC,UAAU,CAAC,CAChC,CACF,CACF,CACP,CAAC;wBAED,IAAI,CAAC,QAAQ,IAAI,CAChB;4BACE,WAAK,KAAK,EAAC,kBAAkB;gCAC3B,WAAK,KAAK,EAAC,iBAAiB,GAAO,CAC/B;4BACN,WAAK,KAAK,EAAC,aAAa;gCACtB,qCAA+B;gCAC/B,YAAM,KAAK,EAAC,aAAa,GAAQ,CAC7B,CACF,CACP,CACG,CACP;oBAGA,IAAI,CAAC,SAAS,IAAI,IAAI,CAAC,oBAAoB,IAAI,IAAI,CAAC,QAAQ,CAAC,MAAM,KAAK,CAAC,IAAI,CAAC,IAAI,CAAC,QAAQ,IAAI,CAC9F,WAAK,KAAK,EAAC,mBAAmB,IAC3B,IAAI,CAAC,sBAAsB,CAAC,GAAG,CAAC,CAAC,QAAQ,EAAE,KAAK,EAAE,EAAE,CAAC,CACpD,WAAK,GAAG,EAAE,WAAW,KAAK,EAAE,EAAE,KAAK,EAAC,sBAAsB;wBACxD,cACE,KAAK,EAAC,kBAAkB,EACxB,OAAO,EAAE,GAAG,EAAE,CAAC,IAAI,CAAC,0BAA0B,CAAC,QAAQ,CAAC,IAEvD,QAAQ,CACF,CACL,CACP,CAAC,CACE,CACP;oBAGA,IAAI,CAAC,SAAS,IAAI,CACjB,WAAK,KAAK,EAAC,YAAY;wBACrB,WAAK,KAAK,EAAC,iBAAiB;4BAC1B,gBACE,GAAG,EAAE,CAAC,EAAE,EAAE,EAAE,CAAC,IAAI,CAAC,WAAW,GAAG,EAAE,EAClC,KAAK,EAAC,kBAAkB,EACxB,IAAI,EAAE,CAAC,EACP,WAAW,EAAC,sBAAsB,EAClC,KAAK,EAAE,IAAI,CAAC,YAAY,EACxB,OAAO,EAAE,CAAC,CAAC,EAAE,EAAE,CAAC,IAAI,CAAC,iBAAiB,CAAC,CAAC,CAAC,EACzC,UAAU,EAAE,CAAC,CAAC,EAAE,EAAE,CAAC,IAAI,CAAC,cAAc,CAAC,CAAC,CAAC,EACzC,QAAQ,EAAE,IAAI,CAAC,QAAQ,GACb;4BACZ,cACE,KAAK,EAAE,eACL,CAAC,IAAI,CAAC,QAAQ,IAAI,CAAC,CAAC,IAAI,CAAC,YAAY,CAAC,IAAI,EAAE;oCAC1C,CAAC,CAAC,qBAAqB;oCACvB,CAAC,CAAC,sBACN,EAAE,EACF,OAAO,EAAE,GAAG,EAAE,CAAC,IAAI,CAAC,WAAW,CAAC,IAAI,CAAC,YAAY,CAAC,EAClD,QAAQ,EAAE,IAAI,CAAC,QAAQ,IAAI,CAAC,IAAI,CAAC,YAAY,CAAC,IAAI,EAAE,WAG7C,CACL,CACF,CACP,CACG,CACF,CACP,CACI,CACR,CAAC;IACJ,CAAC;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AA7gCuB,iCAAyB,GAAG,EAAE,AAAL,CAAM;AAC/B,gCAAwB,GAAG,IAAI,AAAP,CAAQ;AAChC,mCAA2B,GAAG,KAAK,AAAR,CAAS;AAEpC,uBAAe,GAAG,GAAG,AAAN,CAAO;AACtB,sBAAc,GAAG,GAAG,AAAN,CAAO;AAErB,yBAAiB,GAAG,GAAG,AAAN,CAAO;AACxB,qBAAa,GAAG,EAAE,AAAL,CAAM;AAEnB,6BAAqB,GAAG,cAAc,AAAjB,CAAkB","sourcesContent":["import { Component, Host, h, Prop, State, Element } from '@stencil/core';\nimport {\n XMarkIcon,\n GripDotsVerticalIcon, PencilSquare, ArrowsPointingOutIcon, ArrowsPointingInIcon,\n} from './heroicons';\nimport { renderMarkdownSync as renderMarkdownComplete } from '../../utils/markdown';\nimport { varToPixels } from '../../utils/utils';\n\ninterface ChatMessage {\n created_at: string;\n role: 'system' | 'user' | 'assistant';\n content: string;\n metadata?: any;\n attachments?: ChatAttachment[];\n}\n\ninterface ChatAttachment {\n name: string;\n content_type: string;\n size: number;\n content_url: string;\n}\n\ninterface ChatStartSessionResponse {\n session_id: string;\n chatbot: any;\n participant: any;\n seed_message_task_id?: string;\n}\n\ninterface ChatSendMessageResponse {\n task_id: string;\n status: 'processing' | 'completed' | 'error';\n error?: string;\n}\n\ninterface ChatTaskPollResponse {\n message?: ChatMessage;\n status: 'processing' | 'complete';\n error?: string;\n}\n\ninterface ChatPollResponse {\n messages: ChatMessage[];\n has_more: boolean;\n session_status: 'active' | 'ended';\n}\n\ninterface PointerEvent {\n clientX: number;\n clientY: number;\n}\n\ninterface SessionStorageData {\n sessionId?: string;\n messages: ChatMessage[];\n}\n\n@Component({\n tag: 'open-chat-studio-widget',\n styleUrl: 'ocs-chat.css',\n shadow: true,\n})\nexport class OcsChat {\n\n private static readonly TASK_POLLING_MAX_ATTEMPTS = 30;\n private static readonly TASK_POLLING_INTERVAL_MS = 1000;\n private static readonly MESSAGE_POLLING_INTERVAL_MS = 30000;\n\n private static readonly SCROLL_DELAY_MS = 100;\n private static readonly FOCUS_DELAY_MS = 100;\n\n private static readonly MOBILE_BREAKPOINT = 640;\n private static readonly WINDOW_MARGIN = 20;\n\n private static readonly LOCALSTORAGE_TEST_KEY = '__ocs_test__';\n\n /**\n * The ID of the chatbot to connect to.\n */\n @Prop() chatbotId!: string;\n\n /**\n * The base URL for the API (defaults to current origin).\n */\n @Prop() apiBaseUrl?: string = \"https://chatbots.dimagi.com\";\n\n /**\n * The text to display on the button.\n */\n @Prop() buttonText?: string;\n\n /**\n * URL of the icon to display on the button. If not provided, uses the default OCS logo.\n */\n @Prop() iconUrl?: string;\n\n /**\n * The shape of the chat button. 'round' makes it circular, 'square' keeps it rectangular.\n */\n @Prop() buttonShape: 'round' | 'square' = 'square';\n\n /**\n * Whether the chat widget is visible on load.\n */\n @Prop({ mutable: true }) visible: boolean = false;\n\n /**\n * The initial position of the chat widget on the screen.\n */\n @Prop({ mutable: true }) position: 'left' | 'center' | 'right' = 'right';\n\n /**\n * Welcome messages to display above starter questions (JSON array of strings)\n */\n @Prop() welcomeMessages?: string;\n\n /**\n * Array of starter questions that users can click to send (JSON array of strings)\n */\n @Prop() starterQuestions?: string;\n\n /**\n * Used to associate chat sessions with a specific user across multiple visits/sessions\n */\n @Prop() userId?: string;\n /**\n * Display name for the user.\n */\n @Prop() userName?: string;\n /**\n * Whether to persist session data to local storage to allow resuming previous conversations after page reload.\n */\n @Prop() persistentSession: boolean = true;\n\n /**\n * Minutes since the most recent message after which the session data in local storage will expire. Set this to\n * `0` to never expire.\n */\n @Prop() persistentSessionExpire: number = 60 * 24;\n\n /**\n * Allow the user to make the chat window full screen.\n */\n @Prop() allowFullScreen: boolean = true;\n\n @State() loaded: boolean = false;\n @State() error: string = \"\";\n @State() messages: ChatMessage[] = [];\n @State() sessionId?: string;\n @State() isLoading: boolean = false;\n @State() isTyping: boolean = false;\n @State() messageInput: string = \"\";\n @State() pollingInterval?: any;\n @State() lastPollTime?: Date;\n @State() isTaskPolling: boolean = false;\n @State() isDragging: boolean = false;\n @State() dragOffset: { x: number; y: number } = { x: 0, y: 0 };\n @State() windowPosition: { x: number; y: number } = { x: 0, y: 0 };\n @State() fullscreenPosition: { x: number } = { x: 0 };\n @State() showStarterQuestions: boolean = true;\n @State() parsedWelcomeMessages: string[] = [];\n @State() parsedStarterQuestions: string[] = [];\n @State() generatedUserId?: string;\n @State() isFullscreen: boolean = false;\n\n private messageListRef?: HTMLDivElement;\n private textareaRef?: HTMLTextAreaElement;\n private chatWindowRef?: HTMLDivElement;\n private chatWindowHeight: number = 600;\n private chatWindowWidth: number = 450;\n private chatWindowFullscreenWidth: number = 1024;\n @Element() host: HTMLElement;\n\n\n componentWillLoad() {\n this.loaded = this.visible;\n if (!this.chatbotId) {\n this.error = 'Chatbot ID is required';\n return;\n }\n // Always try to load existing session if localStorage is available\n if (this.persistentSession && this.isLocalStorageAvailable()) {\n const { sessionId, messages } = this.loadSessionFromStorage();\n if (sessionId && messages) {\n this.sessionId = sessionId;\n this.messages = messages;\n this.showStarterQuestions = messages.length === 0;\n }\n }\n this.parseWelcomeMessages();\n this.parseStarterQuestions();\n }\n\n componentDidLoad() {\n // Only auto-start session if we don't have an existing one\n if (this.visible && !this.sessionId) {\n this.startSession();\n } else if (this.visible && this.sessionId) {\n // Resume polling for existing session\n this.startPolling();\n }\n const computedStyle = getComputedStyle(this.host);\n const windowHeightVar = computedStyle.getPropertyValue('--chat-window-height');\n const windowWidthVar = computedStyle.getPropertyValue('--chat-window-width');\n const fullscreenWidthVar = computedStyle.getPropertyValue('--chat-window-fullscreen-width');\n this.chatWindowHeight = varToPixels(windowHeightVar, window.innerHeight, this.chatWindowHeight);\n this.chatWindowWidth = varToPixels(windowWidthVar, window.innerWidth, this.chatWindowWidth);\n this.chatWindowFullscreenWidth = varToPixels(fullscreenWidthVar, window.innerWidth, this.chatWindowFullscreenWidth);\n this.initializePosition();\n window.addEventListener('resize', this.handleWindowResize);\n }\n\n disconnectedCallback() {\n this.cleanup();\n this.removeEventListeners();\n window.removeEventListener('resize', this.handleWindowResize);\n }\n\n private parseJSONProp(propValue: string | undefined, propName: string): string[] {\n try {\n if (propValue) {\n try {\n return JSON.parse(propValue);\n } catch {\n const fixedValue = propValue.replace(/'/g, '\"');\n return JSON.parse(fixedValue);\n }\n }\n } catch (error) {\n console.warn(`Failed to parse ${propName}:`, error);\n }\n return [];\n }\n\n private parseWelcomeMessages() {\n this.parsedWelcomeMessages = this.parseJSONProp(this.welcomeMessages, 'welcome messages');\n }\n\n private parseStarterQuestions() {\n this.parsedStarterQuestions = this.parseJSONProp(this.starterQuestions, 'starter questions');\n }\n\n private cleanup() {\n if (this.pollingInterval) {\n clearInterval(this.pollingInterval);\n this.pollingInterval = undefined;\n }\n this.isTaskPolling = false;\n }\n\n private getApiBaseUrl(): string {\n return this.apiBaseUrl || window.location.origin;\n }\n\n private async startSession(): Promise<void> {\n try {\n this.isLoading = true;\n this.error = '';\n\n const userId = this.getOrGenerateUserId();\n\n const requestBody: any = {\n chatbot_id: this.chatbotId,\n session_data: {\n source: 'widget',\n page_url: window.location.href\n },\n participant_remote_id: userId\n };\n\n if (this.userName) {\n requestBody.participant_name = this.userName;\n }\n\n const response = await fetch(`${this.getApiBaseUrl()}/api/chat/start/`, {\n method: 'POST',\n headers: {\n 'Content-Type': 'application/json',\n },\n body: JSON.stringify(requestBody)\n });\n\n if (!response.ok) {\n throw new Error(`Failed to start session: ${response.statusText}`);\n }\n\n const data: ChatStartSessionResponse = await response.json();\n this.sessionId = data.session_id;\n this.saveSessionToStorage();\n\n // Handle seed message if present\n if (data.seed_message_task_id) {\n this.isTyping = true; // Show typing indicator for seed message\n await this.pollTaskResponse(data.seed_message_task_id);\n }\n\n // Start polling for messages\n this.startPolling();\n } catch (error) {\n this.error = error instanceof Error ? error.message : 'Failed to start chat session';\n } finally {\n this.isLoading = false;\n }\n }\n\n private async sendMessage(message: string): Promise<void> {\n if (!this.sessionId || !message.trim()) return;\n\n // Hide starter questions on any user interaction\n this.showStarterQuestions = false;\n\n try {\n // If this is the first user message and there are welcome messages,\n // add them to chat history as assistant messages\n if (this.messages.length === 0 && this.parsedWelcomeMessages.length > 0) {\n const now = new Date();\n const welcomeMessages: ChatMessage[] = this.parsedWelcomeMessages.map((welcomeMsg, index) => ({\n created_at: new Date(now.getTime() - (this.parsedWelcomeMessages.length - index) * 1000).toISOString(),\n role: 'assistant' as const,\n content: welcomeMsg,\n attachments: []\n }));\n this.messages = [...this.messages, ...welcomeMessages];\n }\n // Add user message immediately\n const userMessage: ChatMessage = {\n created_at: new Date().toISOString(),\n role: 'user',\n content: message.trim(),\n attachments: []\n };\n this.messages = [...this.messages, userMessage];\n this.saveSessionToStorage();\n this.messageInput = '';\n this.scrollToBottom();\n\n // Start typing indicator - it will stay on during task polling\n this.isTyping = true;\n\n const response = await fetch(`${this.getApiBaseUrl()}/api/chat/${this.sessionId}/message/`, {\n method: 'POST',\n headers: {\n 'Content-Type': 'application/json',\n },\n body: JSON.stringify({ message: message.trim() })\n });\n\n if (!response.ok) {\n throw new Error(`Failed to send message: ${response.statusText}`);\n }\n\n const data: ChatSendMessageResponse = await response.json();\n\n if (data.status === 'error') {\n throw new Error(data.error || 'Failed to send message');\n }\n\n // Poll for the response - typing indicator will be managed in pollTaskResponse\n await this.pollTaskResponse(data.task_id);\n } catch (error) {\n this.error = error instanceof Error ? error.message : 'Failed to send message';\n // Clear typing indicator on error\n this.isTyping = false;\n }\n }\n\n private handleStarterQuestionClick(question: string): void {\n this.sendMessage(question);\n }\n\n private async pollTaskResponse(taskId: string): Promise<void> {\n if (!this.sessionId) return;\n\n // Stop message polling while task polling is active\n this.isTaskPolling = true;\n this.pauseMessagePolling();\n\n let attempts = 0;\n\n const poll = async (): Promise<void> => {\n try {\n const response = await fetch(`${this.getApiBaseUrl()}/api/chat/${this.sessionId}/${taskId}/poll/`);\n\n if (!response.ok) {\n throw new Error(`Failed to poll task: ${response.statusText}`);\n }\n\n const data: ChatTaskPollResponse = await response.json();\n\n if (data.error) {\n throw new Error(data.error);\n }\n\n if (data.status === 'complete' && data.message) {\n this.messages = [...this.messages, data.message];\n this.saveSessionToStorage();\n this.scrollToBottom();\n // Task polling complete, clear typing indicator and resume message polling\n this.isTyping = false;\n this.isTaskPolling = false;\n this.resumeMessagePolling();\n this.focusInput();\n return;\n }\n\n if (data.status === 'processing' && attempts < OcsChat.TASK_POLLING_MAX_ATTEMPTS) {\n attempts++;\n setTimeout(poll, OcsChat.TASK_POLLING_INTERVAL_MS);\n } else if (attempts >= OcsChat.TASK_POLLING_MAX_ATTEMPTS) {\n // Task polling timed out, clear typing indicator and resume message polling\n this.isTyping = false;\n this.isTaskPolling = false;\n this.resumeMessagePolling();\n }\n } catch (error) {\n this.error = error instanceof Error ? error.message : 'Failed to get response';\n // Error in task polling, clear typing indicator and resume message polling\n this.isTyping = false;\n this.isTaskPolling = false;\n this.resumeMessagePolling();\n }\n };\n\n await poll();\n }\n\n private startPolling(): void {\n if (this.pollingInterval) return;\n\n this.pollingInterval = setInterval(async () => {\n // Only poll for messages if not currently polling for a task\n if (!this.isTaskPolling) {\n await this.pollForMessages();\n }\n }, OcsChat.MESSAGE_POLLING_INTERVAL_MS);\n }\n\n private pauseMessagePolling(): void {\n if (this.pollingInterval) {\n clearInterval(this.pollingInterval);\n this.pollingInterval = undefined;\n }\n }\n\n private resumeMessagePolling(): void {\n // Resume message polling after task polling is complete\n this.startPolling();\n }\n\n private async pollForMessages(): Promise<void> {\n if (!this.sessionId) return;\n\n try {\n const url = new URL(`${this.getApiBaseUrl()}/api/chat/${this.sessionId}/poll/`);\n if (this.messages && this.messages.length > 0) {\n url.searchParams.set('since', this.messages.at(-1).created_at);\n }\n\n const response = await fetch(url.toString());\n\n if (!response.ok) return; // Silently fail for polling\n\n const data: ChatPollResponse = await response.json();\n\n if (data.messages.length > 0) {\n this.messages = [...this.messages, ...data.messages];\n this.saveSessionToStorage();\n this.scrollToBottom();\n this.focusInput();\n }\n\n this.lastPollTime = new Date();\n } catch (error) {\n // Silently fail for polling\n }\n }\n\n private clearError() {\n this.error = '';\n }\n\n private scrollToBottom(): void {\n setTimeout(() => {\n if (this.messageListRef) {\n this.messageListRef.scrollTop = this.messageListRef.scrollHeight;\n }\n }, OcsChat.SCROLL_DELAY_MS);\n }\n\n private focusInput(): void {\n setTimeout(() => {\n if (this.textareaRef && !this.isTyping) {\n this.textareaRef.focus();\n }\n }, OcsChat.FOCUS_DELAY_MS);\n }\n\n private handleKeyPress(event: KeyboardEvent): void {\n if (event.key === 'Enter' && !event.shiftKey) {\n event.preventDefault();\n this.sendMessage(this.messageInput);\n }\n }\n\n private handleInputChange(event: Event): void {\n this.messageInput = (event.target as HTMLTextAreaElement).value;\n // Hide starter questions when user starts typing\n if (this.messageInput.trim().length > 0) {\n this.showStarterQuestions = false;\n }\n }\n\n private formatTime(dateString: string): string {\n const date = new Date(dateString);\n return date.toLocaleTimeString([], { hour: '2-digit', minute: '2-digit' });\n }\n\n async load() {\n this.visible = !this.visible;\n this.loaded = true;\n\n if (this.visible && !this.sessionId) {\n this.clearError();\n await this.startSession();\n } else if (!this.visible) {\n // Don't reset session when closing, allow resume\n }\n }\n\n setPosition(position: 'left' | 'center' | 'right') {\n if (position === this.position) return;\n this.position = position;\n }\n\n getPositionClasses() {\n if (this.isFullscreen) {\n return 'chat-window-fullscreen';\n }\n const baseClasses = 'chat-window-normal';\n const draggingClass = this.isDragging ? ' chat-window-dragging' : '';\n return baseClasses + draggingClass;\n }\n\n private getFullscreenBounds() {\n const windowWidth = window.innerWidth;\n const actualChatWidth = Math.min(windowWidth, this.chatWindowFullscreenWidth);\n const centeredX = (windowWidth - actualChatWidth) / 2;\n const maxOffset = (windowWidth - actualChatWidth) / 2;\n\n return { windowWidth, actualChatWidth, centeredX, maxOffset };\n }\n\n getPositionStyles() {\n if (this.isFullscreen) {\n const { centeredX } = this.getFullscreenBounds();\n const finalX = centeredX + this.fullscreenPosition.x;\n\n return {\n left: `${finalX}px`,\n top: '0px',\n transform: 'none',\n };\n }\n return {\n left: `${this.windowPosition.x}px`,\n top: `${this.windowPosition.y}px`,\n };\n }\n\n private initializePosition(): void {\n const windowWidth = window.innerWidth;\n const windowHeight = window.innerHeight;\n const chatWidth = windowWidth < OcsChat.MOBILE_BREAKPOINT ? windowWidth : this.chatWindowWidth;\n const isMobile = windowWidth < OcsChat.MOBILE_BREAKPOINT;\n\n if (isMobile) {\n this.windowPosition = { x: 0, y: 0 };\n return;\n }\n\n switch (this.position) {\n case 'left':\n this.windowPosition = {\n x: OcsChat.WINDOW_MARGIN,\n y: windowHeight - this.chatWindowHeight - OcsChat.WINDOW_MARGIN\n };\n break;\n case 'right':\n this.windowPosition = {\n x: windowWidth - chatWidth - OcsChat.WINDOW_MARGIN,\n y: windowHeight - this.chatWindowHeight - OcsChat.WINDOW_MARGIN\n };\n break;\n case 'center':\n this.windowPosition = {\n x: (windowWidth - chatWidth) / 2,\n y: (windowHeight - this.chatWindowHeight) / 2\n };\n break;\n }\n }\n\n private getPointerCoordinates(event: MouseEvent | TouchEvent): PointerEvent | null {\n if (event instanceof MouseEvent) {\n return { clientX: event.clientX, clientY: event.clientY };\n } else if (event instanceof TouchEvent && event.touches.length === 1) {\n const touch = event.touches[0];\n return { clientX: touch.clientX, clientY: touch.clientY };\n }\n return null;\n }\n\n private startDrag(pointer: PointerEvent): void {\n if (!this.chatWindowRef) return;\n\n this.isDragging = true;\n\n if (this.isFullscreen) {\n // For fullscreen, track relative to current position\n this.dragOffset = {\n x: pointer.clientX,\n y: pointer.clientY\n };\n } else {\n const rect = this.chatWindowRef.getBoundingClientRect();\n this.dragOffset = {\n x: pointer.clientX - rect.left,\n y: pointer.clientY - rect.top\n };\n }\n }\n\n private updateDragPosition(pointer: PointerEvent): void {\n if (!this.isDragging) return;\n\n if (this.isFullscreen) {\n // In fullscreen, only allow horizontal dragging\n const { maxOffset } = this.getFullscreenBounds();\n\n const deltaX = pointer.clientX - this.dragOffset.x;\n this.fullscreenPosition = {\n x: Math.max(-maxOffset, Math.min(maxOffset, deltaX))\n };\n } else {\n const newX = pointer.clientX - this.dragOffset.x;\n const newY = pointer.clientY - this.dragOffset.y;\n\n // Constrain chatbox to window\n const windowWidth = window.innerWidth;\n const windowHeight = window.innerHeight;\n const chatWidth = windowWidth < OcsChat.MOBILE_BREAKPOINT ? windowWidth : this.chatWindowWidth;\n const chatHeight = this.chatWindowRef.offsetHeight;\n\n this.windowPosition = {\n x: Math.max(0, Math.min(newX, windowWidth - chatWidth)),\n y: Math.max(0, Math.min(newY, windowHeight - chatHeight))\n };\n }\n }\n\n private endDrag(): void {\n this.isDragging = false;\n this.removeEventListeners();\n }\n\n private addEventListeners(): void {\n document.addEventListener('mousemove', this.handleMouseMove);\n document.addEventListener('mouseup', this.handleMouseUp);\n document.addEventListener('touchmove', this.handleTouchMove, { passive: false });\n document.addEventListener('touchend', this.handleTouchEnd);\n }\n\n private removeEventListeners(): void {\n document.removeEventListener('mousemove', this.handleMouseMove);\n document.removeEventListener('mouseup', this.handleMouseUp);\n document.removeEventListener('touchmove', this.handleTouchMove);\n document.removeEventListener('touchend', this.handleTouchEnd);\n }\n\n private handleMouseDown = (event: MouseEvent): void => {\n if (!this.isFullscreen && window.innerWidth < OcsChat.MOBILE_BREAKPOINT) return;\n if ((event.target as HTMLElement).closest('button')) return;\n\n const pointer = this.getPointerCoordinates(event);\n if (!pointer) return;\n\n this.startDrag(pointer);\n this.addEventListeners();\n event.preventDefault();\n };\n\n private handleMouseMove = (event: MouseEvent): void => {\n const pointer = this.getPointerCoordinates(event);\n if (!pointer) return;\n\n this.updateDragPosition(pointer);\n };\n\n private handleMouseUp = (): void => {\n this.endDrag();\n };\n\n private handleTouchStart = (event: TouchEvent): void => {\n if ((event.target as HTMLElement).closest('button')) return;\n if (!this.chatWindowRef) return;\n\n const pointer = this.getPointerCoordinates(event);\n if (!pointer) return;\n\n this.startDrag(pointer);\n this.addEventListeners();\n event.preventDefault();\n };\n\n private handleTouchMove = (event: TouchEvent): void => {\n const pointer = this.getPointerCoordinates(event);\n if (!pointer) return;\n\n this.updateDragPosition(pointer);\n event.preventDefault();\n };\n\n private handleTouchEnd = (): void => {\n this.endDrag();\n };\n\n private handleWindowResize = (): void => {\n this.initializePosition();\n };\n\n private getDefaultIconUrl(): string {\n return `${this.getApiBaseUrl()}/static/images/favicons/favicon.svg`;\n }\n\n private getButtonClasses(): string {\n const hasText = this.buttonText && this.buttonText.trim();\n const baseClass = hasText ? 'chat-btn-text' : 'chat-btn-icon';\n const shapeClass = this.buttonShape === 'round' ? 'round' : '';\n return `${baseClass} ${shapeClass}`.trim();\n }\n\n private renderButton() {\n const hasText = this.buttonText && this.buttonText.trim();\n const hasCustomIcon = this.iconUrl && this.iconUrl.trim();\n const iconSrc = hasCustomIcon ? this.iconUrl : this.getDefaultIconUrl();\n const buttonClasses = this.getButtonClasses();\n\n if (hasText) {\n return (\n <button\n class={buttonClasses}\n onClick={() => this.load()}\n aria-label={`Open chat - ${this.buttonText}`}\n title={this.buttonText}\n >\n <img src={iconSrc} alt=\"\" />\n <span>{this.buttonText}</span>\n </button>\n );\n } else {\n return (\n <button\n class={buttonClasses}\n onClick={() => this.load()}\n aria-label=\"Open chat\"\n title=\"Open chat\"\n >\n <img src={iconSrc} alt=\"Chat\" />\n </button>\n );\n }\n }\n\n private getStorageKeys() {\n return {\n sessionId: `ocs-chat-session-${this.chatbotId}`,\n messages: `ocs-chat-messages-${this.chatbotId}`,\n lastActivity: `ocs-chat-activity-${this.chatbotId}`\n };\n }\n\n private saveSessionToStorage(): void {\n if (!this.persistentSession) {\n return\n }\n const keys = this.getStorageKeys();\n try {\n if (this.sessionId) {\n localStorage.setItem(keys.sessionId, this.sessionId);\n localStorage.setItem(keys.lastActivity, new Date().toISOString());\n }\n localStorage.setItem(keys.messages, JSON.stringify(this.messages));\n } catch (error) {\n console.warn('Failed to save chat session to localStorage:', error);\n }\n }\n\n private loadSessionFromStorage(): SessionStorageData {\n const keys = this.getStorageKeys();\n try {\n if (this.persistentSessionExpire > 0) {\n const lastActivity = localStorage.getItem(keys.lastActivity);\n if (lastActivity) {\n const lastActivityDate = new Date(lastActivity);\n const minutesSinceActivity = (Date.now() - lastActivityDate.getTime()) / (1000 * 60);\n if (minutesSinceActivity > this.persistentSessionExpire) {\n this.clearSessionStorage();\n return {messages: []};\n }\n }\n }\n\n const storedSessionId = localStorage.getItem(keys.sessionId);\n const sessionId = storedSessionId ? storedSessionId : undefined;\n\n const messagesJson = localStorage.getItem(keys.messages);\n let messages: ChatMessage[] = [];\n\n if (messagesJson) {\n try {\n const parsedMessages = JSON.parse(messagesJson);\n messages = Array.isArray(parsedMessages) ? parsedMessages : [];\n } catch (parseError) {\n console.warn('Failed to parse messages from localStorage:', parseError);\n messages = [];\n }\n }\n\n return { sessionId, messages };\n } catch (error) {\n // fall back to starting a new session\n console.warn('Failed to load chat session from localStorage, starting new session:', error);\n return { messages: [] };\n }\n }\n\n private getOrGenerateUserId(): string {\n if (this.userId) {\n return this.userId;\n }\n\n if (this.generatedUserId) {\n return this.generatedUserId;\n }\n\n const storageKey = `ocs-user-id`;\n const stored = localStorage.getItem(storageKey);\n if (stored) {\n this.generatedUserId = stored;\n return stored;\n }\n\n const array = new Uint8Array(9);\n window.crypto.getRandomValues(array);\n const randomString = Array.from(array, byte => byte.toString(36)).join('').substr(0, 9);\n const newUserId = `ocs:${Date.now()}_${randomString}`;\n this.generatedUserId = newUserId;\n localStorage.setItem(storageKey, newUserId);\n\n return newUserId;\n }\n\n private clearSessionStorage(): void {\n const keys = this.getStorageKeys();\n try {\n localStorage.removeItem(keys.sessionId);\n localStorage.removeItem(keys.messages);\n localStorage.removeItem(keys.lastActivity);\n } catch (error) {\n console.warn('Failed to clear chat session from localStorage:', error);\n }\n }\n\n private isLocalStorageAvailable(): boolean {\n try {\n localStorage.setItem(OcsChat.LOCALSTORAGE_TEST_KEY, 'test');\n localStorage.removeItem(OcsChat.LOCALSTORAGE_TEST_KEY);\n return true;\n } catch {\n return false;\n }\n }\n\n private async startNewChat(): Promise<void> {\n this.clearSessionStorage();\n this.sessionId = undefined;\n this.messages = [];\n this.showStarterQuestions = true;\n this.isTyping = false;\n this.error = '';\n this.cleanup();\n\n await this.startSession();\n }\n\n private toggleFullscreen(): void {\n this.isFullscreen = !this.isFullscreen;\n // Reset fullscreen position when toggling\n this.fullscreenPosition = { x: 0 };\n }\n\n render() {\n if (this.error) {\n return (\n <Host>\n <p class=\"error-message\">{this.error}</p>\n </Host>\n );\n }\n\n return (\n <Host>\n {this.renderButton()}\n {this.visible && (\n <div\n ref={(el) => this.chatWindowRef = el}\n id=\"ocs-chat-window\"\n class={this.getPositionClasses()}\n style={this.getPositionStyles()}\n >\n {/* Header */}\n <div\n class={`chat-header ${this.isDragging ? 'chat-header-dragging' : 'chat-header-draggable'}`}\n onMouseDown={this.handleMouseDown}\n onTouchStart={this.handleTouchStart}\n >\n {/* Drag indicator */}\n <div class=\"drag-indicator\">\n <div class=\"drag-dots\">\n <GripDotsVerticalIcon/>\n </div>\n </div>\n <div class=\"drag-spacer\"></div>\n <div class=\"header-buttons\">\n {/* Fullscreen toggle button */}\n {this.allowFullScreen && <button\n class=\"header-button fullscreen-button\"\n onClick={() => this.toggleFullscreen()}\n title={this.isFullscreen ? \"Exit fullscreen\" : \"Enter fullscreen\"}\n aria-label={this.isFullscreen ? \"Exit fullscreen\" : \"Enter fullscreen\"}\n >\n {this.isFullscreen ? <ArrowsPointingInIcon/> : <ArrowsPointingOutIcon/>}\n </button>}\n {/* New Chat button */}\n {this.sessionId && this.messages.length > 0 && (\n <button\n class=\"header-button\"\n onClick={() => this.startNewChat()}\n title=\"Start new chat\"\n aria-label=\"Start new chat\"\n >\n <PencilSquare/>\n </button>\n )}\n <button\n class=\"header-button\"\n onClick={() => this.visible = false}\n aria-label=\"Close\"\n >\n <XMarkIcon/>\n </button>\n </div>\n </div>\n\n {/* Chat Content */}\n <div class=\"chat-content\">\n {/* Loading State */}\n {this.isLoading && !this.sessionId && (\n <div class=\"loading-container\">\n <div class=\"loading-spinner\"></div>\n <span class=\"loading-text\">Starting chat...</span>\n </div>\n )}\n\n {/* Messages */}\n {this.sessionId && (\n <div\n ref={(el) => this.messageListRef = el}\n class=\"messages-container\"\n >\n {this.messages.length === 0 && !this.isTyping && this.parsedWelcomeMessages.length > 0 && (\n <div class=\"welcome-messages\">\n {/* Welcome Messages */}\n {this.parsedWelcomeMessages.map((message, index) => (\n <div key={`welcome-${index}`} class=\"message-row message-row-assistant\">\n <div class=\"message-bubble message-bubble-assistant\">\n <div\n class=\"chat-markdown\"\n innerHTML={renderMarkdownComplete(message)}\n ></div>\n </div>\n </div>\n ))}\n </div>\n )}\n {/* Regular Chat Messages */}\n {this.messages.map((message, index) => (\n <div\n key={index}\n class={`message-row ${\n message.role === 'user' ? 'message-row-user' : 'message-row-assistant'\n }`}\n >\n <div\n class={`message-bubble ${\n message.role === 'user'\n ? 'message-bubble-user'\n : message.role === 'assistant'\n ? 'message-bubble-assistant'\n : 'message-bubble-system'\n }`}\n >\n <div\n class=\"chat-markdown\"\n innerHTML={renderMarkdownComplete(message.content)}\n ></div>\n {message.attachments && message.attachments.length > 0 && (\n <div class=\"message-attachments\">\n {message.attachments.map((attachment, attachmentIndex) => (\n <a\n key={attachmentIndex}\n href={attachment.content_url}\n target=\"_blank\"\n rel=\"noopener noreferrer\"\n class=\"attachment-link\"\n >\n 📎 {attachment.name}\n </a>\n ))}\n </div>\n )}\n <div class=\"message-timestamp\">\n {this.formatTime(message.created_at)}\n </div>\n </div>\n </div>\n ))}\n {/* Typing Indicator */}\n {this.isTyping && (\n <div>\n <div class=\"typing-indicator\">\n <div class=\"typing-progress\"></div>\n </div>\n <div class=\"typing-text\">\n <span>Preparing response</span>\n <span class=\"typing-dots\"></span>\n </div>\n </div>\n )}\n </div>\n )}\n\n {/* Starter Questions */}\n {this.sessionId && this.showStarterQuestions && this.messages.length === 0 && !this.isTyping && (\n <div class=\"starter-questions\">\n {this.parsedStarterQuestions.map((question, index) => (\n <div key={`starter-${index}`} class=\"starter-question-row\">\n <button\n class=\"starter-question\"\n onClick={() => this.handleStarterQuestionClick(question)}\n >\n {question}\n </button>\n </div>\n ))}\n </div>\n )}\n\n {/* Input Area */}\n {this.sessionId && (\n <div class=\"input-area\">\n <div class=\"input-container\">\n <textarea\n ref={(el) => this.textareaRef = el}\n class=\"message-textarea\"\n rows={1}\n placeholder=\"Type your message...\"\n value={this.messageInput}\n onInput={(e) => this.handleInputChange(e)}\n onKeyPress={(e) => this.handleKeyPress(e)}\n disabled={this.isTyping}\n ></textarea>\n <button\n class={`send-button ${\n !this.isTyping && !!this.messageInput.trim()\n ? 'send-button-enabled'\n : 'send-button-disabled'\n }`}\n onClick={() => this.sendMessage(this.messageInput)}\n disabled={this.isTyping || !this.messageInput.trim()}\n >\n Send\n </button>\n </div>\n </div>\n )}\n </div>\n </div>\n )}\n </Host>\n );\n }\n}\n"]}
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Convert a CSS percentage (60%) or pixel (10px) value to pixels.
|
|
3
|
+
* @param value The CSS string value
|
|
4
|
+
* @param maxValue The max value to use when converting from a percentage
|
|
5
|
+
* @param defaultValue The default value if the CSS value is neither a percentage nor a pixel value.
|
|
6
|
+
*/
|
|
7
|
+
export const varToPixels = (value, maxValue, defaultValue) => {
|
|
8
|
+
value = value.trim();
|
|
9
|
+
if (value.includes("%")) {
|
|
10
|
+
const percent = percentToFloat(value);
|
|
11
|
+
if (!isNaN(percent)) {
|
|
12
|
+
return maxValue * percent;
|
|
13
|
+
}
|
|
14
|
+
}
|
|
15
|
+
else if (value.includes("px")) {
|
|
16
|
+
const pixels = parseFloat(value);
|
|
17
|
+
if (!isNaN(pixels)) {
|
|
18
|
+
return pixels;
|
|
19
|
+
}
|
|
20
|
+
}
|
|
21
|
+
return defaultValue;
|
|
22
|
+
};
|
|
23
|
+
const percentToFloat = (percentageString) => {
|
|
24
|
+
const numericValue = parseFloat(percentageString);
|
|
25
|
+
if (isNaN(numericValue)) {
|
|
26
|
+
return NaN;
|
|
27
|
+
}
|
|
28
|
+
return numericValue / 100;
|
|
29
|
+
};
|
|
30
|
+
//# sourceMappingURL=utils.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"utils.js","sourceRoot":"","sources":["../../src/utils/utils.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AACH,MAAM,CAAC,MAAM,WAAW,GAAG,CAAC,KAAa,EAAE,QAAgB,EAAE,YAAoB,EAAE,EAAE;IACnF,KAAK,GAAG,KAAK,CAAC,IAAI,EAAE,CAAA;IACpB,IAAI,KAAK,CAAC,QAAQ,CAAC,GAAG,CAAC,EAAE,CAAC;QACtB,MAAM,OAAO,GAAG,cAAc,CAAC,KAAK,CAAC,CAAC;QACtC,IAAI,CAAC,KAAK,CAAC,OAAO,CAAC,EAAE,CAAC;YACpB,OAAO,QAAQ,GAAG,OAAO,CAAC;QAC5B,CAAC;IACH,CAAC;SAAM,IAAI,KAAK,CAAC,QAAQ,CAAC,IAAI,CAAC,EAAE,CAAC;QAChC,MAAM,MAAM,GAAG,UAAU,CAAC,KAAK,CAAC,CAAC;QACjC,IAAI,CAAC,KAAK,CAAC,MAAM,CAAC,EAAE,CAAC;YACnB,OAAO,MAAM,CAAC;QAChB,CAAC;IACH,CAAC;IACD,OAAO,YAAY,CAAC;AACxB,CAAC,CAAA;AAED,MAAM,cAAc,GAAG,CAAC,gBAAwB,EAAE,EAAE;IAClD,MAAM,YAAY,GAAG,UAAU,CAAC,gBAAgB,CAAC,CAAC;IAClD,IAAI,KAAK,CAAC,YAAY,CAAC,EAAE,CAAC;QACxB,OAAO,GAAG,CAAC;IACb,CAAC;IACD,OAAO,YAAY,GAAG,GAAG,CAAC;AAC5B,CAAC,CAAC","sourcesContent":["/**\n * Convert a CSS percentage (60%) or pixel (10px) value to pixels.\n * @param value The CSS string value\n * @param maxValue The max value to use when converting from a percentage\n * @param defaultValue The default value if the CSS value is neither a percentage nor a pixel value.\n */\nexport const varToPixels = (value: string, maxValue: number, defaultValue: number) => {\n value = value.trim()\n if (value.includes(\"%\")) {\n const percent = percentToFloat(value);\n if (!isNaN(percent)) {\n return maxValue * percent;\n }\n } else if (value.includes(\"px\")) {\n const pixels = parseFloat(value);\n if (!isNaN(pixels)) {\n return pixels;\n }\n }\n return defaultValue;\n}\n\nconst percentToFloat = (percentageString: string) => {\n const numericValue = parseFloat(percentageString);\n if (isNaN(numericValue)) {\n return NaN;\n }\n return numericValue / 100;\n};\n"]}
|