waygraph 0.12.36 → 0.12.37
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/cli.js +125 -32
- package/package.json +1 -1
package/dist/cli.js
CHANGED
|
@@ -711,6 +711,7 @@ async function installOverlay(page, title) {
|
|
|
711
711
|
const cursor = document.getElementById("wg-cursor");
|
|
712
712
|
if (!cursor) return;
|
|
713
713
|
const travel = ms || 600;
|
|
714
|
+
window.__wgCursorPos = { x: Number(x) || 0, y: Number(y) || 0 };
|
|
714
715
|
cursor.style.setProperty("--wg-cursor-ms", travel + "ms");
|
|
715
716
|
if (instant) {
|
|
716
717
|
const prev = cursor.style.transition;
|
|
@@ -811,6 +812,50 @@ async function installOverlay(page, title) {
|
|
|
811
812
|
let settled = zoom <= 1;
|
|
812
813
|
const settleAt = Date.now() + camMs;
|
|
813
814
|
const style = { size, weight, focus, color };
|
|
815
|
+
// Screen Studio / Screenify: dead zone = center ~40% of viewport.
|
|
816
|
+
// Pan only when the demo cursor leaves that zone - never hard-center
|
|
817
|
+
// on every mousemove (that fights like same-pole magnets).
|
|
818
|
+
const deadFrac = 0.4;
|
|
819
|
+
let lastPanAt = 0;
|
|
820
|
+
const readCursorViewport = () => {
|
|
821
|
+
const cursor = document.getElementById("wg-cursor");
|
|
822
|
+
if (cursor && cursor.style.opacity !== "0") {
|
|
823
|
+
const r = cursor.getBoundingClientRect();
|
|
824
|
+
if (r.width || r.height || r.left || r.top) {
|
|
825
|
+
return { x: r.left, y: r.top };
|
|
826
|
+
}
|
|
827
|
+
}
|
|
828
|
+
if (window.__wgCursorPos) return window.__wgCursorPos;
|
|
829
|
+
return null;
|
|
830
|
+
};
|
|
831
|
+
const followTick = () => {
|
|
832
|
+
if (!followMouse || !settled || window.__wgCameraLock) return;
|
|
833
|
+
if (!window.__wgSetCamera || !window.__wgViewportToDoc) return;
|
|
834
|
+
const cam = window.__wgCamera;
|
|
835
|
+
if (!cam || !(cam.scale > 1.001)) return;
|
|
836
|
+
const pos = readCursorViewport();
|
|
837
|
+
if (!pos) return;
|
|
838
|
+
const vw = window.innerWidth;
|
|
839
|
+
const vh = window.innerHeight;
|
|
840
|
+
const dx = pos.x - vw / 2;
|
|
841
|
+
const dy = pos.y - vh / 2;
|
|
842
|
+
const deadX = (vw * deadFrac) / 2;
|
|
843
|
+
const deadY = (vh * deadFrac) / 2;
|
|
844
|
+
let ox = 0;
|
|
845
|
+
let oy = 0;
|
|
846
|
+
if (dx > deadX) ox = dx - deadX;
|
|
847
|
+
else if (dx < -deadX) ox = dx + deadX;
|
|
848
|
+
if (dy > deadY) oy = dy - deadY;
|
|
849
|
+
else if (dy < -deadY) oy = dy + deadY;
|
|
850
|
+
if (ox === 0 && oy === 0) return;
|
|
851
|
+
const now = Date.now();
|
|
852
|
+
if (now - lastPanAt < 80) return;
|
|
853
|
+
lastPanAt = now;
|
|
854
|
+
// Viewport overflow -> document delta (divide by scale).
|
|
855
|
+
const nx = cam.cx + ox / cam.scale;
|
|
856
|
+
const ny = cam.cy + oy / cam.scale;
|
|
857
|
+
window.__wgSetCamera(nx, ny, cam.scale, 220);
|
|
858
|
+
};
|
|
814
859
|
const tick = () => {
|
|
815
860
|
const el = document.querySelector(sel);
|
|
816
861
|
if (el && window.__wgPositionRing) {
|
|
@@ -823,32 +868,34 @@ async function installOverlay(page, title) {
|
|
|
823
868
|
);
|
|
824
869
|
}
|
|
825
870
|
if (!settled && Date.now() >= settleAt) settled = true;
|
|
871
|
+
followTick();
|
|
826
872
|
window.__wgRingRaf = requestAnimationFrame(tick);
|
|
827
873
|
};
|
|
828
874
|
if (zoom > 1 && window.__wgSetCamera) {
|
|
829
875
|
const el0 = document.querySelector(sel);
|
|
830
876
|
if (el0) {
|
|
831
|
-
const r0 = el0.getBoundingClientRect();
|
|
832
877
|
const already =
|
|
833
878
|
window.__wgCamera && window.__wgCamera.scale > 1.001;
|
|
834
|
-
// Already zoomed (zoomOut:false chain): short pan, not full zoom-in.
|
|
835
879
|
const dur = already ? Math.min(camMs, 420) : camMs;
|
|
836
|
-
|
|
837
|
-
|
|
838
|
-
|
|
839
|
-
|
|
840
|
-
|
|
841
|
-
|
|
880
|
+
// Focus must be document-space, not raw getBoundingClientRect
|
|
881
|
+
// (viewport) - otherwise already-zoomed pans fight the cursor.
|
|
882
|
+
const pt = window.__wgElDocPoint
|
|
883
|
+
? window.__wgElDocPoint(el0)
|
|
884
|
+
: {
|
|
885
|
+
x: el0.getBoundingClientRect().left + el0.getBoundingClientRect().width / 2,
|
|
886
|
+
y: el0.getBoundingClientRect().top + el0.getBoundingClientRect().height / 2,
|
|
887
|
+
};
|
|
888
|
+
window.__wgCameraLock = true;
|
|
889
|
+
window.__wgSetCamera(pt.x, pt.y, zoom, dur);
|
|
890
|
+
setTimeout(() => {
|
|
891
|
+
window.__wgCameraLock = false;
|
|
892
|
+
}, dur + 40);
|
|
842
893
|
}
|
|
843
894
|
}
|
|
844
895
|
window.__wgRingRaf = requestAnimationFrame(tick);
|
|
896
|
+
// Real mouse only seeds cursor pos; dead-zone follow runs in RAF.
|
|
845
897
|
const onMove = (ev) => {
|
|
846
|
-
|
|
847
|
-
if (!window.__wgSetCamera) return;
|
|
848
|
-
const cam = window.__wgCamera;
|
|
849
|
-
const scale = (cam && cam.scale > 1 ? cam.scale : zoom) || zoom;
|
|
850
|
-
if (!(scale > 1)) return;
|
|
851
|
-
window.__wgSetCamera(ev.clientX, ev.clientY, scale, 140);
|
|
898
|
+
window.__wgCursorPos = { x: ev.clientX, y: ev.clientY };
|
|
852
899
|
};
|
|
853
900
|
window.addEventListener("mousemove", onMove, { passive: true });
|
|
854
901
|
window.__wgRingTrack = onMove;
|
|
@@ -893,7 +940,34 @@ async function installOverlay(page, title) {
|
|
|
893
940
|
// rings; only resetCameraZoom / teardown call __wgClearZoom.
|
|
894
941
|
};
|
|
895
942
|
// Screen Studio-style camera: scale <body>, keep overlays on <html> fixed.
|
|
896
|
-
|
|
943
|
+
// Focus (cx,cy) is DOCUMENT space (pre-transform). Viewport mouse/rects
|
|
944
|
+
// must go through __wgViewportToDoc before SetCamera.
|
|
945
|
+
window.__wgCamera = {
|
|
946
|
+
scale: 1,
|
|
947
|
+
cx: window.innerWidth / 2,
|
|
948
|
+
cy: window.innerHeight / 2,
|
|
949
|
+
};
|
|
950
|
+
window.__wgCameraLock = false;
|
|
951
|
+
window.__wgViewportToDoc = (vx, vy) => {
|
|
952
|
+
const cam = window.__wgCamera || {
|
|
953
|
+
scale: 1,
|
|
954
|
+
cx: window.innerWidth / 2,
|
|
955
|
+
cy: window.innerHeight / 2,
|
|
956
|
+
};
|
|
957
|
+
const s = cam.scale > 1.001 ? cam.scale : 1;
|
|
958
|
+
if (s <= 1.001) return { x: vx, y: vy };
|
|
959
|
+
return {
|
|
960
|
+
x: (vx - window.innerWidth / 2) / s + cam.cx,
|
|
961
|
+
y: (vy - window.innerHeight / 2) / s + cam.cy,
|
|
962
|
+
};
|
|
963
|
+
};
|
|
964
|
+
window.__wgElDocPoint = (el) => {
|
|
965
|
+
const r = el.getBoundingClientRect();
|
|
966
|
+
return window.__wgViewportToDoc(
|
|
967
|
+
r.left + r.width / 2,
|
|
968
|
+
r.top + r.height / 2,
|
|
969
|
+
);
|
|
970
|
+
};
|
|
897
971
|
window.__wgSetCamera = (fx, fy, scale, ms) => {
|
|
898
972
|
const body = document.body;
|
|
899
973
|
if (!body) return;
|
|
@@ -961,7 +1035,7 @@ async function installOverlay(page, title) {
|
|
|
961
1035
|
'<div class="wg-todo-head">Checklist</div><ul>' + rows + '</ul>';
|
|
962
1036
|
modal.classList.add("wg-todo-on");
|
|
963
1037
|
};
|
|
964
|
-
window.__wgResetCamera = () => {
|
|
1038
|
+
window.__wgResetCamera = () => {
|
|
965
1039
|
window.__wgSetCamera(window.innerWidth / 2, window.innerHeight / 2, 1);
|
|
966
1040
|
};
|
|
967
1041
|
window.__wgClearZoom = () => {
|
|
@@ -1413,13 +1487,17 @@ async function applyCameraZoom(page, box, zoom, ms) {
|
|
|
1413
1487
|
}).catch(() => {});
|
|
1414
1488
|
return;
|
|
1415
1489
|
}
|
|
1416
|
-
const
|
|
1417
|
-
const
|
|
1490
|
+
const vx = box.x + box.width / 2;
|
|
1491
|
+
const vy = box.y + box.height / 2;
|
|
1418
1492
|
const dur = ms != null ? ms : 650;
|
|
1419
1493
|
await page
|
|
1420
|
-
.evaluate(({
|
|
1421
|
-
if (window.__wgSetCamera)
|
|
1422
|
-
|
|
1494
|
+
.evaluate(({ vx, vy, scale, dur }) => {
|
|
1495
|
+
if (!window.__wgSetCamera) return;
|
|
1496
|
+
const pt = window.__wgViewportToDoc
|
|
1497
|
+
? window.__wgViewportToDoc(vx, vy)
|
|
1498
|
+
: { x: vx, y: vy };
|
|
1499
|
+
window.__wgSetCamera(pt.x, pt.y, scale, dur);
|
|
1500
|
+
}, { vx, vy, scale: z, dur })
|
|
1423
1501
|
.catch(() => {});
|
|
1424
1502
|
}
|
|
1425
1503
|
|
|
@@ -1553,16 +1631,9 @@ async function cycleHighlightRings(page, highlights, gatesFast, opts) {
|
|
|
1553
1631
|
: h.follow !== undefined
|
|
1554
1632
|
? !!h.follow
|
|
1555
1633
|
: z > 1;
|
|
1556
|
-
|
|
1557
|
-
|
|
1558
|
-
|
|
1559
|
-
await page
|
|
1560
|
-
.evaluate(({ cx, cy, camMs }) => {
|
|
1561
|
-
if (window.__wgMoveCursorTo) window.__wgMoveCursorTo(cx, cy, camMs, false);
|
|
1562
|
-
}, { cx, cy, camMs })
|
|
1563
|
-
.catch(() => {});
|
|
1564
|
-
}
|
|
1565
|
-
// Track first: ring rides visual rect through the zoom (no re-adjust).
|
|
1634
|
+
// Track/zoom first, then park the demo cursor on the LIVE rect.
|
|
1635
|
+
// Placing the cursor on a pre-zoom boundingBox leaves it stranded after
|
|
1636
|
+
// body scale (html cursor is outside the transform).
|
|
1566
1637
|
await page
|
|
1567
1638
|
.evaluate(
|
|
1568
1639
|
({ sel, label, tone, size, weight, focus, color, zoom, followMouse, camMs }) => {
|
|
@@ -1600,7 +1671,21 @@ async function cycleHighlightRings(page, highlights, gatesFast, opts) {
|
|
|
1600
1671
|
.catch(() => false);
|
|
1601
1672
|
const waitMs = alreadyZoomed ? Math.min(camMs, 420) : camMs;
|
|
1602
1673
|
await new Promise((res) => setTimeout(res, waitMs));
|
|
1603
|
-
|
|
1674
|
+
if (h.cursor !== false) {
|
|
1675
|
+
await page
|
|
1676
|
+
.evaluate(({ sel, ms }) => {
|
|
1677
|
+
const el = document.querySelector(sel);
|
|
1678
|
+
if (!el || !window.__wgMoveCursorTo) return;
|
|
1679
|
+
window.__wgCameraLock = true;
|
|
1680
|
+
const r = el.getBoundingClientRect();
|
|
1681
|
+
window.__wgMoveCursorTo(r.left + r.width / 2, r.top + r.height / 2, ms, false);
|
|
1682
|
+
setTimeout(() => {
|
|
1683
|
+
window.__wgCameraLock = false;
|
|
1684
|
+
}, ms + 40);
|
|
1685
|
+
}, { sel: h.selector, ms: Math.min(280, camMs) })
|
|
1686
|
+
.catch(() => {});
|
|
1687
|
+
await new Promise((res) => setTimeout(res, Math.min(280, camMs)));
|
|
1688
|
+
}
|
|
1604
1689
|
// Appear settle
|
|
1605
1690
|
await new Promise((res) => setTimeout(res, fadeMs));
|
|
1606
1691
|
const authored = resolveFixtureDwellMs(h, { gatesFast, pace });
|
|
@@ -2363,8 +2448,11 @@ async function moveCursorTo(page, box, ms) {
|
|
|
2363
2448
|
const x = box.x + box.width / 2;
|
|
2364
2449
|
const y = box.y + box.height / 2;
|
|
2365
2450
|
const travel = Math.max(0, Number(ms) || 0);
|
|
2451
|
+
// Freeze camera follow while the demo cursor travels - otherwise dead-zone
|
|
2452
|
+
// pans fight the click target (esp. right-edge cart chrome).
|
|
2366
2453
|
await page
|
|
2367
2454
|
.evaluate(({ x, y, ms }) => {
|
|
2455
|
+
window.__wgCameraLock = true;
|
|
2368
2456
|
if (window.__wgMoveCursorTo) window.__wgMoveCursorTo(x, y, ms);
|
|
2369
2457
|
}, { x, y, ms: travel })
|
|
2370
2458
|
.catch(() => {});
|
|
@@ -2374,6 +2462,11 @@ async function moveCursorTo(page, box, ms) {
|
|
|
2374
2462
|
if (travel > 0) {
|
|
2375
2463
|
await new Promise((res) => setTimeout(res, travel));
|
|
2376
2464
|
}
|
|
2465
|
+
await page
|
|
2466
|
+
.evaluate(() => {
|
|
2467
|
+
window.__wgCameraLock = false;
|
|
2468
|
+
})
|
|
2469
|
+
.catch(() => {});
|
|
2377
2470
|
return { x, y };
|
|
2378
2471
|
}
|
|
2379
2472
|
|