pixi-effects 0.28.2 → 0.29.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +52 -0
- package/README.md +10 -10
- package/ai/chat-template.html +5 -5
- package/ai/tools/check.mjs +18 -3
- package/ai/tools/pixi-effects.mjs +1 -1
- package/ai/tools/render.mjs +14 -9
- package/ai/tools/view.mjs +6 -2
- package/dist/Base-CB1_FPZD.d.cts +60 -0
- package/dist/Base-Ne74ztNl.d.ts +60 -0
- package/dist/Composition-MUKR3FYD.cjs +16 -0
- package/dist/{Composition-K6B3APM5.cjs.map → Composition-MUKR3FYD.cjs.map} +1 -1
- package/dist/Composition-RJGA7KDU.js +7 -0
- package/dist/{Composition-H7UNR5F5.js.map → Composition-RJGA7KDU.js.map} +1 -1
- package/dist/Controller.cjs +73 -45
- package/dist/Controller.cjs.map +1 -1
- package/dist/Controller.d.cts +16 -22
- package/dist/Controller.d.ts +16 -22
- package/dist/Controller.js +74 -40
- package/dist/Controller.js.map +1 -1
- package/dist/{Movie-CHcM8HNB.d.ts → Movie-C2rZFkrO.d.ts} +227 -119
- package/dist/{Movie-Cx5ozUGb.d.cts → Movie-DdnpLpw1.d.cts} +227 -119
- package/dist/{blendModes-HDOP6R7T.cjs → blendModes-ETMYWATF.cjs} +5 -5
- package/dist/{blendModes-HDOP6R7T.cjs.map → blendModes-ETMYWATF.cjs.map} +1 -1
- package/dist/{blendModes-PAVTW3BO.js → blendModes-RIVZXL5A.js} +4 -4
- package/dist/{blendModes-PAVTW3BO.js.map → blendModes-RIVZXL5A.js.map} +1 -1
- package/dist/{chunk-P4GY3Z4G.cjs → chunk-2DXPTKQZ.cjs} +6 -6
- package/dist/chunk-2DXPTKQZ.cjs.map +1 -0
- package/dist/{chunk-TYWFKCPY.js → chunk-4KB3GUEK.js} +5 -5
- package/dist/chunk-4KB3GUEK.js.map +1 -0
- package/dist/{chunk-5MZWXVTT.js → chunk-A3Q3SDSH.js} +35 -28
- package/dist/chunk-A3Q3SDSH.js.map +1 -0
- package/dist/chunk-CRQFDY7E.js +4182 -0
- package/dist/chunk-CRQFDY7E.js.map +1 -0
- package/dist/chunk-HREBQAY4.cjs +4206 -0
- package/dist/chunk-HREBQAY4.cjs.map +1 -0
- package/dist/{chunk-ZMAD3KJU.cjs → chunk-LYOKH7KE.cjs} +22 -3
- package/dist/chunk-LYOKH7KE.cjs.map +1 -0
- package/dist/{chunk-45QKLD6M.js → chunk-RCVZX2JP.js} +22 -3
- package/dist/chunk-RCVZX2JP.js.map +1 -0
- package/dist/{chunk-KBH33IQX.cjs → chunk-WHNADXXG.cjs} +121 -114
- package/dist/chunk-WHNADXXG.cjs.map +1 -0
- package/dist/{chunk-7VN2KI3U.js → chunk-ZAXYPXKW.js} +14 -6
- package/dist/chunk-ZAXYPXKW.js.map +1 -0
- package/dist/{chunk-MJW7KILM.cjs → chunk-ZVUO325O.cjs} +32 -24
- package/dist/chunk-ZVUO325O.cjs.map +1 -0
- package/dist/index.cjs +106 -4482
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +15 -60
- package/dist/index.d.ts +15 -60
- package/dist/index.js +6 -4457
- package/dist/index.js.map +1 -1
- package/dist/loader.css +1 -1
- package/dist/{Presenter.cjs → present.cjs} +370 -31
- package/dist/present.cjs.map +1 -0
- package/dist/present.d.cts +278 -0
- package/dist/present.d.ts +278 -0
- package/dist/{Presenter.js → present.js} +358 -32
- package/dist/present.js.map +1 -0
- package/dist/three.cjs +6 -6
- package/dist/three.d.cts +2 -2
- package/dist/three.d.ts +2 -2
- package/dist/three.js +2 -2
- package/dist/{types-DpK1vwcl.d.ts → types-BzIB65Vk.d.cts} +11 -265
- package/dist/{types-DpK1vwcl.d.cts → types-BzIB65Vk.d.ts} +11 -265
- package/docs/api.md +44 -77
- package/docs/dsl.md +16 -14
- package/llms-full.txt +86 -115
- package/llms.txt +1 -1
- package/package.json +5 -5
- package/skills/pixi-effects/SKILL.md +5 -5
- package/skills/pixi-effects/reference/cheatsheet.md +9 -9
- package/skills/pixi-effects/reference/direction.md +2 -0
- package/skills/pixi-effects/reference/pitfalls.md +6 -6
- package/skills/pixi-effects/reference/recipes.md +4 -4
- package/skills/pixi-effects/template.html +7 -7
- package/dist/Base-C6f0fE8j.d.ts +0 -109
- package/dist/Base-DI1FCGcH.d.cts +0 -109
- package/dist/Composition-H7UNR5F5.js +0 -7
- package/dist/Composition-K6B3APM5.cjs +0 -16
- package/dist/Presenter.cjs.map +0 -1
- package/dist/Presenter.d.cts +0 -122
- package/dist/Presenter.d.ts +0 -122
- package/dist/Presenter.js.map +0 -1
- package/dist/chunk-45QKLD6M.js.map +0 -1
- package/dist/chunk-5MZWXVTT.js.map +0 -1
- package/dist/chunk-7VN2KI3U.js.map +0 -1
- package/dist/chunk-KBH33IQX.cjs.map +0 -1
- package/dist/chunk-MJW7KILM.cjs.map +0 -1
- package/dist/chunk-P4GY3Z4G.cjs.map +0 -1
- package/dist/chunk-TYWFKCPY.js.map +0 -1
- package/dist/chunk-ZMAD3KJU.cjs.map +0 -1
package/dist/Controller.d.ts
CHANGED
|
@@ -1,20 +1,7 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { k as Movie } from './Movie-C2rZFkrO.js';
|
|
2
2
|
import 'pixi.js';
|
|
3
|
-
import './types-
|
|
3
|
+
import './types-BzIB65Vk.js';
|
|
4
4
|
|
|
5
|
-
/** 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. */
|
|
6
|
-
declare 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";
|
|
7
|
-
declare function formatTime(seconds: number): string;
|
|
8
|
-
declare function frameToPercent(frame: number, totalFrames: number): number;
|
|
9
|
-
declare function pxToFrame(clientX: number, rect: {
|
|
10
|
-
left: number;
|
|
11
|
-
width: number;
|
|
12
|
-
}, totalFrames: number): number;
|
|
13
|
-
declare function pxToFraction(clientX: number, rect: {
|
|
14
|
-
left: number;
|
|
15
|
-
width: number;
|
|
16
|
-
}, inset?: number): number;
|
|
17
|
-
declare function extensionForMimeType(mime: string): string;
|
|
18
5
|
/**
|
|
19
6
|
* 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
|
|
20
7
|
* canvas's parent or on `:root`). `null` puts a value back to the default.
|
|
@@ -37,22 +24,24 @@ interface ControllerOptions {
|
|
|
37
24
|
canvas: HTMLCanvasElement;
|
|
38
25
|
/** Colours and sizes of the bar, see {@link ControllerTheme}. Can be changed later with `controller.setTheme()`. */
|
|
39
26
|
theme?: ControllerTheme;
|
|
40
|
-
|
|
41
|
-
|
|
27
|
+
/** The download button and its panel. Default true. */
|
|
28
|
+
exportButton?: boolean;
|
|
29
|
+
/** Space, arrows, M, F, E … on the page (not while typing in a field). Default true. */
|
|
30
|
+
keyboard?: boolean;
|
|
42
31
|
/** A click (or tap) on the picture plays / pauses, like a `<video>` element. Default true; `false` leaves the canvas alone. */
|
|
43
32
|
clickToPlay?: boolean;
|
|
44
33
|
/** 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. */
|
|
45
|
-
|
|
34
|
+
presentButton?: boolean;
|
|
46
35
|
/** 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. */
|
|
47
36
|
pauseAtStops?: boolean;
|
|
48
37
|
className?: string;
|
|
49
38
|
}
|
|
50
39
|
interface ResolvedOptions {
|
|
51
40
|
canvas: HTMLCanvasElement;
|
|
52
|
-
|
|
53
|
-
|
|
41
|
+
exportButton: boolean;
|
|
42
|
+
keyboard: boolean;
|
|
54
43
|
clickToPlay: boolean;
|
|
55
|
-
|
|
44
|
+
presentButton: boolean;
|
|
56
45
|
pauseAtStops: boolean;
|
|
57
46
|
className: string;
|
|
58
47
|
}
|
|
@@ -98,6 +87,11 @@ declare class Controller {
|
|
|
98
87
|
private settingsOutsideHandler;
|
|
99
88
|
private onReady;
|
|
100
89
|
private presenter;
|
|
90
|
+
/** `pixi-effects/present`, loaded as soon as the movie has stops (a press of play must not wait for it). */
|
|
91
|
+
private present;
|
|
92
|
+
private presentLoading;
|
|
93
|
+
private playStarting;
|
|
94
|
+
private loadPresent;
|
|
101
95
|
private presentBtn;
|
|
102
96
|
private onFrame;
|
|
103
97
|
private onPlay;
|
|
@@ -183,4 +177,4 @@ declare class Controller {
|
|
|
183
177
|
destroy(): void;
|
|
184
178
|
}
|
|
185
179
|
|
|
186
|
-
export {
|
|
180
|
+
export { Controller, type ControllerOptions, type ControllerTheme };
|
package/dist/Controller.js
CHANGED
|
@@ -1,17 +1,6 @@
|
|
|
1
1
|
import { warnUnknownOptions } from './chunk-BXOCEZ4U.js';
|
|
2
2
|
|
|
3
|
-
// src/
|
|
4
|
-
var ICONS = {
|
|
5
|
-
play: '<svg viewBox="0 0 16 16" width="16" height="16" fill="currentColor"><path d="M3 2 L13 8 L3 14 Z"/></svg>',
|
|
6
|
-
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>',
|
|
7
|
-
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>',
|
|
8
|
-
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>',
|
|
9
|
-
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>',
|
|
10
|
-
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>',
|
|
11
|
-
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>',
|
|
12
|
-
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>'
|
|
13
|
-
};
|
|
14
|
-
var STYLE_ATTR = "data-movie-controller";
|
|
3
|
+
// src/controller/css.ts
|
|
15
4
|
var CONTROLLER_CSS = `
|
|
16
5
|
.movie-controller-wrap { position: relative; display: inline-block; line-height: 0; }
|
|
17
6
|
.movie-controller {
|
|
@@ -230,22 +219,8 @@ var CONTROLLER_CSS = `
|
|
|
230
219
|
font-family: Menlo, Monaco, monospace;
|
|
231
220
|
}
|
|
232
221
|
`;
|
|
233
|
-
|
|
234
|
-
|
|
235
|
-
if (styleRefCount === 0) {
|
|
236
|
-
const el = document.createElement("style");
|
|
237
|
-
el.setAttribute(STYLE_ATTR, "");
|
|
238
|
-
el.textContent = CONTROLLER_CSS;
|
|
239
|
-
document.head.appendChild(el);
|
|
240
|
-
}
|
|
241
|
-
styleRefCount++;
|
|
242
|
-
}
|
|
243
|
-
function uninstallStyles() {
|
|
244
|
-
styleRefCount = Math.max(0, styleRefCount - 1);
|
|
245
|
-
if (styleRefCount === 0) {
|
|
246
|
-
document.head.querySelectorAll(`style[${STYLE_ATTR}]`).forEach((n) => n.remove());
|
|
247
|
-
}
|
|
248
|
-
}
|
|
222
|
+
|
|
223
|
+
// src/controller/helpers.ts
|
|
249
224
|
function formatTime(seconds) {
|
|
250
225
|
const s = Math.max(0, Math.floor(seconds));
|
|
251
226
|
const m = Math.floor(s / 60);
|
|
@@ -270,7 +245,6 @@ function pxToFraction(clientX, rect, inset = 0) {
|
|
|
270
245
|
const ratio = (clientX - innerLeft) / innerWidth;
|
|
271
246
|
return Math.min(Math.max(ratio, 0), 1);
|
|
272
247
|
}
|
|
273
|
-
var PDF_QUALITY = { "low": 0.6, "medium": 0.75, "high": 0.88, "very-high": 0.95 };
|
|
274
248
|
function extensionForMimeType(mime) {
|
|
275
249
|
const t = (mime || "").toLowerCase();
|
|
276
250
|
if (t.includes("pdf")) return "pdf";
|
|
@@ -279,6 +253,36 @@ function extensionForMimeType(mime) {
|
|
|
279
253
|
if (t.includes("matroska") || t.includes("mkv")) return "mkv";
|
|
280
254
|
return "mp4";
|
|
281
255
|
}
|
|
256
|
+
|
|
257
|
+
// src/Controller.ts
|
|
258
|
+
var ICONS = {
|
|
259
|
+
play: '<svg viewBox="0 0 16 16" width="16" height="16" fill="currentColor"><path d="M3 2 L13 8 L3 14 Z"/></svg>',
|
|
260
|
+
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>',
|
|
261
|
+
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>',
|
|
262
|
+
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>',
|
|
263
|
+
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>',
|
|
264
|
+
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>',
|
|
265
|
+
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>',
|
|
266
|
+
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>'
|
|
267
|
+
};
|
|
268
|
+
var STYLE_ATTR = "data-movie-controller";
|
|
269
|
+
var styleRefCount = 0;
|
|
270
|
+
function installStyles() {
|
|
271
|
+
if (styleRefCount === 0) {
|
|
272
|
+
const el = document.createElement("style");
|
|
273
|
+
el.setAttribute(STYLE_ATTR, "");
|
|
274
|
+
el.textContent = CONTROLLER_CSS;
|
|
275
|
+
document.head.appendChild(el);
|
|
276
|
+
}
|
|
277
|
+
styleRefCount++;
|
|
278
|
+
}
|
|
279
|
+
function uninstallStyles() {
|
|
280
|
+
styleRefCount = Math.max(0, styleRefCount - 1);
|
|
281
|
+
if (styleRefCount === 0) {
|
|
282
|
+
document.head.querySelectorAll(`style[${STYLE_ATTR}]`).forEach((n) => n.remove());
|
|
283
|
+
}
|
|
284
|
+
}
|
|
285
|
+
var PDF_QUALITY = { "low": 0.6, "medium": 0.75, "high": 0.88, "very-high": 0.95 };
|
|
282
286
|
var THEME_PROPERTIES = {
|
|
283
287
|
accent: "--mc-accent",
|
|
284
288
|
foreground: "--mc-fg",
|
|
@@ -287,6 +291,7 @@ var THEME_PROPERTIES = {
|
|
|
287
291
|
trackHeight: "--mc-track-height",
|
|
288
292
|
font: "--mc-font"
|
|
289
293
|
};
|
|
294
|
+
var CONTROLLER_OPTION_KEYS = ["canvas", "theme", "exportButton", "keyboard", "clickToPlay", "presentButton", "pauseAtStops", "className"];
|
|
290
295
|
var Controller = class _Controller {
|
|
291
296
|
movie;
|
|
292
297
|
options;
|
|
@@ -329,6 +334,16 @@ var Controller = class _Controller {
|
|
|
329
334
|
settingsOutsideHandler = null;
|
|
330
335
|
onReady = null;
|
|
331
336
|
presenter = null;
|
|
337
|
+
/** `pixi-effects/present`, loaded as soon as the movie has stops (a press of play must not wait for it). */
|
|
338
|
+
present = null;
|
|
339
|
+
presentLoading = null;
|
|
340
|
+
playStarting = false;
|
|
341
|
+
loadPresent() {
|
|
342
|
+
return this.presentLoading ??= import('./present.js').then((m) => this.present = m, (err) => {
|
|
343
|
+
this.presentLoading = null;
|
|
344
|
+
throw err;
|
|
345
|
+
});
|
|
346
|
+
}
|
|
332
347
|
presentBtn = null;
|
|
333
348
|
onFrame = null;
|
|
334
349
|
onPlay = null;
|
|
@@ -354,13 +369,14 @@ var Controller = class _Controller {
|
|
|
354
369
|
if (!options || !options.canvas) {
|
|
355
370
|
throw new Error("Controller requires options.canvas (HTMLCanvasElement).");
|
|
356
371
|
}
|
|
372
|
+
warnUnknownOptions("Controller", options, CONTROLLER_OPTION_KEYS);
|
|
357
373
|
this.movie = movie;
|
|
358
374
|
this.options = {
|
|
359
375
|
canvas: options.canvas,
|
|
360
|
-
|
|
361
|
-
|
|
376
|
+
exportButton: options.exportButton ?? true,
|
|
377
|
+
keyboard: options.keyboard ?? true,
|
|
362
378
|
clickToPlay: options.clickToPlay ?? true,
|
|
363
|
-
|
|
379
|
+
presentButton: options.presentButton ?? true,
|
|
364
380
|
pauseAtStops: options.pauseAtStops ?? true,
|
|
365
381
|
className: options.className ?? "movie-controller"
|
|
366
382
|
};
|
|
@@ -389,10 +405,10 @@ var Controller = class _Controller {
|
|
|
389
405
|
this.bindExportPopover();
|
|
390
406
|
this.bindFullscreen();
|
|
391
407
|
this.bindVisibility();
|
|
392
|
-
if (this.options.
|
|
408
|
+
if (this.options.keyboard) this.bindKeyboard();
|
|
393
409
|
}
|
|
394
410
|
buildBar() {
|
|
395
|
-
const popoverHtml = this.options.
|
|
411
|
+
const popoverHtml = this.options.exportButton ? `
|
|
396
412
|
<div class="mc-settings-popover" role="dialog" aria-label="Export settings" data-open="false">
|
|
397
413
|
<label class="mc-settings-row">
|
|
398
414
|
<span>Format</span>
|
|
@@ -431,7 +447,7 @@ var Controller = class _Controller {
|
|
|
431
447
|
</div>
|
|
432
448
|
<span class="mc-time">0:00 / 0:00</span>
|
|
433
449
|
<div class="mc-spacer"></div>
|
|
434
|
-
${this.options.
|
|
450
|
+
${this.options.exportButton ? `<button class="mc-btn mc-export" aria-label="Export" aria-expanded="false">${ICONS.download}</button>` : ""}
|
|
435
451
|
<button class="mc-btn mc-fullscreen" aria-label="Enter fullscreen">${ICONS.fullscreenEnter}</button>
|
|
436
452
|
</div>
|
|
437
453
|
`;
|
|
@@ -575,6 +591,8 @@ var Controller = class _Controller {
|
|
|
575
591
|
this.presentBtn = null;
|
|
576
592
|
return;
|
|
577
593
|
}
|
|
594
|
+
this.loadPresent().catch(() => {
|
|
595
|
+
});
|
|
578
596
|
const total = this.movie.totalFrames || 1;
|
|
579
597
|
const holder = document.createElement("div");
|
|
580
598
|
holder.className = "mc-stops";
|
|
@@ -586,7 +604,7 @@ var Controller = class _Controller {
|
|
|
586
604
|
holder.appendChild(tick);
|
|
587
605
|
}
|
|
588
606
|
this.progressEl.appendChild(holder);
|
|
589
|
-
if (this.options.
|
|
607
|
+
if (this.options.presentButton && !this.presentBtn && this.fullscreenBtn) {
|
|
590
608
|
const btn = document.createElement("button");
|
|
591
609
|
btn.className = "mc-btn mc-present";
|
|
592
610
|
btn.setAttribute("aria-label", "Present");
|
|
@@ -631,13 +649,29 @@ var Controller = class _Controller {
|
|
|
631
649
|
async startPlaying() {
|
|
632
650
|
if (this.options.pauseAtStops && (this.movie.stops?.length ?? 0) > 0) {
|
|
633
651
|
if (this.movie.currentFrame >= this.movie.totalFrames) await this.movie.gotoFrame(0, true);
|
|
634
|
-
|
|
652
|
+
let present = this.present;
|
|
653
|
+
if (!present) {
|
|
654
|
+
if (this.playStarting) return;
|
|
655
|
+
this.playStarting = true;
|
|
656
|
+
try {
|
|
657
|
+
present = await this.loadPresent();
|
|
658
|
+
} catch (err) {
|
|
659
|
+
console.warn("pixi-effects: could not load pixi-effects/present, playing straight through:", err);
|
|
660
|
+
} finally {
|
|
661
|
+
this.playStarting = false;
|
|
662
|
+
}
|
|
663
|
+
}
|
|
664
|
+
if (!present) {
|
|
665
|
+
this.movie.play();
|
|
666
|
+
return;
|
|
667
|
+
}
|
|
668
|
+
await present.next(this.movie);
|
|
635
669
|
} else this.movie.play();
|
|
636
670
|
}
|
|
637
671
|
/** Hand the page over to a Presenter (fullscreen, keys, click and swipe move through the stops); Escape gives it back. */
|
|
638
672
|
async startPresenting() {
|
|
639
673
|
if (this.presenter || this.destroyed) return;
|
|
640
|
-
const { Presenter } = await
|
|
674
|
+
const { Presenter } = await this.loadPresent();
|
|
641
675
|
if (this.presenter || this.destroyed) return;
|
|
642
676
|
const p = new Presenter(this.movie, { canvas: this.options.canvas, onExit: () => this.stopPresenting() });
|
|
643
677
|
this.presenter = p;
|
|
@@ -935,7 +969,7 @@ var Controller = class _Controller {
|
|
|
935
969
|
this.exportPages = { done: 0, total };
|
|
936
970
|
} else this.showExportOverlay();
|
|
937
971
|
try {
|
|
938
|
-
const blob = pdf ? await this.
|
|
972
|
+
const blob = pdf ? await (await this.loadPresent()).exportPDF(this.movie, {
|
|
939
973
|
which: this.exportFormat === "pdf-steps" ? "stops" : "pages",
|
|
940
974
|
quality: PDF_QUALITY[this.exportQuality],
|
|
941
975
|
onImage: () => this.pdfPageDone()
|
|
@@ -1217,6 +1251,6 @@ var Controller = class _Controller {
|
|
|
1217
1251
|
}
|
|
1218
1252
|
};
|
|
1219
1253
|
|
|
1220
|
-
export {
|
|
1254
|
+
export { Controller };
|
|
1221
1255
|
//# sourceMappingURL=Controller.js.map
|
|
1222
1256
|
//# sourceMappingURL=Controller.js.map
|