open-chat-studio-widget 0.5.0 → 0.5.2

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.
Files changed (30) hide show
  1. package/dist/cjs/{index-CC3Krx2K.js → index-Ctja7z-R.js} +3 -3
  2. package/dist/cjs/{index-CC3Krx2K.js.map → index-Ctja7z-R.js.map} +1 -1
  3. package/dist/cjs/loader.cjs.js +1 -1
  4. package/dist/cjs/open-chat-studio-widget.cjs.entry.js +45 -38
  5. package/dist/cjs/open-chat-studio-widget.cjs.entry.js.map +1 -1
  6. package/dist/cjs/open-chat-studio-widget.cjs.js +1 -1
  7. package/dist/cjs/open-chat-studio-widget.entry.cjs.js.map +1 -1
  8. package/dist/collection/components/ocs-chat/ocs-chat.js +44 -37
  9. package/dist/collection/components/ocs-chat/ocs-chat.js.map +1 -1
  10. package/dist/collection/services/chat-session-service.js.map +1 -1
  11. package/dist/collection/utils/translations.js +2 -2
  12. package/dist/collection/utils/translations.js.map +1 -1
  13. package/dist/components/open-chat-studio-widget.js +44 -37
  14. package/dist/components/open-chat-studio-widget.js.map +1 -1
  15. package/dist/esm/{index-BF7CYZiN.js → index-BbCwiO7g.js} +3 -3
  16. package/dist/esm/{index-BF7CYZiN.js.map → index-BbCwiO7g.js.map} +1 -1
  17. package/dist/esm/loader.js +2 -2
  18. package/dist/esm/open-chat-studio-widget.entry.js +45 -38
  19. package/dist/esm/open-chat-studio-widget.entry.js.map +1 -1
  20. package/dist/esm/open-chat-studio-widget.js +2 -2
  21. package/dist/open-chat-studio-widget/open-chat-studio-widget.entry.esm.js.map +1 -1
  22. package/dist/open-chat-studio-widget/open-chat-studio-widget.esm.js +1 -1
  23. package/dist/open-chat-studio-widget/{p-400b1f47.entry.js → p-96920183.entry.js} +4 -4
  24. package/dist/open-chat-studio-widget/p-96920183.entry.js.map +1 -0
  25. package/dist/open-chat-studio-widget/{p-BF7CYZiN.js → p-BbCwiO7g.js} +2 -2
  26. package/dist/open-chat-studio-widget/{p-BF7CYZiN.js.map → p-BbCwiO7g.js.map} +1 -1
  27. package/dist/types/components/ocs-chat/ocs-chat.d.ts +5 -1
  28. package/dist/types/services/chat-session-service.d.ts +0 -1
  29. package/package.json +2 -2
  30. package/dist/open-chat-studio-widget/p-400b1f47.entry.js.map +0 -1
