mehdi-akbari-ai-assistant-free 0.0.1

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.
@@ -0,0 +1,12 @@
1
+ type Role = 'user' | 'assistant' | 'system';
2
+ interface Message {
3
+ role: Role;
4
+ content: string;
5
+ }
6
+ interface AiRobotConfig {
7
+ apiKey: string;
8
+ model?: string;
9
+ systemPrompt?: string;
10
+ }
11
+
12
+ export type { AiRobotConfig as A, Message as M, Role as R };
@@ -0,0 +1,12 @@
1
+ type Role = 'user' | 'assistant' | 'system';
2
+ interface Message {
3
+ role: Role;
4
+ content: string;
5
+ }
6
+ interface AiRobotConfig {
7
+ apiKey: string;
8
+ model?: string;
9
+ systemPrompt?: string;
10
+ }
11
+
12
+ export type { AiRobotConfig as A, Message as M, Role as R };
@@ -0,0 +1,24 @@
1
+ import { A as AiRobotConfig, M as Message } from './index-Dr3adAXO.mjs';
2
+ export { R as Role } from './index-Dr3adAXO.mjs';
3
+
4
+ declare class AiRobot {
5
+ private model;
6
+ private systemPrompt;
7
+ constructor(config: AiRobotConfig);
8
+ /**
9
+ /**
10
+ * این متد پیام‌ها را به فرمت مورد نیاز LangChain تبدیل می‌کند.
11
+ * تایپ خروجی برای سازگاری با نسخه‌های جدید LangChain اصلاح شده است.
12
+ *
13
+ * Return plain message objects with explicit `role` and `content` to match
14
+ * the BaseMessageLike / MessageFieldWithRole shape expected by model.invoke().
15
+ */
16
+ private formatMessages;
17
+ /**
18
+ * متد اصلی برای ارسال پیام و دریافت پاسخ.
19
+ * شامل حالت Mock برای جلوگیری از خطا در صورت قطعی اینترنت.
20
+ */
21
+ chat(messages: Message[]): Promise<string>;
22
+ }
23
+
24
+ export { AiRobot, AiRobotConfig, Message };
@@ -0,0 +1,24 @@
1
+ import { A as AiRobotConfig, M as Message } from './index-Dr3adAXO.js';
2
+ export { R as Role } from './index-Dr3adAXO.js';
3
+
4
+ declare class AiRobot {
5
+ private model;
6
+ private systemPrompt;
7
+ constructor(config: AiRobotConfig);
8
+ /**
9
+ /**
10
+ * این متد پیام‌ها را به فرمت مورد نیاز LangChain تبدیل می‌کند.
11
+ * تایپ خروجی برای سازگاری با نسخه‌های جدید LangChain اصلاح شده است.
12
+ *
13
+ * Return plain message objects with explicit `role` and `content` to match
14
+ * the BaseMessageLike / MessageFieldWithRole shape expected by model.invoke().
15
+ */
16
+ private formatMessages;
17
+ /**
18
+ * متد اصلی برای ارسال پیام و دریافت پاسخ.
19
+ * شامل حالت Mock برای جلوگیری از خطا در صورت قطعی اینترنت.
20
+ */
21
+ chat(messages: Message[]): Promise<string>;
22
+ }
23
+
24
+ export { AiRobot, AiRobotConfig, Message };
package/dist/index.js ADDED
@@ -0,0 +1,80 @@
1
+ "use strict";
2
+ var __defProp = Object.defineProperty;
3
+ var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
4
+ var __getOwnPropNames = Object.getOwnPropertyNames;
5
+ var __hasOwnProp = Object.prototype.hasOwnProperty;
6
+ var __export = (target, all) => {
7
+ for (var name in all)
8
+ __defProp(target, name, { get: all[name], enumerable: true });
9
+ };
10
+ var __copyProps = (to, from, except, desc) => {
11
+ if (from && typeof from === "object" || typeof from === "function") {
12
+ for (let key of __getOwnPropNames(from))
13
+ if (!__hasOwnProp.call(to, key) && key !== except)
14
+ __defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
15
+ }
16
+ return to;
17
+ };
18
+ var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
19
+
20
+ // src/index.ts
21
+ var index_exports = {};
22
+ __export(index_exports, {
23
+ AiRobot: () => AiRobot
24
+ });
25
+ module.exports = __toCommonJS(index_exports);
26
+
27
+ // src/core/ai-robot.ts
28
+ var import_groq = require("@langchain/groq");
29
+ var AiRobot = class {
30
+ constructor(config) {
31
+ if (!config.apiKey) {
32
+ throw new Error("API Key is required for AiRobot.");
33
+ }
34
+ this.systemPrompt = config.systemPrompt || "You are a helpful assistant.";
35
+ this.model = new import_groq.ChatGroq({
36
+ apiKey: config.apiKey,
37
+ model: config.model || "llama3-8b-8192"
38
+ });
39
+ }
40
+ /**
41
+ /**
42
+ * این متد پیام‌ها را به فرمت مورد نیاز LangChain تبدیل می‌کند.
43
+ * تایپ خروجی برای سازگاری با نسخه‌های جدید LangChain اصلاح شده است.
44
+ *
45
+ * Return plain message objects with explicit `role` and `content` to match
46
+ * the BaseMessageLike / MessageFieldWithRole shape expected by model.invoke().
47
+ */
48
+ formatMessages(messages) {
49
+ const formatted = [
50
+ { role: "system", content: this.systemPrompt }
51
+ ];
52
+ messages.forEach((msg) => {
53
+ if (msg.role === "user") {
54
+ formatted.push({ role: "user", content: msg.content });
55
+ } else if (msg.role === "assistant") {
56
+ formatted.push({ role: "assistant", content: msg.content });
57
+ }
58
+ });
59
+ return formatted;
60
+ }
61
+ /**
62
+ * متد اصلی برای ارسال پیام و دریافت پاسخ.
63
+ * شامل حالت Mock برای جلوگیری از خطا در صورت قطعی اینترنت.
64
+ */
65
+ async chat(messages) {
66
+ try {
67
+ const formattedMessages = this.formatMessages(messages);
68
+ const response = await this.model.invoke(formattedMessages);
69
+ return response.content;
70
+ } catch (error) {
71
+ console.warn("AI connection failed. Returning a mock response.", error);
72
+ return "\u0627\u06CC\u0646\u062A\u0631\u0646\u062A \u0634\u0645\u0627 \u0645\u062A\u0635\u0644 \u0646\u06CC\u0633\u062A\u060C \u0627\u0645\u0627 \u067E\u06A9\u06CC\u062C \u0628\u0647 \u062F\u0631\u0633\u062A\u06CC \u06A9\u0627\u0631 \u0645\u06CC\u200C\u06A9\u0646\u062F! \u2705 (\u0627\u06CC\u0646 \u06CC\u06A9 \u067E\u06CC\u0627\u0645 \u062A\u0633\u062A\u06CC \u0627\u0633\u062A)";
73
+ }
74
+ }
75
+ };
76
+ // Annotate the CommonJS export names for ESM import in node:
77
+ 0 && (module.exports = {
78
+ AiRobot
79
+ });
80
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/index.ts","../src/core/ai-robot.ts"],"sourcesContent":["export * from \"./types\";\r\nexport { AiRobot } from \"./core/ai-robot\";","import { ChatGroq } from \"@langchain/groq\";\r\nimport { AiRobotConfig, Message } from \"../types\";\r\n\r\nexport class AiRobot {\r\n private model: ChatGroq;\r\n private systemPrompt: string;\r\n\r\n constructor(config: AiRobotConfig) {\r\n if (!config.apiKey) {\r\n throw new Error(\"API Key is required for AiRobot.\");\r\n }\r\n\r\n this.systemPrompt = config.systemPrompt || \"You are a helpful assistant.\";\r\n\r\n this.model = new ChatGroq({\r\n apiKey: config.apiKey,\r\n model: config.model || \"llama3-8b-8192\",\r\n });\r\n }\r\n\r\n /**\r\n /**\r\n * این متد پیام‌ها را به فرمت مورد نیاز LangChain تبدیل می‌کند.\r\n * تایپ خروجی برای سازگاری با نسخه‌های جدید LangChain اصلاح شده است.\r\n *\r\n * Return plain message objects with explicit `role` and `content` to match\r\n * the BaseMessageLike / MessageFieldWithRole shape expected by model.invoke().\r\n */\r\n private formatMessages(messages: Message[]): { role: 'system' | 'user' | 'assistant' | string; content: string }[] {\r\n const formatted: { role: 'system' | 'user' | 'assistant' | string; content: string }[] = [\r\n { role: 'system', content: this.systemPrompt }\r\n ];\r\n\r\n messages.forEach((msg) => {\r\n if (msg.role === 'user') {\r\n formatted.push({ role: 'user', content: msg.content });\r\n } else if (msg.role === 'assistant') {\r\n formatted.push({ role: 'assistant', content: msg.content });\r\n }\r\n });\r\n\r\n return formatted;\r\n }\r\n /**\r\n * متد اصلی برای ارسال پیام و دریافت پاسخ.\r\n * شامل حالت Mock برای جلوگیری از خطا در صورت قطعی اینترنت.\r\n */\r\n async chat(messages: Message[]): Promise<string> {\r\n try {\r\n const formattedMessages = this.formatMessages(messages);\r\n const response = await this.model.invoke(formattedMessages);\r\n return response.content as string;\r\n } catch (error) {\r\n console.warn(\"AI connection failed. Returning a mock response.\", error);\r\n return \"اینترنت شما متصل نیست، اما پکیج به درستی کار می‌کند! ✅ (این یک پیام تستی است)\";\r\n }\r\n }\r\n}"],"mappings":";;;;;;;;;;;;;;;;;;;;AAAA;AAAA;AAAA;AAAA;AAAA;;;ACAA,kBAAyB;AAGlB,IAAM,UAAN,MAAc;AAAA,EAInB,YAAY,QAAuB;AACjC,QAAI,CAAC,OAAO,QAAQ;AAClB,YAAM,IAAI,MAAM,kCAAkC;AAAA,IACpD;AAEA,SAAK,eAAe,OAAO,gBAAgB;AAE3C,SAAK,QAAQ,IAAI,qBAAS;AAAA,MACxB,QAAQ,OAAO;AAAA,MACf,OAAO,OAAO,SAAS;AAAA,IACzB,CAAC;AAAA,EACH;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAUQ,eAAe,UAA4F;AACjH,UAAM,YAAmF;AAAA,MACvF,EAAE,MAAM,UAAU,SAAS,KAAK,aAAa;AAAA,IAC/C;AAEA,aAAS,QAAQ,CAAC,QAAQ;AACxB,UAAI,IAAI,SAAS,QAAQ;AACvB,kBAAU,KAAK,EAAE,MAAM,QAAQ,SAAS,IAAI,QAAQ,CAAC;AAAA,MACvD,WAAW,IAAI,SAAS,aAAa;AACnC,kBAAU,KAAK,EAAE,MAAM,aAAa,SAAS,IAAI,QAAQ,CAAC;AAAA,MAC5D;AAAA,IACF,CAAC;AAED,WAAO;AAAA,EACT;AAAA;AAAA;AAAA;AAAA;AAAA,EAKA,MAAM,KAAK,UAAsC;AAC/C,QAAI;AACF,YAAM,oBAAoB,KAAK,eAAe,QAAQ;AACtD,YAAM,WAAW,MAAM,KAAK,MAAM,OAAO,iBAAiB;AAC1D,aAAO,SAAS;AAAA,IAClB,SAAS,OAAO;AACd,cAAQ,KAAK,oDAAoD,KAAK;AACtE,aAAO;AAAA,IACT;AAAA,EACF;AACF;","names":[]}
package/dist/index.mjs ADDED
@@ -0,0 +1,53 @@
1
+ // src/core/ai-robot.ts
2
+ import { ChatGroq } from "@langchain/groq";
3
+ var AiRobot = class {
4
+ constructor(config) {
5
+ if (!config.apiKey) {
6
+ throw new Error("API Key is required for AiRobot.");
7
+ }
8
+ this.systemPrompt = config.systemPrompt || "You are a helpful assistant.";
9
+ this.model = new ChatGroq({
10
+ apiKey: config.apiKey,
11
+ model: config.model || "llama3-8b-8192"
12
+ });
13
+ }
14
+ /**
15
+ /**
16
+ * این متد پیام‌ها را به فرمت مورد نیاز LangChain تبدیل می‌کند.
17
+ * تایپ خروجی برای سازگاری با نسخه‌های جدید LangChain اصلاح شده است.
18
+ *
19
+ * Return plain message objects with explicit `role` and `content` to match
20
+ * the BaseMessageLike / MessageFieldWithRole shape expected by model.invoke().
21
+ */
22
+ formatMessages(messages) {
23
+ const formatted = [
24
+ { role: "system", content: this.systemPrompt }
25
+ ];
26
+ messages.forEach((msg) => {
27
+ if (msg.role === "user") {
28
+ formatted.push({ role: "user", content: msg.content });
29
+ } else if (msg.role === "assistant") {
30
+ formatted.push({ role: "assistant", content: msg.content });
31
+ }
32
+ });
33
+ return formatted;
34
+ }
35
+ /**
36
+ * متد اصلی برای ارسال پیام و دریافت پاسخ.
37
+ * شامل حالت Mock برای جلوگیری از خطا در صورت قطعی اینترنت.
38
+ */
39
+ async chat(messages) {
40
+ try {
41
+ const formattedMessages = this.formatMessages(messages);
42
+ const response = await this.model.invoke(formattedMessages);
43
+ return response.content;
44
+ } catch (error) {
45
+ console.warn("AI connection failed. Returning a mock response.", error);
46
+ return "\u0627\u06CC\u0646\u062A\u0631\u0646\u062A \u0634\u0645\u0627 \u0645\u062A\u0635\u0644 \u0646\u06CC\u0633\u062A\u060C \u0627\u0645\u0627 \u067E\u06A9\u06CC\u062C \u0628\u0647 \u062F\u0631\u0633\u062A\u06CC \u06A9\u0627\u0631 \u0645\u06CC\u200C\u06A9\u0646\u062F! \u2705 (\u0627\u06CC\u0646 \u06CC\u06A9 \u067E\u06CC\u0627\u0645 \u062A\u0633\u062A\u06CC \u0627\u0633\u062A)";
47
+ }
48
+ }
49
+ };
50
+ export {
51
+ AiRobot
52
+ };
53
+ //# sourceMappingURL=index.mjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/core/ai-robot.ts"],"sourcesContent":["import { ChatGroq } from \"@langchain/groq\";\r\nimport { AiRobotConfig, Message } from \"../types\";\r\n\r\nexport class AiRobot {\r\n private model: ChatGroq;\r\n private systemPrompt: string;\r\n\r\n constructor(config: AiRobotConfig) {\r\n if (!config.apiKey) {\r\n throw new Error(\"API Key is required for AiRobot.\");\r\n }\r\n\r\n this.systemPrompt = config.systemPrompt || \"You are a helpful assistant.\";\r\n\r\n this.model = new ChatGroq({\r\n apiKey: config.apiKey,\r\n model: config.model || \"llama3-8b-8192\",\r\n });\r\n }\r\n\r\n /**\r\n /**\r\n * این متد پیام‌ها را به فرمت مورد نیاز LangChain تبدیل می‌کند.\r\n * تایپ خروجی برای سازگاری با نسخه‌های جدید LangChain اصلاح شده است.\r\n *\r\n * Return plain message objects with explicit `role` and `content` to match\r\n * the BaseMessageLike / MessageFieldWithRole shape expected by model.invoke().\r\n */\r\n private formatMessages(messages: Message[]): { role: 'system' | 'user' | 'assistant' | string; content: string }[] {\r\n const formatted: { role: 'system' | 'user' | 'assistant' | string; content: string }[] = [\r\n { role: 'system', content: this.systemPrompt }\r\n ];\r\n\r\n messages.forEach((msg) => {\r\n if (msg.role === 'user') {\r\n formatted.push({ role: 'user', content: msg.content });\r\n } else if (msg.role === 'assistant') {\r\n formatted.push({ role: 'assistant', content: msg.content });\r\n }\r\n });\r\n\r\n return formatted;\r\n }\r\n /**\r\n * متد اصلی برای ارسال پیام و دریافت پاسخ.\r\n * شامل حالت Mock برای جلوگیری از خطا در صورت قطعی اینترنت.\r\n */\r\n async chat(messages: Message[]): Promise<string> {\r\n try {\r\n const formattedMessages = this.formatMessages(messages);\r\n const response = await this.model.invoke(formattedMessages);\r\n return response.content as string;\r\n } catch (error) {\r\n console.warn(\"AI connection failed. Returning a mock response.\", error);\r\n return \"اینترنت شما متصل نیست، اما پکیج به درستی کار می‌کند! ✅ (این یک پیام تستی است)\";\r\n }\r\n }\r\n}"],"mappings":";AAAA,SAAS,gBAAgB;AAGlB,IAAM,UAAN,MAAc;AAAA,EAInB,YAAY,QAAuB;AACjC,QAAI,CAAC,OAAO,QAAQ;AAClB,YAAM,IAAI,MAAM,kCAAkC;AAAA,IACpD;AAEA,SAAK,eAAe,OAAO,gBAAgB;AAE3C,SAAK,QAAQ,IAAI,SAAS;AAAA,MACxB,QAAQ,OAAO;AAAA,MACf,OAAO,OAAO,SAAS;AAAA,IACzB,CAAC;AAAA,EACH;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAUQ,eAAe,UAA4F;AACjH,UAAM,YAAmF;AAAA,MACvF,EAAE,MAAM,UAAU,SAAS,KAAK,aAAa;AAAA,IAC/C;AAEA,aAAS,QAAQ,CAAC,QAAQ;AACxB,UAAI,IAAI,SAAS,QAAQ;AACvB,kBAAU,KAAK,EAAE,MAAM,QAAQ,SAAS,IAAI,QAAQ,CAAC;AAAA,MACvD,WAAW,IAAI,SAAS,aAAa;AACnC,kBAAU,KAAK,EAAE,MAAM,aAAa,SAAS,IAAI,QAAQ,CAAC;AAAA,MAC5D;AAAA,IACF,CAAC;AAED,WAAO;AAAA,EACT;AAAA;AAAA;AAAA;AAAA;AAAA,EAKA,MAAM,KAAK,UAAsC;AAC/C,QAAI;AACF,YAAM,oBAAoB,KAAK,eAAe,QAAQ;AACtD,YAAM,WAAW,MAAM,KAAK,MAAM,OAAO,iBAAiB;AAC1D,aAAO,SAAS;AAAA,IAClB,SAAS,OAAO;AACd,cAAQ,KAAK,oDAAoD,KAAK;AACtE,aAAO;AAAA,IACT;AAAA,EACF;AACF;","names":[]}
package/dist/react.css ADDED
@@ -0,0 +1,132 @@
1
+ /* src/components/ChatWindow/ChatWindow.module.css */
2
+ .container {
3
+ --ai-primary: #2563eb;
4
+ --ai-primary-fg: #ffffff;
5
+ --ai-bg: #ffffff;
6
+ --ai-bot-bg: #f3f4f6;
7
+ --ai-user-bg: var(--ai-primary);
8
+ --ai-text: #1f2937;
9
+ --ai-text-secondary: #6b7280;
10
+ --ai-user-text: var(--ai-primary-fg);
11
+ --ai-border: #e5e7eb;
12
+ font-family: inherit;
13
+ font-size: 16px;
14
+ line-height: 1.5;
15
+ box-sizing: border-box;
16
+ }
17
+ .chatWindow {
18
+ display: flex;
19
+ flex-direction: column;
20
+ height: 500px;
21
+ width: 100%;
22
+ max-width: 400px;
23
+ background-color: var(--ai-bg);
24
+ border: 1px solid var(--ai-border);
25
+ border-radius: 12px;
26
+ overflow: hidden;
27
+ box-shadow: 0 4px 6px -1px rgba(0, 0, 0, 0.1), 0 2px 4px -2px rgba(0, 0, 0, 0.1);
28
+ position: relative;
29
+ }
30
+
31
+ /* src/components/MessageList/MessageList.module.css */
32
+ .messageList {
33
+ flex: 1;
34
+ overflow-y: auto;
35
+ padding: 16px;
36
+ display: flex;
37
+ flex-direction: column;
38
+ gap: 12px;
39
+ scroll-behavior: smooth;
40
+ }
41
+ .loading {
42
+ display: flex;
43
+ gap: 4px;
44
+ padding: 4px;
45
+ }
46
+ .dot {
47
+ width: 6px;
48
+ height: 6px;
49
+ background-color: #9ca3af;
50
+ border-radius: 50%;
51
+ animation: bounce 1.4s infinite ease-in-out both;
52
+ }
53
+ .dot:nth-child(1) {
54
+ animation-delay: -0.32s;
55
+ }
56
+ .dot:nth-child(2) {
57
+ animation-delay: -0.16s;
58
+ }
59
+ @keyframes bounce {
60
+ 0%, 80%, 100% {
61
+ transform: scale(0);
62
+ }
63
+ 40% {
64
+ transform: scale(1);
65
+ }
66
+ }
67
+
68
+ /* src/components/MessageBubble/MessageBubble.module.css */
69
+ .messageRow {
70
+ display: flex;
71
+ width: 100%;
72
+ }
73
+ .messageRow.user {
74
+ justify-content: flex-end;
75
+ }
76
+ .messageRow.assistant {
77
+ justify-content: flex-start;
78
+ }
79
+ .bubble {
80
+ max-width: 80%;
81
+ padding: 8px 12px;
82
+ border-radius: 12px;
83
+ font-size: 0.95em;
84
+ word-wrap: break-word;
85
+ }
86
+ .bubble.user {
87
+ background-color: var(--ai-user-bg, #2563eb);
88
+ color: var(--ai-user-text, #ffffff);
89
+ border-bottom-right-radius: 2px;
90
+ }
91
+ .bubble.assistant {
92
+ background-color: var(--ai-bot-bg, #f3f4f6);
93
+ color: var(--ai-text, #1f2937);
94
+ border-bottom-left-radius: 2px;
95
+ }
96
+
97
+ /* src/components/ChatInput/ChatInput.module.css */
98
+ .inputArea {
99
+ padding: 12px;
100
+ border-top: 1px solid var(--ai-border, #e5e7eb);
101
+ display: flex;
102
+ gap: 8px;
103
+ background-color: var(--ai-bg, #ffffff);
104
+ }
105
+ .input {
106
+ flex: 1;
107
+ padding: 8px 12px;
108
+ border: 1px solid var(--ai-border, #e5e7eb);
109
+ border-radius: 8px;
110
+ outline: none;
111
+ font-family: inherit;
112
+ }
113
+ .input:focus {
114
+ border-color: var(--ai-primary, #2563eb);
115
+ }
116
+ .sendButton {
117
+ background-color: var(--ai-primary, #2563eb);
118
+ color: var(--ai-primary-fg, #ffffff);
119
+ border: none;
120
+ border-radius: 8px;
121
+ padding: 8px 12px;
122
+ cursor: pointer;
123
+ display: flex;
124
+ align-items: center;
125
+ justify-content: center;
126
+ transition: opacity 0.2s;
127
+ }
128
+ .sendButton:disabled {
129
+ opacity: 0.5;
130
+ cursor: not-allowed;
131
+ }
132
+ /*# sourceMappingURL=react.css.map */
@@ -0,0 +1 @@
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":[]}
@@ -0,0 +1,11 @@
1
+ import React from 'react';
2
+ export { A as AiRobotConfig, M as Message, R as Role } from './index-Dr3adAXO.mjs';
3
+
4
+ interface ChatWindowProps {
5
+ apiEndpoint: string;
6
+ title?: string;
7
+ welcomeMessage?: string;
8
+ }
9
+ declare const ChatWindow: React.FC<ChatWindowProps>;
10
+
11
+ export { ChatWindow, type ChatWindowProps };
@@ -0,0 +1,11 @@
1
+ import React from 'react';
2
+ export { A as AiRobotConfig, M as Message, R as Role } from './index-Dr3adAXO.js';
3
+
4
+ interface ChatWindowProps {
5
+ apiEndpoint: string;
6
+ title?: string;
7
+ welcomeMessage?: string;
8
+ }
9
+ declare const ChatWindow: React.FC<ChatWindowProps>;
10
+
11
+ export { ChatWindow, type ChatWindowProps };
package/dist/react.js ADDED
@@ -0,0 +1,181 @@
1
+ "use strict";
2
+ "use client";
3
+ var __create = Object.create;
4
+ var __defProp = Object.defineProperty;
5
+ var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
6
+ var __getOwnPropNames = Object.getOwnPropertyNames;
7
+ var __getProtoOf = Object.getPrototypeOf;
8
+ var __hasOwnProp = Object.prototype.hasOwnProperty;
9
+ var __export = (target, all) => {
10
+ for (var name in all)
11
+ __defProp(target, name, { get: all[name], enumerable: true });
12
+ };
13
+ var __copyProps = (to, from, except, desc) => {
14
+ if (from && typeof from === "object" || typeof from === "function") {
15
+ for (let key of __getOwnPropNames(from))
16
+ if (!__hasOwnProp.call(to, key) && key !== except)
17
+ __defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
18
+ }
19
+ return to;
20
+ };
21
+ var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__getProtoOf(mod)) : {}, __copyProps(
22
+ // If the importer is in node compatibility mode or this is not an ESM
23
+ // file that has been converted to a CommonJS file using a Babel-
24
+ // compatible transform (i.e. "__esModule" has not been set), then set
25
+ // "default" to the CommonJS "module.exports" for node compatibility.
26
+ isNodeMode || !mod || !mod.__esModule ? __defProp(target, "default", { value: mod, enumerable: true }) : target,
27
+ mod
28
+ ));
29
+ var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
30
+
31
+ // src/react.ts
32
+ var react_exports = {};
33
+ __export(react_exports, {
34
+ ChatWindow: () => ChatWindow
35
+ });
36
+ module.exports = __toCommonJS(react_exports);
37
+
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
46
+ var import_react = require("react");
47
+ var import_clsx2 = __toESM(require("clsx"));
48
+
49
+ // src/components/MessageList/MessageList.module.css
50
+ var MessageList_default = {};
51
+
52
+ // src/components/MessageBubble/MessageBubble.tsx
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
59
+ var import_jsx_runtime = require("react/jsx-runtime");
60
+ var MessageBubble = ({ message }) => {
61
+ const isUser = message.role === "user";
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 }) });
63
+ };
64
+
65
+ // src/components/MessageList/MessageList.tsx
66
+ var import_jsx_runtime2 = require("react/jsx-runtime");
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 = ({
134
+ apiEndpoint,
135
+ title = "AI Assistant",
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"
137
+ }) => {
138
+ const [messages, setMessages] = (0, import_react3.useState)([]);
139
+ const [isLoading, setIsLoading] = (0, import_react3.useState)(false);
140
+ (0, import_react3.useEffect)(() => {
141
+ if (welcomeMessage && messages.length === 0) {
142
+ setMessages([{ role: "assistant", content: welcomeMessage }]);
143
+ }
144
+ }, [welcomeMessage]);
145
+ const handleSendMessage = async (userMessage) => {
146
+ const newUserMsg = { role: "user", content: userMessage };
147
+ const currentMessages = [...messages, newUserMsg];
148
+ setMessages(currentMessages);
149
+ setIsLoading(true);
150
+ try {
151
+ const response = await fetch(apiEndpoint, {
152
+ method: "POST",
153
+ headers: { "Content-Type": "application/json" },
154
+ body: JSON.stringify({ messages: currentMessages })
155
+ });
156
+ if (!response.ok) throw new Error("Network response was not ok");
157
+ const data = await response.json();
158
+ const botMsg = { role: "assistant", content: data.content };
159
+ setMessages((prev) => [...prev, botMsg]);
160
+ } catch (error) {
161
+ console.error("Chat Error:", error);
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]);
164
+ } finally {
165
+ setIsLoading(false);
166
+ }
167
+ };
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
+ ] });
176
+ };
177
+ // Annotate the CommonJS export names for ESM import in node:
178
+ 0 && (module.exports = {
179
+ ChatWindow
180
+ });
181
+ //# sourceMappingURL=react.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/react.ts","../src/components/ChatWindow/ChatWindow.tsx","../src/components/ChatWindow/ChatWindow.module.css","../src/components/MessageList/MessageList.tsx","../src/components/MessageList/MessageList.module.css","../src/components/MessageBubble/MessageBubble.tsx","../src/components/MessageBubble/MessageBubble.module.css","../src/components/ChatInput/ChatInput.tsx","../src/components/ChatInput/ChatInput.module.css"],"sourcesContent":["\"use client\";\r\n\r\n\r\n\r\n\r\nexport { ChatWindow, type ChatWindowProps } from \"./components/ChatWindow/ChatWindow\";\r\n\r\n\r\nexport * from \"./types\";","// src/components/ChatWindow/ChatWindow.tsx\r\nimport React, { useState, useEffect } from 'react';\r\nimport clsx from 'clsx';\r\nimport styles from './ChatWindow.module.css';\r\nimport { MessageList } from '../MessageList/MessageList';\r\nimport { ChatInput } from '../ChatInput/ChatInput';\r\nimport { Message } from '../../types';\r\nimport { Bot } from 'lucide-react';\r\n\r\nexport interface ChatWindowProps {\r\n apiEndpoint: string;\r\n title?: string;\r\n welcomeMessage?: string;\r\n}\r\n\r\nexport const ChatWindow: React.FC<ChatWindowProps> = ({\r\n apiEndpoint,\r\n title = \"AI Assistant\",\r\n welcomeMessage = \"سلام! چطور می‌توانم کمکتان کنم؟\"\r\n}) => {\r\n const [messages, setMessages] = useState<Message[]>([]);\r\n const [isLoading, setIsLoading] = useState(false);\r\n\r\n useEffect(() => {\r\n if (welcomeMessage && messages.length === 0) {\r\n setMessages([{ role: 'assistant', content: welcomeMessage }]);\r\n }\r\n }, [welcomeMessage]);\r\n\r\n const handleSendMessage = async (userMessage: string) => {\r\n const newUserMsg: Message = { role: 'user', content: userMessage };\r\n const currentMessages = [...messages, newUserMsg];\r\n setMessages(currentMessages);\r\n setIsLoading(true);\r\n\r\n try {\r\n const response = await fetch(apiEndpoint, {\r\n method: 'POST',\r\n headers: { 'Content-Type': 'application/json' },\r\n body: JSON.stringify({ messages: currentMessages }),\r\n });\r\n\r\n if (!response.ok) throw new Error(\"Network response was not ok\");\r\n \r\n const data = await response.json();\r\n const botMsg: Message = { role: 'assistant', content: data.content };\r\n setMessages(prev => [...prev, botMsg]);\r\n\r\n } catch (error) {\r\n console.error(\"Chat Error:\", error);\r\n const errorMsg: Message = { role: 'assistant', content: \"خطایی رخ داده است.\" };\r\n setMessages(prev => [...prev, errorMsg]);\r\n } finally {\r\n setIsLoading(false);\r\n }\r\n };\r\n\r\n return (\r\n <div className={clsx(styles.container, styles.chatWindow)}>\r\n <div style={{ padding: '16px', borderBottom: '1px solid var(--ai-border)', display: 'flex', alignItems: 'center', gap: '8px', background: '#f9fafb' }}>\r\n <Bot size={20} />\r\n <span style={{ fontWeight: 600 }}>{title}</span>\r\n </div>\r\n <MessageList messages={messages} isLoading={isLoading} />\r\n <ChatInput onSendMessage={handleSendMessage} isLoading={isLoading} />\r\n </div>\r\n );\r\n};","/* \r\n این فایل استایل‌های اصلی و کانتینر چت را تعریف می‌کند.\r\n متغیرهای CSS به کاربر اجازه می‌دهند تا به راحتی ظاهر ربات را شخصی‌سازی کند.\r\n*/\r\n\r\n.container {\r\n /* ======== متغیرهای قابل شخصی‌سازی ======== */\r\n \r\n /* رنگ اصلی (دکمه ارسال، حباب کاربر) */\r\n --ai-primary: #2563eb;\r\n /* رنگ متن روی المان‌های اصلی */\r\n --ai-primary-fg: #ffffff;\r\n\r\n /* رنگ‌های پس‌زمینه */\r\n --ai-bg: #ffffff;\r\n --ai-bot-bg: #f3f4f6;\r\n --ai-user-bg: var(--ai-primary);\r\n\r\n /* رنگ‌های متن */\r\n --ai-text: #1f2937;\r\n --ai-text-secondary: #6b7280;\r\n --ai-user-text: var(--ai-primary-fg);\r\n\r\n /* رنگ حاشیه و جداکننده‌ها */\r\n --ai-border: #e5e7eb;\r\n\r\n /* ======================================== */\r\n\r\n /* ارث‌بری فونت از سایت میزبان برای هماهنگی بیشتر */\r\n font-family: inherit; \r\n font-size: 16px;\r\n line-height: 1.5;\r\n box-sizing: border-box;\r\n}\r\n\r\n/* کانتینر اصلی پنجره چت */\r\n.chatWindow {\r\n display: flex;\r\n flex-direction: column;\r\n height: 500px; /* ارتفاع پیش‌فرض، کاربر می‌تواند تغییر دهد */\r\n width: 100%;\r\n max-width: 400px;\r\n background-color: var(--ai-bg);\r\n border: 1px solid var(--ai-border);\r\n border-radius: 12px;\r\n overflow: hidden; /* برای اینکه گوشه‌های گرد درست نمایش داده شوند */\r\n box-shadow: 0 4px 6px -1px rgba(0, 0, 0, 0.1), 0 2px 4px -2px rgba(0, 0, 0, 0.1);\r\n position: relative;\r\n}","// src/components/MessageList/MessageList.tsx\r\nimport React, { useRef, useEffect } from 'react';\r\nimport clsx from 'clsx';\r\nimport styles from './MessageList.module.css';\r\nimport { MessageBubble } from '../MessageBubble/MessageBubble';\r\nimport { Message } from '../../types';\r\n\r\ninterface MessageListProps {\r\n messages: Message[];\r\n isLoading: boolean;\r\n}\r\n\r\nexport const MessageList: React.FC<MessageListProps> = ({ messages, isLoading }) => {\r\n const messagesEndRef = useRef<HTMLDivElement>(null);\r\n\r\n useEffect(() => {\r\n messagesEndRef.current?.scrollIntoView({ behavior: 'smooth' });\r\n }, [messages, isLoading]);\r\n\r\n return (\r\n <div className={styles.messageList}>\r\n {messages.map((msg, index) => (\r\n <MessageBubble key={index} message={msg} />\r\n ))}\r\n {isLoading && (\r\n <div className={clsx(styles.messageRow, styles.assistant)}>\r\n <div className={clsx(styles.bubble, styles.assistant, styles.loading)}>\r\n <div className={styles.dot}></div>\r\n <div className={styles.dot}></div>\r\n <div className={styles.dot}></div>\r\n </div>\r\n </div>\r\n )}\r\n <div ref={messagesEndRef} />\r\n </div>\r\n );\r\n};",".messageList {\r\nflex: 1;\r\noverflow-y: auto;\r\npadding: 16px;\r\ndisplay: flex;\r\nflex-direction: column;\r\ngap: 12px;\r\nscroll-behavior: smooth;\r\n}\r\n/* این استایل‌ها برای انیمیشن لودینگ هستند */\r\n.loading {\r\ndisplay: flex;\r\ngap: 4px;\r\npadding: 4px;\r\n}\r\n.dot {\r\nwidth: 6px;\r\nheight: 6px;\r\nbackground-color: #9ca3af;\r\nborder-radius: 50%;\r\nanimation: bounce 1.4s infinite ease-in-out both;\r\n}\r\n.dot:nth-child(1) { animation-delay: -0.32s; }\r\n.dot:nth-child(2) { animation-delay: -0.16s; }\r\n@keyframes bounce {\r\n0%, 80%, 100% { transform: scale(0); }\r\n40% { transform: scale(1); }\r\n}","// src/components/MessageBubble/MessageBubble.tsx\r\nimport React from 'react';\r\nimport clsx from 'clsx';\r\nimport styles from './MessageBubble.module.css'; // 👈 مسیر جدید\r\nimport { Message } from '../../types';\r\n\r\ninterface MessageBubbleProps {\r\n message: Message;\r\n}\r\n\r\nexport const MessageBubble: React.FC<MessageBubbleProps> = ({ message }) => {\r\n const isUser = message.role === 'user';\r\n return (\r\n <div className={clsx(styles.messageRow, isUser ? styles.user : styles.assistant)}>\r\n <div className={clsx(styles.bubble, isUser ? styles.user : styles.assistant)}>\r\n {message.content}\r\n </div>\r\n </div>\r\n );\r\n};",".messageRow {\r\n display: flex;\r\n width: 100%;\r\n}\r\n.messageRow.user {\r\n justify-content: flex-end;\r\n}\r\n.messageRow.assistant {\r\n justify-content: flex-start;\r\n}\r\n.bubble {\r\n max-width: 80%;\r\n padding: 8px 12px;\r\n border-radius: 12px;\r\n font-size: 0.95em;\r\n word-wrap: break-word;\r\n}\r\n.bubble.user {\r\n background-color: var(--ai-user-bg, #2563eb);\r\n color: var(--ai-user-text, #ffffff);\r\n border-bottom-right-radius: 2px;\r\n}\r\n.bubble.assistant {\r\n background-color: var(--ai-bot-bg, #f3f4f6);\r\n color: var(--ai-text, #1f2937);\r\n border-bottom-left-radius: 2px;\r\n}","// src/components/ChatInput/ChatInput.tsx\r\nimport React, { useState } from 'react';\r\nimport styles from './ChatInput.module.css';\r\nimport { Send } from 'lucide-react';\r\n\r\ninterface ChatInputProps {\r\n onSendMessage: (message: string) => void;\r\n isLoading: boolean;\r\n}\r\n\r\nexport const ChatInput: React.FC<ChatInputProps> = ({ onSendMessage, isLoading }) => {\r\n const [inputValue, setInputValue] = useState('');\r\n\r\n const handleSend = () => {\r\n if (inputValue.trim()) {\r\n onSendMessage(inputValue);\r\n setInputValue('');\r\n }\r\n };\r\n\r\n const handleKeyDown = (e: React.KeyboardEvent) => {\r\n if (e.key === 'Enter' && !e.shiftKey) {\r\n e.preventDefault();\r\n handleSend();\r\n }\r\n };\r\n\r\n return (\r\n <div className={styles.inputArea}>\r\n <input\r\n className={styles.input}\r\n value={inputValue}\r\n onChange={(e) => setInputValue(e.target.value)}\r\n onKeyDown={handleKeyDown}\r\n placeholder=\"پیام خود را بنویسید...\"\r\n disabled={isLoading}\r\n />\r\n <button\r\n className={styles.sendButton}\r\n onClick={handleSend}\r\n disabled={isLoading || !inputValue.trim()}\r\n >\r\n <Send size={18} />\r\n </button>\r\n </div>\r\n );\r\n};","/* src/components/ChatInput/ChatInput.module.css */\r\n.inputArea {\r\n padding: 12px;\r\n border-top: 1px solid var(--ai-border, #e5e7eb);\r\n display: flex;\r\n gap: 8px;\r\n background-color: var(--ai-bg, #ffffff);\r\n}\r\n.input {\r\n flex: 1;\r\n padding: 8px 12px;\r\n border: 1px solid var(--ai-border, #e5e7eb);\r\n border-radius: 8px;\r\n outline: none;\r\n font-family: inherit;\r\n}\r\n.input:focus {\r\n border-color: var(--ai-primary, #2563eb);\r\n}\r\n.sendButton {\r\n background-color: var(--ai-primary, #2563eb);\r\n color: var(--ai-primary-fg, #ffffff);\r\n border: none;\r\n border-radius: 8px;\r\n padding: 8px 12px;\r\n cursor: pointer;\r\n display: flex;\r\n align-items: center;\r\n justify-content: center;\r\n transition: opacity 0.2s;\r\n}\r\n.sendButton:disabled {\r\n opacity: 0.5;\r\n cursor: not-allowed;\r\n}"],"mappings":"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","names":["import_react","import_clsx","import_clsx","clsx","import_jsx_runtime","clsx","import_react","import_jsx_runtime","import_lucide_react","import_jsx_runtime","clsx"]}
package/dist/react.mjs ADDED
@@ -0,0 +1,145 @@
1
+ "use client";
2
+
3
+ // src/components/ChatWindow/ChatWindow.tsx
4
+ import { useState as useState2, useEffect as useEffect2 } from "react";
5
+ import clsx3 from "clsx";
6
+
7
+ // src/components/ChatWindow/ChatWindow.module.css
8
+ var ChatWindow_default = {};
9
+
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
18
+ import clsx from "clsx";
19
+
20
+ // src/components/MessageBubble/MessageBubble.module.css
21
+ var MessageBubble_default = {};
22
+
23
+ // src/components/MessageBubble/MessageBubble.tsx
24
+ import { jsx } from "react/jsx-runtime";
25
+ var MessageBubble = ({ message }) => {
26
+ const isUser = message.role === "user";
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 }) });
28
+ };
29
+
30
+ // src/components/MessageList/MessageList.tsx
31
+ import { jsx as jsx2, jsxs } from "react/jsx-runtime";
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 = ({
99
+ apiEndpoint,
100
+ title = "AI Assistant",
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"
102
+ }) => {
103
+ const [messages, setMessages] = useState2([]);
104
+ const [isLoading, setIsLoading] = useState2(false);
105
+ useEffect2(() => {
106
+ if (welcomeMessage && messages.length === 0) {
107
+ setMessages([{ role: "assistant", content: welcomeMessage }]);
108
+ }
109
+ }, [welcomeMessage]);
110
+ const handleSendMessage = async (userMessage) => {
111
+ const newUserMsg = { role: "user", content: userMessage };
112
+ const currentMessages = [...messages, newUserMsg];
113
+ setMessages(currentMessages);
114
+ setIsLoading(true);
115
+ try {
116
+ const response = await fetch(apiEndpoint, {
117
+ method: "POST",
118
+ headers: { "Content-Type": "application/json" },
119
+ body: JSON.stringify({ messages: currentMessages })
120
+ });
121
+ if (!response.ok) throw new Error("Network response was not ok");
122
+ const data = await response.json();
123
+ const botMsg = { role: "assistant", content: data.content };
124
+ setMessages((prev) => [...prev, botMsg]);
125
+ } catch (error) {
126
+ console.error("Chat Error:", error);
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]);
129
+ } finally {
130
+ setIsLoading(false);
131
+ }
132
+ };
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
+ ] });
141
+ };
142
+ export {
143
+ ChatWindow
144
+ };
145
+ //# sourceMappingURL=react.mjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/components/ChatWindow/ChatWindow.tsx","../src/components/ChatWindow/ChatWindow.module.css","../src/components/MessageList/MessageList.tsx","../src/components/MessageList/MessageList.module.css","../src/components/MessageBubble/MessageBubble.tsx","../src/components/MessageBubble/MessageBubble.module.css","../src/components/ChatInput/ChatInput.tsx","../src/components/ChatInput/ChatInput.module.css"],"sourcesContent":["// src/components/ChatWindow/ChatWindow.tsx\r\nimport React, { useState, useEffect } from 'react';\r\nimport clsx from 'clsx';\r\nimport styles from './ChatWindow.module.css';\r\nimport { MessageList } from '../MessageList/MessageList';\r\nimport { ChatInput } from '../ChatInput/ChatInput';\r\nimport { Message } from '../../types';\r\nimport { Bot } from 'lucide-react';\r\n\r\nexport interface ChatWindowProps {\r\n apiEndpoint: string;\r\n title?: string;\r\n welcomeMessage?: string;\r\n}\r\n\r\nexport const ChatWindow: React.FC<ChatWindowProps> = ({\r\n apiEndpoint,\r\n title = \"AI Assistant\",\r\n welcomeMessage = \"سلام! چطور می‌توانم کمکتان کنم؟\"\r\n}) => {\r\n const [messages, setMessages] = useState<Message[]>([]);\r\n const [isLoading, setIsLoading] = useState(false);\r\n\r\n useEffect(() => {\r\n if (welcomeMessage && messages.length === 0) {\r\n setMessages([{ role: 'assistant', content: welcomeMessage }]);\r\n }\r\n }, [welcomeMessage]);\r\n\r\n const handleSendMessage = async (userMessage: string) => {\r\n const newUserMsg: Message = { role: 'user', content: userMessage };\r\n const currentMessages = [...messages, newUserMsg];\r\n setMessages(currentMessages);\r\n setIsLoading(true);\r\n\r\n try {\r\n const response = await fetch(apiEndpoint, {\r\n method: 'POST',\r\n headers: { 'Content-Type': 'application/json' },\r\n body: JSON.stringify({ messages: currentMessages }),\r\n });\r\n\r\n if (!response.ok) throw new Error(\"Network response was not ok\");\r\n \r\n const data = await response.json();\r\n const botMsg: Message = { role: 'assistant', content: data.content };\r\n setMessages(prev => [...prev, botMsg]);\r\n\r\n } catch (error) {\r\n console.error(\"Chat Error:\", error);\r\n const errorMsg: Message = { role: 'assistant', content: \"خطایی رخ داده است.\" };\r\n setMessages(prev => [...prev, errorMsg]);\r\n } finally {\r\n setIsLoading(false);\r\n }\r\n };\r\n\r\n return (\r\n <div className={clsx(styles.container, styles.chatWindow)}>\r\n <div style={{ padding: '16px', borderBottom: '1px solid var(--ai-border)', display: 'flex', alignItems: 'center', gap: '8px', background: '#f9fafb' }}>\r\n <Bot size={20} />\r\n <span style={{ fontWeight: 600 }}>{title}</span>\r\n </div>\r\n <MessageList messages={messages} isLoading={isLoading} />\r\n <ChatInput onSendMessage={handleSendMessage} isLoading={isLoading} />\r\n </div>\r\n );\r\n};","/* \r\n این فایل استایل‌های اصلی و کانتینر چت را تعریف می‌کند.\r\n متغیرهای CSS به کاربر اجازه می‌دهند تا به راحتی ظاهر ربات را شخصی‌سازی کند.\r\n*/\r\n\r\n.container {\r\n /* ======== متغیرهای قابل شخصی‌سازی ======== */\r\n \r\n /* رنگ اصلی (دکمه ارسال، حباب کاربر) */\r\n --ai-primary: #2563eb;\r\n /* رنگ متن روی المان‌های اصلی */\r\n --ai-primary-fg: #ffffff;\r\n\r\n /* رنگ‌های پس‌زمینه */\r\n --ai-bg: #ffffff;\r\n --ai-bot-bg: #f3f4f6;\r\n --ai-user-bg: var(--ai-primary);\r\n\r\n /* رنگ‌های متن */\r\n --ai-text: #1f2937;\r\n --ai-text-secondary: #6b7280;\r\n --ai-user-text: var(--ai-primary-fg);\r\n\r\n /* رنگ حاشیه و جداکننده‌ها */\r\n --ai-border: #e5e7eb;\r\n\r\n /* ======================================== */\r\n\r\n /* ارث‌بری فونت از سایت میزبان برای هماهنگی بیشتر */\r\n font-family: inherit; \r\n font-size: 16px;\r\n line-height: 1.5;\r\n box-sizing: border-box;\r\n}\r\n\r\n/* کانتینر اصلی پنجره چت */\r\n.chatWindow {\r\n display: flex;\r\n flex-direction: column;\r\n height: 500px; /* ارتفاع پیش‌فرض، کاربر می‌تواند تغییر دهد */\r\n width: 100%;\r\n max-width: 400px;\r\n background-color: var(--ai-bg);\r\n border: 1px solid var(--ai-border);\r\n border-radius: 12px;\r\n overflow: hidden; /* برای اینکه گوشه‌های گرد درست نمایش داده شوند */\r\n box-shadow: 0 4px 6px -1px rgba(0, 0, 0, 0.1), 0 2px 4px -2px rgba(0, 0, 0, 0.1);\r\n position: relative;\r\n}","// src/components/MessageList/MessageList.tsx\r\nimport React, { useRef, useEffect } from 'react';\r\nimport clsx from 'clsx';\r\nimport styles from './MessageList.module.css';\r\nimport { MessageBubble } from '../MessageBubble/MessageBubble';\r\nimport { Message } from '../../types';\r\n\r\ninterface MessageListProps {\r\n messages: Message[];\r\n isLoading: boolean;\r\n}\r\n\r\nexport const MessageList: React.FC<MessageListProps> = ({ messages, isLoading }) => {\r\n const messagesEndRef = useRef<HTMLDivElement>(null);\r\n\r\n useEffect(() => {\r\n messagesEndRef.current?.scrollIntoView({ behavior: 'smooth' });\r\n }, [messages, isLoading]);\r\n\r\n return (\r\n <div className={styles.messageList}>\r\n {messages.map((msg, index) => (\r\n <MessageBubble key={index} message={msg} />\r\n ))}\r\n {isLoading && (\r\n <div className={clsx(styles.messageRow, styles.assistant)}>\r\n <div className={clsx(styles.bubble, styles.assistant, styles.loading)}>\r\n <div className={styles.dot}></div>\r\n <div className={styles.dot}></div>\r\n <div className={styles.dot}></div>\r\n </div>\r\n </div>\r\n )}\r\n <div ref={messagesEndRef} />\r\n </div>\r\n );\r\n};",".messageList {\r\nflex: 1;\r\noverflow-y: auto;\r\npadding: 16px;\r\ndisplay: flex;\r\nflex-direction: column;\r\ngap: 12px;\r\nscroll-behavior: smooth;\r\n}\r\n/* این استایل‌ها برای انیمیشن لودینگ هستند */\r\n.loading {\r\ndisplay: flex;\r\ngap: 4px;\r\npadding: 4px;\r\n}\r\n.dot {\r\nwidth: 6px;\r\nheight: 6px;\r\nbackground-color: #9ca3af;\r\nborder-radius: 50%;\r\nanimation: bounce 1.4s infinite ease-in-out both;\r\n}\r\n.dot:nth-child(1) { animation-delay: -0.32s; }\r\n.dot:nth-child(2) { animation-delay: -0.16s; }\r\n@keyframes bounce {\r\n0%, 80%, 100% { transform: scale(0); }\r\n40% { transform: scale(1); }\r\n}","// src/components/MessageBubble/MessageBubble.tsx\r\nimport React from 'react';\r\nimport clsx from 'clsx';\r\nimport styles from './MessageBubble.module.css'; // 👈 مسیر جدید\r\nimport { Message } from '../../types';\r\n\r\ninterface MessageBubbleProps {\r\n message: Message;\r\n}\r\n\r\nexport const MessageBubble: React.FC<MessageBubbleProps> = ({ message }) => {\r\n const isUser = message.role === 'user';\r\n return (\r\n <div className={clsx(styles.messageRow, isUser ? styles.user : styles.assistant)}>\r\n <div className={clsx(styles.bubble, isUser ? styles.user : styles.assistant)}>\r\n {message.content}\r\n </div>\r\n </div>\r\n );\r\n};",".messageRow {\r\n display: flex;\r\n width: 100%;\r\n}\r\n.messageRow.user {\r\n justify-content: flex-end;\r\n}\r\n.messageRow.assistant {\r\n justify-content: flex-start;\r\n}\r\n.bubble {\r\n max-width: 80%;\r\n padding: 8px 12px;\r\n border-radius: 12px;\r\n font-size: 0.95em;\r\n word-wrap: break-word;\r\n}\r\n.bubble.user {\r\n background-color: var(--ai-user-bg, #2563eb);\r\n color: var(--ai-user-text, #ffffff);\r\n border-bottom-right-radius: 2px;\r\n}\r\n.bubble.assistant {\r\n background-color: var(--ai-bot-bg, #f3f4f6);\r\n color: var(--ai-text, #1f2937);\r\n border-bottom-left-radius: 2px;\r\n}","// src/components/ChatInput/ChatInput.tsx\r\nimport React, { useState } from 'react';\r\nimport styles from './ChatInput.module.css';\r\nimport { Send } from 'lucide-react';\r\n\r\ninterface ChatInputProps {\r\n onSendMessage: (message: string) => void;\r\n isLoading: boolean;\r\n}\r\n\r\nexport const ChatInput: React.FC<ChatInputProps> = ({ onSendMessage, isLoading }) => {\r\n const [inputValue, setInputValue] = useState('');\r\n\r\n const handleSend = () => {\r\n if (inputValue.trim()) {\r\n onSendMessage(inputValue);\r\n setInputValue('');\r\n }\r\n };\r\n\r\n const handleKeyDown = (e: React.KeyboardEvent) => {\r\n if (e.key === 'Enter' && !e.shiftKey) {\r\n e.preventDefault();\r\n handleSend();\r\n }\r\n };\r\n\r\n return (\r\n <div className={styles.inputArea}>\r\n <input\r\n className={styles.input}\r\n value={inputValue}\r\n onChange={(e) => setInputValue(e.target.value)}\r\n onKeyDown={handleKeyDown}\r\n placeholder=\"پیام خود را بنویسید...\"\r\n disabled={isLoading}\r\n />\r\n <button\r\n className={styles.sendButton}\r\n onClick={handleSend}\r\n disabled={isLoading || !inputValue.trim()}\r\n >\r\n <Send size={18} />\r\n </button>\r\n </div>\r\n );\r\n};","/* src/components/ChatInput/ChatInput.module.css */\r\n.inputArea {\r\n padding: 12px;\r\n border-top: 1px solid var(--ai-border, #e5e7eb);\r\n display: flex;\r\n gap: 8px;\r\n background-color: var(--ai-bg, #ffffff);\r\n}\r\n.input {\r\n flex: 1;\r\n padding: 8px 12px;\r\n border: 1px solid var(--ai-border, #e5e7eb);\r\n border-radius: 8px;\r\n outline: none;\r\n font-family: inherit;\r\n}\r\n.input:focus {\r\n border-color: var(--ai-primary, #2563eb);\r\n}\r\n.sendButton {\r\n background-color: var(--ai-primary, #2563eb);\r\n color: var(--ai-primary-fg, #ffffff);\r\n border: none;\r\n border-radius: 8px;\r\n padding: 8px 12px;\r\n cursor: pointer;\r\n display: flex;\r\n align-items: center;\r\n justify-content: center;\r\n transition: opacity 0.2s;\r\n}\r\n.sendButton:disabled {\r\n opacity: 0.5;\r\n cursor: not-allowed;\r\n}"],"mappings":"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","names":["useState","useEffect","clsx","clsx","jsx","clsx","jsx","jsxs","jsx","jsxs","useState","useEffect","clsx"]}
package/package.json ADDED
@@ -0,0 +1,47 @@
1
+ {
2
+ "name": "mehdi-akbari-ai-assistant-free",
3
+ "version": "0.0.1",
4
+ "description": "Professional AI Chatbot Library",
5
+ "main": "./dist/index.js",
6
+ "module": "./dist/index.mjs",
7
+ "types": "./dist/index.d.ts",
8
+ "exports": {
9
+ ".": {
10
+ "types": "./dist/index.d.ts",
11
+ "import": "./dist/index.mjs",
12
+ "require": "./dist/index.js"
13
+ },
14
+ "./react": {
15
+ "types": "./dist/react.d.ts",
16
+ "import": "./dist/react.mjs",
17
+ "require": "./dist/react.js"
18
+ },
19
+ "./dist/react.css": "./dist/react.css"
20
+ },
21
+ "files": [
22
+ "dist"
23
+ ],
24
+ "scripts": {
25
+ "build": "tsup",
26
+ "dev": "tsup --watch",
27
+ "prepublishOnly": "npm run build"
28
+ },
29
+ "peerDependencies": {
30
+ "react": ">=18",
31
+ "react-dom": ">=18"
32
+ },
33
+ "dependencies": {
34
+ "@langchain/core": "^0.1.0",
35
+ "@langchain/groq": "^0.0.14",
36
+ "clsx": "^2.1.0",
37
+ "lucide-react": "^0.300.0"
38
+ },
39
+ "devDependencies": {
40
+ "@types/react": "^18.3.27",
41
+ "@types/react-dom": "^18.3.7",
42
+ "react": "^18.3.1",
43
+ "react-dom": "^18.3.1",
44
+ "tsup": "^8.5.1",
45
+ "typescript": "^5.9.3"
46
+ }
47
+ }