@motion-script/web 0.1.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 (262) hide show
  1. package/README.md +47 -0
  2. package/dist/audio/player.d.ts +43 -0
  3. package/dist/audio/player.d.ts.map +1 -0
  4. package/dist/audio/player.js +165 -0
  5. package/dist/audio/player.js.map +1 -0
  6. package/dist/effects/bloom.d.ts +19 -0
  7. package/dist/effects/bloom.d.ts.map +1 -0
  8. package/dist/effects/bloom.js +64 -0
  9. package/dist/effects/bloom.js.map +1 -0
  10. package/dist/effects/blur.d.ts +8 -0
  11. package/dist/effects/blur.d.ts.map +1 -0
  12. package/dist/effects/blur.js +12 -0
  13. package/dist/effects/blur.js.map +1 -0
  14. package/dist/effects/bulge-pinch.d.ts +20 -0
  15. package/dist/effects/bulge-pinch.d.ts.map +1 -0
  16. package/dist/effects/bulge-pinch.js +86 -0
  17. package/dist/effects/bulge-pinch.js.map +1 -0
  18. package/dist/effects/chromatic-aberration.d.ts +19 -0
  19. package/dist/effects/chromatic-aberration.d.ts.map +1 -0
  20. package/dist/effects/chromatic-aberration.js +59 -0
  21. package/dist/effects/chromatic-aberration.js.map +1 -0
  22. package/dist/effects/effect.d.ts +32 -0
  23. package/dist/effects/effect.d.ts.map +1 -0
  24. package/dist/effects/effect.js +22 -0
  25. package/dist/effects/effect.js.map +1 -0
  26. package/dist/effects/grayscale.d.ts +12 -0
  27. package/dist/effects/grayscale.d.ts.map +1 -0
  28. package/dist/effects/grayscale.js +31 -0
  29. package/dist/effects/grayscale.js.map +1 -0
  30. package/dist/effects/index.d.ts +13 -0
  31. package/dist/effects/index.d.ts.map +1 -0
  32. package/dist/effects/index.js +13 -0
  33. package/dist/effects/index.js.map +1 -0
  34. package/dist/effects/pixelate.d.ts +23 -0
  35. package/dist/effects/pixelate.d.ts.map +1 -0
  36. package/dist/effects/pixelate.js +37 -0
  37. package/dist/effects/pixelate.js.map +1 -0
  38. package/dist/effects/registry.d.ts +17 -0
  39. package/dist/effects/registry.d.ts.map +1 -0
  40. package/dist/effects/registry.js +56 -0
  41. package/dist/effects/registry.js.map +1 -0
  42. package/dist/effects/sksl-cache.d.ts +6 -0
  43. package/dist/effects/sksl-cache.d.ts.map +1 -0
  44. package/dist/effects/sksl-cache.js +21 -0
  45. package/dist/effects/sksl-cache.js.map +1 -0
  46. package/dist/effects/sksl-layer.d.ts +30 -0
  47. package/dist/effects/sksl-layer.d.ts.map +1 -0
  48. package/dist/effects/sksl-layer.js +82 -0
  49. package/dist/effects/sksl-layer.js.map +1 -0
  50. package/dist/effects/texture.d.ts +31 -0
  51. package/dist/effects/texture.d.ts.map +1 -0
  52. package/dist/effects/texture.js +66 -0
  53. package/dist/effects/texture.js.map +1 -0
  54. package/dist/effects/vintage.d.ts +20 -0
  55. package/dist/effects/vintage.d.ts.map +1 -0
  56. package/dist/effects/vintage.js +47 -0
  57. package/dist/effects/vintage.js.map +1 -0
  58. package/dist/effects/zoom.d.ts +20 -0
  59. package/dist/effects/zoom.d.ts.map +1 -0
  60. package/dist/effects/zoom.js +65 -0
  61. package/dist/effects/zoom.js.map +1 -0
  62. package/dist/exporter.d.ts +24 -0
  63. package/dist/exporter.d.ts.map +1 -0
  64. package/dist/exporter.js +177 -0
  65. package/dist/exporter.js.map +1 -0
  66. package/dist/fills/conic-gradient.d.ts +12 -0
  67. package/dist/fills/conic-gradient.d.ts.map +1 -0
  68. package/dist/fills/conic-gradient.js +44 -0
  69. package/dist/fills/conic-gradient.js.map +1 -0
  70. package/dist/fills/filters/alpha.d.ts +9 -0
  71. package/dist/fills/filters/alpha.d.ts.map +1 -0
  72. package/dist/fills/filters/alpha.js +21 -0
  73. package/dist/fills/filters/alpha.js.map +1 -0
  74. package/dist/fills/filters/blur.d.ts +9 -0
  75. package/dist/fills/filters/blur.d.ts.map +1 -0
  76. package/dist/fills/filters/blur.js +12 -0
  77. package/dist/fills/filters/blur.js.map +1 -0
  78. package/dist/fills/filters/color-adjustment.d.ts +14 -0
  79. package/dist/fills/filters/color-adjustment.d.ts.map +1 -0
  80. package/dist/fills/filters/color-adjustment.js +147 -0
  81. package/dist/fills/filters/color-adjustment.js.map +1 -0
  82. package/dist/fills/filters/color-matrix.d.ts +9 -0
  83. package/dist/fills/filters/color-matrix.d.ts.map +1 -0
  84. package/dist/fills/filters/color-matrix.js +14 -0
  85. package/dist/fills/filters/color-matrix.js.map +1 -0
  86. package/dist/fills/filters/curves.d.ts +9 -0
  87. package/dist/fills/filters/curves.d.ts.map +1 -0
  88. package/dist/fills/filters/curves.js +89 -0
  89. package/dist/fills/filters/curves.js.map +1 -0
  90. package/dist/fills/filters/exposure.d.ts +9 -0
  91. package/dist/fills/filters/exposure.d.ts.map +1 -0
  92. package/dist/fills/filters/exposure.js +22 -0
  93. package/dist/fills/filters/exposure.js.map +1 -0
  94. package/dist/fills/filters/filter.d.ts +17 -0
  95. package/dist/fills/filters/filter.d.ts.map +1 -0
  96. package/dist/fills/filters/filter.js +16 -0
  97. package/dist/fills/filters/filter.js.map +1 -0
  98. package/dist/fills/filters/grayscale.d.ts +9 -0
  99. package/dist/fills/filters/grayscale.d.ts.map +1 -0
  100. package/dist/fills/filters/grayscale.js +25 -0
  101. package/dist/fills/filters/grayscale.js.map +1 -0
  102. package/dist/fills/filters/registry.d.ts +16 -0
  103. package/dist/fills/filters/registry.d.ts.map +1 -0
  104. package/dist/fills/filters/registry.js +50 -0
  105. package/dist/fills/filters/registry.js.map +1 -0
  106. package/dist/fills/gradient-cache.d.ts +29 -0
  107. package/dist/fills/gradient-cache.d.ts.map +1 -0
  108. package/dist/fills/gradient-cache.js +57 -0
  109. package/dist/fills/gradient-cache.js.map +1 -0
  110. package/dist/fills/handler.d.ts +49 -0
  111. package/dist/fills/handler.d.ts.map +1 -0
  112. package/dist/fills/handler.js +172 -0
  113. package/dist/fills/handler.js.map +1 -0
  114. package/dist/fills/image.d.ts +34 -0
  115. package/dist/fills/image.d.ts.map +1 -0
  116. package/dist/fills/image.js +91 -0
  117. package/dist/fills/image.js.map +1 -0
  118. package/dist/fills/linear-gradient.d.ts +12 -0
  119. package/dist/fills/linear-gradient.d.ts.map +1 -0
  120. package/dist/fills/linear-gradient.js +48 -0
  121. package/dist/fills/linear-gradient.js.map +1 -0
  122. package/dist/fills/noise.d.ts +11 -0
  123. package/dist/fills/noise.d.ts.map +1 -0
  124. package/dist/fills/noise.js +82 -0
  125. package/dist/fills/noise.js.map +1 -0
  126. package/dist/fills/radial-gradient.d.ts +9 -0
  127. package/dist/fills/radial-gradient.d.ts.map +1 -0
  128. package/dist/fills/radial-gradient.js +43 -0
  129. package/dist/fills/radial-gradient.js.map +1 -0
  130. package/dist/fills/registry.d.ts +10 -0
  131. package/dist/fills/registry.d.ts.map +1 -0
  132. package/dist/fills/registry.js +34 -0
  133. package/dist/fills/registry.js.map +1 -0
  134. package/dist/fills/renderer.d.ts +24 -0
  135. package/dist/fills/renderer.d.ts.map +1 -0
  136. package/dist/fills/renderer.js +5 -0
  137. package/dist/fills/renderer.js.map +1 -0
  138. package/dist/fills/solid.d.ts +7 -0
  139. package/dist/fills/solid.d.ts.map +1 -0
  140. package/dist/fills/solid.js +13 -0
  141. package/dist/fills/solid.js.map +1 -0
  142. package/dist/fills/stripe.d.ts +7 -0
  143. package/dist/fills/stripe.d.ts.map +1 -0
  144. package/dist/fills/stripe.js +85 -0
  145. package/dist/fills/stripe.js.map +1 -0
  146. package/dist/fills/video.d.ts +6 -0
  147. package/dist/fills/video.d.ts.map +1 -0
  148. package/dist/fills/video.js +14 -0
  149. package/dist/fills/video.js.map +1 -0
  150. package/dist/font-style.d.ts +23 -0
  151. package/dist/font-style.d.ts.map +1 -0
  152. package/dist/font-style.js +34 -0
  153. package/dist/font-style.js.map +1 -0
  154. package/dist/getter.d.ts +9 -0
  155. package/dist/getter.d.ts.map +1 -0
  156. package/dist/getter.js +26 -0
  157. package/dist/getter.js.map +1 -0
  158. package/dist/index.d.ts +9 -0
  159. package/dist/index.d.ts.map +1 -0
  160. package/dist/index.js +11 -0
  161. package/dist/index.js.map +1 -0
  162. package/dist/master-clock.d.ts +42 -0
  163. package/dist/master-clock.d.ts.map +1 -0
  164. package/dist/master-clock.js +134 -0
  165. package/dist/master-clock.js.map +1 -0
  166. package/dist/measure-scope.d.ts +14 -0
  167. package/dist/measure-scope.d.ts.map +1 -0
  168. package/dist/measure-scope.js +29 -0
  169. package/dist/measure-scope.js.map +1 -0
  170. package/dist/render-context.d.ts +107 -0
  171. package/dist/render-context.d.ts.map +1 -0
  172. package/dist/render-context.js +940 -0
  173. package/dist/render-context.js.map +1 -0
  174. package/dist/shapes/alpha-contour.d.ts +27 -0
  175. package/dist/shapes/alpha-contour.d.ts.map +1 -0
  176. package/dist/shapes/alpha-contour.js +330 -0
  177. package/dist/shapes/alpha-contour.js.map +1 -0
  178. package/dist/shapes/base.d.ts +46 -0
  179. package/dist/shapes/base.d.ts.map +1 -0
  180. package/dist/shapes/base.js +95 -0
  181. package/dist/shapes/base.js.map +1 -0
  182. package/dist/shapes/boolean.d.ts +28 -0
  183. package/dist/shapes/boolean.d.ts.map +1 -0
  184. package/dist/shapes/boolean.js +90 -0
  185. package/dist/shapes/boolean.js.map +1 -0
  186. package/dist/shapes/ellipse.d.ts +32 -0
  187. package/dist/shapes/ellipse.d.ts.map +1 -0
  188. package/dist/shapes/ellipse.js +50 -0
  189. package/dist/shapes/ellipse.js.map +1 -0
  190. package/dist/shapes/image.d.ts +66 -0
  191. package/dist/shapes/image.d.ts.map +1 -0
  192. package/dist/shapes/image.js +214 -0
  193. package/dist/shapes/image.js.map +1 -0
  194. package/dist/shapes/index.d.ts +67 -0
  195. package/dist/shapes/index.d.ts.map +1 -0
  196. package/dist/shapes/index.js +297 -0
  197. package/dist/shapes/index.js.map +1 -0
  198. package/dist/shapes/line.d.ts +25 -0
  199. package/dist/shapes/line.d.ts.map +1 -0
  200. package/dist/shapes/line.js +87 -0
  201. package/dist/shapes/line.js.map +1 -0
  202. package/dist/shapes/mask.d.ts +28 -0
  203. package/dist/shapes/mask.d.ts.map +1 -0
  204. package/dist/shapes/mask.js +106 -0
  205. package/dist/shapes/mask.js.map +1 -0
  206. package/dist/shapes/paragraph-layout.d.ts +64 -0
  207. package/dist/shapes/paragraph-layout.d.ts.map +1 -0
  208. package/dist/shapes/paragraph-layout.js +156 -0
  209. package/dist/shapes/paragraph-layout.js.map +1 -0
  210. package/dist/shapes/path.d.ts +29 -0
  211. package/dist/shapes/path.d.ts.map +1 -0
  212. package/dist/shapes/path.js +71 -0
  213. package/dist/shapes/path.js.map +1 -0
  214. package/dist/shapes/polygon.d.ts +33 -0
  215. package/dist/shapes/polygon.d.ts.map +1 -0
  216. package/dist/shapes/polygon.js +86 -0
  217. package/dist/shapes/polygon.js.map +1 -0
  218. package/dist/shapes/polygram.d.ts +34 -0
  219. package/dist/shapes/polygram.d.ts.map +1 -0
  220. package/dist/shapes/polygram.js +90 -0
  221. package/dist/shapes/polygram.js.map +1 -0
  222. package/dist/shapes/rect.d.ts +41 -0
  223. package/dist/shapes/rect.d.ts.map +1 -0
  224. package/dist/shapes/rect.js +111 -0
  225. package/dist/shapes/rect.js.map +1 -0
  226. package/dist/shapes/richtext.d.ts +28 -0
  227. package/dist/shapes/richtext.d.ts.map +1 -0
  228. package/dist/shapes/richtext.js +32 -0
  229. package/dist/shapes/richtext.js.map +1 -0
  230. package/dist/shapes/shape-handler.d.ts +79 -0
  231. package/dist/shapes/shape-handler.d.ts.map +1 -0
  232. package/dist/shapes/shape-handler.js +304 -0
  233. package/dist/shapes/shape-handler.js.map +1 -0
  234. package/dist/shapes/text.d.ts +13 -0
  235. package/dist/shapes/text.d.ts.map +1 -0
  236. package/dist/shapes/text.js +67 -0
  237. package/dist/shapes/text.js.map +1 -0
  238. package/dist/shapes/trim.d.ts +10 -0
  239. package/dist/shapes/trim.d.ts.map +1 -0
  240. package/dist/shapes/trim.js +49 -0
  241. package/dist/shapes/trim.js.map +1 -0
  242. package/dist/storage-adapter.d.ts +56 -0
  243. package/dist/storage-adapter.d.ts.map +1 -0
  244. package/dist/storage-adapter.js +188 -0
  245. package/dist/storage-adapter.js.map +1 -0
  246. package/dist/stroke/index.d.ts +34 -0
  247. package/dist/stroke/index.d.ts.map +1 -0
  248. package/dist/stroke/index.js +360 -0
  249. package/dist/stroke/index.js.map +1 -0
  250. package/dist/stroke/stroke-handler.d.ts +45 -0
  251. package/dist/stroke/stroke-handler.d.ts.map +1 -0
  252. package/dist/stroke/stroke-handler.js +371 -0
  253. package/dist/stroke/stroke-handler.js.map +1 -0
  254. package/dist/video/extract.d.ts +54 -0
  255. package/dist/video/extract.d.ts.map +1 -0
  256. package/dist/video/extract.js +192 -0
  257. package/dist/video/extract.js.map +1 -0
  258. package/dist/video/extract.worker.d.ts +50 -0
  259. package/dist/video/extract.worker.d.ts.map +1 -0
  260. package/dist/video/extract.worker.js +224 -0
  261. package/dist/video/extract.worker.js.map +1 -0
  262. package/package.json +57 -0
