canvasengine 2.0.0-beta.16 → 2.0.0-beta.17
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/index.d.ts +55 -25
- package/dist/index.js +361 -238
- package/dist/index.js.map +1 -1
- package/package.json +4 -3
- package/src/components/Canvas.ts +53 -45
- package/src/components/Container.ts +2 -2
- package/src/components/DisplayObject.ts +232 -173
- package/src/components/Graphic.ts +18 -7
- package/src/components/NineSliceSprite.ts +4 -1
- package/src/components/ParticleEmitter.ts +12 -8
- package/src/components/Sprite.ts +7 -4
- package/src/components/Text.ts +26 -10
- package/src/components/Viewport.ts +53 -31
- package/src/components/types/DisplayObject.ts +22 -0
- package/src/directives/ViewportFollow.ts +1 -1
- package/src/engine/bootstrap.ts +14 -2
- package/src/engine/reactive.ts +5 -4
- package/src/index.ts +1 -0
- package/src/utils/functions.ts +7 -0
- package/testing/index.ts +3 -2
package/src/components/Text.ts
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { Text as PixiText, TextStyle } from "pixi.js";
|
|
2
|
-
import { createComponent, registerComponent } from "../engine/reactive";
|
|
3
|
-
import { DisplayObject } from "./DisplayObject";
|
|
2
|
+
import { createComponent, registerComponent, Element, Props } from "../engine/reactive";
|
|
3
|
+
import { DisplayObject, ComponentInstance } from "./DisplayObject";
|
|
4
4
|
import { DisplayObjectProps } from "./types/DisplayObject";
|
|
5
5
|
import { Signal } from "@signe/reactive";
|
|
6
6
|
import { on } from "../engine/trigger";
|
|
@@ -9,7 +9,7 @@ enum TextEffect {
|
|
|
9
9
|
Typewriter = "typewriter",
|
|
10
10
|
}
|
|
11
11
|
|
|
12
|
-
interface TextProps extends DisplayObjectProps {
|
|
12
|
+
export interface TextProps extends DisplayObjectProps {
|
|
13
13
|
text?: string;
|
|
14
14
|
style?: Partial<TextStyle>;
|
|
15
15
|
color?: string;
|
|
@@ -21,6 +21,7 @@ interface TextProps extends DisplayObjectProps {
|
|
|
21
21
|
onComplete?: () => void;
|
|
22
22
|
skip?: () => void;
|
|
23
23
|
};
|
|
24
|
+
context?: any; // Ensure context is available, ideally typed from a base prop or injected
|
|
24
25
|
}
|
|
25
26
|
|
|
26
27
|
class CanvasText extends DisplayObject(PixiText) {
|
|
@@ -32,9 +33,15 @@ class CanvasText extends DisplayObject(PixiText) {
|
|
|
32
33
|
private typewriterOptions: any = {};
|
|
33
34
|
private skipSignal?: () => void;
|
|
34
35
|
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
36
|
+
/**
|
|
37
|
+
* Called when the component is mounted to the scene graph.
|
|
38
|
+
* Initializes the typewriter effect if configured.
|
|
39
|
+
* @param {Element<CanvasText>} element - The element being mounted. Its `props` property (of type TextProps) contains component properties and context.
|
|
40
|
+
* @param {number} [index] - The index of the component among its siblings.
|
|
41
|
+
*/
|
|
42
|
+
async onMount(element: Element<CanvasText>, index?: number): Promise<void> {
|
|
43
|
+
await super.onMount(element, index);
|
|
44
|
+
const { props } = element; // props here will be of type TextProps due to Element<CanvasText>
|
|
38
45
|
const tick: Signal = props.context.tick;
|
|
39
46
|
|
|
40
47
|
if (props.text && props.typewriter) {
|
|
@@ -130,13 +137,22 @@ class CanvasText extends DisplayObject(PixiText) {
|
|
|
130
137
|
this.currentIndex = this.fullText.length;
|
|
131
138
|
}
|
|
132
139
|
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
140
|
+
/**
|
|
141
|
+
* Called when the component is about to be destroyed.
|
|
142
|
+
* Unsubscribes from the tick observable.
|
|
143
|
+
* @param {Element<any>} parent - The parent element.
|
|
144
|
+
* @param {() => void} [afterDestroy] - An optional callback function to be executed after the component's own destruction logic.
|
|
145
|
+
*/
|
|
146
|
+
async onDestroy(parent: Element<any>, afterDestroy?: () => void): Promise<void> {
|
|
147
|
+
const _afterDestroy = async () => {
|
|
148
|
+
this.subscriptionTick.unsubscribe();
|
|
149
|
+
afterDestroy();
|
|
150
|
+
}
|
|
151
|
+
await super.onDestroy(parent, _afterDestroy);
|
|
136
152
|
}
|
|
137
153
|
}
|
|
138
154
|
|
|
139
|
-
interface CanvasText extends PixiText {}
|
|
155
|
+
// interface CanvasText extends PixiText {} // Removed as it's redundant and causes type conflicts
|
|
140
156
|
|
|
141
157
|
registerComponent("Text", CanvasText);
|
|
142
158
|
|
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
import { Viewport as PixiViewport } from 'pixi-viewport';
|
|
2
2
|
import { Subscription } from 'rxjs';
|
|
3
|
-
import { createComponent, registerComponent } from '../engine/reactive';
|
|
4
|
-
import { DisplayObject } from './DisplayObject';
|
|
5
|
-
import { effect } from '@signe/reactive';
|
|
3
|
+
import { createComponent, registerComponent, Element, Props } from '../engine/reactive';
|
|
4
|
+
import { DisplayObject, ComponentInstance } from './DisplayObject';
|
|
5
|
+
import { effect, Signal } from '@signe/reactive';
|
|
6
6
|
|
|
7
7
|
const EVENTS = [
|
|
8
8
|
'bounce-x-end',
|
|
@@ -28,6 +28,21 @@ const EVENTS = [
|
|
|
28
28
|
'zoomed-end'
|
|
29
29
|
]
|
|
30
30
|
|
|
31
|
+
export interface ViewportProps extends Props {
|
|
32
|
+
screenWidth?: number;
|
|
33
|
+
screenHeight?: number;
|
|
34
|
+
worldWidth?: number;
|
|
35
|
+
worldHeight?: number;
|
|
36
|
+
clamp?: boolean | {
|
|
37
|
+
left?: number;
|
|
38
|
+
right?: number;
|
|
39
|
+
top?: number;
|
|
40
|
+
bottom?: number;
|
|
41
|
+
};
|
|
42
|
+
context?: any;
|
|
43
|
+
[key: string]: any;
|
|
44
|
+
}
|
|
45
|
+
|
|
31
46
|
export class CanvasViewport extends DisplayObject(PixiViewport) {
|
|
32
47
|
private tickSubscription: Subscription
|
|
33
48
|
overrideProps = ['wheel']
|
|
@@ -52,9 +67,16 @@ export class CanvasViewport extends DisplayObject(PixiViewport) {
|
|
|
52
67
|
}
|
|
53
68
|
}
|
|
54
69
|
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
70
|
+
/**
|
|
71
|
+
* Called when the component is mounted to the scene graph.
|
|
72
|
+
* Initializes viewport settings and subscriptions.
|
|
73
|
+
* @param {Element<CanvasViewport>} element - The element being mounted. Its `props` property (of type ViewportProps) contains component properties and context.
|
|
74
|
+
* @param {number} [index] - The index of the component among its siblings.
|
|
75
|
+
*/
|
|
76
|
+
async onMount(element: Element<CanvasViewport>, index?: number): Promise<void> {
|
|
77
|
+
await super.onMount(element, index);
|
|
78
|
+
const { props } = element;
|
|
79
|
+
const { tick, app, canvasSize } = props.context;
|
|
58
80
|
let isDragging = false
|
|
59
81
|
|
|
60
82
|
effect(() => {
|
|
@@ -62,19 +84,26 @@ export class CanvasViewport extends DisplayObject(PixiViewport) {
|
|
|
62
84
|
this.screenHeight = canvasSize().height
|
|
63
85
|
})
|
|
64
86
|
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
87
|
+
effect(() => {
|
|
88
|
+
const _app = app()
|
|
89
|
+
if (!_app) return
|
|
90
|
+
|
|
91
|
+
const renderer = _app.renderer
|
|
92
|
+
|
|
93
|
+
renderer.events.domElement.addEventListener(
|
|
94
|
+
'wheel',
|
|
95
|
+
this.input.wheelFunction
|
|
96
|
+
);
|
|
69
97
|
|
|
70
|
-
|
|
98
|
+
this.options.events = renderer.events
|
|
99
|
+
})
|
|
71
100
|
|
|
72
101
|
this.tickSubscription = tick.observable.subscribe(({ value }) => {
|
|
73
102
|
this.update(value.timestamp)
|
|
74
103
|
})
|
|
75
104
|
|
|
76
105
|
element.props.context.viewport = this
|
|
77
|
-
this.updateViewportSettings(
|
|
106
|
+
this.updateViewportSettings(props)
|
|
78
107
|
}
|
|
79
108
|
|
|
80
109
|
onUpdate(props) {
|
|
@@ -124,30 +153,23 @@ export class CanvasViewport extends DisplayObject(PixiViewport) {
|
|
|
124
153
|
}
|
|
125
154
|
}
|
|
126
155
|
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
156
|
+
/**
|
|
157
|
+
* Called when the component is about to be destroyed.
|
|
158
|
+
* Unsubscribes from the tick observable.
|
|
159
|
+
* @param {Element<any>} parent - The parent element.
|
|
160
|
+
* @param {() => void} [afterDestroy] - An optional callback function to be executed after the component's own destruction logic.
|
|
161
|
+
*/
|
|
162
|
+
async onDestroy(parent: Element<any>, afterDestroy?: () => void): Promise<void> {
|
|
163
|
+
const _afterDestroy = async () => {
|
|
164
|
+
this.tickSubscription.unsubscribe()
|
|
165
|
+
afterDestroy()
|
|
166
|
+
}
|
|
167
|
+
await super.onDestroy(parent, _afterDestroy);
|
|
130
168
|
}
|
|
131
169
|
}
|
|
132
170
|
|
|
133
|
-
export interface CanvasViewport extends PixiViewport { }
|
|
134
|
-
|
|
135
171
|
registerComponent('Viewport', CanvasViewport)
|
|
136
172
|
|
|
137
|
-
export interface ViewportProps {
|
|
138
|
-
screenWidth?: number;
|
|
139
|
-
screenHeight?: number;
|
|
140
|
-
worldWidth?: number;
|
|
141
|
-
worldHeight?: number;
|
|
142
|
-
clamp?: boolean | {
|
|
143
|
-
left?: number;
|
|
144
|
-
right?: number;
|
|
145
|
-
top?: number;
|
|
146
|
-
bottom?: number;
|
|
147
|
-
};
|
|
148
|
-
[key: string]: any;
|
|
149
|
-
}
|
|
150
|
-
|
|
151
173
|
export function Viewport(props: ViewportProps) {
|
|
152
174
|
return createComponent('Viewport', props);
|
|
153
175
|
}
|
|
@@ -8,6 +8,10 @@ export type JustifyContent = 'flex-start' | 'flex-end' | 'center' | 'space-betwe
|
|
|
8
8
|
export type AlignContent = 'flex-start' | 'flex-end' | 'center' | 'space-between' | 'space-around';
|
|
9
9
|
export type Size = number | `${number}%`
|
|
10
10
|
export type EdgeSize = SignalOrPrimitive<Size | [Size, Size] | [Size, Size, Size, Size]>
|
|
11
|
+
export type ObjectFit = 'contain' | 'cover' | 'fill' | 'none' | 'scale-down';
|
|
12
|
+
export type ObjectPosition = string;
|
|
13
|
+
export type TransformOrigin = string;
|
|
14
|
+
export type PositionType = 'relative' | 'absolute' | 'static';
|
|
11
15
|
|
|
12
16
|
export interface DisplayObjectProps {
|
|
13
17
|
attach?: any;
|
|
@@ -16,6 +20,24 @@ export interface DisplayObjectProps {
|
|
|
16
20
|
y?: SignalOrPrimitive<number>;
|
|
17
21
|
width?: SignalOrPrimitive<Size>;
|
|
18
22
|
height?: SignalOrPrimitive<Size>;
|
|
23
|
+
minWidth?: SignalOrPrimitive<Size>;
|
|
24
|
+
minHeight?: SignalOrPrimitive<Size>;
|
|
25
|
+
maxWidth?: SignalOrPrimitive<Size>;
|
|
26
|
+
maxHeight?: SignalOrPrimitive<Size>;
|
|
27
|
+
aspectRatio?: SignalOrPrimitive<number>;
|
|
28
|
+
flexGrow?: SignalOrPrimitive<number>;
|
|
29
|
+
flexShrink?: SignalOrPrimitive<number>;
|
|
30
|
+
flexBasis?: SignalOrPrimitive<Size>;
|
|
31
|
+
rowGap?: SignalOrPrimitive<number>;
|
|
32
|
+
columnGap?: SignalOrPrimitive<number>;
|
|
33
|
+
positionType?: PositionType;
|
|
34
|
+
top?: SignalOrPrimitive<Size>;
|
|
35
|
+
right?: SignalOrPrimitive<Size>;
|
|
36
|
+
bottom?: SignalOrPrimitive<Size>;
|
|
37
|
+
left?: SignalOrPrimitive<Size>;
|
|
38
|
+
objectFit?: ObjectFit;
|
|
39
|
+
objectPosition?: ObjectPosition;
|
|
40
|
+
transformOrigin?: TransformOrigin;
|
|
19
41
|
children?: any[];
|
|
20
42
|
flexDirection?: FlexDirection;
|
|
21
43
|
justifyContent?: JustifyContent;
|
package/src/engine/bootstrap.ts
CHANGED
|
@@ -1,3 +1,5 @@
|
|
|
1
|
+
import '@pixi/layout';
|
|
2
|
+
import { Application } from "pixi.js";
|
|
1
3
|
import { ComponentFunction, h } from "./signal";
|
|
2
4
|
|
|
3
5
|
/**
|
|
@@ -9,11 +11,21 @@ import { ComponentFunction, h } from "./signal";
|
|
|
9
11
|
* @throws {Error} If the provided element is not a Canvas component.
|
|
10
12
|
*/
|
|
11
13
|
export const bootstrapCanvas = async (rootElement: HTMLElement | null, canvas: ComponentFunction<any>) => {
|
|
14
|
+
|
|
15
|
+
const app = new Application();
|
|
16
|
+
await app.init({
|
|
17
|
+
resizeTo: rootElement,
|
|
18
|
+
autoStart: false,
|
|
19
|
+
});
|
|
20
|
+
|
|
12
21
|
const canvasElement = await h(canvas);
|
|
13
22
|
if (canvasElement.tag != 'Canvas') {
|
|
14
23
|
throw new Error('Canvas is required');
|
|
15
24
|
}
|
|
16
|
-
(canvasElement as any).render(rootElement);
|
|
25
|
+
(canvasElement as any).render(rootElement, app);
|
|
17
26
|
|
|
18
|
-
return
|
|
27
|
+
return {
|
|
28
|
+
canvasElement,
|
|
29
|
+
app
|
|
30
|
+
};
|
|
19
31
|
};
|
package/src/engine/reactive.ts
CHANGED
|
@@ -83,13 +83,14 @@ function destroyElement(element: Element | Element[]) {
|
|
|
83
83
|
if (!element) {
|
|
84
84
|
return;
|
|
85
85
|
}
|
|
86
|
-
element.propSubscriptions.forEach((sub) => sub.unsubscribe());
|
|
87
|
-
element.effectSubscriptions.forEach((sub) => sub.unsubscribe());
|
|
88
|
-
element.effectUnmounts.forEach((fn) => fn?.());
|
|
89
86
|
for (let name in element.directives) {
|
|
90
87
|
element.directives[name].onDestroy?.(element);
|
|
91
88
|
}
|
|
92
|
-
element.componentInstance.onDestroy
|
|
89
|
+
element.componentInstance.onDestroy(element.parent as any, () => {
|
|
90
|
+
element.propSubscriptions.forEach((sub) => sub.unsubscribe());
|
|
91
|
+
element.effectSubscriptions.forEach((sub) => sub.unsubscribe());
|
|
92
|
+
element.effectUnmounts.forEach((fn) => fn?.());
|
|
93
|
+
});
|
|
93
94
|
}
|
|
94
95
|
|
|
95
96
|
/**
|
package/src/index.ts
CHANGED
package/testing/index.ts
CHANGED
|
@@ -5,7 +5,8 @@ export class TestBed {
|
|
|
5
5
|
const comp = () => h(Canvas, {
|
|
6
6
|
tickStart: false
|
|
7
7
|
}, h(component, props, children))
|
|
8
|
-
const
|
|
9
|
-
|
|
8
|
+
const { canvasElement, app } = await bootstrapCanvas(document.getElementById('root'), comp)
|
|
9
|
+
app.render()
|
|
10
|
+
return canvasElement.props.children?.[0]
|
|
10
11
|
}
|
|
11
12
|
}
|