screenci 0.0.68 → 0.0.70

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.
Files changed (161) hide show
  1. package/README.md +45 -122
  2. package/dist/cli.d.ts +3 -18
  3. package/dist/cli.d.ts.map +1 -1
  4. package/dist/cli.js +117 -158
  5. package/dist/cli.js.map +1 -1
  6. package/dist/docs/manifest.d.ts +66 -35
  7. package/dist/docs/manifest.d.ts.map +1 -1
  8. package/dist/docs/manifest.js +22 -11
  9. package/dist/docs/manifest.js.map +1 -1
  10. package/dist/docs/video-sources/cli.screenci.d.ts +2 -0
  11. package/dist/docs/video-sources/cli.screenci.d.ts.map +1 -0
  12. package/dist/docs/video-sources/{cli.video.js → cli.screenci.js} +1 -1
  13. package/dist/docs/video-sources/cli.screenci.js.map +1 -0
  14. package/dist/docs/video-sources/installation.screenci.d.ts +2 -0
  15. package/dist/docs/video-sources/installation.screenci.d.ts.map +1 -0
  16. package/dist/docs/video-sources/{installation.video.js → installation.screenci.js} +1 -1
  17. package/dist/docs/video-sources/installation.screenci.js.map +1 -0
  18. package/dist/docs/video-sources/landing.screenci.d.ts +2 -0
  19. package/dist/docs/video-sources/landing.screenci.d.ts.map +1 -0
  20. package/dist/docs/video-sources/{landing.video.js → landing.screenci.js} +1 -1
  21. package/dist/docs/video-sources/landing.screenci.js.map +1 -0
  22. package/dist/docs/video-sources/locator-highlight-animated.screenci.d.ts +2 -0
  23. package/dist/docs/video-sources/locator-highlight-animated.screenci.d.ts.map +1 -0
  24. package/dist/docs/video-sources/locator-highlight-animated.screenci.js +53 -0
  25. package/dist/docs/video-sources/locator-highlight-animated.screenci.js.map +1 -0
  26. package/dist/docs/video-sources/locator-highlight-still.screenci.d.ts +2 -0
  27. package/dist/docs/video-sources/locator-highlight-still.screenci.d.ts.map +1 -0
  28. package/dist/docs/video-sources/locator-highlight-still.screenci.js +24 -0
  29. package/dist/docs/video-sources/locator-highlight-still.screenci.js.map +1 -0
  30. package/dist/docs/video-sources/product-pitch.screenci.d.ts +2 -0
  31. package/dist/docs/video-sources/product-pitch.screenci.d.ts.map +1 -0
  32. package/dist/docs/video-sources/product-pitch.screenci.js +136 -0
  33. package/dist/docs/video-sources/product-pitch.screenci.js.map +1 -0
  34. package/dist/docs/video-sources/public-urls.screenci.d.ts +2 -0
  35. package/dist/docs/video-sources/public-urls.screenci.d.ts.map +1 -0
  36. package/dist/docs/video-sources/public-urls.screenci.js +34 -0
  37. package/dist/docs/video-sources/public-urls.screenci.js.map +1 -0
  38. package/dist/docs/video-sources/studio.screenci.d.ts +2 -0
  39. package/dist/docs/video-sources/studio.screenci.d.ts.map +1 -0
  40. package/dist/docs/video-sources/studio.screenci.js +57 -0
  41. package/dist/docs/video-sources/studio.screenci.js.map +1 -0
  42. package/dist/docs/videos.d.ts +36 -15
  43. package/dist/docs/videos.d.ts.map +1 -1
  44. package/dist/docs/videos.js +27 -2
  45. package/dist/docs/videos.js.map +1 -1
  46. package/dist/e2e/htmlRasterizer.e2e.d.ts +2 -0
  47. package/dist/e2e/htmlRasterizer.e2e.d.ts.map +1 -0
  48. package/dist/e2e/htmlRasterizer.e2e.js +107 -0
  49. package/dist/e2e/htmlRasterizer.e2e.js.map +1 -0
  50. package/dist/e2e/screenshot.e2e.d.ts +2 -0
  51. package/dist/e2e/screenshot.e2e.d.ts.map +1 -0
  52. package/dist/e2e/screenshot.e2e.js +73 -0
  53. package/dist/e2e/screenshot.e2e.js.map +1 -0
  54. package/dist/index.d.ts +10 -4
  55. package/dist/index.d.ts.map +1 -1
  56. package/dist/index.js +5 -2
  57. package/dist/index.js.map +1 -1
  58. package/dist/src/asset.d.ts +245 -53
  59. package/dist/src/asset.d.ts.map +1 -1
  60. package/dist/src/asset.js +718 -77
  61. package/dist/src/asset.js.map +1 -1
  62. package/dist/src/audio.d.ts +127 -0
  63. package/dist/src/audio.d.ts.map +1 -0
  64. package/dist/src/audio.js +207 -0
  65. package/dist/src/audio.js.map +1 -0
  66. package/dist/src/config.d.ts.map +1 -1
  67. package/dist/src/config.js +9 -3
  68. package/dist/src/config.js.map +1 -1
  69. package/dist/src/contextOptions.d.ts +48 -0
  70. package/dist/src/contextOptions.d.ts.map +1 -0
  71. package/dist/src/contextOptions.js +71 -0
  72. package/dist/src/contextOptions.js.map +1 -0
  73. package/dist/src/crop.d.ts +93 -0
  74. package/dist/src/crop.d.ts.map +1 -0
  75. package/dist/src/crop.js +133 -0
  76. package/dist/src/crop.js.map +1 -0
  77. package/dist/src/cue.d.ts +17 -4
  78. package/dist/src/cue.d.ts.map +1 -1
  79. package/dist/src/cue.js +31 -3
  80. package/dist/src/cue.js.map +1 -1
  81. package/dist/src/defaults.d.ts +13 -1
  82. package/dist/src/defaults.d.ts.map +1 -1
  83. package/dist/src/defaults.js +13 -0
  84. package/dist/src/defaults.js.map +1 -1
  85. package/dist/src/dimensions.d.ts +6 -0
  86. package/dist/src/dimensions.d.ts.map +1 -1
  87. package/dist/src/dimensions.js +15 -0
  88. package/dist/src/dimensions.js.map +1 -1
  89. package/dist/src/events.d.ts +283 -13
  90. package/dist/src/events.d.ts.map +1 -1
  91. package/dist/src/events.js +134 -5
  92. package/dist/src/events.js.map +1 -1
  93. package/dist/src/htmlRasterizer.d.ts +153 -0
  94. package/dist/src/htmlRasterizer.d.ts.map +1 -0
  95. package/dist/src/htmlRasterizer.js +386 -0
  96. package/dist/src/htmlRasterizer.js.map +1 -0
  97. package/dist/src/init.d.ts +17 -0
  98. package/dist/src/init.d.ts.map +1 -1
  99. package/dist/src/init.js +131 -11
  100. package/dist/src/init.js.map +1 -1
  101. package/dist/src/linkSession.d.ts +36 -0
  102. package/dist/src/linkSession.d.ts.map +1 -0
  103. package/dist/src/linkSession.js +122 -0
  104. package/dist/src/linkSession.js.map +1 -0
  105. package/dist/src/overlayFlush.d.ts +18 -0
  106. package/dist/src/overlayFlush.d.ts.map +1 -0
  107. package/dist/src/overlayFlush.js +56 -0
  108. package/dist/src/overlayFlush.js.map +1 -0
  109. package/dist/src/overlayRect.d.ts +69 -0
  110. package/dist/src/overlayRect.d.ts.map +1 -0
  111. package/dist/src/overlayRect.js +55 -0
  112. package/dist/src/overlayRect.js.map +1 -0
  113. package/dist/src/performance.d.ts +1 -3
  114. package/dist/src/performance.d.ts.map +1 -1
  115. package/dist/src/performance.js +0 -12
  116. package/dist/src/performance.js.map +1 -1
  117. package/dist/src/recording.d.ts +3 -2
  118. package/dist/src/recording.d.ts.map +1 -1
  119. package/dist/src/recordingData.d.ts +22 -2
  120. package/dist/src/recordingData.d.ts.map +1 -1
  121. package/dist/src/runtimeContext.d.ts +57 -1
  122. package/dist/src/runtimeContext.d.ts.map +1 -1
  123. package/dist/src/runtimeContext.js +40 -0
  124. package/dist/src/runtimeContext.js.map +1 -1
  125. package/dist/src/screenshot.d.ts +105 -0
  126. package/dist/src/screenshot.d.ts.map +1 -0
  127. package/dist/src/screenshot.js +188 -0
  128. package/dist/src/screenshot.js.map +1 -0
  129. package/dist/src/stillCapture.d.ts +68 -0
  130. package/dist/src/stillCapture.d.ts.map +1 -0
  131. package/dist/src/stillCapture.js +119 -0
  132. package/dist/src/stillCapture.js.map +1 -0
  133. package/dist/src/studio.d.ts +8 -11
  134. package/dist/src/studio.d.ts.map +1 -1
  135. package/dist/src/studio.js +2 -25
  136. package/dist/src/studio.js.map +1 -1
  137. package/dist/src/types.d.ts +125 -15
  138. package/dist/src/types.d.ts.map +1 -1
  139. package/dist/src/types.js.map +1 -1
  140. package/dist/src/video.d.ts +54 -1
  141. package/dist/src/video.d.ts.map +1 -1
  142. package/dist/src/video.js +190 -42
  143. package/dist/src/video.js.map +1 -1
  144. package/dist/src/voices.d.ts +22 -9
  145. package/dist/src/voices.d.ts.map +1 -1
  146. package/dist/src/voices.js +6 -24
  147. package/dist/src/voices.js.map +1 -1
  148. package/dist/tsconfig.tsbuildinfo +1 -1
  149. package/package.json +16 -2
  150. package/skills/screenci/SKILL.md +37 -15
  151. package/skills/screenci/references/init.md +3 -1
  152. package/skills/screenci/references/record.md +8 -3
  153. package/dist/docs/video-sources/cli.video.d.ts +0 -2
  154. package/dist/docs/video-sources/cli.video.d.ts.map +0 -1
  155. package/dist/docs/video-sources/cli.video.js.map +0 -1
  156. package/dist/docs/video-sources/installation.video.d.ts +0 -2
  157. package/dist/docs/video-sources/installation.video.d.ts.map +0 -1
  158. package/dist/docs/video-sources/installation.video.js.map +0 -1
  159. package/dist/docs/video-sources/landing.video.d.ts +0 -2
  160. package/dist/docs/video-sources/landing.video.d.ts.map +0 -1
  161. package/dist/docs/video-sources/landing.video.js.map +0 -1
