@blockspark/chat-widget 1.0.1 → 1.0.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -1,57 +1,88 @@
1
1
  # BlockSpark Chat Widget
2
2
 
3
- A reusable React chat widget component that connects directly with Dialogflow CX - no backend API required!
3
+ A reusable chat widget for **React**, **Next.js**, **Vue 3**, and **vanilla HTML (CDN)** that connects directly with Dialogflow CX no backend API required.
4
4
 
5
5
  ## Installation
6
6
 
7
- ### Option 1: Install from Local Path (Recommended for Development)
7
+ Install from npm (for React, Next.js, or Vue projects):
8
8
 
9
9
  ```bash
10
- # In your website project directory
11
- npm install /path/to/blockspark-chat-widget
12
- # or
13
- npm install ../blockspark-chat-widget
10
+ npm install @blockspark/chat-widget
14
11
  ```
15
12
 
16
- ### Option 2: Use npm link (For Development)
13
+ - **React / Next.js**: You also need `react` and `react-dom` (they are peer dependencies).
14
+ - **Vue 3**: You also need `vue`. The widget bundles React internally for the Vue build, so you do **not** need to install React.
17
15
 
18
16
  ```bash
19
- # In the blockspark-chat-widget directory
20
- npm link
17
+ # React or Next.js
18
+ npm install @blockspark/chat-widget react react-dom
21
19
 
22
- # In your website project directory
23
- npm link @blockspark/chat-widget
20
+ # Vue 3 only
21
+ npm install @blockspark/chat-widget vue
24
22
  ```
25
23
 
26
- ### Option 3: Publish to npm (For Production)
24
+ **Development / local testing:**
27
25
 
28
26
  ```bash
29
- # Build the library first
30
- npm run build
31
-
32
- # Publish to npm (make sure you're logged in)
33
- npm publish
27
+ # From your app directory
28
+ npm install /path/to/blockspark-chat-widget
29
+ # or use npm link in the widget repo, then npm link @blockspark/chat-widget in your app
34
30
  ```
35
31
 
36
- Then install in your project:
37
- ```bash
38
- npm install @blockspark/chat-widget
39
- ```
32
+ ---
40
33
 
41
34
  ## Usage
42
35
 
43
- ### Basic Usage
36
+ ### React
37
+
38
+ Import the component and the default styles, then render with your config.
44
39
 
45
40
  ```tsx
46
41
  import ChatWidget from '@blockspark/chat-widget';
47
42
  import '@blockspark/chat-widget/dist/styles.css';
48
43
 
49
- // Load your Google Cloud service account key
50
44
  import serviceAccountKey from './path/to/service-account-key.json';
51
45
 
52
46
  function App() {
47
+ return (
48
+ <ChatWidget
49
+ dfProjectId="your-project-id"
50
+ dfLocation="us-central1"
51
+ dfAgentId="your-agent-id"
52
+ serviceAccountKey={serviceAccountKey}
53
+ languageCode="en"
54
+ title="💬 My Chat"
55
+ subtitle="We're here to help"
56
+ />
57
+ );
58
+ }
59
+ ```
60
+
61
+ ### Next.js
62
+
63
+ The widget uses browser APIs (e.g. `localStorage`) and is intended to run on the client. Use **dynamic import with SSR disabled** so it only loads in the browser.
64
+
65
+ **App Router (Next.js 13+):**
66
+
67
+ ```tsx
68
+ 'use client';
69
+
70
+ import dynamic from 'next/dynamic';
71
+ import '@blockspark/chat-widget/dist/styles.css';
72
+
73
+ const ChatWidget = dynamic(
74
+ () => import('@blockspark/chat-widget').then((mod) => mod.default),
75
+ { ssr: false }
76
+ );
77
+
78
+ export default function Page() {
79
+ const serviceAccountKey = {
80
+ /* your key object, or load from env/server */
81
+ };
82
+
53
83
  return (
54
84
  <div>
85
+ <h1>My Page</h1>
55
86
  <ChatWidget
56
87
  dfProjectId="your-project-id"
57
88
  dfLocation="us-central1"
@@ -64,106 +95,165 @@ function App() {
64
95
  }
65
96
  ```
