@akropolys/kiku 1.7.8 → 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 +660 -425
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +652 -417
- package/dist/index.mjs.map +1 -1
- package/dist/styles.css +195 -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,20 +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
|
-
isComplete ? /* @__PURE__ */ (0,
|
|
1643
|
-
/* @__PURE__ */ (0,
|
|
1644
|
-
/* @__PURE__ */ (0,
|
|
1645
|
-
] }) : /* @__PURE__ */ (0,
|
|
1646
|
-
/* @__PURE__ */ (0,
|
|
1647
|
-
/* @__PURE__ */ (0,
|
|
1648
|
-
/* @__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", {})
|
|
1649
1866
|
] }),
|
|
1650
|
-
/* @__PURE__ */ (0,
|
|
1651
|
-
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" })
|
|
1652
1869
|
]
|
|
1653
1870
|
}
|
|
1654
1871
|
),
|
|
1655
|
-
expandable && isOpen && /* @__PURE__ */ (0,
|
|
1872
|
+
expandable && isOpen && /* @__PURE__ */ (0, import_jsx_runtime8.jsx)("div", { className: "hsk-cb-think-body", children: text })
|
|
1656
1873
|
] });
|
|
1657
1874
|
}
|
|
1658
1875
|
function ChatModal({
|
|
@@ -1673,18 +1890,18 @@ function ChatModal({
|
|
|
1673
1890
|
}) {
|
|
1674
1891
|
const client = (0, import_sdk6.useAkropolysContext)();
|
|
1675
1892
|
const { messages, sources, loading, streaming, error, lastAction, lastIntent, send, stop, stopped, interrupted, continueGenerating, reset, referencedIds } = (0, import_sdk5.useKiku)();
|
|
1676
|
-
const [input, setInput] = (0,
|
|
1677
|
-
const [shopperName, setShopperNameState] = (0,
|
|
1893
|
+
const [input, setInput] = (0, import_react6.useState)("");
|
|
1894
|
+
const [shopperName, setShopperNameState] = (0, import_react6.useState)(() => {
|
|
1678
1895
|
try {
|
|
1679
1896
|
return client.getShopperName?.() ?? "";
|
|
1680
1897
|
} catch {
|
|
1681
1898
|
return "";
|
|
1682
1899
|
}
|
|
1683
1900
|
});
|
|
1684
|
-
const [nameSkipped, setNameSkipped] = (0,
|
|
1901
|
+
const [nameSkipped, setNameSkipped] = (0, import_react6.useState)(false);
|
|
1685
1902
|
const awaitingName = messages.length === 0 && !shopperName && !nameSkipped;
|
|
1686
|
-
const [attachments, setAttachments] = (0,
|
|
1687
|
-
const imageInputRef = (0,
|
|
1903
|
+
const [attachments, setAttachments] = (0, import_react6.useState)([]);
|
|
1904
|
+
const imageInputRef = (0, import_react6.useRef)(null);
|
|
1688
1905
|
const handleImageFiles = (files) => {
|
|
1689
1906
|
if (!files || files.length === 0) return;
|
|
1690
1907
|
Array.from(files).forEach((file) => {
|
|
@@ -1702,11 +1919,11 @@ function ChatModal({
|
|
|
1702
1919
|
const removeAttachment = (idx) => {
|
|
1703
1920
|
setAttachments((prev) => prev.filter((_, i) => i !== idx));
|
|
1704
1921
|
};
|
|
1705
|
-
const [voiceState, setVoiceState] = (0,
|
|
1706
|
-
const recognitionRef = (0,
|
|
1707
|
-
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);
|
|
1708
1925
|
const hasSpeechAPI = typeof window !== "undefined" && ("SpeechRecognition" in window || "webkitSpeechRecognition" in window);
|
|
1709
|
-
const startVoice = (0,
|
|
1926
|
+
const startVoice = (0, import_react6.useCallback)(() => {
|
|
1710
1927
|
if (!hasSpeechAPI || voiceState !== "idle") return;
|
|
1711
1928
|
const SR = window.SpeechRecognition || window.webkitSpeechRecognition;
|
|
1712
1929
|
const recognition = new SR();
|
|
@@ -1744,25 +1961,26 @@ function ChatModal({
|
|
|
1744
1961
|
};
|
|
1745
1962
|
recognition.start();
|
|
1746
1963
|
}, [hasSpeechAPI, voiceState, voiceLang]);
|
|
1747
|
-
const stopVoice = (0,
|
|
1964
|
+
const stopVoice = (0, import_react6.useCallback)(() => {
|
|
1748
1965
|
recognitionRef.current?.stop();
|
|
1749
1966
|
setVoiceState("idle");
|
|
1750
1967
|
}, []);
|
|
1751
|
-
(0,
|
|
1968
|
+
(0, import_react6.useEffect)(() => {
|
|
1752
1969
|
return () => recognitionRef.current?.abort();
|
|
1753
1970
|
}, []);
|
|
1754
1971
|
const activeChips = chips;
|
|
1755
1972
|
const activeTitle = title;
|
|
1756
1973
|
const activePlaceholder = awaitingName ? "Type your name\u2026" : placeholder;
|
|
1757
|
-
const [selectedProduct, setSelectedProduct] = (0,
|
|
1758
|
-
const [lightboxSrc, setLightboxSrc] = (0,
|
|
1759
|
-
const
|
|
1760
|
-
const
|
|
1761
|
-
const
|
|
1762
|
-
const [
|
|
1763
|
-
const [
|
|
1764
|
-
const [
|
|
1765
|
-
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);
|
|
1766
1984
|
const copyValue = (value, which) => {
|
|
1767
1985
|
try {
|
|
1768
1986
|
navigator.clipboard?.writeText(value);
|
|
@@ -1771,17 +1989,17 @@ function ChatModal({
|
|
|
1771
1989
|
setCopied(which);
|
|
1772
1990
|
setTimeout(() => setCopied((c) => c === which ? null : c), 1600);
|
|
1773
1991
|
};
|
|
1774
|
-
const [keyCountdown, setKeyCountdown] = (0,
|
|
1775
|
-
const [minting, setMinting] = (0,
|
|
1776
|
-
const [showKikuPicker, setShowKikuPicker] = (0,
|
|
1777
|
-
const [showAtPicker, setShowAtPicker] = (0,
|
|
1778
|
-
(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)(() => {
|
|
1779
1997
|
if (!lastAction) return;
|
|
1780
1998
|
if (lastAction.type === "request_kiku_key") {
|
|
1781
1999
|
setKeyPhase("prompt_key");
|
|
1782
2000
|
}
|
|
1783
2001
|
}, [lastAction]);
|
|
1784
|
-
(0,
|
|
2002
|
+
(0, import_react6.useEffect)(() => {
|
|
1785
2003
|
if (!mintedKey) return;
|
|
1786
2004
|
setKeyCountdown(KIKU_KEY_REVEAL_SECONDS);
|
|
1787
2005
|
const t = setInterval(() => {
|
|
@@ -1832,9 +2050,9 @@ function ChatModal({
|
|
|
1832
2050
|
setMinting(false);
|
|
1833
2051
|
}
|
|
1834
2052
|
};
|
|
1835
|
-
const msgsContainerRef = (0,
|
|
1836
|
-
const messageRefs = (0,
|
|
1837
|
-
(0,
|
|
2053
|
+
const msgsContainerRef = (0, import_react6.useRef)(null);
|
|
2054
|
+
const messageRefs = (0, import_react6.useRef)([]);
|
|
2055
|
+
(0, import_react6.useEffect)(() => {
|
|
1838
2056
|
const container = msgsContainerRef.current;
|
|
1839
2057
|
if (!container) return;
|
|
1840
2058
|
const lastMsg = messages[messages.length - 1];
|
|
@@ -1847,14 +2065,14 @@ function ChatModal({
|
|
|
1847
2065
|
bottomRef.current?.scrollIntoView({ behavior: "smooth" });
|
|
1848
2066
|
}
|
|
1849
2067
|
}, [messages, loading, selectedProduct]);
|
|
1850
|
-
(0,
|
|
2068
|
+
(0, import_react6.useEffect)(() => {
|
|
1851
2069
|
const prev = document.body.style.overflow;
|
|
1852
2070
|
document.body.style.overflow = "hidden";
|
|
1853
2071
|
return () => {
|
|
1854
2072
|
document.body.style.overflow = prev;
|
|
1855
2073
|
};
|
|
1856
2074
|
}, []);
|
|
1857
|
-
(0,
|
|
2075
|
+
(0, import_react6.useEffect)(() => {
|
|
1858
2076
|
const h = (e) => {
|
|
1859
2077
|
if (e.key !== "Escape") return;
|
|
1860
2078
|
if (lightboxSrc) {
|
|
@@ -1866,7 +2084,7 @@ function ChatModal({
|
|
|
1866
2084
|
document.addEventListener("keydown", h);
|
|
1867
2085
|
return () => document.removeEventListener("keydown", h);
|
|
1868
2086
|
}, [lightboxSrc, onClose]);
|
|
1869
|
-
const handleReset = (0,
|
|
2087
|
+
const handleReset = (0, import_react6.useCallback)(() => {
|
|
1870
2088
|
reset();
|
|
1871
2089
|
setKeyPhase("idle");
|
|
1872
2090
|
}, [reset]);
|
|
@@ -1920,7 +2138,7 @@ function ChatModal({
|
|
|
1920
2138
|
textareaRef.current.focus();
|
|
1921
2139
|
}
|
|
1922
2140
|
};
|
|
1923
|
-
const handleKikuCapture = (0,
|
|
2141
|
+
const handleKikuCapture = (0, import_react6.useCallback)((product) => {
|
|
1924
2142
|
const name = product.name || "";
|
|
1925
2143
|
const display = `@kiku capture${name ? " " + name : ""}`;
|
|
1926
2144
|
const q = name || "capture current page";
|
|
@@ -1930,7 +2148,7 @@ function ChatModal({
|
|
|
1930
2148
|
setAttachments([]);
|
|
1931
2149
|
send(q, display, toSend.length > 0 ? toSend : void 0, "capture");
|
|
1932
2150
|
}, [attachments, send]);
|
|
1933
|
-
const handleKikuCaptureAll = (0,
|
|
2151
|
+
const handleKikuCaptureAll = (0, import_react6.useCallback)((products) => {
|
|
1934
2152
|
const targets = products.filter((p) => p.id).map((p) => ({
|
|
1935
2153
|
name: p.name || "",
|
|
1936
2154
|
url: p.url || "",
|
|
@@ -1945,14 +2163,14 @@ function ChatModal({
|
|
|
1945
2163
|
setAttachments([]);
|
|
1946
2164
|
send(names || "capture all", display, void 0, "capture_all", targets);
|
|
1947
2165
|
}, [defaultCurrency, send]);
|
|
1948
|
-
const handleKikuViewHistory = (0,
|
|
2166
|
+
const handleKikuViewHistory = (0, import_react6.useCallback)(() => {
|
|
1949
2167
|
const display = "@kiku what have you saved?";
|
|
1950
2168
|
setInput("");
|
|
1951
2169
|
setSelectedProduct(null);
|
|
1952
2170
|
setAttachments([]);
|
|
1953
2171
|
send("show my saved items", display, void 0, "view_history");
|
|
1954
2172
|
}, [send]);
|
|
1955
|
-
const handleKikuDelete = (0,
|
|
2173
|
+
const handleKikuDelete = (0, import_react6.useCallback)(() => {
|
|
1956
2174
|
const display = "@kiku delete this";
|
|
1957
2175
|
setInput("");
|
|
1958
2176
|
setSelectedProduct(null);
|
|
@@ -1985,7 +2203,7 @@ function ChatModal({
|
|
|
1985
2203
|
t.style.height = "auto";
|
|
1986
2204
|
t.style.height = `${Math.min(t.scrollHeight, 140)}px`;
|
|
1987
2205
|
};
|
|
1988
|
-
(0,
|
|
2206
|
+
(0, import_react6.useEffect)(() => {
|
|
1989
2207
|
if (voiceState !== "processing") return;
|
|
1990
2208
|
const transcript = pendingVoiceRef.current;
|
|
1991
2209
|
if (!transcript) {
|
|
@@ -2001,7 +2219,7 @@ function ChatModal({
|
|
|
2001
2219
|
}, [voiceState]);
|
|
2002
2220
|
const blurVal = typeof backdropBlur === "number" ? `${backdropBlur}px` : backdropBlur ?? "20px";
|
|
2003
2221
|
const displayMessages = messages;
|
|
2004
|
-
return /* @__PURE__ */ (0,
|
|
2222
|
+
return /* @__PURE__ */ (0, import_jsx_runtime8.jsx)(
|
|
2005
2223
|
"div",
|
|
2006
2224
|
{
|
|
2007
2225
|
className: cn("hsk-cb-overlay", classNames.overlay),
|
|
@@ -2013,7 +2231,7 @@ function ChatModal({
|
|
|
2013
2231
|
...backdropColor ? { background: backdropColor } : {},
|
|
2014
2232
|
...customStyles
|
|
2015
2233
|
},
|
|
2016
|
-
children: /* @__PURE__ */ (0,
|
|
2234
|
+
children: /* @__PURE__ */ (0, import_jsx_runtime8.jsxs)(
|
|
2017
2235
|
"div",
|
|
2018
2236
|
{
|
|
2019
2237
|
className: cn("hsk-cb-panel", classNames.panel),
|
|
@@ -2026,48 +2244,62 @@ function ChatModal({
|
|
|
2026
2244
|
}
|
|
2027
2245
|
},
|
|
2028
2246
|
children: [
|
|
2029
|
-
lightboxSrc && /* @__PURE__ */ (0,
|
|
2030
|
-
/* @__PURE__ */ (0,
|
|
2031
|
-
/* @__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() })
|
|
2032
2250
|
] }),
|
|
2033
|
-
/* @__PURE__ */ (0,
|
|
2034
|
-
|
|
2035
|
-
|
|
2036
|
-
|
|
2037
|
-
|
|
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 }) })
|
|
2038
2270
|
] }),
|
|
2039
|
-
/* @__PURE__ */ (0,
|
|
2040
|
-
messages.length > 0 && /* @__PURE__ */ (0,
|
|
2041
|
-
/* @__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, {}) })
|
|
2042
2274
|
] })
|
|
2043
2275
|
] }),
|
|
2044
|
-
/* @__PURE__ */ (0,
|
|
2045
|
-
displayMessages.length === 0 ? /* @__PURE__ */ (0,
|
|
2046
|
-
awaitingName ? /* @__PURE__ */ (0,
|
|
2047
|
-
/* @__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: [
|
|
2048
2280
|
"Hi, I'm ",
|
|
2049
|
-
/* @__PURE__ */ (0,
|
|
2281
|
+
/* @__PURE__ */ (0, import_jsx_runtime8.jsx)("b", { children: "kiku" }),
|
|
2050
2282
|
"."
|
|
2051
2283
|
] }),
|
|
2052
|
-
/* @__PURE__ */ (0,
|
|
2053
|
-
/* @__PURE__ */ (0,
|
|
2054
|
-
/* @__PURE__ */ (0,
|
|
2055
|
-
] }) : shopperName ? /* @__PURE__ */ (0,
|
|
2056
|
-
/* @__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: [
|
|
2057
2289
|
"Hi, ",
|
|
2058
2290
|
shopperName,
|
|
2059
2291
|
"."
|
|
2060
2292
|
] }),
|
|
2061
|
-
/* @__PURE__ */ (0,
|
|
2062
|
-
] }) : /* @__PURE__ */ (0,
|
|
2063
|
-
/* @__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: [
|
|
2064
2296
|
"Hi, I'm ",
|
|
2065
|
-
/* @__PURE__ */ (0,
|
|
2297
|
+
/* @__PURE__ */ (0, import_jsx_runtime8.jsx)("b", { children: "kiku" }),
|
|
2066
2298
|
"."
|
|
2067
2299
|
] }),
|
|
2068
|
-
/* @__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." })
|
|
2069
2301
|
] }),
|
|
2070
|
-
!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)(
|
|
2071
2303
|
"button",
|
|
2072
2304
|
{
|
|
2073
2305
|
className: "hsk-cb-chip",
|
|
@@ -2083,36 +2315,36 @@ function ChatModal({
|
|
|
2083
2315
|
const compareSources = sources.filter((s) => s.id && referencedIds.includes(s.id));
|
|
2084
2316
|
const showMatrix = isLast && lastIntent === "compare" && compareSources.length >= 2;
|
|
2085
2317
|
const displayContent = !isUser && showMatrix ? stripMarkdownTables(msg.content) : msg.content;
|
|
2086
|
-
return /* @__PURE__ */ (0,
|
|
2318
|
+
return /* @__PURE__ */ (0, import_jsx_runtime8.jsx)("div", { className: "hsk-cb-msg-group", ref: (el) => {
|
|
2087
2319
|
messageRefs.current[idx] = el;
|
|
2088
|
-
}, children: isUser ? /* @__PURE__ */ (0,
|
|
2089
|
-
msg.images && msg.images.length > 0 && /* @__PURE__ */ (0,
|
|
2090
|
-
msg.content && /* @__PURE__ */ (0,
|
|
2091
|
-
/* @__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" }),
|
|
2092
2324
|
msg.content.replace(/^@kiku\s*/i, "")
|
|
2093
2325
|
] }) : msg.content })
|
|
2094
|
-
] }) : /* @__PURE__ */ (0,
|
|
2095
|
-
/* @__PURE__ */ (0,
|
|
2096
|
-
/* @__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: [
|
|
2097
2329
|
(() => {
|
|
2098
2330
|
const parsed = parseThinking(displayContent);
|
|
2099
2331
|
const thinking = msg.thinking || parsed.thinking;
|
|
2100
2332
|
const content = parsed.content;
|
|
2101
2333
|
const isComplete = msg.thinking ? content.length > 0 || !(isLast && streaming) : parsed.isComplete;
|
|
2102
|
-
return /* @__PURE__ */ (0,
|
|
2103
|
-
(thinking || msg.thoughtForSeconds != null) && /* @__PURE__ */ (0,
|
|
2104
|
-
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: [
|
|
2105
2337
|
renderMarkdown(content, isLast && streaming),
|
|
2106
|
-
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" } })
|
|
2107
2339
|
] })
|
|
2108
2340
|
] });
|
|
2109
2341
|
})(),
|
|
2110
|
-
msg.visualizing && /* @__PURE__ */ (0,
|
|
2111
|
-
/* @__PURE__ */ (0,
|
|
2112
|
-
/* @__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" })
|
|
2113
2345
|
] }),
|
|
2114
|
-
msg.visualization && /* @__PURE__ */ (0,
|
|
2115
|
-
/* @__PURE__ */ (0,
|
|
2346
|
+
msg.visualization && /* @__PURE__ */ (0, import_jsx_runtime8.jsxs)("div", { className: "hsk-cb-viz", children: [
|
|
2347
|
+
/* @__PURE__ */ (0, import_jsx_runtime8.jsx)(
|
|
2116
2348
|
"img",
|
|
2117
2349
|
{
|
|
2118
2350
|
src: msg.visualization,
|
|
@@ -2123,10 +2355,13 @@ function ChatModal({
|
|
|
2123
2355
|
}
|
|
2124
2356
|
}
|
|
2125
2357
|
),
|
|
2126
|
-
/* @__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
|
+
] })
|
|
2127
2362
|
] }),
|
|
2128
|
-
!isUser && (msg.knowledgeImages?.length ?? 0) > 0 && /* @__PURE__ */ (0,
|
|
2129
|
-
/* @__PURE__ */ (0,
|
|
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)(
|
|
2130
2365
|
"img",
|
|
2131
2366
|
{
|
|
2132
2367
|
src: img.url,
|
|
@@ -2140,16 +2375,16 @@ function ChatModal({
|
|
|
2140
2375
|
},
|
|
2141
2376
|
i
|
|
2142
2377
|
)) }),
|
|
2143
|
-
(ref.title || ref.images[0]?.note) && /* @__PURE__ */ (0,
|
|
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 })
|
|
2144
2379
|
] }, ref.entryId)) }),
|
|
2145
|
-
showMatrix && /* @__PURE__ */ (0,
|
|
2380
|
+
showMatrix && /* @__PURE__ */ (0, import_jsx_runtime8.jsx)(ComparisonMatrix, { sources: compareSources, defaultCurrency }),
|
|
2146
2381
|
(() => {
|
|
2147
2382
|
const msgReferencedIds = isLast ? referencedIds : msg.referencedIds ?? [];
|
|
2148
2383
|
const msgSources = isLast ? sources : msg.sources ?? [];
|
|
2149
2384
|
const msgIntent = isLast ? lastIntent : msg.intent;
|
|
2150
2385
|
const hiddenIntent = msgIntent === "compare" || msgIntent === "capture" || msgIntent === "capture_all" || msgIntent === "delete" || msgIntent === "view_history";
|
|
2151
2386
|
const showCarousel = msgReferencedIds.length > 0 && !hiddenIntent && (!isLast || lastAction?.type !== "request_kiku_key");
|
|
2152
|
-
return showCarousel && /* @__PURE__ */ (0,
|
|
2387
|
+
return showCarousel && /* @__PURE__ */ (0, import_jsx_runtime8.jsx)(
|
|
2153
2388
|
SourcesCarousel,
|
|
2154
2389
|
{
|
|
2155
2390
|
sources: msgSources,
|
|
@@ -2161,11 +2396,11 @@ function ChatModal({
|
|
|
2161
2396
|
}
|
|
2162
2397
|
);
|
|
2163
2398
|
})(),
|
|
2164
|
-
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: [
|
|
2165
2400
|
String(lastAction.type || "continue").replace(/_/g, " "),
|
|
2166
2401
|
" \u2192"
|
|
2167
2402
|
] }) }),
|
|
2168
|
-
isLast && !loading && /* @__PURE__ */ (0,
|
|
2403
|
+
isLast && !loading && /* @__PURE__ */ (0, import_jsx_runtime8.jsx)(
|
|
2169
2404
|
SmartContextPills,
|
|
2170
2405
|
{
|
|
2171
2406
|
intent: lastIntent,
|
|
@@ -2177,16 +2412,16 @@ function ChatModal({
|
|
|
2177
2412
|
] })
|
|
2178
2413
|
] }) }, idx);
|
|
2179
2414
|
}),
|
|
2180
|
-
selectedProduct && loading && /* @__PURE__ */ (0,
|
|
2415
|
+
selectedProduct && loading && /* @__PURE__ */ (0, import_jsx_runtime8.jsxs)(
|
|
2181
2416
|
"div",
|
|
2182
2417
|
{
|
|
2183
2418
|
className: "hsk-cb-selected-product",
|
|
2184
2419
|
onClick: () => selectedProduct.url && window.open(selectedProduct.url, "_blank"),
|
|
2185
2420
|
children: [
|
|
2186
|
-
selectedProduct.image && /* @__PURE__ */ (0,
|
|
2187
|
-
/* @__PURE__ */ (0,
|
|
2188
|
-
/* @__PURE__ */ (0,
|
|
2189
|
-
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: [
|
|
2190
2425
|
selectedProduct.currency ?? defaultCurrency,
|
|
2191
2426
|
" ",
|
|
2192
2427
|
parseFloat(String(selectedProduct.price ?? "").replace(/[^0-9.]/g, "") || "0").toLocaleString()
|
|
@@ -2195,22 +2430,22 @@ function ChatModal({
|
|
|
2195
2430
|
]
|
|
2196
2431
|
}
|
|
2197
2432
|
),
|
|
2198
|
-
loading && !streaming && /* @__PURE__ */ (0,
|
|
2199
|
-
/* @__PURE__ */ (0,
|
|
2200
|
-
/* @__PURE__ */ (0,
|
|
2201
|
-
/* @__PURE__ */ (0,
|
|
2202
|
-
/* @__PURE__ */ (0,
|
|
2203
|
-
/* @__PURE__ */ (0,
|
|
2204
|
-
/* @__PURE__ */ (0,
|
|
2205
|
-
/* @__PURE__ */ (0,
|
|
2206
|
-
/* @__PURE__ */ (0,
|
|
2207
|
-
/* @__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" })
|
|
2208
2443
|
] }) }),
|
|
2209
|
-
/* @__PURE__ */ (0,
|
|
2444
|
+
/* @__PURE__ */ (0, import_jsx_runtime8.jsx)("span", { className: "hsk-handle-rest" })
|
|
2210
2445
|
] }),
|
|
2211
|
-
/* @__PURE__ */ (0,
|
|
2446
|
+
/* @__PURE__ */ (0, import_jsx_runtime8.jsx)("span", { className: "hsk-cb-thinking-text", children: "Thinking\u2026" })
|
|
2212
2447
|
] }),
|
|
2213
|
-
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)(
|
|
2214
2449
|
"a",
|
|
2215
2450
|
{
|
|
2216
2451
|
className: "hsk-cb-memory-pill",
|
|
@@ -2219,23 +2454,23 @@ function ChatModal({
|
|
|
2219
2454
|
rel: "noopener noreferrer",
|
|
2220
2455
|
children: [
|
|
2221
2456
|
"Open my memory on mimi",
|
|
2222
|
-
/* @__PURE__ */ (0,
|
|
2457
|
+
/* @__PURE__ */ (0, import_jsx_runtime8.jsx)(ExternalIcon, {})
|
|
2223
2458
|
]
|
|
2224
2459
|
}
|
|
2225
2460
|
),
|
|
2226
|
-
(stopped || interrupted) && !loading && !streaming && messages.length > 0 && /* @__PURE__ */ (0,
|
|
2227
|
-
/* @__PURE__ */ (0,
|
|
2228
|
-
/* @__PURE__ */ (0,
|
|
2229
|
-
/* @__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, {}),
|
|
2230
2465
|
messages[messages.length - 1]?.role === "assistant" ? "Continue generating" : "Generate response"
|
|
2231
2466
|
] })
|
|
2232
2467
|
] }),
|
|
2233
|
-
error && /* @__PURE__ */ (0,
|
|
2234
|
-
keyPhase === "prompt_key" && /* @__PURE__ */ (0,
|
|
2235
|
-
/* @__PURE__ */ (0,
|
|
2236
|
-
/* @__PURE__ */ (0,
|
|
2237
|
-
/* @__PURE__ */ (0,
|
|
2238
|
-
/* @__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)(
|
|
2239
2474
|
"input",
|
|
2240
2475
|
{
|
|
2241
2476
|
type: "text",
|
|
@@ -2247,49 +2482,49 @@ function ChatModal({
|
|
|
2247
2482
|
autoFocus: true
|
|
2248
2483
|
}
|
|
2249
2484
|
),
|
|
2250
|
-
/* @__PURE__ */ (0,
|
|
2251
|
-
/* @__PURE__ */ (0,
|
|
2252
|
-
/* @__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" })
|
|
2253
2488
|
] })
|
|
2254
2489
|
] }) }) })
|
|
2255
2490
|
] }),
|
|
2256
|
-
mintedKey && /* @__PURE__ */ (0,
|
|
2257
|
-
/* @__PURE__ */ (0,
|
|
2258
|
-
/* @__PURE__ */ (0,
|
|
2259
|
-
/* @__PURE__ */ (0,
|
|
2260
|
-
/* @__PURE__ */ (0,
|
|
2261
|
-
/* @__PURE__ */ (0,
|
|
2262
|
-
/* @__PURE__ */ (0,
|
|
2263
|
-
/* @__PURE__ */ (0,
|
|
2264
|
-
/* @__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." })
|
|
2265
2500
|
] })
|
|
2266
2501
|
] }),
|
|
2267
|
-
mintedPub && /* @__PURE__ */ (0,
|
|
2268
|
-
/* @__PURE__ */ (0,
|
|
2269
|
-
/* @__PURE__ */ (0,
|
|
2270
|
-
/* @__PURE__ */ (0,
|
|
2271
|
-
/* @__PURE__ */ (0,
|
|
2272
|
-
/* @__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." })
|
|
2273
2508
|
] })
|
|
2274
2509
|
] }),
|
|
2275
|
-
/* @__PURE__ */ (0,
|
|
2510
|
+
/* @__PURE__ */ (0, import_jsx_runtime8.jsxs)("div", { style: { fontSize: 11, opacity: 0.6 }, children: [
|
|
2276
2511
|
"Hidden in ",
|
|
2277
2512
|
keyCountdown,
|
|
2278
2513
|
"s."
|
|
2279
2514
|
] })
|
|
2280
2515
|
] }) }) })
|
|
2281
2516
|
] }),
|
|
2282
|
-
/* @__PURE__ */ (0,
|
|
2517
|
+
/* @__PURE__ */ (0, import_jsx_runtime8.jsx)("div", { ref: bottomRef, style: { height: 1 } })
|
|
2283
2518
|
] }),
|
|
2284
|
-
/* @__PURE__ */ (0,
|
|
2285
|
-
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)(
|
|
2286
2521
|
AtPickerMenu,
|
|
2287
2522
|
{
|
|
2288
2523
|
onSelect: handleSelectExtension,
|
|
2289
2524
|
onDismiss: () => setShowAtPicker(false)
|
|
2290
2525
|
}
|
|
2291
2526
|
),
|
|
2292
|
-
showKikuPicker && /* @__PURE__ */ (0,
|
|
2527
|
+
showKikuPicker && /* @__PURE__ */ (0, import_jsx_runtime8.jsx)(
|
|
2293
2528
|
KikuPickerMenu,
|
|
2294
2529
|
{
|
|
2295
2530
|
sources,
|
|
@@ -2302,9 +2537,9 @@ function ChatModal({
|
|
|
2302
2537
|
onDismiss: () => setShowKikuPicker(false)
|
|
2303
2538
|
}
|
|
2304
2539
|
),
|
|
2305
|
-
attachments.length > 0 && /* @__PURE__ */ (0,
|
|
2306
|
-
/* @__PURE__ */ (0,
|
|
2307
|
-
/* @__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)(
|
|
2308
2543
|
"button",
|
|
2309
2544
|
{
|
|
2310
2545
|
className: "hsk-cb-img-thumb-remove",
|
|
@@ -2314,8 +2549,8 @@ function ChatModal({
|
|
|
2314
2549
|
}
|
|
2315
2550
|
)
|
|
2316
2551
|
] }, i)) }),
|
|
2317
|
-
/* @__PURE__ */ (0,
|
|
2318
|
-
/* @__PURE__ */ (0,
|
|
2552
|
+
/* @__PURE__ */ (0, import_jsx_runtime8.jsxs)("div", { className: "hsk-cb-input-box", children: [
|
|
2553
|
+
/* @__PURE__ */ (0, import_jsx_runtime8.jsx)(
|
|
2319
2554
|
"input",
|
|
2320
2555
|
{
|
|
2321
2556
|
ref: imageInputRef,
|
|
@@ -2326,7 +2561,7 @@ function ChatModal({
|
|
|
2326
2561
|
onChange: (e) => handleImageFiles(e.target.files)
|
|
2327
2562
|
}
|
|
2328
2563
|
),
|
|
2329
|
-
enableVision && /* @__PURE__ */ (0,
|
|
2564
|
+
enableVision && /* @__PURE__ */ (0, import_jsx_runtime8.jsx)(
|
|
2330
2565
|
"button",
|
|
2331
2566
|
{
|
|
2332
2567
|
className: "hsk-cb-attach-btn",
|
|
@@ -2334,10 +2569,10 @@ function ChatModal({
|
|
|
2334
2569
|
disabled: loading,
|
|
2335
2570
|
"aria-label": "Attach image",
|
|
2336
2571
|
title: "Attach image",
|
|
2337
|
-
children: /* @__PURE__ */ (0,
|
|
2572
|
+
children: /* @__PURE__ */ (0, import_jsx_runtime8.jsx)(PaperclipIcon, {})
|
|
2338
2573
|
}
|
|
2339
2574
|
),
|
|
2340
|
-
/* @__PURE__ */ (0,
|
|
2575
|
+
/* @__PURE__ */ (0, import_jsx_runtime8.jsx)(
|
|
2341
2576
|
"textarea",
|
|
2342
2577
|
{
|
|
2343
2578
|
ref: textareaRef,
|
|
@@ -2351,7 +2586,7 @@ function ChatModal({
|
|
|
2351
2586
|
autoFocus: true
|
|
2352
2587
|
}
|
|
2353
2588
|
),
|
|
2354
|
-
hasSpeechAPI && enableVoice && /* @__PURE__ */ (0,
|
|
2589
|
+
hasSpeechAPI && enableVoice && /* @__PURE__ */ (0, import_jsx_runtime8.jsxs)(
|
|
2355
2590
|
"button",
|
|
2356
2591
|
{
|
|
2357
2592
|
className: cn(
|
|
@@ -2364,32 +2599,32 @@ function ChatModal({
|
|
|
2364
2599
|
"aria-label": voiceState === "idle" ? "Start voice input" : "Stop recording",
|
|
2365
2600
|
title: voiceState === "idle" ? "Voice input" : "Stop",
|
|
2366
2601
|
children: [
|
|
2367
|
-
voiceState === "listening" ? /* @__PURE__ */ (0,
|
|
2368
|
-
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" })
|
|
2369
2604
|
]
|
|
2370
2605
|
}
|
|
2371
2606
|
),
|
|
2372
|
-
loading || streaming ? /* @__PURE__ */ (0,
|
|
2607
|
+
loading || streaming ? /* @__PURE__ */ (0, import_jsx_runtime8.jsx)(
|
|
2373
2608
|
"button",
|
|
2374
2609
|
{
|
|
2375
2610
|
className: cn("hsk-cb-send", "hsk-cb-send--stop", classNames.sendButton),
|
|
2376
2611
|
onClick: stop,
|
|
2377
2612
|
"aria-label": "Stop generating",
|
|
2378
2613
|
title: "Stop generating",
|
|
2379
|
-
children: /* @__PURE__ */ (0,
|
|
2614
|
+
children: /* @__PURE__ */ (0, import_jsx_runtime8.jsx)(StopIcon, {})
|
|
2380
2615
|
}
|
|
2381
|
-
) : /* @__PURE__ */ (0,
|
|
2616
|
+
) : /* @__PURE__ */ (0, import_jsx_runtime8.jsx)(
|
|
2382
2617
|
"button",
|
|
2383
2618
|
{
|
|
2384
2619
|
className: cn("hsk-cb-send", classNames.sendButton),
|
|
2385
2620
|
onClick: () => handleSend(),
|
|
2386
2621
|
disabled: !input.trim() && attachments.length === 0,
|
|
2387
2622
|
"aria-label": "Send message",
|
|
2388
|
-
children: /* @__PURE__ */ (0,
|
|
2623
|
+
children: /* @__PURE__ */ (0, import_jsx_runtime8.jsx)(ArrowUpIcon2, {})
|
|
2389
2624
|
}
|
|
2390
2625
|
)
|
|
2391
2626
|
] }),
|
|
2392
|
-
/* @__PURE__ */ (0,
|
|
2627
|
+
/* @__PURE__ */ (0, import_jsx_runtime8.jsx)("div", { className: "hsk-cb-hint", children: "kiku \xB7 searches the whole catalogue in real time" })
|
|
2393
2628
|
] })
|
|
2394
2629
|
] })
|
|
2395
2630
|
]
|
|
@@ -2415,9 +2650,9 @@ function KikuButton({
|
|
|
2415
2650
|
enableVision = false,
|
|
2416
2651
|
visionCategoryHint
|
|
2417
2652
|
}) {
|
|
2418
|
-
const [open, setOpen] = (0,
|
|
2419
|
-
const [mounted, setMounted] = (0,
|
|
2420
|
-
(0,
|
|
2653
|
+
const [open, setOpen] = (0, import_react6.useState)(false);
|
|
2654
|
+
const [mounted, setMounted] = (0, import_react6.useState)(false);
|
|
2655
|
+
(0, import_react6.useEffect)(() => {
|
|
2421
2656
|
setMounted(true);
|
|
2422
2657
|
if (typeof window !== "undefined" && !window.__akropolys_nav_patched) {
|
|
2423
2658
|
window.__akropolys_nav_patched = true;
|
|
@@ -2451,8 +2686,8 @@ function KikuButton({
|
|
|
2451
2686
|
...theme?.fontFamily && { "--hsk-font": theme.fontFamily },
|
|
2452
2687
|
...theme?.borderRadius && { "--hsk-border-radius": theme.borderRadius }
|
|
2453
2688
|
} : void 0;
|
|
2454
|
-
return /* @__PURE__ */ (0,
|
|
2455
|
-
/* @__PURE__ */ (0,
|
|
2689
|
+
return /* @__PURE__ */ (0, import_jsx_runtime8.jsxs)(import_jsx_runtime8.Fragment, { children: [
|
|
2690
|
+
/* @__PURE__ */ (0, import_jsx_runtime8.jsxs)(
|
|
2456
2691
|
"button",
|
|
2457
2692
|
{
|
|
2458
2693
|
className: cn("hsk-cb-btn", classNames.button, className),
|
|
@@ -2461,13 +2696,13 @@ function KikuButton({
|
|
|
2461
2696
|
"data-hsk-theme": hskThemeAttr,
|
|
2462
2697
|
"aria-label": "Open AI chat",
|
|
2463
2698
|
children: [
|
|
2464
|
-
/* @__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, {}) }),
|
|
2465
2700
|
label !== void 0 ? label : null
|
|
2466
2701
|
]
|
|
2467
2702
|
}
|
|
2468
2703
|
),
|
|
2469
2704
|
open && mounted && (0, import_react_dom.createPortal)(
|
|
2470
|
-
/* @__PURE__ */ (0,
|
|
2705
|
+
/* @__PURE__ */ (0, import_jsx_runtime8.jsx)(
|
|
2471
2706
|
ChatModal,
|
|
2472
2707
|
{
|
|
2473
2708
|
title,
|
|
@@ -2492,11 +2727,11 @@ function KikuButton({
|
|
|
2492
2727
|
}
|
|
2493
2728
|
|
|
2494
2729
|
// src/components/Sparkle.tsx
|
|
2495
|
-
var
|
|
2730
|
+
var import_react7 = require("react");
|
|
2496
2731
|
var import_react_dom2 = require("react-dom");
|
|
2497
2732
|
var import_sdk7 = require("@akropolys/sdk");
|
|
2498
|
-
var
|
|
2499
|
-
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)(
|
|
2500
2735
|
"svg",
|
|
2501
2736
|
{
|
|
2502
2737
|
className: cn("hsk-brand-mark", className),
|
|
@@ -2505,19 +2740,19 @@ var SparkleIcon3 = ({ className, size = 16 }) => /* @__PURE__ */ (0, import_jsx_
|
|
|
2505
2740
|
viewBox: "0 0 100 100",
|
|
2506
2741
|
xmlns: "http://www.w3.org/2000/svg",
|
|
2507
2742
|
"aria-label": "kiku",
|
|
2508
|
-
children: /* @__PURE__ */ (0,
|
|
2509
|
-
/* @__PURE__ */ (0,
|
|
2510
|
-
/* @__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" })
|
|
2511
2746
|
] })
|
|
2512
2747
|
}
|
|
2513
2748
|
);
|
|
2514
|
-
var CloseIcon2 = () => /* @__PURE__ */ (0,
|
|
2515
|
-
/* @__PURE__ */ (0,
|
|
2516
|
-
/* @__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" })
|
|
2517
2752
|
] });
|
|
2518
|
-
var ArrowUpIcon3 = () => /* @__PURE__ */ (0,
|
|
2519
|
-
/* @__PURE__ */ (0,
|
|
2520
|
-
/* @__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" })
|
|
2521
2756
|
] });
|
|
2522
2757
|
var getFriendlyError2 = (err) => {
|
|
2523
2758
|
let str = "";
|
|
@@ -2551,17 +2786,17 @@ function SparkleModal({
|
|
|
2551
2786
|
product: initialProduct
|
|
2552
2787
|
}) {
|
|
2553
2788
|
const client = (0, import_sdk7.useAkropolysContext)();
|
|
2554
|
-
const [fetchedProduct, setFetchedProduct] = (0,
|
|
2789
|
+
const [fetchedProduct, setFetchedProduct] = (0, import_react7.useState)(null);
|
|
2555
2790
|
const displayProduct = initialProduct || fetchedProduct;
|
|
2556
2791
|
const { results, loading: searchLoading, search } = (0, import_sdk7.useSearch)({ type: "vector" });
|
|
2557
2792
|
const { messages, sources, loading: chatLoading, error: chatError, send } = (0, import_sdk7.useKiku)();
|
|
2558
|
-
const [chatInput, setChatInput] = (0,
|
|
2559
|
-
const [isMobile, setIsMobile] = (0,
|
|
2560
|
-
const [showSpecs, setShowSpecs] = (0,
|
|
2561
|
-
const [collapseSimilar, setCollapseSimilar] = (0,
|
|
2562
|
-
const chatBottomRef = (0,
|
|
2563
|
-
const chatTextareaRef = (0,
|
|
2564
|
-
(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)(() => {
|
|
2565
2800
|
if (!initialProduct && !fetchedProduct) {
|
|
2566
2801
|
client.api.searchVector(productName, 1).then((res) => {
|
|
2567
2802
|
if (res.results && res.results.length > 0) {
|
|
@@ -2571,7 +2806,7 @@ function SparkleModal({
|
|
|
2571
2806
|
}
|
|
2572
2807
|
search(productName, limit);
|
|
2573
2808
|
}, [productName, initialProduct, fetchedProduct, client, limit, search]);
|
|
2574
|
-
(0,
|
|
2809
|
+
(0, import_react7.useEffect)(() => {
|
|
2575
2810
|
const handleResize = () => setIsMobile(window.innerWidth <= 768);
|
|
2576
2811
|
handleResize();
|
|
2577
2812
|
if (typeof window !== "undefined") {
|
|
@@ -2579,17 +2814,17 @@ function SparkleModal({
|
|
|
2579
2814
|
return () => window.removeEventListener("resize", handleResize);
|
|
2580
2815
|
}
|
|
2581
2816
|
}, []);
|
|
2582
|
-
(0,
|
|
2817
|
+
(0, import_react7.useEffect)(() => {
|
|
2583
2818
|
if (results.length > 0) onResult?.(results);
|
|
2584
2819
|
}, [results, onResult]);
|
|
2585
|
-
(0,
|
|
2820
|
+
(0, import_react7.useEffect)(() => {
|
|
2586
2821
|
const h = (e) => {
|
|
2587
2822
|
if (e.key === "Escape") onClose();
|
|
2588
2823
|
};
|
|
2589
2824
|
document.addEventListener("keydown", h);
|
|
2590
2825
|
return () => document.removeEventListener("keydown", h);
|
|
2591
2826
|
}, [onClose]);
|
|
2592
|
-
(0,
|
|
2827
|
+
(0, import_react7.useEffect)(() => {
|
|
2593
2828
|
chatBottomRef.current?.scrollIntoView({ behavior: "smooth" });
|
|
2594
2829
|
}, [messages, chatLoading]);
|
|
2595
2830
|
const blurVal = typeof backdropBlur === "number" ? `${backdropBlur}px` : backdropBlur ?? "16px";
|
|
@@ -2643,7 +2878,7 @@ Question: ${q}`;
|
|
|
2643
2878
|
}
|
|
2644
2879
|
] : messages;
|
|
2645
2880
|
if (isMobile) {
|
|
2646
|
-
return /* @__PURE__ */ (0,
|
|
2881
|
+
return /* @__PURE__ */ (0, import_jsx_runtime9.jsx)(
|
|
2647
2882
|
"div",
|
|
2648
2883
|
{
|
|
2649
2884
|
className: cn("hsk-sp-backdrop hsk-sp-mobile-view", classNames.backdrop),
|
|
@@ -2654,13 +2889,13 @@ Question: ${q}`;
|
|
|
2654
2889
|
background: bg ?? void 0,
|
|
2655
2890
|
...customStyles
|
|
2656
2891
|
},
|
|
2657
|
-
children: /* @__PURE__ */ (0,
|
|
2658
|
-
/* @__PURE__ */ (0,
|
|
2659
|
-
/* @__PURE__ */ (0,
|
|
2660
|
-
/* @__PURE__ */ (0,
|
|
2661
|
-
/* @__PURE__ */ (0,
|
|
2662
|
-
/* @__PURE__ */ (0,
|
|
2663
|
-
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)(
|
|
2664
2899
|
"button",
|
|
2665
2900
|
{
|
|
2666
2901
|
type: "button",
|
|
@@ -2670,32 +2905,32 @@ Question: ${q}`;
|
|
|
2670
2905
|
}
|
|
2671
2906
|
)
|
|
2672
2907
|
] }),
|
|
2673
|
-
/* @__PURE__ */ (0,
|
|
2908
|
+
/* @__PURE__ */ (0, import_jsx_runtime9.jsx)("div", { className: "hsk-sp-header-sub", children: "kiku" })
|
|
2674
2909
|
] }),
|
|
2675
|
-
/* @__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, {}) })
|
|
2676
2911
|
] }),
|
|
2677
|
-
searchLoading && /* @__PURE__ */ (0,
|
|
2678
|
-
/* @__PURE__ */ (0,
|
|
2679
|
-
/* @__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: [
|
|
2680
2915
|
displayMessages.map((msg, idx) => {
|
|
2681
2916
|
const isUser = msg.role === "user";
|
|
2682
|
-
return /* @__PURE__ */ (0,
|
|
2683
|
-
/* @__PURE__ */ (0,
|
|
2684
|
-
/* @__PURE__ */ (0,
|
|
2685
|
-
/* @__PURE__ */ (0,
|
|
2686
|
-
idx === 0 && displayProduct && /* @__PURE__ */ (0,
|
|
2687
|
-
/* @__PURE__ */ (0,
|
|
2688
|
-
/* @__PURE__ */ (0,
|
|
2689
|
-
/* @__PURE__ */ (0,
|
|
2690
|
-
/* @__PURE__ */ (0,
|
|
2691
|
-
/* @__PURE__ */ (0,
|
|
2692
|
-
/* @__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: [
|
|
2693
2928
|
displayProduct.currency ?? "KES",
|
|
2694
2929
|
" ",
|
|
2695
2930
|
parseFloat(displayProduct.price?.replace(/[^0-9.]/g, "") || "0").toLocaleString()
|
|
2696
2931
|
] })
|
|
2697
2932
|
] }),
|
|
2698
|
-
(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)(
|
|
2699
2934
|
"button",
|
|
2700
2935
|
{
|
|
2701
2936
|
type: "button",
|
|
@@ -2714,21 +2949,21 @@ Question: ${q}`;
|
|
|
2714
2949
|
}
|
|
2715
2950
|
);
|
|
2716
2951
|
if (similarProducts.length === 0) return null;
|
|
2717
|
-
return /* @__PURE__ */ (0,
|
|
2718
|
-
/* @__PURE__ */ (0,
|
|
2719
|
-
/* @__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) => {
|
|
2720
2955
|
const price = parseFloat(r.entity.price?.replace(/[^0-9.]/g, "") || "0");
|
|
2721
2956
|
const currency = r.entity.currency ?? "KES";
|
|
2722
|
-
return /* @__PURE__ */ (0,
|
|
2957
|
+
return /* @__PURE__ */ (0, import_jsx_runtime9.jsxs)(
|
|
2723
2958
|
"div",
|
|
2724
2959
|
{
|
|
2725
2960
|
className: "hsk-sp-mobile-similar-carousel-item",
|
|
2726
2961
|
onClick: () => handleNav(r),
|
|
2727
2962
|
children: [
|
|
2728
|
-
/* @__PURE__ */ (0,
|
|
2729
|
-
/* @__PURE__ */ (0,
|
|
2730
|
-
/* @__PURE__ */ (0,
|
|
2731
|
-
/* @__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: [
|
|
2732
2967
|
currency,
|
|
2733
2968
|
" ",
|
|
2734
2969
|
price.toLocaleString()
|
|
@@ -2745,19 +2980,19 @@ Question: ${q}`;
|
|
|
2745
2980
|
] })
|
|
2746
2981
|
] }) }, idx);
|
|
2747
2982
|
}),
|
|
2748
|
-
chatLoading && /* @__PURE__ */ (0,
|
|
2749
|
-
/* @__PURE__ */ (0,
|
|
2750
|
-
/* @__PURE__ */ (0,
|
|
2751
|
-
/* @__PURE__ */ (0,
|
|
2752
|
-
/* @__PURE__ */ (0,
|
|
2753
|
-
/* @__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" })
|
|
2754
2989
|
] })
|
|
2755
2990
|
] }),
|
|
2756
|
-
chatError && /* @__PURE__ */ (0,
|
|
2757
|
-
/* @__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 } })
|
|
2758
2993
|
] }),
|
|
2759
|
-
/* @__PURE__ */ (0,
|
|
2760
|
-
/* @__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)(
|
|
2761
2996
|
"textarea",
|
|
2762
2997
|
{
|
|
2763
2998
|
ref: chatTextareaRef,
|
|
@@ -2770,34 +3005,34 @@ Question: ${q}`;
|
|
|
2770
3005
|
disabled: chatLoading
|
|
2771
3006
|
}
|
|
2772
3007
|
),
|
|
2773
|
-
/* @__PURE__ */ (0,
|
|
3008
|
+
/* @__PURE__ */ (0, import_jsx_runtime9.jsx)(
|
|
2774
3009
|
"button",
|
|
2775
3010
|
{
|
|
2776
3011
|
className: "hsk-cb-send",
|
|
2777
3012
|
onClick: () => handleSend(),
|
|
2778
3013
|
disabled: !chatInput.trim() || chatLoading,
|
|
2779
3014
|
"aria-label": "Send message",
|
|
2780
|
-
children: /* @__PURE__ */ (0,
|
|
3015
|
+
children: /* @__PURE__ */ (0, import_jsx_runtime9.jsx)(ArrowUpIcon3, {})
|
|
2781
3016
|
}
|
|
2782
3017
|
)
|
|
2783
3018
|
] }) })
|
|
2784
3019
|
] }),
|
|
2785
|
-
showSpecs && displayProduct && /* @__PURE__ */ (0,
|
|
2786
|
-
/* @__PURE__ */ (0,
|
|
2787
|
-
/* @__PURE__ */ (0,
|
|
2788
|
-
/* @__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" })
|
|
2789
3024
|
] }),
|
|
2790
|
-
/* @__PURE__ */ (0,
|
|
2791
|
-
/* @__PURE__ */ (0,
|
|
2792
|
-
displayProduct.description && /* @__PURE__ */ (0,
|
|
2793
|
-
/* @__PURE__ */ (0,
|
|
2794
|
-
/* @__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 })
|
|
2795
3030
|
] }),
|
|
2796
|
-
displayProduct.specs && Object.keys(displayProduct.specs).length > 0 && /* @__PURE__ */ (0,
|
|
2797
|
-
/* @__PURE__ */ (0,
|
|
2798
|
-
Object.entries(displayProduct.specs).map(([key, val]) => /* @__PURE__ */ (0,
|
|
2799
|
-
/* @__PURE__ */ (0,
|
|
2800
|
-
/* @__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 })
|
|
2801
3036
|
] }, key))
|
|
2802
3037
|
] })
|
|
2803
3038
|
] })
|
|
@@ -2806,7 +3041,7 @@ Question: ${q}`;
|
|
|
2806
3041
|
}
|
|
2807
3042
|
);
|
|
2808
3043
|
}
|
|
2809
|
-
return /* @__PURE__ */ (0,
|
|
3044
|
+
return /* @__PURE__ */ (0, import_jsx_runtime9.jsx)(
|
|
2810
3045
|
"div",
|
|
2811
3046
|
{
|
|
2812
3047
|
className: cn("hsk-sp-backdrop", classNames.backdrop),
|
|
@@ -2817,65 +3052,65 @@ Question: ${q}`;
|
|
|
2817
3052
|
background: bg ?? void 0,
|
|
2818
3053
|
...customStyles
|
|
2819
3054
|
},
|
|
2820
|
-
children: /* @__PURE__ */ (0,
|
|
2821
|
-
/* @__PURE__ */ (0,
|
|
2822
|
-
/* @__PURE__ */ (0,
|
|
2823
|
-
/* @__PURE__ */ (0,
|
|
2824
|
-
/* @__PURE__ */ (0,
|
|
2825
|
-
/* @__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" })
|
|
2826
3061
|
] }),
|
|
2827
|
-
/* @__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, {}) })
|
|
2828
3063
|
] }),
|
|
2829
|
-
searchLoading && /* @__PURE__ */ (0,
|
|
2830
|
-
/* @__PURE__ */ (0,
|
|
2831
|
-
/* @__PURE__ */ (0,
|
|
2832
|
-
displayProduct && /* @__PURE__ */ (0,
|
|
2833
|
-
/* @__PURE__ */ (0,
|
|
2834
|
-
/* @__PURE__ */ (0,
|
|
2835
|
-
/* @__PURE__ */ (0,
|
|
2836
|
-
displayProduct.brand && /* @__PURE__ */ (0,
|
|
2837
|
-
displayProduct.category && /* @__PURE__ */ (0,
|
|
2838
|
-
/* @__PURE__ */ (0,
|
|
2839
|
-
/* @__PURE__ */ (0,
|
|
2840
|
-
/* @__PURE__ */ (0,
|
|
2841
|
-
/* @__PURE__ */ (0,
|
|
2842
|
-
displayProduct.originalPrice && /* @__PURE__ */ (0,
|
|
2843
|
-
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: [
|
|
2844
3079
|
"(",
|
|
2845
3080
|
displayProduct.discount,
|
|
2846
3081
|
")"
|
|
2847
3082
|
] })
|
|
2848
3083
|
] }),
|
|
2849
|
-
/* @__PURE__ */ (0,
|
|
2850
|
-
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: [
|
|
2851
3086
|
"\xE2\u02DC\u2026 ",
|
|
2852
3087
|
parseFloat(displayProduct.rating.toString()).toFixed(1),
|
|
2853
3088
|
" ",
|
|
2854
3089
|
displayProduct.reviewCount ? `(${displayProduct.reviewCount})` : ""
|
|
2855
3090
|
] }),
|
|
2856
|
-
displayProduct.availability && /* @__PURE__ */ (0,
|
|
2857
|
-
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: [
|
|
2858
3093
|
"Stock: ",
|
|
2859
3094
|
displayProduct.stock
|
|
2860
3095
|
] })
|
|
2861
3096
|
] })
|
|
2862
3097
|
] })
|
|
2863
3098
|
] }),
|
|
2864
|
-
displayProduct.specs && Object.keys(displayProduct.specs).length > 0 && /* @__PURE__ */ (0,
|
|
2865
|
-
/* @__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: [
|
|
2866
3101
|
key,
|
|
2867
3102
|
":"
|
|
2868
3103
|
] }),
|
|
2869
|
-
/* @__PURE__ */ (0,
|
|
3104
|
+
/* @__PURE__ */ (0, import_jsx_runtime9.jsx)("span", { className: "hsk-sp-spec-value-horizontal", title: val, children: val })
|
|
2870
3105
|
] }, key)) }),
|
|
2871
|
-
displayProduct.description && /* @__PURE__ */ (0,
|
|
2872
|
-
/* @__PURE__ */ (0,
|
|
2873
|
-
/* @__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 })
|
|
2874
3109
|
] })
|
|
2875
3110
|
] }),
|
|
2876
|
-
/* @__PURE__ */ (0,
|
|
2877
|
-
/* @__PURE__ */ (0,
|
|
2878
|
-
/* @__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: (() => {
|
|
2879
3114
|
const similarProducts = results.filter(
|
|
2880
3115
|
(r) => {
|
|
2881
3116
|
const isSameName = !!(r.entity.name && displayProduct?.name && r.entity.name.toLowerCase() === displayProduct.name.toLowerCase());
|
|
@@ -2884,29 +3119,29 @@ Question: ${q}`;
|
|
|
2884
3119
|
}
|
|
2885
3120
|
);
|
|
2886
3121
|
if (!searchLoading && similarProducts.length === 0) {
|
|
2887
|
-
return /* @__PURE__ */ (0,
|
|
3122
|
+
return /* @__PURE__ */ (0, import_jsx_runtime9.jsx)("div", { className: "hsk-sp-empty", children: "No similar products found." });
|
|
2888
3123
|
}
|
|
2889
3124
|
return similarProducts.map((r, i) => {
|
|
2890
3125
|
const price = parseFloat(r.entity.price?.replace(/[^0-9.]/g, "") || "0");
|
|
2891
3126
|
const currency = r.entity.currency ?? "KES";
|
|
2892
|
-
return /* @__PURE__ */ (0,
|
|
3127
|
+
return /* @__PURE__ */ (0, import_jsx_runtime9.jsxs)(
|
|
2893
3128
|
"div",
|
|
2894
3129
|
{
|
|
2895
3130
|
className: cn("hsk-sp-item", classNames.item),
|
|
2896
3131
|
style: { animationDelay: `${i * 55}ms`, cursor: "pointer" },
|
|
2897
3132
|
onClick: () => handleNav(r),
|
|
2898
3133
|
children: [
|
|
2899
|
-
/* @__PURE__ */ (0,
|
|
2900
|
-
/* @__PURE__ */ (0,
|
|
2901
|
-
/* @__PURE__ */ (0,
|
|
2902
|
-
r.entity.category && /* @__PURE__ */ (0,
|
|
2903
|
-
/* @__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 })
|
|
2904
3139
|
] }),
|
|
2905
|
-
/* @__PURE__ */ (0,
|
|
2906
|
-
/* @__PURE__ */ (0,
|
|
2907
|
-
/* @__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() })
|
|
2908
3143
|
] }),
|
|
2909
|
-
/* @__PURE__ */ (0,
|
|
3144
|
+
/* @__PURE__ */ (0, import_jsx_runtime9.jsx)("div", { className: "hsk-sp-actions", children: /* @__PURE__ */ (0, import_jsx_runtime9.jsx)(
|
|
2910
3145
|
"button",
|
|
2911
3146
|
{
|
|
2912
3147
|
className: "hsk-sp-action hsk-sp-action-primary",
|
|
@@ -2926,29 +3161,29 @@ Question: ${q}`;
|
|
|
2926
3161
|
})() })
|
|
2927
3162
|
] })
|
|
2928
3163
|
] }),
|
|
2929
|
-
/* @__PURE__ */ (0,
|
|
2930
|
-
/* @__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: [
|
|
2931
3166
|
displayMessages.map((msg, idx) => {
|
|
2932
3167
|
const isUser = msg.role === "user";
|
|
2933
|
-
return /* @__PURE__ */ (0,
|
|
2934
|
-
/* @__PURE__ */ (0,
|
|
2935
|
-
/* @__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) }) })
|
|
2936
3171
|
] }) }, idx);
|
|
2937
3172
|
}),
|
|
2938
|
-
chatLoading && /* @__PURE__ */ (0,
|
|
2939
|
-
/* @__PURE__ */ (0,
|
|
2940
|
-
/* @__PURE__ */ (0,
|
|
2941
|
-
/* @__PURE__ */ (0,
|
|
2942
|
-
/* @__PURE__ */ (0,
|
|
2943
|
-
/* @__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" })
|
|
2944
3179
|
] })
|
|
2945
3180
|
] }),
|
|
2946
|
-
chatError && /* @__PURE__ */ (0,
|
|
2947
|
-
/* @__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 } })
|
|
2948
3183
|
] }),
|
|
2949
|
-
/* @__PURE__ */ (0,
|
|
2950
|
-
/* @__PURE__ */ (0,
|
|
2951
|
-
/* @__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)(
|
|
2952
3187
|
"textarea",
|
|
2953
3188
|
{
|
|
2954
3189
|
ref: chatTextareaRef,
|
|
@@ -2961,22 +3196,22 @@ Question: ${q}`;
|
|
|
2961
3196
|
disabled: chatLoading
|
|
2962
3197
|
}
|
|
2963
3198
|
),
|
|
2964
|
-
/* @__PURE__ */ (0,
|
|
3199
|
+
/* @__PURE__ */ (0, import_jsx_runtime9.jsx)(
|
|
2965
3200
|
"button",
|
|
2966
3201
|
{
|
|
2967
3202
|
className: "hsk-cb-send",
|
|
2968
3203
|
onClick: () => handleSend(),
|
|
2969
3204
|
disabled: !chatInput.trim() || chatLoading,
|
|
2970
3205
|
"aria-label": "Send message",
|
|
2971
|
-
children: /* @__PURE__ */ (0,
|
|
3206
|
+
children: /* @__PURE__ */ (0, import_jsx_runtime9.jsx)(ArrowUpIcon3, {})
|
|
2972
3207
|
}
|
|
2973
3208
|
)
|
|
2974
3209
|
] }),
|
|
2975
|
-
/* @__PURE__ */ (0,
|
|
3210
|
+
/* @__PURE__ */ (0, import_jsx_runtime9.jsx)("div", { className: "hsk-cb-hint", children: "Akropolys \xB7 instant product knowledge" })
|
|
2976
3211
|
] })
|
|
2977
3212
|
] })
|
|
2978
3213
|
] }),
|
|
2979
|
-
/* @__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" }) })
|
|
2980
3215
|
] })
|
|
2981
3216
|
}
|
|
2982
3217
|
);
|
|
@@ -2994,9 +3229,9 @@ function Sparkle({
|
|
|
2994
3229
|
product,
|
|
2995
3230
|
children
|
|
2996
3231
|
}) {
|
|
2997
|
-
const [open, setOpen] = (0,
|
|
2998
|
-
const [mounted, setMounted] = (0,
|
|
2999
|
-
(0,
|
|
3232
|
+
const [open, setOpen] = (0, import_react7.useState)(false);
|
|
3233
|
+
const [mounted, setMounted] = (0, import_react7.useState)(false);
|
|
3234
|
+
(0, import_react7.useEffect)(() => {
|
|
3000
3235
|
setMounted(true);
|
|
3001
3236
|
}, []);
|
|
3002
3237
|
const customStyles = {
|
|
@@ -3006,8 +3241,8 @@ function Sparkle({
|
|
|
3006
3241
|
...theme?.fontFamily && { "--hsk-font": theme.fontFamily },
|
|
3007
3242
|
...theme?.borderRadius && { "--hsk-border-radius": theme.borderRadius }
|
|
3008
3243
|
};
|
|
3009
|
-
return /* @__PURE__ */ (0,
|
|
3010
|
-
/* @__PURE__ */ (0,
|
|
3244
|
+
return /* @__PURE__ */ (0, import_jsx_runtime9.jsxs)(import_jsx_runtime9.Fragment, { children: [
|
|
3245
|
+
/* @__PURE__ */ (0, import_jsx_runtime9.jsx)(
|
|
3011
3246
|
"button",
|
|
3012
3247
|
{
|
|
3013
3248
|
className: cn("hsk-sp-btn", classNames.button, className),
|
|
@@ -3015,11 +3250,11 @@ function Sparkle({
|
|
|
3015
3250
|
style: customStyles,
|
|
3016
3251
|
title: "Find similar products",
|
|
3017
3252
|
"aria-label": "Find similar products",
|
|
3018
|
-
children: children || /* @__PURE__ */ (0,
|
|
3253
|
+
children: children || /* @__PURE__ */ (0, import_jsx_runtime9.jsx)(SparkleIcon3, {})
|
|
3019
3254
|
}
|
|
3020
3255
|
),
|
|
3021
3256
|
open && mounted && (0, import_react_dom2.createPortal)(
|
|
3022
|
-
/* @__PURE__ */ (0,
|
|
3257
|
+
/* @__PURE__ */ (0, import_jsx_runtime9.jsx)(
|
|
3023
3258
|
SparkleModal,
|
|
3024
3259
|
{
|
|
3025
3260
|
productName,
|