mehdi-akbari-ai-assistant-free 0.0.1 → 0.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/react.js +35 -29
- package/dist/react.js.map +1 -1
- package/dist/react.mjs +35 -29
- package/dist/react.mjs.map +1 -1
- package/package.json +23 -6
- package/dist/react.css +0 -132
- package/dist/react.css.map +0 -1
package/dist/react.js
CHANGED
|
@@ -39,27 +39,24 @@ module.exports = __toCommonJS(react_exports);
|
|
|
39
39
|
var import_react3 = require("react");
|
|
40
40
|
var import_clsx3 = __toESM(require("clsx"));
|
|
41
41
|
|
|
42
|
-
// src/components/ChatWindow/ChatWindow.module.css
|
|
43
|
-
var ChatWindow_default = {};
|
|
44
|
-
|
|
45
42
|
// src/components/MessageList/MessageList.tsx
|
|
46
43
|
var import_react = require("react");
|
|
47
|
-
var import_clsx2 = __toESM(require("clsx"));
|
|
48
|
-
|
|
49
|
-
// src/components/MessageList/MessageList.module.css
|
|
50
|
-
var MessageList_default = {};
|
|
51
44
|
|
|
52
45
|
// src/components/MessageBubble/MessageBubble.tsx
|
|
53
46
|
var import_clsx = __toESM(require("clsx"));
|
|
54
|
-
|
|
55
|
-
// src/components/MessageBubble/MessageBubble.module.css
|
|
56
|
-
var MessageBubble_default = {};
|
|
57
|
-
|
|
58
|
-
// src/components/MessageBubble/MessageBubble.tsx
|
|
59
47
|
var import_jsx_runtime = require("react/jsx-runtime");
|
|
60
48
|
var MessageBubble = ({ message }) => {
|
|
61
49
|
const isUser = message.role === "user";
|
|
62
|
-
return /* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", { className: (0, import_clsx.default)(
|
|
50
|
+
return /* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", { className: (0, import_clsx.default)("flex w-full", isUser ? "justify-end" : "justify-start"), children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
|
|
51
|
+
"div",
|
|
52
|
+
{
|
|
53
|
+
className: (0, import_clsx.default)(
|
|
54
|
+
"max-w-[80%] px-3 py-2 rounded-xl text-sm break-words",
|
|
55
|
+
isUser ? "bg-[var(--ai-user-bg)] text-[var(--ai-user-text)] rounded-br-sm" : "bg-[var(--ai-bot-bg)] text-[var(--ai-text)] rounded-bl-sm"
|
|
56
|
+
),
|
|
57
|
+
children: message.content
|
|
58
|
+
}
|
|
59
|
+
) });
|
|
63
60
|
};
|
|
64
61
|
|
|
65
62
|
// src/components/MessageList/MessageList.tsx
|
|
@@ -69,12 +66,12 @@ var MessageList = ({ messages, isLoading }) => {
|
|
|
69
66
|
(0, import_react.useEffect)(() => {
|
|
70
67
|
messagesEndRef.current?.scrollIntoView({ behavior: "smooth" });
|
|
71
68
|
}, [messages, isLoading]);
|
|
72
|
-
return /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("div", { className:
|
|
69
|
+
return /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("div", { className: "flex-1 overflow-y-auto p-4 flex flex-col gap-3 scroll-smooth", children: [
|
|
73
70
|
messages.map((msg, index) => /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(MessageBubble, { message: msg }, index)),
|
|
74
|
-
isLoading && /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("div", { className:
|
|
75
|
-
/* @__PURE__ */ (0, import_jsx_runtime2.jsx)("div", { className:
|
|
76
|
-
/* @__PURE__ */ (0, import_jsx_runtime2.jsx)("div", { className:
|
|
77
|
-
/* @__PURE__ */ (0, import_jsx_runtime2.jsx)("div", { className:
|
|
71
|
+
isLoading && /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("div", { className: "flex justify-start", children: /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("div", { className: "max-w-[80%] px-3 py-2 rounded-xl bg-[var(--ai-bot-bg)] text-[var(--ai-text)] rounded-bl-sm flex gap-1 items-center", children: [
|
|
72
|
+
/* @__PURE__ */ (0, import_jsx_runtime2.jsx)("div", { className: "w-1.5 h-1.5 bg-gray-400 rounded-full animate-bounce", style: { animationDelay: "-0.32s" } }),
|
|
73
|
+
/* @__PURE__ */ (0, import_jsx_runtime2.jsx)("div", { className: "w-1.5 h-1.5 bg-gray-400 rounded-full animate-bounce", style: { animationDelay: "-0.16s" } }),
|
|
74
|
+
/* @__PURE__ */ (0, import_jsx_runtime2.jsx)("div", { className: "w-1.5 h-1.5 bg-gray-400 rounded-full animate-bounce" })
|
|
78
75
|
] }) }),
|
|
79
76
|
/* @__PURE__ */ (0, import_jsx_runtime2.jsx)("div", { ref: messagesEndRef })
|
|
80
77
|
] });
|
|
@@ -82,11 +79,7 @@ var MessageList = ({ messages, isLoading }) => {
|
|
|
82
79
|
|
|
83
80
|
// src/components/ChatInput/ChatInput.tsx
|
|
84
81
|
var import_react2 = require("react");
|
|
85
|
-
|
|
86
|
-
// src/components/ChatInput/ChatInput.module.css
|
|
87
|
-
var ChatInput_default = {};
|
|
88
|
-
|
|
89
|
-
// src/components/ChatInput/ChatInput.tsx
|
|
82
|
+
var import_clsx2 = __toESM(require("clsx"));
|
|
90
83
|
var import_lucide_react = require("lucide-react");
|
|
91
84
|
var import_jsx_runtime3 = require("react/jsx-runtime");
|
|
92
85
|
var ChatInput = ({ onSendMessage, isLoading }) => {
|
|
@@ -103,11 +96,15 @@ var ChatInput = ({ onSendMessage, isLoading }) => {
|
|
|
103
96
|
handleSend();
|
|
104
97
|
}
|
|
105
98
|
};
|
|
106
|
-
return /* @__PURE__ */ (0, import_jsx_runtime3.jsxs)("div", { className:
|
|
99
|
+
return /* @__PURE__ */ (0, import_jsx_runtime3.jsxs)("div", { className: "flex gap-2 p-3 border-t border-[var(--ai-border)] bg-[var(--ai-bg)]", children: [
|
|
107
100
|
/* @__PURE__ */ (0, import_jsx_runtime3.jsx)(
|
|
108
101
|
"input",
|
|
109
102
|
{
|
|
110
|
-
className:
|
|
103
|
+
className: (0, import_clsx2.default)(
|
|
104
|
+
"flex-1 px-3 py-2 border border-[var(--ai-border)] rounded-lg outline-none",
|
|
105
|
+
"font-inherit text-[var(--ai-text)] placeholder:text-[var(--ai-text-secondary)]",
|
|
106
|
+
"focus:border-[var(--ai-primary)] disabled:opacity-50"
|
|
107
|
+
),
|
|
111
108
|
value: inputValue,
|
|
112
109
|
onChange: (e) => setInputValue(e.target.value),
|
|
113
110
|
onKeyDown: handleKeyDown,
|
|
@@ -118,7 +115,12 @@ var ChatInput = ({ onSendMessage, isLoading }) => {
|
|
|
118
115
|
/* @__PURE__ */ (0, import_jsx_runtime3.jsx)(
|
|
119
116
|
"button",
|
|
120
117
|
{
|
|
121
|
-
className:
|
|
118
|
+
className: (0, import_clsx2.default)(
|
|
119
|
+
"px-3 py-2 rounded-lg flex items-center justify-center transition-opacity",
|
|
120
|
+
"bg-[var(--ai-primary)] text-[var(--ai-primary-fg)]",
|
|
121
|
+
"hover:opacity-90",
|
|
122
|
+
(isLoading || !inputValue.trim()) && "opacity-50 cursor-not-allowed"
|
|
123
|
+
),
|
|
122
124
|
onClick: handleSend,
|
|
123
125
|
disabled: isLoading || !inputValue.trim(),
|
|
124
126
|
children: /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(import_lucide_react.Send, { size: 18 })
|
|
@@ -165,10 +167,14 @@ var ChatWindow = ({
|
|
|
165
167
|
setIsLoading(false);
|
|
166
168
|
}
|
|
167
169
|
};
|
|
168
|
-
return /* @__PURE__ */ (0, import_jsx_runtime4.jsxs)("div", { className: (0, import_clsx3.default)(
|
|
169
|
-
|
|
170
|
+
return /* @__PURE__ */ (0, import_jsx_runtime4.jsxs)("div", { className: (0, import_clsx3.default)(
|
|
171
|
+
"flex flex-col h-[500px] w-full max-w-md rounded-xl border border-[var(--ai-border)]",
|
|
172
|
+
"bg-[var(--ai-bg)] overflow-hidden shadow-lg relative",
|
|
173
|
+
"font-inherit text-base leading-6 box-border"
|
|
174
|
+
), children: [
|
|
175
|
+
/* @__PURE__ */ (0, import_jsx_runtime4.jsxs)("div", { className: "flex items-center gap-2 px-4 py-4 border-b border-[var(--ai-border)] bg-gray-50", children: [
|
|
170
176
|
/* @__PURE__ */ (0, import_jsx_runtime4.jsx)(import_lucide_react2.Bot, { size: 20 }),
|
|
171
|
-
/* @__PURE__ */ (0, import_jsx_runtime4.jsx)("span", {
|
|
177
|
+
/* @__PURE__ */ (0, import_jsx_runtime4.jsx)("span", { className: "font-semibold", children: title })
|
|
172
178
|
] }),
|
|
173
179
|
/* @__PURE__ */ (0, import_jsx_runtime4.jsx)(MessageList, { messages, isLoading }),
|
|
174
180
|
/* @__PURE__ */ (0, import_jsx_runtime4.jsx)(ChatInput, { onSendMessage: handleSendMessage, isLoading })
|
package/dist/react.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/react.ts","../src/components/ChatWindow/ChatWindow.tsx","../src/components/ChatWindow/ChatWindow.module.css","../src/components/MessageList/MessageList.tsx","../src/components/MessageList/MessageList.module.css","../src/components/MessageBubble/MessageBubble.tsx","../src/components/MessageBubble/MessageBubble.module.css","../src/components/ChatInput/ChatInput.tsx","../src/components/ChatInput/ChatInput.module.css"],"sourcesContent":["\"use client\";\r\n\r\n\r\n\r\n\r\nexport { ChatWindow, type ChatWindowProps } from \"./components/ChatWindow/ChatWindow\";\r\n\r\n\r\nexport * from \"./types\";","// src/components/ChatWindow/ChatWindow.tsx\r\nimport React, { useState, useEffect } from 'react';\r\nimport clsx from 'clsx';\r\nimport styles from './ChatWindow.module.css';\r\nimport { MessageList } from '../MessageList/MessageList';\r\nimport { ChatInput } from '../ChatInput/ChatInput';\r\nimport { Message } from '../../types';\r\nimport { Bot } from 'lucide-react';\r\n\r\nexport interface ChatWindowProps {\r\n apiEndpoint: string;\r\n title?: string;\r\n welcomeMessage?: string;\r\n}\r\n\r\nexport const ChatWindow: React.FC<ChatWindowProps> = ({\r\n apiEndpoint,\r\n title = \"AI Assistant\",\r\n welcomeMessage = \"سلام! چطور میتوانم کمکتان کنم؟\"\r\n}) => {\r\n const [messages, setMessages] = useState<Message[]>([]);\r\n const [isLoading, setIsLoading] = useState(false);\r\n\r\n useEffect(() => {\r\n if (welcomeMessage && messages.length === 0) {\r\n setMessages([{ role: 'assistant', content: welcomeMessage }]);\r\n }\r\n }, [welcomeMessage]);\r\n\r\n const handleSendMessage = async (userMessage: string) => {\r\n const newUserMsg: Message = { role: 'user', content: userMessage };\r\n const currentMessages = [...messages, newUserMsg];\r\n setMessages(currentMessages);\r\n setIsLoading(true);\r\n\r\n try {\r\n const response = await fetch(apiEndpoint, {\r\n method: 'POST',\r\n headers: { 'Content-Type': 'application/json' },\r\n body: JSON.stringify({ messages: currentMessages }),\r\n });\r\n\r\n if (!response.ok) throw new Error(\"Network response was not ok\");\r\n \r\n const data = await response.json();\r\n const botMsg: Message = { role: 'assistant', content: data.content };\r\n setMessages(prev => [...prev, botMsg]);\r\n\r\n } catch (error) {\r\n console.error(\"Chat Error:\", error);\r\n const errorMsg: Message = { role: 'assistant', content: \"خطایی رخ داده است.\" };\r\n setMessages(prev => [...prev, errorMsg]);\r\n } finally {\r\n setIsLoading(false);\r\n }\r\n };\r\n\r\n return (\r\n <div className={clsx(styles.container, styles.chatWindow)}>\r\n <div style={{ padding: '16px', borderBottom: '1px solid var(--ai-border)', display: 'flex', alignItems: 'center', gap: '8px', background: '#f9fafb' }}>\r\n <Bot size={20} />\r\n <span style={{ fontWeight: 600 }}>{title}</span>\r\n </div>\r\n <MessageList messages={messages} isLoading={isLoading} />\r\n <ChatInput onSendMessage={handleSendMessage} isLoading={isLoading} />\r\n </div>\r\n );\r\n};","/* \r\n این فایل استایلهای اصلی و کانتینر چت را تعریف میکند.\r\n متغیرهای CSS به کاربر اجازه میدهند تا به راحتی ظاهر ربات را شخصیسازی کند.\r\n*/\r\n\r\n.container {\r\n /* ======== متغیرهای قابل شخصیسازی ======== */\r\n \r\n /* رنگ اصلی (دکمه ارسال، حباب کاربر) */\r\n --ai-primary: #2563eb;\r\n /* رنگ متن روی المانهای اصلی */\r\n --ai-primary-fg: #ffffff;\r\n\r\n /* رنگهای پسزمینه */\r\n --ai-bg: #ffffff;\r\n --ai-bot-bg: #f3f4f6;\r\n --ai-user-bg: var(--ai-primary);\r\n\r\n /* رنگهای متن */\r\n --ai-text: #1f2937;\r\n --ai-text-secondary: #6b7280;\r\n --ai-user-text: var(--ai-primary-fg);\r\n\r\n /* رنگ حاشیه و جداکنندهها */\r\n --ai-border: #e5e7eb;\r\n\r\n /* ======================================== */\r\n\r\n /* ارثبری فونت از سایت میزبان برای هماهنگی بیشتر */\r\n font-family: inherit; \r\n font-size: 16px;\r\n line-height: 1.5;\r\n box-sizing: border-box;\r\n}\r\n\r\n/* کانتینر اصلی پنجره چت */\r\n.chatWindow {\r\n display: flex;\r\n flex-direction: column;\r\n height: 500px; /* ارتفاع پیشفرض، کاربر میتواند تغییر دهد */\r\n width: 100%;\r\n max-width: 400px;\r\n background-color: var(--ai-bg);\r\n border: 1px solid var(--ai-border);\r\n border-radius: 12px;\r\n overflow: hidden; /* برای اینکه گوشههای گرد درست نمایش داده شوند */\r\n box-shadow: 0 4px 6px -1px rgba(0, 0, 0, 0.1), 0 2px 4px -2px rgba(0, 0, 0, 0.1);\r\n position: relative;\r\n}","// src/components/MessageList/MessageList.tsx\r\nimport React, { useRef, useEffect } from 'react';\r\nimport clsx from 'clsx';\r\nimport styles from './MessageList.module.css';\r\nimport { MessageBubble } from '../MessageBubble/MessageBubble';\r\nimport { Message } from '../../types';\r\n\r\ninterface MessageListProps {\r\n messages: Message[];\r\n isLoading: boolean;\r\n}\r\n\r\nexport const MessageList: React.FC<MessageListProps> = ({ messages, isLoading }) => {\r\n const messagesEndRef = useRef<HTMLDivElement>(null);\r\n\r\n useEffect(() => {\r\n messagesEndRef.current?.scrollIntoView({ behavior: 'smooth' });\r\n }, [messages, isLoading]);\r\n\r\n return (\r\n <div className={styles.messageList}>\r\n {messages.map((msg, index) => (\r\n <MessageBubble key={index} message={msg} />\r\n ))}\r\n {isLoading && (\r\n <div className={clsx(styles.messageRow, styles.assistant)}>\r\n <div className={clsx(styles.bubble, styles.assistant, styles.loading)}>\r\n <div className={styles.dot}></div>\r\n <div className={styles.dot}></div>\r\n <div className={styles.dot}></div>\r\n </div>\r\n </div>\r\n )}\r\n <div ref={messagesEndRef} />\r\n </div>\r\n );\r\n};",".messageList {\r\nflex: 1;\r\noverflow-y: auto;\r\npadding: 16px;\r\ndisplay: flex;\r\nflex-direction: column;\r\ngap: 12px;\r\nscroll-behavior: smooth;\r\n}\r\n/* این استایلها برای انیمیشن لودینگ هستند */\r\n.loading {\r\ndisplay: flex;\r\ngap: 4px;\r\npadding: 4px;\r\n}\r\n.dot {\r\nwidth: 6px;\r\nheight: 6px;\r\nbackground-color: #9ca3af;\r\nborder-radius: 50%;\r\nanimation: bounce 1.4s infinite ease-in-out both;\r\n}\r\n.dot:nth-child(1) { animation-delay: -0.32s; }\r\n.dot:nth-child(2) { animation-delay: -0.16s; }\r\n@keyframes bounce {\r\n0%, 80%, 100% { transform: scale(0); }\r\n40% { transform: scale(1); }\r\n}","// src/components/MessageBubble/MessageBubble.tsx\r\nimport React from 'react';\r\nimport clsx from 'clsx';\r\nimport styles from './MessageBubble.module.css'; // 👈 مسیر جدید\r\nimport { Message } from '../../types';\r\n\r\ninterface MessageBubbleProps {\r\n message: Message;\r\n}\r\n\r\nexport const MessageBubble: React.FC<MessageBubbleProps> = ({ message }) => {\r\n const isUser = message.role === 'user';\r\n return (\r\n <div className={clsx(styles.messageRow, isUser ? styles.user : styles.assistant)}>\r\n <div className={clsx(styles.bubble, isUser ? styles.user : styles.assistant)}>\r\n {message.content}\r\n </div>\r\n </div>\r\n );\r\n};",".messageRow {\r\n display: flex;\r\n width: 100%;\r\n}\r\n.messageRow.user {\r\n justify-content: flex-end;\r\n}\r\n.messageRow.assistant {\r\n justify-content: flex-start;\r\n}\r\n.bubble {\r\n max-width: 80%;\r\n padding: 8px 12px;\r\n border-radius: 12px;\r\n font-size: 0.95em;\r\n word-wrap: break-word;\r\n}\r\n.bubble.user {\r\n background-color: var(--ai-user-bg, #2563eb);\r\n color: var(--ai-user-text, #ffffff);\r\n border-bottom-right-radius: 2px;\r\n}\r\n.bubble.assistant {\r\n background-color: var(--ai-bot-bg, #f3f4f6);\r\n color: var(--ai-text, #1f2937);\r\n border-bottom-left-radius: 2px;\r\n}","// src/components/ChatInput/ChatInput.tsx\r\nimport React, { useState } from 'react';\r\nimport styles from './ChatInput.module.css';\r\nimport { Send } from 'lucide-react';\r\n\r\ninterface ChatInputProps {\r\n onSendMessage: (message: string) => void;\r\n isLoading: boolean;\r\n}\r\n\r\nexport const ChatInput: React.FC<ChatInputProps> = ({ onSendMessage, isLoading }) => {\r\n const [inputValue, setInputValue] = useState('');\r\n\r\n const handleSend = () => {\r\n if (inputValue.trim()) {\r\n onSendMessage(inputValue);\r\n setInputValue('');\r\n }\r\n };\r\n\r\n const handleKeyDown = (e: React.KeyboardEvent) => {\r\n if (e.key === 'Enter' && !e.shiftKey) {\r\n e.preventDefault();\r\n handleSend();\r\n }\r\n };\r\n\r\n return (\r\n <div className={styles.inputArea}>\r\n <input\r\n className={styles.input}\r\n value={inputValue}\r\n onChange={(e) => setInputValue(e.target.value)}\r\n onKeyDown={handleKeyDown}\r\n placeholder=\"پیام خود را بنویسید...\"\r\n disabled={isLoading}\r\n />\r\n <button\r\n className={styles.sendButton}\r\n onClick={handleSend}\r\n disabled={isLoading || !inputValue.trim()}\r\n >\r\n <Send size={18} />\r\n </button>\r\n </div>\r\n );\r\n};","/* src/components/ChatInput/ChatInput.module.css */\r\n.inputArea {\r\n padding: 12px;\r\n border-top: 1px solid var(--ai-border, #e5e7eb);\r\n display: flex;\r\n gap: 8px;\r\n background-color: var(--ai-bg, #ffffff);\r\n}\r\n.input {\r\n flex: 1;\r\n padding: 8px 12px;\r\n border: 1px solid var(--ai-border, #e5e7eb);\r\n border-radius: 8px;\r\n outline: none;\r\n font-family: inherit;\r\n}\r\n.input:focus {\r\n border-color: var(--ai-primary, #2563eb);\r\n}\r\n.sendButton {\r\n background-color: var(--ai-primary, #2563eb);\r\n color: var(--ai-primary-fg, #ffffff);\r\n border: none;\r\n border-radius: 8px;\r\n padding: 8px 12px;\r\n cursor: pointer;\r\n display: flex;\r\n align-items: center;\r\n justify-content: center;\r\n transition: opacity 0.2s;\r\n}\r\n.sendButton:disabled {\r\n opacity: 0.5;\r\n cursor: not-allowed;\r\n}"],"mappings":"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","names":["import_react","import_clsx","import_clsx","clsx","import_jsx_runtime","clsx","import_react","import_jsx_runtime","import_lucide_react","import_jsx_runtime","clsx"]}
|
|
1
|
+
{"version":3,"sources":["../src/react.ts","../src/components/ChatWindow/ChatWindow.tsx","../src/components/MessageList/MessageList.tsx","../src/components/MessageBubble/MessageBubble.tsx","../src/components/ChatInput/ChatInput.tsx"],"sourcesContent":["\"use client\";\r\n\r\n\r\n\r\n\r\nexport { ChatWindow, type ChatWindowProps } from \"./components/ChatWindow/ChatWindow\";\r\n\r\n\r\nexport * from \"./types\";","// src/components/ChatWindow/ChatWindow.tsx\r\n\"use client\";\r\n\r\nimport React, { useState, useEffect } from 'react';\r\nimport clsx from 'clsx';\r\nimport { MessageList } from '../MessageList/MessageList';\r\nimport { ChatInput } from '../ChatInput/ChatInput';\r\nimport { Message } from '../../types';\r\nimport { Bot } from 'lucide-react';\r\n\r\nexport interface ChatWindowProps {\r\n apiEndpoint: string;\r\n title?: string;\r\n welcomeMessage?: string;\r\n}\r\n\r\nexport const ChatWindow: React.FC<ChatWindowProps> = ({\r\n apiEndpoint,\r\n title = \"AI Assistant\",\r\n welcomeMessage = \"سلام! چطور میتوانم کمکتان کنم؟\"\r\n}) => {\r\n const [messages, setMessages] = useState<Message[]>([]);\r\n const [isLoading, setIsLoading] = useState(false);\r\n\r\n useEffect(() => {\r\n if (welcomeMessage && messages.length === 0) {\r\n setMessages([{ role: 'assistant', content: welcomeMessage }]);\r\n }\r\n }, [welcomeMessage]);\r\n\r\n const handleSendMessage = async (userMessage: string) => {\r\n const newUserMsg: Message = { role: 'user', content: userMessage };\r\n const currentMessages = [...messages, newUserMsg];\r\n setMessages(currentMessages);\r\n setIsLoading(true);\r\n\r\n try {\r\n const response = await fetch(apiEndpoint, {\r\n method: 'POST',\r\n headers: { 'Content-Type': 'application/json' },\r\n body: JSON.stringify({ messages: currentMessages }),\r\n });\r\n\r\n if (!response.ok) throw new Error(\"Network response was not ok\");\r\n \r\n const data = await response.json();\r\n const botMsg: Message = { role: 'assistant', content: data.content };\r\n setMessages(prev => [...prev, botMsg]);\r\n\r\n } catch (error) {\r\n console.error(\"Chat Error:\", error);\r\n const errorMsg: Message = { role: 'assistant', content: \"خطایی رخ داده است.\" };\r\n setMessages(prev => [...prev, errorMsg]);\r\n } finally {\r\n setIsLoading(false);\r\n }\r\n };\r\n\r\n return (\r\n <div className={clsx(\r\n \"flex flex-col h-[500px] w-full max-w-md rounded-xl border border-[var(--ai-border)]\",\r\n \"bg-[var(--ai-bg)] overflow-hidden shadow-lg relative\",\r\n \"font-inherit text-base leading-6 box-border\"\r\n )}>\r\n <div className=\"flex items-center gap-2 px-4 py-4 border-b border-[var(--ai-border)] bg-gray-50\">\r\n <Bot size={20} />\r\n <span className=\"font-semibold\">{title}</span>\r\n </div>\r\n\r\n <MessageList messages={messages} isLoading={isLoading} />\r\n <ChatInput onSendMessage={handleSendMessage} isLoading={isLoading} />\r\n </div>\r\n );\r\n};","// src/components/MessageList/MessageList.tsx\r\n\"use client\";\r\n\r\nimport React, { useRef, useEffect } from 'react';\r\nimport clsx from 'clsx';\r\nimport { MessageBubble } from '../MessageBubble/MessageBubble';\r\nimport { Message } from '../../types';\r\n\r\ninterface MessageListProps {\r\n messages: Message[];\r\n isLoading: boolean;\r\n}\r\n\r\nexport const MessageList: React.FC<MessageListProps> = ({ messages, isLoading }) => {\r\n const messagesEndRef = useRef<HTMLDivElement>(null);\r\n\r\n useEffect(() => {\r\n messagesEndRef.current?.scrollIntoView({ behavior: 'smooth' });\r\n }, [messages, isLoading]);\r\n\r\n return (\r\n <div className=\"flex-1 overflow-y-auto p-4 flex flex-col gap-3 scroll-smooth\">\r\n {messages.map((msg, index) => (\r\n <MessageBubble key={index} message={msg} />\r\n ))}\r\n\r\n {isLoading && (\r\n <div className=\"flex justify-start\">\r\n <div className=\"max-w-[80%] px-3 py-2 rounded-xl bg-[var(--ai-bot-bg)] text-[var(--ai-text)] rounded-bl-sm flex gap-1 items-center\">\r\n <div className=\"w-1.5 h-1.5 bg-gray-400 rounded-full animate-bounce\" style={{ animationDelay: '-0.32s' }}></div>\r\n <div className=\"w-1.5 h-1.5 bg-gray-400 rounded-full animate-bounce\" style={{ animationDelay: '-0.16s' }}></div>\r\n <div className=\"w-1.5 h-1.5 bg-gray-400 rounded-full animate-bounce\"></div>\r\n </div>\r\n </div>\r\n )}\r\n\r\n <div ref={messagesEndRef} />\r\n </div>\r\n );\r\n};","// src/components/MessageBubble/MessageBubble.tsx\r\n\"use client\";\r\n\r\nimport React from 'react';\r\nimport clsx from 'clsx';\r\nimport { Message } from '../../types';\r\n\r\ninterface MessageBubbleProps {\r\n message: Message;\r\n}\r\n\r\nexport const MessageBubble: React.FC<MessageBubbleProps> = ({ message }) => {\r\n const isUser = message.role === 'user';\r\n\r\n return (\r\n <div className={clsx(\"flex w-full\", isUser ? \"justify-end\" : \"justify-start\")}>\r\n <div\r\n className={clsx(\r\n \"max-w-[80%] px-3 py-2 rounded-xl text-sm break-words\",\r\n isUser\r\n ? \"bg-[var(--ai-user-bg)] text-[var(--ai-user-text)] rounded-br-sm\"\r\n : \"bg-[var(--ai-bot-bg)] text-[var(--ai-text)] rounded-bl-sm\"\r\n )}\r\n >\r\n {message.content}\r\n </div>\r\n </div>\r\n );\r\n};","// src/components/ChatInput/ChatInput.tsx\r\n\"use client\";\r\n\r\nimport React, { useState } from 'react';\r\nimport clsx from 'clsx';\r\nimport { Send } from 'lucide-react';\r\n\r\ninterface ChatInputProps {\r\n onSendMessage: (message: string) => void;\r\n isLoading: boolean;\r\n}\r\n\r\nexport const ChatInput: React.FC<ChatInputProps> = ({ onSendMessage, isLoading }) => {\r\n const [inputValue, setInputValue] = useState('');\r\n\r\n const handleSend = () => {\r\n if (inputValue.trim()) {\r\n onSendMessage(inputValue);\r\n setInputValue('');\r\n }\r\n };\r\n\r\n const handleKeyDown = (e: React.KeyboardEvent) => {\r\n if (e.key === 'Enter' && !e.shiftKey) {\r\n e.preventDefault();\r\n handleSend();\r\n }\r\n };\r\n\r\n return (\r\n <div className=\"flex gap-2 p-3 border-t border-[var(--ai-border)] bg-[var(--ai-bg)]\">\r\n <input\r\n className={clsx(\r\n \"flex-1 px-3 py-2 border border-[var(--ai-border)] rounded-lg outline-none\",\r\n \"font-inherit text-[var(--ai-text)] placeholder:text-[var(--ai-text-secondary)]\",\r\n \"focus:border-[var(--ai-primary)] disabled:opacity-50\"\r\n )}\r\n value={inputValue}\r\n onChange={(e) => setInputValue(e.target.value)}\r\n onKeyDown={handleKeyDown}\r\n placeholder=\"پیام خود را بنویسید...\"\r\n disabled={isLoading}\r\n />\r\n <button\r\n className={clsx(\r\n \"px-3 py-2 rounded-lg flex items-center justify-center transition-opacity\",\r\n \"bg-[var(--ai-primary)] text-[var(--ai-primary-fg)]\",\r\n \"hover:opacity-90\",\r\n (isLoading || !inputValue.trim()) && \"opacity-50 cursor-not-allowed\"\r\n )}\r\n onClick={handleSend}\r\n disabled={isLoading || !inputValue.trim()}\r\n >\r\n <Send size={18} />\r\n </button>\r\n </div>\r\n );\r\n};"],"mappings":"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","names":["import_react","import_clsx","clsx","import_jsx_runtime","import_react","import_clsx","import_jsx_runtime","clsx","import_lucide_react","import_jsx_runtime","clsx"]}
|
package/dist/react.mjs
CHANGED
|
@@ -4,27 +4,24 @@
|
|
|
4
4
|
import { useState as useState2, useEffect as useEffect2 } from "react";
|
|
5
5
|
import clsx3 from "clsx";
|
|
6
6
|
|
|
7
|
-
// src/components/ChatWindow/ChatWindow.module.css
|
|
8
|
-
var ChatWindow_default = {};
|
|
9
|
-
|
|
10
7
|
// src/components/MessageList/MessageList.tsx
|
|
11
8
|
import { useRef, useEffect } from "react";
|
|
12
|
-
import clsx2 from "clsx";
|
|
13
|
-
|
|
14
|
-
// src/components/MessageList/MessageList.module.css
|
|
15
|
-
var MessageList_default = {};
|
|
16
9
|
|
|
17
10
|
// src/components/MessageBubble/MessageBubble.tsx
|
|
18
11
|
import clsx from "clsx";
|
|
19
|
-
|
|
20
|
-
// src/components/MessageBubble/MessageBubble.module.css
|
|
21
|
-
var MessageBubble_default = {};
|
|
22
|
-
|
|
23
|
-
// src/components/MessageBubble/MessageBubble.tsx
|
|
24
12
|
import { jsx } from "react/jsx-runtime";
|
|
25
13
|
var MessageBubble = ({ message }) => {
|
|
26
14
|
const isUser = message.role === "user";
|
|
27
|
-
return /* @__PURE__ */ jsx("div", { className: clsx(
|
|
15
|
+
return /* @__PURE__ */ jsx("div", { className: clsx("flex w-full", isUser ? "justify-end" : "justify-start"), children: /* @__PURE__ */ jsx(
|
|
16
|
+
"div",
|
|
17
|
+
{
|
|
18
|
+
className: clsx(
|
|
19
|
+
"max-w-[80%] px-3 py-2 rounded-xl text-sm break-words",
|
|
20
|
+
isUser ? "bg-[var(--ai-user-bg)] text-[var(--ai-user-text)] rounded-br-sm" : "bg-[var(--ai-bot-bg)] text-[var(--ai-text)] rounded-bl-sm"
|
|
21
|
+
),
|
|
22
|
+
children: message.content
|
|
23
|
+
}
|
|
24
|
+
) });
|
|
28
25
|
};
|
|
29
26
|
|
|
30
27
|
// src/components/MessageList/MessageList.tsx
|
|
@@ -34,12 +31,12 @@ var MessageList = ({ messages, isLoading }) => {
|
|
|
34
31
|
useEffect(() => {
|
|
35
32
|
messagesEndRef.current?.scrollIntoView({ behavior: "smooth" });
|
|
36
33
|
}, [messages, isLoading]);
|
|
37
|
-
return /* @__PURE__ */ jsxs("div", { className:
|
|
34
|
+
return /* @__PURE__ */ jsxs("div", { className: "flex-1 overflow-y-auto p-4 flex flex-col gap-3 scroll-smooth", children: [
|
|
38
35
|
messages.map((msg, index) => /* @__PURE__ */ jsx2(MessageBubble, { message: msg }, index)),
|
|
39
|
-
isLoading && /* @__PURE__ */ jsx2("div", { className:
|
|
40
|
-
/* @__PURE__ */ jsx2("div", { className:
|
|
41
|
-
/* @__PURE__ */ jsx2("div", { className:
|
|
42
|
-
/* @__PURE__ */ jsx2("div", { className:
|
|
36
|
+
isLoading && /* @__PURE__ */ jsx2("div", { className: "flex justify-start", children: /* @__PURE__ */ jsxs("div", { className: "max-w-[80%] px-3 py-2 rounded-xl bg-[var(--ai-bot-bg)] text-[var(--ai-text)] rounded-bl-sm flex gap-1 items-center", children: [
|
|
37
|
+
/* @__PURE__ */ jsx2("div", { className: "w-1.5 h-1.5 bg-gray-400 rounded-full animate-bounce", style: { animationDelay: "-0.32s" } }),
|
|
38
|
+
/* @__PURE__ */ jsx2("div", { className: "w-1.5 h-1.5 bg-gray-400 rounded-full animate-bounce", style: { animationDelay: "-0.16s" } }),
|
|
39
|
+
/* @__PURE__ */ jsx2("div", { className: "w-1.5 h-1.5 bg-gray-400 rounded-full animate-bounce" })
|
|
43
40
|
] }) }),
|
|
44
41
|
/* @__PURE__ */ jsx2("div", { ref: messagesEndRef })
|
|
45
42
|
] });
|
|
@@ -47,11 +44,7 @@ var MessageList = ({ messages, isLoading }) => {
|
|
|
47
44
|
|
|
48
45
|
// src/components/ChatInput/ChatInput.tsx
|
|
49
46
|
import { useState } from "react";
|
|
50
|
-
|
|
51
|
-
// src/components/ChatInput/ChatInput.module.css
|
|
52
|
-
var ChatInput_default = {};
|
|
53
|
-
|
|
54
|
-
// src/components/ChatInput/ChatInput.tsx
|
|
47
|
+
import clsx2 from "clsx";
|
|
55
48
|
import { Send } from "lucide-react";
|
|
56
49
|
import { jsx as jsx3, jsxs as jsxs2 } from "react/jsx-runtime";
|
|
57
50
|
var ChatInput = ({ onSendMessage, isLoading }) => {
|
|
@@ -68,11 +61,15 @@ var ChatInput = ({ onSendMessage, isLoading }) => {
|
|
|
68
61
|
handleSend();
|
|
69
62
|
}
|
|
70
63
|
};
|
|
71
|
-
return /* @__PURE__ */ jsxs2("div", { className:
|
|
64
|
+
return /* @__PURE__ */ jsxs2("div", { className: "flex gap-2 p-3 border-t border-[var(--ai-border)] bg-[var(--ai-bg)]", children: [
|
|
72
65
|
/* @__PURE__ */ jsx3(
|
|
73
66
|
"input",
|
|
74
67
|
{
|
|
75
|
-
className:
|
|
68
|
+
className: clsx2(
|
|
69
|
+
"flex-1 px-3 py-2 border border-[var(--ai-border)] rounded-lg outline-none",
|
|
70
|
+
"font-inherit text-[var(--ai-text)] placeholder:text-[var(--ai-text-secondary)]",
|
|
71
|
+
"focus:border-[var(--ai-primary)] disabled:opacity-50"
|
|
72
|
+
),
|
|
76
73
|
value: inputValue,
|
|
77
74
|
onChange: (e) => setInputValue(e.target.value),
|
|
78
75
|
onKeyDown: handleKeyDown,
|
|
@@ -83,7 +80,12 @@ var ChatInput = ({ onSendMessage, isLoading }) => {
|
|
|
83
80
|
/* @__PURE__ */ jsx3(
|
|
84
81
|
"button",
|
|
85
82
|
{
|
|
86
|
-
className:
|
|
83
|
+
className: clsx2(
|
|
84
|
+
"px-3 py-2 rounded-lg flex items-center justify-center transition-opacity",
|
|
85
|
+
"bg-[var(--ai-primary)] text-[var(--ai-primary-fg)]",
|
|
86
|
+
"hover:opacity-90",
|
|
87
|
+
(isLoading || !inputValue.trim()) && "opacity-50 cursor-not-allowed"
|
|
88
|
+
),
|
|
87
89
|
onClick: handleSend,
|
|
88
90
|
disabled: isLoading || !inputValue.trim(),
|
|
89
91
|
children: /* @__PURE__ */ jsx3(Send, { size: 18 })
|
|
@@ -130,10 +132,14 @@ var ChatWindow = ({
|
|
|
130
132
|
setIsLoading(false);
|
|
131
133
|
}
|
|
132
134
|
};
|
|
133
|
-
return /* @__PURE__ */ jsxs3("div", { className: clsx3(
|
|
134
|
-
|
|
135
|
+
return /* @__PURE__ */ jsxs3("div", { className: clsx3(
|
|
136
|
+
"flex flex-col h-[500px] w-full max-w-md rounded-xl border border-[var(--ai-border)]",
|
|
137
|
+
"bg-[var(--ai-bg)] overflow-hidden shadow-lg relative",
|
|
138
|
+
"font-inherit text-base leading-6 box-border"
|
|
139
|
+
), children: [
|
|
140
|
+
/* @__PURE__ */ jsxs3("div", { className: "flex items-center gap-2 px-4 py-4 border-b border-[var(--ai-border)] bg-gray-50", children: [
|
|
135
141
|
/* @__PURE__ */ jsx4(Bot, { size: 20 }),
|
|
136
|
-
/* @__PURE__ */ jsx4("span", {
|
|
142
|
+
/* @__PURE__ */ jsx4("span", { className: "font-semibold", children: title })
|
|
137
143
|
] }),
|
|
138
144
|
/* @__PURE__ */ jsx4(MessageList, { messages, isLoading }),
|
|
139
145
|
/* @__PURE__ */ jsx4(ChatInput, { onSendMessage: handleSendMessage, isLoading })
|
package/dist/react.mjs.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/components/ChatWindow/ChatWindow.tsx","../src/components/ChatWindow/ChatWindow.module.css","../src/components/MessageList/MessageList.tsx","../src/components/MessageList/MessageList.module.css","../src/components/MessageBubble/MessageBubble.tsx","../src/components/MessageBubble/MessageBubble.module.css","../src/components/ChatInput/ChatInput.tsx","../src/components/ChatInput/ChatInput.module.css"],"sourcesContent":["// src/components/ChatWindow/ChatWindow.tsx\r\nimport React, { useState, useEffect } from 'react';\r\nimport clsx from 'clsx';\r\nimport styles from './ChatWindow.module.css';\r\nimport { MessageList } from '../MessageList/MessageList';\r\nimport { ChatInput } from '../ChatInput/ChatInput';\r\nimport { Message } from '../../types';\r\nimport { Bot } from 'lucide-react';\r\n\r\nexport interface ChatWindowProps {\r\n apiEndpoint: string;\r\n title?: string;\r\n welcomeMessage?: string;\r\n}\r\n\r\nexport const ChatWindow: React.FC<ChatWindowProps> = ({\r\n apiEndpoint,\r\n title = \"AI Assistant\",\r\n welcomeMessage = \"سلام! چطور میتوانم کمکتان کنم؟\"\r\n}) => {\r\n const [messages, setMessages] = useState<Message[]>([]);\r\n const [isLoading, setIsLoading] = useState(false);\r\n\r\n useEffect(() => {\r\n if (welcomeMessage && messages.length === 0) {\r\n setMessages([{ role: 'assistant', content: welcomeMessage }]);\r\n }\r\n }, [welcomeMessage]);\r\n\r\n const handleSendMessage = async (userMessage: string) => {\r\n const newUserMsg: Message = { role: 'user', content: userMessage };\r\n const currentMessages = [...messages, newUserMsg];\r\n setMessages(currentMessages);\r\n setIsLoading(true);\r\n\r\n try {\r\n const response = await fetch(apiEndpoint, {\r\n method: 'POST',\r\n headers: { 'Content-Type': 'application/json' },\r\n body: JSON.stringify({ messages: currentMessages }),\r\n });\r\n\r\n if (!response.ok) throw new Error(\"Network response was not ok\");\r\n \r\n const data = await response.json();\r\n const botMsg: Message = { role: 'assistant', content: data.content };\r\n setMessages(prev => [...prev, botMsg]);\r\n\r\n } catch (error) {\r\n console.error(\"Chat Error:\", error);\r\n const errorMsg: Message = { role: 'assistant', content: \"خطایی رخ داده است.\" };\r\n setMessages(prev => [...prev, errorMsg]);\r\n } finally {\r\n setIsLoading(false);\r\n }\r\n };\r\n\r\n return (\r\n <div className={clsx(styles.container, styles.chatWindow)}>\r\n <div style={{ padding: '16px', borderBottom: '1px solid var(--ai-border)', display: 'flex', alignItems: 'center', gap: '8px', background: '#f9fafb' }}>\r\n <Bot size={20} />\r\n <span style={{ fontWeight: 600 }}>{title}</span>\r\n </div>\r\n <MessageList messages={messages} isLoading={isLoading} />\r\n <ChatInput onSendMessage={handleSendMessage} isLoading={isLoading} />\r\n </div>\r\n );\r\n};","/* \r\n این فایل استایلهای اصلی و کانتینر چت را تعریف میکند.\r\n متغیرهای CSS به کاربر اجازه میدهند تا به راحتی ظاهر ربات را شخصیسازی کند.\r\n*/\r\n\r\n.container {\r\n /* ======== متغیرهای قابل شخصیسازی ======== */\r\n \r\n /* رنگ اصلی (دکمه ارسال، حباب کاربر) */\r\n --ai-primary: #2563eb;\r\n /* رنگ متن روی المانهای اصلی */\r\n --ai-primary-fg: #ffffff;\r\n\r\n /* رنگهای پسزمینه */\r\n --ai-bg: #ffffff;\r\n --ai-bot-bg: #f3f4f6;\r\n --ai-user-bg: var(--ai-primary);\r\n\r\n /* رنگهای متن */\r\n --ai-text: #1f2937;\r\n --ai-text-secondary: #6b7280;\r\n --ai-user-text: var(--ai-primary-fg);\r\n\r\n /* رنگ حاشیه و جداکنندهها */\r\n --ai-border: #e5e7eb;\r\n\r\n /* ======================================== */\r\n\r\n /* ارثبری فونت از سایت میزبان برای هماهنگی بیشتر */\r\n font-family: inherit; \r\n font-size: 16px;\r\n line-height: 1.5;\r\n box-sizing: border-box;\r\n}\r\n\r\n/* کانتینر اصلی پنجره چت */\r\n.chatWindow {\r\n display: flex;\r\n flex-direction: column;\r\n height: 500px; /* ارتفاع پیشفرض، کاربر میتواند تغییر دهد */\r\n width: 100%;\r\n max-width: 400px;\r\n background-color: var(--ai-bg);\r\n border: 1px solid var(--ai-border);\r\n border-radius: 12px;\r\n overflow: hidden; /* برای اینکه گوشههای گرد درست نمایش داده شوند */\r\n box-shadow: 0 4px 6px -1px rgba(0, 0, 0, 0.1), 0 2px 4px -2px rgba(0, 0, 0, 0.1);\r\n position: relative;\r\n}","// src/components/MessageList/MessageList.tsx\r\nimport React, { useRef, useEffect } from 'react';\r\nimport clsx from 'clsx';\r\nimport styles from './MessageList.module.css';\r\nimport { MessageBubble } from '../MessageBubble/MessageBubble';\r\nimport { Message } from '../../types';\r\n\r\ninterface MessageListProps {\r\n messages: Message[];\r\n isLoading: boolean;\r\n}\r\n\r\nexport const MessageList: React.FC<MessageListProps> = ({ messages, isLoading }) => {\r\n const messagesEndRef = useRef<HTMLDivElement>(null);\r\n\r\n useEffect(() => {\r\n messagesEndRef.current?.scrollIntoView({ behavior: 'smooth' });\r\n }, [messages, isLoading]);\r\n\r\n return (\r\n <div className={styles.messageList}>\r\n {messages.map((msg, index) => (\r\n <MessageBubble key={index} message={msg} />\r\n ))}\r\n {isLoading && (\r\n <div className={clsx(styles.messageRow, styles.assistant)}>\r\n <div className={clsx(styles.bubble, styles.assistant, styles.loading)}>\r\n <div className={styles.dot}></div>\r\n <div className={styles.dot}></div>\r\n <div className={styles.dot}></div>\r\n </div>\r\n </div>\r\n )}\r\n <div ref={messagesEndRef} />\r\n </div>\r\n );\r\n};",".messageList {\r\nflex: 1;\r\noverflow-y: auto;\r\npadding: 16px;\r\ndisplay: flex;\r\nflex-direction: column;\r\ngap: 12px;\r\nscroll-behavior: smooth;\r\n}\r\n/* این استایلها برای انیمیشن لودینگ هستند */\r\n.loading {\r\ndisplay: flex;\r\ngap: 4px;\r\npadding: 4px;\r\n}\r\n.dot {\r\nwidth: 6px;\r\nheight: 6px;\r\nbackground-color: #9ca3af;\r\nborder-radius: 50%;\r\nanimation: bounce 1.4s infinite ease-in-out both;\r\n}\r\n.dot:nth-child(1) { animation-delay: -0.32s; }\r\n.dot:nth-child(2) { animation-delay: -0.16s; }\r\n@keyframes bounce {\r\n0%, 80%, 100% { transform: scale(0); }\r\n40% { transform: scale(1); }\r\n}","// src/components/MessageBubble/MessageBubble.tsx\r\nimport React from 'react';\r\nimport clsx from 'clsx';\r\nimport styles from './MessageBubble.module.css'; // 👈 مسیر جدید\r\nimport { Message } from '../../types';\r\n\r\ninterface MessageBubbleProps {\r\n message: Message;\r\n}\r\n\r\nexport const MessageBubble: React.FC<MessageBubbleProps> = ({ message }) => {\r\n const isUser = message.role === 'user';\r\n return (\r\n <div className={clsx(styles.messageRow, isUser ? styles.user : styles.assistant)}>\r\n <div className={clsx(styles.bubble, isUser ? styles.user : styles.assistant)}>\r\n {message.content}\r\n </div>\r\n </div>\r\n );\r\n};",".messageRow {\r\n display: flex;\r\n width: 100%;\r\n}\r\n.messageRow.user {\r\n justify-content: flex-end;\r\n}\r\n.messageRow.assistant {\r\n justify-content: flex-start;\r\n}\r\n.bubble {\r\n max-width: 80%;\r\n padding: 8px 12px;\r\n border-radius: 12px;\r\n font-size: 0.95em;\r\n word-wrap: break-word;\r\n}\r\n.bubble.user {\r\n background-color: var(--ai-user-bg, #2563eb);\r\n color: var(--ai-user-text, #ffffff);\r\n border-bottom-right-radius: 2px;\r\n}\r\n.bubble.assistant {\r\n background-color: var(--ai-bot-bg, #f3f4f6);\r\n color: var(--ai-text, #1f2937);\r\n border-bottom-left-radius: 2px;\r\n}","// src/components/ChatInput/ChatInput.tsx\r\nimport React, { useState } from 'react';\r\nimport styles from './ChatInput.module.css';\r\nimport { Send } from 'lucide-react';\r\n\r\ninterface ChatInputProps {\r\n onSendMessage: (message: string) => void;\r\n isLoading: boolean;\r\n}\r\n\r\nexport const ChatInput: React.FC<ChatInputProps> = ({ onSendMessage, isLoading }) => {\r\n const [inputValue, setInputValue] = useState('');\r\n\r\n const handleSend = () => {\r\n if (inputValue.trim()) {\r\n onSendMessage(inputValue);\r\n setInputValue('');\r\n }\r\n };\r\n\r\n const handleKeyDown = (e: React.KeyboardEvent) => {\r\n if (e.key === 'Enter' && !e.shiftKey) {\r\n e.preventDefault();\r\n handleSend();\r\n }\r\n };\r\n\r\n return (\r\n <div className={styles.inputArea}>\r\n <input\r\n className={styles.input}\r\n value={inputValue}\r\n onChange={(e) => setInputValue(e.target.value)}\r\n onKeyDown={handleKeyDown}\r\n placeholder=\"پیام خود را بنویسید...\"\r\n disabled={isLoading}\r\n />\r\n <button\r\n className={styles.sendButton}\r\n onClick={handleSend}\r\n disabled={isLoading || !inputValue.trim()}\r\n >\r\n <Send size={18} />\r\n </button>\r\n </div>\r\n );\r\n};","/* src/components/ChatInput/ChatInput.module.css */\r\n.inputArea {\r\n padding: 12px;\r\n border-top: 1px solid var(--ai-border, #e5e7eb);\r\n display: flex;\r\n gap: 8px;\r\n background-color: var(--ai-bg, #ffffff);\r\n}\r\n.input {\r\n flex: 1;\r\n padding: 8px 12px;\r\n border: 1px solid var(--ai-border, #e5e7eb);\r\n border-radius: 8px;\r\n outline: none;\r\n font-family: inherit;\r\n}\r\n.input:focus {\r\n border-color: var(--ai-primary, #2563eb);\r\n}\r\n.sendButton {\r\n background-color: var(--ai-primary, #2563eb);\r\n color: var(--ai-primary-fg, #ffffff);\r\n border: none;\r\n border-radius: 8px;\r\n padding: 8px 12px;\r\n cursor: pointer;\r\n display: flex;\r\n align-items: center;\r\n justify-content: center;\r\n transition: opacity 0.2s;\r\n}\r\n.sendButton:disabled {\r\n opacity: 0.5;\r\n cursor: not-allowed;\r\n}"],"mappings":"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","names":["useState","useEffect","clsx","clsx","jsx","clsx","jsx","jsxs","jsx","jsxs","useState","useEffect","clsx"]}
|
|
1
|
+
{"version":3,"sources":["../src/components/ChatWindow/ChatWindow.tsx","../src/components/MessageList/MessageList.tsx","../src/components/MessageBubble/MessageBubble.tsx","../src/components/ChatInput/ChatInput.tsx"],"sourcesContent":["// src/components/ChatWindow/ChatWindow.tsx\r\n\"use client\";\r\n\r\nimport React, { useState, useEffect } from 'react';\r\nimport clsx from 'clsx';\r\nimport { MessageList } from '../MessageList/MessageList';\r\nimport { ChatInput } from '../ChatInput/ChatInput';\r\nimport { Message } from '../../types';\r\nimport { Bot } from 'lucide-react';\r\n\r\nexport interface ChatWindowProps {\r\n apiEndpoint: string;\r\n title?: string;\r\n welcomeMessage?: string;\r\n}\r\n\r\nexport const ChatWindow: React.FC<ChatWindowProps> = ({\r\n apiEndpoint,\r\n title = \"AI Assistant\",\r\n welcomeMessage = \"سلام! چطور میتوانم کمکتان کنم؟\"\r\n}) => {\r\n const [messages, setMessages] = useState<Message[]>([]);\r\n const [isLoading, setIsLoading] = useState(false);\r\n\r\n useEffect(() => {\r\n if (welcomeMessage && messages.length === 0) {\r\n setMessages([{ role: 'assistant', content: welcomeMessage }]);\r\n }\r\n }, [welcomeMessage]);\r\n\r\n const handleSendMessage = async (userMessage: string) => {\r\n const newUserMsg: Message = { role: 'user', content: userMessage };\r\n const currentMessages = [...messages, newUserMsg];\r\n setMessages(currentMessages);\r\n setIsLoading(true);\r\n\r\n try {\r\n const response = await fetch(apiEndpoint, {\r\n method: 'POST',\r\n headers: { 'Content-Type': 'application/json' },\r\n body: JSON.stringify({ messages: currentMessages }),\r\n });\r\n\r\n if (!response.ok) throw new Error(\"Network response was not ok\");\r\n \r\n const data = await response.json();\r\n const botMsg: Message = { role: 'assistant', content: data.content };\r\n setMessages(prev => [...prev, botMsg]);\r\n\r\n } catch (error) {\r\n console.error(\"Chat Error:\", error);\r\n const errorMsg: Message = { role: 'assistant', content: \"خطایی رخ داده است.\" };\r\n setMessages(prev => [...prev, errorMsg]);\r\n } finally {\r\n setIsLoading(false);\r\n }\r\n };\r\n\r\n return (\r\n <div className={clsx(\r\n \"flex flex-col h-[500px] w-full max-w-md rounded-xl border border-[var(--ai-border)]\",\r\n \"bg-[var(--ai-bg)] overflow-hidden shadow-lg relative\",\r\n \"font-inherit text-base leading-6 box-border\"\r\n )}>\r\n <div className=\"flex items-center gap-2 px-4 py-4 border-b border-[var(--ai-border)] bg-gray-50\">\r\n <Bot size={20} />\r\n <span className=\"font-semibold\">{title}</span>\r\n </div>\r\n\r\n <MessageList messages={messages} isLoading={isLoading} />\r\n <ChatInput onSendMessage={handleSendMessage} isLoading={isLoading} />\r\n </div>\r\n );\r\n};","// src/components/MessageList/MessageList.tsx\r\n\"use client\";\r\n\r\nimport React, { useRef, useEffect } from 'react';\r\nimport clsx from 'clsx';\r\nimport { MessageBubble } from '../MessageBubble/MessageBubble';\r\nimport { Message } from '../../types';\r\n\r\ninterface MessageListProps {\r\n messages: Message[];\r\n isLoading: boolean;\r\n}\r\n\r\nexport const MessageList: React.FC<MessageListProps> = ({ messages, isLoading }) => {\r\n const messagesEndRef = useRef<HTMLDivElement>(null);\r\n\r\n useEffect(() => {\r\n messagesEndRef.current?.scrollIntoView({ behavior: 'smooth' });\r\n }, [messages, isLoading]);\r\n\r\n return (\r\n <div className=\"flex-1 overflow-y-auto p-4 flex flex-col gap-3 scroll-smooth\">\r\n {messages.map((msg, index) => (\r\n <MessageBubble key={index} message={msg} />\r\n ))}\r\n\r\n {isLoading && (\r\n <div className=\"flex justify-start\">\r\n <div className=\"max-w-[80%] px-3 py-2 rounded-xl bg-[var(--ai-bot-bg)] text-[var(--ai-text)] rounded-bl-sm flex gap-1 items-center\">\r\n <div className=\"w-1.5 h-1.5 bg-gray-400 rounded-full animate-bounce\" style={{ animationDelay: '-0.32s' }}></div>\r\n <div className=\"w-1.5 h-1.5 bg-gray-400 rounded-full animate-bounce\" style={{ animationDelay: '-0.16s' }}></div>\r\n <div className=\"w-1.5 h-1.5 bg-gray-400 rounded-full animate-bounce\"></div>\r\n </div>\r\n </div>\r\n )}\r\n\r\n <div ref={messagesEndRef} />\r\n </div>\r\n );\r\n};","// src/components/MessageBubble/MessageBubble.tsx\r\n\"use client\";\r\n\r\nimport React from 'react';\r\nimport clsx from 'clsx';\r\nimport { Message } from '../../types';\r\n\r\ninterface MessageBubbleProps {\r\n message: Message;\r\n}\r\n\r\nexport const MessageBubble: React.FC<MessageBubbleProps> = ({ message }) => {\r\n const isUser = message.role === 'user';\r\n\r\n return (\r\n <div className={clsx(\"flex w-full\", isUser ? \"justify-end\" : \"justify-start\")}>\r\n <div\r\n className={clsx(\r\n \"max-w-[80%] px-3 py-2 rounded-xl text-sm break-words\",\r\n isUser\r\n ? \"bg-[var(--ai-user-bg)] text-[var(--ai-user-text)] rounded-br-sm\"\r\n : \"bg-[var(--ai-bot-bg)] text-[var(--ai-text)] rounded-bl-sm\"\r\n )}\r\n >\r\n {message.content}\r\n </div>\r\n </div>\r\n );\r\n};","// src/components/ChatInput/ChatInput.tsx\r\n\"use client\";\r\n\r\nimport React, { useState } from 'react';\r\nimport clsx from 'clsx';\r\nimport { Send } from 'lucide-react';\r\n\r\ninterface ChatInputProps {\r\n onSendMessage: (message: string) => void;\r\n isLoading: boolean;\r\n}\r\n\r\nexport const ChatInput: React.FC<ChatInputProps> = ({ onSendMessage, isLoading }) => {\r\n const [inputValue, setInputValue] = useState('');\r\n\r\n const handleSend = () => {\r\n if (inputValue.trim()) {\r\n onSendMessage(inputValue);\r\n setInputValue('');\r\n }\r\n };\r\n\r\n const handleKeyDown = (e: React.KeyboardEvent) => {\r\n if (e.key === 'Enter' && !e.shiftKey) {\r\n e.preventDefault();\r\n handleSend();\r\n }\r\n };\r\n\r\n return (\r\n <div className=\"flex gap-2 p-3 border-t border-[var(--ai-border)] bg-[var(--ai-bg)]\">\r\n <input\r\n className={clsx(\r\n \"flex-1 px-3 py-2 border border-[var(--ai-border)] rounded-lg outline-none\",\r\n \"font-inherit text-[var(--ai-text)] placeholder:text-[var(--ai-text-secondary)]\",\r\n \"focus:border-[var(--ai-primary)] disabled:opacity-50\"\r\n )}\r\n value={inputValue}\r\n onChange={(e) => setInputValue(e.target.value)}\r\n onKeyDown={handleKeyDown}\r\n placeholder=\"پیام خود را بنویسید...\"\r\n disabled={isLoading}\r\n />\r\n <button\r\n className={clsx(\r\n \"px-3 py-2 rounded-lg flex items-center justify-center transition-opacity\",\r\n \"bg-[var(--ai-primary)] text-[var(--ai-primary-fg)]\",\r\n \"hover:opacity-90\",\r\n (isLoading || !inputValue.trim()) && \"opacity-50 cursor-not-allowed\"\r\n )}\r\n onClick={handleSend}\r\n disabled={isLoading || !inputValue.trim()}\r\n >\r\n <Send size={18} />\r\n </button>\r\n </div>\r\n );\r\n};"],"mappings":"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","names":["useState","useEffect","clsx","jsx","clsx","jsx","jsxs","jsx","jsxs","useState","useEffect","clsx"]}
|
package/package.json
CHANGED
|
@@ -1,10 +1,14 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "mehdi-akbari-ai-assistant-free",
|
|
3
|
-
"version": "0.0
|
|
3
|
+
"version": "0.1.0",
|
|
4
4
|
"description": "Professional AI Chatbot Library",
|
|
5
5
|
"main": "./dist/index.js",
|
|
6
6
|
"module": "./dist/index.mjs",
|
|
7
7
|
"types": "./dist/index.d.ts",
|
|
8
|
+
"style": "dist/react.css",
|
|
9
|
+
"files": [
|
|
10
|
+
"dist"
|
|
11
|
+
],
|
|
8
12
|
"exports": {
|
|
9
13
|
".": {
|
|
10
14
|
"types": "./dist/index.d.ts",
|
|
@@ -13,14 +17,13 @@
|
|
|
13
17
|
},
|
|
14
18
|
"./react": {
|
|
15
19
|
"types": "./dist/react.d.ts",
|
|
20
|
+
"style": "./dist/react.css",
|
|
16
21
|
"import": "./dist/react.mjs",
|
|
17
22
|
"require": "./dist/react.js"
|
|
18
23
|
},
|
|
19
|
-
"./dist/react.css": "./dist/react.css"
|
|
24
|
+
"./dist/react.css": "./dist/react.css",
|
|
25
|
+
"./package.json": "./package.json"
|
|
20
26
|
},
|
|
21
|
-
"files": [
|
|
22
|
-
"dist"
|
|
23
|
-
],
|
|
24
27
|
"scripts": {
|
|
25
28
|
"build": "tsup",
|
|
26
29
|
"dev": "tsup --watch",
|
|
@@ -39,9 +42,23 @@
|
|
|
39
42
|
"devDependencies": {
|
|
40
43
|
"@types/react": "^18.3.27",
|
|
41
44
|
"@types/react-dom": "^18.3.7",
|
|
45
|
+
"autoprefixer": "^10.4.23",
|
|
46
|
+
"postcss": "^8.5.6",
|
|
42
47
|
"react": "^18.3.1",
|
|
43
48
|
"react-dom": "^18.3.1",
|
|
49
|
+
"tailwindcss": "^4.1.18",
|
|
44
50
|
"tsup": "^8.5.1",
|
|
45
51
|
"typescript": "^5.9.3"
|
|
46
|
-
}
|
|
52
|
+
},
|
|
53
|
+
"keywords": [
|
|
54
|
+
"react",
|
|
55
|
+
"chatbot",
|
|
56
|
+
"ai",
|
|
57
|
+
"groq",
|
|
58
|
+
"langchain",
|
|
59
|
+
"chat-window",
|
|
60
|
+
"ui-component"
|
|
61
|
+
],
|
|
62
|
+
"author": "Mehdi Akbari",
|
|
63
|
+
"license": "MIT"
|
|
47
64
|
}
|
package/dist/react.css
DELETED
|
@@ -1,132 +0,0 @@
|
|
|
1
|
-
/* src/components/ChatWindow/ChatWindow.module.css */
|
|
2
|
-
.container {
|
|
3
|
-
--ai-primary: #2563eb;
|
|
4
|
-
--ai-primary-fg: #ffffff;
|
|
5
|
-
--ai-bg: #ffffff;
|
|
6
|
-
--ai-bot-bg: #f3f4f6;
|
|
7
|
-
--ai-user-bg: var(--ai-primary);
|
|
8
|
-
--ai-text: #1f2937;
|
|
9
|
-
--ai-text-secondary: #6b7280;
|
|
10
|
-
--ai-user-text: var(--ai-primary-fg);
|
|
11
|
-
--ai-border: #e5e7eb;
|
|
12
|
-
font-family: inherit;
|
|
13
|
-
font-size: 16px;
|
|
14
|
-
line-height: 1.5;
|
|
15
|
-
box-sizing: border-box;
|
|
16
|
-
}
|
|
17
|
-
.chatWindow {
|
|
18
|
-
display: flex;
|
|
19
|
-
flex-direction: column;
|
|
20
|
-
height: 500px;
|
|
21
|
-
width: 100%;
|
|
22
|
-
max-width: 400px;
|
|
23
|
-
background-color: var(--ai-bg);
|
|
24
|
-
border: 1px solid var(--ai-border);
|
|
25
|
-
border-radius: 12px;
|
|
26
|
-
overflow: hidden;
|
|
27
|
-
box-shadow: 0 4px 6px -1px rgba(0, 0, 0, 0.1), 0 2px 4px -2px rgba(0, 0, 0, 0.1);
|
|
28
|
-
position: relative;
|
|
29
|
-
}
|
|
30
|
-
|
|
31
|
-
/* src/components/MessageList/MessageList.module.css */
|
|
32
|
-
.messageList {
|
|
33
|
-
flex: 1;
|
|
34
|
-
overflow-y: auto;
|
|
35
|
-
padding: 16px;
|
|
36
|
-
display: flex;
|
|
37
|
-
flex-direction: column;
|
|
38
|
-
gap: 12px;
|
|
39
|
-
scroll-behavior: smooth;
|
|
40
|
-
}
|
|
41
|
-
.loading {
|
|
42
|
-
display: flex;
|
|
43
|
-
gap: 4px;
|
|
44
|
-
padding: 4px;
|
|
45
|
-
}
|
|
46
|
-
.dot {
|
|
47
|
-
width: 6px;
|
|
48
|
-
height: 6px;
|
|
49
|
-
background-color: #9ca3af;
|
|
50
|
-
border-radius: 50%;
|
|
51
|
-
animation: bounce 1.4s infinite ease-in-out both;
|
|
52
|
-
}
|
|
53
|
-
.dot:nth-child(1) {
|
|
54
|
-
animation-delay: -0.32s;
|
|
55
|
-
}
|
|
56
|
-
.dot:nth-child(2) {
|
|
57
|
-
animation-delay: -0.16s;
|
|
58
|
-
}
|
|
59
|
-
@keyframes bounce {
|
|
60
|
-
0%, 80%, 100% {
|
|
61
|
-
transform: scale(0);
|
|
62
|
-
}
|
|
63
|
-
40% {
|
|
64
|
-
transform: scale(1);
|
|
65
|
-
}
|
|
66
|
-
}
|
|
67
|
-
|
|
68
|
-
/* src/components/MessageBubble/MessageBubble.module.css */
|
|
69
|
-
.messageRow {
|
|
70
|
-
display: flex;
|
|
71
|
-
width: 100%;
|
|
72
|
-
}
|
|
73
|
-
.messageRow.user {
|
|
74
|
-
justify-content: flex-end;
|
|
75
|
-
}
|
|
76
|
-
.messageRow.assistant {
|
|
77
|
-
justify-content: flex-start;
|
|
78
|
-
}
|
|
79
|
-
.bubble {
|
|
80
|
-
max-width: 80%;
|
|
81
|
-
padding: 8px 12px;
|
|
82
|
-
border-radius: 12px;
|
|
83
|
-
font-size: 0.95em;
|
|
84
|
-
word-wrap: break-word;
|
|
85
|
-
}
|
|
86
|
-
.bubble.user {
|
|
87
|
-
background-color: var(--ai-user-bg, #2563eb);
|
|
88
|
-
color: var(--ai-user-text, #ffffff);
|
|
89
|
-
border-bottom-right-radius: 2px;
|
|
90
|
-
}
|
|
91
|
-
.bubble.assistant {
|
|
92
|
-
background-color: var(--ai-bot-bg, #f3f4f6);
|
|
93
|
-
color: var(--ai-text, #1f2937);
|
|
94
|
-
border-bottom-left-radius: 2px;
|
|
95
|
-
}
|
|
96
|
-
|
|
97
|
-
/* src/components/ChatInput/ChatInput.module.css */
|
|
98
|
-
.inputArea {
|
|
99
|
-
padding: 12px;
|
|
100
|
-
border-top: 1px solid var(--ai-border, #e5e7eb);
|
|
101
|
-
display: flex;
|
|
102
|
-
gap: 8px;
|
|
103
|
-
background-color: var(--ai-bg, #ffffff);
|
|
104
|
-
}
|
|
105
|
-
.input {
|
|
106
|
-
flex: 1;
|
|
107
|
-
padding: 8px 12px;
|
|
108
|
-
border: 1px solid var(--ai-border, #e5e7eb);
|
|
109
|
-
border-radius: 8px;
|
|
110
|
-
outline: none;
|
|
111
|
-
font-family: inherit;
|
|
112
|
-
}
|
|
113
|
-
.input:focus {
|
|
114
|
-
border-color: var(--ai-primary, #2563eb);
|
|
115
|
-
}
|
|
116
|
-
.sendButton {
|
|
117
|
-
background-color: var(--ai-primary, #2563eb);
|
|
118
|
-
color: var(--ai-primary-fg, #ffffff);
|
|
119
|
-
border: none;
|
|
120
|
-
border-radius: 8px;
|
|
121
|
-
padding: 8px 12px;
|
|
122
|
-
cursor: pointer;
|
|
123
|
-
display: flex;
|
|
124
|
-
align-items: center;
|
|
125
|
-
justify-content: center;
|
|
126
|
-
transition: opacity 0.2s;
|
|
127
|
-
}
|
|
128
|
-
.sendButton:disabled {
|
|
129
|
-
opacity: 0.5;
|
|
130
|
-
cursor: not-allowed;
|
|
131
|
-
}
|
|
132
|
-
/*# sourceMappingURL=react.css.map */
|
package/dist/react.css.map
DELETED
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/components/ChatWindow/ChatWindow.module.css","../src/components/MessageList/MessageList.module.css","../src/components/MessageBubble/MessageBubble.module.css","../src/components/ChatInput/ChatInput.module.css"],"sourcesContent":["/* \r\n این فایل استایلهای اصلی و کانتینر چت را تعریف میکند.\r\n متغیرهای CSS به کاربر اجازه میدهند تا به راحتی ظاهر ربات را شخصیسازی کند.\r\n*/\r\n\r\n.container {\r\n /* ======== متغیرهای قابل شخصیسازی ======== */\r\n \r\n /* رنگ اصلی (دکمه ارسال، حباب کاربر) */\r\n --ai-primary: #2563eb;\r\n /* رنگ متن روی المانهای اصلی */\r\n --ai-primary-fg: #ffffff;\r\n\r\n /* رنگهای پسزمینه */\r\n --ai-bg: #ffffff;\r\n --ai-bot-bg: #f3f4f6;\r\n --ai-user-bg: var(--ai-primary);\r\n\r\n /* رنگهای متن */\r\n --ai-text: #1f2937;\r\n --ai-text-secondary: #6b7280;\r\n --ai-user-text: var(--ai-primary-fg);\r\n\r\n /* رنگ حاشیه و جداکنندهها */\r\n --ai-border: #e5e7eb;\r\n\r\n /* ======================================== */\r\n\r\n /* ارثبری فونت از سایت میزبان برای هماهنگی بیشتر */\r\n font-family: inherit; \r\n font-size: 16px;\r\n line-height: 1.5;\r\n box-sizing: border-box;\r\n}\r\n\r\n/* کانتینر اصلی پنجره چت */\r\n.chatWindow {\r\n display: flex;\r\n flex-direction: column;\r\n height: 500px; /* ارتفاع پیشفرض، کاربر میتواند تغییر دهد */\r\n width: 100%;\r\n max-width: 400px;\r\n background-color: var(--ai-bg);\r\n border: 1px solid var(--ai-border);\r\n border-radius: 12px;\r\n overflow: hidden; /* برای اینکه گوشههای گرد درست نمایش داده شوند */\r\n box-shadow: 0 4px 6px -1px rgba(0, 0, 0, 0.1), 0 2px 4px -2px rgba(0, 0, 0, 0.1);\r\n position: relative;\r\n}",".messageList {\r\nflex: 1;\r\noverflow-y: auto;\r\npadding: 16px;\r\ndisplay: flex;\r\nflex-direction: column;\r\ngap: 12px;\r\nscroll-behavior: smooth;\r\n}\r\n/* این استایلها برای انیمیشن لودینگ هستند */\r\n.loading {\r\ndisplay: flex;\r\ngap: 4px;\r\npadding: 4px;\r\n}\r\n.dot {\r\nwidth: 6px;\r\nheight: 6px;\r\nbackground-color: #9ca3af;\r\nborder-radius: 50%;\r\nanimation: bounce 1.4s infinite ease-in-out both;\r\n}\r\n.dot:nth-child(1) { animation-delay: -0.32s; }\r\n.dot:nth-child(2) { animation-delay: -0.16s; }\r\n@keyframes bounce {\r\n0%, 80%, 100% { transform: scale(0); }\r\n40% { transform: scale(1); }\r\n}",".messageRow {\r\n display: flex;\r\n width: 100%;\r\n}\r\n.messageRow.user {\r\n justify-content: flex-end;\r\n}\r\n.messageRow.assistant {\r\n justify-content: flex-start;\r\n}\r\n.bubble {\r\n max-width: 80%;\r\n padding: 8px 12px;\r\n border-radius: 12px;\r\n font-size: 0.95em;\r\n word-wrap: break-word;\r\n}\r\n.bubble.user {\r\n background-color: var(--ai-user-bg, #2563eb);\r\n color: var(--ai-user-text, #ffffff);\r\n border-bottom-right-radius: 2px;\r\n}\r\n.bubble.assistant {\r\n background-color: var(--ai-bot-bg, #f3f4f6);\r\n color: var(--ai-text, #1f2937);\r\n border-bottom-left-radius: 2px;\r\n}","/* src/components/ChatInput/ChatInput.module.css */\r\n.inputArea {\r\n padding: 12px;\r\n border-top: 1px solid var(--ai-border, #e5e7eb);\r\n display: flex;\r\n gap: 8px;\r\n background-color: var(--ai-bg, #ffffff);\r\n}\r\n.input {\r\n flex: 1;\r\n padding: 8px 12px;\r\n border: 1px solid var(--ai-border, #e5e7eb);\r\n border-radius: 8px;\r\n outline: none;\r\n font-family: inherit;\r\n}\r\n.input:focus {\r\n border-color: var(--ai-primary, #2563eb);\r\n}\r\n.sendButton {\r\n background-color: var(--ai-primary, #2563eb);\r\n color: var(--ai-primary-fg, #ffffff);\r\n border: none;\r\n border-radius: 8px;\r\n padding: 8px 12px;\r\n cursor: pointer;\r\n display: flex;\r\n align-items: center;\r\n justify-content: center;\r\n transition: opacity 0.2s;\r\n}\r\n.sendButton:disabled {\r\n opacity: 0.5;\r\n cursor: not-allowed;\r\n}"],"mappings":";AAKA,CAAC;AAIC,gBAAc;AAEd,mBAAiB;AAGjB,WAAS;AACT,eAAa;AACb,gBAAc,IAAI;AAGlB,aAAW;AACX,uBAAqB;AACrB,kBAAgB,IAAI;AAGpB,eAAa;AAKb,eAAa;AACb,aAAW;AACX,eAAa;AACb,cAAY;AACd;AAGA,CAAC;AACC,WAAS;AACT,kBAAgB;AAChB,UAAQ;AACR,SAAO;AACP,aAAW;AACX,oBAAkB,IAAI;AACtB,UAAQ,IAAI,MAAM,IAAI;AACtB,iBAAe;AACf,YAAU;AACV,cAAY,EAAE,IAAI,IAAI,KAAK,KAAK,CAAC,EAAE,CAAC,EAAE,CAAC,EAAE,IAAI,EAAE,EAAE,IAAI,IAAI,KAAK,KAAK,CAAC,EAAE,CAAC,EAAE,CAAC,EAAE;AAC5E,YAAU;AACZ;;;AChDA,CAAC;AACD,QAAM;AACN,cAAY;AACZ,WAAS;AACT,WAAS;AACT,kBAAgB;AAChB,OAAK;AACL,mBAAiB;AACjB;AAEA,CAAC;AACD,WAAS;AACT,OAAK;AACL,WAAS;AACT;AACA,CAAC;AACD,SAAO;AACP,UAAQ;AACR,oBAAkB;AAClB,iBAAe;AACf,aAAW,OAAO,KAAK,SAAS,YAAY;AAC5C;AACA,CAPC,GAOG;AAAgB,mBAAiB;AAAQ;AAC7C,CARC,GAQG;AAAgB,mBAAiB;AAAQ;AAC7C,WAJW;AAKX;AAAgB,eAAW,MAAM;AAAI;AACrC;AAAM,eAAW,MAAM;AAAI;AAC3B;;;AC3BA,CAAC;AACC,WAAS;AACT,SAAO;AACT;AACA,CAJC,UAIU,CAAC;AACV,mBAAiB;AACnB;AACA,CAPC,UAOU,CAAC;AACV,mBAAiB;AACnB;AACA,CAAC;AACC,aAAW;AACX,WAAS,IAAI;AACb,iBAAe;AACf,aAAW;AACX,aAAW;AACb;AACA,CAPC,MAOM,CAbK;AAcV,oBAAkB,IAAI,YAAY,EAAE;AACpC,SAAO,IAAI,cAAc,EAAE;AAC3B,8BAA4B;AAC9B;AACA,CAZC,MAYM,CAfK;AAgBV,oBAAkB,IAAI,WAAW,EAAE;AACnC,SAAO,IAAI,SAAS,EAAE;AACtB,6BAA2B;AAC7B;;;ACzBA,CAAC;AACC,WAAS;AACT,cAAY,IAAI,MAAM,IAAI,WAAW,EAAE;AACvC,WAAS;AACT,OAAK;AACL,oBAAkB,IAAI,OAAO,EAAE;AACjC;AACA,CAAC;AACC,QAAM;AACN,WAAS,IAAI;AACb,UAAQ,IAAI,MAAM,IAAI,WAAW,EAAE;AACnC,iBAAe;AACf,WAAS;AACT,eAAa;AACf;AACA,CARC,KAQK;AACJ,gBAAc,IAAI,YAAY,EAAE;AAClC;AACA,CAAC;AACC,oBAAkB,IAAI,YAAY,EAAE;AACpC,SAAO,IAAI,eAAe,EAAE;AAC5B,UAAQ;AACR,iBAAe;AACf,WAAS,IAAI;AACb,UAAQ;AACR,WAAS;AACT,eAAa;AACb,mBAAiB;AACjB,cAAY,QAAQ;AACtB;AACA,CAZC,UAYU;AACT,WAAS;AACT,UAAQ;AACV;","names":[]}
|