pixi-effects 0.28.2 → 0.30.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 (93) hide show
  1. package/CHANGELOG.md +59 -0
  2. package/README.md +11 -10
  3. package/ai/chat-template.html +5 -5
  4. package/ai/tools/check.mjs +18 -3
  5. package/ai/tools/lookup.mjs +208 -0
  6. package/ai/tools/pixi-effects.mjs +16 -5
  7. package/ai/tools/render.mjs +14 -9
  8. package/ai/tools/view.mjs +6 -2
  9. package/dist/Base-CB1_FPZD.d.cts +60 -0
  10. package/dist/Base-Ne74ztNl.d.ts +60 -0
  11. package/dist/Composition-MUKR3FYD.cjs +16 -0
  12. package/dist/{Composition-K6B3APM5.cjs.map → Composition-MUKR3FYD.cjs.map} +1 -1
  13. package/dist/Composition-RJGA7KDU.js +7 -0
  14. package/dist/{Composition-H7UNR5F5.js.map → Composition-RJGA7KDU.js.map} +1 -1
  15. package/dist/Controller.cjs +73 -45
  16. package/dist/Controller.cjs.map +1 -1
  17. package/dist/Controller.d.cts +16 -22
  18. package/dist/Controller.d.ts +16 -22
  19. package/dist/Controller.js +74 -40
  20. package/dist/Controller.js.map +1 -1
  21. package/dist/{Movie-CHcM8HNB.d.ts → Movie-C2rZFkrO.d.ts} +227 -119
  22. package/dist/{Movie-Cx5ozUGb.d.cts → Movie-DdnpLpw1.d.cts} +227 -119
  23. package/dist/{blendModes-HDOP6R7T.cjs → blendModes-ETMYWATF.cjs} +5 -5
  24. package/dist/{blendModes-HDOP6R7T.cjs.map → blendModes-ETMYWATF.cjs.map} +1 -1
  25. package/dist/{blendModes-PAVTW3BO.js → blendModes-RIVZXL5A.js} +4 -4
  26. package/dist/{blendModes-PAVTW3BO.js.map → blendModes-RIVZXL5A.js.map} +1 -1
  27. package/dist/{chunk-P4GY3Z4G.cjs → chunk-2DXPTKQZ.cjs} +6 -6
  28. package/dist/chunk-2DXPTKQZ.cjs.map +1 -0
  29. package/dist/{chunk-TYWFKCPY.js → chunk-4KB3GUEK.js} +5 -5
  30. package/dist/chunk-4KB3GUEK.js.map +1 -0
  31. package/dist/{chunk-5MZWXVTT.js → chunk-A3Q3SDSH.js} +35 -28
  32. package/dist/chunk-A3Q3SDSH.js.map +1 -0
  33. package/dist/chunk-CRQFDY7E.js +4182 -0
  34. package/dist/chunk-CRQFDY7E.js.map +1 -0
  35. package/dist/chunk-HREBQAY4.cjs +4206 -0
  36. package/dist/chunk-HREBQAY4.cjs.map +1 -0
  37. package/dist/{chunk-ZMAD3KJU.cjs → chunk-LYOKH7KE.cjs} +22 -3
  38. package/dist/chunk-LYOKH7KE.cjs.map +1 -0
  39. package/dist/{chunk-45QKLD6M.js → chunk-RCVZX2JP.js} +22 -3
  40. package/dist/chunk-RCVZX2JP.js.map +1 -0
  41. package/dist/{chunk-KBH33IQX.cjs → chunk-WHNADXXG.cjs} +121 -114
  42. package/dist/chunk-WHNADXXG.cjs.map +1 -0
  43. package/dist/{chunk-7VN2KI3U.js → chunk-ZAXYPXKW.js} +14 -6
  44. package/dist/chunk-ZAXYPXKW.js.map +1 -0
  45. package/dist/{chunk-MJW7KILM.cjs → chunk-ZVUO325O.cjs} +32 -24
  46. package/dist/chunk-ZVUO325O.cjs.map +1 -0
  47. package/dist/index.cjs +106 -4482
  48. package/dist/index.cjs.map +1 -1
  49. package/dist/index.d.cts +15 -60
  50. package/dist/index.d.ts +15 -60
  51. package/dist/index.js +6 -4457
  52. package/dist/index.js.map +1 -1
  53. package/dist/loader.css +1 -1
  54. package/dist/{Presenter.cjs → present.cjs} +370 -31
  55. package/dist/present.cjs.map +1 -0
  56. package/dist/present.d.cts +278 -0
  57. package/dist/present.d.ts +278 -0
  58. package/dist/{Presenter.js → present.js} +358 -32
  59. package/dist/present.js.map +1 -0
  60. package/dist/three.cjs +6 -6
  61. package/dist/three.d.cts +2 -2
  62. package/dist/three.d.ts +2 -2
  63. package/dist/three.js +2 -2
  64. package/dist/{types-DpK1vwcl.d.ts → types-BzIB65Vk.d.cts} +11 -265
  65. package/dist/{types-DpK1vwcl.d.cts → types-BzIB65Vk.d.ts} +11 -265
  66. package/docs/api.md +44 -77
  67. package/docs/dsl.md +16 -14
  68. package/llms-full.txt +121 -117
  69. package/llms.txt +3 -2
  70. package/package.json +5 -5
  71. package/skills/pixi-effects/SKILL.md +7 -7
  72. package/skills/pixi-effects/reference/cheatsheet.md +9 -9
  73. package/skills/pixi-effects/reference/direction.md +2 -0
  74. package/skills/pixi-effects/reference/pitfalls.md +6 -6
  75. package/skills/pixi-effects/reference/quickstart.md +29 -0
  76. package/skills/pixi-effects/reference/recipes.md +4 -4
  77. package/skills/pixi-effects/template.html +7 -7
  78. package/dist/Base-C6f0fE8j.d.ts +0 -109
  79. package/dist/Base-DI1FCGcH.d.cts +0 -109
  80. package/dist/Composition-H7UNR5F5.js +0 -7
  81. package/dist/Composition-K6B3APM5.cjs +0 -16
  82. package/dist/Presenter.cjs.map +0 -1
  83. package/dist/Presenter.d.cts +0 -122
  84. package/dist/Presenter.d.ts +0 -122
  85. package/dist/Presenter.js.map +0 -1
  86. package/dist/chunk-45QKLD6M.js.map +0 -1
  87. package/dist/chunk-5MZWXVTT.js.map +0 -1
  88. package/dist/chunk-7VN2KI3U.js.map +0 -1
  89. package/dist/chunk-KBH33IQX.cjs.map +0 -1
  90. package/dist/chunk-MJW7KILM.cjs.map +0 -1
  91. package/dist/chunk-P4GY3Z4G.cjs.map +0 -1
  92. package/dist/chunk-TYWFKCPY.js.map +0 -1
  93. package/dist/chunk-ZMAD3KJU.cjs.map +0 -1
