@blumessage/react-chat 1.0.0 → 1.0.2

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.
@@ -0,0 +1,624 @@
1
+ var __assign = (this && this.__assign) || function () {
2
+ __assign = Object.assign || function(t) {
3
+ for (var s, i = 1, n = arguments.length; i < n; i++) {
4
+ s = arguments[i];
5
+ for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p))
6
+ t[p] = s[p];
7
+ }
8
+ return t;
9
+ };
10
+ return __assign.apply(this, arguments);
11
+ };
12
+ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
13
+ function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
14
+ return new (P || (P = Promise))(function (resolve, reject) {
15
+ function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
16
+ function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
17
+ function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
18
+ step((generator = generator.apply(thisArg, _arguments || [])).next());
19
+ });
20
+ };
21
+ var __generator = (this && this.__generator) || function (thisArg, body) {
22
+ var _ = { label: 0, sent: function() { if (t[0] & 1) throw t[1]; return t[1]; }, trys: [], ops: [] }, f, y, t, g = Object.create((typeof Iterator === "function" ? Iterator : Object).prototype);
23
+ return g.next = verb(0), g["throw"] = verb(1), g["return"] = verb(2), typeof Symbol === "function" && (g[Symbol.iterator] = function() { return this; }), g;
24
+ function verb(n) { return function (v) { return step([n, v]); }; }
25
+ function step(op) {
26
+ if (f) throw new TypeError("Generator is already executing.");
27
+ while (g && (g = 0, op[0] && (_ = 0)), _) try {
28
+ if (f = 1, y && (t = op[0] & 2 ? y["return"] : op[0] ? y["throw"] || ((t = y["return"]) && t.call(y), 0) : y.next) && !(t = t.call(y, op[1])).done) return t;
29
+ if (y = 0, t) op = [op[0] & 2, t.value];
30
+ switch (op[0]) {
31
+ case 0: case 1: t = op; break;
32
+ case 4: _.label++; return { value: op[1], done: false };
33
+ case 5: _.label++; y = op[1]; op = [0]; continue;
34
+ case 7: op = _.ops.pop(); _.trys.pop(); continue;
35
+ default:
36
+ if (!(t = _.trys, t = t.length > 0 && t[t.length - 1]) && (op[0] === 6 || op[0] === 2)) { _ = 0; continue; }
37
+ if (op[0] === 3 && (!t || (op[1] > t[0] && op[1] < t[3]))) { _.label = op[1]; break; }
38
+ if (op[0] === 6 && _.label < t[1]) { _.label = t[1]; t = op; break; }
39
+ if (t && _.label < t[2]) { _.label = t[2]; _.ops.push(op); break; }
40
+ if (t[2]) _.ops.pop();
41
+ _.trys.pop(); continue;
42
+ }
43
+ op = body.call(thisArg, _);
44
+ } catch (e) { op = [6, e]; y = 0; } finally { f = t = 0; }
45
+ if (op[0] & 5) throw op[1]; return { value: op[0] ? op[1] : void 0, done: true };
46
+ }
47
+ };
48
+ var __spreadArray = (this && this.__spreadArray) || function (to, from, pack) {
49
+ if (pack || arguments.length === 2) for (var i = 0, l = from.length, ar; i < l; i++) {
50
+ if (ar || !(i in from)) {
51
+ if (!ar) ar = Array.prototype.slice.call(from, 0, i);
52
+ ar[i] = from[i];
53
+ }
54
+ }
55
+ return to.concat(ar || Array.prototype.slice.call(from));
56
+ };
57
+ import { jsx as _jsx, jsxs as _jsxs, Fragment as _Fragment } from "react/jsx-runtime";
58
+ import React, { useState, useEffect, useRef } from "react";
59
+ import { MessageCircle, AlertTriangle, Loader2, Send, X, Maximize, Minimize2, Bot, MessageSquare, Phone, Mail, Headphones, Users, User, Heart, Star, Zap } from "lucide-react";
60
+ // Session storage key for conversation ID
61
+ var CONVERSATION_ID_KEY = 'blumessage_conversation_id';
62
+ // Utility functions for storage
63
+ var saveConversationId = function (conversationId, persistent) {
64
+ if (persistent === void 0) { persistent = false; }
65
+ try {
66
+ var storage = persistent ? localStorage : sessionStorage;
67
+ storage.setItem(CONVERSATION_ID_KEY, conversationId);
68
+ }
69
+ catch (error) {
70
+ console.warn("Failed to save conversation ID to ".concat(persistent ? 'local' : 'session', " storage:"), error);
71
+ }
72
+ };
73
+ var getStoredConversationId = function (persistent) {
74
+ if (persistent === void 0) { persistent = false; }
75
+ try {
76
+ var storage = persistent ? localStorage : sessionStorage;
77
+ return storage.getItem(CONVERSATION_ID_KEY);
78
+ }
79
+ catch (error) {
80
+ console.warn("Failed to get conversation ID from ".concat(persistent ? 'local' : 'session', " storage:"), error);
81
+ return null;
82
+ }
83
+ };
84
+ var clearStoredConversationId = function (persistent) {
85
+ if (persistent === void 0) { persistent = false; }
86
+ try {
87
+ var storage = persistent ? localStorage : sessionStorage;
88
+ storage.removeItem(CONVERSATION_ID_KEY);
89
+ }
90
+ catch (error) {
91
+ console.warn("Failed to clear conversation ID from ".concat(persistent ? 'local' : 'session', " storage:"), error);
92
+ }
93
+ };
94
+ export var BlumessageChat = function (_a) {
95
+ var apiKey = _a.apiKey, _b = _a.placeholder, placeholder = _b === void 0 ? "Type your message..." : _b, _c = _a.theme, theme = _c === void 0 ? 'light' : _c, width = _a.width, height = _a.height, _d = _a.size, size = _d === void 0 ? 'medium' : _d, _e = _a.name, name = _e === void 0 ? "Blumessage AI" : _e, _f = _a.subtitle, subtitle = _f === void 0 ? "Online • Instant responses" : _f, _g = _a.initialMessages, initialMessages = _g === void 0 ? [] : _g, onUserMessage = _a.onUserMessage, onAssistantMessage = _a.onAssistantMessage, initialConversationId = _a.conversationId, onConversationIdChange = _a.onConversationIdChange, onChatWidgetOpen = _a.onChatWidgetOpen, onChatWidgetClosed = _a.onChatWidgetClosed, onError = _a.onError, _h = _a.persistent, persistent = _h === void 0 ? false : _h,
96
+ // Floating button props
97
+ _j = _a.floating,
98
+ // Floating button props
99
+ floating = _j === void 0 ? true : _j, _k = _a.buttonText, buttonText = _k === void 0 ? "Chat with us" : _k, _l = _a.buttonPosition, buttonPosition = _l === void 0 ? 'bottom-right' : _l, buttonStyle = _a.buttonStyle, _m = _a.defaultOpen, defaultOpen = _m === void 0 ? false : _m, _o = _a.maximizeToggleButton, maximizeToggleButton = _o === void 0 ? true : _o, _p = _a.fullScreen, fullScreen = _p === void 0 ? false : _p, _q = _a.icon, icon = _q === void 0 ? 'message-circle' : _q,
100
+ // Styling props
101
+ _r = _a.primaryColor,
102
+ // Styling props
103
+ primaryColor = _r === void 0 ? "linear-gradient(to right, #3b82f6,rgb(8, 98, 242))" : _r;
104
+ var _s = useState(false), isInitialized = _s[0], setIsInitialized = _s[1];
105
+ var _t = useState(null), error = _t[0], setError = _t[1];
106
+ var _u = useState(initialMessages), messages = _u[0], setMessages = _u[1];
107
+ var _v = useState(''), inputValue = _v[0], setInputValue = _v[1];
108
+ var _w = useState(initialConversationId || getStoredConversationId(persistent)), conversationId = _w[0], setConversationId = _w[1];
109
+ var _x = useState(defaultOpen), isOpen = _x[0], setIsOpen = _x[1];
110
+ var _y = useState(false), isAnimating = _y[0], setIsAnimating = _y[1];
111
+ var _z = useState(false), isLoading = _z[0], setIsLoading = _z[1];
112
+ var _0 = useState(false), isMaximized = _0[0], setIsMaximized = _0[1];
113
+ var messagesEndRef = useRef(null);
114
+ // Helper function to get dimensions based on size
115
+ var getDimensions = function () {
116
+ // If custom width/height are provided, use them
117
+ if (width && height) {
118
+ return { width: width, height: height };
119
+ }
120
+ // Otherwise, use size-based dimensions
121
+ switch (size) {
122
+ case 'small':
123
+ return { width: '320px', height: '400px' };
124
+ case 'large':
125
+ return { width: '480px', height: '600px' };
126
+ case 'medium':
127
+ default:
128
+ return { width: '380px', height: '500px' };
129
+ }
130
+ };
131
+ var _1 = getDimensions(), actualWidth = _1.width, actualHeight = _1.height;
132
+ // Function to update conversation ID and notify parent
133
+ var updateConversationId = function (newConversationId) {
134
+ setConversationId(newConversationId);
135
+ if (newConversationId) {
136
+ saveConversationId(newConversationId, persistent);
137
+ }
138
+ else {
139
+ clearStoredConversationId(persistent);
140
+ }
141
+ if (onConversationIdChange) {
142
+ onConversationIdChange(newConversationId);
143
+ }
144
+ };
145
+ // Function to fetch conversation history
146
+ var fetchConversationHistory = function (convId) { return __awaiter(void 0, void 0, void 0, function () {
147
+ var response, sessionData, error_1;
148
+ return __generator(this, function (_a) {
149
+ switch (_a.label) {
150
+ case 0:
151
+ _a.trys.push([0, 5, , 6]);
152
+ console.log("Fetching conversation history for:", convId);
153
+ return [4 /*yield*/, fetch("https://api.blumessage.com/api/v1/conversations/session/".concat(convId), {
154
+ method: 'GET',
155
+ headers: {
156
+ 'Authorization': apiKey,
157
+ },
158
+ })];
159
+ case 1:
160
+ response = _a.sent();
161
+ if (!response.ok) return [3 /*break*/, 3];
162
+ return [4 /*yield*/, response.json()];
163
+ case 2:
164
+ sessionData = _a.sent();
165
+ console.log("Conversation history loaded successfully");
166
+ return [2 /*return*/, sessionData.messages || []];
167
+ case 3:
168
+ console.error("Failed to fetch conversation history:", response.status, response.statusText);
169
+ // Clear invalid conversation ID from storage
170
+ updateConversationId(null);
171
+ if (onError) {
172
+ onError("Failed to fetch conversation history: ".concat(response.status, " ").concat(response.statusText), "conversation_history");
173
+ }
174
+ return [2 /*return*/, []];
175
+ case 4: return [3 /*break*/, 6];
176
+ case 5:
177
+ error_1 = _a.sent();
178
+ console.error("Error fetching conversation history:", error_1);
179
+ // Clear invalid conversation ID from storage
180
+ updateConversationId(null);
181
+ if (onError) {
182
+ onError("Error fetching conversation history: ".concat(error_1), "conversation_history");
183
+ }
184
+ return [2 /*return*/, []];
185
+ case 6: return [2 /*return*/];
186
+ }
187
+ });
188
+ }); };
189
+ useEffect(function () {
190
+ if (!apiKey) {
191
+ console.error("Blumessage Chat: API key is required");
192
+ var errorMessage = "API key is required";
193
+ setError(errorMessage);
194
+ if (onError) {
195
+ onError(errorMessage, "missing_api_key");
196
+ }
197
+ return;
198
+ }
199
+ // Validate API key with Blumessage API
200
+ var validateApiKey = function () { return __awaiter(void 0, void 0, void 0, function () {
201
+ var response, historyMessages, errorMessage, err_1, errorMessage;
202
+ return __generator(this, function (_a) {
203
+ switch (_a.label) {
204
+ case 0:
205
+ _a.trys.push([0, 9, , 10]);
206
+ setIsInitialized(false);
207
+ setError(null);
208
+ console.log("Initializing Blumessage chat...");
209
+ return [4 /*yield*/, fetch('https://api.blumessage.com/api/v1/api-keys/validate', {
210
+ method: 'POST',
211
+ headers: {
212
+ 'Content-Type': 'application/json',
213
+ },
214
+ body: JSON.stringify({ apiKey: apiKey }),
215
+ })];
216
+ case 1:
217
+ response = _a.sent();
218
+ if (!(response.status === 201)) return [3 /*break*/, 7];
219
+ console.log("Blumessage chat initialized successfully");
220
+ setIsInitialized(true);
221
+ setError(null);
222
+ if (!(initialMessages.length > 0 && conversationId)) return [3 /*break*/, 2];
223
+ // Warn if both are provided - initialMessages takes precedence
224
+ console.warn('Both initialMessages and conversationId provided. Using initialMessages and ignoring stored conversation.');
225
+ setMessages(initialMessages);
226
+ return [3 /*break*/, 6];
227
+ case 2:
228
+ if (!(initialMessages.length > 0)) return [3 /*break*/, 3];
229
+ // Use provided initial messages
230
+ setMessages(initialMessages);
231
+ return [3 /*break*/, 6];
232
+ case 3:
233
+ if (!conversationId) return [3 /*break*/, 5];
234
+ return [4 /*yield*/, fetchConversationHistory(conversationId)];
235
+ case 4:
236
+ historyMessages = _a.sent();
237
+ setMessages(historyMessages); // Will be empty array if fetch failed
238
+ return [3 /*break*/, 6];
239
+ case 5:
240
+ // No conversation ID and no initial messages - start with empty array
241
+ setMessages([]);
242
+ _a.label = 6;
243
+ case 6: return [3 /*break*/, 8];
244
+ case 7:
245
+ console.error("Blumessage chat initialization failed:", response.status, response.statusText);
246
+ errorMessage = "Unable to connect - invalid API key";
247
+ setError(errorMessage);
248
+ setIsInitialized(false);
249
+ if (onError) {
250
+ onError(errorMessage, "api_key_validation");
251
+ }
252
+ _a.label = 8;
253
+ case 8: return [3 /*break*/, 10];
254
+ case 9:
255
+ err_1 = _a.sent();
256
+ console.error("Blumessage chat initialization error:", err_1);
257
+ errorMessage = "Unable to connect - network error";
258
+ setError(errorMessage);
259
+ setIsInitialized(false);
260
+ if (onError) {
261
+ onError(errorMessage, "network_error");
262
+ }
263
+ return [3 /*break*/, 10];
264
+ case 10: return [2 /*return*/];
265
+ }
266
+ });
267
+ }); };
268
+ validateApiKey();
269
+ }, [apiKey, conversationId]);
270
+ var handleSendMessage = function () { return __awaiter(void 0, void 0, void 0, function () {
271
+ var userMessage, currentInput, requestBody, response, apiResponse, assistantMessages, latestAssistantMessage, assistantResponse_1, errorMessage_1, error_2, errorMessage_2;
272
+ return __generator(this, function (_a) {
273
+ switch (_a.label) {
274
+ case 0:
275
+ if (!inputValue.trim() || isLoading)
276
+ return [2 /*return*/];
277
+ userMessage = {
278
+ id: Date.now().toString(),
279
+ content: inputValue.trim(),
280
+ role: 'user',
281
+ timestamp: Date.now()
282
+ };
283
+ // Add user message to UI immediately
284
+ setMessages(function (prev) { return __spreadArray(__spreadArray([], prev, true), [userMessage], false); });
285
+ currentInput = inputValue.trim();
286
+ setInputValue('');
287
+ setIsLoading(true);
288
+ // Call the callback if provided
289
+ if (onUserMessage) {
290
+ onUserMessage(userMessage);
291
+ }
292
+ _a.label = 1;
293
+ case 1:
294
+ _a.trys.push([1, 6, 7, 8]);
295
+ requestBody = {
296
+ message: currentInput,
297
+ };
298
+ // Include conversationId if we have one
299
+ if (conversationId) {
300
+ requestBody.conversationId = conversationId;
301
+ }
302
+ return [4 /*yield*/, fetch('https://api.blumessage.com/api/v1/conversations', {
303
+ method: 'POST',
304
+ headers: {
305
+ 'Content-Type': 'application/json',
306
+ 'Authorization': "Bearer ".concat(apiKey),
307
+ },
308
+ body: JSON.stringify(requestBody),
309
+ })];
310
+ case 2:
311
+ response = _a.sent();
312
+ if (!response.ok) return [3 /*break*/, 4];
313
+ return [4 /*yield*/, response.json()];
314
+ case 3:
315
+ apiResponse = _a.sent();
316
+ // Update conversation ID if this is the first message
317
+ if (!conversationId) {
318
+ updateConversationId(apiResponse.conversationId);
319
+ }
320
+ assistantMessages = apiResponse.messages.filter(function (msg) { return msg.role === 'assistant'; });
321
+ latestAssistantMessage = assistantMessages[assistantMessages.length - 1];
322
+ if (latestAssistantMessage) {
323
+ assistantResponse_1 = {
324
+ id: (Date.now() + 1).toString(),
325
+ content: latestAssistantMessage.content,
326
+ role: 'assistant',
327
+ timestamp: latestAssistantMessage.timestamp,
328
+ };
329
+ setMessages(function (prev) { return __spreadArray(__spreadArray([], prev, true), [assistantResponse_1], false); });
330
+ // This was already handled in the component, assistant message callback
331
+ if (onAssistantMessage) {
332
+ onAssistantMessage(assistantResponse_1);
333
+ }
334
+ }
335
+ return [3 /*break*/, 5];
336
+ case 4:
337
+ console.error('Failed to send message to Blumessage API:', response.status, response.statusText);
338
+ errorMessage_1 = {
339
+ id: (Date.now() + 1).toString(),
340
+ content: "Sorry, I'm having trouble connecting right now. Please try again.",
341
+ role: 'assistant',
342
+ timestamp: Date.now(),
343
+ };
344
+ setMessages(function (prev) { return __spreadArray(__spreadArray([], prev, true), [errorMessage_1], false); });
345
+ if (onError) {
346
+ onError("Failed to send message: ".concat(response.status, " ").concat(response.statusText), "message_send");
347
+ }
348
+ _a.label = 5;
349
+ case 5: return [3 /*break*/, 8];
350
+ case 6:
351
+ error_2 = _a.sent();
352
+ console.error('Error sending message to Blumessage API:', error_2);
353
+ errorMessage_2 = {
354
+ id: (Date.now() + 1).toString(),
355
+ content: "Sorry, I'm having trouble connecting right now. Please try again.",
356
+ role: 'assistant',
357
+ timestamp: Date.now(),
358
+ };
359
+ setMessages(function (prev) { return __spreadArray(__spreadArray([], prev, true), [errorMessage_2], false); });
360
+ if (onError) {
361
+ onError("Error sending message: ".concat(error_2), "message_send");
362
+ }
363
+ return [3 /*break*/, 8];
364
+ case 7:
365
+ setIsLoading(false);
366
+ return [7 /*endfinally*/];
367
+ case 8: return [2 /*return*/];
368
+ }
369
+ });
370
+ }); };
371
+ var handleKeyPress = function (e) {
372
+ if (e.key === 'Enter' && !isLoading) {
373
+ handleSendMessage();
374
+ }
375
+ };
376
+ // Auto-scroll to bottom when messages change
377
+ useEffect(function () {
378
+ var _a;
379
+ (_a = messagesEndRef.current) === null || _a === void 0 ? void 0 : _a.scrollIntoView({ behavior: 'smooth' });
380
+ }, [messages]);
381
+ // Auto-scroll to bottom when chat widget opens
382
+ useEffect(function () {
383
+ if (isOpen && floating) {
384
+ // Add a small delay to ensure the DOM is updated after the animation starts
385
+ setTimeout(function () {
386
+ var _a;
387
+ (_a = messagesEndRef.current) === null || _a === void 0 ? void 0 : _a.scrollIntoView({ behavior: 'smooth' });
388
+ }, 50);
389
+ }
390
+ }, [isOpen, floating]);
391
+ // Handle opening the chat with animation
392
+ var handleOpenChat = function () {
393
+ if (!isOpen && !isAnimating) {
394
+ setIsAnimating(true);
395
+ // Small delay to ensure smooth animation start
396
+ setTimeout(function () {
397
+ setIsOpen(true);
398
+ // Call the callback after the chat is open
399
+ if (onChatWidgetOpen) {
400
+ onChatWidgetOpen();
401
+ }
402
+ }, 10);
403
+ // Animation duration
404
+ setTimeout(function () {
405
+ setIsAnimating(false);
406
+ }, 300);
407
+ }
408
+ };
409
+ // Handle closing the chat with animation
410
+ var handleCloseChat = function () {
411
+ if (isOpen && !isAnimating) {
412
+ setIsAnimating(true);
413
+ setIsOpen(false);
414
+ // Reset maximized state when closing
415
+ setIsMaximized(false);
416
+ // Call the callback when closing
417
+ if (onChatWidgetClosed) {
418
+ onChatWidgetClosed();
419
+ }
420
+ // Wait for animation to complete
421
+ setTimeout(function () {
422
+ setIsAnimating(false);
423
+ }, 300);
424
+ }
425
+ };
426
+ // Handle maximize/minimize toggle
427
+ var handleToggleMaximize = function () {
428
+ setIsMaximized(!isMaximized);
429
+ };
430
+ // Get the icon component based on the icon prop
431
+ var getIconComponent = function () {
432
+ // More permissive icon matching - handle various naming patterns
433
+ var iconName = icon.toLowerCase().replace(/[-_\s]/g, '');
434
+ // Try to match common icon patterns
435
+ if (iconName.includes('message') || iconName.includes('chat')) {
436
+ if (iconName.includes('square'))
437
+ return MessageSquare;
438
+ return MessageCircle;
439
+ }
440
+ if (iconName.includes('bot') || iconName.includes('robot'))
441
+ return Bot;
442
+ if (iconName.includes('phone') || iconName.includes('call'))
443
+ return Phone;
444
+ if (iconName.includes('mail') || iconName.includes('email'))
445
+ return Mail;
446
+ if (iconName.includes('headphone') || iconName.includes('support'))
447
+ return Headphones;
448
+ if (iconName.includes('user')) {
449
+ if (iconName.includes('users') || iconName.includes('group'))
450
+ return Users;
451
+ return User;
452
+ }
453
+ if (iconName.includes('heart') || iconName.includes('like') || iconName.includes('love'))
454
+ return Heart;
455
+ if (iconName.includes('star') || iconName.includes('favorite'))
456
+ return Star;
457
+ if (iconName.includes('zap') || iconName.includes('lightning') || iconName.includes('bolt'))
458
+ return Zap;
459
+ // Default fallback
460
+ return MessageCircle;
461
+ };
462
+ // Helper function to get position styles for floating button
463
+ var getButtonPositionStyles = function () {
464
+ var baseStyles = {
465
+ position: 'fixed',
466
+ zIndex: 1000,
467
+ opacity: isOpen ? 0 : 1,
468
+ pointerEvents: isOpen ? 'none' : 'auto',
469
+ transition: 'opacity 0.3s cubic-bezier(0.4, 0, 0.2, 1)',
470
+ };
471
+ switch (buttonPosition) {
472
+ case 'bottom-right':
473
+ return __assign(__assign({}, baseStyles), { bottom: '24px', right: '24px' });
474
+ case 'bottom-left':
475
+ return __assign(__assign({}, baseStyles), { bottom: '24px', left: '24px' });
476
+ case 'top-right':
477
+ return __assign(__assign({}, baseStyles), { top: '24px', right: '24px' });
478
+ case 'top-left':
479
+ return __assign(__assign({}, baseStyles), { top: '24px', left: '24px' });
480
+ default:
481
+ return __assign(__assign({}, baseStyles), { bottom: '24px', right: '24px' });
482
+ }
483
+ };
484
+ // Helper function to get position styles for floating chat window
485
+ var getChatPositionStyles = function () {
486
+ var getTransform = function () {
487
+ if (!isOpen) {
488
+ // Slide down for bottom positions, slide up for top positions
489
+ return (buttonPosition === null || buttonPosition === void 0 ? void 0 : buttonPosition.includes('bottom')) ? 'translateY(100%)' : 'translateY(-100%)';
490
+ }
491
+ return 'translateY(0)';
492
+ };
493
+ var baseStyles = {
494
+ position: 'fixed',
495
+ zIndex: 999,
496
+ transform: getTransform(),
497
+ transition: 'transform 0.3s cubic-bezier(0.4, 0, 0.2, 1), opacity 0.3s cubic-bezier(0.4, 0, 0.2, 1)',
498
+ opacity: isOpen ? 1 : 0,
499
+ pointerEvents: isOpen ? 'auto' : 'none',
500
+ };
501
+ // If fullScreen or maximized, override positioning to be centered and full screen
502
+ if (fullScreen || isMaximized) {
503
+ // Set transform origin and direction based on button position for proper animation
504
+ var transformOrigin = 'center';
505
+ var closedTransform = 'translateY(100%)';
506
+ switch (buttonPosition) {
507
+ case 'bottom-right':
508
+ transformOrigin = 'bottom right';
509
+ closedTransform = 'translateY(100%)';
510
+ break;
511
+ case 'bottom-left':
512
+ transformOrigin = 'bottom left';
513
+ closedTransform = 'translateY(100%)';
514
+ break;
515
+ case 'top-right':
516
+ transformOrigin = 'top right';
517
+ closedTransform = 'translateY(-100%)';
518
+ break;
519
+ case 'top-left':
520
+ transformOrigin = 'top left';
521
+ closedTransform = 'translateY(-100%)';
522
+ break;
523
+ default:
524
+ transformOrigin = 'bottom right';
525
+ closedTransform = 'translateY(100%)';
526
+ }
527
+ return __assign(__assign({}, baseStyles), { top: '20px', left: '20px', right: '20px', bottom: '20px', transform: isOpen ? 'translateY(0)' : closedTransform, transformOrigin: transformOrigin });
528
+ }
529
+ switch (buttonPosition) {
530
+ case 'bottom-right':
531
+ return __assign(__assign({}, baseStyles), { bottom: '24px', right: '24px', transformOrigin: 'bottom right' });
532
+ case 'bottom-left':
533
+ return __assign(__assign({}, baseStyles), { bottom: '24px', left: '24px', transformOrigin: 'bottom left' });
534
+ case 'top-right':
535
+ return __assign(__assign({}, baseStyles), { top: '24px', right: '24px', transformOrigin: 'top right' });
536
+ case 'top-left':
537
+ return __assign(__assign({}, baseStyles), { top: '24px', left: '24px', transformOrigin: 'top left' });
538
+ default:
539
+ return __assign(__assign({}, baseStyles), { bottom: '24px', right: '24px', transformOrigin: 'bottom right' });
540
+ }
541
+ };
542
+ // Render chat window component
543
+ var renderChatWindow = function () {
544
+ var chatContent = (_jsxs("div", { className: "shadow-2xl flex flex-col overflow-hidden border ".concat(theme === 'dark'
545
+ ? 'bg-gray-900 border-gray-700'
546
+ : 'bg-white border-black/10'), style: {
547
+ width: (fullScreen || isMaximized) ? '100%' : actualWidth,
548
+ height: (fullScreen || isMaximized) ? '100%' : actualHeight,
549
+ fontFamily: 'system-ui, -apple-system, sans-serif',
550
+ borderRadius: (fullScreen || isMaximized) ? '12px' : '24px'
551
+ }, children: [_jsxs("div", { className: "flex items-center px-6 py-4 border-b ".concat(theme === 'dark'
552
+ ? 'bg-gray-900 border-gray-700'
553
+ : 'bg-white border-gray-100'), children: [_jsx("div", { className: "w-12 h-12 rounded-full flex items-center justify-center mr-4", style: { backgroundImage: primaryColor }, children: React.createElement(getIconComponent(), { className: "w-6 h-6 text-white" }) }), _jsxs("div", { className: "flex-1", children: [_jsx("div", { className: "text-lg font-semibold m-0 leading-6 ".concat(theme === 'dark' ? 'text-gray-100' : 'text-gray-900'), children: name }), _jsx("div", { className: "text-sm m-0 leading-5 ".concat(theme === 'dark' ? 'text-gray-400' : 'text-gray-500'), children: subtitle })] }), floating && (_jsxs("div", { className: "flex items-center gap-1", children: [maximizeToggleButton && (_jsx("button", { onClick: handleToggleMaximize, className: "w-8 h-8 rounded-full flex items-center justify-center cursor-pointer transition-colors ".concat(theme === 'dark'
554
+ ? 'hover:bg-gray-800 text-gray-400 hover:text-gray-200'
555
+ : 'hover:bg-gray-100 text-gray-500 hover:text-gray-700'), children: isMaximized ? _jsx(Minimize2, { className: "w-4 h-4" }) : _jsx(Maximize, { className: "w-4 h-4" }) })), _jsx("button", { onClick: handleCloseChat, className: "w-8 h-8 rounded-full flex items-center justify-center cursor-pointer transition-colors ".concat(theme === 'dark'
556
+ ? 'hover:bg-gray-800 text-gray-400 hover:text-gray-200'
557
+ : 'hover:bg-gray-100 text-gray-500 hover:text-gray-700'), children: _jsx(X, { className: "w-4 h-4" }) })] }))] }), _jsxs("div", { className: "flex-1 px-6 py-4 flex flex-col gap-4 overflow-y-auto ".concat(theme === 'dark' ? 'bg-gray-800' : 'bg-gray-50'), children: [messages.map(function (message) { return (_jsx("div", { className: "flex ".concat(message.role === 'user' ? 'justify-end' : 'justify-start'), children: _jsx("div", { className: "px-4 py-3 rounded-2xl max-w-[80%] text-sm leading-6 ".concat(message.role === 'user'
558
+ ? 'text-white'
559
+ : theme === 'dark'
560
+ ? 'bg-gray-700 text-gray-100 border border-gray-600 shadow-sm'
561
+ : 'bg-white text-gray-800 border border-gray-200 shadow-sm'), style: message.role === 'user' ? { backgroundImage: primaryColor } : {}, children: message.content }) }, message.id)); }), isLoading && (_jsx("div", { className: "flex justify-start", children: _jsx("div", { className: "px-4 py-3 rounded-2xl max-w-[80%] text-sm leading-6 shadow-sm ".concat(theme === 'dark'
562
+ ? 'bg-gray-700 text-gray-100 border border-gray-600'
563
+ : 'bg-white text-gray-800 border border-gray-200'), children: _jsxs("div", { className: "flex space-x-1", children: [_jsx("div", { className: "w-2 h-2 rounded-full animate-bounce ".concat(theme === 'dark' ? 'bg-gray-400' : 'bg-gray-400'), style: { animationDelay: '0ms' } }), _jsx("div", { className: "w-2 h-2 rounded-full animate-bounce ".concat(theme === 'dark' ? 'bg-gray-400' : 'bg-gray-400'), style: { animationDelay: '150ms' } }), _jsx("div", { className: "w-2 h-2 rounded-full animate-bounce ".concat(theme === 'dark' ? 'bg-gray-400' : 'bg-gray-400'), style: { animationDelay: '300ms' } })] }) }) })), messages.length === 0 && !isLoading && (_jsx("div", { className: "text-center text-sm py-8 ".concat(theme === 'dark' ? 'text-gray-400' : 'text-gray-500'), children: "No messages yet. Start a conversation!" })), _jsx("div", { ref: messagesEndRef })] }), _jsx("div", { className: "px-6 py-4 border-t ".concat(theme === 'dark'
564
+ ? 'bg-gray-900 border-gray-700'
565
+ : 'bg-white border-gray-100'), children: _jsxs("div", { className: "flex items-center rounded-full px-4 py-3 border ".concat(theme === 'dark'
566
+ ? 'bg-gray-800 border-gray-600'
567
+ : 'bg-gray-50 border-gray-200'), children: [_jsx("input", { className: "flex-1 border-none bg-transparent outline-none text-sm font-inherit ".concat(theme === 'dark' ? 'text-gray-100' : 'text-gray-700'), type: "text", placeholder: placeholder, value: inputValue, onChange: function (e) { return setInputValue(e.target.value); }, onKeyPress: handleKeyPress }), _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 ? (_jsx(Loader2, { className: "w-4 h-4 animate-spin" })) : (_jsx(Send, { className: "w-4 h-4" })) })] }) })] }));
568
+ if (floating) {
569
+ return (_jsx("div", { style: getChatPositionStyles(), children: chatContent }));
570
+ }
571
+ return chatContent;
572
+ };
573
+ // Don't render anything if no API key is provided
574
+ if (!apiKey) {
575
+ return null;
576
+ }
577
+ if (error) {
578
+ var errorContent = (_jsxs("div", { className: "shadow-2xl flex flex-col overflow-hidden border ".concat(theme === 'dark'
579
+ ? 'bg-gray-900 border-gray-700'
580
+ : 'bg-white border-black/10'), style: {
581
+ width: (fullScreen || isMaximized) ? '100%' : actualWidth,
582
+ height: (fullScreen || isMaximized) ? '100%' : actualHeight,
583
+ fontFamily: 'system-ui, -apple-system, sans-serif',
584
+ borderRadius: (fullScreen || isMaximized) ? '12px' : '24px'
585
+ }, children: [_jsxs("div", { className: "flex items-center px-6 py-4 border-b ".concat(theme === 'dark'
586
+ ? 'bg-gray-900 border-gray-700'
587
+ : 'bg-white border-gray-100'), children: [_jsx("div", { className: "w-12 h-12 rounded-full bg-red-500 flex items-center justify-center mr-4", children: _jsx(AlertTriangle, { className: "w-6 h-6 text-white" }) }), _jsxs("div", { className: "flex-1", children: [_jsx("div", { className: "text-lg font-semibold m-0 leading-6 ".concat(theme === 'dark' ? 'text-gray-100' : 'text-gray-900'), children: "Connection Error" }), _jsx("div", { className: "text-sm m-0 leading-5 ".concat(theme === 'dark' ? 'text-gray-400' : 'text-gray-500'), children: "Unable to connect" })] }), floating && (_jsxs("div", { className: "flex items-center gap-1", children: [maximizeToggleButton && (_jsx("button", { onClick: handleToggleMaximize, className: "w-8 h-8 rounded-full flex items-center justify-center cursor-pointer transition-colors ".concat(theme === 'dark'
588
+ ? 'hover:bg-gray-800 text-gray-400 hover:text-gray-200'
589
+ : 'hover:bg-gray-100 text-gray-500 hover:text-gray-700'), children: isMaximized ? _jsx(Minimize2, { className: "w-4 h-4" }) : _jsx(Maximize, { className: "w-4 h-4" }) })), _jsx("button", { onClick: handleCloseChat, className: "w-8 h-8 rounded-full flex items-center justify-center cursor-pointer transition-colors ".concat(theme === 'dark'
590
+ ? 'hover:bg-gray-800 text-gray-400 hover:text-gray-200'
591
+ : 'hover:bg-gray-100 text-gray-500 hover:text-gray-700'), children: _jsx(X, { className: "w-4 h-4" }) })] }))] }), _jsx("div", { className: "flex-1 px-6 py-4 flex flex-col gap-4 overflow-y-auto ".concat(theme === 'dark' ? 'bg-gray-800' : 'bg-gray-50'), children: _jsx("div", { className: "flex justify-start", children: _jsx("div", { className: "px-4 py-3 rounded-2xl max-w-[80%] text-sm leading-6 shadow-sm ".concat(theme === 'dark'
592
+ ? 'bg-gray-700 text-gray-100 border border-gray-600'
593
+ : 'bg-white text-gray-800 border border-gray-200'), children: error }) }) })] }));
594
+ if (floating) {
595
+ return (_jsxs(_Fragment, { children: [_jsxs("button", { onClick: handleOpenChat, className: "text-white rounded-full shadow-lg transition-all duration-200 flex items-center justify-center gap-2 ".concat(buttonText ? 'px-4 py-3 h-12' : 'w-14 h-14'), style: __assign(__assign(__assign({}, getButtonPositionStyles()), buttonStyle), { backgroundImage: primaryColor }), children: [React.createElement(getIconComponent(), { className: "w-6 h-6" }), buttonText && _jsx("span", { className: "text-sm font-medium whitespace-nowrap", children: buttonText })] }), _jsx("div", { style: getChatPositionStyles(), children: errorContent })] }));
596
+ }
597
+ return errorContent;
598
+ }
599
+ if (!isInitialized) {
600
+ var loadingContent = (_jsxs("div", { className: "shadow-2xl flex flex-col overflow-hidden border ".concat(theme === 'dark'
601
+ ? 'bg-gray-900 border-gray-700'
602
+ : 'bg-white border-black/10'), style: {
603
+ width: (fullScreen || isMaximized) ? '100%' : actualWidth,
604
+ height: (fullScreen || isMaximized) ? '100%' : actualHeight,
605
+ fontFamily: 'system-ui, -apple-system, sans-serif',
606
+ borderRadius: (fullScreen || isMaximized) ? '12px' : '24px'
607
+ }, children: [_jsxs("div", { className: "flex items-center px-6 py-4 border-b ".concat(theme === 'dark'
608
+ ? 'bg-gray-900 border-gray-700'
609
+ : 'bg-white border-gray-100'), children: [_jsx("div", { className: "w-12 h-12 rounded-full flex items-center justify-center mr-4", style: { backgroundImage: primaryColor }, children: _jsx(Loader2, { className: "w-6 h-6 text-white animate-spin" }) }), _jsxs("div", { className: "flex-1", children: [_jsx("div", { className: "text-lg font-semibold m-0 leading-6 ".concat(theme === 'dark' ? 'text-gray-100' : 'text-gray-900'), children: name }), _jsx("div", { className: "text-sm m-0 leading-5 ".concat(theme === 'dark' ? 'text-gray-400' : 'text-gray-500'), children: subtitle })] }), floating && (_jsxs("div", { className: "flex items-center gap-1", children: [maximizeToggleButton && (_jsx("button", { onClick: handleToggleMaximize, className: "w-8 h-8 rounded-full flex items-center justify-center cursor-pointer transition-colors ".concat(theme === 'dark'
610
+ ? 'hover:bg-gray-800 text-gray-400 hover:text-gray-200'
611
+ : 'hover:bg-gray-100 text-gray-500 hover:text-gray-700'), children: isMaximized ? _jsx(Minimize2, { className: "w-4 h-4" }) : _jsx(Maximize, { className: "w-4 h-4" }) })), _jsx("button", { onClick: handleCloseChat, className: "w-8 h-8 rounded-full flex items-center justify-center cursor-pointer transition-colors ".concat(theme === 'dark'
612
+ ? 'hover:bg-gray-800 text-gray-400 hover:text-gray-200'
613
+ : 'hover:bg-gray-100 text-gray-500 hover:text-gray-700'), children: _jsx(X, { className: "w-4 h-4" }) })] }))] }), _jsx("div", { className: "flex-1 px-6 py-4 flex flex-col gap-4 overflow-y-auto ".concat(theme === 'dark' ? 'bg-gray-800' : 'bg-gray-50'), children: _jsx("div", { className: "text-center text-sm py-8 ".concat(theme === 'dark' ? 'text-gray-400' : 'text-gray-500'), children: "Ready to chat..." }) })] }));
614
+ if (floating) {
615
+ return (_jsxs(_Fragment, { children: [_jsxs("button", { onClick: handleOpenChat, className: "text-white rounded-full shadow-lg transition-all duration-200 flex items-center justify-center gap-2 ".concat(buttonText ? 'px-4 py-3 h-12' : 'w-14 h-14'), style: __assign(__assign(__assign({}, getButtonPositionStyles()), buttonStyle), { backgroundImage: primaryColor }), children: [React.createElement(getIconComponent(), { className: "w-6 h-6" }), buttonText && _jsx("span", { className: "text-sm font-medium whitespace-nowrap", children: buttonText })] }), _jsx("div", { style: getChatPositionStyles(), children: loadingContent })] }));
616
+ }
617
+ return loadingContent;
618
+ }
619
+ // Main render for initialized state
620
+ if (floating) {
621
+ return (_jsxs(_Fragment, { children: [_jsxs("button", { onClick: handleOpenChat, className: "text-white rounded-full shadow-lg transition-all duration-200 flex items-center justify-center gap-2 ".concat(buttonText ? 'px-4 py-3 h-12' : 'w-14 h-14'), style: __assign(__assign(__assign({}, getButtonPositionStyles()), buttonStyle), { backgroundImage: primaryColor }), children: [React.createElement(getIconComponent(), { className: "w-6 h-6" }), buttonText && _jsx("span", { className: "text-sm font-medium whitespace-nowrap", children: buttonText })] }), renderChatWindow()] }));
622
+ }
623
+ return renderChatWindow();
624
+ };