@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.js
CHANGED
|
@@ -69,6 +69,19 @@ async function buildApiError(response, defaultMessage) {
|
|
|
69
69
|
class WidgetApiClient {
|
|
70
70
|
constructor(config) {
|
|
71
71
|
this.config = config;
|
|
72
|
+
this.detectedTimeZone = WidgetApiClient.detectTimeZone();
|
|
73
|
+
}
|
|
74
|
+
static detectTimeZone() {
|
|
75
|
+
try {
|
|
76
|
+
const tz = Intl.DateTimeFormat().resolvedOptions().timeZone;
|
|
77
|
+
return tz && tz.trim().length > 0 ? tz : "UTC";
|
|
78
|
+
}
|
|
79
|
+
catch {
|
|
80
|
+
return "UTC";
|
|
81
|
+
}
|
|
82
|
+
}
|
|
83
|
+
getTimeZone() {
|
|
84
|
+
return this.detectedTimeZone;
|
|
72
85
|
}
|
|
73
86
|
/**
|
|
74
87
|
* Get widget configuration
|
|
@@ -89,7 +102,15 @@ class WidgetApiClient {
|
|
|
89
102
|
}
|
|
90
103
|
async getOrCreateConversation(conversationId) {
|
|
91
104
|
const baseUrl = `${this.config.apiUrl}/api/widget/${this.config.widgetId}/conversation`;
|
|
92
|
-
const
|
|
105
|
+
const params = new URLSearchParams();
|
|
106
|
+
if (conversationId) {
|
|
107
|
+
params.set('conversationId', conversationId);
|
|
108
|
+
}
|
|
109
|
+
const timeZone = this.getTimeZone();
|
|
110
|
+
if (timeZone) {
|
|
111
|
+
params.set('timeZone', timeZone);
|
|
112
|
+
}
|
|
113
|
+
const query = params.toString() ? `?${params.toString()}` : '';
|
|
93
114
|
const response = await fetch(`${baseUrl}${query}`, {
|
|
94
115
|
method: 'GET',
|
|
95
116
|
headers: {
|
|
@@ -136,6 +157,7 @@ class WidgetApiClient {
|
|
|
136
157
|
conversationId: conversationId,
|
|
137
158
|
message,
|
|
138
159
|
fileIds,
|
|
160
|
+
timeZone: this.getTimeZone(),
|
|
139
161
|
}),
|
|
140
162
|
});
|
|
141
163
|
if (!response.ok) {
|
|
@@ -158,6 +180,7 @@ class WidgetApiClient {
|
|
|
158
180
|
conversationId: conversationId,
|
|
159
181
|
message,
|
|
160
182
|
fileIds,
|
|
183
|
+
timeZone: this.getTimeZone(),
|
|
161
184
|
}),
|
|
162
185
|
});
|
|
163
186
|
if (!response.ok) {
|
|
@@ -234,11 +257,6 @@ class WidgetApiClient {
|
|
|
234
257
|
/**
|
|
235
258
|
* Generate a unique session ID
|
|
236
259
|
*/
|
|
237
|
-
function generateSessionId() {
|
|
238
|
-
const timestamp = Date.now().toString(36);
|
|
239
|
-
const randomStr = Math.random().toString(36).substring(2, 15);
|
|
240
|
-
return `session_${timestamp}_${randomStr}`;
|
|
241
|
-
}
|
|
242
260
|
/**
|
|
243
261
|
* Generate a unique message ID
|
|
244
262
|
*/
|
|
@@ -293,6 +311,18 @@ function loadConversation(widgetId) {
|
|
|
293
311
|
return null;
|
|
294
312
|
}
|
|
295
313
|
}
|
|
314
|
+
/**
|
|
315
|
+
* Clear conversation from localStorage
|
|
316
|
+
*/
|
|
317
|
+
function clearConversation(widgetId) {
|
|
318
|
+
try {
|
|
319
|
+
const key = getStorageKey(widgetId);
|
|
320
|
+
localStorage.removeItem(key);
|
|
321
|
+
}
|
|
322
|
+
catch (error) {
|
|
323
|
+
console.error('Failed to clear conversation:', error);
|
|
324
|
+
}
|
|
325
|
+
}
|
|
296
326
|
/**
|
|
297
327
|
* Check if localStorage is available
|
|
298
328
|
*/
|
|
@@ -385,29 +415,53 @@ function useChat(options) {
|
|
|
385
415
|
config: null,
|
|
386
416
|
});
|
|
387
417
|
const apiClient = react.useRef(new WidgetApiClient({ widgetId, apiKey, apiUrl }));
|
|
388
|
-
// Load configuration and conversation
|
|
418
|
+
// Load configuration on mount and hydrate with existing conversation if available
|
|
389
419
|
react.useEffect(() => {
|
|
420
|
+
let isMounted = true;
|
|
421
|
+
console.log('[useChat] Effect running, mounting component');
|
|
390
422
|
const initialize = async () => {
|
|
391
423
|
try {
|
|
392
|
-
|
|
424
|
+
console.log('[useChat] Fetching config...');
|
|
393
425
|
const config = await apiClient.current.getConfig();
|
|
394
|
-
|
|
426
|
+
console.log('[useChat] Config fetched successfully:', {
|
|
427
|
+
hasAppearance: !!config.appearance,
|
|
428
|
+
hasLightMode: !!config.appearance?.lightMode,
|
|
429
|
+
hasDarkMode: !!config.appearance?.darkMode,
|
|
430
|
+
});
|
|
395
431
|
const persistConversation = config.behavior.persistConversation ?? true;
|
|
396
|
-
let conversationId;
|
|
432
|
+
let conversationId = '';
|
|
433
|
+
let messages = [];
|
|
397
434
|
if (persistConversation && isStorageAvailable()) {
|
|
398
435
|
const stored = loadConversation(widgetId);
|
|
399
|
-
|
|
436
|
+
const storedId = stored?.conversationId || stored?.sessionId;
|
|
437
|
+
if (storedId) {
|
|
438
|
+
try {
|
|
439
|
+
const conversation = await apiClient.current.getOrCreateConversation(storedId);
|
|
440
|
+
conversationId = conversation.id;
|
|
441
|
+
messages = conversation.messages;
|
|
442
|
+
}
|
|
443
|
+
catch (conversationError) {
|
|
444
|
+
console.warn('Failed to load existing conversation:', conversationError);
|
|
445
|
+
}
|
|
446
|
+
}
|
|
400
447
|
}
|
|
401
|
-
|
|
402
|
-
|
|
448
|
+
if (!isMounted) {
|
|
449
|
+
console.log('[useChat] Component unmounted, skipping state update');
|
|
450
|
+
return;
|
|
451
|
+
}
|
|
452
|
+
console.log('[useChat] Setting config in state');
|
|
403
453
|
setState(prev => ({
|
|
404
454
|
...prev,
|
|
405
455
|
config,
|
|
406
|
-
conversationId
|
|
407
|
-
messages
|
|
456
|
+
conversationId,
|
|
457
|
+
messages,
|
|
408
458
|
}));
|
|
409
459
|
}
|
|
410
460
|
catch (error) {
|
|
461
|
+
console.error('[useChat] Error fetching config:', error);
|
|
462
|
+
if (!isMounted) {
|
|
463
|
+
return;
|
|
464
|
+
}
|
|
411
465
|
const errorInfo = deriveErrorInfo(error);
|
|
412
466
|
const err = error instanceof Error ? error : new Error(errorInfo.message);
|
|
413
467
|
setState(prev => ({ ...prev, error: errorInfo.message }));
|
|
@@ -415,11 +469,18 @@ function useChat(options) {
|
|
|
415
469
|
}
|
|
416
470
|
};
|
|
417
471
|
initialize();
|
|
472
|
+
return () => {
|
|
473
|
+
console.log('[useChat] Effect cleanup, unmounting component');
|
|
474
|
+
isMounted = false;
|
|
475
|
+
};
|
|
418
476
|
}, [widgetId, apiKey, apiUrl, onError]);
|
|
419
477
|
// Save conversation when messages change
|
|
420
478
|
react.useEffect(() => {
|
|
421
479
|
const persistConversation = state.config?.behavior.persistConversation ?? true;
|
|
422
|
-
if (persistConversation &&
|
|
480
|
+
if (persistConversation &&
|
|
481
|
+
isStorageAvailable() &&
|
|
482
|
+
state.messages.length > 0 &&
|
|
483
|
+
state.conversationId) {
|
|
423
484
|
saveConversation(widgetId, state.conversationId, state.messages);
|
|
424
485
|
}
|
|
425
486
|
}, [widgetId, state.messages, state.conversationId, state.config?.behavior.persistConversation]);
|
|
@@ -427,13 +488,15 @@ function useChat(options) {
|
|
|
427
488
|
* Send a message
|
|
428
489
|
*/
|
|
429
490
|
const sendMessage = react.useCallback(async (content, files) => {
|
|
430
|
-
|
|
491
|
+
const trimmedContent = content.trim();
|
|
492
|
+
const hasFiles = !!files && files.length > 0;
|
|
493
|
+
if (!trimmedContent && !hasFiles)
|
|
431
494
|
return;
|
|
432
495
|
const userMessage = {
|
|
433
496
|
id: generateMessageId(),
|
|
434
497
|
message: {
|
|
435
498
|
type: 'human',
|
|
436
|
-
content:
|
|
499
|
+
content: trimmedContent,
|
|
437
500
|
},
|
|
438
501
|
timestamp: new Date().toISOString(),
|
|
439
502
|
sources: [],
|
|
@@ -448,13 +511,37 @@ function useChat(options) {
|
|
|
448
511
|
}));
|
|
449
512
|
onMessage?.(userMessage);
|
|
450
513
|
try {
|
|
514
|
+
let conversationId = state.conversationId;
|
|
515
|
+
if (!conversationId) {
|
|
516
|
+
const conversation = await apiClient.current.getOrCreateConversation();
|
|
517
|
+
conversationId = conversation.id;
|
|
518
|
+
setState(prev => {
|
|
519
|
+
const serverMessages = conversation.messages ?? [];
|
|
520
|
+
if (serverMessages.length === 0) {
|
|
521
|
+
return {
|
|
522
|
+
...prev,
|
|
523
|
+
conversationId,
|
|
524
|
+
};
|
|
525
|
+
}
|
|
526
|
+
const serverIds = new Set(serverMessages.map(msg => msg.id));
|
|
527
|
+
const mergedMessages = [
|
|
528
|
+
...serverMessages,
|
|
529
|
+
...prev.messages.filter(msg => !serverIds.has(msg.id)),
|
|
530
|
+
];
|
|
531
|
+
return {
|
|
532
|
+
...prev,
|
|
533
|
+
conversationId,
|
|
534
|
+
messages: mergedMessages,
|
|
535
|
+
};
|
|
536
|
+
});
|
|
537
|
+
}
|
|
451
538
|
// Upload files if provided
|
|
452
539
|
let fileIds;
|
|
453
540
|
if (files && files.length > 0) {
|
|
454
541
|
fileIds = [];
|
|
455
542
|
for (const file of files) {
|
|
456
543
|
try {
|
|
457
|
-
const uploadedFile = await apiClient.current.uploadFile(
|
|
544
|
+
const uploadedFile = await apiClient.current.uploadFile(conversationId, file);
|
|
458
545
|
fileIds.push(uploadedFile.id);
|
|
459
546
|
}
|
|
460
547
|
catch (uploadError) {
|
|
@@ -468,11 +555,11 @@ function useChat(options) {
|
|
|
468
555
|
let response;
|
|
469
556
|
if (useAgent) {
|
|
470
557
|
// Use agent endpoint - returns ConversationMessage[]
|
|
471
|
-
response = await apiClient.current.sendAgentMessage(
|
|
558
|
+
response = await apiClient.current.sendAgentMessage(conversationId, trimmedContent, fileIds);
|
|
472
559
|
}
|
|
473
560
|
else {
|
|
474
561
|
// Use standard chat endpoint
|
|
475
|
-
response = await apiClient.current.sendMessage(
|
|
562
|
+
response = await apiClient.current.sendMessage(conversationId, trimmedContent, fileIds);
|
|
476
563
|
}
|
|
477
564
|
// Both endpoints now return ConversationMessage[] array (FULL conversation)
|
|
478
565
|
if (Array.isArray(response)) {
|
|
@@ -584,12 +671,12 @@ function useChat(options) {
|
|
|
584
671
|
setState(prev => ({
|
|
585
672
|
...prev,
|
|
586
673
|
messages: [],
|
|
587
|
-
conversationId:
|
|
674
|
+
conversationId: '',
|
|
588
675
|
error: null,
|
|
589
676
|
}));
|
|
590
677
|
const persistConversation = state.config?.behavior.persistConversation ?? true;
|
|
591
678
|
if (persistConversation && isStorageAvailable()) {
|
|
592
|
-
|
|
679
|
+
clearConversation(widgetId);
|
|
593
680
|
}
|
|
594
681
|
}, [widgetId, state.config?.behavior.persistConversation]);
|
|
595
682
|
/**
|
|
@@ -21357,7 +21444,7 @@ const TypingIndicator = () => {
|
|
|
21357
21444
|
return (jsxRuntime.jsx("div", { className: "ai-chat-message assistant", children: jsxRuntime.jsxs("div", { className: "ai-chat-typing", children: [jsxRuntime.jsx("span", { className: "ai-chat-typing-dot" }), jsxRuntime.jsx("span", { className: "ai-chat-typing-dot" }), jsxRuntime.jsx("span", { className: "ai-chat-typing-dot" })] }) }));
|
|
21358
21445
|
};
|
|
21359
21446
|
|
|
21360
|
-
const MessageList = ({ messages, isTyping = false, showTypingIndicator = true, showTimestamps = true, enableFeedback = true, showSources = true, sourceDisplayMode = 'with-score', welcomeMessage, onFeedback, }) => {
|
|
21447
|
+
const MessageList = ({ messages, isTyping = false, showTypingIndicator = true, showTimestamps = true, enableFeedback = true, showSources = true, sourceDisplayMode = 'with-score', welcomeTitle, welcomeMessage, onFeedback, }) => {
|
|
21361
21448
|
const messagesEndRef = react.useRef(null);
|
|
21362
21449
|
// Auto-scroll to bottom when new messages arrive
|
|
21363
21450
|
react.useEffect(() => {
|
|
@@ -21377,7 +21464,7 @@ const MessageList = ({ messages, isTyping = false, showTypingIndicator = true, s
|
|
|
21377
21464
|
}
|
|
21378
21465
|
return map;
|
|
21379
21466
|
}, [messages]);
|
|
21380
|
-
return (jsxRuntime.jsxs("div", { className: "ai-chat-messages", role: "log", "aria-live": "polite", "aria-atomic": "false", children: [messages.length === 0 && welcomeMessage && (jsxRuntime.jsxs("div", { className: "ai-chat-welcome", children: [jsxRuntime.jsx("div", { className: "ai-chat-welcome-title", children:
|
|
21467
|
+
return (jsxRuntime.jsxs("div", { className: "ai-chat-messages", role: "log", "aria-live": "polite", "aria-atomic": "false", children: [messages.length === 0 && (welcomeTitle || welcomeMessage) && (jsxRuntime.jsxs("div", { className: "ai-chat-welcome", children: [welcomeTitle && (jsxRuntime.jsx("div", { className: "ai-chat-welcome-title", children: welcomeTitle })), welcomeMessage && (jsxRuntime.jsx("div", { className: "ai-chat-welcome-text", children: welcomeMessage }))] })), messages.map((message) => (jsxRuntime.jsx(Message, { message: message, showTimestamp: showTimestamps, enableFeedback: enableFeedback, showSources: showSources, sourceDisplayMode: sourceDisplayMode, toolCallNameById: toolCallNameById, onFeedback: onFeedback }, message.id))), isTyping && showTypingIndicator && jsxRuntime.jsx(TypingIndicator, {}), jsxRuntime.jsx("div", { ref: messagesEndRef })] }));
|
|
21381
21468
|
};
|
|
21382
21469
|
|
|
21383
21470
|
// Allowed file types
|
|
@@ -21403,7 +21490,7 @@ const formatFileSize = (bytes) => {
|
|
|
21403
21490
|
return (bytes / 1024).toFixed(1) + ' KB';
|
|
21404
21491
|
return (bytes / (1024 * 1024)).toFixed(1) + ' MB';
|
|
21405
21492
|
};
|
|
21406
|
-
const MessageInput = ({ onSend, placeholder = 'Type your message...', disabled = false, enableFileUpload = false, }) => {
|
|
21493
|
+
const MessageInput = ({ onSend, placeholder = 'Type your message...', disabled = false, enableFileUpload = false, separateFromChat = true, }) => {
|
|
21407
21494
|
const [value, setValue] = react.useState('');
|
|
21408
21495
|
const [selectedFiles, setSelectedFiles] = react.useState([]);
|
|
21409
21496
|
const textareaRef = react.useRef(null);
|
|
@@ -21461,7 +21548,8 @@ const MessageInput = ({ onSend, placeholder = 'Type your message...', disabled =
|
|
|
21461
21548
|
textareaRef.current.style.height = `${textareaRef.current.scrollHeight}px`;
|
|
21462
21549
|
}
|
|
21463
21550
|
};
|
|
21464
|
-
|
|
21551
|
+
console.log('[MessageInput] separateFromChat:', separateFromChat, 'class:', separateFromChat ? 'separate' : 'integrated');
|
|
21552
|
+
return (jsxRuntime.jsxs("div", { className: `ai-chat-input-container ${separateFromChat ? 'separate' : 'integrated'}`, children: [selectedFiles.length > 0 && (jsxRuntime.jsx("div", { className: "ai-chat-file-list", children: selectedFiles.map((file, index) => {
|
|
21465
21553
|
const ext = getFileExtension(file.name);
|
|
21466
21554
|
return (jsxRuntime.jsxs("div", { className: "ai-chat-file-item", children: [jsxRuntime.jsx("span", { className: "ai-chat-file-extension", children: ext }), jsxRuntime.jsxs("div", { className: "ai-chat-file-info", children: [jsxRuntime.jsx("span", { className: "ai-chat-file-name", children: file.name }), jsxRuntime.jsx("span", { className: "ai-chat-file-size", children: formatFileSize(file.size) })] }), jsxRuntime.jsx("button", { className: "ai-chat-file-remove", onClick: () => handleRemoveFile(index), "aria-label": "Remove file", children: "\u00D7" })] }, index));
|
|
21467
21555
|
}) })), jsxRuntime.jsxs("div", { className: "ai-chat-input-wrapper", children: [enableFileUpload && (jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [jsxRuntime.jsx("input", { ref: fileInputRef, type: "file", onChange: handleFileSelect, style: { display: 'none' }, multiple: true, accept: ALLOWED_EXTENSIONS.join(','), "aria-label": "File input" }), jsxRuntime.jsx("button", { className: "ai-chat-file-button", onClick: () => fileInputRef.current?.click(), disabled: disabled, "aria-label": "Attach file", children: jsxRuntime.jsx("svg", { width: "20", height: "20", viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "2", strokeLinecap: "round", strokeLinejoin: "round", children: jsxRuntime.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" }) }) })] })), jsxRuntime.jsx("textarea", { ref: textareaRef, className: "ai-chat-input", value: value, onChange: handleChange, onKeyDown: handleKeyDown, placeholder: placeholder, disabled: disabled, rows: 1, "aria-label": "Message input" }), jsxRuntime.jsx("button", { className: "ai-chat-send-button", onClick: handleSend, disabled: disabled || (!value.trim() && selectedFiles.length === 0), "aria-label": "Send message", children: jsxRuntime.jsxs("svg", { width: "20", height: "20", viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "2", strokeLinecap: "round", strokeLinejoin: "round", children: [jsxRuntime.jsx("line", { x1: "22", y1: "2", x2: "11", y2: "13" }), jsxRuntime.jsx("polygon", { points: "22 2 15 22 11 13 2 9 22 2" })] }) })] })] }));
|
|
@@ -21480,9 +21568,23 @@ const SuggestedQuestions = ({ questions, onQuestionClick, }) => {
|
|
|
21480
21568
|
};
|
|
21481
21569
|
|
|
21482
21570
|
const ChatWindow = ({ messages, isLoading, isTyping, error, config, onSendMessage, onClose, onFeedback, }) => {
|
|
21571
|
+
console.log('[ChatWindow] Rendering ChatWindow component');
|
|
21483
21572
|
const appearance = config?.appearance;
|
|
21484
21573
|
const behavior = config?.behavior;
|
|
21485
21574
|
const size = appearance?.size || 'medium';
|
|
21575
|
+
console.log('[ChatWindow] Size:', size, 'Appearance:', !!appearance);
|
|
21576
|
+
// Determine current theme config
|
|
21577
|
+
const themePreference = appearance?.theme ?? 'light';
|
|
21578
|
+
const canUseDarkMode = appearance?.darkModeEnabled !== false;
|
|
21579
|
+
const prefersDark = typeof window !== 'undefined' && window.matchMedia('(prefers-color-scheme: dark)').matches;
|
|
21580
|
+
const isDarkMode = themePreference === 'auto'
|
|
21581
|
+
? (canUseDarkMode && prefersDark)
|
|
21582
|
+
: themePreference === 'dark' && canUseDarkMode;
|
|
21583
|
+
const themeConfig = (isDarkMode ? appearance?.darkMode : appearance?.lightMode) ?? (appearance?.lightMode || appearance?.darkMode);
|
|
21584
|
+
const headerTitle = themeConfig?.header?.title ?? appearance?.header?.title ?? appearance?.companyName ?? 'AI Assistant';
|
|
21585
|
+
const welcomeTitle = themeConfig?.chat?.welcomeTitle ?? 'Welcome!';
|
|
21586
|
+
const welcomeMessage = themeConfig?.chat?.welcomeMessage ?? appearance?.welcomeMessage ?? '👋 Hi there! How can I assist you today?';
|
|
21587
|
+
const inputPlaceholder = themeConfig?.footer?.inputPlaceholder ?? appearance?.placeholder ?? 'Ask me anything...';
|
|
21486
21588
|
// Track if suggested questions should be shown
|
|
21487
21589
|
const [showSuggestedQuestions, setShowSuggestedQuestions] = react.useState(true);
|
|
21488
21590
|
// Hide suggested questions after first user message
|
|
@@ -21501,9 +21603,240 @@ const ChatWindow = ({ messages, isLoading, isTyping, error, config, onSendMessag
|
|
|
21501
21603
|
setShowSuggestedQuestions(false);
|
|
21502
21604
|
onSendMessage(question);
|
|
21503
21605
|
};
|
|
21504
|
-
return (jsxRuntime.jsxs("div", { className: `ai-chat-window size-${size}`, role: "dialog", "aria-label": "Chat window", children: [jsxRuntime.jsxs("div", { className: "ai-chat-header", children: [jsxRuntime.jsxs("div", { className: "ai-chat-header-content", children: [appearance?.logo && (jsxRuntime.jsx("img", { src: appearance.logo, alt: "Logo", className: "ai-chat-logo" })), jsxRuntime.jsx("div", { className: "ai-chat-title", children:
|
|
21606
|
+
return (jsxRuntime.jsxs("div", { className: `ai-chat-window size-${size}`, role: "dialog", "aria-label": "Chat window", children: [jsxRuntime.jsxs("div", { className: "ai-chat-header", children: [jsxRuntime.jsxs("div", { className: "ai-chat-header-content", children: [appearance?.logo && (jsxRuntime.jsx("img", { src: appearance.logo, alt: "Logo", className: "ai-chat-logo" })), jsxRuntime.jsx("div", { className: "ai-chat-title", children: headerTitle })] }), jsxRuntime.jsx("button", { className: "ai-chat-close-button", onClick: onClose, "aria-label": "Close chat", children: jsxRuntime.jsxs("svg", { width: "20", height: "20", viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "2", strokeLinecap: "round", strokeLinejoin: "round", children: [jsxRuntime.jsx("line", { x1: "18", y1: "6", x2: "6", y2: "18" }), jsxRuntime.jsx("line", { x1: "6", y1: "6", x2: "18", y2: "18" })] }) })] }), error && (jsxRuntime.jsx("div", { className: "ai-chat-error", role: "alert", children: error })), maxMessages && userMessageCount >= maxMessages - 2 && !isLimitReached && (jsxRuntime.jsxs("div", { className: "ai-chat-warning", role: "alert", children: [maxMessages - userMessageCount, " message", maxMessages - userMessageCount !== 1 ? 's' : '', " remaining in this session"] })), isLimitReached && (jsxRuntime.jsxs("div", { className: "ai-chat-error", role: "alert", children: ["Message limit reached (", maxMessages, " messages per session). Please start a new conversation."] })), jsxRuntime.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 && (jsxRuntime.jsx(SuggestedQuestions, { questions: behavior.suggestedQuestions, onQuestionClick: handleQuestionClick })), jsxRuntime.jsx(MessageInput, { onSend: onSendMessage, placeholder: isLimitReached ? 'Message limit reached' : inputPlaceholder, disabled: isLoading || isLimitReached, enableFileUpload: behavior?.enableFileUpload, separateFromChat: themeConfig?.footer?.separateFromChat })] }));
|
|
21505
21607
|
};
|
|
21506
21608
|
|
|
21609
|
+
/**
|
|
21610
|
+
* Convert shadow size to CSS box-shadow value
|
|
21611
|
+
*/
|
|
21612
|
+
function getShadowValue(size) {
|
|
21613
|
+
const shadows = {
|
|
21614
|
+
'none': 'none',
|
|
21615
|
+
'sm': '0 1px 2px 0 rgba(0, 0, 0, 0.05)',
|
|
21616
|
+
'md': '0 4px 6px -1px rgba(0, 0, 0, 0.1), 0 2px 4px -1px rgba(0, 0, 0, 0.06)',
|
|
21617
|
+
'lg': '0 10px 15px -3px rgba(0, 0, 0, 0.1), 0 4px 6px -2px rgba(0, 0, 0, 0.05)',
|
|
21618
|
+
'xl': '0 20px 25px -5px rgba(0, 0, 0, 0.1), 0 10px 10px -5px rgba(0, 0, 0, 0.04)',
|
|
21619
|
+
'2xl': '0 25px 50px -12px rgba(0, 0, 0, 0.25)',
|
|
21620
|
+
};
|
|
21621
|
+
return shadows[size] || shadows.none;
|
|
21622
|
+
}
|
|
21623
|
+
/**
|
|
21624
|
+
* Apply appearance configuration as CSS custom properties
|
|
21625
|
+
* This allows the widget to be fully customizable via the appearance config
|
|
21626
|
+
*
|
|
21627
|
+
* @param appearance - Widget appearance configuration
|
|
21628
|
+
* @param theme - Current theme ('light' or 'dark')
|
|
21629
|
+
*/
|
|
21630
|
+
function applyAppearanceStyles(appearance, theme = 'light') {
|
|
21631
|
+
const styles = {};
|
|
21632
|
+
// Global font family
|
|
21633
|
+
if (appearance.fontFamily) {
|
|
21634
|
+
styles.fontFamily = appearance.fontFamily;
|
|
21635
|
+
}
|
|
21636
|
+
// Select the correct theme configuration
|
|
21637
|
+
const themeConfig = theme === 'dark' ? appearance.darkMode : appearance.lightMode;
|
|
21638
|
+
// If theme config exists and has required properties, use it
|
|
21639
|
+
if (themeConfig && themeConfig.button) {
|
|
21640
|
+
// ========================================================================
|
|
21641
|
+
// BUTTON APPEARANCE
|
|
21642
|
+
// ========================================================================
|
|
21643
|
+
const btn = themeConfig.button;
|
|
21644
|
+
if (btn.color)
|
|
21645
|
+
styles['--button-color'] = btn.color;
|
|
21646
|
+
if (btn.opacity !== undefined)
|
|
21647
|
+
styles['--button-opacity'] = btn.opacity.toString();
|
|
21648
|
+
if (btn.size)
|
|
21649
|
+
styles['--button-size'] = `${btn.size}px`;
|
|
21650
|
+
if (btn.borderRadius !== undefined)
|
|
21651
|
+
styles['--button-border-radius'] = `${btn.borderRadius}px`;
|
|
21652
|
+
if (btn.borderWidth !== undefined)
|
|
21653
|
+
styles['--button-border-width'] = `${btn.borderWidth}px`;
|
|
21654
|
+
if (btn.borderColor)
|
|
21655
|
+
styles['--button-border-color'] = btn.borderColor;
|
|
21656
|
+
if (btn.borderOpacity !== undefined)
|
|
21657
|
+
styles['--button-border-opacity'] = btn.borderOpacity.toString();
|
|
21658
|
+
if (btn.backdropBlur !== undefined)
|
|
21659
|
+
styles['--button-backdrop-blur'] = `${btn.backdropBlur}px`;
|
|
21660
|
+
if (btn.shadow)
|
|
21661
|
+
styles['--button-shadow'] = getShadowValue(btn.shadow);
|
|
21662
|
+
// ========================================================================
|
|
21663
|
+
// CARD/WINDOW APPEARANCE
|
|
21664
|
+
// ========================================================================
|
|
21665
|
+
const card = themeConfig.card;
|
|
21666
|
+
if (card.backgroundColor)
|
|
21667
|
+
styles['--card-background'] = card.backgroundColor;
|
|
21668
|
+
if (card.opacity !== undefined)
|
|
21669
|
+
styles['--card-opacity'] = card.opacity.toString();
|
|
21670
|
+
if (card.borderRadius !== undefined)
|
|
21671
|
+
styles['--card-border-radius'] = `${card.borderRadius}px`;
|
|
21672
|
+
if (card.borderWidth !== undefined)
|
|
21673
|
+
styles['--card-border-width'] = `${card.borderWidth}px`;
|
|
21674
|
+
if (card.borderColor) {
|
|
21675
|
+
styles['--card-border-color'] = card.borderColor;
|
|
21676
|
+
// Create rgba border color with opacity for box-shadow
|
|
21677
|
+
if (card.borderOpacity !== undefined) {
|
|
21678
|
+
const opacity = card.borderOpacity;
|
|
21679
|
+
// Convert hex to rgba
|
|
21680
|
+
const hex = card.borderColor.replace('#', '');
|
|
21681
|
+
const r = parseInt(hex.substring(0, 2), 16);
|
|
21682
|
+
const g = parseInt(hex.substring(2, 4), 16);
|
|
21683
|
+
const b = parseInt(hex.substring(4, 6), 16);
|
|
21684
|
+
styles['--card-border-color-rgba'] = `rgba(${r}, ${g}, ${b}, ${opacity})`;
|
|
21685
|
+
}
|
|
21686
|
+
}
|
|
21687
|
+
if (card.borderOpacity !== undefined)
|
|
21688
|
+
styles['--card-border-opacity'] = card.borderOpacity.toString();
|
|
21689
|
+
if (card.backdropBlur !== undefined)
|
|
21690
|
+
styles['--card-backdrop-blur'] = `${card.backdropBlur}px`;
|
|
21691
|
+
if (card.shadow)
|
|
21692
|
+
styles['--card-shadow'] = getShadowValue(card.shadow);
|
|
21693
|
+
// ========================================================================
|
|
21694
|
+
// HEADER APPEARANCE
|
|
21695
|
+
// ========================================================================
|
|
21696
|
+
const header = themeConfig.header;
|
|
21697
|
+
if (header.backgroundColor)
|
|
21698
|
+
styles['--header-background'] = header.backgroundColor;
|
|
21699
|
+
if (header.opacity !== undefined)
|
|
21700
|
+
styles['--header-opacity'] = header.opacity.toString();
|
|
21701
|
+
if (header.textColor)
|
|
21702
|
+
styles['--header-text-color'] = header.textColor;
|
|
21703
|
+
if (header.borderBottomWidth !== undefined)
|
|
21704
|
+
styles['--header-border-bottom-width'] = `${header.borderBottomWidth}px`;
|
|
21705
|
+
if (header.borderBottomColor)
|
|
21706
|
+
styles['--header-border-bottom-color'] = header.borderBottomColor;
|
|
21707
|
+
if (header.borderBottomOpacity !== undefined)
|
|
21708
|
+
styles['--header-border-bottom-opacity'] = header.borderBottomOpacity.toString();
|
|
21709
|
+
// ========================================================================
|
|
21710
|
+
// CHAT APPEARANCE
|
|
21711
|
+
// ========================================================================
|
|
21712
|
+
const chat = themeConfig.chat;
|
|
21713
|
+
if (chat.backgroundColor)
|
|
21714
|
+
styles['--chat-background'] = chat.backgroundColor;
|
|
21715
|
+
if (chat.opacity !== undefined)
|
|
21716
|
+
styles['--chat-opacity'] = chat.opacity.toString();
|
|
21717
|
+
// Welcome message
|
|
21718
|
+
if (chat.welcomeColor)
|
|
21719
|
+
styles['--welcome-color'] = chat.welcomeColor;
|
|
21720
|
+
// Message bubbles
|
|
21721
|
+
if (chat.enableBubbles) {
|
|
21722
|
+
if (chat.bubbleUserColor)
|
|
21723
|
+
styles['--bubble-user-color'] = chat.bubbleUserColor;
|
|
21724
|
+
if (chat.bubbleUserOpacity !== undefined)
|
|
21725
|
+
styles['--bubble-user-opacity'] = chat.bubbleUserOpacity.toString();
|
|
21726
|
+
if (chat.bubbleAssistantColor)
|
|
21727
|
+
styles['--bubble-assistant-color'] = chat.bubbleAssistantColor;
|
|
21728
|
+
if (chat.bubbleAssistantOpacity !== undefined)
|
|
21729
|
+
styles['--bubble-assistant-opacity'] = chat.bubbleAssistantOpacity.toString();
|
|
21730
|
+
if (chat.bubbleBorderWidth !== undefined)
|
|
21731
|
+
styles['--bubble-border-width'] = `${chat.bubbleBorderWidth}px`;
|
|
21732
|
+
if (chat.bubbleBorderColor)
|
|
21733
|
+
styles['--bubble-border-color'] = chat.bubbleBorderColor;
|
|
21734
|
+
if (chat.bubbleBorderOpacity !== undefined)
|
|
21735
|
+
styles['--bubble-border-opacity'] = chat.bubbleBorderOpacity.toString();
|
|
21736
|
+
}
|
|
21737
|
+
else {
|
|
21738
|
+
// Plain text mode
|
|
21739
|
+
if (chat.textColor)
|
|
21740
|
+
styles['--message-text-color'] = chat.textColor;
|
|
21741
|
+
}
|
|
21742
|
+
// ========================================================================
|
|
21743
|
+
// FOOTER APPEARANCE
|
|
21744
|
+
// ========================================================================
|
|
21745
|
+
const footer = themeConfig.footer;
|
|
21746
|
+
// Only if separate from chat
|
|
21747
|
+
if (footer.separateFromChat) {
|
|
21748
|
+
if (footer.backgroundColor)
|
|
21749
|
+
styles['--footer-background'] = footer.backgroundColor;
|
|
21750
|
+
if (footer.opacity !== undefined)
|
|
21751
|
+
styles['--footer-opacity'] = footer.opacity.toString();
|
|
21752
|
+
if (footer.borderTopWidth !== undefined)
|
|
21753
|
+
styles['--footer-border-top-width'] = `${footer.borderTopWidth}px`;
|
|
21754
|
+
if (footer.borderTopColor)
|
|
21755
|
+
styles['--footer-border-top-color'] = footer.borderTopColor;
|
|
21756
|
+
if (footer.borderTopOpacity !== undefined)
|
|
21757
|
+
styles['--footer-border-top-opacity'] = footer.borderTopOpacity.toString();
|
|
21758
|
+
}
|
|
21759
|
+
// Backdrop blur (only when floating)
|
|
21760
|
+
if (!footer.separateFromChat && footer.backdropBlur !== undefined) {
|
|
21761
|
+
styles['--footer-backdrop-blur'] = `${footer.backdropBlur}px`;
|
|
21762
|
+
}
|
|
21763
|
+
// Input field
|
|
21764
|
+
if (footer.inputBackgroundColor)
|
|
21765
|
+
styles['--input-background'] = footer.inputBackgroundColor;
|
|
21766
|
+
if (footer.inputBackgroundOpacity !== undefined)
|
|
21767
|
+
styles['--input-background-opacity'] = footer.inputBackgroundOpacity.toString();
|
|
21768
|
+
if (footer.inputBorderRadius !== undefined)
|
|
21769
|
+
styles['--input-border-radius'] = `${footer.inputBorderRadius}px`;
|
|
21770
|
+
if (footer.inputBorderWidth !== undefined)
|
|
21771
|
+
styles['--input-border-width'] = `${footer.inputBorderWidth}px`;
|
|
21772
|
+
if (footer.inputBorderColor)
|
|
21773
|
+
styles['--input-border-color'] = footer.inputBorderColor;
|
|
21774
|
+
if (footer.inputBorderOpacity !== undefined)
|
|
21775
|
+
styles['--input-border-opacity'] = footer.inputBorderOpacity.toString();
|
|
21776
|
+
if (footer.inputShadow)
|
|
21777
|
+
styles['--input-shadow'] = getShadowValue(footer.inputShadow);
|
|
21778
|
+
// Send button
|
|
21779
|
+
if (footer.buttonBackgroundColor)
|
|
21780
|
+
styles['--send-button-background'] = footer.buttonBackgroundColor;
|
|
21781
|
+
if (footer.buttonOpacity !== undefined)
|
|
21782
|
+
styles['--send-button-opacity'] = footer.buttonOpacity.toString();
|
|
21783
|
+
if (footer.buttonBorderRadius !== undefined)
|
|
21784
|
+
styles['--send-button-border-radius'] = `${footer.buttonBorderRadius}px`;
|
|
21785
|
+
if (footer.buttonBorderWidth !== undefined)
|
|
21786
|
+
styles['--send-button-border-width'] = `${footer.buttonBorderWidth}px`;
|
|
21787
|
+
if (footer.buttonBorderColor)
|
|
21788
|
+
styles['--send-button-border-color'] = footer.buttonBorderColor;
|
|
21789
|
+
if (footer.buttonBorderOpacity !== undefined)
|
|
21790
|
+
styles['--send-button-border-opacity'] = footer.buttonBorderOpacity.toString();
|
|
21791
|
+
// ========================================================================
|
|
21792
|
+
// HOVER STATES
|
|
21793
|
+
// ========================================================================
|
|
21794
|
+
const hover = themeConfig.hover;
|
|
21795
|
+
if (hover.buttonScale !== undefined)
|
|
21796
|
+
styles['--hover-button-scale'] = hover.buttonScale.toString();
|
|
21797
|
+
if (hover.buttonOpacity !== undefined)
|
|
21798
|
+
styles['--hover-button-opacity'] = hover.buttonOpacity.toString();
|
|
21799
|
+
if (hover.inputBorderColor)
|
|
21800
|
+
styles['--hover-input-border-color'] = hover.inputBorderColor;
|
|
21801
|
+
if (hover.sendButtonOpacity !== undefined)
|
|
21802
|
+
styles['--hover-send-button-opacity'] = hover.sendButtonOpacity.toString();
|
|
21803
|
+
if (hover.closeButtonOpacity !== undefined)
|
|
21804
|
+
styles['--hover-close-button-opacity'] = hover.closeButtonOpacity.toString();
|
|
21805
|
+
// ========================================================================
|
|
21806
|
+
// ACTIVE STATES
|
|
21807
|
+
// ========================================================================
|
|
21808
|
+
const active = themeConfig.active;
|
|
21809
|
+
if (active.inputBorderColor)
|
|
21810
|
+
styles['--active-input-border-color'] = active.inputBorderColor;
|
|
21811
|
+
if (active.inputShadow)
|
|
21812
|
+
styles['--active-input-shadow'] = active.inputShadow;
|
|
21813
|
+
}
|
|
21814
|
+
else {
|
|
21815
|
+
// Fallback to legacy fields if no theme config
|
|
21816
|
+
if (appearance.primaryColor)
|
|
21817
|
+
styles['--primary-color'] = appearance.primaryColor;
|
|
21818
|
+
if (appearance.borderRadius !== undefined)
|
|
21819
|
+
styles['--border-radius'] = `${appearance.borderRadius}px`;
|
|
21820
|
+
// Legacy button
|
|
21821
|
+
if (appearance.button) {
|
|
21822
|
+
const btn = appearance.button;
|
|
21823
|
+
if (btn.color)
|
|
21824
|
+
styles['--button-color'] = btn.color;
|
|
21825
|
+
if (btn.size)
|
|
21826
|
+
styles['--button-size'] = `${btn.size}px`;
|
|
21827
|
+
if (btn.borderRadius !== undefined)
|
|
21828
|
+
styles['--button-border-radius'] = `${btn.borderRadius}px`;
|
|
21829
|
+
if (btn.borderWidth !== undefined)
|
|
21830
|
+
styles['--button-border-width'] = `${btn.borderWidth}px`;
|
|
21831
|
+
if (btn.borderColor)
|
|
21832
|
+
styles['--button-border-color'] = btn.borderColor;
|
|
21833
|
+
if (btn.opacity !== undefined)
|
|
21834
|
+
styles['--button-opacity'] = btn.opacity.toString();
|
|
21835
|
+
}
|
|
21836
|
+
}
|
|
21837
|
+
return styles;
|
|
21838
|
+
}
|
|
21839
|
+
|
|
21507
21840
|
function styleInject(css, ref) {
|
|
21508
21841
|
if ( ref === void 0 ) ref = {};
|
|
21509
21842
|
var insertAt = ref.insertAt;
|
|
@@ -21531,11 +21864,12 @@ function styleInject(css, ref) {
|
|
|
21531
21864
|
}
|
|
21532
21865
|
}
|
|
21533
21866
|
|
|
21534
|
-
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)}}";
|
|
21867
|
+
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)}}";
|
|
21535
21868
|
styleInject(css_248z);
|
|
21536
21869
|
|
|
21537
21870
|
const ChatWidget = ({ widgetId, apiKey, apiUrl = window.location.origin, position = 'bottom-right', theme: themeOverride, primaryColor, onOpen, onClose, onMessage, onError, }) => {
|
|
21538
21871
|
const [isOpen, setIsOpen] = react.useState(false);
|
|
21872
|
+
const widgetRef = react.useRef(null);
|
|
21539
21873
|
const { messages, isLoading, isTyping, error, config, sendMessage, submitFeedback, } = useChat({
|
|
21540
21874
|
widgetId,
|
|
21541
21875
|
apiKey,
|
|
@@ -21543,6 +21877,21 @@ const ChatWidget = ({ widgetId, apiKey, apiUrl = window.location.origin, positio
|
|
|
21543
21877
|
onMessage,
|
|
21544
21878
|
onError,
|
|
21545
21879
|
});
|
|
21880
|
+
// Debug logging
|
|
21881
|
+
react.useEffect(() => {
|
|
21882
|
+
console.log('[ChatWidget] Config loaded:', config ? 'YES' : 'NO');
|
|
21883
|
+
if (config) {
|
|
21884
|
+
console.log('[ChatWidget] Config details:', {
|
|
21885
|
+
theme: config.appearance?.theme,
|
|
21886
|
+
darkModeEnabled: config.appearance?.darkModeEnabled,
|
|
21887
|
+
hasLightMode: !!config.appearance?.lightMode,
|
|
21888
|
+
hasDarkMode: !!config.appearance?.darkMode,
|
|
21889
|
+
});
|
|
21890
|
+
}
|
|
21891
|
+
}, [config]);
|
|
21892
|
+
react.useEffect(() => {
|
|
21893
|
+
console.log('[ChatWidget] isOpen changed:', isOpen);
|
|
21894
|
+
}, [isOpen]);
|
|
21546
21895
|
// Handle auto-open
|
|
21547
21896
|
react.useEffect(() => {
|
|
21548
21897
|
if (config?.behavior.autoOpen) {
|
|
@@ -21555,26 +21904,84 @@ const ChatWidget = ({ widgetId, apiKey, apiUrl = window.location.origin, positio
|
|
|
21555
21904
|
}
|
|
21556
21905
|
return undefined;
|
|
21557
21906
|
}, [config, onOpen]);
|
|
21907
|
+
// Handle close on outside click
|
|
21908
|
+
react.useEffect(() => {
|
|
21909
|
+
if (!isOpen || !config?.appearance.closeOnOutsideClick)
|
|
21910
|
+
return;
|
|
21911
|
+
const handleClickOutside = (event) => {
|
|
21912
|
+
if (widgetRef.current && !widgetRef.current.contains(event.target)) {
|
|
21913
|
+
console.log('[ChatWidget] Closing due to outside click');
|
|
21914
|
+
setIsOpen(false);
|
|
21915
|
+
onClose?.();
|
|
21916
|
+
}
|
|
21917
|
+
};
|
|
21918
|
+
// Add slight delay to avoid immediate close on open
|
|
21919
|
+
const timer = setTimeout(() => {
|
|
21920
|
+
document.addEventListener('mousedown', handleClickOutside);
|
|
21921
|
+
}, 100);
|
|
21922
|
+
return () => {
|
|
21923
|
+
clearTimeout(timer);
|
|
21924
|
+
document.removeEventListener('mousedown', handleClickOutside);
|
|
21925
|
+
};
|
|
21926
|
+
}, [isOpen, config, onClose]);
|
|
21927
|
+
// Handle close on Escape key
|
|
21928
|
+
react.useEffect(() => {
|
|
21929
|
+
if (!isOpen || !config?.appearance.closeOnEscape)
|
|
21930
|
+
return;
|
|
21931
|
+
const handleEscapeKey = (event) => {
|
|
21932
|
+
if (event.key === 'Escape') {
|
|
21933
|
+
setIsOpen(false);
|
|
21934
|
+
onClose?.();
|
|
21935
|
+
}
|
|
21936
|
+
};
|
|
21937
|
+
document.addEventListener('keydown', handleEscapeKey);
|
|
21938
|
+
return () => document.removeEventListener('keydown', handleEscapeKey);
|
|
21939
|
+
}, [isOpen, config, onClose]);
|
|
21558
21940
|
// Determine theme
|
|
21559
|
-
const
|
|
21560
|
-
const
|
|
21561
|
-
|
|
21562
|
-
|
|
21941
|
+
const appearanceConfig = config?.appearance;
|
|
21942
|
+
const themeSetting = themeOverride || appearanceConfig?.theme || 'light';
|
|
21943
|
+
const canUseDarkMode = appearanceConfig?.darkModeEnabled !== false;
|
|
21944
|
+
// Only check system preference if dark mode is enabled
|
|
21945
|
+
const systemPrefersDark = canUseDarkMode && typeof window !== "undefined"
|
|
21946
|
+
? window.matchMedia('(prefers-color-scheme: dark)').matches
|
|
21947
|
+
: false;
|
|
21948
|
+
const effectiveTheme = !canUseDarkMode
|
|
21949
|
+
? 'light' // Force light mode if dark mode is disabled
|
|
21950
|
+
: themeSetting === 'auto'
|
|
21951
|
+
? (systemPrefersDark ? 'dark' : 'light')
|
|
21952
|
+
: themeSetting === 'dark'
|
|
21953
|
+
? 'dark'
|
|
21954
|
+
: 'light';
|
|
21563
21955
|
// Determine position (config takes priority over prop)
|
|
21564
21956
|
const effectivePosition = config?.appearance.position || position;
|
|
21565
|
-
// Apply custom styles
|
|
21566
|
-
|
|
21567
|
-
|
|
21568
|
-
|
|
21569
|
-
|
|
21570
|
-
if
|
|
21571
|
-
|
|
21572
|
-
|
|
21573
|
-
|
|
21574
|
-
|
|
21575
|
-
|
|
21957
|
+
// Apply custom styles from appearance configuration
|
|
21958
|
+
// Use the correct theme configuration (lightMode or darkMode)
|
|
21959
|
+
const customStyles = appearanceConfig
|
|
21960
|
+
? applyAppearanceStyles(appearanceConfig, effectiveTheme)
|
|
21961
|
+
: {};
|
|
21962
|
+
// Override with prop values if provided
|
|
21963
|
+
if (primaryColor) {
|
|
21964
|
+
customStyles['--primary-color'] = primaryColor;
|
|
21965
|
+
}
|
|
21966
|
+
// Debug logging for theme and styles
|
|
21967
|
+
react.useEffect(() => {
|
|
21968
|
+
console.log('[ChatWidget] Theme info:', {
|
|
21969
|
+
effectiveTheme,
|
|
21970
|
+
canUseDarkMode,
|
|
21971
|
+
themeSetting,
|
|
21972
|
+
systemPrefersDark,
|
|
21973
|
+
hasCustomStyles: Object.keys(customStyles).length > 0,
|
|
21974
|
+
buttonColor: customStyles['--button-color'],
|
|
21975
|
+
buttonSize: customStyles['--button-size'],
|
|
21976
|
+
cardBackground: customStyles['--card-background'],
|
|
21977
|
+
cardOpacity: customStyles['--card-opacity'],
|
|
21978
|
+
cardBorderRadius: customStyles['--card-border-radius'],
|
|
21979
|
+
});
|
|
21980
|
+
console.log('[ChatWidget] All CSS variables:', customStyles);
|
|
21981
|
+
}, [effectiveTheme, customStyles]);
|
|
21576
21982
|
const handleToggle = () => {
|
|
21577
21983
|
const newState = !isOpen;
|
|
21984
|
+
console.log('[ChatWidget] handleToggle called, setting isOpen to:', newState);
|
|
21578
21985
|
setIsOpen(newState);
|
|
21579
21986
|
if (newState) {
|
|
21580
21987
|
onOpen?.();
|
|
@@ -21586,10 +21993,13 @@ const ChatWidget = ({ widgetId, apiKey, apiUrl = window.location.origin, positio
|
|
|
21586
21993
|
const handleFeedback = async (messageId, feedback) => {
|
|
21587
21994
|
await submitFeedback(messageId, feedback);
|
|
21588
21995
|
};
|
|
21589
|
-
|
|
21590
|
-
|
|
21591
|
-
|
|
21592
|
-
|
|
21996
|
+
// Don't render until config is loaded to avoid flash of unstyled content
|
|
21997
|
+
if (!config) {
|
|
21998
|
+
console.log('[ChatWidget] Not rendering - config not loaded yet');
|
|
21999
|
+
return null;
|
|
22000
|
+
}
|
|
22001
|
+
console.log('[ChatWidget] Rendering widget', { isOpen, hasConfig: !!config });
|
|
22002
|
+
return (jsxRuntime.jsx("div", { className: `ai-chat-widget ${effectiveTheme}`, style: customStyles, children: jsxRuntime.jsxs("div", { ref: widgetRef, className: `ai-chat-widget-container ${effectivePosition}`, children: [isOpen && (jsxRuntime.jsx(ChatWindow, { messages: messages, isLoading: isLoading, isTyping: isTyping, error: error, config: config, onSendMessage: sendMessage, onClose: handleToggle, onFeedback: handleFeedback })), !isOpen && (jsxRuntime.jsx("button", { className: "ai-chat-button", onClick: handleToggle, "aria-label": "Open chat", children: config?.appearance.buttonIcon ? (jsxRuntime.jsx("span", { className: "ai-chat-button-icon", children: config.appearance.buttonIcon })) : (jsxRuntime.jsx("svg", { className: "ai-chat-button-svg", viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "2", strokeLinecap: "round", strokeLinejoin: "round", children: jsxRuntime.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" }) })) }))] }) }));
|
|
21593
22003
|
};
|
|
21594
22004
|
|
|
21595
22005
|
exports.ApiError = ApiError;
|