66
97
 
67
- ### Using Access Token (Alternative)
68
-
69
- If you prefer to manage authentication yourself:
98
+ **Pages Router:**
70
99
 
71
100
  ```tsx
72
- import ChatWidget from '@blockspark/chat-widget';
101
+ import dynamic from 'next/dynamic';
73
102
  import '@blockspark/chat-widget/dist/styles.css';
74
103
 
75
- function App() {
76
- const [accessToken, setAccessToken] = useState<string>('');
77
-
78
- // Get access token from your backend or OAuth flow
79
- useEffect(() => {
80
- // Your token fetching logic here
81
- fetchAccessToken().then(setAccessToken);
82
- }, []);
104
+ const ChatWidget = dynamic(
105
+ () => import('@blockspark/chat-widget').then((mod) => mod.default),
106
+ { ssr: false }
107
+ );
83
108
 
109
+ export default function ChatPage() {
84
110
  return (
85
111
  <ChatWidget
86
112
  dfProjectId="your-project-id"
87
113
  dfLocation="us-central1"
88
114
  dfAgentId="your-agent-id"
89
- accessToken={accessToken}
115
+ serviceAccountKey={process.env.NEXT_PUBLIC_SERVICE_ACCOUNT_KEY_JSON ? JSON.parse(process.env.NEXT_PUBLIC_SERVICE_ACCOUNT_KEY_JSON) : undefined}
90
116
  languageCode="en"
91
117
  />
92
118
  );
93
119
  }
94
120
  ```
95
121
 
96
- ### With Custom Configuration
122
+ **Important:** Do not expose raw service account keys in client-side code in production. Prefer a backend that returns short-lived tokens or use a proxy.
97
123
 
98
- ```tsx
99
- import ChatWidget from '@blockspark/chat-widget';
124
+ ### Vue 3
125
+
126
+ Use either the global plugin or the component directly.
127
+
128
+ **Option A — Global plugin (e.g. `main.js` / `main.ts`):**
129
+
130
+ ```js
131
+ import { createApp } from 'vue';
132
+ import App from './App.vue';
133
+ import BlockSparkChatWidget from '@blockspark/chat-widget/vue';
100
134
  import '@blockspark/chat-widget/dist/styles.css';
101
- import serviceAccountKey from './service-account-key.json';
102
135
 
103
- function App() {
104
- return (
105
- <ChatWidget
106
- dfProjectId="your-project-id"
107
- dfLocation="us-central1"
108
- dfAgentId="your-agent-id"
109
- serviceAccountKey={serviceAccountKey}
110
- languageCode="en"
111
- title="💬 My Chat Assistant"
112
- subtitle="How can I help you?"
113
- welcomeTitle="👋 Welcome!"
114
- welcomeMessage="I'm here to help you with any questions."
115
- welcomeCta="Start chatting"
116
- showWelcomePopup={true}
117
- welcomePopupDelay={2000}
118
- inputPlaceholder="Type your message..."
119
- emptyStateMessage="Hi! How can I help you today?"
120
- debug={false}
121
- />
122
- );
123
- }
136
+ const app = createApp(App);
137
+ app.use(BlockSparkChatWidget); // registers <BlockSparkChatWidget>
138
+ app.mount('#app');
124
139
  ```
125
140
 
126
- ### Using Environment Variables
141
+ Then in any template:
142
+
143
+ ```vue
144
+ <template>
145
+ <BlockSparkChatWidget
146
+ df-project-id="your-project-id"
147
+ df-location="us-central1"
148
+ df-agent-id="your-agent-id"
149
+ :service-account-key="serviceAccountKey"
150
+ language-code="en"
151
+ />
152
+ </template>
153
+ ```
127
154
 
128
- You can configure the backend API URLs for Human Support Mode using environment variables. Create a `.env` file in the project root:
155
+ **Option B Component only:**
129
156
 
130
- ```bash
131
- # .env file
132
- REACT_APP_BACKEND_BASE_URL=http://localhost:8012
133
- REACT_APP_BACKEND_WS_URL=ws://localhost:8012
134
- ```
157
+ ```vue
158
+ <script setup>
159
+ import { BlockSparkChatWidgetVue } from '@blockspark/chat-widget/vue';
160
+ import '@blockspark/chat-widget/dist/styles.css';
135
161
 
