waygraph 0.12.30 → 0.12.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.
- package/dist/cli.js +239 -155
- package/dist/engine.d.ts +51 -0
- package/package.json +1 -1
package/dist/cli.js
CHANGED
|
@@ -274,12 +274,12 @@ async function findBlock(projectDir, ref) {
|
|
|
274
274
|
if (byRuntimeName.length === 1) return byRuntimeName[0];
|
|
275
275
|
if (byRuntimeName.length > 1) {
|
|
276
276
|
throw new Error(
|
|
277
|
-
"waygraph chain:
|
|
277
|
+
"waygraph chain: \\\"" + ref + "\\\" matches " + byRuntimeName.length + " Blocks by name - " +
|
|
278
278
|
byRuntimeName.map((b) => b.exportName + " (" + b.file + ")").join(", ") +
|
|
279
279
|
". Use the export name to disambiguate.",
|
|
280
280
|
);
|
|
281
281
|
}
|
|
282
|
-
throw new Error("waygraph chain: no Block named
|
|
282
|
+
throw new Error("waygraph chain: no Block named \\\"" + ref + "\\\" found under " + projectDir);
|
|
283
283
|
}
|
|
284
284
|
|
|
285
285
|
/**
|
|
@@ -316,7 +316,7 @@ function parseChainSpec(spec) {
|
|
|
316
316
|
const m = /^([A-Za-z_$][\\w-]*)\\s*(?:\\(([\\s\\S]*)\\))?$/.exec(s);
|
|
317
317
|
if (!m) {
|
|
318
318
|
throw new Error(
|
|
319
|
-
"waygraph chain: could not parse segment
|
|
319
|
+
"waygraph chain: could not parse segment \\\"" + s + "\\\" - expected \\\"blockName\\\" or \\\"blockName({...json...})\\\"",
|
|
320
320
|
);
|
|
321
321
|
}
|
|
322
322
|
const ref = m[1];
|
|
@@ -329,7 +329,7 @@ function seedMemFromRequires(mem, requires, json, label) {
|
|
|
329
329
|
if (requires.length === 0) {
|
|
330
330
|
if (json !== undefined) {
|
|
331
331
|
throw new Error(
|
|
332
|
-
"waygraph chain:
|
|
332
|
+
"waygraph chain: \\\"" + label + "\\\" takes no input (empty requires) but got a payload: " + json,
|
|
333
333
|
);
|
|
334
334
|
}
|
|
335
335
|
return;
|
|
@@ -341,7 +341,7 @@ function seedMemFromRequires(mem, requires, json, label) {
|
|
|
341
341
|
json = fromEnv;
|
|
342
342
|
} else {
|
|
343
343
|
throw new Error(
|
|
344
|
-
"waygraph chain:
|
|
344
|
+
"waygraph chain: \\\"" + label + "\\\" requires " + requires.map((k) => k.name).join(", ") +
|
|
345
345
|
" - give a JSON payload (inline blockName({...}) or --data '{...}')",
|
|
346
346
|
);
|
|
347
347
|
}
|
|
@@ -350,7 +350,7 @@ function seedMemFromRequires(mem, requires, json, label) {
|
|
|
350
350
|
try {
|
|
351
351
|
parsed = JSON.parse(json);
|
|
352
352
|
} catch (err) {
|
|
353
|
-
throw new Error("waygraph chain:
|
|
353
|
+
throw new Error("waygraph chain: \\\"" + label + "\\\" payload is not valid JSON - " + String(err));
|
|
354
354
|
}
|
|
355
355
|
// Keyed-by-name when every require name is a top-level key (preferred for
|
|
356
356
|
// --data and for {"saucedemo.credentials":{...}} even with one require).
|
|
@@ -367,13 +367,13 @@ function seedMemFromRequires(mem, requires, json, label) {
|
|
|
367
367
|
}
|
|
368
368
|
if (parsed === null || typeof parsed !== "object" || Array.isArray(parsed)) {
|
|
369
369
|
throw new Error(
|
|
370
|
-
"waygraph chain:
|
|
370
|
+
"waygraph chain: \\\"" + label + "\\\" requires " + requires.length + " keys (" +
|
|
371
371
|
requires.map((k) => k.name).join(", ") + ") - payload must be an object keyed by each key's name",
|
|
372
372
|
);
|
|
373
373
|
}
|
|
374
374
|
for (const k of requires) {
|
|
375
375
|
if (!(k.name in parsed)) {
|
|
376
|
-
throw new Error("waygraph chain:
|
|
376
|
+
throw new Error("waygraph chain: \\\"" + label + "\\\" payload is missing required key \\\"" + k.name + "\\\"");
|
|
377
377
|
}
|
|
378
378
|
mem.set(k, parsed[k.name]);
|
|
379
379
|
}
|
|
@@ -415,7 +415,7 @@ const RING_CSS =
|
|
|
415
415
|
"box-shadow:0 0 0 4px rgba(124,58,237,.16);" +
|
|
416
416
|
"transition:opacity .32s ease,left .28s ease,top .28s ease,width .28s ease,height .28s ease,border-color .15s,box-shadow .32s ease;}" +
|
|
417
417
|
// Unquoted [data-focus=1]: this lives inside CHAIN_RUNNER_SCRIPT's template
|
|
418
|
-
// literal - a
|
|
418
|
+
// literal - a \\" here would be eaten by the outer template and break the
|
|
419
419
|
// generated .mjs. CSS allows unquoted attr values for identifiers.
|
|
420
420
|
"#wg-ring[data-focus=1]{box-shadow:0 0 0 4px rgba(124,58,237,.2),0 0 0 9999px rgba(15,6,32,.55);}" +
|
|
421
421
|
"#wg-ring[data-tone=auto][data-focus=1]{box-shadow:0 0 0 4px rgba(156,163,175,.28),0 0 0 9999px rgba(15,6,32,.55);}" +
|
|
@@ -527,6 +527,24 @@ const RING_CSS =
|
|
|
527
527
|
"#wg-todos .wg-todo-done{color:#6ee7b7;text-decoration:line-through;opacity:.85;}" +
|
|
528
528
|
"#wg-todos .wg-todo-current{color:#fff;}" +
|
|
529
529
|
"#wg-todos .wg-todo-pending{color:#9a7ad1;}" +
|
|
530
|
+
"#wg-todo-modal{position:fixed;z-index:2147483647;left:14px;bottom:14px;min-width:240px;max-width:min(360px,92vw);" +
|
|
531
|
+
"padding:14px 16px 12px;background:rgba(18,8,36,.94);color:#f0e8ff;" +
|
|
532
|
+
"border:1px solid rgba(124,58,237,.55);border-radius:12px;" +
|
|
533
|
+
"box-shadow:0 12px 40px rgba(0,0,0,.45);backdrop-filter:blur(8px);" +
|
|
534
|
+
"opacity:0;transform:translateY(8px);pointer-events:none;" +
|
|
535
|
+
"transition:opacity .28s ease,transform .28s ease;}" +
|
|
536
|
+
"#wg-todo-modal.wg-todo-on{opacity:1;transform:none;pointer-events:auto;}" +
|
|
537
|
+
"#wg-todo-modal .wg-todo-head{font:700 11px/1.2 system-ui,sans-serif;color:#c9a6ff;" +
|
|
538
|
+
"letter-spacing:.04em;text-transform:uppercase;margin:0 0 10px;}" +
|
|
539
|
+
"#wg-todo-modal ul{list-style:none;margin:0;padding:0;}" +
|
|
540
|
+
"#wg-todo-modal li{display:flex;gap:10px;align-items:flex-start;margin:0 0 8px;" +
|
|
541
|
+
"font:600 14px/1.4 system-ui,sans-serif;}" +
|
|
542
|
+
"#wg-todo-modal li:last-child{margin-bottom:0;}" +
|
|
543
|
+
"#wg-todo-modal .wg-todo-mark{flex:0 0 auto;width:1.2em;text-align:center;font-size:15px;}" +
|
|
544
|
+
"#wg-todo-modal .wg-todo-done{color:#6ee7b7;text-decoration:line-through;opacity:.8;}" +
|
|
545
|
+
"#wg-todo-modal .wg-todo-current{color:#fff;}" +
|
|
546
|
+
"#wg-todo-modal .wg-todo-current .wg-todo-mark{color:#c9a6ff;}" +
|
|
547
|
+
"#wg-todo-modal .wg-todo-pending{color:#9a7ad1;}" +
|
|
530
548
|
"#wg-progress{height:4px;background:#2a1650;border-radius:2px;margin:0 0 12px;overflow:hidden;}" +
|
|
531
549
|
"#wg-progress-bar{height:100%;background:#7C3AED;border-radius:2px;transition:width .3s ease;}" +
|
|
532
550
|
// A real tab bar for episodes - the currently-active episode reads as
|
|
@@ -707,11 +725,6 @@ async function installOverlay(page, title) {
|
|
|
707
725
|
cursor.style.transform = "translate(" + x + "px," + y + "px)";
|
|
708
726
|
}
|
|
709
727
|
cursor.style.opacity = "1";
|
|
710
|
-
// Screen Studio: pan the zoomed camera with the cursor.
|
|
711
|
-
const cam = window.__wgCamera;
|
|
712
|
-
if (cam && cam.scale > 1.001 && window.__wgSetCamera) {
|
|
713
|
-
window.__wgSetCamera(x, y, cam.scale, instant ? 0 : travel);
|
|
714
|
-
}
|
|
715
728
|
};
|
|
716
729
|
window.__wgHideCursor = () => {
|
|
717
730
|
const cursor = document.getElementById("wg-cursor");
|
|
@@ -801,12 +814,14 @@ async function installOverlay(page, title) {
|
|
|
801
814
|
};
|
|
802
815
|
// Screen Studio-style camera: scale <body>, keep overlays on <html> fixed.
|
|
803
816
|
window.__wgCamera = { scale: 1, cx: 0, cy: 0 };
|
|
804
|
-
window.__wgSetCamera = (
|
|
817
|
+
window.__wgSetCamera = (fx, fy, scale, ms) => {
|
|
805
818
|
const body = document.body;
|
|
806
819
|
if (!body) return;
|
|
807
820
|
const s = Math.max(1, Math.min(Number(scale) || 1, 2.75));
|
|
808
|
-
|
|
809
|
-
const
|
|
821
|
+
const vw = window.innerWidth;
|
|
822
|
+
const vh = window.innerHeight;
|
|
823
|
+
window.__wgCamera = { scale: s, cx: fx, cy: fy };
|
|
824
|
+
const dur = ms != null && Number(ms) >= 0 ? Number(ms) : 650;
|
|
810
825
|
body.style.transition =
|
|
811
826
|
dur <= 0
|
|
812
827
|
? "none"
|
|
@@ -816,10 +831,57 @@ async function installOverlay(page, title) {
|
|
|
816
831
|
body.style.transform = "";
|
|
817
832
|
return;
|
|
818
833
|
}
|
|
834
|
+
// One transform: scale AND bring focus to viewport center.
|
|
819
835
|
body.style.transform =
|
|
820
|
-
"translate(" +
|
|
836
|
+
"translate(" + vw / 2 + "px," + vh / 2 + "px) scale(" + s + ") translate(" + -fx + "px," + -fy + "px)";
|
|
821
837
|
};
|
|
822
|
-
window.
|
|
838
|
+
window.__wgSetTodos = (todos) => {
|
|
839
|
+
let modal = document.getElementById("wg-todo-modal");
|
|
840
|
+
if (!todos || !todos.length) {
|
|
841
|
+
if (modal) {
|
|
842
|
+
modal.classList.remove("wg-todo-on");
|
|
843
|
+
modal.innerHTML = "";
|
|
844
|
+
}
|
|
845
|
+
return;
|
|
846
|
+
}
|
|
847
|
+
if (!modal) {
|
|
848
|
+
modal = document.createElement("div");
|
|
849
|
+
modal.id = "wg-todo-modal";
|
|
850
|
+
document.documentElement.appendChild(modal);
|
|
851
|
+
}
|
|
852
|
+
const esc = (s) =>
|
|
853
|
+
String(s)
|
|
854
|
+
.replace(/&/g, "&")
|
|
855
|
+
.replace(/</g, "<")
|
|
856
|
+
.replace(/>/g, ">");
|
|
857
|
+
const rows = todos
|
|
858
|
+
.map((t) => {
|
|
859
|
+
const cls = t.current
|
|
860
|
+
? "wg-todo-current"
|
|
861
|
+
: t.done
|
|
862
|
+
? "wg-todo-done"
|
|
863
|
+
: "wg-todo-pending";
|
|
864
|
+
const mark = t.done
|
|
865
|
+
? String.fromCharCode(0x2713)
|
|
866
|
+
: t.current
|
|
867
|
+
? String.fromCharCode(0x2192)
|
|
868
|
+
: String.fromCharCode(0x25cb);
|
|
869
|
+
return (
|
|
870
|
+
'<li class="' +
|
|
871
|
+
cls +
|
|
872
|
+
'"><span class="wg-todo-mark">' +
|
|
873
|
+
mark +
|
|
874
|
+
'</span><span>' +
|
|
875
|
+
esc(t.text || "") +
|
|
876
|
+
'</span></li>'
|
|
877
|
+
);
|
|
878
|
+
})
|
|
879
|
+
.join("");
|
|
880
|
+
modal.innerHTML =
|
|
881
|
+
'<div class="wg-todo-head">Checklist</div><ul>' + rows + '</ul>';
|
|
882
|
+
modal.classList.add("wg-todo-on");
|
|
883
|
+
};
|
|
884
|
+
window.__wgResetCamera = () => {
|
|
823
885
|
window.__wgSetCamera(window.innerWidth / 2, window.innerHeight / 2, 1);
|
|
824
886
|
};
|
|
825
887
|
window.__wgClearZoom = () => {
|
|
@@ -1008,7 +1070,7 @@ async function renderBeforeStep(page, info) {
|
|
|
1008
1070
|
// active, the episode 2 tab is inactive"). Absent entirely for an ad
|
|
1009
1071
|
// hoc block chain with no named Flows.
|
|
1010
1072
|
const episodesHtml = info.allEpisodes && info.allEpisodes.length > 0
|
|
1011
|
-
? "<div id
|
|
1073
|
+
? "<div id=\\\"wg-episodes\\\">" +
|
|
1012
1074
|
info.allEpisodes
|
|
1013
1075
|
.map((e) => {
|
|
1014
1076
|
const cls = e.episodeNumber < info.episodeNumber ? "wg-ep-done"
|
|
@@ -1019,7 +1081,7 @@ async function renderBeforeStep(page, info) {
|
|
|
1019
1081
|
const enteredCls = info.justEnteredEpisode && e.episodeNumber === info.episodeNumber
|
|
1020
1082
|
? " wg-ep-entered"
|
|
1021
1083
|
: "";
|
|
1022
|
-
return "<span class
|
|
1084
|
+
return "<span class=\\\"wg-ep-tab " + cls + enteredCls + "\\\">Episode " + e.episodeNumber + ": " +
|
|
1023
1085
|
esc(e.episodeTitle || "") + "</span>";
|
|
1024
1086
|
})
|
|
1025
1087
|
.join("") +
|
|
@@ -1035,40 +1097,66 @@ async function renderBeforeStep(page, info) {
|
|
|
1035
1097
|
.map((name, idx) => {
|
|
1036
1098
|
const cls = idx < info.moduleIndex ? "wg-mod-done" : idx === info.moduleIndex ? "wg-mod-current" : "wg-mod-upcoming";
|
|
1037
1099
|
const desc = info.allDescriptions && info.allDescriptions[idx];
|
|
1038
|
-
const titleAttr = desc ? " title
|
|
1039
|
-
return "<span class
|
|
1100
|
+
const titleAttr = desc ? " title=\\\"" + esc(desc) + "\\\"" : "";
|
|
1101
|
+
return "<span class=\\\"wg-mod " + cls + "\\\"" + titleAttr + ">" + name + "</span>";
|
|
1040
1102
|
})
|
|
1041
1103
|
.join("");
|
|
1042
1104
|
const narrationHtml = info.description
|
|
1043
|
-
? "<div class
|
|
1105
|
+
? "<div class=\\\"wg-narration\\\">" + esc(info.description) + "</div>"
|
|
1044
1106
|
: "";
|
|
1045
1107
|
const paceHtml =
|
|
1046
1108
|
info.paceBadge || info.paceLabel
|
|
1047
|
-
? "<div class
|
|
1109
|
+
? "<div class=\\\"wg-pace\\\" data-pace-kind=\\\"" +
|
|
1048
1110
|
esc(info.paceKind || "normal") +
|
|
1049
|
-
"
|
|
1111
|
+
"\\\"><span class=\\\"wg-pace-badge\\\">" +
|
|
1050
1112
|
esc(info.paceBadge || "1x") +
|
|
1051
1113
|
"</span><span>" +
|
|
1052
1114
|
esc(info.paceLabel || "") +
|
|
1053
1115
|
"</span></div>"
|
|
1054
1116
|
: "";
|
|
1055
1117
|
let html =
|
|
1056
|
-
"<div id
|
|
1118
|
+
"<div id=\\\"wg-progress\\\"><div id=\\\"wg-progress-bar\\\" style=\\\"width:" + pct + "%\\\"></div></div>" +
|
|
1057
1119
|
episodesHtml +
|
|
1058
1120
|
paceHtml +
|
|
1059
|
-
"<div id
|
|
1121
|
+
"<div id=\\\"wg-modules\\\" class=\\\"" + modulesClass + "\\\">" + modulesHtml + "</div>" +
|
|
1060
1122
|
"<h3>Step " + (info.index + 1) + " / " + info.total + " - " + info.blockName + "</h3>" +
|
|
1061
1123
|
narrationHtml +
|
|
1062
|
-
|
|
1124
|
+
((() => {
|
|
1125
|
+
const list = info.todos || [];
|
|
1126
|
+
if (!list.length) return "";
|
|
1127
|
+
return (
|
|
1128
|
+
'<ul id="wg-todos">' +
|
|
1129
|
+
list
|
|
1130
|
+
.map((t) => {
|
|
1131
|
+
const cls = t.current ? "wg-todo-current" : t.done ? "wg-todo-done" : "wg-todo-pending";
|
|
1132
|
+
const mark = t.done
|
|
1133
|
+
? String.fromCharCode(0x2713)
|
|
1134
|
+
: t.current
|
|
1135
|
+
? String.fromCharCode(0x2192)
|
|
1136
|
+
: String.fromCharCode(0x25cb);
|
|
1137
|
+
return (
|
|
1138
|
+
'<li class="' +
|
|
1139
|
+
cls +
|
|
1140
|
+
'"><span class="wg-todo-mark">' +
|
|
1141
|
+
mark +
|
|
1142
|
+
'</span><span>' +
|
|
1143
|
+
esc(t.text || "") +
|
|
1144
|
+
'</span></li>'
|
|
1145
|
+
);
|
|
1146
|
+
})
|
|
1147
|
+
.join("") +
|
|
1148
|
+
'</ul>'
|
|
1149
|
+
);
|
|
1150
|
+
})());
|
|
1063
1151
|
if (info.keys.length === 0) {
|
|
1064
|
-
html += "<div class
|
|
1152
|
+
html += "<div class=\\\"wg-key\\\">(no MemKeys required)</div>";
|
|
1065
1153
|
}
|
|
1066
1154
|
for (const k of info.keys) {
|
|
1067
1155
|
html +=
|
|
1068
|
-
"<div class
|
|
1069
|
-
"<textarea data-key
|
|
1156
|
+
"<div class=\\\"wg-key\\\"><label>" + k.name + "</label>" +
|
|
1157
|
+
"<textarea data-key=\\\"" + k.name + "\\\" rows=\\\"2\\\">" +
|
|
1070
1158
|
k.value.replace(/</g, "<") + "</textarea>" +
|
|
1071
|
-
"<div class
|
|
1159
|
+
"<div class=\\\"wg-key-pretty\\\" data-pretty-for=\\\"" + esc(k.name) + "\\\"></div>" +
|
|
1072
1160
|
"</div>";
|
|
1073
1161
|
}
|
|
1074
1162
|
let autoNow = false;
|
|
@@ -1078,12 +1166,12 @@ async function renderBeforeStep(page, info) {
|
|
|
1078
1166
|
/* private mode / blocked storage - defaults to manual */
|
|
1079
1167
|
}
|
|
1080
1168
|
html +=
|
|
1081
|
-
"<div class
|
|
1169
|
+
"<div class=\\\"wg-autoplay-row\\\"><label><input type=\\\"checkbox\\\" id=\\\"wg-autoplay-cb\\\"" +
|
|
1082
1170
|
(autoNow ? " checked" : "") +
|
|
1083
1171
|
"> Auto-advance</label></div>" +
|
|
1084
|
-
"<div id
|
|
1085
|
-
"><button id
|
|
1086
|
-
"<div id
|
|
1172
|
+
"<div id=\\\"wg-gate-manual\\\"" + (autoNow ? " style=\\\"display:none\\\"" : "") +
|
|
1173
|
+
"><button id=\\\"wg-run\\\">Run this step \\u25B6</button></div>" +
|
|
1174
|
+
"<div id=\\\"wg-gate-auto\\\" class=\\\"wg-auto\\\"" + (autoNow ? "" : " style=\\\"display:none\\\"") +
|
|
1087
1175
|
">Auto-advancing...</div>";
|
|
1088
1176
|
panel.innerHTML = html;
|
|
1089
1177
|
if (isNewPanel) {
|
|
@@ -1116,7 +1204,7 @@ async function renderBeforeStep(page, info) {
|
|
|
1116
1204
|
return Object.entries(parsed)
|
|
1117
1205
|
.map(([field, value]) => {
|
|
1118
1206
|
const label = field.replace(/([a-z0-9])([A-Z])/g, "$1 $2").replace(/^./, (c) => c.toUpperCase());
|
|
1119
|
-
return "<div class
|
|
1207
|
+
return "<div class=\\\"wg-key-pretty-row\\\"><span class=\\\"wg-key-pretty-label\\\">" +
|
|
1120
1208
|
esc(label) + ":</span> " + esc(String(value)) + "</div>";
|
|
1121
1209
|
})
|
|
1122
1210
|
.join("");
|
|
@@ -1125,7 +1213,7 @@ async function renderBeforeStep(page, info) {
|
|
|
1125
1213
|
const prettyOn = window.__wgPretty !== false;
|
|
1126
1214
|
panel.querySelectorAll("textarea[data-key]").forEach((ta) => {
|
|
1127
1215
|
const key = ta.getAttribute("data-key");
|
|
1128
|
-
const previewEl = panel.querySelector(".wg-key-pretty[data-pretty-for
|
|
1216
|
+
const previewEl = panel.querySelector(".wg-key-pretty[data-pretty-for=\\\"" + key + "\\\"]");
|
|
1129
1217
|
if (!previewEl) return;
|
|
1130
1218
|
previewEl.style.display = prettyOn ? "" : "none";
|
|
1131
1219
|
if (prettyOn) previewEl.innerHTML = prettyMemValue(ta.value);
|
|
@@ -1237,9 +1325,9 @@ async function ensureSelectorInView(page, selector) {
|
|
|
1237
1325
|
}
|
|
1238
1326
|
}
|
|
1239
1327
|
|
|
1240
|
-
async function applyCameraZoom(page, box, zoom) {
|
|
1328
|
+
async function applyCameraZoom(page, box, zoom, ms) {
|
|
1241
1329
|
const z = zoom != null && Number(zoom) > 1 ? Number(zoom) : 1;
|
|
1242
|
-
if (!box) {
|
|
1330
|
+
if (!box || z <= 1) {
|
|
1243
1331
|
await page.evaluate(() => {
|
|
1244
1332
|
if (window.__wgResetCamera) window.__wgResetCamera();
|
|
1245
1333
|
}).catch(() => {});
|
|
@@ -1247,10 +1335,19 @@ async function applyCameraZoom(page, box, zoom) {
|
|
|
1247
1335
|
}
|
|
1248
1336
|
const cx = box.x + box.width / 2;
|
|
1249
1337
|
const cy = box.y + box.height / 2;
|
|
1338
|
+
const dur = ms != null ? ms : 650;
|
|
1250
1339
|
await page
|
|
1251
|
-
.evaluate(({ cx, cy, scale }) => {
|
|
1252
|
-
if (window.__wgSetCamera) window.__wgSetCamera(cx, cy, scale);
|
|
1253
|
-
}, { cx, cy, scale: z })
|
|
1340
|
+
.evaluate(({ cx, cy, scale, dur }) => {
|
|
1341
|
+
if (window.__wgSetCamera) window.__wgSetCamera(cx, cy, scale, dur);
|
|
1342
|
+
}, { cx, cy, scale: z, dur })
|
|
1343
|
+
.catch(() => {});
|
|
1344
|
+
}
|
|
1345
|
+
|
|
1346
|
+
async function setDemoTodos(page, todos) {
|
|
1347
|
+
await page
|
|
1348
|
+
.evaluate((list) => {
|
|
1349
|
+
if (window.__wgSetTodos) window.__wgSetTodos(list || []);
|
|
1350
|
+
}, todos && todos.length ? todos : [])
|
|
1254
1351
|
.catch(() => {});
|
|
1255
1352
|
}
|
|
1256
1353
|
|
|
@@ -1355,15 +1452,27 @@ async function cycleHighlightRings(page, highlights, gatesFast, opts) {
|
|
|
1355
1452
|
const box = await page.locator(h.selector).first().boundingBox();
|
|
1356
1453
|
if (!box) continue;
|
|
1357
1454
|
await updateHlProgress(i);
|
|
1358
|
-
|
|
1359
|
-
|
|
1360
|
-
|
|
1361
|
-
|
|
1362
|
-
|
|
1455
|
+
if (opts && opts.todos && opts.todos.length) {
|
|
1456
|
+
const rows = opts.todos.map((t, ti) => ({
|
|
1457
|
+
text: t.text,
|
|
1458
|
+
done: ti < i,
|
|
1459
|
+
current: ti === i,
|
|
1460
|
+
}));
|
|
1461
|
+
await setDemoTodos(page, rows);
|
|
1462
|
+
} else if (h.todos && h.todos.length) {
|
|
1463
|
+
await setDemoTodos(page, normalizeTodos(h.todos, h.todoIndex));
|
|
1464
|
+
}
|
|
1465
|
+
const cx = box.x + box.width / 2;
|
|
1466
|
+
const cy = box.y + box.height / 2;
|
|
1467
|
+
const z = h.zoom != null && Number(h.zoom) > 1 ? Number(h.zoom) : 1;
|
|
1468
|
+
const camMs = 700;
|
|
1469
|
+
// One-shot camera: zoom + center together (no zoom-then-align).
|
|
1470
|
+
await applyCameraZoom(page, box, z, camMs);
|
|
1471
|
+
if (h.cursor !== false) {
|
|
1363
1472
|
await page
|
|
1364
|
-
.evaluate(({ cx, cy }) => {
|
|
1365
|
-
if (window.__wgMoveCursorTo) window.__wgMoveCursorTo(cx, cy,
|
|
1366
|
-
}, { cx, cy })
|
|
1473
|
+
.evaluate(({ cx, cy, camMs }) => {
|
|
1474
|
+
if (window.__wgMoveCursorTo) window.__wgMoveCursorTo(cx, cy, camMs, false);
|
|
1475
|
+
}, { cx, cy, camMs })
|
|
1367
1476
|
.catch(() => {});
|
|
1368
1477
|
}
|
|
1369
1478
|
await showRing(page, box, h.label, h.tone || "planned", {
|
|
@@ -1372,9 +1481,10 @@ async function cycleHighlightRings(page, highlights, gatesFast, opts) {
|
|
|
1372
1481
|
focus: !!h.focus,
|
|
1373
1482
|
color: h.color || h.labelColor || h.textColor,
|
|
1374
1483
|
});
|
|
1375
|
-
|
|
1484
|
+
await new Promise((res) => setTimeout(res, camMs));
|
|
1485
|
+
// Live ring track only - camera stays locked (no per-frame re-pan).
|
|
1376
1486
|
await page
|
|
1377
|
-
.evaluate(({ sel, label, tone, size, weight, focus, color
|
|
1487
|
+
.evaluate(({ sel, label, tone, size, weight, focus, color }) => {
|
|
1378
1488
|
const tick = () => {
|
|
1379
1489
|
const el = document.querySelector(sel);
|
|
1380
1490
|
if (!el) {
|
|
@@ -1386,26 +1496,10 @@ async function cycleHighlightRings(page, highlights, gatesFast, opts) {
|
|
|
1386
1496
|
if (window.__wgPositionRing) {
|
|
1387
1497
|
window.__wgPositionRing(box, label, tone || "planned", { size, weight, focus, color });
|
|
1388
1498
|
}
|
|
1389
|
-
if (zoom && zoom > 1 && window.__wgSetCamera) {
|
|
1390
|
-
// Prefer cursor tip when visible (Screen Studio follow-mouse);
|
|
1391
|
-
// else keep the ring target centered.
|
|
1392
|
-
let cx = box.x + box.width / 2;
|
|
1393
|
-
let cy = box.y + box.height / 2;
|
|
1394
|
-
const cur = document.getElementById("wg-cursor");
|
|
1395
|
-
if (cur && cur.style.opacity !== "0") {
|
|
1396
|
-
const m = /translate\(([-\d.]+)px,\s*([-\d.]+)px\)/.exec(cur.style.transform || "");
|
|
1397
|
-
if (m) {
|
|
1398
|
-
cx = Number(m[1]);
|
|
1399
|
-
cy = Number(m[2]);
|
|
1400
|
-
}
|
|
1401
|
-
}
|
|
1402
|
-
window.__wgSetCamera(cx, cy, zoom, 0);
|
|
1403
|
-
}
|
|
1404
1499
|
window.__wgRingRaf = requestAnimationFrame(tick);
|
|
1405
1500
|
};
|
|
1406
1501
|
window.__wgRingRaf = requestAnimationFrame(tick);
|
|
1407
|
-
|
|
1408
|
-
window.__wgRingTrack = onScroll;
|
|
1502
|
+
window.__wgRingTrack = () => {};
|
|
1409
1503
|
}, {
|
|
1410
1504
|
sel: h.selector,
|
|
1411
1505
|
label: h.label,
|
|
@@ -1414,47 +1508,9 @@ async function cycleHighlightRings(page, highlights, gatesFast, opts) {
|
|
|
1414
1508
|
weight: h.weight || "normal",
|
|
1415
1509
|
focus: !!h.focus,
|
|
1416
1510
|
color: h.color || h.labelColor || h.textColor || "",
|
|
1417
|
-
zoom: h.zoom != null && h.zoom > 1 ? h.zoom : 0,
|
|
1418
1511
|
})
|
|
1419
1512
|
.catch(() => {});
|
|
1420
1513
|
|
|
1421
|
-
if ((opts && opts.todos && opts.todos.length) || (h.todos && h.todos.length)) {
|
|
1422
|
-
const rows =
|
|
1423
|
-
opts && opts.todos && opts.todos.length
|
|
1424
|
-
? opts.todos
|
|
1425
|
-
: normalizeTodos(h.todos, h.todoIndex);
|
|
1426
|
-
await page
|
|
1427
|
-
.evaluate((todos) => {
|
|
1428
|
-
const ul = document.getElementById("wg-todos");
|
|
1429
|
-
if (!ul) return;
|
|
1430
|
-
ul.innerHTML = todos
|
|
1431
|
-
.map((t) => {
|
|
1432
|
-
const cls = t.current
|
|
1433
|
-
? "wg-todo-current"
|
|
1434
|
-
: t.done
|
|
1435
|
-
? "wg-todo-done"
|
|
1436
|
-
: "wg-todo-pending";
|
|
1437
|
-
const mark = t.done ? "\\u2713" : t.current ? "\\u2192" : "\\u25CB";
|
|
1438
|
-
const esc = (s) =>
|
|
1439
|
-
String(s)
|
|
1440
|
-
.replace(/&/g, "&")
|
|
1441
|
-
.replace(/</g, "<")
|
|
1442
|
-
.replace(/>/g, ">");
|
|
1443
|
-
return (
|
|
1444
|
-
"<li class=\\"" +
|
|
1445
|
-
cls +
|
|
1446
|
-
"\\"><span class=\\"wg-todo-mark\\">" +
|
|
1447
|
-
mark +
|
|
1448
|
-
"</span><span>" +
|
|
1449
|
-
esc(t.text || "") +
|
|
1450
|
-
"</span></li>"
|
|
1451
|
-
);
|
|
1452
|
-
})
|
|
1453
|
-
.join("");
|
|
1454
|
-
}, rows)
|
|
1455
|
-
.catch(() => {});
|
|
1456
|
-
}
|
|
1457
|
-
|
|
1458
1514
|
// Appear settle
|
|
1459
1515
|
await new Promise((res) => setTimeout(res, fadeMs));
|
|
1460
1516
|
const authored = resolveFixtureDwellMs(h, { gatesFast, pace });
|
|
@@ -1522,8 +1578,8 @@ async function renderAfterStep(page, info) {
|
|
|
1522
1578
|
.map((name, idx) => {
|
|
1523
1579
|
const cls = idx <= info.moduleIndex ? "wg-mod-done" : "wg-mod-upcoming";
|
|
1524
1580
|
const desc = info.allDescriptions && info.allDescriptions[idx];
|
|
1525
|
-
const titleAttr = desc ? " title
|
|
1526
|
-
return "<span class
|
|
1581
|
+
const titleAttr = desc ? " title=\\\"" + escA(desc) + "\\\"" : "";
|
|
1582
|
+
return "<span class=\\\"wg-mod " + cls + "\\\"" + titleAttr + ">" + name + "</span>";
|
|
1527
1583
|
})
|
|
1528
1584
|
.join("");
|
|
1529
1585
|
// QA-friendly by default ("LoginSuccess" -> "Login Success") - raw
|
|
@@ -1534,13 +1590,13 @@ async function renderAfterStep(page, info) {
|
|
|
1534
1590
|
.replace(/([A-Z]+)([A-Z][a-z])/g, "$1 $2") || info.resultTag;
|
|
1535
1591
|
const pretty = window.__wgPretty !== false;
|
|
1536
1592
|
const resultHtml =
|
|
1537
|
-
"<div class
|
|
1538
|
-
"<button class
|
|
1539
|
-
"<button class
|
|
1593
|
+
"<div class=\\\"wg-toggle\\\">" +
|
|
1594
|
+
"<button class=\\\"wg-toggle-btn" + (pretty ? " wg-active" : "") + "\\\" data-mode=\\\"pretty\\\">Pretty</button>" +
|
|
1595
|
+
"<button class=\\\"wg-toggle-btn" + (pretty ? "" : " wg-active") + "\\\" data-mode=\\\"json\\\">JSON</button>" +
|
|
1540
1596
|
"</div>" +
|
|
1541
|
-
"<div class
|
|
1597
|
+
"<div class=\\\"wg-result wg-result-pretty\\\" style=\\\"display:" + (pretty ? "block" : "none") + "\\\">" +
|
|
1542
1598
|
prettyText + "</div>" +
|
|
1543
|
-
"<div class
|
|
1599
|
+
"<div class=\\\"wg-result wg-result-json\\\" style=\\\"display:" + (pretty ? "none" : "block") + "\\\">" +
|
|
1544
1600
|
info.resultTag + "</div>";
|
|
1545
1601
|
let autoNow = false;
|
|
1546
1602
|
try {
|
|
@@ -1549,21 +1605,21 @@ async function renderAfterStep(page, info) {
|
|
|
1549
1605
|
/* private mode / blocked storage - defaults to manual */
|
|
1550
1606
|
}
|
|
1551
1607
|
const gateHtml =
|
|
1552
|
-
"<div class
|
|
1608
|
+
"<div class=\\\"wg-autoplay-row\\\"><label><input type=\\\"checkbox\\\" id=\\\"wg-autoplay-cb\\\"" +
|
|
1553
1609
|
(autoNow ? " checked" : "") +
|
|
1554
1610
|
"> Auto-advance</label></div>" +
|
|
1555
|
-
"<div id
|
|
1556
|
-
"><button id
|
|
1557
|
-
"<div id
|
|
1611
|
+
"<div id=\\\"wg-gate-manual\\\"" + (autoNow ? " style=\\\"display:none\\\"" : "") +
|
|
1612
|
+
"><button id=\\\"wg-run\\\">" + buttonLabel + "</button></div>" +
|
|
1613
|
+
"<div id=\\\"wg-gate-auto\\\" class=\\\"wg-auto\\\"" + (autoNow ? "" : " style=\\\"display:none\\\"") +
|
|
1558
1614
|
">Auto-advancing...</div>";
|
|
1559
1615
|
const episodesHtml = info.allEpisodes && info.allEpisodes.length > 0
|
|
1560
|
-
? "<div id
|
|
1616
|
+
? "<div id=\\\"wg-episodes\\\">" +
|
|
1561
1617
|
info.allEpisodes
|
|
1562
1618
|
.map((e) => {
|
|
1563
1619
|
const cls = e.episodeNumber < info.episodeNumber ? "wg-ep-done"
|
|
1564
1620
|
: e.episodeNumber === info.episodeNumber ? "wg-ep-current"
|
|
1565
1621
|
: "wg-ep-upcoming";
|
|
1566
|
-
return "<span class
|
|
1622
|
+
return "<span class=\\\"wg-ep-tab " + cls + "\\\">Episode " + e.episodeNumber + ": " +
|
|
1567
1623
|
escA(e.episodeTitle || "") + "</span>";
|
|
1568
1624
|
})
|
|
1569
1625
|
.join("") +
|
|
@@ -1571,21 +1627,47 @@ async function renderAfterStep(page, info) {
|
|
|
1571
1627
|
: "";
|
|
1572
1628
|
const paceHtml =
|
|
1573
1629
|
info.paceBadge || info.paceLabel
|
|
1574
|
-
? "<div class
|
|
1630
|
+
? "<div class=\\\"wg-pace\\\" data-pace-kind=\\\"" +
|
|
1575
1631
|
escA(info.paceKind || "normal") +
|
|
1576
|
-
"
|
|
1632
|
+
"\\\"><span class=\\\"wg-pace-badge\\\">" +
|
|
1577
1633
|
escA(info.paceBadge || "1x") +
|
|
1578
1634
|
"</span><span>" +
|
|
1579
1635
|
escA(info.paceLabel || "") +
|
|
1580
1636
|
"</span></div>"
|
|
1581
1637
|
: "";
|
|
1582
1638
|
panel.innerHTML =
|
|
1583
|
-
"<div id
|
|
1639
|
+
"<div id=\\\"wg-progress\\\"><div id=\\\"wg-progress-bar\\\" style=\\\"width:" + pct + "%\\\"></div></div>" +
|
|
1584
1640
|
episodesHtml +
|
|
1585
1641
|
paceHtml +
|
|
1586
|
-
"<div id
|
|
1642
|
+
"<div id=\\\"wg-modules\\\" class=\\\"" + modulesClass + "\\\">" + modulesHtml + "</div>" +
|
|
1587
1643
|
"<h3>" + heading + "</h3>" +
|
|
1588
|
-
|
|
1644
|
+
((() => {
|
|
1645
|
+
const list = info.todos || [];
|
|
1646
|
+
if (!list.length) return "";
|
|
1647
|
+
return (
|
|
1648
|
+
'<ul id="wg-todos">' +
|
|
1649
|
+
list
|
|
1650
|
+
.map((t) => {
|
|
1651
|
+
const cls = t.current ? "wg-todo-current" : t.done ? "wg-todo-done" : "wg-todo-pending";
|
|
1652
|
+
const mark = t.done
|
|
1653
|
+
? String.fromCharCode(0x2713)
|
|
1654
|
+
: t.current
|
|
1655
|
+
? String.fromCharCode(0x2192)
|
|
1656
|
+
: String.fromCharCode(0x25cb);
|
|
1657
|
+
return (
|
|
1658
|
+
'<li class="' +
|
|
1659
|
+
cls +
|
|
1660
|
+
'"><span class="wg-todo-mark">' +
|
|
1661
|
+
mark +
|
|
1662
|
+
'</span><span>' +
|
|
1663
|
+
escA(t.text || "") +
|
|
1664
|
+
'</span></li>'
|
|
1665
|
+
);
|
|
1666
|
+
})
|
|
1667
|
+
.join("") +
|
|
1668
|
+
'</ul>'
|
|
1669
|
+
);
|
|
1670
|
+
})()) +
|
|
1589
1671
|
resultHtml +
|
|
1590
1672
|
gateHtml;
|
|
1591
1673
|
if (isNewPanel) {
|
|
@@ -1652,13 +1734,13 @@ async function renderStepError(page, info) {
|
|
|
1652
1734
|
if (!isNewPanel) panel.classList.add("wg-in");
|
|
1653
1735
|
const esc = (s) => String(s).replace(/&/g, "&").replace(/"/g, """).replace(/</g, "<");
|
|
1654
1736
|
const episodesHtml = info.allEpisodes && info.allEpisodes.length > 0
|
|
1655
|
-
? "<div id
|
|
1737
|
+
? "<div id=\\\"wg-episodes\\\">" +
|
|
1656
1738
|
info.allEpisodes
|
|
1657
1739
|
.map((e) => {
|
|
1658
1740
|
const cls = e.episodeNumber < info.episodeNumber ? "wg-ep-done"
|
|
1659
1741
|
: e.episodeNumber === info.episodeNumber ? "wg-ep-current"
|
|
1660
1742
|
: "wg-ep-upcoming";
|
|
1661
|
-
return "<span class
|
|
1743
|
+
return "<span class=\\\"wg-ep-tab " + cls + "\\\">Episode " + e.episodeNumber + ": " +
|
|
1662
1744
|
esc(e.episodeTitle || "") + "</span>";
|
|
1663
1745
|
})
|
|
1664
1746
|
.join("") +
|
|
@@ -1669,8 +1751,8 @@ async function renderStepError(page, info) {
|
|
|
1669
1751
|
.map((name, idx) => {
|
|
1670
1752
|
const cls = idx === info.moduleIndex ? "wg-mod-current" : idx < info.moduleIndex ? "wg-mod-done" : "wg-mod-upcoming";
|
|
1671
1753
|
const desc = info.allDescriptions && info.allDescriptions[idx];
|
|
1672
|
-
const titleAttr = desc ? " title
|
|
1673
|
-
return "<span class
|
|
1754
|
+
const titleAttr = desc ? " title=\\\"" + esc(desc) + "\\\"" : "";
|
|
1755
|
+
return "<span class=\\\"wg-mod " + cls + "\\\"" + titleAttr + ">" + name + "</span>";
|
|
1674
1756
|
})
|
|
1675
1757
|
.join("");
|
|
1676
1758
|
const retryLabel = info.episodeNumber !== undefined ? "Retry Episode " + info.episodeNumber : "Retry";
|
|
@@ -1678,17 +1760,17 @@ async function renderStepError(page, info) {
|
|
|
1678
1760
|
? "Expected outcome - Step " + (info.index + 1) + " / " + info.total + " - " + info.blockName + " failed as intended"
|
|
1679
1761
|
: "Step " + (info.index + 1) + " / " + info.total + " - " + info.blockName + " threw";
|
|
1680
1762
|
const reasonHtml = isExpected
|
|
1681
|
-
? "<div class
|
|
1763
|
+
? "<div class=\\\"wg-expected-reason\\\">" + esc(info.expectedFailureReason) + "</div>"
|
|
1682
1764
|
: "";
|
|
1683
1765
|
panel.innerHTML =
|
|
1684
1766
|
episodesHtml +
|
|
1685
|
-
"<div id
|
|
1686
|
-
"<h3 class
|
|
1767
|
+
"<div id=\\\"wg-modules\\\" class=\\\"" + modulesClass + "\\\">" + modulesHtml + "</div>" +
|
|
1768
|
+
"<h3 class=\\\"" + (isExpected ? "wg-expected-heading" : "wg-error-heading") + "\\\">" + headingText + "</h3>" +
|
|
1687
1769
|
reasonHtml +
|
|
1688
|
-
"<div class
|
|
1689
|
-
"<div class
|
|
1690
|
-
"<button id
|
|
1691
|
-
"<button id
|
|
1770
|
+
"<div class=\\\"wg-error-msg\\\">" + esc(info.message) + "</div>" +
|
|
1771
|
+
"<div class=\\\"wg-error-actions\\\">" +
|
|
1772
|
+
"<button id=\\\"wg-error-retry\\\" class=\\\"wg-error-retry\\\">" + esc(retryLabel) + "</button>" +
|
|
1773
|
+
"<button id=\\\"wg-run\\\" class=\\\"wg-error-stop\\\">Stop</button>" +
|
|
1692
1774
|
"</div>";
|
|
1693
1775
|
if (isNewPanel) {
|
|
1694
1776
|
document.documentElement.appendChild(panel);
|
|
@@ -1952,25 +2034,25 @@ async function presentSlides(page, slides, _gate, opts) {
|
|
|
1952
2034
|
String(t).replace(/&/g, "&").replace(/</g, "<").replace(/"/g, """);
|
|
1953
2035
|
const episodeLine =
|
|
1954
2036
|
info.episodeNumber !== undefined && info.episodeNumber !== null
|
|
1955
|
-
? "<div class
|
|
2037
|
+
? "<div class=\\\"wg-episode\\\">Episode " +
|
|
1956
2038
|
info.episodeNumber +
|
|
1957
2039
|
(info.episodeTitle ? ": " + esc(info.episodeTitle) : "") +
|
|
1958
2040
|
" · yap slides</div>"
|
|
1959
2041
|
: "";
|
|
1960
2042
|
const paceHtml =
|
|
1961
2043
|
info.paceBadge || info.paceLabel
|
|
1962
|
-
? "<div class
|
|
2044
|
+
? "<div class=\\\"wg-pace\\\" data-pace-kind=\\\"" +
|
|
1963
2045
|
esc(info.paceKind || "normal") +
|
|
1964
|
-
"
|
|
2046
|
+
"\\\"><span class=\\\"wg-pace-badge\\\">" +
|
|
1965
2047
|
esc(info.paceBadge || "1x") +
|
|
1966
2048
|
"</span><span>" +
|
|
1967
2049
|
esc(info.paceLabel || "") +
|
|
1968
2050
|
"</span></div>"
|
|
1969
2051
|
: "";
|
|
1970
2052
|
panel.innerHTML =
|
|
1971
|
-
"<div class
|
|
1972
|
-
"<button type
|
|
1973
|
-
"<div class
|
|
2053
|
+
"<div class=\\\"wg-chrome\\\"><span class=\\\"wg-chrome-title\\\">waygraph demo</span>" +
|
|
2054
|
+
"<button type=\\\"button\\\" class=\\\"wg-hide-btn\\\" data-wg-toggle=\\\"1\\\">Hide</button></div>" +
|
|
2055
|
+
"<div class=\\\"wg-body\\\">" +
|
|
1974
2056
|
episodeLine +
|
|
1975
2057
|
paceHtml +
|
|
1976
2058
|
"<h3>Slide " +
|
|
@@ -1980,35 +2062,35 @@ async function presentSlides(page, slides, _gate, opts) {
|
|
|
1980
2062
|
(info.blockName ? " · " + esc(info.blockName) : "") +
|
|
1981
2063
|
"</h3>" +
|
|
1982
2064
|
(info.tag
|
|
1983
|
-
? "<div style
|
|
2065
|
+
? "<div style=\\\"border:none;padding:0;margin:0 0 6px;font-size:11px;color:#c9a6ff\\\">" +
|
|
1984
2066
|
esc(info.tag) +
|
|
1985
2067
|
"</div>"
|
|
1986
2068
|
: "") +
|
|
1987
|
-
"<div class
|
|
2069
|
+
"<div class=\\\"wg-narration\\\">" +
|
|
1988
2070
|
esc(info.caption) +
|
|
1989
2071
|
"</div>" +
|
|
1990
2072
|
(info.detail
|
|
1991
|
-
? "<div class
|
|
2073
|
+
? "<div class=\\\"wg-result-pretty\\\" style=\\\"margin:0 0 12px;color:#f0e8ff\\\">" +
|
|
1992
2074
|
esc(info.detail) +
|
|
1993
2075
|
"</div>"
|
|
1994
2076
|
: "") +
|
|
1995
2077
|
(info.dwellMs != null
|
|
1996
|
-
? "<div class
|
|
2078
|
+
? "<div class=\\\"wg-auto\\\" id=\\\"wg-dwell-hint\\\" style=\\\"margin:0 0 8px\\\">Hold " +
|
|
1997
2079
|
(info.dwellMs / 1000).toFixed(1) +
|
|
1998
2080
|
"s before next...</div>"
|
|
1999
2081
|
: "") +
|
|
2000
|
-
"<div class
|
|
2082
|
+
"<div class=\\\"wg-autoplay-row\\\"><label><input type=\\\"checkbox\\\" id=\\\"wg-autoplay-cb\\\"" +
|
|
2001
2083
|
(info.autoNow ? " checked" : "") +
|
|
2002
2084
|
"> Auto-advance</label></div>" +
|
|
2003
|
-
"<div id
|
|
2004
|
-
(info.autoNow ? " style
|
|
2005
|
-
"><button type
|
|
2085
|
+
"<div id=\\\"wg-gate-manual\\\"" +
|
|
2086
|
+
(info.autoNow ? " style=\\\"display:none\\\"" : "") +
|
|
2087
|
+
"><button type=\\\"button\\\" id=\\\"wg-run\\\"" +
|
|
2006
2088
|
(info.dwellMs != null ? " disabled" : "") +
|
|
2007
2089
|
">" +
|
|
2008
2090
|
(info.isLast ? "Continue \\u25B6" : "Next slide \\u25B6") +
|
|
2009
2091
|
"</button></div>" +
|
|
2010
|
-
"<div id
|
|
2011
|
-
(info.autoNow ? "" : " style
|
|
2092
|
+
"<div id=\\\"wg-gate-auto\\\" class=\\\"wg-auto\\\"" +
|
|
2093
|
+
(info.autoNow ? "" : " style=\\\"display:none\\\"") +
|
|
2012
2094
|
">Auto-advancing...</div>" +
|
|
2013
2095
|
"</div>";
|
|
2014
2096
|
if (isNew) {
|
|
@@ -2173,7 +2255,7 @@ async function teardownOverlay(page) {
|
|
|
2173
2255
|
window.__wgRingTrack = null;
|
|
2174
2256
|
}
|
|
2175
2257
|
window.__wgNarrateOwnsRing = false;
|
|
2176
|
-
for (const id of ["wg-panel", "wg-ring", "wg-ring-label", "wg-cursor", "wg-click-pulse", "wg-banner"]) {
|
|
2258
|
+
for (const id of ["wg-panel", "wg-ring", "wg-ring-label", "wg-cursor", "wg-click-pulse", "wg-banner", "wg-todo-modal"]) {
|
|
2177
2259
|
const el = document.getElementById(id);
|
|
2178
2260
|
if (el) el.remove();
|
|
2179
2261
|
}
|
|
@@ -2747,6 +2829,7 @@ async function runStepMode(engine, start, end, context, page, mem, resolved, slo
|
|
|
2747
2829
|
todos: stubBeforeTodos,
|
|
2748
2830
|
...paceSpeak,
|
|
2749
2831
|
});
|
|
2832
|
+
await setDemoTodos(page, stubBeforeTodos);
|
|
2750
2833
|
const edits = await gate();
|
|
2751
2834
|
for (const k of requires) {
|
|
2752
2835
|
if (edits[k.name] !== undefined) {
|
|
@@ -2934,6 +3017,7 @@ async function runStepMode(engine, start, end, context, page, mem, resolved, slo
|
|
|
2934
3017
|
});
|
|
2935
3018
|
stubAfterTodos = afterPhase.todos || [];
|
|
2936
3019
|
await setDemoBannerTitle(page, afterPhase.title);
|
|
3020
|
+
await setDemoTodos(page, afterPhase.todos || []);
|
|
2937
3021
|
highlights = afterPhase.highlights.map((h) => {
|
|
2938
3022
|
const styled = applyHighlightStyleDefaults(h, r.highlightStyle);
|
|
2939
3023
|
return {
|
package/dist/engine.d.ts
CHANGED
|
@@ -544,6 +544,57 @@ export declare class Engine {
|
|
|
544
544
|
Block<K, L>,
|
|
545
545
|
EndMarker
|
|
546
546
|
]): Flow<L>;
|
|
547
|
+
defineFlow<B extends Checkpoint<string>, C extends Checkpoint<string>, D extends Checkpoint<string>, E extends Checkpoint<string>, F extends Checkpoint<string>, G extends Checkpoint<string>, H extends Checkpoint<string>, I extends Checkpoint<string>, J extends Checkpoint<string>, K extends Checkpoint<string>, L extends Checkpoint<string>, M extends Checkpoint<string>>(blocks: readonly [
|
|
548
|
+
StartMarker,
|
|
549
|
+
Block<S, B>,
|
|
550
|
+
Block<B, C>,
|
|
551
|
+
Block<C, D>,
|
|
552
|
+
Block<D, E>,
|
|
553
|
+
Block<E, F>,
|
|
554
|
+
Block<F, G>,
|
|
555
|
+
Block<G, H>,
|
|
556
|
+
Block<H, I>,
|
|
557
|
+
Block<I, J>,
|
|
558
|
+
Block<J, K>,
|
|
559
|
+
Block<K, L>,
|
|
560
|
+
Block<L, M>,
|
|
561
|
+
EndMarker
|
|
562
|
+
]): Flow<M>;
|
|
563
|
+
defineFlow<B extends Checkpoint<string>, C extends Checkpoint<string>, D extends Checkpoint<string>, E extends Checkpoint<string>, F extends Checkpoint<string>, G extends Checkpoint<string>, H extends Checkpoint<string>, I extends Checkpoint<string>, J extends Checkpoint<string>, K extends Checkpoint<string>, L extends Checkpoint<string>, M extends Checkpoint<string>, N extends Checkpoint<string>>(blocks: readonly [
|
|
564
|
+
StartMarker,
|
|
565
|
+
Block<S, B>,
|
|
566
|
+
Block<B, C>,
|
|
567
|
+
Block<C, D>,
|
|
568
|
+
Block<D, E>,
|
|
569
|
+
Block<E, F>,
|
|
570
|
+
Block<F, G>,
|
|
571
|
+
Block<G, H>,
|
|
572
|
+
Block<H, I>,
|
|
573
|
+
Block<I, J>,
|
|
574
|
+
Block<J, K>,
|
|
575
|
+
Block<K, L>,
|
|
576
|
+
Block<L, M>,
|
|
577
|
+
Block<M, N>,
|
|
578
|
+
EndMarker
|
|
579
|
+
]): Flow<N>;
|
|
580
|
+
defineFlow<B extends Checkpoint<string>, C extends Checkpoint<string>, D extends Checkpoint<string>, E extends Checkpoint<string>, F extends Checkpoint<string>, G extends Checkpoint<string>, H extends Checkpoint<string>, I extends Checkpoint<string>, J extends Checkpoint<string>, K extends Checkpoint<string>, L extends Checkpoint<string>, M extends Checkpoint<string>, N extends Checkpoint<string>, O extends Checkpoint<string>>(blocks: readonly [
|
|
581
|
+
StartMarker,
|
|
582
|
+
Block<S, B>,
|
|
583
|
+
Block<B, C>,
|
|
584
|
+
Block<C, D>,
|
|
585
|
+
Block<D, E>,
|
|
586
|
+
Block<E, F>,
|
|
587
|
+
Block<F, G>,
|
|
588
|
+
Block<G, H>,
|
|
589
|
+
Block<H, I>,
|
|
590
|
+
Block<I, J>,
|
|
591
|
+
Block<J, K>,
|
|
592
|
+
Block<K, L>,
|
|
593
|
+
Block<L, M>,
|
|
594
|
+
Block<M, N>,
|
|
595
|
+
Block<N, O>,
|
|
596
|
+
EndMarker
|
|
597
|
+
]): Flow<O>;
|
|
547
598
|
}
|
|
548
599
|
/**
|
|
549
600
|
* Attaches routing to `block` without touching its act/observe/resolve/verify -
|