@@ -0,0 +1,60 @@
1
+ import { Container } from 'pixi.js';
2
+ import { S as SequenceSpec, C as CompositionShape } from './types-BzIB65Vk.cjs';
3
+
4
+ /**
5
+ * Resolves a routed keyframe path to a concrete tween target.
6
+ * `path` is everything after the registered prefix + dot (for
7
+ * `three.cube.rotation.y` under prefix `three`, path = `cube.rotation.y`).
8
+ * Return null to skip the key (the router is expected to have warned).
9
+ */
10
+ type PathRouter = (path: string) => {
11
+ target: object;
12
+ prop: string;
13
+ } | null;
14
+ type PathRouters = Record<string, PathRouter>;
15
+
16
+ /** Variables available to expression evaluation. */
17
+ interface Scope {
18
+ w: number;
19
+ h: number;
20
+ W: number;
21
+ H: number;
22
+ GW: number;
23
+ GH: number;
24
+ contain: number;
25
+ cover: number;
26
+ t: number;
27
+ d: number;
28
+ T: number;
29
+ }
30
+
31
+ declare abstract class Sequence {
32
+ spec: SequenceSpec;
33
+ parent: CompositionShape | null;
34
+ root: CompositionShape;
35
+ target: Container | null;
36
+ intrinsicWidth: number;
37
+ intrinsicHeight: number;
38
+ at: number;
39
+ duration: number | undefined;
40
+ constructor(spec: SequenceSpec, parent: CompositionShape | null, root: CompositionShape);
41
+ abstract build(): Promise<void>;
42
+ buildFilters(): void;
43
+ scope(): Scope;
44
+ /**
45
+ * Prefix routers contributed to the keyframe pipeline (e.g. `three.` in
46
+ * pixi-effects/three). Base sequences route nothing extra.
47
+ */
48
+ protected pathRouters(): PathRouters;
49
+ /**
50
+ * The `initial` and `keyframes` that go onto the display object. A layer whose `time` runs a clock (video, composition) takes `time`
51
+ * out of them: it is not a property of the display object.
52
+ */
53
+ protected displayProps(): {
54
+ initial: SequenceSpec['initial'];
55
+ keyframes: SequenceSpec['keyframes'];
56
+ };
57
+ destroy(): void;
58
+ }
59
+
60
+ export { type PathRouters as P, Sequence as S };
@@ -0,0 +1,60 @@
1
+ import { Container } from 'pixi.js';
2
+ import { S as SequenceSpec, C as CompositionShape } from './types-BzIB65Vk.js';
3
+
4
+ /**
5
+ * Resolves a routed keyframe path to a concrete tween target.
6
+ * `path` is everything after the registered prefix + dot (for
7
+ * `three.cube.rotation.y` under prefix `three`, path = `cube.rotation.y`).
8
+ * Return null to skip the key (the router is expected to have warned).
9
+ */
10
+ type PathRouter = (path: string) => {
11
+ target: object;
12
+ prop: string;
13
+ } | null;
14
+ type PathRouters = Record<string, PathRouter>;
15
+
16
+ /** Variables available to expression evaluation. */
17
+ interface Scope {
18
+ w: number;
19
+ h: number;
20
+ W: number;
21
+ H: number;
22
+ GW: number;
23
+ GH: number;
24
+ contain: number;
25
+ cover: number;
26
+ t: number;
27
+ d: number;
28
+ T: number;
29
+ }
30
+
31
+ declare abstract class Sequence {
32
+ spec: SequenceSpec;
33
+ parent: CompositionShape | null;
34
+ root: CompositionShape;
35
+ target: Container | null;
36
+ intrinsicWidth: number;
37
+ intrinsicHeight: number;
38
+ at: number;
39
+ duration: number | undefined;
40
+ constructor(spec: SequenceSpec, parent: CompositionShape | null, root: CompositionShape);
41
+ abstract build(): Promise<void>;
42
+ buildFilters(): void;
43
+ scope(): Scope;
44
+ /**
45
+ * Prefix routers contributed to the keyframe pipeline (e.g. `three.` in
46
+ * pixi-effects/three). Base sequences route nothing extra.
47
+ */
48
+ protected pathRouters(): PathRouters;
49
+ /**
50
+ * The `initial` and `keyframes` that go onto the display object. A layer whose `time` runs a clock (video, composition) takes `time`
51
+ * out of them: it is not a property of the display object.
52
+ */
53
+ protected displayProps(): {
54
+ initial: SequenceSpec['initial'];
55
+ keyframes: SequenceSpec['keyframes'];
56
+ };
57
+ destroy(): void;
58
+ }
59
+
60
+ export { type PathRouters as P, Sequence as S };
@@ -0,0 +1,16 @@
1
+ 'use strict';
2
+
3
+ var chunkWHNADXXG_cjs = require('./chunk-WHNADXXG.cjs');
4
+ require('./chunk-ZVUO325O.cjs');
5
+ require('./chunk-2DXPTKQZ.cjs');
6
+ require('./chunk-LYOKH7KE.cjs');
7
+ require('./chunk-TWZNOUM7.cjs');
8
+
9
+
10
+
11
+ Object.defineProperty(exports, "CompositionSequence", {
12
+ enumerable: true,
13
+ get: function () { return chunkWHNADXXG_cjs.CompositionSequence; }
14
+ });
15
+ //# sourceMappingURL=Composition-MUKR3FYD.cjs.map
16
+ //# sourceMappingURL=Composition-MUKR3FYD.cjs.map
@@ -1 +1 @@
1
- {"version":3,"sources":[],"names":[],"mappings":"","file":"Composition-K6B3APM5.cjs"}
1
+ {"version":3,"sources":[],"names":[],"mappings":"","file":"Composition-MUKR3FYD.cjs"}
@@ -0,0 +1,7 @@
1
+ export { CompositionSequence } from './chunk-A3Q3SDSH.js';
2
+ import './chunk-ZAXYPXKW.js';
3
+ import './chunk-4KB3GUEK.js';
4
+ import './chunk-RCVZX2JP.js';
5
+ import './chunk-BXOCEZ4U.js';
6
+ //# sourceMappingURL=Composition-RJGA7KDU.js.map
7
+ //# sourceMappingURL=Composition-RJGA7KDU.js.map
@@ -1 +1 @@
1
- {"version":3,"sources":[],"names":[],"mappings":"","file":"Composition-H7UNR5F5.js"}
1
+ {"version":3,"sources":[],"names":[],"mappings":"","file":"Composition-RJGA7KDU.js"}
@@ -2,18 +2,7 @@
2
2
 
