@akropolys/kiku 1.5.1 → 1.5.3

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.mjs CHANGED
@@ -437,18 +437,31 @@ var ArrowUpIcon = () => /* @__PURE__ */ jsxs4("svg", { width: "18", height: "18"
437
437
  /* @__PURE__ */ jsx5("path", { d: "m5 12 7-7 7 7" }),
438
438
  /* @__PURE__ */ jsx5("path", { d: "M12 19V5" })
439
439
  ] });
440
- function SourceCard({ source, defaultCurrency, onSelect }) {
441
- return /* @__PURE__ */ jsxs4("div", { className: "hsk-source-card", onClick: () => onSelect?.(source), children: [
442
- source.image && /* @__PURE__ */ jsx5("img", { src: source.image, alt: source.name, className: "hsk-source-img" }),
443
- /* @__PURE__ */ jsxs4("div", { style: { flex: 1, minWidth: 0 }, children: [
444
- /* @__PURE__ */ jsx5("div", { className: "hsk-source-name", children: source.name }),
445
- source.price && /* @__PURE__ */ jsxs4("div", { className: "hsk-source-price", children: [
446
- source.currency ?? defaultCurrency,
447
- " ",
448
- source.price
449
- ] })
450
- ] })
451
- ] });
440
+ function SourceCard({
441
+ source,
442
+ defaultCurrency,
443
+ onSelect,
444
+ isReferenced
445
+ }) {
446
+ return /* @__PURE__ */ jsxs4(
447
+ "div",
448
+ {
449
+ className: cn("hsk-source-card", isReferenced && "hsk-source-card--referenced"),
450
+ onClick: () => onSelect?.(source),
451
+ children: [
452
+ source.image && /* @__PURE__ */ jsx5("img", { src: source.image, alt: source.name, className: "hsk-source-img" }),
453
+ /* @__PURE__ */ jsxs4("div", { style: { flex: 1, minWidth: 0, position: "relative" }, children: [
454
+ isReferenced && /* @__PURE__ */ jsx5("div", { className: "hsk-cb-source-ref-badge", title: "Featured in response", style: { top: "0", right: "0" }, children: /* @__PURE__ */ jsx5(SparkleIcon, {}) }),
455
+ /* @__PURE__ */ jsx5("div", { className: "hsk-source-name", style: { paddingRight: isReferenced ? "20px" : void 0 }, children: source.name }),
456
+ source.price && /* @__PURE__ */ jsxs4("div", { className: "hsk-source-price", children: [
457
+ source.currency ?? defaultCurrency,
458
+ " ",
459
+ source.price
460
+ ] })
461
+ ] })
462
+ ]
463
+ }
464
+ );
452
465
  }
453
466
  function ChatWidget({
454
467
  title = "AI Shopping Assistant",
@@ -464,7 +477,7 @@ function ChatWidget({
464
477
  enableVision = false,
465
478
  visionCategoryHint
466
479
  }) {
467
- const { messages, sources, loading: chatLoading, error, send, reset } = useKiku();
480
+ const { messages, sources, referencedIds, loading: chatLoading, streaming, error, send, reset } = useKiku();
468
481
  const [input, setInput] = useState4("");
469
482
  const [visualLoading, setVisualLoading] = useState4(false);
470
483
  const bottomRef = useRef4(null);
@@ -622,7 +635,54 @@ I couldn't find any matching products in the store.`;
622
635
  ] })
623
636
  ] }),
624
637
  msg.role === "assistant" && msg.visualSources && msg.visualSources.length > 0 && /* @__PURE__ */ jsx5("div", { className: "hsk-sources-container", children: /* @__PURE__ */ jsx5("div", { className: "hsk-sources", children: msg.visualSources.map((src, si) => /* @__PURE__ */ jsx5(SourceCard, { source: src, defaultCurrency, onSelect: onSelectSource }, si)) }) }),
