@baseportal/chat-widget 0.1.0
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 +333 -0
- package/dist/index.cjs.js +2286 -0
- package/dist/index.cjs.js.map +1 -0
- package/dist/index.css +2 -0
- package/dist/index.css.map +1 -0
- package/dist/index.d.mts +119 -0
- package/dist/index.d.ts +119 -0
- package/dist/index.esm.js +2253 -0
- package/dist/index.esm.js.map +1 -0
- package/dist/index.iife.js +869 -0
- package/dist/index.iife.js.map +1 -0
- package/package.json +30 -0
package/README.md
ADDED
|
@@ -0,0 +1,333 @@
|
|
|
1
|
+
# @baseportal/chat-widget
|
|
2
|
+
|
|
3
|
+
Embeddable chat widget for Baseportal. Lightweight (~60KB gzipped) with Preact, Ably realtime, and multi-language support.
|
|
4
|
+
|
|
5
|
+
## Installation
|
|
6
|
+
|
|
7
|
+
### Script tag (IIFE)
|
|
8
|
+
|
|
9
|
+
```html
|
|
10
|
+
<script src="https://your-domain.com/baseportal-chat.iife.js"></script>
|
|
11
|
+
<script>
|
|
12
|
+
const chat = new BaseportalChat({
|
|
13
|
+
channelToken: 'your-channel-token',
|
|
14
|
+
})
|
|
15
|
+
</script>
|
|
16
|
+
```
|
|
17
|
+
|
|
18
|
+
### NPM / PNPM
|
|
19
|
+
|
|
20
|
+
```bash
|
|
21
|
+
pnpm add @baseportal/chat-widget
|
|
22
|
+
```
|
|
23
|
+
|
|
24
|
+
```typescript
|
|
25
|
+
import { BaseportalChat } from '@baseportal/chat-widget'
|
|
26
|
+
|
|
27
|
+
const chat = new BaseportalChat({
|
|
28
|
+
channelToken: 'your-channel-token',
|
|
29
|
+
})
|
|
30
|
+
```
|
|
31
|
+
|
|
32
|
+
## Configuration
|
|
33
|
+
|
|
34
|
+
```typescript
|
|
35
|
+
const chat = new BaseportalChat({
|
|
36
|
+
// Required
|
|
37
|
+
channelToken: 'your-channel-token',
|
|
38
|
+
|
|
39
|
+
// Optional
|
|
40
|
+
apiUrl: 'https://api.baseportal.io', // Custom API URL
|
|
41
|
+
position: 'bottom-right', // 'bottom-right' | 'bottom-left'
|
|
42
|
+
locale: 'pt', // 'pt' | 'en' | 'es'
|
|
43
|
+
hideOnLoad: false, // Start hidden (no bubble)
|
|
44
|
+
theme: {
|
|
45
|
+
primaryColor: '#6366f1', // Custom primary color
|
|
46
|
+
},
|
|
47
|
+
container: document.getElementById('chat'), // Mount inside a specific element
|
|
48
|
+
visitor: { // Pre-identify the visitor
|
|
49
|
+
name: 'John Doe',
|
|
50
|
+
email: 'john@example.com',
|
|
51
|
+
hash: 'hmac-sha256-hash', // Required if identity verification is enabled
|
|
52
|
+
metadata: { plan: 'pro' },
|
|
53
|
+
},
|
|
54
|
+
})
|
|
55
|
+
```
|
|
56
|
+
|
|
57
|
+
### Configuration Options
|
|
58
|
+
|
|
59
|
+
| Option | Type | Default | Description |
|
|
60
|
+
|--------|------|---------|-------------|
|
|
61
|
+
| `channelToken` | `string` | — | **(Required)** Channel token from Baseportal dashboard |
|
|
62
|
+
| `apiUrl` | `string` | `https://api.baseportal.io` | API base URL |
|
|
63
|
+
| `position` | `'bottom-right' \| 'bottom-left'` | `'bottom-right'` | Widget position on the page |
|
|
64
|
+
| `locale` | `'pt' \| 'en' \| 'es'` | `'pt'` | UI language |
|
|
65
|
+
| `hideOnLoad` | `boolean` | `false` | If `true`, widget starts hidden (no bubble) |
|
|
66
|
+
| `theme` | `{ primaryColor?: string }` | — | Custom theme overrides |
|
|
67
|
+
| `container` | `HTMLElement` | — | Mount inside a specific DOM element instead of `document.body` |
|
|
68
|
+
| `visitor` | `VisitorData` | — | Pre-identify the visitor (see Identity Verification) |
|
|
69
|
+
|
|
70
|
+
## API Methods
|
|
71
|
+
|
|
72
|
+
### Visibility
|
|
73
|
+
|
|
74
|
+
```typescript
|
|
75
|
+
chat.open() // Open the chat window
|
|
76
|
+
chat.close() // Close the chat window
|
|
77
|
+
chat.toggle() // Toggle open/close
|
|
78
|
+
chat.show() // Show the widget (bubble + window)
|
|
79
|
+
chat.hide() // Hide the widget entirely
|
|
80
|
+
chat.isOpen() // Returns true if chat window is open
|
|
81
|
+
```
|
|
82
|
+
|
|
83
|
+
### Visitor Identity
|
|
84
|
+
|
|
85
|
+
```typescript
|
|
86
|
+
// Identify a visitor (enables conversation history)
|
|
87
|
+
chat.identify({
|
|
88
|
+
email: 'john@example.com',
|
|
89
|
+
name: 'John Doe',
|
|
90
|
+
hash: 'hmac-sha256-hash', // Required if identity verification is enabled
|
|
91
|
+
metadata: { plan: 'pro' },
|
|
92
|
+
})
|
|
93
|
+
|
|
94
|
+
// Update visitor data
|
|
95
|
+
chat.updateVisitor({
|
|
96
|
+
name: 'Jane Doe',
|
|
97
|
+
metadata: { plan: 'enterprise' },
|
|
98
|
+
})
|
|
99
|
+
|
|
100
|
+
// Clear visitor data and reset
|
|
101
|
+
chat.clearVisitor()
|
|
102
|
+
```
|
|
103
|
+
|
|
104
|
+
### Actions
|
|
105
|
+
|
|
106
|
+
```typescript
|
|
107
|
+
// Send a message programmatically
|
|
108
|
+
chat.sendMessage('Hello!')
|
|
109
|
+
|
|
110
|
+
// Open a specific conversation
|
|
111
|
+
chat.setConversationId('conversation-uuid')
|
|
112
|
+
|
|
113
|
+
// Start a new conversation
|
|
114
|
+
chat.newConversation()
|
|
115
|
+
```
|
|
116
|
+
|
|
117
|
+
### Configuration (Runtime)
|
|
118
|
+
|
|
119
|
+
```typescript
|
|
120
|
+
chat.setTheme({ primaryColor: '#10b981' })
|
|
121
|
+
chat.setPosition('bottom-left')
|
|
122
|
+
chat.setLocale('en')
|
|
123
|
+
```
|
|
124
|
+
|
|
125
|
+
### Lifecycle
|
|
126
|
+
|
|
127
|
+
```typescript
|
|
128
|
+
chat.destroy() // Unmount widget and clean up all listeners
|
|
129
|
+
```
|
|
130
|
+
|
|
131
|
+
## Events
|
|
132
|
+
|
|
133
|
+
```typescript
|
|
134
|
+
chat.on('ready', () => {
|
|
135
|
+
console.log('Widget initialized')
|
|
136
|
+
})
|
|
137
|
+
|
|
138
|
+
chat.on('open', () => {
|
|
139
|
+
console.log('Chat window opened')
|
|
140
|
+
})
|
|
141
|
+
|
|
142
|
+
chat.on('close', () => {
|
|
143
|
+
console.log('Chat window closed')
|
|
144
|
+
})
|
|
145
|
+
|
|
146
|
+
chat.on('message:sent', (message) => {
|
|
147
|
+
console.log('Message sent:', message)
|
|
148
|
+
})
|
|
149
|
+
|
|
150
|
+
chat.on('message:received', (message) => {
|
|
151
|
+
console.log('Message received:', message)
|
|
152
|
+
})
|
|
153
|
+
|
|
154
|
+
chat.on('conversation:started', (conversation) => {
|
|
155
|
+
console.log('New conversation:', conversation)
|
|
156
|
+
})
|
|
157
|
+
|
|
158
|
+
chat.on('conversation:closed', (conversation) => {
|
|
159
|
+
console.log('Conversation closed:', conversation)
|
|
160
|
+
})
|
|
161
|
+
|
|
162
|
+
chat.on('identified', (visitor) => {
|
|
163
|
+
console.log('Visitor identified:', visitor)
|
|
164
|
+
})
|
|
165
|
+
|
|
166
|
+
// Remove listener
|
|
167
|
+
const handler = (msg) => console.log(msg)
|
|
168
|
+
chat.on('message:received', handler)
|
|
169
|
+
chat.off('message:received', handler)
|
|
170
|
+
```
|
|
171
|
+
|
|
172
|
+
### Available Events
|
|
173
|
+
|
|
174
|
+
| Event | Payload | Description |
|
|
175
|
+
|-------|---------|-------------|
|
|
176
|
+
| `ready` | — | Widget initialized and mounted |
|
|
177
|
+
| `open` | — | Chat window opened |
|
|
178
|
+
| `close` | — | Chat window closed |
|
|
179
|
+
| `show` | — | Widget made visible |
|
|
180
|
+
| `hide` | — | Widget hidden |
|
|
181
|
+
| `message:sent` | `Message` | Visitor sent a message |
|
|
182
|
+
| `message:received` | `Message` | Agent/bot message received |
|
|
183
|
+
| `conversation:started` | `Conversation` | New conversation created |
|
|
184
|
+
| `conversation:closed` | `Conversation` | Conversation closed by agent |
|
|
185
|
+
| `identified` | `VisitorData` | Visitor identified via `identify()` |
|
|
186
|
+
|
|
187
|
+
## Identity Verification
|
|
188
|
+
|
|
189
|
+
For authenticated users, identity verification ensures visitors can only access their own conversation history. It uses HMAC-SHA256 with a secret key configured in the Baseportal dashboard.
|
|
190
|
+
|
|
191
|
+
### Server-side hash generation
|
|
192
|
+
|
|
193
|
+
```javascript
|
|
194
|
+
// Node.js
|
|
195
|
+
const crypto = require('crypto')
|
|
196
|
+
const hash = crypto
|
|
197
|
+
.createHmac('sha256', 'your-identity-verification-secret')
|
|
198
|
+
.update(userEmail)
|
|
199
|
+
.digest('hex')
|
|
200
|
+
```
|
|
201
|
+
|
|
202
|
+
```python
|
|
203
|
+
# Python
|
|
204
|
+
import hmac, hashlib
|
|
205
|
+
hash = hmac.new(
|
|
206
|
+
b'your-identity-verification-secret',
|
|
207
|
+
user_email.encode(),
|
|
208
|
+
hashlib.sha256
|
|
209
|
+
).hexdigest()
|
|
210
|
+
```
|
|
211
|
+
|
|
212
|
+
```php
|
|
213
|
+
// PHP
|
|
214
|
+
$hash = hash_hmac('sha256', $userEmail, 'your-identity-verification-secret');
|
|
215
|
+
```
|
|
216
|
+
|
|
217
|
+
```ruby
|
|
218
|
+
# Ruby
|
|
219
|
+
hash = OpenSSL::HMAC.hexdigest('SHA256', 'your-identity-verification-secret', user_email)
|
|
220
|
+
```
|
|
221
|
+
|
|
222
|
+
### Client-side usage
|
|
223
|
+
|
|
224
|
+
```typescript
|
|
225
|
+
const chat = new BaseportalChat({
|
|
226
|
+
channelToken: 'your-channel-token',
|
|
227
|
+
visitor: {
|
|
228
|
+
email: 'john@example.com',
|
|
229
|
+
name: 'John Doe',
|
|
230
|
+
hash: 'server-generated-hmac-hash',
|
|
231
|
+
},
|
|
232
|
+
})
|
|
233
|
+
```
|
|
234
|
+
|
|
235
|
+
When identity verification is enabled on the channel:
|
|
236
|
+
- `visitor.email` and `visitor.hash` are required
|
|
237
|
+
- The visitor can view their conversation history
|
|
238
|
+
- Conversations are linked to the visitor's email across sessions
|
|
239
|
+
|
|
240
|
+
## File Uploads
|
|
241
|
+
|
|
242
|
+
The widget supports file uploads directly in the chat. Visitors can attach files by clicking the paperclip icon in the composer.
|
|
243
|
+
|
|
244
|
+
**Supported file types:** Images, videos (MP4), audio, PDF, Word, Excel, and text files.
|
|
245
|
+
|
|
246
|
+
**Limits:**
|
|
247
|
+
- Max file size: 25 MB
|
|
248
|
+
- Max files per conversation: 20
|
|
249
|
+
- Rate limit: 10 uploads per minute
|
|
250
|
+
|
|
251
|
+
**Media rendering:**
|
|
252
|
+
- **Images** — displayed inline with click-to-expand lightbox
|
|
253
|
+
- **Videos** — native HTML5 video player
|
|
254
|
+
- **Other files** — download card with file name and icon
|
|
255
|
+
|
|
256
|
+
## Container Mode
|
|
257
|
+
|
|
258
|
+
Mount the widget inside a specific element instead of showing the floating bubble:
|
|
259
|
+
|
|
260
|
+
```html
|
|
261
|
+
<div id="chat-container" style="width: 400px; height: 600px;"></div>
|
|
262
|
+
|
|
263
|
+
<script>
|
|
264
|
+
const chat = new BaseportalChat({
|
|
265
|
+
channelToken: 'your-channel-token',
|
|
266
|
+
container: document.getElementById('chat-container'),
|
|
267
|
+
})
|
|
268
|
+
</script>
|
|
269
|
+
```
|
|
270
|
+
|
|
271
|
+
In container mode:
|
|
272
|
+
- No floating bubble is rendered
|
|
273
|
+
- The chat window fills the container element
|
|
274
|
+
- `show()` / `hide()` / `open()` / `close()` still work
|
|
275
|
+
|
|
276
|
+
## Channel Configuration
|
|
277
|
+
|
|
278
|
+
Features are configured per channel in the Baseportal dashboard:
|
|
279
|
+
|
|
280
|
+
| Feature | Description |
|
|
281
|
+
|---------|-------------|
|
|
282
|
+
| `requireName` | Require visitor name before starting a conversation |
|
|
283
|
+
| `requireEmail` | Require visitor email before starting a conversation |
|
|
284
|
+
| `allowViewHistory` | Allow authenticated visitors to see past conversations |
|
|
285
|
+
| `allowReopenConversation` | Allow visitors to reopen closed conversations |
|
|
286
|
+
| `privacyPolicyUrl` | Display a link to your privacy policy |
|
|
287
|
+
| Identity Verification | Enable HMAC verification for visitor identity |
|
|
288
|
+
|
|
289
|
+
## Development
|
|
290
|
+
|
|
291
|
+
```bash
|
|
292
|
+
cd packages/chat-widget
|
|
293
|
+
|
|
294
|
+
# Install dependencies
|
|
295
|
+
pnpm install
|
|
296
|
+
|
|
297
|
+
# Build
|
|
298
|
+
pnpm build
|
|
299
|
+
|
|
300
|
+
# Watch mode
|
|
301
|
+
pnpm dev
|
|
302
|
+
```
|
|
303
|
+
|
|
304
|
+
### Build outputs
|
|
305
|
+
|
|
306
|
+
| File | Format | Usage |
|
|
307
|
+
|------|--------|-------|
|
|
308
|
+
| `dist/index.iife.js` | IIFE | Script tag (global `BaseportalChat`) |
|
|
309
|
+
| `dist/index.esm.js` | ESM | `import` in bundlers |
|
|
310
|
+
| `dist/index.cjs.js` | CJS | `require()` in Node.js |
|
|
311
|
+
| `dist/index.d.ts` | TypeScript | Type definitions |
|
|
312
|
+
|
|
313
|
+
### Deploy to client
|
|
314
|
+
|
|
315
|
+
After building, copy the IIFE bundle to the client's public directory:
|
|
316
|
+
|
|
317
|
+
```bash
|
|
318
|
+
cp dist/index.iife.js ../../baseportal-client/public/baseportal-chat.iife.js
|
|
319
|
+
```
|
|
320
|
+
|
|
321
|
+
## TypeScript
|
|
322
|
+
|
|
323
|
+
All types are exported:
|
|
324
|
+
|
|
325
|
+
```typescript
|
|
326
|
+
import type {
|
|
327
|
+
BaseportalChatConfig,
|
|
328
|
+
ChannelInfo,
|
|
329
|
+
Conversation,
|
|
330
|
+
Message,
|
|
331
|
+
VisitorData,
|
|
332
|
+
} from '@baseportal/chat-widget'
|
|
333
|
+
```
|