pixi-effects 0.16.2 → 0.17.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 (52) hide show
  1. package/CHANGELOG.md +39 -0
  2. package/README.md +6 -6
  3. package/ai/CHAT.md +4 -0
  4. package/ai/SKILL.md +2 -1
  5. package/ai/chat-template.html +3 -3
  6. package/ai/reference/cheatsheet.md +4 -2
  7. package/ai/reference/pitfalls.md +3 -0
  8. package/ai/reference/recipes.md +67 -0
  9. package/ai/template.html +5 -5
  10. package/ai/tools/check.mjs +162 -18
  11. package/ai/tools/render.mjs +21 -7
  12. package/dist/Composition-HYAOYPAX.js +5 -0
  13. package/dist/{Composition-VJWY2NDL.js.map → Composition-HYAOYPAX.js.map} +1 -1
  14. package/dist/Composition-LMVEASHF.cjs +14 -0
  15. package/dist/{Composition-3WWNVRR5.cjs.map → Composition-LMVEASHF.cjs.map} +1 -1
  16. package/dist/Controller.cjs +9 -3
  17. package/dist/Controller.cjs.map +1 -1
  18. package/dist/Controller.d.cts +1 -1
  19. package/dist/Controller.d.ts +1 -1
  20. package/dist/Controller.js +9 -3
  21. package/dist/Controller.js.map +1 -1
  22. package/dist/{Movie-oA0SUAyb.d.cts → Movie-CoxF2Z7t.d.cts} +82 -2
  23. package/dist/{Movie-DilBC348.d.ts → Movie-DHJRrUfI.d.ts} +82 -2
  24. package/dist/Presenter.d.cts +1 -1
  25. package/dist/Presenter.d.ts +1 -1
  26. package/dist/{chunk-2ROVCPSL.cjs → chunk-ETAIVOHP.cjs} +32 -27
  27. package/dist/chunk-ETAIVOHP.cjs.map +1 -0
  28. package/dist/{chunk-FJA5VUOF.cjs → chunk-LBJRXU7N.cjs} +15 -3
  29. package/dist/chunk-LBJRXU7N.cjs.map +1 -0
  30. package/dist/{chunk-ZNKQH356.js → chunk-ORTYBA42.js} +15 -4
  31. package/dist/chunk-ORTYBA42.js.map +1 -0
  32. package/dist/{chunk-XTIHKODH.js → chunk-Q3IVBYT7.js} +10 -5
  33. package/dist/chunk-Q3IVBYT7.js.map +1 -0
  34. package/dist/index.cjs +351 -41
  35. package/dist/index.cjs.map +1 -1
  36. package/dist/index.d.cts +1 -1
  37. package/dist/index.d.ts +1 -1
  38. package/dist/index.js +329 -19
  39. package/dist/index.js.map +1 -1
  40. package/dist/loader.css +1 -1
  41. package/dist/three.cjs +5 -5
  42. package/dist/three.js +1 -1
  43. package/docs/dsl.md +2 -1
  44. package/llms-full.txt +78 -4
  45. package/llms.txt +1 -1
  46. package/package.json +6 -3
  47. package/dist/Composition-3WWNVRR5.cjs +0 -14
  48. package/dist/Composition-VJWY2NDL.js +0 -5
  49. package/dist/chunk-2ROVCPSL.cjs.map +0 -1
  50. package/dist/chunk-FJA5VUOF.cjs.map +0 -1
  51. package/dist/chunk-XTIHKODH.js.map +0 -1
  52. package/dist/chunk-ZNKQH356.js.map +0 -1
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/Controller.ts"],"names":[],"mappings":"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","file":"Controller.js","sourcesContent":["import type { Movie } from './core/Movie';\nimport { warnUnknownOptions } from './core/options';\n\nconst ICONS = {\n play: '<svg viewBox=\"0 0 16 16\" width=\"16\" height=\"16\" fill=\"currentColor\"><path d=\"M3 2 L13 8 L3 14 Z\"/></svg>',\n 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>',\n 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>',\n 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>',\n 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>',\n 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>',\n 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>',\n 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>',\n} as const;\n\nconst STYLE_ATTR = 'data-movie-controller';\n\n/** The bar's default stylesheet. Its colours and sizes are CSS custom properties (`--mc-accent`, `--mc-fg`, `--mc-track`, `--mc-bar-bg`, `--mc-track-height`, `--mc-font`): set them in your page CSS, or with the `theme` option. */\nexport const CONTROLLER_CSS = `\n.movie-controller-wrap { position: relative; display: inline-block; line-height: 0; }\n.movie-controller {\n position: absolute;\n pointer-events: none;\n font-family: var(--mc-font, -apple-system, BlinkMacSystemFont, \"Segoe UI\", Roboto, sans-serif);\n display: flex;\n flex-direction: column;\n justify-content: flex-end;\n opacity: 1;\n transition: opacity 200ms ease;\n}\n.movie-controller[data-state=\"hidden\"] { opacity: 0; }\n.movie-controller > * { pointer-events: auto; }\n\n.mc-progress {\n position: relative;\n width: 100%;\n height: 16px;\n cursor: pointer;\n display: flex;\n align-items: center;\n outline: none;\n}\n.mc-progress:focus-visible {\n outline: 2px solid var(--mc-accent, #007AFF);\n outline-offset: 2px;\n}\n.mc-progress::before {\n content: \"\"; position: absolute; left: 12px; right: 12px;\n height: var(--mc-track-height, 3px); background: var(--mc-track, rgba(255,255,255,0.25));\n transition: height 120ms ease;\n}\n.mc-progress:hover::before, .mc-progress.mc-scrubbing::before { height: calc(var(--mc-track-height, 3px) + 2px); }\n.mc-stops { position: absolute; left: 12px; right: 12px; top: 0; bottom: 0; pointer-events: none; }\n.mc-stop-tick { position: absolute; top: 50%; width: 7px; height: 7px; transform: translate(-50%, -50%); border-radius: 50%; background: var(--mc-fg, #fff); box-shadow: 0 0 0 1.5px rgba(0,0,0,0.5); }\n.mc-stop-page { width: 11px; height: 11px; box-shadow: 0 0 0 2.5px var(--mc-accent, #007AFF), 0 0 0 4px rgba(0,0,0,0.35); }\n.mc-progress-fill {\n position: absolute; left: 12px; top: 50%;\n height: var(--mc-track-height, 3px);\n width: calc((100% - 24px) * var(--mc-fill, 0));\n background: var(--mc-accent, #007AFF);\n transform: translateY(-50%);\n transition: height 120ms ease;\n pointer-events: none;\n}\n.mc-progress:hover .mc-progress-fill,\n.mc-progress.mc-scrubbing .mc-progress-fill { height: calc(var(--mc-track-height, 3px) + 2px); }\n.mc-progress-thumb {\n position: absolute; top: 50%;\n left: calc(12px + (100% - 24px) * var(--mc-fill, 0));\n width: 12px; height: 12px; border-radius: 50%;\n background: var(--mc-accent, #007AFF);\n transform: translate(-50%, -50%) scale(0);\n transition: transform 120ms ease;\n pointer-events: none;\n}\n.mc-progress:hover .mc-progress-thumb,\n.mc-progress.mc-scrubbing .mc-progress-thumb { transform: translate(-50%, -50%) scale(1); }\n\n.mc-bar {\n position: relative;\n display: flex;\n align-items: center;\n gap: 12px;\n padding: 6px 12px 8px 12px;\n background: var(--mc-bar-bg, linear-gradient(to top, rgba(0,0,0,0.75) 0%, rgba(0,0,0,0) 100%));\n color: var(--mc-fg, #fff);\n line-height: 1;\n}\n.mc-btn {\n background: none; border: 0; padding: 0; margin: 0;\n width: 28px; height: 28px;\n display: inline-flex; align-items: center; justify-content: center;\n color: var(--mc-fg, #fff); opacity: 0.85; cursor: pointer;\n transition: opacity 120ms ease;\n}\n.mc-btn:hover { opacity: 1; }\n.mc-btn:disabled { opacity: 0.4; cursor: not-allowed; }\n.mc-time {\n font-size: 12px; font-family: Menlo, Monaco, monospace;\n color: var(--mc-fg, #fff); opacity: 0.85;\n min-width: 90px;\n}\n.mc-spacer { flex: 1; }\n\n.mc-volume { display: flex; align-items: center; }\n.mc-vol-slider {\n position: relative;\n width: 0;\n height: 28px;\n display: flex;\n align-items: center;\n cursor: pointer;\n margin-left: 0;\n outline: none;\n transition: width 200ms ease, margin-left 200ms ease;\n overflow: hidden;\n}\n.mc-volume:hover .mc-vol-slider,\n.mc-volume:focus-within .mc-vol-slider,\n.mc-vol-slider.mc-scrubbing {\n width: 70px;\n margin-left: 6px;\n}\n.mc-vol-slider:focus-visible { outline: 2px solid var(--mc-accent, #007AFF); outline-offset: 2px; }\n.mc-vol-slider::before {\n content: \"\"; position: absolute; left: 4px; right: 4px;\n height: 3px; background: var(--mc-track, rgba(255,255,255,0.25)); border-radius: 2px;\n}\n.mc-vol-fill {\n position: absolute; left: 4px; top: 50%;\n height: 3px;\n width: calc((100% - 8px) * var(--mc-volume, 1));\n background: var(--mc-fg, #fff);\n transform: translateY(-50%);\n border-radius: 2px;\n pointer-events: none;\n}\n.mc-vol-thumb {\n position: absolute; top: 50%;\n left: calc(4px + (100% - 8px) * var(--mc-volume, 1));\n width: 10px; height: 10px; border-radius: 50%;\n background: var(--mc-fg, #fff);\n transform: translate(-50%, -50%);\n pointer-events: none;\n}\n\n[data-mc-wrap]:fullscreen {\n width: 100vw; height: 100vh;\n display: flex; align-items: center; justify-content: center;\n background: #000;\n}\n[data-mc-wrap]:fullscreen > canvas {\n width: 100% !important;\n height: 100% !important;\n max-width: none !important;\n max-height: none !important;\n object-fit: contain;\n border-radius: 0;\n}\n\n.mc-settings-popover {\n position: absolute;\n bottom: calc(100% + 8px);\n right: 12px;\n background: rgba(20, 20, 20, 0.96);\n border-radius: 8px;\n padding: 10px 12px;\n min-width: 180px;\n color: #fff;\n font-size: 12px;\n box-shadow: 0 4px 16px rgba(0,0,0,0.4);\n display: flex;\n flex-direction: column;\n gap: 8px;\n}\n.mc-settings-popover[data-open=\"false\"] { display: none; }\n.mc-settings-row {\n display: flex;\n align-items: center;\n justify-content: space-between;\n gap: 12px;\n}\n.mc-settings-row > span { color: rgba(255,255,255,0.85); }\n.mc-settings-row > select {\n font: inherit;\n background: rgba(255,255,255,0.1);\n color: #fff;\n border: 1px solid rgba(255,255,255,0.18);\n border-radius: 4px;\n padding: 2px 6px;\n cursor: pointer;\n}\n.mc-export-confirm {\n margin-top: 4px;\n width: 100%;\n background: var(--mc-accent, #007AFF);\n color: #fff;\n border: 0;\n border-radius: 4px;\n padding: 6px 10px;\n font: inherit;\n font-weight: 600;\n cursor: pointer;\n transition: background 120ms ease;\n}\n.mc-export-confirm:hover { background: #0066d6; }\n.mc-export-confirm:disabled { background: rgba(255,255,255,0.18); cursor: not-allowed; }\n\n.mc-export-overlay {\n position: absolute; inset: 0;\n background: rgba(0,0,0,0.7);\n display: flex; justify-content: center; align-items: center;\n z-index: 2;\n}\n.mc-export-panel {\n background: rgba(20,20,20,0.96); color: #fff;\n border-radius: 8px; padding: 16px 20px;\n text-align: center; min-width: 200px; max-width: 80%;\n font-family: -apple-system, BlinkMacSystemFont, \"Segoe UI\", Roboto, sans-serif;\n}\n.mc-export-title { font-size: 13px; margin-bottom: 10px; opacity: 0.9; }\n.mc-export-track {\n width: 100%; height: 6px;\n background: rgba(255,255,255,0.15); border-radius: 3px;\n margin-bottom: 8px; overflow: hidden;\n}\n.mc-export-fill {\n height: 100%; width: 0%;\n background: linear-gradient(90deg, var(--mc-accent, #007AFF), var(--mc-accent, #0056CC));\n transition: width 0.3s ease; border-radius: 3px;\n}\n.mc-export-text {\n color: rgba(255,255,255,0.7); font-size: 11px;\n font-family: Menlo, Monaco, monospace;\n}\n`;\n\nlet styleRefCount = 0;\n\nfunction installStyles(): void {\n if (styleRefCount === 0) {\n const el = document.createElement('style');\n el.setAttribute(STYLE_ATTR, '');\n el.textContent = CONTROLLER_CSS;\n document.head.appendChild(el);\n }\n styleRefCount++;\n}\n\nfunction uninstallStyles(): void {\n styleRefCount = Math.max(0, styleRefCount - 1);\n if (styleRefCount === 0) {\n document.head.querySelectorAll(`style[${STYLE_ATTR}]`).forEach((n) => n.remove());\n }\n}\n\nexport function formatTime(seconds: number): string {\n const s = Math.max(0, Math.floor(seconds));\n const m = Math.floor(s / 60);\n const r = s % 60;\n return `${m}:${r.toString().padStart(2, '0')}`;\n}\n\nexport function frameToPercent(frame: number, totalFrames: number): number {\n if (totalFrames <= 0) return 0;\n const f = Math.min(Math.max(frame, 0), totalFrames);\n return (f / totalFrames) * 100;\n}\n\nexport function pxToFrame(clientX: number, rect: { left: number; width: number }, totalFrames: number): number {\n if (rect.width <= 0 || totalFrames <= 0) return 0;\n const ratio = (clientX - rect.left) / rect.width;\n const clamped = Math.min(Math.max(ratio, 0), 1);\n return Math.round(clamped * totalFrames);\n}\n\nexport function pxToFraction(clientX: number, rect: { left: number; width: number }, inset = 0): number {\n const innerLeft = rect.left + inset;\n const innerWidth = Math.max(0, rect.width - 2 * inset);\n if (innerWidth <= 0) return 0;\n const ratio = (clientX - innerLeft) / innerWidth;\n return Math.min(Math.max(ratio, 0), 1);\n}\n\n/** The JPEG quality of a PDF page for each quality choice of the panel. */\nconst PDF_QUALITY = { 'low': 0.6, 'medium': 0.75, 'high': 0.88, 'very-high': 0.95 } as const;\n\nexport function extensionForMimeType(mime: string): string {\n const t = (mime || '').toLowerCase();\n if (t.includes('pdf')) return 'pdf';\n if (t.includes('webm')) return 'webm';\n if (t.includes('quicktime') || t.includes('mov')) return 'mov';\n if (t.includes('matroska') || t.includes('mkv')) return 'mkv';\n return 'mp4';\n}\n\n/**\n * The look of the bar. Each key sets a CSS custom property on the bar (so you can also set `--mc-accent` … in your own CSS, on the\n * canvas's parent or on `:root`). `null` puts a value back to the default.\n */\nexport interface ControllerTheme {\n /** The colour of the progress bar, its thumb and the focus rings. Default `#007AFF` (blue). */\n accent?: string | null;\n /** Icons, the time and the volume slider. Default `#fff`. */\n foreground?: string | null;\n /** The unfilled part of the progress and volume bars. Default `rgba(255,255,255,0.25)`. */\n track?: string | null;\n /** The background behind the buttons: any CSS background, e.g. a gradient. Default: black fading to transparent upward. */\n barBackground?: string | null;\n /** Thickness of the progress bar in px (a number) or any CSS length. Default 3. */\n trackHeight?: number | string | null;\n /** `font-family` of the bar. */\n font?: string | null;\n}\n\nconst THEME_PROPERTIES: Record<keyof ControllerTheme, string> = {\n accent: '--mc-accent', foreground: '--mc-fg', track: '--mc-track', barBackground: '--mc-bar-bg', trackHeight: '--mc-track-height', font: '--mc-font',\n};\n\nexport interface ControllerOptions {\n canvas: HTMLCanvasElement;\n /** Colours and sizes of the bar, see {@link ControllerTheme}. Can be changed later with `controller.setTheme()`. */\n theme?: ControllerTheme;\n showExportButton?: boolean;\n enableKeyboardShortcuts?: boolean;\n /** A click (or tap) on the picture plays / pauses, like a `<video>` element. Default true; `false` leaves the canvas alone. */\n clickToPlay?: boolean;\n /** A movie with `stops` gets a Present button that starts a {@link Presenter} (keys, click and swipe move through the stops). Default true; `false` keeps only the marks on the seek bar. */\n present?: boolean;\n /** A movie with `stops`: the play button (and a click on the picture, and Space) plays to the next stop and pauses there, like a slide. Default true; `false` plays straight through to the end. */\n pauseAtStops?: boolean;\n className?: string;\n}\n\ninterface ResolvedOptions {\n canvas: HTMLCanvasElement;\n showExportButton: boolean;\n enableKeyboardShortcuts: boolean;\n clickToPlay: boolean;\n present: boolean;\n pauseAtStops: boolean;\n className: string;\n}\n\nexport class Controller {\n movie: Movie;\n options: ResolvedOptions;\n\n private root: HTMLDivElement;\n private wrapper: HTMLDivElement;\n private wrappedHere = false;\n /** The canvas's own inline width / height, as the page wrote them (we override them while the wrapper is fitted). */\n private canvasInlineWidth = '';\n private canvasInlineHeight = '';\n private fitWrapHandler: (() => void) | null = null;\n private fitObserver: ResizeObserver | null = null;\n private destroyed = false;\n\n private progressEl!: HTMLDivElement;\n private progressFillEl!: HTMLDivElement;\n private progressThumbEl!: HTMLDivElement;\n private playBtn!: HTMLButtonElement;\n private muteBtn!: HTMLButtonElement;\n private timeEl!: HTMLSpanElement;\n private exportBtn: HTMLButtonElement | null = null;\n private settingsPopoverEl: HTMLDivElement | null = null;\n private settingsFormatSelect: HTMLSelectElement | null = null;\n private settingsQualitySelect: HTMLSelectElement | null = null;\n private exportConfirmBtn: HTMLButtonElement | null = null;\n private exportFormat: 'mp4' | 'webm' | 'mov' | 'pdf' | 'pdf-steps' = 'mp4';\n private exportQuality: 'low' | 'medium' | 'high' | 'very-high' = 'high';\n private settingsOpen = false;\n private hideTimer: ReturnType<typeof setTimeout> | null = null;\n private static readonly HIDE_DELAY_MS = 2500;\n private static readonly PROGRESS_INSET_PX = 12;\n private isScrubbing = false;\n private wasPlayingBeforeScrub = false;\n private activePointerId: number | null = null;\n private isExporting = false;\n private exportPages: { done: number; total: number } | null = null;\n private exportOverlay: HTMLDivElement | null = null;\n private exportFillEl: HTMLDivElement | null = null;\n private exportTextEl: HTMLDivElement | null = null;\n private keyHandler: ((e: KeyboardEvent) => void) | null = null;\n private settingsKeyHandler: ((e: KeyboardEvent) => void) | null = null;\n private settingsOutsideHandler: ((e: PointerEvent) => void) | null = null;\n private onReady: (() => void) | null = null;\n private presenter: { destroy(): void } | null = null;\n private presentBtn: HTMLButtonElement | null = null;\n private onFrame: ((e: { frame: number; totalFrames: number }) => void) | null = null;\n private onPlay: (() => void) | null = null;\n private onPause: (() => void) | null = null;\n private onProgress: ((e: { progress: number; frame: number; totalFrames: number }) => void) | null = null;\n private onWrapPointerMove: (() => void) | null = null;\n private onWrapMouseLeave: (() => void) | null = null;\n private resizeObserver: ResizeObserver | null = null;\n private volumeSliderEl: HTMLDivElement | null = null;\n private volumeContainerEl: HTMLDivElement | null = null;\n private fullscreenBtn: HTMLButtonElement | null = null;\n private isVolumeScrubbing = false;\n private canvasClickHandler: (() => void) | null = null;\n private canvasPointerDownHandler: (() => void) | null = null;\n private canvasCursor = '';\n /** Set when a pointerdown on the canvas closed the export popover: the click that follows must not play / pause. */\n private swallowCanvasClick = false;\n private fullscreenChangeHandler: (() => void) | null = null;\n private wheelHandler: ((e: WheelEvent) => void) | null = null;\n /** Ends a drag the pointerup of which never arrives (see bindScrubbing). */\n private windowBlurHandler: (() => void) | null = null;\n\n constructor(movie: Movie, options: ControllerOptions) {\n if (!options || !options.canvas) {\n throw new Error('Controller requires options.canvas (HTMLCanvasElement).');\n }\n this.movie = movie;\n this.options = {\n canvas: options.canvas,\n showExportButton: options.showExportButton ?? true,\n enableKeyboardShortcuts: options.enableKeyboardShortcuts ?? true,\n clickToPlay: options.clickToPlay ?? true,\n present: options.present ?? true,\n pauseAtStops: options.pauseAtStops ?? true,\n className: options.className ?? 'movie-controller',\n };\n\n installStyles();\n this.wrapper = this.ensurePositioningContext(this.options.canvas);\n this.root = document.createElement('div');\n this.root.className = this.options.className;\n this.wrapper.appendChild(this.root);\n this.buildBar();\n this.setTheme(options.theme ?? {});\n this.bindFitWrap();\n this.syncRootToCanvas();\n if (typeof ResizeObserver !== 'undefined') {\n this.resizeObserver = new ResizeObserver(() => this.syncRootToCanvas());\n this.resizeObserver.observe(this.options.canvas);\n // Also observe the wrapper: when its size changes (browser resize, sibling\n // panels resizing) the canvas's position can shift without its own size\n // changing, which canvas-only observation would miss.\n this.resizeObserver.observe(this.wrapper);\n }\n this.root.setAttribute('data-state', 'visible');\n this.bindMovieEvents();\n this.refreshStops();\n this.bindPlayButton();\n if (this.options.clickToPlay) this.bindCanvasClick();\n this.bindScrubbing();\n this.bindMuteButton();\n this.bindVolumeSlider();\n this.bindExportPopover();\n this.bindFullscreen();\n this.bindVisibility();\n if (this.options.enableKeyboardShortcuts) this.bindKeyboard();\n }\n\n private buildBar(): void {\n const popoverHtml = this.options.showExportButton ? `\n <div class=\"mc-settings-popover\" role=\"dialog\" aria-label=\"Export settings\" data-open=\"false\">\n <label class=\"mc-settings-row\">\n <span>Format</span>\n <select class=\"mc-settings-format\">\n <option value=\"mp4\">MP4</option>\n <option value=\"webm\">WebM</option>\n <option value=\"mov\">MOV</option>\n </select>\n </label>\n <label class=\"mc-settings-row\">\n <span>Quality</span>\n <select class=\"mc-settings-quality\">\n <option value=\"low\">Low</option>\n <option value=\"medium\">Medium</option>\n <option value=\"high\" selected>High</option>\n <option value=\"very-high\">Very High</option>\n </select>\n </label>\n <button type=\"button\" class=\"mc-export-confirm\">Download</button>\n </div>\n ` : '';\n this.root.innerHTML = `\n <div class=\"mc-progress\" role=\"slider\" tabindex=\"0\" aria-label=\"Seek\" aria-valuemin=\"0\" aria-valuemax=\"${this.movie.totalFrames}\" aria-valuenow=\"0\">\n <div class=\"mc-progress-fill\"></div>\n <div class=\"mc-progress-thumb\"></div>\n </div>\n <div class=\"mc-bar\">\n ${popoverHtml}\n <button class=\"mc-btn mc-play\" aria-label=\"Play\">${ICONS.play}</button>\n <div class=\"mc-volume\">\n <button class=\"mc-btn mc-mute\" aria-label=\"Mute\">${ICONS.volumeOn}</button>\n <div class=\"mc-vol-slider\" role=\"slider\" tabindex=\"0\" aria-label=\"Volume\" aria-valuemin=\"0\" aria-valuemax=\"100\" aria-valuenow=\"100\">\n <div class=\"mc-vol-fill\"></div>\n <div class=\"mc-vol-thumb\"></div>\n </div>\n </div>\n <span class=\"mc-time\">0:00 / 0:00</span>\n <div class=\"mc-spacer\"></div>\n ${this.options.showExportButton ? `<button class=\"mc-btn mc-export\" aria-label=\"Export\" aria-expanded=\"false\">${ICONS.download}</button>` : ''}\n <button class=\"mc-btn mc-fullscreen\" aria-label=\"Enter fullscreen\">${ICONS.fullscreenEnter}</button>\n </div>\n `;\n this.progressEl = this.root.querySelector('.mc-progress') as HTMLDivElement;\n this.progressFillEl = this.root.querySelector('.mc-progress-fill') as HTMLDivElement;\n this.progressThumbEl = this.root.querySelector('.mc-progress-thumb') as HTMLDivElement;\n this.playBtn = this.root.querySelector('.mc-play') as HTMLButtonElement;\n this.muteBtn = this.root.querySelector('.mc-mute') as HTMLButtonElement;\n this.timeEl = this.root.querySelector('.mc-time') as HTMLSpanElement;\n this.exportBtn = this.root.querySelector('.mc-export') as HTMLButtonElement | null;\n this.settingsPopoverEl = this.root.querySelector('.mc-settings-popover') as HTMLDivElement | null;\n this.settingsFormatSelect = this.root.querySelector('.mc-settings-format') as HTMLSelectElement | null;\n this.settingsQualitySelect = this.root.querySelector('.mc-settings-quality') as HTMLSelectElement | null;\n this.exportConfirmBtn = this.root.querySelector('.mc-export-confirm') as HTMLButtonElement | null;\n this.volumeSliderEl = this.root.querySelector('.mc-vol-slider') as HTMLDivElement | null;\n this.volumeContainerEl = this.root.querySelector('.mc-volume') as HTMLDivElement | null;\n this.fullscreenBtn = this.root.querySelector('.mc-fullscreen') as HTMLButtonElement | null;\n if (this.settingsFormatSelect) this.settingsFormatSelect.value = this.exportFormat;\n if (this.settingsQualitySelect) this.settingsQualitySelect.value = this.exportQuality;\n }\n\n /** Change the look of the bar (see {@link ControllerTheme}): only the keys you give change, `null` restores the default. */\n setTheme(theme: ControllerTheme): void {\n warnUnknownOptions('Controller theme', theme as Record<string, unknown>, Object.keys(THEME_PROPERTIES));\n for (const key of Object.keys(THEME_PROPERTIES) as Array<keyof ControllerTheme>) {\n if (!(key in theme)) continue;\n const value = theme[key];\n const prop = THEME_PROPERTIES[key];\n if (value === null || value === undefined || value === '') this.root.style.removeProperty(prop);\n else this.root.style.setProperty(prop, typeof value === 'number' ? `${value}px` : String(value));\n }\n }\n\n private ensurePositioningContext(canvas: HTMLCanvasElement): HTMLDivElement {\n const parent = canvas.parentElement;\n if (!parent) {\n throw new Error('Controller: canvas must be attached to the DOM before constructing.');\n }\n const pos = getComputedStyle(parent).position;\n if (pos === 'relative' || pos === 'absolute' || pos === 'fixed' || pos === 'sticky') {\n // Tag the user's element so the [data-mc-wrap]:fullscreen style hooks apply\n // to it the same way they apply to our auto-wrap. Cleaned up on destroy.\n parent.setAttribute('data-mc-wrap', '');\n return parent as HTMLDivElement;\n }\n const wrap = document.createElement('div');\n wrap.className = 'movie-controller-wrap';\n wrap.setAttribute('data-mc-wrap', '');\n wrap.style.position = 'relative';\n wrap.style.display = 'inline-block';\n wrap.style.lineHeight = '0';\n parent.insertBefore(wrap, canvas);\n wrap.appendChild(canvas);\n this.wrappedHere = true;\n this.canvasInlineWidth = canvas.style.width;\n this.canvasInlineHeight = canvas.style.height;\n\n return wrap;\n }\n\n /**\n * Make the wrapper exactly as wide as the canvas. A shrink-to-fit wrapper around a canvas that is sized in percent (the usual\n * `canvas { width: min(960px, 100%) }`) is as wide as the canvas's width ATTRIBUTE (1280), so the picture sat at its left edge\n * with an empty strip beside it. We measure the canvas as the page styled it (the wrapper made transparent to layout), give\n * the wrapper that width, and let the canvas fill the wrapper. Re-measured when the window or the page's box changes.\n */\n private fitWrap(): void {\n if (!this.wrappedHere) return;\n const wrap = this.wrapper, canvas = this.options.canvas;\n if (document.fullscreenElement === wrap) { // the fullscreen CSS owns the size\n wrap.style.width = '';\n canvas.style.width = this.canvasInlineWidth; canvas.style.height = this.canvasInlineHeight;\n return;\n }\n canvas.style.width = this.canvasInlineWidth; canvas.style.height = this.canvasInlineHeight;\n const display = wrap.style.display;\n wrap.style.display = 'contents'; wrap.style.width = '';\n const w = canvas.getBoundingClientRect().width;\n wrap.style.display = display;\n if (!(w > 0)) return;\n wrap.style.width = `${w}px`;\n canvas.style.width = '100%'; canvas.style.height = 'auto';\n }\n\n private bindFitWrap(): void {\n if (!this.wrappedHere) return;\n this.fitWrap();\n let queued = false;\n this.fitWrapHandler = () => {\n if (queued) return;\n queued = true;\n requestAnimationFrame(() => { queued = false; this.fitWrap(); });\n };\n window.addEventListener('resize', this.fitWrapHandler);\n const parent = this.wrapper.parentElement;\n if (parent && typeof ResizeObserver !== 'undefined') {\n this.fitObserver = new ResizeObserver(this.fitWrapHandler);\n this.fitObserver.observe(parent);\n }\n }\n\n private bindMovieEvents(): void {\n this.onReady = () => {\n this.progressEl.setAttribute('aria-valuemax', String(this.movie.totalFrames));\n this.refreshTime(0);\n this.refreshProgress(0);\n this.refreshVolumeUI();\n this.refreshStops();\n };\n this.onFrame = ({ frame, totalFrames }) => {\n if (!this.isScrubbing) {\n this.refreshProgress(frame, totalFrames);\n }\n this.refreshTime(frame);\n };\n // `movie.play()` may be called by the host page, not only by this bar's button.\n this.onPlay = () => {\n this.refreshPlayIcon();\n this.kickIdleTimer();\n };\n this.onPause = () => {\n this.refreshPlayIcon();\n // YouTube-style: pause shows the bar momentarily, then auto-hides on idle.\n this.kickIdleTimer();\n };\n this.onProgress = ({ progress, frame, totalFrames }) => {\n if (!this.isExporting || !this.exportFillEl || !this.exportTextEl) return;\n this.exportFillEl.style.width = `${progress}%`;\n this.exportTextEl.textContent = `${progress}% (${frame} / ${totalFrames} frames)`;\n };\n this.movie.on('ready', this.onReady);\n this.movie.on('frame', this.onFrame);\n this.movie.on('play', this.onPlay);\n this.movie.on('pause', this.onPause);\n this.movie.on('progress', this.onProgress);\n }\n\n /** The stops of a presentation as marks on the seek bar, and the Present button. */\n private refreshStops(): void {\n this.progressEl.querySelector('.mc-stops')?.remove();\n const stops = this.movie.stops ?? [];\n this.refreshPdfChoices(stops.length > 0);\n if (stops.length === 0) {\n this.presentBtn?.remove(); this.presentBtn = null;\n return;\n }\n const total = this.movie.totalFrames || 1;\n const holder = document.createElement('div');\n holder.className = 'mc-stops';\n for (const s of stops) {\n const tick = document.createElement('div');\n tick.className = s.pageStart ? 'mc-stop-tick mc-stop-page' : 'mc-stop-tick';\n tick.style.left = `${(s.frame / total) * 100}%`;\n if (s.page) tick.title = s.page;\n holder.appendChild(tick);\n }\n this.progressEl.appendChild(holder);\n if (this.options.present && !this.presentBtn && this.fullscreenBtn) {\n const btn = document.createElement('button');\n btn.className = 'mc-btn mc-present';\n btn.setAttribute('aria-label', 'Present');\n btn.title = 'Present';\n btn.innerHTML = ICONS.present;\n btn.addEventListener('click', () => { void this.startPresenting(); });\n this.fullscreenBtn.parentElement?.insertBefore(btn, this.fullscreenBtn);\n this.presentBtn = btn;\n }\n }\n\n /** A deck can be downloaded as a PDF: the format list gets \"PDF\" choices while the movie has stops. */\n private refreshPdfChoices(has: boolean): void {\n const select = this.settingsFormatSelect;\n if (!select) return;\n const present = !!select.querySelector('option[value=\"pdf\"]');\n if (has && !present) {\n for (const [value, label] of [['pdf', 'PDF (pages)'], ['pdf-steps', 'PDF (every step)']] as const) {\n const o = document.createElement('option');\n o.value = value; o.textContent = label;\n select.appendChild(o);\n }\n } else if (!has && present) {\n select.querySelectorAll('option[value=\"pdf\"], option[value=\"pdf-steps\"]').forEach((o) => o.remove());\n if (this.exportFormat === 'pdf' || this.exportFormat === 'pdf-steps') { this.exportFormat = 'mp4'; select.value = 'mp4'; }\n }\n }\n\n /** Play, or pause: a movie with stops plays to the next stop (and from the end, again from the start). */\n private async togglePlay(): Promise<void> {\n if (this.movie.isPlaying) { this.movie.pause(); return; }\n await this.startPlaying();\n }\n\n /** Start playing: to the next stop for a movie with stops, to the end for any other (or with `pauseAtStops: false`). */\n private async startPlaying(): Promise<void> {\n if (this.options.pauseAtStops && (this.movie.stops?.length ?? 0) > 0) {\n if (this.movie.currentFrame >= this.movie.totalFrames) await this.movie.gotoFrame(0, true);\n await this.movie.next();\n } else this.movie.play();\n }\n\n /** Hand the page over to a Presenter (fullscreen, keys, click and swipe move through the stops); Escape gives it back. */\n private async startPresenting(): Promise<void> {\n if (this.presenter || this.destroyed) return;\n const { Presenter } = await import('./Presenter');\n if (this.presenter || this.destroyed) return;\n const p = new Presenter(this.movie, { canvas: this.options.canvas, onExit: () => this.stopPresenting() });\n this.presenter = p;\n await p.start();\n }\n\n private stopPresenting(): void {\n const p = this.presenter;\n this.presenter = null;\n p?.destroy();\n }\n\n private bindPlayButton(): void {\n // pause / play emit 'pause' / 'play' events, which the handlers turn into refreshPlayIcon + kickIdleTimer\n this.playBtn.addEventListener('click', () => { void this.togglePlay(); });\n }\n\n /** Clicking the picture plays / pauses (a tap on a phone too). */\n private bindCanvasClick(): void {\n const canvas = this.options.canvas;\n this.canvasCursor = canvas.style.cursor;\n canvas.style.cursor = 'pointer';\n this.canvasPointerDownHandler = () => { this.swallowCanvasClick = false; };\n this.canvasClickHandler = () => {\n if (this.presenter) return; // a presentation: the Presenter owns clicks\n // the tap that closed the export popover (see bindExportPopover) is not also a play / pause\n if (this.swallowCanvasClick) { this.swallowCanvasClick = false; return; }\n void this.togglePlay();\n };\n canvas.addEventListener('pointerdown', this.canvasPointerDownHandler);\n canvas.addEventListener('click', this.canvasClickHandler);\n }\n\n private refreshPlayIcon(): void {\n this.playBtn.innerHTML = this.movie.isPlaying ? ICONS.pause : ICONS.play;\n this.playBtn.setAttribute('aria-label', this.movie.isPlaying ? 'Pause' : 'Play');\n }\n\n private bindMuteButton(): void {\n this.muteBtn.addEventListener('click', () => {\n this.movie.toggleMute();\n this.refreshVolumeUI();\n });\n }\n\n private refreshMuteIcon(): void {\n const silent = this.movie.muted || this.movie.volume <= 0;\n this.muteBtn.innerHTML = silent ? ICONS.volumeOff : ICONS.volumeOn;\n this.muteBtn.setAttribute('aria-label', silent ? 'Unmute' : 'Mute');\n }\n\n private refreshVolumeUI(): void {\n this.refreshMuteIcon();\n if (!this.volumeSliderEl) return;\n const effective = this.movie.muted ? 0 : this.movie.volume;\n this.volumeSliderEl.style.setProperty('--mc-volume', String(effective));\n this.volumeSliderEl.setAttribute('aria-valuenow', String(Math.round(effective * 100)));\n }\n\n private bindVolumeSlider(): void {\n if (!this.volumeSliderEl || !this.volumeContainerEl) return;\n const slider = this.volumeSliderEl;\n const container = this.volumeContainerEl;\n\n const setFromPointer = (clientX: number) => {\n const rect = slider.getBoundingClientRect();\n const v = pxToFraction(clientX, { left: rect.left, width: rect.width }, 4);\n this.movie.volume = v;\n if (this.movie.muted && v > 0) this.movie.muted = false;\n this.refreshVolumeUI();\n };\n\n const onDown = (e: PointerEvent) => {\n this.isVolumeScrubbing = true;\n slider.classList.add('mc-scrubbing');\n try { slider.setPointerCapture(e.pointerId); } catch { /* unsupported */ }\n setFromPointer(e.clientX);\n };\n const finish = (pointerId?: number) => {\n if (!this.isVolumeScrubbing) return;\n this.isVolumeScrubbing = false;\n slider.classList.remove('mc-scrubbing');\n try { if (pointerId !== undefined) slider.releasePointerCapture(pointerId); } catch { /* unsupported */ }\n };\n const onMove = (e: PointerEvent) => {\n if (!this.isVolumeScrubbing) return;\n if (e.buttons === 0) { finish(e.pointerId); return; } // released outside an iframe: see bindScrubbing\n setFromPointer(e.clientX);\n };\n const onUp = (e: PointerEvent) => finish(e.pointerId);\n slider.addEventListener('pointerdown', onDown);\n slider.addEventListener('pointermove', onMove);\n slider.addEventListener('pointerup', onUp);\n slider.addEventListener('pointercancel', onUp);\n slider.addEventListener('lostpointercapture', () => finish());\n\n this.wheelHandler = (e: WheelEvent) => {\n e.preventDefault();\n this.adjustVolume(e.deltaY < 0 ? 0.05 : -0.05);\n };\n container.addEventListener('wheel', this.wheelHandler, { passive: false });\n }\n\n /**\n * Does this browser have the Fullscreen API for an element? iPhone Safari does not (it can only put a <video> in fullscreen),\n * and a button that does nothing is worse than none.\n */\n private supportsFullscreen(): boolean {\n return typeof (this.wrapper as { requestFullscreen?: unknown }).requestFullscreen === 'function' && document.fullscreenEnabled !== false;\n }\n\n private bindFullscreen(): void {\n if (!this.fullscreenBtn) return;\n if (!this.supportsFullscreen()) {\n this.fullscreenBtn.remove();\n this.fullscreenBtn = null; // the F key checks this too\n return;\n }\n this.fullscreenBtn.addEventListener('click', () => {\n void this.toggleFullscreen();\n });\n this.fullscreenChangeHandler = () => {\n this.fitWrap();\n this.refreshFullscreenIcon();\n // Fullscreen reflow can shift the canvas without changing its size, which\n // ResizeObserver would miss; resync the overlay explicitly.\n this.syncRootToCanvas();\n };\n document.addEventListener('fullscreenchange', this.fullscreenChangeHandler);\n }\n\n private async toggleFullscreen(): Promise<void> {\n try {\n if (document.fullscreenElement === this.wrapper) {\n await document.exitFullscreen();\n } else {\n await this.wrapper.requestFullscreen();\n }\n } catch (err) {\n console.warn('pixi-effects: fullscreen denied:', err);\n }\n }\n\n private refreshFullscreenIcon(): void {\n if (!this.fullscreenBtn) return;\n const inFs = document.fullscreenElement === this.wrapper;\n this.fullscreenBtn.innerHTML = inFs ? ICONS.fullscreenExit : ICONS.fullscreenEnter;\n this.fullscreenBtn.setAttribute('aria-label', inFs ? 'Exit fullscreen' : 'Enter fullscreen');\n }\n\n private refreshProgress(frame: number, totalFrames?: number): void {\n const total = totalFrames ?? this.movie.totalFrames;\n const pct = frameToPercent(frame, total);\n this.progressEl.style.setProperty('--mc-fill', String(pct / 100));\n this.progressEl.setAttribute('aria-valuenow', String(frame));\n }\n\n private refreshTime(frame: number): void {\n const fr = this.movie.frameRate || 1;\n const cur = frame / fr;\n const total = this.movie.totalFrames / fr;\n this.timeEl.textContent = `${formatTime(cur)} / ${formatTime(total)}`;\n }\n\n private bindScrubbing(): void {\n const onDown = (e: PointerEvent) => {\n this.isScrubbing = true;\n this.activePointerId = e.pointerId;\n this.wasPlayingBeforeScrub = this.movie.isPlaying;\n if (this.movie.isPlaying) {\n this.movie.pause();\n this.refreshPlayIcon();\n }\n this.progressEl.classList.add('mc-scrubbing');\n try { this.progressEl.setPointerCapture(e.pointerId); } catch { /* unsupported */ }\n this.seekFromPointer(e.clientX);\n };\n // End the drag. `clientX` is given when the pointer was released over the bar (seek to where it was).\n // A page inside an iframe never receives the pointerup of a button released OUTSIDE the iframe, so the\n // drag also ends on lostpointercapture, on the window losing focus, and on the first pointermove that\n // has no button down — otherwise it stayed \"scrubbing\" (paused, seeking on every hover).\n const finish = (clientX?: number, pointerId?: number) => {\n if (!this.isScrubbing) return;\n if (clientX !== undefined) this.seekFromPointer(clientX);\n this.isScrubbing = false;\n this.activePointerId = null;\n this.progressEl.classList.remove('mc-scrubbing');\n try { if (pointerId !== undefined) this.progressEl.releasePointerCapture(pointerId); } catch { /* unsupported */ }\n if (this.wasPlayingBeforeScrub) {\n void this.startPlaying();\n this.refreshPlayIcon();\n }\n };\n const onMove = (e: PointerEvent) => {\n if (!this.isScrubbing) return;\n if (e.buttons === 0) { finish(undefined, e.pointerId); return; }\n this.seekFromPointer(e.clientX);\n };\n const onUp = (e: PointerEvent) => finish(e.clientX, e.pointerId);\n this.progressEl.addEventListener('pointerdown', onDown);\n this.progressEl.addEventListener('pointermove', onMove);\n this.progressEl.addEventListener('pointerup', onUp);\n this.progressEl.addEventListener('pointercancel', onUp);\n this.progressEl.addEventListener('lostpointercapture', () => finish());\n this.windowBlurHandler = () => { finish(); this.isVolumeScrubbing = false; this.volumeSliderEl?.classList.remove('mc-scrubbing'); };\n window.addEventListener('blur', this.windowBlurHandler);\n }\n\n private seekFromPointer(clientX: number): void {\n const rect = this.progressEl.getBoundingClientRect();\n const inset = Controller.PROGRESS_INSET_PX;\n const innerLeft = rect.left + inset;\n const innerWidth = Math.max(0, rect.width - 2 * inset);\n const frame = pxToFrame(clientX, { left: innerLeft, width: innerWidth }, this.movie.totalFrames);\n this.refreshProgress(frame);\n void this.movie.gotoFrame(frame);\n }\n\n private bindExportPopover(): void {\n if (!this.exportBtn || !this.settingsPopoverEl) return;\n\n // Download icon on the bar toggles the popover (it does NOT directly trigger export).\n this.exportBtn.addEventListener('click', (e) => {\n e.stopPropagation();\n this.toggleSettings(!this.settingsOpen);\n });\n\n // Confirm button inside the popover triggers the actual export, then closes.\n if (this.exportConfirmBtn) {\n this.exportConfirmBtn.addEventListener('click', () => {\n this.toggleSettings(false);\n void this.handleExport();\n });\n }\n\n if (this.settingsFormatSelect) {\n this.settingsFormatSelect.addEventListener('change', (e) => {\n const v = (e.target as HTMLSelectElement).value;\n if (v === 'mp4' || v === 'webm' || v === 'mov' || v === 'pdf' || v === 'pdf-steps') this.exportFormat = v;\n });\n }\n if (this.settingsQualitySelect) {\n this.settingsQualitySelect.addEventListener('change', (e) => {\n const v = (e.target as HTMLSelectElement).value;\n if (v === 'low' || v === 'medium' || v === 'high' || v === 'very-high') this.exportQuality = v;\n });\n }\n\n this.settingsKeyHandler = (e: KeyboardEvent) => {\n if (e.code === 'Escape' && this.settingsOpen) {\n e.preventDefault();\n this.toggleSettings(false);\n }\n };\n document.addEventListener('keydown', this.settingsKeyHandler);\n\n this.settingsOutsideHandler = (e: PointerEvent) => {\n if (!this.settingsOpen) return;\n const target = e.target as Node | null;\n if (!target) return;\n if (this.settingsPopoverEl?.contains(target)) return;\n if (this.exportBtn?.contains(target)) return;\n if (this.options.canvas.contains(target)) this.swallowCanvasClick = true; // closing the popover is all this tap does\n this.toggleSettings(false);\n };\n document.addEventListener('pointerdown', this.settingsOutsideHandler);\n }\n\n private toggleSettings(open: boolean): void {\n if (!this.exportBtn || !this.settingsPopoverEl) return;\n this.settingsOpen = open;\n this.settingsPopoverEl.setAttribute('data-open', open ? 'true' : 'false');\n this.exportBtn.setAttribute('aria-expanded', open ? 'true' : 'false');\n if (open) {\n // Keep the bar visible while the popover is open.\n if (this.hideTimer) { clearTimeout(this.hideTimer); this.hideTimer = null; }\n this.setVisible(true);\n } else {\n // Resume normal auto-hide cadence after closing.\n this.kickIdleTimer();\n }\n }\n\n private async handleExport(): Promise<void> {\n if (this.isExporting) return;\n this.isExporting = true;\n const wasPlaying = this.movie.isPlaying;\n if (wasPlaying) {\n this.movie.pause();\n this.refreshPlayIcon();\n }\n const pdf = this.exportFormat === 'pdf' || this.exportFormat === 'pdf-steps';\n if (pdf) {\n const stops = this.movie.stops ?? [];\n const total = this.exportFormat === 'pdf-steps' ? stops.filter((s) => s.pdf !== false).length : new Set(stops.map((s) => s.pageIndex)).size;\n this.showExportOverlay('Exporting PDF...', `0% (0 / ${total} pages)`);\n this.exportPages = { done: 0, total };\n } else this.showExportOverlay();\n try {\n const blob = pdf\n ? await this.movie.exportPDF({\n which: this.exportFormat === 'pdf-steps' ? 'stops' : 'pages',\n quality: PDF_QUALITY[this.exportQuality],\n onImage: () => this.pdfPageDone(),\n })\n : await this.movie.render({\n format: this.exportFormat as 'mp4' | 'webm' | 'mov',\n video: { bitrate: this.exportQuality },\n audio: { bitrate: this.exportQuality },\n });\n if (this.exportFillEl) this.exportFillEl.style.width = '100%';\n if (this.exportTextEl) this.exportTextEl.textContent = 'Preparing download...';\n this.triggerDownload(blob);\n await new Promise((r) => setTimeout(r, 300));\n } catch (err) {\n console.error('Export failed:', err);\n alert('Export failed.');\n } finally {\n this.hideExportOverlay();\n this.isExporting = false;\n if (wasPlaying) {\n void this.startPlaying();\n this.refreshPlayIcon();\n }\n }\n }\n\n private triggerDownload(blob: Blob): void {\n const url = URL.createObjectURL(blob);\n const a = document.createElement('a');\n a.href = url;\n a.download = this.makeFilename(blob);\n a.style.display = 'none';\n document.body.appendChild(a);\n a.click();\n a.remove();\n setTimeout(() => URL.revokeObjectURL(url), 100);\n }\n\n private makeFilename(blob: Blob): string {\n const ext = extensionForMimeType(blob.type);\n const d = new Date();\n const pad = (n: number) => n.toString().padStart(2, '0');\n const ts = `${d.getFullYear()}${pad(d.getMonth() + 1)}${pad(d.getDate())}-${pad(d.getHours())}${pad(d.getMinutes())}${pad(d.getSeconds())}`;\n return `movie-${ts}.${ext}`;\n }\n\n /** One more PDF page is ready: move the bar. */\n private pdfPageDone(): void {\n const p = this.exportPages;\n if (!p || !this.exportFillEl || !this.exportTextEl) return;\n p.done++;\n const percent = p.total ? Math.min(100, Math.round((p.done / p.total) * 100)) : 100;\n this.exportFillEl.style.width = `${percent}%`;\n this.exportTextEl.textContent = `${percent}% (${p.done} / ${p.total} pages)`;\n }\n\n private showExportOverlay(title = 'Exporting video...', text = '0% (0 / 0 frames)'): void {\n const overlay = document.createElement('div');\n overlay.className = 'mc-export-overlay';\n overlay.innerHTML = `\n <div class=\"mc-export-panel\">\n <div class=\"mc-export-title\"></div>\n <div class=\"mc-export-track\"><div class=\"mc-export-fill\"></div></div>\n <div class=\"mc-export-text\"></div>\n </div>\n `;\n overlay.querySelector('.mc-export-title')!.textContent = title;\n overlay.querySelector('.mc-export-text')!.textContent = text;\n this.root.appendChild(overlay);\n this.exportOverlay = overlay;\n this.exportFillEl = overlay.querySelector('.mc-export-fill') as HTMLDivElement;\n this.exportTextEl = overlay.querySelector('.mc-export-text') as HTMLDivElement;\n }\n\n private hideExportOverlay(): void {\n if (this.exportOverlay) {\n this.exportOverlay.remove();\n this.exportOverlay = null;\n this.exportFillEl = null;\n this.exportTextEl = null;\n }\n this.exportPages = null;\n }\n\n private bindVisibility(): void {\n const wrap = this.wrapper;\n this.onWrapPointerMove = () => this.kickIdleTimer();\n this.onWrapMouseLeave = () => {\n if (!this.settingsOpen && !this.isScrubbing && !this.isVolumeScrubbing) this.setVisible(false);\n };\n wrap.addEventListener('pointermove', this.onWrapPointerMove);\n wrap.addEventListener('mouseleave', this.onWrapMouseLeave);\n this.root.addEventListener('pointerenter', () => {\n if (this.hideTimer) { clearTimeout(this.hideTimer); this.hideTimer = null; }\n this.setVisible(true);\n });\n }\n\n private kickIdleTimer(): void {\n this.setVisible(true);\n if (this.hideTimer) { clearTimeout(this.hideTimer); this.hideTimer = null; }\n if (this.settingsOpen) return;\n this.hideTimer = setTimeout(() => {\n if (!this.isScrubbing && !this.isVolumeScrubbing && !this.settingsOpen) this.setVisible(false);\n }, Controller.HIDE_DELAY_MS);\n }\n\n private setVisible(v: boolean): void {\n this.root.setAttribute('data-state', v ? 'visible' : 'hidden');\n }\n\n private syncRootToCanvas(): void {\n const c = this.options.canvas;\n const cr = c.getBoundingClientRect();\n const wr = this.wrapper.getBoundingClientRect();\n this.root.style.left = `${cr.left - wr.left}px`;\n this.root.style.top = `${cr.top - wr.top}px`;\n this.root.style.width = `${cr.width}px`;\n this.root.style.height = `${cr.height}px`;\n }\n\n private bindKeyboard(): void {\n this.keyHandler = (e: KeyboardEvent) => {\n if (this.presenter) return; // a presentation: the Presenter owns the keys\n const target = e.target as HTMLElement | null;\n if (target) {\n const tag = target.tagName;\n if (tag === 'INPUT' || tag === 'TEXTAREA' || tag === 'SELECT') return;\n if (target.isContentEditable || target.getAttribute?.('contenteditable') === 'true') return;\n }\n if (this.isExporting) return;\n\n switch (e.code) {\n case 'Space':\n e.preventDefault();\n this.playBtn.click();\n break;\n case 'ArrowLeft':\n e.preventDefault();\n this.stepFrame(-1);\n break;\n case 'ArrowRight':\n e.preventDefault();\n this.stepFrame(1);\n break;\n case 'ArrowUp':\n e.preventDefault();\n this.adjustVolume(0.05);\n break;\n case 'ArrowDown':\n e.preventDefault();\n this.adjustVolume(-0.05);\n break;\n case 'KeyM':\n e.preventDefault();\n this.muteBtn.click();\n break;\n case 'KeyE':\n if (e.shiftKey && this.exportBtn) {\n e.preventDefault();\n // Power-user shortcut: skip the popover and export with current settings.\n void this.handleExport();\n }\n break;\n case 'KeyF':\n if (this.fullscreenBtn) {\n e.preventDefault();\n void this.toggleFullscreen();\n }\n break;\n }\n };\n document.addEventListener('keydown', this.keyHandler);\n }\n\n private stepFrame(delta: number): void {\n const next = Math.max(0, Math.min(this.movie.totalFrames, this.movie.currentFrame + delta));\n void this.movie.gotoFrame(next);\n }\n\n private adjustVolume(delta: number): void {\n const next = Math.max(0, Math.min(1, this.movie.volume + delta));\n this.movie.volume = next;\n if (this.movie.muted && next > 0) this.movie.muted = false;\n this.refreshVolumeUI();\n }\n\n destroy(): void {\n if (this.destroyed) return;\n this.destroyed = true;\n this.stopPresenting();\n if (this.onReady) { this.movie.off('ready', this.onReady); this.onReady = null; }\n if (this.onFrame) { this.movie.off('frame', this.onFrame); this.onFrame = null; }\n if (this.onPlay) { this.movie.off('play', this.onPlay); this.onPlay = null; }\n if (this.onPause) { this.movie.off('pause', this.onPause); this.onPause = null; }\n if (this.onProgress) { this.movie.off('progress', this.onProgress); this.onProgress = null; }\n if (this.onWrapPointerMove) {\n this.wrapper.removeEventListener('pointermove', this.onWrapPointerMove);\n this.onWrapPointerMove = null;\n }\n if (this.onWrapMouseLeave) {\n this.wrapper.removeEventListener('mouseleave', this.onWrapMouseLeave);\n this.onWrapMouseLeave = null;\n }\n if (this.resizeObserver) {\n this.resizeObserver.disconnect();\n this.resizeObserver = null;\n }\n if (this.canvasClickHandler) {\n this.options.canvas.removeEventListener('click', this.canvasClickHandler);\n this.options.canvas.removeEventListener('pointerdown', this.canvasPointerDownHandler!);\n this.options.canvas.style.cursor = this.canvasCursor;\n this.canvasClickHandler = null; this.canvasPointerDownHandler = null;\n }\n if (this.fitObserver) { this.fitObserver.disconnect(); this.fitObserver = null; }\n if (this.fitWrapHandler) { window.removeEventListener('resize', this.fitWrapHandler); this.fitWrapHandler = null; }\n if (this.wrappedHere) { // give the canvas its own sizing back\n this.options.canvas.style.width = this.canvasInlineWidth;\n this.options.canvas.style.height = this.canvasInlineHeight;\n }\n this.root.remove();\n if (this.wrappedHere) {\n const parent = this.wrapper.parentElement;\n const canvas = this.options.canvas;\n if (parent) {\n parent.insertBefore(canvas, this.wrapper);\n this.wrapper.remove();\n }\n } else {\n this.wrapper.removeAttribute('data-mc-wrap');\n }\n if (this.keyHandler) {\n document.removeEventListener('keydown', this.keyHandler);\n this.keyHandler = null;\n }\n if (this.settingsKeyHandler) {\n document.removeEventListener('keydown', this.settingsKeyHandler);\n this.settingsKeyHandler = null;\n }\n if (this.settingsOutsideHandler) {\n document.removeEventListener('pointerdown', this.settingsOutsideHandler);\n this.settingsOutsideHandler = null;\n }\n if (this.fullscreenChangeHandler) {\n document.removeEventListener('fullscreenchange', this.fullscreenChangeHandler);\n this.fullscreenChangeHandler = null;\n }\n if (this.windowBlurHandler) {\n window.removeEventListener('blur', this.windowBlurHandler);\n this.windowBlurHandler = null;\n }\n if (this.wheelHandler && this.volumeContainerEl) {\n this.volumeContainerEl.removeEventListener('wheel', this.wheelHandler);\n this.wheelHandler = null;\n }\n if (document.fullscreenElement === this.wrapper) {\n void document.exitFullscreen().catch(() => {});\n }\n if (this.hideTimer) { clearTimeout(this.hideTimer); this.hideTimer = null; }\n this.hideExportOverlay();\n uninstallStyles();\n }\n}\n"]}
1
+ {"version":3,"sources":["../src/Controller.ts"],"names":[],"mappings":"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","file":"Controller.js","sourcesContent":["import type { Movie } from './core/Movie';\nimport { warnUnknownOptions } from './core/options';\n\nconst ICONS = {\n play: '<svg viewBox=\"0 0 16 16\" width=\"16\" height=\"16\" fill=\"currentColor\"><path d=\"M3 2 L13 8 L3 14 Z\"/></svg>',\n 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>',\n 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>',\n 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>',\n 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>',\n 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>',\n 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>',\n 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>',\n} as const;\n\nconst STYLE_ATTR = 'data-movie-controller';\n\n/** The bar's default stylesheet. Its colours and sizes are CSS custom properties (`--mc-accent`, `--mc-fg`, `--mc-track`, `--mc-bar-bg`, `--mc-track-height`, `--mc-font`): set them in your page CSS, or with the `theme` option. */\nexport const CONTROLLER_CSS = `\n.movie-controller-wrap { position: relative; display: inline-block; line-height: 0; }\n.movie-controller {\n position: absolute;\n pointer-events: none;\n font-family: var(--mc-font, -apple-system, BlinkMacSystemFont, \"Segoe UI\", Roboto, sans-serif);\n display: flex;\n flex-direction: column;\n justify-content: flex-end;\n opacity: 1;\n transition: opacity 200ms ease;\n}\n.movie-controller[data-state=\"hidden\"] { opacity: 0; }\n.movie-controller > * { pointer-events: auto; }\n\n.mc-progress {\n position: relative;\n width: 100%;\n height: 16px;\n cursor: pointer;\n display: flex;\n align-items: center;\n outline: none;\n}\n.mc-progress:focus-visible {\n outline: 2px solid var(--mc-accent, #007AFF);\n outline-offset: 2px;\n}\n.mc-progress::before {\n content: \"\"; position: absolute; left: 12px; right: 12px;\n height: var(--mc-track-height, 3px); background: var(--mc-track, rgba(255,255,255,0.25));\n transition: height 120ms ease;\n}\n.mc-progress:hover::before, .mc-progress.mc-scrubbing::before { height: calc(var(--mc-track-height, 3px) + 2px); }\n.mc-stops { position: absolute; left: 12px; right: 12px; top: 0; bottom: 0; pointer-events: none; }\n.mc-stop-tick { position: absolute; top: 50%; width: 7px; height: 7px; transform: translate(-50%, -50%); border-radius: 50%; background: var(--mc-fg, #fff); box-shadow: 0 0 0 1.5px rgba(0,0,0,0.5); }\n.mc-stop-page { width: 11px; height: 11px; box-shadow: 0 0 0 2.5px var(--mc-accent, #007AFF), 0 0 0 4px rgba(0,0,0,0.35); }\n.mc-progress-fill {\n position: absolute; left: 12px; top: 50%;\n height: var(--mc-track-height, 3px);\n width: calc((100% - 24px) * var(--mc-fill, 0));\n background: var(--mc-accent, #007AFF);\n transform: translateY(-50%);\n transition: height 120ms ease;\n pointer-events: none;\n}\n.mc-progress:hover .mc-progress-fill,\n.mc-progress.mc-scrubbing .mc-progress-fill { height: calc(var(--mc-track-height, 3px) + 2px); }\n.mc-progress-thumb {\n position: absolute; top: 50%;\n left: calc(12px + (100% - 24px) * var(--mc-fill, 0));\n width: 12px; height: 12px; border-radius: 50%;\n background: var(--mc-accent, #007AFF);\n transform: translate(-50%, -50%) scale(0);\n transition: transform 120ms ease;\n pointer-events: none;\n}\n.mc-progress:hover .mc-progress-thumb,\n.mc-progress.mc-scrubbing .mc-progress-thumb { transform: translate(-50%, -50%) scale(1); }\n\n.mc-bar {\n position: relative;\n display: flex;\n align-items: center;\n gap: 12px;\n padding: 6px 12px 8px 12px;\n background: var(--mc-bar-bg, linear-gradient(to top, rgba(0,0,0,0.75) 0%, rgba(0,0,0,0) 100%));\n color: var(--mc-fg, #fff);\n line-height: 1;\n}\n.mc-btn {\n background: none; border: 0; padding: 0; margin: 0;\n width: 28px; height: 28px;\n display: inline-flex; align-items: center; justify-content: center;\n color: var(--mc-fg, #fff); opacity: 0.85; cursor: pointer;\n transition: opacity 120ms ease;\n}\n.mc-btn:hover { opacity: 1; }\n.mc-btn:disabled { opacity: 0.4; cursor: not-allowed; }\n.mc-time {\n font-size: 12px; font-family: Menlo, Monaco, monospace;\n color: var(--mc-fg, #fff); opacity: 0.85;\n min-width: 90px;\n}\n.mc-spacer { flex: 1; }\n\n.mc-volume { display: flex; align-items: center; }\n.mc-vol-slider {\n position: relative;\n width: 0;\n height: 28px;\n display: flex;\n align-items: center;\n cursor: pointer;\n margin-left: 0;\n outline: none;\n transition: width 200ms ease, margin-left 200ms ease;\n overflow: hidden;\n}\n.mc-volume:hover .mc-vol-slider,\n.mc-volume:focus-within .mc-vol-slider,\n.mc-vol-slider.mc-scrubbing {\n width: 70px;\n margin-left: 6px;\n}\n.mc-vol-slider:focus-visible { outline: 2px solid var(--mc-accent, #007AFF); outline-offset: 2px; }\n.mc-vol-slider::before {\n content: \"\"; position: absolute; left: 4px; right: 4px;\n height: 3px; background: var(--mc-track, rgba(255,255,255,0.25)); border-radius: 2px;\n}\n.mc-vol-fill {\n position: absolute; left: 4px; top: 50%;\n height: 3px;\n width: calc((100% - 8px) * var(--mc-volume, 1));\n background: var(--mc-fg, #fff);\n transform: translateY(-50%);\n border-radius: 2px;\n pointer-events: none;\n}\n.mc-vol-thumb {\n position: absolute; top: 50%;\n left: calc(4px + (100% - 8px) * var(--mc-volume, 1));\n width: 10px; height: 10px; border-radius: 50%;\n background: var(--mc-fg, #fff);\n transform: translate(-50%, -50%);\n pointer-events: none;\n}\n\n[data-mc-wrap]:fullscreen {\n width: 100vw; height: 100vh;\n display: flex; align-items: center; justify-content: center;\n background: #000;\n}\n[data-mc-wrap]:fullscreen > canvas {\n width: 100% !important;\n height: 100% !important;\n max-width: none !important;\n max-height: none !important;\n object-fit: contain;\n border-radius: 0;\n}\n\n.mc-settings-popover {\n position: absolute;\n bottom: calc(100% + 8px);\n right: 12px;\n background: rgba(20, 20, 20, 0.96);\n border-radius: 8px;\n padding: 10px 12px;\n min-width: 180px;\n color: #fff;\n font-size: 12px;\n box-shadow: 0 4px 16px rgba(0,0,0,0.4);\n display: flex;\n flex-direction: column;\n gap: 8px;\n}\n.mc-settings-popover[data-open=\"false\"] { display: none; }\n.mc-settings-row {\n display: flex;\n align-items: center;\n justify-content: space-between;\n gap: 12px;\n}\n.mc-settings-row > span { color: rgba(255,255,255,0.85); }\n.mc-settings-row > select {\n font: inherit;\n background: rgba(255,255,255,0.1);\n color: #fff;\n border: 1px solid rgba(255,255,255,0.18);\n border-radius: 4px;\n padding: 2px 6px;\n cursor: pointer;\n}\n.mc-export-confirm {\n margin-top: 4px;\n width: 100%;\n background: var(--mc-accent, #007AFF);\n color: #fff;\n border: 0;\n border-radius: 4px;\n padding: 6px 10px;\n font: inherit;\n font-weight: 600;\n cursor: pointer;\n transition: background 120ms ease;\n}\n.mc-export-confirm:hover { background: #0066d6; }\n.mc-export-confirm:disabled { background: rgba(255,255,255,0.18); cursor: not-allowed; }\n\n.mc-export-overlay {\n position: absolute; inset: 0;\n background: rgba(0,0,0,0.7);\n display: flex; justify-content: center; align-items: center;\n z-index: 2;\n}\n.mc-export-panel {\n background: rgba(20,20,20,0.96); color: #fff;\n border-radius: 8px; padding: 16px 20px;\n text-align: center; min-width: 200px; max-width: 80%;\n font-family: -apple-system, BlinkMacSystemFont, \"Segoe UI\", Roboto, sans-serif;\n}\n.mc-export-title { font-size: 13px; margin-bottom: 10px; opacity: 0.9; }\n.mc-export-track {\n width: 100%; height: 6px;\n background: rgba(255,255,255,0.15); border-radius: 3px;\n margin-bottom: 8px; overflow: hidden;\n}\n.mc-export-fill {\n height: 100%; width: 0%;\n background: linear-gradient(90deg, var(--mc-accent, #007AFF), var(--mc-accent, #0056CC));\n transition: width 0.3s ease; border-radius: 3px;\n}\n.mc-export-text {\n color: rgba(255,255,255,0.7); font-size: 11px;\n font-family: Menlo, Monaco, monospace;\n}\n`;\n\nlet styleRefCount = 0;\n\nfunction installStyles(): void {\n if (styleRefCount === 0) {\n const el = document.createElement('style');\n el.setAttribute(STYLE_ATTR, '');\n el.textContent = CONTROLLER_CSS;\n document.head.appendChild(el);\n }\n styleRefCount++;\n}\n\nfunction uninstallStyles(): void {\n styleRefCount = Math.max(0, styleRefCount - 1);\n if (styleRefCount === 0) {\n document.head.querySelectorAll(`style[${STYLE_ATTR}]`).forEach((n) => n.remove());\n }\n}\n\nexport function formatTime(seconds: number): string {\n const s = Math.max(0, Math.floor(seconds));\n const m = Math.floor(s / 60);\n const r = s % 60;\n return `${m}:${r.toString().padStart(2, '0')}`;\n}\n\nexport function frameToPercent(frame: number, totalFrames: number): number {\n if (totalFrames <= 0) return 0;\n const f = Math.min(Math.max(frame, 0), totalFrames);\n return (f / totalFrames) * 100;\n}\n\nexport function pxToFrame(clientX: number, rect: { left: number; width: number }, totalFrames: number): number {\n if (rect.width <= 0 || totalFrames <= 0) return 0;\n const ratio = (clientX - rect.left) / rect.width;\n const clamped = Math.min(Math.max(ratio, 0), 1);\n return Math.round(clamped * totalFrames);\n}\n\nexport function pxToFraction(clientX: number, rect: { left: number; width: number }, inset = 0): number {\n const innerLeft = rect.left + inset;\n const innerWidth = Math.max(0, rect.width - 2 * inset);\n if (innerWidth <= 0) return 0;\n const ratio = (clientX - innerLeft) / innerWidth;\n return Math.min(Math.max(ratio, 0), 1);\n}\n\n/** The JPEG quality of a PDF page for each quality choice of the panel. */\nconst PDF_QUALITY = { 'low': 0.6, 'medium': 0.75, 'high': 0.88, 'very-high': 0.95 } as const;\n\nexport function extensionForMimeType(mime: string): string {\n const t = (mime || '').toLowerCase();\n if (t.includes('pdf')) return 'pdf';\n if (t.includes('webm')) return 'webm';\n if (t.includes('quicktime') || t.includes('mov')) return 'mov';\n if (t.includes('matroska') || t.includes('mkv')) return 'mkv';\n return 'mp4';\n}\n\n/**\n * The look of the bar. Each key sets a CSS custom property on the bar (so you can also set `--mc-accent` … in your own CSS, on the\n * canvas's parent or on `:root`). `null` puts a value back to the default.\n */\nexport interface ControllerTheme {\n /** The colour of the progress bar, its thumb and the focus rings. Default `#007AFF` (blue). */\n accent?: string | null;\n /** Icons, the time and the volume slider. Default `#fff`. */\n foreground?: string | null;\n /** The unfilled part of the progress and volume bars. Default `rgba(255,255,255,0.25)`. */\n track?: string | null;\n /** The background behind the buttons: any CSS background, e.g. a gradient. Default: black fading to transparent upward. */\n barBackground?: string | null;\n /** Thickness of the progress bar in px (a number) or any CSS length. Default 3. */\n trackHeight?: number | string | null;\n /** `font-family` of the bar. */\n font?: string | null;\n}\n\nconst THEME_PROPERTIES: Record<keyof ControllerTheme, string> = {\n accent: '--mc-accent', foreground: '--mc-fg', track: '--mc-track', barBackground: '--mc-bar-bg', trackHeight: '--mc-track-height', font: '--mc-font',\n};\n\nexport interface ControllerOptions {\n canvas: HTMLCanvasElement;\n /** Colours and sizes of the bar, see {@link ControllerTheme}. Can be changed later with `controller.setTheme()`. */\n theme?: ControllerTheme;\n showExportButton?: boolean;\n enableKeyboardShortcuts?: boolean;\n /** A click (or tap) on the picture plays / pauses, like a `<video>` element. Default true; `false` leaves the canvas alone. */\n clickToPlay?: boolean;\n /** A movie with `stops` gets a Present button that starts a {@link Presenter} (keys, click and swipe move through the stops). Default true; `false` keeps only the marks on the seek bar. */\n present?: boolean;\n /** A movie with `stops`: the play button (and a click on the picture, and Space) plays to the next stop and pauses there, like a slide. Default true; `false` plays straight through to the end. */\n pauseAtStops?: boolean;\n className?: string;\n}\n\ninterface ResolvedOptions {\n canvas: HTMLCanvasElement;\n showExportButton: boolean;\n enableKeyboardShortcuts: boolean;\n clickToPlay: boolean;\n present: boolean;\n pauseAtStops: boolean;\n className: string;\n}\n\nexport class Controller {\n movie: Movie;\n options: ResolvedOptions;\n\n private root: HTMLDivElement;\n private wrapper: HTMLDivElement;\n private wrappedHere = false;\n /** The canvas's own inline width / height, as the page wrote them (we override them while the wrapper is fitted). */\n private canvasInlineWidth = '';\n private canvasInlineHeight = '';\n private fitWrapHandler: (() => void) | null = null;\n private fitObserver: ResizeObserver | null = null;\n private destroyed = false;\n\n private progressEl!: HTMLDivElement;\n private progressFillEl!: HTMLDivElement;\n private progressThumbEl!: HTMLDivElement;\n private playBtn!: HTMLButtonElement;\n private muteBtn!: HTMLButtonElement;\n private timeEl!: HTMLSpanElement;\n private exportBtn: HTMLButtonElement | null = null;\n private settingsPopoverEl: HTMLDivElement | null = null;\n private settingsFormatSelect: HTMLSelectElement | null = null;\n private settingsQualitySelect: HTMLSelectElement | null = null;\n private exportConfirmBtn: HTMLButtonElement | null = null;\n private exportFormat: 'mp4' | 'webm' | 'mov' | 'pdf' | 'pdf-steps' = 'mp4';\n private exportQuality: 'low' | 'medium' | 'high' | 'very-high' = 'high';\n private settingsOpen = false;\n private hideTimer: ReturnType<typeof setTimeout> | null = null;\n private static readonly HIDE_DELAY_MS = 2500;\n private static readonly PROGRESS_INSET_PX = 12;\n private isScrubbing = false;\n private wasPlayingBeforeScrub = false;\n private activePointerId: number | null = null;\n private isExporting = false;\n private exportPages: { done: number; total: number } | null = null;\n private exportOverlay: HTMLDivElement | null = null;\n private exportFillEl: HTMLDivElement | null = null;\n private exportTextEl: HTMLDivElement | null = null;\n private keyHandler: ((e: KeyboardEvent) => void) | null = null;\n private settingsKeyHandler: ((e: KeyboardEvent) => void) | null = null;\n private settingsOutsideHandler: ((e: PointerEvent) => void) | null = null;\n private onReady: (() => void) | null = null;\n private presenter: { destroy(): void } | null = null;\n private presentBtn: HTMLButtonElement | null = null;\n private onFrame: ((e: { frame: number; totalFrames: number }) => void) | null = null;\n private onPlay: (() => void) | null = null;\n private onPause: (() => void) | null = null;\n private onProgress: ((e: { progress: number; frame: number; totalFrames: number }) => void) | null = null;\n private onWrapPointerMove: (() => void) | null = null;\n private onWrapMouseLeave: (() => void) | null = null;\n private resizeObserver: ResizeObserver | null = null;\n private volumeSliderEl: HTMLDivElement | null = null;\n private volumeContainerEl: HTMLDivElement | null = null;\n private fullscreenBtn: HTMLButtonElement | null = null;\n private isVolumeScrubbing = false;\n private canvasClickHandler: (() => void) | null = null;\n private canvasPointerDownHandler: (() => void) | null = null;\n private canvasCursor = '';\n /** Set when a pointerdown on the canvas closed the export popover: the click that follows must not play / pause. */\n private swallowCanvasClick = false;\n private fullscreenChangeHandler: (() => void) | null = null;\n private wheelHandler: ((e: WheelEvent) => void) | null = null;\n /** Ends a drag the pointerup of which never arrives (see bindScrubbing). */\n private windowBlurHandler: (() => void) | null = null;\n\n constructor(movie: Movie, options: ControllerOptions) {\n if (!options || !options.canvas) {\n throw new Error('Controller requires options.canvas (HTMLCanvasElement).');\n }\n this.movie = movie;\n this.options = {\n canvas: options.canvas,\n showExportButton: options.showExportButton ?? true,\n enableKeyboardShortcuts: options.enableKeyboardShortcuts ?? true,\n clickToPlay: options.clickToPlay ?? true,\n present: options.present ?? true,\n pauseAtStops: options.pauseAtStops ?? true,\n className: options.className ?? 'movie-controller',\n };\n\n installStyles();\n this.wrapper = this.ensurePositioningContext(this.options.canvas);\n this.root = document.createElement('div');\n this.root.className = this.options.className;\n this.wrapper.appendChild(this.root);\n this.buildBar();\n this.setTheme(options.theme ?? {});\n this.bindFitWrap();\n this.syncRootToCanvas();\n if (typeof ResizeObserver !== 'undefined') {\n this.resizeObserver = new ResizeObserver(() => this.syncRootToCanvas());\n this.resizeObserver.observe(this.options.canvas);\n // Also observe the wrapper: when its size changes (browser resize, sibling\n // panels resizing) the canvas's position can shift without its own size\n // changing, which canvas-only observation would miss.\n this.resizeObserver.observe(this.wrapper);\n }\n this.root.setAttribute('data-state', 'visible');\n this.bindMovieEvents();\n this.refreshStops();\n this.bindPlayButton();\n if (this.options.clickToPlay) this.bindCanvasClick();\n this.bindScrubbing();\n this.bindMuteButton();\n this.bindVolumeSlider();\n this.bindExportPopover();\n this.bindFullscreen();\n this.bindVisibility();\n if (this.options.enableKeyboardShortcuts) this.bindKeyboard();\n }\n\n private buildBar(): void {\n const popoverHtml = this.options.showExportButton ? `\n <div class=\"mc-settings-popover\" role=\"dialog\" aria-label=\"Export settings\" data-open=\"false\">\n <label class=\"mc-settings-row\">\n <span>Format</span>\n <select class=\"mc-settings-format\">\n <option value=\"mp4\">MP4</option>\n <option value=\"webm\">WebM</option>\n <option value=\"mov\">MOV</option>\n </select>\n </label>\n <label class=\"mc-settings-row\">\n <span>Quality</span>\n <select class=\"mc-settings-quality\">\n <option value=\"low\">Low</option>\n <option value=\"medium\">Medium</option>\n <option value=\"high\" selected>High</option>\n <option value=\"very-high\">Very High</option>\n </select>\n </label>\n <button type=\"button\" class=\"mc-export-confirm\">Download</button>\n </div>\n ` : '';\n this.root.innerHTML = `\n <div class=\"mc-progress\" role=\"slider\" tabindex=\"0\" aria-label=\"Seek\" aria-valuemin=\"0\" aria-valuemax=\"${this.movie.totalFrames}\" aria-valuenow=\"0\">\n <div class=\"mc-progress-fill\"></div>\n <div class=\"mc-progress-thumb\"></div>\n </div>\n <div class=\"mc-bar\">\n ${popoverHtml}\n <button class=\"mc-btn mc-play\" aria-label=\"Play\">${ICONS.play}</button>\n <div class=\"mc-volume\">\n <button class=\"mc-btn mc-mute\" aria-label=\"Mute\">${ICONS.volumeOn}</button>\n <div class=\"mc-vol-slider\" role=\"slider\" tabindex=\"0\" aria-label=\"Volume\" aria-valuemin=\"0\" aria-valuemax=\"100\" aria-valuenow=\"100\">\n <div class=\"mc-vol-fill\"></div>\n <div class=\"mc-vol-thumb\"></div>\n </div>\n </div>\n <span class=\"mc-time\">0:00 / 0:00</span>\n <div class=\"mc-spacer\"></div>\n ${this.options.showExportButton ? `<button class=\"mc-btn mc-export\" aria-label=\"Export\" aria-expanded=\"false\">${ICONS.download}</button>` : ''}\n <button class=\"mc-btn mc-fullscreen\" aria-label=\"Enter fullscreen\">${ICONS.fullscreenEnter}</button>\n </div>\n `;\n this.progressEl = this.root.querySelector('.mc-progress') as HTMLDivElement;\n this.progressFillEl = this.root.querySelector('.mc-progress-fill') as HTMLDivElement;\n this.progressThumbEl = this.root.querySelector('.mc-progress-thumb') as HTMLDivElement;\n this.playBtn = this.root.querySelector('.mc-play') as HTMLButtonElement;\n this.muteBtn = this.root.querySelector('.mc-mute') as HTMLButtonElement;\n this.timeEl = this.root.querySelector('.mc-time') as HTMLSpanElement;\n this.exportBtn = this.root.querySelector('.mc-export') as HTMLButtonElement | null;\n this.settingsPopoverEl = this.root.querySelector('.mc-settings-popover') as HTMLDivElement | null;\n this.settingsFormatSelect = this.root.querySelector('.mc-settings-format') as HTMLSelectElement | null;\n this.settingsQualitySelect = this.root.querySelector('.mc-settings-quality') as HTMLSelectElement | null;\n this.exportConfirmBtn = this.root.querySelector('.mc-export-confirm') as HTMLButtonElement | null;\n this.volumeSliderEl = this.root.querySelector('.mc-vol-slider') as HTMLDivElement | null;\n this.volumeContainerEl = this.root.querySelector('.mc-volume') as HTMLDivElement | null;\n this.fullscreenBtn = this.root.querySelector('.mc-fullscreen') as HTMLButtonElement | null;\n if (this.settingsFormatSelect) this.settingsFormatSelect.value = this.exportFormat;\n if (this.settingsQualitySelect) this.settingsQualitySelect.value = this.exportQuality;\n }\n\n /** Change the look of the bar (see {@link ControllerTheme}): only the keys you give change, `null` restores the default. */\n setTheme(theme: ControllerTheme): void {\n warnUnknownOptions('Controller theme', theme as Record<string, unknown>, Object.keys(THEME_PROPERTIES));\n for (const key of Object.keys(THEME_PROPERTIES) as Array<keyof ControllerTheme>) {\n if (!(key in theme)) continue;\n const value = theme[key];\n const prop = THEME_PROPERTIES[key];\n if (value === null || value === undefined || value === '') this.root.style.removeProperty(prop);\n else this.root.style.setProperty(prop, typeof value === 'number' ? `${value}px` : String(value));\n }\n }\n\n private ensurePositioningContext(canvas: HTMLCanvasElement): HTMLDivElement {\n const parent = canvas.parentElement;\n if (!parent) {\n throw new Error('Controller: canvas must be attached to the DOM before constructing.');\n }\n const pos = getComputedStyle(parent).position;\n if (pos === 'relative' || pos === 'absolute' || pos === 'fixed' || pos === 'sticky') {\n // Tag the user's element so the [data-mc-wrap]:fullscreen style hooks apply\n // to it the same way they apply to our auto-wrap. Cleaned up on destroy.\n parent.setAttribute('data-mc-wrap', '');\n return parent as HTMLDivElement;\n }\n const wrap = document.createElement('div');\n wrap.className = 'movie-controller-wrap';\n wrap.setAttribute('data-mc-wrap', '');\n wrap.style.position = 'relative';\n wrap.style.display = 'inline-block';\n wrap.style.lineHeight = '0';\n parent.insertBefore(wrap, canvas);\n wrap.appendChild(canvas);\n this.wrappedHere = true;\n this.canvasInlineWidth = canvas.style.width;\n this.canvasInlineHeight = canvas.style.height;\n\n return wrap;\n }\n\n /**\n * Make the wrapper exactly as wide as the canvas. A shrink-to-fit wrapper around a canvas that is sized in percent (the usual\n * `canvas { width: min(960px, 100%) }`) is as wide as the canvas's width ATTRIBUTE (1280), so the picture sat at its left edge\n * with an empty strip beside it. We measure the canvas as the page styled it (the wrapper made transparent to layout), give\n * the wrapper that width, and let the canvas fill the wrapper. Re-measured when the window or the page's box changes.\n */\n private fitWrap(): void {\n if (!this.wrappedHere) return;\n const wrap = this.wrapper, canvas = this.options.canvas;\n if (document.fullscreenElement === wrap) { // the fullscreen CSS owns the size\n wrap.style.width = '';\n canvas.style.width = this.canvasInlineWidth; canvas.style.height = this.canvasInlineHeight;\n return;\n }\n canvas.style.width = this.canvasInlineWidth; canvas.style.height = this.canvasInlineHeight;\n const display = wrap.style.display;\n wrap.style.display = 'contents'; wrap.style.width = '';\n const w = canvas.getBoundingClientRect().width;\n wrap.style.display = display;\n if (!(w > 0)) return;\n wrap.style.width = `${w}px`;\n canvas.style.width = '100%'; canvas.style.height = 'auto';\n }\n\n private bindFitWrap(): void {\n if (!this.wrappedHere) return;\n this.fitWrap();\n let queued = false;\n this.fitWrapHandler = () => {\n if (queued) return;\n queued = true;\n requestAnimationFrame(() => { queued = false; this.fitWrap(); });\n };\n window.addEventListener('resize', this.fitWrapHandler);\n const parent = this.wrapper.parentElement;\n if (parent && typeof ResizeObserver !== 'undefined') {\n this.fitObserver = new ResizeObserver(this.fitWrapHandler);\n this.fitObserver.observe(parent);\n }\n }\n\n private bindMovieEvents(): void {\n this.onReady = () => {\n this.progressEl.setAttribute('aria-valuemax', String(this.movie.totalFrames));\n this.refreshTime(0);\n this.refreshProgress(0);\n this.refreshVolumeUI();\n this.refreshStops();\n };\n this.onFrame = ({ frame, totalFrames }) => {\n if (!this.isScrubbing) {\n this.refreshProgress(frame, totalFrames);\n }\n this.refreshTime(frame);\n };\n // `movie.play()` may be called by the host page, not only by this bar's button.\n this.onPlay = () => {\n this.refreshPlayIcon();\n this.kickIdleTimer();\n };\n this.onPause = () => {\n this.refreshPlayIcon();\n // YouTube-style: pause shows the bar momentarily, then auto-hides on idle.\n this.kickIdleTimer();\n };\n this.onProgress = ({ progress, frame, totalFrames }) => {\n if (!this.isExporting || !this.exportFillEl || !this.exportTextEl) return;\n this.exportFillEl.style.width = `${progress}%`;\n this.exportTextEl.textContent = `${progress}% (${frame} / ${totalFrames} frames)`;\n };\n this.movie.on('ready', this.onReady);\n this.movie.on('frame', this.onFrame);\n this.movie.on('play', this.onPlay);\n this.movie.on('pause', this.onPause);\n this.movie.on('progress', this.onProgress);\n }\n\n /** The stops of a presentation as marks on the seek bar, and the Present button. */\n private refreshStops(): void {\n this.progressEl.querySelector('.mc-stops')?.remove();\n const stops = this.movie.stops ?? [];\n this.refreshPdfChoices(stops.length > 0);\n if (stops.length === 0) {\n this.presentBtn?.remove(); this.presentBtn = null;\n return;\n }\n const total = this.movie.totalFrames || 1;\n const holder = document.createElement('div');\n holder.className = 'mc-stops';\n for (const s of stops) {\n const tick = document.createElement('div');\n tick.className = s.pageStart ? 'mc-stop-tick mc-stop-page' : 'mc-stop-tick';\n tick.style.left = `${(s.frame / total) * 100}%`;\n if (s.page) tick.title = s.page;\n holder.appendChild(tick);\n }\n this.progressEl.appendChild(holder);\n if (this.options.present && !this.presentBtn && this.fullscreenBtn) {\n const btn = document.createElement('button');\n btn.className = 'mc-btn mc-present';\n btn.setAttribute('aria-label', 'Present');\n btn.title = 'Present';\n btn.innerHTML = ICONS.present;\n btn.addEventListener('click', () => { void this.startPresenting(); });\n this.fullscreenBtn.parentElement?.insertBefore(btn, this.fullscreenBtn);\n this.presentBtn = btn;\n }\n }\n\n /** A deck can be downloaded as a PDF: the format list gets \"PDF\" choices while the movie has stops. */\n private refreshPdfChoices(has: boolean): void {\n const select = this.settingsFormatSelect;\n if (!select) return;\n const present = !!select.querySelector('option[value=\"pdf\"]');\n if (has && !present) {\n for (const [value, label] of [['pdf', 'PDF (pages)'], ['pdf-steps', 'PDF (every step)']] as const) {\n const o = document.createElement('option');\n o.value = value; o.textContent = label;\n select.appendChild(o);\n }\n } else if (!has && present) {\n select.querySelectorAll('option[value=\"pdf\"], option[value=\"pdf-steps\"]').forEach((o) => o.remove());\n if (this.exportFormat === 'pdf' || this.exportFormat === 'pdf-steps') { this.exportFormat = 'mp4'; select.value = 'mp4'; }\n }\n }\n\n /** Play, or pause: a movie with stops plays to the next stop (and from the end, again from the start). */\n private async togglePlay(): Promise<void> {\n if (this.movie.isPlaying) { this.movie.pause(); return; }\n await this.startPlaying();\n }\n\n /** Start playing: to the next stop for a movie with stops, to the end for any other (or with `pauseAtStops: false`). */\n private async startPlaying(): Promise<void> {\n if (this.options.pauseAtStops && (this.movie.stops?.length ?? 0) > 0) {\n if (this.movie.currentFrame >= this.movie.totalFrames) await this.movie.gotoFrame(0, true);\n await this.movie.next();\n } else this.movie.play();\n }\n\n /** Hand the page over to a Presenter (fullscreen, keys, click and swipe move through the stops); Escape gives it back. */\n private async startPresenting(): Promise<void> {\n if (this.presenter || this.destroyed) return;\n const { Presenter } = await import('./Presenter');\n if (this.presenter || this.destroyed) return;\n const p = new Presenter(this.movie, { canvas: this.options.canvas, onExit: () => this.stopPresenting() });\n this.presenter = p;\n await p.start();\n }\n\n private stopPresenting(): void {\n const p = this.presenter;\n this.presenter = null;\n p?.destroy();\n }\n\n private bindPlayButton(): void {\n // pause / play emit 'pause' / 'play' events, which the handlers turn into refreshPlayIcon + kickIdleTimer\n this.playBtn.addEventListener('click', () => { void this.togglePlay(); });\n }\n\n /** Clicking the picture plays / pauses (a tap on a phone too). */\n private bindCanvasClick(): void {\n const canvas = this.options.canvas;\n this.canvasCursor = canvas.style.cursor;\n canvas.style.cursor = 'pointer';\n this.canvasPointerDownHandler = () => { this.swallowCanvasClick = false; };\n this.canvasClickHandler = () => {\n if (this.presenter) return; // a presentation: the Presenter owns clicks\n // the tap that closed the export popover (see bindExportPopover) is not also a play / pause\n if (this.swallowCanvasClick) { this.swallowCanvasClick = false; return; }\n void this.togglePlay();\n };\n canvas.addEventListener('pointerdown', this.canvasPointerDownHandler);\n canvas.addEventListener('click', this.canvasClickHandler);\n }\n\n private refreshPlayIcon(): void {\n this.playBtn.innerHTML = this.movie.isPlaying ? ICONS.pause : ICONS.play;\n this.playBtn.setAttribute('aria-label', this.movie.isPlaying ? 'Pause' : 'Play');\n }\n\n private bindMuteButton(): void {\n this.muteBtn.addEventListener('click', () => {\n this.movie.toggleMute();\n this.refreshVolumeUI();\n });\n }\n\n private refreshMuteIcon(): void {\n const silent = this.movie.muted || this.movie.volume <= 0;\n this.muteBtn.innerHTML = silent ? ICONS.volumeOff : ICONS.volumeOn;\n this.muteBtn.setAttribute('aria-label', silent ? 'Unmute' : 'Mute');\n }\n\n private refreshVolumeUI(): void {\n this.refreshMuteIcon();\n if (!this.volumeSliderEl) return;\n const effective = this.movie.muted ? 0 : this.movie.volume;\n this.volumeSliderEl.style.setProperty('--mc-volume', String(effective));\n this.volumeSliderEl.setAttribute('aria-valuenow', String(Math.round(effective * 100)));\n }\n\n private bindVolumeSlider(): void {\n if (!this.volumeSliderEl || !this.volumeContainerEl) return;\n const slider = this.volumeSliderEl;\n const container = this.volumeContainerEl;\n\n const setFromPointer = (clientX: number) => {\n const rect = slider.getBoundingClientRect();\n const v = pxToFraction(clientX, { left: rect.left, width: rect.width }, 4);\n this.movie.volume = v;\n if (this.movie.muted && v > 0) this.movie.muted = false;\n this.refreshVolumeUI();\n };\n\n const onDown = (e: PointerEvent) => {\n this.isVolumeScrubbing = true;\n slider.classList.add('mc-scrubbing');\n try { slider.setPointerCapture(e.pointerId); } catch { /* unsupported */ }\n setFromPointer(e.clientX);\n };\n const finish = (pointerId?: number) => {\n if (!this.isVolumeScrubbing) return;\n this.isVolumeScrubbing = false;\n slider.classList.remove('mc-scrubbing');\n try { if (pointerId !== undefined) slider.releasePointerCapture(pointerId); } catch { /* unsupported */ }\n };\n const onMove = (e: PointerEvent) => {\n if (!this.isVolumeScrubbing) return;\n if (e.buttons === 0) { finish(e.pointerId); return; } // released outside an iframe: see bindScrubbing\n setFromPointer(e.clientX);\n };\n const onUp = (e: PointerEvent) => finish(e.pointerId);\n slider.addEventListener('pointerdown', onDown);\n slider.addEventListener('pointermove', onMove);\n slider.addEventListener('pointerup', onUp);\n slider.addEventListener('pointercancel', onUp);\n slider.addEventListener('lostpointercapture', () => finish());\n\n this.wheelHandler = (e: WheelEvent) => {\n e.preventDefault();\n this.adjustVolume(e.deltaY < 0 ? 0.05 : -0.05);\n };\n container.addEventListener('wheel', this.wheelHandler, { passive: false });\n }\n\n /**\n * Does this browser have the Fullscreen API for an element? iPhone Safari does not (it can only put a <video> in fullscreen),\n * and a button that does nothing is worse than none.\n */\n private supportsFullscreen(): boolean {\n return typeof (this.wrapper as { requestFullscreen?: unknown }).requestFullscreen === 'function' && document.fullscreenEnabled !== false;\n }\n\n private bindFullscreen(): void {\n if (!this.fullscreenBtn) return;\n if (!this.supportsFullscreen()) {\n this.fullscreenBtn.remove();\n this.fullscreenBtn = null; // the F key checks this too\n return;\n }\n this.fullscreenBtn.addEventListener('click', () => {\n void this.toggleFullscreen();\n });\n this.fullscreenChangeHandler = () => {\n this.fitWrap();\n this.refreshFullscreenIcon();\n // Fullscreen reflow can shift the canvas without changing its size, which\n // ResizeObserver would miss; resync the overlay explicitly.\n this.syncRootToCanvas();\n };\n document.addEventListener('fullscreenchange', this.fullscreenChangeHandler);\n }\n\n private async toggleFullscreen(): Promise<void> {\n try {\n if (document.fullscreenElement === this.wrapper) {\n await document.exitFullscreen();\n } else {\n await this.wrapper.requestFullscreen();\n }\n } catch (err) {\n console.warn('pixi-effects: fullscreen denied:', err);\n }\n }\n\n private refreshFullscreenIcon(): void {\n if (!this.fullscreenBtn) return;\n const inFs = document.fullscreenElement === this.wrapper;\n this.fullscreenBtn.innerHTML = inFs ? ICONS.fullscreenExit : ICONS.fullscreenEnter;\n this.fullscreenBtn.setAttribute('aria-label', inFs ? 'Exit fullscreen' : 'Enter fullscreen');\n }\n\n private refreshProgress(frame: number, totalFrames?: number): void {\n const total = totalFrames ?? this.movie.totalFrames;\n const pct = frameToPercent(frame, total);\n this.progressEl.style.setProperty('--mc-fill', String(pct / 100));\n this.progressEl.setAttribute('aria-valuenow', String(frame));\n }\n\n private refreshTime(frame: number): void {\n const fr = this.movie.frameRate || 1;\n const cur = frame / fr;\n const total = this.movie.totalFrames / fr;\n this.timeEl.textContent = `${formatTime(cur)} / ${formatTime(total)}`;\n }\n\n private bindScrubbing(): void {\n const onDown = (e: PointerEvent) => {\n this.isScrubbing = true;\n this.activePointerId = e.pointerId;\n this.wasPlayingBeforeScrub = this.movie.isPlaying;\n if (this.movie.isPlaying) {\n this.movie.pause();\n this.refreshPlayIcon();\n }\n this.progressEl.classList.add('mc-scrubbing');\n try { this.progressEl.setPointerCapture(e.pointerId); } catch { /* unsupported */ }\n this.seekFromPointer(e.clientX);\n };\n // End the drag. `clientX` is given when the pointer was released over the bar (seek to where it was).\n // A page inside an iframe never receives the pointerup of a button released OUTSIDE the iframe, so the\n // drag also ends on lostpointercapture, on the window losing focus, and on the first pointermove that\n // has no button down — otherwise it stayed \"scrubbing\" (paused, seeking on every hover).\n const finish = (clientX?: number, pointerId?: number) => {\n if (!this.isScrubbing) return;\n if (clientX !== undefined) this.seekFromPointer(clientX);\n this.isScrubbing = false;\n this.activePointerId = null;\n this.progressEl.classList.remove('mc-scrubbing');\n try { if (pointerId !== undefined) this.progressEl.releasePointerCapture(pointerId); } catch { /* unsupported */ }\n if (this.wasPlayingBeforeScrub) {\n void this.startPlaying();\n this.refreshPlayIcon();\n }\n };\n const onMove = (e: PointerEvent) => {\n if (!this.isScrubbing) return;\n if (e.buttons === 0) { finish(undefined, e.pointerId); return; }\n this.seekFromPointer(e.clientX);\n };\n const onUp = (e: PointerEvent) => finish(e.clientX, e.pointerId);\n this.progressEl.addEventListener('pointerdown', onDown);\n this.progressEl.addEventListener('pointermove', onMove);\n this.progressEl.addEventListener('pointerup', onUp);\n this.progressEl.addEventListener('pointercancel', onUp);\n this.progressEl.addEventListener('lostpointercapture', () => finish());\n this.windowBlurHandler = () => { finish(); this.isVolumeScrubbing = false; this.volumeSliderEl?.classList.remove('mc-scrubbing'); };\n window.addEventListener('blur', this.windowBlurHandler);\n }\n\n private seekFromPointer(clientX: number): void {\n const rect = this.progressEl.getBoundingClientRect();\n const inset = Controller.PROGRESS_INSET_PX;\n const innerLeft = rect.left + inset;\n const innerWidth = Math.max(0, rect.width - 2 * inset);\n const frame = pxToFrame(clientX, { left: innerLeft, width: innerWidth }, this.movie.totalFrames);\n this.refreshProgress(frame);\n void this.movie.gotoFrame(frame);\n }\n\n private bindExportPopover(): void {\n if (!this.exportBtn || !this.settingsPopoverEl) return;\n\n // Download icon on the bar toggles the popover (it does NOT directly trigger export).\n this.exportBtn.addEventListener('click', (e) => {\n e.stopPropagation();\n this.toggleSettings(!this.settingsOpen);\n });\n\n // Confirm button inside the popover triggers the actual export, then closes.\n if (this.exportConfirmBtn) {\n this.exportConfirmBtn.addEventListener('click', () => {\n this.toggleSettings(false);\n void this.handleExport();\n });\n }\n\n if (this.settingsFormatSelect) {\n this.settingsFormatSelect.addEventListener('change', (e) => {\n const v = (e.target as HTMLSelectElement).value;\n if (v === 'mp4' || v === 'webm' || v === 'mov' || v === 'pdf' || v === 'pdf-steps') this.exportFormat = v;\n });\n }\n if (this.settingsQualitySelect) {\n this.settingsQualitySelect.addEventListener('change', (e) => {\n const v = (e.target as HTMLSelectElement).value;\n if (v === 'low' || v === 'medium' || v === 'high' || v === 'very-high') this.exportQuality = v;\n });\n }\n\n this.settingsKeyHandler = (e: KeyboardEvent) => {\n if (e.code === 'Escape' && this.settingsOpen) {\n e.preventDefault();\n this.toggleSettings(false);\n }\n };\n document.addEventListener('keydown', this.settingsKeyHandler);\n\n this.settingsOutsideHandler = (e: PointerEvent) => {\n if (!this.settingsOpen) return;\n const target = e.target as Node | null;\n if (!target) return;\n if (this.settingsPopoverEl?.contains(target)) return;\n if (this.exportBtn?.contains(target)) return;\n if (this.options.canvas.contains(target)) this.swallowCanvasClick = true; // closing the popover is all this tap does\n this.toggleSettings(false);\n };\n document.addEventListener('pointerdown', this.settingsOutsideHandler);\n }\n\n private toggleSettings(open: boolean): void {\n if (!this.exportBtn || !this.settingsPopoverEl) return;\n this.settingsOpen = open;\n this.settingsPopoverEl.setAttribute('data-open', open ? 'true' : 'false');\n this.exportBtn.setAttribute('aria-expanded', open ? 'true' : 'false');\n if (open) {\n // Keep the bar visible while the popover is open.\n if (this.hideTimer) { clearTimeout(this.hideTimer); this.hideTimer = null; }\n this.setVisible(true);\n } else {\n // Resume normal auto-hide cadence after closing.\n this.kickIdleTimer();\n }\n }\n\n private async handleExport(): Promise<void> {\n if (this.isExporting) return;\n this.isExporting = true;\n this.setVisible(true); // the progress is in the bar: keep it on screen until the export ends\n if (this.hideTimer) { clearTimeout(this.hideTimer); this.hideTimer = null; }\n const wasPlaying = this.movie.isPlaying;\n if (wasPlaying) {\n this.movie.pause();\n this.refreshPlayIcon();\n }\n const pdf = this.exportFormat === 'pdf' || this.exportFormat === 'pdf-steps';\n if (pdf) {\n const stops = this.movie.stops ?? [];\n const total = this.exportFormat === 'pdf-steps' ? stops.filter((s) => s.pdf !== false).length : new Set(stops.map((s) => s.pageIndex)).size;\n this.showExportOverlay('Exporting PDF...', `0% (0 / ${total} pages)`);\n this.exportPages = { done: 0, total };\n } else this.showExportOverlay();\n try {\n const blob = pdf\n ? await this.movie.exportPDF({\n which: this.exportFormat === 'pdf-steps' ? 'stops' : 'pages',\n quality: PDF_QUALITY[this.exportQuality],\n onImage: () => this.pdfPageDone(),\n })\n : await this.movie.render({\n format: this.exportFormat as 'mp4' | 'webm' | 'mov',\n video: { bitrate: this.exportQuality },\n audio: { bitrate: this.exportQuality },\n });\n if (this.exportFillEl) this.exportFillEl.style.width = '100%';\n if (this.exportTextEl) this.exportTextEl.textContent = 'Preparing download...';\n this.triggerDownload(blob);\n await new Promise((r) => setTimeout(r, 300));\n } catch (err) {\n console.error('Export failed:', err);\n alert('Export failed.');\n } finally {\n this.hideExportOverlay();\n this.isExporting = false;\n this.kickIdleTimer(); // the normal idle behaviour again: the bar fades after a pause\n if (wasPlaying) {\n void this.startPlaying();\n this.refreshPlayIcon();\n }\n }\n }\n\n private triggerDownload(blob: Blob): void {\n const url = URL.createObjectURL(blob);\n const a = document.createElement('a');\n a.href = url;\n a.download = this.makeFilename(blob);\n a.style.display = 'none';\n document.body.appendChild(a);\n a.click();\n a.remove();\n setTimeout(() => URL.revokeObjectURL(url), 100);\n }\n\n private makeFilename(blob: Blob): string {\n const ext = extensionForMimeType(blob.type);\n const d = new Date();\n const pad = (n: number) => n.toString().padStart(2, '0');\n const ts = `${d.getFullYear()}${pad(d.getMonth() + 1)}${pad(d.getDate())}-${pad(d.getHours())}${pad(d.getMinutes())}${pad(d.getSeconds())}`;\n return `movie-${ts}.${ext}`;\n }\n\n /** One more PDF page is ready: move the bar. */\n private pdfPageDone(): void {\n const p = this.exportPages;\n if (!p || !this.exportFillEl || !this.exportTextEl) return;\n p.done++;\n const percent = p.total ? Math.min(100, Math.round((p.done / p.total) * 100)) : 100;\n this.exportFillEl.style.width = `${percent}%`;\n this.exportTextEl.textContent = `${percent}% (${p.done} / ${p.total} pages)`;\n }\n\n private showExportOverlay(title = 'Exporting video...', text = '0% (0 / 0 frames)'): void {\n const overlay = document.createElement('div');\n overlay.className = 'mc-export-overlay';\n overlay.innerHTML = `\n <div class=\"mc-export-panel\">\n <div class=\"mc-export-title\"></div>\n <div class=\"mc-export-track\"><div class=\"mc-export-fill\"></div></div>\n <div class=\"mc-export-text\"></div>\n </div>\n `;\n overlay.querySelector('.mc-export-title')!.textContent = title;\n overlay.querySelector('.mc-export-text')!.textContent = text;\n this.root.appendChild(overlay);\n this.exportOverlay = overlay;\n this.exportFillEl = overlay.querySelector('.mc-export-fill') as HTMLDivElement;\n this.exportTextEl = overlay.querySelector('.mc-export-text') as HTMLDivElement;\n }\n\n private hideExportOverlay(): void {\n if (this.exportOverlay) {\n this.exportOverlay.remove();\n this.exportOverlay = null;\n this.exportFillEl = null;\n this.exportTextEl = null;\n }\n this.exportPages = null;\n }\n\n private bindVisibility(): void {\n const wrap = this.wrapper;\n this.onWrapPointerMove = () => this.kickIdleTimer();\n this.onWrapMouseLeave = () => {\n if (!this.settingsOpen && !this.isScrubbing && !this.isVolumeScrubbing && !this.isExporting) this.setVisible(false);\n };\n wrap.addEventListener('pointermove', this.onWrapPointerMove);\n wrap.addEventListener('mouseleave', this.onWrapMouseLeave);\n this.root.addEventListener('pointerenter', () => {\n if (this.hideTimer) { clearTimeout(this.hideTimer); this.hideTimer = null; }\n this.setVisible(true);\n });\n }\n\n private kickIdleTimer(): void {\n this.setVisible(true);\n if (this.hideTimer) { clearTimeout(this.hideTimer); this.hideTimer = null; }\n if (this.settingsOpen || this.isExporting) return; // the export progress lives in the bar: it stays until the export is done\n this.hideTimer = setTimeout(() => {\n if (!this.isScrubbing && !this.isVolumeScrubbing && !this.settingsOpen && !this.isExporting) this.setVisible(false);\n }, Controller.HIDE_DELAY_MS);\n }\n\n private setVisible(v: boolean): void {\n this.root.setAttribute('data-state', v ? 'visible' : 'hidden');\n }\n\n private syncRootToCanvas(): void {\n const c = this.options.canvas;\n const cr = c.getBoundingClientRect();\n const wr = this.wrapper.getBoundingClientRect();\n this.root.style.left = `${cr.left - wr.left}px`;\n this.root.style.top = `${cr.top - wr.top}px`;\n this.root.style.width = `${cr.width}px`;\n this.root.style.height = `${cr.height}px`;\n }\n\n private bindKeyboard(): void {\n this.keyHandler = (e: KeyboardEvent) => {\n if (this.presenter) return; // a presentation: the Presenter owns the keys\n const target = e.target as HTMLElement | null;\n if (target) {\n const tag = target.tagName;\n if (tag === 'INPUT' || tag === 'TEXTAREA' || tag === 'SELECT') return;\n if (target.isContentEditable || target.getAttribute?.('contenteditable') === 'true') return;\n }\n if (this.isExporting) return;\n\n switch (e.code) {\n case 'Space':\n e.preventDefault();\n this.playBtn.click();\n break;\n case 'ArrowLeft':\n e.preventDefault();\n this.stepFrame(-1);\n break;\n case 'ArrowRight':\n e.preventDefault();\n this.stepFrame(1);\n break;\n case 'ArrowUp':\n e.preventDefault();\n this.adjustVolume(0.05);\n break;\n case 'ArrowDown':\n e.preventDefault();\n this.adjustVolume(-0.05);\n break;\n case 'KeyM':\n e.preventDefault();\n this.muteBtn.click();\n break;\n case 'KeyE':\n if (e.shiftKey && this.exportBtn) {\n e.preventDefault();\n // Power-user shortcut: skip the popover and export with current settings.\n void this.handleExport();\n }\n break;\n case 'KeyF':\n if (this.fullscreenBtn) {\n e.preventDefault();\n void this.toggleFullscreen();\n }\n break;\n }\n };\n document.addEventListener('keydown', this.keyHandler);\n }\n\n private stepFrame(delta: number): void {\n const next = Math.max(0, Math.min(this.movie.totalFrames, this.movie.currentFrame + delta));\n void this.movie.gotoFrame(next);\n }\n\n private adjustVolume(delta: number): void {\n const next = Math.max(0, Math.min(1, this.movie.volume + delta));\n this.movie.volume = next;\n if (this.movie.muted && next > 0) this.movie.muted = false;\n this.refreshVolumeUI();\n }\n\n destroy(): void {\n if (this.destroyed) return;\n this.destroyed = true;\n this.stopPresenting();\n if (this.onReady) { this.movie.off('ready', this.onReady); this.onReady = null; }\n if (this.onFrame) { this.movie.off('frame', this.onFrame); this.onFrame = null; }\n if (this.onPlay) { this.movie.off('play', this.onPlay); this.onPlay = null; }\n if (this.onPause) { this.movie.off('pause', this.onPause); this.onPause = null; }\n if (this.onProgress) { this.movie.off('progress', this.onProgress); this.onProgress = null; }\n if (this.onWrapPointerMove) {\n this.wrapper.removeEventListener('pointermove', this.onWrapPointerMove);\n this.onWrapPointerMove = null;\n }\n if (this.onWrapMouseLeave) {\n this.wrapper.removeEventListener('mouseleave', this.onWrapMouseLeave);\n this.onWrapMouseLeave = null;\n }\n if (this.resizeObserver) {\n this.resizeObserver.disconnect();\n this.resizeObserver = null;\n }\n if (this.canvasClickHandler) {\n this.options.canvas.removeEventListener('click', this.canvasClickHandler);\n this.options.canvas.removeEventListener('pointerdown', this.canvasPointerDownHandler!);\n this.options.canvas.style.cursor = this.canvasCursor;\n this.canvasClickHandler = null; this.canvasPointerDownHandler = null;\n }\n if (this.fitObserver) { this.fitObserver.disconnect(); this.fitObserver = null; }\n if (this.fitWrapHandler) { window.removeEventListener('resize', this.fitWrapHandler); this.fitWrapHandler = null; }\n if (this.wrappedHere) { // give the canvas its own sizing back\n this.options.canvas.style.width = this.canvasInlineWidth;\n this.options.canvas.style.height = this.canvasInlineHeight;\n }\n this.root.remove();\n if (this.wrappedHere) {\n const parent = this.wrapper.parentElement;\n const canvas = this.options.canvas;\n if (parent) {\n parent.insertBefore(canvas, this.wrapper);\n this.wrapper.remove();\n }\n } else {\n this.wrapper.removeAttribute('data-mc-wrap');\n }\n if (this.keyHandler) {\n document.removeEventListener('keydown', this.keyHandler);\n this.keyHandler = null;\n }\n if (this.settingsKeyHandler) {\n document.removeEventListener('keydown', this.settingsKeyHandler);\n this.settingsKeyHandler = null;\n }\n if (this.settingsOutsideHandler) {\n document.removeEventListener('pointerdown', this.settingsOutsideHandler);\n this.settingsOutsideHandler = null;\n }\n if (this.fullscreenChangeHandler) {\n document.removeEventListener('fullscreenchange', this.fullscreenChangeHandler);\n this.fullscreenChangeHandler = null;\n }\n if (this.windowBlurHandler) {\n window.removeEventListener('blur', this.windowBlurHandler);\n this.windowBlurHandler = null;\n }\n if (this.wheelHandler && this.volumeContainerEl) {\n this.volumeContainerEl.removeEventListener('wheel', this.wheelHandler);\n this.wheelHandler = null;\n }\n if (document.fullscreenElement === this.wrapper) {\n void document.exitFullscreen().catch(() => {});\n }\n if (this.hideTimer) { clearTimeout(this.hideTimer); this.hideTimer = null; }\n this.hideExportOverlay();\n uninstallStyles();\n }\n}\n"]}
@@ -5,6 +5,12 @@ import { U as Stop, e as AssetSpec, c as CompositionSpec } from './types-SS51lP6
5
5
  interface AudioInspectOptions {
6
6
  /** Width of each loudness window in seconds. Default 0.1. */
7
7
  window?: number;
8
+ /** The scenes to measure one by one (`movie.inspectAudio()` fills this from the movie's named top-level compositions). Default: the whole movie as one. */
9
+ scenes?: Array<{
10
+ name: string;
11
+ start: number;
12
+ end: number;
13
+ }>;
8
14
  }
9
15
  /** One sound measured ON ITS OWN (not mixed), so overlapping layers do not blur it. */
10
16
  interface SoundMeasure {
@@ -44,8 +50,44 @@ interface AudioReport {
44
50
  peakDb: number;
45
51
  brightnessHz: number;
46
52
  }>;
47
- /** Problems worth fixing: limiting, inaudible layers, sounds cut off by the end of the movie. Read this first. */
53
+ /** Problems worth fixing: limiting, clipping, a true peak above 0 dBTP, inaudible layers, sounds cut off by the end of the movie. Read this first. */
48
54
  issues: string[];
55
+ /** The mix as a whole (ITU-R BS.1770 loudness; `integratedLufs` is null for a mix shorter than 0.4 s or with nothing above −70 LUFS). */
56
+ loudness: {
57
+ integratedLufs: number | null;
58
+ truePeakDb: number;
59
+ clippedSamples: number;
60
+ silences: Array<{
61
+ from: number;
62
+ to: number;
63
+ }>;
64
+ };
65
+ /** The same measure for each scene (`silent`: nothing above −60 dBFS). */
66
+ scenes: Array<{
67
+ name: string;
68
+ from: number;
69
+ to: number;
70
+ lufs: number | null;
71
+ peakDb: number;
72
+ silent: boolean;
73
+ }>;
74
+ /** When each sound starts: what a waveform marks. */
75
+ cues: Array<{
76
+ t: number;
77
+ name: string;
78
+ }>;
79
+ /** Advice, not faults: a mix that is quiet or loud for web video, little headroom, silent stretches. */
80
+ notes: string[];
81
+ }
82
+
83
+ interface FontReport {
84
+ /** Text layers none of whose fonts is available here: they are drawn in a fallback. */
85
+ missing: Array<{
86
+ layer: string;
87
+ family: string;
88
+ }>;
89
+ /** Web fonts (`@font-face`) whose file could not be loaded. */
90
+ failed: string[];
49
91
  }
50
92
 
51
93
  interface Rect {
@@ -196,6 +238,15 @@ interface RenderOptions {
196
238
  codec?: string;
197
239
  bitrate?: 'very-low' | 'low' | 'medium' | 'high' | 'very-high';
198
240
  };
241
+ /**
242
+ * Only part of the movie: `[from, to]` in seconds, or the name of a top-level layer (its start to its end). The file starts at 0
243
+ * and its sound is cut the same way (with a 10 ms fade on a cut edge). Past the end, backwards or an unknown name is an error.
244
+ */
245
+ range?: [number, number] | string;
246
+ /** Output size relative to the canvas, above 0 and at most 1. Each frame is drawn at full size and copied smaller before it is encoded: the file and the encoding get smaller, the drawing is not faster. */
247
+ scale?: number;
248
+ /** For looking, not for delivering: `scale: 0.5`, `video.bitrate: 'low'` and no motion blur. Anything you set yourself wins. */
249
+ draft?: boolean;
199
250
  }
200
251
  interface SnapshotOptions {
201
252
  /** Motion blur for this picture (see `MovieOptions.motionBlur`); overrides the movie's own setting, `false` turns it off. */
@@ -248,6 +299,19 @@ interface ContactSheetOptions {
248
299
  cellWidth?: number;
249
300
  as?: 'blob' | 'dataURL';
250
301
  }
302
+ interface OnionSkinOptions {
303
+ /** Where the movement starts, in seconds. Default 0. */
304
+ from?: number;
305
+ /** Where it ends, in seconds. Default: the end of the movie. */
306
+ to?: number;
307
+ /** How many frames are overlaid, 1–64, spread evenly from `from` to `to`. Default 8. */
308
+ count?: number;
309
+ /** Output size relative to the canvas, above 0 and at most 4. Default 1. */
310
+ scale?: number;
311
+ /** Motion blur for these pictures (see `MovieOptions.motionBlur`); overrides the movie's own setting, `false` turns it off. */
312
+ motionBlur?: MotionBlurSpec;
313
+ as?: 'blob' | 'dataURL';
314
+ }
251
315
  interface FrameEvent {
252
316
  frame: number;
253
317
  totalFrames: number;
@@ -419,6 +483,17 @@ declare class Movie {
419
483
  motionBlur?: MotionBlurSpec;
420
484
  onImage?: (image: StopImage) => void;
421
485
  }): Promise<Blob>;
486
+ /**
487
+ * One picture of a movement: `count` frames from `from` to `to` drawn one over the other, each later one stronger, so a thing that
488
+ * moves leaves a trail (its path and its easing: even steps = constant speed, bunched = slow) and what stays still stays itself.
489
+ * The movie is left where it was.
490
+ */
491
+ onionSkin(opts?: OnionSkinOptions & {
492
+ as?: 'blob';
493
+ }): Promise<Blob>;
494
+ onionSkin(opts: OnionSkinOptions & {
495
+ as: 'dataURL';
496
+ }): Promise<string>;
422
497
  /**
423
498
  * Several frames on ONE image, each labelled with its frame number and time — the cheapest way to
424
499
  * check a whole animation by eye. Restores the current frame afterwards.
@@ -447,6 +522,11 @@ declare class Movie {
447
522
  * The soundtrack, measured: when every audio layer plays, how loud the mix is over time, and `issues`
448
523
  * (limiting, inaudible layers, sounds cut off by the end). Use it to CHECK sound you cannot hear.
449
524
  */
525
+ /**
526
+ * The fonts of the text layers: `missing` lists layers none of whose `fontFamily` entries is available in this browser (they are
527
+ * drawn in a fallback font), `failed` lists web fonts (`@font-face`) whose file could not be loaded.
528
+ */
529
+ inspectFonts(): FontReport;
450
530
  inspectAudio(opts?: AudioInspectOptions): AudioReport;
451
531
  /**
452
532
  * Draw the stage now. PixiJS's CullerPlugin only culls inside `app.render()` (the ticker), and we render
@@ -509,4 +589,4 @@ declare class Movie {
509
589
  destroy(): Promise<void>;
510
590
  }
511
591
 
512
- 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 };
592
+ export { type AudioInspectOptions as A, type ContactSheetOptions as C, type FontReport as F, type InspectOptions as I, type LayerInfo as L, type MotionBlurOptions as M, type OnionSkinOptions as O, 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 FrameEvent as c, type InspectReport as d, type LoaderOption as e, type MotionBlurSpec as f, Movie as g, type MovieErrorEvent as h, type MovieOptions as i, type SoundMeasure as j, type StopEvent as k, type StopImage as l, type StopImagesOptions as m, type TimelineHtmlOptions as n, type TimelineRow as o, type TimelineSvgOptions as p, type TimelineTransition as q, dismissLoader as r, failLoader as s, resolveLoader as t };