visualfries 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 (219) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +213 -0
  3. package/dist/DIContainer.d.ts +4 -0
  4. package/dist/DIContainer.js +145 -0
  5. package/dist/SceneBuilder.svelte.d.ts +8574 -0
  6. package/dist/SceneBuilder.svelte.js +409 -0
  7. package/dist/adapters/subtitleHelpers.d.ts +2 -0
  8. package/dist/adapters/subtitleHelpers.js +187 -0
  9. package/dist/animations/AnimationContext.d.ts +17 -0
  10. package/dist/animations/AnimationContext.js +72 -0
  11. package/dist/animations/AnimationPresetsRegister.d.ts +362 -0
  12. package/dist/animations/AnimationPresetsRegister.js +20 -0
  13. package/dist/animations/AnimationSetup.d.ts +8 -0
  14. package/dist/animations/AnimationSetup.js +30 -0
  15. package/dist/animations/SplitTextCache.d.ts +28 -0
  16. package/dist/animations/SplitTextCache.js +68 -0
  17. package/dist/animations/animationBuilder.d.ts +31 -0
  18. package/dist/animations/animationBuilder.js +255 -0
  19. package/dist/animations/animationPreset.d.ts +7 -0
  20. package/dist/animations/animationPreset.js +31 -0
  21. package/dist/animations/builders/AnimationPresetFactory.d.ts +43 -0
  22. package/dist/animations/builders/AnimationPresetFactory.js +139 -0
  23. package/dist/animations/builders/LineHighlighterAnimationBuilder.d.ts +16 -0
  24. package/dist/animations/builders/LineHighlighterAnimationBuilder.js +183 -0
  25. package/dist/animations/builders/WordHighlighterAnimationBuilder.d.ts +15 -0
  26. package/dist/animations/builders/WordHighlighterAnimationBuilder.js +180 -0
  27. package/dist/animations/engines/AnimationEngineAdaptor.d.ts +107 -0
  28. package/dist/animations/engines/AnimationEngineAdaptor.js +1 -0
  29. package/dist/animations/engines/GSAPEngineAdaptor.d.ts +21 -0
  30. package/dist/animations/engines/GSAPEngineAdaptor.js +145 -0
  31. package/dist/animations/presets/index.d.ts +2 -0
  32. package/dist/animations/presets/index.js +3 -0
  33. package/dist/animations/presets/lines.d.ts +52 -0
  34. package/dist/animations/presets/lines.js +547 -0
  35. package/dist/animations/presets/words.d.ts +31 -0
  36. package/dist/animations/presets/words.js +268 -0
  37. package/dist/animations/transformers/AnimationReferenceTransformer.d.ts +9 -0
  38. package/dist/animations/transformers/AnimationReferenceTransformer.js +114 -0
  39. package/dist/builders/PixiComponentBuilder.d.ts +63 -0
  40. package/dist/builders/PixiComponentBuilder.js +112 -0
  41. package/dist/builders/_ComponentState.svelte.d.ts +795 -0
  42. package/dist/builders/_ComponentState.svelte.js +203 -0
  43. package/dist/builders/html/HtmlBuilder.d.ts +66 -0
  44. package/dist/builders/html/HtmlBuilder.js +171 -0
  45. package/dist/builders/html/HtmlBuilderFactory.d.ts +27 -0
  46. package/dist/builders/html/HtmlBuilderFactory.js +30 -0
  47. package/dist/builders/html/StyleBuilder.d.ts +13 -0
  48. package/dist/builders/html/StyleBuilder.js +133 -0
  49. package/dist/builders/html/StyleProcessor.d.ts +9 -0
  50. package/dist/builders/html/StyleProcessor.js +1 -0
  51. package/dist/builders/html/TextComponentHtmlBuilder.d.ts +16 -0
  52. package/dist/builders/html/TextComponentHtmlBuilder.js +93 -0
  53. package/dist/builders/html/TextShadowBuilder.d.ts +60 -0
  54. package/dist/builders/html/TextShadowBuilder.js +227 -0
  55. package/dist/builders/html/processors/AppearanceStyleProcessor.d.ts +5 -0
  56. package/dist/builders/html/processors/AppearanceStyleProcessor.js +57 -0
  57. package/dist/builders/html/processors/TextAppearanceStyleProcessor.d.ts +5 -0
  58. package/dist/builders/html/processors/TextAppearanceStyleProcessor.js +37 -0
  59. package/dist/builders/html/processors/TextEffectsStyleProcessor.d.ts +6 -0
  60. package/dist/builders/html/processors/TextEffectsStyleProcessor.js +68 -0
  61. package/dist/commands/Command.d.ts +6 -0
  62. package/dist/commands/Command.js +1 -0
  63. package/dist/commands/CommandRunner.d.ts +28 -0
  64. package/dist/commands/CommandRunner.js +81 -0
  65. package/dist/commands/CommandTypes.d.ts +11 -0
  66. package/dist/commands/CommandTypes.js +13 -0
  67. package/dist/commands/PauseCommand.d.ts +4 -0
  68. package/dist/commands/PauseCommand.js +5 -0
  69. package/dist/commands/PlayCommand.d.ts +4 -0
  70. package/dist/commands/PlayCommand.js +6 -0
  71. package/dist/commands/RenderCommand.d.ts +15 -0
  72. package/dist/commands/RenderCommand.js +18 -0
  73. package/dist/commands/RenderFrameCommand.d.ts +17 -0
  74. package/dist/commands/RenderFrameCommand.js +93 -0
  75. package/dist/commands/ReplaceSourceOnTimeCommand.d.ts +4 -0
  76. package/dist/commands/ReplaceSourceOnTimeCommand.js +22 -0
  77. package/dist/commands/SeekCommand.d.ts +15 -0
  78. package/dist/commands/SeekCommand.js +39 -0
  79. package/dist/commands/UpdateComponentCommand.d.ts +4 -0
  80. package/dist/commands/UpdateComponentCommand.js +17 -0
  81. package/dist/components/AnimatedGIF.d.ts +201 -0
  82. package/dist/components/AnimatedGIF.js +391 -0
  83. package/dist/components/Component.svelte.d.ts +33 -0
  84. package/dist/components/Component.svelte.js +152 -0
  85. package/dist/components/ComponentContext.svelte.d.ts +33 -0
  86. package/dist/components/ComponentContext.svelte.js +105 -0
  87. package/dist/components/hooks/AnimationHook.d.ts +25 -0
  88. package/dist/components/hooks/AnimationHook.js +180 -0
  89. package/dist/components/hooks/CanvasShapeHook.d.ts +12 -0
  90. package/dist/components/hooks/CanvasShapeHook.js +229 -0
  91. package/dist/components/hooks/HtmlAnimationHook.d.ts +8 -0
  92. package/dist/components/hooks/HtmlAnimationHook.js +70 -0
  93. package/dist/components/hooks/HtmlTextHook.d.ts +16 -0
  94. package/dist/components/hooks/HtmlTextHook.js +102 -0
  95. package/dist/components/hooks/HtmlToCanvasHook.d.ts +16 -0
  96. package/dist/components/hooks/HtmlToCanvasHook.js +148 -0
  97. package/dist/components/hooks/ImageHook.d.ts +10 -0
  98. package/dist/components/hooks/ImageHook.js +45 -0
  99. package/dist/components/hooks/MediaHook.d.ts +15 -0
  100. package/dist/components/hooks/MediaHook.js +252 -0
  101. package/dist/components/hooks/MediaSeekingHook.d.ts +12 -0
  102. package/dist/components/hooks/MediaSeekingHook.js +204 -0
  103. package/dist/components/hooks/PixiDisplayObjectHook.d.ts +15 -0
  104. package/dist/components/hooks/PixiDisplayObjectHook.js +77 -0
  105. package/dist/components/hooks/PixiGifHook.d.ts +15 -0
  106. package/dist/components/hooks/PixiGifHook.js +97 -0
  107. package/dist/components/hooks/PixiProgressShapeHook.d.ts +12 -0
  108. package/dist/components/hooks/PixiProgressShapeHook.js +128 -0
  109. package/dist/components/hooks/PixiSplitScreenDisplayObjectHook.d.ts +21 -0
  110. package/dist/components/hooks/PixiSplitScreenDisplayObjectHook.js +210 -0
  111. package/dist/components/hooks/PixiTextureHook.d.ts +7 -0
  112. package/dist/components/hooks/PixiTextureHook.js +29 -0
  113. package/dist/components/hooks/PixiVideoTextureHook.d.ts +10 -0
  114. package/dist/components/hooks/PixiVideoTextureHook.js +35 -0
  115. package/dist/components/hooks/SubtitlesHook.d.ts +88 -0
  116. package/dist/components/hooks/SubtitlesHook.js +199 -0
  117. package/dist/components/hooks/VerifyGifHook.d.ts +7 -0
  118. package/dist/components/hooks/VerifyGifHook.js +27 -0
  119. package/dist/components/hooks/VerifyImageHook.d.ts +7 -0
  120. package/dist/components/hooks/VerifyImageHook.js +27 -0
  121. package/dist/components/hooks/VerifyMediaHook.d.ts +7 -0
  122. package/dist/components/hooks/VerifyMediaHook.js +21 -0
  123. package/dist/components/hooks/shapes/progress/CustomProgressRenderer.d.ts +8 -0
  124. package/dist/components/hooks/shapes/progress/CustomProgressRenderer.js +53 -0
  125. package/dist/components/hooks/shapes/progress/DoubleProgressRenderer.d.ts +8 -0
  126. package/dist/components/hooks/shapes/progress/DoubleProgressRenderer.js +69 -0
  127. package/dist/components/hooks/shapes/progress/LinearProgressRenderer.d.ts +8 -0
  128. package/dist/components/hooks/shapes/progress/LinearProgressRenderer.js +60 -0
  129. package/dist/components/hooks/shapes/progress/PerimeterProgressRenderer.d.ts +9 -0
  130. package/dist/components/hooks/shapes/progress/PerimeterProgressRenderer.js +213 -0
  131. package/dist/components/hooks/shapes/progress/ProgressRenderer.d.ts +17 -0
  132. package/dist/components/hooks/shapes/progress/ProgressRenderer.js +75 -0
  133. package/dist/components/hooks/shapes/progress/RadialProgressRenderer.d.ts +8 -0
  134. package/dist/components/hooks/shapes/progress/RadialProgressRenderer.js +50 -0
  135. package/dist/components/hooks/shapes/progress/index.d.ts +6 -0
  136. package/dist/components/hooks/shapes/progress/index.js +6 -0
  137. package/dist/composers/componentComposer.d.ts +55 -0
  138. package/dist/composers/componentComposer.js +118 -0
  139. package/dist/composers/layerComposer.d.ts +46 -0
  140. package/dist/composers/layerComposer.js +79 -0
  141. package/dist/composers/sceneComposer.d.ts +48 -0
  142. package/dist/composers/sceneComposer.js +92 -0
  143. package/dist/constants.d.ts +12 -0
  144. package/dist/constants.js +14 -0
  145. package/dist/directors/ComponentDirector.d.ts +20 -0
  146. package/dist/directors/ComponentDirector.js +86 -0
  147. package/dist/factories/SceneBuilderFactory.d.ts +15 -0
  148. package/dist/factories/SceneBuilderFactory.js +51 -0
  149. package/dist/fonts/GoogleFontsProvider.d.ts +12 -0
  150. package/dist/fonts/GoogleFontsProvider.js +125 -0
  151. package/dist/fonts/fontLoader.d.ts +15 -0
  152. package/dist/fonts/fontLoader.js +41 -0
  153. package/dist/fonts/types.d.ts +1 -0
  154. package/dist/fonts/types.js +1 -0
  155. package/dist/index.d.ts +11 -0
  156. package/dist/index.js +14 -0
  157. package/dist/layers/Layer.svelte.d.ts +8492 -0
  158. package/dist/layers/Layer.svelte.js +125 -0
  159. package/dist/managers/AppManager.svelte.d.ts +23 -0
  160. package/dist/managers/AppManager.svelte.js +89 -0
  161. package/dist/managers/ComponentsManager.svelte.d.ts +49 -0
  162. package/dist/managers/ComponentsManager.svelte.js +247 -0
  163. package/dist/managers/DomManager.d.ts +18 -0
  164. package/dist/managers/DomManager.js +73 -0
  165. package/dist/managers/EventManager.d.ts +7 -0
  166. package/dist/managers/EventManager.js +22 -0
  167. package/dist/managers/LayersManager.svelte.d.ts +8499 -0
  168. package/dist/managers/LayersManager.svelte.js +176 -0
  169. package/dist/managers/MediaManager.d.ts +32 -0
  170. package/dist/managers/MediaManager.js +243 -0
  171. package/dist/managers/RenderManager.d.ts +23 -0
  172. package/dist/managers/RenderManager.js +59 -0
  173. package/dist/managers/StateManager.svelte.d.ts +8746 -0
  174. package/dist/managers/StateManager.svelte.js +272 -0
  175. package/dist/managers/SubtitlesManager.svelte.d.ts +261 -0
  176. package/dist/managers/SubtitlesManager.svelte.js +1385 -0
  177. package/dist/managers/TimeManager.svelte.d.ts +6 -0
  178. package/dist/managers/TimeManager.svelte.js +18 -0
  179. package/dist/managers/TimelineManager.svelte.d.ts +25 -0
  180. package/dist/managers/TimelineManager.svelte.js +152 -0
  181. package/dist/registers.d.ts +12 -0
  182. package/dist/registers.js +29 -0
  183. package/dist/schemas/runtime/index.d.ts +3 -0
  184. package/dist/schemas/runtime/index.js +4 -0
  185. package/dist/schemas/runtime/types.d.ts +323 -0
  186. package/dist/schemas/runtime/types.js +12 -0
  187. package/dist/schemas/scene/animations.d.ts +89738 -0
  188. package/dist/schemas/scene/animations.js +211 -0
  189. package/dist/schemas/scene/components.js +515 -0
  190. package/dist/schemas/scene/core.js +160 -0
  191. package/dist/schemas/scene/index.d.ts +22 -0
  192. package/dist/schemas/scene/index.js +10 -0
  193. package/dist/schemas/scene/properties.d.ts +914 -0
  194. package/dist/schemas/scene/properties.js +398 -0
  195. package/dist/schemas/scene/subtitles.d.ts +1141 -0
  196. package/dist/schemas/scene/subtitles.js +111 -0
  197. package/dist/schemas/scene/utils.d.ts +1 -0
  198. package/dist/schemas/scene/utils.js +5 -0
  199. package/dist/seeds/SeedFactory.d.ts +59 -0
  200. package/dist/seeds/SeedFactory.js +99 -0
  201. package/dist/seeds/index.d.ts +8 -0
  202. package/dist/seeds/index.js +8 -0
  203. package/dist/transformers/ColorTransformer.d.ts +5 -0
  204. package/dist/transformers/ColorTransformer.js +67 -0
  205. package/dist/transformers/PixiColorTransformer.d.ts +22 -0
  206. package/dist/transformers/PixiColorTransformer.js +104 -0
  207. package/dist/utils/canvas.d.ts +6 -0
  208. package/dist/utils/canvas.js +18 -0
  209. package/dist/utils/document.d.ts +2 -0
  210. package/dist/utils/document.js +36 -0
  211. package/dist/utils/emoji.d.ts +10 -0
  212. package/dist/utils/emoji.js +51 -0
  213. package/dist/utils/html.d.ts +4 -0
  214. package/dist/utils/html.js +45 -0
  215. package/dist/utils/svgGenerator.d.ts +20 -0
  216. package/dist/utils/svgGenerator.js +103 -0
  217. package/dist/utils/utils.d.ts +5 -0
  218. package/dist/utils/utils.js +125 -0
  219. package/package.json +96 -0
