@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/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
- console.log('[ChatWindow] Size:', size, 'Appearance:', !!appearance);
21583
- // Determine current theme config
21584
- const themePreference = appearance?.theme ?? 'light';
21585
- const canUseDarkMode = appearance?.darkModeEnabled !== false;
21586
- const prefersDark = typeof window !== 'undefined' && window.matchMedia('(prefers-color-scheme: dark)').matches;
21587
- const isDarkMode = themePreference === 'auto'
21588
- ? (canUseDarkMode && prefersDark)
21589
- : themePreference === 'dark' && canUseDarkMode;
21590
- const themeConfig = (isDarkMode ? appearance?.darkMode : appearance?.lightMode) ?? (appearance?.lightMode || appearance?.darkMode);
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, welcomeTitle: welcomeTitle, 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, separateFromChat: themeConfig?.footer?.separateFromChat })] }));
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
- * This allows the widget to be fully customizable via the appearance config
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, theme = 'light') {
21619
+ function applyAppearanceStyles(appearance) {
21639
21620
  const styles = {};
21640
- // Global font family
21641
- if (appearance.fontFamily) {
21642
- styles.fontFamily = appearance.fontFamily;
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
- callback(theme);
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', theme: themeOverride, primaryColor, onOpen, onClose, onMessage, onError, }) => {
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 || !config?.appearance.closeOnEscape)
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, config, onClose]);
22367
- // Determine theme - simplified: always auto-detect unless explicitly overridden
22138
+ }, [isOpen, onClose]);
22139
+ // Determine theme - always auto-detect from background
22368
22140
  const appearanceConfig = config?.appearance;
22369
- const themeSetting = themeOverride || appearanceConfig?.theme || 'auto';
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
- welcomeTitle: appearanceConfig?.lightMode?.chat?.welcomeTitle,
22385
- welcomeMessage: appearanceConfig?.welcomeMessage || appearanceConfig?.lightMode?.chat?.welcomeMessage,
22386
- placeholder: appearanceConfig?.placeholder || appearanceConfig?.lightMode?.footer?.inputPlaceholder,
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, effectiveTheme)
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, themeSetting, accentColor]);
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 getButtonIcon = () => {
22432
- if (isOpen) {
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;