@akropolys/kiku 1.2.4 → 1.4.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.d.mts +59 -4
- package/dist/index.d.ts +59 -4
- package/dist/index.js +968 -559
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +939 -532
- package/dist/index.mjs.map +1 -1
- package/dist/styles.css +407 -1
- package/dist/styles.css.map +1 -1
- package/package.json +2 -2
package/dist/index.js
CHANGED
|
@@ -29,7 +29,9 @@ __export(src_exports, {
|
|
|
29
29
|
KikuButton: () => KikuButton,
|
|
30
30
|
KikuChat: () => ChatWidget,
|
|
31
31
|
SearchBar: () => SearchBar,
|
|
32
|
-
Sparkle: () => Sparkle
|
|
32
|
+
Sparkle: () => Sparkle,
|
|
33
|
+
VisualSearch: () => VisualSearch,
|
|
34
|
+
VoiceButton: () => VoiceButton
|
|
33
35
|
});
|
|
34
36
|
module.exports = __toCommonJS(src_exports);
|
|
35
37
|
|
|
@@ -197,8 +199,8 @@ function SearchBar({
|
|
|
197
199
|
}
|
|
198
200
|
|
|
199
201
|
// src/components/ChatWidget.tsx
|
|
200
|
-
var
|
|
201
|
-
var
|
|
202
|
+
var import_react4 = require("react");
|
|
203
|
+
var import_sdk3 = require("@akropolys/sdk");
|
|
202
204
|
|
|
203
205
|
// src/utils/markdown.tsx
|
|
204
206
|
var import_jsx_runtime2 = require("react/jsx-runtime");
|
|
@@ -285,19 +287,151 @@ function renderMarkdown(content) {
|
|
|
285
287
|
return /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(import_jsx_runtime2.Fragment, { children: elements });
|
|
286
288
|
}
|
|
287
289
|
|
|
288
|
-
// src/components/
|
|
290
|
+
// src/components/VoiceButton.tsx
|
|
291
|
+
var import_react2 = require("react");
|
|
289
292
|
var import_jsx_runtime3 = require("react/jsx-runtime");
|
|
290
|
-
var
|
|
291
|
-
|
|
292
|
-
/* @__PURE__ */ (0, import_jsx_runtime3.jsx)("path", { d: "
|
|
293
|
-
/* @__PURE__ */ (0, import_jsx_runtime3.jsx)("
|
|
293
|
+
var MicIcon = ({ active }) => /* @__PURE__ */ (0, import_jsx_runtime3.jsxs)("svg", { width: "16", height: "16", viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "2", strokeLinecap: "round", strokeLinejoin: "round", children: [
|
|
294
|
+
/* @__PURE__ */ (0, import_jsx_runtime3.jsx)("rect", { x: "9", y: "2", width: "6", height: "11", rx: "3", fill: active ? "currentColor" : "none" }),
|
|
295
|
+
/* @__PURE__ */ (0, import_jsx_runtime3.jsx)("path", { d: "M5 10a7 7 0 0 0 14 0" }),
|
|
296
|
+
/* @__PURE__ */ (0, import_jsx_runtime3.jsx)("line", { x1: "12", y1: "19", x2: "12", y2: "23" }),
|
|
297
|
+
/* @__PURE__ */ (0, import_jsx_runtime3.jsx)("line", { x1: "8", y1: "23", x2: "16", y2: "23" })
|
|
298
|
+
] });
|
|
299
|
+
function VoiceButton({
|
|
300
|
+
onTranscript,
|
|
301
|
+
onInterim,
|
|
302
|
+
lang = "en-US",
|
|
303
|
+
className = "",
|
|
304
|
+
disabled = false
|
|
305
|
+
}) {
|
|
306
|
+
const [listening, setListening] = (0, import_react2.useState)(false);
|
|
307
|
+
const recognitionRef = (0, import_react2.useRef)(null);
|
|
308
|
+
const isSupported = typeof window !== "undefined" && ("SpeechRecognition" in window || "webkitSpeechRecognition" in window);
|
|
309
|
+
const start = (0, import_react2.useCallback)(() => {
|
|
310
|
+
if (!isSupported || listening) return;
|
|
311
|
+
const SR = window.SpeechRecognition || window.webkitSpeechRecognition;
|
|
312
|
+
const recognition = new SR();
|
|
313
|
+
recognition.lang = lang;
|
|
314
|
+
recognition.interimResults = true;
|
|
315
|
+
recognition.maxAlternatives = 1;
|
|
316
|
+
recognitionRef.current = recognition;
|
|
317
|
+
recognition.onstart = () => setListening(true);
|
|
318
|
+
recognition.onend = () => setListening(false);
|
|
319
|
+
recognition.onerror = () => setListening(false);
|
|
320
|
+
recognition.onresult = (e) => {
|
|
321
|
+
const results = Array.from(e.results);
|
|
322
|
+
const transcript = results.map((r) => r[0].transcript).join("");
|
|
323
|
+
const isFinal = e.results[e.results.length - 1].isFinal;
|
|
324
|
+
if (isFinal) {
|
|
325
|
+
onTranscript(transcript);
|
|
326
|
+
setListening(false);
|
|
327
|
+
} else {
|
|
328
|
+
onInterim?.(transcript);
|
|
329
|
+
}
|
|
330
|
+
};
|
|
331
|
+
recognition.start();
|
|
332
|
+
}, [isSupported, listening, lang, onTranscript, onInterim]);
|
|
333
|
+
const stop = (0, import_react2.useCallback)(() => {
|
|
334
|
+
recognitionRef.current?.stop();
|
|
335
|
+
setListening(false);
|
|
336
|
+
}, []);
|
|
337
|
+
if (!isSupported) return null;
|
|
338
|
+
return /* @__PURE__ */ (0, import_jsx_runtime3.jsxs)(
|
|
339
|
+
"button",
|
|
340
|
+
{
|
|
341
|
+
type: "button",
|
|
342
|
+
className: `kiku-voice-btn${listening ? " kiku-voice-btn--active" : ""} ${className}`,
|
|
343
|
+
onClick: listening ? stop : start,
|
|
344
|
+
disabled,
|
|
345
|
+
title: listening ? "Stop listening" : "Speak your search",
|
|
346
|
+
"aria-label": listening ? "Stop voice input" : "Start voice input",
|
|
347
|
+
children: [
|
|
348
|
+
/* @__PURE__ */ (0, import_jsx_runtime3.jsx)(MicIcon, { active: listening }),
|
|
349
|
+
listening && /* @__PURE__ */ (0, import_jsx_runtime3.jsx)("span", { className: "kiku-voice-ripple", "aria-hidden": "true" })
|
|
350
|
+
]
|
|
351
|
+
}
|
|
352
|
+
);
|
|
353
|
+
}
|
|
354
|
+
|
|
355
|
+
// src/components/VisualSearch.tsx
|
|
356
|
+
var import_react3 = require("react");
|
|
357
|
+
var import_sdk2 = require("@akropolys/sdk");
|
|
358
|
+
var import_jsx_runtime4 = require("react/jsx-runtime");
|
|
359
|
+
var CameraIcon = () => /* @__PURE__ */ (0, import_jsx_runtime4.jsxs)("svg", { width: "16", height: "16", viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "2", strokeLinecap: "round", strokeLinejoin: "round", children: [
|
|
360
|
+
/* @__PURE__ */ (0, import_jsx_runtime4.jsx)("path", { d: "M23 19a2 2 0 0 1-2 2H3a2 2 0 0 1-2-2V8a2 2 0 0 1 2-2h4l2-3h6l2 3h4a2 2 0 0 1 2 2z" }),
|
|
361
|
+
/* @__PURE__ */ (0, import_jsx_runtime4.jsx)("circle", { cx: "12", cy: "13", r: "4" })
|
|
362
|
+
] });
|
|
363
|
+
var SpinnerIcon = () => /* @__PURE__ */ (0, import_jsx_runtime4.jsx)("svg", { width: "16", height: "16", viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "2", className: "kiku-vs-spin", children: /* @__PURE__ */ (0, import_jsx_runtime4.jsx)("path", { d: "M21 12a9 9 0 1 1-6.219-8.56" }) });
|
|
364
|
+
function fileToBase64(file) {
|
|
365
|
+
return new Promise((resolve, reject) => {
|
|
366
|
+
const reader = new FileReader();
|
|
367
|
+
reader.onload = () => resolve(reader.result);
|
|
368
|
+
reader.onerror = reject;
|
|
369
|
+
reader.readAsDataURL(file);
|
|
370
|
+
});
|
|
371
|
+
}
|
|
372
|
+
function VisualSearch({
|
|
373
|
+
onResults,
|
|
374
|
+
onError,
|
|
375
|
+
categoryHint,
|
|
376
|
+
className = "",
|
|
377
|
+
disabled = false
|
|
378
|
+
}) {
|
|
379
|
+
const client = (0, import_sdk2.useAkropolysContext)();
|
|
380
|
+
const inputRef = (0, import_react3.useRef)(null);
|
|
381
|
+
const [loading, setLoading] = (0, import_react3.useState)(false);
|
|
382
|
+
const handleFile = async (file) => {
|
|
383
|
+
if (!file.type.startsWith("image/")) return;
|
|
384
|
+
setLoading(true);
|
|
385
|
+
try {
|
|
386
|
+
const base64 = await fileToBase64(file);
|
|
387
|
+
const res = await client.api.searchByImage(base64, categoryHint);
|
|
388
|
+
onResults(res, base64);
|
|
389
|
+
} catch (e) {
|
|
390
|
+
onError?.(e instanceof Error ? e : new Error(String(e)));
|
|
391
|
+
} finally {
|
|
392
|
+
setLoading(false);
|
|
393
|
+
if (inputRef.current) inputRef.current.value = "";
|
|
394
|
+
}
|
|
395
|
+
};
|
|
396
|
+
return /* @__PURE__ */ (0, import_jsx_runtime4.jsxs)(
|
|
397
|
+
"label",
|
|
398
|
+
{
|
|
399
|
+
className: `kiku-vs-btn${loading ? " kiku-vs-btn--loading" : ""} ${className}`,
|
|
400
|
+
title: "Search by photo",
|
|
401
|
+
"aria-label": "Search by uploading a photo",
|
|
402
|
+
style: { cursor: disabled || loading ? "not-allowed" : "pointer" },
|
|
403
|
+
children: [
|
|
404
|
+
/* @__PURE__ */ (0, import_jsx_runtime4.jsx)(
|
|
405
|
+
"input",
|
|
406
|
+
{
|
|
407
|
+
ref: inputRef,
|
|
408
|
+
type: "file",
|
|
409
|
+
accept: "image/*",
|
|
410
|
+
capture: "environment",
|
|
411
|
+
onChange: (e) => e.target.files?.[0] && handleFile(e.target.files[0]),
|
|
412
|
+
disabled: disabled || loading,
|
|
413
|
+
hidden: true
|
|
414
|
+
}
|
|
415
|
+
),
|
|
416
|
+
loading ? /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(SpinnerIcon, {}) : /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(CameraIcon, {})
|
|
417
|
+
]
|
|
418
|
+
}
|
|
419
|
+
);
|
|
420
|
+
}
|
|
421
|
+
|
|
422
|
+
// src/components/ChatWidget.tsx
|
|
423
|
+
var import_jsx_runtime5 = require("react/jsx-runtime");
|
|
424
|
+
var SparkleIcon = () => /* @__PURE__ */ (0, import_jsx_runtime5.jsx)("svg", { width: "16", height: "16", viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "2", strokeLinecap: "round", strokeLinejoin: "round", children: /* @__PURE__ */ (0, import_jsx_runtime5.jsx)("path", { d: "m12 3-1.912 5.813a2 2 0 0 1-1.275 1.275L3 12l5.813 1.912a2 2 0 0 1 1.275 1.275L12 21l1.912-5.813a2 2 0 0 1 1.275-1.275L21 12l-5.813-1.912a2 2 0 0 1-1.275-1.275L12 3Z" }) });
|
|
425
|
+
var ArrowUpIcon = () => /* @__PURE__ */ (0, import_jsx_runtime5.jsxs)("svg", { width: "18", height: "18", viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "2", strokeLinecap: "round", strokeLinejoin: "round", children: [
|
|
426
|
+
/* @__PURE__ */ (0, import_jsx_runtime5.jsx)("path", { d: "m5 12 7-7 7 7" }),
|
|
427
|
+
/* @__PURE__ */ (0, import_jsx_runtime5.jsx)("path", { d: "M12 19V5" })
|
|
294
428
|
] });
|
|
295
429
|
function SourceCard({ source, defaultCurrency, onSelect }) {
|
|
296
|
-
return /* @__PURE__ */ (0,
|
|
297
|
-
source.image && /* @__PURE__ */ (0,
|
|
298
|
-
/* @__PURE__ */ (0,
|
|
299
|
-
/* @__PURE__ */ (0,
|
|
300
|
-
source.price && /* @__PURE__ */ (0,
|
|
430
|
+
return /* @__PURE__ */ (0, import_jsx_runtime5.jsxs)("div", { className: "hsk-source-card", onClick: () => onSelect?.(source), children: [
|
|
431
|
+
source.image && /* @__PURE__ */ (0, import_jsx_runtime5.jsx)("img", { src: source.image, alt: source.name, className: "hsk-source-img" }),
|
|
432
|
+
/* @__PURE__ */ (0, import_jsx_runtime5.jsxs)("div", { style: { flex: 1, minWidth: 0 }, children: [
|
|
433
|
+
/* @__PURE__ */ (0, import_jsx_runtime5.jsx)("div", { className: "hsk-source-name", children: source.name }),
|
|
434
|
+
source.price && /* @__PURE__ */ (0, import_jsx_runtime5.jsxs)("div", { className: "hsk-source-price", children: [
|
|
301
435
|
source.currency ?? defaultCurrency,
|
|
302
436
|
" ",
|
|
303
437
|
source.price
|
|
@@ -314,15 +448,56 @@ function ChatWidget({
|
|
|
314
448
|
className,
|
|
315
449
|
theme,
|
|
316
450
|
classNames = {},
|
|
317
|
-
onSelectSource
|
|
451
|
+
onSelectSource,
|
|
452
|
+
enableVoice = false,
|
|
453
|
+
enableVision = false,
|
|
454
|
+
visionCategoryHint
|
|
318
455
|
}) {
|
|
319
|
-
const { messages, sources, loading, error, send, reset } = (0,
|
|
320
|
-
const [input, setInput] = (0,
|
|
321
|
-
const
|
|
322
|
-
const
|
|
323
|
-
(0,
|
|
456
|
+
const { messages, sources, loading: chatLoading, error, send, reset } = (0, import_sdk3.useKiku)();
|
|
457
|
+
const [input, setInput] = (0, import_react4.useState)("");
|
|
458
|
+
const [visualLoading, setVisualLoading] = (0, import_react4.useState)(false);
|
|
459
|
+
const bottomRef = (0, import_react4.useRef)(null);
|
|
460
|
+
const textareaRef = (0, import_react4.useRef)(null);
|
|
461
|
+
const loading = chatLoading || visualLoading;
|
|
462
|
+
const [chatHistory, setChatHistory] = (0, import_react4.useState)([]);
|
|
463
|
+
const lastSyncedCount = (0, import_react4.useRef)(0);
|
|
464
|
+
(0, import_react4.useEffect)(() => {
|
|
465
|
+
if (messages.length === 0) {
|
|
466
|
+
setChatHistory([]);
|
|
467
|
+
lastSyncedCount.current = 0;
|
|
468
|
+
return;
|
|
469
|
+
}
|
|
470
|
+
if (messages.length > lastSyncedCount.current) {
|
|
471
|
+
const newMsgs = messages.slice(lastSyncedCount.current);
|
|
472
|
+
setChatHistory((prev) => [...prev, ...newMsgs]);
|
|
473
|
+
lastSyncedCount.current = messages.length;
|
|
474
|
+
} else if (messages.length < lastSyncedCount.current) {
|
|
475
|
+
setChatHistory(messages);
|
|
476
|
+
lastSyncedCount.current = messages.length;
|
|
477
|
+
} else {
|
|
478
|
+
setChatHistory((prev) => {
|
|
479
|
+
const next = [...prev];
|
|
480
|
+
let hookIdx = messages.length - 1;
|
|
481
|
+
let historyIdx = next.length - 1;
|
|
482
|
+
while (hookIdx >= 0 && historyIdx >= 0) {
|
|
483
|
+
if (next[historyIdx].role === messages[hookIdx].role) {
|
|
484
|
+
next[historyIdx] = {
|
|
485
|
+
...next[historyIdx],
|
|
486
|
+
content: messages[hookIdx].content,
|
|
487
|
+
cartSnapshot: messages[hookIdx].cartSnapshot,
|
|
488
|
+
actionType: messages[hookIdx].actionType
|
|
489
|
+
};
|
|
490
|
+
break;
|
|
491
|
+
}
|
|
492
|
+
historyIdx--;
|
|
493
|
+
}
|
|
494
|
+
return next;
|
|
495
|
+
});
|
|
496
|
+
}
|
|
497
|
+
}, [messages]);
|
|
498
|
+
(0, import_react4.useEffect)(() => {
|
|
324
499
|
bottomRef.current?.scrollIntoView({ behavior: "smooth" });
|
|
325
|
-
}, [
|
|
500
|
+
}, [chatHistory, loading]);
|
|
326
501
|
const handleSend = async () => {
|
|
327
502
|
const q = input.trim();
|
|
328
503
|
if (!q || loading) return;
|
|
@@ -342,6 +517,56 @@ function ChatWidget({
|
|
|
342
517
|
t.style.height = "auto";
|
|
343
518
|
t.style.height = Math.min(t.scrollHeight, 120) + "px";
|
|
344
519
|
};
|
|
520
|
+
const handleVisualResults = (res, preview) => {
|
|
521
|
+
const userMsg = {
|
|
522
|
+
role: "user",
|
|
523
|
+
content: "Uploaded a photo for visual search",
|
|
524
|
+
imagePreview: preview
|
|
525
|
+
};
|
|
526
|
+
const dna = res.style_dna;
|
|
527
|
+
let content = `I've analyzed your image! Here is the Style DNA I found:
|
|
528
|
+
`;
|
|
529
|
+
if (dna) {
|
|
530
|
+
if (dna.color_palette) content += `* **Palette:** ${dna.color_palette}
|
|
531
|
+
`;
|
|
532
|
+
if (dna.dominant_colors && dna.dominant_colors.length > 0) {
|
|
533
|
+
content += `* **Colors:** ${dna.dominant_colors.join(", ")}
|
|
534
|
+
`;
|
|
535
|
+
}
|
|
536
|
+
if (dna.aesthetic && dna.aesthetic.length > 0) {
|
|
537
|
+
content += `* **Aesthetic:** ${dna.aesthetic.join(", ")}
|
|
538
|
+
`;
|
|
539
|
+
}
|
|
540
|
+
if (dna.texture) content += `* **Texture:** ${dna.texture}
|
|
541
|
+
`;
|
|
542
|
+
if (dna.formality) content += `* **Formality:** ${dna.formality}
|
|
543
|
+
`;
|
|
544
|
+
}
|
|
545
|
+
const results = res.results || [];
|
|
546
|
+
if (results.length > 0) {
|
|
547
|
+
content += `
|
|
548
|
+
I found ${results.length} matching products in the store for you.`;
|
|
549
|
+
} else {
|
|
550
|
+
content += `
|
|
551
|
+
I couldn't find any matching products in the store.`;
|
|
552
|
+
}
|
|
553
|
+
const assistantMsg = {
|
|
554
|
+
role: "assistant",
|
|
555
|
+
content,
|
|
556
|
+
styleDNA: dna,
|
|
557
|
+
visualSources: results.map((r) => ({
|
|
558
|
+
id: r.id,
|
|
559
|
+
name: r.product.name,
|
|
560
|
+
price: r.product.price,
|
|
561
|
+
currency: r.product.currency,
|
|
562
|
+
category: r.product.category,
|
|
563
|
+
url: r.product.url,
|
|
564
|
+
image: r.product.images && r.product.images.length > 0 ? r.product.images[0] : void 0,
|
|
565
|
+
brand: r.product.brand
|
|
566
|
+
}))
|
|
567
|
+
};
|
|
568
|
+
setChatHistory((prev) => [...prev, userMsg, assistantMsg]);
|
|
569
|
+
};
|
|
345
570
|
const customStyles = {
|
|
346
571
|
...theme?.primaryColor && { "--hsk-primary": theme.primaryColor },
|
|
347
572
|
...theme?.backgroundColor && { "--hsk-bg": theme.backgroundColor },
|
|
@@ -349,45 +574,60 @@ function ChatWidget({
|
|
|
349
574
|
...theme?.fontFamily && { "--hsk-font": theme.fontFamily },
|
|
350
575
|
...theme?.borderRadius && { "--hsk-border-radius": theme.borderRadius }
|
|
351
576
|
};
|
|
352
|
-
return /* @__PURE__ */ (0,
|
|
577
|
+
return /* @__PURE__ */ (0, import_jsx_runtime5.jsxs)(
|
|
353
578
|
"div",
|
|
354
579
|
{
|
|
355
580
|
className: cn("hsk-chat-widget", classNames.root, className),
|
|
356
581
|
style: customStyles,
|
|
357
582
|
children: [
|
|
358
|
-
/* @__PURE__ */ (0,
|
|
359
|
-
/* @__PURE__ */ (0,
|
|
360
|
-
/* @__PURE__ */ (0,
|
|
361
|
-
/* @__PURE__ */ (0,
|
|
362
|
-
|
|
583
|
+
/* @__PURE__ */ (0, import_jsx_runtime5.jsxs)("div", { className: cn("hsk-chat-header", classNames.header), children: [
|
|
584
|
+
/* @__PURE__ */ (0, import_jsx_runtime5.jsx)("span", { className: "hsk-chat-header-icon", children: /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(SparkleIcon, {}) }),
|
|
585
|
+
/* @__PURE__ */ (0, import_jsx_runtime5.jsx)("span", { className: "hsk-chat-title", children: title }),
|
|
586
|
+
/* @__PURE__ */ (0, import_jsx_runtime5.jsx)("span", { className: "hsk-chat-badge", children: "AI" }),
|
|
587
|
+
chatHistory.length > 0 && /* @__PURE__ */ (0, import_jsx_runtime5.jsx)("button", { className: "hsk-chat-reset", onClick: reset, style: { marginLeft: "auto" }, children: "Clear" })
|
|
363
588
|
] }),
|
|
364
|
-
/* @__PURE__ */ (0,
|
|
365
|
-
|
|
366
|
-
/* @__PURE__ */ (0,
|
|
367
|
-
/* @__PURE__ */ (0,
|
|
368
|
-
/* @__PURE__ */ (0,
|
|
369
|
-
] }) :
|
|
370
|
-
/* @__PURE__ */ (0,
|
|
371
|
-
/* @__PURE__ */ (0,
|
|
372
|
-
/* @__PURE__ */ (0,
|
|
589
|
+
/* @__PURE__ */ (0, import_jsx_runtime5.jsxs)("div", { className: "hsk-chat-messages", children: [
|
|
590
|
+
chatHistory.length === 0 ? /* @__PURE__ */ (0, import_jsx_runtime5.jsxs)("div", { className: "hsk-chat-empty", children: [
|
|
591
|
+
/* @__PURE__ */ (0, import_jsx_runtime5.jsx)("div", { className: "hsk-chat-empty-icon", children: /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(SparkleIcon, {}) }),
|
|
592
|
+
/* @__PURE__ */ (0, import_jsx_runtime5.jsx)("div", { children: emptyStateText }),
|
|
593
|
+
/* @__PURE__ */ (0, import_jsx_runtime5.jsx)("div", { className: "hsk-chat-empty-suggestions", children: emptyStateSuggestions })
|
|
594
|
+
] }) : chatHistory.map((msg, idx) => /* @__PURE__ */ (0, import_jsx_runtime5.jsxs)("div", { children: [
|
|
595
|
+
/* @__PURE__ */ (0, import_jsx_runtime5.jsxs)("div", { className: `hsk-msg-row ${msg.role}`, children: [
|
|
596
|
+
/* @__PURE__ */ (0, import_jsx_runtime5.jsx)("div", { className: cn("hsk-msg-avatar", msg.role === "assistant" ? "ai" : "user"), children: msg.role === "assistant" ? /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(SparkleIcon, {}) : "U" }),
|
|
597
|
+
/* @__PURE__ */ (0, import_jsx_runtime5.jsxs)("div", { className: cn("hsk-msg-bubble", msg.role, classNames.messageBubble), children: [
|
|
598
|
+
msg.imagePreview && /* @__PURE__ */ (0, import_jsx_runtime5.jsx)("div", { className: "kiku-vs-preview-bubble", style: { marginBottom: "8px" }, children: /* @__PURE__ */ (0, import_jsx_runtime5.jsx)("img", { src: msg.imagePreview, alt: "Uploaded Preview", className: "kiku-vs-preview-bubble-img", style: { maxWidth: "200px", borderRadius: "8px" } }) }),
|
|
599
|
+
renderMarkdown(msg.content),
|
|
600
|
+
msg.styleDNA && /* @__PURE__ */ (0, import_jsx_runtime5.jsxs)("div", { className: "kiku-vs-preview-banner", style: { marginTop: "10px" }, children: [
|
|
601
|
+
chatHistory[idx - 1]?.imagePreview && /* @__PURE__ */ (0, import_jsx_runtime5.jsx)("img", { src: chatHistory[idx - 1].imagePreview, alt: "Visual Search Input", className: "kiku-vs-preview-img" }),
|
|
602
|
+
/* @__PURE__ */ (0, import_jsx_runtime5.jsxs)("div", { className: "kiku-vs-preview-info", children: [
|
|
603
|
+
/* @__PURE__ */ (0, import_jsx_runtime5.jsx)("div", { className: "kiku-vs-preview-label", children: "Visual Match Palette" }),
|
|
604
|
+
/* @__PURE__ */ (0, import_jsx_runtime5.jsx)("div", { className: "kiku-vs-preview-palette", children: msg.styleDNA.color_palette || "Detected Style DNA" }),
|
|
605
|
+
msg.styleDNA.style_tags && msg.styleDNA.style_tags.length > 0 && /* @__PURE__ */ (0, import_jsx_runtime5.jsx)("div", { className: "kiku-style-tags", children: msg.styleDNA.style_tags.map((tag, ti) => /* @__PURE__ */ (0, import_jsx_runtime5.jsxs)("span", { className: "kiku-style-tag", children: [
|
|
606
|
+
"#",
|
|
607
|
+
tag
|
|
608
|
+
] }, ti)) })
|
|
609
|
+
] })
|
|
610
|
+
] })
|
|
611
|
+
] })
|
|
373
612
|
] }),
|
|
374
|
-
msg.role === "assistant" &&
|
|
613
|
+
msg.role === "assistant" && msg.visualSources && msg.visualSources.length > 0 && /* @__PURE__ */ (0, import_jsx_runtime5.jsx)("div", { className: "hsk-sources-container", children: /* @__PURE__ */ (0, import_jsx_runtime5.jsx)("div", { className: "hsk-sources", children: msg.visualSources.map((src, si) => /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(SourceCard, { source: src, defaultCurrency, onSelect: onSelectSource }, si)) }) }),
|
|
614
|
+
msg.role === "assistant" && idx === chatHistory.length - 1 && !msg.visualSources && sources.length > 0 && /* @__PURE__ */ (0, import_jsx_runtime5.jsx)("div", { className: "hsk-sources-container", children: /* @__PURE__ */ (0, import_jsx_runtime5.jsx)("div", { className: "hsk-sources", children: sources.map((src, si) => /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(SourceCard, { source: src, defaultCurrency, onSelect: onSelectSource }, si)) }) })
|
|
375
615
|
] }, idx)),
|
|
376
|
-
loading && /* @__PURE__ */ (0,
|
|
377
|
-
/* @__PURE__ */ (0,
|
|
378
|
-
/* @__PURE__ */ (0,
|
|
379
|
-
/* @__PURE__ */ (0,
|
|
380
|
-
/* @__PURE__ */ (0,
|
|
381
|
-
/* @__PURE__ */ (0,
|
|
616
|
+
loading && /* @__PURE__ */ (0, import_jsx_runtime5.jsxs)("div", { className: "hsk-msg-row", children: [
|
|
617
|
+
/* @__PURE__ */ (0, import_jsx_runtime5.jsx)("div", { className: "hsk-msg-avatar ai", children: /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(SparkleIcon, {}) }),
|
|
618
|
+
/* @__PURE__ */ (0, import_jsx_runtime5.jsxs)("div", { className: "hsk-pending", role: "status", "aria-live": "polite", children: [
|
|
619
|
+
/* @__PURE__ */ (0, import_jsx_runtime5.jsxs)("div", { className: "hsk-pending-glyph", children: [
|
|
620
|
+
/* @__PURE__ */ (0, import_jsx_runtime5.jsx)("span", { className: "hsk-pending-ring" }),
|
|
621
|
+
/* @__PURE__ */ (0, import_jsx_runtime5.jsx)("span", { className: "hsk-pending-dot" })
|
|
382
622
|
] }),
|
|
383
|
-
/* @__PURE__ */ (0,
|
|
384
|
-
/* @__PURE__ */ (0,
|
|
385
|
-
/* @__PURE__ */ (0,
|
|
386
|
-
/* @__PURE__ */ (0,
|
|
623
|
+
/* @__PURE__ */ (0, import_jsx_runtime5.jsxs)("div", { className: "hsk-pending-text", children: [
|
|
624
|
+
/* @__PURE__ */ (0, import_jsx_runtime5.jsx)("span", { className: "hsk-pending-step step-1", children: "Searching catalog" }),
|
|
625
|
+
/* @__PURE__ */ (0, import_jsx_runtime5.jsx)("span", { className: "hsk-pending-step step-2", children: "Reasoning" }),
|
|
626
|
+
/* @__PURE__ */ (0, import_jsx_runtime5.jsx)("span", { className: "hsk-pending-step step-3", children: "Composing" })
|
|
387
627
|
] })
|
|
388
628
|
] })
|
|
389
629
|
] }),
|
|
390
|
-
error && /* @__PURE__ */ (0,
|
|
630
|
+
error && /* @__PURE__ */ (0, import_jsx_runtime5.jsx)("div", { className: "hsk-chat-error", children: (() => {
|
|
391
631
|
try {
|
|
392
632
|
const parsed = JSON.parse(error);
|
|
393
633
|
return parsed.error || parsed.message || error;
|
|
@@ -395,10 +635,19 @@ function ChatWidget({
|
|
|
395
635
|
return error;
|
|
396
636
|
}
|
|
397
637
|
})() }),
|
|
398
|
-
/* @__PURE__ */ (0,
|
|
638
|
+
/* @__PURE__ */ (0, import_jsx_runtime5.jsx)("div", { ref: bottomRef })
|
|
399
639
|
] }),
|
|
400
|
-
/* @__PURE__ */ (0,
|
|
401
|
-
/* @__PURE__ */ (0,
|
|
640
|
+
/* @__PURE__ */ (0, import_jsx_runtime5.jsxs)("div", { className: "hsk-chat-input-area", style: { display: "flex", alignItems: "center", gap: "8px" }, children: [
|
|
641
|
+
enableVision && /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(
|
|
642
|
+
VisualSearch,
|
|
643
|
+
{
|
|
644
|
+
onResults: handleVisualResults,
|
|
645
|
+
onError: (err) => console.error("[VisualSearch] error:", err),
|
|
646
|
+
categoryHint: visionCategoryHint,
|
|
647
|
+
disabled: loading
|
|
648
|
+
}
|
|
649
|
+
),
|
|
650
|
+
/* @__PURE__ */ (0, import_jsx_runtime5.jsx)(
|
|
402
651
|
"textarea",
|
|
403
652
|
{
|
|
404
653
|
ref: textareaRef,
|
|
@@ -408,17 +657,30 @@ function ChatWidget({
|
|
|
408
657
|
onKeyDown: handleKey,
|
|
409
658
|
placeholder,
|
|
410
659
|
rows: 1,
|
|
660
|
+
disabled: loading,
|
|
661
|
+
style: { flex: 1 }
|
|
662
|
+
}
|
|
663
|
+
),
|
|
664
|
+
enableVoice && /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(
|
|
665
|
+
VoiceButton,
|
|
666
|
+
{
|
|
667
|
+
onTranscript: (text) => {
|
|
668
|
+
setInput(text);
|
|
669
|
+
send(text);
|
|
670
|
+
setInput("");
|
|
671
|
+
},
|
|
672
|
+
onInterim: (text) => setInput(text),
|
|
411
673
|
disabled: loading
|
|
412
674
|
}
|
|
413
675
|
),
|
|
414
|
-
/* @__PURE__ */ (0,
|
|
676
|
+
/* @__PURE__ */ (0, import_jsx_runtime5.jsx)(
|
|
415
677
|
"button",
|
|
416
678
|
{
|
|
417
679
|
className: "hsk-chat-send",
|
|
418
680
|
onClick: handleSend,
|
|
419
681
|
disabled: !input.trim() || loading,
|
|
420
682
|
"aria-label": "Send message",
|
|
421
|
-
children: /* @__PURE__ */ (0,
|
|
683
|
+
children: /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(ArrowUpIcon, {})
|
|
422
684
|
}
|
|
423
685
|
)
|
|
424
686
|
] })
|
|
@@ -428,14 +690,14 @@ function ChatWidget({
|
|
|
428
690
|
}
|
|
429
691
|
|
|
430
692
|
// src/components/KikuButton.tsx
|
|
431
|
-
var
|
|
693
|
+
var import_react5 = require("react");
|
|
432
694
|
var import_react_dom = require("react-dom");
|
|
433
|
-
var import_sdk3 = require("@akropolys/sdk");
|
|
434
695
|
var import_sdk4 = require("@akropolys/sdk");
|
|
435
696
|
var import_sdk5 = require("@akropolys/sdk");
|
|
697
|
+
var import_sdk6 = require("@akropolys/sdk");
|
|
436
698
|
|
|
437
699
|
// src/components/ComparisonMatrix.tsx
|
|
438
|
-
var
|
|
700
|
+
var import_jsx_runtime6 = require("react/jsx-runtime");
|
|
439
701
|
function extractSize(p) {
|
|
440
702
|
const name = p.name;
|
|
441
703
|
const cat = (p.category || "").toLowerCase();
|
|
@@ -547,9 +809,9 @@ function buildRows(products, currency) {
|
|
|
547
809
|
}
|
|
548
810
|
function ImageCell({ value, name }) {
|
|
549
811
|
if (!value) {
|
|
550
|
-
return /* @__PURE__ */ (0,
|
|
812
|
+
return /* @__PURE__ */ (0, import_jsx_runtime6.jsx)("div", { style: { fontSize: 28, textAlign: "center" }, children: "\u{1F4E6}" });
|
|
551
813
|
}
|
|
552
|
-
return /* @__PURE__ */ (0,
|
|
814
|
+
return /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(
|
|
553
815
|
"img",
|
|
554
816
|
{
|
|
555
817
|
src: value,
|
|
@@ -566,10 +828,10 @@ function ImageCell({ value, name }) {
|
|
|
566
828
|
);
|
|
567
829
|
}
|
|
568
830
|
function AvailabilityCell({ value }) {
|
|
569
|
-
if (!value) return /* @__PURE__ */ (0,
|
|
831
|
+
if (!value) return /* @__PURE__ */ (0, import_jsx_runtime6.jsx)("span", { style: { color: "#9ca3af" }, children: "\u2014" });
|
|
570
832
|
const inStock = /in.?stock/i.test(value);
|
|
571
|
-
return /* @__PURE__ */ (0,
|
|
572
|
-
/* @__PURE__ */ (0,
|
|
833
|
+
return /* @__PURE__ */ (0, import_jsx_runtime6.jsxs)("span", { style: { display: "flex", alignItems: "center", gap: 6, fontSize: 13, color: "var(--hsk-text, #111827)" }, children: [
|
|
834
|
+
/* @__PURE__ */ (0, import_jsx_runtime6.jsx)("span", { style: {
|
|
573
835
|
width: 8,
|
|
574
836
|
height: 8,
|
|
575
837
|
borderRadius: "50%",
|
|
@@ -610,7 +872,7 @@ function ComparisonMatrix({ sources, defaultCurrency = "KES" }) {
|
|
|
610
872
|
display: "flex",
|
|
611
873
|
alignItems: "center"
|
|
612
874
|
};
|
|
613
|
-
return /* @__PURE__ */ (0,
|
|
875
|
+
return /* @__PURE__ */ (0, import_jsx_runtime6.jsxs)(
|
|
614
876
|
"div",
|
|
615
877
|
{
|
|
616
878
|
className: "hsk-compare-matrix",
|
|
@@ -623,9 +885,9 @@ function ComparisonMatrix({ sources, defaultCurrency = "KES" }) {
|
|
|
623
885
|
fontSize: 13
|
|
624
886
|
},
|
|
625
887
|
children: [
|
|
626
|
-
/* @__PURE__ */ (0,
|
|
627
|
-
/* @__PURE__ */ (0,
|
|
628
|
-
products.map((p, i) => /* @__PURE__ */ (0,
|
|
888
|
+
/* @__PURE__ */ (0, import_jsx_runtime6.jsxs)("div", { style: { display: "grid", gridTemplateColumns: colTemplate, background: "var(--hsk-surface2, #f9fafb)", borderBottom: "2px solid var(--hsk-border, rgba(0,0,0,0.09))" }, children: [
|
|
889
|
+
/* @__PURE__ */ (0, import_jsx_runtime6.jsx)("div", { style: { ...labelStyle, borderBottom: "none", color: "var(--hsk-text, #111)", fontSize: 12 }, children: "Feature" }),
|
|
890
|
+
products.map((p, i) => /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(
|
|
629
891
|
"a",
|
|
630
892
|
{
|
|
631
893
|
href: p.url || "#",
|
|
@@ -647,7 +909,7 @@ function ComparisonMatrix({ sources, defaultCurrency = "KES" }) {
|
|
|
647
909
|
i
|
|
648
910
|
))
|
|
649
911
|
] }),
|
|
650
|
-
rows.map((row, rowIdx) => /* @__PURE__ */ (0,
|
|
912
|
+
rows.map((row, rowIdx) => /* @__PURE__ */ (0, import_jsx_runtime6.jsxs)(
|
|
651
913
|
"div",
|
|
652
914
|
{
|
|
653
915
|
style: {
|
|
@@ -656,17 +918,17 @@ function ComparisonMatrix({ sources, defaultCurrency = "KES" }) {
|
|
|
656
918
|
background: rowIdx % 2 === 1 ? "var(--hsk-surface2, rgba(0,0,0,0.015))" : "transparent"
|
|
657
919
|
},
|
|
658
920
|
children: [
|
|
659
|
-
/* @__PURE__ */ (0,
|
|
921
|
+
/* @__PURE__ */ (0, import_jsx_runtime6.jsx)("div", { style: labelStyle, children: row.label }),
|
|
660
922
|
products.map((p, i) => {
|
|
661
923
|
const val = row.values[i];
|
|
662
924
|
const isBest = row.bestIdx === i && row.values.filter(Boolean).length > 1;
|
|
663
925
|
if (row.type === "image") {
|
|
664
|
-
return /* @__PURE__ */ (0,
|
|
926
|
+
return /* @__PURE__ */ (0, import_jsx_runtime6.jsx)("div", { style: { ...cellBase, justifyContent: "center", padding: "12px", borderLeft: i > 0 ? "1px solid var(--hsk-border, rgba(0,0,0,0.07))" : "none" }, children: /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(ImageCell, { value: val, name: p.name }) }, i);
|
|
665
927
|
}
|
|
666
928
|
if (row.type === "availability") {
|
|
667
|
-
return /* @__PURE__ */ (0,
|
|
929
|
+
return /* @__PURE__ */ (0, import_jsx_runtime6.jsx)("div", { style: { ...cellBase, borderLeft: i > 0 ? "1px solid var(--hsk-border, rgba(0,0,0,0.07))" : "none" }, children: /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(AvailabilityCell, { value: val }) }, i);
|
|
668
930
|
}
|
|
669
|
-
return /* @__PURE__ */ (0,
|
|
931
|
+
return /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(
|
|
670
932
|
"div",
|
|
671
933
|
{
|
|
672
934
|
style: {
|
|
@@ -676,7 +938,7 @@ function ComparisonMatrix({ sources, defaultCurrency = "KES" }) {
|
|
|
676
938
|
color: isBest ? "var(--hsk-primary, #ea580c)" : row.type === "price" ? "var(--hsk-text, #374151)" : "var(--hsk-text, #111827)",
|
|
677
939
|
borderLeft: i > 0 ? "1px solid var(--hsk-border, rgba(0,0,0,0.07))" : "none"
|
|
678
940
|
},
|
|
679
|
-
children: val ?? /* @__PURE__ */ (0,
|
|
941
|
+
children: val ?? /* @__PURE__ */ (0, import_jsx_runtime6.jsx)("span", { style: { color: "#9ca3af" }, children: "\u2014" })
|
|
680
942
|
},
|
|
681
943
|
i
|
|
682
944
|
);
|
|
@@ -691,8 +953,8 @@ function ComparisonMatrix({ sources, defaultCurrency = "KES" }) {
|
|
|
691
953
|
}
|
|
692
954
|
|
|
693
955
|
// src/components/KikuButton.tsx
|
|
694
|
-
var
|
|
695
|
-
var AkropolysAIcon = ({ className, size = 18 }) => /* @__PURE__ */ (0,
|
|
956
|
+
var import_jsx_runtime7 = require("react/jsx-runtime");
|
|
957
|
+
var AkropolysAIcon = ({ className, size = 18 }) => /* @__PURE__ */ (0, import_jsx_runtime7.jsxs)(
|
|
696
958
|
"svg",
|
|
697
959
|
{
|
|
698
960
|
className: cn("hsk-brand-a", className),
|
|
@@ -703,7 +965,7 @@ var AkropolysAIcon = ({ className, size = 18 }) => /* @__PURE__ */ (0, import_js
|
|
|
703
965
|
xmlns: "http://www.w3.org/2000/svg",
|
|
704
966
|
"aria-label": "Akropolys",
|
|
705
967
|
children: [
|
|
706
|
-
/* @__PURE__ */ (0,
|
|
968
|
+
/* @__PURE__ */ (0, import_jsx_runtime7.jsx)(
|
|
707
969
|
"path",
|
|
708
970
|
{
|
|
709
971
|
d: "M14.5 4.5 L6.5 25",
|
|
@@ -712,7 +974,7 @@ var AkropolysAIcon = ({ className, size = 18 }) => /* @__PURE__ */ (0, import_js
|
|
|
712
974
|
strokeLinecap: "round"
|
|
713
975
|
}
|
|
714
976
|
),
|
|
715
|
-
/* @__PURE__ */ (0,
|
|
977
|
+
/* @__PURE__ */ (0, import_jsx_runtime7.jsx)(
|
|
716
978
|
"path",
|
|
717
979
|
{
|
|
718
980
|
d: "M14.5 4.5 L22.5 25",
|
|
@@ -721,7 +983,7 @@ var AkropolysAIcon = ({ className, size = 18 }) => /* @__PURE__ */ (0, import_js
|
|
|
721
983
|
strokeLinecap: "round"
|
|
722
984
|
}
|
|
723
985
|
),
|
|
724
|
-
/* @__PURE__ */ (0,
|
|
986
|
+
/* @__PURE__ */ (0, import_jsx_runtime7.jsx)(
|
|
725
987
|
"path",
|
|
726
988
|
{
|
|
727
989
|
d: "M9.5 17 H19.5",
|
|
@@ -730,7 +992,7 @@ var AkropolysAIcon = ({ className, size = 18 }) => /* @__PURE__ */ (0, import_js
|
|
|
730
992
|
strokeLinecap: "round"
|
|
731
993
|
}
|
|
732
994
|
),
|
|
733
|
-
/* @__PURE__ */ (0,
|
|
995
|
+
/* @__PURE__ */ (0, import_jsx_runtime7.jsx)(
|
|
734
996
|
"path",
|
|
735
997
|
{
|
|
736
998
|
d: "M3 25 H10",
|
|
@@ -739,7 +1001,7 @@ var AkropolysAIcon = ({ className, size = 18 }) => /* @__PURE__ */ (0, import_js
|
|
|
739
1001
|
strokeLinecap: "round"
|
|
740
1002
|
}
|
|
741
1003
|
),
|
|
742
|
-
/* @__PURE__ */ (0,
|
|
1004
|
+
/* @__PURE__ */ (0, import_jsx_runtime7.jsx)(
|
|
743
1005
|
"path",
|
|
744
1006
|
{
|
|
745
1007
|
d: "M19 25 H26",
|
|
@@ -748,7 +1010,7 @@ var AkropolysAIcon = ({ className, size = 18 }) => /* @__PURE__ */ (0, import_js
|
|
|
748
1010
|
strokeLinecap: "round"
|
|
749
1011
|
}
|
|
750
1012
|
),
|
|
751
|
-
/* @__PURE__ */ (0,
|
|
1013
|
+
/* @__PURE__ */ (0, import_jsx_runtime7.jsx)(
|
|
752
1014
|
"path",
|
|
753
1015
|
{
|
|
754
1016
|
d: "M8.5 2.5 C10 2.5, 11 3.5, 11 5 C11 7, 8.5 8.5, 7.5 9.5",
|
|
@@ -763,25 +1025,39 @@ var AkropolysAIcon = ({ className, size = 18 }) => /* @__PURE__ */ (0, import_js
|
|
|
763
1025
|
}
|
|
764
1026
|
);
|
|
765
1027
|
var SparkleIcon2 = AkropolysAIcon;
|
|
766
|
-
var ArrowUpIcon2 = () => /* @__PURE__ */ (0,
|
|
767
|
-
/* @__PURE__ */ (0,
|
|
768
|
-
/* @__PURE__ */ (0,
|
|
1028
|
+
var ArrowUpIcon2 = () => /* @__PURE__ */ (0, import_jsx_runtime7.jsxs)("svg", { width: "18", height: "18", viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "2", strokeLinecap: "round", strokeLinejoin: "round", children: [
|
|
1029
|
+
/* @__PURE__ */ (0, import_jsx_runtime7.jsx)("path", { d: "m5 12 7-7 7 7" }),
|
|
1030
|
+
/* @__PURE__ */ (0, import_jsx_runtime7.jsx)("path", { d: "M12 19V5" })
|
|
769
1031
|
] });
|
|
770
|
-
var CloseIcon = () => /* @__PURE__ */ (0,
|
|
771
|
-
/* @__PURE__ */ (0,
|
|
772
|
-
/* @__PURE__ */ (0,
|
|
1032
|
+
var CloseIcon = () => /* @__PURE__ */ (0, import_jsx_runtime7.jsxs)("svg", { width: "16", height: "16", viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "2.5", strokeLinecap: "round", strokeLinejoin: "round", children: [
|
|
1033
|
+
/* @__PURE__ */ (0, import_jsx_runtime7.jsx)("line", { x1: "18", y1: "6", x2: "6", y2: "18" }),
|
|
1034
|
+
/* @__PURE__ */ (0, import_jsx_runtime7.jsx)("line", { x1: "6", y1: "6", x2: "18", y2: "18" })
|
|
773
1035
|
] });
|
|
774
|
-
var ChevronRightIcon = () => /* @__PURE__ */ (0,
|
|
775
|
-
var HistoryIcon = () => /* @__PURE__ */ (0,
|
|
776
|
-
/* @__PURE__ */ (0,
|
|
777
|
-
/* @__PURE__ */ (0,
|
|
778
|
-
/* @__PURE__ */ (0,
|
|
1036
|
+
var ChevronRightIcon = () => /* @__PURE__ */ (0, import_jsx_runtime7.jsx)("svg", { width: "16", height: "16", viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "2", strokeLinecap: "round", strokeLinejoin: "round", children: /* @__PURE__ */ (0, import_jsx_runtime7.jsx)("path", { d: "m9 18 6-6-6-6" }) });
|
|
1037
|
+
var HistoryIcon = () => /* @__PURE__ */ (0, import_jsx_runtime7.jsxs)("svg", { width: "16", height: "16", viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "2", strokeLinecap: "round", strokeLinejoin: "round", children: [
|
|
1038
|
+
/* @__PURE__ */ (0, import_jsx_runtime7.jsx)("path", { d: "M3 12a9 9 0 1 0 9-9 9.75 9.75 0 0 0-6.74 2.74L3 8" }),
|
|
1039
|
+
/* @__PURE__ */ (0, import_jsx_runtime7.jsx)("path", { d: "M3 3v5h5" }),
|
|
1040
|
+
/* @__PURE__ */ (0, import_jsx_runtime7.jsx)("path", { d: "M12 7v5l4 2" })
|
|
779
1041
|
] });
|
|
780
|
-
var NewChatIcon = () => /* @__PURE__ */ (0,
|
|
781
|
-
var ShoppingBagIcon = () => /* @__PURE__ */ (0,
|
|
782
|
-
/* @__PURE__ */ (0,
|
|
783
|
-
/* @__PURE__ */ (0,
|
|
784
|
-
/* @__PURE__ */ (0,
|
|
1042
|
+
var NewChatIcon = () => /* @__PURE__ */ (0, import_jsx_runtime7.jsx)("svg", { width: "14", height: "14", viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "2", strokeLinecap: "round", strokeLinejoin: "round", children: /* @__PURE__ */ (0, import_jsx_runtime7.jsx)("path", { d: "M12 5v14M5 12h14" }) });
|
|
1043
|
+
var ShoppingBagIcon = () => /* @__PURE__ */ (0, import_jsx_runtime7.jsxs)("svg", { width: "13", height: "13", viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "2", strokeLinecap: "round", strokeLinejoin: "round", children: [
|
|
1044
|
+
/* @__PURE__ */ (0, import_jsx_runtime7.jsx)("path", { d: "M6 2 3 6v14a2 2 0 0 0 2 2h14a2 2 0 0 0 2-2V6l-3-4z" }),
|
|
1045
|
+
/* @__PURE__ */ (0, import_jsx_runtime7.jsx)("line", { x1: "3", y1: "6", x2: "21", y2: "6" }),
|
|
1046
|
+
/* @__PURE__ */ (0, import_jsx_runtime7.jsx)("path", { d: "M16 10a4 4 0 0 1-8 0" })
|
|
1047
|
+
] });
|
|
1048
|
+
var PaperclipIcon = () => /* @__PURE__ */ (0, import_jsx_runtime7.jsx)("svg", { width: "16", height: "16", viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "2", strokeLinecap: "round", strokeLinejoin: "round", children: /* @__PURE__ */ (0, import_jsx_runtime7.jsx)("path", { d: "m21.44 11.05-9.19 9.19a6 6 0 0 1-8.49-8.49l8.57-8.57A4 4 0 1 1 18 8.84l-8.59 8.57a2 2 0 0 1-2.83-2.83l8.49-8.48" }) });
|
|
1049
|
+
var MicIcon2 = () => /* @__PURE__ */ (0, import_jsx_runtime7.jsxs)("svg", { width: "16", height: "16", viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "2", strokeLinecap: "round", strokeLinejoin: "round", children: [
|
|
1050
|
+
/* @__PURE__ */ (0, import_jsx_runtime7.jsx)("path", { d: "M12 2a3 3 0 0 0-3 3v7a3 3 0 0 0 6 0V5a3 3 0 0 0-3-3z" }),
|
|
1051
|
+
/* @__PURE__ */ (0, import_jsx_runtime7.jsx)("path", { d: "M19 10v2a7 7 0 0 1-14 0v-2" }),
|
|
1052
|
+
/* @__PURE__ */ (0, import_jsx_runtime7.jsx)("line", { x1: "12", y1: "19", x2: "12", y2: "22" })
|
|
1053
|
+
] });
|
|
1054
|
+
var MicOffIcon = () => /* @__PURE__ */ (0, import_jsx_runtime7.jsxs)("svg", { width: "16", height: "16", viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "2", strokeLinecap: "round", strokeLinejoin: "round", children: [
|
|
1055
|
+
/* @__PURE__ */ (0, import_jsx_runtime7.jsx)("line", { x1: "2", y1: "2", x2: "22", y2: "22" }),
|
|
1056
|
+
/* @__PURE__ */ (0, import_jsx_runtime7.jsx)("path", { d: "M18.89 13.23A7.12 7.12 0 0 0 19 12v-2" }),
|
|
1057
|
+
/* @__PURE__ */ (0, import_jsx_runtime7.jsx)("path", { d: "M5 10v2a7 7 0 0 0 12 5" }),
|
|
1058
|
+
/* @__PURE__ */ (0, import_jsx_runtime7.jsx)("path", { d: "M15 9.34V5a3 3 0 0 0-5.68-1.33" }),
|
|
1059
|
+
/* @__PURE__ */ (0, import_jsx_runtime7.jsx)("path", { d: "M9 9v3a3 3 0 0 0 5.12 2.12" }),
|
|
1060
|
+
/* @__PURE__ */ (0, import_jsx_runtime7.jsx)("line", { x1: "12", y1: "19", x2: "12", y2: "22" })
|
|
785
1061
|
] });
|
|
786
1062
|
var DEFAULT_CHIPS = [
|
|
787
1063
|
"Cheapest smartphone",
|
|
@@ -821,25 +1097,25 @@ function CartContextCard({ cart, defaultCurrency }) {
|
|
|
821
1097
|
if (!cart.items || cart.items.length === 0) return null;
|
|
822
1098
|
const currency = cart.currency || defaultCurrency;
|
|
823
1099
|
const total = cart.total ?? cart.items.reduce((s, i) => s + i.price_numeric * i.quantity, 0);
|
|
824
|
-
return /* @__PURE__ */ (0,
|
|
825
|
-
/* @__PURE__ */ (0,
|
|
826
|
-
/* @__PURE__ */ (0,
|
|
827
|
-
/* @__PURE__ */ (0,
|
|
1100
|
+
return /* @__PURE__ */ (0, import_jsx_runtime7.jsxs)("div", { className: "hsk-cart-card", children: [
|
|
1101
|
+
/* @__PURE__ */ (0, import_jsx_runtime7.jsxs)("div", { className: "hsk-cart-card-header", children: [
|
|
1102
|
+
/* @__PURE__ */ (0, import_jsx_runtime7.jsx)(ShoppingBagIcon, {}),
|
|
1103
|
+
/* @__PURE__ */ (0, import_jsx_runtime7.jsxs)("span", { children: [
|
|
828
1104
|
"Your cart \xB7 ",
|
|
829
1105
|
cart.item_count ?? cart.items.length,
|
|
830
1106
|
" item",
|
|
831
1107
|
(cart.item_count ?? cart.items.length) !== 1 ? "s" : ""
|
|
832
1108
|
] })
|
|
833
1109
|
] }),
|
|
834
|
-
/* @__PURE__ */ (0,
|
|
835
|
-
/* @__PURE__ */ (0,
|
|
836
|
-
item.image ? /* @__PURE__ */ (0,
|
|
837
|
-
item.quantity > 1 && /* @__PURE__ */ (0,
|
|
1110
|
+
/* @__PURE__ */ (0, import_jsx_runtime7.jsx)("div", { className: "hsk-cart-items", children: cart.items.map((item) => /* @__PURE__ */ (0, import_jsx_runtime7.jsxs)("div", { className: "hsk-cart-item", children: [
|
|
1111
|
+
/* @__PURE__ */ (0, import_jsx_runtime7.jsxs)("div", { className: "hsk-cart-item-img-wrap", children: [
|
|
1112
|
+
item.image ? /* @__PURE__ */ (0, import_jsx_runtime7.jsx)("img", { className: "hsk-cart-item-img", src: item.image, alt: item.name, loading: "lazy" }) : /* @__PURE__ */ (0, import_jsx_runtime7.jsx)("div", { className: "hsk-cart-item-img-placeholder", children: /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(ShoppingBagIcon, {}) }),
|
|
1113
|
+
item.quantity > 1 && /* @__PURE__ */ (0, import_jsx_runtime7.jsx)("span", { className: "hsk-cart-item-qty", children: item.quantity })
|
|
838
1114
|
] }),
|
|
839
|
-
/* @__PURE__ */ (0,
|
|
840
|
-
/* @__PURE__ */ (0,
|
|
841
|
-
/* @__PURE__ */ (0,
|
|
842
|
-
item.quantity > 1 && /* @__PURE__ */ (0,
|
|
1115
|
+
/* @__PURE__ */ (0, import_jsx_runtime7.jsxs)("div", { className: "hsk-cart-item-info", children: [
|
|
1116
|
+
/* @__PURE__ */ (0, import_jsx_runtime7.jsx)("div", { className: "hsk-cart-item-name", children: item.name }),
|
|
1117
|
+
/* @__PURE__ */ (0, import_jsx_runtime7.jsxs)("div", { className: "hsk-cart-item-price", children: [
|
|
1118
|
+
item.quantity > 1 && /* @__PURE__ */ (0, import_jsx_runtime7.jsxs)("span", { className: "hsk-cart-item-qty-label", children: [
|
|
843
1119
|
item.quantity,
|
|
844
1120
|
"\xD7 "
|
|
845
1121
|
] }),
|
|
@@ -849,9 +1125,9 @@ function CartContextCard({ cart, defaultCurrency }) {
|
|
|
849
1125
|
] })
|
|
850
1126
|
] })
|
|
851
1127
|
] }, item.id)) }),
|
|
852
|
-
/* @__PURE__ */ (0,
|
|
853
|
-
/* @__PURE__ */ (0,
|
|
854
|
-
/* @__PURE__ */ (0,
|
|
1128
|
+
/* @__PURE__ */ (0, import_jsx_runtime7.jsxs)("div", { className: "hsk-cart-total", children: [
|
|
1129
|
+
/* @__PURE__ */ (0, import_jsx_runtime7.jsx)("span", { children: "Total" }),
|
|
1130
|
+
/* @__PURE__ */ (0, import_jsx_runtime7.jsxs)("span", { className: "hsk-cart-total-amount", children: [
|
|
855
1131
|
currency,
|
|
856
1132
|
" ",
|
|
857
1133
|
total.toLocaleString()
|
|
@@ -883,14 +1159,14 @@ function ActionPills({ cart, actionType, onSend, loading }) {
|
|
|
883
1159
|
}
|
|
884
1160
|
}
|
|
885
1161
|
if (pills.length === 0) return null;
|
|
886
|
-
return /* @__PURE__ */ (0,
|
|
1162
|
+
return /* @__PURE__ */ (0, import_jsx_runtime7.jsx)("div", { className: "hsk-action-pills", children: pills.map((pill) => /* @__PURE__ */ (0, import_jsx_runtime7.jsxs)(
|
|
887
1163
|
"button",
|
|
888
1164
|
{
|
|
889
1165
|
className: "hsk-action-pill",
|
|
890
1166
|
onClick: () => onSend(pill.query),
|
|
891
1167
|
disabled: loading,
|
|
892
1168
|
children: [
|
|
893
|
-
/* @__PURE__ */ (0,
|
|
1169
|
+
/* @__PURE__ */ (0, import_jsx_runtime7.jsx)("span", { className: "hsk-pill-emoji", children: pill.emoji }),
|
|
894
1170
|
pill.label
|
|
895
1171
|
]
|
|
896
1172
|
},
|
|
@@ -898,17 +1174,17 @@ function ActionPills({ cart, actionType, onSend, loading }) {
|
|
|
898
1174
|
)) });
|
|
899
1175
|
}
|
|
900
1176
|
function SourcesCarousel({ sources, defaultCurrency, onSelectSource }) {
|
|
901
|
-
const client = (0,
|
|
1177
|
+
const client = (0, import_sdk6.useAkropolysContext)();
|
|
902
1178
|
const isProperty = client?.vertical === "property";
|
|
903
|
-
const railRef = (0,
|
|
904
|
-
const [showNext, setShowNext] = (0,
|
|
905
|
-
const measure = (0,
|
|
1179
|
+
const railRef = (0, import_react5.useRef)(null);
|
|
1180
|
+
const [showNext, setShowNext] = (0, import_react5.useState)(false);
|
|
1181
|
+
const measure = (0, import_react5.useCallback)(() => {
|
|
906
1182
|
const el = railRef.current;
|
|
907
1183
|
if (!el) return;
|
|
908
1184
|
const atEnd = el.scrollLeft + el.clientWidth >= el.scrollWidth - 8;
|
|
909
1185
|
setShowNext(el.scrollWidth > el.clientWidth + 4 && !atEnd);
|
|
910
1186
|
}, []);
|
|
911
|
-
(0,
|
|
1187
|
+
(0, import_react5.useEffect)(() => {
|
|
912
1188
|
measure();
|
|
913
1189
|
const el = railRef.current;
|
|
914
1190
|
if (!el) return;
|
|
@@ -923,17 +1199,17 @@ function SourcesCarousel({ sources, defaultCurrency, onSelectSource }) {
|
|
|
923
1199
|
const scrollNext = () => {
|
|
924
1200
|
railRef.current?.scrollBy({ left: 170, behavior: "smooth" });
|
|
925
1201
|
};
|
|
926
|
-
return /* @__PURE__ */ (0,
|
|
927
|
-
/* @__PURE__ */ (0,
|
|
1202
|
+
return /* @__PURE__ */ (0, import_jsx_runtime7.jsxs)("div", { className: "hsk-cb-sources-wrap", children: [
|
|
1203
|
+
/* @__PURE__ */ (0, import_jsx_runtime7.jsx)("div", { className: "hsk-cb-sources", ref: railRef, children: sources.map((src, si) => /* @__PURE__ */ (0, import_jsx_runtime7.jsxs)(
|
|
928
1204
|
"div",
|
|
929
1205
|
{
|
|
930
1206
|
className: "hsk-cb-source",
|
|
931
1207
|
style: { animationDelay: `${si * 50}ms` },
|
|
932
1208
|
onClick: () => onSelectSource?.(src),
|
|
933
1209
|
children: [
|
|
934
|
-
src.image ? /* @__PURE__ */ (0,
|
|
935
|
-
/* @__PURE__ */ (0,
|
|
936
|
-
isProperty && /* @__PURE__ */ (0,
|
|
1210
|
+
src.image ? /* @__PURE__ */ (0, import_jsx_runtime7.jsxs)("div", { className: "hsk-cb-src-imgwrap", style: { position: "relative" }, children: [
|
|
1211
|
+
/* @__PURE__ */ (0, import_jsx_runtime7.jsx)("img", { src: src.image, alt: src.name, loading: "lazy" }),
|
|
1212
|
+
isProperty && /* @__PURE__ */ (0, import_jsx_runtime7.jsx)("div", { style: {
|
|
937
1213
|
position: "absolute",
|
|
938
1214
|
top: "6px",
|
|
939
1215
|
right: "6px",
|
|
@@ -948,11 +1224,11 @@ function SourcesCarousel({ sources, defaultCurrency, onSelectSource }) {
|
|
|
948
1224
|
color: "#fbbf24",
|
|
949
1225
|
// Gold sparkle badge
|
|
950
1226
|
boxShadow: "0 2px 4px rgba(0,0,0,0.2)"
|
|
951
|
-
}, children: /* @__PURE__ */ (0,
|
|
952
|
-
] }) : /* @__PURE__ */ (0,
|
|
953
|
-
/* @__PURE__ */ (0,
|
|
954
|
-
/* @__PURE__ */ (0,
|
|
955
|
-
src.price && /* @__PURE__ */ (0,
|
|
1227
|
+
}, children: /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(SparkleIcon2, { size: 12 }) })
|
|
1228
|
+
] }) : /* @__PURE__ */ (0, import_jsx_runtime7.jsx)("div", { className: "hsk-cb-src-imgwrap-empty", children: /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(SparkleIcon2, {}) }),
|
|
1229
|
+
/* @__PURE__ */ (0, import_jsx_runtime7.jsxs)("div", { className: "hsk-cb-src-info", children: [
|
|
1230
|
+
/* @__PURE__ */ (0, import_jsx_runtime7.jsx)("div", { className: "hsk-cb-src-name", children: src.name }),
|
|
1231
|
+
src.price && /* @__PURE__ */ (0, import_jsx_runtime7.jsxs)("div", { className: "hsk-cb-src-price", children: [
|
|
956
1232
|
src.currency ?? defaultCurrency,
|
|
957
1233
|
" ",
|
|
958
1234
|
parseFloat(String(src.price).replace(/[^0-9.]/g, "") || "0").toLocaleString()
|
|
@@ -962,15 +1238,15 @@ function SourcesCarousel({ sources, defaultCurrency, onSelectSource }) {
|
|
|
962
1238
|
},
|
|
963
1239
|
si
|
|
964
1240
|
)) }),
|
|
965
|
-
showNext && /* @__PURE__ */ (0,
|
|
966
|
-
/* @__PURE__ */ (0,
|
|
1241
|
+
showNext && /* @__PURE__ */ (0, import_jsx_runtime7.jsxs)(import_jsx_runtime7.Fragment, { children: [
|
|
1242
|
+
/* @__PURE__ */ (0, import_jsx_runtime7.jsx)(
|
|
967
1243
|
"div",
|
|
968
1244
|
{
|
|
969
1245
|
className: "hsk-cb-sources-fade",
|
|
970
1246
|
style: { background: "linear-gradient(to right, transparent, var(--hsk-fade-bg, #0e0e0f))" }
|
|
971
1247
|
}
|
|
972
1248
|
),
|
|
973
|
-
/* @__PURE__ */ (0,
|
|
1249
|
+
/* @__PURE__ */ (0, import_jsx_runtime7.jsx)("button", { className: "hsk-cb-sources-next", onClick: scrollNext, "aria-label": "See more", children: /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(ChevronRightIcon, {}) })
|
|
974
1250
|
] })
|
|
975
1251
|
] });
|
|
976
1252
|
}
|
|
@@ -989,7 +1265,7 @@ function SmartContextPills({
|
|
|
989
1265
|
onSend,
|
|
990
1266
|
loading
|
|
991
1267
|
}) {
|
|
992
|
-
const client = (0,
|
|
1268
|
+
const client = (0, import_sdk6.useAkropolysContext)();
|
|
993
1269
|
const isProperty = client?.vertical === "property";
|
|
994
1270
|
if (!intent) return null;
|
|
995
1271
|
const pills = [];
|
|
@@ -1058,14 +1334,14 @@ function SmartContextPills({
|
|
|
1058
1334
|
pills.push({ emoji: "\u{1F4A1}", label: "Recommend something", query: "What do you recommend for me?" });
|
|
1059
1335
|
}
|
|
1060
1336
|
if (pills.length === 0) return null;
|
|
1061
|
-
return /* @__PURE__ */ (0,
|
|
1337
|
+
return /* @__PURE__ */ (0, import_jsx_runtime7.jsx)("div", { className: "hsk-action-pills", children: pills.map((pill) => /* @__PURE__ */ (0, import_jsx_runtime7.jsxs)(
|
|
1062
1338
|
"button",
|
|
1063
1339
|
{
|
|
1064
1340
|
className: "hsk-action-pill",
|
|
1065
1341
|
onClick: () => onSend(pill.query),
|
|
1066
1342
|
disabled: loading,
|
|
1067
1343
|
children: [
|
|
1068
|
-
/* @__PURE__ */ (0,
|
|
1344
|
+
/* @__PURE__ */ (0, import_jsx_runtime7.jsx)("span", { className: "hsk-pill-emoji", children: pill.emoji }),
|
|
1069
1345
|
pill.label
|
|
1070
1346
|
]
|
|
1071
1347
|
},
|
|
@@ -1124,17 +1400,71 @@ function ChatModal({
|
|
|
1124
1400
|
defaultCurrency = "KES",
|
|
1125
1401
|
chips = DEFAULT_CHIPS,
|
|
1126
1402
|
theme,
|
|
1127
|
-
classNames = {}
|
|
1403
|
+
classNames = {},
|
|
1404
|
+
enableVoice = false,
|
|
1405
|
+
enableVision = false,
|
|
1406
|
+
visionCategoryHint
|
|
1128
1407
|
}) {
|
|
1129
|
-
const client = (0,
|
|
1130
|
-
const { messages, sources, loading, streaming, error, lastAction, lastIntent, send, reset } = (0,
|
|
1131
|
-
const [input, setInput] = (0,
|
|
1132
|
-
const [loadingMessageIndex, setLoadingMessageIndex] = (0,
|
|
1408
|
+
const client = (0, import_sdk6.useAkropolysContext)();
|
|
1409
|
+
const { messages, sources, loading, streaming, error, lastAction, lastIntent, send, reset } = (0, import_sdk4.useKiku)();
|
|
1410
|
+
const [input, setInput] = (0, import_react5.useState)("");
|
|
1411
|
+
const [loadingMessageIndex, setLoadingMessageIndex] = (0, import_react5.useState)(0);
|
|
1412
|
+
const [attachments, setAttachments] = (0, import_react5.useState)([]);
|
|
1413
|
+
const imageInputRef = (0, import_react5.useRef)(null);
|
|
1414
|
+
const handleImageFiles = (files) => {
|
|
1415
|
+
if (!files || files.length === 0) return;
|
|
1416
|
+
Array.from(files).forEach((file) => {
|
|
1417
|
+
if (!file.type.startsWith("image/")) return;
|
|
1418
|
+
const reader = new FileReader();
|
|
1419
|
+
reader.onload = (e) => {
|
|
1420
|
+
const dataUrl = e.target?.result;
|
|
1421
|
+
if (dataUrl) {
|
|
1422
|
+
setAttachments((prev) => [...prev, { type: "image", data: dataUrl }]);
|
|
1423
|
+
}
|
|
1424
|
+
};
|
|
1425
|
+
reader.readAsDataURL(file);
|
|
1426
|
+
});
|
|
1427
|
+
};
|
|
1428
|
+
const removeAttachment = (idx) => {
|
|
1429
|
+
setAttachments((prev) => prev.filter((_, i) => i !== idx));
|
|
1430
|
+
};
|
|
1431
|
+
const [voiceState, setVoiceState] = (0, import_react5.useState)("idle");
|
|
1432
|
+
const recognitionRef = (0, import_react5.useRef)(null);
|
|
1433
|
+
const pendingVoiceRef = (0, import_react5.useRef)(null);
|
|
1434
|
+
const hasSpeechAPI = typeof window !== "undefined" && ("SpeechRecognition" in window || "webkitSpeechRecognition" in window);
|
|
1435
|
+
const startVoice = (0, import_react5.useCallback)(() => {
|
|
1436
|
+
if (!hasSpeechAPI || voiceState !== "idle") return;
|
|
1437
|
+
const SR = window.SpeechRecognition || window.webkitSpeechRecognition;
|
|
1438
|
+
const recognition = new SR();
|
|
1439
|
+
recognition.lang = "en-US";
|
|
1440
|
+
recognition.interimResults = false;
|
|
1441
|
+
recognition.maxAlternatives = 1;
|
|
1442
|
+
recognitionRef.current = recognition;
|
|
1443
|
+
recognition.onstart = () => setVoiceState("listening");
|
|
1444
|
+
recognition.onresult = (event) => {
|
|
1445
|
+
const transcript = event.results[0][0].transcript;
|
|
1446
|
+
setInput(transcript);
|
|
1447
|
+
pendingVoiceRef.current = transcript;
|
|
1448
|
+
setVoiceState("processing");
|
|
1449
|
+
};
|
|
1450
|
+
recognition.onerror = () => setVoiceState("idle");
|
|
1451
|
+
recognition.onend = () => {
|
|
1452
|
+
setVoiceState((prev) => prev === "listening" ? "idle" : prev);
|
|
1453
|
+
};
|
|
1454
|
+
recognition.start();
|
|
1455
|
+
}, [hasSpeechAPI, voiceState]);
|
|
1456
|
+
const stopVoice = (0, import_react5.useCallback)(() => {
|
|
1457
|
+
recognitionRef.current?.stop();
|
|
1458
|
+
setVoiceState("idle");
|
|
1459
|
+
}, []);
|
|
1460
|
+
(0, import_react5.useEffect)(() => {
|
|
1461
|
+
return () => recognitionRef.current?.abort();
|
|
1462
|
+
}, []);
|
|
1133
1463
|
const isProperty = client.vertical === "property";
|
|
1134
1464
|
const activeChips = chips === DEFAULT_CHIPS && isProperty ? PROPERTY_CHIPS : chips;
|
|
1135
1465
|
const activeTitle = title === "Shopping Assistant" && isProperty ? "Property Assistant" : title;
|
|
1136
1466
|
const activePlaceholder = placeholder === "Ask me anything \u2014 gifts, budget, use case\u2026" && isProperty ? "Ask me anything \u2014 location, budget, bedrooms\u2026" : placeholder;
|
|
1137
|
-
(0,
|
|
1467
|
+
(0, import_react5.useEffect)(() => {
|
|
1138
1468
|
if (loading && !streaming) {
|
|
1139
1469
|
const interval = setInterval(() => {
|
|
1140
1470
|
setLoadingMessageIndex((prev) => (prev + 1) % LOADING_MESSAGES.length);
|
|
@@ -1144,21 +1474,21 @@ function ChatModal({
|
|
|
1144
1474
|
setLoadingMessageIndex(0);
|
|
1145
1475
|
}
|
|
1146
1476
|
}, [loading, streaming]);
|
|
1147
|
-
const [selectedProduct, setSelectedProduct] = (0,
|
|
1148
|
-
const bottomRef = (0,
|
|
1149
|
-
const textareaRef = (0,
|
|
1150
|
-
const [phoneInput, setPhoneInput] = (0,
|
|
1477
|
+
const [selectedProduct, setSelectedProduct] = (0, import_react5.useState)(null);
|
|
1478
|
+
const bottomRef = (0, import_react5.useRef)(null);
|
|
1479
|
+
const textareaRef = (0, import_react5.useRef)(null);
|
|
1480
|
+
const [phoneInput, setPhoneInput] = (0, import_react5.useState)(() => {
|
|
1151
1481
|
if (typeof window !== "undefined") {
|
|
1152
1482
|
return localStorage.getItem("akropolys_user_phone") || "";
|
|
1153
1483
|
}
|
|
1154
1484
|
return "";
|
|
1155
1485
|
});
|
|
1156
|
-
const [merchantRef, setMerchantRef] = (0,
|
|
1157
|
-
const [paymentPhase, setPaymentPhase] = (0,
|
|
1158
|
-
const [sessions, setSessions] = (0,
|
|
1159
|
-
const [sidebarOpen, setSidebarOpen] = (0,
|
|
1160
|
-
const [replayMessages, setReplayMessages] = (0,
|
|
1161
|
-
const { status: pollStatus } = (0,
|
|
1486
|
+
const [merchantRef, setMerchantRef] = (0, import_react5.useState)(null);
|
|
1487
|
+
const [paymentPhase, setPaymentPhase] = (0, import_react5.useState)("idle");
|
|
1488
|
+
const [sessions, setSessions] = (0, import_react5.useState)(() => loadSessions());
|
|
1489
|
+
const [sidebarOpen, setSidebarOpen] = (0, import_react5.useState)(false);
|
|
1490
|
+
const [replayMessages, setReplayMessages] = (0, import_react5.useState)(null);
|
|
1491
|
+
const { status: pollStatus } = (0, import_sdk5.usePaymentPolling)({
|
|
1162
1492
|
client: client.api,
|
|
1163
1493
|
merchantReference: merchantRef,
|
|
1164
1494
|
onSuccess: () => {
|
|
@@ -1170,7 +1500,7 @@ function ChatModal({
|
|
|
1170
1500
|
setMerchantRef(null);
|
|
1171
1501
|
}
|
|
1172
1502
|
});
|
|
1173
|
-
(0,
|
|
1503
|
+
(0, import_react5.useEffect)(() => {
|
|
1174
1504
|
if (!lastAction) return;
|
|
1175
1505
|
if (lastAction.type === "request_phone") {
|
|
1176
1506
|
setPaymentPhase("prompt_phone");
|
|
@@ -1211,8 +1541,8 @@ function ChatModal({
|
|
|
1211
1541
|
setPaymentPhase("failed");
|
|
1212
1542
|
}
|
|
1213
1543
|
};
|
|
1214
|
-
const msgsContainerRef = (0,
|
|
1215
|
-
(0,
|
|
1544
|
+
const msgsContainerRef = (0, import_react5.useRef)(null);
|
|
1545
|
+
(0, import_react5.useEffect)(() => {
|
|
1216
1546
|
const container = msgsContainerRef.current;
|
|
1217
1547
|
if (!container) return;
|
|
1218
1548
|
const distanceFromBottom = container.scrollHeight - container.scrollTop - container.clientHeight;
|
|
@@ -1220,14 +1550,14 @@ function ChatModal({
|
|
|
1220
1550
|
bottomRef.current?.scrollIntoView({ behavior: "smooth" });
|
|
1221
1551
|
}
|
|
1222
1552
|
}, [messages, loading, selectedProduct]);
|
|
1223
|
-
(0,
|
|
1553
|
+
(0, import_react5.useEffect)(() => {
|
|
1224
1554
|
const h = (e) => {
|
|
1225
1555
|
if (e.key === "Escape") onClose();
|
|
1226
1556
|
};
|
|
1227
1557
|
document.addEventListener("keydown", h);
|
|
1228
1558
|
return () => document.removeEventListener("keydown", h);
|
|
1229
1559
|
}, []);
|
|
1230
|
-
const saveCurrentSession = (0,
|
|
1560
|
+
const saveCurrentSession = (0, import_react5.useCallback)(() => {
|
|
1231
1561
|
if (messages.length < 2) return;
|
|
1232
1562
|
const firstUser = messages.find((m) => m.role === "user");
|
|
1233
1563
|
const session = {
|
|
@@ -1240,7 +1570,7 @@ function ChatModal({
|
|
|
1240
1570
|
setSessions(updated);
|
|
1241
1571
|
saveSessions(updated);
|
|
1242
1572
|
}, [messages, sessions]);
|
|
1243
|
-
const handleReset = (0,
|
|
1573
|
+
const handleReset = (0, import_react5.useCallback)(() => {
|
|
1244
1574
|
saveCurrentSession();
|
|
1245
1575
|
reset();
|
|
1246
1576
|
setReplayMessages(null);
|
|
@@ -1253,7 +1583,7 @@ function ChatModal({
|
|
|
1253
1583
|
const q = `Tell me more about the ${src.name}${src.price ? ` (${src.currency ?? defaultCurrency} ${src.price})` : ""} \u2014 what are its key specs, who is it best for, and is it worth buying?`;
|
|
1254
1584
|
send(q);
|
|
1255
1585
|
};
|
|
1256
|
-
const handleSend = async (text) => {
|
|
1586
|
+
const handleSend = async (text, extraAttachments) => {
|
|
1257
1587
|
const q = (text ?? input).trim();
|
|
1258
1588
|
if (!q || loading) return;
|
|
1259
1589
|
setReplayMessages(null);
|
|
@@ -1262,7 +1592,9 @@ function ChatModal({
|
|
|
1262
1592
|
if (textareaRef.current) {
|
|
1263
1593
|
textareaRef.current.style.height = "auto";
|
|
1264
1594
|
}
|
|
1265
|
-
|
|
1595
|
+
const toSend = extraAttachments ?? attachments;
|
|
1596
|
+
setAttachments([]);
|
|
1597
|
+
await send(q, void 0, toSend.length > 0 ? toSend : void 0);
|
|
1266
1598
|
};
|
|
1267
1599
|
const handleKeyDown = (e) => {
|
|
1268
1600
|
if (e.key === "Enter" && !e.shiftKey) {
|
|
@@ -1276,6 +1608,20 @@ function ChatModal({
|
|
|
1276
1608
|
t.style.height = "auto";
|
|
1277
1609
|
t.style.height = `${Math.min(t.scrollHeight, 140)}px`;
|
|
1278
1610
|
};
|
|
1611
|
+
(0, import_react5.useEffect)(() => {
|
|
1612
|
+
if (voiceState !== "processing") return;
|
|
1613
|
+
const transcript = pendingVoiceRef.current;
|
|
1614
|
+
if (!transcript) {
|
|
1615
|
+
setVoiceState("idle");
|
|
1616
|
+
return;
|
|
1617
|
+
}
|
|
1618
|
+
pendingVoiceRef.current = null;
|
|
1619
|
+
const timer = setTimeout(() => {
|
|
1620
|
+
setVoiceState("idle");
|
|
1621
|
+
handleSend(transcript);
|
|
1622
|
+
}, 400);
|
|
1623
|
+
return () => clearTimeout(timer);
|
|
1624
|
+
}, [voiceState]);
|
|
1279
1625
|
const blurVal = typeof backdropBlur === "number" ? `${backdropBlur}px` : backdropBlur ?? "20px";
|
|
1280
1626
|
const displayMessages = replayMessages ?? messages;
|
|
1281
1627
|
const loadSession = (session) => {
|
|
@@ -1288,7 +1634,7 @@ function ChatModal({
|
|
|
1288
1634
|
setSessions(updated);
|
|
1289
1635
|
saveSessions(updated);
|
|
1290
1636
|
};
|
|
1291
|
-
return /* @__PURE__ */ (0,
|
|
1637
|
+
return /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(
|
|
1292
1638
|
"div",
|
|
1293
1639
|
{
|
|
1294
1640
|
className: cn("hsk-cb-overlay", classNames.overlay),
|
|
@@ -1300,27 +1646,27 @@ function ChatModal({
|
|
|
1300
1646
|
...backdropColor ? { background: backdropColor } : {},
|
|
1301
1647
|
...customStyles
|
|
1302
1648
|
},
|
|
1303
|
-
children: /* @__PURE__ */ (0,
|
|
1304
|
-
/* @__PURE__ */ (0,
|
|
1305
|
-
/* @__PURE__ */ (0,
|
|
1306
|
-
/* @__PURE__ */ (0,
|
|
1307
|
-
/* @__PURE__ */ (0,
|
|
1649
|
+
children: /* @__PURE__ */ (0, import_jsx_runtime7.jsxs)("div", { className: cn("hsk-cb-panel hsk-cb-panel--with-sidebar", classNames.panel), onClick: (e) => e.stopPropagation(), children: [
|
|
1650
|
+
/* @__PURE__ */ (0, import_jsx_runtime7.jsxs)("div", { className: cn("hsk-cb-sidebar", sidebarOpen && "hsk-cb-sidebar--open"), children: [
|
|
1651
|
+
/* @__PURE__ */ (0, import_jsx_runtime7.jsxs)("div", { className: "hsk-cb-sidebar-header", children: [
|
|
1652
|
+
/* @__PURE__ */ (0, import_jsx_runtime7.jsx)("span", { className: "hsk-cb-sidebar-title", children: "History" }),
|
|
1653
|
+
/* @__PURE__ */ (0, import_jsx_runtime7.jsxs)(
|
|
1308
1654
|
"button",
|
|
1309
1655
|
{
|
|
1310
1656
|
className: "hsk-cb-sidebar-new",
|
|
1311
1657
|
onClick: handleReset,
|
|
1312
1658
|
title: "New chat",
|
|
1313
1659
|
children: [
|
|
1314
|
-
/* @__PURE__ */ (0,
|
|
1315
|
-
/* @__PURE__ */ (0,
|
|
1660
|
+
/* @__PURE__ */ (0, import_jsx_runtime7.jsx)(NewChatIcon, {}),
|
|
1661
|
+
/* @__PURE__ */ (0, import_jsx_runtime7.jsx)("span", { children: "New chat" })
|
|
1316
1662
|
]
|
|
1317
1663
|
}
|
|
1318
1664
|
)
|
|
1319
1665
|
] }),
|
|
1320
|
-
/* @__PURE__ */ (0,
|
|
1321
|
-
/* @__PURE__ */ (0,
|
|
1322
|
-
/* @__PURE__ */ (0,
|
|
1323
|
-
] }) : sessions.map((session) => /* @__PURE__ */ (0,
|
|
1666
|
+
/* @__PURE__ */ (0, import_jsx_runtime7.jsx)("div", { className: "hsk-cb-sidebar-list", children: sessions.length === 0 ? /* @__PURE__ */ (0, import_jsx_runtime7.jsxs)("div", { className: "hsk-cb-sidebar-empty", children: [
|
|
1667
|
+
/* @__PURE__ */ (0, import_jsx_runtime7.jsx)(HistoryIcon, {}),
|
|
1668
|
+
/* @__PURE__ */ (0, import_jsx_runtime7.jsx)("span", { children: "No history yet" })
|
|
1669
|
+
] }) : sessions.map((session) => /* @__PURE__ */ (0, import_jsx_runtime7.jsxs)(
|
|
1324
1670
|
"div",
|
|
1325
1671
|
{
|
|
1326
1672
|
className: cn(
|
|
@@ -1329,9 +1675,9 @@ function ChatModal({
|
|
|
1329
1675
|
),
|
|
1330
1676
|
onClick: () => loadSession(session),
|
|
1331
1677
|
children: [
|
|
1332
|
-
/* @__PURE__ */ (0,
|
|
1333
|
-
/* @__PURE__ */ (0,
|
|
1334
|
-
/* @__PURE__ */ (0,
|
|
1678
|
+
/* @__PURE__ */ (0, import_jsx_runtime7.jsx)("div", { className: "hsk-cb-sidebar-session-title", children: session.title }),
|
|
1679
|
+
/* @__PURE__ */ (0, import_jsx_runtime7.jsx)("div", { className: "hsk-cb-sidebar-session-meta", children: relativeTime(session.ts) }),
|
|
1680
|
+
/* @__PURE__ */ (0, import_jsx_runtime7.jsx)(
|
|
1335
1681
|
"button",
|
|
1336
1682
|
{
|
|
1337
1683
|
className: "hsk-cb-sidebar-session-del",
|
|
@@ -1345,10 +1691,10 @@ function ChatModal({
|
|
|
1345
1691
|
session.id
|
|
1346
1692
|
)) })
|
|
1347
1693
|
] }),
|
|
1348
|
-
/* @__PURE__ */ (0,
|
|
1349
|
-
/* @__PURE__ */ (0,
|
|
1350
|
-
/* @__PURE__ */ (0,
|
|
1351
|
-
/* @__PURE__ */ (0,
|
|
1694
|
+
/* @__PURE__ */ (0, import_jsx_runtime7.jsxs)("div", { className: "hsk-cb-main", children: [
|
|
1695
|
+
/* @__PURE__ */ (0, import_jsx_runtime7.jsxs)("div", { className: "hsk-cb-topbar", children: [
|
|
1696
|
+
/* @__PURE__ */ (0, import_jsx_runtime7.jsxs)("div", { className: "hsk-cb-topbar-left", children: [
|
|
1697
|
+
/* @__PURE__ */ (0, import_jsx_runtime7.jsx)(
|
|
1352
1698
|
"button",
|
|
1353
1699
|
{
|
|
1354
1700
|
className: cn("hsk-cb-sidebar-toggle", sidebarOpen && "hsk-cb-sidebar-toggle--active"),
|
|
@@ -1357,29 +1703,29 @@ function ChatModal({
|
|
|
1357
1703
|
setSidebarOpen((v) => !v);
|
|
1358
1704
|
},
|
|
1359
1705
|
"aria-label": "Toggle history",
|
|
1360
|
-
children: /* @__PURE__ */ (0,
|
|
1706
|
+
children: /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(HistoryIcon, {})
|
|
1361
1707
|
}
|
|
1362
1708
|
),
|
|
1363
|
-
/* @__PURE__ */ (0,
|
|
1364
|
-
/* @__PURE__ */ (0,
|
|
1709
|
+
/* @__PURE__ */ (0, import_jsx_runtime7.jsx)("span", { className: "hsk-cb-topbar-icon", style: { display: "flex", alignItems: "center" }, children: /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(SparkleIcon2, {}) }),
|
|
1710
|
+
/* @__PURE__ */ (0, import_jsx_runtime7.jsx)("div", { children: /* @__PURE__ */ (0, import_jsx_runtime7.jsx)("div", { className: "hsk-cb-topbar-title", children: activeTitle }) })
|
|
1365
1711
|
] }),
|
|
1366
|
-
/* @__PURE__ */ (0,
|
|
1367
|
-
replayMessages ? /* @__PURE__ */ (0,
|
|
1712
|
+
/* @__PURE__ */ (0, import_jsx_runtime7.jsxs)("div", { className: "hsk-cb-topbar-actions", children: [
|
|
1713
|
+
replayMessages ? /* @__PURE__ */ (0, import_jsx_runtime7.jsx)("button", { className: "hsk-cb-topbar-btn", onClick: () => {
|
|
1368
1714
|
setReplayMessages(null);
|
|
1369
|
-
}, children: "\u2190 Live chat" }) : messages.length > 0 && /* @__PURE__ */ (0,
|
|
1370
|
-
/* @__PURE__ */ (0,
|
|
1715
|
+
}, children: "\u2190 Live chat" }) : messages.length > 0 && /* @__PURE__ */ (0, import_jsx_runtime7.jsx)("button", { className: "hsk-cb-topbar-btn", onClick: handleReset, children: "Clear chat" }),
|
|
1716
|
+
/* @__PURE__ */ (0, import_jsx_runtime7.jsx)("button", { className: "hsk-cb-close", onClick: onClose, "aria-label": "Close", children: /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(CloseIcon, {}) })
|
|
1371
1717
|
] })
|
|
1372
1718
|
] }),
|
|
1373
|
-
replayMessages && /* @__PURE__ */ (0,
|
|
1374
|
-
/* @__PURE__ */ (0,
|
|
1375
|
-
/* @__PURE__ */ (0,
|
|
1376
|
-
/* @__PURE__ */ (0,
|
|
1719
|
+
replayMessages && /* @__PURE__ */ (0, import_jsx_runtime7.jsxs)("div", { className: "hsk-cb-replay-banner", children: [
|
|
1720
|
+
/* @__PURE__ */ (0, import_jsx_runtime7.jsx)(HistoryIcon, {}),
|
|
1721
|
+
/* @__PURE__ */ (0, import_jsx_runtime7.jsx)("span", { children: "You're viewing a past conversation." }),
|
|
1722
|
+
/* @__PURE__ */ (0, import_jsx_runtime7.jsx)("button", { onClick: () => setReplayMessages(null), children: "Back to chat \u2192" })
|
|
1377
1723
|
] }),
|
|
1378
|
-
/* @__PURE__ */ (0,
|
|
1379
|
-
displayMessages.length === 0 ? /* @__PURE__ */ (0,
|
|
1380
|
-
/* @__PURE__ */ (0,
|
|
1381
|
-
/* @__PURE__ */ (0,
|
|
1382
|
-
/* @__PURE__ */ (0,
|
|
1724
|
+
/* @__PURE__ */ (0, import_jsx_runtime7.jsxs)("div", { className: "hsk-cb-msgs", ref: msgsContainerRef, children: [
|
|
1725
|
+
displayMessages.length === 0 ? /* @__PURE__ */ (0, import_jsx_runtime7.jsxs)("div", { className: "hsk-cb-empty", children: [
|
|
1726
|
+
/* @__PURE__ */ (0, import_jsx_runtime7.jsx)("div", { className: "hsk-cb-empty-icon", style: { display: "flex", alignItems: "center" }, children: /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(SparkleIcon2, {}) }),
|
|
1727
|
+
/* @__PURE__ */ (0, import_jsx_runtime7.jsx)("div", { className: "hsk-cb-empty-title", children: "Find exactly what you need" }),
|
|
1728
|
+
/* @__PURE__ */ (0, import_jsx_runtime7.jsx)("div", { className: "hsk-cb-chips", children: activeChips.map((chip) => /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(
|
|
1383
1729
|
"button",
|
|
1384
1730
|
{
|
|
1385
1731
|
className: "hsk-cb-chip",
|
|
@@ -1392,12 +1738,15 @@ function ChatModal({
|
|
|
1392
1738
|
const isLast = idx === displayMessages.length - 1 && !replayMessages;
|
|
1393
1739
|
const isUser = msg.role === "user";
|
|
1394
1740
|
const displayContent = !isUser && isLast && lastIntent === "compare" && sources.length >= 2 && !replayMessages ? stripMarkdownTables(msg.content) : msg.content;
|
|
1395
|
-
return /* @__PURE__ */ (0,
|
|
1396
|
-
/* @__PURE__ */ (0,
|
|
1397
|
-
/* @__PURE__ */ (0,
|
|
1398
|
-
|
|
1399
|
-
|
|
1400
|
-
|
|
1741
|
+
return /* @__PURE__ */ (0, import_jsx_runtime7.jsx)("div", { className: "hsk-cb-msg-group", children: isUser ? /* @__PURE__ */ (0, import_jsx_runtime7.jsxs)("div", { className: "hsk-cb-user-msg", children: [
|
|
1742
|
+
msg.images && msg.images.length > 0 && /* @__PURE__ */ (0, import_jsx_runtime7.jsx)("div", { className: "hsk-cb-user-imgs", children: msg.images.map((img, i) => /* @__PURE__ */ (0, import_jsx_runtime7.jsx)("img", { src: img, alt: `attachment ${i + 1}`, className: "hsk-cb-user-img-thumb" }, i)) }),
|
|
1743
|
+
msg.content && /* @__PURE__ */ (0, import_jsx_runtime7.jsx)("div", { className: "hsk-cb-user-bubble", children: msg.content })
|
|
1744
|
+
] }) : /* @__PURE__ */ (0, import_jsx_runtime7.jsxs)("div", { className: "hsk-cb-ai-msg", children: [
|
|
1745
|
+
/* @__PURE__ */ (0, import_jsx_runtime7.jsx)("div", { className: "hsk-cb-ai-icon", style: { display: "flex", alignItems: "center" }, children: /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(SparkleIcon2, {}) }),
|
|
1746
|
+
/* @__PURE__ */ (0, import_jsx_runtime7.jsxs)("div", { className: "hsk-cb-ai-body", children: [
|
|
1747
|
+
/* @__PURE__ */ (0, import_jsx_runtime7.jsx)("div", { className: "hsk-cb-ai-text", children: renderMarkdown(displayContent) }),
|
|
1748
|
+
isLast && lastIntent === "compare" && sources.length >= 2 && !replayMessages && /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(ComparisonMatrix, { sources, defaultCurrency }),
|
|
1749
|
+
isLast && sources.length > 0 && lastIntent !== "compare" && lastAction?.type !== "request_phone" && lastAction?.type !== "awaiting_payment" && lastAction?.type !== "checkout" && !msg.cartSnapshot && /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(
|
|
1401
1750
|
SourcesCarousel,
|
|
1402
1751
|
{
|
|
1403
1752
|
sources,
|
|
@@ -1405,14 +1754,14 @@ function ChatModal({
|
|
|
1405
1754
|
onSelectSource: handleSourceClick
|
|
1406
1755
|
}
|
|
1407
1756
|
),
|
|
1408
|
-
msg.cartSnapshot && msg.cartSnapshot.items?.length > 0 && /* @__PURE__ */ (0,
|
|
1757
|
+
msg.cartSnapshot && msg.cartSnapshot.items?.length > 0 && /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(
|
|
1409
1758
|
CartContextCard,
|
|
1410
1759
|
{
|
|
1411
1760
|
cart: msg.cartSnapshot,
|
|
1412
1761
|
defaultCurrency
|
|
1413
1762
|
}
|
|
1414
1763
|
),
|
|
1415
|
-
isLast && msg.cartSnapshot && !loading && /* @__PURE__ */ (0,
|
|
1764
|
+
isLast && msg.cartSnapshot && !loading && /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(
|
|
1416
1765
|
ActionPills,
|
|
1417
1766
|
{
|
|
1418
1767
|
cart: msg.cartSnapshot,
|
|
@@ -1421,7 +1770,7 @@ function ChatModal({
|
|
|
1421
1770
|
loading
|
|
1422
1771
|
}
|
|
1423
1772
|
),
|
|
1424
|
-
isLast && !loading && !msg.cartSnapshot && !replayMessages && /* @__PURE__ */ (0,
|
|
1773
|
+
isLast && !loading && !msg.cartSnapshot && !replayMessages && /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(
|
|
1425
1774
|
SmartContextPills,
|
|
1426
1775
|
{
|
|
1427
1776
|
intent: lastIntent,
|
|
@@ -1433,16 +1782,16 @@ function ChatModal({
|
|
|
1433
1782
|
] })
|
|
1434
1783
|
] }) }, idx);
|
|
1435
1784
|
}),
|
|
1436
|
-
selectedProduct && loading && /* @__PURE__ */ (0,
|
|
1785
|
+
selectedProduct && loading && /* @__PURE__ */ (0, import_jsx_runtime7.jsxs)(
|
|
1437
1786
|
"div",
|
|
1438
1787
|
{
|
|
1439
1788
|
className: "hsk-cb-selected-product",
|
|
1440
1789
|
onClick: () => selectedProduct.url && window.open(selectedProduct.url, "_blank"),
|
|
1441
1790
|
children: [
|
|
1442
|
-
selectedProduct.image && /* @__PURE__ */ (0,
|
|
1443
|
-
/* @__PURE__ */ (0,
|
|
1444
|
-
/* @__PURE__ */ (0,
|
|
1445
|
-
selectedProduct.price && /* @__PURE__ */ (0,
|
|
1791
|
+
selectedProduct.image && /* @__PURE__ */ (0, import_jsx_runtime7.jsx)("img", { className: "hsk-cb-selected-img", src: selectedProduct.image, alt: selectedProduct.name }),
|
|
1792
|
+
/* @__PURE__ */ (0, import_jsx_runtime7.jsxs)("div", { className: "hsk-cb-selected-info", children: [
|
|
1793
|
+
/* @__PURE__ */ (0, import_jsx_runtime7.jsx)("div", { className: "hsk-cb-selected-name", children: selectedProduct.name }),
|
|
1794
|
+
selectedProduct.price && /* @__PURE__ */ (0, import_jsx_runtime7.jsxs)("div", { className: "hsk-cb-selected-price", children: [
|
|
1446
1795
|
selectedProduct.currency ?? defaultCurrency,
|
|
1447
1796
|
" ",
|
|
1448
1797
|
parseFloat(String(selectedProduct.price ?? "").replace(/[^0-9.]/g, "") || "0").toLocaleString()
|
|
@@ -1451,34 +1800,34 @@ function ChatModal({
|
|
|
1451
1800
|
]
|
|
1452
1801
|
}
|
|
1453
1802
|
),
|
|
1454
|
-
loading && !streaming && /* @__PURE__ */ (0,
|
|
1455
|
-
/* @__PURE__ */ (0,
|
|
1456
|
-
/* @__PURE__ */ (0,
|
|
1457
|
-
/* @__PURE__ */ (0,
|
|
1803
|
+
loading && !streaming && /* @__PURE__ */ (0, import_jsx_runtime7.jsxs)("div", { className: "hsk-cb-typing-row", style: { display: "flex", alignItems: "flex-start", gap: "10px" }, children: [
|
|
1804
|
+
/* @__PURE__ */ (0, import_jsx_runtime7.jsx)("div", { className: "hsk-cb-ai-icon", style: { display: "flex", alignItems: "center", marginTop: "4px" }, children: /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(SparkleIcon2, {}) }),
|
|
1805
|
+
/* @__PURE__ */ (0, import_jsx_runtime7.jsxs)("div", { style: { display: "flex", flexDirection: "column", gap: "6px" }, children: [
|
|
1806
|
+
/* @__PURE__ */ (0, import_jsx_runtime7.jsx)("style", { children: `
|
|
1458
1807
|
@keyframes hsk-pulse {
|
|
1459
1808
|
0%, 100% { opacity: 0.6; }
|
|
1460
1809
|
50% { opacity: 1; }
|
|
1461
1810
|
}
|
|
1462
1811
|
` }),
|
|
1463
|
-
/* @__PURE__ */ (0,
|
|
1464
|
-
/* @__PURE__ */ (0,
|
|
1465
|
-
/* @__PURE__ */ (0,
|
|
1466
|
-
/* @__PURE__ */ (0,
|
|
1467
|
-
/* @__PURE__ */ (0,
|
|
1812
|
+
/* @__PURE__ */ (0, import_jsx_runtime7.jsx)("div", { style: { fontSize: "0.85rem", color: "#6b7280", fontStyle: "italic", animation: "hsk-pulse 1.5s infinite ease-in-out" }, children: LOADING_MESSAGES[loadingMessageIndex] }),
|
|
1813
|
+
/* @__PURE__ */ (0, import_jsx_runtime7.jsxs)("div", { className: "hsk-cb-typing", style: { margin: 0, alignSelf: "flex-start" }, children: [
|
|
1814
|
+
/* @__PURE__ */ (0, import_jsx_runtime7.jsx)("div", { className: "hsk-cb-dot" }),
|
|
1815
|
+
/* @__PURE__ */ (0, import_jsx_runtime7.jsx)("div", { className: "hsk-cb-dot" }),
|
|
1816
|
+
/* @__PURE__ */ (0, import_jsx_runtime7.jsx)("div", { className: "hsk-cb-dot" })
|
|
1468
1817
|
] })
|
|
1469
1818
|
] })
|
|
1470
1819
|
] }),
|
|
1471
|
-
error && /* @__PURE__ */ (0,
|
|
1820
|
+
error && /* @__PURE__ */ (0, import_jsx_runtime7.jsx)("div", { className: "hsk-cb-error", children: getFriendlyError(error) }),
|
|
1472
1821
|
!replayMessages && paymentPhase === "prompt_phone" && (() => {
|
|
1473
1822
|
const isHistoryIntent = lastIntent === "capture" || lastIntent === "delete" || lastIntent === "view_history";
|
|
1474
1823
|
if (isHistoryIntent) {
|
|
1475
1824
|
return null;
|
|
1476
1825
|
}
|
|
1477
|
-
return /* @__PURE__ */ (0,
|
|
1478
|
-
/* @__PURE__ */ (0,
|
|
1479
|
-
/* @__PURE__ */ (0,
|
|
1480
|
-
/* @__PURE__ */ (0,
|
|
1481
|
-
/* @__PURE__ */ (0,
|
|
1826
|
+
return /* @__PURE__ */ (0, import_jsx_runtime7.jsxs)("div", { className: "hsk-cb-ai-msg", children: [
|
|
1827
|
+
/* @__PURE__ */ (0, import_jsx_runtime7.jsx)("div", { className: "hsk-cb-ai-icon", style: { display: "flex", alignItems: "center" }, children: /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(SparkleIcon2, {}) }),
|
|
1828
|
+
/* @__PURE__ */ (0, import_jsx_runtime7.jsx)("div", { className: "hsk-cb-ai-body", children: /* @__PURE__ */ (0, import_jsx_runtime7.jsx)("div", { className: "hsk-cb-ai-text", children: /* @__PURE__ */ (0, import_jsx_runtime7.jsxs)("div", { className: "hsk-cb-phone-form", children: [
|
|
1829
|
+
/* @__PURE__ */ (0, import_jsx_runtime7.jsx)("label", { className: "hsk-cb-phone-label", children: "Enter your M-Pesa number to pay" }),
|
|
1830
|
+
/* @__PURE__ */ (0, import_jsx_runtime7.jsx)(
|
|
1482
1831
|
"input",
|
|
1483
1832
|
{
|
|
1484
1833
|
type: "tel",
|
|
@@ -1490,37 +1839,37 @@ function ChatModal({
|
|
|
1490
1839
|
autoFocus: true
|
|
1491
1840
|
}
|
|
1492
1841
|
),
|
|
1493
|
-
/* @__PURE__ */ (0,
|
|
1842
|
+
/* @__PURE__ */ (0, import_jsx_runtime7.jsx)("button", { className: "hsk-cb-phone-submit", onClick: handlePhoneSubmit, children: "Send STK push" })
|
|
1494
1843
|
] }) }) })
|
|
1495
1844
|
] });
|
|
1496
1845
|
})(),
|
|
1497
|
-
!replayMessages && paymentPhase === "awaiting" && /* @__PURE__ */ (0,
|
|
1498
|
-
/* @__PURE__ */ (0,
|
|
1499
|
-
/* @__PURE__ */ (0,
|
|
1500
|
-
/* @__PURE__ */ (0,
|
|
1501
|
-
/* @__PURE__ */ (0,
|
|
1846
|
+
!replayMessages && paymentPhase === "awaiting" && /* @__PURE__ */ (0, import_jsx_runtime7.jsxs)("div", { className: "hsk-cb-payment-prompt hsk-cb-payment-prompt--awaiting", children: [
|
|
1847
|
+
/* @__PURE__ */ (0, import_jsx_runtime7.jsx)("div", { className: "hsk-cb-payment-pulse-ring" }),
|
|
1848
|
+
/* @__PURE__ */ (0, import_jsx_runtime7.jsx)("div", { className: "hsk-cb-payment-icon-wrap", children: /* @__PURE__ */ (0, import_jsx_runtime7.jsx)("span", { style: { fontSize: "2rem" }, children: "\u{1F4F1}" }) }),
|
|
1849
|
+
/* @__PURE__ */ (0, import_jsx_runtime7.jsx)("p", { className: "hsk-cb-payment-label", style: { fontWeight: 600 }, children: "Check your phone" }),
|
|
1850
|
+
/* @__PURE__ */ (0, import_jsx_runtime7.jsxs)("p", { className: "hsk-cb-payment-sub", children: [
|
|
1502
1851
|
"An M-Pesa STK push has been sent.",
|
|
1503
|
-
/* @__PURE__ */ (0,
|
|
1852
|
+
/* @__PURE__ */ (0, import_jsx_runtime7.jsx)("br", {}),
|
|
1504
1853
|
"Enter your PIN to complete payment."
|
|
1505
1854
|
] }),
|
|
1506
|
-
/* @__PURE__ */ (0,
|
|
1507
|
-
/* @__PURE__ */ (0,
|
|
1508
|
-
/* @__PURE__ */ (0,
|
|
1509
|
-
/* @__PURE__ */ (0,
|
|
1855
|
+
/* @__PURE__ */ (0, import_jsx_runtime7.jsxs)("div", { className: "hsk-cb-payment-dots", children: [
|
|
1856
|
+
/* @__PURE__ */ (0, import_jsx_runtime7.jsx)("div", { className: "hsk-cb-dot hsk-cb-dot--amber" }),
|
|
1857
|
+
/* @__PURE__ */ (0, import_jsx_runtime7.jsx)("div", { className: "hsk-cb-dot hsk-cb-dot--amber" }),
|
|
1858
|
+
/* @__PURE__ */ (0, import_jsx_runtime7.jsx)("div", { className: "hsk-cb-dot hsk-cb-dot--amber" })
|
|
1510
1859
|
] })
|
|
1511
1860
|
] }),
|
|
1512
|
-
!replayMessages && paymentPhase === "done" && /* @__PURE__ */ (0,
|
|
1513
|
-
/* @__PURE__ */ (0,
|
|
1514
|
-
/* @__PURE__ */ (0,
|
|
1515
|
-
/* @__PURE__ */ (0,
|
|
1516
|
-
/* @__PURE__ */ (0,
|
|
1861
|
+
!replayMessages && paymentPhase === "done" && /* @__PURE__ */ (0, import_jsx_runtime7.jsxs)("div", { className: "hsk-cb-payment-prompt hsk-cb-payment-prompt--success", children: [
|
|
1862
|
+
/* @__PURE__ */ (0, import_jsx_runtime7.jsx)("div", { className: "hsk-cb-payment-success-ring" }),
|
|
1863
|
+
/* @__PURE__ */ (0, import_jsx_runtime7.jsx)("div", { className: "hsk-cb-payment-icon-wrap", children: /* @__PURE__ */ (0, import_jsx_runtime7.jsx)("span", { style: { fontSize: "2.5rem" }, children: "\u2705" }) }),
|
|
1864
|
+
/* @__PURE__ */ (0, import_jsx_runtime7.jsx)("p", { className: "hsk-cb-payment-label", children: "Payment complete!" }),
|
|
1865
|
+
/* @__PURE__ */ (0, import_jsx_runtime7.jsx)("p", { className: "hsk-cb-payment-sub", children: "Thank you for your order. A confirmation has been sent." })
|
|
1517
1866
|
] }),
|
|
1518
|
-
!replayMessages && paymentPhase === "failed" && /* @__PURE__ */ (0,
|
|
1519
|
-
/* @__PURE__ */ (0,
|
|
1520
|
-
/* @__PURE__ */ (0,
|
|
1521
|
-
/* @__PURE__ */ (0,
|
|
1522
|
-
/* @__PURE__ */ (0,
|
|
1523
|
-
/* @__PURE__ */ (0,
|
|
1867
|
+
!replayMessages && paymentPhase === "failed" && /* @__PURE__ */ (0, import_jsx_runtime7.jsxs)("div", { className: "hsk-cb-payment-prompt hsk-cb-payment-prompt--failed", children: [
|
|
1868
|
+
/* @__PURE__ */ (0, import_jsx_runtime7.jsx)("div", { className: "hsk-cb-payment-icon-wrap", children: /* @__PURE__ */ (0, import_jsx_runtime7.jsx)("span", { style: { fontSize: "2.5rem" }, children: "\u274C" }) }),
|
|
1869
|
+
/* @__PURE__ */ (0, import_jsx_runtime7.jsx)("p", { className: "hsk-cb-payment-label", children: "Payment failed or timed out" }),
|
|
1870
|
+
/* @__PURE__ */ (0, import_jsx_runtime7.jsx)("p", { className: "hsk-cb-payment-sub", children: "Please check your M-Pesa PIN and try again, or contact support." }),
|
|
1871
|
+
/* @__PURE__ */ (0, import_jsx_runtime7.jsxs)("div", { className: "hsk-cb-payment-actions", children: [
|
|
1872
|
+
/* @__PURE__ */ (0, import_jsx_runtime7.jsx)(
|
|
1524
1873
|
"button",
|
|
1525
1874
|
{
|
|
1526
1875
|
className: "hsk-cb-pay-submit",
|
|
@@ -1531,7 +1880,7 @@ function ChatModal({
|
|
|
1531
1880
|
children: "Try again"
|
|
1532
1881
|
}
|
|
1533
1882
|
),
|
|
1534
|
-
/* @__PURE__ */ (0,
|
|
1883
|
+
/* @__PURE__ */ (0, import_jsx_runtime7.jsx)(
|
|
1535
1884
|
"button",
|
|
1536
1885
|
{
|
|
1537
1886
|
className: "hsk-cb-pay-secondary",
|
|
@@ -1544,11 +1893,45 @@ function ChatModal({
|
|
|
1544
1893
|
)
|
|
1545
1894
|
] })
|
|
1546
1895
|
] }),
|
|
1547
|
-
/* @__PURE__ */ (0,
|
|
1896
|
+
/* @__PURE__ */ (0, import_jsx_runtime7.jsx)("div", { ref: bottomRef, style: { height: 1 } })
|
|
1548
1897
|
] }),
|
|
1549
|
-
!replayMessages && /* @__PURE__ */ (0,
|
|
1550
|
-
/* @__PURE__ */ (0,
|
|
1551
|
-
/* @__PURE__ */ (0,
|
|
1898
|
+
!replayMessages && /* @__PURE__ */ (0, import_jsx_runtime7.jsxs)("div", { className: "hsk-cb-input-wrap", children: [
|
|
1899
|
+
attachments.length > 0 && /* @__PURE__ */ (0, import_jsx_runtime7.jsx)("div", { className: "hsk-cb-img-strip", children: attachments.map((att, i) => /* @__PURE__ */ (0, import_jsx_runtime7.jsxs)("div", { className: "hsk-cb-img-thumb-wrap", children: [
|
|
1900
|
+
/* @__PURE__ */ (0, import_jsx_runtime7.jsx)("img", { src: att.data, alt: `attachment ${i + 1}`, className: "hsk-cb-img-thumb" }),
|
|
1901
|
+
/* @__PURE__ */ (0, import_jsx_runtime7.jsx)(
|
|
1902
|
+
"button",
|
|
1903
|
+
{
|
|
1904
|
+
className: "hsk-cb-img-thumb-remove",
|
|
1905
|
+
onClick: () => removeAttachment(i),
|
|
1906
|
+
"aria-label": "Remove image",
|
|
1907
|
+
children: "\xD7"
|
|
1908
|
+
}
|
|
1909
|
+
)
|
|
1910
|
+
] }, i)) }),
|
|
1911
|
+
/* @__PURE__ */ (0, import_jsx_runtime7.jsxs)("div", { className: "hsk-cb-input-box", children: [
|
|
1912
|
+
/* @__PURE__ */ (0, import_jsx_runtime7.jsx)(
|
|
1913
|
+
"input",
|
|
1914
|
+
{
|
|
1915
|
+
ref: imageInputRef,
|
|
1916
|
+
type: "file",
|
|
1917
|
+
accept: "image/*",
|
|
1918
|
+
multiple: true,
|
|
1919
|
+
style: { display: "none" },
|
|
1920
|
+
onChange: (e) => handleImageFiles(e.target.files)
|
|
1921
|
+
}
|
|
1922
|
+
),
|
|
1923
|
+
enableVision && /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(
|
|
1924
|
+
"button",
|
|
1925
|
+
{
|
|
1926
|
+
className: "hsk-cb-attach-btn",
|
|
1927
|
+
onClick: () => imageInputRef.current?.click(),
|
|
1928
|
+
disabled: loading,
|
|
1929
|
+
"aria-label": "Attach image",
|
|
1930
|
+
title: "Attach image",
|
|
1931
|
+
children: /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(PaperclipIcon, {})
|
|
1932
|
+
}
|
|
1933
|
+
),
|
|
1934
|
+
/* @__PURE__ */ (0, import_jsx_runtime7.jsx)(
|
|
1552
1935
|
"textarea",
|
|
1553
1936
|
{
|
|
1554
1937
|
ref: textareaRef,
|
|
@@ -1562,18 +1945,36 @@ function ChatModal({
|
|
|
1562
1945
|
autoFocus: true
|
|
1563
1946
|
}
|
|
1564
1947
|
),
|
|
1565
|
-
/* @__PURE__ */ (0,
|
|
1948
|
+
hasSpeechAPI && enableVoice && /* @__PURE__ */ (0, import_jsx_runtime7.jsxs)(
|
|
1949
|
+
"button",
|
|
1950
|
+
{
|
|
1951
|
+
className: cn(
|
|
1952
|
+
"hsk-cb-mic-btn",
|
|
1953
|
+
voiceState === "listening" && "hsk-cb-mic-btn--listening",
|
|
1954
|
+
voiceState === "processing" && "hsk-cb-mic-btn--processing"
|
|
1955
|
+
),
|
|
1956
|
+
onClick: voiceState === "idle" ? startVoice : stopVoice,
|
|
1957
|
+
disabled: loading,
|
|
1958
|
+
"aria-label": voiceState === "idle" ? "Start voice input" : "Stop recording",
|
|
1959
|
+
title: voiceState === "idle" ? "Voice input" : "Stop",
|
|
1960
|
+
children: [
|
|
1961
|
+
voiceState === "listening" ? /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(MicOffIcon, {}) : /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(MicIcon2, {}),
|
|
1962
|
+
voiceState === "listening" && /* @__PURE__ */ (0, import_jsx_runtime7.jsx)("span", { className: "hsk-cb-mic-pulse" })
|
|
1963
|
+
]
|
|
1964
|
+
}
|
|
1965
|
+
),
|
|
1966
|
+
/* @__PURE__ */ (0, import_jsx_runtime7.jsx)(
|
|
1566
1967
|
"button",
|
|
1567
1968
|
{
|
|
1568
1969
|
className: cn("hsk-cb-send", classNames.sendButton),
|
|
1569
1970
|
onClick: () => handleSend(),
|
|
1570
|
-
disabled: !input.trim() || loading,
|
|
1971
|
+
disabled: !input.trim() && attachments.length === 0 || loading,
|
|
1571
1972
|
"aria-label": "Send message",
|
|
1572
|
-
children: /* @__PURE__ */ (0,
|
|
1973
|
+
children: /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(ArrowUpIcon2, {})
|
|
1573
1974
|
}
|
|
1574
1975
|
)
|
|
1575
1976
|
] }),
|
|
1576
|
-
/* @__PURE__ */ (0,
|
|
1977
|
+
/* @__PURE__ */ (0, import_jsx_runtime7.jsx)("div", { className: "hsk-cb-hint", children: "Akropolys AI \xB7 searches the whole catalogue in real time" })
|
|
1577
1978
|
] })
|
|
1578
1979
|
] })
|
|
1579
1980
|
] })
|
|
@@ -1591,11 +1992,14 @@ function KikuButton({
|
|
|
1591
1992
|
defaultCurrency,
|
|
1592
1993
|
chips,
|
|
1593
1994
|
theme,
|
|
1594
|
-
classNames = {}
|
|
1995
|
+
classNames = {},
|
|
1996
|
+
enableVoice = false,
|
|
1997
|
+
enableVision = false,
|
|
1998
|
+
visionCategoryHint
|
|
1595
1999
|
}) {
|
|
1596
|
-
const [open, setOpen] = (0,
|
|
1597
|
-
const [mounted, setMounted] = (0,
|
|
1598
|
-
(0,
|
|
2000
|
+
const [open, setOpen] = (0, import_react5.useState)(false);
|
|
2001
|
+
const [mounted, setMounted] = (0, import_react5.useState)(false);
|
|
2002
|
+
(0, import_react5.useEffect)(() => {
|
|
1599
2003
|
setMounted(true);
|
|
1600
2004
|
if (typeof window !== "undefined" && !window.__akropolys_nav_patched) {
|
|
1601
2005
|
window.__akropolys_nav_patched = true;
|
|
@@ -1629,8 +2033,8 @@ function KikuButton({
|
|
|
1629
2033
|
...theme?.fontFamily && { "--hsk-font": theme.fontFamily },
|
|
1630
2034
|
...theme?.borderRadius && { "--hsk-border-radius": theme.borderRadius }
|
|
1631
2035
|
} : void 0;
|
|
1632
|
-
return /* @__PURE__ */ (0,
|
|
1633
|
-
/* @__PURE__ */ (0,
|
|
2036
|
+
return /* @__PURE__ */ (0, import_jsx_runtime7.jsxs)(import_jsx_runtime7.Fragment, { children: [
|
|
2037
|
+
/* @__PURE__ */ (0, import_jsx_runtime7.jsxs)(
|
|
1634
2038
|
"button",
|
|
1635
2039
|
{
|
|
1636
2040
|
className: cn("hsk-cb-btn", classNames.button, className),
|
|
@@ -1639,13 +2043,13 @@ function KikuButton({
|
|
|
1639
2043
|
"data-hsk-theme": hskThemeAttr,
|
|
1640
2044
|
"aria-label": "Open AI chat",
|
|
1641
2045
|
children: [
|
|
1642
|
-
/* @__PURE__ */ (0,
|
|
2046
|
+
/* @__PURE__ */ (0, import_jsx_runtime7.jsx)("span", { className: "hsk-cb-btn-icon", style: { display: "flex", alignItems: "center" }, children: /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(SparkleIcon2, {}) }),
|
|
1643
2047
|
label !== void 0 ? label : null
|
|
1644
2048
|
]
|
|
1645
2049
|
}
|
|
1646
2050
|
),
|
|
1647
2051
|
open && mounted && (0, import_react_dom.createPortal)(
|
|
1648
|
-
/* @__PURE__ */ (0,
|
|
2052
|
+
/* @__PURE__ */ (0, import_jsx_runtime7.jsx)(
|
|
1649
2053
|
ChatModal,
|
|
1650
2054
|
{
|
|
1651
2055
|
title,
|
|
@@ -1657,7 +2061,10 @@ function KikuButton({
|
|
|
1657
2061
|
defaultCurrency,
|
|
1658
2062
|
chips,
|
|
1659
2063
|
theme,
|
|
1660
|
-
classNames
|
|
2064
|
+
classNames,
|
|
2065
|
+
enableVoice,
|
|
2066
|
+
enableVision,
|
|
2067
|
+
visionCategoryHint
|
|
1661
2068
|
}
|
|
1662
2069
|
),
|
|
1663
2070
|
document.body
|
|
@@ -1666,11 +2073,11 @@ function KikuButton({
|
|
|
1666
2073
|
}
|
|
1667
2074
|
|
|
1668
2075
|
// src/components/Sparkle.tsx
|
|
1669
|
-
var
|
|
2076
|
+
var import_react6 = require("react");
|
|
1670
2077
|
var import_react_dom2 = require("react-dom");
|
|
1671
|
-
var
|
|
1672
|
-
var
|
|
1673
|
-
var SparkleIcon3 = ({ className, size = 16 }) => /* @__PURE__ */ (0,
|
|
2078
|
+
var import_sdk7 = require("@akropolys/sdk");
|
|
2079
|
+
var import_jsx_runtime8 = require("react/jsx-runtime");
|
|
2080
|
+
var SparkleIcon3 = ({ className, size = 16 }) => /* @__PURE__ */ (0, import_jsx_runtime8.jsxs)(
|
|
1674
2081
|
"svg",
|
|
1675
2082
|
{
|
|
1676
2083
|
className: cn("hsk-brand-a", className),
|
|
@@ -1681,7 +2088,7 @@ var SparkleIcon3 = ({ className, size = 16 }) => /* @__PURE__ */ (0, import_jsx_
|
|
|
1681
2088
|
xmlns: "http://www.w3.org/2000/svg",
|
|
1682
2089
|
"aria-label": "Akropolys",
|
|
1683
2090
|
children: [
|
|
1684
|
-
/* @__PURE__ */ (0,
|
|
2091
|
+
/* @__PURE__ */ (0, import_jsx_runtime8.jsx)(
|
|
1685
2092
|
"path",
|
|
1686
2093
|
{
|
|
1687
2094
|
d: "M14.5 4.5 L6.5 25",
|
|
@@ -1690,7 +2097,7 @@ var SparkleIcon3 = ({ className, size = 16 }) => /* @__PURE__ */ (0, import_jsx_
|
|
|
1690
2097
|
strokeLinecap: "round"
|
|
1691
2098
|
}
|
|
1692
2099
|
),
|
|
1693
|
-
/* @__PURE__ */ (0,
|
|
2100
|
+
/* @__PURE__ */ (0, import_jsx_runtime8.jsx)(
|
|
1694
2101
|
"path",
|
|
1695
2102
|
{
|
|
1696
2103
|
d: "M14.5 4.5 L22.5 25",
|
|
@@ -1699,7 +2106,7 @@ var SparkleIcon3 = ({ className, size = 16 }) => /* @__PURE__ */ (0, import_jsx_
|
|
|
1699
2106
|
strokeLinecap: "round"
|
|
1700
2107
|
}
|
|
1701
2108
|
),
|
|
1702
|
-
/* @__PURE__ */ (0,
|
|
2109
|
+
/* @__PURE__ */ (0, import_jsx_runtime8.jsx)(
|
|
1703
2110
|
"path",
|
|
1704
2111
|
{
|
|
1705
2112
|
d: "M9.5 17 H19.5",
|
|
@@ -1708,7 +2115,7 @@ var SparkleIcon3 = ({ className, size = 16 }) => /* @__PURE__ */ (0, import_jsx_
|
|
|
1708
2115
|
strokeLinecap: "round"
|
|
1709
2116
|
}
|
|
1710
2117
|
),
|
|
1711
|
-
/* @__PURE__ */ (0,
|
|
2118
|
+
/* @__PURE__ */ (0, import_jsx_runtime8.jsx)(
|
|
1712
2119
|
"path",
|
|
1713
2120
|
{
|
|
1714
2121
|
d: "M3 25 H10",
|
|
@@ -1717,7 +2124,7 @@ var SparkleIcon3 = ({ className, size = 16 }) => /* @__PURE__ */ (0, import_jsx_
|
|
|
1717
2124
|
strokeLinecap: "round"
|
|
1718
2125
|
}
|
|
1719
2126
|
),
|
|
1720
|
-
/* @__PURE__ */ (0,
|
|
2127
|
+
/* @__PURE__ */ (0, import_jsx_runtime8.jsx)(
|
|
1721
2128
|
"path",
|
|
1722
2129
|
{
|
|
1723
2130
|
d: "M19 25 H26",
|
|
@@ -1726,7 +2133,7 @@ var SparkleIcon3 = ({ className, size = 16 }) => /* @__PURE__ */ (0, import_jsx_
|
|
|
1726
2133
|
strokeLinecap: "round"
|
|
1727
2134
|
}
|
|
1728
2135
|
),
|
|
1729
|
-
/* @__PURE__ */ (0,
|
|
2136
|
+
/* @__PURE__ */ (0, import_jsx_runtime8.jsx)(
|
|
1730
2137
|
"path",
|
|
1731
2138
|
{
|
|
1732
2139
|
d: "M8.5 2.5 C10 2.5, 11 3.5, 11 5 C11 7, 8.5 8.5, 7.5 9.5",
|
|
@@ -1740,13 +2147,13 @@ var SparkleIcon3 = ({ className, size = 16 }) => /* @__PURE__ */ (0, import_jsx_
|
|
|
1740
2147
|
]
|
|
1741
2148
|
}
|
|
1742
2149
|
);
|
|
1743
|
-
var CloseIcon2 = () => /* @__PURE__ */ (0,
|
|
1744
|
-
/* @__PURE__ */ (0,
|
|
1745
|
-
/* @__PURE__ */ (0,
|
|
2150
|
+
var CloseIcon2 = () => /* @__PURE__ */ (0, import_jsx_runtime8.jsxs)("svg", { width: "16", height: "16", viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "2.5", strokeLinecap: "round", strokeLinejoin: "round", children: [
|
|
2151
|
+
/* @__PURE__ */ (0, import_jsx_runtime8.jsx)("line", { x1: "18", y1: "6", x2: "6", y2: "18" }),
|
|
2152
|
+
/* @__PURE__ */ (0, import_jsx_runtime8.jsx)("line", { x1: "6", y1: "6", x2: "18", y2: "18" })
|
|
1746
2153
|
] });
|
|
1747
|
-
var ArrowUpIcon3 = () => /* @__PURE__ */ (0,
|
|
1748
|
-
/* @__PURE__ */ (0,
|
|
1749
|
-
/* @__PURE__ */ (0,
|
|
2154
|
+
var ArrowUpIcon3 = () => /* @__PURE__ */ (0, import_jsx_runtime8.jsxs)("svg", { width: "18", height: "18", viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "2", strokeLinecap: "round", strokeLinejoin: "round", children: [
|
|
2155
|
+
/* @__PURE__ */ (0, import_jsx_runtime8.jsx)("path", { d: "m5 12 7-7 7 7" }),
|
|
2156
|
+
/* @__PURE__ */ (0, import_jsx_runtime8.jsx)("path", { d: "M12 19V5" })
|
|
1750
2157
|
] });
|
|
1751
2158
|
var getFriendlyError2 = (err) => {
|
|
1752
2159
|
let str = "";
|
|
@@ -1779,18 +2186,18 @@ function SparkleModal({
|
|
|
1779
2186
|
classNames = {},
|
|
1780
2187
|
product: initialProduct
|
|
1781
2188
|
}) {
|
|
1782
|
-
const client = (0,
|
|
1783
|
-
const [fetchedProduct, setFetchedProduct] = (0,
|
|
2189
|
+
const client = (0, import_sdk7.useAkropolysContext)();
|
|
2190
|
+
const [fetchedProduct, setFetchedProduct] = (0, import_react6.useState)(null);
|
|
1784
2191
|
const displayProduct = initialProduct || fetchedProduct;
|
|
1785
|
-
const { results, loading: searchLoading, search } = (0,
|
|
1786
|
-
const { messages, sources, loading: chatLoading, error: chatError, send } = (0,
|
|
1787
|
-
const [chatInput, setChatInput] = (0,
|
|
1788
|
-
const [isMobile, setIsMobile] = (0,
|
|
1789
|
-
const [showSpecs, setShowSpecs] = (0,
|
|
1790
|
-
const [collapseSimilar, setCollapseSimilar] = (0,
|
|
1791
|
-
const chatBottomRef = (0,
|
|
1792
|
-
const chatTextareaRef = (0,
|
|
1793
|
-
(0,
|
|
2192
|
+
const { results, loading: searchLoading, search } = (0, import_sdk7.useSearch)();
|
|
2193
|
+
const { messages, sources, loading: chatLoading, error: chatError, send } = (0, import_sdk7.useKiku)();
|
|
2194
|
+
const [chatInput, setChatInput] = (0, import_react6.useState)("");
|
|
2195
|
+
const [isMobile, setIsMobile] = (0, import_react6.useState)(false);
|
|
2196
|
+
const [showSpecs, setShowSpecs] = (0, import_react6.useState)(false);
|
|
2197
|
+
const [collapseSimilar, setCollapseSimilar] = (0, import_react6.useState)(false);
|
|
2198
|
+
const chatBottomRef = (0, import_react6.useRef)(null);
|
|
2199
|
+
const chatTextareaRef = (0, import_react6.useRef)(null);
|
|
2200
|
+
(0, import_react6.useEffect)(() => {
|
|
1794
2201
|
if (!initialProduct && !fetchedProduct) {
|
|
1795
2202
|
client.api.searchVector(productName, 1).then((res) => {
|
|
1796
2203
|
if (res.results && res.results.length > 0) {
|
|
@@ -1800,7 +2207,7 @@ function SparkleModal({
|
|
|
1800
2207
|
}
|
|
1801
2208
|
search(productName, limit);
|
|
1802
2209
|
}, [productName, initialProduct, fetchedProduct, client, limit, search]);
|
|
1803
|
-
(0,
|
|
2210
|
+
(0, import_react6.useEffect)(() => {
|
|
1804
2211
|
const handleResize = () => setIsMobile(window.innerWidth <= 768);
|
|
1805
2212
|
handleResize();
|
|
1806
2213
|
if (typeof window !== "undefined") {
|
|
@@ -1808,17 +2215,17 @@ function SparkleModal({
|
|
|
1808
2215
|
return () => window.removeEventListener("resize", handleResize);
|
|
1809
2216
|
}
|
|
1810
2217
|
}, []);
|
|
1811
|
-
(0,
|
|
2218
|
+
(0, import_react6.useEffect)(() => {
|
|
1812
2219
|
if (results.length > 0) onResult?.(results);
|
|
1813
2220
|
}, [results, onResult]);
|
|
1814
|
-
(0,
|
|
2221
|
+
(0, import_react6.useEffect)(() => {
|
|
1815
2222
|
const h = (e) => {
|
|
1816
2223
|
if (e.key === "Escape") onClose();
|
|
1817
2224
|
};
|
|
1818
2225
|
document.addEventListener("keydown", h);
|
|
1819
2226
|
return () => document.removeEventListener("keydown", h);
|
|
1820
2227
|
}, [onClose]);
|
|
1821
|
-
(0,
|
|
2228
|
+
(0, import_react6.useEffect)(() => {
|
|
1822
2229
|
chatBottomRef.current?.scrollIntoView({ behavior: "smooth" });
|
|
1823
2230
|
}, [messages, chatLoading]);
|
|
1824
2231
|
const blurVal = typeof backdropBlur === "number" ? `${backdropBlur}px` : backdropBlur ?? "16px";
|
|
@@ -1872,7 +2279,7 @@ Question: ${q}`;
|
|
|
1872
2279
|
}
|
|
1873
2280
|
] : messages;
|
|
1874
2281
|
if (isMobile) {
|
|
1875
|
-
return /* @__PURE__ */ (0,
|
|
2282
|
+
return /* @__PURE__ */ (0, import_jsx_runtime8.jsx)(
|
|
1876
2283
|
"div",
|
|
1877
2284
|
{
|
|
1878
2285
|
className: cn("hsk-sp-backdrop hsk-sp-mobile-view", classNames.backdrop),
|
|
@@ -1883,13 +2290,13 @@ Question: ${q}`;
|
|
|
1883
2290
|
background: bg ?? void 0,
|
|
1884
2291
|
...customStyles
|
|
1885
2292
|
},
|
|
1886
|
-
children: /* @__PURE__ */ (0,
|
|
1887
|
-
/* @__PURE__ */ (0,
|
|
1888
|
-
/* @__PURE__ */ (0,
|
|
1889
|
-
/* @__PURE__ */ (0,
|
|
1890
|
-
/* @__PURE__ */ (0,
|
|
1891
|
-
/* @__PURE__ */ (0,
|
|
1892
|
-
displayProduct && /* @__PURE__ */ (0,
|
|
2293
|
+
children: /* @__PURE__ */ (0, import_jsx_runtime8.jsxs)("div", { className: cn("hsk-sp-card hsk-sp-fullscreen hsk-sp-mobile-card", classNames.card), onClick: (e) => e.stopPropagation(), children: [
|
|
2294
|
+
/* @__PURE__ */ (0, import_jsx_runtime8.jsxs)("div", { className: "hsk-sp-header", children: [
|
|
2295
|
+
/* @__PURE__ */ (0, import_jsx_runtime8.jsx)("span", { className: "hsk-sp-header-icon", style: { display: "flex", alignItems: "center" }, children: /* @__PURE__ */ (0, import_jsx_runtime8.jsx)(SparkleIcon3, {}) }),
|
|
2296
|
+
/* @__PURE__ */ (0, import_jsx_runtime8.jsxs)("div", { className: "hsk-sp-header-body", children: [
|
|
2297
|
+
/* @__PURE__ */ (0, import_jsx_runtime8.jsxs)("div", { className: "hsk-sp-header-title-row", children: [
|
|
2298
|
+
/* @__PURE__ */ (0, import_jsx_runtime8.jsx)("div", { className: "hsk-sp-header-title", children: displayProduct?.name || productName }),
|
|
2299
|
+
displayProduct && /* @__PURE__ */ (0, import_jsx_runtime8.jsx)(
|
|
1893
2300
|
"button",
|
|
1894
2301
|
{
|
|
1895
2302
|
type: "button",
|
|
@@ -1899,32 +2306,32 @@ Question: ${q}`;
|
|
|
1899
2306
|
}
|
|
1900
2307
|
)
|
|
1901
2308
|
] }),
|
|
1902
|
-
/* @__PURE__ */ (0,
|
|
2309
|
+
/* @__PURE__ */ (0, import_jsx_runtime8.jsx)("div", { className: "hsk-sp-header-sub", children: "Akropolys AI Shopping Assistant" })
|
|
1903
2310
|
] }),
|
|
1904
|
-
/* @__PURE__ */ (0,
|
|
2311
|
+
/* @__PURE__ */ (0, import_jsx_runtime8.jsx)("button", { className: "hsk-sp-close", onClick: onClose, "aria-label": "Close", children: /* @__PURE__ */ (0, import_jsx_runtime8.jsx)(CloseIcon2, {}) })
|
|
1905
2312
|
] }),
|
|
1906
|
-
searchLoading && /* @__PURE__ */ (0,
|
|
1907
|
-
/* @__PURE__ */ (0,
|
|
1908
|
-
/* @__PURE__ */ (0,
|
|
2313
|
+
searchLoading && /* @__PURE__ */ (0, import_jsx_runtime8.jsx)("div", { className: "hsk-sp-bar" }),
|
|
2314
|
+
/* @__PURE__ */ (0, import_jsx_runtime8.jsxs)("div", { className: "hsk-sp-mobile-chat-container", children: [
|
|
2315
|
+
/* @__PURE__ */ (0, import_jsx_runtime8.jsxs)("div", { className: "hsk-cb-msgs", children: [
|
|
1909
2316
|
displayMessages.map((msg, idx) => {
|
|
1910
2317
|
const isUser = msg.role === "user";
|
|
1911
|
-
return /* @__PURE__ */ (0,
|
|
1912
|
-
/* @__PURE__ */ (0,
|
|
1913
|
-
/* @__PURE__ */ (0,
|
|
1914
|
-
/* @__PURE__ */ (0,
|
|
1915
|
-
idx === 0 && displayProduct && /* @__PURE__ */ (0,
|
|
1916
|
-
/* @__PURE__ */ (0,
|
|
1917
|
-
/* @__PURE__ */ (0,
|
|
1918
|
-
/* @__PURE__ */ (0,
|
|
1919
|
-
/* @__PURE__ */ (0,
|
|
1920
|
-
/* @__PURE__ */ (0,
|
|
1921
|
-
/* @__PURE__ */ (0,
|
|
2318
|
+
return /* @__PURE__ */ (0, import_jsx_runtime8.jsx)("div", { className: "hsk-cb-msg-group", children: isUser ? /* @__PURE__ */ (0, import_jsx_runtime8.jsx)("div", { className: "hsk-cb-user-msg", children: /* @__PURE__ */ (0, import_jsx_runtime8.jsx)("div", { className: "hsk-cb-user-bubble", children: msg.content }) }) : /* @__PURE__ */ (0, import_jsx_runtime8.jsxs)("div", { className: "hsk-cb-ai-msg", children: [
|
|
2319
|
+
/* @__PURE__ */ (0, import_jsx_runtime8.jsx)("div", { className: "hsk-cb-ai-icon", style: { display: "flex", alignItems: "center" }, children: /* @__PURE__ */ (0, import_jsx_runtime8.jsx)(SparkleIcon3, {}) }),
|
|
2320
|
+
/* @__PURE__ */ (0, import_jsx_runtime8.jsxs)("div", { className: "hsk-cb-ai-body", children: [
|
|
2321
|
+
/* @__PURE__ */ (0, import_jsx_runtime8.jsx)("div", { className: "hsk-cb-ai-text", children: renderMarkdown(msg.content) }),
|
|
2322
|
+
idx === 0 && displayProduct && /* @__PURE__ */ (0, import_jsx_runtime8.jsxs)("div", { className: "hsk-sp-mobile-attachment-deck", children: [
|
|
2323
|
+
/* @__PURE__ */ (0, import_jsx_runtime8.jsxs)("div", { className: "hsk-sp-mobile-main-card", children: [
|
|
2324
|
+
/* @__PURE__ */ (0, import_jsx_runtime8.jsx)("div", { className: "hsk-sp-mobile-main-card-img", children: displayProduct.images?.[0] ? /* @__PURE__ */ (0, import_jsx_runtime8.jsx)("img", { src: displayProduct.images[0], alt: displayProduct.name }) : /* @__PURE__ */ (0, import_jsx_runtime8.jsx)("span", { children: "\u{1F6CD}" }) }),
|
|
2325
|
+
/* @__PURE__ */ (0, import_jsx_runtime8.jsxs)("div", { className: "hsk-sp-mobile-main-card-info", children: [
|
|
2326
|
+
/* @__PURE__ */ (0, import_jsx_runtime8.jsx)("div", { className: "hsk-sp-mobile-main-card-brand", children: displayProduct.brand || displayProduct.category || "Product" }),
|
|
2327
|
+
/* @__PURE__ */ (0, import_jsx_runtime8.jsx)("div", { className: "hsk-sp-mobile-main-card-name", children: displayProduct.name }),
|
|
2328
|
+
/* @__PURE__ */ (0, import_jsx_runtime8.jsxs)("div", { className: "hsk-sp-mobile-main-card-price", children: [
|
|
1922
2329
|
displayProduct.currency ?? "KES",
|
|
1923
2330
|
" ",
|
|
1924
2331
|
parseFloat(displayProduct.price?.replace(/[^0-9.]/g, "") || "0").toLocaleString()
|
|
1925
2332
|
] })
|
|
1926
2333
|
] }),
|
|
1927
|
-
(displayProduct.specs && Object.keys(displayProduct.specs).length > 0 || displayProduct.description) && /* @__PURE__ */ (0,
|
|
2334
|
+
(displayProduct.specs && Object.keys(displayProduct.specs).length > 0 || displayProduct.description) && /* @__PURE__ */ (0, import_jsx_runtime8.jsx)(
|
|
1928
2335
|
"button",
|
|
1929
2336
|
{
|
|
1930
2337
|
type: "button",
|
|
@@ -1943,21 +2350,21 @@ Question: ${q}`;
|
|
|
1943
2350
|
}
|
|
1944
2351
|
);
|
|
1945
2352
|
if (similarProducts.length === 0) return null;
|
|
1946
|
-
return /* @__PURE__ */ (0,
|
|
1947
|
-
/* @__PURE__ */ (0,
|
|
1948
|
-
/* @__PURE__ */ (0,
|
|
2353
|
+
return /* @__PURE__ */ (0, import_jsx_runtime8.jsxs)("div", { className: "hsk-sp-mobile-similar-carousel-inline", children: [
|
|
2354
|
+
/* @__PURE__ */ (0, import_jsx_runtime8.jsx)("div", { className: "hsk-sp-mobile-similar-carousel-title", children: "Similar Products" }),
|
|
2355
|
+
/* @__PURE__ */ (0, import_jsx_runtime8.jsx)("div", { className: "hsk-sp-mobile-similar-carousel-list", children: similarProducts.map((r) => {
|
|
1949
2356
|
const price = parseFloat(r.product.price?.replace(/[^0-9.]/g, "") || "0");
|
|
1950
2357
|
const currency = r.product.currency ?? "KES";
|
|
1951
|
-
return /* @__PURE__ */ (0,
|
|
2358
|
+
return /* @__PURE__ */ (0, import_jsx_runtime8.jsxs)(
|
|
1952
2359
|
"div",
|
|
1953
2360
|
{
|
|
1954
2361
|
className: "hsk-sp-mobile-similar-carousel-item",
|
|
1955
2362
|
onClick: () => handleNav(r),
|
|
1956
2363
|
children: [
|
|
1957
|
-
/* @__PURE__ */ (0,
|
|
1958
|
-
/* @__PURE__ */ (0,
|
|
1959
|
-
/* @__PURE__ */ (0,
|
|
1960
|
-
/* @__PURE__ */ (0,
|
|
2364
|
+
/* @__PURE__ */ (0, import_jsx_runtime8.jsx)("div", { className: "hsk-sp-mobile-similar-carousel-img", children: r.product.images?.[0] ? /* @__PURE__ */ (0, import_jsx_runtime8.jsx)("img", { src: r.product.images[0], alt: r.product.name }) : /* @__PURE__ */ (0, import_jsx_runtime8.jsx)("span", { children: "\u{1F6CD}" }) }),
|
|
2365
|
+
/* @__PURE__ */ (0, import_jsx_runtime8.jsxs)("div", { className: "hsk-sp-mobile-similar-carousel-meta", children: [
|
|
2366
|
+
/* @__PURE__ */ (0, import_jsx_runtime8.jsx)("div", { className: "hsk-sp-mobile-similar-carousel-name", title: r.product.name, children: r.product.name }),
|
|
2367
|
+
/* @__PURE__ */ (0, import_jsx_runtime8.jsxs)("div", { className: "hsk-sp-mobile-similar-carousel-price", children: [
|
|
1961
2368
|
currency,
|
|
1962
2369
|
" ",
|
|
1963
2370
|
price.toLocaleString()
|
|
@@ -1974,19 +2381,19 @@ Question: ${q}`;
|
|
|
1974
2381
|
] })
|
|
1975
2382
|
] }) }, idx);
|
|
1976
2383
|
}),
|
|
1977
|
-
chatLoading && /* @__PURE__ */ (0,
|
|
1978
|
-
/* @__PURE__ */ (0,
|
|
1979
|
-
/* @__PURE__ */ (0,
|
|
1980
|
-
/* @__PURE__ */ (0,
|
|
1981
|
-
/* @__PURE__ */ (0,
|
|
1982
|
-
/* @__PURE__ */ (0,
|
|
2384
|
+
chatLoading && /* @__PURE__ */ (0, import_jsx_runtime8.jsxs)("div", { className: "hsk-cb-typing-row", children: [
|
|
2385
|
+
/* @__PURE__ */ (0, import_jsx_runtime8.jsx)("div", { className: "hsk-cb-ai-icon", style: { display: "flex", alignItems: "center" }, children: /* @__PURE__ */ (0, import_jsx_runtime8.jsx)(SparkleIcon3, {}) }),
|
|
2386
|
+
/* @__PURE__ */ (0, import_jsx_runtime8.jsxs)("div", { className: "hsk-cb-typing", children: [
|
|
2387
|
+
/* @__PURE__ */ (0, import_jsx_runtime8.jsx)("div", { className: "hsk-cb-dot" }),
|
|
2388
|
+
/* @__PURE__ */ (0, import_jsx_runtime8.jsx)("div", { className: "hsk-cb-dot" }),
|
|
2389
|
+
/* @__PURE__ */ (0, import_jsx_runtime8.jsx)("div", { className: "hsk-cb-dot" })
|
|
1983
2390
|
] })
|
|
1984
2391
|
] }),
|
|
1985
|
-
chatError && /* @__PURE__ */ (0,
|
|
1986
|
-
/* @__PURE__ */ (0,
|
|
2392
|
+
chatError && /* @__PURE__ */ (0, import_jsx_runtime8.jsx)("div", { className: "hsk-cb-error", children: getFriendlyError2(chatError) }),
|
|
2393
|
+
/* @__PURE__ */ (0, import_jsx_runtime8.jsx)("div", { ref: chatBottomRef, style: { height: 1 } })
|
|
1987
2394
|
] }),
|
|
1988
|
-
/* @__PURE__ */ (0,
|
|
1989
|
-
/* @__PURE__ */ (0,
|
|
2395
|
+
/* @__PURE__ */ (0, import_jsx_runtime8.jsx)("div", { className: "hsk-cb-input-wrap", children: /* @__PURE__ */ (0, import_jsx_runtime8.jsxs)("div", { className: "hsk-cb-input-box", children: [
|
|
2396
|
+
/* @__PURE__ */ (0, import_jsx_runtime8.jsx)(
|
|
1990
2397
|
"textarea",
|
|
1991
2398
|
{
|
|
1992
2399
|
ref: chatTextareaRef,
|
|
@@ -1999,34 +2406,34 @@ Question: ${q}`;
|
|
|
1999
2406
|
disabled: chatLoading
|
|
2000
2407
|
}
|
|
2001
2408
|
),
|
|
2002
|
-
/* @__PURE__ */ (0,
|
|
2409
|
+
/* @__PURE__ */ (0, import_jsx_runtime8.jsx)(
|
|
2003
2410
|
"button",
|
|
2004
2411
|
{
|
|
2005
2412
|
className: "hsk-cb-send",
|
|
2006
2413
|
onClick: () => handleSend(),
|
|
2007
2414
|
disabled: !chatInput.trim() || chatLoading,
|
|
2008
2415
|
"aria-label": "Send message",
|
|
2009
|
-
children: /* @__PURE__ */ (0,
|
|
2416
|
+
children: /* @__PURE__ */ (0, import_jsx_runtime8.jsx)(ArrowUpIcon3, {})
|
|
2010
2417
|
}
|
|
2011
2418
|
)
|
|
2012
2419
|
] }) })
|
|
2013
2420
|
] }),
|
|
2014
|
-
showSpecs && displayProduct && /* @__PURE__ */ (0,
|
|
2015
|
-
/* @__PURE__ */ (0,
|
|
2016
|
-
/* @__PURE__ */ (0,
|
|
2017
|
-
/* @__PURE__ */ (0,
|
|
2421
|
+
showSpecs && displayProduct && /* @__PURE__ */ (0, import_jsx_runtime8.jsx)("div", { className: "hsk-sp-mobile-specs-overlay", onClick: () => setShowSpecs(false), children: /* @__PURE__ */ (0, import_jsx_runtime8.jsxs)("div", { className: "hsk-sp-mobile-specs-drawer", onClick: (e) => e.stopPropagation(), children: [
|
|
2422
|
+
/* @__PURE__ */ (0, import_jsx_runtime8.jsxs)("div", { className: "hsk-sp-mobile-specs-header", children: [
|
|
2423
|
+
/* @__PURE__ */ (0, import_jsx_runtime8.jsx)("h3", { children: "Specifications" }),
|
|
2424
|
+
/* @__PURE__ */ (0, import_jsx_runtime8.jsx)("button", { type: "button", onClick: () => setShowSpecs(false), children: "Close" })
|
|
2018
2425
|
] }),
|
|
2019
|
-
/* @__PURE__ */ (0,
|
|
2020
|
-
/* @__PURE__ */ (0,
|
|
2021
|
-
displayProduct.description && /* @__PURE__ */ (0,
|
|
2022
|
-
/* @__PURE__ */ (0,
|
|
2023
|
-
/* @__PURE__ */ (0,
|
|
2426
|
+
/* @__PURE__ */ (0, import_jsx_runtime8.jsxs)("div", { className: "hsk-sp-mobile-specs-body", children: [
|
|
2427
|
+
/* @__PURE__ */ (0, import_jsx_runtime8.jsx)("h4", { className: "hsk-sp-mobile-specs-title", children: displayProduct.name }),
|
|
2428
|
+
displayProduct.description && /* @__PURE__ */ (0, import_jsx_runtime8.jsxs)("div", { className: "hsk-sp-mobile-specs-desc", children: [
|
|
2429
|
+
/* @__PURE__ */ (0, import_jsx_runtime8.jsx)("h5", { children: "Description" }),
|
|
2430
|
+
/* @__PURE__ */ (0, import_jsx_runtime8.jsx)("p", { children: displayProduct.description })
|
|
2024
2431
|
] }),
|
|
2025
|
-
displayProduct.specs && Object.keys(displayProduct.specs).length > 0 && /* @__PURE__ */ (0,
|
|
2026
|
-
/* @__PURE__ */ (0,
|
|
2027
|
-
Object.entries(displayProduct.specs).map(([key, val]) => /* @__PURE__ */ (0,
|
|
2028
|
-
/* @__PURE__ */ (0,
|
|
2029
|
-
/* @__PURE__ */ (0,
|
|
2432
|
+
displayProduct.specs && Object.keys(displayProduct.specs).length > 0 && /* @__PURE__ */ (0, import_jsx_runtime8.jsxs)("div", { className: "hsk-sp-mobile-specs-list", children: [
|
|
2433
|
+
/* @__PURE__ */ (0, import_jsx_runtime8.jsx)("h5", { children: "Details" }),
|
|
2434
|
+
Object.entries(displayProduct.specs).map(([key, val]) => /* @__PURE__ */ (0, import_jsx_runtime8.jsxs)("div", { className: "hsk-sp-mobile-spec-row", children: [
|
|
2435
|
+
/* @__PURE__ */ (0, import_jsx_runtime8.jsx)("span", { className: "hsk-sp-mobile-spec-label", children: key }),
|
|
2436
|
+
/* @__PURE__ */ (0, import_jsx_runtime8.jsx)("span", { className: "hsk-sp-mobile-spec-value", children: val })
|
|
2030
2437
|
] }, key))
|
|
2031
2438
|
] })
|
|
2032
2439
|
] })
|
|
@@ -2035,7 +2442,7 @@ Question: ${q}`;
|
|
|
2035
2442
|
}
|
|
2036
2443
|
);
|
|
2037
2444
|
}
|
|
2038
|
-
return /* @__PURE__ */ (0,
|
|
2445
|
+
return /* @__PURE__ */ (0, import_jsx_runtime8.jsx)(
|
|
2039
2446
|
"div",
|
|
2040
2447
|
{
|
|
2041
2448
|
className: cn("hsk-sp-backdrop", classNames.backdrop),
|
|
@@ -2046,65 +2453,65 @@ Question: ${q}`;
|
|
|
2046
2453
|
background: bg ?? void 0,
|
|
2047
2454
|
...customStyles
|
|
2048
2455
|
},
|
|
2049
|
-
children: /* @__PURE__ */ (0,
|
|
2050
|
-
/* @__PURE__ */ (0,
|
|
2051
|
-
/* @__PURE__ */ (0,
|
|
2052
|
-
/* @__PURE__ */ (0,
|
|
2053
|
-
/* @__PURE__ */ (0,
|
|
2054
|
-
/* @__PURE__ */ (0,
|
|
2456
|
+
children: /* @__PURE__ */ (0, import_jsx_runtime8.jsxs)("div", { className: cn("hsk-sp-card hsk-sp-fullscreen", classNames.card), onClick: (e) => e.stopPropagation(), children: [
|
|
2457
|
+
/* @__PURE__ */ (0, import_jsx_runtime8.jsxs)("div", { className: "hsk-sp-header", children: [
|
|
2458
|
+
/* @__PURE__ */ (0, import_jsx_runtime8.jsx)("span", { className: "hsk-sp-header-icon", style: { display: "flex", alignItems: "center" }, children: /* @__PURE__ */ (0, import_jsx_runtime8.jsx)(SparkleIcon3, {}) }),
|
|
2459
|
+
/* @__PURE__ */ (0, import_jsx_runtime8.jsxs)("div", { className: "hsk-sp-header-body", children: [
|
|
2460
|
+
/* @__PURE__ */ (0, import_jsx_runtime8.jsx)("div", { className: "hsk-sp-header-title", children: displayProduct?.name || productName }),
|
|
2461
|
+
/* @__PURE__ */ (0, import_jsx_runtime8.jsx)("div", { className: "hsk-sp-header-sub", children: "Ask questions, compare specs, or check similar products" })
|
|
2055
2462
|
] }),
|
|
2056
|
-
/* @__PURE__ */ (0,
|
|
2463
|
+
/* @__PURE__ */ (0, import_jsx_runtime8.jsx)("button", { className: "hsk-sp-close", onClick: onClose, "aria-label": "Close", children: /* @__PURE__ */ (0, import_jsx_runtime8.jsx)(CloseIcon2, {}) })
|
|
2057
2464
|
] }),
|
|
2058
|
-
searchLoading && /* @__PURE__ */ (0,
|
|
2059
|
-
/* @__PURE__ */ (0,
|
|
2060
|
-
/* @__PURE__ */ (0,
|
|
2061
|
-
displayProduct && /* @__PURE__ */ (0,
|
|
2062
|
-
/* @__PURE__ */ (0,
|
|
2063
|
-
/* @__PURE__ */ (0,
|
|
2064
|
-
/* @__PURE__ */ (0,
|
|
2065
|
-
displayProduct.brand && /* @__PURE__ */ (0,
|
|
2066
|
-
displayProduct.category && /* @__PURE__ */ (0,
|
|
2067
|
-
/* @__PURE__ */ (0,
|
|
2068
|
-
/* @__PURE__ */ (0,
|
|
2069
|
-
/* @__PURE__ */ (0,
|
|
2070
|
-
/* @__PURE__ */ (0,
|
|
2071
|
-
displayProduct.originalPrice && /* @__PURE__ */ (0,
|
|
2072
|
-
displayProduct.discount && /* @__PURE__ */ (0,
|
|
2465
|
+
searchLoading && /* @__PURE__ */ (0, import_jsx_runtime8.jsx)("div", { className: "hsk-sp-bar" }),
|
|
2466
|
+
/* @__PURE__ */ (0, import_jsx_runtime8.jsxs)("div", { className: "hsk-sp-body", children: [
|
|
2467
|
+
/* @__PURE__ */ (0, import_jsx_runtime8.jsxs)("div", { className: "hsk-sp-details-pane", children: [
|
|
2468
|
+
displayProduct && /* @__PURE__ */ (0, import_jsx_runtime8.jsxs)("div", { className: "hsk-sp-product-profile-container", children: [
|
|
2469
|
+
/* @__PURE__ */ (0, import_jsx_runtime8.jsxs)("div", { className: "hsk-sp-product-profile", children: [
|
|
2470
|
+
/* @__PURE__ */ (0, import_jsx_runtime8.jsx)("div", { className: "hsk-sp-details-imgwrap", children: displayProduct.images?.[0] ? /* @__PURE__ */ (0, import_jsx_runtime8.jsx)("img", { src: displayProduct.images[0], alt: displayProduct.name }) : /* @__PURE__ */ (0, import_jsx_runtime8.jsx)("span", { className: "hsk-sp-img-placeholder", children: "\u{1F6CD}" }) }),
|
|
2471
|
+
/* @__PURE__ */ (0, import_jsx_runtime8.jsxs)("div", { className: "hsk-sp-details-meta", children: [
|
|
2472
|
+
displayProduct.brand && /* @__PURE__ */ (0, import_jsx_runtime8.jsx)("span", { className: "hsk-sp-item-brand", children: displayProduct.brand }),
|
|
2473
|
+
displayProduct.category && /* @__PURE__ */ (0, import_jsx_runtime8.jsx)("span", { className: "hsk-sp-item-cat", children: displayProduct.category }),
|
|
2474
|
+
/* @__PURE__ */ (0, import_jsx_runtime8.jsx)("h2", { className: "hsk-sp-details-name", children: displayProduct.name }),
|
|
2475
|
+
/* @__PURE__ */ (0, import_jsx_runtime8.jsxs)("div", { className: "hsk-sp-item-price-row", children: [
|
|
2476
|
+
/* @__PURE__ */ (0, import_jsx_runtime8.jsx)("span", { className: "hsk-sp-item-currency", children: displayProduct.currency ?? "KES" }),
|
|
2477
|
+
/* @__PURE__ */ (0, import_jsx_runtime8.jsx)("span", { className: "hsk-sp-item-price", children: parseFloat(displayProduct.price?.replace(/[^0-9.]/g, "") || "0").toLocaleString() }),
|
|
2478
|
+
displayProduct.originalPrice && /* @__PURE__ */ (0, import_jsx_runtime8.jsx)("span", { className: "hsk-sp-item-original-price", children: parseFloat(displayProduct.originalPrice.replace(/[^0-9.]/g, "") || "0").toLocaleString() }),
|
|
2479
|
+
displayProduct.discount && /* @__PURE__ */ (0, import_jsx_runtime8.jsxs)("span", { className: "hsk-sp-item-discount", children: [
|
|
2073
2480
|
"(",
|
|
2074
2481
|
displayProduct.discount,
|
|
2075
2482
|
")"
|
|
2076
2483
|
] })
|
|
2077
2484
|
] }),
|
|
2078
|
-
/* @__PURE__ */ (0,
|
|
2079
|
-
displayProduct.rating && /* @__PURE__ */ (0,
|
|
2485
|
+
/* @__PURE__ */ (0, import_jsx_runtime8.jsxs)("div", { className: "hsk-sp-item-meta-badges", children: [
|
|
2486
|
+
displayProduct.rating && /* @__PURE__ */ (0, import_jsx_runtime8.jsxs)("span", { className: "hsk-sp-meta-badge hsk-sp-meta-badge-rating", children: [
|
|
2080
2487
|
"\u2605 ",
|
|
2081
2488
|
parseFloat(displayProduct.rating.toString()).toFixed(1),
|
|
2082
2489
|
" ",
|
|
2083
2490
|
displayProduct.reviewCount ? `(${displayProduct.reviewCount})` : ""
|
|
2084
2491
|
] }),
|
|
2085
|
-
displayProduct.availability && /* @__PURE__ */ (0,
|
|
2086
|
-
displayProduct.stock && !displayProduct.availability && /* @__PURE__ */ (0,
|
|
2492
|
+
displayProduct.availability && /* @__PURE__ */ (0, import_jsx_runtime8.jsx)("span", { className: `hsk-sp-meta-badge hsk-sp-meta-badge-avail ${displayProduct.availability.toLowerCase().includes("in") ? "in-stock" : "out-stock"}`, children: displayProduct.availability }),
|
|
2493
|
+
displayProduct.stock && !displayProduct.availability && /* @__PURE__ */ (0, import_jsx_runtime8.jsxs)("span", { className: "hsk-sp-meta-badge hsk-sp-meta-badge-stock", children: [
|
|
2087
2494
|
"Stock: ",
|
|
2088
2495
|
displayProduct.stock
|
|
2089
2496
|
] })
|
|
2090
2497
|
] })
|
|
2091
2498
|
] })
|
|
2092
2499
|
] }),
|
|
2093
|
-
displayProduct.specs && Object.keys(displayProduct.specs).length > 0 && /* @__PURE__ */ (0,
|
|
2094
|
-
/* @__PURE__ */ (0,
|
|
2500
|
+
displayProduct.specs && Object.keys(displayProduct.specs).length > 0 && /* @__PURE__ */ (0, import_jsx_runtime8.jsx)("div", { className: "hsk-sp-specs-horizontal", children: Object.entries(displayProduct.specs).map(([key, val]) => /* @__PURE__ */ (0, import_jsx_runtime8.jsxs)("div", { className: "hsk-sp-spec-item-horizontal", children: [
|
|
2501
|
+
/* @__PURE__ */ (0, import_jsx_runtime8.jsxs)("span", { className: "hsk-sp-spec-label-horizontal", children: [
|
|
2095
2502
|
key,
|
|
2096
2503
|
":"
|
|
2097
2504
|
] }),
|
|
2098
|
-
/* @__PURE__ */ (0,
|
|
2505
|
+
/* @__PURE__ */ (0, import_jsx_runtime8.jsx)("span", { className: "hsk-sp-spec-value-horizontal", title: val, children: val })
|
|
2099
2506
|
] }, key)) }),
|
|
2100
|
-
displayProduct.description && /* @__PURE__ */ (0,
|
|
2101
|
-
/* @__PURE__ */ (0,
|
|
2102
|
-
/* @__PURE__ */ (0,
|
|
2507
|
+
displayProduct.description && /* @__PURE__ */ (0, import_jsx_runtime8.jsxs)("div", { className: "hsk-sp-details-desc", children: [
|
|
2508
|
+
/* @__PURE__ */ (0, import_jsx_runtime8.jsx)("h4", { children: "Description" }),
|
|
2509
|
+
/* @__PURE__ */ (0, import_jsx_runtime8.jsx)("p", { children: displayProduct.description })
|
|
2103
2510
|
] })
|
|
2104
2511
|
] }),
|
|
2105
|
-
/* @__PURE__ */ (0,
|
|
2106
|
-
/* @__PURE__ */ (0,
|
|
2107
|
-
/* @__PURE__ */ (0,
|
|
2512
|
+
/* @__PURE__ */ (0, import_jsx_runtime8.jsxs)("div", { className: "hsk-sp-similar-section", children: [
|
|
2513
|
+
/* @__PURE__ */ (0, import_jsx_runtime8.jsx)("h3", { children: "Similar Products" }),
|
|
2514
|
+
/* @__PURE__ */ (0, import_jsx_runtime8.jsx)("div", { className: "hsk-sp-results", children: (() => {
|
|
2108
2515
|
const similarProducts = results.filter(
|
|
2109
2516
|
(r) => {
|
|
2110
2517
|
const isSameName = r.product.name.toLowerCase() === displayProduct?.name?.toLowerCase();
|
|
@@ -2113,29 +2520,29 @@ Question: ${q}`;
|
|
|
2113
2520
|
}
|
|
2114
2521
|
);
|
|
2115
2522
|
if (!searchLoading && similarProducts.length === 0) {
|
|
2116
|
-
return /* @__PURE__ */ (0,
|
|
2523
|
+
return /* @__PURE__ */ (0, import_jsx_runtime8.jsx)("div", { className: "hsk-sp-empty", children: "No similar products found." });
|
|
2117
2524
|
}
|
|
2118
2525
|
return similarProducts.map((r, i) => {
|
|
2119
2526
|
const price = parseFloat(r.product.price?.replace(/[^0-9.]/g, "") || "0");
|
|
2120
2527
|
const currency = r.product.currency ?? "KES";
|
|
2121
|
-
return /* @__PURE__ */ (0,
|
|
2528
|
+
return /* @__PURE__ */ (0, import_jsx_runtime8.jsxs)(
|
|
2122
2529
|
"div",
|
|
2123
2530
|
{
|
|
2124
2531
|
className: cn("hsk-sp-item", classNames.item),
|
|
2125
2532
|
style: { animationDelay: `${i * 55}ms`, cursor: "pointer" },
|
|
2126
2533
|
onClick: () => handleNav(r),
|
|
2127
2534
|
children: [
|
|
2128
|
-
/* @__PURE__ */ (0,
|
|
2129
|
-
/* @__PURE__ */ (0,
|
|
2130
|
-
/* @__PURE__ */ (0,
|
|
2131
|
-
r.product.category && /* @__PURE__ */ (0,
|
|
2132
|
-
/* @__PURE__ */ (0,
|
|
2535
|
+
/* @__PURE__ */ (0, import_jsx_runtime8.jsx)("div", { className: "hsk-sp-img-wrap", children: r.product.images?.[0] ? /* @__PURE__ */ (0, import_jsx_runtime8.jsx)("img", { src: r.product.images[0], alt: r.product.name }) : /* @__PURE__ */ (0, import_jsx_runtime8.jsx)("span", { className: "hsk-sp-img-placeholder", children: "\u{1F6CD}" }) }),
|
|
2536
|
+
/* @__PURE__ */ (0, import_jsx_runtime8.jsxs)("div", { className: "hsk-sp-item-body", children: [
|
|
2537
|
+
/* @__PURE__ */ (0, import_jsx_runtime8.jsxs)("div", { children: [
|
|
2538
|
+
r.product.category && /* @__PURE__ */ (0, import_jsx_runtime8.jsx)("div", { className: "hsk-sp-item-cat", children: r.product.category }),
|
|
2539
|
+
/* @__PURE__ */ (0, import_jsx_runtime8.jsx)("div", { className: "hsk-sp-item-name", title: r.product.name, children: r.product.name })
|
|
2133
2540
|
] }),
|
|
2134
|
-
/* @__PURE__ */ (0,
|
|
2135
|
-
/* @__PURE__ */ (0,
|
|
2136
|
-
/* @__PURE__ */ (0,
|
|
2541
|
+
/* @__PURE__ */ (0, import_jsx_runtime8.jsxs)("div", { className: "hsk-sp-item-price-row", children: [
|
|
2542
|
+
/* @__PURE__ */ (0, import_jsx_runtime8.jsx)("span", { className: "hsk-sp-item-currency", children: currency }),
|
|
2543
|
+
/* @__PURE__ */ (0, import_jsx_runtime8.jsx)("span", { className: "hsk-sp-item-price", children: price.toLocaleString() })
|
|
2137
2544
|
] }),
|
|
2138
|
-
/* @__PURE__ */ (0,
|
|
2545
|
+
/* @__PURE__ */ (0, import_jsx_runtime8.jsx)("div", { className: "hsk-sp-actions", children: /* @__PURE__ */ (0, import_jsx_runtime8.jsx)(
|
|
2139
2546
|
"button",
|
|
2140
2547
|
{
|
|
2141
2548
|
className: "hsk-sp-action hsk-sp-action-primary",
|
|
@@ -2155,29 +2562,29 @@ Question: ${q}`;
|
|
|
2155
2562
|
})() })
|
|
2156
2563
|
] })
|
|
2157
2564
|
] }),
|
|
2158
|
-
/* @__PURE__ */ (0,
|
|
2159
|
-
/* @__PURE__ */ (0,
|
|
2565
|
+
/* @__PURE__ */ (0, import_jsx_runtime8.jsxs)("div", { className: "hsk-sp-chat-pane", children: [
|
|
2566
|
+
/* @__PURE__ */ (0, import_jsx_runtime8.jsxs)("div", { className: "hsk-cb-msgs", children: [
|
|
2160
2567
|
displayMessages.map((msg, idx) => {
|
|
2161
2568
|
const isUser = msg.role === "user";
|
|
2162
|
-
return /* @__PURE__ */ (0,
|
|
2163
|
-
/* @__PURE__ */ (0,
|
|
2164
|
-
/* @__PURE__ */ (0,
|
|
2569
|
+
return /* @__PURE__ */ (0, import_jsx_runtime8.jsx)("div", { className: "hsk-cb-msg-group", children: isUser ? /* @__PURE__ */ (0, import_jsx_runtime8.jsx)("div", { className: "hsk-cb-user-msg", children: /* @__PURE__ */ (0, import_jsx_runtime8.jsx)("div", { className: "hsk-cb-user-bubble", children: msg.content }) }) : /* @__PURE__ */ (0, import_jsx_runtime8.jsxs)("div", { className: "hsk-cb-ai-msg", children: [
|
|
2570
|
+
/* @__PURE__ */ (0, import_jsx_runtime8.jsx)("div", { className: "hsk-cb-ai-icon", style: { display: "flex", alignItems: "center" }, children: /* @__PURE__ */ (0, import_jsx_runtime8.jsx)(SparkleIcon3, {}) }),
|
|
2571
|
+
/* @__PURE__ */ (0, import_jsx_runtime8.jsx)("div", { className: "hsk-cb-ai-body", children: /* @__PURE__ */ (0, import_jsx_runtime8.jsx)("div", { className: "hsk-cb-ai-text", children: renderMarkdown(msg.content) }) })
|
|
2165
2572
|
] }) }, idx);
|
|
2166
2573
|
}),
|
|
2167
|
-
chatLoading && /* @__PURE__ */ (0,
|
|
2168
|
-
/* @__PURE__ */ (0,
|
|
2169
|
-
/* @__PURE__ */ (0,
|
|
2170
|
-
/* @__PURE__ */ (0,
|
|
2171
|
-
/* @__PURE__ */ (0,
|
|
2172
|
-
/* @__PURE__ */ (0,
|
|
2574
|
+
chatLoading && /* @__PURE__ */ (0, import_jsx_runtime8.jsxs)("div", { className: "hsk-cb-typing-row", children: [
|
|
2575
|
+
/* @__PURE__ */ (0, import_jsx_runtime8.jsx)("div", { className: "hsk-cb-ai-icon", style: { display: "flex", alignItems: "center" }, children: /* @__PURE__ */ (0, import_jsx_runtime8.jsx)(SparkleIcon3, {}) }),
|
|
2576
|
+
/* @__PURE__ */ (0, import_jsx_runtime8.jsxs)("div", { className: "hsk-cb-typing", children: [
|
|
2577
|
+
/* @__PURE__ */ (0, import_jsx_runtime8.jsx)("div", { className: "hsk-cb-dot" }),
|
|
2578
|
+
/* @__PURE__ */ (0, import_jsx_runtime8.jsx)("div", { className: "hsk-cb-dot" }),
|
|
2579
|
+
/* @__PURE__ */ (0, import_jsx_runtime8.jsx)("div", { className: "hsk-cb-dot" })
|
|
2173
2580
|
] })
|
|
2174
2581
|
] }),
|
|
2175
|
-
chatError && /* @__PURE__ */ (0,
|
|
2176
|
-
/* @__PURE__ */ (0,
|
|
2582
|
+
chatError && /* @__PURE__ */ (0, import_jsx_runtime8.jsx)("div", { className: "hsk-cb-error", children: getFriendlyError2(chatError) }),
|
|
2583
|
+
/* @__PURE__ */ (0, import_jsx_runtime8.jsx)("div", { ref: chatBottomRef, style: { height: 1 } })
|
|
2177
2584
|
] }),
|
|
2178
|
-
/* @__PURE__ */ (0,
|
|
2179
|
-
/* @__PURE__ */ (0,
|
|
2180
|
-
/* @__PURE__ */ (0,
|
|
2585
|
+
/* @__PURE__ */ (0, import_jsx_runtime8.jsxs)("div", { className: "hsk-cb-input-wrap", children: [
|
|
2586
|
+
/* @__PURE__ */ (0, import_jsx_runtime8.jsxs)("div", { className: "hsk-cb-input-box", children: [
|
|
2587
|
+
/* @__PURE__ */ (0, import_jsx_runtime8.jsx)(
|
|
2181
2588
|
"textarea",
|
|
2182
2589
|
{
|
|
2183
2590
|
ref: chatTextareaRef,
|
|
@@ -2190,22 +2597,22 @@ Question: ${q}`;
|
|
|
2190
2597
|
disabled: chatLoading
|
|
2191
2598
|
}
|
|
2192
2599
|
),
|
|
2193
|
-
/* @__PURE__ */ (0,
|
|
2600
|
+
/* @__PURE__ */ (0, import_jsx_runtime8.jsx)(
|
|
2194
2601
|
"button",
|
|
2195
2602
|
{
|
|
2196
2603
|
className: "hsk-cb-send",
|
|
2197
2604
|
onClick: () => handleSend(),
|
|
2198
2605
|
disabled: !chatInput.trim() || chatLoading,
|
|
2199
2606
|
"aria-label": "Send message",
|
|
2200
|
-
children: /* @__PURE__ */ (0,
|
|
2607
|
+
children: /* @__PURE__ */ (0, import_jsx_runtime8.jsx)(ArrowUpIcon3, {})
|
|
2201
2608
|
}
|
|
2202
2609
|
)
|
|
2203
2610
|
] }),
|
|
2204
|
-
/* @__PURE__ */ (0,
|
|
2611
|
+
/* @__PURE__ */ (0, import_jsx_runtime8.jsx)("div", { className: "hsk-cb-hint", children: "Akropolys \xB7 instant product knowledge" })
|
|
2205
2612
|
] })
|
|
2206
2613
|
] })
|
|
2207
2614
|
] }),
|
|
2208
|
-
/* @__PURE__ */ (0,
|
|
2615
|
+
/* @__PURE__ */ (0, import_jsx_runtime8.jsx)("div", { className: "hsk-sp-footer", children: /* @__PURE__ */ (0, import_jsx_runtime8.jsx)("span", { className: "hsk-sp-esc", children: "Esc to close" }) })
|
|
2209
2616
|
] })
|
|
2210
2617
|
}
|
|
2211
2618
|
);
|
|
@@ -2223,9 +2630,9 @@ function Sparkle({
|
|
|
2223
2630
|
product,
|
|
2224
2631
|
children
|
|
2225
2632
|
}) {
|
|
2226
|
-
const [open, setOpen] = (0,
|
|
2227
|
-
const [mounted, setMounted] = (0,
|
|
2228
|
-
(0,
|
|
2633
|
+
const [open, setOpen] = (0, import_react6.useState)(false);
|
|
2634
|
+
const [mounted, setMounted] = (0, import_react6.useState)(false);
|
|
2635
|
+
(0, import_react6.useEffect)(() => {
|
|
2229
2636
|
setMounted(true);
|
|
2230
2637
|
}, []);
|
|
2231
2638
|
const customStyles = {
|
|
@@ -2235,8 +2642,8 @@ function Sparkle({
|
|
|
2235
2642
|
...theme?.fontFamily && { "--hsk-font": theme.fontFamily },
|
|
2236
2643
|
...theme?.borderRadius && { "--hsk-border-radius": theme.borderRadius }
|
|
2237
2644
|
};
|
|
2238
|
-
return /* @__PURE__ */ (0,
|
|
2239
|
-
/* @__PURE__ */ (0,
|
|
2645
|
+
return /* @__PURE__ */ (0, import_jsx_runtime8.jsxs)(import_jsx_runtime8.Fragment, { children: [
|
|
2646
|
+
/* @__PURE__ */ (0, import_jsx_runtime8.jsx)(
|
|
2240
2647
|
"button",
|
|
2241
2648
|
{
|
|
2242
2649
|
className: cn("hsk-sp-btn", classNames.button, className),
|
|
@@ -2244,11 +2651,11 @@ function Sparkle({
|
|
|
2244
2651
|
style: customStyles,
|
|
2245
2652
|
title: "Find similar products",
|
|
2246
2653
|
"aria-label": "Find similar products",
|
|
2247
|
-
children: children || /* @__PURE__ */ (0,
|
|
2654
|
+
children: children || /* @__PURE__ */ (0, import_jsx_runtime8.jsx)(SparkleIcon3, {})
|
|
2248
2655
|
}
|
|
2249
2656
|
),
|
|
2250
2657
|
open && mounted && (0, import_react_dom2.createPortal)(
|
|
2251
|
-
/* @__PURE__ */ (0,
|
|
2658
|
+
/* @__PURE__ */ (0, import_jsx_runtime8.jsx)(
|
|
2252
2659
|
SparkleModal,
|
|
2253
2660
|
{
|
|
2254
2661
|
productName,
|
|
@@ -2269,62 +2676,62 @@ function Sparkle({
|
|
|
2269
2676
|
}
|
|
2270
2677
|
|
|
2271
2678
|
// src/components/CartBadge.tsx
|
|
2272
|
-
var
|
|
2273
|
-
var
|
|
2679
|
+
var import_sdk8 = require("@akropolys/sdk");
|
|
2680
|
+
var import_jsx_runtime9 = require("react/jsx-runtime");
|
|
2274
2681
|
function CartBadge({ className }) {
|
|
2275
|
-
const { cart } = (0,
|
|
2682
|
+
const { cart } = (0, import_sdk8.useCart)();
|
|
2276
2683
|
if (!cart || cart.item_count === 0) return null;
|
|
2277
|
-
return /* @__PURE__ */ (0,
|
|
2684
|
+
return /* @__PURE__ */ (0, import_jsx_runtime9.jsx)("span", { className: cn("hsk-cart-badge", className), children: cart.item_count });
|
|
2278
2685
|
}
|
|
2279
2686
|
|
|
2280
2687
|
// src/components/CartDrawer.tsx
|
|
2281
|
-
var
|
|
2688
|
+
var import_react8 = require("react");
|
|
2282
2689
|
var import_react_dom4 = require("react-dom");
|
|
2283
|
-
var
|
|
2690
|
+
var import_sdk10 = require("@akropolys/sdk");
|
|
2284
2691
|
|
|
2285
2692
|
// src/components/CheckoutModal.tsx
|
|
2286
|
-
var
|
|
2693
|
+
var import_react7 = require("react");
|
|
2287
2694
|
var import_react_dom3 = require("react-dom");
|
|
2288
|
-
var
|
|
2289
|
-
var
|
|
2695
|
+
var import_sdk9 = require("@akropolys/sdk");
|
|
2696
|
+
var import_jsx_runtime10 = require("react/jsx-runtime");
|
|
2290
2697
|
function CheckoutModal({
|
|
2291
2698
|
onClose,
|
|
2292
2699
|
theme,
|
|
2293
2700
|
customStyles,
|
|
2294
2701
|
hskThemeAttr
|
|
2295
2702
|
}) {
|
|
2296
|
-
const { cart, loading: cartLoading } = (0,
|
|
2297
|
-
const client = (0,
|
|
2298
|
-
const [config, setConfig] = (0,
|
|
2299
|
-
const [loadingConfig, setLoadingConfig] = (0,
|
|
2300
|
-
const [phone, setPhone] = (0,
|
|
2703
|
+
const { cart, loading: cartLoading } = (0, import_sdk9.useCart)();
|
|
2704
|
+
const client = (0, import_sdk9.useAkropolysContext)();
|
|
2705
|
+
const [config, setConfig] = (0, import_react7.useState)(null);
|
|
2706
|
+
const [loadingConfig, setLoadingConfig] = (0, import_react7.useState)(true);
|
|
2707
|
+
const [phone, setPhone] = (0, import_react7.useState)(() => {
|
|
2301
2708
|
if (typeof window !== "undefined") {
|
|
2302
2709
|
return localStorage.getItem("akropolys_user_phone") || "";
|
|
2303
2710
|
}
|
|
2304
2711
|
return "";
|
|
2305
2712
|
});
|
|
2306
|
-
const [email, setEmail] = (0,
|
|
2713
|
+
const [email, setEmail] = (0, import_react7.useState)(() => {
|
|
2307
2714
|
if (typeof window !== "undefined") {
|
|
2308
2715
|
return localStorage.getItem("akropolys_user_email") || "";
|
|
2309
2716
|
}
|
|
2310
2717
|
return "";
|
|
2311
2718
|
});
|
|
2312
|
-
const [firstName, setFirstName] = (0,
|
|
2719
|
+
const [firstName, setFirstName] = (0, import_react7.useState)(() => {
|
|
2313
2720
|
if (typeof window !== "undefined") {
|
|
2314
2721
|
return localStorage.getItem("akropolys_user_firstname") || "";
|
|
2315
2722
|
}
|
|
2316
2723
|
return "";
|
|
2317
2724
|
});
|
|
2318
|
-
const [lastName, setLastName] = (0,
|
|
2725
|
+
const [lastName, setLastName] = (0, import_react7.useState)(() => {
|
|
2319
2726
|
if (typeof window !== "undefined") {
|
|
2320
2727
|
return localStorage.getItem("akropolys_user_lastname") || "";
|
|
2321
2728
|
}
|
|
2322
2729
|
return "";
|
|
2323
2730
|
});
|
|
2324
|
-
const [phase, setPhase] = (0,
|
|
2325
|
-
const [merchantRef, setMerchantRef] = (0,
|
|
2326
|
-
const [payError, setPayError] = (0,
|
|
2327
|
-
const {} = (0,
|
|
2731
|
+
const [phase, setPhase] = (0, import_react7.useState)("idle");
|
|
2732
|
+
const [merchantRef, setMerchantRef] = (0, import_react7.useState)(null);
|
|
2733
|
+
const [payError, setPayError] = (0, import_react7.useState)(null);
|
|
2734
|
+
const {} = (0, import_sdk9.usePaymentPolling)({
|
|
2328
2735
|
client: client.api,
|
|
2329
2736
|
merchantReference: merchantRef,
|
|
2330
2737
|
onSuccess: () => {
|
|
@@ -2337,7 +2744,7 @@ function CheckoutModal({
|
|
|
2337
2744
|
setMerchantRef(null);
|
|
2338
2745
|
}
|
|
2339
2746
|
});
|
|
2340
|
-
(0,
|
|
2747
|
+
(0, import_react7.useEffect)(() => {
|
|
2341
2748
|
client.api.getCheckoutConfig().then((res) => setConfig(res.payment_methods)).catch(() => {
|
|
2342
2749
|
}).finally(() => setLoadingConfig(false));
|
|
2343
2750
|
}, [client]);
|
|
@@ -2372,20 +2779,20 @@ function CheckoutModal({
|
|
|
2372
2779
|
const total = cart?.total || 0;
|
|
2373
2780
|
const backdropStyle = { ...customStyles, fontSize: "15px", fontFamily: '-apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, Helvetica, Arial, sans-serif', zIndex: 999999 };
|
|
2374
2781
|
return (0, import_react_dom3.createPortal)(
|
|
2375
|
-
/* @__PURE__ */ (0,
|
|
2782
|
+
/* @__PURE__ */ (0, import_jsx_runtime10.jsx)(
|
|
2376
2783
|
"div",
|
|
2377
2784
|
{
|
|
2378
2785
|
className: "hsk-checkout-backdrop-full",
|
|
2379
2786
|
style: backdropStyle,
|
|
2380
2787
|
"data-hsk-theme": hskThemeAttr,
|
|
2381
|
-
children: /* @__PURE__ */ (0,
|
|
2788
|
+
children: /* @__PURE__ */ (0, import_jsx_runtime10.jsxs)(
|
|
2382
2789
|
"div",
|
|
2383
2790
|
{
|
|
2384
2791
|
className: "hsk-checkout-modal-full",
|
|
2385
2792
|
style: customStyles,
|
|
2386
2793
|
"data-hsk-theme": hskThemeAttr,
|
|
2387
2794
|
children: [
|
|
2388
|
-
/* @__PURE__ */ (0,
|
|
2795
|
+
/* @__PURE__ */ (0, import_jsx_runtime10.jsx)(
|
|
2389
2796
|
"button",
|
|
2390
2797
|
{
|
|
2391
2798
|
onClick: (e) => {
|
|
@@ -2395,71 +2802,71 @@ function CheckoutModal({
|
|
|
2395
2802
|
},
|
|
2396
2803
|
className: "hsk-checkout-close-x",
|
|
2397
2804
|
"aria-label": "Close checkout",
|
|
2398
|
-
children: /* @__PURE__ */ (0,
|
|
2399
|
-
/* @__PURE__ */ (0,
|
|
2400
|
-
/* @__PURE__ */ (0,
|
|
2805
|
+
children: /* @__PURE__ */ (0, import_jsx_runtime10.jsxs)("svg", { width: "18", height: "18", viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "2", strokeLinecap: "round", strokeLinejoin: "round", children: [
|
|
2806
|
+
/* @__PURE__ */ (0, import_jsx_runtime10.jsx)("line", { x1: "18", y1: "6", x2: "6", y2: "18" }),
|
|
2807
|
+
/* @__PURE__ */ (0, import_jsx_runtime10.jsx)("line", { x1: "6", y1: "6", x2: "18", y2: "18" })
|
|
2401
2808
|
] })
|
|
2402
2809
|
}
|
|
2403
2810
|
),
|
|
2404
|
-
/* @__PURE__ */ (0,
|
|
2405
|
-
/* @__PURE__ */ (0,
|
|
2811
|
+
/* @__PURE__ */ (0, import_jsx_runtime10.jsx)("div", { className: "hsk-checkout-panel-left", children: /* @__PURE__ */ (0, import_jsx_runtime10.jsxs)("div", { className: "hsk-checkout-left-content", children: [
|
|
2812
|
+
/* @__PURE__ */ (0, import_jsx_runtime10.jsxs)("button", { onClick: (e) => {
|
|
2406
2813
|
e.preventDefault();
|
|
2407
2814
|
e.stopPropagation();
|
|
2408
2815
|
onClose();
|
|
2409
2816
|
}, className: "hsk-checkout-back-btn", children: [
|
|
2410
|
-
/* @__PURE__ */ (0,
|
|
2411
|
-
/* @__PURE__ */ (0,
|
|
2412
|
-
/* @__PURE__ */ (0,
|
|
2817
|
+
/* @__PURE__ */ (0, import_jsx_runtime10.jsxs)("svg", { width: "16", height: "16", viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "2.5", strokeLinecap: "round", strokeLinejoin: "round", children: [
|
|
2818
|
+
/* @__PURE__ */ (0, import_jsx_runtime10.jsx)("line", { x1: "19", y1: "12", x2: "5", y2: "12" }),
|
|
2819
|
+
/* @__PURE__ */ (0, import_jsx_runtime10.jsx)("polyline", { points: "12 19 5 12 12 5" })
|
|
2413
2820
|
] }),
|
|
2414
2821
|
"Back to store"
|
|
2415
2822
|
] }),
|
|
2416
|
-
/* @__PURE__ */ (0,
|
|
2417
|
-
/* @__PURE__ */ (0,
|
|
2418
|
-
/* @__PURE__ */ (0,
|
|
2419
|
-
/* @__PURE__ */ (0,
|
|
2823
|
+
/* @__PURE__ */ (0, import_jsx_runtime10.jsx)("div", { className: "hsk-checkout-store-info", children: /* @__PURE__ */ (0, import_jsx_runtime10.jsx)("h2", { children: "Secure Checkout" }) }),
|
|
2824
|
+
/* @__PURE__ */ (0, import_jsx_runtime10.jsxs)("div", { className: "hsk-checkout-amount-due", children: [
|
|
2825
|
+
/* @__PURE__ */ (0, import_jsx_runtime10.jsx)("span", { className: "hsk-checkout-label-muted", children: "Pay total" }),
|
|
2826
|
+
/* @__PURE__ */ (0, import_jsx_runtime10.jsxs)("div", { className: "hsk-checkout-grand-total", children: [
|
|
2420
2827
|
currency,
|
|
2421
2828
|
" ",
|
|
2422
2829
|
total.toLocaleString(void 0, { minimumFractionDigits: 2 })
|
|
2423
2830
|
] })
|
|
2424
2831
|
] }),
|
|
2425
|
-
cartLoading || !cart ? /* @__PURE__ */ (0,
|
|
2426
|
-
/* @__PURE__ */ (0,
|
|
2427
|
-
item.image ? /* @__PURE__ */ (0,
|
|
2428
|
-
/* @__PURE__ */ (0,
|
|
2832
|
+
cartLoading || !cart ? /* @__PURE__ */ (0, import_jsx_runtime10.jsx)("p", { className: "hsk-cart-loading", children: "Loading order..." }) : /* @__PURE__ */ (0, import_jsx_runtime10.jsx)("div", { className: "hsk-checkout-items-list-wrap", children: /* @__PURE__ */ (0, import_jsx_runtime10.jsx)("ul", { className: "hsk-checkout-items-list", children: cart.items.map((item) => /* @__PURE__ */ (0, import_jsx_runtime10.jsxs)("li", { className: "hsk-checkout-item-row", children: [
|
|
2833
|
+
/* @__PURE__ */ (0, import_jsx_runtime10.jsxs)("div", { className: "hsk-checkout-item-img-container", children: [
|
|
2834
|
+
item.image ? /* @__PURE__ */ (0, import_jsx_runtime10.jsx)("img", { src: item.image, alt: item.name, className: "hsk-checkout-item-img" }) : /* @__PURE__ */ (0, import_jsx_runtime10.jsx)("div", { className: "hsk-checkout-item-img-placeholder", children: "\u{1F6D2}" }),
|
|
2835
|
+
/* @__PURE__ */ (0, import_jsx_runtime10.jsx)("span", { className: "hsk-checkout-item-qty-badge", children: item.quantity })
|
|
2429
2836
|
] }),
|
|
2430
|
-
/* @__PURE__ */ (0,
|
|
2431
|
-
/* @__PURE__ */ (0,
|
|
2837
|
+
/* @__PURE__ */ (0, import_jsx_runtime10.jsx)("div", { className: "hsk-checkout-item-details", children: /* @__PURE__ */ (0, import_jsx_runtime10.jsx)("span", { className: "hsk-checkout-item-name", children: item.name }) }),
|
|
2838
|
+
/* @__PURE__ */ (0, import_jsx_runtime10.jsxs)("span", { className: "hsk-checkout-item-price", children: [
|
|
2432
2839
|
item.currency,
|
|
2433
2840
|
" ",
|
|
2434
2841
|
(item.price_numeric * item.quantity).toLocaleString(void 0, { minimumFractionDigits: 2 })
|
|
2435
2842
|
] })
|
|
2436
2843
|
] }, item.id)) }) })
|
|
2437
2844
|
] }) }),
|
|
2438
|
-
/* @__PURE__ */ (0,
|
|
2439
|
-
/* @__PURE__ */ (0,
|
|
2440
|
-
/* @__PURE__ */ (0,
|
|
2441
|
-
/* @__PURE__ */ (0,
|
|
2845
|
+
/* @__PURE__ */ (0, import_jsx_runtime10.jsx)("div", { className: "hsk-checkout-panel-right", children: /* @__PURE__ */ (0, import_jsx_runtime10.jsx)("div", { className: "hsk-checkout-right-content", children: phase === "done" ? /* @__PURE__ */ (0, import_jsx_runtime10.jsxs)("div", { className: "hsk-checkout-status-card success", children: [
|
|
2846
|
+
/* @__PURE__ */ (0, import_jsx_runtime10.jsx)("div", { className: "hsk-status-icon-wrap success", children: /* @__PURE__ */ (0, import_jsx_runtime10.jsxs)("svg", { width: "32", height: "32", viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "2.5", strokeLinecap: "round", strokeLinejoin: "round", children: [
|
|
2847
|
+
/* @__PURE__ */ (0, import_jsx_runtime10.jsx)("path", { d: "M22 11.08V12a10 10 0 1 1-5.93-9.14" }),
|
|
2848
|
+
/* @__PURE__ */ (0, import_jsx_runtime10.jsx)("polyline", { points: "22 4 12 14.01 9 11.01" })
|
|
2442
2849
|
] }) }),
|
|
2443
|
-
/* @__PURE__ */ (0,
|
|
2444
|
-
/* @__PURE__ */ (0,
|
|
2445
|
-
/* @__PURE__ */ (0,
|
|
2446
|
-
] }) : phase === "awaiting" ? /* @__PURE__ */ (0,
|
|
2447
|
-
/* @__PURE__ */ (0,
|
|
2448
|
-
/* @__PURE__ */ (0,
|
|
2449
|
-
/* @__PURE__ */ (0,
|
|
2850
|
+
/* @__PURE__ */ (0, import_jsx_runtime10.jsx)("h3", { children: "Payment Successful!" }),
|
|
2851
|
+
/* @__PURE__ */ (0, import_jsx_runtime10.jsx)("p", { children: "Your transaction has been confirmed. Thank you for your order!" }),
|
|
2852
|
+
/* @__PURE__ */ (0, import_jsx_runtime10.jsx)("button", { onClick: onClose, className: "hsk-pay-btn hsk-btn-primary", style: { marginTop: "1.5rem" }, children: "Continue Shopping" })
|
|
2853
|
+
] }) : phase === "awaiting" ? /* @__PURE__ */ (0, import_jsx_runtime10.jsxs)("div", { className: "hsk-checkout-status-card awaiting", children: [
|
|
2854
|
+
/* @__PURE__ */ (0, import_jsx_runtime10.jsx)("div", { className: "hsk-status-spinner-wrap", children: /* @__PURE__ */ (0, import_jsx_runtime10.jsx)("div", { className: "hsk-status-spinner" }) }),
|
|
2855
|
+
/* @__PURE__ */ (0, import_jsx_runtime10.jsx)("h3", { children: "Confirm payment on your phone" }),
|
|
2856
|
+
/* @__PURE__ */ (0, import_jsx_runtime10.jsxs)("p", { children: [
|
|
2450
2857
|
"We've sent an M-Pesa STK push prompt to ",
|
|
2451
|
-
/* @__PURE__ */ (0,
|
|
2858
|
+
/* @__PURE__ */ (0, import_jsx_runtime10.jsxs)("strong", { children: [
|
|
2452
2859
|
"254",
|
|
2453
2860
|
phone
|
|
2454
2861
|
] }),
|
|
2455
2862
|
"."
|
|
2456
2863
|
] }),
|
|
2457
|
-
/* @__PURE__ */ (0,
|
|
2458
|
-
/* @__PURE__ */ (0,
|
|
2459
|
-
/* @__PURE__ */ (0,
|
|
2460
|
-
/* @__PURE__ */ (0,
|
|
2864
|
+
/* @__PURE__ */ (0, import_jsx_runtime10.jsxs)("div", { className: "hsk-checkout-stk-instructions", children: [
|
|
2865
|
+
/* @__PURE__ */ (0, import_jsx_runtime10.jsx)("p", { children: "1. Check your phone lockscreen for the M-Pesa prompt." }),
|
|
2866
|
+
/* @__PURE__ */ (0, import_jsx_runtime10.jsx)("p", { children: "2. Enter your M-Pesa PIN and press OK." }),
|
|
2867
|
+
/* @__PURE__ */ (0, import_jsx_runtime10.jsx)("p", { children: "3. Wait here \u2014 this page auto-updates once confirmed." })
|
|
2461
2868
|
] }),
|
|
2462
|
-
/* @__PURE__ */ (0,
|
|
2869
|
+
/* @__PURE__ */ (0, import_jsx_runtime10.jsx)(
|
|
2463
2870
|
"button",
|
|
2464
2871
|
{
|
|
2465
2872
|
onClick: () => {
|
|
@@ -2470,43 +2877,43 @@ function CheckoutModal({
|
|
|
2470
2877
|
children: "Cancel payment"
|
|
2471
2878
|
}
|
|
2472
2879
|
)
|
|
2473
|
-
] }) : phase === "cancelled" ? /* @__PURE__ */ (0,
|
|
2474
|
-
/* @__PURE__ */ (0,
|
|
2475
|
-
/* @__PURE__ */ (0,
|
|
2476
|
-
/* @__PURE__ */ (0,
|
|
2880
|
+
] }) : phase === "cancelled" ? /* @__PURE__ */ (0, import_jsx_runtime10.jsxs)("div", { className: "hsk-checkout-status-card cancelled", children: [
|
|
2881
|
+
/* @__PURE__ */ (0, import_jsx_runtime10.jsx)("div", { className: "hsk-status-icon-wrap cancelled", children: /* @__PURE__ */ (0, import_jsx_runtime10.jsxs)("svg", { width: "32", height: "32", viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "2.5", strokeLinecap: "round", strokeLinejoin: "round", children: [
|
|
2882
|
+
/* @__PURE__ */ (0, import_jsx_runtime10.jsx)("path", { d: "m15 9-6 6M9 9l6 6" }),
|
|
2883
|
+
/* @__PURE__ */ (0, import_jsx_runtime10.jsx)("circle", { cx: "12", cy: "12", r: "10" })
|
|
2477
2884
|
] }) }),
|
|
2478
|
-
/* @__PURE__ */ (0,
|
|
2479
|
-
/* @__PURE__ */ (0,
|
|
2480
|
-
/* @__PURE__ */ (0,
|
|
2481
|
-
/* @__PURE__ */ (0,
|
|
2885
|
+
/* @__PURE__ */ (0, import_jsx_runtime10.jsx)("h3", { children: "Payment Cancelled" }),
|
|
2886
|
+
/* @__PURE__ */ (0, import_jsx_runtime10.jsx)("p", { children: "No charge was made. You can update your phone number and try again whenever you're ready." }),
|
|
2887
|
+
/* @__PURE__ */ (0, import_jsx_runtime10.jsxs)("div", { className: "hsk-checkout-status-actions", children: [
|
|
2888
|
+
/* @__PURE__ */ (0, import_jsx_runtime10.jsx)("button", { onClick: () => {
|
|
2482
2889
|
setPhase("idle");
|
|
2483
2890
|
setPayError(null);
|
|
2484
2891
|
}, className: "hsk-pay-btn hsk-btn-primary", children: "Try again" }),
|
|
2485
|
-
/* @__PURE__ */ (0,
|
|
2892
|
+
/* @__PURE__ */ (0, import_jsx_runtime10.jsx)("button", { onClick: onClose, className: "hsk-checkout-cancel-btn", children: "Back to cart" })
|
|
2486
2893
|
] })
|
|
2487
|
-
] }) : phase === "failed" ? /* @__PURE__ */ (0,
|
|
2488
|
-
/* @__PURE__ */ (0,
|
|
2489
|
-
/* @__PURE__ */ (0,
|
|
2490
|
-
/* @__PURE__ */ (0,
|
|
2491
|
-
/* @__PURE__ */ (0,
|
|
2894
|
+
] }) : phase === "failed" ? /* @__PURE__ */ (0, import_jsx_runtime10.jsxs)("div", { className: "hsk-checkout-status-card failed", children: [
|
|
2895
|
+
/* @__PURE__ */ (0, import_jsx_runtime10.jsx)("div", { className: "hsk-status-icon-wrap failed", children: /* @__PURE__ */ (0, import_jsx_runtime10.jsxs)("svg", { width: "32", height: "32", viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "2.5", strokeLinecap: "round", strokeLinejoin: "round", children: [
|
|
2896
|
+
/* @__PURE__ */ (0, import_jsx_runtime10.jsx)("circle", { cx: "12", cy: "12", r: "10" }),
|
|
2897
|
+
/* @__PURE__ */ (0, import_jsx_runtime10.jsx)("line", { x1: "12", y1: "8", x2: "12", y2: "12" }),
|
|
2898
|
+
/* @__PURE__ */ (0, import_jsx_runtime10.jsx)("line", { x1: "12", y1: "16", x2: "12.01", y2: "16" })
|
|
2492
2899
|
] }) }),
|
|
2493
|
-
/* @__PURE__ */ (0,
|
|
2494
|
-
/* @__PURE__ */ (0,
|
|
2495
|
-
/* @__PURE__ */ (0,
|
|
2496
|
-
/* @__PURE__ */ (0,
|
|
2900
|
+
/* @__PURE__ */ (0, import_jsx_runtime10.jsx)("h3", { children: "Payment Failed" }),
|
|
2901
|
+
/* @__PURE__ */ (0, import_jsx_runtime10.jsx)("p", { className: "hsk-checkout-error-text", children: payError || "Could not verify M-Pesa transaction. Please check your phone and try again." }),
|
|
2902
|
+
/* @__PURE__ */ (0, import_jsx_runtime10.jsxs)("div", { className: "hsk-checkout-status-actions", children: [
|
|
2903
|
+
/* @__PURE__ */ (0, import_jsx_runtime10.jsx)("button", { onClick: () => {
|
|
2497
2904
|
setPhase("idle");
|
|
2498
2905
|
setPayError(null);
|
|
2499
2906
|
}, className: "hsk-pay-btn hsk-btn-primary", children: "Try again" }),
|
|
2500
|
-
/* @__PURE__ */ (0,
|
|
2907
|
+
/* @__PURE__ */ (0, import_jsx_runtime10.jsx)("button", { onClick: onClose, className: "hsk-checkout-cancel-btn", children: "Back to cart" })
|
|
2501
2908
|
] })
|
|
2502
|
-
] }) : /* @__PURE__ */ (0,
|
|
2503
|
-
/* @__PURE__ */ (0,
|
|
2504
|
-
loadingConfig ? /* @__PURE__ */ (0,
|
|
2505
|
-
/* @__PURE__ */ (0,
|
|
2506
|
-
/* @__PURE__ */ (0,
|
|
2507
|
-
/* @__PURE__ */ (0,
|
|
2508
|
-
/* @__PURE__ */ (0,
|
|
2509
|
-
/* @__PURE__ */ (0,
|
|
2909
|
+
] }) : /* @__PURE__ */ (0, import_jsx_runtime10.jsxs)("div", { className: "hsk-checkout-payment-form-wrap", children: [
|
|
2910
|
+
/* @__PURE__ */ (0, import_jsx_runtime10.jsx)("h3", { className: "hsk-checkout-section-title", children: "Payment details" }),
|
|
2911
|
+
loadingConfig ? /* @__PURE__ */ (0, import_jsx_runtime10.jsx)("p", { className: "hsk-cart-loading", children: "Loading payment configuration..." }) : !hasPaymentMethods ? /* @__PURE__ */ (0, import_jsx_runtime10.jsx)("p", { className: "hsk-checkout-error", children: "No payment methods configured for this store." }) : /* @__PURE__ */ (0, import_jsx_runtime10.jsxs)("form", { onSubmit: handlePay, className: "hsk-stripe-checkout-form", children: [
|
|
2912
|
+
/* @__PURE__ */ (0, import_jsx_runtime10.jsxs)("div", { className: "hsk-form-group", children: [
|
|
2913
|
+
/* @__PURE__ */ (0, import_jsx_runtime10.jsx)("label", { className: "hsk-form-label", children: "M-Pesa Mobile Number" }),
|
|
2914
|
+
/* @__PURE__ */ (0, import_jsx_runtime10.jsxs)("div", { className: "hsk-phone-input-container", children: [
|
|
2915
|
+
/* @__PURE__ */ (0, import_jsx_runtime10.jsx)("span", { className: "hsk-phone-prefix", children: "254" }),
|
|
2916
|
+
/* @__PURE__ */ (0, import_jsx_runtime10.jsx)(
|
|
2510
2917
|
"input",
|
|
2511
2918
|
{
|
|
2512
2919
|
type: "tel",
|
|
@@ -2520,11 +2927,11 @@ function CheckoutModal({
|
|
|
2520
2927
|
}
|
|
2521
2928
|
)
|
|
2522
2929
|
] }),
|
|
2523
|
-
/* @__PURE__ */ (0,
|
|
2930
|
+
/* @__PURE__ */ (0, import_jsx_runtime10.jsx)("span", { className: "hsk-form-hint", children: "Enter your 9-digit number (e.g. 712345678)" })
|
|
2524
2931
|
] }),
|
|
2525
|
-
/* @__PURE__ */ (0,
|
|
2526
|
-
/* @__PURE__ */ (0,
|
|
2527
|
-
/* @__PURE__ */ (0,
|
|
2932
|
+
/* @__PURE__ */ (0, import_jsx_runtime10.jsxs)("div", { className: "hsk-form-group", children: [
|
|
2933
|
+
/* @__PURE__ */ (0, import_jsx_runtime10.jsx)("label", { className: "hsk-form-label", children: "Email address" }),
|
|
2934
|
+
/* @__PURE__ */ (0, import_jsx_runtime10.jsx)(
|
|
2528
2935
|
"input",
|
|
2529
2936
|
{
|
|
2530
2937
|
type: "email",
|
|
@@ -2535,10 +2942,10 @@ function CheckoutModal({
|
|
|
2535
2942
|
}
|
|
2536
2943
|
)
|
|
2537
2944
|
] }),
|
|
2538
|
-
/* @__PURE__ */ (0,
|
|
2539
|
-
/* @__PURE__ */ (0,
|
|
2540
|
-
/* @__PURE__ */ (0,
|
|
2541
|
-
/* @__PURE__ */ (0,
|
|
2945
|
+
/* @__PURE__ */ (0, import_jsx_runtime10.jsxs)("div", { className: "hsk-form-row", children: [
|
|
2946
|
+
/* @__PURE__ */ (0, import_jsx_runtime10.jsxs)("div", { className: "hsk-form-group", children: [
|
|
2947
|
+
/* @__PURE__ */ (0, import_jsx_runtime10.jsx)("label", { className: "hsk-form-label", children: "First Name" }),
|
|
2948
|
+
/* @__PURE__ */ (0, import_jsx_runtime10.jsx)(
|
|
2542
2949
|
"input",
|
|
2543
2950
|
{
|
|
2544
2951
|
type: "text",
|
|
@@ -2549,9 +2956,9 @@ function CheckoutModal({
|
|
|
2549
2956
|
}
|
|
2550
2957
|
)
|
|
2551
2958
|
] }),
|
|
2552
|
-
/* @__PURE__ */ (0,
|
|
2553
|
-
/* @__PURE__ */ (0,
|
|
2554
|
-
/* @__PURE__ */ (0,
|
|
2959
|
+
/* @__PURE__ */ (0, import_jsx_runtime10.jsxs)("div", { className: "hsk-form-group", children: [
|
|
2960
|
+
/* @__PURE__ */ (0, import_jsx_runtime10.jsx)("label", { className: "hsk-form-label", children: "Last Name" }),
|
|
2961
|
+
/* @__PURE__ */ (0, import_jsx_runtime10.jsx)(
|
|
2555
2962
|
"input",
|
|
2556
2963
|
{
|
|
2557
2964
|
type: "text",
|
|
@@ -2563,14 +2970,14 @@ function CheckoutModal({
|
|
|
2563
2970
|
)
|
|
2564
2971
|
] })
|
|
2565
2972
|
] }),
|
|
2566
|
-
payError && /* @__PURE__ */ (0,
|
|
2567
|
-
/* @__PURE__ */ (0,
|
|
2973
|
+
payError && /* @__PURE__ */ (0, import_jsx_runtime10.jsx)("div", { className: "hsk-form-error-banner", children: payError }),
|
|
2974
|
+
/* @__PURE__ */ (0, import_jsx_runtime10.jsxs)("button", { type: "submit", className: "hsk-checkout-submit-btn", children: [
|
|
2568
2975
|
"Pay ",
|
|
2569
2976
|
currency,
|
|
2570
2977
|
" ",
|
|
2571
2978
|
total.toLocaleString()
|
|
2572
2979
|
] }),
|
|
2573
|
-
/* @__PURE__ */ (0,
|
|
2980
|
+
/* @__PURE__ */ (0, import_jsx_runtime10.jsx)("div", { className: "hsk-checkout-footer-brand", children: /* @__PURE__ */ (0, import_jsx_runtime10.jsx)("span", { children: "Powered by Akropolys" }) })
|
|
2574
2981
|
] })
|
|
2575
2982
|
] }) }) })
|
|
2576
2983
|
]
|
|
@@ -2583,18 +2990,18 @@ function CheckoutModal({
|
|
|
2583
2990
|
}
|
|
2584
2991
|
|
|
2585
2992
|
// src/components/CartDrawer.tsx
|
|
2586
|
-
var
|
|
2993
|
+
var import_jsx_runtime11 = require("react/jsx-runtime");
|
|
2587
2994
|
function CartDrawer({
|
|
2588
2995
|
trigger,
|
|
2589
2996
|
className,
|
|
2590
2997
|
theme
|
|
2591
2998
|
}) {
|
|
2592
|
-
const { cart, loading } = (0,
|
|
2593
|
-
const [open, setOpen] = (0,
|
|
2594
|
-
const [showCheckout, setShowCheckout] = (0,
|
|
2595
|
-
const [mounted, setMounted] = (0,
|
|
2596
|
-
const client = (0,
|
|
2597
|
-
(0,
|
|
2999
|
+
const { cart, loading } = (0, import_sdk10.useCart)();
|
|
3000
|
+
const [open, setOpen] = (0, import_react8.useState)(false);
|
|
3001
|
+
const [showCheckout, setShowCheckout] = (0, import_react8.useState)(false);
|
|
3002
|
+
const [mounted, setMounted] = (0, import_react8.useState)(false);
|
|
3003
|
+
const client = (0, import_sdk10.useAkropolysContext)();
|
|
3004
|
+
(0, import_react8.useEffect)(() => {
|
|
2598
3005
|
setMounted(true);
|
|
2599
3006
|
const handleTriggerCheckout = () => {
|
|
2600
3007
|
setShowCheckout(true);
|
|
@@ -2605,7 +3012,7 @@ function CartDrawer({
|
|
|
2605
3012
|
window.removeEventListener("akropolys:trigger_checkout", handleTriggerCheckout);
|
|
2606
3013
|
};
|
|
2607
3014
|
}, []);
|
|
2608
|
-
(0,
|
|
3015
|
+
(0, import_react8.useEffect)(() => {
|
|
2609
3016
|
if (open) {
|
|
2610
3017
|
document.body.style.overflow = "hidden";
|
|
2611
3018
|
} else {
|
|
@@ -2634,8 +3041,8 @@ function CartDrawer({
|
|
|
2634
3041
|
...theme?.fontFamily && { "--hsk-font": theme.fontFamily },
|
|
2635
3042
|
...theme?.borderRadius && { "--hsk-border-radius": theme.borderRadius }
|
|
2636
3043
|
} : void 0;
|
|
2637
|
-
return /* @__PURE__ */ (0,
|
|
2638
|
-
trigger ? /* @__PURE__ */ (0,
|
|
3044
|
+
return /* @__PURE__ */ (0, import_jsx_runtime11.jsxs)(import_jsx_runtime11.Fragment, { children: [
|
|
3045
|
+
trigger ? /* @__PURE__ */ (0, import_jsx_runtime11.jsx)("div", { onClick: () => setOpen(true), style: { display: "inline-block" }, children: trigger }) : /* @__PURE__ */ (0, import_jsx_runtime11.jsxs)(
|
|
2639
3046
|
"button",
|
|
2640
3047
|
{
|
|
2641
3048
|
onClick: () => setOpen(true),
|
|
@@ -2644,24 +3051,24 @@ function CartDrawer({
|
|
|
2644
3051
|
"data-hsk-theme": hskThemeAttr,
|
|
2645
3052
|
"aria-label": "Open cart",
|
|
2646
3053
|
children: [
|
|
2647
|
-
/* @__PURE__ */ (0,
|
|
2648
|
-
/* @__PURE__ */ (0,
|
|
2649
|
-
/* @__PURE__ */ (0,
|
|
2650
|
-
/* @__PURE__ */ (0,
|
|
3054
|
+
/* @__PURE__ */ (0, import_jsx_runtime11.jsxs)("svg", { width: "20", height: "20", viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "2", strokeLinecap: "round", strokeLinejoin: "round", children: [
|
|
3055
|
+
/* @__PURE__ */ (0, import_jsx_runtime11.jsx)("circle", { cx: "9", cy: "21", r: "1" }),
|
|
3056
|
+
/* @__PURE__ */ (0, import_jsx_runtime11.jsx)("circle", { cx: "20", cy: "21", r: "1" }),
|
|
3057
|
+
/* @__PURE__ */ (0, import_jsx_runtime11.jsx)("path", { d: "M1 1h4l2.68 13.39a2 2 0 0 0 2 1.61h9.72a2 2 0 0 0 2-1.61L23 6H6" })
|
|
2651
3058
|
] }),
|
|
2652
|
-
cart && cart.item_count > 0 ? /* @__PURE__ */ (0,
|
|
3059
|
+
cart && cart.item_count > 0 ? /* @__PURE__ */ (0, import_jsx_runtime11.jsx)("span", { className: "hsk-cart-trigger-badge", children: cart.item_count }) : null
|
|
2653
3060
|
]
|
|
2654
3061
|
}
|
|
2655
3062
|
),
|
|
2656
3063
|
open && mounted && (0, import_react_dom4.createPortal)(
|
|
2657
|
-
/* @__PURE__ */ (0,
|
|
3064
|
+
/* @__PURE__ */ (0, import_jsx_runtime11.jsx)(
|
|
2658
3065
|
"div",
|
|
2659
3066
|
{
|
|
2660
3067
|
className: "hsk-cart-backdrop",
|
|
2661
3068
|
style: customStyles,
|
|
2662
3069
|
"data-hsk-theme": hskThemeAttr,
|
|
2663
3070
|
onClick: () => setOpen(false),
|
|
2664
|
-
children: /* @__PURE__ */ (0,
|
|
3071
|
+
children: /* @__PURE__ */ (0, import_jsx_runtime11.jsxs)(
|
|
2665
3072
|
"div",
|
|
2666
3073
|
{
|
|
2667
3074
|
className: "hsk-cart-bottom-sheet",
|
|
@@ -2669,36 +3076,36 @@ function CartDrawer({
|
|
|
2669
3076
|
"data-hsk-theme": hskThemeAttr,
|
|
2670
3077
|
onClick: (e) => e.stopPropagation(),
|
|
2671
3078
|
children: [
|
|
2672
|
-
/* @__PURE__ */ (0,
|
|
2673
|
-
/* @__PURE__ */ (0,
|
|
2674
|
-
/* @__PURE__ */ (0,
|
|
2675
|
-
/* @__PURE__ */ (0,
|
|
3079
|
+
/* @__PURE__ */ (0, import_jsx_runtime11.jsx)("div", { className: "hsk-cart-sheet-handle" }),
|
|
3080
|
+
/* @__PURE__ */ (0, import_jsx_runtime11.jsxs)("div", { className: "hsk-cart-sheet-header", children: [
|
|
3081
|
+
/* @__PURE__ */ (0, import_jsx_runtime11.jsx)("h2", { children: "Your Cart" }),
|
|
3082
|
+
/* @__PURE__ */ (0, import_jsx_runtime11.jsx)("button", { onClick: () => setOpen(false), className: "hsk-close-btn", children: "\xD7" })
|
|
2676
3083
|
] }),
|
|
2677
|
-
/* @__PURE__ */ (0,
|
|
2678
|
-
item.image && /* @__PURE__ */ (0,
|
|
2679
|
-
/* @__PURE__ */ (0,
|
|
2680
|
-
/* @__PURE__ */ (0,
|
|
2681
|
-
/* @__PURE__ */ (0,
|
|
3084
|
+
/* @__PURE__ */ (0, import_jsx_runtime11.jsx)("div", { className: "hsk-cart-sheet-content", children: loading && !cart ? /* @__PURE__ */ (0, import_jsx_runtime11.jsx)("div", { className: "hsk-cart-loading", children: "Loading cart..." }) : !cart || cart.items.length === 0 ? /* @__PURE__ */ (0, import_jsx_runtime11.jsx)("div", { className: "hsk-cart-empty", children: "Your cart is empty." }) : /* @__PURE__ */ (0, import_jsx_runtime11.jsx)("ul", { className: "hsk-cart-items", children: cart.items.map((item) => /* @__PURE__ */ (0, import_jsx_runtime11.jsxs)("li", { className: "hsk-cart-item", children: [
|
|
3085
|
+
item.image && /* @__PURE__ */ (0, import_jsx_runtime11.jsx)("img", { src: item.image, alt: item.name, className: "hsk-cart-item-img" }),
|
|
3086
|
+
/* @__PURE__ */ (0, import_jsx_runtime11.jsxs)("div", { className: "hsk-cart-item-info", children: [
|
|
3087
|
+
/* @__PURE__ */ (0, import_jsx_runtime11.jsx)("span", { className: "hsk-cart-item-name", children: item.name }),
|
|
3088
|
+
/* @__PURE__ */ (0, import_jsx_runtime11.jsxs)("span", { className: "hsk-cart-item-price", children: [
|
|
2682
3089
|
item.currency,
|
|
2683
3090
|
" ",
|
|
2684
3091
|
item.price_numeric.toLocaleString(void 0, { minimumFractionDigits: 2 })
|
|
2685
3092
|
] })
|
|
2686
3093
|
] }),
|
|
2687
|
-
/* @__PURE__ */ (0,
|
|
3094
|
+
/* @__PURE__ */ (0, import_jsx_runtime11.jsxs)("div", { className: "hsk-cart-item-qty", children: [
|
|
2688
3095
|
"x",
|
|
2689
3096
|
item.quantity
|
|
2690
3097
|
] })
|
|
2691
3098
|
] }, item.id)) }) }),
|
|
2692
|
-
cart && cart.items.length > 0 && /* @__PURE__ */ (0,
|
|
2693
|
-
/* @__PURE__ */ (0,
|
|
2694
|
-
/* @__PURE__ */ (0,
|
|
2695
|
-
/* @__PURE__ */ (0,
|
|
3099
|
+
cart && cart.items.length > 0 && /* @__PURE__ */ (0, import_jsx_runtime11.jsxs)("div", { className: "hsk-cart-sheet-footer", children: [
|
|
3100
|
+
/* @__PURE__ */ (0, import_jsx_runtime11.jsxs)("div", { className: "hsk-cart-total", children: [
|
|
3101
|
+
/* @__PURE__ */ (0, import_jsx_runtime11.jsx)("span", { children: "Total" }),
|
|
3102
|
+
/* @__PURE__ */ (0, import_jsx_runtime11.jsxs)("span", { children: [
|
|
2696
3103
|
cart.currency,
|
|
2697
3104
|
" ",
|
|
2698
3105
|
cart.total.toLocaleString(void 0, { minimumFractionDigits: 2 })
|
|
2699
3106
|
] })
|
|
2700
3107
|
] }),
|
|
2701
|
-
/* @__PURE__ */ (0,
|
|
3108
|
+
/* @__PURE__ */ (0, import_jsx_runtime11.jsx)("button", { onClick: handleCheckout, className: "hsk-checkout-btn", children: "Checkout securely" })
|
|
2702
3109
|
] })
|
|
2703
3110
|
]
|
|
2704
3111
|
}
|
|
@@ -2707,7 +3114,7 @@ function CartDrawer({
|
|
|
2707
3114
|
),
|
|
2708
3115
|
document.body
|
|
2709
3116
|
),
|
|
2710
|
-
showCheckout && mounted && /* @__PURE__ */ (0,
|
|
3117
|
+
showCheckout && mounted && /* @__PURE__ */ (0, import_jsx_runtime11.jsx)(
|
|
2711
3118
|
CheckoutModal,
|
|
2712
3119
|
{
|
|
2713
3120
|
onClose: () => {
|
|
@@ -2731,6 +3138,8 @@ function CartDrawer({
|
|
|
2731
3138
|
KikuButton,
|
|
2732
3139
|
KikuChat,
|
|
2733
3140
|
SearchBar,
|
|
2734
|
-
Sparkle
|
|
3141
|
+
Sparkle,
|
|
3142
|
+
VisualSearch,
|
|
3143
|
+
VoiceButton
|
|
2735
3144
|
});
|
|
2736
3145
|
//# sourceMappingURL=index.js.map
|