mehdi-ai-assistant 0.0.1 → 0.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md ADDED
@@ -0,0 +1,109 @@
1
+ <div align="center">
2
+ <h1>mehdi-ai-assistant 🤖 Powered By Mehdi Akbari</h1>
3
+ <p>یک کامپوننت چت‌بات هوشمند، زیبا و آماده برای پروژه‌های React و Next.js که با LangChain و Groq قدرت گرفته است.</p>
4
+
5
+ <p>
6
+ <a href="https://www.npmjs.com/package/mehdi-ai-assistant"><img src="https://img.shields.io/npm/v/mehdi-ai-assistant" alt="NPM Version"></a>
7
+ <a href="https://www.npmjs.com/package/mehdi-ai-assistant"><img src="https://img.shields.io/npm/l/mehdi-ai-assistant" alt="License"></a>
8
+ <a href="https://www.npmjs.com/package/mehdi-ai-assistant"><img src="https://img.shields.io/npm/dt/mehdi-ai-assistant" alt="NPM Downloads"></a>
9
+ </p>
10
+ </div>
11
+
12
+ ## ✨ ویژگی‌ها
13
+
14
+ - **نصب و استفاده آسان:** در کمتر از ۵ دقیقه ربات را به پروژه خود اضافه کنید.
15
+ - **امنیت بالا:** کلید API شما در سمت سرور محفوظ می‌ماند و هرگز به مرورگر کاربر ارسال نمی‌شود.
16
+ - **سرعت فوق‌العاده:** با استفاده از مدل‌های بهینه شده در Groq، پاسخ‌ها به سرعت تولید می‌شوند.
17
+ - **قابلیت شخصی‌سازی:** به راحتی رنگ‌ها و استایل ربات را با وب‌سایت خود هماهنگ کنید.
18
+ - **سبک و کم‌حجم:** بدون وابستگی‌های سنگین و اضافی.
19
+
20
+ ## 🚀 نصب
21
+
22
+ برای نصب پکیج، از دستور زیر استفاده کنید:
23
+
24
+ ```bash
25
+ npm install mehdi-ai-assistant
26
+ 💡 راهنمای سریع (Quick Start)
27
+ برای استفاده از این پکیج در یک پروژه Next.js (App Router)، مراحل زیر را دنبال کنید.
28
+ قدم ۱: ساخت API Endpoint (سمت سرور)
29
+ برای حفظ امنیت کلید API، منطق ربات در سرور اجرا می‌شود.
30
+ ۱. یک فایل در مسیر src/app/api/chat/route.ts بسازید.
31
+ ۲. کدهای زیر را داخل آن قرار دهید:
32
+ code
33
+ TypeScript
34
+ // src/app/api/chat/route.ts
35
+ import { NextResponse } from 'next/server';
36
+ import { AiRobot } from 'mehdi-ai-assistant';
37
+
38
+ export async function POST(req: Request) {
39
+ try {
40
+ const { messages } = await req.json();
41
+
42
+ const bot = new AiRobot({
43
+ apiKey: process.env.GROQ_API_KEY!,
44
+ model: "llama3-8b-8192",
45
+ systemPrompt: "You are a helpful and friendly assistant."
46
+ });
47
+
48
+ const responseContent = await bot.chat(messages);
49
+ return NextResponse.json({ content: responseContent });
50
+
51
+ } catch (error) {
52
+ console.error(error);
53
+ return NextResponse.json({ error: 'Internal Server Error' }, { status: 500 });
54
+ }
55
+ }
56
+ ۳. کلید API خود را در فایل .env.local در ریشه پروژه اضافه کنید:
57
+ code
58
+ Env
59
+ # .env.local
60
+ GROQ_API_KEY=gsk_...
61
+ قدم ۲: اضافه کردن کامپوننت به صفحه (سمت کلاینت)
62
+ حالا کامپوننت ChatBot را در صفحه مورد نظر خود قرار دهید.
63
+ code
64
+ Tsx
65
+ // src/app/page.tsx
66
+ "use client";
67
+
68
+ import { ChatBot } from "mehdi-ai-assistant/react";
69
+ import "mehdi-ai-assistant/dist/react.css";
70
+
71
+ export default function Home() {
72
+ return (
73
+ <div className="flex h-screen items-center justify-center bg-gray-100">
74
+ <div className="w-full max-w-md rounded-xl border bg-white shadow-xl">
75
+ <ChatBot
76
+ apiEndpoint="/api/chat"
77
+ title="دستیار هوشمند"
78
+ welcomeMessage="سلام! چطور می‌توانم کمکتان کنم؟"
79
+ />
80
+ </div>
81
+ </div>
82
+ );
83
+ }
84
+ تمام! ربات شما آماده استفاده است.
85
+ 🎨 شخصی‌سازی استایل
86
+ شما می‌توانید به راحتی رنگ‌های اصلی ربات را با استفاده از متغیرهای CSS (CSS Variables) تغییر دهید. کافیست در فایل CSS گلوبال پروژه خود، این متغیرها را بازنویسی کنید:
87
+ code
88
+ CSS
89
+ /* In your global.css */
90
+ :root {
91
+ --ai-primary: #007bff; /* رنگ اصلی (دکمه ارسال) */
92
+ --ai-primary-fg: #ffffff; /* رنگ متن روی دکمه */
93
+ --ai-user-bg: #007bff; /* رنگ حباب پیام کاربر */
94
+ --ai-user-text: #ffffff; /* رنگ متن پیام کاربر */
95
+ --ai-bot-bg: #f1f1f1; /* رنگ حباب پیام ربات */
96
+ }```
97
+
98
+ ## ⚙️ پراپ‌های کامپوننت (API)
99
+
100
+ | پراپ | تایپ | الزامی | پیش‌فرض | توضیحات |
101
+ |----------------|-----------|:------:|---------------------------|-------------------------------------------|
102
+ | `apiEndpoint` | `string` | ✅ | - | آدرس API که در قدم ۱ ساختید. |
103
+ | `title` | `string` | ❌ | `"AI Assistant"` | عنوانی که در بالای پنجره چت نمایش داده می‌شود. |
104
+ | `welcomeMessage`| `string` | ❌ | "سلام! چطور..." | اولین پیامی که ربات به کاربر نشان می‌دهد. |
105
+
106
+
107
+ ## 📄 لایسنس
108
+
109
+ این پروژه تحت لایسنس [ISC](https://opensource.org/licenses/ISC) منتشر شده است.
package/dist/react.css CHANGED
@@ -1,14 +1,14 @@
1
- /* src/styles/chat.module.css */
1
+ /* src/components/ChatWindow/ChatWindow.module.css */
2
2
  .container {
3
3
  --ai-primary: #2563eb;
4
4
  --ai-primary-fg: #ffffff;
5
5
  --ai-bg: #ffffff;
6
- --ai-border: #e5e7eb;
6
+ --ai-bot-bg: #f3f4f6;
7
+ --ai-user-bg: var(--ai-primary);
7
8
  --ai-text: #1f2937;
8
9
  --ai-text-secondary: #6b7280;
9
- --ai-bot-bg: #f3f4f6;
10
- --ai-user-bg: #2563eb;
11
- --ai-user-text: #ffffff;
10
+ --ai-user-text: var(--ai-primary-fg);
11
+ --ai-border: #e5e7eb;
12
12
  font-family: inherit;
13
13
  font-size: 16px;
14
14
  line-height: 1.5;
@@ -24,9 +24,11 @@
24
24
  border: 1px solid var(--ai-border);
25
25
  border-radius: 12px;
26
26
  overflow: hidden;
27
- box-shadow: 0 4px 6px -1px rgba(0, 0, 0, 0.1);
27
+ box-shadow: 0 4px 6px -1px rgba(0, 0, 0, 0.1), 0 2px 4px -2px rgba(0, 0, 0, 0.1);
28
28
  position: relative;
29
29
  }
30
+
31
+ /* src/components/MessageList/MessageList.module.css */
30
32
  .messageList {
31
33
  flex: 1;
32
34
  overflow-y: auto;
@@ -36,6 +38,34 @@
36
38
  gap: 12px;
37
39
  scroll-behavior: smooth;
38
40
  }
41
+ .loading {
42
+ display: flex;
43
+ gap: 4px;
44
+ padding: 4px;
45
+ }
46
+ .dot {
47
+ width: 6px;
48
+ height: 6px;
49
+ background-color: #9ca3af;
50
+ border-radius: 50%;
51
+ animation: bounce 1.4s infinite ease-in-out both;
52
+ }
53
+ .dot:nth-child(1) {
54
+ animation-delay: -0.32s;
55
+ }
56
+ .dot:nth-child(2) {
57
+ animation-delay: -0.16s;
58
+ }
59
+ @keyframes bounce {
60
+ 0%, 80%, 100% {
61
+ transform: scale(0);
62
+ }
63
+ 40% {
64
+ transform: scale(1);
65
+ }
66
+ }
67
+
68
+ /* src/components/MessageBubble/MessageBubble.module.css */
39
69
  .messageRow {
40
70
  display: flex;
41
71
  width: 100%;
@@ -54,36 +84,38 @@
54
84
  word-wrap: break-word;
55
85
  }
56
86
  .bubble.user {
57
- background-color: var(--ai-user-bg);
58
- color: var(--ai-user-text);
87
+ background-color: var(--ai-user-bg, #2563eb);
88
+ color: var(--ai-user-text, #ffffff);
59
89
  border-bottom-right-radius: 2px;
60
90
  }
61
91
  .bubble.assistant {
62
- background-color: var(--ai-bot-bg);
63
- color: var(--ai-text);
92
+ background-color: var(--ai-bot-bg, #f3f4f6);
93
+ color: var(--ai-text, #1f2937);
64
94
  border-bottom-left-radius: 2px;
65
95
  }
96
+
97
+ /* src/components/ChatInput/ChatInput.module.css */
66
98
  .inputArea {
67
99
  padding: 12px;
68
- border-top: 1px solid var(--ai-border);
100
+ border-top: 1px solid var(--ai-border, #e5e7eb);
69
101
  display: flex;
70
102
  gap: 8px;
71
- background-color: var(--ai-bg);
103
+ background-color: var(--ai-bg, #ffffff);
72
104
  }
73
105
  .input {
74
106
  flex: 1;
75
107
  padding: 8px 12px;
76
- border: 1px solid var(--ai-border);
108
+ border: 1px solid var(--ai-border, #e5e7eb);
77
109
  border-radius: 8px;
78
110
  outline: none;
79
111
  font-family: inherit;
80
112
  }
81
113
  .input:focus {
82
- border-color: var(--ai-primary);
114
+ border-color: var(--ai-primary, #2563eb);
83
115
  }
84
116
  .sendButton {
85
- background-color: var(--ai-primary);
86
- color: var(--ai-primary-fg);
117
+ background-color: var(--ai-primary, #2563eb);
118
+ color: var(--ai-primary-fg, #ffffff);
87
119
  border: none;
88
120
  border-radius: 8px;
89
121
  padding: 8px 12px;
@@ -97,30 +129,4 @@
97
129
  opacity: 0.5;
98
130
  cursor: not-allowed;
99
131
  }
100
- .loading {
101
- display: flex;
102
- gap: 4px;
103
- padding: 4px;
104
- }
105
- .dot {
106
- width: 6px;
107
- height: 6px;
108
- background-color: #9ca3af;
109
- border-radius: 50%;
110
- animation: bounce 1.4s infinite ease-in-out both;
111
- }
112
- .dot:nth-child(1) {
113
- animation-delay: -0.32s;
114
- }
115
- .dot:nth-child(2) {
116
- animation-delay: -0.16s;
117
- }
118
- @keyframes bounce {
119
- 0%, 80%, 100% {
120
- transform: scale(0);
121
- }
122
- 40% {
123
- transform: scale(1);
124
- }
125
- }
126
132
  /*# sourceMappingURL=react.css.map */
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/styles/chat.module.css"],"sourcesContent":["/* src/styles/chat.module.css */\r\n\r\n/* تعریف متغیرها برای اینکه کاربر بتواند رنگ‌ها را شخصی‌سازی کند */\r\n.container {\r\n /* رنگ‌های پیش‌فرض - کاربر می‌تواند این‌ها را در فایل CSS خود بازنویسی کند */\r\n --ai-primary: #2563eb; /* رنگ آبی استاندارد */\r\n --ai-primary-fg: #ffffff; /* رنگ متن روی دکمه‌ها */\r\n --ai-bg: #ffffff; /* رنگ پس‌زمینه چت */\r\n --ai-border: #e5e7eb; /* رنگ حاشیه */\r\n --ai-text: #1f2937; /* رنگ متن اصلی */\r\n --ai-text-secondary: #6b7280; /* رنگ متن فرعی */\r\n --ai-bot-bg: #f3f4f6; /* رنگ حباب پیام ربات */\r\n --ai-user-bg: #2563eb; /* رنگ حباب پیام کاربر */\r\n --ai-user-text: #ffffff; /* رنگ متن پیام کاربر */\r\n \r\n font-family: inherit; /* از فونت وبسایت کاربر ارث‌بری می‌کند */\r\n font-size: 16px;\r\n line-height: 1.5;\r\n box-sizing: border-box;\r\n}\r\n\r\n/* کانتینر اصلی چت */\r\n.chatWindow {\r\n display: flex;\r\n flex-direction: column;\r\n height: 500px;\r\n width: 100%;\r\n max-width: 400px;\r\n background-color: var(--ai-bg);\r\n border: 1px solid var(--ai-border);\r\n border-radius: 12px;\r\n overflow: hidden;\r\n box-shadow: 0 4px 6px -1px rgba(0, 0, 0, 0.1);\r\n position: relative;\r\n}\r\n\r\n/* لیست پیام‌ها */\r\n.messageList {\r\n flex: 1;\r\n overflow-y: auto;\r\n padding: 16px;\r\n display: flex;\r\n flex-direction: column;\r\n gap: 12px;\r\n scroll-behavior: smooth;\r\n}\r\n\r\n/* استایل هر پیام */\r\n.messageRow {\r\n display: flex;\r\n width: 100%;\r\n}\r\n\r\n.messageRow.user {\r\n justify-content: flex-end;\r\n}\r\n\r\n.messageRow.assistant {\r\n justify-content: flex-start;\r\n}\r\n\r\n.bubble {\r\n max-width: 80%;\r\n padding: 8px 12px;\r\n border-radius: 12px;\r\n font-size: 0.95em;\r\n word-wrap: break-word;\r\n}\r\n\r\n.bubble.user {\r\n background-color: var(--ai-user-bg);\r\n color: var(--ai-user-text);\r\n border-bottom-right-radius: 2px;\r\n}\r\n\r\n.bubble.assistant {\r\n background-color: var(--ai-bot-bg);\r\n color: var(--ai-text);\r\n border-bottom-left-radius: 2px;\r\n}\r\n\r\n/* ناحیه ورودی متن */\r\n.inputArea {\r\n padding: 12px;\r\n border-top: 1px solid var(--ai-border);\r\n display: flex;\r\n gap: 8px;\r\n background-color: var(--ai-bg);\r\n}\r\n\r\n.input {\r\n flex: 1;\r\n padding: 8px 12px;\r\n border: 1px solid var(--ai-border);\r\n border-radius: 8px;\r\n outline: none;\r\n font-family: inherit;\r\n}\r\n\r\n.input:focus {\r\n border-color: var(--ai-primary);\r\n}\r\n\r\n.sendButton {\r\n background-color: var(--ai-primary);\r\n color: var(--ai-primary-fg);\r\n border: none;\r\n border-radius: 8px;\r\n padding: 8px 12px;\r\n cursor: pointer;\r\n display: flex;\r\n align-items: center;\r\n justify-content: center;\r\n transition: opacity 0.2s;\r\n}\r\n\r\n.sendButton:disabled {\r\n opacity: 0.5;\r\n cursor: not-allowed;\r\n}\r\n\r\n.loading {\r\n display: flex;\r\n gap: 4px;\r\n padding: 4px;\r\n}\r\n\r\n.dot {\r\n width: 6px;\r\n height: 6px;\r\n background-color: #9ca3af;\r\n border-radius: 50%;\r\n animation: bounce 1.4s infinite ease-in-out both;\r\n}\r\n\r\n.dot:nth-child(1) { animation-delay: -0.32s; }\r\n.dot:nth-child(2) { animation-delay: -0.16s; }\r\n\r\n@keyframes bounce {\r\n 0%, 80%, 100% { transform: scale(0); }\r\n 40% { transform: scale(1); }\r\n}"],"mappings":";AAGA,CAAC;AAEC,gBAAc;AACd,mBAAiB;AACjB,WAAS;AACT,eAAa;AACb,aAAW;AACX,uBAAqB;AACrB,eAAa;AACb,gBAAc;AACd,kBAAgB;AAEhB,eAAa;AACb,aAAW;AACX,eAAa;AACb,cAAY;AACd;AAGA,CAAC;AACC,WAAS;AACT,kBAAgB;AAChB,UAAQ;AACR,SAAO;AACP,aAAW;AACX,oBAAkB,IAAI;AACtB,UAAQ,IAAI,MAAM,IAAI;AACtB,iBAAe;AACf,YAAU;AACV,cAAY,EAAE,IAAI,IAAI,KAAK,KAAK,CAAC,EAAE,CAAC,EAAE,CAAC,EAAE;AACzC,YAAU;AACZ;AAGA,CAAC;AACC,QAAM;AACN,cAAY;AACZ,WAAS;AACT,WAAS;AACT,kBAAgB;AAChB,OAAK;AACL,mBAAiB;AACnB;AAGA,CAAC;AACC,WAAS;AACT,SAAO;AACT;AAEA,CALC,UAKU,CAAC;AACV,mBAAiB;AACnB;AAEA,CATC,UASU,CAAC;AACV,mBAAiB;AACnB;AAEA,CAAC;AACC,aAAW;AACX,WAAS,IAAI;AACb,iBAAe;AACf,aAAW;AACX,aAAW;AACb;AAEA,CARC,MAQM,CAhBK;AAiBV,oBAAkB,IAAI;AACtB,SAAO,IAAI;AACX,8BAA4B;AAC9B;AAEA,CAdC,MAcM,CAlBK;AAmBV,oBAAkB,IAAI;AACtB,SAAO,IAAI;AACX,6BAA2B;AAC7B;AAGA,CAAC;AACC,WAAS;AACT,cAAY,IAAI,MAAM,IAAI;AAC1B,WAAS;AACT,OAAK;AACL,oBAAkB,IAAI;AACxB;AAEA,CAAC;AACC,QAAM;AACN,WAAS,IAAI;AACb,UAAQ,IAAI,MAAM,IAAI;AACtB,iBAAe;AACf,WAAS;AACT,eAAa;AACf;AAEA,CATC,KASK;AACJ,gBAAc,IAAI;AACpB;AAEA,CAAC;AACC,oBAAkB,IAAI;AACtB,SAAO,IAAI;AACX,UAAQ;AACR,iBAAe;AACf,WAAS,IAAI;AACb,UAAQ;AACR,WAAS;AACT,eAAa;AACb,mBAAiB;AACjB,cAAY,QAAQ;AACtB;AAEA,CAbC,UAaU;AACT,WAAS;AACT,UAAQ;AACV;AAEA,CAAC;AACC,WAAS;AACT,OAAK;AACL,WAAS;AACX;AAEA,CAAC;AACC,SAAO;AACP,UAAQ;AACR,oBAAkB;AAClB,iBAAe;AACf,aAAW,OAAO,KAAK,SAAS,YAAY;AAC9C;AAEA,CARC,GAQG;AAAgB,mBAAiB;AAAQ;AAC7C,CATC,GASG;AAAgB,mBAAiB;AAAQ;AAE7C,WANa;AAOX;AAAgB,eAAW,MAAM;AAAI;AACrC;AAAM,eAAW,MAAM;AAAI;AAC7B;","names":[]}
1
+ {"version":3,"sources":["../src/components/ChatWindow/ChatWindow.module.css","../src/components/MessageList/MessageList.module.css","../src/components/MessageBubble/MessageBubble.module.css","../src/components/ChatInput/ChatInput.module.css"],"sourcesContent":["/* \r\n این فایل استایل‌های اصلی و کانتینر چت را تعریف می‌کند.\r\n متغیرهای CSS به کاربر اجازه می‌دهند تا به راحتی ظاهر ربات را شخصی‌سازی کند.\r\n*/\r\n\r\n.container {\r\n /* ======== متغیرهای قابل شخصی‌سازی ======== */\r\n \r\n /* رنگ اصلی (دکمه ارسال، حباب کاربر) */\r\n --ai-primary: #2563eb;\r\n /* رنگ متن روی المان‌های اصلی */\r\n --ai-primary-fg: #ffffff;\r\n\r\n /* رنگ‌های پس‌زمینه */\r\n --ai-bg: #ffffff;\r\n --ai-bot-bg: #f3f4f6;\r\n --ai-user-bg: var(--ai-primary);\r\n\r\n /* رنگ‌های متن */\r\n --ai-text: #1f2937;\r\n --ai-text-secondary: #6b7280;\r\n --ai-user-text: var(--ai-primary-fg);\r\n\r\n /* رنگ حاشیه و جداکننده‌ها */\r\n --ai-border: #e5e7eb;\r\n\r\n /* ======================================== */\r\n\r\n /* ارث‌بری فونت از سایت میزبان برای هماهنگی بیشتر */\r\n font-family: inherit; \r\n font-size: 16px;\r\n line-height: 1.5;\r\n box-sizing: border-box;\r\n}\r\n\r\n/* کانتینر اصلی پنجره چت */\r\n.chatWindow {\r\n display: flex;\r\n flex-direction: column;\r\n height: 500px; /* ارتفاع پیش‌فرض، کاربر می‌تواند تغییر دهد */\r\n width: 100%;\r\n max-width: 400px;\r\n background-color: var(--ai-bg);\r\n border: 1px solid var(--ai-border);\r\n border-radius: 12px;\r\n overflow: hidden; /* برای اینکه گوشه‌های گرد درست نمایش داده شوند */\r\n box-shadow: 0 4px 6px -1px rgba(0, 0, 0, 0.1), 0 2px 4px -2px rgba(0, 0, 0, 0.1);\r\n position: relative;\r\n}",".messageList {\r\nflex: 1;\r\noverflow-y: auto;\r\npadding: 16px;\r\ndisplay: flex;\r\nflex-direction: column;\r\ngap: 12px;\r\nscroll-behavior: smooth;\r\n}\r\n/* این استایل‌ها برای انیمیشن لودینگ هستند */\r\n.loading {\r\ndisplay: flex;\r\ngap: 4px;\r\npadding: 4px;\r\n}\r\n.dot {\r\nwidth: 6px;\r\nheight: 6px;\r\nbackground-color: #9ca3af;\r\nborder-radius: 50%;\r\nanimation: bounce 1.4s infinite ease-in-out both;\r\n}\r\n.dot:nth-child(1) { animation-delay: -0.32s; }\r\n.dot:nth-child(2) { animation-delay: -0.16s; }\r\n@keyframes bounce {\r\n0%, 80%, 100% { transform: scale(0); }\r\n40% { transform: scale(1); }\r\n}",".messageRow {\r\n display: flex;\r\n width: 100%;\r\n}\r\n.messageRow.user {\r\n justify-content: flex-end;\r\n}\r\n.messageRow.assistant {\r\n justify-content: flex-start;\r\n}\r\n.bubble {\r\n max-width: 80%;\r\n padding: 8px 12px;\r\n border-radius: 12px;\r\n font-size: 0.95em;\r\n word-wrap: break-word;\r\n}\r\n.bubble.user {\r\n background-color: var(--ai-user-bg, #2563eb);\r\n color: var(--ai-user-text, #ffffff);\r\n border-bottom-right-radius: 2px;\r\n}\r\n.bubble.assistant {\r\n background-color: var(--ai-bot-bg, #f3f4f6);\r\n color: var(--ai-text, #1f2937);\r\n border-bottom-left-radius: 2px;\r\n}","/* src/components/ChatInput/ChatInput.module.css */\r\n.inputArea {\r\n padding: 12px;\r\n border-top: 1px solid var(--ai-border, #e5e7eb);\r\n display: flex;\r\n gap: 8px;\r\n background-color: var(--ai-bg, #ffffff);\r\n}\r\n.input {\r\n flex: 1;\r\n padding: 8px 12px;\r\n border: 1px solid var(--ai-border, #e5e7eb);\r\n border-radius: 8px;\r\n outline: none;\r\n font-family: inherit;\r\n}\r\n.input:focus {\r\n border-color: var(--ai-primary, #2563eb);\r\n}\r\n.sendButton {\r\n background-color: var(--ai-primary, #2563eb);\r\n color: var(--ai-primary-fg, #ffffff);\r\n border: none;\r\n border-radius: 8px;\r\n padding: 8px 12px;\r\n cursor: pointer;\r\n display: flex;\r\n align-items: center;\r\n justify-content: center;\r\n transition: opacity 0.2s;\r\n}\r\n.sendButton:disabled {\r\n opacity: 0.5;\r\n cursor: not-allowed;\r\n}"],"mappings":";AAKA,CAAC;AAIC,gBAAc;AAEd,mBAAiB;AAGjB,WAAS;AACT,eAAa;AACb,gBAAc,IAAI;AAGlB,aAAW;AACX,uBAAqB;AACrB,kBAAgB,IAAI;AAGpB,eAAa;AAKb,eAAa;AACb,aAAW;AACX,eAAa;AACb,cAAY;AACd;AAGA,CAAC;AACC,WAAS;AACT,kBAAgB;AAChB,UAAQ;AACR,SAAO;AACP,aAAW;AACX,oBAAkB,IAAI;AACtB,UAAQ,IAAI,MAAM,IAAI;AACtB,iBAAe;AACf,YAAU;AACV,cAAY,EAAE,IAAI,IAAI,KAAK,KAAK,CAAC,EAAE,CAAC,EAAE,CAAC,EAAE,IAAI,EAAE,EAAE,IAAI,IAAI,KAAK,KAAK,CAAC,EAAE,CAAC,EAAE,CAAC,EAAE;AAC5E,YAAU;AACZ;;;AChDA,CAAC;AACD,QAAM;AACN,cAAY;AACZ,WAAS;AACT,WAAS;AACT,kBAAgB;AAChB,OAAK;AACL,mBAAiB;AACjB;AAEA,CAAC;AACD,WAAS;AACT,OAAK;AACL,WAAS;AACT;AACA,CAAC;AACD,SAAO;AACP,UAAQ;AACR,oBAAkB;AAClB,iBAAe;AACf,aAAW,OAAO,KAAK,SAAS,YAAY;AAC5C;AACA,CAPC,GAOG;AAAgB,mBAAiB;AAAQ;AAC7C,CARC,GAQG;AAAgB,mBAAiB;AAAQ;AAC7C,WAJW;AAKX;AAAgB,eAAW,MAAM;AAAI;AACrC;AAAM,eAAW,MAAM;AAAI;AAC3B;;;AC3BA,CAAC;AACC,WAAS;AACT,SAAO;AACT;AACA,CAJC,UAIU,CAAC;AACV,mBAAiB;AACnB;AACA,CAPC,UAOU,CAAC;AACV,mBAAiB;AACnB;AACA,CAAC;AACC,aAAW;AACX,WAAS,IAAI;AACb,iBAAe;AACf,aAAW;AACX,aAAW;AACb;AACA,CAPC,MAOM,CAbK;AAcV,oBAAkB,IAAI,YAAY,EAAE;AACpC,SAAO,IAAI,cAAc,EAAE;AAC3B,8BAA4B;AAC9B;AACA,CAZC,MAYM,CAfK;AAgBV,oBAAkB,IAAI,WAAW,EAAE;AACnC,SAAO,IAAI,SAAS,EAAE;AACtB,6BAA2B;AAC7B;;;ACzBA,CAAC;AACC,WAAS;AACT,cAAY,IAAI,MAAM,IAAI,WAAW,EAAE;AACvC,WAAS;AACT,OAAK;AACL,oBAAkB,IAAI,OAAO,EAAE;AACjC;AACA,CAAC;AACC,QAAM;AACN,WAAS,IAAI;AACb,UAAQ,IAAI,MAAM,IAAI,WAAW,EAAE;AACnC,iBAAe;AACf,WAAS;AACT,eAAa;AACf;AACA,CARC,KAQK;AACJ,gBAAc,IAAI,YAAY,EAAE;AAClC;AACA,CAAC;AACC,oBAAkB,IAAI,YAAY,EAAE;AACpC,SAAO,IAAI,eAAe,EAAE;AAC5B,UAAQ;AACR,iBAAe;AACf,WAAS,IAAI;AACb,UAAQ;AACR,WAAS;AACT,eAAa;AACb,mBAAiB;AACjB,cAAY,QAAQ;AACtB;AACA,CAZC,UAYU;AACT,WAAS;AACT,UAAQ;AACV;","names":[]}
package/dist/react.d.mts CHANGED
@@ -1,20 +1,11 @@
1
1
  import React from 'react';
2
- import { M as Message } from './index-BeDFcZll.mjs';
3
- export { A as AiRobotConfig, C as ChatResponse, R as Role } from './index-BeDFcZll.mjs';
2
+ export { A as AiRobotConfig, C as ChatResponse, M as Message, R as Role } from './index-BeDFcZll.mjs';
4
3
 
5
- interface ChatBotProps {
6
- /** آدرس ای‌پی‌آی که کاربر در پروژه خودش ساخته */
4
+ interface ChatWindowProps {
7
5
  apiEndpoint: string;
8
- /** عنوان بالای چت باکس */
9
6
  title?: string;
10
- /** پیام خوش‌آمدگویی اولیه */
11
7
  welcomeMessage?: string;
12
8
  }
13
- declare const ChatBot: React.FC<ChatBotProps>;
9
+ declare const ChatWindow: React.FC<ChatWindowProps>;
14
10
 
15
- interface MessageBubbleProps {
16
- message: Message;
17
- }
18
- declare const MessageBubble: React.FC<MessageBubbleProps>;
19
-
20
- export { ChatBot, type ChatBotProps, Message, MessageBubble };
11
+ export { ChatWindow, type ChatWindowProps };
package/dist/react.d.ts CHANGED
@@ -1,20 +1,11 @@
1
1
  import React from 'react';
2
- import { M as Message } from './index-BeDFcZll.js';
3
- export { A as AiRobotConfig, C as ChatResponse, R as Role } from './index-BeDFcZll.js';
2
+ export { A as AiRobotConfig, C as ChatResponse, M as Message, R as Role } from './index-BeDFcZll.js';
4
3
 
5
- interface ChatBotProps {
6
- /** آدرس ای‌پی‌آی که کاربر در پروژه خودش ساخته */
4
+ interface ChatWindowProps {
7
5
  apiEndpoint: string;
8
- /** عنوان بالای چت باکس */
9
6
  title?: string;
10
- /** پیام خوش‌آمدگویی اولیه */
11
7
  welcomeMessage?: string;
12
8
  }
13
- declare const ChatBot: React.FC<ChatBotProps>;
9
+ declare const ChatWindow: React.FC<ChatWindowProps>;
14
10
 
15
- interface MessageBubbleProps {
16
- message: Message;
17
- }
18
- declare const MessageBubble: React.FC<MessageBubbleProps>;
19
-
20
- export { ChatBot, type ChatBotProps, Message, MessageBubble };
11
+ export { ChatWindow, type ChatWindowProps };
package/dist/react.js CHANGED
@@ -31,75 +31,127 @@ var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: tru
31
31
  // src/react.ts
32
32
  var react_exports = {};
33
33
  __export(react_exports, {
34
- ChatBot: () => ChatBot,
35
- MessageBubble: () => MessageBubble
34
+ ChatWindow: () => ChatWindow
36
35
  });
37
36
  module.exports = __toCommonJS(react_exports);
38
37
 
39
- // src/components/ChatBot.tsx
38
+ // src/components/ChatWindow/ChatWindow.tsx
39
+ var import_react3 = require("react");
40
+ var import_clsx3 = __toESM(require("clsx"));
41
+
42
+ // src/components/ChatWindow/ChatWindow.module.css
43
+ var ChatWindow_default = {};
44
+
45
+ // src/components/MessageList/MessageList.tsx
40
46
  var import_react = require("react");
47
+ var import_clsx2 = __toESM(require("clsx"));
41
48
 
42
- // src/styles/chat.module.css
43
- var chat_default = {};
49
+ // src/components/MessageList/MessageList.module.css
50
+ var MessageList_default = {};
44
51
 
45
- // src/components/MessageBubble.tsx
52
+ // src/components/MessageBubble/MessageBubble.tsx
46
53
  var import_clsx = __toESM(require("clsx"));
54
+
55
+ // src/components/MessageBubble/MessageBubble.module.css
56
+ var MessageBubble_default = {};
57
+
58
+ // src/components/MessageBubble/MessageBubble.tsx
47
59
  var import_jsx_runtime = require("react/jsx-runtime");
48
60
  var MessageBubble = ({ message }) => {
49
61
  const isUser = message.role === "user";
50
- return /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
51
- "div",
52
- {
53
- className: (0, import_clsx.default)(
54
- chat_default.messageRow,
55
- isUser ? chat_default.user : chat_default.assistant
56
- ),
57
- children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
58
- "div",
59
- {
60
- className: (0, import_clsx.default)(
61
- chat_default.bubble,
62
- isUser ? chat_default.user : chat_default.assistant
63
- ),
64
- children: message.content
65
- }
66
- )
67
- }
68
- );
62
+ return /* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", { className: (0, import_clsx.default)(MessageBubble_default.messageRow, isUser ? MessageBubble_default.user : MessageBubble_default.assistant), children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", { className: (0, import_clsx.default)(MessageBubble_default.bubble, isUser ? MessageBubble_default.user : MessageBubble_default.assistant), children: message.content }) });
69
63
  };
70
64
 
71
- // src/components/ChatBot.tsx
72
- var import_lucide_react = require("lucide-react");
73
- var import_clsx2 = __toESM(require("clsx"));
65
+ // src/components/MessageList/MessageList.tsx
74
66
  var import_jsx_runtime2 = require("react/jsx-runtime");
75
- var ChatBot = ({
67
+ var MessageList = ({ messages, isLoading }) => {
68
+ const messagesEndRef = (0, import_react.useRef)(null);
69
+ (0, import_react.useEffect)(() => {
70
+ messagesEndRef.current?.scrollIntoView({ behavior: "smooth" });
71
+ }, [messages, isLoading]);
72
+ return /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("div", { className: MessageList_default.messageList, children: [
73
+ messages.map((msg, index) => /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(MessageBubble, { message: msg }, index)),
74
+ isLoading && /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("div", { className: (0, import_clsx2.default)(MessageList_default.messageRow, MessageList_default.assistant), children: /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("div", { className: (0, import_clsx2.default)(MessageList_default.bubble, MessageList_default.assistant, MessageList_default.loading), children: [
75
+ /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("div", { className: MessageList_default.dot }),
76
+ /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("div", { className: MessageList_default.dot }),
77
+ /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("div", { className: MessageList_default.dot })
78
+ ] }) }),
79
+ /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("div", { ref: messagesEndRef })
80
+ ] });
81
+ };
82
+
83
+ // src/components/ChatInput/ChatInput.tsx
84
+ var import_react2 = require("react");
85
+
86
+ // src/components/ChatInput/ChatInput.module.css
87
+ var ChatInput_default = {};
88
+
89
+ // src/components/ChatInput/ChatInput.tsx
90
+ var import_lucide_react = require("lucide-react");
91
+ var import_jsx_runtime3 = require("react/jsx-runtime");
92
+ var ChatInput = ({ onSendMessage, isLoading }) => {
93
+ const [inputValue, setInputValue] = (0, import_react2.useState)("");
94
+ const handleSend = () => {
95
+ if (inputValue.trim()) {
96
+ onSendMessage(inputValue);
97
+ setInputValue("");
98
+ }
99
+ };
100
+ const handleKeyDown = (e) => {
101
+ if (e.key === "Enter" && !e.shiftKey) {
102
+ e.preventDefault();
103
+ handleSend();
104
+ }
105
+ };
106
+ return /* @__PURE__ */ (0, import_jsx_runtime3.jsxs)("div", { className: ChatInput_default.inputArea, children: [
107
+ /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(
108
+ "input",
109
+ {
110
+ className: ChatInput_default.input,
111
+ value: inputValue,
112
+ onChange: (e) => setInputValue(e.target.value),
113
+ onKeyDown: handleKeyDown,
114
+ placeholder: "\u067E\u06CC\u0627\u0645 \u062E\u0648\u062F \u0631\u0627 \u0628\u0646\u0648\u06CC\u0633\u06CC\u062F...",
115
+ disabled: isLoading
116
+ }
117
+ ),
118
+ /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(
119
+ "button",
120
+ {
121
+ className: ChatInput_default.sendButton,
122
+ onClick: handleSend,
123
+ disabled: isLoading || !inputValue.trim(),
124
+ children: /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(import_lucide_react.Send, { size: 18 })
125
+ }
126
+ )
127
+ ] });
128
+ };
129
+
130
+ // src/components/ChatWindow/ChatWindow.tsx
131
+ var import_lucide_react2 = require("lucide-react");
132
+ var import_jsx_runtime4 = require("react/jsx-runtime");
133
+ var ChatWindow = ({
76
134
  apiEndpoint,
77
135
  title = "AI Assistant",
78
136
  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"
79
137
  }) => {
80
- const [messages, setMessages] = (0, import_react.useState)([]);
81
- const [inputValue, setInputValue] = (0, import_react.useState)("");
82
- const [isLoading, setIsLoading] = (0, import_react.useState)(false);
83
- const messagesEndRef = (0, import_react.useRef)(null);
84
- (0, import_react.useEffect)(() => {
138
+ const [messages, setMessages] = (0, import_react3.useState)([]);
139
+ const [isLoading, setIsLoading] = (0, import_react3.useState)(false);
140
+ (0, import_react3.useEffect)(() => {
85
141
  if (welcomeMessage && messages.length === 0) {
86
142
  setMessages([{ role: "assistant", content: welcomeMessage }]);
87
143
  }
88
144
  }, [welcomeMessage]);
89
- (0, import_react.useEffect)(() => {
90
- messagesEndRef.current?.scrollIntoView({ behavior: "smooth" });
91
- }, [messages]);
92
- const handleSendMessage = async () => {
93
- if (!inputValue.trim() || isLoading) return;
94
- const userMsg = { role: "user", content: inputValue };
95
- setMessages((prev) => [...prev, userMsg]);
96
- setInputValue("");
145
+ const handleSendMessage = async (userMessage) => {
146
+ const newUserMsg = { role: "user", content: userMessage };
147
+ const currentMessages = [...messages, newUserMsg];
148
+ setMessages(currentMessages);
97
149
  setIsLoading(true);
98
150
  try {
99
151
  const response = await fetch(apiEndpoint, {
100
152
  method: "POST",
101
153
  headers: { "Content-Type": "application/json" },
102
- body: JSON.stringify({ messages: [...messages, userMsg] })
154
+ body: JSON.stringify({ messages: currentMessages })
103
155
  });
104
156
  if (!response.ok) throw new Error("Network response was not ok");
105
157
  const data = await response.json();
@@ -107,61 +159,23 @@ var ChatBot = ({
107
159
  setMessages((prev) => [...prev, botMsg]);
108
160
  } catch (error) {
109
161
  console.error("Chat Error:", error);
110
- setMessages((prev) => [...prev, { role: "assistant", content: "\u062E\u0637\u0627\u06CC\u06CC \u0631\u062E \u062F\u0627\u062F\u0647 \u0627\u0633\u062A. \u0644\u0637\u0641\u0627\u064B \u062F\u0648\u0628\u0627\u0631\u0647 \u062A\u0644\u0627\u0634 \u06A9\u0646\u06CC\u062F." }]);
162
+ const errorMsg = { role: "assistant", content: "\u062E\u0637\u0627\u06CC\u06CC \u0631\u062E \u062F\u0627\u062F\u0647 \u0627\u0633\u062A." };
163
+ setMessages((prev) => [...prev, errorMsg]);
111
164
  } finally {
112
165
  setIsLoading(false);
113
166
  }
114
167
  };
115
- const handleKeyDown = (e) => {
116
- if (e.key === "Enter" && !e.shiftKey) {
117
- e.preventDefault();
118
- handleSendMessage();
119
- }
120
- };
121
- return (
122
- // کلاس کانتینر برای اعمال متغیرهای CSS
123
- /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("div", { className: (0, import_clsx2.default)(chat_default.container, chat_default.chatWindow), children: [
124
- /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("div", { style: { padding: "16px", borderBottom: "1px solid var(--ai-border)", display: "flex", alignItems: "center", gap: "8px", background: "#f9fafb" }, children: [
125
- /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(import_lucide_react.Bot, { size: 20 }),
126
- /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("span", { style: { fontWeight: 600 }, children: title })
127
- ] }),
128
- /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("div", { className: chat_default.messageList, children: [
129
- messages.map((msg, index) => /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(MessageBubble, { message: msg }, index)),
130
- isLoading && /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("div", { className: (0, import_clsx2.default)(chat_default.messageRow, chat_default.assistant), children: /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("div", { className: (0, import_clsx2.default)(chat_default.bubble, chat_default.assistant, chat_default.loading), children: [
131
- /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("div", { className: chat_default.dot }),
132
- /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("div", { className: chat_default.dot }),
133
- /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("div", { className: chat_default.dot })
134
- ] }) }),
135
- /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("div", { ref: messagesEndRef })
136
- ] }),
137
- /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("div", { className: chat_default.inputArea, children: [
138
- /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(
139
- "input",
140
- {
141
- className: chat_default.input,
142
- value: inputValue,
143
- onChange: (e) => setInputValue(e.target.value),
144
- onKeyDown: handleKeyDown,
145
- placeholder: "\u067E\u06CC\u0627\u0645 \u062E\u0648\u062F \u0631\u0627 \u0628\u0646\u0648\u06CC\u0633\u06CC\u062F...",
146
- disabled: isLoading
147
- }
148
- ),
149
- /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(
150
- "button",
151
- {
152
- className: chat_default.sendButton,
153
- onClick: handleSendMessage,
154
- disabled: isLoading || !inputValue.trim(),
155
- children: /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(import_lucide_react.Send, { size: 18 })
156
- }
157
- )
158
- ] })
159
- ] })
160
- );
168
+ return /* @__PURE__ */ (0, import_jsx_runtime4.jsxs)("div", { className: (0, import_clsx3.default)(ChatWindow_default.container, ChatWindow_default.chatWindow), children: [
169
+ /* @__PURE__ */ (0, import_jsx_runtime4.jsxs)("div", { style: { padding: "16px", borderBottom: "1px solid var(--ai-border)", display: "flex", alignItems: "center", gap: "8px", background: "#f9fafb" }, children: [
170
+ /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(import_lucide_react2.Bot, { size: 20 }),
171
+ /* @__PURE__ */ (0, import_jsx_runtime4.jsx)("span", { style: { fontWeight: 600 }, children: title })
172
+ ] }),
173
+ /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(MessageList, { messages, isLoading }),
174
+ /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(ChatInput, { onSendMessage: handleSendMessage, isLoading })
175
+ ] });
161
176
  };
162
177
  // Annotate the CommonJS export names for ESM import in node:
163
178
  0 && (module.exports = {
164
- ChatBot,
165
- MessageBubble
179
+ ChatWindow
166
180
  });
167
181
  //# sourceMappingURL=react.js.map
package/dist/react.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/react.ts","../src/components/ChatBot.tsx","../src/styles/chat.module.css","../src/components/MessageBubble.tsx"],"sourcesContent":["// src/react.ts\r\n\"use client\"; // 👈 این خط حیاتی است\r\n\r\nexport { ChatBot, type ChatBotProps } from \"./components/ChatBot\";\r\nexport { MessageBubble } from \"./components/MessageBubble\";\r\nexport * from \"./types\"; // تایپ‌ها در هر دو مشترک هستند","\"use client\"\r\n\r\nimport React, { useState, useRef, useEffect } from 'react';\r\nimport styles from '../styles/chat.module.css';\r\nimport { MessageBubble } from './MessageBubble';\r\nimport { Message } from '../types';\r\nimport { Send, Bot } from 'lucide-react'; // آیکون‌ها\r\nimport clsx from 'clsx';\r\n\r\nexport interface ChatBotProps {\r\n /** آدرس ای‌پی‌آی که کاربر در پروژه خودش ساخته */\r\n apiEndpoint: string;\r\n /** عنوان بالای چت باکس */\r\n title?: string;\r\n /** پیام خوش‌آمدگویی اولیه */\r\n welcomeMessage?: string;\r\n}\r\n\r\nexport const ChatBot: React.FC<ChatBotProps> = ({\r\n apiEndpoint,\r\n title = \"AI Assistant\",\r\n welcomeMessage = \"سلام! چطور می‌توانم کمکتان کنم؟\"\r\n}) => {\r\n const [messages, setMessages] = useState<Message[]>([]);\r\n const [inputValue, setInputValue] = useState(\"\");\r\n const [isLoading, setIsLoading] = useState(false);\r\n \r\n // برای اسکرول خودکار به پایین\r\n const messagesEndRef = useRef<HTMLDivElement>(null);\r\n\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 // اسکرول به پایین وقتی پیام جدید می‌آید\r\n useEffect(() => {\r\n messagesEndRef.current?.scrollIntoView({ behavior: 'smooth' });\r\n }, [messages]);\r\n\r\n const handleSendMessage = async () => {\r\n if (!inputValue.trim() || isLoading) return;\r\n\r\n const userMsg: Message = { role: 'user', content: inputValue };\r\n \r\n // 1. اضافه کردن پیام کاربر به لیست و خالی کردن اینپوت\r\n setMessages(prev => [...prev, userMsg]);\r\n setInputValue(\"\");\r\n setIsLoading(true);\r\n\r\n try {\r\n // 2. ارسال درخواست به سرور (API کاربر)\r\n const response = await fetch(apiEndpoint, {\r\n method: 'POST',\r\n headers: { 'Content-Type': 'application/json' },\r\n body: JSON.stringify({ messages: [...messages, userMsg] }),\r\n });\r\n\r\n if (!response.ok) throw new Error(\"Network response was not ok\");\r\n \r\n // نکته: اینجا فعلاً فرض می‌کنیم پاسخ متنی ساده است (بعداً استریم را اضافه می‌کنیم)\r\n const data = await response.json();\r\n \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 setMessages(prev => [...prev, { role: 'assistant', content: \"خطایی رخ داده است. لطفاً دوباره تلاش کنید.\" }]);\r\n } finally {\r\n setIsLoading(false);\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 handleSendMessage();\r\n }\r\n };\r\n\r\n return (\r\n // کلاس کانتینر برای اعمال متغیرهای CSS\r\n <div className={clsx(styles.container, styles.chatWindow)}>\r\n {/* هدر */}\r\n <div style={{ padding: '16px', borderBottom: '1px solid var(--ai-border)', display: 'flex', alignItems: 'center', gap: '8px', background: '#f9fafb' }}>\r\n <Bot size={20} />\r\n <span style={{ fontWeight: 600 }}>{title}</span>\r\n </div>\r\n\r\n {/* لیست پیام‌ها */}\r\n <div className={styles.messageList}>\r\n {messages.map((msg, index) => (\r\n <MessageBubble key={index} message={msg} />\r\n ))}\r\n {isLoading && (\r\n <div className={clsx(styles.messageRow, styles.assistant)}>\r\n <div className={clsx(styles.bubble, styles.assistant, styles.loading)}>\r\n <div className={styles.dot}></div>\r\n <div className={styles.dot}></div>\r\n <div className={styles.dot}></div>\r\n </div>\r\n </div>\r\n )}\r\n <div ref={messagesEndRef} />\r\n </div>\r\n\r\n {/* ورودی */}\r\n <div className={styles.inputArea}>\r\n <input\r\n className={styles.input}\r\n value={inputValue}\r\n onChange={(e) => setInputValue(e.target.value)}\r\n onKeyDown={handleKeyDown}\r\n placeholder=\"پیام خود را بنویسید...\"\r\n disabled={isLoading}\r\n />\r\n <button \r\n className={styles.sendButton} \r\n onClick={handleSendMessage}\r\n disabled={isLoading || !inputValue.trim()}\r\n >\r\n <Send size={18} />\r\n </button>\r\n </div>\r\n </div>\r\n );\r\n};","/* src/styles/chat.module.css */\r\n\r\n/* تعریف متغیرها برای اینکه کاربر بتواند رنگ‌ها را شخصی‌سازی کند */\r\n.container {\r\n /* رنگ‌های پیش‌فرض - کاربر می‌تواند این‌ها را در فایل CSS خود بازنویسی کند */\r\n --ai-primary: #2563eb; /* رنگ آبی استاندارد */\r\n --ai-primary-fg: #ffffff; /* رنگ متن روی دکمه‌ها */\r\n --ai-bg: #ffffff; /* رنگ پس‌زمینه چت */\r\n --ai-border: #e5e7eb; /* رنگ حاشیه */\r\n --ai-text: #1f2937; /* رنگ متن اصلی */\r\n --ai-text-secondary: #6b7280; /* رنگ متن فرعی */\r\n --ai-bot-bg: #f3f4f6; /* رنگ حباب پیام ربات */\r\n --ai-user-bg: #2563eb; /* رنگ حباب پیام کاربر */\r\n --ai-user-text: #ffffff; /* رنگ متن پیام کاربر */\r\n \r\n font-family: inherit; /* از فونت وبسایت کاربر ارث‌بری می‌کند */\r\n font-size: 16px;\r\n line-height: 1.5;\r\n box-sizing: border-box;\r\n}\r\n\r\n/* کانتینر اصلی چت */\r\n.chatWindow {\r\n display: flex;\r\n flex-direction: column;\r\n height: 500px;\r\n width: 100%;\r\n max-width: 400px;\r\n background-color: var(--ai-bg);\r\n border: 1px solid var(--ai-border);\r\n border-radius: 12px;\r\n overflow: hidden;\r\n box-shadow: 0 4px 6px -1px rgba(0, 0, 0, 0.1);\r\n position: relative;\r\n}\r\n\r\n/* لیست پیام‌ها */\r\n.messageList {\r\n flex: 1;\r\n overflow-y: auto;\r\n padding: 16px;\r\n display: flex;\r\n flex-direction: column;\r\n gap: 12px;\r\n scroll-behavior: smooth;\r\n}\r\n\r\n/* استایل هر پیام */\r\n.messageRow {\r\n display: flex;\r\n width: 100%;\r\n}\r\n\r\n.messageRow.user {\r\n justify-content: flex-end;\r\n}\r\n\r\n.messageRow.assistant {\r\n justify-content: flex-start;\r\n}\r\n\r\n.bubble {\r\n max-width: 80%;\r\n padding: 8px 12px;\r\n border-radius: 12px;\r\n font-size: 0.95em;\r\n word-wrap: break-word;\r\n}\r\n\r\n.bubble.user {\r\n background-color: var(--ai-user-bg);\r\n color: var(--ai-user-text);\r\n border-bottom-right-radius: 2px;\r\n}\r\n\r\n.bubble.assistant {\r\n background-color: var(--ai-bot-bg);\r\n color: var(--ai-text);\r\n border-bottom-left-radius: 2px;\r\n}\r\n\r\n/* ناحیه ورودی متن */\r\n.inputArea {\r\n padding: 12px;\r\n border-top: 1px solid var(--ai-border);\r\n display: flex;\r\n gap: 8px;\r\n background-color: var(--ai-bg);\r\n}\r\n\r\n.input {\r\n flex: 1;\r\n padding: 8px 12px;\r\n border: 1px solid var(--ai-border);\r\n border-radius: 8px;\r\n outline: none;\r\n font-family: inherit;\r\n}\r\n\r\n.input:focus {\r\n border-color: var(--ai-primary);\r\n}\r\n\r\n.sendButton {\r\n background-color: var(--ai-primary);\r\n color: var(--ai-primary-fg);\r\n border: none;\r\n border-radius: 8px;\r\n padding: 8px 12px;\r\n cursor: pointer;\r\n display: flex;\r\n align-items: center;\r\n justify-content: center;\r\n transition: opacity 0.2s;\r\n}\r\n\r\n.sendButton:disabled {\r\n opacity: 0.5;\r\n cursor: not-allowed;\r\n}\r\n\r\n.loading {\r\n display: flex;\r\n gap: 4px;\r\n padding: 4px;\r\n}\r\n\r\n.dot {\r\n width: 6px;\r\n height: 6px;\r\n background-color: #9ca3af;\r\n border-radius: 50%;\r\n animation: bounce 1.4s infinite ease-in-out both;\r\n}\r\n\r\n.dot:nth-child(1) { animation-delay: -0.32s; }\r\n.dot:nth-child(2) { animation-delay: -0.16s; }\r\n\r\n@keyframes bounce {\r\n 0%, 80%, 100% { transform: scale(0); }\r\n 40% { transform: scale(1); }\r\n}","// src/components/MessageBubble.tsx\r\nimport React from 'react';\r\nimport clsx from 'clsx'; // ابزاری عالی برای ترکیب کلاس‌های CSS\r\nimport styles from '../styles/chat.module.css';\r\nimport { Message } from '../types';\r\n\r\ninterface MessageBubbleProps {\r\n message: Message;\r\n}\r\n\r\nexport const MessageBubble: React.FC<MessageBubbleProps> = ({ message }) => {\r\n const isUser = message.role === 'user';\r\n\r\n return (\r\n <div\r\n className={clsx(\r\n styles.messageRow,\r\n isUser ? styles.user : styles.assistant\r\n )}\r\n >\r\n <div\r\n className={clsx(\r\n styles.bubble,\r\n isUser ? styles.user : styles.assistant\r\n )}\r\n >\r\n {/* فعلاً متن ساده را رندر می‌کنیم. بعداً می‌توانیم Markdown اضافه کنیم */}\r\n {message.content}\r\n </div>\r\n </div>\r\n );\r\n};"],"mappings":"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","names":["clsx","import_clsx","import_jsx_runtime","clsx"]}
1
+ {"version":3,"sources":["../src/react.ts","../src/components/ChatWindow/ChatWindow.tsx","../src/components/ChatWindow/ChatWindow.module.css","../src/components/MessageList/MessageList.tsx","../src/components/MessageList/MessageList.module.css","../src/components/MessageBubble/MessageBubble.tsx","../src/components/MessageBubble/MessageBubble.module.css","../src/components/ChatInput/ChatInput.tsx","../src/components/ChatInput/ChatInput.module.css"],"sourcesContent":["\"use client\";\r\n\r\n/**\r\n * این فایل نقطه ورود (Entry Point) برای تمام کامپوننت‌های React پکیج است.\r\n * هر کامپوننتی که کاربر باید در فرانت‌اند استفاده کند، از اینجا صادر (export) می‌شود.\r\n * دستور \"use client\" تضمین می‌کند که این کدها فقط در مرورگر اجرا شوند.\r\n */\r\n\r\n// ۱. کامپوننت اصلی و سطح بالا که کاربر در صفحه خود قرار می‌دهد.\r\n// ما ChatWindowProps را هم اکسپورت می‌کنیم تا کاربر بتواند تایپ‌های آن را ببیند.\r\nexport { ChatWindow, type ChatWindowProps } from \"./components/ChatWindow/ChatWindow\";\r\n\r\n// ۲. اکسپورت تایپ‌های عمومی (مثل ساختار پیام) تا کاربر بتواند از آنها استفاده کند.\r\nexport * from \"./types\";","// src/components/ChatWindow/ChatWindow.tsx\r\nimport React, { useState, useEffect } from 'react';\r\nimport clsx from 'clsx';\r\nimport styles from './ChatWindow.module.css';\r\nimport { MessageList } from '../MessageList/MessageList';\r\nimport { ChatInput } from '../ChatInput/ChatInput';\r\nimport { Message } from '../../types';\r\nimport { Bot } from 'lucide-react';\r\n\r\nexport interface ChatWindowProps {\r\n apiEndpoint: string;\r\n title?: string;\r\n welcomeMessage?: string;\r\n}\r\n\r\nexport const ChatWindow: React.FC<ChatWindowProps> = ({\r\n apiEndpoint,\r\n title = \"AI Assistant\",\r\n welcomeMessage = \"سلام! چطور می‌توانم کمکتان کنم؟\"\r\n}) => {\r\n const [messages, setMessages] = useState<Message[]>([]);\r\n const [isLoading, setIsLoading] = useState(false);\r\n\r\n useEffect(() => {\r\n if (welcomeMessage && messages.length === 0) {\r\n setMessages([{ role: 'assistant', content: welcomeMessage }]);\r\n }\r\n }, [welcomeMessage]);\r\n\r\n const handleSendMessage = async (userMessage: string) => {\r\n const newUserMsg: Message = { role: 'user', content: userMessage };\r\n const currentMessages = [...messages, newUserMsg];\r\n setMessages(currentMessages);\r\n setIsLoading(true);\r\n\r\n try {\r\n const response = await fetch(apiEndpoint, {\r\n method: 'POST',\r\n headers: { 'Content-Type': 'application/json' },\r\n body: JSON.stringify({ messages: currentMessages }),\r\n });\r\n\r\n if (!response.ok) throw new Error(\"Network response was not ok\");\r\n \r\n const data = await response.json();\r\n const botMsg: Message = { role: 'assistant', content: data.content };\r\n setMessages(prev => [...prev, botMsg]);\r\n\r\n } catch (error) {\r\n console.error(\"Chat Error:\", error);\r\n const errorMsg: Message = { role: 'assistant', content: \"خطایی رخ داده است.\" };\r\n setMessages(prev => [...prev, errorMsg]);\r\n } finally {\r\n setIsLoading(false);\r\n }\r\n };\r\n\r\n return (\r\n <div className={clsx(styles.container, styles.chatWindow)}>\r\n <div style={{ padding: '16px', borderBottom: '1px solid var(--ai-border)', display: 'flex', alignItems: 'center', gap: '8px', background: '#f9fafb' }}>\r\n <Bot size={20} />\r\n <span style={{ fontWeight: 600 }}>{title}</span>\r\n </div>\r\n <MessageList messages={messages} isLoading={isLoading} />\r\n <ChatInput onSendMessage={handleSendMessage} isLoading={isLoading} />\r\n </div>\r\n );\r\n};","/* \r\n این فایل استایل‌های اصلی و کانتینر چت را تعریف می‌کند.\r\n متغیرهای CSS به کاربر اجازه می‌دهند تا به راحتی ظاهر ربات را شخصی‌سازی کند.\r\n*/\r\n\r\n.container {\r\n /* ======== متغیرهای قابل شخصی‌سازی ======== */\r\n \r\n /* رنگ اصلی (دکمه ارسال، حباب کاربر) */\r\n --ai-primary: #2563eb;\r\n /* رنگ متن روی المان‌های اصلی */\r\n --ai-primary-fg: #ffffff;\r\n\r\n /* رنگ‌های پس‌زمینه */\r\n --ai-bg: #ffffff;\r\n --ai-bot-bg: #f3f4f6;\r\n --ai-user-bg: var(--ai-primary);\r\n\r\n /* رنگ‌های متن */\r\n --ai-text: #1f2937;\r\n --ai-text-secondary: #6b7280;\r\n --ai-user-text: var(--ai-primary-fg);\r\n\r\n /* رنگ حاشیه و جداکننده‌ها */\r\n --ai-border: #e5e7eb;\r\n\r\n /* ======================================== */\r\n\r\n /* ارث‌بری فونت از سایت میزبان برای هماهنگی بیشتر */\r\n font-family: inherit; \r\n font-size: 16px;\r\n line-height: 1.5;\r\n box-sizing: border-box;\r\n}\r\n\r\n/* کانتینر اصلی پنجره چت */\r\n.chatWindow {\r\n display: flex;\r\n flex-direction: column;\r\n height: 500px; /* ارتفاع پیش‌فرض، کاربر می‌تواند تغییر دهد */\r\n width: 100%;\r\n max-width: 400px;\r\n background-color: var(--ai-bg);\r\n border: 1px solid var(--ai-border);\r\n border-radius: 12px;\r\n overflow: hidden; /* برای اینکه گوشه‌های گرد درست نمایش داده شوند */\r\n box-shadow: 0 4px 6px -1px rgba(0, 0, 0, 0.1), 0 2px 4px -2px rgba(0, 0, 0, 0.1);\r\n position: relative;\r\n}","// src/components/MessageList/MessageList.tsx\r\nimport React, { useRef, useEffect } from 'react';\r\nimport clsx from 'clsx';\r\nimport styles from './MessageList.module.css';\r\nimport { MessageBubble } from '../MessageBubble/MessageBubble';\r\nimport { Message } from '../../types';\r\n\r\ninterface MessageListProps {\r\n messages: Message[];\r\n isLoading: boolean;\r\n}\r\n\r\nexport const MessageList: React.FC<MessageListProps> = ({ messages, isLoading }) => {\r\n const messagesEndRef = useRef<HTMLDivElement>(null);\r\n\r\n useEffect(() => {\r\n messagesEndRef.current?.scrollIntoView({ behavior: 'smooth' });\r\n }, [messages, isLoading]);\r\n\r\n return (\r\n <div className={styles.messageList}>\r\n {messages.map((msg, index) => (\r\n <MessageBubble key={index} message={msg} />\r\n ))}\r\n {isLoading && (\r\n <div className={clsx(styles.messageRow, styles.assistant)}>\r\n <div className={clsx(styles.bubble, styles.assistant, styles.loading)}>\r\n <div className={styles.dot}></div>\r\n <div className={styles.dot}></div>\r\n <div className={styles.dot}></div>\r\n </div>\r\n </div>\r\n )}\r\n <div ref={messagesEndRef} />\r\n </div>\r\n );\r\n};",".messageList {\r\nflex: 1;\r\noverflow-y: auto;\r\npadding: 16px;\r\ndisplay: flex;\r\nflex-direction: column;\r\ngap: 12px;\r\nscroll-behavior: smooth;\r\n}\r\n/* این استایل‌ها برای انیمیشن لودینگ هستند */\r\n.loading {\r\ndisplay: flex;\r\ngap: 4px;\r\npadding: 4px;\r\n}\r\n.dot {\r\nwidth: 6px;\r\nheight: 6px;\r\nbackground-color: #9ca3af;\r\nborder-radius: 50%;\r\nanimation: bounce 1.4s infinite ease-in-out both;\r\n}\r\n.dot:nth-child(1) { animation-delay: -0.32s; }\r\n.dot:nth-child(2) { animation-delay: -0.16s; }\r\n@keyframes bounce {\r\n0%, 80%, 100% { transform: scale(0); }\r\n40% { transform: scale(1); }\r\n}","// src/components/MessageBubble/MessageBubble.tsx\r\nimport React from 'react';\r\nimport clsx from 'clsx';\r\nimport styles from './MessageBubble.module.css'; // 👈 مسیر جدید\r\nimport { Message } from '../../types';\r\n\r\ninterface MessageBubbleProps {\r\n message: Message;\r\n}\r\n\r\nexport const MessageBubble: React.FC<MessageBubbleProps> = ({ message }) => {\r\n const isUser = message.role === 'user';\r\n return (\r\n <div className={clsx(styles.messageRow, isUser ? styles.user : styles.assistant)}>\r\n <div className={clsx(styles.bubble, isUser ? styles.user : styles.assistant)}>\r\n {message.content}\r\n </div>\r\n </div>\r\n );\r\n};",".messageRow {\r\n display: flex;\r\n width: 100%;\r\n}\r\n.messageRow.user {\r\n justify-content: flex-end;\r\n}\r\n.messageRow.assistant {\r\n justify-content: flex-start;\r\n}\r\n.bubble {\r\n max-width: 80%;\r\n padding: 8px 12px;\r\n border-radius: 12px;\r\n font-size: 0.95em;\r\n word-wrap: break-word;\r\n}\r\n.bubble.user {\r\n background-color: var(--ai-user-bg, #2563eb);\r\n color: var(--ai-user-text, #ffffff);\r\n border-bottom-right-radius: 2px;\r\n}\r\n.bubble.assistant {\r\n background-color: var(--ai-bot-bg, #f3f4f6);\r\n color: var(--ai-text, #1f2937);\r\n border-bottom-left-radius: 2px;\r\n}","// src/components/ChatInput/ChatInput.tsx\r\nimport React, { useState } from 'react';\r\nimport styles from './ChatInput.module.css';\r\nimport { Send } from 'lucide-react';\r\n\r\ninterface ChatInputProps {\r\n onSendMessage: (message: string) => void;\r\n isLoading: boolean;\r\n}\r\n\r\nexport const ChatInput: React.FC<ChatInputProps> = ({ onSendMessage, isLoading }) => {\r\n const [inputValue, setInputValue] = useState('');\r\n\r\n const handleSend = () => {\r\n if (inputValue.trim()) {\r\n onSendMessage(inputValue);\r\n setInputValue('');\r\n }\r\n };\r\n\r\n const handleKeyDown = (e: React.KeyboardEvent) => {\r\n if (e.key === 'Enter' && !e.shiftKey) {\r\n e.preventDefault();\r\n handleSend();\r\n }\r\n };\r\n\r\n return (\r\n <div className={styles.inputArea}>\r\n <input\r\n className={styles.input}\r\n value={inputValue}\r\n onChange={(e) => setInputValue(e.target.value)}\r\n onKeyDown={handleKeyDown}\r\n placeholder=\"پیام خود را بنویسید...\"\r\n disabled={isLoading}\r\n />\r\n <button\r\n className={styles.sendButton}\r\n onClick={handleSend}\r\n disabled={isLoading || !inputValue.trim()}\r\n >\r\n <Send size={18} />\r\n </button>\r\n </div>\r\n );\r\n};","/* src/components/ChatInput/ChatInput.module.css */\r\n.inputArea {\r\n padding: 12px;\r\n border-top: 1px solid var(--ai-border, #e5e7eb);\r\n display: flex;\r\n gap: 8px;\r\n background-color: var(--ai-bg, #ffffff);\r\n}\r\n.input {\r\n flex: 1;\r\n padding: 8px 12px;\r\n border: 1px solid var(--ai-border, #e5e7eb);\r\n border-radius: 8px;\r\n outline: none;\r\n font-family: inherit;\r\n}\r\n.input:focus {\r\n border-color: var(--ai-primary, #2563eb);\r\n}\r\n.sendButton {\r\n background-color: var(--ai-primary, #2563eb);\r\n color: var(--ai-primary-fg, #ffffff);\r\n border: none;\r\n border-radius: 8px;\r\n padding: 8px 12px;\r\n cursor: pointer;\r\n display: flex;\r\n align-items: center;\r\n justify-content: center;\r\n transition: opacity 0.2s;\r\n}\r\n.sendButton:disabled {\r\n opacity: 0.5;\r\n cursor: not-allowed;\r\n}"],"mappings":"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","names":["import_react","import_clsx","import_clsx","clsx","import_jsx_runtime","clsx","import_react","import_jsx_runtime","import_lucide_react","import_jsx_runtime","clsx"]}
package/dist/react.mjs CHANGED
@@ -1,69 +1,122 @@
1
1
  "use client";
2
2
 
3
- // src/components/ChatBot.tsx
4
- import { useState, useRef, useEffect } from "react";
3
+ // src/components/ChatWindow/ChatWindow.tsx
4
+ import { useState as useState2, useEffect as useEffect2 } from "react";
5
+ import clsx3 from "clsx";
5
6
 
6
- // src/styles/chat.module.css
7
- var chat_default = {};
7
+ // src/components/ChatWindow/ChatWindow.module.css
8
+ var ChatWindow_default = {};
8
9
 
9
- // src/components/MessageBubble.tsx
10
+ // src/components/MessageList/MessageList.tsx
11
+ import { useRef, useEffect } from "react";
12
+ import clsx2 from "clsx";
13
+
14
+ // src/components/MessageList/MessageList.module.css
15
+ var MessageList_default = {};
16
+
17
+ // src/components/MessageBubble/MessageBubble.tsx
10
18
  import clsx from "clsx";
19
+
20
+ // src/components/MessageBubble/MessageBubble.module.css
21
+ var MessageBubble_default = {};
22
+
23
+ // src/components/MessageBubble/MessageBubble.tsx
11
24
  import { jsx } from "react/jsx-runtime";
12
25
  var MessageBubble = ({ message }) => {
13
26
  const isUser = message.role === "user";
14
- return /* @__PURE__ */ jsx(
15
- "div",
16
- {
17
- className: clsx(
18
- chat_default.messageRow,
19
- isUser ? chat_default.user : chat_default.assistant
20
- ),
21
- children: /* @__PURE__ */ jsx(
22
- "div",
23
- {
24
- className: clsx(
25
- chat_default.bubble,
26
- isUser ? chat_default.user : chat_default.assistant
27
- ),
28
- children: message.content
29
- }
30
- )
31
- }
32
- );
27
+ return /* @__PURE__ */ jsx("div", { className: clsx(MessageBubble_default.messageRow, isUser ? MessageBubble_default.user : MessageBubble_default.assistant), children: /* @__PURE__ */ jsx("div", { className: clsx(MessageBubble_default.bubble, isUser ? MessageBubble_default.user : MessageBubble_default.assistant), children: message.content }) });
33
28
  };
34
29
 
35
- // src/components/ChatBot.tsx
36
- import { Send, Bot } from "lucide-react";
37
- import clsx2 from "clsx";
30
+ // src/components/MessageList/MessageList.tsx
38
31
  import { jsx as jsx2, jsxs } from "react/jsx-runtime";
39
- var ChatBot = ({
32
+ var MessageList = ({ messages, isLoading }) => {
33
+ const messagesEndRef = useRef(null);
34
+ useEffect(() => {
35
+ messagesEndRef.current?.scrollIntoView({ behavior: "smooth" });
36
+ }, [messages, isLoading]);
37
+ return /* @__PURE__ */ jsxs("div", { className: MessageList_default.messageList, children: [
38
+ messages.map((msg, index) => /* @__PURE__ */ jsx2(MessageBubble, { message: msg }, index)),
39
+ isLoading && /* @__PURE__ */ jsx2("div", { className: clsx2(MessageList_default.messageRow, MessageList_default.assistant), children: /* @__PURE__ */ jsxs("div", { className: clsx2(MessageList_default.bubble, MessageList_default.assistant, MessageList_default.loading), children: [
40
+ /* @__PURE__ */ jsx2("div", { className: MessageList_default.dot }),
41
+ /* @__PURE__ */ jsx2("div", { className: MessageList_default.dot }),
42
+ /* @__PURE__ */ jsx2("div", { className: MessageList_default.dot })
43
+ ] }) }),
44
+ /* @__PURE__ */ jsx2("div", { ref: messagesEndRef })
45
+ ] });
46
+ };
47
+
48
+ // src/components/ChatInput/ChatInput.tsx
49
+ import { useState } from "react";
50
+
51
+ // src/components/ChatInput/ChatInput.module.css
52
+ var ChatInput_default = {};
53
+
54
+ // src/components/ChatInput/ChatInput.tsx
55
+ import { Send } from "lucide-react";
56
+ import { jsx as jsx3, jsxs as jsxs2 } from "react/jsx-runtime";
57
+ var ChatInput = ({ onSendMessage, isLoading }) => {
58
+ const [inputValue, setInputValue] = useState("");
59
+ const handleSend = () => {
60
+ if (inputValue.trim()) {
61
+ onSendMessage(inputValue);
62
+ setInputValue("");
63
+ }
64
+ };
65
+ const handleKeyDown = (e) => {
66
+ if (e.key === "Enter" && !e.shiftKey) {
67
+ e.preventDefault();
68
+ handleSend();
69
+ }
70
+ };
71
+ return /* @__PURE__ */ jsxs2("div", { className: ChatInput_default.inputArea, children: [
72
+ /* @__PURE__ */ jsx3(
73
+ "input",
74
+ {
75
+ className: ChatInput_default.input,
76
+ value: inputValue,
77
+ onChange: (e) => setInputValue(e.target.value),
78
+ onKeyDown: handleKeyDown,
79
+ placeholder: "\u067E\u06CC\u0627\u0645 \u062E\u0648\u062F \u0631\u0627 \u0628\u0646\u0648\u06CC\u0633\u06CC\u062F...",
80
+ disabled: isLoading
81
+ }
82
+ ),
83
+ /* @__PURE__ */ jsx3(
84
+ "button",
85
+ {
86
+ className: ChatInput_default.sendButton,
87
+ onClick: handleSend,
88
+ disabled: isLoading || !inputValue.trim(),
89
+ children: /* @__PURE__ */ jsx3(Send, { size: 18 })
90
+ }
91
+ )
92
+ ] });
93
+ };
94
+
95
+ // src/components/ChatWindow/ChatWindow.tsx
96
+ import { Bot } from "lucide-react";
97
+ import { jsx as jsx4, jsxs as jsxs3 } from "react/jsx-runtime";
98
+ var ChatWindow = ({
40
99
  apiEndpoint,
41
100
  title = "AI Assistant",
42
101
  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"
43
102
  }) => {
44
- const [messages, setMessages] = useState([]);
45
- const [inputValue, setInputValue] = useState("");
46
- const [isLoading, setIsLoading] = useState(false);
47
- const messagesEndRef = useRef(null);
48
- useEffect(() => {
103
+ const [messages, setMessages] = useState2([]);
104
+ const [isLoading, setIsLoading] = useState2(false);
105
+ useEffect2(() => {
49
106
  if (welcomeMessage && messages.length === 0) {
50
107
  setMessages([{ role: "assistant", content: welcomeMessage }]);
51
108
  }
52
109
  }, [welcomeMessage]);
53
- useEffect(() => {
54
- messagesEndRef.current?.scrollIntoView({ behavior: "smooth" });
55
- }, [messages]);
56
- const handleSendMessage = async () => {
57
- if (!inputValue.trim() || isLoading) return;
58
- const userMsg = { role: "user", content: inputValue };
59
- setMessages((prev) => [...prev, userMsg]);
60
- setInputValue("");
110
+ const handleSendMessage = async (userMessage) => {
111
+ const newUserMsg = { role: "user", content: userMessage };
112
+ const currentMessages = [...messages, newUserMsg];
113
+ setMessages(currentMessages);
61
114
  setIsLoading(true);
62
115
  try {
63
116
  const response = await fetch(apiEndpoint, {
64
117
  method: "POST",
65
118
  headers: { "Content-Type": "application/json" },
66
- body: JSON.stringify({ messages: [...messages, userMsg] })
119
+ body: JSON.stringify({ messages: currentMessages })
67
120
  });
68
121
  if (!response.ok) throw new Error("Network response was not ok");
69
122
  const data = await response.json();
@@ -71,60 +124,22 @@ var ChatBot = ({
71
124
  setMessages((prev) => [...prev, botMsg]);
72
125
  } catch (error) {
73
126
  console.error("Chat Error:", error);
74
- setMessages((prev) => [...prev, { role: "assistant", content: "\u062E\u0637\u0627\u06CC\u06CC \u0631\u062E \u062F\u0627\u062F\u0647 \u0627\u0633\u062A. \u0644\u0637\u0641\u0627\u064B \u062F\u0648\u0628\u0627\u0631\u0647 \u062A\u0644\u0627\u0634 \u06A9\u0646\u06CC\u062F." }]);
127
+ const errorMsg = { role: "assistant", content: "\u062E\u0637\u0627\u06CC\u06CC \u0631\u062E \u062F\u0627\u062F\u0647 \u0627\u0633\u062A." };
128
+ setMessages((prev) => [...prev, errorMsg]);
75
129
  } finally {
76
130
  setIsLoading(false);
77
131
  }
78
132
  };
79
- const handleKeyDown = (e) => {
80
- if (e.key === "Enter" && !e.shiftKey) {
81
- e.preventDefault();
82
- handleSendMessage();
83
- }
84
- };
85
- return (
86
- // کلاس کانتینر برای اعمال متغیرهای CSS
87
- /* @__PURE__ */ jsxs("div", { className: clsx2(chat_default.container, chat_default.chatWindow), children: [
88
- /* @__PURE__ */ jsxs("div", { style: { padding: "16px", borderBottom: "1px solid var(--ai-border)", display: "flex", alignItems: "center", gap: "8px", background: "#f9fafb" }, children: [
89
- /* @__PURE__ */ jsx2(Bot, { size: 20 }),
90
- /* @__PURE__ */ jsx2("span", { style: { fontWeight: 600 }, children: title })
91
- ] }),
92
- /* @__PURE__ */ jsxs("div", { className: chat_default.messageList, children: [
93
- messages.map((msg, index) => /* @__PURE__ */ jsx2(MessageBubble, { message: msg }, index)),
94
- isLoading && /* @__PURE__ */ jsx2("div", { className: clsx2(chat_default.messageRow, chat_default.assistant), children: /* @__PURE__ */ jsxs("div", { className: clsx2(chat_default.bubble, chat_default.assistant, chat_default.loading), children: [
95
- /* @__PURE__ */ jsx2("div", { className: chat_default.dot }),
96
- /* @__PURE__ */ jsx2("div", { className: chat_default.dot }),
97
- /* @__PURE__ */ jsx2("div", { className: chat_default.dot })
98
- ] }) }),
99
- /* @__PURE__ */ jsx2("div", { ref: messagesEndRef })
100
- ] }),
101
- /* @__PURE__ */ jsxs("div", { className: chat_default.inputArea, children: [
102
- /* @__PURE__ */ jsx2(
103
- "input",
104
- {
105
- className: chat_default.input,
106
- value: inputValue,
107
- onChange: (e) => setInputValue(e.target.value),
108
- onKeyDown: handleKeyDown,
109
- placeholder: "\u067E\u06CC\u0627\u0645 \u062E\u0648\u062F \u0631\u0627 \u0628\u0646\u0648\u06CC\u0633\u06CC\u062F...",
110
- disabled: isLoading
111
- }
112
- ),
113
- /* @__PURE__ */ jsx2(
114
- "button",
115
- {
116
- className: chat_default.sendButton,
117
- onClick: handleSendMessage,
118
- disabled: isLoading || !inputValue.trim(),
119
- children: /* @__PURE__ */ jsx2(Send, { size: 18 })
120
- }
121
- )
122
- ] })
123
- ] })
124
- );
133
+ return /* @__PURE__ */ jsxs3("div", { className: clsx3(ChatWindow_default.container, ChatWindow_default.chatWindow), children: [
134
+ /* @__PURE__ */ jsxs3("div", { style: { padding: "16px", borderBottom: "1px solid var(--ai-border)", display: "flex", alignItems: "center", gap: "8px", background: "#f9fafb" }, children: [
135
+ /* @__PURE__ */ jsx4(Bot, { size: 20 }),
136
+ /* @__PURE__ */ jsx4("span", { style: { fontWeight: 600 }, children: title })
137
+ ] }),
138
+ /* @__PURE__ */ jsx4(MessageList, { messages, isLoading }),
139
+ /* @__PURE__ */ jsx4(ChatInput, { onSendMessage: handleSendMessage, isLoading })
140
+ ] });
125
141
  };
126
142
  export {
127
- ChatBot,
128
- MessageBubble
143
+ ChatWindow
129
144
  };
130
145
  //# sourceMappingURL=react.mjs.map
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/components/ChatBot.tsx","../src/styles/chat.module.css","../src/components/MessageBubble.tsx"],"sourcesContent":["\"use client\"\r\n\r\nimport React, { useState, useRef, useEffect } from 'react';\r\nimport styles from '../styles/chat.module.css';\r\nimport { MessageBubble } from './MessageBubble';\r\nimport { Message } from '../types';\r\nimport { Send, Bot } from 'lucide-react'; // آیکون‌ها\r\nimport clsx from 'clsx';\r\n\r\nexport interface ChatBotProps {\r\n /** آدرس ای‌پی‌آی که کاربر در پروژه خودش ساخته */\r\n apiEndpoint: string;\r\n /** عنوان بالای چت باکس */\r\n title?: string;\r\n /** پیام خوش‌آمدگویی اولیه */\r\n welcomeMessage?: string;\r\n}\r\n\r\nexport const ChatBot: React.FC<ChatBotProps> = ({\r\n apiEndpoint,\r\n title = \"AI Assistant\",\r\n welcomeMessage = \"سلام! چطور می‌توانم کمکتان کنم؟\"\r\n}) => {\r\n const [messages, setMessages] = useState<Message[]>([]);\r\n const [inputValue, setInputValue] = useState(\"\");\r\n const [isLoading, setIsLoading] = useState(false);\r\n \r\n // برای اسکرول خودکار به پایین\r\n const messagesEndRef = useRef<HTMLDivElement>(null);\r\n\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 // اسکرول به پایین وقتی پیام جدید می‌آید\r\n useEffect(() => {\r\n messagesEndRef.current?.scrollIntoView({ behavior: 'smooth' });\r\n }, [messages]);\r\n\r\n const handleSendMessage = async () => {\r\n if (!inputValue.trim() || isLoading) return;\r\n\r\n const userMsg: Message = { role: 'user', content: inputValue };\r\n \r\n // 1. اضافه کردن پیام کاربر به لیست و خالی کردن اینپوت\r\n setMessages(prev => [...prev, userMsg]);\r\n setInputValue(\"\");\r\n setIsLoading(true);\r\n\r\n try {\r\n // 2. ارسال درخواست به سرور (API کاربر)\r\n const response = await fetch(apiEndpoint, {\r\n method: 'POST',\r\n headers: { 'Content-Type': 'application/json' },\r\n body: JSON.stringify({ messages: [...messages, userMsg] }),\r\n });\r\n\r\n if (!response.ok) throw new Error(\"Network response was not ok\");\r\n \r\n // نکته: اینجا فعلاً فرض می‌کنیم پاسخ متنی ساده است (بعداً استریم را اضافه می‌کنیم)\r\n const data = await response.json();\r\n \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 setMessages(prev => [...prev, { role: 'assistant', content: \"خطایی رخ داده است. لطفاً دوباره تلاش کنید.\" }]);\r\n } finally {\r\n setIsLoading(false);\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 handleSendMessage();\r\n }\r\n };\r\n\r\n return (\r\n // کلاس کانتینر برای اعمال متغیرهای CSS\r\n <div className={clsx(styles.container, styles.chatWindow)}>\r\n {/* هدر */}\r\n <div style={{ padding: '16px', borderBottom: '1px solid var(--ai-border)', display: 'flex', alignItems: 'center', gap: '8px', background: '#f9fafb' }}>\r\n <Bot size={20} />\r\n <span style={{ fontWeight: 600 }}>{title}</span>\r\n </div>\r\n\r\n {/* لیست پیام‌ها */}\r\n <div className={styles.messageList}>\r\n {messages.map((msg, index) => (\r\n <MessageBubble key={index} message={msg} />\r\n ))}\r\n {isLoading && (\r\n <div className={clsx(styles.messageRow, styles.assistant)}>\r\n <div className={clsx(styles.bubble, styles.assistant, styles.loading)}>\r\n <div className={styles.dot}></div>\r\n <div className={styles.dot}></div>\r\n <div className={styles.dot}></div>\r\n </div>\r\n </div>\r\n )}\r\n <div ref={messagesEndRef} />\r\n </div>\r\n\r\n {/* ورودی */}\r\n <div className={styles.inputArea}>\r\n <input\r\n className={styles.input}\r\n value={inputValue}\r\n onChange={(e) => setInputValue(e.target.value)}\r\n onKeyDown={handleKeyDown}\r\n placeholder=\"پیام خود را بنویسید...\"\r\n disabled={isLoading}\r\n />\r\n <button \r\n className={styles.sendButton} \r\n onClick={handleSendMessage}\r\n disabled={isLoading || !inputValue.trim()}\r\n >\r\n <Send size={18} />\r\n </button>\r\n </div>\r\n </div>\r\n );\r\n};","/* src/styles/chat.module.css */\r\n\r\n/* تعریف متغیرها برای اینکه کاربر بتواند رنگ‌ها را شخصی‌سازی کند */\r\n.container {\r\n /* رنگ‌های پیش‌فرض - کاربر می‌تواند این‌ها را در فایل CSS خود بازنویسی کند */\r\n --ai-primary: #2563eb; /* رنگ آبی استاندارد */\r\n --ai-primary-fg: #ffffff; /* رنگ متن روی دکمه‌ها */\r\n --ai-bg: #ffffff; /* رنگ پس‌زمینه چت */\r\n --ai-border: #e5e7eb; /* رنگ حاشیه */\r\n --ai-text: #1f2937; /* رنگ متن اصلی */\r\n --ai-text-secondary: #6b7280; /* رنگ متن فرعی */\r\n --ai-bot-bg: #f3f4f6; /* رنگ حباب پیام ربات */\r\n --ai-user-bg: #2563eb; /* رنگ حباب پیام کاربر */\r\n --ai-user-text: #ffffff; /* رنگ متن پیام کاربر */\r\n \r\n font-family: inherit; /* از فونت وبسایت کاربر ارث‌بری می‌کند */\r\n font-size: 16px;\r\n line-height: 1.5;\r\n box-sizing: border-box;\r\n}\r\n\r\n/* کانتینر اصلی چت */\r\n.chatWindow {\r\n display: flex;\r\n flex-direction: column;\r\n height: 500px;\r\n width: 100%;\r\n max-width: 400px;\r\n background-color: var(--ai-bg);\r\n border: 1px solid var(--ai-border);\r\n border-radius: 12px;\r\n overflow: hidden;\r\n box-shadow: 0 4px 6px -1px rgba(0, 0, 0, 0.1);\r\n position: relative;\r\n}\r\n\r\n/* لیست پیام‌ها */\r\n.messageList {\r\n flex: 1;\r\n overflow-y: auto;\r\n padding: 16px;\r\n display: flex;\r\n flex-direction: column;\r\n gap: 12px;\r\n scroll-behavior: smooth;\r\n}\r\n\r\n/* استایل هر پیام */\r\n.messageRow {\r\n display: flex;\r\n width: 100%;\r\n}\r\n\r\n.messageRow.user {\r\n justify-content: flex-end;\r\n}\r\n\r\n.messageRow.assistant {\r\n justify-content: flex-start;\r\n}\r\n\r\n.bubble {\r\n max-width: 80%;\r\n padding: 8px 12px;\r\n border-radius: 12px;\r\n font-size: 0.95em;\r\n word-wrap: break-word;\r\n}\r\n\r\n.bubble.user {\r\n background-color: var(--ai-user-bg);\r\n color: var(--ai-user-text);\r\n border-bottom-right-radius: 2px;\r\n}\r\n\r\n.bubble.assistant {\r\n background-color: var(--ai-bot-bg);\r\n color: var(--ai-text);\r\n border-bottom-left-radius: 2px;\r\n}\r\n\r\n/* ناحیه ورودی متن */\r\n.inputArea {\r\n padding: 12px;\r\n border-top: 1px solid var(--ai-border);\r\n display: flex;\r\n gap: 8px;\r\n background-color: var(--ai-bg);\r\n}\r\n\r\n.input {\r\n flex: 1;\r\n padding: 8px 12px;\r\n border: 1px solid var(--ai-border);\r\n border-radius: 8px;\r\n outline: none;\r\n font-family: inherit;\r\n}\r\n\r\n.input:focus {\r\n border-color: var(--ai-primary);\r\n}\r\n\r\n.sendButton {\r\n background-color: var(--ai-primary);\r\n color: var(--ai-primary-fg);\r\n border: none;\r\n border-radius: 8px;\r\n padding: 8px 12px;\r\n cursor: pointer;\r\n display: flex;\r\n align-items: center;\r\n justify-content: center;\r\n transition: opacity 0.2s;\r\n}\r\n\r\n.sendButton:disabled {\r\n opacity: 0.5;\r\n cursor: not-allowed;\r\n}\r\n\r\n.loading {\r\n display: flex;\r\n gap: 4px;\r\n padding: 4px;\r\n}\r\n\r\n.dot {\r\n width: 6px;\r\n height: 6px;\r\n background-color: #9ca3af;\r\n border-radius: 50%;\r\n animation: bounce 1.4s infinite ease-in-out both;\r\n}\r\n\r\n.dot:nth-child(1) { animation-delay: -0.32s; }\r\n.dot:nth-child(2) { animation-delay: -0.16s; }\r\n\r\n@keyframes bounce {\r\n 0%, 80%, 100% { transform: scale(0); }\r\n 40% { transform: scale(1); }\r\n}","// src/components/MessageBubble.tsx\r\nimport React from 'react';\r\nimport clsx from 'clsx'; // ابزاری عالی برای ترکیب کلاس‌های CSS\r\nimport styles from '../styles/chat.module.css';\r\nimport { Message } from '../types';\r\n\r\ninterface MessageBubbleProps {\r\n message: Message;\r\n}\r\n\r\nexport const MessageBubble: React.FC<MessageBubbleProps> = ({ message }) => {\r\n const isUser = message.role === 'user';\r\n\r\n return (\r\n <div\r\n className={clsx(\r\n styles.messageRow,\r\n isUser ? styles.user : styles.assistant\r\n )}\r\n >\r\n <div\r\n className={clsx(\r\n styles.bubble,\r\n isUser ? styles.user : styles.assistant\r\n )}\r\n >\r\n {/* فعلاً متن ساده را رندر می‌کنیم. بعداً می‌توانیم Markdown اضافه کنیم */}\r\n {message.content}\r\n </div>\r\n </div>\r\n );\r\n};"],"mappings":"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","names":["clsx","jsx"]}
1
+ {"version":3,"sources":["../src/components/ChatWindow/ChatWindow.tsx","../src/components/ChatWindow/ChatWindow.module.css","../src/components/MessageList/MessageList.tsx","../src/components/MessageList/MessageList.module.css","../src/components/MessageBubble/MessageBubble.tsx","../src/components/MessageBubble/MessageBubble.module.css","../src/components/ChatInput/ChatInput.tsx","../src/components/ChatInput/ChatInput.module.css"],"sourcesContent":["// src/components/ChatWindow/ChatWindow.tsx\r\nimport React, { useState, useEffect } from 'react';\r\nimport clsx from 'clsx';\r\nimport styles from './ChatWindow.module.css';\r\nimport { MessageList } from '../MessageList/MessageList';\r\nimport { ChatInput } from '../ChatInput/ChatInput';\r\nimport { Message } from '../../types';\r\nimport { Bot } from 'lucide-react';\r\n\r\nexport interface ChatWindowProps {\r\n apiEndpoint: string;\r\n title?: string;\r\n welcomeMessage?: string;\r\n}\r\n\r\nexport const ChatWindow: React.FC<ChatWindowProps> = ({\r\n apiEndpoint,\r\n title = \"AI Assistant\",\r\n welcomeMessage = \"سلام! چطور می‌توانم کمکتان کنم؟\"\r\n}) => {\r\n const [messages, setMessages] = useState<Message[]>([]);\r\n const [isLoading, setIsLoading] = useState(false);\r\n\r\n useEffect(() => {\r\n if (welcomeMessage && messages.length === 0) {\r\n setMessages([{ role: 'assistant', content: welcomeMessage }]);\r\n }\r\n }, [welcomeMessage]);\r\n\r\n const handleSendMessage = async (userMessage: string) => {\r\n const newUserMsg: Message = { role: 'user', content: userMessage };\r\n const currentMessages = [...messages, newUserMsg];\r\n setMessages(currentMessages);\r\n setIsLoading(true);\r\n\r\n try {\r\n const response = await fetch(apiEndpoint, {\r\n method: 'POST',\r\n headers: { 'Content-Type': 'application/json' },\r\n body: JSON.stringify({ messages: currentMessages }),\r\n });\r\n\r\n if (!response.ok) throw new Error(\"Network response was not ok\");\r\n \r\n const data = await response.json();\r\n const botMsg: Message = { role: 'assistant', content: data.content };\r\n setMessages(prev => [...prev, botMsg]);\r\n\r\n } catch (error) {\r\n console.error(\"Chat Error:\", error);\r\n const errorMsg: Message = { role: 'assistant', content: \"خطایی رخ داده است.\" };\r\n setMessages(prev => [...prev, errorMsg]);\r\n } finally {\r\n setIsLoading(false);\r\n }\r\n };\r\n\r\n return (\r\n <div className={clsx(styles.container, styles.chatWindow)}>\r\n <div style={{ padding: '16px', borderBottom: '1px solid var(--ai-border)', display: 'flex', alignItems: 'center', gap: '8px', background: '#f9fafb' }}>\r\n <Bot size={20} />\r\n <span style={{ fontWeight: 600 }}>{title}</span>\r\n </div>\r\n <MessageList messages={messages} isLoading={isLoading} />\r\n <ChatInput onSendMessage={handleSendMessage} isLoading={isLoading} />\r\n </div>\r\n );\r\n};","/* \r\n این فایل استایل‌های اصلی و کانتینر چت را تعریف می‌کند.\r\n متغیرهای CSS به کاربر اجازه می‌دهند تا به راحتی ظاهر ربات را شخصی‌سازی کند.\r\n*/\r\n\r\n.container {\r\n /* ======== متغیرهای قابل شخصی‌سازی ======== */\r\n \r\n /* رنگ اصلی (دکمه ارسال، حباب کاربر) */\r\n --ai-primary: #2563eb;\r\n /* رنگ متن روی المان‌های اصلی */\r\n --ai-primary-fg: #ffffff;\r\n\r\n /* رنگ‌های پس‌زمینه */\r\n --ai-bg: #ffffff;\r\n --ai-bot-bg: #f3f4f6;\r\n --ai-user-bg: var(--ai-primary);\r\n\r\n /* رنگ‌های متن */\r\n --ai-text: #1f2937;\r\n --ai-text-secondary: #6b7280;\r\n --ai-user-text: var(--ai-primary-fg);\r\n\r\n /* رنگ حاشیه و جداکننده‌ها */\r\n --ai-border: #e5e7eb;\r\n\r\n /* ======================================== */\r\n\r\n /* ارث‌بری فونت از سایت میزبان برای هماهنگی بیشتر */\r\n font-family: inherit; \r\n font-size: 16px;\r\n line-height: 1.5;\r\n box-sizing: border-box;\r\n}\r\n\r\n/* کانتینر اصلی پنجره چت */\r\n.chatWindow {\r\n display: flex;\r\n flex-direction: column;\r\n height: 500px; /* ارتفاع پیش‌فرض، کاربر می‌تواند تغییر دهد */\r\n width: 100%;\r\n max-width: 400px;\r\n background-color: var(--ai-bg);\r\n border: 1px solid var(--ai-border);\r\n border-radius: 12px;\r\n overflow: hidden; /* برای اینکه گوشه‌های گرد درست نمایش داده شوند */\r\n box-shadow: 0 4px 6px -1px rgba(0, 0, 0, 0.1), 0 2px 4px -2px rgba(0, 0, 0, 0.1);\r\n position: relative;\r\n}","// src/components/MessageList/MessageList.tsx\r\nimport React, { useRef, useEffect } from 'react';\r\nimport clsx from 'clsx';\r\nimport styles from './MessageList.module.css';\r\nimport { MessageBubble } from '../MessageBubble/MessageBubble';\r\nimport { Message } from '../../types';\r\n\r\ninterface MessageListProps {\r\n messages: Message[];\r\n isLoading: boolean;\r\n}\r\n\r\nexport const MessageList: React.FC<MessageListProps> = ({ messages, isLoading }) => {\r\n const messagesEndRef = useRef<HTMLDivElement>(null);\r\n\r\n useEffect(() => {\r\n messagesEndRef.current?.scrollIntoView({ behavior: 'smooth' });\r\n }, [messages, isLoading]);\r\n\r\n return (\r\n <div className={styles.messageList}>\r\n {messages.map((msg, index) => (\r\n <MessageBubble key={index} message={msg} />\r\n ))}\r\n {isLoading && (\r\n <div className={clsx(styles.messageRow, styles.assistant)}>\r\n <div className={clsx(styles.bubble, styles.assistant, styles.loading)}>\r\n <div className={styles.dot}></div>\r\n <div className={styles.dot}></div>\r\n <div className={styles.dot}></div>\r\n </div>\r\n </div>\r\n )}\r\n <div ref={messagesEndRef} />\r\n </div>\r\n );\r\n};",".messageList {\r\nflex: 1;\r\noverflow-y: auto;\r\npadding: 16px;\r\ndisplay: flex;\r\nflex-direction: column;\r\ngap: 12px;\r\nscroll-behavior: smooth;\r\n}\r\n/* این استایل‌ها برای انیمیشن لودینگ هستند */\r\n.loading {\r\ndisplay: flex;\r\ngap: 4px;\r\npadding: 4px;\r\n}\r\n.dot {\r\nwidth: 6px;\r\nheight: 6px;\r\nbackground-color: #9ca3af;\r\nborder-radius: 50%;\r\nanimation: bounce 1.4s infinite ease-in-out both;\r\n}\r\n.dot:nth-child(1) { animation-delay: -0.32s; }\r\n.dot:nth-child(2) { animation-delay: -0.16s; }\r\n@keyframes bounce {\r\n0%, 80%, 100% { transform: scale(0); }\r\n40% { transform: scale(1); }\r\n}","// src/components/MessageBubble/MessageBubble.tsx\r\nimport React from 'react';\r\nimport clsx from 'clsx';\r\nimport styles from './MessageBubble.module.css'; // 👈 مسیر جدید\r\nimport { Message } from '../../types';\r\n\r\ninterface MessageBubbleProps {\r\n message: Message;\r\n}\r\n\r\nexport const MessageBubble: React.FC<MessageBubbleProps> = ({ message }) => {\r\n const isUser = message.role === 'user';\r\n return (\r\n <div className={clsx(styles.messageRow, isUser ? styles.user : styles.assistant)}>\r\n <div className={clsx(styles.bubble, isUser ? styles.user : styles.assistant)}>\r\n {message.content}\r\n </div>\r\n </div>\r\n );\r\n};",".messageRow {\r\n display: flex;\r\n width: 100%;\r\n}\r\n.messageRow.user {\r\n justify-content: flex-end;\r\n}\r\n.messageRow.assistant {\r\n justify-content: flex-start;\r\n}\r\n.bubble {\r\n max-width: 80%;\r\n padding: 8px 12px;\r\n border-radius: 12px;\r\n font-size: 0.95em;\r\n word-wrap: break-word;\r\n}\r\n.bubble.user {\r\n background-color: var(--ai-user-bg, #2563eb);\r\n color: var(--ai-user-text, #ffffff);\r\n border-bottom-right-radius: 2px;\r\n}\r\n.bubble.assistant {\r\n background-color: var(--ai-bot-bg, #f3f4f6);\r\n color: var(--ai-text, #1f2937);\r\n border-bottom-left-radius: 2px;\r\n}","// src/components/ChatInput/ChatInput.tsx\r\nimport React, { useState } from 'react';\r\nimport styles from './ChatInput.module.css';\r\nimport { Send } from 'lucide-react';\r\n\r\ninterface ChatInputProps {\r\n onSendMessage: (message: string) => void;\r\n isLoading: boolean;\r\n}\r\n\r\nexport const ChatInput: React.FC<ChatInputProps> = ({ onSendMessage, isLoading }) => {\r\n const [inputValue, setInputValue] = useState('');\r\n\r\n const handleSend = () => {\r\n if (inputValue.trim()) {\r\n onSendMessage(inputValue);\r\n setInputValue('');\r\n }\r\n };\r\n\r\n const handleKeyDown = (e: React.KeyboardEvent) => {\r\n if (e.key === 'Enter' && !e.shiftKey) {\r\n e.preventDefault();\r\n handleSend();\r\n }\r\n };\r\n\r\n return (\r\n <div className={styles.inputArea}>\r\n <input\r\n className={styles.input}\r\n value={inputValue}\r\n onChange={(e) => setInputValue(e.target.value)}\r\n onKeyDown={handleKeyDown}\r\n placeholder=\"پیام خود را بنویسید...\"\r\n disabled={isLoading}\r\n />\r\n <button\r\n className={styles.sendButton}\r\n onClick={handleSend}\r\n disabled={isLoading || !inputValue.trim()}\r\n >\r\n <Send size={18} />\r\n </button>\r\n </div>\r\n );\r\n};","/* src/components/ChatInput/ChatInput.module.css */\r\n.inputArea {\r\n padding: 12px;\r\n border-top: 1px solid var(--ai-border, #e5e7eb);\r\n display: flex;\r\n gap: 8px;\r\n background-color: var(--ai-bg, #ffffff);\r\n}\r\n.input {\r\n flex: 1;\r\n padding: 8px 12px;\r\n border: 1px solid var(--ai-border, #e5e7eb);\r\n border-radius: 8px;\r\n outline: none;\r\n font-family: inherit;\r\n}\r\n.input:focus {\r\n border-color: var(--ai-primary, #2563eb);\r\n}\r\n.sendButton {\r\n background-color: var(--ai-primary, #2563eb);\r\n color: var(--ai-primary-fg, #ffffff);\r\n border: none;\r\n border-radius: 8px;\r\n padding: 8px 12px;\r\n cursor: pointer;\r\n display: flex;\r\n align-items: center;\r\n justify-content: center;\r\n transition: opacity 0.2s;\r\n}\r\n.sendButton:disabled {\r\n opacity: 0.5;\r\n cursor: not-allowed;\r\n}"],"mappings":"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","names":["useState","useEffect","clsx","clsx","jsx","clsx","jsx","jsxs","jsx","jsxs","useState","useEffect","clsx"]}
package/package.json CHANGED
@@ -1,11 +1,11 @@
1
1
  {
2
2
  "name": "mehdi-ai-assistant",
3
- "version": "0.0.1",
3
+ "version": "0.1.0",
4
4
  "description": "A professional AI Chatbot for Next.js/React powered by LangChain",
5
5
  "main": "./dist/index.js",
6
6
  "module": "./dist/index.mjs",
7
7
  "types": "./dist/index.d.ts",
8
- "exports": {
8
+ "exports": {
9
9
  ".": {
10
10
  "types": "./dist/index.d.ts",
11
11
  "import": "./dist/index.mjs",
@@ -21,7 +21,6 @@
21
21
  "files": [
22
22
  "dist"
23
23
  ],
24
-
25
24
  "scripts": {
26
25
  "build": "tsup",
27
26
  "dev": "tsup --watch",
@@ -55,4 +54,4 @@
55
54
  "tsup": "^8.5.1",
56
55
  "typescript": "^5.0.0"
57
56
  }
58
- }
57
+ }