waygraph 0.12.43 → 0.12.44
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/README.md +1 -1
- package/dist/cli.js +187 -90
- package/dist/highlights.d.ts +13 -0
- package/dist/highlights.js +20 -0
- package/dist/index.d.ts +1 -1
- package/dist/index.js +1 -1
- package/dist/step-overlay.js +5 -2
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -3,7 +3,7 @@
|
|
|
3
3
|
A typed graph of reusable Blocks for driving a browser through E2E flows, in place of a
|
|
4
4
|
flat pile of ad hoc helper functions.
|
|
5
5
|
|
|
6
|
-
**Current:** `0.12.
|
|
6
|
+
**Current:** `0.12.44` — floating todo dock (visible under `--mini`, `ctx.todoPos` / click / `--todo-left|right`), live `ctx.title` banner updates, instant highlight tone snaps.
|
|
7
7
|
|
|
8
8
|
This repo is the `waygraph` npm package itself. The full live **Sauce Demo** example
|
|
9
9
|
(Page inventory hub, Effect Add/Remove, MemNav Open details, `waygraph auto`) ships
|
package/dist/cli.js
CHANGED
|
@@ -412,10 +412,14 @@ function seedMemForFlow(mem, flowBlocks, json, label) {
|
|
|
412
412
|
const RING_CSS =
|
|
413
413
|
"#wg-ring{position:fixed;z-index:2147483646;pointer-events:none;opacity:0;" +
|
|
414
414
|
"border:2.5px solid #7C3AED;border-radius:10px;" +
|
|
415
|
-
|
|
415
|
+
// Opacity fade only - NEVER transition border-color/box-shadow. Tone swaps
|
|
416
|
+
// (auto gray -> planned purple -> warning yellow) must snap instantly;
|
|
417
|
+
// color transitions read as a muddy gray/purple/yellow morph on ring 2+.
|
|
418
|
+
"box-shadow:0 0 0 4px rgba(124,58,237,.16);transition:opacity .3s ease;}" +
|
|
416
419
|
// Planned (stubs / fixtures / YAP / instruction.highlights) = purple.
|
|
417
420
|
// Automation (verify fallback, unmatched fill/click) = gray - operators
|
|
418
421
|
// can ignore engine checks and watch purple + semantic tones.
|
|
422
|
+
"#wg-ring[data-tone=planned]{border-color:#7C3AED;box-shadow:0 0 0 4px rgba(124,58,237,.16);}" +
|
|
419
423
|
"#wg-ring[data-tone=auto]{border-color:#9CA3AF;box-shadow:0 0 0 4px rgba(156,163,175,.28);}" +
|
|
420
424
|
"#wg-ring[data-tone=info]{border-color:#3B82F6;box-shadow:0 0 0 4px rgba(59,130,246,.22);}" +
|
|
421
425
|
"#wg-ring[data-tone=warning]{border-color:#EAB308;box-shadow:0 0 0 4px rgba(234,179,8,.22);}" +
|
|
@@ -431,7 +435,8 @@ const RING_CSS =
|
|
|
431
435
|
// window.__wgPositionRing in installOverlay.
|
|
432
436
|
"#wg-ring-label{position:fixed;z-index:2147483646;pointer-events:none;opacity:0;" +
|
|
433
437
|
"max-width:min(360px,70vw);white-space:normal;padding:6px 10px;border-radius:7px;background:#7C3AED;color:#fff;" +
|
|
434
|
-
"font:600 12px/1.35 system-ui,sans-serif;transition:opacity .3s ease
|
|
438
|
+
"font:600 12px/1.35 system-ui,sans-serif;transition:opacity .3s ease;}" +
|
|
439
|
+
"#wg-ring-label[data-tone=planned]{background:#7C3AED;color:#fff;}" +
|
|
435
440
|
"#wg-ring-label[data-tone=auto]{background:#6B7280;color:#fff;}" +
|
|
436
441
|
"#wg-ring-label[data-tone=info]{background:#2563EB;color:#fff;}" +
|
|
437
442
|
"#wg-ring-label[data-tone=warning]{background:#EAB308;color:#1c1917;}" +
|
|
@@ -509,6 +514,18 @@ const RING_CSS =
|
|
|
509
514
|
"#wg-panel .wg-pace[data-pace-kind=blitz] .wg-pace-badge{background:#22C55E;color:#052e16;}" +
|
|
510
515
|
"#wg-panel .wg-pace[data-pace-kind=ms] .wg-pace-badge{background:#3B82F6;color:#fff;}" +
|
|
511
516
|
"#wg-panel .wg-narration{margin:0 0 12px;font:italic 14px/1.4 system-ui,sans-serif;color:#f0e8ff;}" +
|
|
517
|
+
// Todo checklist lives in #wg-todo-dock (fixed, outside #wg-panel) so
|
|
518
|
+
// --mini / Hide collapse never hides it (.wg-body {display:none} would).
|
|
519
|
+
// Click dock to slide left <-> right (WAYGRAPH_TODO_POS / --todo-left|right).
|
|
520
|
+
"#wg-todo-dock{position:fixed;z-index:2147483646;top:72px;left:14px;" +
|
|
521
|
+
"width:min(280px,42vw);max-height:calc(100vh - 100px);overflow:auto;box-sizing:border-box;" +
|
|
522
|
+
"padding:10px 12px;background:rgba(20,10,40,.94);color:#fff;border-radius:12px;" +
|
|
523
|
+
"border:1px solid rgba(124,58,237,.45);box-shadow:0 8px 24px rgba(0,0,0,.35);" +
|
|
524
|
+
"pointer-events:auto;cursor:pointer;" +
|
|
525
|
+
"transition:transform .4s cubic-bezier(.22,1,.36,1);transform:translateX(0);}" +
|
|
526
|
+
"#wg-todo-dock[data-pos=right]{transform:translateX(calc(100vw - 100% - 28px));}" +
|
|
527
|
+
"#wg-todo-dock[data-pos=left]{transform:translateX(0);}" +
|
|
528
|
+
"#wg-todo-dock #wg-todos{list-style:none;margin:0;padding:0;background:transparent;border:none;}" +
|
|
512
529
|
"#wg-todos{list-style:none;margin:0 0 12px;padding:8px 10px;background:#0f0620;border-radius:8px;" +
|
|
513
530
|
"border:1px solid #3a2a60;}" +
|
|
514
531
|
"#wg-todos li{display:flex;gap:8px;align-items:flex-start;margin:0 0 6px;font:600 12.5px/1.35 system-ui,sans-serif;}" +
|
|
@@ -647,10 +664,12 @@ async function installOverlay(page, title) {
|
|
|
647
664
|
// navigation that rebuilds the banner keeps the human's last pick).
|
|
648
665
|
const envPos = (process.env.WAYGRAPH_TITLE_POS || "left").toLowerCase();
|
|
649
666
|
const bannerPos = envPos === "center" || envPos === "right" ? envPos : "left";
|
|
667
|
+
const envTodoPos = (process.env.WAYGRAPH_TODO_POS || "left").toLowerCase();
|
|
668
|
+
const todoPos = envTodoPos === "right" ? "right" : "left";
|
|
650
669
|
const envAutoplay = process.env.WAYGRAPH_AUTOPLAY === "1";
|
|
651
670
|
await page
|
|
652
671
|
.evaluate(
|
|
653
|
-
({ title, favicon, bannerPos, envAutoplay }) => {
|
|
672
|
+
({ title, favicon, bannerPos, todoPos, envAutoplay }) => {
|
|
654
673
|
// Seed the live autoplay toggle from the env default on first ever
|
|
655
674
|
// load only - a real navigation re-runs this, and re-stamping here
|
|
656
675
|
// would silently undo a human's mid-run checkbox click.
|
|
@@ -818,32 +837,46 @@ async function installOverlay(page, title) {
|
|
|
818
837
|
/* private mode / blocked storage - position still applies this page */
|
|
819
838
|
}
|
|
820
839
|
};
|
|
821
|
-
if (title
|
|
822
|
-
|
|
823
|
-
banner
|
|
824
|
-
|
|
825
|
-
|
|
826
|
-
saved =
|
|
827
|
-
|
|
828
|
-
|
|
840
|
+
if (title) {
|
|
841
|
+
let banner = document.getElementById("wg-banner");
|
|
842
|
+
if (!banner) {
|
|
843
|
+
banner = document.createElement("div");
|
|
844
|
+
banner.id = "wg-banner";
|
|
845
|
+
let saved = null;
|
|
846
|
+
try {
|
|
847
|
+
saved = localStorage.getItem("wg-banner-pos");
|
|
848
|
+
} catch {
|
|
849
|
+
/* ignore */
|
|
850
|
+
}
|
|
851
|
+
const startPos =
|
|
852
|
+
saved && POSITIONS.includes(saved) ? saved : bannerPos;
|
|
853
|
+
applyPos(banner, startPos);
|
|
854
|
+
banner.title = "Click to move: top left / center / right";
|
|
855
|
+
banner.addEventListener("click", (e) => {
|
|
856
|
+
e.stopPropagation();
|
|
857
|
+
const i = POSITIONS.indexOf(banner.dataset.pos || "left");
|
|
858
|
+
applyPos(banner, POSITIONS[(i + 1) % POSITIONS.length]);
|
|
859
|
+
});
|
|
860
|
+
const tag = document.createElement("span");
|
|
861
|
+
tag.className = "wg-banner-tag";
|
|
862
|
+
tag.textContent = "waygraph demo";
|
|
863
|
+
const text = document.createElement("span");
|
|
864
|
+
text.className = "wg-banner-text";
|
|
865
|
+
text.textContent = title;
|
|
866
|
+
banner.appendChild(tag);
|
|
867
|
+
banner.appendChild(text);
|
|
868
|
+
document.documentElement.appendChild(banner);
|
|
869
|
+
} else {
|
|
870
|
+
// Fixture / episode title changes every step - update in place
|
|
871
|
+
// (banner is created once; do not leave the first step's text stuck).
|
|
872
|
+
let text = banner.querySelector(".wg-banner-text");
|
|
873
|
+
if (!text) {
|
|
874
|
+
text = document.createElement("span");
|
|
875
|
+
text.className = "wg-banner-text";
|
|
876
|
+
banner.appendChild(text);
|
|
877
|
+
}
|
|
878
|
+
text.textContent = title;
|
|
829
879
|
}
|
|
830
|
-
const startPos =
|
|
831
|
-
saved && POSITIONS.includes(saved) ? saved : bannerPos;
|
|
832
|
-
applyPos(banner, startPos);
|
|
833
|
-
banner.title = "Click to move: top left / center / right";
|
|
834
|
-
banner.addEventListener("click", (e) => {
|
|
835
|
-
e.stopPropagation();
|
|
836
|
-
const i = POSITIONS.indexOf(banner.dataset.pos || "left");
|
|
837
|
-
applyPos(banner, POSITIONS[(i + 1) % POSITIONS.length]);
|
|
838
|
-
});
|
|
839
|
-
const tag = document.createElement("span");
|
|
840
|
-
tag.className = "wg-banner-tag";
|
|
841
|
-
tag.textContent = "waygraph demo";
|
|
842
|
-
const text = document.createElement("span");
|
|
843
|
-
text.textContent = title;
|
|
844
|
-
banner.appendChild(tag);
|
|
845
|
-
banner.appendChild(text);
|
|
846
|
-
document.documentElement.appendChild(banner);
|
|
847
880
|
}
|
|
848
881
|
// Tab title/favicon: a real navigation resets document.title and any
|
|
849
882
|
// <link rel="icon"> the new document brings, so re-check (not
|
|
@@ -1046,8 +1079,93 @@ async function installOverlay(page, title) {
|
|
|
1046
1079
|
}
|
|
1047
1080
|
}
|
|
1048
1081
|
};
|
|
1082
|
+
// Floating todo dock - lives outside #wg-panel so --mini / Hide never
|
|
1083
|
+
// hide the checklist. Click cycles left <-> right with CSS transform.
|
|
1084
|
+
// Authors set side via ctx.todoPos("left"|"right"); env / --todo-* fallback.
|
|
1085
|
+
window.__wgSyncTodos = (list, pos) => {
|
|
1086
|
+
list = Array.isArray(list) ? list : [];
|
|
1087
|
+
const POS = ["left", "right"];
|
|
1088
|
+
let dock = document.getElementById("wg-todo-dock");
|
|
1089
|
+
// Drop any in-panel leftover (old builds put #wg-todos in .wg-body).
|
|
1090
|
+
document.querySelectorAll("#wg-panel #wg-todos").forEach((el) => el.remove());
|
|
1091
|
+
if (!list.length) {
|
|
1092
|
+
if (dock) dock.remove();
|
|
1093
|
+
return;
|
|
1094
|
+
}
|
|
1095
|
+
const wantPos =
|
|
1096
|
+
pos === "left" || pos === "right"
|
|
1097
|
+
? pos
|
|
1098
|
+
: null;
|
|
1099
|
+
if (!dock) {
|
|
1100
|
+
dock = document.createElement("div");
|
|
1101
|
+
dock.id = "wg-todo-dock";
|
|
1102
|
+
dock.setAttribute("data-wg-ui", "1");
|
|
1103
|
+
dock.setAttribute("data-wg-modal", "todos");
|
|
1104
|
+
dock.setAttribute("data-wg-ready", "1");
|
|
1105
|
+
let saved = null;
|
|
1106
|
+
try {
|
|
1107
|
+
saved = localStorage.getItem("wg-todo-pos");
|
|
1108
|
+
} catch {
|
|
1109
|
+
/* ignore */
|
|
1110
|
+
}
|
|
1111
|
+
const start =
|
|
1112
|
+
wantPos ||
|
|
1113
|
+
(saved && POS.includes(saved) ? saved : todoPos === "right" ? "right" : "left");
|
|
1114
|
+
dock.dataset.pos = start;
|
|
1115
|
+
dock.title = "Click to move checklist: left / right";
|
|
1116
|
+
dock.addEventListener("click", (e) => {
|
|
1117
|
+
e.stopPropagation();
|
|
1118
|
+
const i = POS.indexOf(dock.dataset.pos || "left");
|
|
1119
|
+
const next = POS[(i + 1) % POS.length];
|
|
1120
|
+
dock.dataset.pos = next;
|
|
1121
|
+
try {
|
|
1122
|
+
localStorage.setItem("wg-todo-pos", next);
|
|
1123
|
+
} catch {
|
|
1124
|
+
/* ignore */
|
|
1125
|
+
}
|
|
1126
|
+
});
|
|
1127
|
+
document.documentElement.appendChild(dock);
|
|
1128
|
+
} else if (wantPos) {
|
|
1129
|
+
dock.dataset.pos = wantPos;
|
|
1130
|
+
try {
|
|
1131
|
+
localStorage.setItem("wg-todo-pos", wantPos);
|
|
1132
|
+
} catch {
|
|
1133
|
+
/* ignore */
|
|
1134
|
+
}
|
|
1135
|
+
}
|
|
1136
|
+
const esc = (s) =>
|
|
1137
|
+
String(s)
|
|
1138
|
+
.replace(/&/g, "&")
|
|
1139
|
+
.replace(/</g, "<")
|
|
1140
|
+
.replace(/>/g, ">");
|
|
1141
|
+
dock.innerHTML =
|
|
1142
|
+
'<ul id="wg-todos">' +
|
|
1143
|
+
list
|
|
1144
|
+
.map((t) => {
|
|
1145
|
+
const cls = t.current
|
|
1146
|
+
? "wg-todo-current"
|
|
1147
|
+
: t.done
|
|
1148
|
+
? "wg-todo-done"
|
|
1149
|
+
: "wg-todo-pending";
|
|
1150
|
+
const mark = t.done ? "\u2713" : t.current ? "\u2192" : "\u25CB";
|
|
1151
|
+
return (
|
|
1152
|
+
'<li class="' +
|
|
1153
|
+
cls +
|
|
1154
|
+
'"><span class="wg-todo-mark">' +
|
|
1155
|
+
mark +
|
|
1156
|
+
"</span><span>" +
|
|
1157
|
+
esc(t.text || "") +
|
|
1158
|
+
"</span></li>"
|
|
1159
|
+
);
|
|
1160
|
+
})
|
|
1161
|
+
.join("") +
|
|
1162
|
+
"</ul>";
|
|
1163
|
+
if (window.__wgStampModal) {
|
|
1164
|
+
window.__wgStampModal(dock, "todos", { ready: true });
|
|
1165
|
+
}
|
|
1166
|
+
};
|
|
1049
1167
|
},
|
|
1050
|
-
{ title, favicon: WAYGRAPH_FAVICON, bannerPos, envAutoplay },
|
|
1168
|
+
{ title, favicon: WAYGRAPH_FAVICON, bannerPos, todoPos, envAutoplay },
|
|
1051
1169
|
)
|
|
1052
1170
|
.catch(() => {});
|
|
1053
1171
|
}
|
|
@@ -1137,41 +1255,15 @@ async function renderBeforeStep(page, info) {
|
|
|
1137
1255
|
esc(info.paceLabel || "") +
|
|
1138
1256
|
"</span></div>"
|
|
1139
1257
|
: "";
|
|
1140
|
-
|
|
1141
|
-
|
|
1142
|
-
if (!list.length) return "";
|
|
1143
|
-
return (
|
|
1144
|
-
'<ul id=\\"wg-todos\\">' +
|
|
1145
|
-
list
|
|
1146
|
-
.map((t) => {
|
|
1147
|
-
const cls = t.current ? "wg-todo-current" : t.done ? "wg-todo-done" : "wg-todo-pending";
|
|
1148
|
-
const mark = t.done
|
|
1149
|
-
? String.fromCharCode(0x2713)
|
|
1150
|
-
: t.current
|
|
1151
|
-
? String.fromCharCode(0x2192)
|
|
1152
|
-
: String.fromCharCode(0x25cb);
|
|
1153
|
-
return (
|
|
1154
|
-
'<li class=\\"' +
|
|
1155
|
-
cls +
|
|
1156
|
-
'\\"><span class=\\"wg-todo-mark\\">' +
|
|
1157
|
-
mark +
|
|
1158
|
-
'</span><span>' +
|
|
1159
|
-
esc(t.text || "") +
|
|
1160
|
-
"</span></li>"
|
|
1161
|
-
);
|
|
1162
|
-
})
|
|
1163
|
-
.join("") +
|
|
1164
|
-
"</ul>"
|
|
1165
|
-
);
|
|
1166
|
-
})();
|
|
1258
|
+
// Todos render into floating #wg-todo-dock via __wgSyncTodos - never
|
|
1259
|
+
// inside .wg-body (would vanish under --mini / Hide collapse).
|
|
1167
1260
|
let html =
|
|
1168
1261
|
"<div id=\\"wg-progress\\"><div id=\\"wg-progress-bar\\" style=\\"width:" + pct + "%\\"></div></div>" +
|
|
1169
1262
|
episodesHtml +
|
|
1170
1263
|
paceHtml +
|
|
1171
1264
|
"<div id=\\"wg-modules\\" class=\\"" + modulesClass + "\\">" + modulesHtml + "</div>" +
|
|
1172
1265
|
"<h3>Step " + (info.index + 1) + " / " + info.total + " - " + info.blockName + "</h3>" +
|
|
1173
|
-
narrationHtml
|
|
1174
|
-
todosHtml;
|
|
1266
|
+
narrationHtml;
|
|
1175
1267
|
if (info.keys.length === 0) {
|
|
1176
1268
|
html += "<div class=\\"wg-key\\">(no MemKeys required)</div>";
|
|
1177
1269
|
}
|
|
@@ -1210,6 +1302,7 @@ async function renderBeforeStep(page, info) {
|
|
|
1210
1302
|
forceCollapsed: info.forceCollapsed === true ? true : undefined,
|
|
1211
1303
|
});
|
|
1212
1304
|
}
|
|
1305
|
+
if (window.__wgSyncTodos) window.__wgSyncTodos(info.todos || [], info.todoPos || null);
|
|
1213
1306
|
if (window.__wgStampModal) {
|
|
1214
1307
|
window.__wgStampModal(panel, "panel", {
|
|
1215
1308
|
phase: "before",
|
|
@@ -1552,6 +1645,11 @@ async function cycleHighlightRings(page, highlights, gatesFast, opts) {
|
|
|
1552
1645
|
: normalizeTodos(h.todos, h.todoIndex);
|
|
1553
1646
|
await page
|
|
1554
1647
|
.evaluate((todos) => {
|
|
1648
|
+
if (window.__wgSyncTodos) {
|
|
1649
|
+
window.__wgSyncTodos(todos);
|
|
1650
|
+
return;
|
|
1651
|
+
}
|
|
1652
|
+
// Fallback for pages that never got installOverlay sync helper.
|
|
1555
1653
|
const ul = document.getElementById("wg-todos");
|
|
1556
1654
|
if (!ul) return;
|
|
1557
1655
|
ul.innerHTML = todos
|
|
@@ -1720,33 +1818,7 @@ async function renderAfterStep(page, info) {
|
|
|
1720
1818
|
escA(info.paceLabel || "") +
|
|
1721
1819
|
"</span></div>"
|
|
1722
1820
|
: "";
|
|
1723
|
-
const todosHtml =
|
|
1724
|
-
const list = info.todos || [];
|
|
1725
|
-
if (!list.length) return "";
|
|
1726
|
-
return (
|
|
1727
|
-
'<ul id=\\"wg-todos\\">' +
|
|
1728
|
-
list
|
|
1729
|
-
.map((t) => {
|
|
1730
|
-
const cls = t.current ? "wg-todo-current" : t.done ? "wg-todo-done" : "wg-todo-pending";
|
|
1731
|
-
const mark = t.done
|
|
1732
|
-
? String.fromCharCode(0x2713)
|
|
1733
|
-
: t.current
|
|
1734
|
-
? String.fromCharCode(0x2192)
|
|
1735
|
-
: String.fromCharCode(0x25cb);
|
|
1736
|
-
return (
|
|
1737
|
-
'<li class=\\"' +
|
|
1738
|
-
cls +
|
|
1739
|
-
'\\"><span class=\\"wg-todo-mark\\">' +
|
|
1740
|
-
mark +
|
|
1741
|
-
'</span><span>' +
|
|
1742
|
-
escA(t.text || "") +
|
|
1743
|
-
"</span></li>"
|
|
1744
|
-
);
|
|
1745
|
-
})
|
|
1746
|
-
.join("") +
|
|
1747
|
-
"</ul>"
|
|
1748
|
-
);
|
|
1749
|
-
})();
|
|
1821
|
+
const todosHtml = ""; // todos float in #wg-todo-dock via __wgSyncTodos
|
|
1750
1822
|
panel.innerHTML =
|
|
1751
1823
|
"<div id=\\"wg-progress\\"><div id=\\"wg-progress-bar\\" style=\\"width:" + pct + "%\\"></div></div>" +
|
|
1752
1824
|
episodesHtml +
|
|
@@ -1768,6 +1840,7 @@ async function renderAfterStep(page, info) {
|
|
|
1768
1840
|
forceCollapsed: info.forceCollapsed === true ? true : undefined,
|
|
1769
1841
|
});
|
|
1770
1842
|
}
|
|
1843
|
+
if (window.__wgSyncTodos) window.__wgSyncTodos(info.todos || [], info.todoPos || null);
|
|
1771
1844
|
if (window.__wgStampModal) {
|
|
1772
1845
|
window.__wgStampModal(panel, "panel", {
|
|
1773
1846
|
phase: "after",
|
|
@@ -2390,7 +2463,7 @@ async function teardownOverlay(page) {
|
|
|
2390
2463
|
window.__wgRingTrack = null;
|
|
2391
2464
|
}
|
|
2392
2465
|
window.__wgNarrateOwnsRing = false;
|
|
2393
|
-
for (const id of ["wg-panel", "wg-ring", "wg-ring-label", "wg-cursor", "wg-click-pulse", "wg-banner"]) {
|
|
2466
|
+
for (const id of ["wg-panel", "wg-ring", "wg-ring-label", "wg-cursor", "wg-click-pulse", "wg-banner", "wg-todo-dock"]) {
|
|
2394
2467
|
const el = document.getElementById(id);
|
|
2395
2468
|
if (el) el.remove();
|
|
2396
2469
|
}
|
|
@@ -2921,6 +2994,12 @@ async function runStepMode(engine, start, end, context, page, mem, resolved, slo
|
|
|
2921
2994
|
applyHighlightStyleDefaults(h, flowStyle),
|
|
2922
2995
|
);
|
|
2923
2996
|
const stubBeforeTodos = stubBeforePhase.todos || [];
|
|
2997
|
+
const overlayTitle =
|
|
2998
|
+
(stubBeforePhase.title && String(stubBeforePhase.title).trim()) ||
|
|
2999
|
+
(r.episodeTitle && String(r.episodeTitle).trim()) ||
|
|
3000
|
+
title ||
|
|
3001
|
+
"waygraph demo";
|
|
3002
|
+
const overlayTodoPos = stubBeforePhase.todoPos || undefined;
|
|
2924
3003
|
const isNavBlock = r.block.__waygraphKind === "nav";
|
|
2925
3004
|
const autoNow = await currentAutoplay();
|
|
2926
3005
|
// Video / --mini: compact pill. Never pass false - Hide/localStorage wins.
|
|
@@ -2965,7 +3044,8 @@ async function runStepMode(engine, start, end, context, page, mem, resolved, slo
|
|
|
2965
3044
|
moduleIndex,
|
|
2966
3045
|
allEpisodes,
|
|
2967
3046
|
justEnteredEpisode,
|
|
2968
|
-
title,
|
|
3047
|
+
title: overlayTitle,
|
|
3048
|
+
todoPos: overlayTodoPos,
|
|
2969
3049
|
episodeNumber: r.episodeNumber,
|
|
2970
3050
|
episodeTitle: r.episodeTitle,
|
|
2971
3051
|
stepperMode,
|
|
@@ -3124,12 +3204,18 @@ async function runStepMode(engine, start, end, context, page, mem, resolved, slo
|
|
|
3124
3204
|
}
|
|
3125
3205
|
let highlights;
|
|
3126
3206
|
let stubAfterTodos = [];
|
|
3207
|
+
let afterOverlayTitle = overlayTitle;
|
|
3208
|
+
let afterTodoPos = overlayTodoPos;
|
|
3127
3209
|
if (hasAuthoredStubAfter(r.block, result, fixturesAfter)) {
|
|
3128
3210
|
const afterPhase = await runStubPhase(r.block, "stubAfter", {
|
|
3129
3211
|
out: result,
|
|
3130
3212
|
fixtures: fixturesAfter,
|
|
3131
3213
|
});
|
|
3132
3214
|
stubAfterTodos = afterPhase.todos || [];
|
|
3215
|
+
if (afterPhase.title && String(afterPhase.title).trim()) {
|
|
3216
|
+
afterOverlayTitle = String(afterPhase.title).trim();
|
|
3217
|
+
}
|
|
3218
|
+
if (afterPhase.todoPos) afterTodoPos = afterPhase.todoPos;
|
|
3133
3219
|
highlights = afterPhase.highlights.map((h) => {
|
|
3134
3220
|
const styled = applyHighlightStyleDefaults(h, r.highlightStyle);
|
|
3135
3221
|
return {
|
|
@@ -3163,7 +3249,8 @@ async function runStepMode(engine, start, end, context, page, mem, resolved, slo
|
|
|
3163
3249
|
allDescriptions: moduleDescriptions,
|
|
3164
3250
|
moduleIndex,
|
|
3165
3251
|
allEpisodes,
|
|
3166
|
-
title,
|
|
3252
|
+
title: afterOverlayTitle,
|
|
3253
|
+
todoPos: afterTodoPos,
|
|
3167
3254
|
episodeNumber: r.episodeNumber,
|
|
3168
3255
|
episodeTitle: r.episodeTitle,
|
|
3169
3256
|
stepperMode,
|
|
@@ -4191,6 +4278,12 @@ function parseRunFlags(argv) {
|
|
|
4191
4278
|
else if (a === "--mini" || a === "--stepper-mini") {
|
|
4192
4279
|
out.miniStepper = true;
|
|
4193
4280
|
}
|
|
4281
|
+
else if (a === "--todo-left") {
|
|
4282
|
+
out.todoPos = "left";
|
|
4283
|
+
}
|
|
4284
|
+
else if (a === "--todo-right") {
|
|
4285
|
+
out.todoPos = "right";
|
|
4286
|
+
}
|
|
4194
4287
|
else if (a === "--ff-expand") {
|
|
4195
4288
|
out.ffExpand = true;
|
|
4196
4289
|
}
|
|
@@ -4311,8 +4404,8 @@ function applyRunFlags(flags, opts) {
|
|
|
4311
4404
|
process.env.WAYGRAPH_HEADED = "0";
|
|
4312
4405
|
}
|
|
4313
4406
|
}
|
|
4314
|
-
if ((flags.fast || flags.fullStepper || flags.miniStepper) && !opts?.allowDemoUi) {
|
|
4315
|
-
console.error("waygraph: --fast / --full / --mini are demo-only flags");
|
|
4407
|
+
if ((flags.fast || flags.fullStepper || flags.miniStepper || flags.todoPos) && !opts?.allowDemoUi) {
|
|
4408
|
+
console.error("waygraph: --fast / --full / --mini / --todo-left|--todo-right are demo-only flags");
|
|
4316
4409
|
process.exit(1);
|
|
4317
4410
|
}
|
|
4318
4411
|
if (flags.step === true) {
|
|
@@ -4359,6 +4452,9 @@ function applyRunFlags(flags, opts) {
|
|
|
4359
4452
|
if (flags.miniStepper) {
|
|
4360
4453
|
process.env.WAYGRAPH_MINI = "1";
|
|
4361
4454
|
}
|
|
4455
|
+
if (flags.todoPos === "left" || flags.todoPos === "right") {
|
|
4456
|
+
process.env.WAYGRAPH_TODO_POS = flags.todoPos;
|
|
4457
|
+
}
|
|
4362
4458
|
if (flags.ffExpand) {
|
|
4363
4459
|
process.env.WAYGRAPH_FF_EXPAND = "1";
|
|
4364
4460
|
}
|
|
@@ -4524,6 +4620,7 @@ Primary (less is more):
|
|
|
4524
4620
|
--fast Shorter auto-next / Next gates (keeps smooth cursor)
|
|
4525
4621
|
--full Classic wrap-all block chips (default: carousel)
|
|
4526
4622
|
--mini Force compact mini panel (Hide pill + Next); alias --stepper-mini
|
|
4623
|
+
--todo-left|--todo-right Floating checklist dock side (also ctx.todoPos / WAYGRAPH_TODO_POS)
|
|
4527
4624
|
--ff-expand Expand fastForwardComposeBlock inners as separate steps
|
|
4528
4625
|
--ff-disabled Dispute: expand FF (alias --no-ff); blitz kept on those inners
|
|
4529
4626
|
--auto-play-video Unattended + recorded: --auto-next + --video (+ step); headless by default
|
package/dist/highlights.d.ts
CHANGED
|
@@ -54,6 +54,11 @@ export type StubPhaseFixtures = {
|
|
|
54
54
|
zoomOut?: boolean;
|
|
55
55
|
/** Top demo banner title (the purple "waygraph demo" card). */
|
|
56
56
|
title?: string;
|
|
57
|
+
/**
|
|
58
|
+
* Floating checklist dock side. `left` | `right`.
|
|
59
|
+
* Authored control (also click / WAYGRAPH_TODO_POS / --todo-left|right).
|
|
60
|
+
*/
|
|
61
|
+
todoPos?: "left" | "right";
|
|
57
62
|
};
|
|
58
63
|
/** One named highlight slot on a block (selector + caption). */
|
|
59
64
|
export interface WaygraphHighlightStub extends FixtureDurationFields {
|
|
@@ -161,6 +166,11 @@ export type StubCtx<Out extends Checkpoint<string> = Checkpoint<string>> = {
|
|
|
161
166
|
title(text: string): void;
|
|
162
167
|
/** Alias for {@link StubCtx.title}. */
|
|
163
168
|
banner(text: string): void;
|
|
169
|
+
/**
|
|
170
|
+
* Floating checklist dock side (`left` | `right`). Authors control this in
|
|
171
|
+
* code; click / env / --todo-left|right are fallbacks.
|
|
172
|
+
*/
|
|
173
|
+
todoPos(side: "left" | "right"): void;
|
|
164
174
|
/** Batch-set rings + episode fixtures. */
|
|
165
175
|
set(partial: {
|
|
166
176
|
highlights?: HighlightStubPhase;
|
|
@@ -182,6 +192,7 @@ export type StubPhaseResult = {
|
|
|
182
192
|
zoom?: number;
|
|
183
193
|
zoomOut?: boolean;
|
|
184
194
|
title?: string;
|
|
195
|
+
todoPos?: "left" | "right";
|
|
185
196
|
};
|
|
186
197
|
/**
|
|
187
198
|
* One yap/slide in a multi-step demo caption sequence.
|
|
@@ -322,6 +333,8 @@ export type ResolvedHighlight = WaygraphHighlightStub;
|
|
|
322
333
|
* Normalize checklist rows; apply todoIndex for sequential done/current.
|
|
323
334
|
*/
|
|
324
335
|
export declare function normalizeTodos(todos: readonly WaygraphTodoInput[] | undefined, todoIndex?: number): WaygraphTodoItem[];
|
|
336
|
+
/** Normalize checklist dock side. */
|
|
337
|
+
export declare function normalizeTodoPos(raw: unknown): "left" | "right" | undefined;
|
|
325
338
|
/**
|
|
326
339
|
* Run an open stub lifecycle (preferred) or resolve a static slot map.
|
|
327
340
|
* Returns rings + episode fixtures (todos / todoIndex / zoom).
|
package/dist/highlights.js
CHANGED
|
@@ -383,6 +383,17 @@ function mergeSlot(base, patch) {
|
|
|
383
383
|
...fx,
|
|
384
384
|
};
|
|
385
385
|
}
|
|
386
|
+
/** Normalize checklist dock side. */
|
|
387
|
+
export function normalizeTodoPos(raw) {
|
|
388
|
+
const s = String(raw ?? "")
|
|
389
|
+
.trim()
|
|
390
|
+
.toLowerCase();
|
|
391
|
+
if (s === "left" || s === "l")
|
|
392
|
+
return "left";
|
|
393
|
+
if (s === "right" || s === "r")
|
|
394
|
+
return "right";
|
|
395
|
+
return undefined;
|
|
396
|
+
}
|
|
386
397
|
function createStubCtx(bag, opts) {
|
|
387
398
|
return {
|
|
388
399
|
out: opts.out,
|
|
@@ -412,6 +423,11 @@ function createStubCtx(bag, opts) {
|
|
|
412
423
|
banner(text) {
|
|
413
424
|
bag.title = String(text ?? "");
|
|
414
425
|
},
|
|
426
|
+
todoPos(side) {
|
|
427
|
+
const p = normalizeTodoPos(side);
|
|
428
|
+
if (p)
|
|
429
|
+
bag.todoPos = p;
|
|
430
|
+
},
|
|
415
431
|
set(partial) {
|
|
416
432
|
if (partial.highlights)
|
|
417
433
|
bag.highlights = { ...partial.highlights };
|
|
@@ -426,6 +442,9 @@ function createStubCtx(bag, opts) {
|
|
|
426
442
|
bag.zoomOut = !!partial.zoomOut;
|
|
427
443
|
if (partial.title !== undefined)
|
|
428
444
|
bag.title = String(partial.title ?? "");
|
|
445
|
+
const tp = normalizeTodoPos(partial.todoPos);
|
|
446
|
+
if (tp)
|
|
447
|
+
bag.todoPos = tp;
|
|
429
448
|
},
|
|
430
449
|
};
|
|
431
450
|
}
|
|
@@ -565,6 +584,7 @@ export async function runStubPhase(block, phase, opts) {
|
|
|
565
584
|
...(bag.zoom !== undefined ? { zoom: bag.zoom } : {}),
|
|
566
585
|
...(bag.zoomOut !== undefined ? { zoomOut: bag.zoomOut } : {}),
|
|
567
586
|
...(bag.title !== undefined && bag.title !== "" ? { title: bag.title } : {}),
|
|
587
|
+
...(bag.todoPos !== undefined ? { todoPos: bag.todoPos } : {}),
|
|
568
588
|
};
|
|
569
589
|
}
|
|
570
590
|
/**
|
package/dist/index.d.ts
CHANGED
|
@@ -3,7 +3,7 @@ export { connect, checkpoint } from "./types.js";
|
|
|
3
3
|
export { MemKey, MemPage, key, keyGroup } from "./mem-page.js";
|
|
4
4
|
export { Trait, urlMatches, textEquals, visible } from "./trait.js";
|
|
5
5
|
export { runGraph, spawnTab, narrate, Engine, start, end, branch, withVerify, modVerify, modVerifyAll, defineBlock, defineNavBlock, defineNavClickBlock, defineMethodBlock, defineActionBlock, definePageBlock, defineEffectBlock, defineMemEffectBlock, defineMemNavBlock, locate, composeBlock, fastForwardComposeBlock, isFastForwardBlock, preflight, withSessionReset, withTitle, withDemoPace, withBlockPace, withHighlightStyle, withExpectedFailure, withHighlightFixtures, chainFlow, } from "./engine.js";
|
|
6
|
-
export { resolveHighlightSlots, resolveSlides, runStubPhase, resolveFixtureDwellMs, resolveSlideDwellMs, formatHighlightCaption, hasAuthoredStubAfter, hasAuthoredStubOnError, normalizeHighlightTone, normalizeDemoPace, normalizeHighlightSize, normalizeHighlightWeight, applyHighlightStyleDefaults, toneIconPrefix, resolveStepDemoPace, demoPaceScale, demoPaceIsBlitz, demoPaceIsFast, demoPaceIsSlow, demoPaceGateMs, formatDemoPaceBadge, formatDemoPaceLabel, normalizeTodos, FIXTURE_DURATION_MS_DEFAULT, FIXTURE_DURATION_FAST_MS_DEFAULT, FIXTURE_DURATION_SLOW_MS_DEFAULT, SLIDE_DURATION_MS_DEFAULT, SLIDE_DURATION_FAST_MS_DEFAULT, } from "./highlights.js";
|
|
6
|
+
export { resolveHighlightSlots, resolveSlides, runStubPhase, resolveFixtureDwellMs, resolveSlideDwellMs, formatHighlightCaption, hasAuthoredStubAfter, hasAuthoredStubOnError, normalizeHighlightTone, normalizeDemoPace, normalizeHighlightSize, normalizeHighlightWeight, applyHighlightStyleDefaults, toneIconPrefix, resolveStepDemoPace, demoPaceScale, demoPaceIsBlitz, demoPaceIsFast, demoPaceIsSlow, demoPaceGateMs, formatDemoPaceBadge, formatDemoPaceLabel, normalizeTodos, normalizeTodoPos, FIXTURE_DURATION_MS_DEFAULT, FIXTURE_DURATION_FAST_MS_DEFAULT, FIXTURE_DURATION_SLOW_MS_DEFAULT, SLIDE_DURATION_MS_DEFAULT, SLIDE_DURATION_FAST_MS_DEFAULT, } from "./highlights.js";
|
|
7
7
|
export type { WaygraphHighlightStub, WaygraphHighlightFixture, WaygraphSlide, WaygraphTodoItem, WaygraphTodoInput, FixtureDurationFields, HighlightStubPhase, HighlightStubPhaseName, HighlightFixtureMap, ResolvedHighlight, WaygraphHighlight, HighlightTone, HighlightSize, HighlightWeight, HighlightStyleDefaults, DemoPace, DemoPaceName, StubCtx, StubLifecycleFn, StubPhaseResult, StubPhaseFixtures, } from "./highlights.js";
|
|
8
8
|
export type { Flow, EngineConfig, ComposedBlock, FastForwardComposedBlock, RunGraphOptions, BlockInfo, NavBlock, NavBlockOptions, NavClickBlock, NavClickBlockOptions, MethodBlock, ActionBlock, PageBlock, PageBlockOptions, PageMethodEntry, EffectBlock, MemEffectBlock, MemNavBlock, } from "./engine.js";
|
|
9
9
|
export type { ActionPage } from "./types.js";
|
package/dist/index.js
CHANGED
|
@@ -2,7 +2,7 @@ export { connect, checkpoint } from "./types.js";
|
|
|
2
2
|
export { MemKey, MemPage, key, keyGroup } from "./mem-page.js";
|
|
3
3
|
export { Trait, urlMatches, textEquals, visible } from "./trait.js";
|
|
4
4
|
export { runGraph, spawnTab, narrate, Engine, start, end, branch, withVerify, modVerify, modVerifyAll, defineBlock, defineNavBlock, defineNavClickBlock, defineMethodBlock, defineActionBlock, definePageBlock, defineEffectBlock, defineMemEffectBlock, defineMemNavBlock, locate, composeBlock, fastForwardComposeBlock, isFastForwardBlock, preflight, withSessionReset, withTitle, withDemoPace, withBlockPace, withHighlightStyle, withExpectedFailure, withHighlightFixtures, chainFlow, } from "./engine.js";
|
|
5
|
-
export { resolveHighlightSlots, resolveSlides, runStubPhase, resolveFixtureDwellMs, resolveSlideDwellMs, formatHighlightCaption, hasAuthoredStubAfter, hasAuthoredStubOnError, normalizeHighlightTone, normalizeDemoPace, normalizeHighlightSize, normalizeHighlightWeight, applyHighlightStyleDefaults, toneIconPrefix, resolveStepDemoPace, demoPaceScale, demoPaceIsBlitz, demoPaceIsFast, demoPaceIsSlow, demoPaceGateMs, formatDemoPaceBadge, formatDemoPaceLabel, normalizeTodos, FIXTURE_DURATION_MS_DEFAULT, FIXTURE_DURATION_FAST_MS_DEFAULT, FIXTURE_DURATION_SLOW_MS_DEFAULT, SLIDE_DURATION_MS_DEFAULT, SLIDE_DURATION_FAST_MS_DEFAULT, } from "./highlights.js";
|
|
5
|
+
export { resolveHighlightSlots, resolveSlides, runStubPhase, resolveFixtureDwellMs, resolveSlideDwellMs, formatHighlightCaption, hasAuthoredStubAfter, hasAuthoredStubOnError, normalizeHighlightTone, normalizeDemoPace, normalizeHighlightSize, normalizeHighlightWeight, applyHighlightStyleDefaults, toneIconPrefix, resolveStepDemoPace, demoPaceScale, demoPaceIsBlitz, demoPaceIsFast, demoPaceIsSlow, demoPaceGateMs, formatDemoPaceBadge, formatDemoPaceLabel, normalizeTodos, normalizeTodoPos, FIXTURE_DURATION_MS_DEFAULT, FIXTURE_DURATION_FAST_MS_DEFAULT, FIXTURE_DURATION_SLOW_MS_DEFAULT, SLIDE_DURATION_MS_DEFAULT, SLIDE_DURATION_FAST_MS_DEFAULT, } from "./highlights.js";
|
|
6
6
|
export { discoverGraph, toMermaid, findOrphanBlocks, findBlockPath } from "./graph.js";
|
|
7
7
|
export { isFileSelectToken, parseBlocksSelect, matchBlocksSelect, globToRegExp, } from "./blocks-select.js";
|
|
8
8
|
export { EdgeLeaseCoordinator } from "./traverse-lease.js";
|
package/dist/step-overlay.js
CHANGED
|
@@ -1,7 +1,9 @@
|
|
|
1
1
|
const RING_CSS = "#wg-ring{position:fixed;z-index:2147483646;pointer-events:none;opacity:0;" +
|
|
2
2
|
"border:2.5px solid #7C3AED;border-radius:10px;box-shadow:0 0 0 4px rgba(124,58,237,.16);" +
|
|
3
|
-
|
|
3
|
+
// Opacity only - tone color must snap (no gray/purple/yellow morph).
|
|
4
|
+
"transition:opacity .3s ease;}" +
|
|
4
5
|
// Automation = gray; semantic tones for authored highlights.
|
|
6
|
+
"#wg-ring[data-tone=planned]{border-color:#7C3AED;box-shadow:0 0 0 4px rgba(124,58,237,.16);}" +
|
|
5
7
|
"#wg-ring[data-tone=auto]{border-color:#9CA3AF;box-shadow:0 0 0 4px rgba(156,163,175,.28);}" +
|
|
6
8
|
"#wg-ring[data-tone=info]{border-color:#3B82F6;box-shadow:0 0 0 4px rgba(59,130,246,.22);}" +
|
|
7
9
|
"#wg-ring[data-tone=warning]{border-color:#EAB308;box-shadow:0 0 0 4px rgba(234,179,8,.22);}" +
|
|
@@ -9,7 +11,8 @@ const RING_CSS = "#wg-ring{position:fixed;z-index:2147483646;pointer-events:none
|
|
|
9
11
|
"#wg-ring[data-tone=success]{border-color:#22C55E;box-shadow:0 0 0 4px rgba(34,197,94,.22);}" +
|
|
10
12
|
"#wg-ring-label{position:fixed;z-index:2147483646;pointer-events:none;opacity:0;" +
|
|
11
13
|
"white-space:nowrap;padding:4px 9px;border-radius:7px;background:#7C3AED;color:#fff;" +
|
|
12
|
-
"font:600 12px/1.2 system-ui,sans-serif;transition:opacity .3s ease
|
|
14
|
+
"font:600 12px/1.2 system-ui,sans-serif;transition:opacity .3s ease;}" +
|
|
15
|
+
"#wg-ring-label[data-tone=planned]{background:#7C3AED;color:#fff;}" +
|
|
13
16
|
"#wg-ring-label[data-tone=auto]{background:#6B7280;color:#fff;}" +
|
|
14
17
|
"#wg-ring-label[data-tone=info]{background:#2563EB;color:#fff;}" +
|
|
15
18
|
"#wg-ring-label[data-tone=warning]{background:#EAB308;color:#1c1917;}" +
|