package/README.md ADDED
@@ -0,0 +1,47 @@
1
+ # @motion-script/web
2
+
3
+ The browser rendering backend for [Motion Script](https://motionscript.dev),
4
+ built on Skia via [`@motion-script/canvaskit`](../canvaskit). It implements the
5
+ `platform`/`render` abstractions from [`@motion-script/core`](../core) so
6
+ scenes can be drawn to a canvas, played back with synchronized audio, and
7
+ exported to video all in the browser.
8
+
9
+ ## What's in here
10
+
11
+ - **Render context** — `WebRenderContext` draws the `@motion-script/core` scene
12
+ graph (shapes, fills, strokes, effects, text, video, masks) onto a CanvasKit
13
+ surface.
14
+ - **Exporter** — `exportScenesAsVideo` renders one or more scenes offline and
15
+ muxes video and audio into an MP4 using [mediabunny](https://github.com/Vanilagy/mediabunny).
16
+ - **Audio** — `WebAudioPlayer` drives playback through the Web Audio API.
17
+ - **Storage / assets** — `WebStorageAdapter` and `WebMeasureScope` implement the
18
+ asset-loading and text-measurement abstractions `@motion-script/core` needs.
19
+ - **Clock** — `WebMasterClock` synchronizes scene playback to `requestAnimationFrame`.
20
+ - **CanvasKit access** — `getCanvasKit` loads and caches the CanvasKit/Skia
21
+ WebAssembly module used for rendering.
22
+
23
+ ## Usage
24
+
25
+ ```bash
26
+ npm install @motion-script/web @motion-script/core @motion-script/canvaskit
27
+ ```
28
+
29
+ For a guided setup, scaffold a project instead with:
30
+
31
+ ```bash
32
+ npm create motion-script@latest
33
+ ```
34
+
35
+ See the [docs](https://motionscript.dev/docs) for the full feature set and API
36
+ reference.
37
+
38
+ ## Development
39
+
40
+ From the monorepo root:
41
+
42
+ ```bash
43
+ pnpm --filter @motion-script/web build
44
+ pnpm --filter @motion-script/web test
45
+ ```
46
+
47
+ See [CONTRIBUTING.md](../../CONTRIBUTING.md) for the architecture overview.
@@ -0,0 +1,43 @@
1
+ import { AudioDevice, AudioRequest } from "@motion-script/core";
2
+ /**
3
+ * Web Audio implementation of {@link AudioDevice} — decodes and caches source
4
+ * buffers, then schedules/plays {@link AudioRequest}s as `AudioBufferSourceNode`s
5
+ * through a shared master gain (for global mute). `schedule` registers the
6
+ * active set of requests for the current frame; `syncTo` then starts/stops
7
+ * sources to match `sceneTime`, so playback follows scrubbing and seeks.
8
+ */
9
+ export declare class WebAudioDevice extends AudioDevice {
10
+ private context;
11
+ private ownsContext;
12
+ private bufferCache;
13
+ private decoding;
14
+ private active;
15
+ private scheduled;
16
+ private disposed;
17
+ private masterGain;
18
+ private muted;
19
+ constructor(context?: AudioContext);
20
+ getContext(): AudioContext;
21
+ /**
22
+ * Resume the AudioContext. Must be called from within a user gesture
23
+ * (e.g. a click handler) the first time, or browsers keep the context
24
+ * suspended and no audio is heard.
25
+ */
26
+ unlock(): void;
27
+ has(src: string): boolean;
28
+ append(src: string, data: ArrayBuffer): Promise<void>;
29
+ /** Drops cached buffers and stops active sources for srcs/requests no longer referenced — called when the asset set changes (e.g. seeking across scene boundaries). */
30
+ retain(keep: ReadonlySet<string>): void;
31
+ /** Replaces the active request set; stops any currently-playing source whose request is no longer scheduled. Actual start/stop-to-match-time happens in `syncTo`. */
32
+ schedule(requests: readonly AudioRequest[]): void;
33
+ /** Starts sources whose `[startAt, endAt)` window now contains `sceneTime` (computing the correct buffer offset for the seek point) and stops any that have fallen outside it. */
34
+ syncTo(sceneTime: number): void;
35
+ play(time: number, _speed: number, _reverse: boolean): Promise<void>;
36
+ stop(): void;
37
+ setMuted(muted: boolean): void;
38
+ /** Starts a buffer source mid-clip if `sceneTime` lands after the request's start — `audioOffset` accounts for both the request's trim and the elapsed time since `startAt`. */
39
+ private playBuffer;
40
+ private stopSource;
41
+ dispose(): void;
42
+ }
43
+ //# sourceMappingURL=player.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"player.d.ts","sourceRoot":"","sources":["../../src/audio/player.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,WAAW,EAAE,YAAY,EAAE,MAAM,qBAAqB,CAAC;AAQhE;;;;;;GAMG;AACH,qBAAa,cAAe,SAAQ,WAAW;IAC3C,OAAO,CAAC,OAAO,CAAe;IAC9B,OAAO,CAAC,WAAW,CAAU;IAC7B,OAAO,CAAC,WAAW,CAAkC;IACrD,OAAO,CAAC,QAAQ,CAAoC;IACpD,OAAO,CAAC,MAAM,CAAmC;IACjD,OAAO,CAAC,SAAS,CAAsB;IACvC,OAAO,CAAC,QAAQ,CAAkB;IAClC,OAAO,CAAC,UAAU,CAAW;IAC7B,OAAO,CAAC,KAAK,CAAS;gBAEV,OAAO,CAAC,EAAE,YAAY;IAQlC,UAAU,IAAI,YAAY;IAI1B;;;;OAIG;IACH,MAAM,IAAI,IAAI;IAMd,GAAG,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO;IAInB,MAAM,CAAC,GAAG,EAAE,MAAM,EAAE,IAAI,EAAE,WAAW,GAAG,OAAO,CAAC,IAAI,CAAC;IAkB3D,uKAAuK;IACvK,MAAM,CAAC,IAAI,EAAE,WAAW,CAAC,MAAM,CAAC,GAAG,IAAI;IASvC,qKAAqK;IACrK,QAAQ,CAAC,QAAQ,EAAE,SAAS,YAAY,EAAE,GAAG,IAAI;IAQjD,kLAAkL;IAClL,MAAM,CAAC,SAAS,EAAE,MAAM,GAAG,IAAI;IAoBzB,IAAI,CAAC,IAAI,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,EAAE,QAAQ,EAAE,OAAO,GAAG,OAAO,CAAC,IAAI,CAAC;IAO1E,IAAI,IAAI,IAAI;IAMZ,QAAQ,CAAC,KAAK,EAAE,OAAO,GAAG,IAAI;IAK9B,gLAAgL;IAChL,OAAO,CAAC,UAAU;IAwBlB,OAAO,CAAC,UAAU;IAYlB,OAAO,IAAI,IAAI;CAgBlB"}
@@ -0,0 +1,165 @@
1
+ import { AudioDevice } from "@motion-script/core";
2
+ /**
3
+ * Web Audio implementation of {@link AudioDevice} — decodes and caches source
4
+ * buffers, then schedules/plays {@link AudioRequest}s as `AudioBufferSourceNode`s
5
+ * through a shared master gain (for global mute). `schedule` registers the
6
+ * active set of requests for the current frame; `syncTo` then starts/stops
7
+ * sources to match `sceneTime`, so playback follows scrubbing and seeks.
8
+ */
9
+ export class WebAudioDevice extends AudioDevice {
10
+ context;
11
+ ownsContext;
12
+ bufferCache = new Map();
13
+ decoding = new Map();
14
+ active = new Map();
15
+ scheduled = [];
16
+ disposed = false;
17
+ masterGain;
18
+ muted = false;
19
+ constructor(context) {
20
+ super();
21
+ this.context = context ?? new AudioContext();
22
+ this.ownsContext = !context;
23
+ this.masterGain = this.context.createGain();
24
+ this.masterGain.connect(this.context.destination);
25
+ }
26
+ getContext() {
27
+ return this.context;
28
+ }
29
+ /**
30
+ * Resume the AudioContext. Must be called from within a user gesture
31
+ * (e.g. a click handler) the first time, or browsers keep the context
32
+ * suspended and no audio is heard.
33
+ */
34
+ unlock() {
35
+ if (this.context.state === "suspended") {
36
+ this.context.resume();
37
+ }
38
+ }
39
+ has(src) {
40
+ return this.bufferCache.has(src);
41
+ }
42
+ async append(src, data) {
43
+ if (this.bufferCache.has(src))
44
+ return;
45
+ const existing = this.decoding.get(src);
46
+ if (existing)
47
+ return existing;
48
+ // decodeAudioData detaches `data` — that's fine, the caller in
49
+ // AssetManager.fetchAudio discards its reference immediately after
50
+ // awaiting append. Skipping the defensive .slice(0) saves a multi-MB
51
+ // allocation per audio source.
52
+ const job = this.context.decodeAudioData(data).then((buffer) => {
53
+ this.bufferCache.set(src, buffer);
54
+ }).finally(() => {
55
+ this.decoding.delete(src);
56
+ });
57
+ this.decoding.set(src, job);
58
+ await job;
59
+ }
60
+ /** Drops cached buffers and stops active sources for srcs/requests no longer referenced — called when the asset set changes (e.g. seeking across scene boundaries). */
61
+ retain(keep) {
62
+ for (const src of [...this.bufferCache.keys()]) {
63
+ if (!keep.has(src))
64
+ this.bufferCache.delete(src);
65
+ }
66
+ for (const [id, active] of this.active) {
67
+ if (!keep.has(active.request.src))
68
+ this.stopSource(id, active);
69
+ }
70
+ }
71
+ /** Replaces the active request set; stops any currently-playing source whose request is no longer scheduled. Actual start/stop-to-match-time happens in `syncTo`. */
72
+ schedule(requests) {
73
+ const next = new Set(requests.map(r => r.id));
74
+ for (const [id, active] of this.active) {
75
+ if (!next.has(id))
76
+ this.stopSource(id, active);
77
+ }
78
+ this.scheduled = requests.slice();
79
+ }
80
+ /** Starts sources whose `[startAt, endAt)` window now contains `sceneTime` (computing the correct buffer offset for the seek point) and stops any that have fallen outside it. */
81
+ syncTo(sceneTime) {
82
+ const liveIds = new Set();
83
+ for (const req of this.scheduled) {
84
+ const end = req.endAt ?? Infinity;
85
+ const isInWindow = sceneTime >= req.startAt && sceneTime < end;
86
+ if (!isInWindow)
87
+ continue;
88
+ liveIds.add(req.id);
89
+ if (!this.active.has(req.id)) {
90
+ const buffer = this.bufferCache.get(req.src);
91
+ if (buffer)
92
+ this.playBuffer(buffer, req, sceneTime);
93
+ }
94
+ }
95
+ for (const [id, active] of this.active) {
96
+ if (!liveIds.has(id))
97
+ this.stopSource(id, active);
98
+ }
99
+ }
100
+ async play(time, _speed, _reverse) {
101
+ if (this.context.state === "suspended") {
102
+ await this.context.resume();
103
+ }
104
+ this.syncTo(time);
105
+ }
106
+ stop() {
107
+ for (const [id, active] of this.active) {
108
+ this.stopSource(id, active);
109
+ }
110
+ }
111
+ setMuted(muted) {
112
+ this.muted = muted;
113
+ this.masterGain.gain.value = muted ? 0 : 1;
114
+ }
115
+ /** Starts a buffer source mid-clip if `sceneTime` lands after the request's start — `audioOffset` accounts for both the request's trim and the elapsed time since `startAt`. */
116
+ playBuffer(buffer, req, sceneTime) {
117
+ const gainNode = this.context.createGain();
118
+ gainNode.gain.value = req.volume;
119
+ gainNode.connect(this.masterGain);
120
+ const source = this.context.createBufferSource();
121
+ source.buffer = buffer;
122
+ source.loop = req.loop;
123
+ source.connect(gainNode);
124
+ const elapsed = sceneTime - req.startAt;
125
+ const audioOffset = req.trimStart + Math.max(0, elapsed);
126
+ source.start(0, audioOffset);
127
+ source.onended = () => {
128
+ if (this.active.get(req.id)?.source === source) {
129
+ this.active.delete(req.id);
130
+ }
131
+ };
132
+ this.active.set(req.id, { source, gainNode, request: req });
133
+ }
134
+ stopSource(id, active) {
135
+ try {
136
+ active.source.onended = null;
137
+ active.source.stop();
138
+ active.source.disconnect();
139
+ active.gainNode.disconnect();
140
+ }
141
+ catch {
142
+ // already stopped
143
+ }
144
+ this.active.delete(id);
145
+ }
146
+ dispose() {
147
+ if (this.disposed)
148
+ return;
149
+ this.disposed = true;
150
+ super.dispose();
151
+ this.bufferCache.clear();
152
+ this.decoding.clear();
153
+ this.scheduled.length = 0;
154
+ try {
155
+ this.masterGain.disconnect();
156
+ }
157
+ catch {
158
+ // already disconnected
159
+ }
160
+ if (this.ownsContext && this.context.state !== "closed") {
161
+ this.context.close();
162
+ }
163
+ }
164
+ }
165
+ //# sourceMappingURL=player.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"player.js","sourceRoot":"","sources":["../../src/audio/player.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,19 @@
1
+ import type { CanvasKit } from "@motion-script/canvaskit";
2
+ import type { BloomEffect } from "@motion-script/core";
3
+ import { CanvasKitEffect } from "./effect";
4
+ /**
5
+ * Bloom glow effect. Extracts pixels above `threshold`, blurs them, then
6
+ * Screen-blends that bright-pass back onto the original layer.
7
+ *
8
+ * Screen blend: result = 1 − (1 − source) × (1 − bloom)
9
+ * This ensures the bloom only brightens, never darkens, and naturally caps at white.
10
+ *
11
+ * MakeBlend(Screen, background=null, foreground=bloomFilter):
12
+ * background = null → the dynamic source (the saveLayer content)
13
+ * foreground = blurred threshold pass of the same source
14
+ */
15
+ export declare class BloomCanvasKitEffect extends CanvasKitEffect<BloomEffect> {
16
+ constructor();
17
+ makeImageFilter(effect: BloomEffect, ck: CanvasKit): any;
18
+ }
19
+ //# sourceMappingURL=bloom.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"bloom.d.ts","sourceRoot":"","sources":["../../src/effects/bloom.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,0BAA0B,CAAC;AAC1D,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,qBAAqB,CAAC;AACvD,OAAO,EAAE,eAAe,EAAE,MAAM,UAAU,CAAC;AAE3C;;;;;;;;;;GAUG;AACH,qBAAa,oBAAqB,SAAQ,eAAe,CAAC,WAAW,CAAC;;IAKlE,eAAe,CAAC,MAAM,EAAE,WAAW,EAAE,EAAE,EAAE,SAAS,GAAG,GAAG;CAoD3D"}
@@ -0,0 +1,64 @@
1
+ import { CanvasKitEffect } from "./effect";
2
+ /**
3
+ * Bloom glow effect. Extracts pixels above `threshold`, blurs them, then
4
+ * Screen-blends that bright-pass back onto the original layer.
5
+ *
6
+ * Screen blend: result = 1 − (1 − source) × (1 − bloom)
7
+ * This ensures the bloom only brightens, never darkens, and naturally caps at white.
8
+ *
9
+ * MakeBlend(Screen, background=null, foreground=bloomFilter):
10
+ * background = null → the dynamic source (the saveLayer content)
11
+ * foreground = blurred threshold pass of the same source
12
+ */
13
+ export class BloomCanvasKitEffect extends CanvasKitEffect {
14
+ constructor() {
15
+ super("bloom");
16
+ }
17
+ makeImageFilter(effect, ck) {
18
+ if (effect.radius <= 0 || effect.intensity <= 0)
19
+ return null;
20
+ const t = Math.max(0, Math.min(1, effect.threshold));
21
+ const sigma = effect.radius / 2;
22
+ // Color matrix that zeroes out pixels below threshold and rescales the rest.
23
+ // Each channel: output = max(0, input − t) / (1 − t)
24
+ // In 5×4 matrix terms (row-major, applied to non-premultiplied colors):
25
+ // output_R = 1/(1-t) * input_R + (-t/(1-t))
26
+ const scale = t < 1 ? 1 / (1 - t) : 1;
27
+ const bias = -t * scale;
28
+ // prettier-ignore
29
+ const thresholdMatrix = [
30
+ scale, 0, 0, 0, bias,
31
+ 0, scale, 0, 0, bias,
32
+ 0, 0, scale, 0, bias,
33
+ 0, 0, 0, 1, 0,
34
+ ];
35
+ const thresholdCF = ck.ColorFilter.MakeMatrix(thresholdMatrix);
36
+ const thresholdIF = ck.ImageFilter.MakeColorFilter(thresholdCF, null);
37
+ thresholdCF.delete();
38
+ // Blur the bright pass.
39
+ const blurIF = ck.ImageFilter.MakeBlur(sigma, sigma, ck.TileMode.Decal, thresholdIF);
40
+ thresholdIF.delete();
41
+ // Scale the bloom pass by intensity using another color matrix.
42
+ let bloomIF = blurIF;
43
+ if (effect.intensity !== 1) {
44
+ const i = effect.intensity;
45
+ // prettier-ignore
46
+ const intensityMatrix = [
47
+ i, 0, 0, 0, 0,
48
+ 0, i, 0, 0, 0,
49
+ 0, 0, i, 0, 0,
50
+ 0, 0, 0, 1, 0,
51
+ ];
52
+ const intensityCF = ck.ColorFilter.MakeMatrix(intensityMatrix);
53
+ bloomIF = ck.ImageFilter.MakeColorFilter(intensityCF, blurIF);
54
+ intensityCF.delete();
55
+ blurIF.delete();
56
+ }
57
+ // Screen-blend the bloom pass onto the source layer.
58
+ // background = null → source layer; foreground = bloomIF
59
+ const result = ck.ImageFilter.MakeBlend(ck.BlendMode.Screen, null, bloomIF);
60
+ bloomIF.delete();
61
+ return result;
62
+ }
63
+ }
64
+ //# sourceMappingURL=bloom.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"bloom.js","sourceRoot":"","sources":["../../src/effects/bloom.ts"],"names":[],"mappings":"AAEA,OAAO,EAAE,eAAe,EAAE,MAAM,UAAU,CAAC;AAE3C;;;;;;;;;;GAUG;AACH,MAAM,OAAO,oBAAqB,SAAQ,eAA4B;IAClE;QACI,KAAK,CAAC,OAAO,CAAC,CAAC;IACnB,CAAC;IAED,eAAe,CAAC,MAAmB,EAAE,EAAa;QAC9C,IAAI,MAAM,CAAC,MAAM,IAAI,CAAC,IAAI,MAAM,CAAC,SAAS,IAAI,CAAC;YAAE,OAAO,IAAI,CAAC;QAE7D,MAAM,CAAC,GAAG,IAAI,CAAC,GAAG,CAAC,CAAC,EAAE,IAAI,CAAC,GAAG,CAAC,CAAC,EAAE,MAAM,CAAC,SAAS,CAAC,CAAC,CAAC;QACrD,MAAM,KAAK,GAAG,MAAM,CAAC,MAAM,GAAG,CAAC,CAAC;QAEhC,6EAA6E;QAC7E,qDAAqD;QACrD,wEAAwE;QACxE,8CAA8C;QAC9C,MAAM,KAAK,GAAG,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC;QACtC,MAAM,IAAI,GAAG,CAAC,CAAC,GAAG,KAAK,CAAC;QAExB,kBAAkB;QAClB,MAAM,eAAe,GAAG;YACpB,KAAK,EAAE,CAAC,EAAM,CAAC,EAAM,CAAC,EAAE,IAAI;YAC5B,CAAC,EAAM,KAAK,EAAE,CAAC,EAAM,CAAC,EAAE,IAAI;YAC5B,CAAC,EAAM,CAAC,EAAM,KAAK,EAAE,CAAC,EAAE,IAAI;YAC5B,CAAC,EAAM,CAAC,EAAM,CAAC,EAAM,CAAC,EAAE,CAAC;SAC5B,CAAC;QAEF,MAAM,WAAW,GAAG,EAAE,CAAC,WAAW,CAAC,UAAU,CAAC,eAAe,CAAC,CAAC;QAC/D,MAAM,WAAW,GAAG,EAAE,CAAC,WAAW,CAAC,eAAe,CAAC,WAAW,EAAE,IAAI,CAAC,CAAC;QACtE,WAAW,CAAC,MAAM,EAAE,CAAC;QAErB,wBAAwB;QACxB,MAAM,MAAM,GAAG,EAAE,CAAC,WAAW,CAAC,QAAQ,CAAC,KAAK,EAAE,KAAK,EAAE,EAAE,CAAC,QAAQ,CAAC,KAAK,EAAE,WAAW,CAAC,CAAC;QACrF,WAAW,CAAC,MAAM,EAAE,CAAC;QAErB,gEAAgE;QAChE,IAAI,OAAO,GAAQ,MAAM,CAAC;QAC1B,IAAI,MAAM,CAAC,SAAS,KAAK,CAAC,EAAE,CAAC;YACzB,MAAM,CAAC,GAAG,MAAM,CAAC,SAAS,CAAC;YAC3B,kBAAkB;YAClB,MAAM,eAAe,GAAG;gBACpB,CAAC,EAAE,CAAC,EAAE,CAAC,EAAE,CAAC,EAAE,CAAC;gBACb,CAAC,EAAE,CAAC,EAAE,CAAC,EAAE,CAAC,EAAE,CAAC;gBACb,CAAC,EAAE,CAAC,EAAE,CAAC,EAAE,CAAC,EAAE,CAAC;gBACb,CAAC,EAAE,CAAC,EAAE,CAAC,EAAE,CAAC,EAAE,CAAC;aAChB,CAAC;YACF,MAAM,WAAW,GAAG,EAAE,CAAC,WAAW,CAAC,UAAU,CAAC,eAAe,CAAC,CAAC;YAC/D,OAAO,GAAG,EAAE,CAAC,WAAW,CAAC,eAAe,CAAC,WAAW,EAAE,MAAM,CAAC,CAAC;YAC9D,WAAW,CAAC,MAAM,EAAE,CAAC;YACrB,MAAM,CAAC,MAAM,EAAE,CAAC;QACpB,CAAC;QAED,qDAAqD;QACrD,yDAAyD;QACzD,MAAM,MAAM,GAAG,EAAE,CAAC,WAAW,CAAC,SAAS,CAAC,EAAE,CAAC,SAAS,CAAC,MAAM,EAAE,IAAI,EAAE,OAAO,CAAC,CAAC;QAC5E,OAAO,CAAC,MAAM,EAAE,CAAC;QACjB,OAAO,MAAM,CAAC;IAClB,CAAC;CACJ"}
@@ -0,0 +1,8 @@
1
+ import type { CanvasKit } from "@motion-script/canvaskit";
2
+ import { CanvasKitEffect } from "./effect";
3
+ import { type BlurEffect } from "@motion-script/core";
4
+ export declare class BlurCanvasKitEffect extends CanvasKitEffect<BlurEffect> {
5
+ constructor();
6
+ makeImageFilter(effect: BlurEffect, ck: CanvasKit): any;
7
+ }
8
+ //# sourceMappingURL=blur.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"blur.d.ts","sourceRoot":"","sources":["../../src/effects/blur.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,0BAA0B,CAAC;AAC1D,OAAO,EAAE,eAAe,EAAE,MAAM,UAAU,CAAC;AAC3C,OAAO,EAAE,KAAK,UAAU,EAAE,MAAM,qBAAqB,CAAC;AAEtD,qBAAa,mBAAoB,SAAQ,eAAe,CAAC,UAAU,CAAC;;IAKhE,eAAe,CAAC,MAAM,EAAE,UAAU,EAAE,EAAE,EAAE,SAAS,GAAG,GAAG;CAK1D"}
@@ -0,0 +1,12 @@
1
+ import { CanvasKitEffect } from "./effect";
2
+ export class BlurCanvasKitEffect extends CanvasKitEffect {
3
+ constructor() {
4
+ super("blur");
5
+ }
6
+ makeImageFilter(effect, ck) {
7
+ // Skia's blur sigma is roughly half the perceived "radius" of the blur.
8
+ const sigma = effect.radius / 2;
9
+ return ck.ImageFilter.MakeBlur(sigma, sigma, ck.TileMode.Decal, null);
10
+ }
11
+ }
12
+ //# sourceMappingURL=blur.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"blur.js","sourceRoot":"","sources":["../../src/effects/blur.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,eAAe,EAAE,MAAM,UAAU,CAAC;AAG3C,MAAM,OAAO,mBAAoB,SAAQ,eAA2B;IAChE;QACI,KAAK,CAAC,MAAM,CAAC,CAAC;IAClB,CAAC;IAED,eAAe,CAAC,MAAkB,EAAE,EAAa;QAC7C,wEAAwE;QACxE,MAAM,KAAK,GAAG,MAAM,CAAC,MAAM,GAAG,CAAC,CAAC;QAChC,OAAO,EAAE,CAAC,WAAW,CAAC,QAAQ,CAAC,KAAK,EAAE,KAAK,EAAE,EAAE,CAAC,QAAQ,CAAC,KAAK,EAAE,IAAI,CAAC,CAAC;IAC1E,CAAC;CACJ"}
@@ -0,0 +1,20 @@
1
+ import type { CanvasKit, Shader } from "@motion-script/canvaskit";
2
+ import { type BulgePinchEffect } from "@motion-script/core";
3
+ /** Drop the cached RuntimeEffect (called when the draw context is disposed). */
4
+ export declare function disposeBulgePinch(): void;
5
+ /**
6
+ * Build a paint shader that draws the backdrop bulged/pinched within the lens
7
+ * disc and passes it through untouched elsewhere. The caller draws it over the
8
+ * surface (clipped to the node silhouette), replacing the backdrop region with
9
+ * the warped version. Returns null when the effect is a no-op.
10
+ *
11
+ * @param effect bulge/pinch params (strength, radius=reach, centre).
12
+ * @param ck live CanvasKit instance.
13
+ * @param backdrop child shader wrapping the snapshot of the content beneath.
14
+ * @param centerX lens centre X in device px (node centre).
15
+ * @param centerY lens centre Y in device px.
16
+ * @param width node width in device px (the lens box width).
17
+ * @param height node height in device px (the lens box height).
18
+ */
19
+ export declare function makeBulgePinchShader(effect: BulgePinchEffect, ck: CanvasKit, backdrop: Shader, centerX: number, centerY: number, width: number, height: number): Shader | null;
20
+ //# sourceMappingURL=bulge-pinch.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"bulge-pinch.d.ts","sourceRoot":"","sources":["../../src/effects/bulge-pinch.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,SAAS,EAAiB,MAAM,EAAE,MAAM,0BAA0B,CAAC;AACjF,OAAO,EAAE,KAAK,gBAAgB,EAAE,MAAM,qBAAqB,CAAC;AAsD5D,gFAAgF;AAChF,wBAAgB,iBAAiB,IAAI,IAAI,CAGxC;AAED;;;;;;;;;;;;;GAaG;AACH,wBAAgB,oBAAoB,CAChC,MAAM,EAAE,gBAAgB,EACxB,EAAE,EAAE,SAAS,EACb,QAAQ,EAAE,MAAM,EAChB,OAAO,EAAE,MAAM,EACf,OAAO,EAAE,MAAM,EACf,KAAK,EAAE,MAAM,EACb,MAAM,EAAE,MAAM,GACf,MAAM,GAAG,IAAI,CAmBf"}
@@ -0,0 +1,86 @@
1
+ /**
2
+ * Magnifier/pinch lens that *resamples the backdrop* — it reads the content
3
+ * beneath the node (passed in as the `u_backdrop` child shader) at a remapped
4
+ * position, so the area under the node is genuinely bulged or pinched, not just
5
+ * nudged. This is the resample approach a magnifying glass uses.
6
+ *
7
+ * The lens fills the node's *bounding box* (not a circle): position is normalised
8
+ * into the box as `n = (uv − centre) / halfExtent`, and the box metric
9
+ * `q = max(|n.x|, |n.y|)` runs 0 at the centre → 1 at the box edge. So a wide
10
+ * rect distorts across its whole width, a tall one across its height, etc. The
11
+ * caller clips the draw to the node's exact silhouette, so rounded corners /
12
+ * ellipses / polygons round or shape the lens to match.
13
+ *
14
+ * `u_reach` (0–1) sets how far from the centre the warp extends within the box;
15
+ * beyond it the field eases to identity so there is no seam at the shape edge.
16
+ * Inside, a spherical (barrel) profile drives the magnification:
17
+ *
18
+ * t = clamp((reach − q) / reach, 0, 1) 1 at centre → 0 at the reach edge
19
+ * z = sqrt(1 − (1 − t)²) dome height; 1 at centre → 0 at edge
20
+ * factor = 1 − strength · z strength>0 magnifies; <0 compresses
21
+ * sample = centre + (uv − centre) · factor
22
+ */
23
+ const BULGE_PINCH_SKSL = `
24
+ uniform shader u_backdrop;
25
+ uniform vec2 u_center; // lens centre, device px
26
+ uniform vec2 u_half; // node half-extent (halfWidth, halfHeight), device px
27
+ uniform float u_reach; // 0–1 fraction of the box the warp spans
28
+ uniform float u_strength; // + bulge (magnify), − pinch (compress)
29
+
30
+ vec4 main(vec2 fragCoord) {
31
+ vec2 n = (fragCoord - u_center) / max(u_half, vec2(1.0));
32
+ float q = max(abs(n.x), abs(n.y)); // box metric: 0 centre → 1 box edge
33
+ float reach = max(u_reach, 0.001);
34
+ if (q >= reach) {
35
+ return u_backdrop.eval(fragCoord);
36
+ }
37
+ float t = clamp((reach - q) / reach, 0.0, 1.0); // 1 centre → 0 at reach edge
38
+ float e = 1.0 - t;
39
+ float z = sqrt(max(0.0, 1.0 - e * e)); // dome falloff
40
+ float factor = 1.0 - u_strength * z;
41
+ vec2 samplePos = u_center + (fragCoord - u_center) * factor;
42
+ return u_backdrop.eval(samplePos);
43
+ }
44
+ `;
45
+ let cachedEffect = null;
46
+ function getRuntimeEffect(ck) {
47
+ if (!cachedEffect)
48
+ cachedEffect = ck.RuntimeEffect.Make(BULGE_PINCH_SKSL);
49
+ return cachedEffect;
50
+ }
51
+ /** Drop the cached RuntimeEffect (called when the draw context is disposed). */
52
+ export function disposeBulgePinch() {
53
+ cachedEffect?.delete();
54
+ cachedEffect = null;
55
+ }
56
+ /**
57
+ * Build a paint shader that draws the backdrop bulged/pinched within the lens
58
+ * disc and passes it through untouched elsewhere. The caller draws it over the
59
+ * surface (clipped to the node silhouette), replacing the backdrop region with
60
+ * the warped version. Returns null when the effect is a no-op.
61
+ *
62
+ * @param effect bulge/pinch params (strength, radius=reach, centre).
63
+ * @param ck live CanvasKit instance.
64
+ * @param backdrop child shader wrapping the snapshot of the content beneath.
65
+ * @param centerX lens centre X in device px (node centre).
66
+ * @param centerY lens centre Y in device px.
67
+ * @param width node width in device px (the lens box width).
68
+ * @param height node height in device px (the lens box height).
69
+ */
70
+ export function makeBulgePinchShader(effect, ck, backdrop, centerX, centerY, width, height) {
71
+ const strength = effect.strength;
72
+ if (strength === 0 || effect.radius <= 0 || width <= 0 || height <= 0)
73
+ return null;
74
+ // center is a 0–1 offset from the node centre (0.5,0.5 = dead centre).
75
+ const cx = centerX + (effect.center.x - 0.5) * width;
76
+ const cy = centerY + (effect.center.y - 0.5) * height;
77
+ const halfW = width / 2;
78
+ const halfH = height / 2;
79
+ // radius is a 0–1 reach: how far across the node box the warp spans.
80
+ const reach = Math.min(1, effect.radius);
81
+ const runtimeEffect = getRuntimeEffect(ck);
82
+ if (!runtimeEffect)
83
+ return null;
84
+ return runtimeEffect.makeShaderWithChildren([cx, cy, halfW, halfH, reach, strength], [backdrop]);
85
+ }
86
+ //# sourceMappingURL=bulge-pinch.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"bulge-pinch.js","sourceRoot":"","sources":["../../src/effects/bulge-pinch.ts"],"names":[],"mappings":"AAGA;;;;;;;;;;;;;;;;;;;;;GAqBG;AACH,MAAM,gBAAgB,GAAG;;;;;;;;;;;;;;;;;;;;;CAqBxB,CAAC;AAEF,IAAI,YAAY,GAAyB,IAAI,CAAC;AAE9C,SAAS,gBAAgB,CAAC,EAAa;IACnC,IAAI,CAAC,YAAY;QAAE,YAAY,GAAG,EAAE,CAAC,aAAa,CAAC,IAAI,CAAC,gBAAgB,CAAC,CAAC;IAC1E,OAAO,YAAY,CAAC;AACxB,CAAC;AAED,gFAAgF;AAChF,MAAM,UAAU,iBAAiB;IAC7B,YAAY,EAAE,MAAM,EAAE,CAAC;IACvB,YAAY,GAAG,IAAI,CAAC;AACxB,CAAC;AAED;;;;;;;;;;;;;GAaG;AACH,MAAM,UAAU,oBAAoB,CAChC,MAAwB,EACxB,EAAa,EACb,QAAgB,EAChB,OAAe,EACf,OAAe,EACf,KAAa,EACb,MAAc;IAEd,MAAM,QAAQ,GAAG,MAAM,CAAC,QAAQ,CAAC;IACjC,IAAI,QAAQ,KAAK,CAAC,IAAI,MAAM,CAAC,MAAM,IAAI,CAAC,IAAI,KAAK,IAAI,CAAC,IAAI,MAAM,IAAI,CAAC;QAAE,OAAO,IAAI,CAAC;IAEnF,uEAAuE;IACvE,MAAM,EAAE,GAAG,OAAO,GAAG,CAAC,MAAM,CAAC,MAAM,CAAC,CAAC,GAAG,GAAG,CAAC,GAAG,KAAK,CAAC;IACrD,MAAM,EAAE,GAAG,OAAO,GAAG,CAAC,MAAM,CAAC,MAAM,CAAC,CAAC,GAAG,GAAG,CAAC,GAAG,MAAM,CAAC;IACtD,MAAM,KAAK,GAAG,KAAK,GAAG,CAAC,CAAC;IACxB,MAAM,KAAK,GAAG,MAAM,GAAG,CAAC,CAAC;IACzB,qEAAqE;IACrE,MAAM,KAAK,GAAG,IAAI,CAAC,GAAG,CAAC,CAAC,EAAE,MAAM,CAAC,MAAM,CAAC,CAAC;IAEzC,MAAM,aAAa,GAAG,gBAAgB,CAAC,EAAE,CAAC,CAAC;IAC3C,IAAI,CAAC,aAAa;QAAE,OAAO,IAAI,CAAC;IAEhC,OAAO,aAAa,CAAC,sBAAsB,CACvC,CAAC,EAAE,EAAE,EAAE,EAAE,KAAK,EAAE,KAAK,EAAE,KAAK,EAAE,QAAQ,CAAC,EACvC,CAAC,QAAQ,CAAC,CACb,CAAC;AACN,CAAC"}
@@ -0,0 +1,19 @@
1
+ import type { CanvasKit } from "@motion-script/canvaskit";
2
+ import type { ChromaticAberrationEffect } from "@motion-script/core";
3
+ import { CanvasKitEffect } from "./effect";
4
+ /**
5
+ * Chromatic aberration — red/blue lens-dispersion fringing.
6
+ *
7
+ * Implemented as three ImageFilter passes composed via Screen-blend:
8
+ * 1. R ghost: source shifted by (+dx, +dy) with red colour boost
9
+ * 2. B ghost: source shifted by (-dx, -dy) with blue colour boost
10
+ * 3. Screen-blend both ghosts onto the original source
11
+ *
12
+ * Screen-blend keeps the result from over-brightening and naturally
13
+ * saturates highlights, mimicking real lens dispersion.
14
+ */
15
+ export declare class ChromaticAberrationCanvasKitEffect extends CanvasKitEffect<ChromaticAberrationEffect> {
16
+ constructor();
17
+ makeImageFilter(effect: ChromaticAberrationEffect, ck: CanvasKit): any;
18
+ }
19
+ //# sourceMappingURL=chromatic-aberration.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"chromatic-aberration.d.ts","sourceRoot":"","sources":["../../src/effects/chromatic-aberration.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,0BAA0B,CAAC;AAC1D,OAAO,KAAK,EAAE,yBAAyB,EAAE,MAAM,qBAAqB,CAAC;AACrE,OAAO,EAAE,eAAe,EAAE,MAAM,UAAU,CAAC;AAE3C;;;;;;;;;;GAUG;AACH,qBAAa,kCAAmC,SAAQ,eAAe,CAAC,yBAAyB,CAAC;;IAK9F,eAAe,CAAC,MAAM,EAAE,yBAAyB,EAAE,EAAE,EAAE,SAAS,GAAG,GAAG;CA8CzE"}
@@ -0,0 +1,59 @@
1
+ import { CanvasKitEffect } from "./effect";
2
+ /**
3
+ * Chromatic aberration — red/blue lens-dispersion fringing.
4
+ *
5
+ * Implemented as three ImageFilter passes composed via Screen-blend:
6
+ * 1. R ghost: source shifted by (+dx, +dy) with red colour boost
7
+ * 2. B ghost: source shifted by (-dx, -dy) with blue colour boost
8
+ * 3. Screen-blend both ghosts onto the original source
9
+ *
10
+ * Screen-blend keeps the result from over-brightening and naturally
11
+ * saturates highlights, mimicking real lens dispersion.
12
+ */
13
+ export class ChromaticAberrationCanvasKitEffect extends CanvasKitEffect {
14
+ constructor() {
15
+ super("chromaticAberration");
16
+ }
17
+ makeImageFilter(effect, ck) {
18
+ if (effect.amount <= 0)
19
+ return null;
20
+ const rad = (effect.angle * Math.PI) / 180;
21
+ const dx = Math.cos(rad) * effect.amount;
22
+ const dy = Math.sin(rad) * effect.amount;
23
+ // R ghost: shift source by (+dx, +dy), boost red channel, suppress others.
24
+ // prettier-ignore
25
+ const redMatrix = [
26
+ 1.4, -0.2, -0.2, 0, 0,
27
+ 0, 0, 0, 0, 0,
28
+ 0, 0, 0, 0, 0,
29
+ 0, 0, 0, 1, 0,
30
+ ];
31
+ const redCF = ck.ColorFilter.MakeMatrix(redMatrix);
32
+ const redOffset = ck.ImageFilter.MakeOffset(dx, dy, null);
33
+ const rGhost = ck.ImageFilter.MakeColorFilter(redCF, redOffset);
34
+ redCF.delete();
35
+ redOffset.delete();
36
+ // B ghost: shift source by (-dx, -dy), boost blue channel, suppress others.
37
+ // prettier-ignore
38
+ const blueMatrix = [
39
+ 0, 0, 0, 0, 0,
40
+ 0, 0, 0, 0, 0,
41
+ -0.2, -0.2, 1.4, 0, 0,
42
+ 0, 0, 0, 1, 0,
43
+ ];
44
+ const blueCF = ck.ColorFilter.MakeMatrix(blueMatrix);
45
+ const blueOffset = ck.ImageFilter.MakeOffset(-dx, -dy, null);
46
+ const bGhost = ck.ImageFilter.MakeColorFilter(blueCF, blueOffset);
47
+ blueCF.delete();
48
+ blueOffset.delete();
49
+ // Screen-blend R ghost onto source (background = null = source).
50
+ const step1 = ck.ImageFilter.MakeBlend(ck.BlendMode.Screen, null, rGhost);
51
+ rGhost.delete();
52
+ // Screen-blend B ghost onto the result of step1.
53
+ const result = ck.ImageFilter.MakeBlend(ck.BlendMode.Screen, step1, bGhost);
54
+ step1.delete();
55
+ bGhost.delete();
56
+ return result;
57
+ }
58
+ }
59
+ //# sourceMappingURL=chromatic-aberration.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"chromatic-aberration.js","sourceRoot":"","sources":["../../src/effects/chromatic-aberration.ts"],"names":[],"mappings":"AAEA,OAAO,EAAE,eAAe,EAAE,MAAM,UAAU,CAAC;AAE3C;;;;;;;;;;GAUG;AACH,MAAM,OAAO,kCAAmC,SAAQ,eAA0C;IAC9F;QACI,KAAK,CAAC,qBAAqB,CAAC,CAAC;IACjC,CAAC;IAED,eAAe,CAAC,MAAiC,EAAE,EAAa;QAC5D,IAAI,MAAM,CAAC,MAAM,IAAI,CAAC;YAAE,OAAO,IAAI,CAAC;QAEpC,MAAM,GAAG,GAAG,CAAC,MAAM,CAAC,KAAK,GAAG,IAAI,CAAC,EAAE,CAAC,GAAG,GAAG,CAAC;QAC3C,MAAM,EAAE,GAAG,IAAI,CAAC,GAAG,CAAC,GAAG,CAAC,GAAG,MAAM,CAAC,MAAM,CAAC;QACzC,MAAM,EAAE,GAAG,IAAI,CAAC,GAAG,CAAC,GAAG,CAAC,GAAG,MAAM,CAAC,MAAM,CAAC;QAEzC,2EAA2E;QAC3E,kBAAkB;QAClB,MAAM,SAAS,GAAG;YACd,GAAG,EAAE,CAAC,GAAG,EAAE,CAAC,GAAG,EAAE,CAAC,EAAE,CAAC;YACrB,CAAC,EAAK,CAAC,EAAK,CAAC,EAAI,CAAC,EAAE,CAAC;YACrB,CAAC,EAAK,CAAC,EAAK,CAAC,EAAI,CAAC,EAAE,CAAC;YACrB,CAAC,EAAK,CAAC,EAAK,CAAC,EAAI,CAAC,EAAE,CAAC;SACxB,CAAC;QACF,MAAM,KAAK,GAAG,EAAE,CAAC,WAAW,CAAC,UAAU,CAAC,SAAS,CAAC,CAAC;QACnD,MAAM,SAAS,GAAG,EAAE,CAAC,WAAW,CAAC,UAAU,CAAC,EAAE,EAAE,EAAE,EAAE,IAAI,CAAC,CAAC;QAC1D,MAAM,MAAM,GAAG,EAAE,CAAC,WAAW,CAAC,eAAe,CAAC,KAAK,EAAE,SAAS,CAAC,CAAC;QAChE,KAAK,CAAC,MAAM,EAAE,CAAC;QACf,SAAS,CAAC,MAAM,EAAE,CAAC;QAEnB,4EAA4E;QAC5E,kBAAkB;QAClB,MAAM,UAAU,GAAG;YACf,CAAC,EAAK,CAAC,EAAK,CAAC,EAAI,CAAC,EAAE,CAAC;YACrB,CAAC,EAAK,CAAC,EAAK,CAAC,EAAI,CAAC,EAAE,CAAC;YACrB,CAAC,GAAG,EAAE,CAAC,GAAG,EAAE,GAAG,EAAE,CAAC,EAAE,CAAC;YACrB,CAAC,EAAK,CAAC,EAAK,CAAC,EAAI,CAAC,EAAE,CAAC;SACxB,CAAC;QACF,MAAM,MAAM,GAAG,EAAE,CAAC,WAAW,CAAC,UAAU,CAAC,UAAU,CAAC,CAAC;QACrD,MAAM,UAAU,GAAG,EAAE,CAAC,WAAW,CAAC,UAAU,CAAC,CAAC,EAAE,EAAE,CAAC,EAAE,EAAE,IAAI,CAAC,CAAC;QAC7D,MAAM,MAAM,GAAG,EAAE,CAAC,WAAW,CAAC,eAAe,CAAC,MAAM,EAAE,UAAU,CAAC,CAAC;QAClE,MAAM,CAAC,MAAM,EAAE,CAAC;QAChB,UAAU,CAAC,MAAM,EAAE,CAAC;QAEpB,iEAAiE;QACjE,MAAM,KAAK,GAAG,EAAE,CAAC,WAAW,CAAC,SAAS,CAAC,EAAE,CAAC,SAAS,CAAC,MAAM,EAAE,IAAI,EAAE,MAAM,CAAC,CAAC;QAC1E,MAAM,CAAC,MAAM,EAAE,CAAC;QAEhB,iDAAiD;QACjD,MAAM,MAAM,GAAG,EAAE,CAAC,WAAW,CAAC,SAAS,CAAC,EAAE,CAAC,SAAS,CAAC,MAAM,EAAE,KAAK,EAAE,MAAM,CAAC,CAAC;QAC5E,KAAK,CAAC,MAAM,EAAE,CAAC;QACf,MAAM,CAAC,MAAM,EAAE,CAAC;QAEhB,OAAO,MAAM,CAAC;IAClB,CAAC;CACJ"}
@@ -0,0 +1,32 @@
1
+ import { type SceneEffect as IEffect } from "@motion-script/core";
2
+ import type { CanvasKit } from "@motion-script/canvaskit";
3
+ /**
4
+ * Abstract base for CanvasKit effect renderers.
5
+ *
6
+ * Subclasses implement `makeImageFilter` using either built-in CanvasKit filters
7
+ * (ImageFilter.MakeBlur, ColorFilter.MakeMatrix, etc.) or custom SkSL shaders
8
+ * via CanvasKit.RuntimeEffect.Make(sksl).
9
+ *
10
+ * The returned ImageFilter is applied as a saveLayer paint wrapping the node's
11
+ * draw calls, so it composites the entire node before applying the filter.
12
+ */
13
+ export declare abstract class CanvasKitEffect<T extends IEffect = IEffect> {
14
+ readonly type: string;
15
+ constructor(type: string);
16
+ /**
17
+ * Produce a Skia ImageFilter for this effect.
18
+ *
19
+ * @param effect Effect data (radius, amount, etc.)
20
+ * @param ck Live CanvasKit instance
21
+ * @param width Surface width in pixels — needed for size-relative effects (e.g. pixelate)
22
+ * @param height Surface height in pixels
23
+ * @returns An ImageFilter object, or null if the effect cannot be applied
24
+ */
25
+ abstract makeImageFilter(effect: T, ck: CanvasKit, width: number, height: number): any;
26
+ /**
27
+ * Clean up any persistent CanvasKit objects (e.g. cached RuntimeEffect).
28
+ * Called when the draw context is disposed.
29
+ */
30
+ dispose(): void;
31
+ }
32
+ //# sourceMappingURL=effect.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"effect.d.ts","sourceRoot":"","sources":["../../src/effects/effect.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,KAAK,WAAW,IAAI,OAAO,EAAE,MAAM,qBAAqB,CAAC;AAClE,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,0BAA0B,CAAC;AAE1D;;;;;;;;;GASG;AACH,8BAAsB,eAAe,CAAC,CAAC,SAAS,OAAO,GAAG,OAAO;IAC7D,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;gBAEV,IAAI,EAAE,MAAM;IAIxB;;;;;;;;OAQG;IACH,QAAQ,CAAC,eAAe,CAAC,MAAM,EAAE,CAAC,EAAE,EAAE,EAAE,SAAS,EAAE,KAAK,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,GAAG,GAAG;IAEtF;;;OAGG;IACH,OAAO,IAAI,IAAI;CAClB"}