@om_patel_26/chat-widget 1.0.1

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 (203) hide show
  1. package/README.md +276 -0
  2. package/dist/_virtual/_plugin-vue_export-helper.cjs.js +2 -0
  3. package/dist/_virtual/_plugin-vue_export-helper.cjs.js.map +1 -0
  4. package/dist/_virtual/_plugin-vue_export-helper.esm.js +11 -0
  5. package/dist/_virtual/_plugin-vue_export-helper.esm.js.map +1 -0
  6. package/dist/adapters/vue/index.d.ts +7 -0
  7. package/dist/adapters/vue/index.d.ts.map +1 -0
  8. package/dist/adapters/vue/useChatMode.d.ts +21 -0
  9. package/dist/adapters/vue/useChatMode.d.ts.map +1 -0
  10. package/dist/components/ChatWidget.d.ts +43 -0
  11. package/dist/components/ChatWidget.d.ts.map +1 -0
  12. package/dist/components/ChatWidget.vue.cjs.js +2 -0
  13. package/dist/components/ChatWidget.vue.cjs.js.map +1 -0
  14. package/dist/components/ChatWidget.vue.cjs2.js +2 -0
  15. package/dist/components/ChatWidget.vue.cjs2.js.map +1 -0
  16. package/dist/components/ChatWidget.vue.esm.js +8 -0
  17. package/dist/components/ChatWidget.vue.esm.js.map +1 -0
  18. package/dist/components/ChatWidget.vue.esm2.js +331 -0
  19. package/dist/components/ChatWidget.vue.esm2.js.map +1 -0
  20. package/dist/composables/useChatWidget.cjs.js +2 -0
  21. package/dist/composables/useChatWidget.cjs.js.map +1 -0
  22. package/dist/composables/useChatWidget.d.ts +34 -0
  23. package/dist/composables/useChatWidget.d.ts.map +1 -0
  24. package/dist/composables/useChatWidget.esm.js +72 -0
  25. package/dist/composables/useChatWidget.esm.js.map +1 -0
  26. package/dist/core/stateManager.cjs.js +2 -0
  27. package/dist/core/stateManager.cjs.js.map +1 -0
  28. package/dist/core/stateManager.d.ts +136 -0
  29. package/dist/core/stateManager.d.ts.map +1 -0
  30. package/dist/core/stateManager.esm.js +907 -0
  31. package/dist/core/stateManager.esm.js.map +1 -0
  32. package/dist/core/types.d.ts +66 -0
  33. package/dist/core/types.d.ts.map +1 -0
  34. package/dist/entry/next.d.ts +9 -0
  35. package/dist/entry/next.d.ts.map +1 -0
  36. package/dist/entry/nuxt.d.ts +10 -0
  37. package/dist/entry/nuxt.d.ts.map +1 -0
  38. package/dist/entry/react.d.ts +10 -0
  39. package/dist/entry/react.d.ts.map +1 -0
  40. package/dist/entry/vanilla.d.ts +33 -0
  41. package/dist/entry/vanilla.d.ts.map +1 -0
  42. package/dist/entry/vite.d.ts +11 -0
  43. package/dist/entry/vite.d.ts.map +1 -0
  44. package/dist/entry/vue.d.ts +11 -0
  45. package/dist/entry/vue.d.ts.map +1 -0
  46. package/dist/hooks/useChatMode.d.ts +17 -0
  47. package/dist/hooks/useChatMode.d.ts.map +1 -0
  48. package/dist/index.cjs.js +2 -0
  49. package/dist/index.cjs.js.map +1 -0
  50. package/dist/index.d.ts +14 -0
  51. package/dist/index.d.ts.map +1 -0
  52. package/dist/index.esm.js +25 -0
  53. package/dist/index.esm.js.map +1 -0
  54. package/dist/node_modules/jose/dist/browser/jws/compact/sign.cjs.js +2 -0
  55. package/dist/node_modules/jose/dist/browser/jws/compact/sign.cjs.js.map +1 -0
  56. package/dist/node_modules/jose/dist/browser/jws/compact/sign.esm.js +21 -0
  57. package/dist/node_modules/jose/dist/browser/jws/compact/sign.esm.js.map +1 -0
  58. package/dist/node_modules/jose/dist/browser/jws/flattened/sign.cjs.js +2 -0
  59. package/dist/node_modules/jose/dist/browser/jws/flattened/sign.cjs.js.map +1 -0
  60. package/dist/node_modules/jose/dist/browser/jws/flattened/sign.esm.js +84 -0
  61. package/dist/node_modules/jose/dist/browser/jws/flattened/sign.esm.js.map +1 -0
  62. package/dist/node_modules/jose/dist/browser/jwt/produce.cjs.js +2 -0
  63. package/dist/node_modules/jose/dist/browser/jwt/produce.cjs.js.map +1 -0
  64. package/dist/node_modules/jose/dist/browser/jwt/produce.esm.js +72 -0
  65. package/dist/node_modules/jose/dist/browser/jwt/produce.esm.js.map +1 -0
  66. package/dist/node_modules/jose/dist/browser/jwt/sign.cjs.js +2 -0
  67. package/dist/node_modules/jose/dist/browser/jwt/sign.cjs.js.map +1 -0
  68. package/dist/node_modules/jose/dist/browser/jwt/sign.esm.js +22 -0
  69. package/dist/node_modules/jose/dist/browser/jwt/sign.esm.js.map +1 -0
  70. package/dist/node_modules/jose/dist/browser/key/import.cjs.js +2 -0
  71. package/dist/node_modules/jose/dist/browser/key/import.cjs.js.map +1 -0
  72. package/dist/node_modules/jose/dist/browser/key/import.esm.js +11 -0
  73. package/dist/node_modules/jose/dist/browser/key/import.esm.js.map +1 -0
  74. package/dist/node_modules/jose/dist/browser/lib/buffer_utils.cjs.js +2 -0
  75. package/dist/node_modules/jose/dist/browser/lib/buffer_utils.cjs.js.map +1 -0
  76. package/dist/node_modules/jose/dist/browser/lib/buffer_utils.esm.js +18 -0
  77. package/dist/node_modules/jose/dist/browser/lib/buffer_utils.esm.js.map +1 -0
  78. package/dist/node_modules/jose/dist/browser/lib/check_key_type.cjs.js +2 -0
  79. package/dist/node_modules/jose/dist/browser/lib/check_key_type.cjs.js.map +1 -0
  80. package/dist/node_modules/jose/dist/browser/lib/check_key_type.esm.js +77 -0
  81. package/dist/node_modules/jose/dist/browser/lib/check_key_type.esm.js.map +1 -0
  82. package/dist/node_modules/jose/dist/browser/lib/crypto_key.cjs.js +2 -0
  83. package/dist/node_modules/jose/dist/browser/lib/crypto_key.cjs.js.map +1 -0
  84. package/dist/node_modules/jose/dist/browser/lib/crypto_key.esm.js +101 -0
  85. package/dist/node_modules/jose/dist/browser/lib/crypto_key.esm.js.map +1 -0
  86. package/dist/node_modules/jose/dist/browser/lib/epoch.cjs.js +2 -0
  87. package/dist/node_modules/jose/dist/browser/lib/epoch.cjs.js.map +1 -0
  88. package/dist/node_modules/jose/dist/browser/lib/epoch.esm.js +5 -0
  89. package/dist/node_modules/jose/dist/browser/lib/epoch.esm.js.map +1 -0
  90. package/dist/node_modules/jose/dist/browser/lib/invalid_key_input.cjs.js +2 -0
  91. package/dist/node_modules/jose/dist/browser/lib/invalid_key_input.cjs.js.map +1 -0
  92. package/dist/node_modules/jose/dist/browser/lib/invalid_key_input.esm.js +32 -0
  93. package/dist/node_modules/jose/dist/browser/lib/invalid_key_input.esm.js.map +1 -0
  94. package/dist/node_modules/jose/dist/browser/lib/is_disjoint.cjs.js +2 -0
  95. package/dist/node_modules/jose/dist/browser/lib/is_disjoint.cjs.js.map +1 -0
  96. package/dist/node_modules/jose/dist/browser/lib/is_disjoint.esm.js +25 -0
  97. package/dist/node_modules/jose/dist/browser/lib/is_disjoint.esm.js.map +1 -0
  98. package/dist/node_modules/jose/dist/browser/lib/is_jwk.cjs.js +2 -0
  99. package/dist/node_modules/jose/dist/browser/lib/is_jwk.cjs.js.map +1 -0
  100. package/dist/node_modules/jose/dist/browser/lib/is_jwk.esm.js +20 -0
  101. package/dist/node_modules/jose/dist/browser/lib/is_jwk.esm.js.map +1 -0
  102. package/dist/node_modules/jose/dist/browser/lib/is_object.cjs.js +2 -0
  103. package/dist/node_modules/jose/dist/browser/lib/is_object.cjs.js.map +1 -0
  104. package/dist/node_modules/jose/dist/browser/lib/is_object.esm.js +20 -0
  105. package/dist/node_modules/jose/dist/browser/lib/is_object.esm.js.map +1 -0
  106. package/dist/node_modules/jose/dist/browser/lib/secs.cjs.js +2 -0
  107. package/dist/node_modules/jose/dist/browser/lib/secs.cjs.js.map +1 -0
  108. package/dist/node_modules/jose/dist/browser/lib/secs.esm.js +59 -0
  109. package/dist/node_modules/jose/dist/browser/lib/secs.esm.js.map +1 -0
  110. package/dist/node_modules/jose/dist/browser/lib/validate_crit.cjs.js +2 -0
  111. package/dist/node_modules/jose/dist/browser/lib/validate_crit.cjs.js.map +1 -0
  112. package/dist/node_modules/jose/dist/browser/lib/validate_crit.esm.js +34 -0
  113. package/dist/node_modules/jose/dist/browser/lib/validate_crit.esm.js.map +1 -0
  114. package/dist/node_modules/jose/dist/browser/runtime/asn1.cjs.js +2 -0
  115. package/dist/node_modules/jose/dist/browser/runtime/asn1.cjs.js.map +1 -0
  116. package/dist/node_modules/jose/dist/browser/runtime/asn1.esm.js +103 -0
  117. package/dist/node_modules/jose/dist/browser/runtime/asn1.esm.js.map +1 -0
  118. package/dist/node_modules/jose/dist/browser/runtime/base64url.cjs.js +2 -0
  119. package/dist/node_modules/jose/dist/browser/runtime/base64url.cjs.js.map +1 -0
  120. package/dist/node_modules/jose/dist/browser/runtime/base64url.esm.js +43 -0
  121. package/dist/node_modules/jose/dist/browser/runtime/base64url.esm.js.map +1 -0
  122. package/dist/node_modules/jose/dist/browser/runtime/check_key_length.cjs.js +2 -0
  123. package/dist/node_modules/jose/dist/browser/runtime/check_key_length.cjs.js.map +1 -0
  124. package/dist/node_modules/jose/dist/browser/runtime/check_key_length.esm.js +12 -0
  125. package/dist/node_modules/jose/dist/browser/runtime/check_key_length.esm.js.map +1 -0
  126. package/dist/node_modules/jose/dist/browser/runtime/get_sign_verify_key.cjs.js +2 -0
  127. package/dist/node_modules/jose/dist/browser/runtime/get_sign_verify_key.cjs.js.map +1 -0
  128. package/dist/node_modules/jose/dist/browser/runtime/get_sign_verify_key.esm.js +25 -0
  129. package/dist/node_modules/jose/dist/browser/runtime/get_sign_verify_key.esm.js.map +1 -0
  130. package/dist/node_modules/jose/dist/browser/runtime/is_key_like.cjs.js +2 -0
  131. package/dist/node_modules/jose/dist/browser/runtime/is_key_like.cjs.js.map +1 -0
  132. package/dist/node_modules/jose/dist/browser/runtime/is_key_like.esm.js +13 -0
  133. package/dist/node_modules/jose/dist/browser/runtime/is_key_like.esm.js.map +1 -0
  134. package/dist/node_modules/jose/dist/browser/runtime/jwk_to_key.cjs.js +2 -0
  135. package/dist/node_modules/jose/dist/browser/runtime/jwk_to_key.cjs.js.map +1 -0
  136. package/dist/node_modules/jose/dist/browser/runtime/jwk_to_key.esm.js +107 -0
  137. package/dist/node_modules/jose/dist/browser/runtime/jwk_to_key.esm.js.map +1 -0
  138. package/dist/node_modules/jose/dist/browser/runtime/normalize_key.cjs.js +2 -0
  139. package/dist/node_modules/jose/dist/browser/runtime/normalize_key.cjs.js.map +1 -0
  140. package/dist/node_modules/jose/dist/browser/runtime/normalize_key.esm.js +71 -0
  141. package/dist/node_modules/jose/dist/browser/runtime/normalize_key.esm.js.map +1 -0
  142. package/dist/node_modules/jose/dist/browser/runtime/sign.cjs.js +2 -0
  143. package/dist/node_modules/jose/dist/browser/runtime/sign.cjs.js.map +1 -0
  144. package/dist/node_modules/jose/dist/browser/runtime/sign.esm.js +14 -0
  145. package/dist/node_modules/jose/dist/browser/runtime/sign.esm.js.map +1 -0
  146. package/dist/node_modules/jose/dist/browser/runtime/subtle_dsa.cjs.js +2 -0
  147. package/dist/node_modules/jose/dist/browser/runtime/subtle_dsa.cjs.js.map +1 -0
  148. package/dist/node_modules/jose/dist/browser/runtime/subtle_dsa.esm.js +32 -0
  149. package/dist/node_modules/jose/dist/browser/runtime/subtle_dsa.esm.js.map +1 -0
  150. package/dist/node_modules/jose/dist/browser/runtime/webcrypto.cjs.js +2 -0
  151. package/dist/node_modules/jose/dist/browser/runtime/webcrypto.cjs.js.map +1 -0
  152. package/dist/node_modules/jose/dist/browser/runtime/webcrypto.esm.js +7 -0
  153. package/dist/node_modules/jose/dist/browser/runtime/webcrypto.esm.js.map +1 -0
  154. package/dist/node_modules/jose/dist/browser/util/errors.cjs.js +2 -0
  155. package/dist/node_modules/jose/dist/browser/util/errors.cjs.js.map +1 -0
  156. package/dist/node_modules/jose/dist/browser/util/errors.esm.js +131 -0
  157. package/dist/node_modules/jose/dist/browser/util/errors.esm.js.map +1 -0
  158. package/dist/nuxt.cjs.js +2 -0
  159. package/dist/nuxt.cjs.js.map +1 -0
  160. package/dist/nuxt.esm.js +8 -0
  161. package/dist/nuxt.esm.js.map +1 -0
  162. package/dist/services/chatService.cjs.js +2 -0
  163. package/dist/services/chatService.cjs.js.map +1 -0
  164. package/dist/services/chatService.d.ts +144 -0
  165. package/dist/services/chatService.d.ts.map +1 -0
  166. package/dist/services/chatService.esm.js +482 -0
  167. package/dist/services/chatService.esm.js.map +1 -0
  168. package/dist/services/dialogflowClient.cjs.js +2 -0
  169. package/dist/services/dialogflowClient.cjs.js.map +1 -0
  170. package/dist/services/dialogflowClient.d.ts +36 -0
  171. package/dist/services/dialogflowClient.d.ts.map +1 -0
  172. package/dist/services/dialogflowClient.esm.js +282 -0
  173. package/dist/services/dialogflowClient.esm.js.map +1 -0
  174. package/dist/services/sessionManager.cjs.js +2 -0
  175. package/dist/services/sessionManager.cjs.js.map +1 -0
  176. package/dist/services/sessionManager.d.ts +13 -0
  177. package/dist/services/sessionManager.d.ts.map +1 -0
  178. package/dist/services/sessionManager.esm.js +48 -0
  179. package/dist/services/sessionManager.esm.js.map +1 -0
  180. package/dist/styles.css +0 -0
  181. package/dist/types.d.ts +5 -0
  182. package/dist/types.d.ts.map +1 -0
  183. package/dist/utils/dialogflowHandler.d.ts +31 -0
  184. package/dist/utils/dialogflowHandler.d.ts.map +1 -0
  185. package/dist/utils/frameworkDetector.d.ts +17 -0
  186. package/dist/utils/frameworkDetector.d.ts.map +1 -0
  187. package/dist/utils/sanitize.cjs.js +2 -0
  188. package/dist/utils/sanitize.cjs.js.map +1 -0
  189. package/dist/utils/sanitize.d.ts +25 -0
  190. package/dist/utils/sanitize.d.ts.map +1 -0
  191. package/dist/utils/sanitize.esm.js +57 -0
  192. package/dist/utils/sanitize.esm.js.map +1 -0
  193. package/dist/utils/ssr.cjs.js +2 -0
  194. package/dist/utils/ssr.cjs.js.map +1 -0
  195. package/dist/utils/ssr.d.ts +35 -0
  196. package/dist/utils/ssr.d.ts.map +1 -0
  197. package/dist/utils/ssr.esm.js +48 -0
  198. package/dist/utils/ssr.esm.js.map +1 -0
  199. package/dist/vue.cjs.js +2 -0
  200. package/dist/vue.cjs.js.map +1 -0
  201. package/dist/vue.esm.js +10 -0
  202. package/dist/vue.esm.js.map +1 -0
  203. package/package.json +145 -0
