waygraph 0.15.32 → 0.15.34

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 (66) hide show
  1. package/dist/engine/core.js +5 -0
  2. package/dist/engine/engine-class.d.ts +37 -0
  3. package/dist/engine/engine-class.js +98 -0
  4. package/dist/highlights/run-phase.js +2 -0
  5. package/dist/highlights/stub-ctx.js +36 -2
  6. package/dist/highlights/types.d.ts +35 -3
  7. package/dist/index.d.ts +1 -1
  8. package/dist/pilot-overlay/fixtures.d.ts +9 -1
  9. package/dist/pilot-overlay/fixtures.js +38 -1
  10. package/dist/pilot-overlay/overlay-fixtures.d.ts +9 -0
  11. package/dist/pilot-overlay/overlay-fixtures.js +45 -0
  12. package/dist/pilot-overlay/shell.js +4 -23
  13. package/dist/pilot-overlay.d.ts +1 -0
  14. package/dist/pilot-overlay.js +1 -0
  15. package/dist/runner/banner-log.js +62 -0
  16. package/dist/runner/demo-log.js +9 -1
  17. package/dist/runner/inpage/banner.js +56 -1
  18. package/dist/runner/inpage/core.js +2 -0
  19. package/dist/runner/overlay-css.js +6 -27
  20. package/dist/runner/overlay-install.js +7 -4
  21. package/dist/runner/overlay-present.d.ts +8 -0
  22. package/dist/runner/overlay-present.js +57 -0
  23. package/dist/runner/overlay-stage.js +105 -0
  24. package/dist/runner/step-mode.js +35 -126
  25. package/dist/runner/step-panels.js +3 -3
  26. package/dist/step-overlay.js +1 -3
  27. package/dist/ui/overlay.css +209 -0
  28. package/dist/ui/shadow.d.ts +7 -2
  29. package/dist/ui/shadow.js +12 -4
  30. package/dist/ui/stylesheet.d.ts +7 -0
  31. package/dist/ui/stylesheet.js +18 -0
  32. package/dist/verbose-log.d.ts +1 -0
  33. package/dist/verbose-log.js +16 -0
  34. package/examples/saucedemo/.waygraph-auto/03df352d.log +0 -0
  35. package/examples/saucedemo/.waygraph-auto/0a8c3719.log +0 -0
  36. package/examples/saucedemo/.waygraph-auto/102c38ca.log +0 -0
  37. package/examples/saucedemo/.waygraph-auto/232a1d81.log +0 -0
  38. package/examples/saucedemo/.waygraph-auto/2553d107.log +0 -0
  39. package/examples/saucedemo/.waygraph-auto/2f4f531e.log +0 -0
  40. package/examples/saucedemo/.waygraph-auto/2fdbd916.log +0 -0
  41. package/examples/saucedemo/.waygraph-auto/331c6e8e.log +0 -0
  42. package/examples/saucedemo/.waygraph-auto/38f6799d.log +0 -0
  43. package/examples/saucedemo/.waygraph-auto/3bdb2f5a.log +0 -0
  44. package/examples/saucedemo/.waygraph-auto/5b838485.log +0 -0
  45. package/examples/saucedemo/.waygraph-auto/5d13bdde.log +0 -0
  46. package/examples/saucedemo/.waygraph-auto/63b0f4cd.log +0 -0
  47. package/examples/saucedemo/.waygraph-auto/6f05bdc1.log +0 -0
  48. package/examples/saucedemo/.waygraph-auto/70279fc3.log +0 -0
  49. package/examples/saucedemo/.waygraph-auto/731a14bd.log +0 -0
  50. package/examples/saucedemo/.waygraph-auto/76128a2d.log +0 -0
  51. package/examples/saucedemo/.waygraph-auto/796ab578.log +0 -0
  52. package/examples/saucedemo/.waygraph-auto/81257bf0.log +0 -0
  53. package/examples/saucedemo/.waygraph-auto/859a261d.log +0 -0
  54. package/examples/saucedemo/.waygraph-auto/a1ab5d29.log +0 -0
  55. package/examples/saucedemo/.waygraph-auto/a4b36275.log +0 -0
  56. package/examples/saucedemo/.waygraph-auto/a94738b7.log +0 -0
  57. package/examples/saucedemo/.waygraph-auto/b3d172f3.log +0 -0
  58. package/examples/saucedemo/.waygraph-auto/b5569336.log +0 -0
  59. package/examples/saucedemo/.waygraph-auto/b57921c5.log +0 -0
  60. package/examples/saucedemo/.waygraph-auto/b9ab0983.log +0 -0
  61. package/examples/saucedemo/.waygraph-auto/d37719a6.log +0 -0
  62. package/examples/saucedemo/.waygraph-auto/da0a06bf.log +0 -0
  63. package/examples/saucedemo/.waygraph-auto/dc58eb72.log +0 -0
  64. package/examples/saucedemo/.waygraph-auto/ff616932.log +0 -0
  65. package/package.json +3 -2
  66. package/examples/saucedemo/.waygraph-auto/535e8922.json +0 -8
