@akropolys/kiku 1.7.7 → 1.7.9
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/index.js +675 -418
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +667 -410
- package/dist/index.mjs.map +1 -1
- package/dist/styles.css +285 -0
- package/dist/styles.css.map +1 -1
- package/package.json +2 -2
package/dist/index.js
CHANGED
|
@@ -826,7 +826,7 @@ I couldn't find any matching products in the store.`;
|
|
|
826
826
|
}
|
|
827
827
|
|
|
828
828
|
// src/components/KikuButton.tsx
|
|
829
|
-
var
|
|
829
|
+
var import_react6 = require("react");
|
|
830
830
|
var import_react_dom = require("react-dom");
|
|
831
831
|
var import_sdk5 = require("@akropolys/sdk");
|
|
832
832
|
var import_sdk6 = require("@akropolys/sdk");
|
|
@@ -1139,9 +1139,226 @@ function ComparisonMatrix({ sources, defaultCurrency = "KES", displayConfig }) {
|
|
|
1139
1139
|
);
|
|
1140
1140
|
}
|
|
1141
1141
|
|
|
1142
|
-
// src/components/
|
|
1142
|
+
// src/components/MarkupEditor.tsx
|
|
1143
|
+
var import_react5 = require("react");
|
|
1143
1144
|
var import_jsx_runtime7 = require("react/jsx-runtime");
|
|
1144
|
-
var
|
|
1145
|
+
var COLORS = ["#111111", "#ff5a5a", "#ffb300", "#22c55e", "#06b6d4", "#d946ef", "#9ca3af"];
|
|
1146
|
+
var MAX_EXPORT_DIM = 1280;
|
|
1147
|
+
function MarkupEditor({ src, onCancel, onSend }) {
|
|
1148
|
+
const [img, setImg] = (0, import_react5.useState)(null);
|
|
1149
|
+
const [loadError, setLoadError] = (0, import_react5.useState)(false);
|
|
1150
|
+
const [tool, setTool] = (0, import_react5.useState)("pen");
|
|
1151
|
+
const [color, setColor] = (0, import_react5.useState)(COLORS[1]);
|
|
1152
|
+
const [actions, setActions] = (0, import_react5.useState)([]);
|
|
1153
|
+
const [pendingText, setPendingText] = (0, import_react5.useState)(null);
|
|
1154
|
+
const [textValue, setTextValue] = (0, import_react5.useState)("");
|
|
1155
|
+
const [instruction, setInstruction] = (0, import_react5.useState)("");
|
|
1156
|
+
const [exportError, setExportError] = (0, import_react5.useState)(false);
|
|
1157
|
+
const canvasRef = (0, import_react5.useRef)(null);
|
|
1158
|
+
const drawingRef = (0, import_react5.useRef)(null);
|
|
1159
|
+
const textInputRef = (0, import_react5.useRef)(null);
|
|
1160
|
+
(0, import_react5.useEffect)(() => {
|
|
1161
|
+
const el = new Image();
|
|
1162
|
+
el.crossOrigin = "anonymous";
|
|
1163
|
+
el.onload = () => setImg(el);
|
|
1164
|
+
el.onerror = () => setLoadError(true);
|
|
1165
|
+
el.src = src;
|
|
1166
|
+
}, [src]);
|
|
1167
|
+
const dims = (() => {
|
|
1168
|
+
if (!img) return { w: 0, h: 0 };
|
|
1169
|
+
const scale = Math.min(1, MAX_EXPORT_DIM / Math.max(img.naturalWidth, img.naturalHeight));
|
|
1170
|
+
return { w: Math.round(img.naturalWidth * scale), h: Math.round(img.naturalHeight * scale) };
|
|
1171
|
+
})();
|
|
1172
|
+
const markLayer = (0, import_react5.useRef)(null);
|
|
1173
|
+
const paint = (live) => {
|
|
1174
|
+
const canvas = canvasRef.current;
|
|
1175
|
+
if (!canvas || !img) return;
|
|
1176
|
+
const ctx = canvas.getContext("2d");
|
|
1177
|
+
if (!ctx) return;
|
|
1178
|
+
if (!markLayer.current) markLayer.current = document.createElement("canvas");
|
|
1179
|
+
const layer = markLayer.current;
|
|
1180
|
+
layer.width = canvas.width;
|
|
1181
|
+
layer.height = canvas.height;
|
|
1182
|
+
const lctx = layer.getContext("2d");
|
|
1183
|
+
const all = live ? [...actions, live] : actions;
|
|
1184
|
+
for (const a of all) {
|
|
1185
|
+
if (a.kind === "stroke") {
|
|
1186
|
+
lctx.save();
|
|
1187
|
+
lctx.globalCompositeOperation = a.tool === "eraser" ? "destination-out" : "source-over";
|
|
1188
|
+
lctx.strokeStyle = a.color;
|
|
1189
|
+
lctx.lineWidth = a.tool === "eraser" ? a.size * 3 : a.size;
|
|
1190
|
+
lctx.lineCap = "round";
|
|
1191
|
+
lctx.lineJoin = "round";
|
|
1192
|
+
lctx.beginPath();
|
|
1193
|
+
a.points.forEach((p, i) => i === 0 ? lctx.moveTo(p.x, p.y) : lctx.lineTo(p.x, p.y));
|
|
1194
|
+
if (a.points.length === 1) lctx.lineTo(a.points[0].x + 0.01, a.points[0].y);
|
|
1195
|
+
lctx.stroke();
|
|
1196
|
+
lctx.restore();
|
|
1197
|
+
} else {
|
|
1198
|
+
lctx.save();
|
|
1199
|
+
lctx.fillStyle = a.color;
|
|
1200
|
+
lctx.font = `600 ${a.size}px system-ui, sans-serif`;
|
|
1201
|
+
lctx.fillText(a.value, a.x, a.y);
|
|
1202
|
+
lctx.restore();
|
|
1203
|
+
}
|
|
1204
|
+
}
|
|
1205
|
+
ctx.clearRect(0, 0, canvas.width, canvas.height);
|
|
1206
|
+
ctx.drawImage(img, 0, 0, canvas.width, canvas.height);
|
|
1207
|
+
ctx.drawImage(layer, 0, 0);
|
|
1208
|
+
};
|
|
1209
|
+
(0, import_react5.useEffect)(() => {
|
|
1210
|
+
paint();
|
|
1211
|
+
}, [img, actions, dims.w, dims.h]);
|
|
1212
|
+
(0, import_react5.useEffect)(() => {
|
|
1213
|
+
if (pendingText) textInputRef.current?.focus();
|
|
1214
|
+
}, [pendingText]);
|
|
1215
|
+
const toCanvasPoint = (e) => {
|
|
1216
|
+
const canvas = canvasRef.current;
|
|
1217
|
+
const rect = canvas.getBoundingClientRect();
|
|
1218
|
+
return {
|
|
1219
|
+
x: (e.clientX - rect.left) / rect.width * canvas.width,
|
|
1220
|
+
y: (e.clientY - rect.top) / rect.height * canvas.height
|
|
1221
|
+
};
|
|
1222
|
+
};
|
|
1223
|
+
const strokeSize = () => Math.max(4, Math.round(dims.w / 180));
|
|
1224
|
+
const textSize = () => Math.max(18, Math.round(dims.w / 28));
|
|
1225
|
+
const onPointerDown = (e) => {
|
|
1226
|
+
if (!img) return;
|
|
1227
|
+
const p = toCanvasPoint(e);
|
|
1228
|
+
if (tool === "text") {
|
|
1229
|
+
setPendingText({ x: p.x, y: p.y });
|
|
1230
|
+
setTextValue("");
|
|
1231
|
+
return;
|
|
1232
|
+
}
|
|
1233
|
+
e.target.setPointerCapture(e.pointerId);
|
|
1234
|
+
drawingRef.current = { kind: "stroke", tool, color, size: strokeSize(), points: [p] };
|
|
1235
|
+
paint(drawingRef.current);
|
|
1236
|
+
};
|
|
1237
|
+
const onPointerMove = (e) => {
|
|
1238
|
+
if (!drawingRef.current) return;
|
|
1239
|
+
drawingRef.current.points.push(toCanvasPoint(e));
|
|
1240
|
+
paint(drawingRef.current);
|
|
1241
|
+
};
|
|
1242
|
+
const onPointerUp = () => {
|
|
1243
|
+
if (!drawingRef.current) return;
|
|
1244
|
+
const done = drawingRef.current;
|
|
1245
|
+
drawingRef.current = null;
|
|
1246
|
+
setActions((prev) => [...prev, done]);
|
|
1247
|
+
};
|
|
1248
|
+
const commitText = () => {
|
|
1249
|
+
if (pendingText && textValue.trim()) {
|
|
1250
|
+
setActions((prev) => [...prev, { kind: "text", x: pendingText.x, y: pendingText.y, color, value: textValue.trim(), size: textSize() }]);
|
|
1251
|
+
}
|
|
1252
|
+
setPendingText(null);
|
|
1253
|
+
setTextValue("");
|
|
1254
|
+
};
|
|
1255
|
+
const handleSend = () => {
|
|
1256
|
+
const canvas = canvasRef.current;
|
|
1257
|
+
if (!canvas) return;
|
|
1258
|
+
try {
|
|
1259
|
+
paint();
|
|
1260
|
+
const dataUrl = canvas.toDataURL("image/jpeg", 0.92);
|
|
1261
|
+
onSend(dataUrl, instruction.trim());
|
|
1262
|
+
} catch {
|
|
1263
|
+
setExportError(true);
|
|
1264
|
+
}
|
|
1265
|
+
};
|
|
1266
|
+
const hasMarks = actions.length > 0;
|
|
1267
|
+
return /* @__PURE__ */ (0, import_jsx_runtime7.jsxs)("div", { className: "hsk-markup", role: "dialog", "aria-label": "Mark up image", children: [
|
|
1268
|
+
/* @__PURE__ */ (0, import_jsx_runtime7.jsxs)("div", { className: "hsk-markup-head", children: [
|
|
1269
|
+
/* @__PURE__ */ (0, import_jsx_runtime7.jsx)("span", { className: "hsk-markup-title", children: "Mark where you want the change" }),
|
|
1270
|
+
/* @__PURE__ */ (0, import_jsx_runtime7.jsx)("button", { className: "hsk-markup-cancel", onClick: onCancel, children: "Cancel" })
|
|
1271
|
+
] }),
|
|
1272
|
+
/* @__PURE__ */ (0, import_jsx_runtime7.jsx)("div", { className: "hsk-markup-stage", children: loadError ? /* @__PURE__ */ (0, import_jsx_runtime7.jsx)("div", { className: "hsk-markup-error", children: "This image can't be edited here." }) : !img ? /* @__PURE__ */ (0, import_jsx_runtime7.jsx)("div", { className: "hsk-markup-loading", children: "Loading image\u2026" }) : /* @__PURE__ */ (0, import_jsx_runtime7.jsxs)("div", { className: "hsk-markup-canvas-wrap", children: [
|
|
1273
|
+
/* @__PURE__ */ (0, import_jsx_runtime7.jsx)(
|
|
1274
|
+
"canvas",
|
|
1275
|
+
{
|
|
1276
|
+
ref: canvasRef,
|
|
1277
|
+
width: dims.w,
|
|
1278
|
+
height: dims.h,
|
|
1279
|
+
className: `hsk-markup-canvas hsk-markup-canvas--${tool}`,
|
|
1280
|
+
onPointerDown,
|
|
1281
|
+
onPointerMove,
|
|
1282
|
+
onPointerUp,
|
|
1283
|
+
onPointerLeave: onPointerUp
|
|
1284
|
+
}
|
|
1285
|
+
),
|
|
1286
|
+
pendingText && canvasRef.current && /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(
|
|
1287
|
+
"input",
|
|
1288
|
+
{
|
|
1289
|
+
ref: textInputRef,
|
|
1290
|
+
className: "hsk-markup-textinput",
|
|
1291
|
+
style: {
|
|
1292
|
+
left: `${pendingText.x / dims.w * 100}%`,
|
|
1293
|
+
top: `${pendingText.y / dims.h * 100}%`,
|
|
1294
|
+
color
|
|
1295
|
+
},
|
|
1296
|
+
value: textValue,
|
|
1297
|
+
placeholder: "Type, then Enter",
|
|
1298
|
+
onChange: (e) => setTextValue(e.target.value),
|
|
1299
|
+
onKeyDown: (e) => {
|
|
1300
|
+
if (e.key === "Enter") commitText();
|
|
1301
|
+
if (e.key === "Escape") {
|
|
1302
|
+
setPendingText(null);
|
|
1303
|
+
setTextValue("");
|
|
1304
|
+
}
|
|
1305
|
+
},
|
|
1306
|
+
onBlur: commitText
|
|
1307
|
+
}
|
|
1308
|
+
)
|
|
1309
|
+
] }) }),
|
|
1310
|
+
/* @__PURE__ */ (0, import_jsx_runtime7.jsxs)("div", { className: "hsk-markup-tools", children: [
|
|
1311
|
+
/* @__PURE__ */ (0, import_jsx_runtime7.jsx)("div", { className: "hsk-markup-colors", children: COLORS.map((c) => /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(
|
|
1312
|
+
"button",
|
|
1313
|
+
{
|
|
1314
|
+
className: `hsk-markup-color${color === c ? " hsk-markup-color--on" : ""}`,
|
|
1315
|
+
style: { background: c },
|
|
1316
|
+
onClick: () => {
|
|
1317
|
+
setColor(c);
|
|
1318
|
+
if (tool === "eraser") setTool("pen");
|
|
1319
|
+
},
|
|
1320
|
+
"aria-label": `Colour ${c}`
|
|
1321
|
+
},
|
|
1322
|
+
c
|
|
1323
|
+
)) }),
|
|
1324
|
+
/* @__PURE__ */ (0, import_jsx_runtime7.jsxs)("div", { className: "hsk-markup-actions", children: [
|
|
1325
|
+
/* @__PURE__ */ (0, import_jsx_runtime7.jsx)("button", { className: `hsk-markup-tool${tool === "pen" ? " hsk-markup-tool--on" : ""}`, onClick: () => setTool("pen"), children: "Sketch" }),
|
|
1326
|
+
/* @__PURE__ */ (0, import_jsx_runtime7.jsx)("button", { className: `hsk-markup-tool${tool === "text" ? " hsk-markup-tool--on" : ""}`, onClick: () => setTool("text"), children: "Text" }),
|
|
1327
|
+
/* @__PURE__ */ (0, import_jsx_runtime7.jsx)("button", { className: `hsk-markup-tool${tool === "eraser" ? " hsk-markup-tool--on" : ""}`, onClick: () => setTool("eraser"), children: "Eraser" }),
|
|
1328
|
+
/* @__PURE__ */ (0, import_jsx_runtime7.jsx)("button", { className: "hsk-markup-tool", onClick: () => setActions((prev) => prev.slice(0, -1)), disabled: !hasMarks, children: "Undo" }),
|
|
1329
|
+
/* @__PURE__ */ (0, import_jsx_runtime7.jsx)("button", { className: "hsk-markup-tool", onClick: () => setActions([]), disabled: !hasMarks, children: "Clear" })
|
|
1330
|
+
] })
|
|
1331
|
+
] }),
|
|
1332
|
+
/* @__PURE__ */ (0, import_jsx_runtime7.jsxs)("div", { className: "hsk-markup-send", children: [
|
|
1333
|
+
/* @__PURE__ */ (0, import_jsx_runtime7.jsx)(
|
|
1334
|
+
"input",
|
|
1335
|
+
{
|
|
1336
|
+
className: "hsk-markup-instruction",
|
|
1337
|
+
value: instruction,
|
|
1338
|
+
placeholder: "Describe the change \u2014 e.g. add the sofa here",
|
|
1339
|
+
onChange: (e) => setInstruction(e.target.value),
|
|
1340
|
+
onKeyDown: (e) => {
|
|
1341
|
+
if (e.key === "Enter" && (hasMarks || instruction.trim())) handleSend();
|
|
1342
|
+
}
|
|
1343
|
+
}
|
|
1344
|
+
),
|
|
1345
|
+
/* @__PURE__ */ (0, import_jsx_runtime7.jsx)(
|
|
1346
|
+
"button",
|
|
1347
|
+
{
|
|
1348
|
+
className: "hsk-markup-go",
|
|
1349
|
+
onClick: handleSend,
|
|
1350
|
+
disabled: !img || !hasMarks && !instruction.trim(),
|
|
1351
|
+
children: "Send"
|
|
1352
|
+
}
|
|
1353
|
+
)
|
|
1354
|
+
] }),
|
|
1355
|
+
exportError && /* @__PURE__ */ (0, import_jsx_runtime7.jsx)("div", { className: "hsk-markup-error", children: "Couldn't process this image \u2014 try a newer visualization." })
|
|
1356
|
+
] });
|
|
1357
|
+
}
|
|
1358
|
+
|
|
1359
|
+
// src/components/KikuButton.tsx
|
|
1360
|
+
var import_jsx_runtime8 = require("react/jsx-runtime");
|
|
1361
|
+
var KikuIcon = ({ className, size = 18 }) => /* @__PURE__ */ (0, import_jsx_runtime8.jsx)(
|
|
1145
1362
|
"svg",
|
|
1146
1363
|
{
|
|
1147
1364
|
className: cn("hsk-brand-mark", className),
|
|
@@ -1150,52 +1367,52 @@ var KikuIcon = ({ className, size = 18 }) => /* @__PURE__ */ (0, import_jsx_runt
|
|
|
1150
1367
|
viewBox: "0 0 100 100",
|
|
1151
1368
|
xmlns: "http://www.w3.org/2000/svg",
|
|
1152
1369
|
"aria-label": "kiku",
|
|
1153
|
-
children: /* @__PURE__ */ (0,
|
|
1154
|
-
/* @__PURE__ */ (0,
|
|
1155
|
-
/* @__PURE__ */ (0,
|
|
1370
|
+
children: /* @__PURE__ */ (0, import_jsx_runtime8.jsxs)("g", { transform: "translate(22.7 19) scale(0.62)", fill: "currentColor", fillRule: "evenodd", children: [
|
|
1371
|
+
/* @__PURE__ */ (0, import_jsx_runtime8.jsx)("path", { d: "M39.4 10.4 Q44 0 48.6 10.4 L86.1 95.8 Q88 100 83.4 100 L4.6 100 Q0 100 1.9 95.8 Z M24 100 L24 65 Q24 60 27.4 56.3 Q44 38 60.6 56.3 Q64 60 64 65 L64 100 Z" }),
|
|
1372
|
+
/* @__PURE__ */ (0, import_jsx_runtime8.jsx)("circle", { cx: "55", cy: "82", r: "3.4" })
|
|
1156
1373
|
] })
|
|
1157
1374
|
}
|
|
1158
1375
|
);
|
|
1159
1376
|
var SparkleIcon2 = KikuIcon;
|
|
1160
|
-
var ArrowUpIcon2 = () => /* @__PURE__ */ (0,
|
|
1161
|
-
/* @__PURE__ */ (0,
|
|
1162
|
-
/* @__PURE__ */ (0,
|
|
1377
|
+
var ArrowUpIcon2 = () => /* @__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: [
|
|
1378
|
+
/* @__PURE__ */ (0, import_jsx_runtime8.jsx)("path", { d: "m5 12 7-7 7 7" }),
|
|
1379
|
+
/* @__PURE__ */ (0, import_jsx_runtime8.jsx)("path", { d: "M12 19V5" })
|
|
1163
1380
|
] });
|
|
1164
|
-
var StopIcon = () => /* @__PURE__ */ (0,
|
|
1165
|
-
var ExternalIcon = () => /* @__PURE__ */ (0,
|
|
1166
|
-
/* @__PURE__ */ (0,
|
|
1167
|
-
/* @__PURE__ */ (0,
|
|
1168
|
-
/* @__PURE__ */ (0,
|
|
1381
|
+
var StopIcon = () => /* @__PURE__ */ (0, import_jsx_runtime8.jsx)("svg", { width: "14", height: "14", viewBox: "0 0 24 24", fill: "currentColor", children: /* @__PURE__ */ (0, import_jsx_runtime8.jsx)("rect", { x: "5", y: "5", width: "14", height: "14", rx: "2" }) });
|
|
1382
|
+
var ExternalIcon = () => /* @__PURE__ */ (0, import_jsx_runtime8.jsxs)("svg", { width: "12", height: "12", viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "2.2", strokeLinecap: "round", strokeLinejoin: "round", children: [
|
|
1383
|
+
/* @__PURE__ */ (0, import_jsx_runtime8.jsx)("path", { d: "M18 13v6a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2V8a2 2 0 0 1 2-2h6" }),
|
|
1384
|
+
/* @__PURE__ */ (0, import_jsx_runtime8.jsx)("polyline", { points: "15 3 21 3 21 9" }),
|
|
1385
|
+
/* @__PURE__ */ (0, import_jsx_runtime8.jsx)("line", { x1: "10", y1: "14", x2: "21", y2: "3" })
|
|
1169
1386
|
] });
|
|
1170
|
-
var ContinueIcon = () => /* @__PURE__ */ (0,
|
|
1171
|
-
var CloseIcon = () => /* @__PURE__ */ (0,
|
|
1172
|
-
/* @__PURE__ */ (0,
|
|
1173
|
-
/* @__PURE__ */ (0,
|
|
1387
|
+
var ContinueIcon = () => /* @__PURE__ */ (0, import_jsx_runtime8.jsx)("svg", { width: "13", height: "13", viewBox: "0 0 24 24", fill: "currentColor", children: /* @__PURE__ */ (0, import_jsx_runtime8.jsx)("path", { d: "M8 5v14l11-7z" }) });
|
|
1388
|
+
var CloseIcon = () => /* @__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: [
|
|
1389
|
+
/* @__PURE__ */ (0, import_jsx_runtime8.jsx)("line", { x1: "18", y1: "6", x2: "6", y2: "18" }),
|
|
1390
|
+
/* @__PURE__ */ (0, import_jsx_runtime8.jsx)("line", { x1: "6", y1: "6", x2: "18", y2: "18" })
|
|
1174
1391
|
] });
|
|
1175
|
-
var ChevronRightIcon = () => /* @__PURE__ */ (0,
|
|
1176
|
-
var HistoryIcon = () => /* @__PURE__ */ (0,
|
|
1177
|
-
/* @__PURE__ */ (0,
|
|
1178
|
-
/* @__PURE__ */ (0,
|
|
1179
|
-
/* @__PURE__ */ (0,
|
|
1392
|
+
var ChevronRightIcon = () => /* @__PURE__ */ (0, import_jsx_runtime8.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_runtime8.jsx)("path", { d: "m9 18 6-6-6-6" }) });
|
|
1393
|
+
var HistoryIcon = () => /* @__PURE__ */ (0, import_jsx_runtime8.jsxs)("svg", { width: "16", height: "16", viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "2", strokeLinecap: "round", strokeLinejoin: "round", children: [
|
|
1394
|
+
/* @__PURE__ */ (0, import_jsx_runtime8.jsx)("path", { d: "M3 12a9 9 0 1 0 9-9 9.75 9.75 0 0 0-6.74 2.74L3 8" }),
|
|
1395
|
+
/* @__PURE__ */ (0, import_jsx_runtime8.jsx)("path", { d: "M3 3v5h5" }),
|
|
1396
|
+
/* @__PURE__ */ (0, import_jsx_runtime8.jsx)("path", { d: "M12 7v5l4 2" })
|
|
1180
1397
|
] });
|
|
1181
|
-
var BookmarkIcon = () => /* @__PURE__ */ (0,
|
|
1182
|
-
var TrashIcon = () => /* @__PURE__ */ (0,
|
|
1183
|
-
/* @__PURE__ */ (0,
|
|
1184
|
-
/* @__PURE__ */ (0,
|
|
1398
|
+
var BookmarkIcon = () => /* @__PURE__ */ (0, import_jsx_runtime8.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_runtime8.jsx)("path", { d: "M19 21 12 16l-7 5V5a2 2 0 0 1 2-2h10a2 2 0 0 1 2 2z" }) });
|
|
1399
|
+
var TrashIcon = () => /* @__PURE__ */ (0, import_jsx_runtime8.jsxs)("svg", { width: "16", height: "16", viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "2", strokeLinecap: "round", strokeLinejoin: "round", children: [
|
|
1400
|
+
/* @__PURE__ */ (0, import_jsx_runtime8.jsx)("path", { d: "M3 6h18" }),
|
|
1401
|
+
/* @__PURE__ */ (0, import_jsx_runtime8.jsx)("path", { d: "M19 6v14a2 2 0 0 1-2 2H7a2 2 0 0 1-2-2V6m3 0V4a2 2 0 0 1 2-2h4a2 2 0 0 1 2 2v2" })
|
|
1185
1402
|
] });
|
|
1186
|
-
var PaperclipIcon = () => /* @__PURE__ */ (0,
|
|
1187
|
-
var MicIcon2 = () => /* @__PURE__ */ (0,
|
|
1188
|
-
/* @__PURE__ */ (0,
|
|
1189
|
-
/* @__PURE__ */ (0,
|
|
1190
|
-
/* @__PURE__ */ (0,
|
|
1403
|
+
var PaperclipIcon = () => /* @__PURE__ */ (0, import_jsx_runtime8.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_runtime8.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" }) });
|
|
1404
|
+
var MicIcon2 = () => /* @__PURE__ */ (0, import_jsx_runtime8.jsxs)("svg", { width: "16", height: "16", viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "2", strokeLinecap: "round", strokeLinejoin: "round", children: [
|
|
1405
|
+
/* @__PURE__ */ (0, import_jsx_runtime8.jsx)("path", { d: "M12 2a3 3 0 0 0-3 3v7a3 3 0 0 0 6 0V5a3 3 0 0 0-3-3z" }),
|
|
1406
|
+
/* @__PURE__ */ (0, import_jsx_runtime8.jsx)("path", { d: "M19 10v2a7 7 0 0 1-14 0v-2" }),
|
|
1407
|
+
/* @__PURE__ */ (0, import_jsx_runtime8.jsx)("line", { x1: "12", y1: "19", x2: "12", y2: "22" })
|
|
1191
1408
|
] });
|
|
1192
|
-
var MicOffIcon = () => /* @__PURE__ */ (0,
|
|
1193
|
-
/* @__PURE__ */ (0,
|
|
1194
|
-
/* @__PURE__ */ (0,
|
|
1195
|
-
/* @__PURE__ */ (0,
|
|
1196
|
-
/* @__PURE__ */ (0,
|
|
1197
|
-
/* @__PURE__ */ (0,
|
|
1198
|
-
/* @__PURE__ */ (0,
|
|
1409
|
+
var MicOffIcon = () => /* @__PURE__ */ (0, import_jsx_runtime8.jsxs)("svg", { width: "16", height: "16", viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "2", strokeLinecap: "round", strokeLinejoin: "round", children: [
|
|
1410
|
+
/* @__PURE__ */ (0, import_jsx_runtime8.jsx)("line", { x1: "2", y1: "2", x2: "22", y2: "22" }),
|
|
1411
|
+
/* @__PURE__ */ (0, import_jsx_runtime8.jsx)("path", { d: "M18.89 13.23A7.12 7.12 0 0 0 19 12v-2" }),
|
|
1412
|
+
/* @__PURE__ */ (0, import_jsx_runtime8.jsx)("path", { d: "M5 10v2a7 7 0 0 0 12 5" }),
|
|
1413
|
+
/* @__PURE__ */ (0, import_jsx_runtime8.jsx)("path", { d: "M15 9.34V5a3 3 0 0 0-5.68-1.33" }),
|
|
1414
|
+
/* @__PURE__ */ (0, import_jsx_runtime8.jsx)("path", { d: "M9 9v3a3 3 0 0 0 5.12 2.12" }),
|
|
1415
|
+
/* @__PURE__ */ (0, import_jsx_runtime8.jsx)("line", { x1: "12", y1: "19", x2: "12", y2: "22" })
|
|
1199
1416
|
] });
|
|
1200
1417
|
var DEFAULT_CHIPS = [];
|
|
1201
1418
|
function extractName(raw) {
|
|
@@ -1245,7 +1462,7 @@ function KikuPickerMenu({
|
|
|
1245
1462
|
onDismiss
|
|
1246
1463
|
}) {
|
|
1247
1464
|
const discussed = sources.filter((s) => s.id && referencedIds.includes(s.id));
|
|
1248
|
-
return /* @__PURE__ */ (0,
|
|
1465
|
+
return /* @__PURE__ */ (0, import_jsx_runtime8.jsxs)(
|
|
1249
1466
|
"div",
|
|
1250
1467
|
{
|
|
1251
1468
|
className: "hsk-kiku-picker",
|
|
@@ -1253,7 +1470,7 @@ function KikuPickerMenu({
|
|
|
1253
1470
|
"aria-label": "@kiku commands",
|
|
1254
1471
|
onMouseDown: (e) => e.preventDefault(),
|
|
1255
1472
|
children: [
|
|
1256
|
-
discussed.map((src, i) => /* @__PURE__ */ (0,
|
|
1473
|
+
discussed.map((src, i) => /* @__PURE__ */ (0, import_jsx_runtime8.jsxs)(
|
|
1257
1474
|
"button",
|
|
1258
1475
|
{
|
|
1259
1476
|
className: "hsk-kiku-picker-item",
|
|
@@ -1263,9 +1480,9 @@ function KikuPickerMenu({
|
|
|
1263
1480
|
onDismiss();
|
|
1264
1481
|
},
|
|
1265
1482
|
children: [
|
|
1266
|
-
/* @__PURE__ */ (0,
|
|
1267
|
-
/* @__PURE__ */ (0,
|
|
1268
|
-
src.price && /* @__PURE__ */ (0,
|
|
1483
|
+
/* @__PURE__ */ (0, import_jsx_runtime8.jsx)("span", { className: "hsk-kiku-picker-icon", children: src.image ? /* @__PURE__ */ (0, import_jsx_runtime8.jsx)("img", { src: src.image, alt: "" }) : /* @__PURE__ */ (0, import_jsx_runtime8.jsx)(BookmarkIcon, {}) }),
|
|
1484
|
+
/* @__PURE__ */ (0, import_jsx_runtime8.jsx)("span", { className: "hsk-kiku-picker-item-name", children: src.name }),
|
|
1485
|
+
src.price && /* @__PURE__ */ (0, import_jsx_runtime8.jsxs)("span", { className: "hsk-kiku-picker-item-price", children: [
|
|
1269
1486
|
src.currency ?? defaultCurrency,
|
|
1270
1487
|
" ",
|
|
1271
1488
|
parseFloat(String(src.price).replace(/[^0-9.]/g, "") || "0").toLocaleString()
|
|
@@ -1274,7 +1491,7 @@ function KikuPickerMenu({
|
|
|
1274
1491
|
},
|
|
1275
1492
|
src.id ?? i
|
|
1276
1493
|
)),
|
|
1277
|
-
discussed.length > 1 && /* @__PURE__ */ (0,
|
|
1494
|
+
discussed.length > 1 && /* @__PURE__ */ (0, import_jsx_runtime8.jsxs)(
|
|
1278
1495
|
"button",
|
|
1279
1496
|
{
|
|
1280
1497
|
className: "hsk-kiku-picker-item",
|
|
@@ -1284,8 +1501,8 @@ function KikuPickerMenu({
|
|
|
1284
1501
|
onDismiss();
|
|
1285
1502
|
},
|
|
1286
1503
|
children: [
|
|
1287
|
-
/* @__PURE__ */ (0,
|
|
1288
|
-
/* @__PURE__ */ (0,
|
|
1504
|
+
/* @__PURE__ */ (0, import_jsx_runtime8.jsx)("span", { className: "hsk-kiku-picker-icon", children: /* @__PURE__ */ (0, import_jsx_runtime8.jsx)(BookmarkIcon, {}) }),
|
|
1505
|
+
/* @__PURE__ */ (0, import_jsx_runtime8.jsxs)("span", { className: "hsk-kiku-picker-item-name", children: [
|
|
1289
1506
|
"Capture all (",
|
|
1290
1507
|
discussed.length,
|
|
1291
1508
|
")"
|
|
@@ -1293,7 +1510,7 @@ function KikuPickerMenu({
|
|
|
1293
1510
|
]
|
|
1294
1511
|
}
|
|
1295
1512
|
),
|
|
1296
|
-
discussed.length === 0 && /* @__PURE__ */ (0,
|
|
1513
|
+
discussed.length === 0 && /* @__PURE__ */ (0, import_jsx_runtime8.jsxs)(
|
|
1297
1514
|
"button",
|
|
1298
1515
|
{
|
|
1299
1516
|
className: "hsk-kiku-picker-item",
|
|
@@ -1303,12 +1520,12 @@ function KikuPickerMenu({
|
|
|
1303
1520
|
onDismiss();
|
|
1304
1521
|
},
|
|
1305
1522
|
children: [
|
|
1306
|
-
/* @__PURE__ */ (0,
|
|
1307
|
-
/* @__PURE__ */ (0,
|
|
1523
|
+
/* @__PURE__ */ (0, import_jsx_runtime8.jsx)("span", { className: "hsk-kiku-picker-icon", children: /* @__PURE__ */ (0, import_jsx_runtime8.jsx)(BookmarkIcon, {}) }),
|
|
1524
|
+
/* @__PURE__ */ (0, import_jsx_runtime8.jsx)("span", { className: "hsk-kiku-picker-item-name", children: "Capture current page" })
|
|
1308
1525
|
]
|
|
1309
1526
|
}
|
|
1310
1527
|
),
|
|
1311
|
-
/* @__PURE__ */ (0,
|
|
1528
|
+
/* @__PURE__ */ (0, import_jsx_runtime8.jsxs)(
|
|
1312
1529
|
"button",
|
|
1313
1530
|
{
|
|
1314
1531
|
className: "hsk-kiku-picker-item",
|
|
@@ -1318,12 +1535,12 @@ function KikuPickerMenu({
|
|
|
1318
1535
|
onDismiss();
|
|
1319
1536
|
},
|
|
1320
1537
|
children: [
|
|
1321
|
-
/* @__PURE__ */ (0,
|
|
1322
|
-
/* @__PURE__ */ (0,
|
|
1538
|
+
/* @__PURE__ */ (0, import_jsx_runtime8.jsx)("span", { className: "hsk-kiku-picker-icon", children: /* @__PURE__ */ (0, import_jsx_runtime8.jsx)(HistoryIcon, {}) }),
|
|
1539
|
+
/* @__PURE__ */ (0, import_jsx_runtime8.jsx)("span", { className: "hsk-kiku-picker-item-name", children: "What have you saved?" })
|
|
1323
1540
|
]
|
|
1324
1541
|
}
|
|
1325
1542
|
),
|
|
1326
|
-
/* @__PURE__ */ (0,
|
|
1543
|
+
/* @__PURE__ */ (0, import_jsx_runtime8.jsxs)(
|
|
1327
1544
|
"button",
|
|
1328
1545
|
{
|
|
1329
1546
|
className: "hsk-kiku-picker-item",
|
|
@@ -1333,8 +1550,8 @@ function KikuPickerMenu({
|
|
|
1333
1550
|
onDismiss();
|
|
1334
1551
|
},
|
|
1335
1552
|
children: [
|
|
1336
|
-
/* @__PURE__ */ (0,
|
|
1337
|
-
/* @__PURE__ */ (0,
|
|
1553
|
+
/* @__PURE__ */ (0, import_jsx_runtime8.jsx)("span", { className: "hsk-kiku-picker-icon", children: /* @__PURE__ */ (0, import_jsx_runtime8.jsx)(TrashIcon, {}) }),
|
|
1554
|
+
/* @__PURE__ */ (0, import_jsx_runtime8.jsx)("span", { className: "hsk-kiku-picker-item-name", children: "Delete this" })
|
|
1338
1555
|
]
|
|
1339
1556
|
}
|
|
1340
1557
|
)
|
|
@@ -1343,22 +1560,22 @@ function KikuPickerMenu({
|
|
|
1343
1560
|
);
|
|
1344
1561
|
}
|
|
1345
1562
|
function AtPickerMenu({ onSelect, onDismiss }) {
|
|
1346
|
-
return /* @__PURE__ */ (0,
|
|
1563
|
+
return /* @__PURE__ */ (0, import_jsx_runtime8.jsx)(
|
|
1347
1564
|
"div",
|
|
1348
1565
|
{
|
|
1349
1566
|
className: "hsk-kiku-picker",
|
|
1350
1567
|
role: "menu",
|
|
1351
1568
|
"aria-label": "Extensions",
|
|
1352
1569
|
onMouseDown: (e) => e.preventDefault(),
|
|
1353
|
-
children: /* @__PURE__ */ (0,
|
|
1570
|
+
children: /* @__PURE__ */ (0, import_jsx_runtime8.jsxs)(
|
|
1354
1571
|
"button",
|
|
1355
1572
|
{
|
|
1356
1573
|
className: "hsk-kiku-picker-item",
|
|
1357
1574
|
role: "menuitem",
|
|
1358
1575
|
onClick: () => onSelect("@kiku"),
|
|
1359
1576
|
children: [
|
|
1360
|
-
/* @__PURE__ */ (0,
|
|
1361
|
-
/* @__PURE__ */ (0,
|
|
1577
|
+
/* @__PURE__ */ (0, import_jsx_runtime8.jsx)("span", { className: "hsk-kiku-picker-icon hsk-kiku-picker-icon--accent", children: /* @__PURE__ */ (0, import_jsx_runtime8.jsx)(SparkleIcon2, {}) }),
|
|
1578
|
+
/* @__PURE__ */ (0, import_jsx_runtime8.jsx)("span", { className: "hsk-kiku-picker-item-name", children: "kiku \u2014 capture & remember" })
|
|
1362
1579
|
]
|
|
1363
1580
|
}
|
|
1364
1581
|
)
|
|
@@ -1366,11 +1583,11 @@ function AtPickerMenu({ onSelect, onDismiss }) {
|
|
|
1366
1583
|
);
|
|
1367
1584
|
}
|
|
1368
1585
|
function SourceImg({ src, alt, onImageClick }) {
|
|
1369
|
-
const [failed, setFailed] = (0,
|
|
1586
|
+
const [failed, setFailed] = (0, import_react6.useState)(false);
|
|
1370
1587
|
if (failed) {
|
|
1371
|
-
return /* @__PURE__ */ (0,
|
|
1588
|
+
return /* @__PURE__ */ (0, import_jsx_runtime8.jsx)("div", { style: { width: "100%", height: "100%", display: "flex", alignItems: "center", justifyContent: "center", background: "var(--hsk-chat-source-bg, rgba(0,0,0,.04))", color: "var(--hsk-chat-muted, #888)" }, children: /* @__PURE__ */ (0, import_jsx_runtime8.jsx)(SparkleIcon2, {}) });
|
|
1372
1589
|
}
|
|
1373
|
-
return /* @__PURE__ */ (0,
|
|
1590
|
+
return /* @__PURE__ */ (0, import_jsx_runtime8.jsx)(
|
|
1374
1591
|
"img",
|
|
1375
1592
|
{
|
|
1376
1593
|
src,
|
|
@@ -1386,15 +1603,15 @@ function SourceImg({ src, alt, onImageClick }) {
|
|
|
1386
1603
|
function SourcesCarousel({ sources, defaultCurrency, onSelectSource, onImageClick, referencedIds = [], compact = false }) {
|
|
1387
1604
|
const client = (0, import_sdk6.useAkropolysContext)();
|
|
1388
1605
|
const isProperty = client?.vertical === "property";
|
|
1389
|
-
const railRef = (0,
|
|
1390
|
-
const [showNext, setShowNext] = (0,
|
|
1391
|
-
const measure = (0,
|
|
1606
|
+
const railRef = (0, import_react6.useRef)(null);
|
|
1607
|
+
const [showNext, setShowNext] = (0, import_react6.useState)(false);
|
|
1608
|
+
const measure = (0, import_react6.useCallback)(() => {
|
|
1392
1609
|
const el = railRef.current;
|
|
1393
1610
|
if (!el) return;
|
|
1394
1611
|
const atEnd = el.scrollLeft + el.clientWidth >= el.scrollWidth - 8;
|
|
1395
1612
|
setShowNext(el.scrollWidth > el.clientWidth + 4 && !atEnd);
|
|
1396
1613
|
}, []);
|
|
1397
|
-
(0,
|
|
1614
|
+
(0, import_react6.useEffect)(() => {
|
|
1398
1615
|
measure();
|
|
1399
1616
|
const el = railRef.current;
|
|
1400
1617
|
if (!el) return;
|
|
@@ -1411,20 +1628,20 @@ function SourcesCarousel({ sources, defaultCurrency, onSelectSource, onImageClic
|
|
|
1411
1628
|
};
|
|
1412
1629
|
const display = sources.filter((s) => s.id && referencedIds.includes(s.id));
|
|
1413
1630
|
if (display.length === 0) return null;
|
|
1414
|
-
return /* @__PURE__ */ (0,
|
|
1415
|
-
/* @__PURE__ */ (0,
|
|
1631
|
+
return /* @__PURE__ */ (0, import_jsx_runtime8.jsxs)("div", { className: cn("hsk-cb-sources-wrap", compact && "hsk-cb-sources-wrap--compact"), children: [
|
|
1632
|
+
/* @__PURE__ */ (0, import_jsx_runtime8.jsx)("div", { className: "hsk-cb-sources", ref: railRef, children: display.map((src, si) => {
|
|
1416
1633
|
const isReferenced = !!(src.id && referencedIds.includes(src.id));
|
|
1417
|
-
return /* @__PURE__ */ (0,
|
|
1634
|
+
return /* @__PURE__ */ (0, import_jsx_runtime8.jsxs)(
|
|
1418
1635
|
"div",
|
|
1419
1636
|
{
|
|
1420
1637
|
className: cn("hsk-cb-source", isReferenced && "hsk-cb-source--referenced"),
|
|
1421
1638
|
style: { animationDelay: `${si * 50}ms` },
|
|
1422
1639
|
onClick: () => onSelectSource?.(src),
|
|
1423
1640
|
children: [
|
|
1424
|
-
src.image ? /* @__PURE__ */ (0,
|
|
1425
|
-
/* @__PURE__ */ (0,
|
|
1426
|
-
isReferenced && /* @__PURE__ */ (0,
|
|
1427
|
-
isProperty && /* @__PURE__ */ (0,
|
|
1641
|
+
src.image ? /* @__PURE__ */ (0, import_jsx_runtime8.jsxs)("div", { className: "hsk-cb-src-imgwrap", style: { position: "relative" }, children: [
|
|
1642
|
+
/* @__PURE__ */ (0, import_jsx_runtime8.jsx)(SourceImg, { src: src.image, alt: src.name, onImageClick }),
|
|
1643
|
+
isReferenced && /* @__PURE__ */ (0, import_jsx_runtime8.jsx)("div", { className: "hsk-cb-source-ref-badge", title: "Featured in response", children: /* @__PURE__ */ (0, import_jsx_runtime8.jsx)(SparkleIcon2, { size: 10 }) }),
|
|
1644
|
+
isProperty && /* @__PURE__ */ (0, import_jsx_runtime8.jsx)("div", { style: {
|
|
1428
1645
|
position: "absolute",
|
|
1429
1646
|
top: "6px",
|
|
1430
1647
|
right: "6px",
|
|
@@ -1439,14 +1656,14 @@ function SourcesCarousel({ sources, defaultCurrency, onSelectSource, onImageClic
|
|
|
1439
1656
|
color: "#fbbf24",
|
|
1440
1657
|
// Gold sparkle badge
|
|
1441
1658
|
boxShadow: "0 2px 4px rgba(0,0,0,0.2)"
|
|
1442
|
-
}, children: /* @__PURE__ */ (0,
|
|
1443
|
-
] }) : /* @__PURE__ */ (0,
|
|
1444
|
-
/* @__PURE__ */ (0,
|
|
1445
|
-
isReferenced && /* @__PURE__ */ (0,
|
|
1659
|
+
}, children: /* @__PURE__ */ (0, import_jsx_runtime8.jsx)(SparkleIcon2, { size: 12 }) })
|
|
1660
|
+
] }) : /* @__PURE__ */ (0, import_jsx_runtime8.jsxs)("div", { className: "hsk-cb-src-imgwrap-empty", style: { position: "relative" }, children: [
|
|
1661
|
+
/* @__PURE__ */ (0, import_jsx_runtime8.jsx)(SparkleIcon2, {}),
|
|
1662
|
+
isReferenced && /* @__PURE__ */ (0, import_jsx_runtime8.jsx)("div", { className: "hsk-cb-source-ref-badge", title: "Featured in response", children: /* @__PURE__ */ (0, import_jsx_runtime8.jsx)(SparkleIcon2, { size: 10 }) })
|
|
1446
1663
|
] }),
|
|
1447
|
-
/* @__PURE__ */ (0,
|
|
1448
|
-
/* @__PURE__ */ (0,
|
|
1449
|
-
src.price && /* @__PURE__ */ (0,
|
|
1664
|
+
/* @__PURE__ */ (0, import_jsx_runtime8.jsxs)("div", { className: "hsk-cb-src-info", children: [
|
|
1665
|
+
/* @__PURE__ */ (0, import_jsx_runtime8.jsx)("div", { className: "hsk-cb-src-name", children: src.name }),
|
|
1666
|
+
src.price && /* @__PURE__ */ (0, import_jsx_runtime8.jsxs)("div", { className: "hsk-cb-src-price", children: [
|
|
1450
1667
|
src.currency ?? defaultCurrency,
|
|
1451
1668
|
" ",
|
|
1452
1669
|
parseFloat(String(src.price).replace(/[^0-9.]/g, "") || "0").toLocaleString()
|
|
@@ -1457,15 +1674,15 @@ function SourcesCarousel({ sources, defaultCurrency, onSelectSource, onImageClic
|
|
|
1457
1674
|
src.id ?? si
|
|
1458
1675
|
);
|
|
1459
1676
|
}) }),
|
|
1460
|
-
showNext && /* @__PURE__ */ (0,
|
|
1461
|
-
/* @__PURE__ */ (0,
|
|
1677
|
+
showNext && /* @__PURE__ */ (0, import_jsx_runtime8.jsxs)(import_jsx_runtime8.Fragment, { children: [
|
|
1678
|
+
/* @__PURE__ */ (0, import_jsx_runtime8.jsx)(
|
|
1462
1679
|
"div",
|
|
1463
1680
|
{
|
|
1464
1681
|
className: "hsk-cb-sources-fade",
|
|
1465
1682
|
style: { background: "linear-gradient(to right, transparent, var(--hsk-fade-bg, #0e0e0f))" }
|
|
1466
1683
|
}
|
|
1467
1684
|
),
|
|
1468
|
-
/* @__PURE__ */ (0,
|
|
1685
|
+
/* @__PURE__ */ (0, import_jsx_runtime8.jsx)("button", { className: "hsk-cb-sources-next", onClick: scrollNext, "aria-label": "See more", children: /* @__PURE__ */ (0, import_jsx_runtime8.jsx)(ChevronRightIcon, {}) })
|
|
1469
1686
|
] })
|
|
1470
1687
|
] });
|
|
1471
1688
|
}
|
|
@@ -1542,14 +1759,14 @@ function SmartContextPills({
|
|
|
1542
1759
|
pills.push({ emoji: "\u{1F4A1}", label: "Recommend something", query: "What do you recommend for me?" });
|
|
1543
1760
|
}
|
|
1544
1761
|
if (pills.length === 0) return null;
|
|
1545
|
-
return /* @__PURE__ */ (0,
|
|
1762
|
+
return /* @__PURE__ */ (0, import_jsx_runtime8.jsx)("div", { className: "hsk-action-pills", children: pills.map((pill) => /* @__PURE__ */ (0, import_jsx_runtime8.jsxs)(
|
|
1546
1763
|
"button",
|
|
1547
1764
|
{
|
|
1548
1765
|
className: "hsk-action-pill",
|
|
1549
1766
|
onClick: () => onSend(pill.query),
|
|
1550
1767
|
disabled: loading,
|
|
1551
1768
|
children: [
|
|
1552
|
-
/* @__PURE__ */ (0,
|
|
1769
|
+
/* @__PURE__ */ (0, import_jsx_runtime8.jsx)("span", { className: "hsk-pill-emoji", children: pill.emoji }),
|
|
1553
1770
|
pill.label
|
|
1554
1771
|
]
|
|
1555
1772
|
},
|
|
@@ -1610,10 +1827,10 @@ function parseThinking(text) {
|
|
|
1610
1827
|
};
|
|
1611
1828
|
}
|
|
1612
1829
|
function ThinkingBlock({ text, isComplete, seconds: fixedSeconds }) {
|
|
1613
|
-
const startRef = (0,
|
|
1614
|
-
const [seconds, setSeconds] = (0,
|
|
1615
|
-
const [isOpen, setIsOpen] = (0,
|
|
1616
|
-
(0,
|
|
1830
|
+
const startRef = (0, import_react6.useRef)(Date.now());
|
|
1831
|
+
const [seconds, setSeconds] = (0, import_react6.useState)(() => isComplete ? null : 0);
|
|
1832
|
+
const [isOpen, setIsOpen] = (0, import_react6.useState)(!isComplete);
|
|
1833
|
+
(0, import_react6.useEffect)(() => {
|
|
1617
1834
|
if (isComplete) {
|
|
1618
1835
|
if (seconds !== null) {
|
|
1619
1836
|
setSeconds(Math.max(1, Math.round((Date.now() - startRef.current) / 1e3)));
|
|
@@ -1630,8 +1847,8 @@ function ThinkingBlock({ text, isComplete, seconds: fixedSeconds }) {
|
|
|
1630
1847
|
const finalSeconds = fixedSeconds ?? seconds;
|
|
1631
1848
|
const label = isComplete ? finalSeconds !== null && finalSeconds !== void 0 ? `Thought for ${finalSeconds}s` : "Thought process" : `Thinking${seconds ? ` \xB7 ${seconds}s` : "\u2026"}`;
|
|
1632
1849
|
const expandable = !!text;
|
|
1633
|
-
return /* @__PURE__ */ (0,
|
|
1634
|
-
/* @__PURE__ */ (0,
|
|
1850
|
+
return /* @__PURE__ */ (0, import_jsx_runtime8.jsxs)("div", { className: cn("hsk-cb-think", !isComplete && "hsk-cb-think--live"), children: [
|
|
1851
|
+
/* @__PURE__ */ (0, import_jsx_runtime8.jsxs)(
|
|
1635
1852
|
"button",
|
|
1636
1853
|
{
|
|
1637
1854
|
type: "button",
|
|
@@ -1639,16 +1856,20 @@ function ThinkingBlock({ text, isComplete, seconds: fixedSeconds }) {
|
|
|
1639
1856
|
onClick: expandable ? () => setIsOpen((o) => !o) : void 0,
|
|
1640
1857
|
"aria-expanded": expandable ? isOpen : void 0,
|
|
1641
1858
|
children: [
|
|
1642
|
-
/* @__PURE__ */ (0,
|
|
1643
|
-
/* @__PURE__ */ (0,
|
|
1644
|
-
/* @__PURE__ */ (0,
|
|
1859
|
+
isComplete ? /* @__PURE__ */ (0, import_jsx_runtime8.jsxs)("svg", { width: "13", height: "13", viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "2", strokeLinecap: "round", strokeLinejoin: "round", children: [
|
|
1860
|
+
/* @__PURE__ */ (0, import_jsx_runtime8.jsx)("circle", { cx: "12", cy: "12", r: "10" }),
|
|
1861
|
+
/* @__PURE__ */ (0, import_jsx_runtime8.jsx)("path", { d: "M12 6v6l4 2" })
|
|
1862
|
+
] }) : /* @__PURE__ */ (0, import_jsx_runtime8.jsxs)("span", { className: "hsk-cb-typing", "aria-hidden": "true", children: [
|
|
1863
|
+
/* @__PURE__ */ (0, import_jsx_runtime8.jsx)("span", {}),
|
|
1864
|
+
/* @__PURE__ */ (0, import_jsx_runtime8.jsx)("span", {}),
|
|
1865
|
+
/* @__PURE__ */ (0, import_jsx_runtime8.jsx)("span", {})
|
|
1645
1866
|
] }),
|
|
1646
|
-
/* @__PURE__ */ (0,
|
|
1647
|
-
expandable && /* @__PURE__ */ (0,
|
|
1867
|
+
/* @__PURE__ */ (0, import_jsx_runtime8.jsx)("span", { children: label }),
|
|
1868
|
+
expandable && /* @__PURE__ */ (0, import_jsx_runtime8.jsx)("span", { className: cn("hsk-cb-think-chevron", isOpen && "hsk-cb-think-chevron--open"), children: "\u25B6" })
|
|
1648
1869
|
]
|
|
1649
1870
|
}
|
|
1650
1871
|
),
|
|
1651
|
-
expandable && isOpen && /* @__PURE__ */ (0,
|
|
1872
|
+
expandable && isOpen && /* @__PURE__ */ (0, import_jsx_runtime8.jsx)("div", { className: "hsk-cb-think-body", children: text })
|
|
1652
1873
|
] });
|
|
1653
1874
|
}
|
|
1654
1875
|
function ChatModal({
|
|
@@ -1669,18 +1890,18 @@ function ChatModal({
|
|
|
1669
1890
|
}) {
|
|
1670
1891
|
const client = (0, import_sdk6.useAkropolysContext)();
|
|
1671
1892
|
const { messages, sources, loading, streaming, error, lastAction, lastIntent, send, stop, stopped, interrupted, continueGenerating, reset, referencedIds } = (0, import_sdk5.useKiku)();
|
|
1672
|
-
const [input, setInput] = (0,
|
|
1673
|
-
const [shopperName, setShopperNameState] = (0,
|
|
1893
|
+
const [input, setInput] = (0, import_react6.useState)("");
|
|
1894
|
+
const [shopperName, setShopperNameState] = (0, import_react6.useState)(() => {
|
|
1674
1895
|
try {
|
|
1675
1896
|
return client.getShopperName?.() ?? "";
|
|
1676
1897
|
} catch {
|
|
1677
1898
|
return "";
|
|
1678
1899
|
}
|
|
1679
1900
|
});
|
|
1680
|
-
const [nameSkipped, setNameSkipped] = (0,
|
|
1901
|
+
const [nameSkipped, setNameSkipped] = (0, import_react6.useState)(false);
|
|
1681
1902
|
const awaitingName = messages.length === 0 && !shopperName && !nameSkipped;
|
|
1682
|
-
const [attachments, setAttachments] = (0,
|
|
1683
|
-
const imageInputRef = (0,
|
|
1903
|
+
const [attachments, setAttachments] = (0, import_react6.useState)([]);
|
|
1904
|
+
const imageInputRef = (0, import_react6.useRef)(null);
|
|
1684
1905
|
const handleImageFiles = (files) => {
|
|
1685
1906
|
if (!files || files.length === 0) return;
|
|
1686
1907
|
Array.from(files).forEach((file) => {
|
|
@@ -1698,11 +1919,11 @@ function ChatModal({
|
|
|
1698
1919
|
const removeAttachment = (idx) => {
|
|
1699
1920
|
setAttachments((prev) => prev.filter((_, i) => i !== idx));
|
|
1700
1921
|
};
|
|
1701
|
-
const [voiceState, setVoiceState] = (0,
|
|
1702
|
-
const recognitionRef = (0,
|
|
1703
|
-
const pendingVoiceRef = (0,
|
|
1922
|
+
const [voiceState, setVoiceState] = (0, import_react6.useState)("idle");
|
|
1923
|
+
const recognitionRef = (0, import_react6.useRef)(null);
|
|
1924
|
+
const pendingVoiceRef = (0, import_react6.useRef)(null);
|
|
1704
1925
|
const hasSpeechAPI = typeof window !== "undefined" && ("SpeechRecognition" in window || "webkitSpeechRecognition" in window);
|
|
1705
|
-
const startVoice = (0,
|
|
1926
|
+
const startVoice = (0, import_react6.useCallback)(() => {
|
|
1706
1927
|
if (!hasSpeechAPI || voiceState !== "idle") return;
|
|
1707
1928
|
const SR = window.SpeechRecognition || window.webkitSpeechRecognition;
|
|
1708
1929
|
const recognition = new SR();
|
|
@@ -1740,25 +1961,26 @@ function ChatModal({
|
|
|
1740
1961
|
};
|
|
1741
1962
|
recognition.start();
|
|
1742
1963
|
}, [hasSpeechAPI, voiceState, voiceLang]);
|
|
1743
|
-
const stopVoice = (0,
|
|
1964
|
+
const stopVoice = (0, import_react6.useCallback)(() => {
|
|
1744
1965
|
recognitionRef.current?.stop();
|
|
1745
1966
|
setVoiceState("idle");
|
|
1746
1967
|
}, []);
|
|
1747
|
-
(0,
|
|
1968
|
+
(0, import_react6.useEffect)(() => {
|
|
1748
1969
|
return () => recognitionRef.current?.abort();
|
|
1749
1970
|
}, []);
|
|
1750
1971
|
const activeChips = chips;
|
|
1751
1972
|
const activeTitle = title;
|
|
1752
1973
|
const activePlaceholder = awaitingName ? "Type your name\u2026" : placeholder;
|
|
1753
|
-
const [selectedProduct, setSelectedProduct] = (0,
|
|
1754
|
-
const [lightboxSrc, setLightboxSrc] = (0,
|
|
1755
|
-
const
|
|
1756
|
-
const
|
|
1757
|
-
const
|
|
1758
|
-
const [
|
|
1759
|
-
const [
|
|
1760
|
-
const [
|
|
1761
|
-
const [
|
|
1974
|
+
const [selectedProduct, setSelectedProduct] = (0, import_react6.useState)(null);
|
|
1975
|
+
const [lightboxSrc, setLightboxSrc] = (0, import_react6.useState)(null);
|
|
1976
|
+
const [markupSrc, setMarkupSrc] = (0, import_react6.useState)(null);
|
|
1977
|
+
const bottomRef = (0, import_react6.useRef)(null);
|
|
1978
|
+
const textareaRef = (0, import_react6.useRef)(null);
|
|
1979
|
+
const [keyInput, setKeyInput] = (0, import_react6.useState)("");
|
|
1980
|
+
const [keyPhase, setKeyPhase] = (0, import_react6.useState)("idle");
|
|
1981
|
+
const [mintedKey, setMintedKey] = (0, import_react6.useState)(null);
|
|
1982
|
+
const [mintedPub, setMintedPub] = (0, import_react6.useState)(null);
|
|
1983
|
+
const [copied, setCopied] = (0, import_react6.useState)(null);
|
|
1762
1984
|
const copyValue = (value, which) => {
|
|
1763
1985
|
try {
|
|
1764
1986
|
navigator.clipboard?.writeText(value);
|
|
@@ -1767,17 +1989,17 @@ function ChatModal({
|
|
|
1767
1989
|
setCopied(which);
|
|
1768
1990
|
setTimeout(() => setCopied((c) => c === which ? null : c), 1600);
|
|
1769
1991
|
};
|
|
1770
|
-
const [keyCountdown, setKeyCountdown] = (0,
|
|
1771
|
-
const [minting, setMinting] = (0,
|
|
1772
|
-
const [showKikuPicker, setShowKikuPicker] = (0,
|
|
1773
|
-
const [showAtPicker, setShowAtPicker] = (0,
|
|
1774
|
-
(0,
|
|
1992
|
+
const [keyCountdown, setKeyCountdown] = (0, import_react6.useState)(KIKU_KEY_REVEAL_SECONDS);
|
|
1993
|
+
const [minting, setMinting] = (0, import_react6.useState)(false);
|
|
1994
|
+
const [showKikuPicker, setShowKikuPicker] = (0, import_react6.useState)(false);
|
|
1995
|
+
const [showAtPicker, setShowAtPicker] = (0, import_react6.useState)(false);
|
|
1996
|
+
(0, import_react6.useEffect)(() => {
|
|
1775
1997
|
if (!lastAction) return;
|
|
1776
1998
|
if (lastAction.type === "request_kiku_key") {
|
|
1777
1999
|
setKeyPhase("prompt_key");
|
|
1778
2000
|
}
|
|
1779
2001
|
}, [lastAction]);
|
|
1780
|
-
(0,
|
|
2002
|
+
(0, import_react6.useEffect)(() => {
|
|
1781
2003
|
if (!mintedKey) return;
|
|
1782
2004
|
setKeyCountdown(KIKU_KEY_REVEAL_SECONDS);
|
|
1783
2005
|
const t = setInterval(() => {
|
|
@@ -1828,9 +2050,9 @@ function ChatModal({
|
|
|
1828
2050
|
setMinting(false);
|
|
1829
2051
|
}
|
|
1830
2052
|
};
|
|
1831
|
-
const msgsContainerRef = (0,
|
|
1832
|
-
const messageRefs = (0,
|
|
1833
|
-
(0,
|
|
2053
|
+
const msgsContainerRef = (0, import_react6.useRef)(null);
|
|
2054
|
+
const messageRefs = (0, import_react6.useRef)([]);
|
|
2055
|
+
(0, import_react6.useEffect)(() => {
|
|
1834
2056
|
const container = msgsContainerRef.current;
|
|
1835
2057
|
if (!container) return;
|
|
1836
2058
|
const lastMsg = messages[messages.length - 1];
|
|
@@ -1843,14 +2065,14 @@ function ChatModal({
|
|
|
1843
2065
|
bottomRef.current?.scrollIntoView({ behavior: "smooth" });
|
|
1844
2066
|
}
|
|
1845
2067
|
}, [messages, loading, selectedProduct]);
|
|
1846
|
-
(0,
|
|
2068
|
+
(0, import_react6.useEffect)(() => {
|
|
1847
2069
|
const prev = document.body.style.overflow;
|
|
1848
2070
|
document.body.style.overflow = "hidden";
|
|
1849
2071
|
return () => {
|
|
1850
2072
|
document.body.style.overflow = prev;
|
|
1851
2073
|
};
|
|
1852
2074
|
}, []);
|
|
1853
|
-
(0,
|
|
2075
|
+
(0, import_react6.useEffect)(() => {
|
|
1854
2076
|
const h = (e) => {
|
|
1855
2077
|
if (e.key !== "Escape") return;
|
|
1856
2078
|
if (lightboxSrc) {
|
|
@@ -1862,7 +2084,7 @@ function ChatModal({
|
|
|
1862
2084
|
document.addEventListener("keydown", h);
|
|
1863
2085
|
return () => document.removeEventListener("keydown", h);
|
|
1864
2086
|
}, [lightboxSrc, onClose]);
|
|
1865
|
-
const handleReset = (0,
|
|
2087
|
+
const handleReset = (0, import_react6.useCallback)(() => {
|
|
1866
2088
|
reset();
|
|
1867
2089
|
setKeyPhase("idle");
|
|
1868
2090
|
}, [reset]);
|
|
@@ -1916,7 +2138,7 @@ function ChatModal({
|
|
|
1916
2138
|
textareaRef.current.focus();
|
|
1917
2139
|
}
|
|
1918
2140
|
};
|
|
1919
|
-
const handleKikuCapture = (0,
|
|
2141
|
+
const handleKikuCapture = (0, import_react6.useCallback)((product) => {
|
|
1920
2142
|
const name = product.name || "";
|
|
1921
2143
|
const display = `@kiku capture${name ? " " + name : ""}`;
|
|
1922
2144
|
const q = name || "capture current page";
|
|
@@ -1926,7 +2148,7 @@ function ChatModal({
|
|
|
1926
2148
|
setAttachments([]);
|
|
1927
2149
|
send(q, display, toSend.length > 0 ? toSend : void 0, "capture");
|
|
1928
2150
|
}, [attachments, send]);
|
|
1929
|
-
const handleKikuCaptureAll = (0,
|
|
2151
|
+
const handleKikuCaptureAll = (0, import_react6.useCallback)((products) => {
|
|
1930
2152
|
const targets = products.filter((p) => p.id).map((p) => ({
|
|
1931
2153
|
name: p.name || "",
|
|
1932
2154
|
url: p.url || "",
|
|
@@ -1941,14 +2163,14 @@ function ChatModal({
|
|
|
1941
2163
|
setAttachments([]);
|
|
1942
2164
|
send(names || "capture all", display, void 0, "capture_all", targets);
|
|
1943
2165
|
}, [defaultCurrency, send]);
|
|
1944
|
-
const handleKikuViewHistory = (0,
|
|
2166
|
+
const handleKikuViewHistory = (0, import_react6.useCallback)(() => {
|
|
1945
2167
|
const display = "@kiku what have you saved?";
|
|
1946
2168
|
setInput("");
|
|
1947
2169
|
setSelectedProduct(null);
|
|
1948
2170
|
setAttachments([]);
|
|
1949
2171
|
send("show my saved items", display, void 0, "view_history");
|
|
1950
2172
|
}, [send]);
|
|
1951
|
-
const handleKikuDelete = (0,
|
|
2173
|
+
const handleKikuDelete = (0, import_react6.useCallback)(() => {
|
|
1952
2174
|
const display = "@kiku delete this";
|
|
1953
2175
|
setInput("");
|
|
1954
2176
|
setSelectedProduct(null);
|
|
@@ -1981,7 +2203,7 @@ function ChatModal({
|
|
|
1981
2203
|
t.style.height = "auto";
|
|
1982
2204
|
t.style.height = `${Math.min(t.scrollHeight, 140)}px`;
|
|
1983
2205
|
};
|
|
1984
|
-
(0,
|
|
2206
|
+
(0, import_react6.useEffect)(() => {
|
|
1985
2207
|
if (voiceState !== "processing") return;
|
|
1986
2208
|
const transcript = pendingVoiceRef.current;
|
|
1987
2209
|
if (!transcript) {
|
|
@@ -1997,7 +2219,7 @@ function ChatModal({
|
|
|
1997
2219
|
}, [voiceState]);
|
|
1998
2220
|
const blurVal = typeof backdropBlur === "number" ? `${backdropBlur}px` : backdropBlur ?? "20px";
|
|
1999
2221
|
const displayMessages = messages;
|
|
2000
|
-
return /* @__PURE__ */ (0,
|
|
2222
|
+
return /* @__PURE__ */ (0, import_jsx_runtime8.jsx)(
|
|
2001
2223
|
"div",
|
|
2002
2224
|
{
|
|
2003
2225
|
className: cn("hsk-cb-overlay", classNames.overlay),
|
|
@@ -2009,7 +2231,7 @@ function ChatModal({
|
|
|
2009
2231
|
...backdropColor ? { background: backdropColor } : {},
|
|
2010
2232
|
...customStyles
|
|
2011
2233
|
},
|
|
2012
|
-
children: /* @__PURE__ */ (0,
|
|
2234
|
+
children: /* @__PURE__ */ (0, import_jsx_runtime8.jsxs)(
|
|
2013
2235
|
"div",
|
|
2014
2236
|
{
|
|
2015
2237
|
className: cn("hsk-cb-panel", classNames.panel),
|
|
@@ -2022,48 +2244,62 @@ function ChatModal({
|
|
|
2022
2244
|
}
|
|
2023
2245
|
},
|
|
2024
2246
|
children: [
|
|
2025
|
-
lightboxSrc && /* @__PURE__ */ (0,
|
|
2026
|
-
/* @__PURE__ */ (0,
|
|
2027
|
-
/* @__PURE__ */ (0,
|
|
2247
|
+
lightboxSrc && /* @__PURE__ */ (0, import_jsx_runtime8.jsxs)("div", { className: "hsk-lightbox", onClick: () => setLightboxSrc(null), children: [
|
|
2248
|
+
/* @__PURE__ */ (0, import_jsx_runtime8.jsx)("button", { className: "hsk-lightbox-close", onClick: () => setLightboxSrc(null), "aria-label": "Close image", children: /* @__PURE__ */ (0, import_jsx_runtime8.jsx)(CloseIcon, {}) }),
|
|
2249
|
+
/* @__PURE__ */ (0, import_jsx_runtime8.jsx)("img", { src: lightboxSrc, alt: "", className: "hsk-lightbox-img", onClick: (e) => e.stopPropagation() })
|
|
2028
2250
|
] }),
|
|
2029
|
-
/* @__PURE__ */ (0,
|
|
2030
|
-
|
|
2031
|
-
|
|
2032
|
-
|
|
2033
|
-
|
|
2251
|
+
markupSrc && /* @__PURE__ */ (0, import_jsx_runtime8.jsx)("div", { className: "hsk-markup-overlay", children: /* @__PURE__ */ (0, import_jsx_runtime8.jsx)(
|
|
2252
|
+
MarkupEditor,
|
|
2253
|
+
{
|
|
2254
|
+
src: markupSrc,
|
|
2255
|
+
onCancel: () => setMarkupSrc(null),
|
|
2256
|
+
onSend: (dataUrl, instruction) => {
|
|
2257
|
+
setMarkupSrc(null);
|
|
2258
|
+
handleSend(
|
|
2259
|
+
instruction || "Apply the change indicated by the markings on the image.",
|
|
2260
|
+
[{ type: "image", data: dataUrl, annotated: true }]
|
|
2261
|
+
);
|
|
2262
|
+
}
|
|
2263
|
+
}
|
|
2264
|
+
) }),
|
|
2265
|
+
/* @__PURE__ */ (0, import_jsx_runtime8.jsxs)("div", { className: "hsk-cb-main", children: [
|
|
2266
|
+
/* @__PURE__ */ (0, import_jsx_runtime8.jsxs)("div", { className: "hsk-cb-topbar", children: [
|
|
2267
|
+
/* @__PURE__ */ (0, import_jsx_runtime8.jsxs)("div", { className: "hsk-cb-topbar-left", children: [
|
|
2268
|
+
/* @__PURE__ */ (0, import_jsx_runtime8.jsx)("span", { className: "hsk-cb-topbar-icon", style: { display: "flex", alignItems: "center" }, children: /* @__PURE__ */ (0, import_jsx_runtime8.jsx)(SparkleIcon2, {}) }),
|
|
2269
|
+
/* @__PURE__ */ (0, import_jsx_runtime8.jsx)("div", { children: /* @__PURE__ */ (0, import_jsx_runtime8.jsx)("div", { className: "hsk-cb-topbar-title", children: activeTitle }) })
|
|
2034
2270
|
] }),
|
|
2035
|
-
/* @__PURE__ */ (0,
|
|
2036
|
-
messages.length > 0 && /* @__PURE__ */ (0,
|
|
2037
|
-
/* @__PURE__ */ (0,
|
|
2271
|
+
/* @__PURE__ */ (0, import_jsx_runtime8.jsxs)("div", { className: "hsk-cb-topbar-actions", children: [
|
|
2272
|
+
messages.length > 0 && /* @__PURE__ */ (0, import_jsx_runtime8.jsx)("button", { className: "hsk-cb-topbar-btn", onClick: handleReset, children: "Clear chat" }),
|
|
2273
|
+
/* @__PURE__ */ (0, import_jsx_runtime8.jsx)("button", { className: "hsk-cb-close", onClick: onClose, "aria-label": "Close", children: /* @__PURE__ */ (0, import_jsx_runtime8.jsx)(CloseIcon, {}) })
|
|
2038
2274
|
] })
|
|
2039
2275
|
] }),
|
|
2040
|
-
/* @__PURE__ */ (0,
|
|
2041
|
-
displayMessages.length === 0 ? /* @__PURE__ */ (0,
|
|
2042
|
-
awaitingName ? /* @__PURE__ */ (0,
|
|
2043
|
-
/* @__PURE__ */ (0,
|
|
2276
|
+
/* @__PURE__ */ (0, import_jsx_runtime8.jsxs)("div", { className: "hsk-cb-msgs", ref: msgsContainerRef, children: [
|
|
2277
|
+
displayMessages.length === 0 ? /* @__PURE__ */ (0, import_jsx_runtime8.jsxs)("div", { className: "hsk-cb-empty", children: [
|
|
2278
|
+
awaitingName ? /* @__PURE__ */ (0, import_jsx_runtime8.jsxs)(import_jsx_runtime8.Fragment, { children: [
|
|
2279
|
+
/* @__PURE__ */ (0, import_jsx_runtime8.jsxs)("h2", { className: "hsk-cb-hello", children: [
|
|
2044
2280
|
"Hi, I'm ",
|
|
2045
|
-
/* @__PURE__ */ (0,
|
|
2281
|
+
/* @__PURE__ */ (0, import_jsx_runtime8.jsx)("b", { children: "kiku" }),
|
|
2046
2282
|
"."
|
|
2047
2283
|
] }),
|
|
2048
|
-
/* @__PURE__ */ (0,
|
|
2049
|
-
/* @__PURE__ */ (0,
|
|
2050
|
-
/* @__PURE__ */ (0,
|
|
2051
|
-
] }) : shopperName ? /* @__PURE__ */ (0,
|
|
2052
|
-
/* @__PURE__ */ (0,
|
|
2284
|
+
/* @__PURE__ */ (0, import_jsx_runtime8.jsx)("p", { className: "hsk-cb-hello-lead", children: "I can search, visualize, or capture anything for you \u2014 on this site or any other." }),
|
|
2285
|
+
/* @__PURE__ */ (0, import_jsx_runtime8.jsx)("p", { className: "hsk-cb-hello-ask", children: "What should I call you?" }),
|
|
2286
|
+
/* @__PURE__ */ (0, import_jsx_runtime8.jsx)("button", { className: "hsk-cb-hello-skip", onClick: () => setNameSkipped(true), children: "Skip for now" })
|
|
2287
|
+
] }) : shopperName ? /* @__PURE__ */ (0, import_jsx_runtime8.jsxs)(import_jsx_runtime8.Fragment, { children: [
|
|
2288
|
+
/* @__PURE__ */ (0, import_jsx_runtime8.jsxs)("h2", { className: "hsk-cb-hello", children: [
|
|
2053
2289
|
"Hi, ",
|
|
2054
2290
|
shopperName,
|
|
2055
2291
|
"."
|
|
2056
2292
|
] }),
|
|
2057
|
-
/* @__PURE__ */ (0,
|
|
2058
|
-
] }) : /* @__PURE__ */ (0,
|
|
2059
|
-
/* @__PURE__ */ (0,
|
|
2293
|
+
/* @__PURE__ */ (0, import_jsx_runtime8.jsx)("p", { className: "hsk-cb-hello-lead", children: "What can I find for you today?" })
|
|
2294
|
+
] }) : /* @__PURE__ */ (0, import_jsx_runtime8.jsxs)(import_jsx_runtime8.Fragment, { children: [
|
|
2295
|
+
/* @__PURE__ */ (0, import_jsx_runtime8.jsxs)("h2", { className: "hsk-cb-hello", children: [
|
|
2060
2296
|
"Hi, I'm ",
|
|
2061
|
-
/* @__PURE__ */ (0,
|
|
2297
|
+
/* @__PURE__ */ (0, import_jsx_runtime8.jsx)("b", { children: "kiku" }),
|
|
2062
2298
|
"."
|
|
2063
2299
|
] }),
|
|
2064
|
-
/* @__PURE__ */ (0,
|
|
2300
|
+
/* @__PURE__ */ (0, import_jsx_runtime8.jsx)("p", { className: "hsk-cb-hello-lead", children: "Ask me to search, visualize, or capture anything \u2014 I look across the whole site in real time." })
|
|
2065
2301
|
] }),
|
|
2066
|
-
!awaitingName && activeChips.length > 0 && /* @__PURE__ */ (0,
|
|
2302
|
+
!awaitingName && activeChips.length > 0 && /* @__PURE__ */ (0, import_jsx_runtime8.jsx)("div", { className: "hsk-cb-chips", children: activeChips.map((chip) => /* @__PURE__ */ (0, import_jsx_runtime8.jsx)(
|
|
2067
2303
|
"button",
|
|
2068
2304
|
{
|
|
2069
2305
|
className: "hsk-cb-chip",
|
|
@@ -2074,40 +2310,41 @@ function ChatModal({
|
|
|
2074
2310
|
)) })
|
|
2075
2311
|
] }) : displayMessages.map((msg, idx) => {
|
|
2076
2312
|
const isLast = idx === displayMessages.length - 1;
|
|
2313
|
+
const isLastUser = msg.role === "user" && !displayMessages.slice(idx + 1).some((m) => m.role === "user");
|
|
2077
2314
|
const isUser = msg.role === "user";
|
|
2078
2315
|
const compareSources = sources.filter((s) => s.id && referencedIds.includes(s.id));
|
|
2079
2316
|
const showMatrix = isLast && lastIntent === "compare" && compareSources.length >= 2;
|
|
2080
2317
|
const displayContent = !isUser && showMatrix ? stripMarkdownTables(msg.content) : msg.content;
|
|
2081
|
-
return /* @__PURE__ */ (0,
|
|
2318
|
+
return /* @__PURE__ */ (0, import_jsx_runtime8.jsx)("div", { className: "hsk-cb-msg-group", ref: (el) => {
|
|
2082
2319
|
messageRefs.current[idx] = el;
|
|
2083
|
-
}, children: isUser ? /* @__PURE__ */ (0,
|
|
2084
|
-
msg.images && msg.images.length > 0 && /* @__PURE__ */ (0,
|
|
2085
|
-
msg.content && /* @__PURE__ */ (0,
|
|
2086
|
-
/* @__PURE__ */ (0,
|
|
2320
|
+
}, children: isUser ? /* @__PURE__ */ (0, import_jsx_runtime8.jsxs)("div", { className: `hsk-cb-user-msg${isLastUser ? " hsk-sent" : ""}`, children: [
|
|
2321
|
+
msg.images && msg.images.length > 0 && /* @__PURE__ */ (0, import_jsx_runtime8.jsx)("div", { className: "hsk-cb-user-imgs", children: msg.images.map((img, i) => /* @__PURE__ */ (0, import_jsx_runtime8.jsx)("img", { src: img, alt: `attachment ${i + 1}`, className: "hsk-cb-user-img-thumb" }, i)) }),
|
|
2322
|
+
msg.content && /* @__PURE__ */ (0, import_jsx_runtime8.jsx)("div", { className: "hsk-cb-user-bubble", children: /^@kiku\b/i.test(msg.content) ? /* @__PURE__ */ (0, import_jsx_runtime8.jsxs)(import_jsx_runtime8.Fragment, { children: [
|
|
2323
|
+
/* @__PURE__ */ (0, import_jsx_runtime8.jsx)("span", { className: "hsk-kiku-badge", children: "@kiku" }),
|
|
2087
2324
|
msg.content.replace(/^@kiku\s*/i, "")
|
|
2088
2325
|
] }) : msg.content })
|
|
2089
|
-
] }) : /* @__PURE__ */ (0,
|
|
2090
|
-
/* @__PURE__ */ (0,
|
|
2091
|
-
/* @__PURE__ */ (0,
|
|
2326
|
+
] }) : /* @__PURE__ */ (0, import_jsx_runtime8.jsxs)("div", { className: "hsk-cb-ai-msg", children: [
|
|
2327
|
+
/* @__PURE__ */ (0, import_jsx_runtime8.jsx)("div", { className: "hsk-cb-ai-icon", style: { display: "flex", alignItems: "center" }, children: /* @__PURE__ */ (0, import_jsx_runtime8.jsx)(SparkleIcon2, {}) }),
|
|
2328
|
+
/* @__PURE__ */ (0, import_jsx_runtime8.jsxs)("div", { className: "hsk-cb-ai-body", children: [
|
|
2092
2329
|
(() => {
|
|
2093
2330
|
const parsed = parseThinking(displayContent);
|
|
2094
2331
|
const thinking = msg.thinking || parsed.thinking;
|
|
2095
2332
|
const content = parsed.content;
|
|
2096
2333
|
const isComplete = msg.thinking ? content.length > 0 || !(isLast && streaming) : parsed.isComplete;
|
|
2097
|
-
return /* @__PURE__ */ (0,
|
|
2098
|
-
(thinking || msg.thoughtForSeconds != null) && /* @__PURE__ */ (0,
|
|
2099
|
-
content && /* @__PURE__ */ (0,
|
|
2334
|
+
return /* @__PURE__ */ (0, import_jsx_runtime8.jsxs)(import_jsx_runtime8.Fragment, { children: [
|
|
2335
|
+
(thinking || msg.thoughtForSeconds != null) && /* @__PURE__ */ (0, import_jsx_runtime8.jsx)(ThinkingBlock, { text: thinking, isComplete, seconds: msg.thoughtForSeconds }),
|
|
2336
|
+
content && /* @__PURE__ */ (0, import_jsx_runtime8.jsxs)("div", { className: "hsk-cb-ai-text", children: [
|
|
2100
2337
|
renderMarkdown(content, isLast && streaming),
|
|
2101
|
-
isLast && streaming && /* @__PURE__ */ (0,
|
|
2338
|
+
isLast && streaming && /* @__PURE__ */ (0, import_jsx_runtime8.jsx)("span", { style: { display: "inline-block", width: "0.5em", height: "1.05em", marginLeft: "2px", verticalAlign: "text-bottom", background: "currentColor", opacity: 0.55, borderRadius: "1px" } })
|
|
2102
2339
|
] })
|
|
2103
2340
|
] });
|
|
2104
2341
|
})(),
|
|
2105
|
-
msg.visualizing && /* @__PURE__ */ (0,
|
|
2106
|
-
/* @__PURE__ */ (0,
|
|
2107
|
-
/* @__PURE__ */ (0,
|
|
2342
|
+
msg.visualizing && /* @__PURE__ */ (0, import_jsx_runtime8.jsxs)("div", { className: "hsk-cb-viz hsk-cb-viz--loading", children: [
|
|
2343
|
+
/* @__PURE__ */ (0, import_jsx_runtime8.jsx)("span", { className: "hsk-cb-viz-spinner" }),
|
|
2344
|
+
/* @__PURE__ */ (0, import_jsx_runtime8.jsx)("span", { children: "Visualizing\u2026" })
|
|
2108
2345
|
] }),
|
|
2109
|
-
msg.visualization && /* @__PURE__ */ (0,
|
|
2110
|
-
/* @__PURE__ */ (0,
|
|
2346
|
+
msg.visualization && /* @__PURE__ */ (0, import_jsx_runtime8.jsxs)("div", { className: "hsk-cb-viz", children: [
|
|
2347
|
+
/* @__PURE__ */ (0, import_jsx_runtime8.jsx)(
|
|
2111
2348
|
"img",
|
|
2112
2349
|
{
|
|
2113
2350
|
src: msg.visualization,
|
|
@@ -2118,16 +2355,36 @@ function ChatModal({
|
|
|
2118
2355
|
}
|
|
2119
2356
|
}
|
|
2120
2357
|
),
|
|
2121
|
-
/* @__PURE__ */ (0,
|
|
2358
|
+
/* @__PURE__ */ (0, import_jsx_runtime8.jsxs)("div", { className: "hsk-cb-viz-foot", children: [
|
|
2359
|
+
/* @__PURE__ */ (0, import_jsx_runtime8.jsx)("div", { className: "hsk-cb-viz-disclaimer", children: "AI-generated preview \u2014 colours, size and placement may differ from the real product." }),
|
|
2360
|
+
isLast && !streaming && /* @__PURE__ */ (0, import_jsx_runtime8.jsx)("button", { className: "hsk-cb-viz-mark", onClick: () => setMarkupSrc(msg.visualization), children: "Mark & edit" })
|
|
2361
|
+
] })
|
|
2122
2362
|
] }),
|
|
2123
|
-
|
|
2363
|
+
!isUser && (msg.knowledgeImages?.length ?? 0) > 0 && /* @__PURE__ */ (0, import_jsx_runtime8.jsx)("div", { className: "hsk-cb-kimgs", children: msg.knowledgeImages.map((ref) => /* @__PURE__ */ (0, import_jsx_runtime8.jsxs)("div", { className: "hsk-cb-kimg-group", children: [
|
|
2364
|
+
/* @__PURE__ */ (0, import_jsx_runtime8.jsx)("div", { className: "hsk-cb-kimg-grid", children: ref.images.map((img, i) => /* @__PURE__ */ (0, import_jsx_runtime8.jsx)(
|
|
2365
|
+
"img",
|
|
2366
|
+
{
|
|
2367
|
+
src: img.url,
|
|
2368
|
+
alt: img.note || ref.title || "Reference image",
|
|
2369
|
+
className: "hsk-cb-kimg",
|
|
2370
|
+
loading: "lazy",
|
|
2371
|
+
onClick: () => setLightboxSrc(img.url),
|
|
2372
|
+
onError: (e) => {
|
|
2373
|
+
e.target.style.display = "none";
|
|
2374
|
+
}
|
|
2375
|
+
},
|
|
2376
|
+
i
|
|
2377
|
+
)) }),
|
|
2378
|
+
(ref.title || ref.images[0]?.note) && /* @__PURE__ */ (0, import_jsx_runtime8.jsx)("div", { className: "hsk-cb-kimg-caption", children: ref.title || ref.images[0]?.note })
|
|
2379
|
+
] }, ref.entryId)) }),
|
|
2380
|
+
showMatrix && /* @__PURE__ */ (0, import_jsx_runtime8.jsx)(ComparisonMatrix, { sources: compareSources, defaultCurrency }),
|
|
2124
2381
|
(() => {
|
|
2125
2382
|
const msgReferencedIds = isLast ? referencedIds : msg.referencedIds ?? [];
|
|
2126
2383
|
const msgSources = isLast ? sources : msg.sources ?? [];
|
|
2127
2384
|
const msgIntent = isLast ? lastIntent : msg.intent;
|
|
2128
2385
|
const hiddenIntent = msgIntent === "compare" || msgIntent === "capture" || msgIntent === "capture_all" || msgIntent === "delete" || msgIntent === "view_history";
|
|
2129
2386
|
const showCarousel = msgReferencedIds.length > 0 && !hiddenIntent && (!isLast || lastAction?.type !== "request_kiku_key");
|
|
2130
|
-
return showCarousel && /* @__PURE__ */ (0,
|
|
2387
|
+
return showCarousel && /* @__PURE__ */ (0, import_jsx_runtime8.jsx)(
|
|
2131
2388
|
SourcesCarousel,
|
|
2132
2389
|
{
|
|
2133
2390
|
sources: msgSources,
|
|
@@ -2139,11 +2396,11 @@ function ChatModal({
|
|
|
2139
2396
|
}
|
|
2140
2397
|
);
|
|
2141
2398
|
})(),
|
|
2142
|
-
isLast && !loading && lastAction?.url && /* @__PURE__ */ (0,
|
|
2399
|
+
isLast && !loading && lastAction?.url && /* @__PURE__ */ (0, import_jsx_runtime8.jsx)("div", { className: "hsk-action-pills", children: /* @__PURE__ */ (0, import_jsx_runtime8.jsxs)("a", { className: "hsk-action-pill", href: lastAction.url, children: [
|
|
2143
2400
|
String(lastAction.type || "continue").replace(/_/g, " "),
|
|
2144
2401
|
" \u2192"
|
|
2145
2402
|
] }) }),
|
|
2146
|
-
isLast && !loading && /* @__PURE__ */ (0,
|
|
2403
|
+
isLast && !loading && /* @__PURE__ */ (0, import_jsx_runtime8.jsx)(
|
|
2147
2404
|
SmartContextPills,
|
|
2148
2405
|
{
|
|
2149
2406
|
intent: lastIntent,
|
|
@@ -2155,16 +2412,16 @@ function ChatModal({
|
|
|
2155
2412
|
] })
|
|
2156
2413
|
] }) }, idx);
|
|
2157
2414
|
}),
|
|
2158
|
-
selectedProduct && loading && /* @__PURE__ */ (0,
|
|
2415
|
+
selectedProduct && loading && /* @__PURE__ */ (0, import_jsx_runtime8.jsxs)(
|
|
2159
2416
|
"div",
|
|
2160
2417
|
{
|
|
2161
2418
|
className: "hsk-cb-selected-product",
|
|
2162
2419
|
onClick: () => selectedProduct.url && window.open(selectedProduct.url, "_blank"),
|
|
2163
2420
|
children: [
|
|
2164
|
-
selectedProduct.image && /* @__PURE__ */ (0,
|
|
2165
|
-
/* @__PURE__ */ (0,
|
|
2166
|
-
/* @__PURE__ */ (0,
|
|
2167
|
-
selectedProduct.price && /* @__PURE__ */ (0,
|
|
2421
|
+
selectedProduct.image && /* @__PURE__ */ (0, import_jsx_runtime8.jsx)("img", { className: "hsk-cb-selected-img", src: selectedProduct.image, alt: selectedProduct.name }),
|
|
2422
|
+
/* @__PURE__ */ (0, import_jsx_runtime8.jsxs)("div", { className: "hsk-cb-selected-info", children: [
|
|
2423
|
+
/* @__PURE__ */ (0, import_jsx_runtime8.jsx)("div", { className: "hsk-cb-selected-name", children: selectedProduct.name }),
|
|
2424
|
+
selectedProduct.price && /* @__PURE__ */ (0, import_jsx_runtime8.jsxs)("div", { className: "hsk-cb-selected-price", children: [
|
|
2168
2425
|
selectedProduct.currency ?? defaultCurrency,
|
|
2169
2426
|
" ",
|
|
2170
2427
|
parseFloat(String(selectedProduct.price ?? "").replace(/[^0-9.]/g, "") || "0").toLocaleString()
|
|
@@ -2173,22 +2430,22 @@ function ChatModal({
|
|
|
2173
2430
|
]
|
|
2174
2431
|
}
|
|
2175
2432
|
),
|
|
2176
|
-
loading && !streaming && /* @__PURE__ */ (0,
|
|
2177
|
-
/* @__PURE__ */ (0,
|
|
2178
|
-
/* @__PURE__ */ (0,
|
|
2179
|
-
/* @__PURE__ */ (0,
|
|
2180
|
-
/* @__PURE__ */ (0,
|
|
2181
|
-
/* @__PURE__ */ (0,
|
|
2182
|
-
/* @__PURE__ */ (0,
|
|
2183
|
-
/* @__PURE__ */ (0,
|
|
2184
|
-
/* @__PURE__ */ (0,
|
|
2185
|
-
/* @__PURE__ */ (0,
|
|
2433
|
+
loading && !streaming && /* @__PURE__ */ (0, import_jsx_runtime8.jsxs)("div", { className: "hsk-cb-typing-row", style: { display: "flex", alignItems: "center", gap: "10px" }, children: [
|
|
2434
|
+
/* @__PURE__ */ (0, import_jsx_runtime8.jsxs)("div", { className: "hsk-cb-thinking-icon", children: [
|
|
2435
|
+
/* @__PURE__ */ (0, import_jsx_runtime8.jsx)("svg", { className: "hsk-brand-mark", viewBox: "0 0 100 100", "aria-hidden": "true", children: /* @__PURE__ */ (0, import_jsx_runtime8.jsx)("path", { d: "M39.4 10.4 Q44 0 48.6 10.4 L86.1 95.8 Q88 100 83.4 100 L4.6 100 Q0 100 1.9 95.8 Z M24 100 L24 65 Q24 60 27.4 56.3 Q44 38 60.6 56.3 Q64 60 64 65 L64 100 Z", transform: "translate(22.7 19) scale(0.62)", fillRule: "evenodd" }) }),
|
|
2436
|
+
/* @__PURE__ */ (0, import_jsx_runtime8.jsx)("svg", { className: "hsk-brand-mark hsk-brand-mark--sheen", viewBox: "0 0 100 100", "aria-hidden": "true", children: /* @__PURE__ */ (0, import_jsx_runtime8.jsx)("path", { d: "M39.4 10.4 Q44 0 48.6 10.4 L86.1 95.8 Q88 100 83.4 100 L4.6 100 Q0 100 1.9 95.8 Z M24 100 L24 65 Q24 60 27.4 56.3 Q44 38 60.6 56.3 Q64 60 64 65 L64 100 Z", transform: "translate(22.7 19) scale(0.62)", fillRule: "evenodd" }) }),
|
|
2437
|
+
/* @__PURE__ */ (0, import_jsx_runtime8.jsx)("span", { className: "hsk-handle-orbit", children: /* @__PURE__ */ (0, import_jsx_runtime8.jsxs)("span", { className: "hsk-handle-ring", children: [
|
|
2438
|
+
/* @__PURE__ */ (0, import_jsx_runtime8.jsx)("span", { className: "hsk-handle-ball" }),
|
|
2439
|
+
/* @__PURE__ */ (0, import_jsx_runtime8.jsx)("span", { className: "hsk-handle-ball" }),
|
|
2440
|
+
/* @__PURE__ */ (0, import_jsx_runtime8.jsx)("span", { className: "hsk-handle-ball" }),
|
|
2441
|
+
/* @__PURE__ */ (0, import_jsx_runtime8.jsx)("span", { className: "hsk-handle-ball" }),
|
|
2442
|
+
/* @__PURE__ */ (0, import_jsx_runtime8.jsx)("span", { className: "hsk-handle-ball" })
|
|
2186
2443
|
] }) }),
|
|
2187
|
-
/* @__PURE__ */ (0,
|
|
2444
|
+
/* @__PURE__ */ (0, import_jsx_runtime8.jsx)("span", { className: "hsk-handle-rest" })
|
|
2188
2445
|
] }),
|
|
2189
|
-
/* @__PURE__ */ (0,
|
|
2446
|
+
/* @__PURE__ */ (0, import_jsx_runtime8.jsx)("span", { className: "hsk-cb-thinking-text", children: "Thinking\u2026" })
|
|
2190
2447
|
] }),
|
|
2191
|
-
lastAction?.type === "open_memory" && lastAction.url && !loading && !streaming && /* @__PURE__ */ (0,
|
|
2448
|
+
lastAction?.type === "open_memory" && lastAction.url && !loading && !streaming && /* @__PURE__ */ (0, import_jsx_runtime8.jsxs)(
|
|
2192
2449
|
"a",
|
|
2193
2450
|
{
|
|
2194
2451
|
className: "hsk-cb-memory-pill",
|
|
@@ -2197,23 +2454,23 @@ function ChatModal({
|
|
|
2197
2454
|
rel: "noopener noreferrer",
|
|
2198
2455
|
children: [
|
|
2199
2456
|
"Open my memory on mimi",
|
|
2200
|
-
/* @__PURE__ */ (0,
|
|
2457
|
+
/* @__PURE__ */ (0, import_jsx_runtime8.jsx)(ExternalIcon, {})
|
|
2201
2458
|
]
|
|
2202
2459
|
}
|
|
2203
2460
|
),
|
|
2204
|
-
(stopped || interrupted) && !loading && !streaming && messages.length > 0 && /* @__PURE__ */ (0,
|
|
2205
|
-
/* @__PURE__ */ (0,
|
|
2206
|
-
/* @__PURE__ */ (0,
|
|
2207
|
-
/* @__PURE__ */ (0,
|
|
2461
|
+
(stopped || interrupted) && !loading && !streaming && messages.length > 0 && /* @__PURE__ */ (0, import_jsx_runtime8.jsxs)("div", { className: "hsk-cb-stopped", children: [
|
|
2462
|
+
/* @__PURE__ */ (0, import_jsx_runtime8.jsx)("span", { className: "hsk-cb-stopped-label", children: stopped ? "You stopped this response." : "This response was interrupted." }),
|
|
2463
|
+
/* @__PURE__ */ (0, import_jsx_runtime8.jsxs)("button", { className: "hsk-cb-continue", onClick: continueGenerating, children: [
|
|
2464
|
+
/* @__PURE__ */ (0, import_jsx_runtime8.jsx)(ContinueIcon, {}),
|
|
2208
2465
|
messages[messages.length - 1]?.role === "assistant" ? "Continue generating" : "Generate response"
|
|
2209
2466
|
] })
|
|
2210
2467
|
] }),
|
|
2211
|
-
error && /* @__PURE__ */ (0,
|
|
2212
|
-
keyPhase === "prompt_key" && /* @__PURE__ */ (0,
|
|
2213
|
-
/* @__PURE__ */ (0,
|
|
2214
|
-
/* @__PURE__ */ (0,
|
|
2215
|
-
/* @__PURE__ */ (0,
|
|
2216
|
-
/* @__PURE__ */ (0,
|
|
2468
|
+
error && /* @__PURE__ */ (0, import_jsx_runtime8.jsx)("div", { className: "hsk-cb-error", children: getFriendlyError(error) }),
|
|
2469
|
+
keyPhase === "prompt_key" && /* @__PURE__ */ (0, import_jsx_runtime8.jsxs)("div", { className: "hsk-cb-ai-msg", children: [
|
|
2470
|
+
/* @__PURE__ */ (0, import_jsx_runtime8.jsx)("div", { className: "hsk-cb-ai-icon", style: { display: "flex", alignItems: "center" }, children: /* @__PURE__ */ (0, import_jsx_runtime8.jsx)(SparkleIcon2, {}) }),
|
|
2471
|
+
/* @__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: /* @__PURE__ */ (0, import_jsx_runtime8.jsxs)("div", { className: "hsk-cb-phone-form", children: [
|
|
2472
|
+
/* @__PURE__ */ (0, import_jsx_runtime8.jsx)("label", { className: "hsk-cb-phone-label", children: "Paste your public id \u2014 or create one" }),
|
|
2473
|
+
/* @__PURE__ */ (0, import_jsx_runtime8.jsx)(
|
|
2217
2474
|
"input",
|
|
2218
2475
|
{
|
|
2219
2476
|
type: "text",
|
|
@@ -2225,49 +2482,49 @@ function ChatModal({
|
|
|
2225
2482
|
autoFocus: true
|
|
2226
2483
|
}
|
|
2227
2484
|
),
|
|
2228
|
-
/* @__PURE__ */ (0,
|
|
2229
|
-
/* @__PURE__ */ (0,
|
|
2230
|
-
/* @__PURE__ */ (0,
|
|
2485
|
+
/* @__PURE__ */ (0, import_jsx_runtime8.jsxs)("div", { style: { display: "flex", gap: 8 }, children: [
|
|
2486
|
+
/* @__PURE__ */ (0, import_jsx_runtime8.jsx)("button", { className: "hsk-cb-phone-submit", onClick: handleUseExistingKey, disabled: !keyInput.trim(), children: "Use my id" }),
|
|
2487
|
+
/* @__PURE__ */ (0, import_jsx_runtime8.jsx)("button", { className: "hsk-cb-phone-submit", onClick: handleCreateKey, disabled: minting, children: minting ? "Creating\u2026" : "I'm new \u2014 create one" })
|
|
2231
2488
|
] })
|
|
2232
2489
|
] }) }) })
|
|
2233
2490
|
] }),
|
|
2234
|
-
mintedKey && /* @__PURE__ */ (0,
|
|
2235
|
-
/* @__PURE__ */ (0,
|
|
2236
|
-
/* @__PURE__ */ (0,
|
|
2237
|
-
/* @__PURE__ */ (0,
|
|
2238
|
-
/* @__PURE__ */ (0,
|
|
2239
|
-
/* @__PURE__ */ (0,
|
|
2240
|
-
/* @__PURE__ */ (0,
|
|
2241
|
-
/* @__PURE__ */ (0,
|
|
2242
|
-
/* @__PURE__ */ (0,
|
|
2491
|
+
mintedKey && /* @__PURE__ */ (0, import_jsx_runtime8.jsxs)("div", { className: "hsk-cb-ai-msg", children: [
|
|
2492
|
+
/* @__PURE__ */ (0, import_jsx_runtime8.jsx)("div", { className: "hsk-cb-ai-icon", style: { display: "flex", alignItems: "center" }, children: /* @__PURE__ */ (0, import_jsx_runtime8.jsx)(SparkleIcon2, {}) }),
|
|
2493
|
+
/* @__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: /* @__PURE__ */ (0, import_jsx_runtime8.jsxs)("div", { style: { padding: "12px 14px", border: "1px solid var(--hsk-border, #e5e5e5)", borderRadius: "var(--hsk-border-radius, 0px)", display: "flex", flexDirection: "column", gap: 12 }, children: [
|
|
2494
|
+
/* @__PURE__ */ (0, import_jsx_runtime8.jsxs)("div", { children: [
|
|
2495
|
+
/* @__PURE__ */ (0, import_jsx_runtime8.jsx)("div", { style: { fontSize: 12, fontWeight: 600, marginBottom: 4 }, children: "Your secret \u2014 shown only once" }),
|
|
2496
|
+
/* @__PURE__ */ (0, import_jsx_runtime8.jsx)("code", { style: { display: "block", fontSize: 14, fontWeight: 700, marginBottom: 6, wordBreak: "break-all" }, children: mintedKey }),
|
|
2497
|
+
/* @__PURE__ */ (0, import_jsx_runtime8.jsxs)("div", { style: { display: "flex", gap: 8, alignItems: "center" }, children: [
|
|
2498
|
+
/* @__PURE__ */ (0, import_jsx_runtime8.jsx)("button", { className: "hsk-cb-phone-submit", style: { padding: "4px 10px" }, onClick: () => copyValue(mintedKey, "secret"), children: copied === "secret" ? "Copied" : "Copy secret" }),
|
|
2499
|
+
/* @__PURE__ */ (0, import_jsx_runtime8.jsx)("span", { style: { fontSize: 11, opacity: 0.7 }, children: "Keep it private \u2014 use it to unlock your memory at mimi.akropolys.cloud. If lost, the memory is lost with it." })
|
|
2243
2500
|
] })
|
|
2244
2501
|
] }),
|
|
2245
|
-
mintedPub && /* @__PURE__ */ (0,
|
|
2246
|
-
/* @__PURE__ */ (0,
|
|
2247
|
-
/* @__PURE__ */ (0,
|
|
2248
|
-
/* @__PURE__ */ (0,
|
|
2249
|
-
/* @__PURE__ */ (0,
|
|
2250
|
-
/* @__PURE__ */ (0,
|
|
2502
|
+
mintedPub && /* @__PURE__ */ (0, import_jsx_runtime8.jsxs)("div", { children: [
|
|
2503
|
+
/* @__PURE__ */ (0, import_jsx_runtime8.jsx)("div", { style: { fontSize: 12, fontWeight: 600, marginBottom: 4 }, children: "Your public id" }),
|
|
2504
|
+
/* @__PURE__ */ (0, import_jsx_runtime8.jsx)("code", { style: { display: "block", fontSize: 13, fontWeight: 600, marginBottom: 6, wordBreak: "break-all", opacity: 0.85 }, children: mintedPub }),
|
|
2505
|
+
/* @__PURE__ */ (0, import_jsx_runtime8.jsxs)("div", { style: { display: "flex", gap: 8, alignItems: "center" }, children: [
|
|
2506
|
+
/* @__PURE__ */ (0, import_jsx_runtime8.jsx)("button", { className: "hsk-cb-phone-submit", style: { padding: "4px 10px" }, onClick: () => copyValue(mintedPub, "pub"), children: copied === "pub" ? "Copied" : "Copy id" }),
|
|
2507
|
+
/* @__PURE__ */ (0, import_jsx_runtime8.jsx)("span", { style: { fontSize: 11, opacity: 0.7 }, children: "Paste this on any site to keep saving to the same memory." })
|
|
2251
2508
|
] })
|
|
2252
2509
|
] }),
|
|
2253
|
-
/* @__PURE__ */ (0,
|
|
2510
|
+
/* @__PURE__ */ (0, import_jsx_runtime8.jsxs)("div", { style: { fontSize: 11, opacity: 0.6 }, children: [
|
|
2254
2511
|
"Hidden in ",
|
|
2255
2512
|
keyCountdown,
|
|
2256
2513
|
"s."
|
|
2257
2514
|
] })
|
|
2258
2515
|
] }) }) })
|
|
2259
2516
|
] }),
|
|
2260
|
-
/* @__PURE__ */ (0,
|
|
2517
|
+
/* @__PURE__ */ (0, import_jsx_runtime8.jsx)("div", { ref: bottomRef, style: { height: 1 } })
|
|
2261
2518
|
] }),
|
|
2262
|
-
/* @__PURE__ */ (0,
|
|
2263
|
-
showAtPicker && /* @__PURE__ */ (0,
|
|
2519
|
+
/* @__PURE__ */ (0, import_jsx_runtime8.jsxs)("div", { className: "hsk-cb-input-wrap", children: [
|
|
2520
|
+
showAtPicker && /* @__PURE__ */ (0, import_jsx_runtime8.jsx)(
|
|
2264
2521
|
AtPickerMenu,
|
|
2265
2522
|
{
|
|
2266
2523
|
onSelect: handleSelectExtension,
|
|
2267
2524
|
onDismiss: () => setShowAtPicker(false)
|
|
2268
2525
|
}
|
|
2269
2526
|
),
|
|
2270
|
-
showKikuPicker && /* @__PURE__ */ (0,
|
|
2527
|
+
showKikuPicker && /* @__PURE__ */ (0, import_jsx_runtime8.jsx)(
|
|
2271
2528
|
KikuPickerMenu,
|
|
2272
2529
|
{
|
|
2273
2530
|
sources,
|
|
@@ -2280,9 +2537,9 @@ function ChatModal({
|
|
|
2280
2537
|
onDismiss: () => setShowKikuPicker(false)
|
|
2281
2538
|
}
|
|
2282
2539
|
),
|
|
2283
|
-
attachments.length > 0 && /* @__PURE__ */ (0,
|
|
2284
|
-
/* @__PURE__ */ (0,
|
|
2285
|
-
/* @__PURE__ */ (0,
|
|
2540
|
+
attachments.length > 0 && /* @__PURE__ */ (0, import_jsx_runtime8.jsx)("div", { className: "hsk-cb-img-strip", children: attachments.map((att, i) => /* @__PURE__ */ (0, import_jsx_runtime8.jsxs)("div", { className: "hsk-cb-img-thumb-wrap", children: [
|
|
2541
|
+
/* @__PURE__ */ (0, import_jsx_runtime8.jsx)("img", { src: att.data, alt: `attachment ${i + 1}`, className: "hsk-cb-img-thumb" }),
|
|
2542
|
+
/* @__PURE__ */ (0, import_jsx_runtime8.jsx)(
|
|
2286
2543
|
"button",
|
|
2287
2544
|
{
|
|
2288
2545
|
className: "hsk-cb-img-thumb-remove",
|
|
@@ -2292,8 +2549,8 @@ function ChatModal({
|
|
|
2292
2549
|
}
|
|
2293
2550
|
)
|
|
2294
2551
|
] }, i)) }),
|
|
2295
|
-
/* @__PURE__ */ (0,
|
|
2296
|
-
/* @__PURE__ */ (0,
|
|
2552
|
+
/* @__PURE__ */ (0, import_jsx_runtime8.jsxs)("div", { className: "hsk-cb-input-box", children: [
|
|
2553
|
+
/* @__PURE__ */ (0, import_jsx_runtime8.jsx)(
|
|
2297
2554
|
"input",
|
|
2298
2555
|
{
|
|
2299
2556
|
ref: imageInputRef,
|
|
@@ -2304,7 +2561,7 @@ function ChatModal({
|
|
|
2304
2561
|
onChange: (e) => handleImageFiles(e.target.files)
|
|
2305
2562
|
}
|
|
2306
2563
|
),
|
|
2307
|
-
enableVision && /* @__PURE__ */ (0,
|
|
2564
|
+
enableVision && /* @__PURE__ */ (0, import_jsx_runtime8.jsx)(
|
|
2308
2565
|
"button",
|
|
2309
2566
|
{
|
|
2310
2567
|
className: "hsk-cb-attach-btn",
|
|
@@ -2312,10 +2569,10 @@ function ChatModal({
|
|
|
2312
2569
|
disabled: loading,
|
|
2313
2570
|
"aria-label": "Attach image",
|
|
2314
2571
|
title: "Attach image",
|
|
2315
|
-
children: /* @__PURE__ */ (0,
|
|
2572
|
+
children: /* @__PURE__ */ (0, import_jsx_runtime8.jsx)(PaperclipIcon, {})
|
|
2316
2573
|
}
|
|
2317
2574
|
),
|
|
2318
|
-
/* @__PURE__ */ (0,
|
|
2575
|
+
/* @__PURE__ */ (0, import_jsx_runtime8.jsx)(
|
|
2319
2576
|
"textarea",
|
|
2320
2577
|
{
|
|
2321
2578
|
ref: textareaRef,
|
|
@@ -2329,7 +2586,7 @@ function ChatModal({
|
|
|
2329
2586
|
autoFocus: true
|
|
2330
2587
|
}
|
|
2331
2588
|
),
|
|
2332
|
-
hasSpeechAPI && enableVoice && /* @__PURE__ */ (0,
|
|
2589
|
+
hasSpeechAPI && enableVoice && /* @__PURE__ */ (0, import_jsx_runtime8.jsxs)(
|
|
2333
2590
|
"button",
|
|
2334
2591
|
{
|
|
2335
2592
|
className: cn(
|
|
@@ -2342,32 +2599,32 @@ function ChatModal({
|
|
|
2342
2599
|
"aria-label": voiceState === "idle" ? "Start voice input" : "Stop recording",
|
|
2343
2600
|
title: voiceState === "idle" ? "Voice input" : "Stop",
|
|
2344
2601
|
children: [
|
|
2345
|
-
voiceState === "listening" ? /* @__PURE__ */ (0,
|
|
2346
|
-
voiceState === "listening" && /* @__PURE__ */ (0,
|
|
2602
|
+
voiceState === "listening" ? /* @__PURE__ */ (0, import_jsx_runtime8.jsx)(MicOffIcon, {}) : /* @__PURE__ */ (0, import_jsx_runtime8.jsx)(MicIcon2, {}),
|
|
2603
|
+
voiceState === "listening" && /* @__PURE__ */ (0, import_jsx_runtime8.jsx)("span", { className: "hsk-cb-mic-pulse" })
|
|
2347
2604
|
]
|
|
2348
2605
|
}
|
|
2349
2606
|
),
|
|
2350
|
-
loading || streaming ? /* @__PURE__ */ (0,
|
|
2607
|
+
loading || streaming ? /* @__PURE__ */ (0, import_jsx_runtime8.jsx)(
|
|
2351
2608
|
"button",
|
|
2352
2609
|
{
|
|
2353
2610
|
className: cn("hsk-cb-send", "hsk-cb-send--stop", classNames.sendButton),
|
|
2354
2611
|
onClick: stop,
|
|
2355
2612
|
"aria-label": "Stop generating",
|
|
2356
2613
|
title: "Stop generating",
|
|
2357
|
-
children: /* @__PURE__ */ (0,
|
|
2614
|
+
children: /* @__PURE__ */ (0, import_jsx_runtime8.jsx)(StopIcon, {})
|
|
2358
2615
|
}
|
|
2359
|
-
) : /* @__PURE__ */ (0,
|
|
2616
|
+
) : /* @__PURE__ */ (0, import_jsx_runtime8.jsx)(
|
|
2360
2617
|
"button",
|
|
2361
2618
|
{
|
|
2362
2619
|
className: cn("hsk-cb-send", classNames.sendButton),
|
|
2363
2620
|
onClick: () => handleSend(),
|
|
2364
2621
|
disabled: !input.trim() && attachments.length === 0,
|
|
2365
2622
|
"aria-label": "Send message",
|
|
2366
|
-
children: /* @__PURE__ */ (0,
|
|
2623
|
+
children: /* @__PURE__ */ (0, import_jsx_runtime8.jsx)(ArrowUpIcon2, {})
|
|
2367
2624
|
}
|
|
2368
2625
|
)
|
|
2369
2626
|
] }),
|
|
2370
|
-
/* @__PURE__ */ (0,
|
|
2627
|
+
/* @__PURE__ */ (0, import_jsx_runtime8.jsx)("div", { className: "hsk-cb-hint", children: "kiku \xB7 searches the whole catalogue in real time" })
|
|
2371
2628
|
] })
|
|
2372
2629
|
] })
|
|
2373
2630
|
]
|
|
@@ -2393,9 +2650,9 @@ function KikuButton({
|
|
|
2393
2650
|
enableVision = false,
|
|
2394
2651
|
visionCategoryHint
|
|
2395
2652
|
}) {
|
|
2396
|
-
const [open, setOpen] = (0,
|
|
2397
|
-
const [mounted, setMounted] = (0,
|
|
2398
|
-
(0,
|
|
2653
|
+
const [open, setOpen] = (0, import_react6.useState)(false);
|
|
2654
|
+
const [mounted, setMounted] = (0, import_react6.useState)(false);
|
|
2655
|
+
(0, import_react6.useEffect)(() => {
|
|
2399
2656
|
setMounted(true);
|
|
2400
2657
|
if (typeof window !== "undefined" && !window.__akropolys_nav_patched) {
|
|
2401
2658
|
window.__akropolys_nav_patched = true;
|
|
@@ -2429,8 +2686,8 @@ function KikuButton({
|
|
|
2429
2686
|
...theme?.fontFamily && { "--hsk-font": theme.fontFamily },
|
|
2430
2687
|
...theme?.borderRadius && { "--hsk-border-radius": theme.borderRadius }
|
|
2431
2688
|
} : void 0;
|
|
2432
|
-
return /* @__PURE__ */ (0,
|
|
2433
|
-
/* @__PURE__ */ (0,
|
|
2689
|
+
return /* @__PURE__ */ (0, import_jsx_runtime8.jsxs)(import_jsx_runtime8.Fragment, { children: [
|
|
2690
|
+
/* @__PURE__ */ (0, import_jsx_runtime8.jsxs)(
|
|
2434
2691
|
"button",
|
|
2435
2692
|
{
|
|
2436
2693
|
className: cn("hsk-cb-btn", classNames.button, className),
|
|
@@ -2439,13 +2696,13 @@ function KikuButton({
|
|
|
2439
2696
|
"data-hsk-theme": hskThemeAttr,
|
|
2440
2697
|
"aria-label": "Open AI chat",
|
|
2441
2698
|
children: [
|
|
2442
|
-
/* @__PURE__ */ (0,
|
|
2699
|
+
/* @__PURE__ */ (0, import_jsx_runtime8.jsx)("span", { className: "hsk-cb-btn-icon", style: { display: "flex", alignItems: "center" }, children: /* @__PURE__ */ (0, import_jsx_runtime8.jsx)(SparkleIcon2, {}) }),
|
|
2443
2700
|
label !== void 0 ? label : null
|
|
2444
2701
|
]
|
|
2445
2702
|
}
|
|
2446
2703
|
),
|
|
2447
2704
|
open && mounted && (0, import_react_dom.createPortal)(
|
|
2448
|
-
/* @__PURE__ */ (0,
|
|
2705
|
+
/* @__PURE__ */ (0, import_jsx_runtime8.jsx)(
|
|
2449
2706
|
ChatModal,
|
|
2450
2707
|
{
|
|
2451
2708
|
title,
|
|
@@ -2470,11 +2727,11 @@ function KikuButton({
|
|
|
2470
2727
|
}
|
|
2471
2728
|
|
|
2472
2729
|
// src/components/Sparkle.tsx
|
|
2473
|
-
var
|
|
2730
|
+
var import_react7 = require("react");
|
|
2474
2731
|
var import_react_dom2 = require("react-dom");
|
|
2475
2732
|
var import_sdk7 = require("@akropolys/sdk");
|
|
2476
|
-
var
|
|
2477
|
-
var SparkleIcon3 = ({ className, size = 16 }) => /* @__PURE__ */ (0,
|
|
2733
|
+
var import_jsx_runtime9 = require("react/jsx-runtime");
|
|
2734
|
+
var SparkleIcon3 = ({ className, size = 16 }) => /* @__PURE__ */ (0, import_jsx_runtime9.jsx)(
|
|
2478
2735
|
"svg",
|
|
2479
2736
|
{
|
|
2480
2737
|
className: cn("hsk-brand-mark", className),
|
|
@@ -2483,19 +2740,19 @@ var SparkleIcon3 = ({ className, size = 16 }) => /* @__PURE__ */ (0, import_jsx_
|
|
|
2483
2740
|
viewBox: "0 0 100 100",
|
|
2484
2741
|
xmlns: "http://www.w3.org/2000/svg",
|
|
2485
2742
|
"aria-label": "kiku",
|
|
2486
|
-
children: /* @__PURE__ */ (0,
|
|
2487
|
-
/* @__PURE__ */ (0,
|
|
2488
|
-
/* @__PURE__ */ (0,
|
|
2743
|
+
children: /* @__PURE__ */ (0, import_jsx_runtime9.jsxs)("g", { transform: "translate(22.7 19) scale(0.62)", fill: "currentColor", fillRule: "evenodd", children: [
|
|
2744
|
+
/* @__PURE__ */ (0, import_jsx_runtime9.jsx)("path", { d: "M39.4 10.4 Q44 0 48.6 10.4 L86.1 95.8 Q88 100 83.4 100 L4.6 100 Q0 100 1.9 95.8 Z M24 100 L24 65 Q24 60 27.4 56.3 Q44 38 60.6 56.3 Q64 60 64 65 L64 100 Z" }),
|
|
2745
|
+
/* @__PURE__ */ (0, import_jsx_runtime9.jsx)("circle", { cx: "55", cy: "82", r: "3.4" })
|
|
2489
2746
|
] })
|
|
2490
2747
|
}
|
|
2491
2748
|
);
|
|
2492
|
-
var CloseIcon2 = () => /* @__PURE__ */ (0,
|
|
2493
|
-
/* @__PURE__ */ (0,
|
|
2494
|
-
/* @__PURE__ */ (0,
|
|
2749
|
+
var CloseIcon2 = () => /* @__PURE__ */ (0, import_jsx_runtime9.jsxs)("svg", { width: "16", height: "16", viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "2.5", strokeLinecap: "round", strokeLinejoin: "round", children: [
|
|
2750
|
+
/* @__PURE__ */ (0, import_jsx_runtime9.jsx)("line", { x1: "18", y1: "6", x2: "6", y2: "18" }),
|
|
2751
|
+
/* @__PURE__ */ (0, import_jsx_runtime9.jsx)("line", { x1: "6", y1: "6", x2: "18", y2: "18" })
|
|
2495
2752
|
] });
|
|
2496
|
-
var ArrowUpIcon3 = () => /* @__PURE__ */ (0,
|
|
2497
|
-
/* @__PURE__ */ (0,
|
|
2498
|
-
/* @__PURE__ */ (0,
|
|
2753
|
+
var ArrowUpIcon3 = () => /* @__PURE__ */ (0, import_jsx_runtime9.jsxs)("svg", { width: "18", height: "18", viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "2", strokeLinecap: "round", strokeLinejoin: "round", children: [
|
|
2754
|
+
/* @__PURE__ */ (0, import_jsx_runtime9.jsx)("path", { d: "m5 12 7-7 7 7" }),
|
|
2755
|
+
/* @__PURE__ */ (0, import_jsx_runtime9.jsx)("path", { d: "M12 19V5" })
|
|
2499
2756
|
] });
|
|
2500
2757
|
var getFriendlyError2 = (err) => {
|
|
2501
2758
|
let str = "";
|
|
@@ -2529,17 +2786,17 @@ function SparkleModal({
|
|
|
2529
2786
|
product: initialProduct
|
|
2530
2787
|
}) {
|
|
2531
2788
|
const client = (0, import_sdk7.useAkropolysContext)();
|
|
2532
|
-
const [fetchedProduct, setFetchedProduct] = (0,
|
|
2789
|
+
const [fetchedProduct, setFetchedProduct] = (0, import_react7.useState)(null);
|
|
2533
2790
|
const displayProduct = initialProduct || fetchedProduct;
|
|
2534
2791
|
const { results, loading: searchLoading, search } = (0, import_sdk7.useSearch)({ type: "vector" });
|
|
2535
2792
|
const { messages, sources, loading: chatLoading, error: chatError, send } = (0, import_sdk7.useKiku)();
|
|
2536
|
-
const [chatInput, setChatInput] = (0,
|
|
2537
|
-
const [isMobile, setIsMobile] = (0,
|
|
2538
|
-
const [showSpecs, setShowSpecs] = (0,
|
|
2539
|
-
const [collapseSimilar, setCollapseSimilar] = (0,
|
|
2540
|
-
const chatBottomRef = (0,
|
|
2541
|
-
const chatTextareaRef = (0,
|
|
2542
|
-
(0,
|
|
2793
|
+
const [chatInput, setChatInput] = (0, import_react7.useState)("");
|
|
2794
|
+
const [isMobile, setIsMobile] = (0, import_react7.useState)(false);
|
|
2795
|
+
const [showSpecs, setShowSpecs] = (0, import_react7.useState)(false);
|
|
2796
|
+
const [collapseSimilar, setCollapseSimilar] = (0, import_react7.useState)(false);
|
|
2797
|
+
const chatBottomRef = (0, import_react7.useRef)(null);
|
|
2798
|
+
const chatTextareaRef = (0, import_react7.useRef)(null);
|
|
2799
|
+
(0, import_react7.useEffect)(() => {
|
|
2543
2800
|
if (!initialProduct && !fetchedProduct) {
|
|
2544
2801
|
client.api.searchVector(productName, 1).then((res) => {
|
|
2545
2802
|
if (res.results && res.results.length > 0) {
|
|
@@ -2549,7 +2806,7 @@ function SparkleModal({
|
|
|
2549
2806
|
}
|
|
2550
2807
|
search(productName, limit);
|
|
2551
2808
|
}, [productName, initialProduct, fetchedProduct, client, limit, search]);
|
|
2552
|
-
(0,
|
|
2809
|
+
(0, import_react7.useEffect)(() => {
|
|
2553
2810
|
const handleResize = () => setIsMobile(window.innerWidth <= 768);
|
|
2554
2811
|
handleResize();
|
|
2555
2812
|
if (typeof window !== "undefined") {
|
|
@@ -2557,17 +2814,17 @@ function SparkleModal({
|
|
|
2557
2814
|
return () => window.removeEventListener("resize", handleResize);
|
|
2558
2815
|
}
|
|
2559
2816
|
}, []);
|
|
2560
|
-
(0,
|
|
2817
|
+
(0, import_react7.useEffect)(() => {
|
|
2561
2818
|
if (results.length > 0) onResult?.(results);
|
|
2562
2819
|
}, [results, onResult]);
|
|
2563
|
-
(0,
|
|
2820
|
+
(0, import_react7.useEffect)(() => {
|
|
2564
2821
|
const h = (e) => {
|
|
2565
2822
|
if (e.key === "Escape") onClose();
|
|
2566
2823
|
};
|
|
2567
2824
|
document.addEventListener("keydown", h);
|
|
2568
2825
|
return () => document.removeEventListener("keydown", h);
|
|
2569
2826
|
}, [onClose]);
|
|
2570
|
-
(0,
|
|
2827
|
+
(0, import_react7.useEffect)(() => {
|
|
2571
2828
|
chatBottomRef.current?.scrollIntoView({ behavior: "smooth" });
|
|
2572
2829
|
}, [messages, chatLoading]);
|
|
2573
2830
|
const blurVal = typeof backdropBlur === "number" ? `${backdropBlur}px` : backdropBlur ?? "16px";
|
|
@@ -2621,7 +2878,7 @@ Question: ${q}`;
|
|
|
2621
2878
|
}
|
|
2622
2879
|
] : messages;
|
|
2623
2880
|
if (isMobile) {
|
|
2624
|
-
return /* @__PURE__ */ (0,
|
|
2881
|
+
return /* @__PURE__ */ (0, import_jsx_runtime9.jsx)(
|
|
2625
2882
|
"div",
|
|
2626
2883
|
{
|
|
2627
2884
|
className: cn("hsk-sp-backdrop hsk-sp-mobile-view", classNames.backdrop),
|
|
@@ -2632,13 +2889,13 @@ Question: ${q}`;
|
|
|
2632
2889
|
background: bg ?? void 0,
|
|
2633
2890
|
...customStyles
|
|
2634
2891
|
},
|
|
2635
|
-
children: /* @__PURE__ */ (0,
|
|
2636
|
-
/* @__PURE__ */ (0,
|
|
2637
|
-
/* @__PURE__ */ (0,
|
|
2638
|
-
/* @__PURE__ */ (0,
|
|
2639
|
-
/* @__PURE__ */ (0,
|
|
2640
|
-
/* @__PURE__ */ (0,
|
|
2641
|
-
displayProduct && /* @__PURE__ */ (0,
|
|
2892
|
+
children: /* @__PURE__ */ (0, import_jsx_runtime9.jsxs)("div", { className: cn("hsk-sp-card hsk-sp-fullscreen hsk-sp-mobile-card", classNames.card), onClick: (e) => e.stopPropagation(), children: [
|
|
2893
|
+
/* @__PURE__ */ (0, import_jsx_runtime9.jsxs)("div", { className: "hsk-sp-header", children: [
|
|
2894
|
+
/* @__PURE__ */ (0, import_jsx_runtime9.jsx)("span", { className: "hsk-sp-header-icon", style: { display: "flex", alignItems: "center" }, children: /* @__PURE__ */ (0, import_jsx_runtime9.jsx)(SparkleIcon3, {}) }),
|
|
2895
|
+
/* @__PURE__ */ (0, import_jsx_runtime9.jsxs)("div", { className: "hsk-sp-header-body", children: [
|
|
2896
|
+
/* @__PURE__ */ (0, import_jsx_runtime9.jsxs)("div", { className: "hsk-sp-header-title-row", children: [
|
|
2897
|
+
/* @__PURE__ */ (0, import_jsx_runtime9.jsx)("div", { className: "hsk-sp-header-title", children: displayProduct?.name || productName }),
|
|
2898
|
+
displayProduct && /* @__PURE__ */ (0, import_jsx_runtime9.jsx)(
|
|
2642
2899
|
"button",
|
|
2643
2900
|
{
|
|
2644
2901
|
type: "button",
|
|
@@ -2648,32 +2905,32 @@ Question: ${q}`;
|
|
|
2648
2905
|
}
|
|
2649
2906
|
)
|
|
2650
2907
|
] }),
|
|
2651
|
-
/* @__PURE__ */ (0,
|
|
2908
|
+
/* @__PURE__ */ (0, import_jsx_runtime9.jsx)("div", { className: "hsk-sp-header-sub", children: "kiku" })
|
|
2652
2909
|
] }),
|
|
2653
|
-
/* @__PURE__ */ (0,
|
|
2910
|
+
/* @__PURE__ */ (0, import_jsx_runtime9.jsx)("button", { className: "hsk-sp-close", onClick: onClose, "aria-label": "Close", children: /* @__PURE__ */ (0, import_jsx_runtime9.jsx)(CloseIcon2, {}) })
|
|
2654
2911
|
] }),
|
|
2655
|
-
searchLoading && /* @__PURE__ */ (0,
|
|
2656
|
-
/* @__PURE__ */ (0,
|
|
2657
|
-
/* @__PURE__ */ (0,
|
|
2912
|
+
searchLoading && /* @__PURE__ */ (0, import_jsx_runtime9.jsx)("div", { className: "hsk-sp-bar" }),
|
|
2913
|
+
/* @__PURE__ */ (0, import_jsx_runtime9.jsxs)("div", { className: "hsk-sp-mobile-chat-container", children: [
|
|
2914
|
+
/* @__PURE__ */ (0, import_jsx_runtime9.jsxs)("div", { className: "hsk-cb-msgs", children: [
|
|
2658
2915
|
displayMessages.map((msg, idx) => {
|
|
2659
2916
|
const isUser = msg.role === "user";
|
|
2660
|
-
return /* @__PURE__ */ (0,
|
|
2661
|
-
/* @__PURE__ */ (0,
|
|
2662
|
-
/* @__PURE__ */ (0,
|
|
2663
|
-
/* @__PURE__ */ (0,
|
|
2664
|
-
idx === 0 && displayProduct && /* @__PURE__ */ (0,
|
|
2665
|
-
/* @__PURE__ */ (0,
|
|
2666
|
-
/* @__PURE__ */ (0,
|
|
2667
|
-
/* @__PURE__ */ (0,
|
|
2668
|
-
/* @__PURE__ */ (0,
|
|
2669
|
-
/* @__PURE__ */ (0,
|
|
2670
|
-
/* @__PURE__ */ (0,
|
|
2917
|
+
return /* @__PURE__ */ (0, import_jsx_runtime9.jsx)("div", { className: "hsk-cb-msg-group", children: isUser ? /* @__PURE__ */ (0, import_jsx_runtime9.jsx)("div", { className: "hsk-cb-user-msg", children: /* @__PURE__ */ (0, import_jsx_runtime9.jsx)("div", { className: "hsk-cb-user-bubble", children: msg.content }) }) : /* @__PURE__ */ (0, import_jsx_runtime9.jsxs)("div", { className: "hsk-cb-ai-msg", children: [
|
|
2918
|
+
/* @__PURE__ */ (0, import_jsx_runtime9.jsx)("div", { className: "hsk-cb-ai-icon", style: { display: "flex", alignItems: "center" }, children: /* @__PURE__ */ (0, import_jsx_runtime9.jsx)(SparkleIcon3, {}) }),
|
|
2919
|
+
/* @__PURE__ */ (0, import_jsx_runtime9.jsxs)("div", { className: "hsk-cb-ai-body", children: [
|
|
2920
|
+
/* @__PURE__ */ (0, import_jsx_runtime9.jsx)("div", { className: "hsk-cb-ai-text", children: renderMarkdown(msg.content) }),
|
|
2921
|
+
idx === 0 && displayProduct && /* @__PURE__ */ (0, import_jsx_runtime9.jsxs)("div", { className: "hsk-sp-mobile-attachment-deck", children: [
|
|
2922
|
+
/* @__PURE__ */ (0, import_jsx_runtime9.jsxs)("div", { className: "hsk-sp-mobile-main-card", children: [
|
|
2923
|
+
/* @__PURE__ */ (0, import_jsx_runtime9.jsx)("div", { className: "hsk-sp-mobile-main-card-img", children: displayProduct.images?.[0] ? /* @__PURE__ */ (0, import_jsx_runtime9.jsx)("img", { src: displayProduct.images[0], alt: displayProduct.name }) : /* @__PURE__ */ (0, import_jsx_runtime9.jsx)("span", { children: "\xF0\u0178\u203A\x8D" }) }),
|
|
2924
|
+
/* @__PURE__ */ (0, import_jsx_runtime9.jsxs)("div", { className: "hsk-sp-mobile-main-card-info", children: [
|
|
2925
|
+
/* @__PURE__ */ (0, import_jsx_runtime9.jsx)("div", { className: "hsk-sp-mobile-main-card-brand", children: displayProduct.brand || displayProduct.category || "Product" }),
|
|
2926
|
+
/* @__PURE__ */ (0, import_jsx_runtime9.jsx)("div", { className: "hsk-sp-mobile-main-card-name", children: displayProduct.name }),
|
|
2927
|
+
/* @__PURE__ */ (0, import_jsx_runtime9.jsxs)("div", { className: "hsk-sp-mobile-main-card-price", children: [
|
|
2671
2928
|
displayProduct.currency ?? "KES",
|
|
2672
2929
|
" ",
|
|
2673
2930
|
parseFloat(displayProduct.price?.replace(/[^0-9.]/g, "") || "0").toLocaleString()
|
|
2674
2931
|
] })
|
|
2675
2932
|
] }),
|
|
2676
|
-
(displayProduct.specs && Object.keys(displayProduct.specs).length > 0 || displayProduct.description) && /* @__PURE__ */ (0,
|
|
2933
|
+
(displayProduct.specs && Object.keys(displayProduct.specs).length > 0 || displayProduct.description) && /* @__PURE__ */ (0, import_jsx_runtime9.jsx)(
|
|
2677
2934
|
"button",
|
|
2678
2935
|
{
|
|
2679
2936
|
type: "button",
|
|
@@ -2692,21 +2949,21 @@ Question: ${q}`;
|
|
|
2692
2949
|
}
|
|
2693
2950
|
);
|
|
2694
2951
|
if (similarProducts.length === 0) return null;
|
|
2695
|
-
return /* @__PURE__ */ (0,
|
|
2696
|
-
/* @__PURE__ */ (0,
|
|
2697
|
-
/* @__PURE__ */ (0,
|
|
2952
|
+
return /* @__PURE__ */ (0, import_jsx_runtime9.jsxs)("div", { className: "hsk-sp-mobile-similar-carousel-inline", children: [
|
|
2953
|
+
/* @__PURE__ */ (0, import_jsx_runtime9.jsx)("div", { className: "hsk-sp-mobile-similar-carousel-title", children: "Similar Products" }),
|
|
2954
|
+
/* @__PURE__ */ (0, import_jsx_runtime9.jsx)("div", { className: "hsk-sp-mobile-similar-carousel-list", children: similarProducts.map((r) => {
|
|
2698
2955
|
const price = parseFloat(r.entity.price?.replace(/[^0-9.]/g, "") || "0");
|
|
2699
2956
|
const currency = r.entity.currency ?? "KES";
|
|
2700
|
-
return /* @__PURE__ */ (0,
|
|
2957
|
+
return /* @__PURE__ */ (0, import_jsx_runtime9.jsxs)(
|
|
2701
2958
|
"div",
|
|
2702
2959
|
{
|
|
2703
2960
|
className: "hsk-sp-mobile-similar-carousel-item",
|
|
2704
2961
|
onClick: () => handleNav(r),
|
|
2705
2962
|
children: [
|
|
2706
|
-
/* @__PURE__ */ (0,
|
|
2707
|
-
/* @__PURE__ */ (0,
|
|
2708
|
-
/* @__PURE__ */ (0,
|
|
2709
|
-
/* @__PURE__ */ (0,
|
|
2963
|
+
/* @__PURE__ */ (0, import_jsx_runtime9.jsx)("div", { className: "hsk-sp-mobile-similar-carousel-img", children: r.entity.images?.[0] ? /* @__PURE__ */ (0, import_jsx_runtime9.jsx)("img", { src: r.entity.images[0], alt: r.entity.name }) : /* @__PURE__ */ (0, import_jsx_runtime9.jsx)("span", { children: "\xF0\u0178\u203A\x8D" }) }),
|
|
2964
|
+
/* @__PURE__ */ (0, import_jsx_runtime9.jsxs)("div", { className: "hsk-sp-mobile-similar-carousel-meta", children: [
|
|
2965
|
+
/* @__PURE__ */ (0, import_jsx_runtime9.jsx)("div", { className: "hsk-sp-mobile-similar-carousel-name", title: r.entity.name, children: r.entity.name }),
|
|
2966
|
+
/* @__PURE__ */ (0, import_jsx_runtime9.jsxs)("div", { className: "hsk-sp-mobile-similar-carousel-price", children: [
|
|
2710
2967
|
currency,
|
|
2711
2968
|
" ",
|
|
2712
2969
|
price.toLocaleString()
|
|
@@ -2723,19 +2980,19 @@ Question: ${q}`;
|
|
|
2723
2980
|
] })
|
|
2724
2981
|
] }) }, idx);
|
|
2725
2982
|
}),
|
|
2726
|
-
chatLoading && /* @__PURE__ */ (0,
|
|
2727
|
-
/* @__PURE__ */ (0,
|
|
2728
|
-
/* @__PURE__ */ (0,
|
|
2729
|
-
/* @__PURE__ */ (0,
|
|
2730
|
-
/* @__PURE__ */ (0,
|
|
2731
|
-
/* @__PURE__ */ (0,
|
|
2983
|
+
chatLoading && /* @__PURE__ */ (0, import_jsx_runtime9.jsxs)("div", { className: "hsk-cb-typing-row", children: [
|
|
2984
|
+
/* @__PURE__ */ (0, import_jsx_runtime9.jsx)("div", { className: "hsk-cb-ai-icon", style: { display: "flex", alignItems: "center" }, children: /* @__PURE__ */ (0, import_jsx_runtime9.jsx)(SparkleIcon3, {}) }),
|
|
2985
|
+
/* @__PURE__ */ (0, import_jsx_runtime9.jsxs)("div", { className: "hsk-cb-typing", children: [
|
|
2986
|
+
/* @__PURE__ */ (0, import_jsx_runtime9.jsx)("div", { className: "hsk-cb-dot" }),
|
|
2987
|
+
/* @__PURE__ */ (0, import_jsx_runtime9.jsx)("div", { className: "hsk-cb-dot" }),
|
|
2988
|
+
/* @__PURE__ */ (0, import_jsx_runtime9.jsx)("div", { className: "hsk-cb-dot" })
|
|
2732
2989
|
] })
|
|
2733
2990
|
] }),
|
|
2734
|
-
chatError && /* @__PURE__ */ (0,
|
|
2735
|
-
/* @__PURE__ */ (0,
|
|
2991
|
+
chatError && /* @__PURE__ */ (0, import_jsx_runtime9.jsx)("div", { className: "hsk-cb-error", children: getFriendlyError2(chatError) }),
|
|
2992
|
+
/* @__PURE__ */ (0, import_jsx_runtime9.jsx)("div", { ref: chatBottomRef, style: { height: 1 } })
|
|
2736
2993
|
] }),
|
|
2737
|
-
/* @__PURE__ */ (0,
|
|
2738
|
-
/* @__PURE__ */ (0,
|
|
2994
|
+
/* @__PURE__ */ (0, import_jsx_runtime9.jsx)("div", { className: "hsk-cb-input-wrap", children: /* @__PURE__ */ (0, import_jsx_runtime9.jsxs)("div", { className: "hsk-cb-input-box", children: [
|
|
2995
|
+
/* @__PURE__ */ (0, import_jsx_runtime9.jsx)(
|
|
2739
2996
|
"textarea",
|
|
2740
2997
|
{
|
|
2741
2998
|
ref: chatTextareaRef,
|
|
@@ -2748,34 +3005,34 @@ Question: ${q}`;
|
|
|
2748
3005
|
disabled: chatLoading
|
|
2749
3006
|
}
|
|
2750
3007
|
),
|
|
2751
|
-
/* @__PURE__ */ (0,
|
|
3008
|
+
/* @__PURE__ */ (0, import_jsx_runtime9.jsx)(
|
|
2752
3009
|
"button",
|
|
2753
3010
|
{
|
|
2754
3011
|
className: "hsk-cb-send",
|
|
2755
3012
|
onClick: () => handleSend(),
|
|
2756
3013
|
disabled: !chatInput.trim() || chatLoading,
|
|
2757
3014
|
"aria-label": "Send message",
|
|
2758
|
-
children: /* @__PURE__ */ (0,
|
|
3015
|
+
children: /* @__PURE__ */ (0, import_jsx_runtime9.jsx)(ArrowUpIcon3, {})
|
|
2759
3016
|
}
|
|
2760
3017
|
)
|
|
2761
3018
|
] }) })
|
|
2762
3019
|
] }),
|
|
2763
|
-
showSpecs && displayProduct && /* @__PURE__ */ (0,
|
|
2764
|
-
/* @__PURE__ */ (0,
|
|
2765
|
-
/* @__PURE__ */ (0,
|
|
2766
|
-
/* @__PURE__ */ (0,
|
|
3020
|
+
showSpecs && displayProduct && /* @__PURE__ */ (0, import_jsx_runtime9.jsx)("div", { className: "hsk-sp-mobile-specs-overlay", onClick: () => setShowSpecs(false), children: /* @__PURE__ */ (0, import_jsx_runtime9.jsxs)("div", { className: "hsk-sp-mobile-specs-drawer", onClick: (e) => e.stopPropagation(), children: [
|
|
3021
|
+
/* @__PURE__ */ (0, import_jsx_runtime9.jsxs)("div", { className: "hsk-sp-mobile-specs-header", children: [
|
|
3022
|
+
/* @__PURE__ */ (0, import_jsx_runtime9.jsx)("h3", { children: "Specifications" }),
|
|
3023
|
+
/* @__PURE__ */ (0, import_jsx_runtime9.jsx)("button", { type: "button", onClick: () => setShowSpecs(false), children: "Close" })
|
|
2767
3024
|
] }),
|
|
2768
|
-
/* @__PURE__ */ (0,
|
|
2769
|
-
/* @__PURE__ */ (0,
|
|
2770
|
-
displayProduct.description && /* @__PURE__ */ (0,
|
|
2771
|
-
/* @__PURE__ */ (0,
|
|
2772
|
-
/* @__PURE__ */ (0,
|
|
3025
|
+
/* @__PURE__ */ (0, import_jsx_runtime9.jsxs)("div", { className: "hsk-sp-mobile-specs-body", children: [
|
|
3026
|
+
/* @__PURE__ */ (0, import_jsx_runtime9.jsx)("h4", { className: "hsk-sp-mobile-specs-title", children: displayProduct.name }),
|
|
3027
|
+
displayProduct.description && /* @__PURE__ */ (0, import_jsx_runtime9.jsxs)("div", { className: "hsk-sp-mobile-specs-desc", children: [
|
|
3028
|
+
/* @__PURE__ */ (0, import_jsx_runtime9.jsx)("h5", { children: "Description" }),
|
|
3029
|
+
/* @__PURE__ */ (0, import_jsx_runtime9.jsx)("p", { children: displayProduct.description })
|
|
2773
3030
|
] }),
|
|
2774
|
-
displayProduct.specs && Object.keys(displayProduct.specs).length > 0 && /* @__PURE__ */ (0,
|
|
2775
|
-
/* @__PURE__ */ (0,
|
|
2776
|
-
Object.entries(displayProduct.specs).map(([key, val]) => /* @__PURE__ */ (0,
|
|
2777
|
-
/* @__PURE__ */ (0,
|
|
2778
|
-
/* @__PURE__ */ (0,
|
|
3031
|
+
displayProduct.specs && Object.keys(displayProduct.specs).length > 0 && /* @__PURE__ */ (0, import_jsx_runtime9.jsxs)("div", { className: "hsk-sp-mobile-specs-list", children: [
|
|
3032
|
+
/* @__PURE__ */ (0, import_jsx_runtime9.jsx)("h5", { children: "Details" }),
|
|
3033
|
+
Object.entries(displayProduct.specs).map(([key, val]) => /* @__PURE__ */ (0, import_jsx_runtime9.jsxs)("div", { className: "hsk-sp-mobile-spec-row", children: [
|
|
3034
|
+
/* @__PURE__ */ (0, import_jsx_runtime9.jsx)("span", { className: "hsk-sp-mobile-spec-label", children: key }),
|
|
3035
|
+
/* @__PURE__ */ (0, import_jsx_runtime9.jsx)("span", { className: "hsk-sp-mobile-spec-value", children: val })
|
|
2779
3036
|
] }, key))
|
|
2780
3037
|
] })
|
|
2781
3038
|
] })
|
|
@@ -2784,7 +3041,7 @@ Question: ${q}`;
|
|
|
2784
3041
|
}
|
|
2785
3042
|
);
|
|
2786
3043
|
}
|
|
2787
|
-
return /* @__PURE__ */ (0,
|
|
3044
|
+
return /* @__PURE__ */ (0, import_jsx_runtime9.jsx)(
|
|
2788
3045
|
"div",
|
|
2789
3046
|
{
|
|
2790
3047
|
className: cn("hsk-sp-backdrop", classNames.backdrop),
|
|
@@ -2795,65 +3052,65 @@ Question: ${q}`;
|
|
|
2795
3052
|
background: bg ?? void 0,
|
|
2796
3053
|
...customStyles
|
|
2797
3054
|
},
|
|
2798
|
-
children: /* @__PURE__ */ (0,
|
|
2799
|
-
/* @__PURE__ */ (0,
|
|
2800
|
-
/* @__PURE__ */ (0,
|
|
2801
|
-
/* @__PURE__ */ (0,
|
|
2802
|
-
/* @__PURE__ */ (0,
|
|
2803
|
-
/* @__PURE__ */ (0,
|
|
3055
|
+
children: /* @__PURE__ */ (0, import_jsx_runtime9.jsxs)("div", { className: cn("hsk-sp-card hsk-sp-fullscreen", classNames.card), onClick: (e) => e.stopPropagation(), children: [
|
|
3056
|
+
/* @__PURE__ */ (0, import_jsx_runtime9.jsxs)("div", { className: "hsk-sp-header", children: [
|
|
3057
|
+
/* @__PURE__ */ (0, import_jsx_runtime9.jsx)("span", { className: "hsk-sp-header-icon", style: { display: "flex", alignItems: "center" }, children: /* @__PURE__ */ (0, import_jsx_runtime9.jsx)(SparkleIcon3, {}) }),
|
|
3058
|
+
/* @__PURE__ */ (0, import_jsx_runtime9.jsxs)("div", { className: "hsk-sp-header-body", children: [
|
|
3059
|
+
/* @__PURE__ */ (0, import_jsx_runtime9.jsx)("div", { className: "hsk-sp-header-title", children: displayProduct?.name || productName }),
|
|
3060
|
+
/* @__PURE__ */ (0, import_jsx_runtime9.jsx)("div", { className: "hsk-sp-header-sub", children: "Ask questions, compare specs, or check similar products" })
|
|
2804
3061
|
] }),
|
|
2805
|
-
/* @__PURE__ */ (0,
|
|
3062
|
+
/* @__PURE__ */ (0, import_jsx_runtime9.jsx)("button", { className: "hsk-sp-close", onClick: onClose, "aria-label": "Close", children: /* @__PURE__ */ (0, import_jsx_runtime9.jsx)(CloseIcon2, {}) })
|
|
2806
3063
|
] }),
|
|
2807
|
-
searchLoading && /* @__PURE__ */ (0,
|
|
2808
|
-
/* @__PURE__ */ (0,
|
|
2809
|
-
/* @__PURE__ */ (0,
|
|
2810
|
-
displayProduct && /* @__PURE__ */ (0,
|
|
2811
|
-
/* @__PURE__ */ (0,
|
|
2812
|
-
/* @__PURE__ */ (0,
|
|
2813
|
-
/* @__PURE__ */ (0,
|
|
2814
|
-
displayProduct.brand && /* @__PURE__ */ (0,
|
|
2815
|
-
displayProduct.category && /* @__PURE__ */ (0,
|
|
2816
|
-
/* @__PURE__ */ (0,
|
|
2817
|
-
/* @__PURE__ */ (0,
|
|
2818
|
-
/* @__PURE__ */ (0,
|
|
2819
|
-
/* @__PURE__ */ (0,
|
|
2820
|
-
displayProduct.originalPrice && /* @__PURE__ */ (0,
|
|
2821
|
-
displayProduct.discount && /* @__PURE__ */ (0,
|
|
3064
|
+
searchLoading && /* @__PURE__ */ (0, import_jsx_runtime9.jsx)("div", { className: "hsk-sp-bar" }),
|
|
3065
|
+
/* @__PURE__ */ (0, import_jsx_runtime9.jsxs)("div", { className: "hsk-sp-body", children: [
|
|
3066
|
+
/* @__PURE__ */ (0, import_jsx_runtime9.jsxs)("div", { className: "hsk-sp-details-pane", children: [
|
|
3067
|
+
displayProduct && /* @__PURE__ */ (0, import_jsx_runtime9.jsxs)("div", { className: "hsk-sp-product-profile-container", children: [
|
|
3068
|
+
/* @__PURE__ */ (0, import_jsx_runtime9.jsxs)("div", { className: "hsk-sp-product-profile", children: [
|
|
3069
|
+
/* @__PURE__ */ (0, import_jsx_runtime9.jsx)("div", { className: "hsk-sp-details-imgwrap", children: displayProduct.images?.[0] ? /* @__PURE__ */ (0, import_jsx_runtime9.jsx)("img", { src: displayProduct.images[0], alt: displayProduct.name }) : /* @__PURE__ */ (0, import_jsx_runtime9.jsx)("span", { className: "hsk-sp-img-placeholder", children: "\xF0\u0178\u203A\x8D" }) }),
|
|
3070
|
+
/* @__PURE__ */ (0, import_jsx_runtime9.jsxs)("div", { className: "hsk-sp-details-meta", children: [
|
|
3071
|
+
displayProduct.brand && /* @__PURE__ */ (0, import_jsx_runtime9.jsx)("span", { className: "hsk-sp-item-brand", children: displayProduct.brand }),
|
|
3072
|
+
displayProduct.category && /* @__PURE__ */ (0, import_jsx_runtime9.jsx)("span", { className: "hsk-sp-item-cat", children: displayProduct.category }),
|
|
3073
|
+
/* @__PURE__ */ (0, import_jsx_runtime9.jsx)("h2", { className: "hsk-sp-details-name", children: displayProduct.name }),
|
|
3074
|
+
/* @__PURE__ */ (0, import_jsx_runtime9.jsxs)("div", { className: "hsk-sp-item-price-row", children: [
|
|
3075
|
+
/* @__PURE__ */ (0, import_jsx_runtime9.jsx)("span", { className: "hsk-sp-item-currency", children: displayProduct.currency ?? "KES" }),
|
|
3076
|
+
/* @__PURE__ */ (0, import_jsx_runtime9.jsx)("span", { className: "hsk-sp-item-price", children: parseFloat(displayProduct.price?.replace(/[^0-9.]/g, "") || "0").toLocaleString() }),
|
|
3077
|
+
displayProduct.originalPrice && /* @__PURE__ */ (0, import_jsx_runtime9.jsx)("span", { className: "hsk-sp-item-original-price", children: parseFloat(displayProduct.originalPrice.replace(/[^0-9.]/g, "") || "0").toLocaleString() }),
|
|
3078
|
+
displayProduct.discount && /* @__PURE__ */ (0, import_jsx_runtime9.jsxs)("span", { className: "hsk-sp-item-discount", children: [
|
|
2822
3079
|
"(",
|
|
2823
3080
|
displayProduct.discount,
|
|
2824
3081
|
")"
|
|
2825
3082
|
] })
|
|
2826
3083
|
] }),
|
|
2827
|
-
/* @__PURE__ */ (0,
|
|
2828
|
-
displayProduct.rating && /* @__PURE__ */ (0,
|
|
3084
|
+
/* @__PURE__ */ (0, import_jsx_runtime9.jsxs)("div", { className: "hsk-sp-item-meta-badges", children: [
|
|
3085
|
+
displayProduct.rating && /* @__PURE__ */ (0, import_jsx_runtime9.jsxs)("span", { className: "hsk-sp-meta-badge hsk-sp-meta-badge-rating", children: [
|
|
2829
3086
|
"\xE2\u02DC\u2026 ",
|
|
2830
3087
|
parseFloat(displayProduct.rating.toString()).toFixed(1),
|
|
2831
3088
|
" ",
|
|
2832
3089
|
displayProduct.reviewCount ? `(${displayProduct.reviewCount})` : ""
|
|
2833
3090
|
] }),
|
|
2834
|
-
displayProduct.availability && /* @__PURE__ */ (0,
|
|
2835
|
-
displayProduct.stock && !displayProduct.availability && /* @__PURE__ */ (0,
|
|
3091
|
+
displayProduct.availability && /* @__PURE__ */ (0, import_jsx_runtime9.jsx)("span", { className: `hsk-sp-meta-badge hsk-sp-meta-badge-avail ${displayProduct.availability.toLowerCase().includes("in") ? "in-stock" : "out-stock"}`, children: displayProduct.availability }),
|
|
3092
|
+
displayProduct.stock && !displayProduct.availability && /* @__PURE__ */ (0, import_jsx_runtime9.jsxs)("span", { className: "hsk-sp-meta-badge hsk-sp-meta-badge-stock", children: [
|
|
2836
3093
|
"Stock: ",
|
|
2837
3094
|
displayProduct.stock
|
|
2838
3095
|
] })
|
|
2839
3096
|
] })
|
|
2840
3097
|
] })
|
|
2841
3098
|
] }),
|
|
2842
|
-
displayProduct.specs && Object.keys(displayProduct.specs).length > 0 && /* @__PURE__ */ (0,
|
|
2843
|
-
/* @__PURE__ */ (0,
|
|
3099
|
+
displayProduct.specs && Object.keys(displayProduct.specs).length > 0 && /* @__PURE__ */ (0, import_jsx_runtime9.jsx)("div", { className: "hsk-sp-specs-horizontal", children: Object.entries(displayProduct.specs).map(([key, val]) => /* @__PURE__ */ (0, import_jsx_runtime9.jsxs)("div", { className: "hsk-sp-spec-item-horizontal", children: [
|
|
3100
|
+
/* @__PURE__ */ (0, import_jsx_runtime9.jsxs)("span", { className: "hsk-sp-spec-label-horizontal", children: [
|
|
2844
3101
|
key,
|
|
2845
3102
|
":"
|
|
2846
3103
|
] }),
|
|
2847
|
-
/* @__PURE__ */ (0,
|
|
3104
|
+
/* @__PURE__ */ (0, import_jsx_runtime9.jsx)("span", { className: "hsk-sp-spec-value-horizontal", title: val, children: val })
|
|
2848
3105
|
] }, key)) }),
|
|
2849
|
-
displayProduct.description && /* @__PURE__ */ (0,
|
|
2850
|
-
/* @__PURE__ */ (0,
|
|
2851
|
-
/* @__PURE__ */ (0,
|
|
3106
|
+
displayProduct.description && /* @__PURE__ */ (0, import_jsx_runtime9.jsxs)("div", { className: "hsk-sp-details-desc", children: [
|
|
3107
|
+
/* @__PURE__ */ (0, import_jsx_runtime9.jsx)("h4", { children: "Description" }),
|
|
3108
|
+
/* @__PURE__ */ (0, import_jsx_runtime9.jsx)("p", { children: displayProduct.description })
|
|
2852
3109
|
] })
|
|
2853
3110
|
] }),
|
|
2854
|
-
/* @__PURE__ */ (0,
|
|
2855
|
-
/* @__PURE__ */ (0,
|
|
2856
|
-
/* @__PURE__ */ (0,
|
|
3111
|
+
/* @__PURE__ */ (0, import_jsx_runtime9.jsxs)("div", { className: "hsk-sp-similar-section", children: [
|
|
3112
|
+
/* @__PURE__ */ (0, import_jsx_runtime9.jsx)("h3", { children: "Similar Products" }),
|
|
3113
|
+
/* @__PURE__ */ (0, import_jsx_runtime9.jsx)("div", { className: "hsk-sp-results", children: (() => {
|
|
2857
3114
|
const similarProducts = results.filter(
|
|
2858
3115
|
(r) => {
|
|
2859
3116
|
const isSameName = !!(r.entity.name && displayProduct?.name && r.entity.name.toLowerCase() === displayProduct.name.toLowerCase());
|
|
@@ -2862,29 +3119,29 @@ Question: ${q}`;
|
|
|
2862
3119
|
}
|
|
2863
3120
|
);
|
|
2864
3121
|
if (!searchLoading && similarProducts.length === 0) {
|
|
2865
|
-
return /* @__PURE__ */ (0,
|
|
3122
|
+
return /* @__PURE__ */ (0, import_jsx_runtime9.jsx)("div", { className: "hsk-sp-empty", children: "No similar products found." });
|
|
2866
3123
|
}
|
|
2867
3124
|
return similarProducts.map((r, i) => {
|
|
2868
3125
|
const price = parseFloat(r.entity.price?.replace(/[^0-9.]/g, "") || "0");
|
|
2869
3126
|
const currency = r.entity.currency ?? "KES";
|
|
2870
|
-
return /* @__PURE__ */ (0,
|
|
3127
|
+
return /* @__PURE__ */ (0, import_jsx_runtime9.jsxs)(
|
|
2871
3128
|
"div",
|
|
2872
3129
|
{
|
|
2873
3130
|
className: cn("hsk-sp-item", classNames.item),
|
|
2874
3131
|
style: { animationDelay: `${i * 55}ms`, cursor: "pointer" },
|
|
2875
3132
|
onClick: () => handleNav(r),
|
|
2876
3133
|
children: [
|
|
2877
|
-
/* @__PURE__ */ (0,
|
|
2878
|
-
/* @__PURE__ */ (0,
|
|
2879
|
-
/* @__PURE__ */ (0,
|
|
2880
|
-
r.entity.category && /* @__PURE__ */ (0,
|
|
2881
|
-
/* @__PURE__ */ (0,
|
|
3134
|
+
/* @__PURE__ */ (0, import_jsx_runtime9.jsx)("div", { className: "hsk-sp-img-wrap", children: r.entity.images?.[0] ? /* @__PURE__ */ (0, import_jsx_runtime9.jsx)("img", { src: r.entity.images[0], alt: r.entity.name }) : /* @__PURE__ */ (0, import_jsx_runtime9.jsx)("span", { className: "hsk-sp-img-placeholder", children: "\xF0\u0178\u203A\x8D" }) }),
|
|
3135
|
+
/* @__PURE__ */ (0, import_jsx_runtime9.jsxs)("div", { className: "hsk-sp-item-body", children: [
|
|
3136
|
+
/* @__PURE__ */ (0, import_jsx_runtime9.jsxs)("div", { children: [
|
|
3137
|
+
r.entity.category && /* @__PURE__ */ (0, import_jsx_runtime9.jsx)("div", { className: "hsk-sp-item-cat", children: r.entity.category }),
|
|
3138
|
+
/* @__PURE__ */ (0, import_jsx_runtime9.jsx)("div", { className: "hsk-sp-item-name", title: r.entity.name, children: r.entity.name })
|
|
2882
3139
|
] }),
|
|
2883
|
-
/* @__PURE__ */ (0,
|
|
2884
|
-
/* @__PURE__ */ (0,
|
|
2885
|
-
/* @__PURE__ */ (0,
|
|
3140
|
+
/* @__PURE__ */ (0, import_jsx_runtime9.jsxs)("div", { className: "hsk-sp-item-price-row", children: [
|
|
3141
|
+
/* @__PURE__ */ (0, import_jsx_runtime9.jsx)("span", { className: "hsk-sp-item-currency", children: currency }),
|
|
3142
|
+
/* @__PURE__ */ (0, import_jsx_runtime9.jsx)("span", { className: "hsk-sp-item-price", children: price.toLocaleString() })
|
|
2886
3143
|
] }),
|
|
2887
|
-
/* @__PURE__ */ (0,
|
|
3144
|
+
/* @__PURE__ */ (0, import_jsx_runtime9.jsx)("div", { className: "hsk-sp-actions", children: /* @__PURE__ */ (0, import_jsx_runtime9.jsx)(
|
|
2888
3145
|
"button",
|
|
2889
3146
|
{
|
|
2890
3147
|
className: "hsk-sp-action hsk-sp-action-primary",
|
|
@@ -2904,29 +3161,29 @@ Question: ${q}`;
|
|
|
2904
3161
|
})() })
|
|
2905
3162
|
] })
|
|
2906
3163
|
] }),
|
|
2907
|
-
/* @__PURE__ */ (0,
|
|
2908
|
-
/* @__PURE__ */ (0,
|
|
3164
|
+
/* @__PURE__ */ (0, import_jsx_runtime9.jsxs)("div", { className: "hsk-sp-chat-pane", children: [
|
|
3165
|
+
/* @__PURE__ */ (0, import_jsx_runtime9.jsxs)("div", { className: "hsk-cb-msgs", children: [
|
|
2909
3166
|
displayMessages.map((msg, idx) => {
|
|
2910
3167
|
const isUser = msg.role === "user";
|
|
2911
|
-
return /* @__PURE__ */ (0,
|
|
2912
|
-
/* @__PURE__ */ (0,
|
|
2913
|
-
/* @__PURE__ */ (0,
|
|
3168
|
+
return /* @__PURE__ */ (0, import_jsx_runtime9.jsx)("div", { className: "hsk-cb-msg-group", children: isUser ? /* @__PURE__ */ (0, import_jsx_runtime9.jsx)("div", { className: "hsk-cb-user-msg", children: /* @__PURE__ */ (0, import_jsx_runtime9.jsx)("div", { className: "hsk-cb-user-bubble", children: msg.content }) }) : /* @__PURE__ */ (0, import_jsx_runtime9.jsxs)("div", { className: "hsk-cb-ai-msg", children: [
|
|
3169
|
+
/* @__PURE__ */ (0, import_jsx_runtime9.jsx)("div", { className: "hsk-cb-ai-icon", style: { display: "flex", alignItems: "center" }, children: /* @__PURE__ */ (0, import_jsx_runtime9.jsx)(SparkleIcon3, {}) }),
|
|
3170
|
+
/* @__PURE__ */ (0, import_jsx_runtime9.jsx)("div", { className: "hsk-cb-ai-body", children: /* @__PURE__ */ (0, import_jsx_runtime9.jsx)("div", { className: "hsk-cb-ai-text", children: renderMarkdown(msg.content) }) })
|
|
2914
3171
|
] }) }, idx);
|
|
2915
3172
|
}),
|
|
2916
|
-
chatLoading && /* @__PURE__ */ (0,
|
|
2917
|
-
/* @__PURE__ */ (0,
|
|
2918
|
-
/* @__PURE__ */ (0,
|
|
2919
|
-
/* @__PURE__ */ (0,
|
|
2920
|
-
/* @__PURE__ */ (0,
|
|
2921
|
-
/* @__PURE__ */ (0,
|
|
3173
|
+
chatLoading && /* @__PURE__ */ (0, import_jsx_runtime9.jsxs)("div", { className: "hsk-cb-typing-row", children: [
|
|
3174
|
+
/* @__PURE__ */ (0, import_jsx_runtime9.jsx)("div", { className: "hsk-cb-ai-icon", style: { display: "flex", alignItems: "center" }, children: /* @__PURE__ */ (0, import_jsx_runtime9.jsx)(SparkleIcon3, {}) }),
|
|
3175
|
+
/* @__PURE__ */ (0, import_jsx_runtime9.jsxs)("div", { className: "hsk-cb-typing", children: [
|
|
3176
|
+
/* @__PURE__ */ (0, import_jsx_runtime9.jsx)("div", { className: "hsk-cb-dot" }),
|
|
3177
|
+
/* @__PURE__ */ (0, import_jsx_runtime9.jsx)("div", { className: "hsk-cb-dot" }),
|
|
3178
|
+
/* @__PURE__ */ (0, import_jsx_runtime9.jsx)("div", { className: "hsk-cb-dot" })
|
|
2922
3179
|
] })
|
|
2923
3180
|
] }),
|
|
2924
|
-
chatError && /* @__PURE__ */ (0,
|
|
2925
|
-
/* @__PURE__ */ (0,
|
|
3181
|
+
chatError && /* @__PURE__ */ (0, import_jsx_runtime9.jsx)("div", { className: "hsk-cb-error", children: getFriendlyError2(chatError) }),
|
|
3182
|
+
/* @__PURE__ */ (0, import_jsx_runtime9.jsx)("div", { ref: chatBottomRef, style: { height: 1 } })
|
|
2926
3183
|
] }),
|
|
2927
|
-
/* @__PURE__ */ (0,
|
|
2928
|
-
/* @__PURE__ */ (0,
|
|
2929
|
-
/* @__PURE__ */ (0,
|
|
3184
|
+
/* @__PURE__ */ (0, import_jsx_runtime9.jsxs)("div", { className: "hsk-cb-input-wrap", children: [
|
|
3185
|
+
/* @__PURE__ */ (0, import_jsx_runtime9.jsxs)("div", { className: "hsk-cb-input-box", children: [
|
|
3186
|
+
/* @__PURE__ */ (0, import_jsx_runtime9.jsx)(
|
|
2930
3187
|
"textarea",
|
|
2931
3188
|
{
|
|
2932
3189
|
ref: chatTextareaRef,
|
|
@@ -2939,22 +3196,22 @@ Question: ${q}`;
|
|
|
2939
3196
|
disabled: chatLoading
|
|
2940
3197
|
}
|
|
2941
3198
|
),
|
|
2942
|
-
/* @__PURE__ */ (0,
|
|
3199
|
+
/* @__PURE__ */ (0, import_jsx_runtime9.jsx)(
|
|
2943
3200
|
"button",
|
|
2944
3201
|
{
|
|
2945
3202
|
className: "hsk-cb-send",
|
|
2946
3203
|
onClick: () => handleSend(),
|
|
2947
3204
|
disabled: !chatInput.trim() || chatLoading,
|
|
2948
3205
|
"aria-label": "Send message",
|
|
2949
|
-
children: /* @__PURE__ */ (0,
|
|
3206
|
+
children: /* @__PURE__ */ (0, import_jsx_runtime9.jsx)(ArrowUpIcon3, {})
|
|
2950
3207
|
}
|
|
2951
3208
|
)
|
|
2952
3209
|
] }),
|
|
2953
|
-
/* @__PURE__ */ (0,
|
|
3210
|
+
/* @__PURE__ */ (0, import_jsx_runtime9.jsx)("div", { className: "hsk-cb-hint", children: "Akropolys \xB7 instant product knowledge" })
|
|
2954
3211
|
] })
|
|
2955
3212
|
] })
|
|
2956
3213
|
] }),
|
|
2957
|
-
/* @__PURE__ */ (0,
|
|
3214
|
+
/* @__PURE__ */ (0, import_jsx_runtime9.jsx)("div", { className: "hsk-sp-footer", children: /* @__PURE__ */ (0, import_jsx_runtime9.jsx)("span", { className: "hsk-sp-esc", children: "Esc to close" }) })
|
|
2958
3215
|
] })
|
|
2959
3216
|
}
|
|
2960
3217
|
);
|
|
@@ -2972,9 +3229,9 @@ function Sparkle({
|
|
|
2972
3229
|
product,
|
|
2973
3230
|
children
|
|
2974
3231
|
}) {
|
|
2975
|
-
const [open, setOpen] = (0,
|
|
2976
|
-
const [mounted, setMounted] = (0,
|
|
2977
|
-
(0,
|
|
3232
|
+
const [open, setOpen] = (0, import_react7.useState)(false);
|
|
3233
|
+
const [mounted, setMounted] = (0, import_react7.useState)(false);
|
|
3234
|
+
(0, import_react7.useEffect)(() => {
|
|
2978
3235
|
setMounted(true);
|
|
2979
3236
|
}, []);
|
|
2980
3237
|
const customStyles = {
|
|
@@ -2984,8 +3241,8 @@ function Sparkle({
|
|
|
2984
3241
|
...theme?.fontFamily && { "--hsk-font": theme.fontFamily },
|
|
2985
3242
|
...theme?.borderRadius && { "--hsk-border-radius": theme.borderRadius }
|
|
2986
3243
|
};
|
|
2987
|
-
return /* @__PURE__ */ (0,
|
|
2988
|
-
/* @__PURE__ */ (0,
|
|
3244
|
+
return /* @__PURE__ */ (0, import_jsx_runtime9.jsxs)(import_jsx_runtime9.Fragment, { children: [
|
|
3245
|
+
/* @__PURE__ */ (0, import_jsx_runtime9.jsx)(
|
|
2989
3246
|
"button",
|
|
2990
3247
|
{
|
|
2991
3248
|
className: cn("hsk-sp-btn", classNames.button, className),
|
|
@@ -2993,11 +3250,11 @@ function Sparkle({
|
|
|
2993
3250
|
style: customStyles,
|
|
2994
3251
|
title: "Find similar products",
|
|
2995
3252
|
"aria-label": "Find similar products",
|
|
2996
|
-
children: children || /* @__PURE__ */ (0,
|
|
3253
|
+
children: children || /* @__PURE__ */ (0, import_jsx_runtime9.jsx)(SparkleIcon3, {})
|
|
2997
3254
|
}
|
|
2998
3255
|
),
|
|
2999
3256
|
open && mounted && (0, import_react_dom2.createPortal)(
|
|
3000
|
-
/* @__PURE__ */ (0,
|
|
3257
|
+
/* @__PURE__ */ (0, import_jsx_runtime9.jsx)(
|
|
3001
3258
|
SparkleModal,
|
|
3002
3259
|
{
|
|
3003
3260
|
productName,
|