waygraph 0.12.38 → 0.12.40
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 +123 -135
- package/dist/highlights.d.ts +3 -4
- package/examples/saucedemo/src/blocks/saucedemo-web/cart/nav-cart.block.ts +2 -2
- package/examples/saucedemo/src/blocks/saucedemo-web/inventory/methods/add-to-cart.effect.block.ts +0 -2
- package/package.json +1 -1
- package/templates/quickstart/src/blocks/saucedemo-web/cart/nav-cart.block.ts +2 -2
- package/templates/quickstart/src/blocks/saucedemo-web/inventory/methods/add-to-cart.effect.block.ts +0 -2
package/dist/cli.js
CHANGED
|
@@ -808,59 +808,11 @@ async function installOverlay(page, title) {
|
|
|
808
808
|
const focus = !!opts.focus;
|
|
809
809
|
const color = opts.color || "";
|
|
810
810
|
const zoom = opts.zoom != null && opts.zoom > 1 ? opts.zoom : 1;
|
|
811
|
-
const followMouse = opts.followMouse !== false && zoom > 1;
|
|
812
811
|
const camMs = opts.camMs != null ? opts.camMs : 700;
|
|
813
|
-
let settled = zoom <= 1;
|
|
814
|
-
const settleAt = Date.now() + camMs;
|
|
815
812
|
const style = { size, weight, focus, color };
|
|
816
|
-
//
|
|
817
|
-
|
|
818
|
-
|
|
819
|
-
const readCursorViewport = () => {
|
|
820
|
-
const cursor = document.getElementById("wg-cursor");
|
|
821
|
-
if (cursor && cursor.style.opacity !== "0") {
|
|
822
|
-
const r = cursor.getBoundingClientRect();
|
|
823
|
-
if (r.width || r.height || r.left || r.top) {
|
|
824
|
-
return { x: r.left, y: r.top };
|
|
825
|
-
}
|
|
826
|
-
}
|
|
827
|
-
if (window.__wgCursorPos) return window.__wgCursorPos;
|
|
828
|
-
return null;
|
|
829
|
-
};
|
|
830
|
-
const followTick = () => {
|
|
831
|
-
if (!followMouse || !settled || window.__wgCameraLock) return;
|
|
832
|
-
if (!window.__wgSetCamera || !window.__wgViewportToDoc) return;
|
|
833
|
-
const cam = window.__wgCamera;
|
|
834
|
-
if (!cam || !(cam.scale > 1.001)) return;
|
|
835
|
-
// Skip while the demo cursor is mid CSS travel - reading a
|
|
836
|
-
// mid-lerp rect makes the camera chase noise and teleport.
|
|
837
|
-
if (window.__wgCursorTravelUntil && Date.now() < window.__wgCursorTravelUntil) {
|
|
838
|
-
return;
|
|
839
|
-
}
|
|
840
|
-
const pos = readCursorViewport();
|
|
841
|
-
if (!pos) return;
|
|
842
|
-
const vw = window.innerWidth;
|
|
843
|
-
const vh = window.innerHeight;
|
|
844
|
-
const dx = pos.x - vw / 2;
|
|
845
|
-
const dy = pos.y - vh / 2;
|
|
846
|
-
const deadX = (vw * deadFrac) / 2;
|
|
847
|
-
const deadY = (vh * deadFrac) / 2;
|
|
848
|
-
let ox = 0;
|
|
849
|
-
let oy = 0;
|
|
850
|
-
if (dx > deadX) ox = dx - deadX;
|
|
851
|
-
else if (dx < -deadX) ox = dx + deadX;
|
|
852
|
-
if (dy > deadY) oy = dy - deadY;
|
|
853
|
-
else if (dy < -deadY) oy = dy + deadY;
|
|
854
|
-
if (ox === 0 && oy === 0) return;
|
|
855
|
-
const now = Date.now();
|
|
856
|
-
if (now - lastPanAt < 120) return;
|
|
857
|
-
lastPanAt = now;
|
|
858
|
-
// Partial gain - never yank the full overflow in one pan.
|
|
859
|
-
const gain = 0.35;
|
|
860
|
-
const nx = cam.cx + (ox / cam.scale) * gain;
|
|
861
|
-
const ny = cam.cy + (oy / cam.scale) * gain;
|
|
862
|
-
window.__wgSetCamera(nx, ny, cam.scale, 280);
|
|
863
|
-
};
|
|
813
|
+
// Auto-center only. Never chase the host mouse (that fights the
|
|
814
|
+
// camera). Playwright's real mouse is driven separately by the CLI.
|
|
815
|
+
window.__wgIgnoreHostMouse = true;
|
|
864
816
|
const tick = () => {
|
|
865
817
|
const el = document.querySelector(sel);
|
|
866
818
|
if (el && window.__wgPositionRing) {
|
|
@@ -872,8 +824,6 @@ async function installOverlay(page, title) {
|
|
|
872
824
|
style,
|
|
873
825
|
);
|
|
874
826
|
}
|
|
875
|
-
if (!settled && Date.now() >= settleAt) settled = true;
|
|
876
|
-
followTick();
|
|
877
827
|
window.__wgRingRaf = requestAnimationFrame(tick);
|
|
878
828
|
};
|
|
879
829
|
if (zoom > 1 && window.__wgSetCamera) {
|
|
@@ -882,37 +832,25 @@ async function installOverlay(page, title) {
|
|
|
882
832
|
const already =
|
|
883
833
|
window.__wgCamera && window.__wgCamera.scale > 1.001;
|
|
884
834
|
const dur = already ? Math.min(camMs, 420) : camMs;
|
|
885
|
-
// Focus must be document-space, not raw getBoundingClientRect
|
|
886
|
-
// (viewport) - otherwise already-zoomed pans fight the cursor.
|
|
887
835
|
const pt = window.__wgElDocPoint
|
|
888
836
|
? window.__wgElDocPoint(el0)
|
|
889
837
|
: {
|
|
890
838
|
x: el0.getBoundingClientRect().left + el0.getBoundingClientRect().width / 2,
|
|
891
839
|
y: el0.getBoundingClientRect().top + el0.getBoundingClientRect().height / 2,
|
|
892
840
|
};
|
|
841
|
+
// Lock for the whole ring - host mouse cannot steer.
|
|
893
842
|
window.__wgCameraLock = true;
|
|
894
843
|
window.__wgSetCamera(pt.x, pt.y, zoom, dur);
|
|
895
|
-
setTimeout(() => {
|
|
896
|
-
window.__wgCameraLock = false;
|
|
897
|
-
}, dur + 40);
|
|
898
844
|
}
|
|
899
845
|
}
|
|
900
846
|
window.__wgRingRaf = requestAnimationFrame(tick);
|
|
901
|
-
//
|
|
902
|
-
|
|
903
|
-
window.__wgCursorPos = { x: ev.clientX, y: ev.clientY };
|
|
904
|
-
};
|
|
905
|
-
window.addEventListener("mousemove", onMove, { passive: true });
|
|
906
|
-
window.__wgRingTrack = onMove;
|
|
847
|
+
// Do NOT listen to host mousemove - it was steering the camera.
|
|
848
|
+
window.__wgRingTrack = null;
|
|
907
849
|
window.__wgStopHighlightTrack = () => {
|
|
908
850
|
if (window.__wgRingRaf) {
|
|
909
851
|
cancelAnimationFrame(window.__wgRingRaf);
|
|
910
852
|
window.__wgRingRaf = null;
|
|
911
853
|
}
|
|
912
|
-
if (window.__wgRingTrack) {
|
|
913
|
-
window.removeEventListener("mousemove", window.__wgRingTrack);
|
|
914
|
-
window.__wgRingTrack = null;
|
|
915
|
-
}
|
|
916
854
|
window.__wgStopHighlightTrack = null;
|
|
917
855
|
};
|
|
918
856
|
};
|
|
@@ -1418,6 +1356,25 @@ async function renderBeforeStep(page, info) {
|
|
|
1418
1356
|
|
|
1419
1357
|
async function ensureSelectorInView(page, selector) {
|
|
1420
1358
|
try {
|
|
1359
|
+
// Body-scale camera + scrollIntoView = teleport / "outside viewport" loop.
|
|
1360
|
+
// When zoomed, pan the camera to the target instead of scrolling the document.
|
|
1361
|
+
const zoomed = await page
|
|
1362
|
+
.evaluate(() => !!(window.__wgCamera && window.__wgCamera.scale > 1.001))
|
|
1363
|
+
.catch(() => false);
|
|
1364
|
+
if (zoomed) {
|
|
1365
|
+
await page
|
|
1366
|
+
.evaluate((sel) => {
|
|
1367
|
+
const el = document.querySelector(sel);
|
|
1368
|
+
if (!el || !window.__wgSetCamera || !window.__wgElDocPoint) return;
|
|
1369
|
+
const cam = window.__wgCamera;
|
|
1370
|
+
const pt = window.__wgElDocPoint(el);
|
|
1371
|
+
window.__wgCameraLock = true;
|
|
1372
|
+
window.__wgSetCamera(pt.x, pt.y, cam.scale > 1 ? cam.scale : 1.4, 320);
|
|
1373
|
+
}, selector)
|
|
1374
|
+
.catch(() => {});
|
|
1375
|
+
await new Promise((res) => setTimeout(res, 340));
|
|
1376
|
+
return;
|
|
1377
|
+
}
|
|
1421
1378
|
const loc = page.locator(selector).first();
|
|
1422
1379
|
await loc.scrollIntoViewIfNeeded().catch(() => {});
|
|
1423
1380
|
await page
|
|
@@ -1630,18 +1587,10 @@ async function cycleHighlightRings(page, highlights, gatesFast, opts) {
|
|
|
1630
1587
|
}
|
|
1631
1588
|
const z = h.zoom != null && Number(h.zoom) > 1 ? Number(h.zoom) : 1;
|
|
1632
1589
|
const camMs = 700;
|
|
1633
|
-
|
|
1634
|
-
h.followMouse !== undefined
|
|
1635
|
-
? !!h.followMouse
|
|
1636
|
-
: h.follow !== undefined
|
|
1637
|
-
? !!h.follow
|
|
1638
|
-
: z > 1;
|
|
1639
|
-
// Track/zoom first, then park the demo cursor on the LIVE rect.
|
|
1640
|
-
// Placing the cursor on a pre-zoom boundingBox leaves it stranded after
|
|
1641
|
-
// body scale (html cursor is outside the transform).
|
|
1590
|
+
// Camera auto-centers on the ring target. Host mouse never steers.
|
|
1642
1591
|
await page
|
|
1643
1592
|
.evaluate(
|
|
1644
|
-
({ sel, label, tone, size, weight, focus, color, zoom,
|
|
1593
|
+
({ sel, label, tone, size, weight, focus, color, zoom, camMs }) => {
|
|
1645
1594
|
if (window.__wgStartHighlightTrack) {
|
|
1646
1595
|
window.__wgStartHighlightTrack({
|
|
1647
1596
|
sel,
|
|
@@ -1652,7 +1601,6 @@ async function cycleHighlightRings(page, highlights, gatesFast, opts) {
|
|
|
1652
1601
|
focus,
|
|
1653
1602
|
color,
|
|
1654
1603
|
zoom,
|
|
1655
|
-
followMouse,
|
|
1656
1604
|
camMs,
|
|
1657
1605
|
});
|
|
1658
1606
|
}
|
|
@@ -1666,7 +1614,6 @@ async function cycleHighlightRings(page, highlights, gatesFast, opts) {
|
|
|
1666
1614
|
focus: !!h.focus,
|
|
1667
1615
|
color: h.color || h.labelColor || h.textColor || "",
|
|
1668
1616
|
zoom: z,
|
|
1669
|
-
followMouse,
|
|
1670
1617
|
camMs,
|
|
1671
1618
|
},
|
|
1672
1619
|
)
|
|
@@ -1677,19 +1624,18 @@ async function cycleHighlightRings(page, highlights, gatesFast, opts) {
|
|
|
1677
1624
|
const waitMs = alreadyZoomed ? Math.min(camMs, 420) : camMs;
|
|
1678
1625
|
await new Promise((res) => setTimeout(res, waitMs));
|
|
1679
1626
|
if (h.cursor !== false) {
|
|
1680
|
-
|
|
1681
|
-
|
|
1627
|
+
// Park Playwright real mouse + demo cursor on the LIVE centered target.
|
|
1628
|
+
const live = await page
|
|
1629
|
+
.evaluate((sel) => {
|
|
1682
1630
|
const el = document.querySelector(sel);
|
|
1683
|
-
if (!el
|
|
1684
|
-
window.__wgCameraLock = true;
|
|
1631
|
+
if (!el) return null;
|
|
1685
1632
|
const r = el.getBoundingClientRect();
|
|
1686
|
-
|
|
1687
|
-
|
|
1688
|
-
|
|
1689
|
-
|
|
1690
|
-
|
|
1691
|
-
|
|
1692
|
-
await new Promise((res) => setTimeout(res, Math.min(280, camMs)));
|
|
1633
|
+
return { x: r.left, y: r.top, width: r.width, height: r.height };
|
|
1634
|
+
}, h.selector)
|
|
1635
|
+
.catch(() => null);
|
|
1636
|
+
if (live) {
|
|
1637
|
+
await moveCursorTo(page, live, Math.min(280, camMs), { keepLock: true });
|
|
1638
|
+
}
|
|
1693
1639
|
}
|
|
1694
1640
|
// Appear settle
|
|
1695
1641
|
await new Promise((res) => setTimeout(res, fadeMs));
|
|
@@ -2462,19 +2408,27 @@ async function moveCursorTo(page, box, ms, opts) {
|
|
|
2462
2408
|
const y = box.y + box.height / 2;
|
|
2463
2409
|
const travel = Math.max(0, Number(ms) || 0);
|
|
2464
2410
|
const keepLock = !!(opts && opts.keepLock);
|
|
2465
|
-
//
|
|
2466
|
-
//
|
|
2411
|
+
// Camera stays locked; demo cursor + Playwright real mouse move together.
|
|
2412
|
+
// Host OS mouse is ignored (no mousemove camera steer).
|
|
2467
2413
|
await page
|
|
2468
2414
|
.evaluate(({ x, y, ms }) => {
|
|
2469
2415
|
window.__wgCameraLock = true;
|
|
2416
|
+
window.__wgIgnoreHostMouse = true;
|
|
2470
2417
|
if (window.__wgMoveCursorTo) window.__wgMoveCursorTo(x, y, ms);
|
|
2471
2418
|
}, { x, y, ms: travel })
|
|
2472
2419
|
.catch(() => {});
|
|
2473
|
-
|
|
2474
|
-
|
|
2475
|
-
|
|
2420
|
+
try {
|
|
2421
|
+
if (travel > 0) {
|
|
2422
|
+
const steps = Math.max(1, Math.min(30, Math.round(travel / 20)));
|
|
2423
|
+
await page.mouse.move(x, y, { steps });
|
|
2424
|
+
} else {
|
|
2425
|
+
await page.mouse.move(x, y);
|
|
2426
|
+
}
|
|
2427
|
+
} catch {
|
|
2428
|
+
/* headed / detached - demo cursor still moved */
|
|
2429
|
+
}
|
|
2476
2430
|
if (travel > 0) {
|
|
2477
|
-
await new Promise((res) => setTimeout(res, travel));
|
|
2431
|
+
await new Promise((res) => setTimeout(res, Math.min(80, travel)));
|
|
2478
2432
|
}
|
|
2479
2433
|
if (!keepLock) {
|
|
2480
2434
|
await page
|
|
@@ -2486,6 +2440,16 @@ async function moveCursorTo(page, box, ms, opts) {
|
|
|
2486
2440
|
return { x, y };
|
|
2487
2441
|
}
|
|
2488
2442
|
|
|
2443
|
+
/** Live viewport center of a locator (after camera transform) - no scroll. */
|
|
2444
|
+
async function liveCenterOf(locator) {
|
|
2445
|
+
return locator
|
|
2446
|
+
.evaluate((el) => {
|
|
2447
|
+
const r = el.getBoundingClientRect();
|
|
2448
|
+
return { x: r.left + r.width / 2, y: r.top + r.height / 2, w: r.width, h: r.height };
|
|
2449
|
+
})
|
|
2450
|
+
.catch(() => null);
|
|
2451
|
+
}
|
|
2452
|
+
|
|
2489
2453
|
async function clickPulseAt(page, x, y, tone) {
|
|
2490
2454
|
await page
|
|
2491
2455
|
.evaluate(({ x, y, tone }) => {
|
|
@@ -2613,29 +2577,44 @@ function instrumentInteractionHighlighting(page, mem, slowMo, pacing, stubBefore
|
|
|
2613
2577
|
let keptCameraLock = false;
|
|
2614
2578
|
try {
|
|
2615
2579
|
await installOverlay(page);
|
|
2616
|
-
// Wait until the target is visible BEFORE measuring - otherwise
|
|
2617
|
-
// defineNavBlock({ click }) (and any slow-to-appear control) skips
|
|
2618
|
-
// the cursor entirely: boundingBox was null, then originalClick
|
|
2619
|
-
// waited and clicked with no demo animation.
|
|
2620
2580
|
await this.waitFor({
|
|
2621
2581
|
state: "visible",
|
|
2622
2582
|
timeout: (options && options.timeout) || 30000,
|
|
2623
2583
|
}).catch(() => {});
|
|
2624
|
-
// Body-scale camera + Playwright scrollIntoView = teleport storm.
|
|
2625
|
-
// Lock the camera for the whole click when zoomed; force-click so
|
|
2626
|
-
// Playwright does not try to scroll the transformed page.
|
|
2627
2584
|
const zoomed = await page
|
|
2628
2585
|
.evaluate(() => !!(window.__wgCamera && window.__wgCamera.scale > 1.001))
|
|
2629
2586
|
.catch(() => false);
|
|
2630
2587
|
if (zoomed) {
|
|
2588
|
+
// Re-auto-center on this target, then lock - no host mouse, no scroll.
|
|
2631
2589
|
await page
|
|
2632
2590
|
.evaluate(() => {
|
|
2633
2591
|
window.__wgCameraLock = true;
|
|
2592
|
+
window.__wgIgnoreHostMouse = true;
|
|
2634
2593
|
})
|
|
2635
2594
|
.catch(() => {});
|
|
2636
2595
|
keptCameraLock = true;
|
|
2596
|
+
const handle = await this.elementHandle().catch(() => null);
|
|
2597
|
+
if (handle) {
|
|
2598
|
+
await page
|
|
2599
|
+
.evaluate(
|
|
2600
|
+
(el) => {
|
|
2601
|
+
if (!el || !window.__wgSetCamera || !window.__wgElDocPoint) return;
|
|
2602
|
+
const cam = window.__wgCamera || { scale: 1.4 };
|
|
2603
|
+
const pt = window.__wgElDocPoint(el);
|
|
2604
|
+
const s = cam.scale > 1.001 ? cam.scale : 1.4;
|
|
2605
|
+
window.__wgSetCamera(pt.x, pt.y, s, 280);
|
|
2606
|
+
},
|
|
2607
|
+
handle,
|
|
2608
|
+
)
|
|
2609
|
+
.catch(() => {});
|
|
2610
|
+
await handle.dispose().catch(() => {});
|
|
2611
|
+
await new Promise((res) => setTimeout(res, 300));
|
|
2612
|
+
}
|
|
2637
2613
|
}
|
|
2638
|
-
const
|
|
2614
|
+
const live = await liveCenterOf(this);
|
|
2615
|
+
const box = live
|
|
2616
|
+
? { x: live.x - live.w / 2, y: live.y - live.h / 2, width: live.w, height: live.h }
|
|
2617
|
+
: await this.boundingBox();
|
|
2639
2618
|
const narrated = box ? await wasJustNarrated(page) : false;
|
|
2640
2619
|
if (box && !narrated) {
|
|
2641
2620
|
let fallback = "click";
|
|
@@ -2643,10 +2622,8 @@ function instrumentInteractionHighlighting(page, mem, slowMo, pacing, stubBefore
|
|
|
2643
2622
|
const text = (await this.textContent())?.trim();
|
|
2644
2623
|
if (text && text.length > 0 && text.length <= 30) fallback = text;
|
|
2645
2624
|
} catch {
|
|
2646
|
-
|
|
2625
|
+
/* ignore */
|
|
2647
2626
|
}
|
|
2648
|
-
// Prefer "nav: …" when this locator is a NavBlock click target
|
|
2649
|
-
// (set on page by runStepMode just before act).
|
|
2650
2627
|
try {
|
|
2651
2628
|
const navLabel = await page.evaluate(() => window.__wgPendingNavClickLabel || null);
|
|
2652
2629
|
if (navLabel) fallback = String(navLabel);
|
|
@@ -2656,13 +2633,13 @@ function instrumentInteractionHighlighting(page, mem, slowMo, pacing, stubBefore
|
|
|
2656
2633
|
const stubs = (stubBeforeRef && stubBeforeRef.current) || [];
|
|
2657
2634
|
const cap = await captionForLocator(page, this, stubs, fallback);
|
|
2658
2635
|
clickTone = cap.tone;
|
|
2659
|
-
|
|
2660
|
-
const
|
|
2661
|
-
|
|
2662
|
-
|
|
2663
|
-
|
|
2664
|
-
|
|
2665
|
-
const liveBox =
|
|
2636
|
+
const travel = zoomed ? cursorMs(200) : cursorMs(600);
|
|
2637
|
+
const again = (await liveCenterOf(this)) || live;
|
|
2638
|
+
const aim = again
|
|
2639
|
+
? { x: again.x - again.w / 2, y: again.y - again.h / 2, width: again.w, height: again.h }
|
|
2640
|
+
: box;
|
|
2641
|
+
clickPoint = await moveCursorTo(page, aim, travel, { keepLock: zoomed });
|
|
2642
|
+
const liveBox = aim;
|
|
2666
2643
|
clickPoint = {
|
|
2667
2644
|
x: liveBox.x + liveBox.width / 2,
|
|
2668
2645
|
y: liveBox.y + liveBox.height / 2,
|
|
@@ -2672,41 +2649,52 @@ function instrumentInteractionHighlighting(page, mem, slowMo, pacing, stubBefore
|
|
|
2672
2649
|
weight: cap.weight,
|
|
2673
2650
|
});
|
|
2674
2651
|
await dwellMatchedStub(page, this, stubs, pacing);
|
|
2675
|
-
// "pop for a few seconds" - Dan's own phrase, matching the
|
|
2676
|
-
// zsign demo-engine's ring-before-click pattern in
|
|
2677
|
-
// services/help-center-clip-engine's video-pipeline.
|
|
2678
2652
|
await new Promise((res) => setTimeout(res, clickPrePop()));
|
|
2679
2653
|
} else if (box) {
|
|
2680
|
-
// Ring/caption already handled by narrate() - still move the
|
|
2681
|
-
// cursor + pulse the click point, just skip re-showing the ring.
|
|
2682
2654
|
const travel = zoomed ? cursorMs(120) : cursorMs(200);
|
|
2683
|
-
clickPoint = await moveCursorTo(page, box, travel, {
|
|
2684
|
-
keepLock: zoomed,
|
|
2685
|
-
});
|
|
2655
|
+
clickPoint = await moveCursorTo(page, box, travel, { keepLock: zoomed });
|
|
2686
2656
|
clickTone = "planned";
|
|
2687
2657
|
}
|
|
2688
2658
|
} catch {
|
|
2689
|
-
|
|
2659
|
+
/* best-effort */
|
|
2690
2660
|
}
|
|
2691
2661
|
if (clickPoint) {
|
|
2692
2662
|
await clickPulseAt(page, clickPoint.x, clickPoint.y, clickTone);
|
|
2693
|
-
// clickPulseAt only triggers the CSS animation class - it doesn't
|
|
2694
|
-
// wait for it. Without a pause here, the real click (and any
|
|
2695
|
-
// resulting navigation/DOM change) fires while the ripple is still
|
|
2696
|
-
// mid-animation, sometimes cutting it off before it's even visible.
|
|
2697
|
-
// Wait out the same .5s the "@keyframes wg-pulse" rule uses, so the
|
|
2698
|
-
// mock click visually completes before the real one fires.
|
|
2699
2663
|
await new Promise((res) => setTimeout(res, skipTheater() ? 0 : 500));
|
|
2700
2664
|
}
|
|
2701
2665
|
const zoomedClick = await page
|
|
2702
2666
|
.evaluate(() => !!(window.__wgCamera && window.__wgCamera.scale > 1.001))
|
|
2703
2667
|
.catch(() => false);
|
|
2704
|
-
const clickOpts =
|
|
2705
|
-
zoomedClick || keptCameraLock
|
|
2706
|
-
? { ...(options || {}), force: true }
|
|
2707
|
-
: options;
|
|
2708
2668
|
try {
|
|
2709
|
-
|
|
2669
|
+
let result;
|
|
2670
|
+
if (zoomedClick || keptCameraLock) {
|
|
2671
|
+
// Real Playwright mouse at live visual center - never scrollIntoView.
|
|
2672
|
+
const pt =
|
|
2673
|
+
clickPoint ||
|
|
2674
|
+
(await liveCenterOf(this)) ||
|
|
2675
|
+
null;
|
|
2676
|
+
if (pt && Number.isFinite(pt.x) && Number.isFinite(pt.y)) {
|
|
2677
|
+
await page.mouse.click(pt.x, pt.y);
|
|
2678
|
+
result = undefined;
|
|
2679
|
+
} else {
|
|
2680
|
+
const handle = await this.elementHandle().catch(() => null);
|
|
2681
|
+
if (handle) {
|
|
2682
|
+
await handle.evaluate((el) => {
|
|
2683
|
+
if (el && typeof el.click === "function") el.click();
|
|
2684
|
+
});
|
|
2685
|
+
await handle.dispose().catch(() => {});
|
|
2686
|
+
result = undefined;
|
|
2687
|
+
} else {
|
|
2688
|
+
result = await originalClick.call(this, {
|
|
2689
|
+
...(options || {}),
|
|
2690
|
+
force: true,
|
|
2691
|
+
timeout: (options && options.timeout) || 5000,
|
|
2692
|
+
});
|
|
2693
|
+
}
|
|
2694
|
+
}
|
|
2695
|
+
} else {
|
|
2696
|
+
result = await originalClick.call(this, options);
|
|
2697
|
+
}
|
|
2710
2698
|
await new Promise((res) => setTimeout(res, clickPostPop()));
|
|
2711
2699
|
await hideRing(page);
|
|
2712
2700
|
return result;
|
package/dist/highlights.d.ts
CHANGED
|
@@ -97,12 +97,11 @@ export interface WaygraphHighlightStub extends FixtureDurationFields {
|
|
|
97
97
|
*/
|
|
98
98
|
focus?: boolean;
|
|
99
99
|
/**
|
|
100
|
-
*
|
|
101
|
-
*
|
|
102
|
-
* Alias: `follow`.
|
|
100
|
+
* Deprecated no-op. Camera auto-centers on the ring target; host mouse is
|
|
101
|
+
* ignored. Playwright's real mouse is driven to the centered target instead.
|
|
103
102
|
*/
|
|
104
103
|
followMouse?: boolean;
|
|
105
|
-
/** Alias for {@link WaygraphHighlightStub.followMouse}. */
|
|
104
|
+
/** Alias for {@link WaygraphHighlightStub.followMouse} (no-op). */
|
|
106
105
|
follow?: boolean;
|
|
107
106
|
/**
|
|
108
107
|
* Caption text color (CSS color). Overrides tone label color when set.
|
|
@@ -30,7 +30,7 @@ export const NavCartBlock = defineNavClickBlock<CartPage>({
|
|
|
30
30
|
color: "#c9a6ff",
|
|
31
31
|
zoom: 1.55,
|
|
32
32
|
zoomOut: false,
|
|
33
|
-
followMouse:
|
|
33
|
+
followMouse: false,
|
|
34
34
|
weight: "bold",
|
|
35
35
|
},
|
|
36
36
|
});
|
|
@@ -45,7 +45,7 @@ export const NavCartBlock = defineNavClickBlock<CartPage>({
|
|
|
45
45
|
focus: true,
|
|
46
46
|
color: "#86efac",
|
|
47
47
|
zoom: 1.4,
|
|
48
|
-
followMouse:
|
|
48
|
+
followMouse: false,
|
|
49
49
|
duration: true,
|
|
50
50
|
});
|
|
51
51
|
},
|
package/examples/saucedemo/src/blocks/saucedemo-web/inventory/methods/add-to-cart.effect.block.ts
CHANGED
|
@@ -49,7 +49,6 @@ export const AddToCartBlock = defineEffectBlock<Checkpoint<string>, ItemInCart>(
|
|
|
49
49
|
color: "#c9a6ff",
|
|
50
50
|
zoom: 1.45,
|
|
51
51
|
zoomOut: false,
|
|
52
|
-
followMouse: true,
|
|
53
52
|
},
|
|
54
53
|
add: {
|
|
55
54
|
selector: InventorySel.addBtn(DEMO_PRODUCT_ID),
|
|
@@ -75,7 +74,6 @@ export const AddToCartBlock = defineEffectBlock<Checkpoint<string>, ItemInCart>(
|
|
|
75
74
|
color: "#86efac",
|
|
76
75
|
zoom: 1.6,
|
|
77
76
|
zoomOut: false,
|
|
78
|
-
followMouse: true,
|
|
79
77
|
duration: true,
|
|
80
78
|
});
|
|
81
79
|
},
|
package/package.json
CHANGED
|
@@ -30,7 +30,7 @@ export const NavCartBlock = defineNavClickBlock<CartPage>({
|
|
|
30
30
|
color: "#c9a6ff",
|
|
31
31
|
zoom: 1.55,
|
|
32
32
|
zoomOut: false,
|
|
33
|
-
followMouse:
|
|
33
|
+
followMouse: false,
|
|
34
34
|
weight: "bold",
|
|
35
35
|
},
|
|
36
36
|
});
|
|
@@ -45,7 +45,7 @@ export const NavCartBlock = defineNavClickBlock<CartPage>({
|
|
|
45
45
|
focus: true,
|
|
46
46
|
color: "#86efac",
|
|
47
47
|
zoom: 1.4,
|
|
48
|
-
followMouse:
|
|
48
|
+
followMouse: false,
|
|
49
49
|
duration: true,
|
|
50
50
|
});
|
|
51
51
|
},
|
package/templates/quickstart/src/blocks/saucedemo-web/inventory/methods/add-to-cart.effect.block.ts
CHANGED
|
@@ -49,7 +49,6 @@ export const AddToCartBlock = defineEffectBlock<Checkpoint<string>, ItemInCart>(
|
|
|
49
49
|
color: "#c9a6ff",
|
|
50
50
|
zoom: 1.45,
|
|
51
51
|
zoomOut: false,
|
|
52
|
-
followMouse: true,
|
|
53
52
|
},
|
|
54
53
|
add: {
|
|
55
54
|
selector: InventorySel.addBtn(DEMO_PRODUCT_ID),
|
|
@@ -75,7 +74,6 @@ export const AddToCartBlock = defineEffectBlock<Checkpoint<string>, ItemInCart>(
|
|
|
75
74
|
color: "#86efac",
|
|
76
75
|
zoom: 1.6,
|
|
77
76
|
zoomOut: false,
|
|
78
|
-
followMouse: true,
|
|
79
77
|
duration: true,
|
|
80
78
|
});
|
|
81
79
|
},
|