canvasengine 2.0.0-beta.5 → 2.0.0-beta.50
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/dist/components/Button.d.ts +185 -0
- package/dist/components/Button.d.ts.map +1 -0
- package/dist/components/Canvas.d.ts +17 -0
- package/dist/components/Canvas.d.ts.map +1 -0
- package/dist/components/Container.d.ts +86 -0
- package/dist/components/Container.d.ts.map +1 -0
- package/dist/components/DOMContainer.d.ts +98 -0
- package/dist/components/DOMContainer.d.ts.map +1 -0
- package/dist/components/DOMElement.d.ts +54 -0
- package/dist/components/DOMElement.d.ts.map +1 -0
- package/dist/components/DOMSprite.d.ts +127 -0
- package/dist/components/DOMSprite.d.ts.map +1 -0
- package/dist/components/DisplayObject.d.ts +94 -0
- package/dist/components/DisplayObject.d.ts.map +1 -0
- package/dist/components/FocusContainer.d.ts +129 -0
- package/dist/components/FocusContainer.d.ts.map +1 -0
- package/dist/components/Graphic.d.ts +64 -0
- package/dist/components/Graphic.d.ts.map +1 -0
- package/dist/components/Joystick.d.ts +36 -0
- package/dist/components/Joystick.d.ts.map +1 -0
- package/dist/components/Mesh.d.ts +208 -0
- package/dist/components/Mesh.d.ts.map +1 -0
- package/dist/components/NineSliceSprite.d.ts +16 -0
- package/dist/components/NineSliceSprite.d.ts.map +1 -0
- package/dist/components/ParticleEmitter.d.ts +4 -0
- package/dist/components/ParticleEmitter.d.ts.map +1 -0
- package/dist/components/Scene.d.ts +2 -0
- package/dist/components/Scene.d.ts.map +1 -0
- package/dist/components/Sprite.d.ts +242 -0
- package/dist/components/Sprite.d.ts.map +1 -0
- package/dist/components/Text.d.ts +25 -0
- package/dist/components/Text.d.ts.map +1 -0
- package/dist/components/TilingSprite.d.ts +17 -0
- package/dist/components/TilingSprite.d.ts.map +1 -0
- package/dist/components/Video.d.ts +14 -0
- package/dist/components/Video.d.ts.map +1 -0
- package/dist/components/Viewport.d.ts +121 -0
- package/dist/components/Viewport.d.ts.map +1 -0
- package/dist/components/index.d.ts +20 -0
- package/dist/components/index.d.ts.map +1 -0
- package/dist/components/types/DisplayObject.d.ts +106 -0
- package/dist/components/types/DisplayObject.d.ts.map +1 -0
- package/dist/components/types/MouseEvent.d.ts +4 -0
- package/dist/components/types/MouseEvent.d.ts.map +1 -0
- package/dist/components/types/Spritesheet.d.ts +248 -0
- package/dist/components/types/Spritesheet.d.ts.map +1 -0
- package/dist/components/types/index.d.ts +4 -0
- package/dist/components/types/index.d.ts.map +1 -0
- package/dist/directives/Controls.d.ts +112 -0
- package/dist/directives/Controls.d.ts.map +1 -0
- package/dist/directives/ControlsBase.d.ts +199 -0
- package/dist/directives/ControlsBase.d.ts.map +1 -0
- package/dist/directives/Drag.d.ts +69 -0
- package/dist/directives/Drag.d.ts.map +1 -0
- package/dist/directives/Flash.d.ts +116 -0
- package/dist/directives/Flash.d.ts.map +1 -0
- package/dist/directives/FocusNavigation.d.ts +52 -0
- package/dist/directives/FocusNavigation.d.ts.map +1 -0
- package/dist/directives/GamepadControls.d.ts +224 -0
- package/dist/directives/GamepadControls.d.ts.map +1 -0
- package/dist/directives/JoystickControls.d.ts +171 -0
- package/dist/directives/JoystickControls.d.ts.map +1 -0
- package/dist/directives/KeyboardControls.d.ts +219 -0
- package/dist/directives/KeyboardControls.d.ts.map +1 -0
- package/dist/directives/Scheduler.d.ts +35 -0
- package/dist/directives/Scheduler.d.ts.map +1 -0
- package/dist/directives/Shake.d.ts +98 -0
- package/dist/directives/Shake.d.ts.map +1 -0
- package/dist/directives/Sound.d.ts +25 -0
- package/dist/directives/Sound.d.ts.map +1 -0
- package/dist/directives/Transition.d.ts +10 -0
- package/dist/directives/Transition.d.ts.map +1 -0
- package/dist/directives/ViewportCull.d.ts +11 -0
- package/dist/directives/ViewportCull.d.ts.map +1 -0
- package/dist/directives/ViewportFollow.d.ts +18 -0
- package/dist/directives/ViewportFollow.d.ts.map +1 -0
- package/dist/directives/index.d.ts +13 -0
- package/dist/directives/index.d.ts.map +1 -0
- package/dist/engine/FocusManager.d.ts +174 -0
- package/dist/engine/FocusManager.d.ts.map +1 -0
- package/dist/engine/animation.d.ts +72 -0
- package/dist/engine/animation.d.ts.map +1 -0
- package/dist/engine/bootstrap.d.ts +48 -0
- package/dist/engine/bootstrap.d.ts.map +1 -0
- package/dist/engine/directive.d.ts +13 -0
- package/dist/engine/directive.d.ts.map +1 -0
- package/dist/engine/reactive.d.ts +134 -0
- package/dist/engine/reactive.d.ts.map +1 -0
- package/dist/engine/signal.d.ts +71 -0
- package/dist/engine/signal.d.ts.map +1 -0
- package/dist/engine/trigger.d.ts +54 -0
- package/dist/engine/trigger.d.ts.map +1 -0
- package/dist/engine/utils.d.ts +89 -0
- package/dist/engine/utils.d.ts.map +1 -0
- package/dist/hooks/addContext.d.ts +2 -0
- package/dist/hooks/addContext.d.ts.map +1 -0
- package/dist/hooks/useFocus.d.ts +60 -0
- package/dist/hooks/useFocus.d.ts.map +1 -0
- package/dist/hooks/useProps.d.ts +42 -0
- package/dist/hooks/useProps.d.ts.map +1 -0
- package/dist/hooks/useRef.d.ts +4 -0
- package/dist/hooks/useRef.d.ts.map +1 -0
- package/dist/index-DaGekQUW.js +2218 -0
- package/dist/index-DaGekQUW.js.map +1 -0
- package/dist/index.d.ts +19 -1099
- package/dist/index.d.ts.map +1 -0
- package/dist/index.global.js +5 -0
- package/dist/index.global.js.map +1 -0
- package/dist/index.js +11749 -2901
- package/dist/index.js.map +1 -1
- package/dist/utils/Ease.d.ts +17 -0
- package/dist/utils/Ease.d.ts.map +1 -0
- package/dist/utils/GlobalAssetLoader.d.ts +141 -0
- package/dist/utils/GlobalAssetLoader.d.ts.map +1 -0
- package/dist/utils/RadialGradient.d.ts +57 -0
- package/dist/utils/RadialGradient.d.ts.map +1 -0
- package/dist/utils/functions.d.ts +2 -0
- package/dist/utils/functions.d.ts.map +1 -0
- package/dist/utils/tabindex.d.ts +16 -0
- package/dist/utils/tabindex.d.ts.map +1 -0
- package/package.json +13 -7
- package/src/components/Button.ts +399 -0
- package/src/components/Canvas.ts +62 -46
- package/src/components/Container.ts +21 -2
- package/src/components/DOMContainer.ts +379 -0
- package/src/components/DOMElement.ts +556 -0
- package/src/components/DOMSprite.ts +1040 -0
- package/src/components/DisplayObject.ts +392 -201
- package/src/components/FocusContainer.ts +368 -0
- package/src/components/Graphic.ts +227 -66
- package/src/components/Joystick.ts +363 -0
- package/src/components/Mesh.ts +222 -0
- package/src/components/NineSliceSprite.ts +4 -1
- package/src/components/ParticleEmitter.ts +12 -8
- package/src/components/Sprite.ts +297 -31
- package/src/components/Text.ts +125 -18
- package/src/components/Video.ts +2 -2
- package/src/components/Viewport.ts +118 -63
- package/src/components/index.ts +9 -2
- package/src/components/types/DisplayObject.ts +41 -4
- package/src/components/types/Spritesheet.ts +0 -118
- package/src/directives/Controls.ts +254 -0
- package/src/directives/ControlsBase.ts +267 -0
- package/src/directives/Drag.ts +357 -52
- package/src/directives/Flash.ts +419 -0
- package/src/directives/FocusNavigation.ts +113 -0
- package/src/directives/GamepadControls.ts +537 -0
- package/src/directives/JoystickControls.ts +396 -0
- package/src/directives/KeyboardControls.ts +85 -430
- package/src/directives/Scheduler.ts +12 -4
- package/src/directives/Shake.ts +298 -0
- package/src/directives/Sound.ts +94 -31
- package/src/directives/ViewportFollow.ts +40 -9
- package/src/directives/index.ts +12 -6
- package/src/engine/FocusManager.ts +510 -0
- package/src/engine/animation.ts +175 -21
- package/src/engine/bootstrap.ts +93 -3
- package/src/engine/directive.ts +4 -4
- package/src/engine/reactive.ts +901 -161
- package/src/engine/signal.ts +113 -25
- package/src/engine/trigger.ts +34 -7
- package/src/engine/utils.ts +19 -3
- package/src/hooks/useFocus.ts +91 -0
- package/src/hooks/useProps.ts +1 -1
- package/src/index.ts +8 -2
- package/src/types/pixi-cull.d.ts +7 -0
- package/src/utils/GlobalAssetLoader.ts +257 -0
- package/src/utils/functions.ts +7 -0
- package/src/utils/tabindex.ts +70 -0
- package/testing/index.ts +35 -4
- package/tsconfig.json +18 -0
- package/vite.config.ts +39 -0
package/src/engine/animation.ts
CHANGED
|
@@ -1,10 +1,24 @@
|
|
|
1
|
-
import { effect, signal, type WritableSignal } from "@signe/reactive";
|
|
1
|
+
import { effect, signal, type WritableSignal, type Signal } from "@signe/reactive";
|
|
2
2
|
import { animate as animatePopmotion } from "popmotion";
|
|
3
|
+
import { Tick } from "../directives/Scheduler";
|
|
4
|
+
import { Subscription } from "rxjs";
|
|
3
5
|
|
|
4
|
-
|
|
6
|
+
/**
|
|
7
|
+
* Gets the global tick signal from the engine context.
|
|
8
|
+
* This is automatically set by the Canvas component when it initializes.
|
|
9
|
+
*
|
|
10
|
+
* @returns The global tick signal if available, undefined otherwise
|
|
11
|
+
*/
|
|
12
|
+
function getGlobalTickSignal(): Signal<Tick> | undefined {
|
|
13
|
+
return (globalThis as any).__CANVAS_ENGINE_TICK__;
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
export interface AnimateOptions<T> {
|
|
5
17
|
duration?: number;
|
|
6
18
|
ease?: (t: number) => number;
|
|
7
19
|
onUpdate?: (value: T) => void;
|
|
20
|
+
onComplete?: () => void;
|
|
21
|
+
tick?: Signal<Tick>;
|
|
8
22
|
}
|
|
9
23
|
|
|
10
24
|
export interface AnimatedState<T> {
|
|
@@ -15,15 +29,65 @@ export interface AnimatedState<T> {
|
|
|
15
29
|
|
|
16
30
|
export interface AnimatedSignal<T> extends Omit<WritableSignal<T>, 'set'> {
|
|
17
31
|
(): T;
|
|
18
|
-
set: (newValue: T) => void
|
|
32
|
+
set: (newValue: T, options?: AnimateOptions<T>) => Promise<void>;
|
|
19
33
|
animatedState: WritableSignal<AnimatedState<T>>;
|
|
20
34
|
update: (updater: (value: T) => T) => void;
|
|
35
|
+
pause: () => void;
|
|
36
|
+
resume: () => void;
|
|
21
37
|
}
|
|
22
38
|
|
|
23
39
|
export function isAnimatedSignal(signal: WritableSignal<any>): boolean {
|
|
24
40
|
return (signal as unknown as AnimatedSignal<any>).animatedState !== undefined;
|
|
25
41
|
}
|
|
26
42
|
|
|
43
|
+
/**
|
|
44
|
+
* Creates a popmotion driver that uses the engine's tick system.
|
|
45
|
+
* The driver subscribes to the tick signal and calls the update function with deltaTime on each tick.
|
|
46
|
+
*
|
|
47
|
+
* @param tickSignal - The tick signal from the engine context
|
|
48
|
+
* @returns A driver function for popmotion
|
|
49
|
+
* @example
|
|
50
|
+
* ```ts
|
|
51
|
+
* const driver = createTickDriver(context.tick);
|
|
52
|
+
* animate({
|
|
53
|
+
* to: 100,
|
|
54
|
+
* driver: driver
|
|
55
|
+
* });
|
|
56
|
+
* ```
|
|
57
|
+
*/
|
|
58
|
+
function createTickDriver(tickSignal: Signal<Tick>) {
|
|
59
|
+
return (update: (delta: number) => void) => {
|
|
60
|
+
let subscription: Subscription | undefined;
|
|
61
|
+
let lastTimestamp: number | null = null;
|
|
62
|
+
|
|
63
|
+
const start = () => {
|
|
64
|
+
if (subscription) return;
|
|
65
|
+
|
|
66
|
+
subscription = (tickSignal.observable as any).subscribe((result: any) => {
|
|
67
|
+
const tick = result?.value ?? result;
|
|
68
|
+
if (!tick) return;
|
|
69
|
+
|
|
70
|
+
if (lastTimestamp === null) {
|
|
71
|
+
lastTimestamp = tick.timestamp;
|
|
72
|
+
return;
|
|
73
|
+
}
|
|
74
|
+
|
|
75
|
+
const delta = tick.deltaTime;
|
|
76
|
+
lastTimestamp = tick.timestamp;
|
|
77
|
+
update(delta);
|
|
78
|
+
});
|
|
79
|
+
};
|
|
80
|
+
|
|
81
|
+
const stop = () => {
|
|
82
|
+
subscription?.unsubscribe();
|
|
83
|
+
subscription = undefined;
|
|
84
|
+
lastTimestamp = null;
|
|
85
|
+
};
|
|
86
|
+
|
|
87
|
+
return { start, stop };
|
|
88
|
+
};
|
|
89
|
+
}
|
|
90
|
+
|
|
27
91
|
/**
|
|
28
92
|
* Creates an animated signal with the given initial value and animation options.
|
|
29
93
|
* It's a writable signal that can be animated using popmotion. Properties of the animated signal are:
|
|
@@ -31,16 +95,26 @@ export function isAnimatedSignal(signal: WritableSignal<any>): boolean {
|
|
|
31
95
|
* - start: the start value of the animation.
|
|
32
96
|
* - end: the end value of the animation.
|
|
33
97
|
*
|
|
98
|
+
* If a tick signal is provided in options, the animation will use the engine's tick system.
|
|
99
|
+
* Otherwise, it will automatically use the global tick signal from the Canvas context if available.
|
|
100
|
+
* If no tick signal is available, it will use requestAnimationFrame by default.
|
|
101
|
+
*
|
|
34
102
|
* @param initialValue The initial value of the signal.
|
|
35
|
-
* @param options The animation options.
|
|
103
|
+
* @param options The animation options. Can include a `tick` signal to use a specific tick system.
|
|
36
104
|
* @returns The animated signal.
|
|
37
105
|
* @example
|
|
106
|
+
* ```ts
|
|
107
|
+
* // Automatically uses the Canvas tick system if available, otherwise requestAnimationFrame
|
|
38
108
|
* const animatedValue = animatedSignal(0, { duration: 1000 });
|
|
39
109
|
* animatedValue.set(10);
|
|
40
|
-
* animatedValue.update((value) => value + 1);
|
|
41
|
-
* console.log(animatedValue()); // 11
|
|
42
110
|
*
|
|
43
|
-
*
|
|
111
|
+
* // Explicitly using a specific tick signal
|
|
112
|
+
* mount((element) => {
|
|
113
|
+
* const tickSignal = element.props.context.tick;
|
|
114
|
+
* const animatedValue = animatedSignal(0, { duration: 1000, tick: tickSignal });
|
|
115
|
+
* animatedValue.set(10);
|
|
116
|
+
* });
|
|
117
|
+
* ```
|
|
44
118
|
*/
|
|
45
119
|
export function animatedSignal<T>(initialValue: T, options: AnimateOptions<T> = {}): AnimatedSignal<T> {
|
|
46
120
|
const state: AnimatedState<T> = {
|
|
@@ -48,7 +122,9 @@ export function animatedSignal<T>(initialValue: T, options: AnimateOptions<T> =
|
|
|
48
122
|
start: initialValue,
|
|
49
123
|
end: initialValue,
|
|
50
124
|
};
|
|
51
|
-
|
|
125
|
+
const DEFAULT_DURATION = 20;
|
|
126
|
+
let animation: { stop: () => void } | null = null;
|
|
127
|
+
let isPaused = false;
|
|
52
128
|
|
|
53
129
|
const publicSignal = signal(initialValue);
|
|
54
130
|
const privateSignal = signal(state);
|
|
@@ -60,7 +136,8 @@ export function animatedSignal<T>(initialValue: T, options: AnimateOptions<T> =
|
|
|
60
136
|
|
|
61
137
|
function animatedSignal(): AnimatedState<T>;
|
|
62
138
|
function animatedSignal(newValue: T): void;
|
|
63
|
-
function animatedSignal(newValue
|
|
139
|
+
function animatedSignal(newValue: T, animationConfig: AnimateOptions<T>): void;
|
|
140
|
+
function animatedSignal(newValue?: T, animationConfig: AnimateOptions<T> = {}): AnimatedState<T> | void {
|
|
64
141
|
if (newValue === undefined) {
|
|
65
142
|
return privateSignal();
|
|
66
143
|
}
|
|
@@ -74,23 +151,43 @@ export function animatedSignal<T>(initialValue: T, options: AnimateOptions<T> =
|
|
|
74
151
|
|
|
75
152
|
privateSignal.set(newState);
|
|
76
153
|
|
|
154
|
+
// Stop any running animation
|
|
77
155
|
if (animation) {
|
|
78
156
|
animation.stop();
|
|
157
|
+
animation = null;
|
|
79
158
|
}
|
|
80
159
|
|
|
160
|
+
isPaused = false;
|
|
161
|
+
const mergedConfig = { ...options, ...animationConfig };
|
|
162
|
+
const duration = mergedConfig.duration ?? DEFAULT_DURATION;
|
|
163
|
+
const ease = mergedConfig.ease ?? ((t: number) => t);
|
|
164
|
+
const tickSignal = mergedConfig.tick || getGlobalTickSignal();
|
|
165
|
+
|
|
166
|
+
const startValue = prevState.current;
|
|
167
|
+
const endValue = newValue;
|
|
168
|
+
|
|
169
|
+
const onCompleteCb = animationConfig.onComplete ?? options.onComplete;
|
|
170
|
+
|
|
171
|
+
|
|
81
172
|
animation = animatePopmotion({
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
onUpdate: (value) => {
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
173
|
+
from: startValue as any,
|
|
174
|
+
to: endValue as any,
|
|
175
|
+
duration,
|
|
176
|
+
ease,
|
|
177
|
+
|
|
178
|
+
onUpdate: (value: any) => {
|
|
179
|
+
if (isPaused) return;
|
|
180
|
+
const nextValue = value as T;
|
|
181
|
+
privateSignal.update(s => ({ ...s, current: nextValue }));
|
|
182
|
+
mergedConfig.onUpdate?.(nextValue);
|
|
183
|
+
animationConfig.onUpdate?.(nextValue);
|
|
92
184
|
},
|
|
185
|
+
onComplete: () => {
|
|
186
|
+
privateSignal.update(s => ({ ...s, current: endValue }));
|
|
187
|
+
onCompleteCb?.();
|
|
188
|
+
}
|
|
93
189
|
});
|
|
190
|
+
|
|
94
191
|
}
|
|
95
192
|
|
|
96
193
|
const fn = function() {
|
|
@@ -105,9 +202,66 @@ export function animatedSignal<T>(initialValue: T, options: AnimateOptions<T> =
|
|
|
105
202
|
fn.update = (updater: (value: T) => any) => {
|
|
106
203
|
animatedSignal(updater(privateSignal().current));
|
|
107
204
|
}
|
|
108
|
-
fn.set = (newValue: T) => {
|
|
109
|
-
|
|
205
|
+
fn.set = async (newValue: T, animationConfig: AnimateOptions<T> = {}) => {
|
|
206
|
+
return new Promise<void>((resolve) => {
|
|
207
|
+
const userOnComplete = animationConfig.onComplete;
|
|
208
|
+
animatedSignal(newValue, {
|
|
209
|
+
...animationConfig,
|
|
210
|
+
onComplete: () => {
|
|
211
|
+
if (userOnComplete) {
|
|
212
|
+
userOnComplete();
|
|
213
|
+
} else if (options.onComplete) {
|
|
214
|
+
options.onComplete();
|
|
215
|
+
}
|
|
216
|
+
resolve();
|
|
217
|
+
}
|
|
218
|
+
});
|
|
219
|
+
});
|
|
220
|
+
}
|
|
221
|
+
fn.pause = () => {
|
|
222
|
+
if (isPaused) return;
|
|
223
|
+
isPaused = true;
|
|
224
|
+
if (animation) {
|
|
225
|
+
animation.stop();
|
|
226
|
+
animation = null;
|
|
227
|
+
}
|
|
228
|
+
}
|
|
229
|
+
fn.resume = () => {
|
|
230
|
+
if (!isPaused) return;
|
|
231
|
+
isPaused = false;
|
|
232
|
+
const currentState = privateSignal();
|
|
233
|
+
if (currentState.current !== currentState.end) {
|
|
234
|
+
animatedSignal(currentState.end, options);
|
|
235
|
+
}
|
|
110
236
|
}
|
|
111
237
|
|
|
112
238
|
return fn as any
|
|
239
|
+
}
|
|
240
|
+
|
|
241
|
+
/**
|
|
242
|
+
* Executes a sequence of animations. If an array is provided as an element in the sequence,
|
|
243
|
+
* those animations will be executed in parallel.
|
|
244
|
+
*
|
|
245
|
+
* @param sequence Array of animation functions or arrays of animation functions for parallel execution
|
|
246
|
+
* @returns Promise that resolves when all animations are complete
|
|
247
|
+
* @example
|
|
248
|
+
* ```ts
|
|
249
|
+
* await animatedSequence([
|
|
250
|
+
* () => value1.set(10),
|
|
251
|
+
* [
|
|
252
|
+
* () => value2.set(20),
|
|
253
|
+
* () => value3.set(30)
|
|
254
|
+
* ],
|
|
255
|
+
* () => value1.set(0)
|
|
256
|
+
* ])
|
|
257
|
+
* ```
|
|
258
|
+
*/
|
|
259
|
+
export async function animatedSequence(sequence: ((() => Promise<void>) | (() => Promise<void>)[])[]) {
|
|
260
|
+
for (const item of sequence) {
|
|
261
|
+
if (Array.isArray(item)) {
|
|
262
|
+
await Promise.all(item.map(fn => fn()));
|
|
263
|
+
} else {
|
|
264
|
+
await item();
|
|
265
|
+
}
|
|
266
|
+
}
|
|
113
267
|
}
|
package/src/engine/bootstrap.ts
CHANGED
|
@@ -1,19 +1,109 @@
|
|
|
1
|
+
import { Application, ApplicationOptions } from "pixi.js";
|
|
1
2
|
import { ComponentFunction, h } from "./signal";
|
|
3
|
+
import { useProps } from '../hooks/useProps';
|
|
4
|
+
import { registerAllComponents, registerComponent } from './reactive';
|
|
5
|
+
|
|
6
|
+
// Import all components to ensure they are registered
|
|
7
|
+
// This is done here (not in reactive.ts) to avoid circular dependencies
|
|
8
|
+
// Components register themselves when their modules are imported
|
|
9
|
+
import '../components/Canvas';
|
|
10
|
+
import '../components/Container';
|
|
11
|
+
import '../components/Sprite';
|
|
12
|
+
import '../components/Text';
|
|
13
|
+
import '../components/Graphic';
|
|
14
|
+
import '../components/Mesh';
|
|
15
|
+
import '../components/Viewport';
|
|
16
|
+
import '../components/TilingSprite';
|
|
17
|
+
import '../components/NineSliceSprite';
|
|
18
|
+
import '../components/DOMContainer';
|
|
19
|
+
import '../components/DOMElement';
|
|
20
|
+
import '../components/ParticleEmitter';
|
|
21
|
+
|
|
22
|
+
/**
|
|
23
|
+
* Extended options for bootstrapCanvas that includes component registration configuration.
|
|
24
|
+
*
|
|
25
|
+
* @property components - Optional mapping of component names to their classes (can include mocks for testing)
|
|
26
|
+
* @property autoRegister - If true (default), registers all default components before applying custom components. If false, only registers the specified components.
|
|
27
|
+
*/
|
|
28
|
+
export interface BootstrapOptions extends ApplicationOptions {
|
|
29
|
+
components?: {
|
|
30
|
+
[name: string]: any; // ComponentClass
|
|
31
|
+
};
|
|
32
|
+
autoRegister?: boolean; // true by default if components is not provided
|
|
33
|
+
enableLayout?: boolean; // true by default
|
|
34
|
+
}
|
|
2
35
|
|
|
3
36
|
/**
|
|
4
37
|
* Bootstraps a canvas element and renders it to the DOM.
|
|
5
38
|
*
|
|
6
39
|
* @param rootElement - The HTML element where the canvas will be rendered. Can be null.
|
|
7
40
|
* @param canvas - A Promise that resolves to an Element representing the canvas component.
|
|
41
|
+
* @param options - Optional bootstrap options including ApplicationOptions and component registration configuration.
|
|
8
42
|
* @returns A Promise that resolves to the rendered canvas element.
|
|
9
43
|
* @throws {Error} If the provided element is not a Canvas component.
|
|
44
|
+
*
|
|
45
|
+
* @example
|
|
46
|
+
* ```typescript
|
|
47
|
+
* // Default: all components registered automatically
|
|
48
|
+
* await bootstrapCanvas(rootElement, MyComponent, {
|
|
49
|
+
* width: 800,
|
|
50
|
+
* height: 600
|
|
51
|
+
* });
|
|
52
|
+
* ```
|
|
53
|
+
*
|
|
54
|
+
* @example
|
|
55
|
+
* ```typescript
|
|
56
|
+
* // With mocks for testing
|
|
57
|
+
* import { mockComponents } from '@canvasengine/testing';
|
|
58
|
+
* await bootstrapCanvas(rootElement, MyComponent, {
|
|
59
|
+
* components: mockComponents,
|
|
60
|
+
* autoRegister: false
|
|
61
|
+
* });
|
|
62
|
+
* ```
|
|
10
63
|
*/
|
|
11
|
-
export const bootstrapCanvas = async (rootElement: HTMLElement | null, canvas: ComponentFunction<any
|
|
64
|
+
export const bootstrapCanvas = async (rootElement: HTMLElement | null, canvas: ComponentFunction<any>, options?: BootstrapOptions) => {
|
|
65
|
+
// Extract component registration options
|
|
66
|
+
const { components, autoRegister, enableLayout, ...appOptions } = options ?? {};
|
|
67
|
+
if (enableLayout !== false) {
|
|
68
|
+
await import('@pixi/layout');
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
// Handle component registration
|
|
72
|
+
if (components) {
|
|
73
|
+
if (autoRegister !== false) {
|
|
74
|
+
// Register all default components first, then override with custom ones
|
|
75
|
+
registerAllComponents();
|
|
76
|
+
}
|
|
77
|
+
// Register the specified components (overriding defaults if autoRegister is true)
|
|
78
|
+
Object.entries(components).forEach(([name, componentClass]) => {
|
|
79
|
+
registerComponent(name, componentClass);
|
|
80
|
+
});
|
|
81
|
+
} else {
|
|
82
|
+
// Default behavior: register all components
|
|
83
|
+
registerAllComponents();
|
|
84
|
+
}
|
|
85
|
+
|
|
86
|
+
const app = new Application();
|
|
87
|
+
await app.init({
|
|
88
|
+
resizeTo: rootElement,
|
|
89
|
+
autoStart: false,
|
|
90
|
+
antialias: true,
|
|
91
|
+
...appOptions
|
|
92
|
+
});
|
|
12
93
|
const canvasElement = await h(canvas);
|
|
13
94
|
if (canvasElement.tag != 'Canvas') {
|
|
14
95
|
throw new Error('Canvas is required');
|
|
15
96
|
}
|
|
16
|
-
(canvasElement as any).render(rootElement);
|
|
97
|
+
(canvasElement as any).render(rootElement, app);
|
|
98
|
+
|
|
99
|
+
const { backgroundColor } = useProps(canvasElement.props, {
|
|
100
|
+
backgroundColor: 'black'
|
|
101
|
+
});
|
|
102
|
+
|
|
103
|
+
app.renderer.background.color = backgroundColor()
|
|
17
104
|
|
|
18
|
-
return
|
|
105
|
+
return {
|
|
106
|
+
canvasElement,
|
|
107
|
+
app
|
|
108
|
+
};
|
|
19
109
|
};
|
package/src/engine/directive.ts
CHANGED
|
@@ -3,21 +3,21 @@ import { Element } from "./reactive"
|
|
|
3
3
|
export const directives: { [key: string]: any } = {}
|
|
4
4
|
|
|
5
5
|
export abstract class Directive {
|
|
6
|
-
abstract onDestroy();
|
|
6
|
+
abstract onDestroy(element: Element<any>);
|
|
7
7
|
abstract onInit(element: Element<any>);
|
|
8
8
|
abstract onMount(element: Element<any>);
|
|
9
|
-
abstract onUpdate(props: any);
|
|
9
|
+
abstract onUpdate(props: any, element: Element<any>);
|
|
10
10
|
}
|
|
11
11
|
|
|
12
12
|
export function registerDirective(name: string, directive: any) {
|
|
13
13
|
directives[name] = directive
|
|
14
14
|
}
|
|
15
15
|
|
|
16
|
-
export function applyDirective(element: Element
|
|
16
|
+
export function applyDirective(element: Element<any>, directiveName: string) {
|
|
17
17
|
if (!directives[directiveName]) {
|
|
18
18
|
return null
|
|
19
19
|
}
|
|
20
20
|
const directive = new directives[directiveName]()
|
|
21
21
|
directive.onInit?.(element)
|
|
22
22
|
return directive
|
|
23
|
-
}
|
|
23
|
+
}
|