136
- Or pass them as props:
162
+ import serviceAccountKey from './path/to/service-account-key.json';
163
+ </script>
164
+
165
+ <template>
166
+ <BlockSparkChatWidgetVue
167
+ df-project-id="your-project-id"
168
+ df-location="us-central1"
169
+ df-agent-id="your-agent-id"
170
+ :service-account-key="serviceAccountKey"
171
+ language-code="en"
172
+ />
173
+ </template>
174
+ ```
137
175
 
138
- ```tsx
139
- <ChatWidget
140
- dfProjectId="your-project-id"
141
- dfAgentId="your-agent-id"
142
- serviceAccountKey={serviceAccountKey}
143
- backendBaseUrl="http://your-backend-url:8012"
144
- backendWsUrl="ws://your-backend-url:8012"
145
- />
176
+ Use **kebab-case** for props in templates (e.g. `df-project-id`, `service-account-key`). All props from the Props table below are supported.
177
+
178
+ ### CDN (script tag, no build step)
179
+
180
+ You can load the widget from a CDN and mount it with React (the widget is a React component). Load React, ReactDOM, the widget CSS, and the widget script, then render into a container.
181
+
182
+ Replace `1.0.1` with the version you want (or use `latest` for the latest release).
183
+
184
+ **Using unpkg:**
185
+
186
+ ```html
187
+ <!DOCTYPE html>
188
+ <html lang="en">
189
+ <head>
190
+ <meta charset="UTF-8" />
191
+ <title>BlockSpark Chat Widget</title>
192
+ <!-- 1. React (required by the widget) -->
193
+ <script crossorigin src="https://unpkg.com/react@18/umd/react.production.min.js"></script>
194
+ <script crossorigin src="https://unpkg.com/react-dom@18/umd/react-dom.production.min.js"></script>
195
+ <!-- 2. Widget CSS -->
196
+ <link rel="stylesheet" href="https://unpkg.com/@blockspark/chat-widget@1.0.1/dist/styles.css" />
197
+ </head>
198
+ <body>
199
+ <div id="chat-root"></div>
200
+
201
+ <!-- 3. Widget script (UMD: exposes BlockSparkChatWidget) -->
202
+ <script src="https://unpkg.com/@blockspark/chat-widget@1.0.1/dist/index.js"></script>
203
+
204
+ <script>
205
+ (function () {
206
+ var container = document.getElementById('chat-root');
207
+ var React = window.React;
208
+ var ReactDOM = window.ReactDOM;
209
+ var ChatWidget = window.BlockSparkChatWidget;
210
+
211
+ var config = {
212
+ dfProjectId: 'your-project-id',
213
+ dfLocation: 'us-central1',
214
+ dfAgentId: 'your-agent-id',
215
+ serviceAccountKey: { /* your service account key object */ },
216
+ languageCode: 'en',
217
+ title: '💬 BlockSpark AI Assistant',
218
+ subtitle: "We're here to help"
219
+ };
220
+
221
+ if (ReactDOM.createRoot) {
222
+ ReactDOM.createRoot(container).render(React.createElement(ChatWidget, config));
223
+ } else {
224
+ ReactDOM.render(React.createElement(ChatWidget, config), container);
225
+ }
226
+ })();
227
+ </script>
228
+ </body>
229
+ </html>
146
230
  ```
147
231
 
148
- **Note**: Props take precedence over environment variables.
232
+ **Using jsDelivr:**
149
233
 
150
- ### Human Support Mode
234
+ Use the same structure and swap the CDN base URL:
151
235
 
152
- The widget supports automatic handoff from bot to human agents. When Dialogflow returns `{"handoff": true}`, the widget will:
236
+ - CSS: `https://cdn.jsdelivr.net/npm/@blockspark/chat-widget@1.0.1/dist/styles.css`
237
+ - JS: `https://cdn.jsdelivr.net/npm/@blockspark/chat-widget@1.0.1/dist/index.js`
153
238
 