package/README.md ADDED
@@ -0,0 +1,276 @@
1
+ # BlockSpark Chat Widget
2
+
3
+ A reusable React chat widget component that connects directly with Dialogflow CX - no backend API required!
4
+
5
+ ## Installation
6
+
7
+ ### Option 1: Install from Local Path (Recommended for Development)
8
+
9
+ ```bash
10
+ # In your website project directory
11
+ npm install /path/to/blockspark-chat-widget
12
+ # or
13
+ npm install ../blockspark-chat-widget
14
+ ```
15
+
16
+ ### Option 2: Use npm link (For Development)
17
+
18
+ ```bash
19
+ # In the blockspark-chat-widget directory
20
+ npm link
21
+
22
+ # In your website project directory
23
+ npm link @blockspark/chat-widget
24
+ ```
25
+
26
+ ### Option 3: Publish to npm (For Production)
27
+
28
+ ```bash
29
+ # Build the library first
30
+ npm run build
31
+
32
+ # Publish to npm (make sure you're logged in)
33
+ npm publish
34
+ ```
35
+
36
+ Then install in your project:
37
+ ```bash
38
+ npm install @blockspark/chat-widget
39
+ ```
40
+
41
+ ## Usage
42
+
43
+ ### Vue.js Usage (Quick Start)
44
+
45
+ ```bash
46
+ # Install
47
+ npm install @blockspark/chat-widget
48
+ ```
49
+
50
+ ```vue
51
+ <template>
52
+ <ChatWidget
53
+ :df-project-id="'your-project-id'"
54
+ :df-agent-id="'your-agent-id'"
55
+ :service-account-key="serviceAccountKey"
56
+ />
57
+ </template>
58
+
59
+ <script setup>
60
+ import ChatWidget from '@blockspark/chat-widget/vue';
61
+ import '@blockspark/chat-widget/dist/styles.css';
62
+ import serviceAccountKey from './service-account-key.json';
63
+ </script>
64
+ ```
65
+
66
+ **📚 For detailed Vue.js setup guide, see [VUE_INSTALLATION_GUIDE.md](./VUE_INSTALLATION_GUIDE.md)**
67
+
68
+ ---
69
+
70
+ ### React/Next.js Usage
71
+
72
+ ### Basic Usage
73
+
74
+ ```tsx
75
+ import ChatWidget from '@blockspark/chat-widget';
76
+ import '@blockspark/chat-widget/dist/styles.css';
77
+
78
+ // Load your Google Cloud service account key
79
+ import serviceAccountKey from './path/to/service-account-key.json';
80
+
81
+ function App() {
82
+ return (
83
+ <div>
84
+ <ChatWidget
85
+ dfProjectId="your-project-id"
86
+ dfLocation="us-central1"
87
+ dfAgentId="your-agent-id"
88
+ serviceAccountKey={serviceAccountKey}
89
+ languageCode="en"
90
+ />
91
+ </div>
92
+ );
93
+ }
94
+ ```
95
+
96
+ ### Using Access Token (Alternative)
97
+
98
+ If you prefer to manage authentication yourself:
99
+
100
+ ```tsx
101
+ import ChatWidget from '@blockspark/chat-widget';
102
+ import '@blockspark/chat-widget/dist/styles.css';
103
+
104
+ function App() {
105
+ const [accessToken, setAccessToken] = useState<string>('');
106
+
107
+ // Get access token from your backend or OAuth flow
108
+ useEffect(() => {
109
+ // Your token fetching logic here
110
+ fetchAccessToken().then(setAccessToken);
111
+ }, []);
112
+
113
+ return (
114
+ <ChatWidget
115
+ dfProjectId="your-project-id"
116
+ dfLocation="us-central1"
117
+ dfAgentId="your-agent-id"
118
+ accessToken={accessToken}
119
+ languageCode="en"
120
+ />
121
+ );
122
+ }
123
+ ```
124
+
125
+ ### With Custom Configuration
126
+
127
+ ```tsx
128
+ import ChatWidget from '@blockspark/chat-widget';
129
+ import '@blockspark/chat-widget/dist/styles.css';
130
+ import serviceAccountKey from './service-account-key.json';
131
+
132
+ function App() {
133
+ return (
134
+ <ChatWidget
135
+ dfProjectId="your-project-id"
136
+ dfLocation="us-central1"
137
+ dfAgentId="your-agent-id"
138
+ serviceAccountKey={serviceAccountKey}
139
+ languageCode="en"
140
+ title="💬 My Chat Assistant"
141
+ subtitle="How can I help you?"
142
+ welcomeTitle="👋 Welcome!"
143
+ welcomeMessage="I'm here to help you with any questions."
144
+ welcomeCta="Start chatting"
145
+ showWelcomePopup={true}
146
+ welcomePopupDelay={2000}
147
+ inputPlaceholder="Type your message..."
148
+ emptyStateMessage="Hi! How can I help you today?"
149
+ debug={false}
150
+ />
151
+ );
152
+ }
153
+ ```
154
+
155
+ ### Using Environment Variables
156
+
157
+ You can configure the backend API URLs for Human Support Mode using environment variables. Create a `.env` file in the project root:
158
+
159
+ ```bash
160
+ # .env file
161
+ REACT_APP_BACKEND_BASE_URL=http://localhost:8012
162
+ REACT_APP_BACKEND_WS_URL=ws://localhost:8012
163
+ ```
164
+
165
+ Or pass them as props:
166
+
167
+ ```tsx
168
+ <ChatWidget
169
+ dfProjectId="your-project-id"
170
+ dfAgentId="your-agent-id"
171
+ serviceAccountKey={serviceAccountKey}
172
+ backendBaseUrl="http://your-backend-url:8012"
173
+ backendWsUrl="ws://your-backend-url:8012"
174
+ />
175
+ ```
176
+
177
+ **Note**: Props take precedence over environment variables.
178
+
179
+ ### Human Support Mode
180
+
181
+ The widget supports automatic handoff from bot to human agents. When Dialogflow returns `{"handoff": true}`, the widget will:
182
+
183
+ 1. Switch from Bot Mode to Human Support Mode
184
+ 2. Create a support chat session
185
+ 3. Connect via WebSocket for real-time messaging
186
+ 4. Load message history
187
+ 5. Route messages to the backend API instead of Dialogflow
188
+
189
+ The widget displays mode indicators and connection status in the chat header.
190
+
191
+ ### Import Types (TypeScript)
192
+
193
+ ```tsx
194
+ import ChatWidget, { ChatWidgetProps, DialogflowConfig } from '@blockspark/chat-widget';
195
+ ```
196
+
197
+ ## Props
198
+
199
+ | Prop | Type | Required | Default | Description |
200
+ |------|------|----------|---------|-------------|
201
+ | `dfProjectId` | `string` | Yes | - | Dialogflow project ID |
202
+ | `dfLocation` | `string` | No | `"us-central1"` | Dialogflow location |
203
+ | `dfAgentId` | `string` | Yes | - | Dialogflow agent ID |
204
+ | `serviceAccountKey` | `object` | Yes* | - | Google Cloud service account key JSON object |
205
+ | `accessToken` | `string` | Yes* | - | Access token (alternative to serviceAccountKey) |
206
+ | `languageCode` | `string` | No | `"en"` | Language code for Dialogflow |
207
+ | `title` | `string` | No | `"💬 BlockSpark AI Assistant"` | Chat widget title |
208
+ | `subtitle` | `string` | No | `"We're here to help"` | Chat widget subtitle |
209
+ | `welcomeTitle` | `string` | No | `"👋 Welcome to Blockspark"` | Welcome popup title |
210
+ | `welcomeMessage` | `string` | No | `"My name is BlockSpark..."` | Welcome popup message |
211
+ | `welcomeCta` | `string` | No | `"💬 Click here to start chatting!"` | Welcome popup CTA text |
212
+ | `showWelcomePopup` | `boolean` | No | `true` | Whether to show welcome popup |
213
+ | `welcomePopupDelay` | `number` | No | `1500` | Delay before showing welcome popup (ms) |
214
+ | `fallbackWelcomeMessage` | `string` | No | `"Hello! I'm BlockSpark..."` | Fallback message if API fails |
215
+ | `inputPlaceholder` | `string` | No | `"Type your message..."` | Input field placeholder |
216
+ | `emptyStateMessage` | `string` | No | `"Hi! I'm BlockSpark..."` | Empty state message |
217
+ | `debug` | `boolean` | No | `false` | Enable debug logging |
218
+ | `backendBaseUrl` | `string` | No | `process.env.REACT_APP_BACKEND_BASE_URL` or `"http://localhost:8012"` | Backend REST API base URL for Human Support Mode |
219
+ | `backendWsUrl` | `string` | No | `process.env.REACT_APP_BACKEND_WS_URL` or `"ws://localhost:8012"` | Backend WebSocket URL for Human Support Mode |
220
+
221
+ \* Either `serviceAccountKey` or `accessToken` must be provided.
222
+
223
+ ## How It Works
224
+
225
+ The widget connects **directly** to Dialogflow CX using the REST API - no backend required!
226
+
227
+ 1. **Authentication**: Uses Google Cloud service account key to generate OAuth2 access tokens
228
+ 2. **Session Management**: Creates and manages Dialogflow sessions automatically
229
+ 3. **Message Handling**: Sends messages directly to Dialogflow and displays responses
230
+ 4. **Rich Content**: Supports Dialogflow rich content (chips, cards, etc.)
231
+
232
+ ## Requirements
233
+
234
+ - React 16.8.0 or higher
235
+ - React DOM 16.8.0 or higher
236
+ - Google Cloud service account with Dialogflow API enabled
237
+ - Dialogflow CX agent
238
+
239
+ ## Getting Your Service Account Key
240
+
241
+ 1. Go to [Google Cloud Console](https://console.cloud.google.com/)
242
+ 2. Select your project
243
+ 3. Navigate to **IAM & Admin** > **Service Accounts**
244
+ 4. Create a new service account or select an existing one
245
+ 5. Create a JSON key and download it
246
+ 6. Enable **Dialogflow API** for your project
247
+ 7. Grant the service account **Dialogflow API User** role
248
+
249
+ ## Security Warning ⚠️
250
+
251
+ **Important**: Service account keys contain sensitive credentials.
252
+
253
+ - **For Development**: You can import the key directly (as shown in examples)
254
+ - **For Production**:
255
+ - **DO NOT** expose service account keys in client-side code
256
+ - Use a backend proxy to handle authentication
257
+ - Or use OAuth2 flow to get access tokens securely
258
+ - Consider using restricted service account keys with minimal permissions
259
+
260
+ ## Development
261
+
262
+ ```bash
263
+ # Install dependencies
264
+ npm install
265
+
266
+ # Build for production
267
+ npm run build
268
+
269
+ # Watch mode for development
270
+ npm run dev
271
+ ```
272
+
273
+ ## License
274
+
275
+ MIT
276
+ export NPM_TOKEN=your_token_here
@@ -0,0 +1,2 @@
1
+ "use strict";Object.defineProperties(exports,{__esModule:{value:!0},[Symbol.toStringTag]:{value:"Module"}});exports.default=(e,t)=>{const o=e.__vccOpts||e;for(const[r,s]of t)o[r]=s;return o};
2
+ //# sourceMappingURL=_plugin-vue_export-helper.cjs.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"_plugin-vue_export-helper.cjs.js","sources":[],"sourcesContent":[],"names":[],"mappings":""}
@@ -0,0 +1,11 @@
1
+ const _export_sfc = (sfc, props) => {
2
+ const target = sfc.__vccOpts || sfc;
3
+ for (const [key, val] of props) {
4
+ target[key] = val;
5
+ }
6
+ return target;
7
+ };
8
+ export {
9
+ _export_sfc as default
10
+ };
11
+ //# sourceMappingURL=_plugin-vue_export-helper.esm.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"_plugin-vue_export-helper.esm.js","sources":[],"sourcesContent":[],"names":[],"mappings":";;;;;;;"}
@@ -0,0 +1,7 @@
1
+ /**
2
+ * Vue Adapter Entry Point
3
+ * Supports Vue 2.7+ and Vue 3.x
4
+ */
5
+ export { default } from './ChatWidget.vue';
6
+ export { default as ChatWidget } from './ChatWidget.vue';
7
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/adapters/vue/index.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,OAAO,EAAE,OAAO,EAAE,MAAM,kBAAkB,CAAC;AAC3C,OAAO,EAAE,OAAO,IAAI,UAAU,EAAE,MAAM,kBAAkB,CAAC"}
@@ -0,0 +1,21 @@
1
+ /**
2
+ * Vue Composable for Chat Mode Management
3
+ * Equivalent to React's useChatMode hook
4
+ */
5
+ import type { ChatResponse } from '../../services/dialogflowClient';
6
+ export type ChatMode = 'BOT' | 'HUMAN';
7
+ export interface UseChatModeReturn {
8
+ currentMode: ChatMode;
9
+ switchToHumanMode: () => void;
10
+ switchToBotMode: () => void;
11
+ isHandoffTriggered: (dialogflowResponse: ChatResponse) => boolean;
12
+ chatId: string | null;
13
+ sessionId: string | null;
14
+ setChatId: (id: string | null) => void;
15
+ setSessionId: (id: string | null) => void;
16
+ }
17
+ /**
18
+ * Vue composable to manage chat mode (BOT or HUMAN)
19
+ */
20
+ export declare function useChatMode(): UseChatModeReturn;
21
+ //# sourceMappingURL=useChatMode.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"useChatMode.d.ts","sourceRoot":"","sources":["../../../src/adapters/vue/useChatMode.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAGH,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,iCAAiC,CAAC;AAEpE,MAAM,MAAM,QAAQ,GAAG,KAAK,GAAG,OAAO,CAAC;AAMvC,MAAM,WAAW,iBAAiB;IAChC,WAAW,EAAE,QAAQ,CAAC;IACtB,iBAAiB,EAAE,MAAM,IAAI,CAAC;IAC9B,eAAe,EAAE,MAAM,IAAI,CAAC;IAC5B,kBAAkB,EAAE,CAAC,kBAAkB,EAAE,YAAY,KAAK,OAAO,CAAC;IAClE,MAAM,EAAE,MAAM,GAAG,IAAI,CAAC;IACtB,SAAS,EAAE,MAAM,GAAG,IAAI,CAAC;IACzB,SAAS,EAAE,CAAC,EAAE,EAAE,MAAM,GAAG,IAAI,KAAK,IAAI,CAAC;IACvC,YAAY,EAAE,CAAC,EAAE,EAAE,MAAM,GAAG,IAAI,KAAK,IAAI,CAAC;CAC3C;AAED;;GAEG;AACH,wBAAgB,WAAW,IAAI,iBAAiB,CAqF/C"}
@@ -0,0 +1,43 @@
1
+ import "../styles/chatWidget.css";
2
+ export interface ChatWidgetProps {
3
+ /** Custom title for the chat widget */
4
+ title?: string;
5
+ /** Custom subtitle for the chat widget */
6
+ subtitle?: string;
7
+ /** Welcome popup title */
8
+ welcomeTitle?: string;
9
+ /** Welcome popup message */
10
+ welcomeMessage?: string;
11
+ /** Welcome popup CTA text */
12
+ welcomeCta?: string;
13
+ /** Whether to show the welcome popup */
14
+ showWelcomePopup?: boolean;
15
+ /** Delay in milliseconds before showing welcome popup */
16
+ welcomePopupDelay?: number;
17
+ /** Fallback welcome message if API fails */
18
+ fallbackWelcomeMessage?: string;
19
+ /** Placeholder text for input field */
20
+ inputPlaceholder?: string;
21
+ /** Custom empty state message */
22
+ emptyStateMessage?: string;
23
+ /** Enable/disable debug logging */
24
+ debug?: boolean;
25
+ /** Dialogflow project ID */
26
+ dfProjectId?: string;
27
+ /** Dialogflow location (e.g., "us-central1") */
28
+ dfLocation?: string;
29
+ /** Dialogflow agent ID */
30
+ dfAgentId?: string;
31
+ /** Google Cloud service account key JSON object */
32
+ serviceAccountKey?: any;
33
+ /** Access token (alternative to serviceAccountKey) */
34
+ accessToken?: string;
35
+ /** Language code for Dialogflow */
36
+ languageCode?: string;
37
+ /** Backend API base URL (default: http://localhost:8012) */
38
+ backendBaseUrl?: string;
39
+ /** WebSocket URL (default: ws://localhost:8012) */
40
+ backendWsUrl?: string;
41
+ }
42
+ export default function ChatWidget({ title, subtitle, welcomeTitle, welcomeMessage, welcomeCta, showWelcomePopup: enableWelcomePopup, welcomePopupDelay, fallbackWelcomeMessage, inputPlaceholder, emptyStateMessage, debug, dfProjectId, dfLocation, dfAgentId, serviceAccountKey, accessToken, languageCode, backendBaseUrl, backendWsUrl, }: ChatWidgetProps): import("react/jsx-runtime").JSX.Element;
43
+ //# sourceMappingURL=ChatWidget.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"ChatWidget.d.ts","sourceRoot":"","sources":["../../src/components/ChatWidget.tsx"],"names":[],"mappings":"AAWA,OAAO,0BAA0B,CAAC;AAsBlC,MAAM,WAAW,eAAe;IAC9B,uCAAuC;IACvC,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,0CAA0C;IAC1C,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,0BAA0B;IAC1B,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,4BAA4B;IAC5B,cAAc,CAAC,EAAE,MAAM,CAAC;IACxB,6BAA6B;IAC7B,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,wCAAwC;IACxC,gBAAgB,CAAC,EAAE,OAAO,CAAC;IAC3B,yDAAyD;IACzD,iBAAiB,CAAC,EAAE,MAAM,CAAC;IAC3B,4CAA4C;IAC5C,sBAAsB,CAAC,EAAE,MAAM,CAAC;IAChC,uCAAuC;IACvC,gBAAgB,CAAC,EAAE,MAAM,CAAC;IAC1B,iCAAiC;IACjC,iBAAiB,CAAC,EAAE,MAAM,CAAC;IAC3B,mCAAmC;IACnC,KAAK,CAAC,EAAE,OAAO,CAAC;IAChB,4BAA4B;IAC5B,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,gDAAgD;IAChD,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,0BAA0B;IAC1B,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,mDAAmD;IACnD,iBAAiB,CAAC,EAAE,GAAG,CAAC;IACxB,sDAAsD;IACtD,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,mCAAmC;IACnC,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,4DAA4D;IAC5D,cAAc,CAAC,EAAE,MAAM,CAAC;IACxB,mDAAmD;IACnD,YAAY,CAAC,EAAE,MAAM,CAAC;CACvB;AAED,MAAM,CAAC,OAAO,UAAU,UAAU,CAAC,EACjC,KAAoC,EACpC,QAA+B,EAC/B,YAAyC,EACzC,cAAyE,EACzE,UAA+C,EAC/C,gBAAgB,EAAE,kBAAyB,EAC3C,iBAAwB,EACxB,sBAAwF,EACxF,gBAAyC,EACzC,iBAAgF,EAChF,KAAa,EACb,WAAW,EACX,UAA0B,EAC1B,SAAS,EACT,iBAAiB,EACjB,WAAW,EACX,YAAmB,EACnB,cAAc,EACd,YAAY,GACb,EAAE,eAAe,2CAm3CjB"}
@@ -0,0 +1,2 @@
1
+ "use strict";Object.defineProperties(exports,{__esModule:{value:!0},[Symbol.toStringTag]:{value:"Module"}});const e=require("./ChatWidget.vue.cjs2.js");;/* empty css */const t=require("../_virtual/_plugin-vue_export-helper.cjs.js").default(e.default,[["__scopeId","data-v-cbfcf702"]]);exports.default=t;
2
+ //# sourceMappingURL=ChatWidget.vue.cjs.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"ChatWidget.vue.cjs.js","sources":[],"sourcesContent":[],"names":[],"mappings":""}
@@ -0,0 +1,2 @@
1
+ "use strict";Object.defineProperties(exports,{__esModule:{value:!0},[Symbol.toStringTag]:{value:"Module"}});const e=require("vue"),t=require("../composables/useChatWidget.cjs.js"),o=require("../utils/sanitize.cjs.js"),a={class:"blockspark-chat-widget"},l={class:"blockspark-welcome-header"},n={class:"blockspark-welcome-title"},c={class:"blockspark-welcome-message"},s={class:"blockspark-welcome-cta"},r={key:2,class:"blockspark-chat-window"},i={class:"blockspark-chat-header"},p={class:"blockspark-chat-header-content"},k={class:"blockspark-chat-title"},d={class:"blockspark-chat-subtitle"},m={key:0,class:"blockspark-mode-indicator"},u={key:0,class:"blockspark-mode-badge"},g={key:1,class:"blockspark-agent-info"},b={class:"blockspark-agent-name"},h={key:2,class:"blockspark-mode-badge"},y={key:0,class:"blockspark-chat-empty"},E={class:"blockspark-message-content"},B=["innerHTML"],f={key:0,class:"blockspark-chips-container"},V={key:0,class:"blockspark-chips-group"},v=["onClick"],N={key:0,class:"blockspark-chips-group"},C=["onClick"],w={class:"blockspark-message-time"},M={key:1,class:"blockspark-message blockspark-message-bot"},S={key:2,class:"blockspark-agent-typing-indicator"},A=["value","placeholder","disabled"],x=["disabled"],I=e.defineComponent({__name:"ChatWidget",props:{dfProjectId:{},dfLocation:{},dfAgentId:{},serviceAccountKey:{},accessToken:{},languageCode:{},backendBaseUrl:{},backendWsUrl:{},title:{default:"💬 BlockSpark AI Assistant"},subtitle:{default:"We're here to help"},welcomeTitle:{default:"👋 Welcome to BlockSpark"},welcomeMessage:{default:"My name is BlockSpark 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 BlockSpark AI Assistant. How can I help you today?"},inputPlaceholder:{default:"Type your message..."},emptyStateMessage:{default:"Hi! I'm BlockSpark AI Assistant. How can I help you today?"},debug:{type:Boolean,default:!1}},setup(I){const L=I,{state:D,isOpen:T,messages:W,isLoading:P,error:j,chatMode:F,wsConnected:H,agentTyping:O,currentAgent:_,openChat:z,closeChat:q,sendMessage:$,toggleChat:U,setInputValue:K,clearError:R,manager:G}=t.useChatWidget(L),J=e.ref(null),Q=e.ref(null),X=e.computed(()=>L);e.watch(()=>W.value.length,()=>{e.nextTick(()=>{J.value?.scrollIntoView({behavior:"smooth"})})});const Y=async()=>{await z()},Z=()=>{q()},ee=()=>{G.closeWelcomePopup()},te=e=>{const t=e.target;K(t.value)},oe=async e=>{e.preventDefault(),D.value.inputValue.trim()&&await $(D.value.inputValue)},ae=async(e,t)=>{const o=e||t||"";await $(o)};return e.onMounted(()=>{X.value.showWelcomePopup&&"undefined"!=typeof window&&G.initializeWelcomePopup()}),(t,I)=>(e.openBlock(),e.createElementBlock("div",a,[e.unref(D).showWelcomePopup&&!e.unref(D).isOpen?(e.openBlock(),e.createElementBlock("div",{key:0,class:"blockspark-welcome-popup",onClick:Y},[e.createElementVNode("div",l,[e.createElementVNode("div",n,e.toDisplayString(X.value.welcomeTitle),1),e.createElementVNode("button",{class:"blockspark-close-popup",onClick:e.withModifiers(ee,["stop"]),"aria-label":"Close welcome popup"}," × ")]),e.createElementVNode("div",c,e.toDisplayString(X.value.welcomeMessage),1),e.createElementVNode("div",s,e.toDisplayString(X.value.welcomeCta),1)])):e.createCommentVNode("",!0),e.unref(D).isOpen?e.createCommentVNode("",!0):(e.openBlock(),e.createElementBlock("button",{key:1,class:"blockspark-chat-toggle-btn",onClick:Y,"aria-label":"Open chat"},[...I[0]||(I[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(D).isOpen?(e.openBlock(),e.createElementBlock("div",r,[e.createElementVNode("div",i,[e.createElementVNode("div",p,[e.createElementVNode("div",k,e.toDisplayString(X.value.title),1),e.createElementVNode("div",d,[e.createTextVNode(e.toDisplayString(X.value.subtitle)+" ",1),"human"===e.unref(D).chatMode?(e.openBlock(),e.createElementBlock("span",m," • "+e.toDisplayString(e.unref(H)?"🟢 Connected":"🟡 Connecting..."),1)):e.createCommentVNode("",!0)]),"human"===e.unref(D).chatMode?(e.openBlock(),e.createElementBlock("div",u," Human Support Mode ")):e.createCommentVNode("",!0),"human"===e.unref(D).chatMode?(e.openBlock(),e.createElementBlock("div",g,[I[1]||(I[1]=e.createElementVNode("span",{class:"blockspark-agent-label"},"Agent:",-1)),e.createElementVNode("span",b,e.toDisplayString(e.unref(_).name),1)])):e.createCommentVNode("",!0),"ai"===e.unref(D).chatMode?(e.openBlock(),e.createElementBlock("div",h," Bot Mode ")):e.createCommentVNode("",!0)]),e.createElementVNode("button",{class:"blockspark-chat-close-btn",onClick:Z,"aria-label":"Close chat"}," × ")]),e.createElementVNode("div",{class:"blockspark-chat-messages",ref_key:"messagesContainer",ref:Q},[0===e.unref(D).messages.length?(e.openBlock(),e.createElementBlock("div",y,[I[2]||(I[2]=e.createElementVNode("div",{class:"blockspark-chat-empty-icon"},"👋",-1)),e.createElementVNode("p",null,e.toDisplayString(X.value.emptyStateMessage),1)])):e.createCommentVNode("",!0),(e.openBlock(!0),e.createElementBlock(e.Fragment,null,e.renderList(e.unref(D).messages,t=>{return e.openBlock(),e.createElementBlock("div",{key:t.id,class:e.normalizeClass(["blockspark-message",`blockspark-message-${t.sender}`])},[e.createElementVNode("div",E,[e.createElementVNode("span",{innerHTML:e.unref(o.safeLinkifyText)(t.text)},null,8,B)]),t.richContent&&Array.isArray(t.richContent)&&t.richContent.length>0?(e.openBlock(),e.createElementBlock("div",f,[(e.openBlock(!0),e.createElementBlock(e.Fragment,null,e.renderList(t.richContent,(t,o)=>(e.openBlock(),e.createElementBlock(e.Fragment,{key:o},[Array.isArray(t)?(e.openBlock(!0),e.createElementBlock(e.Fragment,{key:1},e.renderList(t,(t,a)=>(e.openBlock(),e.createElementBlock(e.Fragment,{key:`${o}-${a}`},["chips"===t.type&&t.options?(e.openBlock(),e.createElementBlock("div",N,[(e.openBlock(!0),e.createElementBlock(e.Fragment,null,e.renderList(t.options,(t,o)=>(e.openBlock(),e.createElementBlock("button",{key:o,class:"blockspark-chip-button",type:"button",onClick:e=>ae(t.text,t.payload)},e.toDisplayString(t.text),9,C))),128))])):e.createCommentVNode("",!0)],64))),128)):(e.openBlock(),e.createElementBlock(e.Fragment,{key:0},["chips"===t.type&&t.options?(e.openBlock(),e.createElementBlock("div",V,[(e.openBlock(!0),e.createElementBlock(e.Fragment,null,e.renderList(t.options,(t,o)=>(e.openBlock(),e.createElementBlock("button",{key:o,class:"blockspark-chip-button",type:"button",onClick:e=>ae(t.text,t.payload)},e.toDisplayString(t.text),9,v))),128))])):e.createCommentVNode("",!0)],64))],64))),128))])):e.createCommentVNode("",!0),e.createElementVNode("div",w,e.toDisplayString((a=t.timestamp,a.toLocaleTimeString([],{hour:"2-digit",minute:"2-digit"}))),1)],2);var a}),128)),e.unref(D).isLoading?(e.openBlock(),e.createElementBlock("div",M,[...I[3]||(I[3]=[e.createElementVNode("div",{class:"blockspark-typing-indicator"},[e.createElementVNode("span"),e.createElementVNode("span"),e.createElementVNode("span")],-1)])])):e.createCommentVNode("",!0),"human"===e.unref(D).chatMode&&e.unref(O)?(e.openBlock(),e.createElementBlock("div",S,[...I[4]||(I[4]=[e.createElementVNode("span",{class:"blockspark-typing-dots"},[e.createElementVNode("span"),e.createElementVNode("span"),e.createElementVNode("span")],-1),e.createElementVNode("span",{class:"blockspark-typing-text"},"Agent is typing...",-1)])])):e.createCommentVNode("",!0),e.createElementVNode("div",{ref_key:"messagesEndRef",ref:J},null,512)],512),e.createElementVNode("form",{class:"blockspark-chat-input-form",onSubmit:e.withModifiers(oe,["prevent"])},[e.createElementVNode("input",{type:"text",class:"blockspark-chat-input",value:e.unref(D).inputValue,onInput:te,placeholder:X.value.inputPlaceholder,disabled:e.unref(D).isLoading},null,40,A),e.createElementVNode("button",{type:"submit",class:"blockspark-chat-send-btn",disabled:!e.unref(D).inputValue.trim()||e.unref(D).isLoading},[...I[5]||(I[5]=[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,x)],32)])):e.createCommentVNode("",!0)]))}});exports.default=I;
2
+ //# sourceMappingURL=ChatWidget.vue.cjs2.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"ChatWidget.vue.cjs2.js","sources":["../../src/components/ChatWidget.vue"],"sourcesContent":["<template>\n <div class=\"blockspark-chat-widget\">\n <!-- Welcome Popup -->\n <div\n v-if=\"state.showWelcomePopup && !state.isOpen\"\n class=\"blockspark-welcome-popup\"\n @click=\"handleOpenChat\"\n >\n <div class=\"blockspark-welcome-header\">\n <div class=\"blockspark-welcome-title\">{{ config.welcomeTitle }}</div>\n <button\n class=\"blockspark-close-popup\"\n @click.stop=\"handleCloseWelcomePopup\"\n aria-label=\"Close welcome popup\"\n >\n ×\n </button>\n </div>\n <div class=\"blockspark-welcome-message\">{{ config.welcomeMessage }}</div>\n <div class=\"blockspark-welcome-cta\">{{ config.welcomeCta }}</div>\n </div>\n\n <!-- Chat Toggle Button -->\n <button\n v-if=\"!state.isOpen\"\n class=\"blockspark-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=\"blockspark-chat-window\">\n <div class=\"blockspark-chat-header\">\n <div class=\"blockspark-chat-header-content\">\n <div class=\"blockspark-chat-title\">{{ config.title }}</div>\n <div class=\"blockspark-chat-subtitle\">\n {{ config.subtitle }}\n <span v-if=\"state.chatMode === 'human'\" class=\"blockspark-mode-indicator\">\n • {{ wsConnected ? '🟢 Connected' : '🟡 Connecting...' }}\n </span>\n </div>\n <div v-if=\"state.chatMode === 'human'\" class=\"blockspark-mode-badge\">\n Human Support Mode\n </div>\n <div v-if=\"state.chatMode === 'human'\" class=\"blockspark-agent-info\">\n <span class=\"blockspark-agent-label\">Agent:</span>\n <span class=\"blockspark-agent-name\">{{ currentAgent.name }}</span>\n </div>\n <div v-if=\"state.chatMode === 'ai'\" class=\"blockspark-mode-badge\">\n Bot Mode\n </div>\n </div>\n <button\n class=\"blockspark-chat-close-btn\"\n @click=\"handleCloseChat\"\n aria-label=\"Close chat\"\n >\n ×\n </button>\n </div>\n\n <div class=\"blockspark-chat-messages\" ref=\"messagesContainer\">\n <!-- Empty State -->\n <div v-if=\"state.messages.length === 0\" class=\"blockspark-chat-empty\">\n <div class=\"blockspark-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=\"['blockspark-message', `blockspark-message-${message.sender}`]\"\n >\n <div class=\"blockspark-message-content\">\n <!-- Safe HTML rendering with sanitization -->\n <span v-html=\"safeLinkifyText(message.text)\"></span>\n </div>\n\n <!-- Rich Content (Chips) -->\n <div\n v-if=\"message.richContent && Array.isArray(message.richContent) && message.richContent.length > 0\"\n class=\"blockspark-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=\"blockspark-chips-group\"\n >\n <button\n v-for=\"(chip, chipIndex) in contentGroup.options\"\n :key=\"chipIndex\"\n class=\"blockspark-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=\"blockspark-chips-group\"\n >\n <button\n v-for=\"(chip, chipIndex) in content.options\"\n :key=\"chipIndex\"\n class=\"blockspark-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=\"blockspark-message-time\">\n {{ formatTime(message.timestamp) }}\n </div>\n </div>\n\n <!-- Loading Indicator -->\n <div v-if=\"state.isLoading\" class=\"blockspark-message blockspark-message-bot\">\n <div class=\"blockspark-typing-indicator\">\n <span></span>\n <span></span>\n <span></span>\n </div>\n </div>\n\n <!-- Agent Typing Indicator -->\n <div v-if=\"state.chatMode === 'human' && agentTyping\" class=\"blockspark-agent-typing-indicator\">\n <span class=\"blockspark-typing-dots\">\n <span></span>\n <span></span>\n <span></span>\n </span>\n <span class=\"blockspark-typing-text\">Agent is typing...</span>\n </div>\n\n <div ref=\"messagesEndRef\"></div>\n </div>\n\n <!-- Input Form -->\n <form class=\"blockspark-chat-input-form\" @submit.prevent=\"handleSubmit\">\n <input\n type=\"text\"\n class=\"blockspark-chat-input\"\n :value=\"state.inputValue\"\n @input=\"handleInput\"\n :placeholder=\"config.inputPlaceholder\"\n :disabled=\"state.isLoading\"\n />\n <button\n type=\"submit\"\n class=\"blockspark-chat-send-btn\"\n :disabled=\"!state.inputValue.trim() || state.isLoading\"\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// 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 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// 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 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// 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","openChat","closeChat","sendMessage","toggleChat","setInputValue","clearError","manager","useChatWidget","messagesEndRef","ref","messagesContainer","config","computed","watch","value","length","nextTick","scrollIntoView","behavior","handleOpenChat","async","handleCloseChat","handleCloseWelcomePopup","closeWelcomePopup","handleInput","event","target","handleSubmit","preventDefault","inputValue","trim","handleChipClick","chipText","payload","messageToSend","onMounted","showWelcomePopup","window","initializeWelcomePopup","_openBlock","_createElementBlock","_hoisted_1","_unref","class","onClick","_createElementVNode","_hoisted_2","_hoisted_3","_toDisplayString","welcomeTitle","_hoisted_4","welcomeMessage","_hoisted_5","welcomeCta","width","height","viewBox","fill","stroke","d","_hoisted_6","_hoisted_7","_hoisted_8","_hoisted_9","title","_hoisted_10","subtitle","_hoisted_11","_hoisted_12","_hoisted_13","_cache","_hoisted_14","name","_hoisted_15","_hoisted_16","emptyStateMessage","_Fragment","_renderList","message","key","id","_normalizeClass","sender","_hoisted_17","innerHTML","safeLinkifyText","text","richContent","Array","isArray","_hoisted_19","contentGroup","groupIndex","content","contentIndex","type","options","_hoisted_22","chip","chipIndex","$event","_hoisted_23","_hoisted_20","_hoisted_21","_hoisted_24","date","timestamp","toLocaleTimeString","hour","minute","_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 ChatWidget = /* @__PURE__ */ _export_sfc(_sfc_main, [["__scopeId", "data-v-cbfcf702"]]);
5
+ export {
6
+ ChatWidget 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":";;;;"}