waygraph 0.12.16 → 0.12.17

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 CHANGED
@@ -236,7 +236,8 @@ 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"`. Episode pacing:
239
+ `size: "sm" | "md" | "lg"` and `weight: "normal" | "bold"`. Flow episode defaults:
240
+ `withHighlightStyle(flow, { size, weight, tone? })` (slot/fixture wins). Episode pacing:
240
241
  `withDemoPace(flow, "fast" | "slow" | "normal" | "blitz")` or `withBlockPace(block, ...)`
241
242
  (FFCompose stays blitz). Living objectives: `docs/proposals/OBJECTIVES.md`.
242
243
  `spawnTab(entry, page, mem)` drives a genuinely separate second tab through its own
package/dist/cli.js CHANGED
@@ -215,6 +215,7 @@ import {
215
215
  normalizeDemoPace,
216
216
  normalizeHighlightSize,
217
217
  normalizeHighlightWeight,
218
+ applyHighlightStyleDefaults,
218
219
  resolveStepDemoPace,
219
220
  } from "waygraph";
220
221
 
@@ -2277,7 +2278,10 @@ async function runStepMode(engine, start, end, context, page, mem, resolved, slo
2277
2278
  !!r.block.fastForward ||
2278
2279
  !!r.wasFastForward;
2279
2280
  const fixtures = r.highlightFixtures;
2280
- stubBeforeRef.current = resolveHighlightSlots(r.block, "stubBefore", { fixtures });
2281
+ const flowStyle = r.highlightStyle;
2282
+ stubBeforeRef.current = resolveHighlightSlots(r.block, "stubBefore", { fixtures }).map((h) =>
2283
+ applyHighlightStyleDefaults(h, flowStyle),
2284
+ );
2281
2285
  const isNavBlock = r.block.__waygraphKind === "nav";
2282
2286
  const autoNow = await currentAutoplay();
2283
2287
  // Auto-next: tuck stepper on NavBlocks so the page transition fills the frame.
@@ -2369,15 +2373,18 @@ async function runStepMode(engine, start, end, context, page, mem, resolved, slo
2369
2373
  .catch(() => {});
2370
2374
  const errHighlights = resolveHighlightSlots(r.block, "stubOnError", {
2371
2375
  fixtures: fixturesOnError,
2372
- }).map((h) => ({
2373
- selector: h.selector,
2374
- label: formatHighlightCaption(h),
2375
- duration: h.duration,
2376
- fastMode: h.fastMode,
2377
- tone: normalizeHighlightTone(h.tone),
2378
- size: normalizeHighlightSize(h.size),
2379
- weight: normalizeHighlightWeight(h.weight),
2380
- }));
2376
+ }).map((h) => {
2377
+ const styled = applyHighlightStyleDefaults(h, r.highlightStyle);
2378
+ return {
2379
+ selector: styled.selector,
2380
+ label: formatHighlightCaption(styled),
2381
+ duration: styled.duration,
2382
+ fastMode: styled.fastMode,
2383
+ tone: styled.tone,
2384
+ size: styled.size,
2385
+ weight: styled.weight,
2386
+ };
2387
+ });
2381
2388
  await cycleHighlightRings(page, errHighlights, !!pacing.gatesFast, {
2382
2389
  defaultHoldMs: 2000,
2383
2390
  });
