mehdi-akbari-ai-assistant-free 0.2.0 → 0.6.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 +15 -30
- package/dist/react.js.map +1 -1
- package/dist/react.mjs +15 -30
- package/dist/react.mjs.map +1 -1
- package/dist/styles.css +157 -0
- package/package.json +8 -7
package/dist/react.js
CHANGED
|
@@ -37,7 +37,6 @@ module.exports = __toCommonJS(react_exports);
|
|
|
37
37
|
|
|
38
38
|
// src/components/ChatWindow/ChatWindow.tsx
|
|
39
39
|
var import_react3 = require("react");
|
|
40
|
-
var import_clsx3 = __toESM(require("clsx"));
|
|
41
40
|
|
|
42
41
|
// src/components/MessageList/MessageList.tsx
|
|
43
42
|
var import_react = require("react");
|
|
@@ -47,12 +46,12 @@ var import_clsx = __toESM(require("clsx"));
|
|
|
47
46
|
var import_jsx_runtime = require("react/jsx-runtime");
|
|
48
47
|
var MessageBubble = ({ message }) => {
|
|
49
48
|
const isUser = message.role === "user";
|
|
50
|
-
return /* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", { className: (0, import_clsx.default)("
|
|
49
|
+
return /* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", { className: (0, import_clsx.default)("mra-bubble-wrapper", isUser ? "mra-wrapper-user" : "mra-wrapper-bot"), children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
|
|
51
50
|
"div",
|
|
52
51
|
{
|
|
53
52
|
className: (0, import_clsx.default)(
|
|
54
|
-
"
|
|
55
|
-
isUser ? "
|
|
53
|
+
"mra-bubble",
|
|
54
|
+
isUser ? "mra-bubble-user" : "mra-bubble-bot"
|
|
56
55
|
),
|
|
57
56
|
children: message.content
|
|
58
57
|
}
|
|
@@ -66,12 +65,12 @@ var MessageList = ({ messages, isLoading }) => {
|
|
|
66
65
|
(0, import_react.useEffect)(() => {
|
|
67
66
|
messagesEndRef.current?.scrollIntoView({ behavior: "smooth" });
|
|
68
67
|
}, [messages, isLoading]);
|
|
69
|
-
return /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("div", { className: "
|
|
68
|
+
return /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("div", { className: "mra-message-list", children: [
|
|
70
69
|
messages.map((msg, index) => /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(MessageBubble, { message: msg }, index)),
|
|
71
|
-
isLoading && /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("div", { className: "
|
|
72
|
-
/* @__PURE__ */ (0, import_jsx_runtime2.jsx)("div", { className: "
|
|
73
|
-
/* @__PURE__ */ (0, import_jsx_runtime2.jsx)("div", { className: "
|
|
74
|
-
/* @__PURE__ */ (0, import_jsx_runtime2.jsx)("div", { className: "
|
|
70
|
+
isLoading && /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("div", { className: "mra-loading-wrapper", children: /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("div", { className: "mra-loading-bubble", children: [
|
|
71
|
+
/* @__PURE__ */ (0, import_jsx_runtime2.jsx)("div", { className: "mra-loading-dot", style: { animationDelay: "-0.32s" } }),
|
|
72
|
+
/* @__PURE__ */ (0, import_jsx_runtime2.jsx)("div", { className: "mra-loading-dot", style: { animationDelay: "-0.16s" } }),
|
|
73
|
+
/* @__PURE__ */ (0, import_jsx_runtime2.jsx)("div", { className: "mra-loading-dot" })
|
|
75
74
|
] }) }),
|
|
76
75
|
/* @__PURE__ */ (0, import_jsx_runtime2.jsx)("div", { ref: messagesEndRef })
|
|
77
76
|
] });
|
|
@@ -79,7 +78,6 @@ var MessageList = ({ messages, isLoading }) => {
|
|
|
79
78
|
|
|
80
79
|
// src/components/ChatInput/ChatInput.tsx
|
|
81
80
|
var import_react2 = require("react");
|
|
82
|
-
var import_clsx2 = __toESM(require("clsx"));
|
|
83
81
|
var import_lucide_react = require("lucide-react");
|
|
84
82
|
var import_jsx_runtime3 = require("react/jsx-runtime");
|
|
85
83
|
var ChatInput = ({ onSendMessage, isLoading }) => {
|
|
@@ -96,15 +94,11 @@ var ChatInput = ({ onSendMessage, isLoading }) => {
|
|
|
96
94
|
handleSend();
|
|
97
95
|
}
|
|
98
96
|
};
|
|
99
|
-
return /* @__PURE__ */ (0, import_jsx_runtime3.jsxs)("div", { className: "
|
|
97
|
+
return /* @__PURE__ */ (0, import_jsx_runtime3.jsxs)("div", { className: "mra-input-wrapper", children: [
|
|
100
98
|
/* @__PURE__ */ (0, import_jsx_runtime3.jsx)(
|
|
101
99
|
"input",
|
|
102
100
|
{
|
|
103
|
-
className:
|
|
104
|
-
"flex-1 px-3 py-2 border border-(--ai-border) rounded-lg outline-none",
|
|
105
|
-
"font-inherit text-(--ai-text) placeholder:text-(--ai-text-secondary)",
|
|
106
|
-
"focus:border-(--ai-primary) disabled:opacity-50"
|
|
107
|
-
),
|
|
101
|
+
className: "mra-input-field",
|
|
108
102
|
value: inputValue,
|
|
109
103
|
onChange: (e) => setInputValue(e.target.value),
|
|
110
104
|
onKeyDown: handleKeyDown,
|
|
@@ -115,12 +109,7 @@ var ChatInput = ({ onSendMessage, isLoading }) => {
|
|
|
115
109
|
/* @__PURE__ */ (0, import_jsx_runtime3.jsx)(
|
|
116
110
|
"button",
|
|
117
111
|
{
|
|
118
|
-
className:
|
|
119
|
-
"px-3 py-2 rounded-lg flex items-center justify-center transition-opacity",
|
|
120
|
-
"bg-(--ai-primary) text-(--ai-primary-fg)",
|
|
121
|
-
"hover:opacity-90",
|
|
122
|
-
(isLoading || !inputValue.trim()) && "opacity-50 cursor-not-allowed"
|
|
123
|
-
),
|
|
112
|
+
className: "mra-send-button",
|
|
124
113
|
onClick: handleSend,
|
|
125
114
|
disabled: isLoading || !inputValue.trim(),
|
|
126
115
|
children: /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(import_lucide_react.Send, { size: 18 })
|
|
@@ -143,7 +132,7 @@ var ChatWindow = ({
|
|
|
143
132
|
if (welcomeMessage && messages.length === 0) {
|
|
144
133
|
setMessages([{ role: "assistant", content: welcomeMessage }]);
|
|
145
134
|
}
|
|
146
|
-
}, [welcomeMessage]);
|
|
135
|
+
}, [welcomeMessage, messages.length]);
|
|
147
136
|
const handleSendMessage = async (userMessage) => {
|
|
148
137
|
const newUserMsg = { role: "user", content: userMessage };
|
|
149
138
|
const currentMessages = [...messages, newUserMsg];
|
|
@@ -167,14 +156,10 @@ var ChatWindow = ({
|
|
|
167
156
|
setIsLoading(false);
|
|
168
157
|
}
|
|
169
158
|
};
|
|
170
|
-
return /* @__PURE__ */ (0, import_jsx_runtime4.jsxs)("div", { className:
|
|
171
|
-
|
|
172
|
-
"bg-(--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-(--ai-border) bg-gray-50", children: [
|
|
159
|
+
return /* @__PURE__ */ (0, import_jsx_runtime4.jsxs)("div", { className: "mra-chat-window", children: [
|
|
160
|
+
/* @__PURE__ */ (0, import_jsx_runtime4.jsxs)("div", { className: "mra-header", children: [
|
|
176
161
|
/* @__PURE__ */ (0, import_jsx_runtime4.jsx)(import_lucide_react2.Bot, { size: 20 }),
|
|
177
|
-
/* @__PURE__ */ (0, import_jsx_runtime4.jsx)("span", { className: "
|
|
162
|
+
/* @__PURE__ */ (0, import_jsx_runtime4.jsx)("span", { className: "mra-title", children: title })
|
|
178
163
|
] }),
|
|
179
164
|
/* @__PURE__ */ (0, import_jsx_runtime4.jsx)(MessageList, { messages, isLoading }),
|
|
180
165
|
/* @__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/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-(--ai-border)\",\r\n \"bg-(--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-(--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-(--ai-bot-bg) text-(--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-all\",\r\n isUser\r\n ? \"bg-(--ai-user-bg) text-(--ai-user-text) rounded-br-sm\"\r\n : \"bg-(--ai-bot-bg) text-(--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-(--ai-border) bg-(--ai-bg)\">\r\n <input\r\n className={clsx(\r\n \"flex-1 px-3 py-2 border border-(--ai-border) rounded-lg outline-none\",\r\n \"font-inherit text-(--ai-text) placeholder:text-(--ai-text-secondary)\",\r\n \"focus:border-(--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-(--ai-primary) text-(--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"]}
|
|
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\nexport { ChatWindow, type ChatWindowProps } from \"./components/ChatWindow/ChatWindow\";\r\nexport * from \"./types\";","// src/components/ChatWindow/ChatWindow.tsx\r\n\"use client\";\r\n\r\nimport React, { useState, useEffect } from 'react';\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, messages.length]); // messages.length را به وابستگیها اضافه کردم برای اطمینان بیشتر\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=\"mra-chat-window\">\r\n <div className=\"mra-header\">\r\n <Bot size={20} />\r\n <span className=\"mra-title\">{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 { 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=\"mra-message-list\">\r\n {messages.map((msg, index) => (\r\n <MessageBubble key={index} message={msg} />\r\n ))}\r\n\r\n {isLoading && (\r\n <div className=\"mra-loading-wrapper\">\r\n <div className=\"mra-loading-bubble\">\r\n <div className=\"mra-loading-dot\" style={{ animationDelay: '-0.32s' }}></div>\r\n <div className=\"mra-loading-dot\" style={{ animationDelay: '-0.16s' }}></div>\r\n <div className=\"mra-loading-dot\"></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(\"mra-bubble-wrapper\", isUser ? \"mra-wrapper-user\" : \"mra-wrapper-bot\")}>\r\n <div\r\n className={clsx(\r\n \"mra-bubble\",\r\n isUser ? \"mra-bubble-user\" : \"mra-bubble-bot\"\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 { 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=\"mra-input-wrapper\">\r\n <input\r\n className=\"mra-input-field\"\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=\"mra-send-button\"\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","clsx","import_jsx_runtime","import_react","import_jsx_runtime","import_lucide_react","import_jsx_runtime"]}
|
package/dist/react.mjs
CHANGED
|
@@ -2,7 +2,6 @@
|
|
|
2
2
|
|
|
3
3
|
// src/components/ChatWindow/ChatWindow.tsx
|
|
4
4
|
import { useState as useState2, useEffect as useEffect2 } from "react";
|
|
5
|
-
import clsx3 from "clsx";
|
|
6
5
|
|
|
7
6
|
// src/components/MessageList/MessageList.tsx
|
|
8
7
|
import { useRef, useEffect } from "react";
|
|
@@ -12,12 +11,12 @@ import clsx from "clsx";
|
|
|
12
11
|
import { jsx } from "react/jsx-runtime";
|
|
13
12
|
var MessageBubble = ({ message }) => {
|
|
14
13
|
const isUser = message.role === "user";
|
|
15
|
-
return /* @__PURE__ */ jsx("div", { className: clsx("
|
|
14
|
+
return /* @__PURE__ */ jsx("div", { className: clsx("mra-bubble-wrapper", isUser ? "mra-wrapper-user" : "mra-wrapper-bot"), children: /* @__PURE__ */ jsx(
|
|
16
15
|
"div",
|
|
17
16
|
{
|
|
18
17
|
className: clsx(
|
|
19
|
-
"
|
|
20
|
-
isUser ? "
|
|
18
|
+
"mra-bubble",
|
|
19
|
+
isUser ? "mra-bubble-user" : "mra-bubble-bot"
|
|
21
20
|
),
|
|
22
21
|
children: message.content
|
|
23
22
|
}
|
|
@@ -31,12 +30,12 @@ var MessageList = ({ messages, isLoading }) => {
|
|
|
31
30
|
useEffect(() => {
|
|
32
31
|
messagesEndRef.current?.scrollIntoView({ behavior: "smooth" });
|
|
33
32
|
}, [messages, isLoading]);
|
|
34
|
-
return /* @__PURE__ */ jsxs("div", { className: "
|
|
33
|
+
return /* @__PURE__ */ jsxs("div", { className: "mra-message-list", children: [
|
|
35
34
|
messages.map((msg, index) => /* @__PURE__ */ jsx2(MessageBubble, { message: msg }, index)),
|
|
36
|
-
isLoading && /* @__PURE__ */ jsx2("div", { className: "
|
|
37
|
-
/* @__PURE__ */ jsx2("div", { className: "
|
|
38
|
-
/* @__PURE__ */ jsx2("div", { className: "
|
|
39
|
-
/* @__PURE__ */ jsx2("div", { className: "
|
|
35
|
+
isLoading && /* @__PURE__ */ jsx2("div", { className: "mra-loading-wrapper", children: /* @__PURE__ */ jsxs("div", { className: "mra-loading-bubble", children: [
|
|
36
|
+
/* @__PURE__ */ jsx2("div", { className: "mra-loading-dot", style: { animationDelay: "-0.32s" } }),
|
|
37
|
+
/* @__PURE__ */ jsx2("div", { className: "mra-loading-dot", style: { animationDelay: "-0.16s" } }),
|
|
38
|
+
/* @__PURE__ */ jsx2("div", { className: "mra-loading-dot" })
|
|
40
39
|
] }) }),
|
|
41
40
|
/* @__PURE__ */ jsx2("div", { ref: messagesEndRef })
|
|
42
41
|
] });
|
|
@@ -44,7 +43,6 @@ var MessageList = ({ messages, isLoading }) => {
|
|
|
44
43
|
|
|
45
44
|
// src/components/ChatInput/ChatInput.tsx
|
|
46
45
|
import { useState } from "react";
|
|
47
|
-
import clsx2 from "clsx";
|
|
48
46
|
import { Send } from "lucide-react";
|
|
49
47
|
import { jsx as jsx3, jsxs as jsxs2 } from "react/jsx-runtime";
|
|
50
48
|
var ChatInput = ({ onSendMessage, isLoading }) => {
|
|
@@ -61,15 +59,11 @@ var ChatInput = ({ onSendMessage, isLoading }) => {
|
|
|
61
59
|
handleSend();
|
|
62
60
|
}
|
|
63
61
|
};
|
|
64
|
-
return /* @__PURE__ */ jsxs2("div", { className: "
|
|
62
|
+
return /* @__PURE__ */ jsxs2("div", { className: "mra-input-wrapper", children: [
|
|
65
63
|
/* @__PURE__ */ jsx3(
|
|
66
64
|
"input",
|
|
67
65
|
{
|
|
68
|
-
className:
|
|
69
|
-
"flex-1 px-3 py-2 border border-(--ai-border) rounded-lg outline-none",
|
|
70
|
-
"font-inherit text-(--ai-text) placeholder:text-(--ai-text-secondary)",
|
|
71
|
-
"focus:border-(--ai-primary) disabled:opacity-50"
|
|
72
|
-
),
|
|
66
|
+
className: "mra-input-field",
|
|
73
67
|
value: inputValue,
|
|
74
68
|
onChange: (e) => setInputValue(e.target.value),
|
|
75
69
|
onKeyDown: handleKeyDown,
|
|
@@ -80,12 +74,7 @@ var ChatInput = ({ onSendMessage, isLoading }) => {
|
|
|
80
74
|
/* @__PURE__ */ jsx3(
|
|
81
75
|
"button",
|
|
82
76
|
{
|
|
83
|
-
className:
|
|
84
|
-
"px-3 py-2 rounded-lg flex items-center justify-center transition-opacity",
|
|
85
|
-
"bg-(--ai-primary) text-(--ai-primary-fg)",
|
|
86
|
-
"hover:opacity-90",
|
|
87
|
-
(isLoading || !inputValue.trim()) && "opacity-50 cursor-not-allowed"
|
|
88
|
-
),
|
|
77
|
+
className: "mra-send-button",
|
|
89
78
|
onClick: handleSend,
|
|
90
79
|
disabled: isLoading || !inputValue.trim(),
|
|
91
80
|
children: /* @__PURE__ */ jsx3(Send, { size: 18 })
|
|
@@ -108,7 +97,7 @@ var ChatWindow = ({
|
|
|
108
97
|
if (welcomeMessage && messages.length === 0) {
|
|
109
98
|
setMessages([{ role: "assistant", content: welcomeMessage }]);
|
|
110
99
|
}
|
|
111
|
-
}, [welcomeMessage]);
|
|
100
|
+
}, [welcomeMessage, messages.length]);
|
|
112
101
|
const handleSendMessage = async (userMessage) => {
|
|
113
102
|
const newUserMsg = { role: "user", content: userMessage };
|
|
114
103
|
const currentMessages = [...messages, newUserMsg];
|
|
@@ -132,14 +121,10 @@ var ChatWindow = ({
|
|
|
132
121
|
setIsLoading(false);
|
|
133
122
|
}
|
|
134
123
|
};
|
|
135
|
-
return /* @__PURE__ */ jsxs3("div", { className:
|
|
136
|
-
|
|
137
|
-
"bg-(--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-(--ai-border) bg-gray-50", children: [
|
|
124
|
+
return /* @__PURE__ */ jsxs3("div", { className: "mra-chat-window", children: [
|
|
125
|
+
/* @__PURE__ */ jsxs3("div", { className: "mra-header", children: [
|
|
141
126
|
/* @__PURE__ */ jsx4(Bot, { size: 20 }),
|
|
142
|
-
/* @__PURE__ */ jsx4("span", { className: "
|
|
127
|
+
/* @__PURE__ */ jsx4("span", { className: "mra-title", children: title })
|
|
143
128
|
] }),
|
|
144
129
|
/* @__PURE__ */ jsx4(MessageList, { messages, isLoading }),
|
|
145
130
|
/* @__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/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-(--ai-border)\",\r\n \"bg-(--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-(--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-(--ai-bot-bg) text-(--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-all\",\r\n isUser\r\n ? \"bg-(--ai-user-bg) text-(--ai-user-text) rounded-br-sm\"\r\n : \"bg-(--ai-bot-bg) text-(--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-(--ai-border) bg-(--ai-bg)\">\r\n <input\r\n className={clsx(\r\n \"flex-1 px-3 py-2 border border-(--ai-border) rounded-lg outline-none\",\r\n \"font-inherit text-(--ai-text) placeholder:text-(--ai-text-secondary)\",\r\n \"focus:border-(--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-(--ai-primary) text-(--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"]}
|
|
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 { 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, messages.length]); // messages.length را به وابستگیها اضافه کردم برای اطمینان بیشتر\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=\"mra-chat-window\">\r\n <div className=\"mra-header\">\r\n <Bot size={20} />\r\n <span className=\"mra-title\">{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 { 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=\"mra-message-list\">\r\n {messages.map((msg, index) => (\r\n <MessageBubble key={index} message={msg} />\r\n ))}\r\n\r\n {isLoading && (\r\n <div className=\"mra-loading-wrapper\">\r\n <div className=\"mra-loading-bubble\">\r\n <div className=\"mra-loading-dot\" style={{ animationDelay: '-0.32s' }}></div>\r\n <div className=\"mra-loading-dot\" style={{ animationDelay: '-0.16s' }}></div>\r\n <div className=\"mra-loading-dot\"></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(\"mra-bubble-wrapper\", isUser ? \"mra-wrapper-user\" : \"mra-wrapper-bot\")}>\r\n <div\r\n className={clsx(\r\n \"mra-bubble\",\r\n isUser ? \"mra-bubble-user\" : \"mra-bubble-bot\"\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 { 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=\"mra-input-wrapper\">\r\n <input\r\n className=\"mra-input-field\"\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=\"mra-send-button\"\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","jsx","jsx","jsxs","jsx","jsxs","useState","useEffect"]}
|
package/dist/styles.css
ADDED
|
@@ -0,0 +1,157 @@
|
|
|
1
|
+
/* src/styles.css */
|
|
2
|
+
|
|
3
|
+
/* === ChatWindow Styles === */
|
|
4
|
+
.mra-chat-window {
|
|
5
|
+
display: flex;
|
|
6
|
+
flex-direction: column;
|
|
7
|
+
height: 500px;
|
|
8
|
+
width: 100%;
|
|
9
|
+
max-width: 28rem; /* max-w-md */
|
|
10
|
+
border-radius: 0.75rem; /* rounded-xl */
|
|
11
|
+
border: 1px solid var(--ai-border, #e5e7eb);
|
|
12
|
+
background-color: var(--ai-bg, #ffffff);
|
|
13
|
+
overflow: hidden;
|
|
14
|
+
box-shadow: 0 10px 15px -3px rgb(0 0 0 / 0.1), 0 4px 6px -4px rgb(0 0 0 / 0.1); /* shadow-lg */
|
|
15
|
+
position: relative;
|
|
16
|
+
font-family: inherit;
|
|
17
|
+
font-size: 1rem;
|
|
18
|
+
line-height: 1.5rem;
|
|
19
|
+
box-sizing: border-box;
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
.mra-header {
|
|
23
|
+
display: flex;
|
|
24
|
+
align-items: center;
|
|
25
|
+
gap: 0.5rem; /* gap-2 */
|
|
26
|
+
padding: 1rem; /* px-4 py-4 */
|
|
27
|
+
border-bottom: 1px solid var(--ai-border, #e5e7eb);
|
|
28
|
+
background-color: #f9fafb; /* bg-gray-50 */
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
.mra-title {
|
|
32
|
+
font-weight: 600; /* font-semibold */
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
/* === MessageList Styles === */
|
|
36
|
+
.mra-message-list {
|
|
37
|
+
flex: 1 1 0%;
|
|
38
|
+
overflow-y: auto;
|
|
39
|
+
padding: 1rem;
|
|
40
|
+
display: flex;
|
|
41
|
+
flex-direction: column;
|
|
42
|
+
gap: 0.75rem; /* gap-3 */
|
|
43
|
+
scroll-behavior: smooth;
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
.mra-loading-wrapper {
|
|
47
|
+
display: flex;
|
|
48
|
+
justify-content: flex-start;
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
.mra-loading-bubble {
|
|
52
|
+
max-width: 80%;
|
|
53
|
+
padding: 0.5rem 0.75rem; /* px-3 py-2 */
|
|
54
|
+
border-radius: 0.75rem;
|
|
55
|
+
background-color: var(--ai-bot-bg, #f3f4f6);
|
|
56
|
+
color: var(--ai-text, #1f2937);
|
|
57
|
+
border-bottom-left-radius: 0.125rem; /* rounded-bl-sm */
|
|
58
|
+
display: flex;
|
|
59
|
+
gap: 0.25rem; /* gap-1 */
|
|
60
|
+
align-items: center;
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
.mra-loading-dot {
|
|
64
|
+
width: 0.375rem; /* w-1.5 */
|
|
65
|
+
height: 0.375rem; /* h-1.5 */
|
|
66
|
+
background-color: #9ca3af; /* bg-gray-400 */
|
|
67
|
+
border-radius: 9999px; /* rounded-full */
|
|
68
|
+
animation: bounce 1s infinite;
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
@keyframes bounce {
|
|
72
|
+
0%, 100% {
|
|
73
|
+
transform: translateY(-25%);
|
|
74
|
+
animation-timing-function: cubic-bezier(0.8, 0, 1, 1);
|
|
75
|
+
}
|
|
76
|
+
50% {
|
|
77
|
+
transform: translateY(0);
|
|
78
|
+
animation-timing-function: cubic-bezier(0, 0, 0.2, 1);
|
|
79
|
+
}
|
|
80
|
+
}
|
|
81
|
+
|
|
82
|
+
/* === MessageBubble Styles === */
|
|
83
|
+
.mra-bubble-wrapper {
|
|
84
|
+
display: flex;
|
|
85
|
+
width: 100%;
|
|
86
|
+
}
|
|
87
|
+
.mra-wrapper-user {
|
|
88
|
+
justify-content: flex-end;
|
|
89
|
+
}
|
|
90
|
+
.mra-wrapper-bot {
|
|
91
|
+
justify-content: flex-start;
|
|
92
|
+
}
|
|
93
|
+
|
|
94
|
+
.mra-bubble {
|
|
95
|
+
max-width: 80%;
|
|
96
|
+
padding: 0.5rem 0.75rem;
|
|
97
|
+
border-radius: 0.75rem;
|
|
98
|
+
font-size: 0.875rem; /* text-sm */
|
|
99
|
+
word-wrap: break-word;
|
|
100
|
+
}
|
|
101
|
+
.mra-bubble-user {
|
|
102
|
+
background-color: var(--ai-user-bg, #dbeafe);
|
|
103
|
+
color: var(--ai-user-text, #1e40af);
|
|
104
|
+
border-bottom-right-radius: 0.125rem; /* rounded-br-sm */
|
|
105
|
+
}
|
|
106
|
+
.mra-bubble-bot {
|
|
107
|
+
background-color: var(--ai-bot-bg, #f3f4f6);
|
|
108
|
+
color: var(--ai-text, #1f2937);
|
|
109
|
+
border-bottom-left-radius: 0.125rem; /* rounded-bl-sm */
|
|
110
|
+
}
|
|
111
|
+
|
|
112
|
+
/* === ChatInput Styles === */
|
|
113
|
+
.mra-input-wrapper {
|
|
114
|
+
display: flex;
|
|
115
|
+
gap: 0.5rem;
|
|
116
|
+
padding: 0.75rem; /* p-3 */
|
|
117
|
+
border-top: 1px solid var(--ai-border, #e5e7eb);
|
|
118
|
+
background-color: var(--ai-bg, #ffffff);
|
|
119
|
+
}
|
|
120
|
+
.mra-input-field {
|
|
121
|
+
flex: 1 1 0%;
|
|
122
|
+
padding: 0.5rem 0.75rem;
|
|
123
|
+
border: 1px solid var(--ai-border, #e5e7eb);
|
|
124
|
+
border-radius: 0.5rem; /* rounded-lg */
|
|
125
|
+
outline: none;
|
|
126
|
+
font-family: inherit;
|
|
127
|
+
color: var(--ai-text, #1f2937);
|
|
128
|
+
}
|
|
129
|
+
.mra-input-field::placeholder {
|
|
130
|
+
color: var(--ai-text-secondary, #6b7280);
|
|
131
|
+
}
|
|
132
|
+
.mra-input-field:focus {
|
|
133
|
+
border-color: var(--ai-primary, #2563eb);
|
|
134
|
+
}
|
|
135
|
+
.mra-input-field:disabled {
|
|
136
|
+
opacity: 0.5;
|
|
137
|
+
}
|
|
138
|
+
|
|
139
|
+
.mra-send-button {
|
|
140
|
+
padding: 0.5rem 0.75rem;
|
|
141
|
+
border-radius: 0.5rem;
|
|
142
|
+
display: flex;
|
|
143
|
+
align-items: center;
|
|
144
|
+
justify-content: center;
|
|
145
|
+
transition: opacity 0.2s;
|
|
146
|
+
background-color: var(--ai-primary, #2563eb);
|
|
147
|
+
color: var(--ai-primary-fg, #ffffff);
|
|
148
|
+
border: none;
|
|
149
|
+
cursor: pointer;
|
|
150
|
+
}
|
|
151
|
+
.mra-send-button:hover {
|
|
152
|
+
opacity: 0.9;
|
|
153
|
+
}
|
|
154
|
+
.mra-send-button:disabled {
|
|
155
|
+
opacity: 0.5;
|
|
156
|
+
cursor: not-allowed;
|
|
157
|
+
}
|
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "mehdi-akbari-ai-assistant-free",
|
|
3
|
-
"version": "0.
|
|
4
|
-
"description": "Professional AI Chatbot Library with
|
|
3
|
+
"version": "0.6.0",
|
|
4
|
+
"description": "Professional AI Chatbot Library with self-contained CSS styles",
|
|
5
5
|
"main": "./dist/index.js",
|
|
6
6
|
"module": "./dist/index.mjs",
|
|
7
7
|
"types": "./dist/index.d.ts",
|
|
@@ -18,10 +18,11 @@
|
|
|
18
18
|
"types": "./dist/react.d.ts",
|
|
19
19
|
"import": "./dist/react.mjs",
|
|
20
20
|
"require": "./dist/react.js"
|
|
21
|
-
}
|
|
21
|
+
},
|
|
22
|
+
"./styles.css": "./dist/styles.css"
|
|
22
23
|
},
|
|
23
24
|
"scripts": {
|
|
24
|
-
"build": "tsup",
|
|
25
|
+
"build": "tsup && copyfiles -u 1 src/styles.css dist",
|
|
25
26
|
"dev": "tsup --watch",
|
|
26
27
|
"prepublishOnly": "npm run build"
|
|
27
28
|
},
|
|
@@ -38,6 +39,7 @@
|
|
|
38
39
|
"devDependencies": {
|
|
39
40
|
"@types/react": "^18.3.27",
|
|
40
41
|
"@types/react-dom": "^18.3.7",
|
|
42
|
+
"copyfiles": "^2.4.1",
|
|
41
43
|
"react": "^18.3.1",
|
|
42
44
|
"react-dom": "^18.3.1",
|
|
43
45
|
"tsup": "^8.5.1",
|
|
@@ -50,9 +52,8 @@
|
|
|
50
52
|
"groq",
|
|
51
53
|
"langchain",
|
|
52
54
|
"chat-window",
|
|
53
|
-
"ui-component"
|
|
54
|
-
"tailwindcss"
|
|
55
|
+
"ui-component"
|
|
55
56
|
],
|
|
56
57
|
"author": "Mehdi Akbari",
|
|
57
58
|
"license": "MIT"
|
|
58
|
-
}
|
|
59
|
+
}
|