@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.
@@ -1 +1 @@
1
- {"version":3,"file":"ChatWidget.d.ts","sourceRoot":"","sources":["../../src/components/ChatWidget.tsx"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AAEH,OAAO,KAAsC,MAAM,OAAO,CAAC;AAC3D,OAAO,EAAE,WAAW,EAAE,MAAM,UAAU,CAAC;AAMvC,OAAO,sBAAsB,CAAC;AAC9B,OAAO,qBAAqB,CAAC;AAoF7B,eAAO,MAAM,UAAU,EAAE,KAAK,CAAC,EAAE,CAAC,WAAW,CAoQ5C,CAAC"}
1
+ {"version":3,"file":"ChatWidget.d.ts","sourceRoot":"","sources":["../../src/components/ChatWidget.tsx"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AAEH,OAAO,KAAsC,MAAM,OAAO,CAAC;AAC3D,OAAO,EAAE,WAAW,EAAE,MAAM,UAAU,CAAC;AAMvC,OAAO,sBAAsB,CAAC;AAC9B,OAAO,qBAAqB,CAAC;AAoF7B,eAAO,MAAM,UAAU,EAAE,KAAK,CAAC,EAAE,CAAC,WAAW,CAoO5C,CAAC"}
@@ -1 +1 @@
1
- {"version":3,"file":"ChatWindow.d.ts","sourceRoot":"","sources":["../../src/components/ChatWindow.tsx"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,OAAO,KAA8B,MAAM,OAAO,CAAC;AACnD,OAAO,EAAE,mBAAmB,EAAE,YAAY,EAAE,MAAM,UAAU,CAAC;AAW7D,MAAM,WAAW,eAAe;IAC9B,QAAQ,EAAE,mBAAmB,EAAE,CAAC;IAChC,SAAS,EAAE,OAAO,CAAC;IACnB,QAAQ,EAAE,OAAO,CAAC;IAClB,KAAK,EAAE,MAAM,GAAG,IAAI,CAAC;IACrB,MAAM,EAAE,YAAY,GAAG,IAAI,CAAC;IAC5B,aAAa,EAAE,CAAC,OAAO,EAAE,MAAM,KAAK,IAAI,CAAC;IACzC,OAAO,EAAE,MAAM,IAAI,CAAC;IACpB,UAAU,EAAE,CAAC,SAAS,EAAE,MAAM,EAAE,QAAQ,EAAE,UAAU,GAAG,UAAU,KAAK,IAAI,CAAC;CAC5E;AAED,eAAO,MAAM,UAAU,EAAE,KAAK,CAAC,EAAE,CAAC,eAAe,CAuIhD,CAAC"}
1
+ {"version":3,"file":"ChatWindow.d.ts","sourceRoot":"","sources":["../../src/components/ChatWindow.tsx"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,OAAO,KAA8B,MAAM,OAAO,CAAC;AACnD,OAAO,EAAE,mBAAmB,EAAE,YAAY,EAAE,MAAM,UAAU,CAAC;AAW7D,MAAM,WAAW,eAAe;IAC9B,QAAQ,EAAE,mBAAmB,EAAE,CAAC;IAChC,SAAS,EAAE,OAAO,CAAC;IACnB,QAAQ,EAAE,OAAO,CAAC;IAClB,KAAK,EAAE,MAAM,GAAG,IAAI,CAAC;IACrB,MAAM,EAAE,YAAY,GAAG,IAAI,CAAC;IAC5B,aAAa,EAAE,CAAC,OAAO,EAAE,MAAM,KAAK,IAAI,CAAC;IACzC,OAAO,EAAE,MAAM,IAAI,CAAC;IACpB,UAAU,EAAE,CAAC,SAAS,EAAE,MAAM,EAAE,QAAQ,EAAE,UAAU,GAAG,UAAU,KAAK,IAAI,CAAC;CAC5E;AAED,eAAO,MAAM,UAAU,EAAE,KAAK,CAAC,EAAE,CAAC,eAAe,CAmIhD,CAAC"}
@@ -1 +1 @@
1
- {"version":3,"file":"useChat.d.ts","sourceRoot":"","sources":["../../src/hooks/useChat.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAGH,OAAO,EAAE,mBAAmB,EAAE,YAAY,EAAa,MAAM,UAAU,CAAC;AAKxE,MAAM,WAAW,cAAc;IAC7B,QAAQ,EAAE,MAAM,CAAC;IACjB,MAAM,EAAE,MAAM,CAAC;IACf,SAAS,CAAC,EAAE,CAAC,OAAO,EAAE,mBAAmB,KAAK,IAAI,CAAC;IACnD,OAAO,CAAC,EAAE,CAAC,KAAK,EAAE,KAAK,KAAK,IAAI,CAAC;CAClC;AAED,MAAM,WAAW,aAAa;IAC5B,QAAQ,EAAE,mBAAmB,EAAE,CAAC;IAChC,SAAS,EAAE,OAAO,CAAC;IACnB,QAAQ,EAAE,OAAO,CAAC;IAClB,KAAK,EAAE,MAAM,GAAG,IAAI,CAAC;IACrB,MAAM,EAAE,YAAY,GAAG,IAAI,CAAC;IAC5B,cAAc,EAAE,MAAM,CAAC;IACvB,WAAW,EAAE,CAAC,OAAO,EAAE,MAAM,KAAK,OAAO,CAAC,IAAI,CAAC,CAAC;IAChD,aAAa,EAAE,MAAM,IAAI,CAAC;IAC1B,cAAc,EAAE,CAAC,SAAS,EAAE,MAAM,EAAE,QAAQ,EAAE,UAAU,GAAG,UAAU,KAAK,OAAO,CAAC,IAAI,CAAC,CAAC;CACzF;AAkED,wBAAgB,OAAO,CAAC,OAAO,EAAE,cAAc,GAAG,aAAa,CA2W9D"}
1
+ {"version":3,"file":"useChat.d.ts","sourceRoot":"","sources":["../../src/hooks/useChat.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAGH,OAAO,EAAE,mBAAmB,EAAE,YAAY,EAAa,MAAM,UAAU,CAAC;AAKxE,MAAM,WAAW,cAAc;IAC7B,QAAQ,EAAE,MAAM,CAAC;IACjB,MAAM,EAAE,MAAM,CAAC;IACf,SAAS,CAAC,EAAE,CAAC,OAAO,EAAE,mBAAmB,KAAK,IAAI,CAAC;IACnD,OAAO,CAAC,EAAE,CAAC,KAAK,EAAE,KAAK,KAAK,IAAI,CAAC;CAClC;AAED,MAAM,WAAW,aAAa;IAC5B,QAAQ,EAAE,mBAAmB,EAAE,CAAC;IAChC,SAAS,EAAE,OAAO,CAAC;IACnB,QAAQ,EAAE,OAAO,CAAC;IAClB,KAAK,EAAE,MAAM,GAAG,IAAI,CAAC;IACrB,MAAM,EAAE,YAAY,GAAG,IAAI,CAAC;IAC5B,cAAc,EAAE,MAAM,CAAC;IACvB,WAAW,EAAE,CAAC,OAAO,EAAE,MAAM,KAAK,OAAO,CAAC,IAAI,CAAC,CAAC;IAChD,aAAa,EAAE,MAAM,IAAI,CAAC;IAC1B,cAAc,EAAE,CAAC,SAAS,EAAE,MAAM,EAAE,QAAQ,EAAE,UAAU,GAAG,UAAU,KAAK,OAAO,CAAC,IAAI,CAAC,CAAC;CACzF;AAkED,wBAAgB,OAAO,CAAC,OAAO,EAAE,cAAc,GAAG,aAAa,CAyW9D"}
package/dist/index.d.ts CHANGED
@@ -5,6 +5,6 @@
5
5
  export { ChatWidget } from './components/ChatWidget';
6
6
  export { useChat } from './hooks/useChat';
7
7
  export { ApiError } from './api/client';
8
- export type { WidgetProps, WidgetTheme, WidgetPosition, WidgetSize, WidgetAppearance, WidgetBehavior, WidgetConfig, ConversationMessage, ChatMessage, KbDocument, SourceDisplayMode, ChatState, } from './types';
8
+ export type { WidgetProps, WidgetPosition, WidgetSize, WidgetAppearance, WidgetBehavior, WidgetConfig, ConversationMessage, ChatMessage, KbDocument, SourceDisplayMode, ChatState, } from './types';
9
9
  export type { UseChatOptions, UseChatReturn, } from './hooks/useChat';
10
10
  //# sourceMappingURL=index.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,OAAO,EAAE,UAAU,EAAE,MAAM,yBAAyB,CAAC;AACrD,OAAO,EAAE,OAAO,EAAE,MAAM,iBAAiB,CAAC;AAC1C,OAAO,EAAE,QAAQ,EAAE,MAAM,cAAc,CAAC;AAGxC,YAAY,EACV,WAAW,EACX,WAAW,EACX,cAAc,EACd,UAAU,EACV,gBAAgB,EAChB,cAAc,EACd,YAAY,EACZ,mBAAmB,EACnB,WAAW,EACX,UAAU,EACV,iBAAiB,EACjB,SAAS,GACV,MAAM,SAAS,CAAC;AAEjB,YAAY,EACV,cAAc,EACd,aAAa,GACd,MAAM,iBAAiB,CAAC"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,OAAO,EAAE,UAAU,EAAE,MAAM,yBAAyB,CAAC;AACrD,OAAO,EAAE,OAAO,EAAE,MAAM,iBAAiB,CAAC;AAC1C,OAAO,EAAE,QAAQ,EAAE,MAAM,cAAc,CAAC;AAGxC,YAAY,EACV,WAAW,EACX,cAAc,EACd,UAAU,EACV,gBAAgB,EAChB,cAAc,EACd,YAAY,EACZ,mBAAmB,EACnB,WAAW,EACX,UAAU,EACV,iBAAiB,EACjB,SAAS,GACV,MAAM,SAAS,CAAC;AAEjB,YAAY,EACV,cAAc,EACd,aAAa,GACd,MAAM,iBAAiB,CAAC"}
package/dist/index.esm.js CHANGED
@@ -415,8 +415,6 @@ function useChat(options) {
415
415
  const config = await apiClient.current.getConfig();
416
416
  console.log('[useChat] Config fetched successfully:', {
417
417
  hasAppearance: !!config.appearance,
418
- hasLightMode: !!config.appearance?.lightMode,
419
- hasDarkMode: !!config.appearance?.darkMode,
420
418
  });
421
419
  const persistConversation = config.behavior.persistConversation ?? true;
422
420
  let conversationId = '';
@@ -21576,20 +21574,17 @@ const ChatWindow = ({ messages, isLoading, isTyping, error, config, onSendMessag
21576
21574
  console.log('[ChatWindow] Rendering ChatWindow component');
21577
21575
  const appearance = config?.appearance;
21578
21576
  const behavior = config?.behavior;
21577
+ // Use simplified appearance fields
21579
21578
  const size = appearance?.size || 'medium';
21580
- console.log('[ChatWindow] Size:', size, 'Appearance:', !!appearance);
21581
- // Determine current theme config
21582
- const themePreference = appearance?.theme ?? 'light';
21583
- const canUseDarkMode = appearance?.darkModeEnabled !== false;
21584
- const prefersDark = typeof window !== 'undefined' && window.matchMedia('(prefers-color-scheme: dark)').matches;
21585
- const isDarkMode = themePreference === 'auto'
21586
- ? (canUseDarkMode && prefersDark)
21587
- : themePreference === 'dark' && canUseDarkMode;
21588
- const themeConfig = (isDarkMode ? appearance?.darkMode : appearance?.lightMode) ?? (appearance?.lightMode || appearance?.darkMode);
21589
- const headerTitle = themeConfig?.header?.title ?? appearance?.header?.title ?? appearance?.companyName ?? 'AI Assistant';
21590
- const welcomeTitle = themeConfig?.chat?.welcomeTitle ?? 'Welcome!';
21591
- const welcomeMessage = themeConfig?.chat?.welcomeMessage ?? appearance?.welcomeMessage ?? '👋 Hi there! How can I assist you today?';
21592
- const inputPlaceholder = themeConfig?.footer?.inputPlaceholder ?? appearance?.placeholder ?? 'Ask me anything...';
21579
+ const headerTitle = appearance?.headerTitle || 'AI Assistant';
21580
+ const welcomeMessage = appearance?.welcomeMessage || '👋 Hi there! How can I assist you today?';
21581
+ const inputPlaceholder = appearance?.placeholder || 'Ask me anything...';
21582
+ console.log('[ChatWindow] Appearance values:', {
21583
+ size,
21584
+ headerTitle,
21585
+ welcomeMessage,
21586
+ inputPlaceholder,
21587
+ });
21593
21588
  // Track if suggested questions should be shown
21594
21589
  const [showSuggestedQuestions, setShowSuggestedQuestions] = useState(true);
21595
21590
  // Hide suggested questions after first user message
@@ -21609,241 +21604,25 @@ const ChatWindow = ({ messages, isLoading, isTyping, error, config, onSendMessag
21609
21604
  onSendMessage(question);
21610
21605
  };
21611
21606
  const hasMessages = messages.length > 0;
21612
- return (jsxs("div", { className: `ai-chat-window size-${size}`, role: "dialog", "aria-label": "Chat window", children: [jsxs("div", { className: "ai-chat-header", children: [jsxs("div", { className: "ai-chat-header-content", children: [appearance?.logo && (jsx("img", { src: appearance.logo, alt: "Logo", className: "ai-chat-logo" })), jsx("div", { className: "ai-chat-title", children: headerTitle })] }), jsx("button", { className: "ai-chat-close-button", onClick: onClose, "aria-label": "Minimize chat", children: jsx(MinimizeIcon, {}) })] }), error && (jsx("div", { className: "ai-chat-error", role: "alert", children: error })), maxMessages && userMessageCount >= maxMessages - 2 && !isLimitReached && (jsxs("div", { className: "ai-chat-warning", role: "alert", children: [maxMessages - userMessageCount, " message", maxMessages - userMessageCount !== 1 ? 's' : '', " remaining"] })), isLimitReached && (jsx("div", { className: "ai-chat-error", role: "alert", children: "Message limit reached. Please start a new conversation." })), jsx(MessageList, { messages: messages, isTyping: isTyping, showTypingIndicator: behavior?.showTypingIndicator, showTimestamps: behavior?.showTimestamps, enableFeedback: behavior?.enableFeedback, showSources: behavior?.showSources, sourceDisplayMode: behavior?.sourceDisplayMode, welcomeTitle: welcomeTitle, welcomeMessage: welcomeMessage, onFeedback: onFeedback }), showSuggestedQuestions && !hasMessages && behavior?.suggestedQuestions && behavior.suggestedQuestions.length > 0 && (jsx(SuggestedQuestions, { questions: behavior.suggestedQuestions, onQuestionClick: handleQuestionClick })), jsx(MessageInput, { onSend: onSendMessage, placeholder: isLimitReached ? 'Message limit reached' : inputPlaceholder, disabled: isLoading || isLimitReached, enableFileUpload: behavior?.enableFileUpload, separateFromChat: themeConfig?.footer?.separateFromChat })] }));
21607
+ return (jsxs("div", { className: `ai-chat-window size-${size}`, role: "dialog", "aria-label": "Chat window", children: [jsxs("div", { className: "ai-chat-header", children: [jsxs("div", { className: "ai-chat-header-content", children: [appearance?.logo && (jsx("img", { src: appearance.logo, alt: "Logo", className: "ai-chat-logo" })), jsx("div", { className: "ai-chat-title", children: headerTitle })] }), jsx("button", { className: "ai-chat-close-button", onClick: onClose, "aria-label": "Minimize chat", children: jsx(MinimizeIcon, {}) })] }), error && (jsx("div", { className: "ai-chat-error", role: "alert", children: error })), maxMessages && userMessageCount >= maxMessages - 2 && !isLimitReached && (jsxs("div", { className: "ai-chat-warning", role: "alert", children: [maxMessages - userMessageCount, " message", maxMessages - userMessageCount !== 1 ? 's' : '', " remaining"] })), isLimitReached && (jsx("div", { className: "ai-chat-error", role: "alert", children: "Message limit reached. Please start a new conversation." })), jsx(MessageList, { messages: messages, isTyping: isTyping, showTypingIndicator: behavior?.showTypingIndicator, showTimestamps: behavior?.showTimestamps, enableFeedback: behavior?.enableFeedback, showSources: behavior?.showSources, sourceDisplayMode: behavior?.sourceDisplayMode, welcomeMessage: welcomeMessage, onFeedback: onFeedback }), showSuggestedQuestions && !hasMessages && behavior?.suggestedQuestions && behavior.suggestedQuestions.length > 0 && (jsx(SuggestedQuestions, { questions: behavior.suggestedQuestions, onQuestionClick: handleQuestionClick })), jsx(MessageInput, { onSend: onSendMessage, placeholder: isLimitReached ? 'Message limit reached' : inputPlaceholder, disabled: isLoading || isLimitReached, enableFileUpload: behavior?.enableFileUpload })] }));
21613
21608
  };
21614
21609
 
21615
- /**
21616
- * Convert shadow size to CSS box-shadow value
21617
- */
21618
- function getShadowValue(size) {
21619
- const shadows = {
21620
- 'none': 'none',
21621
- 'sm': '0 1px 2px 0 rgba(0, 0, 0, 0.05)',
21622
- 'md': '0 4px 6px -1px rgba(0, 0, 0, 0.1), 0 2px 4px -1px rgba(0, 0, 0, 0.06)',
21623
- 'lg': '0 10px 15px -3px rgba(0, 0, 0, 0.1), 0 4px 6px -2px rgba(0, 0, 0, 0.05)',
21624
- 'xl': '0 20px 25px -5px rgba(0, 0, 0, 0.1), 0 10px 10px -5px rgba(0, 0, 0, 0.04)',
21625
- '2xl': '0 25px 50px -12px rgba(0, 0, 0, 0.25)',
21626
- };
21627
- return shadows[size] || shadows.none;
21628
- }
21629
21610
  /**
21630
21611
  * Apply appearance configuration as CSS custom properties
21631
- * This allows the widget to be fully customizable via the appearance config
21612
+ * Simplified to only handle flat appearance schema
21632
21613
  *
21633
21614
  * @param appearance - Widget appearance configuration
21634
- * @param theme - Current theme ('light' or 'dark')
21615
+ * @param theme - Current theme ('light' or 'dark') - kept for compatibility but not used for theme selection
21635
21616
  */
21636
- function applyAppearanceStyles(appearance, theme = 'light') {
21617
+ function applyAppearanceStyles(appearance) {
21637
21618
  const styles = {};
21638
- // Global font family
21639
- if (appearance.fontFamily) {
21640
- styles.fontFamily = appearance.fontFamily;
21641
- }
21642
- // Select the correct theme configuration
21643
- const themeConfig = theme === 'dark' ? appearance.darkMode : appearance.lightMode;
21644
- // If theme config exists and has required properties, use it
21645
- if (themeConfig && themeConfig.button) {
21646
- // ========================================================================
21647
- // BUTTON APPEARANCE
21648
- // ========================================================================
21649
- const btn = themeConfig.button;
21650
- if (btn.color)
21651
- styles['--button-color'] = btn.color;
21652
- if (btn.opacity !== undefined)
21653
- styles['--button-opacity'] = btn.opacity.toString();
21654
- if (btn.size)
21655
- styles['--button-size'] = `${btn.size}px`;
21656
- if (btn.icon)
21657
- styles['--button-icon'] = btn.icon;
21658
- if (btn.iconColor)
21659
- styles['--button-icon-color'] = btn.iconColor;
21660
- if (btn.borderRadius !== undefined)
21661
- styles['--button-border-radius'] = `${btn.borderRadius}px`;
21662
- if (btn.borderWidth !== undefined)
21663
- styles['--button-border-width'] = `${btn.borderWidth}px`;
21664
- if (btn.borderColor)
21665
- styles['--button-border-color'] = btn.borderColor;
21666
- if (btn.borderOpacity !== undefined)
21667
- styles['--button-border-opacity'] = btn.borderOpacity.toString();
21668
- if (btn.backdropBlur !== undefined)
21669
- styles['--button-backdrop-blur'] = `${btn.backdropBlur}px`;
21670
- if (btn.shadow)
21671
- styles['--button-shadow'] = getShadowValue(btn.shadow);
21672
- // ========================================================================
21673
- // CARD/WINDOW APPEARANCE
21674
- // ========================================================================
21675
- const card = themeConfig.card;
21676
- if (card.backgroundColor)
21677
- styles['--card-background'] = card.backgroundColor;
21678
- if (card.opacity !== undefined)
21679
- styles['--card-opacity'] = card.opacity.toString();
21680
- if (card.borderRadius !== undefined)
21681
- styles['--card-border-radius'] = `${card.borderRadius}px`;
21682
- if (card.borderWidth !== undefined)
21683
- styles['--card-border-width'] = `${card.borderWidth}px`;
21684
- if (card.borderColor) {
21685
- styles['--card-border-color'] = card.borderColor;
21686
- // Create rgba border color with opacity for box-shadow
21687
- if (card.borderOpacity !== undefined) {
21688
- const opacity = card.borderOpacity;
21689
- // Convert hex to rgba
21690
- const hex = card.borderColor.replace('#', '');
21691
- const r = parseInt(hex.substring(0, 2), 16);
21692
- const g = parseInt(hex.substring(2, 4), 16);
21693
- const b = parseInt(hex.substring(4, 6), 16);
21694
- styles['--card-border-color-rgba'] = `rgba(${r}, ${g}, ${b}, ${opacity})`;
21695
- }
21696
- }
21697
- if (card.borderOpacity !== undefined)
21698
- styles['--card-border-opacity'] = card.borderOpacity.toString();
21699
- if (card.backdropBlur !== undefined)
21700
- styles['--card-backdrop-blur'] = `${card.backdropBlur}px`;
21701
- if (card.shadow)
21702
- styles['--card-shadow'] = getShadowValue(card.shadow);
21703
- // ========================================================================
21704
- // HEADER APPEARANCE
21705
- // ========================================================================
21706
- const header = themeConfig.header;
21707
- if (header.backgroundColor)
21708
- styles['--header-background'] = header.backgroundColor;
21709
- if (header.opacity !== undefined)
21710
- styles['--header-opacity'] = header.opacity.toString();
21711
- if (header.textColor)
21712
- styles['--header-text-color'] = header.textColor;
21713
- if (header.borderBottomWidth !== undefined)
21714
- styles['--header-border-bottom-width'] = `${header.borderBottomWidth}px`;
21715
- if (header.borderBottomColor)
21716
- styles['--header-border-bottom-color'] = header.borderBottomColor;
21717
- if (header.borderBottomOpacity !== undefined)
21718
- styles['--header-border-bottom-opacity'] = header.borderBottomOpacity.toString();
21719
- // ========================================================================
21720
- // CHAT APPEARANCE
21721
- // ========================================================================
21722
- const chat = themeConfig.chat;
21723
- if (chat.backgroundColor)
21724
- styles['--chat-background'] = chat.backgroundColor;
21725
- if (chat.opacity !== undefined)
21726
- styles['--chat-opacity'] = chat.opacity.toString();
21727
- // Welcome message
21728
- if (chat.welcomeColor)
21729
- styles['--welcome-color'] = chat.welcomeColor;
21730
- // Message bubbles
21731
- if (chat.enableBubbles) {
21732
- if (chat.bubbleUserColor)
21733
- styles['--bubble-user-color'] = chat.bubbleUserColor;
21734
- if (chat.bubbleUserOpacity !== undefined)
21735
- styles['--bubble-user-opacity'] = chat.bubbleUserOpacity.toString();
21736
- if (chat.bubbleAssistantColor)
21737
- styles['--bubble-assistant-color'] = chat.bubbleAssistantColor;
21738
- if (chat.bubbleAssistantOpacity !== undefined)
21739
- styles['--bubble-assistant-opacity'] = chat.bubbleAssistantOpacity.toString();
21740
- if (chat.bubbleBorderWidth !== undefined)
21741
- styles['--bubble-border-width'] = `${chat.bubbleBorderWidth}px`;
21742
- if (chat.bubbleBorderColor)
21743
- styles['--bubble-border-color'] = chat.bubbleBorderColor;
21744
- if (chat.bubbleBorderOpacity !== undefined)
21745
- styles['--bubble-border-opacity'] = chat.bubbleBorderOpacity.toString();
21746
- }
21747
- else {
21748
- // Plain text mode
21749
- if (chat.textColor)
21750
- styles['--message-text-color'] = chat.textColor;
21751
- }
21752
- // ========================================================================
21753
- // FOOTER APPEARANCE
21754
- // ========================================================================
21755
- const footer = themeConfig.footer;
21756
- // Only if separate from chat
21757
- if (footer.separateFromChat) {
21758
- if (footer.backgroundColor)
21759
- styles['--footer-background'] = footer.backgroundColor;
21760
- if (footer.opacity !== undefined)
21761
- styles['--footer-opacity'] = footer.opacity.toString();
21762
- if (footer.borderTopWidth !== undefined)
21763
- styles['--footer-border-top-width'] = `${footer.borderTopWidth}px`;
21764
- if (footer.borderTopColor)
21765
- styles['--footer-border-top-color'] = footer.borderTopColor;
21766
- if (footer.borderTopOpacity !== undefined)
21767
- styles['--footer-border-top-opacity'] = footer.borderTopOpacity.toString();
21768
- }
21769
- // Backdrop blur (only when floating)
21770
- if (!footer.separateFromChat && footer.backdropBlur !== undefined) {
21771
- styles['--footer-backdrop-blur'] = `${footer.backdropBlur}px`;
21772
- }
21773
- // Input field
21774
- if (footer.inputBackgroundColor)
21775
- styles['--input-background'] = footer.inputBackgroundColor;
21776
- if (footer.inputBackgroundOpacity !== undefined)
21777
- styles['--input-background-opacity'] = footer.inputBackgroundOpacity.toString();
21778
- if (footer.inputBorderRadius !== undefined)
21779
- styles['--input-border-radius'] = `${footer.inputBorderRadius}px`;
21780
- if (footer.inputBorderWidth !== undefined)
21781
- styles['--input-border-width'] = `${footer.inputBorderWidth}px`;
21782
- if (footer.inputBorderColor)
21783
- styles['--input-border-color'] = footer.inputBorderColor;
21784
- if (footer.inputBorderOpacity !== undefined)
21785
- styles['--input-border-opacity'] = footer.inputBorderOpacity.toString();
21786
- if (footer.inputShadow)
21787
- styles['--input-shadow'] = getShadowValue(footer.inputShadow);
21788
- // Send button
21789
- if (footer.buttonBackgroundColor)
21790
- styles['--send-button-background'] = footer.buttonBackgroundColor;
21791
- if (footer.buttonOpacity !== undefined)
21792
- styles['--send-button-opacity'] = footer.buttonOpacity.toString();
21793
- if (footer.buttonBorderRadius !== undefined)
21794
- styles['--send-button-border-radius'] = `${footer.buttonBorderRadius}px`;
21795
- if (footer.buttonBorderWidth !== undefined)
21796
- styles['--send-button-border-width'] = `${footer.buttonBorderWidth}px`;
21797
- if (footer.buttonBorderColor)
21798
- styles['--send-button-border-color'] = footer.buttonBorderColor;
21799
- if (footer.buttonBorderOpacity !== undefined)
21800
- styles['--send-button-border-opacity'] = footer.buttonBorderOpacity.toString();
21801
- // ========================================================================
21802
- // HOVER STATES
21803
- // ========================================================================
21804
- const hover = themeConfig.hover;
21805
- if (hover.buttonScale !== undefined)
21806
- styles['--hover-button-scale'] = hover.buttonScale.toString();
21807
- if (hover.buttonOpacity !== undefined)
21808
- styles['--hover-button-opacity'] = hover.buttonOpacity.toString();
21809
- if (hover.inputBorderColor)
21810
- styles['--hover-input-border-color'] = hover.inputBorderColor;
21811
- if (hover.sendButtonOpacity !== undefined)
21812
- styles['--hover-send-button-opacity'] = hover.sendButtonOpacity.toString();
21813
- if (hover.closeButtonOpacity !== undefined)
21814
- styles['--hover-close-button-opacity'] = hover.closeButtonOpacity.toString();
21815
- // ========================================================================
21816
- // ACTIVE STATES
21817
- // ========================================================================
21818
- const active = themeConfig.active;
21819
- if (active.inputBorderColor)
21820
- styles['--active-input-border-color'] = active.inputBorderColor;
21821
- if (active.inputShadow)
21822
- styles['--active-input-shadow'] = active.inputShadow;
21823
- }
21824
- else {
21825
- // Fallback to legacy fields if no theme config
21826
- if (appearance.primaryColor)
21827
- styles['--primary-color'] = appearance.primaryColor;
21828
- if (appearance.borderRadius !== undefined)
21829
- styles['--border-radius'] = `${appearance.borderRadius}px`;
21830
- // Legacy button
21831
- if (appearance.button) {
21832
- const btn = appearance.button;
21833
- if (btn.color)
21834
- styles['--button-color'] = btn.color;
21835
- if (btn.size)
21836
- styles['--button-size'] = `${btn.size}px`;
21837
- if (btn.borderRadius !== undefined)
21838
- styles['--button-border-radius'] = `${btn.borderRadius}px`;
21839
- if (btn.borderWidth !== undefined)
21840
- styles['--button-border-width'] = `${btn.borderWidth}px`;
21841
- if (btn.borderColor)
21842
- styles['--button-border-color'] = btn.borderColor;
21843
- if (btn.opacity !== undefined)
21844
- styles['--button-opacity'] = btn.opacity.toString();
21845
- }
21619
+ // Apply primary color
21620
+ if (appearance.primaryColor) {
21621
+ styles['--primary-color'] = appearance.primaryColor;
21846
21622
  }
21623
+ // Note: All legacy theme system code (lightMode, darkMode, ThemeAppearanceConfig)
21624
+ // has been removed. The widget now uses a simplified flat appearance schema.
21625
+ // Theme-specific styling is handled by generateThemeStyles() using auto-detected theme.
21847
21626
  return styles;
21848
21627
  }
21849
21628
 
@@ -22205,19 +21984,23 @@ function detectTheme(element) {
22205
21984
  * Create a MutationObserver to watch for theme changes
22206
21985
  */
22207
21986
  function createThemeObserver(element, callback) {
21987
+ let lastTheme = detectTheme(element);
22208
21988
  const observer = new MutationObserver(() => {
22209
21989
  const theme = detectTheme(element);
22210
- callback(theme);
21990
+ if (theme !== lastTheme) {
21991
+ lastTheme = theme;
21992
+ callback(theme);
21993
+ }
22211
21994
  });
22212
21995
  // Observe body for class/style changes (common for theme switching)
22213
21996
  observer.observe(document.body, {
22214
21997
  attributes: true,
22215
- attributeFilter: ['class', 'style', 'data-theme'],
21998
+ attributeFilter: ['class', 'style', 'data-theme', 'data-bs-theme'],
22216
21999
  });
22217
22000
  // Also observe html element
22218
22001
  observer.observe(document.documentElement, {
22219
22002
  attributes: true,
22220
- attributeFilter: ['class', 'style', 'data-theme'],
22003
+ attributeFilter: ['class', 'style', 'data-theme', 'data-bs-theme'],
22221
22004
  });
22222
22005
  return observer;
22223
22006
  }
@@ -22258,19 +22041,9 @@ styleInject(css_248z);
22258
22041
  // Icon components mapping
22259
22042
  const iconComponents = {
22260
22043
  FiMessageCircle: () => (jsx("svg", { viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "2", strokeLinecap: "round", strokeLinejoin: "round", children: 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" }) })),
22261
- FiMessageSquare: () => (jsx("svg", { viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "2", strokeLinecap: "round", strokeLinejoin: "round", children: jsx("path", { d: "M21 15a2 2 0 0 1-2 2H7l-4 4V5a2 2 0 0 1 2-2h14a2 2 0 0 1 2 2z" }) })),
22262
- FiMail: () => (jsxs("svg", { viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "2", strokeLinecap: "round", strokeLinejoin: "round", children: [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" }), jsx("polyline", { points: "22,6 12,13 2,6" })] })),
22263
- FiPhone: () => (jsx("svg", { viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "2", strokeLinecap: "round", strokeLinejoin: "round", children: 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" }) })),
22264
- FiHelpCircle: () => (jsxs("svg", { viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "2", strokeLinecap: "round", strokeLinejoin: "round", children: [jsx("circle", { cx: "12", cy: "12", r: "10" }), jsx("path", { d: "M9.09 9a3 3 0 0 1 5.83 1c0 2-3 3-3 3" }), jsx("line", { x1: "12", y1: "17", x2: "12.01", y2: "17" })] })),
22265
- FiZap: () => (jsx("svg", { viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "2", strokeLinecap: "round", strokeLinejoin: "round", children: jsx("polygon", { points: "13 2 3 14 12 14 11 22 21 10 12 10 13 2" }) })),
22266
- FiSend: () => (jsxs("svg", { viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "2", strokeLinecap: "round", strokeLinejoin: "round", children: [jsx("line", { x1: "22", y1: "2", x2: "11", y2: "13" }), jsx("polygon", { points: "22 2 15 22 11 13 2 9 22 2" })] })),
22267
- FiUser: () => (jsxs("svg", { viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "2", strokeLinecap: "round", strokeLinejoin: "round", children: [jsx("path", { d: "M20 21v-2a4 4 0 0 0-4-4H8a4 4 0 0 0-4 4v2" }), jsx("circle", { cx: "12", cy: "7", r: "4" })] })),
22268
- FiUsers: () => (jsxs("svg", { viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "2", strokeLinecap: "round", strokeLinejoin: "round", children: [jsx("path", { d: "M17 21v-2a4 4 0 0 0-4-4H5a4 4 0 0 0-4 4v2" }), jsx("circle", { cx: "9", cy: "7", r: "4" }), jsx("path", { d: "M23 21v-2a4 4 0 0 0-3-3.87" }), jsx("path", { d: "M16 3.13a4 4 0 0 1 0 7.75" })] })),
22269
- FiHeadphones: () => (jsxs("svg", { viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "2", strokeLinecap: "round", strokeLinejoin: "round", children: [jsx("path", { d: "M3 18v-6a9 9 0 0 1 18 0v6" }), 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" })] })),
22270
- FiCpu: () => (jsxs("svg", { viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "2", strokeLinecap: "round", strokeLinejoin: "round", children: [jsx("rect", { x: "4", y: "4", width: "16", height: "16", rx: "2", ry: "2" }), jsx("rect", { x: "9", y: "9", width: "6", height: "6" }), jsx("line", { x1: "9", y1: "1", x2: "9", y2: "4" }), jsx("line", { x1: "15", y1: "1", x2: "15", y2: "4" }), jsx("line", { x1: "9", y1: "20", x2: "9", y2: "23" }), jsx("line", { x1: "15", y1: "20", x2: "15", y2: "23" }), jsx("line", { x1: "20", y1: "9", x2: "23", y2: "9" }), jsx("line", { x1: "20", y1: "14", x2: "23", y2: "14" }), jsx("line", { x1: "1", y1: "9", x2: "4", y2: "9" }), jsx("line", { x1: "1", y1: "14", x2: "4", y2: "14" })] })),
22271
22044
  FiChevronDown: () => (jsx("svg", { viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "2.5", strokeLinecap: "round", strokeLinejoin: "round", children: jsx("polyline", { points: "6 9 12 15 18 9" }) })),
22272
22045
  };
22273
- const ChatWidget = ({ widgetId, apiUrl = window.location.origin, position = 'bottom-right', theme: themeOverride, primaryColor, onOpen, onClose, onMessage, onError, }) => {
22046
+ const ChatWidget = ({ widgetId, apiUrl = window.location.origin, position = 'bottom-right', primaryColor, onOpen, onClose, onMessage, onError, }) => {
22274
22047
  const [isOpen, setIsOpen] = useState(false);
22275
22048
  const [autoDetectedTheme, setAutoDetectedTheme] = useState('light');
22276
22049
  const widgetRef = useRef(null);
@@ -22311,7 +22084,6 @@ const ChatWidget = ({ widgetId, apiUrl = window.location.origin, position = 'bot
22311
22084
  console.log('[ChatWidget] Config loaded:', config ? 'YES' : 'NO');
22312
22085
  if (config) {
22313
22086
  console.log('[ChatWidget] Config details:', {
22314
- theme: config.appearance?.theme,
22315
22087
  accentColor: config.appearance?.primaryColor,
22316
22088
  autoDetectedTheme,
22317
22089
  });
@@ -22351,7 +22123,7 @@ const ChatWidget = ({ widgetId, apiUrl = window.location.origin, position = 'bot
22351
22123
  }, [isOpen, onClose]);
22352
22124
  // Handle close on Escape key
22353
22125
  useEffect(() => {
22354
- if (!isOpen || !config?.appearance.closeOnEscape)
22126
+ if (!isOpen)
22355
22127
  return;
22356
22128
  const handleEscapeKey = (event) => {
22357
22129
  if (event.key === 'Escape') {
@@ -22361,16 +22133,10 @@ const ChatWidget = ({ widgetId, apiUrl = window.location.origin, position = 'bot
22361
22133
  };
22362
22134
  document.addEventListener('keydown', handleEscapeKey);
22363
22135
  return () => document.removeEventListener('keydown', handleEscapeKey);
22364
- }, [isOpen, config, onClose]);
22365
- // Determine theme - simplified: always auto-detect unless explicitly overridden
22136
+ }, [isOpen, onClose]);
22137
+ // Determine theme - always auto-detect from background
22366
22138
  const appearanceConfig = config?.appearance;
22367
- const themeSetting = themeOverride || appearanceConfig?.theme || 'auto';
22368
- // Use auto-detected theme, or explicit override
22369
- const effectiveTheme = themeSetting === 'auto'
22370
- ? autoDetectedTheme
22371
- : themeSetting === 'dark'
22372
- ? 'dark'
22373
- : 'light';
22139
+ const effectiveTheme = autoDetectedTheme;
22374
22140
  // Determine position (config takes priority over prop)
22375
22141
  const effectivePosition = config?.appearance.position || position;
22376
22142
  // Get accent color from config or prop
@@ -22379,17 +22145,15 @@ const ChatWidget = ({ widgetId, apiUrl = window.location.origin, position = 'bot
22379
22145
  const simpleAppearance = {
22380
22146
  accentColor,
22381
22147
  size: appearanceConfig?.size || 'small',
22382
- welcomeTitle: appearanceConfig?.lightMode?.chat?.welcomeTitle,
22383
- welcomeMessage: appearanceConfig?.welcomeMessage || appearanceConfig?.lightMode?.chat?.welcomeMessage,
22384
- placeholder: appearanceConfig?.placeholder || appearanceConfig?.lightMode?.footer?.inputPlaceholder,
22385
- headerTitle: appearanceConfig?.lightMode?.header?.title,
22386
- buttonIcon: appearanceConfig?.buttonIcon || appearanceConfig?.lightMode?.button?.icon,
22148
+ welcomeMessage: appearanceConfig?.welcomeMessage || '',
22149
+ placeholder: appearanceConfig?.placeholder || '',
22150
+ headerTitle: appearanceConfig?.headerTitle || '',
22387
22151
  };
22388
22152
  // Generate theme styles from accent color
22389
22153
  const generatedStyles = generateThemeStyles(simpleAppearance, effectiveTheme);
22390
22154
  // Also apply legacy styles for backward compatibility
22391
22155
  const legacyStyles = appearanceConfig
22392
- ? applyAppearanceStyles(appearanceConfig, effectiveTheme)
22156
+ ? applyAppearanceStyles(appearanceConfig)
22393
22157
  : {};
22394
22158
  // Merge styles (generated takes priority for new simplified system)
22395
22159
  const customStyles = {
@@ -22401,10 +22165,9 @@ const ChatWidget = ({ widgetId, apiUrl = window.location.origin, position = 'bot
22401
22165
  console.log('[ChatWidget] Theme info:', {
22402
22166
  effectiveTheme,
22403
22167
  autoDetectedTheme,
22404
- themeSetting,
22405
22168
  accentColor,
22406
22169
  });
22407
- }, [effectiveTheme, autoDetectedTheme, themeSetting, accentColor]);
22170
+ }, [effectiveTheme, autoDetectedTheme, accentColor]);
22408
22171
  const handleToggle = () => {
22409
22172
  const newState = !isOpen;
22410
22173
  console.log('[ChatWidget] handleToggle called, setting isOpen to:', newState);
@@ -22426,24 +22189,8 @@ const ChatWidget = ({ widgetId, apiUrl = window.location.origin, position = 'bot
22426
22189
  }
22427
22190
  console.log('[ChatWidget] Rendering widget', { isOpen, hasConfig: !!config });
22428
22191
  // Get button icon based on state
22429
- const getButtonIcon = () => {
22430
- if (isOpen) {
22431
- return iconComponents.FiChevronDown;
22432
- }
22433
- const themeConfig = effectiveTheme === 'dark'
22434
- ? appearanceConfig?.darkMode
22435
- : appearanceConfig?.lightMode;
22436
- const buttonIcon = themeConfig?.button?.icon || 'FiMessageCircle';
22437
- return iconComponents[buttonIcon] || iconComponents.FiMessageCircle;
22438
- };
22439
- const buttonIconColor = (() => {
22440
- const themeConfig = effectiveTheme === 'dark'
22441
- ? appearanceConfig?.darkMode
22442
- : appearanceConfig?.lightMode;
22443
- return themeConfig?.button?.iconColor || customStyles['--button-icon-color'] || '#ffffff';
22444
- })();
22445
- const IconComponent = getButtonIcon();
22446
- return (jsx("div", { ref: containerRef, className: `ai-chat-widget ${effectiveTheme}`, style: customStyles, children: jsxs("div", { ref: widgetRef, className: `ai-chat-widget-container ${effectivePosition}`, children: [isOpen && (jsx(ChatWindow, { messages: messages, isLoading: isLoading, isTyping: isTyping, error: error, config: config, onSendMessage: sendMessage, onClose: handleToggle, onFeedback: handleFeedback })), jsx("button", { className: `ai-chat-button ${isOpen ? 'is-open' : ''}`, onClick: handleToggle, "aria-label": isOpen ? "Minimize chat" : "Open chat", style: { color: buttonIconColor }, children: jsx("div", { className: "ai-chat-button-svg", children: jsx(IconComponent, {}) }) })] }) }));
22192
+ const IconComponent = isOpen ? iconComponents.FiChevronDown : iconComponents.FiMessageCircle;
22193
+ return (jsx("div", { ref: containerRef, className: `ai-chat-widget ${effectiveTheme}`, style: customStyles, children: jsxs("div", { ref: widgetRef, className: `ai-chat-widget-container ${effectivePosition}`, children: [isOpen && (jsx(ChatWindow, { messages: messages, isLoading: isLoading, isTyping: isTyping, error: error, config: config, onSendMessage: sendMessage, onClose: handleToggle, onFeedback: handleFeedback })), jsx("button", { className: `ai-chat-button ${isOpen ? 'is-open' : ''}`, onClick: handleToggle, "aria-label": isOpen ? "Minimize chat" : "Open chat", children: jsx("div", { className: "ai-chat-button-svg", children: jsx(IconComponent, {}) }) })] }) }));
22447
22194
  };
22448
22195
 
22449
22196
  export { ApiError, ChatWidget, useChat };