3
3
  var chunkTWZNOUM7_cjs = require('./chunk-TWZNOUM7.cjs');
4
4
 
5
- // src/Controller.ts
6
- var ICONS = {
7
- play: '<svg viewBox="0 0 16 16" width="16" height="16" fill="currentColor"><path d="M3 2 L13 8 L3 14 Z"/></svg>',
8
- pause: '<svg viewBox="0 0 16 16" width="16" height="16" fill="currentColor"><rect x="3" y="2" width="3.5" height="12"/><rect x="9.5" y="2" width="3.5" height="12"/></svg>',
9
- volumeOn: '<svg viewBox="0 0 16 16" width="16" height="16" fill="currentColor"><path d="M2 6 H5 L9 2 V14 L5 10 H2 Z"/><path d="M11 5 Q13 8 11 11" fill="none" stroke="currentColor" stroke-width="1.2"/><path d="M12.5 3.5 Q15.5 8 12.5 12.5" fill="none" stroke="currentColor" stroke-width="1.2"/></svg>',
10
- volumeOff: '<svg viewBox="0 0 16 16" width="16" height="16" fill="currentColor"><path d="M2 6 H5 L9 2 V14 L5 10 H2 Z"/><path d="M11 5 L15 11 M15 5 L11 11" fill="none" stroke="currentColor" stroke-width="1.4"/></svg>',
11
- download: '<svg viewBox="0 0 16 16" width="16" height="16" fill="none" stroke="currentColor" stroke-width="1.4" stroke-linecap="round" stroke-linejoin="round"><path d="M8 2 V11 M4 7 L8 11 L12 7 M3 13 H13"/></svg>',
12
- fullscreenEnter: '<svg viewBox="0 0 16 16" width="16" height="16" fill="none" stroke="currentColor" stroke-width="1.4" stroke-linecap="round" stroke-linejoin="round"><path d="M2 6 V2 H6 M14 6 V2 H10 M2 10 V14 H6 M14 10 V14 H10"/></svg>',
13
- present: '<svg viewBox="0 0 16 16" width="16" height="16" fill="none" stroke="currentColor" stroke-width="1.4" stroke-linecap="round" stroke-linejoin="round"><path d="M2 2.5 H14 V10.5 H2 Z M8 10.5 V13.5 M5 13.5 H11"/></svg>',
14
- fullscreenExit: '<svg viewBox="0 0 16 16" width="16" height="16" fill="none" stroke="currentColor" stroke-width="1.4" stroke-linecap="round" stroke-linejoin="round"><path d="M6 2 V6 H2 M10 2 V6 H14 M6 14 V10 H2 M10 14 V10 H14"/></svg>'
15
- };
16
- var STYLE_ATTR = "data-movie-controller";
5
+ // src/controller/css.ts
17
6
  var CONTROLLER_CSS = `
18
7
  .movie-controller-wrap { position: relative; display: inline-block; line-height: 0; }
19
8
  .movie-controller {
@@ -232,22 +221,8 @@ var CONTROLLER_CSS = `
232
221
  font-family: Menlo, Monaco, monospace;