@@ -2430,7 +2437,9 @@ async function runStepMode(engine, start, end, context, page, mem, resolved, slo
2430
2437
  .catch(() => {});
2431
2438
  result = stepOutcome.result;
2432
2439
  const fixturesAfter = r.highlightFixtures;
2433
- const slides = resolveSlides(r.block, { out: result, fixtures: fixturesAfter });
2440
+ const slides = resolveSlides(r.block, { out: result, fixtures: fixturesAfter }).map((s) =>
2441
+ applyHighlightStyleDefaults(s, r.highlightStyle),
2442
+ );
2434
2443
  if (slides.length > 0) {
2435
2444
  await presentSlides(page, slides, gate, {
2436
2445
  title,
@@ -2445,18 +2454,23 @@ async function runStepMode(engine, start, end, context, page, mem, resolved, slo
2445
2454
  let highlights;
2446
2455
  if (hasAuthoredStubAfter(r.block, result, fixturesAfter)) {
2447
2456
  highlights = resolveHighlightSlots(r.block, "stubAfter", { out: result, fixtures: fixturesAfter }).map(
2448
- (h) => ({
2449
- selector: h.selector,
2450
- label: formatHighlightCaption(h),
2451
- duration: h.duration,
2452
- fastMode: h.fastMode,
2453
- tone: normalizeHighlightTone(h.tone),
2454
- size: normalizeHighlightSize(h.size),
2455
- weight: normalizeHighlightWeight(h.weight),
2456
- }),
2457
+ (h) => {
2458
+ const styled = applyHighlightStyleDefaults(h, r.highlightStyle);
2459
+ return {
2460
+ selector: styled.selector,
2461
+ label: formatHighlightCaption(styled),
2462
+ duration: styled.duration,
2463
+ fastMode: styled.fastMode,
2464
+ tone: styled.tone,
2465
+ size: styled.size,
2466
+ weight: styled.weight,
2467
+ };
2468
+ },
2457
2469
  );
2458
2470
  } else {
2459
- highlights = extractVerifyHighlights(r.block, result.__state);
2471
+ highlights = extractVerifyHighlights(r.block, result.__state).map((h) =>
2472
+ applyHighlightStyleDefaults(h, r.highlightStyle),
2473
+ );
2460
2474
  }
2461
2475
  await renderAfterStep(page, {
2462
2476
  index: i,
@@ -2638,6 +2652,7 @@ async function main() {
2638
2652
  seedMem: idx === 0 ? seedMem : undefined,
2639
2653
  highlightFixtures: flow.highlightFixtures,
2640
2654
  demoPace: flow.demoPace,
2655
+ highlightStyle: flow.highlightStyle,
2641
2656
  expectedFailureReason:
2642
2657
  flow.expectedFailureReason && idx === blockInfos.length - 1
2643
2658
  ? flow.expectedFailureReason
@@ -2707,6 +2722,7 @@ async function main() {
2707
2722
  expectedFailureReason: flow.expectedFailureReason,
2708
2723
  highlightFixtures: flow.highlightFixtures,
2709
2724
  demoPace: flow.demoPace,
2725
+ highlightStyle: flow.highlightStyle,
2710
2726
  seedMem: () => seedMemForFlow(mem, flow.blocks(), seg.json, seg.ref),
2711
2727
  });
2712
2728
  } else {
@@ -2717,6 +2733,7 @@ async function main() {
2717
2733
  episodeTitle: undefined,
2718
2734
  highlightFixtures: undefined,
2719
2735
  demoPace: undefined,
2736
+ highlightStyle: undefined,
2720
2737
  seedMem: () => seedMemForBlock(mem, r, seg.json),
2721
2738
  });
2722
2739
  }
@@ -2742,6 +2759,7 @@ async function main() {
2742
2759
  episodeTitle: meta.episodeTitle,
2743
2760
  highlightFixtures: meta.highlightFixtures,
2744
2761
  demoPace: meta.demoPace,
2762
+ highlightStyle: meta.highlightStyle,
2745
2763
  expectedFailureReason:
2746
2764
  meta.expectedFailureReason && remainingInFlow === 1 ? meta.expectedFailureReason : undefined,
2747
2765
  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.
@@ -264,12 +270,18 @@ export declare function withTitle<Out extends Checkpoint<string>>(flow: Flow<Out
264
270
  * use this when an entire episode should be fast or slow.
265
271
  * @example withDemoPace(withTitle(gapFlow, "Episode 2 - gaps"), "slow")
266
272
  */
267
- export declare function withDemoPace<Out extends Checkpoint<string>>(flow: Flow<Out>, pace: import("./highlights.js").DemoPace): Flow<Out>;
273
+ export declare function withDemoPace<Out extends Checkpoint<string>>(flow: Flow<Out>, pace: DemoPace): Flow<Out>;
274
+ /**
275
+ * Default highlight look for a Flow episode (size / weight / optional tone).
276
+ * Per-slot stub or {@link withHighlightFixtures} values win when set.
277
+ * @example withHighlightStyle(withDemoPace(gapFlow, "slow"), { size: "lg", weight: "bold" })
278
+ */
279
+ export declare function withHighlightStyle<Out extends Checkpoint<string>>(flow: Flow<Out>, style: HighlightStyleDefaults): Flow<Out>;
268
280
  /**
269
281
  * Demo pacing for one Block or compose unit (not FF - use fastForwardComposeBlock for blitz).
270
282
  * @example withBlockPace(composeBlock("gap-review", [...]), "slow")
271
283
  */
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>;
284
+ export declare function withBlockPace<In extends Checkpoint<string>, Out extends Checkpoint<string>>(block: Block<In, Out>, pace: DemoPace): Block<In, Out>;
273
285
  /**
274
286
  * Marks a Flow as one that's SUPPOSED to throw - e.g. a locked-out user's
275
287
  * 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
@@ -366,6 +367,24 @@ export function withDemoPace(flow, pace) {
366
367
  modBlockVerify: (block, nameOrIndex, newCheck) => withDemoPace(flow.modBlockVerify(block, nameOrIndex, newCheck), demoPace),
367
368
  };
368
369
  }
370
+ /**
371
+ * Default highlight look for a Flow episode (size / weight / optional tone).
372
+ * Per-slot stub or {@link withHighlightFixtures} values win when set.
373
+ * @example withHighlightStyle(withDemoPace(gapFlow, "slow"), { size: "lg", weight: "bold" })
374
+ */
375
+ export function withHighlightStyle(flow, style) {
376
+ const highlightStyle = {
377
+ ...(style.tone !== undefined ? { tone: normalizeHighlightTone(style.tone) } : {}),
378
+ ...(style.size !== undefined ? { size: normalizeHighlightSize(style.size) } : {}),
379
+ ...(style.weight !== undefined ? { weight: normalizeHighlightWeight(style.weight) } : {}),
380
+ };
381
+ return {
382
+ ...flow,
383
+ highlightStyle,
384
+ withBlockVerify: (block, verify) => withHighlightStyle(flow.withBlockVerify(block, verify), highlightStyle),
385
+ modBlockVerify: (block, nameOrIndex, newCheck) => withHighlightStyle(flow.modBlockVerify(block, nameOrIndex, newCheck), highlightStyle),
386
+ };
387
+ }
369
388
  /**
370
389
  * Demo pacing for one Block or compose unit (not FF - use fastForwardComposeBlock for blitz).
371
390
  * @example withBlockPace(composeBlock("gap-review", [...]), "slow")
@@ -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. */
@@ -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: "",
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, 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, } 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, 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/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "waygraph",
3
- "version": "0.12.16",
3
+ "version": "0.12.17",
4
4
  "type": "module",
5
5
  "description": "A typed graph of reusable Blocks for driving a browser through E2E flows.",
6
6
  "license": "MIT",