canvasengine 2.0.0-beta.3 → 2.0.0-beta.31

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 (130) hide show
  1. package/dist/DebugRenderer-DrlzuIVv.js +172 -0
  2. package/dist/DebugRenderer-DrlzuIVv.js.map +1 -0
  3. package/dist/components/Button.d.ts +136 -0
  4. package/dist/components/Button.d.ts.map +1 -0
  5. package/dist/components/Canvas.d.ts +18 -0
  6. package/dist/components/Canvas.d.ts.map +1 -0
  7. package/dist/components/Container.d.ts +80 -0
  8. package/dist/components/Container.d.ts.map +1 -0
  9. package/dist/components/DOMContainer.d.ts +77 -0
  10. package/dist/components/DOMContainer.d.ts.map +1 -0
  11. package/dist/components/DOMElement.d.ts +44 -0
  12. package/dist/components/DOMElement.d.ts.map +1 -0
  13. package/dist/components/DisplayObject.d.ts +82 -0
  14. package/dist/components/DisplayObject.d.ts.map +1 -0
  15. package/dist/components/Graphic.d.ts +65 -0
  16. package/dist/components/Graphic.d.ts.map +1 -0
  17. package/dist/components/Mesh.d.ts +202 -0
  18. package/dist/components/Mesh.d.ts.map +1 -0
  19. package/dist/components/NineSliceSprite.d.ts +17 -0
  20. package/dist/components/NineSliceSprite.d.ts.map +1 -0
  21. package/dist/components/ParticleEmitter.d.ts +5 -0
  22. package/dist/components/ParticleEmitter.d.ts.map +1 -0
  23. package/dist/components/Scene.d.ts +2 -0
  24. package/dist/components/Scene.d.ts.map +1 -0
  25. package/dist/components/Sprite.d.ts +174 -0
  26. package/dist/components/Sprite.d.ts.map +1 -0
  27. package/dist/components/Text.d.ts +21 -0
  28. package/dist/components/Text.d.ts.map +1 -0
  29. package/dist/components/TilingSprite.d.ts +18 -0
  30. package/dist/components/TilingSprite.d.ts.map +1 -0
  31. package/dist/components/Video.d.ts +15 -0
  32. package/dist/components/Video.d.ts.map +1 -0
  33. package/dist/components/Viewport.d.ts +106 -0
  34. package/dist/components/Viewport.d.ts.map +1 -0
  35. package/dist/components/index.d.ts +17 -0
  36. package/dist/components/index.d.ts.map +1 -0
  37. package/dist/components/types/DisplayObject.d.ts +106 -0
  38. package/dist/components/types/DisplayObject.d.ts.map +1 -0
  39. package/dist/components/types/MouseEvent.d.ts +4 -0
  40. package/dist/components/types/MouseEvent.d.ts.map +1 -0
  41. package/dist/components/types/Spritesheet.d.ts +366 -0
  42. package/dist/components/types/Spritesheet.d.ts.map +1 -0
  43. package/dist/components/types/index.d.ts +5 -0
  44. package/dist/components/types/index.d.ts.map +1 -0
  45. package/dist/directives/Drag.d.ts +70 -0
  46. package/dist/directives/Drag.d.ts.map +1 -0
  47. package/dist/directives/KeyboardControls.d.ts +530 -0
  48. package/dist/directives/KeyboardControls.d.ts.map +1 -0
  49. package/dist/directives/Scheduler.d.ts +36 -0
  50. package/dist/directives/Scheduler.d.ts.map +1 -0
  51. package/dist/directives/Sound.d.ts +26 -0
  52. package/dist/directives/Sound.d.ts.map +1 -0
  53. package/dist/directives/Transition.d.ts +11 -0
  54. package/dist/directives/Transition.d.ts.map +1 -0
  55. package/dist/directives/ViewportCull.d.ts +12 -0
  56. package/dist/directives/ViewportCull.d.ts.map +1 -0
  57. package/dist/directives/ViewportFollow.d.ts +19 -0
  58. package/dist/directives/ViewportFollow.d.ts.map +1 -0
  59. package/dist/directives/index.d.ts +2 -0
  60. package/dist/directives/index.d.ts.map +1 -0
  61. package/dist/engine/animation.d.ts +59 -0
  62. package/dist/engine/animation.d.ts.map +1 -0
  63. package/dist/engine/bootstrap.d.ts +16 -0
  64. package/dist/engine/bootstrap.d.ts.map +1 -0
  65. package/dist/engine/directive.d.ts +14 -0
  66. package/dist/engine/directive.d.ts.map +1 -0
  67. package/dist/engine/reactive.d.ts +95 -0
  68. package/dist/engine/reactive.d.ts.map +1 -0
  69. package/dist/engine/signal.d.ts +72 -0
  70. package/dist/engine/signal.d.ts.map +1 -0
  71. package/dist/engine/trigger.d.ts +51 -0
  72. package/dist/engine/trigger.d.ts.map +1 -0
  73. package/dist/engine/utils.d.ts +90 -0
  74. package/dist/engine/utils.d.ts.map +1 -0
  75. package/dist/hooks/addContext.d.ts +2 -0
  76. package/dist/hooks/addContext.d.ts.map +1 -0
  77. package/dist/hooks/useProps.d.ts +42 -0
  78. package/dist/hooks/useProps.d.ts.map +1 -0
  79. package/dist/hooks/useRef.d.ts +5 -0
  80. package/dist/hooks/useRef.d.ts.map +1 -0
  81. package/dist/index-DNDNQN-q.js +11088 -0
  82. package/dist/index-DNDNQN-q.js.map +1 -0
  83. package/dist/index.d.ts +15 -919
  84. package/dist/index.d.ts.map +1 -0
  85. package/dist/index.global.js +29 -0
  86. package/dist/index.global.js.map +1 -0
  87. package/dist/index.js +63 -2950
  88. package/dist/index.js.map +1 -1
  89. package/dist/utils/Ease.d.ts +17 -0
  90. package/dist/utils/Ease.d.ts.map +1 -0
  91. package/dist/utils/RadialGradient.d.ts +58 -0
  92. package/dist/utils/RadialGradient.d.ts.map +1 -0
  93. package/dist/utils/functions.d.ts +2 -0
  94. package/dist/utils/functions.d.ts.map +1 -0
  95. package/index.d.ts +4 -0
  96. package/package.json +12 -7
  97. package/src/components/Button.ts +269 -0
  98. package/src/components/Canvas.ts +53 -45
  99. package/src/components/Container.ts +2 -2
  100. package/src/components/DOMContainer.ts +123 -0
  101. package/src/components/DOMElement.ts +421 -0
  102. package/src/components/DisplayObject.ts +283 -190
  103. package/src/components/Graphic.ts +200 -34
  104. package/src/components/Mesh.ts +222 -0
  105. package/src/components/NineSliceSprite.ts +4 -1
  106. package/src/components/ParticleEmitter.ts +12 -8
  107. package/src/components/Sprite.ts +92 -22
  108. package/src/components/Text.ts +34 -14
  109. package/src/components/Video.ts +110 -0
  110. package/src/components/Viewport.ts +59 -43
  111. package/src/components/index.ts +7 -2
  112. package/src/components/types/DisplayObject.ts +30 -0
  113. package/src/directives/Drag.ts +357 -52
  114. package/src/directives/KeyboardControls.ts +3 -1
  115. package/src/directives/Sound.ts +94 -31
  116. package/src/directives/ViewportFollow.ts +35 -7
  117. package/src/engine/animation.ts +41 -5
  118. package/src/engine/bootstrap.ts +23 -3
  119. package/src/engine/directive.ts +2 -2
  120. package/src/engine/reactive.ts +542 -170
  121. package/src/engine/signal.ts +22 -2
  122. package/src/engine/trigger.ts +65 -9
  123. package/src/engine/utils.ts +97 -9
  124. package/src/hooks/useProps.ts +1 -1
  125. package/src/index.ts +4 -1
  126. package/src/utils/RadialGradient.ts +29 -0
  127. package/src/utils/functions.ts +7 -0
  128. package/testing/index.ts +12 -0
  129. package/tsconfig.json +17 -0
  130. package/vite.config.ts +39 -0
