@blockspark/chat-widget 1.0.17 → 1.0.18

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 (41) hide show
  1. package/README.md +28 -28
  2. package/dist/{ChatWidget-DKfLes8T.js → ChatWidget-Bs0XV_7i.js} +31 -36
  3. package/dist/ChatWidget-Bs0XV_7i.js.map +1 -0
  4. package/dist/ChatWidget-PcqRrOmi.cjs +2 -0
  5. package/dist/ChatWidget-PcqRrOmi.cjs.map +1 -0
  6. package/dist/adapters/vue/useChatMode.d.ts +1 -1
  7. package/dist/adapters/vue/useChatMode.d.ts.map +1 -1
  8. package/dist/components/ChatWidget.d.ts +1 -5
  9. package/dist/components/ChatWidget.d.ts.map +1 -1
  10. package/dist/core/stateManager.d.ts.map +1 -1
  11. package/dist/core/types.d.ts +0 -2
  12. package/dist/core/types.d.ts.map +1 -1
  13. package/dist/entry/vite.d.ts +1 -1
  14. package/dist/hooks/useChatMode.d.ts +1 -1
  15. package/dist/hooks/useChatMode.d.ts.map +1 -1
  16. package/dist/index.cjs.js +1 -1
  17. package/dist/index.cjs.js.map +1 -1
  18. package/dist/index.d.ts +5 -5
  19. package/dist/index.d.ts.map +1 -1
  20. package/dist/index.esm.js +39 -22
  21. package/dist/index.esm.js.map +1 -1
  22. package/dist/nuxt.cjs.js +1 -1
  23. package/dist/nuxt.esm.js +2 -2
  24. package/dist/sanitize-C8MB41vY.cjs +4 -0
  25. package/dist/sanitize-C8MB41vY.cjs.map +1 -0
  26. package/dist/{sanitize-O18C3eqP.js → sanitize-Cm1kskSD.js} +154 -1260
  27. package/dist/sanitize-Cm1kskSD.js.map +1 -0
  28. package/dist/services/dialogflowBackendService.d.ts +36 -0
  29. package/dist/services/dialogflowBackendService.d.ts.map +1 -0
  30. package/dist/styles.css +1 -1
  31. package/dist/types.d.ts +1 -1
  32. package/dist/types.d.ts.map +1 -1
  33. package/dist/vue.cjs.js +1 -1
  34. package/dist/vue.esm.js +2 -2
  35. package/package.json +2 -2
  36. package/dist/ChatWidget-DKfLes8T.js.map +0 -1
  37. package/dist/ChatWidget-lvHzA07s.cjs +0 -2
  38. package/dist/ChatWidget-lvHzA07s.cjs.map +0 -1
  39. package/dist/sanitize-D904jROs.cjs +0 -4
  40. package/dist/sanitize-D904jROs.cjs.map +0 -1
  41. package/dist/sanitize-O18C3eqP.js.map +0 -1
package/README.md CHANGED
@@ -1,4 +1,4 @@
1
- # BlockSpark Chat Widget
1
+ # chartsconnect Chat Widget
2
2
 
3
3
  A universal JavaScript chat widget library that connects directly with Dialogflow CX - no backend API required!
4
4
 
@@ -10,19 +10,19 @@ A universal JavaScript chat widget library that connects directly with Dialogflo
10
10
 
11
11
  ```bash
12
12
  # In your website project directory
13
- npm install /path/to/blockspark-chat-widget
13
+ npm install /path/to/chartsconnect-chat-widget
14
14
  # or
15
- npm install ../blockspark-chat-widget
15
+ npm install ../chartsconnect-chat-widget
16
16
  ```
17
17
 
18
18
  ### Option 2: Use npm link (For Development)
19
19
 
20
20
  ```bash
21
- # In the blockspark-chat-widget directory
21
+ # In the chartsconnect-chat-widget directory
22
22
  npm link
23
23
 
24
24
  # In your website project directory
25
- npm link @blockspark/chat-widget
25
+ npm link @chartsconnect/chat-widget
26
26
  ```
27
27
 
28
28
  ### Option 3: Publish to npm (For Production)
@@ -37,7 +37,7 @@ npm publish
37
37
 
38
38
  Then install in your project:
39
39
  ```bash
40
- npm install @blockspark/chat-widget
40
+ npm install @chartsconnect/chat-widget
41
41
  ```
42
42
 
43
43
  ## Usage
@@ -50,22 +50,22 @@ npm install @blockspark/chat-widget
50
50
  df-project-id="your-project-id"
51
51
  df-agent-id="your-agent-id"
52
52
  :service-account-key="serviceAccountKey"
53
- backendBaseUrl="https://chartconnect.blockspark.in"
54
- backendWsUrl="wss://chartconnect.blockspark.in"
53
+ backendBaseUrl="https://chartconnect.chartsconnect.in"
54
+ backendWsUrl="wss://chartconnect.chartsconnect.in"
55
55
  />
56
56
  </template>
57
57
 
58
58
  <script setup>
59
- import ChatWidget from '@blockspark/chat-widget/vue';
59
+ import ChatWidget from '@chartsconnect/chat-widget/vue';
60
60
  // ⚠️ REQUIRED: Import CSS separately
61
- import '@blockspark/chat-widget/styles';
61
+ import '@chartsconnect/chat-widget/styles';
62
62
  import serviceAccountKey from './credentials/dialogflow.json';
63
63
  </script>
64
64
  ```
65
65
 
66
66
  **CSS Import Options:**
67
- - `import '@blockspark/chat-widget/styles'` (recommended)
68
- - `import '@blockspark/chat-widget/dist/styles.css'` (alternative)
67
+ - `import '@chartsconnect/chat-widget/styles'` (recommended)
68
+ - `import '@chartsconnect/chat-widget/dist/styles.css'` (alternative)
69
69
 
70
70
  ### Nuxt 3 / Vue.js 3 (Important: Use ClientOnly!)
71
71
 
@@ -81,8 +81,8 @@ import serviceAccountKey from './credentials/dialogflow.json';
81
81
  </template>
82
82
 
83
83
  <script setup>
84
- import ChatWidget from '@blockspark/chat-widget/nuxt';
85
- import '@blockspark/chat-widget/styles';
84
+ import ChatWidget from '@chartsconnect/chat-widget/nuxt';
85
+ import '@chartsconnect/chat-widget/styles';
86
86
  import serviceAccountKey from './credentials/dialogflow.json';
87
87
  </script>
88
88
  ```
@@ -90,11 +90,11 @@ import serviceAccountKey from './credentials/dialogflow.json';
90
90
  **In `nuxt.config.ts`:**
91
91
  ```typescript
92
92
  export default defineNuxtConfig({
93
- css: ['@blockspark/chat-widget/dist/styles.css'],
93
+ css: ['@chartsconnect/chat-widget/dist/styles.css'],
94
94
 
95
95
  vite: {
96
96
  optimizeDeps: {
97
- exclude: ['@blockspark/chat-widget'],
97
+ exclude: ['@chartsconnect/chat-widget'],
98
98
  },
99
99
  },
100
100
  });
@@ -103,14 +103,14 @@ export default defineNuxtConfig({
103
103
  **⚠️ CRITICAL for Nuxt:** The component MUST be wrapped in `<ClientOnly>` because it uses browser-only APIs (`localStorage`, `window`, `WebSocket`) that don't exist during SSR.
104
104
 
105
105
  **CSS Import Options:**
106
- - `import '@blockspark/chat-widget/styles'` (recommended - shorter path)
107
- - `import '@blockspark/chat-widget/dist/styles.css'` (alternative)
106
+ - `import '@chartsconnect/chat-widget/styles'` (recommended - shorter path)
107
+ - `import '@chartsconnect/chat-widget/dist/styles.css'` (alternative)
108
108
 
109
109
  ### React/Next.js
110
110
 
111
111
  ```tsx
112
- import ChatWidget from '@blockspark/chat-widget';
113
- import '@blockspark/chat-widget/dist/styles.css';
112
+ import ChatWidget from '@chartsconnect/chat-widget';
113
+ import '@chartsconnect/chat-widget/dist/styles.css';
114
114
  import serviceAccountKey from './service-account-key.json';
115
115
 
