@shop-prompter/react 0.1.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.js ADDED
@@ -0,0 +1,1181 @@
1
+ "use strict";
2
+ var __create = Object.create;
3
+ var __defProp = Object.defineProperty;
4
+ var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
5
+ var __getOwnPropNames = Object.getOwnPropertyNames;
6
+ var __getProtoOf = Object.getPrototypeOf;
7
+ var __hasOwnProp = Object.prototype.hasOwnProperty;
8
+ var __export = (target, all) => {
9
+ for (var name in all)
10
+ __defProp(target, name, { get: all[name], enumerable: true });
11
+ };
12
+ var __copyProps = (to, from, except, desc) => {
13
+ if (from && typeof from === "object" || typeof from === "function") {
14
+ for (let key of __getOwnPropNames(from))
15
+ if (!__hasOwnProp.call(to, key) && key !== except)
16
+ __defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
17
+ }
18
+ return to;
19
+ };
20
+ var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__getProtoOf(mod)) : {}, __copyProps(
21
+ // If the importer is in node compatibility mode or this is not an ESM
22
+ // file that has been converted to a CommonJS file using a Babel-
23
+ // compatible transform (i.e. "__esModule" has not been set), then set
24
+ // "default" to the CommonJS "module.exports" for node compatibility.
25
+ isNodeMode || !mod || !mod.__esModule ? __defProp(target, "default", { value: mod, enumerable: true }) : target,
26
+ mod
27
+ ));
28
+ var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
29
+
30
+ // src/index.ts
31
+ var index_exports = {};
32
+ __export(index_exports, {
33
+ ShopPrompter: () => shop_prompter_component_default
34
+ });
35
+ module.exports = __toCommonJS(index_exports);
36
+
37
+ // src/shop-prompter.component.jsx
38
+ var React = __toESM(require("react"));
39
+ var import_react = require("react");
40
+
41
+ // src/api/shop-prompter-api.ts
42
+ var DefaultShopPrompterApi = class {
43
+ constructor() {
44
+ this.config = null;
45
+ }
46
+ setApiConfig(config) {
47
+ this.config = config;
48
+ }
49
+ async execute(prompt, userId, sessionId) {
50
+ if (!this.config) {
51
+ throw new Error("API configuration not set. Call setApiConfig first.");
52
+ }
53
+ const response = await fetch(`${this.config.baseUrl}/interaction`, {
54
+ method: "POST",
55
+ headers: {
56
+ "Content-Type": "application/json",
57
+ "X-Api-Key": this.config.apiKey
58
+ },
59
+ body: JSON.stringify({
60
+ prompt,
61
+ userId,
62
+ sessionId
63
+ })
64
+ });
65
+ if (!response.ok) {
66
+ throw new Error(`API error: ${response.status}`);
67
+ }
68
+ return response.json();
69
+ }
70
+ async executeStream(prompt, userId, sessionId, onEvent, cartContext) {
71
+ var _a;
72
+ if (!this.config) {
73
+ throw new Error("API configuration not set. Call setApiConfig first.");
74
+ }
75
+ const url = `${this.config.baseUrl}/interaction/stream`;
76
+ console.log("ShopPrompter Request:", {
77
+ url,
78
+ prompt,
79
+ userId,
80
+ sessionId,
81
+ cartContext
82
+ });
83
+ let response;
84
+ try {
85
+ response = await fetch(url, {
86
+ method: "POST",
87
+ headers: {
88
+ "Content-Type": "application/json",
89
+ "X-Api-Key": this.config.apiKey,
90
+ Accept: "text/event-stream",
91
+ "Cache-Control": "no-cache"
92
+ },
93
+ body: JSON.stringify({
94
+ prompt,
95
+ userId,
96
+ sessionId,
97
+ cart: cartContext
98
+ })
99
+ });
100
+ } catch (fetchError) {
101
+ console.error("ShopPrompter Fetch Error:", fetchError);
102
+ onEvent({
103
+ type: "error",
104
+ reason: `Failed to fetch: ${fetchError instanceof Error ? fetchError.message : "Network error"}`
105
+ });
106
+ return;
107
+ }
108
+ console.log("ShopPrompter Response:", response.status);
109
+ if (!response.ok) {
110
+ const errorText = await response.text().catch(() => "");
111
+ console.error("ShopPrompter API Error:", response.status, errorText);
112
+ onEvent({
113
+ type: "error",
114
+ reason: `API error: ${response.status} - ${errorText}`
115
+ });
116
+ return;
117
+ }
118
+ const reader = (_a = response.body) == null ? void 0 : _a.getReader();
119
+ if (!reader) {
120
+ onEvent({ type: "error", reason: "No response body" });
121
+ return;
122
+ }
123
+ const decoder = new TextDecoder();
124
+ let buffer = "";
125
+ try {
126
+ while (true) {
127
+ const { done, value } = await reader.read();
128
+ if (done) {
129
+ console.log("ShopPrompter Stream done");
130
+ onEvent({ type: "close" });
131
+ break;
132
+ }
133
+ const chunk = decoder.decode(value, { stream: true });
134
+ console.log("ShopPrompter Raw chunk:", chunk);
135
+ buffer += chunk;
136
+ const lines = buffer.split("\n");
137
+ buffer = lines.pop() || "";
138
+ let currentEventType = "";
139
+ for (const line of lines) {
140
+ console.log("ShopPrompter Line:", line);
141
+ if (line.startsWith("event:")) {
142
+ currentEventType = line.slice(6).trim();
143
+ console.log("ShopPrompter Event type:", currentEventType);
144
+ if (currentEventType === "error") {
145
+ onEvent({
146
+ type: "error",
147
+ reason: "Server returned an error event. Check backend configuration."
148
+ });
149
+ }
150
+ } else if (line.startsWith("data:")) {
151
+ const data = line.slice(5).trim();
152
+ console.log("ShopPrompter Data:", data);
153
+ if (data) {
154
+ if (currentEventType === "error") {
155
+ try {
156
+ const errorData = JSON.parse(data);
157
+ onEvent({
158
+ type: "error",
159
+ reason: errorData.message || errorData.error || "Unknown server error"
160
+ });
161
+ } catch {
162
+ onEvent({
163
+ type: "error",
164
+ reason: data || "Unknown server error"
165
+ });
166
+ }
167
+ } else {
168
+ const event = this.parseEvent(data);
169
+ console.log("ShopPrompter Parsed event:", event);
170
+ if (event) {
171
+ onEvent(event);
172
+ }
173
+ }
174
+ }
175
+ currentEventType = "";
176
+ }
177
+ }
178
+ }
179
+ } catch (error) {
180
+ console.error("ShopPrompter Stream error:", error);
181
+ onEvent({
182
+ type: "error",
183
+ reason: error instanceof Error ? error.message : "Unknown error"
184
+ });
185
+ }
186
+ }
187
+ async getAgentExperience() {
188
+ if (!this.config) {
189
+ console.warn("API configuration not set. Call setApiConfig first.");
190
+ return null;
191
+ }
192
+ try {
193
+ const response = await fetch(`${this.config.baseUrl}/agent-experience`, {
194
+ method: "GET",
195
+ headers: {
196
+ "Content-Type": "application/json",
197
+ "X-Api-Key": this.config.apiKey
198
+ }
199
+ });
200
+ if (!response.ok) {
201
+ console.error(`Failed to fetch agent experience: ${response.status}`);
202
+ return null;
203
+ }
204
+ const data = await response.json();
205
+ console.log(
206
+ "## ~ DefaultShopPrompterApi ~ getAgentExperience ~ data:",
207
+ data
208
+ );
209
+ return data;
210
+ } catch (error) {
211
+ console.error("Error fetching agent experience:", error);
212
+ return null;
213
+ }
214
+ }
215
+ parseEvent(data) {
216
+ try {
217
+ const json = JSON.parse(data);
218
+ if (json.token !== void 0) {
219
+ if (json.token === "close") {
220
+ return { type: "close" };
221
+ }
222
+ return {
223
+ type: "text",
224
+ text: json.token
225
+ };
226
+ }
227
+ if (json.text !== void 0) {
228
+ return {
229
+ type: "text",
230
+ text: json.text
231
+ };
232
+ }
233
+ if (json.skus !== void 0) {
234
+ return {
235
+ type: "productSkus",
236
+ skus: json.skus
237
+ };
238
+ }
239
+ if (json.products !== void 0 && Array.isArray(json.products)) {
240
+ const skus = json.products.map((p) => p.sku).filter(Boolean);
241
+ if (skus.length > 0) {
242
+ return {
243
+ type: "productSkus",
244
+ skus
245
+ };
246
+ }
247
+ }
248
+ if (json.productSkus !== void 0) {
249
+ return {
250
+ type: "productSkus",
251
+ skus: json.productSkus
252
+ };
253
+ }
254
+ if (json.output !== void 0 && Array.isArray(json.output)) {
255
+ for (const item of json.output) {
256
+ if (item.type === "product" && item.data && Array.isArray(item.data)) {
257
+ const skus = item.data.filter((p) => p !== null).map((p) => typeof p === "string" ? p : p == null ? void 0 : p.sku).filter(Boolean);
258
+ if (skus.length > 0) {
259
+ return {
260
+ type: "productSkus",
261
+ skus
262
+ };
263
+ }
264
+ }
265
+ if (item.type === "product" && item.skus && Array.isArray(item.skus)) {
266
+ return {
267
+ type: "productSkus",
268
+ skus: item.skus
269
+ };
270
+ }
271
+ }
272
+ }
273
+ if (json.navigation !== void 0) {
274
+ return {
275
+ type: "navigation",
276
+ navigationOperations: json.navigation.map((nav) => ({
277
+ name: nav.name,
278
+ route: nav.path || nav.route,
279
+ description: nav.description
280
+ }))
281
+ };
282
+ }
283
+ if (json.cart !== void 0) {
284
+ return {
285
+ type: "cart",
286
+ operations: json.cart.map((op) => ({
287
+ sku: op.sku,
288
+ action: op.action,
289
+ quantity: op.quantity || 1
290
+ }))
291
+ };
292
+ }
293
+ if (json.output !== void 0 && Array.isArray(json.output)) {
294
+ for (const item of json.output) {
295
+ if (item.type === "cart" && item.data) {
296
+ return {
297
+ type: "cart",
298
+ operations: (Array.isArray(item.data) ? item.data : [item.data]).map((op) => ({
299
+ sku: op.sku,
300
+ action: op.action || "add",
301
+ quantity: op.quantity || 1
302
+ }))
303
+ };
304
+ }
305
+ }
306
+ }
307
+ if (json.close !== void 0 || json.type === "close") {
308
+ return { type: "close" };
309
+ }
310
+ return null;
311
+ } catch {
312
+ if (data && typeof data === "string") {
313
+ return {
314
+ type: "text",
315
+ text: data
316
+ };
317
+ }
318
+ return null;
319
+ }
320
+ }
321
+ };
322
+ var shopPrompterApi = new DefaultShopPrompterApi();
323
+
324
+ // src/api/session-handler.ts
325
+ var import_uuid = require("uuid");
326
+ var SESSION_KEY = "shopprompter_sessionId";
327
+ var USER_KEY = "shopprompter_userId";
328
+ var DefaultSessionHandler = class {
329
+ constructor() {
330
+ this.sessionId = "";
331
+ this.userId = "";
332
+ }
333
+ initialize(userIdentifier) {
334
+ this.userId = userIdentifier || this.getPersistedUserId() || (0, import_uuid.v4)();
335
+ this.persistUserId(this.userId);
336
+ this.sessionId = this.getPersistedSessionId() || this.userId;
337
+ this.persistSessionId(this.sessionId);
338
+ }
339
+ regenerate() {
340
+ this.sessionId = (0, import_uuid.v4)();
341
+ this.persistSessionId(this.sessionId);
342
+ }
343
+ getSessionId() {
344
+ if (!this.sessionId) {
345
+ this.initialize();
346
+ }
347
+ return this.sessionId;
348
+ }
349
+ getUserId() {
350
+ if (!this.userId) {
351
+ this.initialize();
352
+ }
353
+ return this.userId;
354
+ }
355
+ getPersistedSessionId() {
356
+ try {
357
+ return localStorage.getItem(SESSION_KEY);
358
+ } catch {
359
+ return null;
360
+ }
361
+ }
362
+ persistSessionId(sessionId) {
363
+ try {
364
+ localStorage.setItem(SESSION_KEY, sessionId);
365
+ } catch {
366
+ }
367
+ }
368
+ getPersistedUserId() {
369
+ try {
370
+ return localStorage.getItem(USER_KEY);
371
+ } catch {
372
+ return null;
373
+ }
374
+ }
375
+ persistUserId(userId) {
376
+ try {
377
+ localStorage.setItem(USER_KEY, userId);
378
+ } catch {
379
+ }
380
+ }
381
+ };
382
+ var sessionHandler = new DefaultSessionHandler();
383
+
384
+ // src/shop-prompter.service.ts
385
+ var SHOP_PROMPTER_CONFIG = {
386
+ baseUrl: "https://demo.dev.shop-prompter.com/touch-points-api",
387
+ apiKey: "864c87266ef52c079c09b3248d86b4b5ef430bf9e5a4188476124c93ee2f6dda380f337986837b30b60f73e6aceefe7a0e0f778b3d21a7fa7698cf8546afc709"
388
+ };
389
+ var ShopPrompterService = class {
390
+ constructor() {
391
+ this.isLoading = false;
392
+ this.error = null;
393
+ this.streamingText = "";
394
+ shopPrompterApi.setApiConfig(SHOP_PROMPTER_CONFIG);
395
+ sessionHandler.initialize();
396
+ }
397
+ async sendMessage(prompt, callbacks, cartContext) {
398
+ var _a, _b, _c;
399
+ this.isLoading = true;
400
+ (_a = callbacks.onLoadingChange) == null ? void 0 : _a.call(callbacks, true);
401
+ this.error = null;
402
+ this.streamingText = "";
403
+ const userId = sessionHandler.getUserId();
404
+ const sessionId = sessionHandler.getSessionId();
405
+ let accumulatedText = "";
406
+ try {
407
+ await shopPrompterApi.executeStream(
408
+ prompt,
409
+ userId,
410
+ sessionId,
411
+ (event) => {
412
+ var _a2, _b2, _c2, _d, _e, _f, _g;
413
+ switch (event.type) {
414
+ case "text":
415
+ accumulatedText += event.text;
416
+ this.streamingText = accumulatedText;
417
+ (_a2 = callbacks.onTextUpdate) == null ? void 0 : _a2.call(callbacks, accumulatedText);
418
+ break;
419
+ case "productSkus":
420
+ (_b2 = callbacks.onProductSkus) == null ? void 0 : _b2.call(callbacks, event.skus);
421
+ break;
422
+ case "navigation":
423
+ console.log("Navigation event:", event.navigationOperations);
424
+ break;
425
+ case "cart":
426
+ (_c2 = callbacks.onCartOperation) == null ? void 0 : _c2.call(callbacks, event.operations);
427
+ break;
428
+ case "close":
429
+ this.isLoading = false;
430
+ (_d = callbacks.onLoadingChange) == null ? void 0 : _d.call(callbacks, false);
431
+ (_e = callbacks.onComplete) == null ? void 0 : _e.call(callbacks);
432
+ break;
433
+ case "error":
434
+ this.error = event.reason;
435
+ this.isLoading = false;
436
+ (_f = callbacks.onLoadingChange) == null ? void 0 : _f.call(callbacks, false);
437
+ (_g = callbacks.onError) == null ? void 0 : _g.call(callbacks, event.reason);
438
+ break;
439
+ }
440
+ },
441
+ cartContext
442
+ );
443
+ } catch (err) {
444
+ const errorMessage = err instanceof Error ? err.message : "Unknown error";
445
+ this.error = errorMessage;
446
+ this.isLoading = false;
447
+ (_b = callbacks.onLoadingChange) == null ? void 0 : _b.call(callbacks, false);
448
+ (_c = callbacks.onError) == null ? void 0 : _c.call(callbacks, errorMessage);
449
+ }
450
+ return accumulatedText;
451
+ }
452
+ async getAgentExperience() {
453
+ console.log(
454
+ "## ~ ShopPrompterService ~ getAgentExperience ~ getAgentExperience:"
455
+ );
456
+ try {
457
+ return await shopPrompterApi.getAgentExperience();
458
+ } catch (err) {
459
+ console.error("Failed to fetch agent experience:", err);
460
+ throw err;
461
+ }
462
+ }
463
+ resetSession() {
464
+ sessionHandler.regenerate();
465
+ }
466
+ getStatus() {
467
+ return {
468
+ isLoading: this.isLoading,
469
+ error: this.error,
470
+ streamingText: this.streamingText
471
+ };
472
+ }
473
+ };
474
+
475
+ // src/shop-prompter.component.jsx
476
+ var import_jsx_runtime = require("react/jsx-runtime");
477
+ var styles = {
478
+ header: {
479
+ display: "flex",
480
+ alignItems: "center",
481
+ justifyContent: "space-between",
482
+ padding: "16px"
483
+ },
484
+ subHeaderContainer: {
485
+ display: "flex",
486
+ alignItems: "center",
487
+ gap: "0.5rem"
488
+ },
489
+ headerButton: {
490
+ fontSize: "0.75rem",
491
+ color: "#71717a",
492
+ padding: "0.25rem 0.5rem",
493
+ borderRadius: "0.25rem",
494
+ backgroundColor: "transparent",
495
+ border: "none",
496
+ cursor: "pointer",
497
+ transition: "background-color 0.2s, color 0.2s",
498
+ onHover: {
499
+ backgroundColor: "hsl(220 14% 96%)",
500
+ color: "hsl(220 13% 13%)"
501
+ }
502
+ },
503
+ headerText: {
504
+ color: "hsl(220 13% 13%)",
505
+ fontWeight: 600
506
+ },
507
+ button: {
508
+ padding: "0.625rem 1rem",
509
+ border: "1px solid #e5e7eb",
510
+ borderRadius: "0.75rem",
511
+ backgroundColor: "transparent",
512
+ transition: "background-color 0.2s, color 0.2s",
513
+ display: "flex",
514
+ alignItems: "center",
515
+ gap: "0.5rem",
516
+ cursor: "pointer",
517
+ fontSize: "0.875rem",
518
+ color: "#09090b"
519
+ },
520
+ ButtonSheetButton: {
521
+ color: "#6b7280",
522
+ backgroundColor: "transparent",
523
+ border: "none",
524
+ cursor: "pointer",
525
+ padding: "0.25rem",
526
+ fontSize: "1.25rem",
527
+ transition: "color 0.2s"
528
+ },
529
+ chatContainer: {
530
+ flex: 1,
531
+ overflowY: "auto",
532
+ padding: "1rem",
533
+ backgroundColor: "white"
534
+ },
535
+ welcomeContainer: {
536
+ textAlign: "center",
537
+ paddingTop: "3rem",
538
+ paddingBottom: "3rem",
539
+ display: "flex",
540
+ flexDirection: "column",
541
+ alignItems: "center"
542
+ },
543
+ welcomeTitle: {
544
+ color: "#111827",
545
+ marginBottom: "0.5rem",
546
+ fontFamily: 'var(--font-space-grotesk), "Space Grotesk", sans-serif',
547
+ fontWeight: 500,
548
+ fontStyle: "Medium",
549
+ fontSize: "32px",
550
+ leadingTrim: "NONE",
551
+ lineHeight: "100%",
552
+ letterSpacing: "0%",
553
+ textAlign: "center"
554
+ },
555
+ welcomeDescription: {
556
+ color: "#4b5563",
557
+ maxWidth: "20rem",
558
+ fontFamily: 'var(--font-space-grotesk), "Space Grotesk", sans-serif',
559
+ fontWeight: 400,
560
+ fontStyle: "Regular",
561
+ fontSize: "16px",
562
+ leadingTrim: "NONE",
563
+ lineHeight: "100%",
564
+ letterSpacing: "0%",
565
+ textAlign: "center"
566
+ },
567
+ buttonContainer: {
568
+ marginTop: "2rem",
569
+ display: "flex",
570
+ flexWrap: "wrap",
571
+ justifyContent: "center",
572
+ gap: "0.5rem"
573
+ },
574
+ messageContainerUser: {
575
+ display: "flex",
576
+ flexDirection: "column",
577
+ alignItems: "flex-end"
578
+ },
579
+ messageContainerAssistant: {
580
+ display: "flex",
581
+ flexDirection: "column",
582
+ alignItems: "flex-start"
583
+ },
584
+ messageBubbleUser: {
585
+ backgroundColor: "#111827",
586
+ color: "white",
587
+ borderRadius: "1rem",
588
+ borderTopRightRadius: "0",
589
+ padding: "0.5rem 1rem",
590
+ fontSize: "0.875rem",
591
+ boxShadow: "0 1px 2px 0 rgba(0, 0, 0, 0.05)",
592
+ maxWidth: "85%"
593
+ },
594
+ messageBubbleAssistant: {
595
+ backgroundColor: "#f3f4f6",
596
+ color: "#1f2937",
597
+ borderRadius: "1rem",
598
+ borderTopLeftRadius: "0",
599
+ padding: "0.5rem 1rem",
600
+ fontSize: "0.875rem",
601
+ boxShadow: "0 1px 2px 0 rgba(0, 0, 0, 0.05)",
602
+ maxWidth: "85%"
603
+ },
604
+ thinkingIndicator: {
605
+ display: "flex",
606
+ alignItems: "center",
607
+ gap: "0.5rem",
608
+ fontStyle: "italic",
609
+ color: "#6b7280"
610
+ },
611
+ productCardsContainer: {
612
+ marginTop: "1rem",
613
+ display: "flex",
614
+ gap: "0.75rem",
615
+ overflowX: "auto",
616
+ width: "100%",
617
+ paddingBottom: "0.5rem"
618
+ },
619
+ productCard: {
620
+ minWidth: "8rem",
621
+ backgroundColor: "white",
622
+ border: "1px solid #e5e7eb",
623
+ borderRadius: "0.75rem",
624
+ overflow: "hidden",
625
+ boxShadow: "0 1px 2px 0 rgba(0, 0, 0, 0.05)",
626
+ display: "flex",
627
+ flexDirection: "column"
628
+ },
629
+ productImageContainer: {
630
+ height: "6rem",
631
+ backgroundColor: "#f9fafb",
632
+ display: "flex",
633
+ alignItems: "center",
634
+ justifyContent: "center",
635
+ padding: "0.5rem"
636
+ },
637
+ productInfo: {
638
+ padding: "0.5rem"
639
+ },
640
+ productSku: {
641
+ fontSize: "0.75rem",
642
+ fontWeight: 600,
643
+ overflow: "hidden",
644
+ textOverflow: "ellipsis",
645
+ whiteSpace: "nowrap",
646
+ color: "#111827"
647
+ },
648
+ productLink: {
649
+ fontSize: "0.625rem",
650
+ color: "#2563eb",
651
+ fontWeight: "bold",
652
+ textDecoration: "none"
653
+ },
654
+ errorContainer: {
655
+ padding: "0.75rem",
656
+ backgroundColor: "#fef2f2",
657
+ border: "1px solid #fecaca",
658
+ color: "#dc2626",
659
+ fontSize: "0.75rem",
660
+ borderRadius: "0.5rem"
661
+ },
662
+ inputSection: {
663
+ padding: "1rem",
664
+ borderTop: "1px solid #e5e7eb",
665
+ backgroundColor: "#f9fafb"
666
+ },
667
+ inputWrapper: {
668
+ display: "flex",
669
+ alignItems: "center",
670
+ gap: "0.5rem",
671
+ backgroundColor: "white",
672
+ border: "1px solid #d1d5db",
673
+ borderRadius: "0.75rem",
674
+ padding: "0.5rem 1rem",
675
+ transition: "all 0.2s"
676
+ },
677
+ input: {
678
+ flex: 1,
679
+ backgroundColor: "transparent",
680
+ border: "none",
681
+ outline: "none",
682
+ fontSize: "0.875rem",
683
+ color: "#111827",
684
+ padding: "0.25rem 0"
685
+ },
686
+ formButton: {
687
+ backgroundColor: "transparent",
688
+ color: "white",
689
+ width: "32px",
690
+ height: "32px",
691
+ borderRadius: "0.5rem",
692
+ padding: 0,
693
+ fontSize: "0.75rem",
694
+ fontWeight: "bold",
695
+ border: "none",
696
+ cursor: "pointer",
697
+ transition: "background-color 0.2s"
698
+ },
699
+ sendButton: {
700
+ backgroundColor: "#AD59FF1A"
701
+ },
702
+ disclaimer: {
703
+ fontSize: "0.625rem",
704
+ color: "#9ca3af",
705
+ textAlign: "center",
706
+ marginTop: "0.75rem"
707
+ }
708
+ };
709
+ var TRANSLATIONS = {
710
+ newChat: "New Chat",
711
+ welcomeToShopPrompter: "Welcome to ShopPrompter",
712
+ welcomeDescription: "I am your personal AI shopping assistant. Ask me anything about our products!",
713
+ askMeAnything: "Ask me anything...",
714
+ thinking: "Thinking...",
715
+ showPopularItems: "Show popular items",
716
+ compareProducts: "Compare products",
717
+ findByBudget: "Find by budget"
718
+ };
719
+ var ICONS = {
720
+ chat: "https://cdn.jsdelivr.net/gh/lucide-icons/lucide@latest/icons/message-square.svg",
721
+ shopprompter: "https://cdn.jsdelivr.net/gh/lucide-icons/lucide@latest/icons/bot.svg",
722
+ popularitems: "https://cdn.jsdelivr.net/gh/lucide-icons/lucide@latest/icons/fire.svg",
723
+ compareproducts: "https://cdn.jsdelivr.net/gh/lucide-icons/lucide@latest/icons/box.svg",
724
+ findbybudget: "https://cdn.jsdelivr.net/gh/lucide-icons/lucide@latest/icons/foto.svg",
725
+ sendHorizontal: "https://cdn.jsdelivr.net/gh/lucide-icons/lucide@latest/icons/send-horizontal.svg"
726
+ };
727
+ function ShopPrompter(props) {
728
+ var _a, _b, _c;
729
+ const [input, setInput] = (0, import_react.useState)(() => "");
730
+ const [isLoading, setIsLoading] = (0, import_react.useState)(() => false);
731
+ const [error, setError] = (0, import_react.useState)(() => null);
732
+ const [chatMessages, setChatMessages] = (0, import_react.useState)(() => []);
733
+ const [showChat, setShowChat] = (0, import_react.useState)(
734
+ () => props.chatPosition === "right-panel" || props.chatPosition === "full-page"
735
+ );
736
+ const [service, setService] = (0, import_react.useState)(() => null);
737
+ const [isHeaderButtonHovered, setIsHeaderButtonHovered] = (0, import_react.useState)(
738
+ () => false
739
+ );
740
+ const [agentExperience, setAgentExperience] = (0, import_react.useState)(() => null);
741
+ function containerStyle() {
742
+ const pos = props.chatPosition || "classic-chatbot";
743
+ const isFull = pos === "full-page";
744
+ const isBottom = pos === "bottom-sheet";
745
+ const isClassic = pos === "classic-chatbot";
746
+ const isRight = pos === "right-panel";
747
+ return {
748
+ position: isFull ? "relative" : "fixed",
749
+ bottom: isClassic ? "1rem" : isBottom ? "2rem" : "0",
750
+ right: isClassic || isRight ? "1rem" : "0",
751
+ width: isFull ? "100%" : isBottom ? "90%" : "24rem",
752
+ height: isClassic ? "550px" : isBottom ? "700px" : "100%",
753
+ maxWidth: isBottom ? "900px" : "none",
754
+ left: isBottom ? "50%" : "auto",
755
+ transform: isBottom ? "translateX(-50%)" : "none",
756
+ zIndex: 50,
757
+ backgroundColor: "white",
758
+ display: "flex",
759
+ flexDirection: "column",
760
+ overflow: "hidden",
761
+ borderRadius: isFull ? "0" : "0.5rem",
762
+ border: isFull ? "none" : "1px solid #e5e7eb",
763
+ boxShadow: isFull ? "none" : "0 25px 50px -12px rgba(0, 0, 0, 0.25)"
764
+ };
765
+ }
766
+ function containerClass() {
767
+ const pos = props.chatPosition || "classic-chatbot";
768
+ if (pos === "classic-chatbot") return "sh-classic";
769
+ if (pos === "right-panel") return "sh-right";
770
+ if (pos === "bottom-sheet") return "sh-bottom";
771
+ return "sh-full";
772
+ }
773
+ function messages() {
774
+ return chatMessages.map((msg) => ({
775
+ ...msg,
776
+ safeProductSkus: msg.productSkus || []
777
+ }));
778
+ }
779
+ function showWelcome() {
780
+ return chatMessages.length === 0;
781
+ }
782
+ function getProductImageUrl(sku) {
783
+ return "https://placehold.co/100x100?text=" + sku;
784
+ }
785
+ function getProductLink(sku) {
786
+ return "/product/" + sku;
787
+ }
788
+ function handleSend() {
789
+ if (!input.trim() || isLoading) return;
790
+ const userQuery = input;
791
+ setInput("");
792
+ const userMsg = {
793
+ id: Date.now().toString() + "-user",
794
+ role: "user",
795
+ content: userQuery,
796
+ productSkus: []
797
+ };
798
+ setChatMessages([...chatMessages, userMsg]);
799
+ const assistantMsg = {
800
+ id: Date.now().toString() + "-assistant",
801
+ role: "assistant",
802
+ content: "",
803
+ productSkus: []
804
+ };
805
+ setChatMessages([...chatMessages, assistantMsg]);
806
+ service == null ? void 0 : service.sendMessage(
807
+ userQuery,
808
+ {
809
+ onTextUpdate: (text) => {
810
+ const updatedMessages = [...chatMessages];
811
+ const lastMsg = updatedMessages[updatedMessages.length - 1];
812
+ if (lastMsg) {
813
+ lastMsg.content = text;
814
+ setChatMessages(updatedMessages);
815
+ }
816
+ },
817
+ onProductSkus: (skus) => {
818
+ const updatedMessages = [...chatMessages];
819
+ const lastMsg = updatedMessages[updatedMessages.length - 1];
820
+ if (lastMsg) {
821
+ lastMsg.productSkus = skus;
822
+ setChatMessages(updatedMessages);
823
+ }
824
+ },
825
+ onLoadingChange: (loading) => {
826
+ setIsLoading(loading);
827
+ },
828
+ onError: (err) => {
829
+ setError(err);
830
+ },
831
+ onCartOperation: (ops) => {
832
+ if (props.onCartOperation) {
833
+ props.onCartOperation(ops);
834
+ }
835
+ }
836
+ },
837
+ props.cart || []
838
+ );
839
+ }
840
+ function toggleChat() {
841
+ setShowChat(!showChat);
842
+ if (!showChat && props.onClose) {
843
+ props.onClose();
844
+ }
845
+ }
846
+ function handleNewChat() {
847
+ setChatMessages([]);
848
+ service == null ? void 0 : service.resetSession();
849
+ }
850
+ function onPopularItemsClick() {
851
+ setInput(TRANSLATIONS.showPopularItems);
852
+ handleSend();
853
+ }
854
+ function onCompareProductsClick() {
855
+ setInput(TRANSLATIONS.compareProducts);
856
+ handleSend();
857
+ }
858
+ function onInputChange(event) {
859
+ setInput(event.target.value);
860
+ }
861
+ function onInputKeyDown(event) {
862
+ if (event.key === "Enter") {
863
+ handleSend();
864
+ }
865
+ }
866
+ function onHeaderButtonMouseEnter() {
867
+ setIsHeaderButtonHovered(true);
868
+ }
869
+ function onHeaderButtonMouseLeave() {
870
+ setIsHeaderButtonHovered(false);
871
+ }
872
+ function doSomethingAsync() {
873
+ void (async function() {
874
+ console.log("## ~ ShopPrompter ~ state.service:", service);
875
+ if (!service) {
876
+ console.warn("Service not initialized yet");
877
+ return;
878
+ }
879
+ const response = await (service == null ? void 0 : service.getAgentExperience());
880
+ console.log("## ~ ShopPrompter ~ response:", response);
881
+ setAgentExperience(response);
882
+ })();
883
+ }
884
+ (0, import_react.useEffect)(() => {
885
+ const shopPrompterService = new ShopPrompterService();
886
+ setService(shopPrompterService);
887
+ }, []);
888
+ (0, import_react.useEffect)(() => {
889
+ if (service && !agentExperience) {
890
+ doSomethingAsync();
891
+ }
892
+ if (agentExperience) {
893
+ console.log("## ~ ShopPrompter ~ agentExperience updated:", {
894
+ greeting: agentExperience.greeting,
895
+ agentLogoUrl: agentExperience.agentLogoUrl
896
+ });
897
+ }
898
+ }, [service, agentExperience]);
899
+ return /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", { className: "shopprompter-sdk", children: [
900
+ props.chatPosition === "classic-chatbot" ? /* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_jsx_runtime.Fragment, { children: !showChat ? /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
901
+ "button",
902
+ {
903
+ 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",
904
+ onClick: (e) => toggleChat(),
905
+ style: {
906
+ boxShadow: "0 0 0 8px rgba(37, 99, 235, 0.2)"
907
+ },
908
+ children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
909
+ "img",
910
+ {
911
+ alt: "Chat",
912
+ src: ICONS.chat,
913
+ style: {
914
+ width: "28px",
915
+ height: "28px"
916
+ }
917
+ }
918
+ )
919
+ }
920
+ ) : null }) : null,
921
+ showChat ? /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", { style: containerStyle(), className: containerClass(), children: [
922
+ /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", { style: styles.header, children: [
923
+ /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", { style: styles.subHeaderContainer, children: [
924
+ /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(
925
+ "svg",
926
+ {
927
+ xmlns: "http://www.w3.org/2000/svg",
928
+ viewBox: "0 0 46 47",
929
+ width: "24",
930
+ height: "24",
931
+ fill: "none",
932
+ children: [
933
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
934
+ "path",
935
+ {
936
+ fill: "url(#a)",
937
+ 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"
938
+ }
939
+ ),
940
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
941
+ "path",
942
+ {
943
+ fill: "url(#b)",
944
+ 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"
945
+ }
946
+ ),
947
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
948
+ "path",
949
+ {
950
+ fill: "url(#c)",
951
+ 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"
952
+ }
953
+ ),
954
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
955
+ "path",
956
+ {
957
+ fill: "url(#d)",
958
+ 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"
959
+ }
960
+ ),
961
+ /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("defs", { children: [
962
+ /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(
963
+ "linearGradient",
964
+ {
965
+ id: "a",
966
+ x1: "14.3",
967
+ x2: "3.322",
968
+ y1: "22.494",
969
+ y2: "4.382",
970
+ gradientUnits: "userSpaceOnUse",
971
+ children: [
972
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)("stop", { stopColor: "#B0145C" }),
973
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)("stop", { offset: ".37", stopColor: "#AE2E9A" }),
974
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)("stop", { offset: "1", stopColor: "#AD59FF" })
975
+ ]
976
+ }
977
+ ),
978
+ /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(
979
+ "linearGradient",
980
+ {
981
+ id: "b",
982
+ x1: "21.156",
983
+ x2: "40.431",
984
+ y1: "21.216",
985
+ y2: "1.624",
986
+ gradientUnits: "userSpaceOnUse",
987
+ children: [
988
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)("stop", { offset: ".08", stopColor: "#E7A2FF" }),
989
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)("stop", { offset: ".37", stopColor: "#E983CD" }),
990
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)("stop", { offset: ".99", stopColor: "#F03A58" })
991
+ ]
992
+ }
993
+ ),
994
+ /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(
995
+ "linearGradient",
996
+ {
997
+ id: "c",
998
+ x1: "30.464",
999
+ x2: "46.567",
1000
+ y1: "27.405",
1001
+ y2: "42.472",
1002
+ gradientUnits: "userSpaceOnUse",
1003
+ children: [
1004
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)("stop", { stopColor: "#B0145C" }),
1005
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)("stop", { offset: ".02", stopColor: "#B11861" }),
1006
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)("stop", { offset: ".27", stopColor: "#C44999" }),
1007
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)("stop", { offset: ".5", stopColor: "#D36FC5" }),
1008
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)("stop", { offset: ".71", stopColor: "#DE8BE4" }),
1009
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)("stop", { offset: ".88", stopColor: "#E49BF8" }),
1010
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)("stop", { offset: "1", stopColor: "#E7A2FF" })
1011
+ ]
1012
+ }
1013
+ ),
1014
+ /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(
1015
+ "linearGradient",
1016
+ {
1017
+ id: "d",
1018
+ x1: "23.356",
1019
+ x2: "-.618",
1020
+ y1: "44.082",
1021
+ y2: "30.739",
1022
+ gradientUnits: "userSpaceOnUse",
1023
+ children: [
1024
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)("stop", { stopColor: "#AD59FF" }),
1025
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)("stop", { offset: ".1", stopColor: "#B455EB" }),
1026
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)("stop", { offset: ".54", stopColor: "#D4469C" }),
1027
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)("stop", { offset: ".85", stopColor: "#E83D6B" }),
1028
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)("stop", { offset: "1", stopColor: "#F03A58" })
1029
+ ]
1030
+ }
1031
+ )
1032
+ ] })
1033
+ ]
1034
+ }
1035
+ ),
1036
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)("span", { style: styles.headerText, children: "ShopPrompter\xAE" })
1037
+ ] }),
1038
+ /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", { style: styles.subHeaderContainer, children: [
1039
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
1040
+ "button",
1041
+ {
1042
+ onClick: (e) => handleNewChat(),
1043
+ onMouseEnter: (e) => onHeaderButtonMouseEnter(),
1044
+ onMouseLeave: (e) => onHeaderButtonMouseLeave(),
1045
+ style: {
1046
+ ...styles.headerButton,
1047
+ ...isHeaderButtonHovered ? styles.headerButton.onHover : {}
1048
+ },
1049
+ children: TRANSLATIONS.newChat
1050
+ }
1051
+ ),
1052
+ props.chatPosition === "classic-chatbot" || props.chatPosition === "right-panel" || props.chatPosition === "bottom-sheet" ? /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
1053
+ "button",
1054
+ {
1055
+ onClick: (e) => toggleChat(),
1056
+ style: styles.ButtonSheetButton,
1057
+ children: "\xD7"
1058
+ }
1059
+ ) : null
1060
+ ] })
1061
+ ] }),
1062
+ /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", { style: styles.chatContainer, children: [
1063
+ showWelcome() ? /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", { style: styles.welcomeContainer, children: [
1064
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
1065
+ "img",
1066
+ {
1067
+ alt: "ShopPrompter",
1068
+ src: (agentExperience == null ? void 0 : agentExperience.agentLogoUrl) ? agentExperience.agentLogoUrl : ICONS.shopprompter,
1069
+ style: {
1070
+ width: "64px",
1071
+ height: "64px",
1072
+ marginBottom: "24px"
1073
+ }
1074
+ }
1075
+ ),
1076
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)("h3", { style: styles.welcomeTitle, children: ((_a = agentExperience == null ? void 0 : agentExperience.greeting) == null ? void 0 : _a.title) || TRANSLATIONS.welcomeToShopPrompter }),
1077
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)("p", { style: styles.welcomeDescription, children: ((_b = agentExperience == null ? void 0 : agentExperience.greeting) == null ? void 0 : _b.description) || TRANSLATIONS.welcomeDescription }),
1078
+ /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", { style: styles.buttonContainer, children: [
1079
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
1080
+ "button",
1081
+ {
1082
+ style: styles.button,
1083
+ onClick: (e) => onPopularItemsClick(),
1084
+ children: TRANSLATIONS.showPopularItems
1085
+ }
1086
+ ),
1087
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
1088
+ "button",
1089
+ {
1090
+ style: styles.button,
1091
+ onClick: (e) => onCompareProductsClick(),
1092
+ children: TRANSLATIONS.compareProducts
1093
+ }
1094
+ )
1095
+ ] })
1096
+ ] }) : /* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_jsx_runtime.Fragment, { children: (_c = messages()) == null ? void 0 : _c.map((message) => {
1097
+ var _a2;
1098
+ return /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(
1099
+ "div",
1100
+ {
1101
+ style: message.role === "user" ? styles.messageContainerUser : styles.messageContainerAssistant,
1102
+ children: [
1103
+ /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(
1104
+ "div",
1105
+ {
1106
+ style: message.role === "user" ? styles.messageBubbleUser : styles.messageBubbleAssistant,
1107
+ children: [
1108
+ message.content,
1109
+ !message.content ? /* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_jsx_runtime.Fragment, { children: message.role === "assistant" ? /* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_jsx_runtime.Fragment, { children: isLoading ? /* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", { style: styles.thinkingIndicator, children: TRANSLATIONS.thinking }) : null }) : null }) : null
1110
+ ]
1111
+ }
1112
+ ),
1113
+ message.role === "assistant" ? /* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", { style: styles.productCardsContainer, children: (_a2 = message.safeProductSkus) == null ? void 0 : _a2.map((sku) => /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", { style: styles.productCard, children: [
1114
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", { style: styles.productImageContainer, children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
1115
+ "img",
1116
+ {
1117
+ src: getProductImageUrl(sku),
1118
+ alt: sku,
1119
+ style: {
1120
+ maxHeight: "100%",
1121
+ maxWidth: "100%"
1122
+ }
1123
+ }
1124
+ ) }),
1125
+ /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", { style: styles.productInfo, children: [
1126
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)("p", { style: styles.productSku, children: sku }),
1127
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
1128
+ "a",
1129
+ {
1130
+ href: getProductLink(sku),
1131
+ style: styles.productLink,
1132
+ children: "VIEW DETAILS"
1133
+ }
1134
+ )
1135
+ ] })
1136
+ ] }, sku)) }) : null
1137
+ ]
1138
+ },
1139
+ message.id
1140
+ );
1141
+ }) }),
1142
+ error ? /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", { style: styles.errorContainer, children: [
1143
+ "Error: ",
1144
+ error
1145
+ ] }) : null
1146
+ ] }),
1147
+ /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", { style: styles.inputSection, children: [
1148
+ /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", { style: styles.inputWrapper, children: [
1149
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
1150
+ "input",
1151
+ {
1152
+ type: "text",
1153
+ style: styles.input,
1154
+ placeholder: TRANSLATIONS.askMeAnything,
1155
+ value: input,
1156
+ onInput: (e) => onInputChange(e),
1157
+ onKeyDown: (e) => onInputKeyDown(e)
1158
+ }
1159
+ ),
1160
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
1161
+ "button",
1162
+ {
1163
+ onClick: (e) => handleSend(),
1164
+ style: {
1165
+ ...styles.formButton,
1166
+ ...styles.sendButton
1167
+ },
1168
+ children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)("img", { alt: "Send", src: ICONS.sendHorizontal })
1169
+ }
1170
+ )
1171
+ ] }),
1172
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)("p", { style: styles.disclaimer, children: "AI content may be inaccurate." })
1173
+ ] })
1174
+ ] }) : null
1175
+ ] });
1176
+ }
1177
+ var shop_prompter_component_default = ShopPrompter;
1178
+ // Annotate the CommonJS export names for ESM import in node:
1179
+ 0 && (module.exports = {
1180
+ ShopPrompter
1181
+ });