@waysdrop/chat 1.0.4 โ†’ 1.0.6

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.cjs CHANGED
@@ -253,7 +253,7 @@ var useChat = (config) => {
253
253
  var import_react2 = require("react");
254
254
  var import_css = require("@emotion/css");
255
255
  var import_jsx_runtime = require("react/jsx-runtime");
256
- var BUTTON_SIZE = 56;
256
+ var BUTTON_SIZE = 58;
257
257
  var FloatingButton = ({ isOpen, onToggle }) => {
258
258
  const [isMobile, setIsMobile] = (0, import_react2.useState)(false);
259
259
  (0, import_react2.useEffect)(() => {
@@ -263,49 +263,17 @@ var FloatingButton = ({ isOpen, onToggle }) => {
263
263
  return () => window.removeEventListener("resize", check);
264
264
  }, []);
265
265
  if (isMobile && isOpen) {
266
- return /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
267
- "button",
268
- {
269
- className: styles.mobileCloseBtn,
270
- onClick: onToggle,
271
- type: "button",
272
- children: /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(
273
- "svg",
274
- {
275
- width: "22",
276
- height: "22",
277
- viewBox: "0 0 24 24",
278
- fill: "none",
279
- stroke: "currentColor",
280
- strokeWidth: "2.5",
281
- strokeLinecap: "round",
282
- children: [
283
- /* @__PURE__ */ (0, import_jsx_runtime.jsx)("line", { x1: "18", y1: "6", x2: "6", y2: "18" }),
284
- /* @__PURE__ */ (0, import_jsx_runtime.jsx)("line", { x1: "6", y1: "6", x2: "18", y2: "18" })
285
- ]
286
- }
287
- )
288
- }
289
- );
266
+ return /* @__PURE__ */ (0, import_jsx_runtime.jsx)("button", { className: styles.mobileCloseBtn, onClick: onToggle, type: "button", children: /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("svg", { width: "22", height: "22", viewBox: "0 0 24 24", fill: "none", stroke: "#fff", strokeWidth: "2.5", strokeLinecap: "round", children: [
267
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)("line", { x1: "18", y1: "6", x2: "6", y2: "18" }),
268
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)("line", { x1: "6", y1: "6", x2: "18", y2: "18" })
269
+ ] }) });
290
270
  }
291
271
  return /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("button", { className: styles.btn, onClick: onToggle, type: "button", children: [
292
- /* @__PURE__ */ (0, import_jsx_runtime.jsx)("span", { className: styles.icon(!isOpen), children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)("svg", { width: "24", height: "24", viewBox: "0 0 24 24", fill: "currentColor", children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)("path", { d: "M20 2H4a2 2 0 0 0-2 2v18l4-4h14a2 2 0 0 0 2-2V4a2 2 0 0 0-2-2z" }) }) }),
293
- /* @__PURE__ */ (0, import_jsx_runtime.jsx)("span", { className: styles.icon(isOpen), children: /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(
294
- "svg",
295
- {
296
- width: "20",
297
- height: "20",
298
- viewBox: "0 0 24 24",
299
- fill: "none",
300
- stroke: "currentColor",
301
- strokeWidth: "2.5",
302
- strokeLinecap: "round",
303
- children: [
304
- /* @__PURE__ */ (0, import_jsx_runtime.jsx)("line", { x1: "18", y1: "6", x2: "6", y2: "18" }),
305
- /* @__PURE__ */ (0, import_jsx_runtime.jsx)("line", { x1: "6", y1: "6", x2: "18", y2: "18" })
306
- ]
307
- }
308
- ) })
272
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)("span", { className: styles.icon(!isOpen), children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)("svg", { width: "24", height: "24", viewBox: "0 0 24 24", fill: "#fff", children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)("path", { d: "M20 2H4a2 2 0 0 0-2 2v18l4-4h14a2 2 0 0 0 2-2V4a2 2 0 0 0-2-2z" }) }) }),
273
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)("span", { className: styles.icon(isOpen), children: /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("svg", { width: "20", height: "20", viewBox: "0 0 24 24", fill: "none", stroke: "#fff", strokeWidth: "2.5", strokeLinecap: "round", children: [
274
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)("line", { x1: "18", y1: "6", x2: "6", y2: "18" }),
275
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)("line", { x1: "6", y1: "6", x2: "18", y2: "18" })
276
+ ] }) })
309
277
  ] });
310
278
  };
