waygraph 0.12.16 → 0.12.18
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 -3
- package/dist/cli.js +64 -39
- package/dist/engine.d.ts +17 -2
- package/dist/engine.js +22 -0
- package/dist/highlights.d.ts +37 -7
- package/dist/highlights.js +110 -15
- package/dist/index.d.ts +3 -3
- package/dist/index.js +2 -2
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -236,9 +236,11 @@ snapshot, partitions edges by hash, and claims via in-process edge leases (audit
|
|
|
236
236
|
|
|
237
237
|
**Richer demo narration:** automation rings are **gray**; authored stubs/slides can use
|
|
238
238
|
`tone: "info" | "warning" | "danger" | "success"` (iconified captions), plus
|
|
239
|
-
`size: "sm" | "md" | "lg"` and `weight: "normal" | "bold"`.
|
|
240
|
-
`
|
|
241
|
-
(
|
|
239
|
+
`size: "sm" | "md" | "lg"` and `weight: "normal" | "bold"`. Flow episode defaults:
|
|
240
|
+
`withHighlightStyle(flow, { size, weight, tone? })` (slot/fixture wins). Episode pacing:
|
|
241
|
+
`withDemoPace(flow, "fast" | "slow" | "normal" | "blitz" | number)` or `withBlockPace(block, ...)`
|
|
242
|
+
(`number` `<=20` = scale vs normal, e.g. `0.5` / `2`; `>20` = absolute ms, e.g. `4500`).
|
|
243
|
+
FFCompose stays blitz. Living objectives: `docs/proposals/OBJECTIVES.md`.
|
|
242
244
|
`spawnTab(entry, page, mem)` drives a genuinely separate second tab through its own
|
|
243
245
|
Block/Flow, in the same browser context an existing `page` already belongs to - the
|
|
244
246
|
pattern `observe()` could already reach for (it's the only phase allowed to touch
|
package/dist/cli.js
CHANGED
|
@@ -215,7 +215,12 @@ import {
|
|
|
215
215
|
normalizeDemoPace,
|
|
216
216
|
normalizeHighlightSize,
|
|
217
217
|
normalizeHighlightWeight,
|
|
218
|
+
applyHighlightStyleDefaults,
|
|
218
219
|
resolveStepDemoPace,
|
|
220
|
+
demoPaceGateMs,
|
|
221
|
+
demoPaceIsBlitz,
|
|
222
|
+
demoPaceIsFast,
|
|
223
|
+
demoPaceIsSlow,
|
|
219
224
|
} from "waygraph";
|
|
220
225
|
|
|
221
226
|
function walkDir(dir, pattern) {
|
|
@@ -1072,6 +1077,7 @@ async function cycleHighlightRings(page, highlights, gatesFast, opts) {
|
|
|
1072
1077
|
// defaultHoldMs: when set (fail path), use instead of legacy 900/200 so BUG
|
|
1073
1078
|
// rings stay visible ~2s before the error panel (PIA stubOnError RFC).
|
|
1074
1079
|
const defaultHoldMs = opts && opts.defaultHoldMs != null ? opts.defaultHoldMs : null;
|
|
1080
|
+
const pace = opts && opts.pace !== undefined ? opts.pace : undefined;
|
|
1075
1081
|
for (let i = 0; i < list.length; i++) {
|
|
1076
1082
|
const h = list[i];
|
|
1077
1083
|
try {
|
|
@@ -1081,7 +1087,7 @@ async function cycleHighlightRings(page, highlights, gatesFast, opts) {
|
|
|
1081
1087
|
size: h.size,
|
|
1082
1088
|
weight: h.weight,
|
|
1083
1089
|
});
|
|
1084
|
-
const authored = resolveFixtureDwellMs(h, { gatesFast });
|
|
1090
|
+
const authored = resolveFixtureDwellMs(h, { gatesFast, pace });
|
|
1085
1091
|
const legacyMs = i === list.length - 1 ? 200 : 900;
|
|
1086
1092
|
const holdMs =
|
|
1087
1093
|
authored != null ? authored : defaultHoldMs != null ? defaultHoldMs : legacyMs;
|
|
@@ -1138,7 +1144,9 @@ async function renderAfterStep(page, info) {
|
|
|
1138
1144
|
// it highlights something [else] and next," not just the first one.
|
|
1139
1145
|
// duration / fastMode on stubAfter (or flow fixtures) override the legacy
|
|
1140
1146
|
// 900ms / 200ms holds when set.
|
|
1141
|
-
await cycleHighlightRings(page, highlights, gatesFast,
|
|
1147
|
+
await cycleHighlightRings(page, highlights, gatesFast, {
|
|
1148
|
+
pace: info.pace,
|
|
1149
|
+
});
|
|
1142
1150
|
await page
|
|
1143
1151
|
.evaluate((info) => {
|
|
1144
1152
|
// Reused in place - see renderBeforeStep's own comment on this.
|
|
@@ -2159,13 +2167,10 @@ async function runStepMode(engine, start, end, context, page, mem, resolved, slo
|
|
|
2159
2167
|
// gates too, not just skip its interaction dwell - otherwise autoplay
|
|
2160
2168
|
// still stalls the full autoplayMs admiring a step that intentionally
|
|
2161
2169
|
// ran too fast to watch.
|
|
2162
|
-
const ms =
|
|
2163
|
-
?
|
|
2164
|
-
|
|
2165
|
-
|
|
2166
|
-
: pacing.gatesSlow
|
|
2167
|
-
? Math.max(autoplayMs * 2, 3500)
|
|
2168
|
-
: autoplayMs;
|
|
2170
|
+
const ms = demoPaceGateMs(
|
|
2171
|
+
pacing.skipTheater ? "blitz" : pacing.demoPace,
|
|
2172
|
+
autoplayMs,
|
|
2173
|
+
);
|
|
2169
2174
|
let elapsed = 0;
|
|
2170
2175
|
for (;;) {
|
|
2171
2176
|
// Re-read the checkbox EVERY loop tick, not once up front - a human
|
|
@@ -2248,36 +2253,40 @@ async function runStepMode(engine, start, end, context, page, mem, resolved, slo
|
|
|
2248
2253
|
if ((clearSession || r.resetSession) && i > 0) {
|
|
2249
2254
|
await resetPageState(context, page, baseURL);
|
|
2250
2255
|
}
|
|
2251
|
-
//
|
|
2252
|
-
//
|
|
2253
|
-
// gates only (keeps theater). Episode pace: block > flow > CLI --fast.
|
|
2256
|
+
// Episode pace: block > flow > CLI --fast (only when no authored pace).
|
|
2257
|
+
// Authoring wins: withDemoPace("slow"|2|4500) keeps slow dwell even under --fast.
|
|
2254
2258
|
const stepPace = resolveStepDemoPace({
|
|
2255
2259
|
blockPace: r.block.demoPace,
|
|
2256
2260
|
flowPace: r.demoPace,
|
|
2257
2261
|
fastForward: !!r.block.fastForward,
|
|
2258
2262
|
wasFastForward: !!r.wasFastForward,
|
|
2259
2263
|
});
|
|
2264
|
+
const authoredPace =
|
|
2265
|
+
(r.block.demoPace != null && r.block.demoPace !== "") ||
|
|
2266
|
+
(r.demoPace != null && r.demoPace !== "");
|
|
2260
2267
|
const cliFast = demoFast || fastBlockNames.has(r.block.name);
|
|
2261
2268
|
pacing.demoPace =
|
|
2262
|
-
stepPace === "normal" && cliFast
|
|
2269
|
+
stepPace === "normal" && cliFast && !authoredPace
|
|
2263
2270
|
? fastBlockNames.has(r.block.name)
|
|
2264
2271
|
? "blitz"
|
|
2265
2272
|
: "fast"
|
|
2266
2273
|
: stepPace;
|
|
2267
2274
|
pacing.gatesFast =
|
|
2268
|
-
pacing.demoPace
|
|
2269
|
-
pacing.demoPace === "fast" ||
|
|
2275
|
+
demoPaceIsFast(pacing.demoPace) ||
|
|
2270
2276
|
!!r.block.fastForward ||
|
|
2271
2277
|
!!r.wasFastForward ||
|
|
2272
|
-
demoFast;
|
|
2273
|
-
pacing.gatesSlow = pacing.demoPace
|
|
2278
|
+
(!authoredPace && demoFast);
|
|
2279
|
+
pacing.gatesSlow = demoPaceIsSlow(pacing.demoPace);
|
|
2274
2280
|
pacing.skipTheater =
|
|
2275
|
-
pacing.demoPace
|
|
2281
|
+
demoPaceIsBlitz(pacing.demoPace) ||
|
|
2276
2282
|
fastBlockNames.has(r.block.name) ||
|
|
2277
2283
|
!!r.block.fastForward ||
|
|
2278
2284
|
!!r.wasFastForward;
|
|
2279
2285
|
const fixtures = r.highlightFixtures;
|
|
2280
|
-
|
|
2286
|
+
const flowStyle = r.highlightStyle;
|
|
2287
|
+
stubBeforeRef.current = resolveHighlightSlots(r.block, "stubBefore", { fixtures }).map((h) =>
|
|
2288
|
+
applyHighlightStyleDefaults(h, flowStyle),
|
|
2289
|
+
);
|
|
2281
2290
|
const isNavBlock = r.block.__waygraphKind === "nav";
|
|
2282
2291
|
const autoNow = await currentAutoplay();
|
|
2283
2292
|
// Auto-next: tuck stepper on NavBlocks so the page transition fills the frame.
|
|
@@ -2369,17 +2378,21 @@ async function runStepMode(engine, start, end, context, page, mem, resolved, slo
|
|
|
2369
2378
|
.catch(() => {});
|
|
2370
2379
|
const errHighlights = resolveHighlightSlots(r.block, "stubOnError", {
|
|
2371
2380
|
fixtures: fixturesOnError,
|
|
2372
|
-
}).map((h) =>
|
|
2373
|
-
|
|
2374
|
-
|
|
2375
|
-
|
|
2376
|
-
|
|
2377
|
-
|
|
2378
|
-
|
|
2379
|
-
|
|
2380
|
-
|
|
2381
|
+
}).map((h) => {
|
|
2382
|
+
const styled = applyHighlightStyleDefaults(h, r.highlightStyle);
|
|
2383
|
+
return {
|
|
2384
|
+
selector: styled.selector,
|
|
2385
|
+
label: formatHighlightCaption(styled),
|
|
2386
|
+
duration: styled.duration,
|
|
2387
|
+
fastMode: styled.fastMode,
|
|
2388
|
+
tone: styled.tone,
|
|
2389
|
+
size: styled.size,
|
|
2390
|
+
weight: styled.weight,
|
|
2391
|
+
};
|
|
2392
|
+
});
|
|
2381
2393
|
await cycleHighlightRings(page, errHighlights, !!pacing.gatesFast, {
|
|
2382
2394
|
defaultHoldMs: 2000,
|
|
2395
|
+
pace: pacing.demoPace,
|
|
2383
2396
|
});
|
|
2384
2397
|
}
|
|
2385
2398
|
// A thrown act()/observe()/a failed verify Trait used to just crash
|
|
@@ -2430,7 +2443,9 @@ async function runStepMode(engine, start, end, context, page, mem, resolved, slo
|
|
|
2430
2443
|
.catch(() => {});
|
|
2431
2444
|
result = stepOutcome.result;
|
|
2432
2445
|
const fixturesAfter = r.highlightFixtures;
|
|
2433
|
-
const slides = resolveSlides(r.block, { out: result, fixtures: fixturesAfter })
|
|
2446
|
+
const slides = resolveSlides(r.block, { out: result, fixtures: fixturesAfter }).map((s) =>
|
|
2447
|
+
applyHighlightStyleDefaults(s, r.highlightStyle),
|
|
2448
|
+
);
|
|
2434
2449
|
if (slides.length > 0) {
|
|
2435
2450
|
await presentSlides(page, slides, gate, {
|
|
2436
2451
|
title,
|
|
@@ -2445,18 +2460,23 @@ async function runStepMode(engine, start, end, context, page, mem, resolved, slo
|
|
|
2445
2460
|
let highlights;
|
|
2446
2461
|
if (hasAuthoredStubAfter(r.block, result, fixturesAfter)) {
|
|
2447
2462
|
highlights = resolveHighlightSlots(r.block, "stubAfter", { out: result, fixtures: fixturesAfter }).map(
|
|
2448
|
-
(h) =>
|
|
2449
|
-
|
|
2450
|
-
|
|
2451
|
-
|
|
2452
|
-
|
|
2453
|
-
|
|
2454
|
-
|
|
2455
|
-
|
|
2456
|
-
|
|
2463
|
+
(h) => {
|
|
2464
|
+
const styled = applyHighlightStyleDefaults(h, r.highlightStyle);
|
|
2465
|
+
return {
|
|
2466
|
+
selector: styled.selector,
|
|
2467
|
+
label: formatHighlightCaption(styled),
|
|
2468
|
+
duration: styled.duration,
|
|
2469
|
+
fastMode: styled.fastMode,
|
|
2470
|
+
tone: styled.tone,
|
|
2471
|
+
size: styled.size,
|
|
2472
|
+
weight: styled.weight,
|
|
2473
|
+
};
|
|
2474
|
+
},
|
|
2457
2475
|
);
|
|
2458
2476
|
} else {
|
|
2459
|
-
highlights = extractVerifyHighlights(r.block, result.__state)
|
|
2477
|
+
highlights = extractVerifyHighlights(r.block, result.__state).map((h) =>
|
|
2478
|
+
applyHighlightStyleDefaults(h, r.highlightStyle),
|
|
2479
|
+
);
|
|
2460
2480
|
}
|
|
2461
2481
|
await renderAfterStep(page, {
|
|
2462
2482
|
index: i,
|
|
@@ -2466,6 +2486,7 @@ async function runStepMode(engine, start, end, context, page, mem, resolved, slo
|
|
|
2466
2486
|
resultTag: JSON.stringify(result),
|
|
2467
2487
|
highlights,
|
|
2468
2488
|
gatesFast: pacing.gatesFast,
|
|
2489
|
+
pace: pacing.demoPace,
|
|
2469
2490
|
isLast: i === resolved.length - 1,
|
|
2470
2491
|
allNames: moduleNames,
|
|
2471
2492
|
allDescriptions: moduleDescriptions,
|
|
@@ -2638,6 +2659,7 @@ async function main() {
|
|
|
2638
2659
|
seedMem: idx === 0 ? seedMem : undefined,
|
|
2639
2660
|
highlightFixtures: flow.highlightFixtures,
|
|
2640
2661
|
demoPace: flow.demoPace,
|
|
2662
|
+
highlightStyle: flow.highlightStyle,
|
|
2641
2663
|
expectedFailureReason:
|
|
2642
2664
|
flow.expectedFailureReason && idx === blockInfos.length - 1
|
|
2643
2665
|
? flow.expectedFailureReason
|
|
@@ -2707,6 +2729,7 @@ async function main() {
|
|
|
2707
2729
|
expectedFailureReason: flow.expectedFailureReason,
|
|
2708
2730
|
highlightFixtures: flow.highlightFixtures,
|
|
2709
2731
|
demoPace: flow.demoPace,
|
|
2732
|
+
highlightStyle: flow.highlightStyle,
|
|
2710
2733
|
seedMem: () => seedMemForFlow(mem, flow.blocks(), seg.json, seg.ref),
|
|
2711
2734
|
});
|
|
2712
2735
|
} else {
|
|
@@ -2717,6 +2740,7 @@ async function main() {
|
|
|
2717
2740
|
episodeTitle: undefined,
|
|
2718
2741
|
highlightFixtures: undefined,
|
|
2719
2742
|
demoPace: undefined,
|
|
2743
|
+
highlightStyle: undefined,
|
|
2720
2744
|
seedMem: () => seedMemForBlock(mem, r, seg.json),
|
|
2721
2745
|
});
|
|
2722
2746
|
}
|
|
@@ -2742,6 +2766,7 @@ async function main() {
|
|
|
2742
2766
|
episodeTitle: meta.episodeTitle,
|
|
2743
2767
|
highlightFixtures: meta.highlightFixtures,
|
|
2744
2768
|
demoPace: meta.demoPace,
|
|
2769
|
+
highlightStyle: meta.highlightStyle,
|
|
2745
2770
|
expectedFailureReason:
|
|
2746
2771
|
meta.expectedFailureReason && remainingInFlow === 1 ? meta.expectedFailureReason : undefined,
|
|
2747
2772
|
seedMem: isFirstOfSegment ? meta.seedMem : undefined,
|
package/dist/engine.d.ts
CHANGED
|
@@ -3,6 +3,7 @@ import type { Block, Checkpoint, Instruction, DefinedBlock, ActionPage, Waygraph
|
|
|
3
3
|
import { MemPage } from "./mem-page.js";
|
|
4
4
|
import type { MemKey } from "./mem-page.js";
|
|
5
5
|
import type { Trait } from "./trait.js";
|
|
6
|
+
import { type HighlightStyleDefaults, type DemoPace } from "./highlights.js";
|
|
6
7
|
/**
|
|
7
8
|
* Checks `block.requires` against `mem` and throws, naming every missing key at
|
|
8
9
|
* once, if any are unset. `connect()` unions each Block's `requires` into the
|
|
@@ -191,6 +192,11 @@ export interface Flow<Out extends Checkpoint<string>> {
|
|
|
191
192
|
* `run()` ignores; step/demo applies per Block in the episode.
|
|
192
193
|
*/
|
|
193
194
|
readonly demoPace?: import("./highlights.js").DemoPace;
|
|
195
|
+
/**
|
|
196
|
+
* Default highlight size/weight/tone for this Flow's episode (`withHighlightStyle`).
|
|
197
|
+
* Per-slot stub/fixture values win. `run()` ignores.
|
|
198
|
+
*/
|
|
199
|
+
readonly highlightStyle?: import("./highlights.js").HighlightStyleDefaults;
|
|
194
200
|
/**
|
|
195
201
|
* This Flow's constituent Blocks, in order between `start`/`end`, as plain
|
|
196
202
|
* data - for introspection/visualization tools, without running anything.
|
|
@@ -263,13 +269,22 @@ export declare function withTitle<Out extends Checkpoint<string>>(flow: Flow<Out
|
|
|
263
269
|
* Non-destructive. `fastForwardComposeBlock` is always blitz for its own step;
|
|
264
270
|
* use this when an entire episode should be fast or slow.
|
|
265
271
|
* @example withDemoPace(withTitle(gapFlow, "Episode 2 - gaps"), "slow")
|
|
272
|
+
* @example withDemoPace(happyFlow, 0.5) // 2x faster than normal
|
|
273
|
+
* @example withDemoPace(gapFlow, 2.5) // 2.5x slower
|
|
274
|
+
* @example withDemoPace(gapFlow, 4500) // absolute ~4.5s gates/dwells
|
|
275
|
+
*/
|
|
276
|
+
export declare function withDemoPace<Out extends Checkpoint<string>>(flow: Flow<Out>, pace: DemoPace): Flow<Out>;
|
|
277
|
+
/**
|
|
278
|
+
* Default highlight look for a Flow episode (size / weight / optional tone).
|
|
279
|
+
* Per-slot stub or {@link withHighlightFixtures} values win when set.
|
|
280
|
+
* @example withHighlightStyle(withDemoPace(gapFlow, "slow"), { size: "lg", weight: "bold" })
|
|
266
281
|
*/
|
|
267
|
-
export declare function
|
|
282
|
+
export declare function withHighlightStyle<Out extends Checkpoint<string>>(flow: Flow<Out>, style: HighlightStyleDefaults): Flow<Out>;
|
|
268
283
|
/**
|
|
269
284
|
* Demo pacing for one Block or compose unit (not FF - use fastForwardComposeBlock for blitz).
|
|
270
285
|
* @example withBlockPace(composeBlock("gap-review", [...]), "slow")
|
|
271
286
|
*/
|
|
272
|
-
export declare function withBlockPace<In extends Checkpoint<string>, Out extends Checkpoint<string>>(block: Block<In, Out>, pace:
|
|
287
|
+
export declare function withBlockPace<In extends Checkpoint<string>, Out extends Checkpoint<string>>(block: Block<In, Out>, pace: DemoPace): Block<In, Out>;
|
|
273
288
|
/**
|
|
274
289
|
* Marks a Flow as one that's SUPPOSED to throw - e.g. a locked-out user's
|
|
275
290
|
* login attempt genuinely failing, demonstrating the app's own real
|
package/dist/engine.js
CHANGED
|
@@ -2,6 +2,7 @@ import { chromium, firefox, webkit } from "@playwright/test";
|
|
|
2
2
|
import { connect, checkpoint } from "./types.js";
|
|
3
3
|
import { MemPage } from "./mem-page.js";
|
|
4
4
|
import { runVerify, runPrecondition } from "./trait.js";
|
|
5
|
+
import { normalizeHighlightTone, normalizeHighlightSize, normalizeHighlightWeight, } from "./highlights.js";
|
|
5
6
|
const LAUNCHERS = { chromium, firefox, webkit };
|
|
6
7
|
/**
|
|
7
8
|
* Resolves which `BrowserType` actually launches for a `mem`-only run (no
|
|
@@ -356,6 +357,9 @@ export function withTitle(flow, title) {
|
|
|
356
357
|
* Non-destructive. `fastForwardComposeBlock` is always blitz for its own step;
|
|
357
358
|
* use this when an entire episode should be fast or slow.
|
|
358
359
|
* @example withDemoPace(withTitle(gapFlow, "Episode 2 - gaps"), "slow")
|
|
360
|
+
* @example withDemoPace(happyFlow, 0.5) // 2x faster than normal
|
|
361
|
+
* @example withDemoPace(gapFlow, 2.5) // 2.5x slower
|
|
362
|
+
* @example withDemoPace(gapFlow, 4500) // absolute ~4.5s gates/dwells
|
|
359
363
|
*/
|
|
360
364
|
export function withDemoPace(flow, pace) {
|
|
361
365
|
const demoPace = pace;
|
|
@@ -366,6 +370,24 @@ export function withDemoPace(flow, pace) {
|
|
|
366
370
|
modBlockVerify: (block, nameOrIndex, newCheck) => withDemoPace(flow.modBlockVerify(block, nameOrIndex, newCheck), demoPace),
|
|
367
371
|
};
|
|
368
372
|
}
|
|
373
|
+
/**
|
|
374
|
+
* Default highlight look for a Flow episode (size / weight / optional tone).
|
|
375
|
+
* Per-slot stub or {@link withHighlightFixtures} values win when set.
|
|
376
|
+
* @example withHighlightStyle(withDemoPace(gapFlow, "slow"), { size: "lg", weight: "bold" })
|
|
377
|
+
*/
|
|
378
|
+
export function withHighlightStyle(flow, style) {
|
|
379
|
+
const highlightStyle = {
|
|
380
|
+
...(style.tone !== undefined ? { tone: normalizeHighlightTone(style.tone) } : {}),
|
|
381
|
+
...(style.size !== undefined ? { size: normalizeHighlightSize(style.size) } : {}),
|
|
382
|
+
...(style.weight !== undefined ? { weight: normalizeHighlightWeight(style.weight) } : {}),
|
|
383
|
+
};
|
|
384
|
+
return {
|
|
385
|
+
...flow,
|
|
386
|
+
highlightStyle,
|
|
387
|
+
withBlockVerify: (block, verify) => withHighlightStyle(flow.withBlockVerify(block, verify), highlightStyle),
|
|
388
|
+
modBlockVerify: (block, nameOrIndex, newCheck) => withHighlightStyle(flow.modBlockVerify(block, nameOrIndex, newCheck), highlightStyle),
|
|
389
|
+
};
|
|
390
|
+
}
|
|
369
391
|
/**
|
|
370
392
|
* Demo pacing for one Block or compose unit (not FF - use fastForwardComposeBlock for blitz).
|
|
371
393
|
* @example withBlockPace(composeBlock("gap-review", [...]), "slow")
|
package/dist/highlights.d.ts
CHANGED
|
@@ -79,6 +79,22 @@ export type HighlightTone = "planned" | "auto" | "info" | "warning" | "danger" |
|
|
|
79
79
|
export type HighlightSize = "sm" | "md" | "lg";
|
|
80
80
|
/** Label font weight. */
|
|
81
81
|
export type HighlightWeight = "normal" | "bold";
|
|
82
|
+
/** Optional Flow-level defaults for demo rings (episode-wide). Stub/fixture wins. */
|
|
83
|
+
export type HighlightStyleDefaults = {
|
|
84
|
+
tone?: HighlightTone;
|
|
85
|
+
size?: HighlightSize;
|
|
86
|
+
weight?: HighlightWeight;
|
|
87
|
+
};
|
|
88
|
+
/** Apply Flow defaults under per-slot authored values (slot wins when set). */
|
|
89
|
+
export declare function applyHighlightStyleDefaults<T extends {
|
|
90
|
+
tone?: HighlightTone | string;
|
|
91
|
+
size?: HighlightSize | string;
|
|
92
|
+
weight?: HighlightWeight | string;
|
|
93
|
+
}>(slot: T, defaults?: HighlightStyleDefaults | null): T & {
|
|
94
|
+
tone: HighlightTone;
|
|
95
|
+
size: HighlightSize;
|
|
96
|
+
weight: HighlightWeight;
|
|
97
|
+
};
|
|
82
98
|
/** Map author aliases (`error` -> danger) to a canonical tone. */
|
|
83
99
|
export declare function normalizeHighlightTone(raw: unknown): HighlightTone;
|
|
84
100
|
/** Map size aliases to sm/md/lg. */
|
|
@@ -90,12 +106,14 @@ export declare function toneIconPrefix(tone: HighlightTone): string;
|
|
|
90
106
|
/**
|
|
91
107
|
* Demo pacing for a Flow episode or a Block/compose group.
|
|
92
108
|
* - `blitz` - FF-like: skip theater + short gates (same as fastForwardComposeBlock)
|
|
93
|
-
* - `fast` - shorter gates, keep cursor theater
|
|
94
|
-
* - `normal` - default demo pace
|
|
95
|
-
* - `slow` - longer autoplay + fixture dwell (
|
|
109
|
+
* - `fast` - shorter gates, keep cursor theater (~0.33x normal)
|
|
110
|
+
* - `normal` - default demo pace (1x)
|
|
111
|
+
* - `slow` - longer autoplay + fixture dwell (~2x)
|
|
112
|
+
* - `number` - scale vs normal when `<= 20` (e.g. `0.5`, `1.5`, `3`);
|
|
113
|
+
* absolute gate/dwell ms when `> 20` (e.g. `4500`)
|
|
96
114
|
*/
|
|
97
|
-
export type
|
|
98
|
-
export
|
|
115
|
+
export type DemoPaceName = "blitz" | "fast" | "normal" | "slow";
|
|
116
|
+
export type DemoPace = DemoPaceName | number;
|
|
99
117
|
/** Default fixture dwell when `duration: true`. */
|
|
100
118
|
export declare const FIXTURE_DURATION_MS_DEFAULT = 2000;
|
|
101
119
|
/** Default fixture dwell under `--fast` when duration is enabled. */
|
|
@@ -106,9 +124,21 @@ export declare const FIXTURE_DURATION_SLOW_MS_DEFAULT = 4000;
|
|
|
106
124
|
export declare const SLIDE_DURATION_MS_DEFAULT = 2000;
|
|
107
125
|
/** @deprecated Prefer FIXTURE_DURATION_FAST_MS_DEFAULT */
|
|
108
126
|
export declare const SLIDE_DURATION_FAST_MS_DEFAULT = 600;
|
|
127
|
+
export declare function normalizeDemoPace(raw: unknown): DemoPace;
|
|
128
|
+
/** Named / numeric pace -> scale vs normal (1 = normal). Absolute ms (>20) maps via default dwell. */
|
|
129
|
+
export declare function demoPaceScale(pace: DemoPace): number;
|
|
130
|
+
export declare function demoPaceIsBlitz(pace: DemoPace): boolean;
|
|
131
|
+
/** True when pace should use the short-gate / fast fixture path (not slow authored). */
|
|
132
|
+
export declare function demoPaceIsFast(pace: DemoPace): boolean;
|
|
133
|
+
export declare function demoPaceIsSlow(pace: DemoPace): boolean;
|
|
134
|
+
/** Autoplay / Next-gate ms for this pace (base is WAYGRAPH_AUTOPLAY_MS or 1800). */
|
|
135
|
+
export declare function demoPaceGateMs(pace: DemoPace, baseAutoplayMs: number): number;
|
|
109
136
|
/**
|
|
110
137
|
* Resolve min dwell ms for any fixture (stub / flow fixture / yap slide),
|
|
111
138
|
* or `null` when duration is unset (caller keeps legacy timing).
|
|
139
|
+
*
|
|
140
|
+
* Authoring wins: an explicit slow/numeric pace is not crushed by CLI `--fast`
|
|
141
|
+
* (`gatesFast`). `--fast` only shortens when pace is unset/normal.
|
|
112
142
|
*/
|
|
113
143
|
export declare function resolveFixtureDwellMs(fixture: FixtureDurationFields, opts?: {
|
|
114
144
|
gatesFast?: boolean;
|
|
@@ -124,8 +154,8 @@ export declare function resolveSlideDwellMs(slide: FixtureDurationFields, opts?:
|
|
|
124
154
|
* Opaque FF / wasFastForward always win as blitz.
|
|
125
155
|
*/
|
|
126
156
|
export declare function resolveStepDemoPace(opts: {
|
|
127
|
-
blockPace?: DemoPace | string | null;
|
|
128
|
-
flowPace?: DemoPace | string | null;
|
|
157
|
+
blockPace?: DemoPace | string | number | null;
|
|
158
|
+
flowPace?: DemoPace | string | number | null;
|
|
129
159
|
fastForward?: boolean;
|
|
130
160
|
wasFastForward?: boolean;
|
|
131
161
|
}): DemoPace;
|
package/dist/highlights.js
CHANGED
|
@@ -8,6 +8,25 @@
|
|
|
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
|
+
/** Apply Flow defaults under per-slot authored values (slot wins when set). */
|
|
12
|
+
export function applyHighlightStyleDefaults(slot, defaults) {
|
|
13
|
+
const tone = slot.tone !== undefined && slot.tone !== ""
|
|
14
|
+
? normalizeHighlightTone(slot.tone)
|
|
15
|
+
: defaults?.tone !== undefined
|
|
16
|
+
? normalizeHighlightTone(defaults.tone)
|
|
17
|
+
: "planned";
|
|
18
|
+
const size = slot.size !== undefined && slot.size !== ""
|
|
19
|
+
? normalizeHighlightSize(slot.size)
|
|
20
|
+
: defaults?.size !== undefined
|
|
21
|
+
? normalizeHighlightSize(defaults.size)
|
|
22
|
+
: "md";
|
|
23
|
+
const weight = slot.weight !== undefined && slot.weight !== ""
|
|
24
|
+
? normalizeHighlightWeight(slot.weight)
|
|
25
|
+
: defaults?.weight !== undefined
|
|
26
|
+
? normalizeHighlightWeight(defaults.weight)
|
|
27
|
+
: "normal";
|
|
28
|
+
return { ...slot, tone, size, weight };
|
|
29
|
+
}
|
|
11
30
|
const TONE_ICONS = {
|
|
12
31
|
planned: "",
|
|
13
32
|
auto: "",
|
|
@@ -60,18 +79,6 @@ export function toneIconPrefix(tone) {
|
|
|
60
79
|
const icon = TONE_ICONS[tone];
|
|
61
80
|
return icon ? `[${icon}] ` : "";
|
|
62
81
|
}
|
|
63
|
-
export function normalizeDemoPace(raw) {
|
|
64
|
-
if (typeof raw !== "string")
|
|
65
|
-
return "normal";
|
|
66
|
-
const t = raw.trim().toLowerCase();
|
|
67
|
-
if (t === "blitz" || t === "ff")
|
|
68
|
-
return "blitz";
|
|
69
|
-
if (t === "fast" || t === "quick")
|
|
70
|
-
return "fast";
|
|
71
|
-
if (t === "slow" || t === "careful" || t === "review")
|
|
72
|
-
return "slow";
|
|
73
|
-
return "normal";
|
|
74
|
-
}
|
|
75
82
|
/** Default fixture dwell when `duration: true`. */
|
|
76
83
|
export const FIXTURE_DURATION_MS_DEFAULT = 2000;
|
|
77
84
|
/** Default fixture dwell under `--fast` when duration is enabled. */
|
|
@@ -82,24 +89,112 @@ export const FIXTURE_DURATION_SLOW_MS_DEFAULT = 4000;
|
|
|
82
89
|
export const SLIDE_DURATION_MS_DEFAULT = FIXTURE_DURATION_MS_DEFAULT;
|
|
83
90
|
/** @deprecated Prefer FIXTURE_DURATION_FAST_MS_DEFAULT */
|
|
84
91
|
export const SLIDE_DURATION_FAST_MS_DEFAULT = FIXTURE_DURATION_FAST_MS_DEFAULT;
|
|
92
|
+
export function normalizeDemoPace(raw) {
|
|
93
|
+
if (typeof raw === "number" && Number.isFinite(raw) && raw > 0)
|
|
94
|
+
return raw;
|
|
95
|
+
if (typeof raw === "string") {
|
|
96
|
+
const t = raw.trim().toLowerCase();
|
|
97
|
+
if (t === "blitz" || t === "ff")
|
|
98
|
+
return "blitz";
|
|
99
|
+
if (t === "fast" || t === "quick")
|
|
100
|
+
return "fast";
|
|
101
|
+
if (t === "slow" || t === "careful" || t === "review")
|
|
102
|
+
return "slow";
|
|
103
|
+
if (t === "normal" || t === "default" || t === "1x")
|
|
104
|
+
return "normal";
|
|
105
|
+
// "2x" / "0.5x"
|
|
106
|
+
if (t.endsWith("x")) {
|
|
107
|
+
const n = Number(t.slice(0, -1));
|
|
108
|
+
if (Number.isFinite(n) && n > 0)
|
|
109
|
+
return n;
|
|
110
|
+
}
|
|
111
|
+
const n = Number(t);
|
|
112
|
+
if (Number.isFinite(n) && n > 0)
|
|
113
|
+
return n;
|
|
114
|
+
}
|
|
115
|
+
return "normal";
|
|
116
|
+
}
|
|
117
|
+
/** Named / numeric pace -> scale vs normal (1 = normal). Absolute ms (>20) maps via default dwell. */
|
|
118
|
+
export function demoPaceScale(pace) {
|
|
119
|
+
if (typeof pace === "number") {
|
|
120
|
+
if (pace > 20)
|
|
121
|
+
return Math.min(10, Math.max(0.05, pace / FIXTURE_DURATION_MS_DEFAULT));
|
|
122
|
+
return Math.min(10, Math.max(0.05, pace));
|
|
123
|
+
}
|
|
124
|
+
if (pace === "blitz")
|
|
125
|
+
return 0.05;
|
|
126
|
+
if (pace === "fast")
|
|
127
|
+
return 0.33;
|
|
128
|
+
if (pace === "slow")
|
|
129
|
+
return 2;
|
|
130
|
+
return 1;
|
|
131
|
+
}
|
|
132
|
+
export function demoPaceIsBlitz(pace) {
|
|
133
|
+
return pace === "blitz" || (typeof pace === "number" && pace > 0 && pace <= 0.1);
|
|
134
|
+
}
|
|
135
|
+
/** True when pace should use the short-gate / fast fixture path (not slow authored). */
|
|
136
|
+
export function demoPaceIsFast(pace) {
|
|
137
|
+
if (demoPaceIsBlitz(pace))
|
|
138
|
+
return true;
|
|
139
|
+
if (pace === "fast")
|
|
140
|
+
return true;
|
|
141
|
+
if (typeof pace === "number" && pace <= 20)
|
|
142
|
+
return pace < 0.75;
|
|
143
|
+
return false;
|
|
144
|
+
}
|
|
145
|
+
export function demoPaceIsSlow(pace) {
|
|
146
|
+
if (pace === "slow")
|
|
147
|
+
return true;
|
|
148
|
+
if (typeof pace === "number") {
|
|
149
|
+
if (pace > 20)
|
|
150
|
+
return pace >= 3000;
|
|
151
|
+
return pace > 1.25;
|
|
152
|
+
}
|
|
153
|
+
return false;
|
|
154
|
+
}
|
|
155
|
+
/** Autoplay / Next-gate ms for this pace (base is WAYGRAPH_AUTOPLAY_MS or 1800). */
|
|
156
|
+
export function demoPaceGateMs(pace, baseAutoplayMs) {
|
|
157
|
+
if (demoPaceIsBlitz(pace))
|
|
158
|
+
return Math.min(80, baseAutoplayMs);
|
|
159
|
+
if (typeof pace === "number" && pace > 20) {
|
|
160
|
+
return Math.min(30000, Math.max(80, Math.round(pace)));
|
|
161
|
+
}
|
|
162
|
+
const scale = demoPaceScale(pace);
|
|
163
|
+
return Math.min(30000, Math.max(80, Math.round(baseAutoplayMs * scale)));
|
|
164
|
+
}
|
|
85
165
|
/**
|
|
86
166
|
* Resolve min dwell ms for any fixture (stub / flow fixture / yap slide),
|
|
87
167
|
* or `null` when duration is unset (caller keeps legacy timing).
|
|
168
|
+
*
|
|
169
|
+
* Authoring wins: an explicit slow/numeric pace is not crushed by CLI `--fast`
|
|
170
|
+
* (`gatesFast`). `--fast` only shortens when pace is unset/normal.
|
|
88
171
|
*/
|
|
89
172
|
export function resolveFixtureDwellMs(fixture, opts) {
|
|
90
173
|
if (fixture.duration === undefined || fixture.duration === false)
|
|
91
174
|
return null;
|
|
92
|
-
const pace =
|
|
175
|
+
const pace = opts?.pace !== undefined && opts.pace !== null
|
|
176
|
+
? normalizeDemoPace(opts.pace)
|
|
177
|
+
: opts?.gatesFast
|
|
178
|
+
? "fast"
|
|
179
|
+
: "normal";
|
|
93
180
|
const fastMs = typeof fixture.fastMode === "number" && Number.isFinite(fixture.fastMode) && fixture.fastMode >= 0
|
|
94
181
|
? fixture.fastMode
|
|
95
182
|
: FIXTURE_DURATION_FAST_MS_DEFAULT;
|
|
96
|
-
if (pace === "blitz" || pace === "fast" || opts?.gatesFast)
|
|
97
|
-
return fastMs;
|
|
98
183
|
const normalMs = fixture.duration === true
|
|
99
184
|
? FIXTURE_DURATION_MS_DEFAULT
|
|
100
185
|
: typeof fixture.duration === "number" && Number.isFinite(fixture.duration) && fixture.duration >= 0
|
|
101
186
|
? fixture.duration
|
|
102
187
|
: FIXTURE_DURATION_MS_DEFAULT;
|
|
188
|
+
if (typeof pace === "number") {
|
|
189
|
+
if (pace > 20)
|
|
190
|
+
return Math.round(pace);
|
|
191
|
+
return Math.max(0, Math.round(normalMs * Math.min(10, Math.max(0.05, pace))));
|
|
192
|
+
}
|
|
193
|
+
if (pace === "blitz" || pace === "fast")
|
|
194
|
+
return fastMs;
|
|
195
|
+
// CLI --fast only when author left pace at normal
|
|
196
|
+
if (opts?.gatesFast && pace === "normal")
|
|
197
|
+
return fastMs;
|
|
103
198
|
if (pace === "slow")
|
|
104
199
|
return Math.max(normalMs, FIXTURE_DURATION_SLOW_MS_DEFAULT);
|
|
105
200
|
return normalMs;
|
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, withDemoPace, withBlockPace, withExpectedFailure, withHighlightFixtures, chainFlow, } from "./engine.js";
|
|
6
|
-
export { resolveHighlightSlots, resolveSlides, resolveFixtureDwellMs, resolveSlideDwellMs, formatHighlightCaption, hasAuthoredStubAfter, hasAuthoredStubOnError, normalizeHighlightTone, normalizeDemoPace, normalizeHighlightSize, normalizeHighlightWeight, 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, HighlightSize, HighlightWeight, DemoPace, } 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, withHighlightStyle, withExpectedFailure, withHighlightFixtures, chainFlow, } from "./engine.js";
|
|
6
|
+
export { resolveHighlightSlots, resolveSlides, resolveFixtureDwellMs, resolveSlideDwellMs, formatHighlightCaption, hasAuthoredStubAfter, hasAuthoredStubOnError, normalizeHighlightTone, normalizeDemoPace, normalizeHighlightSize, normalizeHighlightWeight, applyHighlightStyleDefaults, toneIconPrefix, resolveStepDemoPace, demoPaceScale, demoPaceIsBlitz, demoPaceIsFast, demoPaceIsSlow, demoPaceGateMs, 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, HighlightSize, HighlightWeight, HighlightStyleDefaults, DemoPace, DemoPaceName, } 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, withDemoPace, withBlockPace, withExpectedFailure, withHighlightFixtures, chainFlow, } from "./engine.js";
|
|
5
|
-
export { resolveHighlightSlots, resolveSlides, resolveFixtureDwellMs, resolveSlideDwellMs, formatHighlightCaption, hasAuthoredStubAfter, hasAuthoredStubOnError, normalizeHighlightTone, normalizeDemoPace, normalizeHighlightSize, normalizeHighlightWeight, 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";
|
|
4
|
+
export { runGraph, spawnTab, narrate, Engine, start, end, branch, withVerify, modVerify, modVerifyAll, defineBlock, defineNavBlock, defineNavClickBlock, defineMethodBlock, defineActionBlock, definePageBlock, defineEffectBlock, defineMemEffectBlock, defineMemNavBlock, locate, composeBlock, fastForwardComposeBlock, isFastForwardBlock, preflight, withSessionReset, withTitle, withDemoPace, withBlockPace, withHighlightStyle, withExpectedFailure, withHighlightFixtures, chainFlow, } from "./engine.js";
|
|
5
|
+
export { resolveHighlightSlots, resolveSlides, resolveFixtureDwellMs, resolveSlideDwellMs, formatHighlightCaption, hasAuthoredStubAfter, hasAuthoredStubOnError, normalizeHighlightTone, normalizeDemoPace, normalizeHighlightSize, normalizeHighlightWeight, applyHighlightStyleDefaults, toneIconPrefix, resolveStepDemoPace, demoPaceScale, demoPaceIsBlitz, demoPaceIsFast, demoPaceIsSlow, demoPaceGateMs, 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";
|