625
- msg.role === "assistant" && idx === chatHistory.length - 1 && !msg.visualSources && sources.length > 0 && /* @__PURE__ */ jsx5("div", { className: "hsk-sources-container", children: /* @__PURE__ */ jsx5("div", { className: "hsk-sources", children: sources.map((src, si) => /* @__PURE__ */ jsx5(SourceCard, { source: src, defaultCurrency, onSelect: onSelectSource }, si)) }) })
638
+ msg.role === "assistant" && idx === chatHistory.length - 1 && !msg.visualSources && sources.length > 0 && (() => {
639
+ const isStreamingActive = chatLoading || streaming;
640
+ if (isStreamingActive) {
641
+ return /* @__PURE__ */ jsx5("div", { className: "hsk-sources-container", children: /* @__PURE__ */ jsx5("div", { className: "hsk-sources", children: sources.map((src, si) => {
642
+ const isReferenced = !!(src.id && referencedIds.includes(src.id));
643
+ return /* @__PURE__ */ jsx5(
644
+ SourceCard,
645
+ {
646
+ source: src,
647
+ defaultCurrency,
648
+ onSelect: onSelectSource,
649
+ isReferenced
650
+ },
651
+ si
652
+ );
653
+ }) }) });
654
+ }
655
+ const featured = sources.filter((src) => src.id && referencedIds.includes(src.id));
656
+ const general = sources.filter((src) => !src.id || !referencedIds.includes(src.id));
657
+ return /* @__PURE__ */ jsxs4("div", { className: "hsk-sources-container", children: [
658
+ featured.length > 0 && /* @__PURE__ */ jsxs4("div", { className: "hsk-sources-group", style: { marginBottom: "10px" }, children: [
659
+ /* @__PURE__ */ jsx5("div", { className: "hsk-sources-group-title", children: "\u2B50 Featured in response" }),
660
+ /* @__PURE__ */ jsx5("div", { className: "hsk-sources", children: featured.map((src, si) => /* @__PURE__ */ jsx5(
661
+ SourceCard,
662
+ {
663
+ source: src,
664
+ defaultCurrency,
665
+ onSelect: onSelectSource,
666
+ isReferenced: true
667
+ },
668
+ `feat-${si}`
669
+ )) })
670
+ ] }),
671
+ general.length > 0 && /* @__PURE__ */ jsxs4("div", { className: "hsk-sources-group", children: [
672
+ featured.length > 0 && /* @__PURE__ */ jsx5("div", { className: "hsk-sources-group-title", children: "All matches" }),
673
+ /* @__PURE__ */ jsx5("div", { className: "hsk-sources", children: general.map((src, si) => /* @__PURE__ */ jsx5(
674
+ SourceCard,
675
+ {
676
+ source: src,
677
+ defaultCurrency,
678
+ onSelect: onSelectSource,
679
+ isReferenced: false
680
+ },
681
+ `gen-${si}`
682
+ )) })
683
+ ] })
684
+ ] });
685
+ })()
626
686
  ] }, idx)),
