waygraph 0.15.30 → 0.15.32

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.
Files changed (47) hide show
  1. package/dist/auto-explore-run.js +9 -6
  2. package/dist/auto-session/session.js +2 -1
  3. package/dist/pilot-overlay/action-ring.d.ts +16 -0
  4. package/dist/pilot-overlay/action-ring.js +67 -0
  5. package/dist/pilot-overlay/fixtures.js +17 -17
  6. package/dist/pilot-overlay/panel.js +3 -3
  7. package/dist/pilot-overlay/shell.js +27 -27
  8. package/dist/pilot-overlay.d.ts +1 -0
  9. package/dist/pilot-overlay.js +1 -0
  10. package/dist/runner/cursor.js +3 -3
  11. package/dist/runner/inpage/banner.js +2 -2
  12. package/dist/runner/inpage/core.js +23 -23
  13. package/dist/runner/inpage/device.js +11 -11
  14. package/dist/runner/inpage/panel-chrome.js +3 -3
  15. package/dist/runner/inpage/stamp.js +2 -2
  16. package/dist/runner/inpage/swipe-zoom.js +10 -10
  17. package/dist/runner/inpage/todos.js +6 -6
  18. package/dist/runner/overlay-css.js +21 -18
  19. package/dist/runner/overlay-install.js +5 -2
  20. package/dist/runner/rings.js +1 -1
  21. package/dist/runner/slides.js +11 -11
  22. package/dist/runner/step-panels.js +18 -18
  23. package/dist/runner/teardown.js +8 -8
  24. package/dist/runner/todo-dock.js +1 -1
  25. package/dist/step-overlay.js +20 -18
  26. package/dist/ui/components/ring.js +5 -0
  27. package/dist/ui/shadow.d.ts +15 -0
  28. package/dist/ui/shadow.js +42 -0
  29. package/examples/saucedemo/.waygraph-auto/1bd7b7bf.log +0 -0
  30. package/examples/saucedemo/.waygraph-auto/2a577961.log +0 -0
  31. package/examples/saucedemo/.waygraph-auto/2c79c73a.log +0 -0
  32. package/examples/saucedemo/.waygraph-auto/2c94a05b.log +0 -0
  33. package/examples/saucedemo/.waygraph-auto/37b56184.log +0 -0
  34. package/examples/saucedemo/.waygraph-auto/401177a3.log +0 -0
  35. package/examples/saucedemo/.waygraph-auto/476cff76.log +0 -0
  36. package/examples/saucedemo/.waygraph-auto/535e8922.json +8 -0
  37. package/examples/saucedemo/.waygraph-auto/535e8922.log +0 -0
  38. package/examples/saucedemo/.waygraph-auto/68fa0682.log +0 -0
  39. package/examples/saucedemo/.waygraph-auto/73a41843.log +0 -0
  40. package/examples/saucedemo/.waygraph-auto/8598b4c0.log +0 -0
  41. package/examples/saucedemo/.waygraph-auto/982138cf.log +0 -0
  42. package/examples/saucedemo/.waygraph-auto/a8645294.log +0 -0
  43. package/examples/saucedemo/.waygraph-auto/bf8693e7.log +0 -0
  44. package/examples/saucedemo/.waygraph-auto/f86224c6.log +0 -0
  45. package/examples/saucedemo/.waygraph-auto/fc917c18.log +0 -0
  46. package/examples/saucedemo/.waygraph-auto/fe83305d.log +0 -0
  47. package/package.json +1 -1
@@ -1,38 +1,40 @@
1
+ import { ensureShadowRoot } from "./ui/shadow.js";
1
2
  import { composeStepOverlay } from "./ui/compose.js";
2
3
  const RING_CSS = composeStepOverlay();
3
4
  const FAVICON = "data:image/svg+xml," +
4
5
  encodeURIComponent("<svg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 32 32'><circle cx='16' cy='16' r='14' fill='#7C3AED'/></svg>");
