@skippr/live-agent-sdk 0.32.0 → 0.33.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/esm/lib-exports.js +256 -263
- package/dist/skippr-sdk.css +1 -1
- package/dist/skippr-sdk.js +117 -117
- package/package.json +1 -1
package/dist/esm/lib-exports.js
CHANGED
|
@@ -1194,255 +1194,6 @@ function DomCapture() {
|
|
|
1194
1194
|
|
|
1195
1195
|
// src/components/HighlightOverlay.tsx
|
|
1196
1196
|
import { useDataChannel } from "@livekit/components-react/hooks";
|
|
1197
|
-
import { useCallback as useCallback3, useEffect as useEffect5, useRef as useRef3, useState as useState3 } from "react";
|
|
1198
|
-
import { jsx, jsxs, Fragment } from "react/jsx-runtime";
|
|
1199
|
-
var TOOLTIP_MAX_WIDTH = 280;
|
|
1200
|
-
var TOOLTIP_GAP = 8;
|
|
1201
|
-
var VIEWPORT_MARGIN = 8;
|
|
1202
|
-
var TOOLTIP_TOP_THRESHOLD = 48;
|
|
1203
|
-
var Z_INDEX = 2147483646;
|
|
1204
|
-
var RING_INNER = "oklab(0.585 0.0288678 -0.231205 / 0.95)";
|
|
1205
|
-
var RING_OUTER = "oklab(0.585 0.0288678 -0.231205 / 0.25)";
|
|
1206
|
-
var textDecoder = new TextDecoder;
|
|
1207
|
-
function parseHighlightMessage(payload) {
|
|
1208
|
-
try {
|
|
1209
|
-
const json = JSON.parse(textDecoder.decode(payload));
|
|
1210
|
-
if (!json || typeof json !== "object")
|
|
1211
|
-
return null;
|
|
1212
|
-
if (json.type === "show" && typeof json.ref === "string") {
|
|
1213
|
-
return {
|
|
1214
|
-
type: "show",
|
|
1215
|
-
ref: json.ref,
|
|
1216
|
-
message: typeof json.message === "string" ? json.message : ""
|
|
1217
|
-
};
|
|
1218
|
-
}
|
|
1219
|
-
if (json.type === "clear")
|
|
1220
|
-
return { type: "clear" };
|
|
1221
|
-
return null;
|
|
1222
|
-
} catch {
|
|
1223
|
-
return null;
|
|
1224
|
-
}
|
|
1225
|
-
}
|
|
1226
|
-
function safeGetIframeDocument(iframe) {
|
|
1227
|
-
try {
|
|
1228
|
-
return iframe.contentDocument;
|
|
1229
|
-
} catch {
|
|
1230
|
-
return null;
|
|
1231
|
-
}
|
|
1232
|
-
}
|
|
1233
|
-
function safeQuerySelector(doc, selector) {
|
|
1234
|
-
try {
|
|
1235
|
-
return doc.querySelector(selector);
|
|
1236
|
-
} catch {
|
|
1237
|
-
return null;
|
|
1238
|
-
}
|
|
1239
|
-
}
|
|
1240
|
-
function safeQueryAllIframes(doc) {
|
|
1241
|
-
try {
|
|
1242
|
-
return Array.from(doc.querySelectorAll("iframe"));
|
|
1243
|
-
} catch {
|
|
1244
|
-
return [];
|
|
1245
|
-
}
|
|
1246
|
-
}
|
|
1247
|
-
function findElementInDocumentTree(rootDoc, selector) {
|
|
1248
|
-
const hit = safeQuerySelector(rootDoc, selector);
|
|
1249
|
-
if (hit)
|
|
1250
|
-
return hit;
|
|
1251
|
-
for (const iframe of safeQueryAllIframes(rootDoc)) {
|
|
1252
|
-
const innerDoc = safeGetIframeDocument(iframe);
|
|
1253
|
-
if (!innerDoc)
|
|
1254
|
-
continue;
|
|
1255
|
-
const nested = findElementInDocumentTree(innerDoc, selector);
|
|
1256
|
-
if (nested)
|
|
1257
|
-
return nested;
|
|
1258
|
-
}
|
|
1259
|
-
return null;
|
|
1260
|
-
}
|
|
1261
|
-
function findElementByRef(ref) {
|
|
1262
|
-
const selector = `[${REF_ATTR}="${CSS.escape(ref)}"]`;
|
|
1263
|
-
return findElementInDocumentTree(document, selector);
|
|
1264
|
-
}
|
|
1265
|
-
function findIframeHostingDocument(targetDoc) {
|
|
1266
|
-
const queue = [document];
|
|
1267
|
-
while (queue.length > 0) {
|
|
1268
|
-
const doc = queue.shift();
|
|
1269
|
-
if (!doc)
|
|
1270
|
-
continue;
|
|
1271
|
-
for (const iframe of safeQueryAllIframes(doc)) {
|
|
1272
|
-
if (safeGetIframeDocument(iframe) === targetDoc)
|
|
1273
|
-
return iframe;
|
|
1274
|
-
const innerDoc = safeGetIframeDocument(iframe);
|
|
1275
|
-
if (innerDoc)
|
|
1276
|
-
queue.push(innerDoc);
|
|
1277
|
-
}
|
|
1278
|
-
}
|
|
1279
|
-
return null;
|
|
1280
|
-
}
|
|
1281
|
-
function getRectInTopViewport(el) {
|
|
1282
|
-
let rect = el.getBoundingClientRect();
|
|
1283
|
-
let ownerDoc = el.ownerDocument;
|
|
1284
|
-
while (ownerDoc && ownerDoc !== document) {
|
|
1285
|
-
const hostingIframe = findIframeHostingDocument(ownerDoc);
|
|
1286
|
-
if (!hostingIframe)
|
|
1287
|
-
return rect;
|
|
1288
|
-
const iframeRect = hostingIframe.getBoundingClientRect();
|
|
1289
|
-
rect = new DOMRect(rect.left + iframeRect.left, rect.top + iframeRect.top, rect.width, rect.height);
|
|
1290
|
-
ownerDoc = hostingIframe.ownerDocument;
|
|
1291
|
-
}
|
|
1292
|
-
return rect;
|
|
1293
|
-
}
|
|
1294
|
-
function findScrollableAncestor(el) {
|
|
1295
|
-
const win = el.ownerDocument?.defaultView ?? window;
|
|
1296
|
-
let node = el.parentElement;
|
|
1297
|
-
while (node) {
|
|
1298
|
-
const overflow = win.getComputedStyle(node).overflow;
|
|
1299
|
-
if (/auto|scroll|overlay/.test(overflow))
|
|
1300
|
-
return node;
|
|
1301
|
-
node = node.parentElement;
|
|
1302
|
-
}
|
|
1303
|
-
return el.ownerDocument?.documentElement ?? document.documentElement;
|
|
1304
|
-
}
|
|
1305
|
-
function HighlightOverlay() {
|
|
1306
|
-
const [overlayState, setOverlayState] = useState3(null);
|
|
1307
|
-
const targetElementRef = useRef3(null);
|
|
1308
|
-
const pendingFrameRef = useRef3(null);
|
|
1309
|
-
const clearOverlay = useCallback3(() => {
|
|
1310
|
-
targetElementRef.current = null;
|
|
1311
|
-
setOverlayState(null);
|
|
1312
|
-
}, []);
|
|
1313
|
-
const recomputeRect = useCallback3(() => {
|
|
1314
|
-
pendingFrameRef.current = null;
|
|
1315
|
-
const target = targetElementRef.current;
|
|
1316
|
-
if (!target)
|
|
1317
|
-
return;
|
|
1318
|
-
if (!target.isConnected) {
|
|
1319
|
-
clearOverlay();
|
|
1320
|
-
return;
|
|
1321
|
-
}
|
|
1322
|
-
const rect2 = getRectInTopViewport(target);
|
|
1323
|
-
setOverlayState((prev) => prev ? { ...prev, rect: rect2 } : prev);
|
|
1324
|
-
}, [clearOverlay]);
|
|
1325
|
-
const scheduleRecompute = useCallback3(() => {
|
|
1326
|
-
if (pendingFrameRef.current !== null)
|
|
1327
|
-
return;
|
|
1328
|
-
pendingFrameRef.current = window.requestAnimationFrame(recomputeRect);
|
|
1329
|
-
}, [recomputeRect]);
|
|
1330
|
-
const onHighlightMessage = useCallback3((msg) => {
|
|
1331
|
-
const parsed = parseHighlightMessage(msg.payload);
|
|
1332
|
-
if (!parsed)
|
|
1333
|
-
return;
|
|
1334
|
-
if (parsed.type === "clear") {
|
|
1335
|
-
clearOverlay();
|
|
1336
|
-
return;
|
|
1337
|
-
}
|
|
1338
|
-
const target = findElementByRef(parsed.ref);
|
|
1339
|
-
if (!target) {
|
|
1340
|
-
clearOverlay();
|
|
1341
|
-
return;
|
|
1342
|
-
}
|
|
1343
|
-
targetElementRef.current = target;
|
|
1344
|
-
setOverlayState({
|
|
1345
|
-
ref: parsed.ref,
|
|
1346
|
-
message: parsed.message ?? "",
|
|
1347
|
-
rect: getRectInTopViewport(target)
|
|
1348
|
-
});
|
|
1349
|
-
}, [clearOverlay]);
|
|
1350
|
-
useDataChannel(HIGHLIGHT_TOPIC, onHighlightMessage);
|
|
1351
|
-
useEffect5(() => {
|
|
1352
|
-
if (!overlayState)
|
|
1353
|
-
return;
|
|
1354
|
-
const target = targetElementRef.current;
|
|
1355
|
-
if (!target)
|
|
1356
|
-
return;
|
|
1357
|
-
const onScroll = () => scheduleRecompute();
|
|
1358
|
-
const onResize = () => scheduleRecompute();
|
|
1359
|
-
const watchedWindows = new Set;
|
|
1360
|
-
watchedWindows.add(window);
|
|
1361
|
-
const ownerWindow = target.ownerDocument?.defaultView;
|
|
1362
|
-
if (ownerWindow && ownerWindow !== window)
|
|
1363
|
-
watchedWindows.add(ownerWindow);
|
|
1364
|
-
for (const win of watchedWindows) {
|
|
1365
|
-
win.addEventListener("scroll", onScroll, { capture: true, passive: true });
|
|
1366
|
-
win.addEventListener("resize", onResize, { passive: true });
|
|
1367
|
-
}
|
|
1368
|
-
const resizeObserver = new ResizeObserver(scheduleRecompute);
|
|
1369
|
-
resizeObserver.observe(target);
|
|
1370
|
-
const scrollContainer = findScrollableAncestor(target);
|
|
1371
|
-
const mutationObserver = new MutationObserver(() => {
|
|
1372
|
-
if (!targetElementRef.current?.isConnected) {
|
|
1373
|
-
clearOverlay();
|
|
1374
|
-
return;
|
|
1375
|
-
}
|
|
1376
|
-
scheduleRecompute();
|
|
1377
|
-
});
|
|
1378
|
-
mutationObserver.observe(scrollContainer, { childList: true, subtree: true });
|
|
1379
|
-
return () => {
|
|
1380
|
-
for (const win of watchedWindows) {
|
|
1381
|
-
win.removeEventListener("scroll", onScroll, { capture: true });
|
|
1382
|
-
win.removeEventListener("resize", onResize);
|
|
1383
|
-
}
|
|
1384
|
-
resizeObserver.disconnect();
|
|
1385
|
-
mutationObserver.disconnect();
|
|
1386
|
-
if (pendingFrameRef.current !== null) {
|
|
1387
|
-
window.cancelAnimationFrame(pendingFrameRef.current);
|
|
1388
|
-
pendingFrameRef.current = null;
|
|
1389
|
-
}
|
|
1390
|
-
};
|
|
1391
|
-
}, [overlayState, scheduleRecompute, clearOverlay]);
|
|
1392
|
-
if (!overlayState)
|
|
1393
|
-
return null;
|
|
1394
|
-
const { rect, message } = overlayState;
|
|
1395
|
-
const ringStyle = {
|
|
1396
|
-
position: "fixed",
|
|
1397
|
-
left: `${rect.left}px`,
|
|
1398
|
-
top: `${rect.top}px`,
|
|
1399
|
-
width: `${rect.width}px`,
|
|
1400
|
-
height: `${rect.height}px`,
|
|
1401
|
-
pointerEvents: "none",
|
|
1402
|
-
zIndex: Z_INDEX,
|
|
1403
|
-
boxShadow: `0 0 0 2px ${RING_INNER}, 0 0 0 6px ${RING_OUTER}`,
|
|
1404
|
-
borderRadius: "4px",
|
|
1405
|
-
transition: "none"
|
|
1406
|
-
};
|
|
1407
|
-
const showTooltipBelow = rect.top < TOOLTIP_TOP_THRESHOLD;
|
|
1408
|
-
const tooltipTop = showTooltipBelow ? rect.bottom + TOOLTIP_GAP : rect.top - TOOLTIP_GAP;
|
|
1409
|
-
const tooltipTransform = showTooltipBelow ? "translateY(0)" : "translateY(-100%)";
|
|
1410
|
-
const tooltipLeft = Math.min(Math.max(rect.left, VIEWPORT_MARGIN), window.innerWidth - TOOLTIP_MAX_WIDTH - VIEWPORT_MARGIN);
|
|
1411
|
-
const tooltipStyle = {
|
|
1412
|
-
position: "fixed",
|
|
1413
|
-
left: `${tooltipLeft}px`,
|
|
1414
|
-
top: `${tooltipTop}px`,
|
|
1415
|
-
transform: tooltipTransform,
|
|
1416
|
-
maxWidth: `${TOOLTIP_MAX_WIDTH}px`,
|
|
1417
|
-
pointerEvents: "none",
|
|
1418
|
-
zIndex: Z_INDEX,
|
|
1419
|
-
background: "rgba(45, 43, 61, 0.96)",
|
|
1420
|
-
color: "#ffffff",
|
|
1421
|
-
padding: "6px 10px",
|
|
1422
|
-
borderRadius: "8px",
|
|
1423
|
-
fontSize: "13px",
|
|
1424
|
-
lineHeight: "1.35",
|
|
1425
|
-
fontFamily: 'ui-sans-serif, system-ui, -apple-system, "Segoe UI", Roboto, Inter, sans-serif',
|
|
1426
|
-
boxShadow: "0 6px 20px rgba(0, 0, 0, 0.25)",
|
|
1427
|
-
whiteSpace: "normal",
|
|
1428
|
-
wordWrap: "break-word"
|
|
1429
|
-
};
|
|
1430
|
-
return /* @__PURE__ */ jsxs(Fragment, {
|
|
1431
|
-
children: [
|
|
1432
|
-
/* @__PURE__ */ jsx("div", {
|
|
1433
|
-
"data-skippr-private": "true",
|
|
1434
|
-
style: ringStyle,
|
|
1435
|
-
"aria-hidden": "true"
|
|
1436
|
-
}),
|
|
1437
|
-
message && /* @__PURE__ */ jsx("div", {
|
|
1438
|
-
"data-skippr-private": "true",
|
|
1439
|
-
style: tooltipStyle,
|
|
1440
|
-
role: "tooltip",
|
|
1441
|
-
children: message
|
|
1442
|
-
})
|
|
1443
|
-
]
|
|
1444
|
-
});
|
|
1445
|
-
}
|
|
1446
1197
|
// ../../node_modules/.bun/lucide-react@1.8.0+83d5fd7b249dbeef/node_modules/lucide-react/dist/esm/createLucideIcon.js
|
|
1447
1198
|
import { forwardRef as forwardRef2, createElement as createElement3 } from "react";
|
|
1448
1199
|
|
|
@@ -1640,8 +1391,19 @@ var __iconNode14 = [
|
|
|
1640
1391
|
["line", { x1: "12", x2: "12", y1: "17", y2: "21", key: "vw1qmm" }]
|
|
1641
1392
|
];
|
|
1642
1393
|
var Monitor = createLucideIcon("monitor", __iconNode14);
|
|
1643
|
-
// ../../node_modules/.bun/lucide-react@1.8.0+83d5fd7b249dbeef/node_modules/lucide-react/dist/esm/icons/
|
|
1394
|
+
// ../../node_modules/.bun/lucide-react@1.8.0+83d5fd7b249dbeef/node_modules/lucide-react/dist/esm/icons/mouse-pointer-2.js
|
|
1644
1395
|
var __iconNode15 = [
|
|
1396
|
+
[
|
|
1397
|
+
"path",
|
|
1398
|
+
{
|
|
1399
|
+
d: "M4.037 4.688a.495.495 0 0 1 .651-.651l16 6.5a.5.5 0 0 1-.063.947l-6.124 1.58a2 2 0 0 0-1.438 1.435l-1.579 6.126a.5.5 0 0 1-.947.063z",
|
|
1400
|
+
key: "edeuup"
|
|
1401
|
+
}
|
|
1402
|
+
]
|
|
1403
|
+
];
|
|
1404
|
+
var MousePointer2 = createLucideIcon("mouse-pointer-2", __iconNode15);
|
|
1405
|
+
// ../../node_modules/.bun/lucide-react@1.8.0+83d5fd7b249dbeef/node_modules/lucide-react/dist/esm/icons/phone-off.js
|
|
1406
|
+
var __iconNode16 = [
|
|
1645
1407
|
[
|
|
1646
1408
|
"path",
|
|
1647
1409
|
{
|
|
@@ -1658,9 +1420,9 @@ var __iconNode15 = [
|
|
|
1658
1420
|
}
|
|
1659
1421
|
]
|
|
1660
1422
|
];
|
|
1661
|
-
var PhoneOff = createLucideIcon("phone-off",
|
|
1423
|
+
var PhoneOff = createLucideIcon("phone-off", __iconNode16);
|
|
1662
1424
|
// ../../node_modules/.bun/lucide-react@1.8.0+83d5fd7b249dbeef/node_modules/lucide-react/dist/esm/icons/send.js
|
|
1663
|
-
var
|
|
1425
|
+
var __iconNode17 = [
|
|
1664
1426
|
[
|
|
1665
1427
|
"path",
|
|
1666
1428
|
{
|
|
@@ -1670,7 +1432,238 @@ var __iconNode16 = [
|
|
|
1670
1432
|
],
|
|
1671
1433
|
["path", { d: "m21.854 2.147-10.94 10.939", key: "12cjpa" }]
|
|
1672
1434
|
];
|
|
1673
|
-
var Send = createLucideIcon("send",
|
|
1435
|
+
var Send = createLucideIcon("send", __iconNode17);
|
|
1436
|
+
// src/components/HighlightOverlay.tsx
|
|
1437
|
+
import { useCallback as useCallback3, useEffect as useEffect5, useRef as useRef3, useState as useState3 } from "react";
|
|
1438
|
+
import { jsx, jsxs } from "react/jsx-runtime";
|
|
1439
|
+
var Z_INDEX = 2147483646;
|
|
1440
|
+
var HIGHLIGHT_PADDING = 6;
|
|
1441
|
+
var textDecoder = new TextDecoder;
|
|
1442
|
+
function parseHighlightMessage(payload) {
|
|
1443
|
+
try {
|
|
1444
|
+
const json = JSON.parse(textDecoder.decode(payload));
|
|
1445
|
+
if (!json || typeof json !== "object")
|
|
1446
|
+
return null;
|
|
1447
|
+
if (json.type === "show" && typeof json.ref === "string") {
|
|
1448
|
+
return {
|
|
1449
|
+
type: "show",
|
|
1450
|
+
ref: json.ref,
|
|
1451
|
+
message: typeof json.message === "string" ? json.message : undefined
|
|
1452
|
+
};
|
|
1453
|
+
}
|
|
1454
|
+
if (json.type === "clear")
|
|
1455
|
+
return { type: "clear" };
|
|
1456
|
+
return null;
|
|
1457
|
+
} catch {
|
|
1458
|
+
return null;
|
|
1459
|
+
}
|
|
1460
|
+
}
|
|
1461
|
+
function safeGetIframeDocument(iframe) {
|
|
1462
|
+
try {
|
|
1463
|
+
return iframe.contentDocument;
|
|
1464
|
+
} catch {
|
|
1465
|
+
return null;
|
|
1466
|
+
}
|
|
1467
|
+
}
|
|
1468
|
+
function safeQuerySelector(doc, selector) {
|
|
1469
|
+
try {
|
|
1470
|
+
return doc.querySelector(selector);
|
|
1471
|
+
} catch {
|
|
1472
|
+
return null;
|
|
1473
|
+
}
|
|
1474
|
+
}
|
|
1475
|
+
function safeQueryAllIframes(doc) {
|
|
1476
|
+
try {
|
|
1477
|
+
return Array.from(doc.querySelectorAll("iframe"));
|
|
1478
|
+
} catch {
|
|
1479
|
+
return [];
|
|
1480
|
+
}
|
|
1481
|
+
}
|
|
1482
|
+
function findElementInDocumentTree(rootDoc, selector) {
|
|
1483
|
+
const hit = safeQuerySelector(rootDoc, selector);
|
|
1484
|
+
if (hit)
|
|
1485
|
+
return hit;
|
|
1486
|
+
for (const iframe of safeQueryAllIframes(rootDoc)) {
|
|
1487
|
+
const innerDoc = safeGetIframeDocument(iframe);
|
|
1488
|
+
if (!innerDoc)
|
|
1489
|
+
continue;
|
|
1490
|
+
const nested = findElementInDocumentTree(innerDoc, selector);
|
|
1491
|
+
if (nested)
|
|
1492
|
+
return nested;
|
|
1493
|
+
}
|
|
1494
|
+
return null;
|
|
1495
|
+
}
|
|
1496
|
+
function findElementByRef(ref) {
|
|
1497
|
+
const selector = `[${REF_ATTR}="${CSS.escape(ref)}"]`;
|
|
1498
|
+
return findElementInDocumentTree(document, selector);
|
|
1499
|
+
}
|
|
1500
|
+
function findIframeHostingDocument(targetDoc) {
|
|
1501
|
+
const queue = [document];
|
|
1502
|
+
while (queue.length > 0) {
|
|
1503
|
+
const doc = queue.shift();
|
|
1504
|
+
if (!doc)
|
|
1505
|
+
continue;
|
|
1506
|
+
for (const iframe of safeQueryAllIframes(doc)) {
|
|
1507
|
+
if (safeGetIframeDocument(iframe) === targetDoc)
|
|
1508
|
+
return iframe;
|
|
1509
|
+
const innerDoc = safeGetIframeDocument(iframe);
|
|
1510
|
+
if (innerDoc)
|
|
1511
|
+
queue.push(innerDoc);
|
|
1512
|
+
}
|
|
1513
|
+
}
|
|
1514
|
+
return null;
|
|
1515
|
+
}
|
|
1516
|
+
function getRectInTopViewport(el) {
|
|
1517
|
+
let rect = el.getBoundingClientRect();
|
|
1518
|
+
let ownerDoc = el.ownerDocument;
|
|
1519
|
+
while (ownerDoc && ownerDoc !== document) {
|
|
1520
|
+
const hostingIframe = findIframeHostingDocument(ownerDoc);
|
|
1521
|
+
if (!hostingIframe)
|
|
1522
|
+
return rect;
|
|
1523
|
+
const iframeRect = hostingIframe.getBoundingClientRect();
|
|
1524
|
+
rect = new DOMRect(rect.left + iframeRect.left, rect.top + iframeRect.top, rect.width, rect.height);
|
|
1525
|
+
ownerDoc = hostingIframe.ownerDocument;
|
|
1526
|
+
}
|
|
1527
|
+
return rect;
|
|
1528
|
+
}
|
|
1529
|
+
function findScrollableAncestor(el) {
|
|
1530
|
+
const win = el.ownerDocument?.defaultView ?? window;
|
|
1531
|
+
let node = el.parentElement;
|
|
1532
|
+
while (node) {
|
|
1533
|
+
const overflow = win.getComputedStyle(node).overflow;
|
|
1534
|
+
if (/auto|scroll|overlay/.test(overflow))
|
|
1535
|
+
return node;
|
|
1536
|
+
node = node.parentElement;
|
|
1537
|
+
}
|
|
1538
|
+
return el.ownerDocument?.documentElement ?? document.documentElement;
|
|
1539
|
+
}
|
|
1540
|
+
function HighlightOverlay() {
|
|
1541
|
+
const [overlayState, setOverlayState] = useState3(null);
|
|
1542
|
+
const targetElementRef = useRef3(null);
|
|
1543
|
+
const pendingFrameRef = useRef3(null);
|
|
1544
|
+
const clearOverlay = useCallback3(() => {
|
|
1545
|
+
targetElementRef.current = null;
|
|
1546
|
+
setOverlayState(null);
|
|
1547
|
+
}, []);
|
|
1548
|
+
const recomputeRect = useCallback3(() => {
|
|
1549
|
+
pendingFrameRef.current = null;
|
|
1550
|
+
const target = targetElementRef.current;
|
|
1551
|
+
if (!target)
|
|
1552
|
+
return;
|
|
1553
|
+
if (!target.isConnected) {
|
|
1554
|
+
clearOverlay();
|
|
1555
|
+
return;
|
|
1556
|
+
}
|
|
1557
|
+
const rect2 = getRectInTopViewport(target);
|
|
1558
|
+
setOverlayState((prev) => prev ? { ...prev, rect: rect2 } : prev);
|
|
1559
|
+
}, [clearOverlay]);
|
|
1560
|
+
const scheduleRecompute = useCallback3(() => {
|
|
1561
|
+
if (pendingFrameRef.current !== null)
|
|
1562
|
+
return;
|
|
1563
|
+
pendingFrameRef.current = window.requestAnimationFrame(recomputeRect);
|
|
1564
|
+
}, [recomputeRect]);
|
|
1565
|
+
const onHighlightMessage = useCallback3((msg) => {
|
|
1566
|
+
const parsed = parseHighlightMessage(msg.payload);
|
|
1567
|
+
if (!parsed)
|
|
1568
|
+
return;
|
|
1569
|
+
if (parsed.type === "clear") {
|
|
1570
|
+
clearOverlay();
|
|
1571
|
+
return;
|
|
1572
|
+
}
|
|
1573
|
+
const target = findElementByRef(parsed.ref);
|
|
1574
|
+
if (!target) {
|
|
1575
|
+
clearOverlay();
|
|
1576
|
+
return;
|
|
1577
|
+
}
|
|
1578
|
+
targetElementRef.current = target;
|
|
1579
|
+
setOverlayState({
|
|
1580
|
+
ref: parsed.ref,
|
|
1581
|
+
message: parsed.message || "Click here",
|
|
1582
|
+
rect: getRectInTopViewport(target)
|
|
1583
|
+
});
|
|
1584
|
+
}, [clearOverlay]);
|
|
1585
|
+
useDataChannel(HIGHLIGHT_TOPIC, onHighlightMessage);
|
|
1586
|
+
useEffect5(() => {
|
|
1587
|
+
if (!overlayState)
|
|
1588
|
+
return;
|
|
1589
|
+
const target = targetElementRef.current;
|
|
1590
|
+
if (!target)
|
|
1591
|
+
return;
|
|
1592
|
+
const onScroll = () => scheduleRecompute();
|
|
1593
|
+
const onResize = () => scheduleRecompute();
|
|
1594
|
+
const watchedWindows = new Set;
|
|
1595
|
+
watchedWindows.add(window);
|
|
1596
|
+
const ownerWindow = target.ownerDocument?.defaultView;
|
|
1597
|
+
if (ownerWindow && ownerWindow !== window)
|
|
1598
|
+
watchedWindows.add(ownerWindow);
|
|
1599
|
+
for (const win of watchedWindows) {
|
|
1600
|
+
win.addEventListener("scroll", onScroll, { capture: true, passive: true });
|
|
1601
|
+
win.addEventListener("resize", onResize, { passive: true });
|
|
1602
|
+
}
|
|
1603
|
+
const resizeObserver = new ResizeObserver(scheduleRecompute);
|
|
1604
|
+
resizeObserver.observe(target);
|
|
1605
|
+
const scrollContainer = findScrollableAncestor(target);
|
|
1606
|
+
const mutationObserver = new MutationObserver(() => {
|
|
1607
|
+
if (!targetElementRef.current?.isConnected) {
|
|
1608
|
+
clearOverlay();
|
|
1609
|
+
return;
|
|
1610
|
+
}
|
|
1611
|
+
scheduleRecompute();
|
|
1612
|
+
});
|
|
1613
|
+
mutationObserver.observe(scrollContainer, { childList: true, subtree: true });
|
|
1614
|
+
return () => {
|
|
1615
|
+
for (const win of watchedWindows) {
|
|
1616
|
+
win.removeEventListener("scroll", onScroll, { capture: true });
|
|
1617
|
+
win.removeEventListener("resize", onResize);
|
|
1618
|
+
}
|
|
1619
|
+
resizeObserver.disconnect();
|
|
1620
|
+
mutationObserver.disconnect();
|
|
1621
|
+
if (pendingFrameRef.current !== null) {
|
|
1622
|
+
window.cancelAnimationFrame(pendingFrameRef.current);
|
|
1623
|
+
pendingFrameRef.current = null;
|
|
1624
|
+
}
|
|
1625
|
+
};
|
|
1626
|
+
}, [overlayState, scheduleRecompute, clearOverlay]);
|
|
1627
|
+
if (!overlayState)
|
|
1628
|
+
return null;
|
|
1629
|
+
const { rect, message } = overlayState;
|
|
1630
|
+
const containerStyle = {
|
|
1631
|
+
position: "fixed",
|
|
1632
|
+
left: `${rect.left - HIGHLIGHT_PADDING}px`,
|
|
1633
|
+
top: `${rect.top - HIGHLIGHT_PADDING}px`,
|
|
1634
|
+
width: `${rect.width + HIGHLIGHT_PADDING * 2}px`,
|
|
1635
|
+
height: `${rect.height + HIGHLIGHT_PADDING * 2}px`,
|
|
1636
|
+
pointerEvents: "none",
|
|
1637
|
+
zIndex: Z_INDEX
|
|
1638
|
+
};
|
|
1639
|
+
return /* @__PURE__ */ jsxs("div", {
|
|
1640
|
+
"data-skippr-private": "true",
|
|
1641
|
+
style: containerStyle,
|
|
1642
|
+
className: "skippr:relative",
|
|
1643
|
+
children: [
|
|
1644
|
+
/* @__PURE__ */ jsx("div", {
|
|
1645
|
+
"aria-hidden": "true",
|
|
1646
|
+
className: "skippr:absolute skippr:inset-0 skippr:rounded-[1rem] skippr:border-2 skippr:border-cyan-400 skippr:animate-skippr-annotation-pulse"
|
|
1647
|
+
}),
|
|
1648
|
+
/* @__PURE__ */ jsxs("div", {
|
|
1649
|
+
role: "tooltip",
|
|
1650
|
+
className: "skippr:absolute skippr:-bottom-9 skippr:left-1/2 skippr:-translate-x-1/2 skippr:flex skippr:items-center skippr:gap-1.5 skippr:rounded-full skippr:bg-cyan-400 skippr:px-2.5 skippr:py-1 skippr:shadow-[0_4px_12px_rgba(0,0,0,0.12)]",
|
|
1651
|
+
children: [
|
|
1652
|
+
/* @__PURE__ */ jsx(MousePointer2, {
|
|
1653
|
+
"aria-hidden": "true",
|
|
1654
|
+
className: "skippr:h-3 skippr:w-3 skippr:text-cyan-900",
|
|
1655
|
+
fill: "currentColor"
|
|
1656
|
+
}),
|
|
1657
|
+
/* @__PURE__ */ jsx("span", {
|
|
1658
|
+
className: "skippr:text-[11px] skippr:font-medium skippr:text-cyan-900 skippr:whitespace-nowrap",
|
|
1659
|
+
children: message
|
|
1660
|
+
})
|
|
1661
|
+
]
|
|
1662
|
+
})
|
|
1663
|
+
]
|
|
1664
|
+
});
|
|
1665
|
+
}
|
|
1666
|
+
|
|
1674
1667
|
// src/components/MinimizedBubble.tsx
|
|
1675
1668
|
import { useEffect as useEffect6 } from "react";
|
|
1676
1669
|
|
|
@@ -1734,7 +1727,7 @@ function useAgentVoiceState() {
|
|
|
1734
1727
|
}
|
|
1735
1728
|
|
|
1736
1729
|
// src/components/LauncherStatusPill.tsx
|
|
1737
|
-
import { jsx as jsx2, jsxs as jsxs2, Fragment
|
|
1730
|
+
import { jsx as jsx2, jsxs as jsxs2, Fragment } from "react/jsx-runtime";
|
|
1738
1731
|
function pillStatusFromAgent(state, canSeePage) {
|
|
1739
1732
|
if (state === "speaking")
|
|
1740
1733
|
return "talking";
|
|
@@ -1762,7 +1755,7 @@ function LauncherStatusPill() {
|
|
|
1762
1755
|
children: /* @__PURE__ */ jsxs2("span", {
|
|
1763
1756
|
className: "skippr:flex skippr:items-center skippr:gap-2 skippr:animate-[skippr-pill-content_0.22s_ease-out]",
|
|
1764
1757
|
children: [
|
|
1765
|
-
status === "observing" && /* @__PURE__ */ jsxs2(
|
|
1758
|
+
status === "observing" && /* @__PURE__ */ jsxs2(Fragment, {
|
|
1766
1759
|
children: [
|
|
1767
1760
|
/* @__PURE__ */ jsx2(ObservingIcon, {}),
|
|
1768
1761
|
/* @__PURE__ */ jsx2("span", {
|
|
@@ -1770,7 +1763,7 @@ function LauncherStatusPill() {
|
|
|
1770
1763
|
})
|
|
1771
1764
|
]
|
|
1772
1765
|
}),
|
|
1773
|
-
status === "connected" && /* @__PURE__ */ jsxs2(
|
|
1766
|
+
status === "connected" && /* @__PURE__ */ jsxs2(Fragment, {
|
|
1774
1767
|
children: [
|
|
1775
1768
|
/* @__PURE__ */ jsx2(ConnectedDot, {}),
|
|
1776
1769
|
/* @__PURE__ */ jsx2("span", {
|
|
@@ -1778,7 +1771,7 @@ function LauncherStatusPill() {
|
|
|
1778
1771
|
})
|
|
1779
1772
|
]
|
|
1780
1773
|
}),
|
|
1781
|
-
status === "talking" && /* @__PURE__ */ jsxs2(
|
|
1774
|
+
status === "talking" && /* @__PURE__ */ jsxs2(Fragment, {
|
|
1782
1775
|
children: [
|
|
1783
1776
|
/* @__PURE__ */ jsx2(SpeakingBars, {}),
|
|
1784
1777
|
/* @__PURE__ */ jsx2("span", {
|
|
@@ -1786,7 +1779,7 @@ function LauncherStatusPill() {
|
|
|
1786
1779
|
})
|
|
1787
1780
|
]
|
|
1788
1781
|
}),
|
|
1789
|
-
status === "thinking" && /* @__PURE__ */ jsxs2(
|
|
1782
|
+
status === "thinking" && /* @__PURE__ */ jsxs2(Fragment, {
|
|
1790
1783
|
children: [
|
|
1791
1784
|
/* @__PURE__ */ jsx2(ThinkingDots, {}),
|
|
1792
1785
|
/* @__PURE__ */ jsx2("span", {
|
|
@@ -1958,7 +1951,7 @@ function Logo({ className }) {
|
|
|
1958
1951
|
}
|
|
1959
1952
|
|
|
1960
1953
|
// src/components/MinimizedBubble.tsx
|
|
1961
|
-
import { jsx as jsx4, jsxs as jsxs4, Fragment as
|
|
1954
|
+
import { jsx as jsx4, jsxs as jsxs4, Fragment as Fragment2 } from "react/jsx-runtime";
|
|
1962
1955
|
var CONTROL_BUTTON = "skippr:flex skippr:size-12 skippr:items-center skippr:justify-center skippr:rounded-[14px] skippr:cursor-pointer skippr:transition-all skippr:hover:-translate-y-0.5 skippr:active:translate-y-0";
|
|
1963
1956
|
var CONTROL_SHADOW = "skippr:shadow-[0_4px_16px_rgba(0,0,0,0.15),0_2px_4px_rgba(0,0,0,0.1)]";
|
|
1964
1957
|
function ConnectedLauncher() {
|
|
@@ -1969,7 +1962,7 @@ function ConnectedLauncher() {
|
|
|
1969
1962
|
setSidebarTab("chat");
|
|
1970
1963
|
expandPanel();
|
|
1971
1964
|
};
|
|
1972
|
-
return /* @__PURE__ */ jsxs4(
|
|
1965
|
+
return /* @__PURE__ */ jsxs4(Fragment2, {
|
|
1973
1966
|
children: [
|
|
1974
1967
|
/* @__PURE__ */ jsx4("button", {
|
|
1975
1968
|
type: "button",
|
|
@@ -2055,7 +2048,7 @@ function MinimizedBubble({
|
|
|
2055
2048
|
}) {
|
|
2056
2049
|
const { isConnected, isStarting, position } = useLiveAgent();
|
|
2057
2050
|
const inSession = isConnected || isStarting;
|
|
2058
|
-
return /* @__PURE__ */ jsxs4(
|
|
2051
|
+
return /* @__PURE__ */ jsxs4(Fragment2, {
|
|
2059
2052
|
children: [
|
|
2060
2053
|
/* @__PURE__ */ jsx4(LauncherStatusPill, {}),
|
|
2061
2054
|
/* @__PURE__ */ jsxs4("div", {
|
|
@@ -2969,7 +2962,7 @@ function StartSessionPrompt({
|
|
|
2969
2962
|
}
|
|
2970
2963
|
|
|
2971
2964
|
// src/components/Sidebar.tsx
|
|
2972
|
-
import { jsx as jsx17, jsxs as jsxs15, Fragment as
|
|
2965
|
+
import { jsx as jsx17, jsxs as jsxs15, Fragment as Fragment3 } from "react/jsx-runtime";
|
|
2973
2966
|
function Sidebar({
|
|
2974
2967
|
hideControls = false,
|
|
2975
2968
|
hideHeader = false,
|
|
@@ -3055,7 +3048,7 @@ function AuthenticatedContent({
|
|
|
3055
3048
|
autoFocusChat,
|
|
3056
3049
|
showScreenShareToggle
|
|
3057
3050
|
}) {
|
|
3058
|
-
return /* @__PURE__ */ jsxs15(
|
|
3051
|
+
return /* @__PURE__ */ jsxs15(Fragment3, {
|
|
3059
3052
|
children: [
|
|
3060
3053
|
isConnected && /* @__PURE__ */ jsx17(ConnectedBanner, {}),
|
|
3061
3054
|
/* @__PURE__ */ jsxs15("div", {
|