@@ -1,85 +1,267 @@
1
+ import type { Locator } from '@playwright/test';
1
2
  import type { IEventRecorder } from './events.js';
2
- export type SvgPath = `${string}.svg`;
3
- export type PngPath = `${string}.png`;
4
- export type Mp4Path = `${string}.mp4`;
3
+ export { setOverlayCss } from './htmlRasterizer.js';
4
+ export type { OverlayPlacement } from './events.js';
5
5
  /**
6
- * Image assets are timed overlays. The duration must be recorded up front so
7
- * rendering never needs to probe image files for timing.
6
+ * Minimal structural stand-in for a React element. Defined here so the core SDK
7
+ * never has to depend on `@types/react`: any JSX element is assignable to this,
8
+ * while a plain {@link OverlayConfig} object is not (it has no `type`/`props`).
9
+ * React itself is detected structurally at runtime and rendered lazily, so it
10
+ * stays an optional peer dependency.
8
11
  */
9
- export type ImageAssetConfig<TPath extends SvgPath | PngPath = SvgPath | PngPath> = {
10
- path: TPath;
11
- durationMs: number;
12
- fullScreen: boolean;
13
- audio?: never;
12
+ export type ReactElementLike = {
13
+ type: unknown;
14
+ props: unknown;
15
+ key?: string | null;
14
16
  };
15
17
  /**
16
- * Video assets use their natural media duration. Audio is allowed only here so
17
- * the API cannot attach soundtrack controls to still-image overlays. When
18
- * omitted, audio defaults to full volume for `.mp4` playback.
18
+ * Display options for an overlay. Placement fields are flat (not nested) and use
19
+ * CSS pixels in the recording viewport (the same space as Playwright's
20
+ * `boundingBox()`, `page.mouse`, and `viewportSize()`), each defaulting
21
+ * independently: `relativeTo: 'recording'`, `x: 0`, `y: 0`. Provide exactly one
22
+ * of `width`/`height` (the other follows the source aspect, or `aspectRatio`).
23
+ * When no placement field is set, the overlay fills the recording area.
19
24
  */
20
- export type VideoAssetConfig<TPath extends Mp4Path = Mp4Path> = {
21
- path: TPath;
25
+ export type OverlayConfig = {
26
+ /** File path: `.html` (rendered), `.svg`/`.png` (image), or `.mp4` (video). */
27
+ path?: string;
28
+ /**
29
+ * A React element, rendered to a transparent PNG. Use this for overlays built
30
+ * in JSX. Provide exactly one source: `path`, `element`, or `html`.
31
+ */
32
+ element?: ReactElementLike;
33
+ /**
34
+ * An inline HTML fragment, rendered to a transparent PNG. Use this when you
35
+ * want plain HTML without a React dependency or a separate `.html` file. It
36
+ * must be a fragment (for example `'<div class="badge">New</div>'`), never a
37
+ * full document: `<!doctype>`, `<html>`, `<head>`, and `<body>` tags are
38
+ * rejected because screenci wraps the markup in its own document. Provide
39
+ * exactly one source: `path`, `element`, or `html`.
40
+ */
41
+ html?: string;
42
+ /** Reference box for placement coordinates. Defaults to `'recording'`. */
43
+ relativeTo?: 'screen' | 'recording';
44
+ /** Left edge in CSS px of the recording viewport. Defaults to `0`. */
45
+ x?: number;
46
+ /** Top edge in CSS px of the recording viewport. Defaults to `0`. */
47
+ y?: number;
48
+ /** Width in CSS px. Provide instead of `height` (exactly one). */
49
+ width?: number;
50
+ /** Height in CSS px. Provide instead of `width` (exactly one). */
51
+ height?: number;
52
+ /**
53
+ * Aspect ratio (`width / height`) used to derive the unset axis from the one
54
+ * you provide, instead of the source's intrinsic aspect. Optional.
55
+ */
56
+ aspectRatio?: number;
57
+ /** Fill the whole output frame. Overrides x/y/width/height. */
58
+ fullScreen?: boolean;
59
+ /**
60
+ * Position the overlay over a live element, captured at recording time from
61
+ * the locator's bounding box. The overlay is sized to that box (plus
62
+ * {@link margin}) and fills it, so it frames the element exactly. Overrides
63
+ * `x`/`y`/`width`/`height`/`relativeTo`/`fullScreen` (placement is always
64
+ * recording-relative). HTML files, inline `html`, and React elements only;
65
+ * your content should fill its box (for example `width:100%;height:100%`).
66
+ */
67
+ over?: Locator;
68
+ /**
69
+ * Extra space (CSS px) added around the {@link over} element on every side,
70
+ * so the overlay surrounds it rather than sitting exactly on its edges. Only
71
+ * valid together with `over`.
72
+ */
73
+ margin?: number;
74
+ /**
75
+ * Visible length for the blocking call form (`await overlays.logo(1200)`).
76
+ * Omit when driving with `start()`/`end()`. Image/HTML/React overlays only.
77
+ *
78
+ * For animated overlays (`animate: true`) this is also the capture length: it
79
+ * is required when driving with `start()`/`end()` (the capture length is
80
+ * otherwise unknown).
81
+ */
82
+ durationMs?: number;
83
+ /**
84
+ * Capture the overlay as an animation so its CSS/JS animation plays back in
85
+ * the video (HTML files and React elements only). The animation is sampled
86
+ * over the resolved duration with a transparent background preserved.
87
+ */
88
+ animate?: boolean;
89
+ /** Animation capture frame rate. Only valid with `animate`. Defaults to `30`. */
90
+ fps?: number;
91
+ /**
92
+ * Extra CSS injected into the overlay document so it can be styled with
93
+ * `className` (for example a compiled Tailwind stylesheet). Merged on top of
94
+ * any global CSS set via `setOverlayCss`. HTML files and React elements only.
95
+ */
96
+ css?: string;
97
+ /**
98
+ * Transparent padding (CSS px) added around the overlay content. Lets an
99
+ * animation move, scale, or rotate beyond its box without being clipped (an
100
+ * automatic "stage"), at the cost of the placement sizing the padded box.
101
+ * HTML files and React elements only.
102
+ */
103
+ capturePadding?: number;
104
+ /**
105
+ * Soundtrack level for `.mp4` overlays as a linear gain. `1` (the default)
106
+ * plays the source at its natural level, `0` mutes it, and values above `1`
107
+ * boost it (e.g. `2` is twice the natural level). Capped at
108
+ * {@link MAX_AUDIO_LEVEL}.
109
+ */
22
110
  audio?: number;
23
- fullScreen: boolean;
24
- durationMs?: never;
111
+ /**
112
+ * Playback-rate multiplier for `.mp4` overlays. `2` plays the clip (and its
113
+ * audio) twice as fast, `0.5` at half speed; `1` (the default) is the natural
114
+ * rate. Works like {@link speed} for a recording. For a blocking overlay
115
+ * (`await overlays.clip()`) this also shortens or lengthens the window it
116
+ * holds, so later content shifts; a live overlay (`start()`/`end()`) keeps
117
+ * its window and just plays the source faster/slower inside it. Mutually
118
+ * exclusive with {@link time}. Video overlays only.
119
+ */
120
+ speed?: number;
121
+ /**
122
+ * Target playback duration (ms) for a `.mp4` overlay, an alternative to
123
+ * {@link speed}: the clip is sped up or slowed down so its source plays over
124
+ * exactly this long. Works like {@link time} for a recording. Mutually
125
+ * exclusive with {@link speed}. Video overlays only.
126
+ */
127
+ time?: number;
25
128
  };
26
- export type AssetConfig = ImageAssetConfig<SvgPath | PngPath> | VideoAssetConfig<Mp4Path>;
27
- type AssetConfigForPath<TPath extends string> = string extends TPath ? AssetConfig : TPath extends SvgPath | PngPath ? ImageAssetConfig<TPath> : TPath extends Mp4Path ? VideoAssetConfig<TPath> : never;
129
+ /**
130
+ * Upper bound for an audio level (linear gain). `4` is +12 dB, plenty of
131
+ * headroom for a boost while guarding against accidental extreme distortion.
132
+ */
133
+ export declare const MAX_AUDIO_LEVEL = 4;
134
+ /**
135
+ * A value accepted by {@link createOverlays} for each key:
136
+ *
137
+ * - a `string` file path (`.html`/`.svg`/`.png`/`.mp4`),
138
+ * - a React element, or
139
+ * - an {@link OverlayConfig} object.
140
+ */
141
+ export type OverlayInput = string | ReactElementLike | OverlayConfig;
142
+ /**
143
+ * A factory that builds an {@link OverlayConfig} from caller-supplied props.
144
+ * Use this to make an overlay programmatic: the returned config (its content and
145
+ * its placement) can depend on values only known at runtime, for example a
146
+ * locator's position captured with {@link overlayRect}. Both the `element`/`html`
147
+ * content and the placement may vary per call.
148
+ *
149
+ * @example
150
+ * ```tsx
151
+ * const overlays = createOverlays({
152
+ * note: (p: { text: string }) => ({ html: `<div class="note">${p.text}</div>` }),
153
+ * })
154
+ * await overlays.note({ text: 'Saved' })(1200)
155
+ * ```
156
+ */
157
+ export type OverlayConfigFactory<P = unknown> = (props: P) => OverlayConfig;
158
+ /**
159
+ * A value accepted by {@link createOverlays}: a static input or a config
160
+ * factory. The factory arm uses a `never` parameter so a factory with any
161
+ * concrete props type is assignable (function parameters are contravariant);
162
+ * {@link OverlayControllerFor} then recovers the real props type per key.
163
+ */
164
+ export type OverlayInputOrFactory = OverlayInput | ((props: never) => OverlayConfig);
165
+ export declare function setAssetSleepFn(fn: (ms: number) => void): void;
28
166
  export declare function setActiveAssetRecorder(recorder: IEventRecorder | null): void;
29
167
  export declare function resetRegisteredAssetPaths(): void;
168
+ export declare function resetAssetChain(): void;
30
169
  export declare function validateRegisteredAssetPaths(testFilePath: string): Promise<void>;
31
170
  /**
32
- * An asset controller.
171
+ * An overlay controller.
33
172
  *
34
- * Calling it marks the asset in the recording timeline. The renderer places
35
- * the asset at this point in the video. Images use explicit `durationMs`
36
- * overlays; `.mp4` assets use the media file's natural duration.
173
+ * Calling it shows the overlay over a frozen frame for a fixed duration
174
+ * (blocking). Use `start()`/`end()` to keep the overlay on screen while the page
175
+ * is driven underneath.
176
+ *
177
+ * Overlays may overlap: several can be live at once (interleaved, not just
178
+ * nested), and a blocking overlay can run while others stay live. Each overlay
179
+ * you `start()` must be `end()`ed before the video function returns, and the
180
+ * same overlay cannot be started twice without ending it in between.
37
181
  *
38
182
  * @example
39
183
  * ```ts
40
- * await assets.intro()
41
- * await page.goto('/dashboard')
42
- * await assets.logo()
184
+ * // Blocking: hold the overlay for 1.2s, then continue.
185
+ * await overlays.logo(1200)
186
+ *
187
+ * // Live: keep the overlay up while interacting with the page.
188
+ * await overlays.badge.start()
189
+ * await page.click('#next')
190
+ * await overlays.badge.end()
191
+ *
192
+ * // Overlapping: two overlays live at the same time, ended independently.
193
+ * await overlays.badge.start()
194
+ * await overlays.logo.start()
195
+ * await page.click('#next')
196
+ * await overlays.badge.end()
197
+ * await overlays.logo.end()
43
198
  * ```
44
199
  */
45
- export type AssetController = () => Promise<void>;
46
- /** Typed asset controllers keyed by the names passed to {@link createAssets}. */
47
- export type Assets<T extends Record<string, AssetConfig>> = {
48
- [K in keyof T]: AssetController;
200
+ export type OverlayController = {
201
+ (durationMs?: number): Promise<void>;
202
+ start(): Promise<void>;
203
+ end(): Promise<void>;
49
204
  };
50
205
  /**
51
- * Creates a set of typed asset controllers, one per key in the map.
206
+ * The controller type for one {@link createOverlays} value: a static input
207
+ * (string/element/config) yields a plain {@link OverlayController}; a config
208
+ * factory yields a `(props) => OverlayController` so props are passed at the
209
+ * call site. A static input is never callable, so it never matches the factory
210
+ * arm: existing static maps keep exactly today's controller type.
211
+ */
212
+ export type OverlayControllerFor<V> = V extends (props: infer P) => OverlayConfig ? (props: P) => OverlayController : OverlayController;
213
+ /** Typed overlay controllers keyed by the names passed to {@link createOverlays}. */
214
+ export type Overlays<T extends Record<string, OverlayInputOrFactory>> = {
215
+ [K in keyof T]: OverlayControllerFor<T[K]>;
216
+ };
217
+ /**
218
+ * Creates a set of typed overlay controllers, one per key in the map. Each value
219
+ * is a file path string, a React element, or an {@link OverlayConfig} object.
220
+ * A config can draw its content from exactly one source: a file `path`, a React
221
+ * `element`, or an inline `html` fragment.
222
+ *
223
+ * Calling a controller shows the overlay in the recording timeline. Image
224
+ * (`.svg`/`.png`), HTML, and React overlays need a `durationMs` (in the config
225
+ * or passed to the blocking call) unless driven with `start()`/`end()`; `.mp4`
226
+ * overlays use their natural duration and default `audio` to `1` (natural level).
52
227
  *
53
- * Calling a controller marks the asset in the recording timeline.
54
- * `.svg`/`.png` assets require explicit `durationMs`; `.mp4` assets use their
55
- * natural duration and default `audio` to `1` when omitted.
228
+ * Placement defaults to the full recording area (`relativeTo: 'recording'`);
229
+ * override any field independently. Coordinates are CSS px of the recording
230
+ * viewport.
56
231
  *
57
232
  * @example
58
- * ```ts
59
- * const assets = createAssets({
60
- * logo: { path: './logo.png', durationMs: 1200, fullScreen: false },
61
- * intro: { path: './intro.mp4', fullScreen: true },
233
+ * ```tsx
234
+ * const overlays = createOverlays({
235
+ * hint: 'callout.html', // HTML file
236
+ * badge: <Badge label="New" />, // React element
237
+ * note: { html: '<div class="note">Tip</div>', x: 1340, y: 110, width: 380 },
238
+ * logo: { path: 'logo.png', x: 96, y: 96, width: 240 },
239
+ * intro: { path: 'intro.mp4', fullScreen: true },
62
240
  * })
63
241
  *
64
242
  * video('Product demo', async ({ page }) => {
65
- * await assets.intro()
243
+ * await overlays.intro()
66
244
  * await page.goto('/dashboard')
67
- * await assets.logo()
245
+ * await overlays.logo(1200)
68
246
  * })
69
247
  * ```
248
+ *
249
+ * A value can also be an {@link OverlayConfigFactory} `(props) => OverlayConfig`,
250
+ * making the overlay programmatic. Calling `overlays.name(props)` builds and
251
+ * returns a controller you then drive with `(durationMs)`, `start()`, or
252
+ * `end()`. The factory runs (and its config is validated) on each call, so
253
+ * content and placement can depend on runtime values.
70
254
  */
71
- export declare function createAssets<const T extends Record<string, AssetConfig>>(assetsMap: T & {
72
- [K in keyof T]: AssetConfigForPath<T[K]['path']>;
73
- }): Assets<T>;
255
+ export declare function createOverlays<const T extends Record<string, OverlayInputOrFactory>>(overlays: T): Overlays<T>;
74
256
  /**
75
- * Creates typed asset controllers whose files and display options are
257
+ * Creates typed overlay controllers whose files and display options are
76
258
  * configured on the ScreenCI Studio page instead of in code. Business tier
77
259
  * only.
78
260
  *
79
- * Each key becomes a callable asset controller with the same timeline
80
- * behavior as {@link createAssets} controllers. The file (`.svg`, `.png`, or
81
- * `.mp4`), full-screen mode, image duration, and video audio level all come
82
- * from Studio.
261
+ * Each key becomes a callable overlay controller with the same timeline
262
+ * behavior as {@link createOverlays} controllers, including `start()`/`end()`.
263
+ * The file (`.svg`, `.png`, or `.mp4`), placement, image duration, and video
264
+ * audio level all come from Studio.
83
265
  *
84
266
  * On the first upload of a studio-mode video, rendering is held until the
85
267
  * video is configured in Studio (the CLI prints a direct link). Later uploads
@@ -87,15 +269,25 @@ export declare function createAssets<const T extends Record<string, AssetConfig>
87
269
  *
88
270
  * @example
89
271
  * ```ts
90
- * const assets = createStudioAssets('intro', 'logo')
272
+ * const overlays = createStudioOverlays('intro', 'logo')
91
273
  *
92
274
  * video('Product demo', async ({ page }) => {
93
- * await assets.intro()
275
+ * await overlays.intro()
94
276
  * await page.goto('/dashboard')
95
- * await assets.logo()
277
+ * await overlays.logo()
96
278
  * })
97
279
  * ```
98
280
  */
99
- export declare function createStudioAssets<const K extends readonly [string, ...string[]]>(...keys: K): Record<K[number], AssetController>;
100
- export {};
281
+ export declare function createStudioOverlays<const K extends readonly [string, ...string[]]>(...keys: K): Record<K[number], OverlayController>;
282
+ /**
283
+ * Upper bound for a playback-speed multiplier. `16` is already an extreme rate;
284
+ * the cap guards against accidental runaway values producing degenerate output.
285
+ */
286
+ export declare const MAX_SPEED = 16;
287
+ /**
288
+ * Validates a `speed`/`time` pair shared by `.mp4` overlays and audio tracks.
289
+ * `speed` must be a finite multiplier in `(0, MAX_SPEED]`; `time` must be a
290
+ * finite duration greater than 0 (ms). They are mutually exclusive.
291
+ */
292
+ export declare function validateSpeedTime(label: string, speed: number | undefined, time: number | undefined): void;
101
293
  //# sourceMappingURL=asset.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"asset.d.ts","sourceRoot":"","sources":["../../src/asset.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,aAAa,CAAA;AASjD,MAAM,MAAM,OAAO,GAAG,GAAG,MAAM,MAAM,CAAA;AACrC,MAAM,MAAM,OAAO,GAAG,GAAG,MAAM,MAAM,CAAA;AACrC,MAAM,MAAM,OAAO,GAAG,GAAG,MAAM,MAAM,CAAA;AAErC;;;GAGG;AACH,MAAM,MAAM,gBAAgB,CAC1B,KAAK,SAAS,OAAO,GAAG,OAAO,GAAG,OAAO,GAAG,OAAO,IACjD;IACF,IAAI,EAAE,KAAK,CAAA;IACX,UAAU,EAAE,MAAM,CAAA;IAClB,UAAU,EAAE,OAAO,CAAA;IACnB,KAAK,CAAC,EAAE,KAAK,CAAA;CACd,CAAA;AAED;;;;GAIG;AACH,MAAM,MAAM,gBAAgB,CAAC,KAAK,SAAS,OAAO,GAAG,OAAO,IAAI;IAC9D,IAAI,EAAE,KAAK,CAAA;IACX,KAAK,CAAC,EAAE,MAAM,CAAA;IACd,UAAU,EAAE,OAAO,CAAA;IACnB,UAAU,CAAC,EAAE,KAAK,CAAA;CACnB,CAAA;AAED,MAAM,MAAM,WAAW,GACnB,gBAAgB,CAAC,OAAO,GAAG,OAAO,CAAC,GACnC,gBAAgB,CAAC,OAAO,CAAC,CAAA;AAE7B,KAAK,kBAAkB,CAAC,KAAK,SAAS,MAAM,IAAI,MAAM,SAAS,KAAK,GAChE,WAAW,GACX,KAAK,SAAS,OAAO,GAAG,OAAO,GAC7B,gBAAgB,CAAC,KAAK,CAAC,GACvB,KAAK,SAAS,OAAO,GACnB,gBAAgB,CAAC,KAAK,CAAC,GACvB,KAAK,CAAA;AAIb,wBAAgB,sBAAsB,CAAC,QAAQ,EAAE,cAAc,GAAG,IAAI,GAAG,IAAI,CAE5E;AAED,wBAAgB,yBAAyB,IAAI,IAAI,CAEhD;AAED,wBAAsB,4BAA4B,CAChD,YAAY,EAAE,MAAM,GACnB,OAAO,CAAC,IAAI,CAAC,CAIf;AAuBD;;;;;;;;;;;;;GAaG;AACH,MAAM,MAAM,eAAe,GAAG,MAAM,OAAO,CAAC,IAAI,CAAC,CAAA;AAEjD,iFAAiF;AACjF,MAAM,MAAM,MAAM,CAAC,CAAC,SAAS,MAAM,CAAC,MAAM,EAAE,WAAW,CAAC,IAAI;KACzD,CAAC,IAAI,MAAM,CAAC,GAAG,eAAe;CAChC,CAAA;AAED;;;;;;;;;;;;;;;;;;;;GAoBG;AACH,wBAAgB,YAAY,CAAC,KAAK,CAAC,CAAC,SAAS,MAAM,CAAC,MAAM,EAAE,WAAW,CAAC,EACtE,SAAS,EAAE,CAAC,GAAG;KAAG,CAAC,IAAI,MAAM,CAAC,GAAG,kBAAkB,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC;CAAE,GAClE,MAAM,CAAC,CAAC,CAAC,CAWX;AAED;;;;;;;;;;;;;;;;;;;;;;;;GAwBG;AACH,wBAAgB,kBAAkB,CAChC,KAAK,CAAC,CAAC,SAAS,SAAS,CAAC,MAAM,EAAE,GAAG,MAAM,EAAE,CAAC,EAC9C,GAAG,IAAI,EAAE,CAAC,GAAG,MAAM,CAAC,CAAC,CAAC,MAAM,CAAC,EAAE,eAAe,CAAC,CAgBhD"}
1
+ {"version":3,"file":"asset.d.ts","sourceRoot":"","sources":["../../src/asset.ts"],"names":[],"mappings":"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"}