@@ -6,7 +6,7 @@ import { applyHighlightStyleDefaults, formatHighlightCaption, hasAuthoredStubOnE
6
6
  import { cycleHighlightRings } from "./rings.js";
7
7
 
8
8
  export async function renderBeforeStep(page, info) {
9
- await installOverlay(page, info.title);
9
+ await installOverlay(page, info.title, info.bannerUi);
10
10
  // A ring left highlighting the PREVIOUS step's element (and its live
11
11
  // resize/scroll tracker) shouldn't linger once a new step's own panel is
12
12
  // up - only relevant when a Block's act() doesn't navigate away, since a
@@ -375,7 +375,7 @@ export async function presentFailPanel(page, opts) {
375
375
 
376
376
 
377
377
  export async function renderAfterStep(page, info) {
378
- await installOverlay(page, info.title);
378
+ await installOverlay(page, info.title, info.bannerUi);
379
379
  // Clear any tracker from a previous highlight before cycling through this
380
380
  // step's own.
381
381
  await page
@@ -574,7 +574,7 @@ export async function renderAfterStep(page, info) {
574
574
  * regardless - main()'s own try/finally - but not before this is visible).
575
575
  */
576
576
  async function renderStepError(page, info) {
577
- await installOverlay(page, info.title);
577
+ await installOverlay(page, info.title, info.bannerUi);
578
578
  const errorPayload = { ...info, stepLabel: miniStepLabel(info) };
579
579
  await page
580
580
  .evaluate((info) => {
@@ -1,12 +1,10 @@
1
1
  import { ensureShadowRoot } from "./ui/shadow.js";
2
- import { composeStepOverlay } from "./ui/compose.js";
3
- const RING_CSS = composeStepOverlay();
4
2
  const FAVICON = "data:image/svg+xml," +
5
3
  encodeURIComponent("<svg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 32 32'><circle cx='16' cy='16' r='14' fill='#7C3AED'/></svg>");
6
4
  export async function installDemoChrome(page, title = "waygraph auto", options = {}) {
7
5
  const showBanner = options.banner !== false;
6
+ // ring/cursor/banner CSS comes from the one shared bundle - see ui/css/README.md.
8
7
  await ensureShadowRoot(page);
9
- await page.evaluate(([css, key]) => __wgCss(css, key), [RING_CSS, "wg-overlay-css"]).catch(() => { });
10
8
  await page
11
9
  .evaluate(({ title, favicon, showBanner }) => {
12
10
  if (!__wgById("wg-ring")) {
@@ -0,0 +1,209 @@
1
+ /* Bundled at build time by scripts/copy-ui-css.mjs - do not hand-edit. Edit src/ui/css/*.css. */
2
+
3
+ :host{--layer-1:1;--layer-2:2;--layer-3:3;--layer-4:4;--layer-5:5;--layer-important:2147483647}
4
+
5
+ :host{--ease-1:cubic-bezier(.25,0,.5,1);--ease-2:cubic-bezier(.25,0,.4,1);--ease-3:cubic-bezier(.25,0,.3,1);--ease-4:cubic-bezier(.25,0,.2,1);--ease-5:cubic-bezier(.25,0,.1,1);--ease-in-1:cubic-bezier(.25,0,1,1);--ease-in-2:cubic-bezier(.50,0,1,1);--ease-in-3:cubic-bezier(.70,0,1,1);--ease-in-4:cubic-bezier(.90,0,1,1);--ease-in-5:cubic-bezier(1,0,1,1);--ease-out-1:cubic-bezier(0,0,.75,1);--ease-out-2:cubic-bezier(0,0,.50,1);--ease-out-3:cubic-bezier(0,0,.3,1);--ease-out-4:cubic-bezier(0,0,.1,1);--ease-out-5:cubic-bezier(0,0,0,1);--ease-in-out-1:cubic-bezier(.1,0,.9,1);--ease-in-out-2:cubic-bezier(.3,0,.7,1);--ease-in-out-3:cubic-bezier(.5,0,.5,1);--ease-in-out-4:cubic-bezier(.7,0,.3,1);--ease-in-out-5:cubic-bezier(.9,0,.1,1);--ease-elastic-out-1:cubic-bezier(.5,.75,.75,1.25);--ease-elastic-out-2:cubic-bezier(.5,1,.75,1.25);--ease-elastic-out-3:cubic-bezier(.5,1.25,.75,1.25);--ease-elastic-out-4:cubic-bezier(.5,1.5,.75,1.25);--ease-elastic-out-5:cubic-bezier(.5,1.75,.75,1.25);--ease-elastic-in-1:cubic-bezier(.5,-0.25,.75,1);--ease-elastic-in-2:cubic-bezier(.5,-0.50,.75,1);--ease-elastic-in-3:cubic-bezier(.5,-0.75,.75,1);--ease-elastic-in-4:cubic-bezier(.5,-1.00,.75,1);--ease-elastic-in-5:cubic-bezier(.5,-1.25,.75,1);--ease-elastic-in-out-1:cubic-bezier(.5,-.1,.1,1.5);--ease-elastic-in-out-2:cubic-bezier(.5,-.3,.1,1.5);--ease-elastic-in-out-3:cubic-bezier(.5,-.5,.1,1.5);--ease-elastic-in-out-4:cubic-bezier(.5,-.7,.1,1.5);--ease-elastic-in-out-5:cubic-bezier(.5,-.9,.1,1.5);--ease-step-1:steps(2);--ease-step-2:steps(3);--ease-step-3:steps(4);--ease-step-4:steps(7);--ease-step-5:steps(10);--ease-elastic-1:var(--ease-elastic-out-1);--ease-elastic-2:var(--ease-elastic-out-2);--ease-elastic-3:var(--ease-elastic-out-3);--ease-elastic-4:var(--ease-elastic-out-4);--ease-elastic-5:var(--ease-elastic-out-5);--ease-squish-1:var(--ease-elastic-in-out-1);--ease-squish-2:var(--ease-elastic-in-out-2);--ease-squish-3:var(--ease-elastic-in-out-3);--ease-squish-4:var(--ease-elastic-in-out-4);--ease-squish-5:var(--ease-elastic-in-out-5);--ease-spring-1:linear(0,0.006,0.025 2.8%,0.101 6.1%,0.539 18.9%,0.721 25.3%,0.849 31.5%,0.937 38.1%,0.968 41.8%,0.991 45.7%,1.006 50.1%,1.015 55%,1.017 63.9%,1.001);--ease-spring-2:linear(0,0.007,0.029 2.2%,0.118 4.7%,0.625 14.4%,0.826 19%,0.902,0.962,1.008 26.1%,1.041 28.7%,1.064 32.1%,1.07 36%,1.061 40.5%,1.015 53.4%,0.999 61.6%,0.995 71.2%,1);--ease-spring-3:linear(0,0.009,0.035 2.1%,0.141 4.4%,0.723 12.9%,0.938 16.7%,1.017,1.077,1.121,1.149 24.3%,1.159,1.163,1.161,1.154 29.9%,1.129 32.8%,1.051 39.6%,1.017 43.1%,0.991,0.977 51%,0.974 53.8%,0.975 57.1%,0.997 69.8%,1.003 76.9%,1);--ease-spring-4:linear(0,0.009,0.037 1.7%,0.153 3.6%,0.776 10.3%,1.001,1.142 16%,1.185,1.209 19%,1.215 19.9% 20.8%,1.199,1.165 25%,1.056 30.3%,1.008 33%,0.973,0.955 39.2%,0.953 41.1%,0.957 43.3%,0.998 53.3%,1.009 59.1% 63.7%,0.998 78.9%,1);--ease-spring-5:linear(0,0.01,0.04 1.6%,0.161 3.3%,0.816 9.4%,1.046,1.189 14.4%,1.231,1.254 17%,1.259,1.257 18.6%,1.236,1.194 22.3%,1.057 27%,0.999 29.4%,0.955 32.1%,0.942,0.935 34.9%,0.933,0.939 38.4%,1 47.3%,1.011,1.017 52.6%,1.016 56.4%,1 65.2%,0.996 70.2%,1.001 87.2%,1);--ease-bounce-1:linear(0,0.004,0.016,0.035,0.063,0.098,0.141,0.191,0.25,0.316,0.391 36.8%,0.563,0.766,1 58.8%,0.946,0.908 69.1%,0.895,0.885,0.879,0.878,0.879,0.885,0.895,0.908 89.7%,0.946,1);--ease-bounce-2:linear(0,0.004,0.016,0.035,0.063,0.098,0.141 15.1%,0.25,0.391,0.562,0.765,1,0.892 45.2%,0.849,0.815,0.788,0.769,0.757,0.753,0.757,0.769,0.788,0.815,0.85,0.892 75.2%,1 80.2%,0.973,0.954,0.943,0.939,0.943,0.954,0.973,1);--ease-bounce-3:linear(0,0.004,0.016,0.035,0.062,0.098,0.141 11.4%,0.25,0.39,0.562,0.764,1 30.3%,0.847 34.8%,0.787,0.737,0.699,0.672,0.655,0.65,0.656,0.672,0.699,0.738,0.787,0.847 61.7%,1 66.2%,0.946,0.908,0.885 74.2%,0.879,0.878,0.879,0.885 79.5%,0.908,0.946,1 87.4%,0.981,0.968,0.96,0.957,0.96,0.968,0.981,1);--ease-bounce-4:linear(0,0.004,0.016 3%,0.062,0.141,0.25,0.391,0.562 18.2%,1 24.3%,0.81,0.676 32.3%,0.629,0.595,0.575,0.568,0.575,0.595,0.629,0.676 48.2%,0.811,1 56.2%,0.918,0.86,0.825,0.814,0.825,0.86,0.918,1 77.2%,0.94 80.6%,0.925,0.92,0.925,0.94 87.5%,1 90.9%,0.974,0.965,0.974,1);--ease-bounce-5:linear(0,0.004,0.016 2.5%,0.063,0.141,0.25 10.1%,0.562,1 20.2%,0.783,0.627,0.534 30.9%,0.511,0.503,0.511,0.534 38%,0.627,0.782,1 48.7%,0.892,0.815,0.769 56.3%,0.757,0.753,0.757,0.769 61.3%,0.815,0.892,1 68.8%,0.908 72.4%,0.885,0.878,0.885,0.908 79.4%,1 83%,0.954 85.5%,0.943,0.939,0.943,0.954 90.5%,1 93%,0.977,0.97,0.977,1);--ease-circ-in:cubic-bezier(.6,.04,.98,.335);--ease-circ-in-out:cubic-bezier(.785,.135,.15,.86);--ease-circ-out:cubic-bezier(.075,.82,.165,1);--ease-cubic-in:cubic-bezier(.55,.055,.675,.19);--ease-cubic-in-out:cubic-bezier(.645,.045,.355,1);--ease-cubic-out:cubic-bezier(.215,.61,.355,1);--ease-expo-in:cubic-bezier(.95,.05,.795,.035);--ease-expo-in-out:cubic-bezier(1,0,0,1);--ease-expo-out:cubic-bezier(.19,1,.22,1);--ease-quad-in:cubic-bezier(.55,.085,.68,.53);--ease-quad-in-out:cubic-bezier(.455,.03,.515,.955);--ease-quad-out:cubic-bezier(.25,.46,.45,.94);--ease-quart-in:cubic-bezier(.895,.03,.685,.22);--ease-quart-in-out:cubic-bezier(.77,0,.175,1);--ease-quart-out:cubic-bezier(.165,.84,.44,1);--ease-quint-in:cubic-bezier(.755,.05,.855,.06);--ease-quint-in-out:cubic-bezier(.86,0,.07,1);--ease-quint-out:cubic-bezier(.23,1,.32,1);--ease-sine-in:cubic-bezier(.47,0,.745,.715);--ease-sine-in-out:cubic-bezier(.445,.05,.55,.95);--ease-sine-out:cubic-bezier(.39,.575,.565,1)}
6
+
7
+ :host{--shadow-color:220 3% 15%;--shadow-strength:1%;--shadow-strength-3:calc(var(--shadow-strength) + 2%);--shadow-strength-4:calc(var(--shadow-strength) + 3%);--shadow-strength-5:calc(var(--shadow-strength) + 4%);--shadow-strength-6:calc(var(--shadow-strength) + 5%);--shadow-strength-7:calc(var(--shadow-strength) + 6%);--shadow-strength-8:calc(var(--shadow-strength) + 7%);--shadow-strength-10:calc(var(--shadow-strength) + 9%);--inner-shadow-highlight:inset 0 -.5px 0 0 #fff,inset 0 .5px 0 0 rgba(0,0,0,.067);--shadow-1:0 1px 2px -1px hsl(var(--shadow-color)/var(--shadow-strength-10));--shadow-2:0 3px 5px -2px hsl(var(--shadow-color)/var(--shadow-strength-4)),0 7px 14px -5px hsl(var(--shadow-color)/var(--shadow-strength-6));--shadow-3:0 -1px 3px 0 hsl(var(--shadow-color)/var(--shadow-strength-3)),0 1px 2px -5px hsl(var(--shadow-color)/var(--shadow-strength-3)),0 2px 5px -5px hsl(var(--shadow-color)/var(--shadow-strength-5)),0 4px 12px -5px hsl(var(--shadow-color)/var(--shadow-strength-6)),0 12px 15px -5px hsl(var(--shadow-color)/var(--shadow-strength-8));--shadow-4:0 -2px 5px 0 hsl(var(--shadow-color)/var(--shadow-strength-3)),0 1px 1px -2px hsl(var(--shadow-color)/var(--shadow-strength-4)),0 2px 2px -2px hsl(var(--shadow-color)/var(--shadow-strength-4)),0 5px 5px -2px hsl(var(--shadow-color)/var(--shadow-strength-5)),0 9px 9px -2px hsl(var(--shadow-color)/var(--shadow-strength-6)),0 16px 16px -2px hsl(var(--shadow-color)/var(--shadow-strength-7));--shadow-5:0 -1px 2px 0 hsl(var(--shadow-color)/var(--shadow-strength-3)),0 2px 1px -2px hsl(var(--shadow-color)/var(--shadow-strength-4)),0 5px 5px -2px hsl(var(--shadow-color)/var(--shadow-strength-4)),0 10px 10px -2px hsl(var(--shadow-color)/var(--shadow-strength-5)),0 20px 20px -2px hsl(var(--shadow-color)/var(--shadow-strength-6)),0 40px 40px -2px hsl(var(--shadow-color)/var(--shadow-strength-8));--shadow-6:0 -1px 2px 0 hsl(var(--shadow-color)/var(--shadow-strength-3)),0 3px 2px -2px hsl(var(--shadow-color)/var(--shadow-strength-4)),0 7px 5px -2px hsl(var(--shadow-color)/var(--shadow-strength-4)),0 12px 10px -2px hsl(var(--shadow-color)/var(--shadow-strength-5)),0 22px 18px -2px hsl(var(--shadow-color)/var(--shadow-strength-6)),0 41px 33px -2px hsl(var(--shadow-color)/var(--shadow-strength-7)),0 100px 80px -2px hsl(var(--shadow-color)/var(--shadow-strength-8));--inner-shadow-0:inset 0 0 0 1px hsl(var(--shadow-color)/var(--shadow-strength-10));--inner-shadow-1:inset 0 1px 2px 0 hsl(var(--shadow-color)/var(--shadow-strength-10)),var(--inner-shadow-highlight);--inner-shadow-2:inset 0 1px 4px 0 hsl(var(--shadow-color)/var(--shadow-strength-10)),var(--inner-shadow-highlight);--inner-shadow-3:inset 0 2px 8px 0 hsl(var(--shadow-color)/var(--shadow-strength-10)),var(--inner-shadow-highlight);--inner-shadow-4:inset 0 2px 14px 0 hsl(var(--shadow-color)/var(--shadow-strength-10)),var(--inner-shadow-highlight)}@media (prefers-color-scheme:dark){:host{--shadow-color:220 40% 2%;--shadow-strength:25%;--inner-shadow-highlight:inset 0 -.5px 0 0 hsla(0,0%,100%,.067),inset 0 .5px 0 0 rgba(0,0,0,.467)}}
8
+
9
+ /*
10
+ * waygraph overlay design tokens. Built on Open Props (github.com/argyleink/open-props, MIT) for
11
+ * z-index/easing/shadow primitives - see the imports this file's loader concatenates ahead of it
12
+ * (open-props's own `.shadow.min.css` builds, written for exactly this: variables scoped to a
13
+ * shadow root via `:host` instead of `:root`). Brand tones are ours; everything else structural
14
+ * (stacking, motion, elevation) comes from the library, not hand-tuned per rule.
15
+ *
16
+ * Change a color/size here - every component below reads it via var(), nothing is hand-duplicated.
17
+ */
18
+ :host {
19
+ /* Tone palette: ring border/glow, click-pulse, label bg/fg. One row per tone. */
20
+ --wg-tone-planned-ring: #7C3AED; --wg-tone-planned-glow: rgba(124,58,237,.16); --wg-tone-planned-bg: #7C3AED; --wg-tone-planned-fg: #fff;
21
+ --wg-tone-auto-ring: #9CA3AF; --wg-tone-auto-glow: rgba(156,163,175,.28); --wg-tone-auto-bg: #6B7280; --wg-tone-auto-fg: #fff;
22
+ --wg-tone-info-ring: #3B82F6; --wg-tone-info-glow: rgba(59,130,246,.22); --wg-tone-info-bg: #2563EB; --wg-tone-info-fg: #fff;
23
+ --wg-tone-warning-ring: #EAB308; --wg-tone-warning-glow: rgba(234,179,8,.22); --wg-tone-warning-bg: #EAB308; --wg-tone-warning-fg: #1c1917;
24
+ --wg-tone-danger-ring: #EF4444; --wg-tone-danger-glow: rgba(239,68,68,.22); --wg-tone-danger-bg: #DC2626; --wg-tone-danger-fg: #fff;
25
+ --wg-tone-success-ring: #22C55E; --wg-tone-success-glow: rgba(34,197,94,.22); --wg-tone-success-bg: #16A34A; --wg-tone-success-fg: #fff;
26
+ --wg-tone-orange-ring: #F97316; --wg-tone-orange-glow: rgba(249,115,22,.22); --wg-tone-orange-bg: #EA580C; --wg-tone-orange-fg: #fff;
27
+
28
+ --wg-surface: rgba(20,10,40,.94);
29
+ --wg-accent: #7C3AED;
30
+ --wg-accent-soft: #c9a6ff;
31
+ --wg-font: system-ui, sans-serif;
32
+ --wg-font-mono: ui-monospace, "SF Mono", Consolas, monospace;
33
+
34
+ /* Stacking: Open Props' --layer-important is the one legitimate use of a max z-index (a
35
+ floating control that must sit above literally anything the host page can throw at it). */
36
+ --wg-z-top: var(--layer-important, 2147483647);
37
+ --wg-z-ring: 2147483646;
38
+ --wg-z-fx: 2147483645;
39
+ --wg-z-focus: 2147483644;
40
+ --wg-z-dock: 2147483000;
41
+ /* Banner sits BELOW rings/labels/todos - a title card must never shadow a highlight. */
42
+ --wg-z-banner: 2147483000;
43
+
44
+ --wg-ease: var(--ease-3, cubic-bezier(.22,1,.36,1));
45
+ --wg-shadow-dock: var(--shadow-3, 0 2px 10px rgba(0,0,0,.3));
46
+ --wg-shadow-banner: var(--shadow-4, 0 8px 20px rgba(0,0,0,.3));
47
+ --wg-radius-sm: var(--radius-2, 8px);
48
+ --wg-radius-md: var(--radius-3, 10px);
49
+ --wg-radius-lg: var(--radius-4, 12px);
50
+ }
51
+
52
+
53
+ /* The highlight ring + its label (#wg-ring, #wg-ring-label). Tone comes from data-tone, resolved
54
+ * against the tokens in tokens.css - add a tone there, it works here with no new rule. */
55
+ #wg-ring {
56
+ position: fixed; z-index: var(--wg-z-ring); pointer-events: none; opacity: 0;
57
+ border: 2.5px solid var(--wg-tone-planned-ring, #7C3AED); border-radius: var(--wg-radius-md);
58
+ box-shadow: 0 0 0 4px var(--wg-tone-planned-glow, rgba(124,58,237,.16));
59
+ /* Opacity fade only - NEVER transition border-color/box-shadow: tone swaps must snap instantly. */
60
+ transition: opacity .3s ease;
61
+ }
62
+ #wg-ring[data-tone] { border-color: var(--wg-tone-ring); box-shadow: 0 0 0 4px var(--wg-tone-glow); }
63
+ #wg-ring[data-tone=planned] { --wg-tone-ring: var(--wg-tone-planned-ring); --wg-tone-glow: var(--wg-tone-planned-glow); }
64
+ #wg-ring[data-tone=auto] { --wg-tone-ring: var(--wg-tone-auto-ring); --wg-tone-glow: var(--wg-tone-auto-glow); }
65
+ #wg-ring[data-tone=info] { --wg-tone-ring: var(--wg-tone-info-ring); --wg-tone-glow: var(--wg-tone-info-glow); }
66
+ #wg-ring[data-tone=warning] { --wg-tone-ring: var(--wg-tone-warning-ring); --wg-tone-glow: var(--wg-tone-warning-glow); }
67
+ #wg-ring[data-tone=danger] { --wg-tone-ring: var(--wg-tone-danger-ring); --wg-tone-glow: var(--wg-tone-danger-glow); }
68
+ #wg-ring[data-tone=success] { --wg-tone-ring: var(--wg-tone-success-ring); --wg-tone-glow: var(--wg-tone-success-glow); }
69
+ #wg-ring[data-tone=orange] { --wg-tone-ring: var(--wg-tone-orange-ring); --wg-tone-glow: var(--wg-tone-orange-glow); }
70
+ #wg-ring[data-size=sm] { border-width: 1.5px; border-radius: var(--wg-radius-sm); }
71
+ #wg-ring[data-size=lg] { border-width: 4px; border-radius: var(--wg-radius-lg); }
72
+
73
+ #wg-ring-label {
74
+ position: fixed; z-index: var(--wg-z-ring); pointer-events: none; opacity: 0;
75
+ max-width: min(360px, 70vw); white-space: normal; padding: 6px 10px; border-radius: 7px;
76
+ background: var(--wg-tone-bg, var(--wg-tone-planned-bg)); color: var(--wg-tone-fg, var(--wg-tone-planned-fg));
77
+ font: 600 12px/1.35 var(--wg-font); transition: opacity .3s ease;
78
+ }
79
+ #wg-ring-label[data-tone=planned] { --wg-tone-bg: var(--wg-tone-planned-bg); --wg-tone-fg: var(--wg-tone-planned-fg); }
80
+ #wg-ring-label[data-tone=auto] { --wg-tone-bg: var(--wg-tone-auto-bg); --wg-tone-fg: var(--wg-tone-auto-fg); }
81
+ #wg-ring-label[data-tone=info] { --wg-tone-bg: var(--wg-tone-info-bg); --wg-tone-fg: var(--wg-tone-info-fg); }
82
+ #wg-ring-label[data-tone=warning] { --wg-tone-bg: var(--wg-tone-warning-bg); --wg-tone-fg: var(--wg-tone-warning-fg); }
83
+ #wg-ring-label[data-tone=danger] { --wg-tone-bg: var(--wg-tone-danger-bg); --wg-tone-fg: var(--wg-tone-danger-fg); }
84
+ #wg-ring-label[data-tone=success] { --wg-tone-bg: var(--wg-tone-success-bg); --wg-tone-fg: var(--wg-tone-success-fg); }
85
+ #wg-ring-label[data-tone=orange] { --wg-tone-bg: var(--wg-tone-orange-bg); --wg-tone-fg: var(--wg-tone-orange-fg); }
86
+ /* Gray (auto) = a real Playwright-driven instruction - mark it, a human/AI watching can't "see" DOM state otherwise. */
87
+ #wg-ring-label[data-tone=auto]::before { content: "\1F916\00a0"; }
88
+ #wg-ring-label[data-size=sm] { font-size: 10px; line-height: 1.25; padding: 4px 7px; border-radius: 5px; }
89
+ #wg-ring-label[data-size=lg] { font-size: 16px; line-height: 1.35; padding: 8px 14px; border-radius: 9px; max-width: min(480px, 85vw); }
90
+ #wg-ring-label[data-weight=bold] { font-weight: 800; }
91
+ #wg-ring-label[data-weight=normal] { font-weight: 600; }
92
+
93
+ /* Agent-sent pilot fixture rings/labels (.wg-pilot-fx-ring|label) - identical tone language as #wg-ring. */
94
+ .wg-pilot-fx-ring {
95
+ position: fixed; z-index: var(--wg-z-fx); pointer-events: none; opacity: 0; box-sizing: border-box;
96
+ border: 3px solid var(--wg-tone-planned-ring); border-radius: var(--wg-radius-md);
97
+ transition: opacity .12s ease, left .12s, top .12s, width .12s, height .12s;
98
+ }
99
+ .wg-pilot-fx-ring[data-tone] { border-color: var(--wg-tone-ring); box-shadow: 0 0 0 4px var(--wg-tone-glow); }
100
+ .wg-pilot-fx-ring[data-tone=planned] { --wg-tone-ring: var(--wg-tone-planned-ring); --wg-tone-glow: var(--wg-tone-planned-glow); }
101
+ .wg-pilot-fx-ring[data-tone=auto] { --wg-tone-ring: var(--wg-tone-auto-ring); --wg-tone-glow: var(--wg-tone-auto-glow); }
102
+ .wg-pilot-fx-ring[data-tone=info] { --wg-tone-ring: var(--wg-tone-info-ring); --wg-tone-glow: var(--wg-tone-info-glow); }
103
+ .wg-pilot-fx-ring[data-tone=warning] { --wg-tone-ring: var(--wg-tone-warning-ring); --wg-tone-glow: var(--wg-tone-warning-glow); }
104
+ .wg-pilot-fx-ring[data-tone=danger] { --wg-tone-ring: var(--wg-tone-danger-ring); --wg-tone-glow: var(--wg-tone-danger-glow); }
105
+ .wg-pilot-fx-ring[data-tone=success] { --wg-tone-ring: var(--wg-tone-success-ring); --wg-tone-glow: var(--wg-tone-success-glow); }
106
+ .wg-pilot-fx-ring[data-tone=orange] { --wg-tone-ring: var(--wg-tone-orange-ring); --wg-tone-glow: var(--wg-tone-orange-glow); }
107
+ .wg-pilot-fx-ring[data-size=sm] { border-width: 1.5px; border-radius: var(--wg-radius-sm); }
108
+ .wg-pilot-fx-ring[data-size=lg] { border-width: 4px; border-radius: var(--wg-radius-lg); }
109
+
110
+ .wg-pilot-fx-label {
111
+ position: fixed; z-index: var(--wg-z-fx); pointer-events: none; opacity: 0;
112
+ font: 600 12px/1.3 var(--wg-font); padding: 5px 9px; border-radius: 6px;
113
+ max-width: min(360px, 80vw); box-shadow: 0 2px 8px rgba(0,0,0,.25); white-space: nowrap;
114
+ overflow: hidden; text-overflow: ellipsis; transition: opacity .12s ease;
115
+ background: var(--wg-tone-bg, var(--wg-tone-planned-bg)); color: var(--wg-tone-fg, var(--wg-tone-planned-fg));
116
+ }
117
+ .wg-pilot-fx-label[data-tone=planned] { --wg-tone-bg: var(--wg-tone-planned-bg); --wg-tone-fg: var(--wg-tone-planned-fg); }
118
+ .wg-pilot-fx-label[data-tone=auto] { --wg-tone-bg: var(--wg-tone-auto-bg); --wg-tone-fg: var(--wg-tone-auto-fg); }
119
+ .wg-pilot-fx-label[data-tone=info] { --wg-tone-bg: var(--wg-tone-info-bg); --wg-tone-fg: var(--wg-tone-info-fg); }
120
+ .wg-pilot-fx-label[data-tone=warning] { --wg-tone-bg: var(--wg-tone-warning-bg); --wg-tone-fg: var(--wg-tone-warning-fg); }
121
+ .wg-pilot-fx-label[data-tone=danger] { --wg-tone-bg: var(--wg-tone-danger-bg); --wg-tone-fg: var(--wg-tone-danger-fg); }
122
+ .wg-pilot-fx-label[data-tone=success] { --wg-tone-bg: var(--wg-tone-success-bg); --wg-tone-fg: var(--wg-tone-success-fg); }
123
+ .wg-pilot-fx-label[data-tone=orange] { --wg-tone-bg: var(--wg-tone-orange-bg); --wg-tone-fg: var(--wg-tone-orange-fg); }
124
+ .wg-pilot-fx-label[data-tone=auto]::before { content: "\1F916\00a0"; }
125
+ .wg-pilot-fx-label[data-size=sm] { font-size: 10px; padding: 4px 7px; }
126
+ .wg-pilot-fx-label[data-size=lg] { font-size: 16px; padding: 8px 14px; }
127
+ .wg-pilot-fx-label[data-weight=bold] { font-weight: 800; }
128
+
129
+
130
+ /* Travelling mouse cursor + click ripple (#wg-cursor, #wg-click-pulse). */
131
+ #wg-cursor {
132
+ position: fixed; z-index: var(--wg-z-top); width: 24px; height: 24px; pointer-events: none;
133
+ left: 0; top: 0; opacity: 0; margin: 0;
134
+ /* Travel time is JS-driven via --wg-cursor-ms (a hardcoded duration would make speed a no-op). */
135
+ transition: transform var(--wg-cursor-ms, 600ms) var(--wg-ease), opacity .2s ease;
136
+ filter: drop-shadow(0 2px 4px rgba(12,12,26,.4));
137
+ }
138
+ #wg-click-pulse {
139
+ position: fixed; z-index: var(--wg-z-top); width: 14px; height: 14px;
140
+ margin-left: -7px; margin-top: -7px; border-radius: 50%; pointer-events: none; opacity: 0;
141
+ border: 2px solid var(--wg-tone-ring, var(--wg-tone-planned-ring)); background: var(--wg-tone-pulse, var(--wg-tone-planned-glow));
142
+ }
143
+ #wg-click-pulse[data-tone=auto] { --wg-tone-ring: var(--wg-tone-auto-ring); --wg-tone-pulse: var(--wg-tone-auto-glow); }
144
+ #wg-click-pulse[data-tone=info] { --wg-tone-ring: var(--wg-tone-info-ring); --wg-tone-pulse: var(--wg-tone-info-glow); }
145
+ #wg-click-pulse[data-tone=warning] { --wg-tone-ring: var(--wg-tone-warning-ring); --wg-tone-pulse: var(--wg-tone-warning-glow); }
146
+ #wg-click-pulse[data-tone=danger] { --wg-tone-ring: var(--wg-tone-danger-ring); --wg-tone-pulse: var(--wg-tone-danger-glow); }
147
+ #wg-click-pulse[data-tone=success] { --wg-tone-ring: var(--wg-tone-success-ring); --wg-tone-pulse: var(--wg-tone-success-glow); }
148
+ #wg-click-pulse.wg-pulse { animation: wg-pulse .5s ease-out; }
149
+ @keyframes wg-pulse { 0% { opacity: .9; transform: scale(.4); } 100% { opacity: 0; transform: scale(2.4); } }
150
+
151
+
152
+ /* Top title banner (#wg-banner). Sits BELOW the ring/label/dock layers (--wg-z-banner) - a title
153
+ * card must never shadow a highlight; see tokens.css. Moves out of the way of a ring it overlaps
154
+ * (data-collision, driven from inpage/banner.js's __wgBannerAvoidRing) unless authored off. */
155
+ #wg-banner {
156
+ position: fixed; z-index: var(--wg-z-banner); top: 14px; left: 14px;
157
+ background: var(--wg-surface); color: #fff; border-radius: var(--wg-radius-lg); padding: 10px 16px;
158
+ font: 14px/1.4 var(--wg-font); box-shadow: var(--wg-shadow-banner);
159
+ border: 1px solid rgba(124,58,237,.4); cursor: pointer;
160
+ transition: left .3s var(--wg-ease), right .3s var(--wg-ease), transform .3s var(--wg-ease);
161
+ }
162
+ #wg-banner[data-pos=left] { left: 14px; right: auto; transform: none; }
163
+ #wg-banner[data-pos=center] { left: 50%; right: auto; transform: translateX(-50%); }
164
+ #wg-banner[data-pos=right] { right: 14px; left: auto; transform: none; }
165
+ #wg-banner .wg-banner-tag {
166
+ display: block; font-size: 10px; font-weight: 700; color: var(--wg-accent-soft);
167
+ letter-spacing: .05em; text-transform: uppercase; margin-bottom: 2px;
168
+ }
169
+
170
+
171
+ /*
172
+ * Floating fixture todo dock for Pilot (#wg-pilot-fx-todos). The demo runner's OWN `.wg-todo-dock` /
173
+ * `#wg-todo-dock` (src/runner/overlay-css.js) is a separate, richer implementation - fold/tucked/
174
+ * slide-position transitions this file does not replicate - and deliberately NOT redefined here:
175
+ * two rule sets for the same selector, injected in different orders, is exactly the "sometimes it
176
+ * doesn't line up" bug class this split guards against. Only #wg-pilot-fx-todos, a genuine
177
+ * duplicate of this file's own rules, is consolidated.
178
+ */
179
+ #wg-pilot-fx-todos {
180
+ position: fixed; z-index: var(--wg-z-fx); top: 72px; max-width: 280px; max-height: calc(100vh - 100px);
181
+ overflow: auto; font: 12px/1.4 ui-sans-serif, system-ui, sans-serif; color: #fff;
182
+ background: var(--wg-surface); border-radius: var(--wg-radius-md); padding: 10px 12px;
183
+ box-shadow: var(--wg-shadow-dock); pointer-events: auto; transition: opacity .25s ease;
184
+ }
185
+ #wg-pilot-fx-todos.wg-todo-behind { z-index: var(--wg-z-focus); opacity: .42; pointer-events: none; }
186
+ #wg-pilot-fx-todos[data-pos=left] { left: 14px; right: auto; }
187
+ #wg-pilot-fx-todos[data-pos=right] { right: 14px; left: auto; }
188
+ #wg-pilot-fx-todos .wg-pilot-fx-todo-title {
189
+ font: 700 11px/1.2 system-ui, sans-serif; color: var(--wg-accent-soft);
190
+ letter-spacing: .04em; text-transform: uppercase; margin: 0 0 8px;
191
+ }
192
+ #wg-pilot-fx-todos ol { list-style: none; margin: 0; padding: 0; }
193
+ #wg-pilot-fx-todos li { margin: 3px 0; color: #ddd; }
194
+ #wg-pilot-fx-todos li.wg-pilot-fx-todo-done { color: #888; text-decoration: line-through; }
195
+ #wg-pilot-fx-todos li.wg-pilot-fx-todo-now { color: #fff; font-weight: 700; }
196
+ #wg-pilot-fx-todos[data-compact="1"]:not(:hover) li.wg-todo-fold { display: none; }
197
+ #wg-pilot-fx-todos .wg-todo-more {
198
+ margin-top: 6px; padding: 4px 8px; border-radius: var(--wg-radius-sm);
199
+ background: rgba(124,58,237,.22); font: 700 11px/1.2 system-ui, sans-serif; color: #e8dcff; cursor: pointer;
200
+ }
201
+ #wg-pilot-fx-todos .wg-todo-more:hover { background: rgba(124,58,237,.35); }
202
+
203
+
204
+ /* Shared dark panel surface token (pilot panel, auto panel, step chrome). Consumers set their own
205
+ * layout (position/size); this file only supplies the shared look. */
206
+ .wg-panel-surface {
207
+ background: var(--wg-surface); color: #fff; border-radius: var(--wg-radius-sm);
208
+ box-shadow: 0 2px 8px rgba(0,0,0,.25);
209
+ }
@@ -8,8 +8,13 @@
8
8
  * host-page markers such as `[data-wg-zoomed]` intentionally stay in the light DOM).
9
9
  */
10
10
  import type { BrowserContext, Page } from "@playwright/test";
11
- export declare function installShadowRoot(): void;
12
- /** Idempotent; call before any overlay install on a page. */
11
+ /**
12
+ * `overlaySheet` is the ONE real-CSS bundle (`ui/stylesheet.ts` -> `dist/ui/overlay.css`, built on
13
+ * Open Props - see `src/ui/css/README.md`) every surface shares; passed in from Node since in-page
14
+ * code can't read a file. Installed once per shadow root, before anything else runs.
15
+ */
16
+ export declare function installShadowRoot(overlaySheet?: string): void;
17
+ /** Idempotent; call before any overlay install on a page. Installs the shared stylesheet bundle. */
13
18
  export declare function ensureShadowRoot(page: Page): Promise<void>;
14
19
  /** Also define the helpers on every future document (pilot overlay persists across navigations). */
15
20
  export declare function installShadowRootEverywhere(context: BrowserContext): Promise<void>;
package/dist/ui/shadow.js CHANGED
@@ -1,4 +1,10 @@
1
- export function installShadowRoot() {
1
+ import { getOverlaySheet } from "./stylesheet.js";
2
+ /**
3
+ * `overlaySheet` is the ONE real-CSS bundle (`ui/stylesheet.ts` -> `dist/ui/overlay.css`, built on
4
+ * Open Props - see `src/ui/css/README.md`) every surface shares; passed in from Node since in-page
5
+ * code can't read a file. Installed once per shadow root, before anything else runs.
6
+ */
7
+ export function installShadowRoot(overlaySheet) {
2
8
  const w = window;
3
9
  if (w.__wgById)
4
10
  return;
@@ -31,12 +37,14 @@ export function installShadowRoot() {
31
37
  if (style.textContent !== css)
32
38
  style.textContent = css;
33
39
  };
40
+ if (overlaySheet)
41
+ w.__wgCss(overlaySheet, "wg-overlay-css");
34
42
  }
35
- /** Idempotent; call before any overlay install on a page. */
43
+ /** Idempotent; call before any overlay install on a page. Installs the shared stylesheet bundle. */
36
44
  export async function ensureShadowRoot(page) {
37
- await page.evaluate(installShadowRoot).catch(() => { });
45
+ await page.evaluate(installShadowRoot, getOverlaySheet()).catch(() => { });
38
46
  }
39
47
  /** Also define the helpers on every future document (pilot overlay persists across navigations). */
40
48
  export async function installShadowRootEverywhere(context) {
41
- await context.addInitScript(installShadowRoot);
49
+ await context.addInitScript(installShadowRoot, getOverlaySheet());
42
50
  }
@@ -0,0 +1,7 @@
1
+ /**
2
+ * The whole overlay stylesheet (Open Props subset + ring/cursor/banner/dock/panel), bundled by
3
+ * `scripts/copy-ui-css.mjs` into `dist/ui/overlay.css`. One real CSS file, read once, injected by
4
+ * `ui/shadow.ts` into the overlay's shadow root - every surface (demo/auto/browser/pilot) gets the
5
+ * exact same rules, not a per-surface regenerated copy.
6
+ */
7
+ export declare function getOverlaySheet(): string;
@@ -0,0 +1,18 @@
1
+ import { readFileSync } from "node:fs";
2
+ import { dirname, join } from "node:path";
3
+ import { fileURLToPath } from "node:url";
4
+ let cached;
5
+ /**
6
+ * The whole overlay stylesheet (Open Props subset + ring/cursor/banner/dock/panel), bundled by
7
+ * `scripts/copy-ui-css.mjs` into `dist/ui/overlay.css`. One real CSS file, read once, injected by
8
+ * `ui/shadow.ts` into the overlay's shadow root - every surface (demo/auto/browser/pilot) gets the
9
+ * exact same rules, not a per-surface regenerated copy.
10
+ */
11
+ export function getOverlaySheet() {
12
+ if (cached !== undefined)
13
+ return cached;
14
+ const here = dirname(fileURLToPath(import.meta.url));
15
+ // Compiled to dist/ui/stylesheet.js; the bundle sits right next to it.
16
+ cached = readFileSync(join(here, "overlay.css"), "utf8");
17
+ return cached;
18
+ }
@@ -0,0 +1 @@
1
+ export declare function verboseLog(surface: string, msg: string): void;
@@ -0,0 +1,16 @@
1
+ /**
2
+ * One log format for every overlay surface (demo / auto / browser / pilot): `waygraph <surface>: ...`
3
+ * with a `HH:MM:SS.mmm` prefix, same shape as `runner/demo-log.js`'s (demo stays on the JS copy since
4
+ * it runs in the target project's own process; this one is for TS-side code — pilot/auto/browser —
5
+ * that can't import a plain .js runner module). Silenced by WAYGRAPH_JSON=1, same convention as demo.
6
+ */
7
+ function ts() {
8
+ const d = new Date();
9
+ const p = (n) => String(n).padStart(2, "0");
10
+ return `${p(d.getHours())}:${p(d.getMinutes())}:${p(d.getSeconds())}.${String(d.getMilliseconds()).padStart(3, "0")}`;
11
+ }
12
+ export function verboseLog(surface, msg) {
13
+ if (process.env.WAYGRAPH_JSON === "1")
14
+ return;
15
+ console.log(`[${ts()}] waygraph ${surface}: ${msg}`);
16
+ }
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
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
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
File without changes
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "waygraph",
3
- "version": "0.15.32",
3
+ "version": "0.15.34",
4
4
  "type": "module",
5
5
  "description": "A typed graph of reusable Blocks for driving a browser through E2E flows.",
6
6
  "license": "MIT",
@@ -37,7 +37,7 @@
37
37
  "url": "git+https://github.com/deviate-dv8/waygraph.git"
38
38
  },
39
39
  "scripts": {
40
- "build": "tsc -p tsconfig.build.json && node scripts/copy-runner.mjs",
40
+ "build": "tsc -p tsconfig.build.json && node scripts/copy-runner.mjs && node scripts/copy-ui-css.mjs",
41
41
  "typecheck": "node bin/waygraph typecheck .",
42
42
  "test": "npm run check:structure && npm run test:unit && playwright test",
43
43
  "test:ui": "playwright test --ui",
@@ -52,6 +52,7 @@
52
52
  "@playwright/test": "^1.40.0"
53
53
  },
54
54
  "dependencies": {
55
+ "open-props": "^1.7.23",
55
56
  "tsx": "^4.0.0"
56
57
  },
57
58
  "devDependencies": {
@@ -1,8 +0,0 @@
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
- }