@blockspark/chat-widget 1.0.13 → 1.0.15

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 (185) hide show
  1. package/dist/_virtual/_plugin-vue_export-helper.cjs.js +2 -0
  2. package/dist/_virtual/_plugin-vue_export-helper.cjs.js.map +1 -0
  3. package/dist/_virtual/_plugin-vue_export-helper.esm.js +11 -0
  4. package/dist/_virtual/_plugin-vue_export-helper.esm.js.map +1 -0
  5. package/dist/components/ChatWidget.cjs.js +2 -0
  6. package/dist/components/ChatWidget.cjs.js.map +1 -0
  7. package/dist/{ChatWidget-Dfxoglek.js → components/ChatWidget.esm.js} +8 -60
  8. package/dist/components/ChatWidget.esm.js.map +1 -0
  9. package/dist/components/ChatWidget.vue.cjs.js +2 -0
  10. package/dist/components/ChatWidget.vue.cjs.js.map +1 -0
  11. package/dist/components/ChatWidget.vue.cjs2.js +2 -0
  12. package/dist/components/ChatWidget.vue.cjs2.js.map +1 -0
  13. package/dist/components/ChatWidget.vue.esm.js +8 -0
  14. package/dist/components/ChatWidget.vue.esm.js.map +1 -0
  15. package/dist/components/ChatWidget.vue.esm2.js +374 -0
  16. package/dist/components/ChatWidget.vue.esm2.js.map +1 -0
  17. package/dist/composables/useChatWidget.cjs.js +2 -0
  18. package/dist/composables/useChatWidget.cjs.js.map +1 -0
  19. package/dist/composables/useChatWidget.esm.js +75 -0
  20. package/dist/composables/useChatWidget.esm.js.map +1 -0
  21. package/dist/core/stateManager.cjs.js +2 -0
  22. package/dist/core/stateManager.cjs.js.map +1 -0
  23. package/dist/{ChatWidget-B6nWBTpX.js → core/stateManager.esm.js} +4 -450
  24. package/dist/core/stateManager.esm.js.map +1 -0
  25. package/dist/entry/vanilla.cjs.js +2 -0
  26. package/dist/entry/vanilla.cjs.js.map +1 -0
  27. package/dist/{vanilla.esm.js → entry/vanilla.esm.js} +4 -4
  28. package/dist/entry/vanilla.esm.js.map +1 -0
  29. package/dist/hooks/useChatMode.cjs.js +2 -0
  30. package/dist/hooks/useChatMode.cjs.js.map +1 -0
  31. package/dist/hooks/useChatMode.esm.js +61 -0
  32. package/dist/hooks/useChatMode.esm.js.map +1 -0
  33. package/dist/index.cjs.js +2 -0
  34. package/dist/index.cjs.js.map +1 -0
  35. package/dist/index.esm.js +9 -108
  36. package/dist/index.esm.js.map +1 -1
  37. package/dist/node_modules/jose/dist/browser/jws/compact/sign.cjs.js +2 -0
  38. package/dist/node_modules/jose/dist/browser/jws/compact/sign.cjs.js.map +1 -0
  39. package/dist/node_modules/jose/dist/browser/jws/compact/sign.esm.js +21 -0
  40. package/dist/node_modules/jose/dist/browser/jws/compact/sign.esm.js.map +1 -0
  41. package/dist/node_modules/jose/dist/browser/jws/flattened/sign.cjs.js +2 -0
  42. package/dist/node_modules/jose/dist/browser/jws/flattened/sign.cjs.js.map +1 -0
  43. package/dist/node_modules/jose/dist/browser/jws/flattened/sign.esm.js +84 -0
  44. package/dist/node_modules/jose/dist/browser/jws/flattened/sign.esm.js.map +1 -0
  45. package/dist/node_modules/jose/dist/browser/jwt/produce.cjs.js +2 -0
  46. package/dist/node_modules/jose/dist/browser/jwt/produce.cjs.js.map +1 -0
  47. package/dist/node_modules/jose/dist/browser/jwt/produce.esm.js +72 -0
  48. package/dist/node_modules/jose/dist/browser/jwt/produce.esm.js.map +1 -0
  49. package/dist/node_modules/jose/dist/browser/jwt/sign.cjs.js +2 -0
  50. package/dist/node_modules/jose/dist/browser/jwt/sign.cjs.js.map +1 -0
  51. package/dist/node_modules/jose/dist/browser/jwt/sign.esm.js +22 -0
  52. package/dist/node_modules/jose/dist/browser/jwt/sign.esm.js.map +1 -0
  53. package/dist/node_modules/jose/dist/browser/key/import.cjs.js +2 -0
  54. package/dist/node_modules/jose/dist/browser/key/import.cjs.js.map +1 -0
  55. package/dist/node_modules/jose/dist/browser/key/import.esm.js +11 -0
  56. package/dist/node_modules/jose/dist/browser/key/import.esm.js.map +1 -0
  57. package/dist/node_modules/jose/dist/browser/lib/buffer_utils.cjs.js +2 -0
  58. package/dist/node_modules/jose/dist/browser/lib/buffer_utils.cjs.js.map +1 -0
  59. package/dist/node_modules/jose/dist/browser/lib/buffer_utils.esm.js +18 -0
  60. package/dist/node_modules/jose/dist/browser/lib/buffer_utils.esm.js.map +1 -0
  61. package/dist/node_modules/jose/dist/browser/lib/check_key_type.cjs.js +2 -0
  62. package/dist/node_modules/jose/dist/browser/lib/check_key_type.cjs.js.map +1 -0
  63. package/dist/node_modules/jose/dist/browser/lib/check_key_type.esm.js +77 -0
  64. package/dist/node_modules/jose/dist/browser/lib/check_key_type.esm.js.map +1 -0
  65. package/dist/node_modules/jose/dist/browser/lib/crypto_key.cjs.js +2 -0
  66. package/dist/node_modules/jose/dist/browser/lib/crypto_key.cjs.js.map +1 -0
  67. package/dist/node_modules/jose/dist/browser/lib/crypto_key.esm.js +101 -0
  68. package/dist/node_modules/jose/dist/browser/lib/crypto_key.esm.js.map +1 -0
  69. package/dist/node_modules/jose/dist/browser/lib/epoch.cjs.js +2 -0
  70. package/dist/node_modules/jose/dist/browser/lib/epoch.cjs.js.map +1 -0
  71. package/dist/node_modules/jose/dist/browser/lib/epoch.esm.js +5 -0
  72. package/dist/node_modules/jose/dist/browser/lib/epoch.esm.js.map +1 -0
  73. package/dist/node_modules/jose/dist/browser/lib/invalid_key_input.cjs.js +2 -0
  74. package/dist/node_modules/jose/dist/browser/lib/invalid_key_input.cjs.js.map +1 -0
  75. package/dist/node_modules/jose/dist/browser/lib/invalid_key_input.esm.js +32 -0
  76. package/dist/node_modules/jose/dist/browser/lib/invalid_key_input.esm.js.map +1 -0
  77. package/dist/node_modules/jose/dist/browser/lib/is_disjoint.cjs.js +2 -0
  78. package/dist/node_modules/jose/dist/browser/lib/is_disjoint.cjs.js.map +1 -0
  79. package/dist/node_modules/jose/dist/browser/lib/is_disjoint.esm.js +25 -0
  80. package/dist/node_modules/jose/dist/browser/lib/is_disjoint.esm.js.map +1 -0
  81. package/dist/node_modules/jose/dist/browser/lib/is_jwk.cjs.js +2 -0
  82. package/dist/node_modules/jose/dist/browser/lib/is_jwk.cjs.js.map +1 -0
  83. package/dist/node_modules/jose/dist/browser/lib/is_jwk.esm.js +20 -0
  84. package/dist/node_modules/jose/dist/browser/lib/is_jwk.esm.js.map +1 -0
  85. package/dist/node_modules/jose/dist/browser/lib/is_object.cjs.js +2 -0
  86. package/dist/node_modules/jose/dist/browser/lib/is_object.cjs.js.map +1 -0
  87. package/dist/node_modules/jose/dist/browser/lib/is_object.esm.js +20 -0
  88. package/dist/node_modules/jose/dist/browser/lib/is_object.esm.js.map +1 -0
  89. package/dist/node_modules/jose/dist/browser/lib/secs.cjs.js +2 -0
  90. package/dist/node_modules/jose/dist/browser/lib/secs.cjs.js.map +1 -0
  91. package/dist/node_modules/jose/dist/browser/lib/secs.esm.js +59 -0
  92. package/dist/node_modules/jose/dist/browser/lib/secs.esm.js.map +1 -0
  93. package/dist/node_modules/jose/dist/browser/lib/validate_crit.cjs.js +2 -0
  94. package/dist/node_modules/jose/dist/browser/lib/validate_crit.cjs.js.map +1 -0
  95. package/dist/node_modules/jose/dist/browser/lib/validate_crit.esm.js +34 -0
  96. package/dist/node_modules/jose/dist/browser/lib/validate_crit.esm.js.map +1 -0
  97. package/dist/node_modules/jose/dist/browser/runtime/asn1.cjs.js +2 -0
  98. package/dist/node_modules/jose/dist/browser/runtime/asn1.cjs.js.map +1 -0
  99. package/dist/node_modules/jose/dist/browser/runtime/asn1.esm.js +103 -0
  100. package/dist/node_modules/jose/dist/browser/runtime/asn1.esm.js.map +1 -0
  101. package/dist/node_modules/jose/dist/browser/runtime/base64url.cjs.js +2 -0
  102. package/dist/node_modules/jose/dist/browser/runtime/base64url.cjs.js.map +1 -0
  103. package/dist/node_modules/jose/dist/browser/runtime/base64url.esm.js +43 -0
  104. package/dist/node_modules/jose/dist/browser/runtime/base64url.esm.js.map +1 -0
  105. package/dist/node_modules/jose/dist/browser/runtime/check_key_length.cjs.js +2 -0
  106. package/dist/node_modules/jose/dist/browser/runtime/check_key_length.cjs.js.map +1 -0
  107. package/dist/node_modules/jose/dist/browser/runtime/check_key_length.esm.js +12 -0
  108. package/dist/node_modules/jose/dist/browser/runtime/check_key_length.esm.js.map +1 -0
  109. package/dist/node_modules/jose/dist/browser/runtime/get_sign_verify_key.cjs.js +2 -0
  110. package/dist/node_modules/jose/dist/browser/runtime/get_sign_verify_key.cjs.js.map +1 -0
  111. package/dist/node_modules/jose/dist/browser/runtime/get_sign_verify_key.esm.js +25 -0
  112. package/dist/node_modules/jose/dist/browser/runtime/get_sign_verify_key.esm.js.map +1 -0
  113. package/dist/node_modules/jose/dist/browser/runtime/is_key_like.cjs.js +2 -0
  114. package/dist/node_modules/jose/dist/browser/runtime/is_key_like.cjs.js.map +1 -0
  115. package/dist/node_modules/jose/dist/browser/runtime/is_key_like.esm.js +13 -0
  116. package/dist/node_modules/jose/dist/browser/runtime/is_key_like.esm.js.map +1 -0
  117. package/dist/node_modules/jose/dist/browser/runtime/jwk_to_key.cjs.js +2 -0
  118. package/dist/node_modules/jose/dist/browser/runtime/jwk_to_key.cjs.js.map +1 -0
  119. package/dist/node_modules/jose/dist/browser/runtime/jwk_to_key.esm.js +107 -0
  120. package/dist/node_modules/jose/dist/browser/runtime/jwk_to_key.esm.js.map +1 -0
  121. package/dist/node_modules/jose/dist/browser/runtime/normalize_key.cjs.js +2 -0
  122. package/dist/node_modules/jose/dist/browser/runtime/normalize_key.cjs.js.map +1 -0
  123. package/dist/node_modules/jose/dist/browser/runtime/normalize_key.esm.js +71 -0
  124. package/dist/node_modules/jose/dist/browser/runtime/normalize_key.esm.js.map +1 -0
  125. package/dist/node_modules/jose/dist/browser/runtime/sign.cjs.js +2 -0
  126. package/dist/node_modules/jose/dist/browser/runtime/sign.cjs.js.map +1 -0
  127. package/dist/node_modules/jose/dist/browser/runtime/sign.esm.js +14 -0
  128. package/dist/node_modules/jose/dist/browser/runtime/sign.esm.js.map +1 -0
  129. package/dist/node_modules/jose/dist/browser/runtime/subtle_dsa.cjs.js +2 -0
  130. package/dist/node_modules/jose/dist/browser/runtime/subtle_dsa.cjs.js.map +1 -0
  131. package/dist/node_modules/jose/dist/browser/runtime/subtle_dsa.esm.js +32 -0
  132. package/dist/node_modules/jose/dist/browser/runtime/subtle_dsa.esm.js.map +1 -0
  133. package/dist/node_modules/jose/dist/browser/runtime/webcrypto.cjs.js +2 -0
  134. package/dist/node_modules/jose/dist/browser/runtime/webcrypto.cjs.js.map +1 -0
  135. package/dist/node_modules/jose/dist/browser/runtime/webcrypto.esm.js +7 -0
  136. package/dist/node_modules/jose/dist/browser/runtime/webcrypto.esm.js.map +1 -0
  137. package/dist/node_modules/jose/dist/browser/util/errors.cjs.js +2 -0
  138. package/dist/node_modules/jose/dist/browser/util/errors.cjs.js.map +1 -0
  139. package/dist/node_modules/jose/dist/browser/util/errors.esm.js +131 -0
  140. package/dist/node_modules/jose/dist/browser/util/errors.esm.js.map +1 -0
  141. package/dist/node_modules/react-dom/client.cjs.js +2 -0
  142. package/dist/node_modules/react-dom/client.cjs.js.map +1 -0
  143. package/dist/node_modules/react-dom/client.esm.js +21 -0
  144. package/dist/node_modules/react-dom/client.esm.js.map +1 -0
  145. package/dist/nuxt.cjs.js +2 -0
  146. package/dist/nuxt.cjs.js.map +1 -0
  147. package/dist/nuxt.esm.js +5 -4
  148. package/dist/nuxt.esm.js.map +1 -1
  149. package/dist/services/chatService.cjs.js +2 -0
  150. package/dist/services/chatService.cjs.js.map +1 -0
  151. package/dist/services/chatService.esm.js +482 -0
  152. package/dist/services/chatService.esm.js.map +1 -0
  153. package/dist/services/dialogflowClient.cjs.js +2 -0
  154. package/dist/services/dialogflowClient.cjs.js.map +1 -0
  155. package/dist/services/dialogflowClient.esm.js +282 -0
  156. package/dist/services/dialogflowClient.esm.js.map +1 -0
  157. package/dist/services/sessionManager.cjs.js +2 -0
  158. package/dist/services/sessionManager.cjs.js.map +1 -0
  159. package/dist/services/sessionManager.esm.js +48 -0
  160. package/dist/services/sessionManager.esm.js.map +1 -0
  161. package/dist/utils/frameworkDetector.cjs.js +2 -0
  162. package/dist/utils/frameworkDetector.cjs.js.map +1 -0
  163. package/dist/utils/frameworkDetector.d.ts.map +1 -1
  164. package/dist/utils/frameworkDetector.esm.js +125 -0
  165. package/dist/utils/frameworkDetector.esm.js.map +1 -0
  166. package/dist/utils/sanitize.cjs.js +2 -0
  167. package/dist/utils/sanitize.cjs.js.map +1 -0
  168. package/dist/utils/sanitize.d.ts.map +1 -1
  169. package/dist/utils/sanitize.esm.js +52 -0
  170. package/dist/utils/sanitize.esm.js.map +1 -0
  171. package/dist/vue.cjs.js +2 -0
  172. package/dist/vue.cjs.js.map +1 -0
  173. package/dist/vue.esm.js +5 -4
  174. package/dist/vue.esm.js.map +1 -1
  175. package/package.json +122 -92
  176. package/dist/ChatWidget-B6nWBTpX.js.map +0 -1
  177. package/dist/ChatWidget-Dfxoglek.js.map +0 -1
  178. package/dist/next.esm.js +0 -9
  179. package/dist/next.esm.js.map +0 -1
  180. package/dist/react.esm.js +0 -5
  181. package/dist/react.esm.js.map +0 -1
  182. package/dist/sanitize-BpLEG5NX.js +0 -2834
  183. package/dist/sanitize-BpLEG5NX.js.map +0 -1
  184. package/dist/vanilla.esm.js.map +0 -1
  185. /package/dist/{style.css → styles.css} +0 -0
