@chatwidgetai/chat-widget 0.1.6 → 0.1.7
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/ai-chat-widget.umd.js +39 -293
- package/dist/ai-chat-widget.umd.js.map +1 -1
- package/dist/components/ChatWidget.d.ts.map +1 -1
- package/dist/components/ChatWindow.d.ts.map +1 -1
- package/dist/hooks/useChat.d.ts.map +1 -1
- package/dist/index.d.ts +1 -1
- package/dist/index.d.ts.map +1 -1
- package/dist/index.esm.js +39 -292
- package/dist/index.esm.js.map +1 -1
- package/dist/index.js +39 -292
- package/dist/index.js.map +1 -1
- package/dist/types/index.d.ts +5 -121
- package/dist/types/index.d.ts.map +1 -1
- package/dist/umd.d.ts +0 -1
- package/dist/umd.d.ts.map +1 -1
- package/dist/utils/applyAppearanceStyles.d.ts +3 -3
- package/dist/utils/applyAppearanceStyles.d.ts.map +1 -1
- package/dist/utils/autoThemeDetector.d.ts.map +1 -1
- package/package.json +1 -1
package/dist/index.js
CHANGED
|
@@ -417,8 +417,6 @@ function useChat(options) {
|
|
|
417
417
|
const config = await apiClient.current.getConfig();
|
|
418
418
|
console.log('[useChat] Config fetched successfully:', {
|
|
419
419
|
hasAppearance: !!config.appearance,
|
|
420
|
-
hasLightMode: !!config.appearance?.lightMode,
|
|
421
|
-
hasDarkMode: !!config.appearance?.darkMode,
|
|
422
420
|
});
|
|
423
421
|
const persistConversation = config.behavior.persistConversation ?? true;
|
|
424
422
|
let conversationId = '';
|
|
@@ -21578,20 +21576,17 @@ const ChatWindow = ({ messages, isLoading, isTyping, error, config, onSendMessag
|
|
|
21578
21576
|
console.log('[ChatWindow] Rendering ChatWindow component');
|
|
21579
21577
|
const appearance = config?.appearance;
|
|
21580
21578
|
const behavior = config?.behavior;
|
|
21579
|
+
// Use simplified appearance fields
|
|
21581
21580
|
const size = appearance?.size || 'medium';
|
|
21582
|
-
|
|
21583
|
-
|
|
21584
|
-
const
|
|
21585
|
-
|
|
21586
|
-
|
|
21587
|
-
|
|
21588
|
-
|
|
21589
|
-
|
|
21590
|
-
|
|
21591
|
-
const headerTitle = themeConfig?.header?.title ?? appearance?.header?.title ?? appearance?.companyName ?? 'AI Assistant';
|
|
21592
|
-
const welcomeTitle = themeConfig?.chat?.welcomeTitle ?? 'Welcome!';
|
|
21593
|
-
const welcomeMessage = themeConfig?.chat?.welcomeMessage ?? appearance?.welcomeMessage ?? '👋 Hi there! How can I assist you today?';
|
|
21594
|
-
const inputPlaceholder = themeConfig?.footer?.inputPlaceholder ?? appearance?.placeholder ?? 'Ask me anything...';
|
|
21581
|
+
const headerTitle = appearance?.headerTitle || 'AI Assistant';
|
|
21582
|
+
const welcomeMessage = appearance?.welcomeMessage || '👋 Hi there! How can I assist you today?';
|
|
21583
|
+
const inputPlaceholder = appearance?.placeholder || 'Ask me anything...';
|
|
21584
|
+
console.log('[ChatWindow] Appearance values:', {
|
|
21585
|
+
size,
|
|
21586
|
+
headerTitle,
|
|
21587
|
+
welcomeMessage,
|
|
21588
|
+
inputPlaceholder,
|
|
21589
|
+
});
|
|
21595
21590
|
// Track if suggested questions should be shown
|
|
21596
21591
|
const [showSuggestedQuestions, setShowSuggestedQuestions] = react.useState(true);
|
|
21597
21592
|
// Hide suggested questions after first user message
|
|
@@ -21611,241 +21606,25 @@ const ChatWindow = ({ messages, isLoading, isTyping, error, config, onSendMessag
|
|
|
21611
21606
|
onSendMessage(question);
|
|
21612
21607
|
};
|
|
21613
21608
|
const hasMessages = messages.length > 0;
|
|
21614
|
-
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": "Minimize chat", children: jsxRuntime.jsx(MinimizeIcon, {}) })] }), 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"] })), isLimitReached && (jsxRuntime.jsx("div", { className: "ai-chat-error", role: "alert", children: "Message limit reached. 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,
|
|
21609
|
+
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": "Minimize chat", children: jsxRuntime.jsx(MinimizeIcon, {}) })] }), 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"] })), isLimitReached && (jsxRuntime.jsx("div", { className: "ai-chat-error", role: "alert", children: "Message limit reached. 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, welcomeMessage: welcomeMessage, onFeedback: onFeedback }), showSuggestedQuestions && !hasMessages && 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 })] }));
|
|
21615
21610
|
};
|
|
21616
21611
|
|
|
21617
|
-
/**
|
|
21618
|
-
* Convert shadow size to CSS box-shadow value
|
|
21619
|
-
*/
|
|
21620
|
-
function getShadowValue(size) {
|
|
21621
|
-
const shadows = {
|
|
21622
|
-
'none': 'none',
|
|
21623
|
-
'sm': '0 1px 2px 0 rgba(0, 0, 0, 0.05)',
|
|
21624
|
-
'md': '0 4px 6px -1px rgba(0, 0, 0, 0.1), 0 2px 4px -1px rgba(0, 0, 0, 0.06)',
|
|
21625
|
-
'lg': '0 10px 15px -3px rgba(0, 0, 0, 0.1), 0 4px 6px -2px rgba(0, 0, 0, 0.05)',
|
|
21626
|
-
'xl': '0 20px 25px -5px rgba(0, 0, 0, 0.1), 0 10px 10px -5px rgba(0, 0, 0, 0.04)',
|
|
21627
|
-
'2xl': '0 25px 50px -12px rgba(0, 0, 0, 0.25)',
|
|
21628
|
-
};
|
|
21629
|
-
return shadows[size] || shadows.none;
|
|
21630
|
-
}
|
|
21631
21612
|
/**
|
|
21632
21613
|
* Apply appearance configuration as CSS custom properties
|
|
21633
|
-
*
|
|
21614
|
+
* Simplified to only handle flat appearance schema
|
|
21634
21615
|
*
|
|
21635
21616
|
* @param appearance - Widget appearance configuration
|
|
21636
|
-
* @param theme - Current theme ('light' or 'dark')
|
|
21617
|
+
* @param theme - Current theme ('light' or 'dark') - kept for compatibility but not used for theme selection
|
|
21637
21618
|
*/
|
|
21638
|
-
function applyAppearanceStyles(appearance
|
|
21619
|
+
function applyAppearanceStyles(appearance) {
|
|
21639
21620
|
const styles = {};
|
|
21640
|
-
//
|
|
21641
|
-
if (appearance.
|
|
21642
|
-
styles
|
|
21643
|
-
}
|
|
21644
|
-
// Select the correct theme configuration
|
|
21645
|
-
const themeConfig = theme === 'dark' ? appearance.darkMode : appearance.lightMode;
|
|
21646
|
-
// If theme config exists and has required properties, use it
|
|
21647
|
-
if (themeConfig && themeConfig.button) {
|
|
21648
|
-
// ========================================================================
|
|
21649
|
-
// BUTTON APPEARANCE
|
|
21650
|
-
// ========================================================================
|
|
21651
|
-
const btn = themeConfig.button;
|
|
21652
|
-
if (btn.color)
|
|
21653
|
-
styles['--button-color'] = btn.color;
|
|
21654
|
-
if (btn.opacity !== undefined)
|
|
21655
|
-
styles['--button-opacity'] = btn.opacity.toString();
|
|
21656
|
-
if (btn.size)
|
|
21657
|
-
styles['--button-size'] = `${btn.size}px`;
|
|
21658
|
-
if (btn.icon)
|
|
21659
|
-
styles['--button-icon'] = btn.icon;
|
|
21660
|
-
if (btn.iconColor)
|
|
21661
|
-
styles['--button-icon-color'] = btn.iconColor;
|
|
21662
|
-
if (btn.borderRadius !== undefined)
|
|
21663
|
-
styles['--button-border-radius'] = `${btn.borderRadius}px`;
|
|
21664
|
-
if (btn.borderWidth !== undefined)
|
|
21665
|
-
styles['--button-border-width'] = `${btn.borderWidth}px`;
|
|
21666
|
-
if (btn.borderColor)
|
|
21667
|
-
styles['--button-border-color'] = btn.borderColor;
|
|
21668
|
-
if (btn.borderOpacity !== undefined)
|
|
21669
|
-
styles['--button-border-opacity'] = btn.borderOpacity.toString();
|
|
21670
|
-
if (btn.backdropBlur !== undefined)
|
|
21671
|
-
styles['--button-backdrop-blur'] = `${btn.backdropBlur}px`;
|
|
21672
|
-
if (btn.shadow)
|
|
21673
|
-
styles['--button-shadow'] = getShadowValue(btn.shadow);
|
|
21674
|
-
// ========================================================================
|
|
21675
|
-
// CARD/WINDOW APPEARANCE
|
|
21676
|
-
// ========================================================================
|
|
21677
|
-
const card = themeConfig.card;
|
|
21678
|
-
if (card.backgroundColor)
|
|
21679
|
-
styles['--card-background'] = card.backgroundColor;
|
|
21680
|
-
if (card.opacity !== undefined)
|
|
21681
|
-
styles['--card-opacity'] = card.opacity.toString();
|
|
21682
|
-
if (card.borderRadius !== undefined)
|
|
21683
|
-
styles['--card-border-radius'] = `${card.borderRadius}px`;
|
|
21684
|
-
if (card.borderWidth !== undefined)
|
|
21685
|
-
styles['--card-border-width'] = `${card.borderWidth}px`;
|
|
21686
|
-
if (card.borderColor) {
|
|
21687
|
-
styles['--card-border-color'] = card.borderColor;
|
|
21688
|
-
// Create rgba border color with opacity for box-shadow
|
|
21689
|
-
if (card.borderOpacity !== undefined) {
|
|
21690
|
-
const opacity = card.borderOpacity;
|
|
21691
|
-
// Convert hex to rgba
|
|
21692
|
-
const hex = card.borderColor.replace('#', '');
|
|
21693
|
-
const r = parseInt(hex.substring(0, 2), 16);
|
|
21694
|
-
const g = parseInt(hex.substring(2, 4), 16);
|
|
21695
|
-
const b = parseInt(hex.substring(4, 6), 16);
|
|
21696
|
-
styles['--card-border-color-rgba'] = `rgba(${r}, ${g}, ${b}, ${opacity})`;
|
|
21697
|
-
}
|
|
21698
|
-
}
|
|
21699
|
-
if (card.borderOpacity !== undefined)
|
|
21700
|
-
styles['--card-border-opacity'] = card.borderOpacity.toString();
|
|
21701
|
-
if (card.backdropBlur !== undefined)
|
|
21702
|
-
styles['--card-backdrop-blur'] = `${card.backdropBlur}px`;
|
|
21703
|
-
if (card.shadow)
|
|
21704
|
-
styles['--card-shadow'] = getShadowValue(card.shadow);
|
|
21705
|
-
// ========================================================================
|
|
21706
|
-
// HEADER APPEARANCE
|
|
21707
|
-
// ========================================================================
|
|
21708
|
-
const header = themeConfig.header;
|
|
21709
|
-
if (header.backgroundColor)
|
|
21710
|
-
styles['--header-background'] = header.backgroundColor;
|
|
21711
|
-
if (header.opacity !== undefined)
|
|
21712
|
-
styles['--header-opacity'] = header.opacity.toString();
|
|
21713
|
-
if (header.textColor)
|
|
21714
|
-
styles['--header-text-color'] = header.textColor;
|
|
21715
|
-
if (header.borderBottomWidth !== undefined)
|
|
21716
|
-
styles['--header-border-bottom-width'] = `${header.borderBottomWidth}px`;
|
|
21717
|
-
if (header.borderBottomColor)
|
|
21718
|
-
styles['--header-border-bottom-color'] = header.borderBottomColor;
|
|
21719
|
-
if (header.borderBottomOpacity !== undefined)
|
|
21720
|
-
styles['--header-border-bottom-opacity'] = header.borderBottomOpacity.toString();
|
|
21721
|
-
// ========================================================================
|
|
21722
|
-
// CHAT APPEARANCE
|
|
21723
|
-
// ========================================================================
|
|
21724
|
-
const chat = themeConfig.chat;
|
|
21725
|
-
if (chat.backgroundColor)
|
|
21726
|
-
styles['--chat-background'] = chat.backgroundColor;
|
|
21727
|
-
if (chat.opacity !== undefined)
|
|
21728
|
-
styles['--chat-opacity'] = chat.opacity.toString();
|
|
21729
|
-
// Welcome message
|
|
21730
|
-
if (chat.welcomeColor)
|
|
21731
|
-
styles['--welcome-color'] = chat.welcomeColor;
|
|
21732
|
-
// Message bubbles
|
|
21733
|
-
if (chat.enableBubbles) {
|
|
21734
|
-
if (chat.bubbleUserColor)
|
|
21735
|
-
styles['--bubble-user-color'] = chat.bubbleUserColor;
|
|
21736
|
-
if (chat.bubbleUserOpacity !== undefined)
|
|
21737
|
-
styles['--bubble-user-opacity'] = chat.bubbleUserOpacity.toString();
|
|
21738
|
-
if (chat.bubbleAssistantColor)
|
|
21739
|
-
styles['--bubble-assistant-color'] = chat.bubbleAssistantColor;
|
|
21740
|
-
if (chat.bubbleAssistantOpacity !== undefined)
|
|
21741
|
-
styles['--bubble-assistant-opacity'] = chat.bubbleAssistantOpacity.toString();
|
|
21742
|
-
if (chat.bubbleBorderWidth !== undefined)
|
|
21743
|
-
styles['--bubble-border-width'] = `${chat.bubbleBorderWidth}px`;
|
|
21744
|
-
if (chat.bubbleBorderColor)
|
|
21745
|
-
styles['--bubble-border-color'] = chat.bubbleBorderColor;
|
|
21746
|
-
if (chat.bubbleBorderOpacity !== undefined)
|
|
21747
|
-
styles['--bubble-border-opacity'] = chat.bubbleBorderOpacity.toString();
|
|
21748
|
-
}
|
|
21749
|
-
else {
|
|
21750
|
-
// Plain text mode
|
|
21751
|
-
if (chat.textColor)
|
|
21752
|
-
styles['--message-text-color'] = chat.textColor;
|
|
21753
|
-
}
|
|
21754
|
-
// ========================================================================
|
|
21755
|
-
// FOOTER APPEARANCE
|
|
21756
|
-
// ========================================================================
|
|
21757
|
-
const footer = themeConfig.footer;
|
|
21758
|
-
// Only if separate from chat
|
|
21759
|
-
if (footer.separateFromChat) {
|
|
21760
|
-
if (footer.backgroundColor)
|
|
21761
|
-
styles['--footer-background'] = footer.backgroundColor;
|
|
21762
|
-
if (footer.opacity !== undefined)
|
|
21763
|
-
styles['--footer-opacity'] = footer.opacity.toString();
|
|
21764
|
-
if (footer.borderTopWidth !== undefined)
|
|
21765
|
-
styles['--footer-border-top-width'] = `${footer.borderTopWidth}px`;
|
|
21766
|
-
if (footer.borderTopColor)
|
|
21767
|
-
styles['--footer-border-top-color'] = footer.borderTopColor;
|
|
21768
|
-
if (footer.borderTopOpacity !== undefined)
|
|
21769
|
-
styles['--footer-border-top-opacity'] = footer.borderTopOpacity.toString();
|
|
21770
|
-
}
|
|
21771
|
-
// Backdrop blur (only when floating)
|
|
21772
|
-
if (!footer.separateFromChat && footer.backdropBlur !== undefined) {
|
|
21773
|
-
styles['--footer-backdrop-blur'] = `${footer.backdropBlur}px`;
|
|
21774
|
-
}
|
|
21775
|
-
// Input field
|
|
21776
|
-
if (footer.inputBackgroundColor)
|
|
21777
|
-
styles['--input-background'] = footer.inputBackgroundColor;
|
|
21778
|
-
if (footer.inputBackgroundOpacity !== undefined)
|
|
21779
|
-
styles['--input-background-opacity'] = footer.inputBackgroundOpacity.toString();
|
|
21780
|
-
if (footer.inputBorderRadius !== undefined)
|
|
21781
|
-
styles['--input-border-radius'] = `${footer.inputBorderRadius}px`;
|
|
21782
|
-
if (footer.inputBorderWidth !== undefined)
|
|
21783
|
-
styles['--input-border-width'] = `${footer.inputBorderWidth}px`;
|
|
21784
|
-
if (footer.inputBorderColor)
|
|
21785
|
-
styles['--input-border-color'] = footer.inputBorderColor;
|
|
21786
|
-
if (footer.inputBorderOpacity !== undefined)
|
|
21787
|
-
styles['--input-border-opacity'] = footer.inputBorderOpacity.toString();
|
|
21788
|
-
if (footer.inputShadow)
|
|
21789
|
-
styles['--input-shadow'] = getShadowValue(footer.inputShadow);
|
|
21790
|
-
// Send button
|
|
21791
|
-
if (footer.buttonBackgroundColor)
|
|
21792
|
-
styles['--send-button-background'] = footer.buttonBackgroundColor;
|
|
21793
|
-
if (footer.buttonOpacity !== undefined)
|
|
21794
|
-
styles['--send-button-opacity'] = footer.buttonOpacity.toString();
|
|
21795
|
-
if (footer.buttonBorderRadius !== undefined)
|
|
21796
|
-
styles['--send-button-border-radius'] = `${footer.buttonBorderRadius}px`;
|
|
21797
|
-
if (footer.buttonBorderWidth !== undefined)
|
|
21798
|
-
styles['--send-button-border-width'] = `${footer.buttonBorderWidth}px`;
|
|
21799
|
-
if (footer.buttonBorderColor)
|
|
21800
|
-
styles['--send-button-border-color'] = footer.buttonBorderColor;
|
|
21801
|
-
if (footer.buttonBorderOpacity !== undefined)
|
|
21802
|
-
styles['--send-button-border-opacity'] = footer.buttonBorderOpacity.toString();
|
|
21803
|
-
// ========================================================================
|
|
21804
|
-
// HOVER STATES
|
|
21805
|
-
// ========================================================================
|
|
21806
|
-
const hover = themeConfig.hover;
|
|
21807
|
-
if (hover.buttonScale !== undefined)
|
|
21808
|
-
styles['--hover-button-scale'] = hover.buttonScale.toString();
|
|
21809
|
-
if (hover.buttonOpacity !== undefined)
|
|
21810
|
-
styles['--hover-button-opacity'] = hover.buttonOpacity.toString();
|
|
21811
|
-
if (hover.inputBorderColor)
|
|
21812
|
-
styles['--hover-input-border-color'] = hover.inputBorderColor;
|
|
21813
|
-
if (hover.sendButtonOpacity !== undefined)
|
|
21814
|
-
styles['--hover-send-button-opacity'] = hover.sendButtonOpacity.toString();
|
|
21815
|
-
if (hover.closeButtonOpacity !== undefined)
|
|
21816
|
-
styles['--hover-close-button-opacity'] = hover.closeButtonOpacity.toString();
|
|
21817
|
-
// ========================================================================
|
|
21818
|
-
// ACTIVE STATES
|
|
21819
|
-
// ========================================================================
|
|
21820
|
-
const active = themeConfig.active;
|
|
21821
|
-
if (active.inputBorderColor)
|
|
21822
|
-
styles['--active-input-border-color'] = active.inputBorderColor;
|
|
21823
|
-
if (active.inputShadow)
|
|
21824
|
-
styles['--active-input-shadow'] = active.inputShadow;
|
|
21825
|
-
}
|
|
21826
|
-
else {
|
|
21827
|
-
// Fallback to legacy fields if no theme config
|
|
21828
|
-
if (appearance.primaryColor)
|
|
21829
|
-
styles['--primary-color'] = appearance.primaryColor;
|
|
21830
|
-
if (appearance.borderRadius !== undefined)
|
|
21831
|
-
styles['--border-radius'] = `${appearance.borderRadius}px`;
|
|
21832
|
-
// Legacy button
|
|
21833
|
-
if (appearance.button) {
|
|
21834
|
-
const btn = appearance.button;
|
|
21835
|
-
if (btn.color)
|
|
21836
|
-
styles['--button-color'] = btn.color;
|
|
21837
|
-
if (btn.size)
|
|
21838
|
-
styles['--button-size'] = `${btn.size}px`;
|
|
21839
|
-
if (btn.borderRadius !== undefined)
|
|
21840
|
-
styles['--button-border-radius'] = `${btn.borderRadius}px`;
|
|
21841
|
-
if (btn.borderWidth !== undefined)
|
|
21842
|
-
styles['--button-border-width'] = `${btn.borderWidth}px`;
|
|
21843
|
-
if (btn.borderColor)
|
|
21844
|
-
styles['--button-border-color'] = btn.borderColor;
|
|
21845
|
-
if (btn.opacity !== undefined)
|
|
21846
|
-
styles['--button-opacity'] = btn.opacity.toString();
|
|
21847
|
-
}
|
|
21621
|
+
// Apply primary color
|
|
21622
|
+
if (appearance.primaryColor) {
|
|
21623
|
+
styles['--primary-color'] = appearance.primaryColor;
|
|
21848
21624
|
}
|
|
21625
|
+
// Note: All legacy theme system code (lightMode, darkMode, ThemeAppearanceConfig)
|
|
21626
|
+
// has been removed. The widget now uses a simplified flat appearance schema.
|
|
21627
|
+
// Theme-specific styling is handled by generateThemeStyles() using auto-detected theme.
|
|
21849
21628
|
return styles;
|
|
21850
21629
|
}
|
|
21851
21630
|
|
|
@@ -22207,19 +21986,23 @@ function detectTheme(element) {
|
|
|
22207
21986
|
* Create a MutationObserver to watch for theme changes
|
|
22208
21987
|
*/
|
|
22209
21988
|
function createThemeObserver(element, callback) {
|
|
21989
|
+
let lastTheme = detectTheme(element);
|
|
22210
21990
|
const observer = new MutationObserver(() => {
|
|
22211
21991
|
const theme = detectTheme(element);
|
|
22212
|
-
|
|
21992
|
+
if (theme !== lastTheme) {
|
|
21993
|
+
lastTheme = theme;
|
|
21994
|
+
callback(theme);
|
|
21995
|
+
}
|
|
22213
21996
|
});
|
|
22214
21997
|
// Observe body for class/style changes (common for theme switching)
|
|
22215
21998
|
observer.observe(document.body, {
|
|
22216
21999
|
attributes: true,
|
|
22217
|
-
attributeFilter: ['class', 'style', 'data-theme'],
|
|
22000
|
+
attributeFilter: ['class', 'style', 'data-theme', 'data-bs-theme'],
|
|
22218
22001
|
});
|
|
22219
22002
|
// Also observe html element
|
|
22220
22003
|
observer.observe(document.documentElement, {
|
|
22221
22004
|
attributes: true,
|
|
22222
|
-
attributeFilter: ['class', 'style', 'data-theme'],
|
|
22005
|
+
attributeFilter: ['class', 'style', 'data-theme', 'data-bs-theme'],
|
|
22223
22006
|
});
|
|
22224
22007
|
return observer;
|
|
22225
22008
|
}
|
|
@@ -22260,19 +22043,9 @@ styleInject(css_248z);
|
|
|
22260
22043
|
// Icon components mapping
|
|
22261
22044
|
const iconComponents = {
|
|
22262
22045
|
FiMessageCircle: () => (jsxRuntime.jsx("svg", { viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "2", strokeLinecap: "round", strokeLinejoin: "round", children: jsxRuntime.jsx("path", { d: "M21 11.5a8.38 8.38 0 0 1-.9 3.8 8.5 8.5 0 0 1-7.6 4.7 8.38 8.38 0 0 1-3.8-.9L3 21l1.9-5.7a8.38 8.38 0 0 1-.9-3.8 8.5 8.5 0 0 1 4.7-7.6 8.38 8.38 0 0 1 3.8-.9h.5a8.48 8.48 0 0 1 8 8v.5z" }) })),
|
|
22263
|
-
FiMessageSquare: () => (jsxRuntime.jsx("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" }) })),
|
|
22264
|
-
FiMail: () => (jsxRuntime.jsxs("svg", { viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "2", strokeLinecap: "round", strokeLinejoin: "round", children: [jsxRuntime.jsx("path", { d: "M4 4h16c1.1 0 2 .9 2 2v12c0 1.1-.9 2-2 2H4c-1.1 0-2-.9-2-2V6c0-1.1.9-2 2-2z" }), jsxRuntime.jsx("polyline", { points: "22,6 12,13 2,6" })] })),
|
|
22265
|
-
FiPhone: () => (jsxRuntime.jsx("svg", { viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "2", strokeLinecap: "round", strokeLinejoin: "round", children: jsxRuntime.jsx("path", { d: "M22 16.92v3a2 2 0 0 1-2.18 2 19.79 19.79 0 0 1-8.63-3.07 19.5 19.5 0 0 1-6-6 19.79 19.79 0 0 1-3.07-8.67A2 2 0 0 1 4.11 2h3a2 2 0 0 1 2 1.72 12.84 12.84 0 0 0 .7 2.81 2 2 0 0 1-.45 2.11L8.09 9.91a16 16 0 0 0 6 6l1.27-1.27a2 2 0 0 1 2.11-.45 12.84 12.84 0 0 0 2.81.7A2 2 0 0 1 22 16.92z" }) })),
|
|
22266
|
-
FiHelpCircle: () => (jsxRuntime.jsxs("svg", { viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "2", strokeLinecap: "round", strokeLinejoin: "round", children: [jsxRuntime.jsx("circle", { cx: "12", cy: "12", r: "10" }), jsxRuntime.jsx("path", { d: "M9.09 9a3 3 0 0 1 5.83 1c0 2-3 3-3 3" }), jsxRuntime.jsx("line", { x1: "12", y1: "17", x2: "12.01", y2: "17" })] })),
|
|
22267
|
-
FiZap: () => (jsxRuntime.jsx("svg", { viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "2", strokeLinecap: "round", strokeLinejoin: "round", children: jsxRuntime.jsx("polygon", { points: "13 2 3 14 12 14 11 22 21 10 12 10 13 2" }) })),
|
|
22268
|
-
FiSend: () => (jsxRuntime.jsxs("svg", { 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" })] })),
|
|
22269
|
-
FiUser: () => (jsxRuntime.jsxs("svg", { viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "2", strokeLinecap: "round", strokeLinejoin: "round", children: [jsxRuntime.jsx("path", { d: "M20 21v-2a4 4 0 0 0-4-4H8a4 4 0 0 0-4 4v2" }), jsxRuntime.jsx("circle", { cx: "12", cy: "7", r: "4" })] })),
|
|
22270
|
-
FiUsers: () => (jsxRuntime.jsxs("svg", { viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "2", strokeLinecap: "round", strokeLinejoin: "round", children: [jsxRuntime.jsx("path", { d: "M17 21v-2a4 4 0 0 0-4-4H5a4 4 0 0 0-4 4v2" }), jsxRuntime.jsx("circle", { cx: "9", cy: "7", r: "4" }), jsxRuntime.jsx("path", { d: "M23 21v-2a4 4 0 0 0-3-3.87" }), jsxRuntime.jsx("path", { d: "M16 3.13a4 4 0 0 1 0 7.75" })] })),
|
|
22271
|
-
FiHeadphones: () => (jsxRuntime.jsxs("svg", { viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "2", strokeLinecap: "round", strokeLinejoin: "round", children: [jsxRuntime.jsx("path", { d: "M3 18v-6a9 9 0 0 1 18 0v6" }), jsxRuntime.jsx("path", { d: "M21 19a2 2 0 0 1-2 2h-1a2 2 0 0 1-2-2v-3a2 2 0 0 1 2-2h3zM3 19a2 2 0 0 0 2 2h1a2 2 0 0 0 2-2v-3a2 2 0 0 0-2-2H3z" })] })),
|
|
22272
|
-
FiCpu: () => (jsxRuntime.jsxs("svg", { viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "2", strokeLinecap: "round", strokeLinejoin: "round", children: [jsxRuntime.jsx("rect", { x: "4", y: "4", width: "16", height: "16", rx: "2", ry: "2" }), jsxRuntime.jsx("rect", { x: "9", y: "9", width: "6", height: "6" }), jsxRuntime.jsx("line", { x1: "9", y1: "1", x2: "9", y2: "4" }), jsxRuntime.jsx("line", { x1: "15", y1: "1", x2: "15", y2: "4" }), jsxRuntime.jsx("line", { x1: "9", y1: "20", x2: "9", y2: "23" }), jsxRuntime.jsx("line", { x1: "15", y1: "20", x2: "15", y2: "23" }), jsxRuntime.jsx("line", { x1: "20", y1: "9", x2: "23", y2: "9" }), jsxRuntime.jsx("line", { x1: "20", y1: "14", x2: "23", y2: "14" }), jsxRuntime.jsx("line", { x1: "1", y1: "9", x2: "4", y2: "9" }), jsxRuntime.jsx("line", { x1: "1", y1: "14", x2: "4", y2: "14" })] })),
|
|
22273
22046
|
FiChevronDown: () => (jsxRuntime.jsx("svg", { viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "2.5", strokeLinecap: "round", strokeLinejoin: "round", children: jsxRuntime.jsx("polyline", { points: "6 9 12 15 18 9" }) })),
|
|
22274
22047
|
};
|
|
22275
|
-
const ChatWidget = ({ widgetId, apiUrl = window.location.origin, position = 'bottom-right',
|
|
22048
|
+
const ChatWidget = ({ widgetId, apiUrl = window.location.origin, position = 'bottom-right', primaryColor, onOpen, onClose, onMessage, onError, }) => {
|
|
22276
22049
|
const [isOpen, setIsOpen] = react.useState(false);
|
|
22277
22050
|
const [autoDetectedTheme, setAutoDetectedTheme] = react.useState('light');
|
|
22278
22051
|
const widgetRef = react.useRef(null);
|
|
@@ -22313,7 +22086,6 @@ const ChatWidget = ({ widgetId, apiUrl = window.location.origin, position = 'bot
|
|
|
22313
22086
|
console.log('[ChatWidget] Config loaded:', config ? 'YES' : 'NO');
|
|
22314
22087
|
if (config) {
|
|
22315
22088
|
console.log('[ChatWidget] Config details:', {
|
|
22316
|
-
theme: config.appearance?.theme,
|
|
22317
22089
|
accentColor: config.appearance?.primaryColor,
|
|
22318
22090
|
autoDetectedTheme,
|
|
22319
22091
|
});
|
|
@@ -22353,7 +22125,7 @@ const ChatWidget = ({ widgetId, apiUrl = window.location.origin, position = 'bot
|
|
|
22353
22125
|
}, [isOpen, onClose]);
|
|
22354
22126
|
// Handle close on Escape key
|
|
22355
22127
|
react.useEffect(() => {
|
|
22356
|
-
if (!isOpen
|
|
22128
|
+
if (!isOpen)
|
|
22357
22129
|
return;
|
|
22358
22130
|
const handleEscapeKey = (event) => {
|
|
22359
22131
|
if (event.key === 'Escape') {
|
|
@@ -22363,16 +22135,10 @@ const ChatWidget = ({ widgetId, apiUrl = window.location.origin, position = 'bot
|
|
|
22363
22135
|
};
|
|
22364
22136
|
document.addEventListener('keydown', handleEscapeKey);
|
|
22365
22137
|
return () => document.removeEventListener('keydown', handleEscapeKey);
|
|
22366
|
-
}, [isOpen,
|
|
22367
|
-
// Determine theme -
|
|
22138
|
+
}, [isOpen, onClose]);
|
|
22139
|
+
// Determine theme - always auto-detect from background
|
|
22368
22140
|
const appearanceConfig = config?.appearance;
|
|
22369
|
-
const
|
|
22370
|
-
// Use auto-detected theme, or explicit override
|
|
22371
|
-
const effectiveTheme = themeSetting === 'auto'
|
|
22372
|
-
? autoDetectedTheme
|
|
22373
|
-
: themeSetting === 'dark'
|
|
22374
|
-
? 'dark'
|
|
22375
|
-
: 'light';
|
|
22141
|
+
const effectiveTheme = autoDetectedTheme;
|
|
22376
22142
|
// Determine position (config takes priority over prop)
|
|
22377
22143
|
const effectivePosition = config?.appearance.position || position;
|
|
22378
22144
|
// Get accent color from config or prop
|
|
@@ -22381,17 +22147,15 @@ const ChatWidget = ({ widgetId, apiUrl = window.location.origin, position = 'bot
|
|
|
22381
22147
|
const simpleAppearance = {
|
|
22382
22148
|
accentColor,
|
|
22383
22149
|
size: appearanceConfig?.size || 'small',
|
|
22384
|
-
|
|
22385
|
-
|
|
22386
|
-
|
|
22387
|
-
headerTitle: appearanceConfig?.lightMode?.header?.title,
|
|
22388
|
-
buttonIcon: appearanceConfig?.buttonIcon || appearanceConfig?.lightMode?.button?.icon,
|
|
22150
|
+
welcomeMessage: appearanceConfig?.welcomeMessage || '',
|
|
22151
|
+
placeholder: appearanceConfig?.placeholder || '',
|
|
22152
|
+
headerTitle: appearanceConfig?.headerTitle || '',
|
|
22389
22153
|
};
|
|
22390
22154
|
// Generate theme styles from accent color
|
|
22391
22155
|
const generatedStyles = generateThemeStyles(simpleAppearance, effectiveTheme);
|
|
22392
22156
|
// Also apply legacy styles for backward compatibility
|
|
22393
22157
|
const legacyStyles = appearanceConfig
|
|
22394
|
-
? applyAppearanceStyles(appearanceConfig
|
|
22158
|
+
? applyAppearanceStyles(appearanceConfig)
|
|
22395
22159
|
: {};
|
|
22396
22160
|
// Merge styles (generated takes priority for new simplified system)
|
|
22397
22161
|
const customStyles = {
|
|
@@ -22403,10 +22167,9 @@ const ChatWidget = ({ widgetId, apiUrl = window.location.origin, position = 'bot
|
|
|
22403
22167
|
console.log('[ChatWidget] Theme info:', {
|
|
22404
22168
|
effectiveTheme,
|
|
22405
22169
|
autoDetectedTheme,
|
|
22406
|
-
themeSetting,
|
|
22407
22170
|
accentColor,
|
|
22408
22171
|
});
|
|
22409
|
-
}, [effectiveTheme, autoDetectedTheme,
|
|
22172
|
+
}, [effectiveTheme, autoDetectedTheme, accentColor]);
|
|
22410
22173
|
const handleToggle = () => {
|
|
22411
22174
|
const newState = !isOpen;
|
|
22412
22175
|
console.log('[ChatWidget] handleToggle called, setting isOpen to:', newState);
|
|
@@ -22428,24 +22191,8 @@ const ChatWidget = ({ widgetId, apiUrl = window.location.origin, position = 'bot
|
|
|
22428
22191
|
}
|
|
22429
22192
|
console.log('[ChatWidget] Rendering widget', { isOpen, hasConfig: !!config });
|
|
22430
22193
|
// Get button icon based on state
|
|
22431
|
-
const
|
|
22432
|
-
|
|
22433
|
-
return iconComponents.FiChevronDown;
|
|
22434
|
-
}
|
|
22435
|
-
const themeConfig = effectiveTheme === 'dark'
|
|
22436
|
-
? appearanceConfig?.darkMode
|
|
22437
|
-
: appearanceConfig?.lightMode;
|
|
22438
|
-
const buttonIcon = themeConfig?.button?.icon || 'FiMessageCircle';
|
|
22439
|
-
return iconComponents[buttonIcon] || iconComponents.FiMessageCircle;
|
|
22440
|
-
};
|
|
22441
|
-
const buttonIconColor = (() => {
|
|
22442
|
-
const themeConfig = effectiveTheme === 'dark'
|
|
22443
|
-
? appearanceConfig?.darkMode
|
|
22444
|
-
: appearanceConfig?.lightMode;
|
|
22445
|
-
return themeConfig?.button?.iconColor || customStyles['--button-icon-color'] || '#ffffff';
|
|
22446
|
-
})();
|
|
22447
|
-
const IconComponent = getButtonIcon();
|
|
22448
|
-
return (jsxRuntime.jsx("div", { ref: containerRef, 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 })), jsxRuntime.jsx("button", { className: `ai-chat-button ${isOpen ? 'is-open' : ''}`, onClick: handleToggle, "aria-label": isOpen ? "Minimize chat" : "Open chat", style: { color: buttonIconColor }, children: jsxRuntime.jsx("div", { className: "ai-chat-button-svg", children: jsxRuntime.jsx(IconComponent, {}) }) })] }) }));
|
|
22194
|
+
const IconComponent = isOpen ? iconComponents.FiChevronDown : iconComponents.FiMessageCircle;
|
|
22195
|
+
return (jsxRuntime.jsx("div", { ref: containerRef, 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 })), jsxRuntime.jsx("button", { className: `ai-chat-button ${isOpen ? 'is-open' : ''}`, onClick: handleToggle, "aria-label": isOpen ? "Minimize chat" : "Open chat", children: jsxRuntime.jsx("div", { className: "ai-chat-button-svg", children: jsxRuntime.jsx(IconComponent, {}) }) })] }) }));
|
|
22449
22196
|
};
|
|
22450
22197
|
|
|
22451
22198
|
exports.ApiError = ApiError;
|