pixi-effects 0.10.0 → 0.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.
Files changed (59) hide show
  1. package/CHANGELOG.md +37 -0
  2. package/README.md +11 -8
  3. package/ai/SKILL.md +4 -3
  4. package/ai/reference/cheatsheet.md +16 -2
  5. package/ai/reference/pitfalls.md +6 -2
  6. package/ai/reference/recipes.md +76 -10
  7. package/ai/template.html +15 -8
  8. package/ai/tools/check.mjs +17 -1
  9. package/ai/tools/render.mjs +23 -10
  10. package/dist/{Base-CyvSLoCP.d.ts → Base-CYH9vPCH.d.ts} +1 -1
  11. package/dist/{Base-CwUxTfja.d.cts → Base-W3sQzGPO.d.cts} +1 -1
  12. package/dist/Composition-7TEKHZNQ.cjs +14 -0
  13. package/dist/{Composition-EKVTUYCI.cjs.map → Composition-7TEKHZNQ.cjs.map} +1 -1
  14. package/dist/Composition-HIISJAX2.js +5 -0
  15. package/dist/{Composition-NJCOMGD7.js.map → Composition-HIISJAX2.js.map} +1 -1
  16. package/dist/Controller.cjs +58 -0
  17. package/dist/Controller.cjs.map +1 -1
  18. package/dist/Controller.d.cts +13 -3
  19. package/dist/Controller.d.ts +13 -3
  20. package/dist/Controller.js +58 -0
  21. package/dist/Controller.js.map +1 -1
  22. package/dist/{Movie-w3GliuP3.d.cts → Movie-CY2QPVVM.d.cts} +149 -2
  23. package/dist/{Movie-puD9oZPg.d.ts → Movie-EBF6_RfX.d.ts} +149 -2
  24. package/dist/Presenter.cjs +671 -0
  25. package/dist/Presenter.cjs.map +1 -0
  26. package/dist/Presenter.d.cts +123 -0
  27. package/dist/Presenter.d.ts +123 -0
  28. package/dist/Presenter.js +669 -0
  29. package/dist/Presenter.js.map +1 -0
  30. package/dist/{chunk-WDGAVOMS.js → chunk-3IPDNC3E.js} +8 -5
  31. package/dist/chunk-3IPDNC3E.js.map +1 -0
  32. package/dist/{chunk-S3ZI4MKS.cjs → chunk-6NWJLVCA.cjs} +3 -3
  33. package/dist/{chunk-S3ZI4MKS.cjs.map → chunk-6NWJLVCA.cjs.map} +1 -1
  34. package/dist/{chunk-JAMNDBXW.js → chunk-C6QHKYC5.js} +3 -3
  35. package/dist/{chunk-JAMNDBXW.js.map → chunk-C6QHKYC5.js.map} +1 -1
  36. package/dist/{chunk-4WJUSDJJ.cjs → chunk-F7NCHS6Q.cjs} +31 -28
  37. package/dist/chunk-F7NCHS6Q.cjs.map +1 -0
  38. package/dist/index.cjs +884 -58
  39. package/dist/index.cjs.map +1 -1
  40. package/dist/index.d.cts +234 -5
  41. package/dist/index.d.ts +234 -5
  42. package/dist/index.js +856 -40
  43. package/dist/index.js.map +1 -1
  44. package/dist/loader.css +110 -0
  45. package/dist/three.cjs +5 -5
  46. package/dist/three.d.cts +2 -2
  47. package/dist/three.d.ts +2 -2
  48. package/dist/three.js +1 -1
  49. package/dist/{types-BXu28nJj.d.cts → types-mpqQO8MJ.d.cts} +39 -1
  50. package/dist/{types-BXu28nJj.d.ts → types-mpqQO8MJ.d.ts} +39 -1
  51. package/docs/api.md +94 -1
  52. package/docs/dsl.md +77 -0
  53. package/llms-full.txt +273 -18
  54. package/llms.txt +3 -3
  55. package/package.json +9 -2
  56. package/dist/Composition-EKVTUYCI.cjs +0 -14
  57. package/dist/Composition-NJCOMGD7.js +0 -5
  58. package/dist/chunk-4WJUSDJJ.cjs.map +0 -1
  59. package/dist/chunk-WDGAVOMS.js.map +0 -1
