@mobil80-dev/chatbot-widget 1.0.8 → 2.0.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 +66 -17
- package/index.js +163 -27
- package/package.json +5 -2
package/README.md
CHANGED
|
@@ -4,33 +4,60 @@ A lightweight JavaScript chatbot widget powered by VaultChat, designed to be emb
|
|
|
4
4
|
|
|
5
5
|
## ✨ Features
|
|
6
6
|
|
|
7
|
-
- Floating chat button
|
|
7
|
+
- Floating chat button (fully customizable)
|
|
8
8
|
- Chat card UI
|
|
9
|
-
- API-based chatbot responses
|
|
10
|
-
-
|
|
11
|
-
- No
|
|
9
|
+
- API-based chatbot responses
|
|
10
|
+
- Light & Dark theme support
|
|
11
|
+
- No iframe
|
|
12
|
+
- No dependencies
|
|
12
13
|
- Easy setup
|
|
13
14
|
|
|
14
15
|
## 📦 Installation
|
|
15
|
-
|
|
16
|
+
|
|
17
|
+
```bash
|
|
16
18
|
npm install @mobil80-dev/chatbot-widget
|
|
17
19
|
```
|
|
18
20
|
|
|
21
|
+
## 🎨 Theme (Light / Dark)
|
|
22
|
+
|
|
23
|
+
VaultChat supports light and dark themes to match your application UI.
|
|
24
|
+
This helps improve text visibility and appearance when used inside dark-themed websites.
|
|
25
|
+
|
|
26
|
+
```
|
|
27
|
+
theme: 'light' | 'dark'
|
|
28
|
+
```
|
|
29
|
+
|
|
30
|
+
## ✅ Supported Button Types
|
|
31
|
+
|
|
32
|
+
You can use emoji, text, image, or custom HTML as the floating button.
|
|
33
|
+
|
|
34
|
+
## ✅ Supported Button Shapes
|
|
35
|
+
|
|
36
|
+
You can use circle, square, pill as the floating button shape.
|
|
37
|
+
|
|
19
38
|
## 🌐 HTML / CSS
|
|
39
|
+
|
|
20
40
|
### 🚀 Usage
|
|
41
|
+
|
|
21
42
|
```
|
|
22
43
|
<script type="module">
|
|
23
44
|
import VaultChat from 'https://unpkg.com/@mobil80-dev/chatbot-widget/dist/index.js'
|
|
24
45
|
|
|
25
46
|
VaultChat.init({
|
|
26
47
|
apiKey: 'YOUR_API_KEY',
|
|
27
|
-
primaryColor: '#7c3aed'
|
|
48
|
+
primaryColor: '#7c3aed',
|
|
49
|
+
theme: 'light' | 'dark'
|
|
50
|
+
buttonContent: '💬', // content | image Url | emote
|
|
51
|
+
buttonType: 'emoji', // emoji | text | image | html
|
|
52
|
+
buttonShape: 'circle' // circle | square | pill
|
|
28
53
|
})
|
|
29
54
|
</script>
|
|
30
55
|
```
|
|
31
56
|
|
|
32
57
|
## 🧩 Vue
|
|
58
|
+
|
|
33
59
|
### 🚀 Usage (Vue 3)
|
|
60
|
+
|
|
34
61
|
```
|
|
35
62
|
import { onMounted } from 'vue'
|
|
36
63
|
import VaultChat from '@mobil80-dev/chatbot-widget'
|
|
@@ -38,21 +65,31 @@ import VaultChat from '@mobil80-dev/chatbot-widget'
|
|
|
38
65
|
onMounted(() => {
|
|
39
66
|
VaultChat.init({
|
|
40
67
|
apiKey: 'YOUR_API_KEY',
|
|
41
|
-
primaryColor: '#7c3aed'
|
|
68
|
+
primaryColor: '#7c3aed',
|
|
69
|
+
theme: 'light' | 'dark'
|
|
70
|
+
buttonContent: '💬', // content | image Url | emote
|
|
71
|
+
buttonType: 'emoji', // emoji | text | image | html
|
|
72
|
+
buttonShape: 'circle' // circle | square | pill
|
|
42
73
|
})
|
|
43
74
|
})
|
|
44
75
|
```
|
|
76
|
+
|
|
45
77
|
## ⚛️ React
|
|
46
78
|
|
|
47
79
|
### 🚀 Usage
|
|
48
|
-
|
|
80
|
+
|
|
81
|
+
```
|
|
49
82
|
import { useEffect } from 'react'
|
|
50
83
|
import VaultChat from '@mobil80-dev/chatbot-widget'
|
|
51
84
|
|
|
52
85
|
useEffect(() => {
|
|
53
86
|
VaultChat.init({
|
|
54
87
|
apiKey: 'YOUR_API_KEY',
|
|
55
|
-
primaryColor: '#7c3aed'
|
|
88
|
+
primaryColor: '#7c3aed',
|
|
89
|
+
theme: 'light' | 'dark'
|
|
90
|
+
buttonContent: '💬', // content | image Url | emote
|
|
91
|
+
buttonType: 'emoji', // emoji | text | image | html
|
|
92
|
+
buttonShape: 'circle' // circle | square | pill
|
|
56
93
|
})
|
|
57
94
|
}, [])
|
|
58
95
|
```
|
|
@@ -60,29 +97,41 @@ useEffect(() => {
|
|
|
60
97
|
## 🅰️ Angular
|
|
61
98
|
|
|
62
99
|
### 🚀 Usage
|
|
63
|
-
|
|
100
|
+
|
|
101
|
+
```
|
|
64
102
|
import VaultChat from '@mobil80-dev/chatbot-widget'
|
|
65
103
|
|
|
66
104
|
VaultChat.init({
|
|
67
105
|
apiKey: 'YOUR_API_KEY',
|
|
68
|
-
primaryColor: '#7c3aed'
|
|
106
|
+
primaryColor: '#7c3aed',
|
|
107
|
+
theme: 'light' | 'dark'
|
|
108
|
+
buttonContent: '💬', // content | image Url | emote
|
|
109
|
+
buttonType: 'emoji', // emoji | text | image | html
|
|
110
|
+
buttonShape: 'circle' // circle | square | pill
|
|
69
111
|
})
|
|
70
112
|
|
|
71
113
|
```
|
|
72
114
|
|
|
73
|
-
|
|
74
115
|
📌 Call this inside ngOnInit() of your root or layout component.
|
|
75
116
|
|
|
76
|
-
## ⚙️ Configuration
|
|
117
|
+
## ⚙️ Configuration Reference
|
|
118
|
+
|
|
77
119
|
```
|
|
78
|
-
Option
|
|
79
|
-
|
|
80
|
-
|
|
120
|
+
| Option | Type | Description |
|
|
121
|
+
| ------------- | ------ | ----------------------------------- |
|
|
122
|
+
| apiKey | string | Your VaultChat API key |
|
|
123
|
+
| primaryColor | string | Primary UI color |
|
|
124
|
+
| theme | string | `light` or `dark` |
|
|
125
|
+
| buttonContent | string | Emoji, text, image URL, or HTML |
|
|
126
|
+
| buttonType | string | `emoji` | `text` | `image` | `html` |
|
|
127
|
+
| buttonShape | string | `circle` | `square` | `pill` |
|
|
128
|
+
|
|
81
129
|
|
|
82
130
|
```
|
|
131
|
+
|
|
83
132
|
## 📄 License
|
|
84
133
|
|
|
85
134
|
```
|
|
86
135
|
MIT
|
|
87
136
|
Mobil80
|
|
88
|
-
```
|
|
137
|
+
```
|
package/index.js
CHANGED
|
@@ -1,46 +1,154 @@
|
|
|
1
1
|
const VaultChat = {
|
|
2
2
|
init (config = {}) {
|
|
3
|
+
/* ============================
|
|
4
|
+
THEME RESOLUTION
|
|
5
|
+
============================ */
|
|
6
|
+
const theme =
|
|
7
|
+
config.theme === 'dark'
|
|
8
|
+
? 'dark'
|
|
9
|
+
: config.theme === 'light'
|
|
10
|
+
? 'light'
|
|
11
|
+
: window.matchMedia('(prefers-color-scheme: dark)').matches
|
|
12
|
+
? 'dark'
|
|
13
|
+
: 'light'
|
|
14
|
+
|
|
15
|
+
const isDark = theme === 'dark'
|
|
16
|
+
|
|
17
|
+
const colors = isDark
|
|
18
|
+
? {
|
|
19
|
+
cardBg: '#0f172a',
|
|
20
|
+
headerBorder: '#1e293b',
|
|
21
|
+
text: '#e5e7eb',
|
|
22
|
+
mutedText: '#94a3b8',
|
|
23
|
+
inputBg: '#020617',
|
|
24
|
+
inputBorder: '#334155',
|
|
25
|
+
botBubble: '#1e293b',
|
|
26
|
+
userText: '#ffffff',
|
|
27
|
+
messagesBg: '#020617'
|
|
28
|
+
}
|
|
29
|
+
: {
|
|
30
|
+
cardBg: '#ffffff',
|
|
31
|
+
headerBorder: '#e5e7eb',
|
|
32
|
+
text: '#0f172a',
|
|
33
|
+
mutedText: '#64748b',
|
|
34
|
+
inputBg: '#ffffff',
|
|
35
|
+
inputBorder: '#cbd5f5',
|
|
36
|
+
botBubble: '#e5e7eb',
|
|
37
|
+
userText: '#ffffff',
|
|
38
|
+
messagesBg: '#f8fafc'
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
const primaryColor = config.primaryColor || '#2563eb'
|
|
42
|
+
let loaderEl = null
|
|
43
|
+
|
|
44
|
+
/* ============================
|
|
45
|
+
LOADER STYLES (Injected once)
|
|
46
|
+
============================ */
|
|
47
|
+
const style = document.createElement('style')
|
|
48
|
+
style.innerHTML = `
|
|
49
|
+
.vc-loader {
|
|
50
|
+
display: inline-flex;
|
|
51
|
+
gap: 6px;
|
|
52
|
+
padding: 8px 12px;
|
|
53
|
+
background: var(--vc-bot-bg);
|
|
54
|
+
border-radius: 12px;
|
|
55
|
+
max-width: 80%;
|
|
56
|
+
margin-bottom: 8px;
|
|
57
|
+
}
|
|
58
|
+
.vc-loader span {
|
|
59
|
+
width: 6px;
|
|
60
|
+
height: 6px;
|
|
61
|
+
background: var(--vc-text-muted);
|
|
62
|
+
border-radius: 50%;
|
|
63
|
+
animation: vc-bounce 1.4s infinite ease-in-out both;
|
|
64
|
+
}
|
|
65
|
+
.vc-loader span:nth-child(1) { animation-delay: -0.32s; }
|
|
66
|
+
.vc-loader span:nth-child(2) { animation-delay: -0.16s; }
|
|
67
|
+
|
|
68
|
+
@keyframes vc-bounce {
|
|
69
|
+
0%, 80%, 100% { transform: scale(0); }
|
|
70
|
+
40% { transform: scale(1); }
|
|
71
|
+
}
|
|
72
|
+
`
|
|
73
|
+
document.head.appendChild(style)
|
|
74
|
+
|
|
75
|
+
/* ============================
|
|
76
|
+
FLOATING BUTTON
|
|
77
|
+
============================ */
|
|
3
78
|
const button = document.createElement('div')
|
|
4
|
-
|
|
79
|
+
const buttonContent = config.buttonContent || '🤖'
|
|
80
|
+
const buttonType = config.buttonType || 'emoji'
|
|
81
|
+
const buttonShape = config.buttonShape || 'circle'
|
|
82
|
+
|
|
83
|
+
if (buttonType === 'image') {
|
|
84
|
+
const img = document.createElement('img')
|
|
85
|
+
img.src = buttonContent
|
|
86
|
+
img.style.width = '26px'
|
|
87
|
+
img.style.height = '26px'
|
|
88
|
+
img.style.objectFit = 'contain'
|
|
89
|
+
button.appendChild(img)
|
|
90
|
+
} else if (buttonType === 'html') {
|
|
91
|
+
button.innerHTML = buttonContent
|
|
92
|
+
} else {
|
|
93
|
+
button.textContent = buttonContent
|
|
94
|
+
}
|
|
95
|
+
|
|
96
|
+
let borderRadius = '50%'
|
|
97
|
+
if (buttonShape === 'square') borderRadius = '8px'
|
|
98
|
+
if (buttonShape === 'pill') borderRadius = '999px'
|
|
99
|
+
|
|
100
|
+
const isTextButton = buttonType === 'text'
|
|
5
101
|
|
|
6
102
|
Object.assign(button.style, {
|
|
7
103
|
position: 'fixed',
|
|
8
104
|
bottom: '20px',
|
|
9
105
|
right: '20px',
|
|
10
|
-
width: '56px',
|
|
11
|
-
height: '56px',
|
|
12
|
-
|
|
13
|
-
|
|
106
|
+
width: isTextButton ? 'auto' : '56px',
|
|
107
|
+
height: isTextButton ? 'auto' : '56px',
|
|
108
|
+
padding: isTextButton ? '10px 16px' : '0',
|
|
109
|
+
minWidth: '56px',
|
|
110
|
+
minHeight: '56px',
|
|
111
|
+
borderRadius,
|
|
112
|
+
background: primaryColor,
|
|
14
113
|
color: '#fff',
|
|
15
114
|
display: 'flex',
|
|
16
115
|
alignItems: 'center',
|
|
17
116
|
justifyContent: 'center',
|
|
18
117
|
cursor: 'pointer',
|
|
19
|
-
fontSize: '
|
|
20
|
-
|
|
118
|
+
fontSize: '18px',
|
|
119
|
+
fontWeight: '500',
|
|
120
|
+
boxShadow: '0 8px 20px rgba(0,0,0,.25)',
|
|
121
|
+
userSelect: 'none',
|
|
122
|
+
zIndex: 999999
|
|
21
123
|
})
|
|
22
124
|
|
|
125
|
+
/* ============================
|
|
126
|
+
CHAT CARD
|
|
127
|
+
============================ */
|
|
23
128
|
const card = document.createElement('div')
|
|
24
129
|
card.innerHTML = `
|
|
25
|
-
<div style="
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
Powered by <strong>VaultChat</strong>
|
|
33
|
-
</div>
|
|
130
|
+
<div style="
|
|
131
|
+
padding:12px;
|
|
132
|
+
border-bottom:1px solid ${colors.headerBorder};
|
|
133
|
+
color:${colors.mutedText};
|
|
134
|
+
font-size:14px;
|
|
135
|
+
user-select:none">
|
|
136
|
+
Powered by <strong>VaultChat</strong>
|
|
34
137
|
</div>
|
|
35
138
|
|
|
36
139
|
<div id="vc-messages" style="
|
|
37
140
|
flex:1;
|
|
38
141
|
padding:12px;
|
|
39
142
|
overflow-y:auto;
|
|
40
|
-
background
|
|
143
|
+
background:${colors.messagesBg};
|
|
144
|
+
color:${colors.text}">
|
|
41
145
|
</div>
|
|
42
146
|
|
|
43
|
-
<div style="
|
|
147
|
+
<div style="
|
|
148
|
+
display:flex;
|
|
149
|
+
padding:10px;
|
|
150
|
+
border-top:1px solid ${colors.headerBorder};
|
|
151
|
+
background:${colors.cardBg}">
|
|
44
152
|
<input
|
|
45
153
|
id="vc-input"
|
|
46
154
|
placeholder="Type your message..."
|
|
@@ -48,7 +156,9 @@ const VaultChat = {
|
|
|
48
156
|
flex:1;
|
|
49
157
|
padding:10px;
|
|
50
158
|
border-radius:8px;
|
|
51
|
-
border:1px solid
|
|
159
|
+
border:1px solid ${colors.inputBorder};
|
|
160
|
+
background:${colors.inputBg};
|
|
161
|
+
color:${colors.text};
|
|
52
162
|
outline:none"
|
|
53
163
|
/>
|
|
54
164
|
<button id="vc-send" style="
|
|
@@ -56,7 +166,7 @@ const VaultChat = {
|
|
|
56
166
|
padding:0 14px;
|
|
57
167
|
border:none;
|
|
58
168
|
border-radius:8px;
|
|
59
|
-
background:${
|
|
169
|
+
background:${primaryColor};
|
|
60
170
|
color:white;
|
|
61
171
|
cursor:pointer">
|
|
62
172
|
➤
|
|
@@ -70,14 +180,17 @@ const VaultChat = {
|
|
|
70
180
|
right: '20px',
|
|
71
181
|
width: '400px',
|
|
72
182
|
height: '420px',
|
|
73
|
-
background:
|
|
183
|
+
background: colors.cardBg,
|
|
74
184
|
borderRadius: '12px',
|
|
75
185
|
boxShadow: '0 10px 30px rgba(0,0,0,.3)',
|
|
76
|
-
zIndex:
|
|
186
|
+
zIndex: 999999,
|
|
77
187
|
display: 'none',
|
|
78
188
|
flexDirection: 'column'
|
|
79
189
|
})
|
|
80
190
|
|
|
191
|
+
card.style.setProperty('--vc-bot-bg', colors.botBubble)
|
|
192
|
+
card.style.setProperty('--vc-text-muted', colors.mutedText)
|
|
193
|
+
|
|
81
194
|
let open = false
|
|
82
195
|
button.onclick = () => {
|
|
83
196
|
open = !open
|
|
@@ -87,6 +200,9 @@ const VaultChat = {
|
|
|
87
200
|
document.body.appendChild(button)
|
|
88
201
|
document.body.appendChild(card)
|
|
89
202
|
|
|
203
|
+
/* ============================
|
|
204
|
+
CHAT LOGIC
|
|
205
|
+
============================ */
|
|
90
206
|
const messages = card.querySelector('#vc-messages')
|
|
91
207
|
const input = card.querySelector('#vc-input')
|
|
92
208
|
const sendBtn = card.querySelector('#vc-send')
|
|
@@ -94,8 +210,8 @@ const VaultChat = {
|
|
|
94
210
|
function addUserMessage (text) {
|
|
95
211
|
const div = document.createElement('div')
|
|
96
212
|
div.style.cssText = `
|
|
97
|
-
background:${
|
|
98
|
-
color
|
|
213
|
+
background:${primaryColor};
|
|
214
|
+
color:${colors.userText};
|
|
99
215
|
padding:8px 12px;
|
|
100
216
|
border-radius:12px;
|
|
101
217
|
max-width:80%;
|
|
@@ -105,10 +221,26 @@ const VaultChat = {
|
|
|
105
221
|
messages.scrollTop = messages.scrollHeight
|
|
106
222
|
}
|
|
107
223
|
|
|
224
|
+
function showLoader () {
|
|
225
|
+
loaderEl = document.createElement('div')
|
|
226
|
+
loaderEl.className = 'vc-loader'
|
|
227
|
+
loaderEl.innerHTML = '<span></span><span></span><span></span>'
|
|
228
|
+
messages.appendChild(loaderEl)
|
|
229
|
+
messages.scrollTop = messages.scrollHeight
|
|
230
|
+
}
|
|
231
|
+
|
|
232
|
+
function hideLoader () {
|
|
233
|
+
if (loaderEl) {
|
|
234
|
+
loaderEl.remove()
|
|
235
|
+
loaderEl = null
|
|
236
|
+
}
|
|
237
|
+
}
|
|
238
|
+
|
|
108
239
|
function addBotMessage (text) {
|
|
109
240
|
const div = document.createElement('div')
|
|
110
241
|
div.style.cssText = `
|
|
111
|
-
background
|
|
242
|
+
background:${colors.botBubble};
|
|
243
|
+
color:${colors.text};
|
|
112
244
|
padding:8px 12px;
|
|
113
245
|
border-radius:12px;
|
|
114
246
|
max-width:80%;
|
|
@@ -125,12 +257,13 @@ const VaultChat = {
|
|
|
125
257
|
addUserMessage(text)
|
|
126
258
|
input.value = ''
|
|
127
259
|
|
|
128
|
-
// ✅ apiKey not configured → internal message only
|
|
129
260
|
if (!config.apiKey) {
|
|
130
|
-
addBotMessage('⚠️ API key not configured. Please add apiKey
|
|
261
|
+
addBotMessage('⚠️ API key not configured. Please add apiKey.')
|
|
131
262
|
return
|
|
132
263
|
}
|
|
133
264
|
|
|
265
|
+
showLoader()
|
|
266
|
+
|
|
134
267
|
try {
|
|
135
268
|
const res = await fetch('https://api.vaultchat.io/askChatbot', {
|
|
136
269
|
method: 'POST',
|
|
@@ -142,12 +275,15 @@ const VaultChat = {
|
|
|
142
275
|
})
|
|
143
276
|
|
|
144
277
|
const data = await res.json()
|
|
278
|
+
hideLoader()
|
|
279
|
+
|
|
145
280
|
const reply =
|
|
146
281
|
data?.data?.blocks?.map(b => b.text).join('\n') ||
|
|
147
282
|
'No response received'
|
|
148
283
|
|
|
149
284
|
addBotMessage(reply)
|
|
150
285
|
} catch {
|
|
286
|
+
hideLoader()
|
|
151
287
|
addBotMessage('⚠️ Something went wrong')
|
|
152
288
|
}
|
|
153
289
|
}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@mobil80-dev/chatbot-widget",
|
|
3
|
-
"version": "
|
|
3
|
+
"version": "2.0.0",
|
|
4
4
|
"description": "Drop-in JavaScript chat widget for websites (no iframe, no framework)",
|
|
5
5
|
"main": "index.js",
|
|
6
6
|
"type": "module",
|
|
@@ -12,5 +12,8 @@
|
|
|
12
12
|
"vaultchat"
|
|
13
13
|
],
|
|
14
14
|
"author": "Nantha Gopal",
|
|
15
|
-
"license": "MIT"
|
|
15
|
+
"license": "MIT",
|
|
16
|
+
"dependencies": {
|
|
17
|
+
"@mobil80-dev/chatbot-widget": "^1.0.8"
|
|
18
|
+
}
|
|
16
19
|
}
|