116
116
  function App() {
@@ -136,16 +136,16 @@ function App() {
136
136
  | `serviceAccountKey` | `object` | Yes* | - | Google Cloud service account key JSON object |
137
137
  | `accessToken` | `string` | Yes* | - | Access token (alternative to serviceAccountKey) |
138
138
  | `languageCode` | `string` | No | `"en"` | Language code for Dialogflow |
139
- | `title` | `string` | No | `"💬 BlockSpark AI Assistant"` | Chat widget title |
139
+ | `title` | `string` | No | `"💬 chartsconnect AI Assistant"` | Chat widget title |
140
140
  | `subtitle` | `string` | No | `"We're here to help"` | Chat widget subtitle |
141
- | `welcomeTitle` | `string` | No | `"👋 Welcome to Blockspark"` | Welcome popup title |
142
- | `welcomeMessage` | `string` | No | `"My name is BlockSpark..."` | Welcome popup message |
141
+ | `welcomeTitle` | `string` | No | `"👋 Welcome to chartsconnect"` | Welcome popup title |
142
+ | `welcomeMessage` | `string` | No | `"My name is chartsconnect..."` | Welcome popup message |
143
143
  | `welcomeCta` | `string` | No | `"💬 Click here to start chatting!"` | Welcome popup CTA text |
144
144
  | `showWelcomePopup` | `boolean` | No | `true` | Whether to show welcome popup |
145
145
  | `welcomePopupDelay` | `number` | No | `1500` | Delay before showing welcome popup (ms) |
146
- | `fallbackWelcomeMessage` | `string` | No | `"Hello! I'm BlockSpark..."` | Fallback message if API fails |
146
+ | `fallbackWelcomeMessage` | `string` | No | `"Hello! I'm chartsconnect..."` | Fallback message if API fails |
147
147
  | `inputPlaceholder` | `string` | No | `"Type your message..."` | Input field placeholder |
148
- | `emptyStateMessage` | `string` | No | `"Hi! I'm BlockSpark..."` | Empty state message |
148
+ | `emptyStateMessage` | `string` | No | `"Hi! I'm chartsconnect..."` | Empty state message |
149
149
  | `debug` | `boolean` | No | `false` | Enable debug logging |
150
150
  | `backendBaseUrl` | `string` | No | `"http://localhost:8012"` | Backend REST API base URL for Human Support Mode |
151
151
  | `backendWsUrl` | `string` | No | `"ws://localhost:8012"` | Backend WebSocket URL for Human Support Mode |
@@ -223,7 +223,7 @@ npm run dev
223
223
  ### Vue.js/Nuxt Issues
224
224
 
225
225
  **Widget not displaying?**
226
- - ✅ Make sure you imported the CSS: `import '@blockspark/chat-widget/styles'`
226
+ - ✅ Make sure you imported the CSS: `import '@chartsconnect/chat-widget/styles'`
227
227
  - ✅ For Nuxt: Wrap in `<ClientOnly>` component
228
228
  - ✅ For Nuxt: Add CSS to `nuxt.config.ts` and exclude from optimization
229
229
 
@@ -237,7 +237,7 @@ npm run dev
237
237
  ```ts
238
238
  vite: {
239
239
  optimizeDeps: {
240
- exclude: ['@blockspark/chat-widget'],
240
+ exclude: ['@chartsconnect/chat-widget'],
241
241
  },
242
242
  }
243
243
  ```
@@ -248,7 +248,7 @@ npm run dev
248
248
  - ✅ Or add to `vite.config.ts`:
249
249
  ```ts
250
250
  optimizeDeps: {
251
- exclude: ['@blockspark/chat-widget'],
251
+ exclude: ['@chartsconnect/chat-widget'],
252
252
  }
253
253
  ```
254
254
 
@@ -1,5 +1,5 @@
1
1
  import { ref, computed, onUnmounted, watch, defineComponent, nextTick, onMounted, openBlock, createElementBlock, mergeProps, unref, createElementVNode, toDisplayString, withModifiers, createCommentVNode, createTextVNode, Fragment, renderList, normalizeClass } from "vue";
2
- import { c as createChatService, a as createDialogflowSession, C as ChatResolvedError, s as sendDialogflowMessage, b as safeLinkifyText } from "./sanitize-O18C3eqP.js";
2
+ import { c as createChatService, a as createDialogflowSession, C as ChatResolvedError, s as sendDialogflowMessage, b as safeLinkifyText } from "./sanitize-Cm1kskSD.js";
3
3
  class WidgetStateManager {
4
4
  constructor(config) {
5
5
  this.listeners = /* @__PURE__ */ new Set();
@@ -38,11 +38,11 @@ class WidgetStateManager {
38
38
  debug: this.config.debug || false
39
39
  });
40
40
  if (typeof window !== "undefined" && window.localStorage) {
41
- const savedMode = localStorage.getItem("blockspark_chat_mode");
41
+ const savedMode = localStorage.getItem("chartsconnectect_chat_mode");
42
42
  this.chatMode = savedMode === "HUMAN" ? "human" : "ai";
43
43
  this.state.chatMode = this.chatMode;
44
- this.chatId = localStorage.getItem("blockspark_chat_id");
45
- this.supportSessionId = localStorage.getItem("blockspark_session_id");
44
+ this.chatId = localStorage.getItem("chartsconnect_chat_id");
45
+ this.supportSessionId = localStorage.getItem("chartsconnect_session_id");
46
46
  }
47
47
  }
48
48
  /**
@@ -88,9 +88,8 @@ class WidgetStateManager {
88
88
  dfProjectId: this.config.dfProjectId,
89
89
  dfLocation: this.config.dfLocation || "us-central1",
90
90
  dfAgentId: this.config.dfAgentId,
91
- serviceAccountKey: this.config.serviceAccountKey,
92
- accessToken: this.config.accessToken,
93
- languageCode: this.config.languageCode || "en"
91
+ languageCode: this.config.languageCode || "en",
92
+ backendBaseUrl: this.config.backendBaseUrl || "http://localhost:8012"
94
93
  };
95
94
  const session = await createDialogflowSession(dialogflowConfig);
96
95
  this.setState({
@@ -240,9 +239,8 @@ class WidgetStateManager {
240
239
  dfProjectId: this.config.dfProjectId,
241
240
  dfLocation: this.config.dfLocation || "us-central1",
242
241
  dfAgentId: this.config.dfAgentId,
243
- serviceAccountKey: this.config.serviceAccountKey,
244
- accessToken: this.config.accessToken,
245
- languageCode: this.config.languageCode || "en"
242
+ languageCode: this.config.languageCode || "en",
243
+ backendBaseUrl: this.config.backendBaseUrl || "http://localhost:8012"
246
244
  };
247
245
  if (!this.state.sessionId) {
248
246
  const session = await createDialogflowSession(dialogflowConfig);
@@ -337,8 +335,8 @@ class WidgetStateManager {
337
335
  this.chatId = null;
338
336
  this.supportSessionId = null;
339
337
  if (typeof window !== "undefined" && window.localStorage) {
340
- localStorage.removeItem("blockspark_chat_id");
341
- localStorage.removeItem("blockspark_session_id");
338
+ localStorage.removeItem("chartsconnect_chat_id");
339
+ localStorage.removeItem("chartsconnect_session_id");
342
340
  }
343
341
  try {
344
342
  const newSession = await this.chatService.startSupportChat(
@@ -350,8 +348,8 @@ class WidgetStateManager {
350
348
  this.chatId = newSession.chat_id;
351
349
  this.supportSessionId = newSession.session_id;
352
350
  if (typeof window !== "undefined" && window.localStorage) {
353
- localStorage.setItem("blockspark_chat_id", this.chatId);
354
- localStorage.setItem("blockspark_session_id", this.supportSessionId);
351
+ localStorage.setItem("chartsconnect_chat_id", this.chatId);
352
+ localStorage.setItem("chartsconnect_session_id", this.supportSessionId);
355
353
  }
356
354
  if (this.chatId && this.supportSessionId) {
357
355
  await this.chatService.sendMessageToAgent(
@@ -381,7 +379,7 @@ class WidgetStateManager {
381
379
  this.chatMode = "human";
382
380
  this.setState({ chatMode: "human" });
383
381
  if (typeof window !== "undefined" && window.localStorage) {
384
- localStorage.setItem("blockspark_chat_mode", "HUMAN");
382
+ localStorage.setItem("chartsconnect_chat_mode", "HUMAN");
385
383
  }
386
384
  }
387
385
  /**
@@ -391,7 +389,7 @@ class WidgetStateManager {
391
389
  this.chatMode = "ai";
392
390
  this.setState({ chatMode: "ai" });
393
391
  if (typeof window !== "undefined" && window.localStorage) {
394
- localStorage.setItem("blockspark_chat_mode", "BOT");
392
+ localStorage.setItem("chartsconnect_chat_mode", "BOT");
395
393
  }
396
394
  }
397
395
  /**
@@ -524,8 +522,8 @@ class WidgetStateManager {
524
522
  this.chatId = currentChatId;
525
523
  this.supportSessionId = currentSupportSessionId;
526
524
  if (typeof window !== "undefined" && window.localStorage) {
527
- localStorage.setItem("blockspark_chat_id", this.chatId);
528
- localStorage.setItem("blockspark_session_id", this.supportSessionId);
525
+ localStorage.setItem("chartsconnect_chat_id", this.chatId);
526
+ localStorage.setItem("chartsconnect_session_id", this.supportSessionId);
529
527
  }
530
528
  if (this.config.debug) {
531
529
  console.log("✅ Chat initialized:", { chatId: currentChatId, sessionId: currentSupportSessionId });
@@ -552,8 +550,8 @@ class WidgetStateManager {
552
550
  this.chatId = null;
553
551
  this.supportSessionId = null;
554
552
  if (typeof window !== "undefined" && window.localStorage) {
555
- localStorage.removeItem("blockspark_chat_id");
556
- localStorage.removeItem("blockspark_session_id");
553
+ localStorage.removeItem("chartsconnect_chat_id");
554
+ localStorage.removeItem("chartsconnect_session_id");
557
555
  }
558
556
  const newSession = await this.chatService.startSupportChat(
559
557
  dialogflowSessionId || null,
@@ -567,8 +565,8 @@ class WidgetStateManager {
567
565
  this.chatId = newSession.chat_id;
568
566
  this.supportSessionId = newSession.session_id;
569
567
  if (typeof window !== "undefined" && window.localStorage) {
570
- localStorage.setItem("blockspark_chat_id", this.chatId);
571
- localStorage.setItem("blockspark_session_id", this.supportSessionId);
568
+ localStorage.setItem("chartsconnect_chat_id", this.chatId);
569
+ localStorage.setItem("chartsconnect_session_id", this.supportSessionId);
572
570
  }
573
571
  await this.chatService.requestHandoff(
574
572
  this.chatId,
@@ -762,8 +760,8 @@ class WidgetStateManager {
762
760
  this.chatId = null;
763
761
  this.supportSessionId = null;
764
762
  if (typeof window !== "undefined" && window.localStorage) {
765
- localStorage.removeItem("blockspark_chat_id");
766
- localStorage.removeItem("blockspark_session_id");
763
+ localStorage.removeItem("chartsconnect_chat_id");
764
+ localStorage.removeItem("chartsconnect_session_id");
767
765
  }
768
766
  const thankYouMessage = {
769
767
  id: `resolved-${Date.now()}`,
@@ -794,9 +792,8 @@ class WidgetStateManager {
794
792
  dfProjectId: this.config.dfProjectId,
795
793
  dfLocation: this.config.dfLocation || "us-central1",
796
794
  dfAgentId: this.config.dfAgentId,
797
- serviceAccountKey: this.config.serviceAccountKey,
798
- accessToken: this.config.accessToken,
799
- languageCode: this.config.languageCode || "en"
795
+ languageCode: this.config.languageCode || "en",
796
+ backendBaseUrl: this.config.backendBaseUrl || "http://localhost:8012"
800
797
  };
801
798
  const session = await createDialogflowSession(dialogflowConfig);
802
799
  this.setState({
@@ -1055,21 +1052,19 @@ const _sfc_main = /* @__PURE__ */ defineComponent({
1055
1052
  dfProjectId: {},
1056
1053
  dfLocation: {},
1057
1054
  dfAgentId: {},
1058
- serviceAccountKey: {},
1059
- accessToken: {},
1060
1055
  languageCode: {},
1061
1056
  backendBaseUrl: {},
1062
1057
  backendWsUrl: {},
1063
- title: { default: "💬 BlockSpark AI Assistant" },
1058
+ title: { default: "💬 Charts Connect AI Assistant" },
1064
1059
  subtitle: { default: "We're here to help" },
1065
- welcomeTitle: { default: "👋 Welcome to BlockSpark" },
1066
- welcomeMessage: { default: "My name is BlockSpark AI Assistant and I'll guide you." },
1060
+ welcomeTitle: { default: "👋 Welcome to Charts Connect" },
1061
+ welcomeMessage: { default: "My name is Charts Connect AI Assistant and I'll guide you." },
1067
1062
  welcomeCta: { default: "💬 Click here to start chatting!" },
1068
1063
  showWelcomePopup: { type: Boolean, default: true },
1069
1064
  welcomePopupDelay: { default: 1500 },
1070
- fallbackWelcomeMessage: { default: "Hello! I'm BlockSpark AI Assistant. How can I help you today?" },
1065
+ fallbackWelcomeMessage: { default: "Hello! I'm Charts Connect AI Assistant. How can I help you today?" },
1071
1066
  inputPlaceholder: { default: "Type your message..." },
1072
- emptyStateMessage: { default: "Hi! I'm BlockSpark AI Assistant. How can I help you today?" },
1067
+ emptyStateMessage: { default: "Hi! I'm Charts Connect AI Assistant. How can I help you today?" },
1073
1068
  debug: { type: Boolean, default: false }
1074
1069
  },
1075
1070
  setup(__props) {
@@ -1352,10 +1347,10 @@ const _export_sfc = (sfc, props) => {
1352
1347
  }
1353
1348
  return target;
1354
1349
  };
1355
- const ChatWidgetComponent = /* @__PURE__ */ _export_sfc(_sfc_main, [["__scopeId", "data-v-0d32fcf4"]]);
1350
+ const ChatWidgetComponent = /* @__PURE__ */ _export_sfc(_sfc_main, [["__scopeId", "data-v-11671761"]]);
1356
1351
  export {
1357
1352
  ChatWidgetComponent as C,
1358
1353
  WidgetStateManager as W,
1359
1354
  useChatWidget as u
1360
1355
  };
1361
- //# sourceMappingURL=ChatWidget-DKfLes8T.js.map
1356
+ //# sourceMappingURL=ChatWidget-Bs0XV_7i.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"ChatWidget-Bs0XV_7i.js","sources":["../src/core/stateManager.ts","../src/composables/useChatWidget.ts","../src/components/ChatWidget.vue"],"sourcesContent":["/**\n * State Manager - Framework Agnostic\n * Manages widget state independently of framework\n */\n\nimport type { WidgetState, WidgetConfig, ChatMessage } from './types';\nimport {\n createDialogflowSession,\n sendDialogflowMessage,\n type DialogflowBackendConfig,\n} from '../services/dialogflowBackendService';\nimport { \n createChatService, \n ChatResolvedError,\n type WebSocketMessage\n} from '../services/chatService';\n\nexport class WidgetStateManager {\n private state: WidgetState;\n private config: WidgetConfig;\n private listeners: Set<(state: WidgetState) => void> = new Set();\n private chatMode: 'ai' | 'human' = 'ai';\n private chatId: string | null = null;\n private supportSessionId: string | null = null;\n private chatService: ReturnType<typeof createChatService> | null = null;\n \n // User info collection for handoff\n private collectingUserInfo: boolean = false;\n private userInfoStep: 'name' | 'email' | 'mobile' | null = null;\n private collectedUserName: string = '';\n private collectedUserEmail: string = '';\n private collectedUserMobile: string = '';\n \n // Additional state for human support\n private wsConnected: boolean = false;\n private agentTyping: boolean = false;\n private currentAgent: { name: string; id?: string } = { name: 'Agent' };\n private isConnectingToAgent: boolean = false;\n private agentAccepted: boolean = false;\n private chatResolved: boolean = false;\n private historyLoaded: string | null = null;\n \n // Typing timeout refs (stored as class properties since we can't use refs)\n private typingTimeout: NodeJS.Timeout | null = null;\n private agentTypingTimeout: NodeJS.Timeout | null = null;\n\n constructor(config: WidgetConfig) {\n this.config = config;\n this.state = {\n isOpen: false,\n showWelcomePopup: false,\n messages: [],\n inputValue: '',\n isLoading: false,\n error: null,\n sessionId: null,\n chatMode: 'ai',\n };\n \n // Initialize ChatService\n this.chatService = createChatService({\n baseUrl: this.config.backendBaseUrl || 'http://localhost:8012',\n wsUrl: this.config.backendWsUrl || 'ws://localhost:8012',\n debug: this.config.debug || false,\n });\n \n // Load chat mode and chat IDs from localStorage if available\n if (typeof window !== 'undefined' && window.localStorage) {\n const savedMode = localStorage.getItem('chartsconnectect_chat_mode');\n this.chatMode = savedMode === 'HUMAN' ? 'human' : 'ai';\n this.state.chatMode = this.chatMode;\n \n this.chatId = localStorage.getItem('chartsconnect_chat_id');\n this.supportSessionId = localStorage.getItem('chartsconnect_session_id');\n }\n }\n\n /**\n * Subscribe to state changes\n */\n subscribe(listener: (state: WidgetState) => void): () => void {\n this.listeners.add(listener);\n return () => {\n this.listeners.delete(listener);\n };\n }\n\n /**\n * Get current state\n */\n getState(): WidgetState {\n return { ...this.state };\n }\n\n /**\n * Update state and notify listeners\n */\n private setState(updates: Partial<WidgetState>): void {\n this.state = { ...this.state, ...updates };\n this.listeners.forEach(listener => listener(this.getState()));\n }\n\n /**\n * Update configuration\n */\n updateConfig(config: Partial<WidgetConfig>): void {\n this.config = { ...this.config, ...config };\n }\n\n /**\n * Open chat\n */\n async openChat(): Promise<void> {\n this.setState({ isOpen: true });\n if (this.state.showWelcomePopup) {\n this.setState({ showWelcomePopup: false });\n }\n \n // Initialize Dialogflow session when chat opens (if in AI mode and no session exists)\n if (this.state.chatMode === 'ai' && !this.state.sessionId && this.config.dfProjectId && this.config.dfAgentId) {\n try {\n this.setState({ isLoading: true });\n const dialogflowConfig: DialogflowBackendConfig = {\n dfProjectId: this.config.dfProjectId,\n dfLocation: this.config.dfLocation || 'us-central1',\n dfAgentId: this.config.dfAgentId,\n languageCode: this.config.languageCode || 'en',\n backendBaseUrl: this.config.backendBaseUrl || 'http://localhost:8012',\n };\n \n const session = await createDialogflowSession(dialogflowConfig);\n this.setState({ \n sessionId: session.session_id,\n isLoading: false,\n });\n \n // Add welcome message from Dialogflow if available\n if (session.message) {\n const welcomeMessage: ChatMessage = {\n id: `welcome-${Date.now()}`,\n text: session.message,\n sender: 'bot',\n timestamp: new Date(),\n richContent: session.richContent,\n };\n this.setState({\n messages: [welcomeMessage],\n });\n }\n } catch (error: any) {\n console.error('Error initializing Dialogflow session:', error);\n this.setState({ \n isLoading: false,\n error: error.message || 'Failed to initialize chat',\n });\n \n // Show fallback welcome message\n const fallbackMessage: ChatMessage = {\n id: `fallback-${Date.now()}`,\n text: this.config.fallbackWelcomeMessage || 'Hello! How can I help you today?',\n sender: 'bot',\n timestamp: new Date(),\n };\n this.setState({\n messages: [fallbackMessage],\n });\n }\n }\n }\n\n /**\n * Close chat\n */\n closeChat(): void {\n this.setState({ isOpen: false });\n }\n\n /**\n * Close welcome popup\n */\n closeWelcomePopup(): void {\n this.setState({ showWelcomePopup: false });\n }\n\n /**\n * Toggle chat\n */\n toggleChat(): void {\n const willBeOpen = !this.state.isOpen;\n this.setState({ isOpen: willBeOpen });\n if (willBeOpen && this.state.showWelcomePopup) {\n this.setState({ showWelcomePopup: false });\n }\n }\n\n /**\n * Set input value\n */\n setInputValue(value: string): void {\n this.setState({ inputValue: value });\n }\n\n /**\n * Clear error\n */\n clearError(): void {\n this.setState({ error: null });\n }\n\n /**\n * Send message\n */\n async sendMessage(text: string, skipUserMessage: boolean = false): Promise<void> {\n if (!text.trim() || this.state.isLoading) {\n return;\n }\n\n // Handle user info collection for handoff\n if (this.collectingUserInfo) {\n // Add user message first so it appears in chat\n const userMessage: ChatMessage = {\n id: `user-${Date.now()}`,\n text: text.trim(),\n sender: 'user',\n timestamp: new Date(),\n };\n this.setState({\n messages: [...this.state.messages, userMessage],\n inputValue: '',\n isLoading: false,\n error: null,\n });\n \n // Then handle the info collection\n await this.handleUserInfoCollection(text);\n return;\n }\n\n // Add user message unless skipped (e.g., when chip button already added it)\n if (!skipUserMessage) {\n const userMessage: ChatMessage = {\n id: `user-${Date.now()}`,\n text: text.trim(),\n sender: 'user',\n timestamp: new Date(),\n };\n\n this.setState({\n messages: [...this.state.messages, userMessage],\n inputValue: '',\n isLoading: true,\n error: null,\n });\n } else {\n this.setState({\n inputValue: '',\n isLoading: true,\n error: null,\n });\n }\n\n try {\n if (this.state.chatMode === 'human') {\n // Human support mode\n await this.sendHumanMessage(text);\n } else {\n // AI mode (Dialogflow)\n await this.sendAIMessage(text);\n }\n } catch (error: any) {\n console.error('Error sending message:', error);\n \n // chat_resolved is a normal terminal condition, not an error\n if (error instanceof ChatResolvedError || error?.name === 'ChatResolvedError' || error?.message === 'chat_resolved') {\n this.enterResolvedState(this.chatId);\n return;\n }\n \n // Add error message to chat\n const errorMessage: ChatMessage = {\n id: `error-${Date.now()}`,\n text: this.config.debug \n ? `Error: ${error.message || 'Failed to send message'}`\n : error.message?.includes('CORS') || error.message?.includes('Failed to fetch')\n ? 'Unable to connect to Dialogflow. Please check your configuration and network.'\n : 'Sorry, I\\'m having trouble processing your message. Please try again.',\n sender: 'bot',\n timestamp: new Date(),\n };\n \n this.setState({\n messages: [...this.state.messages, errorMessage],\n error: error.message || 'Failed to send message',\n isLoading: false,\n });\n }\n }\n\n /**\n * Send message to Dialogflow\n */\n private async sendAIMessage(text: string): Promise<void> {\n if (!this.config.dfProjectId || !this.config.dfAgentId) {\n throw new Error('Dialogflow configuration is missing');\n }\n\n const dialogflowConfig: DialogflowBackendConfig = {\n dfProjectId: this.config.dfProjectId!,\n dfLocation: this.config.dfLocation || 'us-central1',\n dfAgentId: this.config.dfAgentId!,\n languageCode: this.config.languageCode || 'en',\n backendBaseUrl: this.config.backendBaseUrl || 'http://localhost:8012',\n };\n\n // Create session if needed\n if (!this.state.sessionId) {\n const session = await createDialogflowSession(dialogflowConfig);\n this.setState({ sessionId: session.session_id });\n }\n\n // Send message (correct parameter order: message, sessionId, config)\n if (this.config.debug) {\n console.log('Sending message to Dialogflow:', {\n message: text,\n sessionId: this.state.sessionId,\n hasConfig: !!dialogflowConfig,\n });\n }\n \n const response = await sendDialogflowMessage(\n text,\n this.state.sessionId!,\n dialogflowConfig\n );\n\n if (this.config.debug) {\n console.log('Dialogflow response:', {\n response: response.response,\n hasRichContent: !!response.richContent,\n richContent: response.richContent,\n });\n }\n\n // Check for handoff\n if (response.handoff === true) {\n // Add bot response first\n const botMessage: ChatMessage = {\n id: `bot-${Date.now()}`,\n text: response.response || this.config.fallbackWelcomeMessage || 'No response',\n sender: 'bot',\n timestamp: new Date(),\n richContent: response.richContent,\n };\n this.setState({\n messages: [...this.state.messages, botMessage],\n isLoading: false,\n });\n \n // Start collecting user info for handoff\n this.startUserInfoCollection();\n return;\n }\n \n const botMessage: ChatMessage = {\n id: `bot-${Date.now()}`,\n text: response.response || this.config.fallbackWelcomeMessage || 'No response',\n sender: 'bot',\n timestamp: new Date(),\n richContent: response.richContent,\n };\n\n this.setState({\n messages: [...this.state.messages, botMessage],\n isLoading: false,\n });\n }\n\n /**\n * Send message to human support\n */\n private async sendHumanMessage(text: string): Promise<void> {\n if (!this.chatId || !this.supportSessionId) {\n const errorMessage: ChatMessage = {\n id: `error-${Date.now()}`,\n text: 'Chat session not initialized. Please try again.',\n sender: 'bot',\n timestamp: new Date(),\n };\n this.setState({\n messages: [...this.state.messages, errorMessage],\n isLoading: false,\n });\n return;\n }\n\n if (!this.chatService) {\n throw new Error('Chat service not initialized');\n }\n\n // Send typing_stop before sending message\n this.chatService.sendTypingIndicator('typing_stop');\n if (this.typingTimeout) {\n clearTimeout(this.typingTimeout);\n this.typingTimeout = null;\n }\n\n try {\n // Try WebSocket first, fallback to REST API\n const sentViaWs = this.chatService.sendMessageViaWebSocket(text.trim());\n \n if (!sentViaWs) {\n // Fallback to REST API\n await this.chatService.sendMessageToAgent(this.chatId, this.supportSessionId, text.trim());\n }\n \n this.setState({ isLoading: false });\n } catch (error: any) {\n // chat_resolved is a normal terminal condition, not an error\n if (error instanceof ChatResolvedError || error?.name === 'ChatResolvedError' || error?.message === 'chat_resolved') {\n this.enterResolvedState(this.chatId);\n return;\n }\n\n // Handle 401/404 - clear chat_id and reinitialize\n if (error.message?.includes('Chat not found') ||\n error.message?.includes('unauthorized') ||\n error.message?.includes('401') ||\n error.message?.includes('404')) {\n if (this.config.debug) {\n console.log('⚠️ Chat expired. Re-initializing...');\n }\n \n // Clear chat_id\n this.chatId = null;\n this.supportSessionId = null;\n if (typeof window !== 'undefined' && window.localStorage) {\n localStorage.removeItem('chartsconnect_chat_id');\n localStorage.removeItem('chartsconnect_session_id');\n }\n \n // Try to reinitialize chat\n try {\n const newSession = await this.chatService.startSupportChat(\n this.state.sessionId || null,\n null,\n null,\n null\n );\n this.chatId = newSession.chat_id;\n this.supportSessionId = newSession.session_id;\n if (typeof window !== 'undefined' && window.localStorage) {\n localStorage.setItem('chartsconnect_chat_id', this.chatId);\n localStorage.setItem('chartsconnect_session_id', this.supportSessionId);\n }\n \n // Retry sending message\n if (this.chatId && this.supportSessionId) {\n await this.chatService.sendMessageToAgent(\n this.chatId,\n this.supportSessionId,\n text.trim()\n );\n }\n this.setState({ isLoading: false });\n return;\n } catch (retryError: any) {\n if (retryError instanceof ChatResolvedError || retryError?.message === 'chat_resolved') {\n this.enterResolvedState(this.chatId);\n return;\n }\n throw retryError;\n }\n } else {\n throw error;\n }\n }\n }\n\n /**\n * Switch to human mode\n */\n switchToHumanMode(): void {\n this.chatMode = 'human';\n this.setState({ chatMode: 'human' });\n if (typeof window !== 'undefined' && window.localStorage) {\n localStorage.setItem('chartsconnect_chat_mode', 'HUMAN');\n }\n }\n\n /**\n * Switch to AI mode\n */\n switchToBotMode(): void {\n this.chatMode = 'ai';\n this.setState({ chatMode: 'ai' });\n if (typeof window !== 'undefined' && window.localStorage) {\n localStorage.setItem('chartsconnect_chat_mode', 'BOT');\n }\n }\n\n /**\n * Initialize welcome popup\n */\n initializeWelcomePopup(): void {\n if (this.config.showWelcomePopup !== false) {\n const delay = this.config.welcomePopupDelay || 1500;\n setTimeout(() => {\n if (!this.state.isOpen) {\n this.setState({ showWelcomePopup: true });\n }\n }, delay);\n }\n }\n\n /**\n * Start user info collection for handoff\n */\n private startUserInfoCollection(): void {\n this.collectingUserInfo = true;\n this.userInfoStep = 'name';\n this.collectedUserName = '';\n this.collectedUserEmail = '';\n this.collectedUserMobile = '';\n \n // Ask for name\n const namePrompt: ChatMessage = {\n id: `prompt-${Date.now()}`,\n text: 'To connect you with a human agent, I\\'ll need some information. Please provide your name:',\n sender: 'bot',\n timestamp: new Date(),\n };\n this.setState({\n messages: [...this.state.messages, namePrompt],\n });\n }\n\n /**\n * Handle user info collection\n */\n private async handleUserInfoCollection(text: string): Promise<void> {\n if (this.userInfoStep === 'name') {\n // Save name and ask for email\n const name = text.trim();\n this.collectedUserName = name;\n this.userInfoStep = 'email';\n \n // Ask for email\n const emailPrompt: ChatMessage = {\n id: `prompt-${Date.now()}`,\n text: 'Thank you! Now please provide your email address:',\n sender: 'bot',\n timestamp: new Date(),\n };\n this.setState({\n messages: [...this.state.messages, emailPrompt],\n inputValue: '',\n });\n return;\n } else if (this.userInfoStep === 'email') {\n // Validate email format\n const email = text.trim();\n const emailRegex = /^[^\\s@]+@[^\\s@]+\\.[^\\s@]+$/;\n \n if (!emailRegex.test(email)) {\n // Invalid email, ask again\n const invalidEmailMessage: ChatMessage = {\n id: `prompt-${Date.now()}`,\n text: 'Please provide a valid email address:',\n sender: 'bot',\n timestamp: new Date(),\n };\n this.setState({\n messages: [...this.state.messages, invalidEmailMessage],\n inputValue: '',\n });\n return;\n }\n \n // Save email and ask for mobile\n this.collectedUserEmail = email;\n this.userInfoStep = 'mobile';\n \n // Ask for mobile\n const mobilePrompt: ChatMessage = {\n id: `prompt-${Date.now()}`,\n text: 'Thank you! Now please provide your mobile number:',\n sender: 'bot',\n timestamp: new Date(),\n };\n this.setState({\n messages: [...this.state.messages, mobilePrompt],\n inputValue: '',\n });\n return;\n } else if (this.userInfoStep === 'mobile') {\n // Validate mobile format\n const mobile = text.trim();\n const mobileRegex = /^[\\+]?[(]?[0-9]{1,4}[)]?[-\\s\\.]?[(]?[0-9]{1,4}[)]?[-\\s\\.]?[0-9]{1,9}$/;\n \n if (!mobileRegex.test(mobile) || mobile.length < 10) {\n // Invalid mobile, ask again\n const invalidMobileMessage: ChatMessage = {\n id: `prompt-${Date.now()}`,\n text: 'Please provide a valid mobile number (e.g., +1234567890):',\n sender: 'bot',\n timestamp: new Date(),\n };\n this.setState({\n messages: [...this.state.messages, invalidMobileMessage],\n inputValue: '',\n });\n return;\n }\n \n // Save mobile and proceed with handoff\n this.collectedUserMobile = mobile;\n \n // Reset collection state\n this.collectingUserInfo = false;\n this.userInfoStep = null;\n \n // Proceed with handoff using collected info\n await this.handleHandoff(this.collectedUserName, this.collectedUserEmail, mobile);\n this.setState({ inputValue: '' });\n }\n }\n\n /**\n * Handle handoff from Dialogflow to human support\n */\n async handleHandoff(customerName?: string, customerEmail?: string, customerMobile?: string): Promise<void> {\n if (!this.chatService) {\n throw new Error('Chat service not initialized');\n }\n\n try {\n this.isConnectingToAgent = true;\n \n // Get Dialogflow session ID if available\n const dialogflowSessionId = this.state.sessionId;\n \n // STEP 1: Ensure chat is initialized\n const session = await this.chatService.ensureChatInitialized(\n this.chatId,\n this.supportSessionId,\n dialogflowSessionId || null,\n customerName || null,\n customerEmail || null,\n customerMobile || null\n );\n \n if (!session || !session.chat_id) {\n throw new Error('Failed to initialize chat session');\n }\n \n const currentChatId = session.chat_id;\n const currentSupportSessionId = session.session_id;\n \n // Update state if chat was newly initialized\n if (currentChatId !== this.chatId) {\n this.chatId = currentChatId;\n this.supportSessionId = currentSupportSessionId;\n if (typeof window !== 'undefined' && window.localStorage) {\n localStorage.setItem('chartsconnect_chat_id', this.chatId);\n localStorage.setItem('chartsconnect_session_id', this.supportSessionId);\n }\n if (this.config.debug) {\n console.log('✅ Chat initialized:', { chatId: currentChatId, sessionId: currentSupportSessionId });\n }\n }\n\n // STEP 2: Request handoff\n try {\n await this.chatService.requestHandoff(\n currentChatId,\n currentSupportSessionId,\n 'Customer requested human agent',\n dialogflowSessionId || null,\n customerName || null,\n customerEmail || null,\n customerMobile || null\n );\n \n if (this.config.debug) {\n console.log('✅ Handoff requested successfully');\n }\n } catch (handoffError: any) {\n // Handle 401/404 or \"chat not found\" - clear chat_id and retry\n if (handoffError.message?.includes('Invalid chat_id') || \n handoffError.message?.includes('Chat not found') ||\n handoffError.message?.includes('unauthorized') ||\n handoffError.message?.includes('400') ||\n handoffError.message?.includes('401') ||\n handoffError.message?.includes('404') ||\n handoffError.message?.includes('expired')) {\n if (this.config.debug) {\n console.log('⚠️ Chat expired or not found. Re-initializing chat...');\n }\n \n // Clear old chat_id\n this.chatId = null;\n this.supportSessionId = null;\n if (typeof window !== 'undefined' && window.localStorage) {\n localStorage.removeItem('chartsconnect_chat_id');\n localStorage.removeItem('chartsconnect_session_id');\n }\n \n // Create new chat session\n const newSession = await this.chatService.startSupportChat(\n dialogflowSessionId || null,\n customerName || null,\n customerEmail || null,\n customerMobile || null\n );\n \n if (!newSession || !newSession.chat_id) {\n throw new Error('Failed to re-initialize chat session');\n }\n \n this.chatId = newSession.chat_id;\n this.supportSessionId = newSession.session_id;\n if (typeof window !== 'undefined' && window.localStorage) {\n localStorage.setItem('chartsconnect_chat_id', this.chatId);\n localStorage.setItem('chartsconnect_session_id', this.supportSessionId);\n }\n \n // Retry handoff with new chat_id\n await this.chatService.requestHandoff(\n this.chatId,\n this.supportSessionId,\n 'Customer requested human agent',\n dialogflowSessionId || null,\n customerName || null,\n customerEmail || null,\n customerMobile || null\n );\n \n if (this.config.debug) {\n console.log('✅ Handoff requested successfully after retry');\n }\n } else {\n throw handoffError;\n }\n }\n\n // Switch to human mode\n this.switchToHumanMode();\n this.chatResolved = false;\n this.agentAccepted = false;\n\n // Add connecting message\n const connectingMessage: ChatMessage = {\n id: `connecting-${Date.now()}`,\n text: 'Connecting you to a human agent...',\n sender: 'bot',\n timestamp: new Date(),\n };\n this.setState({\n messages: [...this.state.messages, connectingMessage],\n });\n\n // Connect WebSocket with handlers\n if (currentChatId && currentSupportSessionId) {\n this.chatService.connectWebSocket(\n currentChatId,\n currentSupportSessionId,\n (message: WebSocketMessage) => {\n this.handleWebSocketMessage(message);\n },\n (connected: boolean) => {\n this.wsConnected = connected;\n }\n );\n }\n \n this.isConnectingToAgent = false;\n } catch (error: any) {\n console.error('Error handling handoff:', error);\n const errorMessage: ChatMessage = {\n id: `error-${Date.now()}`,\n text: this.config.debug\n ? `Handoff error: ${error.message}`\n : 'Failed to connect to agent. Please try again.',\n sender: 'bot',\n timestamp: new Date(),\n };\n this.setState({\n messages: [...this.state.messages, errorMessage],\n });\n this.isConnectingToAgent = false;\n }\n }\n\n /**\n * Handle WebSocket messages\n */\n private handleWebSocketMessage(message: WebSocketMessage): void {\n switch (message.type) {\n case 'message':\n if (message.content) {\n // Only display messages from agent\n if (message.sender_type === 'agent' || !message.sender_type) {\n const agentMessage: ChatMessage = {\n id: message.id || `agent-${Date.now()}`,\n text: message.content,\n sender: 'agent',\n timestamp: new Date(message.timestamp || Date.now()),\n };\n \n // Avoid duplicate messages\n const existingIds = new Set(this.state.messages.map(m => m.id));\n if (!existingIds.has(agentMessage.id)) {\n this.setState({\n messages: [...this.state.messages, agentMessage],\n });\n }\n \n // Hide typing indicator when message received\n this.agentTyping = false;\n if (this.agentTypingTimeout) {\n clearTimeout(this.agentTypingTimeout);\n this.agentTypingTimeout = null;\n }\n }\n }\n break;\n\n case 'typing_start':\n if (message.sender_type === 'agent') {\n this.agentTyping = true;\n // Auto-hide after 3 seconds if no message received\n if (this.agentTypingTimeout) {\n clearTimeout(this.agentTypingTimeout);\n }\n this.agentTypingTimeout = setTimeout(() => {\n this.agentTyping = false;\n }, 3000);\n }\n break;\n\n case 'typing_stop':\n if (message.sender_type === 'agent') {\n this.agentTyping = false;\n if (this.agentTypingTimeout) {\n clearTimeout(this.agentTypingTimeout);\n this.agentTypingTimeout = null;\n }\n }\n break;\n\n case 'agent_changed':\n if (message.to_agent) {\n this.currentAgent = {\n id: message.to_agent_id,\n name: message.to_agent,\n };\n\n // Add system message to chat\n const systemMessage: ChatMessage = {\n id: `system-${Date.now()}`,\n text: message.from_agent\n ? `Chat has been transferred from ${message.from_agent} to ${message.to_agent}`\n : `Chat has been transferred to ${message.to_agent}`,\n sender: 'bot',\n timestamp: new Date(),\n };\n this.setState({\n messages: [...this.state.messages, systemMessage],\n });\n }\n break;\n\n case 'agent_accepted':\n this.agentAccepted = true;\n this.isConnectingToAgent = false;\n const acceptedMessage: ChatMessage = {\n id: message.id || `agent-accepted-${Date.now()}`,\n text: 'You can chat now, the agent has accepted your request.',\n sender: 'bot',\n timestamp: message.timestamp ? new Date(message.timestamp) : new Date(),\n };\n const existingIds = new Set(this.state.messages.map(m => m.id));\n if (!existingIds.has(acceptedMessage.id)) {\n this.setState({\n messages: [...this.state.messages, acceptedMessage],\n });\n }\n if (message.to_agent) {\n this.currentAgent = {\n name: message.to_agent,\n id: message.to_agent_id,\n };\n }\n break;\n\n case 'chat_resolved':\n case 'chat_ended':\n this.enterResolvedState(message.chat_id || null);\n break;\n\n case 'chat_info':\n if (message.status === 'active') {\n this.isConnectingToAgent = false;\n this.agentAccepted = true;\n } else if (message.status === 'resolved' || message.status === 'ended') {\n this.enterResolvedState(message.chat_id || null);\n }\n if (message.agent_id) {\n this.currentAgent = {\n ...this.currentAgent,\n id: message.agent_id,\n };\n }\n break;\n\n case 'error':\n console.error('WebSocket error:', message.error);\n const errorMessage: ChatMessage = {\n id: `error-${Date.now()}`,\n text: message.error || 'An error occurred. Please try again.',\n sender: 'bot',\n timestamp: new Date(),\n };\n this.setState({\n messages: [...this.state.messages, errorMessage],\n });\n break;\n }\n }\n\n /**\n * Enter resolved state\n */\n private enterResolvedState(resolvedChatId?: string | null): void {\n this.chatResolved = true;\n this.isConnectingToAgent = false;\n this.agentAccepted = false;\n this.agentTyping = false;\n if (this.agentTypingTimeout) {\n clearTimeout(this.agentTypingTimeout);\n this.agentTypingTimeout = null;\n }\n\n // Stop WS + prevent any reuse of the old chat_id\n if (this.chatService) {\n this.chatService.disconnectWebSocket();\n }\n this.chatId = null;\n this.supportSessionId = null;\n if (typeof window !== 'undefined' && window.localStorage) {\n localStorage.removeItem('chartsconnect_chat_id');\n localStorage.removeItem('chartsconnect_session_id');\n }\n \n // Add thank you message before reset\n const thankYouMessage: ChatMessage = {\n id: `resolved-${Date.now()}`,\n text: 'Thank you for contacting us!',\n sender: 'bot',\n timestamp: new Date(),\n };\n this.setState({\n messages: [...this.state.messages, thankYouMessage],\n });\n \n // Automatically reset to BOT mode after showing thank you message\n setTimeout(async () => {\n this.switchToBotMode();\n this.chatResolved = false;\n this.setState({\n messages: [],\n sessionId: null, // Clear session ID to force recreation\n });\n this.collectingUserInfo = false;\n this.userInfoStep = null;\n this.collectedUserName = '';\n this.collectedUserEmail = '';\n this.collectedUserMobile = '';\n \n // Recreate Dialogflow session to start fresh\n if (this.config.dfProjectId && this.config.dfAgentId && this.state.isOpen) {\n try {\n this.setState({ isLoading: true });\n const dialogflowConfig: DialogflowBackendConfig = {\n dfProjectId: this.config.dfProjectId,\n dfLocation: this.config.dfLocation || 'us-central1',\n dfAgentId: this.config.dfAgentId,\n languageCode: this.config.languageCode || 'en',\n backendBaseUrl: this.config.backendBaseUrl || 'http://localhost:8012',\n };\n \n const session = await createDialogflowSession(dialogflowConfig);\n this.setState({ \n sessionId: session.session_id,\n isLoading: false,\n });\n \n // Add welcome message from Dialogflow if available\n if (session.message) {\n const welcomeMessage: ChatMessage = {\n id: `welcome-${Date.now()}`,\n text: session.message,\n sender: 'bot',\n timestamp: new Date(),\n richContent: session.richContent,\n };\n this.setState({\n messages: [welcomeMessage],\n });\n }\n } catch (error: any) {\n console.error('Error recreating Dialogflow session after handoff:', error);\n this.setState({ \n isLoading: false,\n error: error.message || 'Failed to initialize chat',\n });\n \n // Show fallback welcome message\n const fallbackMessage: ChatMessage = {\n id: `fallback-${Date.now()}`,\n text: this.config.fallbackWelcomeMessage || 'Hello! How can I help you today?',\n sender: 'bot',\n timestamp: new Date(),\n };\n this.setState({\n messages: [fallbackMessage],\n });\n }\n }\n }, 2000);\n }\n\n /**\n * Load message history\n */\n async loadMessageHistory(preserveExisting: boolean = false): Promise<void> {\n if (!this.chatService || !this.chatId || !this.supportSessionId) {\n return;\n }\n\n try {\n if (this.chatId && this.supportSessionId) {\n const history = await this.chatService.loadMessageHistory(this.chatId, this.supportSessionId);\n \n const historyMessages: ChatMessage[] = history.map((msg: any) => ({\n id: msg.id || `history-${Date.now()}-${Math.random()}`,\n text: msg.content,\n sender: msg.sender_type === 'agent' ? 'agent' : 'user',\n timestamp: new Date(msg.timestamp),\n }));\n\n if (preserveExisting) {\n // Merge with existing messages, avoiding duplicates\n const existingIds = new Set(this.state.messages.map(m => m.id));\n const newMessages = historyMessages.filter(m => !existingIds.has(m.id));\n \n // Combine existing messages with new history messages\n // Sort by timestamp to maintain chronological order\n const combined = [...this.state.messages, ...newMessages].sort((a, b) => \n a.timestamp.getTime() - b.timestamp.getTime()\n );\n \n this.setState({\n messages: combined,\n });\n } else {\n // Replace all messages\n this.setState({\n messages: historyMessages,\n });\n }\n }\n } catch (error: any) {\n console.error('Error loading message history:', error);\n if (this.config.debug) {\n const errorMessage: ChatMessage = {\n id: `error-${Date.now()}`,\n text: `Failed to load chat history: ${error.message}`,\n sender: 'bot',\n timestamp: new Date(),\n };\n this.setState({\n messages: [...this.state.messages, errorMessage],\n });\n }\n }\n }\n\n /**\n * Get additional state for UI (not in WidgetState but needed by components)\n */\n getAdditionalState() {\n return {\n wsConnected: this.wsConnected,\n agentTyping: this.agentTyping,\n currentAgent: this.currentAgent,\n isConnectingToAgent: this.isConnectingToAgent,\n agentAccepted: this.agentAccepted,\n chatResolved: this.chatResolved,\n };\n }\n\n /**\n * Cleanup\n */\n destroy(): void {\n if (this.typingTimeout) {\n clearTimeout(this.typingTimeout);\n }\n if (this.agentTypingTimeout) {\n clearTimeout(this.agentTypingTimeout);\n }\n if (this.chatService) {\n this.chatService.disconnectWebSocket();\n }\n this.listeners.clear();\n }\n}\n","/**\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","<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: '💬 Charts Connect AI Assistant',\n subtitle: \"We're here to help\",\n welcomeTitle: '👋 Welcome to Charts Connect',\n welcomeMessage: \"My name is Charts Connect 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 Charts Connect AI Assistant. How can I help you today?\",\n inputPlaceholder: 'Type your message...',\n emptyStateMessage: \"Hi! I'm Charts Connect 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":["botMessage","existingIds","_openBlock","_createElementBlock","_mergeProps","$attrs","_unref","_createElementVNode","_toDisplayString","_Fragment","_renderList","_normalizeClass"],"mappings":"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"}
@@ -0,0 +1,2 @@
1
+ "use strict";const e=require("vue"),t=require("./sanitize-C8MB41vY.cjs");class s{constructor(e){if(this.listeners=new Set,this.chatMode="ai",this.chatId=null,this.supportSessionId=null,this.chatService=null,this.collectingUserInfo=!1,this.userInfoStep=null,this.collectedUserName="",this.collectedUserEmail="",this.collectedUserMobile="",this.wsConnected=!1,this.agentTyping=!1,this.currentAgent={name:"Agent"},this.isConnectingToAgent=!1,this.agentAccepted=!1,this.chatResolved=!1,this.historyLoaded=null,this.typingTimeout=null,this.agentTypingTimeout=null,this.config=e,this.state={isOpen:!1,showWelcomePopup:!1,messages:[],inputValue:"",isLoading:!1,error:null,sessionId:null,chatMode:"ai"},this.chatService=t.createChatService({baseUrl:this.config.backendBaseUrl||"http://localhost:8012",wsUrl:this.config.backendWsUrl||"ws://localhost:8012",debug:this.config.debug||!1}),"undefined"!=typeof window&&window.localStorage){const e=localStorage.getItem("chartsconnectect_chat_mode");this.chatMode="HUMAN"===e?"human":"ai",this.state.chatMode=this.chatMode,this.chatId=localStorage.getItem("chartsconnect_chat_id"),this.supportSessionId=localStorage.getItem("chartsconnect_session_id")}}subscribe(e){return this.listeners.add(e),()=>{this.listeners.delete(e)}}getState(){return{...this.state}}setState(e){this.state={...this.state,...e},this.listeners.forEach(e=>e(this.getState()))}updateConfig(e){this.config={...this.config,...e}}async openChat(){if(this.setState({isOpen:!0}),this.state.showWelcomePopup&&this.setState({showWelcomePopup:!1}),"ai"===this.state.chatMode&&!this.state.sessionId&&this.config.dfProjectId&&this.config.dfAgentId)try{this.setState({isLoading:!0});const e={dfProjectId:this.config.dfProjectId,dfLocation:this.config.dfLocation||"us-central1",dfAgentId:this.config.dfAgentId,languageCode:this.config.languageCode||"en",backendBaseUrl:this.config.backendBaseUrl||"http://localhost:8012"},s=await t.createDialogflowSession(e);if(this.setState({sessionId:s.session_id,isLoading:!1}),s.message){const e={id:`welcome-${Date.now()}`,text:s.message,sender:"bot",timestamp:new Date,richContent:s.richContent};this.setState({messages:[e]})}}catch(e){this.setState({isLoading:!1,error:e.message||"Failed to initialize chat"});const t={id:`fallback-${Date.now()}`,text:this.config.fallbackWelcomeMessage||"Hello! How can I help you today?",sender:"bot",timestamp:new Date};this.setState({messages:[t]})}}closeChat(){this.setState({isOpen:!1})}closeWelcomePopup(){this.setState({showWelcomePopup:!1})}toggleChat(){const e=!this.state.isOpen;this.setState({isOpen:e}),e&&this.state.showWelcomePopup&&this.setState({showWelcomePopup:!1})}setInputValue(e){this.setState({inputValue:e})}clearError(){this.setState({error:null})}async sendMessage(e,s=!1){if(e.trim()&&!this.state.isLoading){if(this.collectingUserInfo){const t={id:`user-${Date.now()}`,text:e.trim(),sender:"user",timestamp:new Date};return this.setState({messages:[...this.state.messages,t],inputValue:"",isLoading:!1,error:null}),void(await this.handleUserInfoCollection(e))}if(s)this.setState({inputValue:"",isLoading:!0,error:null});else{const t={id:`user-${Date.now()}`,text:e.trim(),sender:"user",timestamp:new Date};this.setState({messages:[...this.state.messages,t],inputValue:"",isLoading:!0,error:null})}try{"human"===this.state.chatMode?await this.sendHumanMessage(e):await this.sendAIMessage(e)}catch(a){if(a instanceof t.ChatResolvedError||"ChatResolvedError"===a?.name||"chat_resolved"===a?.message)return void this.enterResolvedState(this.chatId);const e={id:`error-${Date.now()}`,text:this.config.debug?`Error: ${a.message||"Failed to send message"}`:a.message?.includes("CORS")||a.message?.includes("Failed to fetch")?"Unable to connect to Dialogflow. Please check your configuration and network.":"Sorry, I'm having trouble processing your message. Please try again.",sender:"bot",timestamp:new Date};this.setState({messages:[...this.state.messages,e],error:a.message||"Failed to send message",isLoading:!1})}}}async sendAIMessage(e){if(!this.config.dfProjectId||!this.config.dfAgentId)throw new Error("Dialogflow configuration is missing");const s={dfProjectId:this.config.dfProjectId,dfLocation:this.config.dfLocation||"us-central1",dfAgentId:this.config.dfAgentId,languageCode:this.config.languageCode||"en",backendBaseUrl:this.config.backendBaseUrl||"http://localhost:8012"};if(!this.state.sessionId){const e=await t.createDialogflowSession(s);this.setState({sessionId:e.session_id})}this.config.debug;const a=await t.sendDialogflowMessage(e,this.state.sessionId,s);if(this.config.debug,!0===a.handoff){const e={id:`bot-${Date.now()}`,text:a.response||this.config.fallbackWelcomeMessage||"No response",sender:"bot",timestamp:new Date,richContent:a.richContent};return this.setState({messages:[...this.state.messages,e],isLoading:!1}),void this.startUserInfoCollection()}const n={id:`bot-${Date.now()}`,text:a.response||this.config.fallbackWelcomeMessage||"No response",sender:"bot",timestamp:new Date,richContent:a.richContent};this.setState({messages:[...this.state.messages,n],isLoading:!1})}async sendHumanMessage(e){if(!this.chatId||!this.supportSessionId){const e={id:`error-${Date.now()}`,text:"Chat session not initialized. Please try again.",sender:"bot",timestamp:new Date};return void this.setState({messages:[...this.state.messages,e],isLoading:!1})}if(!this.chatService)throw new Error("Chat service not initialized");this.chatService.sendTypingIndicator("typing_stop"),this.typingTimeout&&(clearTimeout(this.typingTimeout),this.typingTimeout=null);try{this.chatService.sendMessageViaWebSocket(e.trim())||await this.chatService.sendMessageToAgent(this.chatId,this.supportSessionId,e.trim()),this.setState({isLoading:!1})}catch(s){if(s instanceof t.ChatResolvedError||"ChatResolvedError"===s?.name||"chat_resolved"===s?.message)return void this.enterResolvedState(this.chatId);if(!(s.message?.includes("Chat not found")||s.message?.includes("unauthorized")||s.message?.includes("401")||s.message?.includes("404")))throw s;this.config.debug,this.chatId=null,this.supportSessionId=null,"undefined"!=typeof window&&window.localStorage&&(localStorage.removeItem("chartsconnect_chat_id"),localStorage.removeItem("chartsconnect_session_id"));try{const t=await this.chatService.startSupportChat(this.state.sessionId||null,null,null,null);return this.chatId=t.chat_id,this.supportSessionId=t.session_id,"undefined"!=typeof window&&window.localStorage&&(localStorage.setItem("chartsconnect_chat_id",this.chatId),localStorage.setItem("chartsconnect_session_id",this.supportSessionId)),this.chatId&&this.supportSessionId&&await this.chatService.sendMessageToAgent(this.chatId,this.supportSessionId,e.trim()),void this.setState({isLoading:!1})}catch(a){if(a instanceof t.ChatResolvedError||"chat_resolved"===a?.message)return void this.enterResolvedState(this.chatId);throw a}}}switchToHumanMode(){this.chatMode="human",this.setState({chatMode:"human"}),"undefined"!=typeof window&&window.localStorage&&localStorage.setItem("chartsconnect_chat_mode","HUMAN")}switchToBotMode(){this.chatMode="ai",this.setState({chatMode:"ai"}),"undefined"!=typeof window&&window.localStorage&&localStorage.setItem("chartsconnect_chat_mode","BOT")}initializeWelcomePopup(){if(!1!==this.config.showWelcomePopup){const e=this.config.welcomePopupDelay||1500;setTimeout(()=>{this.state.isOpen||this.setState({showWelcomePopup:!0})},e)}}startUserInfoCollection(){this.collectingUserInfo=!0,this.userInfoStep="name",this.collectedUserName="",this.collectedUserEmail="",this.collectedUserMobile="";const e={id:`prompt-${Date.now()}`,text:"To connect you with a human agent, I'll need some information. Please provide your name:",sender:"bot",timestamp:new Date};this.setState({messages:[...this.state.messages,e]})}async handleUserInfoCollection(e){if("name"===this.userInfoStep){const t=e.trim();this.collectedUserName=t,this.userInfoStep="email";const s={id:`prompt-${Date.now()}`,text:"Thank you! Now please provide your email address:",sender:"bot",timestamp:new Date};return void this.setState({messages:[...this.state.messages,s],inputValue:""})}if("email"===this.userInfoStep){const t=e.trim();if(!/^[^\s@]+@[^\s@]+\.[^\s@]+$/.test(t)){const e={id:`prompt-${Date.now()}`,text:"Please provide a valid email address:",sender:"bot",timestamp:new Date};return void this.setState({messages:[...this.state.messages,e],inputValue:""})}this.collectedUserEmail=t,this.userInfoStep="mobile";const s={id:`prompt-${Date.now()}`,text:"Thank you! Now please provide your mobile number:",sender:"bot",timestamp:new Date};return void this.setState({messages:[...this.state.messages,s],inputValue:""})}if("mobile"===this.userInfoStep){const t=e.trim();if(!/^[\+]?[(]?[0-9]{1,4}[)]?[-\s\.]?[(]?[0-9]{1,4}[)]?[-\s\.]?[0-9]{1,9}$/.test(t)||t.length<10){const e={id:`prompt-${Date.now()}`,text:"Please provide a valid mobile number (e.g., +1234567890):",sender:"bot",timestamp:new Date};return void this.setState({messages:[...this.state.messages,e],inputValue:""})}this.collectedUserMobile=t,this.collectingUserInfo=!1,this.userInfoStep=null,await this.handleHandoff(this.collectedUserName,this.collectedUserEmail,t),this.setState({inputValue:""})}}async handleHandoff(e,t,s){if(!this.chatService)throw new Error("Chat service not initialized");try{this.isConnectingToAgent=!0;const n=this.state.sessionId,o=await this.chatService.ensureChatInitialized(this.chatId,this.supportSessionId,n||null,e||null,t||null,s||null);if(!o||!o.chat_id)throw new Error("Failed to initialize chat session");const i=o.chat_id,c=o.session_id;i!==this.chatId&&(this.chatId=i,this.supportSessionId=c,"undefined"!=typeof window&&window.localStorage&&(localStorage.setItem("chartsconnect_chat_id",this.chatId),localStorage.setItem("chartsconnect_session_id",this.supportSessionId)),this.config.debug);try{await this.chatService.requestHandoff(i,c,"Customer requested human agent",n||null,e||null,t||null,s||null),this.config.debug}catch(a){if(!(a.message?.includes("Invalid chat_id")||a.message?.includes("Chat not found")||a.message?.includes("unauthorized")||a.message?.includes("400")||a.message?.includes("401")||a.message?.includes("404")||a.message?.includes("expired")))throw a;{this.config.debug,this.chatId=null,this.supportSessionId=null,"undefined"!=typeof window&&window.localStorage&&(localStorage.removeItem("chartsconnect_chat_id"),localStorage.removeItem("chartsconnect_session_id"));const a=await this.chatService.startSupportChat(n||null,e||null,t||null,s||null);if(!a||!a.chat_id)throw new Error("Failed to re-initialize chat session");this.chatId=a.chat_id,this.supportSessionId=a.session_id,"undefined"!=typeof window&&window.localStorage&&(localStorage.setItem("chartsconnect_chat_id",this.chatId),localStorage.setItem("chartsconnect_session_id",this.supportSessionId)),await this.chatService.requestHandoff(this.chatId,this.supportSessionId,"Customer requested human agent",n||null,e||null,t||null,s||null),this.config.debug}}this.switchToHumanMode(),this.chatResolved=!1,this.agentAccepted=!1;const l={id:`connecting-${Date.now()}`,text:"Connecting you to a human agent...",sender:"bot",timestamp:new Date};this.setState({messages:[...this.state.messages,l]}),i&&c&&this.chatService.connectWebSocket(i,c,e=>{this.handleWebSocketMessage(e)},e=>{this.wsConnected=e}),this.isConnectingToAgent=!1}catch(n){const e={id:`error-${Date.now()}`,text:this.config.debug?`Handoff error: ${n.message}`:"Failed to connect to agent. Please try again.",sender:"bot",timestamp:new Date};this.setState({messages:[...this.state.messages,e]}),this.isConnectingToAgent=!1}}handleWebSocketMessage(e){switch(e.type){case"message":if(e.content&&("agent"===e.sender_type||!e.sender_type)){const t={id:e.id||`agent-${Date.now()}`,text:e.content,sender:"agent",timestamp:new Date(e.timestamp||Date.now())};new Set(this.state.messages.map(e=>e.id)).has(t.id)||this.setState({messages:[...this.state.messages,t]}),this.agentTyping=!1,this.agentTypingTimeout&&(clearTimeout(this.agentTypingTimeout),this.agentTypingTimeout=null)}break;case"typing_start":"agent"===e.sender_type&&(this.agentTyping=!0,this.agentTypingTimeout&&clearTimeout(this.agentTypingTimeout),this.agentTypingTimeout=setTimeout(()=>{this.agentTyping=!1},3e3));break;case"typing_stop":"agent"===e.sender_type&&(this.agentTyping=!1,this.agentTypingTimeout&&(clearTimeout(this.agentTypingTimeout),this.agentTypingTimeout=null));break;case"agent_changed":if(e.to_agent){this.currentAgent={id:e.to_agent_id,name:e.to_agent};const t={id:`system-${Date.now()}`,text:e.from_agent?`Chat has been transferred from ${e.from_agent} to ${e.to_agent}`:`Chat has been transferred to ${e.to_agent}`,sender:"bot",timestamp:new Date};this.setState({messages:[...this.state.messages,t]})}break;case"agent_accepted":this.agentAccepted=!0,this.isConnectingToAgent=!1;const t={id:e.id||`agent-accepted-${Date.now()}`,text:"You can chat now, the agent has accepted your request.",sender:"bot",timestamp:e.timestamp?new Date(e.timestamp):new Date};new Set(this.state.messages.map(e=>e.id)).has(t.id)||this.setState({messages:[...this.state.messages,t]}),e.to_agent&&(this.currentAgent={name:e.to_agent,id:e.to_agent_id});break;case"chat_resolved":case"chat_ended":this.enterResolvedState(e.chat_id||null);break;case"chat_info":"active"===e.status?(this.isConnectingToAgent=!1,this.agentAccepted=!0):"resolved"!==e.status&&"ended"!==e.status||this.enterResolvedState(e.chat_id||null),e.agent_id&&(this.currentAgent={...this.currentAgent,id:e.agent_id});break;case"error":const s={id:`error-${Date.now()}`,text:e.error||"An error occurred. Please try again.",sender:"bot",timestamp:new Date};this.setState({messages:[...this.state.messages,s]})}}enterResolvedState(e){this.chatResolved=!0,this.isConnectingToAgent=!1,this.agentAccepted=!1,this.agentTyping=!1,this.agentTypingTimeout&&(clearTimeout(this.agentTypingTimeout),this.agentTypingTimeout=null),this.chatService&&this.chatService.disconnectWebSocket(),this.chatId=null,this.supportSessionId=null,"undefined"!=typeof window&&window.localStorage&&(localStorage.removeItem("chartsconnect_chat_id"),localStorage.removeItem("chartsconnect_session_id"));const s={id:`resolved-${Date.now()}`,text:"Thank you for contacting us!",sender:"bot",timestamp:new Date};this.setState({messages:[...this.state.messages,s]}),setTimeout(async()=>{if(this.switchToBotMode(),this.chatResolved=!1,this.setState({messages:[],sessionId:null}),this.collectingUserInfo=!1,this.userInfoStep=null,this.collectedUserName="",this.collectedUserEmail="",this.collectedUserMobile="",this.config.dfProjectId&&this.config.dfAgentId&&this.state.isOpen)try{this.setState({isLoading:!0});const e={dfProjectId:this.config.dfProjectId,dfLocation:this.config.dfLocation||"us-central1",dfAgentId:this.config.dfAgentId,languageCode:this.config.languageCode||"en",backendBaseUrl:this.config.backendBaseUrl||"http://localhost:8012"},s=await t.createDialogflowSession(e);if(this.setState({sessionId:s.session_id,isLoading:!1}),s.message){const e={id:`welcome-${Date.now()}`,text:s.message,sender:"bot",timestamp:new Date,richContent:s.richContent};this.setState({messages:[e]})}}catch(e){this.setState({isLoading:!1,error:e.message||"Failed to initialize chat"});const t={id:`fallback-${Date.now()}`,text:this.config.fallbackWelcomeMessage||"Hello! How can I help you today?",sender:"bot",timestamp:new Date};this.setState({messages:[t]})}},2e3)}async loadMessageHistory(e=!1){if(this.chatService&&this.chatId&&this.supportSessionId)try{if(this.chatId&&this.supportSessionId){const t=(await this.chatService.loadMessageHistory(this.chatId,this.supportSessionId)).map(e=>({id:e.id||`history-${Date.now()}-${Math.random()}`,text:e.content,sender:"agent"===e.sender_type?"agent":"user",timestamp:new Date(e.timestamp)}));if(e){const e=new Set(this.state.messages.map(e=>e.id)),s=t.filter(t=>!e.has(t.id)),a=[...this.state.messages,...s].sort((e,t)=>e.timestamp.getTime()-t.timestamp.getTime());this.setState({messages:a})}else this.setState({messages:t})}}catch(t){if(this.config.debug){const e={id:`error-${Date.now()}`,text:`Failed to load chat history: ${t.message}`,sender:"bot",timestamp:new Date};this.setState({messages:[...this.state.messages,e]})}}}getAdditionalState(){return{wsConnected:this.wsConnected,agentTyping:this.agentTyping,currentAgent:this.currentAgent,isConnectingToAgent:this.isConnectingToAgent,agentAccepted:this.agentAccepted,chatResolved:this.chatResolved}}destroy(){this.typingTimeout&&clearTimeout(this.typingTimeout),this.agentTypingTimeout&&clearTimeout(this.agentTypingTimeout),this.chatService&&this.chatService.disconnectWebSocket(),this.listeners.clear()}}function a(t){const a=new s(t),n=e.ref(a.getState()),o=e.ref(!1),i=e.ref(!1),c=e.ref({name:"Agent"}),l=e.ref(!1),r=a.subscribe(e=>{n.value={...e};const t=a.getAdditionalState();o.value=t.wsConnected,i.value=t.agentTyping,c.value=t.currentAgent,l.value=t.isConnectingToAgent}),d=e.computed(()=>n.value.isOpen),h=e.computed(()=>n.value.messages),m=e.computed(()=>n.value.isLoading),g=e.computed(()=>n.value.error),u=e.computed(()=>n.value.chatMode);return e.onUnmounted(()=>{r(),a.destroy()}),e.watch(()=>t,e=>{a.updateConfig(e)},{deep:!0}),{state:n,isOpen:d,messages:h,isLoading:m,error:g,chatMode:u,wsConnected:o,agentTyping:i,currentAgent:c,isConnectingToAgent:l,openChat:async()=>{await a.openChat()},closeChat:()=>{a.closeChat()},sendMessage:async e=>{await a.sendMessage(e)},toggleChat:async()=>{await a.toggleChat()},setInputValue:e=>{a.setInputValue(e)},clearError:()=>{a.clearError()},manager:a}}const n={class:"custom-welcome-header"},o={class:"custom-welcome-title"},i={class:"custom-welcome-message"},c={class:"custom-welcome-cta"},l={key:2,class:"custom-chat-window"},r={class:"custom-chat-header"},d={class:"custom-chat-header-content"},h={class:"custom-chat-title"},m={class:"custom-chat-subtitle"},g={key:0,class:"custom-mode-indicator"},u={key:0,class:"custom-mode-badge"},p={key:1,class:"custom-agent-info"},f={class:"custom-agent-name"},w={key:2,class:"custom-mode-badge"},y={key:0,class:"custom-chat-empty"},S={key:1,class:"custom-chat-empty"},v=["innerHTML"],I={key:0,class:"custom-chips-container"},k={key:0,class:"custom-chips-group"},C=["onClick"],b={key:0,class:"custom-chips-group"},E=["onClick"],T={class:"custom-message-time"},_={key:2,class:"custom-message custom-message-bot"},V={key:3,class:"custom-message custom-message-bot"},N={key:4,class:"custom-agent-typing-indicator"},B=["value","placeholder","disabled"],D=["disabled"],A=((e,t)=>{const s=e.__vccOpts||e;for(const[a,n]of t)s[a]=n;return s})(e.defineComponent({inheritAttrs:!1,__name:"ChatWidget",props:{dfProjectId:{},dfLocation:{},dfAgentId:{},languageCode:{},backendBaseUrl:{},backendWsUrl:{},title:{default:"💬 Charts Connect AI Assistant"},subtitle:{default:"We're here to help"},welcomeTitle:{default:"👋 Welcome to Charts Connect"},welcomeMessage:{default:"My name is Charts Connect AI Assistant and I'll guide you."},welcomeCta:{default:"💬 Click here to start chatting!"},showWelcomePopup:{type:Boolean,default:!0},welcomePopupDelay:{default:1500},fallbackWelcomeMessage:{default:"Hello! I'm Charts Connect AI Assistant. How can I help you today?"},inputPlaceholder:{default:"Type your message..."},emptyStateMessage:{default:"Hi! I'm Charts Connect AI Assistant. How can I help you today?"},debug:{type:Boolean,default:!1}},setup(s){const A=s,{state:M,isOpen:x,messages:L,isLoading:P,error:U,chatMode:$,wsConnected:W,agentTyping:H,currentAgent:O,isConnectingToAgent:R,openChat:z,closeChat:F,sendMessage:j,toggleChat:q,setInputValue:Y,clearError:G,manager:J}=a(A),K=e.ref(null),Q=e.ref(null),X=e.computed(()=>A),Z=e.computed(()=>M.value.isLoading&&0===M.value.messages.length&&!M.value.sessionId),ee=e.computed(()=>!1),te=R;e.watch(()=>L.value.length,()=>{e.nextTick(()=>{K.value?.scrollIntoView({behavior:"smooth"})})});const se=async()=>{M.value.isOpen||(M.value.isOpen=!0,M.value.showWelcomePopup=!1),await z()},ae=()=>{F()},ne=()=>{J.closeWelcomePopup()},oe=e=>{const t=e.target;Y(t.value)},ie=async e=>{e.preventDefault(),M.value.inputValue.trim()&&await j(M.value.inputValue)},ce=async(e,t)=>{const s=e||t||"";await j(s)},le=e=>e.includes("👤")||e.includes("being connected")||e.includes("live support agent")||e.includes("transfer your conversation");return e.onMounted(()=>{X.value.showWelcomePopup&&"undefined"!=typeof window&&J.initializeWelcomePopup()}),(s,a)=>(e.openBlock(),e.createElementBlock("div",e.mergeProps({class:"custom-chat-widget"},s.$attrs),[e.unref(M).showWelcomePopup&&!e.unref(M).isOpen?(e.openBlock(),e.createElementBlock("div",{key:0,class:"custom-welcome-popup",onClick:se},[e.createElementVNode("div",n,[e.createElementVNode("div",o,e.toDisplayString(X.value.welcomeTitle),1),e.createElementVNode("button",{class:"custom-close-popup",onClick:e.withModifiers(ne,["stop"]),"aria-label":"Close welcome popup"}," × ")]),e.createElementVNode("div",i,e.toDisplayString(X.value.welcomeMessage),1),e.createElementVNode("div",c,e.toDisplayString(X.value.welcomeCta),1)])):e.createCommentVNode("",!0),e.unref(M).isOpen?e.createCommentVNode("",!0):(e.openBlock(),e.createElementBlock("button",{key:1,class:"custom-chat-toggle-btn",onClick:se,"aria-label":"Open chat"},[...a[0]||(a[0]=[e.createElementVNode("svg",{width:"24",height:"24",viewBox:"0 0 24 24",fill:"none",stroke:"currentColor","stroke-width":"2","stroke-linecap":"round","stroke-linejoin":"round"},[e.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"})],-1)])])),e.unref(M).isOpen?(e.openBlock(),e.createElementBlock("div",l,[e.createElementVNode("div",r,[e.createElementVNode("div",d,[e.createElementVNode("div",h,e.toDisplayString(X.value.title),1),e.createElementVNode("div",m,[e.createTextVNode(e.toDisplayString(X.value.subtitle)+" ",1),"human"===e.unref(M).chatMode?(e.openBlock(),e.createElementBlock("span",g," • "+e.toDisplayString(e.unref(W)?"🟢 Connected":"🟡 Connecting..."),1)):e.createCommentVNode("",!0)]),"human"===e.unref(M).chatMode?(e.openBlock(),e.createElementBlock("div",u," Human Support Mode ")):e.createCommentVNode("",!0),"human"===e.unref(M).chatMode?(e.openBlock(),e.createElementBlock("div",p,[a[1]||(a[1]=e.createElementVNode("span",{class:"custom-agent-label"},"Agent:",-1)),e.createElementVNode("span",f,e.toDisplayString(e.unref(O).name),1)])):e.createCommentVNode("",!0),"ai"===e.unref(M).chatMode?(e.openBlock(),e.createElementBlock("div",w," Bot Mode ")):e.createCommentVNode("",!0)]),e.createElementVNode("button",{class:"custom-chat-close-btn",onClick:ae,"aria-label":"Close chat"}," × ")]),e.createElementVNode("div",{class:"custom-chat-messages",ref_key:"messagesContainer",ref:Q},[Z.value&&0===e.unref(M).messages.length?(e.openBlock(),e.createElementBlock("div",y,[...a[2]||(a[2]=[e.createElementVNode("div",{class:"custom-typing-indicator"},[e.createElementVNode("span"),e.createElementVNode("span"),e.createElementVNode("span")],-1),e.createElementVNode("p",null,"Initializing chat...",-1)])])):Z.value||0!==e.unref(M).messages.length?e.createCommentVNode("",!0):(e.openBlock(),e.createElementBlock("div",S,[a[3]||(a[3]=e.createElementVNode("div",{class:"custom-chat-empty-icon"},"👋",-1)),e.createElementVNode("p",null,e.toDisplayString(X.value.emptyStateMessage),1)])),(e.openBlock(!0),e.createElementBlock(e.Fragment,null,e.renderList(e.unref(M).messages,s=>{return e.openBlock(),e.createElementBlock("div",{key:s.id,class:e.normalizeClass(["custom-message",`custom-message-${s.sender}`,{"custom-handoff-message":le(s.text)}])},[e.createElementVNode("div",{class:e.normalizeClass(["custom-message-content",{"custom-handoff-content":le(s.text)}]),innerHTML:e.unref(t.safeLinkifyText)(s.text).replace(/\n/g,"<br>")},null,10,v),s.richContent&&Array.isArray(s.richContent)&&s.richContent.length>0?(e.openBlock(),e.createElementBlock("div",I,[(e.openBlock(!0),e.createElementBlock(e.Fragment,null,e.renderList(s.richContent,(t,s)=>(e.openBlock(),e.createElementBlock(e.Fragment,{key:s},[Array.isArray(t)?(e.openBlock(!0),e.createElementBlock(e.Fragment,{key:1},e.renderList(t,(t,a)=>(e.openBlock(),e.createElementBlock(e.Fragment,{key:`${s}-${a}`},["chips"===t.type&&t.options?(e.openBlock(),e.createElementBlock("div",b,[(e.openBlock(!0),e.createElementBlock(e.Fragment,null,e.renderList(t.options,(t,s)=>(e.openBlock(),e.createElementBlock("button",{key:s,class:"custom-chip-button",type:"button",onClick:e=>ce(t.text,t.payload)},e.toDisplayString(t.text),9,E))),128))])):e.createCommentVNode("",!0)],64))),128)):(e.openBlock(),e.createElementBlock(e.Fragment,{key:0},["chips"===t.type&&t.options?(e.openBlock(),e.createElementBlock("div",k,[(e.openBlock(!0),e.createElementBlock(e.Fragment,null,e.renderList(t.options,(t,s)=>(e.openBlock(),e.createElementBlock("button",{key:s,class:"custom-chip-button",type:"button",onClick:e=>ce(t.text,t.payload)},e.toDisplayString(t.text),9,C))),128))])):e.createCommentVNode("",!0)],64))],64))),128))])):e.createCommentVNode("",!0),e.createElementVNode("div",T,e.toDisplayString((a=s.timestamp,a.toLocaleTimeString([],{hour:"2-digit",minute:"2-digit"}))),1)],2);var a}),128)),e.unref(M).isLoading?(e.openBlock(),e.createElementBlock("div",_,[...a[4]||(a[4]=[e.createElementVNode("div",{class:"custom-typing-indicator"},[e.createElementVNode("span"),e.createElementVNode("span"),e.createElementVNode("span")],-1)])])):e.createCommentVNode("",!0),e.unref(te)?(e.openBlock(),e.createElementBlock("div",V,[...a[5]||(a[5]=[e.createElementVNode("div",{class:"custom-typing-indicator"},[e.createElementVNode("span"),e.createElementVNode("span"),e.createElementVNode("span")],-1),e.createElementVNode("div",{class:"custom-message-content"}," Connecting to agent... ",-1)])])):e.createCommentVNode("",!0),"human"===e.unref(M).chatMode&&e.unref(H)?(e.openBlock(),e.createElementBlock("div",N,[...a[6]||(a[6]=[e.createElementVNode("span",{class:"custom-typing-dots"},[e.createElementVNode("span"),e.createElementVNode("span"),e.createElementVNode("span")],-1),e.createElementVNode("span",{class:"custom-typing-text"},"Agent is typing...",-1)])])):e.createCommentVNode("",!0),e.createElementVNode("div",{ref_key:"messagesEndRef",ref:K},null,512)],512),e.createElementVNode("form",{class:"custom-chat-input-form",onSubmit:e.withModifiers(ie,["prevent"])},[e.createElementVNode("input",{type:"text",class:"custom-chat-input",value:e.unref(M).inputValue,onInput:oe,placeholder:X.value.inputPlaceholder,disabled:e.unref(M).isLoading||Z.value||ee.value},null,40,B),e.createElementVNode("button",{type:"submit",class:"custom-chat-send-btn",disabled:!e.unref(M).inputValue.trim()||e.unref(M).isLoading||Z.value||ee.value},[...a[7]||(a[7]=[e.createElementVNode("svg",{width:"20",height:"20",viewBox:"0 0 24 24",fill:"none",stroke:"currentColor","stroke-width":"2","stroke-linecap":"round","stroke-linejoin":"round"},[e.createElementVNode("line",{x1:"22",y1:"2",x2:"11",y2:"13"}),e.createElementVNode("polygon",{points:"22 2 15 22 11 13 2 9 22 2"})],-1)])],8,D)],32)])):e.createCommentVNode("",!0)],16))}}),[["__scopeId","data-v-11671761"]]);exports.ChatWidgetComponent=A,exports.WidgetStateManager=s,exports.useChatWidget=a;
2
+ //# sourceMappingURL=ChatWidget-PcqRrOmi.cjs.map