627
687
  loading && /* @__PURE__ */ jsxs4("div", { className: "hsk-msg-row", children: [
628
688
  /* @__PURE__ */ jsx5("div", { className: "hsk-msg-avatar ai", children: /* @__PURE__ */ jsx5(SparkleIcon, {}) }),
@@ -1152,8 +1212,10 @@ function ActionPills({ cart, actionType, onSend, loading }) {
1152
1212
  const pills = [];
1153
1213
  if (hasItems && lastItem) {
1154
1214
  if (actionType === "add_to_cart") {
1155
- pills.push({ emoji: "\u2795", label: "Add 1 more", query: `Add one more ${lastItem.name} to my cart` });
1156
- pills.push({ emoji: "\u{1F5D1}\uFE0F", label: `Remove ${lastItem.name.split(" ")[0]}`, query: `Remove the ${lastItem.name} from my cart` });
1215
+ const name = lastItem.name || "item";
1216
+ const shortName = name.split(" ")[0] || "item";
1217
+ pills.push({ emoji: "\u2795", label: "Add 1 more", query: `Add one more ${name} to my cart` });
1218
+ pills.push({ emoji: "\u{1F5D1}\uFE0F", label: `Remove ${shortName}`, query: `Remove the ${name} from my cart` });
1157
1219
  }
1158
1220
  if (cart.items.length > 1) {
1159
1221
  pills.push({ emoji: "\u{1F6D2}", label: "View cart", query: "Show me my cart" });
@@ -1184,7 +1246,7 @@ function ActionPills({ cart, actionType, onSend, loading }) {
1184
1246
  pill.query
1185
1247
  )) });
1186
1248
  }
1187
- function SourcesCarousel({ sources, defaultCurrency, onSelectSource }) {
1249
+ function SourcesCarousel({ sources, defaultCurrency, onSelectSource, referencedIds = [] }) {
1188
1250
  const client = useAkropolysContext3();
1189
1251
  const isProperty = client?.vertical === "property";
1190
1252
  const railRef = useRef5(null);
@@ -1211,44 +1273,51 @@ function SourcesCarousel({ sources, defaultCurrency, onSelectSource }) {
1211
1273
  railRef.current?.scrollBy({ left: 170, behavior: "smooth" });
1212
1274
  };
1213
1275
  return /* @__PURE__ */ jsxs6("div", { className: "hsk-cb-sources-wrap", children: [
1214
- /* @__PURE__ */ jsx7("div", { className: "hsk-cb-sources", ref: railRef, children: sources.map((src, si) => /* @__PURE__ */ jsxs6(
1215
- "div",
1216
- {
1217
- className: "hsk-cb-source",
1218
- style: { animationDelay: `${si * 50}ms` },
1219
- onClick: () => onSelectSource?.(src),
1220
- children: [
1221
- src.image ? /* @__PURE__ */ jsxs6("div", { className: "hsk-cb-src-imgwrap", style: { position: "relative" }, children: [
1222
- /* @__PURE__ */ jsx7("img", { src: src.image, alt: src.name, loading: "lazy" }),
1223
- isProperty && /* @__PURE__ */ jsx7("div", { style: {
1224
- position: "absolute",
1225
- top: "6px",
1226
- right: "6px",
1227
- background: "rgba(14, 14, 15, 0.75)",
1228
- backdropFilter: "blur(4px)",
1229
- borderRadius: "50%",
1230
- width: "24px",
1231
- height: "24px",
1232
- display: "flex",
1233
- alignItems: "center",
1234
- justifyContent: "center",
1235
- color: "#fbbf24",
1236
- // Gold sparkle badge
1237
- boxShadow: "0 2px 4px rgba(0,0,0,0.2)"
1238
- }, children: /* @__PURE__ */ jsx7(SparkleIcon2, { size: 12 }) })
1239
- ] }) : /* @__PURE__ */ jsx7("div", { className: "hsk-cb-src-imgwrap-empty", children: /* @__PURE__ */ jsx7(SparkleIcon2, {}) }),
1240
- /* @__PURE__ */ jsxs6("div", { className: "hsk-cb-src-info", children: [
1241
- /* @__PURE__ */ jsx7("div", { className: "hsk-cb-src-name", children: src.name }),
1242
- src.price && /* @__PURE__ */ jsxs6("div", { className: "hsk-cb-src-price", children: [
1243
- src.currency ?? defaultCurrency,
1244
- " ",
1245
- parseFloat(String(src.price).replace(/[^0-9.]/g, "") || "0").toLocaleString()
1276
+ /* @__PURE__ */ jsx7("div", { className: "hsk-cb-sources", ref: railRef, children: sources.map((src, si) => {
1277
+ const isReferenced = !!(src.id && referencedIds.includes(src.id));
1278
+ return /* @__PURE__ */ jsxs6(
1279
+ "div",
1280
+ {
1281
+ className: cn("hsk-cb-source", isReferenced && "hsk-cb-source--referenced"),
1282
+ style: { animationDelay: `${si * 50}ms` },
1283
+ onClick: () => onSelectSource?.(src),
1284
+ children: [
1285
+ src.image ? /* @__PURE__ */ jsxs6("div", { className: "hsk-cb-src-imgwrap", style: { position: "relative" }, children: [
1286
+ /* @__PURE__ */ jsx7("img", { src: src.image, alt: src.name, loading: "lazy" }),
1287
+ isReferenced && /* @__PURE__ */ jsx7("div", { className: "hsk-cb-source-ref-badge", title: "Featured in response", children: /* @__PURE__ */ jsx7(SparkleIcon2, { size: 10 }) }),
1288
+ isProperty && /* @__PURE__ */ jsx7("div", { style: {
1289
+ position: "absolute",
1290
+ top: "6px",
1291
+ right: "6px",
1292
+ background: "rgba(14, 14, 15, 0.75)",
1293
+ backdropFilter: "blur(4px)",
1294
+ borderRadius: "50%",
1295
+ width: "24px",
1296
+ height: "24px",
1297
+ display: "flex",
1298
+ alignItems: "center",
1299
+ justifyContent: "center",
1300
+ color: "#fbbf24",
1301
+ // Gold sparkle badge
1302
+ boxShadow: "0 2px 4px rgba(0,0,0,0.2)"
1303
+ }, children: /* @__PURE__ */ jsx7(SparkleIcon2, { size: 12 }) })
1304
+ ] }) : /* @__PURE__ */ jsxs6("div", { className: "hsk-cb-src-imgwrap-empty", style: { position: "relative" }, children: [
1305
+ /* @__PURE__ */ jsx7(SparkleIcon2, {}),
1306
+ isReferenced && /* @__PURE__ */ jsx7("div", { className: "hsk-cb-source-ref-badge", title: "Featured in response", children: /* @__PURE__ */ jsx7(SparkleIcon2, { size: 10 }) })
1307
+ ] }),
1308
+ /* @__PURE__ */ jsxs6("div", { className: "hsk-cb-src-info", children: [
1309
+ /* @__PURE__ */ jsx7("div", { className: "hsk-cb-src-name", children: src.name }),
1310
+ src.price && /* @__PURE__ */ jsxs6("div", { className: "hsk-cb-src-price", children: [
1311
+ src.currency ?? defaultCurrency,
1312
+ " ",
1313
+ parseFloat(String(src.price).replace(/[^0-9.]/g, "") || "0").toLocaleString()
1314
+ ] })
1246
1315
  ] })
1247
- ] })
1248
- ]
1249
- },
1250
- si
1251
- )) }),
1316
+ ]
1317
+ },
1318
+ si
1319
+ );
1320
+ }) }),
1252
1321
  showNext && /* @__PURE__ */ jsxs6(Fragment3, { children: [
1253
1322
  /* @__PURE__ */ jsx7(
1254
1323
  "div",
@@ -1296,11 +1365,12 @@ function SmartContextPills({
1296
1365
  });
1297
1366
  }
1298
1367
  if (cheapest && !isProperty) {
1299
- const short = cheapest.name.split(" ").slice(0, 3).join(" ");
1368
+ const name = cheapest.name || "";
1369
+ const short = name.split(" ").slice(0, 3).join(" ");
1300
1370
  pills.push({
1301
1371
  emoji: "\u{1F6D2}",
1302
1372
  label: `Add ${short}`,
1303
- query: `Add the ${cheapest.name} to my cart`
1373
+ query: `Add the ${name} to my cart`
1304
1374
  });
1305
1375
  }
1306
1376
  if (isProperty) {
@@ -1310,11 +1380,12 @@ function SmartContextPills({
1310
1380
  }
1311
1381
  } else if (intent === "compare" && sources.length > 0) {
1312
1382
  if (cheapest && !isProperty) {
1313
- const short = cheapest.name.split(" ").slice(0, 3).join(" ");
1383
+ const name = cheapest.name || "";
1384
+ const short = name.split(" ").slice(0, 3).join(" ");
1314
1385
  pills.push({
1315
1386
  emoji: "\u{1F6D2}",
1316
1387
  label: `Add ${short}`,
1317
- query: `Add the ${cheapest.name} to my cart`
1388
+ query: `Add the ${name} to my cart`
1318
1389
  });
1319
1390
  }
1320
1391
  if (firstName) {
@@ -1417,7 +1488,7 @@ function ChatModal({
1417
1488
  visionCategoryHint
1418
1489
  }) {
1419
1490
  const client = useAkropolysContext3();
1420
- const { messages, sources, loading, streaming, error, lastAction, lastIntent, send, reset } = useKiku2();
1491
+ const { messages, sources, loading, streaming, error, lastAction, lastIntent, send, reset, referencedIds } = useKiku2();
1421
1492
  const [input, setInput] = useState5("");
1422
1493
  const [loadingMessageIndex, setLoadingMessageIndex] = useState5(0);
1423
1494
  const [attachments, setAttachments] = useState5([]);
@@ -1762,7 +1833,8 @@ function ChatModal({
1762
1833
  {
1763
1834
  sources,
1764
1835
  defaultCurrency,
1765
- onSelectSource: handleSourceClick
1836
+ onSelectSource: handleSourceClick,
1837
+ referencedIds
1766
1838
  }
1767
1839
  ),
1768
1840
  msg.cartSnapshot && msg.cartSnapshot.items?.length > 0 && /* @__PURE__ */ jsx7(