mehdi-akbari-ai-assistant-free 0.9.1 → 0.9.3

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.d.mts CHANGED
@@ -5,6 +5,8 @@ interface ChatWindowProps {
5
5
  apiEndpoint: string;
6
6
  title?: string;
7
7
  welcomeMessage?: string;
8
+ isFullScreen?: boolean;
9
+ onToggleFullScreen?: () => void;
8
10
  }
9
11
  declare const ChatWindow: React.FC<ChatWindowProps>;
10
12
 
package/dist/react.d.ts CHANGED
@@ -5,6 +5,8 @@ interface ChatWindowProps {
5
5
  apiEndpoint: string;
6
6
  title?: string;
7
7
  welcomeMessage?: string;
8
+ isFullScreen?: boolean;
9
+ onToggleFullScreen?: () => void;
8
10
  }
9
11
  declare const ChatWindow: React.FC<ChatWindowProps>;
10
12
 
package/dist/react.js CHANGED
@@ -138,11 +138,13 @@ var import_jsx_runtime4 = require("react/jsx-runtime");
138
138
  var ChatWindow = ({
139
139
  apiEndpoint,
140
140
  title = "AI Assistant",
141
- welcomeMessage = "\u0633\u0644\u0627\u0645! \u0686\u0637\u0648\u0631 \u0645\u06CC\u200C\u062A\u0648\u0627\u0646\u0645 \u06A9\u0645\u06A9\u062A\u0627\u0646 \u06A9\u0646\u0645\u061F"
141
+ welcomeMessage = "\u0633\u0644\u0627\u0645! \u0686\u0637\u0648\u0631 \u0645\u06CC\u200C\u062A\u0648\u0627\u0646\u0645 \u06A9\u0645\u06A9\u062A\u0627\u0646 \u06A9\u0646\u0645\u061F",
142
+ isFullScreen = false,
143
+ onToggleFullScreen
142
144
  }) => {
143
145
  const [messages, setMessages] = (0, import_react3.useState)([]);
144
146
  const [isLoading, setIsLoading] = (0, import_react3.useState)(false);
145
- const version = "0.9.1";
147
+ const version = "0.9.3";
146
148
  (0, import_react3.useEffect)(() => {
147
149
  if (welcomeMessage && messages.length === 0) {
148
150
  setMessages([{ role: "assistant", content: welcomeMessage }]);
@@ -173,8 +175,11 @@ var ChatWindow = ({
173
175
  };
174
176
  return /* @__PURE__ */ (0, import_jsx_runtime4.jsxs)("div", { className: "mra-chat-window", children: [
175
177
  /* @__PURE__ */ (0, import_jsx_runtime4.jsxs)("div", { className: "mra-header", children: [
176
- /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(import_lucide_react2.Bot, { size: 20 }),
177
- /* @__PURE__ */ (0, import_jsx_runtime4.jsx)("span", { className: "mra-title", children: title })
178
+ /* @__PURE__ */ (0, import_jsx_runtime4.jsxs)("div", { className: "mra-header-title-group", children: [
179
+ /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(import_lucide_react2.Bot, { size: 20 }),
180
+ /* @__PURE__ */ (0, import_jsx_runtime4.jsx)("span", { className: "mra-title", children: title })
181
+ ] }),
182
+ onToggleFullScreen && /* @__PURE__ */ (0, import_jsx_runtime4.jsx)("button", { onClick: onToggleFullScreen, className: "mra-header-icon-button", children: isFullScreen ? /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(import_lucide_react2.Minimize, { size: 16 }) : /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(import_lucide_react2.Maximize, { size: 16 }) })
178
183
  ] }),
179
184
  /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(MessageList, { messages, isLoading }),
180
185
  /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(ChatInput, { onSendMessage: handleSendMessage, isLoading }),
@@ -202,16 +207,28 @@ var ChatbotFAB = ({ onClick, animationData }) => {
202
207
 
203
208
  // src/components/AiAssistant/AiAssistant.tsx
204
209
  var import_clsx2 = __toESM(require("clsx"));
205
- var import_jsx_runtime6 = require("react/jsx-runtime");
210
+ var import_jsx_runtime6 = (
211
+ // اگر تمام‌صفحه باشد، کلاس جدید اضافه می‌شود
212
+ require("react/jsx-runtime")
213
+ );
206
214
  var DEFAULT_LOTTIE_URL = "https://lottie.host/a822cf1a-1e96-4187-a220-42adb2a61d19/B5bQnC2p9K.json";
207
215
  var AiAssistant = ({
208
216
  lottieAnimationData = DEFAULT_LOTTIE_URL,
209
217
  ...chatWindowProps
210
218
  }) => {
211
219
  const [isOpen, setIsOpen] = (0, import_react4.useState)(false);
220
+ const [isFullScreen, setIsFullScreen] = (0, import_react4.useState)(false);
212
221
  const toggleChat = () => setIsOpen((prev) => !prev);
213
- return /* @__PURE__ */ (0, import_jsx_runtime6.jsxs)("div", { className: "mra-container", children: [
214
- /* @__PURE__ */ (0, import_jsx_runtime6.jsx)("div", { className: (0, import_clsx2.default)("mra-chat-window-container", isOpen && "mra-chat-window-container--open"), children: /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(ChatWindow, { ...chatWindowProps }) }),
222
+ const toggleFullScreen = () => setIsFullScreen((prev) => !prev);
223
+ return /* @__PURE__ */ (0, import_jsx_runtime6.jsxs)("div", { className: (0, import_clsx2.default)("mra-container", isFullScreen && "mra-container--fullscreen"), children: [
224
+ /* @__PURE__ */ (0, import_jsx_runtime6.jsx)("div", { className: (0, import_clsx2.default)("mra-chat-window-container", isOpen && "mra-chat-window-container--open"), children: /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(
225
+ ChatWindow,
226
+ {
227
+ ...chatWindowProps,
228
+ isFullScreen,
229
+ onToggleFullScreen: toggleFullScreen
230
+ }
231
+ ) }),
215
232
  /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(ChatbotFAB, { onClick: toggleChat, animationData: lottieAnimationData })
216
233
  ] });
217
234
  };
package/dist/react.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/react.ts","../src/components/AiAssistant/AiAssistant.tsx","../src/components/ChatWindow/ChatWindow.tsx","../src/components/MessageList/MessageList.tsx","../src/components/MessageBubble/MessageBubble.tsx","../src/components/ChatInput/ChatInput.tsx","../src/components/ChatbotFAB/ChatbotFAB.tsx"],"sourcesContent":["\r\n\"use client\";\r\n\r\n\r\nexport { AiAssistant } from \"./components/AiAssistant/AiAssistant\";\r\n\r\n\r\n\r\nexport { ChatWindow, type ChatWindowProps } from \"./components/ChatWindow/ChatWindow\";\r\nexport * from \"./types\";","// src/components/AiAssistant/AiAssistant.tsx\r\n\"use client\";\r\nimport React, { useState } from 'react';\r\nimport { ChatWindow, ChatWindowProps } from '../ChatWindow/ChatWindow';\r\nimport { ChatbotFAB } from '../ChatbotFAB/ChatbotFAB';\r\nimport clsx from 'clsx';\r\n\r\ninterface AiAssistantProps extends ChatWindowProps {\r\n // تایپ را به any تغییر می‌دهیم تا هم رشته و هم آبجکت JSON را بپذیرد\r\n lottieAnimationData?: any; \r\n}\r\n\r\nconst DEFAULT_LOTTIE_URL = \"https://lottie.host/a822cf1a-1e96-4187-a220-42adb2a61d19/B5bQnC2p9K.json\";\r\n\r\nexport const AiAssistant: React.FC<AiAssistantProps> = ({ \r\n lottieAnimationData = DEFAULT_LOTTIE_URL,\r\n ...chatWindowProps\r\n}) => {\r\n const [isOpen, setIsOpen] = useState(false);\r\n\r\n const toggleChat = () => setIsOpen(prev => !prev);\r\n\r\n return (\r\n <div className=\"mra-container\">\r\n <div className={clsx(\"mra-chat-window-container\", isOpen && \"mra-chat-window-container--open\")}>\r\n <ChatWindow {...chatWindowProps} />\r\n </div>\r\n <ChatbotFAB onClick={toggleChat} animationData={lottieAnimationData} />\r\n </div>\r\n );\r\n};","// 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 const version = process.env.PACKAGE_VERSION; \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]);\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\r\n {/* === فوتر جدید اضافه شده === */}\r\n <footer className=\"mra-footer\">\r\n <span>v{version}</span>\r\n <div className=\"mra-footer-links\">\r\n <span>Powered By Mehdi Akbari |</span>\r\n <a href=\"mailto:mehdiakbarideveloper@gmail.com\" className=\"mra-footer-link\" target=\"_blank\" rel=\"noopener noreferrer\">Gmail</a>\r\n <a href=\"https://t.me/MehdiAkbariDev\" className=\"mra-footer-link\" target=\"_blank\" rel=\"noopener noreferrer\">Telegram</a>\r\n </div>\r\n </footer>\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, useRef, useEffect } 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 const textareaRef = useRef<HTMLTextAreaElement>(null); // Ref برای دسترسی به textarea\r\n\r\n // این افکت با هر بار تغییر متن، ارتفاع textarea را تنظیم می‌کند\r\n useEffect(() => {\r\n const textarea = textareaRef.current;\r\n if (textarea) {\r\n // ارتفاع را ریست می‌کنیم تا در صورت پاک کردن متن، کوچک شود\r\n textarea.style.height = 'auto';\r\n // ارتفاع جدید را بر اساس محتوای داخلی تنظیم می‌کنیم\r\n textarea.style.height = `${textarea.scrollHeight}px`;\r\n }\r\n }, [inputValue]);\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 // این منطق به درستی Shift+Enter را برای ایجاد خط جدید مدیریت می‌کند\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 <textarea\r\n ref={textareaRef}\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 rows={1} // با یک ردیف شروع می‌شود\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};","\r\n\"use client\";\r\nimport React from 'react';\r\nimport Lottie from 'lottie-react';\r\n\r\ninterface ChatbotFABProps {\r\n onClick: () => void;\r\n \r\n \r\n animationData: any; \r\n}\r\n\r\nexport const ChatbotFAB: React.FC<ChatbotFABProps> = ({ onClick, animationData }) => {\r\n \r\n \r\n const lottieProps = typeof animationData === 'string' \r\n ? { animationData: null, path: animationData } \r\n : { animationData: animationData };\r\n\r\n return (\r\n <button className=\"mra-fab\" onClick={onClick}>\r\n <Lottie {...lottieProps} loop={true} />\r\n </button>\r\n );\r\n};"],"mappings":"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","names":["import_react","import_react","clsx","import_jsx_runtime","import_react","import_jsx_runtime","import_lucide_react","import_jsx_runtime","import_jsx_runtime","Lottie","import_clsx","import_jsx_runtime","clsx"]}
1
+ {"version":3,"sources":["../src/react.ts","../src/components/AiAssistant/AiAssistant.tsx","../src/components/ChatWindow/ChatWindow.tsx","../src/components/MessageList/MessageList.tsx","../src/components/MessageBubble/MessageBubble.tsx","../src/components/ChatInput/ChatInput.tsx","../src/components/ChatbotFAB/ChatbotFAB.tsx"],"sourcesContent":["\r\n\"use client\";\r\n\r\n\r\nexport { AiAssistant } from \"./components/AiAssistant/AiAssistant\";\r\n\r\n\r\n\r\nexport { ChatWindow, type ChatWindowProps } from \"./components/ChatWindow/ChatWindow\";\r\nexport * from \"./types\";","// src/components/AiAssistant/AiAssistant.tsx\r\n\"use client\";\r\nimport React, { useState } from 'react';\r\nimport { ChatWindow, ChatWindowProps } from '../ChatWindow/ChatWindow';\r\nimport { ChatbotFAB } from '../ChatbotFAB/ChatbotFAB';\r\nimport clsx from 'clsx';\r\n\r\ninterface AiAssistantProps extends ChatWindowProps {\r\n lottieAnimationData?: any;\r\n}\r\n\r\nconst DEFAULT_LOTTIE_URL = \"https://lottie.host/a822cf1a-1e96-4187-a220-42adb2a61d19/B5bQnC2p9K.json\";\r\n\r\nexport const AiAssistant: React.FC<AiAssistantProps> = ({\r\n lottieAnimationData = DEFAULT_LOTTIE_URL,\r\n ...chatWindowProps\r\n}) => {\r\n const [isOpen, setIsOpen] = useState(false);\r\n const [isFullScreen, setIsFullScreen] = useState(false); // استیت جدید برای حالت تمام‌صفحه\r\n\r\n const toggleChat = () => setIsOpen(prev => !prev);\r\n const toggleFullScreen = () => setIsFullScreen(prev => !prev);\r\n\r\n return (\r\n // اگر تمام‌صفحه باشد، کلاس جدید اضافه می‌شود\r\n <div className={clsx(\"mra-container\", isFullScreen && \"mra-container--fullscreen\")}>\r\n <div className={clsx(\"mra-chat-window-container\", isOpen && \"mra-chat-window-container--open\")}>\r\n <ChatWindow\r\n {...chatWindowProps}\r\n // دو پراپ جدید به ChatWindow پاس می‌دهیم\r\n isFullScreen={isFullScreen}\r\n onToggleFullScreen={toggleFullScreen}\r\n />\r\n </div>\r\n <ChatbotFAB onClick={toggleChat} animationData={lottieAnimationData} />\r\n </div>\r\n );\r\n};","// 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, Maximize, Minimize } from 'lucide-react'; // آیکون‌های تمام‌صفحه اضافه شدند\r\n\r\n// پراپ‌های کامپوننت با گزینه‌های جدید آپدیت شدند\r\nexport interface ChatWindowProps {\r\n apiEndpoint: string;\r\n title?: string;\r\n welcomeMessage?: string;\r\n isFullScreen?: boolean;\r\n onToggleFullScreen?: () => void;\r\n}\r\n\r\nexport const ChatWindow: React.FC<ChatWindowProps> = ({\r\n apiEndpoint,\r\n title = \"AI Assistant\",\r\n welcomeMessage = \"سلام! چطور می‌توانم کمکتان کنم؟\",\r\n isFullScreen = false,\r\n onToggleFullScreen,\r\n}) => {\r\n const [messages, setMessages] = useState<Message[]>([]);\r\n const [isLoading, setIsLoading] = useState(false);\r\n const version = process.env.PACKAGE_VERSION; \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]);\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 {/* هدر با دکمه تمام‌صفحه آپدیت شده است */}\r\n <div className=\"mra-header\">\r\n <div className=\"mra-header-title-group\">\r\n <Bot size={20} />\r\n <span className=\"mra-title\">{title}</span>\r\n </div>\r\n {onToggleFullScreen && (\r\n <button onClick={onToggleFullScreen} className=\"mra-header-icon-button\">\r\n {isFullScreen ? <Minimize size={16} /> : <Maximize size={16} />}\r\n </button>\r\n )}\r\n </div>\r\n\r\n <MessageList messages={messages} isLoading={isLoading} />\r\n <ChatInput onSendMessage={handleSendMessage} isLoading={isLoading} />\r\n\r\n <footer className=\"mra-footer\">\r\n <span>v{version}</span>\r\n <div className=\"mra-footer-links\">\r\n <span>Powered By Mehdi Akbari |</span>\r\n <a href=\"mailto:mehdiakbarideveloper@gmail.com\" className=\"mra-footer-link\" target=\"_blank\" rel=\"noopener noreferrer\">Gmail</a>\r\n <a href=\"https://t.me/MehdiAkbariDev\" className=\"mra-footer-link\" target=\"_blank\" rel=\"noopener noreferrer\">Telegram</a>\r\n </div>\r\n </footer>\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, useRef, useEffect } 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 const textareaRef = useRef<HTMLTextAreaElement>(null); // Ref برای دسترسی به textarea\r\n\r\n // این افکت با هر بار تغییر متن، ارتفاع textarea را تنظیم می‌کند\r\n useEffect(() => {\r\n const textarea = textareaRef.current;\r\n if (textarea) {\r\n // ارتفاع را ریست می‌کنیم تا در صورت پاک کردن متن، کوچک شود\r\n textarea.style.height = 'auto';\r\n // ارتفاع جدید را بر اساس محتوای داخلی تنظیم می‌کنیم\r\n textarea.style.height = `${textarea.scrollHeight}px`;\r\n }\r\n }, [inputValue]);\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 // این منطق به درستی Shift+Enter را برای ایجاد خط جدید مدیریت می‌کند\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 <textarea\r\n ref={textareaRef}\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 rows={1} // با یک ردیف شروع می‌شود\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};","\r\n\"use client\";\r\nimport React from 'react';\r\nimport Lottie from 'lottie-react';\r\n\r\ninterface ChatbotFABProps {\r\n onClick: () => void;\r\n \r\n \r\n animationData: any; \r\n}\r\n\r\nexport const ChatbotFAB: React.FC<ChatbotFABProps> = ({ onClick, animationData }) => {\r\n \r\n \r\n const lottieProps = typeof animationData === 'string' \r\n ? { animationData: null, path: animationData } \r\n : { animationData: animationData };\r\n\r\n return (\r\n <button className=\"mra-fab\" onClick={onClick}>\r\n <Lottie {...lottieProps} loop={true} />\r\n </button>\r\n );\r\n};"],"mappings":"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","names":["import_react","import_react","clsx","import_jsx_runtime","import_react","import_jsx_runtime","import_lucide_react","import_jsx_runtime","import_jsx_runtime","Lottie","import_clsx","import_jsx_runtime","clsx"]}
package/dist/react.mjs CHANGED
@@ -97,16 +97,18 @@ var ChatInput = ({ onSendMessage, isLoading }) => {
97
97
  };
98
98
 
99
99
  // src/components/ChatWindow/ChatWindow.tsx
100
- import { Bot } from "lucide-react";
100
+ import { Bot, Maximize, Minimize } from "lucide-react";
101
101
  import { jsx as jsx4, jsxs as jsxs3 } from "react/jsx-runtime";
102
102
  var ChatWindow = ({
103
103
  apiEndpoint,
104
104
  title = "AI Assistant",
105
- welcomeMessage = "\u0633\u0644\u0627\u0645! \u0686\u0637\u0648\u0631 \u0645\u06CC\u200C\u062A\u0648\u0627\u0646\u0645 \u06A9\u0645\u06A9\u062A\u0627\u0646 \u06A9\u0646\u0645\u061F"
105
+ welcomeMessage = "\u0633\u0644\u0627\u0645! \u0686\u0637\u0648\u0631 \u0645\u06CC\u200C\u062A\u0648\u0627\u0646\u0645 \u06A9\u0645\u06A9\u062A\u0627\u0646 \u06A9\u0646\u0645\u061F",
106
+ isFullScreen = false,
107
+ onToggleFullScreen
106
108
  }) => {
107
109
  const [messages, setMessages] = useState2([]);
108
110
  const [isLoading, setIsLoading] = useState2(false);
109
- const version = "0.9.1";
111
+ const version = "0.9.3";
110
112
  useEffect3(() => {
111
113
  if (welcomeMessage && messages.length === 0) {
112
114
  setMessages([{ role: "assistant", content: welcomeMessage }]);
@@ -137,8 +139,11 @@ var ChatWindow = ({
137
139
  };
138
140
  return /* @__PURE__ */ jsxs3("div", { className: "mra-chat-window", children: [
139
141
  /* @__PURE__ */ jsxs3("div", { className: "mra-header", children: [
140
- /* @__PURE__ */ jsx4(Bot, { size: 20 }),
141
- /* @__PURE__ */ jsx4("span", { className: "mra-title", children: title })
142
+ /* @__PURE__ */ jsxs3("div", { className: "mra-header-title-group", children: [
143
+ /* @__PURE__ */ jsx4(Bot, { size: 20 }),
144
+ /* @__PURE__ */ jsx4("span", { className: "mra-title", children: title })
145
+ ] }),
146
+ onToggleFullScreen && /* @__PURE__ */ jsx4("button", { onClick: onToggleFullScreen, className: "mra-header-icon-button", children: isFullScreen ? /* @__PURE__ */ jsx4(Minimize, { size: 16 }) : /* @__PURE__ */ jsx4(Maximize, { size: 16 }) })
142
147
  ] }),
143
148
  /* @__PURE__ */ jsx4(MessageList, { messages, isLoading }),
144
149
  /* @__PURE__ */ jsx4(ChatInput, { onSendMessage: handleSendMessage, isLoading }),
@@ -173,11 +178,23 @@ var AiAssistant = ({
173
178
  ...chatWindowProps
174
179
  }) => {
175
180
  const [isOpen, setIsOpen] = useState3(false);
181
+ const [isFullScreen, setIsFullScreen] = useState3(false);
176
182
  const toggleChat = () => setIsOpen((prev) => !prev);
177
- return /* @__PURE__ */ jsxs4("div", { className: "mra-container", children: [
178
- /* @__PURE__ */ jsx6("div", { className: clsx2("mra-chat-window-container", isOpen && "mra-chat-window-container--open"), children: /* @__PURE__ */ jsx6(ChatWindow, { ...chatWindowProps }) }),
179
- /* @__PURE__ */ jsx6(ChatbotFAB, { onClick: toggleChat, animationData: lottieAnimationData })
180
- ] });
183
+ const toggleFullScreen = () => setIsFullScreen((prev) => !prev);
184
+ return (
185
+ // اگر تمام‌صفحه باشد، کلاس جدید اضافه می‌شود
186
+ /* @__PURE__ */ jsxs4("div", { className: clsx2("mra-container", isFullScreen && "mra-container--fullscreen"), children: [
187
+ /* @__PURE__ */ jsx6("div", { className: clsx2("mra-chat-window-container", isOpen && "mra-chat-window-container--open"), children: /* @__PURE__ */ jsx6(
188
+ ChatWindow,
189
+ {
190
+ ...chatWindowProps,
191
+ isFullScreen,
192
+ onToggleFullScreen: toggleFullScreen
193
+ }
194
+ ) }),
195
+ /* @__PURE__ */ jsx6(ChatbotFAB, { onClick: toggleChat, animationData: lottieAnimationData })
196
+ ] })
197
+ );
181
198
  };
182
199
  export {
183
200
  AiAssistant,
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/components/AiAssistant/AiAssistant.tsx","../src/components/ChatWindow/ChatWindow.tsx","../src/components/MessageList/MessageList.tsx","../src/components/MessageBubble/MessageBubble.tsx","../src/components/ChatInput/ChatInput.tsx","../src/components/ChatbotFAB/ChatbotFAB.tsx"],"sourcesContent":["// src/components/AiAssistant/AiAssistant.tsx\r\n\"use client\";\r\nimport React, { useState } from 'react';\r\nimport { ChatWindow, ChatWindowProps } from '../ChatWindow/ChatWindow';\r\nimport { ChatbotFAB } from '../ChatbotFAB/ChatbotFAB';\r\nimport clsx from 'clsx';\r\n\r\ninterface AiAssistantProps extends ChatWindowProps {\r\n // تایپ را به any تغییر می‌دهیم تا هم رشته و هم آبجکت JSON را بپذیرد\r\n lottieAnimationData?: any; \r\n}\r\n\r\nconst DEFAULT_LOTTIE_URL = \"https://lottie.host/a822cf1a-1e96-4187-a220-42adb2a61d19/B5bQnC2p9K.json\";\r\n\r\nexport const AiAssistant: React.FC<AiAssistantProps> = ({ \r\n lottieAnimationData = DEFAULT_LOTTIE_URL,\r\n ...chatWindowProps\r\n}) => {\r\n const [isOpen, setIsOpen] = useState(false);\r\n\r\n const toggleChat = () => setIsOpen(prev => !prev);\r\n\r\n return (\r\n <div className=\"mra-container\">\r\n <div className={clsx(\"mra-chat-window-container\", isOpen && \"mra-chat-window-container--open\")}>\r\n <ChatWindow {...chatWindowProps} />\r\n </div>\r\n <ChatbotFAB onClick={toggleChat} animationData={lottieAnimationData} />\r\n </div>\r\n );\r\n};","// 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 const version = process.env.PACKAGE_VERSION; \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]);\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\r\n {/* === فوتر جدید اضافه شده === */}\r\n <footer className=\"mra-footer\">\r\n <span>v{version}</span>\r\n <div className=\"mra-footer-links\">\r\n <span>Powered By Mehdi Akbari |</span>\r\n <a href=\"mailto:mehdiakbarideveloper@gmail.com\" className=\"mra-footer-link\" target=\"_blank\" rel=\"noopener noreferrer\">Gmail</a>\r\n <a href=\"https://t.me/MehdiAkbariDev\" className=\"mra-footer-link\" target=\"_blank\" rel=\"noopener noreferrer\">Telegram</a>\r\n </div>\r\n </footer>\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, useRef, useEffect } 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 const textareaRef = useRef<HTMLTextAreaElement>(null); // Ref برای دسترسی به textarea\r\n\r\n // این افکت با هر بار تغییر متن، ارتفاع textarea را تنظیم می‌کند\r\n useEffect(() => {\r\n const textarea = textareaRef.current;\r\n if (textarea) {\r\n // ارتفاع را ریست می‌کنیم تا در صورت پاک کردن متن، کوچک شود\r\n textarea.style.height = 'auto';\r\n // ارتفاع جدید را بر اساس محتوای داخلی تنظیم می‌کنیم\r\n textarea.style.height = `${textarea.scrollHeight}px`;\r\n }\r\n }, [inputValue]);\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 // این منطق به درستی Shift+Enter را برای ایجاد خط جدید مدیریت می‌کند\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 <textarea\r\n ref={textareaRef}\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 rows={1} // با یک ردیف شروع می‌شود\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};","\r\n\"use client\";\r\nimport React from 'react';\r\nimport Lottie from 'lottie-react';\r\n\r\ninterface ChatbotFABProps {\r\n onClick: () => void;\r\n \r\n \r\n animationData: any; \r\n}\r\n\r\nexport const ChatbotFAB: React.FC<ChatbotFABProps> = ({ onClick, animationData }) => {\r\n \r\n \r\n const lottieProps = typeof animationData === 'string' \r\n ? { animationData: null, path: animationData } \r\n : { animationData: animationData };\r\n\r\n return (\r\n <button className=\"mra-fab\" onClick={onClick}>\r\n <Lottie {...lottieProps} loop={true} />\r\n </button>\r\n );\r\n};"],"mappings":"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","names":["useState","useState","useEffect","jsx","useRef","useEffect","jsx","jsxs","jsx","jsxs","useState","useEffect","jsx","clsx","jsx","jsxs","useState"]}
1
+ {"version":3,"sources":["../src/components/AiAssistant/AiAssistant.tsx","../src/components/ChatWindow/ChatWindow.tsx","../src/components/MessageList/MessageList.tsx","../src/components/MessageBubble/MessageBubble.tsx","../src/components/ChatInput/ChatInput.tsx","../src/components/ChatbotFAB/ChatbotFAB.tsx"],"sourcesContent":["// src/components/AiAssistant/AiAssistant.tsx\r\n\"use client\";\r\nimport React, { useState } from 'react';\r\nimport { ChatWindow, ChatWindowProps } from '../ChatWindow/ChatWindow';\r\nimport { ChatbotFAB } from '../ChatbotFAB/ChatbotFAB';\r\nimport clsx from 'clsx';\r\n\r\ninterface AiAssistantProps extends ChatWindowProps {\r\n lottieAnimationData?: any;\r\n}\r\n\r\nconst DEFAULT_LOTTIE_URL = \"https://lottie.host/a822cf1a-1e96-4187-a220-42adb2a61d19/B5bQnC2p9K.json\";\r\n\r\nexport const AiAssistant: React.FC<AiAssistantProps> = ({\r\n lottieAnimationData = DEFAULT_LOTTIE_URL,\r\n ...chatWindowProps\r\n}) => {\r\n const [isOpen, setIsOpen] = useState(false);\r\n const [isFullScreen, setIsFullScreen] = useState(false); // استیت جدید برای حالت تمام‌صفحه\r\n\r\n const toggleChat = () => setIsOpen(prev => !prev);\r\n const toggleFullScreen = () => setIsFullScreen(prev => !prev);\r\n\r\n return (\r\n // اگر تمام‌صفحه باشد، کلاس جدید اضافه می‌شود\r\n <div className={clsx(\"mra-container\", isFullScreen && \"mra-container--fullscreen\")}>\r\n <div className={clsx(\"mra-chat-window-container\", isOpen && \"mra-chat-window-container--open\")}>\r\n <ChatWindow\r\n {...chatWindowProps}\r\n // دو پراپ جدید به ChatWindow پاس می‌دهیم\r\n isFullScreen={isFullScreen}\r\n onToggleFullScreen={toggleFullScreen}\r\n />\r\n </div>\r\n <ChatbotFAB onClick={toggleChat} animationData={lottieAnimationData} />\r\n </div>\r\n );\r\n};","// 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, Maximize, Minimize } from 'lucide-react'; // آیکون‌های تمام‌صفحه اضافه شدند\r\n\r\n// پراپ‌های کامپوننت با گزینه‌های جدید آپدیت شدند\r\nexport interface ChatWindowProps {\r\n apiEndpoint: string;\r\n title?: string;\r\n welcomeMessage?: string;\r\n isFullScreen?: boolean;\r\n onToggleFullScreen?: () => void;\r\n}\r\n\r\nexport const ChatWindow: React.FC<ChatWindowProps> = ({\r\n apiEndpoint,\r\n title = \"AI Assistant\",\r\n welcomeMessage = \"سلام! چطور می‌توانم کمکتان کنم؟\",\r\n isFullScreen = false,\r\n onToggleFullScreen,\r\n}) => {\r\n const [messages, setMessages] = useState<Message[]>([]);\r\n const [isLoading, setIsLoading] = useState(false);\r\n const version = process.env.PACKAGE_VERSION; \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]);\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 {/* هدر با دکمه تمام‌صفحه آپدیت شده است */}\r\n <div className=\"mra-header\">\r\n <div className=\"mra-header-title-group\">\r\n <Bot size={20} />\r\n <span className=\"mra-title\">{title}</span>\r\n </div>\r\n {onToggleFullScreen && (\r\n <button onClick={onToggleFullScreen} className=\"mra-header-icon-button\">\r\n {isFullScreen ? <Minimize size={16} /> : <Maximize size={16} />}\r\n </button>\r\n )}\r\n </div>\r\n\r\n <MessageList messages={messages} isLoading={isLoading} />\r\n <ChatInput onSendMessage={handleSendMessage} isLoading={isLoading} />\r\n\r\n <footer className=\"mra-footer\">\r\n <span>v{version}</span>\r\n <div className=\"mra-footer-links\">\r\n <span>Powered By Mehdi Akbari |</span>\r\n <a href=\"mailto:mehdiakbarideveloper@gmail.com\" className=\"mra-footer-link\" target=\"_blank\" rel=\"noopener noreferrer\">Gmail</a>\r\n <a href=\"https://t.me/MehdiAkbariDev\" className=\"mra-footer-link\" target=\"_blank\" rel=\"noopener noreferrer\">Telegram</a>\r\n </div>\r\n </footer>\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, useRef, useEffect } 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 const textareaRef = useRef<HTMLTextAreaElement>(null); // Ref برای دسترسی به textarea\r\n\r\n // این افکت با هر بار تغییر متن، ارتفاع textarea را تنظیم می‌کند\r\n useEffect(() => {\r\n const textarea = textareaRef.current;\r\n if (textarea) {\r\n // ارتفاع را ریست می‌کنیم تا در صورت پاک کردن متن، کوچک شود\r\n textarea.style.height = 'auto';\r\n // ارتفاع جدید را بر اساس محتوای داخلی تنظیم می‌کنیم\r\n textarea.style.height = `${textarea.scrollHeight}px`;\r\n }\r\n }, [inputValue]);\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 // این منطق به درستی Shift+Enter را برای ایجاد خط جدید مدیریت می‌کند\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 <textarea\r\n ref={textareaRef}\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 rows={1} // با یک ردیف شروع می‌شود\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};","\r\n\"use client\";\r\nimport React from 'react';\r\nimport Lottie from 'lottie-react';\r\n\r\ninterface ChatbotFABProps {\r\n onClick: () => void;\r\n \r\n \r\n animationData: any; \r\n}\r\n\r\nexport const ChatbotFAB: React.FC<ChatbotFABProps> = ({ onClick, animationData }) => {\r\n \r\n \r\n const lottieProps = typeof animationData === 'string' \r\n ? { animationData: null, path: animationData } \r\n : { animationData: animationData };\r\n\r\n return (\r\n <button className=\"mra-fab\" onClick={onClick}>\r\n <Lottie {...lottieProps} loop={true} />\r\n </button>\r\n );\r\n};"],"mappings":"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","names":["useState","useState","useEffect","jsx","useRef","useEffect","jsx","jsxs","jsx","jsxs","useState","useEffect","jsx","clsx","jsx","jsxs","useState"]}
package/dist/styles.css CHANGED
@@ -1,46 +1,146 @@
1
1
  /* src/styles.css */
2
2
 
3
+ /* === Container & FAB Styles === */
4
+ .mra-container {
5
+ position: fixed;
6
+ bottom: 2rem;
7
+ right: 2rem;
8
+ z-index: 1000;
9
+ transition: all 0.3s ease-in-out;
10
+ }
11
+
12
+ /* Styles for Fullscreen Mode */
13
+ .mra-container--fullscreen {
14
+ bottom: 0;
15
+ right: 0;
16
+ width: 100%;
17
+ height: 100%;
18
+ max-width: 100%;
19
+ max-height: 100%;
20
+ }
21
+
22
+ .mra-container--fullscreen .mra-chat-window-container {
23
+ position: static;
24
+ /* (اصلاح کلیدی) عرض و ارتفاع را 100% می‌کنیم تا کل فضا را پر کند */
25
+ width: 100%;
26
+ height: 100%;
27
+ }
28
+
29
+ .mra-container--fullscreen .mra-chat-window {
30
+ height: 100%;
31
+ width: 100%;
32
+ max-width: 100%;
33
+ border-radius: 0;
34
+ }
35
+
36
+ .mra-container--fullscreen .mra-fab {
37
+ display: none;
38
+ }
39
+
40
+
41
+ /* Floating Action Button */
42
+ .mra-fab {
43
+ width: 64px;
44
+ height: 64px;
45
+ border-radius: 9999px;
46
+ background-color: var(--ai-primary, #2563eb);
47
+ border: none;
48
+ cursor: pointer;
49
+ box-shadow: 0 10px 15px -3px rgb(0 0 0 / 0.2), 0 4px 6px -4px rgb(0 0 0 / 0.2);
50
+ display: flex;
51
+ align-items: center;
52
+ justify-content: center;
53
+ transition: transform 0.2s ease-in-out;
54
+ }
55
+ .mra-fab:hover {
56
+ transform: scale(1.1);
57
+ }
58
+
59
+ /* Chat Window Container (when not fullscreen) */
60
+ .mra-chat-window-container {
61
+ position: absolute;
62
+ bottom: calc(100% + 1rem);
63
+ right: 0;
64
+ opacity: 0;
65
+ transform: translateY(20px);
66
+ transition: opacity 0.3s ease, transform 0.3s ease;
67
+ pointer-events: none;
68
+ /* (اصلاح کلیدی) عرض را به این کانتینر منتقل می‌کنیم */
69
+ width: 32rem; /* معادل max-w-lg */
70
+ max-width: calc(100vw - 4rem); /* جلوگیری از سرریز شدن در صفحات کوچک */
71
+ }
72
+
73
+ .mra-chat-window-container--open {
74
+ opacity: 1;
75
+ transform: translateY(0);
76
+ pointer-events: auto;
77
+ }
78
+
79
+
3
80
  /* === ChatWindow Styles === */
4
81
  .mra-chat-window {
5
82
  display: flex;
6
83
  flex-direction: column;
7
84
  height: 500px;
8
85
  width: 100%;
9
- max-width: 28rem; /* max-w-md */
10
- border-radius: 0.75rem; /* rounded-xl */
86
+ /* (اصلاح کلیدی) max-width را از اینجا حذف می‌کنیم چون توسط والد کنترل می‌شود */
87
+ border-radius: 0.75rem;
11
88
  border: 1px solid var(--ai-border, #e5e7eb);
12
89
  background-color: var(--ai-bg, #ffffff);
13
90
  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 */
91
+ box-shadow: 0 10px 15px -3px rgb(0 0 0 / 0.1), 0 4px 6px -4px rgb(0 0 0 / 0.1);
15
92
  position: relative;
16
93
  font-family: inherit;
17
94
  font-size: 1rem;
18
95
  line-height: 1.5rem;
19
96
  box-sizing: border-box;
97
+ transition: all 0.3s ease-in-out;
20
98
  }
21
99
 
22
100
  .mra-header {
23
101
  display: flex;
24
102
  align-items: center;
25
- gap: 0.5rem; /* gap-2 */
26
- padding: 1rem; /* px-4 py-4 */
103
+ justify-content: space-between;
104
+ gap: 0.5rem;
105
+ padding: 1rem;
27
106
  border-bottom: 1px solid var(--ai-border, #e5e7eb);
28
- background-color: #f9fafb; /* bg-gray-50 */
107
+ background-color: #f9fafb;
108
+ }
109
+
110
+ .mra-header-title-group {
111
+ display: flex;
112
+ align-items: center;
113
+ gap: 0.5rem;
29
114
  }
30
115
 
31
116
  .mra-title {
32
- font-weight: 600;
33
- color: #1f2937;
117
+ font-weight: 600;
118
+ color: #1f2937;
34
119
  }
35
120
 
121
+ .mra-header-icon-button {
122
+ padding: 0.25rem;
123
+ border-radius: 0.25rem;
124
+ background: transparent;
125
+ border: none;
126
+ cursor: pointer;
127
+ color: #6b7280;
128
+ transition: background-color 0.2s, color 0.2s;
129
+ }
36
130
 
131
+ .mra-header-icon-button:hover {
132
+ background-color: #e5e7eb;
133
+ color: #1f2937;
134
+ }
135
+
136
+ /* === MessageList Styles === */
37
137
  .mra-message-list {
38
138
  flex: 1 1 0%;
39
139
  overflow-y: auto;
40
140
  padding: 1rem;
41
141
  display: flex;
42
142
  flex-direction: column;
43
- gap: 0.75rem; /* gap-3 */
143
+ gap: 0.75rem;
44
144
  scroll-behavior: smooth;
45
145
  }
46
146
 
@@ -51,21 +151,21 @@
51
151
 
52
152
  .mra-loading-bubble {
53
153
  max-width: 80%;
54
- padding: 0.5rem 0.75rem; /* px-3 py-2 */
154
+ padding: 0.5rem 0.75rem;
55
155
  border-radius: 0.75rem;
56
156
  background-color: var(--ai-bot-bg, #f3f4f6);
57
157
  color: var(--ai-text, #1f2937);
58
- border-bottom-left-radius: 0.125rem; /* rounded-bl-sm */
158
+ border-bottom-left-radius: 0.125rem;
59
159
  display: flex;
60
- gap: 0.25rem; /* gap-1 */
160
+ gap: 0.25rem;
61
161
  align-items: center;
62
162
  }
63
163
 
64
164
  .mra-loading-dot {
65
- width: 0.375rem; /* w-1.5 */
66
- height: 0.375rem; /* h-1.5 */
67
- background-color: #9ca3af; /* bg-gray-400 */
68
- border-radius: 9999px; /* rounded-full */
165
+ width: 0.375rem;
166
+ height: 0.375rem;
167
+ background-color: #9ca3af;
168
+ border-radius: 9999px;
69
169
  animation: bounce 1s infinite;
70
170
  }
71
171
 
@@ -96,18 +196,18 @@
96
196
  max-width: 80%;
97
197
  padding: 0.5rem 0.75rem;
98
198
  border-radius: 0.75rem;
99
- font-size: 0.875rem; /* text-sm */
199
+ font-size: 0.875rem;
100
200
  word-wrap: break-word;
101
201
  }
102
202
  .mra-bubble-user {
103
203
  background-color: var(--ai-user-bg, #dbeafe);
104
204
  color: var(--ai-user-text, #1e40af);
105
- border-bottom-right-radius: 0.125rem; /* rounded-br-sm */
205
+ border-bottom-right-radius: 0.125rem;
106
206
  }
107
207
  .mra-bubble-bot {
108
208
  background-color: var(--ai-bot-bg, #f3f4f6);
109
209
  color: var(--ai-text, #1f2937);
110
- border-bottom-left-radius: 0.125rem; /* rounded-bl-sm */
210
+ border-bottom-left-radius: 0.125rem;
111
211
  }
112
212
 
113
213
  /* === ChatInput Styles === */
@@ -117,7 +217,6 @@
117
217
  padding: 0.75rem;
118
218
  border-top: 1px solid var(--ai-border, #e5e7eb);
119
219
  background-color: var(--ai-bg, #ffffff);
120
- /* این خط جدید برای تراز کردن دکمه با textarea است */
121
220
  align-items: flex-end;
122
221
  }
123
222
 
@@ -129,13 +228,11 @@
129
228
  outline: none;
130
229
  font-family: inherit;
131
230
  color: var(--ai-text, #1f2937);
132
- /* === تغییرات و اضافات برای textarea === */
133
- resize: none; /* غیرفعال کردن تغییر سایز دستی */
134
- max-height: 120px; /* حداکثر ارتفاع قبل از نمایش اسکرول‌بار (تقریباً 5 خط) */
135
- overflow-y: auto; /* نمایش اسکرول‌بار در صورت نیاز */
136
- line-height: 1.5; /* بهبود خوانایی متن چندخطی */
231
+ resize: none;
232
+ max-height: 120px;
233
+ overflow-y: auto;
234
+ line-height: 1.5;
137
235
  }
138
-
139
236
  .mra-input-field::placeholder {
140
237
  color: var(--ai-text-secondary, #6b7280);
141
238
  }
@@ -157,11 +254,9 @@
157
254
  color: var(--ai-primary-fg, #ffffff);
158
255
  border: none;
159
256
  cursor: pointer;
160
- /* این خط جدید برای تراز کردن دکمه است */
161
257
  align-self: flex-end;
162
- height: 38px; /* ارتفاع ثابت برای هم‌ترازی با اولین ردیف textarea */
258
+ height: 38px;
163
259
  }
164
-
165
260
  .mra-send-button:hover {
166
261
  opacity: 0.9;
167
262
  }
@@ -170,15 +265,16 @@
170
265
  cursor: not-allowed;
171
266
  }
172
267
 
268
+ /* === Footer Styles === */
173
269
  .mra-footer {
174
- padding: 0.5rem 0.75rem;
270
+ padding: 0.5rem 0.75rem;
175
271
  border-top: 1px solid var(--ai-border, #e5e7eb);
176
- background-color: #f9fafb;
272
+ background-color: #f9fafb;
177
273
  display: flex;
178
274
  justify-content: space-between;
179
275
  align-items: center;
180
276
  font-size: 0.75rem;
181
- color: #6b7280;
277
+ color: #6b7280;
182
278
  }
183
279
 
184
280
  .mra-footer-links {
@@ -188,71 +284,11 @@
188
284
  }
189
285
 
190
286
  .mra-footer-link {
191
- color: #4b5563;
287
+ color: #4b5563;
192
288
  text-decoration: none;
193
289
  transition: color 0.2s;
194
290
  }
195
291
 
196
292
  .mra-footer-link:hover {
197
293
  color: var(--ai-primary, #2563eb);
198
- }
199
-
200
- .mra-container {
201
- position: fixed;
202
- bottom: 2rem; /* 32px */
203
- right: 2rem; /* 32px */
204
- z-index: 1000;
205
- }
206
-
207
- .mra-fab {
208
- width: 64px;
209
- height: 64px;
210
- border-radius: 9999px; /* rounded-full */
211
- background-color: var(--ai-primary, #2563eb);
212
- border: none;
213
- cursor: pointer;
214
- box-shadow: 0 10px 15px -3px rgb(0 0 0 / 0.2), 0 4px 6px -4px rgb(0 0 0 / 0.2);
215
- display: flex;
216
- align-items: center;
217
- justify-content: center;
218
- transition: transform 0.2s ease-in-out;
219
- }
220
- .mra-fab:hover {
221
- transform: scale(1.1);
222
- }
223
-
224
- .mra-chat-window-container {
225
- position: absolute;
226
- bottom: calc(100% + 1rem); /* 16px فاصله بالای دکمه */
227
- right: 0;
228
- opacity: 0;
229
- transform: translateY(20px);
230
- transition: opacity 0.3s ease, transform 0.3s ease;
231
- pointer-events: none; /* در حالت بسته قابل کلیک نیست */
232
- }
233
-
234
- .mra-chat-window-container--open {
235
- opacity: 1;
236
- transform: translateY(0);
237
- pointer-events: auto; /* در حالت باز قابل کلیک است */
238
- }
239
-
240
-
241
- /* === ChatWindow Styles === */
242
- .mra-chat-window {
243
- display: flex;
244
- flex-direction: column;
245
- height: 500px;
246
- width: 100%;
247
- max-width: 28rem; /* max-w-md */
248
- border-radius: 0.75rem; /* rounded-xl */
249
- border: 1px solid var(--ai-border, #e5e7eb);
250
- background-color: var(--ai-bg, #ffffff);
251
- overflow: hidden;
252
- box-shadow: 0 10px 15px -3px rgb(0 0 0 / 0.1), 0 4px 6px -4px rgb(0 0 0 / 0.1); /* shadow-lg */
253
- position: relative;
254
- font-family: inherit;
255
- font-size: 1rem;
256
- line-height: 1.5rem;
257
- box-sizing: border-box;
258
294
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "mehdi-akbari-ai-assistant-free",
3
- "version": "0.9.1",
3
+ "version": "0.9.3",
4
4
  "description": "Professional AI Chatbot Library with self-contained CSS styles",
5
5
  "main": "./dist/index.js",
6
6
  "module": "./dist/index.mjs",