233
222
  }
234
223
  `;
235
- var styleRefCount = 0;
236
- function installStyles() {
237
- if (styleRefCount === 0) {
238
- const el = document.createElement("style");
239
- el.setAttribute(STYLE_ATTR, "");
240
- el.textContent = CONTROLLER_CSS;
241
- document.head.appendChild(el);
242
- }
243
- styleRefCount++;
244
- }
245
- function uninstallStyles() {
246
- styleRefCount = Math.max(0, styleRefCount - 1);
247
- if (styleRefCount === 0) {
248
- document.head.querySelectorAll(`style[${STYLE_ATTR}]`).forEach((n) => n.remove());
249
- }
250
- }
224
+
225
+ // src/controller/helpers.ts
251
226
  function formatTime(seconds) {
252
227
  const s = Math.max(0, Math.floor(seconds));
253
228
  const m = Math.floor(s / 60);
@@ -272,7 +247,6 @@ function pxToFraction(clientX, rect, inset = 0) {
272
247
  const ratio = (clientX - innerLeft) / innerWidth;
273
248
  return Math.min(Math.max(ratio, 0), 1);
274
249
  }
275
- var PDF_QUALITY = { "low": 0.6, "medium": 0.75, "high": 0.88, "very-high": 0.95 };
276
250
  function extensionForMimeType(mime) {
277
251
  const t = (mime || "").toLowerCase();
278
252
  if (t.includes("pdf")) return "pdf";
@@ -281,6 +255,36 @@ function extensionForMimeType(mime) {
281
255
  if (t.includes("matroska") || t.includes("mkv")) return "mkv";
282
256
  return "mp4";
283
257
  }
258
+
259
+ // src/Controller.ts
260
+ var ICONS = {
261
+ play: '<svg viewBox="0 0 16 16" width="16" height="16" fill="currentColor"><path d="M3 2 L13 8 L3 14 Z"/></svg>',
262
+ pause: '<svg viewBox="0 0 16 16" width="16" height="16" fill="currentColor"><rect x="3" y="2" width="3.5" height="12"/><rect x="9.5" y="2" width="3.5" height="12"/></svg>',
263
+ volumeOn: '<svg viewBox="0 0 16 16" width="16" height="16" fill="currentColor"><path d="M2 6 H5 L9 2 V14 L5 10 H2 Z"/><path d="M11 5 Q13 8 11 11" fill="none" stroke="currentColor" stroke-width="1.2"/><path d="M12.5 3.5 Q15.5 8 12.5 12.5" fill="none" stroke="currentColor" stroke-width="1.2"/></svg>',
264
+ volumeOff: '<svg viewBox="0 0 16 16" width="16" height="16" fill="currentColor"><path d="M2 6 H5 L9 2 V14 L5 10 H2 Z"/><path d="M11 5 L15 11 M15 5 L11 11" fill="none" stroke="currentColor" stroke-width="1.4"/></svg>',
265
+ download: '<svg viewBox="0 0 16 16" width="16" height="16" fill="none" stroke="currentColor" stroke-width="1.4" stroke-linecap="round" stroke-linejoin="round"><path d="M8 2 V11 M4 7 L8 11 L12 7 M3 13 H13"/></svg>',
266
+ fullscreenEnter: '<svg viewBox="0 0 16 16" width="16" height="16" fill="none" stroke="currentColor" stroke-width="1.4" stroke-linecap="round" stroke-linejoin="round"><path d="M2 6 V2 H6 M14 6 V2 H10 M2 10 V14 H6 M14 10 V14 H10"/></svg>',
267
+ present: '<svg viewBox="0 0 16 16" width="16" height="16" fill="none" stroke="currentColor" stroke-width="1.4" stroke-linecap="round" stroke-linejoin="round"><path d="M2 2.5 H14 V10.5 H2 Z M8 10.5 V13.5 M5 13.5 H11"/></svg>',
268
+ fullscreenExit: '<svg viewBox="0 0 16 16" width="16" height="16" fill="none" stroke="currentColor" stroke-width="1.4" stroke-linecap="round" stroke-linejoin="round"><path d="M6 2 V6 H2 M10 2 V6 H14 M6 14 V10 H2 M10 14 V10 H14"/></svg>'
269
+ };
270
+ var STYLE_ATTR = "data-movie-controller";
271
+ var styleRefCount = 0;
272
+ function installStyles() {
273
+ if (styleRefCount === 0) {
274
+ const el = document.createElement("style");
275
+ el.setAttribute(STYLE_ATTR, "");
276
+ el.textContent = CONTROLLER_CSS;
277
+ document.head.appendChild(el);
278
+ }
279
+ styleRefCount++;
280
+ }
281
+ function uninstallStyles() {
282
+ styleRefCount = Math.max(0, styleRefCount - 1);
283
+ if (styleRefCount === 0) {
284
+ document.head.querySelectorAll(`style[${STYLE_ATTR}]`).forEach((n) => n.remove());
285
+ }
286
+ }
287
+ var PDF_QUALITY = { "low": 0.6, "medium": 0.75, "high": 0.88, "very-high": 0.95 };
284
288
  var THEME_PROPERTIES = {
285
289
  accent: "--mc-accent",
286
290
  foreground: "--mc-fg",
@@ -289,6 +293,7 @@ var THEME_PROPERTIES = {
289
293
  trackHeight: "--mc-track-height",
290
294
  font: "--mc-font"
291
295
  };
296
+ var CONTROLLER_OPTION_KEYS = ["canvas", "theme", "exportButton", "keyboard", "clickToPlay", "presentButton", "pauseAtStops", "className"];
292
297
  var Controller = class _Controller {
293
298
  movie;
294
299
  options;
@@ -331,6 +336,16 @@ var Controller = class _Controller {
331
336
  settingsOutsideHandler = null;
332
337
  onReady = null;
333
338
  presenter = null;
339
+ /** `pixi-effects/present`, loaded as soon as the movie has stops (a press of play must not wait for it). */
340
+ present = null;
341
+ presentLoading = null;
342
+ playStarting = false;
343
+ loadPresent() {
344
+ return this.presentLoading ??= import('./present.cjs').then((m) => this.present = m, (err) => {
345
+ this.presentLoading = null;
346
+ throw err;
347
+ });
348
+ }
334
349
  presentBtn = null;
335
350
  onFrame = null;
336
351
  onPlay = null;
@@ -356,13 +371,14 @@ var Controller = class _Controller {
356
371
  if (!options || !options.canvas) {
357
372
  throw new Error("Controller requires options.canvas (HTMLCanvasElement).");
358
373
  }
374
+ chunkTWZNOUM7_cjs.warnUnknownOptions("Controller", options, CONTROLLER_OPTION_KEYS);
359
375
  this.movie = movie;
360
376
  this.options = {
361
377
  canvas: options.canvas,
362
- showExportButton: options.showExportButton ?? true,
363
- enableKeyboardShortcuts: options.enableKeyboardShortcuts ?? true,
378
+ exportButton: options.exportButton ?? true,
379
+ keyboard: options.keyboard ?? true,
364
380
  clickToPlay: options.clickToPlay ?? true,
365
- present: options.present ?? true,
381
+ presentButton: options.presentButton ?? true,
366
382
  pauseAtStops: options.pauseAtStops ?? true,
367
383
  className: options.className ?? "movie-controller"
368
384
  };
@@ -391,10 +407,10 @@ var Controller = class _Controller {
391
407
  this.bindExportPopover();
392
408
  this.bindFullscreen();
393
409
  this.bindVisibility();
394
- if (this.options.enableKeyboardShortcuts) this.bindKeyboard();
410
+ if (this.options.keyboard) this.bindKeyboard();
395
411
  }
396
412
  buildBar() {
397
- const popoverHtml = this.options.showExportButton ? `
413
+ const popoverHtml = this.options.exportButton ? `
398
414
  <div class="mc-settings-popover" role="dialog" aria-label="Export settings" data-open="false">
399
415
  <label class="mc-settings-row">
400
416
  <span>Format</span>
@@ -433,7 +449,7 @@ var Controller = class _Controller {
433
449
  </div>
434
450
  <span class="mc-time">0:00 / 0:00</span>
435
451
  <div class="mc-spacer"></div>
436
- ${this.options.showExportButton ? `<button class="mc-btn mc-export" aria-label="Export" aria-expanded="false">${ICONS.download}</button>` : ""}
452
+ ${this.options.exportButton ? `<button class="mc-btn mc-export" aria-label="Export" aria-expanded="false">${ICONS.download}</button>` : ""}
437
453
  <button class="mc-btn mc-fullscreen" aria-label="Enter fullscreen">${ICONS.fullscreenEnter}</button>
438
454
  </div>
439
455
  `;
