@plaintake/scenario 1.10.0 → 1.12.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/index.js +47 -1
- package/dist/schema/render-plan.d.ts +21 -0
- package/dist/types.d.ts +74 -0
- package/package.json +1 -1
package/dist/index.js
CHANGED
|
@@ -443,7 +443,32 @@ var HighlightRectSchema = z5.object({
|
|
|
443
443
|
height: z5.number().int().positive(),
|
|
444
444
|
startMs: z5.number().int().nonnegative(),
|
|
445
445
|
endMs: z5.number().int().positive(),
|
|
446
|
-
label: z5.string().min(1).optional()
|
|
446
|
+
label: z5.string().min(1).optional(),
|
|
447
|
+
/**
|
|
448
|
+
* The rect the spotlight glides *from*, when this window's cutout should animate rather
|
|
449
|
+
* than cut straight to the held `x`/`y`/`width`/`height` — the pre-reveal position a
|
|
450
|
+
* step's `target` measured before a scroll-causing `reveal` settled it into place.
|
|
451
|
+
* Present only together with `settleMs`: a glide needs both where it starts and when it
|
|
452
|
+
* finishes, and one without the other cannot be drawn.
|
|
453
|
+
*
|
|
454
|
+
* Absent means exactly today's behaviour — a single static rect held for the window's
|
|
455
|
+
* whole span — so every plan frozen before this field existed, and every window a future
|
|
456
|
+
* derivation decides not to glide, is unaffected by construction.
|
|
457
|
+
*/
|
|
458
|
+
from: z5.object({
|
|
459
|
+
x: z5.number().int().min(0),
|
|
460
|
+
y: z5.number().int().min(0),
|
|
461
|
+
width: z5.number().int().positive(),
|
|
462
|
+
height: z5.number().int().positive()
|
|
463
|
+
}).optional(),
|
|
464
|
+
/**
|
|
465
|
+
* The absolute video-ms at which the glide from `from` completes and the spotlight
|
|
466
|
+
* settles into the held rect — not a duration, the same convention `startMs`/`endMs`
|
|
467
|
+
* and `CameraShot.enterMs`/`holdFromMs` already carry. Strictly after `startMs` (there
|
|
468
|
+
* has to be real time left to glide across) and no later than `endMs` (the window
|
|
469
|
+
* cannot settle after it has already closed).
|
|
470
|
+
*/
|
|
471
|
+
settleMs: z5.number().int().positive().optional()
|
|
447
472
|
}).refine(({ x, y, width, height }) => x + width <= 1920 && y + height <= 1080, {
|
|
448
473
|
// Unlike CameraShotSchema's crop window, a highlight rect is drawn by libass, not fed to
|
|
449
474
|
// `crop` — there is no yuv420p even-pixel rule to enforce — but it still has to fit the
|
|
@@ -451,6 +476,27 @@ var HighlightRectSchema = z5.object({
|
|
|
451
476
|
// meant to sit inside.
|
|
452
477
|
message: "the rect must stay inside the 1920x1080 frame",
|
|
453
478
|
path: ["x"]
|
|
479
|
+
}).refine(({ from, settleMs }) => from === void 0 === (settleMs === void 0), {
|
|
480
|
+
// A glide needs both where it starts (`from`) and when it finishes (`settleMs`) — one
|
|
481
|
+
// without the other cannot be drawn, so the pair is refused rather than tolerated as a
|
|
482
|
+
// half-declared capability.
|
|
483
|
+
message: "from and settleMs must be present together or both absent",
|
|
484
|
+
path: ["from"]
|
|
485
|
+
}).refine(
|
|
486
|
+
({ from }) => from === void 0 || from.x + from.width <= 1920 && from.y + from.height <= 1080,
|
|
487
|
+
{
|
|
488
|
+
// The same 1920x1080 containment the held rect enforces above, applied to the rect the
|
|
489
|
+
// spotlight glides from — an off-canvas starting point is no more drawable than an
|
|
490
|
+
// off-canvas held one.
|
|
491
|
+
message: "from must stay inside the 1920x1080 frame",
|
|
492
|
+
path: ["from"]
|
|
493
|
+
}
|
|
494
|
+
).refine(({ startMs, endMs, settleMs }) => settleMs === void 0 || settleMs > startMs && settleMs <= endMs, {
|
|
495
|
+
// settleMs is absolute video-ms, like startMs/endMs themselves — the glide needs real
|
|
496
|
+
// room to run (strictly after startMs) and cannot settle after its own window has
|
|
497
|
+
// already closed (no later than endMs).
|
|
498
|
+
message: "settleMs must be strictly after startMs and no later than endMs",
|
|
499
|
+
path: ["settleMs"]
|
|
454
500
|
});
|
|
455
501
|
var HighlightSchema = z5.object({
|
|
456
502
|
assPath: z5.literal("captions/highlight.ass"),
|
|
@@ -314,6 +314,13 @@ export declare const HighlightRectSchema: z.ZodObject<{
|
|
|
314
314
|
startMs: z.ZodNumber;
|
|
315
315
|
endMs: z.ZodNumber;
|
|
316
316
|
label: z.ZodOptional<z.ZodString>;
|
|
317
|
+
from: z.ZodOptional<z.ZodObject<{
|
|
318
|
+
x: z.ZodNumber;
|
|
319
|
+
y: z.ZodNumber;
|
|
320
|
+
width: z.ZodNumber;
|
|
321
|
+
height: z.ZodNumber;
|
|
322
|
+
}, z.core.$strip>>;
|
|
323
|
+
settleMs: z.ZodOptional<z.ZodNumber>;
|
|
317
324
|
}, z.core.$strip>;
|
|
318
325
|
/**
|
|
319
326
|
* The highlight track. A rect **list**, ordered and non-overlapping on the same discipline
|
|
@@ -332,6 +339,13 @@ export declare const HighlightSchema: z.ZodObject<{
|
|
|
332
339
|
startMs: z.ZodNumber;
|
|
333
340
|
endMs: z.ZodNumber;
|
|
334
341
|
label: z.ZodOptional<z.ZodString>;
|
|
342
|
+
from: z.ZodOptional<z.ZodObject<{
|
|
343
|
+
x: z.ZodNumber;
|
|
344
|
+
y: z.ZodNumber;
|
|
345
|
+
width: z.ZodNumber;
|
|
346
|
+
height: z.ZodNumber;
|
|
347
|
+
}, z.core.$strip>>;
|
|
348
|
+
settleMs: z.ZodOptional<z.ZodNumber>;
|
|
335
349
|
}, z.core.$strip>>;
|
|
336
350
|
}, z.core.$strip>;
|
|
337
351
|
export type Highlight = z.infer<typeof HighlightSchema>;
|
|
@@ -688,6 +702,13 @@ export declare const RenderPlanSchema: z.ZodObject<{
|
|
|
688
702
|
startMs: z.ZodNumber;
|
|
689
703
|
endMs: z.ZodNumber;
|
|
690
704
|
label: z.ZodOptional<z.ZodString>;
|
|
705
|
+
from: z.ZodOptional<z.ZodObject<{
|
|
706
|
+
x: z.ZodNumber;
|
|
707
|
+
y: z.ZodNumber;
|
|
708
|
+
width: z.ZodNumber;
|
|
709
|
+
height: z.ZodNumber;
|
|
710
|
+
}, z.core.$strip>>;
|
|
711
|
+
settleMs: z.ZodOptional<z.ZodNumber>;
|
|
691
712
|
}, z.core.$strip>>;
|
|
692
713
|
}, z.core.$strip>>;
|
|
693
714
|
speech: z.ZodOptional<z.ZodObject<{
|
package/dist/types.d.ts
CHANGED
|
@@ -49,6 +49,63 @@ export type DemoStep = {
|
|
|
49
49
|
voice?: string;
|
|
50
50
|
/** Extra presentation hold after the action completes, in whole milliseconds. */
|
|
51
51
|
holdMs?: number;
|
|
52
|
+
/**
|
|
53
|
+
* Scrolled into view after `run()` completes and before the hold — the opposite ordering
|
|
54
|
+
* from `target`, which is measured *before* `run()`. Exists for content the action itself
|
|
55
|
+
* reveals below the fold (a response panel that renders after a click, say): without it,
|
|
56
|
+
* an author either remembers to append a separate `Actor.scroll()` step for what is
|
|
57
|
+
* conceptually part of this one action, or the recording holds on an off-screen result.
|
|
58
|
+
*
|
|
59
|
+
* Independent of `target`: the element acted on and the element revealed are often not
|
|
60
|
+
* the same one, and a step may declare `reveal` with none at all.
|
|
61
|
+
*
|
|
62
|
+
* Not best-effort like `target`'s measurement — a `reveal` locator that never appears
|
|
63
|
+
* fails the step normally, the same as `run()` itself or `Actor.scroll`'s own unguarded
|
|
64
|
+
* `scrollIntoViewIfNeeded()`, because unlike `target` (inert metadata) this performs a
|
|
65
|
+
* real action with a real effect on what capture sees.
|
|
66
|
+
*
|
|
67
|
+
* `target` (if declared) is re-measured, best-effort, once this scroll settles: the
|
|
68
|
+
* settled rect and a real "revealed at" timestamp both ride on `step.finish`, alongside
|
|
69
|
+
* the pre-scroll rect `step.start` already carried. Camera zoom and `highlight` both
|
|
70
|
+
* prefer that settled rect over the stale one once it is written, so declaring the same
|
|
71
|
+
* locator as both `target` and `reveal` is the supported way to have them frame the
|
|
72
|
+
* revealed content rather than the position it was scrolled away from —
|
|
73
|
+
* `Actor.scroll`'s own locator form takes the mirror-image approach of scrolling in
|
|
74
|
+
* `prepare`, *before* measuring, for the same reason (see its comment); `reveal` cannot
|
|
75
|
+
* do that since the scroll it causes is itself a consequence of `run()`. Camera zoom
|
|
76
|
+
* additionally anchors a shot's settle time to the *later* of the click and the reveal
|
|
77
|
+
* completing, rather than the click alone, so a `run()` that keeps the page busy after
|
|
78
|
+
* the click (rendering a response panel, say) does not leave the camera's pan finished
|
|
79
|
+
* before the captured frames actually show the revealed content. That push has a limit,
|
|
80
|
+
* though: if this step's reveal is slow AND the next step follows in quick succession,
|
|
81
|
+
* the settle time is pulled earlier so it cannot land after the next step's own arrival —
|
|
82
|
+
* preserving step order rather than exactly matching when the reveal finished, diagnosed
|
|
83
|
+
* with `camera.compressed` when it binds.
|
|
84
|
+
*
|
|
85
|
+
* The scroll itself is a real, live glide (`smoothScrollIntoView` in `recorder-playwright`),
|
|
86
|
+
* not an instant jump — a genuine rAF-driven ease over the capture's own variable-frame-rate
|
|
87
|
+
* screencast, the one piece of on-screen motion in a plaintake recording that is not
|
|
88
|
+
* synthesised at render time from frozen numbers. See that function's doc comment for why a
|
|
89
|
+
* live capture can show it without touching the byte-reproducibility guarantee, which has
|
|
90
|
+
* only ever covered re-rendering an already-frozen bundle.
|
|
91
|
+
*
|
|
92
|
+
* Two narrower caveats remain, both because they cannot be *re*-measured the way `target`
|
|
93
|
+
* is: (a) the cursor arrow itself still marks the pre-scroll click position and does not
|
|
94
|
+
* chase the settled rect, so a large reveal-scroll can leave the arrow outside a
|
|
95
|
+
* tightly-zoomed shot for the rest of the hold; (b) on a `click`-action step specifically,
|
|
96
|
+
* `highlight`'s spotlight window is a brief pulse bracketing the click, with no structural
|
|
97
|
+
* room for a glide to read as intentional motion rather than a timing glitch — it still
|
|
98
|
+
* settles on the target rect instantly, a property of that window's own timing rather than
|
|
99
|
+
* a gap left to close later. Non-click actions (`type`/`point`/`scroll`) are different:
|
|
100
|
+
* their window already spans to the step's own end, so when the pre-reveal and settled
|
|
101
|
+
* rects genuinely differ, the spotlight glides between them at render time — timed to when
|
|
102
|
+
* the reveal actually finished, not the window's own edges — falling back to the same
|
|
103
|
+
* instant settle when there isn't genuinely enough of that window left to glide across,
|
|
104
|
+
* or when the pre-reveal position itself was never usable (no area, or entirely off-frame).
|
|
105
|
+
*
|
|
106
|
+
* Also: if `run()` throws, this scroll never executes — the step fails before reaching it.
|
|
107
|
+
*/
|
|
108
|
+
reveal?: Locator;
|
|
52
109
|
run: () => Promise<unknown>;
|
|
53
110
|
};
|
|
54
111
|
export type DemoAssertion = {
|
|
@@ -304,8 +361,25 @@ export type ActorStepMeta = {
|
|
|
304
361
|
highlight?: boolean | {
|
|
305
362
|
label?: string;
|
|
306
363
|
};
|
|
364
|
+
/** See `DemoStep.reveal`. */
|
|
365
|
+
reveal?: Locator;
|
|
307
366
|
/** See `DemoStep.voice` — one verb-call override, ahead of this actor's own `voice`. */
|
|
308
367
|
voice?: string;
|
|
368
|
+
/**
|
|
369
|
+
* Alignment `Actor.scroll`'s locator form settles the viewport on, mirroring
|
|
370
|
+
* `Element.scrollIntoView`'s own `block`. Only `scroll` reads this — every other verb
|
|
371
|
+
* has no notion of where the viewport ends up after it runs, so this is silently ignored
|
|
372
|
+
* elsewhere. Absent means `'center'`, the same default a bare `scrollIntoView()` call has.
|
|
373
|
+
*/
|
|
374
|
+
block?: 'start' | 'center' | 'end' | 'nearest';
|
|
375
|
+
/**
|
|
376
|
+
* Minimum gap, in pixels, `Actor.scroll`'s locator form leaves between the target and the
|
|
377
|
+
* edge `block` settles it against — breathing room so the target doesn't land flush
|
|
378
|
+
* against the viewport edge. Only meaningful alongside `block: 'start'` or `'end'`, which
|
|
379
|
+
* name an edge; ignored for `'center'`/`'nearest'` and by every verb but `scroll`. Absent
|
|
380
|
+
* means 0, flush with the edge.
|
|
381
|
+
*/
|
|
382
|
+
paddingPx?: number;
|
|
309
383
|
};
|
|
310
384
|
/**
|
|
311
385
|
* A named participant in a multi-actor demo: its own Playwright `BrowserContext`, its own
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@plaintake/scenario",
|
|
3
|
-
"version": "1.
|
|
3
|
+
"version": "1.12.0",
|
|
4
4
|
"description": "Authoring SDK for PlainTake demo scenarios: defineDemo and the scenario DSL types. Install for editor autocomplete; the PlainTake binary ships a runtime fallback.",
|
|
5
5
|
"license": "MIT",
|
|
6
6
|
"type": "module",
|