waygraph 0.16.0 → 0.16.2
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/commands/browser.d.ts +2 -0
- package/dist/cli/commands/browser.js +109 -0
- package/dist/cli/commands/codemod-stubs.js +90 -2
- package/dist/cli/commands/pilot.d.ts +2 -0
- package/dist/cli/commands/pilot.js +102 -0
- package/dist/cli/commands/session-ops.d.ts +3 -0
- package/dist/cli/commands/session-ops.js +257 -0
- package/dist/cli/commands/session.js +20 -461
- package/dist/cli/run-chain.js +2 -2
- package/dist/cli/usage.d.ts +1 -1
- package/dist/cli/util.js +1 -1
- package/dist/demo/narration/demo-pace.d.ts +2 -2
- package/dist/demo/narration/demo-pace.js +1 -1
- package/dist/demo/narration/device.d.ts +2 -2
- package/dist/demo/narration/merge.d.ts +5 -3
- package/dist/demo/narration/merge.js +3 -7
- package/dist/demo/narration/narration.d.ts +9 -13
- package/dist/demo/narration/narration.js +5 -17
- package/dist/demo/narration/stub-ctx.js +3 -3
- package/dist/demo/narration/todo-dock.d.ts +5 -5
- package/dist/demo/overlay/cursor.d.ts +9 -2
- package/dist/demo/overlay/cursor.js +1 -1
- package/dist/demo/overlay/device-stage.d.ts +15 -2
- package/dist/demo/overlay/inpage/banner.d.ts +2 -1
- package/dist/demo/overlay/inpage/banner.js +3 -3
- package/dist/demo/overlay/inpage/caption.d.ts +1 -1
- package/dist/demo/overlay/inpage/core.d.ts +2 -1
- package/dist/demo/overlay/inpage/core.js +1 -7
- package/dist/demo/overlay/inpage/device-chip.d.ts +1 -1
- package/dist/demo/overlay/inpage/device-chip.js +6 -6
- package/dist/demo/overlay/inpage/network.d.ts +3 -2
- package/dist/demo/overlay/inpage/network.js +1 -12
- package/dist/demo/overlay/inpage/panel-chrome.d.ts +1 -1
- package/dist/demo/overlay/inpage/panel-chrome.js +1 -1
- package/dist/demo/overlay/inpage/stamp.d.ts +1 -1
- package/dist/demo/overlay/inpage/stamp.js +1 -1
- package/dist/demo/overlay/inpage/swipe-zoom.d.ts +1 -1
- package/dist/demo/overlay/inpage/swipe-zoom.js +1 -1
- package/dist/demo/overlay/inpage/todos.d.ts +2 -1
- package/dist/demo/overlay/inpage/todos.js +1 -2
- package/dist/demo/overlay/network-capture.d.ts +2 -2
- package/dist/demo/overlay/network-capture.js +1 -1
- package/dist/demo/overlay/overlay-css.js +1 -55
- package/dist/demo/overlay/overlay-stage.d.ts +19 -11
- package/dist/demo/overlay/overlay.d.ts +2 -2
- package/dist/demo/overlay/overlay.js +3 -2
- package/dist/demo/overlay/rings.d.ts +38 -18
- package/dist/demo/overlay/rings.js +21 -62
- package/dist/demo/overlay/ui/overlay.css +40 -0
- package/dist/demo/stepper/after.js +11 -34
- package/dist/demo/stepper/banner-log.d.ts +4 -6
- package/dist/demo/stepper/banner-log.js +3 -1
- package/dist/demo/stepper/before.js +6 -4
- package/dist/demo/stepper/demo-log.d.ts +26 -9
- package/dist/demo/stepper/demo-log.js +10 -27
- package/dist/demo/stepper/interaction-patch.d.ts +3 -2
- package/dist/demo/stepper/interaction-patch.js +22 -34
- package/dist/demo/stepper/panel-after.d.ts +17 -0
- package/dist/demo/stepper/panel-after.js +166 -0
- package/dist/demo/stepper/panel-before.d.ts +12 -0
- package/dist/demo/stepper/panel-before.js +241 -0
- package/dist/demo/stepper/slides.d.ts +16 -1
- package/dist/demo/stepper/slides.js +21 -5
- package/dist/demo/stepper/step-panels.d.ts +57 -9
- package/dist/demo/stepper/step-panels.js +10 -427
- package/dist/demo/stepper/stepper.js +1 -1
- package/dist/demo/stepper/teardown.d.ts +4 -5
- package/dist/demo/stepper/teardown.js +4 -6
- package/dist/demo/stepper/todo-advance.d.ts +3 -2
- package/dist/demo/stepper/todo-advance.js +2 -2
- package/dist/demo/stepper/view.d.ts +4 -14
- package/dist/demo/types.d.ts +69 -1
- package/dist/demo/verbose-log.js +1 -1
- package/dist/engine/block/action-page.d.ts +53 -0
- package/dist/engine/block/action-page.js +1 -0
- package/dist/engine/block/block.d.ts +24 -90
- package/dist/engine/block/block.js +2 -77
- package/dist/engine/block/branch.d.ts +17 -0
- package/dist/engine/block/branch.js +40 -0
- package/dist/engine/block/dialog.d.ts +13 -0
- package/dist/engine/block/dialog.js +37 -0
- package/dist/engine/block/kinds/method.d.ts +0 -2
- package/dist/engine/block/kinds/method.js +0 -1
- package/dist/engine/block/kinds/nav.js +1 -1
- package/dist/engine/flow/map-branch.d.ts +9 -0
- package/dist/engine/flow/map-branch.js +57 -0
- package/dist/engine/flow/map-builder.d.ts +7 -22
- package/dist/engine/flow/map-builder.js +6 -145
- package/dist/engine/flow/map-steps.d.ts +30 -0
- package/dist/engine/flow/map-steps.js +87 -0
- package/dist/engine/run/run.d.ts +1 -19
- package/dist/engine/run/run.js +0 -88
- package/dist/engine/stub/ring.d.ts +2 -4
- package/dist/engine/stub/ring.js +1 -0
- package/dist/engine/stub/stub.d.ts +16 -8
- package/dist/engine/trait/trait.js +1 -1
- package/dist/index.d.ts +15 -12
- package/dist/index.js +9 -7
- package/dist/live/auto/auto.d.ts +3 -15
- package/dist/live/auto/auto.js +10 -420
- package/dist/live/auto/explore.d.ts +2 -2
- package/dist/live/auto/mem.d.ts +11 -0
- package/dist/live/auto/mem.js +85 -0
- package/dist/live/auto/menu.d.ts +30 -0
- package/dist/live/auto/menu.js +335 -0
- package/dist/live/auto-session/auto-session.d.ts +23 -103
- package/dist/live/auto-session/auto-session.js +100 -370
- package/dist/live/auto-session/console.d.ts +4 -0
- package/dist/live/auto-session/console.js +41 -0
- package/dist/live/auto-session/files.d.ts +44 -0
- package/dist/live/auto-session/files.js +145 -0
- package/dist/live/auto-session/helpers.d.ts +5 -2
- package/dist/live/auto-session/helpers.js +17 -0
- package/dist/live/auto-session/inspect.d.ts +4 -0
- package/dist/live/auto-session/inspect.js +75 -0
- package/dist/live/auto-session/ipc.d.ts +3 -22
- package/dist/live/auto-session/ipc.js +7 -147
- package/dist/live/auto-session/open-browser.d.ts +6 -0
- package/dist/live/auto-session/open-browser.js +47 -0
- package/dist/live/pilot/pilot.d.ts +1 -1
- package/dist/live/pilot/pilot.js +2 -1
- package/dist/live/traverse/traverse.js +6 -200
- package/dist/live/traverse/worker.d.ts +37 -0
- package/dist/live/traverse/worker.js +200 -0
- package/dist/runner/plan/find.js +2 -2
- package/dist/runner/plan/plan.js +1 -1
- package/dist/runner/plan/seed-mem.js +5 -5
- package/dist/runner/plan/spec.js +1 -1
- package/examples/saucedemo/src/blocks/saucedemo-web/checkout-step-two/methods/finish-order.method.block.ts +2 -34
- package/examples/saucedemo/src/flows/checkout-then-browse-again.flow.ts +2 -1
- package/examples/saucedemo/src/flows/checkout.flow.ts +2 -1
- package/examples/saucedemo/src/flows/shop.flow.ts +2 -1
- package/examples/saucedemo/src/stubs/device-showcase.ts +37 -43
- package/examples/saucedemo/src/stubs/finish-order.ts +38 -0
- package/package.json +5 -1
- package/templates/quickstart/src/blocks/saucedemo-web/checkout-step-two/methods/finish-order.method.block.ts +2 -34
- package/templates/quickstart/src/flows/checkout-then-browse-again.flow.ts +2 -1
- package/templates/quickstart/src/flows/checkout.flow.ts +2 -1
- package/templates/quickstart/src/flows/shop.flow.ts +2 -1
- package/templates/quickstart/src/stubs/device-showcase.ts +37 -43
- package/templates/quickstart/src/stubs/finish-order.ts +38 -0
- package/templates/scaffold/src/flows/home/hello.flow.ts +3 -0
- package/templates/scaffold/src/map/(app_base)/home/_methods/assert-hello.method.block.ts +1 -9
|
@@ -1,11 +1,11 @@
|
|
|
1
1
|
import { ANSI, ansiPaint, demoFixture, demoHighlight, demoLog } from "../stepper/demo-log.js";
|
|
2
2
|
import { playSwipeTrail } from "./cursor.js";
|
|
3
|
-
import { advanceTodoDock
|
|
3
|
+
import { advanceTodoDock } from "../narration/todo-dock.js";
|
|
4
4
|
import { formatHighlightCaption } from "../narration/style.js";
|
|
5
5
|
import { normalizeHighlightSize, normalizeHighlightTone, normalizeHighlightWeight } from "../../engine/stub/ring.js";
|
|
6
6
|
import { resolveFixtureDwellMs } from "../narration/demo-pace.js";
|
|
7
7
|
import { envNumber } from "../../engine/env.js";
|
|
8
|
-
import { ignorePageGone } from "../../engine/page-gone.js";
|
|
8
|
+
import { ignorePageGone, ignoreTimeout } from "../../engine/page-gone.js";
|
|
9
9
|
/**
|
|
10
10
|
* Scroll a locator into view for demo theater.
|
|
11
11
|
* Prefer CSS smooth scroll + scrollend wait. Do NOT call Playwright's
|
|
@@ -184,8 +184,7 @@ export async function cycleHighlightRings(page, highlights, gatesFast, opts) {
|
|
|
184
184
|
.catch(ignorePageGone);
|
|
185
185
|
}
|
|
186
186
|
let lastRingEndedAt = null;
|
|
187
|
-
for (
|
|
188
|
-
const h = list[i];
|
|
187
|
+
for (const [i, h] of list.entries()) {
|
|
189
188
|
const ringStarted = Date.now();
|
|
190
189
|
try {
|
|
191
190
|
await ensureSelectorInView(page, h.selector);
|
|
@@ -200,13 +199,13 @@ export async function cycleHighlightRings(page, highlights, gatesFast, opts) {
|
|
|
200
199
|
// "does it exist right now" check - ensureSelectorInView above already gave the page a real
|
|
201
200
|
// moment to settle.
|
|
202
201
|
const hLoc = page.locator(h.selector).first();
|
|
203
|
-
const box = (await hLoc.count().catch(
|
|
202
|
+
const box = ((await hLoc.count().catch(ignorePageGone)) ?? 0) > 0
|
|
204
203
|
? await hLoc
|
|
205
204
|
.evaluate((el) => {
|
|
206
205
|
const r = el.getBoundingClientRect();
|
|
207
206
|
return { x: r.x, y: r.y, width: r.width, height: r.height };
|
|
208
207
|
})
|
|
209
|
-
.catch(
|
|
208
|
+
.catch(ignorePageGone)
|
|
210
209
|
: null;
|
|
211
210
|
if (box && box.width > 0 && box.height > 0) {
|
|
212
211
|
await showRing(page, box, h.label, h.tone || "planned", {
|
|
@@ -230,10 +229,8 @@ export async function cycleHighlightRings(page, highlights, gatesFast, opts) {
|
|
|
230
229
|
}, dock)
|
|
231
230
|
.catch(ignorePageGone);
|
|
232
231
|
}
|
|
233
|
-
else if (!dock &&
|
|
234
|
-
const rows = opts
|
|
235
|
-
? opts.todos
|
|
236
|
-
: normalizeTodos(h.todos, h.todoIndex);
|
|
232
|
+
else if (!dock && opts?.todos?.length) {
|
|
233
|
+
const rows = opts.todos;
|
|
237
234
|
await page
|
|
238
235
|
.evaluate((todos) => {
|
|
239
236
|
if (window.__wgSyncTodos)
|
|
@@ -273,16 +270,16 @@ export async function cycleHighlightRings(page, highlights, gatesFast, opts) {
|
|
|
273
270
|
}
|
|
274
271
|
}
|
|
275
272
|
catch (err) {
|
|
276
|
-
demoHighlight(h
|
|
273
|
+
demoHighlight(h, "SKIP " + String(err instanceof Error ? err.message : err).slice(0, 80));
|
|
277
274
|
}
|
|
278
275
|
}
|
|
279
|
-
|
|
280
|
-
|
|
276
|
+
const last = list.at(-1);
|
|
277
|
+
if (last) {
|
|
281
278
|
// Resolved through Playwright's own locator (>> piercing / :has-text() / :visible support),
|
|
282
279
|
// not handed to the page as a string for a raw DOM querySelector to fail silently on - see
|
|
283
280
|
// showRing's own comment (same fix, same reason) and __wgFollowRing's in core.js.
|
|
284
281
|
const handle = last.selector
|
|
285
|
-
? await page.locator(last.selector).first().elementHandle({ timeout: 100 }).catch(
|
|
282
|
+
? await page.locator(last.selector).first().elementHandle({ timeout: 100 }).catch(ignoreTimeout)
|
|
286
283
|
: null;
|
|
287
284
|
await page
|
|
288
285
|
.evaluate(({ h, el }) => {
|
|
@@ -333,7 +330,7 @@ export async function showRing(page, box, label, tone, style) {
|
|
|
333
330
|
// syntax, invisible to document.querySelector. The resolved element handle is passed straight
|
|
334
331
|
// into evaluate (Playwright unwraps it to the real DOM node inside the page), so __wgFollowRing's
|
|
335
332
|
// per-frame RAF loop tracks that exact element directly - no repeated selector re-resolution.
|
|
336
|
-
const handle = selector ? await page.locator(selector).first().elementHandle({ timeout: 100 }).catch(
|
|
333
|
+
const handle = selector ? await page.locator(selector).first().elementHandle({ timeout: 100 }).catch(ignoreTimeout) : null;
|
|
337
334
|
await page
|
|
338
335
|
.evaluate(({ box, label, tone, size, weight, el, focus }) => {
|
|
339
336
|
if (el && window.__wgFollowRing) {
|
|
@@ -352,46 +349,18 @@ export async function showRing(page, box, label, tone, style) {
|
|
|
352
349
|
}, { box, label, tone: tone || "planned", size, weight, el: handle, focus })
|
|
353
350
|
.catch(ignorePageGone);
|
|
354
351
|
}
|
|
355
|
-
/**
|
|
356
|
-
async function matchStubForLocator(page, locator, stubs) {
|
|
357
|
-
if (!stubs || stubs.length === 0)
|
|
358
|
-
return null;
|
|
359
|
-
const box = await locator.boundingBox().catch(() => null);
|
|
360
|
-
if (!box)
|
|
361
|
-
return null;
|
|
362
|
-
for (const s of stubs) {
|
|
363
|
-
try {
|
|
364
|
-
const b = await page.locator(s.selector).first().boundingBox();
|
|
365
|
-
if (b &&
|
|
366
|
-
Math.abs(b.x - box.x) < 4 &&
|
|
367
|
-
Math.abs(b.y - box.y) < 4 &&
|
|
368
|
-
Math.abs(b.width - box.width) < 8) {
|
|
369
|
-
return s;
|
|
370
|
-
}
|
|
371
|
-
}
|
|
372
|
-
catch {
|
|
373
|
-
// A stub selector Playwright can't parse can't be this element either.
|
|
374
|
-
}
|
|
375
|
-
}
|
|
376
|
-
return null;
|
|
377
|
-
}
|
|
378
|
-
/** 0-based stub index for Method fill/click todo advance; -1 if none. */
|
|
352
|
+
/** The stubBefore ring a locator is, by overlapping bounding boxes: its index, or -1. For a Method's todo advance. */
|
|
379
353
|
export async function matchStubIndexForLocator(page, locator, stubs) {
|
|
380
354
|
if (!stubs || stubs.length === 0)
|
|
381
355
|
return -1;
|
|
382
|
-
const box = await locator.boundingBox().catch(
|
|
356
|
+
const box = await locator.boundingBox().catch(ignorePageGone);
|
|
383
357
|
if (!box)
|
|
384
358
|
return -1;
|
|
385
359
|
for (let i = 0; i < stubs.length; i++) {
|
|
386
|
-
const s = stubs[i];
|
|
387
360
|
try {
|
|
388
|
-
const b = await page.locator(
|
|
389
|
-
if (b &&
|
|
390
|
-
Math.abs(b.x - box.x) < 4 &&
|
|
391
|
-
Math.abs(b.y - box.y) < 4 &&
|
|
392
|
-
Math.abs(b.width - box.width) < 8) {
|
|
361
|
+
const b = await page.locator(stubs[i].selector).first().boundingBox();
|
|
362
|
+
if (b && Math.abs(b.x - box.x) < 4 && Math.abs(b.y - box.y) < 4 && Math.abs(b.width - box.width) < 8)
|
|
393
363
|
return i;
|
|
394
|
-
}
|
|
395
364
|
}
|
|
396
365
|
catch {
|
|
397
366
|
// A stub selector Playwright can't parse can't be this element either.
|
|
@@ -399,6 +368,11 @@ export async function matchStubIndexForLocator(page, locator, stubs) {
|
|
|
399
368
|
}
|
|
400
369
|
return -1;
|
|
401
370
|
}
|
|
371
|
+
/** The stubBefore ring a locator is, or null. */
|
|
372
|
+
async function matchStubForLocator(page, locator, stubs) {
|
|
373
|
+
const i = await matchStubIndexForLocator(page, locator, stubs);
|
|
374
|
+
return i >= 0 && stubs ? stubs[i] : null;
|
|
375
|
+
}
|
|
402
376
|
export async function captionForLocator(page, locator, stubs, fallback) {
|
|
403
377
|
const matched = await matchStubForLocator(page, locator, stubs);
|
|
404
378
|
if (matched) {
|
|
@@ -431,18 +405,3 @@ export async function hideRing(page) {
|
|
|
431
405
|
})
|
|
432
406
|
.catch(ignorePageGone);
|
|
433
407
|
}
|
|
434
|
-
/**
|
|
435
|
-
* True if the engine's own narrate() (waygraph's public export, for a Block
|
|
436
|
-
* author explicitly captioning one action) JUST positioned the ring for
|
|
437
|
-
* THIS action, moments ago - the automatic per-fill/per-click narration
|
|
438
|
-
* below should not immediately overwrite an author's own explicit caption
|
|
439
|
-
* with its generic guess.
|
|
440
|
-
*/
|
|
441
|
-
export async function wasJustNarrated(page) {
|
|
442
|
-
return page
|
|
443
|
-
.evaluate(() => {
|
|
444
|
-
const w = window;
|
|
445
|
-
return typeof w.__wgLastNarrate === "number" && Date.now() - w.__wgLastNarrate < 500;
|
|
446
|
-
})
|
|
447
|
-
.catch(() => false);
|
|
448
|
-
}
|
|
@@ -215,3 +215,43 @@
|
|
|
215
215
|
background: #fff; border-radius: var(--wg-radius-lg);
|
|
216
216
|
padding: 10px 18px; box-shadow: var(--wg-shadow-banner);
|
|
217
217
|
}
|
|
218
|
+
|
|
219
|
+
|
|
220
|
+
/* The network tab: real page traffic (network-capture.ts) and defineApiBlock's own calls, bottom-left (the one corner
|
|
221
|
+
* free of the zoom HUD and the typing chip). Hidden until ctx.showNetworkTab(); stays up once shown. In the shared
|
|
222
|
+
* bundle, not the runner CSS: a navigation rebuilds the panel the moment the shadow root is back, before any later
|
|
223
|
+
* stylesheet, and without its CSS it painted unstyled and visible, then faded out. */
|
|
224
|
+
#wg-network-log{position:fixed;z-index:2147483646;bottom:14px;left:14px;min-width:260px;max-width:min(92vw,420px);max-height:min(60vh,420px);display:flex;flex-direction:column;border-radius:10px;background:var(--wg-surface);color:#f0e8ff;border:1px solid rgba(124,58,237,.45);box-shadow:0 8px 22px rgba(0,0,0,.4);font:12px/1.4 ui-monospace,"SF Mono",Consolas,monospace;opacity:0;transform:translateY(8px);transition:opacity .25s ease,transform .25s ease;overflow:hidden;}
|
|
225
|
+
#wg-network-log.wg-in{opacity:1;transform:translateY(0);}
|
|
226
|
+
#wg-network-log.wg-net-collapsed .wg-net-list{display:none;}
|
|
227
|
+
#wg-network-log .wg-net-header{display:flex;align-items:center;gap:6px;padding:8px 10px;border-bottom:1px solid rgba(124,58,237,.25);cursor:default;flex:0 0 auto;}
|
|
228
|
+
#wg-network-log .wg-net-title{font:700 10px/1.2 system-ui,sans-serif;color:#c9a6ff;letter-spacing:.06em;text-transform:uppercase;flex:1 1 auto;}
|
|
229
|
+
#wg-network-log .wg-net-count{font:700 10px/1.2 system-ui,sans-serif;color:#9CA3AF;background:rgba(124,58,237,.22);border-radius:999px;padding:1px 7px;}
|
|
230
|
+
#wg-network-log .wg-net-collapse{flex:0 0 auto;width:18px;height:18px;border-radius:5px;border:none;background:rgba(124,58,237,.28);color:#e8dcff;font:700 13px/1 system-ui,sans-serif;cursor:pointer;pointer-events:auto;}
|
|
231
|
+
#wg-network-log .wg-net-collapse:hover{background:rgba(124,58,237,.42);}
|
|
232
|
+
#wg-network-log .wg-net-list{list-style:none;margin:0;padding:6px 8px;display:flex;flex-direction:column;gap:2px;overflow-y:auto;pointer-events:auto;}
|
|
233
|
+
#wg-network-log .wg-net-row{display:flex;align-items:baseline;gap:7px;opacity:0;padding:3px 4px;border-radius:5px;cursor:pointer;transform:translateX(-4px);transition:opacity .2s ease,transform .2s ease;}
|
|
234
|
+
#wg-network-log .wg-net-row:hover,#wg-network-log .wg-net-row.wg-net-open{background:rgba(124,58,237,.18);}
|
|
235
|
+
#wg-network-log .wg-net-row.wg-in{opacity:1;transform:translateX(0);}
|
|
236
|
+
#wg-network-log .wg-net-method{flex:0 0 auto;font-weight:800;font-size:10px;min-width:38px;}
|
|
237
|
+
#wg-network-log .wg-net-method-get{color:#3B82F6;}
|
|
238
|
+
#wg-network-log .wg-net-method-post{color:#22C55E;}
|
|
239
|
+
#wg-network-log .wg-net-method-put{color:#F97316;}
|
|
240
|
+
#wg-network-log .wg-net-method-delete{color:#EF4444;}
|
|
241
|
+
#wg-network-log .wg-net-method-other{color:#9CA3AF;}
|
|
242
|
+
#wg-network-log .wg-net-path{flex:1 1 auto;min-width:0;overflow:hidden;text-overflow:ellipsis;white-space:nowrap;color:#e0e0f0;}
|
|
243
|
+
#wg-network-log .wg-net-status{flex:0 0 auto;font-weight:700;color:#22C55E;}
|
|
244
|
+
#wg-network-log .wg-net-row[data-ok="0"] .wg-net-status{color:#EF4444;}
|
|
245
|
+
#wg-network-log .wg-net-ms{flex:0 0 auto;color:#9CA3AF;font-size:10px;}
|
|
246
|
+
#wg-network-log .wg-net-detail{list-style:none;background:rgba(0,0,0,.28);border-radius:6px;padding:8px;margin:2px 0 6px;}
|
|
247
|
+
#wg-network-log .wg-net-detail-section{margin-bottom:8px;}
|
|
248
|
+
#wg-network-log .wg-net-detail-section:last-child{margin-bottom:0;}
|
|
249
|
+
#wg-network-log .wg-net-detail-section h4{margin:0 0 4px;font:700 9px/1.2 system-ui,sans-serif;color:#9CA3AF;letter-spacing:.06em;text-transform:uppercase;}
|
|
250
|
+
#wg-network-log .wg-net-headers{width:100%;border-collapse:collapse;font-size:11px;}
|
|
251
|
+
#wg-network-log .wg-net-headers td{padding:1px 6px 1px 0;vertical-align:top;word-break:break-all;}
|
|
252
|
+
#wg-network-log .wg-net-headers td:first-child{color:#c9a6ff;white-space:nowrap;}
|
|
253
|
+
#wg-network-log .wg-net-body{margin:0;font-size:11px;white-space:pre-wrap;word-break:break-all;max-height:160px;overflow-y:auto;color:#e0e0f0;}
|
|
254
|
+
#wg-network-log .wg-net-curl{color:#7dd3fc;}
|
|
255
|
+
#wg-network-log .wg-net-empty{font-size:11px;color:#6b7280;font-style:italic;}
|
|
256
|
+
#wg-network-log .wg-net-copy{margin-top:5px;padding:3px 9px;border-radius:5px;border:1px solid rgba(124,58,237,.5);background:rgba(124,58,237,.22);color:#e8dcff;font:700 10px system-ui,sans-serif;cursor:pointer;}
|
|
257
|
+
#wg-network-log .wg-net-copy:hover{background:rgba(124,58,237,.38);}
|
|
@@ -1,17 +1,19 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { envFlag } from "../../engine/env.js";
|
|
2
|
+
import { hasAuthoredStubAfter, runStubPhase } from "../narration/narration.js";
|
|
2
3
|
import { applyHighlightStyleDefaults, formatHighlightCaption } from "../narration/style.js";
|
|
3
|
-
import { demoLog, logStubPhaseFixtures, logTodoDockFull, paceSpeakFields, summarizeDevice } from "./demo-log.js";
|
|
4
|
-
import { extractVerifyHighlights, renderAfterStep } from "./step-panels.js";
|
|
5
|
-
import { presentSlides } from "./slides.js";
|
|
6
4
|
import { logBannerDom, probeBanner } from "./banner-log.js";
|
|
7
5
|
import { logDocks } from "./before.js";
|
|
6
|
+
import { demoLog, logStubPhaseFixtures, logTodoDockFull, paceSpeakFields, summarizeDevice } from "./demo-log.js";
|
|
7
|
+
import { renderAfterStep } from "./panel-after.js";
|
|
8
|
+
import { showSlides } from "./slides.js";
|
|
9
|
+
import { extractVerifyHighlights } from "./step-panels.js";
|
|
8
10
|
import { forceCollapsed } from "./view.js";
|
|
9
|
-
import { envFlag } from "../../engine/env.js";
|
|
10
11
|
const quiet = () => envFlag("WAYGRAPH_JSON");
|
|
11
12
|
export async function showAfter(ctx, view, result) {
|
|
12
13
|
const { stage, refs } = ctx;
|
|
13
|
-
await showSlides(ctx, view, result);
|
|
14
14
|
const after = hasAuthoredStubAfter(view.step.block, result) ? await narrateAfter(ctx, view, result) : undefined;
|
|
15
|
+
if (after)
|
|
16
|
+
await showSlides(ctx, view, after.phase.slides);
|
|
15
17
|
const applied = after ? await stage.applyPhase(after.phase) : { appliedTodo: { sync: "keep" }, appliedDevice: { sync: "keep" } };
|
|
16
18
|
await renderAfterStep(ctx.page, {
|
|
17
19
|
index: view.index,
|
|
@@ -61,20 +63,6 @@ export async function showAfter(ctx, view, result) {
|
|
|
61
63
|
}
|
|
62
64
|
await ctx.gate.wait();
|
|
63
65
|
}
|
|
64
|
-
async function showSlides(ctx, view, result) {
|
|
65
|
-
const slides = resolveSlides(view.step.block, { out: result }).map((s) => applyHighlightStyleDefaults(s, view.step.highlightStyle));
|
|
66
|
-
if (slides.length === 0)
|
|
67
|
-
return;
|
|
68
|
-
await presentSlides(ctx.page, slides, ctx.gate.wait, {
|
|
69
|
-
title: ctx.title,
|
|
70
|
-
blockName: view.step.block.name,
|
|
71
|
-
fast: ctx.pacing.gatesFast,
|
|
72
|
-
pace: ctx.pacing.demoPace,
|
|
73
|
-
episodeNumber: view.step.episodeNumber,
|
|
74
|
-
episodeTitle: view.step.episodeTitle,
|
|
75
|
-
autoplayMs: ctx.gate.autoplayMs,
|
|
76
|
-
});
|
|
77
|
-
}
|
|
78
66
|
/** Runs the Block's stubAfter; its rings carry the flow's highlight style and a caption. */
|
|
79
67
|
async function narrateAfter(ctx, view, result) {
|
|
80
68
|
const style = view.step.highlightStyle;
|
|
@@ -89,21 +77,10 @@ async function narrateAfter(ctx, view, result) {
|
|
|
89
77
|
}),
|
|
90
78
|
});
|
|
91
79
|
const highlights = phase.highlights.map((h) => {
|
|
80
|
+
// The ring's look and timing only; its todo, gesture and cursor belong to stubBefore.
|
|
92
81
|
const styled = applyHighlightStyleDefaults(h, style);
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
label: formatHighlightCaption(styled),
|
|
96
|
-
duration: styled.duration,
|
|
97
|
-
fastMode: styled.fastMode,
|
|
98
|
-
tone: styled.tone,
|
|
99
|
-
size: styled.size,
|
|
100
|
-
weight: styled.weight,
|
|
101
|
-
zoom: styled.zoom,
|
|
102
|
-
zoomOut: styled.zoomOut,
|
|
103
|
-
focus: !!styled.focus,
|
|
104
|
-
color: styled.color,
|
|
105
|
-
detail: styled.detail,
|
|
106
|
-
};
|
|
82
|
+
const { tag: _tag, cursor: _cursor, todo: _todo, slotId: _slotId, gesture: _gesture, ...ring } = styled;
|
|
83
|
+
return { ...ring, label: formatHighlightCaption(styled), focus: !!styled.focus };
|
|
107
84
|
});
|
|
108
85
|
return { phase, highlights };
|
|
109
86
|
}
|
|
@@ -1,6 +1,7 @@
|
|
|
1
|
-
import type { WgPage } from "../types.js";
|
|
1
|
+
import type { BannerUiState, WgPage } from "../types.js";
|
|
2
|
+
import type { StubPhaseResult } from "../../engine/stub/stub.js";
|
|
2
3
|
/** Authored banner UX from a stub phase -> the { pos, collision, hidden } shape installOverlay takes. */
|
|
3
|
-
export declare function bannerUiFromPhase(phase:
|
|
4
|
+
export declare function bannerUiFromPhase(phase: Pick<StubPhaseResult, "titlePos" | "bannerUi"> | null | undefined): BannerUiState;
|
|
4
5
|
/** Read the live banner: text, position, whether it was moved by ring collision; drains the move log. */
|
|
5
6
|
export declare function probeBanner(page: WgPage): Promise<{
|
|
6
7
|
present: boolean;
|
|
@@ -30,8 +31,5 @@ export declare function probeBanner(page: WgPage): Promise<{
|
|
|
30
31
|
w: number;
|
|
31
32
|
h: number;
|
|
32
33
|
log: any;
|
|
33
|
-
} | {
|
|
34
|
-
present: boolean;
|
|
35
|
-
log: never[];
|
|
36
34
|
}>;
|
|
37
|
-
export declare function logBannerDom(tag:
|
|
35
|
+
export declare function logBannerDom(tag: string, p: Awaited<ReturnType<typeof probeBanner>> | null | undefined): void;
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import { demoLog } from "./demo-log.js";
|
|
2
|
+
import { ignorePageGone } from "../../engine/page-gone.js";
|
|
2
3
|
/** Authored banner UX from a stub phase -> the { pos, collision, hidden } shape installOverlay takes. */
|
|
3
4
|
export function bannerUiFromPhase(phase) {
|
|
4
5
|
const ui = {};
|
|
@@ -41,7 +42,8 @@ export async function probeBanner(page) {
|
|
|
41
42
|
log,
|
|
42
43
|
};
|
|
43
44
|
})
|
|
44
|
-
.catch(
|
|
45
|
+
.catch(ignorePageGone)
|
|
46
|
+
.then((probe) => probe ?? { present: false, log: [] });
|
|
45
47
|
}
|
|
46
48
|
export function logBannerDom(tag, p) {
|
|
47
49
|
if (!p)
|
|
@@ -1,18 +1,20 @@
|
|
|
1
|
-
// Before a demo step runs: play the Block's stubBefore narration (rings, todos, device, title, caption) and show the
|
|
1
|
+
// Before a demo step runs: play the Block's stubBefore narration (slides, rings, todos, device, title, caption) and show the
|
|
2
2
|
// step's panel, then log what was painted so an agent without eyes can check it.
|
|
3
|
+
import { envFlag } from "../../engine/env.js";
|
|
3
4
|
import { runStubPhase } from "../narration/narration.js";
|
|
4
5
|
import { applyHighlightStyleDefaults, formatHighlightCaption } from "../narration/style.js";
|
|
6
|
+
import { logBannerDom, probeBanner } from "./banner-log.js";
|
|
5
7
|
import { demoLog, logStubPhaseFixtures, logTodoDockFull, paceSpeakFields, summarizeDevice } from "./demo-log.js";
|
|
6
|
-
import { renderBeforeStep } from "./
|
|
8
|
+
import { renderBeforeStep } from "./panel-before.js";
|
|
9
|
+
import { showSlides } from "./slides.js";
|
|
7
10
|
import { probeTodoDocksOnPage } from "./todo-advance.js";
|
|
8
|
-
import { logBannerDom, probeBanner } from "./banner-log.js";
|
|
9
11
|
import { forceCollapsed } from "./view.js";
|
|
10
|
-
import { envFlag } from "../../engine/env.js";
|
|
11
12
|
const quiet = () => envFlag("WAYGRAPH_JSON");
|
|
12
13
|
export async function showBefore(ctx, view) {
|
|
13
14
|
const { stage } = ctx;
|
|
14
15
|
const phase = await narrateBefore(ctx, view);
|
|
15
16
|
const { appliedTodo } = await stage.applyPhase(phase, { reapplyDeviceOnKeep: true });
|
|
17
|
+
await showSlides(ctx, view, phase.slides);
|
|
16
18
|
if (phase.title && String(phase.title).trim())
|
|
17
19
|
ctx.stickyTitle = String(phase.title).trim();
|
|
18
20
|
view.overlayTitle = ctx.stickyTitle || (view.step.episodeTitle && String(view.step.episodeTitle).trim()) || ctx.title || "waygraph demo";
|
|
@@ -1,5 +1,21 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
1
|
+
import type { StubPhaseResult } from "../../engine/stub/stub.js";
|
|
2
|
+
import type { TodoDockState } from "../../engine/stub/todos.js";
|
|
3
|
+
import type { DeviceState } from "../../engine/stub/viewport.js";
|
|
4
|
+
/** What a HIGHLIGHT log line shows: a ring as painted (no selector for a narrated caption). Logged, not checked. */
|
|
5
|
+
type LoggedHighlight = {
|
|
6
|
+
selector?: string | null | undefined;
|
|
7
|
+
label?: string | undefined;
|
|
8
|
+
tone?: string | undefined;
|
|
9
|
+
color?: string | undefined;
|
|
10
|
+
focus?: boolean | undefined;
|
|
11
|
+
zoom?: number | undefined;
|
|
12
|
+
zoomOut?: boolean | undefined;
|
|
13
|
+
gesture?: string | undefined;
|
|
14
|
+
weight?: string | undefined;
|
|
15
|
+
size?: string | undefined;
|
|
16
|
+
};
|
|
17
|
+
export declare function demoPaceKind(pace: unknown): string;
|
|
18
|
+
export declare function paceSpeakFields(pace: unknown, baseAutoplayMs: number | undefined): {
|
|
3
19
|
pace: import("../../index.js").DemoPace;
|
|
4
20
|
paceBadge: string;
|
|
5
21
|
paceLabel: string;
|
|
@@ -19,13 +35,14 @@ export declare const ANSI: {
|
|
|
19
35
|
magenta: string;
|
|
20
36
|
white: string;
|
|
21
37
|
};
|
|
22
|
-
export declare function ansiPaint(code:
|
|
23
|
-
export declare function demoLog(msg:
|
|
38
|
+
export declare function ansiPaint(code: string, text: unknown): string;
|
|
39
|
+
export declare function demoLog(msg: string): void;
|
|
24
40
|
/** Fixture catch-all: how it was called + value. */
|
|
25
|
-
export declare function demoFixture(kind:
|
|
41
|
+
export declare function demoFixture(kind: string, call: string, value?: unknown): void;
|
|
26
42
|
/** Highlight trigger line: PURPLE · Cart items - Product landed in cart */
|
|
27
|
-
export declare function demoHighlight(h:
|
|
28
|
-
export declare function logStubPhaseFixtures(phaseName:
|
|
43
|
+
export declare function demoHighlight(h: LoggedHighlight | null | undefined, extra?: string): void;
|
|
44
|
+
export declare function logStubPhaseFixtures(phaseName: string, phase: StubPhaseResult | null | undefined): void;
|
|
29
45
|
/** Full todo dump for agents (every group/item id + flags). */
|
|
30
|
-
export declare function logTodoDockFull(dock:
|
|
31
|
-
export declare function summarizeDevice(d:
|
|
46
|
+
export declare function logTodoDockFull(dock: TodoDockState | null | undefined, tag?: string): void;
|
|
47
|
+
export declare function summarizeDevice(d: DeviceState | null | undefined): string;
|
|
48
|
+
export {};
|
|
@@ -14,7 +14,7 @@ export function demoPaceKind(pace) {
|
|
|
14
14
|
}
|
|
15
15
|
export function paceSpeakFields(pace, baseAutoplayMs) {
|
|
16
16
|
const p = normalizeDemoPace(pace);
|
|
17
|
-
const base = Number.isFinite(baseAutoplayMs) && baseAutoplayMs > 0 ? baseAutoplayMs : 1800;
|
|
17
|
+
const base = baseAutoplayMs !== undefined && Number.isFinite(baseAutoplayMs) && baseAutoplayMs > 0 ? baseAutoplayMs : 1800;
|
|
18
18
|
return {
|
|
19
19
|
pace: p,
|
|
20
20
|
paceBadge: formatDemoPaceBadge(p, base),
|
|
@@ -207,12 +207,10 @@ export function logStubPhaseFixtures(phaseName, phase) {
|
|
|
207
207
|
}
|
|
208
208
|
: phase.todoSync);
|
|
209
209
|
}
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
const h = rings[i];
|
|
213
|
-
demoFixture(tag, "ctx.ring/highlights[" + i + "]", {
|
|
210
|
+
phase.highlights.forEach((h, i) => {
|
|
211
|
+
demoFixture(tag, "ctx.ring[" + i + "]", {
|
|
214
212
|
selector: h.selector,
|
|
215
|
-
label: h.label
|
|
213
|
+
label: h.label,
|
|
216
214
|
detail: h.detail,
|
|
217
215
|
tone: h.tone || "planned",
|
|
218
216
|
color: h.color,
|
|
@@ -222,10 +220,7 @@ export function logStubPhaseFixtures(phaseName, phase) {
|
|
|
222
220
|
gesture: h.gesture,
|
|
223
221
|
duration: h.duration,
|
|
224
222
|
});
|
|
225
|
-
}
|
|
226
|
-
if (phase.slides && phase.slides.length) {
|
|
227
|
-
demoFixture(tag, "ctx.slides(...)", { n: phase.slides.length });
|
|
228
|
-
}
|
|
223
|
+
});
|
|
229
224
|
}
|
|
230
225
|
function summarizeTodoDock(dock) {
|
|
231
226
|
if (!dock)
|
|
@@ -267,8 +262,7 @@ export function logTodoDockFull(dock, tag) {
|
|
|
267
262
|
demoLog(prefix + " (no groups)");
|
|
268
263
|
return;
|
|
269
264
|
}
|
|
270
|
-
|
|
271
|
-
const g = groups[gi];
|
|
265
|
+
groups.forEach((g, gi) => {
|
|
272
266
|
const gLabel = "group[" +
|
|
273
267
|
gi +
|
|
274
268
|
"]" +
|
|
@@ -276,22 +270,11 @@ export function logTodoDockFull(dock, tag) {
|
|
|
276
270
|
(g.title ? ' title="' + String(g.title).slice(0, 40) + '"' : "") +
|
|
277
271
|
(g.style ? " style=" + g.style : "");
|
|
278
272
|
demoLog(prefix + " " + gLabel);
|
|
279
|
-
|
|
280
|
-
for (let ti = 0; ti < items.length; ti++) {
|
|
281
|
-
const t = items[ti];
|
|
273
|
+
(g.items || []).forEach((t, ti) => {
|
|
282
274
|
const mark = t.done ? "done" : t.current ? "CURRENT" : "pending";
|
|
283
|
-
demoLog(prefix +
|
|
284
|
-
|
|
285
|
-
|
|
286
|
-
"] " +
|
|
287
|
-
mark +
|
|
288
|
-
(t.id ? " id=" + t.id : "") +
|
|
289
|
-
' text="' +
|
|
290
|
-
String(t.text || "").slice(0, 80) +
|
|
291
|
-
'"' +
|
|
292
|
-
(t.detail ? ' detail="' + String(t.detail).slice(0, 40) + '"' : ""));
|
|
293
|
-
}
|
|
294
|
-
}
|
|
275
|
+
demoLog(prefix + " [" + ti + "] " + mark + (t.id ? " id=" + t.id : "") + ' text="' + String(t.text || "").slice(0, 80) + '"');
|
|
276
|
+
});
|
|
277
|
+
});
|
|
295
278
|
}
|
|
296
279
|
export function summarizeDevice(d) {
|
|
297
280
|
if (!d)
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
-
import type { WgPage } from "../types.js";
|
|
1
|
+
import type { StepperRefs, WgPage } from "../types.js";
|
|
2
|
+
import type { Pacing } from "./pacing.js";
|
|
2
3
|
import type { MemPage } from "../../engine/mem/mem.js";
|
|
3
|
-
export declare function instrumentInteractionHighlighting(page: WgPage, mem: MemPage, slowMo: number, pacing:
|
|
4
|
+
export declare function instrumentInteractionHighlighting(page: WgPage, mem: MemPage, slowMo: number, pacing: Pacing, stubBeforeRef: StepperRefs["stubBefore"], todoDockRef: StepperRefs["todoDock"], deviceRef: StepperRefs["device"]): void;
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { installOverlay } from "../overlay/overlay.js";
|
|
2
|
-
import { applyHighlightZoom, captionForLocator, dwellMatchedStub, ensureLocatorInView, hideRing, matchStubIndexForLocator, showRing
|
|
2
|
+
import { applyHighlightZoom, captionForLocator, dwellMatchedStub, ensureLocatorInView, hideRing, matchStubIndexForLocator, showRing } from "../overlay/rings.js";
|
|
3
3
|
import { syncTodoDockAdvance } from "./todo-advance.js";
|
|
4
4
|
import { clickPulseAt, moveCursorTo } from "../overlay/cursor.js";
|
|
5
5
|
import { demoHighlight } from "./demo-log.js";
|
|
@@ -70,7 +70,7 @@ export function instrumentInteractionHighlighting(page, mem, slowMo, pacing, stu
|
|
|
70
70
|
const memTrack = { lastKeyName: null, at: 0 };
|
|
71
71
|
const originalGet = mem.get.bind(mem);
|
|
72
72
|
mem.get = (key) => {
|
|
73
|
-
memTrack.lastKeyName = key
|
|
73
|
+
memTrack.lastKeyName = key.name;
|
|
74
74
|
memTrack.at = Date.now();
|
|
75
75
|
return originalGet(key);
|
|
76
76
|
};
|
|
@@ -109,7 +109,7 @@ export function instrumentInteractionHighlighting(page, mem, slowMo, pacing, stu
|
|
|
109
109
|
catch {
|
|
110
110
|
/* ignore */
|
|
111
111
|
}
|
|
112
|
-
if (box
|
|
112
|
+
if (box) {
|
|
113
113
|
// Only trust the "last mem.get()" as THIS fill's source if it
|
|
114
114
|
// happened recently - a stale read from several actions ago is
|
|
115
115
|
// more likely unrelated than actually describing this field.
|
|
@@ -126,33 +126,28 @@ export function instrumentInteractionHighlighting(page, mem, slowMo, pacing, stu
|
|
|
126
126
|
await applyHighlightZoom(page, stub.selector, stub.zoom, stub.zoomOut);
|
|
127
127
|
}
|
|
128
128
|
demoHighlight({
|
|
129
|
-
selector: stub
|
|
129
|
+
selector: stub?.selector,
|
|
130
130
|
label: cap.label,
|
|
131
|
-
tone: cap.tone || (stub
|
|
132
|
-
color: stub
|
|
133
|
-
focus: !!(stub
|
|
134
|
-
zoom: stub
|
|
135
|
-
zoomOut: stub
|
|
136
|
-
gesture: stub
|
|
131
|
+
tone: cap.tone || (stub?.tone) || "planned",
|
|
132
|
+
color: stub?.color,
|
|
133
|
+
focus: !!(stub?.focus),
|
|
134
|
+
zoom: stub?.zoom,
|
|
135
|
+
zoomOut: stub?.zoomOut,
|
|
136
|
+
gesture: stub?.gesture,
|
|
137
137
|
weight: cap.weight,
|
|
138
138
|
size: cap.size,
|
|
139
139
|
}, "fill");
|
|
140
140
|
await showRing(page, box, cap.label, cap.tone, {
|
|
141
141
|
size: cap.size,
|
|
142
142
|
weight: cap.weight,
|
|
143
|
-
selector: stub
|
|
144
|
-
focus: !!(stub
|
|
143
|
+
selector: stub?.selector,
|
|
144
|
+
focus: !!(stub?.focus),
|
|
145
145
|
});
|
|
146
146
|
await dwellMatchedStub(page, locator, stubs, pacing);
|
|
147
147
|
await new Promise((res) => setTimeout(res, skipTheater() ? 0 : 200));
|
|
148
148
|
if (cap && cap.label)
|
|
149
149
|
typeLabel = String(cap.label).slice(0, 40);
|
|
150
150
|
}
|
|
151
|
-
else if (box) {
|
|
152
|
-
// Ring/caption already handled by narrate() - still move the
|
|
153
|
-
// cursor there, just skip re-showing the ring with a generic label.
|
|
154
|
-
await moveCursorTo(page, box, cursorMs(200));
|
|
155
|
-
}
|
|
156
151
|
await page
|
|
157
152
|
.evaluate((label) => {
|
|
158
153
|
if (window.__wgSetTypingBadge)
|
|
@@ -191,8 +186,7 @@ export function instrumentInteractionHighlighting(page, mem, slowMo, pacing, stu
|
|
|
191
186
|
// own click scroll is instant and reads as a teleport under --fast.
|
|
192
187
|
await ensureLocatorInView(locator, { instant: skipTheater() });
|
|
193
188
|
const box = await locator.boundingBox();
|
|
194
|
-
|
|
195
|
-
if (box && !narrated) {
|
|
189
|
+
if (box) {
|
|
196
190
|
let fallback = "click";
|
|
197
191
|
try {
|
|
198
192
|
const text = (await locator.textContent())?.trim();
|
|
@@ -218,22 +212,22 @@ export function instrumentInteractionHighlighting(page, mem, slowMo, pacing, stu
|
|
|
218
212
|
await applyHighlightZoom(page, stub.selector, stub.zoom, stub.zoomOut);
|
|
219
213
|
}
|
|
220
214
|
demoHighlight({
|
|
221
|
-
selector: stub
|
|
215
|
+
selector: stub?.selector,
|
|
222
216
|
label: cap.label,
|
|
223
|
-
tone: cap.tone || (stub
|
|
224
|
-
color: stub
|
|
225
|
-
focus: !!(stub
|
|
226
|
-
zoom: stub
|
|
227
|
-
zoomOut: stub
|
|
228
|
-
gesture: stub
|
|
217
|
+
tone: cap.tone || (stub?.tone) || "planned",
|
|
218
|
+
color: stub?.color,
|
|
219
|
+
focus: !!(stub?.focus),
|
|
220
|
+
zoom: stub?.zoom,
|
|
221
|
+
zoomOut: stub?.zoomOut,
|
|
222
|
+
gesture: stub?.gesture,
|
|
229
223
|
weight: cap.weight,
|
|
230
224
|
size: cap.size,
|
|
231
225
|
}, "click");
|
|
232
226
|
await showRing(page, box, cap.label, cap.tone, {
|
|
233
227
|
size: cap.size,
|
|
234
228
|
weight: cap.weight,
|
|
235
|
-
selector: stub
|
|
236
|
-
focus: !!(stub
|
|
229
|
+
selector: stub?.selector,
|
|
230
|
+
focus: !!(stub?.focus),
|
|
237
231
|
});
|
|
238
232
|
await dwellMatchedStub(page, locator, stubs, pacing);
|
|
239
233
|
// "pop for a few seconds" - the user's own phrase, matching the
|
|
@@ -241,12 +235,6 @@ export function instrumentInteractionHighlighting(page, mem, slowMo, pacing, stu
|
|
|
241
235
|
// services/help-center-clip-engine's video-pipeline.
|
|
242
236
|
await new Promise((res) => setTimeout(res, clickPrePop()));
|
|
243
237
|
}
|
|
244
|
-
else if (box) {
|
|
245
|
-
// Ring/caption already handled by narrate() - still move the
|
|
246
|
-
// cursor + pulse the click point, just skip re-showing the ring.
|
|
247
|
-
clickPoint = await moveCursorTo(page, box, cursorMs(200));
|
|
248
|
-
clickTone = "planned";
|
|
249
|
-
}
|
|
250
238
|
if (clickPoint) {
|
|
251
239
|
await clickPulseAt(page, clickPoint.x, clickPoint.y, clickTone);
|
|
252
240
|
// clickPulseAt only triggers the CSS animation class - it doesn't
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
import type { Checkpoint } from "../../engine/checkpoint/checkpoint.js";
|
|
2
|
+
import type { DemoPace } from "../../engine/stub/pace.js";
|
|
3
|
+
import type { ResolvedHighlight } from "../../engine/stub/ring.js";
|
|
4
|
+
import type { TodoDockState } from "../../engine/stub/todos.js";
|
|
5
|
+
import type { Ref, WgPage } from "../types.js";
|
|
6
|
+
import { type PanelTodos, type StepPanelInfo } from "./step-panels.js";
|
|
7
|
+
/** The panel after a step: the Checkpoint it resolved to, the rings to cycle, and whether it was the last step. */
|
|
8
|
+
export interface AfterPanelInfo extends StepPanelInfo, PanelTodos {
|
|
9
|
+
result: Checkpoint<string>;
|
|
10
|
+
resultTag: string;
|
|
11
|
+
highlights: readonly ResolvedHighlight[];
|
|
12
|
+
gatesFast?: boolean | undefined;
|
|
13
|
+
isLast: boolean;
|
|
14
|
+
pace?: DemoPace | undefined;
|
|
15
|
+
todoDockRef?: Ref<TodoDockState | undefined> | undefined;
|
|
16
|
+
}
|
|
17
|
+
export declare function renderAfterStep(page: WgPage, info: AfterPanelInfo): Promise<void>;
|