154
- 1. Switch from Bot Mode to Human Support Mode
155
- 2. Create a support chat session
156
- 3. Connect via WebSocket for real-time messaging
157
- 4. Load message history
158
- 5. Route messages to the backend API instead of Dialogflow
239
+ **Notes for CDN:**
159
240
 
160
- The widget displays mode indicators and connection status in the chat header.
241
+ - You must provide `serviceAccountKey` (or `accessToken`) in the config object. Do not hardcode real keys in production; use a backend or token endpoint.
242
+ - Pin the version in the URL (e.g. `@1.0.1`) instead of `@latest` for stable behavior.
161
243
 
162
- ### Import Types (TypeScript)
244
+ ---
163
245
 
164
- ```tsx
165
- import ChatWidget, { ChatWidgetProps, DialogflowConfig } from '@blockspark/chat-widget';
166
- ```
246
+ ## Human Support Mode
247
+
248
+ The widget supports automatic handoff from bot to human agents. When Dialogflow returns `{"handoff": true}`, the widget will:
249
+
250
+ 1. Switch from Bot Mode to Human Support Mode
251
+ 2. Create a support chat session
252
+ 3. Connect via WebSocket for real-time messaging
253
+ 4. Load message history
254
+ 5. Route messages to the backend API instead of Dialogflow
255
+
256
+ The widget shows mode and connection status in the chat header.
167
257
 
168
258
  ## Props
169
259
 
@@ -186,62 +276,57 @@ import ChatWidget, { ChatWidgetProps, DialogflowConfig } from '@blockspark/chat-
186
276
  | `inputPlaceholder` | `string` | No | `"Type your message..."` | Input field placeholder |
187
277
  | `emptyStateMessage` | `string` | No | `"Hi! I'm BlockSpark..."` | Empty state message |
188
278
  | `debug` | `boolean` | No | `false` | Enable debug logging |
189
- | `backendBaseUrl` | `string` | No | `process.env.REACT_APP_BACKEND_BASE_URL` or `"http://localhost:8012"` | Backend REST API base URL for Human Support Mode |
190
- | `backendWsUrl` | `string` | No | `process.env.REACT_APP_BACKEND_WS_URL` or `"ws://localhost:8012"` | Backend WebSocket URL for Human Support Mode |
279
+ | `backendBaseUrl` | `string` | No | env or `"http://localhost:8012"` | Backend REST API base URL for Human Support Mode |
280
+ | `backendWsUrl` | `string` | No | env or `"ws://localhost:8012"` | Backend WebSocket URL for Human Support Mode |
191
281
 
192
282
  \* Either `serviceAccountKey` or `accessToken` must be provided.
193
283
 
284
+ ## TypeScript
285
+
286
+ ```tsx
287
+ import ChatWidget, { ChatWidgetProps, DialogflowConfig } from '@blockspark/chat-widget';
288
+ ```
289
+
194
290
  ## How It Works
195
291
 
196
- The widget connects **directly** to Dialogflow CX using the REST API - no backend required!
292
+ The widget talks **directly** to Dialogflow CX via the REST API (no custom backend required for basic use):
197
293
 
198
- 1. **Authentication**: Uses Google Cloud service account key to generate OAuth2 access tokens
199
- 2. **Session Management**: Creates and manages Dialogflow sessions automatically
200
- 3. **Message Handling**: Sends messages directly to Dialogflow and displays responses
201
- 4. **Rich Content**: Supports Dialogflow rich content (chips, cards, etc.)
294
+ 1. **Authentication** Uses a Google Cloud service account key to obtain OAuth2 access tokens
295
+ 2. **Sessions** Creates and manages Dialogflow sessions
296
+ 3. **Messages** Sends user messages to Dialogflow and displays responses
297
+ 4. **Rich content** Supports Dialogflow rich content (chips, cards, etc.)
202
298
 
203
299
  ## Requirements
204
300
 
205
- - React 16.8.0 or higher
206
- - React DOM 16.8.0 or higher
207
- - Google Cloud service account with Dialogflow API enabled
208
- - Dialogflow CX agent
301
+ - **React / Next.js**: React 16.8+ and React DOM
302
+ - **Vue**: Vue 3.x
303
+ - **CDN**: React 17 or 18 and React DOM loaded via script tags
304
+ - Google Cloud project with Dialogflow API enabled and a Dialogflow CX agent
209
305
 