311
279
  var styles = {
@@ -316,8 +284,7 @@ var styles = {
316
284
  width: ${BUTTON_SIZE}px;
317
285
  height: ${BUTTON_SIZE}px;
318
286
  border-radius: 50%;
319
- background: var(--wds-primary);
320
- color: #fff;
287
+ background: var(--wds-primary, oklch(0.5811 0.2268 259.15));
321
288
  border: none;
322
289
  cursor: pointer;
323
290
  box-shadow: 0 4px 20px rgba(0, 0, 0, 0.18);
@@ -338,8 +305,7 @@ var styles = {
338
305
  width: ${BUTTON_SIZE}px;
339
306
  height: ${BUTTON_SIZE}px;
340
307
  border-radius: 50%;
341
- background: var(--wds-primary);
342
- color: #fff;
308
+ background: var(--wds-primary, oklch(0.5811 0.2268 259.15));
343
309
  border: none;
344
310
  cursor: pointer;
345
311
  box-shadow: 0 4px 20px rgba(0, 0, 0, 0.25);
@@ -353,9 +319,8 @@ var styles = {
353
319
  display: flex;
354
320
  align-items: center;
355
321
  justify-content: center;
356
- transition:
357
- opacity 0.2s,
358
- transform 0.2s;
322
+ transition: opacity 0.15s, transform 0.15s;
323
+ transition-delay: ${visible ? "0.1s" : "0s"};
359
324
  opacity: ${visible ? 1 : 0};
360
325
  transform: ${visible ? "scale(1)" : "scale(0.6) rotate(30deg)"};
361
326
  pointer-events: ${visible ? "auto" : "none"};
@@ -1081,7 +1046,6 @@ var styles5 = {
1081
1046
  margin: 0;
1082
1047
  text-align: center;
1083
1048
  opacity: 0.7;
1084
- text-align: center;
1085
1049
  `
1086
1050
  };
1087
1051
 
@@ -1102,7 +1066,7 @@ var ChatScreen = ({
1102
1066
  const connected = status === "connected";
1103
1067
  const [showScrollBtn, setShowScrollBtn] = (0, import_react4.useState)(false);
1104
1068
  const lastMsg = messages[messages.length - 1];
1105
- const isThinking = connected && (lastMsg == null ? void 0 : lastMsg.direction) === "INBOUND";
1069
+ const isThinking = connected && (lastMsg == null ? void 0 : lastMsg.direction) === "OUTBOUND";
1106
1070
  (0, import_react4.useEffect)(() => {
1107
1071
  var _a;
1108
1072
  (_a = bottomRef.current) == null ? void 0 : _a.scrollIntoView({ behavior: "smooth" });
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/index.ts","../src/components/ChatWidget.tsx","../src/lib/upload.ts","../src/hooks/useChat.ts","../src/lib/socket.ts","../src/store/chatStore.ts","../src/components/FloatingButton.tsx","../src/components/ChatPanel.tsx","../src/components/HomeScreen.tsx","../src/components/ChatScreen.tsx","../src/components/MessageBubble.tsx","../src/components/MarkdownRenderer.tsx","../src/components/ChatInput.tsx"],"sourcesContent":["export { ChatWidget } from './components/ChatWidget'\nexport type { ChatWidgetProps } from './components/ChatWidget'\nexport { useChat } from './hooks/useChat'\nexport { useChatStore } from './store/chatStore'\nexport { loadVisitorId, saveVisitorId, clearVisitorId } from './lib/upload'\nexport * from './types'","import React, { useEffect, useState } from 'react'\nimport { injectGlobal } from '@emotion/css'\nimport { ChatConfig } from '../types'\nimport { loadVisitorId } from '../lib/upload'\nimport { useChat } from '../hooks/useChat'\nimport { useChatStore } from '../store/chatStore'\nimport { FloatingButton } from './FloatingButton'\nimport { ChatPanel } from './ChatPanel'\nimport { HomeScreen } from './HomeScreen'\nimport { ChatScreen } from './ChatScreen'\n\nexport type ChatWidgetProps = {\n config: ChatConfig\n}\n\ntype View = 'home' | 'chat'\n\nconst LIGHT_VARS = `\n --wds-bg: oklch(1 0 0);\n --wds-fg: oklch(0.145 0 0);\n --wds-muted: oklch(0.556 0 0);\n --wds-muted-bg: oklch(0.97 0 0);\n --wds-border: oklch(0.922 0 0);\n`\n\nconst DARK_VARS = `\n --wds-bg: oklch(0.145 0 0);\n --wds-fg: oklch(0.985 0 0);\n --wds-muted: oklch(0.708 0 0);\n --wds-muted-bg: oklch(0.205 0 0);\n --wds-border: oklch(1 0 0 / 10%);\n`\n\nfunction buildPrimaryVars(color: string) {\n return `\n --wds-primary: ${color};\n --wds-primary-soft: color-mix(in oklch, ${color} 12%, transparent);\n --wds-primary-border: color-mix(in oklch, ${color} 40%, transparent);\n `\n}\n\nconst DEFAULT_PRIMARY = 'oklch(0.5811 0.2268 259.15)'\n\nfunction buildThemeStyle(theme: 'light' | 'dark' | 'system', primaryColor: string) {\n const primary = buildPrimaryVars(primaryColor)\n\n if (theme === 'light') {\n return `\n [data-wds-root] {\n ${LIGHT_VARS}\n ${primary}\n }\n `\n }\n\n if (theme === 'dark') {\n return `\n [data-wds-root] {\n ${DARK_VARS}\n ${primary}\n }\n `\n }\n\n return `\n [data-wds-root] {\n ${LIGHT_VARS}\n ${primary}\n }\n @media (prefers-color-scheme: dark) {\n [data-wds-root] {\n ${DARK_VARS}\n --wds-primary-soft: color-mix(in oklch, ${primaryColor} 15%, transparent);\n }\n }\n `\n}\n\nexport const ChatWidget: React.FC<ChatWidgetProps> = ({ config }) => {\n const [isOpen, setIsOpen] = useState(false)\n const [isExpanded, setIsExpanded] = useState(false)\n const [view, setView] = useState<View>('home')\n const [visitorId] = useState<string | undefined>(\n () => config.visitorId ?? loadVisitorId() ?? undefined\n )\n\n const reset = useChatStore((s) => s.reset)\n\n const resolvedConfig: ChatConfig = {\n ...config,\n visitorId,\n }\n\n const hasHistory = !!visitorId\n\n const { status, messages, error, sendMessage, sendFile } = useChat(resolvedConfig)\n\n const handleNewConversation = () => {\n reset()\n setView('chat')\n }\n\n useEffect(() => {\n const isMobile = window.innerWidth <= 480\n if (isMobile) {\n document.body.style.overflow = isOpen ? 'hidden' : ''\n }\n return () => {\n document.body.style.overflow = ''\n }\n }, [isOpen])\n\n useEffect(() => {\n const theme = config.theme ?? 'system'\n const primaryColor = config.primaryColor ?? DEFAULT_PRIMARY\n const style = buildThemeStyle(theme, primaryColor)\n const el = document.createElement('style')\n el.setAttribute('data-wds-theme', '')\n el.textContent = style\n document.head.appendChild(el)\n return () => {\n document.head.removeChild(el)\n }\n }, [config.theme, config.primaryColor])\n\n return (\n <>\n <FloatingButton\n isOpen={isOpen}\n onToggle={() => setIsOpen((p) => !p)}\n />\n\n <ChatPanel\n isOpen={isOpen}\n isExpanded={isExpanded}\n >\n {view === 'home' ? (\n <HomeScreen\n onStartChat={handleNewConversation}\n onContinueChat={() => setView('chat')}\n hasHistory={hasHistory}\n onExpand={() => setIsExpanded((p) => !p)}\n isExpanded={isExpanded}\n />\n ) : (\n <ChatScreen\n messages={messages}\n onSendText={sendMessage}\n onSendFile={sendFile}\n onBack={() => setView('home')}\n onExpand={() => setIsExpanded((p) => !p)}\n isExpanded={isExpanded}\n status={status}\n error={error}\n />\n )}\n </ChatPanel>\n </>\n )\n}\n\ninjectGlobal`\n [data-wds-root] * {\n box-sizing: border-box;\n text-align: left;\n }\n`","import type { ChatConfig } from \"../types\";\n\nconst VISITOR_ID_KEY = \"waysdrop_visitor_id\";\n\nexport const saveVisitorId = (id: string): void => {\n if (typeof window === 'undefined') return;\n localStorage.setItem(VISITOR_ID_KEY, id);\n};\n\nexport const loadVisitorId = (): string | null => {\n if (typeof window === 'undefined') return null;\n return localStorage.getItem(VISITOR_ID_KEY);\n};\n\nexport const clearVisitorId = (): void => {\n if (typeof window === 'undefined') return;\n localStorage.removeItem(VISITOR_ID_KEY);\n};\n\nexport const uploadFile = async (\n file: File,\n config: ChatConfig,\n): Promise<string> => {\n const formData = new FormData();\n formData.append(\"files\", file);\n\n const headers: HeadersInit = {};\n if (config.token) headers[\"Authorization\"] = `Bearer ${config.token}`;\n\n const res = await fetch(`${config.apiUrl}/file/bulk-upload`, {\n method: \"POST\",\n headers,\n body: formData,\n });\n\n if (!res.ok) {\n throw new Error(\"File upload failed\");\n }\n\n const json = await res.json();\n\n if (!json.success || !json.data?.urls?.length) {\n throw new Error(json.message || \"File upload failed\");\n }\n\n const first = json.data.urls[0];\n if (typeof first !== \"string\") {\n throw new Error(first?.error || \"File upload failed\");\n }\n\n return first;\n};","import { useEffect, useCallback } from 'react'\nimport { createSocket, getSocket, destroySocket } from '../lib/socket'\nimport { saveVisitorId, uploadFile } from '../lib/upload'\nimport { useChatStore } from '../store/chatStore'\nimport type {\n ChatConfig,\n ConnectedPayload,\n SupportMessageSentPayload,\n SupportNewMessagePayload,\n SocketError,\n SupportSendMessageDTO,\n VisitorInfo,\n} from '../types'\n\nexport const useChat = (config: ChatConfig) => {\n const {\n status,\n role,\n visitorId,\n chatId,\n messages,\n error,\n visitorInfo,\n setStatus,\n setRole,\n setVisitorId,\n setChatId,\n addMessage,\n setError,\n setVisitorInfo,\n reset,\n } = useChatStore()\n\n useEffect(() => {\n const socket = createSocket(config)\n\n setStatus('connecting')\n socket.connect()\n\n socket.on('connected', (payload: ConnectedPayload) => {\n setStatus('connected')\n setRole(payload.role)\n\n if (payload.role === 'VISITOR') {\n saveVisitorId(payload.visitorId)\n setVisitorId(payload.visitorId)\n }\n })\n\n socket.on('support-message-sent', (payload: SupportMessageSentPayload) => {\n setChatId(payload.chatId)\n addMessage(payload.message)\n })\n\n socket.on('support-new-message', (payload: SupportNewMessagePayload) => {\n setChatId(payload.chatId)\n addMessage(payload.message)\n })\n\n socket.on('error', (err: SocketError) => {\n setError(err)\n setStatus('error')\n })\n\n return () => {\n destroySocket()\n reset()\n }\n }, [config.token])\n\n const sendMessage = useCallback(\n (content: string, info?: VisitorInfo) => {\n const socket = getSocket(config)\n\n const dto: SupportSendMessageDTO = {\n content,\n externalId: `msg-${Date.now()}`,\n ...(info ?? visitorInfo\n ? {\n email: (info ?? visitorInfo)!.email,\n name: (info ?? visitorInfo)?.name,\n phone: (info ?? visitorInfo)?.phone,\n }\n : {}),\n }\n\n socket.emit('support-send-message', dto)\n },\n [config, visitorInfo]\n )\n\n const sendFile = useCallback(\n async (file: File, content?: string, info?: VisitorInfo) => {\n const url = await uploadFile(file, config)\n\n const socket = getSocket(config)\n\n const dto: SupportSendMessageDTO = {\n file: url,\n ...(content ? { content } : {}),\n externalId: `file-${Date.now()}`,\n ...(info ?? visitorInfo\n ? {\n email: (info ?? visitorInfo)!.email,\n name: (info ?? visitorInfo)?.name,\n phone: (info ?? visitorInfo)?.phone,\n }\n : {}),\n }\n\n socket.emit('support-send-message', dto)\n },\n [config, visitorInfo]\n )\n\n return {\n status,\n role,\n visitorId,\n chatId,\n messages,\n error,\n visitorInfo,\n setVisitorInfo,\n sendMessage,\n sendFile,\n }\n}","import { io, Socket } from 'socket.io-client'\nimport type { ChatConfig } from '../types'\n\nlet socket: Socket | null = null\n\nexport const createSocket = (config: ChatConfig): Socket => {\n if (socket) {\n socket.disconnect()\n socket = null\n }\n\n const { serverUrl, token, visitorId } = config\n\n socket = io(serverUrl, {\n transports: ['websocket', 'polling'],\n auth: {\n ...(token ? { token } : {}),\n ...(visitorId ? { visitorId } : {}),\n },\n autoConnect: false,\n })\n\n return socket\n}\n\nexport const getSocket = (config: ChatConfig): Socket => {\n if (socket) return socket\n return createSocket(config)\n}\n\nexport const destroySocket = (): void => {\n if (socket) {\n socket.disconnect()\n socket = null\n }\n}","import { create } from 'zustand'\nimport type {\n ChatState,\n ChatMessage,\n UserRole,\n SocketError,\n VisitorInfo,\n ConnectionStatus,\n} from '../types'\n\ntype ChatActions = {\n setStatus: (status: ConnectionStatus) => void\n setRole: (role: UserRole) => void\n setVisitorId: (id: string) => void\n setChatId: (id: string) => void\n addMessage: (message: ChatMessage) => void\n setError: (error: SocketError | null) => void\n setVisitorInfo: (info: VisitorInfo) => void\n reset: () => void\n}\n\nconst initialState: ChatState = {\n status: 'idle',\n role: null,\n visitorId: null,\n chatId: null,\n messages: [],\n error: null,\n visitorInfo: null,\n}\n\nexport const useChatStore = create<ChatState & ChatActions>((set) => ({\n ...initialState,\n\n setStatus: (status) => set({ status }),\n setRole: (role) => set({ role }),\n setVisitorId: (id) => set({ visitorId: id }),\n setChatId: (id) => set({ chatId: id }),\n addMessage: (message) =>\n set((state) => ({\n messages: [...state.messages, message],\n })),\n setError: (error) => set({ error }),\n setVisitorInfo: (info) => set({ visitorInfo: info }),\n reset: () => set(initialState),\n}))","import React, { useEffect, useState } from \"react\";\nimport { css } from \"@emotion/css\";\n\nconst BUTTON_SIZE = 56;\n\ninterface Props {\n isOpen: boolean;\n onToggle: () => void;\n}\n\nexport const FloatingButton: React.FC<Props> = ({ isOpen, onToggle }) => {\n const [isMobile, setIsMobile] = useState(false);\n\n useEffect(() => {\n const check = () => setIsMobile(window.innerWidth <= 480);\n check();\n window.addEventListener(\"resize\", check);\n return () => window.removeEventListener(\"resize\", check);\n }, []);\n\n if (isMobile && isOpen) {\n return (\n <button\n className={styles.mobileCloseBtn}\n onClick={onToggle}\n type=\"button\"\n >\n <svg\n width=\"22\"\n height=\"22\"\n viewBox=\"0 0 24 24\"\n fill=\"none\"\n stroke=\"currentColor\"\n strokeWidth=\"2.5\"\n strokeLinecap=\"round\"\n >\n <line x1=\"18\" y1=\"6\" x2=\"6\" y2=\"18\" />\n <line x1=\"6\" y1=\"6\" x2=\"18\" y2=\"18\" />\n </svg>\n </button>\n );\n }\n\n return (\n <button className={styles.btn} onClick={onToggle} type=\"button\">\n <span className={styles.icon(!isOpen)}>\n <svg width=\"24\" height=\"24\" viewBox=\"0 0 24 24\" fill=\"currentColor\">\n <path d=\"M20 2H4a2 2 0 0 0-2 2v18l4-4h14a2 2 0 0 0 2-2V4a2 2 0 0 0-2-2z\" />\n </svg>\n </span>\n <span className={styles.icon(isOpen)}>\n <svg\n width=\"20\"\n height=\"20\"\n viewBox=\"0 0 24 24\"\n fill=\"none\"\n stroke=\"currentColor\"\n strokeWidth=\"2.5\"\n strokeLinecap=\"round\"\n >\n <line x1=\"18\" y1=\"6\" x2=\"6\" y2=\"18\" />\n <line x1=\"6\" y1=\"6\" x2=\"18\" y2=\"18\" />\n </svg>\n </span>\n </button>\n );\n};\n\nconst styles = {\n btn: css`\n position: fixed;\n right: 30px;\n bottom: 20px;\n width: ${BUTTON_SIZE}px;\n height: ${BUTTON_SIZE}px;\n border-radius: 50%;\n background: var(--wds-primary);\n color: #fff;\n border: none;\n cursor: pointer;\n box-shadow: 0 4px 20px rgba(0, 0, 0, 0.18);\n z-index: 999999;\n display: flex;\n align-items: center;\n justify-content: center;\n user-select: none;\n -webkit-user-select: none;\n &:hover {\n opacity: 0.92;\n }\n `,\n mobileCloseBtn: css`\n position: fixed;\n top: 16px;\n right: 20px;\n width: ${BUTTON_SIZE}px;\n height: ${BUTTON_SIZE}px;\n border-radius: 50%;\n background: var(--wds-primary);\n color: #fff;\n border: none;\n cursor: pointer;\n box-shadow: 0 4px 20px rgba(0, 0, 0, 0.25);\n z-index: 999999;\n display: flex;\n align-items: center;\n justify-content: center;\n `,\n icon: (visible: boolean) => css`\n position: absolute;\n display: flex;\n align-items: center;\n justify-content: center;\n transition:\n opacity 0.2s,\n transform 0.2s;\n opacity: ${visible ? 1 : 0};\n transform: ${visible ? \"scale(1)\" : \"scale(0.6) rotate(30deg)\"};\n pointer-events: ${visible ? \"auto\" : \"none\"};\n `,\n};\n","import React from 'react'\nimport { css } from '@emotion/css'\n\ninterface Props {\n isOpen: boolean\n isExpanded: boolean\n children: React.ReactNode\n}\n\nexport const ChatPanel: React.FC<Props> = ({ isOpen, isExpanded, children }) => {\n return (\n <div data-wds-root className={styles.panel(isOpen, isExpanded)}>\n <div className={styles.inner}>{children}</div>\n </div>\n )\n}\n\nconst styles = {\n panel: (isOpen: boolean, isExpanded: boolean) => css`\n position: fixed;\n bottom: 86px;\n z-index: 999998;\n transition: opacity 0.2s, transform 0.25s cubic-bezier(0.34, 1.2, 0.64, 1);\n opacity: ${isOpen ? 1 : 0};\n pointer-events: ${isOpen ? 'auto' : 'none'};\n\n ${isExpanded\n ? `\n width: min(760px, calc(100vw - 32px));\n height: min(780px, calc(100vh - 120px));\n border-radius: 20px;\n box-shadow: 0 20px 60px rgba(0,0,0,0.2), 0 4px 16px rgba(0,0,0,0.1);\n left: 50%;\n right: auto;\n translate: -50% 0;\n transform: ${isOpen ? 'scale(1)' : 'scale(0.95)'};\n transform-origin: bottom center;\n `\n : `\n width: 400px;\n height: 620px;\n border-radius: 20px;\n box-shadow: 0 12px 48px rgba(0,0,0,0.16), 0 2px 8px rgba(0,0,0,0.08);\n right: 22px;\n transform: ${isOpen ? 'translateY(0) scale(1)' : 'translateY(16px) scale(0.97)'};\n `}\n\n overflow: hidden;\n\n @media (max-width: 480px) {\n top: 0 !important;\n left: 0 !important;\n right: 0 !important;\n bottom: 0 !important;\n width: 100% !important;\n height: 100% !important;\n border-radius: 0 !important;\n translate: none !important;\n }\n `,\n inner: css`\n width: 100%;\n height: 100%;\n overflow: hidden;\n border-radius: inherit;\n `,\n}","import React from 'react'\nimport { css } from '@emotion/css'\n\ninterface Props {\n onStartChat: () => void\n onContinueChat: () => void\n hasHistory: boolean\n onExpand: () => void\n isExpanded: boolean\n}\n\nexport const HomeScreen: React.FC<Props> = ({\n onStartChat,\n onContinueChat,\n hasHistory,\n onExpand,\n isExpanded,\n}) => {\n return (\n <div className={styles.wrapper}>\n <div className={styles.topBar}>\n <div className={styles.logoMark}>\n <img\n src=\"https://cdn.waysdrop.com/bulk/horizon_20260411202129966_d25edae2.png\"\n alt=\"Waysdrop\"\n style={{ width: '100%', height: '100%', objectFit: 'contain' }}\n />\n </div>\n <button className={styles.expandBtn} onClick={onExpand}>\n {isExpanded ? (\n <svg width=\"15\" height=\"15\" viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" strokeWidth=\"2\" strokeLinecap=\"round\" strokeLinejoin=\"round\">\n <polyline points=\"4 14 10 14 10 20\"/><polyline points=\"20 10 14 10 14 4\"/>\n <line x1=\"10\" y1=\"14\" x2=\"3\" y2=\"21\"/><line x1=\"21\" y1=\"3\" x2=\"14\" y2=\"10\"/>\n </svg>\n ) : (\n <svg width=\"15\" height=\"15\" viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" strokeWidth=\"2\" strokeLinecap=\"round\" strokeLinejoin=\"round\">\n <polyline points=\"15 3 21 3 21 9\"/><polyline points=\"9 21 3 21 3 15\"/>\n <line x1=\"21\" y1=\"3\" x2=\"14\" y2=\"10\"/><line x1=\"3\" y1=\"21\" x2=\"10\" y2=\"14\"/>\n </svg>\n )}\n </button>\n </div>\n\n <div className={styles.hero}>\n <h2 className={styles.heroTitle}>Hi there! ๐Ÿ‘‹</h2>\n <p className={styles.heroSub}>We're here to help. Ask us anything or share your feedback.</p>\n </div>\n\n <div className={styles.section}>\n <p className={styles.sectionLabel}>Conversations</p>\n {hasHistory ? (\n <button className={styles.conversationCard} onClick={onContinueChat}>\n <div className={styles.cardIcon}>\n <svg width=\"16\" height=\"16\" viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" 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 </div>\n <div className={styles.cardBody}>\n <span className={styles.cardTitle}>Continue conversation</span>\n <span className={styles.cardSub}>Tap to resume your last chat</span>\n </div>\n <svg width=\"14\" height=\"14\" viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" strokeWidth=\"2\" strokeLinecap=\"round\" strokeLinejoin=\"round\">\n <polyline points=\"9 18 15 12 9 6\"/>\n </svg>\n </button>\n ) : (\n <div className={styles.emptyHistory}>\n <svg width=\"32\" height=\"32\" viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" strokeWidth=\"1.5\" strokeLinecap=\"round\" strokeLinejoin=\"round\" style={{ opacity: 0.25 }}>\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 <p>No previous conversations</p>\n </div>\n )}\n </div>\n\n <div className={styles.footer}>\n <button className={styles.startBtn} onClick={onStartChat}>\n New conversation\n <svg width=\"15\" height=\"15\" viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" strokeWidth=\"2.5\" strokeLinecap=\"round\" strokeLinejoin=\"round\">\n <polyline points=\"9 18 15 12 9 6\"/>\n </svg>\n </button>\n <p className={styles.poweredBy}>Powered by Waysdrop</p>\n </div>\n </div>\n )\n}\n\nconst styles = {\n wrapper: css`\n display: flex;\n flex-direction: column;\n height: 100%;\n background: var(--wds-bg);\n text-align: left;\n `,\n topBar: css`\n display: flex;\n align-items: center;\n justify-content: space-between;\n padding: 18px 18px 0;\n flex-shrink: 0;\n `,\n logoMark: css`\n width: 48px;\n height: 48px;\n flex-shrink: 0;\n `,\n expandBtn: css`\n background: none;\n border: none;\n cursor: pointer;\n color: var(--wds-muted);\n padding: 8px;\n border-radius: 8px;\n display: flex;\n align-items: center;\n justify-content: center;\n transition: color 0.15s, background 0.15s;\n &:hover {\n color: var(--wds-fg);\n background: var(--wds-muted-bg);\n }\n @media (max-width: 480px) {\n display: none;\n }\n `,\n hero: css`\n padding: 20px 20px 16px;\n display: flex;\n flex-direction: column;\n align-items: flex-start;\n gap: 10px;\n flex-shrink: 0;\n `,\n heroTitle: css`\n font-size: 1.375rem;\n font-weight: 700;\n color: var(--wds-fg);\n margin: 0;\n line-height: 1.2;\n text-align: left;\n `,\n heroSub: css`\n font-size: 0.9375rem;\n color: var(--wds-muted);\n margin: 0;\n line-height: 1.6;\n text-align: left;\n `,\n section: css`\n flex: 1;\n padding: 4px 18px 0;\n overflow-y: auto;\n `,\n sectionLabel: css`\n font-size: 11px;\n font-weight: 600;\n letter-spacing: 0.07em;\n text-transform: uppercase;\n color: var(--wds-muted);\n margin: 0 0 12px 2px;\n text-align: left;\n `,\n conversationCard: css`\n display: flex;\n align-items: center;\n gap: 14px;\n width: 100%;\n padding: 14px 16px;\n background: var(--wds-muted-bg);\n border: 1px solid var(--wds-border);\n border-radius: 14px;\n cursor: pointer;\n text-align: left;\n transition: border-color 0.15s, background 0.15s;\n color: var(--wds-fg);\n &:hover {\n border-color: var(--wds-primary);\n background: var(--wds-primary-soft);\n }\n `,\n cardIcon: css`\n width: 38px;\n height: 38px;\n border-radius: 10px;\n background: var(--wds-primary-soft);\n color: var(--wds-primary);\n display: flex;\n align-items: center;\n justify-content: center;\n flex-shrink: 0;\n `,\n cardBody: css`\n flex: 1;\n display: flex;\n flex-direction: column;\n gap: 3px;\n `,\n cardTitle: css`\n font-size: 0.875rem;\n font-weight: 600;\n color: var(--wds-fg);\n text-align: left;\n `,\n cardSub: css`\n font-size: 12px;\n color: var(--wds-muted);\n text-align: left;\n `,\n emptyHistory: css`\n display: flex;\n flex-direction: column;\n align-items: center;\n gap: 10px;\n padding: 40px 0;\n color: var(--wds-muted);\n font-size: 12px;\n `,\n footer: css`\n padding: 18px 18px 16px;\n display: flex;\n flex-direction: column;\n gap: 12px;\n align-items: center;\n flex-shrink: 0;\n border-top: 1px solid var(--wds-border);\n `,\n startBtn: css`\n display: flex;\n align-items: center;\n justify-content: center;\n gap: 6px;\n width: 100%;\n padding: 13px 16px;\n background: var(--wds-primary);\n color: #fff;\n border: none;\n border-radius: 14px;\n font-size: 0.9375rem;\n font-weight: 600;\n cursor: pointer;\n transition: opacity 0.15s;\n font-family: inherit;\n &:hover { opacity: 0.88; }\n `,\n poweredBy: css`\n font-size: 11px;\n color: var(--wds-muted);\n margin: 0;\n opacity: 0.7;\n `,\n}","import React, { useEffect, useRef, useState } from \"react\";\nimport { css, keyframes } from \"@emotion/css\";\nimport { ChatMessage } from \"../types\";\nimport { MessageBubble } from \"./MessageBubble\";\nimport { ChatInput } from \"./ChatInput\";\n\ninterface Props {\n messages: ChatMessage[];\n onSendText: (content: string) => void;\n onSendFile: (file: File, content?: string) => Promise<void>;\n onBack: () => void;\n onExpand: () => void;\n isExpanded: boolean;\n status: string;\n error: { code: number; message: string } | null;\n}\n\nexport const ChatScreen: React.FC<Props> = ({\n messages,\n onSendText,\n onSendFile,\n onBack,\n onExpand,\n isExpanded,\n status,\n error,\n}) => {\n const bottomRef = useRef<HTMLDivElement>(null);\n const scrollRef = useRef<HTMLDivElement>(null);\n const connected = status === \"connected\";\n const [showScrollBtn, setShowScrollBtn] = useState(false);\n\n const lastMsg = messages[messages.length - 1];\n const isThinking = connected && lastMsg?.direction === \"INBOUND\";\n\n useEffect(() => {\n bottomRef.current?.scrollIntoView({ behavior: \"smooth\" });\n }, [messages]);\n\n const handleScroll = () => {\n const el = scrollRef.current;\n if (!el) return;\n setShowScrollBtn(el.scrollHeight - el.scrollTop - el.clientHeight > 80);\n };\n\n return (\n <div className={styles.wrapper}>\n <div className={styles.header}>\n <button className={styles.iconBtn} onClick={onBack}>\n <svg\n width=\"18\"\n height=\"18\"\n viewBox=\"0 0 24 24\"\n fill=\"none\"\n stroke=\"currentColor\"\n strokeWidth=\"2\"\n strokeLinecap=\"round\"\n strokeLinejoin=\"round\"\n >\n <polyline points=\"15 18 9 12 15 6\" />\n </svg>\n </button>\n\n <div className={styles.headerCenter}>\n <span className={styles.headerTitle}>Support</span>\n <span className={styles.statusDot(connected)} />\n <span className={styles.statusLabel}>\n {connected ? \"Online\" : \"Connecting...\"}\n </span>\n </div>\n\n <button className={styles.expandBtn} onClick={onExpand}>\n {isExpanded ? (\n <svg\n width=\"16\"\n height=\"16\"\n viewBox=\"0 0 24 24\"\n fill=\"none\"\n stroke=\"currentColor\"\n strokeWidth=\"2\"\n strokeLinecap=\"round\"\n strokeLinejoin=\"round\"\n >\n <polyline points=\"4 14 10 14 10 20\" />\n <polyline points=\"20 10 14 10 14 4\" />\n <line x1=\"10\" y1=\"14\" x2=\"3\" y2=\"21\" />\n <line x1=\"21\" y1=\"3\" x2=\"14\" y2=\"10\" />\n </svg>\n ) : (\n <svg\n width=\"16\"\n height=\"16\"\n viewBox=\"0 0 24 24\"\n fill=\"none\"\n stroke=\"currentColor\"\n strokeWidth=\"2\"\n strokeLinecap=\"round\"\n strokeLinejoin=\"round\"\n >\n <polyline points=\"15 3 21 3 21 9\" />\n <polyline points=\"9 21 3 21 3 15\" />\n <line x1=\"21\" y1=\"3\" x2=\"14\" y2=\"10\" />\n <line x1=\"3\" y1=\"21\" x2=\"10\" y2=\"14\" />\n </svg>\n )}\n </button>\n </div>\n\n <div className={styles.messagesWrap}>\n <div\n className={styles.messages}\n ref={scrollRef}\n onScroll={handleScroll}\n >\n {error && <div className={styles.errorBanner}>{error.message}</div>}\n {messages.length === 0 && connected && (\n <div className={styles.emptyState}>\n <p>Send a message to start the conversation.</p>\n </div>\n )}\n {messages.map((msg) => (\n <MessageBubble key={msg.id} message={msg} />\n ))}\n <div ref={bottomRef} />\n </div>\n\n {showScrollBtn && (\n <button\n className={styles.scrollBtn}\n onClick={() =>\n bottomRef.current?.scrollIntoView({ behavior: \"smooth\" })\n }\n >\n <svg\n width=\"14\"\n height=\"14\"\n viewBox=\"0 0 24 24\"\n fill=\"none\"\n stroke=\"currentColor\"\n strokeWidth=\"2.5\"\n strokeLinecap=\"round\"\n strokeLinejoin=\"round\"\n >\n <polyline points=\"6 9 12 15 18 9\" />\n </svg>\n </button>\n )}\n </div>\n\n <ChatInput\n onSendText={onSendText}\n onSendFile={onSendFile}\n disabled={!connected}\n isThinking={isThinking}\n />\n </div>\n );\n};\n\nconst pulse = keyframes`\n 0%, 100% { opacity: 1; }\n 50% { opacity: 0.4; }\n`;\n\nconst styles = {\n wrapper: css`\n display: flex;\n flex-direction: column;\n height: 100%;\n background: var(--wds-bg);\n `,\n header: css`\n display: flex;\n align-items: center;\n gap: 10px;\n padding: 12px 14px;\n border-bottom: 1px solid var(--wds-border);\n flex-shrink: 0;\n `,\n headerCenter: css`\n flex: 1;\n display: flex;\n align-items: center;\n gap: 6px;\n `,\n headerTitle: css`\n font-size: 0.875rem;\n font-weight: 600;\n color: var(--wds-fg);\n `,\n statusDot: (connected: boolean) => css`\n width: 7px;\n height: 7px;\n border-radius: 50%;\n flex-shrink: 0;\n background: ${connected ? \"#22c55e\" : \"#f59e0b\"};\n animation: ${connected ? \"none\" : `${pulse} 1.2s ease-in-out infinite`};\n `,\n statusLabel: css`\n font-size: 11px;\n color: var(--wds-muted);\n `,\n iconBtn: css`\n background: none;\n border: none;\n cursor: pointer;\n color: var(--wds-muted);\n padding: 6px;\n border-radius: 8px;\n display: flex;\n align-items: center;\n justify-content: center;\n flex-shrink: 0;\n transition:\n color 0.15s,\n background 0.15s;\n &:hover {\n color: var(--wds-fg);\n background: var(--wds-muted-bg);\n }\n `,\n expandBtn: css`\n background: none;\n border: none;\n cursor: pointer;\n color: var(--wds-muted);\n padding: 6px;\n border-radius: 8px;\n display: flex;\n align-items: center;\n justify-content: center;\n flex-shrink: 0;\n transition:\n color 0.15s,\n background 0.15s;\n &:hover {\n color: var(--wds-fg);\n background: var(--wds-muted-bg);\n }\n @media (max-width: 480px) {\n display: none;\n }\n `,\n messagesWrap: css`\n flex: 1;\n position: relative;\n overflow: hidden;\n `,\n messages: css`\n position: absolute;\n inset: 0;\n overflow-y: auto;\n padding: 16px 14px;\n display: flex;\n flex-direction: column;\n gap: 10px;\n `,\n errorBanner: css`\n background: oklch(0.9705 0.0129 17.04);\n color: oklch(0.5054 0.1905 27.51);\n border: 1px solid oklch(0.8845 0.0592 18.27);\n border-radius: 8px;\n padding: 8px 12px;\n font-size: 12px;\n text-align: center;\n `,\n emptyState: css`\n flex: 1;\n display: flex;\n align-items: center;\n justify-content: center;\n color: var(--wds-muted);\n font-size: 13px;\n text-align: center;\n padding: 40px 20px;\n `,\n scrollBtn: css`\n position: absolute;\n bottom: 12px;\n left: 50%;\n transform: translateX(-50%);\n width: 30px;\n height: 30px;\n border-radius: 50%;\n background: var(--wds-bg);\n border: 1px solid var(--wds-border);\n color: var(--wds-muted);\n display: flex;\n align-items: center;\n justify-content: center;\n cursor: pointer;\n box-shadow: 0 2px 8px rgba(0, 0, 0, 0.12);\n transition:\n color 0.15s,\n border-color 0.15s;\n &:hover {\n color: var(--wds-primary);\n border-color: var(--wds-primary);\n }\n `,\n};\n","import React from 'react'\nimport { css } from '@emotion/css'\nimport { ChatMessage } from '../types'\nimport { MarkdownRenderer } from './MarkdownRenderer'\n\nfunction formatTime(iso: string): string {\n return new Date(iso).toLocaleTimeString([], { hour: '2-digit', minute: '2-digit' })\n}\n\ninterface Props {\n message: ChatMessage\n}\n\nexport const MessageBubble: React.FC<Props> = ({ message }) => {\n const isCustomer = message.direction === 'OUTBOUND'\n const isBot = message.senderRole === 'BOT'\n\n return (\n <div className={styles.row(isCustomer)}>\n <div className={styles.group(isCustomer)}>\n {isBot && <span className={styles.botLabel}>Ways AI</span>}\n <div className={styles.bubble(isCustomer)}>\n {message.file && (\n <a href={message.file} target=\"_blank\" rel=\"noreferrer\" className={styles.fileLink(!!message.content)}>\n ๐Ÿ“Ž View attachment\n </a>\n )}\n {message.content && (\n isBot\n ? <MarkdownRenderer content={message.content} />\n : <p className={styles.text}>{message.content}</p>\n )}\n </div>\n <span className={styles.time}>{formatTime(message.createdAt)}</span>\n </div>\n </div>\n )\n}\n\nconst styles = {\n row: (isCustomer: boolean) => css`\n display: flex;\n width: 100%;\n justify-content: ${isCustomer ? 'flex-start' : 'flex-end'};\n `,\n group: (isCustomer: boolean) => css`\n display: flex;\n flex-direction: column;\n max-width: 78%;\n gap: 4px;\n align-items: ${isCustomer ? 'flex-start' : 'flex-end'};\n `,\n botLabel: css`\n font-size: 10px;\n color: var(--wds-muted);\n padding: 0 4px;\n font-weight: 500;\n letter-spacing: 0.03em;\n `,\n bubble: (isCustomer: boolean) => css`\n border-radius: 18px;\n padding: 10px 14px;\n word-break: break-word;\n text-align: left;\n border-top-left-radius: ${isCustomer ? '4px' : '18px'};\n border-top-right-radius: ${isCustomer ? '18px' : '4px'};\n background: ${isCustomer ? 'var(--wds-muted-bg)' : 'var(--wds-primary)'};\n color: ${isCustomer ? 'var(--wds-fg)' : '#fff'};\n `,\n text: css`\n font-size: 0.875rem;\n line-height: 1.5;\n margin: 0;\n white-space: pre-wrap;\n text-align: left;\n `,\n fileLink: (hasContent: boolean) => css`\n font-size: 0.875rem;\n color: inherit;\n text-decoration: underline;\n display: block;\n text-align: left;\n ${hasContent ? 'margin-bottom: 6px;' : ''}\n `,\n time: css`\n font-size: 10px;\n color: var(--wds-muted);\n padding: 0 4px;\n `,\n}","import React from 'react'\nimport ReactMarkdown from 'react-markdown'\nimport { css } from '@emotion/css'\n\nconst markdownStyle = css`\n font-size: 0.875rem;\n line-height: 1.6;\n color: inherit;\n text-align: left;\n\n p {\n margin: 0 0 0.6rem 0;\n text-align: left;\n }\n p:last-child {\n margin-bottom: 0;\n }\n strong { font-weight: 600; }\n em { font-style: italic; }\n\n ul, ol {\n margin: 0.4rem 0 0.6rem 0;\n padding-left: 1.4rem;\n text-align: left;\n }\n ul { list-style-type: disc; }\n ol { list-style-type: decimal; }\n li {\n margin-bottom: 0.3rem;\n }\n li > ul, li > ol {\n margin: 0.25rem 0 0.25rem 0;\n padding-left: 1.2rem;\n }\n li:last-child { margin-bottom: 0; }\n\n hr {\n border: none;\n border-top: 1px solid rgba(255, 255, 255, 0.25);\n margin: 0.75rem 0;\n }\n\n code {\n font-family: monospace;\n font-size: 0.8rem;\n background: rgba(255,255,255,0.15);\n border-radius: 4px;\n padding: 0.1rem 0.35rem;\n }\n pre {\n background: rgba(255,255,255,0.1);\n border-radius: 8px;\n padding: 0.75rem 1rem;\n overflow-x: auto;\n margin: 0.5rem 0;\n }\n pre code {\n background: none;\n padding: 0;\n font-size: 0.78rem;\n }\n blockquote {\n border-left: 3px solid rgba(255,255,255,0.25);\n margin: 0.5rem 0;\n padding-left: 0.75rem;\n opacity: 0.8;\n }\n a {\n color: rgba(255,255,255,0.85);\n text-decoration: underline;\n }\n h1, h2, h3 {\n font-weight: 600;\n margin: 0.6rem 0 0.3rem;\n line-height: 1.3;\n text-align: left;\n }\n h1 { font-size: 1rem; }\n h2 { font-size: 0.95rem; }\n h3 { font-size: 0.875rem; }\n`\n\ninterface Props {\n content: string\n}\n\nexport const MarkdownRenderer: React.FC<Props> = ({ content }) => {\n return (\n <div className={markdownStyle}>\n <ReactMarkdown>{content}</ReactMarkdown>\n </div>\n )\n}","import React, { useState, useRef, useCallback, KeyboardEvent } from 'react'\nimport { css, keyframes } from '@emotion/css'\n\nconst spin = keyframes`\n to { transform: rotate(360deg); }\n`\n\nconst pulse = keyframes`\n 0%, 100% { opacity: 0.4; transform: scaleY(0.6); }\n 50% { opacity: 1; transform: scaleY(1); }\n`\n\ninterface Props {\n onSendText: (content: string) => void\n onSendFile: (file: File, content?: string) => Promise<void>\n disabled?: boolean\n isThinking?: boolean\n}\n\nexport const ChatInput: React.FC<Props> = ({ onSendText, onSendFile, disabled, isThinking }) => {\n const [value, setValue] = useState('')\n const [uploading, setUploading] = useState(false)\n const [pendingFile, setPendingFile] = useState<File | null>(null)\n const [pendingPreview, setPendingPreview] = useState<string | null>(null)\n const textareaRef = useRef<HTMLTextAreaElement>(null)\n const fileInputRef = useRef<HTMLInputElement>(null)\n\n const handleSend = useCallback(() => {\n const trimmed = value.trim()\n if ((!trimmed && !pendingFile) || disabled || uploading) return\n\n if (pendingFile) {\n setUploading(true)\n onSendFile(pendingFile, trimmed || undefined).finally(() => {\n setUploading(false)\n setPendingFile(null)\n setPendingPreview(null)\n setValue('')\n })\n } else if (trimmed) {\n onSendText(trimmed)\n setValue('')\n }\n\n textareaRef.current?.focus()\n }, [value, pendingFile, disabled, uploading, onSendText, onSendFile])\n\n const handleKeyDown = (e: KeyboardEvent<HTMLTextAreaElement>) => {\n if (e.key === 'Enter' && !e.shiftKey) {\n e.preventDefault()\n handleSend()\n }\n }\n\n const handleFileChange = (e: React.ChangeEvent<HTMLInputElement>) => {\n const file = e.target.files?.[0]\n if (!file) return\n if (!file.type.startsWith('image/')) return\n setPendingFile(file)\n const reader = new FileReader()\n reader.onload = (ev) => setPendingPreview(ev.target?.result as string)\n reader.readAsDataURL(file)\n e.target.value = ''\n }\n\n const canSend = (value.trim() || pendingFile) && !disabled && !uploading\n\n return (\n <div className={styles.wrapper}>\n {isThinking && (\n <div className={styles.thinkingBar}>\n <div className={styles.thinkingDots}>\n <span className={styles.dot(0)} />\n <span className={styles.dot(1)} />\n <span className={styles.dot(2)} />\n </div>\n <span className={styles.thinkingLabel}>Ways AI is typing...</span>\n </div>\n )}\n\n {pendingPreview && (\n <div className={styles.imagePreview}>\n <img src={pendingPreview} alt=\"attachment\" className={styles.previewImg} />\n <button className={styles.removeFile} onClick={() => { setPendingFile(null); setPendingPreview(null) }}>\n <svg width=\"12\" height=\"12\" viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" strokeWidth=\"2.5\" strokeLinecap=\"round\">\n <line x1=\"18\" y1=\"6\" x2=\"6\" y2=\"18\"/><line x1=\"6\" y1=\"6\" x2=\"18\" y2=\"18\"/>\n </svg>\n </button>\n </div>\n )}\n\n <div className={styles.inputRow}>\n <button\n className={styles.attachBtn}\n onClick={() => fileInputRef.current?.click()}\n disabled={disabled || uploading}\n type=\"button\"\n >\n <svg width=\"18\" height=\"18\" viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" strokeWidth=\"2\" strokeLinecap=\"round\" strokeLinejoin=\"round\">\n <rect x=\"3\" y=\"3\" width=\"18\" height=\"18\" rx=\"3\"/><circle cx=\"8.5\" cy=\"8.5\" r=\"1.5\"/><polyline points=\"21 15 16 10 5 21\"/>\n </svg>\n </button>\n\n <input\n ref={fileInputRef}\n type=\"file\"\n accept=\"image/*\"\n className={styles.hiddenInput}\n onChange={handleFileChange}\n />\n\n <textarea\n ref={textareaRef}\n className={styles.textarea}\n value={value}\n onChange={(e) => setValue(e.target.value)}\n onKeyDown={handleKeyDown}\n placeholder=\"Type a message...\"\n disabled={disabled || uploading}\n rows={1}\n />\n\n <button className={styles.sendBtn} onClick={handleSend} disabled={!canSend} type=\"button\">\n {uploading ? (\n <span className={styles.spinner} />\n ) : (\n <svg width=\"16\" height=\"16\" viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" strokeWidth=\"2.5\" strokeLinecap=\"round\" strokeLinejoin=\"round\">\n <line x1=\"12\" y1=\"19\" x2=\"12\" y2=\"5\"/><polyline points=\"5 12 12 5 19 12\"/>\n </svg>\n )}\n </button>\n </div>\n\n <p className={styles.hint}>Enter to send ยท Shift+Enter for new line</p>\n </div>\n )\n}\n\nconst styles = {\n wrapper: css`\n padding: 8px 12px 10px;\n border-top: 1px solid var(--wds-border);\n display: flex;\n flex-direction: column;\n gap: 6px;\n background: var(--wds-bg);\n flex-shrink: 0;\n `,\n thinkingBar: css`\n display: flex;\n align-items: center;\n gap: 8px;\n padding: 6px 2px 2px;\n `,\n thinkingDots: css`\n display: flex;\n align-items: center;\n gap: 3px;\n `,\n dot: (i: number) => css`\n width: 5px;\n height: 5px;\n border-radius: 50%;\n background: var(--wds-primary);\n animation: ${pulse} 1.2s ease-in-out infinite;\n animation-delay: ${i * 0.18}s;\n display: inline-block;\n `,\n thinkingLabel: css`\n font-size: 11px;\n color: var(--wds-muted);\n `,\n imagePreview: css`\n position: relative;\n width: fit-content;\n margin: 0 2px;\n `,\n previewImg: css`\n width: 72px;\n height: 72px;\n object-fit: cover;\n border-radius: 10px;\n border: 1px solid var(--wds-border);\n display: block;\n `,\n removeFile: css`\n position: absolute;\n top: -6px;\n right: -6px;\n width: 18px;\n height: 18px;\n border-radius: 50%;\n background: var(--wds-fg);\n color: var(--wds-bg);\n border: none;\n cursor: pointer;\n display: flex;\n align-items: center;\n justify-content: center;\n padding: 0;\n `,\n inputRow: css`\n display: flex;\n align-items: center;\n gap: 6px;\n background: var(--wds-muted-bg);\n border: 1px solid var(--wds-border);\n border-radius: 14px;\n padding: 4px 4px 4px 8px;\n transition: border-color 0.15s;\n &:focus-within {\n border-color: var(--wds-primary);\n background: var(--wds-bg);\n }\n `,\n attachBtn: css`\n background: none;\n border: none;\n cursor: pointer;\n color: var(--wds-muted);\n padding: 5px;\n border-radius: 8px;\n display: flex;\n align-items: center;\n justify-content: center;\n flex-shrink: 0;\n transition: color 0.15s;\n &:hover:not(:disabled) {\n color: var(--wds-primary);\n }\n &:disabled {\n opacity: 0.35;\n cursor: not-allowed;\n }\n `,\n hiddenInput: css`\n display: none;\n `,\n textarea: css`\n flex: 1;\n resize: none;\n border: none;\n padding: 6px 0;\n font-size: 0.875rem;\n font-family: inherit;\n line-height: 1.5;\n background: transparent;\n color: var(--wds-fg);\n outline: none;\n max-height: 120px;\n overflow-y: auto;\n &::placeholder { color: var(--wds-muted); }\n &:disabled {\n opacity: 0.5;\n cursor: not-allowed;\n }\n `,\n sendBtn: css`\n background: var(--wds-primary);\n border: none;\n border-radius: 10px;\n width: 34px;\n height: 34px;\n display: flex;\n align-items: center;\n justify-content: center;\n cursor: pointer;\n color: #fff;\n flex-shrink: 0;\n transition: opacity 0.15s;\n &:disabled {\n opacity: 0.35;\n cursor: not-allowed;\n }\n &:hover:not(:disabled) { opacity: 0.85; }\n `,\n spinner: css`\n width: 14px;\n height: 14px;\n border: 2px solid rgba(255,255,255,0.3);\n border-top-color: #fff;\n border-radius: 50%;\n animation: ${spin} 0.7s linear infinite;\n display: block;\n `,\n hint: css`\n font-size: 10px;\n color: var(--wds-muted);\n margin: 0;\n text-align: center;\n opacity: 0.7;\n text-align: center;\n `,\n}"],"mappings":"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","names":["import_react","import_css","socket","import_react","import_css","import_jsx_runtime","styles","import_css","import_jsx_runtime","styles","import_react","import_css","import_css","import_css","import_jsx_runtime","ReactMarkdown","import_jsx_runtime","styles","import_react","import_css","import_jsx_runtime","_a","styles","import_jsx_runtime","styles","pulse","import_jsx_runtime"]}
1
+ {"version":3,"sources":["../src/index.ts","../src/components/ChatWidget.tsx","../src/lib/upload.ts","../src/hooks/useChat.ts","../src/lib/socket.ts","../src/store/chatStore.ts","../src/components/FloatingButton.tsx","../src/components/ChatPanel.tsx","../src/components/HomeScreen.tsx","../src/components/ChatScreen.tsx","../src/components/MessageBubble.tsx","../src/components/MarkdownRenderer.tsx","../src/components/ChatInput.tsx"],"sourcesContent":["export { ChatWidget } from './components/ChatWidget'\nexport type { ChatWidgetProps } from './components/ChatWidget'\nexport { useChat } from './hooks/useChat'\nexport { useChatStore } from './store/chatStore'\nexport { loadVisitorId, saveVisitorId, clearVisitorId } from './lib/upload'\nexport * from './types'","import React, { useEffect, useState } from 'react'\nimport { injectGlobal } from '@emotion/css'\nimport { ChatConfig } from '../types'\nimport { loadVisitorId } from '../lib/upload'\nimport { useChat } from '../hooks/useChat'\nimport { useChatStore } from '../store/chatStore'\nimport { FloatingButton } from './FloatingButton'\nimport { ChatPanel } from './ChatPanel'\nimport { HomeScreen } from './HomeScreen'\nimport { ChatScreen } from './ChatScreen'\n\nexport type ChatWidgetProps = {\n config: ChatConfig\n}\n\ntype View = 'home' | 'chat'\n\nconst LIGHT_VARS = `\n --wds-bg: oklch(1 0 0);\n --wds-fg: oklch(0.145 0 0);\n --wds-muted: oklch(0.556 0 0);\n --wds-muted-bg: oklch(0.97 0 0);\n --wds-border: oklch(0.922 0 0);\n`\n\nconst DARK_VARS = `\n --wds-bg: oklch(0.145 0 0);\n --wds-fg: oklch(0.985 0 0);\n --wds-muted: oklch(0.708 0 0);\n --wds-muted-bg: oklch(0.205 0 0);\n --wds-border: oklch(1 0 0 / 10%);\n`\n\nfunction buildPrimaryVars(color: string) {\n return `\n --wds-primary: ${color};\n --wds-primary-soft: color-mix(in oklch, ${color} 12%, transparent);\n --wds-primary-border: color-mix(in oklch, ${color} 40%, transparent);\n `\n}\n\nconst DEFAULT_PRIMARY = 'oklch(0.5811 0.2268 259.15)'\n\nfunction buildThemeStyle(theme: 'light' | 'dark' | 'system', primaryColor: string) {\n const primary = buildPrimaryVars(primaryColor)\n\n if (theme === 'light') {\n return `\n [data-wds-root] {\n ${LIGHT_VARS}\n ${primary}\n }\n `\n }\n\n if (theme === 'dark') {\n return `\n [data-wds-root] {\n ${DARK_VARS}\n ${primary}\n }\n `\n }\n\n return `\n [data-wds-root] {\n ${LIGHT_VARS}\n ${primary}\n }\n @media (prefers-color-scheme: dark) {\n [data-wds-root] {\n ${DARK_VARS}\n --wds-primary-soft: color-mix(in oklch, ${primaryColor} 15%, transparent);\n }\n }\n `\n}\n\nexport const ChatWidget: React.FC<ChatWidgetProps> = ({ config }) => {\n const [isOpen, setIsOpen] = useState(false)\n const [isExpanded, setIsExpanded] = useState(false)\n const [view, setView] = useState<View>('home')\n const [visitorId] = useState<string | undefined>(\n () => config.visitorId ?? loadVisitorId() ?? undefined\n )\n\n const reset = useChatStore((s) => s.reset)\n\n const resolvedConfig: ChatConfig = {\n ...config,\n visitorId,\n }\n\n const hasHistory = !!visitorId\n\n const { status, messages, error, sendMessage, sendFile } = useChat(resolvedConfig)\n\n const handleNewConversation = () => {\n reset()\n setView('chat')\n }\n\n useEffect(() => {\n const isMobile = window.innerWidth <= 480\n if (isMobile) {\n document.body.style.overflow = isOpen ? 'hidden' : ''\n }\n return () => {\n document.body.style.overflow = ''\n }\n }, [isOpen])\n\n useEffect(() => {\n const theme = config.theme ?? 'system'\n const primaryColor = config.primaryColor ?? DEFAULT_PRIMARY\n const style = buildThemeStyle(theme, primaryColor)\n const el = document.createElement('style')\n el.setAttribute('data-wds-theme', '')\n el.textContent = style\n document.head.appendChild(el)\n return () => {\n document.head.removeChild(el)\n }\n }, [config.theme, config.primaryColor])\n\n return (\n <>\n <FloatingButton\n isOpen={isOpen}\n onToggle={() => setIsOpen((p) => !p)}\n />\n\n <ChatPanel\n isOpen={isOpen}\n isExpanded={isExpanded}\n >\n {view === 'home' ? (\n <HomeScreen\n onStartChat={handleNewConversation}\n onContinueChat={() => setView('chat')}\n hasHistory={hasHistory}\n onExpand={() => setIsExpanded((p) => !p)}\n isExpanded={isExpanded}\n />\n ) : (\n <ChatScreen\n messages={messages}\n onSendText={sendMessage}\n onSendFile={sendFile}\n onBack={() => setView('home')}\n onExpand={() => setIsExpanded((p) => !p)}\n isExpanded={isExpanded}\n status={status}\n error={error}\n />\n )}\n </ChatPanel>\n </>\n )\n}\n\ninjectGlobal`\n [data-wds-root] * {\n box-sizing: border-box;\n text-align: left;\n }\n`","import type { ChatConfig } from \"../types\";\n\nconst VISITOR_ID_KEY = \"waysdrop_visitor_id\";\n\nexport const saveVisitorId = (id: string): void => {\n if (typeof window === 'undefined') return;\n localStorage.setItem(VISITOR_ID_KEY, id);\n};\n\nexport const loadVisitorId = (): string | null => {\n if (typeof window === 'undefined') return null;\n return localStorage.getItem(VISITOR_ID_KEY);\n};\n\nexport const clearVisitorId = (): void => {\n if (typeof window === 'undefined') return;\n localStorage.removeItem(VISITOR_ID_KEY);\n};\n\nexport const uploadFile = async (\n file: File,\n config: ChatConfig,\n): Promise<string> => {\n const formData = new FormData();\n formData.append(\"files\", file);\n\n const headers: HeadersInit = {};\n if (config.token) headers[\"Authorization\"] = `Bearer ${config.token}`;\n\n const res = await fetch(`${config.apiUrl}/file/bulk-upload`, {\n method: \"POST\",\n headers,\n body: formData,\n });\n\n if (!res.ok) {\n throw new Error(\"File upload failed\");\n }\n\n const json = await res.json();\n\n if (!json.success || !json.data?.urls?.length) {\n throw new Error(json.message || \"File upload failed\");\n }\n\n const first = json.data.urls[0];\n if (typeof first !== \"string\") {\n throw new Error(first?.error || \"File upload failed\");\n }\n\n return first;\n};","import { useEffect, useCallback } from 'react'\nimport { createSocket, getSocket, destroySocket } from '../lib/socket'\nimport { saveVisitorId, uploadFile } from '../lib/upload'\nimport { useChatStore } from '../store/chatStore'\nimport type {\n ChatConfig,\n ConnectedPayload,\n SupportMessageSentPayload,\n SupportNewMessagePayload,\n SocketError,\n SupportSendMessageDTO,\n VisitorInfo,\n} from '../types'\n\nexport const useChat = (config: ChatConfig) => {\n const {\n status,\n role,\n visitorId,\n chatId,\n messages,\n error,\n visitorInfo,\n setStatus,\n setRole,\n setVisitorId,\n setChatId,\n addMessage,\n setError,\n setVisitorInfo,\n reset,\n } = useChatStore()\n\n useEffect(() => {\n const socket = createSocket(config)\n\n setStatus('connecting')\n socket.connect()\n\n socket.on('connected', (payload: ConnectedPayload) => {\n setStatus('connected')\n setRole(payload.role)\n\n if (payload.role === 'VISITOR') {\n saveVisitorId(payload.visitorId)\n setVisitorId(payload.visitorId)\n }\n })\n\n socket.on('support-message-sent', (payload: SupportMessageSentPayload) => {\n setChatId(payload.chatId)\n addMessage(payload.message)\n })\n\n socket.on('support-new-message', (payload: SupportNewMessagePayload) => {\n setChatId(payload.chatId)\n addMessage(payload.message)\n })\n\n socket.on('error', (err: SocketError) => {\n setError(err)\n setStatus('error')\n })\n\n return () => {\n destroySocket()\n reset()\n }\n }, [config.token])\n\n const sendMessage = useCallback(\n (content: string, info?: VisitorInfo) => {\n const socket = getSocket(config)\n\n const dto: SupportSendMessageDTO = {\n content,\n externalId: `msg-${Date.now()}`,\n ...(info ?? visitorInfo\n ? {\n email: (info ?? visitorInfo)!.email,\n name: (info ?? visitorInfo)?.name,\n phone: (info ?? visitorInfo)?.phone,\n }\n : {}),\n }\n\n socket.emit('support-send-message', dto)\n },\n [config, visitorInfo]\n )\n\n const sendFile = useCallback(\n async (file: File, content?: string, info?: VisitorInfo) => {\n const url = await uploadFile(file, config)\n\n const socket = getSocket(config)\n\n const dto: SupportSendMessageDTO = {\n file: url,\n ...(content ? { content } : {}),\n externalId: `file-${Date.now()}`,\n ...(info ?? visitorInfo\n ? {\n email: (info ?? visitorInfo)!.email,\n name: (info ?? visitorInfo)?.name,\n phone: (info ?? visitorInfo)?.phone,\n }\n : {}),\n }\n\n socket.emit('support-send-message', dto)\n },\n [config, visitorInfo]\n )\n\n return {\n status,\n role,\n visitorId,\n chatId,\n messages,\n error,\n visitorInfo,\n setVisitorInfo,\n sendMessage,\n sendFile,\n }\n}","import { io, Socket } from 'socket.io-client'\nimport type { ChatConfig } from '../types'\n\nlet socket: Socket | null = null\n\nexport const createSocket = (config: ChatConfig): Socket => {\n if (socket) {\n socket.disconnect()\n socket = null\n }\n\n const { serverUrl, token, visitorId } = config\n\n socket = io(serverUrl, {\n transports: ['websocket', 'polling'],\n auth: {\n ...(token ? { token } : {}),\n ...(visitorId ? { visitorId } : {}),\n },\n autoConnect: false,\n })\n\n return socket\n}\n\nexport const getSocket = (config: ChatConfig): Socket => {\n if (socket) return socket\n return createSocket(config)\n}\n\nexport const destroySocket = (): void => {\n if (socket) {\n socket.disconnect()\n socket = null\n }\n}","import { create } from 'zustand'\nimport type {\n ChatState,\n ChatMessage,\n UserRole,\n SocketError,\n VisitorInfo,\n ConnectionStatus,\n} from '../types'\n\ntype ChatActions = {\n setStatus: (status: ConnectionStatus) => void\n setRole: (role: UserRole) => void\n setVisitorId: (id: string) => void\n setChatId: (id: string) => void\n addMessage: (message: ChatMessage) => void\n setError: (error: SocketError | null) => void\n setVisitorInfo: (info: VisitorInfo) => void\n reset: () => void\n}\n\nconst initialState: ChatState = {\n status: 'idle',\n role: null,\n visitorId: null,\n chatId: null,\n messages: [],\n error: null,\n visitorInfo: null,\n}\n\nexport const useChatStore = create<ChatState & ChatActions>((set) => ({\n ...initialState,\n\n setStatus: (status) => set({ status }),\n setRole: (role) => set({ role }),\n setVisitorId: (id) => set({ visitorId: id }),\n setChatId: (id) => set({ chatId: id }),\n addMessage: (message) =>\n set((state) => ({\n messages: [...state.messages, message],\n })),\n setError: (error) => set({ error }),\n setVisitorInfo: (info) => set({ visitorInfo: info }),\n reset: () => set(initialState),\n}))","import React, { useEffect, useState } from 'react'\nimport { css } from '@emotion/css'\n\nconst BUTTON_SIZE = 58\n\ninterface Props {\n isOpen: boolean\n onToggle: () => void\n}\n\nexport const FloatingButton: React.FC<Props> = ({ isOpen, onToggle }) => {\n const [isMobile, setIsMobile] = useState(false)\n\n useEffect(() => {\n const check = () => setIsMobile(window.innerWidth <= 480)\n check()\n window.addEventListener('resize', check)\n return () => window.removeEventListener('resize', check)\n }, [])\n\n if (isMobile && isOpen) {\n return (\n <button className={styles.mobileCloseBtn} onClick={onToggle} type=\"button\">\n <svg width=\"22\" height=\"22\" viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"#fff\" strokeWidth=\"2.5\" strokeLinecap=\"round\">\n <line x1=\"18\" y1=\"6\" x2=\"6\" y2=\"18\" />\n <line x1=\"6\" y1=\"6\" x2=\"18\" y2=\"18\" />\n </svg>\n </button>\n )\n }\n\n return (\n <button className={styles.btn} onClick={onToggle} type=\"button\">\n <span className={styles.icon(!isOpen)}>\n <svg width=\"24\" height=\"24\" viewBox=\"0 0 24 24\" fill=\"#fff\">\n <path d=\"M20 2H4a2 2 0 0 0-2 2v18l4-4h14a2 2 0 0 0 2-2V4a2 2 0 0 0-2-2z\" />\n </svg>\n </span>\n <span className={styles.icon(isOpen)}>\n <svg width=\"20\" height=\"20\" viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"#fff\" strokeWidth=\"2.5\" strokeLinecap=\"round\">\n <line x1=\"18\" y1=\"6\" x2=\"6\" y2=\"18\" />\n <line x1=\"6\" y1=\"6\" x2=\"18\" y2=\"18\" />\n </svg>\n </span>\n </button>\n )\n}\n\nconst styles = {\n btn: css`\n position: fixed;\n right: 30px;\n bottom: 20px;\n width: ${BUTTON_SIZE}px;\n height: ${BUTTON_SIZE}px;\n border-radius: 50%;\n background: var(--wds-primary, oklch(0.5811 0.2268 259.15));\n border: none;\n cursor: pointer;\n box-shadow: 0 4px 20px rgba(0, 0, 0, 0.18);\n z-index: 999999;\n display: flex;\n align-items: center;\n justify-content: center;\n user-select: none;\n -webkit-user-select: none;\n &:hover {\n opacity: 0.92;\n }\n `,\n mobileCloseBtn: css`\n position: fixed;\n top: 16px;\n right: 20px;\n width: ${BUTTON_SIZE}px;\n height: ${BUTTON_SIZE}px;\n border-radius: 50%;\n background: var(--wds-primary, oklch(0.5811 0.2268 259.15));\n border: none;\n cursor: pointer;\n box-shadow: 0 4px 20px rgba(0, 0, 0, 0.25);\n z-index: 999999;\n display: flex;\n align-items: center;\n justify-content: center;\n `,\n icon: (visible: boolean) => css`\n position: absolute;\n display: flex;\n align-items: center;\n justify-content: center;\n transition: opacity 0.15s, transform 0.15s;\n transition-delay: ${visible ? '0.1s' : '0s'};\n opacity: ${visible ? 1 : 0};\n transform: ${visible ? 'scale(1)' : 'scale(0.6) rotate(30deg)'};\n pointer-events: ${visible ? 'auto' : 'none'};\n `,\n}","import React from 'react'\nimport { css } from '@emotion/css'\n\ninterface Props {\n isOpen: boolean\n isExpanded: boolean\n children: React.ReactNode\n}\n\nexport const ChatPanel: React.FC<Props> = ({ isOpen, isExpanded, children }) => {\n return (\n <div data-wds-root className={styles.panel(isOpen, isExpanded)}>\n <div className={styles.inner}>{children}</div>\n </div>\n )\n}\n\nconst styles = {\n panel: (isOpen: boolean, isExpanded: boolean) => css`\n position: fixed;\n bottom: 86px;\n z-index: 999998;\n transition: opacity 0.2s, transform 0.25s cubic-bezier(0.34, 1.2, 0.64, 1);\n opacity: ${isOpen ? 1 : 0};\n pointer-events: ${isOpen ? 'auto' : 'none'};\n\n ${isExpanded\n ? `\n width: min(760px, calc(100vw - 32px));\n height: min(780px, calc(100vh - 120px));\n border-radius: 20px;\n box-shadow: 0 20px 60px rgba(0,0,0,0.2), 0 4px 16px rgba(0,0,0,0.1);\n left: 50%;\n right: auto;\n translate: -50% 0;\n transform: ${isOpen ? 'scale(1)' : 'scale(0.95)'};\n transform-origin: bottom center;\n `\n : `\n width: 400px;\n height: 620px;\n border-radius: 20px;\n box-shadow: 0 12px 48px rgba(0,0,0,0.16), 0 2px 8px rgba(0,0,0,0.08);\n right: 22px;\n transform: ${isOpen ? 'translateY(0) scale(1)' : 'translateY(16px) scale(0.97)'};\n `}\n\n overflow: hidden;\n\n @media (max-width: 480px) {\n top: 0 !important;\n left: 0 !important;\n right: 0 !important;\n bottom: 0 !important;\n width: 100% !important;\n height: 100% !important;\n border-radius: 0 !important;\n translate: none !important;\n }\n `,\n inner: css`\n width: 100%;\n height: 100%;\n overflow: hidden;\n border-radius: inherit;\n `,\n}","import React from 'react'\nimport { css } from '@emotion/css'\n\ninterface Props {\n onStartChat: () => void\n onContinueChat: () => void\n hasHistory: boolean\n onExpand: () => void\n isExpanded: boolean\n}\n\nexport const HomeScreen: React.FC<Props> = ({\n onStartChat,\n onContinueChat,\n hasHistory,\n onExpand,\n isExpanded,\n}) => {\n return (\n <div className={styles.wrapper}>\n <div className={styles.topBar}>\n <div className={styles.logoMark}>\n <img\n src=\"https://cdn.waysdrop.com/bulk/horizon_20260411202129966_d25edae2.png\"\n alt=\"Waysdrop\"\n style={{ width: '100%', height: '100%', objectFit: 'contain' }}\n />\n </div>\n <button className={styles.expandBtn} onClick={onExpand}>\n {isExpanded ? (\n <svg width=\"15\" height=\"15\" viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" strokeWidth=\"2\" strokeLinecap=\"round\" strokeLinejoin=\"round\">\n <polyline points=\"4 14 10 14 10 20\"/><polyline points=\"20 10 14 10 14 4\"/>\n <line x1=\"10\" y1=\"14\" x2=\"3\" y2=\"21\"/><line x1=\"21\" y1=\"3\" x2=\"14\" y2=\"10\"/>\n </svg>\n ) : (\n <svg width=\"15\" height=\"15\" viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" strokeWidth=\"2\" strokeLinecap=\"round\" strokeLinejoin=\"round\">\n <polyline points=\"15 3 21 3 21 9\"/><polyline points=\"9 21 3 21 3 15\"/>\n <line x1=\"21\" y1=\"3\" x2=\"14\" y2=\"10\"/><line x1=\"3\" y1=\"21\" x2=\"10\" y2=\"14\"/>\n </svg>\n )}\n </button>\n </div>\n\n <div className={styles.hero}>\n <h2 className={styles.heroTitle}>Hi there! ๐Ÿ‘‹</h2>\n <p className={styles.heroSub}>We're here to help. Ask us anything or share your feedback.</p>\n </div>\n\n <div className={styles.section}>\n <p className={styles.sectionLabel}>Conversations</p>\n {hasHistory ? (\n <button className={styles.conversationCard} onClick={onContinueChat}>\n <div className={styles.cardIcon}>\n <svg width=\"16\" height=\"16\" viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" 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 </div>\n <div className={styles.cardBody}>\n <span className={styles.cardTitle}>Continue conversation</span>\n <span className={styles.cardSub}>Tap to resume your last chat</span>\n </div>\n <svg width=\"14\" height=\"14\" viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" strokeWidth=\"2\" strokeLinecap=\"round\" strokeLinejoin=\"round\">\n <polyline points=\"9 18 15 12 9 6\"/>\n </svg>\n </button>\n ) : (\n <div className={styles.emptyHistory}>\n <svg width=\"32\" height=\"32\" viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" strokeWidth=\"1.5\" strokeLinecap=\"round\" strokeLinejoin=\"round\" style={{ opacity: 0.25 }}>\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 <p>No previous conversations</p>\n </div>\n )}\n </div>\n\n <div className={styles.footer}>\n <button className={styles.startBtn} onClick={onStartChat}>\n New conversation\n <svg width=\"15\" height=\"15\" viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" strokeWidth=\"2.5\" strokeLinecap=\"round\" strokeLinejoin=\"round\">\n <polyline points=\"9 18 15 12 9 6\"/>\n </svg>\n </button>\n <p className={styles.poweredBy}>Powered by Waysdrop</p>\n </div>\n </div>\n )\n}\n\nconst styles = {\n wrapper: css`\n display: flex;\n flex-direction: column;\n height: 100%;\n background: var(--wds-bg);\n text-align: left;\n `,\n topBar: css`\n display: flex;\n align-items: center;\n justify-content: space-between;\n padding: 18px 18px 0;\n flex-shrink: 0;\n `,\n logoMark: css`\n width: 48px;\n height: 48px;\n flex-shrink: 0;\n `,\n expandBtn: css`\n background: none;\n border: none;\n cursor: pointer;\n color: var(--wds-muted);\n padding: 8px;\n border-radius: 8px;\n display: flex;\n align-items: center;\n justify-content: center;\n transition: color 0.15s, background 0.15s;\n &:hover {\n color: var(--wds-fg);\n background: var(--wds-muted-bg);\n }\n @media (max-width: 480px) {\n display: none;\n }\n `,\n hero: css`\n padding: 20px 20px 16px;\n display: flex;\n flex-direction: column;\n align-items: flex-start;\n gap: 10px;\n flex-shrink: 0;\n `,\n heroTitle: css`\n font-size: 1.375rem;\n font-weight: 700;\n color: var(--wds-fg);\n margin: 0;\n line-height: 1.2;\n text-align: left;\n `,\n heroSub: css`\n font-size: 0.9375rem;\n color: var(--wds-muted);\n margin: 0;\n line-height: 1.6;\n text-align: left;\n `,\n section: css`\n flex: 1;\n padding: 4px 18px 0;\n overflow-y: auto;\n `,\n sectionLabel: css`\n font-size: 11px;\n font-weight: 600;\n letter-spacing: 0.07em;\n text-transform: uppercase;\n color: var(--wds-muted);\n margin: 0 0 12px 2px;\n text-align: left;\n `,\n conversationCard: css`\n display: flex;\n align-items: center;\n gap: 14px;\n width: 100%;\n padding: 14px 16px;\n background: var(--wds-muted-bg);\n border: 1px solid var(--wds-border);\n border-radius: 14px;\n cursor: pointer;\n text-align: left;\n transition: border-color 0.15s, background 0.15s;\n color: var(--wds-fg);\n &:hover {\n border-color: var(--wds-primary);\n background: var(--wds-primary-soft);\n }\n `,\n cardIcon: css`\n width: 38px;\n height: 38px;\n border-radius: 10px;\n background: var(--wds-primary-soft);\n color: var(--wds-primary);\n display: flex;\n align-items: center;\n justify-content: center;\n flex-shrink: 0;\n `,\n cardBody: css`\n flex: 1;\n display: flex;\n flex-direction: column;\n gap: 3px;\n `,\n cardTitle: css`\n font-size: 0.875rem;\n font-weight: 600;\n color: var(--wds-fg);\n text-align: left;\n `,\n cardSub: css`\n font-size: 12px;\n color: var(--wds-muted);\n text-align: left;\n `,\n emptyHistory: css`\n display: flex;\n flex-direction: column;\n align-items: center;\n gap: 10px;\n padding: 40px 0;\n color: var(--wds-muted);\n font-size: 12px;\n `,\n footer: css`\n padding: 18px 18px 16px;\n display: flex;\n flex-direction: column;\n gap: 12px;\n align-items: center;\n flex-shrink: 0;\n border-top: 1px solid var(--wds-border);\n `,\n startBtn: css`\n display: flex;\n align-items: center;\n justify-content: center;\n gap: 6px;\n width: 100%;\n padding: 13px 16px;\n background: var(--wds-primary);\n color: #fff;\n border: none;\n border-radius: 14px;\n font-size: 0.9375rem;\n font-weight: 600;\n cursor: pointer;\n transition: opacity 0.15s;\n font-family: inherit;\n &:hover { opacity: 0.88; }\n `,\n poweredBy: css`\n font-size: 11px;\n color: var(--wds-muted);\n margin: 0;\n opacity: 0.7;\n `,\n}","import React, { useEffect, useRef, useState } from \"react\";\nimport { css, keyframes } from \"@emotion/css\";\nimport { ChatMessage } from \"../types\";\nimport { MessageBubble } from \"./MessageBubble\";\nimport { ChatInput } from \"./ChatInput\";\n\ninterface Props {\n messages: ChatMessage[];\n onSendText: (content: string) => void;\n onSendFile: (file: File, content?: string) => Promise<void>;\n onBack: () => void;\n onExpand: () => void;\n isExpanded: boolean;\n status: string;\n error: { code: number; message: string } | null;\n}\n\nexport const ChatScreen: React.FC<Props> = ({\n messages,\n onSendText,\n onSendFile,\n onBack,\n onExpand,\n isExpanded,\n status,\n error,\n}) => {\n const bottomRef = useRef<HTMLDivElement>(null);\n const scrollRef = useRef<HTMLDivElement>(null);\n const connected = status === \"connected\";\n const [showScrollBtn, setShowScrollBtn] = useState(false);\n\n const lastMsg = messages[messages.length - 1];\n const isThinking = connected && lastMsg?.direction === \"OUTBOUND\";\n\n useEffect(() => {\n bottomRef.current?.scrollIntoView({ behavior: \"smooth\" });\n }, [messages]);\n\n const handleScroll = () => {\n const el = scrollRef.current;\n if (!el) return;\n setShowScrollBtn(el.scrollHeight - el.scrollTop - el.clientHeight > 80);\n };\n\n return (\n <div className={styles.wrapper}>\n <div className={styles.header}>\n <button className={styles.iconBtn} onClick={onBack}>\n <svg\n width=\"18\"\n height=\"18\"\n viewBox=\"0 0 24 24\"\n fill=\"none\"\n stroke=\"currentColor\"\n strokeWidth=\"2\"\n strokeLinecap=\"round\"\n strokeLinejoin=\"round\"\n >\n <polyline points=\"15 18 9 12 15 6\" />\n </svg>\n </button>\n\n <div className={styles.headerCenter}>\n <span className={styles.headerTitle}>Support</span>\n <span className={styles.statusDot(connected)} />\n <span className={styles.statusLabel}>\n {connected ? \"Online\" : \"Connecting...\"}\n </span>\n </div>\n\n <button className={styles.expandBtn} onClick={onExpand}>\n {isExpanded ? (\n <svg\n width=\"16\"\n height=\"16\"\n viewBox=\"0 0 24 24\"\n fill=\"none\"\n stroke=\"currentColor\"\n strokeWidth=\"2\"\n strokeLinecap=\"round\"\n strokeLinejoin=\"round\"\n >\n <polyline points=\"4 14 10 14 10 20\" />\n <polyline points=\"20 10 14 10 14 4\" />\n <line x1=\"10\" y1=\"14\" x2=\"3\" y2=\"21\" />\n <line x1=\"21\" y1=\"3\" x2=\"14\" y2=\"10\" />\n </svg>\n ) : (\n <svg\n width=\"16\"\n height=\"16\"\n viewBox=\"0 0 24 24\"\n fill=\"none\"\n stroke=\"currentColor\"\n strokeWidth=\"2\"\n strokeLinecap=\"round\"\n strokeLinejoin=\"round\"\n >\n <polyline points=\"15 3 21 3 21 9\" />\n <polyline points=\"9 21 3 21 3 15\" />\n <line x1=\"21\" y1=\"3\" x2=\"14\" y2=\"10\" />\n <line x1=\"3\" y1=\"21\" x2=\"10\" y2=\"14\" />\n </svg>\n )}\n </button>\n </div>\n\n <div className={styles.messagesWrap}>\n <div\n className={styles.messages}\n ref={scrollRef}\n onScroll={handleScroll}\n >\n {error && <div className={styles.errorBanner}>{error.message}</div>}\n {messages.length === 0 && connected && (\n <div className={styles.emptyState}>\n <p>Send a message to start the conversation.</p>\n </div>\n )}\n {messages.map((msg) => (\n <MessageBubble key={msg.id} message={msg} />\n ))}\n <div ref={bottomRef} />\n </div>\n\n {showScrollBtn && (\n <button\n className={styles.scrollBtn}\n onClick={() =>\n bottomRef.current?.scrollIntoView({ behavior: \"smooth\" })\n }\n >\n <svg\n width=\"14\"\n height=\"14\"\n viewBox=\"0 0 24 24\"\n fill=\"none\"\n stroke=\"currentColor\"\n strokeWidth=\"2.5\"\n strokeLinecap=\"round\"\n strokeLinejoin=\"round\"\n >\n <polyline points=\"6 9 12 15 18 9\" />\n </svg>\n </button>\n )}\n </div>\n\n <ChatInput\n onSendText={onSendText}\n onSendFile={onSendFile}\n disabled={!connected}\n isThinking={isThinking}\n />\n </div>\n );\n};\n\nconst pulse = keyframes`\n 0%, 100% { opacity: 1; }\n 50% { opacity: 0.4; }\n`;\n\nconst styles = {\n wrapper: css`\n display: flex;\n flex-direction: column;\n height: 100%;\n background: var(--wds-bg);\n `,\n header: css`\n display: flex;\n align-items: center;\n gap: 10px;\n padding: 12px 14px;\n border-bottom: 1px solid var(--wds-border);\n flex-shrink: 0;\n `,\n headerCenter: css`\n flex: 1;\n display: flex;\n align-items: center;\n gap: 6px;\n `,\n headerTitle: css`\n font-size: 0.875rem;\n font-weight: 600;\n color: var(--wds-fg);\n `,\n statusDot: (connected: boolean) => css`\n width: 7px;\n height: 7px;\n border-radius: 50%;\n flex-shrink: 0;\n background: ${connected ? \"#22c55e\" : \"#f59e0b\"};\n animation: ${connected ? \"none\" : `${pulse} 1.2s ease-in-out infinite`};\n `,\n statusLabel: css`\n font-size: 11px;\n color: var(--wds-muted);\n `,\n iconBtn: css`\n background: none;\n border: none;\n cursor: pointer;\n color: var(--wds-muted);\n padding: 6px;\n border-radius: 8px;\n display: flex;\n align-items: center;\n justify-content: center;\n flex-shrink: 0;\n transition:\n color 0.15s,\n background 0.15s;\n &:hover {\n color: var(--wds-fg);\n background: var(--wds-muted-bg);\n }\n `,\n expandBtn: css`\n background: none;\n border: none;\n cursor: pointer;\n color: var(--wds-muted);\n padding: 6px;\n border-radius: 8px;\n display: flex;\n align-items: center;\n justify-content: center;\n flex-shrink: 0;\n transition:\n color 0.15s,\n background 0.15s;\n &:hover {\n color: var(--wds-fg);\n background: var(--wds-muted-bg);\n }\n @media (max-width: 480px) {\n display: none;\n }\n `,\n messagesWrap: css`\n flex: 1;\n position: relative;\n overflow: hidden;\n `,\n messages: css`\n position: absolute;\n inset: 0;\n overflow-y: auto;\n padding: 16px 14px;\n display: flex;\n flex-direction: column;\n gap: 10px;\n `,\n errorBanner: css`\n background: oklch(0.9705 0.0129 17.04);\n color: oklch(0.5054 0.1905 27.51);\n border: 1px solid oklch(0.8845 0.0592 18.27);\n border-radius: 8px;\n padding: 8px 12px;\n font-size: 12px;\n text-align: center;\n `,\n emptyState: css`\n flex: 1;\n display: flex;\n align-items: center;\n justify-content: center;\n color: var(--wds-muted);\n font-size: 13px;\n text-align: center;\n padding: 40px 20px;\n `,\n scrollBtn: css`\n position: absolute;\n bottom: 12px;\n left: 50%;\n transform: translateX(-50%);\n width: 30px;\n height: 30px;\n border-radius: 50%;\n background: var(--wds-bg);\n border: 1px solid var(--wds-border);\n color: var(--wds-muted);\n display: flex;\n align-items: center;\n justify-content: center;\n cursor: pointer;\n box-shadow: 0 2px 8px rgba(0, 0, 0, 0.12);\n transition:\n color 0.15s,\n border-color 0.15s;\n &:hover {\n color: var(--wds-primary);\n border-color: var(--wds-primary);\n }\n `,\n};","import React from 'react'\nimport { css } from '@emotion/css'\nimport { ChatMessage } from '../types'\nimport { MarkdownRenderer } from './MarkdownRenderer'\n\nfunction formatTime(iso: string): string {\n return new Date(iso).toLocaleTimeString([], { hour: '2-digit', minute: '2-digit' })\n}\n\ninterface Props {\n message: ChatMessage\n}\n\nexport const MessageBubble: React.FC<Props> = ({ message }) => {\n const isCustomer = message.direction === 'OUTBOUND'\n const isBot = message.senderRole === 'BOT'\n\n return (\n <div className={styles.row(isCustomer)}>\n <div className={styles.group(isCustomer)}>\n {isBot && <span className={styles.botLabel}>Ways AI</span>}\n <div className={styles.bubble(isCustomer)}>\n {message.file && (\n <a href={message.file} target=\"_blank\" rel=\"noreferrer\" className={styles.fileLink(!!message.content)}>\n ๐Ÿ“Ž View attachment\n </a>\n )}\n {message.content && (\n isBot\n ? <MarkdownRenderer content={message.content} />\n : <p className={styles.text}>{message.content}</p>\n )}\n </div>\n <span className={styles.time}>{formatTime(message.createdAt)}</span>\n </div>\n </div>\n )\n}\n\nconst styles = {\n row: (isCustomer: boolean) => css`\n display: flex;\n width: 100%;\n justify-content: ${isCustomer ? 'flex-start' : 'flex-end'};\n `,\n group: (isCustomer: boolean) => css`\n display: flex;\n flex-direction: column;\n max-width: 78%;\n gap: 4px;\n align-items: ${isCustomer ? 'flex-start' : 'flex-end'};\n `,\n botLabel: css`\n font-size: 10px;\n color: var(--wds-muted);\n padding: 0 4px;\n font-weight: 500;\n letter-spacing: 0.03em;\n `,\n bubble: (isCustomer: boolean) => css`\n border-radius: 18px;\n padding: 10px 14px;\n word-break: break-word;\n text-align: left;\n border-top-left-radius: ${isCustomer ? '4px' : '18px'};\n border-top-right-radius: ${isCustomer ? '18px' : '4px'};\n background: ${isCustomer ? 'var(--wds-muted-bg)' : 'var(--wds-primary)'};\n color: ${isCustomer ? 'var(--wds-fg)' : '#fff'};\n `,\n text: css`\n font-size: 0.875rem;\n line-height: 1.5;\n margin: 0;\n white-space: pre-wrap;\n text-align: left;\n `,\n fileLink: (hasContent: boolean) => css`\n font-size: 0.875rem;\n color: inherit;\n text-decoration: underline;\n display: block;\n text-align: left;\n ${hasContent ? 'margin-bottom: 6px;' : ''}\n `,\n time: css`\n font-size: 10px;\n color: var(--wds-muted);\n padding: 0 4px;\n `,\n}","import React from 'react'\nimport ReactMarkdown from 'react-markdown'\nimport { css } from '@emotion/css'\n\nconst markdownStyle = css`\n font-size: 0.875rem;\n line-height: 1.6;\n color: inherit;\n text-align: left;\n\n p {\n margin: 0 0 0.6rem 0;\n text-align: left;\n }\n p:last-child {\n margin-bottom: 0;\n }\n strong { font-weight: 600; }\n em { font-style: italic; }\n\n ul, ol {\n margin: 0.4rem 0 0.6rem 0;\n padding-left: 1.4rem;\n text-align: left;\n }\n ul { list-style-type: disc; }\n ol { list-style-type: decimal; }\n li {\n margin-bottom: 0.3rem;\n }\n li > ul, li > ol {\n margin: 0.25rem 0 0.25rem 0;\n padding-left: 1.2rem;\n }\n li:last-child { margin-bottom: 0; }\n\n hr {\n border: none;\n border-top: 1px solid rgba(255, 255, 255, 0.25);\n margin: 0.75rem 0;\n }\n\n code {\n font-family: monospace;\n font-size: 0.8rem;\n background: rgba(255,255,255,0.15);\n border-radius: 4px;\n padding: 0.1rem 0.35rem;\n }\n pre {\n background: rgba(255,255,255,0.1);\n border-radius: 8px;\n padding: 0.75rem 1rem;\n overflow-x: auto;\n margin: 0.5rem 0;\n }\n pre code {\n background: none;\n padding: 0;\n font-size: 0.78rem;\n }\n blockquote {\n border-left: 3px solid rgba(255,255,255,0.25);\n margin: 0.5rem 0;\n padding-left: 0.75rem;\n opacity: 0.8;\n }\n a {\n color: rgba(255,255,255,0.85);\n text-decoration: underline;\n }\n h1, h2, h3 {\n font-weight: 600;\n margin: 0.6rem 0 0.3rem;\n line-height: 1.3;\n text-align: left;\n }\n h1 { font-size: 1rem; }\n h2 { font-size: 0.95rem; }\n h3 { font-size: 0.875rem; }\n`\n\ninterface Props {\n content: string\n}\n\nexport const MarkdownRenderer: React.FC<Props> = ({ content }) => {\n return (\n <div className={markdownStyle}>\n <ReactMarkdown>{content}</ReactMarkdown>\n </div>\n )\n}","import React, { useState, useRef, useCallback, KeyboardEvent } from 'react'\nimport { css, keyframes } from '@emotion/css'\n\nconst spin = keyframes`\n to { transform: rotate(360deg); }\n`\n\nconst pulse = keyframes`\n 0%, 100% { opacity: 0.4; transform: scaleY(0.6); }\n 50% { opacity: 1; transform: scaleY(1); }\n`\n\ninterface Props {\n onSendText: (content: string) => void\n onSendFile: (file: File, content?: string) => Promise<void>\n disabled?: boolean\n isThinking?: boolean\n}\n\nexport const ChatInput: React.FC<Props> = ({ onSendText, onSendFile, disabled, isThinking }) => {\n const [value, setValue] = useState('')\n const [uploading, setUploading] = useState(false)\n const [pendingFile, setPendingFile] = useState<File | null>(null)\n const [pendingPreview, setPendingPreview] = useState<string | null>(null)\n const textareaRef = useRef<HTMLTextAreaElement>(null)\n const fileInputRef = useRef<HTMLInputElement>(null)\n\n const handleSend = useCallback(() => {\n const trimmed = value.trim()\n if ((!trimmed && !pendingFile) || disabled || uploading) return\n\n if (pendingFile) {\n setUploading(true)\n onSendFile(pendingFile, trimmed || undefined).finally(() => {\n setUploading(false)\n setPendingFile(null)\n setPendingPreview(null)\n setValue('')\n })\n } else if (trimmed) {\n onSendText(trimmed)\n setValue('')\n }\n\n textareaRef.current?.focus()\n }, [value, pendingFile, disabled, uploading, onSendText, onSendFile])\n\n const handleKeyDown = (e: KeyboardEvent<HTMLTextAreaElement>) => {\n if (e.key === 'Enter' && !e.shiftKey) {\n e.preventDefault()\n handleSend()\n }\n }\n\n const handleFileChange = (e: React.ChangeEvent<HTMLInputElement>) => {\n const file = e.target.files?.[0]\n if (!file) return\n if (!file.type.startsWith('image/')) return\n setPendingFile(file)\n const reader = new FileReader()\n reader.onload = (ev) => setPendingPreview(ev.target?.result as string)\n reader.readAsDataURL(file)\n e.target.value = ''\n }\n\n const canSend = (value.trim() || pendingFile) && !disabled && !uploading\n\n return (\n <div className={styles.wrapper}>\n {isThinking && (\n <div className={styles.thinkingBar}>\n <div className={styles.thinkingDots}>\n <span className={styles.dot(0)} />\n <span className={styles.dot(1)} />\n <span className={styles.dot(2)} />\n </div>\n <span className={styles.thinkingLabel}>Ways AI is typing...</span>\n </div>\n )}\n\n {pendingPreview && (\n <div className={styles.imagePreview}>\n <img src={pendingPreview} alt=\"attachment\" className={styles.previewImg} />\n <button className={styles.removeFile} onClick={() => { setPendingFile(null); setPendingPreview(null) }}>\n <svg width=\"12\" height=\"12\" viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" strokeWidth=\"2.5\" strokeLinecap=\"round\">\n <line x1=\"18\" y1=\"6\" x2=\"6\" y2=\"18\"/><line x1=\"6\" y1=\"6\" x2=\"18\" y2=\"18\"/>\n </svg>\n </button>\n </div>\n )}\n\n <div className={styles.inputRow}>\n <button\n className={styles.attachBtn}\n onClick={() => fileInputRef.current?.click()}\n disabled={disabled || uploading}\n type=\"button\"\n >\n <svg width=\"18\" height=\"18\" viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" strokeWidth=\"2\" strokeLinecap=\"round\" strokeLinejoin=\"round\">\n <rect x=\"3\" y=\"3\" width=\"18\" height=\"18\" rx=\"3\"/><circle cx=\"8.5\" cy=\"8.5\" r=\"1.5\"/><polyline points=\"21 15 16 10 5 21\"/>\n </svg>\n </button>\n\n <input\n ref={fileInputRef}\n type=\"file\"\n accept=\"image/*\"\n className={styles.hiddenInput}\n onChange={handleFileChange}\n />\n\n <textarea\n ref={textareaRef}\n className={styles.textarea}\n value={value}\n onChange={(e) => setValue(e.target.value)}\n onKeyDown={handleKeyDown}\n placeholder=\"Type a message...\"\n disabled={disabled || uploading}\n rows={1}\n />\n\n <button className={styles.sendBtn} onClick={handleSend} disabled={!canSend} type=\"button\">\n {uploading ? (\n <span className={styles.spinner} />\n ) : (\n <svg width=\"16\" height=\"16\" viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" strokeWidth=\"2.5\" strokeLinecap=\"round\" strokeLinejoin=\"round\">\n <line x1=\"12\" y1=\"19\" x2=\"12\" y2=\"5\"/><polyline points=\"5 12 12 5 19 12\"/>\n </svg>\n )}\n </button>\n </div>\n\n <p className={styles.hint}>Enter to send ยท Shift+Enter for new line</p>\n </div>\n )\n}\n\nconst styles = {\n wrapper: css`\n padding: 8px 12px 10px;\n border-top: 1px solid var(--wds-border);\n display: flex;\n flex-direction: column;\n gap: 6px;\n background: var(--wds-bg);\n flex-shrink: 0;\n `,\n thinkingBar: css`\n display: flex;\n align-items: center;\n gap: 8px;\n padding: 6px 2px 2px;\n `,\n thinkingDots: css`\n display: flex;\n align-items: center;\n gap: 3px;\n `,\n dot: (i: number) => css`\n width: 5px;\n height: 5px;\n border-radius: 50%;\n background: var(--wds-primary);\n animation: ${pulse} 1.2s ease-in-out infinite;\n animation-delay: ${i * 0.18}s;\n display: inline-block;\n `,\n thinkingLabel: css`\n font-size: 11px;\n color: var(--wds-muted);\n `,\n imagePreview: css`\n position: relative;\n width: fit-content;\n margin: 0 2px;\n `,\n previewImg: css`\n width: 72px;\n height: 72px;\n object-fit: cover;\n border-radius: 10px;\n border: 1px solid var(--wds-border);\n display: block;\n `,\n removeFile: css`\n position: absolute;\n top: -6px;\n right: -6px;\n width: 18px;\n height: 18px;\n border-radius: 50%;\n background: var(--wds-fg);\n color: var(--wds-bg);\n border: none;\n cursor: pointer;\n display: flex;\n align-items: center;\n justify-content: center;\n padding: 0;\n `,\n inputRow: css`\n display: flex;\n align-items: center;\n gap: 6px;\n background: var(--wds-muted-bg);\n border: 1px solid var(--wds-border);\n border-radius: 14px;\n padding: 4px 4px 4px 8px;\n transition: border-color 0.15s;\n &:focus-within {\n border-color: var(--wds-primary);\n background: var(--wds-bg);\n }\n `,\n attachBtn: css`\n background: none;\n border: none;\n cursor: pointer;\n color: var(--wds-muted);\n padding: 5px;\n border-radius: 8px;\n display: flex;\n align-items: center;\n justify-content: center;\n flex-shrink: 0;\n transition: color 0.15s;\n &:hover:not(:disabled) {\n color: var(--wds-primary);\n }\n &:disabled {\n opacity: 0.35;\n cursor: not-allowed;\n }\n `,\n hiddenInput: css`\n display: none;\n `,\n textarea: css`\n flex: 1;\n resize: none;\n border: none;\n padding: 6px 0;\n font-size: 0.875rem;\n font-family: inherit;\n line-height: 1.5;\n background: transparent;\n color: var(--wds-fg);\n outline: none;\n max-height: 120px;\n overflow-y: auto;\n &::placeholder { color: var(--wds-muted); }\n &:disabled {\n opacity: 0.5;\n cursor: not-allowed;\n }\n `,\n sendBtn: css`\n background: var(--wds-primary);\n border: none;\n border-radius: 10px;\n width: 34px;\n height: 34px;\n display: flex;\n align-items: center;\n justify-content: center;\n cursor: pointer;\n color: #fff;\n flex-shrink: 0;\n transition: opacity 0.15s;\n &:disabled {\n opacity: 0.35;\n cursor: not-allowed;\n }\n &:hover:not(:disabled) { opacity: 0.85; }\n `,\n spinner: css`\n width: 14px;\n height: 14px;\n border: 2px solid rgba(255,255,255,0.3);\n border-top-color: #fff;\n border-radius: 50%;\n animation: ${spin} 0.7s linear infinite;\n display: block;\n `,\n hint: css`\n font-size: 10px;\n color: var(--wds-muted);\n margin: 0;\n text-align: center;\n opacity: 0.7;\n `,\n}"],"mappings":"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","names":["import_react","import_css","socket","import_react","import_css","import_jsx_runtime","styles","import_css","import_jsx_runtime","styles","import_react","import_css","import_css","import_css","import_jsx_runtime","ReactMarkdown","import_jsx_runtime","styles","import_react","import_css","import_jsx_runtime","_a","styles","import_jsx_runtime","styles","pulse","import_jsx_runtime"]}
package/dist/index.js CHANGED
@@ -215,7 +215,7 @@ var useChat = (config) => {
215
215
  import { useEffect as useEffect2, useState } from "react";
216
216
  import { css } from "@emotion/css";
217
217
  import { jsx, jsxs } from "react/jsx-runtime";
218
- var BUTTON_SIZE = 56;
218
+ var BUTTON_SIZE = 58;
219
219
  var FloatingButton = ({ isOpen, onToggle }) => {
220
220
  const [isMobile, setIsMobile] = useState(false);
221
221
  useEffect2(() => {
@@ -225,49 +225,17 @@ var FloatingButton = ({ isOpen, onToggle }) => {
225
225
  return () => window.removeEventListener("resize", check);
226
226
  }, []);
227
227
  if (isMobile && isOpen) {
228
- return /* @__PURE__ */ jsx(
229
- "button",
230
- {
231
- className: styles.mobileCloseBtn,
232
- onClick: onToggle,
233
- type: "button",
234
- children: /* @__PURE__ */ jsxs(
235
- "svg",
236
- {
237
- width: "22",
238
- height: "22",
239
- viewBox: "0 0 24 24",
240
- fill: "none",
241
- stroke: "currentColor",
242
- strokeWidth: "2.5",
243
- strokeLinecap: "round",
244
- children: [
245
- /* @__PURE__ */ jsx("line", { x1: "18", y1: "6", x2: "6", y2: "18" }),
246
- /* @__PURE__ */ jsx("line", { x1: "6", y1: "6", x2: "18", y2: "18" })
247
- ]
248
- }
249
- )
250
- }
251
- );
228
+ return /* @__PURE__ */ jsx("button", { className: styles.mobileCloseBtn, onClick: onToggle, type: "button", children: /* @__PURE__ */ jsxs("svg", { width: "22", height: "22", viewBox: "0 0 24 24", fill: "none", stroke: "#fff", strokeWidth: "2.5", strokeLinecap: "round", children: [
229
+ /* @__PURE__ */ jsx("line", { x1: "18", y1: "6", x2: "6", y2: "18" }),
230
+ /* @__PURE__ */ jsx("line", { x1: "6", y1: "6", x2: "18", y2: "18" })
231
+ ] }) });
252
232
  }
253
233
  return /* @__PURE__ */ jsxs("button", { className: styles.btn, onClick: onToggle, type: "button", children: [
254
- /* @__PURE__ */ jsx("span", { className: styles.icon(!isOpen), children: /* @__PURE__ */ jsx("svg", { width: "24", height: "24", viewBox: "0 0 24 24", fill: "currentColor", children: /* @__PURE__ */ jsx("path", { d: "M20 2H4a2 2 0 0 0-2 2v18l4-4h14a2 2 0 0 0 2-2V4a2 2 0 0 0-2-2z" }) }) }),
255
- /* @__PURE__ */ jsx("span", { className: styles.icon(isOpen), children: /* @__PURE__ */ jsxs(
256
- "svg",
257
- {
258
- width: "20",
259
- height: "20",
260
- viewBox: "0 0 24 24",
261
- fill: "none",
262
- stroke: "currentColor",
263
- strokeWidth: "2.5",
264
- strokeLinecap: "round",
265
- children: [
266
- /* @__PURE__ */ jsx("line", { x1: "18", y1: "6", x2: "6", y2: "18" }),
267
- /* @__PURE__ */ jsx("line", { x1: "6", y1: "6", x2: "18", y2: "18" })
268
- ]
269
- }
270
- ) })
234
+ /* @__PURE__ */ jsx("span", { className: styles.icon(!isOpen), children: /* @__PURE__ */ jsx("svg", { width: "24", height: "24", viewBox: "0 0 24 24", fill: "#fff", children: /* @__PURE__ */ jsx("path", { d: "M20 2H4a2 2 0 0 0-2 2v18l4-4h14a2 2 0 0 0 2-2V4a2 2 0 0 0-2-2z" }) }) }),
235
+ /* @__PURE__ */ jsx("span", { className: styles.icon(isOpen), children: /* @__PURE__ */ jsxs("svg", { width: "20", height: "20", viewBox: "0 0 24 24", fill: "none", stroke: "#fff", strokeWidth: "2.5", strokeLinecap: "round", children: [
236
+ /* @__PURE__ */ jsx("line", { x1: "18", y1: "6", x2: "6", y2: "18" }),
237
+ /* @__PURE__ */ jsx("line", { x1: "6", y1: "6", x2: "18", y2: "18" })
238
+ ] }) })
271
239
  ] });
272
240
  };
273
241
  var styles = {
@@ -278,8 +246,7 @@ var styles = {
278
246
  width: ${BUTTON_SIZE}px;
279
247
  height: ${BUTTON_SIZE}px;
280
248
  border-radius: 50%;
281
- background: var(--wds-primary);
282
- color: #fff;
249
+ background: var(--wds-primary, oklch(0.5811 0.2268 259.15));
283
250
  border: none;
284
251
  cursor: pointer;
285
252
  box-shadow: 0 4px 20px rgba(0, 0, 0, 0.18);
@@ -300,8 +267,7 @@ var styles = {
300
267
  width: ${BUTTON_SIZE}px;
301
268
  height: ${BUTTON_SIZE}px;
302
269
  border-radius: 50%;
303
- background: var(--wds-primary);
304
- color: #fff;
270
+ background: var(--wds-primary, oklch(0.5811 0.2268 259.15));
305
271
  border: none;
306
272
  cursor: pointer;
307
273
  box-shadow: 0 4px 20px rgba(0, 0, 0, 0.25);
@@ -315,9 +281,8 @@ var styles = {
315
281
  display: flex;
316
282
  align-items: center;
317
283
  justify-content: center;
318
- transition:
319
- opacity 0.2s,
320
- transform 0.2s;
284
+ transition: opacity 0.15s, transform 0.15s;
285
+ transition-delay: ${visible ? "0.1s" : "0s"};
321
286
  opacity: ${visible ? 1 : 0};
322
287
  transform: ${visible ? "scale(1)" : "scale(0.6) rotate(30deg)"};
323
288
  pointer-events: ${visible ? "auto" : "none"};
@@ -1043,7 +1008,6 @@ var styles5 = {
1043
1008
  margin: 0;
1044
1009
  text-align: center;
1045
1010
  opacity: 0.7;
1046
- text-align: center;
1047
1011
  `
1048
1012
  };
1049
1013
 
@@ -1064,7 +1028,7 @@ var ChatScreen = ({
1064
1028
  const connected = status === "connected";
1065
1029
  const [showScrollBtn, setShowScrollBtn] = useState3(false);
1066
1030
  const lastMsg = messages[messages.length - 1];
1067
- const isThinking = connected && (lastMsg == null ? void 0 : lastMsg.direction) === "INBOUND";
1031
+ const isThinking = connected && (lastMsg == null ? void 0 : lastMsg.direction) === "OUTBOUND";
1068
1032
  useEffect3(() => {
1069
1033
  var _a;
1070
1034
  (_a = bottomRef.current) == null ? void 0 : _a.scrollIntoView({ behavior: "smooth" });
package/dist/index.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/components/ChatWidget.tsx","../src/lib/upload.ts","../src/hooks/useChat.ts","../src/lib/socket.ts","../src/store/chatStore.ts","../src/components/FloatingButton.tsx","../src/components/ChatPanel.tsx","../src/components/HomeScreen.tsx","../src/components/ChatScreen.tsx","../src/components/MessageBubble.tsx","../src/components/MarkdownRenderer.tsx","../src/components/ChatInput.tsx"],"sourcesContent":["import React, { useEffect, useState } from 'react'\nimport { injectGlobal } from '@emotion/css'\nimport { ChatConfig } from '../types'\nimport { loadVisitorId } from '../lib/upload'\nimport { useChat } from '../hooks/useChat'\nimport { useChatStore } from '../store/chatStore'\nimport { FloatingButton } from './FloatingButton'\nimport { ChatPanel } from './ChatPanel'\nimport { HomeScreen } from './HomeScreen'\nimport { ChatScreen } from './ChatScreen'\n\nexport type ChatWidgetProps = {\n config: ChatConfig\n}\n\ntype View = 'home' | 'chat'\n\nconst LIGHT_VARS = `\n --wds-bg: oklch(1 0 0);\n --wds-fg: oklch(0.145 0 0);\n --wds-muted: oklch(0.556 0 0);\n --wds-muted-bg: oklch(0.97 0 0);\n --wds-border: oklch(0.922 0 0);\n`\n\nconst DARK_VARS = `\n --wds-bg: oklch(0.145 0 0);\n --wds-fg: oklch(0.985 0 0);\n --wds-muted: oklch(0.708 0 0);\n --wds-muted-bg: oklch(0.205 0 0);\n --wds-border: oklch(1 0 0 / 10%);\n`\n\nfunction buildPrimaryVars(color: string) {\n return `\n --wds-primary: ${color};\n --wds-primary-soft: color-mix(in oklch, ${color} 12%, transparent);\n --wds-primary-border: color-mix(in oklch, ${color} 40%, transparent);\n `\n}\n\nconst DEFAULT_PRIMARY = 'oklch(0.5811 0.2268 259.15)'\n\nfunction buildThemeStyle(theme: 'light' | 'dark' | 'system', primaryColor: string) {\n const primary = buildPrimaryVars(primaryColor)\n\n if (theme === 'light') {\n return `\n [data-wds-root] {\n ${LIGHT_VARS}\n ${primary}\n }\n `\n }\n\n if (theme === 'dark') {\n return `\n [data-wds-root] {\n ${DARK_VARS}\n ${primary}\n }\n `\n }\n\n return `\n [data-wds-root] {\n ${LIGHT_VARS}\n ${primary}\n }\n @media (prefers-color-scheme: dark) {\n [data-wds-root] {\n ${DARK_VARS}\n --wds-primary-soft: color-mix(in oklch, ${primaryColor} 15%, transparent);\n }\n }\n `\n}\n\nexport const ChatWidget: React.FC<ChatWidgetProps> = ({ config }) => {\n const [isOpen, setIsOpen] = useState(false)\n const [isExpanded, setIsExpanded] = useState(false)\n const [view, setView] = useState<View>('home')\n const [visitorId] = useState<string | undefined>(\n () => config.visitorId ?? loadVisitorId() ?? undefined\n )\n\n const reset = useChatStore((s) => s.reset)\n\n const resolvedConfig: ChatConfig = {\n ...config,\n visitorId,\n }\n\n const hasHistory = !!visitorId\n\n const { status, messages, error, sendMessage, sendFile } = useChat(resolvedConfig)\n\n const handleNewConversation = () => {\n reset()\n setView('chat')\n }\n\n useEffect(() => {\n const isMobile = window.innerWidth <= 480\n if (isMobile) {\n document.body.style.overflow = isOpen ? 'hidden' : ''\n }\n return () => {\n document.body.style.overflow = ''\n }\n }, [isOpen])\n\n useEffect(() => {\n const theme = config.theme ?? 'system'\n const primaryColor = config.primaryColor ?? DEFAULT_PRIMARY\n const style = buildThemeStyle(theme, primaryColor)\n const el = document.createElement('style')\n el.setAttribute('data-wds-theme', '')\n el.textContent = style\n document.head.appendChild(el)\n return () => {\n document.head.removeChild(el)\n }\n }, [config.theme, config.primaryColor])\n\n return (\n <>\n <FloatingButton\n isOpen={isOpen}\n onToggle={() => setIsOpen((p) => !p)}\n />\n\n <ChatPanel\n isOpen={isOpen}\n isExpanded={isExpanded}\n >\n {view === 'home' ? (\n <HomeScreen\n onStartChat={handleNewConversation}\n onContinueChat={() => setView('chat')}\n hasHistory={hasHistory}\n onExpand={() => setIsExpanded((p) => !p)}\n isExpanded={isExpanded}\n />\n ) : (\n <ChatScreen\n messages={messages}\n onSendText={sendMessage}\n onSendFile={sendFile}\n onBack={() => setView('home')}\n onExpand={() => setIsExpanded((p) => !p)}\n isExpanded={isExpanded}\n status={status}\n error={error}\n />\n )}\n </ChatPanel>\n </>\n )\n}\n\ninjectGlobal`\n [data-wds-root] * {\n box-sizing: border-box;\n text-align: left;\n }\n`","import type { ChatConfig } from \"../types\";\n\nconst VISITOR_ID_KEY = \"waysdrop_visitor_id\";\n\nexport const saveVisitorId = (id: string): void => {\n if (typeof window === 'undefined') return;\n localStorage.setItem(VISITOR_ID_KEY, id);\n};\n\nexport const loadVisitorId = (): string | null => {\n if (typeof window === 'undefined') return null;\n return localStorage.getItem(VISITOR_ID_KEY);\n};\n\nexport const clearVisitorId = (): void => {\n if (typeof window === 'undefined') return;\n localStorage.removeItem(VISITOR_ID_KEY);\n};\n\nexport const uploadFile = async (\n file: File,\n config: ChatConfig,\n): Promise<string> => {\n const formData = new FormData();\n formData.append(\"files\", file);\n\n const headers: HeadersInit = {};\n if (config.token) headers[\"Authorization\"] = `Bearer ${config.token}`;\n\n const res = await fetch(`${config.apiUrl}/file/bulk-upload`, {\n method: \"POST\",\n headers,\n body: formData,\n });\n\n if (!res.ok) {\n throw new Error(\"File upload failed\");\n }\n\n const json = await res.json();\n\n if (!json.success || !json.data?.urls?.length) {\n throw new Error(json.message || \"File upload failed\");\n }\n\n const first = json.data.urls[0];\n if (typeof first !== \"string\") {\n throw new Error(first?.error || \"File upload failed\");\n }\n\n return first;\n};","import { useEffect, useCallback } from 'react'\nimport { createSocket, getSocket, destroySocket } from '../lib/socket'\nimport { saveVisitorId, uploadFile } from '../lib/upload'\nimport { useChatStore } from '../store/chatStore'\nimport type {\n ChatConfig,\n ConnectedPayload,\n SupportMessageSentPayload,\n SupportNewMessagePayload,\n SocketError,\n SupportSendMessageDTO,\n VisitorInfo,\n} from '../types'\n\nexport const useChat = (config: ChatConfig) => {\n const {\n status,\n role,\n visitorId,\n chatId,\n messages,\n error,\n visitorInfo,\n setStatus,\n setRole,\n setVisitorId,\n setChatId,\n addMessage,\n setError,\n setVisitorInfo,\n reset,\n } = useChatStore()\n\n useEffect(() => {\n const socket = createSocket(config)\n\n setStatus('connecting')\n socket.connect()\n\n socket.on('connected', (payload: ConnectedPayload) => {\n setStatus('connected')\n setRole(payload.role)\n\n if (payload.role === 'VISITOR') {\n saveVisitorId(payload.visitorId)\n setVisitorId(payload.visitorId)\n }\n })\n\n socket.on('support-message-sent', (payload: SupportMessageSentPayload) => {\n setChatId(payload.chatId)\n addMessage(payload.message)\n })\n\n socket.on('support-new-message', (payload: SupportNewMessagePayload) => {\n setChatId(payload.chatId)\n addMessage(payload.message)\n })\n\n socket.on('error', (err: SocketError) => {\n setError(err)\n setStatus('error')\n })\n\n return () => {\n destroySocket()\n reset()\n }\n }, [config.token])\n\n const sendMessage = useCallback(\n (content: string, info?: VisitorInfo) => {\n const socket = getSocket(config)\n\n const dto: SupportSendMessageDTO = {\n content,\n externalId: `msg-${Date.now()}`,\n ...(info ?? visitorInfo\n ? {\n email: (info ?? visitorInfo)!.email,\n name: (info ?? visitorInfo)?.name,\n phone: (info ?? visitorInfo)?.phone,\n }\n : {}),\n }\n\n socket.emit('support-send-message', dto)\n },\n [config, visitorInfo]\n )\n\n const sendFile = useCallback(\n async (file: File, content?: string, info?: VisitorInfo) => {\n const url = await uploadFile(file, config)\n\n const socket = getSocket(config)\n\n const dto: SupportSendMessageDTO = {\n file: url,\n ...(content ? { content } : {}),\n externalId: `file-${Date.now()}`,\n ...(info ?? visitorInfo\n ? {\n email: (info ?? visitorInfo)!.email,\n name: (info ?? visitorInfo)?.name,\n phone: (info ?? visitorInfo)?.phone,\n }\n : {}),\n }\n\n socket.emit('support-send-message', dto)\n },\n [config, visitorInfo]\n )\n\n return {\n status,\n role,\n visitorId,\n chatId,\n messages,\n error,\n visitorInfo,\n setVisitorInfo,\n sendMessage,\n sendFile,\n }\n}","import { io, Socket } from 'socket.io-client'\nimport type { ChatConfig } from '../types'\n\nlet socket: Socket | null = null\n\nexport const createSocket = (config: ChatConfig): Socket => {\n if (socket) {\n socket.disconnect()\n socket = null\n }\n\n const { serverUrl, token, visitorId } = config\n\n socket = io(serverUrl, {\n transports: ['websocket', 'polling'],\n auth: {\n ...(token ? { token } : {}),\n ...(visitorId ? { visitorId } : {}),\n },\n autoConnect: false,\n })\n\n return socket\n}\n\nexport const getSocket = (config: ChatConfig): Socket => {\n if (socket) return socket\n return createSocket(config)\n}\n\nexport const destroySocket = (): void => {\n if (socket) {\n socket.disconnect()\n socket = null\n }\n}","import { create } from 'zustand'\nimport type {\n ChatState,\n ChatMessage,\n UserRole,\n SocketError,\n VisitorInfo,\n ConnectionStatus,\n} from '../types'\n\ntype ChatActions = {\n setStatus: (status: ConnectionStatus) => void\n setRole: (role: UserRole) => void\n setVisitorId: (id: string) => void\n setChatId: (id: string) => void\n addMessage: (message: ChatMessage) => void\n setError: (error: SocketError | null) => void\n setVisitorInfo: (info: VisitorInfo) => void\n reset: () => void\n}\n\nconst initialState: ChatState = {\n status: 'idle',\n role: null,\n visitorId: null,\n chatId: null,\n messages: [],\n error: null,\n visitorInfo: null,\n}\n\nexport const useChatStore = create<ChatState & ChatActions>((set) => ({\n ...initialState,\n\n setStatus: (status) => set({ status }),\n setRole: (role) => set({ role }),\n setVisitorId: (id) => set({ visitorId: id }),\n setChatId: (id) => set({ chatId: id }),\n addMessage: (message) =>\n set((state) => ({\n messages: [...state.messages, message],\n })),\n setError: (error) => set({ error }),\n setVisitorInfo: (info) => set({ visitorInfo: info }),\n reset: () => set(initialState),\n}))","import React, { useEffect, useState } from \"react\";\nimport { css } from \"@emotion/css\";\n\nconst BUTTON_SIZE = 56;\n\ninterface Props {\n isOpen: boolean;\n onToggle: () => void;\n}\n\nexport const FloatingButton: React.FC<Props> = ({ isOpen, onToggle }) => {\n const [isMobile, setIsMobile] = useState(false);\n\n useEffect(() => {\n const check = () => setIsMobile(window.innerWidth <= 480);\n check();\n window.addEventListener(\"resize\", check);\n return () => window.removeEventListener(\"resize\", check);\n }, []);\n\n if (isMobile && isOpen) {\n return (\n <button\n className={styles.mobileCloseBtn}\n onClick={onToggle}\n type=\"button\"\n >\n <svg\n width=\"22\"\n height=\"22\"\n viewBox=\"0 0 24 24\"\n fill=\"none\"\n stroke=\"currentColor\"\n strokeWidth=\"2.5\"\n strokeLinecap=\"round\"\n >\n <line x1=\"18\" y1=\"6\" x2=\"6\" y2=\"18\" />\n <line x1=\"6\" y1=\"6\" x2=\"18\" y2=\"18\" />\n </svg>\n </button>\n );\n }\n\n return (\n <button className={styles.btn} onClick={onToggle} type=\"button\">\n <span className={styles.icon(!isOpen)}>\n <svg width=\"24\" height=\"24\" viewBox=\"0 0 24 24\" fill=\"currentColor\">\n <path d=\"M20 2H4a2 2 0 0 0-2 2v18l4-4h14a2 2 0 0 0 2-2V4a2 2 0 0 0-2-2z\" />\n </svg>\n </span>\n <span className={styles.icon(isOpen)}>\n <svg\n width=\"20\"\n height=\"20\"\n viewBox=\"0 0 24 24\"\n fill=\"none\"\n stroke=\"currentColor\"\n strokeWidth=\"2.5\"\n strokeLinecap=\"round\"\n >\n <line x1=\"18\" y1=\"6\" x2=\"6\" y2=\"18\" />\n <line x1=\"6\" y1=\"6\" x2=\"18\" y2=\"18\" />\n </svg>\n </span>\n </button>\n );\n};\n\nconst styles = {\n btn: css`\n position: fixed;\n right: 30px;\n bottom: 20px;\n width: ${BUTTON_SIZE}px;\n height: ${BUTTON_SIZE}px;\n border-radius: 50%;\n background: var(--wds-primary);\n color: #fff;\n border: none;\n cursor: pointer;\n box-shadow: 0 4px 20px rgba(0, 0, 0, 0.18);\n z-index: 999999;\n display: flex;\n align-items: center;\n justify-content: center;\n user-select: none;\n -webkit-user-select: none;\n &:hover {\n opacity: 0.92;\n }\n `,\n mobileCloseBtn: css`\n position: fixed;\n top: 16px;\n right: 20px;\n width: ${BUTTON_SIZE}px;\n height: ${BUTTON_SIZE}px;\n border-radius: 50%;\n background: var(--wds-primary);\n color: #fff;\n border: none;\n cursor: pointer;\n box-shadow: 0 4px 20px rgba(0, 0, 0, 0.25);\n z-index: 999999;\n display: flex;\n align-items: center;\n justify-content: center;\n `,\n icon: (visible: boolean) => css`\n position: absolute;\n display: flex;\n align-items: center;\n justify-content: center;\n transition:\n opacity 0.2s,\n transform 0.2s;\n opacity: ${visible ? 1 : 0};\n transform: ${visible ? \"scale(1)\" : \"scale(0.6) rotate(30deg)\"};\n pointer-events: ${visible ? \"auto\" : \"none\"};\n `,\n};\n","import React from 'react'\nimport { css } from '@emotion/css'\n\ninterface Props {\n isOpen: boolean\n isExpanded: boolean\n children: React.ReactNode\n}\n\nexport const ChatPanel: React.FC<Props> = ({ isOpen, isExpanded, children }) => {\n return (\n <div data-wds-root className={styles.panel(isOpen, isExpanded)}>\n <div className={styles.inner}>{children}</div>\n </div>\n )\n}\n\nconst styles = {\n panel: (isOpen: boolean, isExpanded: boolean) => css`\n position: fixed;\n bottom: 86px;\n z-index: 999998;\n transition: opacity 0.2s, transform 0.25s cubic-bezier(0.34, 1.2, 0.64, 1);\n opacity: ${isOpen ? 1 : 0};\n pointer-events: ${isOpen ? 'auto' : 'none'};\n\n ${isExpanded\n ? `\n width: min(760px, calc(100vw - 32px));\n height: min(780px, calc(100vh - 120px));\n border-radius: 20px;\n box-shadow: 0 20px 60px rgba(0,0,0,0.2), 0 4px 16px rgba(0,0,0,0.1);\n left: 50%;\n right: auto;\n translate: -50% 0;\n transform: ${isOpen ? 'scale(1)' : 'scale(0.95)'};\n transform-origin: bottom center;\n `\n : `\n width: 400px;\n height: 620px;\n border-radius: 20px;\n box-shadow: 0 12px 48px rgba(0,0,0,0.16), 0 2px 8px rgba(0,0,0,0.08);\n right: 22px;\n transform: ${isOpen ? 'translateY(0) scale(1)' : 'translateY(16px) scale(0.97)'};\n `}\n\n overflow: hidden;\n\n @media (max-width: 480px) {\n top: 0 !important;\n left: 0 !important;\n right: 0 !important;\n bottom: 0 !important;\n width: 100% !important;\n height: 100% !important;\n border-radius: 0 !important;\n translate: none !important;\n }\n `,\n inner: css`\n width: 100%;\n height: 100%;\n overflow: hidden;\n border-radius: inherit;\n `,\n}","import React from 'react'\nimport { css } from '@emotion/css'\n\ninterface Props {\n onStartChat: () => void\n onContinueChat: () => void\n hasHistory: boolean\n onExpand: () => void\n isExpanded: boolean\n}\n\nexport const HomeScreen: React.FC<Props> = ({\n onStartChat,\n onContinueChat,\n hasHistory,\n onExpand,\n isExpanded,\n}) => {\n return (\n <div className={styles.wrapper}>\n <div className={styles.topBar}>\n <div className={styles.logoMark}>\n <img\n src=\"https://cdn.waysdrop.com/bulk/horizon_20260411202129966_d25edae2.png\"\n alt=\"Waysdrop\"\n style={{ width: '100%', height: '100%', objectFit: 'contain' }}\n />\n </div>\n <button className={styles.expandBtn} onClick={onExpand}>\n {isExpanded ? (\n <svg width=\"15\" height=\"15\" viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" strokeWidth=\"2\" strokeLinecap=\"round\" strokeLinejoin=\"round\">\n <polyline points=\"4 14 10 14 10 20\"/><polyline points=\"20 10 14 10 14 4\"/>\n <line x1=\"10\" y1=\"14\" x2=\"3\" y2=\"21\"/><line x1=\"21\" y1=\"3\" x2=\"14\" y2=\"10\"/>\n </svg>\n ) : (\n <svg width=\"15\" height=\"15\" viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" strokeWidth=\"2\" strokeLinecap=\"round\" strokeLinejoin=\"round\">\n <polyline points=\"15 3 21 3 21 9\"/><polyline points=\"9 21 3 21 3 15\"/>\n <line x1=\"21\" y1=\"3\" x2=\"14\" y2=\"10\"/><line x1=\"3\" y1=\"21\" x2=\"10\" y2=\"14\"/>\n </svg>\n )}\n </button>\n </div>\n\n <div className={styles.hero}>\n <h2 className={styles.heroTitle}>Hi there! ๐Ÿ‘‹</h2>\n <p className={styles.heroSub}>We're here to help. Ask us anything or share your feedback.</p>\n </div>\n\n <div className={styles.section}>\n <p className={styles.sectionLabel}>Conversations</p>\n {hasHistory ? (\n <button className={styles.conversationCard} onClick={onContinueChat}>\n <div className={styles.cardIcon}>\n <svg width=\"16\" height=\"16\" viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" 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 </div>\n <div className={styles.cardBody}>\n <span className={styles.cardTitle}>Continue conversation</span>\n <span className={styles.cardSub}>Tap to resume your last chat</span>\n </div>\n <svg width=\"14\" height=\"14\" viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" strokeWidth=\"2\" strokeLinecap=\"round\" strokeLinejoin=\"round\">\n <polyline points=\"9 18 15 12 9 6\"/>\n </svg>\n </button>\n ) : (\n <div className={styles.emptyHistory}>\n <svg width=\"32\" height=\"32\" viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" strokeWidth=\"1.5\" strokeLinecap=\"round\" strokeLinejoin=\"round\" style={{ opacity: 0.25 }}>\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 <p>No previous conversations</p>\n </div>\n )}\n </div>\n\n <div className={styles.footer}>\n <button className={styles.startBtn} onClick={onStartChat}>\n New conversation\n <svg width=\"15\" height=\"15\" viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" strokeWidth=\"2.5\" strokeLinecap=\"round\" strokeLinejoin=\"round\">\n <polyline points=\"9 18 15 12 9 6\"/>\n </svg>\n </button>\n <p className={styles.poweredBy}>Powered by Waysdrop</p>\n </div>\n </div>\n )\n}\n\nconst styles = {\n wrapper: css`\n display: flex;\n flex-direction: column;\n height: 100%;\n background: var(--wds-bg);\n text-align: left;\n `,\n topBar: css`\n display: flex;\n align-items: center;\n justify-content: space-between;\n padding: 18px 18px 0;\n flex-shrink: 0;\n `,\n logoMark: css`\n width: 48px;\n height: 48px;\n flex-shrink: 0;\n `,\n expandBtn: css`\n background: none;\n border: none;\n cursor: pointer;\n color: var(--wds-muted);\n padding: 8px;\n border-radius: 8px;\n display: flex;\n align-items: center;\n justify-content: center;\n transition: color 0.15s, background 0.15s;\n &:hover {\n color: var(--wds-fg);\n background: var(--wds-muted-bg);\n }\n @media (max-width: 480px) {\n display: none;\n }\n `,\n hero: css`\n padding: 20px 20px 16px;\n display: flex;\n flex-direction: column;\n align-items: flex-start;\n gap: 10px;\n flex-shrink: 0;\n `,\n heroTitle: css`\n font-size: 1.375rem;\n font-weight: 700;\n color: var(--wds-fg);\n margin: 0;\n line-height: 1.2;\n text-align: left;\n `,\n heroSub: css`\n font-size: 0.9375rem;\n color: var(--wds-muted);\n margin: 0;\n line-height: 1.6;\n text-align: left;\n `,\n section: css`\n flex: 1;\n padding: 4px 18px 0;\n overflow-y: auto;\n `,\n sectionLabel: css`\n font-size: 11px;\n font-weight: 600;\n letter-spacing: 0.07em;\n text-transform: uppercase;\n color: var(--wds-muted);\n margin: 0 0 12px 2px;\n text-align: left;\n `,\n conversationCard: css`\n display: flex;\n align-items: center;\n gap: 14px;\n width: 100%;\n padding: 14px 16px;\n background: var(--wds-muted-bg);\n border: 1px solid var(--wds-border);\n border-radius: 14px;\n cursor: pointer;\n text-align: left;\n transition: border-color 0.15s, background 0.15s;\n color: var(--wds-fg);\n &:hover {\n border-color: var(--wds-primary);\n background: var(--wds-primary-soft);\n }\n `,\n cardIcon: css`\n width: 38px;\n height: 38px;\n border-radius: 10px;\n background: var(--wds-primary-soft);\n color: var(--wds-primary);\n display: flex;\n align-items: center;\n justify-content: center;\n flex-shrink: 0;\n `,\n cardBody: css`\n flex: 1;\n display: flex;\n flex-direction: column;\n gap: 3px;\n `,\n cardTitle: css`\n font-size: 0.875rem;\n font-weight: 600;\n color: var(--wds-fg);\n text-align: left;\n `,\n cardSub: css`\n font-size: 12px;\n color: var(--wds-muted);\n text-align: left;\n `,\n emptyHistory: css`\n display: flex;\n flex-direction: column;\n align-items: center;\n gap: 10px;\n padding: 40px 0;\n color: var(--wds-muted);\n font-size: 12px;\n `,\n footer: css`\n padding: 18px 18px 16px;\n display: flex;\n flex-direction: column;\n gap: 12px;\n align-items: center;\n flex-shrink: 0;\n border-top: 1px solid var(--wds-border);\n `,\n startBtn: css`\n display: flex;\n align-items: center;\n justify-content: center;\n gap: 6px;\n width: 100%;\n padding: 13px 16px;\n background: var(--wds-primary);\n color: #fff;\n border: none;\n border-radius: 14px;\n font-size: 0.9375rem;\n font-weight: 600;\n cursor: pointer;\n transition: opacity 0.15s;\n font-family: inherit;\n &:hover { opacity: 0.88; }\n `,\n poweredBy: css`\n font-size: 11px;\n color: var(--wds-muted);\n margin: 0;\n opacity: 0.7;\n `,\n}","import React, { useEffect, useRef, useState } from \"react\";\nimport { css, keyframes } from \"@emotion/css\";\nimport { ChatMessage } from \"../types\";\nimport { MessageBubble } from \"./MessageBubble\";\nimport { ChatInput } from \"./ChatInput\";\n\ninterface Props {\n messages: ChatMessage[];\n onSendText: (content: string) => void;\n onSendFile: (file: File, content?: string) => Promise<void>;\n onBack: () => void;\n onExpand: () => void;\n isExpanded: boolean;\n status: string;\n error: { code: number; message: string } | null;\n}\n\nexport const ChatScreen: React.FC<Props> = ({\n messages,\n onSendText,\n onSendFile,\n onBack,\n onExpand,\n isExpanded,\n status,\n error,\n}) => {\n const bottomRef = useRef<HTMLDivElement>(null);\n const scrollRef = useRef<HTMLDivElement>(null);\n const connected = status === \"connected\";\n const [showScrollBtn, setShowScrollBtn] = useState(false);\n\n const lastMsg = messages[messages.length - 1];\n const isThinking = connected && lastMsg?.direction === \"INBOUND\";\n\n useEffect(() => {\n bottomRef.current?.scrollIntoView({ behavior: \"smooth\" });\n }, [messages]);\n\n const handleScroll = () => {\n const el = scrollRef.current;\n if (!el) return;\n setShowScrollBtn(el.scrollHeight - el.scrollTop - el.clientHeight > 80);\n };\n\n return (\n <div className={styles.wrapper}>\n <div className={styles.header}>\n <button className={styles.iconBtn} onClick={onBack}>\n <svg\n width=\"18\"\n height=\"18\"\n viewBox=\"0 0 24 24\"\n fill=\"none\"\n stroke=\"currentColor\"\n strokeWidth=\"2\"\n strokeLinecap=\"round\"\n strokeLinejoin=\"round\"\n >\n <polyline points=\"15 18 9 12 15 6\" />\n </svg>\n </button>\n\n <div className={styles.headerCenter}>\n <span className={styles.headerTitle}>Support</span>\n <span className={styles.statusDot(connected)} />\n <span className={styles.statusLabel}>\n {connected ? \"Online\" : \"Connecting...\"}\n </span>\n </div>\n\n <button className={styles.expandBtn} onClick={onExpand}>\n {isExpanded ? (\n <svg\n width=\"16\"\n height=\"16\"\n viewBox=\"0 0 24 24\"\n fill=\"none\"\n stroke=\"currentColor\"\n strokeWidth=\"2\"\n strokeLinecap=\"round\"\n strokeLinejoin=\"round\"\n >\n <polyline points=\"4 14 10 14 10 20\" />\n <polyline points=\"20 10 14 10 14 4\" />\n <line x1=\"10\" y1=\"14\" x2=\"3\" y2=\"21\" />\n <line x1=\"21\" y1=\"3\" x2=\"14\" y2=\"10\" />\n </svg>\n ) : (\n <svg\n width=\"16\"\n height=\"16\"\n viewBox=\"0 0 24 24\"\n fill=\"none\"\n stroke=\"currentColor\"\n strokeWidth=\"2\"\n strokeLinecap=\"round\"\n strokeLinejoin=\"round\"\n >\n <polyline points=\"15 3 21 3 21 9\" />\n <polyline points=\"9 21 3 21 3 15\" />\n <line x1=\"21\" y1=\"3\" x2=\"14\" y2=\"10\" />\n <line x1=\"3\" y1=\"21\" x2=\"10\" y2=\"14\" />\n </svg>\n )}\n </button>\n </div>\n\n <div className={styles.messagesWrap}>\n <div\n className={styles.messages}\n ref={scrollRef}\n onScroll={handleScroll}\n >\n {error && <div className={styles.errorBanner}>{error.message}</div>}\n {messages.length === 0 && connected && (\n <div className={styles.emptyState}>\n <p>Send a message to start the conversation.</p>\n </div>\n )}\n {messages.map((msg) => (\n <MessageBubble key={msg.id} message={msg} />\n ))}\n <div ref={bottomRef} />\n </div>\n\n {showScrollBtn && (\n <button\n className={styles.scrollBtn}\n onClick={() =>\n bottomRef.current?.scrollIntoView({ behavior: \"smooth\" })\n }\n >\n <svg\n width=\"14\"\n height=\"14\"\n viewBox=\"0 0 24 24\"\n fill=\"none\"\n stroke=\"currentColor\"\n strokeWidth=\"2.5\"\n strokeLinecap=\"round\"\n strokeLinejoin=\"round\"\n >\n <polyline points=\"6 9 12 15 18 9\" />\n </svg>\n </button>\n )}\n </div>\n\n <ChatInput\n onSendText={onSendText}\n onSendFile={onSendFile}\n disabled={!connected}\n isThinking={isThinking}\n />\n </div>\n );\n};\n\nconst pulse = keyframes`\n 0%, 100% { opacity: 1; }\n 50% { opacity: 0.4; }\n`;\n\nconst styles = {\n wrapper: css`\n display: flex;\n flex-direction: column;\n height: 100%;\n background: var(--wds-bg);\n `,\n header: css`\n display: flex;\n align-items: center;\n gap: 10px;\n padding: 12px 14px;\n border-bottom: 1px solid var(--wds-border);\n flex-shrink: 0;\n `,\n headerCenter: css`\n flex: 1;\n display: flex;\n align-items: center;\n gap: 6px;\n `,\n headerTitle: css`\n font-size: 0.875rem;\n font-weight: 600;\n color: var(--wds-fg);\n `,\n statusDot: (connected: boolean) => css`\n width: 7px;\n height: 7px;\n border-radius: 50%;\n flex-shrink: 0;\n background: ${connected ? \"#22c55e\" : \"#f59e0b\"};\n animation: ${connected ? \"none\" : `${pulse} 1.2s ease-in-out infinite`};\n `,\n statusLabel: css`\n font-size: 11px;\n color: var(--wds-muted);\n `,\n iconBtn: css`\n background: none;\n border: none;\n cursor: pointer;\n color: var(--wds-muted);\n padding: 6px;\n border-radius: 8px;\n display: flex;\n align-items: center;\n justify-content: center;\n flex-shrink: 0;\n transition:\n color 0.15s,\n background 0.15s;\n &:hover {\n color: var(--wds-fg);\n background: var(--wds-muted-bg);\n }\n `,\n expandBtn: css`\n background: none;\n border: none;\n cursor: pointer;\n color: var(--wds-muted);\n padding: 6px;\n border-radius: 8px;\n display: flex;\n align-items: center;\n justify-content: center;\n flex-shrink: 0;\n transition:\n color 0.15s,\n background 0.15s;\n &:hover {\n color: var(--wds-fg);\n background: var(--wds-muted-bg);\n }\n @media (max-width: 480px) {\n display: none;\n }\n `,\n messagesWrap: css`\n flex: 1;\n position: relative;\n overflow: hidden;\n `,\n messages: css`\n position: absolute;\n inset: 0;\n overflow-y: auto;\n padding: 16px 14px;\n display: flex;\n flex-direction: column;\n gap: 10px;\n `,\n errorBanner: css`\n background: oklch(0.9705 0.0129 17.04);\n color: oklch(0.5054 0.1905 27.51);\n border: 1px solid oklch(0.8845 0.0592 18.27);\n border-radius: 8px;\n padding: 8px 12px;\n font-size: 12px;\n text-align: center;\n `,\n emptyState: css`\n flex: 1;\n display: flex;\n align-items: center;\n justify-content: center;\n color: var(--wds-muted);\n font-size: 13px;\n text-align: center;\n padding: 40px 20px;\n `,\n scrollBtn: css`\n position: absolute;\n bottom: 12px;\n left: 50%;\n transform: translateX(-50%);\n width: 30px;\n height: 30px;\n border-radius: 50%;\n background: var(--wds-bg);\n border: 1px solid var(--wds-border);\n color: var(--wds-muted);\n display: flex;\n align-items: center;\n justify-content: center;\n cursor: pointer;\n box-shadow: 0 2px 8px rgba(0, 0, 0, 0.12);\n transition:\n color 0.15s,\n border-color 0.15s;\n &:hover {\n color: var(--wds-primary);\n border-color: var(--wds-primary);\n }\n `,\n};\n","import React from 'react'\nimport { css } from '@emotion/css'\nimport { ChatMessage } from '../types'\nimport { MarkdownRenderer } from './MarkdownRenderer'\n\nfunction formatTime(iso: string): string {\n return new Date(iso).toLocaleTimeString([], { hour: '2-digit', minute: '2-digit' })\n}\n\ninterface Props {\n message: ChatMessage\n}\n\nexport const MessageBubble: React.FC<Props> = ({ message }) => {\n const isCustomer = message.direction === 'OUTBOUND'\n const isBot = message.senderRole === 'BOT'\n\n return (\n <div className={styles.row(isCustomer)}>\n <div className={styles.group(isCustomer)}>\n {isBot && <span className={styles.botLabel}>Ways AI</span>}\n <div className={styles.bubble(isCustomer)}>\n {message.file && (\n <a href={message.file} target=\"_blank\" rel=\"noreferrer\" className={styles.fileLink(!!message.content)}>\n ๐Ÿ“Ž View attachment\n </a>\n )}\n {message.content && (\n isBot\n ? <MarkdownRenderer content={message.content} />\n : <p className={styles.text}>{message.content}</p>\n )}\n </div>\n <span className={styles.time}>{formatTime(message.createdAt)}</span>\n </div>\n </div>\n )\n}\n\nconst styles = {\n row: (isCustomer: boolean) => css`\n display: flex;\n width: 100%;\n justify-content: ${isCustomer ? 'flex-start' : 'flex-end'};\n `,\n group: (isCustomer: boolean) => css`\n display: flex;\n flex-direction: column;\n max-width: 78%;\n gap: 4px;\n align-items: ${isCustomer ? 'flex-start' : 'flex-end'};\n `,\n botLabel: css`\n font-size: 10px;\n color: var(--wds-muted);\n padding: 0 4px;\n font-weight: 500;\n letter-spacing: 0.03em;\n `,\n bubble: (isCustomer: boolean) => css`\n border-radius: 18px;\n padding: 10px 14px;\n word-break: break-word;\n text-align: left;\n border-top-left-radius: ${isCustomer ? '4px' : '18px'};\n border-top-right-radius: ${isCustomer ? '18px' : '4px'};\n background: ${isCustomer ? 'var(--wds-muted-bg)' : 'var(--wds-primary)'};\n color: ${isCustomer ? 'var(--wds-fg)' : '#fff'};\n `,\n text: css`\n font-size: 0.875rem;\n line-height: 1.5;\n margin: 0;\n white-space: pre-wrap;\n text-align: left;\n `,\n fileLink: (hasContent: boolean) => css`\n font-size: 0.875rem;\n color: inherit;\n text-decoration: underline;\n display: block;\n text-align: left;\n ${hasContent ? 'margin-bottom: 6px;' : ''}\n `,\n time: css`\n font-size: 10px;\n color: var(--wds-muted);\n padding: 0 4px;\n `,\n}","import React from 'react'\nimport ReactMarkdown from 'react-markdown'\nimport { css } from '@emotion/css'\n\nconst markdownStyle = css`\n font-size: 0.875rem;\n line-height: 1.6;\n color: inherit;\n text-align: left;\n\n p {\n margin: 0 0 0.6rem 0;\n text-align: left;\n }\n p:last-child {\n margin-bottom: 0;\n }\n strong { font-weight: 600; }\n em { font-style: italic; }\n\n ul, ol {\n margin: 0.4rem 0 0.6rem 0;\n padding-left: 1.4rem;\n text-align: left;\n }\n ul { list-style-type: disc; }\n ol { list-style-type: decimal; }\n li {\n margin-bottom: 0.3rem;\n }\n li > ul, li > ol {\n margin: 0.25rem 0 0.25rem 0;\n padding-left: 1.2rem;\n }\n li:last-child { margin-bottom: 0; }\n\n hr {\n border: none;\n border-top: 1px solid rgba(255, 255, 255, 0.25);\n margin: 0.75rem 0;\n }\n\n code {\n font-family: monospace;\n font-size: 0.8rem;\n background: rgba(255,255,255,0.15);\n border-radius: 4px;\n padding: 0.1rem 0.35rem;\n }\n pre {\n background: rgba(255,255,255,0.1);\n border-radius: 8px;\n padding: 0.75rem 1rem;\n overflow-x: auto;\n margin: 0.5rem 0;\n }\n pre code {\n background: none;\n padding: 0;\n font-size: 0.78rem;\n }\n blockquote {\n border-left: 3px solid rgba(255,255,255,0.25);\n margin: 0.5rem 0;\n padding-left: 0.75rem;\n opacity: 0.8;\n }\n a {\n color: rgba(255,255,255,0.85);\n text-decoration: underline;\n }\n h1, h2, h3 {\n font-weight: 600;\n margin: 0.6rem 0 0.3rem;\n line-height: 1.3;\n text-align: left;\n }\n h1 { font-size: 1rem; }\n h2 { font-size: 0.95rem; }\n h3 { font-size: 0.875rem; }\n`\n\ninterface Props {\n content: string\n}\n\nexport const MarkdownRenderer: React.FC<Props> = ({ content }) => {\n return (\n <div className={markdownStyle}>\n <ReactMarkdown>{content}</ReactMarkdown>\n </div>\n )\n}","import React, { useState, useRef, useCallback, KeyboardEvent } from 'react'\nimport { css, keyframes } from '@emotion/css'\n\nconst spin = keyframes`\n to { transform: rotate(360deg); }\n`\n\nconst pulse = keyframes`\n 0%, 100% { opacity: 0.4; transform: scaleY(0.6); }\n 50% { opacity: 1; transform: scaleY(1); }\n`\n\ninterface Props {\n onSendText: (content: string) => void\n onSendFile: (file: File, content?: string) => Promise<void>\n disabled?: boolean\n isThinking?: boolean\n}\n\nexport const ChatInput: React.FC<Props> = ({ onSendText, onSendFile, disabled, isThinking }) => {\n const [value, setValue] = useState('')\n const [uploading, setUploading] = useState(false)\n const [pendingFile, setPendingFile] = useState<File | null>(null)\n const [pendingPreview, setPendingPreview] = useState<string | null>(null)\n const textareaRef = useRef<HTMLTextAreaElement>(null)\n const fileInputRef = useRef<HTMLInputElement>(null)\n\n const handleSend = useCallback(() => {\n const trimmed = value.trim()\n if ((!trimmed && !pendingFile) || disabled || uploading) return\n\n if (pendingFile) {\n setUploading(true)\n onSendFile(pendingFile, trimmed || undefined).finally(() => {\n setUploading(false)\n setPendingFile(null)\n setPendingPreview(null)\n setValue('')\n })\n } else if (trimmed) {\n onSendText(trimmed)\n setValue('')\n }\n\n textareaRef.current?.focus()\n }, [value, pendingFile, disabled, uploading, onSendText, onSendFile])\n\n const handleKeyDown = (e: KeyboardEvent<HTMLTextAreaElement>) => {\n if (e.key === 'Enter' && !e.shiftKey) {\n e.preventDefault()\n handleSend()\n }\n }\n\n const handleFileChange = (e: React.ChangeEvent<HTMLInputElement>) => {\n const file = e.target.files?.[0]\n if (!file) return\n if (!file.type.startsWith('image/')) return\n setPendingFile(file)\n const reader = new FileReader()\n reader.onload = (ev) => setPendingPreview(ev.target?.result as string)\n reader.readAsDataURL(file)\n e.target.value = ''\n }\n\n const canSend = (value.trim() || pendingFile) && !disabled && !uploading\n\n return (\n <div className={styles.wrapper}>\n {isThinking && (\n <div className={styles.thinkingBar}>\n <div className={styles.thinkingDots}>\n <span className={styles.dot(0)} />\n <span className={styles.dot(1)} />\n <span className={styles.dot(2)} />\n </div>\n <span className={styles.thinkingLabel}>Ways AI is typing...</span>\n </div>\n )}\n\n {pendingPreview && (\n <div className={styles.imagePreview}>\n <img src={pendingPreview} alt=\"attachment\" className={styles.previewImg} />\n <button className={styles.removeFile} onClick={() => { setPendingFile(null); setPendingPreview(null) }}>\n <svg width=\"12\" height=\"12\" viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" strokeWidth=\"2.5\" strokeLinecap=\"round\">\n <line x1=\"18\" y1=\"6\" x2=\"6\" y2=\"18\"/><line x1=\"6\" y1=\"6\" x2=\"18\" y2=\"18\"/>\n </svg>\n </button>\n </div>\n )}\n\n <div className={styles.inputRow}>\n <button\n className={styles.attachBtn}\n onClick={() => fileInputRef.current?.click()}\n disabled={disabled || uploading}\n type=\"button\"\n >\n <svg width=\"18\" height=\"18\" viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" strokeWidth=\"2\" strokeLinecap=\"round\" strokeLinejoin=\"round\">\n <rect x=\"3\" y=\"3\" width=\"18\" height=\"18\" rx=\"3\"/><circle cx=\"8.5\" cy=\"8.5\" r=\"1.5\"/><polyline points=\"21 15 16 10 5 21\"/>\n </svg>\n </button>\n\n <input\n ref={fileInputRef}\n type=\"file\"\n accept=\"image/*\"\n className={styles.hiddenInput}\n onChange={handleFileChange}\n />\n\n <textarea\n ref={textareaRef}\n className={styles.textarea}\n value={value}\n onChange={(e) => setValue(e.target.value)}\n onKeyDown={handleKeyDown}\n placeholder=\"Type a message...\"\n disabled={disabled || uploading}\n rows={1}\n />\n\n <button className={styles.sendBtn} onClick={handleSend} disabled={!canSend} type=\"button\">\n {uploading ? (\n <span className={styles.spinner} />\n ) : (\n <svg width=\"16\" height=\"16\" viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" strokeWidth=\"2.5\" strokeLinecap=\"round\" strokeLinejoin=\"round\">\n <line x1=\"12\" y1=\"19\" x2=\"12\" y2=\"5\"/><polyline points=\"5 12 12 5 19 12\"/>\n </svg>\n )}\n </button>\n </div>\n\n <p className={styles.hint}>Enter to send ยท Shift+Enter for new line</p>\n </div>\n )\n}\n\nconst styles = {\n wrapper: css`\n padding: 8px 12px 10px;\n border-top: 1px solid var(--wds-border);\n display: flex;\n flex-direction: column;\n gap: 6px;\n background: var(--wds-bg);\n flex-shrink: 0;\n `,\n thinkingBar: css`\n display: flex;\n align-items: center;\n gap: 8px;\n padding: 6px 2px 2px;\n `,\n thinkingDots: css`\n display: flex;\n align-items: center;\n gap: 3px;\n `,\n dot: (i: number) => css`\n width: 5px;\n height: 5px;\n border-radius: 50%;\n background: var(--wds-primary);\n animation: ${pulse} 1.2s ease-in-out infinite;\n animation-delay: ${i * 0.18}s;\n display: inline-block;\n `,\n thinkingLabel: css`\n font-size: 11px;\n color: var(--wds-muted);\n `,\n imagePreview: css`\n position: relative;\n width: fit-content;\n margin: 0 2px;\n `,\n previewImg: css`\n width: 72px;\n height: 72px;\n object-fit: cover;\n border-radius: 10px;\n border: 1px solid var(--wds-border);\n display: block;\n `,\n removeFile: css`\n position: absolute;\n top: -6px;\n right: -6px;\n width: 18px;\n height: 18px;\n border-radius: 50%;\n background: var(--wds-fg);\n color: var(--wds-bg);\n border: none;\n cursor: pointer;\n display: flex;\n align-items: center;\n justify-content: center;\n padding: 0;\n `,\n inputRow: css`\n display: flex;\n align-items: center;\n gap: 6px;\n background: var(--wds-muted-bg);\n border: 1px solid var(--wds-border);\n border-radius: 14px;\n padding: 4px 4px 4px 8px;\n transition: border-color 0.15s;\n &:focus-within {\n border-color: var(--wds-primary);\n background: var(--wds-bg);\n }\n `,\n attachBtn: css`\n background: none;\n border: none;\n cursor: pointer;\n color: var(--wds-muted);\n padding: 5px;\n border-radius: 8px;\n display: flex;\n align-items: center;\n justify-content: center;\n flex-shrink: 0;\n transition: color 0.15s;\n &:hover:not(:disabled) {\n color: var(--wds-primary);\n }\n &:disabled {\n opacity: 0.35;\n cursor: not-allowed;\n }\n `,\n hiddenInput: css`\n display: none;\n `,\n textarea: css`\n flex: 1;\n resize: none;\n border: none;\n padding: 6px 0;\n font-size: 0.875rem;\n font-family: inherit;\n line-height: 1.5;\n background: transparent;\n color: var(--wds-fg);\n outline: none;\n max-height: 120px;\n overflow-y: auto;\n &::placeholder { color: var(--wds-muted); }\n &:disabled {\n opacity: 0.5;\n cursor: not-allowed;\n }\n `,\n sendBtn: css`\n background: var(--wds-primary);\n border: none;\n border-radius: 10px;\n width: 34px;\n height: 34px;\n display: flex;\n align-items: center;\n justify-content: center;\n cursor: pointer;\n color: #fff;\n flex-shrink: 0;\n transition: opacity 0.15s;\n &:disabled {\n opacity: 0.35;\n cursor: not-allowed;\n }\n &:hover:not(:disabled) { opacity: 0.85; }\n `,\n spinner: css`\n width: 14px;\n height: 14px;\n border: 2px solid rgba(255,255,255,0.3);\n border-top-color: #fff;\n border-radius: 50%;\n animation: ${spin} 0.7s linear infinite;\n display: block;\n `,\n hint: css`\n font-size: 10px;\n color: var(--wds-muted);\n margin: 0;\n text-align: center;\n opacity: 0.7;\n text-align: center;\n `,\n}"],"mappings":"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","names":["useEffect","useState","socket","useEffect","css","jsx","styles","css","jsx","jsxs","styles","useEffect","useRef","useState","css","keyframes","css","css","jsx","jsx","jsxs","styles","css","useState","useCallback","css","jsx","jsxs","_a","styles","jsx","jsxs","useRef","useState","useEffect","styles","pulse","keyframes","css","jsx","jsxs","useState","useEffect"]}
1
+ {"version":3,"sources":["../src/components/ChatWidget.tsx","../src/lib/upload.ts","../src/hooks/useChat.ts","../src/lib/socket.ts","../src/store/chatStore.ts","../src/components/FloatingButton.tsx","../src/components/ChatPanel.tsx","../src/components/HomeScreen.tsx","../src/components/ChatScreen.tsx","../src/components/MessageBubble.tsx","../src/components/MarkdownRenderer.tsx","../src/components/ChatInput.tsx"],"sourcesContent":["import React, { useEffect, useState } from 'react'\nimport { injectGlobal } from '@emotion/css'\nimport { ChatConfig } from '../types'\nimport { loadVisitorId } from '../lib/upload'\nimport { useChat } from '../hooks/useChat'\nimport { useChatStore } from '../store/chatStore'\nimport { FloatingButton } from './FloatingButton'\nimport { ChatPanel } from './ChatPanel'\nimport { HomeScreen } from './HomeScreen'\nimport { ChatScreen } from './ChatScreen'\n\nexport type ChatWidgetProps = {\n config: ChatConfig\n}\n\ntype View = 'home' | 'chat'\n\nconst LIGHT_VARS = `\n --wds-bg: oklch(1 0 0);\n --wds-fg: oklch(0.145 0 0);\n --wds-muted: oklch(0.556 0 0);\n --wds-muted-bg: oklch(0.97 0 0);\n --wds-border: oklch(0.922 0 0);\n`\n\nconst DARK_VARS = `\n --wds-bg: oklch(0.145 0 0);\n --wds-fg: oklch(0.985 0 0);\n --wds-muted: oklch(0.708 0 0);\n --wds-muted-bg: oklch(0.205 0 0);\n --wds-border: oklch(1 0 0 / 10%);\n`\n\nfunction buildPrimaryVars(color: string) {\n return `\n --wds-primary: ${color};\n --wds-primary-soft: color-mix(in oklch, ${color} 12%, transparent);\n --wds-primary-border: color-mix(in oklch, ${color} 40%, transparent);\n `\n}\n\nconst DEFAULT_PRIMARY = 'oklch(0.5811 0.2268 259.15)'\n\nfunction buildThemeStyle(theme: 'light' | 'dark' | 'system', primaryColor: string) {\n const primary = buildPrimaryVars(primaryColor)\n\n if (theme === 'light') {\n return `\n [data-wds-root] {\n ${LIGHT_VARS}\n ${primary}\n }\n `\n }\n\n if (theme === 'dark') {\n return `\n [data-wds-root] {\n ${DARK_VARS}\n ${primary}\n }\n `\n }\n\n return `\n [data-wds-root] {\n ${LIGHT_VARS}\n ${primary}\n }\n @media (prefers-color-scheme: dark) {\n [data-wds-root] {\n ${DARK_VARS}\n --wds-primary-soft: color-mix(in oklch, ${primaryColor} 15%, transparent);\n }\n }\n `\n}\n\nexport const ChatWidget: React.FC<ChatWidgetProps> = ({ config }) => {\n const [isOpen, setIsOpen] = useState(false)\n const [isExpanded, setIsExpanded] = useState(false)\n const [view, setView] = useState<View>('home')\n const [visitorId] = useState<string | undefined>(\n () => config.visitorId ?? loadVisitorId() ?? undefined\n )\n\n const reset = useChatStore((s) => s.reset)\n\n const resolvedConfig: ChatConfig = {\n ...config,\n visitorId,\n }\n\n const hasHistory = !!visitorId\n\n const { status, messages, error, sendMessage, sendFile } = useChat(resolvedConfig)\n\n const handleNewConversation = () => {\n reset()\n setView('chat')\n }\n\n useEffect(() => {\n const isMobile = window.innerWidth <= 480\n if (isMobile) {\n document.body.style.overflow = isOpen ? 'hidden' : ''\n }\n return () => {\n document.body.style.overflow = ''\n }\n }, [isOpen])\n\n useEffect(() => {\n const theme = config.theme ?? 'system'\n const primaryColor = config.primaryColor ?? DEFAULT_PRIMARY\n const style = buildThemeStyle(theme, primaryColor)\n const el = document.createElement('style')\n el.setAttribute('data-wds-theme', '')\n el.textContent = style\n document.head.appendChild(el)\n return () => {\n document.head.removeChild(el)\n }\n }, [config.theme, config.primaryColor])\n\n return (\n <>\n <FloatingButton\n isOpen={isOpen}\n onToggle={() => setIsOpen((p) => !p)}\n />\n\n <ChatPanel\n isOpen={isOpen}\n isExpanded={isExpanded}\n >\n {view === 'home' ? (\n <HomeScreen\n onStartChat={handleNewConversation}\n onContinueChat={() => setView('chat')}\n hasHistory={hasHistory}\n onExpand={() => setIsExpanded((p) => !p)}\n isExpanded={isExpanded}\n />\n ) : (\n <ChatScreen\n messages={messages}\n onSendText={sendMessage}\n onSendFile={sendFile}\n onBack={() => setView('home')}\n onExpand={() => setIsExpanded((p) => !p)}\n isExpanded={isExpanded}\n status={status}\n error={error}\n />\n )}\n </ChatPanel>\n </>\n )\n}\n\ninjectGlobal`\n [data-wds-root] * {\n box-sizing: border-box;\n text-align: left;\n }\n`","import type { ChatConfig } from \"../types\";\n\nconst VISITOR_ID_KEY = \"waysdrop_visitor_id\";\n\nexport const saveVisitorId = (id: string): void => {\n if (typeof window === 'undefined') return;\n localStorage.setItem(VISITOR_ID_KEY, id);\n};\n\nexport const loadVisitorId = (): string | null => {\n if (typeof window === 'undefined') return null;\n return localStorage.getItem(VISITOR_ID_KEY);\n};\n\nexport const clearVisitorId = (): void => {\n if (typeof window === 'undefined') return;\n localStorage.removeItem(VISITOR_ID_KEY);\n};\n\nexport const uploadFile = async (\n file: File,\n config: ChatConfig,\n): Promise<string> => {\n const formData = new FormData();\n formData.append(\"files\", file);\n\n const headers: HeadersInit = {};\n if (config.token) headers[\"Authorization\"] = `Bearer ${config.token}`;\n\n const res = await fetch(`${config.apiUrl}/file/bulk-upload`, {\n method: \"POST\",\n headers,\n body: formData,\n });\n\n if (!res.ok) {\n throw new Error(\"File upload failed\");\n }\n\n const json = await res.json();\n\n if (!json.success || !json.data?.urls?.length) {\n throw new Error(json.message || \"File upload failed\");\n }\n\n const first = json.data.urls[0];\n if (typeof first !== \"string\") {\n throw new Error(first?.error || \"File upload failed\");\n }\n\n return first;\n};","import { useEffect, useCallback } from 'react'\nimport { createSocket, getSocket, destroySocket } from '../lib/socket'\nimport { saveVisitorId, uploadFile } from '../lib/upload'\nimport { useChatStore } from '../store/chatStore'\nimport type {\n ChatConfig,\n ConnectedPayload,\n SupportMessageSentPayload,\n SupportNewMessagePayload,\n SocketError,\n SupportSendMessageDTO,\n VisitorInfo,\n} from '../types'\n\nexport const useChat = (config: ChatConfig) => {\n const {\n status,\n role,\n visitorId,\n chatId,\n messages,\n error,\n visitorInfo,\n setStatus,\n setRole,\n setVisitorId,\n setChatId,\n addMessage,\n setError,\n setVisitorInfo,\n reset,\n } = useChatStore()\n\n useEffect(() => {\n const socket = createSocket(config)\n\n setStatus('connecting')\n socket.connect()\n\n socket.on('connected', (payload: ConnectedPayload) => {\n setStatus('connected')\n setRole(payload.role)\n\n if (payload.role === 'VISITOR') {\n saveVisitorId(payload.visitorId)\n setVisitorId(payload.visitorId)\n }\n })\n\n socket.on('support-message-sent', (payload: SupportMessageSentPayload) => {\n setChatId(payload.chatId)\n addMessage(payload.message)\n })\n\n socket.on('support-new-message', (payload: SupportNewMessagePayload) => {\n setChatId(payload.chatId)\n addMessage(payload.message)\n })\n\n socket.on('error', (err: SocketError) => {\n setError(err)\n setStatus('error')\n })\n\n return () => {\n destroySocket()\n reset()\n }\n }, [config.token])\n\n const sendMessage = useCallback(\n (content: string, info?: VisitorInfo) => {\n const socket = getSocket(config)\n\n const dto: SupportSendMessageDTO = {\n content,\n externalId: `msg-${Date.now()}`,\n ...(info ?? visitorInfo\n ? {\n email: (info ?? visitorInfo)!.email,\n name: (info ?? visitorInfo)?.name,\n phone: (info ?? visitorInfo)?.phone,\n }\n : {}),\n }\n\n socket.emit('support-send-message', dto)\n },\n [config, visitorInfo]\n )\n\n const sendFile = useCallback(\n async (file: File, content?: string, info?: VisitorInfo) => {\n const url = await uploadFile(file, config)\n\n const socket = getSocket(config)\n\n const dto: SupportSendMessageDTO = {\n file: url,\n ...(content ? { content } : {}),\n externalId: `file-${Date.now()}`,\n ...(info ?? visitorInfo\n ? {\n email: (info ?? visitorInfo)!.email,\n name: (info ?? visitorInfo)?.name,\n phone: (info ?? visitorInfo)?.phone,\n }\n : {}),\n }\n\n socket.emit('support-send-message', dto)\n },\n [config, visitorInfo]\n )\n\n return {\n status,\n role,\n visitorId,\n chatId,\n messages,\n error,\n visitorInfo,\n setVisitorInfo,\n sendMessage,\n sendFile,\n }\n}","import { io, Socket } from 'socket.io-client'\nimport type { ChatConfig } from '../types'\n\nlet socket: Socket | null = null\n\nexport const createSocket = (config: ChatConfig): Socket => {\n if (socket) {\n socket.disconnect()\n socket = null\n }\n\n const { serverUrl, token, visitorId } = config\n\n socket = io(serverUrl, {\n transports: ['websocket', 'polling'],\n auth: {\n ...(token ? { token } : {}),\n ...(visitorId ? { visitorId } : {}),\n },\n autoConnect: false,\n })\n\n return socket\n}\n\nexport const getSocket = (config: ChatConfig): Socket => {\n if (socket) return socket\n return createSocket(config)\n}\n\nexport const destroySocket = (): void => {\n if (socket) {\n socket.disconnect()\n socket = null\n }\n}","import { create } from 'zustand'\nimport type {\n ChatState,\n ChatMessage,\n UserRole,\n SocketError,\n VisitorInfo,\n ConnectionStatus,\n} from '../types'\n\ntype ChatActions = {\n setStatus: (status: ConnectionStatus) => void\n setRole: (role: UserRole) => void\n setVisitorId: (id: string) => void\n setChatId: (id: string) => void\n addMessage: (message: ChatMessage) => void\n setError: (error: SocketError | null) => void\n setVisitorInfo: (info: VisitorInfo) => void\n reset: () => void\n}\n\nconst initialState: ChatState = {\n status: 'idle',\n role: null,\n visitorId: null,\n chatId: null,\n messages: [],\n error: null,\n visitorInfo: null,\n}\n\nexport const useChatStore = create<ChatState & ChatActions>((set) => ({\n ...initialState,\n\n setStatus: (status) => set({ status }),\n setRole: (role) => set({ role }),\n setVisitorId: (id) => set({ visitorId: id }),\n setChatId: (id) => set({ chatId: id }),\n addMessage: (message) =>\n set((state) => ({\n messages: [...state.messages, message],\n })),\n setError: (error) => set({ error }),\n setVisitorInfo: (info) => set({ visitorInfo: info }),\n reset: () => set(initialState),\n}))","import React, { useEffect, useState } from 'react'\nimport { css } from '@emotion/css'\n\nconst BUTTON_SIZE = 58\n\ninterface Props {\n isOpen: boolean\n onToggle: () => void\n}\n\nexport const FloatingButton: React.FC<Props> = ({ isOpen, onToggle }) => {\n const [isMobile, setIsMobile] = useState(false)\n\n useEffect(() => {\n const check = () => setIsMobile(window.innerWidth <= 480)\n check()\n window.addEventListener('resize', check)\n return () => window.removeEventListener('resize', check)\n }, [])\n\n if (isMobile && isOpen) {\n return (\n <button className={styles.mobileCloseBtn} onClick={onToggle} type=\"button\">\n <svg width=\"22\" height=\"22\" viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"#fff\" strokeWidth=\"2.5\" strokeLinecap=\"round\">\n <line x1=\"18\" y1=\"6\" x2=\"6\" y2=\"18\" />\n <line x1=\"6\" y1=\"6\" x2=\"18\" y2=\"18\" />\n </svg>\n </button>\n )\n }\n\n return (\n <button className={styles.btn} onClick={onToggle} type=\"button\">\n <span className={styles.icon(!isOpen)}>\n <svg width=\"24\" height=\"24\" viewBox=\"0 0 24 24\" fill=\"#fff\">\n <path d=\"M20 2H4a2 2 0 0 0-2 2v18l4-4h14a2 2 0 0 0 2-2V4a2 2 0 0 0-2-2z\" />\n </svg>\n </span>\n <span className={styles.icon(isOpen)}>\n <svg width=\"20\" height=\"20\" viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"#fff\" strokeWidth=\"2.5\" strokeLinecap=\"round\">\n <line x1=\"18\" y1=\"6\" x2=\"6\" y2=\"18\" />\n <line x1=\"6\" y1=\"6\" x2=\"18\" y2=\"18\" />\n </svg>\n </span>\n </button>\n )\n}\n\nconst styles = {\n btn: css`\n position: fixed;\n right: 30px;\n bottom: 20px;\n width: ${BUTTON_SIZE}px;\n height: ${BUTTON_SIZE}px;\n border-radius: 50%;\n background: var(--wds-primary, oklch(0.5811 0.2268 259.15));\n border: none;\n cursor: pointer;\n box-shadow: 0 4px 20px rgba(0, 0, 0, 0.18);\n z-index: 999999;\n display: flex;\n align-items: center;\n justify-content: center;\n user-select: none;\n -webkit-user-select: none;\n &:hover {\n opacity: 0.92;\n }\n `,\n mobileCloseBtn: css`\n position: fixed;\n top: 16px;\n right: 20px;\n width: ${BUTTON_SIZE}px;\n height: ${BUTTON_SIZE}px;\n border-radius: 50%;\n background: var(--wds-primary, oklch(0.5811 0.2268 259.15));\n border: none;\n cursor: pointer;\n box-shadow: 0 4px 20px rgba(0, 0, 0, 0.25);\n z-index: 999999;\n display: flex;\n align-items: center;\n justify-content: center;\n `,\n icon: (visible: boolean) => css`\n position: absolute;\n display: flex;\n align-items: center;\n justify-content: center;\n transition: opacity 0.15s, transform 0.15s;\n transition-delay: ${visible ? '0.1s' : '0s'};\n opacity: ${visible ? 1 : 0};\n transform: ${visible ? 'scale(1)' : 'scale(0.6) rotate(30deg)'};\n pointer-events: ${visible ? 'auto' : 'none'};\n `,\n}","import React from 'react'\nimport { css } from '@emotion/css'\n\ninterface Props {\n isOpen: boolean\n isExpanded: boolean\n children: React.ReactNode\n}\n\nexport const ChatPanel: React.FC<Props> = ({ isOpen, isExpanded, children }) => {\n return (\n <div data-wds-root className={styles.panel(isOpen, isExpanded)}>\n <div className={styles.inner}>{children}</div>\n </div>\n )\n}\n\nconst styles = {\n panel: (isOpen: boolean, isExpanded: boolean) => css`\n position: fixed;\n bottom: 86px;\n z-index: 999998;\n transition: opacity 0.2s, transform 0.25s cubic-bezier(0.34, 1.2, 0.64, 1);\n opacity: ${isOpen ? 1 : 0};\n pointer-events: ${isOpen ? 'auto' : 'none'};\n\n ${isExpanded\n ? `\n width: min(760px, calc(100vw - 32px));\n height: min(780px, calc(100vh - 120px));\n border-radius: 20px;\n box-shadow: 0 20px 60px rgba(0,0,0,0.2), 0 4px 16px rgba(0,0,0,0.1);\n left: 50%;\n right: auto;\n translate: -50% 0;\n transform: ${isOpen ? 'scale(1)' : 'scale(0.95)'};\n transform-origin: bottom center;\n `\n : `\n width: 400px;\n height: 620px;\n border-radius: 20px;\n box-shadow: 0 12px 48px rgba(0,0,0,0.16), 0 2px 8px rgba(0,0,0,0.08);\n right: 22px;\n transform: ${isOpen ? 'translateY(0) scale(1)' : 'translateY(16px) scale(0.97)'};\n `}\n\n overflow: hidden;\n\n @media (max-width: 480px) {\n top: 0 !important;\n left: 0 !important;\n right: 0 !important;\n bottom: 0 !important;\n width: 100% !important;\n height: 100% !important;\n border-radius: 0 !important;\n translate: none !important;\n }\n `,\n inner: css`\n width: 100%;\n height: 100%;\n overflow: hidden;\n border-radius: inherit;\n `,\n}","import React from 'react'\nimport { css } from '@emotion/css'\n\ninterface Props {\n onStartChat: () => void\n onContinueChat: () => void\n hasHistory: boolean\n onExpand: () => void\n isExpanded: boolean\n}\n\nexport const HomeScreen: React.FC<Props> = ({\n onStartChat,\n onContinueChat,\n hasHistory,\n onExpand,\n isExpanded,\n}) => {\n return (\n <div className={styles.wrapper}>\n <div className={styles.topBar}>\n <div className={styles.logoMark}>\n <img\n src=\"https://cdn.waysdrop.com/bulk/horizon_20260411202129966_d25edae2.png\"\n alt=\"Waysdrop\"\n style={{ width: '100%', height: '100%', objectFit: 'contain' }}\n />\n </div>\n <button className={styles.expandBtn} onClick={onExpand}>\n {isExpanded ? (\n <svg width=\"15\" height=\"15\" viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" strokeWidth=\"2\" strokeLinecap=\"round\" strokeLinejoin=\"round\">\n <polyline points=\"4 14 10 14 10 20\"/><polyline points=\"20 10 14 10 14 4\"/>\n <line x1=\"10\" y1=\"14\" x2=\"3\" y2=\"21\"/><line x1=\"21\" y1=\"3\" x2=\"14\" y2=\"10\"/>\n </svg>\n ) : (\n <svg width=\"15\" height=\"15\" viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" strokeWidth=\"2\" strokeLinecap=\"round\" strokeLinejoin=\"round\">\n <polyline points=\"15 3 21 3 21 9\"/><polyline points=\"9 21 3 21 3 15\"/>\n <line x1=\"21\" y1=\"3\" x2=\"14\" y2=\"10\"/><line x1=\"3\" y1=\"21\" x2=\"10\" y2=\"14\"/>\n </svg>\n )}\n </button>\n </div>\n\n <div className={styles.hero}>\n <h2 className={styles.heroTitle}>Hi there! ๐Ÿ‘‹</h2>\n <p className={styles.heroSub}>We're here to help. Ask us anything or share your feedback.</p>\n </div>\n\n <div className={styles.section}>\n <p className={styles.sectionLabel}>Conversations</p>\n {hasHistory ? (\n <button className={styles.conversationCard} onClick={onContinueChat}>\n <div className={styles.cardIcon}>\n <svg width=\"16\" height=\"16\" viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" 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 </div>\n <div className={styles.cardBody}>\n <span className={styles.cardTitle}>Continue conversation</span>\n <span className={styles.cardSub}>Tap to resume your last chat</span>\n </div>\n <svg width=\"14\" height=\"14\" viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" strokeWidth=\"2\" strokeLinecap=\"round\" strokeLinejoin=\"round\">\n <polyline points=\"9 18 15 12 9 6\"/>\n </svg>\n </button>\n ) : (\n <div className={styles.emptyHistory}>\n <svg width=\"32\" height=\"32\" viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" strokeWidth=\"1.5\" strokeLinecap=\"round\" strokeLinejoin=\"round\" style={{ opacity: 0.25 }}>\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 <p>No previous conversations</p>\n </div>\n )}\n </div>\n\n <div className={styles.footer}>\n <button className={styles.startBtn} onClick={onStartChat}>\n New conversation\n <svg width=\"15\" height=\"15\" viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" strokeWidth=\"2.5\" strokeLinecap=\"round\" strokeLinejoin=\"round\">\n <polyline points=\"9 18 15 12 9 6\"/>\n </svg>\n </button>\n <p className={styles.poweredBy}>Powered by Waysdrop</p>\n </div>\n </div>\n )\n}\n\nconst styles = {\n wrapper: css`\n display: flex;\n flex-direction: column;\n height: 100%;\n background: var(--wds-bg);\n text-align: left;\n `,\n topBar: css`\n display: flex;\n align-items: center;\n justify-content: space-between;\n padding: 18px 18px 0;\n flex-shrink: 0;\n `,\n logoMark: css`\n width: 48px;\n height: 48px;\n flex-shrink: 0;\n `,\n expandBtn: css`\n background: none;\n border: none;\n cursor: pointer;\n color: var(--wds-muted);\n padding: 8px;\n border-radius: 8px;\n display: flex;\n align-items: center;\n justify-content: center;\n transition: color 0.15s, background 0.15s;\n &:hover {\n color: var(--wds-fg);\n background: var(--wds-muted-bg);\n }\n @media (max-width: 480px) {\n display: none;\n }\n `,\n hero: css`\n padding: 20px 20px 16px;\n display: flex;\n flex-direction: column;\n align-items: flex-start;\n gap: 10px;\n flex-shrink: 0;\n `,\n heroTitle: css`\n font-size: 1.375rem;\n font-weight: 700;\n color: var(--wds-fg);\n margin: 0;\n line-height: 1.2;\n text-align: left;\n `,\n heroSub: css`\n font-size: 0.9375rem;\n color: var(--wds-muted);\n margin: 0;\n line-height: 1.6;\n text-align: left;\n `,\n section: css`\n flex: 1;\n padding: 4px 18px 0;\n overflow-y: auto;\n `,\n sectionLabel: css`\n font-size: 11px;\n font-weight: 600;\n letter-spacing: 0.07em;\n text-transform: uppercase;\n color: var(--wds-muted);\n margin: 0 0 12px 2px;\n text-align: left;\n `,\n conversationCard: css`\n display: flex;\n align-items: center;\n gap: 14px;\n width: 100%;\n padding: 14px 16px;\n background: var(--wds-muted-bg);\n border: 1px solid var(--wds-border);\n border-radius: 14px;\n cursor: pointer;\n text-align: left;\n transition: border-color 0.15s, background 0.15s;\n color: var(--wds-fg);\n &:hover {\n border-color: var(--wds-primary);\n background: var(--wds-primary-soft);\n }\n `,\n cardIcon: css`\n width: 38px;\n height: 38px;\n border-radius: 10px;\n background: var(--wds-primary-soft);\n color: var(--wds-primary);\n display: flex;\n align-items: center;\n justify-content: center;\n flex-shrink: 0;\n `,\n cardBody: css`\n flex: 1;\n display: flex;\n flex-direction: column;\n gap: 3px;\n `,\n cardTitle: css`\n font-size: 0.875rem;\n font-weight: 600;\n color: var(--wds-fg);\n text-align: left;\n `,\n cardSub: css`\n font-size: 12px;\n color: var(--wds-muted);\n text-align: left;\n `,\n emptyHistory: css`\n display: flex;\n flex-direction: column;\n align-items: center;\n gap: 10px;\n padding: 40px 0;\n color: var(--wds-muted);\n font-size: 12px;\n `,\n footer: css`\n padding: 18px 18px 16px;\n display: flex;\n flex-direction: column;\n gap: 12px;\n align-items: center;\n flex-shrink: 0;\n border-top: 1px solid var(--wds-border);\n `,\n startBtn: css`\n display: flex;\n align-items: center;\n justify-content: center;\n gap: 6px;\n width: 100%;\n padding: 13px 16px;\n background: var(--wds-primary);\n color: #fff;\n border: none;\n border-radius: 14px;\n font-size: 0.9375rem;\n font-weight: 600;\n cursor: pointer;\n transition: opacity 0.15s;\n font-family: inherit;\n &:hover { opacity: 0.88; }\n `,\n poweredBy: css`\n font-size: 11px;\n color: var(--wds-muted);\n margin: 0;\n opacity: 0.7;\n `,\n}","import React, { useEffect, useRef, useState } from \"react\";\nimport { css, keyframes } from \"@emotion/css\";\nimport { ChatMessage } from \"../types\";\nimport { MessageBubble } from \"./MessageBubble\";\nimport { ChatInput } from \"./ChatInput\";\n\ninterface Props {\n messages: ChatMessage[];\n onSendText: (content: string) => void;\n onSendFile: (file: File, content?: string) => Promise<void>;\n onBack: () => void;\n onExpand: () => void;\n isExpanded: boolean;\n status: string;\n error: { code: number; message: string } | null;\n}\n\nexport const ChatScreen: React.FC<Props> = ({\n messages,\n onSendText,\n onSendFile,\n onBack,\n onExpand,\n isExpanded,\n status,\n error,\n}) => {\n const bottomRef = useRef<HTMLDivElement>(null);\n const scrollRef = useRef<HTMLDivElement>(null);\n const connected = status === \"connected\";\n const [showScrollBtn, setShowScrollBtn] = useState(false);\n\n const lastMsg = messages[messages.length - 1];\n const isThinking = connected && lastMsg?.direction === \"OUTBOUND\";\n\n useEffect(() => {\n bottomRef.current?.scrollIntoView({ behavior: \"smooth\" });\n }, [messages]);\n\n const handleScroll = () => {\n const el = scrollRef.current;\n if (!el) return;\n setShowScrollBtn(el.scrollHeight - el.scrollTop - el.clientHeight > 80);\n };\n\n return (\n <div className={styles.wrapper}>\n <div className={styles.header}>\n <button className={styles.iconBtn} onClick={onBack}>\n <svg\n width=\"18\"\n height=\"18\"\n viewBox=\"0 0 24 24\"\n fill=\"none\"\n stroke=\"currentColor\"\n strokeWidth=\"2\"\n strokeLinecap=\"round\"\n strokeLinejoin=\"round\"\n >\n <polyline points=\"15 18 9 12 15 6\" />\n </svg>\n </button>\n\n <div className={styles.headerCenter}>\n <span className={styles.headerTitle}>Support</span>\n <span className={styles.statusDot(connected)} />\n <span className={styles.statusLabel}>\n {connected ? \"Online\" : \"Connecting...\"}\n </span>\n </div>\n\n <button className={styles.expandBtn} onClick={onExpand}>\n {isExpanded ? (\n <svg\n width=\"16\"\n height=\"16\"\n viewBox=\"0 0 24 24\"\n fill=\"none\"\n stroke=\"currentColor\"\n strokeWidth=\"2\"\n strokeLinecap=\"round\"\n strokeLinejoin=\"round\"\n >\n <polyline points=\"4 14 10 14 10 20\" />\n <polyline points=\"20 10 14 10 14 4\" />\n <line x1=\"10\" y1=\"14\" x2=\"3\" y2=\"21\" />\n <line x1=\"21\" y1=\"3\" x2=\"14\" y2=\"10\" />\n </svg>\n ) : (\n <svg\n width=\"16\"\n height=\"16\"\n viewBox=\"0 0 24 24\"\n fill=\"none\"\n stroke=\"currentColor\"\n strokeWidth=\"2\"\n strokeLinecap=\"round\"\n strokeLinejoin=\"round\"\n >\n <polyline points=\"15 3 21 3 21 9\" />\n <polyline points=\"9 21 3 21 3 15\" />\n <line x1=\"21\" y1=\"3\" x2=\"14\" y2=\"10\" />\n <line x1=\"3\" y1=\"21\" x2=\"10\" y2=\"14\" />\n </svg>\n )}\n </button>\n </div>\n\n <div className={styles.messagesWrap}>\n <div\n className={styles.messages}\n ref={scrollRef}\n onScroll={handleScroll}\n >\n {error && <div className={styles.errorBanner}>{error.message}</div>}\n {messages.length === 0 && connected && (\n <div className={styles.emptyState}>\n <p>Send a message to start the conversation.</p>\n </div>\n )}\n {messages.map((msg) => (\n <MessageBubble key={msg.id} message={msg} />\n ))}\n <div ref={bottomRef} />\n </div>\n\n {showScrollBtn && (\n <button\n className={styles.scrollBtn}\n onClick={() =>\n bottomRef.current?.scrollIntoView({ behavior: \"smooth\" })\n }\n >\n <svg\n width=\"14\"\n height=\"14\"\n viewBox=\"0 0 24 24\"\n fill=\"none\"\n stroke=\"currentColor\"\n strokeWidth=\"2.5\"\n strokeLinecap=\"round\"\n strokeLinejoin=\"round\"\n >\n <polyline points=\"6 9 12 15 18 9\" />\n </svg>\n </button>\n )}\n </div>\n\n <ChatInput\n onSendText={onSendText}\n onSendFile={onSendFile}\n disabled={!connected}\n isThinking={isThinking}\n />\n </div>\n );\n};\n\nconst pulse = keyframes`\n 0%, 100% { opacity: 1; }\n 50% { opacity: 0.4; }\n`;\n\nconst styles = {\n wrapper: css`\n display: flex;\n flex-direction: column;\n height: 100%;\n background: var(--wds-bg);\n `,\n header: css`\n display: flex;\n align-items: center;\n gap: 10px;\n padding: 12px 14px;\n border-bottom: 1px solid var(--wds-border);\n flex-shrink: 0;\n `,\n headerCenter: css`\n flex: 1;\n display: flex;\n align-items: center;\n gap: 6px;\n `,\n headerTitle: css`\n font-size: 0.875rem;\n font-weight: 600;\n color: var(--wds-fg);\n `,\n statusDot: (connected: boolean) => css`\n width: 7px;\n height: 7px;\n border-radius: 50%;\n flex-shrink: 0;\n background: ${connected ? \"#22c55e\" : \"#f59e0b\"};\n animation: ${connected ? \"none\" : `${pulse} 1.2s ease-in-out infinite`};\n `,\n statusLabel: css`\n font-size: 11px;\n color: var(--wds-muted);\n `,\n iconBtn: css`\n background: none;\n border: none;\n cursor: pointer;\n color: var(--wds-muted);\n padding: 6px;\n border-radius: 8px;\n display: flex;\n align-items: center;\n justify-content: center;\n flex-shrink: 0;\n transition:\n color 0.15s,\n background 0.15s;\n &:hover {\n color: var(--wds-fg);\n background: var(--wds-muted-bg);\n }\n `,\n expandBtn: css`\n background: none;\n border: none;\n cursor: pointer;\n color: var(--wds-muted);\n padding: 6px;\n border-radius: 8px;\n display: flex;\n align-items: center;\n justify-content: center;\n flex-shrink: 0;\n transition:\n color 0.15s,\n background 0.15s;\n &:hover {\n color: var(--wds-fg);\n background: var(--wds-muted-bg);\n }\n @media (max-width: 480px) {\n display: none;\n }\n `,\n messagesWrap: css`\n flex: 1;\n position: relative;\n overflow: hidden;\n `,\n messages: css`\n position: absolute;\n inset: 0;\n overflow-y: auto;\n padding: 16px 14px;\n display: flex;\n flex-direction: column;\n gap: 10px;\n `,\n errorBanner: css`\n background: oklch(0.9705 0.0129 17.04);\n color: oklch(0.5054 0.1905 27.51);\n border: 1px solid oklch(0.8845 0.0592 18.27);\n border-radius: 8px;\n padding: 8px 12px;\n font-size: 12px;\n text-align: center;\n `,\n emptyState: css`\n flex: 1;\n display: flex;\n align-items: center;\n justify-content: center;\n color: var(--wds-muted);\n font-size: 13px;\n text-align: center;\n padding: 40px 20px;\n `,\n scrollBtn: css`\n position: absolute;\n bottom: 12px;\n left: 50%;\n transform: translateX(-50%);\n width: 30px;\n height: 30px;\n border-radius: 50%;\n background: var(--wds-bg);\n border: 1px solid var(--wds-border);\n color: var(--wds-muted);\n display: flex;\n align-items: center;\n justify-content: center;\n cursor: pointer;\n box-shadow: 0 2px 8px rgba(0, 0, 0, 0.12);\n transition:\n color 0.15s,\n border-color 0.15s;\n &:hover {\n color: var(--wds-primary);\n border-color: var(--wds-primary);\n }\n `,\n};","import React from 'react'\nimport { css } from '@emotion/css'\nimport { ChatMessage } from '../types'\nimport { MarkdownRenderer } from './MarkdownRenderer'\n\nfunction formatTime(iso: string): string {\n return new Date(iso).toLocaleTimeString([], { hour: '2-digit', minute: '2-digit' })\n}\n\ninterface Props {\n message: ChatMessage\n}\n\nexport const MessageBubble: React.FC<Props> = ({ message }) => {\n const isCustomer = message.direction === 'OUTBOUND'\n const isBot = message.senderRole === 'BOT'\n\n return (\n <div className={styles.row(isCustomer)}>\n <div className={styles.group(isCustomer)}>\n {isBot && <span className={styles.botLabel}>Ways AI</span>}\n <div className={styles.bubble(isCustomer)}>\n {message.file && (\n <a href={message.file} target=\"_blank\" rel=\"noreferrer\" className={styles.fileLink(!!message.content)}>\n ๐Ÿ“Ž View attachment\n </a>\n )}\n {message.content && (\n isBot\n ? <MarkdownRenderer content={message.content} />\n : <p className={styles.text}>{message.content}</p>\n )}\n </div>\n <span className={styles.time}>{formatTime(message.createdAt)}</span>\n </div>\n </div>\n )\n}\n\nconst styles = {\n row: (isCustomer: boolean) => css`\n display: flex;\n width: 100%;\n justify-content: ${isCustomer ? 'flex-start' : 'flex-end'};\n `,\n group: (isCustomer: boolean) => css`\n display: flex;\n flex-direction: column;\n max-width: 78%;\n gap: 4px;\n align-items: ${isCustomer ? 'flex-start' : 'flex-end'};\n `,\n botLabel: css`\n font-size: 10px;\n color: var(--wds-muted);\n padding: 0 4px;\n font-weight: 500;\n letter-spacing: 0.03em;\n `,\n bubble: (isCustomer: boolean) => css`\n border-radius: 18px;\n padding: 10px 14px;\n word-break: break-word;\n text-align: left;\n border-top-left-radius: ${isCustomer ? '4px' : '18px'};\n border-top-right-radius: ${isCustomer ? '18px' : '4px'};\n background: ${isCustomer ? 'var(--wds-muted-bg)' : 'var(--wds-primary)'};\n color: ${isCustomer ? 'var(--wds-fg)' : '#fff'};\n `,\n text: css`\n font-size: 0.875rem;\n line-height: 1.5;\n margin: 0;\n white-space: pre-wrap;\n text-align: left;\n `,\n fileLink: (hasContent: boolean) => css`\n font-size: 0.875rem;\n color: inherit;\n text-decoration: underline;\n display: block;\n text-align: left;\n ${hasContent ? 'margin-bottom: 6px;' : ''}\n `,\n time: css`\n font-size: 10px;\n color: var(--wds-muted);\n padding: 0 4px;\n `,\n}","import React from 'react'\nimport ReactMarkdown from 'react-markdown'\nimport { css } from '@emotion/css'\n\nconst markdownStyle = css`\n font-size: 0.875rem;\n line-height: 1.6;\n color: inherit;\n text-align: left;\n\n p {\n margin: 0 0 0.6rem 0;\n text-align: left;\n }\n p:last-child {\n margin-bottom: 0;\n }\n strong { font-weight: 600; }\n em { font-style: italic; }\n\n ul, ol {\n margin: 0.4rem 0 0.6rem 0;\n padding-left: 1.4rem;\n text-align: left;\n }\n ul { list-style-type: disc; }\n ol { list-style-type: decimal; }\n li {\n margin-bottom: 0.3rem;\n }\n li > ul, li > ol {\n margin: 0.25rem 0 0.25rem 0;\n padding-left: 1.2rem;\n }\n li:last-child { margin-bottom: 0; }\n\n hr {\n border: none;\n border-top: 1px solid rgba(255, 255, 255, 0.25);\n margin: 0.75rem 0;\n }\n\n code {\n font-family: monospace;\n font-size: 0.8rem;\n background: rgba(255,255,255,0.15);\n border-radius: 4px;\n padding: 0.1rem 0.35rem;\n }\n pre {\n background: rgba(255,255,255,0.1);\n border-radius: 8px;\n padding: 0.75rem 1rem;\n overflow-x: auto;\n margin: 0.5rem 0;\n }\n pre code {\n background: none;\n padding: 0;\n font-size: 0.78rem;\n }\n blockquote {\n border-left: 3px solid rgba(255,255,255,0.25);\n margin: 0.5rem 0;\n padding-left: 0.75rem;\n opacity: 0.8;\n }\n a {\n color: rgba(255,255,255,0.85);\n text-decoration: underline;\n }\n h1, h2, h3 {\n font-weight: 600;\n margin: 0.6rem 0 0.3rem;\n line-height: 1.3;\n text-align: left;\n }\n h1 { font-size: 1rem; }\n h2 { font-size: 0.95rem; }\n h3 { font-size: 0.875rem; }\n`\n\ninterface Props {\n content: string\n}\n\nexport const MarkdownRenderer: React.FC<Props> = ({ content }) => {\n return (\n <div className={markdownStyle}>\n <ReactMarkdown>{content}</ReactMarkdown>\n </div>\n )\n}","import React, { useState, useRef, useCallback, KeyboardEvent } from 'react'\nimport { css, keyframes } from '@emotion/css'\n\nconst spin = keyframes`\n to { transform: rotate(360deg); }\n`\n\nconst pulse = keyframes`\n 0%, 100% { opacity: 0.4; transform: scaleY(0.6); }\n 50% { opacity: 1; transform: scaleY(1); }\n`\n\ninterface Props {\n onSendText: (content: string) => void\n onSendFile: (file: File, content?: string) => Promise<void>\n disabled?: boolean\n isThinking?: boolean\n}\n\nexport const ChatInput: React.FC<Props> = ({ onSendText, onSendFile, disabled, isThinking }) => {\n const [value, setValue] = useState('')\n const [uploading, setUploading] = useState(false)\n const [pendingFile, setPendingFile] = useState<File | null>(null)\n const [pendingPreview, setPendingPreview] = useState<string | null>(null)\n const textareaRef = useRef<HTMLTextAreaElement>(null)\n const fileInputRef = useRef<HTMLInputElement>(null)\n\n const handleSend = useCallback(() => {\n const trimmed = value.trim()\n if ((!trimmed && !pendingFile) || disabled || uploading) return\n\n if (pendingFile) {\n setUploading(true)\n onSendFile(pendingFile, trimmed || undefined).finally(() => {\n setUploading(false)\n setPendingFile(null)\n setPendingPreview(null)\n setValue('')\n })\n } else if (trimmed) {\n onSendText(trimmed)\n setValue('')\n }\n\n textareaRef.current?.focus()\n }, [value, pendingFile, disabled, uploading, onSendText, onSendFile])\n\n const handleKeyDown = (e: KeyboardEvent<HTMLTextAreaElement>) => {\n if (e.key === 'Enter' && !e.shiftKey) {\n e.preventDefault()\n handleSend()\n }\n }\n\n const handleFileChange = (e: React.ChangeEvent<HTMLInputElement>) => {\n const file = e.target.files?.[0]\n if (!file) return\n if (!file.type.startsWith('image/')) return\n setPendingFile(file)\n const reader = new FileReader()\n reader.onload = (ev) => setPendingPreview(ev.target?.result as string)\n reader.readAsDataURL(file)\n e.target.value = ''\n }\n\n const canSend = (value.trim() || pendingFile) && !disabled && !uploading\n\n return (\n <div className={styles.wrapper}>\n {isThinking && (\n <div className={styles.thinkingBar}>\n <div className={styles.thinkingDots}>\n <span className={styles.dot(0)} />\n <span className={styles.dot(1)} />\n <span className={styles.dot(2)} />\n </div>\n <span className={styles.thinkingLabel}>Ways AI is typing...</span>\n </div>\n )}\n\n {pendingPreview && (\n <div className={styles.imagePreview}>\n <img src={pendingPreview} alt=\"attachment\" className={styles.previewImg} />\n <button className={styles.removeFile} onClick={() => { setPendingFile(null); setPendingPreview(null) }}>\n <svg width=\"12\" height=\"12\" viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" strokeWidth=\"2.5\" strokeLinecap=\"round\">\n <line x1=\"18\" y1=\"6\" x2=\"6\" y2=\"18\"/><line x1=\"6\" y1=\"6\" x2=\"18\" y2=\"18\"/>\n </svg>\n </button>\n </div>\n )}\n\n <div className={styles.inputRow}>\n <button\n className={styles.attachBtn}\n onClick={() => fileInputRef.current?.click()}\n disabled={disabled || uploading}\n type=\"button\"\n >\n <svg width=\"18\" height=\"18\" viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" strokeWidth=\"2\" strokeLinecap=\"round\" strokeLinejoin=\"round\">\n <rect x=\"3\" y=\"3\" width=\"18\" height=\"18\" rx=\"3\"/><circle cx=\"8.5\" cy=\"8.5\" r=\"1.5\"/><polyline points=\"21 15 16 10 5 21\"/>\n </svg>\n </button>\n\n <input\n ref={fileInputRef}\n type=\"file\"\n accept=\"image/*\"\n className={styles.hiddenInput}\n onChange={handleFileChange}\n />\n\n <textarea\n ref={textareaRef}\n className={styles.textarea}\n value={value}\n onChange={(e) => setValue(e.target.value)}\n onKeyDown={handleKeyDown}\n placeholder=\"Type a message...\"\n disabled={disabled || uploading}\n rows={1}\n />\n\n <button className={styles.sendBtn} onClick={handleSend} disabled={!canSend} type=\"button\">\n {uploading ? (\n <span className={styles.spinner} />\n ) : (\n <svg width=\"16\" height=\"16\" viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" strokeWidth=\"2.5\" strokeLinecap=\"round\" strokeLinejoin=\"round\">\n <line x1=\"12\" y1=\"19\" x2=\"12\" y2=\"5\"/><polyline points=\"5 12 12 5 19 12\"/>\n </svg>\n )}\n </button>\n </div>\n\n <p className={styles.hint}>Enter to send ยท Shift+Enter for new line</p>\n </div>\n )\n}\n\nconst styles = {\n wrapper: css`\n padding: 8px 12px 10px;\n border-top: 1px solid var(--wds-border);\n display: flex;\n flex-direction: column;\n gap: 6px;\n background: var(--wds-bg);\n flex-shrink: 0;\n `,\n thinkingBar: css`\n display: flex;\n align-items: center;\n gap: 8px;\n padding: 6px 2px 2px;\n `,\n thinkingDots: css`\n display: flex;\n align-items: center;\n gap: 3px;\n `,\n dot: (i: number) => css`\n width: 5px;\n height: 5px;\n border-radius: 50%;\n background: var(--wds-primary);\n animation: ${pulse} 1.2s ease-in-out infinite;\n animation-delay: ${i * 0.18}s;\n display: inline-block;\n `,\n thinkingLabel: css`\n font-size: 11px;\n color: var(--wds-muted);\n `,\n imagePreview: css`\n position: relative;\n width: fit-content;\n margin: 0 2px;\n `,\n previewImg: css`\n width: 72px;\n height: 72px;\n object-fit: cover;\n border-radius: 10px;\n border: 1px solid var(--wds-border);\n display: block;\n `,\n removeFile: css`\n position: absolute;\n top: -6px;\n right: -6px;\n width: 18px;\n height: 18px;\n border-radius: 50%;\n background: var(--wds-fg);\n color: var(--wds-bg);\n border: none;\n cursor: pointer;\n display: flex;\n align-items: center;\n justify-content: center;\n padding: 0;\n `,\n inputRow: css`\n display: flex;\n align-items: center;\n gap: 6px;\n background: var(--wds-muted-bg);\n border: 1px solid var(--wds-border);\n border-radius: 14px;\n padding: 4px 4px 4px 8px;\n transition: border-color 0.15s;\n &:focus-within {\n border-color: var(--wds-primary);\n background: var(--wds-bg);\n }\n `,\n attachBtn: css`\n background: none;\n border: none;\n cursor: pointer;\n color: var(--wds-muted);\n padding: 5px;\n border-radius: 8px;\n display: flex;\n align-items: center;\n justify-content: center;\n flex-shrink: 0;\n transition: color 0.15s;\n &:hover:not(:disabled) {\n color: var(--wds-primary);\n }\n &:disabled {\n opacity: 0.35;\n cursor: not-allowed;\n }\n `,\n hiddenInput: css`\n display: none;\n `,\n textarea: css`\n flex: 1;\n resize: none;\n border: none;\n padding: 6px 0;\n font-size: 0.875rem;\n font-family: inherit;\n line-height: 1.5;\n background: transparent;\n color: var(--wds-fg);\n outline: none;\n max-height: 120px;\n overflow-y: auto;\n &::placeholder { color: var(--wds-muted); }\n &:disabled {\n opacity: 0.5;\n cursor: not-allowed;\n }\n `,\n sendBtn: css`\n background: var(--wds-primary);\n border: none;\n border-radius: 10px;\n width: 34px;\n height: 34px;\n display: flex;\n align-items: center;\n justify-content: center;\n cursor: pointer;\n color: #fff;\n flex-shrink: 0;\n transition: opacity 0.15s;\n &:disabled {\n opacity: 0.35;\n cursor: not-allowed;\n }\n &:hover:not(:disabled) { opacity: 0.85; }\n `,\n spinner: css`\n width: 14px;\n height: 14px;\n border: 2px solid rgba(255,255,255,0.3);\n border-top-color: #fff;\n border-radius: 50%;\n animation: ${spin} 0.7s linear infinite;\n display: block;\n `,\n hint: css`\n font-size: 10px;\n color: var(--wds-muted);\n margin: 0;\n text-align: center;\n opacity: 0.7;\n `,\n}"],"mappings":";;;;;;;;;;;;;;;;;;;;;AAAA,SAAgB,aAAAA,YAAW,YAAAC,iBAAgB;AAC3C,SAAS,oBAAoB;;;ACC7B,IAAM,iBAAiB;AAEhB,IAAM,gBAAgB,CAAC,OAAqB;AACjD,MAAI,OAAO,WAAW,YAAa;AACnC,eAAa,QAAQ,gBAAgB,EAAE;AACzC;AAEO,IAAM,gBAAgB,MAAqB;AAChD,MAAI,OAAO,WAAW,YAAa,QAAO;AAC1C,SAAO,aAAa,QAAQ,cAAc;AAC5C;AAEO,IAAM,iBAAiB,MAAY;AACxC,MAAI,OAAO,WAAW,YAAa;AACnC,eAAa,WAAW,cAAc;AACxC;AAEO,IAAM,aAAa,OACxB,MACA,WACoB;AAtBtB;AAuBE,QAAM,WAAW,IAAI,SAAS;AAC9B,WAAS,OAAO,SAAS,IAAI;AAE7B,QAAM,UAAuB,CAAC;AAC9B,MAAI,OAAO,MAAO,SAAQ,eAAe,IAAI,UAAU,OAAO,KAAK;AAEnE,QAAM,MAAM,MAAM,MAAM,GAAG,OAAO,MAAM,qBAAqB;AAAA,IAC3D,QAAQ;AAAA,IACR;AAAA,IACA,MAAM;AAAA,EACR,CAAC;AAED,MAAI,CAAC,IAAI,IAAI;AACX,UAAM,IAAI,MAAM,oBAAoB;AAAA,EACtC;AAEA,QAAM,OAAO,MAAM,IAAI,KAAK;AAE5B,MAAI,CAAC,KAAK,WAAW,GAAC,gBAAK,SAAL,mBAAW,SAAX,mBAAiB,SAAQ;AAC7C,UAAM,IAAI,MAAM,KAAK,WAAW,oBAAoB;AAAA,EACtD;AAEA,QAAM,QAAQ,KAAK,KAAK,KAAK,CAAC;AAC9B,MAAI,OAAO,UAAU,UAAU;AAC7B,UAAM,IAAI,OAAM,+BAAO,UAAS,oBAAoB;AAAA,EACtD;AAEA,SAAO;AACT;;;ACnDA,SAAS,WAAW,mBAAmB;;;ACAvC,SAAS,UAAkB;AAG3B,IAAI,SAAwB;AAErB,IAAM,eAAe,CAAC,WAA+B;AAC1D,MAAI,QAAQ;AACV,WAAO,WAAW;AAClB,aAAS;AAAA,EACX;AAEA,QAAM,EAAE,WAAW,OAAO,UAAU,IAAI;AAExC,WAAS,GAAG,WAAW;AAAA,IACrB,YAAY,CAAC,aAAa,SAAS;AAAA,IACnC,MAAM,kCACA,QAAQ,EAAE,MAAM,IAAI,CAAC,IACrB,YAAY,EAAE,UAAU,IAAI,CAAC;AAAA,IAEnC,aAAa;AAAA,EACf,CAAC;AAED,SAAO;AACT;AAEO,IAAM,YAAY,CAAC,WAA+B;AACvD,MAAI,OAAQ,QAAO;AACnB,SAAO,aAAa,MAAM;AAC5B;AAEO,IAAM,gBAAgB,MAAY;AACvC,MAAI,QAAQ;AACV,WAAO,WAAW;AAClB,aAAS;AAAA,EACX;AACF;;;ACnCA,SAAS,cAAc;AAqBvB,IAAM,eAA0B;AAAA,EAC9B,QAAQ;AAAA,EACR,MAAM;AAAA,EACN,WAAW;AAAA,EACX,QAAQ;AAAA,EACR,UAAU,CAAC;AAAA,EACX,OAAO;AAAA,EACP,aAAa;AACf;AAEO,IAAM,eAAe,OAAgC,CAAC,QAAS,iCACjE,eADiE;AAAA,EAGpE,WAAW,CAAC,WAAW,IAAI,EAAE,OAAO,CAAC;AAAA,EACrC,SAAS,CAAC,SAAS,IAAI,EAAE,KAAK,CAAC;AAAA,EAC/B,cAAc,CAAC,OAAO,IAAI,EAAE,WAAW,GAAG,CAAC;AAAA,EAC3C,WAAW,CAAC,OAAO,IAAI,EAAE,QAAQ,GAAG,CAAC;AAAA,EACrC,YAAY,CAAC,YACX,IAAI,CAAC,WAAW;AAAA,IACd,UAAU,CAAC,GAAG,MAAM,UAAU,OAAO;AAAA,EACvC,EAAE;AAAA,EACJ,UAAU,CAAC,UAAU,IAAI,EAAE,MAAM,CAAC;AAAA,EAClC,gBAAgB,CAAC,SAAS,IAAI,EAAE,aAAa,KAAK,CAAC;AAAA,EACnD,OAAO,MAAM,IAAI,YAAY;AAC/B,EAAE;;;AF/BK,IAAM,UAAU,CAAC,WAAuB;AAC7C,QAAM;AAAA,IACJ;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,EACF,IAAI,aAAa;AAEjB,YAAU,MAAM;AACd,UAAMC,UAAS,aAAa,MAAM;AAElC,cAAU,YAAY;AACtB,IAAAA,QAAO,QAAQ;AAEf,IAAAA,QAAO,GAAG,aAAa,CAAC,YAA8B;AACpD,gBAAU,WAAW;AACrB,cAAQ,QAAQ,IAAI;AAEpB,UAAI,QAAQ,SAAS,WAAW;AAC9B,sBAAc,QAAQ,SAAS;AAC/B,qBAAa,QAAQ,SAAS;AAAA,MAChC;AAAA,IACF,CAAC;AAED,IAAAA,QAAO,GAAG,wBAAwB,CAAC,YAAuC;AACxE,gBAAU,QAAQ,MAAM;AACxB,iBAAW,QAAQ,OAAO;AAAA,IAC5B,CAAC;AAED,IAAAA,QAAO,GAAG,uBAAuB,CAAC,YAAsC;AACtE,gBAAU,QAAQ,MAAM;AACxB,iBAAW,QAAQ,OAAO;AAAA,IAC5B,CAAC;AAED,IAAAA,QAAO,GAAG,SAAS,CAAC,QAAqB;AACvC,eAAS,GAAG;AACZ,gBAAU,OAAO;AAAA,IACnB,CAAC;AAED,WAAO,MAAM;AACX,oBAAc;AACd,YAAM;AAAA,IACR;AAAA,EACF,GAAG,CAAC,OAAO,KAAK,CAAC;AAEjB,QAAM,cAAc;AAAA,IAClB,CAAC,SAAiB,SAAuB;AAvE7C;AAwEM,YAAMA,UAAS,UAAU,MAAM;AAE/B,YAAM,MAA6B;AAAA,QACjC;AAAA,QACA,YAAY,OAAO,KAAK,IAAI,CAAC;AAAA,UACzB,sBAAQ,eACR;AAAA,QACE,QAAQ,sBAAQ,aAAc;AAAA,QAC9B,OAAO,2BAAQ,gBAAR,mBAAsB;AAAA,QAC7B,QAAQ,2BAAQ,gBAAR,mBAAsB;AAAA,MAChC,IACA,CAAC;AAGP,MAAAA,QAAO,KAAK,wBAAwB,GAAG;AAAA,IACzC;AAAA,IACA,CAAC,QAAQ,WAAW;AAAA,EACtB;AAEA,QAAM,WAAW;AAAA,IACf,OAAO,MAAY,SAAkB,SAAuB;AA5FhE;AA6FM,YAAM,MAAM,MAAM,WAAW,MAAM,MAAM;AAEzC,YAAMA,UAAS,UAAU,MAAM;AAE/B,YAAM,MAA6B;AAAA,QACjC,MAAM;AAAA,SACF,UAAU,EAAE,QAAQ,IAAI,CAAC,IAFI;AAAA,QAGjC,YAAY,QAAQ,KAAK,IAAI,CAAC;AAAA,WAC1B,sBAAQ,eACR;AAAA,QACE,QAAQ,sBAAQ,aAAc;AAAA,QAC9B,OAAO,2BAAQ,gBAAR,mBAAsB;AAAA,QAC7B,QAAQ,2BAAQ,gBAAR,mBAAsB;AAAA,MAChC,IACA,CAAC;AAGP,MAAAA,QAAO,KAAK,wBAAwB,GAAG;AAAA,IACzC;AAAA,IACA,CAAC,QAAQ,WAAW;AAAA,EACtB;AAEA,SAAO;AAAA,IACL;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,EACF;AACF;;;AG/HA,SAAgB,aAAAC,YAAW,gBAAgB;AAC3C,SAAS,WAAW;AAsBZ,SACE,KADF;AApBR,IAAM,cAAc;AAOb,IAAM,iBAAkC,CAAC,EAAE,QAAQ,SAAS,MAAM;AACvE,QAAM,CAAC,UAAU,WAAW,IAAI,SAAS,KAAK;AAE9C,EAAAA,WAAU,MAAM;AACd,UAAM,QAAQ,MAAM,YAAY,OAAO,cAAc,GAAG;AACxD,UAAM;AACN,WAAO,iBAAiB,UAAU,KAAK;AACvC,WAAO,MAAM,OAAO,oBAAoB,UAAU,KAAK;AAAA,EACzD,GAAG,CAAC,CAAC;AAEL,MAAI,YAAY,QAAQ;AACtB,WACE,oBAAC,YAAO,WAAW,OAAO,gBAAgB,SAAS,UAAU,MAAK,UAChE,+BAAC,SAAI,OAAM,MAAK,QAAO,MAAK,SAAQ,aAAY,MAAK,QAAO,QAAO,QAAO,aAAY,OAAM,eAAc,SACxG;AAAA,0BAAC,UAAK,IAAG,MAAK,IAAG,KAAI,IAAG,KAAI,IAAG,MAAK;AAAA,MACpC,oBAAC,UAAK,IAAG,KAAI,IAAG,KAAI,IAAG,MAAK,IAAG,MAAK;AAAA,OACtC,GACF;AAAA,EAEJ;AAEA,SACE,qBAAC,YAAO,WAAW,OAAO,KAAK,SAAS,UAAU,MAAK,UACrD;AAAA,wBAAC,UAAK,WAAW,OAAO,KAAK,CAAC,MAAM,GAClC,8BAAC,SAAI,OAAM,MAAK,QAAO,MAAK,SAAQ,aAAY,MAAK,QACnD,8BAAC,UAAK,GAAE,kEAAiE,GAC3E,GACF;AAAA,IACA,oBAAC,UAAK,WAAW,OAAO,KAAK,MAAM,GACjC,+BAAC,SAAI,OAAM,MAAK,QAAO,MAAK,SAAQ,aAAY,MAAK,QAAO,QAAO,QAAO,aAAY,OAAM,eAAc,SACxG;AAAA,0BAAC,UAAK,IAAG,MAAK,IAAG,KAAI,IAAG,KAAI,IAAG,MAAK;AAAA,MACpC,oBAAC,UAAK,IAAG,KAAI,IAAG,KAAI,IAAG,MAAK,IAAG,MAAK;AAAA,OACtC,GACF;AAAA,KACF;AAEJ;AAEA,IAAM,SAAS;AAAA,EACb,KAAK;AAAA;AAAA;AAAA;AAAA,aAIM,WAAW;AAAA,cACV,WAAW;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAgBvB,gBAAgB;AAAA;AAAA;AAAA;AAAA,aAIL,WAAW;AAAA,cACV,WAAW;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAWvB,MAAM,CAAC,YAAqB;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,wBAMN,UAAU,SAAS,IAAI;AAAA,eAChC,UAAU,IAAI,CAAC;AAAA,iBACb,UAAU,aAAa,0BAA0B;AAAA,sBAC5C,UAAU,SAAS,MAAM;AAAA;AAE/C;;;AChGA,SAAS,OAAAC,YAAW;AAWd,gBAAAC,YAAA;AAHC,IAAM,YAA6B,CAAC,EAAE,QAAQ,YAAY,SAAS,MAAM;AAC9E,SACE,gBAAAA,KAAC,SAAI,iBAAa,MAAC,WAAWC,QAAO,MAAM,QAAQ,UAAU,GAC3D,0BAAAD,KAAC,SAAI,WAAWC,QAAO,OAAQ,UAAS,GAC1C;AAEJ;AAEA,IAAMA,UAAS;AAAA,EACb,OAAO,CAAC,QAAiB,eAAwBF;AAAA;AAAA;AAAA;AAAA;AAAA,eAKpC,SAAS,IAAI,CAAC;AAAA,sBACP,SAAS,SAAS,MAAM;AAAA;AAAA,MAExC,aACE;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,mBAQW,SAAS,aAAa,aAAa;AAAA;AAAA,QAG9C;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,mBAMW,SAAS,2BAA2B,8BAA8B;AAAA,KAChF;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAeH,OAAOA;AAAA;AAAA;AAAA;AAAA;AAAA;AAMT;;;ACjEA,SAAS,OAAAG,YAAW;AAqBV,gBAAAC,MAQE,QAAAC,aARF;AAXH,IAAM,aAA8B,CAAC;AAAA,EAC1C;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AACF,MAAM;AACJ,SACE,gBAAAA,MAAC,SAAI,WAAWC,QAAO,SACrB;AAAA,oBAAAD,MAAC,SAAI,WAAWC,QAAO,QACrB;AAAA,sBAAAF,KAAC,SAAI,WAAWE,QAAO,UACrB,0BAAAF;AAAA,QAAC;AAAA;AAAA,UACC,KAAI;AAAA,UACJ,KAAI;AAAA,UACJ,OAAO,EAAE,OAAO,QAAQ,QAAQ,QAAQ,WAAW,UAAU;AAAA;AAAA,MAC/D,GACF;AAAA,MACA,gBAAAA,KAAC,YAAO,WAAWE,QAAO,WAAW,SAAS,UAC3C,uBACC,gBAAAD,MAAC,SAAI,OAAM,MAAK,QAAO,MAAK,SAAQ,aAAY,MAAK,QAAO,QAAO,gBAAe,aAAY,KAAI,eAAc,SAAQ,gBAAe,SACrI;AAAA,wBAAAD,KAAC,cAAS,QAAO,oBAAkB;AAAA,QAAE,gBAAAA,KAAC,cAAS,QAAO,oBAAkB;AAAA,QACxE,gBAAAA,KAAC,UAAK,IAAG,MAAK,IAAG,MAAK,IAAG,KAAI,IAAG,MAAI;AAAA,QAAE,gBAAAA,KAAC,UAAK,IAAG,MAAK,IAAG,KAAI,IAAG,MAAK,IAAG,MAAI;AAAA,SAC5E,IAEA,gBAAAC,MAAC,SAAI,OAAM,MAAK,QAAO,MAAK,SAAQ,aAAY,MAAK,QAAO,QAAO,gBAAe,aAAY,KAAI,eAAc,SAAQ,gBAAe,SACrI;AAAA,wBAAAD,KAAC,cAAS,QAAO,kBAAgB;AAAA,QAAE,gBAAAA,KAAC,cAAS,QAAO,kBAAgB;AAAA,QACpE,gBAAAA,KAAC,UAAK,IAAG,MAAK,IAAG,KAAI,IAAG,MAAK,IAAG,MAAI;AAAA,QAAE,gBAAAA,KAAC,UAAK,IAAG,KAAI,IAAG,MAAK,IAAG,MAAK,IAAG,MAAI;AAAA,SAC5E,GAEJ;AAAA,OACF;AAAA,IAEA,gBAAAC,MAAC,SAAI,WAAWC,QAAO,MACrB;AAAA,sBAAAF,KAAC,QAAG,WAAWE,QAAO,WAAW,iCAAY;AAAA,MAC7C,gBAAAF,KAAC,OAAE,WAAWE,QAAO,SAAS,yEAA2D;AAAA,OAC3F;AAAA,IAEA,gBAAAD,MAAC,SAAI,WAAWC,QAAO,SACrB;AAAA,sBAAAF,KAAC,OAAE,WAAWE,QAAO,cAAc,2BAAa;AAAA,MAC/C,aACC,gBAAAD,MAAC,YAAO,WAAWC,QAAO,kBAAkB,SAAS,gBACnD;AAAA,wBAAAF,KAAC,SAAI,WAAWE,QAAO,UACrB,0BAAAF,KAAC,SAAI,OAAM,MAAK,QAAO,MAAK,SAAQ,aAAY,MAAK,QAAO,QAAO,gBAAe,aAAY,KAAI,eAAc,SAAQ,gBAAe,SACrI,0BAAAA,KAAC,UAAK,GAAE,iEAA+D,GACzE,GACF;AAAA,QACA,gBAAAC,MAAC,SAAI,WAAWC,QAAO,UACrB;AAAA,0BAAAF,KAAC,UAAK,WAAWE,QAAO,WAAW,mCAAqB;AAAA,UACxD,gBAAAF,KAAC,UAAK,WAAWE,QAAO,SAAS,0CAA4B;AAAA,WAC/D;AAAA,QACA,gBAAAF,KAAC,SAAI,OAAM,MAAK,QAAO,MAAK,SAAQ,aAAY,MAAK,QAAO,QAAO,gBAAe,aAAY,KAAI,eAAc,SAAQ,gBAAe,SACrI,0BAAAA,KAAC,cAAS,QAAO,kBAAgB,GACnC;AAAA,SACF,IAEA,gBAAAC,MAAC,SAAI,WAAWC,QAAO,cACrB;AAAA,wBAAAF,KAAC,SAAI,OAAM,MAAK,QAAO,MAAK,SAAQ,aAAY,MAAK,QAAO,QAAO,gBAAe,aAAY,OAAM,eAAc,SAAQ,gBAAe,SAAQ,OAAO,EAAE,SAAS,KAAK,GACtK,0BAAAA,KAAC,UAAK,GAAE,iEAA+D,GACzE;AAAA,QACA,gBAAAA,KAAC,OAAE,uCAAyB;AAAA,SAC9B;AAAA,OAEJ;AAAA,IAEA,gBAAAC,MAAC,SAAI,WAAWC,QAAO,QACrB;AAAA,sBAAAD,MAAC,YAAO,WAAWC,QAAO,UAAU,SAAS,aAAa;AAAA;AAAA,QAExD,gBAAAF,KAAC,SAAI,OAAM,MAAK,QAAO,MAAK,SAAQ,aAAY,MAAK,QAAO,QAAO,gBAAe,aAAY,OAAM,eAAc,SAAQ,gBAAe,SACvI,0BAAAA,KAAC,cAAS,QAAO,kBAAgB,GACnC;AAAA,SACF;AAAA,MACA,gBAAAA,KAAC,OAAE,WAAWE,QAAO,WAAW,iCAAmB;AAAA,OACrD;AAAA,KACF;AAEJ;AAEA,IAAMA,UAAS;AAAA,EACb,SAASH;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAOT,QAAQA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAOR,UAAUA;AAAA;AAAA;AAAA;AAAA;AAAA,EAKV,WAAWA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAmBX,MAAMA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAQN,WAAWA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAQX,SAASA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAOT,SAASA;AAAA;AAAA;AAAA;AAAA;AAAA,EAKT,cAAcA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EASd,kBAAkBA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAkBlB,UAAUA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAWV,UAAUA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAMV,WAAWA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAMX,SAASA;AAAA;AAAA;AAAA;AAAA;AAAA,EAKT,cAAcA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EASd,QAAQA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EASR,UAAUA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAkBV,WAAWA;AAAA;AAAA;AAAA;AAAA;AAAA;AAMb;;;AC5PA,SAAgB,aAAAI,YAAW,UAAAC,SAAQ,YAAAC,iBAAgB;AACnD,SAAS,OAAAC,MAAK,aAAAC,kBAAiB;;;ACA/B,SAAS,OAAAC,YAAW;;;ACApB,OAAO,mBAAmB;AAC1B,SAAS,OAAAC,YAAW;AAuFd,gBAAAC,YAAA;AArFN,IAAM,gBAAgBD;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAkFf,IAAM,mBAAoC,CAAC,EAAE,QAAQ,MAAM;AAChE,SACE,gBAAAC,KAAC,SAAI,WAAW,eACd,0BAAAA,KAAC,iBAAe,mBAAQ,GAC1B;AAEJ;;;ADxEkB,gBAAAC,MACV,QAAAC,aADU;AAflB,SAAS,WAAW,KAAqB;AACvC,SAAO,IAAI,KAAK,GAAG,EAAE,mBAAmB,CAAC,GAAG,EAAE,MAAM,WAAW,QAAQ,UAAU,CAAC;AACpF;AAMO,IAAM,gBAAiC,CAAC,EAAE,QAAQ,MAAM;AAC7D,QAAM,aAAa,QAAQ,cAAc;AACzC,QAAM,QAAQ,QAAQ,eAAe;AAErC,SACE,gBAAAD,KAAC,SAAI,WAAWE,QAAO,IAAI,UAAU,GACnC,0BAAAD,MAAC,SAAI,WAAWC,QAAO,MAAM,UAAU,GACpC;AAAA,aAAS,gBAAAF,KAAC,UAAK,WAAWE,QAAO,UAAU,qBAAO;AAAA,IACnD,gBAAAD,MAAC,SAAI,WAAWC,QAAO,OAAO,UAAU,GACrC;AAAA,cAAQ,QACP,gBAAAF,KAAC,OAAE,MAAM,QAAQ,MAAM,QAAO,UAAS,KAAI,cAAa,WAAWE,QAAO,SAAS,CAAC,CAAC,QAAQ,OAAO,GAAG,uCAEvG;AAAA,MAED,QAAQ,YACP,QACI,gBAAAF,KAAC,oBAAiB,SAAS,QAAQ,SAAS,IAC5C,gBAAAA,KAAC,OAAE,WAAWE,QAAO,MAAO,kBAAQ,SAAQ;AAAA,OAEpD;AAAA,IACA,gBAAAF,KAAC,UAAK,WAAWE,QAAO,MAAO,qBAAW,QAAQ,SAAS,GAAE;AAAA,KAC/D,GACF;AAEJ;AAEA,IAAMA,UAAS;AAAA,EACb,KAAK,CAAC,eAAwBC;AAAA;AAAA;AAAA,uBAGT,aAAa,eAAe,UAAU;AAAA;AAAA,EAE3D,OAAO,CAAC,eAAwBA;AAAA;AAAA;AAAA;AAAA;AAAA,mBAKf,aAAa,eAAe,UAAU;AAAA;AAAA,EAEvD,UAAUA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAOV,QAAQ,CAAC,eAAwBA;AAAA;AAAA;AAAA;AAAA;AAAA,8BAKL,aAAa,QAAQ,MAAM;AAAA,+BAC1B,aAAa,SAAS,KAAK;AAAA,kBACxC,aAAa,wBAAwB,oBAAoB;AAAA,aAC9D,aAAa,kBAAkB,MAAM;AAAA;AAAA,EAEhD,MAAMA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAON,UAAU,CAAC,eAAwBA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,MAM/B,aAAa,wBAAwB,EAAE;AAAA;AAAA,EAE3C,MAAMA;AAAA;AAAA;AAAA;AAAA;AAKR;;;AEzFA,SAAgB,YAAAC,WAAU,QAAQ,eAAAC,oBAAkC;AACpE,SAAS,OAAAC,MAAK,iBAAiB;AAsErB,SACE,OAAAC,MADF,QAAAC,aAAA;AApEV,IAAM,OAAO;AAAA;AAAA;AAIb,IAAM,QAAQ;AAAA;AAAA;AAAA;AAYP,IAAM,YAA6B,CAAC,EAAE,YAAY,YAAY,UAAU,WAAW,MAAM;AAC9F,QAAM,CAAC,OAAO,QAAQ,IAAIJ,UAAS,EAAE;AACrC,QAAM,CAAC,WAAW,YAAY,IAAIA,UAAS,KAAK;AAChD,QAAM,CAAC,aAAa,cAAc,IAAIA,UAAsB,IAAI;AAChE,QAAM,CAAC,gBAAgB,iBAAiB,IAAIA,UAAwB,IAAI;AACxE,QAAM,cAAc,OAA4B,IAAI;AACpD,QAAM,eAAe,OAAyB,IAAI;AAElD,QAAM,aAAaC,aAAY,MAAM;AA3BvC;AA4BI,UAAM,UAAU,MAAM,KAAK;AAC3B,QAAK,CAAC,WAAW,CAAC,eAAgB,YAAY,UAAW;AAEzD,QAAI,aAAa;AACf,mBAAa,IAAI;AACjB,iBAAW,aAAa,WAAW,MAAS,EAAE,QAAQ,MAAM;AAC1D,qBAAa,KAAK;AAClB,uBAAe,IAAI;AACnB,0BAAkB,IAAI;AACtB,iBAAS,EAAE;AAAA,MACb,CAAC;AAAA,IACH,WAAW,SAAS;AAClB,iBAAW,OAAO;AAClB,eAAS,EAAE;AAAA,IACb;AAEA,sBAAY,YAAZ,mBAAqB;AAAA,EACvB,GAAG,CAAC,OAAO,aAAa,UAAU,WAAW,YAAY,UAAU,CAAC;AAEpE,QAAM,gBAAgB,CAAC,MAA0C;AAC/D,QAAI,EAAE,QAAQ,WAAW,CAAC,EAAE,UAAU;AACpC,QAAE,eAAe;AACjB,iBAAW;AAAA,IACb;AAAA,EACF;AAEA,QAAM,mBAAmB,CAAC,MAA2C;AAtDvE;AAuDI,UAAM,QAAO,OAAE,OAAO,UAAT,mBAAiB;AAC9B,QAAI,CAAC,KAAM;AACX,QAAI,CAAC,KAAK,KAAK,WAAW,QAAQ,EAAG;AACrC,mBAAe,IAAI;AACnB,UAAM,SAAS,IAAI,WAAW;AAC9B,WAAO,SAAS,CAAC,OAAI;AA5DzB,UAAAI;AA4D4B,gCAAkBA,MAAA,GAAG,WAAH,gBAAAA,IAAW,MAAgB;AAAA;AACrE,WAAO,cAAc,IAAI;AACzB,MAAE,OAAO,QAAQ;AAAA,EACnB;AAEA,QAAM,WAAW,MAAM,KAAK,KAAK,gBAAgB,CAAC,YAAY,CAAC;AAE/D,SACE,gBAAAD,MAAC,SAAI,WAAWE,QAAO,SACpB;AAAA,kBACC,gBAAAF,MAAC,SAAI,WAAWE,QAAO,aACrB;AAAA,sBAAAF,MAAC,SAAI,WAAWE,QAAO,cACrB;AAAA,wBAAAH,KAAC,UAAK,WAAWG,QAAO,IAAI,CAAC,GAAG;AAAA,QAChC,gBAAAH,KAAC,UAAK,WAAWG,QAAO,IAAI,CAAC,GAAG;AAAA,QAChC,gBAAAH,KAAC,UAAK,WAAWG,QAAO,IAAI,CAAC,GAAG;AAAA,SAClC;AAAA,MACA,gBAAAH,KAAC,UAAK,WAAWG,QAAO,eAAe,kCAAoB;AAAA,OAC7D;AAAA,IAGD,kBACC,gBAAAF,MAAC,SAAI,WAAWE,QAAO,cACrB;AAAA,sBAAAH,KAAC,SAAI,KAAK,gBAAgB,KAAI,cAAa,WAAWG,QAAO,YAAY;AAAA,MACzE,gBAAAH,KAAC,YAAO,WAAWG,QAAO,YAAY,SAAS,MAAM;AAAE,uBAAe,IAAI;AAAG,0BAAkB,IAAI;AAAA,MAAE,GACnG,0BAAAF,MAAC,SAAI,OAAM,MAAK,QAAO,MAAK,SAAQ,aAAY,MAAK,QAAO,QAAO,gBAAe,aAAY,OAAM,eAAc,SAChH;AAAA,wBAAAD,KAAC,UAAK,IAAG,MAAK,IAAG,KAAI,IAAG,KAAI,IAAG,MAAI;AAAA,QAAE,gBAAAA,KAAC,UAAK,IAAG,KAAI,IAAG,KAAI,IAAG,MAAK,IAAG,MAAI;AAAA,SAC1E,GACF;AAAA,OACF;AAAA,IAGF,gBAAAC,MAAC,SAAI,WAAWE,QAAO,UACrB;AAAA,sBAAAH;AAAA,QAAC;AAAA;AAAA,UACC,WAAWG,QAAO;AAAA,UAClB,SAAS,MAAG;AA9FtB;AA8FyB,sCAAa,YAAb,mBAAsB;AAAA;AAAA,UACrC,UAAU,YAAY;AAAA,UACtB,MAAK;AAAA,UAEL,0BAAAF,MAAC,SAAI,OAAM,MAAK,QAAO,MAAK,SAAQ,aAAY,MAAK,QAAO,QAAO,gBAAe,aAAY,KAAI,eAAc,SAAQ,gBAAe,SACrI;AAAA,4BAAAD,KAAC,UAAK,GAAE,KAAI,GAAE,KAAI,OAAM,MAAK,QAAO,MAAK,IAAG,KAAG;AAAA,YAAE,gBAAAA,KAAC,YAAO,IAAG,OAAM,IAAG,OAAM,GAAE,OAAK;AAAA,YAAE,gBAAAA,KAAC,cAAS,QAAO,oBAAkB;AAAA,aACzH;AAAA;AAAA,MACF;AAAA,MAEA,gBAAAA;AAAA,QAAC;AAAA;AAAA,UACC,KAAK;AAAA,UACL,MAAK;AAAA,UACL,QAAO;AAAA,UACP,WAAWG,QAAO;AAAA,UAClB,UAAU;AAAA;AAAA,MACZ;AAAA,MAEA,gBAAAH;AAAA,QAAC;AAAA;AAAA,UACC,KAAK;AAAA,UACL,WAAWG,QAAO;AAAA,UAClB;AAAA,UACA,UAAU,CAAC,MAAM,SAAS,EAAE,OAAO,KAAK;AAAA,UACxC,WAAW;AAAA,UACX,aAAY;AAAA,UACZ,UAAU,YAAY;AAAA,UACtB,MAAM;AAAA;AAAA,MACR;AAAA,MAEA,gBAAAH,KAAC,YAAO,WAAWG,QAAO,SAAS,SAAS,YAAY,UAAU,CAAC,SAAS,MAAK,UAC9E,sBACC,gBAAAH,KAAC,UAAK,WAAWG,QAAO,SAAS,IAEjC,gBAAAF,MAAC,SAAI,OAAM,MAAK,QAAO,MAAK,SAAQ,aAAY,MAAK,QAAO,QAAO,gBAAe,aAAY,OAAM,eAAc,SAAQ,gBAAe,SACvI;AAAA,wBAAAD,KAAC,UAAK,IAAG,MAAK,IAAG,MAAK,IAAG,MAAK,IAAG,KAAG;AAAA,QAAE,gBAAAA,KAAC,cAAS,QAAO,mBAAiB;AAAA,SAC1E,GAEJ;AAAA,OACF;AAAA,IAEA,gBAAAA,KAAC,OAAE,WAAWG,QAAO,MAAM,yDAAwC;AAAA,KACrE;AAEJ;AAEA,IAAMA,UAAS;AAAA,EACb,SAASJ;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAST,aAAaA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAMb,cAAcA;AAAA;AAAA;AAAA;AAAA;AAAA,EAKd,KAAK,CAAC,MAAcA;AAAA;AAAA;AAAA;AAAA;AAAA,iBAKL,KAAK;AAAA,uBACC,IAAI,IAAI;AAAA;AAAA;AAAA,EAG7B,eAAeA;AAAA;AAAA;AAAA;AAAA,EAIf,cAAcA;AAAA;AAAA;AAAA;AAAA;AAAA,EAKd,YAAYA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAQZ,YAAYA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAgBZ,UAAUA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAcV,WAAWA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAoBX,aAAaA;AAAA;AAAA;AAAA,EAGb,UAAUA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAmBV,SAASA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAmBT,SAASA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,iBAMM,IAAI;AAAA;AAAA;AAAA,EAGnB,MAAMA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAOR;;;AHzOY,gBAAAK,MAIJ,QAAAC,aAJI;AA1CL,IAAM,aAA8B,CAAC;AAAA,EAC1C;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AACF,MAAM;AACJ,QAAM,YAAYC,QAAuB,IAAI;AAC7C,QAAM,YAAYA,QAAuB,IAAI;AAC7C,QAAM,YAAY,WAAW;AAC7B,QAAM,CAAC,eAAe,gBAAgB,IAAIC,UAAS,KAAK;AAExD,QAAM,UAAU,SAAS,SAAS,SAAS,CAAC;AAC5C,QAAM,aAAa,cAAa,mCAAS,eAAc;AAEvD,EAAAC,WAAU,MAAM;AAnClB;AAoCI,oBAAU,YAAV,mBAAmB,eAAe,EAAE,UAAU,SAAS;AAAA,EACzD,GAAG,CAAC,QAAQ,CAAC;AAEb,QAAM,eAAe,MAAM;AACzB,UAAM,KAAK,UAAU;AACrB,QAAI,CAAC,GAAI;AACT,qBAAiB,GAAG,eAAe,GAAG,YAAY,GAAG,eAAe,EAAE;AAAA,EACxE;AAEA,SACE,gBAAAH,MAAC,SAAI,WAAWI,QAAO,SACrB;AAAA,oBAAAJ,MAAC,SAAI,WAAWI,QAAO,QACrB;AAAA,sBAAAL,KAAC,YAAO,WAAWK,QAAO,SAAS,SAAS,QAC1C,0BAAAL;AAAA,QAAC;AAAA;AAAA,UACC,OAAM;AAAA,UACN,QAAO;AAAA,UACP,SAAQ;AAAA,UACR,MAAK;AAAA,UACL,QAAO;AAAA,UACP,aAAY;AAAA,UACZ,eAAc;AAAA,UACd,gBAAe;AAAA,UAEf,0BAAAA,KAAC,cAAS,QAAO,mBAAkB;AAAA;AAAA,MACrC,GACF;AAAA,MAEA,gBAAAC,MAAC,SAAI,WAAWI,QAAO,cACrB;AAAA,wBAAAL,KAAC,UAAK,WAAWK,QAAO,aAAa,qBAAO;AAAA,QAC5C,gBAAAL,KAAC,UAAK,WAAWK,QAAO,UAAU,SAAS,GAAG;AAAA,QAC9C,gBAAAL,KAAC,UAAK,WAAWK,QAAO,aACrB,sBAAY,WAAW,iBAC1B;AAAA,SACF;AAAA,MAEA,gBAAAL,KAAC,YAAO,WAAWK,QAAO,WAAW,SAAS,UAC3C,uBACC,gBAAAJ;AAAA,QAAC;AAAA;AAAA,UACC,OAAM;AAAA,UACN,QAAO;AAAA,UACP,SAAQ;AAAA,UACR,MAAK;AAAA,UACL,QAAO;AAAA,UACP,aAAY;AAAA,UACZ,eAAc;AAAA,UACd,gBAAe;AAAA,UAEf;AAAA,4BAAAD,KAAC,cAAS,QAAO,oBAAmB;AAAA,YACpC,gBAAAA,KAAC,cAAS,QAAO,oBAAmB;AAAA,YACpC,gBAAAA,KAAC,UAAK,IAAG,MAAK,IAAG,MAAK,IAAG,KAAI,IAAG,MAAK;AAAA,YACrC,gBAAAA,KAAC,UAAK,IAAG,MAAK,IAAG,KAAI,IAAG,MAAK,IAAG,MAAK;AAAA;AAAA;AAAA,MACvC,IAEA,gBAAAC;AAAA,QAAC;AAAA;AAAA,UACC,OAAM;AAAA,UACN,QAAO;AAAA,UACP,SAAQ;AAAA,UACR,MAAK;AAAA,UACL,QAAO;AAAA,UACP,aAAY;AAAA,UACZ,eAAc;AAAA,UACd,gBAAe;AAAA,UAEf;AAAA,4BAAAD,KAAC,cAAS,QAAO,kBAAiB;AAAA,YAClC,gBAAAA,KAAC,cAAS,QAAO,kBAAiB;AAAA,YAClC,gBAAAA,KAAC,UAAK,IAAG,MAAK,IAAG,KAAI,IAAG,MAAK,IAAG,MAAK;AAAA,YACrC,gBAAAA,KAAC,UAAK,IAAG,KAAI,IAAG,MAAK,IAAG,MAAK,IAAG,MAAK;AAAA;AAAA;AAAA,MACvC,GAEJ;AAAA,OACF;AAAA,IAEA,gBAAAC,MAAC,SAAI,WAAWI,QAAO,cACrB;AAAA,sBAAAJ;AAAA,QAAC;AAAA;AAAA,UACC,WAAWI,QAAO;AAAA,UAClB,KAAK;AAAA,UACL,UAAU;AAAA,UAET;AAAA,qBAAS,gBAAAL,KAAC,SAAI,WAAWK,QAAO,aAAc,gBAAM,SAAQ;AAAA,YAC5D,SAAS,WAAW,KAAK,aACxB,gBAAAL,KAAC,SAAI,WAAWK,QAAO,YACrB,0BAAAL,KAAC,OAAE,uDAAyC,GAC9C;AAAA,YAED,SAAS,IAAI,CAAC,QACb,gBAAAA,KAAC,iBAA2B,SAAS,OAAjB,IAAI,EAAkB,CAC3C;AAAA,YACD,gBAAAA,KAAC,SAAI,KAAK,WAAW;AAAA;AAAA;AAAA,MACvB;AAAA,MAEC,iBACC,gBAAAA;AAAA,QAAC;AAAA;AAAA,UACC,WAAWK,QAAO;AAAA,UAClB,SAAS,MAAG;AAjIxB;AAkIc,mCAAU,YAAV,mBAAmB,eAAe,EAAE,UAAU,SAAS;AAAA;AAAA,UAGzD,0BAAAL;AAAA,YAAC;AAAA;AAAA,cACC,OAAM;AAAA,cACN,QAAO;AAAA,cACP,SAAQ;AAAA,cACR,MAAK;AAAA,cACL,QAAO;AAAA,cACP,aAAY;AAAA,cACZ,eAAc;AAAA,cACd,gBAAe;AAAA,cAEf,0BAAAA,KAAC,cAAS,QAAO,kBAAiB;AAAA;AAAA,UACpC;AAAA;AAAA,MACF;AAAA,OAEJ;AAAA,IAEA,gBAAAA;AAAA,MAAC;AAAA;AAAA,QACC;AAAA,QACA;AAAA,QACA,UAAU,CAAC;AAAA,QACX;AAAA;AAAA,IACF;AAAA,KACF;AAEJ;AAEA,IAAMM,SAAQC;AAAA;AAAA;AAAA;AAKd,IAAMF,UAAS;AAAA,EACb,SAASG;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAMT,QAAQA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAQR,cAAcA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAMd,aAAaA;AAAA;AAAA;AAAA;AAAA;AAAA,EAKb,WAAW,CAAC,cAAuBA;AAAA;AAAA;AAAA;AAAA;AAAA,kBAKnB,YAAY,YAAY,SAAS;AAAA,iBAClC,YAAY,SAAS,GAAGF,MAAK,4BAA4B;AAAA;AAAA,EAExE,aAAaE;AAAA;AAAA;AAAA;AAAA,EAIb,SAASA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAmBT,WAAWA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAsBX,cAAcA;AAAA;AAAA;AAAA;AAAA;AAAA,EAKd,UAAUA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EASV,aAAaA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EASb,YAAYA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAUZ,WAAWA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAwBb;;;AR9KI,mBACE,OAAAC,MADF,QAAAC,aAAA;AA7GJ,IAAM,aAAa;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAQnB,IAAM,YAAY;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAQlB,SAAS,iBAAiB,OAAe;AACvC,SAAO;AAAA,qBACY,KAAK;AAAA,8CACoB,KAAK;AAAA,gDACH,KAAK;AAAA;AAErD;AAEA,IAAM,kBAAkB;AAExB,SAAS,gBAAgB,OAAoC,cAAsB;AACjF,QAAM,UAAU,iBAAiB,YAAY;AAE7C,MAAI,UAAU,SAAS;AACrB,WAAO;AAAA;AAAA,UAED,UAAU;AAAA,UACV,OAAO;AAAA;AAAA;AAAA,EAGf;AAEA,MAAI,UAAU,QAAQ;AACpB,WAAO;AAAA;AAAA,UAED,SAAS;AAAA,UACT,OAAO;AAAA;AAAA;AAAA,EAGf;AAEA,SAAO;AAAA;AAAA,QAED,UAAU;AAAA,QACV,OAAO;AAAA;AAAA;AAAA;AAAA,UAIL,SAAS;AAAA,kDAC+B,YAAY;AAAA;AAAA;AAAA;AAI9D;AAEO,IAAM,aAAwC,CAAC,EAAE,OAAO,MAAM;AACnE,QAAM,CAAC,QAAQ,SAAS,IAAIC,UAAS,KAAK;AAC1C,QAAM,CAAC,YAAY,aAAa,IAAIA,UAAS,KAAK;AAClD,QAAM,CAAC,MAAM,OAAO,IAAIA,UAAe,MAAM;AAC7C,QAAM,CAAC,SAAS,IAAIA;AAAA,IAClB,MAAG;AAnFP;AAmFU,gCAAO,cAAP,YAAoB,cAAc,MAAlC,YAAuC;AAAA;AAAA,EAC/C;AAEA,QAAM,QAAQ,aAAa,CAAC,MAAM,EAAE,KAAK;AAEzC,QAAM,iBAA6B,iCAC9B,SAD8B;AAAA,IAEjC;AAAA,EACF;AAEA,QAAM,aAAa,CAAC,CAAC;AAErB,QAAM,EAAE,QAAQ,UAAU,OAAO,aAAa,SAAS,IAAI,QAAQ,cAAc;AAEjF,QAAM,wBAAwB,MAAM;AAClC,UAAM;AACN,YAAQ,MAAM;AAAA,EAChB;AAEA,EAAAC,WAAU,MAAM;AACd,UAAM,WAAW,OAAO,cAAc;AACtC,QAAI,UAAU;AACZ,eAAS,KAAK,MAAM,WAAW,SAAS,WAAW;AAAA,IACrD;AACA,WAAO,MAAM;AACX,eAAS,KAAK,MAAM,WAAW;AAAA,IACjC;AAAA,EACF,GAAG,CAAC,MAAM,CAAC;AAEX,EAAAA,WAAU,MAAM;AAhHlB;AAiHI,UAAM,SAAQ,YAAO,UAAP,YAAgB;AAC9B,UAAM,gBAAe,YAAO,iBAAP,YAAuB;AAC5C,UAAM,QAAQ,gBAAgB,OAAO,YAAY;AACjD,UAAM,KAAK,SAAS,cAAc,OAAO;AACzC,OAAG,aAAa,kBAAkB,EAAE;AACpC,OAAG,cAAc;AACjB,aAAS,KAAK,YAAY,EAAE;AAC5B,WAAO,MAAM;AACX,eAAS,KAAK,YAAY,EAAE;AAAA,IAC9B;AAAA,EACF,GAAG,CAAC,OAAO,OAAO,OAAO,YAAY,CAAC;AAEtC,SACE,gBAAAF,MAAA,YACE;AAAA,oBAAAD;AAAA,MAAC;AAAA;AAAA,QACC;AAAA,QACA,UAAU,MAAM,UAAU,CAAC,MAAM,CAAC,CAAC;AAAA;AAAA,IACrC;AAAA,IAEA,gBAAAA;AAAA,MAAC;AAAA;AAAA,QACC;AAAA,QACA;AAAA,QAEC,mBAAS,SACR,gBAAAA;AAAA,UAAC;AAAA;AAAA,YACC,aAAa;AAAA,YACb,gBAAgB,MAAM,QAAQ,MAAM;AAAA,YACpC;AAAA,YACA,UAAU,MAAM,cAAc,CAAC,MAAM,CAAC,CAAC;AAAA,YACvC;AAAA;AAAA,QACF,IAEA,gBAAAA;AAAA,UAAC;AAAA;AAAA,YACC;AAAA,YACA,YAAY;AAAA,YACZ,YAAY;AAAA,YACZ,QAAQ,MAAM,QAAQ,MAAM;AAAA,YAC5B,UAAU,MAAM,cAAc,CAAC,MAAM,CAAC,CAAC;AAAA,YACvC;AAAA,YACA;AAAA,YACA;AAAA;AAAA,QACF;AAAA;AAAA,IAEJ;AAAA,KACF;AAEJ;AAEA;AAAA;AAAA;AAAA;AAAA;AAAA;","names":["useEffect","useState","socket","useEffect","css","jsx","styles","css","jsx","jsxs","styles","useEffect","useRef","useState","css","keyframes","css","css","jsx","jsx","jsxs","styles","css","useState","useCallback","css","jsx","jsxs","_a","styles","jsx","jsxs","useRef","useState","useEffect","styles","pulse","keyframes","css","jsx","jsxs","useState","useEffect"]}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@waysdrop/chat",
3
- "version": "1.0.4",
3
+ "version": "1.0.6",
4
4
  "description": "Floating support chat widget for React apps",
5
5
  "license": "UNLICENSED",
6
6
  "homepage": "https://waysdrop.com",