@enjoys/react-chatbot-plugin 1.3.0 → 1.4.0

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":"index.cjs","names":[],"sources":["../src/context/ChatContext.ts","../src/styles/theme.ts","../src/components/icons/Icons.tsx","../src/components/Launcher.tsx","../src/components/ChatHeader.tsx","../src/components/WelcomeScreen.tsx","../src/components/forms/TextField.tsx","../src/components/forms/SelectField.tsx","../src/components/forms/RadioField.tsx","../src/components/forms/CheckboxField.tsx","../src/components/forms/FileUploadField.tsx","../src/components/forms/DynamicForm.tsx","../src/components/LoginScreen.tsx","../src/components/MessageBubble.tsx","../src/components/QuickReplies.tsx","../src/components/TypingIndicator.tsx","../src/components/MessageList.tsx","../src/components/EmojiPicker.tsx","../src/components/FileUpload.tsx","../src/components/ChatInput.tsx","../src/components/Branding.tsx","../src/engine/FlowEngine.ts","../src/utils/helpers.ts","../src/hooks/useChat.ts","../src/components/ChatWindow.tsx","../src/core/PluginManager.ts","../src/components/ChatBot.tsx","../src/plugins/analyticsPlugin.ts","../src/plugins/webhookPlugin.ts","../src/plugins/persistencePlugin.ts"],"sourcesContent":["import { createContext, useContext } from 'react';\r\nimport type { ChatMessage, ChatBotProps } from '../types';\r\n\r\nexport interface ChatState {\r\n isOpen: boolean;\r\n messages: ChatMessage[];\r\n isTyping: boolean;\r\n showWelcome: boolean;\r\n currentStepId: string | null;\r\n collectedData: Record<string, unknown>;\r\n isLoggedIn: boolean;\r\n}\r\n\r\nexport type ChatAction =\r\n | { type: 'TOGGLE_OPEN' }\r\n | { type: 'SET_OPEN'; payload: boolean }\r\n | { type: 'ADD_MESSAGE'; payload: ChatMessage }\r\n | { type: 'ADD_MESSAGES'; payload: ChatMessage[] }\r\n | { type: 'SET_TYPING'; payload: boolean }\r\n | { type: 'DISMISS_WELCOME' }\r\n | { type: 'SET_STEP'; payload: string | null }\r\n | { type: 'SET_DATA'; payload: Record<string, unknown> }\r\n | { type: 'SET_LOGGED_IN'; payload: boolean }\r\n | { type: 'CLEAR_QUICK_REPLIES' }\r\n | { type: 'RESET_CHAT' }\r\n | { type: 'UPDATE_MESSAGE'; payload: { id: string; updates: Partial<ChatMessage> } };\r\n\r\nexport function chatReducer(state: ChatState, action: ChatAction): ChatState {\r\n switch (action.type) {\r\n case 'TOGGLE_OPEN':\r\n return { ...state, isOpen: !state.isOpen };\r\n case 'SET_OPEN':\r\n return { ...state, isOpen: action.payload };\r\n case 'ADD_MESSAGE':\r\n return { ...state, messages: [...state.messages, action.payload] };\r\n case 'ADD_MESSAGES':\r\n return { ...state, messages: [...state.messages, ...action.payload] };\r\n case 'SET_TYPING':\r\n return { ...state, isTyping: action.payload };\r\n case 'DISMISS_WELCOME':\r\n return { ...state, showWelcome: false };\r\n case 'SET_STEP':\r\n return { ...state, currentStepId: action.payload };\r\n case 'SET_DATA':\r\n return { ...state, collectedData: { ...state.collectedData, ...action.payload } };\r\n case 'SET_LOGGED_IN':\r\n return { ...state, isLoggedIn: action.payload };\r\n case 'CLEAR_QUICK_REPLIES': {\r\n // Only clear quick replies from the last message that has them\r\n let lastIdx = -1;\r\n for (let i = state.messages.length - 1; i >= 0; i--) {\r\n if (state.messages[i].quickReplies) { lastIdx = i; break; }\r\n }\r\n if (lastIdx === -1) return state;\r\n const updated = [...state.messages];\r\n updated[lastIdx] = { ...updated[lastIdx], quickReplies: undefined };\r\n return { ...state, messages: updated };\r\n }\r\n case 'RESET_CHAT':\r\n return {\r\n ...state,\r\n messages: [],\r\n isTyping: false,\r\n currentStepId: null,\r\n collectedData: {},\r\n };\r\n case 'UPDATE_MESSAGE':\r\n return {\r\n ...state,\r\n messages: state.messages.map((m) =>\r\n m.id === action.payload.id ? { ...m, ...action.payload.updates } : m,\r\n ),\r\n };\r\n default:\r\n return state;\r\n }\r\n}\r\n\r\nexport const initialState = (props: ChatBotProps): ChatState => ({\r\n isOpen: props.defaultOpen ?? false,\r\n messages: props.initialMessages ?? [],\r\n isTyping: false,\r\n showWelcome: !!props.welcomeScreen,\r\n currentStepId: null,\r\n collectedData: {},\r\n isLoggedIn: !props.loginForm,\r\n});\r\n\r\ninterface ChatContextValue {\r\n state: ChatState;\r\n dispatch: React.Dispatch<ChatAction>;\r\n props: ChatBotProps;\r\n}\r\n\r\nexport const ChatContext = createContext<ChatContextValue | null>(null);\r\n\r\nexport function useChatContext(): ChatContextValue {\r\n const ctx = useContext(ChatContext);\r\n if (!ctx) throw new Error('useChatContext must be used within ChatProvider');\r\n return ctx;\r\n}\r\n","import type { ChatTheme, ChatStyle } from '../types';\r\nimport type { CSSProperties } from 'react';\r\n\r\n// ─── Light Mode Defaults ─────────────────────────────────────────\r\n\r\nconst lightDefaults: Required<ChatTheme> = {\r\n primaryColor: '#6C5CE7',\r\n headerBg: 'linear-gradient(135deg, #6C5CE7 0%, #A29BFE 100%)',\r\n headerText: '#FFFFFF',\r\n bubbleBg: 'rgba(241, 243, 249, 0.85)',\r\n bubbleText: '#2D3436',\r\n userBubbleBg: 'linear-gradient(135deg, #6C5CE7 0%, #A29BFE 100%)',\r\n userBubbleText: '#FFFFFF',\r\n fontFamily: '\"Inter\", -apple-system, BlinkMacSystemFont, \"Segoe UI\", Roboto, sans-serif',\r\n fontSize: '14px',\r\n borderRadius: '20px',\r\n windowWidth: '400px',\r\n windowHeight: '600px',\r\n mode: 'light',\r\n};\r\n\r\n// ─── Dark Mode Overrides ─────────────────────────────────────────\r\n\r\nconst darkOverrides: Partial<ChatTheme> = {\r\n headerBg: 'linear-gradient(135deg, #2D1B69 0%, #4A3298 100%)',\r\n headerText: '#F0F0FF',\r\n bubbleBg: 'rgba(45, 45, 70, 0.85)',\r\n bubbleText: '#E8E8F0',\r\n userBubbleBg: 'linear-gradient(135deg, #6C5CE7 0%, #A29BFE 100%)',\r\n userBubbleText: '#FFFFFF',\r\n};\r\n\r\nexport function resolveTheme(theme?: ChatTheme): Required<ChatTheme> {\r\n const base = { ...lightDefaults, ...theme };\r\n if (base.mode === 'dark') {\r\n return { ...base, ...darkOverrides, ...theme };\r\n }\r\n return base;\r\n}\r\n\r\n// ─── CSS Custom Properties ───────────────────────────────────────\r\n\r\nexport function buildCSSVariables(theme: Required<ChatTheme>): Record<string, string> {\r\n return {\r\n '--cb-primary': theme.primaryColor,\r\n '--cb-header-bg': theme.headerBg,\r\n '--cb-header-text': theme.headerText,\r\n '--cb-bubble-bg': theme.bubbleBg,\r\n '--cb-bubble-text': theme.bubbleText,\r\n '--cb-user-bubble-bg': theme.userBubbleBg,\r\n '--cb-user-bubble-text': theme.userBubbleText,\r\n '--cb-font-family': theme.fontFamily,\r\n '--cb-font-size': theme.fontSize,\r\n '--cb-border-radius': theme.borderRadius,\r\n '--cb-window-width': theme.windowWidth,\r\n '--cb-window-height': theme.windowHeight,\r\n '--cb-bg': theme.mode === 'dark' ? 'rgba(22, 22, 40, 0.95)' : 'rgba(255, 255, 255, 0.92)',\r\n '--cb-border': theme.mode === 'dark' ? 'rgba(255,255,255,0.08)' : 'rgba(0,0,0,0.06)',\r\n '--cb-input-bg': theme.mode === 'dark' ? 'rgba(40, 40, 65, 0.8)' : 'rgba(245, 247, 252, 0.9)',\r\n '--cb-input-border': theme.mode === 'dark' ? 'rgba(255,255,255,0.1)' : 'rgba(0,0,0,0.06)',\r\n '--cb-input-text': theme.mode === 'dark' ? '#E0E0E0' : '#2D3436',\r\n '--cb-branding-bg': theme.mode === 'dark' ? 'rgba(20, 20, 35, 0.8)' : 'rgba(250, 250, 255, 0.8)',\r\n };\r\n}\r\n\r\n// ─── Inline Styles Builder ───────────────────────────────────────\r\n\r\nexport function buildStyles(\r\n theme: Required<ChatTheme>,\r\n overrides?: ChatStyle,\r\n) {\r\n const isDark = theme.mode === 'dark';\r\n\r\n const styles = {\r\n root: {\r\n fontFamily: theme.fontFamily,\r\n fontSize: theme.fontSize,\r\n lineHeight: '1.5',\r\n } satisfies CSSProperties,\r\n\r\n launcher: {\r\n position: 'fixed',\r\n width: '62px',\r\n height: '62px',\r\n borderRadius: '50%',\r\n background: theme.headerBg,\r\n color: '#fff',\r\n border: 'none',\r\n cursor: 'pointer',\r\n display: 'flex',\r\n alignItems: 'center',\r\n justifyContent: 'center',\r\n boxShadow: `0 6px 24px rgba(108, 92, 231, 0.4), 0 2px 8px rgba(0,0,0,0.1)`,\r\n transition: 'all 0.3s cubic-bezier(0.4, 0, 0.2, 1)',\r\n zIndex: 9998,\r\n ...overrides?.launcher,\r\n } satisfies CSSProperties,\r\n\r\n window: {\r\n position: 'fixed',\r\n width: theme.windowWidth,\r\n height: theme.windowHeight,\r\n maxHeight: '85vh',\r\n borderRadius: theme.borderRadius,\r\n overflow: 'hidden',\r\n display: 'flex',\r\n flexDirection: 'column',\r\n boxShadow: isDark\r\n ? '0 20px 60px rgba(0,0,0,0.5), 0 0 0 1px rgba(255,255,255,0.05)'\r\n : '0 20px 60px rgba(108, 92, 231, 0.15), 0 8px 24px rgba(0,0,0,0.08), 0 0 0 1px rgba(0,0,0,0.04)',\r\n backgroundColor: isDark ? 'rgba(22, 22, 40, 0.95)' : 'rgba(255, 255, 255, 0.95)',\r\n backdropFilter: 'blur(20px)',\r\n WebkitBackdropFilter: 'blur(20px)',\r\n border: isDark ? '1px solid rgba(255,255,255,0.08)' : '1px solid rgba(255,255,255,0.8)',\r\n zIndex: 9999,\r\n animation: 'cb-window-enter 0.35s cubic-bezier(0.4, 0, 0.2, 1)',\r\n ...overrides?.window,\r\n } satisfies CSSProperties,\r\n\r\n header: {\r\n background: theme.headerBg,\r\n color: theme.headerText,\r\n padding: '18px 20px',\r\n display: 'flex',\r\n alignItems: 'center',\r\n justifyContent: 'space-between',\r\n gap: '12px',\r\n flexShrink: 0,\r\n position: 'relative',\r\n overflow: 'hidden',\r\n ...overrides?.header,\r\n } satisfies CSSProperties,\r\n\r\n messageList: {\r\n flex: 1,\r\n overflowY: 'auto',\r\n padding: '20px 16px',\r\n display: 'flex',\r\n flexDirection: 'column',\r\n gap: '10px',\r\n background: isDark\r\n ? 'linear-gradient(180deg, rgba(22, 22, 40, 0.98) 0%, rgba(30, 30, 50, 0.98) 100%)'\r\n : 'linear-gradient(180deg, rgba(248, 249, 254, 0.95) 0%, rgba(255, 255, 255, 0.95) 100%)',\r\n ...overrides?.messageList,\r\n } satisfies CSSProperties,\r\n\r\n inputArea: {\r\n padding: '12px 16px 14px',\r\n borderTop: `1px solid ${isDark ? 'rgba(255,255,255,0.06)' : 'rgba(0,0,0,0.05)'}`,\r\n backgroundColor: isDark ? 'rgba(20, 20, 38, 0.9)' : 'rgba(255, 255, 255, 0.95)',\r\n backdropFilter: 'blur(12px)',\r\n WebkitBackdropFilter: 'blur(12px)',\r\n flexShrink: 0,\r\n ...overrides?.inputArea,\r\n } satisfies CSSProperties,\r\n\r\n botBubble: {\r\n background: isDark ? 'rgba(45, 45, 70, 0.7)' : 'rgba(241, 243, 249, 0.9)',\r\n color: isDark ? '#E8E8F0' : '#2D3436',\r\n padding: '12px 16px',\r\n borderRadius: '18px 18px 18px 4px',\r\n maxWidth: '82%',\r\n alignSelf: 'flex-start',\r\n wordBreak: 'break-word',\r\n whiteSpace: 'pre-wrap',\r\n backdropFilter: 'blur(8px)',\r\n WebkitBackdropFilter: 'blur(8px)',\r\n border: isDark ? '1px solid rgba(255,255,255,0.06)' : '1px solid rgba(0,0,0,0.04)',\r\n boxShadow: isDark\r\n ? '0 2px 8px rgba(0,0,0,0.2)'\r\n : '0 2px 8px rgba(0,0,0,0.04)',\r\n fontSize: '14px',\r\n lineHeight: '1.55',\r\n letterSpacing: '0.01em',\r\n } satisfies CSSProperties,\r\n\r\n userBubble: {\r\n background: theme.userBubbleBg,\r\n color: theme.userBubbleText,\r\n padding: '12px 16px',\r\n borderRadius: '18px 18px 4px 18px',\r\n maxWidth: '82%',\r\n alignSelf: 'flex-end',\r\n wordBreak: 'break-word',\r\n whiteSpace: 'pre-wrap',\r\n boxShadow: '0 4px 14px rgba(108, 92, 231, 0.25)',\r\n fontSize: '14px',\r\n lineHeight: '1.55',\r\n letterSpacing: '0.01em',\r\n } satisfies CSSProperties,\r\n };\r\n\r\n return styles;\r\n}\r\n\r\nexport type ChatStyles = ReturnType<typeof buildStyles>;\r\n","import React from 'react';\n\ninterface IconProps {\n size?: number;\n color?: string;\n className?: string;\n}\n\nexport const SendIcon: React.FC<IconProps> = ({ size = 18, color = 'currentColor' }) => (\n <svg width={size} height={size} viewBox=\"0 0 24 24\" fill={color}>\n <path d=\"M2.01 21L23 12 2.01 3 2 10l15 2-15 2z\" />\n </svg>\n);\n\nexport const ChatBubbleIcon: React.FC<IconProps> = ({ size = 28, color = 'currentColor' }) => (\n <svg width={size} height={size} viewBox=\"0 0 24 24\" fill=\"none\" stroke={color} strokeWidth=\"2\" strokeLinecap=\"round\" strokeLinejoin=\"round\">\n <path d=\"M21 15a2 2 0 0 1-2 2H7l-4 4V5a2 2 0 0 1 2-2h14a2 2 0 0 1 2 2z\" />\n </svg>\n);\n\nexport const CloseIcon: React.FC<IconProps> = ({ size = 20, color = 'currentColor' }) => (\n <svg width={size} height={size} viewBox=\"0 0 24 24\" fill=\"none\" stroke={color} strokeWidth=\"2\" strokeLinecap=\"round\" strokeLinejoin=\"round\">\n <line x1=\"18\" y1=\"6\" x2=\"6\" y2=\"18\" />\n <line x1=\"6\" y1=\"6\" x2=\"18\" y2=\"18\" />\n </svg>\n);\n\nexport const MinimizeIcon: React.FC<IconProps> = ({ size = 20, color = 'currentColor' }) => (\n <svg width={size} height={size} viewBox=\"0 0 24 24\" fill=\"none\" stroke={color} strokeWidth=\"2\" strokeLinecap=\"round\" strokeLinejoin=\"round\">\n <line x1=\"5\" y1=\"12\" x2=\"19\" y2=\"12\" />\n </svg>\n);\n\nexport const EmojiIcon: React.FC<IconProps> = ({ size = 20, color = 'currentColor' }) => (\n <svg width={size} height={size} viewBox=\"0 0 24 24\" fill=\"none\" stroke={color} strokeWidth=\"2\" strokeLinecap=\"round\" strokeLinejoin=\"round\">\n <circle cx=\"12\" cy=\"12\" r=\"10\" />\n <path d=\"M8 14s1.5 2 4 2 4-2 4-2\" />\n <line x1=\"9\" y1=\"9\" x2=\"9.01\" y2=\"9\" />\n <line x1=\"15\" y1=\"9\" x2=\"15.01\" y2=\"9\" />\n </svg>\n);\n\nexport const AttachmentIcon: React.FC<IconProps> = ({ size = 20, color = 'currentColor' }) => (\n <svg width={size} height={size} viewBox=\"0 0 24 24\" fill=\"none\" stroke={color} strokeWidth=\"2\" strokeLinecap=\"round\" strokeLinejoin=\"round\">\n <path d=\"M21.44 11.05l-9.19 9.19a6 6 0 01-8.49-8.49l9.19-9.19a4 4 0 015.66 5.66l-9.2 9.19a2 2 0 01-2.83-2.83l8.49-8.48\" />\n </svg>\n);\n\nexport const FileIcon: React.FC<IconProps> = ({ size = 16, color = 'currentColor' }) => (\n <svg width={size} height={size} viewBox=\"0 0 24 24\" fill=\"none\" stroke={color} strokeWidth=\"2\" strokeLinecap=\"round\" strokeLinejoin=\"round\">\n <path d=\"M14 2H6a2 2 0 00-2 2v16a2 2 0 002 2h12a2 2 0 002-2V8z\" />\n <polyline points=\"14 2 14 8 20 8\" />\n </svg>\n);\n\nexport const ImageIcon: React.FC<IconProps> = ({ size = 16, color = 'currentColor' }) => (\n <svg width={size} height={size} viewBox=\"0 0 24 24\" fill=\"none\" stroke={color} strokeWidth=\"2\" strokeLinecap=\"round\" strokeLinejoin=\"round\">\n <rect x=\"3\" y=\"3\" width=\"18\" height=\"18\" rx=\"2\" ry=\"2\" />\n <circle cx=\"8.5\" cy=\"8.5\" r=\"1.5\" />\n <polyline points=\"21 15 16 10 5 21\" />\n </svg>\n);\n\nexport const RemoveIcon: React.FC<IconProps> = ({ size = 14, color = 'currentColor' }) => (\n <svg width={size} height={size} viewBox=\"0 0 24 24\" fill=\"none\" stroke={color} strokeWidth=\"2\" strokeLinecap=\"round\" strokeLinejoin=\"round\">\n <circle cx=\"12\" cy=\"12\" r=\"10\" />\n <line x1=\"15\" y1=\"9\" x2=\"9\" y2=\"15\" />\n <line x1=\"9\" y1=\"9\" x2=\"15\" y2=\"15\" />\n </svg>\n);\n\nexport const RestartIcon: React.FC<IconProps> = ({ size = 16, color = 'currentColor' }) => (\n <svg width={size} height={size} viewBox=\"0 0 24 24\" fill=\"none\" stroke={color} strokeWidth=\"2\" strokeLinecap=\"round\" strokeLinejoin=\"round\">\n <polyline points=\"1 4 1 10 7 10\" />\n <path d=\"M3.51 15a9 9 0 1 0 2.13-9.36L1 10\" />\n </svg>\n);\n","import React from 'react';\nimport type { CSSProperties } from 'react';\nimport type { ChatStyles } from '../styles/theme';\nimport { ChatBubbleIcon, CloseIcon } from './icons';\n\ninterface LauncherProps {\n onClick: () => void;\n isOpen: boolean;\n position: 'bottom-right' | 'bottom-left';\n styles: ChatStyles;\n icon?: React.ReactNode;\n closeIcon?: React.ReactNode;\n zIndex?: number;\n}\n\nexport const Launcher: React.FC<LauncherProps> = ({\n onClick,\n isOpen,\n position,\n styles,\n icon,\n closeIcon,\n zIndex,\n}) => {\n const posStyle: CSSProperties =\n position === 'bottom-left'\n ? { bottom: '24px', left: '24px' }\n : { bottom: '24px', right: '24px' };\n\n return (\n <button\n onClick={onClick}\n aria-label={isOpen ? 'Close chat' : 'Open chat'}\n style={{\n ...styles.launcher,\n ...posStyle,\n ...(zIndex != null ? { zIndex } : {}),\n transform: isOpen ? 'scale(0.92) rotate(90deg)' : 'scale(1)',\n animation: isOpen ? 'none' : 'cb-launcher-pulse 3s ease-in-out infinite',\n }}\n >\n {isOpen\n ? closeIcon ?? <CloseIcon size={22} />\n : icon ?? <ChatBubbleIcon size={26} />}\n </button>\n );\n};\n","import React from 'react';\nimport type { HeaderConfig } from '../types';\nimport type { ChatStyles as ThemeStyles } from '../styles/theme';\nimport { CloseIcon, MinimizeIcon, RestartIcon } from './icons';\n\ninterface ChatHeaderProps {\n config: HeaderConfig;\n styles: ThemeStyles;\n onClose: () => void;\n onRestart?: () => void;\n logo?: string;\n logoWidth?: string;\n}\n\nexport const ChatHeader: React.FC<ChatHeaderProps> = ({ config, styles, onClose, onRestart, logo, logoWidth }) => {\n return (\n <div style={styles.header}>\n {/* Decorative glow overlay */}\n <div\n style={{\n position: 'absolute',\n top: 0,\n left: 0,\n right: 0,\n bottom: 0,\n background: 'linear-gradient(135deg, rgba(255,255,255,0.12) 0%, transparent 50%)',\n pointerEvents: 'none',\n }}\n />\n <div style={{ display: 'flex', alignItems: 'center', gap: '12px', flex: 1, position: 'relative', zIndex: 1 }}>\n {config.avatar && (\n <div style={{ position: 'relative' }}>\n <img\n src={config.avatar}\n alt=\"\"\n style={{\n width: '40px',\n height: '40px',\n borderRadius: '50%',\n objectFit: 'cover',\n border: '2px solid rgba(255,255,255,0.3)',\n }}\n />\n <span\n style={{\n position: 'absolute',\n bottom: '1px',\n right: '1px',\n width: '10px',\n height: '10px',\n backgroundColor: '#2ECC71',\n borderRadius: '50%',\n border: '2px solid rgba(255,255,255,0.8)',\n }}\n />\n </div>\n )}\n {logo && !config.avatar && (\n <img\n src={logo}\n alt=\"\"\n style={{ width: logoWidth ?? '36px', height: 'auto', objectFit: 'contain', filter: 'brightness(1.1)' }}\n />\n )}\n {!config.avatar && !logo && (\n <div\n style={{\n width: '40px',\n height: '40px',\n borderRadius: '50%',\n background: 'rgba(255,255,255,0.2)',\n backdropFilter: 'blur(4px)',\n display: 'flex',\n alignItems: 'center',\n justifyContent: 'center',\n fontSize: '18px',\n fontWeight: 700,\n color: 'rgba(255,255,255,0.9)',\n border: '1px solid rgba(255,255,255,0.2)',\n }}\n >\n {(config.title ?? 'C').charAt(0).toUpperCase()}\n </div>\n )}\n <div>\n <div style={{ fontWeight: 600, fontSize: '16px', letterSpacing: '-0.01em' }}>\n {config.title ?? 'Chat with us'}\n </div>\n {config.subtitle && (\n <div style={{\n fontSize: '12px',\n opacity: 0.8,\n display: 'flex',\n alignItems: 'center',\n gap: '5px',\n marginTop: '1px',\n }}>\n <span style={{\n width: '6px',\n height: '6px',\n borderRadius: '50%',\n backgroundColor: '#2ECC71',\n display: 'inline-block',\n }} />\n {config.subtitle}\n </div>\n )}\n </div>\n </div>\n <div style={{ display: 'flex', alignItems: 'center', gap: '2px', position: 'relative', zIndex: 1 }}>\n {config.showRestart && onRestart && (\n <button\n onClick={onRestart}\n aria-label=\"Restart conversation\"\n title=\"Restart conversation\"\n style={{\n background: 'rgba(255,255,255,0.1)',\n border: 'none',\n color: 'inherit',\n cursor: 'pointer',\n padding: '6px',\n display: 'flex',\n alignItems: 'center',\n borderRadius: '8px',\n transition: 'background 0.2s ease',\n }}\n onMouseEnter={(e) => (e.currentTarget.style.background = 'rgba(255,255,255,0.2)')}\n onMouseLeave={(e) => (e.currentTarget.style.background = 'rgba(255,255,255,0.1)')}\n >\n <RestartIcon size={16} />\n </button>\n )}\n {config.showMinimize && (\n <button\n onClick={onClose}\n aria-label=\"Minimize chat\"\n style={{\n background: 'rgba(255,255,255,0.1)',\n border: 'none',\n color: 'inherit',\n cursor: 'pointer',\n padding: '6px',\n display: 'flex',\n alignItems: 'center',\n borderRadius: '8px',\n transition: 'background 0.2s ease',\n }}\n onMouseEnter={(e) => (e.currentTarget.style.background = 'rgba(255,255,255,0.2)')}\n onMouseLeave={(e) => (e.currentTarget.style.background = 'rgba(255,255,255,0.1)')}\n >\n <MinimizeIcon size={16} />\n </button>\n )}\n {config.showClose !== false && (\n <button\n onClick={onClose}\n aria-label=\"Close chat\"\n style={{\n background: 'rgba(255,255,255,0.1)',\n border: 'none',\n color: 'inherit',\n cursor: 'pointer',\n padding: '6px',\n display: 'flex',\n alignItems: 'center',\n borderRadius: '8px',\n transition: 'background 0.2s ease',\n }}\n onMouseEnter={(e) => (e.currentTarget.style.background = 'rgba(255,255,255,0.2)')}\n onMouseLeave={(e) => (e.currentTarget.style.background = 'rgba(255,255,255,0.1)')}\n >\n <CloseIcon size={18} />\n </button>\n )}\n </div>\n </div>\n );\n};\n","import React from 'react';\nimport type { ReactNode } from 'react';\n\ninterface WelcomeScreenProps {\n content: ReactNode;\n onDismiss: () => void;\n primaryColor: string;\n}\n\nexport const WelcomeScreen: React.FC<WelcomeScreenProps> = ({ content, onDismiss, primaryColor }) => {\n return (\n <div\n style={{\n flex: 1,\n display: 'flex',\n flexDirection: 'column',\n overflow: 'auto',\n background: 'linear-gradient(180deg, rgba(248, 249, 254, 0.95) 0%, rgba(255, 255, 255, 0.98) 100%)',\n }}\n >\n <div style={{ flex: 1, padding: '28px 24px', overflow: 'auto' }}>\n {content}\n </div>\n <div\n style={{\n padding: '16px 20px',\n borderTop: '1px solid rgba(0,0,0,0.05)',\n backdropFilter: 'blur(12px)',\n WebkitBackdropFilter: 'blur(12px)',\n flexShrink: 0,\n }}\n >\n <button\n onClick={onDismiss}\n style={{\n width: '100%',\n padding: '14px',\n background: `linear-gradient(135deg, ${primaryColor} 0%, ${adjustColor(primaryColor, 30)} 100%)`,\n color: '#fff',\n border: 'none',\n borderRadius: '14px',\n fontSize: '15px',\n fontWeight: 600,\n cursor: 'pointer',\n fontFamily: 'inherit',\n letterSpacing: '0.02em',\n boxShadow: `0 6px 20px ${primaryColor}44`,\n transition: 'all 0.25s cubic-bezier(0.4, 0, 0.2, 1)',\n }}\n onMouseEnter={(e) => {\n e.currentTarget.style.transform = 'translateY(-1px)';\n e.currentTarget.style.boxShadow = `0 8px 28px ${primaryColor}55`;\n }}\n onMouseLeave={(e) => {\n e.currentTarget.style.transform = 'translateY(0)';\n e.currentTarget.style.boxShadow = `0 6px 20px ${primaryColor}44`;\n }}\n >\n Start Chat\n </button>\n </div>\n </div>\n );\n};\n\nfunction adjustColor(hex: string, amount: number): string {\n const num = parseInt(hex.replace('#', ''), 16);\n const r = Math.min(255, ((num >> 16) & 0xff) + amount);\n const g = Math.min(255, ((num >> 8) & 0xff) + amount);\n const b = Math.min(255, (num & 0xff) + amount);\n return `#${((r << 16) | (g << 8) | b).toString(16).padStart(6, '0')}`;\n}\n","import React from 'react';\nimport type { FormFieldConfig } from '../../types';\n\ninterface TextFieldProps {\n field: FormFieldConfig;\n value: string;\n onChange: (value: string) => void;\n error?: string;\n}\n\nexport const TextField: React.FC<TextFieldProps> = ({ field, value, onChange, error }) => {\n const isTextarea = field.type === 'textarea';\n const inputType = field.type === 'textarea' ? undefined : field.type;\n\n const baseStyle: React.CSSProperties = {\n width: '100%',\n padding: '10px 14px',\n border: `1.5px solid ${error ? 'rgba(229, 62, 62, 0.5)' : 'rgba(0,0,0,0.08)'}`,\n borderRadius: '12px',\n fontSize: '13px',\n fontFamily: 'inherit',\n outline: 'none',\n boxSizing: 'border-box',\n transition: 'all 0.2s ease',\n backgroundColor: 'rgba(245, 247, 252, 0.6)',\n color: '#2D3436',\n letterSpacing: '0.01em',\n };\n\n return (\n <div style={{ marginBottom: '14px' }}>\n {field.label && (\n <label style={{ display: 'block', marginBottom: '6px', fontSize: '13px', fontWeight: 500, color: '#2D3436' }}>\n {field.label}\n {field.required && <span style={{ color: '#E53E3E', marginLeft: '3px' }}>*</span>}\n </label>\n )}\n {isTextarea ? (\n <textarea\n value={value}\n onChange={(e) => onChange(e.target.value)}\n placeholder={field.placeholder}\n required={field.required}\n rows={3}\n style={{ ...baseStyle, resize: 'vertical' }}\n minLength={field.validation?.minLength}\n maxLength={field.validation?.maxLength}\n />\n ) : (\n <input\n type={inputType}\n value={value}\n onChange={(e) => onChange(e.target.value)}\n placeholder={field.placeholder}\n required={field.required}\n style={baseStyle}\n min={field.validation?.min}\n max={field.validation?.max}\n minLength={field.validation?.minLength}\n maxLength={field.validation?.maxLength}\n pattern={field.validation?.pattern}\n />\n )}\n {error && <div style={{ color: '#E53E3E', fontSize: '12px', marginTop: '2px' }}>{error}</div>}\n </div>\n );\n};\n","import React from 'react';\nimport type { FormFieldConfig } from '../../types';\n\ninterface SelectFieldProps {\n field: FormFieldConfig;\n value: string | string[];\n onChange: (value: string | string[]) => void;\n error?: string;\n}\n\nexport const SelectField: React.FC<SelectFieldProps> = ({ field, value, onChange, error }) => {\n const isMulti = field.type === 'multiselect' || field.multiple;\n\n const handleChange = (e: React.ChangeEvent<HTMLSelectElement>) => {\n if (isMulti) {\n const selected = Array.from(e.target.selectedOptions, (opt) => opt.value);\n onChange(selected);\n } else {\n onChange(e.target.value);\n }\n };\n\n const selectValue = isMulti\n ? Array.isArray(value) ? value : [value].filter(Boolean)\n : typeof value === 'string' ? value : '';\n\n return (\n <div style={{ marginBottom: '14px' }}>\n {field.label && (\n <label style={{ display: 'block', marginBottom: '6px', fontSize: '13px', fontWeight: 500, color: '#2D3436' }}>\n {field.label}\n {field.required && <span style={{ color: '#E53E3E', marginLeft: '3px' }}>*</span>}\n </label>\n )}\n <select\n value={selectValue}\n onChange={handleChange}\n multiple={isMulti}\n required={field.required}\n style={{\n width: '100%',\n padding: '10px 14px',\n border: `1.5px solid ${error ? 'rgba(229, 62, 62, 0.5)' : 'rgba(0,0,0,0.08)'}`,\n borderRadius: '12px',\n fontSize: '13px',\n fontFamily: 'inherit',\n outline: 'none',\n backgroundColor: 'rgba(245, 247, 252, 0.6)',\n color: '#2D3436',\n boxSizing: 'border-box',\n transition: 'all 0.2s ease',\n ...(isMulti ? { minHeight: '80px' } : {}),\n }}\n >\n {!isMulti && <option value=\"\">Select...</option>}\n {field.options?.map((opt) => (\n <option key={opt.value} value={opt.value}>\n {opt.label}\n </option>\n ))}\n </select>\n {isMulti && (\n <div style={{ fontSize: '11px', color: '#888', marginTop: '2px' }}>\n Hold Ctrl/Cmd to select multiple\n </div>\n )}\n {error && <div style={{ color: '#E53E3E', fontSize: '12px', marginTop: '2px' }}>{error}</div>}\n </div>\n );\n};\n","import React from 'react';\nimport type { FormFieldConfig } from '../../types';\n\ninterface RadioFieldProps {\n field: FormFieldConfig;\n value: string;\n onChange: (value: string) => void;\n error?: string;\n}\n\nexport const RadioField: React.FC<RadioFieldProps> = ({ field, value, onChange, error }) => {\n return (\n <div style={{ marginBottom: '12px' }}>\n {field.label && (\n <label style={{ display: 'block', marginBottom: '6px', fontSize: '13px', fontWeight: 500 }}>\n {field.label}\n {field.required && <span style={{ color: '#E53E3E', marginLeft: '2px' }}>*</span>}\n </label>\n )}\n <div style={{ display: 'flex', flexDirection: 'column', gap: '6px' }}>\n {field.options?.map((opt) => (\n <label\n key={opt.value}\n style={{\n display: 'flex',\n alignItems: 'center',\n gap: '8px',\n cursor: 'pointer',\n fontSize: '13px',\n }}\n >\n <input\n type=\"radio\"\n name={field.name}\n value={opt.value}\n checked={value === opt.value}\n onChange={() => onChange(opt.value)}\n style={{ margin: 0 }}\n />\n {opt.label}\n </label>\n ))}\n </div>\n {error && <div style={{ color: '#E53E3E', fontSize: '12px', marginTop: '2px' }}>{error}</div>}\n </div>\n );\n};\n","import React from 'react';\nimport type { FormFieldConfig } from '../../types';\n\ninterface CheckboxFieldProps {\n field: FormFieldConfig;\n value: string[];\n onChange: (value: string[]) => void;\n error?: string;\n}\n\nexport const CheckboxField: React.FC<CheckboxFieldProps> = ({ field, value, onChange, error }) => {\n const handleToggle = (optValue: string) => {\n if (value.includes(optValue)) {\n onChange(value.filter((v) => v !== optValue));\n } else {\n onChange([...value, optValue]);\n }\n };\n\n return (\n <div style={{ marginBottom: '12px' }}>\n {field.label && (\n <label style={{ display: 'block', marginBottom: '6px', fontSize: '13px', fontWeight: 500 }}>\n {field.label}\n {field.required && <span style={{ color: '#E53E3E', marginLeft: '2px' }}>*</span>}\n </label>\n )}\n <div style={{ display: 'flex', flexDirection: 'column', gap: '6px' }}>\n {field.options?.map((opt) => (\n <label\n key={opt.value}\n style={{\n display: 'flex',\n alignItems: 'center',\n gap: '8px',\n cursor: 'pointer',\n fontSize: '13px',\n }}\n >\n <input\n type=\"checkbox\"\n checked={value.includes(opt.value)}\n onChange={() => handleToggle(opt.value)}\n style={{ margin: 0 }}\n />\n {opt.label}\n </label>\n ))}\n </div>\n {error && <div style={{ color: '#E53E3E', fontSize: '12px', marginTop: '2px' }}>{error}</div>}\n </div>\n );\n};\n","import React, { useRef } from 'react';\nimport type { FormFieldConfig } from '../../types';\n\ninterface FileUploadFieldProps {\n field: FormFieldConfig;\n value: FileList | null;\n onChange: (files: FileList | null) => void;\n error?: string;\n primaryColor: string;\n}\n\nexport const FileUploadField: React.FC<FileUploadFieldProps> = ({\n field,\n value,\n onChange,\n error,\n primaryColor,\n}) => {\n const inputRef = useRef<HTMLInputElement>(null);\n\n const fileNames = value ? Array.from(value).map((f) => f.name).join(', ') : '';\n\n return (\n <div style={{ marginBottom: '12px' }}>\n {field.label && (\n <label style={{ display: 'block', marginBottom: '4px', fontSize: '13px', fontWeight: 500 }}>\n {field.label}\n {field.required && <span style={{ color: '#E53E3E', marginLeft: '2px' }}>*</span>}\n </label>\n )}\n <input\n ref={inputRef}\n type=\"file\"\n accept={field.accept}\n multiple={field.multiple}\n onChange={(e) => onChange(e.target.files)}\n style={{ display: 'none' }}\n />\n <button\n type=\"button\"\n onClick={() => inputRef.current?.click()}\n style={{\n padding: '8px 16px',\n border: `1px dashed ${error ? '#E53E3E' : '#D1D5DB'}`,\n borderRadius: '8px',\n backgroundColor: '#FAFAFA',\n cursor: 'pointer',\n fontSize: '13px',\n color: '#555',\n width: '100%',\n textAlign: 'left',\n }}\n >\n {fileNames || field.placeholder || 'Choose file(s)...'}\n </button>\n {fileNames && (\n <div style={{ fontSize: '12px', color: primaryColor, marginTop: '4px' }}>\n {Array.from(value!).length} file(s) selected\n </div>\n )}\n {error && <div style={{ color: '#E53E3E', fontSize: '12px', marginTop: '2px' }}>{error}</div>}\n </div>\n );\n};\n","import React, { useState, useCallback } from 'react';\r\nimport type { FormConfig, FormFieldConfig } from '../../types';\r\nimport type { FormFieldRenderMap } from '../../types/form';\r\nimport { TextField } from './TextField';\r\nimport { SelectField } from './SelectField';\r\nimport { RadioField } from './RadioField';\r\nimport { CheckboxField } from './CheckboxField';\r\nimport { FileUploadField } from './FileUploadField';\r\n\r\ninterface DynamicFormProps {\r\n config: FormConfig;\r\n onSubmit: (data: Record<string, unknown>) => void;\r\n primaryColor: string;\r\n renderFormField?: FormFieldRenderMap;\r\n}\r\n\r\nexport const DynamicForm: React.FC<DynamicFormProps> = ({ config, onSubmit, primaryColor, renderFormField }) => {\r\n const [values, setValues] = useState<Record<string, unknown>>(() => {\r\n const init: Record<string, unknown> = {};\r\n for (const field of config.fields) {\r\n if (field.defaultValue !== undefined) {\r\n init[field.name] = field.defaultValue;\r\n } else if (field.type === 'checkbox' || field.type === 'multiselect') {\r\n init[field.name] = [];\r\n } else if (field.type === 'file') {\r\n init[field.name] = null;\r\n } else {\r\n init[field.name] = '';\r\n }\r\n }\r\n return init;\r\n });\r\n\r\n const [errors, setErrors] = useState<Record<string, string>>({});\r\n const [submitted, setSubmitted] = useState(false);\r\n\r\n const setValue = useCallback((name: string, value: unknown) => {\r\n setValues((prev) => ({ ...prev, [name]: value }));\r\n setErrors((prev) => {\r\n const next = { ...prev };\r\n delete next[name];\r\n return next;\r\n });\r\n }, []);\r\n\r\n const validate = (): boolean => {\r\n const newErrors: Record<string, string> = {};\r\n\r\n for (const field of config.fields) {\r\n const val = values[field.name];\r\n\r\n // Required check\r\n if (field.required) {\r\n if (\r\n val === '' ||\r\n val === null ||\r\n val === undefined ||\r\n (Array.isArray(val) && val.length === 0)\r\n ) {\r\n newErrors[field.name] = field.validation?.message ?? `${field.label || field.name} is required`;\r\n continue;\r\n }\r\n }\r\n\r\n // Pattern check\r\n if (field.validation?.pattern && typeof val === 'string' && val) {\r\n try {\r\n const regex = new RegExp(field.validation.pattern);\r\n if (!regex.test(val)) {\r\n newErrors[field.name] = field.validation.message ?? 'Invalid format';\r\n }\r\n } catch {\r\n // Invalid regex pattern in config — skip validation\r\n }\r\n }\r\n }\r\n\r\n setErrors(newErrors);\r\n return Object.keys(newErrors).length === 0;\r\n };\r\n\r\n const handleSubmit = (e: React.FormEvent) => {\r\n e.preventDefault();\r\n if (!validate()) return;\r\n setSubmitted(true);\r\n onSubmit(values);\r\n };\r\n\r\n if (submitted) {\r\n return (\r\n <div\r\n style={{\r\n padding: '16px',\r\n background: 'linear-gradient(135deg, rgba(46, 213, 115, 0.1), rgba(46, 213, 115, 0.05))',\r\n borderRadius: '14px',\r\n fontSize: '14px',\r\n color: '#2ecc71',\r\n textAlign: 'center',\r\n fontWeight: 500,\r\n border: '1px solid rgba(46, 213, 115, 0.15)',\r\n animation: 'cb-fade-in 0.3s ease-out',\r\n }}\r\n >\r\n ✓ Submitted successfully\r\n </div>\r\n );\r\n }\r\n\r\n return (\r\n <form\r\n onSubmit={handleSubmit}\r\n style={{\r\n background: 'rgba(255, 255, 255, 0.7)',\r\n backdropFilter: 'blur(12px)',\r\n WebkitBackdropFilter: 'blur(12px)',\r\n borderRadius: '16px',\r\n padding: '20px',\r\n border: '1px solid rgba(0,0,0,0.06)',\r\n boxShadow: '0 4px 16px rgba(0,0,0,0.04)',\r\n animation: 'cb-slide-up 0.35s ease-out',\r\n }}\r\n >\r\n {config.title && (\r\n <div style={{ fontWeight: 600, fontSize: '15px', marginBottom: '4px', color: '#2D3436', letterSpacing: '-0.01em' }}>\r\n {config.title}\r\n </div>\r\n )}\r\n {config.description && (\r\n <div style={{ fontSize: '12px', color: 'rgba(0,0,0,0.45)', marginBottom: '16px', lineHeight: '1.5' }}>\r\n {config.description}\r\n </div>\r\n )}\r\n\r\n {config.fields.map((field) => (\r\n <FormField\r\n key={field.name}\r\n field={field}\r\n value={values[field.name]}\r\n onChange={(v) => setValue(field.name, v)}\r\n error={errors[field.name]}\r\n primaryColor={primaryColor}\r\n renderFormField={renderFormField}\r\n />\r\n ))}\r\n\r\n <button\r\n type=\"submit\"\r\n style={{\r\n width: '100%',\r\n padding: '12px',\r\n background: `linear-gradient(135deg, ${primaryColor} 0%, ${adjustColor(primaryColor, 30)} 100%)`,\r\n color: '#fff',\r\n border: 'none',\r\n borderRadius: '12px',\r\n fontSize: '14px',\r\n fontWeight: 600,\r\n cursor: 'pointer',\r\n marginTop: '8px',\r\n fontFamily: 'inherit',\r\n letterSpacing: '0.02em',\r\n boxShadow: `0 4px 14px ${primaryColor}33`,\r\n transition: 'all 0.25s cubic-bezier(0.4, 0, 0.2, 1)',\r\n }}\r\n onMouseEnter={(e) => {\r\n e.currentTarget.style.transform = 'translateY(-1px)';\r\n e.currentTarget.style.boxShadow = `0 6px 20px ${primaryColor}44`;\r\n }}\r\n onMouseLeave={(e) => {\r\n e.currentTarget.style.transform = 'translateY(0)';\r\n e.currentTarget.style.boxShadow = `0 4px 14px ${primaryColor}33`;\r\n }}\r\n >\r\n {config.submitLabel ?? 'Submit'}\r\n </button>\r\n </form>\r\n );\r\n};\r\n\r\n// ─── Field Router ────────────────────────────────────────────────\r\n\r\ninterface FormFieldProps {\r\n field: FormFieldConfig;\r\n value: unknown;\r\n onChange: (value: unknown) => void;\r\n error?: string;\r\n primaryColor: string;\r\n renderFormField?: FormFieldRenderMap;\r\n}\r\n\r\nconst FormField: React.FC<FormFieldProps> = ({ field, value, onChange, error, primaryColor, renderFormField }) => {\r\n // Check for custom renderer override\r\n const customRenderer = renderFormField?.[field.type as keyof FormFieldRenderMap];\r\n\r\n switch (field.type) {\r\n case 'text':\r\n case 'email':\r\n case 'password':\r\n case 'number':\r\n case 'tel':\r\n case 'url':\r\n case 'textarea':\r\n case 'date':\r\n case 'time': {\r\n const typedProps = { type: field.type as 'text', field, value: String(value ?? ''), onChange: onChange as (v: string) => void, error };\r\n const defaultEl = <TextField field={field} value={String(value ?? '')} onChange={onChange as (v: string) => void} error={error} />;\r\n if (customRenderer) return <>{(customRenderer as (p: typeof typedProps, d: React.ReactNode) => React.ReactNode)(typedProps, defaultEl)}</>;\r\n return defaultEl;\r\n }\r\n case 'select':\r\n case 'multiselect': {\r\n const typedProps = { type: field.type as 'select', field, value: value as string | string[], onChange: onChange as (v: string | string[]) => void, error };\r\n const defaultEl = <SelectField field={field} value={value as string | string[]} onChange={onChange as (v: string | string[]) => void} error={error} />;\r\n if (customRenderer) return <>{(customRenderer as (p: typeof typedProps, d: React.ReactNode) => React.ReactNode)(typedProps, defaultEl)}</>;\r\n return defaultEl;\r\n }\r\n case 'radio': {\r\n const typedProps = { type: 'radio' as const, field, value: String(value ?? ''), onChange: onChange as (v: string) => void, error };\r\n const defaultEl = <RadioField field={field} value={String(value ?? '')} onChange={onChange as (v: string) => void} error={error} />;\r\n if (customRenderer) return <>{(customRenderer as (p: typeof typedProps, d: React.ReactNode) => React.ReactNode)(typedProps, defaultEl)}</>;\r\n return defaultEl;\r\n }\r\n case 'checkbox': {\r\n const typedProps = { type: 'checkbox' as const, field, value: ((value as string[]) ?? []), onChange: onChange as (v: string[]) => void, error };\r\n const defaultEl = <CheckboxField field={field} value={(value as string[]) ?? []} onChange={onChange as (v: string[]) => void} error={error} />;\r\n if (customRenderer) return <>{(customRenderer as (p: typeof typedProps, d: React.ReactNode) => React.ReactNode)(typedProps, defaultEl)}</>;\r\n return defaultEl;\r\n }\r\n case 'file': {\r\n const typedProps = { type: 'file' as const, field, value: value as FileList | null, onChange: onChange as (v: FileList | null) => void, error, primaryColor };\r\n const defaultEl = <FileUploadField field={field} value={value as FileList | null} onChange={onChange as (v: FileList | null) => void} error={error} primaryColor={primaryColor} />;\r\n if (customRenderer) return <>{(customRenderer as (p: typeof typedProps, d: React.ReactNode) => React.ReactNode)(typedProps, defaultEl)}</>;\r\n return defaultEl;\r\n }\r\n case 'hidden':\r\n return <input type=\"hidden\" name={field.name} value={String(value ?? '')} />;\r\n default:\r\n return null;\r\n }\r\n};\r\n\r\nfunction adjustColor(hex: string, amount: number): string {\r\n const num = parseInt(hex.replace('#', ''), 16);\r\n const r = Math.min(255, ((num >> 16) & 0xff) + amount);\r\n const g = Math.min(255, ((num >> 8) & 0xff) + amount);\r\n const b = Math.min(255, (num & 0xff) + amount);\r\n return `#${((r << 16) | (g << 8) | b).toString(16).padStart(6, '0')}`;\r\n}\r\n","import React from 'react';\nimport type { FormConfig } from '../types';\nimport type { FormFieldRenderMap } from '../types/form';\nimport { DynamicForm } from './forms/DynamicForm';\n\ninterface LoginScreenProps {\n config: FormConfig;\n onLogin: (data: Record<string, unknown>) => void;\n primaryColor: string;\n renderFormField?: FormFieldRenderMap;\n}\n\nexport const LoginScreen: React.FC<LoginScreenProps> = ({ config, onLogin, primaryColor, renderFormField }) => {\n return (\n <div\n style={{\n flex: 1,\n display: 'flex',\n flexDirection: 'column',\n justifyContent: 'center',\n padding: '24px',\n overflow: 'auto',\n background: 'linear-gradient(180deg, rgba(248, 249, 254, 0.95) 0%, rgba(255, 255, 255, 0.98) 100%)',\n }}\n >\n <DynamicForm config={config} onSubmit={onLogin} primaryColor={primaryColor} renderFormField={renderFormField} />\n </div>\n );\n};\n","import React from 'react';\r\nimport type { ChatMessage, MessageAttachment } from '../types';\r\nimport type { ChatStyles } from '../styles/theme';\r\nimport { FileIcon } from './icons';\r\n\r\ninterface MessageBubbleProps {\r\n message: ChatMessage;\r\n styles: ChatStyles;\r\n}\r\n\r\nexport const MessageBubble: React.FC<MessageBubbleProps> = ({ message, styles }) => {\r\n const isBot = message.sender === 'bot';\r\n const isSystem = message.sender === 'system';\r\n const bubbleStyle = isBot || isSystem ? styles.botBubble : styles.userBubble;\r\n\r\n const hasContent = message.text || (message.attachments && message.attachments.length > 0);\r\n if (!hasContent) return null;\r\n\r\n const systemStyle: React.CSSProperties = isSystem\r\n ? {\r\n background: 'transparent',\r\n border: 'none',\r\n boxShadow: 'none',\r\n color: '#999',\r\n fontSize: '12px',\r\n alignSelf: 'center',\r\n padding: '6px 12px',\r\n backdropFilter: 'none',\r\n WebkitBackdropFilter: 'none',\r\n }\r\n : {};\r\n\r\n return (\r\n <div\r\n style={{\r\n ...bubbleStyle,\r\n ...systemStyle,\r\n animation: 'cb-fade-in 0.3s ease-out',\r\n }}\r\n >\r\n {message.text && (\r\n <span style={{ display: 'block' }}>{message.text}</span>\r\n )}\r\n {message.attachments && message.attachments.length > 0 && (\r\n <div style={{ marginTop: message.text ? '10px' : 0, display: 'flex', flexDirection: 'column', gap: '6px' }}>\r\n {message.attachments.map((attachment, i) => (\r\n <AttachmentPreview key={i} attachment={attachment} isBot={isBot} />\r\n ))}\r\n </div>\r\n )}\r\n </div>\r\n );\r\n};\r\n\r\n// ─── Attachment Preview ──────────────────────────────────────────\r\n\r\ninterface AttachmentPreviewProps {\r\n attachment: MessageAttachment;\r\n isBot: boolean;\r\n}\r\n\r\nconst AttachmentPreview: React.FC<AttachmentPreviewProps> = ({ attachment, isBot }) => {\r\n const isImage = attachment.type.startsWith('image/');\r\n\r\n if (isImage && attachment.url) {\r\n return (\r\n <div style={{ borderRadius: '12px', overflow: 'hidden', maxWidth: '220px' }}>\r\n <img\r\n src={attachment.url}\r\n alt={attachment.name}\r\n style={{\r\n width: '100%',\r\n height: 'auto',\r\n display: 'block',\r\n borderRadius: '12px',\r\n }}\r\n />\r\n <div style={{ fontSize: '11px', padding: '4px 0', opacity: 0.6 }}>{attachment.name}</div>\r\n </div>\r\n );\r\n }\r\n\r\n return (\r\n <a\r\n href={attachment.url}\r\n target=\"_blank\"\r\n rel=\"noopener noreferrer\"\r\n style={{\r\n display: 'flex',\r\n alignItems: 'center',\r\n gap: '8px',\r\n padding: '8px 12px',\r\n backgroundColor: isBot ? 'rgba(0,0,0,0.04)' : 'rgba(255,255,255,0.15)',\r\n borderRadius: '10px',\r\n textDecoration: 'none',\r\n color: 'inherit',\r\n fontSize: '13px',\r\n border: isBot ? '1px solid rgba(0,0,0,0.06)' : '1px solid rgba(255,255,255,0.15)',\r\n transition: 'background 0.2s ease',\r\n }}\r\n >\r\n <FileIcon size={16} />\r\n <span style={{ overflow: 'hidden', textOverflow: 'ellipsis', whiteSpace: 'nowrap', flex: 1 }}>\r\n {attachment.name}\r\n </span>\r\n {attachment.size && (\r\n <span style={{ fontSize: '11px', opacity: 0.5, flexShrink: 0 }}>\r\n {formatFileSize(attachment.size)}\r\n </span>\r\n )}\r\n </a>\r\n );\r\n};\r\n\r\nfunction formatFileSize(bytes: number): string {\r\n if (bytes < 1024) return `${bytes}B`;\r\n if (bytes < 1024 * 1024) return `${(bytes / 1024).toFixed(1)}KB`;\r\n return `${(bytes / (1024 * 1024)).toFixed(1)}MB`;\r\n}\r\n","import React from 'react';\nimport type { FlowQuickReply } from '../types';\n\ninterface QuickRepliesProps {\n replies: FlowQuickReply[];\n onSelect: (value: string, label: string) => void;\n primaryColor: string;\n}\n\nexport const QuickReplies: React.FC<QuickRepliesProps> = ({ replies, onSelect, primaryColor }) => {\n return (\n <div\n style={{\n display: 'flex',\n flexWrap: 'wrap',\n gap: '8px',\n alignSelf: 'flex-start',\n maxWidth: '90%',\n animation: 'cb-slide-up 0.35s ease-out',\n padding: '4px 0',\n }}\n >\n {replies.map((reply) => (\n <button\n key={reply.value}\n onClick={() => onSelect(reply.value, reply.label)}\n style={{\n padding: '8px 18px',\n borderRadius: '22px',\n border: `1.5px solid ${primaryColor}`,\n backgroundColor: 'rgba(108, 92, 231, 0.06)',\n color: primaryColor,\n cursor: 'pointer',\n fontSize: '13px',\n fontWeight: 500,\n fontFamily: 'inherit',\n transition: 'all 0.25s cubic-bezier(0.4, 0, 0.2, 1)',\n backdropFilter: 'blur(4px)',\n WebkitBackdropFilter: 'blur(4px)',\n letterSpacing: '0.01em',\n }}\n onMouseEnter={(e) => {\n e.currentTarget.style.backgroundColor = primaryColor;\n e.currentTarget.style.color = '#fff';\n e.currentTarget.style.transform = 'translateY(-1px)';\n e.currentTarget.style.boxShadow = `0 4px 14px ${primaryColor}44`;\n }}\n onMouseLeave={(e) => {\n e.currentTarget.style.backgroundColor = 'rgba(108, 92, 231, 0.06)';\n e.currentTarget.style.color = primaryColor;\n e.currentTarget.style.transform = 'translateY(0)';\n e.currentTarget.style.boxShadow = 'none';\n }}\n >\n {reply.label}\n </button>\n ))}\n </div>\n );\n};\n","import React from 'react';\n\ninterface TypingIndicatorProps {\n color: string;\n}\n\nexport const TypingIndicator: React.FC<TypingIndicatorProps> = ({ color }) => {\n const dotStyle: React.CSSProperties = {\n width: '7px',\n height: '7px',\n borderRadius: '50%',\n backgroundColor: color,\n opacity: 0.35,\n animation: 'cb-typing-bounce 1.4s infinite ease-in-out',\n };\n\n return (\n <div\n style={{\n display: 'flex',\n gap: '5px',\n padding: '14px 18px',\n background: 'rgba(241, 243, 249, 0.8)',\n backdropFilter: 'blur(8px)',\n WebkitBackdropFilter: 'blur(8px)',\n borderRadius: '18px 18px 18px 4px',\n alignSelf: 'flex-start',\n alignItems: 'center',\n border: '1px solid rgba(0,0,0,0.04)',\n boxShadow: '0 2px 8px rgba(0,0,0,0.04)',\n animation: 'cb-fade-in 0.3s ease-out',\n }}\n >\n <span style={{ ...dotStyle, animationDelay: '0s' }} />\n <span style={{ ...dotStyle, animationDelay: '0.2s' }} />\n <span style={{ ...dotStyle, animationDelay: '0.4s' }} />\n </div>\n );\n};\n","import React, { useRef, useEffect } from 'react';\r\nimport type { ComponentType } from 'react';\r\nimport type { ChatMessage } from '../types';\r\nimport type { StepComponentProps, FlowActionResult } from '../types/config';\r\nimport type { FormFieldRenderMap } from '../types/form';\r\nimport type { ChatStyles } from '../styles/theme';\r\nimport { MessageBubble } from './MessageBubble';\r\nimport { QuickReplies } from './QuickReplies';\r\nimport { TypingIndicator } from './TypingIndicator';\r\nimport { DynamicForm } from './forms/DynamicForm';\r\n\r\ninterface MessageListProps {\r\n messages: ChatMessage[];\r\n isTyping: boolean;\r\n styles: ChatStyles;\r\n primaryColor: string;\r\n onQuickReply: (value: string, label: string) => void;\r\n onFormSubmit: (formId: string, data: Record<string, unknown>) => void;\r\n /** Map of custom step components */\r\n components?: Record<string, ComponentType<StepComponentProps>>;\r\n /** Called when a custom component completes */\r\n onComponentComplete?: (result?: FlowActionResult) => void;\r\n /** Collected flow data — passed to custom components */\r\n collectedData?: Record<string, unknown>;\r\n /** Current step ID */\r\n currentStepId?: string | null;\r\n /** Custom form field renderers per field type */\r\n renderFormField?: FormFieldRenderMap;\r\n}\r\n\r\nexport const MessageList: React.FC<MessageListProps> = ({\r\n messages,\r\n isTyping,\r\n styles,\r\n primaryColor,\r\n onQuickReply,\r\n onFormSubmit,\r\n components,\r\n onComponentComplete,\r\n collectedData,\r\n currentStepId,\r\n renderFormField,\r\n}) => {\r\n const bottomRef = useRef<HTMLDivElement>(null);\r\n\r\n useEffect(() => {\r\n bottomRef.current?.scrollIntoView({ behavior: 'smooth' });\r\n }, [messages, isTyping]);\r\n\r\n return (\r\n <div style={styles.messageList} className=\"cb-scrollbar\">\r\n {messages.map((msg) => (\r\n <React.Fragment key={msg.id}>\r\n <MessageBubble message={msg} styles={styles} />\r\n {msg.quickReplies && msg.quickReplies.length > 0 && (\r\n <QuickReplies\r\n replies={msg.quickReplies}\r\n onSelect={onQuickReply}\r\n primaryColor={primaryColor}\r\n />\r\n )}\r\n {msg.form && (\r\n <div style={{ alignSelf: 'flex-start', width: '92%', animation: 'cb-slide-up 0.35s ease-out' }}>\r\n <DynamicForm\r\n config={msg.form}\r\n onSubmit={(data) => onFormSubmit(msg.form!.id, data)}\r\n primaryColor={primaryColor}\r\n renderFormField={renderFormField}\r\n />\r\n </div>\r\n )}\r\n {msg.component && components?.[msg.component] && (\r\n <div style={{ alignSelf: 'flex-start', width: '92%', animation: 'cb-slide-up 0.35s ease-out' }}>\r\n {React.createElement(components[msg.component], {\r\n stepId: currentStepId ?? '',\r\n data: collectedData ?? {},\r\n onComplete: (result?: FlowActionResult) => onComponentComplete?.(result),\r\n })}\r\n </div>\r\n )}\r\n </React.Fragment>\r\n ))}\r\n {isTyping && <TypingIndicator color={primaryColor} />}\r\n <div ref={bottomRef} />\r\n </div>\r\n );\r\n};\r\n","import React, { useState, useRef, useEffect } from 'react';\n\nconst EMOJI_CATEGORIES = [\n {\n name: 'Smileys',\n emojis: ['😀', '😃', '😄', '😁', '😅', '😂', '🤣', '😊', '😇', '🙂', '😉', '😍', '🥰', '😘', '😋', '😜', '🤪', '🤗', '🤔', '🤫', '🤭', '😏', '😐', '😑', '😶', '😌', '😴', '🤤', '😷', '🤒'],\n },\n {\n name: 'Gestures',\n emojis: ['👍', '👎', '👌', '✌️', '🤞', '🤟', '🤘', '👋', '🤚', '✋', '🖖', '👏', '🙌', '🤝', '🙏', '💪', '🖐️', '☝️', '👆', '👇', '👈', '👉', '🤙', '🫡', '🫶', '🫰', '🫳', '🫴', '🫲', '🫱'],\n },\n {\n name: 'Hearts',\n emojis: ['❤️', '🧡', '💛', '💚', '💙', '💜', '🖤', '🤍', '🤎', '💔', '❣️', '💕', '💞', '💓', '💗', '💖', '💘', '💝', '💟', '♥️', '🫀', '💌', '💐', '🌹', '🌺', '🌸', '🌼', '🌻', '🌷', '💮'],\n },\n {\n name: 'Objects',\n emojis: ['🔥', '⭐', '✨', '💯', '🎉', '🎊', '🎯', '🚀', '💡', '📌', '📎', '🔗', '💻', '📱', '☎️', '📧', '📝', '📋', '📊', '📈', '🗂️', '📁', '🔒', '🔑', '⚙️', '🛠️', '🔧', '📦', '🏷️', '✅'],\n },\n];\n\ninterface EmojiPickerProps {\n onSelect: (emoji: string) => void;\n onClose: () => void;\n primaryColor: string;\n}\n\nexport const EmojiPicker: React.FC<EmojiPickerProps> = ({ onSelect, onClose, primaryColor }) => {\n const [activeCategory, setActiveCategory] = useState(0);\n const pickerRef = useRef<HTMLDivElement>(null);\n\n useEffect(() => {\n const handleClickOutside = (e: MouseEvent) => {\n if (pickerRef.current && !pickerRef.current.contains(e.target as Node)) {\n onClose();\n }\n };\n document.addEventListener('mousedown', handleClickOutside);\n return () => document.removeEventListener('mousedown', handleClickOutside);\n }, [onClose]);\n\n const currentEmojis = EMOJI_CATEGORIES[activeCategory]?.emojis ?? [];\n\n return (\n <div\n ref={pickerRef}\n style={{\n position: 'absolute',\n bottom: '100%',\n left: 0,\n width: '280px',\n backgroundColor: 'rgba(255, 255, 255, 0.92)',\n backdropFilter: 'blur(20px)',\n WebkitBackdropFilter: 'blur(20px)',\n borderRadius: '16px',\n boxShadow: '0 8px 32px rgba(0,0,0,0.12), 0 0 0 1px rgba(0,0,0,0.04)',\n border: '1px solid rgba(255,255,255,0.8)',\n overflow: 'hidden',\n zIndex: 10,\n marginBottom: '8px',\n animation: 'cb-slide-up 0.25s ease-out',\n }}\n >\n {/* Category tabs */}\n <div\n style={{\n display: 'flex',\n borderBottom: '1px solid rgba(0,0,0,0.06)',\n padding: '6px',\n gap: '3px',\n }}\n >\n {EMOJI_CATEGORIES.map((cat, idx) => (\n <button\n key={cat.name}\n onClick={() => setActiveCategory(idx)}\n title={cat.name}\n style={{\n flex: 1,\n padding: '6px 4px',\n border: 'none',\n borderRadius: '8px',\n cursor: 'pointer',\n fontSize: '11px',\n fontWeight: 600,\n fontFamily: 'inherit',\n letterSpacing: '0.02em',\n background: idx === activeCategory\n ? `linear-gradient(135deg, ${primaryColor}, ${primaryColor}CC)`\n : 'transparent',\n color: idx === activeCategory ? '#fff' : 'rgba(0,0,0,0.4)',\n transition: 'all 0.2s ease',\n boxShadow: idx === activeCategory ? `0 2px 8px ${primaryColor}33` : 'none',\n }}\n >\n {cat.name}\n </button>\n ))}\n </div>\n\n {/* Emoji Grid */}\n <div\n style={{\n display: 'grid',\n gridTemplateColumns: 'repeat(8, 1fr)',\n gap: '2px',\n padding: '8px',\n maxHeight: '180px',\n overflowY: 'auto',\n }}\n >\n {currentEmojis.map((emoji) => (\n <button\n key={emoji}\n onClick={() => {\n onSelect(emoji);\n onClose();\n }}\n style={{\n width: '30px',\n height: '30px',\n border: 'none',\n backgroundColor: 'transparent',\n cursor: 'pointer',\n fontSize: '18px',\n borderRadius: '6px',\n display: 'flex',\n alignItems: 'center',\n justifyContent: 'center',\n transition: 'all 0.15s ease',\n }}\n onMouseEnter={(e) => (e.currentTarget.style.backgroundColor = 'rgba(108, 92, 231, 0.08)')}\n onMouseLeave={(e) => (e.currentTarget.style.backgroundColor = 'transparent')}\n >\n {emoji}\n </button>\n ))}\n </div>\n </div>\n );\n};\n","import React, { useRef } from 'react';\r\nimport type { FileUploadConfig } from '../types/config';\r\nimport { AttachmentIcon, RemoveIcon, FileIcon, ImageIcon } from './icons';\r\n\r\ninterface FileUploadButtonProps {\r\n config: FileUploadConfig;\r\n onFiles: (files: File[]) => void;\r\n selectedFiles: File[];\r\n onRemoveFile: (index: number) => void;\r\n primaryColor: string;\r\n}\r\n\r\nexport const FileUploadButton: React.FC<FileUploadButtonProps> = ({\r\n config,\r\n onFiles,\r\n selectedFiles,\r\n onRemoveFile,\r\n primaryColor,\r\n}) => {\r\n const inputRef = useRef<HTMLInputElement>(null);\r\n\r\n const handleChange = (e: React.ChangeEvent<HTMLInputElement>) => {\r\n const files = e.target.files;\r\n if (!files || files.length === 0) return;\r\n\r\n const fileArr = Array.from(files);\r\n\r\n // Validate file size\r\n if (config.maxSize) {\r\n const oversized = fileArr.filter((f) => f.size > config.maxSize!);\r\n if (oversized.length > 0) {\r\n alert(`File(s) too large. Max size: ${formatSize(config.maxSize)}`);\r\n return;\r\n }\r\n }\r\n\r\n // Validate max count\r\n const maxFiles = config.maxFiles ?? 5;\r\n if (selectedFiles.length + fileArr.length > maxFiles) {\r\n alert(`Maximum ${maxFiles} files allowed`);\r\n return;\r\n }\r\n\r\n onFiles(fileArr);\r\n // Reset input to allow re-selecting same file\r\n if (inputRef.current) inputRef.current.value = '';\r\n };\r\n\r\n return (\r\n <div>\r\n <input\r\n ref={inputRef}\r\n type=\"file\"\r\n accept={config.accept}\r\n multiple={config.multiple !== false}\r\n onChange={handleChange}\r\n style={{ display: 'none' }}\r\n />\r\n <button\r\n type=\"button\"\r\n onClick={() => inputRef.current?.click()}\r\n aria-label=\"Attach file\"\r\n title=\"Attach file\"\r\n style={{\r\n background: 'none',\r\n border: 'none',\r\n cursor: 'pointer',\r\n padding: '6px',\r\n display: 'flex',\r\n alignItems: 'center',\r\n color: '#999',\r\n borderRadius: '6px',\r\n transition: 'color 0.15s ease',\r\n }}\r\n onMouseEnter={(e) => (e.currentTarget.style.color = primaryColor)}\r\n onMouseLeave={(e) => (e.currentTarget.style.color = '#999')}\r\n >\r\n <AttachmentIcon size={20} />\r\n </button>\r\n </div>\r\n );\r\n};\r\n\r\n// ─── File Preview List ───────────────────────────────────────────\r\n\r\ninterface FilePreviewListProps {\r\n files: File[];\r\n onRemove: (index: number) => void;\r\n primaryColor: string;\r\n}\r\n\r\nexport const FilePreviewList: React.FC<FilePreviewListProps> = ({\r\n files,\r\n onRemove,\r\n primaryColor,\r\n}) => {\r\n if (files.length === 0) return null;\r\n\r\n return (\r\n <div\r\n style={{\r\n display: 'flex',\r\n flexWrap: 'wrap',\r\n gap: '6px',\r\n padding: '8px 12px 0',\r\n }}\r\n >\r\n {files.map((file, idx) => (\r\n <FilePreviewChip\r\n key={`${file.name}-${idx}`}\r\n file={file}\r\n onRemove={() => onRemove(idx)}\r\n primaryColor={primaryColor}\r\n />\r\n ))}\r\n </div>\r\n );\r\n};\r\n\r\n// ─── Single File Chip ────────────────────────────────────────────\r\n\r\ninterface FilePreviewChipProps {\r\n file: File;\r\n onRemove: () => void;\r\n primaryColor: string;\r\n}\r\n\r\nconst FilePreviewChip: React.FC<FilePreviewChipProps> = ({ file, onRemove, primaryColor }) => {\r\n const isImage = file.type.startsWith('image/');\r\n\r\n return (\r\n <div\r\n style={{\r\n display: 'flex',\r\n alignItems: 'center',\r\n gap: '6px',\r\n padding: '4px 8px',\r\n backgroundColor: '#F3F4F6',\r\n borderRadius: '8px',\r\n fontSize: '12px',\r\n maxWidth: '200px',\r\n }}\r\n >\r\n <span style={{ color: primaryColor, flexShrink: 0 }}>\r\n {isImage ? <ImageIcon size={14} /> : <FileIcon size={14} />}\r\n </span>\r\n <span\r\n style={{\r\n overflow: 'hidden',\r\n textOverflow: 'ellipsis',\r\n whiteSpace: 'nowrap',\r\n color: '#555',\r\n }}\r\n >\r\n {file.name}\r\n </span>\r\n <span style={{ color: '#999', fontSize: '11px', flexShrink: 0 }}>\r\n {formatSize(file.size)}\r\n </span>\r\n <button\r\n onClick={onRemove}\r\n style={{\r\n background: 'none',\r\n border: 'none',\r\n cursor: 'pointer',\r\n padding: '0',\r\n display: 'flex',\r\n color: '#999',\r\n flexShrink: 0,\r\n }}\r\n >\r\n <RemoveIcon size={14} />\r\n </button>\r\n </div>\r\n );\r\n};\r\n\r\n// ─── Utils ───────────────────────────────────────────────────────\r\n\r\nfunction formatSize(bytes: number): string {\r\n if (bytes < 1024) return `${bytes}B`;\r\n if (bytes < 1024 * 1024) return `${(bytes / 1024).toFixed(1)}KB`;\r\n return `${(bytes / (1024 * 1024)).toFixed(1)}MB`;\r\n}\r\n","import React, { useState, useRef, useCallback } from 'react';\nimport type { CSSProperties } from 'react';\nimport type { FileUploadConfig } from '../types/config';\nimport { SendIcon, EmojiIcon } from './icons';\nimport { EmojiPicker } from './EmojiPicker';\nimport { FileUploadButton, FilePreviewList } from './FileUpload';\n\ninterface ChatInputProps {\n onSend: (text: string, files?: File[]) => void;\n placeholder?: string;\n primaryColor: string;\n isDark?: boolean;\n disabled?: boolean;\n styleOverride?: CSSProperties;\n enableEmoji?: boolean;\n fileUpload?: FileUploadConfig;\n onFileUpload?: (files: File[]) => void;\n}\n\nexport const ChatInput: React.FC<ChatInputProps> = ({\n onSend,\n placeholder = 'Type a message...',\n primaryColor,\n isDark = false,\n disabled,\n styleOverride,\n enableEmoji = false,\n fileUpload,\n onFileUpload,\n}) => {\n const [text, setText] = useState('');\n const [showEmoji, setShowEmoji] = useState(false);\n const [attachedFiles, setAttachedFiles] = useState<File[]>([]);\n const inputRef = useRef<HTMLTextAreaElement>(null);\n\n const handleSend = useCallback(() => {\n const trimmed = text.trim();\n if (!trimmed && attachedFiles.length === 0) return;\n onSend(trimmed, attachedFiles.length > 0 ? attachedFiles : undefined);\n setText('');\n setAttachedFiles([]);\n inputRef.current?.focus();\n }, [text, attachedFiles, onSend]);\n\n const handleKeyDown = (e: React.KeyboardEvent) => {\n if (e.key === 'Enter' && !e.shiftKey) {\n e.preventDefault();\n handleSend();\n }\n };\n\n const handleEmojiSelect = (emoji: string) => {\n setText((prev) => prev + emoji);\n inputRef.current?.focus();\n };\n\n const handleFiles = (files: File[]) => {\n setAttachedFiles((prev) => [...prev, ...files]);\n onFileUpload?.(files);\n };\n\n const handleRemoveFile = (index: number) => {\n setAttachedFiles((prev) => prev.filter((_, i) => i !== index));\n };\n\n const hasContent = text.trim() || attachedFiles.length > 0;\n\n return (\n <div style={{ position: 'relative', ...styleOverride }}>\n {/* File preview above input */}\n {attachedFiles.length > 0 && (\n <FilePreviewList\n files={attachedFiles}\n onRemove={handleRemoveFile}\n primaryColor={primaryColor}\n />\n )}\n\n {/* Emoji picker */}\n {showEmoji && (\n <EmojiPicker\n onSelect={handleEmojiSelect}\n onClose={() => setShowEmoji(false)}\n primaryColor={primaryColor}\n />\n )}\n\n <div\n style={{\n display: 'flex',\n gap: '8px',\n alignItems: 'flex-end',\n background: isDark ? 'rgba(40, 40, 65, 0.5)' : 'rgba(245, 247, 252, 0.7)',\n borderRadius: '16px',\n border: `1px solid ${isDark ? 'rgba(255,255,255,0.08)' : 'rgba(0,0,0,0.05)'}`,\n backdropFilter: 'blur(8px)',\n WebkitBackdropFilter: 'blur(8px)',\n padding: '6px 6px 6px 12px',\n }}\n >\n {/* Action buttons */}\n <div style={{ display: 'flex', alignItems: 'center', gap: '2px', flexShrink: 0, paddingBottom: '2px' }}>\n {enableEmoji && (\n <button\n type=\"button\"\n onClick={() => setShowEmoji(!showEmoji)}\n aria-label=\"Emoji\"\n title=\"Emoji\"\n style={{\n background: 'none',\n border: 'none',\n cursor: 'pointer',\n padding: '6px',\n display: 'flex',\n color: showEmoji ? primaryColor : (isDark ? 'rgba(255,255,255,0.35)' : 'rgba(0,0,0,0.3)'),\n borderRadius: '8px',\n transition: 'all 0.2s ease',\n }}\n >\n <EmojiIcon size={20} />\n </button>\n )}\n\n {fileUpload?.enabled && (\n <FileUploadButton\n config={fileUpload}\n onFiles={handleFiles}\n selectedFiles={attachedFiles}\n onRemoveFile={handleRemoveFile}\n primaryColor={primaryColor}\n />\n )}\n </div>\n\n {/* Text Input */}\n <textarea\n ref={inputRef}\n value={text}\n onChange={(e) => setText(e.target.value)}\n onKeyDown={handleKeyDown}\n placeholder={placeholder}\n disabled={disabled}\n rows={1}\n style={{\n flex: 1,\n padding: '8px 2px',\n border: 'none',\n borderRadius: '12px',\n outline: 'none',\n resize: 'none',\n fontFamily: 'inherit',\n fontSize: '14px',\n lineHeight: '1.45',\n maxHeight: '100px',\n overflowY: 'auto',\n backgroundColor: 'transparent',\n color: isDark ? '#E0E0E0' : '#2D3436',\n letterSpacing: '0.01em',\n }}\n />\n\n {/* Send Button */}\n <button\n onClick={handleSend}\n disabled={disabled || !hasContent}\n aria-label=\"Send message\"\n style={{\n width: '36px',\n height: '36px',\n borderRadius: '12px',\n background: hasContent\n ? `linear-gradient(135deg, ${primaryColor} 0%, ${adjustColor(primaryColor, 30)} 100%)`\n : (isDark ? 'rgba(255,255,255,0.08)' : 'rgba(0,0,0,0.06)'),\n color: hasContent ? '#fff' : (isDark ? 'rgba(255,255,255,0.25)' : 'rgba(0,0,0,0.2)'),\n border: 'none',\n cursor: hasContent ? 'pointer' : 'default',\n display: 'flex',\n alignItems: 'center',\n justifyContent: 'center',\n flexShrink: 0,\n transition: 'all 0.25s cubic-bezier(0.4, 0, 0.2, 1)',\n boxShadow: hasContent ? `0 4px 12px ${primaryColor}44` : 'none',\n }}\n >\n <SendIcon size={16} />\n </button>\n </div>\n </div>\n );\n};\n\nfunction adjustColor(hex: string, amount: number): string {\n const num = parseInt(hex.replace('#', ''), 16);\n const r = Math.min(255, ((num >> 16) & 0xff) + amount);\n const g = Math.min(255, ((num >> 8) & 0xff) + amount);\n const b = Math.min(255, (num & 0xff) + amount);\n return `#${((r << 16) | (g << 8) | b).toString(16).padStart(6, '0')}`;\n}\n","import React from 'react';\nimport type { BrandingConfig } from '../types/config';\n\ninterface BrandingProps {\n config: BrandingConfig;\n primaryColor: string;\n}\n\nexport const Branding: React.FC<BrandingProps> = ({ config, primaryColor }) => {\n if (config.showBranding === false) return null;\n\n const text = config.poweredBy ?? 'React ChatBot';\n\n return (\n <div\n style={{\n padding: '8px 16px',\n textAlign: 'center',\n fontSize: '11px',\n color: 'rgba(0,0,0,0.35)',\n background: 'rgba(250, 250, 255, 0.7)',\n backdropFilter: 'blur(8px)',\n WebkitBackdropFilter: 'blur(8px)',\n borderTop: '1px solid rgba(0,0,0,0.04)',\n flexShrink: 0,\n letterSpacing: '0.02em',\n }}\n >\n Powered by{' '}\n {config.poweredByUrl ? (\n <a\n href={config.poweredByUrl}\n target=\"_blank\"\n rel=\"noopener noreferrer\"\n style={{\n color: primaryColor,\n textDecoration: 'none',\n fontWeight: 600,\n transition: 'opacity 0.2s ease',\n }}\n >\n {text}\n </a>\n ) : (\n <span style={{ color: primaryColor, fontWeight: 600 }}>{text}</span>\n )}\n </div>\n );\n};\n","import type { FlowConfig, FlowStep, ChatMessage, FlowQuickReply } from '../types';\r\n\r\nexport class FlowEngine {\r\n private steps: Map<string, FlowStep>;\r\n private startStep: string;\r\n private collectedData: Record<string, unknown> = {};\r\n private idCounter = 0;\r\n private uid = (): string => `msg_${Date.now()}_${++this.idCounter}`;\r\n private stepHistory: string[] = [];\r\n\r\n constructor(flow: FlowConfig) {\r\n this.startStep = flow.startStep;\r\n this.steps = new Map(flow.steps.map((s) => [s.id, s]));\r\n }\r\n\r\n getStartStepId(): string {\r\n return this.startStep;\r\n }\r\n\r\n getStep(id: string): FlowStep | undefined {\r\n return this.steps.get(id);\r\n }\r\n\r\n getData(): Record<string, unknown> {\r\n return { ...this.collectedData };\r\n }\r\n\r\n setData(key: string, value: unknown): void {\r\n this.collectedData[key] = value;\r\n }\r\n\r\n mergeData(data: Record<string, unknown>): void {\r\n Object.assign(this.collectedData, data);\r\n }\r\n\r\n /** Push a step onto the history stack (called when entering a step) */\r\n pushHistory(stepId: string): void {\r\n this.stepHistory.push(stepId);\r\n }\r\n\r\n /** Pop and return the previous step (go back) */\r\n popHistory(): string | undefined {\r\n // Remove current step\r\n this.stepHistory.pop();\r\n // Return previous step\r\n return this.stepHistory.pop();\r\n }\r\n\r\n /** Check if there's a previous step to go back to */\r\n canGoBack(): boolean {\r\n return this.stepHistory.length > 1;\r\n }\r\n\r\n /** Reset the engine to initial state */\r\n reset(): void {\r\n this.collectedData = {};\r\n this.stepHistory = [];\r\n }\r\n\r\n resolveNext(step: FlowStep, userValue?: string): string | undefined {\r\n // Conditional branching\r\n if (step.condition) {\r\n const { field, operator, value, then: thenStep, else: elseStep } = step.condition;\r\n const fieldVal = this.collectedData[field];\r\n const match = this.evaluate(fieldVal, operator, value);\r\n return match ? thenStep : elseStep;\r\n }\r\n\r\n // Quick-reply selected → find the reply's next\r\n if (userValue && step.quickReplies) {\r\n const reply = step.quickReplies.find((r) => r.value === userValue);\r\n if (reply?.next) return reply.next;\r\n }\r\n\r\n return step.next;\r\n }\r\n\r\n /** Returns true if the step expects a quick reply (not free text) */\r\n stepExpectsQuickReply(step: FlowStep): boolean {\r\n return !!(step.quickReplies && step.quickReplies.length > 0);\r\n }\r\n\r\n /** Returns true if the step expects a form submission */\r\n stepExpectsForm(step: FlowStep): boolean {\r\n return !!step.form;\r\n }\r\n\r\n /** Try to fuzzy-match user text against quick reply labels */\r\n matchQuickReply(step: FlowStep, text: string): FlowQuickReply | undefined {\r\n if (!step.quickReplies) return undefined;\r\n const lower = text.toLowerCase().trim();\r\n // Exact value match\r\n const exact = step.quickReplies.find((r) => r.value.toLowerCase() === lower);\r\n if (exact) return exact;\r\n // Exact label match \r\n const labelMatch = step.quickReplies.find((r) => r.label.toLowerCase().replace(/[^\\w\\s]/g, '').trim() === lower);\r\n if (labelMatch) return labelMatch;\r\n // Contains match\r\n const contains = step.quickReplies.find((r) => lower.includes(r.value.toLowerCase()) || r.label.toLowerCase().includes(lower));\r\n return contains;\r\n }\r\n\r\n buildMessages(step: FlowStep): ChatMessage[] {\r\n const messages: ChatMessage[] = [];\r\n\r\n const texts = step.messages ?? (step.message ? [step.message] : []);\r\n for (const text of texts) {\r\n messages.push({\r\n id: this.uid(),\r\n sender: 'bot',\r\n text,\r\n timestamp: Date.now(),\r\n });\r\n }\r\n\r\n // Attach quick replies to the last message\r\n if (step.quickReplies && messages.length > 0) {\r\n messages[messages.length - 1]!.quickReplies = step.quickReplies;\r\n }\r\n\r\n // If step has a form, create a form message\r\n if (step.form) {\r\n messages.push({\r\n id: this.uid(),\r\n sender: 'bot',\r\n timestamp: Date.now(),\r\n form: step.form,\r\n });\r\n }\r\n\r\n // If step has a custom component, create a component message\r\n if (step.component) {\r\n messages.push({\r\n id: this.uid(),\r\n sender: 'bot',\r\n timestamp: Date.now(),\r\n component: step.component,\r\n });\r\n }\r\n\r\n return messages;\r\n }\r\n\r\n private evaluate(\r\n fieldVal: unknown,\r\n operator: string,\r\n value: string | number,\r\n ): boolean {\r\n switch (operator) {\r\n case 'eq':\r\n return String(fieldVal) === String(value);\r\n case 'neq':\r\n return String(fieldVal) !== String(value);\r\n case 'contains':\r\n return String(fieldVal).includes(String(value));\r\n case 'gt':\r\n return Number(fieldVal) > Number(value);\r\n case 'lt':\r\n return Number(fieldVal) < Number(value);\r\n default:\r\n return false;\r\n }\r\n }\r\n}\r\n\r\nlet globalIdCounter = 0;\r\nexport function createQuickReplyMessage(\r\n replies: FlowQuickReply[],\r\n): ChatMessage {\r\n return {\r\n id: `msg_${Date.now()}_${++globalIdCounter}`,\r\n sender: 'bot',\r\n timestamp: Date.now(),\r\n quickReplies: replies,\r\n };\r\n}\r\n","let counter = 0;\n\nexport const uid = (): string => `msg_${Date.now()}_${++counter}`;\n\nexport const classNames = (...args: (string | false | null | undefined)[]): string =>\n args.filter(Boolean).join(' ');\n\nexport const delay = (ms: number): Promise<void> =>\n new Promise((resolve) => setTimeout(resolve, ms));\n","import { useCallback, useRef, useEffect } from 'react';\r\nimport { useChatContext } from '../context/ChatContext';\r\nimport { FlowEngine } from '../engine/FlowEngine';\r\nimport { uid, delay } from '../utils/helpers';\r\nimport type { ChatMessage } from '../types';\r\nimport type { FlowActionResult, ActionContext } from '../types/config';\r\n\r\n/** Slash commands the user can type */\r\nconst COMMANDS: Record<string, string> = {\r\n '/help': 'Show available commands',\r\n '/cancel': 'Cancel current step and go back',\r\n '/back': 'Go back to the previous step',\r\n '/restart': 'Restart the conversation from the beginning',\r\n};\r\n\r\nexport function useChat() {\r\n const { state, dispatch, props } = useChatContext();\r\n const flowRef = useRef<FlowEngine | null>(null);\r\n const flowStartedRef = useRef(false);\r\n\r\n // Keep fresh references for use inside async callbacks (avoids stale closures)\r\n const stateRef = useRef(state);\r\n stateRef.current = state;\r\n const propsRef = useRef(props);\r\n propsRef.current = props;\r\n\r\n // Initialize flow engine\r\n useEffect(() => {\r\n if (props.flow) {\r\n flowRef.current = new FlowEngine(props.flow);\r\n flowStartedRef.current = false;\r\n }\r\n }, [props.flow]);\r\n\r\n const addBotMessage = useCallback(\r\n async (text: string, extras?: Partial<ChatMessage>) => {\r\n dispatch({ type: 'SET_TYPING', payload: true });\r\n await delay(400);\r\n const msg: ChatMessage = {\r\n id: uid(),\r\n sender: 'bot',\r\n text,\r\n timestamp: Date.now(),\r\n ...extras,\r\n };\r\n dispatch({ type: 'SET_TYPING', payload: false });\r\n dispatch({ type: 'ADD_MESSAGE', payload: msg });\r\n propsRef.current.callbacks?.onMessageReceive?.(msg);\r\n },\r\n [dispatch],\r\n );\r\n\r\n const addSystemMessage = useCallback(\r\n (text: string) => {\r\n dispatch({\r\n type: 'ADD_MESSAGE',\r\n payload: { id: uid(), sender: 'system', text, timestamp: Date.now() },\r\n });\r\n },\r\n [dispatch],\r\n );\r\n\r\n // Use a ref so processFlowStep can call itself recursively without stale closure\r\n const processFlowStepRef = useRef<(stepId: string) => Promise<void>>(async () => {});\r\n processFlowStepRef.current = async (stepId: string) => {\r\n const engine = flowRef.current;\r\n if (!engine) return;\r\n\r\n const step = engine.getStep(stepId);\r\n if (!step) return;\r\n\r\n // Track step history for /back navigation\r\n engine.pushHistory(stepId);\r\n\r\n dispatch({ type: 'SET_STEP', payload: stepId });\r\n dispatch({ type: 'SET_TYPING', payload: true });\r\n await delay(step.delay ?? 500);\r\n\r\n const messages = engine.buildMessages(step);\r\n dispatch({ type: 'SET_TYPING', payload: false });\r\n dispatch({ type: 'ADD_MESSAGES', payload: messages });\r\n\r\n messages.forEach((m) => propsRef.current.callbacks?.onMessageReceive?.(m));\r\n\r\n // Handle async action (API calls, verification, etc.)\r\n if (step.asyncAction) {\r\n const handler = propsRef.current.actionHandlers?.[step.asyncAction.handler];\r\n if (handler) {\r\n const statusMsgId = uid();\r\n // Show loading/status message\r\n dispatch({\r\n type: 'ADD_MESSAGE',\r\n payload: {\r\n id: statusMsgId,\r\n sender: 'bot',\r\n text: step.asyncAction.loadingMessage ?? 'Processing...',\r\n timestamp: Date.now(),\r\n },\r\n });\r\n\r\n const ctx: ActionContext = {\r\n updateMessage: (text: string) => {\r\n dispatch({ type: 'UPDATE_MESSAGE', payload: { id: statusMsgId, updates: { text } } });\r\n },\r\n };\r\n\r\n try {\r\n const result = await handler(engine.getData(), ctx);\r\n\r\n // Merge result data into collected data\r\n if (result.data) {\r\n engine.mergeData(result.data);\r\n dispatch({ type: 'SET_DATA', payload: result.data });\r\n }\r\n\r\n // Update status message with final text\r\n const finalMsg =\r\n result.message ??\r\n (result.status === 'success'\r\n ? (step.asyncAction.successMessage ?? 'Done!')\r\n : (step.asyncAction.errorMessage ?? 'Something went wrong.'));\r\n dispatch({ type: 'UPDATE_MESSAGE', payload: { id: statusMsgId, updates: { text: finalMsg } } });\r\n\r\n // Route based on result\r\n const nextStepId = resolveAsyncRoute(step, result);\r\n if (nextStepId) {\r\n await delay(600);\r\n processFlowStepRef.current(nextStepId);\r\n }\r\n } catch {\r\n dispatch({\r\n type: 'UPDATE_MESSAGE',\r\n payload: { id: statusMsgId, updates: { text: step.asyncAction.errorMessage ?? '❌ Something went wrong.' } },\r\n });\r\n if (step.asyncAction.onError) {\r\n await delay(600);\r\n processFlowStepRef.current(step.asyncAction.onError);\r\n }\r\n }\r\n return; // async action handles routing — don't auto-advance\r\n }\r\n }\r\n\r\n // If step has a custom component, wait for onComplete — don't auto-advance\r\n if (step.component && propsRef.current.components?.[step.component]) {\r\n return;\r\n }\r\n\r\n // Auto-advance if no user input required\r\n if (!step.quickReplies && !step.form && step.next) {\r\n await delay(300);\r\n processFlowStepRef.current(step.next);\r\n }\r\n };\r\n\r\n /** Determine next step from async action result */\r\n function resolveAsyncRoute(\r\n step: { asyncAction?: { onSuccess?: string; onError?: string; routes?: Record<string, string> }; next?: string },\r\n result: FlowActionResult,\r\n ): string | undefined {\r\n // 1. Explicit next from result\r\n if (result.next) return result.next;\r\n // 2. Routes map\r\n if (step.asyncAction?.routes?.[result.status]) return step.asyncAction.routes[result.status];\r\n // 3. Success/error defaults\r\n if (result.status === 'success' && step.asyncAction?.onSuccess) return step.asyncAction.onSuccess;\r\n if (result.status === 'error' && step.asyncAction?.onError) return step.asyncAction.onError;\r\n // 4. Fallback\r\n return step.next;\r\n }\r\n\r\n const processFlowStep = useCallback(\r\n (stepId: string) => processFlowStepRef.current(stepId),\r\n [],\r\n );\r\n\r\n /** Go back to the previous step */\r\n const goBack = useCallback(() => {\r\n const engine = flowRef.current;\r\n if (!engine || !engine.canGoBack()) {\r\n addSystemMessage('There is no previous step to go back to.');\r\n return;\r\n }\r\n dispatch({ type: 'CLEAR_QUICK_REPLIES' });\r\n const prevStepId = engine.popHistory();\r\n if (prevStepId) {\r\n processFlowStep(prevStepId);\r\n } else {\r\n addSystemMessage('There is no previous step to go back to.');\r\n }\r\n }, [dispatch, processFlowStep, addSystemMessage]);\r\n\r\n /** Restart the entire conversation */\r\n const restartSession = useCallback(() => {\r\n const engine = flowRef.current;\r\n if (engine) {\r\n engine.reset();\r\n }\r\n flowStartedRef.current = false;\r\n dispatch({ type: 'RESET_CHAT' });\r\n // Re-start the flow after reset\r\n if (engine) {\r\n flowStartedRef.current = true;\r\n processFlowStep(engine.getStartStepId());\r\n }\r\n }, [dispatch, processFlowStep]);\r\n\r\n /** Handle slash commands. Returns true if the text was a command. */\r\n const handleCommandRef = useRef<(text: string) => boolean>(() => false);\r\n handleCommandRef.current = (text: string): boolean => {\r\n const cmd = text.trim().toLowerCase();\r\n if (!cmd.startsWith('/')) return false;\r\n\r\n switch (cmd) {\r\n case '/help': {\r\n const lines = Object.entries(COMMANDS)\r\n .map(([k, v]) => `**${k}** — ${v}`)\r\n .join('\\n');\r\n addSystemMessage(`Available commands:\\n${lines}`);\r\n return true;\r\n }\r\n case '/cancel':\r\n case '/back': {\r\n goBack();\r\n return true;\r\n }\r\n case '/restart': {\r\n restartSession();\r\n return true;\r\n }\r\n default:\r\n addSystemMessage(`Unknown command: ${cmd}. Type /help for available commands.`);\r\n return true;\r\n }\r\n };\r\n\r\n /** Handle completion from a custom component rendered in a step */\r\n const handleComponentComplete = useCallback(\r\n (result?: FlowActionResult) => {\r\n const engine = flowRef.current;\r\n const currentStepId = stateRef.current.currentStepId;\r\n if (!engine || !currentStepId) return;\r\n\r\n const step = engine.getStep(currentStepId);\r\n if (!step) return;\r\n\r\n // Merge result data\r\n if (result?.data) {\r\n engine.mergeData(result.data);\r\n dispatch({ type: 'SET_DATA', payload: result.data });\r\n }\r\n\r\n // Show optional message\r\n if (result?.message) {\r\n dispatch({\r\n type: 'ADD_MESSAGE',\r\n payload: { id: uid(), sender: 'bot', text: result.message, timestamp: Date.now() },\r\n });\r\n }\r\n\r\n // Determine next step\r\n const nextStepId = result?.next ?? step.next;\r\n if (nextStepId) {\r\n processFlowStep(nextStepId);\r\n } else {\r\n propsRef.current.callbacks?.onFlowEnd?.(engine.getData());\r\n dispatch({ type: 'SET_STEP', payload: null });\r\n }\r\n },\r\n [dispatch, processFlowStep],\r\n );\r\n\r\n const sendMessage = useCallback(\r\n (text: string) => {\r\n // Check for slash commands first\r\n if (handleCommandRef.current(text)) return;\r\n\r\n const msg: ChatMessage = {\r\n id: uid(),\r\n sender: 'user',\r\n text,\r\n timestamp: Date.now(),\r\n };\r\n dispatch({ type: 'ADD_MESSAGE', payload: msg });\r\n propsRef.current.callbacks?.onMessageSend?.(msg);\r\n propsRef.current.callbacks?.onSubmit?.({ message: text });\r\n\r\n const currentStepId = stateRef.current.currentStepId;\r\n if (flowRef.current && currentStepId) {\r\n const step = flowRef.current.getStep(currentStepId);\r\n if (step) {\r\n // Block text input during async action or component steps\r\n if (step.asyncAction || step.component) {\r\n addBotMessage(\"Please wait, I'm still processing. You can type /back to go back.\");\r\n return;\r\n }\r\n // If this step has quick replies, try to match user text\r\n if (flowRef.current.stepExpectsQuickReply(step)) {\r\n const matched = flowRef.current.matchQuickReply(step, text);\r\n if (matched) {\r\n // User typed something matching a quick reply — handle it\r\n dispatch({ type: 'CLEAR_QUICK_REPLIES' });\r\n flowRef.current.setData(step.id, matched.value);\r\n const nextId = flowRef.current.resolveNext(step, matched.value);\r\n if (nextId) {\r\n processFlowStep(nextId);\r\n } else {\r\n propsRef.current.callbacks?.onFlowEnd?.(flowRef.current.getData());\r\n dispatch({ type: 'SET_STEP', payload: null });\r\n }\r\n } else {\r\n // User typed something that doesn't match — re-show options\r\n addBotMessage(\r\n \"I didn't quite get that. Please choose one of the options below:\",\r\n {\r\n quickReplies: step.quickReplies,\r\n },\r\n );\r\n }\r\n } else if (flowRef.current.stepExpectsForm(step)) {\r\n // Step has a form, nudge user\r\n addBotMessage(\"Please fill out the form above to continue.\");\r\n } else {\r\n // Normal text input step\r\n flowRef.current.setData(step.id, text);\r\n const nextId = flowRef.current.resolveNext(step, text);\r\n if (nextId) {\r\n processFlowStep(nextId);\r\n } else {\r\n // End of flow — acknowledge\r\n addBotMessage(\"Thanks for your message! Our team will get back to you soon. 🙌\");\r\n propsRef.current.callbacks?.onFlowEnd?.(flowRef.current.getData());\r\n dispatch({ type: 'SET_STEP', payload: null });\r\n }\r\n }\r\n }\r\n }\r\n },\r\n [dispatch, addBotMessage, processFlowStep],\r\n );\r\n\r\n const startFlow = useCallback(() => {\r\n const engine = flowRef.current;\r\n if (!engine || flowStartedRef.current) return;\r\n flowStartedRef.current = true;\r\n processFlowStep(engine.getStartStepId());\r\n }, [processFlowStep]);\r\n\r\n // Auto-start flow when all conditions are met\r\n useEffect(() => {\r\n if (\r\n props.flow &&\r\n !state.showWelcome &&\r\n state.isLoggedIn &&\r\n !flowStartedRef.current\r\n ) {\r\n startFlow();\r\n }\r\n }, [props.flow, state.showWelcome, state.isLoggedIn, startFlow]);\r\n\r\n const handleQuickReply = useCallback(\r\n (value: string, label: string) => {\r\n dispatch({ type: 'CLEAR_QUICK_REPLIES' });\r\n // Add user message\r\n const msg: ChatMessage = {\r\n id: uid(),\r\n sender: 'user',\r\n text: label,\r\n timestamp: Date.now(),\r\n };\r\n dispatch({ type: 'ADD_MESSAGE', payload: msg });\r\n propsRef.current.callbacks?.onQuickReply?.(value, label);\r\n\r\n // Continue flow\r\n const currentStepId = stateRef.current.currentStepId;\r\n if (flowRef.current && currentStepId) {\r\n const step = flowRef.current.getStep(currentStepId);\r\n if (step) {\r\n flowRef.current.setData(step.id, value);\r\n const nextId = flowRef.current.resolveNext(step, value);\r\n if (nextId) {\r\n processFlowStep(nextId);\r\n } else {\r\n propsRef.current.callbacks?.onFlowEnd?.(flowRef.current.getData());\r\n dispatch({ type: 'SET_STEP', payload: null });\r\n }\r\n }\r\n }\r\n },\r\n [dispatch, processFlowStep],\r\n );\r\n\r\n const handleFormSubmit = useCallback(\r\n async (formId: string, data: Record<string, unknown>) => {\r\n dispatch({ type: 'SET_DATA', payload: data });\r\n if (flowRef.current) {\r\n flowRef.current.mergeData(data);\r\n }\r\n\r\n // Summary message\r\n const summaryLines = Object.entries(data)\r\n .filter(([, v]) => v !== undefined && v !== '')\r\n .map(([k, v]) => `${k}: ${String(v)}`)\r\n .join('\\n');\r\n const msg: ChatMessage = {\r\n id: uid(),\r\n sender: 'user',\r\n text: summaryLines,\r\n formData: data,\r\n timestamp: Date.now(),\r\n };\r\n dispatch({ type: 'ADD_MESSAGE', payload: msg });\r\n\r\n await propsRef.current.callbacks?.onFormSubmit?.(formId, data);\r\n\r\n // Advance flow\r\n const currentStepId = stateRef.current.currentStepId;\r\n if (flowRef.current && currentStepId) {\r\n const step = flowRef.current.getStep(currentStepId);\r\n if (step) {\r\n const nextId = flowRef.current.resolveNext(step);\r\n if (nextId) {\r\n processFlowStep(nextId);\r\n } else {\r\n propsRef.current.callbacks?.onFlowEnd?.(flowRef.current.getData());\r\n dispatch({ type: 'SET_STEP', payload: null });\r\n }\r\n }\r\n }\r\n },\r\n [dispatch, processFlowStep],\r\n );\r\n\r\n const handleLogin = useCallback(\r\n async (data: Record<string, unknown>) => {\r\n await propsRef.current.callbacks?.onLogin?.(data);\r\n dispatch({ type: 'SET_LOGGED_IN', payload: true });\r\n },\r\n [dispatch],\r\n );\r\n\r\n const toggleChat = useCallback(() => {\r\n const willOpen = !stateRef.current.isOpen;\r\n dispatch({ type: 'TOGGLE_OPEN' });\r\n if (willOpen) {\r\n propsRef.current.callbacks?.onOpen?.();\r\n } else {\r\n propsRef.current.callbacks?.onClose?.();\r\n }\r\n }, [dispatch]);\r\n\r\n const dismissWelcome = useCallback(() => {\r\n dispatch({ type: 'DISMISS_WELCOME' });\r\n }, [dispatch]);\r\n\r\n return {\r\n state,\r\n sendMessage,\r\n addBotMessage,\r\n handleQuickReply,\r\n handleFormSubmit,\r\n handleLogin,\r\n toggleChat,\r\n dismissWelcome,\r\n startFlow,\r\n processFlowStep,\r\n goBack,\r\n restartSession,\r\n handleComponentComplete,\r\n };\r\n}\r\n","import React, { useCallback, useMemo } from 'react';\r\nimport type { CSSProperties } from 'react';\r\nimport type { ChatStyles } from '../styles/theme';\r\nimport type { ChatRenderContext } from '../types/config';\r\nimport { ChatHeader } from './ChatHeader';\r\nimport { WelcomeScreen } from './WelcomeScreen';\r\nimport { LoginScreen } from './LoginScreen';\r\nimport { MessageList } from './MessageList';\r\nimport { ChatInput } from './ChatInput';\r\nimport { Branding } from './Branding';\r\nimport { useChat } from '../hooks/useChat';\r\nimport { useChatContext } from '../context/ChatContext';\r\nimport { resolveTheme } from '../styles/theme';\r\nimport { uid } from '../utils/helpers';\r\nimport type { MessageAttachment } from '../types/message';\r\n\r\ninterface ChatWindowProps {\r\n styles: ChatStyles;\r\n position: 'bottom-right' | 'bottom-left';\r\n zIndex?: number;\r\n hidden?: boolean;\r\n}\r\n\r\nexport const ChatWindow: React.FC<ChatWindowProps> = ({ styles, position, zIndex, hidden }) => {\r\n const { props, dispatch } = useChatContext();\r\n const theme = resolveTheme(props.theme);\r\n const isDark = theme.mode === 'dark';\r\n const {\r\n state,\r\n sendMessage,\r\n handleQuickReply,\r\n handleFormSubmit,\r\n handleLogin,\r\n toggleChat,\r\n dismissWelcome,\r\n restartSession,\r\n handleComponentComplete,\r\n } = useChat();\r\n\r\n const posStyle: CSSProperties =\r\n position === 'bottom-left'\r\n ? { bottom: '96px', left: '24px' }\r\n : { bottom: '96px', right: '24px' };\r\n\r\n const handleSendWithFiles = useCallback(\r\n (text: string, files?: File[]) => {\r\n if (files && files.length > 0) {\r\n const attachments: MessageAttachment[] = files.map((f) => ({\r\n name: f.name,\r\n url: URL.createObjectURL(f),\r\n type: f.type,\r\n size: f.size,\r\n }));\r\n if (text) {\r\n dispatch({\r\n type: 'ADD_MESSAGE',\r\n payload: {\r\n id: uid(),\r\n sender: 'user',\r\n text,\r\n timestamp: Date.now(),\r\n attachments,\r\n },\r\n });\r\n sendMessage(text);\r\n } else {\r\n dispatch({\r\n type: 'ADD_MESSAGE',\r\n payload: {\r\n id: uid(),\r\n sender: 'user',\r\n timestamp: Date.now(),\r\n attachments,\r\n },\r\n });\r\n }\r\n props.callbacks?.onFileUpload?.(files);\r\n } else if (text) {\r\n sendMessage(text);\r\n }\r\n },\r\n [sendMessage, dispatch, props.callbacks],\r\n );\r\n\r\n // Build render context for custom components\r\n const renderCtx: ChatRenderContext = useMemo(\r\n () => ({\r\n currentStepId: state.currentStepId,\r\n isOpen: state.isOpen,\r\n messages: state.messages,\r\n collectedData: state.collectedData,\r\n toggleChat,\r\n restartSession,\r\n sendMessage,\r\n }),\r\n [state.currentStepId, state.isOpen, state.messages, state.collectedData, toggleChat, restartSession, sendMessage],\r\n );\r\n\r\n // Default header element\r\n const defaultHeader = (\r\n <ChatHeader\r\n config={props.header ?? { title: 'Chat with us' }}\r\n styles={styles}\r\n onClose={toggleChat}\r\n onRestart={restartSession}\r\n logo={props.branding?.logo}\r\n logoWidth={props.branding?.logoWidth}\r\n />\r\n );\r\n\r\n // Default input element\r\n const defaultInput = (\r\n <ChatInput\r\n onSend={handleSendWithFiles}\r\n placeholder={props.inputPlaceholder}\r\n primaryColor={theme.primaryColor}\r\n isDark={isDark}\r\n enableEmoji={props.enableEmoji}\r\n fileUpload={props.fileUpload}\r\n onFileUpload={props.callbacks?.onFileUpload}\r\n />\r\n );\r\n\r\n if (hidden) {\r\n // Keep component mounted (hooks alive) but invisible\r\n return <div style={{ display: 'none' }} />;\r\n }\r\n\r\n return (\r\n <div\r\n style={{\r\n ...styles.window,\r\n ...posStyle,\r\n ...(zIndex != null ? { zIndex } : {}),\r\n }}\r\n >\r\n {props.renderHeader ? props.renderHeader(renderCtx, defaultHeader) : defaultHeader}\r\n\r\n {/* Welcome Screen */}\r\n {state.showWelcome && props.welcomeScreen ? (\r\n <WelcomeScreen\r\n content={props.welcomeScreen}\r\n onDismiss={dismissWelcome}\r\n primaryColor={theme.primaryColor}\r\n />\r\n ) : /* Login Screen */\r\n !state.isLoggedIn && props.loginForm ? (\r\n <LoginScreen\r\n config={props.loginForm}\r\n onLogin={handleLogin}\r\n primaryColor={theme.primaryColor}\r\n renderFormField={props.renderFormField}\r\n />\r\n ) : (\r\n /* Chat Area */\r\n <>\r\n <MessageList\r\n messages={state.messages}\r\n isTyping={state.isTyping}\r\n styles={styles}\r\n primaryColor={theme.primaryColor}\r\n onQuickReply={handleQuickReply}\r\n onFormSubmit={handleFormSubmit}\r\n components={props.components}\r\n onComponentComplete={handleComponentComplete}\r\n collectedData={state.collectedData}\r\n currentStepId={state.currentStepId}\r\n renderFormField={props.renderFormField}\r\n />\r\n <div style={styles.inputArea}>\r\n {props.renderInput ? props.renderInput(renderCtx, defaultInput) : defaultInput}\r\n </div>\r\n {props.branding && (\r\n <Branding config={props.branding} primaryColor={theme.primaryColor} />\r\n )}\r\n </>\r\n )}\r\n </div>\r\n );\r\n};\r\n","import type { ChatPlugin, PluginContext, ChatPluginEvent } from '../types/plugin';\r\nimport type { ChatMessage } from '../types/message';\r\n\r\n/**\r\n * PluginManager — Manages plugin lifecycle (Open/Closed Principle)\r\n * Core is closed for modification, open for extension via plugins.\r\n */\r\nexport class PluginManager {\r\n private plugins: ChatPlugin[] = [];\r\n private context: PluginContext | null = null;\r\n private eventHandlers = new Map<string, Set<(...args: unknown[]) => void>>();\r\n\r\n register(plugins: ChatPlugin[]): void {\r\n this.plugins = [...plugins];\r\n }\r\n\r\n setContext(ctx: Omit<PluginContext, 'on' | 'emit'>): void {\r\n this.context = {\r\n ...ctx,\r\n on: (event, handler) => this.on(event, handler),\r\n emit: (event, ...args) => this.emit(event, ...args),\r\n };\r\n }\r\n\r\n private on(event: string, handler: (...args: unknown[]) => void): void {\r\n if (!this.eventHandlers.has(event)) {\r\n this.eventHandlers.set(event, new Set());\r\n }\r\n this.eventHandlers.get(event)!.add(handler);\r\n }\r\n\r\n private emit(event: string, ...args: unknown[]): void {\r\n const handlers = this.eventHandlers.get(event);\r\n if (handlers) {\r\n handlers.forEach((handler) => handler(...args));\r\n }\r\n }\r\n\r\n async init(): Promise<void> {\r\n if (!this.context) return;\r\n for (const plugin of this.plugins) {\r\n try {\r\n await plugin.onInit?.(this.context);\r\n } catch (err) {\r\n console.error(`[Plugin:${plugin.name}] onInit error:`, err);\r\n }\r\n }\r\n }\r\n\r\n async onMessage(message: ChatMessage): Promise<ChatMessage> {\r\n if (!this.context) return message;\r\n let msg = message;\r\n for (const plugin of this.plugins) {\r\n try {\r\n const result = await plugin.onMessage?.(msg, this.context);\r\n if (result && typeof result === 'object' && 'id' in result) {\r\n msg = result;\r\n }\r\n } catch (err) {\r\n console.error(`[Plugin:${plugin.name}] onMessage error:`, err);\r\n }\r\n }\r\n this.dispatchEvent({ type: 'message', payload: msg, timestamp: Date.now() });\r\n return msg;\r\n }\r\n\r\n async onSubmit(data: Record<string, unknown>): Promise<void> {\r\n if (!this.context) return;\r\n for (const plugin of this.plugins) {\r\n try {\r\n await plugin.onSubmit?.(data, this.context);\r\n } catch (err) {\r\n console.error(`[Plugin:${plugin.name}] onSubmit error:`, err);\r\n }\r\n }\r\n this.dispatchEvent({ type: 'submit', payload: data, timestamp: Date.now() });\r\n }\r\n\r\n async destroy(): Promise<void> {\r\n if (!this.context) return;\r\n for (const plugin of this.plugins) {\r\n try {\r\n await plugin.onDestroy?.(this.context);\r\n } catch (err) {\r\n console.error(`[Plugin:${plugin.name}] onDestroy error:`, err);\r\n }\r\n }\r\n this.eventHandlers.clear();\r\n this.plugins = [];\r\n }\r\n\r\n private dispatchEvent(event: ChatPluginEvent): void {\r\n if (!this.context) return;\r\n for (const plugin of this.plugins) {\r\n try {\r\n plugin.onEvent?.(event, this.context);\r\n } catch (err) {\r\n console.error(`[Plugin:${plugin.name}] onEvent error:`, err);\r\n }\r\n }\r\n }\r\n}\r\n","import React, { useReducer, useEffect, useRef, useCallback } from 'react';\r\nimport type { ChatBotProps } from '../types';\r\nimport { ChatContext, chatReducer, initialState } from '../context/ChatContext';\r\nimport { resolveTheme, buildStyles, buildCSSVariables } from '../styles/theme';\r\nimport { Launcher } from './Launcher';\r\nimport { ChatWindow } from './ChatWindow';\r\nimport { PluginManager } from '../core/PluginManager';\r\nimport { uid } from '../utils/helpers';\r\n\r\nconst GLOBAL_STYLES = `\r\n@import url('https://fonts.googleapis.com/css2?family=Inter:wght@400;500;600;700&display=swap');\r\n\r\n@keyframes cb-window-enter {\r\n 0% { opacity: 0; transform: translateY(16px) scale(0.96); }\r\n 100% { opacity: 1; transform: translateY(0) scale(1); }\r\n}\r\n\r\n@keyframes cb-launcher-pulse {\r\n 0%, 100% { box-shadow: 0 6px 24px rgba(108, 92, 231, 0.4), 0 2px 8px rgba(0,0,0,0.1); }\r\n 50% { box-shadow: 0 8px 32px rgba(108, 92, 231, 0.55), 0 4px 12px rgba(0,0,0,0.15); }\r\n}\r\n\r\n@keyframes cb-fade-in {\r\n 0% { opacity: 0; transform: translateY(6px); }\r\n 100% { opacity: 1; transform: translateY(0); }\r\n}\r\n\r\n@keyframes cb-typing-bounce {\r\n 0%, 80%, 100% { transform: scale(0.6); opacity: 0.3; }\r\n 40% { transform: scale(1); opacity: 1; }\r\n}\r\n\r\n@keyframes cb-slide-up {\r\n 0% { opacity: 0; transform: translateY(10px); }\r\n 100% { opacity: 1; transform: translateY(0); }\r\n}\r\n\r\n.cb-scrollbar::-webkit-scrollbar {\r\n width: 5px;\r\n}\r\n.cb-scrollbar::-webkit-scrollbar-track {\r\n background: transparent;\r\n}\r\n.cb-scrollbar::-webkit-scrollbar-thumb {\r\n background: rgba(108, 92, 231, 0.2);\r\n border-radius: 10px;\r\n}\r\n.cb-scrollbar::-webkit-scrollbar-thumb:hover {\r\n background: rgba(108, 92, 231, 0.35);\r\n}\r\n`;\r\n\r\n// Inject styles globally once per document, not per component instance\r\nlet globalStyleInjected = false;\r\nfunction ensureGlobalStyles() {\r\n if (globalStyleInjected) return;\r\n if (typeof document === 'undefined') return;\r\n if (document.querySelector('style[data-chatbot-styles]')) {\r\n globalStyleInjected = true;\r\n return;\r\n }\r\n const style = document.createElement('style');\r\n style.setAttribute('data-chatbot-styles', '');\r\n style.textContent = GLOBAL_STYLES;\r\n document.head.appendChild(style);\r\n globalStyleInjected = true;\r\n}\r\n\r\nexport const ChatBot: React.FC<ChatBotProps> = (props) => {\r\n const [state, dispatch] = useReducer(chatReducer, props, initialState);\r\n const theme = resolveTheme(props.theme);\r\n const styles = buildStyles(theme, props.style);\r\n const cssVars = buildCSSVariables(theme);\r\n const position = props.position ?? 'bottom-right';\r\n const showLauncher = props.showLauncher !== false;\r\n const pluginManagerRef = useRef<PluginManager | null>(null);\r\n\r\n // Use refs so plugin context always reads fresh state\r\n const stateRef = useRef(state);\r\n stateRef.current = state;\r\n\r\n // Inject global styles once\r\n useEffect(() => {\r\n ensureGlobalStyles();\r\n }, []);\r\n\r\n // Initialize plugins\r\n useEffect(() => {\r\n if (props.plugins && props.plugins.length > 0) {\r\n const pm = new PluginManager();\r\n pm.register(props.plugins);\r\n pm.setContext({\r\n sendMessage: (text) => {\r\n dispatch({\r\n type: 'ADD_MESSAGE',\r\n payload: { id: uid(), sender: 'user', text, timestamp: Date.now() },\r\n });\r\n },\r\n addBotMessage: (text) => {\r\n dispatch({\r\n type: 'ADD_MESSAGE',\r\n payload: { id: uid(), sender: 'bot', text, timestamp: Date.now() },\r\n });\r\n },\r\n getMessages: () => stateRef.current.messages,\r\n getData: () => stateRef.current.collectedData,\r\n setData: (key, value) => dispatch({ type: 'SET_DATA', payload: { [key]: value } }),\r\n });\r\n pm.init();\r\n pluginManagerRef.current = pm;\r\n\r\n return () => {\r\n pm.destroy();\r\n };\r\n }\r\n }, [props.plugins]);\r\n\r\n const handleToggle = useCallback(() => {\r\n const willOpen = !state.isOpen;\r\n dispatch({ type: 'TOGGLE_OPEN' });\r\n if (willOpen) props.callbacks?.onOpen?.();\r\n else props.callbacks?.onClose?.();\r\n }, [state.isOpen, props.callbacks]);\r\n\r\n return (\r\n <ChatContext.Provider value={{ state, dispatch, props }}>\r\n <div style={{ ...styles.root, ...cssVars as React.CSSProperties }} className={props.className}>\r\n <ChatWindow styles={styles} position={position} zIndex={props.zIndex} hidden={!state.isOpen} />\r\n {showLauncher && (\r\n <Launcher\r\n onClick={handleToggle}\r\n isOpen={state.isOpen}\r\n position={position}\r\n styles={styles}\r\n icon={props.launcherIcon}\r\n closeIcon={props.closeIcon}\r\n zIndex={props.zIndex}\r\n />\r\n )}\r\n </div>\r\n </ChatContext.Provider>\r\n );\r\n};\r\n","import type { ChatPlugin } from '../types/plugin';\r\n\r\n/**\r\n * Analytics Plugin — tracks message counts, form completions, drop-offs\r\n */\r\nexport function analyticsPlugin(options?: {\r\n onTrack?: (event: string, data?: unknown) => void;\r\n}): ChatPlugin {\r\n let messageCount = 0;\r\n let formSubmissions = 0;\r\n\r\n return {\r\n name: 'analytics',\r\n\r\n onInit(ctx) {\r\n messageCount = 0;\r\n formSubmissions = 0;\r\n options?.onTrack?.('chatbot:init');\r\n },\r\n\r\n onMessage(message, ctx) {\r\n messageCount++;\r\n options?.onTrack?.('chatbot:message', {\r\n sender: message.sender,\r\n messageCount,\r\n });\r\n },\r\n\r\n onSubmit(data, ctx) {\r\n formSubmissions++;\r\n options?.onTrack?.('chatbot:submit', {\r\n formSubmissions,\r\n fields: Object.keys(data),\r\n });\r\n },\r\n\r\n onDestroy() {\r\n options?.onTrack?.('chatbot:destroy', {\r\n totalMessages: messageCount,\r\n totalFormSubmissions: formSubmissions,\r\n });\r\n },\r\n };\r\n}\r\n","import type { ChatPlugin } from '../types/plugin';\r\n\r\n/**\r\n * Webhook Plugin — sends messages/submissions to an external endpoint\r\n */\r\nexport function webhookPlugin(options: {\r\n url: string;\r\n headers?: Record<string, string>;\r\n events?: ('message' | 'submit' | 'init' | 'destroy')[];\r\n}): ChatPlugin {\r\n const events = options.events ?? ['message', 'submit'];\r\n\r\n const send = async (type: string, payload: unknown) => {\r\n try {\r\n await fetch(options.url, {\r\n method: 'POST',\r\n headers: {\r\n 'Content-Type': 'application/json',\r\n ...options.headers,\r\n },\r\n body: JSON.stringify({ type, payload, timestamp: Date.now() }),\r\n });\r\n } catch (err) {\r\n console.error(`[webhook] Failed to send ${type}:`, err);\r\n }\r\n };\r\n\r\n return {\r\n name: 'webhook',\r\n\r\n async onInit() {\r\n if (events.includes('init')) {\r\n await send('init', {});\r\n }\r\n },\r\n\r\n async onMessage(message) {\r\n if (events.includes('message')) {\r\n await send('message', message);\r\n }\r\n },\r\n\r\n async onSubmit(data) {\r\n if (events.includes('submit')) {\r\n await send('submit', data);\r\n }\r\n },\r\n\r\n async onDestroy() {\r\n if (events.includes('destroy')) {\r\n await send('destroy', {});\r\n }\r\n },\r\n };\r\n}\r\n","import type { ChatPlugin } from '../types/plugin';\r\n\r\n/**\r\n * Persistence Plugin — saves/restores chat history via localStorage\r\n */\r\nexport function persistencePlugin(options?: {\r\n storageKey?: string;\r\n storage?: 'local' | 'session';\r\n}): ChatPlugin {\r\n const key = options?.storageKey ?? 'chatbot_history';\r\n const store = options?.storage === 'session' ? sessionStorage : localStorage;\r\n\r\n return {\r\n name: 'persistence',\r\n\r\n onInit(ctx) {\r\n try {\r\n const saved = store.getItem(key);\r\n if (saved) {\r\n const messages = JSON.parse(saved);\r\n if (Array.isArray(messages)) {\r\n messages.forEach((msg) => {\r\n if (msg.sender === 'bot') {\r\n ctx.addBotMessage(msg.text);\r\n }\r\n // Skip non-bot messages — re-adding user messages as bot bubbles is incorrect\r\n });\r\n }\r\n }\r\n } catch {\r\n // ignore parse errors\r\n }\r\n },\r\n\r\n onMessage(message, ctx) {\r\n try {\r\n const messages = ctx.getMessages();\r\n store.setItem(key, JSON.stringify(messages.slice(-50)));\r\n } catch {\r\n // storage full or unavailable\r\n }\r\n },\r\n\r\n onDestroy() {\r\n // Optionally clear on destroy\r\n },\r\n };\r\n}\r\n"],"mappings":"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"}
1
+ {"version":3,"file":"index.cjs","names":[],"sources":["../src/context/ChatContext.ts","../src/styles/theme.ts","../src/components/icons/Icons.tsx","../src/components/Launcher.tsx","../src/components/ChatHeader.tsx","../src/components/WelcomeScreen.tsx","../src/components/forms/TextField.tsx","../src/components/forms/SelectField.tsx","../src/components/forms/RadioField.tsx","../src/components/forms/CheckboxField.tsx","../src/components/forms/FileUploadField.tsx","../src/components/forms/DynamicForm.tsx","../src/components/LoginScreen.tsx","../src/components/MessageBubble.tsx","../src/components/QuickReplies.tsx","../src/components/TypingIndicator.tsx","../src/components/MessageList.tsx","../src/components/EmojiPicker.tsx","../src/components/FileUpload.tsx","../src/components/ChatInput.tsx","../src/components/Branding.tsx","../src/engine/FlowEngine.ts","../src/utils/helpers.ts","../src/hooks/useChat.ts","../src/components/ChatWindow.tsx","../src/core/PluginManager.ts","../src/components/ChatBot.tsx","../src/plugins/analyticsPlugin.ts","../src/plugins/webhookPlugin.ts","../src/plugins/persistencePlugin.ts"],"sourcesContent":["import { createContext, useContext } from 'react';\r\nimport type { ChatMessage, ChatBotProps } from '../types';\r\nimport type { PluginManager } from '../core/PluginManager';\r\n\r\nexport interface ChatState {\r\n isOpen: boolean;\r\n messages: ChatMessage[];\r\n isTyping: boolean;\r\n showWelcome: boolean;\r\n currentStepId: string | null;\r\n collectedData: Record<string, unknown>;\r\n isLoggedIn: boolean;\r\n}\r\n\r\nexport type ChatAction =\r\n | { type: 'TOGGLE_OPEN' }\r\n | { type: 'SET_OPEN'; payload: boolean }\r\n | { type: 'ADD_MESSAGE'; payload: ChatMessage }\r\n | { type: 'ADD_MESSAGES'; payload: ChatMessage[] }\r\n | { type: 'SET_TYPING'; payload: boolean }\r\n | { type: 'DISMISS_WELCOME' }\r\n | { type: 'SET_STEP'; payload: string | null }\r\n | { type: 'SET_DATA'; payload: Record<string, unknown> }\r\n | { type: 'SET_LOGGED_IN'; payload: boolean }\r\n | { type: 'CLEAR_QUICK_REPLIES' }\r\n | { type: 'RESET_CHAT' }\r\n | { type: 'UPDATE_MESSAGE'; payload: { id: string; updates: Partial<ChatMessage> } };\r\n\r\nexport function chatReducer(state: ChatState, action: ChatAction): ChatState {\r\n switch (action.type) {\r\n case 'TOGGLE_OPEN':\r\n return { ...state, isOpen: !state.isOpen };\r\n case 'SET_OPEN':\r\n return { ...state, isOpen: action.payload };\r\n case 'ADD_MESSAGE':\r\n return { ...state, messages: [...state.messages, action.payload] };\r\n case 'ADD_MESSAGES':\r\n return { ...state, messages: [...state.messages, ...action.payload] };\r\n case 'SET_TYPING':\r\n return { ...state, isTyping: action.payload };\r\n case 'DISMISS_WELCOME':\r\n return { ...state, showWelcome: false };\r\n case 'SET_STEP':\r\n return { ...state, currentStepId: action.payload };\r\n case 'SET_DATA':\r\n return { ...state, collectedData: { ...state.collectedData, ...action.payload } };\r\n case 'SET_LOGGED_IN':\r\n return { ...state, isLoggedIn: action.payload };\r\n case 'CLEAR_QUICK_REPLIES': {\r\n // Only clear quick replies from the last message that has them\r\n let lastIdx = -1;\r\n for (let i = state.messages.length - 1; i >= 0; i--) {\r\n if (state.messages[i].quickReplies) { lastIdx = i; break; }\r\n }\r\n if (lastIdx === -1) return state;\r\n const updated = [...state.messages];\r\n updated[lastIdx] = { ...updated[lastIdx], quickReplies: undefined };\r\n return { ...state, messages: updated };\r\n }\r\n case 'RESET_CHAT':\r\n return {\r\n ...state,\r\n messages: [],\r\n isTyping: false,\r\n currentStepId: null,\r\n collectedData: {},\r\n };\r\n case 'UPDATE_MESSAGE':\r\n return {\r\n ...state,\r\n messages: state.messages.map((m) =>\r\n m.id === action.payload.id ? { ...m, ...action.payload.updates } : m,\r\n ),\r\n };\r\n default:\r\n return state;\r\n }\r\n}\r\n\r\nexport const initialState = (props: ChatBotProps): ChatState => ({\r\n isOpen: props.defaultOpen ?? false,\r\n messages: props.initialMessages ?? [],\r\n isTyping: false,\r\n showWelcome: !!props.welcomeScreen,\r\n currentStepId: null,\r\n collectedData: {},\r\n isLoggedIn: !props.loginForm,\r\n});\r\n\r\ninterface ChatContextValue {\r\n state: ChatState;\r\n dispatch: React.Dispatch<ChatAction>;\r\n props: ChatBotProps;\r\n pluginManager?: PluginManager | null;\r\n}\r\n\r\nexport const ChatContext = createContext<ChatContextValue | null>(null);\r\n\r\nexport function useChatContext(): ChatContextValue {\r\n const ctx = useContext(ChatContext);\r\n if (!ctx) throw new Error('useChatContext must be used within ChatProvider');\r\n return ctx;\r\n}\r\n","import type { ChatTheme, ChatStyle } from '../types';\r\nimport type { CSSProperties } from 'react';\r\n\r\n// ─── Light Mode Defaults ─────────────────────────────────────────\r\n\r\nconst lightDefaults: Required<ChatTheme> = {\r\n primaryColor: '#6C5CE7',\r\n headerBg: 'linear-gradient(135deg, #6C5CE7 0%, #A29BFE 100%)',\r\n headerText: '#FFFFFF',\r\n bubbleBg: 'rgba(241, 243, 249, 0.85)',\r\n bubbleText: '#2D3436',\r\n userBubbleBg: 'linear-gradient(135deg, #6C5CE7 0%, #A29BFE 100%)',\r\n userBubbleText: '#FFFFFF',\r\n fontFamily: '\"Inter\", -apple-system, BlinkMacSystemFont, \"Segoe UI\", Roboto, sans-serif',\r\n fontSize: '14px',\r\n borderRadius: '20px',\r\n windowWidth: '400px',\r\n windowHeight: '600px',\r\n mode: 'light',\r\n};\r\n\r\n// ─── Dark Mode Overrides ─────────────────────────────────────────\r\n\r\nconst darkOverrides: Partial<ChatTheme> = {\r\n headerBg: 'linear-gradient(135deg, #2D1B69 0%, #4A3298 100%)',\r\n headerText: '#F0F0FF',\r\n bubbleBg: 'rgba(45, 45, 70, 0.85)',\r\n bubbleText: '#E8E8F0',\r\n userBubbleBg: 'linear-gradient(135deg, #6C5CE7 0%, #A29BFE 100%)',\r\n userBubbleText: '#FFFFFF',\r\n};\r\n\r\nexport function resolveTheme(theme?: ChatTheme): Required<ChatTheme> {\r\n const base = { ...lightDefaults, ...theme };\r\n if (base.mode === 'dark') {\r\n return { ...base, ...darkOverrides, ...theme };\r\n }\r\n return base;\r\n}\r\n\r\n// ─── CSS Custom Properties ───────────────────────────────────────\r\n\r\nexport function buildCSSVariables(theme: Required<ChatTheme>): Record<string, string> {\r\n return {\r\n '--cb-primary': theme.primaryColor,\r\n '--cb-header-bg': theme.headerBg,\r\n '--cb-header-text': theme.headerText,\r\n '--cb-bubble-bg': theme.bubbleBg,\r\n '--cb-bubble-text': theme.bubbleText,\r\n '--cb-user-bubble-bg': theme.userBubbleBg,\r\n '--cb-user-bubble-text': theme.userBubbleText,\r\n '--cb-font-family': theme.fontFamily,\r\n '--cb-font-size': theme.fontSize,\r\n '--cb-border-radius': theme.borderRadius,\r\n '--cb-window-width': theme.windowWidth,\r\n '--cb-window-height': theme.windowHeight,\r\n '--cb-bg': theme.mode === 'dark' ? 'rgba(22, 22, 40, 0.95)' : 'rgba(255, 255, 255, 0.92)',\r\n '--cb-border': theme.mode === 'dark' ? 'rgba(255,255,255,0.08)' : 'rgba(0,0,0,0.06)',\r\n '--cb-input-bg': theme.mode === 'dark' ? 'rgba(40, 40, 65, 0.8)' : 'rgba(245, 247, 252, 0.9)',\r\n '--cb-input-border': theme.mode === 'dark' ? 'rgba(255,255,255,0.1)' : 'rgba(0,0,0,0.06)',\r\n '--cb-input-text': theme.mode === 'dark' ? '#E0E0E0' : '#2D3436',\r\n '--cb-branding-bg': theme.mode === 'dark' ? 'rgba(20, 20, 35, 0.8)' : 'rgba(250, 250, 255, 0.8)',\r\n };\r\n}\r\n\r\n// ─── Inline Styles Builder ───────────────────────────────────────\r\n\r\nexport function buildStyles(\r\n theme: Required<ChatTheme>,\r\n overrides?: ChatStyle,\r\n) {\r\n const isDark = theme.mode === 'dark';\r\n\r\n const styles = {\r\n root: {\r\n fontFamily: theme.fontFamily,\r\n fontSize: theme.fontSize,\r\n lineHeight: '1.5',\r\n } satisfies CSSProperties,\r\n\r\n launcher: {\r\n position: 'fixed',\r\n width: '62px',\r\n height: '62px',\r\n borderRadius: '50%',\r\n background: theme.headerBg,\r\n color: '#fff',\r\n border: 'none',\r\n cursor: 'pointer',\r\n display: 'flex',\r\n alignItems: 'center',\r\n justifyContent: 'center',\r\n boxShadow: `0 6px 24px rgba(108, 92, 231, 0.4), 0 2px 8px rgba(0,0,0,0.1)`,\r\n transition: 'all 0.3s cubic-bezier(0.4, 0, 0.2, 1)',\r\n zIndex: 9998,\r\n ...overrides?.launcher,\r\n } satisfies CSSProperties,\r\n\r\n window: {\r\n position: 'fixed',\r\n width: theme.windowWidth,\r\n height: theme.windowHeight,\r\n maxHeight: '85vh',\r\n borderRadius: theme.borderRadius,\r\n overflow: 'hidden',\r\n display: 'flex',\r\n flexDirection: 'column',\r\n boxShadow: isDark\r\n ? '0 20px 60px rgba(0,0,0,0.5), 0 0 0 1px rgba(255,255,255,0.05)'\r\n : '0 20px 60px rgba(108, 92, 231, 0.15), 0 8px 24px rgba(0,0,0,0.08), 0 0 0 1px rgba(0,0,0,0.04)',\r\n backgroundColor: isDark ? 'rgba(22, 22, 40, 0.95)' : 'rgba(255, 255, 255, 0.95)',\r\n backdropFilter: 'blur(20px)',\r\n WebkitBackdropFilter: 'blur(20px)',\r\n border: isDark ? '1px solid rgba(255,255,255,0.08)' : '1px solid rgba(255,255,255,0.8)',\r\n zIndex: 9999,\r\n animation: 'cb-window-enter 0.35s cubic-bezier(0.4, 0, 0.2, 1)',\r\n ...overrides?.window,\r\n } satisfies CSSProperties,\r\n\r\n header: {\r\n background: theme.headerBg,\r\n color: theme.headerText,\r\n padding: '18px 20px',\r\n display: 'flex',\r\n alignItems: 'center',\r\n justifyContent: 'space-between',\r\n gap: '12px',\r\n flexShrink: 0,\r\n position: 'relative',\r\n overflow: 'hidden',\r\n ...overrides?.header,\r\n } satisfies CSSProperties,\r\n\r\n messageList: {\r\n flex: 1,\r\n overflowY: 'auto',\r\n padding: '20px 16px',\r\n display: 'flex',\r\n flexDirection: 'column',\r\n gap: '10px',\r\n background: isDark\r\n ? 'linear-gradient(180deg, rgba(22, 22, 40, 0.98) 0%, rgba(30, 30, 50, 0.98) 100%)'\r\n : 'linear-gradient(180deg, rgba(248, 249, 254, 0.95) 0%, rgba(255, 255, 255, 0.95) 100%)',\r\n ...overrides?.messageList,\r\n } satisfies CSSProperties,\r\n\r\n inputArea: {\r\n padding: '12px 16px 14px',\r\n borderTop: `1px solid ${isDark ? 'rgba(255,255,255,0.06)' : 'rgba(0,0,0,0.05)'}`,\r\n backgroundColor: isDark ? 'rgba(20, 20, 38, 0.9)' : 'rgba(255, 255, 255, 0.95)',\r\n backdropFilter: 'blur(12px)',\r\n WebkitBackdropFilter: 'blur(12px)',\r\n flexShrink: 0,\r\n ...overrides?.inputArea,\r\n } satisfies CSSProperties,\r\n\r\n botBubble: {\r\n background: isDark ? 'rgba(45, 45, 70, 0.7)' : 'rgba(241, 243, 249, 0.9)',\r\n color: isDark ? '#E8E8F0' : '#2D3436',\r\n padding: '12px 16px',\r\n borderRadius: '18px 18px 18px 4px',\r\n maxWidth: '82%',\r\n alignSelf: 'flex-start',\r\n wordBreak: 'break-word',\r\n whiteSpace: 'pre-wrap',\r\n backdropFilter: 'blur(8px)',\r\n WebkitBackdropFilter: 'blur(8px)',\r\n border: isDark ? '1px solid rgba(255,255,255,0.06)' : '1px solid rgba(0,0,0,0.04)',\r\n boxShadow: isDark\r\n ? '0 2px 8px rgba(0,0,0,0.2)'\r\n : '0 2px 8px rgba(0,0,0,0.04)',\r\n fontSize: '14px',\r\n lineHeight: '1.55',\r\n letterSpacing: '0.01em',\r\n } satisfies CSSProperties,\r\n\r\n userBubble: {\r\n background: theme.userBubbleBg,\r\n color: theme.userBubbleText,\r\n padding: '12px 16px',\r\n borderRadius: '18px 18px 4px 18px',\r\n maxWidth: '82%',\r\n alignSelf: 'flex-end',\r\n wordBreak: 'break-word',\r\n whiteSpace: 'pre-wrap',\r\n boxShadow: '0 4px 14px rgba(108, 92, 231, 0.25)',\r\n fontSize: '14px',\r\n lineHeight: '1.55',\r\n letterSpacing: '0.01em',\r\n } satisfies CSSProperties,\r\n };\r\n\r\n return styles;\r\n}\r\n\r\nexport type ChatStyles = ReturnType<typeof buildStyles>;\r\n","import React from 'react';\n\ninterface IconProps {\n size?: number;\n color?: string;\n className?: string;\n}\n\nexport const SendIcon: React.FC<IconProps> = ({ size = 18, color = 'currentColor' }) => (\n <svg width={size} height={size} viewBox=\"0 0 24 24\" fill={color}>\n <path d=\"M2.01 21L23 12 2.01 3 2 10l15 2-15 2z\" />\n </svg>\n);\n\nexport const ChatBubbleIcon: React.FC<IconProps> = ({ size = 28, color = 'currentColor' }) => (\n <svg width={size} height={size} viewBox=\"0 0 24 24\" fill=\"none\" stroke={color} strokeWidth=\"2\" strokeLinecap=\"round\" strokeLinejoin=\"round\">\n <path d=\"M21 15a2 2 0 0 1-2 2H7l-4 4V5a2 2 0 0 1 2-2h14a2 2 0 0 1 2 2z\" />\n </svg>\n);\n\nexport const CloseIcon: React.FC<IconProps> = ({ size = 20, color = 'currentColor' }) => (\n <svg width={size} height={size} viewBox=\"0 0 24 24\" fill=\"none\" stroke={color} strokeWidth=\"2\" strokeLinecap=\"round\" strokeLinejoin=\"round\">\n <line x1=\"18\" y1=\"6\" x2=\"6\" y2=\"18\" />\n <line x1=\"6\" y1=\"6\" x2=\"18\" y2=\"18\" />\n </svg>\n);\n\nexport const MinimizeIcon: React.FC<IconProps> = ({ size = 20, color = 'currentColor' }) => (\n <svg width={size} height={size} viewBox=\"0 0 24 24\" fill=\"none\" stroke={color} strokeWidth=\"2\" strokeLinecap=\"round\" strokeLinejoin=\"round\">\n <line x1=\"5\" y1=\"12\" x2=\"19\" y2=\"12\" />\n </svg>\n);\n\nexport const EmojiIcon: React.FC<IconProps> = ({ size = 20, color = 'currentColor' }) => (\n <svg width={size} height={size} viewBox=\"0 0 24 24\" fill=\"none\" stroke={color} strokeWidth=\"2\" strokeLinecap=\"round\" strokeLinejoin=\"round\">\n <circle cx=\"12\" cy=\"12\" r=\"10\" />\n <path d=\"M8 14s1.5 2 4 2 4-2 4-2\" />\n <line x1=\"9\" y1=\"9\" x2=\"9.01\" y2=\"9\" />\n <line x1=\"15\" y1=\"9\" x2=\"15.01\" y2=\"9\" />\n </svg>\n);\n\nexport const AttachmentIcon: React.FC<IconProps> = ({ size = 20, color = 'currentColor' }) => (\n <svg width={size} height={size} viewBox=\"0 0 24 24\" fill=\"none\" stroke={color} strokeWidth=\"2\" strokeLinecap=\"round\" strokeLinejoin=\"round\">\n <path d=\"M21.44 11.05l-9.19 9.19a6 6 0 01-8.49-8.49l9.19-9.19a4 4 0 015.66 5.66l-9.2 9.19a2 2 0 01-2.83-2.83l8.49-8.48\" />\n </svg>\n);\n\nexport const FileIcon: React.FC<IconProps> = ({ size = 16, color = 'currentColor' }) => (\n <svg width={size} height={size} viewBox=\"0 0 24 24\" fill=\"none\" stroke={color} strokeWidth=\"2\" strokeLinecap=\"round\" strokeLinejoin=\"round\">\n <path d=\"M14 2H6a2 2 0 00-2 2v16a2 2 0 002 2h12a2 2 0 002-2V8z\" />\n <polyline points=\"14 2 14 8 20 8\" />\n </svg>\n);\n\nexport const ImageIcon: React.FC<IconProps> = ({ size = 16, color = 'currentColor' }) => (\n <svg width={size} height={size} viewBox=\"0 0 24 24\" fill=\"none\" stroke={color} strokeWidth=\"2\" strokeLinecap=\"round\" strokeLinejoin=\"round\">\n <rect x=\"3\" y=\"3\" width=\"18\" height=\"18\" rx=\"2\" ry=\"2\" />\n <circle cx=\"8.5\" cy=\"8.5\" r=\"1.5\" />\n <polyline points=\"21 15 16 10 5 21\" />\n </svg>\n);\n\nexport const RemoveIcon: React.FC<IconProps> = ({ size = 14, color = 'currentColor' }) => (\n <svg width={size} height={size} viewBox=\"0 0 24 24\" fill=\"none\" stroke={color} strokeWidth=\"2\" strokeLinecap=\"round\" strokeLinejoin=\"round\">\n <circle cx=\"12\" cy=\"12\" r=\"10\" />\n <line x1=\"15\" y1=\"9\" x2=\"9\" y2=\"15\" />\n <line x1=\"9\" y1=\"9\" x2=\"15\" y2=\"15\" />\n </svg>\n);\n\nexport const RestartIcon: React.FC<IconProps> = ({ size = 16, color = 'currentColor' }) => (\n <svg width={size} height={size} viewBox=\"0 0 24 24\" fill=\"none\" stroke={color} strokeWidth=\"2\" strokeLinecap=\"round\" strokeLinejoin=\"round\">\n <polyline points=\"1 4 1 10 7 10\" />\n <path d=\"M3.51 15a9 9 0 1 0 2.13-9.36L1 10\" />\n </svg>\n);\n","import React from 'react';\nimport type { CSSProperties } from 'react';\nimport type { ChatStyles } from '../styles/theme';\nimport { ChatBubbleIcon, CloseIcon } from './icons';\n\ninterface LauncherProps {\n onClick: () => void;\n isOpen: boolean;\n position: 'bottom-right' | 'bottom-left';\n styles: ChatStyles;\n icon?: React.ReactNode;\n closeIcon?: React.ReactNode;\n zIndex?: number;\n}\n\nexport const Launcher: React.FC<LauncherProps> = ({\n onClick,\n isOpen,\n position,\n styles,\n icon,\n closeIcon,\n zIndex,\n}) => {\n const posStyle: CSSProperties =\n position === 'bottom-left'\n ? { bottom: '24px', left: '24px' }\n : { bottom: '24px', right: '24px' };\n\n return (\n <button\n onClick={onClick}\n aria-label={isOpen ? 'Close chat' : 'Open chat'}\n style={{\n ...styles.launcher,\n ...posStyle,\n ...(zIndex != null ? { zIndex } : {}),\n transform: isOpen ? 'scale(0.92) rotate(90deg)' : 'scale(1)',\n animation: isOpen ? 'none' : 'cb-launcher-pulse 3s ease-in-out infinite',\n }}\n >\n {isOpen\n ? closeIcon ?? <CloseIcon size={22} />\n : icon ?? <ChatBubbleIcon size={26} />}\n </button>\n );\n};\n","import React from 'react';\nimport type { HeaderConfig } from '../types';\nimport type { ChatStyles as ThemeStyles } from '../styles/theme';\nimport { CloseIcon, MinimizeIcon, RestartIcon } from './icons';\n\ninterface ChatHeaderProps {\n config: HeaderConfig;\n styles: ThemeStyles;\n onClose: () => void;\n onRestart?: () => void;\n logo?: string;\n logoWidth?: string;\n}\n\nexport const ChatHeader: React.FC<ChatHeaderProps> = ({ config, styles, onClose, onRestart, logo, logoWidth }) => {\n return (\n <div style={styles.header}>\n {/* Decorative glow overlay */}\n <div\n style={{\n position: 'absolute',\n top: 0,\n left: 0,\n right: 0,\n bottom: 0,\n background: 'linear-gradient(135deg, rgba(255,255,255,0.12) 0%, transparent 50%)',\n pointerEvents: 'none',\n }}\n />\n <div style={{ display: 'flex', alignItems: 'center', gap: '12px', flex: 1, position: 'relative', zIndex: 1 }}>\n {config.avatar && (\n <div style={{ position: 'relative' }}>\n <img\n src={config.avatar}\n alt=\"\"\n style={{\n width: '40px',\n height: '40px',\n borderRadius: '50%',\n objectFit: 'cover',\n border: '2px solid rgba(255,255,255,0.3)',\n }}\n />\n <span\n style={{\n position: 'absolute',\n bottom: '1px',\n right: '1px',\n width: '10px',\n height: '10px',\n backgroundColor: '#2ECC71',\n borderRadius: '50%',\n border: '2px solid rgba(255,255,255,0.8)',\n }}\n />\n </div>\n )}\n {logo && !config.avatar && (\n <img\n src={logo}\n alt=\"\"\n style={{ width: logoWidth ?? '36px', height: 'auto', objectFit: 'contain', filter: 'brightness(1.1)' }}\n />\n )}\n {!config.avatar && !logo && (\n <div\n style={{\n width: '40px',\n height: '40px',\n borderRadius: '50%',\n background: 'rgba(255,255,255,0.2)',\n backdropFilter: 'blur(4px)',\n display: 'flex',\n alignItems: 'center',\n justifyContent: 'center',\n fontSize: '18px',\n fontWeight: 700,\n color: 'rgba(255,255,255,0.9)',\n border: '1px solid rgba(255,255,255,0.2)',\n }}\n >\n {(config.title ?? 'C').charAt(0).toUpperCase()}\n </div>\n )}\n <div>\n <div style={{ fontWeight: 600, fontSize: '16px', letterSpacing: '-0.01em' }}>\n {config.title ?? 'Chat with us'}\n </div>\n {config.subtitle && (\n <div style={{\n fontSize: '12px',\n opacity: 0.8,\n display: 'flex',\n alignItems: 'center',\n gap: '5px',\n marginTop: '1px',\n }}>\n <span style={{\n width: '6px',\n height: '6px',\n borderRadius: '50%',\n backgroundColor: '#2ECC71',\n display: 'inline-block',\n }} />\n {config.subtitle}\n </div>\n )}\n </div>\n </div>\n <div style={{ display: 'flex', alignItems: 'center', gap: '2px', position: 'relative', zIndex: 1 }}>\n {config.showRestart && onRestart && (\n <button\n onClick={onRestart}\n aria-label=\"Restart conversation\"\n title=\"Restart conversation\"\n style={{\n background: 'rgba(255,255,255,0.1)',\n border: 'none',\n color: 'inherit',\n cursor: 'pointer',\n padding: '6px',\n display: 'flex',\n alignItems: 'center',\n borderRadius: '8px',\n transition: 'background 0.2s ease',\n }}\n onMouseEnter={(e) => (e.currentTarget.style.background = 'rgba(255,255,255,0.2)')}\n onMouseLeave={(e) => (e.currentTarget.style.background = 'rgba(255,255,255,0.1)')}\n >\n <RestartIcon size={16} />\n </button>\n )}\n {config.showMinimize && (\n <button\n onClick={onClose}\n aria-label=\"Minimize chat\"\n style={{\n background: 'rgba(255,255,255,0.1)',\n border: 'none',\n color: 'inherit',\n cursor: 'pointer',\n padding: '6px',\n display: 'flex',\n alignItems: 'center',\n borderRadius: '8px',\n transition: 'background 0.2s ease',\n }}\n onMouseEnter={(e) => (e.currentTarget.style.background = 'rgba(255,255,255,0.2)')}\n onMouseLeave={(e) => (e.currentTarget.style.background = 'rgba(255,255,255,0.1)')}\n >\n <MinimizeIcon size={16} />\n </button>\n )}\n {config.showClose !== false && (\n <button\n onClick={onClose}\n aria-label=\"Close chat\"\n style={{\n background: 'rgba(255,255,255,0.1)',\n border: 'none',\n color: 'inherit',\n cursor: 'pointer',\n padding: '6px',\n display: 'flex',\n alignItems: 'center',\n borderRadius: '8px',\n transition: 'background 0.2s ease',\n }}\n onMouseEnter={(e) => (e.currentTarget.style.background = 'rgba(255,255,255,0.2)')}\n onMouseLeave={(e) => (e.currentTarget.style.background = 'rgba(255,255,255,0.1)')}\n >\n <CloseIcon size={18} />\n </button>\n )}\n </div>\n </div>\n );\n};\n","import React from 'react';\nimport type { ReactNode } from 'react';\n\ninterface WelcomeScreenProps {\n content: ReactNode;\n onDismiss: () => void;\n primaryColor: string;\n}\n\nexport const WelcomeScreen: React.FC<WelcomeScreenProps> = ({ content, onDismiss, primaryColor }) => {\n return (\n <div\n style={{\n flex: 1,\n display: 'flex',\n flexDirection: 'column',\n overflow: 'auto',\n background: 'linear-gradient(180deg, rgba(248, 249, 254, 0.95) 0%, rgba(255, 255, 255, 0.98) 100%)',\n }}\n >\n <div style={{ flex: 1, padding: '28px 24px', overflow: 'auto' }}>\n {content}\n </div>\n <div\n style={{\n padding: '16px 20px',\n borderTop: '1px solid rgba(0,0,0,0.05)',\n backdropFilter: 'blur(12px)',\n WebkitBackdropFilter: 'blur(12px)',\n flexShrink: 0,\n }}\n >\n <button\n onClick={onDismiss}\n style={{\n width: '100%',\n padding: '14px',\n background: `linear-gradient(135deg, ${primaryColor} 0%, ${adjustColor(primaryColor, 30)} 100%)`,\n color: '#fff',\n border: 'none',\n borderRadius: '14px',\n fontSize: '15px',\n fontWeight: 600,\n cursor: 'pointer',\n fontFamily: 'inherit',\n letterSpacing: '0.02em',\n boxShadow: `0 6px 20px ${primaryColor}44`,\n transition: 'all 0.25s cubic-bezier(0.4, 0, 0.2, 1)',\n }}\n onMouseEnter={(e) => {\n e.currentTarget.style.transform = 'translateY(-1px)';\n e.currentTarget.style.boxShadow = `0 8px 28px ${primaryColor}55`;\n }}\n onMouseLeave={(e) => {\n e.currentTarget.style.transform = 'translateY(0)';\n e.currentTarget.style.boxShadow = `0 6px 20px ${primaryColor}44`;\n }}\n >\n Start Chat\n </button>\n </div>\n </div>\n );\n};\n\nfunction adjustColor(hex: string, amount: number): string {\n const num = parseInt(hex.replace('#', ''), 16);\n const r = Math.min(255, ((num >> 16) & 0xff) + amount);\n const g = Math.min(255, ((num >> 8) & 0xff) + amount);\n const b = Math.min(255, (num & 0xff) + amount);\n return `#${((r << 16) | (g << 8) | b).toString(16).padStart(6, '0')}`;\n}\n","import React from 'react';\nimport type { FormFieldConfig } from '../../types';\n\ninterface TextFieldProps {\n field: FormFieldConfig;\n value: string;\n onChange: (value: string) => void;\n error?: string;\n}\n\nexport const TextField: React.FC<TextFieldProps> = ({ field, value, onChange, error }) => {\n const isTextarea = field.type === 'textarea';\n const inputType = field.type === 'textarea' ? undefined : field.type;\n\n const baseStyle: React.CSSProperties = {\n width: '100%',\n padding: '10px 14px',\n border: `1.5px solid ${error ? 'rgba(229, 62, 62, 0.5)' : 'rgba(0,0,0,0.08)'}`,\n borderRadius: '12px',\n fontSize: '13px',\n fontFamily: 'inherit',\n outline: 'none',\n boxSizing: 'border-box',\n transition: 'all 0.2s ease',\n backgroundColor: 'rgba(245, 247, 252, 0.6)',\n color: '#2D3436',\n letterSpacing: '0.01em',\n };\n\n return (\n <div style={{ marginBottom: '14px' }}>\n {field.label && (\n <label style={{ display: 'block', marginBottom: '6px', fontSize: '13px', fontWeight: 500, color: '#2D3436' }}>\n {field.label}\n {field.required && <span style={{ color: '#E53E3E', marginLeft: '3px' }}>*</span>}\n </label>\n )}\n {isTextarea ? (\n <textarea\n value={value}\n onChange={(e) => onChange(e.target.value)}\n placeholder={field.placeholder}\n required={field.required}\n rows={3}\n style={{ ...baseStyle, resize: 'vertical' }}\n minLength={field.validation?.minLength}\n maxLength={field.validation?.maxLength}\n />\n ) : (\n <input\n type={inputType}\n value={value}\n onChange={(e) => onChange(e.target.value)}\n placeholder={field.placeholder}\n required={field.required}\n style={baseStyle}\n min={field.validation?.min}\n max={field.validation?.max}\n minLength={field.validation?.minLength}\n maxLength={field.validation?.maxLength}\n pattern={field.validation?.pattern}\n />\n )}\n {error && <div style={{ color: '#E53E3E', fontSize: '12px', marginTop: '2px' }}>{error}</div>}\n </div>\n );\n};\n","import React from 'react';\nimport type { FormFieldConfig } from '../../types';\n\ninterface SelectFieldProps {\n field: FormFieldConfig;\n value: string | string[];\n onChange: (value: string | string[]) => void;\n error?: string;\n}\n\nexport const SelectField: React.FC<SelectFieldProps> = ({ field, value, onChange, error }) => {\n const isMulti = field.type === 'multiselect' || field.multiple;\n\n const handleChange = (e: React.ChangeEvent<HTMLSelectElement>) => {\n if (isMulti) {\n const selected = Array.from(e.target.selectedOptions, (opt) => opt.value);\n onChange(selected);\n } else {\n onChange(e.target.value);\n }\n };\n\n const selectValue = isMulti\n ? Array.isArray(value) ? value : [value].filter(Boolean)\n : typeof value === 'string' ? value : '';\n\n return (\n <div style={{ marginBottom: '14px' }}>\n {field.label && (\n <label style={{ display: 'block', marginBottom: '6px', fontSize: '13px', fontWeight: 500, color: '#2D3436' }}>\n {field.label}\n {field.required && <span style={{ color: '#E53E3E', marginLeft: '3px' }}>*</span>}\n </label>\n )}\n <select\n value={selectValue}\n onChange={handleChange}\n multiple={isMulti}\n required={field.required}\n style={{\n width: '100%',\n padding: '10px 14px',\n border: `1.5px solid ${error ? 'rgba(229, 62, 62, 0.5)' : 'rgba(0,0,0,0.08)'}`,\n borderRadius: '12px',\n fontSize: '13px',\n fontFamily: 'inherit',\n outline: 'none',\n backgroundColor: 'rgba(245, 247, 252, 0.6)',\n color: '#2D3436',\n boxSizing: 'border-box',\n transition: 'all 0.2s ease',\n ...(isMulti ? { minHeight: '80px' } : {}),\n }}\n >\n {!isMulti && <option value=\"\">Select...</option>}\n {field.options?.map((opt) => (\n <option key={opt.value} value={opt.value}>\n {opt.label}\n </option>\n ))}\n </select>\n {isMulti && (\n <div style={{ fontSize: '11px', color: '#888', marginTop: '2px' }}>\n Hold Ctrl/Cmd to select multiple\n </div>\n )}\n {error && <div style={{ color: '#E53E3E', fontSize: '12px', marginTop: '2px' }}>{error}</div>}\n </div>\n );\n};\n","import React from 'react';\nimport type { FormFieldConfig } from '../../types';\n\ninterface RadioFieldProps {\n field: FormFieldConfig;\n value: string;\n onChange: (value: string) => void;\n error?: string;\n}\n\nexport const RadioField: React.FC<RadioFieldProps> = ({ field, value, onChange, error }) => {\n return (\n <div style={{ marginBottom: '12px' }}>\n {field.label && (\n <label style={{ display: 'block', marginBottom: '6px', fontSize: '13px', fontWeight: 500 }}>\n {field.label}\n {field.required && <span style={{ color: '#E53E3E', marginLeft: '2px' }}>*</span>}\n </label>\n )}\n <div style={{ display: 'flex', flexDirection: 'column', gap: '6px' }}>\n {field.options?.map((opt) => (\n <label\n key={opt.value}\n style={{\n display: 'flex',\n alignItems: 'center',\n gap: '8px',\n cursor: 'pointer',\n fontSize: '13px',\n }}\n >\n <input\n type=\"radio\"\n name={field.name}\n value={opt.value}\n checked={value === opt.value}\n onChange={() => onChange(opt.value)}\n style={{ margin: 0 }}\n />\n {opt.label}\n </label>\n ))}\n </div>\n {error && <div style={{ color: '#E53E3E', fontSize: '12px', marginTop: '2px' }}>{error}</div>}\n </div>\n );\n};\n","import React from 'react';\nimport type { FormFieldConfig } from '../../types';\n\ninterface CheckboxFieldProps {\n field: FormFieldConfig;\n value: string[];\n onChange: (value: string[]) => void;\n error?: string;\n}\n\nexport const CheckboxField: React.FC<CheckboxFieldProps> = ({ field, value, onChange, error }) => {\n const handleToggle = (optValue: string) => {\n if (value.includes(optValue)) {\n onChange(value.filter((v) => v !== optValue));\n } else {\n onChange([...value, optValue]);\n }\n };\n\n return (\n <div style={{ marginBottom: '12px' }}>\n {field.label && (\n <label style={{ display: 'block', marginBottom: '6px', fontSize: '13px', fontWeight: 500 }}>\n {field.label}\n {field.required && <span style={{ color: '#E53E3E', marginLeft: '2px' }}>*</span>}\n </label>\n )}\n <div style={{ display: 'flex', flexDirection: 'column', gap: '6px' }}>\n {field.options?.map((opt) => (\n <label\n key={opt.value}\n style={{\n display: 'flex',\n alignItems: 'center',\n gap: '8px',\n cursor: 'pointer',\n fontSize: '13px',\n }}\n >\n <input\n type=\"checkbox\"\n checked={value.includes(opt.value)}\n onChange={() => handleToggle(opt.value)}\n style={{ margin: 0 }}\n />\n {opt.label}\n </label>\n ))}\n </div>\n {error && <div style={{ color: '#E53E3E', fontSize: '12px', marginTop: '2px' }}>{error}</div>}\n </div>\n );\n};\n","import React, { useRef } from 'react';\nimport type { FormFieldConfig } from '../../types';\n\ninterface FileUploadFieldProps {\n field: FormFieldConfig;\n value: FileList | null;\n onChange: (files: FileList | null) => void;\n error?: string;\n primaryColor: string;\n}\n\nexport const FileUploadField: React.FC<FileUploadFieldProps> = ({\n field,\n value,\n onChange,\n error,\n primaryColor,\n}) => {\n const inputRef = useRef<HTMLInputElement>(null);\n\n const fileNames = value ? Array.from(value).map((f) => f.name).join(', ') : '';\n\n return (\n <div style={{ marginBottom: '12px' }}>\n {field.label && (\n <label style={{ display: 'block', marginBottom: '4px', fontSize: '13px', fontWeight: 500 }}>\n {field.label}\n {field.required && <span style={{ color: '#E53E3E', marginLeft: '2px' }}>*</span>}\n </label>\n )}\n <input\n ref={inputRef}\n type=\"file\"\n accept={field.accept}\n multiple={field.multiple}\n onChange={(e) => onChange(e.target.files)}\n style={{ display: 'none' }}\n />\n <button\n type=\"button\"\n onClick={() => inputRef.current?.click()}\n style={{\n padding: '8px 16px',\n border: `1px dashed ${error ? '#E53E3E' : '#D1D5DB'}`,\n borderRadius: '8px',\n backgroundColor: '#FAFAFA',\n cursor: 'pointer',\n fontSize: '13px',\n color: '#555',\n width: '100%',\n textAlign: 'left',\n }}\n >\n {fileNames || field.placeholder || 'Choose file(s)...'}\n </button>\n {fileNames && (\n <div style={{ fontSize: '12px', color: primaryColor, marginTop: '4px' }}>\n {Array.from(value!).length} file(s) selected\n </div>\n )}\n {error && <div style={{ color: '#E53E3E', fontSize: '12px', marginTop: '2px' }}>{error}</div>}\n </div>\n );\n};\n","import React, { useState, useCallback } from 'react';\r\nimport type { FormConfig, FormFieldConfig } from '../../types';\r\nimport type { FormFieldRenderMap } from '../../types/form';\r\nimport { TextField } from './TextField';\r\nimport { SelectField } from './SelectField';\r\nimport { RadioField } from './RadioField';\r\nimport { CheckboxField } from './CheckboxField';\r\nimport { FileUploadField } from './FileUploadField';\r\n\r\ninterface DynamicFormProps {\r\n config: FormConfig;\r\n onSubmit: (data: Record<string, unknown>) => void;\r\n primaryColor: string;\r\n renderFormField?: FormFieldRenderMap;\r\n}\r\n\r\nexport const DynamicForm: React.FC<DynamicFormProps> = ({ config, onSubmit, primaryColor, renderFormField }) => {\r\n const [values, setValues] = useState<Record<string, unknown>>(() => {\r\n const init: Record<string, unknown> = {};\r\n for (const field of config.fields) {\r\n if (field.defaultValue !== undefined) {\r\n init[field.name] = field.defaultValue;\r\n } else if (field.type === 'checkbox' || field.type === 'multiselect') {\r\n init[field.name] = [];\r\n } else if (field.type === 'file') {\r\n init[field.name] = null;\r\n } else {\r\n init[field.name] = '';\r\n }\r\n }\r\n return init;\r\n });\r\n\r\n const [errors, setErrors] = useState<Record<string, string>>({});\r\n const [submitted, setSubmitted] = useState(false);\r\n\r\n const setValue = useCallback((name: string, value: unknown) => {\r\n setValues((prev) => ({ ...prev, [name]: value }));\r\n setErrors((prev) => {\r\n const next = { ...prev };\r\n delete next[name];\r\n return next;\r\n });\r\n }, []);\r\n\r\n const validate = (): boolean => {\r\n const newErrors: Record<string, string> = {};\r\n\r\n for (const field of config.fields) {\r\n const val = values[field.name];\r\n\r\n // Required check\r\n if (field.required) {\r\n if (\r\n val === '' ||\r\n val === null ||\r\n val === undefined ||\r\n (Array.isArray(val) && val.length === 0)\r\n ) {\r\n newErrors[field.name] = field.validation?.message ?? `${field.label || field.name} is required`;\r\n continue;\r\n }\r\n }\r\n\r\n // Pattern check\r\n if (field.validation?.pattern && typeof val === 'string' && val) {\r\n try {\r\n const regex = new RegExp(field.validation.pattern);\r\n if (!regex.test(val)) {\r\n newErrors[field.name] = field.validation.message ?? 'Invalid format';\r\n }\r\n } catch {\r\n // Invalid regex pattern in config — skip validation\r\n }\r\n }\r\n }\r\n\r\n setErrors(newErrors);\r\n return Object.keys(newErrors).length === 0;\r\n };\r\n\r\n const handleSubmit = (e: React.FormEvent) => {\r\n e.preventDefault();\r\n if (!validate()) return;\r\n setSubmitted(true);\r\n onSubmit(values);\r\n };\r\n\r\n if (submitted) {\r\n return (\r\n <div\r\n style={{\r\n padding: '16px',\r\n background: 'linear-gradient(135deg, rgba(46, 213, 115, 0.1), rgba(46, 213, 115, 0.05))',\r\n borderRadius: '14px',\r\n fontSize: '14px',\r\n color: '#2ecc71',\r\n textAlign: 'center',\r\n fontWeight: 500,\r\n border: '1px solid rgba(46, 213, 115, 0.15)',\r\n animation: 'cb-fade-in 0.3s ease-out',\r\n }}\r\n >\r\n ✓ Submitted successfully\r\n </div>\r\n );\r\n }\r\n\r\n return (\r\n <form\r\n onSubmit={handleSubmit}\r\n style={{\r\n background: 'rgba(255, 255, 255, 0.7)',\r\n backdropFilter: 'blur(12px)',\r\n WebkitBackdropFilter: 'blur(12px)',\r\n borderRadius: '16px',\r\n padding: '20px',\r\n border: '1px solid rgba(0,0,0,0.06)',\r\n boxShadow: '0 4px 16px rgba(0,0,0,0.04)',\r\n animation: 'cb-slide-up 0.35s ease-out',\r\n }}\r\n >\r\n {config.title && (\r\n <div style={{ fontWeight: 600, fontSize: '15px', marginBottom: '4px', color: '#2D3436', letterSpacing: '-0.01em' }}>\r\n {config.title}\r\n </div>\r\n )}\r\n {config.description && (\r\n <div style={{ fontSize: '12px', color: 'rgba(0,0,0,0.45)', marginBottom: '16px', lineHeight: '1.5' }}>\r\n {config.description}\r\n </div>\r\n )}\r\n\r\n {config.fields.map((field) => (\r\n <FormField\r\n key={field.name}\r\n field={field}\r\n value={values[field.name]}\r\n onChange={(v) => setValue(field.name, v)}\r\n error={errors[field.name]}\r\n primaryColor={primaryColor}\r\n renderFormField={renderFormField}\r\n />\r\n ))}\r\n\r\n <button\r\n type=\"submit\"\r\n style={{\r\n width: '100%',\r\n padding: '12px',\r\n background: `linear-gradient(135deg, ${primaryColor} 0%, ${adjustColor(primaryColor, 30)} 100%)`,\r\n color: '#fff',\r\n border: 'none',\r\n borderRadius: '12px',\r\n fontSize: '14px',\r\n fontWeight: 600,\r\n cursor: 'pointer',\r\n marginTop: '8px',\r\n fontFamily: 'inherit',\r\n letterSpacing: '0.02em',\r\n boxShadow: `0 4px 14px ${primaryColor}33`,\r\n transition: 'all 0.25s cubic-bezier(0.4, 0, 0.2, 1)',\r\n }}\r\n onMouseEnter={(e) => {\r\n e.currentTarget.style.transform = 'translateY(-1px)';\r\n e.currentTarget.style.boxShadow = `0 6px 20px ${primaryColor}44`;\r\n }}\r\n onMouseLeave={(e) => {\r\n e.currentTarget.style.transform = 'translateY(0)';\r\n e.currentTarget.style.boxShadow = `0 4px 14px ${primaryColor}33`;\r\n }}\r\n >\r\n {config.submitLabel ?? 'Submit'}\r\n </button>\r\n </form>\r\n );\r\n};\r\n\r\n// ─── Field Router ────────────────────────────────────────────────\r\n\r\ninterface FormFieldProps {\r\n field: FormFieldConfig;\r\n value: unknown;\r\n onChange: (value: unknown) => void;\r\n error?: string;\r\n primaryColor: string;\r\n renderFormField?: FormFieldRenderMap;\r\n}\r\n\r\nconst FormField: React.FC<FormFieldProps> = ({ field, value, onChange, error, primaryColor, renderFormField }) => {\r\n // Check for custom renderer override\r\n const customRenderer = renderFormField?.[field.type as keyof FormFieldRenderMap];\r\n\r\n switch (field.type) {\r\n case 'text':\r\n case 'email':\r\n case 'password':\r\n case 'number':\r\n case 'tel':\r\n case 'url':\r\n case 'textarea':\r\n case 'date':\r\n case 'time': {\r\n const typedProps = { type: field.type as 'text', field, value: String(value ?? ''), onChange: onChange as (v: string) => void, error };\r\n const defaultEl = <TextField field={field} value={String(value ?? '')} onChange={onChange as (v: string) => void} error={error} />;\r\n if (customRenderer) return <>{(customRenderer as (p: typeof typedProps, d: React.ReactNode) => React.ReactNode)(typedProps, defaultEl)}</>;\r\n return defaultEl;\r\n }\r\n case 'select':\r\n case 'multiselect': {\r\n const typedProps = { type: field.type as 'select', field, value: value as string | string[], onChange: onChange as (v: string | string[]) => void, error };\r\n const defaultEl = <SelectField field={field} value={value as string | string[]} onChange={onChange as (v: string | string[]) => void} error={error} />;\r\n if (customRenderer) return <>{(customRenderer as (p: typeof typedProps, d: React.ReactNode) => React.ReactNode)(typedProps, defaultEl)}</>;\r\n return defaultEl;\r\n }\r\n case 'radio': {\r\n const typedProps = { type: 'radio' as const, field, value: String(value ?? ''), onChange: onChange as (v: string) => void, error };\r\n const defaultEl = <RadioField field={field} value={String(value ?? '')} onChange={onChange as (v: string) => void} error={error} />;\r\n if (customRenderer) return <>{(customRenderer as (p: typeof typedProps, d: React.ReactNode) => React.ReactNode)(typedProps, defaultEl)}</>;\r\n return defaultEl;\r\n }\r\n case 'checkbox': {\r\n const typedProps = { type: 'checkbox' as const, field, value: ((value as string[]) ?? []), onChange: onChange as (v: string[]) => void, error };\r\n const defaultEl = <CheckboxField field={field} value={(value as string[]) ?? []} onChange={onChange as (v: string[]) => void} error={error} />;\r\n if (customRenderer) return <>{(customRenderer as (p: typeof typedProps, d: React.ReactNode) => React.ReactNode)(typedProps, defaultEl)}</>;\r\n return defaultEl;\r\n }\r\n case 'file': {\r\n const typedProps = { type: 'file' as const, field, value: value as FileList | null, onChange: onChange as (v: FileList | null) => void, error, primaryColor };\r\n const defaultEl = <FileUploadField field={field} value={value as FileList | null} onChange={onChange as (v: FileList | null) => void} error={error} primaryColor={primaryColor} />;\r\n if (customRenderer) return <>{(customRenderer as (p: typeof typedProps, d: React.ReactNode) => React.ReactNode)(typedProps, defaultEl)}</>;\r\n return defaultEl;\r\n }\r\n case 'hidden':\r\n return <input type=\"hidden\" name={field.name} value={String(value ?? '')} />;\r\n default:\r\n return null;\r\n }\r\n};\r\n\r\nfunction adjustColor(hex: string, amount: number): string {\r\n const num = parseInt(hex.replace('#', ''), 16);\r\n const r = Math.min(255, ((num >> 16) & 0xff) + amount);\r\n const g = Math.min(255, ((num >> 8) & 0xff) + amount);\r\n const b = Math.min(255, (num & 0xff) + amount);\r\n return `#${((r << 16) | (g << 8) | b).toString(16).padStart(6, '0')}`;\r\n}\r\n","import React from 'react';\nimport type { FormConfig } from '../types';\nimport type { FormFieldRenderMap } from '../types/form';\nimport { DynamicForm } from './forms/DynamicForm';\n\ninterface LoginScreenProps {\n config: FormConfig;\n onLogin: (data: Record<string, unknown>) => void;\n primaryColor: string;\n renderFormField?: FormFieldRenderMap;\n}\n\nexport const LoginScreen: React.FC<LoginScreenProps> = ({ config, onLogin, primaryColor, renderFormField }) => {\n return (\n <div\n style={{\n flex: 1,\n display: 'flex',\n flexDirection: 'column',\n justifyContent: 'center',\n padding: '24px',\n overflow: 'auto',\n background: 'linear-gradient(180deg, rgba(248, 249, 254, 0.95) 0%, rgba(255, 255, 255, 0.98) 100%)',\n }}\n >\n <DynamicForm config={config} onSubmit={onLogin} primaryColor={primaryColor} renderFormField={renderFormField} />\n </div>\n );\n};\n","import React from 'react';\r\nimport type { ChatMessage, MessageAttachment } from '../types';\r\nimport type { ChatStyles } from '../styles/theme';\r\nimport { FileIcon } from './icons';\r\n\r\ninterface MessageBubbleProps {\r\n message: ChatMessage;\r\n styles: ChatStyles;\r\n}\r\n\r\nexport const MessageBubble: React.FC<MessageBubbleProps> = ({ message, styles }) => {\r\n const isBot = message.sender === 'bot';\r\n const isSystem = message.sender === 'system';\r\n const bubbleStyle = isBot || isSystem ? styles.botBubble : styles.userBubble;\r\n\r\n const hasContent = message.text || (message.attachments && message.attachments.length > 0);\r\n if (!hasContent) return null;\r\n\r\n const systemStyle: React.CSSProperties = isSystem\r\n ? {\r\n background: 'transparent',\r\n border: 'none',\r\n boxShadow: 'none',\r\n color: '#999',\r\n fontSize: '12px',\r\n alignSelf: 'center',\r\n padding: '6px 12px',\r\n backdropFilter: 'none',\r\n WebkitBackdropFilter: 'none',\r\n }\r\n : {};\r\n\r\n return (\r\n <div\r\n style={{\r\n ...bubbleStyle,\r\n ...systemStyle,\r\n animation: 'cb-fade-in 0.3s ease-out',\r\n }}\r\n >\r\n {message.text && (\r\n <span style={{ display: 'block' }}>{message.text}</span>\r\n )}\r\n {message.attachments && message.attachments.length > 0 && (\r\n <div style={{ marginTop: message.text ? '10px' : 0, display: 'flex', flexDirection: 'column', gap: '6px' }}>\r\n {message.attachments.map((attachment, i) => (\r\n <AttachmentPreview key={i} attachment={attachment} isBot={isBot} />\r\n ))}\r\n </div>\r\n )}\r\n </div>\r\n );\r\n};\r\n\r\n// ─── Attachment Preview ──────────────────────────────────────────\r\n\r\ninterface AttachmentPreviewProps {\r\n attachment: MessageAttachment;\r\n isBot: boolean;\r\n}\r\n\r\nconst AttachmentPreview: React.FC<AttachmentPreviewProps> = ({ attachment, isBot }) => {\r\n const isImage = attachment.type.startsWith('image/');\r\n\r\n if (isImage && attachment.url) {\r\n return (\r\n <div style={{ borderRadius: '12px', overflow: 'hidden', maxWidth: '220px' }}>\r\n <img\r\n src={attachment.url}\r\n alt={attachment.name}\r\n style={{\r\n width: '100%',\r\n height: 'auto',\r\n display: 'block',\r\n borderRadius: '12px',\r\n }}\r\n />\r\n <div style={{ fontSize: '11px', padding: '4px 0', opacity: 0.6 }}>{attachment.name}</div>\r\n </div>\r\n );\r\n }\r\n\r\n return (\r\n <a\r\n href={attachment.url}\r\n target=\"_blank\"\r\n rel=\"noopener noreferrer\"\r\n style={{\r\n display: 'flex',\r\n alignItems: 'center',\r\n gap: '8px',\r\n padding: '8px 12px',\r\n backgroundColor: isBot ? 'rgba(0,0,0,0.04)' : 'rgba(255,255,255,0.15)',\r\n borderRadius: '10px',\r\n textDecoration: 'none',\r\n color: 'inherit',\r\n fontSize: '13px',\r\n border: isBot ? '1px solid rgba(0,0,0,0.06)' : '1px solid rgba(255,255,255,0.15)',\r\n transition: 'background 0.2s ease',\r\n }}\r\n >\r\n <FileIcon size={16} />\r\n <span style={{ overflow: 'hidden', textOverflow: 'ellipsis', whiteSpace: 'nowrap', flex: 1 }}>\r\n {attachment.name}\r\n </span>\r\n {attachment.size && (\r\n <span style={{ fontSize: '11px', opacity: 0.5, flexShrink: 0 }}>\r\n {formatFileSize(attachment.size)}\r\n </span>\r\n )}\r\n </a>\r\n );\r\n};\r\n\r\nfunction formatFileSize(bytes: number): string {\r\n if (bytes < 1024) return `${bytes}B`;\r\n if (bytes < 1024 * 1024) return `${(bytes / 1024).toFixed(1)}KB`;\r\n return `${(bytes / (1024 * 1024)).toFixed(1)}MB`;\r\n}\r\n","import React from 'react';\nimport type { FlowQuickReply } from '../types';\n\ninterface QuickRepliesProps {\n replies: FlowQuickReply[];\n onSelect: (value: string, label: string) => void;\n primaryColor: string;\n}\n\nexport const QuickReplies: React.FC<QuickRepliesProps> = ({ replies, onSelect, primaryColor }) => {\n return (\n <div\n style={{\n display: 'flex',\n flexWrap: 'wrap',\n gap: '8px',\n alignSelf: 'flex-start',\n maxWidth: '90%',\n animation: 'cb-slide-up 0.35s ease-out',\n padding: '4px 0',\n }}\n >\n {replies.map((reply) => (\n <button\n key={reply.value}\n onClick={() => onSelect(reply.value, reply.label)}\n style={{\n padding: '8px 18px',\n borderRadius: '22px',\n border: `1.5px solid ${primaryColor}`,\n backgroundColor: 'rgba(108, 92, 231, 0.06)',\n color: primaryColor,\n cursor: 'pointer',\n fontSize: '13px',\n fontWeight: 500,\n fontFamily: 'inherit',\n transition: 'all 0.25s cubic-bezier(0.4, 0, 0.2, 1)',\n backdropFilter: 'blur(4px)',\n WebkitBackdropFilter: 'blur(4px)',\n letterSpacing: '0.01em',\n }}\n onMouseEnter={(e) => {\n e.currentTarget.style.backgroundColor = primaryColor;\n e.currentTarget.style.color = '#fff';\n e.currentTarget.style.transform = 'translateY(-1px)';\n e.currentTarget.style.boxShadow = `0 4px 14px ${primaryColor}44`;\n }}\n onMouseLeave={(e) => {\n e.currentTarget.style.backgroundColor = 'rgba(108, 92, 231, 0.06)';\n e.currentTarget.style.color = primaryColor;\n e.currentTarget.style.transform = 'translateY(0)';\n e.currentTarget.style.boxShadow = 'none';\n }}\n >\n {reply.label}\n </button>\n ))}\n </div>\n );\n};\n","import React from 'react';\n\ninterface TypingIndicatorProps {\n color: string;\n}\n\nexport const TypingIndicator: React.FC<TypingIndicatorProps> = ({ color }) => {\n const dotStyle: React.CSSProperties = {\n width: '7px',\n height: '7px',\n borderRadius: '50%',\n backgroundColor: color,\n opacity: 0.35,\n animation: 'cb-typing-bounce 1.4s infinite ease-in-out',\n };\n\n return (\n <div\n style={{\n display: 'flex',\n gap: '5px',\n padding: '14px 18px',\n background: 'rgba(241, 243, 249, 0.8)',\n backdropFilter: 'blur(8px)',\n WebkitBackdropFilter: 'blur(8px)',\n borderRadius: '18px 18px 18px 4px',\n alignSelf: 'flex-start',\n alignItems: 'center',\n border: '1px solid rgba(0,0,0,0.04)',\n boxShadow: '0 2px 8px rgba(0,0,0,0.04)',\n animation: 'cb-fade-in 0.3s ease-out',\n }}\n >\n <span style={{ ...dotStyle, animationDelay: '0s' }} />\n <span style={{ ...dotStyle, animationDelay: '0.2s' }} />\n <span style={{ ...dotStyle, animationDelay: '0.4s' }} />\n </div>\n );\n};\n","import React, { useRef, useEffect } from 'react';\r\nimport type { ComponentType } from 'react';\r\nimport type { ChatMessage } from '../types';\r\nimport type { StepComponentProps, FlowActionResult } from '../types/config';\r\nimport type { FormFieldRenderMap } from '../types/form';\r\nimport type { ChatStyles } from '../styles/theme';\r\nimport { MessageBubble } from './MessageBubble';\r\nimport { QuickReplies } from './QuickReplies';\r\nimport { TypingIndicator } from './TypingIndicator';\r\nimport { DynamicForm } from './forms/DynamicForm';\r\n\r\ninterface MessageListProps {\r\n messages: ChatMessage[];\r\n isTyping: boolean;\r\n styles: ChatStyles;\r\n primaryColor: string;\r\n onQuickReply: (value: string, label: string) => void;\r\n onFormSubmit: (formId: string, data: Record<string, unknown>) => void;\r\n /** Map of custom step components */\r\n components?: Record<string, ComponentType<StepComponentProps>>;\r\n /** Called when a custom component completes */\r\n onComponentComplete?: (result?: FlowActionResult) => void;\r\n /** Collected flow data — passed to custom components */\r\n collectedData?: Record<string, unknown>;\r\n /** Current step ID */\r\n currentStepId?: string | null;\r\n /** Custom form field renderers per field type */\r\n renderFormField?: FormFieldRenderMap;\r\n}\r\n\r\nexport const MessageList: React.FC<MessageListProps> = ({\r\n messages,\r\n isTyping,\r\n styles,\r\n primaryColor,\r\n onQuickReply,\r\n onFormSubmit,\r\n components,\r\n onComponentComplete,\r\n collectedData,\r\n currentStepId,\r\n renderFormField,\r\n}) => {\r\n const bottomRef = useRef<HTMLDivElement>(null);\r\n\r\n useEffect(() => {\r\n bottomRef.current?.scrollIntoView({ behavior: 'smooth' });\r\n }, [messages, isTyping]);\r\n\r\n return (\r\n <div style={styles.messageList} className=\"cb-scrollbar\">\r\n {messages.map((msg) => (\r\n <React.Fragment key={msg.id}>\r\n <MessageBubble message={msg} styles={styles} />\r\n {msg.quickReplies && msg.quickReplies.length > 0 && (\r\n <QuickReplies\r\n replies={msg.quickReplies}\r\n onSelect={onQuickReply}\r\n primaryColor={primaryColor}\r\n />\r\n )}\r\n {msg.form && (\r\n <div style={{ alignSelf: 'flex-start', width: '92%', animation: 'cb-slide-up 0.35s ease-out' }}>\r\n <DynamicForm\r\n config={msg.form}\r\n onSubmit={(data) => onFormSubmit(msg.form!.id, data)}\r\n primaryColor={primaryColor}\r\n renderFormField={renderFormField}\r\n />\r\n </div>\r\n )}\r\n {msg.component && components?.[msg.component] && (\r\n <div style={{ alignSelf: 'flex-start', width: '92%', animation: 'cb-slide-up 0.35s ease-out' }}>\r\n {React.createElement(components[msg.component], {\r\n stepId: currentStepId ?? '',\r\n data: collectedData ?? {},\r\n onComplete: (result?: FlowActionResult) => onComponentComplete?.(result),\r\n })}\r\n </div>\r\n )}\r\n </React.Fragment>\r\n ))}\r\n {isTyping && <TypingIndicator color={primaryColor} />}\r\n <div ref={bottomRef} />\r\n </div>\r\n );\r\n};\r\n","import React, { useState, useRef, useEffect } from 'react';\n\nconst EMOJI_CATEGORIES = [\n {\n name: 'Smileys',\n emojis: ['😀', '😃', '😄', '😁', '😅', '😂', '🤣', '😊', '😇', '🙂', '😉', '😍', '🥰', '😘', '😋', '😜', '🤪', '🤗', '🤔', '🤫', '🤭', '😏', '😐', '😑', '😶', '😌', '😴', '🤤', '😷', '🤒'],\n },\n {\n name: 'Gestures',\n emojis: ['👍', '👎', '👌', '✌️', '🤞', '🤟', '🤘', '👋', '🤚', '✋', '🖖', '👏', '🙌', '🤝', '🙏', '💪', '🖐️', '☝️', '👆', '👇', '👈', '👉', '🤙', '🫡', '🫶', '🫰', '🫳', '🫴', '🫲', '🫱'],\n },\n {\n name: 'Hearts',\n emojis: ['❤️', '🧡', '💛', '💚', '💙', '💜', '🖤', '🤍', '🤎', '💔', '❣️', '💕', '💞', '💓', '💗', '💖', '💘', '💝', '💟', '♥️', '🫀', '💌', '💐', '🌹', '🌺', '🌸', '🌼', '🌻', '🌷', '💮'],\n },\n {\n name: 'Objects',\n emojis: ['🔥', '⭐', '✨', '💯', '🎉', '🎊', '🎯', '🚀', '💡', '📌', '📎', '🔗', '💻', '📱', '☎️', '📧', '📝', '📋', '📊', '📈', '🗂️', '📁', '🔒', '🔑', '⚙️', '🛠️', '🔧', '📦', '🏷️', '✅'],\n },\n];\n\ninterface EmojiPickerProps {\n onSelect: (emoji: string) => void;\n onClose: () => void;\n primaryColor: string;\n}\n\nexport const EmojiPicker: React.FC<EmojiPickerProps> = ({ onSelect, onClose, primaryColor }) => {\n const [activeCategory, setActiveCategory] = useState(0);\n const pickerRef = useRef<HTMLDivElement>(null);\n\n useEffect(() => {\n const handleClickOutside = (e: MouseEvent) => {\n if (pickerRef.current && !pickerRef.current.contains(e.target as Node)) {\n onClose();\n }\n };\n document.addEventListener('mousedown', handleClickOutside);\n return () => document.removeEventListener('mousedown', handleClickOutside);\n }, [onClose]);\n\n const currentEmojis = EMOJI_CATEGORIES[activeCategory]?.emojis ?? [];\n\n return (\n <div\n ref={pickerRef}\n style={{\n position: 'absolute',\n bottom: '100%',\n left: 0,\n width: '280px',\n backgroundColor: 'rgba(255, 255, 255, 0.92)',\n backdropFilter: 'blur(20px)',\n WebkitBackdropFilter: 'blur(20px)',\n borderRadius: '16px',\n boxShadow: '0 8px 32px rgba(0,0,0,0.12), 0 0 0 1px rgba(0,0,0,0.04)',\n border: '1px solid rgba(255,255,255,0.8)',\n overflow: 'hidden',\n zIndex: 10,\n marginBottom: '8px',\n animation: 'cb-slide-up 0.25s ease-out',\n }}\n >\n {/* Category tabs */}\n <div\n style={{\n display: 'flex',\n borderBottom: '1px solid rgba(0,0,0,0.06)',\n padding: '6px',\n gap: '3px',\n }}\n >\n {EMOJI_CATEGORIES.map((cat, idx) => (\n <button\n key={cat.name}\n onClick={() => setActiveCategory(idx)}\n title={cat.name}\n style={{\n flex: 1,\n padding: '6px 4px',\n border: 'none',\n borderRadius: '8px',\n cursor: 'pointer',\n fontSize: '11px',\n fontWeight: 600,\n fontFamily: 'inherit',\n letterSpacing: '0.02em',\n background: idx === activeCategory\n ? `linear-gradient(135deg, ${primaryColor}, ${primaryColor}CC)`\n : 'transparent',\n color: idx === activeCategory ? '#fff' : 'rgba(0,0,0,0.4)',\n transition: 'all 0.2s ease',\n boxShadow: idx === activeCategory ? `0 2px 8px ${primaryColor}33` : 'none',\n }}\n >\n {cat.name}\n </button>\n ))}\n </div>\n\n {/* Emoji Grid */}\n <div\n style={{\n display: 'grid',\n gridTemplateColumns: 'repeat(8, 1fr)',\n gap: '2px',\n padding: '8px',\n maxHeight: '180px',\n overflowY: 'auto',\n }}\n >\n {currentEmojis.map((emoji) => (\n <button\n key={emoji}\n onClick={() => {\n onSelect(emoji);\n onClose();\n }}\n style={{\n width: '30px',\n height: '30px',\n border: 'none',\n backgroundColor: 'transparent',\n cursor: 'pointer',\n fontSize: '18px',\n borderRadius: '6px',\n display: 'flex',\n alignItems: 'center',\n justifyContent: 'center',\n transition: 'all 0.15s ease',\n }}\n onMouseEnter={(e) => (e.currentTarget.style.backgroundColor = 'rgba(108, 92, 231, 0.08)')}\n onMouseLeave={(e) => (e.currentTarget.style.backgroundColor = 'transparent')}\n >\n {emoji}\n </button>\n ))}\n </div>\n </div>\n );\n};\n","import React, { useRef } from 'react';\r\nimport type { FileUploadConfig } from '../types/config';\r\nimport { AttachmentIcon, RemoveIcon, FileIcon, ImageIcon } from './icons';\r\n\r\ninterface FileUploadButtonProps {\r\n config: FileUploadConfig;\r\n onFiles: (files: File[]) => void;\r\n selectedFiles: File[];\r\n onRemoveFile: (index: number) => void;\r\n primaryColor: string;\r\n}\r\n\r\nexport const FileUploadButton: React.FC<FileUploadButtonProps> = ({\r\n config,\r\n onFiles,\r\n selectedFiles,\r\n onRemoveFile,\r\n primaryColor,\r\n}) => {\r\n const inputRef = useRef<HTMLInputElement>(null);\r\n\r\n const handleChange = (e: React.ChangeEvent<HTMLInputElement>) => {\r\n const files = e.target.files;\r\n if (!files || files.length === 0) return;\r\n\r\n const fileArr = Array.from(files);\r\n\r\n // Validate file size\r\n if (config.maxSize) {\r\n const oversized = fileArr.filter((f) => f.size > config.maxSize!);\r\n if (oversized.length > 0) {\r\n alert(`File(s) too large. Max size: ${formatSize(config.maxSize)}`);\r\n return;\r\n }\r\n }\r\n\r\n // Validate max count\r\n const maxFiles = config.maxFiles ?? 5;\r\n if (selectedFiles.length + fileArr.length > maxFiles) {\r\n alert(`Maximum ${maxFiles} files allowed`);\r\n return;\r\n }\r\n\r\n onFiles(fileArr);\r\n // Reset input to allow re-selecting same file\r\n if (inputRef.current) inputRef.current.value = '';\r\n };\r\n\r\n return (\r\n <div>\r\n <input\r\n ref={inputRef}\r\n type=\"file\"\r\n accept={config.accept}\r\n multiple={config.multiple !== false}\r\n onChange={handleChange}\r\n style={{ display: 'none' }}\r\n />\r\n <button\r\n type=\"button\"\r\n onClick={() => inputRef.current?.click()}\r\n aria-label=\"Attach file\"\r\n title=\"Attach file\"\r\n style={{\r\n background: 'none',\r\n border: 'none',\r\n cursor: 'pointer',\r\n padding: '6px',\r\n display: 'flex',\r\n alignItems: 'center',\r\n color: '#999',\r\n borderRadius: '6px',\r\n transition: 'color 0.15s ease',\r\n }}\r\n onMouseEnter={(e) => (e.currentTarget.style.color = primaryColor)}\r\n onMouseLeave={(e) => (e.currentTarget.style.color = '#999')}\r\n >\r\n <AttachmentIcon size={20} />\r\n </button>\r\n </div>\r\n );\r\n};\r\n\r\n// ─── File Preview List ───────────────────────────────────────────\r\n\r\ninterface FilePreviewListProps {\r\n files: File[];\r\n onRemove: (index: number) => void;\r\n primaryColor: string;\r\n}\r\n\r\nexport const FilePreviewList: React.FC<FilePreviewListProps> = ({\r\n files,\r\n onRemove,\r\n primaryColor,\r\n}) => {\r\n if (files.length === 0) return null;\r\n\r\n return (\r\n <div\r\n style={{\r\n display: 'flex',\r\n flexWrap: 'wrap',\r\n gap: '6px',\r\n padding: '8px 12px 0',\r\n }}\r\n >\r\n {files.map((file, idx) => (\r\n <FilePreviewChip\r\n key={`${file.name}-${idx}`}\r\n file={file}\r\n onRemove={() => onRemove(idx)}\r\n primaryColor={primaryColor}\r\n />\r\n ))}\r\n </div>\r\n );\r\n};\r\n\r\n// ─── Single File Chip ────────────────────────────────────────────\r\n\r\ninterface FilePreviewChipProps {\r\n file: File;\r\n onRemove: () => void;\r\n primaryColor: string;\r\n}\r\n\r\nconst FilePreviewChip: React.FC<FilePreviewChipProps> = ({ file, onRemove, primaryColor }) => {\r\n const isImage = file.type.startsWith('image/');\r\n\r\n return (\r\n <div\r\n style={{\r\n display: 'flex',\r\n alignItems: 'center',\r\n gap: '6px',\r\n padding: '4px 8px',\r\n backgroundColor: '#F3F4F6',\r\n borderRadius: '8px',\r\n fontSize: '12px',\r\n maxWidth: '200px',\r\n }}\r\n >\r\n <span style={{ color: primaryColor, flexShrink: 0 }}>\r\n {isImage ? <ImageIcon size={14} /> : <FileIcon size={14} />}\r\n </span>\r\n <span\r\n style={{\r\n overflow: 'hidden',\r\n textOverflow: 'ellipsis',\r\n whiteSpace: 'nowrap',\r\n color: '#555',\r\n }}\r\n >\r\n {file.name}\r\n </span>\r\n <span style={{ color: '#999', fontSize: '11px', flexShrink: 0 }}>\r\n {formatSize(file.size)}\r\n </span>\r\n <button\r\n onClick={onRemove}\r\n style={{\r\n background: 'none',\r\n border: 'none',\r\n cursor: 'pointer',\r\n padding: '0',\r\n display: 'flex',\r\n color: '#999',\r\n flexShrink: 0,\r\n }}\r\n >\r\n <RemoveIcon size={14} />\r\n </button>\r\n </div>\r\n );\r\n};\r\n\r\n// ─── Utils ───────────────────────────────────────────────────────\r\n\r\nfunction formatSize(bytes: number): string {\r\n if (bytes < 1024) return `${bytes}B`;\r\n if (bytes < 1024 * 1024) return `${(bytes / 1024).toFixed(1)}KB`;\r\n return `${(bytes / (1024 * 1024)).toFixed(1)}MB`;\r\n}\r\n","import React, { useState, useRef, useCallback } from 'react';\nimport type { CSSProperties } from 'react';\nimport type { FileUploadConfig } from '../types/config';\nimport { SendIcon, EmojiIcon } from './icons';\nimport { EmojiPicker } from './EmojiPicker';\nimport { FileUploadButton, FilePreviewList } from './FileUpload';\n\ninterface ChatInputProps {\n onSend: (text: string, files?: File[]) => void;\n placeholder?: string;\n primaryColor: string;\n isDark?: boolean;\n disabled?: boolean;\n styleOverride?: CSSProperties;\n enableEmoji?: boolean;\n fileUpload?: FileUploadConfig;\n onFileUpload?: (files: File[]) => void;\n}\n\nexport const ChatInput: React.FC<ChatInputProps> = ({\n onSend,\n placeholder = 'Type a message...',\n primaryColor,\n isDark = false,\n disabled,\n styleOverride,\n enableEmoji = false,\n fileUpload,\n onFileUpload,\n}) => {\n const [text, setText] = useState('');\n const [showEmoji, setShowEmoji] = useState(false);\n const [attachedFiles, setAttachedFiles] = useState<File[]>([]);\n const inputRef = useRef<HTMLTextAreaElement>(null);\n\n const handleSend = useCallback(() => {\n const trimmed = text.trim();\n if (!trimmed && attachedFiles.length === 0) return;\n onSend(trimmed, attachedFiles.length > 0 ? attachedFiles : undefined);\n setText('');\n setAttachedFiles([]);\n inputRef.current?.focus();\n }, [text, attachedFiles, onSend]);\n\n const handleKeyDown = (e: React.KeyboardEvent) => {\n if (e.key === 'Enter' && !e.shiftKey) {\n e.preventDefault();\n handleSend();\n }\n };\n\n const handleEmojiSelect = (emoji: string) => {\n setText((prev) => prev + emoji);\n inputRef.current?.focus();\n };\n\n const handleFiles = (files: File[]) => {\n setAttachedFiles((prev) => [...prev, ...files]);\n onFileUpload?.(files);\n };\n\n const handleRemoveFile = (index: number) => {\n setAttachedFiles((prev) => prev.filter((_, i) => i !== index));\n };\n\n const hasContent = text.trim() || attachedFiles.length > 0;\n\n return (\n <div style={{ position: 'relative', ...styleOverride }}>\n {/* File preview above input */}\n {attachedFiles.length > 0 && (\n <FilePreviewList\n files={attachedFiles}\n onRemove={handleRemoveFile}\n primaryColor={primaryColor}\n />\n )}\n\n {/* Emoji picker */}\n {showEmoji && (\n <EmojiPicker\n onSelect={handleEmojiSelect}\n onClose={() => setShowEmoji(false)}\n primaryColor={primaryColor}\n />\n )}\n\n <div\n style={{\n display: 'flex',\n gap: '8px',\n alignItems: 'flex-end',\n background: isDark ? 'rgba(40, 40, 65, 0.5)' : 'rgba(245, 247, 252, 0.7)',\n borderRadius: '16px',\n border: `1px solid ${isDark ? 'rgba(255,255,255,0.08)' : 'rgba(0,0,0,0.05)'}`,\n backdropFilter: 'blur(8px)',\n WebkitBackdropFilter: 'blur(8px)',\n padding: '6px 6px 6px 12px',\n }}\n >\n {/* Action buttons */}\n <div style={{ display: 'flex', alignItems: 'center', gap: '2px', flexShrink: 0, paddingBottom: '2px' }}>\n {enableEmoji && (\n <button\n type=\"button\"\n onClick={() => setShowEmoji(!showEmoji)}\n aria-label=\"Emoji\"\n title=\"Emoji\"\n style={{\n background: 'none',\n border: 'none',\n cursor: 'pointer',\n padding: '6px',\n display: 'flex',\n color: showEmoji ? primaryColor : (isDark ? 'rgba(255,255,255,0.35)' : 'rgba(0,0,0,0.3)'),\n borderRadius: '8px',\n transition: 'all 0.2s ease',\n }}\n >\n <EmojiIcon size={20} />\n </button>\n )}\n\n {fileUpload?.enabled && (\n <FileUploadButton\n config={fileUpload}\n onFiles={handleFiles}\n selectedFiles={attachedFiles}\n onRemoveFile={handleRemoveFile}\n primaryColor={primaryColor}\n />\n )}\n </div>\n\n {/* Text Input */}\n <textarea\n ref={inputRef}\n value={text}\n onChange={(e) => setText(e.target.value)}\n onKeyDown={handleKeyDown}\n placeholder={placeholder}\n disabled={disabled}\n rows={1}\n style={{\n flex: 1,\n padding: '8px 2px',\n border: 'none',\n borderRadius: '12px',\n outline: 'none',\n resize: 'none',\n fontFamily: 'inherit',\n fontSize: '14px',\n lineHeight: '1.45',\n maxHeight: '100px',\n overflowY: 'auto',\n backgroundColor: 'transparent',\n color: isDark ? '#E0E0E0' : '#2D3436',\n letterSpacing: '0.01em',\n }}\n />\n\n {/* Send Button */}\n <button\n onClick={handleSend}\n disabled={disabled || !hasContent}\n aria-label=\"Send message\"\n style={{\n width: '36px',\n height: '36px',\n borderRadius: '12px',\n background: hasContent\n ? `linear-gradient(135deg, ${primaryColor} 0%, ${adjustColor(primaryColor, 30)} 100%)`\n : (isDark ? 'rgba(255,255,255,0.08)' : 'rgba(0,0,0,0.06)'),\n color: hasContent ? '#fff' : (isDark ? 'rgba(255,255,255,0.25)' : 'rgba(0,0,0,0.2)'),\n border: 'none',\n cursor: hasContent ? 'pointer' : 'default',\n display: 'flex',\n alignItems: 'center',\n justifyContent: 'center',\n flexShrink: 0,\n transition: 'all 0.25s cubic-bezier(0.4, 0, 0.2, 1)',\n boxShadow: hasContent ? `0 4px 12px ${primaryColor}44` : 'none',\n }}\n >\n <SendIcon size={16} />\n </button>\n </div>\n </div>\n );\n};\n\nfunction adjustColor(hex: string, amount: number): string {\n const num = parseInt(hex.replace('#', ''), 16);\n const r = Math.min(255, ((num >> 16) & 0xff) + amount);\n const g = Math.min(255, ((num >> 8) & 0xff) + amount);\n const b = Math.min(255, (num & 0xff) + amount);\n return `#${((r << 16) | (g << 8) | b).toString(16).padStart(6, '0')}`;\n}\n","import React from 'react';\nimport type { BrandingConfig } from '../types/config';\n\ninterface BrandingProps {\n config: BrandingConfig;\n primaryColor: string;\n}\n\nexport const Branding: React.FC<BrandingProps> = ({ config, primaryColor }) => {\n if (config.showBranding === false) return null;\n\n const text = config.poweredBy ?? 'React ChatBot';\n\n return (\n <div\n style={{\n padding: '8px 16px',\n textAlign: 'center',\n fontSize: '11px',\n color: 'rgba(0,0,0,0.35)',\n background: 'rgba(250, 250, 255, 0.7)',\n backdropFilter: 'blur(8px)',\n WebkitBackdropFilter: 'blur(8px)',\n borderTop: '1px solid rgba(0,0,0,0.04)',\n flexShrink: 0,\n letterSpacing: '0.02em',\n }}\n >\n Powered by{' '}\n {config.poweredByUrl ? (\n <a\n href={config.poweredByUrl}\n target=\"_blank\"\n rel=\"noopener noreferrer\"\n style={{\n color: primaryColor,\n textDecoration: 'none',\n fontWeight: 600,\n transition: 'opacity 0.2s ease',\n }}\n >\n {text}\n </a>\n ) : (\n <span style={{ color: primaryColor, fontWeight: 600 }}>{text}</span>\n )}\n </div>\n );\n};\n","import type { FlowConfig, FlowStep, ChatMessage, FlowQuickReply } from '../types';\r\n\r\nexport class FlowEngine {\r\n private steps: Map<string, FlowStep>;\r\n private startStep: string;\r\n private collectedData: Record<string, unknown> = {};\r\n private idCounter = 0;\r\n private uid = (): string => `msg_${Date.now()}_${++this.idCounter}`;\r\n private stepHistory: string[] = [];\r\n\r\n constructor(flow: FlowConfig) {\r\n this.startStep = flow.startStep;\r\n this.steps = new Map(flow.steps.map((s) => [s.id, s]));\r\n }\r\n\r\n getStartStepId(): string {\r\n return this.startStep;\r\n }\r\n\r\n getStep(id: string): FlowStep | undefined {\r\n return this.steps.get(id);\r\n }\r\n\r\n getData(): Record<string, unknown> {\r\n return { ...this.collectedData };\r\n }\r\n\r\n setData(key: string, value: unknown): void {\r\n this.collectedData[key] = value;\r\n }\r\n\r\n mergeData(data: Record<string, unknown>): void {\r\n Object.assign(this.collectedData, data);\r\n }\r\n\r\n /** Push a step onto the history stack (called when entering a step) */\r\n pushHistory(stepId: string): void {\r\n this.stepHistory.push(stepId);\r\n }\r\n\r\n /** Pop and return the previous step (go back) */\r\n popHistory(): string | undefined {\r\n // Remove current step\r\n this.stepHistory.pop();\r\n // Return previous step\r\n return this.stepHistory.pop();\r\n }\r\n\r\n /** Check if there's a previous step to go back to */\r\n canGoBack(): boolean {\r\n return this.stepHistory.length > 1;\r\n }\r\n\r\n /** Reset the engine to initial state */\r\n reset(): void {\r\n this.collectedData = {};\r\n this.stepHistory = [];\r\n }\r\n\r\n resolveNext(step: FlowStep, userValue?: string): string | undefined {\r\n // Conditional branching\r\n if (step.condition) {\r\n const { field, operator, value, then: thenStep, else: elseStep } = step.condition;\r\n const fieldVal = this.collectedData[field];\r\n const match = this.evaluate(fieldVal, operator, value);\r\n return match ? thenStep : elseStep;\r\n }\r\n\r\n // Quick-reply selected → find the reply's next\r\n if (userValue && step.quickReplies) {\r\n const reply = step.quickReplies.find((r) => r.value === userValue);\r\n if (reply?.next) return reply.next;\r\n }\r\n\r\n return step.next;\r\n }\r\n\r\n /** Returns true if the step expects a quick reply (not free text) */\r\n stepExpectsQuickReply(step: FlowStep): boolean {\r\n return !!(step.quickReplies && step.quickReplies.length > 0);\r\n }\r\n\r\n /** Returns true if the step expects a form submission */\r\n stepExpectsForm(step: FlowStep): boolean {\r\n return !!step.form;\r\n }\r\n\r\n /** Try to fuzzy-match user text against quick reply labels */\r\n matchQuickReply(step: FlowStep, text: string): FlowQuickReply | undefined {\r\n if (!step.quickReplies) return undefined;\r\n const lower = text.toLowerCase().trim();\r\n // Exact value match\r\n const exact = step.quickReplies.find((r) => r.value.toLowerCase() === lower);\r\n if (exact) return exact;\r\n // Exact label match \r\n const labelMatch = step.quickReplies.find((r) => r.label.toLowerCase().replace(/[^\\w\\s]/g, '').trim() === lower);\r\n if (labelMatch) return labelMatch;\r\n // Contains match\r\n const contains = step.quickReplies.find((r) => lower.includes(r.value.toLowerCase()) || r.label.toLowerCase().includes(lower));\r\n return contains;\r\n }\r\n\r\n buildMessages(step: FlowStep): ChatMessage[] {\r\n const messages: ChatMessage[] = [];\r\n\r\n const texts = step.messages ?? (step.message ? [step.message] : []);\r\n for (const text of texts) {\r\n messages.push({\r\n id: this.uid(),\r\n sender: 'bot',\r\n text,\r\n timestamp: Date.now(),\r\n });\r\n }\r\n\r\n // Attach quick replies to the last message\r\n if (step.quickReplies && messages.length > 0) {\r\n messages[messages.length - 1]!.quickReplies = step.quickReplies;\r\n }\r\n\r\n // If step has a form, create a form message\r\n if (step.form) {\r\n messages.push({\r\n id: this.uid(),\r\n sender: 'bot',\r\n timestamp: Date.now(),\r\n form: step.form,\r\n });\r\n }\r\n\r\n // If step has a custom component, create a component message\r\n if (step.component) {\r\n messages.push({\r\n id: this.uid(),\r\n sender: 'bot',\r\n timestamp: Date.now(),\r\n component: step.component,\r\n });\r\n }\r\n\r\n return messages;\r\n }\r\n\r\n private evaluate(\r\n fieldVal: unknown,\r\n operator: string,\r\n value: string | number,\r\n ): boolean {\r\n switch (operator) {\r\n case 'eq':\r\n return String(fieldVal) === String(value);\r\n case 'neq':\r\n return String(fieldVal) !== String(value);\r\n case 'contains':\r\n return String(fieldVal).includes(String(value));\r\n case 'gt':\r\n return Number(fieldVal) > Number(value);\r\n case 'lt':\r\n return Number(fieldVal) < Number(value);\r\n default:\r\n return false;\r\n }\r\n }\r\n}\r\n\r\nlet globalIdCounter = 0;\r\nexport function createQuickReplyMessage(\r\n replies: FlowQuickReply[],\r\n): ChatMessage {\r\n return {\r\n id: `msg_${Date.now()}_${++globalIdCounter}`,\r\n sender: 'bot',\r\n timestamp: Date.now(),\r\n quickReplies: replies,\r\n };\r\n}\r\n","let counter = 0;\n\nexport const uid = (): string => `msg_${Date.now()}_${++counter}`;\n\nexport const classNames = (...args: (string | false | null | undefined)[]): string =>\n args.filter(Boolean).join(' ');\n\nexport const delay = (ms: number): Promise<void> =>\n new Promise((resolve) => setTimeout(resolve, ms));\n","import { useCallback, useRef, useEffect } from 'react';\r\nimport { useChatContext } from '../context/ChatContext';\r\nimport { FlowEngine } from '../engine/FlowEngine';\r\nimport { uid, delay } from '../utils/helpers';\r\nimport type { ChatMessage } from '../types';\r\nimport type { FlowActionResult, ActionContext, KeywordRoute } from '../types/config';\r\nimport type { FlowStepInput } from '../types/flow';\r\n\r\n/** Slash commands the user can type */\r\nconst COMMANDS: Record<string, string> = {\r\n '/help': 'Show available commands',\r\n '/cancel': 'Cancel current step and go back',\r\n '/back': 'Go back to the previous step',\r\n '/restart': 'Restart the conversation from the beginning',\r\n};\r\n\r\n/** Common greeting words for auto-detection */\r\nconst GREETING_PATTERNS = ['hi', 'hello', 'hey', 'howdy', 'hola', 'greetings', 'good morning', 'good afternoon', 'good evening', 'sup', 'yo', 'hii', 'hiii'];\r\n\r\n/** Match user text against a single keyword route */\r\nfunction matchesRoute(text: string, route: KeywordRoute): boolean {\r\n const compare = route.caseSensitive ? text : text.toLowerCase();\r\n for (const pattern of route.patterns) {\r\n const pat = route.caseSensitive ? pattern : pattern.toLowerCase();\r\n switch (route.matchType ?? 'contains') {\r\n case 'exact':\r\n if (compare === pat) return true;\r\n break;\r\n case 'startsWith':\r\n if (compare.startsWith(pat)) return true;\r\n break;\r\n case 'regex':\r\n try {\r\n if (new RegExp(pat, route.caseSensitive ? '' : 'i').test(text)) return true;\r\n } catch { /* invalid regex — skip */ }\r\n break;\r\n case 'contains':\r\n default:\r\n if (compare.includes(pat)) return true;\r\n break;\r\n }\r\n }\r\n return false;\r\n}\r\n\r\n/** Find the best matching keyword route (highest priority) */\r\nfunction findKeywordMatch(text: string, keywords: KeywordRoute[]): KeywordRoute | undefined {\r\n const sorted = [...keywords].sort((a, b) => (b.priority ?? 0) - (a.priority ?? 0));\r\n return sorted.find((r) => matchesRoute(text, r));\r\n}\r\n\r\n/** Validate and transform user text for an input step */\r\nfunction validateInput(text: string, input: FlowStepInput): { valid: boolean; value: string; error?: string } {\r\n let value = text;\r\n if (input.transform) {\r\n switch (input.transform) {\r\n case 'trim': value = value.trim(); break;\r\n case 'lowercase': value = value.toLowerCase(); break;\r\n case 'uppercase': value = value.toUpperCase(); break;\r\n case 'email': value = value.trim().toLowerCase(); break;\r\n }\r\n }\r\n if (input.validation) {\r\n const v = input.validation;\r\n if (v.required && !value.trim()) return { valid: false, value, error: v.message ?? 'This field is required.' };\r\n if (v.minLength && value.length < v.minLength) return { valid: false, value, error: v.message ?? `Must be at least ${v.minLength} characters.` };\r\n if (v.maxLength && value.length > v.maxLength) return { valid: false, value, error: v.message ?? `Must be at most ${v.maxLength} characters.` };\r\n if (v.pattern) {\r\n try {\r\n if (!new RegExp(v.pattern).test(value)) return { valid: false, value, error: v.message ?? 'Invalid format.' };\r\n } catch { /* invalid pattern */ }\r\n }\r\n }\r\n return { valid: true, value };\r\n}\r\n\r\nexport function useChat() {\r\n const { state, dispatch, props, pluginManager } = useChatContext();\r\n const flowRef = useRef<FlowEngine | null>(null);\r\n const flowStartedRef = useRef(false);\r\n\r\n // Keep fresh references for use inside async callbacks (avoids stale closures)\r\n const stateRef = useRef(state);\r\n stateRef.current = state;\r\n const propsRef = useRef(props);\r\n propsRef.current = props;\r\n\r\n // Initialize flow engine\r\n useEffect(() => {\r\n if (props.flow) {\r\n flowRef.current = new FlowEngine(props.flow);\r\n flowStartedRef.current = false;\r\n }\r\n }, [props.flow]);\r\n\r\n const addBotMessage = useCallback(\r\n async (text: string, extras?: Partial<ChatMessage>) => {\r\n dispatch({ type: 'SET_TYPING', payload: true });\r\n await delay(400);\r\n const msg: ChatMessage = {\r\n id: uid(),\r\n sender: 'bot',\r\n text,\r\n timestamp: Date.now(),\r\n ...extras,\r\n };\r\n dispatch({ type: 'SET_TYPING', payload: false });\r\n dispatch({ type: 'ADD_MESSAGE', payload: msg });\r\n propsRef.current.callbacks?.onMessageReceive?.(msg);\r\n },\r\n [dispatch],\r\n );\r\n\r\n const addSystemMessage = useCallback(\r\n (text: string) => {\r\n dispatch({\r\n type: 'ADD_MESSAGE',\r\n payload: { id: uid(), sender: 'system', text, timestamp: Date.now() },\r\n });\r\n },\r\n [dispatch],\r\n );\r\n\r\n // Use a ref so processFlowStep can call itself recursively without stale closure\r\n const processFlowStepRef = useRef<(stepId: string) => Promise<void>>(async () => {});\r\n processFlowStepRef.current = async (stepId: string) => {\r\n const engine = flowRef.current;\r\n if (!engine) return;\r\n\r\n const step = engine.getStep(stepId);\r\n if (!step) return;\r\n\r\n // Track step history for /back navigation\r\n engine.pushHistory(stepId);\r\n\r\n dispatch({ type: 'SET_STEP', payload: stepId });\r\n dispatch({ type: 'SET_TYPING', payload: true });\r\n await delay(step.delay ?? 500);\r\n\r\n const messages = engine.buildMessages(step);\r\n dispatch({ type: 'SET_TYPING', payload: false });\r\n dispatch({ type: 'ADD_MESSAGES', payload: messages });\r\n\r\n messages.forEach((m) => propsRef.current.callbacks?.onMessageReceive?.(m));\r\n\r\n // Handle async action (API calls, verification, etc.)\r\n if (step.asyncAction) {\r\n const handler = propsRef.current.actionHandlers?.[step.asyncAction.handler];\r\n if (handler) {\r\n const statusMsgId = uid();\r\n // Show loading/status message\r\n dispatch({\r\n type: 'ADD_MESSAGE',\r\n payload: {\r\n id: statusMsgId,\r\n sender: 'bot',\r\n text: step.asyncAction.loadingMessage ?? 'Processing...',\r\n timestamp: Date.now(),\r\n },\r\n });\r\n\r\n const ctx: ActionContext = {\r\n updateMessage: (text: string) => {\r\n dispatch({ type: 'UPDATE_MESSAGE', payload: { id: statusMsgId, updates: { text } } });\r\n },\r\n };\r\n\r\n try {\r\n const result = await handler(engine.getData(), ctx);\r\n\r\n // Merge result data into collected data\r\n if (result.data) {\r\n engine.mergeData(result.data);\r\n dispatch({ type: 'SET_DATA', payload: result.data });\r\n }\r\n\r\n // Update status message with final text\r\n const finalMsg =\r\n result.message ??\r\n (result.status === 'success'\r\n ? (step.asyncAction.successMessage ?? 'Done!')\r\n : (step.asyncAction.errorMessage ?? 'Something went wrong.'));\r\n dispatch({ type: 'UPDATE_MESSAGE', payload: { id: statusMsgId, updates: { text: finalMsg } } });\r\n\r\n // Route based on result\r\n const nextStepId = resolveAsyncRoute(step, result);\r\n if (nextStepId) {\r\n await delay(600);\r\n processFlowStepRef.current(nextStepId);\r\n }\r\n } catch {\r\n dispatch({\r\n type: 'UPDATE_MESSAGE',\r\n payload: { id: statusMsgId, updates: { text: step.asyncAction.errorMessage ?? '❌ Something went wrong.' } },\r\n });\r\n if (step.asyncAction.onError) {\r\n await delay(600);\r\n processFlowStepRef.current(step.asyncAction.onError);\r\n }\r\n }\r\n return; // async action handles routing — don't auto-advance\r\n }\r\n }\r\n\r\n // If step has a custom component, wait for onComplete — don't auto-advance\r\n if (step.component && propsRef.current.components?.[step.component]) {\r\n return;\r\n }\r\n\r\n // Auto-advance if no user input required\r\n if (!step.quickReplies && !step.form && !step.input && step.next) {\r\n await delay(300);\r\n processFlowStepRef.current(step.next);\r\n }\r\n };\r\n\r\n /** Determine next step from async action result */\r\n function resolveAsyncRoute(\r\n step: { asyncAction?: { onSuccess?: string; onError?: string; routes?: Record<string, string> }; next?: string },\r\n result: FlowActionResult,\r\n ): string | undefined {\r\n // 1. Explicit next from result\r\n if (result.next) return result.next;\r\n // 2. Routes map\r\n if (step.asyncAction?.routes?.[result.status]) return step.asyncAction.routes[result.status];\r\n // 3. Success/error defaults\r\n if (result.status === 'success' && step.asyncAction?.onSuccess) return step.asyncAction.onSuccess;\r\n if (result.status === 'error' && step.asyncAction?.onError) return step.asyncAction.onError;\r\n // 4. Fallback\r\n return step.next;\r\n }\r\n\r\n const processFlowStep = useCallback(\r\n (stepId: string) => processFlowStepRef.current(stepId),\r\n [],\r\n );\r\n\r\n /** Go back to the previous step */\r\n const goBack = useCallback(() => {\r\n const engine = flowRef.current;\r\n if (!engine || !engine.canGoBack()) {\r\n addSystemMessage('There is no previous step to go back to.');\r\n return;\r\n }\r\n dispatch({ type: 'CLEAR_QUICK_REPLIES' });\r\n const prevStepId = engine.popHistory();\r\n if (prevStepId) {\r\n processFlowStep(prevStepId);\r\n } else {\r\n addSystemMessage('There is no previous step to go back to.');\r\n }\r\n }, [dispatch, processFlowStep, addSystemMessage]);\r\n\r\n /** Restart the entire conversation */\r\n const restartSession = useCallback(() => {\r\n const engine = flowRef.current;\r\n if (engine) {\r\n engine.reset();\r\n }\r\n flowStartedRef.current = false;\r\n dispatch({ type: 'RESET_CHAT' });\r\n // Re-start the flow after reset\r\n if (engine) {\r\n flowStartedRef.current = true;\r\n processFlowStep(engine.getStartStepId());\r\n }\r\n }, [dispatch, processFlowStep]);\r\n\r\n /** Handle slash commands. Returns true if the text was a command. */\r\n const handleCommandRef = useRef<(text: string) => boolean>(() => false);\r\n handleCommandRef.current = (text: string): boolean => {\r\n const cmd = text.trim().toLowerCase();\r\n if (!cmd.startsWith('/')) return false;\r\n\r\n switch (cmd) {\r\n case '/help': {\r\n const lines = Object.entries(COMMANDS)\r\n .map(([k, v]) => `**${k}** — ${v}`)\r\n .join('\\n');\r\n addSystemMessage(`Available commands:\\n${lines}`);\r\n return true;\r\n }\r\n case '/cancel':\r\n case '/back': {\r\n goBack();\r\n return true;\r\n }\r\n case '/restart': {\r\n restartSession();\r\n return true;\r\n }\r\n default:\r\n addSystemMessage(`Unknown command: ${cmd}. Type /help for available commands.`);\r\n return true;\r\n }\r\n };\r\n\r\n /** Handle completion from a custom component rendered in a step */\r\n const handleComponentComplete = useCallback(\r\n (result?: FlowActionResult) => {\r\n const engine = flowRef.current;\r\n const currentStepId = stateRef.current.currentStepId;\r\n if (!engine || !currentStepId) return;\r\n\r\n const step = engine.getStep(currentStepId);\r\n if (!step) return;\r\n\r\n // Merge result data\r\n if (result?.data) {\r\n engine.mergeData(result.data);\r\n dispatch({ type: 'SET_DATA', payload: result.data });\r\n }\r\n\r\n // Show optional message\r\n if (result?.message) {\r\n dispatch({\r\n type: 'ADD_MESSAGE',\r\n payload: { id: uid(), sender: 'bot', text: result.message, timestamp: Date.now() },\r\n });\r\n }\r\n\r\n // Determine next step\r\n const nextStepId = result?.next ?? step.next;\r\n if (nextStepId) {\r\n processFlowStep(nextStepId);\r\n } else {\r\n propsRef.current.callbacks?.onFlowEnd?.(engine.getData());\r\n dispatch({ type: 'SET_STEP', payload: null });\r\n }\r\n },\r\n [dispatch, processFlowStep],\r\n );\r\n\r\n const sendMessage = useCallback(\r\n async (text: string) => {\r\n // Check for slash commands first\r\n if (handleCommandRef.current(text)) return;\r\n\r\n const msg: ChatMessage = {\r\n id: uid(),\r\n sender: 'user',\r\n text,\r\n timestamp: Date.now(),\r\n };\r\n\r\n // Let plugins transform the message before dispatching\r\n const finalMsg = pluginManager ? await pluginManager.onMessage(msg) : msg;\r\n dispatch({ type: 'ADD_MESSAGE', payload: finalMsg });\r\n propsRef.current.callbacks?.onMessageSend?.(finalMsg);\r\n propsRef.current.callbacks?.onSubmit?.({ message: finalMsg.text });\r\n\r\n const currentStepId = stateRef.current.currentStepId;\r\n const typingMs = propsRef.current.typingDelay ?? 0;\r\n\r\n // ── Active flow step ─────────────────────────────────────\r\n if (flowRef.current && currentStepId) {\r\n const step = flowRef.current.getStep(currentStepId);\r\n if (step) {\r\n // Block text input during async action or component steps\r\n if (step.asyncAction || step.component) {\r\n addBotMessage(\"Please wait, I'm still processing. You can type /back to go back.\");\r\n return;\r\n }\r\n // If this step has quick replies, try to match user text\r\n if (flowRef.current.stepExpectsQuickReply(step)) {\r\n const matched = flowRef.current.matchQuickReply(step, text);\r\n if (matched) {\r\n dispatch({ type: 'CLEAR_QUICK_REPLIES' });\r\n flowRef.current.setData(step.id, matched.value);\r\n const nextId = flowRef.current.resolveNext(step, matched.value);\r\n if (nextId) {\r\n processFlowStep(nextId);\r\n } else {\r\n propsRef.current.callbacks?.onFlowEnd?.(flowRef.current.getData());\r\n dispatch({ type: 'SET_STEP', payload: null });\r\n }\r\n } else {\r\n addBotMessage(\r\n \"I didn't quite get that. Please choose one of the options below:\",\r\n { quickReplies: step.quickReplies },\r\n );\r\n }\r\n } else if (flowRef.current.stepExpectsForm(step)) {\r\n addBotMessage(\"Please fill out the form above to continue.\");\r\n } else if (step.input) {\r\n // ── Input step with validation ──\r\n const result = validateInput(text, step.input);\r\n if (!result.valid) {\r\n addBotMessage(result.error ?? 'Invalid input. Please try again.');\r\n return;\r\n }\r\n flowRef.current.setData(step.id, result.value);\r\n const nextId = flowRef.current.resolveNext(step, result.value);\r\n if (nextId) {\r\n processFlowStep(nextId);\r\n } else {\r\n addBotMessage(\"Thanks for your message! Our team will get back to you soon. \\u{1F64C}\");\r\n propsRef.current.callbacks?.onFlowEnd?.(flowRef.current.getData());\r\n dispatch({ type: 'SET_STEP', payload: null });\r\n }\r\n } else {\r\n // Normal text input step\r\n flowRef.current.setData(step.id, text);\r\n const nextId = flowRef.current.resolveNext(step, text);\r\n if (nextId) {\r\n processFlowStep(nextId);\r\n } else {\r\n addBotMessage(\"Thanks for your message! Our team will get back to you soon. \\u{1F64C}\");\r\n propsRef.current.callbacks?.onFlowEnd?.(flowRef.current.getData());\r\n dispatch({ type: 'SET_STEP', payload: null });\r\n }\r\n }\r\n return;\r\n }\r\n }\r\n\r\n // ── No active flow step — try keyword / greeting / fallback ──\r\n\r\n // Build runtime keyword list (user keywords + greeting shortcut)\r\n const keywords: KeywordRoute[] = [...(propsRef.current.keywords ?? [])];\r\n if (propsRef.current.greetingResponse) {\r\n keywords.push({\r\n patterns: GREETING_PATTERNS,\r\n response: propsRef.current.greetingResponse,\r\n matchType: 'exact',\r\n priority: -1,\r\n });\r\n }\r\n\r\n if (keywords.length > 0) {\r\n const match = findKeywordMatch(text.trim(), keywords);\r\n if (match) {\r\n // Jump to flow step if route specifies `next`\r\n if (match.next && flowRef.current) {\r\n if (typingMs > 0) await delay(typingMs);\r\n processFlowStep(match.next);\r\n return;\r\n }\r\n // Send response message\r\n if (match.response) {\r\n if (typingMs > 0) {\r\n dispatch({ type: 'SET_TYPING', payload: true });\r\n await delay(typingMs);\r\n dispatch({ type: 'SET_TYPING', payload: false });\r\n }\r\n await addBotMessage(match.response);\r\n return;\r\n }\r\n }\r\n }\r\n\r\n // Fallback\r\n const fb = propsRef.current.fallbackMessage;\r\n if (fb) {\r\n const fbText = typeof fb === 'function' ? fb(text) : fb;\r\n if (fbText) {\r\n if (typingMs > 0) {\r\n dispatch({ type: 'SET_TYPING', payload: true });\r\n await delay(typingMs);\r\n dispatch({ type: 'SET_TYPING', payload: false });\r\n }\r\n await addBotMessage(fbText);\r\n return;\r\n }\r\n }\r\n\r\n // Nothing handled it — fire unhandled callback\r\n propsRef.current.callbacks?.onUnhandledMessage?.(text, { currentStepId });\r\n },\r\n [dispatch, addBotMessage, processFlowStep, pluginManager],\r\n );\r\n\r\n const startFlow = useCallback(() => {\r\n const engine = flowRef.current;\r\n if (!engine || flowStartedRef.current) return;\r\n flowStartedRef.current = true;\r\n processFlowStep(engine.getStartStepId());\r\n }, [processFlowStep]);\r\n\r\n // Auto-start flow when all conditions are met\r\n useEffect(() => {\r\n if (\r\n props.flow &&\r\n !state.showWelcome &&\r\n state.isLoggedIn &&\r\n !flowStartedRef.current\r\n ) {\r\n startFlow();\r\n }\r\n }, [props.flow, state.showWelcome, state.isLoggedIn, startFlow]);\r\n\r\n const handleQuickReply = useCallback(\r\n (value: string, label: string) => {\r\n dispatch({ type: 'CLEAR_QUICK_REPLIES' });\r\n // Add user message\r\n const msg: ChatMessage = {\r\n id: uid(),\r\n sender: 'user',\r\n text: label,\r\n timestamp: Date.now(),\r\n };\r\n dispatch({ type: 'ADD_MESSAGE', payload: msg });\r\n propsRef.current.callbacks?.onQuickReply?.(value, label);\r\n\r\n // Continue flow\r\n const currentStepId = stateRef.current.currentStepId;\r\n if (flowRef.current && currentStepId) {\r\n const step = flowRef.current.getStep(currentStepId);\r\n if (step) {\r\n flowRef.current.setData(step.id, value);\r\n const nextId = flowRef.current.resolveNext(step, value);\r\n if (nextId) {\r\n processFlowStep(nextId);\r\n } else {\r\n propsRef.current.callbacks?.onFlowEnd?.(flowRef.current.getData());\r\n dispatch({ type: 'SET_STEP', payload: null });\r\n }\r\n }\r\n }\r\n },\r\n [dispatch, processFlowStep],\r\n );\r\n\r\n const handleFormSubmit = useCallback(\r\n async (formId: string, data: Record<string, unknown>) => {\r\n dispatch({ type: 'SET_DATA', payload: data });\r\n if (flowRef.current) {\r\n flowRef.current.mergeData(data);\r\n }\r\n\r\n // Summary message\r\n const summaryLines = Object.entries(data)\r\n .filter(([, v]) => v !== undefined && v !== '')\r\n .map(([k, v]) => `${k}: ${String(v)}`)\r\n .join('\\n');\r\n const msg: ChatMessage = {\r\n id: uid(),\r\n sender: 'user',\r\n text: summaryLines,\r\n formData: data,\r\n timestamp: Date.now(),\r\n };\r\n dispatch({ type: 'ADD_MESSAGE', payload: msg });\r\n\r\n await propsRef.current.callbacks?.onFormSubmit?.(formId, data);\r\n\r\n // Advance flow\r\n const currentStepId = stateRef.current.currentStepId;\r\n if (flowRef.current && currentStepId) {\r\n const step = flowRef.current.getStep(currentStepId);\r\n if (step) {\r\n const nextId = flowRef.current.resolveNext(step);\r\n if (nextId) {\r\n processFlowStep(nextId);\r\n } else {\r\n propsRef.current.callbacks?.onFlowEnd?.(flowRef.current.getData());\r\n dispatch({ type: 'SET_STEP', payload: null });\r\n }\r\n }\r\n }\r\n },\r\n [dispatch, processFlowStep],\r\n );\r\n\r\n const handleLogin = useCallback(\r\n async (data: Record<string, unknown>) => {\r\n await propsRef.current.callbacks?.onLogin?.(data);\r\n dispatch({ type: 'SET_LOGGED_IN', payload: true });\r\n },\r\n [dispatch],\r\n );\r\n\r\n const toggleChat = useCallback(() => {\r\n const willOpen = !stateRef.current.isOpen;\r\n dispatch({ type: 'TOGGLE_OPEN' });\r\n if (willOpen) {\r\n propsRef.current.callbacks?.onOpen?.();\r\n } else {\r\n propsRef.current.callbacks?.onClose?.();\r\n }\r\n }, [dispatch]);\r\n\r\n const dismissWelcome = useCallback(() => {\r\n dispatch({ type: 'DISMISS_WELCOME' });\r\n }, [dispatch]);\r\n\r\n return {\r\n state,\r\n sendMessage,\r\n addBotMessage,\r\n handleQuickReply,\r\n handleFormSubmit,\r\n handleLogin,\r\n toggleChat,\r\n dismissWelcome,\r\n startFlow,\r\n processFlowStep,\r\n goBack,\r\n restartSession,\r\n handleComponentComplete,\r\n };\r\n}\r\n","import React, { useCallback, useMemo } from 'react';\r\nimport type { CSSProperties } from 'react';\r\nimport type { ChatStyles } from '../styles/theme';\r\nimport type { ChatRenderContext } from '../types/config';\r\nimport { ChatHeader } from './ChatHeader';\r\nimport { WelcomeScreen } from './WelcomeScreen';\r\nimport { LoginScreen } from './LoginScreen';\r\nimport { MessageList } from './MessageList';\r\nimport { ChatInput } from './ChatInput';\r\nimport { Branding } from './Branding';\r\nimport { useChat } from '../hooks/useChat';\r\nimport { useChatContext } from '../context/ChatContext';\r\nimport { resolveTheme } from '../styles/theme';\r\nimport { uid } from '../utils/helpers';\r\nimport type { MessageAttachment } from '../types/message';\r\n\r\ninterface ChatWindowProps {\r\n styles: ChatStyles;\r\n position: 'bottom-right' | 'bottom-left';\r\n zIndex?: number;\r\n hidden?: boolean;\r\n}\r\n\r\nexport const ChatWindow: React.FC<ChatWindowProps> = ({ styles, position, zIndex, hidden }) => {\r\n const { props, dispatch } = useChatContext();\r\n const theme = resolveTheme(props.theme);\r\n const isDark = theme.mode === 'dark';\r\n const {\r\n state,\r\n sendMessage,\r\n handleQuickReply,\r\n handleFormSubmit,\r\n handleLogin,\r\n toggleChat,\r\n dismissWelcome,\r\n restartSession,\r\n handleComponentComplete,\r\n } = useChat();\r\n\r\n const posStyle: CSSProperties =\r\n position === 'bottom-left'\r\n ? { bottom: '96px', left: '24px' }\r\n : { bottom: '96px', right: '24px' };\r\n\r\n const handleSendWithFiles = useCallback(\r\n (text: string, files?: File[]) => {\r\n if (files && files.length > 0) {\r\n const attachments: MessageAttachment[] = files.map((f) => ({\r\n name: f.name,\r\n url: URL.createObjectURL(f),\r\n type: f.type,\r\n size: f.size,\r\n }));\r\n if (text) {\r\n dispatch({\r\n type: 'ADD_MESSAGE',\r\n payload: {\r\n id: uid(),\r\n sender: 'user',\r\n text,\r\n timestamp: Date.now(),\r\n attachments,\r\n },\r\n });\r\n sendMessage(text);\r\n } else {\r\n dispatch({\r\n type: 'ADD_MESSAGE',\r\n payload: {\r\n id: uid(),\r\n sender: 'user',\r\n timestamp: Date.now(),\r\n attachments,\r\n },\r\n });\r\n }\r\n props.callbacks?.onFileUpload?.(files);\r\n } else if (text) {\r\n sendMessage(text);\r\n }\r\n },\r\n [sendMessage, dispatch, props.callbacks],\r\n );\r\n\r\n // Build render context for custom components\r\n const renderCtx: ChatRenderContext = useMemo(\r\n () => ({\r\n currentStepId: state.currentStepId,\r\n isOpen: state.isOpen,\r\n messages: state.messages,\r\n collectedData: state.collectedData,\r\n toggleChat,\r\n restartSession,\r\n sendMessage,\r\n }),\r\n [state.currentStepId, state.isOpen, state.messages, state.collectedData, toggleChat, restartSession, sendMessage],\r\n );\r\n\r\n // Default header element\r\n const defaultHeader = (\r\n <ChatHeader\r\n config={props.header ?? { title: 'Chat with us' }}\r\n styles={styles}\r\n onClose={toggleChat}\r\n onRestart={restartSession}\r\n logo={props.branding?.logo}\r\n logoWidth={props.branding?.logoWidth}\r\n />\r\n );\r\n\r\n // Default input element\r\n const defaultInput = (\r\n <ChatInput\r\n onSend={handleSendWithFiles}\r\n placeholder={props.inputPlaceholder}\r\n primaryColor={theme.primaryColor}\r\n isDark={isDark}\r\n enableEmoji={props.enableEmoji}\r\n fileUpload={props.fileUpload}\r\n onFileUpload={props.callbacks?.onFileUpload}\r\n />\r\n );\r\n\r\n if (hidden) {\r\n // Keep component mounted (hooks alive) but invisible\r\n return <div style={{ display: 'none' }} />;\r\n }\r\n\r\n return (\r\n <div\r\n style={{\r\n ...styles.window,\r\n ...posStyle,\r\n ...(zIndex != null ? { zIndex } : {}),\r\n }}\r\n >\r\n {props.renderHeader ? props.renderHeader(renderCtx, defaultHeader) : defaultHeader}\r\n\r\n {/* Welcome Screen */}\r\n {state.showWelcome && props.welcomeScreen ? (\r\n <WelcomeScreen\r\n content={props.welcomeScreen}\r\n onDismiss={dismissWelcome}\r\n primaryColor={theme.primaryColor}\r\n />\r\n ) : /* Login Screen */\r\n !state.isLoggedIn && props.loginForm ? (\r\n <LoginScreen\r\n config={props.loginForm}\r\n onLogin={handleLogin}\r\n primaryColor={theme.primaryColor}\r\n renderFormField={props.renderFormField}\r\n />\r\n ) : (\r\n /* Chat Area */\r\n <>\r\n <MessageList\r\n messages={state.messages}\r\n isTyping={state.isTyping}\r\n styles={styles}\r\n primaryColor={theme.primaryColor}\r\n onQuickReply={handleQuickReply}\r\n onFormSubmit={handleFormSubmit}\r\n components={props.components}\r\n onComponentComplete={handleComponentComplete}\r\n collectedData={state.collectedData}\r\n currentStepId={state.currentStepId}\r\n renderFormField={props.renderFormField}\r\n />\r\n <div style={styles.inputArea}>\r\n {props.renderInput ? props.renderInput(renderCtx, defaultInput) : defaultInput}\r\n </div>\r\n {props.branding && (\r\n <Branding config={props.branding} primaryColor={theme.primaryColor} />\r\n )}\r\n </>\r\n )}\r\n </div>\r\n );\r\n};\r\n","import type { ChatPlugin, PluginContext, ChatPluginEvent } from '../types/plugin';\r\nimport type { ChatMessage } from '../types/message';\r\n\r\n/**\r\n * PluginManager — Manages plugin lifecycle (Open/Closed Principle)\r\n * Core is closed for modification, open for extension via plugins.\r\n */\r\nexport class PluginManager {\r\n private plugins: ChatPlugin[] = [];\r\n private context: PluginContext | null = null;\r\n private eventHandlers = new Map<string, Set<(...args: unknown[]) => void>>();\r\n\r\n register(plugins: ChatPlugin[]): void {\r\n this.plugins = [...plugins];\r\n }\r\n\r\n setContext(ctx: Omit<PluginContext, 'on' | 'emit'>): void {\r\n this.context = {\r\n ...ctx,\r\n on: (event, handler) => this.on(event, handler),\r\n emit: (event, ...args) => this.emit(event, ...args),\r\n };\r\n }\r\n\r\n private on(event: string, handler: (...args: unknown[]) => void): void {\r\n if (!this.eventHandlers.has(event)) {\r\n this.eventHandlers.set(event, new Set());\r\n }\r\n this.eventHandlers.get(event)!.add(handler);\r\n }\r\n\r\n private emit(event: string, ...args: unknown[]): void {\r\n const handlers = this.eventHandlers.get(event);\r\n if (handlers) {\r\n handlers.forEach((handler) => handler(...args));\r\n }\r\n }\r\n\r\n async init(): Promise<void> {\r\n if (!this.context) return;\r\n for (const plugin of this.plugins) {\r\n try {\r\n await plugin.onInit?.(this.context);\r\n } catch (err) {\r\n console.error(`[Plugin:${plugin.name}] onInit error:`, err);\r\n }\r\n }\r\n }\r\n\r\n async onMessage(message: ChatMessage): Promise<ChatMessage> {\r\n if (!this.context) return message;\r\n let msg = message;\r\n for (const plugin of this.plugins) {\r\n try {\r\n const result = await plugin.onMessage?.(msg, this.context);\r\n if (result && typeof result === 'object' && 'id' in result) {\r\n msg = result;\r\n }\r\n } catch (err) {\r\n console.error(`[Plugin:${plugin.name}] onMessage error:`, err);\r\n }\r\n }\r\n this.dispatchEvent({ type: 'message', payload: msg, timestamp: Date.now() });\r\n return msg;\r\n }\r\n\r\n async onSubmit(data: Record<string, unknown>): Promise<void> {\r\n if (!this.context) return;\r\n for (const plugin of this.plugins) {\r\n try {\r\n await plugin.onSubmit?.(data, this.context);\r\n } catch (err) {\r\n console.error(`[Plugin:${plugin.name}] onSubmit error:`, err);\r\n }\r\n }\r\n this.dispatchEvent({ type: 'submit', payload: data, timestamp: Date.now() });\r\n }\r\n\r\n async destroy(): Promise<void> {\r\n if (!this.context) return;\r\n for (const plugin of this.plugins) {\r\n try {\r\n await plugin.onDestroy?.(this.context);\r\n } catch (err) {\r\n console.error(`[Plugin:${plugin.name}] onDestroy error:`, err);\r\n }\r\n }\r\n this.eventHandlers.clear();\r\n this.plugins = [];\r\n }\r\n\r\n private dispatchEvent(event: ChatPluginEvent): void {\r\n if (!this.context) return;\r\n for (const plugin of this.plugins) {\r\n try {\r\n plugin.onEvent?.(event, this.context);\r\n } catch (err) {\r\n console.error(`[Plugin:${plugin.name}] onEvent error:`, err);\r\n }\r\n }\r\n }\r\n}\r\n","import React, { useReducer, useEffect, useRef, useCallback } from 'react';\r\nimport type { ChatBotProps } from '../types';\r\nimport { ChatContext, chatReducer, initialState } from '../context/ChatContext';\r\nimport { resolveTheme, buildStyles, buildCSSVariables } from '../styles/theme';\r\nimport { Launcher } from './Launcher';\r\nimport { ChatWindow } from './ChatWindow';\r\nimport { PluginManager } from '../core/PluginManager';\r\nimport { uid } from '../utils/helpers';\r\n\r\nconst GLOBAL_STYLES = `\r\n@import url('https://fonts.googleapis.com/css2?family=Inter:wght@400;500;600;700&display=swap');\r\n\r\n@keyframes cb-window-enter {\r\n 0% { opacity: 0; transform: translateY(16px) scale(0.96); }\r\n 100% { opacity: 1; transform: translateY(0) scale(1); }\r\n}\r\n\r\n@keyframes cb-launcher-pulse {\r\n 0%, 100% { box-shadow: 0 6px 24px rgba(108, 92, 231, 0.4), 0 2px 8px rgba(0,0,0,0.1); }\r\n 50% { box-shadow: 0 8px 32px rgba(108, 92, 231, 0.55), 0 4px 12px rgba(0,0,0,0.15); }\r\n}\r\n\r\n@keyframes cb-fade-in {\r\n 0% { opacity: 0; transform: translateY(6px); }\r\n 100% { opacity: 1; transform: translateY(0); }\r\n}\r\n\r\n@keyframes cb-typing-bounce {\r\n 0%, 80%, 100% { transform: scale(0.6); opacity: 0.3; }\r\n 40% { transform: scale(1); opacity: 1; }\r\n}\r\n\r\n@keyframes cb-slide-up {\r\n 0% { opacity: 0; transform: translateY(10px); }\r\n 100% { opacity: 1; transform: translateY(0); }\r\n}\r\n\r\n.cb-scrollbar::-webkit-scrollbar {\r\n width: 5px;\r\n}\r\n.cb-scrollbar::-webkit-scrollbar-track {\r\n background: transparent;\r\n}\r\n.cb-scrollbar::-webkit-scrollbar-thumb {\r\n background: rgba(108, 92, 231, 0.2);\r\n border-radius: 10px;\r\n}\r\n.cb-scrollbar::-webkit-scrollbar-thumb:hover {\r\n background: rgba(108, 92, 231, 0.35);\r\n}\r\n`;\r\n\r\n// Inject styles globally once per document, not per component instance\r\nlet globalStyleInjected = false;\r\nfunction ensureGlobalStyles() {\r\n if (globalStyleInjected) return;\r\n if (typeof document === 'undefined') return;\r\n if (document.querySelector('style[data-chatbot-styles]')) {\r\n globalStyleInjected = true;\r\n return;\r\n }\r\n const style = document.createElement('style');\r\n style.setAttribute('data-chatbot-styles', '');\r\n style.textContent = GLOBAL_STYLES;\r\n document.head.appendChild(style);\r\n globalStyleInjected = true;\r\n}\r\n\r\nexport const ChatBot: React.FC<ChatBotProps> = (props) => {\r\n const [state, dispatch] = useReducer(chatReducer, props, initialState);\r\n const theme = resolveTheme(props.theme);\r\n const styles = buildStyles(theme, props.style);\r\n const cssVars = buildCSSVariables(theme);\r\n const position = props.position ?? 'bottom-right';\r\n const showLauncher = props.showLauncher !== false;\r\n const pluginManagerRef = useRef<PluginManager | null>(null);\r\n\r\n // Use refs so plugin context always reads fresh state\r\n const stateRef = useRef(state);\r\n stateRef.current = state;\r\n\r\n // Inject global styles once\r\n useEffect(() => {\r\n ensureGlobalStyles();\r\n }, []);\r\n\r\n // Initialize plugins\r\n useEffect(() => {\r\n if (props.plugins && props.plugins.length > 0) {\r\n const pm = new PluginManager();\r\n pm.register(props.plugins);\r\n pm.setContext({\r\n sendMessage: (text) => {\r\n dispatch({\r\n type: 'ADD_MESSAGE',\r\n payload: { id: uid(), sender: 'user', text, timestamp: Date.now() },\r\n });\r\n },\r\n addBotMessage: (text) => {\r\n dispatch({\r\n type: 'ADD_MESSAGE',\r\n payload: { id: uid(), sender: 'bot', text, timestamp: Date.now() },\r\n });\r\n },\r\n getMessages: () => stateRef.current.messages,\r\n getData: () => stateRef.current.collectedData,\r\n setData: (key, value) => dispatch({ type: 'SET_DATA', payload: { [key]: value } }),\r\n });\r\n pm.init();\r\n pluginManagerRef.current = pm;\r\n\r\n return () => {\r\n pm.destroy();\r\n };\r\n }\r\n }, [props.plugins]);\r\n\r\n const handleToggle = useCallback(() => {\r\n const willOpen = !state.isOpen;\r\n dispatch({ type: 'TOGGLE_OPEN' });\r\n if (willOpen) props.callbacks?.onOpen?.();\r\n else props.callbacks?.onClose?.();\r\n }, [state.isOpen, props.callbacks]);\r\n\r\n return (\r\n <ChatContext.Provider value={{ state, dispatch, props, pluginManager: pluginManagerRef.current }}>\r\n <div style={{ ...styles.root, ...cssVars as React.CSSProperties }} className={props.className}>\r\n <ChatWindow styles={styles} position={position} zIndex={props.zIndex} hidden={!state.isOpen} />\r\n {showLauncher && (\r\n <Launcher\r\n onClick={handleToggle}\r\n isOpen={state.isOpen}\r\n position={position}\r\n styles={styles}\r\n icon={props.launcherIcon}\r\n closeIcon={props.closeIcon}\r\n zIndex={props.zIndex}\r\n />\r\n )}\r\n </div>\r\n </ChatContext.Provider>\r\n );\r\n};\r\n","import type { ChatPlugin } from '../types/plugin';\r\n\r\n/**\r\n * Analytics Plugin — tracks message counts, form completions, drop-offs\r\n */\r\nexport function analyticsPlugin(options?: {\r\n onTrack?: (event: string, data?: unknown) => void;\r\n}): ChatPlugin {\r\n let messageCount = 0;\r\n let formSubmissions = 0;\r\n\r\n return {\r\n name: 'analytics',\r\n\r\n onInit(ctx) {\r\n messageCount = 0;\r\n formSubmissions = 0;\r\n options?.onTrack?.('chatbot:init');\r\n },\r\n\r\n onMessage(message, ctx) {\r\n messageCount++;\r\n options?.onTrack?.('chatbot:message', {\r\n sender: message.sender,\r\n messageCount,\r\n });\r\n },\r\n\r\n onSubmit(data, ctx) {\r\n formSubmissions++;\r\n options?.onTrack?.('chatbot:submit', {\r\n formSubmissions,\r\n fields: Object.keys(data),\r\n });\r\n },\r\n\r\n onDestroy() {\r\n options?.onTrack?.('chatbot:destroy', {\r\n totalMessages: messageCount,\r\n totalFormSubmissions: formSubmissions,\r\n });\r\n },\r\n };\r\n}\r\n","import type { ChatPlugin } from '../types/plugin';\r\n\r\n/**\r\n * Webhook Plugin — sends messages/submissions to an external endpoint\r\n */\r\nexport function webhookPlugin(options: {\r\n url: string;\r\n headers?: Record<string, string>;\r\n events?: ('message' | 'submit' | 'init' | 'destroy')[];\r\n}): ChatPlugin {\r\n const events = options.events ?? ['message', 'submit'];\r\n\r\n const send = async (type: string, payload: unknown) => {\r\n try {\r\n await fetch(options.url, {\r\n method: 'POST',\r\n headers: {\r\n 'Content-Type': 'application/json',\r\n ...options.headers,\r\n },\r\n body: JSON.stringify({ type, payload, timestamp: Date.now() }),\r\n });\r\n } catch (err) {\r\n console.error(`[webhook] Failed to send ${type}:`, err);\r\n }\r\n };\r\n\r\n return {\r\n name: 'webhook',\r\n\r\n async onInit() {\r\n if (events.includes('init')) {\r\n await send('init', {});\r\n }\r\n },\r\n\r\n async onMessage(message) {\r\n if (events.includes('message')) {\r\n await send('message', message);\r\n }\r\n },\r\n\r\n async onSubmit(data) {\r\n if (events.includes('submit')) {\r\n await send('submit', data);\r\n }\r\n },\r\n\r\n async onDestroy() {\r\n if (events.includes('destroy')) {\r\n await send('destroy', {});\r\n }\r\n },\r\n };\r\n}\r\n","import type { ChatPlugin } from '../types/plugin';\r\n\r\n/**\r\n * Persistence Plugin — saves/restores chat history via localStorage\r\n */\r\nexport function persistencePlugin(options?: {\r\n storageKey?: string;\r\n storage?: 'local' | 'session';\r\n}): ChatPlugin {\r\n const key = options?.storageKey ?? 'chatbot_history';\r\n const store = options?.storage === 'session' ? sessionStorage : localStorage;\r\n\r\n return {\r\n name: 'persistence',\r\n\r\n onInit(ctx) {\r\n try {\r\n const saved = store.getItem(key);\r\n if (saved) {\r\n const messages = JSON.parse(saved);\r\n if (Array.isArray(messages)) {\r\n messages.forEach((msg) => {\r\n if (msg.sender === 'bot') {\r\n ctx.addBotMessage(msg.text);\r\n }\r\n // Skip non-bot messages — re-adding user messages as bot bubbles is incorrect\r\n });\r\n }\r\n }\r\n } catch {\r\n // ignore parse errors\r\n }\r\n },\r\n\r\n onMessage(message, ctx) {\r\n try {\r\n const messages = ctx.getMessages();\r\n store.setItem(key, JSON.stringify(messages.slice(-50)));\r\n } catch {\r\n // storage full or unavailable\r\n }\r\n },\r\n\r\n onDestroy() {\r\n // Optionally clear on destroy\r\n },\r\n };\r\n}\r\n"],"mappings":"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"}