210
306
  ## Getting Your Service Account Key
211
307
 
212
- 1. Go to [Google Cloud Console](https://console.cloud.google.com/)
213
- 2. Select your project
214
- 3. Navigate to **IAM & Admin** > **Service Accounts**
215
- 4. Create a new service account or select an existing one
216
- 5. Create a JSON key and download it
217
- 6. Enable **Dialogflow API** for your project
218
- 7. Grant the service account **Dialogflow API User** role
219
-
220
- ## Security Warning ⚠️
308
+ 1. Open [Google Cloud Console](https://console.cloud.google.com/) and select your project
309
+ 2. Go to **IAM & Admin** → **Service Accounts**
310
+ 3. Create or select a service account and create a JSON key
311
+ 4. Enable **Dialogflow API** for the project
312
+ 5. Grant the service account the **Dialogflow API User** role
221
313
 
222
- **Important**: Service account keys contain sensitive credentials.
314
+ ## Security
223
315
 
224
- - **For Development**: You can import the key directly (as shown in examples)
225
- - **For Production**:
226
- - **DO NOT** expose service account keys in client-side code
227
- - Use a backend proxy to handle authentication
228
- - Or use OAuth2 flow to get access tokens securely
229
- - Consider using restricted service account keys with minimal permissions
316
+ - **Development**: You can import or pass the service account key in code for local testing
317
+ - **Production**:
318
+ - **Do not** ship service account keys in client-side code or public HTML
319
+ - Prefer a backend that issues short-lived tokens or proxies Dialogflow calls
320
+ - Use restricted keys and minimal permissions where possible
230
321
 
231
322
  ## Development
232
323
 
233
324
  ```bash
234
- # Install dependencies
235
325
  npm install
236
-
237
- # Build for production
238
- npm run build
239
-
240
- # Watch mode for development
241
- npm run dev
326
+ npm run build # production build
327
+ npm run dev # watch mode
242
328
  ```
243
329
 
244
330
  ## License
245
331
 
246
332
  MIT
247
- export NPM_TOKEN=your_token_here
@@ -0,0 +1,182 @@
1
+ /**
2
+ * Vue 3 wrapper for the BlockSpark React ChatWidget.
3
+ * Mounts and unmounts the React component and forwards all props.
4
+ */
5
+ export declare const BlockSparkChatWidgetVue: import("vue").DefineComponent<import("vue").ExtractPropTypes<{
6
+ title: {
7
+ type: StringConstructor;
8
+ default: string;
9
+ };
10
+ subtitle: {
11
+ type: StringConstructor;
12
+ default: string;
13
+ };
14
+ welcomeTitle: {
15
+ type: StringConstructor;
16
+ default: string;
17
+ };
18
+ welcomeMessage: {
19
+ type: StringConstructor;
20
+ default: string;
21
+ };
22
+ welcomeCta: {
23
+ type: StringConstructor;
24
+ default: string;
25
+ };
26
+ showWelcomePopup: {
27
+ type: BooleanConstructor;
28
+ default: boolean;
29
+ };
30
+ welcomePopupDelay: {
31
+ type: NumberConstructor;
32
+ default: number;
33
+ };
34
+ fallbackWelcomeMessage: {
35
+ type: StringConstructor;
36
+ default: string;
37
+ };
38
+ inputPlaceholder: {
39
+ type: StringConstructor;
40
+ default: string;
41
+ };
42
+ emptyStateMessage: {
43
+ type: StringConstructor;
44
+ default: string;
45
+ };
46
+ debug: {
47
+ type: BooleanConstructor;
48
+ default: boolean;
49
+ };
50
+ dfProjectId: {
51
+ type: StringConstructor;
52
+ default: undefined;
53
+ };
54
+ dfLocation: {
55
+ type: StringConstructor;
56
+ default: string;
57
+ };
58
+ dfAgentId: {
59
+ type: StringConstructor;
60
+ default: undefined;
61
+ };
62
+ serviceAccountKey: {
63
+ type: ObjectConstructor;
64
+ default: undefined;
65
+ };
66
+ accessToken: {
67
+ type: StringConstructor;
68
+ default: undefined;
69
+ };
70
+ languageCode: {
71
+ type: StringConstructor;
72
+ default: string;
73
+ };
74
+ backendBaseUrl: {
75
+ type: StringConstructor;
76
+ default: undefined;
77
+ };
78
+ backendWsUrl: {
79
+ type: StringConstructor;
80
+ default: undefined;
81
+ };
82
+ }>, {
83
+ containerRef: import("vue").Ref<HTMLElement | null, HTMLElement | null>;
84
+ }, {}, {}, {}, import("vue").ComponentOptionsMixin, import("vue").ComponentOptionsMixin, {}, string, import("vue").PublicProps, Readonly<import("vue").ExtractPropTypes<{
85
+ title: {
86
+ type: StringConstructor;
87
+ default: string;
88
+ };
89
+ subtitle: {
90
+ type: StringConstructor;
91
+ default: string;
92
+ };
93
+ welcomeTitle: {
94
+ type: StringConstructor;
95
+ default: string;
96
+ };
97
+ welcomeMessage: {
98
+ type: StringConstructor;
99
+ default: string;
100
+ };
101
+ welcomeCta: {
102
+ type: StringConstructor;
103
+ default: string;
104
+ };
105
+ showWelcomePopup: {
106
+ type: BooleanConstructor;
107
+ default: boolean;
108
+ };
109
+ welcomePopupDelay: {
110
+ type: NumberConstructor;
111
+ default: number;
112
+ };
113
+ fallbackWelcomeMessage: {
114
+ type: StringConstructor;
115
+ default: string;
116
+ };
117
+ inputPlaceholder: {
118
+ type: StringConstructor;
119
+ default: string;
120
+ };
121
+ emptyStateMessage: {
122
+ type: StringConstructor;
123
+ default: string;
124
+ };
125
+ debug: {
126
+ type: BooleanConstructor;
127
+ default: boolean;
128
+ };
129
+ dfProjectId: {
130
+ type: StringConstructor;
131
+ default: undefined;
132
+ };
133
+ dfLocation: {
134
+ type: StringConstructor;
135
+ default: string;
136
+ };
137
+ dfAgentId: {
138
+ type: StringConstructor;
139
+ default: undefined;
140
+ };
141
+ serviceAccountKey: {
142
+ type: ObjectConstructor;
143
+ default: undefined;
144
+ };
145
+ accessToken: {
146
+ type: StringConstructor;
147
+ default: undefined;
148
+ };
149
+ languageCode: {
150
+ type: StringConstructor;
151
+ default: string;
152
+ };
153
+ backendBaseUrl: {
154
+ type: StringConstructor;
155
+ default: undefined;
156
+ };
157
+ backendWsUrl: {
158
+ type: StringConstructor;
159
+ default: undefined;
160
+ };
161
+ }>> & Readonly<{}>, {
162
+ title: string;
163
+ subtitle: string;
164
+ welcomeTitle: string;
165
+ welcomeMessage: string;
166
+ welcomeCta: string;
167
+ showWelcomePopup: boolean;
168
+ welcomePopupDelay: number;
169
+ fallbackWelcomeMessage: string;
170
+ inputPlaceholder: string;
171
+ emptyStateMessage: string;
172
+ debug: boolean;
173
+ dfProjectId: string;
174
+ dfLocation: string;
175
+ dfAgentId: string;
176
+ serviceAccountKey: Record<string, any>;
177
+ accessToken: string;
178
+ languageCode: string;
179
+ backendBaseUrl: string;
180
+ backendWsUrl: string;
181
+ }, {}, {}, {}, string, import("vue").ComponentProvideOptions, true, {}, any>;
182
+ //# sourceMappingURL=ChatWidgetWrapper.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"ChatWidgetWrapper.d.ts","sourceRoot":"","sources":["../../src/vue/ChatWidgetWrapper.ts"],"names":[],"mappings":"AAcA;;;GAGG;AACH,eAAO,MAAM,uBAAuB;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;4EAyFlC,CAAC"}