waygraph 0.15.21 → 0.15.23
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/auto-explore-run.d.ts +2 -1
- package/dist/auto-explore-run.js +2 -1
- package/dist/auto-session.js +2 -1
- package/dist/cli.js +21 -6067
- package/dist/runner/chain-run.js +102 -0
- package/dist/runner/cursor.js +140 -0
- package/dist/runner/demo-log.js +314 -0
- package/dist/runner/device-stage.js +400 -0
- package/dist/runner/discovery.js +105 -0
- package/dist/runner/index.js +2 -0
- package/dist/runner/interaction-patch.js +353 -0
- package/dist/runner/main.js +397 -0
- package/dist/runner/overlay-css.js +342 -0
- package/dist/runner/overlay-install.js +1301 -0
- package/dist/runner/rings.js +490 -0
- package/dist/runner/seed-mem.js +110 -0
- package/dist/runner/slides.js +272 -0
- package/dist/runner/step-mode.js +776 -0
- package/dist/runner/step-panels.js +723 -0
- package/dist/runner/teardown.js +195 -0
- package/dist/runner/todo-dock.js +142 -0
- package/examples/saucedemo/.waygraph-auto/19b9eee5.log +0 -0
- package/examples/saucedemo/.waygraph-auto/422d4390.log +0 -0
- package/examples/saucedemo/.waygraph-auto/6c9f8e10.log +0 -0
- package/examples/saucedemo/.waygraph-auto/74ce745a.log +0 -0
- package/examples/saucedemo/.waygraph-auto/89477e92.log +0 -0
- package/examples/saucedemo/.waygraph-auto/b7e545f0.log +0 -0
- package/examples/saucedemo/.waygraph-auto/cb2726d7.log +0 -0
- package/package.json +8 -4
|
@@ -0,0 +1,272 @@
|
|
|
1
|
+
// Moved verbatim from the former CHAIN_RUNNER_SCRIPT template string in cli.ts (see src/ARCHITECTURE.md).
|
|
2
|
+
// Runs inside the target project's own waygraph copy - keep it dependency-light and self-contained.
|
|
3
|
+
import { demoPaceGateMs, formatDemoPaceBadge, formatDemoPaceLabel, formatHighlightCaption, normalizeDemoPace, normalizeHighlightSize, normalizeHighlightTone, normalizeHighlightWeight, resolveFixtureDwellMs } from "../highlights.js";
|
|
4
|
+
import { installOverlay } from "./overlay-install.js";
|
|
5
|
+
import { applyHighlightZoom, ensureSelectorInView, hideRing, showRing } from "./rings.js";
|
|
6
|
+
import { demoPaceKind } from "./demo-log.js";
|
|
7
|
+
|
|
8
|
+
/**
|
|
9
|
+
* Multi-step yap captions - not block lifecycle. Each slide waits for Next
|
|
10
|
+
* (or auto-next), optional ring via slide.selector.
|
|
11
|
+
*
|
|
12
|
+
* Advance wait does NOT use exposeFunction/gate(): after a real navigation
|
|
13
|
+
* (e.g. finish-order -> checkout-complete) the panel can render while
|
|
14
|
+
* __wgNext is momentarily wedged, which left "Next slide" looking live but
|
|
15
|
+
* doing nothing. In-page data-wg-acked + autoplay poll is the source of truth.
|
|
16
|
+
*/
|
|
17
|
+
export async function presentSlides(page, slides, _gate, opts) {
|
|
18
|
+
const title = (opts && opts.title) || "waygraph demo";
|
|
19
|
+
const blockName = (opts && opts.blockName) || "";
|
|
20
|
+
const episodeNumber = opts && opts.episodeNumber;
|
|
21
|
+
const episodeTitle = (opts && opts.episodeTitle) || "";
|
|
22
|
+
const gatesFast = !!(opts && opts.fast);
|
|
23
|
+
const demoPace = normalizeDemoPace((opts && opts.pace) || (gatesFast ? "fast" : "normal"));
|
|
24
|
+
const baseAutoplay =
|
|
25
|
+
opts && opts.autoplayMs
|
|
26
|
+
? Number(opts.autoplayMs)
|
|
27
|
+
: process.env.WAYGRAPH_AUTOPLAY_MS
|
|
28
|
+
? Number(process.env.WAYGRAPH_AUTOPLAY_MS)
|
|
29
|
+
: 1800;
|
|
30
|
+
const autoplayMs = demoPaceGateMs(demoPace, baseAutoplay);
|
|
31
|
+
for (let i = 0; i < slides.length; i++) {
|
|
32
|
+
const s = slides[i];
|
|
33
|
+
const caption = formatHighlightCaption(s);
|
|
34
|
+
const slideTone = normalizeHighlightTone(s.tone);
|
|
35
|
+
const slideStyle = {
|
|
36
|
+
size: normalizeHighlightSize(s.size),
|
|
37
|
+
weight: normalizeHighlightWeight(s.weight),
|
|
38
|
+
};
|
|
39
|
+
const isLast = i === slides.length - 1;
|
|
40
|
+
const dwellMs = resolveFixtureDwellMs(s, { gatesFast, pace: demoPace });
|
|
41
|
+
await installOverlay(page, title);
|
|
42
|
+
if (s.selector) {
|
|
43
|
+
try {
|
|
44
|
+
await ensureSelectorInView(page, s.selector);
|
|
45
|
+
await applyHighlightZoom(page, s.selector, s.zoom, s.zoomOut);
|
|
46
|
+
const box = await page
|
|
47
|
+
.evaluate((sel) => {
|
|
48
|
+
const el = document.querySelector(sel);
|
|
49
|
+
if (!el) return null;
|
|
50
|
+
const r = el.getBoundingClientRect();
|
|
51
|
+
return { x: r.x, y: r.y, width: r.width, height: r.height };
|
|
52
|
+
}, s.selector)
|
|
53
|
+
.catch(() => null);
|
|
54
|
+
if (box && box.width > 0 && box.height > 0) {
|
|
55
|
+
await showRing(page, box, caption, slideTone, {
|
|
56
|
+
...slideStyle,
|
|
57
|
+
selector: s.selector,
|
|
58
|
+
focus: !!s.focus,
|
|
59
|
+
});
|
|
60
|
+
}
|
|
61
|
+
} catch {
|
|
62
|
+
await hideRing(page);
|
|
63
|
+
}
|
|
64
|
+
} else {
|
|
65
|
+
await hideRing(page);
|
|
66
|
+
}
|
|
67
|
+
await page.evaluate(
|
|
68
|
+
(info) => {
|
|
69
|
+
let panel = document.getElementById("wg-panel");
|
|
70
|
+
const isNew = !panel;
|
|
71
|
+
if (!panel) {
|
|
72
|
+
panel = document.createElement("div");
|
|
73
|
+
panel.id = "wg-panel";
|
|
74
|
+
}
|
|
75
|
+
panel.classList.remove("wg-error", "wg-expected");
|
|
76
|
+
// Do not clear wg-collapsed - WirePanelChrome honors Hide (localStorage)
|
|
77
|
+
// unless forceCollapsed:true (--mini / --video).
|
|
78
|
+
const esc = (t) =>
|
|
79
|
+
String(t).replace(/&/g, "&").replace(/</g, "<").replace(/"/g, """);
|
|
80
|
+
const episodeLine =
|
|
81
|
+
info.episodeNumber !== undefined && info.episodeNumber !== null
|
|
82
|
+
? "<div class=\"wg-episode\">Episode " +
|
|
83
|
+
info.episodeNumber +
|
|
84
|
+
(info.episodeTitle ? ": " + esc(info.episodeTitle) : "") +
|
|
85
|
+
" · yap slides</div>"
|
|
86
|
+
: "";
|
|
87
|
+
const paceHtml =
|
|
88
|
+
info.paceBadge || info.paceLabel
|
|
89
|
+
? "<div class=\"wg-pace\" data-pace-kind=\"" +
|
|
90
|
+
esc(info.paceKind || "normal") +
|
|
91
|
+
"\"><span class=\"wg-pace-badge\">" +
|
|
92
|
+
esc(info.paceBadge || "1x") +
|
|
93
|
+
"</span><span>" +
|
|
94
|
+
esc(info.paceLabel || "") +
|
|
95
|
+
"</span></div>"
|
|
96
|
+
: "";
|
|
97
|
+
panel.innerHTML =
|
|
98
|
+
"<div class=\"wg-chrome\"><span class=\"wg-chrome-title\">waygraph demo</span>" +
|
|
99
|
+
"<button type=\"button\" class=\"wg-hide-btn\" data-wg-toggle=\"1\">Hide</button></div>" +
|
|
100
|
+
"<div class=\"wg-body\">" +
|
|
101
|
+
episodeLine +
|
|
102
|
+
paceHtml +
|
|
103
|
+
"<h3>Slide " +
|
|
104
|
+
(info.index + 1) +
|
|
105
|
+
" / " +
|
|
106
|
+
info.total +
|
|
107
|
+
(info.blockName ? " · " + esc(info.blockName) : "") +
|
|
108
|
+
"</h3>" +
|
|
109
|
+
(info.tag
|
|
110
|
+
? "<div style=\"border:none;padding:0;margin:0 0 6px;font-size:11px;color:#c9a6ff\">" +
|
|
111
|
+
esc(info.tag) +
|
|
112
|
+
"</div>"
|
|
113
|
+
: "") +
|
|
114
|
+
"<div class=\"wg-narration\">" +
|
|
115
|
+
esc(info.caption) +
|
|
116
|
+
"</div>" +
|
|
117
|
+
(info.detail
|
|
118
|
+
? "<div class=\"wg-result-pretty\" style=\"margin:0 0 12px;color:#f0e8ff\">" +
|
|
119
|
+
esc(info.detail) +
|
|
120
|
+
"</div>"
|
|
121
|
+
: "") +
|
|
122
|
+
(info.dwellMs != null
|
|
123
|
+
? "<div class=\"wg-auto\" id=\"wg-dwell-hint\" style=\"margin:0 0 8px\">Hold " +
|
|
124
|
+
(info.dwellMs / 1000).toFixed(1) +
|
|
125
|
+
"s before next...</div>"
|
|
126
|
+
: "") +
|
|
127
|
+
"<div class=\"wg-autoplay-row\"><label><input type=\"checkbox\" id=\"wg-autoplay-cb\"" +
|
|
128
|
+
(info.autoNow ? " checked" : "") +
|
|
129
|
+
"> Auto-advance</label></div>" +
|
|
130
|
+
"<div id=\"wg-gate-manual\"" +
|
|
131
|
+
(info.autoNow ? " style=\"display:none\"" : "") +
|
|
132
|
+
"><button type=\"button\" id=\"wg-run\"" +
|
|
133
|
+
(info.dwellMs != null ? " disabled" : "") +
|
|
134
|
+
">" +
|
|
135
|
+
(info.isLast ? "Continue \u25B6" : "Next slide \u25B6") +
|
|
136
|
+
"</button></div>" +
|
|
137
|
+
"<div id=\"wg-gate-auto\" class=\"wg-auto\"" +
|
|
138
|
+
(info.autoNow ? "" : " style=\"display:none\"") +
|
|
139
|
+
">Auto-advancing...</div>" +
|
|
140
|
+
"</div>";
|
|
141
|
+
if (isNew) {
|
|
142
|
+
document.documentElement.appendChild(panel);
|
|
143
|
+
requestAnimationFrame(() => panel.classList.add("wg-in"));
|
|
144
|
+
}
|
|
145
|
+
if (window.__wgWirePanelChrome) {
|
|
146
|
+
window.__wgWirePanelChrome(panel, "wg-panel-hidden", "waygraph demo", {
|
|
147
|
+
stepLabel:
|
|
148
|
+
(info.episodeNumber !== undefined && info.episodeNumber !== null
|
|
149
|
+
? "Ep " + info.episodeNumber + " \u00b7 "
|
|
150
|
+
: "") +
|
|
151
|
+
"Slide " +
|
|
152
|
+
(info.index + 1) +
|
|
153
|
+
" / " +
|
|
154
|
+
info.total +
|
|
155
|
+
(info.blockName ? " \u00b7 " + info.blockName : ""),
|
|
156
|
+
// Video / --mini: compact pill. Else omit so Hide sticks.
|
|
157
|
+
forceCollapsed: info.forceCollapsed === true ? true : undefined,
|
|
158
|
+
});
|
|
159
|
+
}
|
|
160
|
+
if (window.__wgStampModal) {
|
|
161
|
+
window.__wgStampModal(panel, "panel", {
|
|
162
|
+
phase: "slide",
|
|
163
|
+
step: info.index + 1,
|
|
164
|
+
total: info.total,
|
|
165
|
+
block: info.blockName || "",
|
|
166
|
+
ready: true,
|
|
167
|
+
});
|
|
168
|
+
}
|
|
169
|
+
let autoNow = false;
|
|
170
|
+
try {
|
|
171
|
+
autoNow = localStorage.getItem("wg-autoplay") === "1";
|
|
172
|
+
} catch {
|
|
173
|
+
/* ignore */
|
|
174
|
+
}
|
|
175
|
+
const cb = document.getElementById("wg-autoplay-cb");
|
|
176
|
+
if (cb) {
|
|
177
|
+
cb.checked = autoNow;
|
|
178
|
+
cb.addEventListener("change", () => {
|
|
179
|
+
try {
|
|
180
|
+
localStorage.setItem("wg-autoplay", cb.checked ? "1" : "0");
|
|
181
|
+
} catch {
|
|
182
|
+
/* ignore */
|
|
183
|
+
}
|
|
184
|
+
const manual = document.getElementById("wg-gate-manual");
|
|
185
|
+
const auto = document.getElementById("wg-gate-auto");
|
|
186
|
+
if (manual) manual.style.display = cb.checked ? "none" : "";
|
|
187
|
+
if (auto) auto.style.display = cb.checked ? "" : "none";
|
|
188
|
+
});
|
|
189
|
+
}
|
|
190
|
+
const manual = document.getElementById("wg-gate-manual");
|
|
191
|
+
const auto = document.getElementById("wg-gate-auto");
|
|
192
|
+
if (manual) manual.style.display = autoNow ? "none" : "";
|
|
193
|
+
if (auto) auto.style.display = autoNow ? "" : "none";
|
|
194
|
+
const runBtn = document.getElementById("wg-run");
|
|
195
|
+
if (runBtn) {
|
|
196
|
+
runBtn.removeAttribute("data-wg-acked");
|
|
197
|
+
runBtn.addEventListener("click", (e) => {
|
|
198
|
+
e.preventDefault();
|
|
199
|
+
e.stopPropagation();
|
|
200
|
+
if (runBtn.disabled) return;
|
|
201
|
+
runBtn.setAttribute("data-wg-acked", "1");
|
|
202
|
+
});
|
|
203
|
+
}
|
|
204
|
+
if (info.dwellMs != null && info.dwellMs > 0) {
|
|
205
|
+
const unlockAt = Date.now() + info.dwellMs;
|
|
206
|
+
const tick = () => {
|
|
207
|
+
const left = Math.max(0, unlockAt - Date.now());
|
|
208
|
+
const hint = document.getElementById("wg-dwell-hint");
|
|
209
|
+
const btn = document.getElementById("wg-run");
|
|
210
|
+
if (left <= 0) {
|
|
211
|
+
if (hint) hint.remove();
|
|
212
|
+
if (btn) btn.disabled = false;
|
|
213
|
+
return;
|
|
214
|
+
}
|
|
215
|
+
if (hint) hint.textContent = "Hold " + (left / 1000).toFixed(1) + "s before next...";
|
|
216
|
+
setTimeout(tick, 100);
|
|
217
|
+
};
|
|
218
|
+
setTimeout(tick, 100);
|
|
219
|
+
}
|
|
220
|
+
},
|
|
221
|
+
{
|
|
222
|
+
index: i,
|
|
223
|
+
total: slides.length,
|
|
224
|
+
caption: s.caption,
|
|
225
|
+
detail: s.detail || "",
|
|
226
|
+
tag: s.tag || "",
|
|
227
|
+
blockName,
|
|
228
|
+
isLast,
|
|
229
|
+
autoNow: false,
|
|
230
|
+
dwellMs,
|
|
231
|
+
episodeNumber: episodeNumber !== undefined ? episodeNumber : null,
|
|
232
|
+
episodeTitle,
|
|
233
|
+
paceBadge: formatDemoPaceBadge(demoPace, baseAutoplay),
|
|
234
|
+
paceLabel: formatDemoPaceLabel(demoPace, baseAutoplay),
|
|
235
|
+
paceKind: demoPaceKind(demoPace),
|
|
236
|
+
forceCollapsed:
|
|
237
|
+
!!process.env.WAYGRAPH_VIDEO ||
|
|
238
|
+
process.env.WAYGRAPH_MINI === "1" ||
|
|
239
|
+
process.env.WAYGRAPH_STEPPER_MINI === "1"
|
|
240
|
+
? true
|
|
241
|
+
: undefined,
|
|
242
|
+
},
|
|
243
|
+
);
|
|
244
|
+
const started = Date.now();
|
|
245
|
+
// When duration is set: floor both manual Next and auto-next to dwellMs.
|
|
246
|
+
// When unset: legacy - auto uses autoplayMs, manual Next is immediate.
|
|
247
|
+
const autoWaitMs = dwellMs != null ? dwellMs : autoplayMs;
|
|
248
|
+
for (;;) {
|
|
249
|
+
const acked = await page
|
|
250
|
+
.evaluate(() => {
|
|
251
|
+
const btn = document.getElementById("wg-run");
|
|
252
|
+
return !!(btn && btn.getAttribute("data-wg-acked") === "1");
|
|
253
|
+
})
|
|
254
|
+
.catch(() => false);
|
|
255
|
+
if (acked) {
|
|
256
|
+
if (dwellMs == null || Date.now() - started >= dwellMs) break;
|
|
257
|
+
}
|
|
258
|
+
const auto = await page
|
|
259
|
+
.evaluate(() => {
|
|
260
|
+
try {
|
|
261
|
+
return localStorage.getItem("wg-autoplay") === "1";
|
|
262
|
+
} catch {
|
|
263
|
+
return false;
|
|
264
|
+
}
|
|
265
|
+
})
|
|
266
|
+
.catch(() => false);
|
|
267
|
+
if (auto && Date.now() - started >= autoWaitMs) break;
|
|
268
|
+
await new Promise((res) => setTimeout(res, 100));
|
|
269
|
+
}
|
|
270
|
+
}
|
|
271
|
+
await hideRing(page);
|
|
272
|
+
}
|