@chatwidgetai/chat-widget 0.1.1 → 0.1.3
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/dist/api/client.d.ts +3 -0
- package/dist/api/client.d.ts.map +1 -1
- package/dist/components/ChatWidget.d.ts.map +1 -1
- package/dist/components/ChatWindow.d.ts.map +1 -1
- package/dist/components/MessageInput.d.ts +1 -0
- package/dist/components/MessageInput.d.ts.map +1 -1
- package/dist/components/MessageList.d.ts +1 -0
- package/dist/components/MessageList.d.ts.map +1 -1
- package/dist/hooks/useChat.d.ts.map +1 -1
- package/dist/index.esm.js +458 -48
- package/dist/index.esm.js.map +1 -1
- package/dist/index.js +458 -48
- package/dist/index.js.map +1 -1
- package/dist/types/index.d.ts +111 -5
- package/dist/types/index.d.ts.map +1 -1
- package/dist/utils/applyAppearanceStyles.d.ts +10 -0
- package/dist/utils/applyAppearanceStyles.d.ts.map +1 -0
- package/package.json +1 -1
- package/dist/ai-chat-widget.umd.js +0 -65776
- package/dist/ai-chat-widget.umd.js.map +0 -1
package/dist/index.esm.js
CHANGED
|
@@ -67,6 +67,19 @@ async function buildApiError(response, defaultMessage) {
|
|
|
67
67
|
class WidgetApiClient {
|
|
68
68
|
constructor(config) {
|
|
69
69
|
this.config = config;
|
|
70
|
+
this.detectedTimeZone = WidgetApiClient.detectTimeZone();
|
|
71
|
+
}
|
|
72
|
+
static detectTimeZone() {
|
|
73
|
+
try {
|
|
74
|
+
const tz = Intl.DateTimeFormat().resolvedOptions().timeZone;
|
|
75
|
+
return tz && tz.trim().length > 0 ? tz : "UTC";
|
|
76
|
+
}
|
|
77
|
+
catch {
|
|
78
|
+
return "UTC";
|
|
79
|
+
}
|
|
80
|
+
}
|
|
81
|
+
getTimeZone() {
|
|
82
|
+
return this.detectedTimeZone;
|
|
70
83
|
}
|
|
71
84
|
/**
|
|
72
85
|
* Get widget configuration
|
|
@@ -87,7 +100,15 @@ class WidgetApiClient {
|
|
|
87
100
|
}
|
|
88
101
|
async getOrCreateConversation(conversationId) {
|
|
89
102
|
const baseUrl = `${this.config.apiUrl}/api/widget/${this.config.widgetId}/conversation`;
|
|
90
|
-
const
|
|
103
|
+
const params = new URLSearchParams();
|
|
104
|
+
if (conversationId) {
|
|
105
|
+
params.set('conversationId', conversationId);
|
|
106
|
+
}
|
|
107
|
+
const timeZone = this.getTimeZone();
|
|
108
|
+
if (timeZone) {
|
|
109
|
+
params.set('timeZone', timeZone);
|
|
110
|
+
}
|
|
111
|
+
const query = params.toString() ? `?${params.toString()}` : '';
|
|
91
112
|
const response = await fetch(`${baseUrl}${query}`, {
|
|
92
113
|
method: 'GET',
|
|
93
114
|
headers: {
|
|
@@ -134,6 +155,7 @@ class WidgetApiClient {
|
|
|
134
155
|
conversationId: conversationId,
|
|
135
156
|
message,
|
|
136
157
|
fileIds,
|
|
158
|
+
timeZone: this.getTimeZone(),
|
|
137
159
|
}),
|
|
138
160
|
});
|
|
139
161
|
if (!response.ok) {
|
|
@@ -156,6 +178,7 @@ class WidgetApiClient {
|
|
|
156
178
|
conversationId: conversationId,
|
|
157
179
|
message,
|
|
158
180
|
fileIds,
|
|
181
|
+
timeZone: this.getTimeZone(),
|
|
159
182
|
}),
|
|
160
183
|
});
|
|
161
184
|
if (!response.ok) {
|
|
@@ -232,11 +255,6 @@ class WidgetApiClient {
|
|
|
232
255
|
/**
|
|
233
256
|
* Generate a unique session ID
|
|
234
257
|
*/
|
|
235
|
-
function generateSessionId() {
|
|
236
|
-
const timestamp = Date.now().toString(36);
|
|
237
|
-
const randomStr = Math.random().toString(36).substring(2, 15);
|
|
238
|
-
return `session_${timestamp}_${randomStr}`;
|
|
239
|
-
}
|
|
240
258
|
/**
|
|
241
259
|
* Generate a unique message ID
|
|
242
260
|
*/
|
|
@@ -291,6 +309,18 @@ function loadConversation(widgetId) {
|
|
|
291
309
|
return null;
|
|
292
310
|
}
|
|
293
311
|
}
|
|
312
|
+
/**
|
|
313
|
+
* Clear conversation from localStorage
|
|
314
|
+
*/
|
|
315
|
+
function clearConversation(widgetId) {
|
|
316
|
+
try {
|
|
317
|
+
const key = getStorageKey(widgetId);
|
|
318
|
+
localStorage.removeItem(key);
|
|
319
|
+
}
|
|
320
|
+
catch (error) {
|
|
321
|
+
console.error('Failed to clear conversation:', error);
|
|
322
|
+
}
|
|
323
|
+
}
|
|
294
324
|
/**
|
|
295
325
|
* Check if localStorage is available
|
|
296
326
|
*/
|
|
@@ -383,29 +413,53 @@ function useChat(options) {
|
|
|
383
413
|
config: null,
|
|
384
414
|
});
|
|
385
415
|
const apiClient = useRef(new WidgetApiClient({ widgetId, apiKey, apiUrl }));
|
|
386
|
-
// Load configuration and conversation
|
|
416
|
+
// Load configuration on mount and hydrate with existing conversation if available
|
|
387
417
|
useEffect(() => {
|
|
418
|
+
let isMounted = true;
|
|
419
|
+
console.log('[useChat] Effect running, mounting component');
|
|
388
420
|
const initialize = async () => {
|
|
389
421
|
try {
|
|
390
|
-
|
|
422
|
+
console.log('[useChat] Fetching config...');
|
|
391
423
|
const config = await apiClient.current.getConfig();
|
|
392
|
-
|
|
424
|
+
console.log('[useChat] Config fetched successfully:', {
|
|
425
|
+
hasAppearance: !!config.appearance,
|
|
426
|
+
hasLightMode: !!config.appearance?.lightMode,
|
|
427
|
+
hasDarkMode: !!config.appearance?.darkMode,
|
|
428
|
+
});
|
|
393
429
|
const persistConversation = config.behavior.persistConversation ?? true;
|
|
394
|
-
let conversationId;
|
|
430
|
+
let conversationId = '';
|
|
431
|
+
let messages = [];
|
|
395
432
|
if (persistConversation && isStorageAvailable()) {
|
|
396
433
|
const stored = loadConversation(widgetId);
|
|
397
|
-
|
|
434
|
+
const storedId = stored?.conversationId || stored?.sessionId;
|
|
435
|
+
if (storedId) {
|
|
436
|
+
try {
|
|
437
|
+
const conversation = await apiClient.current.getOrCreateConversation(storedId);
|
|
438
|
+
conversationId = conversation.id;
|
|
439
|
+
messages = conversation.messages;
|
|
440
|
+
}
|
|
441
|
+
catch (conversationError) {
|
|
442
|
+
console.warn('Failed to load existing conversation:', conversationError);
|
|
443
|
+
}
|
|
444
|
+
}
|
|
398
445
|
}
|
|
399
|
-
|
|
400
|
-
|
|
446
|
+
if (!isMounted) {
|
|
447
|
+
console.log('[useChat] Component unmounted, skipping state update');
|
|
448
|
+
return;
|
|
449
|
+
}
|
|
450
|
+
console.log('[useChat] Setting config in state');
|
|
401
451
|
setState(prev => ({
|
|
402
452
|
...prev,
|
|
403
453
|
config,
|
|
404
|
-
conversationId
|
|
405
|
-
messages
|
|
454
|
+
conversationId,
|
|
455
|
+
messages,
|
|
406
456
|
}));
|
|
407
457
|
}
|
|
408
458
|
catch (error) {
|
|
459
|
+
console.error('[useChat] Error fetching config:', error);
|
|
460
|
+
if (!isMounted) {
|
|
461
|
+
return;
|
|
462
|
+
}
|
|
409
463
|
const errorInfo = deriveErrorInfo(error);
|
|
410
464
|
const err = error instanceof Error ? error : new Error(errorInfo.message);
|
|
411
465
|
setState(prev => ({ ...prev, error: errorInfo.message }));
|
|
@@ -413,11 +467,18 @@ function useChat(options) {
|
|
|
413
467
|
}
|
|
414
468
|
};
|
|
415
469
|
initialize();
|
|
470
|
+
return () => {
|
|
471
|
+
console.log('[useChat] Effect cleanup, unmounting component');
|
|
472
|
+
isMounted = false;
|
|
473
|
+
};
|
|
416
474
|
}, [widgetId, apiKey, apiUrl, onError]);
|
|
417
475
|
// Save conversation when messages change
|
|
418
476
|
useEffect(() => {
|
|
419
477
|
const persistConversation = state.config?.behavior.persistConversation ?? true;
|
|
420
|
-
if (persistConversation &&
|
|
478
|
+
if (persistConversation &&
|
|
479
|
+
isStorageAvailable() &&
|
|
480
|
+
state.messages.length > 0 &&
|
|
481
|
+
state.conversationId) {
|
|
421
482
|
saveConversation(widgetId, state.conversationId, state.messages);
|
|
422
483
|
}
|
|
423
484
|
}, [widgetId, state.messages, state.conversationId, state.config?.behavior.persistConversation]);
|
|
@@ -425,13 +486,15 @@ function useChat(options) {
|
|
|
425
486
|
* Send a message
|
|
426
487
|
*/
|
|
427
488
|
const sendMessage = useCallback(async (content, files) => {
|
|
428
|
-
|
|
489
|
+
const trimmedContent = content.trim();
|
|
490
|
+
const hasFiles = !!files && files.length > 0;
|
|
491
|
+
if (!trimmedContent && !hasFiles)
|
|
429
492
|
return;
|
|
430
493
|
const userMessage = {
|
|
431
494
|
id: generateMessageId(),
|
|
432
495
|
message: {
|
|
433
496
|
type: 'human',
|
|
434
|
-
content:
|
|
497
|
+
content: trimmedContent,
|
|
435
498
|
},
|
|
436
499
|
timestamp: new Date().toISOString(),
|
|
437
500
|
sources: [],
|
|
@@ -446,13 +509,37 @@ function useChat(options) {
|
|
|
446
509
|
}));
|
|
447
510
|
onMessage?.(userMessage);
|
|
448
511
|
try {
|
|
512
|
+
let conversationId = state.conversationId;
|
|
513
|
+
if (!conversationId) {
|
|
514
|
+
const conversation = await apiClient.current.getOrCreateConversation();
|
|
515
|
+
conversationId = conversation.id;
|
|
516
|
+
setState(prev => {
|
|
517
|
+
const serverMessages = conversation.messages ?? [];
|
|
518
|
+
if (serverMessages.length === 0) {
|
|
519
|
+
return {
|
|
520
|
+
...prev,
|
|
521
|
+
conversationId,
|
|
522
|
+
};
|
|
523
|
+
}
|
|
524
|
+
const serverIds = new Set(serverMessages.map(msg => msg.id));
|
|
525
|
+
const mergedMessages = [
|
|
526
|
+
...serverMessages,
|
|
527
|
+
...prev.messages.filter(msg => !serverIds.has(msg.id)),
|
|
528
|
+
];
|
|
529
|
+
return {
|
|
530
|
+
...prev,
|
|
531
|
+
conversationId,
|
|
532
|
+
messages: mergedMessages,
|
|
533
|
+
};
|
|
534
|
+
});
|
|
535
|
+
}
|
|
449
536
|
// Upload files if provided
|
|
450
537
|
let fileIds;
|
|
451
538
|
if (files && files.length > 0) {
|
|
452
539
|
fileIds = [];
|
|
453
540
|
for (const file of files) {
|
|
454
541
|
try {
|
|
455
|
-
const uploadedFile = await apiClient.current.uploadFile(
|
|
542
|
+
const uploadedFile = await apiClient.current.uploadFile(conversationId, file);
|
|
456
543
|
fileIds.push(uploadedFile.id);
|
|
457
544
|
}
|
|
458
545
|
catch (uploadError) {
|
|
@@ -466,11 +553,11 @@ function useChat(options) {
|
|
|
466
553
|
let response;
|
|
467
554
|
if (useAgent) {
|
|
468
555
|
// Use agent endpoint - returns ConversationMessage[]
|
|
469
|
-
response = await apiClient.current.sendAgentMessage(
|
|
556
|
+
response = await apiClient.current.sendAgentMessage(conversationId, trimmedContent, fileIds);
|
|
470
557
|
}
|
|
471
558
|
else {
|
|
472
559
|
// Use standard chat endpoint
|
|
473
|
-
response = await apiClient.current.sendMessage(
|
|
560
|
+
response = await apiClient.current.sendMessage(conversationId, trimmedContent, fileIds);
|
|
474
561
|
}
|
|
475
562
|
// Both endpoints now return ConversationMessage[] array (FULL conversation)
|
|
476
563
|
if (Array.isArray(response)) {
|
|
@@ -582,12 +669,12 @@ function useChat(options) {
|
|
|
582
669
|
setState(prev => ({
|
|
583
670
|
...prev,
|
|
584
671
|
messages: [],
|
|
585
|
-
conversationId:
|
|
672
|
+
conversationId: '',
|
|
586
673
|
error: null,
|
|
587
674
|
}));
|
|
588
675
|
const persistConversation = state.config?.behavior.persistConversation ?? true;
|
|
589
676
|
if (persistConversation && isStorageAvailable()) {
|
|
590
|
-
|
|
677
|
+
clearConversation(widgetId);
|
|
591
678
|
}
|
|
592
679
|
}, [widgetId, state.config?.behavior.persistConversation]);
|
|
593
680
|
/**
|
|
@@ -21355,7 +21442,7 @@ const TypingIndicator = () => {
|
|
|
21355
21442
|
return (jsx("div", { className: "ai-chat-message assistant", children: jsxs("div", { className: "ai-chat-typing", children: [jsx("span", { className: "ai-chat-typing-dot" }), jsx("span", { className: "ai-chat-typing-dot" }), jsx("span", { className: "ai-chat-typing-dot" })] }) }));
|
|
21356
21443
|
};
|
|
21357
21444
|
|
|
21358
|
-
const MessageList = ({ messages, isTyping = false, showTypingIndicator = true, showTimestamps = true, enableFeedback = true, showSources = true, sourceDisplayMode = 'with-score', welcomeMessage, onFeedback, }) => {
|
|
21445
|
+
const MessageList = ({ messages, isTyping = false, showTypingIndicator = true, showTimestamps = true, enableFeedback = true, showSources = true, sourceDisplayMode = 'with-score', welcomeTitle, welcomeMessage, onFeedback, }) => {
|
|
21359
21446
|
const messagesEndRef = useRef(null);
|
|
21360
21447
|
// Auto-scroll to bottom when new messages arrive
|
|
21361
21448
|
useEffect(() => {
|
|
@@ -21375,7 +21462,7 @@ const MessageList = ({ messages, isTyping = false, showTypingIndicator = true, s
|
|
|
21375
21462
|
}
|
|
21376
21463
|
return map;
|
|
21377
21464
|
}, [messages]);
|
|
21378
|
-
return (jsxs("div", { className: "ai-chat-messages", role: "log", "aria-live": "polite", "aria-atomic": "false", children: [messages.length === 0 && welcomeMessage && (jsxs("div", { className: "ai-chat-welcome", children: [jsx("div", { className: "ai-chat-welcome-title", children:
|
|
21465
|
+
return (jsxs("div", { className: "ai-chat-messages", role: "log", "aria-live": "polite", "aria-atomic": "false", children: [messages.length === 0 && (welcomeTitle || welcomeMessage) && (jsxs("div", { className: "ai-chat-welcome", children: [welcomeTitle && (jsx("div", { className: "ai-chat-welcome-title", children: welcomeTitle })), welcomeMessage && (jsx("div", { className: "ai-chat-welcome-text", children: welcomeMessage }))] })), messages.map((message) => (jsx(Message, { message: message, showTimestamp: showTimestamps, enableFeedback: enableFeedback, showSources: showSources, sourceDisplayMode: sourceDisplayMode, toolCallNameById: toolCallNameById, onFeedback: onFeedback }, message.id))), isTyping && showTypingIndicator && jsx(TypingIndicator, {}), jsx("div", { ref: messagesEndRef })] }));
|
|
21379
21466
|
};
|
|
21380
21467
|
|
|
21381
21468
|
// Allowed file types
|
|
@@ -21401,7 +21488,7 @@ const formatFileSize = (bytes) => {
|
|
|
21401
21488
|
return (bytes / 1024).toFixed(1) + ' KB';
|
|
21402
21489
|
return (bytes / (1024 * 1024)).toFixed(1) + ' MB';
|
|
21403
21490
|
};
|
|
21404
|
-
const MessageInput = ({ onSend, placeholder = 'Type your message...', disabled = false, enableFileUpload = false, }) => {
|
|
21491
|
+
const MessageInput = ({ onSend, placeholder = 'Type your message...', disabled = false, enableFileUpload = false, separateFromChat = true, }) => {
|
|
21405
21492
|
const [value, setValue] = useState('');
|
|
21406
21493
|
const [selectedFiles, setSelectedFiles] = useState([]);
|
|
21407
21494
|
const textareaRef = useRef(null);
|
|
@@ -21459,7 +21546,8 @@ const MessageInput = ({ onSend, placeholder = 'Type your message...', disabled =
|
|
|
21459
21546
|
textareaRef.current.style.height = `${textareaRef.current.scrollHeight}px`;
|
|
21460
21547
|
}
|
|
21461
21548
|
};
|
|
21462
|
-
|
|
21549
|
+
console.log('[MessageInput] separateFromChat:', separateFromChat, 'class:', separateFromChat ? 'separate' : 'integrated');
|
|
21550
|
+
return (jsxs("div", { className: `ai-chat-input-container ${separateFromChat ? 'separate' : 'integrated'}`, children: [selectedFiles.length > 0 && (jsx("div", { className: "ai-chat-file-list", children: selectedFiles.map((file, index) => {
|
|
21463
21551
|
const ext = getFileExtension(file.name);
|
|
21464
21552
|
return (jsxs("div", { className: "ai-chat-file-item", children: [jsx("span", { className: "ai-chat-file-extension", children: ext }), jsxs("div", { className: "ai-chat-file-info", children: [jsx("span", { className: "ai-chat-file-name", children: file.name }), jsx("span", { className: "ai-chat-file-size", children: formatFileSize(file.size) })] }), jsx("button", { className: "ai-chat-file-remove", onClick: () => handleRemoveFile(index), "aria-label": "Remove file", children: "\u00D7" })] }, index));
|
|
21465
21553
|
}) })), jsxs("div", { className: "ai-chat-input-wrapper", children: [enableFileUpload && (jsxs(Fragment, { children: [jsx("input", { ref: fileInputRef, type: "file", onChange: handleFileSelect, style: { display: 'none' }, multiple: true, accept: ALLOWED_EXTENSIONS.join(','), "aria-label": "File input" }), jsx("button", { className: "ai-chat-file-button", onClick: () => fileInputRef.current?.click(), disabled: disabled, "aria-label": "Attach file", children: jsx("svg", { width: "20", height: "20", viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "2", strokeLinecap: "round", strokeLinejoin: "round", children: jsx("path", { d: "M21.44 11.05l-9.19 9.19a6 6 0 0 1-8.49-8.49l9.19-9.19a4 4 0 0 1 5.66 5.66l-9.2 9.19a2 2 0 0 1-2.83-2.83l8.49-8.48" }) }) })] })), jsx("textarea", { ref: textareaRef, className: "ai-chat-input", value: value, onChange: handleChange, onKeyDown: handleKeyDown, placeholder: placeholder, disabled: disabled, rows: 1, "aria-label": "Message input" }), jsx("button", { className: "ai-chat-send-button", onClick: handleSend, disabled: disabled || (!value.trim() && selectedFiles.length === 0), "aria-label": "Send message", children: jsxs("svg", { width: "20", height: "20", viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "2", strokeLinecap: "round", strokeLinejoin: "round", children: [jsx("line", { x1: "22", y1: "2", x2: "11", y2: "13" }), jsx("polygon", { points: "22 2 15 22 11 13 2 9 22 2" })] }) })] })] }));
|
|
@@ -21478,9 +21566,23 @@ const SuggestedQuestions = ({ questions, onQuestionClick, }) => {
|
|
|
21478
21566
|
};
|
|
21479
21567
|
|
|
21480
21568
|
const ChatWindow = ({ messages, isLoading, isTyping, error, config, onSendMessage, onClose, onFeedback, }) => {
|
|
21569
|
+
console.log('[ChatWindow] Rendering ChatWindow component');
|
|
21481
21570
|
const appearance = config?.appearance;
|
|
21482
21571
|
const behavior = config?.behavior;
|
|
21483
21572
|
const size = appearance?.size || 'medium';
|
|
21573
|
+
console.log('[ChatWindow] Size:', size, 'Appearance:', !!appearance);
|
|
21574
|
+
// Determine current theme config
|
|
21575
|
+
const themePreference = appearance?.theme ?? 'light';
|
|
21576
|
+
const canUseDarkMode = appearance?.darkModeEnabled !== false;
|
|
21577
|
+
const prefersDark = typeof window !== 'undefined' && window.matchMedia('(prefers-color-scheme: dark)').matches;
|
|
21578
|
+
const isDarkMode = themePreference === 'auto'
|
|
21579
|
+
? (canUseDarkMode && prefersDark)
|
|
21580
|
+
: themePreference === 'dark' && canUseDarkMode;
|
|
21581
|
+
const themeConfig = (isDarkMode ? appearance?.darkMode : appearance?.lightMode) ?? (appearance?.lightMode || appearance?.darkMode);
|
|
21582
|
+
const headerTitle = themeConfig?.header?.title ?? appearance?.header?.title ?? appearance?.companyName ?? 'AI Assistant';
|
|
21583
|
+
const welcomeTitle = themeConfig?.chat?.welcomeTitle ?? 'Welcome!';
|
|
21584
|
+
const welcomeMessage = themeConfig?.chat?.welcomeMessage ?? appearance?.welcomeMessage ?? '👋 Hi there! How can I assist you today?';
|
|
21585
|
+
const inputPlaceholder = themeConfig?.footer?.inputPlaceholder ?? appearance?.placeholder ?? 'Ask me anything...';
|
|
21484
21586
|
// Track if suggested questions should be shown
|
|
21485
21587
|
const [showSuggestedQuestions, setShowSuggestedQuestions] = useState(true);
|
|
21486
21588
|
// Hide suggested questions after first user message
|
|
@@ -21499,9 +21601,240 @@ const ChatWindow = ({ messages, isLoading, isTyping, error, config, onSendMessag
|
|
|
21499
21601
|
setShowSuggestedQuestions(false);
|
|
21500
21602
|
onSendMessage(question);
|
|
21501
21603
|
};
|
|
21502
|
-
return (jsxs("div", { className: `ai-chat-window size-${size}`, role: "dialog", "aria-label": "Chat window", children: [jsxs("div", { className: "ai-chat-header", children: [jsxs("div", { className: "ai-chat-header-content", children: [appearance?.logo && (jsx("img", { src: appearance.logo, alt: "Logo", className: "ai-chat-logo" })), jsx("div", { className: "ai-chat-title", children:
|
|
21604
|
+
return (jsxs("div", { className: `ai-chat-window size-${size}`, role: "dialog", "aria-label": "Chat window", children: [jsxs("div", { className: "ai-chat-header", children: [jsxs("div", { className: "ai-chat-header-content", children: [appearance?.logo && (jsx("img", { src: appearance.logo, alt: "Logo", className: "ai-chat-logo" })), jsx("div", { className: "ai-chat-title", children: headerTitle })] }), jsx("button", { className: "ai-chat-close-button", onClick: onClose, "aria-label": "Close chat", children: jsxs("svg", { width: "20", height: "20", viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "2", strokeLinecap: "round", strokeLinejoin: "round", children: [jsx("line", { x1: "18", y1: "6", x2: "6", y2: "18" }), jsx("line", { x1: "6", y1: "6", x2: "18", y2: "18" })] }) })] }), error && (jsx("div", { className: "ai-chat-error", role: "alert", children: error })), maxMessages && userMessageCount >= maxMessages - 2 && !isLimitReached && (jsxs("div", { className: "ai-chat-warning", role: "alert", children: [maxMessages - userMessageCount, " message", maxMessages - userMessageCount !== 1 ? 's' : '', " remaining in this session"] })), isLimitReached && (jsxs("div", { className: "ai-chat-error", role: "alert", children: ["Message limit reached (", maxMessages, " messages per session). Please start a new conversation."] })), jsx(MessageList, { messages: messages, isTyping: isTyping, showTypingIndicator: behavior?.showTypingIndicator, showTimestamps: behavior?.showTimestamps, enableFeedback: behavior?.enableFeedback, showSources: behavior?.showSources, sourceDisplayMode: behavior?.sourceDisplayMode, welcomeTitle: welcomeTitle, welcomeMessage: welcomeMessage, onFeedback: onFeedback }), showSuggestedQuestions && behavior?.suggestedQuestions && behavior.suggestedQuestions.length > 0 && (jsx(SuggestedQuestions, { questions: behavior.suggestedQuestions, onQuestionClick: handleQuestionClick })), jsx(MessageInput, { onSend: onSendMessage, placeholder: isLimitReached ? 'Message limit reached' : inputPlaceholder, disabled: isLoading || isLimitReached, enableFileUpload: behavior?.enableFileUpload, separateFromChat: themeConfig?.footer?.separateFromChat })] }));
|
|
21503
21605
|
};
|
|
21504
21606
|
|
|
21607
|
+
/**
|
|
21608
|
+
* Convert shadow size to CSS box-shadow value
|
|
21609
|
+
*/
|
|
21610
|
+
function getShadowValue(size) {
|
|
21611
|
+
const shadows = {
|
|
21612
|
+
'none': 'none',
|
|
21613
|
+
'sm': '0 1px 2px 0 rgba(0, 0, 0, 0.05)',
|
|
21614
|
+
'md': '0 4px 6px -1px rgba(0, 0, 0, 0.1), 0 2px 4px -1px rgba(0, 0, 0, 0.06)',
|
|
21615
|
+
'lg': '0 10px 15px -3px rgba(0, 0, 0, 0.1), 0 4px 6px -2px rgba(0, 0, 0, 0.05)',
|
|
21616
|
+
'xl': '0 20px 25px -5px rgba(0, 0, 0, 0.1), 0 10px 10px -5px rgba(0, 0, 0, 0.04)',
|
|
21617
|
+
'2xl': '0 25px 50px -12px rgba(0, 0, 0, 0.25)',
|
|
21618
|
+
};
|
|
21619
|
+
return shadows[size] || shadows.none;
|
|
21620
|
+
}
|
|
21621
|
+
/**
|
|
21622
|
+
* Apply appearance configuration as CSS custom properties
|
|
21623
|
+
* This allows the widget to be fully customizable via the appearance config
|
|
21624
|
+
*
|
|
21625
|
+
* @param appearance - Widget appearance configuration
|
|
21626
|
+
* @param theme - Current theme ('light' or 'dark')
|
|
21627
|
+
*/
|
|
21628
|
+
function applyAppearanceStyles(appearance, theme = 'light') {
|
|
21629
|
+
const styles = {};
|
|
21630
|
+
// Global font family
|
|
21631
|
+
if (appearance.fontFamily) {
|
|
21632
|
+
styles.fontFamily = appearance.fontFamily;
|
|
21633
|
+
}
|
|
21634
|
+
// Select the correct theme configuration
|
|
21635
|
+
const themeConfig = theme === 'dark' ? appearance.darkMode : appearance.lightMode;
|
|
21636
|
+
// If theme config exists and has required properties, use it
|
|
21637
|
+
if (themeConfig && themeConfig.button) {
|
|
21638
|
+
// ========================================================================
|
|
21639
|
+
// BUTTON APPEARANCE
|
|
21640
|
+
// ========================================================================
|
|
21641
|
+
const btn = themeConfig.button;
|
|
21642
|
+
if (btn.color)
|
|
21643
|
+
styles['--button-color'] = btn.color;
|
|
21644
|
+
if (btn.opacity !== undefined)
|
|
21645
|
+
styles['--button-opacity'] = btn.opacity.toString();
|
|
21646
|
+
if (btn.size)
|
|
21647
|
+
styles['--button-size'] = `${btn.size}px`;
|
|
21648
|
+
if (btn.borderRadius !== undefined)
|
|
21649
|
+
styles['--button-border-radius'] = `${btn.borderRadius}px`;
|
|
21650
|
+
if (btn.borderWidth !== undefined)
|
|
21651
|
+
styles['--button-border-width'] = `${btn.borderWidth}px`;
|
|
21652
|
+
if (btn.borderColor)
|
|
21653
|
+
styles['--button-border-color'] = btn.borderColor;
|
|
21654
|
+
if (btn.borderOpacity !== undefined)
|
|
21655
|
+
styles['--button-border-opacity'] = btn.borderOpacity.toString();
|
|
21656
|
+
if (btn.backdropBlur !== undefined)
|
|
21657
|
+
styles['--button-backdrop-blur'] = `${btn.backdropBlur}px`;
|
|
21658
|
+
if (btn.shadow)
|
|
21659
|
+
styles['--button-shadow'] = getShadowValue(btn.shadow);
|
|
21660
|
+
// ========================================================================
|
|
21661
|
+
// CARD/WINDOW APPEARANCE
|
|
21662
|
+
// ========================================================================
|
|
21663
|
+
const card = themeConfig.card;
|
|
21664
|
+
if (card.backgroundColor)
|
|
21665
|
+
styles['--card-background'] = card.backgroundColor;
|
|
21666
|
+
if (card.opacity !== undefined)
|
|
21667
|
+
styles['--card-opacity'] = card.opacity.toString();
|
|
21668
|
+
if (card.borderRadius !== undefined)
|
|
21669
|
+
styles['--card-border-radius'] = `${card.borderRadius}px`;
|
|
21670
|
+
if (card.borderWidth !== undefined)
|
|
21671
|
+
styles['--card-border-width'] = `${card.borderWidth}px`;
|
|
21672
|
+
if (card.borderColor) {
|
|
21673
|
+
styles['--card-border-color'] = card.borderColor;
|
|
21674
|
+
// Create rgba border color with opacity for box-shadow
|
|
21675
|
+
if (card.borderOpacity !== undefined) {
|
|
21676
|
+
const opacity = card.borderOpacity;
|
|
21677
|
+
// Convert hex to rgba
|
|
21678
|
+
const hex = card.borderColor.replace('#', '');
|
|
21679
|
+
const r = parseInt(hex.substring(0, 2), 16);
|
|
21680
|
+
const g = parseInt(hex.substring(2, 4), 16);
|
|
21681
|
+
const b = parseInt(hex.substring(4, 6), 16);
|
|
21682
|
+
styles['--card-border-color-rgba'] = `rgba(${r}, ${g}, ${b}, ${opacity})`;
|
|
21683
|
+
}
|
|
21684
|
+
}
|
|
21685
|
+
if (card.borderOpacity !== undefined)
|
|
21686
|
+
styles['--card-border-opacity'] = card.borderOpacity.toString();
|
|
21687
|
+
if (card.backdropBlur !== undefined)
|
|
21688
|
+
styles['--card-backdrop-blur'] = `${card.backdropBlur}px`;
|
|
21689
|
+
if (card.shadow)
|
|
21690
|
+
styles['--card-shadow'] = getShadowValue(card.shadow);
|
|
21691
|
+
// ========================================================================
|
|
21692
|
+
// HEADER APPEARANCE
|
|
21693
|
+
// ========================================================================
|
|
21694
|
+
const header = themeConfig.header;
|
|
21695
|
+
if (header.backgroundColor)
|
|
21696
|
+
styles['--header-background'] = header.backgroundColor;
|
|
21697
|
+
if (header.opacity !== undefined)
|
|
21698
|
+
styles['--header-opacity'] = header.opacity.toString();
|
|
21699
|
+
if (header.textColor)
|
|
21700
|
+
styles['--header-text-color'] = header.textColor;
|
|
21701
|
+
if (header.borderBottomWidth !== undefined)
|
|
21702
|
+
styles['--header-border-bottom-width'] = `${header.borderBottomWidth}px`;
|
|
21703
|
+
if (header.borderBottomColor)
|
|
21704
|
+
styles['--header-border-bottom-color'] = header.borderBottomColor;
|
|
21705
|
+
if (header.borderBottomOpacity !== undefined)
|
|
21706
|
+
styles['--header-border-bottom-opacity'] = header.borderBottomOpacity.toString();
|
|
21707
|
+
// ========================================================================
|
|
21708
|
+
// CHAT APPEARANCE
|
|
21709
|
+
// ========================================================================
|
|
21710
|
+
const chat = themeConfig.chat;
|
|
21711
|
+
if (chat.backgroundColor)
|
|
21712
|
+
styles['--chat-background'] = chat.backgroundColor;
|
|
21713
|
+
if (chat.opacity !== undefined)
|
|
21714
|
+
styles['--chat-opacity'] = chat.opacity.toString();
|
|
21715
|
+
// Welcome message
|
|
21716
|
+
if (chat.welcomeColor)
|
|
21717
|
+
styles['--welcome-color'] = chat.welcomeColor;
|
|
21718
|
+
// Message bubbles
|
|
21719
|
+
if (chat.enableBubbles) {
|
|
21720
|
+
if (chat.bubbleUserColor)
|
|
21721
|
+
styles['--bubble-user-color'] = chat.bubbleUserColor;
|
|
21722
|
+
if (chat.bubbleUserOpacity !== undefined)
|
|
21723
|
+
styles['--bubble-user-opacity'] = chat.bubbleUserOpacity.toString();
|
|
21724
|
+
if (chat.bubbleAssistantColor)
|
|
21725
|
+
styles['--bubble-assistant-color'] = chat.bubbleAssistantColor;
|
|
21726
|
+
if (chat.bubbleAssistantOpacity !== undefined)
|
|
21727
|
+
styles['--bubble-assistant-opacity'] = chat.bubbleAssistantOpacity.toString();
|
|
21728
|
+
if (chat.bubbleBorderWidth !== undefined)
|
|
21729
|
+
styles['--bubble-border-width'] = `${chat.bubbleBorderWidth}px`;
|
|
21730
|
+
if (chat.bubbleBorderColor)
|
|
21731
|
+
styles['--bubble-border-color'] = chat.bubbleBorderColor;
|
|
21732
|
+
if (chat.bubbleBorderOpacity !== undefined)
|
|
21733
|
+
styles['--bubble-border-opacity'] = chat.bubbleBorderOpacity.toString();
|
|
21734
|
+
}
|
|
21735
|
+
else {
|
|
21736
|
+
// Plain text mode
|
|
21737
|
+
if (chat.textColor)
|
|
21738
|
+
styles['--message-text-color'] = chat.textColor;
|
|
21739
|
+
}
|
|
21740
|
+
// ========================================================================
|
|
21741
|
+
// FOOTER APPEARANCE
|
|
21742
|
+
// ========================================================================
|
|
21743
|
+
const footer = themeConfig.footer;
|
|
21744
|
+
// Only if separate from chat
|
|
21745
|
+
if (footer.separateFromChat) {
|
|
21746
|
+
if (footer.backgroundColor)
|
|
21747
|
+
styles['--footer-background'] = footer.backgroundColor;
|
|
21748
|
+
if (footer.opacity !== undefined)
|
|
21749
|
+
styles['--footer-opacity'] = footer.opacity.toString();
|
|
21750
|
+
if (footer.borderTopWidth !== undefined)
|
|
21751
|
+
styles['--footer-border-top-width'] = `${footer.borderTopWidth}px`;
|
|
21752
|
+
if (footer.borderTopColor)
|
|
21753
|
+
styles['--footer-border-top-color'] = footer.borderTopColor;
|
|
21754
|
+
if (footer.borderTopOpacity !== undefined)
|
|
21755
|
+
styles['--footer-border-top-opacity'] = footer.borderTopOpacity.toString();
|
|
21756
|
+
}
|
|
21757
|
+
// Backdrop blur (only when floating)
|
|
21758
|
+
if (!footer.separateFromChat && footer.backdropBlur !== undefined) {
|
|
21759
|
+
styles['--footer-backdrop-blur'] = `${footer.backdropBlur}px`;
|
|
21760
|
+
}
|
|
21761
|
+
// Input field
|
|
21762
|
+
if (footer.inputBackgroundColor)
|
|
21763
|
+
styles['--input-background'] = footer.inputBackgroundColor;
|
|
21764
|
+
if (footer.inputBackgroundOpacity !== undefined)
|
|
21765
|
+
styles['--input-background-opacity'] = footer.inputBackgroundOpacity.toString();
|
|
21766
|
+
if (footer.inputBorderRadius !== undefined)
|
|
21767
|
+
styles['--input-border-radius'] = `${footer.inputBorderRadius}px`;
|
|
21768
|
+
if (footer.inputBorderWidth !== undefined)
|
|
21769
|
+
styles['--input-border-width'] = `${footer.inputBorderWidth}px`;
|
|
21770
|
+
if (footer.inputBorderColor)
|
|
21771
|
+
styles['--input-border-color'] = footer.inputBorderColor;
|
|
21772
|
+
if (footer.inputBorderOpacity !== undefined)
|
|
21773
|
+
styles['--input-border-opacity'] = footer.inputBorderOpacity.toString();
|
|
21774
|
+
if (footer.inputShadow)
|
|
21775
|
+
styles['--input-shadow'] = getShadowValue(footer.inputShadow);
|
|
21776
|
+
// Send button
|
|
21777
|
+
if (footer.buttonBackgroundColor)
|
|
21778
|
+
styles['--send-button-background'] = footer.buttonBackgroundColor;
|
|
21779
|
+
if (footer.buttonOpacity !== undefined)
|
|
21780
|
+
styles['--send-button-opacity'] = footer.buttonOpacity.toString();
|
|
21781
|
+
if (footer.buttonBorderRadius !== undefined)
|
|
21782
|
+
styles['--send-button-border-radius'] = `${footer.buttonBorderRadius}px`;
|
|
21783
|
+
if (footer.buttonBorderWidth !== undefined)
|
|
21784
|
+
styles['--send-button-border-width'] = `${footer.buttonBorderWidth}px`;
|
|
21785
|
+
if (footer.buttonBorderColor)
|
|
21786
|
+
styles['--send-button-border-color'] = footer.buttonBorderColor;
|
|
21787
|
+
if (footer.buttonBorderOpacity !== undefined)
|
|
21788
|
+
styles['--send-button-border-opacity'] = footer.buttonBorderOpacity.toString();
|
|
21789
|
+
// ========================================================================
|
|
21790
|
+
// HOVER STATES
|
|
21791
|
+
// ========================================================================
|
|
21792
|
+
const hover = themeConfig.hover;
|
|
21793
|
+
if (hover.buttonScale !== undefined)
|
|
21794
|
+
styles['--hover-button-scale'] = hover.buttonScale.toString();
|
|
21795
|
+
if (hover.buttonOpacity !== undefined)
|
|
21796
|
+
styles['--hover-button-opacity'] = hover.buttonOpacity.toString();
|
|
21797
|
+
if (hover.inputBorderColor)
|
|
21798
|
+
styles['--hover-input-border-color'] = hover.inputBorderColor;
|
|
21799
|
+
if (hover.sendButtonOpacity !== undefined)
|
|
21800
|
+
styles['--hover-send-button-opacity'] = hover.sendButtonOpacity.toString();
|
|
21801
|
+
if (hover.closeButtonOpacity !== undefined)
|
|
21802
|
+
styles['--hover-close-button-opacity'] = hover.closeButtonOpacity.toString();
|
|
21803
|
+
// ========================================================================
|
|
21804
|
+
// ACTIVE STATES
|
|
21805
|
+
// ========================================================================
|
|
21806
|
+
const active = themeConfig.active;
|
|
21807
|
+
if (active.inputBorderColor)
|
|
21808
|
+
styles['--active-input-border-color'] = active.inputBorderColor;
|
|
21809
|
+
if (active.inputShadow)
|
|
21810
|
+
styles['--active-input-shadow'] = active.inputShadow;
|
|
21811
|
+
}
|
|
21812
|
+
else {
|
|
21813
|
+
// Fallback to legacy fields if no theme config
|
|
21814
|
+
if (appearance.primaryColor)
|
|
21815
|
+
styles['--primary-color'] = appearance.primaryColor;
|
|
21816
|
+
if (appearance.borderRadius !== undefined)
|
|
21817
|
+
styles['--border-radius'] = `${appearance.borderRadius}px`;
|
|
21818
|
+
// Legacy button
|
|
21819
|
+
if (appearance.button) {
|
|
21820
|
+
const btn = appearance.button;
|
|
21821
|
+
if (btn.color)
|
|
21822
|
+
styles['--button-color'] = btn.color;
|
|
21823
|
+
if (btn.size)
|
|
21824
|
+
styles['--button-size'] = `${btn.size}px`;
|
|
21825
|
+
if (btn.borderRadius !== undefined)
|
|
21826
|
+
styles['--button-border-radius'] = `${btn.borderRadius}px`;
|
|
21827
|
+
if (btn.borderWidth !== undefined)
|
|
21828
|
+
styles['--button-border-width'] = `${btn.borderWidth}px`;
|
|
21829
|
+
if (btn.borderColor)
|
|
21830
|
+
styles['--button-border-color'] = btn.borderColor;
|
|
21831
|
+
if (btn.opacity !== undefined)
|
|
21832
|
+
styles['--button-opacity'] = btn.opacity.toString();
|
|
21833
|
+
}
|
|
21834
|
+
}
|
|
21835
|
+
return styles;
|
|
21836
|
+
}
|
|
21837
|
+
|
|
21505
21838
|
function styleInject(css, ref) {
|
|
21506
21839
|
if ( ref === void 0 ) ref = {};
|
|
21507
21840
|
var insertAt = ref.insertAt;
|
|
@@ -21529,11 +21862,12 @@ function styleInject(css, ref) {
|
|
|
21529
21862
|
}
|
|
21530
21863
|
}
|
|
21531
21864
|
|
|
21532
|
-
var css_248z = ".ai-chat-widget{--primary-color:#7c3aed;--background-color:#fff;--text-color:#1f2937;--border-color:#e5e7eb;--user-message-bg:var(--primary-color);--user-message-text:#fff;--assistant-message-bg:#f3f4f6;--assistant-message-text:#1f2937;--input-bg:#fff;--input-border:#d1d5db;--shadow:0 4px 6px -1px rgba(0,0,0,.1),0 2px 4px -1px rgba(0,0,0,.06);--shadow-lg:0 10px 15px -3px rgba(0,0,0,.1),0 4px 6px -2px rgba(0,0,0,.05);-webkit-font-smoothing:antialiased;-moz-osx-font-smoothing:grayscale;font-family:-apple-system,BlinkMacSystemFont,Segoe UI,Roboto,Oxygen,Ubuntu,Cantarell,Fira Sans,Droid Sans,Helvetica Neue,sans-serif}.ai-chat-widget.dark{--background-color:#1f2937;--text-color:#f9fafb;--border-color:#374151;--assistant-message-bg:#374151;--assistant-message-text:#f9fafb;--input-bg:#374151;--input-border:#4b5563}.ai-chat-widget.dark .ai-chat-message.system .ai-chat-message-content{background-color:#78350f;color:#fef3c7}.ai-chat-widget.dark .ai-chat-message.tool .ai-chat-message-content{background-color:#1e3a8a;color:#dbeafe}.ai-chat-widget-container{font-size:14px;line-height:1.5;position:fixed;z-index:9999}.ai-chat-widget-container.bottom-right{bottom:20px;right:20px}.ai-chat-widget-container.bottom-left{bottom:20px;left:20px}.ai-chat-widget-container.top-right{right:20px;top:20px}.ai-chat-widget-container.top-left{left:20px;top:20px}.ai-chat-button{align-items:center;background-color:var(--primary-color);border:none;border-radius:50%;box-shadow:var(--shadow-lg);color:#fff;cursor:pointer;display:flex;font-size:24px;height:60px;justify-content:center;transition:transform .2s,box-shadow .2s;width:60px}.ai-chat-button:hover{box-shadow:0 20px 25px -5px rgba(0,0,0,.1),0 10px 10px -5px rgba(0,0,0,.04);transform:scale(1.05)}.ai-chat-button:active{transform:scale(.95)}.ai-chat-button-svg{height:50%;min-height:24px;min-width:24px;width:50%}.ai-chat-button-icon{font-size:1.5em;line-height:1}.ai-chat-window{background-color:var(--background-color);border-radius:12px;box-shadow:var(--shadow-lg);display:flex;flex-direction:column;overflow:hidden;transition:opacity .2s,transform .2s}.ai-chat-window.size-small{height:400px;width:300px}.ai-chat-window.size-medium{height:600px;width:400px}.ai-chat-window.size-large{height:700px;width:500px}.ai-chat-header{align-items:center;background-color:var(--primary-color);color:#fff;display:flex;justify-content:space-between;padding:16px}.ai-chat-header-content{align-items:center;display:flex;flex:1;gap:12px}.ai-chat-logo{border-radius:50%;height:32px;object-fit:cover;width:32px}.ai-chat-title{font-size:16px;font-weight:600}.ai-chat-close-button{align-items:center;background:none;border:none;border-radius:4px;color:#fff;cursor:pointer;display:flex;justify-content:center;padding:4px;transition:background-color .2s}.ai-chat-close-button:hover{background-color:hsla(0,0%,100%,.1)}.ai-chat-messages{background-color:var(--background-color);display:flex;flex:1;flex-direction:column;gap:12px;overflow-y:auto;padding:16px}.ai-chat-messages::-webkit-scrollbar{width:6px}.ai-chat-messages::-webkit-scrollbar-track{background:transparent}.ai-chat-messages::-webkit-scrollbar-thumb{background:var(--border-color);border-radius:3px}.ai-chat-messages::-webkit-scrollbar-thumb:hover{background:var(--input-border)}.ai-chat-message{animation:slideIn .2s ease-out;display:flex;flex-direction:column;gap:4px}@keyframes slideIn{0%{opacity:0;transform:translateY(10px)}to{opacity:1;transform:translateY(0)}}.ai-chat-message.user{align-items:flex-end}.ai-chat-message.assistant{align-items:flex-start}.ai-chat-message.system{align-items:center}.ai-chat-message.tool{align-items:flex-start}.ai-chat-message-content{word-wrap:break-word;border-radius:12px;line-height:1.5;max-width:80%;padding:10px 14px}.ai-chat-message.user .ai-chat-message-content{background-color:var(--user-message-bg);border-bottom-right-radius:4px;color:var(--user-message-text)}.ai-chat-message.assistant .ai-chat-message-content{background-color:var(--assistant-message-bg);border-bottom-left-radius:4px;color:var(--assistant-message-text)}.ai-chat-message.system .ai-chat-message-content{background-color:#fef3c7;border-radius:8px;color:#92400e;font-size:12px;font-style:italic;max-width:90%;text-align:center}.ai-chat-message.tool .ai-chat-message-content{background-color:#dbeafe;border-bottom-left-radius:4px;color:#1e40af;font-family:Courier New,monospace;font-size:13px}.ai-chat-tool-indicators{display:flex;gap:6px;margin-top:6px}.tool-indicator{align-items:center;background:#dbeafe;border-radius:50%;color:#1e40af;display:inline-flex;height:18px;justify-content:center;overflow:hidden;position:relative;width:18px}.tool-indicator .icon{font-size:12px;line-height:1;z-index:1}.tool-indicator.started:after{animation:ai-spin 1s linear infinite;border:2px solid rgba(30,64,175,.25);border-radius:50%;border-top-color:#1e40af;content:\"\";inset:0;position:absolute}@keyframes ai-spin{to{transform:rotate(1turn)}}.ai-chat-tool-message{background:linear-gradient(135deg,#ecfdf5,#d1fae5);border:1px solid #a7f3d0;border-radius:9999px;box-shadow:0 1px 2px rgba(0,0,0,.04),0 1px 8px rgba(16,185,129,.08);color:#065f46;gap:10px;padding:6px 12px}.ai-chat-tool-message,.tool-finished{align-items:center;display:inline-flex}.tool-finished{background:rgba(16,185,129,.12);border-radius:50%;color:#059669;height:22px;justify-content:center;position:relative;width:22px}.tool-finished .tool-icon{font-size:14px}.tool-finished .tool-check{align-items:center;background:#10b981;border-radius:50%;bottom:-3px;box-shadow:0 1px 2px rgba(0,0,0,.12);color:#fff;display:inline-flex;font-size:10px;height:14px;justify-content:center;position:absolute;right:-3px;width:14px}.tool-name{font-size:12px;font-weight:600}.ai-chat-message-timestamp{color:#9ca3af;font-size:11px;padding:0 4px}.ai-chat-welcome{color:var(--text-color);padding:32px 16px;text-align:center}.ai-chat-welcome-title{font-size:18px;font-weight:600;margin-bottom:8px}.ai-chat-welcome-text{color:#6b7280;font-size:14px}.ai-chat-typing{align-items:center;background-color:var(--assistant-message-bg);border-radius:12px;border-bottom-left-radius:4px;display:flex;gap:4px;max-width:80px;padding:10px 14px}.ai-chat-typing-dot{animation:typingBounce 1.4s infinite;background-color:#9ca3af;border-radius:50%;height:8px;width:8px}.ai-chat-typing-dot:nth-child(2){animation-delay:.2s}.ai-chat-typing-dot:nth-child(3){animation-delay:.4s}@keyframes typingBounce{0%,60%,to{transform:translateY(0)}30%{transform:translateY(-8px)}}.ai-chat-input-container{background-color:var(--background-color);border-top:1px solid var(--border-color);padding:16px}.ai-chat-input-wrapper{align-items:flex-end;display:flex;gap:8px}.ai-chat-input{background-color:var(--input-bg);border:1px solid var(--input-border);border-radius:8px;color:var(--text-color);flex:1;font-family:inherit;font-size:14px;max-height:120px;min-height:40px;outline:none;padding:10px 12px;resize:none;transition:border-color .2s}.ai-chat-input:focus{border-color:var(--primary-color)}.ai-chat-input::placeholder{color:#9ca3af}.ai-chat-send-button{align-items:center;background-color:var(--primary-color);border:none;border-radius:8px;color:#fff;cursor:pointer;display:flex;font-weight:500;height:40px;justify-content:center;min-width:40px;padding:10px 16px;transition:opacity .2s,transform .1s}.ai-chat-send-button:hover:not(:disabled){opacity:.9}.ai-chat-send-button:active:not(:disabled){transform:scale(.95)}.ai-chat-send-button:disabled{cursor:not-allowed;opacity:.5}.ai-chat-file-button{align-items:center;background:none;border:none;border-radius:6px;color:var(--text-color);cursor:pointer;display:flex;justify-content:center;padding:8px;transition:background-color .2s}.ai-chat-file-button:hover:not(:disabled){background-color:rgba(0,0,0,.05)}.ai-chat-file-button:disabled{cursor:not-allowed;opacity:.5}.ai-chat-file-list{display:flex;flex-wrap:wrap;gap:8px;padding:8px 12px}.ai-chat-file-item{align-items:center;background-color:rgba(0,0,0,.05);border-radius:6px;display:flex;font-size:12px;gap:8px;padding:6px 10px}.ai-chat-file-extension{background-color:var(--primary-color);border-radius:3px;color:#fff;display:inline-block;font-size:10px;font-weight:600;min-width:40px;padding:2px 6px;text-align:center;text-transform:uppercase}.ai-chat-file-info{display:flex;flex:1;flex-direction:column;gap:2px;min-width:0}.ai-chat-file-name{font-weight:500;max-width:150px;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}.ai-chat-file-size{color:var(--text-muted);font-size:10px;opacity:.7}.ai-chat-file-remove{background:none;border:none;cursor:pointer;font-size:18px;line-height:1;opacity:.6;padding:0 4px;transition:opacity .2s}.ai-chat-file-remove:hover{opacity:1}.ai-chat-message-attachments{display:flex;flex-wrap:wrap;gap:6px;margin-top:6px}.ai-chat-message-attachment{align-items:center;background-color:rgba(0,0,0,.08);border-radius:4px;display:inline-flex;font-size:11px;gap:4px;padding:3px 8px}.ai-chat-attachment-icon{font-size:12px}.ai-chat-attachment-ext{background-color:var(--primary-color);border-radius:2px;color:#fff;display:inline-block;font-size:9px;font-weight:600;padding:1px 4px;text-transform:uppercase}.ai-chat-attachment-name{max-width:120px;opacity:.8;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}.ai-chat-sources{background-color:rgba(0,0,0,.02);border-radius:6px;font-size:12px;margin-top:8px;overflow:hidden}.ai-chat-sources-toggle{align-items:center;background:none;border:none;cursor:pointer;display:flex;gap:6px;padding:8px 10px;text-align:left;transition:background-color .2s;width:100%}.ai-chat-sources-toggle:hover{background-color:rgba(0,0,0,.03)}.ai-chat-sources-icon{color:var(--text-muted);font-size:10px;transition:transform .2s}.ai-chat-sources-title{color:var(--text-color);flex:1;font-size:11px;font-weight:600;letter-spacing:.5px;text-transform:uppercase}.ai-chat-source-item{border-top:1px solid rgba(0,0,0,.05);color:#6b7280;display:flex;gap:8px;padding:8px 10px}.ai-chat-source-item:last-child{border-bottom:none}.ai-chat-source-number{color:var(--primary-color);flex-shrink:0;font-weight:600}.ai-chat-source-details{display:flex;flex:1;flex-direction:column;gap:4px}.ai-chat-source-score{color:#9ca3af;font-size:11px}.ai-chat-source-content{color:#6b7280;font-size:11px;font-style:italic;line-height:1.4}.ai-chat-source-metadata{display:flex;flex-wrap:wrap;gap:6px;margin-top:2px}.ai-chat-source-meta-item{background-color:rgba(0,0,0,.05);border-radius:3px;color:#6b7280;font-size:10px;padding:2px 6px}.ai-chat-feedback{align-items:center;display:flex;gap:8px;margin-top:8px;min-height:32px}.ai-chat-feedback-button{align-items:center;background:none;border:none;border-radius:6px;cursor:pointer;display:flex;font-size:16px;gap:4px;overflow:hidden;padding:6px 10px;position:relative;transition:all .2s ease}.ai-chat-feedback-button:hover:not(:disabled){background-color:rgba(0,0,0,.05);transform:scale(1.2)}.ai-chat-feedback-button:active:not(:disabled){transform:scale(.95)}.ai-chat-feedback-button:disabled{cursor:not-allowed;opacity:.5}.ai-chat-feedback-button.active{background-color:rgba(124,58,237,.1)}.ai-chat-feedback-submitted{align-items:center;animation:feedbackMorph .3s cubic-bezier(.34,1.56,.64,1);display:flex;gap:6px}.ai-chat-feedback-checkmark{animation:checkmarkPop .3s cubic-bezier(.34,1.56,.64,1);color:#10b981;font-size:16px;font-weight:700}.ai-chat-feedback-text{animation:textSlideIn .3s ease;color:#10b981;font-size:13px;font-weight:500}@keyframes feedbackMorph{0%{opacity:.5;transform:scale(.8)}to{opacity:1;transform:scale(1)}}@keyframes checkmarkPop{0%{opacity:0;transform:scale(0) rotate(-45deg)}50%{transform:scale(1.3) rotate(0deg)}to{opacity:1;transform:scale(1) rotate(0deg)}}@keyframes textSlideIn{0%{opacity:0;transform:translateX(-10px)}to{opacity:1;transform:translateX(0)}}.ai-chat-error{align-items:flex-start;background-color:#fee2e2;border-left:4px solid #dc2626;border-radius:8px;color:#991b1b;display:flex;font-size:14px;font-weight:500;gap:8px;line-height:1.5;margin:8px 16px;padding:12px 16px}.ai-chat-error:before{content:\"⚠️\";flex-shrink:0;font-size:16px}.ai-chat-warning{background-color:#fef3c7;border-radius:8px;color:#92400e;font-size:13px;margin:8px 16px;padding:12px}.ai-chat-suggested-questions{margin-bottom:8px;padding:12px 16px}.ai-chat-suggested-questions-label{color:#6b7280;font-size:12px;font-weight:500;margin-bottom:8px}.ai-chat-suggested-questions-list{display:flex;flex-direction:column;gap:8px}.ai-chat-suggested-question{align-items:center;background-color:#f9fafb;border:1px solid #e5e7eb;border-radius:8px;color:#374151;cursor:pointer;display:flex;font-size:14px;gap:8px;padding:10px 12px;text-align:left;transition:all .2s ease;width:100%}.ai-chat-suggested-question:hover{background-color:#f3f4f6;border-color:var(--ai-chat-primary-color,#6366f1);box-shadow:0 2px 4px rgba(0,0,0,.05);transform:translateY(-1px)}.ai-chat-suggested-question:active{transform:translateY(0)}.ai-chat-suggested-question-icon{flex-shrink:0;font-size:16px}.ai-chat-suggested-question-text{flex:1;line-height:1.4}@media (max-width:480px){.ai-chat-window{border-radius:0!important;bottom:0!important;height:100%!important;left:0!important;position:fixed!important;right:0!important;top:0!important;width:100%!important}.ai-chat-widget-container{bottom:20px!important;right:20px!important}.ai-chat-suggested-question{font-size:13px;padding:9px 10px}}.ai-chat-action-approval{background:linear-gradient(135deg,#667eea,#764ba2);border-radius:12px;box-shadow:0 4px 12px rgba(102,126,234,.3);color:#fff;margin:16px;padding:16px}.ai-chat-action-approval-content{align-items:flex-start;display:flex;gap:12px;margin-bottom:16px}.ai-chat-action-approval-icon{align-items:center;background:hsla(0,0%,100%,.2);border-radius:8px;display:flex;flex-shrink:0;height:40px;justify-content:center;width:40px}.ai-chat-action-approval-text{flex:1}.ai-chat-action-approval-title{font-size:15px;font-weight:600;margin-bottom:4px}.ai-chat-action-approval-description{font-size:13px;line-height:1.4;opacity:.95}.ai-chat-action-approval-buttons{display:flex;gap:8px;justify-content:flex-end}.ai-chat-action-button{align-items:center;border:none;border-radius:8px;cursor:pointer;display:flex;font-family:inherit;font-size:14px;font-weight:500;gap:6px;padding:8px 16px;transition:all .2s ease}.ai-chat-action-button:disabled{cursor:not-allowed;opacity:.6}.ai-chat-action-button-reject{background:hsla(0,0%,100%,.2);color:#fff}.ai-chat-action-button-reject:hover:not(:disabled){background:hsla(0,0%,100%,.3)}.ai-chat-action-button-approve{background:#fff;color:#667eea}.ai-chat-action-button-approve:hover:not(:disabled){background:#f0f0f0;box-shadow:0 2px 8px rgba(0,0,0,.15);transform:translateY(-1px)}.ai-chat-action-spinner{animation:ai-chat-spin .6s linear infinite;border:2px solid rgba(102,126,234,.3);border-radius:50%;border-top-color:#667eea;display:inline-block;height:14px;width:14px}@keyframes ai-chat-spin{to{transform:rotate(1turn)}}";
|
|
21865
|
+
var css_248z = ".ai-chat-widget{--primary-color:#07f;--background-color:#fff;--text-color:#1f2937;--border-color:#e5e7eb;--user-message-bg:var(--primary-color);--user-message-text:#fff;--assistant-message-bg:#f3f4f6;--assistant-message-text:#374151;--input-bg:#fff;--input-border:#d1d5db;--shadow:0 4px 6px -1px rgba(0,0,0,.1),0 2px 4px -1px rgba(0,0,0,.06);--shadow-lg:0 10px 15px -3px rgba(0,0,0,.1),0 4px 6px -2px rgba(0,0,0,.05);--button-color:#07f;--button-size:56px;--button-border-radius:28px;--button-border-width:0px;--button-border-color:#07f;--button-opacity:1;--button-backdrop-blur:0px;--button-shadow:0 10px 15px -3px rgba(0,0,0,.1),0 4px 6px -2px rgba(0,0,0,.05);--card-background:#fff;--card-border-radius:16px;--card-border-width:0px;--card-border-color:#e5e7eb;--card-opacity:1;--card-backdrop-blur:0px;--card-shadow:0 25px 50px -12px rgba(0,0,0,.25);--header-background:#07f;--header-text-color:#fff;--header-font-size:18px;--header-border-bottom-width:0px;--header-border-bottom-color:#e5e7eb;--header-opacity:1;--header-backdrop-blur:0px;--chat-background:#fff;--chat-opacity:1;--chat-backdrop-blur:0px;--welcome-font-size:16px;--welcome-color:#1f2937;--welcome-opacity:1;--bubble-user-color:#07f;--bubble-assistant-color:#f3f4f6;--bubble-border-radius:16px;--bubble-border-width:0px;--bubble-border-color:#e5e7eb;--bubble-opacity:1;--typing-animation-color:#f3f4f6;--typing-animation-opacity:1;--typing-animation-border-width:0px;--typing-animation-border-color:#e5e7eb;--typing-animation-border-radius:16px;--footer-background:#fff;--footer-border-top-width:1px;--footer-border-top-color:#e5e7eb;--footer-opacity:1;--footer-backdrop-blur:0px;--input-background:#fff;--input-border-radius:24px;--input-border-width:1.5px;--input-border-color:#d1d5db;--input-opacity:1;--input-shadow:0 1px 2px 0 rgba(0,0,0,.05);--send-button-background:#07f;--send-button-border-radius:20px;--send-button-border-width:0px;--send-button-border-color:#07f;--send-button-opacity:1;--hover-button-scale:1.05;--hover-button-opacity:0.9;--hover-input-border-color:#9ca3af;--hover-send-button-opacity:0.85;--hover-close-button-opacity:1;--active-input-border-color:#07f;--active-input-shadow:0 0 0 3px rgba(0,119,255,.1);-webkit-font-smoothing:antialiased;-moz-osx-font-smoothing:grayscale;font-family:-apple-system,BlinkMacSystemFont,Segoe UI,Roboto,Oxygen,Ubuntu,Cantarell,Fira Sans,Droid Sans,Helvetica Neue,sans-serif}.ai-chat-widget.dark{--background-color:#001d3d;--text-color:#f9fafb;--border-color:#374151;--assistant-message-bg:#036;--assistant-message-text:#e5e7eb;--input-bg:#002855;--input-border:#374151}.ai-chat-widget.dark .ai-chat-message.system .ai-chat-message-content{background-color:#78350f;color:#fef3c7}.ai-chat-widget.dark .ai-chat-message.tool .ai-chat-message-content{background-color:#1e3a8a;color:#dbeafe}.ai-chat-widget-container{font-size:14px;line-height:1.5;position:fixed;z-index:9999}.ai-chat-widget-container.bottom-right{bottom:20px;right:20px}.ai-chat-widget-container.bottom-left{bottom:20px;left:20px}.ai-chat-widget-container.top-right{right:20px;top:20px}.ai-chat-widget-container.top-left{left:20px;top:20px}.ai-chat-button{align-items:center;backdrop-filter:blur(var(--button-backdrop-blur));-webkit-backdrop-filter:blur(var(--button-backdrop-blur));background-color:var(--button-color);border:var(--button-border-width) solid var(--button-border-color);border-radius:var(--button-border-radius);box-shadow:var(--button-shadow);color:#fff;cursor:pointer;display:flex;height:var(--button-size);justify-content:center;opacity:var(--button-opacity);transition:all .3s cubic-bezier(.4,0,.2,1);width:var(--button-size)}.ai-chat-button:hover{box-shadow:0 20px 25px -5px rgba(0,0,0,.1),0 10px 10px -5px rgba(0,0,0,.04);opacity:var(--hover-button-opacity);transform:scale(var(--hover-button-scale))}.ai-chat-button:active{transform:scale(.95)}.ai-chat-button-svg{height:50%;min-height:24px;min-width:24px;width:50%}.ai-chat-button-icon{font-size:1.5em;line-height:1}.ai-chat-window{border-radius:var(--card-border-radius);box-shadow:0 0 0 var(--card-border-width) var(--card-border-color-rgba,var(--card-border-color)),var(--card-shadow);display:flex;flex-direction:column;overflow:hidden;position:absolute}.ai-chat-window>*{position:relative;z-index:1}.ai-chat-window:before{backdrop-filter:blur(var(--card-backdrop-blur));-webkit-backdrop-filter:blur(var(--card-backdrop-blur));background-color:var(--card-background);border-radius:var(--card-border-radius);content:\"\";inset:0;opacity:var(--card-opacity);pointer-events:none;position:absolute;z-index:0}.ai-chat-widget-container.bottom-right .ai-chat-window{bottom:0;right:0}.ai-chat-widget-container.bottom-left .ai-chat-window{bottom:0;left:0}.ai-chat-widget-container.top-right .ai-chat-window{right:0;top:0}.ai-chat-widget-container.top-left .ai-chat-window{left:0;top:0}.ai-chat-window.size-small{height:500px;width:380px}.ai-chat-window.size-medium{height:650px;width:440px}.ai-chat-window.size-large{height:750px;width:520px}.ai-chat-header{align-items:center;border-bottom:var(--header-border-bottom-width) solid var(--header-border-bottom-color);box-shadow:0 2px 8px rgba(0,0,0,.1);color:var(--header-text-color);display:flex;justify-content:space-between;padding:20px;position:relative}.ai-chat-header:before{backdrop-filter:blur(var(--header-backdrop-blur));-webkit-backdrop-filter:blur(var(--header-backdrop-blur));background-color:var(--header-background);content:\"\";inset:0;opacity:var(--header-opacity);pointer-events:none;position:absolute;z-index:0}.ai-chat-header>*{position:relative;z-index:1}.ai-chat-header-content{align-items:center;display:flex;flex:1;gap:12px}.ai-chat-logo{border-radius:50%;height:32px;object-fit:cover;width:32px}.ai-chat-title{color:var(--header-text-color);font-size:var(--header-font-size);font-weight:600;letter-spacing:-.01em}.ai-chat-close-button{align-items:center;background:none;border:none;border-radius:8px;color:var(--header-text-color);cursor:pointer;display:flex;justify-content:center;opacity:.9;padding:8px;transition:all .2s ease}.ai-chat-close-button:hover{background-color:hsla(0,0%,100%,.15);opacity:var(--hover-close-button-opacity);transform:scale(1.05)}.ai-chat-messages{background-color:var(--chat-background);display:flex;flex:1;flex-direction:column;gap:16px;overflow-x:hidden;overflow-y:auto;padding:20px;position:relative}.ai-chat-window:has(.ai-chat-input-container.integrated) .ai-chat-messages{padding-bottom:100px}.ai-chat-messages:before{backdrop-filter:blur(var(--chat-backdrop-blur));-webkit-backdrop-filter:blur(var(--chat-backdrop-blur));background-color:var(--chat-background);bottom:0;content:\"\";left:0;opacity:var(--chat-opacity);pointer-events:none;position:absolute;right:0;top:0;z-index:0}.ai-chat-messages>*{position:relative;z-index:1}.ai-chat-messages::-webkit-scrollbar{width:6px}.ai-chat-messages::-webkit-scrollbar-track{background:transparent}.ai-chat-messages::-webkit-scrollbar-thumb{background:var(--border-color);border-radius:3px}.ai-chat-messages::-webkit-scrollbar-thumb:hover{background:var(--input-border)}.ai-chat-message{animation:slideIn .2s ease-out;display:flex;flex-direction:column;gap:4px}@keyframes slideIn{0%{opacity:0;transform:translateY(10px)}to{opacity:1;transform:translateY(0)}}.ai-chat-message.user{align-items:flex-end}.ai-chat-message.assistant{align-items:flex-start}.ai-chat-message.system{align-items:center}.ai-chat-message.tool{align-items:flex-start}.ai-chat-message-content{word-wrap:break-word;border:var(--bubble-border-width) solid var(--bubble-border-color);border-radius:var(--bubble-border-radius);font-size:15px;line-height:1.6;max-width:80%;opacity:var(--bubble-opacity);padding:12px 16px}.ai-chat-message.user .ai-chat-message-content{background-color:var(--bubble-user-color);border-bottom-right-radius:4px;box-shadow:0 1px 2px rgba(0,0,0,.1);color:var(--user-message-text)}.ai-chat-message.assistant .ai-chat-message-content{background-color:var(--bubble-assistant-color);border-bottom-left-radius:4px;box-shadow:0 1px 2px rgba(0,0,0,.05);color:var(--assistant-message-text)}.ai-chat-message.system .ai-chat-message-content{background-color:#fef3c7;border-radius:8px;color:#92400e;font-size:12px;font-style:italic;max-width:90%;text-align:center}.ai-chat-message.tool .ai-chat-message-content{background-color:#dbeafe;border-bottom-left-radius:4px;color:#1e40af;font-family:Courier New,monospace;font-size:13px}.ai-chat-tool-indicators{display:flex;gap:6px;margin-top:6px}.tool-indicator{align-items:center;background:#dbeafe;border-radius:50%;color:#1e40af;display:inline-flex;height:18px;justify-content:center;overflow:hidden;position:relative;width:18px}.tool-indicator .icon{font-size:12px;line-height:1;z-index:1}.tool-indicator.started:after{animation:ai-spin 1s linear infinite;border:2px solid rgba(30,64,175,.25);border-radius:50%;border-top-color:#1e40af;content:\"\";inset:0;position:absolute}@keyframes ai-spin{to{transform:rotate(1turn)}}.ai-chat-tool-message{background:linear-gradient(135deg,#ecfdf5,#d1fae5);border:1px solid #a7f3d0;border-radius:9999px;box-shadow:0 1px 2px rgba(0,0,0,.04),0 1px 8px rgba(16,185,129,.08);color:#065f46;gap:10px;padding:6px 12px}.ai-chat-tool-message,.tool-finished{align-items:center;display:inline-flex}.tool-finished{background:rgba(16,185,129,.12);border-radius:50%;color:#059669;height:22px;justify-content:center;position:relative;width:22px}.tool-finished .tool-icon{font-size:14px}.tool-finished .tool-check{align-items:center;background:#10b981;border-radius:50%;bottom:-3px;box-shadow:0 1px 2px rgba(0,0,0,.12);color:#fff;display:inline-flex;font-size:10px;height:14px;justify-content:center;position:absolute;right:-3px;width:14px}.tool-name{font-size:12px;font-weight:600}.ai-chat-message-timestamp{color:rgba(0,0,0,.6);filter:invert(1) grayscale(1) contrast(1.2);font-size:11px;mix-blend-mode:difference;padding:0 4px}.ai-chat-welcome{color:var(--welcome-color);opacity:var(--welcome-opacity);padding:48px 24px;text-align:center}.ai-chat-welcome-title{color:var(--welcome-color);font-size:calc(var(--welcome-font-size)*1.5);font-weight:700;letter-spacing:-.02em;margin-bottom:12px}.ai-chat-welcome-text{color:var(--welcome-color);font-size:var(--welcome-font-size);line-height:1.6}.ai-chat-typing{align-items:center;background-color:var(--assistant-message-bg);border-radius:12px;border-bottom-left-radius:4px;display:flex;gap:4px;max-width:80px;padding:10px 14px}.ai-chat-typing-dot{animation:typingBounce 1.4s infinite;background-color:#9ca3af;border-radius:50%;height:8px;width:8px}.ai-chat-typing-dot:nth-child(2){animation-delay:.2s}.ai-chat-typing-dot:nth-child(3){animation-delay:.4s}@keyframes typingBounce{0%,60%,to{transform:translateY(0)}30%{transform:translateY(-8px)}}.ai-chat-input-container{padding:20px;position:relative}.ai-chat-input-container.separate{border-top:var(--footer-border-top-width) solid var(--footer-border-top-color)}.ai-chat-input-container.integrated{bottom:0;left:0;padding-bottom:calc(20px + var(--card-border-width));position:absolute;right:0;z-index:10}.ai-chat-input-container.separate:before{backdrop-filter:blur(var(--footer-backdrop-blur));-webkit-backdrop-filter:blur(var(--footer-backdrop-blur));background-color:var(--footer-background);content:\"\";inset:0;opacity:var(--footer-opacity);pointer-events:none;position:absolute;z-index:0}.ai-chat-input-container>*{position:relative;z-index:1}.ai-chat-input-wrapper{align-items:center;background-color:var(--input-background);border:var(--input-border-width) solid var(--input-border-color);border-radius:var(--input-border-radius);display:flex;gap:0;opacity:var(--input-opacity);padding:6px 6px 6px 16px;transition:all .2s ease}.ai-chat-input-wrapper:hover{border-color:var(--hover-input-border-color)}.ai-chat-input-wrapper:focus-within{border-color:var(--active-input-border-color);box-shadow:var(--active-input-shadow)}.ai-chat-input{background-color:transparent;border:none;border-radius:0;color:var(--text-color);flex:1;font-family:inherit;font-size:15px;max-height:120px;min-height:40px;outline:none;padding:10px 0;resize:none}.ai-chat-input::placeholder{color:#9ca3af}.ai-chat-send-button{align-items:center;background-color:var(--send-button-background);border:var(--send-button-border-width) solid var(--send-button-border-color);border-radius:var(--send-button-border-radius);color:#fff;cursor:pointer;display:flex;flex-shrink:0;font-weight:500;height:40px;justify-content:center;min-width:40px;opacity:var(--send-button-opacity);padding:0;transition:all .2s ease;width:40px}.ai-chat-send-button:hover:not(:disabled){opacity:var(--hover-send-button-opacity);transform:scale(1.05)}.ai-chat-send-button:active:not(:disabled){transform:scale(.98)}.ai-chat-send-button:disabled{cursor:not-allowed;opacity:.5}.ai-chat-file-button{align-items:center;background:none;border:none;border-radius:6px;color:var(--text-color);cursor:pointer;display:flex;justify-content:center;padding:8px;transition:background-color .2s}.ai-chat-file-button:hover:not(:disabled){background-color:rgba(0,0,0,.05)}.ai-chat-file-button:disabled{cursor:not-allowed;opacity:.5}.ai-chat-file-list{display:flex;flex-wrap:wrap;gap:8px;padding:8px 12px}.ai-chat-file-item{align-items:center;background-color:rgba(0,0,0,.05);border-radius:6px;display:flex;font-size:12px;gap:8px;padding:6px 10px}.ai-chat-file-extension{background-color:var(--primary-color);border-radius:3px;color:#fff;display:inline-block;font-size:10px;font-weight:600;min-width:40px;padding:2px 6px;text-align:center;text-transform:uppercase}.ai-chat-file-info{display:flex;flex:1;flex-direction:column;gap:2px;min-width:0}.ai-chat-file-name{font-weight:500;max-width:150px;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}.ai-chat-file-size{color:var(--text-muted);font-size:10px;opacity:.7}.ai-chat-file-remove{background:none;border:none;cursor:pointer;font-size:18px;line-height:1;opacity:.6;padding:0 4px;transition:opacity .2s}.ai-chat-file-remove:hover{opacity:1}.ai-chat-message-attachments{display:flex;flex-wrap:wrap;gap:6px;margin-top:6px}.ai-chat-message-attachment{align-items:center;background-color:rgba(0,0,0,.08);border-radius:4px;display:inline-flex;font-size:11px;gap:4px;padding:3px 8px}.ai-chat-attachment-icon{font-size:12px}.ai-chat-attachment-ext{background-color:var(--primary-color);border-radius:2px;color:#fff;display:inline-block;font-size:9px;font-weight:600;padding:1px 4px;text-transform:uppercase}.ai-chat-attachment-name{max-width:120px;opacity:.8;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}.ai-chat-sources{background-color:rgba(0,0,0,.02);border-radius:6px;font-size:12px;margin-top:8px;overflow:hidden}.ai-chat-sources-toggle{align-items:center;background:none;border:none;cursor:pointer;display:flex;gap:6px;padding:8px 10px;text-align:left;transition:background-color .2s;width:100%}.ai-chat-sources-toggle:hover{background-color:rgba(0,0,0,.03)}.ai-chat-sources-icon{color:var(--text-muted);font-size:10px;transition:transform .2s}.ai-chat-sources-title{color:var(--text-color);flex:1;font-size:11px;font-weight:600;letter-spacing:.5px;text-transform:uppercase}.ai-chat-source-item{border-top:1px solid rgba(0,0,0,.05);color:#6b7280;display:flex;gap:8px;padding:8px 10px}.ai-chat-source-item:last-child{border-bottom:none}.ai-chat-source-number{color:var(--primary-color);flex-shrink:0;font-weight:600}.ai-chat-source-details{display:flex;flex:1;flex-direction:column;gap:4px}.ai-chat-source-score{color:#9ca3af;font-size:11px}.ai-chat-source-content{color:#6b7280;font-size:11px;font-style:italic;line-height:1.4}.ai-chat-source-metadata{display:flex;flex-wrap:wrap;gap:6px;margin-top:2px}.ai-chat-source-meta-item{background-color:rgba(0,0,0,.05);border-radius:3px;color:#6b7280;font-size:10px;padding:2px 6px}.ai-chat-feedback{align-items:center;display:flex;gap:8px;margin-top:8px;min-height:32px}.ai-chat-feedback-button{align-items:center;background:none;border:none;border-radius:6px;cursor:pointer;display:flex;filter:drop-shadow(0 1px 2px rgba(0,0,0,.3));font-size:16px;gap:4px;overflow:hidden;padding:6px 10px;position:relative;transition:all .2s ease}.ai-chat-feedback-button:hover:not(:disabled){background-color:rgba(0,0,0,.05);transform:scale(1.2)}.ai-chat-feedback-button:active:not(:disabled){transform:scale(.95)}.ai-chat-feedback-button:disabled{cursor:not-allowed;opacity:.5}.ai-chat-feedback-button.active{background-color:rgba(0,119,255,.1)}.ai-chat-feedback-submitted{align-items:center;animation:feedbackMorph .3s cubic-bezier(.34,1.56,.64,1);display:flex;gap:6px}.ai-chat-feedback-checkmark{animation:checkmarkPop .3s cubic-bezier(.34,1.56,.64,1);color:#10b981;font-size:16px;font-weight:700}.ai-chat-feedback-text{animation:textSlideIn .3s ease;color:#10b981;font-size:13px;font-weight:500}@keyframes feedbackMorph{0%{opacity:.5;transform:scale(.8)}to{opacity:1;transform:scale(1)}}@keyframes checkmarkPop{0%{opacity:0;transform:scale(0) rotate(-45deg)}50%{transform:scale(1.3) rotate(0deg)}to{opacity:1;transform:scale(1) rotate(0deg)}}@keyframes textSlideIn{0%{opacity:0;transform:translateX(-10px)}to{opacity:1;transform:translateX(0)}}.ai-chat-error{align-items:flex-start;background-color:#fee2e2;border-left:4px solid #dc2626;border-radius:8px;color:#991b1b;display:flex;font-size:14px;font-weight:500;gap:8px;line-height:1.5;margin:8px 16px;padding:12px 16px}.ai-chat-error:before{content:\"⚠️\";flex-shrink:0;font-size:16px}.ai-chat-warning{background-color:#fef3c7;border-radius:8px;color:#92400e;font-size:13px;margin:8px 16px;padding:12px}.ai-chat-suggested-questions{margin-bottom:8px;padding:12px 16px}.ai-chat-suggested-questions-label{color:#6b7280;font-size:12px;font-weight:500;margin-bottom:8px}.ai-chat-suggested-questions-list{display:flex;flex-direction:column;gap:8px}.ai-chat-suggested-question{align-items:center;background-color:#f9fafb;border:1px solid #e5e7eb;border-radius:8px;color:#374151;cursor:pointer;display:flex;font-size:14px;gap:8px;padding:10px 12px;text-align:left;transition:all .2s ease;width:100%}.ai-chat-suggested-question:hover{background-color:#f3f4f6;border-color:var(--ai-chat-primary-color,#6366f1);box-shadow:0 2px 4px rgba(0,0,0,.05);transform:translateY(-1px)}.ai-chat-suggested-question:active{transform:translateY(0)}.ai-chat-suggested-question-icon{flex-shrink:0;font-size:16px}.ai-chat-suggested-question-text{flex:1;line-height:1.4}@media (max-width:480px){.ai-chat-window{border-radius:0!important;bottom:0!important;height:100%!important;left:0!important;position:fixed!important;right:0!important;top:0!important;width:100%!important}.ai-chat-widget-container{bottom:20px!important;right:20px!important}.ai-chat-suggested-question{font-size:13px;padding:9px 10px}}.ai-chat-action-approval{background:linear-gradient(135deg,#07f,#001d3d);border-radius:16px;box-shadow:0 4px 12px rgba(0,119,255,.3);color:#fff;margin:16px;padding:16px}.ai-chat-action-approval-content{align-items:flex-start;display:flex;gap:12px;margin-bottom:16px}.ai-chat-action-approval-icon{align-items:center;background:hsla(0,0%,100%,.2);border-radius:8px;display:flex;flex-shrink:0;height:40px;justify-content:center;width:40px}.ai-chat-action-approval-text{flex:1}.ai-chat-action-approval-title{font-size:15px;font-weight:600;margin-bottom:4px}.ai-chat-action-approval-description{font-size:13px;line-height:1.4;opacity:.95}.ai-chat-action-approval-buttons{display:flex;gap:8px;justify-content:flex-end}.ai-chat-action-button{align-items:center;border:none;border-radius:8px;cursor:pointer;display:flex;font-family:inherit;font-size:14px;font-weight:500;gap:6px;padding:8px 16px;transition:all .2s ease}.ai-chat-action-button:disabled{cursor:not-allowed;opacity:.6}.ai-chat-action-button-reject{background:hsla(0,0%,100%,.2);color:#fff}.ai-chat-action-button-reject:hover:not(:disabled){background:hsla(0,0%,100%,.3)}.ai-chat-action-button-approve{background:#fff;color:#07f}.ai-chat-action-button-approve:hover:not(:disabled){background:#f0f0f0;box-shadow:0 2px 8px rgba(0,0,0,.15);transform:translateY(-1px)}.ai-chat-action-spinner{animation:ai-chat-spin .6s linear infinite;border:2px solid rgba(0,119,255,.3);border-radius:50%;border-top-color:#07f;display:inline-block;height:14px;width:14px}@keyframes ai-chat-spin{to{transform:rotate(1turn)}}";
|
|
21533
21866
|
styleInject(css_248z);
|
|
21534
21867
|
|
|
21535
21868
|
const ChatWidget = ({ widgetId, apiKey, apiUrl = window.location.origin, position = 'bottom-right', theme: themeOverride, primaryColor, onOpen, onClose, onMessage, onError, }) => {
|
|
21536
21869
|
const [isOpen, setIsOpen] = useState(false);
|
|
21870
|
+
const widgetRef = useRef(null);
|
|
21537
21871
|
const { messages, isLoading, isTyping, error, config, sendMessage, submitFeedback, } = useChat({
|
|
21538
21872
|
widgetId,
|
|
21539
21873
|
apiKey,
|
|
@@ -21541,6 +21875,21 @@ const ChatWidget = ({ widgetId, apiKey, apiUrl = window.location.origin, positio
|
|
|
21541
21875
|
onMessage,
|
|
21542
21876
|
onError,
|
|
21543
21877
|
});
|
|
21878
|
+
// Debug logging
|
|
21879
|
+
useEffect(() => {
|
|
21880
|
+
console.log('[ChatWidget] Config loaded:', config ? 'YES' : 'NO');
|
|
21881
|
+
if (config) {
|
|
21882
|
+
console.log('[ChatWidget] Config details:', {
|
|
21883
|
+
theme: config.appearance?.theme,
|
|
21884
|
+
darkModeEnabled: config.appearance?.darkModeEnabled,
|
|
21885
|
+
hasLightMode: !!config.appearance?.lightMode,
|
|
21886
|
+
hasDarkMode: !!config.appearance?.darkMode,
|
|
21887
|
+
});
|
|
21888
|
+
}
|
|
21889
|
+
}, [config]);
|
|
21890
|
+
useEffect(() => {
|
|
21891
|
+
console.log('[ChatWidget] isOpen changed:', isOpen);
|
|
21892
|
+
}, [isOpen]);
|
|
21544
21893
|
// Handle auto-open
|
|
21545
21894
|
useEffect(() => {
|
|
21546
21895
|
if (config?.behavior.autoOpen) {
|
|
@@ -21553,26 +21902,84 @@ const ChatWidget = ({ widgetId, apiKey, apiUrl = window.location.origin, positio
|
|
|
21553
21902
|
}
|
|
21554
21903
|
return undefined;
|
|
21555
21904
|
}, [config, onOpen]);
|
|
21905
|
+
// Handle close on outside click
|
|
21906
|
+
useEffect(() => {
|
|
21907
|
+
if (!isOpen || !config?.appearance.closeOnOutsideClick)
|
|
21908
|
+
return;
|
|
21909
|
+
const handleClickOutside = (event) => {
|
|
21910
|
+
if (widgetRef.current && !widgetRef.current.contains(event.target)) {
|
|
21911
|
+
console.log('[ChatWidget] Closing due to outside click');
|
|
21912
|
+
setIsOpen(false);
|
|
21913
|
+
onClose?.();
|
|
21914
|
+
}
|
|
21915
|
+
};
|
|
21916
|
+
// Add slight delay to avoid immediate close on open
|
|
21917
|
+
const timer = setTimeout(() => {
|
|
21918
|
+
document.addEventListener('mousedown', handleClickOutside);
|
|
21919
|
+
}, 100);
|
|
21920
|
+
return () => {
|
|
21921
|
+
clearTimeout(timer);
|
|
21922
|
+
document.removeEventListener('mousedown', handleClickOutside);
|
|
21923
|
+
};
|
|
21924
|
+
}, [isOpen, config, onClose]);
|
|
21925
|
+
// Handle close on Escape key
|
|
21926
|
+
useEffect(() => {
|
|
21927
|
+
if (!isOpen || !config?.appearance.closeOnEscape)
|
|
21928
|
+
return;
|
|
21929
|
+
const handleEscapeKey = (event) => {
|
|
21930
|
+
if (event.key === 'Escape') {
|
|
21931
|
+
setIsOpen(false);
|
|
21932
|
+
onClose?.();
|
|
21933
|
+
}
|
|
21934
|
+
};
|
|
21935
|
+
document.addEventListener('keydown', handleEscapeKey);
|
|
21936
|
+
return () => document.removeEventListener('keydown', handleEscapeKey);
|
|
21937
|
+
}, [isOpen, config, onClose]);
|
|
21556
21938
|
// Determine theme
|
|
21557
|
-
const
|
|
21558
|
-
const
|
|
21559
|
-
|
|
21560
|
-
|
|
21939
|
+
const appearanceConfig = config?.appearance;
|
|
21940
|
+
const themeSetting = themeOverride || appearanceConfig?.theme || 'light';
|
|
21941
|
+
const canUseDarkMode = appearanceConfig?.darkModeEnabled !== false;
|
|
21942
|
+
// Only check system preference if dark mode is enabled
|
|
21943
|
+
const systemPrefersDark = canUseDarkMode && typeof window !== "undefined"
|
|
21944
|
+
? window.matchMedia('(prefers-color-scheme: dark)').matches
|
|
21945
|
+
: false;
|
|
21946
|
+
const effectiveTheme = !canUseDarkMode
|
|
21947
|
+
? 'light' // Force light mode if dark mode is disabled
|
|
21948
|
+
: themeSetting === 'auto'
|
|
21949
|
+
? (systemPrefersDark ? 'dark' : 'light')
|
|
21950
|
+
: themeSetting === 'dark'
|
|
21951
|
+
? 'dark'
|
|
21952
|
+
: 'light';
|
|
21561
21953
|
// Determine position (config takes priority over prop)
|
|
21562
21954
|
const effectivePosition = config?.appearance.position || position;
|
|
21563
|
-
// Apply custom styles
|
|
21564
|
-
|
|
21565
|
-
|
|
21566
|
-
|
|
21567
|
-
|
|
21568
|
-
if
|
|
21569
|
-
|
|
21570
|
-
|
|
21571
|
-
|
|
21572
|
-
|
|
21573
|
-
|
|
21955
|
+
// Apply custom styles from appearance configuration
|
|
21956
|
+
// Use the correct theme configuration (lightMode or darkMode)
|
|
21957
|
+
const customStyles = appearanceConfig
|
|
21958
|
+
? applyAppearanceStyles(appearanceConfig, effectiveTheme)
|
|
21959
|
+
: {};
|
|
21960
|
+
// Override with prop values if provided
|
|
21961
|
+
if (primaryColor) {
|
|
21962
|
+
customStyles['--primary-color'] = primaryColor;
|
|
21963
|
+
}
|
|
21964
|
+
// Debug logging for theme and styles
|
|
21965
|
+
useEffect(() => {
|
|
21966
|
+
console.log('[ChatWidget] Theme info:', {
|
|
21967
|
+
effectiveTheme,
|
|
21968
|
+
canUseDarkMode,
|
|
21969
|
+
themeSetting,
|
|
21970
|
+
systemPrefersDark,
|
|
21971
|
+
hasCustomStyles: Object.keys(customStyles).length > 0,
|
|
21972
|
+
buttonColor: customStyles['--button-color'],
|
|
21973
|
+
buttonSize: customStyles['--button-size'],
|
|
21974
|
+
cardBackground: customStyles['--card-background'],
|
|
21975
|
+
cardOpacity: customStyles['--card-opacity'],
|
|
21976
|
+
cardBorderRadius: customStyles['--card-border-radius'],
|
|
21977
|
+
});
|
|
21978
|
+
console.log('[ChatWidget] All CSS variables:', customStyles);
|
|
21979
|
+
}, [effectiveTheme, customStyles]);
|
|
21574
21980
|
const handleToggle = () => {
|
|
21575
21981
|
const newState = !isOpen;
|
|
21982
|
+
console.log('[ChatWidget] handleToggle called, setting isOpen to:', newState);
|
|
21576
21983
|
setIsOpen(newState);
|
|
21577
21984
|
if (newState) {
|
|
21578
21985
|
onOpen?.();
|
|
@@ -21584,10 +21991,13 @@ const ChatWidget = ({ widgetId, apiKey, apiUrl = window.location.origin, positio
|
|
|
21584
21991
|
const handleFeedback = async (messageId, feedback) => {
|
|
21585
21992
|
await submitFeedback(messageId, feedback);
|
|
21586
21993
|
};
|
|
21587
|
-
|
|
21588
|
-
|
|
21589
|
-
|
|
21590
|
-
|
|
21994
|
+
// Don't render until config is loaded to avoid flash of unstyled content
|
|
21995
|
+
if (!config) {
|
|
21996
|
+
console.log('[ChatWidget] Not rendering - config not loaded yet');
|
|
21997
|
+
return null;
|
|
21998
|
+
}
|
|
21999
|
+
console.log('[ChatWidget] Rendering widget', { isOpen, hasConfig: !!config });
|
|
22000
|
+
return (jsx("div", { className: `ai-chat-widget ${effectiveTheme}`, style: customStyles, children: jsxs("div", { ref: widgetRef, className: `ai-chat-widget-container ${effectivePosition}`, children: [isOpen && (jsx(ChatWindow, { messages: messages, isLoading: isLoading, isTyping: isTyping, error: error, config: config, onSendMessage: sendMessage, onClose: handleToggle, onFeedback: handleFeedback })), !isOpen && (jsx("button", { className: "ai-chat-button", onClick: handleToggle, "aria-label": "Open chat", children: config?.appearance.buttonIcon ? (jsx("span", { className: "ai-chat-button-icon", children: config.appearance.buttonIcon })) : (jsx("svg", { className: "ai-chat-button-svg", viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "2", strokeLinecap: "round", strokeLinejoin: "round", children: jsx("path", { d: "M21 15a2 2 0 0 1-2 2H7l-4 4V5a2 2 0 0 1 2-2h14a2 2 0 0 1 2 2z" }) })) }))] }) }));
|
|
21591
22001
|
};
|
|
21592
22002
|
|
|
21593
22003
|
export { ApiError, ChatWidget, useChat };
|