@blumessage/react-chat 1.4.2 → 1.5.1
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 +68 -0
- package/dist/BlumessageChat.js +232 -60
- package/dist/blumessage-chat.browser.js +1 -1
- package/dist/blumessage-chat.browser.js.LICENSE.txt +1 -1
- package/dist/index.js +1 -1
- package/dist/index.js.LICENSE.txt +1 -1
- package/dist/types/BlumessageChat.d.ts +12 -0
- package/package.json +5 -5
package/README.md
CHANGED
|
@@ -107,6 +107,12 @@ function App() {
|
|
|
107
107
|
| `defaultOpen` | `boolean` | `false` | Start with chat open |
|
|
108
108
|
| `maximizeToggleButton` | `boolean` | `true` | Show maximize/minimize button |
|
|
109
109
|
| `icon` | `string` | `'message-circle'` | Icon for button (flexible naming) |
|
|
110
|
+
| **Help Bubble Options** |
|
|
111
|
+
| `showHelpBubble` | `boolean` | `true` | Show help bubble above floating button |
|
|
112
|
+
| `helpBubbleMessage` | `string` | `"👋 If you need help chat with us"` | Message text in help bubble |
|
|
113
|
+
| `helpBubbleIcon` | `string` | `'hand'` | Icon for help bubble (supports lucide-react icon names) |
|
|
114
|
+
| `helpBubbleShowAfter` | `number` | `1` | Seconds to wait before showing bubble |
|
|
115
|
+
| `helpBubbleHideAfter` | `number` | `5` | Seconds to wait before hiding bubble (0 = never hide) |
|
|
110
116
|
| **Messages & Data** |
|
|
111
117
|
| `initialMessages` | `Message[]` | `[]` | Pre-populate with messages |
|
|
112
118
|
| `conversationId` | `string` | - | Continue specific conversation |
|
|
@@ -188,6 +194,68 @@ const initialMessages = [
|
|
|
188
194
|
/>
|
|
189
195
|
```
|
|
190
196
|
|
|
197
|
+
### Help Bubble Configuration
|
|
198
|
+
|
|
199
|
+
```tsx
|
|
200
|
+
<BlumessageChat
|
|
201
|
+
apiKey="your-api-key"
|
|
202
|
+
floating={true}
|
|
203
|
+
showHelpBubble={true}
|
|
204
|
+
helpBubbleMessage="👋 Need assistance? We're here to help!"
|
|
205
|
+
helpBubbleIcon="hand" // Use hand icon (default)
|
|
206
|
+
helpBubbleShowAfter={3} // Show after 3 seconds
|
|
207
|
+
helpBubbleHideAfter={10} // Hide after 10 seconds
|
|
208
|
+
/>
|
|
209
|
+
```
|
|
210
|
+
|
|
211
|
+
### Custom Help Bubble Icons
|
|
212
|
+
|
|
213
|
+
```tsx
|
|
214
|
+
<BlumessageChat
|
|
215
|
+
apiKey="your-api-key"
|
|
216
|
+
floating={true}
|
|
217
|
+
showHelpBubble={true}
|
|
218
|
+
helpBubbleIcon="star" // Use star icon
|
|
219
|
+
helpBubbleMessage="⭐ Rate our service!"
|
|
220
|
+
helpBubbleShowAfter={2}
|
|
221
|
+
helpBubbleHideAfter={8}
|
|
222
|
+
/>
|
|
223
|
+
|
|
224
|
+
<BlumessageChat
|
|
225
|
+
apiKey="your-api-key"
|
|
226
|
+
floating={true}
|
|
227
|
+
showHelpBubble={true}
|
|
228
|
+
helpBubbleIcon="lightbulb" // Use lightbulb icon
|
|
229
|
+
helpBubbleMessage="💡 Got an idea? Let's discuss it!"
|
|
230
|
+
helpBubbleShowAfter={1}
|
|
231
|
+
helpBubbleHideAfter={0} // Never hide
|
|
232
|
+
/>
|
|
233
|
+
|
|
234
|
+
<BlumessageChat
|
|
235
|
+
apiKey="your-api-key"
|
|
236
|
+
floating={true}
|
|
237
|
+
showHelpBubble={true}
|
|
238
|
+
helpBubbleIcon="help-circle" // Use help icon
|
|
239
|
+
helpBubbleMessage="❓ Questions? We're here to help!"
|
|
240
|
+
helpBubbleShowAfter={5}
|
|
241
|
+
helpBubbleHideAfter={15}
|
|
242
|
+
/>
|
|
243
|
+
```
|
|
244
|
+
```
|
|
245
|
+
|
|
246
|
+
### Persistent Help Bubble (Never Hide)
|
|
247
|
+
|
|
248
|
+
```tsx
|
|
249
|
+
<BlumessageChat
|
|
250
|
+
apiKey="your-api-key"
|
|
251
|
+
floating={true}
|
|
252
|
+
showHelpBubble={true}
|
|
253
|
+
helpBubbleMessage="💬 Questions? Click to chat with us!"
|
|
254
|
+
helpBubbleShowAfter={2} // Show after 2 seconds
|
|
255
|
+
helpBubbleHideAfter={0} // Never hide (0 = persistent)
|
|
256
|
+
/>
|
|
257
|
+
```
|
|
258
|
+
|
|
191
259
|
### Chat with Timestamps
|
|
192
260
|
|
|
193
261
|
```tsx
|
package/dist/BlumessageChat.js
CHANGED
|
@@ -41,7 +41,7 @@ const jsx_runtime_1 = require("react/jsx-runtime");
|
|
|
41
41
|
const react_1 = __importStar(require("react"));
|
|
42
42
|
const react_markdown_1 = __importDefault(require("react-markdown"));
|
|
43
43
|
const remark_gfm_1 = __importDefault(require("remark-gfm"));
|
|
44
|
-
const
|
|
44
|
+
const LucideIcons = __importStar(require("lucide-react"));
|
|
45
45
|
// Custom CSS animations that don't depend on Tailwind
|
|
46
46
|
const customStyles = `
|
|
47
47
|
@keyframes bounce {
|
|
@@ -62,6 +62,50 @@ const customStyles = `
|
|
|
62
62
|
}
|
|
63
63
|
}
|
|
64
64
|
|
|
65
|
+
@keyframes helpBubbleIn {
|
|
66
|
+
0% {
|
|
67
|
+
transform: translateY(20px) scale(0.8);
|
|
68
|
+
opacity: 0;
|
|
69
|
+
}
|
|
70
|
+
100% {
|
|
71
|
+
transform: translateY(0) scale(1);
|
|
72
|
+
opacity: 1;
|
|
73
|
+
}
|
|
74
|
+
}
|
|
75
|
+
|
|
76
|
+
@keyframes helpBubbleOut {
|
|
77
|
+
0% {
|
|
78
|
+
transform: translateY(0) scale(1);
|
|
79
|
+
opacity: 1;
|
|
80
|
+
}
|
|
81
|
+
100% {
|
|
82
|
+
transform: translateY(20px) scale(0.8);
|
|
83
|
+
opacity: 0;
|
|
84
|
+
}
|
|
85
|
+
}
|
|
86
|
+
|
|
87
|
+
@keyframes helpBubbleInTop {
|
|
88
|
+
0% {
|
|
89
|
+
transform: translateY(-20px) scale(0.8);
|
|
90
|
+
opacity: 0;
|
|
91
|
+
}
|
|
92
|
+
100% {
|
|
93
|
+
transform: translateY(0) scale(1);
|
|
94
|
+
opacity: 1;
|
|
95
|
+
}
|
|
96
|
+
}
|
|
97
|
+
|
|
98
|
+
@keyframes helpBubbleOutTop {
|
|
99
|
+
0% {
|
|
100
|
+
transform: translateY(0) scale(1);
|
|
101
|
+
opacity: 1;
|
|
102
|
+
}
|
|
103
|
+
100% {
|
|
104
|
+
transform: translateY(-20px) scale(0.8);
|
|
105
|
+
opacity: 0;
|
|
106
|
+
}
|
|
107
|
+
}
|
|
108
|
+
|
|
65
109
|
.blumessage-animate-bounce {
|
|
66
110
|
animation: bounce 1s infinite;
|
|
67
111
|
}
|
|
@@ -70,6 +114,22 @@ const customStyles = `
|
|
|
70
114
|
animation: spin 1s linear infinite;
|
|
71
115
|
}
|
|
72
116
|
|
|
117
|
+
.blumessage-help-bubble-in {
|
|
118
|
+
animation: helpBubbleIn 0.3s cubic-bezier(0.4, 0, 0.2, 1) forwards;
|
|
119
|
+
}
|
|
120
|
+
|
|
121
|
+
.blumessage-help-bubble-out {
|
|
122
|
+
animation: helpBubbleOut 0.3s cubic-bezier(0.4, 0, 0.2, 1) forwards;
|
|
123
|
+
}
|
|
124
|
+
|
|
125
|
+
.blumessage-help-bubble-in-top {
|
|
126
|
+
animation: helpBubbleInTop 0.3s cubic-bezier(0.4, 0, 0.2, 1) forwards;
|
|
127
|
+
}
|
|
128
|
+
|
|
129
|
+
.blumessage-help-bubble-out-top {
|
|
130
|
+
animation: helpBubbleOutTop 0.3s cubic-bezier(0.4, 0, 0.2, 1) forwards;
|
|
131
|
+
}
|
|
132
|
+
|
|
73
133
|
/* Mobile-specific styles */
|
|
74
134
|
@media (max-width: 768px) {
|
|
75
135
|
.blumessage-mobile-fullscreen {
|
|
@@ -130,7 +190,7 @@ const saveConversationToken = (token, persistent = false) => {
|
|
|
130
190
|
storage.setItem(CONVERSATION_TOKEN_KEY, token);
|
|
131
191
|
}
|
|
132
192
|
catch (error) {
|
|
133
|
-
|
|
193
|
+
// Silent fail - storage might not be available
|
|
134
194
|
}
|
|
135
195
|
};
|
|
136
196
|
const getStoredConversationToken = (persistent = false) => {
|
|
@@ -139,7 +199,7 @@ const getStoredConversationToken = (persistent = false) => {
|
|
|
139
199
|
return storage.getItem(CONVERSATION_TOKEN_KEY);
|
|
140
200
|
}
|
|
141
201
|
catch (error) {
|
|
142
|
-
|
|
202
|
+
// Silent fail - storage might not be available
|
|
143
203
|
return null;
|
|
144
204
|
}
|
|
145
205
|
};
|
|
@@ -149,7 +209,7 @@ const clearStoredConversationToken = (persistent = false) => {
|
|
|
149
209
|
storage.removeItem(CONVERSATION_TOKEN_KEY);
|
|
150
210
|
}
|
|
151
211
|
catch (error) {
|
|
152
|
-
|
|
212
|
+
// Silent fail - storage might not be available
|
|
153
213
|
}
|
|
154
214
|
};
|
|
155
215
|
// Custom hook for mobile detection
|
|
@@ -173,7 +233,11 @@ exports.BlumessageChat = (0, react_1.forwardRef)(({ apiKey, placeholder = "Type
|
|
|
173
233
|
// Floating button props
|
|
174
234
|
floating = true, buttonText = "Chat with us", buttonPosition = 'bottom-right', buttonStyle, defaultOpen = false, maximizeToggleButton = true, fullScreen = false, icon = 'message-circle',
|
|
175
235
|
// Styling props
|
|
176
|
-
primaryColor = "linear-gradient(to right, #3b82f6,rgb(8, 98, 242))"
|
|
236
|
+
primaryColor = "linear-gradient(to right, #3b82f6,rgb(8, 98, 242))",
|
|
237
|
+
// Help bubble props
|
|
238
|
+
showHelpBubble = true, helpBubbleMessage = "Have a question? We're here to help!", helpBubbleIcon = 'message-circle-question-mark', helpBubbleIconName, helpBubbleShowAfter = 1, // 1 second
|
|
239
|
+
helpBubbleHideAfter = 5, // 5 seconds
|
|
240
|
+
helpBubbleBackgroundColor = "#000000", }, ref) => {
|
|
177
241
|
const [isInitialized, setIsInitialized] = (0, react_1.useState)(false);
|
|
178
242
|
const [error, setError] = (0, react_1.useState)(null);
|
|
179
243
|
const [messages, setMessages] = (0, react_1.useState)(initialMessages);
|
|
@@ -185,8 +249,36 @@ primaryColor = "linear-gradient(to right, #3b82f6,rgb(8, 98, 242))" }, ref) => {
|
|
|
185
249
|
const [isMaximized, setIsMaximized] = (0, react_1.useState)(false);
|
|
186
250
|
const messagesEndRef = (0, react_1.useRef)(null);
|
|
187
251
|
const isInitialLoad = (0, react_1.useRef)(true);
|
|
252
|
+
const [isHelpBubbleVisible, setIsHelpBubbleVisible] = (0, react_1.useState)(false);
|
|
253
|
+
const [isHelpBubbleAnimating, setIsHelpBubbleAnimating] = (0, react_1.useState)(false);
|
|
188
254
|
// Mobile detection
|
|
189
255
|
const isMobile = useIsMobile();
|
|
256
|
+
// Help bubble effect
|
|
257
|
+
(0, react_1.useEffect)(() => {
|
|
258
|
+
if (!floating || !showHelpBubble)
|
|
259
|
+
return;
|
|
260
|
+
const showTimer = setTimeout(() => {
|
|
261
|
+
setIsHelpBubbleAnimating(true);
|
|
262
|
+
setIsHelpBubbleVisible(true);
|
|
263
|
+
// Remove animating state after animation completes
|
|
264
|
+
setTimeout(() => {
|
|
265
|
+
setIsHelpBubbleAnimating(false);
|
|
266
|
+
}, 300);
|
|
267
|
+
// Hide the bubble after the specified time if hideAfter > 0
|
|
268
|
+
if (helpBubbleHideAfter > 0) {
|
|
269
|
+
const hideTimer = setTimeout(() => {
|
|
270
|
+
setIsHelpBubbleAnimating(true);
|
|
271
|
+
setIsHelpBubbleVisible(false);
|
|
272
|
+
// Remove animating state after animation completes
|
|
273
|
+
setTimeout(() => {
|
|
274
|
+
setIsHelpBubbleAnimating(false);
|
|
275
|
+
}, 300);
|
|
276
|
+
}, helpBubbleHideAfter * 1000);
|
|
277
|
+
return () => clearTimeout(hideTimer);
|
|
278
|
+
}
|
|
279
|
+
}, helpBubbleShowAfter * 1000);
|
|
280
|
+
return () => clearTimeout(showTimer);
|
|
281
|
+
}, [floating, showHelpBubble, helpBubbleShowAfter, helpBubbleHideAfter]);
|
|
190
282
|
// Helper function to format timestamp
|
|
191
283
|
const formatTimestamp = (timestamp) => {
|
|
192
284
|
const date = new Date(timestamp);
|
|
@@ -274,7 +366,6 @@ primaryColor = "linear-gradient(to right, #3b82f6,rgb(8, 98, 242))" }, ref) => {
|
|
|
274
366
|
// Function to fetch conversation history
|
|
275
367
|
const fetchConversationHistory = async (convToken) => {
|
|
276
368
|
try {
|
|
277
|
-
console.log("Fetching conversation history for:", convToken);
|
|
278
369
|
const response = await fetch(`https://api.blumessage.com/api/v1/conversations/session/${convToken}`, {
|
|
279
370
|
method: 'GET',
|
|
280
371
|
headers: {
|
|
@@ -283,11 +374,9 @@ primaryColor = "linear-gradient(to right, #3b82f6,rgb(8, 98, 242))" }, ref) => {
|
|
|
283
374
|
});
|
|
284
375
|
if (response.ok) {
|
|
285
376
|
const sessionData = await response.json();
|
|
286
|
-
console.log("Conversation history loaded successfully");
|
|
287
377
|
return sessionData.messages || [];
|
|
288
378
|
}
|
|
289
379
|
else {
|
|
290
|
-
console.error("Failed to fetch conversation history:", response.status, response.statusText);
|
|
291
380
|
// Clear invalid conversation ID from storage
|
|
292
381
|
updateConversationToken(null);
|
|
293
382
|
if (onError) {
|
|
@@ -297,7 +386,6 @@ primaryColor = "linear-gradient(to right, #3b82f6,rgb(8, 98, 242))" }, ref) => {
|
|
|
297
386
|
}
|
|
298
387
|
}
|
|
299
388
|
catch (error) {
|
|
300
|
-
console.error("Error fetching conversation history:", error);
|
|
301
389
|
// Clear invalid conversation ID from storage
|
|
302
390
|
updateConversationToken(null);
|
|
303
391
|
if (onError) {
|
|
@@ -308,7 +396,6 @@ primaryColor = "linear-gradient(to right, #3b82f6,rgb(8, 98, 242))" }, ref) => {
|
|
|
308
396
|
};
|
|
309
397
|
(0, react_1.useEffect)(() => {
|
|
310
398
|
if (!apiKey) {
|
|
311
|
-
console.error("Blumessage Chat: API key is required");
|
|
312
399
|
const errorMessage = "API key is required";
|
|
313
400
|
setError(errorMessage);
|
|
314
401
|
if (onError) {
|
|
@@ -321,7 +408,6 @@ primaryColor = "linear-gradient(to right, #3b82f6,rgb(8, 98, 242))" }, ref) => {
|
|
|
321
408
|
try {
|
|
322
409
|
setIsInitialized(false);
|
|
323
410
|
setError(null);
|
|
324
|
-
console.log("Initializing Blumessage chat...");
|
|
325
411
|
const response = await fetch('https://api.blumessage.com/api/v1/api-keys/validate', {
|
|
326
412
|
method: 'POST',
|
|
327
413
|
headers: {
|
|
@@ -330,12 +416,10 @@ primaryColor = "linear-gradient(to right, #3b82f6,rgb(8, 98, 242))" }, ref) => {
|
|
|
330
416
|
body: JSON.stringify({ apiKey }),
|
|
331
417
|
});
|
|
332
418
|
if (response.ok) {
|
|
333
|
-
console.log("Blumessage chat initialized successfully");
|
|
334
419
|
setIsInitialized(true);
|
|
335
420
|
setError(null);
|
|
336
421
|
}
|
|
337
422
|
else {
|
|
338
|
-
console.error("Blumessage chat initialization failed:", response.status, response.statusText);
|
|
339
423
|
const errorMessage = "Unable to connect - invalid API key";
|
|
340
424
|
setError(errorMessage);
|
|
341
425
|
setIsInitialized(false);
|
|
@@ -345,7 +429,6 @@ primaryColor = "linear-gradient(to right, #3b82f6,rgb(8, 98, 242))" }, ref) => {
|
|
|
345
429
|
}
|
|
346
430
|
}
|
|
347
431
|
catch (err) {
|
|
348
|
-
console.error("Blumessage chat initialization error:", err);
|
|
349
432
|
const errorMessage = "Unable to connect - network error";
|
|
350
433
|
setError(errorMessage);
|
|
351
434
|
setIsInitialized(false);
|
|
@@ -364,7 +447,6 @@ primaryColor = "linear-gradient(to right, #3b82f6,rgb(8, 98, 242))" }, ref) => {
|
|
|
364
447
|
// Handle message initialization based on conversation state
|
|
365
448
|
if (initialMessages.length > 0 && token) {
|
|
366
449
|
// Warn if both are provided - initialMessages takes precedence
|
|
367
|
-
console.warn('Both initialMessages and token provided. Using initialMessages and ignoring stored token.');
|
|
368
450
|
setMessages(initialMessages);
|
|
369
451
|
}
|
|
370
452
|
else if (initialMessages.length > 0) {
|
|
@@ -444,7 +526,6 @@ primaryColor = "linear-gradient(to right, #3b82f6,rgb(8, 98, 242))" }, ref) => {
|
|
|
444
526
|
}
|
|
445
527
|
}
|
|
446
528
|
else {
|
|
447
|
-
console.error('Failed to send message to Blumessage API:', response.status, response.statusText);
|
|
448
529
|
// If token is invalid, clear it
|
|
449
530
|
if (response.status === 401 || response.status === 403) {
|
|
450
531
|
updateConversationToken(null);
|
|
@@ -463,7 +544,6 @@ primaryColor = "linear-gradient(to right, #3b82f6,rgb(8, 98, 242))" }, ref) => {
|
|
|
463
544
|
}
|
|
464
545
|
}
|
|
465
546
|
catch (error) {
|
|
466
|
-
console.error('Error sending message to Blumessage API:', error);
|
|
467
547
|
// Add error message
|
|
468
548
|
const errorMessage = {
|
|
469
549
|
id: (Date.now() + 1).toString(),
|
|
@@ -540,37 +620,68 @@ primaryColor = "linear-gradient(to right, #3b82f6,rgb(8, 98, 242))" }, ref) => {
|
|
|
540
620
|
const handleToggleMaximize = () => {
|
|
541
621
|
setIsMaximized(!isMaximized);
|
|
542
622
|
};
|
|
623
|
+
// Helper function to get any Lucide React icon by name
|
|
624
|
+
const getLucideIcon = (iconName) => {
|
|
625
|
+
if (!iconName)
|
|
626
|
+
return LucideIcons.MessageCircle;
|
|
627
|
+
// Convert icon name to PascalCase (e.g., "message-circle" -> "MessageCircle")
|
|
628
|
+
const pascalCaseName = iconName
|
|
629
|
+
.split(/[-_\s]+/)
|
|
630
|
+
.map(word => word.charAt(0).toUpperCase() + word.slice(1).toLowerCase())
|
|
631
|
+
.join('');
|
|
632
|
+
// Return the icon component if it exists, otherwise fallback to MessageCircle
|
|
633
|
+
const IconComponent = LucideIcons[pascalCaseName];
|
|
634
|
+
if (!IconComponent) {
|
|
635
|
+
}
|
|
636
|
+
return (IconComponent || LucideIcons.MessageCircle);
|
|
637
|
+
};
|
|
638
|
+
// Get the help bubble icon component based on the helpBubbleIcon or helpBubbleIconName prop
|
|
639
|
+
const getHelpBubbleIconComponent = () => {
|
|
640
|
+
// If helpBubbleIconName is provided, use it directly
|
|
641
|
+
if (helpBubbleIconName) {
|
|
642
|
+
return getLucideIcon(helpBubbleIconName);
|
|
643
|
+
}
|
|
644
|
+
// Otherwise use the helpBubbleIcon prop
|
|
645
|
+
return getLucideIcon(helpBubbleIcon);
|
|
646
|
+
};
|
|
647
|
+
// Helper function to determine if a color is dark (for text contrast)
|
|
648
|
+
const isColorDark = (color) => {
|
|
649
|
+
// Handle hex colors
|
|
650
|
+
if (color.startsWith('#')) {
|
|
651
|
+
const hex = color.replace('#', '');
|
|
652
|
+
const r = parseInt(hex.substr(0, 2), 16);
|
|
653
|
+
const g = parseInt(hex.substr(2, 2), 16);
|
|
654
|
+
const b = parseInt(hex.substr(4, 2), 16);
|
|
655
|
+
// Calculate luminance
|
|
656
|
+
const luminance = (0.299 * r + 0.587 * g + 0.114 * b) / 255;
|
|
657
|
+
return luminance < 0.5;
|
|
658
|
+
}
|
|
659
|
+
// Handle rgb/rgba colors
|
|
660
|
+
if (color.startsWith('rgb')) {
|
|
661
|
+
const match = color.match(/\d+/g);
|
|
662
|
+
if (match && match.length >= 3) {
|
|
663
|
+
const r = parseInt(match[0]);
|
|
664
|
+
const g = parseInt(match[1]);
|
|
665
|
+
const b = parseInt(match[2]);
|
|
666
|
+
const luminance = (0.299 * r + 0.587 * g + 0.114 * b) / 255;
|
|
667
|
+
return luminance < 0.5;
|
|
668
|
+
}
|
|
669
|
+
}
|
|
670
|
+
// Default to assuming light color for unknown formats
|
|
671
|
+
return false;
|
|
672
|
+
};
|
|
673
|
+
// Helper function to get appropriate text color based on background
|
|
674
|
+
const getTextColor = (backgroundColor, theme) => {
|
|
675
|
+
// If custom background color is provided, determine text color based on brightness
|
|
676
|
+
if (backgroundColor && backgroundColor !== '#ffffff' && backgroundColor !== '#1f2937') {
|
|
677
|
+
return isColorDark(backgroundColor) ? 'text-white' : 'text-gray-800';
|
|
678
|
+
}
|
|
679
|
+
// Fall back to theme-based colors
|
|
680
|
+
return theme === 'dark' ? 'text-gray-100' : 'text-gray-800';
|
|
681
|
+
};
|
|
543
682
|
// Get the icon component based on the icon prop
|
|
544
683
|
const getIconComponent = () => {
|
|
545
|
-
|
|
546
|
-
const iconName = icon.toLowerCase().replace(/[-_\s]/g, '');
|
|
547
|
-
// Try to match common icon patterns
|
|
548
|
-
if (iconName.includes('message') || iconName.includes('chat')) {
|
|
549
|
-
if (iconName.includes('square'))
|
|
550
|
-
return lucide_react_1.MessageSquare;
|
|
551
|
-
return lucide_react_1.MessageCircle;
|
|
552
|
-
}
|
|
553
|
-
if (iconName.includes('bot') || iconName.includes('robot'))
|
|
554
|
-
return lucide_react_1.Bot;
|
|
555
|
-
if (iconName.includes('phone') || iconName.includes('call'))
|
|
556
|
-
return lucide_react_1.Phone;
|
|
557
|
-
if (iconName.includes('mail') || iconName.includes('email'))
|
|
558
|
-
return lucide_react_1.Mail;
|
|
559
|
-
if (iconName.includes('headphone') || iconName.includes('support'))
|
|
560
|
-
return lucide_react_1.Headphones;
|
|
561
|
-
if (iconName.includes('user')) {
|
|
562
|
-
if (iconName.includes('users') || iconName.includes('group'))
|
|
563
|
-
return lucide_react_1.Users;
|
|
564
|
-
return lucide_react_1.User;
|
|
565
|
-
}
|
|
566
|
-
if (iconName.includes('heart') || iconName.includes('like') || iconName.includes('love'))
|
|
567
|
-
return lucide_react_1.Heart;
|
|
568
|
-
if (iconName.includes('star') || iconName.includes('favorite'))
|
|
569
|
-
return lucide_react_1.Star;
|
|
570
|
-
if (iconName.includes('zap') || iconName.includes('lightning') || iconName.includes('bolt'))
|
|
571
|
-
return lucide_react_1.Zap;
|
|
572
|
-
// Default fallback
|
|
573
|
-
return lucide_react_1.MessageCircle;
|
|
684
|
+
return getLucideIcon(icon);
|
|
574
685
|
};
|
|
575
686
|
// Expose methods to parent component via ref
|
|
576
687
|
(0, react_1.useImperativeHandle)(ref, () => ({
|
|
@@ -630,7 +741,6 @@ primaryColor = "linear-gradient(to right, #3b82f6,rgb(8, 98, 242))" }, ref) => {
|
|
|
630
741
|
}
|
|
631
742
|
}
|
|
632
743
|
else {
|
|
633
|
-
console.error('Failed to send message to Blumessage API:', response.status, response.statusText);
|
|
634
744
|
// If token is invalid, clear it
|
|
635
745
|
if (response.status === 401 || response.status === 403) {
|
|
636
746
|
updateConversationToken(null);
|
|
@@ -649,7 +759,6 @@ primaryColor = "linear-gradient(to right, #3b82f6,rgb(8, 98, 242))" }, ref) => {
|
|
|
649
759
|
}
|
|
650
760
|
}
|
|
651
761
|
catch (error) {
|
|
652
|
-
console.error('Error sending message to Blumessage API:', error);
|
|
653
762
|
// Add error message
|
|
654
763
|
const errorMessage = {
|
|
655
764
|
id: (Date.now() + 1).toString(),
|
|
@@ -739,6 +848,36 @@ primaryColor = "linear-gradient(to right, #3b82f6,rgb(8, 98, 242))" }, ref) => {
|
|
|
739
848
|
return { ...baseStyles, bottom: '24px', right: '24px' };
|
|
740
849
|
}
|
|
741
850
|
};
|
|
851
|
+
// Helper function to get position styles for help bubble
|
|
852
|
+
const getHelpBubblePositionStyles = () => {
|
|
853
|
+
const baseStyles = {
|
|
854
|
+
position: 'fixed',
|
|
855
|
+
zIndex: 999,
|
|
856
|
+
};
|
|
857
|
+
// Mobile-specific positioning
|
|
858
|
+
if (isMobile) {
|
|
859
|
+
return {
|
|
860
|
+
...baseStyles,
|
|
861
|
+
bottom: '80px',
|
|
862
|
+
right: '20px',
|
|
863
|
+
left: 'auto',
|
|
864
|
+
top: 'auto'
|
|
865
|
+
};
|
|
866
|
+
}
|
|
867
|
+
// Desktop positioning - position above the button
|
|
868
|
+
switch (buttonPosition) {
|
|
869
|
+
case 'bottom-right':
|
|
870
|
+
return { ...baseStyles, bottom: '80px', right: '24px' };
|
|
871
|
+
case 'bottom-left':
|
|
872
|
+
return { ...baseStyles, bottom: '80px', left: '24px' };
|
|
873
|
+
case 'top-right':
|
|
874
|
+
return { ...baseStyles, top: '80px', right: '24px' };
|
|
875
|
+
case 'top-left':
|
|
876
|
+
return { ...baseStyles, top: '80px', left: '24px' };
|
|
877
|
+
default:
|
|
878
|
+
return { ...baseStyles, bottom: '80px', right: '24px' };
|
|
879
|
+
}
|
|
880
|
+
};
|
|
742
881
|
// Helper function to get position styles for floating chat window
|
|
743
882
|
const getChatPositionStyles = () => {
|
|
744
883
|
const getTransform = () => {
|
|
@@ -850,9 +989,9 @@ primaryColor = "linear-gradient(to right, #3b82f6,rgb(8, 98, 242))" }, ref) => {
|
|
|
850
989
|
className: isMobile ? "w-5 h-5 text-white" : "w-6 h-6 text-white"
|
|
851
990
|
}) }), (0, jsx_runtime_1.jsxs)("div", { style: { flex: 1 }, children: [(0, jsx_runtime_1.jsx)("div", { className: `${isMobile ? 'text-base' : 'text-lg'} font-semibold m-0 leading-6 ${theme === 'dark' ? 'text-gray-100' : 'text-gray-900'}`, children: name }), (0, jsx_runtime_1.jsx)("div", { className: `text-sm m-0 leading-5 ${theme === 'dark' ? 'text-gray-400' : 'text-gray-500'}`, children: subtitle })] }), floating && ((0, jsx_runtime_1.jsxs)("div", { className: "flex items-center gap-1", children: [maximizeToggleButton && !isMobile && ((0, jsx_runtime_1.jsx)("button", { onClick: handleToggleMaximize, className: `w-8 h-8 rounded-full flex items-center justify-center cursor-pointer transition-colors ${theme === 'dark'
|
|
852
991
|
? 'hover:bg-gray-800 text-gray-400 hover:text-gray-200'
|
|
853
|
-
: 'hover:bg-gray-100 text-gray-500 hover:text-gray-700'}`, children: isMaximized ? (0, jsx_runtime_1.jsx)(
|
|
992
|
+
: 'hover:bg-gray-100 text-gray-500 hover:text-gray-700'}`, children: isMaximized ? (0, jsx_runtime_1.jsx)(LucideIcons.Minimize2, { className: "w-4 h-4" }) : (0, jsx_runtime_1.jsx)(LucideIcons.Maximize, { className: "w-4 h-4" }) })), (0, jsx_runtime_1.jsx)("button", { onClick: handleCloseChat, className: `w-8 h-8 rounded-full flex items-center justify-center cursor-pointer transition-colors ${theme === 'dark'
|
|
854
993
|
? 'hover:bg-gray-800 text-gray-400 hover:text-gray-200'
|
|
855
|
-
: 'hover:bg-gray-100 text-gray-500 hover:text-gray-700'}`, children: (0, jsx_runtime_1.jsx)(
|
|
994
|
+
: 'hover:bg-gray-100 text-gray-500 hover:text-gray-700'}`, children: (0, jsx_runtime_1.jsx)(LucideIcons.X, { className: "w-4 h-4" }) })] }))] }), (0, jsx_runtime_1.jsxs)("div", { className: `flex-1 overflow-y-auto ${theme === 'dark' ? 'bg-gray-800' : 'bg-gray-50'}`, style: { padding: isMobile ? '12px 16px' : '16px 24px' }, children: [messages.map((message) => ((0, jsx_runtime_1.jsx)("div", { className: `flex ${message.role === 'user' ? 'justify-end' : 'justify-start'} mb-4`, children: (0, jsx_runtime_1.jsx)("div", { className: `${isMobile ? 'max-w-[85%]' : 'max-w-[80%]'} inline-block ${message.role === 'user' ? '' : 'text-left'}`, children: (0, jsx_runtime_1.jsxs)("div", { className: `inline-block px-4 py-3 rounded-2xl text-sm leading-6 text-left ${message.role === 'user'
|
|
856
995
|
? 'text-white'
|
|
857
996
|
: theme === 'dark'
|
|
858
997
|
? 'bg-gray-700 text-gray-100 border border-gray-600 shadow-sm'
|
|
@@ -879,7 +1018,7 @@ primaryColor = "linear-gradient(to right, #3b82f6,rgb(8, 98, 242))" }, ref) => {
|
|
|
879
1018
|
const target = e.target;
|
|
880
1019
|
target.style.height = 'auto';
|
|
881
1020
|
target.style.height = Math.min(target.scrollHeight, isMobile ? 100 : 120) + 'px';
|
|
882
|
-
} }), (0, jsx_runtime_1.jsx)("button", { className: "w-8 h-8 rounded-full border-none flex items-center justify-center cursor-pointer ml-2 text-white transition-all disabled:opacity-50 disabled:cursor-not-allowed", style: { backgroundImage: primaryColor }, onClick: handleSendMessage, disabled: !inputValue.trim() || isLoading, children: isLoading ? ((0, jsx_runtime_1.jsx)(
|
|
1021
|
+
} }), (0, jsx_runtime_1.jsx)("button", { className: "w-8 h-8 rounded-full border-none flex items-center justify-center cursor-pointer ml-2 text-white transition-all disabled:opacity-50 disabled:cursor-not-allowed", style: { backgroundImage: primaryColor }, onClick: handleSendMessage, disabled: !inputValue.trim() || isLoading, children: isLoading ? ((0, jsx_runtime_1.jsx)(LucideIcons.Loader2, { className: "w-4 h-4 blumessage-animate-spin" })) : ((0, jsx_runtime_1.jsx)(LucideIcons.Send, { className: "w-4 h-4" })) })] }) })] }));
|
|
883
1022
|
if (floating) {
|
|
884
1023
|
return ((0, jsx_runtime_1.jsx)("div", { style: getChatPositionStyles(), children: chatContent }));
|
|
885
1024
|
}
|
|
@@ -905,15 +1044,26 @@ primaryColor = "linear-gradient(to right, #3b82f6,rgb(8, 98, 242))" }, ref) => {
|
|
|
905
1044
|
width: isMobile ? '40px' : '48px',
|
|
906
1045
|
height: isMobile ? '40px' : '48px',
|
|
907
1046
|
marginRight: isMobile ? '16px' : '24px'
|
|
908
|
-
}, children: (0, jsx_runtime_1.jsx)(
|
|
1047
|
+
}, children: (0, jsx_runtime_1.jsx)(LucideIcons.AlertTriangle, { className: isMobile ? "w-5 h-5 text-white" : "w-6 h-6 text-white" }) }), (0, jsx_runtime_1.jsxs)("div", { className: "flex-1", children: [(0, jsx_runtime_1.jsx)("div", { className: `${isMobile ? 'text-base' : 'text-lg'} font-semibold m-0 leading-6 ${theme === 'dark' ? 'text-gray-100' : 'text-gray-900'}`, children: "Connection Error" }), (0, jsx_runtime_1.jsx)("div", { className: `text-sm m-0 leading-5 ${theme === 'dark' ? 'text-gray-400' : 'text-gray-500'}`, children: "Unable to connect" })] }), floating && ((0, jsx_runtime_1.jsxs)("div", { className: "flex items-center gap-1", children: [maximizeToggleButton && !isMobile && ((0, jsx_runtime_1.jsx)("button", { onClick: handleToggleMaximize, className: `w-8 h-8 rounded-full flex items-center justify-center cursor-pointer transition-colors ${theme === 'dark'
|
|
909
1048
|
? 'hover:bg-gray-800 text-gray-400 hover:text-gray-200'
|
|
910
|
-
: 'hover:bg-gray-100 text-gray-500 hover:text-gray-700'}`, children: isMaximized ? (0, jsx_runtime_1.jsx)(
|
|
1049
|
+
: 'hover:bg-gray-100 text-gray-500 hover:text-gray-700'}`, children: isMaximized ? (0, jsx_runtime_1.jsx)(LucideIcons.Minimize2, { className: "w-4 h-4" }) : (0, jsx_runtime_1.jsx)(LucideIcons.Maximize, { className: "w-4 h-4" }) })), (0, jsx_runtime_1.jsx)("button", { onClick: handleCloseChat, className: `w-8 h-8 rounded-full flex items-center justify-center cursor-pointer transition-colors ${theme === 'dark'
|
|
911
1050
|
? 'hover:bg-gray-800 text-gray-400 hover:text-gray-200'
|
|
912
|
-
: 'hover:bg-gray-100 text-gray-500 hover:text-gray-700'}`, children: (0, jsx_runtime_1.jsx)(
|
|
1051
|
+
: 'hover:bg-gray-100 text-gray-500 hover:text-gray-700'}`, children: (0, jsx_runtime_1.jsx)(LucideIcons.X, { className: "w-4 h-4" }) })] }))] }), (0, jsx_runtime_1.jsx)("div", { className: `flex-1 overflow-y-auto ${theme === 'dark' ? 'bg-gray-800' : 'bg-gray-50'}`, style: { padding: isMobile ? '12px 16px' : '16px 24px' }, children: (0, jsx_runtime_1.jsx)("div", { className: "flex justify-start", children: (0, jsx_runtime_1.jsx)("div", { className: `px-4 py-3 rounded-2xl ${isMobile ? 'max-w-[85%]' : 'max-w-[80%]'} text-sm leading-6 shadow-sm ${theme === 'dark'
|
|
913
1052
|
? 'bg-gray-700 text-gray-100 border border-gray-600'
|
|
914
1053
|
: 'bg-white text-gray-800 border border-gray-200'}`, children: error }) }) })] }));
|
|
915
1054
|
if (floating) {
|
|
916
|
-
return ((0, jsx_runtime_1.jsxs)(jsx_runtime_1.Fragment, { children: [(0, jsx_runtime_1.jsxs)("button", { onClick: handleOpenChat, className: `text-white rounded-full shadow-lg transition-all duration-200 flex items-center justify-center gap-2 ${isMobile ? 'blumessage-mobile-button' : ''} ${buttonText ? 'px-4 py-3 h-12' : 'w-14 h-14'}`, style: { ...getButtonPositionStyles(), ...buttonStyle, backgroundImage: primaryColor }, children: [react_1.default.createElement(getIconComponent(), { className: "w-6 h-6" }), buttonText && !isMobile && (0, jsx_runtime_1.jsx)("span", { className: "text-sm font-medium whitespace-nowrap", children: buttonText })] }), (0, jsx_runtime_1.jsx)("div", {
|
|
1055
|
+
return ((0, jsx_runtime_1.jsxs)(jsx_runtime_1.Fragment, { children: [(0, jsx_runtime_1.jsxs)("button", { onClick: handleOpenChat, className: `text-white rounded-full shadow-lg transition-all duration-200 flex items-center justify-center gap-2 ${isMobile ? 'blumessage-mobile-button' : ''} ${buttonText ? 'px-4 py-3 h-12' : 'w-14 h-14'}`, style: { ...getButtonPositionStyles(), ...buttonStyle, backgroundImage: primaryColor }, children: [react_1.default.createElement(getIconComponent(), { className: "w-6 h-6" }), buttonText && !isMobile && (0, jsx_runtime_1.jsx)("span", { className: "text-sm font-medium whitespace-nowrap", children: buttonText })] }), showHelpBubble && (isHelpBubbleVisible || isHelpBubbleAnimating) && ((0, jsx_runtime_1.jsx)("div", { className: `fixed z-[999] border rounded-lg shadow-lg px-3 py-2 text-sm max-w-[200px] ${isHelpBubbleVisible
|
|
1056
|
+
? (buttonPosition?.includes('top') ? 'blumessage-help-bubble-in-top' : 'blumessage-help-bubble-in')
|
|
1057
|
+
: (buttonPosition?.includes('top') ? 'blumessage-help-bubble-out-top' : 'blumessage-help-bubble-out')} ${theme === 'dark'
|
|
1058
|
+
? 'bg-gray-800 border-gray-600'
|
|
1059
|
+
: 'bg-white border-gray-200'}`, style: {
|
|
1060
|
+
...getHelpBubblePositionStyles(),
|
|
1061
|
+
backgroundColor: helpBubbleBackgroundColor || (theme === 'dark' ? '#1f2937' : '#ffffff'),
|
|
1062
|
+
transformOrigin: buttonPosition?.includes('bottom') ? 'bottom center' : 'top center',
|
|
1063
|
+
}, children: (0, jsx_runtime_1.jsxs)("div", { className: "flex items-center gap-2", children: [react_1.default.createElement(getHelpBubbleIconComponent(), {
|
|
1064
|
+
className: "w-4 h-4 flex-shrink-0",
|
|
1065
|
+
style: { color: primaryColor.includes('linear-gradient') ? '#3b82f6' : primaryColor }
|
|
1066
|
+
}), (0, jsx_runtime_1.jsx)("span", { className: `leading-tight ${getTextColor(helpBubbleBackgroundColor || (theme === 'dark' ? '#1f2937' : '#ffffff'), theme)}`, children: helpBubbleMessage })] }) })), (0, jsx_runtime_1.jsx)("div", { style: getChatPositionStyles(), children: errorContent })] }));
|
|
917
1067
|
}
|
|
918
1068
|
return errorContent;
|
|
919
1069
|
}
|
|
@@ -933,19 +1083,41 @@ primaryColor = "linear-gradient(to right, #3b82f6,rgb(8, 98, 242))" }, ref) => {
|
|
|
933
1083
|
width: isMobile ? '40px' : '48px',
|
|
934
1084
|
height: isMobile ? '40px' : '48px',
|
|
935
1085
|
marginRight: isMobile ? '16px' : '24px'
|
|
936
|
-
}, children: (0, jsx_runtime_1.jsx)(
|
|
1086
|
+
}, children: (0, jsx_runtime_1.jsx)(LucideIcons.Loader2, { className: isMobile ? "w-5 h-5 text-white animate-spin" : "w-6 h-6 text-white animate-spin" }) }), (0, jsx_runtime_1.jsxs)("div", { className: "flex-1", children: [(0, jsx_runtime_1.jsx)("div", { className: `${isMobile ? 'text-base' : 'text-lg'} font-semibold m-0 leading-6 ${theme === 'dark' ? 'text-gray-100' : 'text-gray-900'}`, children: name }), (0, jsx_runtime_1.jsx)("div", { className: `text-sm m-0 leading-5 ${theme === 'dark' ? 'text-gray-400' : 'text-gray-500'}`, children: subtitle })] }), floating && ((0, jsx_runtime_1.jsxs)("div", { className: "flex items-center gap-1", children: [maximizeToggleButton && !isMobile && ((0, jsx_runtime_1.jsx)("button", { onClick: handleToggleMaximize, className: `w-8 h-8 rounded-full flex items-center justify-center cursor-pointer transition-colors ${theme === 'dark'
|
|
937
1087
|
? 'hover:bg-gray-800 text-gray-400 hover:text-gray-200'
|
|
938
|
-
: 'hover:bg-gray-100 text-gray-500 hover:text-gray-700'}`, children: isMaximized ? (0, jsx_runtime_1.jsx)(
|
|
1088
|
+
: 'hover:bg-gray-100 text-gray-500 hover:text-gray-700'}`, children: isMaximized ? (0, jsx_runtime_1.jsx)(LucideIcons.Minimize2, { className: "w-4 h-4" }) : (0, jsx_runtime_1.jsx)(LucideIcons.Maximize, { className: "w-4 h-4" }) })), (0, jsx_runtime_1.jsx)("button", { onClick: handleCloseChat, className: `w-8 h-8 rounded-full flex items-center justify-center cursor-pointer transition-colors ${theme === 'dark'
|
|
939
1089
|
? 'hover:bg-gray-800 text-gray-400 hover:text-gray-200'
|
|
940
|
-
: 'hover:bg-gray-100 text-gray-500 hover:text-gray-700'}`, children: (0, jsx_runtime_1.jsx)(
|
|
1090
|
+
: 'hover:bg-gray-100 text-gray-500 hover:text-gray-700'}`, children: (0, jsx_runtime_1.jsx)(LucideIcons.X, { className: "w-4 h-4" }) })] }))] }), (0, jsx_runtime_1.jsx)("div", { className: `flex-1 overflow-y-auto ${theme === 'dark' ? 'bg-gray-800' : 'bg-gray-50'}`, style: { padding: isMobile ? '12px 16px' : '16px 24px' }, children: (0, jsx_runtime_1.jsx)("div", { className: `text-center text-sm py-8 ${theme === 'dark' ? 'text-gray-400' : 'text-gray-500'}`, children: "Ready to chat..." }) })] }));
|
|
941
1091
|
if (floating) {
|
|
942
|
-
return ((0, jsx_runtime_1.jsxs)(jsx_runtime_1.Fragment, { children: [(0, jsx_runtime_1.jsxs)("button", { onClick: handleOpenChat, className: `text-white rounded-full shadow-lg transition-all duration-200 flex items-center justify-center gap-2 ${isMobile ? 'blumessage-mobile-button' : ''} ${buttonText ? 'px-4 py-3 h-12' : 'w-14 h-14'}`, style: { ...getButtonPositionStyles(), ...buttonStyle, backgroundImage: primaryColor }, children: [react_1.default.createElement(getIconComponent(), { className: "w-6 h-6" }), buttonText && !isMobile && (0, jsx_runtime_1.jsx)("span", { className: "text-sm font-medium whitespace-nowrap", children: buttonText })] }), (0, jsx_runtime_1.jsx)("div", {
|
|
1092
|
+
return ((0, jsx_runtime_1.jsxs)(jsx_runtime_1.Fragment, { children: [(0, jsx_runtime_1.jsxs)("button", { onClick: handleOpenChat, className: `text-white rounded-full shadow-lg transition-all duration-200 flex items-center justify-center gap-2 ${isMobile ? 'blumessage-mobile-button' : ''} ${buttonText ? 'px-4 py-3 h-12' : 'w-14 h-14'}`, style: { ...getButtonPositionStyles(), ...buttonStyle, backgroundImage: primaryColor }, children: [react_1.default.createElement(getIconComponent(), { className: "w-6 h-6" }), buttonText && !isMobile && (0, jsx_runtime_1.jsx)("span", { className: "text-sm font-medium whitespace-nowrap", children: buttonText })] }), showHelpBubble && (isHelpBubbleVisible || isHelpBubbleAnimating) && ((0, jsx_runtime_1.jsx)("div", { className: `fixed z-[999] border rounded-lg shadow-lg px-3 py-2 text-sm max-w-[200px] ${isHelpBubbleVisible
|
|
1093
|
+
? (buttonPosition?.includes('top') ? 'blumessage-help-bubble-in-top' : 'blumessage-help-bubble-in')
|
|
1094
|
+
: (buttonPosition?.includes('top') ? 'blumessage-help-bubble-out-top' : 'blumessage-help-bubble-out')} ${theme === 'dark'
|
|
1095
|
+
? 'bg-gray-800 border-gray-600'
|
|
1096
|
+
: 'bg-white border-gray-200'}`, style: {
|
|
1097
|
+
...getHelpBubblePositionStyles(),
|
|
1098
|
+
backgroundColor: helpBubbleBackgroundColor || (theme === 'dark' ? '#1f2937' : '#ffffff'),
|
|
1099
|
+
transformOrigin: buttonPosition?.includes('bottom') ? 'bottom center' : 'top center',
|
|
1100
|
+
}, children: (0, jsx_runtime_1.jsxs)("div", { className: "flex items-center gap-2", children: [react_1.default.createElement(getHelpBubbleIconComponent(), {
|
|
1101
|
+
className: "w-4 h-4 flex-shrink-0",
|
|
1102
|
+
style: { color: primaryColor.includes('linear-gradient') ? '#3b82f6' : primaryColor }
|
|
1103
|
+
}), (0, jsx_runtime_1.jsx)("span", { className: `leading-tight ${getTextColor(helpBubbleBackgroundColor || (theme === 'dark' ? '#1f2937' : '#ffffff'), theme)}`, children: helpBubbleMessage })] }) })), (0, jsx_runtime_1.jsx)("div", { style: getChatPositionStyles(), children: loadingContent })] }));
|
|
943
1104
|
}
|
|
944
1105
|
return loadingContent;
|
|
945
1106
|
}
|
|
946
1107
|
// Main render for initialized state
|
|
947
1108
|
if (floating) {
|
|
948
|
-
return ((0, jsx_runtime_1.jsxs)(jsx_runtime_1.Fragment, { children: [(0, jsx_runtime_1.jsxs)("button", { onClick: handleOpenChat, className: `text-white rounded-full shadow-lg transition-all duration-200 flex items-center justify-center gap-2 ${isMobile ? 'blumessage-mobile-button' : ''} ${buttonText ? 'px-4 py-3 h-12' : 'w-14 h-14'}`, style: { ...getButtonPositionStyles(), ...buttonStyle, backgroundImage: primaryColor }, children: [react_1.default.createElement(getIconComponent(), { className: "w-6 h-6" }), buttonText && !isMobile && (0, jsx_runtime_1.jsx)("span", { className: "text-sm font-medium whitespace-nowrap", children: buttonText })] }),
|
|
1109
|
+
return ((0, jsx_runtime_1.jsxs)(jsx_runtime_1.Fragment, { children: [(0, jsx_runtime_1.jsxs)("button", { onClick: handleOpenChat, className: `text-white rounded-full shadow-lg transition-all duration-200 flex items-center justify-center gap-2 ${isMobile ? 'blumessage-mobile-button' : ''} ${buttonText ? 'px-4 py-3 h-12' : 'w-14 h-14'}`, style: { ...getButtonPositionStyles(), ...buttonStyle, backgroundImage: primaryColor }, children: [react_1.default.createElement(getIconComponent(), { className: "w-6 h-6" }), buttonText && !isMobile && (0, jsx_runtime_1.jsx)("span", { className: "text-sm font-medium whitespace-nowrap", children: buttonText })] }), showHelpBubble && (isHelpBubbleVisible || isHelpBubbleAnimating) && ((0, jsx_runtime_1.jsx)("div", { className: `fixed z-[999] border rounded-lg shadow-lg px-3 py-2 text-sm max-w-[200px] ${isHelpBubbleVisible
|
|
1110
|
+
? (buttonPosition?.includes('top') ? 'blumessage-help-bubble-in-top' : 'blumessage-help-bubble-in')
|
|
1111
|
+
: (buttonPosition?.includes('top') ? 'blumessage-help-bubble-out-top' : 'blumessage-help-bubble-out')} ${theme === 'dark'
|
|
1112
|
+
? 'bg-gray-800 border-gray-600'
|
|
1113
|
+
: 'bg-white border-gray-200'}`, style: {
|
|
1114
|
+
...getHelpBubblePositionStyles(),
|
|
1115
|
+
backgroundColor: helpBubbleBackgroundColor || (theme === 'dark' ? '#1f2937' : '#ffffff'),
|
|
1116
|
+
transformOrigin: buttonPosition?.includes('bottom') ? 'bottom center' : 'top center',
|
|
1117
|
+
}, children: (0, jsx_runtime_1.jsxs)("div", { className: "flex items-center gap-2", children: [react_1.default.createElement(getHelpBubbleIconComponent(), {
|
|
1118
|
+
className: "w-4 h-4 flex-shrink-0",
|
|
1119
|
+
style: { color: primaryColor.includes('linear-gradient') ? '#3b82f6' : primaryColor }
|
|
1120
|
+
}), (0, jsx_runtime_1.jsx)("span", { className: `leading-tight ${getTextColor(helpBubbleBackgroundColor || (theme === 'dark' ? '#1f2937' : '#ffffff'), theme)}`, children: helpBubbleMessage })] }) })), renderChatWindow()] }));
|
|
949
1121
|
}
|
|
950
1122
|
return renderChatWindow();
|
|
951
1123
|
});
|