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/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,57 @@
|
|
|
1
1
|
# Changelog
|
|
2
2
|
|
|
3
|
+
## 0.29.0
|
|
4
|
+
|
|
5
|
+
**Changed (breaking): presentation leaves the core**
|
|
6
|
+
|
|
7
|
+
The talk side of the library is now its own entry, `pixi-effects/present`, built on the core's public API only (a test enforces the import rule). The core keeps `composition.stops` (named times, `movie.stops`) and gains two general moves; everything else that was about a talk moved out.
|
|
8
|
+
|
|
9
|
+
| before | now |
|
|
10
|
+
|---|---|
|
|
11
|
+
| `movie.next()` `prev()` `goToStop(i)` `goToPage(n)` | `next(movie)` `prev(movie)` `goToStop(movie, i)` `goToPage(movie, n)` from `pixi-effects/present` |
|
|
12
|
+
| `movie.stopIndex` `pageIndex` `pageCount` `currentStop` | `stopIndex(movie)` `pageIndex(movie)` `pageCount(movie)` `currentStop(movie)` |
|
|
13
|
+
| `movie.on('stop', fn)` | `const off = onStop(movie, fn)` |
|
|
14
|
+
| `movie.stopImages(o)` `movie.inspectStops(o)` `movie.exportPDF(o)` | `stopImages(movie, o)` `inspectStops(movie, o)` `exportPDF(movie, o)` |
|
|
15
|
+
| `import { deck } from 'pixi-effects'` | `import { deck } from 'pixi-effects/present'` |
|
|
16
|
+
| `import { Presenter } from 'pixi-effects/presenter'` (`dist/Presenter.js`) | `import { Presenter } from 'pixi-effects/present'` (`dist/present.js`; the import map line is `"pixi-effects/present"`) |
|
|
17
|
+
| `normalizeStops`, `pictureStops` exported from `pixi-effects` | not exported (the core normalises `composition.stops` itself; `pictureStops` is inside `pixi-effects/present`) |
|
|
18
|
+
| the types `StopEvent`, `StopImage`, `StopImagesOptions` from `pixi-effects` | the same names from `pixi-effects/present` (`Stop` and `StopSpec` stay in `pixi-effects`) |
|
|
19
|
+
|
|
20
|
+
A page that only maps `"pixi-effects"` still gets its stops reviewed and its PDF exported by `check` / `render`: they load `present.js` from beside the library.
|
|
21
|
+
|
|
22
|
+
**Changed (breaking): the API list for 0.29** (`docs/api-surface.txt` is the whole public surface, read from the sources and frozen by a test; the decisions are in `docs/superpowers/specs/2026-10-11-api-list-0.29.md`)
|
|
23
|
+
|
|
24
|
+
| before | now |
|
|
25
|
+
|---|---|
|
|
26
|
+
| `maskInverted: true` next to `mask: { …a layer… }` | `mask: { layer: { …the mask layer… }, invert: true }` (the one inverted-mask form, the same as `{ layer: 'name', invert: true }` for a named matte; `channel: 'luma'` works on a layer written in place too). The old key warns and says this. Inside a list of masks only names are allowed |
|
|
27
|
+
| `Controller` options `enableKeyboardShortcuts`, `showExportButton`, `present` | `keyboard`, `exportButton`, `presentButton` (the Presenter's names). An unknown `Controller` option now warns, with did-you-mean |
|
|
28
|
+
| `pixi-effects/controller` also exported `CONTROLLER_CSS`, `formatTime`, `frameToPercent`, `pxToFrame`, `pxToFraction`, `extensionForMimeType` | `Controller`, `ControllerOptions`, `ControllerTheme` only |
|
|
29
|
+
| the bins `pixi-effects-check`, `pixi-effects-render`, `pixi-effects-view` | `pixi-effects check|render|view` (the one bin; `npx pixi-effects-check` never worked) |
|
|
30
|
+
| `pixi-effects render --fail-on-warn` | `--strict`, the word `check` already used (the old flag says so) |
|
|
31
|
+
| `Movie.emit`, `audioSource`, `gainNode`; `Sequence.bindTimeline`, `collectAudio`, `absoluteStart`, `keepHidden`, `maskSequence`, `filters`, `updateSpace`, `syncFrame` in the type declarations | marked `@internal` and stripped from the declarations (the library still uses them) |
|
|
32
|
+
|
|
33
|
+
**Added**
|
|
34
|
+
|
|
35
|
+
- `movie.playUntil(seconds?)`: play and pause exactly at a time (`true` when it landed; `false` when a pause, a seek or a newer `playUntil` ended it first; no time = to the end). It is what `next(movie)` is made of, and the way to "play the intro, then wait".
|
|
36
|
+
- `movie.peek(fn)`: run a function that looks around (seeks, pictures) and put the playhead or the poster back; the seeks inside are not reported as `seeking` / `seeked`.
|
|
37
|
+
- `movie.snapshot(frame, { quality })` (JPEG quality) and `{ as: 'imageData' }` (the pixels, to measure or compare).
|
|
38
|
+
- `warnUnknownOptions(where, options, validNames)` is exported: the did-you-mean warning for an unknown option, for presets and layer types written outside the library.
|
|
39
|
+
- `animateText({ out: { preset, at: T } })`: the exit starts at composition second T (the pieces leave in the same wave and stay gone until the layer ends). Without `at` it is the end of the layer run backwards, as before; a warning says `out.at ≤ …` when the exit does not fit, or when T is before the entrance has finished.
|
|
40
|
+
- `pixi-effects render --help` and `pixi-effects view --help` (usage, exit 0), like `check`.
|
|
41
|
+
- A warning when a picture key (`filters`, `filterArea`, `mask`, `blendMode`, `threeD`, `hideBehindCamera`, `lit`, `castsShadows`) is put on a layer that is never drawn: an audio layer, a camera, a light (a light keeps `castsShadows`, its own switch). The key did nothing there, silently.
|
|
42
|
+
|
|
43
|
+
**Fixed**
|
|
44
|
+
|
|
45
|
+
- `NamedFilterType` lacked `'warp'`: `{ type: 'warp' }` was a TypeScript error though it worked at run time. The compiler now checks the type and the runtime filter tables against each other, both ways.
|
|
46
|
+
|
|
47
|
+
**Checked, not reproduced**
|
|
48
|
+
|
|
49
|
+
- The two bugs the old roadmap listed (an inline shape mask under a transition; a 4000 x 2400 `threeD` layer black on WebGPU) do not reproduce on this code. Real-browser tests pin both, on both backends.
|
|
50
|
+
|
|
51
|
+
**Docs**
|
|
52
|
+
|
|
53
|
+
- **The film guide says who it is for.** `direction.md` opens with a note for an AI in a browser chat (no shell, no files): this guide is not yours, follow `ai/CHAT.md`; you can still put a three-line plan in your reply and ask. The `llms.txt` line for it says "for an AI with a shell and files; a browser chat skips it".
|
|
54
|
+
|
|
3
55
|
## 0.28.2
|
|
4
56
|
|
|
5
57
|
**Added**
|
package/README.md
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
# pixi-effects
|
|
2
2
|
|
|
3
|
-
> **Status**: experimental — current release `0.
|
|
3
|
+
> **Status**: experimental — current release `0.29.0`. The API may still change between minor versions; see the [CHANGELOG](./CHANGELOG.md) for what each release changed.
|
|
4
4
|
|
|
5
5
|
**[Guide →](https://yjmtmtk.github.io/pixi-effects/guide/)** · **[Gallery →](https://yjmtmtk.github.io/pixi-effects/examples/gallery/)** · 52 portfolio pieces written as plain data by AI models · **[Examples →](https://yjmtmtk.github.io/pixi-effects/examples/)** · 15 numbered examples, a music lab + an in-browser playground.
|
|
6
6
|
|
|
@@ -21,14 +21,14 @@ Declarative composition and video rendering for the web. After Effects-style tim
|
|
|
21
21
|
- **Draw-on strokes and changing text** — `trimEnd` 0 → 1 draws a line, border or SVG path on; a keyframe `set: { text }` swaps a string and `visibleChars` is a typewriter.
|
|
22
22
|
- **Masks, transitions, chroma key** — inline masks; chroma key; eight scene transitions (`crossfade`, `wipe`, `iris`, `slide`, `dip`, `zoom`, `dissolve`, `luma`).
|
|
23
23
|
- **Presets** — `kenBurns` for stills, `withFade` for fade-in/out; `wiggle`, `stagger`, `animateText`, `followPath`, `particles` and `react` return keyframes or layers (seeded, so every render is the same).
|
|
24
|
-
- **Presentations** — `stops` in the composition pause the movie where you say; `Presenter` (`pixi-effects/
|
|
24
|
+
- **Presentations** — `stops` in the composition pause the movie where you say; `Presenter` (`pixi-effects/present`) moves on with arrow keys, a click or a swipe, with a page overview (G), a presenter view with notes and a timer (P), and `deck()` to lay out pages and steps. Export a deck as PDF (`exportPDF(movie)`, `pixi-effects render talk.html -o talk.pdf`). See the [Presenting guide](https://yjmtmtk.github.io/pixi-effects/guide/presenting.html).
|
|
25
25
|
- **Music written as text** — `{ type: 'audio', music: { bpm: 96, tracks: [{ inst: 'keys', notes: 'Cmaj7:4 Am7:4' }], drums: { kick: 'x...x...' } } }`: a tune with no audio file, played by a small built-in synthesiser (keys, pluck, pad, bass, lead, bell, music box, drums; chords by name, swing, fades, a ritardando). Deterministic, in the exported file at the same moment; an AI writes it as easily as a title.
|
|
26
26
|
- **Audio-reactive visuals** — `audioEnvelope('music.mp3')` analyses loudness, bass / mid / treble and the beats per frame; `react()` turns them into keyframes, so the picture follows the music and still renders identically.
|
|
27
27
|
- **2.5D layers & camera** — add `threeD: true`, `z`, `rotationX/Y` and a `{ type: 'camera' }` layer for parallax, flips and dolly zooms; no three.js needed.
|
|
28
28
|
- **three.js layer** *(optional)* — drop a real three.js scene in as a layer via `pixi-effects/three`; keyframes drive its objects (`three.cube.rotation.y`).
|
|
29
29
|
- **Built-in player UI — or your own** — a drop-in HTML5-`<video>`-style overlay controller (play, scrub, mute, volume, fullscreen, export-to-file) whose colours are one option (`theme: { accent: '#ff4d6d' }`); or build a player yourself on the movie's `<video>`-named events (`play pause ended seeking seeked volumechange error`).
|
|
30
|
-
- **MP4 / WebM / MOV export** — pick container and quality from the controller, call `movie.render()` from code, or render headless from the command line (`pixi-effects
|
|
31
|
-
- **A timeline you can read and scrub** — `movie.timelineChart()` draws every layer as a bar on a time axis; `pixi-effects
|
|
30
|
+
- **MP4 / WebM / MOV export** — pick container and quality from the controller, call `movie.render()` from code, or render headless from the command line (`pixi-effects render`).
|
|
31
|
+
- **A timeline you can read and scrub** — `movie.timelineChart()` draws every layer as a bar on a time axis; `pixi-effects view` opens the page with that timeline under it, zoomable, with a playhead you can drag.
|
|
32
32
|
- **Tiny dependency surface** — only `mediabunny` (runtime) plus PixiJS (a peer dep). three.js is an *optional* peer, needed only if you import `pixi-effects/three`.
|
|
33
33
|
|
|
34
34
|
## Install
|
|
@@ -49,8 +49,8 @@ Drop the imports into an [importmap](https://developer.mozilla.org/docs/Web/HTML
|
|
|
49
49
|
"imports": {
|
|
50
50
|
"pixi.js": "https://esm.sh/pixi.js@8.22.0?bundle-deps",
|
|
51
51
|
"mediabunny": "https://esm.sh/mediabunny",
|
|
52
|
-
"pixi-effects": "https://cdn.jsdelivr.net/npm/pixi-effects@0.
|
|
53
|
-
"pixi-effects/controller": "https://cdn.jsdelivr.net/npm/pixi-effects@0.
|
|
52
|
+
"pixi-effects": "https://cdn.jsdelivr.net/npm/pixi-effects@0.29.0/dist/index.js",
|
|
53
|
+
"pixi-effects/controller": "https://cdn.jsdelivr.net/npm/pixi-effects@0.29.0/dist/Controller.js"
|
|
54
54
|
}
|
|
55
55
|
}
|
|
56
56
|
</script>
|
|
@@ -61,7 +61,7 @@ Drop the imports into an [importmap](https://developer.mozilla.org/docs/Web/HTML
|
|
|
61
61
|
</script>
|
|
62
62
|
```
|
|
63
63
|
|
|
64
|
-
Load the `dist/` files **as they are** (jsDelivr's `/npm/…/dist/…`, or unpkg's `https://unpkg.com/pixi-effects@0.
|
|
64
|
+
Load the `dist/` files **as they are** (jsDelivr's `/npm/…/dist/…`, or unpkg's `https://unpkg.com/pixi-effects@0.29.0/dist/index.js`) rather than a CDN-rebundled build such as `esm.sh/pixi-effects` or jsDelivr's `+esm`: the entries (`pixi-effects`, `…/controller`, `…/three`) share internal chunks, which only works when each file is served untouched.
|
|
65
65
|
|
|
66
66
|
> **Using three.js?** Add two more entries (`three` and `pixi-effects/three`) to this importmap — see [Adding three.js](#adding-threejs-optional) below.
|
|
67
67
|
>
|
|
@@ -77,7 +77,7 @@ Add two more entries to the importmap above: three.js itself, and the `pixi-effe
|
|
|
77
77
|
"imports": {
|
|
78
78
|
"...": "(everything from the importmap above)",
|
|
79
79
|
"three": "https://esm.sh/three@0.178.0",
|
|
80
|
-
"pixi-effects/three": "https://cdn.jsdelivr.net/npm/pixi-effects@0.
|
|
80
|
+
"pixi-effects/three": "https://cdn.jsdelivr.net/npm/pixi-effects@0.29.0/dist/three.js"
|
|
81
81
|
}
|
|
82
82
|
}
|
|
83
83
|
</script>
|
|
@@ -175,7 +175,7 @@ This library is designed to be written by AI: a video is plain data, and every m
|
|
|
175
175
|
- [`skills/pixi-effects/reference/cheatsheet.md`](./skills/pixi-effects/reference/cheatsheet.md), [`recipes.md`](./skills/pixi-effects/reference/recipes.md) (tested), [`pitfalls.md`](./skills/pixi-effects/reference/pitfalls.md), and a starter [`skills/pixi-effects/template.html`](./skills/pixi-effects/template.html).
|
|
176
176
|
|
|
177
177
|
- **Look at a page with its timeline, and scrub one with the other:** `npx pixi-effects view my-video.html` (it also watches the folder: when the work changes it shows "Updated hh:mm:ss — reload (R)" and never switches by itself; reload comes back to the same frame) (or `node ai/tools/view.mjs …`) opens your browser on a viewer: the page on top, the timeline of every layer under it with a playhead that follows the movie. Click or drag the timeline to seek, click a layer's name to jump to where it starts, Space plays, ← / → step a frame, + / − (or Ctrl/⌘ + wheel) zoom, the names stay in place. For the human who wants to see what the AI made.
|
|
178
|
-
- **Render a page to a video file, headless:** `npx pixi-effects render my-video.html -o my-video.mp4` (or `node ai/tools/render.mjs …`; Node ≥ 22 and Chrome installed, no dependencies). The container follows the extension (`mp4 webm mov mkv`); `--quality very-low…very-high`, `--query lang=ja` (added to the page URL), `--
|
|
178
|
+
- **Render a page to a video file, headless:** `npx pixi-effects render my-video.html -o my-video.mp4` (or `node ai/tools/render.mjs …`; Node ≥ 22 and Chrome installed, no dependencies). The container follows the extension (`mp4 webm mov mkv`); `--quality very-low…very-high`, `--query lang=ja` (added to the page URL), `--strict` (exit 1 when the page logged a warning), `--quiet`. It waits for `window.__ready`, runs `movie.render()` and streams the file to disk; exit 0 = written, 1 = the page or the render failed (no file). For scripts, CI and batches; `pixi-effects check` below is the review.
|
|
179
179
|
- **A talk as a PDF:** `npx pixi-effects render my-talk.html -o my-talk.pdf` (one page per page of a `deck()` / `stops` movie; `--all-stops` makes a page of every step). The review tool writes `stops.png` for such a page, one picture per stop.
|
|
180
180
|
- **One-command review for the AI that wrote the page:** `npx pixi-effects check my-video.html` (or `node ai/tools/check.mjs my-video.html`; Node ≥ 22 and Chrome installed, no dependencies). It opens the page in its own headless Chrome and reports warnings, layout (`movie.inspect` over the whole timeline), the soundtrack (`movie.inspectAudio`) and a real export decoded again, and writes a contact sheet PNG and a `timeline.html` (every layer as a bar on a time axis) to look at. Exit code 0 / 1.
|
|
181
181
|
|
|
@@ -184,7 +184,7 @@ They ship in the npm package (`node_modules/pixi-effects/ai/`).
|
|
|
184
184
|
## Documentation
|
|
185
185
|
|
|
186
186
|
- [**DSL reference**](./docs/dsl.md) — composition, sequences, 3D layers & camera, three.js layer, keyframes, expressions, filters
|
|
187
|
-
- [**API reference**](./docs/api.md) — `Movie`, `Controller`, `pixi-effects/
|
|
187
|
+
- [**API reference**](./docs/api.md) — `Movie`, `Controller`, `pixi-effects/present`, `pixi-effects/three`, events, render options
|
|
188
188
|
- [**Examples**](./examples/) — runnable HTML files (read in order):
|
|
189
189
|
- `01-hello.html` — minimum viable composition
|
|
190
190
|
- `02-keyframes.html` — keyframes, easings, expressions
|
package/ai/chat-template.html
CHANGED
|
@@ -59,17 +59,17 @@
|
|
|
59
59
|
"imports": {
|
|
60
60
|
"pixi.js": "https://cdn.jsdelivr.net/npm/pixi.js@8.22.0/dist/pixi.min.mjs",
|
|
61
61
|
"mediabunny": "https://cdn.jsdelivr.net/npm/mediabunny@1.61.3/+esm",
|
|
62
|
-
"pixi-effects": "https://cdn.jsdelivr.net/npm/pixi-effects@0.
|
|
63
|
-
"pixi-effects/controller": "https://cdn.jsdelivr.net/npm/pixi-effects@0.
|
|
64
|
-
"pixi-effects/
|
|
62
|
+
"pixi-effects": "https://cdn.jsdelivr.net/npm/pixi-effects@0.29.0/dist/index.js",
|
|
63
|
+
"pixi-effects/controller": "https://cdn.jsdelivr.net/npm/pixi-effects@0.29.0/dist/Controller.js",
|
|
64
|
+
"pixi-effects/present": "https://cdn.jsdelivr.net/npm/pixi-effects@0.29.0/dist/present.js"
|
|
65
65
|
}
|
|
66
66
|
}
|
|
67
67
|
</script>
|
|
68
68
|
|
|
69
69
|
<script type="module">
|
|
70
|
-
import { Movie, kenBurns, withFade, wiggle, stagger, animateText, followPath, particles
|
|
70
|
+
import { Movie, kenBurns, withFade, wiggle, stagger, animateText, followPath, particles } from 'pixi-effects';
|
|
71
71
|
import { Controller } from 'pixi-effects/controller';
|
|
72
|
-
// A talk instead of a video: import { Presenter } from 'pixi-effects/
|
|
72
|
+
// A talk instead of a video: import { deck, Presenter } from 'pixi-effects/present'; use deck({ pages: [...] }) and new Presenter(movie, { canvas }) instead of the Controller.
|
|
73
73
|
|
|
74
74
|
// ===================== EDIT FROM HERE =====================
|
|
75
75
|
const W = 1280, H = 720, FPS = 30, DURATION = 6;
|
package/ai/tools/check.mjs
CHANGED
|
@@ -286,6 +286,18 @@ const waveformScript = (audio, duration) => `(() => {
|
|
|
286
286
|
// ───────────────────────────── the check ─────────────────────────────
|
|
287
287
|
|
|
288
288
|
export const sleep = ms => new Promise(r => setTimeout(r, ms));
|
|
289
|
+
|
|
290
|
+
/**
|
|
291
|
+
* JavaScript, as text, for the page: it resolves to the page's own `pixi-effects/present` module (stops, pages, PDF). The page's import map names it
|
|
292
|
+
* (`pixi-effects/present`); a page that only maps `pixi-effects` gets the `present.js` that sits beside the library.
|
|
293
|
+
*/
|
|
294
|
+
export const LOAD_PRESENT = `(async () => {
|
|
295
|
+
try { return await import('pixi-effects/present'); } catch (e) { /* not in the import map: look beside the library */ }
|
|
296
|
+
let lib = null;
|
|
297
|
+
try { lib = JSON.parse(document.querySelector('script[type="importmap"]').textContent).imports['pixi-effects']; } catch (e) { /* none */ }
|
|
298
|
+
if (!lib) throw new Error('the page has no "pixi-effects" in its import map');
|
|
299
|
+
return import(new URL('present.js', new URL(lib, document.baseURI)).href);
|
|
300
|
+
})()`;
|
|
289
301
|
/** A path for display: relative to the cwd when it is inside it, absolute otherwise. */
|
|
290
302
|
export const shown = f => { const r = path.relative(process.cwd(), f); return r.startsWith('..') || path.isAbsolute(r) ? f : r; };
|
|
291
303
|
const kb = n => (n >= 1048576 ? `${(n / 1048576).toFixed(2)} MB` : `${Math.max(1, Math.round(n / 1024))} KB`);
|
|
@@ -404,11 +416,13 @@ export async function runCheck(opts, log = console.log) {
|
|
|
404
416
|
}
|
|
405
417
|
|
|
406
418
|
// a presentation (composition.stops): one picture of every stop, in order, so the pages and steps can be read at a glance
|
|
407
|
-
const stops = await cdp.eval(`(() => { const s = movie.stops || []; return s.length ? { count: s.length, pages:
|
|
419
|
+
const stops = await cdp.eval(`(() => { const s = movie.stops || []; return s.length ? { count: s.length, pages: new Set(s.map(x => x.pageIndex)).size, items: s.map(x => ({ at: Math.round(x.at * 100) / 100, frame: x.frame, page: x.page, pageStart: x.pageStart, notes: !!x.notes, pdf: x.pdf })) } : null; })()`).catch(() => null);
|
|
408
420
|
if (stops) {
|
|
409
421
|
report.stops = stops;
|
|
410
422
|
// is the picture at each stop still changing? (the audience, the page overview and a PDF would see a half-finished animation)
|
|
411
|
-
|
|
423
|
+
let skipped = '';
|
|
424
|
+
const settled = await cdp.eval(`${LOAD_PRESENT}.then(p => p.inspectStops(movie))`).catch(e => { skipped = String((e && e.message) || e); return null; });
|
|
425
|
+
if (!settled) report.stops.reviewSkipped = `${skipped || 'no answer'} (the page needs "pixi-effects/present": ".../dist/present.js" in its import map, from the same version as the library)`;
|
|
412
426
|
if (settled) {
|
|
413
427
|
report.stops.review = settled.issues;
|
|
414
428
|
report.stops.moving = settled.stops.map(s => Math.round(s.moving * 10000) / 10000);
|
|
@@ -529,7 +543,8 @@ function finish(report, outDir, log) {
|
|
|
529
543
|
}
|
|
530
544
|
if (report.stops) {
|
|
531
545
|
const s = report.stops;
|
|
532
|
-
L.push(` stops ${s.count} stop(s) on ${s.pages} page(s) — stops.png shows each one in order; the picture at a stop is what the audience sees while it waits`)
|
|
546
|
+
L.push(` stops ${s.count} stop(s) on ${s.pages} page(s) — stops.png shows each one in order; the picture at a stop is what the audience sees while it waits`)
|
|
547
|
+
if (s.reviewSkipped) L.push(` not reviewed for stops that are still moving: ${s.reviewSkipped}`);
|
|
533
548
|
if (s.review?.length) {
|
|
534
549
|
L.push(` review ${s.review.length} stop(s) where the picture is still changing (may be on purpose, e.g. something always moving; use --strict to fail on them):`);
|
|
535
550
|
for (const r of s.review.slice(0, 4)) L.push(` - ${r}`);
|
|
@@ -7,7 +7,7 @@
|
|
|
7
7
|
* npx pixi-effects view my-video.html open it in a browser with a timeline
|
|
8
8
|
*
|
|
9
9
|
* Everything after the command goes to the tool unchanged (`check.mjs`, `render.mjs`, `view.mjs`; their own headers list every option), and so do the
|
|
10
|
-
* exit code and the output.
|
|
10
|
+
* exit code and the output. It is the package's only bin (the older `pixi-effects-check|render|view` are gone).
|
|
11
11
|
*/
|
|
12
12
|
import { spawn } from 'node:child_process';
|
|
13
13
|
import { realpathSync } from 'node:fs';
|
package/ai/tools/render.mjs
CHANGED
|
@@ -6,7 +6,7 @@
|
|
|
6
6
|
*
|
|
7
7
|
* It starts a private static server and a private headless Chrome, opens the page, waits for `window.__ready === true`
|
|
8
8
|
* (the contract of skills/pixi-effects/template.html), runs `movie.render()` in the page and streams the file to disk. Nothing is decoded or
|
|
9
|
-
* reviewed: that is `pixi-effects
|
|
9
|
+
* reviewed: that is `pixi-effects check`'s job. Use this one to produce the file (a script, CI, a batch).
|
|
10
10
|
*
|
|
11
11
|
* Needs: Node >= 22 (built-in WebSocket), Chrome / Chromium installed (or CHROME=PATH / --chrome PATH). No npm dependencies.
|
|
12
12
|
* Exit code: 0 = the file was written, 1 = the page or the render failed (no file), 2 = bad usage.
|
|
@@ -17,7 +17,7 @@
|
|
|
17
17
|
* --draft (for looking: half size, low quality, no motion blur; a --quality you give still wins) ·
|
|
18
18
|
* --motion-blur SAMPLES (2-64: each frame is drawn that many times over the shutter and averaged; overrides the page's own motionBlur) ·
|
|
19
19
|
* --shutter FRACTION (with --motion-blur: how long the shutter is open, 0-1 of a frame, default 0.5) ·
|
|
20
|
-
* --video-codec C (avc hevc vp9 av1 vp8) · --video-bitrate B (a quality or bits a second: 8M, 800k) · --audio-codec C · --query "a=1&b=2" (added to the page URL) · --
|
|
20
|
+
* --video-codec C (avc hevc vp9 av1 vp8) · --video-bitrate B (a quality or bits a second: 8M, 800k) · --audio-codec C · --query "a=1&b=2" (added to the page URL) · --strict (exit 1 when the page
|
|
21
21
|
* logged a warning; the file is still written) · --quiet (no progress line) · --timeout SECONDS (default 900) ·
|
|
22
22
|
* --root DIR (static server root; default: the nearest folder above the page with dist/) · --chrome PATH
|
|
23
23
|
*/
|
|
@@ -25,7 +25,7 @@ import fs from 'node:fs';
|
|
|
25
25
|
import os from 'node:os';
|
|
26
26
|
import path from 'node:path';
|
|
27
27
|
import { pathToFileURL } from 'node:url';
|
|
28
|
-
import { findChrome, findRoot, serve, launchChrome, shown, sleep } from './check.mjs';
|
|
28
|
+
import { findChrome, findRoot, serve, launchChrome, shown, sleep, LOAD_PRESENT } from './check.mjs';
|
|
29
29
|
|
|
30
30
|
const FORMATS = ['mp4', 'webm', 'mov', 'mkv', 'wav', 'ogg', 'pdf'];
|
|
31
31
|
const SOUND_ONLY = ['wav', 'ogg'];
|
|
@@ -43,12 +43,15 @@ export function defaultOutput(page, format) {
|
|
|
43
43
|
return path.resolve(path.basename(page).replace(/\.[^.]+$/, '') + '.' + format);
|
|
44
44
|
}
|
|
45
45
|
|
|
46
|
+
export const USAGE = 'usage: node ai/tools/render.mjs <page.html> [-o out.mp4] [--format mp4|webm|mov|mkv|pdf] [--range A:B | --scene NAME] [--scale S] [--draft] [--quality very-low|low|medium|high|very-high] [--query a=1] [--strict] [--quiet] [--timeout S] [--root DIR] [--chrome PATH]';
|
|
47
|
+
|
|
46
48
|
export function parseRenderArgs(argv) {
|
|
47
|
-
const o = { range: null, scene: null, scale: null, draft: false, qualityGiven: false, page: null, out: null, format: null, quality: 'high', videoCodec: null, videoBitrate: null, audioCodec: null, allStops: false, motionBlur: null, shutter: null, query: null,
|
|
49
|
+
const o = { range: null, scene: null, scale: null, draft: false, qualityGiven: false, page: null, out: null, format: null, quality: 'high', videoCodec: null, videoBitrate: null, audioCodec: null, allStops: false, motionBlur: null, shutter: null, query: null, strict: false, quiet: false, timeout: 900, root: null, chrome: null };
|
|
48
50
|
const need = (i, name) => { if (i + 1 >= argv.length) throw new Error(`${name} needs a value`); return argv[i + 1]; };
|
|
49
51
|
for (let i = 0; i < argv.length; i++) {
|
|
50
52
|
const a = argv[i];
|
|
51
|
-
if (a === '
|
|
53
|
+
if (a === '--help' || a === '-h') o.help = true;
|
|
54
|
+
else if (a === '-o' || a === '--out') o.out = need(i++, a);
|
|
52
55
|
else if (a === '--format') {
|
|
53
56
|
o.format = need(i++, a).toLowerCase();
|
|
54
57
|
if (!FORMATS.includes(o.format)) throw new Error(`--format must be mp4, webm, mov, mkv, wav, ogg or pdf (got "${o.format}")`);
|
|
@@ -79,7 +82,8 @@ export function parseRenderArgs(argv) {
|
|
|
79
82
|
} else if (a === '--draft') o.draft = true;
|
|
80
83
|
else if (a === '--query') o.query = need(i++, a).replace(/^\?/, '');
|
|
81
84
|
else if (a === '--all-stops') o.allStops = true;
|
|
82
|
-
else if (a === '--
|
|
85
|
+
else if (a === '--strict') o.strict = true;
|
|
86
|
+
else if (a === '--fail-on-warn') throw new Error('--fail-on-warn is now --strict (the same word as in check: a warning, or anything it would only list, fails the run)');
|
|
83
87
|
else if (a === '--quiet') o.quiet = true;
|
|
84
88
|
else if (a === '--timeout') o.timeout = Math.max(10, Number(need(i++, a)) || 900);
|
|
85
89
|
else if (a === '--root') o.root = need(i++, a);
|
|
@@ -109,7 +113,7 @@ const renderScript = (format, quality, videoCodec, audioCodec, motionBlur, shutt
|
|
|
109
113
|
const video = { ${[videoBitrate ? `bitrate: ${JSON.stringify(/^\d+(\.\d+)?$/.test(videoBitrate) ? Number(videoBitrate) : videoBitrate)}` : part.draft && !part.qualityGiven ? null : `bitrate: ${JSON.stringify(quality)}`, videoCodec ? `codec: ${JSON.stringify(videoCodec)}` : null].filter(Boolean).join(', ')} };
|
|
110
114
|
const audio = { bitrate: ${JSON.stringify(quality)}${audioCodec ? `, codec: ${JSON.stringify(audioCodec)}` : ''} };
|
|
111
115
|
const blob = ${JSON.stringify(format)} === 'pdf'
|
|
112
|
-
? await
|
|
116
|
+
? await (${LOAD_PRESENT}).catch(e => { throw new Error('a PDF needs pixi-effects/present in the page (add "pixi-effects/present": ".../dist/present.js" to its import map, from the same version as the library): ' + ((e && e.message) || e)); }).then(p => p.exportPDF(movie, { which: ${allStops ? "'stops'" : "'pages'"}, title: document.title }))
|
|
113
117
|
: await movie.render({ format: ${JSON.stringify(format)}, ${SOUND_ONLY.includes(format) ? '' : 'video, '}audio${part.range ? `, range: [${part.range[0] ?? 0}, ${part.range[1] ?? 'movie.duration'}]` : ''}${part.scene ? `, range: ${JSON.stringify(part.scene)}` : ''}${part.scale ? `, scale: ${part.scale}` : ''}${part.draft ? ', draft: true' : ''}${motionBlur ? `, motionBlur: { samples: ${motionBlur}${shutter ? `, shutter: ${shutter}` : ''} }` : ''} });
|
|
114
118
|
const res = await fetch(${JSON.stringify(UPLOAD)}, { method: 'PUT', body: blob });
|
|
115
119
|
if (!res.ok) throw new Error('could not hand the file to the command (' + res.status + ')');
|
|
@@ -209,8 +213,9 @@ if (process.argv[1] && import.meta.url === pathToFileURL(fs.realpathSync(process
|
|
|
209
213
|
try {
|
|
210
214
|
if (typeof WebSocket === 'undefined') throw new Error('Node >= 22 is needed (built-in WebSocket)');
|
|
211
215
|
const opts = parseRenderArgs(process.argv.slice(2));
|
|
216
|
+
if (opts.help) { console.log(USAGE); process.exit(0); }
|
|
212
217
|
if (!opts.page) {
|
|
213
|
-
console.error(
|
|
218
|
+
console.error(USAGE);
|
|
214
219
|
process.exit(2);
|
|
215
220
|
}
|
|
216
221
|
let last = -1;
|
|
@@ -227,7 +232,7 @@ if (process.argv[1] && import.meta.url === pathToFileURL(fs.realpathSync(process
|
|
|
227
232
|
process.exit(1);
|
|
228
233
|
}
|
|
229
234
|
console.log(`${shown(r.file)} ${kb(r.bytes)} · ${r.duration} s · ${SOUND_ONLY.includes(opts.format) ? 'sound only' : `${r.width}×${r.height} @ ${r.frameRate} fps`} · ${opts.format} · rendered in ${r.seconds} s`);
|
|
230
|
-
process.exit(opts.
|
|
235
|
+
process.exit(opts.strict && r.logs.length ? 1 : 0);
|
|
231
236
|
} catch (e) {
|
|
232
237
|
console.error(`pixi-effects render failed: ${e.message}`);
|
|
233
238
|
process.exit(2);
|
package/ai/tools/view.mjs
CHANGED
|
@@ -26,12 +26,15 @@ import { findRoot, serve } from './check.mjs';
|
|
|
26
26
|
|
|
27
27
|
export const VIEWER = '/__viewer';
|
|
28
28
|
|
|
29
|
+
export const USAGE = 'usage: node ai/tools/view.mjs <page.html> [--port N] [--no-open] [--query a=1] [--root DIR]';
|
|
30
|
+
|
|
29
31
|
export function parseViewArgs(argv) {
|
|
30
32
|
const o = { page: null, port: 0, open: true, query: null, root: null };
|
|
31
33
|
const need = (i, name) => { if (i + 1 >= argv.length) throw new Error(`${name} needs a value`); return argv[i + 1]; };
|
|
32
34
|
for (let i = 0; i < argv.length; i++) {
|
|
33
35
|
const a = argv[i];
|
|
34
|
-
if (a === '--
|
|
36
|
+
if (a === '--help' || a === '-h') o.help = true;
|
|
37
|
+
else if (a === '--port') o.port = Math.max(0, Math.round(Number(need(i++, a))) || 0);
|
|
35
38
|
else if (a === '--no-open') o.open = false;
|
|
36
39
|
else if (a === '--query') o.query = need(i++, a).replace(/^\?/, '');
|
|
37
40
|
else if (a === '--root') o.root = need(i++, a);
|
|
@@ -343,8 +346,9 @@ export async function startViewer(opts) {
|
|
|
343
346
|
if (process.argv[1] && import.meta.url === pathToFileURL(fs.realpathSync(process.argv[1])).href) { // the real path: npm starts a bin through a symlink
|
|
344
347
|
try {
|
|
345
348
|
const opts = parseViewArgs(process.argv.slice(2));
|
|
349
|
+
if (opts.help) { console.log(USAGE); process.exit(0); }
|
|
346
350
|
if (!opts.page) {
|
|
347
|
-
console.error(
|
|
351
|
+
console.error(USAGE);
|
|
348
352
|
process.exit(2);
|
|
349
353
|
}
|
|
350
354
|
const { url } = await startViewer(opts);
|
|
@@ -0,0 +1,60 @@
|
|
|
1
|
+
import { Container } from 'pixi.js';
|
|
2
|
+
import { S as SequenceSpec, C as CompositionShape } from './types-BzIB65Vk.cjs';
|
|
3
|
+
|
|
4
|
+
/**
|
|
5
|
+
* Resolves a routed keyframe path to a concrete tween target.
|
|
6
|
+
* `path` is everything after the registered prefix + dot (for
|
|
7
|
+
* `three.cube.rotation.y` under prefix `three`, path = `cube.rotation.y`).
|
|
8
|
+
* Return null to skip the key (the router is expected to have warned).
|
|
9
|
+
*/
|
|
10
|
+
type PathRouter = (path: string) => {
|
|
11
|
+
target: object;
|
|
12
|
+
prop: string;
|
|
13
|
+
} | null;
|
|
14
|
+
type PathRouters = Record<string, PathRouter>;
|
|
15
|
+
|
|
16
|
+
/** Variables available to expression evaluation. */
|
|
17
|
+
interface Scope {
|
|
18
|
+
w: number;
|
|
19
|
+
h: number;
|
|
20
|
+
W: number;
|
|
21
|
+
H: number;
|
|
22
|
+
GW: number;
|
|
23
|
+
GH: number;
|
|
24
|
+
contain: number;
|
|
25
|
+
cover: number;
|
|
26
|
+
t: number;
|
|
27
|
+
d: number;
|
|
28
|
+
T: number;
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
declare abstract class Sequence {
|
|
32
|
+
spec: SequenceSpec;
|
|
33
|
+
parent: CompositionShape | null;
|
|
34
|
+
root: CompositionShape;
|
|
35
|
+
target: Container | null;
|
|
36
|
+
intrinsicWidth: number;
|
|
37
|
+
intrinsicHeight: number;
|
|
38
|
+
at: number;
|
|
39
|
+
duration: number | undefined;
|
|
40
|
+
constructor(spec: SequenceSpec, parent: CompositionShape | null, root: CompositionShape);
|
|
41
|
+
abstract build(): Promise<void>;
|
|
42
|
+
buildFilters(): void;
|
|
43
|
+
scope(): Scope;
|
|
44
|
+
/**
|
|
45
|
+
* Prefix routers contributed to the keyframe pipeline (e.g. `three.` in
|
|
46
|
+
* pixi-effects/three). Base sequences route nothing extra.
|
|
47
|
+
*/
|
|
48
|
+
protected pathRouters(): PathRouters;
|
|
49
|
+
/**
|
|
50
|
+
* The `initial` and `keyframes` that go onto the display object. A layer whose `time` runs a clock (video, composition) takes `time`
|
|
51
|
+
* out of them: it is not a property of the display object.
|
|
52
|
+
*/
|
|
53
|
+
protected displayProps(): {
|
|
54
|
+
initial: SequenceSpec['initial'];
|
|
55
|
+
keyframes: SequenceSpec['keyframes'];
|
|
56
|
+
};
|
|
57
|
+
destroy(): void;
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
export { type PathRouters as P, Sequence as S };
|
|
@@ -0,0 +1,60 @@
|
|
|
1
|
+
import { Container } from 'pixi.js';
|
|
2
|
+
import { S as SequenceSpec, C as CompositionShape } from './types-BzIB65Vk.js';
|
|
3
|
+
|
|
4
|
+
/**
|
|
5
|
+
* Resolves a routed keyframe path to a concrete tween target.
|
|
6
|
+
* `path` is everything after the registered prefix + dot (for
|
|
7
|
+
* `three.cube.rotation.y` under prefix `three`, path = `cube.rotation.y`).
|
|
8
|
+
* Return null to skip the key (the router is expected to have warned).
|
|
9
|
+
*/
|
|
10
|
+
type PathRouter = (path: string) => {
|
|
11
|
+
target: object;
|
|
12
|
+
prop: string;
|
|
13
|
+
} | null;
|
|
14
|
+
type PathRouters = Record<string, PathRouter>;
|
|
15
|
+
|
|
16
|
+
/** Variables available to expression evaluation. */
|
|
17
|
+
interface Scope {
|
|
18
|
+
w: number;
|
|
19
|
+
h: number;
|
|
20
|
+
W: number;
|
|
21
|
+
H: number;
|
|
22
|
+
GW: number;
|
|
23
|
+
GH: number;
|
|
24
|
+
contain: number;
|
|
25
|
+
cover: number;
|
|
26
|
+
t: number;
|
|
27
|
+
d: number;
|
|
28
|
+
T: number;
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
declare abstract class Sequence {
|
|
32
|
+
spec: SequenceSpec;
|
|
33
|
+
parent: CompositionShape | null;
|
|
34
|
+
root: CompositionShape;
|
|
35
|
+
target: Container | null;
|
|
36
|
+
intrinsicWidth: number;
|
|
37
|
+
intrinsicHeight: number;
|
|
38
|
+
at: number;
|
|
39
|
+
duration: number | undefined;
|
|
40
|
+
constructor(spec: SequenceSpec, parent: CompositionShape | null, root: CompositionShape);
|
|
41
|
+
abstract build(): Promise<void>;
|
|
42
|
+
buildFilters(): void;
|
|
43
|
+
scope(): Scope;
|
|
44
|
+
/**
|
|
45
|
+
* Prefix routers contributed to the keyframe pipeline (e.g. `three.` in
|
|
46
|
+
* pixi-effects/three). Base sequences route nothing extra.
|
|
47
|
+
*/
|
|
48
|
+
protected pathRouters(): PathRouters;
|
|
49
|
+
/**
|
|
50
|
+
* The `initial` and `keyframes` that go onto the display object. A layer whose `time` runs a clock (video, composition) takes `time`
|
|
51
|
+
* out of them: it is not a property of the display object.
|
|
52
|
+
*/
|
|
53
|
+
protected displayProps(): {
|
|
54
|
+
initial: SequenceSpec['initial'];
|
|
55
|
+
keyframes: SequenceSpec['keyframes'];
|
|
56
|
+
};
|
|
57
|
+
destroy(): void;
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
export { type PathRouters as P, Sequence as S };
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
'use strict';
|
|
2
|
+
|
|
3
|
+
var chunkWHNADXXG_cjs = require('./chunk-WHNADXXG.cjs');
|
|
4
|
+
require('./chunk-ZVUO325O.cjs');
|
|
5
|
+
require('./chunk-2DXPTKQZ.cjs');
|
|
6
|
+
require('./chunk-LYOKH7KE.cjs');
|
|
7
|
+
require('./chunk-TWZNOUM7.cjs');
|
|
8
|
+
|
|
9
|
+
|
|
10
|
+
|
|
11
|
+
Object.defineProperty(exports, "CompositionSequence", {
|
|
12
|
+
enumerable: true,
|
|
13
|
+
get: function () { return chunkWHNADXXG_cjs.CompositionSequence; }
|
|
14
|
+
});
|
|
15
|
+
//# sourceMappingURL=Composition-MUKR3FYD.cjs.map
|
|
16
|
+
//# sourceMappingURL=Composition-MUKR3FYD.cjs.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":[],"names":[],"mappings":"","file":"Composition-
|
|
1
|
+
{"version":3,"sources":[],"names":[],"mappings":"","file":"Composition-MUKR3FYD.cjs"}
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
export { CompositionSequence } from './chunk-A3Q3SDSH.js';
|
|
2
|
+
import './chunk-ZAXYPXKW.js';
|
|
3
|
+
import './chunk-4KB3GUEK.js';
|
|
4
|
+
import './chunk-RCVZX2JP.js';
|
|
5
|
+
import './chunk-BXOCEZ4U.js';
|
|
6
|
+
//# sourceMappingURL=Composition-RJGA7KDU.js.map
|
|
7
|
+
//# sourceMappingURL=Composition-RJGA7KDU.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":[],"names":[],"mappings":"","file":"Composition-
|
|
1
|
+
{"version":3,"sources":[],"names":[],"mappings":"","file":"Composition-RJGA7KDU.js"}
|