@mobil80-dev/chatbot-widget 1.0.9 → 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.
Files changed (3) hide show
  1. package/README.md +66 -17
  2. package/index.js +105 -40
  3. package/package.json +1 -1
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
- - No iframe
11
- - No dependencies
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
- ``` bash
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 Type Description
79
- apiKey string Your VaultChat API key
80
- primaryColor string Primary UI theme color
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
@@ -12,67 +12,113 @@ const VaultChat = {
12
12
  ? 'dark'
13
13
  : 'light'
14
14
 
15
- const colors =
16
- theme === 'dark'
17
- ? {
18
- cardBg: '#0f172a',
19
- headerBorder: '#1e293b',
20
- text: '#e5e7eb',
21
- mutedText: '#94a3b8',
22
- inputBg: '#020617',
23
- inputBorder: '#334155',
24
- botBubble: '#1e293b',
25
- userText: '#ffffff',
26
- messagesBg: '#020617'
27
- }
28
- : {
29
- cardBg: '#ffffff',
30
- headerBorder: '#e5e7eb',
31
- text: '#0f172a',
32
- mutedText: '#64748b',
33
- inputBg: '#ffffff',
34
- inputBorder: '#cbd5f5',
35
- botBubble: '#e5e7eb',
36
- userText: '#ffffff',
37
- messagesBg: '#f8fafc'
38
- }
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
+ }
39
40
 
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)
41
74
 
42
75
  /* ============================
43
76
  FLOATING BUTTON
44
77
  ============================ */
45
78
  const button = document.createElement('div')
79
+ const buttonContent = config.buttonContent || '🤖'
80
+ const buttonType = config.buttonType || 'emoji'
81
+ const buttonShape = config.buttonShape || 'circle'
46
82
 
47
- if (config.buttonHtml) {
48
- button.innerHTML = config.buttonHtml
49
- } else if (config.buttonIconUrl) {
83
+ if (buttonType === 'image') {
50
84
  const img = document.createElement('img')
51
- img.src = config.buttonIconUrl
85
+ img.src = buttonContent
52
86
  img.style.width = '26px'
53
87
  img.style.height = '26px'
54
88
  img.style.objectFit = 'contain'
55
89
  button.appendChild(img)
56
- } else if (config.buttonText) {
57
- button.textContent = config.buttonText
90
+ } else if (buttonType === 'html') {
91
+ button.innerHTML = buttonContent
58
92
  } else {
59
- button.textContent = '💬'
93
+ button.textContent = buttonContent
60
94
  }
61
95
 
96
+ let borderRadius = '50%'
97
+ if (buttonShape === 'square') borderRadius = '8px'
98
+ if (buttonShape === 'pill') borderRadius = '999px'
99
+
100
+ const isTextButton = buttonType === 'text'
101
+
62
102
  Object.assign(button.style, {
63
103
  position: 'fixed',
64
104
  bottom: '20px',
65
105
  right: '20px',
66
- width: '56px',
67
- height: '56px',
68
- borderRadius: '50%',
106
+ width: isTextButton ? 'auto' : '56px',
107
+ height: isTextButton ? 'auto' : '56px',
108
+ padding: isTextButton ? '10px 16px' : '0',
109
+ minWidth: '56px',
110
+ minHeight: '56px',
111
+ borderRadius,
69
112
  background: primaryColor,
70
113
  color: '#fff',
71
114
  display: 'flex',
72
115
  alignItems: 'center',
73
116
  justifyContent: 'center',
74
117
  cursor: 'pointer',
75
- fontSize: '24px',
118
+ fontSize: '18px',
119
+ fontWeight: '500',
120
+ boxShadow: '0 8px 20px rgba(0,0,0,.25)',
121
+ userSelect: 'none',
76
122
  zIndex: 999999
77
123
  })
78
124
 
@@ -80,7 +126,6 @@ const VaultChat = {
80
126
  CHAT CARD
81
127
  ============================ */
82
128
  const card = document.createElement('div')
83
-
84
129
  card.innerHTML = `
85
130
  <div style="
86
131
  padding:12px;
@@ -143,6 +188,9 @@ const VaultChat = {
143
188
  flexDirection: 'column'
144
189
  })
145
190
 
191
+ card.style.setProperty('--vc-bot-bg', colors.botBubble)
192
+ card.style.setProperty('--vc-text-muted', colors.mutedText)
193
+
146
194
  let open = false
147
195
  button.onclick = () => {
148
196
  open = !open
@@ -173,6 +221,21 @@ const VaultChat = {
173
221
  messages.scrollTop = messages.scrollHeight
174
222
  }
175
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
+
176
239
  function addBotMessage (text) {
177
240
  const div = document.createElement('div')
178
241
  div.style.cssText = `
@@ -194,14 +257,13 @@ const VaultChat = {
194
257
  addUserMessage(text)
195
258
  input.value = ''
196
259
 
197
- // 🔐 API key missing → internal response only
198
260
  if (!config.apiKey) {
199
- addBotMessage(
200
- '⚠️ API key not configured. Please add apiKey in VaultChat.init().'
201
- )
261
+ addBotMessage('⚠️ API key not configured. Please add apiKey.')
202
262
  return
203
263
  }
204
264
 
265
+ showLoader()
266
+
205
267
  try {
206
268
  const res = await fetch('https://api.vaultchat.io/askChatbot', {
207
269
  method: 'POST',
@@ -213,12 +275,15 @@ const VaultChat = {
213
275
  })
214
276
 
215
277
  const data = await res.json()
278
+ hideLoader()
279
+
216
280
  const reply =
217
281
  data?.data?.blocks?.map(b => b.text).join('\n') ||
218
282
  'No response received'
219
283
 
220
284
  addBotMessage(reply)
221
285
  } catch {
286
+ hideLoader()
222
287
  addBotMessage('⚠️ Something went wrong')
223
288
  }
224
289
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@mobil80-dev/chatbot-widget",
3
- "version": "1.0.9",
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",