5
6
  export async function installDemoChrome(page, title = "waygraph auto", options = {}) {
6
7
  const showBanner = options.banner !== false;
7
- await page.addStyleTag({ content: RING_CSS }).catch(() => { });
8
+ await ensureShadowRoot(page);
9
+ await page.evaluate(([css, key]) => __wgCss(css, key), [RING_CSS, "wg-overlay-css"]).catch(() => { });
8
10
  await page
9
11
  .evaluate(({ title, favicon, showBanner }) => {
10
- if (!document.getElementById("wg-ring")) {
12
+ if (!__wgById("wg-ring")) {
11
13
  const ring = document.createElement("div");
12
14
  ring.id = "wg-ring";
13
- document.documentElement.appendChild(ring);
15
+ __wgAdd(ring);
14
16
  }
15
- if (!document.getElementById("wg-ring-label")) {
17
+ if (!__wgById("wg-ring-label")) {
16
18
  const ringLabel = document.createElement("div");
17
19
  ringLabel.id = "wg-ring-label";
18
- document.documentElement.appendChild(ringLabel);
20
+ __wgAdd(ringLabel);
19
21
  }
20
- if (!document.getElementById("wg-cursor")) {
22
+ if (!__wgById("wg-cursor")) {
21
23
  const cursor = document.createElement("div");
22
24
  cursor.id = "wg-cursor";
23
25
  cursor.innerHTML =
24
26
  "<svg viewBox='0 0 32 32' width='24' height='24'>" +
25
27
  "<path fill='#0C0C1A' stroke='#fff' stroke-width='1.4' stroke-linejoin='round' " +
26
28
  "d='M6 3.5l1.4 22.5 5.8-5.4 4.2 9.4 3.6-1.6-4.2-9.2H26z'/></svg>";
27
- document.documentElement.appendChild(cursor);
29
+ __wgAdd(cursor);
28
30
  }
29
- if (!document.getElementById("wg-click-pulse")) {
31
+ if (!__wgById("wg-click-pulse")) {
30
32
  const pulse = document.createElement("div");
31
33
  pulse.id = "wg-click-pulse";
32
- document.documentElement.appendChild(pulse);
34
+ __wgAdd(pulse);
33
35
  }
34
36
  window.__wgMoveCursorTo = (x, y, ms) => {
35
- const cursor = document.getElementById("wg-cursor");
37
+ const cursor = __wgById("wg-cursor");
36
38
  if (!cursor)
37
39
  return;
38
40
  cursor.style.setProperty("--wg-cursor-ms", (ms || 600) + "ms");
@@ -40,7 +42,7 @@ export async function installDemoChrome(page, title = "waygraph auto", options =
40
42
  cursor.style.opacity = "1";
41
43
  };
42
44
  window.__wgClickPulse = (x, y, tone) => {
43
- const pulse = document.getElementById("wg-click-pulse");
45
+ const pulse = __wgById("wg-click-pulse");
44
46
  if (!pulse)
45
47
  return;
46
48
  const raw = (tone || "planned") + "";
@@ -59,8 +61,8 @@ export async function installDemoChrome(page, title = "waygraph auto", options =
59
61
  pulse.classList.add("wg-pulse");
60
62
  };
61
63
  window.__wgPositionRing = (box, label, tone, style) => {
62
- const ring = document.getElementById("wg-ring");
63
- const ringLabel = document.getElementById("wg-ring-label");
64
+ const ring = __wgById("wg-ring");
65
+ const ringLabel = __wgById("wg-ring-label");
64
66
  if (!ring || !ringLabel)
65
67
  return;
66
68
  const raw = (tone || "planned") + "";
@@ -92,25 +94,25 @@ export async function installDemoChrome(page, title = "waygraph auto", options =
92
94
  ringLabel.style.opacity = "1";
93
95
  };
94
96
  window.__wgHideRing = () => {
95
- const ring = document.getElementById("wg-ring");
96
- const ringLabel = document.getElementById("wg-ring-label");
97
+ const ring = __wgById("wg-ring");
98
+ const ringLabel = __wgById("wg-ring-label");
97
99
  if (ring)
98
100
  ring.style.opacity = "0";
99
101
  if (ringLabel)
100
102
  ringLabel.style.opacity = "0";
101
103
  };
102
- if (showBanner && title && !document.getElementById("wg-banner")) {
104
+ if (showBanner && title && !__wgById("wg-banner")) {
103
105
  const banner = document.createElement("div");
104
106
  banner.id = "wg-banner";
105
107
  banner.innerHTML =
106
108
  "<span class='wg-banner-tag'>waygraph auto</span><span>" + title + "</span>";
107
- document.documentElement.appendChild(banner);
109
+ __wgAdd(banner);
108
110
  banner.setAttribute("data-wg-ui", "1");
109
111
  banner.setAttribute("data-wg-modal", "banner");
110
112
  banner.setAttribute("data-wg-ready", "1");
111
113
  }
112
114
  else {
113
- const existing = document.getElementById("wg-banner");
115
+ const existing = __wgById("wg-banner");
114
116
  if (existing) {
115
117
  existing.setAttribute("data-wg-ui", "1");
116
118
  existing.setAttribute("data-wg-modal", "banner");
@@ -1,4 +1,6 @@
1
1
  import { TONES } from "../tokens.js";
2
+ /** Prefix icon for gray (auto) labels. */
3
+ const ROBOT = 'content:"\\1F916\\00a0";';
2
4
  const toneNames = Object.keys(TONES);
3
5
  /** Tone rules for `sel[data-tone=x]{...}` from the token table. */
4
6
  function toneRules(sel, decl, only) {
@@ -17,6 +19,8 @@ export function ringCss() {
17
19
  `max-width:min(360px,70vw);white-space:normal;padding:6px 10px;border-radius:7px;background:${p.labelBg};color:${p.labelFg};` +
18
20
  "font:600 12px/1.35 system-ui,sans-serif;transition:opacity .3s ease;}" +
19
21
  toneRules("#wg-ring-label", (t) => `background:${t.labelBg};color:${t.labelFg};`) +
22
+ // Gray = a real Playwright-driven instruction: mark it with a robot.
23
+ `#wg-ring-label[data-tone=auto]::before{${ROBOT}}` +
20
24
  "#wg-ring[data-size=sm]{border-width:1.5px;border-radius:8px;}" +
21
25
  "#wg-ring[data-size=lg]{border-width:4px;border-radius:12px;}" +
22
26
  "#wg-ring-label[data-size=sm]{font-size:10px;line-height:1.25;padding:4px 7px;border-radius:5px;}" +
@@ -36,6 +40,7 @@ export function pilotFxRingCss() {
36
40
  "max-width:min(360px,80vw);box-shadow:0 2px 8px rgba(0,0,0,.25);white-space:nowrap;" +
37
41
  "overflow:hidden;text-overflow:ellipsis;transition:opacity .12s ease;}" +
38
42
  toneRules(".wg-pilot-fx-label", (t) => `background:${t.labelBg};color:${t.labelFg};`) +
43
+ `.wg-pilot-fx-label[data-tone=auto]::before{${ROBOT}}` +
39
44
  ".wg-pilot-fx-ring[data-size=sm]{border-width:1.5px;border-radius:8px;}" +
40
45
  ".wg-pilot-fx-ring[data-size=lg]{border-width:4px;border-radius:12px;}" +
41
46
  ".wg-pilot-fx-label[data-size=sm]{font-size:10px;padding:4px 7px;}" +
@@ -0,0 +1,15 @@
1
+ /**
2
+ * Shadow-DOM mount for every waygraph overlay element. Overlay UI lives in one open shadow root under
3
+ * `<div id="wg-root">`, so the host page's CSS can't restyle it and ours can't leak out.
4
+ *
5
+ * `installShadowRoot` runs INSIDE the page (page.evaluate / addInitScript), so it must stay
6
+ * self-contained. It defines the `__wg*` helpers the overlay code uses in place of `document.*`:
7
+ * lookups check the shadow root first and fall back to the light DOM (the device stage shell and
8
+ * host-page markers such as `[data-wg-zoomed]` intentionally stay in the light DOM).
9
+ */
10
+ import type { BrowserContext, Page } from "@playwright/test";
11
+ export declare function installShadowRoot(): void;
12
+ /** Idempotent; call before any overlay install on a page. */
13
+ export declare function ensureShadowRoot(page: Page): Promise<void>;
14
+ /** Also define the helpers on every future document (pilot overlay persists across navigations). */
15
+ export declare function installShadowRootEverywhere(context: BrowserContext): Promise<void>;
@@ -0,0 +1,42 @@
1
+ export function installShadowRoot() {
2
+ const w = window;
3
+ if (w.__wgById)
4
+ return;
5
+ const root = () => {
6
+ let host = document.getElementById("wg-root");
7
+ if (!host || !host.shadowRoot) {
8
+ host?.remove();
9
+ host = document.createElement("div");
10
+ host.id = "wg-root";
11
+ // No box of its own: children are position:fixed, so the host must never affect page layout.
12
+ host.style.cssText = "display:contents";
13
+ host.attachShadow({ mode: "open" });
14
+ document.documentElement.appendChild(host);
15
+ }
16
+ return host.shadowRoot;
17
+ };
18
+ w.__wgRoot = root;
19
+ w.__wgById = (id) => root().getElementById(id) || document.getElementById(id);
20
+ w.__wgQ = (sel) => root().querySelector(sel) || document.querySelector(sel);
21
+ w.__wgQA = (sel) => Array.from(root().querySelectorAll(sel)).concat(Array.from(document.querySelectorAll(sel)));
22
+ w.__wgAdd = (node) => root().appendChild(node);
23
+ w.__wgCss = (css, key) => {
24
+ const r = root();
25
+ let style = Array.from(r.children).find((c) => c.tagName === "STYLE" && c.getAttribute("data-key") === key);
26
+ if (!style) {
27
+ style = document.createElement("style");
28
+ style.setAttribute("data-key", key);
29
+ r.insertBefore(style, r.firstChild);
30
+ }
31
+ if (style.textContent !== css)
32
+ style.textContent = css;
33
+ };
34
+ }
35
+ /** Idempotent; call before any overlay install on a page. */
36
+ export async function ensureShadowRoot(page) {
37
+ await page.evaluate(installShadowRoot).catch(() => { });
38
+ }
39
+ /** Also define the helpers on every future document (pilot overlay persists across navigations). */
40
+ export async function installShadowRootEverywhere(context) {
41
+ await context.addInitScript(installShadowRoot);
42
+ }
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
@@ -0,0 +1,8 @@
1
+ {
2
+ "sessionId": "535e8922",
3
+ "socketPath": "/tmp/waygraph-auto/535e8922.sock",
4
+ "pid": 699159,
5
+ "projectDir": "/home/dan/Desktop/Projects/waygraph/examples/saucedemo",
6
+ "startedAt": "2026-09-25T05:17:09.131Z",
7
+ "headless": false
8
+ }
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "waygraph",
3
- "version": "0.15.30",
3
+ "version": "0.15.32",
4
4
  "type": "module",
5
5
  "description": "A typed graph of reusable Blocks for driving a browser through E2E flows.",
6
6
  "license": "MIT",