@@ -1 +1 @@
1
- {"version":3,"file":"translations.js","sourceRoot":"","sources":["../../src/utils/translations.ts"],"names":[],"mappings":"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","sourcesContent":["/**\n * Translation utilities for the chat widget\n */\n\nimport ar from '../assets/translations/ar.json';\nimport en from '../assets/translations/en.json';\nimport es from '../assets/translations/es.json';\nimport fr from '../assets/translations/fr.json';\nimport hi from '../assets/translations/hi.json';\nimport it from '../assets/translations/ita.json';\nimport pt from '../assets/translations/por.json';\nimport sw from '../assets/translations/sw.json';\nimport uk from '../assets/translations/uk.json';\n\nexport type TranslationStrings = typeof en;\n\n// Default (English) translations\nexport const defaultTranslations: TranslationStrings = en as TranslationStrings;\n\n// Available translations map\nconst translationFiles: Record<string, TranslationStrings> = {\n ar: ar as TranslationStrings,\n en: en as TranslationStrings,\n es: es as TranslationStrings,\n fr: fr as TranslationStrings,\n hi: hi as TranslationStrings,\n it: it as TranslationStrings,\n pt: pt as TranslationStrings,\n sw: sw as TranslationStrings,\n uk: uk as TranslationStrings,\n};\n\n\nexport function getBrowserLanguage(): string {\n if (typeof navigator !== 'undefined') {\n const lang = navigator.language || (navigator as any).userLanguage;\n if (lang) {\n return lang.split('-')[0].toLowerCase();\n }\n }\n return 'en';\n}\n\nexport function resolveLanguage(langProp?: string): string {\n if (langProp) {\n return langProp.toLowerCase();\n }\n return getBrowserLanguage();\n}\n\nexport async function loadTranslations(language: string): Promise<TranslationStrings> {\n return translationFiles[language] || defaultTranslations;\n}\n\n/**\n * Overrides matching keys\n */\nexport function mergeTranslations(\n baseTranslations: TranslationStrings,\n customTranslations: Partial<TranslationStrings>\n): TranslationStrings {\n return { ...baseTranslations, ...customTranslations };\n}\n\nexport class TranslationManager {\n private translations: TranslationStrings = defaultTranslations;\n private language: string = 'en';\n\n constructor(language?: string, customTranslations?: Partial<TranslationStrings>) {\n this.language = resolveLanguage(language);\n this.loadTranslations(customTranslations);\n }\n\n private async loadTranslations(customTranslations?: Partial<TranslationStrings>) {\n let baseTranslations: TranslationStrings;\n try {\n baseTranslations = await loadTranslations(this.language);\n } catch (error) {\n console.error('Failed to load translations:', error);\n baseTranslations = defaultTranslations;\n }\n\n this.translations = customTranslations\n ? mergeTranslations(baseTranslations, customTranslations)\n : baseTranslations;\n }\n\n get(key: keyof TranslationStrings, override?: string | null): string | undefined {\n if (override !== undefined && override !== null) {\n return override;\n }\n\n const value = this.translations[key] ?? defaultTranslations[key];\n if (Array.isArray(value)) {\n return value.length > 0 ? value[0] : undefined;\n }\n return value ?? undefined;\n }\n\n getAll(): TranslationStrings {\n return this.translations;\n }\n\n getArray(key: keyof TranslationStrings): string[] {\n const value = this.translations[key] || defaultTranslations[key];\n if (Array.isArray(value)) {\n return value;\n }\n if (typeof value === 'string') {\n return [value];\n }\n return [];\n }\n\n getLanguage(): string {\n return this.language;\n }\n}\n"]}
1
+ {"version":3,"file":"translations.js","sourceRoot":"","sources":["../../src/utils/translations.ts"],"names":[],"mappings":"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","sourcesContent":["/**\n * Translation utilities for the chat widget\n */\n\nimport ar from '../assets/translations/ar.json';\nimport en from '../assets/translations/en.json';\nimport es from '../assets/translations/es.json';\nimport fr from '../assets/translations/fr.json';\nimport hi from '../assets/translations/hi.json';\nimport it from '../assets/translations/it.json';\nimport pt from '../assets/translations/pt.json';\nimport sw from '../assets/translations/sw.json';\nimport uk from '../assets/translations/uk.json';\n\nexport type TranslationStrings = typeof en;\n\n// Default (English) translations\nexport const defaultTranslations: TranslationStrings = en as TranslationStrings;\n\n// Available translations map\nconst translationFiles: Record<string, TranslationStrings> = {\n ar: ar as TranslationStrings,\n en: en as TranslationStrings,\n es: es as TranslationStrings,\n fr: fr as TranslationStrings,\n hi: hi as TranslationStrings,\n it: it as TranslationStrings,\n pt: pt as TranslationStrings,\n sw: sw as TranslationStrings,\n uk: uk as TranslationStrings,\n};\n\n\nexport function getBrowserLanguage(): string {\n if (typeof navigator !== 'undefined') {\n const lang = navigator.language || (navigator as any).userLanguage;\n if (lang) {\n return lang.split('-')[0].toLowerCase();\n }\n }\n return 'en';\n}\n\nexport function resolveLanguage(langProp?: string): string {\n if (langProp) {\n return langProp.toLowerCase();\n }\n return getBrowserLanguage();\n}\n\nexport async function loadTranslations(language: string): Promise<TranslationStrings> {\n return translationFiles[language] || defaultTranslations;\n}\n\n/**\n * Overrides matching keys\n */\nexport function mergeTranslations(\n baseTranslations: TranslationStrings,\n customTranslations: Partial<TranslationStrings>\n): TranslationStrings {\n return { ...baseTranslations, ...customTranslations };\n}\n\nexport class TranslationManager {\n private translations: TranslationStrings = defaultTranslations;\n private language: string = 'en';\n\n constructor(language?: string, customTranslations?: Partial<TranslationStrings>) {\n this.language = resolveLanguage(language);\n this.loadTranslations(customTranslations);\n }\n\n private async loadTranslations(customTranslations?: Partial<TranslationStrings>) {\n let baseTranslations: TranslationStrings;\n try {\n baseTranslations = await loadTranslations(this.language);\n } catch (error) {\n console.error('Failed to load translations:', error);\n baseTranslations = defaultTranslations;\n }\n\n this.translations = customTranslations\n ? mergeTranslations(baseTranslations, customTranslations)\n : baseTranslations;\n }\n\n get(key: keyof TranslationStrings, override?: string | null): string | undefined {\n if (override !== undefined && override !== null) {\n return override;\n }\n\n const value = this.translations[key] ?? defaultTranslations[key];\n if (Array.isArray(value)) {\n return value.length > 0 ? value[0] : undefined;\n }\n return value ?? undefined;\n }\n\n getAll(): TranslationStrings {\n return this.translations;\n }\n\n getArray(key: keyof TranslationStrings): string[] {\n const value = this.translations[key] || defaultTranslations[key];\n if (Array.isArray(value)) {\n return value;\n }\n if (typeof value === 'string') {\n return [value];\n }\n return [];\n }\n\n getLanguage(): string {\n return this.language;\n }\n}\n"]}
@@ -5402,17 +5402,16 @@ const OcsChat = /*@__PURE__*/ proxyCustomElement(class OcsChat extends HTMLEleme
5402
5402
  this.chatWindowFullscreenWidth = varToPixels(fullscreenWidthVar, window.innerWidth, this.chatWindowFullscreenWidth);
5403
5403
  // Initialize button position from computed styles
5404
5404
  this.initializeButtonPosition();
5405
- if (this.visible) {
5406
- this.initializePosition();
5407
- }
5408
- // Only auto-start session if we don't have an existing one
5409
- if (this.visible && !this.sessionId) {
5410
- this.startSession();
5411
- }
5412
- else if (this.visible && this.sessionId) {
5413
- // Resume polling for existing session
5414
- this.startMessagePolling();
5415
- }
5405
+ // Defer position initialization to avoid state changes during componentDidLoad
5406
+ setTimeout(() => {
5407
+ if (this.visible) {
5408
+ this.initializePosition();
5409
+ }
5410
+ // Resume polling for existing session (don't auto-start new sessions)
5411
+ if (this.visible && this.sessionId) {
5412
+ this.startMessagePolling();
5413
+ }
5414
+ }, 0);
5416
5415
  window.addEventListener('resize', this.handleWindowResize);
5417
5416
  }
