mehdi-ai-assistant 0.0.2 → 0.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/react.css +48 -42
- package/dist/react.css.map +1 -1
- package/dist/react.d.mts +4 -13
- package/dist/react.d.ts +4 -13
- package/dist/react.js +106 -92
- package/dist/react.js.map +1 -1
- package/dist/react.mjs +106 -91
- package/dist/react.mjs.map +1 -1
- package/package.json +1 -1
package/dist/react.css
CHANGED
|
@@ -1,14 +1,14 @@
|
|
|
1
|
-
/* src/
|
|
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-
|
|
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-
|
|
10
|
-
--ai-
|
|
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 */
|
package/dist/react.css.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/
|
|
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
|
-
|
|
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
|
|
6
|
-
/** آدرس ایپیآی که کاربر در پروژه خودش ساخته */
|
|
4
|
+
interface ChatWindowProps {
|
|
7
5
|
apiEndpoint: string;
|
|
8
|
-
/** عنوان بالای چت باکس */
|
|
9
6
|
title?: string;
|
|
10
|
-
/** پیام خوشآمدگویی اولیه */
|
|
11
7
|
welcomeMessage?: string;
|
|
12
8
|
}
|
|
13
|
-
declare const
|
|
9
|
+
declare const ChatWindow: React.FC<ChatWindowProps>;
|
|
14
10
|
|
|
15
|
-
|
|
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
|
-
|
|
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
|
|
6
|
-
/** آدرس ایپیآی که کاربر در پروژه خودش ساخته */
|
|
4
|
+
interface ChatWindowProps {
|
|
7
5
|
apiEndpoint: string;
|
|
8
|
-
/** عنوان بالای چت باکس */
|
|
9
6
|
title?: string;
|
|
10
|
-
/** پیام خوشآمدگویی اولیه */
|
|
11
7
|
welcomeMessage?: string;
|
|
12
8
|
}
|
|
13
|
-
declare const
|
|
9
|
+
declare const ChatWindow: React.FC<ChatWindowProps>;
|
|
14
10
|
|
|
15
|
-
|
|
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
|
-
|
|
35
|
-
MessageBubble: () => MessageBubble
|
|
34
|
+
ChatWindow: () => ChatWindow
|
|
36
35
|
});
|
|
37
36
|
module.exports = __toCommonJS(react_exports);
|
|
38
37
|
|
|
39
|
-
// src/components/
|
|
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/
|
|
43
|
-
var
|
|
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/
|
|
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
|
|
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,
|
|
81
|
-
const [
|
|
82
|
-
|
|
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
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
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:
|
|
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
|
-
|
|
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
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
}
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
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
|
-
|
|
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/
|
|
4
|
-
import { useState
|
|
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/
|
|
7
|
-
var
|
|
7
|
+
// src/components/ChatWindow/ChatWindow.module.css
|
|
8
|
+
var ChatWindow_default = {};
|
|
8
9
|
|
|
9
|
-
// src/components/
|
|
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/
|
|
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
|
|
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] =
|
|
45
|
-
const [
|
|
46
|
-
|
|
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
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
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:
|
|
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
|
-
|
|
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
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
}
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
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
|
-
|
|
128
|
-
MessageBubble
|
|
143
|
+
ChatWindow
|
|
129
144
|
};
|
|
130
145
|
//# sourceMappingURL=react.mjs.map
|
package/dist/react.mjs.map
CHANGED
|
@@ -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"]}
|