@@ -0,0 +1,391 @@
1
+ import { Sprite } from "pixi.js-legacy";
2
+ import { Texture, Renderer, settings, SCALE_MODES, Ticker, UPDATE_PRIORITY, } from "pixi.js-legacy";
3
+ import { parseGIF, decompressFrames } from "gifuct-js";
4
+ /**
5
+ * Runtime object to play animated GIFs. This object is similar to an AnimatedSprite.
6
+ * It support playback (seek, play, stop) as well as animation speed and looping.
7
+ * @see Thanks to {@link https://github.com/matt-way/gifuct-js/ gifuct-js}
8
+ */
9
+ class AnimatedGIF extends Sprite {
10
+ /**
11
+ * Default options for all AnimatedGIF objects.
12
+ * @property {PIXI.SCALE_MODES} [scaleMode=PIXI.SCALE_MODES.LINEAR] - Scale mode to use for the texture.
13
+ * @property {boolean} [loop=true] - To enable looping.
14
+ * @property {number} [animationSpeed=1] - Speed of the animation.
15
+ * @property {boolean} [autoUpdate=true] - Set to `false` to manage updates yourself.
16
+ * @property {boolean} [autoPlay=true] - To start playing right away.
17
+ * @property {Function} [onComplete=null] - The completed callback, optional.
18
+ * @property {Function} [onLoop=null] - The loop callback, optional.
19
+ * @property {Function} [onFrameChange=null] - The frame callback, optional.
20
+ * @property {number} [fps=30] - Fallback FPS if GIF contains no time information.
21
+ */
22
+ static defaultOptions = {
23
+ scaleMode: SCALE_MODES.LINEAR,
24
+ fps: 30,
25
+ loop: true,
26
+ animationSpeed: 1,
27
+ autoPlay: true,
28
+ autoUpdate: true,
29
+ onComplete: null,
30
+ onFrameChange: null,
31
+ onLoop: null,
32
+ };
33
+ /**
34
+ * The speed that the animation will play at. Higher is faster, lower is slower.
35
+ * @default 1
36
+ */
37
+ animationSpeed = 1;
38
+ /**
39
+ * Whether or not the animate sprite repeats after playing.
40
+ * @default true
41
+ */
42
+ loop = true;
43
+ /**
44
+ * User-assigned function to call when animation finishes playing. This only happens
45
+ * if loop is set to `false`.
46
+ *
47
+ * @example
48
+ * animation.onComplete = () => {
49
+ * // finished!
50
+ * };
51
+ */
52
+ onComplete;
53
+ /**
54
+ * User-assigned function to call when animation changes which texture is being rendered.
55
+ *
56
+ * @example
57
+ * animation.onFrameChange = () => {
58
+ * // updated!
59
+ * };
60
+ */
61
+ onFrameChange;
62
+ /**
63
+ * User-assigned function to call when `loop` is true, and animation is played and
64
+ * loops around to start again. This only happens if loop is set to `true`.
65
+ *
66
+ * @example
67
+ * animation.onLoop = () => {
68
+ * // looped!
69
+ * };
70
+ */
71
+ onLoop;
72
+ /** The total duration of animation in milliseconds. */
73
+ duration = 0;
74
+ /** Whether to play the animation after constructing. */
75
+ autoPlay = true;
76
+ /** Collection of frame to render. */
77
+ _frames;
78
+ /** Drawing context reference. */
79
+ _context;
80
+ /** Dirty means the image needs to be redrawn. Set to `true` to force redraw. */
81
+ dirty = false;
82
+ /** The current frame number (zero-based index). */
83
+ _currentFrame = 0;
84
+ /** `true` uses PIXI.Ticker.shared to auto update animation time.*/
85
+ _autoUpdate = false;
86
+ /** `true` if the instance is currently connected to PIXI.Ticker.shared to auto update animation time. */
87
+ _isConnectedToTicker = false;
88
+ /** If animation is currently playing. */
89
+ _playing = false;
90
+ /** Current playback position in milliseconds. */
91
+ _currentTime = 0;
92
+ /**
93
+ * Create an animated GIF animation from a GIF image's ArrayBuffer. The easiest way to get
94
+ * the buffer is to use Assets.
95
+ * @example
96
+ * import { Assets } from 'pixi.js';
97
+ * import '@pixi/gif';
98
+ *
99
+ * const gif = await Assets.load('file.gif');
100
+ * @param buffer - GIF image arraybuffer from Assets.
101
+ * @param options - Options to use.
102
+ * @returns
103
+ */
104
+ static fromBuffer(buffer, options) {
105
+ if (!buffer || buffer.byteLength === 0) {
106
+ throw new Error("Invalid buffer");
107
+ }
108
+ // fix https://github.com/matt-way/gifuct-js/issues/30
109
+ const validateAndFix = (gif) => {
110
+ let currentGce = null;
111
+ for (const frame of gif.frames) {
112
+ currentGce = frame.gce ?? currentGce;
113
+ // fix loosing graphic control extension for same frames
114
+ if ("image" in frame && !("gce" in frame)) {
115
+ frame.gce = currentGce;
116
+ }
117
+ }
118
+ };
119
+ const gif = parseGIF(buffer);
120
+ validateAndFix(gif);
121
+ const gifFrames = decompressFrames(gif, true);
122
+ const frames = [];
123
+ // Temporary canvases required for compositing frames
124
+ const canvas = document.createElement("canvas");
125
+ const context = canvas.getContext("2d", {
126
+ willReadFrequently: true,
127
+ });
128
+ const patchCanvas = document.createElement("canvas");
129
+ const patchContext = patchCanvas.getContext("2d");
130
+ canvas.width = gif.lsd.width;
131
+ canvas.height = gif.lsd.height;
132
+ let time = 0;
133
+ let previousFrame = null;
134
+ // Some GIFs have a non-zero frame delay, so we need to calculate the fallback
135
+ const { fps } = Object.assign({}, AnimatedGIF.defaultOptions, options);
136
+ const defaultDelay = 1000 / fps;
137
+ // Precompute each frame and store as ImageData
138
+ for (let i = 0; i < gifFrames.length; i++) {
139
+ // Some GIF's omit the disposalType, so let's assume clear if missing
140
+ const { disposalType = 2, delay = defaultDelay, patch, dims: { width, height, left, top }, } = gifFrames[i];
141
+ patchCanvas.width = width;
142
+ patchCanvas.height = height;
143
+ patchContext.clearRect(0, 0, width, height);
144
+ const patchData = patchContext.createImageData(width, height);
145
+ patchData.data.set(patch);
146
+ patchContext.putImageData(patchData, 0, 0);
147
+ if (disposalType === 3) {
148
+ previousFrame = context.getImageData(0, 0, canvas.width, canvas.height);
149
+ }
150
+ context.drawImage(patchCanvas, left, top);
151
+ const imageData = context.getImageData(0, 0, canvas.width, canvas.height);
152
+ if (disposalType === 2) {
153
+ context.clearRect(0, 0, canvas.width, canvas.height);
154
+ }
155
+ else if (disposalType === 3) {
156
+ context.putImageData(previousFrame, 0, 0);
157
+ }
158
+ frames.push({
159
+ start: time,
160
+ end: time + delay,
161
+ imageData,
162
+ });
163
+ time += delay;
164
+ }
165
+ // clear the canvases
166
+ canvas.width = canvas.height = 0;
167
+ patchCanvas.width = patchCanvas.height = 0;
168
+ const { width, height } = gif.lsd;
169
+ return new AnimatedGIF(frames, { width, height, ...options });
170
+ }
171
+ /**
172
+ * @param frames - Data of the GIF image.
173
+ * @param options - Options for the AnimatedGIF
174
+ */
175
+ constructor(frames, options) {
176
+ super(Texture.EMPTY);
177
+ // Get the options, apply defaults
178
+ const { scaleMode, width, height, ...rest } = Object.assign({}, AnimatedGIF.defaultOptions, options);
179
+ // Create the texture
180
+ const canvas = document.createElement("canvas");
181
+ const context = canvas.getContext("2d");
182
+ canvas.width = width;
183
+ canvas.height = height;
184
+ this.texture = Texture.from(canvas, { scaleMode });
185
+ this.duration = frames[frames.length - 1].end;
186
+ this._frames = frames;
187
+ this._context = context;
188
+ this._playing = false;
189
+ this._currentTime = 0;
190
+ this._isConnectedToTicker = false;
191
+ Object.assign(this, rest);
192
+ // Draw the first frame
193
+ this.currentFrame = 0;
194
+ if (rest.autoPlay) {
195
+ this.play();
196
+ }
197
+ }
198
+ /** Stops the animation. */
199
+ stop() {
200
+ if (!this._playing) {
201
+ return;
202
+ }
203
+ this._playing = false;
204
+ if (this._autoUpdate && this._isConnectedToTicker) {
205
+ Ticker.shared.remove(this.update, this);
206
+ this._isConnectedToTicker = false;
207
+ }
208
+ }
209
+ /** Plays the animation. */
210
+ play() {
211
+ if (this._playing) {
212
+ return;
213
+ }
214
+ this._playing = true;
215
+ if (this._autoUpdate && !this._isConnectedToTicker) {
216
+ Ticker.shared.add(this.update, this, UPDATE_PRIORITY.HIGH);
217
+ this._isConnectedToTicker = true;
218
+ }
219
+ // If were on the last frame and stopped, play should resume from beginning
220
+ if (!this.loop && this.currentFrame === this._frames.length - 1) {
221
+ this._currentTime = 0;
222
+ }
223
+ }
224
+ /**
225
+ * Get the current progress of the animation from 0 to 1.
226
+ * @readonly
227
+ */
228
+ get progress() {
229
+ return this._currentTime / this.duration;
230
+ }
231
+ /** `true` if the current animation is playing */
232
+ get playing() {
233
+ return this._playing;
234
+ }
235
+ /**
236
+ * Updates the object transform for rendering. You only need to call this
237
+ * if the `autoUpdate` property is set to `false`.
238
+ *
239
+ * @param deltaTime - Time since last tick.
240
+ */
241
+ update(deltaTime) {
242
+ if (!this._playing) {
243
+ return;
244
+ }
245
+ const elapsed = (this.animationSpeed * deltaTime) /
246
+ settings.TARGET_FPMS;
247
+ const currentTime = this._currentTime + elapsed;
248
+ const localTime = currentTime % this.duration;
249
+ const localFrame = this._frames.findIndex((frame) => frame.start <= localTime && frame.end > localTime);
250
+ if (currentTime >= this.duration) {
251
+ if (this.loop) {
252
+ this._currentTime = localTime;
253
+ this.updateFrameIndex(localFrame);
254
+ this.onLoop?.();
255
+ }
256
+ else {
257
+ this._currentTime = this.duration;
258
+ this.updateFrameIndex(this._frames.length - 1);
259
+ this.onComplete?.();
260
+ this.stop();
261
+ }
262
+ }
263
+ else {
264
+ this._currentTime = localTime;
265
+ this.updateFrameIndex(localFrame);
266
+ }
267
+ }
268
+ /**
269
+ * Redraw the current frame, is necessary for the animation to work when
270
+ */
271
+ updateFrame() {
272
+ if (!this.dirty) {
273
+ return;
274
+ }
275
+ // Update the current frame
276
+ const { imageData } = this._frames[this._currentFrame];
277
+ this._context.putImageData(imageData, 0, 0);
278
+ // Workaround hack for Safari & iOS
279
+ // which fails to upload canvas after putImageData
280
+ // See: https://bugs.webkit.org/show_bug.cgi?id=229986
281
+ this._context.fillStyle = "transparent";
282
+ this._context.fillRect(0, 0, 0, 1);
283
+ this.texture.update();
284
+ // Mark as clean
285
+ this.dirty = false;
286
+ }
287
+ /**
288
+ * Renders the object using the WebGL renderer
289
+ *
290
+ * @param {PIXI.Renderer} renderer - The renderer
291
+ * @private
292
+ */
293
+ _render(renderer) {
294
+ this.updateFrame();
295
+ super._render(renderer);
296
+ }
297
+ /**
298
+ * Renders the object using the WebGL renderer
299
+ *
300
+ * @param {PIXI.CanvasRenderer} renderer - The renderer
301
+ * @private
302
+ */
303
+ // eslint-disable-next-line @typescript-eslint/explicit-module-boundary-types
304
+ _renderCanvas(renderer) {
305
+ this.updateFrame();
306
+ // eslint-disable-next-line @typescript-eslint/ban-ts-comment
307
+ // @ts-ignore
308
+ super._renderCanvas(renderer);
309
+ }
310
+ /**
311
+ * Whether to use PIXI.Ticker.shared to auto update animation time.
312
+ * @default true
313
+ */
314
+ get autoUpdate() {
315
+ return this._autoUpdate;
316
+ }
317
+ set autoUpdate(value) {
318
+ if (value !== this._autoUpdate) {
319
+ this._autoUpdate = value;
320
+ if (!this._autoUpdate && this._isConnectedToTicker) {
321
+ Ticker.shared.remove(this.update, this);
322
+ this._isConnectedToTicker = false;
323
+ }
324
+ else if (this._autoUpdate &&
325
+ !this._isConnectedToTicker &&
326
+ this._playing) {
327
+ Ticker.shared.add(this.update, this);
328
+ this._isConnectedToTicker = true;
329
+ }
330
+ }
331
+ }
332
+ /** Set the current frame number */
333
+ get currentFrame() {
334
+ return this._currentFrame;
335
+ }
336
+ set currentFrame(value) {
337
+ this.updateFrameIndex(value);
338
+ this._currentTime = this._frames[value].start;
339
+ }
340
+ /** Internally handle updating the frame index */
341
+ updateFrameIndex(value) {
342
+ if (value < 0 || value >= this._frames.length) {
343
+ throw new Error(`Frame index out of range, expecting 0 to ${this.totalFrames}, got ${value}`);
344
+ }
345
+ if (this._currentFrame !== value) {
346
+ this._currentFrame = value;
347
+ this.dirty = true;
348
+ this.onFrameChange?.(value);
349
+ }
350
+ }
351
+ /**
352
+ * Get the total number of frame in the GIF.
353
+ */
354
+ get totalFrames() {
355
+ return this._frames.length;
356
+ }
357
+ /** Destroy and don't use after this. */
358
+ destroy() {
359
+ this.stop();
360
+ super.destroy(true);
361
+ const forceClear = null;
362
+ this._context = forceClear;
363
+ this._frames = forceClear;
364
+ this.onComplete = forceClear;
365
+ this.onFrameChange = forceClear;
366
+ this.onLoop = forceClear;
367
+ }
368
+ /**
369
+ * Cloning the animation is a useful way to create a duplicate animation.
370
+ * This maintains all the properties of the original animation but allows
371
+ * you to control playback independent of the original animation.
372
+ * If you want to create a simple copy, and not control independently,
373
+ * then you can simply create a new Sprite, e.g. `const sprite = new Sprite(animation.texture)`.
374
+ */
375
+ clone() {
376
+ return new AnimatedGIF([...this._frames], {
377
+ autoUpdate: this._autoUpdate,
378
+ loop: this.loop,
379
+ autoPlay: this.autoPlay,
380
+ scaleMode: this.texture.baseTexture.scaleMode,
381
+ animationSpeed: this.animationSpeed,
382
+ width: this._context.canvas.width,
383
+ height: this._context.canvas.height,
384
+ onComplete: this.onComplete,
385
+ onFrameChange: this.onFrameChange,
386
+ onLoop: this.onLoop,
387
+ });
388
+ }
389
+ }
390
+ export { AnimatedGIF };
391
+ ;
@@ -0,0 +1,33 @@
1
+ import type { IComponent, IComponentContext, ComponentProps, IComponentHook, ComponentRefreshType, ComponentData } from '..';
2
+ import type { AppearanceInput } from '..';
3
+ import { ComponentContext } from './ComponentContext.svelte.js';
4
+ export declare class Component implements IComponent {
5
+ #private;
6
+ constructor(cradle: {
7
+ componentState: ComponentProps;
8
+ componentContext: ComponentContext;
9
+ });
10
+ get id(): string;
11
+ get type(): "IMAGE" | "GIF" | "VIDEO" | "TEXT" | "SHAPE" | "AUDIO" | "COLOR" | "GRADIENT" | "SUBTITLES";
12
+ get props(): ComponentProps;
13
+ get displayObject(): import("pixi.js-legacy").Container<import("pixi.js-legacy").DisplayObject> | undefined;
14
+ get context(): IComponentContext;
15
+ get checksum(): string;
16
+ get autoRefresh(): boolean;
17
+ setAutoRefresh(enabled: boolean): Component;
18
+ private maybeRefresh;
19
+ addHook(hook: IComponentHook, priority?: number): void;
20
+ setup(): Promise<void>;
21
+ update(): Promise<void>;
22
+ refresh(type?: ComponentRefreshType): Promise<void>;
23
+ destroy(): Promise<void>;
24
+ updateAppearance(appearance: Partial<AppearanceInput>): Promise<Component>;
25
+ setStart(start: number): Component;
26
+ setEnd(end: number): Component;
27
+ updateText(text: string): Promise<Component>;
28
+ setText(text: string): Promise<Component>;
29
+ setVisible(visible: boolean): Promise<Component>;
30
+ setOrder(order: number): Promise<Component>;
31
+ onChange(callback: (changes: ComponentData) => void): () => void;
32
+ onTimelineChange(callback: (time: number) => void): () => void;
33
+ }
@@ -0,0 +1,152 @@
1
+ import { ComponentContext } from './ComponentContext.svelte.js';
2
+ export class Component {
3
+ #properties = $state({});
4
+ #context;
5
+ #hooks = [];
6
+ #autoRefresh = false;
7
+ #eventUnsubscribers = [];
8
+ constructor(cradle) {
9
+ this.#properties = cradle.componentState;
10
+ this.#context = cradle.componentContext;
11
+ this.#context.setComponentProps(this.#properties);
12
+ // Set up auto-refresh callback if ComponentState supports it
13
+ if ('setRefreshCallback' in this.#properties &&
14
+ typeof this.#properties.setRefreshCallback === 'function') {
15
+ this.#properties.setRefreshCallback(() => this.maybeRefresh());
16
+ }
17
+ }
18
+ get id() {
19
+ return this.#properties.id;
20
+ }
21
+ get type() {
22
+ return this.#properties.type;
23
+ }
24
+ get props() {
25
+ return this.#properties;
26
+ }
27
+ get displayObject() {
28
+ return this.#context.getResource('pixiRenderObject');
29
+ }
30
+ get context() {
31
+ return this.#context;
32
+ }
33
+ get checksum() {
34
+ return this.#properties.checksum;
35
+ }
36
+ get autoRefresh() {
37
+ return this.#autoRefresh;
38
+ }
39
+ setAutoRefresh(enabled) {
40
+ this.#autoRefresh = enabled;
41
+ return this;
42
+ }
43
+ async maybeRefresh() {
44
+ if (this.#autoRefresh) {
45
+ await this.refresh();
46
+ }
47
+ }
48
+ addHook(hook, priority) {
49
+ const maxPriority = this.#hooks.length > 0 ? Math.max(...this.#hooks.map((h) => h.priority ?? 0)) : 0;
50
+ hook.priority = priority ? priority : maxPriority + 1;
51
+ this.#hooks.push(hook);
52
+ }
53
+ async #handle(type) {
54
+ const hooks = this.#hooks.filter((hook) => hook.types.includes(type));
55
+ await this.#context.runHooks(hooks, type);
56
+ }
57
+ async setup() {
58
+ this.#context.setComponentProps(this.#properties);
59
+ await this.#handle('setup');
60
+ }
61
+ async update() {
62
+ await this.#handle('update');
63
+ }
64
+ async refresh(type = 'refresh') {
65
+ this.#context.setComponentProps(this.#properties);
66
+ await this.#handle(type);
67
+ await this.update(); // also auto update to fix timing bug
68
+ }
69
+ async destroy() {
70
+ // Clean up all event listeners automatically
71
+ // Create a copy of the array to avoid issues with modification during iteration
72
+ const unsubscribers = [...this.#eventUnsubscribers];
73
+ this.#eventUnsubscribers = [];
74
+ unsubscribers.forEach((unsubscribe) => unsubscribe());
75
+ await this.#handle('destroy');
76
+ if (this.displayObject) {
77
+ this.displayObject.destroy();
78
+ }
79
+ }
80
+ // Fluent method chaining - modify existing methods to return Component instance
81
+ async updateAppearance(appearance) {
82
+ await this.#properties.updateAppearance(appearance);
83
+ return this;
84
+ }
85
+ setStart(start) {
86
+ this.#properties.setStart(start);
87
+ return this;
88
+ }
89
+ setEnd(end) {
90
+ this.#properties.setEnd(end);
91
+ return this;
92
+ }
93
+ async updateText(text) {
94
+ await this.#properties.updateText(text);
95
+ return this;
96
+ }
97
+ // Simple fluent wrapper methods
98
+ async setText(text) {
99
+ return this.updateText(text);
100
+ }
101
+ async setVisible(visible) {
102
+ await this.#properties.setVisible(visible);
103
+ return this;
104
+ }
105
+ async setOrder(order) {
106
+ await this.#properties.setOrder(order);
107
+ return this;
108
+ }
109
+ // Component-scoped event filtering methods
110
+ onChange(callback) {
111
+ const wrappedCallback = (e) => {
112
+ const customEvent = e;
113
+ if (customEvent.detail.id === this.id) {
114
+ callback(customEvent.detail);
115
+ }
116
+ };
117
+ // Use addEventListener directly to maintain reference for removal
118
+ this.#context.eventManager.addEventListener('componentchange', wrappedCallback);
119
+ // Create unsubscribe function
120
+ const unsubscribe = () => {
121
+ this.#context.eventManager.removeEventListener('componentchange', wrappedCallback);
122
+ // Remove from tracked unsubscribers
123
+ const index = this.#eventUnsubscribers.indexOf(unsubscribe);
124
+ if (index > -1) {
125
+ this.#eventUnsubscribers.splice(index, 1);
126
+ }
127
+ };
128
+ // Track unsubscribe function for automatic cleanup
129
+ this.#eventUnsubscribers.push(unsubscribe);
130
+ return unsubscribe;
131
+ }
132
+ onTimelineChange(callback) {
133
+ const wrappedCallback = (e) => {
134
+ const customEvent = e;
135
+ callback(customEvent.detail);
136
+ };
137
+ // Use addEventListener directly to maintain reference for removal
138
+ this.#context.eventManager.addEventListener('timeupdate', wrappedCallback);
139
+ // Create unsubscribe function
140
+ const unsubscribe = () => {
141
+ this.#context.eventManager.removeEventListener('timeupdate', wrappedCallback);
142
+ // Remove from tracked unsubscribers
143
+ const index = this.#eventUnsubscribers.indexOf(unsubscribe);
144
+ if (index > -1) {
145
+ this.#eventUnsubscribers.splice(index, 1);
146
+ }
147
+ };
148
+ // Track unsubscribe function for automatic cleanup
149
+ this.#eventUnsubscribers.push(unsubscribe);
150
+ return unsubscribe;
151
+ }
152
+ }
@@ -0,0 +1,33 @@
1
+ import { StateManager } from '../managers/StateManager.svelte.js';
2
+ import { EventManager } from '../managers/EventManager.js';
3
+ import type { IComponentContext, ComponentData, ResourceTypes, IComponentHook, HookType, ComponentProps } from '..';
4
+ export declare class ComponentContext implements IComponentContext {
5
+ #private;
6
+ disabled: boolean;
7
+ resources: Map<keyof ResourceTypes, ResourceTypes[keyof ResourceTypes]>;
8
+ private state;
9
+ eventManager: EventManager;
10
+ constructor(cradle: {
11
+ stateManager: StateManager;
12
+ eventManager: EventManager;
13
+ });
14
+ setComponentProps(props: ComponentProps): void;
15
+ get duration(): number;
16
+ get contextData(): ComponentData;
17
+ get data(): ComponentData;
18
+ get id(): string;
19
+ get type(): "IMAGE" | "GIF" | "VIDEO" | "TEXT" | "SHAPE" | "AUDIO" | "COLOR" | "GRADIENT" | "SUBTITLES";
20
+ get isActive(): boolean;
21
+ get progress(): number;
22
+ get currentComponentTime(): number;
23
+ get componentTimelineTime(): number | undefined;
24
+ get currentTime(): number;
25
+ get sceneState(): StateManager;
26
+ updateContextData(data: ComponentData): void;
27
+ resetContextData(): void;
28
+ getResource<K extends keyof ResourceTypes>(type: K): ResourceTypes[K] | undefined;
29
+ setResource<K extends keyof ResourceTypes>(type: K, resource: ResourceTypes[K]): void;
30
+ removeResource<K extends keyof ResourceTypes>(type: K): void;
31
+ runHooks(hooks: IComponentHook[], type: HookType): Promise<void>;
32
+ destroy(): void;
33
+ }