tenovabot-vue 1.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 ADDED
@@ -0,0 +1,200 @@
1
+ # vue-ai-chatbubble
2
+
3
+ 🤖 A beautiful floating AI chatbot widget for Vue 3 — appears as a bouncing ball in the bottom-right corner that opens into a sleek chat interface.
4
+
5
+ ![Vue 3](https://img.shields.io/badge/Vue-3.x-42b883)
6
+ ![License](https://img.shields.io/badge/license-MIT-blue)
7
+
8
+ ## ✨ Features
9
+
10
+ - 🎈 **Bouncing Bubble** — Eye-catching hopping animation draws user attention
11
+ - 🎨 **Dark Modern UI** — Beautiful glassmorphism design with smooth animations
12
+ - 💬 **Real-time Chat** — Message bubbles with typing indicators
13
+ - 🔌 **AI-Ready** — Connect to any AI API (OpenAI, Claude, custom backends)
14
+ - 📱 **Responsive** — Works perfectly on mobile and desktop
15
+ - ⚙️ **Customizable** — Colors, text, avatar, and behavior options
16
+
17
+ ## 📦 Installation
18
+
19
+ ```bash
20
+ npm install vue-ai-chatbubble
21
+ ```
22
+
23
+ ## 🚀 Quick Start
24
+
25
+ ### Option 1: Global Registration (Plugin)
26
+
27
+ ```javascript
28
+ // main.js
29
+ import { createApp } from 'vue'
30
+ import App from './App.vue'
31
+ import VueAIChatBubble from 'vue-ai-chatbubble'
32
+ import 'vue-ai-chatbubble/dist/style.css'
33
+
34
+ const app = createApp(App)
35
+ app.use(VueAIChatBubble)
36
+ app.mount('#app')
37
+ ```
38
+
39
+ Then use anywhere in your app:
40
+
41
+ ```vue
42
+ <template>
43
+ <ChatBubble
44
+ bot-name="AI Helper"
45
+ welcome-message="Hi! How can I assist you today?"
46
+ api-endpoint="https://your-api.com/chat"
47
+ />
48
+ </template>
49
+ ```
50
+
51
+ ### Option 2: Local Import
52
+
53
+ ```vue
54
+ <template>
55
+ <ChatBubble
56
+ bot-name="Assistant"
57
+ primary-color="#8b5cf6"
58
+ @message-sent="handleSent"
59
+ @message-received="handleReceived"
60
+ />
61
+ </template>
62
+
63
+ <script setup>
64
+ import { ChatBubble } from 'vue-ai-chatbubble'
65
+ import 'vue-ai-chatbubble/dist/style.css'
66
+
67
+ const handleSent = (message) => {
68
+ console.log('User sent:', message.text)
69
+ }
70
+
71
+ const handleReceived = (message) => {
72
+ console.log('Bot replied:', message.text)
73
+ }
74
+ </script>
75
+ ```
76
+
77
+ ## 🔧 Props
78
+
79
+ | Prop | Type | Default | Description |
80
+ |------|------|---------|-------------|
81
+ | `botName` | `String` | `'AI Assistant'` | Name displayed in the chat header |
82
+ | `avatarUrl` | `String` | `''` | URL for the bot's avatar image |
83
+ | `statusText` | `String` | `'Online'` | Status text shown below bot name |
84
+ | `inputPlaceholder` | `String` | `'Type your message...'` | Placeholder for the input field |
85
+ | `welcomeMessage` | `String` | `'Hello! 👋 How can I help you today?'` | First message shown when chat opens |
86
+ | `primaryColor` | `String` | `'#6366f1'` | Primary theme color (hex) |
87
+ | `position` | `String` | `'right'` | Position: `'left'` or `'right'` |
88
+ | `apiEndpoint` | `String` | `''` | URL to your chat API |
89
+ | `apiHeaders` | `Object` | `{}` | Additional headers for API requests |
90
+ | `audioVolume` | `Number` | `0.8` | Volume for audio responses (0.0 to 1.0) |
91
+
92
+ ## 📡 Events
93
+
94
+ | Event | Payload | Description |
95
+ |-------|---------|-------------|
96
+ | `@open` | — | Emitted when chat window opens |
97
+ | `@close` | — | Emitted when chat window closes |
98
+ | `@message-sent` | `{ text, timestamp }` | Emitted when user sends a message |
99
+ | `@message-received` | `{ text, timestamp }` | Emitted when bot responds |
100
+
101
+ ## 🤖 Connecting to AI APIs
102
+
103
+ ### Example: OpenAI Integration
104
+
105
+ ```vue
106
+ <template>
107
+ <ChatBubble
108
+ bot-name="GPT Assistant"
109
+ api-endpoint="/api/chat"
110
+ :api-headers="{ 'Authorization': 'Bearer your-key' }"
111
+ />
112
+ </template>
113
+ ```
114
+
115
+ Your backend endpoint should accept POST requests with:
116
+ ```json
117
+ {
118
+ "message": "user's message here"
119
+ }
120
+ ```
121
+
122
+ And respond with:
123
+ ```json
124
+ {
125
+ "response": "AI's reply here"
126
+ }
127
+ ```
128
+
129
+ ### Example: Custom Backend (Express.js)
130
+
131
+ ```javascript
132
+ // server.js
133
+ app.post('/api/chat', async (req, res) => {
134
+ const { message } = req.body
135
+
136
+ // Call your AI service
137
+ const aiResponse = await callOpenAI(message)
138
+
139
+ res.json({ response: aiResponse })
140
+ })
141
+ ```
142
+
143
+ ## 🎨 Customization Examples
144
+
145
+ ### Purple Theme
146
+ ```vue
147
+ <ChatBubble
148
+ primary-color="#8b5cf6"
149
+ bot-name="Violet"
150
+ />
151
+ ```
152
+
153
+ ### Custom Avatar
154
+ ```vue
155
+ <ChatBubble
156
+ avatar-url="https://your-domain.com/bot-avatar.png"
157
+ bot-name="Custom Bot"
158
+ />
159
+ ```
160
+
161
+ ### Full Configuration
162
+ ```vue
163
+ <ChatBubble
164
+ bot-name="Support Bot"
165
+ avatar-url="/images/support-avatar.png"
166
+ status-text="Always here to help"
167
+ input-placeholder="Ask me anything..."
168
+ welcome-message="Welcome! I'm here to answer your questions."
169
+ primary-color="#10b981"
170
+ api-endpoint="https://api.yoursite.com/chat"
171
+ :api-headers="{ 'X-API-Key': 'your-key' }"
172
+ @open="trackChatOpened"
173
+ @message-sent="logMessage"
174
+ />
175
+ ```
176
+
177
+ ## 📱 Mobile Support
178
+
179
+ The widget automatically adapts to mobile screens with:
180
+ - Smaller bubble button
181
+ - Full-width chat window
182
+ - Touch-optimized interface
183
+
184
+ ## 🛠️ Development
185
+
186
+ ```bash
187
+ # Install dependencies
188
+ npm install
189
+
190
+ # Start dev server
191
+ npm run dev
192
+
193
+ # Build for production
194
+ npm run build
195
+ ```
196
+
197
+ ## 📄 License
198
+
199
+ MIT © 2024
200
+
@@ -0,0 +1 @@
1
+ :root{--cb-primary: #6366f1;--cb-primary-hover: #4f46e5;--cb-primary-light: #eef2ff;--cb-primary-subtle: rgba(99, 102, 241, .08);--cb-bg: #ffffff;--cb-bg-secondary: #f8fafc;--cb-surface: #f1f5f9;--cb-text: #1e293b;--cb-text-secondary: #64748b;--cb-text-muted: #94a3b8;--cb-border: #e2e8f0;--cb-border-light: #f1f5f9;--cb-shadow-sm: 0 1px 2px rgba(0, 0, 0, .04);--cb-shadow: 0 4px 24px rgba(0, 0, 0, .08);--cb-shadow-lg: 0 12px 48px rgba(0, 0, 0, .12);--cb-radius: 16px;--cb-radius-sm: 10px;--cb-radius-xs: 6px}.ai-glow-bar{position:fixed;top:0;left:0;right:0;height:3px;z-index:999999;overflow:hidden}.glow-line{position:absolute;top:0;left:0;right:0;height:100%;background:linear-gradient(90deg,var(--cb-primary) 0%,#818cf8 30%,#a78bfa 50%,#818cf8 70%,var(--cb-primary) 100%);background-size:200% 100%;animation:cb-glow-wave 1.8s ease-in-out infinite}@keyframes cb-glow-wave{0%,to{background-position:0% 50%}50%{background-position:100% 50%}}.glow-fade-enter-active{animation:cb-fade-in .3s ease-out}.glow-fade-leave-active{animation:cb-fade-in .4s ease-in reverse}@keyframes cb-fade-in{0%{opacity:0}to{opacity:1}}.vue-chatbubble-container{position:fixed;bottom:24px;right:24px;z-index:99999;font-family:-apple-system,BlinkMacSystemFont,Segoe UI,Inter,Roboto,sans-serif;-webkit-font-smoothing:antialiased;-moz-osx-font-smoothing:grayscale}.chat-bubble-btn{width:60px;height:60px;border-radius:50%;border:none;background:var(--cb-primary);color:#fff;cursor:pointer;display:flex;align-items:center;justify-content:center;box-shadow:0 4px 14px #6366f159,0 0 #6366f133;transition:all .3s cubic-bezier(.4,0,.2,1);animation:cb-float 3s ease-in-out infinite;position:relative}.chat-bubble-btn:hover{transform:scale(1.08) translateY(-2px);box-shadow:0 8px 28px #6366f166,0 0 0 6px #6366f11a;animation:none}.chat-bubble-btn.is-open{animation:none;background:var(--cb-text);box-shadow:0 4px 14px #00000026}.chat-bubble-btn.is-open:hover{box-shadow:0 8px 28px #0003}.bubble-icon{width:26px;height:26px;display:flex;align-items:center;justify-content:center;transition:transform .3s ease}.bubble-icon svg{width:100%;height:100%}.close-icon{transform:rotate(0)}@keyframes cb-float{0%,to{transform:translateY(0)}50%{transform:translateY(-6px)}}.chat-window{position:absolute;bottom:76px;right:0;width:400px;height:580px;background:var(--cb-bg);border-radius:20px;box-shadow:var(--cb-shadow-lg),0 0 0 1px #0000000a;display:flex;flex-direction:column;overflow:hidden}.chat-slide-enter-active{animation:cb-chat-in .35s cubic-bezier(.34,1.56,.64,1)}.chat-slide-leave-active{animation:cb-chat-in .25s ease reverse}@keyframes cb-chat-in{0%{opacity:0;transform:translateY(16px) scale(.96)}to{opacity:1;transform:translateY(0) scale(1)}}.chat-header{display:flex;align-items:center;justify-content:space-between;padding:18px 20px;background:var(--cb-bg);border-bottom:1px solid var(--cb-border)}.header-left{display:flex;align-items:center;gap:12px}.header-avatar{width:40px;height:40px;border-radius:12px;overflow:hidden;background:var(--cb-primary);display:flex;align-items:center;justify-content:center;flex-shrink:0}.header-avatar img{width:100%;height:100%;object-fit:cover}.avatar-fallback{color:#fff;font-size:16px;font-weight:700}.header-info{flex:1}.bot-name{margin:0;font-size:15px;font-weight:650;color:var(--cb-text);letter-spacing:-.01em}.bot-status{display:flex;align-items:center;gap:5px;font-size:12px;color:var(--cb-text-muted);margin-top:1px}.status-dot{width:7px;height:7px;border-radius:50%;background:#22c55e}.close-btn{width:34px;height:34px;border-radius:10px;border:none;background:var(--cb-surface);color:var(--cb-text-secondary);cursor:pointer;display:flex;align-items:center;justify-content:center;transition:all .2s ease}.close-btn:hover{background:var(--cb-border);color:var(--cb-text)}.close-btn svg{width:16px;height:16px}.chat-messages{flex:1;overflow-y:auto;padding:20px;display:flex;flex-direction:column;gap:20px;background:var(--cb-bg-secondary)}.chat-messages::-webkit-scrollbar{width:5px}.chat-messages::-webkit-scrollbar-track{background:transparent}.chat-messages::-webkit-scrollbar-thumb{background:var(--cb-border);border-radius:3px}.message{display:flex;gap:10px;animation:cb-msg-in .3s ease}@keyframes cb-msg-in{0%{opacity:0;transform:translateY(8px)}to{opacity:1;transform:translateY(0)}}.message.bot{justify-content:flex-start;align-items:flex-start}.message.user{justify-content:flex-end}.msg-avatar{width:30px;height:30px;border-radius:9px;overflow:hidden;background:var(--cb-primary);display:flex;align-items:center;justify-content:center;flex-shrink:0;margin-top:2px}.msg-avatar img{width:100%;height:100%;object-fit:cover}.msg-avatar span{color:#fff;font-size:12px;font-weight:700}.message-bubble{max-width:80%;padding:10px 14px;border-radius:var(--cb-radius);position:relative}.message.bot .message-bubble{background:var(--cb-bg);border:1px solid var(--cb-border);border-top-left-radius:var(--cb-radius-xs);box-shadow:var(--cb-shadow-sm)}.message.user .message-bubble{background:var(--cb-primary);border-top-right-radius:var(--cb-radius-xs);box-shadow:0 2px 8px #6366f133}.message-bubble p{margin:0;font-size:14px;line-height:1.55;color:var(--cb-text);word-wrap:break-word}.message.user .message-bubble p{color:#fff}.message.system-message .message-bubble{background:#fef2f2;border:1px solid #fecaca;border-top-left-radius:var(--cb-radius-xs)}.message.system-message .message-bubble p{color:#dc2626}.markdown-content{font-size:14px;line-height:1.6;color:var(--cb-text);word-wrap:break-word}.markdown-content p{margin:0 0 10px}.markdown-content p:last-child{margin-bottom:0}.markdown-content h1,.markdown-content h2,.markdown-content h3,.markdown-content h4{margin:14px 0 6px;font-weight:650;color:var(--cb-text)}.markdown-content h1{font-size:1.3em}.markdown-content h2{font-size:1.15em}.markdown-content h3{font-size:1.05em}.markdown-content h4{font-size:1em}.markdown-content h1:first-child,.markdown-content h2:first-child,.markdown-content h3:first-child{margin-top:0}.markdown-content .table-wrapper{overflow-x:auto;margin:8px 0;border-radius:var(--cb-radius-xs);border:1px solid var(--cb-border)}.markdown-content table{width:max-content;min-width:100%;border-collapse:collapse;font-size:12px;white-space:nowrap}.markdown-content thead{background:var(--cb-surface)}.markdown-content th{padding:8px 10px;text-align:left;font-weight:600;color:var(--cb-text);font-size:11px;text-transform:uppercase;letter-spacing:.3px;border-bottom:1px solid var(--cb-border)}.markdown-content td{padding:7px 10px;border-bottom:1px solid var(--cb-border-light);color:var(--cb-text);max-width:140px;overflow:hidden;text-overflow:ellipsis}.markdown-content tr:last-child td{border-bottom:none}.markdown-content tbody tr:hover{background:var(--cb-primary-subtle)}.markdown-content .table-wrapper::-webkit-scrollbar{height:4px}.markdown-content .table-wrapper::-webkit-scrollbar-track{background:var(--cb-surface)}.markdown-content .table-wrapper::-webkit-scrollbar-thumb{background:var(--cb-border);border-radius:2px}.markdown-content code{background:var(--cb-primary-light);color:var(--cb-primary);padding:2px 6px;border-radius:4px;font-family:SF Mono,JetBrains Mono,Fira Code,monospace;font-size:12.5px}.markdown-content pre{background:#1e293b;border-radius:var(--cb-radius-sm);padding:14px;overflow-x:auto;margin:10px 0}.markdown-content pre code{background:none;padding:0;color:#e2e8f0;font-size:12.5px}.markdown-content ul,.markdown-content ol{margin:6px 0;padding-left:20px}.markdown-content li{margin:3px 0;color:var(--cb-text)}.markdown-content ul li::marker{color:var(--cb-primary)}.markdown-content ol li::marker{color:var(--cb-primary);font-weight:600}.markdown-content a{color:var(--cb-primary);text-decoration:none;font-weight:500}.markdown-content a:hover{text-decoration:underline}.markdown-content blockquote{margin:10px 0;padding:8px 14px;border-left:3px solid var(--cb-primary);background:var(--cb-primary-subtle);border-radius:0 var(--cb-radius-xs) var(--cb-radius-xs) 0}.markdown-content blockquote p{margin:0;font-style:italic;color:var(--cb-text-secondary)}.markdown-content hr{border:none;height:1px;background:var(--cb-border);margin:14px 0}.markdown-content strong{font-weight:650;color:var(--cb-text)}.markdown-content em{font-style:italic}.markdown-content input[type=checkbox]{margin-right:6px;accent-color:var(--cb-primary)}.message-time{display:block;font-size:10.5px;color:var(--cb-text-muted);margin-top:5px;opacity:.8}.message.user .message-time{text-align:right;color:#ffffffa6}.typing-indicator .message-bubble{padding:14px 18px}.typing-dots{display:flex;gap:4px;align-items:center}.typing-dots span{width:7px;height:7px;border-radius:50%;background:var(--cb-text-muted);animation:cb-typing 1.4s ease-in-out infinite}.typing-dots span:nth-child(1){animation-delay:0s}.typing-dots span:nth-child(2){animation-delay:.15s}.typing-dots span:nth-child(3){animation-delay:.3s}@keyframes cb-typing{0%,60%,to{transform:translateY(0);opacity:.35}30%{transform:translateY(-6px);opacity:1}}.function-executing .message-bubble{background:var(--cb-primary-light)!important;border:1px solid rgba(99,102,241,.15)!important}.function-bubble{padding:12px 16px!important}.function-indicator{display:flex;align-items:center;gap:10px}.function-spinner{width:15px;height:15px;border:2px solid rgba(99,102,241,.2);border-top-color:var(--cb-primary);border-radius:50%;animation:cb-spin .7s linear infinite}.function-text{font-size:13px;color:var(--cb-primary);font-weight:550}@keyframes cb-spin{to{transform:rotate(360deg)}}.chat-input-wrapper{padding:14px 16px;background:var(--cb-bg);border-top:1px solid var(--cb-border)}.chat-input-container{display:flex;align-items:flex-end;gap:10px;padding:8px 8px 8px 16px;background:var(--cb-bg-secondary);border:1.5px solid var(--cb-border);border-radius:var(--cb-radius);transition:all .2s ease}.chat-input-container textarea{flex:1;border:none;background:transparent;color:var(--cb-text);font-size:14px;line-height:1.5;outline:none;resize:none;min-height:22px;max-height:120px;padding:4px 0;font-family:inherit}.chat-input-container textarea:disabled{opacity:.5}.input-hint{display:block;font-size:10.5px;color:var(--cb-text-muted);margin-top:6px;text-align:center;opacity:.7}.send-btn{width:36px;height:36px;border-radius:var(--cb-radius-sm);border:none;background:var(--cb-primary);color:#fff;cursor:pointer;display:flex;align-items:center;justify-content:center;transition:all .2s ease;flex-shrink:0}.send-btn:hover:not(:disabled){background:var(--cb-primary-hover);transform:scale(1.05)}.send-btn:disabled{background:var(--cb-border);color:var(--cb-text-muted);cursor:not-allowed}.send-btn svg{width:16px;height:16px}.modal-fade-enter-active,.modal-fade-leave-active{transition:opacity .3s ease}.modal-fade-enter-from,.modal-fade-leave-to{opacity:0}.rating-modal-overlay{position:fixed;top:0;left:0;right:0;bottom:0;background:#0f172a80;-webkit-backdrop-filter:blur(4px);backdrop-filter:blur(4px);display:flex;align-items:center;justify-content:center;z-index:999998;padding:20px}.rating-modal-panel{background:var(--cb-bg);border:1px solid var(--cb-border);border-radius:24px;padding:32px;max-width:380px;width:100%;box-shadow:var(--cb-shadow-lg);animation:cb-modal-in .3s cubic-bezier(.34,1.56,.64,1);text-align:center}@keyframes cb-modal-in{0%{opacity:0;transform:scale(.94) translateY(12px)}to{opacity:1;transform:scale(1) translateY(0)}}.rating-icon{width:48px;height:48px;margin:0 auto 16px;background:var(--cb-primary-light);border-radius:14px;display:flex;align-items:center;justify-content:center}.rating-icon svg{width:24px;height:24px;color:var(--cb-primary)}.rating-title{margin:0 0 4px;font-size:18px;font-weight:700;color:var(--cb-text)}.rating-subtitle{margin:0 0 24px;font-size:13px;color:var(--cb-text-muted)}.rating-stars{display:flex;gap:6px;justify-content:center;margin-bottom:24px}.star-btn{width:48px;height:48px;background:var(--cb-bg-secondary);border:1.5px solid var(--cb-border);border-radius:12px;cursor:pointer;transition:all .2s ease;display:flex;align-items:center;justify-content:center}.star-btn:hover{border-color:var(--cb-primary);background:var(--cb-primary-light);transform:translateY(-2px)}.star-btn.selected{background:var(--cb-primary);border-color:var(--cb-primary)}.star-number{font-size:16px;font-weight:700;color:var(--cb-text-secondary);transition:color .2s}.star-btn:hover .star-number{color:var(--cb-primary)}.star-btn.selected .star-number{color:#fff}.rating-actions{display:flex;flex-direction:column;gap:8px}.rating-submit-btn,.rating-skip-btn{width:100%;padding:12px 20px;border-radius:12px;font-size:14px;font-weight:600;cursor:pointer;transition:all .2s ease;border:none}.rating-submit-btn{background:var(--cb-primary);color:#fff}.rating-submit-btn:hover:not(:disabled){background:var(--cb-primary-hover)}.rating-submit-btn:disabled{opacity:.4;cursor:not-allowed}.rating-skip-btn{background:transparent;color:var(--cb-text-muted)}.rating-skip-btn:hover{color:var(--cb-text-secondary);background:var(--cb-surface)}@media (max-width: 480px){.vue-chatbubble-container{bottom:16px;right:16px}.chat-window{position:fixed;top:0;left:0;right:0;bottom:0;width:100vw;height:100vh;height:100dvh;max-height:none;border-radius:0;z-index:999999;box-shadow:none}.chat-header{padding-top:calc(16px + env(safe-area-inset-top,0px));padding-left:calc(20px + env(safe-area-inset-left,0px));padding-right:calc(20px + env(safe-area-inset-right,0px))}.chat-messages{padding-left:calc(16px + env(safe-area-inset-left,0px));padding-right:calc(16px + env(safe-area-inset-right,0px))}.chat-input-wrapper{padding-bottom:calc(14px + env(safe-area-inset-bottom,0px));padding-left:calc(16px + env(safe-area-inset-left,0px));padding-right:calc(16px + env(safe-area-inset-right,0px))}.chat-bubble-btn{width:52px;height:52px}.chat-bubble-btn.is-open,.input-hint{display:none}}