aizek-chatbot 1.0.10 → 1.0.11

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,7 +4,6 @@ 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';
8
7
 
9
8
  // src/utils/cx.ts
10
9
  function cx(...args) {
@@ -106,210 +105,299 @@ var useChatbot = (options = {}) => {
106
105
  const generateId = () => {
107
106
  return Date.now().toString() + Math.random().toString(36).substr(2, 9);
108
107
  };
109
- const addMessage = (content, role) => {
108
+ const addMessage = (payload, role) => {
110
109
  const newMessage = {
111
110
  id: generateId(),
112
- content,
111
+ text: payload.text,
112
+ ui: payload.ui,
113
113
  role,
114
114
  timestamp: /* @__PURE__ */ new Date()
115
115
  };
116
116
  setMessages((prev) => [...prev, newMessage]);
117
117
  return newMessage;
118
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.
119
+ const extractUiComponents = (raw) => {
120
+ const regex = /```ui-component([\s\S]*?)```/g;
121
+ const components = [];
122
+ let cleaned = raw;
123
+ let match;
124
+ let componentIndex = 0;
125
+ while ((match = regex.exec(raw)) !== null) {
126
+ const block = match[1].trim();
127
+ try {
128
+ const json = JSON.parse(block);
129
+ if (json.type === "buttons" && json.data && typeof json.data === "object" && !Array.isArray(json.data)) {
130
+ if (json.data.options && Array.isArray(json.data.options)) {
131
+ json.data = json.data.options.map((opt) => {
132
+ if (opt.id && opt.label) {
133
+ return {
134
+ label: opt.label,
135
+ value: opt.id,
136
+ variant: opt.variant
137
+ };
138
+ }
139
+ return opt;
140
+ });
141
+ }
142
+ }
143
+ if (json.type === "table" && json.data) {
144
+ if (Array.isArray(json.data.columns) && json.data.columns.length > 0) {
145
+ const firstCol = json.data.columns[0];
146
+ if (typeof firstCol === "string") {
147
+ json.data.columns = json.data.columns.map(
148
+ (col, idx) => ({
149
+ id: `col-${idx}`,
150
+ label: col
151
+ })
152
+ );
153
+ }
154
+ }
155
+ if (Array.isArray(json.data.rows) && json.data.rows.length > 0) {
156
+ const firstRow = json.data.rows[0];
157
+ if (Array.isArray(firstRow) && typeof firstRow[0] === "string") {
158
+ json.data.rows = json.data.rows.map((row) => {
159
+ const rowObj = {};
160
+ json.data.columns.forEach((col, idx) => {
161
+ const colId = typeof col === "string" ? `col-${idx}` : col.id;
162
+ const cellValue = row[idx];
163
+ if (typeof cellValue === "string" && (cellValue.startsWith("http") || cellValue.startsWith("data:"))) {
164
+ rowObj[colId] = {
165
+ type: "image",
166
+ src: cellValue,
167
+ alt: ""
168
+ };
169
+ } else {
170
+ rowObj[colId] = {
171
+ type: "text",
172
+ value: cellValue || ""
173
+ };
174
+ }
175
+ });
176
+ return rowObj;
177
+ });
178
+ }
179
+ }
180
+ }
181
+ if (json.type === "form" && json.data) {
182
+ if (!json.data.id) {
183
+ json.data.id = json.id || `form-${componentIndex}`;
184
+ }
185
+ if (json.data.fields && Array.isArray(json.data.fields)) {
186
+ json.data.fields = json.data.fields.map((field) => {
187
+ if (field.optional !== void 0) {
188
+ field.required = !field.optional;
189
+ delete field.optional;
190
+ }
191
+ if (!field.type) {
192
+ field.type = "text";
193
+ }
194
+ if (field.options && Array.isArray(field.options)) {
195
+ const firstOption = field.options[0];
196
+ if (typeof firstOption === "string") {
197
+ field.options = field.options.map((opt) => ({
198
+ label: opt,
199
+ value: opt
200
+ }));
201
+ }
202
+ }
203
+ return field;
204
+ });
205
+ }
206
+ }
207
+ if (json.id && typeof json.id !== "string") {
208
+ json.id = String(json.id);
209
+ }
210
+ if (!json.id || !json.id.trim()) {
211
+ json.id = `ui-comp-${componentIndex}-${Date.now()}`;
212
+ }
213
+ components.push(json);
214
+ componentIndex++;
215
+ } catch (e) {
216
+ console.error("Invalid ui-component JSON:", e, block);
217
+ }
218
+ cleaned = cleaned.replace(match[0], "").trim();
219
+ }
220
+ return { text: cleaned, components };
221
+ };
222
+ const instructions = `You are Aizek, an AI assistant running in an environment with Model Context Protocol (MCP) tools.
124
223
 
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).
224
+ Your top priority is to USE MCP TOOLS whenever they can handle the user's request.
225
+ Do NOT bypass available tools to answer from generic knowledge, web browsing, or other external sources if a suitable MCP tool exists.
132
226
 
133
- ====================
134
- THEME (from options.config)
135
- ====================
136
- The chat widget configuration provides:
227
+ ==================================================
228
+ 1. GENERAL BEHAVIOR
229
+ ==================================================
137
230
 
138
- - Header Background Color: ${headerColor}
139
- - Button / Accent Color: ${accentColor}
231
+ - Default language: reply in the same language as the user (Turkish/English).
232
+ - Be concise and task-focused. Avoid small talk, philosophy, or meta-chat unless the user explicitly asks.
233
+ - Do not invent capabilities or tools that are not actually defined in the MCP tool list.
234
+ - If a tool call fails or returns an error, explain briefly and either:
235
+ - try again with a corrected call, or
236
+ - ask the user for the minimal extra info required.
140
237
 
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.
238
+ ==================================================
239
+ 2. MCP TOOL PRIORITY RULES
240
+ ==================================================
146
241
 
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>
242
+ ALWAYS prefer MCP tools over any other strategy WHEN:
164
243
 
165
- GENERAL RULE:
166
- - In NORMAL responses, you MUST NOT use <button>.
244
+ - The user asks for information that matches a tool's domain (weather, products, etc.).
245
+ - The user asks to perform an action (create/update/delete something) that an MCP tool can perform.
167
246
 
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.
247
+ Only if NO provided MCP tool is relevant may you fall back to:
248
+ 1) other tools such as web/browsing, or
249
+ 2) your own internal knowledge.
174
250
 
175
- ====================
176
- LAYOUT TYPE RULES
177
- ====================
178
- You have exactly THREE layout types you can use:
251
+ When deciding whether a tool is relevant:
252
+ - Read the tool name, description, and parameters.
253
+ - If it is even moderately related to what the user wants, you SHOULD try using it.
254
+ - Do NOT choose external (e.g., MGM, random APIs) sources when a matching MCP tool exists.
179
255
 
180
- 1) CARD
181
- 2) TABLE
182
- 3) MINI TABLE
256
+ If multiple tools could work:
257
+ - Choose the single BEST-FIT tool first.
258
+ - If the task clearly requires multiple tools (e.g., get weather then log it), you may call them sequentially.
183
259
 
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.)
260
+ ==================================================
261
+ 3. ACTION TOOLS VS. DRAFTS (IKAS MCP, PRODUCT CREATION)
262
+ ==================================================
188
263
 
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.
264
+ Some MCP tools can PERFORM REAL ACTIONS (e.g., create a product in an e-commerce system via ikas MCP).
200
265
 
201
- If the user does NOT explicitly ask for a table or very structured data,
202
- you MUST use the CARD layout.
266
+ Critical rule:
267
+ - If the user's intent is to PERFORM an action, you MUST call the appropriate tool.
268
+ - Do NOT just "simulate" the action or write a draft object.
269
+ - Do NOT stop at: "Burada \u015F\xF6yle bir \xFCr\xFCn olu\u015Fturabilirim..." and then not call the tool.
270
+ - The goal is that the side effect actually happens through the tool.
203
271
 
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;
272
+ Examples (Turkish / ikas):
215
273
 
216
- Header area (if you use one):
217
- - You may add a top header area using the header background color:
218
- background: ${headerColor};
274
+ 1) User:
275
+ "\u0130kas'ta yeni bir \xFCr\xFCn olu\u015Ftur:
276
+ isim: Siyah T-Shirt,
277
+ fiyat: 299 TL,
278
+ stok: 50,
279
+ kategori: Ti\u015F\xF6rtler."
219
280
 
220
- Typography:
221
- - Titles: 18\u201322px, bold.
222
- - Body text: 12\u201316px, regular.
223
- - Line-height should be comfortable (around 1.4\u20131.6).
281
+ \u2192 You MUST:
282
+ - Map these fields to the ikas product-creation tool schema.
283
+ - CALL the ikas MCP tool to actually create the product.
284
+ - Then answer with something like:
285
+ "\xDCr\xFCn ba\u015Far\u0131yla olu\u015Fturuldu. ID: <tool_output_id>, ad: Siyah T-Shirt, fiyat: 299 TL, stok: 50."
224
286
 
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).
287
+ \u2192 You MUST NOT:
288
+ - Only respond with a JSON draft or description like:
289
+ "\u015E\xF6yle bir taslak \xFCr\xFCn olu\u015Fturabilirsin: {...}"
290
+ without calling the tool.
231
291
 
232
- Mini table:
233
- - Can be a simple two-column table or stacked key-value pairs.
234
- - Keep it compact (less padding, fewer rows).
292
+ 2) If the tool requires fields that the user didn't provide (e.g. currency code, SKU):
293
+ - Ask ONLY the minimal clarifying question needed.
294
+ - Or, if the field is safely inferrable by convention (e.g. default currency for a given store), use the default.
235
295
 
236
- Links:
237
- - You can use <a> for styling or static URLs.
238
- - Use the accent color for links:
239
- color: ${accentColor};
296
+ 3) If the tool response indicates "draft" vs. "published" status:
297
+ - Respect the user's explicit intention.
298
+ - If the user says "taslak olarak kaydet", then request draft=true.
299
+ - If the user says "direkt yay\u0131na al" or clearly wants the product live, then request published/active status.
300
+ - Do NOT downgrade a clear "publish" intent into just a draft.
240
301
 
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).
302
+ ==================================================
303
+ 4. INTERPRETING USER INTENT
304
+ ==================================================
246
305
 
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:
306
+ - Treat verbs like "olu\u015Ftur", "yarat", "ekle", "sil", "g\xFCncelle", "publish et", "yay\u0131na al"
307
+ as strong indicators that an ACTION tool call is expected, not just text output.
250
308
 
251
- <button data-ai-action="approve">Onayla</button>
252
- <button data-ai-action="cancel">Vazge\xE7</button>
309
+ - Treat questions like "nas\u0131l yap\u0131l\u0131r?", "bana g\xF6ster", "\xF6rnek ver", "JSON tasla\u011F\u0131 olu\u015Ftur"
310
+ as more educational; then you may provide drafts/examples without executing tools,
311
+ UNLESS the user explicitly says they want the real action too.
253
312
 
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"
313
+ Examples:
261
314
 
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>).
315
+ - "\u0130kas'ta \xFCr\xFCn olu\u015Fturmay\u0131 bana JSON \xF6rne\u011Fiyle anlat\u0131r m\u0131s\u0131n?"
316
+ \u2192 Explain the schema, show a draft, you may skip real tool call unless they also say "ve bunu benim i\xE7in \u015Fimdi olu\u015Ftur."
267
317
 
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.
318
+ - "Benim ad\u0131ma bu \xFCr\xFCn\xFC ger\xE7ekten olu\u015Ftur ve yay\u0131na al."
319
+ \u2192 This MUST trigger the actual ikas MCP product-creation tool call.
320
+
321
+ ==================================================
322
+ 5. IRRELEVANT TOPICS & SCOPE
323
+ ==================================================
324
+
325
+ - Aizek's primary job in this environment is:
326
+ - Using MCP tools effectively (weather, e-commerce, etc.).
327
+ - Providing concise, helpful answers strictly related to the user's requests.
328
+
329
+ - Avoid:
330
+ - Long off-topic chats.
331
+ - Unnecessary explanations of MCP internals or tool schemas unless the user specifically asks.
332
+ - Using random non-MCP APIs or external services when an MCP tool already exists in that domain.
333
+
334
+ ==================================================
335
+ 6. TOOL-CALLING STYLE
336
+ ==================================================
337
+
338
+ When you decide to call a tool:
339
+ - Use the exact tool name and parameter schema given by the environment.
340
+ - Provide all required parameters; do NOT omit fields the schema marks as required.
341
+ - Prefer a single well-structured call over multiple fragmented ones whenever possible.
342
+
343
+ Once you receive tool results:
344
+ - Summarize them clearly for the user in natural language.
345
+ - If the user requested an action (e.g., create product, update something), confirm:
346
+ - What was done,
347
+ - Any IDs or references returned,
348
+ - Any next steps they might need.
271
349
 
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.
350
+ ==================================================
351
+ 7. FALLBACK LOGIC
352
+ ==================================================
286
353
 
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.
354
+ In this order of priority:
355
+
356
+ 1) If an MCP tool matches the user's request \u2192 USE IT.
357
+ 2) If no tool fits, and the user just needs information \u2192 answer from your own knowledge or other allowed tools.
358
+ 3) If the user asks something completely outside your domain/scope \u2192
359
+ - Briefly explain that it is outside Aizek's scope or that you have limited info,
360
+ - Offer to help only if you can still add value without contradicting previous rules.
361
+
362
+ Always keep in mind:
363
+ Your core value in this environment is to be an intelligent router and operator for MCP tools, not a generic, unconstrained chatbot.`;
364
+ const SYSTEM_PROMPT = `
365
+ You are a helpful assistant that can generate both natural language responses and UI components.
366
+
367
+ You MUST:
368
+ - Always respond with normal conversational text.
369
+ - Optionally include one or more UI components inside code blocks with language "ui-component".
370
+
371
+ When to use components:
372
+ - User needs to provide multiple structured values \u2192 generate a FORM
373
+ - User must choose among options \u2192 generate BUTTONS
374
+ - User must see structured data comparison \u2192 generate a TABLE
375
+ - User must see entity details/summary \u2192 generate a CARD
376
+
377
+ Format for each component (strictly):
378
+
379
+ \`\`\`ui-component
380
+ {
381
+ "type": "form" | "buttons" | "table" | "card",
382
+ "data": { ...component-specific fields... }
383
+ }
384
+ \`\`\`
385
+
386
+ IMPORTANT:
387
+ - Do NOT invent HTML. Only JSON as described.
388
+ - Keep JSON strictly valid.
389
+ - Text response should be outside of code blocks.
303
390
  `;
304
- };
305
- const sendMessage = async (message) => {
391
+ const sendMessage = async (message, approval) => {
306
392
  if (!message.trim() || isLoading) return;
307
- addMessage(message, "user");
393
+ if (approval) {
394
+ addMessage({ text: message }, "approval");
395
+ } else {
396
+ addMessage({ text: message }, "user");
397
+ }
308
398
  setIsLoading(true);
309
- console.log(options.config);
310
399
  try {
311
400
  let resp;
312
- console.log(options.headers);
313
401
  resp = await client.responses.create({
314
402
  model: "gpt-5",
315
403
  tools: [
@@ -321,38 +409,43 @@ BEHAVIOR SUMMARY
321
409
  headers: options.headers || {}
322
410
  }
323
411
  ],
324
- input: message,
412
+ input: [
413
+ { role: "system", content: SYSTEM_PROMPT },
414
+ { role: "user", content: message }
415
+ ],
325
416
  previous_response_id: responseId || void 0,
326
- instructions: getHtmlUiInstructions(options.config)
417
+ instructions
327
418
  });
419
+ console.log("Response:", resp);
328
420
  setResponseId(resp.id);
329
- let responseText = "";
330
- if (resp && Array.isArray(resp)) {
331
- const messageItem = resp.find((item) => item.type === "message");
332
- if (messageItem && messageItem.content && Array.isArray(messageItem.content)) {
333
- const textContent = messageItem.content.find(
334
- (content) => content.type === "output_text"
421
+ let rawText = "";
422
+ const output = resp.output;
423
+ if (Array.isArray(output) && output.length > 0) {
424
+ const assistantMsg = output.find((o) => o.role === "assistant") ?? output[0];
425
+ if (assistantMsg && Array.isArray(assistantMsg.content)) {
426
+ const textItem = assistantMsg.content.find(
427
+ (c) => c.type === "output_text"
335
428
  );
336
- if (textContent && textContent.text) {
337
- responseText = textContent.text;
429
+ if (textItem?.text?.value) {
430
+ rawText = textItem.text.value;
431
+ } else if (textItem?.text?.annotations?.[0]?.text) {
432
+ rawText = textItem.text.annotations[0].text;
338
433
  }
339
434
  }
340
- } else {
341
- if (resp && resp.output_text) {
342
- responseText = resp.output_text;
343
- } else if (typeof resp === "string") {
344
- responseText = resp;
345
- }
346
435
  }
347
- if (!responseText) {
348
- responseText = `"${message}" mesaj\u0131n\u0131z\u0131 ald\u0131m. Size nas\u0131l yard\u0131mc\u0131 olabilirim?`;
436
+ if (!rawText && resp.output_text) {
437
+ rawText = resp.output_text;
438
+ }
439
+ if (!rawText) {
440
+ rawText = `"${message}" mesaj\u0131n\u0131z\u0131 ald\u0131m. Size nas\u0131l yard\u0131mc\u0131 olabilirim?`;
349
441
  }
350
- addMessage(responseText, "assistant");
442
+ const { text, components } = extractUiComponents(rawText);
443
+ addMessage({ text, ui: components }, "assistant");
351
444
  setIsLoading(false);
352
445
  } catch (error) {
353
446
  console.error("Error sending message:", error);
354
447
  addMessage(
355
- "\xDCzg\xFCn\xFCm, bir hata olu\u015Ftu. L\xFCtfen tekrar deneyin.",
448
+ { text: "\xDCzg\xFCn\xFCm, bir hata olu\u015Ftu. L\xFCtfen tekrar deneyin." },
356
449
  "assistant"
357
450
  );
358
451
  setIsLoading(false);
@@ -367,7 +460,7 @@ BEHAVIOR SUMMARY
367
460
  };
368
461
 
369
462
  // src/services/chatWidgetApi.ts
370
- var API_BASE_URL = "https://api.elviz24.com";
463
+ var API_BASE_URL = "https://api-alpha.aizek.ai";
371
464
  var fetchChatWidgetSettings = async (clientId) => {
372
465
  try {
373
466
  const response = await fetch(`${API_BASE_URL}/ChatWidgetSettings/GetByClientId?client_id=${clientId}`, {
@@ -380,7 +473,6 @@ var fetchChatWidgetSettings = async (clientId) => {
380
473
  throw new Error(`HTTP error! status: ${response.status}`);
381
474
  }
382
475
  const data = await response.json();
383
- console.log(data);
384
476
  return data;
385
477
  } catch (error) {
386
478
  console.error("Error fetching chat widget settings:", error);
@@ -414,7 +506,6 @@ var mapApiSettingsToConfig = (apiSettings) => {
414
506
 
415
507
  // src/styles/messageStyles.ts
416
508
  var getMessageBubbleStyles = (isUser, isTyping) => ({
417
- display: !isTyping && !isUser ? "none" : "block",
418
509
  maxWidth: "80%",
419
510
  padding: "12px 16px",
420
511
  borderRadius: isUser ? "18px 18px 4px 18px" : "18px 18px 18px 4px",
@@ -443,7 +534,8 @@ var getTimeStyles = (isUser) => ({
443
534
  textAlign: isUser ? "right" : "left"
444
535
  });
445
536
  var getMarkdownStyles = () => ({
446
- lineHeight: 1.6
537
+ lineHeight: 1.6,
538
+ marginBottom: "6px"
447
539
  });
448
540
  var getMarkdownElementStyles = (isUser) => `
449
541
  .markdown-content p {
@@ -890,6 +982,901 @@ var getAlertAnimationStyles = () => `
890
982
  }
891
983
  }
892
984
  `;
985
+ function UIRenderer({ components, onInteraction }) {
986
+ console.log(components);
987
+ if (!Array.isArray(components) || components.length === 0) {
988
+ return null;
989
+ }
990
+ return /* @__PURE__ */ jsx(
991
+ "div",
992
+ {
993
+ style: {
994
+ display: "flex",
995
+ flexDirection: "column",
996
+ gap: "16px",
997
+ width: "100%"
998
+ },
999
+ children: components.map((comp, idx) => {
1000
+ if (!comp || typeof comp !== "object" || !comp.type) {
1001
+ return null;
1002
+ }
1003
+ const key = typeof comp.id === "string" && comp.id.trim() ? comp.id : `${comp.type}-${idx}`;
1004
+ switch (comp.type) {
1005
+ case "form":
1006
+ return /* @__PURE__ */ jsx(
1007
+ FormComponent,
1008
+ {
1009
+ data: comp.data,
1010
+ onSubmit: (values) => onInteraction?.({
1011
+ type: "formSubmit",
1012
+ componentId: comp.data.id,
1013
+ values
1014
+ })
1015
+ },
1016
+ key
1017
+ );
1018
+ case "buttons":
1019
+ if (!comp.data || !Array.isArray(comp.data)) {
1020
+ return null;
1021
+ }
1022
+ return /* @__PURE__ */ jsx(
1023
+ ButtonsComponent,
1024
+ {
1025
+ data: comp.data,
1026
+ onClick: (value) => onInteraction?.({ type: "buttonClick", value })
1027
+ },
1028
+ key
1029
+ );
1030
+ case "table":
1031
+ return /* @__PURE__ */ jsx(TableComponent, { data: comp.data }, key);
1032
+ case "card":
1033
+ return /* @__PURE__ */ jsx(CardComponent, { data: comp.data }, key);
1034
+ default:
1035
+ return null;
1036
+ }
1037
+ })
1038
+ }
1039
+ );
1040
+ }
1041
+ function FormComponent({
1042
+ data,
1043
+ onSubmit
1044
+ }) {
1045
+ const handleSubmit = (e) => {
1046
+ e.preventDefault();
1047
+ console.log(e.currentTarget);
1048
+ const formData = new FormData(e.currentTarget);
1049
+ console.log(formData);
1050
+ const values = {};
1051
+ data.fields.forEach((f) => {
1052
+ values[f.id || f.name] = String(formData.get(f.id || f.name) ?? "");
1053
+ });
1054
+ onSubmit(values);
1055
+ };
1056
+ console.log("formdata", data);
1057
+ return /* @__PURE__ */ jsxs(
1058
+ "form",
1059
+ {
1060
+ onSubmit: handleSubmit,
1061
+ style: {
1062
+ width: "100%",
1063
+ maxWidth: "500px",
1064
+ border: "1px solid #e0e0e0",
1065
+ borderRadius: "12px",
1066
+ padding: "24px",
1067
+ backgroundColor: "#ffffff",
1068
+ boxShadow: "0 2px 8px rgba(0, 0, 0, 0.08)",
1069
+ fontFamily: '-apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, "Helvetica Neue", Arial, sans-serif'
1070
+ },
1071
+ children: [
1072
+ data.title && /* @__PURE__ */ jsx(
1073
+ "h3",
1074
+ {
1075
+ style: {
1076
+ fontWeight: 600,
1077
+ fontSize: "16px",
1078
+ marginBottom: "20px",
1079
+ color: "#1a1a1a",
1080
+ marginTop: 0
1081
+ },
1082
+ children: data.title
1083
+ }
1084
+ ),
1085
+ /* @__PURE__ */ jsx(
1086
+ "div",
1087
+ {
1088
+ style: {
1089
+ display: "flex",
1090
+ flexDirection: "column",
1091
+ gap: "20px"
1092
+ },
1093
+ children: data.fields.map((field, fieldIdx) => {
1094
+ const fieldKey = typeof field.id === "string" && field.id.trim() ? field.id : `field-${fieldIdx}`;
1095
+ return /* @__PURE__ */ jsxs(
1096
+ "div",
1097
+ {
1098
+ style: {
1099
+ display: "flex",
1100
+ flexDirection: "column",
1101
+ gap: "8px"
1102
+ },
1103
+ children: [
1104
+ /* @__PURE__ */ jsxs(
1105
+ "label",
1106
+ {
1107
+ style: {
1108
+ fontWeight: 500,
1109
+ fontSize: "13px",
1110
+ color: "#374151",
1111
+ display: "flex",
1112
+ alignItems: "center",
1113
+ gap: "4px"
1114
+ },
1115
+ children: [
1116
+ field.label,
1117
+ field.required && /* @__PURE__ */ jsx("span", { style: { color: "#ef4444", fontSize: "14px" }, children: "*" })
1118
+ ]
1119
+ }
1120
+ ),
1121
+ field.type === "select" ? /* @__PURE__ */ jsxs(
1122
+ "select",
1123
+ {
1124
+ name: field.id || field.name,
1125
+ required: field.required,
1126
+ defaultValue: field.value ? String(field.value) : "",
1127
+ style: {
1128
+ border: "1px solid #d1d5db",
1129
+ borderRadius: "8px",
1130
+ padding: "10px 12px",
1131
+ fontSize: "13px",
1132
+ color: "#1a1a1a",
1133
+ backgroundColor: "#ffffff",
1134
+ fontFamily: "inherit",
1135
+ outline: "none",
1136
+ transition: "border-color 0.15s ease, box-shadow 0.15s ease",
1137
+ cursor: "pointer"
1138
+ },
1139
+ onFocus: (e) => {
1140
+ e.currentTarget.style.borderColor = "#3b82f6";
1141
+ e.currentTarget.style.boxShadow = "0 0 0 3px rgba(59, 130, 246, 0.1)";
1142
+ },
1143
+ onBlur: (e) => {
1144
+ e.currentTarget.style.borderColor = "#d1d5db";
1145
+ e.currentTarget.style.boxShadow = "none";
1146
+ },
1147
+ children: [
1148
+ /* @__PURE__ */ jsx("option", { value: "", children: "Se\xE7iniz" }),
1149
+ field.options?.map((opt, optIdx) => {
1150
+ const optKey = typeof opt.value === "string" ? opt.value : `opt-${fieldIdx}-${optIdx}`;
1151
+ return /* @__PURE__ */ jsx("option", { value: opt.value, children: opt.label }, optKey);
1152
+ })
1153
+ ]
1154
+ }
1155
+ ) : /* @__PURE__ */ jsx(
1156
+ "input",
1157
+ {
1158
+ type: field.type === "number" ? "number" : "text",
1159
+ name: field.id || field.name,
1160
+ required: field.required,
1161
+ defaultValue: field.value ? String(field.value) : "",
1162
+ placeholder: field.placeholder || "",
1163
+ min: field.min,
1164
+ max: field.max,
1165
+ style: {
1166
+ border: "1px solid #d1d5db",
1167
+ borderRadius: "8px",
1168
+ padding: "10px 12px",
1169
+ fontSize: "13px",
1170
+ color: "#1a1a1a",
1171
+ backgroundColor: "#ffffff",
1172
+ fontFamily: "inherit",
1173
+ outline: "none",
1174
+ transition: "border-color 0.15s ease, box-shadow 0.15s ease"
1175
+ },
1176
+ onFocus: (e) => {
1177
+ e.currentTarget.style.borderColor = "#3b82f6";
1178
+ e.currentTarget.style.boxShadow = "0 0 0 3px rgba(59, 130, 246, 0.1)";
1179
+ },
1180
+ onBlur: (e) => {
1181
+ e.currentTarget.style.borderColor = "#d1d5db";
1182
+ e.currentTarget.style.boxShadow = "none";
1183
+ }
1184
+ }
1185
+ )
1186
+ ]
1187
+ },
1188
+ fieldKey
1189
+ );
1190
+ })
1191
+ }
1192
+ ),
1193
+ /* @__PURE__ */ jsx(
1194
+ "button",
1195
+ {
1196
+ type: "submit",
1197
+ style: {
1198
+ marginTop: "24px",
1199
+ display: "inline-flex",
1200
+ alignItems: "center",
1201
+ justifyContent: "center",
1202
+ borderRadius: "8px",
1203
+ padding: "12px 24px",
1204
+ fontSize: "13px",
1205
+ fontWeight: 500,
1206
+ backgroundColor: "#3b82f6",
1207
+ color: "#ffffff",
1208
+ border: "none",
1209
+ cursor: "pointer",
1210
+ transition: "background-color 0.15s ease, transform 0.1s ease",
1211
+ fontFamily: "inherit"
1212
+ },
1213
+ onMouseEnter: (e) => {
1214
+ e.currentTarget.style.backgroundColor = "#2563eb";
1215
+ },
1216
+ onMouseLeave: (e) => {
1217
+ e.currentTarget.style.backgroundColor = "#3b82f6";
1218
+ },
1219
+ onMouseDown: (e) => {
1220
+ e.currentTarget.style.transform = "scale(0.98)";
1221
+ },
1222
+ onMouseUp: (e) => {
1223
+ e.currentTarget.style.transform = "scale(1)";
1224
+ },
1225
+ children: data.submitLabel ?? "G\xF6nder"
1226
+ }
1227
+ )
1228
+ ]
1229
+ }
1230
+ );
1231
+ }
1232
+ function ButtonsComponent({
1233
+ data,
1234
+ onClick
1235
+ }) {
1236
+ if (!Array.isArray(data) || data.length === 0) {
1237
+ return null;
1238
+ }
1239
+ const getButtonStyles = (variant) => {
1240
+ const baseStyles = {
1241
+ borderRadius: "8px",
1242
+ padding: "10px 20px",
1243
+ fontSize: "13px",
1244
+ fontWeight: 500,
1245
+ border: "1px solid #e0e0e0",
1246
+ backgroundColor: "#ffffff",
1247
+ color: "#374151",
1248
+ cursor: "pointer",
1249
+ transition: "all 0.15s ease",
1250
+ fontFamily: '-apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, "Helvetica Neue", Arial, sans-serif',
1251
+ outline: "none"
1252
+ };
1253
+ if (variant === "primary") {
1254
+ return {
1255
+ ...baseStyles,
1256
+ backgroundColor: "#3b82f6",
1257
+ color: "#ffffff",
1258
+ borderColor: "#3b82f6"
1259
+ };
1260
+ } else if (variant === "secondary") {
1261
+ return {
1262
+ ...baseStyles,
1263
+ backgroundColor: "#f3f4f6",
1264
+ color: "#374151",
1265
+ borderColor: "#d1d5db"
1266
+ };
1267
+ } else if (variant === "danger") {
1268
+ return {
1269
+ ...baseStyles,
1270
+ backgroundColor: "#ef4444",
1271
+ color: "#ffffff",
1272
+ borderColor: "#ef4444"
1273
+ };
1274
+ }
1275
+ return baseStyles;
1276
+ };
1277
+ const getHoverStyles = (variant) => {
1278
+ if (variant === "primary") {
1279
+ return { backgroundColor: "#2563eb", borderColor: "#2563eb" };
1280
+ } else if (variant === "secondary") {
1281
+ return { backgroundColor: "#e5e7eb", borderColor: "#9ca3af" };
1282
+ } else if (variant === "danger") {
1283
+ return { backgroundColor: "#dc2626", borderColor: "#dc2626" };
1284
+ }
1285
+ return { backgroundColor: "#f9fafb", borderColor: "#d1d5db" };
1286
+ };
1287
+ return /* @__PURE__ */ jsx(
1288
+ "div",
1289
+ {
1290
+ style: {
1291
+ display: "flex",
1292
+ gap: "12px",
1293
+ flexWrap: "wrap"
1294
+ },
1295
+ children: data.map((btn, idx) => {
1296
+ if (!btn || typeof btn !== "object") {
1297
+ return null;
1298
+ }
1299
+ const btnValue = typeof btn.value === "string" ? btn.value : typeof btn.value === "number" ? String(btn.value) : btn.value && typeof btn.value === "object" ? JSON.stringify(btn.value) : `btn-value-${idx}`;
1300
+ const btnKey = typeof btn.value === "string" && btn.value.trim() ? btn.value : `btn-${idx}`;
1301
+ const btnLabel = btn.label || `Button ${idx + 1}`;
1302
+ const buttonStyles = getButtonStyles(btn.variant);
1303
+ const hoverStyles = getHoverStyles(btn.variant);
1304
+ return /* @__PURE__ */ jsx(
1305
+ "button",
1306
+ {
1307
+ onClick: () => {
1308
+ try {
1309
+ onClick(btnValue);
1310
+ } catch (error) {
1311
+ console.error("Error in button onClick:", error);
1312
+ }
1313
+ },
1314
+ style: buttonStyles,
1315
+ onMouseEnter: (e) => {
1316
+ Object.assign(e.currentTarget.style, hoverStyles);
1317
+ },
1318
+ onMouseLeave: (e) => {
1319
+ Object.assign(e.currentTarget.style, buttonStyles);
1320
+ },
1321
+ onMouseDown: (e) => {
1322
+ e.currentTarget.style.transform = "scale(0.97)";
1323
+ },
1324
+ onMouseUp: (e) => {
1325
+ e.currentTarget.style.transform = "scale(1)";
1326
+ },
1327
+ children: btnLabel
1328
+ },
1329
+ btnKey
1330
+ );
1331
+ })
1332
+ }
1333
+ );
1334
+ }
1335
+ function TableComponent({ data }) {
1336
+ if (!data.columns || !Array.isArray(data.columns) || data.columns.length === 0) {
1337
+ return null;
1338
+ }
1339
+ return /* @__PURE__ */ jsxs(
1340
+ "div",
1341
+ {
1342
+ style: {
1343
+ border: "1px solid #e0e0e0",
1344
+ borderRadius: "12px",
1345
+ overflow: "hidden",
1346
+ fontSize: "13px",
1347
+ backgroundColor: "#ffffff",
1348
+ boxShadow: "0 2px 8px rgba(0, 0, 0, 0.08)",
1349
+ fontFamily: '-apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, "Helvetica Neue", Arial, sans-serif'
1350
+ },
1351
+ children: [
1352
+ data.caption && /* @__PURE__ */ jsx(
1353
+ "div",
1354
+ {
1355
+ style: {
1356
+ padding: "16px 20px",
1357
+ fontWeight: 600,
1358
+ fontSize: "14px",
1359
+ borderBottom: "1px solid #e0e0e0",
1360
+ backgroundColor: "#f8f9fa",
1361
+ color: "#1a1a1a"
1362
+ },
1363
+ children: data.caption
1364
+ }
1365
+ ),
1366
+ /* @__PURE__ */ jsx("div", { style: { overflowX: "auto" }, children: /* @__PURE__ */ jsxs(
1367
+ "table",
1368
+ {
1369
+ style: {
1370
+ width: "100%",
1371
+ borderCollapse: "collapse",
1372
+ minWidth: "100%"
1373
+ },
1374
+ children: [
1375
+ /* @__PURE__ */ jsx("thead", { style: { backgroundColor: "#f8f9fa" }, children: /* @__PURE__ */ jsx("tr", { children: data.columns.map((col, i) => {
1376
+ const colKey = typeof col === "string" ? `col-${i}` : col.key || col.id || `col-${i}`;
1377
+ const colLabel = typeof col === "string" ? col : col.label || "";
1378
+ return /* @__PURE__ */ jsx(
1379
+ "th",
1380
+ {
1381
+ style: {
1382
+ borderBottom: "2px solid #e0e0e0",
1383
+ padding: "14px 20px",
1384
+ textAlign: "left",
1385
+ fontWeight: 600,
1386
+ fontSize: "12px",
1387
+ color: "#4a5568",
1388
+ textTransform: "uppercase",
1389
+ letterSpacing: "0.5px",
1390
+ whiteSpace: "nowrap"
1391
+ },
1392
+ children: colLabel
1393
+ },
1394
+ colKey
1395
+ );
1396
+ }) }) }),
1397
+ /* @__PURE__ */ jsx("tbody", { children: data.rows && data.rows.length > 0 ? data.rows.map((row, rowIdx) => /* @__PURE__ */ jsx(
1398
+ "tr",
1399
+ {
1400
+ style: {
1401
+ backgroundColor: rowIdx % 2 === 0 ? "#ffffff" : "#fafbfc",
1402
+ transition: "background-color 0.15s ease"
1403
+ },
1404
+ onMouseEnter: (e) => {
1405
+ e.currentTarget.style.backgroundColor = "#f0f4f8";
1406
+ },
1407
+ onMouseLeave: (e) => {
1408
+ e.currentTarget.style.backgroundColor = rowIdx % 2 === 0 ? "#ffffff" : "#fafbfc";
1409
+ },
1410
+ children: data.columns.map((col, colIdx) => {
1411
+ const colKey = typeof col === "string" ? `col-${colIdx}` : col.key || col.id || `col-${colIdx}`;
1412
+ const colType = typeof col === "object" ? col.type : void 0;
1413
+ const cellKey = `cell-${rowIdx}-${colIdx}`;
1414
+ let cellContent = null;
1415
+ if (typeof row === "object" && row !== null && !Array.isArray(row)) {
1416
+ const cellValue = row[colKey];
1417
+ if (cellValue !== void 0 && cellValue !== null) {
1418
+ if (typeof cellValue === "object" && "type" in cellValue) {
1419
+ cellContent = renderField(cellValue);
1420
+ } else {
1421
+ const stringValue = String(cellValue);
1422
+ const isImageUrl = typeof stringValue === "string" && (stringValue.startsWith("http") || stringValue.startsWith("data:") || stringValue.startsWith("/")) && (stringValue.match(
1423
+ /\.(jpg|jpeg|png|gif|webp|svg)$/i
1424
+ ) || stringValue.includes("image") || stringValue.includes("avatar"));
1425
+ if (colType === "image" || !colType && isImageUrl) {
1426
+ cellContent = /* @__PURE__ */ jsx(
1427
+ "div",
1428
+ {
1429
+ style: {
1430
+ display: "flex",
1431
+ alignItems: "center"
1432
+ },
1433
+ children: /* @__PURE__ */ jsx(
1434
+ "img",
1435
+ {
1436
+ src: stringValue,
1437
+ alt: "",
1438
+ style: {
1439
+ width: "40px",
1440
+ height: "40px",
1441
+ borderRadius: "8px",
1442
+ objectFit: "cover",
1443
+ border: "1px solid #e0e0e0"
1444
+ },
1445
+ onError: (e) => {
1446
+ e.target.style.display = "none";
1447
+ }
1448
+ }
1449
+ )
1450
+ }
1451
+ );
1452
+ } else {
1453
+ cellContent = /* @__PURE__ */ jsx(
1454
+ "span",
1455
+ {
1456
+ style: {
1457
+ color: "#2d3748",
1458
+ lineHeight: "1.5"
1459
+ },
1460
+ children: stringValue
1461
+ }
1462
+ );
1463
+ }
1464
+ }
1465
+ }
1466
+ } else if (Array.isArray(row)) {
1467
+ const cellValue = row[colIdx];
1468
+ if (cellValue !== void 0 && cellValue !== null) {
1469
+ const stringValue = String(cellValue);
1470
+ const isImageUrl = typeof stringValue === "string" && (stringValue.startsWith("http") || stringValue.startsWith("data:") || stringValue.startsWith("/")) && (stringValue.match(
1471
+ /\.(jpg|jpeg|png|gif|webp|svg)$/i
1472
+ ) || stringValue.includes("image") || stringValue.includes("avatar"));
1473
+ if (colType === "image" || !colType && isImageUrl) {
1474
+ cellContent = /* @__PURE__ */ jsx(
1475
+ "div",
1476
+ {
1477
+ style: { display: "flex", alignItems: "center" },
1478
+ children: /* @__PURE__ */ jsx(
1479
+ "img",
1480
+ {
1481
+ src: stringValue,
1482
+ alt: "",
1483
+ style: {
1484
+ width: "40px",
1485
+ height: "40px",
1486
+ borderRadius: "8px",
1487
+ objectFit: "cover",
1488
+ border: "1px solid #e0e0e0"
1489
+ },
1490
+ onError: (e) => {
1491
+ e.target.style.display = "none";
1492
+ }
1493
+ }
1494
+ )
1495
+ }
1496
+ );
1497
+ } else {
1498
+ cellContent = /* @__PURE__ */ jsx(
1499
+ "span",
1500
+ {
1501
+ style: {
1502
+ color: "#2d3748",
1503
+ lineHeight: "1.5"
1504
+ },
1505
+ children: stringValue
1506
+ }
1507
+ );
1508
+ }
1509
+ }
1510
+ }
1511
+ return /* @__PURE__ */ jsx(
1512
+ "td",
1513
+ {
1514
+ style: {
1515
+ borderBottom: "1px solid #e8e8e8",
1516
+ padding: "16px 20px",
1517
+ fontSize: "13px",
1518
+ verticalAlign: "middle"
1519
+ },
1520
+ children: cellContent || /* @__PURE__ */ jsx(
1521
+ "span",
1522
+ {
1523
+ style: { color: "#a0a0a0", fontStyle: "italic" },
1524
+ children: "\u2014"
1525
+ }
1526
+ )
1527
+ },
1528
+ cellKey
1529
+ );
1530
+ })
1531
+ },
1532
+ `row-${rowIdx}`
1533
+ )) : /* @__PURE__ */ jsx("tr", { children: /* @__PURE__ */ jsx(
1534
+ "td",
1535
+ {
1536
+ colSpan: data.columns.length,
1537
+ style: {
1538
+ padding: "40px",
1539
+ textAlign: "center",
1540
+ color: "#9ca3af",
1541
+ fontSize: "13px"
1542
+ },
1543
+ children: "Veri bulunamad\u0131"
1544
+ }
1545
+ ) }) })
1546
+ ]
1547
+ }
1548
+ ) })
1549
+ ]
1550
+ }
1551
+ );
1552
+ }
1553
+ function CardComponent({ data }) {
1554
+ if (data.title) {
1555
+ const hasImage = data.image && typeof data.image === "string";
1556
+ const hasFields = data.fields && Array.isArray(data.fields) && data.fields.length > 0;
1557
+ const hasAttributes = data.attributes && Array.isArray(data.attributes) && data.attributes.length > 0;
1558
+ const hasStatus = data.status && typeof data.status === "string";
1559
+ const hasSubtitle = data.subtitle && typeof data.subtitle === "string";
1560
+ const displayFields = hasAttributes ? data.attributes : hasFields ? data.fields : [];
1561
+ return /* @__PURE__ */ jsx(
1562
+ "div",
1563
+ {
1564
+ style: {
1565
+ border: "1px solid #e5e7eb",
1566
+ borderRadius: "16px",
1567
+ padding: "16px",
1568
+ backgroundColor: "#ffffff",
1569
+ boxShadow: "0 1px 3px 0 rgba(0, 0, 0, 0.1)",
1570
+ overflow: "hidden",
1571
+ marginBottom: "12px"
1572
+ },
1573
+ children: /* @__PURE__ */ jsxs("div", { style: { display: "flex", gap: "12px" }, children: [
1574
+ hasImage && /* @__PURE__ */ jsx(
1575
+ "img",
1576
+ {
1577
+ src: data.image,
1578
+ alt: data.title || "Card image",
1579
+ style: {
1580
+ width: "64px",
1581
+ height: "64px",
1582
+ borderRadius: "8px",
1583
+ objectFit: "cover",
1584
+ flexShrink: 0
1585
+ },
1586
+ onError: (e) => {
1587
+ e.target.style.display = "none";
1588
+ }
1589
+ }
1590
+ ),
1591
+ /* @__PURE__ */ jsxs("div", { style: { flex: 1, minWidth: 0 }, children: [
1592
+ /* @__PURE__ */ jsx(
1593
+ "h4",
1594
+ {
1595
+ style: {
1596
+ fontWeight: 600,
1597
+ fontSize: "14px",
1598
+ marginBottom: "8px",
1599
+ overflow: "hidden",
1600
+ textOverflow: "ellipsis",
1601
+ whiteSpace: "nowrap"
1602
+ },
1603
+ children: data.title
1604
+ }
1605
+ ),
1606
+ hasStatus && /* @__PURE__ */ jsxs(
1607
+ "div",
1608
+ {
1609
+ style: {
1610
+ display: "flex",
1611
+ gap: "8px",
1612
+ fontSize: "12px",
1613
+ marginBottom: "4px"
1614
+ },
1615
+ children: [
1616
+ /* @__PURE__ */ jsx("span", { style: { color: "#6b7280", fontWeight: 500 }, children: "Durum:" }),
1617
+ /* @__PURE__ */ jsx("span", { style: { color: "#374151" }, children: data.status })
1618
+ ]
1619
+ }
1620
+ ),
1621
+ hasSubtitle && /* @__PURE__ */ jsx(
1622
+ "p",
1623
+ {
1624
+ style: {
1625
+ color: "#6b7280",
1626
+ fontSize: "12px",
1627
+ marginBottom: "4px",
1628
+ margin: 0
1629
+ },
1630
+ children: data.subtitle
1631
+ }
1632
+ ),
1633
+ displayFields && displayFields.length > 0 && /* @__PURE__ */ jsx(
1634
+ "div",
1635
+ {
1636
+ style: { display: "flex", flexDirection: "column", gap: "4px" },
1637
+ children: displayFields.map((field, i) => /* @__PURE__ */ jsxs(
1638
+ "div",
1639
+ {
1640
+ style: { display: "flex", gap: "8px", fontSize: "12px" },
1641
+ children: [
1642
+ /* @__PURE__ */ jsxs("span", { style: { color: "#6b7280", fontWeight: 500 }, children: [
1643
+ field.label,
1644
+ ":"
1645
+ ] }),
1646
+ /* @__PURE__ */ jsx("span", { style: { color: "#374151" }, children: field.value })
1647
+ ]
1648
+ },
1649
+ i
1650
+ ))
1651
+ }
1652
+ ),
1653
+ data.description && /* @__PURE__ */ jsx(
1654
+ "p",
1655
+ {
1656
+ style: {
1657
+ color: "#6b7280",
1658
+ fontSize: "12px",
1659
+ marginTop: "8px",
1660
+ margin: 0
1661
+ },
1662
+ children: data.description
1663
+ }
1664
+ )
1665
+ ] })
1666
+ ] })
1667
+ }
1668
+ );
1669
+ }
1670
+ if (!data.items || !Array.isArray(data.items) || data.items.length === 0) {
1671
+ return null;
1672
+ }
1673
+ return /* @__PURE__ */ jsxs("div", { style: { width: "100%" }, children: [
1674
+ data.title && !data.items.some((item) => item.title) && /* @__PURE__ */ jsx(
1675
+ "h3",
1676
+ {
1677
+ style: {
1678
+ fontWeight: 600,
1679
+ marginBottom: "12px",
1680
+ fontSize: "14px",
1681
+ color: "#1a1a1a",
1682
+ marginTop: 0
1683
+ },
1684
+ children: data.title
1685
+ }
1686
+ ),
1687
+ data.description && /* @__PURE__ */ jsx(
1688
+ "p",
1689
+ {
1690
+ style: {
1691
+ color: "#6b7280",
1692
+ marginBottom: "12px",
1693
+ fontSize: "12px",
1694
+ marginTop: 0
1695
+ },
1696
+ children: data.description
1697
+ }
1698
+ ),
1699
+ /* @__PURE__ */ jsx(
1700
+ "div",
1701
+ {
1702
+ style: {
1703
+ display: "grid",
1704
+ gridTemplateColumns: "repeat(auto-fit, minmax(250px, 1fr))",
1705
+ gap: "12px"
1706
+ },
1707
+ children: data.items.map((item, i) => {
1708
+ const itemKey = item.id || `card-item-${i}`;
1709
+ const hasImage = item.image && typeof item.image === "string";
1710
+ const hasTitle = item.title && typeof item.title === "string";
1711
+ const hasSubtitle = item.subtitle && typeof item.subtitle === "string";
1712
+ const isLegacyFormat = item.label && item.value;
1713
+ if (isLegacyFormat && !hasTitle) {
1714
+ return /* @__PURE__ */ jsx(
1715
+ "div",
1716
+ {
1717
+ style: {
1718
+ border: "1px solid #e0e0e0",
1719
+ borderRadius: "12px",
1720
+ padding: "16px",
1721
+ backgroundColor: "#ffffff",
1722
+ boxShadow: "0 2px 8px rgba(0, 0, 0, 0.08)",
1723
+ fontSize: "12px"
1724
+ },
1725
+ children: /* @__PURE__ */ jsxs(
1726
+ "div",
1727
+ {
1728
+ style: {
1729
+ display: "flex",
1730
+ justifyContent: "space-between",
1731
+ gap: "8px"
1732
+ },
1733
+ children: [
1734
+ /* @__PURE__ */ jsx("dt", { style: { color: "#6b7280", margin: 0 }, children: item.label }),
1735
+ /* @__PURE__ */ jsx(
1736
+ "dd",
1737
+ {
1738
+ style: {
1739
+ fontWeight: 500,
1740
+ color: "#1a1a1a",
1741
+ margin: 0
1742
+ },
1743
+ children: item.value
1744
+ }
1745
+ )
1746
+ ]
1747
+ }
1748
+ )
1749
+ },
1750
+ itemKey
1751
+ );
1752
+ }
1753
+ return /* @__PURE__ */ jsx(
1754
+ "div",
1755
+ {
1756
+ style: {
1757
+ border: "1px solid #e0e0e0",
1758
+ borderRadius: "12px",
1759
+ padding: "16px",
1760
+ backgroundColor: "#ffffff",
1761
+ boxShadow: "0 2px 8px rgba(0, 0, 0, 0.08)",
1762
+ overflow: "hidden"
1763
+ },
1764
+ children: /* @__PURE__ */ jsxs("div", { style: { display: "flex", gap: "12px" }, children: [
1765
+ hasImage && /* @__PURE__ */ jsx(
1766
+ "img",
1767
+ {
1768
+ src: item.image,
1769
+ alt: item.title || `Card ${i + 1}`,
1770
+ style: {
1771
+ width: "64px",
1772
+ height: "64px",
1773
+ borderRadius: "8px",
1774
+ objectFit: "cover",
1775
+ flexShrink: 0
1776
+ },
1777
+ onError: (e) => {
1778
+ e.target.style.display = "none";
1779
+ }
1780
+ }
1781
+ ),
1782
+ /* @__PURE__ */ jsxs(
1783
+ "div",
1784
+ {
1785
+ style: {
1786
+ flex: 1,
1787
+ minWidth: 0
1788
+ },
1789
+ children: [
1790
+ hasTitle && /* @__PURE__ */ jsx(
1791
+ "h4",
1792
+ {
1793
+ style: {
1794
+ fontWeight: 600,
1795
+ fontSize: "14px",
1796
+ marginBottom: "4px",
1797
+ overflow: "hidden",
1798
+ textOverflow: "ellipsis",
1799
+ whiteSpace: "nowrap",
1800
+ color: "#1a1a1a",
1801
+ marginTop: 0
1802
+ },
1803
+ children: item.title
1804
+ }
1805
+ ),
1806
+ hasSubtitle && /* @__PURE__ */ jsx(
1807
+ "p",
1808
+ {
1809
+ style: {
1810
+ color: "#6b7280",
1811
+ fontSize: "12px",
1812
+ margin: 0
1813
+ },
1814
+ children: item.subtitle
1815
+ }
1816
+ )
1817
+ ]
1818
+ }
1819
+ )
1820
+ ] })
1821
+ },
1822
+ itemKey
1823
+ );
1824
+ })
1825
+ }
1826
+ )
1827
+ ] });
1828
+ }
1829
+ function renderField(field) {
1830
+ switch (field.type) {
1831
+ case "text":
1832
+ return /* @__PURE__ */ jsx("span", { children: field.value });
1833
+ case "image":
1834
+ return /* @__PURE__ */ jsx(
1835
+ "img",
1836
+ {
1837
+ src: field.src,
1838
+ alt: field.alt ?? "",
1839
+ style: {
1840
+ width: 24,
1841
+ height: 24,
1842
+ borderRadius: "999px",
1843
+ objectFit: "cover"
1844
+ }
1845
+ }
1846
+ );
1847
+ case "link":
1848
+ return /* @__PURE__ */ jsx(
1849
+ "a",
1850
+ {
1851
+ href: field.href,
1852
+ target: "_blank",
1853
+ rel: "noreferrer",
1854
+ style: { textDecoration: "underline" },
1855
+ children: field.label
1856
+ }
1857
+ );
1858
+ case "badge":
1859
+ return /* @__PURE__ */ jsx(
1860
+ "span",
1861
+ {
1862
+ style: {
1863
+ display: "inline-block",
1864
+ padding: "2px 6px",
1865
+ borderRadius: 999,
1866
+ fontSize: 10,
1867
+ fontWeight: 500,
1868
+ backgroundColor: field.tone === "success" ? "#e0fce5" : field.tone === "warning" ? "#fff7d6" : field.tone === "danger" ? "#ffe4e4" : "#f2f2f2",
1869
+ color: field.tone === "success" ? "#1a7f36" : field.tone === "warning" ? "#8a6a00" : field.tone === "danger" ? "#b42318" : "#333"
1870
+ },
1871
+ children: field.label
1872
+ }
1873
+ );
1874
+ case "list":
1875
+ return /* @__PURE__ */ jsx("ul", { style: { margin: 0, paddingLeft: 16 }, children: field.items.map((item, i) => /* @__PURE__ */ jsx("li", { children: renderField(item) }, i)) });
1876
+ default:
1877
+ return null;
1878
+ }
1879
+ }
893
1880
  var AizekChatBot = ({
894
1881
  clientId,
895
1882
  headers
@@ -929,9 +1916,7 @@ var AizekChatBot = ({
929
1916
  const [isOpen, setIsOpen] = useState(false);
930
1917
  const [headerValidation, setHeaderValidation] = useState(null);
931
1918
  const [showAlert, setShowAlert] = useState(true);
932
- console.log("Component rendered");
933
1919
  useEffect(() => {
934
- console.log("use");
935
1920
  const loadConfig = async () => {
936
1921
  try {
937
1922
  setIsConfigLoading(true);
@@ -945,7 +1930,6 @@ var AizekChatBot = ({
945
1930
  caseSensitive: true
946
1931
  }
947
1932
  );
948
- console.log(validationResult);
949
1933
  setHeaderValidation(validationResult);
950
1934
  }
951
1935
  setFinalMcpUrl(apiResponse.data.mcp_url);
@@ -987,41 +1971,54 @@ var AizekChatBot = ({
987
1971
  }, [messages]);
988
1972
  const MessageBubble = ({ message, onAction }) => {
989
1973
  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]);
1010
1974
  return /* @__PURE__ */ jsxs("div", { style: getMessageContainerStyles(isUser), children: [
1011
1975
  /* @__PURE__ */ jsx("style", { children: getMarkdownElementStyles(isUser) }),
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 }) }),
1014
- message.isTyping && /* @__PURE__ */ jsx("div", { style: {
1015
- display: "inline-flex",
1016
- alignItems: "center",
1017
- marginLeft: "8px"
1018
- }, children: /* @__PURE__ */ jsx(TypingDots, {}) })
1976
+ isUser && /* @__PURE__ */ jsxs(Fragment, { children: [
1977
+ /* @__PURE__ */ jsx("div", { style: getMessageBubbleStyles(isUser), children: message.text && /* @__PURE__ */ jsx("div", { style: getMarkdownStyles(), children: message.text }) }),
1978
+ /* @__PURE__ */ jsx("div", { style: getTimeStyles(isUser), children: message.timestamp.toLocaleTimeString("tr-TR", {
1979
+ hour: "2-digit",
1980
+ minute: "2-digit"
1981
+ }) })
1019
1982
  ] }),
1020
- !isUser && /* @__PURE__ */ jsx("div", { dangerouslySetInnerHTML: { __html: cleanContent } }),
1021
- /* @__PURE__ */ jsx("div", { style: getTimeStyles(isUser), children: message.timestamp.toLocaleTimeString("tr-TR", {
1022
- hour: "2-digit",
1023
- minute: "2-digit"
1024
- }) })
1983
+ !isUser && message.role !== "approval" && /* @__PURE__ */ jsxs(Fragment, { children: [
1984
+ /* @__PURE__ */ jsx(
1985
+ "div",
1986
+ {
1987
+ style: getMessageBubbleStyles(isUser, message.isTyping ?? false),
1988
+ children: message.isTyping ? /* @__PURE__ */ jsx(
1989
+ "div",
1990
+ {
1991
+ style: {
1992
+ display: "inline-flex",
1993
+ alignItems: "center",
1994
+ marginLeft: message.text ? "8px" : "0"
1995
+ },
1996
+ children: /* @__PURE__ */ jsx(TypingDots, {})
1997
+ }
1998
+ ) : /* @__PURE__ */ jsxs(Fragment, { children: [
1999
+ /* @__PURE__ */ jsx("div", { style: getMarkdownStyles(), className: "markdown-content", children: /* @__PURE__ */ jsx(ReactMarkdown, { remarkPlugins: [remarkGfm], children: message.text }) }),
2000
+ message.ui && /* @__PURE__ */ jsx(
2001
+ UIRenderer,
2002
+ {
2003
+ components: message.ui,
2004
+ onInteraction: (event) => {
2005
+ console.log(event);
2006
+ if (event.type === "buttonClick" && typeof event.value === "string") {
2007
+ onAction(event.value, true);
2008
+ } else if (event.type === "formSubmit") {
2009
+ onAction(JSON.stringify(event.values), true);
2010
+ }
2011
+ }
2012
+ }
2013
+ )
2014
+ ] })
2015
+ }
2016
+ ),
2017
+ /* @__PURE__ */ jsx("div", { style: getTimeStyles(isUser), children: message.timestamp.toLocaleTimeString("tr-TR", {
2018
+ hour: "2-digit",
2019
+ minute: "2-digit"
2020
+ }) })
2021
+ ] })
1025
2022
  ] });
1026
2023
  };
1027
2024
  const TypingDots = () => {
@@ -1305,14 +2302,15 @@ var AizekChatBot = ({
1305
2302
  MessageBubble,
1306
2303
  {
1307
2304
  message: {
1308
- id: "typing",
1309
- content: "",
2305
+ id: `typing-${messages.length}`,
2306
+ text: "",
1310
2307
  role: "assistant",
1311
2308
  timestamp: /* @__PURE__ */ new Date(),
1312
2309
  isTyping: true
1313
2310
  },
1314
2311
  onAction: handleSendMessage
1315
- }
2312
+ },
2313
+ `typing-${messages.length}`
1316
2314
  ),
1317
2315
  /* @__PURE__ */ jsx("div", { ref: messagesEndRef })
1318
2316
  ] }),