@@ -1,6 +1,6 @@
1
1
  import { Application } from 'pixi.js';
2
2
  import { gsap } from 'gsap';
3
- import { c as AssetSpec, j as CompositionSpec } from './types-BXu28nJj.cjs';
3
+ import { z as Stop, e as AssetSpec, c as CompositionSpec } from './types-mpqQO8MJ.cjs';
4
4
 
5
5
  interface AudioInspectOptions {
6
6
  /** Width of each loudness window in seconds. Default 0.1. */
@@ -131,6 +131,31 @@ interface TimelineSvgOptions {
131
131
  labels?: boolean;
132
132
  }
133
133
 
134
+ /**
135
+ * The page's loader (see `src/loader.css`): a `.pe-loader` element that is on screen before any script runs. `movie.init()` finds it,
136
+ * fades it out when the movie is ready and, if init fails, stops it and says so.
137
+ */
138
+ type LoaderOption = HTMLElement | string | false;
139
+ /** The loader element for a canvas: the one named (element or selector), none (`false`), or a `.pe-loader` near the canvas (its box or a few levels up). */
140
+ declare function resolveLoader(option: LoaderOption | undefined, canvas: HTMLCanvasElement | null): HTMLElement | null;
141
+ /** Fade the loader out (a class, so the CSS transition runs) and take it away. Safe to call twice, or with null. */
142
+ declare function dismissLoader(loader: HTMLElement | null): void;
143
+ /** init failed: stop the animation and say so, and leave the box on screen so the page does not look merely stuck. */
144
+ declare function failLoader(loader: HTMLElement | null, message: string): void;
145
+
146
+ interface MotionBlurOptions {
147
+ /** How many moments one frame is drawn at before they are averaged (2–64). More is smoother and slower. Default 8. */
148
+ samples?: number;
149
+ /** How long the shutter is open, as a fraction of the frame time (0–1]. `0.5` is a 180° shutter (the film look). Default 0.5. */
150
+ shutter?: number;
151
+ }
152
+ /** `true` (8 samples, 180° shutter), a sample count, or `{ samples, shutter }`; `false` is off. */
153
+ type MotionBlurSpec = boolean | number | MotionBlurOptions;
154
+ interface ResolvedMotionBlur {
155
+ samples: number;
156
+ shutter: number;
157
+ }
158
+
134
159
  interface MovieOptions {
135
160
  width?: number;
136
161
  height?: number;
@@ -146,8 +171,22 @@ interface MovieOptions {
146
171
  * value counts back from the end. Default: none (the first frame).
147
172
  */
148
173
  poster?: number;
174
+ /**
175
+ * Motion blur for everything that is *made* (not for live playback): `render()`, `snapshot()` and `contactSheet()` expose each frame
176
+ * over a shutter interval and average `samples` renders of it, so fast motion smears like on film. `true` is 8 samples at a 180° shutter,
177
+ * a number is the sample count, `{ samples, shutter }` sets both. Default: off. Each of those calls can override it (`false` turns it off).
178
+ */
179
+ motionBlur?: MotionBlurSpec;
180
+ /**
181
+ * The page's loader (see `pixi-effects/loader.css`): an element, a selector, or `false` for none. By default a `.pe-loader` next to
182
+ * the canvas is used. It is faded out once the movie is ready (the poster is on the canvas) and, if `init()` fails, it stops and says so.
183
+ */
184
+ loader?: LoaderOption;
149
185
  }
186
+
150
187
  interface RenderOptions {
188
+ /** Motion blur for this export (see `MovieOptions.motionBlur`); overrides the movie's own setting, `false` turns it off. */
189
+ motionBlur?: MotionBlurSpec;
151
190
  format?: 'mp4' | 'mov' | 'webm' | 'mkv';
152
191
  video?: {
153
192
  codec?: string;
@@ -159,6 +198,8 @@ interface RenderOptions {
159
198
  };
160
199
  }
161
200
  interface SnapshotOptions {
201
+ /** Motion blur for this picture (see `MovieOptions.motionBlur`); overrides the movie's own setting, `false` turns it off. */
202
+ motionBlur?: MotionBlurSpec;
162
203
  /** Output size relative to the canvas (default 1). */
163
204
  scale?: number;
164
205
  /** `'image/png'` (default) or `'image/jpeg'`. */
@@ -166,7 +207,33 @@ interface SnapshotOptions {
166
207
  /** Return a `data:` URL string instead of a Blob (handy for scripts that can only return text). */
167
208
  as?: 'blob' | 'dataURL';
168
209
  }
210
+ /** One picture of a stop (see `movie.stopImages()`). */
211
+ interface StopImage {
212
+ stop: Stop; /** The page it belongs to (0-based). */
213
+ page: number;
214
+ image: Blob | string;
215
+ }
216
+ interface StopImagesOptions {
217
+ /** One picture per page (default) or one per stop. */
218
+ which?: 'pages' | 'stops';
219
+ /** With `which: 'pages'`: the page's last stop (default: the page fully built) or its first. */
220
+ pick?: 'last' | 'first';
221
+ /** Output size relative to the canvas. Default 1. */
222
+ scale?: number;
223
+ /** `'image/png'` (default) or `'image/jpeg'`. */
224
+ type?: 'image/png' | 'image/jpeg';
225
+ /** JPEG quality, 0–1. */
226
+ quality?: number;
227
+ /** Return `data:` URLs instead of Blobs. */
228
+ as?: 'blob' | 'dataURL';
229
+ /** Motion blur for the pictures (off unless you ask: they are usually for looking at). */
230
+ motionBlur?: MotionBlurSpec;
231
+ /** Called as each picture is ready, in order. */
232
+ onImage?: (image: StopImage) => void;
233
+ }
169
234
  interface ContactSheetOptions {
235
+ /** Motion blur for these pictures (see `MovieOptions.motionBlur`); overrides the movie's own setting, `false` turns it off. */
236
+ motionBlur?: MotionBlurSpec;
170
237
  /** Frames to show. Default: `count` frames spread evenly over the movie. */
171
238
  frames?: number[];
172
239
  /** Times in seconds to show (used when `frames` is not given). */
@@ -183,6 +250,12 @@ interface FrameEvent {
183
250
  frame: number;
184
251
  totalFrames: number;
185
252
  }
253
+ /** A presentation reached a stop (`movie.next()` played to it, or `prev()` / `goToStop()` / `goToPage()` jumped to it). */
254
+ interface StopEvent {
255
+ index: number;
256
+ stop: Stop;
257
+ pageIndex: number;
258
+ }
186
259
  interface ProgressEvent {
187
260
  progress: number;
188
261
  frame: number;
@@ -211,6 +284,14 @@ declare class Movie {
211
284
  private _cancelAudioStart;
212
285
  /** The poster time in seconds (`movie.init({ poster })`), or null. */
213
286
  poster: number | null;
287
+ /** The stops of the composition (`composition.stops`), checked and in order: where `next()` pauses. Empty for an ordinary movie. */
288
+ stops: Stop[];
289
+ /** The frame `next()` is playing toward, or null. */
290
+ private _stopAt;
291
+ private _stopWaiters;
292
+ private _arriving;
293
+ /** The motion blur `render()`, `snapshot()` and `contactSheet()` apply unless told otherwise (`movie.init({ motionBlur })`), or null. */
294
+ motionBlur: ResolvedMotionBlur | null;
214
295
  private _posterFrame;
215
296
  /** The canvas shows the poster picture while the playhead is still at frame 0 (like `<video poster>`): the first seek or play replaces it. */
216
297
  private _atPoster;
@@ -234,6 +315,8 @@ declare class Movie {
234
315
  private _audioSources;
235
316
  private _mixStats;
236
317
  on(event: 'ready', fn: () => void): this;
318
+ /** A presentation is now on a stop (see `stops` in the composition, `next()`, `prev()`). */
319
+ on(event: 'stop', fn: (e: StopEvent) => void): this;
237
320
  on(event: 'frame', fn: (e: FrameEvent) => void): this;
238
321
  /** A jump to another frame (`gotoFrame`, a seek bar) starts / finishes. Not emitted for playback ticks, `render()`, `snapshot()` or `contactSheet()`. */
239
322
  on(event: 'seeking' | 'seeked', fn: (e: FrameEvent) => void): this;
@@ -268,6 +351,12 @@ declare class Movie {
268
351
  private _quietly;
269
352
  private _emitError;
270
353
  private _goto;
354
+ /**
355
+ * The moment frame `frame` shows. The very last frame (`totalFrames`) is at the end of the movie, where every layer's lifespan
356
+ * has just closed: it is drawn a hair before, so a layer that lasts to the end is still on screen in the final frame
357
+ * (it used to be an empty one, the last frame of every export).
358
+ */
359
+ private _timeOf;
271
360
  private _awaitVideoFrames;
272
361
  /**
273
362
  * A picture of one frame (the canvas only: the player bar is not included). Seeks there first and
@@ -279,6 +368,31 @@ declare class Movie {
279
368
  snapshot(frame: number | undefined, opts: SnapshotOptions & {
280
369
  as: 'dataURL';
281
370
  }): Promise<string>;
371
+ /** Seek to `frame` (quietly, and stay there) and encode the canvas as a picture. */
372
+ private _captureFrame;
373
+ /**
374
+ * A picture of the settled state of each page (default: the page's last stop, fully built) or of every stop, for a page list, an
375
+ * overview, an export. Pauses the movie, and leaves the playhead where it was. `onImage` is called as each picture is ready.
376
+ */
377
+ stopImages(opts: StopImagesOptions & {
378
+ as: 'dataURL';
379
+ }): Promise<Array<StopImage & {
380
+ image: string;
381
+ }>>;
382
+ stopImages(opts?: StopImagesOptions): Promise<StopImage[]>;
383
+ /**
384
+ * The deck as a PDF: one page per page of the talk (the page's last stop, fully built; `which: 'stops'` makes a page of every stop), each a
385
+ * JPEG at the canvas size. Needs `composition.stops`. A transparent background comes out black: give the movie a `background`.
386
+ */
387
+ exportPDF(opts?: {
388
+ which?: 'pages' | 'stops';
389
+ pick?: 'last' | 'first';
390
+ scale?: number;
391
+ quality?: number;
392
+ title?: string;
393
+ motionBlur?: MotionBlurSpec;
394
+ onImage?: (image: StopImage) => void;
395
+ }): Promise<Blob>;
282
396
  /**
283
397
  * Several frames on ONE image, each labelled with its frame number and time — the cheapest way to
284
398
  * check a whole animation by eye. Restores the current frame afterwards.
@@ -319,6 +433,39 @@ declare class Movie {
319
433
  private _requireReady;
320
434
  /** Projects every `threeD` layer for the current frame (see src/space). */
321
435
  private _updateSpace;
436
+ /** The motion blur an operation uses: its own option when given (`false` is off), otherwise the movie's. */
437
+ private _blurFor;
438
+ /**
439
+ * @internal Draw `frame` with motion blur into `target` (a canvas the size of the stage): the average of `mb.samples` renders at moments
440
+ * spread over the shutter interval around the frame time. With `settle` the playhead and the stage are left exactly on the frame.
441
+ */
442
+ _exposeFrame(frame: number, mb: ResolvedMotionBlur, target: HTMLCanvasElement, settle: boolean): Promise<void>;
443
+ private _blurCanvas;
444
+ /** Which stop the playhead is on or has passed (-1 before the first). */
445
+ get stopIndex(): number;
446
+ /** The stop the playhead is on or has passed, or null. */
447
+ get currentStop(): Stop | null;
448
+ /** Which page the playhead is in (0-based), -1 before the first stop. */
449
+ get pageIndex(): number;
450
+ /** How many pages the stops make. */
451
+ get pageCount(): number;
452
+ private _cancelStop;
453
+ private _settleStopWaiters;
454
+ private _emitStop;
455
+ /** Land exactly on a stop's frame, pause, and say so. */
456
+ private _arriveAtStop;
457
+ /**
458
+ * Play to the next stop and pause exactly there (a presentation's "next"). Pressed again while it is playing toward a stop, it skips the
459
+ * rest of the animation and lands on that stop at once. After the last stop it plays to the end. Resolves when it has landed (or
460
+ * stopped for another reason). An ordinary `play()` ignores the stops.
461
+ */
462
+ next(): Promise<void>;
463
+ /** Jump back to the previous stop at once (no reverse playback); from the first stop, to the start. */
464
+ prev(): Promise<void>;
465
+ /** Jump to stop `index` (0-based). */
466
+ goToStop(index: number): Promise<void>;
467
+ /** Jump to the first stop of page `page` (0-based). */
468
+ goToPage(page: number): Promise<void>;
322
469
  play(): void;
323
470
  pause(): void;
324
471
  set volume(v: number);
@@ -330,4 +477,4 @@ declare class Movie {
330
477
  destroy(): Promise<void>;
331
478
  }
332
479
 
333
- export { type AudioInspectOptions as A, type ContactSheetOptions as C, type FrameEvent as F, type InspectOptions as I, type LayerInfo as L, Movie as M, type ProgressEvent as P, type RenderOptions as R, type SnapshotOptions as S, type TimelineData as T, type VolumeEvent as V, type AudioReport as a, type AudioSourceReport as b, type InspectReport as c, type MovieErrorEvent as d, type MovieOptions as e, type SoundMeasure as f, type TimelineHtmlOptions as g, type TimelineRow as h, type TimelineSvgOptions as i, type TimelineTransition as j };
480
+ export { type AudioInspectOptions as A, type ContactSheetOptions as C, type FrameEvent as F, type InspectOptions as I, type LayerInfo as L, type MotionBlurOptions as M, type ProgressEvent as P, type RenderOptions as R, type SnapshotOptions as S, type TimelineData as T, type VolumeEvent as V, type AudioReport as a, type AudioSourceReport as b, type InspectReport as c, type LoaderOption as d, type MotionBlurSpec as e, Movie as f, type MovieErrorEvent as g, type MovieOptions as h, type SoundMeasure as i, type StopEvent as j, type StopImage as k, type StopImagesOptions as l, type TimelineHtmlOptions as m, type TimelineRow as n, type TimelineSvgOptions as o, type TimelineTransition as p, dismissLoader as q, failLoader as r, resolveLoader as s };
@@ -1,6 +1,6 @@
1
1
  import { Application } from 'pixi.js';
2
2
  import { gsap } from 'gsap';
3
- import { c as AssetSpec, j as CompositionSpec } from './types-BXu28nJj.js';
3
+ import { z as Stop, e as AssetSpec, c as CompositionSpec } from './types-mpqQO8MJ.js';
4
4
 
5
5
  interface AudioInspectOptions {
6
6
  /** Width of each loudness window in seconds. Default 0.1. */
@@ -131,6 +131,31 @@ interface TimelineSvgOptions {
131
131
  labels?: boolean;
132
132
  }
133
133
 
134
+ /**
135
+ * The page's loader (see `src/loader.css`): a `.pe-loader` element that is on screen before any script runs. `movie.init()` finds it,
136
+ * fades it out when the movie is ready and, if init fails, stops it and says so.
137
+ */
138
+ type LoaderOption = HTMLElement | string | false;
139
+ /** The loader element for a canvas: the one named (element or selector), none (`false`), or a `.pe-loader` near the canvas (its box or a few levels up). */
140
+ declare function resolveLoader(option: LoaderOption | undefined, canvas: HTMLCanvasElement | null): HTMLElement | null;
141
+ /** Fade the loader out (a class, so the CSS transition runs) and take it away. Safe to call twice, or with null. */
142
+ declare function dismissLoader(loader: HTMLElement | null): void;
143
+ /** init failed: stop the animation and say so, and leave the box on screen so the page does not look merely stuck. */
144
+ declare function failLoader(loader: HTMLElement | null, message: string): void;
145
+
146
+ interface MotionBlurOptions {
147
+ /** How many moments one frame is drawn at before they are averaged (2–64). More is smoother and slower. Default 8. */
148
+ samples?: number;
149
+ /** How long the shutter is open, as a fraction of the frame time (0–1]. `0.5` is a 180° shutter (the film look). Default 0.5. */
150
+ shutter?: number;
151
+ }
152
+ /** `true` (8 samples, 180° shutter), a sample count, or `{ samples, shutter }`; `false` is off. */
153
+ type MotionBlurSpec = boolean | number | MotionBlurOptions;
154
+ interface ResolvedMotionBlur {
155
+ samples: number;
156
+ shutter: number;
157
+ }
158
+
134
159
  interface MovieOptions {
135
160
  width?: number;
136
161
  height?: number;
@@ -146,8 +171,22 @@ interface MovieOptions {
146
171
  * value counts back from the end. Default: none (the first frame).
147
172
  */
148
173
  poster?: number;
174
+ /**
175
+ * Motion blur for everything that is *made* (not for live playback): `render()`, `snapshot()` and `contactSheet()` expose each frame
176
+ * over a shutter interval and average `samples` renders of it, so fast motion smears like on film. `true` is 8 samples at a 180° shutter,
177
+ * a number is the sample count, `{ samples, shutter }` sets both. Default: off. Each of those calls can override it (`false` turns it off).
178
+ */
179
+ motionBlur?: MotionBlurSpec;
180
+ /**
181
+ * The page's loader (see `pixi-effects/loader.css`): an element, a selector, or `false` for none. By default a `.pe-loader` next to
182
+ * the canvas is used. It is faded out once the movie is ready (the poster is on the canvas) and, if `init()` fails, it stops and says so.
183
+ */
184
+ loader?: LoaderOption;
149
185
  }
186
+
150
187
  interface RenderOptions {
188
+ /** Motion blur for this export (see `MovieOptions.motionBlur`); overrides the movie's own setting, `false` turns it off. */
189
+ motionBlur?: MotionBlurSpec;
151
190
  format?: 'mp4' | 'mov' | 'webm' | 'mkv';
152
191
  video?: {
153
192
  codec?: string;
@@ -159,6 +198,8 @@ interface RenderOptions {
159
198
  };
160
199
  }
161
200
  interface SnapshotOptions {
201
+ /** Motion blur for this picture (see `MovieOptions.motionBlur`); overrides the movie's own setting, `false` turns it off. */
202
+ motionBlur?: MotionBlurSpec;
162
203
  /** Output size relative to the canvas (default 1). */
163
204
  scale?: number;
164
205
  /** `'image/png'` (default) or `'image/jpeg'`. */
@@ -166,7 +207,33 @@ interface SnapshotOptions {
166
207
  /** Return a `data:` URL string instead of a Blob (handy for scripts that can only return text). */
167
208
  as?: 'blob' | 'dataURL';
168
209
  }
210
+ /** One picture of a stop (see `movie.stopImages()`). */
211
+ interface StopImage {
212
+ stop: Stop; /** The page it belongs to (0-based). */
213
+ page: number;
214
+ image: Blob | string;
215
+ }
216
+ interface StopImagesOptions {
217
+ /** One picture per page (default) or one per stop. */
218
+ which?: 'pages' | 'stops';
219
+ /** With `which: 'pages'`: the page's last stop (default: the page fully built) or its first. */
220
+ pick?: 'last' | 'first';
221
+ /** Output size relative to the canvas. Default 1. */
222
+ scale?: number;
223
+ /** `'image/png'` (default) or `'image/jpeg'`. */
224
+ type?: 'image/png' | 'image/jpeg';
225
+ /** JPEG quality, 0–1. */
226
+ quality?: number;
227
+ /** Return `data:` URLs instead of Blobs. */
228
+ as?: 'blob' | 'dataURL';
229
+ /** Motion blur for the pictures (off unless you ask: they are usually for looking at). */
230
+ motionBlur?: MotionBlurSpec;
231
+ /** Called as each picture is ready, in order. */
232
+ onImage?: (image: StopImage) => void;
233
+ }
169
234
  interface ContactSheetOptions {
235
+ /** Motion blur for these pictures (see `MovieOptions.motionBlur`); overrides the movie's own setting, `false` turns it off. */
236
+ motionBlur?: MotionBlurSpec;
170
237
  /** Frames to show. Default: `count` frames spread evenly over the movie. */
171
238
  frames?: number[];
172
239
  /** Times in seconds to show (used when `frames` is not given). */
@@ -183,6 +250,12 @@ interface FrameEvent {
183
250
  frame: number;
184
251
  totalFrames: number;
185
252
  }
253
+ /** A presentation reached a stop (`movie.next()` played to it, or `prev()` / `goToStop()` / `goToPage()` jumped to it). */
254
+ interface StopEvent {
255
+ index: number;
256
+ stop: Stop;
257
+ pageIndex: number;
258
+ }
186
259
  interface ProgressEvent {
187
260
  progress: number;
188
261
  frame: number;
@@ -211,6 +284,14 @@ declare class Movie {
211
284
  private _cancelAudioStart;
212
285
  /** The poster time in seconds (`movie.init({ poster })`), or null. */
213
286
  poster: number | null;
287
+ /** The stops of the composition (`composition.stops`), checked and in order: where `next()` pauses. Empty for an ordinary movie. */
288
+ stops: Stop[];
289
+ /** The frame `next()` is playing toward, or null. */
290
+ private _stopAt;
291
+ private _stopWaiters;
292
+ private _arriving;
293
+ /** The motion blur `render()`, `snapshot()` and `contactSheet()` apply unless told otherwise (`movie.init({ motionBlur })`), or null. */
294
+ motionBlur: ResolvedMotionBlur | null;
214
295
  private _posterFrame;
215
296
  /** The canvas shows the poster picture while the playhead is still at frame 0 (like `<video poster>`): the first seek or play replaces it. */
216
297
  private _atPoster;
@@ -234,6 +315,8 @@ declare class Movie {
234
315
  private _audioSources;
235
316
  private _mixStats;
236
317
  on(event: 'ready', fn: () => void): this;
318
+ /** A presentation is now on a stop (see `stops` in the composition, `next()`, `prev()`). */
319
+ on(event: 'stop', fn: (e: StopEvent) => void): this;
237
320
  on(event: 'frame', fn: (e: FrameEvent) => void): this;
238
321
  /** A jump to another frame (`gotoFrame`, a seek bar) starts / finishes. Not emitted for playback ticks, `render()`, `snapshot()` or `contactSheet()`. */
239
322
  on(event: 'seeking' | 'seeked', fn: (e: FrameEvent) => void): this;
@@ -268,6 +351,12 @@ declare class Movie {
268
351
  private _quietly;
269
352
  private _emitError;
270
353
  private _goto;
354
+ /**
355
+ * The moment frame `frame` shows. The very last frame (`totalFrames`) is at the end of the movie, where every layer's lifespan
356
+ * has just closed: it is drawn a hair before, so a layer that lasts to the end is still on screen in the final frame
357
+ * (it used to be an empty one, the last frame of every export).
358
+ */
359
+ private _timeOf;
271
360
  private _awaitVideoFrames;
272
361
  /**
273
362
  * A picture of one frame (the canvas only: the player bar is not included). Seeks there first and
@@ -279,6 +368,31 @@ declare class Movie {
279
368
  snapshot(frame: number | undefined, opts: SnapshotOptions & {
280
369
  as: 'dataURL';
281
370
  }): Promise<string>;
371
+ /** Seek to `frame` (quietly, and stay there) and encode the canvas as a picture. */
372
+ private _captureFrame;
373
+ /**
374
+ * A picture of the settled state of each page (default: the page's last stop, fully built) or of every stop, for a page list, an
375
+ * overview, an export. Pauses the movie, and leaves the playhead where it was. `onImage` is called as each picture is ready.
376
+ */
377
+ stopImages(opts: StopImagesOptions & {
378
+ as: 'dataURL';
379
+ }): Promise<Array<StopImage & {
380
+ image: string;
381
+ }>>;
382
+ stopImages(opts?: StopImagesOptions): Promise<StopImage[]>;
383
+ /**
384
+ * The deck as a PDF: one page per page of the talk (the page's last stop, fully built; `which: 'stops'` makes a page of every stop), each a
385
+ * JPEG at the canvas size. Needs `composition.stops`. A transparent background comes out black: give the movie a `background`.
386
+ */
387
+ exportPDF(opts?: {
388
+ which?: 'pages' | 'stops';
389
+ pick?: 'last' | 'first';
390
+ scale?: number;
391
+ quality?: number;
392
+ title?: string;
393
+ motionBlur?: MotionBlurSpec;
394
+ onImage?: (image: StopImage) => void;
395
+ }): Promise<Blob>;
282
396
  /**
283
397
  * Several frames on ONE image, each labelled with its frame number and time — the cheapest way to
284
398
  * check a whole animation by eye. Restores the current frame afterwards.
@@ -319,6 +433,39 @@ declare class Movie {
319
433
  private _requireReady;
320
434
  /** Projects every `threeD` layer for the current frame (see src/space). */
321
435
  private _updateSpace;
436
+ /** The motion blur an operation uses: its own option when given (`false` is off), otherwise the movie's. */
437
+ private _blurFor;
438
+ /**
439
+ * @internal Draw `frame` with motion blur into `target` (a canvas the size of the stage): the average of `mb.samples` renders at moments
440
+ * spread over the shutter interval around the frame time. With `settle` the playhead and the stage are left exactly on the frame.
441
+ */
442
+ _exposeFrame(frame: number, mb: ResolvedMotionBlur, target: HTMLCanvasElement, settle: boolean): Promise<void>;
443
+ private _blurCanvas;
444
+ /** Which stop the playhead is on or has passed (-1 before the first). */
445
+ get stopIndex(): number;
446
+ /** The stop the playhead is on or has passed, or null. */
447
+ get currentStop(): Stop | null;
448
+ /** Which page the playhead is in (0-based), -1 before the first stop. */
449
+ get pageIndex(): number;
450
+ /** How many pages the stops make. */
451
+ get pageCount(): number;
452
+ private _cancelStop;
453
+ private _settleStopWaiters;
454
+ private _emitStop;
455
+ /** Land exactly on a stop's frame, pause, and say so. */
456
+ private _arriveAtStop;
457
+ /**
458
+ * Play to the next stop and pause exactly there (a presentation's "next"). Pressed again while it is playing toward a stop, it skips the
459
+ * rest of the animation and lands on that stop at once. After the last stop it plays to the end. Resolves when it has landed (or
460
+ * stopped for another reason). An ordinary `play()` ignores the stops.
461
+ */
462
+ next(): Promise<void>;
463
+ /** Jump back to the previous stop at once (no reverse playback); from the first stop, to the start. */
464
+ prev(): Promise<void>;
465
+ /** Jump to stop `index` (0-based). */
466
+ goToStop(index: number): Promise<void>;
467
+ /** Jump to the first stop of page `page` (0-based). */
468
+ goToPage(page: number): Promise<void>;
322
469
  play(): void;
323
470
  pause(): void;
324
471
  set volume(v: number);
@@ -330,4 +477,4 @@ declare class Movie {
330
477
  destroy(): Promise<void>;
331
478
  }
332
479
 
333
- export { type AudioInspectOptions as A, type ContactSheetOptions as C, type FrameEvent as F, type InspectOptions as I, type LayerInfo as L, Movie as M, type ProgressEvent as P, type RenderOptions as R, type SnapshotOptions as S, type TimelineData as T, type VolumeEvent as V, type AudioReport as a, type AudioSourceReport as b, type InspectReport as c, type MovieErrorEvent as d, type MovieOptions as e, type SoundMeasure as f, type TimelineHtmlOptions as g, type TimelineRow as h, type TimelineSvgOptions as i, type TimelineTransition as j };
480
+ export { type AudioInspectOptions as A, type ContactSheetOptions as C, type FrameEvent as F, type InspectOptions as I, type LayerInfo as L, type MotionBlurOptions as M, type ProgressEvent as P, type RenderOptions as R, type SnapshotOptions as S, type TimelineData as T, type VolumeEvent as V, type AudioReport as a, type AudioSourceReport as b, type InspectReport as c, type LoaderOption as d, type MotionBlurSpec as e, Movie as f, type MovieErrorEvent as g, type MovieOptions as h, type SoundMeasure as i, type StopEvent as j, type StopImage as k, type StopImagesOptions as l, type TimelineHtmlOptions as m, type TimelineRow as n, type TimelineSvgOptions as o, type TimelineTransition as p, dismissLoader as q, failLoader as r, resolveLoader as s };