@shop-prompter/react 0.1.1 → 1.0.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/index.mjs CHANGED
@@ -1,6 +1,7 @@
1
1
  // src/shop-prompter.component.jsx
2
- import * as React from "react";
3
- import { useState, useEffect } from "react";
2
+ import * as React4 from "react";
3
+ import { useState as useState2, useEffect as useEffect2 } from "react";
4
+ import { marked } from "marked";
4
5
 
5
6
  // src/api/shop-prompter-api.ts
6
7
  var DefaultShopPrompterApi = class {
@@ -10,16 +11,27 @@ var DefaultShopPrompterApi = class {
10
11
  setApiConfig(config) {
11
12
  this.config = config;
12
13
  }
14
+ getHeaders() {
15
+ if (!this.config) {
16
+ return { "Content-Type": "application/json" };
17
+ }
18
+ const headers = {
19
+ "Content-Type": "application/json"
20
+ };
21
+ if (this.config.shopPrompterToken) {
22
+ headers["Authorization"] = `Bearer ${this.config.shopPrompterToken}`;
23
+ } else if (this.config.apiKey) {
24
+ headers["X-Api-Key"] = this.config.apiKey;
25
+ }
26
+ return headers;
27
+ }
13
28
  async execute(prompt, userId, sessionId) {
14
29
  if (!this.config) {
15
30
  throw new Error("API configuration not set. Call setApiConfig first.");
16
31
  }
17
32
  const response = await fetch(`${this.config.baseUrl}/interaction`, {
18
33
  method: "POST",
19
- headers: {
20
- "Content-Type": "application/json",
21
- "X-Api-Key": this.config.apiKey
22
- },
34
+ headers: this.getHeaders(),
23
35
  body: JSON.stringify({
24
36
  prompt,
25
37
  userId,
@@ -37,20 +49,12 @@ var DefaultShopPrompterApi = class {
37
49
  throw new Error("API configuration not set. Call setApiConfig first.");
38
50
  }
39
51
  const url = `${this.config.baseUrl}/interaction/stream`;
40
- console.log("ShopPrompter Request:", {
41
- url,
42
- prompt,
43
- userId,
44
- sessionId,
45
- cartContext
46
- });
47
52
  let response;
48
53
  try {
49
54
  response = await fetch(url, {
50
55
  method: "POST",
51
56
  headers: {
52
- "Content-Type": "application/json",
53
- "X-Api-Key": this.config.apiKey,
57
+ ...this.getHeaders(),
54
58
  Accept: "text/event-stream",
55
59
  "Cache-Control": "no-cache"
56
60
  },
@@ -69,7 +73,6 @@ var DefaultShopPrompterApi = class {
69
73
  });
70
74
  return;
71
75
  }
72
- console.log("ShopPrompter Response:", response.status);
73
76
  if (!response.ok) {
74
77
  const errorText = await response.text().catch(() => "");
75
78
  console.error("ShopPrompter API Error:", response.status, errorText);
@@ -90,21 +93,17 @@ var DefaultShopPrompterApi = class {
90
93
  while (true) {
91
94
  const { done, value } = await reader.read();
92
95
  if (done) {
93
- console.log("ShopPrompter Stream done");
94
96
  onEvent({ type: "close" });
95
97
  break;
96
98
  }
97
99
  const chunk = decoder.decode(value, { stream: true });
98
- console.log("ShopPrompter Raw chunk:", chunk);
99
100
  buffer += chunk;
100
101
  const lines = buffer.split("\n");
101
102
  buffer = lines.pop() || "";
102
103
  let currentEventType = "";
103
104
  for (const line of lines) {
104
- console.log("ShopPrompter Line:", line);
105
105
  if (line.startsWith("event:")) {
106
106
  currentEventType = line.slice(6).trim();
107
- console.log("ShopPrompter Event type:", currentEventType);
108
107
  if (currentEventType === "error") {
109
108
  onEvent({
110
109
  type: "error",
@@ -113,7 +112,6 @@ var DefaultShopPrompterApi = class {
113
112
  }
114
113
  } else if (line.startsWith("data:")) {
115
114
  const data = line.slice(5).trim();
116
- console.log("ShopPrompter Data:", data);
117
115
  if (data) {
118
116
  if (currentEventType === "error") {
119
117
  try {
@@ -130,7 +128,6 @@ var DefaultShopPrompterApi = class {
130
128
  }
131
129
  } else {
132
130
  const event = this.parseEvent(data);
133
- console.log("ShopPrompter Parsed event:", event);
134
131
  if (event) {
135
132
  onEvent(event);
136
133
  }
@@ -156,26 +153,47 @@ var DefaultShopPrompterApi = class {
156
153
  try {
157
154
  const response = await fetch(`${this.config.baseUrl}/agent-experience`, {
158
155
  method: "GET",
159
- headers: {
160
- "Content-Type": "application/json",
161
- "X-Api-Key": this.config.apiKey
162
- }
156
+ headers: this.getHeaders()
163
157
  });
164
158
  if (!response.ok) {
165
159
  console.error(`Failed to fetch agent experience: ${response.status}`);
166
160
  return null;
167
161
  }
168
162
  const data = await response.json();
169
- console.log(
170
- "## ~ DefaultShopPrompterApi ~ getAgentExperience ~ data:",
171
- data
172
- );
173
163
  return data;
174
164
  } catch (error) {
175
165
  console.error("Error fetching agent experience:", error);
176
166
  return null;
177
167
  }
178
168
  }
169
+ async sendFeedback(threadId, message, feedback) {
170
+ if (!this.config) {
171
+ throw new Error("API configuration not set. Call setApiConfig first.");
172
+ }
173
+ try {
174
+ const response = await fetch(`${this.config.baseUrl}/feedback`, {
175
+ method: "POST",
176
+ headers: this.getHeaders(),
177
+ body: JSON.stringify({
178
+ threadId,
179
+ message,
180
+ feedback
181
+ })
182
+ });
183
+ if (!response.ok) {
184
+ throw new Error(
185
+ "We are sorry, but we could not process your feedback. Please try again later."
186
+ );
187
+ }
188
+ } catch (error) {
189
+ if (error instanceof Error && error.message.startsWith("We are sorry")) {
190
+ throw error;
191
+ }
192
+ throw new Error(
193
+ "We are sorry, but we could not process your feedback. Please try again later."
194
+ );
195
+ }
196
+ }
179
197
  parseEvent(data) {
180
198
  try {
181
199
  const json = JSON.parse(data);
@@ -285,10 +303,78 @@ var DefaultShopPrompterApi = class {
285
303
  };
286
304
  var shopPrompterApi = new DefaultShopPrompterApi();
287
305
 
306
+ // src/api/product-api.ts
307
+ var DefaultProductApi = class {
308
+ constructor() {
309
+ this.config = null;
310
+ this.cache = /* @__PURE__ */ new Map();
311
+ }
312
+ setApiConfig(config) {
313
+ this.config = config;
314
+ }
315
+ isCached(skus) {
316
+ if (!skus || skus.length === 0) return true;
317
+ return skus.every((sku) => this.cache.has(sku));
318
+ }
319
+ getCached(skus) {
320
+ if (!skus || skus.length === 0) return [];
321
+ return skus.map((sku) => this.cache.get(sku)).filter(Boolean);
322
+ }
323
+ async getProducts(skus) {
324
+ if (!this.config) {
325
+ throw new Error("API configuration not set. Call setApiConfig first.");
326
+ }
327
+ const cachedProducts = [];
328
+ const missingSkus = [];
329
+ for (const sku of skus) {
330
+ if (this.cache.has(sku)) {
331
+ const cachedVal = this.cache.get(sku);
332
+ if (cachedVal) {
333
+ cachedProducts.push(cachedVal);
334
+ }
335
+ } else {
336
+ missingSkus.push(sku);
337
+ }
338
+ }
339
+ if (missingSkus.length === 0) {
340
+ return skus.map((sku) => this.cache.get(sku)).filter(Boolean);
341
+ }
342
+ const baseUrl = this.config.productsBaseUrl || this.config.baseUrl;
343
+ const url = `${baseUrl}/products?skus=${encodeURIComponent(missingSkus.join(","))}`;
344
+ const headers = {
345
+ "Content-Type": "application/json"
346
+ };
347
+ const response = await fetch(url, {
348
+ method: "GET",
349
+ headers
350
+ });
351
+ if (!response.ok) {
352
+ throw new Error(`Product API error: ${response.status}`);
353
+ }
354
+ const newProducts = await response.json();
355
+ const returnedSkus = /* @__PURE__ */ new Set();
356
+ for (const p of newProducts) {
357
+ if (p.sku) {
358
+ this.cache.set(p.sku, p);
359
+ returnedSkus.add(p.sku);
360
+ }
361
+ }
362
+ for (const sku of missingSkus) {
363
+ if (!returnedSkus.has(sku)) {
364
+ this.cache.set(sku, null);
365
+ }
366
+ }
367
+ return skus.map((sku) => this.cache.get(sku)).filter(Boolean);
368
+ }
369
+ };
370
+ var productApi = new DefaultProductApi();
371
+
288
372
  // src/api/session-handler.ts
289
373
  import { v4 as uuidv4 } from "uuid";
290
374
  var SESSION_KEY = "shopprompter_sessionId";
291
375
  var USER_KEY = "shopprompter_userId";
376
+ var SESSIONS_KEY = "shopprompter_sessions";
377
+ var MAX_SESSIONS = 3;
292
378
  var DefaultSessionHandler = class {
293
379
  constructor() {
294
380
  this.sessionId = "";
@@ -316,6 +402,98 @@ var DefaultSessionHandler = class {
316
402
  }
317
403
  return this.userId;
318
404
  }
405
+ // -------------------------------------------------------------------------
406
+ // Message persistence
407
+ // -------------------------------------------------------------------------
408
+ /** Persist a user message immediately when it is sent. */
409
+ saveUserMessage(sessionId, message) {
410
+ try {
411
+ const store = this.loadSessionStore();
412
+ if (!store[sessionId]) {
413
+ this.evictIfNeeded(store);
414
+ store[sessionId] = { createdAt: Date.now(), messages: [] };
415
+ }
416
+ store[sessionId].messages.push(message);
417
+ this.saveSessionStore(store);
418
+ } catch {
419
+ }
420
+ }
421
+ /**
422
+ * Persist the fully-streamed assistant message.
423
+ * If the message ID already exists in the store (shouldn't normally happen)
424
+ * it is replaced; otherwise it is appended.
425
+ */
426
+ saveAssistantMessage(sessionId, message) {
427
+ try {
428
+ const store = this.loadSessionStore();
429
+ if (!store[sessionId]) {
430
+ store[sessionId] = { createdAt: Date.now(), messages: [] };
431
+ }
432
+ const msgs = store[sessionId].messages;
433
+ const existingIdx = msgs.findIndex((m) => m.id === message.id);
434
+ if (existingIdx !== -1) {
435
+ msgs[existingIdx] = message;
436
+ } else {
437
+ msgs.push(message);
438
+ }
439
+ this.saveSessionStore(store);
440
+ } catch {
441
+ }
442
+ }
443
+ /** Return the persisted messages for the given session (newest first order preserved). */
444
+ loadMessages(sessionId) {
445
+ var _a, _b;
446
+ try {
447
+ const store = this.loadSessionStore();
448
+ return (_b = (_a = store[sessionId]) == null ? void 0 : _a.messages) != null ? _b : [];
449
+ } catch {
450
+ return [];
451
+ }
452
+ }
453
+ /** Update the feedback field of a specific persisted message. */
454
+ updateMessageFeedback(sessionId, messageId, feedback) {
455
+ try {
456
+ const store = this.loadSessionStore();
457
+ const session = store[sessionId];
458
+ if (!session) return;
459
+ const msg = session.messages.find((m) => m.id === messageId);
460
+ if (!msg) return;
461
+ msg.feedback = feedback;
462
+ this.saveSessionStore(store);
463
+ } catch {
464
+ }
465
+ }
466
+ // -------------------------------------------------------------------------
467
+ // Private helpers
468
+ // -------------------------------------------------------------------------
469
+ /**
470
+ * Remove the single oldest session from the store when it already holds
471
+ * MAX_SESSIONS entries. Mutates the store object in place.
472
+ */
473
+ evictIfNeeded(store) {
474
+ const sessionIds = Object.keys(store);
475
+ if (sessionIds.length < MAX_SESSIONS) return;
476
+ let oldestId = sessionIds[0];
477
+ let oldestTime = store[oldestId].createdAt;
478
+ for (const id of sessionIds) {
479
+ if (store[id].createdAt < oldestTime) {
480
+ oldestId = id;
481
+ oldestTime = store[id].createdAt;
482
+ }
483
+ }
484
+ delete store[oldestId];
485
+ }
486
+ loadSessionStore() {
487
+ try {
488
+ const raw = localStorage.getItem(SESSIONS_KEY);
489
+ return raw ? JSON.parse(raw) : {};
490
+ } catch {
491
+ return {};
492
+ }
493
+ }
494
+ saveSessionStore(store) {
495
+ localStorage.setItem(SESSIONS_KEY, JSON.stringify(store));
496
+ }
319
497
  getPersistedSessionId() {
320
498
  try {
321
499
  return localStorage.getItem(SESSION_KEY);
@@ -346,16 +524,13 @@ var DefaultSessionHandler = class {
346
524
  var sessionHandler = new DefaultSessionHandler();
347
525
 
348
526
  // src/shop-prompter.service.ts
349
- var SHOP_PROMPTER_CONFIG = {
350
- baseUrl: "https://demo.dev.shop-prompter.com/touch-points-api",
351
- apiKey: "864c87266ef52c079c09b3248d86b4b5ef430bf9e5a4188476124c93ee2f6dda380f337986837b30b60f73e6aceefe7a0e0f778b3d21a7fa7698cf8546afc709"
352
- };
353
527
  var ShopPrompterService = class {
354
- constructor() {
528
+ constructor(apiConfig) {
355
529
  this.isLoading = false;
356
530
  this.error = null;
357
531
  this.streamingText = "";
358
- shopPrompterApi.setApiConfig(SHOP_PROMPTER_CONFIG);
532
+ shopPrompterApi.setApiConfig(apiConfig);
533
+ productApi.setApiConfig(apiConfig);
359
534
  sessionHandler.initialize();
360
535
  }
361
536
  async sendMessage(prompt, callbacks, cartContext) {
@@ -366,7 +541,16 @@ var ShopPrompterService = class {
366
541
  this.streamingText = "";
367
542
  const userId = sessionHandler.getUserId();
368
543
  const sessionId = sessionHandler.getSessionId();
544
+ const userMsgId = Date.now().toString() + "-user";
545
+ sessionHandler.saveUserMessage(sessionId, {
546
+ id: userMsgId,
547
+ role: "user",
548
+ content: prompt,
549
+ productSkus: []
550
+ });
551
+ const assistantMsgId = Date.now().toString() + "-assistant";
369
552
  let accumulatedText = "";
553
+ let accumulatedSkus = [];
370
554
  try {
371
555
  await shopPrompterApi.executeStream(
372
556
  prompt,
@@ -381,6 +565,7 @@ var ShopPrompterService = class {
381
565
  (_a2 = callbacks.onTextUpdate) == null ? void 0 : _a2.call(callbacks, accumulatedText);
382
566
  break;
383
567
  case "productSkus":
568
+ accumulatedSkus = event.skus;
384
569
  (_b2 = callbacks.onProductSkus) == null ? void 0 : _b2.call(callbacks, event.skus);
385
570
  break;
386
571
  case "navigation":
@@ -393,6 +578,12 @@ var ShopPrompterService = class {
393
578
  this.isLoading = false;
394
579
  (_d = callbacks.onLoadingChange) == null ? void 0 : _d.call(callbacks, false);
395
580
  (_e = callbacks.onComplete) == null ? void 0 : _e.call(callbacks);
581
+ sessionHandler.saveAssistantMessage(sessionId, {
582
+ id: assistantMsgId,
583
+ role: "assistant",
584
+ content: accumulatedText,
585
+ productSkus: accumulatedSkus
586
+ });
396
587
  break;
397
588
  case "error":
398
589
  this.error = event.reason;
@@ -414,9 +605,6 @@ var ShopPrompterService = class {
414
605
  return accumulatedText;
415
606
  }
416
607
  async getAgentExperience() {
417
- console.log(
418
- "## ~ ShopPrompterService ~ getAgentExperience ~ getAgentExperience:"
419
- );
420
608
  try {
421
609
  return await shopPrompterApi.getAgentExperience();
422
610
  } catch (err) {
@@ -424,6 +612,32 @@ var ShopPrompterService = class {
424
612
  throw err;
425
613
  }
426
614
  }
615
+ /**
616
+ * Load persisted chat messages for the current session from localStorage.
617
+ * Returns an empty array if nothing is stored yet.
618
+ */
619
+ loadMessages() {
620
+ const sessionId = sessionHandler.getSessionId();
621
+ const persisted = sessionHandler.loadMessages(sessionId);
622
+ return persisted.map((msg) => {
623
+ var _a, _b;
624
+ return {
625
+ id: msg.id,
626
+ role: msg.role,
627
+ content: msg.content,
628
+ productSkus: (_a = msg.productSkus) != null ? _a : [],
629
+ feedback: (_b = msg.feedback) != null ? _b : null
630
+ };
631
+ });
632
+ }
633
+ async sendFeedback(messageId, messageContent, feedback) {
634
+ const userId = sessionHandler.getUserId();
635
+ const sessionId = sessionHandler.getSessionId();
636
+ const threadId = `${userId}:${sessionId}`;
637
+ await shopPrompterApi.sendFeedback(threadId, messageContent, feedback);
638
+ const storedFeedback = feedback === "clear" ? null : feedback;
639
+ sessionHandler.updateMessageFeedback(sessionId, messageId, storedFeedback);
640
+ }
427
641
  resetSession() {
428
642
  sessionHandler.regenerate();
429
643
  }
@@ -436,14 +650,244 @@ var ShopPrompterService = class {
436
650
  }
437
651
  };
438
652
 
439
- // src/shop-prompter.component.jsx
440
- import { Fragment, jsx, jsxs } from "react/jsx-runtime";
653
+ // src/thumbs-up-icon.component.jsx
654
+ import * as React from "react";
655
+ import { jsx, jsxs } from "react/jsx-runtime";
656
+ function ThumbsUpIcon(props) {
657
+ return /* @__PURE__ */ jsxs(
658
+ "svg",
659
+ {
660
+ xmlns: "http://www.w3.org/2000/svg",
661
+ width: "18",
662
+ height: "18",
663
+ viewBox: "0 0 24 24",
664
+ "stroke-width": "2",
665
+ "stroke-linecap": "round",
666
+ "stroke-linejoin": "round",
667
+ fill: props.fill || "none",
668
+ stroke: props.stroke || "currentColor",
669
+ style: {
670
+ overflow: "visible"
671
+ },
672
+ children: [
673
+ /* @__PURE__ */ jsx("path", { d: "M7 10v12" }),
674
+ /* @__PURE__ */ jsx("path", { d: "M15 5.88 14 10h5.83a2 2 0 0 1 1.92 2.56l-2.33 8A2 2 0 0 1 17.5 22H4a2 2 0 0 1-2-2v-8a2 2 0 0 1 2-2h2.76a2 2 0 0 0 1.79-1.11L12 2h0a3.13 3.13 0 0 1 3 3.88Z" })
675
+ ]
676
+ }
677
+ );
678
+ }
679
+ var thumbs_up_icon_component_default = ThumbsUpIcon;
680
+
681
+ // src/thumbs-down-icon.component.jsx
682
+ import * as React2 from "react";
683
+ import { jsx as jsx2, jsxs as jsxs2 } from "react/jsx-runtime";
684
+ function ThumbsDownIcon(props) {
685
+ return /* @__PURE__ */ jsxs2(
686
+ "svg",
687
+ {
688
+ xmlns: "http://www.w3.org/2000/svg",
689
+ width: "18",
690
+ height: "18",
691
+ viewBox: "0 0 24 24",
692
+ "stroke-width": "2",
693
+ "stroke-linecap": "round",
694
+ "stroke-linejoin": "round",
695
+ fill: props.fill || "none",
696
+ stroke: props.stroke || "currentColor",
697
+ style: {
698
+ overflow: "visible"
699
+ },
700
+ children: [
701
+ /* @__PURE__ */ jsx2("path", { d: "M17 14V2" }),
702
+ /* @__PURE__ */ jsx2("path", { d: "M9 18.12 10 14H4.17a2 2 0 0 1-1.92-2.56l2.33-8A2 2 0 0 1 6.5 2H20a2 2 0 0 1 2 2v8a2 2 0 0 1-2 2h-2.76a2 2 0 0 0-1.79 1.11L12 22h0a3.13 3.13 0 0 1-3-3.88Z" })
703
+ ]
704
+ }
705
+ );
706
+ }
707
+ var thumbs_down_icon_component_default = ThumbsDownIcon;
708
+
709
+ // src/product-card-list.component.jsx
710
+ import * as React3 from "react";
711
+ import { useState, useEffect } from "react";
712
+ import { Fragment, jsx as jsx3, jsxs as jsxs3 } from "react/jsx-runtime";
441
713
  var styles = {
714
+ productCardsContainer: {
715
+ marginTop: "0.75rem",
716
+ display: "flex",
717
+ gap: "0.75rem",
718
+ overflowX: "auto",
719
+ width: "100%",
720
+ paddingBottom: "0.5rem",
721
+ boxSizing: "border-box",
722
+ scrollbarWidth: "thin",
723
+ scrollSnapType: "x mandatory",
724
+ WebkitOverflowScrolling: "touch"
725
+ },
726
+ productCard: {
727
+ minWidth: "9.5rem",
728
+ maxWidth: "9.5rem",
729
+ backgroundColor: "white",
730
+ border: "1px solid #f3f4f6",
731
+ borderRadius: "0.75rem",
732
+ overflow: "hidden",
733
+ boxShadow: "0 4px 6px -1px rgba(0, 0, 0, 0.05), 0 2px 4px -1px rgba(0, 0, 0, 0.03)",
734
+ display: "flex",
735
+ flexDirection: "column",
736
+ scrollSnapAlign: "start"
737
+ },
738
+ productImageContainer: {
739
+ height: "7rem",
740
+ backgroundColor: "#f9fafb",
741
+ display: "flex",
742
+ alignItems: "center",
743
+ justifyContent: "center",
744
+ padding: "0.5rem",
745
+ borderBottom: "1px solid #f3f4f6"
746
+ },
747
+ productImage: {
748
+ maxHeight: "100%",
749
+ maxWidth: "100%",
750
+ objectFit: "contain"
751
+ },
752
+ productInfo: {
753
+ padding: "0.625rem",
754
+ display: "flex",
755
+ flexDirection: "column",
756
+ gap: "0.25rem"
757
+ },
758
+ productName: {
759
+ fontSize: "0.8125rem",
760
+ fontWeight: 600,
761
+ color: "#1f2937",
762
+ margin: 0,
763
+ whiteSpace: "nowrap",
764
+ overflow: "hidden",
765
+ textOverflow: "ellipsis"
766
+ },
767
+ productPrice: {
768
+ fontSize: "0.8125rem",
769
+ fontWeight: 500,
770
+ color: "#4b5563",
771
+ margin: 0
772
+ },
773
+ statusContainer: {
774
+ padding: "0.5rem 0",
775
+ fontSize: "0.75rem",
776
+ color: "#6b7280",
777
+ display: "flex",
778
+ alignItems: "center",
779
+ gap: "0.5rem"
780
+ },
781
+ errorText: {
782
+ color: "#ef4444"
783
+ },
784
+ spinner: {
785
+ color: "#6b7280"
786
+ },
787
+ wrapper: {
788
+ width: "100%",
789
+ maxWidth: "100%",
790
+ boxSizing: "border-box",
791
+ overflow: "hidden"
792
+ }
793
+ };
794
+ function ProductCardList(props) {
795
+ const [products, setProducts] = useState(() => []);
796
+ const [loading, setLoading] = useState(() => false);
797
+ const [error, setError] = useState(() => null);
798
+ function fetchProducts() {
799
+ let skusList = props.skus;
800
+ if (typeof skusList === "string") {
801
+ skusList = skusList.split(",").map((s) => s.trim()).filter(Boolean);
802
+ }
803
+ if (!skusList || skusList.length === 0) {
804
+ setProducts([]);
805
+ setLoading(false);
806
+ return;
807
+ }
808
+ if (productApi.isCached(skusList)) {
809
+ setProducts(productApi.getCached(skusList));
810
+ setLoading(false);
811
+ setError(null);
812
+ return;
813
+ }
814
+ setLoading(true);
815
+ setError(null);
816
+ productApi.getProducts(skusList).then((data) => {
817
+ setProducts(data || []);
818
+ setLoading(false);
819
+ }).catch((err) => {
820
+ console.error("Failed to fetch products:", err);
821
+ setError((err == null ? void 0 : err.message) || "Failed to load products");
822
+ setLoading(false);
823
+ });
824
+ }
825
+ function getProductName(product) {
826
+ var _a;
827
+ const locale = props.defaultLocale || "de";
828
+ const localized = ((_a = product.localization) == null ? void 0 : _a[locale]) || Object.values(product.localization || {})[0];
829
+ return (localized == null ? void 0 : localized.name) || product.sku;
830
+ }
831
+ function getProductPrice(product) {
832
+ if (!product.pricing) return "";
833
+ const priceVal = product.pricing.gross;
834
+ const currency = product.pricing.currency;
835
+ if (priceVal === void 0 || priceVal === null) return "";
836
+ return priceVal.toFixed(2) + " " + (currency || "\u20AC");
837
+ }
838
+ function getProductImage(product) {
839
+ var _a;
840
+ return ((_a = product.images) == null ? void 0 : _a[0]) || "https://placehold.co/150x150?text=" + product.sku;
841
+ }
842
+ useEffect(() => {
843
+ fetchProducts();
844
+ }, []);
845
+ useEffect(() => {
846
+ fetchProducts();
847
+ }, [
848
+ props.skus ? Array.isArray(props.skus) ? props.skus.join(",") : props.skus : ""
849
+ ]);
850
+ return /* @__PURE__ */ jsx3(Fragment, { children: props.skus && props.skus.length > 0 ? /* @__PURE__ */ jsx3(Fragment, { children: /* @__PURE__ */ jsxs3("div", { style: styles.wrapper, children: [
851
+ loading ? /* @__PURE__ */ jsx3("div", { style: styles.statusContainer, children: /* @__PURE__ */ jsx3("span", { children: "Loading products..." }) }) : null,
852
+ !loading && error ? /* @__PURE__ */ jsx3("div", { style: styles.statusContainer, children: /* @__PURE__ */ jsxs3("span", { style: styles.errorText, children: [
853
+ "Error: ",
854
+ error
855
+ ] }) }) : null,
856
+ !loading && products && products.length > 0 ? /* @__PURE__ */ jsx3("div", { style: styles.productCardsContainer, children: products == null ? void 0 : products.map((product) => /* @__PURE__ */ jsxs3("div", { style: styles.productCard, children: [
857
+ /* @__PURE__ */ jsx3("div", { style: styles.productImageContainer, children: /* @__PURE__ */ jsx3(
858
+ "img",
859
+ {
860
+ src: getProductImage(product),
861
+ alt: getProductName(product),
862
+ style: styles.productImage
863
+ }
864
+ ) }),
865
+ /* @__PURE__ */ jsxs3("div", { style: styles.productInfo, children: [
866
+ /* @__PURE__ */ jsx3(
867
+ "p",
868
+ {
869
+ style: styles.productName,
870
+ title: getProductName(product),
871
+ children: getProductName(product)
872
+ }
873
+ ),
874
+ /* @__PURE__ */ jsx3("p", { style: styles.productPrice, children: getProductPrice(product) })
875
+ ] })
876
+ ] }, product.sku)) }) : null
877
+ ] }) }) : null });
878
+ }
879
+ var product_card_list_component_default = ProductCardList;
880
+
881
+ // src/shop-prompter.component.jsx
882
+ import { Fragment as Fragment2, jsx as jsx4, jsxs as jsxs4 } from "react/jsx-runtime";
883
+ var THINKING_SPINNER = "M21 12a9 9 0 1 1-6.219-8.56";
884
+ var styles2 = {
442
885
  header: {
443
886
  display: "flex",
444
887
  alignItems: "center",
445
888
  justifyContent: "space-between",
446
- padding: "16px"
889
+ padding: "16px",
890
+ borderBottom: "1px solid #e5e7eb"
447
891
  },
448
892
  subHeaderContainer: {
449
893
  display: "flex",
@@ -459,6 +903,7 @@ var styles = {
459
903
  border: "none",
460
904
  cursor: "pointer",
461
905
  transition: "background-color 0.2s, color 0.2s",
906
+ fontFamily: "inherit",
462
907
  onHover: {
463
908
  backgroundColor: "hsl(220 14% 96%)",
464
909
  color: "hsl(220 13% 13%)"
@@ -479,7 +924,8 @@ var styles = {
479
924
  gap: "0.5rem",
480
925
  cursor: "pointer",
481
926
  fontSize: "0.875rem",
482
- color: "#09090b"
927
+ color: "#09090b",
928
+ fontFamily: "inherit"
483
929
  },
484
930
  ButtonSheetButton: {
485
931
  color: "#6b7280",
@@ -488,11 +934,13 @@ var styles = {
488
934
  cursor: "pointer",
489
935
  padding: "0.25rem",
490
936
  fontSize: "1.25rem",
491
- transition: "color 0.2s"
937
+ transition: "color 0.2s",
938
+ fontFamily: "inherit"
492
939
  },
493
940
  chatContainer: {
494
941
  flex: 1,
495
942
  overflowY: "auto",
943
+ overflowX: "hidden",
496
944
  padding: "1rem",
497
945
  backgroundColor: "white"
498
946
  },
@@ -538,12 +986,17 @@ var styles = {
538
986
  messageContainerUser: {
539
987
  display: "flex",
540
988
  flexDirection: "column",
541
- alignItems: "flex-end"
989
+ alignItems: "flex-end",
990
+ marginBottom: "8px"
542
991
  },
543
992
  messageContainerAssistant: {
544
993
  display: "flex",
545
994
  flexDirection: "column",
546
- alignItems: "flex-start"
995
+ alignItems: "flex-start",
996
+ marginBottom: "8px",
997
+ width: "100%",
998
+ maxWidth: "100%",
999
+ boxSizing: "border-box"
547
1000
  },
548
1001
  messageBubbleUser: {
549
1002
  backgroundColor: "#111827",
@@ -553,7 +1006,8 @@ var styles = {
553
1006
  padding: "0.5rem 1rem",
554
1007
  fontSize: "0.875rem",
555
1008
  boxShadow: "0 1px 2px 0 rgba(0, 0, 0, 0.05)",
556
- maxWidth: "85%"
1009
+ maxWidth: "85%",
1010
+ textAlign: "left"
557
1011
  },
558
1012
  messageBubbleAssistant: {
559
1013
  backgroundColor: "#f3f4f6",
@@ -563,7 +1017,8 @@ var styles = {
563
1017
  padding: "0.5rem 1rem",
564
1018
  fontSize: "0.875rem",
565
1019
  boxShadow: "0 1px 2px 0 rgba(0, 0, 0, 0.05)",
566
- maxWidth: "85%"
1020
+ maxWidth: "85%",
1021
+ textAlign: "left"
567
1022
  },
568
1023
  thinkingIndicator: {
569
1024
  display: "flex",
@@ -645,7 +1100,8 @@ var styles = {
645
1100
  outline: "none",
646
1101
  fontSize: "0.875rem",
647
1102
  color: "#111827",
648
- padding: "0.25rem 0"
1103
+ padding: "0.25rem 0",
1104
+ fontFamily: "inherit"
649
1105
  },
650
1106
  formButton: {
651
1107
  backgroundColor: "transparent",
@@ -658,7 +1114,8 @@ var styles = {
658
1114
  fontWeight: "bold",
659
1115
  border: "none",
660
1116
  cursor: "pointer",
661
- transition: "background-color 0.2s"
1117
+ transition: "background-color 0.2s",
1118
+ fontFamily: "inherit"
662
1119
  },
663
1120
  sendButton: {
664
1121
  backgroundColor: "#AD59FF1A"
@@ -668,17 +1125,169 @@ var styles = {
668
1125
  color: "#9ca3af",
669
1126
  textAlign: "center",
670
1127
  marginTop: "0.75rem"
1128
+ },
1129
+ backdrop: {
1130
+ position: "fixed",
1131
+ top: 0,
1132
+ left: 0,
1133
+ right: 0,
1134
+ bottom: 0,
1135
+ backgroundColor: "rgba(0, 0, 0, 0.5)",
1136
+ backdropFilter: "blur(4px)",
1137
+ zIndex: 1e3
1138
+ },
1139
+ feedbackRow: {
1140
+ display: "flex",
1141
+ alignItems: "center",
1142
+ gap: "0.5rem",
1143
+ marginTop: "0.5rem",
1144
+ marginLeft: "0.75rem"
1145
+ },
1146
+ feedbackButton: {
1147
+ backgroundColor: "transparent",
1148
+ border: "none",
1149
+ cursor: "pointer",
1150
+ padding: "6px",
1151
+ borderRadius: "6px",
1152
+ display: "flex",
1153
+ alignItems: "center",
1154
+ justifyContent: "center",
1155
+ transition: "background-color 0.2s"
1156
+ },
1157
+ warningBanner: {
1158
+ backgroundColor: "#fffbeb",
1159
+ color: "#b45309",
1160
+ border: "1px solid #fde68a",
1161
+ borderRadius: "0.375rem",
1162
+ padding: "0.25rem 0.5rem",
1163
+ fontSize: "0.6875rem",
1164
+ fontWeight: 500,
1165
+ textAlign: "center",
1166
+ margin: "0 0.5rem",
1167
+ flex: 1,
1168
+ display: "flex",
1169
+ alignItems: "center",
1170
+ justifyContent: "center"
1171
+ },
1172
+ insufficientConfigContainer: {
1173
+ flex: 1,
1174
+ display: "flex",
1175
+ flexDirection: "column",
1176
+ alignItems: "center",
1177
+ justifyContent: "center",
1178
+ padding: "2rem",
1179
+ textAlign: "center",
1180
+ backgroundColor: "#fff5f5",
1181
+ color: "#2d3748"
1182
+ },
1183
+ insufficientConfigIconContainer: {
1184
+ backgroundColor: "#fee2e2",
1185
+ padding: "1rem",
1186
+ borderRadius: "50%",
1187
+ marginBottom: "1rem",
1188
+ display: "flex",
1189
+ alignItems: "center",
1190
+ justifyContent: "center",
1191
+ boxShadow: "0 4px 6px -1px rgba(239, 68, 68, 0.1), 0 2px 4px -1px rgba(239, 68, 68, 0.06)"
1192
+ },
1193
+ insufficientConfigTitle: {
1194
+ fontSize: "1.25rem",
1195
+ fontWeight: 700,
1196
+ color: "#991b1b",
1197
+ marginBottom: "0.5rem"
1198
+ },
1199
+ insufficientConfigMessage: {
1200
+ fontSize: "0.875rem",
1201
+ color: "#7f1d1d",
1202
+ marginBottom: "1.5rem",
1203
+ lineHeight: "1.5",
1204
+ maxWidth: "280px"
1205
+ },
1206
+ insufficientConfigDetails: {
1207
+ backgroundColor: "white",
1208
+ border: "1px solid #fee2e2",
1209
+ borderRadius: "0.5rem",
1210
+ padding: "1rem",
1211
+ textAlign: "left",
1212
+ width: "100%",
1213
+ maxWidth: "300px",
1214
+ boxShadow: "0 1px 3px 0 rgba(0, 0, 0, 0.05)"
671
1215
  }
672
1216
  };
1217
+ var ANIMATION_STYLES = `
1218
+ @keyframes sh-fade-in {
1219
+ from {
1220
+ opacity: 0;
1221
+ transform: translate(-50%, -48%) scale(0.96);
1222
+ }
1223
+ to {
1224
+ opacity: 1;
1225
+ transform: translate(-50%, -50%) scale(1);
1226
+ }
1227
+ }
1228
+ @keyframes sh-fade-out {
1229
+ from {
1230
+ opacity: 1;
1231
+ transform: translate(-50%, -50%) scale(1);
1232
+ }
1233
+ to {
1234
+ opacity: 0;
1235
+ transform: translate(-50%, -48%) scale(0.96);
1236
+ }
1237
+ }
1238
+ @keyframes sh-backdrop-fade-in {
1239
+ from {
1240
+ opacity: 0;
1241
+ }
1242
+ to {
1243
+ opacity: 1;
1244
+ }
1245
+ }
1246
+ @keyframes sh-backdrop-fade-out {
1247
+ from {
1248
+ opacity: 1;
1249
+ }
1250
+ to {
1251
+ opacity: 0;
1252
+ }
1253
+ }
1254
+ .sh-dialog-animate {
1255
+ animation: sh-fade-in 0.22s cubic-bezier(0.16, 1, 0.3, 1) forwards;
1256
+ }
1257
+ .sh-dialog-animate-out {
1258
+ animation: sh-fade-out 0.2s cubic-bezier(0.16, 1, 0.3, 1) forwards;
1259
+ }
1260
+ .sh-backdrop-animate {
1261
+ animation: sh-backdrop-fade-in 0.18s ease-out forwards;
1262
+ }
1263
+ .sh-backdrop-animate-out {
1264
+ animation: sh-backdrop-fade-out 0.18s ease-out forwards;
1265
+ }
1266
+ .sh-feedback-btn {
1267
+ color: #a1a1aa;
1268
+ border-radius: 4px;
1269
+ transition: color 0.2s, background-color 0.2s;
1270
+ }
1271
+ .sh-feedback-btn:hover {
1272
+ background-color: #f4f4f5 !important;
1273
+ color: #3f3f46 !important;
1274
+ }
1275
+ .sh-header-btn {
1276
+ transition: all 0.2s;
1277
+ }
1278
+ .sh-header-btn:hover {
1279
+ background-color: #f9fafb !important;
1280
+ border-color: #d1d5db !important;
1281
+ }
1282
+ `;
673
1283
  var TRANSLATIONS = {
674
1284
  newChat: "New Chat",
675
1285
  welcomeToShopPrompter: "Welcome to ShopPrompter",
676
1286
  welcomeDescription: "I am your personal AI shopping assistant. Ask me anything about our products!",
677
1287
  askMeAnything: "Ask me anything...",
678
1288
  thinking: "Thinking...",
679
- showPopularItems: "Show popular items",
680
- compareProducts: "Compare products",
681
- findByBudget: "Find by budget"
1289
+ findByBudget: "Find by budget",
1290
+ feedbackError: "We are sorry, but we could not process your feedback. Please try again later."
682
1291
  };
683
1292
  var ICONS = {
684
1293
  chat: "https://cdn.jsdelivr.net/gh/lucide-icons/lucide@latest/icons/message-square.svg",
@@ -689,69 +1298,108 @@ var ICONS = {
689
1298
  sendHorizontal: "https://cdn.jsdelivr.net/gh/lucide-icons/lucide@latest/icons/send-horizontal.svg"
690
1299
  };
691
1300
  function ShopPrompter(props) {
692
- var _a, _b, _c;
693
- const [input, setInput] = useState(() => "");
694
- const [isLoading, setIsLoading] = useState(() => false);
695
- const [error, setError] = useState(() => null);
696
- const [chatMessages, setChatMessages] = useState(() => []);
697
- const [showChat, setShowChat] = useState(
698
- () => props.chatPosition === "right-panel" || props.chatPosition === "full-page"
699
- );
700
- const [service, setService] = useState(() => null);
701
- const [isHeaderButtonHovered, setIsHeaderButtonHovered] = useState(
702
- () => false
1301
+ var _a, _b, _c, _d;
1302
+ const [input, setInput] = useState2(() => "");
1303
+ const [isLoading, setIsLoading] = useState2(() => false);
1304
+ const [error, setError] = useState2(() => null);
1305
+ const [chatMessages, setChatMessages] = useState2(() => []);
1306
+ const [showChat, setShowChat] = useState2(() => false);
1307
+ const [isClosing, setIsClosing] = useState2(() => false);
1308
+ const [closeTimeout, setCloseTimeout] = useState2(() => null);
1309
+ const [service, setService] = useState2(() => null);
1310
+ const [agentExperience, setAgentExperience] = useState2(() => null);
1311
+ const [animationClass, setAnimationClass] = useState2(() => "");
1312
+ const [backdropAnimationClass, setBackdropAnimationClass] = useState2(
1313
+ () => ""
703
1314
  );
704
- const [agentExperience, setAgentExperience] = useState(() => null);
1315
+ function hasToken() {
1316
+ var _a2;
1317
+ const token = props.shopPrompterToken || ((_a2 = apiConfigObj == null ? void 0 : apiConfigObj()) == null ? void 0 : _a2.shopPrompterToken);
1318
+ return !!token;
1319
+ }
1320
+ function isConfigInsufficient() {
1321
+ var _a2, _b2;
1322
+ const token = props.shopPrompterToken || ((_a2 = apiConfigObj == null ? void 0 : apiConfigObj()) == null ? void 0 : _a2.shopPrompterToken);
1323
+ const apiKey = (_b2 = apiConfigObj == null ? void 0 : apiConfigObj()) == null ? void 0 : _b2.apiKey;
1324
+ return !token && !apiKey;
1325
+ }
1326
+ function themeObj() {
1327
+ if (typeof props.theme === "string") {
1328
+ try {
1329
+ return JSON.parse(props.theme);
1330
+ } catch (e) {
1331
+ return {};
1332
+ }
1333
+ }
1334
+ return props.theme || {};
1335
+ }
1336
+ function prompts() {
1337
+ return (agentExperience == null ? void 0 : agentExperience.predefinedPrompts) || [];
1338
+ }
1339
+ function apiConfigObj() {
1340
+ if (typeof props.apiConfig === "string") {
1341
+ try {
1342
+ return JSON.parse(props.apiConfig);
1343
+ } catch (e) {
1344
+ return null;
1345
+ }
1346
+ }
1347
+ return props.apiConfig || null;
1348
+ }
705
1349
  function containerStyle() {
706
1350
  const pos = props.chatPosition || "classic-chatbot";
707
1351
  const isFull = pos === "full-page";
708
- const isBottom = pos === "bottom-sheet";
1352
+ const isDialog = pos === "dialog";
709
1353
  const isClassic = pos === "classic-chatbot";
710
1354
  const isRight = pos === "right-panel";
711
1355
  return {
712
1356
  position: isFull ? "relative" : "fixed",
713
- bottom: isClassic ? "1rem" : isBottom ? "2rem" : "0",
714
- right: isClassic || isRight ? "1rem" : "0",
715
- width: isFull ? "100%" : isBottom ? "90%" : "24rem",
716
- height: isClassic ? "550px" : isBottom ? "700px" : "100%",
717
- maxWidth: isBottom ? "900px" : "none",
718
- left: isBottom ? "50%" : "auto",
719
- transform: isBottom ? "translateX(-50%)" : "none",
720
- zIndex: 50,
721
- backgroundColor: "white",
1357
+ bottom: isClassic ? "1rem" : isDialog ? "auto" : "0",
1358
+ top: isDialog ? "50%" : "auto",
1359
+ right: isClassic || isRight ? "1rem" : isDialog ? "auto" : "0",
1360
+ left: isDialog ? "50%" : isClassic || isRight || isFull ? "auto" : "0",
1361
+ transform: isDialog ? "translate(-50%, -50%)" : "none",
1362
+ width: isFull ? "100%" : isDialog ? "90%" : "24rem",
1363
+ height: isClassic ? "550px" : isDialog ? "700px" : isFull ? "600px" : "100%",
1364
+ maxWidth: isDialog ? "900px" : "none",
1365
+ maxHeight: isDialog ? "90vh" : "none",
1366
+ zIndex: isDialog ? 1001 : isClassic || isRight ? 1001 : 50,
1367
+ backgroundColor: themeObj().mainBackgroundColor || "white",
722
1368
  display: "flex",
723
1369
  flexDirection: "column",
724
1370
  overflow: "hidden",
725
1371
  borderRadius: isFull ? "0" : "0.5rem",
726
1372
  border: isFull ? "none" : "1px solid #e5e7eb",
727
- boxShadow: isFull ? "none" : "0 25px 50px -12px rgba(0, 0, 0, 0.25)"
1373
+ boxShadow: isFull ? "none" : "0 25px 50px -12px rgba(0, 0, 0, 0.25)",
1374
+ fontFamily: themeObj().fontFamily || void 0
728
1375
  };
729
1376
  }
730
1377
  function containerClass() {
731
1378
  const pos = props.chatPosition || "classic-chatbot";
732
1379
  if (pos === "classic-chatbot") return "sh-classic";
733
1380
  if (pos === "right-panel") return "sh-right";
734
- if (pos === "bottom-sheet") return "sh-bottom";
1381
+ if (pos === "dialog") {
1382
+ return "sh-dialog " + animationClass;
1383
+ }
735
1384
  return "sh-full";
736
1385
  }
737
1386
  function messages() {
738
- return chatMessages.map((msg) => ({
739
- ...msg,
740
- safeProductSkus: msg.productSkus || []
741
- }));
1387
+ return chatMessages;
1388
+ }
1389
+ function parseMarkdown(content) {
1390
+ if (!content) return "";
1391
+ return String(marked.parse(content));
742
1392
  }
743
1393
  function showWelcome() {
744
1394
  return chatMessages.length === 0;
745
1395
  }
746
- function getProductImageUrl(sku) {
747
- return "https://placehold.co/100x100?text=" + sku;
1396
+ function getShowProducts(message) {
1397
+ return message.productSkus && message.productSkus.length > 0;
748
1398
  }
749
- function getProductLink(sku) {
750
- return "/product/" + sku;
751
- }
752
- function handleSend() {
753
- if (!input.trim() || isLoading) return;
754
- const userQuery = input;
1399
+ function handleSend(overrideQuery) {
1400
+ const actualQuery = overrideQuery || input;
1401
+ if (!actualQuery.trim() || isLoading) return;
1402
+ const userQuery = actualQuery;
755
1403
  setInput("");
756
1404
  const userMsg = {
757
1405
  id: Date.now().toString() + "-user",
@@ -759,30 +1407,45 @@ function ShopPrompter(props) {
759
1407
  content: userQuery,
760
1408
  productSkus: []
761
1409
  };
762
- setChatMessages([...chatMessages, userMsg]);
763
1410
  const assistantMsg = {
764
1411
  id: Date.now().toString() + "-assistant",
765
1412
  role: "assistant",
766
1413
  content: "",
767
1414
  productSkus: []
768
1415
  };
769
- setChatMessages([...chatMessages, assistantMsg]);
1416
+ let currentMessages = [...chatMessages, userMsg, assistantMsg];
1417
+ setChatMessages(currentMessages);
1418
+ setTimeout(() => {
1419
+ const inputEl = document.getElementById("shop-prompter-input");
1420
+ if (inputEl) {
1421
+ inputEl.value = "";
1422
+ inputEl.focus();
1423
+ }
1424
+ }, 0);
770
1425
  service == null ? void 0 : service.sendMessage(
771
1426
  userQuery,
772
1427
  {
773
1428
  onTextUpdate: (text) => {
774
- const updatedMessages = [...chatMessages];
1429
+ const updatedMessages = [...currentMessages];
775
1430
  const lastMsg = updatedMessages[updatedMessages.length - 1];
776
1431
  if (lastMsg) {
777
- lastMsg.content = text;
1432
+ updatedMessages[updatedMessages.length - 1] = {
1433
+ ...lastMsg,
1434
+ content: text
1435
+ };
1436
+ currentMessages = updatedMessages;
778
1437
  setChatMessages(updatedMessages);
779
1438
  }
780
1439
  },
781
1440
  onProductSkus: (skus) => {
782
- const updatedMessages = [...chatMessages];
1441
+ const updatedMessages = [...currentMessages];
783
1442
  const lastMsg = updatedMessages[updatedMessages.length - 1];
784
1443
  if (lastMsg) {
785
- lastMsg.productSkus = skus;
1444
+ updatedMessages[updatedMessages.length - 1] = {
1445
+ ...lastMsg,
1446
+ productSkus: skus
1447
+ };
1448
+ currentMessages = updatedMessages;
786
1449
  setChatMessages(updatedMessages);
787
1450
  }
788
1451
  },
@@ -796,29 +1459,63 @@ function ShopPrompter(props) {
796
1459
  if (props.onCartOperation) {
797
1460
  props.onCartOperation(ops);
798
1461
  }
1462
+ dispatchCartOperation(ops);
799
1463
  }
800
1464
  },
801
1465
  props.cart || []
802
1466
  );
803
1467
  }
1468
+ function dispatchCartOperation(ops) {
1469
+ if (typeof window !== "undefined") {
1470
+ const root = typeof self !== "undefined" && self && "dispatchEvent" in self && !(self instanceof Window) ? self : null;
1471
+ if (root) {
1472
+ root.dispatchEvent(
1473
+ new CustomEvent("cartOperation", {
1474
+ detail: ops
1475
+ })
1476
+ );
1477
+ }
1478
+ }
1479
+ }
804
1480
  function toggleChat() {
805
- setShowChat(!showChat);
806
- if (!showChat && props.onClose) {
807
- props.onClose();
1481
+ if (showChat) {
1482
+ setIsClosing(true);
1483
+ setAnimationClass("sh-dialog-animate-out");
1484
+ setBackdropAnimationClass("sh-backdrop-animate-out");
1485
+ if (closeTimeout) {
1486
+ clearTimeout(closeTimeout);
1487
+ }
1488
+ setCloseTimeout(
1489
+ setTimeout(() => {
1490
+ setShowChat(false);
1491
+ setIsClosing(false);
1492
+ setAnimationClass("");
1493
+ setBackdropAnimationClass("");
1494
+ setCloseTimeout(null);
1495
+ if (props.onClose) {
1496
+ props.onClose();
1497
+ }
1498
+ }, 200)
1499
+ );
1500
+ } else {
1501
+ if (closeTimeout) {
1502
+ clearTimeout(closeTimeout);
1503
+ setCloseTimeout(null);
1504
+ }
1505
+ setShowChat(true);
1506
+ setIsClosing(false);
1507
+ setAnimationClass("sh-dialog-animate");
1508
+ setBackdropAnimationClass("sh-backdrop-animate");
1509
+ setTimeout(() => {
1510
+ setAnimationClass("");
1511
+ setBackdropAnimationClass("");
1512
+ }, 250);
808
1513
  }
809
1514
  }
810
1515
  function handleNewChat() {
811
1516
  setChatMessages([]);
812
1517
  service == null ? void 0 : service.resetSession();
813
1518
  }
814
- function onPopularItemsClick() {
815
- setInput(TRANSLATIONS.showPopularItems);
816
- handleSend();
817
- }
818
- function onCompareProductsClick() {
819
- setInput(TRANSLATIONS.compareProducts);
820
- handleSend();
821
- }
822
1519
  function onInputChange(event) {
823
1520
  setInput(event.target.value);
824
1521
  }
@@ -827,49 +1524,196 @@ function ShopPrompter(props) {
827
1524
  handleSend();
828
1525
  }
829
1526
  }
830
- function onHeaderButtonMouseEnter() {
831
- setIsHeaderButtonHovered(true);
1527
+ function handleTriggerClick(e) {
1528
+ if (props.chatPosition !== "dialog") return;
1529
+ if (!props.dialogTrigger) return;
1530
+ const isTargetClicked = typeof props.dialogTrigger === "string" ? e.target.closest(props.dialogTrigger) : (() => {
1531
+ let target = null;
1532
+ if (typeof props.dialogTrigger === "object") {
1533
+ if ("current" in props.dialogTrigger) {
1534
+ target = props.dialogTrigger.current;
1535
+ } else {
1536
+ target = props.dialogTrigger;
1537
+ }
1538
+ }
1539
+ return target && target.contains && target.contains(e.target);
1540
+ })();
1541
+ if (isTargetClicked) {
1542
+ if (closeTimeout) {
1543
+ clearTimeout(closeTimeout);
1544
+ setCloseTimeout(null);
1545
+ }
1546
+ setShowChat(true);
1547
+ setIsClosing(false);
1548
+ setAnimationClass("sh-dialog-animate");
1549
+ setBackdropAnimationClass("sh-backdrop-animate");
1550
+ setTimeout(() => {
1551
+ setAnimationClass("");
1552
+ setBackdropAnimationClass("");
1553
+ }, 250);
1554
+ }
832
1555
  }
833
- function onHeaderButtonMouseLeave() {
834
- setIsHeaderButtonHovered(false);
1556
+ function loadCustomFont(fontFamily) {
1557
+ if (!fontFamily || typeof window === "undefined") return;
1558
+ const systemFonts = [
1559
+ "sans-serif",
1560
+ "serif",
1561
+ "monospace",
1562
+ "cursive",
1563
+ "fantasy",
1564
+ "system-ui",
1565
+ "-apple-system",
1566
+ "blinkmacsystemfont",
1567
+ "segoe ui",
1568
+ "roboto",
1569
+ "helvetica",
1570
+ "arial",
1571
+ "inherit"
1572
+ ];
1573
+ const cleanFont = fontFamily.split(",")[0].trim().replace(new RegExp(`['"]`, "g"), "");
1574
+ if (!cleanFont || systemFonts.includes(cleanFont.toLowerCase())) return;
1575
+ const linkId = `shopprompter-font-${cleanFont.toLowerCase().replace(new RegExp("\\s+", "g"), "-")}`;
1576
+ if (document.getElementById(linkId)) return;
1577
+ const link = document.createElement("link");
1578
+ link.id = linkId;
1579
+ link.rel = "stylesheet";
1580
+ const fontNameUrl = cleanFont.replace(new RegExp("\\s+", "g"), "+");
1581
+ link.href = `https://fonts.googleapis.com/css2?family=${fontNameUrl}:wght@400;500;600;700&display=swap`;
1582
+ document.head.appendChild(link);
835
1583
  }
836
- function doSomethingAsync() {
1584
+ function loadAgentExperience() {
837
1585
  void (async function() {
838
- console.log("## ~ ShopPrompter ~ state.service:", service);
839
1586
  if (!service) {
840
- console.warn("Service not initialized yet");
1587
+ console.warn(
1588
+ "Service not initialized yet! Cannot load AgentExperience."
1589
+ );
841
1590
  return;
842
1591
  }
843
1592
  const response = await (service == null ? void 0 : service.getAgentExperience());
844
- console.log("## ~ ShopPrompter ~ response:", response);
845
1593
  setAgentExperience(response);
846
1594
  })();
847
1595
  }
848
- useEffect(() => {
849
- const shopPrompterService = new ShopPrompterService();
850
- setService(shopPrompterService);
1596
+ function handleFeedback(messageId, messageContent, newFeedback) {
1597
+ const msg = chatMessages.find((m) => m.id === messageId);
1598
+ if (!msg) return;
1599
+ const currentFeedback = msg.feedback;
1600
+ const targetFeedback = currentFeedback === newFeedback ? "clear" : newFeedback;
1601
+ const oldMessages = [...chatMessages];
1602
+ setChatMessages(
1603
+ chatMessages.map((m) => {
1604
+ if (m.id === messageId) {
1605
+ return {
1606
+ ...m,
1607
+ feedback: targetFeedback === "clear" ? null : targetFeedback
1608
+ };
1609
+ }
1610
+ return m;
1611
+ })
1612
+ );
1613
+ setError(null);
1614
+ service == null ? void 0 : service.sendFeedback(messageId, messageContent, targetFeedback).catch((err) => {
1615
+ setChatMessages(oldMessages);
1616
+ setError((err == null ? void 0 : err.message) || TRANSLATIONS.feedbackError);
1617
+ });
1618
+ }
1619
+ function canShowFeedback(message) {
1620
+ if (message.role !== "assistant") return false;
1621
+ if (!message.content) return false;
1622
+ const lastMsg = chatMessages[chatMessages.length - 1];
1623
+ if (lastMsg && lastMsg.id === message.id && isLoading) {
1624
+ return false;
1625
+ }
1626
+ return true;
1627
+ }
1628
+ useEffect2(() => {
1629
+ if (typeof window !== "undefined" && !document.getElementById("lottie-player-script")) {
1630
+ const script = document.createElement("script");
1631
+ script.id = "lottie-player-script";
1632
+ script.src = "https://unpkg.com/@lottiefiles/lottie-player@latest/dist/lottie-player";
1633
+ document.head.appendChild(script);
1634
+ }
1635
+ if (themeObj().fontFamily) {
1636
+ loadCustomFont(themeObj().fontFamily);
1637
+ }
1638
+ if (apiConfigObj()) {
1639
+ if (!isConfigInsufficient()) {
1640
+ const apiConfig = {
1641
+ ...apiConfigObj(),
1642
+ shopPrompterToken: props.shopPrompterToken || apiConfigObj().shopPrompterToken
1643
+ };
1644
+ const service2 = new ShopPrompterService(apiConfig);
1645
+ setService(service2);
1646
+ const savedMessages = service2.loadMessages();
1647
+ if (savedMessages.length > 0) {
1648
+ setChatMessages(savedMessages);
1649
+ }
1650
+ }
1651
+ } else {
1652
+ console.error("ShopPrompter: apiConfig prop is required!");
1653
+ }
1654
+ if ((props == null ? void 0 : props.chatPosition) === "right-panel" || (props == null ? void 0 : props.chatPosition) === "full-page") {
1655
+ setShowChat(true);
1656
+ }
1657
+ if (typeof window !== "undefined") {
1658
+ document.addEventListener("click", handleTriggerClick);
1659
+ }
851
1660
  }, []);
852
- useEffect(() => {
1661
+ useEffect2(() => {
853
1662
  if (service && !agentExperience) {
854
- doSomethingAsync();
855
- }
856
- if (agentExperience) {
857
- console.log("## ~ ShopPrompter ~ agentExperience updated:", {
858
- greeting: agentExperience.greeting,
859
- agentLogoUrl: agentExperience.agentLogoUrl
860
- });
1663
+ loadAgentExperience();
861
1664
  }
862
1665
  }, [service, agentExperience]);
863
- return /* @__PURE__ */ jsxs("div", { className: "shopprompter-sdk", children: [
864
- props.chatPosition === "classic-chatbot" ? /* @__PURE__ */ jsx(Fragment, { children: !showChat ? /* @__PURE__ */ jsx(
1666
+ useEffect2(() => {
1667
+ if (themeObj().fontFamily) {
1668
+ loadCustomFont(themeObj().fontFamily);
1669
+ }
1670
+ }, [themeObj().fontFamily || ""]);
1671
+ useEffect2(() => {
1672
+ if ((props == null ? void 0 : props.chatPosition) === "right-panel" || (props == null ? void 0 : props.chatPosition) === "full-page") {
1673
+ setShowChat(true);
1674
+ } else if ((props == null ? void 0 : props.chatPosition) === "dialog" || (props == null ? void 0 : props.chatPosition) === "classic-chatbot") {
1675
+ setShowChat(false);
1676
+ setIsClosing(false);
1677
+ setAnimationClass("");
1678
+ setBackdropAnimationClass("");
1679
+ }
1680
+ }, [(props == null ? void 0 : props.chatPosition) || ""]);
1681
+ return /* @__PURE__ */ jsxs4("div", { className: "shopprompter-sdk", children: [
1682
+ /* @__PURE__ */ jsx4("style", { dangerouslySetInnerHTML: { __html: ANIMATION_STYLES } }),
1683
+ /* @__PURE__ */ jsx4(
1684
+ "div",
1685
+ {
1686
+ onClick: (e) => toggleChat(),
1687
+ style: {
1688
+ ...styles2.backdrop,
1689
+ display: props.chatPosition === "dialog" && (showChat || isClosing) ? "block" : "none"
1690
+ },
1691
+ className: backdropAnimationClass
1692
+ }
1693
+ ),
1694
+ props.chatPosition === "classic-chatbot" ? /* @__PURE__ */ jsx4(Fragment2, { children: !showChat ? /* @__PURE__ */ jsx4(
865
1695
  "button",
866
1696
  {
867
- className: "fixed bottom-6 right-6 w-16 h-16 bg-blue-600 hover:bg-blue-700 rounded-full shadow-lg z-50 flex items-center justify-center transition-colors border-none cursor-pointer",
868
1697
  onClick: (e) => toggleChat(),
869
1698
  style: {
870
- boxShadow: "0 0 0 8px rgba(37, 99, 235, 0.2)"
1699
+ position: "fixed",
1700
+ bottom: "1.5rem",
1701
+ right: "1.5rem",
1702
+ width: "4rem",
1703
+ height: "4rem",
1704
+ backgroundColor: themeObj().actionColor || "#2563eb",
1705
+ borderRadius: "9999px",
1706
+ zIndex: 50,
1707
+ display: "flex",
1708
+ alignItems: "center",
1709
+ justifyContent: "center",
1710
+ transition: "background-color 0.2s",
1711
+ border: "none",
1712
+ cursor: "pointer",
1713
+ boxShadow: themeObj().actionColor ? `0 10px 15px -3px rgba(0, 0, 0, 0.1), 0 4px 6px -2px rgba(0, 0, 0, 0.05), 0 0 0 8px ${themeObj().actionColor}33` : "0 10px 15px -3px rgba(0, 0, 0, 0.1), 0 4px 6px -2px rgba(0, 0, 0, 0.05), 0 0 0 8px rgba(37, 99, 235, 0.2)",
1714
+ fontFamily: themeObj().fontFamily || void 0
871
1715
  },
872
- children: /* @__PURE__ */ jsx(
1716
+ children: /* @__PURE__ */ jsx4(
873
1717
  "img",
874
1718
  {
875
1719
  alt: "Chat",
@@ -882,259 +1726,404 @@ function ShopPrompter(props) {
882
1726
  )
883
1727
  }
884
1728
  ) : null }) : null,
885
- showChat ? /* @__PURE__ */ jsxs("div", { style: containerStyle(), className: containerClass(), children: [
886
- /* @__PURE__ */ jsxs("div", { style: styles.header, children: [
887
- /* @__PURE__ */ jsxs("div", { style: styles.subHeaderContainer, children: [
888
- /* @__PURE__ */ jsxs(
889
- "svg",
890
- {
891
- xmlns: "http://www.w3.org/2000/svg",
892
- viewBox: "0 0 46 47",
893
- width: "24",
894
- height: "24",
895
- fill: "none",
896
- children: [
897
- /* @__PURE__ */ jsx(
898
- "path",
899
- {
900
- fill: "url(#a)",
901
- d: "M16.452 32.747c-1.587 0-2.874-1.3-2.874-2.903V14.25h5.259V0H5.747C2.576 0 0 2.6 0 5.806v21.139c0 3.208 2.575 5.805 5.748 5.805h10.704v-.003Z"
902
- }
903
- ),
904
- /* @__PURE__ */ jsx(
905
- "path",
906
- {
907
- fill: "url(#b)",
908
- d: "M19.326 0c-3.173 0-5.748 2.6-5.748 5.806v8.444h15.438c1.586 0 2.874 1.3 2.874 2.902v3.924H46V0H19.326Z"
909
- }
910
- ),
911
- /* @__PURE__ */ jsx(
912
- "path",
913
- {
914
- fill: "url(#c)",
915
- d: "M40.252 14.25H29.016c1.586 0 2.874 1.3 2.874 2.902v15.595h-6.751V47h15.117c3.173 0 5.748-2.6 5.748-5.806V20.055c0-3.205-2.575-5.806-5.748-5.806h-.004Z"
1729
+ showChat || isClosing ? /* @__PURE__ */ jsxs4("div", { style: containerStyle(), className: containerClass(), children: [
1730
+ /* @__PURE__ */ jsxs4(
1731
+ "div",
1732
+ {
1733
+ style: {
1734
+ ...styles2.header,
1735
+ backgroundColor: themeObj().headerBackgroundColor || "transparent"
1736
+ },
1737
+ children: [
1738
+ themeObj().showAgentName !== false ? /* @__PURE__ */ jsxs4("div", { style: styles2.subHeaderContainer, children: [
1739
+ (agentExperience == null ? void 0 : agentExperience.agentLogoUrl) ? /* @__PURE__ */ jsx4(
1740
+ "img",
1741
+ {
1742
+ src: agentExperience.agentLogoUrl,
1743
+ alt: agentExperience.agentName,
1744
+ style: {
1745
+ width: "24px",
1746
+ height: "24px",
1747
+ borderRadius: "4px",
1748
+ objectFit: "cover"
916
1749
  }
917
- ),
918
- /* @__PURE__ */ jsx(
919
- "path",
920
- {
921
- fill: "url(#d)",
922
- d: "M8.669 32.75H5.751c-3.173 0-5.747-2.6-5.747-5.805V47h26.142c3.172 0 5.747-2.6 5.747-5.806V32.75H8.67Z"
923
- }
924
- ),
925
- /* @__PURE__ */ jsxs("defs", { children: [
926
- /* @__PURE__ */ jsxs(
927
- "linearGradient",
928
- {
929
- id: "a",
930
- x1: "14.3",
931
- x2: "3.322",
932
- y1: "22.494",
933
- y2: "4.382",
934
- gradientUnits: "userSpaceOnUse",
935
- children: [
936
- /* @__PURE__ */ jsx("stop", { stopColor: "#B0145C" }),
937
- /* @__PURE__ */ jsx("stop", { offset: ".37", stopColor: "#AE2E9A" }),
938
- /* @__PURE__ */ jsx("stop", { offset: "1", stopColor: "#AD59FF" })
939
- ]
940
- }
941
- ),
942
- /* @__PURE__ */ jsxs(
943
- "linearGradient",
944
- {
945
- id: "b",
946
- x1: "21.156",
947
- x2: "40.431",
948
- y1: "21.216",
949
- y2: "1.624",
950
- gradientUnits: "userSpaceOnUse",
951
- children: [
952
- /* @__PURE__ */ jsx("stop", { offset: ".08", stopColor: "#E7A2FF" }),
953
- /* @__PURE__ */ jsx("stop", { offset: ".37", stopColor: "#E983CD" }),
954
- /* @__PURE__ */ jsx("stop", { offset: ".99", stopColor: "#F03A58" })
955
- ]
956
- }
957
- ),
958
- /* @__PURE__ */ jsxs(
959
- "linearGradient",
960
- {
961
- id: "c",
962
- x1: "30.464",
963
- x2: "46.567",
964
- y1: "27.405",
965
- y2: "42.472",
966
- gradientUnits: "userSpaceOnUse",
967
- children: [
968
- /* @__PURE__ */ jsx("stop", { stopColor: "#B0145C" }),
969
- /* @__PURE__ */ jsx("stop", { offset: ".02", stopColor: "#B11861" }),
970
- /* @__PURE__ */ jsx("stop", { offset: ".27", stopColor: "#C44999" }),
971
- /* @__PURE__ */ jsx("stop", { offset: ".5", stopColor: "#D36FC5" }),
972
- /* @__PURE__ */ jsx("stop", { offset: ".71", stopColor: "#DE8BE4" }),
973
- /* @__PURE__ */ jsx("stop", { offset: ".88", stopColor: "#E49BF8" }),
974
- /* @__PURE__ */ jsx("stop", { offset: "1", stopColor: "#E7A2FF" })
975
- ]
976
- }
977
- ),
978
- /* @__PURE__ */ jsxs(
979
- "linearGradient",
1750
+ }
1751
+ ) : null,
1752
+ (agentExperience == null ? void 0 : agentExperience.agentName) ? /* @__PURE__ */ jsx4("span", { style: styles2.headerText, children: agentExperience.agentName }) : null
1753
+ ] }) : /* @__PURE__ */ jsx4(Fragment2, { children: /* @__PURE__ */ jsx4("div", { style: styles2.subHeaderContainer }) }),
1754
+ !hasToken() && ((_a = apiConfigObj == null ? void 0 : apiConfigObj()) == null ? void 0 : _a.apiKey) ? /* @__PURE__ */ jsx4("div", { style: styles2.warningBanner, children: "API Key is only for development purposes" }) : null,
1755
+ /* @__PURE__ */ jsxs4("div", { style: styles2.subHeaderContainer, children: [
1756
+ /* @__PURE__ */ jsx4(
1757
+ "button",
1758
+ {
1759
+ className: "sh-header-btn",
1760
+ onClick: (e) => handleNewChat(),
1761
+ style: styles2.headerButton,
1762
+ children: TRANSLATIONS.newChat
1763
+ }
1764
+ ),
1765
+ props.chatPosition === "classic-chatbot" || props.chatPosition === "right-panel" || props.chatPosition === "dialog" ? /* @__PURE__ */ jsx4(
1766
+ "button",
1767
+ {
1768
+ onClick: (e) => toggleChat(),
1769
+ style: styles2.ButtonSheetButton,
1770
+ children: "\xD7"
1771
+ }
1772
+ ) : null
1773
+ ] })
1774
+ ]
1775
+ }
1776
+ ),
1777
+ isConfigInsufficient() ? /* @__PURE__ */ jsxs4("div", { style: styles2.insufficientConfigContainer, children: [
1778
+ /* @__PURE__ */ jsx4("div", { style: styles2.insufficientConfigIconContainer, children: /* @__PURE__ */ jsxs4(
1779
+ "svg",
1780
+ {
1781
+ width: "48",
1782
+ height: "48",
1783
+ viewBox: "0 0 24 24",
1784
+ fill: "none",
1785
+ stroke: "currentColor",
1786
+ strokeWidth: "2",
1787
+ strokeLinecap: "round",
1788
+ strokeLinejoin: "round",
1789
+ style: {
1790
+ color: "#ef4444"
1791
+ },
1792
+ children: [
1793
+ /* @__PURE__ */ jsx4("rect", { x: "3", y: "11", width: "18", height: "11", rx: "2", ry: "2" }),
1794
+ /* @__PURE__ */ jsx4("path", { d: "M7 11V7a5 5 0 0 1 9.9-1" })
1795
+ ]
1796
+ }
1797
+ ) }),
1798
+ /* @__PURE__ */ jsx4(
1799
+ "h3",
1800
+ {
1801
+ style: {
1802
+ ...styles2.insufficientConfigTitle,
1803
+ fontFamily: themeObj().fontFamily || void 0
1804
+ },
1805
+ children: "Configuration Error"
1806
+ }
1807
+ ),
1808
+ /* @__PURE__ */ jsx4(
1809
+ "p",
1810
+ {
1811
+ style: {
1812
+ ...styles2.insufficientConfigMessage,
1813
+ fontFamily: themeObj().fontFamily || void 0
1814
+ },
1815
+ children: "ShopPrompter requires a secure token or API key to initialize. Please check your setup."
1816
+ }
1817
+ ),
1818
+ /* @__PURE__ */ jsxs4(
1819
+ "div",
1820
+ {
1821
+ style: {
1822
+ ...styles2.insufficientConfigDetails,
1823
+ fontFamily: themeObj().fontFamily || void 0
1824
+ },
1825
+ children: [
1826
+ /* @__PURE__ */ jsx4(
1827
+ "div",
1828
+ {
1829
+ style: {
1830
+ fontWeight: 600,
1831
+ marginBottom: "0.25rem"
1832
+ },
1833
+ children: "Missing Parameters:"
1834
+ }
1835
+ ),
1836
+ /* @__PURE__ */ jsxs4(
1837
+ "div",
1838
+ {
1839
+ style: {
1840
+ display: "flex",
1841
+ flexDirection: "column",
1842
+ gap: "0.25rem",
1843
+ fontFamily: "monospace",
1844
+ fontSize: "0.75rem"
1845
+ },
1846
+ children: [
1847
+ /* @__PURE__ */ jsx4(
1848
+ "span",
1849
+ {
1850
+ style: {
1851
+ color: "#ef4444"
1852
+ },
1853
+ children: "\u2717 shopPrompterToken (not found)"
1854
+ }
1855
+ ),
1856
+ /* @__PURE__ */ jsx4(
1857
+ "span",
1858
+ {
1859
+ style: {
1860
+ color: "#ef4444"
1861
+ },
1862
+ children: "\u2717 apiConfig.apiKey (not found)"
1863
+ }
1864
+ )
1865
+ ]
1866
+ }
1867
+ )
1868
+ ]
1869
+ }
1870
+ )
1871
+ ] }) : null,
1872
+ !isConfigInsufficient() ? /* @__PURE__ */ jsxs4(
1873
+ "div",
1874
+ {
1875
+ style: {
1876
+ display: "flex",
1877
+ flexDirection: "column",
1878
+ flex: 1,
1879
+ overflow: "hidden"
1880
+ },
1881
+ children: [
1882
+ /* @__PURE__ */ jsxs4(
1883
+ "div",
1884
+ {
1885
+ id: "shop-prompter-chat-container",
1886
+ style: {
1887
+ ...styles2.chatContainer,
1888
+ backgroundColor: themeObj().mainBackgroundColor || styles2.chatContainer.backgroundColor
1889
+ },
1890
+ children: [
1891
+ showWelcome() ? /* @__PURE__ */ jsxs4("div", { style: styles2.welcomeContainer, children: [
1892
+ /* @__PURE__ */ jsx4(
1893
+ "img",
1894
+ {
1895
+ alt: "ShopPrompter",
1896
+ src: (agentExperience == null ? void 0 : agentExperience.agentLogoUrl) ? agentExperience.agentLogoUrl : ICONS.shopprompter,
1897
+ style: {
1898
+ width: "64px",
1899
+ height: "64px",
1900
+ marginBottom: "24px",
1901
+ borderRadius: "12px",
1902
+ objectFit: "cover"
1903
+ }
1904
+ }
1905
+ ),
1906
+ /* @__PURE__ */ jsx4(
1907
+ "h3",
1908
+ {
1909
+ style: {
1910
+ ...styles2.welcomeTitle,
1911
+ fontFamily: themeObj().fontFamily || styles2.welcomeTitle.fontFamily
1912
+ },
1913
+ children: ((_b = agentExperience == null ? void 0 : agentExperience.greeting) == null ? void 0 : _b.title) || TRANSLATIONS.welcomeToShopPrompter
1914
+ }
1915
+ ),
1916
+ /* @__PURE__ */ jsx4(
1917
+ "p",
1918
+ {
1919
+ style: {
1920
+ ...styles2.welcomeDescription,
1921
+ fontFamily: themeObj().fontFamily || styles2.welcomeDescription.fontFamily
1922
+ },
1923
+ children: ((_c = agentExperience == null ? void 0 : agentExperience.greeting) == null ? void 0 : _c.description) || TRANSLATIONS.welcomeDescription
1924
+ }
1925
+ ),
1926
+ /* @__PURE__ */ jsx4("div", { style: styles2.buttonContainer, children: (_d = prompts()) == null ? void 0 : _d.map((item) => /* @__PURE__ */ jsx4(
1927
+ "button",
1928
+ {
1929
+ style: styles2.button,
1930
+ onClick: (event) => {
1931
+ setInput(item.prompt);
1932
+ handleSend(item.prompt);
1933
+ },
1934
+ children: item.prompt
1935
+ },
1936
+ item.prompt
1937
+ )) })
1938
+ ] }) : null,
1939
+ !showWelcome() ? /* @__PURE__ */ jsx4(
1940
+ "div",
980
1941
  {
981
- id: "d",
982
- x1: "23.356",
983
- x2: "-.618",
984
- y1: "44.082",
985
- y2: "30.739",
986
- gradientUnits: "userSpaceOnUse",
987
- children: [
988
- /* @__PURE__ */ jsx("stop", { stopColor: "#AD59FF" }),
989
- /* @__PURE__ */ jsx("stop", { offset: ".1", stopColor: "#B455EB" }),
990
- /* @__PURE__ */ jsx("stop", { offset: ".54", stopColor: "#D4469C" }),
991
- /* @__PURE__ */ jsx("stop", { offset: ".85", stopColor: "#E83D6B" }),
992
- /* @__PURE__ */ jsx("stop", { offset: "1", stopColor: "#F03A58" })
993
- ]
1942
+ style: {
1943
+ width: "100%"
1944
+ },
1945
+ children: chatMessages == null ? void 0 : chatMessages.map((message) => /* @__PURE__ */ jsxs4("div", { children: [
1946
+ message.role === "user" ? /* @__PURE__ */ jsx4("div", { style: styles2.messageContainerUser, children: /* @__PURE__ */ jsx4(
1947
+ "div",
1948
+ {
1949
+ style: {
1950
+ ...styles2.messageBubbleUser,
1951
+ backgroundColor: themeObj().userMessageBackgroundColor || styles2.messageBubbleUser.backgroundColor
1952
+ },
1953
+ children: message.content
1954
+ }
1955
+ ) }) : null,
1956
+ message.role === "assistant" ? /* @__PURE__ */ jsxs4("div", { style: styles2.messageContainerAssistant, children: [
1957
+ /* @__PURE__ */ jsxs4(
1958
+ "div",
1959
+ {
1960
+ style: {
1961
+ ...styles2.messageBubbleAssistant,
1962
+ backgroundColor: themeObj().assistantMessageBackgroundColor || styles2.messageBubbleAssistant.backgroundColor
1963
+ },
1964
+ children: [
1965
+ /* @__PURE__ */ jsx4(
1966
+ "div",
1967
+ {
1968
+ dangerouslySetInnerHTML: {
1969
+ __html: parseMarkdown(message.content)
1970
+ }
1971
+ }
1972
+ ),
1973
+ !message.content && isLoading ? /* @__PURE__ */ jsx4(Fragment2, { children: (agentExperience == null ? void 0 : agentExperience.loadingIndicatorUrl) ? /* @__PURE__ */ jsx4(
1974
+ "lottie-player",
1975
+ {
1976
+ background: "transparent",
1977
+ speed: "1",
1978
+ src: agentExperience.loadingIndicatorUrl,
1979
+ style: {
1980
+ width: "40px",
1981
+ height: "40px"
1982
+ },
1983
+ loop: true,
1984
+ autoplay: true
1985
+ }
1986
+ ) : /* @__PURE__ */ jsx4("div", { style: styles2.thinkingIndicator, children: /* @__PURE__ */ jsxs4(
1987
+ "svg",
1988
+ {
1989
+ width: "24",
1990
+ height: "24",
1991
+ viewBox: "0 0 24 24",
1992
+ fill: "none",
1993
+ stroke: "currentColor",
1994
+ strokeWidth: "2",
1995
+ strokeLinecap: "round",
1996
+ strokeLinejoin: "round",
1997
+ style: {
1998
+ color: "#6b7280"
1999
+ },
2000
+ children: [
2001
+ /* @__PURE__ */ jsx4("path", { d: THINKING_SPINNER }),
2002
+ /* @__PURE__ */ jsx4(
2003
+ "animateTransform",
2004
+ {
2005
+ attributeName: "transform",
2006
+ type: "rotate",
2007
+ from: "0 12 12",
2008
+ to: "360 12 12",
2009
+ dur: "1s",
2010
+ repeatCount: "indefinite"
2011
+ }
2012
+ )
2013
+ ]
2014
+ }
2015
+ ) }) }) : null
2016
+ ]
2017
+ }
2018
+ ),
2019
+ canShowFeedback(message) ? /* @__PURE__ */ jsxs4("div", { style: styles2.feedbackRow, children: [
2020
+ /* @__PURE__ */ jsx4(
2021
+ "button",
2022
+ {
2023
+ className: "sh-feedback-btn",
2024
+ onClick: (event) => handleFeedback(
2025
+ message.id,
2026
+ message.content,
2027
+ "upvote"
2028
+ ),
2029
+ style: styles2.feedbackButton,
2030
+ children: /* @__PURE__ */ jsx4(
2031
+ thumbs_up_icon_component_default,
2032
+ {
2033
+ fill: message.feedback === "upvote" ? themeObj().actionColor || "#2563eb" : "none",
2034
+ stroke: message.feedback === "upvote" ? themeObj().actionColor || "#2563eb" : "currentColor"
2035
+ }
2036
+ )
2037
+ }
2038
+ ),
2039
+ /* @__PURE__ */ jsx4(
2040
+ "button",
2041
+ {
2042
+ className: "sh-feedback-btn",
2043
+ onClick: (event) => handleFeedback(
2044
+ message.id,
2045
+ message.content,
2046
+ "downvote"
2047
+ ),
2048
+ style: styles2.feedbackButton,
2049
+ children: /* @__PURE__ */ jsx4(
2050
+ thumbs_down_icon_component_default,
2051
+ {
2052
+ fill: message.feedback === "downvote" ? themeObj().actionColor || "#2563eb" : "none",
2053
+ stroke: message.feedback === "downvote" ? themeObj().actionColor || "#2563eb" : "currentColor"
2054
+ }
2055
+ )
2056
+ }
2057
+ )
2058
+ ] }) : null,
2059
+ getShowProducts(message) ? /* @__PURE__ */ jsx4(
2060
+ product_card_list_component_default,
2061
+ {
2062
+ skus: message.productSkus,
2063
+ defaultLocale: props.defaultLocale
2064
+ }
2065
+ ) : null
2066
+ ] }) : null
2067
+ ] }, message.id))
994
2068
  }
995
- )
996
- ] })
997
- ]
998
- }
999
- ),
1000
- /* @__PURE__ */ jsx("span", { style: styles.headerText, children: "ShopPrompter\xAE" })
1001
- ] }),
1002
- /* @__PURE__ */ jsxs("div", { style: styles.subHeaderContainer, children: [
1003
- /* @__PURE__ */ jsx(
1004
- "button",
1005
- {
1006
- onClick: (e) => handleNewChat(),
1007
- onMouseEnter: (e) => onHeaderButtonMouseEnter(),
1008
- onMouseLeave: (e) => onHeaderButtonMouseLeave(),
1009
- style: {
1010
- ...styles.headerButton,
1011
- ...isHeaderButtonHovered ? styles.headerButton.onHover : {}
1012
- },
1013
- children: TRANSLATIONS.newChat
1014
- }
1015
- ),
1016
- props.chatPosition === "classic-chatbot" || props.chatPosition === "right-panel" || props.chatPosition === "bottom-sheet" ? /* @__PURE__ */ jsx(
1017
- "button",
1018
- {
1019
- onClick: (e) => toggleChat(),
1020
- style: styles.ButtonSheetButton,
1021
- children: "\xD7"
1022
- }
1023
- ) : null
1024
- ] })
1025
- ] }),
1026
- /* @__PURE__ */ jsxs("div", { style: styles.chatContainer, children: [
1027
- showWelcome() ? /* @__PURE__ */ jsxs("div", { style: styles.welcomeContainer, children: [
1028
- /* @__PURE__ */ jsx(
1029
- "img",
1030
- {
1031
- alt: "ShopPrompter",
1032
- src: (agentExperience == null ? void 0 : agentExperience.agentLogoUrl) ? agentExperience.agentLogoUrl : ICONS.shopprompter,
1033
- style: {
1034
- width: "64px",
1035
- height: "64px",
1036
- marginBottom: "24px"
1037
- }
1038
- }
1039
- ),
1040
- /* @__PURE__ */ jsx("h3", { style: styles.welcomeTitle, children: ((_a = agentExperience == null ? void 0 : agentExperience.greeting) == null ? void 0 : _a.title) || TRANSLATIONS.welcomeToShopPrompter }),
1041
- /* @__PURE__ */ jsx("p", { style: styles.welcomeDescription, children: ((_b = agentExperience == null ? void 0 : agentExperience.greeting) == null ? void 0 : _b.description) || TRANSLATIONS.welcomeDescription }),
1042
- /* @__PURE__ */ jsxs("div", { style: styles.buttonContainer, children: [
1043
- /* @__PURE__ */ jsx(
1044
- "button",
1045
- {
1046
- style: styles.button,
1047
- onClick: (e) => onPopularItemsClick(),
1048
- children: TRANSLATIONS.showPopularItems
2069
+ ) : null,
2070
+ error ? /* @__PURE__ */ jsxs4("div", { style: styles2.errorContainer, children: [
2071
+ "Error: ",
2072
+ error
2073
+ ] }) : null
2074
+ ]
1049
2075
  }
1050
2076
  ),
1051
- /* @__PURE__ */ jsx(
1052
- "button",
2077
+ /* @__PURE__ */ jsxs4(
2078
+ "div",
1053
2079
  {
1054
- style: styles.button,
1055
- onClick: (e) => onCompareProductsClick(),
1056
- children: TRANSLATIONS.compareProducts
1057
- }
1058
- )
1059
- ] })
1060
- ] }) : /* @__PURE__ */ jsx(Fragment, { children: (_c = messages()) == null ? void 0 : _c.map((message) => {
1061
- var _a2;
1062
- return /* @__PURE__ */ jsxs(
1063
- "div",
1064
- {
1065
- style: message.role === "user" ? styles.messageContainerUser : styles.messageContainerAssistant,
1066
- children: [
1067
- /* @__PURE__ */ jsxs(
1068
- "div",
1069
- {
1070
- style: message.role === "user" ? styles.messageBubbleUser : styles.messageBubbleAssistant,
1071
- children: [
1072
- message.content,
1073
- !message.content ? /* @__PURE__ */ jsx(Fragment, { children: message.role === "assistant" ? /* @__PURE__ */ jsx(Fragment, { children: isLoading ? /* @__PURE__ */ jsx("div", { style: styles.thinkingIndicator, children: TRANSLATIONS.thinking }) : null }) : null }) : null
1074
- ]
1075
- }
1076
- ),
1077
- message.role === "assistant" ? /* @__PURE__ */ jsx("div", { style: styles.productCardsContainer, children: (_a2 = message.safeProductSkus) == null ? void 0 : _a2.map((sku) => /* @__PURE__ */ jsxs("div", { style: styles.productCard, children: [
1078
- /* @__PURE__ */ jsx("div", { style: styles.productImageContainer, children: /* @__PURE__ */ jsx(
1079
- "img",
1080
- {
1081
- src: getProductImageUrl(sku),
1082
- alt: sku,
1083
- style: {
1084
- maxHeight: "100%",
1085
- maxWidth: "100%"
2080
+ style: {
2081
+ ...styles2.inputSection,
2082
+ backgroundColor: themeObj().mainBackgroundColor || styles2.inputSection.backgroundColor
2083
+ },
2084
+ children: [
2085
+ /* @__PURE__ */ jsxs4("div", { style: styles2.inputWrapper, children: [
2086
+ /* @__PURE__ */ jsx4(
2087
+ "input",
2088
+ {
2089
+ id: "shop-prompter-input",
2090
+ type: "text",
2091
+ style: styles2.input,
2092
+ placeholder: (agentExperience == null ? void 0 : agentExperience.hintText) || TRANSLATIONS.askMeAnything,
2093
+ value: input,
2094
+ onInput: (e) => onInputChange(e),
2095
+ onKeyDown: (e) => onInputKeyDown(e)
1086
2096
  }
1087
- }
1088
- ) }),
1089
- /* @__PURE__ */ jsxs("div", { style: styles.productInfo, children: [
1090
- /* @__PURE__ */ jsx("p", { style: styles.productSku, children: sku }),
1091
- /* @__PURE__ */ jsx(
1092
- "a",
2097
+ ),
2098
+ /* @__PURE__ */ jsx4(
2099
+ "button",
1093
2100
  {
1094
- href: getProductLink(sku),
1095
- style: styles.productLink,
1096
- children: "VIEW DETAILS"
2101
+ onClick: (e) => handleSend(),
2102
+ style: {
2103
+ ...styles2.formButton,
2104
+ ...styles2.sendButton,
2105
+ backgroundColor: themeObj().actionColor || styles2.sendButton.backgroundColor
2106
+ },
2107
+ children: /* @__PURE__ */ jsx4(
2108
+ "img",
2109
+ {
2110
+ alt: "Send",
2111
+ src: ICONS.sendHorizontal,
2112
+ style: {
2113
+ padding: "4px"
2114
+ }
2115
+ }
2116
+ )
1097
2117
  }
1098
2118
  )
1099
- ] })
1100
- ] }, sku)) }) : null
1101
- ]
1102
- },
1103
- message.id
1104
- );
1105
- }) }),
1106
- error ? /* @__PURE__ */ jsxs("div", { style: styles.errorContainer, children: [
1107
- "Error: ",
1108
- error
1109
- ] }) : null
1110
- ] }),
1111
- /* @__PURE__ */ jsxs("div", { style: styles.inputSection, children: [
1112
- /* @__PURE__ */ jsxs("div", { style: styles.inputWrapper, children: [
1113
- /* @__PURE__ */ jsx(
1114
- "input",
1115
- {
1116
- type: "text",
1117
- style: styles.input,
1118
- placeholder: TRANSLATIONS.askMeAnything,
1119
- value: input,
1120
- onInput: (e) => onInputChange(e),
1121
- onKeyDown: (e) => onInputKeyDown(e)
1122
- }
1123
- ),
1124
- /* @__PURE__ */ jsx(
1125
- "button",
1126
- {
1127
- onClick: (e) => handleSend(),
1128
- style: {
1129
- ...styles.formButton,
1130
- ...styles.sendButton
1131
- },
1132
- children: /* @__PURE__ */ jsx("img", { alt: "Send", src: ICONS.sendHorizontal })
1133
- }
1134
- )
1135
- ] }),
1136
- /* @__PURE__ */ jsx("p", { style: styles.disclaimer, children: "AI content may be inaccurate." })
1137
- ] })
2119
+ ] }),
2120
+ /* @__PURE__ */ jsx4("p", { style: styles2.disclaimer, children: "AI content may be inaccurate." })
2121
+ ]
2122
+ }
2123
+ )
2124
+ ]
2125
+ }
2126
+ ) : null
1138
2127
  ] }) : null
1139
2128
  ] });
1140
2129
  }