5418
5417
  disconnectedCallback() {
@@ -5524,13 +5523,7 @@ const OcsChat = /*@__PURE__*/ proxyCustomElement(class OcsChat extends HTMLEleme
5524
5523
  const data = await this.getChatService().startSession(requestBody);
5525
5524
  this.sessionId = data.session_id;
5526
5525
  this.saveSessionToStorage();
5527
- // Handle seed message if present
5528
- if (data.seed_message_task_id) {
5529
- this.startTaskPolling(data.seed_message_task_id);
5530
- }
5531
- else {
5532
- this.startMessagePolling();
5533
- }
5526
+ this.startMessagePolling();
5534
5527
  }
5535
5528
  catch (_error) {
5536
5529
  this.handleError('Failed to start chat session');
@@ -5559,8 +5552,20 @@ const OcsChat = /*@__PURE__*/ proxyCustomElement(class OcsChat extends HTMLEleme
5559
5552
  }
5560
5553
  }
5561
5554
  async sendMessage(message) {
5562
- if (!this.sessionId || !message.trim())
5555
+ if (!message.trim())
5563
5556
  return;
5557
+ // Start session if we don't have one yet
5558
+ if (!this.sessionId) {
5559
+ // Prevent concurrent session initialization
5560
+ if (this.isLoading) {
5561
+ return;
5562
+ }
5563
+ await this.startSession();
5564
+ // Check if session started successfully
5565
+ if (!this.sessionId) {
5566
+ return; // startSession already handled the error
5567
+ }
5568
+ }
5564
5569
  try {
5565
5570
  let attachmentIds = [];
5566
5571
  if (this.allowAttachments && this.selectedFiles.length > 0) {
@@ -5575,10 +5580,11 @@ const OcsChat = /*@__PURE__*/ proxyCustomElement(class OcsChat extends HTMLEleme
5575
5580
  }
5576
5581
  // If this is the first user message and there are welcome messages,
5577
5582
  // add them to chat history as assistant messages
5578
- if (this.messages.length === 0 && this.parsedWelcomeMessages.length > 0) {
5583
+ const welcomeMessagesToAdd = this.getWelcomeMessages();
5584
+ if (this.messages.length === 0 && welcomeMessagesToAdd.length > 0) {
5579
5585
  const now = new Date();
5580
- const welcomeMessages = this.parsedWelcomeMessages.map((welcomeMsg, index) => ({
5581
- created_at: new Date(now.getTime() - (this.parsedWelcomeMessages.length - index) * 1000).toISOString(),
5586
+ const welcomeMessages = welcomeMessagesToAdd.map((welcomeMsg, index) => ({
5587
+ created_at: new Date(now.getTime() - (welcomeMessagesToAdd.length - index) * 1000).toISOString(),
5582
5588
  role: 'assistant',
5583
5589
  content: welcomeMsg,
5584
5590
  attachments: []
@@ -5712,16 +5718,14 @@ const OcsChat = /*@__PURE__*/ proxyCustomElement(class OcsChat extends HTMLEleme
5712
5718
  }
5713
5719
  if (visible) {
5714
5720
  this.initializePosition();
5715
- }
5716
- if (visible && !this.sessionId) {
5717
- await this.startSession();
5718
- }
5719
- else if (!visible) {
5720
- this.stopMessagePolling();
5721
+ // Resume polling for existing session (don't auto-start new sessions)
5722
+ if (this.sessionId) {
5723
+ this.scrollToBottom(true);
5724
+ this.startMessagePolling();
5725
+ }
5721
5726
  }
5722
5727
  else {
5723
- this.scrollToBottom(true);
5724
- this.startMessagePolling();
5728
+ this.stopMessagePolling();
5725
5729
  }
5726
5730
  }
5727
5731
  startTaskPolling(taskId) {
@@ -6224,9 +6228,13 @@ const OcsChat = /*@__PURE__*/ proxyCustomElement(class OcsChat extends HTMLEleme
6224
6228
  }
6225
6229
  async confirmNewChat() {
6226
6230
  this.hideConfirmationDialog();
6227
- await this.actuallyStartNewChat();
6231
+ await this.clearSession();
6228
6232
  }
6229
- async actuallyStartNewChat() {
6233
+ /**
6234
+ * This clears out all data related to the previous session. A new session
6235
+ * will start when the user sends a message.
6236
+ */
6237
+ async clearSession() {
6230
6238
  this.clearSessionStorage();
6231
6239
  this.sessionId = undefined;
6232
6240
  this.messages = [];
@@ -6236,7 +6244,6 @@ const OcsChat = /*@__PURE__*/ proxyCustomElement(class OcsChat extends HTMLEleme
6236
6244
  this.selectedFiles = [];
6237
6245
  }
6238
6246
  this.cleanup();
6239
- await this.startSession();
6240
6247
  }
6241
6248
  toggleFullscreen() {
6242
6249
  this.isFullscreen = !this.isFullscreen;
@@ -6248,18 +6255,18 @@ const OcsChat = /*@__PURE__*/ proxyCustomElement(class OcsChat extends HTMLEleme
6248
6255
  if (this.error && !this.sessionId) {
6249
6256
  return (h(Host, null, h("p", { class: "error-message" }, this.error)));
6250
6257
  }
6251
- 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 header-button" }, h(GripDotsVerticalIcon, null))), h("div", { class: "header-text" }, this.translationManager.get('branding.headerText', this.headerText)), h("div", { class: "header-buttons" }, this.messages.length > 0 && (h("button", { class: "header-button", onClick: () => this.showConfirmationDialog(), title: this.translationManager.get('window.newChat'), "aria-label": this.translationManager.get('window.newChat') }, h(PlusWithCircleIcon, null))), this.allowFullScreen && h("button", { class: "header-button fullscreen-button", onClick: () => this.toggleFullscreen(), title: this.isFullscreen ? this.translationManager.get('window.exitFullscreen') : this.translationManager.get('window.fullscreen'), "aria-label": this.isFullscreen ? this.translationManager.get('window.exitFullscreen') : this.translationManager.get('window.fullscreen') }, this.isFullscreen ? h(ArrowsPointingInIcon, null) : h(ArrowsPointingOutIcon, null)), h("button", { class: "header-button", onClick: () => this.visible = false, "aria-label": this.translationManager.get('window.close') }, h(XMarkIcon, null)))), this.showNewChatConfirmation && (h("div", { class: "confirmation-overlay" }, h("div", { class: "confirmation-dialog" }, h("div", { class: "confirmation-content" }, h("h3", { class: "confirmation-title" }, this.translationManager.get('modal.newChatTitle')), h("p", { class: "confirmation-message" }, this.translationManager.get('modal.newChatBody', this.newChatConfirmationMessage)), h("div", { class: "confirmation-buttons" }, h("button", { class: "confirmation-button confirmation-button-cancel", onClick: () => this.hideConfirmationDialog() }, this.translationManager.get('modal.cancel')), h("button", { class: "confirmation-button confirmation-button-confirm", onClick: () => this.confirmNewChat() }, this.translationManager.get('modal.confirm'))))))), h("div", { class: "chat-content" }, this.isLoading && !this.sessionId && (h("div", { class: "loading-container" }, h("div", { class: "loading-spinner" }), h("span", { class: "loading-text" }, this.translationManager.get('status.starting')))), (h("div", { ref: (el) => this.messageListRef = el, class: "messages-container" }, this.messages.length === 0 && this.parsedWelcomeMessages.length > 0 && (h("div", { class: "welcome-messages" }, this.getWelcomeMessages().map((message, index) => (h("div", { key: `welcome-${index}`, class: "message-row message-row-assistant" }, h("div", { class: "message-bubble message-bubble-assistant" }, h("div", { class: "chat-markdown", innerHTML: renderMarkdownSync(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'
6258
+ 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 header-button" }, h(GripDotsVerticalIcon, null))), h("div", { class: "header-text" }, this.translationManager.get('branding.headerText', this.headerText)), h("div", { class: "header-buttons" }, this.messages.length > 0 && (h("button", { class: "header-button", onClick: () => this.showConfirmationDialog(), title: this.translationManager.get('window.newChat'), "aria-label": this.translationManager.get('window.newChat') }, h(PlusWithCircleIcon, null))), this.allowFullScreen && h("button", { class: "header-button fullscreen-button", onClick: () => this.toggleFullscreen(), title: this.isFullscreen ? this.translationManager.get('window.exitFullscreen') : this.translationManager.get('window.fullscreen'), "aria-label": this.isFullscreen ? this.translationManager.get('window.exitFullscreen') : this.translationManager.get('window.fullscreen') }, this.isFullscreen ? h(ArrowsPointingInIcon, null) : h(ArrowsPointingOutIcon, null)), h("button", { class: "header-button", onClick: () => this.visible = false, "aria-label": this.translationManager.get('window.close') }, h(XMarkIcon, null)))), this.showNewChatConfirmation && (h("div", { class: "confirmation-overlay" }, h("div", { class: "confirmation-dialog" }, h("div", { class: "confirmation-content" }, h("h3", { class: "confirmation-title" }, this.translationManager.get('modal.newChatTitle')), h("p", { class: "confirmation-message" }, this.translationManager.get('modal.newChatBody', this.newChatConfirmationMessage)), h("div", { class: "confirmation-buttons" }, h("button", { class: "confirmation-button confirmation-button-cancel", onClick: () => this.hideConfirmationDialog() }, this.translationManager.get('modal.cancel')), h("button", { class: "confirmation-button confirmation-button-confirm", onClick: () => this.confirmNewChat() }, this.translationManager.get('modal.confirm'))))))), h("div", { class: "chat-content" }, this.isLoading && !this.sessionId && (h("div", { class: "loading-container" }, h("div", { class: "loading-spinner" }), h("span", { class: "loading-text" }, this.translationManager.get('status.starting')))), (h("div", { ref: (el) => this.messageListRef = el, class: "messages-container" }, this.messages.length === 0 && this.getWelcomeMessages().length > 0 && (h("div", { class: "welcome-messages" }, this.getWelcomeMessages().map((message, index) => (h("div", { key: `welcome-${index}`, class: "message-row message-row-assistant" }, h("div", { class: "message-bubble message-bubble-assistant" }, h("div", { class: "chat-markdown", innerHTML: renderMarkdownSync(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'
6252
6259
  ? 'message-bubble-user'
6253
6260
  : message.role === 'assistant'
6254
6261
  ? 'message-bubble-assistant'
6255
- : 'message-bubble-system'}` }, h("div", { class: "chat-markdown", innerHTML: renderMarkdownSync(message.content) }), message.attachments && message.attachments.length > 0 && (h("div", { class: "message-attachments" }, message.attachments.map((attachment, attachmentIndex) => (h("div", { key: attachmentIndex, class: "flex items-center gap-[0.5em]" }, h("span", { class: "message-attachment-icon" }, h(PaperClipIcon, null)), h("span", { class: "message-attachment-name" }, attachment.name)))))), h("div", { class: "message-timestamp" }, this.formatTime(message.created_at)))))), this.isTyping && (h("div", null, h("div", { class: "typing-indicator" }, h("div", { class: "typing-progress" })), h("div", { class: "typing-text" }, h("span", null, this.translationManager.get('status.typing', this.typingIndicatorText)), h("span", { class: "typing-dots loading" })))))), this.messages.length === 0 && this.parsedStarterQuestions.length > 0 && (h("div", { class: "starter-questions" }, this.getStarterQuestions().map((question, index) => (h("div", { key: `starter-${index}`, class: "starter-question-row" }, h("button", { class: "starter-question", onClick: () => this.handleStarterQuestionClick(question) }, question)))))), this.allowAttachments && this.selectedFiles.length > 0 && (h("div", { class: "selected-files-container" }, h("div", { class: "space-y-[0.25em]" }, this.selectedFiles.map((selectedFile, index) => (h("div", { key: index, class: "selected-file-item" }, h("div", { class: "flex items-center gap-[0.5em]" }, h("span", { class: "selected-file-icon" }, h(PaperClipIcon, null)), h("span", null, selectedFile.file.name), h("span", { class: "selected-file-size" }, "(", this.formatFileSize(selectedFile.file.size), ")"), selectedFile.error && (h("span", { class: "selected-file-error" }, selectedFile.error)), selectedFile.uploaded && (h("span", { class: "selected-file-success-icon" }, h(CheckDocumentIcon, null)))), h("button", { onClick: () => this.removeSelectedFile(index), class: "selected-file-remove-button", "aria-label": this.translationManager.get('attach.remove') }, h(XIcon, null)))))))), 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: this.translationManager.get('composer.placeholder'), value: this.messageInput, onInput: (e) => this.handleInputChange(e), onKeyPress: (e) => this.handleKeyPress(e), disabled: this.isTyping || this.isUploadingFiles }), this.allowAttachments && (h("input", { ref: (el) => {
6262
+ : 'message-bubble-system'}` }, h("div", { class: "chat-markdown", innerHTML: renderMarkdownSync(message.content) }), message.attachments && message.attachments.length > 0 && (h("div", { class: "message-attachments" }, message.attachments.map((attachment, attachmentIndex) => (h("div", { key: attachmentIndex, class: "flex items-center gap-[0.5em]" }, h("span", { class: "message-attachment-icon" }, h(PaperClipIcon, null)), h("span", { class: "message-attachment-name" }, attachment.name)))))), h("div", { class: "message-timestamp" }, this.formatTime(message.created_at)))))), this.isTyping && (h("div", null, h("div", { class: "typing-indicator" }, h("div", { class: "typing-progress" })), h("div", { class: "typing-text" }, h("span", null, this.translationManager.get('status.typing', this.typingIndicatorText)), h("span", { class: "typing-dots loading" })))))), this.messages.length === 0 && this.getStarterQuestions().length > 0 && (h("div", { class: "starter-questions" }, this.getStarterQuestions().map((question, index) => (h("div", { key: `starter-${index}`, class: "starter-question-row" }, h("button", { class: "starter-question", onClick: () => this.handleStarterQuestionClick(question) }, question)))))), this.allowAttachments && this.selectedFiles.length > 0 && (h("div", { class: "selected-files-container" }, h("div", { class: "space-y-[0.25em]" }, this.selectedFiles.map((selectedFile, index) => (h("div", { key: index, class: "selected-file-item" }, h("div", { class: "flex items-center gap-[0.5em]" }, h("span", { class: "selected-file-icon" }, h(PaperClipIcon, null)), h("span", null, selectedFile.file.name), h("span", { class: "selected-file-size" }, "(", this.formatFileSize(selectedFile.file.size), ")"), selectedFile.error && (h("span", { class: "selected-file-error" }, selectedFile.error)), selectedFile.uploaded && (h("span", { class: "selected-file-success-icon" }, h(CheckDocumentIcon, null)))), h("button", { onClick: () => this.removeSelectedFile(index), class: "selected-file-remove-button", "aria-label": this.translationManager.get('attach.remove') }, h(XIcon, null)))))))), h("div", { class: "input-area" }, h("div", { class: "input-container" }, h("textarea", { ref: (el) => this.textareaRef = el, class: "message-textarea", rows: 1, placeholder: this.translationManager.get('composer.placeholder'), value: this.messageInput, onInput: (e) => this.handleInputChange(e), onKeyPress: (e) => this.handleKeyPress(e), disabled: this.isTyping || this.isUploadingFiles || this.isLoading }), this.allowAttachments && (h("input", { ref: (el) => {
6256
6263
  // Unclear why but after removing all attachments this is being set to `null`.
6257
6264
  if (el) {
6258
6265
  this.fileInputRef = el;
6259
6266
  }
6260
- }, id: "ocs-file-input", type: "file", multiple: true, accept: OcsChat.SUPPORTED_FILE_EXTENSIONS.join(','), onChange: (e) => this.handleFileSelect(e), class: "hidden" })), this.allowAttachments && (h("button", { class: "file-attachment-button", onClick: () => { var _a; return (_a = this.fileInputRef) === null || _a === void 0 ? void 0 : _a.click(); }, disabled: this.isTyping || this.isUploadingFiles, title: this.translationManager.get('attach.add'), "aria-label": this.translationManager.get('attach.add') }, h(PaperClipIcon, null))), h("button", { class: `send-button ${!this.isTyping && !!this.messageInput.trim()
6267
+ }, id: "ocs-file-input", type: "file", multiple: true, accept: OcsChat.SUPPORTED_FILE_EXTENSIONS.join(','), onChange: (e) => this.handleFileSelect(e), class: "hidden" })), this.allowAttachments && (h("button", { class: "file-attachment-button", onClick: () => { var _a; return (_a = this.fileInputRef) === null || _a === void 0 ? void 0 : _a.click(); }, disabled: this.isTyping || this.isUploadingFiles || this.isLoading, title: this.translationManager.get('attach.add'), "aria-label": this.translationManager.get('attach.add') }, h(PaperClipIcon, null))), h("button", { class: `send-button ${!this.isTyping && !this.isLoading && !!this.messageInput.trim()
6261
6268
  ? 'send-button-enabled'
6262
- : 'send-button-disabled'}`, onClick: () => this.sendMessage(this.messageInput), disabled: this.isTyping || this.isUploadingFiles || !this.messageInput.trim() }, this.isUploadingFiles ? `${this.translationManager.get('status.uploading')}...` : this.translationManager.get('composer.send'))))), h("div", { class: "flex items-center justify-center text-[0.8em] font-light w-full text-slate-500 py-[2px]" }, h("p", null, this.translationManager.get('branding.poweredBy'), ' ', " ", h("a", { class: "underline", href: "https://www.dimagi.com", target: "_blank" }, "Dimagi"))))))));
6269
+ : 'send-button-disabled'}`, onClick: () => this.sendMessage(this.messageInput), disabled: this.isTyping || this.isUploadingFiles || this.isLoading || !this.messageInput.trim() }, this.isUploadingFiles ? `${this.translationManager.get('status.uploading')}...` : this.translationManager.get('composer.send')))), h("div", { class: "flex items-center justify-center text-[0.8em] font-light w-full text-slate-500 py-[2px]" }, h("p", null, this.translationManager.get('branding.poweredBy'), ' ', " ", h("a", { class: "underline", href: "https://www.dimagi.com", target: "_blank" }, "Dimagi"))))))));
6263
6270
  }
6264
6271
  get host() { return this; }
6265
6272
  static get watchers() { return {