@@ -1,22 +1,25 @@
1
- import { Node } from "yoga-layout";
2
1
  import { Element, isElement, Props } from "../engine/reactive";
3
2
  import { setObservablePoint } from "../engine/utils";
4
3
  import type {
5
4
  AlignContent,
6
5
  EdgeSize,
7
6
  FlexDirection,
8
- Size,
7
+ ObjectFit,
8
+ ObjectPosition,
9
+ TransformOrigin,
9
10
  } from "./types/DisplayObject";
10
- import { effect, Signal, signal } from "@signe/reactive";
11
- import { DropShadowFilter } from "pixi-filters";
11
+ import { signal } from "@signe/reactive";
12
12
  import { BlurFilter, ObservablePoint } from "pixi.js";
13
+ import * as FILTERS from "pixi-filters";
14
+ import { isPercent } from "../utils/functions";
15
+ import { BehaviorSubject, filter, Subject } from "rxjs";
13
16
 
14
17
  export interface ComponentInstance extends PixiMixins.ContainerOptions {
15
18
  id?: string;
16
19
  children?: ComponentInstance[];
17
20
  onInit?(props: Props): void;
18
21
  onUpdate?(props: Props): void;
19
- onDestroy?(parent: Element): void;
22
+ onDestroy?(parent: Element, afterDestroy: () => void): void;
20
23
  onMount?(context: Element, index?: number): void;
21
24
  setWidth(width: number): void;
22
25
  setHeight(height: number): void;
@@ -93,6 +96,8 @@ export const EVENTS = [
93
96
  "wheelcapture",
94
97
  ];
95
98
 
99
+ export type OnHook = (() => void) | (() => Promise<void> | void);
100
+
96
101
  export function DisplayObject(extendClass) {
97
102
  return class DisplayObject extends extendClass {
98
103
  #canvasContext: {
@@ -101,117 +106,103 @@ export function DisplayObject(extendClass) {
101
106
  isFlex: boolean = false;
102
107
  fullProps: Props = {};
103
108
  isMounted: boolean = false;
104
- _anchorPoints = new ObservablePoint(
105
- { _onUpdate: () => {} },
106
- 0,
107
- 0
108
- );
109
+ _anchorPoints = new ObservablePoint({ _onUpdate: () => {} }, 0, 0);
109
110
  isCustomAnchor: boolean = false;
110
111
  displayWidth = signal(0);
111
112
  displayHeight = signal(0);
112
113
  overrideProps: string[] = [];
113
- node: Node;
114
-
115
- get yoga() {
116
- return this.#canvasContext?.Yoga;
117
- }
114
+ layout = null;
115
+ onBeforeDestroy: OnHook | null = null;
116
+ onAfterMount: OnHook | null = null;
117
+ subjectInit = new BehaviorSubject(null);
118
+ disableLayout: boolean = false;
119
+ // Store registered event listeners for cleanup
120
+ #registeredEvents: Map<string, Function> = new Map();
118
121
 
119
122
  get deltaRatio() {
120
123
  return this.#canvasContext?.scheduler?.tick.value.deltaRatio;
121
124
  }
122
125
 
123
- onInit(props) {
126
+ get parentIsFlex() {
127
+ if (this.disableLayout) return false;
128
+ return this.parent?.isFlex;
129
+ }
130
+
131
+ onInit(props: Props) {
124
132
  this._id = props.id;
125
133
  for (let event of EVENTS) {
126
134
  if (props[event] && !this.overrideProps.includes(event)) {
127
135
  this.eventMode = "static";
128
- this.on(event, props[event]);
136
+ const eventHandler = props[event];
137
+
138
+ // Store the event handler for cleanup
139
+ if (event === 'click') {
140
+ this.on('pointertap', eventHandler);
141
+ this.#registeredEvents.set('pointertap', eventHandler);
142
+ } else {
143
+ this.on(event, eventHandler);
144
+ this.#registeredEvents.set(event, eventHandler);
145
+ }
129
146
  }
130
147
  }
148
+ if (props.onBeforeDestroy || props['on-before-destroy']) {
149
+ this.onBeforeDestroy = props.onBeforeDestroy || props['on-before-destroy'];
150
+ }
151
+ if (props.onAfterMount || props['on-after-mount']) {
152
+ this.onAfterMount = props.onAfterMount || props['on-after-mount'];
153
+ }
154
+ if (
155
+ props.justifyContent ||
156
+ props.alignItems ||
157
+ props.flexDirection ||
158
+ props.flexWrap ||
159
+ props.alignContent ||
160
+ props.display == "flex" ||
161
+ isPercent(props.width) ||
162
+ isPercent(props.height) ||
163
+ props.isRoot
164
+ ) {
165
+ this.layout = {};
166
+ this.isFlex = true;
167
+ }
168
+
169
+ this.subjectInit.next(this);
131
170
  }
132
171
 
133
- onMount({ parent, props }: Element<DisplayObject>, index?: number) {
172
+ async onMount({ parent, props }: Element<DisplayObject>, index?: number) {
173
+ if (this.destroyed) return
134
174
  this.#canvasContext = props.context;
135
- this.node = this.yoga.Node.create();
136
175
  if (parent) {
137
176
  const instance = parent.componentInstance as DisplayObject;
177
+ if (instance.isFlex && !this.layout && !this.disableLayout) {
178
+ try {
179
+ this.layout = {};
180
+ } catch (error) {
181
+ console.warn('Failed to set layout:', error);
182
+ }
183
+ }
138
184
  if (index === undefined) {
139
185
  instance.addChild(this);
140
186
  } else {
141
187
  instance.addChildAt(this, index);
142
188
  }
143
- if (instance.layer) this.parentLayer = instance.layer;
144
189
  this.isMounted = true;
145
- this.effectSize(props.width, props.height);
146
190
  this.onUpdate(props);
147
- this.parent.node.insertChild(
148
- this.node,
149
- this.parent.node.getChildCount()
150
- );
151
- if (parent.props.flexDirection) {
152
- this.parent.node.calculateLayout();
153
- for (let child of this.parent.children) {
154
- const { left, top } = child.getComputedLayout();
155
- child.x = left;
156
- child.y = top;
157
- }
191
+ if (this.onAfterMount) {
192
+ await this.onAfterMount();
158
193
  }
159
-
160
- }
161
- }
162
-
163
- effectSize(width: Size, height: Size) {
164
- const handleSize = (
165
- size: Size,
166
- setter: (value: number) => void,
167
- parentSize: Signal<number>
168
- ) => {
169
- if (typeof size === "string" && size.endsWith("%")) {
170
- effect(() => {
171
- setter(parentSize() * (parseInt(size) / 100));
172
- if (this.isFlex) {
173
- this.#applyFlexLayout();
174
- }
175
- });
176
- } else {
177
- setter(+size);
178
- }
179
- };
180
-
181
- if (width != undefined)
182
- handleSize(width, this.setWidth.bind(this), this.parent.displayWidth);
183
- if (height != undefined)
184
- handleSize(
185
- height,
186
- this.setHeight.bind(this),
187
- this.parent.displayHeight
188
- );
189
- }
190
-
191
- #applyFlexLayout() {
192
- this.calculateLayout();
193
- for (let child of this.children) {
194
- const { left, top } = child.node.getComputedLayout();
195
- child.x = left;
196
- child.y = top;
197
- }
198
- }
199
-
200
- #flexRender(props) {
201
- if (!this.parent) return;
202
- if (props.flexDirection || props.justifyContent) {
203
- this.isFlex = true;
204
- this.#applyFlexLayout();
205
194
  }
206
195
  }
207
196
 
208
- onUpdate(props) {
197
+ onUpdate(props: Props) {
209
198
  this.fullProps = {
210
199
  ...this.fullProps,
211
200
  ...props,
212
201
  };
213
202
 
203
+ if (this.destroyed) return
214
204
  if (!this.#canvasContext || !this.parent) return;
205
+
215
206
  if (props.x !== undefined) this.setX(props.x);
216
207
  if (props.y !== undefined) this.setY(props.y);
217
208
  if (props.scale !== undefined)
@@ -219,6 +210,28 @@ export function DisplayObject(extendClass) {
219
210
  if (props.anchor !== undefined && !this.isCustomAnchor) {
220
211
  setObservablePoint(this.anchor, props.anchor);
221
212
  }
213
+ if (props.width !== undefined) this.setWidth(props.width);
214
+ if (props.height !== undefined) this.setHeight(props.height);
215
+ if (props.minWidth !== undefined) this.setMinWidth(props.minWidth);
216
+ if (props.minHeight !== undefined) this.setMinHeight(props.minHeight);
217
+ if (props.maxWidth !== undefined) this.setMaxWidth(props.maxWidth);
218
+ if (props.maxHeight !== undefined) this.setMaxHeight(props.maxHeight);
219
+ if (props.aspectRatio !== undefined)
220
+ this.setAspectRatio(props.aspectRatio);
221
+ if (props.flexGrow !== undefined) this.setFlexGrow(props.flexGrow);
222
+ if (props.flexShrink !== undefined) this.setFlexShrink(props.flexShrink);
223
+ if (props.flexBasis !== undefined) this.setFlexBasis(props.flexBasis);
224
+ if (props.rowGap !== undefined) this.setRowGap(props.rowGap);
225
+ if (props.columnGap !== undefined) this.setColumnGap(props.columnGap);
226
+ if (props.top !== undefined) this.setTop(props.top);
227
+ if (props.left !== undefined) this.setLeft(props.left);
228
+ if (props.right !== undefined) this.setRight(props.right);
229
+ if (props.bottom !== undefined) this.setBottom(props.bottom);
230
+ if (props.objectFit !== undefined) this.setObjectFit(props.objectFit);
231
+ if (props.objectPosition !== undefined)
232
+ this.setObjectPosition(props.objectPosition);
233
+ if (props.transformOrigin !== undefined)
234
+ this.setTransformOrigin(props.transformOrigin);
222
235
  if (props.skew !== undefined) setObservablePoint(this.skew, props.skew);
223
236
  if (props.tint) this.tint = props.tint;
224
237
  if (props.rotation !== undefined) this.rotation = props.rotation;
@@ -243,23 +256,24 @@ export function DisplayObject(extendClass) {
243
256
  if (props.filters) this.filters = props.filters;
244
257
  if (props.maskOf) {
245
258
  if (isElement(props.maskOf)) {
246
- props.maskOf.componentInstance.mask = this;
259
+ props.maskOf.componentInstance.mask = this as any;
247
260
  }
248
261
  }
249
262
  if (props.blendMode) this.blendMode = props.blendMode;
250
263
  if (props.filterArea) this.filterArea = props.filterArea;
251
264
  const currentFilters = this.filters || [];
252
265
 
253
- if (props.shadow) {
254
- let dropShadowFilter = currentFilters.find(
255
- (filter) => filter instanceof DropShadowFilter
256
- );
257
- if (!dropShadowFilter) {
258
- dropShadowFilter = new DropShadowFilter();
259
- currentFilters.push(dropShadowFilter);
260
- }
261
- Object.assign(dropShadowFilter, props.shadow);
262
- }
266
+ // TODO: Fix DropShadowFilter import issue
267
+ // if (props.shadow) {
268
+ // let dropShadowFilter = currentFilters.find(
269
+ // (filter) => filter instanceof FILTERS.DropShadowFilter
270
+ // );
271
+ // if (!dropShadowFilter) {
272
+ // dropShadowFilter = new FILTERS.DropShadowFilter();
273
+ // currentFilters.push(dropShadowFilter);
274
+ // }
275
+ // Object.assign(dropShadowFilter, props.shadow);
276
+ // }
263
277
 
264
278
  if (props.blur) {
265
279
  let blurFilter = currentFilters.find(
@@ -279,73 +293,40 @@ export function DisplayObject(extendClass) {
279
293
  }
280
294
 
281
295
  this.filters = currentFilters;
282
-
283
- this.#flexRender(props);
284
296
  }
285
297
 
286
- onDestroy() {
287
- super.destroy();
288
- this.node?.freeRecursive();
289
- }
290
-
291
- getComputedLayout() {
292
- return this.node.getComputedLayout();
293
- }
294
-
295
- applyComputedLayout() {
296
- const layout = this.getComputedLayout();
297
- this.x = layout.left;
298
- this.y = layout.top;
299
- }
298
+ async onDestroy(parent: Element, afterDestroy?: () => void) {
299
+ // Remove all registered event listeners
300
+ for (const [eventName, eventHandler] of this.#registeredEvents) {
301
+ this.off(eventName, eventHandler);
302
+ }
303
+ this.#registeredEvents.clear();
300
304
 
301
- calculateLayout() {
302
- this.node.calculateLayout();
305
+ if (this.onBeforeDestroy) {
306
+ await this.onBeforeDestroy();
307
+ }
308
+ if (afterDestroy) afterDestroy();
309
+ super.destroy();
303
310
  }
304
311
 
305
312
  setFlexDirection(direction: FlexDirection) {
306
- const mapping = {
307
- row: this.yoga.FLEX_DIRECTION_ROW,
308
- column: this.yoga.FLEX_DIRECTION_COLUMN,
309
- "row-reverse": this.yoga.FLEX_DIRECTION_ROW_REVERSE,
310
- "column-reverse": this.yoga.FLEX_DIRECTION_COLUMN_REVERSE,
311
- };
312
- this.node.setFlexDirection(mapping[direction]);
313
+ this.layout = { flexDirection: direction };
313
314
  }
314
315
 
315
316
  setFlexWrap(wrap: "wrap" | "nowrap" | "wrap-reverse") {
316
- const mapping = {
317
- wrap: this.yoga.WRAP_WRAP,
318
- nowrap: this.yoga.WRAP_NO_WRAP,
319
- "wrap-reverse": this.yoga.WRAP_WRAP_REVERSE,
320
- };
321
- this.node.setFlexWrap(mapping[wrap]);
322
- }
323
-
324
- #setAlign(methodName: string, align: AlignContent) {
325
- const mapping = {
326
- auto: this.yoga.ALIGN_AUTO,
327
- "flex-start": this.yoga.ALIGN_FLEX_START,
328
- "flex-end": this.yoga.ALIGN_FLEX_END,
329
- center: this.yoga.ALIGN_CENTER,
330
- stretch: this.yoga.ALIGN_STRETCH,
331
- baseline: this.yoga.ALIGN_BASELINE,
332
- "space-between": this.yoga.ALIGN_SPACE_BETWEEN,
333
- "space-around": this.yoga.ALIGN_SPACE_AROUND,
334
- };
335
- const method = (this.node as any)[methodName].bind(this.node);
336
- method(mapping[align]);
317
+ this.layout = { flexWrap: wrap };
337
318
  }
338
319
 
339
320
  setAlignContent(align: AlignContent) {
340
- this.#setAlign("setAlignContent", align);
321
+ this.layout = { alignContent: align };
341
322
  }
342
323
 
343
324
  setAlignSelf(align: AlignContent) {
344
- this.#setAlign("setAlignSelf", align);
325
+ this.layout = { alignSelf: align };
345
326
  }
346
327
 
347
328
  setAlignItems(align: AlignContent) {
348
- this.#setAlign("setAlignItems", align);
329
+ this.layout = { alignItems: align };
349
330
  }
350
331
 
351
332
  setJustifyContent(
@@ -356,95 +337,133 @@ export function DisplayObject(extendClass) {
356
337
  | "space-between"
357
338
  | "space-around"
358
339
  ) {
359
- const mapping = {
360
- "flex-start": this.yoga.JUSTIFY_FLEX_START,
361
- "flex-end": this.yoga.JUSTIFY_FLEX_END,
362
- center: this.yoga.JUSTIFY_CENTER,
363
- "space-between": this.yoga.JUSTIFY_SPACE_BETWEEN,
364
- "space-around": this.yoga.JUSTIFY_SPACE_AROUND,
365
- };
366
- this.node.setJustifyContent(mapping[justifyContent]);
367
- }
368
-
369
- #setEdgeSize(methodName: string, size: EdgeSize) {
370
- const method = (this.node as any)[methodName].bind(this.node);
371
- if (size instanceof Array) {
372
- if (size.length === 2) {
373
- method(this.yoga.EDGE_VERTICAL, size[0]);
374
- method(this.yoga.EDGE_HORIZONTAL, size[1]);
375
- } else if (size.length === 4) {
376
- method(this.yoga.EDGE_TOP, size[0]);
377
- method(this.yoga.EDGE_RIGHT, size[1]);
378
- method(this.yoga.EDGE_BOTTOM, size[2]);
379
- method(this.yoga.EDGE_LEFT, size[3]);
380
- }
381
- } else {
382
- method(this.yoga.EDGE_ALL, size);
383
- }
340
+ this.layout = { justifyContent };
384
341
  }
385
342
 
386
343
  setPosition(position: EdgeSize) {
387
- this.#setEdgeSize("setPosition", position);
344
+ if (position instanceof Array) {
345
+ if (position.length === 2) {
346
+ this.layout = {
347
+ positionY: position[0],
348
+ positionX: position[1],
349
+ };
350
+ } else if (position.length === 4) {
351
+ this.layout = {
352
+ positionTop: position[0],
353
+ positionRight: position[1],
354
+ positionBottom: position[2],
355
+ positionLeft: position[3],
356
+ };
357
+ }
358
+ } else {
359
+ this.layout = { position };
360
+ }
388
361
  }
389
362
 
390
363
  setX(x: number) {
391
364
  x = x + this.getWidth() * this._anchorPoints.x;
392
- if (!this.parent.isFlex) {
365
+ if (!this.parentIsFlex) {
393
366
  this.x = x;
367
+ } else {
368
+ this.x = x;
369
+ this.layout = { x };
394
370
  }
395
- this.node.setPosition(this.yoga.EDGE_LEFT, x);
396
371
  }
397
372
 
398
373
  setY(y: number) {
399
374
  y = y + this.getHeight() * this._anchorPoints.y;
400
- if (!this.parent.isFlex) {
375
+ if (!this.parentIsFlex) {
376
+ this.y = y;
377
+ } else {
401
378
  this.y = y;
379
+ this.layout = { y };
402
380
  }
403
- this.node.setPosition(this.yoga.EDGE_TOP, y);
404
381
  }
405
382
 
406
383
  setPadding(padding: EdgeSize) {
407
- this.#setEdgeSize("setPadding", padding);
384
+ if (padding instanceof Array) {
385
+ if (padding.length === 2) {
386
+ this.layout = {
387
+ paddingVertical: padding[0],
388
+ paddingHorizontal: padding[1],
389
+ };
390
+ } else if (padding.length === 4) {
391
+ this.layout = {
392
+ paddingTop: padding[0],
393
+ paddingRight: padding[1],
394
+ paddingBottom: padding[2],
395
+ paddingLeft: padding[3],
396
+ };
397
+ }
398
+ } else {
399
+ this.layout = { padding };
400
+ }
408
401
  }
409
402
 
410
403
  setMargin(margin: EdgeSize) {
411
- this.#setEdgeSize("setMargin", margin);
404
+ if (margin instanceof Array) {
405
+ if (margin.length === 2) {
406
+ this.layout = {
407
+ marginVertical: margin[0],
408
+ marginHorizontal: margin[1],
409
+ };
410
+ } else if (margin.length === 4) {
411
+ this.layout = {
412
+ marginTop: margin[0],
413
+ marginRight: margin[1],
414
+ marginBottom: margin[2],
415
+ marginLeft: margin[3],
416
+ };
417
+ }
418
+ } else {
419
+ this.layout = { margin };
420
+ }
412
421
  }
413
422
 
414
423
  setGap(gap: EdgeSize) {
415
- this.node.setGap(this.yoga.GAP_ALL, +gap);
424
+ this.layout = { gap };
416
425
  }
417
426
 
418
427
  setBorder(border: EdgeSize) {
419
- this.#setEdgeSize("setBorder", border);
428
+ if (border instanceof Array) {
429
+ if (border.length === 2) {
430
+ this.layout = {
431
+ borderVertical: border[0],
432
+ borderHorizontal: border[1],
433
+ };
434
+ } else if (border.length === 4) {
435
+ this.layout = {
436
+ borderTop: border[0],
437
+ borderRight: border[1],
438
+ borderBottom: border[2],
439
+ borderLeft: border[3],
440
+ };
441
+ }
442
+ } else {
443
+ this.layout = { border };
444
+ }
420
445
  }
421
446
 
422
447
  setPositionType(positionType: "relative" | "absolute") {
423
- const mapping = {
424
- relative: this.yoga.POSITION_TYPE_RELATIVE,
425
- absolute: this.yoga.POSITION_TYPE_ABSOLUTE,
426
- };
427
- this.node.setPositionType(mapping[positionType]);
428
- }
429
-
430
- calculateBounds() {
431
- super.calculateBounds();
432
- if (!this._geometry) return;
433
- const bounds = this._geometry.bounds;
434
- const width = Math.abs(bounds.minX - bounds.maxX);
435
- const height = Math.abs(bounds.minY - bounds.maxY);
436
- // this.node.setWidth(width);
437
- // this.node.setHeight(height);
448
+ this.layout = { position: positionType };
438
449
  }
439
450
 
440
451
  setWidth(width: number) {
441
452
  this.displayWidth.set(width);
442
- this.node?.setWidth(width);
453
+ if (!this.parentIsFlex) {
454
+ this.width = width;
455
+ } else {
456
+ this.layout = { width };
457
+ }
443
458
  }
444
459
 
445
460
  setHeight(height: number) {
446
461
  this.displayHeight.set(height);
447
- this.node?.setHeight(height);
462
+ if (!this.parentIsFlex) {
463
+ this.height = height;
464
+ } else {
465
+ this.layout = { height };
466
+ }
448
467
  }
449
468
 
450
469
  getWidth() {
@@ -454,5 +473,79 @@ export function DisplayObject(extendClass) {
454
473
  getHeight() {
455
474
  return this.displayHeight();
456
475
  }
476
+
477
+ // Min/Max constraints
478
+ setMinWidth(minWidth: number | string) {
479
+ this.layout = { minWidth };
480
+ }
481
+
482
+ setMinHeight(minHeight: number | string) {
483
+ this.layout = { minHeight };
484
+ }
485
+
486
+ setMaxWidth(maxWidth: number | string) {
487
+ this.layout = { maxWidth };
488
+ }
489
+
490
+ setMaxHeight(maxHeight: number | string) {
491
+ this.layout = { maxHeight };
492
+ }
493
+
494
+ // Aspect ratio
495
+ setAspectRatio(aspectRatio: number) {
496
+ this.layout = { aspectRatio };
497
+ }
498
+
499
+ // Flex properties
500
+ setFlexGrow(flexGrow: number) {
501
+ this.layout = { flexGrow };
502
+ }
503
+
504
+ setFlexShrink(flexShrink: number) {
505
+ this.layout = { flexShrink };
506
+ }
507
+
508
+ setFlexBasis(flexBasis: number | string) {
509
+ this.layout = { flexBasis };
510
+ }
511
+
512
+ // Gap properties
513
+ setRowGap(rowGap: number) {
514
+ this.layout = { rowGap };
515
+ }
516
+
517
+ setColumnGap(columnGap: number) {
518
+ this.layout = { columnGap };
519
+ }
520
+
521
+ // Position insets
522
+ setTop(top: number | string) {
523
+ this.layout = { top };
524
+ }
525
+
526
+ setLeft(left: number | string) {
527
+ this.layout = { left };
528
+ }
529
+
530
+ setRight(right: number | string) {
531
+ this.layout = { right };
532
+ }
533
+
534
+ setBottom(bottom: number | string) {
535
+ this.layout = { bottom };
536
+ }
537
+
538
+ // Object properties
539
+ setObjectFit(objectFit: ObjectFit) {
540
+ this.layout = { objectFit };
541
+ }
542
+
543
+ setObjectPosition(objectPosition: ObjectPosition) {
544
+ this.layout = { objectPosition };
545
+ }
546
+
547
+ setTransformOrigin(transformOrigin: TransformOrigin) {
548
+ this.layout = { transformOrigin };
549
+ }
457
550
  };
458
551
  }