@enjoys/react-chatbot-plugin 1.2.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.
- package/README.md +84 -436
- package/dist/index.cjs +5 -6
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.ts +116 -1
- package/dist/index.mjs +5 -2684
- package/dist/index.mjs.map +1 -1
- package/package.json +33 -3
package/dist/index.mjs.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.mjs","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';\r\n\r\ninterface IconProps {\r\n size?: number;\r\n color?: string;\r\n className?: string;\r\n}\r\n\r\nexport const SendIcon: React.FC<IconProps> = ({ size = 18, color = 'currentColor' }) => (\r\n <svg width={size} height={size} viewBox=\"0 0 24 24\" fill={color}>\r\n <path d=\"M2.01 21L23 12 2.01 3 2 10l15 2-15 2z\" />\r\n </svg>\r\n);\r\n\r\nexport const ChatBubbleIcon: React.FC<IconProps> = ({ size = 28, color = 'currentColor' }) => (\r\n <svg width={size} height={size} viewBox=\"0 0 24 24\" fill=\"none\" stroke={color} strokeWidth=\"2\" strokeLinecap=\"round\" strokeLinejoin=\"round\">\r\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\" />\r\n </svg>\r\n);\r\n\r\nexport const CloseIcon: React.FC<IconProps> = ({ size = 20, color = 'currentColor' }) => (\r\n <svg width={size} height={size} viewBox=\"0 0 24 24\" fill=\"none\" stroke={color} strokeWidth=\"2\" strokeLinecap=\"round\" strokeLinejoin=\"round\">\r\n <line x1=\"18\" y1=\"6\" x2=\"6\" y2=\"18\" />\r\n <line x1=\"6\" y1=\"6\" x2=\"18\" y2=\"18\" />\r\n </svg>\r\n);\r\n\r\nexport const MinimizeIcon: React.FC<IconProps> = ({ size = 20, color = 'currentColor' }) => (\r\n <svg width={size} height={size} viewBox=\"0 0 24 24\" fill=\"none\" stroke={color} strokeWidth=\"2\" strokeLinecap=\"round\" strokeLinejoin=\"round\">\r\n <line x1=\"5\" y1=\"12\" x2=\"19\" y2=\"12\" />\r\n </svg>\r\n);\r\n\r\nexport const EmojiIcon: React.FC<IconProps> = ({ size = 20, color = 'currentColor' }) => (\r\n <svg width={size} height={size} viewBox=\"0 0 24 24\" fill=\"none\" stroke={color} strokeWidth=\"2\" strokeLinecap=\"round\" strokeLinejoin=\"round\">\r\n <circle cx=\"12\" cy=\"12\" r=\"10\" />\r\n <path d=\"M8 14s1.5 2 4 2 4-2 4-2\" />\r\n <line x1=\"9\" y1=\"9\" x2=\"9.01\" y2=\"9\" />\r\n <line x1=\"15\" y1=\"9\" x2=\"15.01\" y2=\"9\" />\r\n </svg>\r\n);\r\n\r\nexport const AttachmentIcon: React.FC<IconProps> = ({ size = 20, color = 'currentColor' }) => (\r\n <svg width={size} height={size} viewBox=\"0 0 24 24\" fill=\"none\" stroke={color} strokeWidth=\"2\" strokeLinecap=\"round\" strokeLinejoin=\"round\">\r\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\" />\r\n </svg>\r\n);\r\n\r\nexport const FileIcon: React.FC<IconProps> = ({ size = 16, color = 'currentColor' }) => (\r\n <svg width={size} height={size} viewBox=\"0 0 24 24\" fill=\"none\" stroke={color} strokeWidth=\"2\" strokeLinecap=\"round\" strokeLinejoin=\"round\">\r\n <path d=\"M14 2H6a2 2 0 00-2 2v16a2 2 0 002 2h12a2 2 0 002-2V8z\" />\r\n <polyline points=\"14 2 14 8 20 8\" />\r\n </svg>\r\n);\r\n\r\nexport const ImageIcon: React.FC<IconProps> = ({ size = 16, color = 'currentColor' }) => (\r\n <svg width={size} height={size} viewBox=\"0 0 24 24\" fill=\"none\" stroke={color} strokeWidth=\"2\" strokeLinecap=\"round\" strokeLinejoin=\"round\">\r\n <rect x=\"3\" y=\"3\" width=\"18\" height=\"18\" rx=\"2\" ry=\"2\" />\r\n <circle cx=\"8.5\" cy=\"8.5\" r=\"1.5\" />\r\n <polyline points=\"21 15 16 10 5 21\" />\r\n </svg>\r\n);\r\n\r\nexport const RemoveIcon: React.FC<IconProps> = ({ size = 14, color = 'currentColor' }) => (\r\n <svg width={size} height={size} viewBox=\"0 0 24 24\" fill=\"none\" stroke={color} strokeWidth=\"2\" strokeLinecap=\"round\" strokeLinejoin=\"round\">\r\n <circle cx=\"12\" cy=\"12\" r=\"10\" />\r\n <line x1=\"15\" y1=\"9\" x2=\"9\" y2=\"15\" />\r\n <line x1=\"9\" y1=\"9\" x2=\"15\" y2=\"15\" />\r\n </svg>\r\n);\r\n\r\nexport const RestartIcon: React.FC<IconProps> = ({ size = 16, color = 'currentColor' }) => (\r\n <svg width={size} height={size} viewBox=\"0 0 24 24\" fill=\"none\" stroke={color} strokeWidth=\"2\" strokeLinecap=\"round\" strokeLinejoin=\"round\">\r\n <polyline points=\"1 4 1 10 7 10\" />\r\n <path d=\"M3.51 15a9 9 0 1 0 2.13-9.36L1 10\" />\r\n </svg>\r\n);\r\n","import React from 'react';\r\nimport type { CSSProperties } from 'react';\r\nimport type { ChatStyles } from '../styles/theme';\r\nimport { ChatBubbleIcon, CloseIcon } from './icons';\r\n\r\ninterface LauncherProps {\r\n onClick: () => void;\r\n isOpen: boolean;\r\n position: 'bottom-right' | 'bottom-left';\r\n styles: ChatStyles;\r\n icon?: React.ReactNode;\r\n closeIcon?: React.ReactNode;\r\n zIndex?: number;\r\n}\r\n\r\nexport const Launcher: React.FC<LauncherProps> = ({\r\n onClick,\r\n isOpen,\r\n position,\r\n styles,\r\n icon,\r\n closeIcon,\r\n zIndex,\r\n}) => {\r\n const posStyle: CSSProperties =\r\n position === 'bottom-left'\r\n ? { bottom: '24px', left: '24px' }\r\n : { bottom: '24px', right: '24px' };\r\n\r\n return (\r\n <button\r\n onClick={onClick}\r\n aria-label={isOpen ? 'Close chat' : 'Open chat'}\r\n style={{\r\n ...styles.launcher,\r\n ...posStyle,\r\n ...(zIndex != null ? { zIndex } : {}),\r\n transform: isOpen ? 'scale(0.92) rotate(90deg)' : 'scale(1)',\r\n animation: isOpen ? 'none' : 'cb-launcher-pulse 3s ease-in-out infinite',\r\n }}\r\n >\r\n {isOpen\r\n ? closeIcon ?? <CloseIcon size={22} />\r\n : icon ?? <ChatBubbleIcon size={26} />}\r\n </button>\r\n );\r\n};\r\n","import React from 'react';\r\nimport type { HeaderConfig } from '../types';\r\nimport type { ChatStyles as ThemeStyles } from '../styles/theme';\r\nimport { CloseIcon, MinimizeIcon, RestartIcon } from './icons';\r\n\r\ninterface ChatHeaderProps {\r\n config: HeaderConfig;\r\n styles: ThemeStyles;\r\n onClose: () => void;\r\n onRestart?: () => void;\r\n logo?: string;\r\n logoWidth?: string;\r\n}\r\n\r\nexport const ChatHeader: React.FC<ChatHeaderProps> = ({ config, styles, onClose, onRestart, logo, logoWidth }) => {\r\n return (\r\n <div style={styles.header}>\r\n {/* Decorative glow overlay */}\r\n <div\r\n style={{\r\n position: 'absolute',\r\n top: 0,\r\n left: 0,\r\n right: 0,\r\n bottom: 0,\r\n background: 'linear-gradient(135deg, rgba(255,255,255,0.12) 0%, transparent 50%)',\r\n pointerEvents: 'none',\r\n }}\r\n />\r\n <div style={{ display: 'flex', alignItems: 'center', gap: '12px', flex: 1, position: 'relative', zIndex: 1 }}>\r\n {config.avatar && (\r\n <div style={{ position: 'relative' }}>\r\n <img\r\n src={config.avatar}\r\n alt=\"\"\r\n style={{\r\n width: '40px',\r\n height: '40px',\r\n borderRadius: '50%',\r\n objectFit: 'cover',\r\n border: '2px solid rgba(255,255,255,0.3)',\r\n }}\r\n />\r\n <span\r\n style={{\r\n position: 'absolute',\r\n bottom: '1px',\r\n right: '1px',\r\n width: '10px',\r\n height: '10px',\r\n backgroundColor: '#2ECC71',\r\n borderRadius: '50%',\r\n border: '2px solid rgba(255,255,255,0.8)',\r\n }}\r\n />\r\n </div>\r\n )}\r\n {logo && !config.avatar && (\r\n <img\r\n src={logo}\r\n alt=\"\"\r\n style={{ width: logoWidth ?? '36px', height: 'auto', objectFit: 'contain', filter: 'brightness(1.1)' }}\r\n />\r\n )}\r\n {!config.avatar && !logo && (\r\n <div\r\n style={{\r\n width: '40px',\r\n height: '40px',\r\n borderRadius: '50%',\r\n background: 'rgba(255,255,255,0.2)',\r\n backdropFilter: 'blur(4px)',\r\n display: 'flex',\r\n alignItems: 'center',\r\n justifyContent: 'center',\r\n fontSize: '18px',\r\n fontWeight: 700,\r\n color: 'rgba(255,255,255,0.9)',\r\n border: '1px solid rgba(255,255,255,0.2)',\r\n }}\r\n >\r\n {(config.title ?? 'C').charAt(0).toUpperCase()}\r\n </div>\r\n )}\r\n <div>\r\n <div style={{ fontWeight: 600, fontSize: '16px', letterSpacing: '-0.01em' }}>\r\n {config.title ?? 'Chat with us'}\r\n </div>\r\n {config.subtitle && (\r\n <div style={{\r\n fontSize: '12px',\r\n opacity: 0.8,\r\n display: 'flex',\r\n alignItems: 'center',\r\n gap: '5px',\r\n marginTop: '1px',\r\n }}>\r\n <span style={{\r\n width: '6px',\r\n height: '6px',\r\n borderRadius: '50%',\r\n backgroundColor: '#2ECC71',\r\n display: 'inline-block',\r\n }} />\r\n {config.subtitle}\r\n </div>\r\n )}\r\n </div>\r\n </div>\r\n <div style={{ display: 'flex', alignItems: 'center', gap: '2px', position: 'relative', zIndex: 1 }}>\r\n {config.showRestart && onRestart && (\r\n <button\r\n onClick={onRestart}\r\n aria-label=\"Restart conversation\"\r\n title=\"Restart conversation\"\r\n style={{\r\n background: 'rgba(255,255,255,0.1)',\r\n border: 'none',\r\n color: 'inherit',\r\n cursor: 'pointer',\r\n padding: '6px',\r\n display: 'flex',\r\n alignItems: 'center',\r\n borderRadius: '8px',\r\n transition: 'background 0.2s ease',\r\n }}\r\n onMouseEnter={(e) => (e.currentTarget.style.background = 'rgba(255,255,255,0.2)')}\r\n onMouseLeave={(e) => (e.currentTarget.style.background = 'rgba(255,255,255,0.1)')}\r\n >\r\n <RestartIcon size={16} />\r\n </button>\r\n )}\r\n {config.showMinimize && (\r\n <button\r\n onClick={onClose}\r\n aria-label=\"Minimize chat\"\r\n style={{\r\n background: 'rgba(255,255,255,0.1)',\r\n border: 'none',\r\n color: 'inherit',\r\n cursor: 'pointer',\r\n padding: '6px',\r\n display: 'flex',\r\n alignItems: 'center',\r\n borderRadius: '8px',\r\n transition: 'background 0.2s ease',\r\n }}\r\n onMouseEnter={(e) => (e.currentTarget.style.background = 'rgba(255,255,255,0.2)')}\r\n onMouseLeave={(e) => (e.currentTarget.style.background = 'rgba(255,255,255,0.1)')}\r\n >\r\n <MinimizeIcon size={16} />\r\n </button>\r\n )}\r\n {config.showClose !== false && (\r\n <button\r\n onClick={onClose}\r\n aria-label=\"Close chat\"\r\n style={{\r\n background: 'rgba(255,255,255,0.1)',\r\n border: 'none',\r\n color: 'inherit',\r\n cursor: 'pointer',\r\n padding: '6px',\r\n display: 'flex',\r\n alignItems: 'center',\r\n borderRadius: '8px',\r\n transition: 'background 0.2s ease',\r\n }}\r\n onMouseEnter={(e) => (e.currentTarget.style.background = 'rgba(255,255,255,0.2)')}\r\n onMouseLeave={(e) => (e.currentTarget.style.background = 'rgba(255,255,255,0.1)')}\r\n >\r\n <CloseIcon size={18} />\r\n </button>\r\n )}\r\n </div>\r\n </div>\r\n );\r\n};\r\n","import React from 'react';\r\nimport type { ReactNode } from 'react';\r\n\r\ninterface WelcomeScreenProps {\r\n content: ReactNode;\r\n onDismiss: () => void;\r\n primaryColor: string;\r\n}\r\n\r\nexport const WelcomeScreen: React.FC<WelcomeScreenProps> = ({ content, onDismiss, primaryColor }) => {\r\n return (\r\n <div\r\n style={{\r\n flex: 1,\r\n display: 'flex',\r\n flexDirection: 'column',\r\n overflow: 'auto',\r\n background: 'linear-gradient(180deg, rgba(248, 249, 254, 0.95) 0%, rgba(255, 255, 255, 0.98) 100%)',\r\n }}\r\n >\r\n <div style={{ flex: 1, padding: '28px 24px', overflow: 'auto' }}>\r\n {content}\r\n </div>\r\n <div\r\n style={{\r\n padding: '16px 20px',\r\n borderTop: '1px solid rgba(0,0,0,0.05)',\r\n backdropFilter: 'blur(12px)',\r\n WebkitBackdropFilter: 'blur(12px)',\r\n flexShrink: 0,\r\n }}\r\n >\r\n <button\r\n onClick={onDismiss}\r\n style={{\r\n width: '100%',\r\n padding: '14px',\r\n background: `linear-gradient(135deg, ${primaryColor} 0%, ${adjustColor(primaryColor, 30)} 100%)`,\r\n color: '#fff',\r\n border: 'none',\r\n borderRadius: '14px',\r\n fontSize: '15px',\r\n fontWeight: 600,\r\n cursor: 'pointer',\r\n fontFamily: 'inherit',\r\n letterSpacing: '0.02em',\r\n boxShadow: `0 6px 20px ${primaryColor}44`,\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 8px 28px ${primaryColor}55`;\r\n }}\r\n onMouseLeave={(e) => {\r\n e.currentTarget.style.transform = 'translateY(0)';\r\n e.currentTarget.style.boxShadow = `0 6px 20px ${primaryColor}44`;\r\n }}\r\n >\r\n Start Chat\r\n </button>\r\n </div>\r\n </div>\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';\r\nimport type { FormFieldConfig } from '../../types';\r\n\r\ninterface TextFieldProps {\r\n field: FormFieldConfig;\r\n value: string;\r\n onChange: (value: string) => void;\r\n error?: string;\r\n}\r\n\r\nexport const TextField: React.FC<TextFieldProps> = ({ field, value, onChange, error }) => {\r\n const isTextarea = field.type === 'textarea';\r\n const inputType = field.type === 'textarea' ? undefined : field.type;\r\n\r\n const baseStyle: React.CSSProperties = {\r\n width: '100%',\r\n padding: '10px 14px',\r\n border: `1.5px solid ${error ? 'rgba(229, 62, 62, 0.5)' : 'rgba(0,0,0,0.08)'}`,\r\n borderRadius: '12px',\r\n fontSize: '13px',\r\n fontFamily: 'inherit',\r\n outline: 'none',\r\n boxSizing: 'border-box',\r\n transition: 'all 0.2s ease',\r\n backgroundColor: 'rgba(245, 247, 252, 0.6)',\r\n color: '#2D3436',\r\n letterSpacing: '0.01em',\r\n };\r\n\r\n return (\r\n <div style={{ marginBottom: '14px' }}>\r\n {field.label && (\r\n <label style={{ display: 'block', marginBottom: '6px', fontSize: '13px', fontWeight: 500, color: '#2D3436' }}>\r\n {field.label}\r\n {field.required && <span style={{ color: '#E53E3E', marginLeft: '3px' }}>*</span>}\r\n </label>\r\n )}\r\n {isTextarea ? (\r\n <textarea\r\n value={value}\r\n onChange={(e) => onChange(e.target.value)}\r\n placeholder={field.placeholder}\r\n required={field.required}\r\n rows={3}\r\n style={{ ...baseStyle, resize: 'vertical' }}\r\n minLength={field.validation?.minLength}\r\n maxLength={field.validation?.maxLength}\r\n />\r\n ) : (\r\n <input\r\n type={inputType}\r\n value={value}\r\n onChange={(e) => onChange(e.target.value)}\r\n placeholder={field.placeholder}\r\n required={field.required}\r\n style={baseStyle}\r\n min={field.validation?.min}\r\n max={field.validation?.max}\r\n minLength={field.validation?.minLength}\r\n maxLength={field.validation?.maxLength}\r\n pattern={field.validation?.pattern}\r\n />\r\n )}\r\n {error && <div style={{ color: '#E53E3E', fontSize: '12px', marginTop: '2px' }}>{error}</div>}\r\n </div>\r\n );\r\n};\r\n","import React from 'react';\r\nimport type { FormFieldConfig } from '../../types';\r\n\r\ninterface SelectFieldProps {\r\n field: FormFieldConfig;\r\n value: string | string[];\r\n onChange: (value: string | string[]) => void;\r\n error?: string;\r\n}\r\n\r\nexport const SelectField: React.FC<SelectFieldProps> = ({ field, value, onChange, error }) => {\r\n const isMulti = field.type === 'multiselect' || field.multiple;\r\n\r\n const handleChange = (e: React.ChangeEvent<HTMLSelectElement>) => {\r\n if (isMulti) {\r\n const selected = Array.from(e.target.selectedOptions, (opt) => opt.value);\r\n onChange(selected);\r\n } else {\r\n onChange(e.target.value);\r\n }\r\n };\r\n\r\n const selectValue = isMulti\r\n ? Array.isArray(value) ? value : [value].filter(Boolean)\r\n : typeof value === 'string' ? value : '';\r\n\r\n return (\r\n <div style={{ marginBottom: '14px' }}>\r\n {field.label && (\r\n <label style={{ display: 'block', marginBottom: '6px', fontSize: '13px', fontWeight: 500, color: '#2D3436' }}>\r\n {field.label}\r\n {field.required && <span style={{ color: '#E53E3E', marginLeft: '3px' }}>*</span>}\r\n </label>\r\n )}\r\n <select\r\n value={selectValue}\r\n onChange={handleChange}\r\n multiple={isMulti}\r\n required={field.required}\r\n style={{\r\n width: '100%',\r\n padding: '10px 14px',\r\n border: `1.5px solid ${error ? 'rgba(229, 62, 62, 0.5)' : 'rgba(0,0,0,0.08)'}`,\r\n borderRadius: '12px',\r\n fontSize: '13px',\r\n fontFamily: 'inherit',\r\n outline: 'none',\r\n backgroundColor: 'rgba(245, 247, 252, 0.6)',\r\n color: '#2D3436',\r\n boxSizing: 'border-box',\r\n transition: 'all 0.2s ease',\r\n ...(isMulti ? { minHeight: '80px' } : {}),\r\n }}\r\n >\r\n {!isMulti && <option value=\"\">Select...</option>}\r\n {field.options?.map((opt) => (\r\n <option key={opt.value} value={opt.value}>\r\n {opt.label}\r\n </option>\r\n ))}\r\n </select>\r\n {isMulti && (\r\n <div style={{ fontSize: '11px', color: '#888', marginTop: '2px' }}>\r\n Hold Ctrl/Cmd to select multiple\r\n </div>\r\n )}\r\n {error && <div style={{ color: '#E53E3E', fontSize: '12px', marginTop: '2px' }}>{error}</div>}\r\n </div>\r\n );\r\n};\r\n","import React from 'react';\r\nimport type { FormFieldConfig } from '../../types';\r\n\r\ninterface RadioFieldProps {\r\n field: FormFieldConfig;\r\n value: string;\r\n onChange: (value: string) => void;\r\n error?: string;\r\n}\r\n\r\nexport const RadioField: React.FC<RadioFieldProps> = ({ field, value, onChange, error }) => {\r\n return (\r\n <div style={{ marginBottom: '12px' }}>\r\n {field.label && (\r\n <label style={{ display: 'block', marginBottom: '6px', fontSize: '13px', fontWeight: 500 }}>\r\n {field.label}\r\n {field.required && <span style={{ color: '#E53E3E', marginLeft: '2px' }}>*</span>}\r\n </label>\r\n )}\r\n <div style={{ display: 'flex', flexDirection: 'column', gap: '6px' }}>\r\n {field.options?.map((opt) => (\r\n <label\r\n key={opt.value}\r\n style={{\r\n display: 'flex',\r\n alignItems: 'center',\r\n gap: '8px',\r\n cursor: 'pointer',\r\n fontSize: '13px',\r\n }}\r\n >\r\n <input\r\n type=\"radio\"\r\n name={field.name}\r\n value={opt.value}\r\n checked={value === opt.value}\r\n onChange={() => onChange(opt.value)}\r\n style={{ margin: 0 }}\r\n />\r\n {opt.label}\r\n </label>\r\n ))}\r\n </div>\r\n {error && <div style={{ color: '#E53E3E', fontSize: '12px', marginTop: '2px' }}>{error}</div>}\r\n </div>\r\n );\r\n};\r\n","import React from 'react';\r\nimport type { FormFieldConfig } from '../../types';\r\n\r\ninterface CheckboxFieldProps {\r\n field: FormFieldConfig;\r\n value: string[];\r\n onChange: (value: string[]) => void;\r\n error?: string;\r\n}\r\n\r\nexport const CheckboxField: React.FC<CheckboxFieldProps> = ({ field, value, onChange, error }) => {\r\n const handleToggle = (optValue: string) => {\r\n if (value.includes(optValue)) {\r\n onChange(value.filter((v) => v !== optValue));\r\n } else {\r\n onChange([...value, optValue]);\r\n }\r\n };\r\n\r\n return (\r\n <div style={{ marginBottom: '12px' }}>\r\n {field.label && (\r\n <label style={{ display: 'block', marginBottom: '6px', fontSize: '13px', fontWeight: 500 }}>\r\n {field.label}\r\n {field.required && <span style={{ color: '#E53E3E', marginLeft: '2px' }}>*</span>}\r\n </label>\r\n )}\r\n <div style={{ display: 'flex', flexDirection: 'column', gap: '6px' }}>\r\n {field.options?.map((opt) => (\r\n <label\r\n key={opt.value}\r\n style={{\r\n display: 'flex',\r\n alignItems: 'center',\r\n gap: '8px',\r\n cursor: 'pointer',\r\n fontSize: '13px',\r\n }}\r\n >\r\n <input\r\n type=\"checkbox\"\r\n checked={value.includes(opt.value)}\r\n onChange={() => handleToggle(opt.value)}\r\n style={{ margin: 0 }}\r\n />\r\n {opt.label}\r\n </label>\r\n ))}\r\n </div>\r\n {error && <div style={{ color: '#E53E3E', fontSize: '12px', marginTop: '2px' }}>{error}</div>}\r\n </div>\r\n );\r\n};\r\n","import React, { useRef } from 'react';\r\nimport type { FormFieldConfig } from '../../types';\r\n\r\ninterface FileUploadFieldProps {\r\n field: FormFieldConfig;\r\n value: FileList | null;\r\n onChange: (files: FileList | null) => void;\r\n error?: string;\r\n primaryColor: string;\r\n}\r\n\r\nexport const FileUploadField: React.FC<FileUploadFieldProps> = ({\r\n field,\r\n value,\r\n onChange,\r\n error,\r\n primaryColor,\r\n}) => {\r\n const inputRef = useRef<HTMLInputElement>(null);\r\n\r\n const fileNames = value ? Array.from(value).map((f) => f.name).join(', ') : '';\r\n\r\n return (\r\n <div style={{ marginBottom: '12px' }}>\r\n {field.label && (\r\n <label style={{ display: 'block', marginBottom: '4px', fontSize: '13px', fontWeight: 500 }}>\r\n {field.label}\r\n {field.required && <span style={{ color: '#E53E3E', marginLeft: '2px' }}>*</span>}\r\n </label>\r\n )}\r\n <input\r\n ref={inputRef}\r\n type=\"file\"\r\n accept={field.accept}\r\n multiple={field.multiple}\r\n onChange={(e) => onChange(e.target.files)}\r\n style={{ display: 'none' }}\r\n />\r\n <button\r\n type=\"button\"\r\n onClick={() => inputRef.current?.click()}\r\n style={{\r\n padding: '8px 16px',\r\n border: `1px dashed ${error ? '#E53E3E' : '#D1D5DB'}`,\r\n borderRadius: '8px',\r\n backgroundColor: '#FAFAFA',\r\n cursor: 'pointer',\r\n fontSize: '13px',\r\n color: '#555',\r\n width: '100%',\r\n textAlign: 'left',\r\n }}\r\n >\r\n {fileNames || field.placeholder || 'Choose file(s)...'}\r\n </button>\r\n {fileNames && (\r\n <div style={{ fontSize: '12px', color: primaryColor, marginTop: '4px' }}>\r\n {Array.from(value!).length} file(s) selected\r\n </div>\r\n )}\r\n {error && <div style={{ color: '#E53E3E', fontSize: '12px', marginTop: '2px' }}>{error}</div>}\r\n </div>\r\n );\r\n};\r\n","import React, { useState, useCallback } from 'react';\r\nimport type { FormConfig, FormFieldConfig } from '../../types';\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}\r\n\r\nexport const DynamicForm: React.FC<DynamicFormProps> = ({ config, onSubmit, primaryColor }) => {\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 />\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}\r\n\r\nconst FormField: React.FC<FormFieldProps> = ({ field, value, onChange, error, primaryColor }) => {\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 return (\r\n <TextField\r\n field={field}\r\n value={String(value ?? '')}\r\n onChange={onChange as (v: string) => void}\r\n error={error}\r\n />\r\n );\r\n case 'select':\r\n case 'multiselect':\r\n return (\r\n <SelectField\r\n field={field}\r\n value={value as string | string[]}\r\n onChange={onChange as (v: string | string[]) => void}\r\n error={error}\r\n />\r\n );\r\n case 'radio':\r\n return (\r\n <RadioField\r\n field={field}\r\n value={String(value ?? '')}\r\n onChange={onChange as (v: string) => void}\r\n error={error}\r\n />\r\n );\r\n case 'checkbox':\r\n return (\r\n <CheckboxField\r\n field={field}\r\n value={(value as string[]) ?? []}\r\n onChange={onChange as (v: string[]) => void}\r\n error={error}\r\n />\r\n );\r\n case 'file':\r\n return (\r\n <FileUploadField\r\n field={field}\r\n value={value as FileList | null}\r\n onChange={onChange as (v: FileList | null) => void}\r\n error={error}\r\n primaryColor={primaryColor}\r\n />\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';\r\nimport type { FormConfig } from '../types';\r\nimport { DynamicForm } from './forms/DynamicForm';\r\n\r\ninterface LoginScreenProps {\r\n config: FormConfig;\r\n onLogin: (data: Record<string, unknown>) => void;\r\n primaryColor: string;\r\n}\r\n\r\nexport const LoginScreen: React.FC<LoginScreenProps> = ({ config, onLogin, primaryColor }) => {\r\n return (\r\n <div\r\n style={{\r\n flex: 1,\r\n display: 'flex',\r\n flexDirection: 'column',\r\n justifyContent: 'center',\r\n padding: '24px',\r\n overflow: 'auto',\r\n background: 'linear-gradient(180deg, rgba(248, 249, 254, 0.95) 0%, rgba(255, 255, 255, 0.98) 100%)',\r\n }}\r\n >\r\n <DynamicForm config={config} onSubmit={onLogin} primaryColor={primaryColor} />\r\n </div>\r\n );\r\n};\r\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';\r\nimport type { FlowQuickReply } from '../types';\r\n\r\ninterface QuickRepliesProps {\r\n replies: FlowQuickReply[];\r\n onSelect: (value: string, label: string) => void;\r\n primaryColor: string;\r\n}\r\n\r\nexport const QuickReplies: React.FC<QuickRepliesProps> = ({ replies, onSelect, primaryColor }) => {\r\n return (\r\n <div\r\n style={{\r\n display: 'flex',\r\n flexWrap: 'wrap',\r\n gap: '8px',\r\n alignSelf: 'flex-start',\r\n maxWidth: '90%',\r\n animation: 'cb-slide-up 0.35s ease-out',\r\n padding: '4px 0',\r\n }}\r\n >\r\n {replies.map((reply) => (\r\n <button\r\n key={reply.value}\r\n onClick={() => onSelect(reply.value, reply.label)}\r\n style={{\r\n padding: '8px 18px',\r\n borderRadius: '22px',\r\n border: `1.5px solid ${primaryColor}`,\r\n backgroundColor: 'rgba(108, 92, 231, 0.06)',\r\n color: primaryColor,\r\n cursor: 'pointer',\r\n fontSize: '13px',\r\n fontWeight: 500,\r\n fontFamily: 'inherit',\r\n transition: 'all 0.25s cubic-bezier(0.4, 0, 0.2, 1)',\r\n backdropFilter: 'blur(4px)',\r\n WebkitBackdropFilter: 'blur(4px)',\r\n letterSpacing: '0.01em',\r\n }}\r\n onMouseEnter={(e) => {\r\n e.currentTarget.style.backgroundColor = primaryColor;\r\n e.currentTarget.style.color = '#fff';\r\n e.currentTarget.style.transform = 'translateY(-1px)';\r\n e.currentTarget.style.boxShadow = `0 4px 14px ${primaryColor}44`;\r\n }}\r\n onMouseLeave={(e) => {\r\n e.currentTarget.style.backgroundColor = 'rgba(108, 92, 231, 0.06)';\r\n e.currentTarget.style.color = primaryColor;\r\n e.currentTarget.style.transform = 'translateY(0)';\r\n e.currentTarget.style.boxShadow = 'none';\r\n }}\r\n >\r\n {reply.label}\r\n </button>\r\n ))}\r\n </div>\r\n );\r\n};\r\n","import React from 'react';\r\n\r\ninterface TypingIndicatorProps {\r\n color: string;\r\n}\r\n\r\nexport const TypingIndicator: React.FC<TypingIndicatorProps> = ({ color }) => {\r\n const dotStyle: React.CSSProperties = {\r\n width: '7px',\r\n height: '7px',\r\n borderRadius: '50%',\r\n backgroundColor: color,\r\n opacity: 0.35,\r\n animation: 'cb-typing-bounce 1.4s infinite ease-in-out',\r\n };\r\n\r\n return (\r\n <div\r\n style={{\r\n display: 'flex',\r\n gap: '5px',\r\n padding: '14px 18px',\r\n background: 'rgba(241, 243, 249, 0.8)',\r\n backdropFilter: 'blur(8px)',\r\n WebkitBackdropFilter: 'blur(8px)',\r\n borderRadius: '18px 18px 18px 4px',\r\n alignSelf: 'flex-start',\r\n alignItems: 'center',\r\n border: '1px solid rgba(0,0,0,0.04)',\r\n boxShadow: '0 2px 8px rgba(0,0,0,0.04)',\r\n animation: 'cb-fade-in 0.3s ease-out',\r\n }}\r\n >\r\n <span style={{ ...dotStyle, animationDelay: '0s' }} />\r\n <span style={{ ...dotStyle, animationDelay: '0.2s' }} />\r\n <span style={{ ...dotStyle, animationDelay: '0.4s' }} />\r\n </div>\r\n );\r\n};\r\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 { 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}\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}) => {\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 />\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';\r\n\r\nconst EMOJI_CATEGORIES = [\r\n {\r\n name: 'Smileys',\r\n emojis: ['😀', '😃', '😄', '😁', '😅', '😂', '🤣', '😊', '😇', '🙂', '😉', '😍', '🥰', '😘', '😋', '😜', '🤪', '🤗', '🤔', '🤫', '🤭', '😏', '😐', '😑', '😶', '😌', '😴', '🤤', '😷', '🤒'],\r\n },\r\n {\r\n name: 'Gestures',\r\n emojis: ['👍', '👎', '👌', '✌️', '🤞', '🤟', '🤘', '👋', '🤚', '✋', '🖖', '👏', '🙌', '🤝', '🙏', '💪', '🖐️', '☝️', '👆', '👇', '👈', '👉', '🤙', '🫡', '🫶', '🫰', '🫳', '🫴', '🫲', '🫱'],\r\n },\r\n {\r\n name: 'Hearts',\r\n emojis: ['❤️', '🧡', '💛', '💚', '💙', '💜', '🖤', '🤍', '🤎', '💔', '❣️', '💕', '💞', '💓', '💗', '💖', '💘', '💝', '💟', '♥️', '🫀', '💌', '💐', '🌹', '🌺', '🌸', '🌼', '🌻', '🌷', '💮'],\r\n },\r\n {\r\n name: 'Objects',\r\n emojis: ['🔥', '⭐', '✨', '💯', '🎉', '🎊', '🎯', '🚀', '💡', '📌', '📎', '🔗', '💻', '📱', '☎️', '📧', '📝', '📋', '📊', '📈', '🗂️', '📁', '🔒', '🔑', '⚙️', '🛠️', '🔧', '📦', '🏷️', '✅'],\r\n },\r\n];\r\n\r\ninterface EmojiPickerProps {\r\n onSelect: (emoji: string) => void;\r\n onClose: () => void;\r\n primaryColor: string;\r\n}\r\n\r\nexport const EmojiPicker: React.FC<EmojiPickerProps> = ({ onSelect, onClose, primaryColor }) => {\r\n const [activeCategory, setActiveCategory] = useState(0);\r\n const pickerRef = useRef<HTMLDivElement>(null);\r\n\r\n useEffect(() => {\r\n const handleClickOutside = (e: MouseEvent) => {\r\n if (pickerRef.current && !pickerRef.current.contains(e.target as Node)) {\r\n onClose();\r\n }\r\n };\r\n document.addEventListener('mousedown', handleClickOutside);\r\n return () => document.removeEventListener('mousedown', handleClickOutside);\r\n }, [onClose]);\r\n\r\n const currentEmojis = EMOJI_CATEGORIES[activeCategory]?.emojis ?? [];\r\n\r\n return (\r\n <div\r\n ref={pickerRef}\r\n style={{\r\n position: 'absolute',\r\n bottom: '100%',\r\n left: 0,\r\n width: '280px',\r\n backgroundColor: 'rgba(255, 255, 255, 0.92)',\r\n backdropFilter: 'blur(20px)',\r\n WebkitBackdropFilter: 'blur(20px)',\r\n borderRadius: '16px',\r\n boxShadow: '0 8px 32px rgba(0,0,0,0.12), 0 0 0 1px rgba(0,0,0,0.04)',\r\n border: '1px solid rgba(255,255,255,0.8)',\r\n overflow: 'hidden',\r\n zIndex: 10,\r\n marginBottom: '8px',\r\n animation: 'cb-slide-up 0.25s ease-out',\r\n }}\r\n >\r\n {/* Category tabs */}\r\n <div\r\n style={{\r\n display: 'flex',\r\n borderBottom: '1px solid rgba(0,0,0,0.06)',\r\n padding: '6px',\r\n gap: '3px',\r\n }}\r\n >\r\n {EMOJI_CATEGORIES.map((cat, idx) => (\r\n <button\r\n key={cat.name}\r\n onClick={() => setActiveCategory(idx)}\r\n title={cat.name}\r\n style={{\r\n flex: 1,\r\n padding: '6px 4px',\r\n border: 'none',\r\n borderRadius: '8px',\r\n cursor: 'pointer',\r\n fontSize: '11px',\r\n fontWeight: 600,\r\n fontFamily: 'inherit',\r\n letterSpacing: '0.02em',\r\n background: idx === activeCategory\r\n ? `linear-gradient(135deg, ${primaryColor}, ${primaryColor}CC)`\r\n : 'transparent',\r\n color: idx === activeCategory ? '#fff' : 'rgba(0,0,0,0.4)',\r\n transition: 'all 0.2s ease',\r\n boxShadow: idx === activeCategory ? `0 2px 8px ${primaryColor}33` : 'none',\r\n }}\r\n >\r\n {cat.name}\r\n </button>\r\n ))}\r\n </div>\r\n\r\n {/* Emoji Grid */}\r\n <div\r\n style={{\r\n display: 'grid',\r\n gridTemplateColumns: 'repeat(8, 1fr)',\r\n gap: '2px',\r\n padding: '8px',\r\n maxHeight: '180px',\r\n overflowY: 'auto',\r\n }}\r\n >\r\n {currentEmojis.map((emoji) => (\r\n <button\r\n key={emoji}\r\n onClick={() => {\r\n onSelect(emoji);\r\n onClose();\r\n }}\r\n style={{\r\n width: '30px',\r\n height: '30px',\r\n border: 'none',\r\n backgroundColor: 'transparent',\r\n cursor: 'pointer',\r\n fontSize: '18px',\r\n borderRadius: '6px',\r\n display: 'flex',\r\n alignItems: 'center',\r\n justifyContent: 'center',\r\n transition: 'all 0.15s ease',\r\n }}\r\n onMouseEnter={(e) => (e.currentTarget.style.backgroundColor = 'rgba(108, 92, 231, 0.08)')}\r\n onMouseLeave={(e) => (e.currentTarget.style.backgroundColor = 'transparent')}\r\n >\r\n {emoji}\r\n </button>\r\n ))}\r\n </div>\r\n </div>\r\n );\r\n};\r\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';\r\nimport type { CSSProperties } from 'react';\r\nimport type { FileUploadConfig } from '../types/config';\r\nimport { SendIcon, EmojiIcon } from './icons';\r\nimport { EmojiPicker } from './EmojiPicker';\r\nimport { FileUploadButton, FilePreviewList } from './FileUpload';\r\n\r\ninterface ChatInputProps {\r\n onSend: (text: string, files?: File[]) => void;\r\n placeholder?: string;\r\n primaryColor: string;\r\n isDark?: boolean;\r\n disabled?: boolean;\r\n styleOverride?: CSSProperties;\r\n enableEmoji?: boolean;\r\n fileUpload?: FileUploadConfig;\r\n onFileUpload?: (files: File[]) => void;\r\n}\r\n\r\nexport const ChatInput: React.FC<ChatInputProps> = ({\r\n onSend,\r\n placeholder = 'Type a message...',\r\n primaryColor,\r\n isDark = false,\r\n disabled,\r\n styleOverride,\r\n enableEmoji = false,\r\n fileUpload,\r\n onFileUpload,\r\n}) => {\r\n const [text, setText] = useState('');\r\n const [showEmoji, setShowEmoji] = useState(false);\r\n const [attachedFiles, setAttachedFiles] = useState<File[]>([]);\r\n const inputRef = useRef<HTMLTextAreaElement>(null);\r\n\r\n const handleSend = useCallback(() => {\r\n const trimmed = text.trim();\r\n if (!trimmed && attachedFiles.length === 0) return;\r\n onSend(trimmed, attachedFiles.length > 0 ? attachedFiles : undefined);\r\n setText('');\r\n setAttachedFiles([]);\r\n inputRef.current?.focus();\r\n }, [text, attachedFiles, onSend]);\r\n\r\n const handleKeyDown = (e: React.KeyboardEvent) => {\r\n if (e.key === 'Enter' && !e.shiftKey) {\r\n e.preventDefault();\r\n handleSend();\r\n }\r\n };\r\n\r\n const handleEmojiSelect = (emoji: string) => {\r\n setText((prev) => prev + emoji);\r\n inputRef.current?.focus();\r\n };\r\n\r\n const handleFiles = (files: File[]) => {\r\n setAttachedFiles((prev) => [...prev, ...files]);\r\n onFileUpload?.(files);\r\n };\r\n\r\n const handleRemoveFile = (index: number) => {\r\n setAttachedFiles((prev) => prev.filter((_, i) => i !== index));\r\n };\r\n\r\n const hasContent = text.trim() || attachedFiles.length > 0;\r\n\r\n return (\r\n <div style={{ position: 'relative', ...styleOverride }}>\r\n {/* File preview above input */}\r\n {attachedFiles.length > 0 && (\r\n <FilePreviewList\r\n files={attachedFiles}\r\n onRemove={handleRemoveFile}\r\n primaryColor={primaryColor}\r\n />\r\n )}\r\n\r\n {/* Emoji picker */}\r\n {showEmoji && (\r\n <EmojiPicker\r\n onSelect={handleEmojiSelect}\r\n onClose={() => setShowEmoji(false)}\r\n primaryColor={primaryColor}\r\n />\r\n )}\r\n\r\n <div\r\n style={{\r\n display: 'flex',\r\n gap: '8px',\r\n alignItems: 'flex-end',\r\n background: isDark ? 'rgba(40, 40, 65, 0.5)' : 'rgba(245, 247, 252, 0.7)',\r\n borderRadius: '16px',\r\n border: `1px solid ${isDark ? 'rgba(255,255,255,0.08)' : 'rgba(0,0,0,0.05)'}`,\r\n backdropFilter: 'blur(8px)',\r\n WebkitBackdropFilter: 'blur(8px)',\r\n padding: '6px 6px 6px 12px',\r\n }}\r\n >\r\n {/* Action buttons */}\r\n <div style={{ display: 'flex', alignItems: 'center', gap: '2px', flexShrink: 0, paddingBottom: '2px' }}>\r\n {enableEmoji && (\r\n <button\r\n type=\"button\"\r\n onClick={() => setShowEmoji(!showEmoji)}\r\n aria-label=\"Emoji\"\r\n title=\"Emoji\"\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 color: showEmoji ? primaryColor : (isDark ? 'rgba(255,255,255,0.35)' : 'rgba(0,0,0,0.3)'),\r\n borderRadius: '8px',\r\n transition: 'all 0.2s ease',\r\n }}\r\n >\r\n <EmojiIcon size={20} />\r\n </button>\r\n )}\r\n\r\n {fileUpload?.enabled && (\r\n <FileUploadButton\r\n config={fileUpload}\r\n onFiles={handleFiles}\r\n selectedFiles={attachedFiles}\r\n onRemoveFile={handleRemoveFile}\r\n primaryColor={primaryColor}\r\n />\r\n )}\r\n </div>\r\n\r\n {/* Text Input */}\r\n <textarea\r\n ref={inputRef}\r\n value={text}\r\n onChange={(e) => setText(e.target.value)}\r\n onKeyDown={handleKeyDown}\r\n placeholder={placeholder}\r\n disabled={disabled}\r\n rows={1}\r\n style={{\r\n flex: 1,\r\n padding: '8px 2px',\r\n border: 'none',\r\n borderRadius: '12px',\r\n outline: 'none',\r\n resize: 'none',\r\n fontFamily: 'inherit',\r\n fontSize: '14px',\r\n lineHeight: '1.45',\r\n maxHeight: '100px',\r\n overflowY: 'auto',\r\n backgroundColor: 'transparent',\r\n color: isDark ? '#E0E0E0' : '#2D3436',\r\n letterSpacing: '0.01em',\r\n }}\r\n />\r\n\r\n {/* Send Button */}\r\n <button\r\n onClick={handleSend}\r\n disabled={disabled || !hasContent}\r\n aria-label=\"Send message\"\r\n style={{\r\n width: '36px',\r\n height: '36px',\r\n borderRadius: '12px',\r\n background: hasContent\r\n ? `linear-gradient(135deg, ${primaryColor} 0%, ${adjustColor(primaryColor, 30)} 100%)`\r\n : (isDark ? 'rgba(255,255,255,0.08)' : 'rgba(0,0,0,0.06)'),\r\n color: hasContent ? '#fff' : (isDark ? 'rgba(255,255,255,0.25)' : 'rgba(0,0,0,0.2)'),\r\n border: 'none',\r\n cursor: hasContent ? 'pointer' : 'default',\r\n display: 'flex',\r\n alignItems: 'center',\r\n justifyContent: 'center',\r\n flexShrink: 0,\r\n transition: 'all 0.25s cubic-bezier(0.4, 0, 0.2, 1)',\r\n boxShadow: hasContent ? `0 4px 12px ${primaryColor}44` : 'none',\r\n }}\r\n >\r\n <SendIcon size={16} />\r\n </button>\r\n </div>\r\n </div>\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';\r\nimport type { BrandingConfig } from '../types/config';\r\n\r\ninterface BrandingProps {\r\n config: BrandingConfig;\r\n primaryColor: string;\r\n}\r\n\r\nexport const Branding: React.FC<BrandingProps> = ({ config, primaryColor }) => {\r\n if (config.showBranding === false) return null;\r\n\r\n const text = config.poweredBy ?? 'React ChatBot';\r\n\r\n return (\r\n <div\r\n style={{\r\n padding: '8px 16px',\r\n textAlign: 'center',\r\n fontSize: '11px',\r\n color: 'rgba(0,0,0,0.35)',\r\n background: 'rgba(250, 250, 255, 0.7)',\r\n backdropFilter: 'blur(8px)',\r\n WebkitBackdropFilter: 'blur(8px)',\r\n borderTop: '1px solid rgba(0,0,0,0.04)',\r\n flexShrink: 0,\r\n letterSpacing: '0.02em',\r\n }}\r\n >\r\n Powered by{' '}\r\n {config.poweredByUrl ? (\r\n <a\r\n href={config.poweredByUrl}\r\n target=\"_blank\"\r\n rel=\"noopener noreferrer\"\r\n style={{\r\n color: primaryColor,\r\n textDecoration: 'none',\r\n fontWeight: 600,\r\n transition: 'opacity 0.2s ease',\r\n }}\r\n >\r\n {text}\r\n </a>\r\n ) : (\r\n <span style={{ color: primaryColor, fontWeight: 600 }}>{text}</span>\r\n )}\r\n </div>\r\n );\r\n};\r\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;\r\n\r\nexport const uid = (): string => `msg_${Date.now()}_${++counter}`;\r\n\r\nexport const classNames = (...args: (string | false | null | undefined)[]): string =>\r\n args.filter(Boolean).join(' ');\r\n\r\nexport const delay = (ms: number): Promise<void> =>\r\n new Promise((resolve) => setTimeout(resolve, ms));\r\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 />\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 />\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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,MAAC;AAAA,MAAM;AAAA,MAAM;AAAA,MAAM;AAAA,MAAM;AAAA,MAAM;AAAA,MAAM;AAAA,MAAM;AAAA,MAAM;AAAA,MAAM;AAAA,MAAM;AAAA,MAAM;AAAA,MAAM;AAAA,MAAM;AAAA,MAAM;AAAA,MAAM;AAAA,MAAM;AAAA,MAAM;AAAA,MAAM;AAAA,MAAM;AAAA,MAAM;AAAA,MAAM;AAAA,MAAM;AAAA,MAAM;AAAA,MAAM;AAAA,MAAM;AAAA,MAAM;AAAA,MAAM;AAAA,MAAM;AAAA,MAAM;AAAA;;EAEzL;AAAA,IACE,MAAM;AAAA,IACN,QAAQ;AAAA,MAAC;AAAA,MAAM;AAAA,MAAM;AAAA,MAAM;AAAA,MAAM;AAAA,MAAM;AAAA,MAAM;AAAA,MAAM;AAAA,MAAM;AAAA,MAAM;AAAA,MAAK;AAAA,MAAM;AAAA,MAAM;AAAA,MAAM;AAAA,MAAM;AAAA,MAAM;AAAA,MAAM;AAAA,MAAO;AAAA,MAAM;AAAA,MAAM;AAAA,MAAM;AAAA,MAAM;AAAA,MAAM;AAAA,MAAM;AAAA,MAAM;AAAA,MAAM;AAAA,MAAM;AAAA,MAAM;AAAA,MAAM;AAAA,MAAM;AAAA;;EAEzL;AAAA,IACE,MAAM;AAAA,IACN,QAAQ;AAAA,MAAC;AAAA,MAAM;AAAA,MAAM;AAAA,MAAM;AAAA,MAAM;AAAA,MAAM;AAAA,MAAM;AAAA,MAAM;AAAA,MAAM;AAAA,MAAM;AAAA,MAAM;AAAA,MAAM;AAAA,MAAM;AAAA,MAAM;AAAA,MAAM;AAAA,MAAM;AAAA,MAAM;AAAA,MAAM;AAAA,MAAM;AAAA,MAAM;AAAA,MAAM;AAAA,MAAM;AAAA,MAAM;AAAA,MAAM;AAAA,MAAM;AAAA,MAAM;AAAA,MAAM;AAAA,MAAM;AAAA,MAAM;AAAA,MAAM;AAAA;;EAEzL;AAAA,IACE,MAAM;AAAA,IACN,QAAQ;AAAA,MAAC;AAAA,MAAM;AAAA,MAAK;AAAA,MAAK;AAAA,MAAM;AAAA,MAAM;AAAA,MAAM;AAAA,MAAM;AAAA,MAAM;AAAA,MAAM;AAAA,MAAM;AAAA,MAAM;AAAA,MAAM;AAAA,MAAM;AAAA,MAAM;AAAA,MAAM;AAAA,MAAM;AAAA,MAA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"}
|
|
1
|
+
{"version":3,"file":"index.mjs","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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"}
|