@@ -577,6 +593,8 @@ var Controller = class _Controller {
577
593
  this.presentBtn = null;
578
594
  return;
579
595
  }
596
+ this.loadPresent().catch(() => {
597
+ });
580
598
  const total = this.movie.totalFrames || 1;
581
599
  const holder = document.createElement("div");
582
600
  holder.className = "mc-stops";
@@ -588,7 +606,7 @@ var Controller = class _Controller {
588
606
  holder.appendChild(tick);
589
607
  }
590
608
  this.progressEl.appendChild(holder);
591
- if (this.options.present && !this.presentBtn && this.fullscreenBtn) {
609
+ if (this.options.presentButton && !this.presentBtn && this.fullscreenBtn) {
592
610
  const btn = document.createElement("button");
593
611
  btn.className = "mc-btn mc-present";
594
612
  btn.setAttribute("aria-label", "Present");
@@ -633,13 +651,29 @@ var Controller = class _Controller {
633
651
  async startPlaying() {
634
652
  if (this.options.pauseAtStops && (this.movie.stops?.length ?? 0) > 0) {
635
653
  if (this.movie.currentFrame >= this.movie.totalFrames) await this.movie.gotoFrame(0, true);
636
- await this.movie.next();
654
+ let present = this.present;
655
+ if (!present) {
656
+ if (this.playStarting) return;
657
+ this.playStarting = true;
658
+ try {
659
+ present = await this.loadPresent();
660
+ } catch (err) {
661
+ console.warn("pixi-effects: could not load pixi-effects/present, playing straight through:", err);
662
+ } finally {
663
+ this.playStarting = false;
664
+ }
665
+ }
666
+ if (!present) {
667
+ this.movie.play();
668
+ return;
669
+ }
670
+ await present.next(this.movie);
637
671
  } else this.movie.play();
638
672
  }
639
673
  /** Hand the page over to a Presenter (fullscreen, keys, click and swipe move through the stops); Escape gives it back. */
640
674
  async startPresenting() {
641
675
  if (this.presenter || this.destroyed) return;
642
- const { Presenter } = await import('./Presenter.cjs');
676
+ const { Presenter } = await this.loadPresent();
643
677
  if (this.presenter || this.destroyed) return;
644
678
  const p = new Presenter(this.movie, { canvas: this.options.canvas, onExit: () => this.stopPresenting() });
645
679
  this.presenter = p;
@@ -937,7 +971,7 @@ var Controller = class _Controller {
937
971
  this.exportPages = { done: 0, total };
938
972
  } else this.showExportOverlay();
939
973
  try {
940
- const blob = pdf ? await this.movie.exportPDF({
974
+ const blob = pdf ? await (await this.loadPresent()).exportPDF(this.movie, {
941
975
  which: this.exportFormat === "pdf-steps" ? "stops" : "pages",
942
976
  quality: PDF_QUALITY[this.exportQuality],
943
977
  onImage: () => this.pdfPageDone()
@@ -1219,12 +1253,6 @@ var Controller = class _Controller {
1219
1253
  }
1220
1254
  };
1221
1255
 
1222
- exports.CONTROLLER_CSS = CONTROLLER_CSS;
1223
1256
  exports.Controller = Controller;
1224
- exports.extensionForMimeType = extensionForMimeType;
1225
- exports.formatTime = formatTime;
1226
- exports.frameToPercent = frameToPercent;
1227
- exports.pxToFraction = pxToFraction;
1228
- exports.pxToFrame = pxToFrame;
1229
1257
  //# sourceMappingURL=Controller.cjs.map
1230
1258
  //# sourceMappingURL=Controller.cjs.map