@@ -0,0 +1 @@
1
+ {"version":3,"file":"ChatWidget.vue.cjs2.js","sources":["../../src/components/ChatWidget.vue"],"sourcesContent":["<template>\n <div class=\"custom-chat-widget\" v-bind=\"$attrs\">\n <!-- Welcome Popup -->\n <div\n v-if=\"state.showWelcomePopup && !state.isOpen\"\n class=\"custom-welcome-popup\"\n @click=\"handleOpenChat\"\n >\n <div class=\"custom-welcome-header\">\n <div class=\"custom-welcome-title\">{{ config.welcomeTitle }}</div>\n <button\n class=\"custom-close-popup\"\n @click.stop=\"handleCloseWelcomePopup\"\n aria-label=\"Close welcome popup\"\n >\n ×\n </button>\n </div>\n <div class=\"custom-welcome-message\">{{ config.welcomeMessage }}</div>\n <div class=\"custom-welcome-cta\">{{ config.welcomeCta }}</div>\n </div>\n\n <!-- Chat Toggle Button -->\n <button\n v-if=\"!state.isOpen\"\n class=\"custom-chat-toggle-btn\"\n @click=\"handleOpenChat\"\n aria-label=\"Open chat\"\n >\n <svg\n width=\"24\"\n height=\"24\"\n viewBox=\"0 0 24 24\"\n fill=\"none\"\n stroke=\"currentColor\"\n stroke-width=\"2\"\n stroke-linecap=\"round\"\n stroke-linejoin=\"round\"\n >\n <path d=\"M21 15a2 2 0 0 1-2 2H7l-4 4V5a2 2 0 0 1 2-2h14a2 2 0 0 1 2 2z\"></path>\n </svg>\n </button>\n\n <!-- Chat Window -->\n <div v-if=\"state.isOpen\" class=\"custom-chat-window\">\n <div class=\"custom-chat-header\">\n <div class=\"custom-chat-header-content\">\n <div class=\"custom-chat-title\">{{ config.title }}</div>\n <div class=\"custom-chat-subtitle\">\n {{ config.subtitle }}\n <span v-if=\"state.chatMode === 'human'\" class=\"custom-mode-indicator\">\n • {{ wsConnected ? '🟢 Connected' : '🟡 Connecting...' }}\n </span>\n </div>\n <div v-if=\"state.chatMode === 'human'\" class=\"custom-mode-badge\">\n Human Support Mode\n </div>\n <div v-if=\"state.chatMode === 'human'\" class=\"custom-agent-info\">\n <span class=\"custom-agent-label\">Agent:</span>\n <span class=\"custom-agent-name\">{{ currentAgent.name }}</span>\n </div>\n <div v-if=\"state.chatMode === 'ai'\" class=\"custom-mode-badge\">\n Bot Mode\n </div>\n </div>\n <button\n class=\"custom-chat-close-btn\"\n @click=\"handleCloseChat\"\n aria-label=\"Close chat\"\n >\n ×\n </button>\n </div>\n\n <div class=\"custom-chat-messages\" ref=\"messagesContainer\">\n <!-- Empty State -->\n <div v-if=\"isInitializing && state.messages.length === 0\" class=\"custom-chat-empty\">\n <div class=\"custom-typing-indicator\">\n <span></span>\n <span></span>\n <span></span>\n </div>\n <p>Initializing chat...</p>\n </div>\n <div v-else-if=\"!isInitializing && state.messages.length === 0\" class=\"custom-chat-empty\">\n <div class=\"custom-chat-empty-icon\">👋</div>\n <p>{{ config.emptyStateMessage }}</p>\n </div>\n\n <!-- Messages -->\n <div\n v-for=\"message in state.messages\"\n :key=\"message.id\"\n :class=\"[\n 'custom-message', \n `custom-message-${message.sender}`,\n { 'custom-handoff-message': isHandoffMessage(message.text) }\n ]\"\n >\n <div \n class=\"custom-message-content\"\n :class=\"{ 'custom-handoff-content': isHandoffMessage(message.text) }\"\n v-html=\"safeLinkifyText(message.text).replace(/\\n/g, '<br>')\"\n ></div>\n \n <!-- Rich Content (Chips) -->\n <div\n v-if=\"message.richContent && Array.isArray(message.richContent) && message.richContent.length > 0\"\n class=\"custom-chips-container\"\n >\n <template v-for=\"(contentGroup, groupIndex) in message.richContent\" :key=\"groupIndex\">\n <template v-if=\"!Array.isArray(contentGroup)\">\n <div\n v-if=\"contentGroup.type === 'chips' && contentGroup.options\"\n class=\"custom-chips-group\"\n >\n <button\n v-for=\"(chip, chipIndex) in contentGroup.options\"\n :key=\"chipIndex\"\n class=\"custom-chip-button\"\n type=\"button\"\n @click=\"handleChipClick(chip.text, chip.payload)\"\n >\n {{ chip.text }}\n </button>\n </div>\n </template>\n <template v-else>\n <template\n v-for=\"(content, contentIndex) in contentGroup\"\n :key=\"`${groupIndex}-${contentIndex}`\"\n >\n <div\n v-if=\"content.type === 'chips' && content.options\"\n class=\"custom-chips-group\"\n >\n <button\n v-for=\"(chip, chipIndex) in content.options\"\n :key=\"chipIndex\"\n class=\"custom-chip-button\"\n type=\"button\"\n @click=\"handleChipClick(chip.text, chip.payload)\"\n >\n {{ chip.text }}\n </button>\n </div>\n </template>\n </template>\n </template>\n </div>\n\n <div class=\"custom-message-time\">\n {{ formatTime(message.timestamp) }}\n </div>\n </div>\n\n <!-- Loading Indicator -->\n <div v-if=\"state.isLoading\" class=\"custom-message custom-message-bot\">\n <div class=\"custom-typing-indicator\">\n <span></span>\n <span></span>\n <span></span>\n </div>\n </div>\n\n <!-- Connecting to Agent Indicator -->\n <div v-if=\"isConnectingToAgent\" class=\"custom-message custom-message-bot\">\n <div class=\"custom-typing-indicator\">\n <span></span>\n <span></span>\n <span></span>\n </div>\n <div class=\"custom-message-content\">\n Connecting to agent...\n </div>\n </div>\n\n <!-- Agent Typing Indicator -->\n <div v-if=\"state.chatMode === 'human' && agentTyping\" class=\"custom-agent-typing-indicator\">\n <span class=\"custom-typing-dots\">\n <span></span>\n <span></span>\n <span></span>\n </span>\n <span class=\"custom-typing-text\">Agent is typing...</span>\n </div>\n\n <div ref=\"messagesEndRef\"></div>\n </div>\n\n <!-- Input Form -->\n <form class=\"custom-chat-input-form\" @submit.prevent=\"handleSubmit\">\n <input\n type=\"text\"\n class=\"custom-chat-input\"\n :value=\"state.inputValue\"\n @input=\"handleInput\"\n :placeholder=\"config.inputPlaceholder\"\n :disabled=\"state.isLoading || isInitializing || isStartingNewChat\"\n />\n <button\n type=\"submit\"\n class=\"custom-chat-send-btn\"\n :disabled=\"!state.inputValue.trim() || state.isLoading || isInitializing || isStartingNewChat\"\n >\n <svg\n width=\"20\"\n height=\"20\"\n viewBox=\"0 0 24 24\"\n fill=\"none\"\n stroke=\"currentColor\"\n stroke-width=\"2\"\n stroke-linecap=\"round\"\n stroke-linejoin=\"round\"\n >\n <line x1=\"22\" y1=\"2\" x2=\"11\" y2=\"13\"></line>\n <polygon points=\"22 2 15 22 11 13 2 9 22 2\"></polygon>\n </svg>\n </button>\n </form>\n </div>\n </div>\n</template>\n\n<script setup lang=\"ts\">\nimport { ref, computed, onMounted, nextTick, watch } from 'vue';\nimport { useChatWidget } from '../composables/useChatWidget';\nimport { safeLinkifyText } from '../utils/sanitize';\nimport type { WidgetConfig } from '../core/types';\n\n// Handle attributes properly to avoid Vue warnings\n// For Vue 3.3+, defineOptions is available as a compiler macro\n// @ts-ignore - defineOptions is a compiler macro\ndefineOptions({\n inheritAttrs: false, // We handle attrs manually via v-bind=\"$attrs\"\n});\n\n// Props\nconst props = withDefaults(defineProps<WidgetConfig>(), {\n title: '💬 BlockSpark AI Assistant',\n subtitle: \"We're here to help\",\n welcomeTitle: '👋 Welcome to BlockSpark',\n welcomeMessage: \"My name is BlockSpark AI Assistant and I'll guide you.\",\n welcomeCta: '💬 Click here to start chatting!',\n showWelcomePopup: true,\n welcomePopupDelay: 1500,\n fallbackWelcomeMessage: \"Hello! I'm BlockSpark AI Assistant. How can I help you today?\",\n inputPlaceholder: 'Type your message...',\n emptyStateMessage: \"Hi! I'm BlockSpark AI Assistant. How can I help you today?\",\n debug: false,\n});\n\n// Use headless composable\nconst {\n state,\n isOpen,\n messages,\n isLoading,\n error,\n chatMode,\n wsConnected,\n agentTyping,\n currentAgent,\n isConnectingToAgent: isConnectingToAgentFromComposable,\n openChat,\n closeChat,\n sendMessage,\n toggleChat,\n setInputValue,\n clearError,\n manager,\n} = useChatWidget(props);\n\n// Refs\nconst messagesEndRef = ref<HTMLDivElement | null>(null);\nconst messagesContainer = ref<HTMLDivElement | null>(null);\n\n// Computed config (for reactivity)\nconst config = computed(() => props);\n\n// Computed state for initialization and connection (matching React component)\nconst isInitializing = computed(() => {\n return state.value.isLoading && state.value.messages.length === 0 && !state.value.sessionId;\n});\n\nconst isStartingNewChat = computed(() => {\n // This would be tracked in manager if needed, for now return false\n return false;\n});\n\n// Use isConnectingToAgent from composable (already computed in manager)\nconst isConnectingToAgent = isConnectingToAgentFromComposable;\n\n// Auto-scroll to bottom when messages change\nwatch(\n () => messages.value.length,\n () => {\n nextTick(() => {\n messagesEndRef.value?.scrollIntoView({ behavior: 'smooth' });\n });\n }\n);\n\n// Handlers\nconst handleOpenChat = async () => {\n // Ensure immediate UI response\n if (!state.value.isOpen) {\n state.value.isOpen = true;\n state.value.showWelcomePopup = false;\n }\n await openChat();\n};\n\nconst handleCloseChat = () => {\n closeChat();\n};\n\nconst handleCloseWelcomePopup = () => {\n manager.closeWelcomePopup();\n};\n\nconst handleInput = (event: Event) => {\n const target = event.target as HTMLInputElement;\n setInputValue(target.value);\n};\n\nconst handleSubmit = async (event: Event) => {\n event.preventDefault();\n if (state.value.inputValue.trim()) {\n await sendMessage(state.value.inputValue);\n }\n};\n\nconst handleChipClick = async (chipText: string, payload?: string) => {\n const messageToSend = chipText || payload || '';\n await sendMessage(messageToSend);\n};\n\n// Utility functions\nconst formatTime = (date: Date): string => {\n return date.toLocaleTimeString([], {\n hour: '2-digit',\n minute: '2-digit',\n });\n};\n\n// Check if message is a handoff message\nconst isHandoffMessage = (text: string): boolean => {\n return text.includes('👤') || \n text.includes('being connected') || \n text.includes('live support agent') ||\n text.includes('transfer your conversation');\n};\n\n// Initialize welcome popup on mount (SSR-safe)\nonMounted(() => {\n if (config.value.showWelcomePopup && typeof window !== 'undefined') {\n manager.initializeWelcomePopup();\n }\n});\n</script>\n\n<style scoped>\n/* Styles are imported separately by users */\n/* This ensures SSR compatibility */\n</style>\n"],"names":["props","__props","state","isOpen","messages","isLoading","error","chatMode","wsConnected","agentTyping","currentAgent","isConnectingToAgent","isConnectingToAgentFromComposable","openChat","closeChat","sendMessage","toggleChat","setInputValue","clearError","manager","useChatWidget","messagesEndRef","ref","messagesContainer","config","computed","isInitializing","value","length","sessionId","isStartingNewChat","watch","nextTick","scrollIntoView","behavior","handleOpenChat","async","showWelcomePopup","handleCloseChat","handleCloseWelcomePopup","closeWelcomePopup","handleInput","event","target","handleSubmit","preventDefault","inputValue","trim","handleChipClick","chipText","payload","messageToSend","isHandoffMessage","text","includes","onMounted","window","initializeWelcomePopup","_openBlock","_createElementBlock","_mergeProps","class","$attrs","_unref","onClick","_createElementVNode","_hoisted_1","_hoisted_2","_toDisplayString","welcomeTitle","_hoisted_3","welcomeMessage","_hoisted_4","welcomeCta","width","height","viewBox","fill","stroke","d","_hoisted_5","_hoisted_6","_hoisted_7","_hoisted_8","title","_hoisted_9","subtitle","_hoisted_10","_hoisted_11","_hoisted_12","_cache","_hoisted_13","name","_hoisted_14","_hoisted_15","_hoisted_16","emptyStateMessage","_Fragment","_renderList","message","key","id","_normalizeClass","sender","innerHTML","safeLinkifyText","replace","richContent","Array","isArray","_hoisted_18","contentGroup","groupIndex","content","contentIndex","type","options","_hoisted_21","chip","chipIndex","$event","_hoisted_22","_hoisted_19","_hoisted_20","_hoisted_23","date","timestamp","toLocaleTimeString","hour","minute","_hoisted_24","_hoisted_25","_hoisted_26","onSubmit","onInput","placeholder","inputPlaceholder","disabled","x1","y1","x2","y2","points"],"mappings":"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"}
@@ -0,0 +1,8 @@
1
+ import _sfc_main from "./ChatWidget.vue.esm2.js";
2
+ /* empty css */
3
+ import _export_sfc from "../_virtual/_plugin-vue_export-helper.esm.js";
4
+ const ChatWidgetComponent = /* @__PURE__ */ _export_sfc(_sfc_main, [["__scopeId", "data-v-0d32fcf4"]]);
5
+ export {
6
+ ChatWidgetComponent as default
7
+ };
8
+ //# sourceMappingURL=ChatWidget.vue.esm.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"ChatWidget.vue.esm.js","sources":[],"sourcesContent":[],"names":[],"mappings":";;;;"}
@@ -0,0 +1,374 @@
1
+ import { defineComponent, ref, computed, watch, nextTick, onMounted, openBlock, createElementBlock, mergeProps, unref, createElementVNode, toDisplayString, withModifiers, createCommentVNode, createTextVNode, Fragment, renderList, normalizeClass } from "vue";
2
+ import { useChatWidget } from "../composables/useChatWidget.esm.js";
3
+ import { safeLinkifyText } from "../utils/sanitize.esm.js";
4
+ const _hoisted_1 = { class: "custom-welcome-header" };
5
+ const _hoisted_2 = { class: "custom-welcome-title" };
6
+ const _hoisted_3 = { class: "custom-welcome-message" };
7
+ const _hoisted_4 = { class: "custom-welcome-cta" };
8
+ const _hoisted_5 = {
9
+ key: 2,
10
+ class: "custom-chat-window"
11
+ };
12
+ const _hoisted_6 = { class: "custom-chat-header" };
13
+ const _hoisted_7 = { class: "custom-chat-header-content" };
14
+ const _hoisted_8 = { class: "custom-chat-title" };
15
+ const _hoisted_9 = { class: "custom-chat-subtitle" };
16
+ const _hoisted_10 = {
17
+ key: 0,
18
+ class: "custom-mode-indicator"
19
+ };
20
+ const _hoisted_11 = {
21
+ key: 0,
22
+ class: "custom-mode-badge"
23
+ };
24
+ const _hoisted_12 = {
25
+ key: 1,
26
+ class: "custom-agent-info"
27
+ };
28
+ const _hoisted_13 = { class: "custom-agent-name" };
29
+ const _hoisted_14 = {
30
+ key: 2,
31
+ class: "custom-mode-badge"
32
+ };
33
+ const _hoisted_15 = {
34
+ key: 0,
35
+ class: "custom-chat-empty"
36
+ };
37
+ const _hoisted_16 = {
38
+ key: 1,
39
+ class: "custom-chat-empty"
40
+ };
41
+ const _hoisted_17 = ["innerHTML"];
42
+ const _hoisted_18 = {
43
+ key: 0,
44
+ class: "custom-chips-container"
45
+ };
46
+ const _hoisted_19 = {
47
+ key: 0,
48
+ class: "custom-chips-group"
49
+ };
50
+ const _hoisted_20 = ["onClick"];
51
+ const _hoisted_21 = {
52
+ key: 0,
53
+ class: "custom-chips-group"
54
+ };
55
+ const _hoisted_22 = ["onClick"];
56
+ const _hoisted_23 = { class: "custom-message-time" };
57
+ const _hoisted_24 = {
58
+ key: 2,
59
+ class: "custom-message custom-message-bot"
60
+ };
61
+ const _hoisted_25 = {
62
+ key: 3,
63
+ class: "custom-message custom-message-bot"
64
+ };
65
+ const _hoisted_26 = {
66
+ key: 4,
67
+ class: "custom-agent-typing-indicator"
68
+ };
69
+ const _hoisted_27 = ["value", "placeholder", "disabled"];
70
+ const _hoisted_28 = ["disabled"];
71
+ const _sfc_main = /* @__PURE__ */ defineComponent({
72
+ ...{
73
+ inheritAttrs: false
74
+ // We handle attrs manually via v-bind="$attrs"
75
+ },
76
+ __name: "ChatWidget",
77
+ props: {
78
+ dfProjectId: {},
79
+ dfLocation: {},
80
+ dfAgentId: {},
81
+ serviceAccountKey: {},
82
+ accessToken: {},
83
+ languageCode: {},
84
+ backendBaseUrl: {},
85
+ backendWsUrl: {},
86
+ title: { default: "💬 BlockSpark AI Assistant" },
87
+ subtitle: { default: "We're here to help" },
88
+ welcomeTitle: { default: "👋 Welcome to BlockSpark" },
89
+ welcomeMessage: { default: "My name is BlockSpark AI Assistant and I'll guide you." },
90
+ welcomeCta: { default: "💬 Click here to start chatting!" },
91
+ showWelcomePopup: { type: Boolean, default: true },
92
+ welcomePopupDelay: { default: 1500 },
93
+ fallbackWelcomeMessage: { default: "Hello! I'm BlockSpark AI Assistant. How can I help you today?" },
94
+ inputPlaceholder: { default: "Type your message..." },
95
+ emptyStateMessage: { default: "Hi! I'm BlockSpark AI Assistant. How can I help you today?" },
96
+ debug: { type: Boolean, default: false }
97
+ },
98
+ setup(__props) {
99
+ const props = __props;
100
+ const {
101
+ state,
102
+ isOpen,
103
+ messages,
104
+ isLoading,
105
+ error,
106
+ chatMode,
107
+ wsConnected,
108
+ agentTyping,
109
+ currentAgent,
110
+ isConnectingToAgent: isConnectingToAgentFromComposable,
111
+ openChat,
112
+ closeChat,
113
+ sendMessage,
114
+ toggleChat,
115
+ setInputValue,
116
+ clearError,
117
+ manager
118
+ } = useChatWidget(props);
119
+ const messagesEndRef = ref(null);
120
+ const messagesContainer = ref(null);
121
+ const config = computed(() => props);
122
+ const isInitializing = computed(() => {
123
+ return state.value.isLoading && state.value.messages.length === 0 && !state.value.sessionId;
124
+ });
125
+ const isStartingNewChat = computed(() => {
126
+ return false;
127
+ });
128
+ const isConnectingToAgent = isConnectingToAgentFromComposable;
129
+ watch(
130
+ () => messages.value.length,
131
+ () => {
132
+ nextTick(() => {
133
+ messagesEndRef.value?.scrollIntoView({ behavior: "smooth" });
134
+ });
135
+ }
136
+ );
137
+ const handleOpenChat = async () => {
138
+ if (!state.value.isOpen) {
139
+ state.value.isOpen = true;
140
+ state.value.showWelcomePopup = false;
141
+ }
142
+ await openChat();
143
+ };
144
+ const handleCloseChat = () => {
145
+ closeChat();
146
+ };
147
+ const handleCloseWelcomePopup = () => {
148
+ manager.closeWelcomePopup();
149
+ };
150
+ const handleInput = (event) => {
151
+ const target = event.target;
152
+ setInputValue(target.value);
153
+ };
154
+ const handleSubmit = async (event) => {
155
+ event.preventDefault();
156
+ if (state.value.inputValue.trim()) {
157
+ await sendMessage(state.value.inputValue);
158
+ }
159
+ };
160
+ const handleChipClick = async (chipText, payload) => {
161
+ const messageToSend = chipText || payload || "";
162
+ await sendMessage(messageToSend);
163
+ };
164
+ const formatTime = (date) => {
165
+ return date.toLocaleTimeString([], {
166
+ hour: "2-digit",
167
+ minute: "2-digit"
168
+ });
169
+ };
170
+ const isHandoffMessage = (text) => {
171
+ return text.includes("👤") || text.includes("being connected") || text.includes("live support agent") || text.includes("transfer your conversation");
172
+ };
173
+ onMounted(() => {
174
+ if (config.value.showWelcomePopup && typeof window !== "undefined") {
175
+ manager.initializeWelcomePopup();
176
+ }
177
+ });
178
+ return (_ctx, _cache) => {
179
+ return openBlock(), createElementBlock("div", mergeProps({ class: "custom-chat-widget" }, _ctx.$attrs), [
180
+ unref(state).showWelcomePopup && !unref(state).isOpen ? (openBlock(), createElementBlock("div", {
181
+ key: 0,
182
+ class: "custom-welcome-popup",
183
+ onClick: handleOpenChat
184
+ }, [
185
+ createElementVNode("div", _hoisted_1, [
186
+ createElementVNode("div", _hoisted_2, toDisplayString(config.value.welcomeTitle), 1),
187
+ createElementVNode("button", {
188
+ class: "custom-close-popup",
189
+ onClick: withModifiers(handleCloseWelcomePopup, ["stop"]),
190
+ "aria-label": "Close welcome popup"
191
+ }, " × ")
192
+ ]),
193
+ createElementVNode("div", _hoisted_3, toDisplayString(config.value.welcomeMessage), 1),
194
+ createElementVNode("div", _hoisted_4, toDisplayString(config.value.welcomeCta), 1)
195
+ ])) : createCommentVNode("", true),
196
+ !unref(state).isOpen ? (openBlock(), createElementBlock("button", {
197
+ key: 1,
198
+ class: "custom-chat-toggle-btn",
199
+ onClick: handleOpenChat,
200
+ "aria-label": "Open chat"
201
+ }, [..._cache[0] || (_cache[0] = [
202
+ createElementVNode("svg", {
203
+ width: "24",
204
+ height: "24",
205
+ viewBox: "0 0 24 24",
206
+ fill: "none",
207
+ stroke: "currentColor",
208
+ "stroke-width": "2",
209
+ "stroke-linecap": "round",
210
+ "stroke-linejoin": "round"
211
+ }, [
212
+ createElementVNode("path", { d: "M21 15a2 2 0 0 1-2 2H7l-4 4V5a2 2 0 0 1 2-2h14a2 2 0 0 1 2 2z" })
213
+ ], -1)
214
+ ])])) : createCommentVNode("", true),
215
+ unref(state).isOpen ? (openBlock(), createElementBlock("div", _hoisted_5, [
216
+ createElementVNode("div", _hoisted_6, [
217
+ createElementVNode("div", _hoisted_7, [
218
+ createElementVNode("div", _hoisted_8, toDisplayString(config.value.title), 1),
219
+ createElementVNode("div", _hoisted_9, [
220
+ createTextVNode(toDisplayString(config.value.subtitle) + " ", 1),
221
+ unref(state).chatMode === "human" ? (openBlock(), createElementBlock("span", _hoisted_10, " • " + toDisplayString(unref(wsConnected) ? "🟢 Connected" : "🟡 Connecting..."), 1)) : createCommentVNode("", true)
222
+ ]),
223
+ unref(state).chatMode === "human" ? (openBlock(), createElementBlock("div", _hoisted_11, " Human Support Mode ")) : createCommentVNode("", true),
224
+ unref(state).chatMode === "human" ? (openBlock(), createElementBlock("div", _hoisted_12, [
225
+ _cache[1] || (_cache[1] = createElementVNode("span", { class: "custom-agent-label" }, "Agent:", -1)),
226
+ createElementVNode("span", _hoisted_13, toDisplayString(unref(currentAgent).name), 1)
227
+ ])) : createCommentVNode("", true),
228
+ unref(state).chatMode === "ai" ? (openBlock(), createElementBlock("div", _hoisted_14, " Bot Mode ")) : createCommentVNode("", true)
229
+ ]),
230
+ createElementVNode("button", {
231
+ class: "custom-chat-close-btn",
232
+ onClick: handleCloseChat,
233
+ "aria-label": "Close chat"
234
+ }, " × ")
235
+ ]),
236
+ createElementVNode("div", {
237
+ class: "custom-chat-messages",
238
+ ref_key: "messagesContainer",
239
+ ref: messagesContainer
240
+ }, [
241
+ isInitializing.value && unref(state).messages.length === 0 ? (openBlock(), createElementBlock("div", _hoisted_15, [..._cache[2] || (_cache[2] = [
242
+ createElementVNode("div", { class: "custom-typing-indicator" }, [
243
+ createElementVNode("span"),
244
+ createElementVNode("span"),
245
+ createElementVNode("span")
246
+ ], -1),
247
+ createElementVNode("p", null, "Initializing chat...", -1)
248
+ ])])) : !isInitializing.value && unref(state).messages.length === 0 ? (openBlock(), createElementBlock("div", _hoisted_16, [
249
+ _cache[3] || (_cache[3] = createElementVNode("div", { class: "custom-chat-empty-icon" }, "👋", -1)),
250
+ createElementVNode("p", null, toDisplayString(config.value.emptyStateMessage), 1)
251
+ ])) : createCommentVNode("", true),
252
+ (openBlock(true), createElementBlock(Fragment, null, renderList(unref(state).messages, (message) => {
253
+ return openBlock(), createElementBlock("div", {
254
+ key: message.id,
255
+ class: normalizeClass([
256
+ "custom-message",
257
+ `custom-message-${message.sender}`,
258
+ { "custom-handoff-message": isHandoffMessage(message.text) }
259
+ ])
260
+ }, [
261
+ createElementVNode("div", {
262
+ class: normalizeClass(["custom-message-content", { "custom-handoff-content": isHandoffMessage(message.text) }]),
263
+ innerHTML: unref(safeLinkifyText)(message.text).replace(/\n/g, "<br>")
264
+ }, null, 10, _hoisted_17),
265
+ message.richContent && Array.isArray(message.richContent) && message.richContent.length > 0 ? (openBlock(), createElementBlock("div", _hoisted_18, [
266
+ (openBlock(true), createElementBlock(Fragment, null, renderList(message.richContent, (contentGroup, groupIndex) => {
267
+ return openBlock(), createElementBlock(Fragment, { key: groupIndex }, [
268
+ !Array.isArray(contentGroup) ? (openBlock(), createElementBlock(Fragment, { key: 0 }, [
269
+ contentGroup.type === "chips" && contentGroup.options ? (openBlock(), createElementBlock("div", _hoisted_19, [
270
+ (openBlock(true), createElementBlock(Fragment, null, renderList(contentGroup.options, (chip, chipIndex) => {
271
+ return openBlock(), createElementBlock("button", {
272
+ key: chipIndex,
273
+ class: "custom-chip-button",
274
+ type: "button",
275
+ onClick: ($event) => handleChipClick(chip.text, chip.payload)
276
+ }, toDisplayString(chip.text), 9, _hoisted_20);
277
+ }), 128))
278
+ ])) : createCommentVNode("", true)
279
+ ], 64)) : (openBlock(true), createElementBlock(Fragment, { key: 1 }, renderList(contentGroup, (content, contentIndex) => {
280
+ return openBlock(), createElementBlock(Fragment, {
281
+ key: `${groupIndex}-${contentIndex}`
282
+ }, [
283
+ content.type === "chips" && content.options ? (openBlock(), createElementBlock("div", _hoisted_21, [
284
+ (openBlock(true), createElementBlock(Fragment, null, renderList(content.options, (chip, chipIndex) => {
285
+ return openBlock(), createElementBlock("button", {
286
+ key: chipIndex,
287
+ class: "custom-chip-button",
288
+ type: "button",
289
+ onClick: ($event) => handleChipClick(chip.text, chip.payload)
290
+ }, toDisplayString(chip.text), 9, _hoisted_22);
291
+ }), 128))
292
+ ])) : createCommentVNode("", true)
293
+ ], 64);
294
+ }), 128))
295
+ ], 64);
296
+ }), 128))
297
+ ])) : createCommentVNode("", true),
298
+ createElementVNode("div", _hoisted_23, toDisplayString(formatTime(message.timestamp)), 1)
299
+ ], 2);
300
+ }), 128)),
301
+ unref(state).isLoading ? (openBlock(), createElementBlock("div", _hoisted_24, [..._cache[4] || (_cache[4] = [
302
+ createElementVNode("div", { class: "custom-typing-indicator" }, [
303
+ createElementVNode("span"),
304
+ createElementVNode("span"),
305
+ createElementVNode("span")
306
+ ], -1)
307
+ ])])) : createCommentVNode("", true),
308
+ unref(isConnectingToAgent) ? (openBlock(), createElementBlock("div", _hoisted_25, [..._cache[5] || (_cache[5] = [
309
+ createElementVNode("div", { class: "custom-typing-indicator" }, [
310
+ createElementVNode("span"),
311
+ createElementVNode("span"),
312
+ createElementVNode("span")
313
+ ], -1),
314
+ createElementVNode("div", { class: "custom-message-content" }, " Connecting to agent... ", -1)
315
+ ])])) : createCommentVNode("", true),
316
+ unref(state).chatMode === "human" && unref(agentTyping) ? (openBlock(), createElementBlock("div", _hoisted_26, [..._cache[6] || (_cache[6] = [
317
+ createElementVNode("span", { class: "custom-typing-dots" }, [
318
+ createElementVNode("span"),
319
+ createElementVNode("span"),
320
+ createElementVNode("span")
321
+ ], -1),
322
+ createElementVNode("span", { class: "custom-typing-text" }, "Agent is typing...", -1)
323
+ ])])) : createCommentVNode("", true),
324
+ createElementVNode("div", {
325
+ ref_key: "messagesEndRef",
326
+ ref: messagesEndRef
327
+ }, null, 512)
328
+ ], 512),
329
+ createElementVNode("form", {
330
+ class: "custom-chat-input-form",
331
+ onSubmit: withModifiers(handleSubmit, ["prevent"])
332
+ }, [
333
+ createElementVNode("input", {
334
+ type: "text",
335
+ class: "custom-chat-input",
336
+ value: unref(state).inputValue,
337
+ onInput: handleInput,
338
+ placeholder: config.value.inputPlaceholder,
339
+ disabled: unref(state).isLoading || isInitializing.value || isStartingNewChat.value
340
+ }, null, 40, _hoisted_27),
341
+ createElementVNode("button", {
342
+ type: "submit",
343
+ class: "custom-chat-send-btn",
344
+ disabled: !unref(state).inputValue.trim() || unref(state).isLoading || isInitializing.value || isStartingNewChat.value
345
+ }, [..._cache[7] || (_cache[7] = [
346
+ createElementVNode("svg", {
347
+ width: "20",
348
+ height: "20",
349
+ viewBox: "0 0 24 24",
350
+ fill: "none",
351
+ stroke: "currentColor",
352
+ "stroke-width": "2",
353
+ "stroke-linecap": "round",
354
+ "stroke-linejoin": "round"
355
+ }, [
356
+ createElementVNode("line", {
357
+ x1: "22",
358
+ y1: "2",
359
+ x2: "11",
360
+ y2: "13"
361
+ }),
362
+ createElementVNode("polygon", { points: "22 2 15 22 11 13 2 9 22 2" })
363
+ ], -1)
364
+ ])], 8, _hoisted_28)
365
+ ], 32)
366
+ ])) : createCommentVNode("", true)
367
+ ], 16);
368
+ };
369
+ }
370
+ });
371
+ export {
372
+ _sfc_main as default
373
+ };
374
+ //# sourceMappingURL=ChatWidget.vue.esm2.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"ChatWidget.vue.esm2.js","sources":["../../src/components/ChatWidget.vue"],"sourcesContent":["<template>\n <div class=\"custom-chat-widget\" v-bind=\"$attrs\">\n <!-- Welcome Popup -->\n <div\n v-if=\"state.showWelcomePopup && !state.isOpen\"\n class=\"custom-welcome-popup\"\n @click=\"handleOpenChat\"\n >\n <div class=\"custom-welcome-header\">\n <div class=\"custom-welcome-title\">{{ config.welcomeTitle }}</div>\n <button\n class=\"custom-close-popup\"\n @click.stop=\"handleCloseWelcomePopup\"\n aria-label=\"Close welcome popup\"\n >\n ×\n </button>\n </div>\n <div class=\"custom-welcome-message\">{{ config.welcomeMessage }}</div>\n <div class=\"custom-welcome-cta\">{{ config.welcomeCta }}</div>\n </div>\n\n <!-- Chat Toggle Button -->\n <button\n v-if=\"!state.isOpen\"\n class=\"custom-chat-toggle-btn\"\n @click=\"handleOpenChat\"\n aria-label=\"Open chat\"\n >\n <svg\n width=\"24\"\n height=\"24\"\n viewBox=\"0 0 24 24\"\n fill=\"none\"\n stroke=\"currentColor\"\n stroke-width=\"2\"\n stroke-linecap=\"round\"\n stroke-linejoin=\"round\"\n >\n <path d=\"M21 15a2 2 0 0 1-2 2H7l-4 4V5a2 2 0 0 1 2-2h14a2 2 0 0 1 2 2z\"></path>\n </svg>\n </button>\n\n <!-- Chat Window -->\n <div v-if=\"state.isOpen\" class=\"custom-chat-window\">\n <div class=\"custom-chat-header\">\n <div class=\"custom-chat-header-content\">\n <div class=\"custom-chat-title\">{{ config.title }}</div>\n <div class=\"custom-chat-subtitle\">\n {{ config.subtitle }}\n <span v-if=\"state.chatMode === 'human'\" class=\"custom-mode-indicator\">\n • {{ wsConnected ? '🟢 Connected' : '🟡 Connecting...' }}\n </span>\n </div>\n <div v-if=\"state.chatMode === 'human'\" class=\"custom-mode-badge\">\n Human Support Mode\n </div>\n <div v-if=\"state.chatMode === 'human'\" class=\"custom-agent-info\">\n <span class=\"custom-agent-label\">Agent:</span>\n <span class=\"custom-agent-name\">{{ currentAgent.name }}</span>\n </div>\n <div v-if=\"state.chatMode === 'ai'\" class=\"custom-mode-badge\">\n Bot Mode\n </div>\n </div>\n <button\n class=\"custom-chat-close-btn\"\n @click=\"handleCloseChat\"\n aria-label=\"Close chat\"\n >\n ×\n </button>\n </div>\n\n <div class=\"custom-chat-messages\" ref=\"messagesContainer\">\n <!-- Empty State -->\n <div v-if=\"isInitializing && state.messages.length === 0\" class=\"custom-chat-empty\">\n <div class=\"custom-typing-indicator\">\n <span></span>\n <span></span>\n <span></span>\n </div>\n <p>Initializing chat...</p>\n </div>\n <div v-else-if=\"!isInitializing && state.messages.length === 0\" class=\"custom-chat-empty\">\n <div class=\"custom-chat-empty-icon\">👋</div>\n <p>{{ config.emptyStateMessage }}</p>\n </div>\n\n <!-- Messages -->\n <div\n v-for=\"message in state.messages\"\n :key=\"message.id\"\n :class=\"[\n 'custom-message', \n `custom-message-${message.sender}`,\n { 'custom-handoff-message': isHandoffMessage(message.text) }\n ]\"\n >\n <div \n class=\"custom-message-content\"\n :class=\"{ 'custom-handoff-content': isHandoffMessage(message.text) }\"\n v-html=\"safeLinkifyText(message.text).replace(/\\n/g, '<br>')\"\n ></div>\n \n <!-- Rich Content (Chips) -->\n <div\n v-if=\"message.richContent && Array.isArray(message.richContent) && message.richContent.length > 0\"\n class=\"custom-chips-container\"\n >\n <template v-for=\"(contentGroup, groupIndex) in message.richContent\" :key=\"groupIndex\">\n <template v-if=\"!Array.isArray(contentGroup)\">\n <div\n v-if=\"contentGroup.type === 'chips' && contentGroup.options\"\n class=\"custom-chips-group\"\n >\n <button\n v-for=\"(chip, chipIndex) in contentGroup.options\"\n :key=\"chipIndex\"\n class=\"custom-chip-button\"\n type=\"button\"\n @click=\"handleChipClick(chip.text, chip.payload)\"\n >\n {{ chip.text }}\n </button>\n </div>\n </template>\n <template v-else>\n <template\n v-for=\"(content, contentIndex) in contentGroup\"\n :key=\"`${groupIndex}-${contentIndex}`\"\n >\n <div\n v-if=\"content.type === 'chips' && content.options\"\n class=\"custom-chips-group\"\n >\n <button\n v-for=\"(chip, chipIndex) in content.options\"\n :key=\"chipIndex\"\n class=\"custom-chip-button\"\n type=\"button\"\n @click=\"handleChipClick(chip.text, chip.payload)\"\n >\n {{ chip.text }}\n </button>\n </div>\n </template>\n </template>\n </template>\n </div>\n\n <div class=\"custom-message-time\">\n {{ formatTime(message.timestamp) }}\n </div>\n </div>\n\n <!-- Loading Indicator -->\n <div v-if=\"state.isLoading\" class=\"custom-message custom-message-bot\">\n <div class=\"custom-typing-indicator\">\n <span></span>\n <span></span>\n <span></span>\n </div>\n </div>\n\n <!-- Connecting to Agent Indicator -->\n <div v-if=\"isConnectingToAgent\" class=\"custom-message custom-message-bot\">\n <div class=\"custom-typing-indicator\">\n <span></span>\n <span></span>\n <span></span>\n </div>\n <div class=\"custom-message-content\">\n Connecting to agent...\n </div>\n </div>\n\n <!-- Agent Typing Indicator -->\n <div v-if=\"state.chatMode === 'human' && agentTyping\" class=\"custom-agent-typing-indicator\">\n <span class=\"custom-typing-dots\">\n <span></span>\n <span></span>\n <span></span>\n </span>\n <span class=\"custom-typing-text\">Agent is typing...</span>\n </div>\n\n <div ref=\"messagesEndRef\"></div>\n </div>\n\n <!-- Input Form -->\n <form class=\"custom-chat-input-form\" @submit.prevent=\"handleSubmit\">\n <input\n type=\"text\"\n class=\"custom-chat-input\"\n :value=\"state.inputValue\"\n @input=\"handleInput\"\n :placeholder=\"config.inputPlaceholder\"\n :disabled=\"state.isLoading || isInitializing || isStartingNewChat\"\n />\n <button\n type=\"submit\"\n class=\"custom-chat-send-btn\"\n :disabled=\"!state.inputValue.trim() || state.isLoading || isInitializing || isStartingNewChat\"\n >\n <svg\n width=\"20\"\n height=\"20\"\n viewBox=\"0 0 24 24\"\n fill=\"none\"\n stroke=\"currentColor\"\n stroke-width=\"2\"\n stroke-linecap=\"round\"\n stroke-linejoin=\"round\"\n >\n <line x1=\"22\" y1=\"2\" x2=\"11\" y2=\"13\"></line>\n <polygon points=\"22 2 15 22 11 13 2 9 22 2\"></polygon>\n </svg>\n </button>\n </form>\n </div>\n </div>\n</template>\n\n<script setup lang=\"ts\">\nimport { ref, computed, onMounted, nextTick, watch } from 'vue';\nimport { useChatWidget } from '../composables/useChatWidget';\nimport { safeLinkifyText } from '../utils/sanitize';\nimport type { WidgetConfig } from '../core/types';\n\n// Handle attributes properly to avoid Vue warnings\n// For Vue 3.3+, defineOptions is available as a compiler macro\n// @ts-ignore - defineOptions is a compiler macro\ndefineOptions({\n inheritAttrs: false, // We handle attrs manually via v-bind=\"$attrs\"\n});\n\n// Props\nconst props = withDefaults(defineProps<WidgetConfig>(), {\n title: '💬 BlockSpark AI Assistant',\n subtitle: \"We're here to help\",\n welcomeTitle: '👋 Welcome to BlockSpark',\n welcomeMessage: \"My name is BlockSpark AI Assistant and I'll guide you.\",\n welcomeCta: '💬 Click here to start chatting!',\n showWelcomePopup: true,\n welcomePopupDelay: 1500,\n fallbackWelcomeMessage: \"Hello! I'm BlockSpark AI Assistant. How can I help you today?\",\n inputPlaceholder: 'Type your message...',\n emptyStateMessage: \"Hi! I'm BlockSpark AI Assistant. How can I help you today?\",\n debug: false,\n});\n\n// Use headless composable\nconst {\n state,\n isOpen,\n messages,\n isLoading,\n error,\n chatMode,\n wsConnected,\n agentTyping,\n currentAgent,\n isConnectingToAgent: isConnectingToAgentFromComposable,\n openChat,\n closeChat,\n sendMessage,\n toggleChat,\n setInputValue,\n clearError,\n manager,\n} = useChatWidget(props);\n\n// Refs\nconst messagesEndRef = ref<HTMLDivElement | null>(null);\nconst messagesContainer = ref<HTMLDivElement | null>(null);\n\n// Computed config (for reactivity)\nconst config = computed(() => props);\n\n// Computed state for initialization and connection (matching React component)\nconst isInitializing = computed(() => {\n return state.value.isLoading && state.value.messages.length === 0 && !state.value.sessionId;\n});\n\nconst isStartingNewChat = computed(() => {\n // This would be tracked in manager if needed, for now return false\n return false;\n});\n\n// Use isConnectingToAgent from composable (already computed in manager)\nconst isConnectingToAgent = isConnectingToAgentFromComposable;\n\n// Auto-scroll to bottom when messages change\nwatch(\n () => messages.value.length,\n () => {\n nextTick(() => {\n messagesEndRef.value?.scrollIntoView({ behavior: 'smooth' });\n });\n }\n);\n\n// Handlers\nconst handleOpenChat = async () => {\n // Ensure immediate UI response\n if (!state.value.isOpen) {\n state.value.isOpen = true;\n state.value.showWelcomePopup = false;\n }\n await openChat();\n};\n\nconst handleCloseChat = () => {\n closeChat();\n};\n\nconst handleCloseWelcomePopup = () => {\n manager.closeWelcomePopup();\n};\n\nconst handleInput = (event: Event) => {\n const target = event.target as HTMLInputElement;\n setInputValue(target.value);\n};\n\nconst handleSubmit = async (event: Event) => {\n event.preventDefault();\n if (state.value.inputValue.trim()) {\n await sendMessage(state.value.inputValue);\n }\n};\n\nconst handleChipClick = async (chipText: string, payload?: string) => {\n const messageToSend = chipText || payload || '';\n await sendMessage(messageToSend);\n};\n\n// Utility functions\nconst formatTime = (date: Date): string => {\n return date.toLocaleTimeString([], {\n hour: '2-digit',\n minute: '2-digit',\n });\n};\n\n// Check if message is a handoff message\nconst isHandoffMessage = (text: string): boolean => {\n return text.includes('👤') || \n text.includes('being connected') || \n text.includes('live support agent') ||\n text.includes('transfer your conversation');\n};\n\n// Initialize welcome popup on mount (SSR-safe)\nonMounted(() => {\n if (config.value.showWelcomePopup && typeof window !== 'undefined') {\n manager.initializeWelcomePopup();\n }\n});\n</script>\n\n<style scoped>\n/* Styles are imported separately by users */\n/* This ensures SSR compatibility */\n</style>\n"],"names":["_openBlock","_createElementBlock","_mergeProps","$attrs","_unref","_createElementVNode","_toDisplayString","_Fragment","_renderList","_normalizeClass"],"mappings":"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"}
@@ -0,0 +1,2 @@
1
+ "use strict";Object.defineProperty(exports,Symbol.toStringTag,{value:"Module"});const e=require("vue"),t=require("../core/stateManager.cjs.js");exports.useChatWidget=function(a){const n=new t.WidgetStateManager(a),s=e.ref(n.getState()),o=e.ref(!1),r=e.ref(!1),u=e.ref({name:"Agent"}),g=e.ref(!1),c=n.subscribe(e=>{s.value={...e};const t=n.getAdditionalState();o.value=t.wsConnected,r.value=t.agentTyping,u.value=t.currentAgent,g.value=t.isConnectingToAgent}),i=e.computed(()=>s.value.isOpen),d=e.computed(()=>s.value.messages),l=e.computed(()=>s.value.isLoading),p=e.computed(()=>s.value.error),v=e.computed(()=>s.value.chatMode);return e.onUnmounted(()=>{c(),n.destroy()}),e.watch(()=>a,e=>{n.updateConfig(e)},{deep:!0}),{state:s,isOpen:i,messages:d,isLoading:l,error:p,chatMode:v,wsConnected:o,agentTyping:r,currentAgent:u,isConnectingToAgent:g,openChat:async()=>{await n.openChat()},closeChat:()=>{n.closeChat()},sendMessage:async e=>{await n.sendMessage(e)},toggleChat:async()=>{await n.toggleChat()},setInputValue:e=>{n.setInputValue(e)},clearError:()=>{n.clearError()},manager:n}};
2
+ //# sourceMappingURL=useChatWidget.cjs.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"useChatWidget.cjs.js","sources":["../../src/composables/useChatWidget.ts"],"sourcesContent":["/**\n * useChatWidget Composable\n * Headless mode for Vue 3 - use logic without UI\n */\n\nimport { ref, computed, onUnmounted, watch, readonly, type Ref } from 'vue';\nimport { WidgetStateManager } from '../core/stateManager';\nimport type { WidgetConfig, WidgetState, ChatMessage } from '../core/types';\n\nexport interface UseChatWidgetReturn {\n // State\n state: Readonly<Ref<WidgetState>>;\n isOpen: Readonly<Ref<boolean>>;\n messages: Readonly<Ref<ChatMessage[]>>;\n isLoading: Readonly<Ref<boolean>>;\n error: Readonly<Ref<string | null>>;\n chatMode: Readonly<Ref<'ai' | 'human'>>;\n\n // Additional state\n wsConnected: Readonly<Ref<boolean>>;\n agentTyping: Readonly<Ref<boolean>>;\n currentAgent: Readonly<Ref<{ name: string; id?: string }>>;\n isConnectingToAgent: Readonly<Ref<boolean>>;\n\n // Actions\n openChat: () => Promise<void>;\n closeChat: () => void;\n sendMessage: (text: string) => Promise<void>;\n toggleChat: () => Promise<void>;\n setInputValue: (value: string) => void;\n clearError: () => void;\n\n // Manager instance (for advanced usage)\n manager: WidgetStateManager;\n}\n\n/**\n * Headless chat widget composable\n * Use this for custom UI implementations\n */\nexport function useChatWidget(config: WidgetConfig): UseChatWidgetReturn {\n // Create state manager\n const manager = new WidgetStateManager(config);\n\n // Reactive state\n const state = ref<WidgetState>(manager.getState());\n const wsConnected = ref(false);\n const agentTyping = ref(false);\n const currentAgent = ref<{ name: string; id?: string }>({ name: 'Agent' });\n const isConnectingToAgent = ref(false);\n\n // Subscribe to state changes\n const unsubscribe = manager.subscribe((newState) => {\n state.value = { ...newState };\n \n // Update additional state\n const additional = manager.getAdditionalState();\n wsConnected.value = additional.wsConnected;\n agentTyping.value = additional.agentTyping;\n currentAgent.value = additional.currentAgent;\n isConnectingToAgent.value = additional.isConnectingToAgent;\n });\n\n // Computed properties\n const isOpen = computed(() => state.value.isOpen);\n const messages = computed(() => state.value.messages);\n const isLoading = computed(() => state.value.isLoading);\n const error = computed(() => state.value.error);\n const chatMode = computed(() => state.value.chatMode);\n\n // Actions\n const openChat = async () => {\n await manager.openChat();\n };\n\n const closeChat = () => {\n manager.closeChat();\n };\n\n const sendMessage = async (text: string) => {\n await manager.sendMessage(text);\n };\n\n const toggleChat = async () => {\n await manager.toggleChat();\n };\n\n const setInputValue = (value: string) => {\n manager.setInputValue(value);\n };\n\n const clearError = () => {\n manager.clearError();\n };\n\n // Cleanup on unmount\n onUnmounted(() => {\n unsubscribe();\n manager.destroy();\n });\n\n // Watch config changes\n watch(\n () => config,\n (newConfig) => {\n manager.updateConfig(newConfig);\n },\n { deep: true }\n );\n\n return {\n state: state as Readonly<Ref<WidgetState>>,\n isOpen: isOpen as Readonly<Ref<boolean>>,\n messages: messages as Readonly<Ref<ChatMessage[]>>,\n isLoading: isLoading as Readonly<Ref<boolean>>,\n error: error as Readonly<Ref<string | null>>,\n chatMode: chatMode as Readonly<Ref<'ai' | 'human'>>,\n wsConnected: wsConnected as Readonly<Ref<boolean>>,\n agentTyping: agentTyping as Readonly<Ref<boolean>>,\n currentAgent: currentAgent as Readonly<Ref<{ name: string; id?: string }>>,\n isConnectingToAgent: isConnectingToAgent as Readonly<Ref<boolean>>,\n openChat,\n closeChat,\n sendMessage,\n toggleChat,\n setInputValue,\n clearError,\n manager,\n };\n}\n"],"names":["config","manager","WidgetStateManager","state","ref","getState","wsConnected","agentTyping","currentAgent","name","isConnectingToAgent","unsubscribe","subscribe","newState","value","additional","getAdditionalState","isOpen","computed","messages","isLoading","error","chatMode","onUnmounted","destroy","watch","newConfig","updateConfig","deep","openChat","async","closeChat","sendMessage","text","toggleChat","setInputValue","clearError"],"mappings":"sKAwCO,SAAuBA,GAE5B,MAAMC,EAAU,IAAIC,EAAAA,mBAAmBF,GAGjCG,EAAQC,EAAAA,IAAiBH,EAAQI,YACjCC,EAAcF,EAAAA,KAAI,GAClBG,EAAcH,EAAAA,KAAI,GAClBI,EAAeJ,EAAAA,IAAmC,CAAEK,KAAM,UAC1DC,EAAsBN,EAAAA,KAAI,GAG1BO,EAAcV,EAAQW,UAAWC,IACrCV,EAAMW,MAAQ,IAAKD,GAGnB,MAAME,EAAad,EAAQe,qBAC3BV,EAAYQ,MAAQC,EAAWT,YAC/BC,EAAYO,MAAQC,EAAWR,YAC/BC,EAAaM,MAAQC,EAAWP,aAChCE,EAAoBI,MAAQC,EAAWL,sBAInCO,EAASC,EAAAA,SAAS,IAAMf,EAAMW,MAAMG,QACpCE,EAAWD,EAAAA,SAAS,IAAMf,EAAMW,MAAMK,UACtCC,EAAYF,EAAAA,SAAS,IAAMf,EAAMW,MAAMM,WACvCC,EAAQH,EAAAA,SAAS,IAAMf,EAAMW,MAAMO,OACnCC,EAAWJ,EAAAA,SAAS,IAAMf,EAAMW,MAAMQ,UA0C5C,OAdAC,EAAAA,YAAY,KACVZ,IACAV,EAAQuB,YAIVC,EAAAA,MACE,IAAMzB,EACL0B,IACCzB,EAAQ0B,aAAaD,IAEvB,CAAEE,MAAM,IAGH,CACLzB,QACAc,SACAE,WACAC,YACAC,QACAC,WACAhB,cACAC,cACAC,eACAE,sBACAmB,SAlDeC,gBACT7B,EAAQ4B,YAkDdE,UA/CgB,KAChB9B,EAAQ8B,aA+CRC,YA5CkBF,MAAOG,UACnBhC,EAAQ+B,YAAYC,IA4C1BC,WAzCiBJ,gBACX7B,EAAQiC,cAyCdC,cAtCqBrB,IACrBb,EAAQkC,cAAcrB,IAsCtBsB,WAnCiB,KACjBnC,EAAQmC,cAmCRnC,UAEJ"}
@@ -0,0 +1,75 @@
1
+ import { ref, computed, onUnmounted, watch } from "vue";
2
+ import { WidgetStateManager } from "../core/stateManager.esm.js";
3
+ function useChatWidget(config) {
4
+ const manager = new WidgetStateManager(config);
5
+ const state = ref(manager.getState());
6
+ const wsConnected = ref(false);
7
+ const agentTyping = ref(false);
8
+ const currentAgent = ref({ name: "Agent" });
9
+ const isConnectingToAgent = ref(false);
10
+ const unsubscribe = manager.subscribe((newState) => {
11
+ state.value = { ...newState };
12
+ const additional = manager.getAdditionalState();
13
+ wsConnected.value = additional.wsConnected;
14
+ agentTyping.value = additional.agentTyping;
15
+ currentAgent.value = additional.currentAgent;
16
+ isConnectingToAgent.value = additional.isConnectingToAgent;
17
+ });
18
+ const isOpen = computed(() => state.value.isOpen);
19
+ const messages = computed(() => state.value.messages);
20
+ const isLoading = computed(() => state.value.isLoading);
21
+ const error = computed(() => state.value.error);
22
+ const chatMode = computed(() => state.value.chatMode);
23
+ const openChat = async () => {
24
+ await manager.openChat();
25
+ };
26
+ const closeChat = () => {
27
+ manager.closeChat();
28
+ };
29
+ const sendMessage = async (text) => {
30
+ await manager.sendMessage(text);
31
+ };
32
+ const toggleChat = async () => {
33
+ await manager.toggleChat();
34
+ };
35
+ const setInputValue = (value) => {
36
+ manager.setInputValue(value);
37
+ };
38
+ const clearError = () => {
39
+ manager.clearError();
40
+ };
41
+ onUnmounted(() => {
42
+ unsubscribe();
43
+ manager.destroy();
44
+ });
45
+ watch(
46
+ () => config,
47
+ (newConfig) => {
48
+ manager.updateConfig(newConfig);
49
+ },
50
+ { deep: true }
51
+ );
52
+ return {
53
+ state,
54
+ isOpen,
55
+ messages,
56
+ isLoading,
57
+ error,
58
+ chatMode,
59
+ wsConnected,
60
+ agentTyping,
61
+ currentAgent,
62
+ isConnectingToAgent,
63
+ openChat,
64
+ closeChat,
65
+ sendMessage,
66
+ toggleChat,
67
+ setInputValue,
68
+ clearError,
69
+ manager
70
+ };
71
+ }
72
+ export {
73
+ useChatWidget
74
+ };
75
+ //# sourceMappingURL=useChatWidget.esm.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"useChatWidget.esm.js","sources":["../../src/composables/useChatWidget.ts"],"sourcesContent":["/**\n * useChatWidget Composable\n * Headless mode for Vue 3 - use logic without UI\n */\n\nimport { ref, computed, onUnmounted, watch, readonly, type Ref } from 'vue';\nimport { WidgetStateManager } from '../core/stateManager';\nimport type { WidgetConfig, WidgetState, ChatMessage } from '../core/types';\n\nexport interface UseChatWidgetReturn {\n // State\n state: Readonly<Ref<WidgetState>>;\n isOpen: Readonly<Ref<boolean>>;\n messages: Readonly<Ref<ChatMessage[]>>;\n isLoading: Readonly<Ref<boolean>>;\n error: Readonly<Ref<string | null>>;\n chatMode: Readonly<Ref<'ai' | 'human'>>;\n\n // Additional state\n wsConnected: Readonly<Ref<boolean>>;\n agentTyping: Readonly<Ref<boolean>>;\n currentAgent: Readonly<Ref<{ name: string; id?: string }>>;\n isConnectingToAgent: Readonly<Ref<boolean>>;\n\n // Actions\n openChat: () => Promise<void>;\n closeChat: () => void;\n sendMessage: (text: string) => Promise<void>;\n toggleChat: () => Promise<void>;\n setInputValue: (value: string) => void;\n clearError: () => void;\n\n // Manager instance (for advanced usage)\n manager: WidgetStateManager;\n}\n\n/**\n * Headless chat widget composable\n * Use this for custom UI implementations\n */\nexport function useChatWidget(config: WidgetConfig): UseChatWidgetReturn {\n // Create state manager\n const manager = new WidgetStateManager(config);\n\n // Reactive state\n const state = ref<WidgetState>(manager.getState());\n const wsConnected = ref(false);\n const agentTyping = ref(false);\n const currentAgent = ref<{ name: string; id?: string }>({ name: 'Agent' });\n const isConnectingToAgent = ref(false);\n\n // Subscribe to state changes\n const unsubscribe = manager.subscribe((newState) => {\n state.value = { ...newState };\n \n // Update additional state\n const additional = manager.getAdditionalState();\n wsConnected.value = additional.wsConnected;\n agentTyping.value = additional.agentTyping;\n currentAgent.value = additional.currentAgent;\n isConnectingToAgent.value = additional.isConnectingToAgent;\n });\n\n // Computed properties\n const isOpen = computed(() => state.value.isOpen);\n const messages = computed(() => state.value.messages);\n const isLoading = computed(() => state.value.isLoading);\n const error = computed(() => state.value.error);\n const chatMode = computed(() => state.value.chatMode);\n\n // Actions\n const openChat = async () => {\n await manager.openChat();\n };\n\n const closeChat = () => {\n manager.closeChat();\n };\n\n const sendMessage = async (text: string) => {\n await manager.sendMessage(text);\n };\n\n const toggleChat = async () => {\n await manager.toggleChat();\n };\n\n const setInputValue = (value: string) => {\n manager.setInputValue(value);\n };\n\n const clearError = () => {\n manager.clearError();\n };\n\n // Cleanup on unmount\n onUnmounted(() => {\n unsubscribe();\n manager.destroy();\n });\n\n // Watch config changes\n watch(\n () => config,\n (newConfig) => {\n manager.updateConfig(newConfig);\n },\n { deep: true }\n );\n\n return {\n state: state as Readonly<Ref<WidgetState>>,\n isOpen: isOpen as Readonly<Ref<boolean>>,\n messages: messages as Readonly<Ref<ChatMessage[]>>,\n isLoading: isLoading as Readonly<Ref<boolean>>,\n error: error as Readonly<Ref<string | null>>,\n chatMode: chatMode as Readonly<Ref<'ai' | 'human'>>,\n wsConnected: wsConnected as Readonly<Ref<boolean>>,\n agentTyping: agentTyping as Readonly<Ref<boolean>>,\n currentAgent: currentAgent as Readonly<Ref<{ name: string; id?: string }>>,\n isConnectingToAgent: isConnectingToAgent as Readonly<Ref<boolean>>,\n openChat,\n closeChat,\n sendMessage,\n toggleChat,\n setInputValue,\n clearError,\n manager,\n };\n}\n"],"names":[],"mappings":";;AAwCO,SAAS,cAAc,QAA2C;AAEvE,QAAM,UAAU,IAAI,mBAAmB,MAAM;AAG7C,QAAM,QAAQ,IAAiB,QAAQ,SAAA,CAAU;AACjD,QAAM,cAAc,IAAI,KAAK;AAC7B,QAAM,cAAc,IAAI,KAAK;AAC7B,QAAM,eAAe,IAAmC,EAAE,MAAM,SAAS;AACzE,QAAM,sBAAsB,IAAI,KAAK;AAGrC,QAAM,cAAc,QAAQ,UAAU,CAAC,aAAa;AAClD,UAAM,QAAQ,EAAE,GAAG,SAAA;AAGnB,UAAM,aAAa,QAAQ,mBAAA;AAC3B,gBAAY,QAAQ,WAAW;AAC/B,gBAAY,QAAQ,WAAW;AAC/B,iBAAa,QAAQ,WAAW;AAChC,wBAAoB,QAAQ,WAAW;AAAA,EACzC,CAAC;AAGD,QAAM,SAAS,SAAS,MAAM,MAAM,MAAM,MAAM;AAChD,QAAM,WAAW,SAAS,MAAM,MAAM,MAAM,QAAQ;AACpD,QAAM,YAAY,SAAS,MAAM,MAAM,MAAM,SAAS;AACtD,QAAM,QAAQ,SAAS,MAAM,MAAM,MAAM,KAAK;AAC9C,QAAM,WAAW,SAAS,MAAM,MAAM,MAAM,QAAQ;AAGpD,QAAM,WAAW,YAAY;AAC3B,UAAM,QAAQ,SAAA;AAAA,EAChB;AAEA,QAAM,YAAY,MAAM;AACtB,YAAQ,UAAA;AAAA,EACV;AAEA,QAAM,cAAc,OAAO,SAAiB;AAC1C,UAAM,QAAQ,YAAY,IAAI;AAAA,EAChC;AAEA,QAAM,aAAa,YAAY;AAC7B,UAAM,QAAQ,WAAA;AAAA,EAChB;AAEA,QAAM,gBAAgB,CAAC,UAAkB;AACvC,YAAQ,cAAc,KAAK;AAAA,EAC7B;AAEA,QAAM,aAAa,MAAM;AACvB,YAAQ,WAAA;AAAA,EACV;AAGA,cAAY,MAAM;AAChB,gBAAA;AACA,YAAQ,QAAA;AAAA,EACV,CAAC;AAGD;AAAA,IACE,MAAM;AAAA,IACN,CAAC,cAAc;AACb,cAAQ,aAAa,SAAS;AAAA,IAChC;AAAA,IACA,EAAE,MAAM,KAAA;AAAA,EAAK;AAGf,SAAO;AAAA,IACL;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,EAAA;AAEJ;"}