waygraph 0.12.14 → 0.12.15
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +5 -0
- package/dist/cli.js +85 -20
- package/dist/engine.d.ts +17 -0
- package/dist/engine.js +25 -0
- package/dist/highlights.d.ts +44 -2
- package/dist/highlights.js +88 -13
- package/dist/index.d.ts +3 -3
- package/dist/index.js +2 -2
- package/dist/step-overlay.d.ts +1 -1
- package/dist/step-overlay.js +34 -6
- package/dist/types.d.ts +5 -0
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -233,6 +233,11 @@ Sign In narration.
|
|
|
233
233
|
snapshot, partitions edges by hash, and claims via in-process edge leases (audit under
|
|
234
234
|
`.waygraph-traverse/`). `--session inherit` is refused when `parallel > 1`. See
|
|
235
235
|
`docs/proposals/traverse-ffcompose-rfc.md`.
|
|
236
|
+
|
|
237
|
+
**Richer demo narration:** automation rings are **gray**; authored stubs/slides can use
|
|
238
|
+
`tone: "info" | "warning" | "danger" | "success"` (iconified captions). Episode pacing:
|
|
239
|
+
`withDemoPace(flow, "fast" | "slow" | "normal" | "blitz")` or `withBlockPace(block, ...)`
|
|
240
|
+
(FFCompose stays blitz). Living objectives: `docs/proposals/OBJECTIVES.md`.
|
|
236
241
|
`spawnTab(entry, page, mem)` drives a genuinely separate second tab through its own
|
|
237
242
|
Block/Flow, in the same browser context an existing `page` already belongs to - the
|
|
238
243
|
pattern `observe()` could already reach for (it's the only phase allowed to touch
|
package/dist/cli.js
CHANGED
|
@@ -211,6 +211,9 @@ import {
|
|
|
211
211
|
formatHighlightCaption,
|
|
212
212
|
hasAuthoredStubAfter,
|
|
213
213
|
hasAuthoredStubOnError,
|
|
214
|
+
normalizeHighlightTone,
|
|
215
|
+
normalizeDemoPace,
|
|
216
|
+
resolveStepDemoPace,
|
|
214
217
|
} from "waygraph";
|
|
215
218
|
|
|
216
219
|
function walkDir(dir, pattern) {
|
|
@@ -399,9 +402,13 @@ const RING_CSS =
|
|
|
399
402
|
"border:2.5px solid #7C3AED;border-radius:10px;" +
|
|
400
403
|
"box-shadow:0 0 0 4px rgba(124,58,237,.16);transition:opacity .3s ease,border-color .15s,box-shadow .15s;}" +
|
|
401
404
|
// Planned (stubs / fixtures / YAP / instruction.highlights) = purple.
|
|
402
|
-
// Automation (verify fallback, unmatched fill/click) =
|
|
403
|
-
// can ignore engine checks and
|
|
404
|
-
"#wg-ring[data-tone=auto]{border-color:#
|
|
405
|
+
// Automation (verify fallback, unmatched fill/click) = gray - operators
|
|
406
|
+
// can ignore engine checks and watch purple + semantic tones.
|
|
407
|
+
"#wg-ring[data-tone=auto]{border-color:#9CA3AF;box-shadow:0 0 0 4px rgba(156,163,175,.28);}" +
|
|
408
|
+
"#wg-ring[data-tone=info]{border-color:#3B82F6;box-shadow:0 0 0 4px rgba(59,130,246,.22);}" +
|
|
409
|
+
"#wg-ring[data-tone=warning]{border-color:#EAB308;box-shadow:0 0 0 4px rgba(234,179,8,.22);}" +
|
|
410
|
+
"#wg-ring[data-tone=danger]{border-color:#EF4444;box-shadow:0 0 0 4px rgba(239,68,68,.22);}" +
|
|
411
|
+
"#wg-ring[data-tone=success]{border-color:#22C55E;box-shadow:0 0 0 4px rgba(34,197,94,.22);}" +
|
|
405
412
|
// A real element, not a ::after pseudo-element - a pseudo-element's
|
|
406
413
|
// position is CSS-relative to the ring's own box (left:0 always meant
|
|
407
414
|
// "the ring's own left edge"), so it had no way to be clamped back onto
|
|
@@ -413,7 +420,11 @@ const RING_CSS =
|
|
|
413
420
|
"#wg-ring-label{position:fixed;z-index:2147483646;pointer-events:none;opacity:0;" +
|
|
414
421
|
"max-width:min(360px,70vw);white-space:normal;padding:6px 10px;border-radius:7px;background:#7C3AED;color:#fff;" +
|
|
415
422
|
"font:600 12px/1.35 system-ui,sans-serif;transition:opacity .3s ease,background .15s,color .15s;}" +
|
|
416
|
-
"#wg-ring-label[data-tone=auto]{background:#
|
|
423
|
+
"#wg-ring-label[data-tone=auto]{background:#6B7280;color:#fff;}" +
|
|
424
|
+
"#wg-ring-label[data-tone=info]{background:#2563EB;color:#fff;}" +
|
|
425
|
+
"#wg-ring-label[data-tone=warning]{background:#EAB308;color:#1c1917;}" +
|
|
426
|
+
"#wg-ring-label[data-tone=danger]{background:#DC2626;color:#fff;}" +
|
|
427
|
+
"#wg-ring-label[data-tone=success]{background:#16A34A;color:#fff;}" +
|
|
417
428
|
// Mouse cursor icon that travels to a target before it's acted on, plus a
|
|
418
429
|
// quick expanding ripple at the moment of a click - same idea as
|
|
419
430
|
// help-center-clip-engine's #clip-cursor/#clip-ring (video-pipeline). The
|
|
@@ -431,7 +442,11 @@ const RING_CSS =
|
|
|
431
442
|
"#wg-click-pulse{position:fixed;z-index:2147483647;width:14px;height:14px;" +
|
|
432
443
|
"margin-left:-7px;margin-top:-7px;border-radius:50%;pointer-events:none;opacity:0;" +
|
|
433
444
|
"border:2px solid #7C3AED;background:rgba(124,58,237,.25);}" +
|
|
434
|
-
"#wg-click-pulse[data-tone=auto]{border-color:#
|
|
445
|
+
"#wg-click-pulse[data-tone=auto]{border-color:#9CA3AF;background:rgba(156,163,175,.28);}" +
|
|
446
|
+
"#wg-click-pulse[data-tone=info]{border-color:#3B82F6;background:rgba(59,130,246,.28);}" +
|
|
447
|
+
"#wg-click-pulse[data-tone=warning]{border-color:#EAB308;background:rgba(234,179,8,.28);}" +
|
|
448
|
+
"#wg-click-pulse[data-tone=danger]{border-color:#EF4444;background:rgba(239,68,68,.28);}" +
|
|
449
|
+
"#wg-click-pulse[data-tone=success]{border-color:#22C55E;background:rgba(34,197,94,.28);}" +
|
|
435
450
|
"#wg-click-pulse.wg-pulse{animation:wg-pulse .5s ease-out;}" +
|
|
436
451
|
"@keyframes wg-pulse{0%{opacity:.9;transform:scale(.4);}100%{opacity:0;transform:scale(2.4);}}" +
|
|
437
452
|
"#wg-panel{position:fixed;z-index:2147483647;left:50%;bottom:12px;transform:translateX(-50%);" +
|
|
@@ -651,7 +666,11 @@ async function installOverlay(page, title) {
|
|
|
651
666
|
const ring = document.getElementById("wg-ring");
|
|
652
667
|
const ringLabel = document.getElementById("wg-ring-label");
|
|
653
668
|
if (!ring || !ringLabel) return;
|
|
654
|
-
const
|
|
669
|
+
const raw = (tone || "planned") + "";
|
|
670
|
+
const t =
|
|
671
|
+
raw === "auto" || raw === "info" || raw === "warning" || raw === "danger" || raw === "success"
|
|
672
|
+
? raw
|
|
673
|
+
: "planned";
|
|
655
674
|
ring.dataset.tone = t;
|
|
656
675
|
ringLabel.dataset.tone = t;
|
|
657
676
|
const margin = 6;
|
|
@@ -688,7 +707,11 @@ async function installOverlay(page, title) {
|
|
|
688
707
|
window.__wgClickPulse = (x, y, tone) => {
|
|
689
708
|
const pulse = document.getElementById("wg-click-pulse");
|
|
690
709
|
if (!pulse) return;
|
|
691
|
-
|
|
710
|
+
const raw = (tone || "planned") + "";
|
|
711
|
+
pulse.dataset.tone =
|
|
712
|
+
raw === "auto" || raw === "info" || raw === "warning" || raw === "danger" || raw === "success"
|
|
713
|
+
? raw
|
|
714
|
+
: "planned";
|
|
692
715
|
pulse.style.left = x + "px";
|
|
693
716
|
pulse.style.top = y + "px";
|
|
694
717
|
pulse.classList.remove("wg-pulse");
|
|
@@ -1303,7 +1326,7 @@ function resolveDeclaredHighlights(block, resultTag) {
|
|
|
1303
1326
|
if (!Array.isArray(highlights)) return [];
|
|
1304
1327
|
return highlights.filter((h) => h && typeof h.selector === "string" && typeof h.label === "string").map((h) => ({
|
|
1305
1328
|
...h,
|
|
1306
|
-
tone: h.tone
|
|
1329
|
+
tone: normalizeHighlightTone(h.tone),
|
|
1307
1330
|
}));
|
|
1308
1331
|
}
|
|
1309
1332
|
|
|
@@ -1438,14 +1461,22 @@ async function matchStubForLocator(page, locator, stubs) {
|
|
|
1438
1461
|
|
|
1439
1462
|
async function captionForLocator(page, locator, stubs, fallback) {
|
|
1440
1463
|
const matched = await matchStubForLocator(page, locator, stubs);
|
|
1441
|
-
if (matched)
|
|
1464
|
+
if (matched) {
|
|
1465
|
+
return {
|
|
1466
|
+
label: formatHighlightCaption(matched),
|
|
1467
|
+
tone: normalizeHighlightTone(matched.tone),
|
|
1468
|
+
};
|
|
1469
|
+
}
|
|
1442
1470
|
return { label: fallback, tone: "auto" };
|
|
1443
1471
|
}
|
|
1444
1472
|
|
|
1445
1473
|
async function dwellMatchedStub(page, locator, stubs, pacing) {
|
|
1446
1474
|
const matched = await matchStubForLocator(page, locator, stubs);
|
|
1447
1475
|
if (!matched) return;
|
|
1448
|
-
const ms = resolveFixtureDwellMs(matched, {
|
|
1476
|
+
const ms = resolveFixtureDwellMs(matched, {
|
|
1477
|
+
gatesFast: !!(pacing && pacing.gatesFast),
|
|
1478
|
+
pace: pacing && pacing.demoPace,
|
|
1479
|
+
});
|
|
1449
1480
|
if (ms != null && ms > 0) {
|
|
1450
1481
|
await new Promise((res) => setTimeout(res, ms));
|
|
1451
1482
|
}
|
|
@@ -1466,22 +1497,26 @@ async function presentSlides(page, slides, _gate, opts) {
|
|
|
1466
1497
|
const episodeNumber = opts && opts.episodeNumber;
|
|
1467
1498
|
const episodeTitle = (opts && opts.episodeTitle) || "";
|
|
1468
1499
|
const gatesFast = !!(opts && opts.fast);
|
|
1500
|
+
const demoPace = normalizeDemoPace((opts && opts.pace) || (gatesFast ? "fast" : "normal"));
|
|
1469
1501
|
const autoplayMs =
|
|
1470
1502
|
opts && opts.autoplayMs
|
|
1471
1503
|
? Number(opts.autoplayMs)
|
|
1472
1504
|
: process.env.WAYGRAPH_AUTOPLAY_MS
|
|
1473
1505
|
? Number(process.env.WAYGRAPH_AUTOPLAY_MS)
|
|
1474
|
-
:
|
|
1506
|
+
: demoPace === "slow"
|
|
1507
|
+
? 3500
|
|
1508
|
+
: 1800;
|
|
1475
1509
|
for (let i = 0; i < slides.length; i++) {
|
|
1476
1510
|
const s = slides[i];
|
|
1477
1511
|
const caption = formatHighlightCaption(s);
|
|
1512
|
+
const slideTone = normalizeHighlightTone(s.tone);
|
|
1478
1513
|
const isLast = i === slides.length - 1;
|
|
1479
|
-
const dwellMs = resolveFixtureDwellMs(s, { gatesFast });
|
|
1514
|
+
const dwellMs = resolveFixtureDwellMs(s, { gatesFast, pace: demoPace });
|
|
1480
1515
|
await installOverlay(page, title);
|
|
1481
1516
|
if (s.selector) {
|
|
1482
1517
|
try {
|
|
1483
1518
|
const box = await page.locator(s.selector).first().boundingBox();
|
|
1484
|
-
if (box) await showRing(page, box, caption,
|
|
1519
|
+
if (box) await showRing(page, box, caption, slideTone);
|
|
1485
1520
|
} catch {
|
|
1486
1521
|
await hideRing(page);
|
|
1487
1522
|
}
|
|
@@ -1996,7 +2031,7 @@ async function runStepMode(engine, start, end, context, page, mem, resolved, slo
|
|
|
1996
2031
|
// inside the FF (that was the "30s login / cursor gone but still slow" bug).
|
|
1997
2032
|
const demoFast = process.env.WAYGRAPH_DEMO_FAST === "1";
|
|
1998
2033
|
const stepperMode = process.env.WAYGRAPH_STEPPER === "full" ? "full" : "carousel";
|
|
1999
|
-
const pacing = { gatesFast: demoFast, skipTheater: false };
|
|
2034
|
+
const pacing = { gatesFast: demoFast, gatesSlow: false, skipTheater: false, demoPace: "normal" };
|
|
2000
2035
|
const stubBeforeRef = { current: [] };
|
|
2001
2036
|
instrumentInteractionHighlighting(page, mem, slowMo, pacing, stubBeforeRef);
|
|
2002
2037
|
// Force the panel checkbox from this process's flags/env at run start.
|
|
@@ -2087,7 +2122,9 @@ async function runStepMode(engine, start, end, context, page, mem, resolved, slo
|
|
|
2087
2122
|
? Math.min(80, autoplayMs)
|
|
2088
2123
|
: pacing.gatesFast
|
|
2089
2124
|
? Math.min(400, autoplayMs)
|
|
2090
|
-
:
|
|
2125
|
+
: pacing.gatesSlow
|
|
2126
|
+
? Math.max(autoplayMs * 2, 3500)
|
|
2127
|
+
: autoplayMs;
|
|
2091
2128
|
let elapsed = 0;
|
|
2092
2129
|
for (;;) {
|
|
2093
2130
|
// Re-read the checkbox EVERY loop tick, not once up front - a human
|
|
@@ -2171,10 +2208,33 @@ async function runStepMode(engine, start, end, context, page, mem, resolved, slo
|
|
|
2171
2208
|
await resetPageState(context, page, baseURL);
|
|
2172
2209
|
}
|
|
2173
2210
|
// gatesFast / skipTheater: opaque FF, former-FF inners (--ff-disabled/--ff-expand),
|
|
2174
|
-
// or
|
|
2175
|
-
|
|
2211
|
+
// WAYGRAPH_FAST_BLOCKS, or withDemoPace/withBlockPace. --fast alone = shorter
|
|
2212
|
+
// gates only (keeps theater). Episode pace: block > flow > CLI --fast.
|
|
2213
|
+
const stepPace = resolveStepDemoPace({
|
|
2214
|
+
blockPace: r.block.demoPace,
|
|
2215
|
+
flowPace: r.demoPace,
|
|
2216
|
+
fastForward: !!r.block.fastForward,
|
|
2217
|
+
wasFastForward: !!r.wasFastForward,
|
|
2218
|
+
});
|
|
2219
|
+
const cliFast = demoFast || fastBlockNames.has(r.block.name);
|
|
2220
|
+
pacing.demoPace =
|
|
2221
|
+
stepPace === "normal" && cliFast
|
|
2222
|
+
? fastBlockNames.has(r.block.name)
|
|
2223
|
+
? "blitz"
|
|
2224
|
+
: "fast"
|
|
2225
|
+
: stepPace;
|
|
2226
|
+
pacing.gatesFast =
|
|
2227
|
+
pacing.demoPace === "blitz" ||
|
|
2228
|
+
pacing.demoPace === "fast" ||
|
|
2229
|
+
!!r.block.fastForward ||
|
|
2230
|
+
!!r.wasFastForward ||
|
|
2231
|
+
demoFast;
|
|
2232
|
+
pacing.gatesSlow = pacing.demoPace === "slow";
|
|
2176
2233
|
pacing.skipTheater =
|
|
2177
|
-
|
|
2234
|
+
pacing.demoPace === "blitz" ||
|
|
2235
|
+
fastBlockNames.has(r.block.name) ||
|
|
2236
|
+
!!r.block.fastForward ||
|
|
2237
|
+
!!r.wasFastForward;
|
|
2178
2238
|
const fixtures = r.highlightFixtures;
|
|
2179
2239
|
stubBeforeRef.current = resolveHighlightSlots(r.block, "stubBefore", { fixtures });
|
|
2180
2240
|
const isNavBlock = r.block.__waygraphKind === "nav";
|
|
@@ -2273,7 +2333,7 @@ async function runStepMode(engine, start, end, context, page, mem, resolved, slo
|
|
|
2273
2333
|
label: formatHighlightCaption(h),
|
|
2274
2334
|
duration: h.duration,
|
|
2275
2335
|
fastMode: h.fastMode,
|
|
2276
|
-
tone:
|
|
2336
|
+
tone: normalizeHighlightTone(h.tone),
|
|
2277
2337
|
}));
|
|
2278
2338
|
await cycleHighlightRings(page, errHighlights, !!pacing.gatesFast, {
|
|
2279
2339
|
defaultHoldMs: 2000,
|
|
@@ -2333,6 +2393,7 @@ async function runStepMode(engine, start, end, context, page, mem, resolved, slo
|
|
|
2333
2393
|
title,
|
|
2334
2394
|
blockName: r.block.name,
|
|
2335
2395
|
fast: pacing.gatesFast,
|
|
2396
|
+
pace: pacing.demoPace,
|
|
2336
2397
|
episodeNumber: r.episodeNumber,
|
|
2337
2398
|
episodeTitle: r.episodeTitle,
|
|
2338
2399
|
autoplayMs,
|
|
@@ -2346,7 +2407,7 @@ async function runStepMode(engine, start, end, context, page, mem, resolved, slo
|
|
|
2346
2407
|
label: formatHighlightCaption(h),
|
|
2347
2408
|
duration: h.duration,
|
|
2348
2409
|
fastMode: h.fastMode,
|
|
2349
|
-
tone:
|
|
2410
|
+
tone: normalizeHighlightTone(h.tone),
|
|
2350
2411
|
}),
|
|
2351
2412
|
);
|
|
2352
2413
|
} else {
|
|
@@ -2531,6 +2592,7 @@ async function main() {
|
|
|
2531
2592
|
exportName: bi.name,
|
|
2532
2593
|
seedMem: idx === 0 ? seedMem : undefined,
|
|
2533
2594
|
highlightFixtures: flow.highlightFixtures,
|
|
2595
|
+
demoPace: flow.demoPace,
|
|
2534
2596
|
expectedFailureReason:
|
|
2535
2597
|
flow.expectedFailureReason && idx === blockInfos.length - 1
|
|
2536
2598
|
? flow.expectedFailureReason
|
|
@@ -2599,6 +2661,7 @@ async function main() {
|
|
|
2599
2661
|
episodeTitle: flow.title || seg.ref,
|
|
2600
2662
|
expectedFailureReason: flow.expectedFailureReason,
|
|
2601
2663
|
highlightFixtures: flow.highlightFixtures,
|
|
2664
|
+
demoPace: flow.demoPace,
|
|
2602
2665
|
seedMem: () => seedMemForFlow(mem, flow.blocks(), seg.json, seg.ref),
|
|
2603
2666
|
});
|
|
2604
2667
|
} else {
|
|
@@ -2608,6 +2671,7 @@ async function main() {
|
|
|
2608
2671
|
episodeNumber: undefined,
|
|
2609
2672
|
episodeTitle: undefined,
|
|
2610
2673
|
highlightFixtures: undefined,
|
|
2674
|
+
demoPace: undefined,
|
|
2611
2675
|
seedMem: () => seedMemForBlock(mem, r, seg.json),
|
|
2612
2676
|
});
|
|
2613
2677
|
}
|
|
@@ -2632,6 +2696,7 @@ async function main() {
|
|
|
2632
2696
|
episodeNumber: meta.episodeNumber,
|
|
2633
2697
|
episodeTitle: meta.episodeTitle,
|
|
2634
2698
|
highlightFixtures: meta.highlightFixtures,
|
|
2699
|
+
demoPace: meta.demoPace,
|
|
2635
2700
|
expectedFailureReason:
|
|
2636
2701
|
meta.expectedFailureReason && remainingInFlow === 1 ? meta.expectedFailureReason : undefined,
|
|
2637
2702
|
seedMem: isFirstOfSegment ? meta.seedMem : undefined,
|
package/dist/engine.d.ts
CHANGED
|
@@ -186,6 +186,11 @@ export interface Flow<Out extends Checkpoint<string>> {
|
|
|
186
186
|
* block.name. `run()` never reads this; step/`demo` merges onto block stubs.
|
|
187
187
|
*/
|
|
188
188
|
readonly highlightFixtures?: import("./highlights.js").HighlightFixtureMap;
|
|
189
|
+
/**
|
|
190
|
+
* Demo pacing for this Flow's episode (`withDemoPace`).
|
|
191
|
+
* `run()` ignores; step/demo applies per Block in the episode.
|
|
192
|
+
*/
|
|
193
|
+
readonly demoPace?: import("./highlights.js").DemoPace;
|
|
189
194
|
/**
|
|
190
195
|
* This Flow's constituent Blocks, in order between `start`/`end`, as plain
|
|
191
196
|
* data - for introspection/visualization tools, without running anything.
|
|
@@ -253,6 +258,18 @@ export declare function withSessionReset<Out extends Checkpoint<string>>(flow: F
|
|
|
253
258
|
* @example const ticket123 = withTitle(loginFlow, "Ticket #123 - Sales rep signs in");
|
|
254
259
|
*/
|
|
255
260
|
export declare function withTitle<Out extends Checkpoint<string>>(flow: Flow<Out>, title: string): Flow<Out>;
|
|
261
|
+
/**
|
|
262
|
+
* Demo pacing for a whole Flow episode (fast review vs slow gap/wrong walkthrough).
|
|
263
|
+
* Non-destructive. `fastForwardComposeBlock` is always blitz for its own step;
|
|
264
|
+
* use this when an entire episode should be fast or slow.
|
|
265
|
+
* @example withDemoPace(withTitle(gapFlow, "Episode 2 - gaps"), "slow")
|
|
266
|
+
*/
|
|
267
|
+
export declare function withDemoPace<Out extends Checkpoint<string>>(flow: Flow<Out>, pace: import("./highlights.js").DemoPace): Flow<Out>;
|
|
268
|
+
/**
|
|
269
|
+
* Demo pacing for one Block or compose unit (not FF - use fastForwardComposeBlock for blitz).
|
|
270
|
+
* @example withBlockPace(composeBlock("gap-review", [...]), "slow")
|
|
271
|
+
*/
|
|
272
|
+
export declare function withBlockPace<In extends Checkpoint<string>, Out extends Checkpoint<string>>(block: Block<In, Out>, pace: import("./highlights.js").DemoPace): Block<In, Out>;
|
|
256
273
|
/**
|
|
257
274
|
* Marks a Flow as one that's SUPPOSED to throw - e.g. a locked-out user's
|
|
258
275
|
* login attempt genuinely failing, demonstrating the app's own real
|
package/dist/engine.js
CHANGED
|
@@ -351,6 +351,31 @@ export function withTitle(flow, title) {
|
|
|
351
351
|
modBlockVerify: (block, nameOrIndex, newCheck) => withTitle(flow.modBlockVerify(block, nameOrIndex, newCheck), title),
|
|
352
352
|
};
|
|
353
353
|
}
|
|
354
|
+
/**
|
|
355
|
+
* Demo pacing for a whole Flow episode (fast review vs slow gap/wrong walkthrough).
|
|
356
|
+
* Non-destructive. `fastForwardComposeBlock` is always blitz for its own step;
|
|
357
|
+
* use this when an entire episode should be fast or slow.
|
|
358
|
+
* @example withDemoPace(withTitle(gapFlow, "Episode 2 - gaps"), "slow")
|
|
359
|
+
*/
|
|
360
|
+
export function withDemoPace(flow, pace) {
|
|
361
|
+
const demoPace = pace;
|
|
362
|
+
return {
|
|
363
|
+
...flow,
|
|
364
|
+
demoPace,
|
|
365
|
+
withBlockVerify: (block, verify) => withDemoPace(flow.withBlockVerify(block, verify), demoPace),
|
|
366
|
+
modBlockVerify: (block, nameOrIndex, newCheck) => withDemoPace(flow.modBlockVerify(block, nameOrIndex, newCheck), demoPace),
|
|
367
|
+
};
|
|
368
|
+
}
|
|
369
|
+
/**
|
|
370
|
+
* Demo pacing for one Block or compose unit (not FF - use fastForwardComposeBlock for blitz).
|
|
371
|
+
* @example withBlockPace(composeBlock("gap-review", [...]), "slow")
|
|
372
|
+
*/
|
|
373
|
+
export function withBlockPace(block, pace) {
|
|
374
|
+
return {
|
|
375
|
+
...block,
|
|
376
|
+
demoPace: pace,
|
|
377
|
+
};
|
|
378
|
+
}
|
|
354
379
|
/**
|
|
355
380
|
* Marks a Flow as one that's SUPPOSED to throw - e.g. a locked-out user's
|
|
356
381
|
* login attempt genuinely failing, demonstrating the app's own real
|
package/dist/highlights.d.ts
CHANGED
|
@@ -33,9 +33,16 @@ export interface WaygraphHighlightStub extends FixtureDurationFields {
|
|
|
33
33
|
detail?: string;
|
|
34
34
|
/** Short badge, e.g. AC / BUG / GATE / YAP. */
|
|
35
35
|
tag?: string;
|
|
36
|
+
/**
|
|
37
|
+
* Demo ring color + icon:
|
|
38
|
+
* - `planned` purple (authored narration, default)
|
|
39
|
+
* - `auto` gray (engine automation / verify fallback)
|
|
40
|
+
* - `info` blue · `warning` yellow · `danger` red · `success` green
|
|
41
|
+
*/
|
|
42
|
+
tone?: HighlightTone;
|
|
36
43
|
}
|
|
37
44
|
/** Flow fixture patch: label required; selector optional (inherits from stub). */
|
|
38
|
-
export type WaygraphHighlightFixture = Partial<Pick<WaygraphHighlightStub, "selector">> & Required<Pick<WaygraphHighlightStub, "label">> & Pick<WaygraphHighlightStub, "detail" | "tag"> & FixtureDurationFields;
|
|
45
|
+
export type WaygraphHighlightFixture = Partial<Pick<WaygraphHighlightStub, "selector">> & Required<Pick<WaygraphHighlightStub, "label">> & Pick<WaygraphHighlightStub, "detail" | "tag" | "tone"> & FixtureDurationFields;
|
|
39
46
|
export type HighlightStubPhase = Record<string, WaygraphHighlightStub>;
|
|
40
47
|
export type HighlightStubPhaseOrFn<Out extends Checkpoint<string>> = HighlightStubPhase | ((out: Out) => HighlightStubPhase);
|
|
41
48
|
/**
|
|
@@ -49,11 +56,32 @@ export interface WaygraphSlide extends FixtureDurationFields {
|
|
|
49
56
|
tag?: string;
|
|
50
57
|
/** Optional ring while this slide is showing. */
|
|
51
58
|
selector?: string;
|
|
59
|
+
tone?: HighlightTone;
|
|
52
60
|
}
|
|
61
|
+
/**
|
|
62
|
+
* Demo ring tones (iconified).
|
|
63
|
+
* Automation (`auto`) is gray so authored planned/info/warning/danger/success stand out.
|
|
64
|
+
*/
|
|
65
|
+
export type HighlightTone = "planned" | "auto" | "info" | "warning" | "danger" | "success";
|
|
66
|
+
/** Map author aliases (`error` -> danger) to a canonical tone. */
|
|
67
|
+
export declare function normalizeHighlightTone(raw: unknown): HighlightTone;
|
|
68
|
+
/** Prefix label with a short ASCII icon for semantic tones. */
|
|
69
|
+
export declare function toneIconPrefix(tone: HighlightTone): string;
|
|
70
|
+
/**
|
|
71
|
+
* Demo pacing for a Flow episode or a Block/compose group.
|
|
72
|
+
* - `blitz` - FF-like: skip theater + short gates (same as fastForwardComposeBlock)
|
|
73
|
+
* - `fast` - shorter gates, keep cursor theater
|
|
74
|
+
* - `normal` - default demo pace
|
|
75
|
+
* - `slow` - longer autoplay + fixture dwell (gaps / wrongs review)
|
|
76
|
+
*/
|
|
77
|
+
export type DemoPace = "blitz" | "fast" | "normal" | "slow";
|
|
78
|
+
export declare function normalizeDemoPace(raw: unknown): DemoPace;
|
|
53
79
|
/** Default fixture dwell when `duration: true`. */
|
|
54
80
|
export declare const FIXTURE_DURATION_MS_DEFAULT = 2000;
|
|
55
81
|
/** Default fixture dwell under `--fast` when duration is enabled. */
|
|
56
82
|
export declare const FIXTURE_DURATION_FAST_MS_DEFAULT = 600;
|
|
83
|
+
/** Default fixture dwell under demo pace `slow` (gaps / wrongs review). */
|
|
84
|
+
export declare const FIXTURE_DURATION_SLOW_MS_DEFAULT = 4000;
|
|
57
85
|
/** @deprecated Prefer FIXTURE_DURATION_MS_DEFAULT */
|
|
58
86
|
export declare const SLIDE_DURATION_MS_DEFAULT = 2000;
|
|
59
87
|
/** @deprecated Prefer FIXTURE_DURATION_FAST_MS_DEFAULT */
|
|
@@ -64,11 +92,23 @@ export declare const SLIDE_DURATION_FAST_MS_DEFAULT = 600;
|
|
|
64
92
|
*/
|
|
65
93
|
export declare function resolveFixtureDwellMs(fixture: FixtureDurationFields, opts?: {
|
|
66
94
|
gatesFast?: boolean;
|
|
95
|
+
pace?: DemoPace;
|
|
67
96
|
}): number | null;
|
|
68
97
|
/** @deprecated Prefer {@link resolveFixtureDwellMs} */
|
|
69
98
|
export declare function resolveSlideDwellMs(slide: FixtureDurationFields, opts?: {
|
|
70
99
|
gatesFast?: boolean;
|
|
100
|
+
pace?: DemoPace;
|
|
71
101
|
}): number | null;
|
|
102
|
+
/**
|
|
103
|
+
* Effective demo pace for a step: block override > flow episode > normal.
|
|
104
|
+
* Opaque FF / wasFastForward always win as blitz.
|
|
105
|
+
*/
|
|
106
|
+
export declare function resolveStepDemoPace(opts: {
|
|
107
|
+
blockPace?: DemoPace | string | null;
|
|
108
|
+
flowPace?: DemoPace | string | null;
|
|
109
|
+
fastForward?: boolean;
|
|
110
|
+
wasFastForward?: boolean;
|
|
111
|
+
}): DemoPace;
|
|
72
112
|
export type WaygraphSlidesOrFn<Out extends Checkpoint<string>> = readonly WaygraphSlide[] | ((out: Out) => readonly WaygraphSlide[]);
|
|
73
113
|
/** Demo stub phase names (block instruction + flow fixtures). */
|
|
74
114
|
export type HighlightStubPhaseName = "stubBefore" | "stubAfter" | "stubOnError";
|
|
@@ -85,6 +125,7 @@ export type HighlightFixtureMap = Record<string, {
|
|
|
85
125
|
export interface WaygraphHighlight {
|
|
86
126
|
selector: string;
|
|
87
127
|
label: string;
|
|
128
|
+
tone?: HighlightTone;
|
|
88
129
|
}
|
|
89
130
|
export type ResolvedHighlight = WaygraphHighlightStub;
|
|
90
131
|
/**
|
|
@@ -104,12 +145,13 @@ export declare function resolveSlides(block: Block<any, any>, opts?: {
|
|
|
104
145
|
out?: Checkpoint<string>;
|
|
105
146
|
fixtures?: HighlightFixtureMap;
|
|
106
147
|
}): WaygraphSlide[];
|
|
107
|
-
/** Caption for ring / slide UI (label|caption + optional detail/tag). */
|
|
148
|
+
/** Caption for ring / slide UI (label|caption + optional detail/tag + tone icon). */
|
|
108
149
|
export declare function formatHighlightCaption(h: {
|
|
109
150
|
label?: string;
|
|
110
151
|
caption?: string;
|
|
111
152
|
detail?: string;
|
|
112
153
|
tag?: string;
|
|
154
|
+
tone?: HighlightTone | string;
|
|
113
155
|
}): string;
|
|
114
156
|
/**
|
|
115
157
|
* True when the block authored a non-empty stubAfter (after resolve + shim),
|
package/dist/highlights.js
CHANGED
|
@@ -8,10 +8,56 @@
|
|
|
8
8
|
* All fixture shapes share optional {@link FixtureDurationFields} so demo dwell
|
|
9
9
|
* before advancing is authored the same way on stubs, flow fixtures, and slides.
|
|
10
10
|
*/
|
|
11
|
+
const TONE_ICONS = {
|
|
12
|
+
planned: "",
|
|
13
|
+
auto: "",
|
|
14
|
+
info: "i",
|
|
15
|
+
warning: "!",
|
|
16
|
+
danger: "x",
|
|
17
|
+
success: "+",
|
|
18
|
+
};
|
|
19
|
+
/** Map author aliases (`error` -> danger) to a canonical tone. */
|
|
20
|
+
export function normalizeHighlightTone(raw) {
|
|
21
|
+
if (typeof raw !== "string")
|
|
22
|
+
return "planned";
|
|
23
|
+
const t = raw.trim().toLowerCase();
|
|
24
|
+
if (t === "auto" || t === "automation" || t === "engine")
|
|
25
|
+
return "auto";
|
|
26
|
+
if (t === "info" || t === "blue")
|
|
27
|
+
return "info";
|
|
28
|
+
if (t === "warning" || t === "warn" || t === "yellow")
|
|
29
|
+
return "warning";
|
|
30
|
+
if (t === "danger" || t === "error" || t === "red")
|
|
31
|
+
return "danger";
|
|
32
|
+
if (t === "success" || t === "ok" || t === "green")
|
|
33
|
+
return "success";
|
|
34
|
+
if (t === "planned" || t === "purple" || t === "authored")
|
|
35
|
+
return "planned";
|
|
36
|
+
return "planned";
|
|
37
|
+
}
|
|
38
|
+
/** Prefix label with a short ASCII icon for semantic tones. */
|
|
39
|
+
export function toneIconPrefix(tone) {
|
|
40
|
+
const icon = TONE_ICONS[tone];
|
|
41
|
+
return icon ? `[${icon}] ` : "";
|
|
42
|
+
}
|
|
43
|
+
export function normalizeDemoPace(raw) {
|
|
44
|
+
if (typeof raw !== "string")
|
|
45
|
+
return "normal";
|
|
46
|
+
const t = raw.trim().toLowerCase();
|
|
47
|
+
if (t === "blitz" || t === "ff")
|
|
48
|
+
return "blitz";
|
|
49
|
+
if (t === "fast" || t === "quick")
|
|
50
|
+
return "fast";
|
|
51
|
+
if (t === "slow" || t === "careful" || t === "review")
|
|
52
|
+
return "slow";
|
|
53
|
+
return "normal";
|
|
54
|
+
}
|
|
11
55
|
/** Default fixture dwell when `duration: true`. */
|
|
12
56
|
export const FIXTURE_DURATION_MS_DEFAULT = 2000;
|
|
13
57
|
/** Default fixture dwell under `--fast` when duration is enabled. */
|
|
14
58
|
export const FIXTURE_DURATION_FAST_MS_DEFAULT = 600;
|
|
59
|
+
/** Default fixture dwell under demo pace `slow` (gaps / wrongs review). */
|
|
60
|
+
export const FIXTURE_DURATION_SLOW_MS_DEFAULT = 4000;
|
|
15
61
|
/** @deprecated Prefer FIXTURE_DURATION_MS_DEFAULT */
|
|
16
62
|
export const SLIDE_DURATION_MS_DEFAULT = FIXTURE_DURATION_MS_DEFAULT;
|
|
17
63
|
/** @deprecated Prefer FIXTURE_DURATION_FAST_MS_DEFAULT */
|
|
@@ -23,23 +69,40 @@ export const SLIDE_DURATION_FAST_MS_DEFAULT = FIXTURE_DURATION_FAST_MS_DEFAULT;
|
|
|
23
69
|
export function resolveFixtureDwellMs(fixture, opts) {
|
|
24
70
|
if (fixture.duration === undefined || fixture.duration === false)
|
|
25
71
|
return null;
|
|
26
|
-
const
|
|
72
|
+
const pace = normalizeDemoPace(opts?.pace ?? (opts?.gatesFast ? "fast" : "normal"));
|
|
27
73
|
const fastMs = typeof fixture.fastMode === "number" && Number.isFinite(fixture.fastMode) && fixture.fastMode >= 0
|
|
28
74
|
? fixture.fastMode
|
|
29
75
|
: FIXTURE_DURATION_FAST_MS_DEFAULT;
|
|
30
|
-
if (fast)
|
|
76
|
+
if (pace === "blitz" || pace === "fast" || opts?.gatesFast)
|
|
31
77
|
return fastMs;
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
78
|
+
const normalMs = fixture.duration === true
|
|
79
|
+
? FIXTURE_DURATION_MS_DEFAULT
|
|
80
|
+
: typeof fixture.duration === "number" && Number.isFinite(fixture.duration) && fixture.duration >= 0
|
|
81
|
+
? fixture.duration
|
|
82
|
+
: FIXTURE_DURATION_MS_DEFAULT;
|
|
83
|
+
if (pace === "slow")
|
|
84
|
+
return Math.max(normalMs, FIXTURE_DURATION_SLOW_MS_DEFAULT);
|
|
85
|
+
return normalMs;
|
|
38
86
|
}
|
|
39
87
|
/** @deprecated Prefer {@link resolveFixtureDwellMs} */
|
|
40
88
|
export function resolveSlideDwellMs(slide, opts) {
|
|
41
89
|
return resolveFixtureDwellMs(slide, opts);
|
|
42
90
|
}
|
|
91
|
+
/**
|
|
92
|
+
* Effective demo pace for a step: block override > flow episode > normal.
|
|
93
|
+
* Opaque FF / wasFastForward always win as blitz.
|
|
94
|
+
*/
|
|
95
|
+
export function resolveStepDemoPace(opts) {
|
|
96
|
+
if (opts.fastForward || opts.wasFastForward)
|
|
97
|
+
return "blitz";
|
|
98
|
+
if (opts.blockPace != null && opts.blockPace !== "") {
|
|
99
|
+
return normalizeDemoPace(opts.blockPace);
|
|
100
|
+
}
|
|
101
|
+
if (opts.flowPace != null && opts.flowPace !== "") {
|
|
102
|
+
return normalizeDemoPace(opts.flowPace);
|
|
103
|
+
}
|
|
104
|
+
return "normal";
|
|
105
|
+
}
|
|
43
106
|
function isStubPhase(v) {
|
|
44
107
|
return !!v && typeof v === "object" && !Array.isArray(v);
|
|
45
108
|
}
|
|
@@ -65,6 +128,7 @@ function mergeSlot(base, patch) {
|
|
|
65
128
|
label: patch.label,
|
|
66
129
|
...(patch.detail ? { detail: patch.detail } : {}),
|
|
67
130
|
...(patch.tag ? { tag: patch.tag } : {}),
|
|
131
|
+
...(patch.tone ? { tone: normalizeHighlightTone(patch.tone) } : {}),
|
|
68
132
|
...dwell,
|
|
69
133
|
};
|
|
70
134
|
}
|
|
@@ -79,6 +143,11 @@ function mergeSlot(base, patch) {
|
|
|
79
143
|
? { detail: base.detail }
|
|
80
144
|
: {}),
|
|
81
145
|
...(patch.tag !== undefined ? { tag: patch.tag } : base.tag ? { tag: base.tag } : {}),
|
|
146
|
+
...(patch.tone !== undefined
|
|
147
|
+
? { tone: normalizeHighlightTone(patch.tone) }
|
|
148
|
+
: base.tone
|
|
149
|
+
? { tone: normalizeHighlightTone(base.tone) }
|
|
150
|
+
: {}),
|
|
82
151
|
...dwell,
|
|
83
152
|
};
|
|
84
153
|
}
|
|
@@ -88,7 +157,11 @@ function phaseFromLegacyHighlights(highlights) {
|
|
|
88
157
|
return out;
|
|
89
158
|
highlights.forEach((h, i) => {
|
|
90
159
|
if (h && typeof h.selector === "string" && typeof h.label === "string") {
|
|
91
|
-
out[String(i)] = {
|
|
160
|
+
out[String(i)] = {
|
|
161
|
+
selector: h.selector,
|
|
162
|
+
label: h.label,
|
|
163
|
+
...(h.tone ? { tone: normalizeHighlightTone(h.tone) } : {}),
|
|
164
|
+
};
|
|
92
165
|
}
|
|
93
166
|
});
|
|
94
167
|
return out;
|
|
@@ -169,13 +242,15 @@ export function resolveSlides(block, opts) {
|
|
|
169
242
|
return [];
|
|
170
243
|
return raw.filter((s) => s && typeof s.caption === "string" && s.caption.length > 0);
|
|
171
244
|
}
|
|
172
|
-
/** Caption for ring / slide UI (label|caption + optional detail/tag). */
|
|
245
|
+
/** Caption for ring / slide UI (label|caption + optional detail/tag + tone icon). */
|
|
173
246
|
export function formatHighlightCaption(h) {
|
|
174
|
-
const
|
|
247
|
+
const tone = normalizeHighlightTone(h.tone);
|
|
248
|
+
const icon = toneIconPrefix(tone);
|
|
249
|
+
const primary = (h.label ?? h.caption ?? "").trim();
|
|
175
250
|
const tag = h.tag ? `[${h.tag}] ` : "";
|
|
176
251
|
if (h.detail)
|
|
177
|
-
return `${tag}${primary} - ${h.detail}`;
|
|
178
|
-
return `${tag}${primary}`;
|
|
252
|
+
return `${icon}${tag}${primary} - ${h.detail}`;
|
|
253
|
+
return `${icon}${tag}${primary}`;
|
|
179
254
|
}
|
|
180
255
|
/**
|
|
181
256
|
* True when the block authored a non-empty stubAfter (after resolve + shim),
|
package/dist/index.d.ts
CHANGED
|
@@ -2,9 +2,9 @@ export type { Checkpoint, Instruction, Block, DefinedBlock, Start, WaygraphInsta
|
|
|
2
2
|
export { connect, checkpoint } from "./types.js";
|
|
3
3
|
export { MemKey, MemPage, key, keyGroup } from "./mem-page.js";
|
|
4
4
|
export { Trait, urlMatches, textEquals, visible } from "./trait.js";
|
|
5
|
-
export { runGraph, spawnTab, narrate, Engine, start, end, branch, withVerify, modVerify, modVerifyAll, defineBlock, defineNavBlock, defineNavClickBlock, defineMethodBlock, defineActionBlock, definePageBlock, defineEffectBlock, defineMemEffectBlock, defineMemNavBlock, locate, composeBlock, fastForwardComposeBlock, isFastForwardBlock, preflight, withSessionReset, withTitle, withExpectedFailure, withHighlightFixtures, chainFlow, } from "./engine.js";
|
|
6
|
-
export { resolveHighlightSlots, resolveSlides, resolveFixtureDwellMs, resolveSlideDwellMs, formatHighlightCaption, hasAuthoredStubAfter, hasAuthoredStubOnError, FIXTURE_DURATION_MS_DEFAULT, FIXTURE_DURATION_FAST_MS_DEFAULT, SLIDE_DURATION_MS_DEFAULT, SLIDE_DURATION_FAST_MS_DEFAULT, } from "./highlights.js";
|
|
7
|
-
export type { WaygraphHighlightStub, WaygraphHighlightFixture, WaygraphSlide, FixtureDurationFields, HighlightStubPhase, HighlightStubPhaseName, HighlightFixtureMap, ResolvedHighlight, WaygraphHighlight, } from "./highlights.js";
|
|
5
|
+
export { runGraph, spawnTab, narrate, Engine, start, end, branch, withVerify, modVerify, modVerifyAll, defineBlock, defineNavBlock, defineNavClickBlock, defineMethodBlock, defineActionBlock, definePageBlock, defineEffectBlock, defineMemEffectBlock, defineMemNavBlock, locate, composeBlock, fastForwardComposeBlock, isFastForwardBlock, preflight, withSessionReset, withTitle, withDemoPace, withBlockPace, withExpectedFailure, withHighlightFixtures, chainFlow, } from "./engine.js";
|
|
6
|
+
export { resolveHighlightSlots, resolveSlides, resolveFixtureDwellMs, resolveSlideDwellMs, formatHighlightCaption, hasAuthoredStubAfter, hasAuthoredStubOnError, normalizeHighlightTone, normalizeDemoPace, toneIconPrefix, resolveStepDemoPace, FIXTURE_DURATION_MS_DEFAULT, FIXTURE_DURATION_FAST_MS_DEFAULT, FIXTURE_DURATION_SLOW_MS_DEFAULT, SLIDE_DURATION_MS_DEFAULT, SLIDE_DURATION_FAST_MS_DEFAULT, } from "./highlights.js";
|
|
7
|
+
export type { WaygraphHighlightStub, WaygraphHighlightFixture, WaygraphSlide, FixtureDurationFields, HighlightStubPhase, HighlightStubPhaseName, HighlightFixtureMap, ResolvedHighlight, WaygraphHighlight, HighlightTone, DemoPace, } from "./highlights.js";
|
|
8
8
|
export type { Flow, EngineConfig, ComposedBlock, FastForwardComposedBlock, RunGraphOptions, BlockInfo, NavBlock, NavBlockOptions, NavClickBlock, NavClickBlockOptions, MethodBlock, ActionBlock, PageBlock, PageBlockOptions, PageMethodEntry, EffectBlock, MemEffectBlock, MemNavBlock, } from "./engine.js";
|
|
9
9
|
export type { ActionPage } from "./types.js";
|
|
10
10
|
export { discoverGraph, toMermaid, findOrphanBlocks, findBlockPath } from "./graph.js";
|
package/dist/index.js
CHANGED
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
export { connect, checkpoint } from "./types.js";
|
|
2
2
|
export { MemKey, MemPage, key, keyGroup } from "./mem-page.js";
|
|
3
3
|
export { Trait, urlMatches, textEquals, visible } from "./trait.js";
|
|
4
|
-
export { runGraph, spawnTab, narrate, Engine, start, end, branch, withVerify, modVerify, modVerifyAll, defineBlock, defineNavBlock, defineNavClickBlock, defineMethodBlock, defineActionBlock, definePageBlock, defineEffectBlock, defineMemEffectBlock, defineMemNavBlock, locate, composeBlock, fastForwardComposeBlock, isFastForwardBlock, preflight, withSessionReset, withTitle, withExpectedFailure, withHighlightFixtures, chainFlow, } from "./engine.js";
|
|
5
|
-
export { resolveHighlightSlots, resolveSlides, resolveFixtureDwellMs, resolveSlideDwellMs, formatHighlightCaption, hasAuthoredStubAfter, hasAuthoredStubOnError, FIXTURE_DURATION_MS_DEFAULT, FIXTURE_DURATION_FAST_MS_DEFAULT, SLIDE_DURATION_MS_DEFAULT, SLIDE_DURATION_FAST_MS_DEFAULT, } from "./highlights.js";
|
|
4
|
+
export { runGraph, spawnTab, narrate, Engine, start, end, branch, withVerify, modVerify, modVerifyAll, defineBlock, defineNavBlock, defineNavClickBlock, defineMethodBlock, defineActionBlock, definePageBlock, defineEffectBlock, defineMemEffectBlock, defineMemNavBlock, locate, composeBlock, fastForwardComposeBlock, isFastForwardBlock, preflight, withSessionReset, withTitle, withDemoPace, withBlockPace, withExpectedFailure, withHighlightFixtures, chainFlow, } from "./engine.js";
|
|
5
|
+
export { resolveHighlightSlots, resolveSlides, resolveFixtureDwellMs, resolveSlideDwellMs, formatHighlightCaption, hasAuthoredStubAfter, hasAuthoredStubOnError, normalizeHighlightTone, normalizeDemoPace, toneIconPrefix, resolveStepDemoPace, FIXTURE_DURATION_MS_DEFAULT, FIXTURE_DURATION_FAST_MS_DEFAULT, FIXTURE_DURATION_SLOW_MS_DEFAULT, SLIDE_DURATION_MS_DEFAULT, SLIDE_DURATION_FAST_MS_DEFAULT, } from "./highlights.js";
|
|
6
6
|
export { discoverGraph, toMermaid, findOrphanBlocks, findBlockPath } from "./graph.js";
|
|
7
7
|
export { isFileSelectToken, parseBlocksSelect, matchBlocksSelect, globToRegExp, } from "./blocks-select.js";
|
|
8
8
|
export { EdgeLeaseCoordinator } from "./traverse-lease.js";
|
package/dist/step-overlay.d.ts
CHANGED
|
@@ -3,7 +3,7 @@ import type { MemPage } from "./mem-page.js";
|
|
|
3
3
|
export declare function installDemoChrome(page: Page, title?: string, options?: {
|
|
4
4
|
banner?: boolean;
|
|
5
5
|
}): Promise<void>;
|
|
6
|
-
/** Demo cursor + ring on fill/click during auto explore headful runs (automation =
|
|
6
|
+
/** Demo cursor + ring on fill/click during auto explore headful runs (automation = gray). */
|
|
7
7
|
export declare function instrumentInteractionHighlighting(page: Page, mem: MemPage, slowMo: number): void;
|
|
8
8
|
declare global {
|
|
9
9
|
interface Window {
|
package/dist/step-overlay.js
CHANGED
|
@@ -1,11 +1,20 @@
|
|
|
1
1
|
const RING_CSS = "#wg-ring{position:fixed;z-index:2147483646;pointer-events:none;opacity:0;" +
|
|
2
2
|
"border:2.5px solid #7C3AED;border-radius:10px;box-shadow:0 0 0 4px rgba(124,58,237,.16);" +
|
|
3
3
|
"transition:opacity .3s ease,border-color .15s,box-shadow .15s;}" +
|
|
4
|
-
|
|
4
|
+
// Automation = gray; semantic tones for authored highlights.
|
|
5
|
+
"#wg-ring[data-tone=auto]{border-color:#9CA3AF;box-shadow:0 0 0 4px rgba(156,163,175,.28);}" +
|
|
6
|
+
"#wg-ring[data-tone=info]{border-color:#3B82F6;box-shadow:0 0 0 4px rgba(59,130,246,.22);}" +
|
|
7
|
+
"#wg-ring[data-tone=warning]{border-color:#EAB308;box-shadow:0 0 0 4px rgba(234,179,8,.22);}" +
|
|
8
|
+
"#wg-ring[data-tone=danger]{border-color:#EF4444;box-shadow:0 0 0 4px rgba(239,68,68,.22);}" +
|
|
9
|
+
"#wg-ring[data-tone=success]{border-color:#22C55E;box-shadow:0 0 0 4px rgba(34,197,94,.22);}" +
|
|
5
10
|
"#wg-ring-label{position:fixed;z-index:2147483646;pointer-events:none;opacity:0;" +
|
|
6
11
|
"white-space:nowrap;padding:4px 9px;border-radius:7px;background:#7C3AED;color:#fff;" +
|
|
7
12
|
"font:600 12px/1.2 system-ui,sans-serif;transition:opacity .3s ease,background .15s,color .15s;}" +
|
|
8
|
-
"#wg-ring-label[data-tone=auto]{background:#
|
|
13
|
+
"#wg-ring-label[data-tone=auto]{background:#6B7280;color:#fff;}" +
|
|
14
|
+
"#wg-ring-label[data-tone=info]{background:#2563EB;color:#fff;}" +
|
|
15
|
+
"#wg-ring-label[data-tone=warning]{background:#EAB308;color:#1c1917;}" +
|
|
16
|
+
"#wg-ring-label[data-tone=danger]{background:#DC2626;color:#fff;}" +
|
|
17
|
+
"#wg-ring-label[data-tone=success]{background:#16A34A;color:#fff;}" +
|
|
9
18
|
"#wg-cursor{position:fixed;z-index:2147483647;width:24px;height:24px;pointer-events:none;" +
|
|
10
19
|
"left:0;top:0;opacity:0;margin:0;" +
|
|
11
20
|
"transition:transform var(--wg-cursor-ms,600ms) cubic-bezier(.22,1,.36,1),opacity .2s ease;" +
|
|
@@ -13,7 +22,11 @@ const RING_CSS = "#wg-ring{position:fixed;z-index:2147483646;pointer-events:none
|
|
|
13
22
|
"#wg-click-pulse{position:fixed;z-index:2147483647;width:14px;height:14px;" +
|
|
14
23
|
"margin-left:-7px;margin-top:-7px;border-radius:50%;pointer-events:none;opacity:0;" +
|
|
15
24
|
"border:2px solid #7C3AED;background:rgba(124,58,237,.25);}" +
|
|
16
|
-
"#wg-click-pulse[data-tone=auto]{border-color:#
|
|
25
|
+
"#wg-click-pulse[data-tone=auto]{border-color:#9CA3AF;background:rgba(156,163,175,.28);}" +
|
|
26
|
+
"#wg-click-pulse[data-tone=info]{border-color:#3B82F6;background:rgba(59,130,246,.28);}" +
|
|
27
|
+
"#wg-click-pulse[data-tone=warning]{border-color:#EAB308;background:rgba(234,179,8,.28);}" +
|
|
28
|
+
"#wg-click-pulse[data-tone=danger]{border-color:#EF4444;background:rgba(239,68,68,.28);}" +
|
|
29
|
+
"#wg-click-pulse[data-tone=success]{border-color:#22C55E;background:rgba(34,197,94,.28);}" +
|
|
17
30
|
"#wg-click-pulse.wg-pulse{animation:wg-pulse .5s ease-out;}" +
|
|
18
31
|
"@keyframes wg-pulse{0%{opacity:.9;transform:scale(.4);}100%{opacity:0;transform:scale(2.4);}}" +
|
|
19
32
|
"#wg-banner{position:fixed;z-index:2147483647;top:14px;left:14px;" +
|
|
@@ -65,7 +78,15 @@ export async function installDemoChrome(page, title = "waygraph auto", options =
|
|
|
65
78
|
const pulse = document.getElementById("wg-click-pulse");
|
|
66
79
|
if (!pulse)
|
|
67
80
|
return;
|
|
68
|
-
|
|
81
|
+
const raw = (tone || "planned") + "";
|
|
82
|
+
pulse.dataset.tone =
|
|
83
|
+
raw === "auto" ||
|
|
84
|
+
raw === "info" ||
|
|
85
|
+
raw === "warning" ||
|
|
86
|
+
raw === "danger" ||
|
|
87
|
+
raw === "success"
|
|
88
|
+
? raw
|
|
89
|
+
: "planned";
|
|
69
90
|
pulse.style.left = x + "px";
|
|
70
91
|
pulse.style.top = y + "px";
|
|
71
92
|
pulse.classList.remove("wg-pulse");
|
|
@@ -77,7 +98,14 @@ export async function installDemoChrome(page, title = "waygraph auto", options =
|
|
|
77
98
|
const ringLabel = document.getElementById("wg-ring-label");
|
|
78
99
|
if (!ring || !ringLabel)
|
|
79
100
|
return;
|
|
80
|
-
const
|
|
101
|
+
const raw = (tone || "planned") + "";
|
|
102
|
+
const t = raw === "auto" ||
|
|
103
|
+
raw === "info" ||
|
|
104
|
+
raw === "warning" ||
|
|
105
|
+
raw === "danger" ||
|
|
106
|
+
raw === "success"
|
|
107
|
+
? raw
|
|
108
|
+
: "planned";
|
|
81
109
|
ring.dataset.tone = t;
|
|
82
110
|
ringLabel.dataset.tone = t;
|
|
83
111
|
ring.style.left = box.x - 6 + "px";
|
|
@@ -136,7 +164,7 @@ async function clickPulseAt(page, x, y, tone = "auto") {
|
|
|
136
164
|
.evaluate(({ x, y, tone }) => window.__wgClickPulse?.(x, y, tone), { x, y, tone })
|
|
137
165
|
.catch(() => { });
|
|
138
166
|
}
|
|
139
|
-
/** Demo cursor + ring on fill/click during auto explore headful runs (automation =
|
|
167
|
+
/** Demo cursor + ring on fill/click during auto explore headful runs (automation = gray). */
|
|
140
168
|
export function instrumentInteractionHighlighting(page, mem, slowMo) {
|
|
141
169
|
const typeDelay = () => (slowMo ? 0 : 30);
|
|
142
170
|
const clickPrePop = () => (slowMo ? 300 : 700);
|
package/dist/types.d.ts
CHANGED
|
@@ -209,6 +209,11 @@ export interface Block<In extends Checkpoint<string>, Out extends Checkpoint<str
|
|
|
209
209
|
* @example requires: [LoginCreds.key]
|
|
210
210
|
*/
|
|
211
211
|
requires?: readonly MemKey<any>[];
|
|
212
|
+
/**
|
|
213
|
+
* Demo pacing for this Block or compose group (`withBlockPace`).
|
|
214
|
+
* Demo/step only - `runGraph` ignores. Prefer `fastForwardComposeBlock` for blitz.
|
|
215
|
+
*/
|
|
216
|
+
demoPace?: import("./highlights.js").DemoPace;
|
|
212
217
|
/**
|
|
213
218
|
* Optional. When this Block's real choices depend on the live page
|
|
214
219
|
* (which of several items to add to cart, which of several rows to
|