aizek-chatbot 1.0.8 → 1.0.10

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/index.mjs CHANGED
@@ -4,6 +4,7 @@ import { jsx, jsxs, Fragment } from 'react/jsx-runtime';
4
4
  import OpenAI from 'openai';
5
5
  import ReactMarkdown from 'react-markdown';
6
6
  import remarkGfm from 'remark-gfm';
7
+ import DOMPurify from 'dompurify';
7
8
 
8
9
  // src/utils/cx.ts
9
10
  function cx(...args) {
@@ -97,7 +98,7 @@ var Button = React.forwardRef(
97
98
  );
98
99
  Button.displayName = "Button";
99
100
  var useChatbot = (options = {}) => {
100
- const { mcpUrl, apiKey } = options;
101
+ const { mcpUrl, apiKey, config } = options;
101
102
  const client = new OpenAI({ apiKey, dangerouslyAllowBrowser: true });
102
103
  const [responseId, setResponseId] = useState(null);
103
104
  const [messages, setMessages] = useState([]);
@@ -115,10 +116,197 @@ var useChatbot = (options = {}) => {
115
116
  setMessages((prev) => [...prev, newMessage]);
116
117
  return newMessage;
117
118
  };
119
+ const getHtmlUiInstructions = (config2) => {
120
+ const headerColor = config2?.headerBackground || "#f5f5f5";
121
+ const accentColor = config2?.buttonBackground || "#007bff";
122
+ return `
123
+ You are a helpful assistant that creates UI using ONLY HTML tags.
124
+
125
+ Your task:
126
+ - Read the user message and respond.
127
+ - Render your response as a small HTML layout (card OR table OR mini-table).
128
+ - Use inline CSS styles.
129
+ - Use a clean, light (white-based) theme.
130
+ - Use colors from options.config (headerBackground, buttonBackground).
131
+ - Return ONLY raw HTML (no markdown, no backticks, no JSON, no explanations).
132
+
133
+ ====================
134
+ THEME (from options.config)
135
+ ====================
136
+ The chat widget configuration provides:
137
+
138
+ - Header Background Color: ${headerColor}
139
+ - Button / Accent Color: ${accentColor}
140
+
141
+ How to use these:
142
+ - Use Header Background Color mainly for top headers, title strips, or main highlight areas.
143
+ - Use Button / Accent Color for important accents: borders, highlights, badges, table headers, key text highlights, links, etc.
144
+ - Use a white or very light background for main surfaces.
145
+ - Text color should generally be dark (#111\u2013#333) for readability.
146
+
147
+ ====================
148
+ ALLOWED / FORBIDDEN TAGS
149
+ ====================
150
+ You may use ANY NON-INTERACTIVE HTML element, for example:
151
+ - Text and headings:
152
+ <h1>, <h2>, <h3>, <h4>, <h5>, <h6>,
153
+ <p>, <span>, <strong>, <em>, <small>, <blockquote>, <code>, <pre>
154
+ - Layout:
155
+ <div>, <section>, <article>, <header>, <footer>
156
+ - Lists:
157
+ <ul>, <ol>, <li>
158
+ - Tables:
159
+ <table>, <thead>, <tbody>, <tr>, <th>, <td>
160
+ - Media:
161
+ <img>, <figure>, <figcaption>
162
+ - Links (non-interactive navigation style only):
163
+ <a>
164
+
165
+ GENERAL RULE:
166
+ - In NORMAL responses, you MUST NOT use <button>.
167
+
168
+ FORBIDDEN (NORMAL MODE):
169
+ - <button>, <input>, <textarea>, <select>, <option>, <form>, <label>
170
+ - <details>, <summary>, <dialog>
171
+ - <video> or <audio> with controls for user interaction
172
+ - Any inline event handlers like onclick, onmouseover, etc.
173
+ - <script> or any JavaScript code.
174
+
175
+ ====================
176
+ LAYOUT TYPE RULES
177
+ ====================
178
+ You have exactly THREE layout types you can use:
179
+
180
+ 1) CARD
181
+ 2) TABLE
182
+ 3) MINI TABLE
183
+
184
+ For EACH response:
185
+ - You MUST choose exactly ONE of these layout types.
186
+ - You MUST NOT mix layout types in the same response.
187
+ (Do NOT render card + table together, or table + mini-table together.)
188
+
189
+ Which layout to choose:
190
+ - CARD (DEFAULT):
191
+ - Use this for normal answers, explanations, descriptions, welcome messages,
192
+ and any content that is mostly free text.
193
+ - TABLE:
194
+ - Use this ONLY when the content is clearly structured with multiple columns
195
+ (for example: comparisons, lists of items with several attributes).
196
+ - MINI TABLE:
197
+ - Use this for small, compact key-value style data
198
+ (for example: a few fields like "Token", "Price", "Network"),
199
+ or when a full table would be visually too heavy.
200
+
201
+ If the user does NOT explicitly ask for a table or very structured data,
202
+ you MUST use the CARD layout.
203
+
204
+ ====================
205
+ STYLE RULES
206
+ ====================
207
+ General style (CARD or container):
208
+ - Use a main wrapper <div> with styles similar to:
209
+ background: #ffffff;
210
+ color: #111111;
211
+ border: 1px solid #e5e5e5;
212
+ border-radius: 8px;
213
+ padding: 12px;
214
+ font-family: system-ui, -apple-system, BlinkMacSystemFont, "Segoe UI", sans-serif;
215
+
216
+ Header area (if you use one):
217
+ - You may add a top header area using the header background color:
218
+ background: ${headerColor};
219
+
220
+ Typography:
221
+ - Titles: 18\u201322px, bold.
222
+ - Body text: 12\u201316px, regular.
223
+ - Line-height should be comfortable (around 1.4\u20131.6).
224
+
225
+ Tables:
226
+ - Use <table> with <thead> and <tbody> where appropriate.
227
+ - Header row background: ${accentColor};
228
+ - Header row text color: #ffffff;
229
+ - Body rows background: #ffffff;
230
+ - Row borders: 1px solid #e5e5e5 (or a faint version of the border color).
231
+
232
+ Mini table:
233
+ - Can be a simple two-column table or stacked key-value pairs.
234
+ - Keep it compact (less padding, fewer rows).
235
+
236
+ Links:
237
+ - You can use <a> for styling or static URLs.
238
+ - Use the accent color for links:
239
+ color: ${accentColor};
240
+
241
+ ====================
242
+ CONFIRMATION MODE (SPECIAL CASE)
243
+ ====================
244
+ Sometimes, during a workflow or tool usage, you may need the user to confirm an action
245
+ (e.g., deleting a workflow, sending a transaction, performing an irreversible change).
246
+
247
+ In such CONFIRMATION cases ONLY:
248
+ - You ARE allowed to use exactly TWO <button> elements.
249
+ - They MUST be rendered with these exact data attributes:
250
+
251
+ <button data-ai-action="approve">Onayla</button>
252
+ <button data-ai-action="cancel">Vazge\xE7</button>
253
+
254
+ Rules for confirmation buttons:
255
+ - Do NOT add onclick or any other JS event attributes.
256
+ - Do NOT add custom data attributes besides data-ai-action.
257
+ - The host application will detect these buttons by data-ai-action
258
+ and will send the following messages back to you:
259
+ "__APPROVE__" when the user clicks "Onayla"
260
+ "__CANCEL__" when the user clicks "Vazge\xE7"
261
+
262
+ Behavior after user choice:
263
+ - When you receive "__APPROVE__", behave as if the user confirmed YES.
264
+ - When you receive "__CANCEL__", behave as if the user declined or cancelled.
265
+ - After that, go back to NORMAL mode and return standard HTML output again
266
+ (card, table, or mini table, WITHOUT <button>).
267
+
268
+ IMPORTANT:
269
+ - In NORMAL responses (no confirmation needed), you MUST NOT use <button>.
270
+ - In CONFIRMATION MODE, you MUST use exactly these two buttons and NO others.
271
+
272
+ ====================
273
+ OUTPUT FORMAT
274
+ ====================
275
+ Your final output MUST follow these rules:
276
+ - Output ONLY a single HTML snippet.
277
+ - Do NOT wrap it in backticks or markdown.
278
+ - Do NOT include any explanation text.
279
+ - Do NOT include JSON.
280
+ - Must use exactly ONE of: card, table, mini table.
281
+ - Must respect allowed/forbidden tags.
282
+ - Must use colors derived from:
283
+ - headerBackground
284
+ - buttonBackground
285
+ and otherwise a light theme.
286
+
287
+ ====================
288
+ BEHAVIOR SUMMARY
289
+ ====================
290
+ 1) Read the user message.
291
+ 2) If it is a normal response:
292
+ - Decide whether CARD, TABLE, or MINI TABLE is most suitable.
293
+ - Generate a single HTML layout using only allowed, non-interactive tags (no <button>).
294
+ 3) If you need explicit user confirmation:
295
+ - Enter CONFIRMATION MODE.
296
+ - Render a short explanation AND exactly two <button> elements with:
297
+ data-ai-action="approve" and data-ai-action="cancel".
298
+ 4) Style the layout with inline CSS using:
299
+ - ${headerColor} for header areas,
300
+ - ${accentColor} for accents,
301
+ - white/light backgrounds and dark text.
302
+ 5) Return ONLY the HTML snippet.
303
+ `;
304
+ };
118
305
  const sendMessage = async (message) => {
119
306
  if (!message.trim() || isLoading) return;
120
307
  addMessage(message, "user");
121
308
  setIsLoading(true);
309
+ console.log(options.config);
122
310
  try {
123
311
  let resp;
124
312
  console.log(options.headers);
@@ -134,14 +322,17 @@ var useChatbot = (options = {}) => {
134
322
  }
135
323
  ],
136
324
  input: message,
137
- previous_response_id: responseId || void 0
325
+ previous_response_id: responseId || void 0,
326
+ instructions: getHtmlUiInstructions(options.config)
138
327
  });
139
328
  setResponseId(resp.id);
140
329
  let responseText = "";
141
330
  if (resp && Array.isArray(resp)) {
142
331
  const messageItem = resp.find((item) => item.type === "message");
143
332
  if (messageItem && messageItem.content && Array.isArray(messageItem.content)) {
144
- const textContent = messageItem.content.find((content) => content.type === "output_text");
333
+ const textContent = messageItem.content.find(
334
+ (content) => content.type === "output_text"
335
+ );
145
336
  if (textContent && textContent.text) {
146
337
  responseText = textContent.text;
147
338
  }
@@ -160,7 +351,10 @@ var useChatbot = (options = {}) => {
160
351
  setIsLoading(false);
161
352
  } catch (error) {
162
353
  console.error("Error sending message:", error);
163
- addMessage("\xDCzg\xFCn\xFCm, bir hata olu\u015Ftu. L\xFCtfen tekrar deneyin.", "assistant");
354
+ addMessage(
355
+ "\xDCzg\xFCn\xFCm, bir hata olu\u015Ftu. L\xFCtfen tekrar deneyin.",
356
+ "assistant"
357
+ );
164
358
  setIsLoading(false);
165
359
  }
166
360
  };
@@ -219,7 +413,8 @@ var mapApiSettingsToConfig = (apiSettings) => {
219
413
  };
220
414
 
221
415
  // src/styles/messageStyles.ts
222
- var getMessageBubbleStyles = (isUser) => ({
416
+ var getMessageBubbleStyles = (isUser, isTyping) => ({
417
+ display: !isTyping && !isUser ? "none" : "block",
223
418
  maxWidth: "80%",
224
419
  padding: "12px 16px",
225
420
  borderRadius: isUser ? "18px 18px 4px 18px" : "18px 18px 18px 4px",
@@ -695,7 +890,10 @@ var getAlertAnimationStyles = () => `
695
890
  }
696
891
  }
697
892
  `;
698
- var AizekChatBot = ({ clientId, headers }) => {
893
+ var AizekChatBot = ({
894
+ clientId,
895
+ headers
896
+ }) => {
699
897
  const defaultConfig = {
700
898
  welcomeMessage: "Merhaba! Size nas\u0131l yard\u0131mc\u0131 olabilirim?",
701
899
  buttonBackground: "linear-gradient(135deg, #667eea 0%, #764ba2 100%)",
@@ -714,27 +912,47 @@ var AizekChatBot = ({ clientId, headers }) => {
714
912
  const [isConfigLoading, setIsConfigLoading] = useState(true);
715
913
  const [finalMcpUrl, setFinalMcpUrl] = useState("");
716
914
  const [apiKey, setApiKey] = useState("");
717
- const [validConfig, setValidConfig] = useState(false);
718
- const { welcomeMessage, buttonBackground, placeholder, buttonPosition, buttonSize, chatWidth, chatHeight, showTypingIndicator, initialOpen, headerBackground, companyLogo, companyName } = config;
915
+ const {
916
+ welcomeMessage,
917
+ buttonBackground,
918
+ placeholder,
919
+ buttonPosition,
920
+ buttonSize,
921
+ chatWidth,
922
+ chatHeight,
923
+ showTypingIndicator,
924
+ initialOpen,
925
+ headerBackground,
926
+ companyLogo,
927
+ companyName
928
+ } = config;
719
929
  const [isOpen, setIsOpen] = useState(false);
720
930
  const [headerValidation, setHeaderValidation] = useState(null);
721
931
  const [showAlert, setShowAlert] = useState(true);
932
+ console.log("Component rendered");
722
933
  useEffect(() => {
934
+ console.log("use");
723
935
  const loadConfig = async () => {
724
936
  try {
725
937
  setIsConfigLoading(true);
726
938
  const apiResponse = await fetchChatWidgetSettings(clientId);
727
939
  if (headers && apiResponse.data.auth_config) {
728
- const validationResult = validateHeaders(headers, apiResponse.data.auth_config, {
729
- allowExtra: false,
730
- caseSensitive: true
731
- });
940
+ const validationResult = validateHeaders(
941
+ headers,
942
+ apiResponse.data.auth_config,
943
+ {
944
+ allowExtra: false,
945
+ caseSensitive: true
946
+ }
947
+ );
732
948
  console.log(validationResult);
733
949
  setHeaderValidation(validationResult);
734
950
  }
735
951
  setFinalMcpUrl(apiResponse.data.mcp_url);
736
952
  setApiKey(apiResponse.data.openai_key || "");
737
- const apiConfig = mapApiSettingsToConfig(apiResponse.data.chat_widget_settings);
953
+ const apiConfig = mapApiSettingsToConfig(
954
+ apiResponse.data.chat_widget_settings
955
+ );
738
956
  if (apiConfig) {
739
957
  setConfig(apiConfig);
740
958
  }
@@ -747,7 +965,12 @@ var AizekChatBot = ({ clientId, headers }) => {
747
965
  };
748
966
  loadConfig();
749
967
  }, [clientId]);
750
- const internalChatbot = useChatbot({ mcpUrl: finalMcpUrl, apiKey, headers });
968
+ const internalChatbot = useChatbot({
969
+ mcpUrl: finalMcpUrl,
970
+ apiKey,
971
+ headers,
972
+ config
973
+ });
751
974
  const messages = internalChatbot.messages;
752
975
  const isLoading = internalChatbot.isLoading;
753
976
  const handleSendMessage = internalChatbot.sendMessage;
@@ -762,18 +985,39 @@ var AizekChatBot = ({ clientId, headers }) => {
762
985
  useEffect(() => {
763
986
  messagesEndRef.current?.scrollIntoView({ behavior: "smooth" });
764
987
  }, [messages]);
765
- const MessageBubble = ({ message }) => {
988
+ const MessageBubble = ({ message, onAction }) => {
766
989
  const isUser = message.role === "user";
990
+ const cleanContent = DOMPurify.sanitize(message.content);
991
+ const htmlRef = useRef(null);
992
+ useEffect(() => {
993
+ if (!htmlRef.current || isUser) return;
994
+ const root = htmlRef.current;
995
+ const approveBtn = root.querySelector(
996
+ 'button[data-ai-action="approve"]'
997
+ );
998
+ const cancelBtn = root.querySelector(
999
+ 'button[data-ai-action="cancel"]'
1000
+ );
1001
+ const handleApprove = () => onAction("__APPROVE__");
1002
+ const handleCancel = () => onAction("__CANCEL__");
1003
+ if (approveBtn) approveBtn.addEventListener("click", handleApprove);
1004
+ if (cancelBtn) cancelBtn.addEventListener("click", handleCancel);
1005
+ return () => {
1006
+ if (approveBtn) approveBtn.removeEventListener("click", handleApprove);
1007
+ if (cancelBtn) cancelBtn.removeEventListener("click", handleCancel);
1008
+ };
1009
+ }, [message.content, isUser, onAction]);
767
1010
  return /* @__PURE__ */ jsxs("div", { style: getMessageContainerStyles(isUser), children: [
768
1011
  /* @__PURE__ */ jsx("style", { children: getMarkdownElementStyles(isUser) }),
769
- /* @__PURE__ */ jsxs("div", { style: getMessageBubbleStyles(isUser), children: [
770
- /* @__PURE__ */ jsx("div", { style: getMarkdownStyles(), className: "markdown-content", children: /* @__PURE__ */ jsx(ReactMarkdown, { remarkPlugins: [remarkGfm], children: message.content }) }),
1012
+ /* @__PURE__ */ jsxs("div", { style: getMessageBubbleStyles(isUser, message.isTyping ?? false), children: [
1013
+ isUser && /* @__PURE__ */ jsx("div", { style: getMarkdownStyles(), className: "markdown-content", children: /* @__PURE__ */ jsx(ReactMarkdown, { remarkPlugins: [remarkGfm], children: message.content }) }),
771
1014
  message.isTyping && /* @__PURE__ */ jsx("div", { style: {
772
1015
  display: "inline-flex",
773
1016
  alignItems: "center",
774
1017
  marginLeft: "8px"
775
1018
  }, children: /* @__PURE__ */ jsx(TypingDots, {}) })
776
1019
  ] }),
1020
+ !isUser && /* @__PURE__ */ jsx("div", { dangerouslySetInnerHTML: { __html: cleanContent } }),
777
1021
  /* @__PURE__ */ jsx("div", { style: getTimeStyles(isUser), children: message.timestamp.toLocaleTimeString("tr-TR", {
778
1022
  hour: "2-digit",
779
1023
  minute: "2-digit"
@@ -818,60 +1062,102 @@ var AizekChatBot = ({ clientId, headers }) => {
818
1062
  missingKeys.length > 0 && /* @__PURE__ */ jsxs("div", { children: [
819
1063
  /* @__PURE__ */ jsx("strong", { style: { fontSize: "13px" }, children: "Eksik Header'lar:" }),
820
1064
  /* @__PURE__ */ jsx("ul", { style: getAlertListStyles(), children: missingKeys.map((key, index) => /* @__PURE__ */ jsxs("li", { style: getAlertListItemStyles(), children: [
821
- /* @__PURE__ */ jsx("span", { style: {
822
- position: "absolute",
823
- left: "0",
824
- top: "2px",
825
- fontWeight: "bold"
826
- }, children: "\u2022" }),
827
- /* @__PURE__ */ jsx("code", { style: {
828
- background: "rgba(255, 255, 255, 0.2)",
829
- padding: "2px 6px",
830
- borderRadius: "4px",
831
- fontFamily: "monospace",
832
- fontSize: "12px"
833
- }, children: key })
1065
+ /* @__PURE__ */ jsx(
1066
+ "span",
1067
+ {
1068
+ style: {
1069
+ position: "absolute",
1070
+ left: "0",
1071
+ top: "2px",
1072
+ fontWeight: "bold"
1073
+ },
1074
+ children: "\u2022"
1075
+ }
1076
+ ),
1077
+ /* @__PURE__ */ jsx(
1078
+ "code",
1079
+ {
1080
+ style: {
1081
+ background: "rgba(255, 255, 255, 0.2)",
1082
+ padding: "2px 6px",
1083
+ borderRadius: "4px",
1084
+ fontFamily: "monospace",
1085
+ fontSize: "12px"
1086
+ },
1087
+ children: key
1088
+ }
1089
+ )
834
1090
  ] }, index)) })
835
1091
  ] }),
836
1092
  emptyValueKeys.length > 0 && /* @__PURE__ */ jsxs("div", { children: [
837
1093
  /* @__PURE__ */ jsx("strong", { style: { fontSize: "13px" }, children: "Bo\u015F De\u011Ferli Header'lar:" }),
838
1094
  /* @__PURE__ */ jsx("ul", { style: getAlertListStyles(), children: emptyValueKeys.map((key, index) => /* @__PURE__ */ jsxs("li", { style: getAlertListItemStyles(), children: [
839
- /* @__PURE__ */ jsx("span", { style: {
840
- position: "absolute",
841
- left: "0",
842
- top: "2px",
843
- fontWeight: "bold"
844
- }, children: "\u2022" }),
845
- /* @__PURE__ */ jsx("code", { style: {
846
- background: "rgba(255, 255, 255, 0.2)",
847
- padding: "2px 6px",
848
- borderRadius: "4px",
849
- fontFamily: "monospace",
850
- fontSize: "12px"
851
- }, children: key }),
852
- /* @__PURE__ */ jsx("span", { style: {
853
- marginLeft: "6px",
854
- fontSize: "11px",
855
- opacity: 0.9
856
- }, children: "(de\u011Fer bo\u015F olamaz)" })
1095
+ /* @__PURE__ */ jsx(
1096
+ "span",
1097
+ {
1098
+ style: {
1099
+ position: "absolute",
1100
+ left: "0",
1101
+ top: "2px",
1102
+ fontWeight: "bold"
1103
+ },
1104
+ children: "\u2022"
1105
+ }
1106
+ ),
1107
+ /* @__PURE__ */ jsx(
1108
+ "code",
1109
+ {
1110
+ style: {
1111
+ background: "rgba(255, 255, 255, 0.2)",
1112
+ padding: "2px 6px",
1113
+ borderRadius: "4px",
1114
+ fontFamily: "monospace",
1115
+ fontSize: "12px"
1116
+ },
1117
+ children: key
1118
+ }
1119
+ ),
1120
+ /* @__PURE__ */ jsx(
1121
+ "span",
1122
+ {
1123
+ style: {
1124
+ marginLeft: "6px",
1125
+ fontSize: "11px",
1126
+ opacity: 0.9
1127
+ },
1128
+ children: "(de\u011Fer bo\u015F olamaz)"
1129
+ }
1130
+ )
857
1131
  ] }, index)) })
858
1132
  ] }),
859
1133
  extraKeys.length > 0 && /* @__PURE__ */ jsxs("div", { children: [
860
1134
  /* @__PURE__ */ jsx("strong", { style: { fontSize: "13px" }, children: "Fazla Header'lar:" }),
861
1135
  /* @__PURE__ */ jsx("ul", { style: getAlertListStyles(), children: extraKeys.map((key, index) => /* @__PURE__ */ jsxs("li", { style: getAlertListItemStyles(), children: [
862
- /* @__PURE__ */ jsx("span", { style: {
863
- position: "absolute",
864
- left: "0",
865
- top: "2px",
866
- fontWeight: "bold"
867
- }, children: "\u2022" }),
868
- /* @__PURE__ */ jsx("code", { style: {
869
- background: "rgba(255, 255, 255, 0.2)",
870
- padding: "2px 6px",
871
- borderRadius: "4px",
872
- fontFamily: "monospace",
873
- fontSize: "12px"
874
- }, children: key })
1136
+ /* @__PURE__ */ jsx(
1137
+ "span",
1138
+ {
1139
+ style: {
1140
+ position: "absolute",
1141
+ left: "0",
1142
+ top: "2px",
1143
+ fontWeight: "bold"
1144
+ },
1145
+ children: "\u2022"
1146
+ }
1147
+ ),
1148
+ /* @__PURE__ */ jsx(
1149
+ "code",
1150
+ {
1151
+ style: {
1152
+ background: "rgba(255, 255, 255, 0.2)",
1153
+ padding: "2px 6px",
1154
+ borderRadius: "4px",
1155
+ fontFamily: "monospace",
1156
+ fontSize: "12px"
1157
+ },
1158
+ children: key
1159
+ }
1160
+ )
875
1161
  ] }, index)) })
876
1162
  ] })
877
1163
  ] }),
@@ -954,7 +1240,18 @@ var AizekChatBot = ({ clientId, headers }) => {
954
1240
  return /* @__PURE__ */ jsx("div", { style: getLoadingSpinnerStyles() });
955
1241
  };
956
1242
  if (isConfigLoading) {
957
- return /* @__PURE__ */ jsx("div", { style: getFloatingButtonStyles(buttonPosition, buttonSize, buttonBackground, false), children: /* @__PURE__ */ jsx("div", { style: getLoadingSpinnerStyles() }) });
1243
+ return /* @__PURE__ */ jsx(
1244
+ "div",
1245
+ {
1246
+ style: getFloatingButtonStyles(
1247
+ buttonPosition,
1248
+ buttonSize,
1249
+ buttonBackground,
1250
+ false
1251
+ ),
1252
+ children: /* @__PURE__ */ jsx("div", { style: getLoadingSpinnerStyles() })
1253
+ }
1254
+ );
958
1255
  }
959
1256
  return /* @__PURE__ */ jsxs(Fragment, { children: [
960
1257
  isOpen && /* @__PURE__ */ jsx(
@@ -965,49 +1262,74 @@ var AizekChatBot = ({ clientId, headers }) => {
965
1262
  className: "floating-chat-overlay"
966
1263
  }
967
1264
  ),
968
- /* @__PURE__ */ jsx("div", { style: getChatContainerStyles(buttonPosition, chatWidth, chatHeight, isOpen), className: "floating-chat-container", children: /* @__PURE__ */ jsxs("div", { style: getChatbotContainerStyles(), children: [
969
- /* @__PURE__ */ jsxs("div", { style: getHeaderStyles(headerBackground), children: [
970
- /* @__PURE__ */ jsx("div", { style: getLogoContainerStyles(), children: companyLogo ? companyLogo.startsWith("http") || companyLogo.startsWith("data:") ? /* @__PURE__ */ jsx(
971
- "img",
972
- {
973
- src: companyLogo,
974
- alt: "Company Logo",
975
- style: getLogoImageStyles()
976
- }
977
- ) : /* @__PURE__ */ jsx("span", { style: getLogoTextStyles(), children: companyLogo }) : "\u{1F916}" }),
978
- /* @__PURE__ */ jsxs("div", { children: [
979
- /* @__PURE__ */ jsx("h3", { style: getCompanyNameStyles(), children: companyName }),
980
- /* @__PURE__ */ jsx("p", { style: getStatusTextStyles(), children: isLoading ? "Yaz\u0131yor..." : "\xC7evrimi\xE7i" })
981
- ] })
982
- ] }),
983
- /* @__PURE__ */ jsxs("div", { style: getMessagesContainerStyles(), children: [
984
- /* @__PURE__ */ jsx(HeaderValidationAlert, {}),
985
- messages.length === 0 ? /* @__PURE__ */ jsxs("div", { style: getEmptyStateStyles(), children: [
986
- /* @__PURE__ */ jsx("div", { style: { fontSize: "48px", marginBottom: "16px" }, children: "\u{1F4AC}" }),
987
- /* @__PURE__ */ jsx("h4", { style: { margin: "0 0 8px 0", fontSize: "18px" }, children: welcomeMessage }),
988
- /* @__PURE__ */ jsx("p", { style: { margin: 0, fontSize: "14px", opacity: 0.8 }, children: "A\u015Fa\u011F\u0131daki alana mesaj\u0131n\u0131z\u0131 yazarak ba\u015Flayabilirsiniz." })
989
- ] }) : messages.map((message) => /* @__PURE__ */ jsx(MessageBubble, { message }, message.id)),
990
- showTypingIndicator && isLoading && messages.length > 0 && /* @__PURE__ */ jsx(
991
- MessageBubble,
992
- {
993
- message: {
994
- id: "typing",
995
- content: "",
996
- role: "assistant",
997
- timestamp: /* @__PURE__ */ new Date(),
998
- isTyping: true
999
- }
1000
- }
1265
+ /* @__PURE__ */ jsx(
1266
+ "div",
1267
+ {
1268
+ style: getChatContainerStyles(
1269
+ buttonPosition,
1270
+ chatWidth,
1271
+ chatHeight,
1272
+ isOpen
1001
1273
  ),
1002
- /* @__PURE__ */ jsx("div", { ref: messagesEndRef })
1003
- ] }),
1004
- /* @__PURE__ */ jsx(ChatInput, {})
1005
- ] }) }),
1274
+ className: "floating-chat-container",
1275
+ children: /* @__PURE__ */ jsxs("div", { style: getChatbotContainerStyles(), children: [
1276
+ /* @__PURE__ */ jsxs("div", { style: getHeaderStyles(headerBackground), children: [
1277
+ /* @__PURE__ */ jsx("div", { style: getLogoContainerStyles(), children: companyLogo ? companyLogo.startsWith("http") || companyLogo.startsWith("data:") ? /* @__PURE__ */ jsx(
1278
+ "img",
1279
+ {
1280
+ src: companyLogo,
1281
+ alt: "Company Logo",
1282
+ style: getLogoImageStyles()
1283
+ }
1284
+ ) : /* @__PURE__ */ jsx("span", { style: getLogoTextStyles(), children: companyLogo }) : "\u{1F916}" }),
1285
+ /* @__PURE__ */ jsxs("div", { children: [
1286
+ /* @__PURE__ */ jsx("h3", { style: getCompanyNameStyles(), children: companyName }),
1287
+ /* @__PURE__ */ jsx("p", { style: getStatusTextStyles(), children: isLoading ? "Yaz\u0131yor..." : "\xC7evrimi\xE7i" })
1288
+ ] })
1289
+ ] }),
1290
+ /* @__PURE__ */ jsxs("div", { style: getMessagesContainerStyles(), children: [
1291
+ /* @__PURE__ */ jsx(HeaderValidationAlert, {}),
1292
+ messages.length === 0 ? /* @__PURE__ */ jsxs("div", { style: getEmptyStateStyles(), children: [
1293
+ /* @__PURE__ */ jsx("div", { style: { fontSize: "48px", marginBottom: "16px" }, children: "\u{1F4AC}" }),
1294
+ /* @__PURE__ */ jsx("h4", { style: { margin: "0 0 8px 0", fontSize: "18px" }, children: welcomeMessage }),
1295
+ /* @__PURE__ */ jsx("p", { style: { margin: 0, fontSize: "14px", opacity: 0.8 }, children: "A\u015Fa\u011F\u0131daki alana mesaj\u0131n\u0131z\u0131 yazarak ba\u015Flayabilirsiniz." })
1296
+ ] }) : messages.map((message) => /* @__PURE__ */ jsx(
1297
+ MessageBubble,
1298
+ {
1299
+ message,
1300
+ onAction: handleSendMessage
1301
+ },
1302
+ message.id
1303
+ )),
1304
+ showTypingIndicator && isLoading && messages.length > 0 && /* @__PURE__ */ jsx(
1305
+ MessageBubble,
1306
+ {
1307
+ message: {
1308
+ id: "typing",
1309
+ content: "",
1310
+ role: "assistant",
1311
+ timestamp: /* @__PURE__ */ new Date(),
1312
+ isTyping: true
1313
+ },
1314
+ onAction: handleSendMessage
1315
+ }
1316
+ ),
1317
+ /* @__PURE__ */ jsx("div", { ref: messagesEndRef })
1318
+ ] }),
1319
+ /* @__PURE__ */ jsx(ChatInput, {})
1320
+ ] })
1321
+ }
1322
+ ),
1006
1323
  /* @__PURE__ */ jsx(
1007
1324
  "button",
1008
1325
  {
1009
1326
  onClick: toggleChat,
1010
- style: getFloatingButtonStyles(buttonPosition, buttonSize, buttonBackground, isOpen),
1327
+ style: getFloatingButtonStyles(
1328
+ buttonPosition,
1329
+ buttonSize,
1330
+ buttonBackground,
1331
+ isOpen
1332
+ ),
1011
1333
  onMouseEnter: (e) => {
1012
1334
  e.currentTarget.style.transform = isOpen ? "scale(0.85)" : "scale(1.1)";
1013
1335
  e.currentTarget.style.boxShadow = "0 6px 20px rgba(0, 0, 0, 0.25)";