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.js CHANGED
@@ -10,7 +10,6 @@ var __accessCheck = (obj, member, msg) => member.has(obj) || __typeError("Cannot
10
10
  var __privateGet = (obj, member, getter) => (__accessCheck(obj, member, "read from private field"), getter ? getter.call(obj) : member.get(obj));
11
11
  var __privateAdd = (obj, member, value) => member.has(obj) ? __typeError("Cannot add the same private member more than once") : member instanceof WeakSet ? member.add(obj) : member.set(obj, value);
12
12
  var __privateSet = (obj, member, value, setter) => (__accessCheck(obj, member, "write to private field"), setter ? setter.call(obj, value) : member.set(obj, value), value);
13
- var __privateMethod = (obj, member, method) => (__accessCheck(obj, member, "access private method"), method);
14
13
 
15
14
  // src/engine/directive.ts
16
15
  var directives = {};
@@ -990,13 +989,14 @@ function destroyElement(element) {
990
989
  if (!element) {
991
990
  return;
992
991
  }
993
- element.propSubscriptions.forEach((sub) => sub.unsubscribe());
994
- element.effectSubscriptions.forEach((sub) => sub.unsubscribe());
995
- element.effectUnmounts.forEach((fn) => fn?.());
996
992
  for (let name in element.directives) {
997
993
  element.directives[name].onDestroy?.(element);
998
994
  }
999
- element.componentInstance.onDestroy?.(element.parent);
995
+ element.componentInstance.onDestroy(element.parent, () => {
996
+ element.propSubscriptions.forEach((sub) => sub.unsubscribe());
997
+ element.effectSubscriptions.forEach((sub) => sub.unsubscribe());
998
+ element.effectUnmounts.forEach((fn) => fn?.());
999
+ });
1000
1000
  }
1001
1001
  function createComponent(tag, props) {
1002
1002
  if (!components[tag]) {
@@ -1480,7 +1480,7 @@ var ViewportFollow = class extends Directive {
1480
1480
  radius: options.radius()
1481
1481
  });
1482
1482
  }
1483
- } else {
1483
+ } else if (viewportFollow === null) {
1484
1484
  viewport.plugins.remove("follow");
1485
1485
  }
1486
1486
  }
@@ -1924,14 +1924,24 @@ export * from "@signe/reactive";
1924
1924
  import { Howler } from "howler";
1925
1925
 
1926
1926
  // src/components/Canvas.ts
1927
- import { effect as effect4, signal as signal5 } from "@signe/reactive";
1928
- import { Container as Container3, autoDetectRenderer } from "pixi.js";
1929
- import { loadYoga } from "yoga-layout";
1927
+ import { effect as effect3, signal as signal5 } from "@signe/reactive";
1928
+ import { Container as Container3 } from "pixi.js";
1930
1929
 
1931
1930
  // src/components/DisplayObject.ts
1932
- import { effect as effect3, signal as signal4 } from "@signe/reactive";
1931
+ import { signal as signal4 } from "@signe/reactive";
1933
1932
  import { DropShadowFilter } from "pixi-filters";
1934
1933
  import { BlurFilter, ObservablePoint } from "pixi.js";
1934
+
1935
+ // src/utils/functions.ts
1936
+ function isPercent(value) {
1937
+ if (!value) return false;
1938
+ if (typeof value === "string") {
1939
+ return value.endsWith("%");
1940
+ }
1941
+ return false;
1942
+ }
1943
+
1944
+ // src/components/DisplayObject.ts
1935
1945
  var EVENTS2 = [
1936
1946
  "added",
1937
1947
  "childAdded",
@@ -2003,28 +2013,23 @@ var EVENTS2 = [
2003
2013
  "wheelcapture"
2004
2014
  ];
2005
2015
  function DisplayObject(extendClass) {
2006
- var _canvasContext, _DisplayObject_instances, flexRender_fn, setAlign_fn, setEdgeSize_fn, _a;
2016
+ var _canvasContext, _a;
2007
2017
  return _a = class extends extendClass {
2008
2018
  constructor() {
2009
2019
  super(...arguments);
2010
- __privateAdd(this, _DisplayObject_instances);
2011
2020
  __privateAdd(this, _canvasContext, null);
2012
2021
  this.isFlex = false;
2013
2022
  this.fullProps = {};
2014
2023
  this.isMounted = false;
2015
- this._anchorPoints = new ObservablePoint(
2016
- { _onUpdate: () => {
2017
- } },
2018
- 0,
2019
- 0
2020
- );
2024
+ this._anchorPoints = new ObservablePoint({ _onUpdate: () => {
2025
+ } }, 0, 0);
2021
2026
  this.isCustomAnchor = false;
2022
2027
  this.displayWidth = signal4(0);
2023
2028
  this.displayHeight = signal4(0);
2024
2029
  this.overrideProps = [];
2025
- }
2026
- get yoga() {
2027
- return __privateGet(this, _canvasContext)?.Yoga;
2030
+ this.layout = null;
2031
+ this.onBeforeDestroy = null;
2032
+ this.onAfterMount = null;
2028
2033
  }
2029
2034
  get deltaRatio() {
2030
2035
  return __privateGet(this, _canvasContext)?.scheduler?.tick.value.deltaRatio;
@@ -2037,63 +2042,34 @@ function DisplayObject(extendClass) {
2037
2042
  this.on(event, props[event]);
2038
2043
  }
2039
2044
  }
2045
+ if (props.onBeforeDestroy || props["on-before-destroy"]) {
2046
+ this.onBeforeDestroy = props.onBeforeDestroy || props["on-before-destroy"];
2047
+ }
2048
+ if (props.onAfterMount || props["on-after-mount"]) {
2049
+ this.onAfterMount = props.onAfterMount || props["on-after-mount"];
2050
+ }
2051
+ if (props.justifyContent || props.alignItems || props.flexDirection || props.flexWrap || props.alignContent || props.display == "flex" || isPercent(props.width) || isPercent(props.height) || props.isRoot) {
2052
+ this.layout = {};
2053
+ this.isFlex = true;
2054
+ }
2040
2055
  }
2041
- onMount({ parent, props }, index) {
2056
+ async onMount({ parent, props }, index) {
2042
2057
  __privateSet(this, _canvasContext, props.context);
2043
- this.node = this.yoga.Node.create();
2044
2058
  if (parent) {
2045
2059
  const instance = parent.componentInstance;
2060
+ if (instance.isFlex && !this.layout) {
2061
+ this.layout = {};
2062
+ }
2046
2063
  if (index === void 0) {
2047
2064
  instance.addChild(this);
2048
2065
  } else {
2049
2066
  instance.addChildAt(this, index);
2050
2067
  }
2051
- if (instance.layer) this.parentLayer = instance.layer;
2052
2068
  this.isMounted = true;
2053
- this.effectSize(props.width, props.height);
2054
2069
  this.onUpdate(props);
2055
- this.parent.node.insertChild(
2056
- this.node,
2057
- this.parent.node.getChildCount()
2058
- );
2059
- if (parent.props.flexDirection) {
2060
- this.parent.node.calculateLayout();
2061
- for (let child of this.parent.children) {
2062
- const { left, top } = child.getComputedLayout();
2063
- child.x = left;
2064
- child.y = top;
2065
- }
2066
- }
2067
- }
2068
- }
2069
- effectSize(width, height) {
2070
- const handleSize = (size, setter, parentSize) => {
2071
- if (typeof size === "string" && size.endsWith("%")) {
2072
- effect3(() => {
2073
- setter(parentSize() * (parseInt(size) / 100));
2074
- if (this.isFlex) {
2075
- this.applyFlexLayout();
2076
- }
2077
- });
2078
- } else {
2079
- setter(+size);
2070
+ if (this.onAfterMount) {
2071
+ await this.onAfterMount();
2080
2072
  }
2081
- };
2082
- if (width != void 0)
2083
- handleSize(width, this.setWidth.bind(this), this.parent.displayWidth);
2084
- if (height != void 0)
2085
- handleSize(
2086
- height,
2087
- this.setHeight.bind(this),
2088
- this.parent.displayHeight
2089
- );
2090
- }
2091
- applyFlexLayout() {
2092
- this.calculateLayout();
2093
- for (let child of this.children) {
2094
- const { left, top } = child.node.getComputedLayout();
2095
- child.x = left;
2096
- child.y = top;
2097
2073
  }
2098
2074
  }
2099
2075
  onUpdate(props) {
@@ -2109,6 +2085,28 @@ function DisplayObject(extendClass) {
2109
2085
  if (props.anchor !== void 0 && !this.isCustomAnchor) {
2110
2086
  setObservablePoint(this.anchor, props.anchor);
2111
2087
  }
2088
+ if (props.width !== void 0) this.setWidth(props.width);
2089
+ if (props.height !== void 0) this.setHeight(props.height);
2090
+ if (props.minWidth !== void 0) this.setMinWidth(props.minWidth);
2091
+ if (props.minHeight !== void 0) this.setMinHeight(props.minHeight);
2092
+ if (props.maxWidth !== void 0) this.setMaxWidth(props.maxWidth);
2093
+ if (props.maxHeight !== void 0) this.setMaxHeight(props.maxHeight);
2094
+ if (props.aspectRatio !== void 0)
2095
+ this.setAspectRatio(props.aspectRatio);
2096
+ if (props.flexGrow !== void 0) this.setFlexGrow(props.flexGrow);
2097
+ if (props.flexShrink !== void 0) this.setFlexShrink(props.flexShrink);
2098
+ if (props.flexBasis !== void 0) this.setFlexBasis(props.flexBasis);
2099
+ if (props.rowGap !== void 0) this.setRowGap(props.rowGap);
2100
+ if (props.columnGap !== void 0) this.setColumnGap(props.columnGap);
2101
+ if (props.top !== void 0) this.setTop(props.top);
2102
+ if (props.left !== void 0) this.setLeft(props.left);
2103
+ if (props.right !== void 0) this.setRight(props.right);
2104
+ if (props.bottom !== void 0) this.setBottom(props.bottom);
2105
+ if (props.objectFit !== void 0) this.setObjectFit(props.objectFit);
2106
+ if (props.objectPosition !== void 0)
2107
+ this.setObjectPosition(props.objectPosition);
2108
+ if (props.transformOrigin !== void 0)
2109
+ this.setTransformOrigin(props.transformOrigin);
2112
2110
  if (props.skew !== void 0) setObservablePoint(this.skew, props.skew);
2113
2111
  if (props.tint) this.tint = props.tint;
2114
2112
  if (props.rotation !== void 0) this.rotation = props.rotation;
@@ -2163,109 +2161,147 @@ function DisplayObject(extendClass) {
2163
2161
  Object.assign(blurFilter, props.blur);
2164
2162
  }
2165
2163
  this.filters = currentFilters;
2166
- __privateMethod(this, _DisplayObject_instances, flexRender_fn).call(this, props);
2167
2164
  }
2168
- onDestroy() {
2165
+ async onDestroy(parent, afterDestroy) {
2166
+ if (this.onBeforeDestroy) {
2167
+ await this.onBeforeDestroy();
2168
+ }
2169
2169
  super.destroy();
2170
- this.node?.freeRecursive();
2171
- }
2172
- getComputedLayout() {
2173
- return this.node.getComputedLayout();
2174
- }
2175
- applyComputedLayout() {
2176
- const layout = this.getComputedLayout();
2177
- this.x = layout.left;
2178
- this.y = layout.top;
2179
- }
2180
- calculateLayout() {
2181
- this.node.calculateLayout();
2170
+ if (this.onAfterDestroy) this.onAfterDestroy();
2182
2171
  }
2183
2172
  setFlexDirection(direction) {
2184
- const mapping = {
2185
- row: this.yoga.FLEX_DIRECTION_ROW,
2186
- column: this.yoga.FLEX_DIRECTION_COLUMN,
2187
- "row-reverse": this.yoga.FLEX_DIRECTION_ROW_REVERSE,
2188
- "column-reverse": this.yoga.FLEX_DIRECTION_COLUMN_REVERSE
2189
- };
2190
- this.node.setFlexDirection(mapping[direction]);
2173
+ this.layout = { flexDirection: direction };
2191
2174
  }
2192
2175
  setFlexWrap(wrap) {
2193
- const mapping = {
2194
- wrap: this.yoga.WRAP_WRAP,
2195
- nowrap: this.yoga.WRAP_NO_WRAP,
2196
- "wrap-reverse": this.yoga.WRAP_WRAP_REVERSE
2197
- };
2198
- this.node.setFlexWrap(mapping[wrap]);
2176
+ this.layout = { flexWrap: wrap };
2199
2177
  }
2200
2178
  setAlignContent(align) {
2201
- __privateMethod(this, _DisplayObject_instances, setAlign_fn).call(this, "setAlignContent", align);
2179
+ this.layout = { alignContent: align };
2202
2180
  }
2203
2181
  setAlignSelf(align) {
2204
- __privateMethod(this, _DisplayObject_instances, setAlign_fn).call(this, "setAlignSelf", align);
2182
+ this.layout = { alignSelf: align };
2205
2183
  }
2206
2184
  setAlignItems(align) {
2207
- __privateMethod(this, _DisplayObject_instances, setAlign_fn).call(this, "setAlignItems", align);
2185
+ this.layout = { alignItems: align };
2208
2186
  }
2209
2187
  setJustifyContent(justifyContent) {
2210
- const mapping = {
2211
- "flex-start": this.yoga.JUSTIFY_FLEX_START,
2212
- "flex-end": this.yoga.JUSTIFY_FLEX_END,
2213
- center: this.yoga.JUSTIFY_CENTER,
2214
- "space-between": this.yoga.JUSTIFY_SPACE_BETWEEN,
2215
- "space-around": this.yoga.JUSTIFY_SPACE_AROUND
2216
- };
2217
- this.node.setJustifyContent(mapping[justifyContent]);
2188
+ this.layout = { justifyContent };
2218
2189
  }
2219
2190
  setPosition(position) {
2220
- __privateMethod(this, _DisplayObject_instances, setEdgeSize_fn).call(this, "setPosition", position);
2191
+ if (position instanceof Array) {
2192
+ if (position.length === 2) {
2193
+ this.layout = {
2194
+ positionY: position[0],
2195
+ positionX: position[1]
2196
+ };
2197
+ } else if (position.length === 4) {
2198
+ this.layout = {
2199
+ positionTop: position[0],
2200
+ positionRight: position[1],
2201
+ positionBottom: position[2],
2202
+ positionLeft: position[3]
2203
+ };
2204
+ }
2205
+ } else {
2206
+ this.layout = { position };
2207
+ }
2221
2208
  }
2222
2209
  setX(x) {
2223
2210
  x = x + this.getWidth() * this._anchorPoints.x;
2224
2211
  if (!this.parent.isFlex) {
2225
2212
  this.x = x;
2213
+ } else {
2214
+ this.x = x;
2215
+ this.layout = { x };
2226
2216
  }
2227
- this.node.setPosition(this.yoga.EDGE_LEFT, x);
2228
2217
  }
2229
2218
  setY(y) {
2230
2219
  y = y + this.getHeight() * this._anchorPoints.y;
2231
2220
  if (!this.parent.isFlex) {
2232
2221
  this.y = y;
2222
+ } else {
2223
+ this.y = y;
2224
+ this.layout = { y };
2233
2225
  }
2234
- this.node.setPosition(this.yoga.EDGE_TOP, y);
2235
2226
  }
2236
2227
  setPadding(padding) {
2237
- __privateMethod(this, _DisplayObject_instances, setEdgeSize_fn).call(this, "setPadding", padding);
2228
+ if (padding instanceof Array) {
2229
+ if (padding.length === 2) {
2230
+ this.layout = {
2231
+ paddingVertical: padding[0],
2232
+ paddingHorizontal: padding[1]
2233
+ };
2234
+ } else if (padding.length === 4) {
2235
+ this.layout = {
2236
+ paddingTop: padding[0],
2237
+ paddingRight: padding[1],
2238
+ paddingBottom: padding[2],
2239
+ paddingLeft: padding[3]
2240
+ };
2241
+ }
2242
+ } else {
2243
+ this.layout = { padding };
2244
+ }
2238
2245
  }
2239
2246
  setMargin(margin) {
2240
- __privateMethod(this, _DisplayObject_instances, setEdgeSize_fn).call(this, "setMargin", margin);
2247
+ if (margin instanceof Array) {
2248
+ if (margin.length === 2) {
2249
+ this.layout = {
2250
+ marginVertical: margin[0],
2251
+ marginHorizontal: margin[1]
2252
+ };
2253
+ } else if (margin.length === 4) {
2254
+ this.layout = {
2255
+ marginTop: margin[0],
2256
+ marginRight: margin[1],
2257
+ marginBottom: margin[2],
2258
+ marginLeft: margin[3]
2259
+ };
2260
+ }
2261
+ } else {
2262
+ this.layout = { margin };
2263
+ }
2241
2264
  }
2242
2265
  setGap(gap) {
2243
- this.node.setGap(this.yoga.GAP_ALL, +gap);
2266
+ this.layout = { gap };
2244
2267
  }
2245
2268
  setBorder(border) {
2246
- __privateMethod(this, _DisplayObject_instances, setEdgeSize_fn).call(this, "setBorder", border);
2269
+ if (border instanceof Array) {
2270
+ if (border.length === 2) {
2271
+ this.layout = {
2272
+ borderVertical: border[0],
2273
+ borderHorizontal: border[1]
2274
+ };
2275
+ } else if (border.length === 4) {
2276
+ this.layout = {
2277
+ borderTop: border[0],
2278
+ borderRight: border[1],
2279
+ borderBottom: border[2],
2280
+ borderLeft: border[3]
2281
+ };
2282
+ }
2283
+ } else {
2284
+ this.layout = { border };
2285
+ }
2247
2286
  }
2248
2287
  setPositionType(positionType) {
2249
- const mapping = {
2250
- relative: this.yoga.POSITION_TYPE_RELATIVE,
2251
- absolute: this.yoga.POSITION_TYPE_ABSOLUTE
2252
- };
2253
- this.node.setPositionType(mapping[positionType]);
2254
- }
2255
- calculateBounds() {
2256
- super.calculateBounds();
2257
- if (!this._geometry) return;
2258
- const bounds = this._geometry.bounds;
2259
- const width = Math.abs(bounds.minX - bounds.maxX);
2260
- const height = Math.abs(bounds.minY - bounds.maxY);
2288
+ this.layout = { position: positionType };
2261
2289
  }
2262
2290
  setWidth(width) {
2263
2291
  this.displayWidth.set(width);
2264
- this.node?.setWidth(width);
2292
+ if (!this.parent?.isFlex) {
2293
+ this.width = width;
2294
+ } else {
2295
+ this.layout = { width };
2296
+ }
2265
2297
  }
2266
2298
  setHeight(height) {
2267
2299
  this.displayHeight.set(height);
2268
- this.node?.setHeight(height);
2300
+ if (!this.parent?.isFlex) {
2301
+ this.height = height;
2302
+ } else {
2303
+ this.layout = { height };
2304
+ }
2269
2305
  }
2270
2306
  getWidth() {
2271
2307
  return this.displayWidth();
@@ -2273,41 +2309,64 @@ function DisplayObject(extendClass) {
2273
2309
  getHeight() {
2274
2310
  return this.displayHeight();
2275
2311
  }
2276
- }, _canvasContext = new WeakMap(), _DisplayObject_instances = new WeakSet(), flexRender_fn = function(props) {
2277
- if (!this.parent) return;
2278
- if (props.flexDirection || props.justifyContent) {
2279
- this.isFlex = true;
2280
- this.applyFlexLayout();
2281
- }
2282
- }, setAlign_fn = function(methodName, align) {
2283
- const mapping = {
2284
- auto: this.yoga.ALIGN_AUTO,
2285
- "flex-start": this.yoga.ALIGN_FLEX_START,
2286
- "flex-end": this.yoga.ALIGN_FLEX_END,
2287
- center: this.yoga.ALIGN_CENTER,
2288
- stretch: this.yoga.ALIGN_STRETCH,
2289
- baseline: this.yoga.ALIGN_BASELINE,
2290
- "space-between": this.yoga.ALIGN_SPACE_BETWEEN,
2291
- "space-around": this.yoga.ALIGN_SPACE_AROUND
2292
- };
2293
- const method = this.node[methodName].bind(this.node);
2294
- method(mapping[align]);
2295
- }, setEdgeSize_fn = function(methodName, size) {
2296
- const method = this.node[methodName].bind(this.node);
2297
- if (size instanceof Array) {
2298
- if (size.length === 2) {
2299
- method(this.yoga.EDGE_VERTICAL, size[0]);
2300
- method(this.yoga.EDGE_HORIZONTAL, size[1]);
2301
- } else if (size.length === 4) {
2302
- method(this.yoga.EDGE_TOP, size[0]);
2303
- method(this.yoga.EDGE_RIGHT, size[1]);
2304
- method(this.yoga.EDGE_BOTTOM, size[2]);
2305
- method(this.yoga.EDGE_LEFT, size[3]);
2306
- }
2307
- } else {
2308
- method(this.yoga.EDGE_ALL, size);
2312
+ // Min/Max constraints
2313
+ setMinWidth(minWidth) {
2314
+ this.layout = { minWidth };
2315
+ }
2316
+ setMinHeight(minHeight) {
2317
+ this.layout = { minHeight };
2318
+ }
2319
+ setMaxWidth(maxWidth) {
2320
+ this.layout = { maxWidth };
2321
+ }
2322
+ setMaxHeight(maxHeight) {
2323
+ this.layout = { maxHeight };
2324
+ }
2325
+ // Aspect ratio
2326
+ setAspectRatio(aspectRatio) {
2327
+ this.layout = { aspectRatio };
2328
+ }
2329
+ // Flex properties
2330
+ setFlexGrow(flexGrow) {
2331
+ this.layout = { flexGrow };
2332
+ }
2333
+ setFlexShrink(flexShrink) {
2334
+ this.layout = { flexShrink };
2309
2335
  }
2310
- }, _a;
2336
+ setFlexBasis(flexBasis) {
2337
+ this.layout = { flexBasis };
2338
+ }
2339
+ // Gap properties
2340
+ setRowGap(rowGap) {
2341
+ this.layout = { rowGap };
2342
+ }
2343
+ setColumnGap(columnGap) {
2344
+ this.layout = { columnGap };
2345
+ }
2346
+ // Position insets
2347
+ setTop(top) {
2348
+ this.layout = { top };
2349
+ }
2350
+ setLeft(left) {
2351
+ this.layout = { left };
2352
+ }
2353
+ setRight(right) {
2354
+ this.layout = { right };
2355
+ }
2356
+ setBottom(bottom) {
2357
+ this.layout = { bottom };
2358
+ }
2359
+ // Object properties
2360
+ setObjectFit(objectFit) {
2361
+ this.layout = { objectFit };
2362
+ }
2363
+ setObjectPosition(objectPosition) {
2364
+ this.layout = { objectPosition };
2365
+ }
2366
+ setTransformOrigin(transformOrigin) {
2367
+ this.layout = { transformOrigin };
2368
+ }
2369
+ }, _canvasContext = new WeakMap(), _a;
2311
2370
  }
2312
2371
 
2313
2372
  // src/components/Canvas.ts
@@ -2315,25 +2374,18 @@ registerComponent("Canvas", class Canvas extends DisplayObject(Container3) {
2315
2374
  });
2316
2375
  var Canvas2 = async (props = {}) => {
2317
2376
  let { cursorStyles, width, height, class: className } = useProps(props);
2318
- const Yoga = await loadYoga();
2319
2377
  if (!props.width) width = signal5(800);
2320
2378
  if (!props.height) height = signal5(600);
2321
- const renderer = await autoDetectRenderer({
2322
- ...props,
2323
- width: width?.(),
2324
- height: height?.()
2325
- });
2326
2379
  const canvasSize = signal5({
2327
- width: renderer.width,
2328
- height: renderer.height
2380
+ width: 0,
2381
+ height: 0
2329
2382
  });
2330
2383
  props.isRoot = true;
2331
2384
  const options = {
2332
2385
  ...props,
2333
2386
  context: {
2334
- Yoga,
2335
- renderer,
2336
- canvasSize
2387
+ canvasSize,
2388
+ app: signal5(null)
2337
2389
  },
2338
2390
  width: width?.(),
2339
2391
  height: height?.()
@@ -2347,48 +2399,57 @@ var Canvas2 = async (props = {}) => {
2347
2399
  });
2348
2400
  }
2349
2401
  const canvasElement = createComponent("Canvas", options);
2350
- canvasElement.render = (rootElement) => {
2402
+ canvasElement.render = (rootElement, app) => {
2403
+ if (!app) {
2404
+ return;
2405
+ }
2406
+ const renderer = app.renderer;
2351
2407
  const canvasEl = renderer.view.canvas;
2352
2408
  globalThis.__PIXI_STAGE__ = canvasElement.componentInstance;
2353
2409
  globalThis.__PIXI_RENDERER__ = renderer;
2354
2410
  if (props.tickStart !== false) canvasElement.directives.tick.start();
2355
- effect4(() => {
2411
+ effect3(() => {
2356
2412
  canvasElement.propObservables.tick();
2357
2413
  renderer.render(canvasElement.componentInstance);
2358
2414
  });
2415
+ app.stage = canvasElement.componentInstance;
2416
+ app.stage.layout = {
2417
+ width: app.screen.width,
2418
+ height: app.screen.height,
2419
+ justifyContent: props.justifyContent,
2420
+ alignItems: props.alignItems
2421
+ };
2422
+ canvasSize.set({ width: app.screen.width, height: app.screen.height });
2423
+ app.renderer.on("resize", (width2, height2) => {
2424
+ canvasSize.set({ width: width2, height: height2 });
2425
+ if (app.stage.layout) {
2426
+ app.stage.layout = {
2427
+ width: width2,
2428
+ height: height2
2429
+ };
2430
+ }
2431
+ });
2432
+ if (props.tickStart !== false) canvasElement.directives.tick.start();
2433
+ app.ticker.add(() => {
2434
+ canvasElement.propObservables.tick();
2435
+ });
2359
2436
  if (cursorStyles) {
2360
- effect4(() => {
2437
+ effect3(() => {
2361
2438
  renderer.events.cursorStyles = cursorStyles();
2362
2439
  });
2363
2440
  }
2364
2441
  if (className) {
2365
- effect4(() => {
2442
+ effect3(() => {
2366
2443
  canvasEl.classList.add(className());
2367
2444
  });
2368
2445
  }
2369
- const resizeCanvas = async () => {
2370
- let w, h2;
2371
- if (width?.() === "100%" && height?.() === "100%") {
2372
- const parent = canvasEl.parentElement;
2373
- w = parent ? parent.clientWidth : window.innerWidth;
2374
- h2 = parent ? parent.clientHeight : window.innerHeight;
2375
- } else {
2376
- w = width?.() ?? canvasEl.offsetWidth;
2377
- h2 = height?.() ?? canvasEl.offsetHeight;
2378
- }
2379
- renderer.resize(w, h2);
2380
- canvasSize.set({ width: w, height: h2 });
2381
- canvasElement.componentInstance.setWidth(w);
2382
- canvasElement.componentInstance.setHeight(h2);
2383
- };
2384
- window.addEventListener("resize", resizeCanvas);
2385
2446
  const existingCanvas = rootElement.querySelector("canvas");
2386
2447
  if (existingCanvas) {
2387
2448
  rootElement.replaceChild(canvasEl, existingCanvas);
2388
2449
  } else {
2389
2450
  rootElement.appendChild(canvasEl);
2390
2451
  }
2391
- resizeCanvas();
2452
+ options.context.app.set(app);
2392
2453
  };
2393
2454
  return canvasElement;
2394
2455
  };
@@ -2413,8 +2474,8 @@ var CanvasContainer = class extends DisplayObject(PixiContainer) {
2413
2474
  this.sortableChildren = props.sortableChildren;
2414
2475
  }
2415
2476
  }
2416
- onMount(args) {
2417
- super.onMount(args);
2477
+ async onMount(args) {
2478
+ await super.onMount(args);
2418
2479
  const { componentInstance, props } = args;
2419
2480
  const { pixiChildren } = props;
2420
2481
  if (pixiChildren) {
@@ -2430,21 +2491,34 @@ var Container4 = (props) => {
2430
2491
  };
2431
2492
 
2432
2493
  // src/components/Graphic.ts
2433
- import { effect as effect5 } from "@signe/reactive";
2494
+ import { effect as effect4 } from "@signe/reactive";
2434
2495
  import { Graphics as PixiGraphics } from "pixi.js";
2435
2496
  var CanvasGraphics = class extends DisplayObject(PixiGraphics) {
2436
2497
  onInit(props) {
2437
2498
  super.onInit(props);
2438
2499
  if (props.draw) {
2439
- this.clearEffect = effect5(() => {
2500
+ this.clearEffect = effect4(() => {
2440
2501
  this.clear();
2441
2502
  props.draw?.(this);
2442
2503
  });
2443
2504
  }
2444
2505
  }
2445
- onDestroy() {
2446
- this.clearEffect.subscription.unsubscribe();
2447
- super.onDestroy();
2506
+ /**
2507
+ * Called when the component is about to be destroyed.
2508
+ * This method should be overridden by subclasses to perform any cleanup.
2509
+ * It ensures that the clearEffect subscription is unsubscribed before calling the original afterDestroy callback.
2510
+ * @param parent The parent element.
2511
+ * @param afterDestroy A callback function to be executed after the component's own destruction logic.
2512
+ * @example
2513
+ * // This method is typically called by the engine internally.
2514
+ * // await component.onDestroy(parentElement, () => console.log('Component destroyed'));
2515
+ */
2516
+ async onDestroy(parent, afterDestroy) {
2517
+ const _afterDestroyCallback = async () => {
2518
+ this.clearEffect.subscription.unsubscribe();
2519
+ afterDestroy();
2520
+ };
2521
+ await super.onDestroy(parent, _afterDestroyCallback);
2448
2522
  }
2449
2523
  };
2450
2524
  registerComponent("Graphics", CanvasGraphics);
@@ -2592,8 +2666,8 @@ var CanvasParticlesEmitter = class extends CanvasContainer {
2592
2666
  super(...arguments);
2593
2667
  this.elapsed = Date.now();
2594
2668
  }
2595
- onMount(params) {
2596
- super.onMount(params);
2669
+ async onMount(params) {
2670
+ await super.onMount(params);
2597
2671
  const { props } = params;
2598
2672
  const tick2 = props.context.tick;
2599
2673
  this.emitter = new particles.Emitter(this, props.config);
@@ -2606,11 +2680,14 @@ var CanvasParticlesEmitter = class extends CanvasContainer {
2606
2680
  }
2607
2681
  onUpdate(props) {
2608
2682
  }
2609
- onDestroy() {
2610
- super.onDestroy();
2611
- this.emitter?.destroy();
2612
- this.emitter = null;
2613
- this.subscriptionTick.unsubscribe();
2683
+ async onDestroy(parent, afterDestroy) {
2684
+ const _afterDestroy = async () => {
2685
+ this.emitter?.destroy();
2686
+ this.emitter = null;
2687
+ this.subscriptionTick.unsubscribe();
2688
+ afterDestroy();
2689
+ };
2690
+ await super.onDestroy(parent, _afterDestroy);
2614
2691
  }
2615
2692
  };
2616
2693
  registerComponent("ParticlesEmitter", CanvasParticlesEmitter);
@@ -2620,7 +2697,7 @@ function ParticlesEmitter(props) {
2620
2697
 
2621
2698
  // src/components/Sprite.ts
2622
2699
  import { Howl as Howl2 } from "howler";
2623
- import { computed, effect as effect7, isSignal as isSignal4 } from "@signe/reactive";
2700
+ import { computed, effect as effect6, isSignal as isSignal4 } from "@signe/reactive";
2624
2701
  import {
2625
2702
  Assets,
2626
2703
  Container as Container5,
@@ -2630,7 +2707,7 @@ import {
2630
2707
  } from "pixi.js";
2631
2708
 
2632
2709
  // src/engine/animation.ts
2633
- import { effect as effect6, signal as signal6 } from "@signe/reactive";
2710
+ import { effect as effect5, signal as signal6 } from "@signe/reactive";
2634
2711
  import { animate as animatePopmotion } from "popmotion";
2635
2712
  function isAnimatedSignal(signal9) {
2636
2713
  return signal9.animatedState !== void 0;
@@ -2644,7 +2721,7 @@ function animatedSignal(initialValue, options = {}) {
2644
2721
  let animation;
2645
2722
  const publicSignal = signal6(initialValue);
2646
2723
  const privateSignal = signal6(state);
2647
- effect6(() => {
2724
+ effect5(() => {
2648
2725
  const currentState = privateSignal();
2649
2726
  publicSignal.set(currentState.current);
2650
2727
  });
@@ -2839,7 +2916,7 @@ var CanvasSprite = class extends DisplayObject(PixiSprite) {
2839
2916
  const isMovingY = isAnimatedSignal(ySignal) && ySignal.animatedState().current !== ySignal.animatedState().end;
2840
2917
  return isMovingX || isMovingY;
2841
2918
  });
2842
- effect7(() => {
2919
+ effect6(() => {
2843
2920
  const _isMoving = isMoving();
2844
2921
  if (!this.isMounted) return;
2845
2922
  if (_isMoving) {
@@ -2847,7 +2924,7 @@ var CanvasSprite = class extends DisplayObject(PixiSprite) {
2847
2924
  } else {
2848
2925
  this.sheetCurrentAnimation = "stand" /* Stand */;
2849
2926
  }
2850
- this.play(this.sheetCurrentAnimation, [this.sheetParams]);
2927
+ if (this.spritesheet) this.play(this.sheetCurrentAnimation, [this.sheetParams]);
2851
2928
  });
2852
2929
  super.onMount(params);
2853
2930
  }
@@ -2890,8 +2967,8 @@ var CanvasSprite = class extends DisplayObject(PixiSprite) {
2890
2967
  });
2891
2968
  }
2892
2969
  }
2893
- onDestroy() {
2894
- super.onDestroy();
2970
+ async onDestroy(parent, afterDestroy) {
2971
+ await super.onDestroy(parent);
2895
2972
  this.subscriptionSheet.forEach((sub) => sub.unsubscribe());
2896
2973
  this.subscriptionTick.unsubscribe();
2897
2974
  if (this.currentAnimationContainer && this.parent instanceof Container5) {
@@ -3031,7 +3108,7 @@ var Sprite2 = (props) => {
3031
3108
  };
3032
3109
 
3033
3110
  // src/components/Video.ts
3034
- import { effect as effect8, signal as signal7 } from "@signe/reactive";
3111
+ import { effect as effect7, signal as signal7 } from "@signe/reactive";
3035
3112
  function Video(props) {
3036
3113
  const eventsMap = {
3037
3114
  audioprocess: null,
@@ -3072,7 +3149,7 @@ function Video(props) {
3072
3149
  default: false
3073
3150
  }
3074
3151
  });
3075
- effect8(() => {
3152
+ effect7(() => {
3076
3153
  const _video = video();
3077
3154
  const state = play();
3078
3155
  if (_video && state !== void 0) {
@@ -3126,7 +3203,7 @@ function Video(props) {
3126
3203
  import { Text as PixiText } from "pixi.js";
3127
3204
 
3128
3205
  // src/engine/trigger.ts
3129
- import { effect as effect9, signal as signal8 } from "@signe/reactive";
3206
+ import { effect as effect8, signal as signal8 } from "@signe/reactive";
3130
3207
  function isTrigger(arg) {
3131
3208
  return arg?.start && arg?.listen;
3132
3209
  }
@@ -3161,7 +3238,7 @@ function on(triggerSignal, callback) {
3161
3238
  if (!isTrigger(triggerSignal)) {
3162
3239
  throw new Error("In 'on(arg)' must have a trigger signal type");
3163
3240
  }
3164
- effect9(() => {
3241
+ effect8(() => {
3165
3242
  const result = triggerSignal.listen();
3166
3243
  if (result?.seed.value) {
3167
3244
  const ret = callback(result?.seed.config);
@@ -3183,9 +3260,15 @@ var CanvasText = class extends DisplayObject(PixiText) {
3183
3260
  this._wordWrapWidth = 0;
3184
3261
  this.typewriterOptions = {};
3185
3262
  }
3186
- onMount(args) {
3187
- super.onMount(args);
3188
- const { props } = args;
3263
+ /**
3264
+ * Called when the component is mounted to the scene graph.
3265
+ * Initializes the typewriter effect if configured.
3266
+ * @param {Element<CanvasText>} element - The element being mounted. Its `props` property (of type TextProps) contains component properties and context.
3267
+ * @param {number} [index] - The index of the component among its siblings.
3268
+ */
3269
+ async onMount(element, index) {
3270
+ await super.onMount(element, index);
3271
+ const { props } = element;
3189
3272
  const tick2 = props.context.tick;
3190
3273
  if (props.text && props.typewriter) {
3191
3274
  this.fullText = props.text;
@@ -3269,9 +3352,18 @@ var CanvasText = class extends DisplayObject(PixiText) {
3269
3352
  this.text = this.fullText;
3270
3353
  this.currentIndex = this.fullText.length;
3271
3354
  }
3272
- onDestroy() {
3273
- super.onDestroy();
3274
- this.subscriptionTick.unsubscribe();
3355
+ /**
3356
+ * Called when the component is about to be destroyed.
3357
+ * Unsubscribes from the tick observable.
3358
+ * @param {Element<any>} parent - The parent element.
3359
+ * @param {() => void} [afterDestroy] - An optional callback function to be executed after the component's own destruction logic.
3360
+ */
3361
+ async onDestroy(parent, afterDestroy) {
3362
+ const _afterDestroy = async () => {
3363
+ this.subscriptionTick.unsubscribe();
3364
+ afterDestroy();
3365
+ };
3366
+ await super.onDestroy(parent, _afterDestroy);
3275
3367
  }
3276
3368
  };
3277
3369
  registerComponent("Text", CanvasText);
@@ -3308,7 +3400,7 @@ function TilingSprite(props) {
3308
3400
 
3309
3401
  // src/components/Viewport.ts
3310
3402
  import { Viewport as PixiViewport } from "pixi-viewport";
3311
- import { effect as effect10 } from "@signe/reactive";
3403
+ import { effect as effect9 } from "@signe/reactive";
3312
3404
  var EVENTS3 = [
3313
3405
  "bounce-x-end",
3314
3406
  "bounce-x-start",
@@ -3352,24 +3444,36 @@ var CanvasViewport = class extends DisplayObject(PixiViewport) {
3352
3444
  if (props[event]) this.on(event, props[event]);
3353
3445
  }
3354
3446
  }
3355
- onMount(element) {
3356
- super.onMount(element);
3357
- const { tick: tick2, renderer, canvasSize } = element.props.context;
3447
+ /**
3448
+ * Called when the component is mounted to the scene graph.
3449
+ * Initializes viewport settings and subscriptions.
3450
+ * @param {Element<CanvasViewport>} element - The element being mounted. Its `props` property (of type ViewportProps) contains component properties and context.
3451
+ * @param {number} [index] - The index of the component among its siblings.
3452
+ */
3453
+ async onMount(element, index) {
3454
+ await super.onMount(element, index);
3455
+ const { props } = element;
3456
+ const { tick: tick2, app, canvasSize } = props.context;
3358
3457
  let isDragging = false;
3359
- effect10(() => {
3458
+ effect9(() => {
3360
3459
  this.screenWidth = canvasSize().width;
3361
3460
  this.screenHeight = canvasSize().height;
3362
3461
  });
3363
- renderer.events.domElement.addEventListener(
3364
- "wheel",
3365
- this.input.wheelFunction
3366
- );
3367
- this.options.events = renderer.events;
3462
+ effect9(() => {
3463
+ const _app = app();
3464
+ if (!_app) return;
3465
+ const renderer = _app.renderer;
3466
+ renderer.events.domElement.addEventListener(
3467
+ "wheel",
3468
+ this.input.wheelFunction
3469
+ );
3470
+ this.options.events = renderer.events;
3471
+ });
3368
3472
  this.tickSubscription = tick2.observable.subscribe(({ value }) => {
3369
3473
  this.update(value.timestamp);
3370
3474
  });
3371
3475
  element.props.context.viewport = this;
3372
- this.updateViewportSettings(element.props);
3476
+ this.updateViewportSettings(props);
3373
3477
  }
3374
3478
  onUpdate(props) {
3375
3479
  super.onUpdate(props);
@@ -3416,9 +3520,18 @@ var CanvasViewport = class extends DisplayObject(PixiViewport) {
3416
3520
  }
3417
3521
  }
3418
3522
  }
3419
- onDestroy() {
3420
- super.onDestroy();
3421
- this.tickSubscription.unsubscribe();
3523
+ /**
3524
+ * Called when the component is about to be destroyed.
3525
+ * Unsubscribes from the tick observable.
3526
+ * @param {Element<any>} parent - The parent element.
3527
+ * @param {() => void} [afterDestroy] - An optional callback function to be executed after the component's own destruction logic.
3528
+ */
3529
+ async onDestroy(parent, afterDestroy) {
3530
+ const _afterDestroy = async () => {
3531
+ this.tickSubscription.unsubscribe();
3532
+ afterDestroy();
3533
+ };
3534
+ await super.onDestroy(parent, _afterDestroy);
3422
3535
  }
3423
3536
  };
3424
3537
  registerComponent("Viewport", CanvasViewport);
@@ -3453,13 +3566,23 @@ function NineSliceSprite(props) {
3453
3566
  }
3454
3567
 
3455
3568
  // src/engine/bootstrap.ts
3569
+ import "@pixi/layout";
3570
+ import { Application as Application2 } from "pixi.js";
3456
3571
  var bootstrapCanvas = async (rootElement, canvas) => {
3572
+ const app = new Application2();
3573
+ await app.init({
3574
+ resizeTo: rootElement,
3575
+ autoStart: false
3576
+ });
3457
3577
  const canvasElement = await h(canvas);
3458
3578
  if (canvasElement.tag != "Canvas") {
3459
3579
  throw new Error("Canvas is required");
3460
3580
  }
3461
- canvasElement.render(rootElement);
3462
- return canvasElement;
3581
+ canvasElement.render(rootElement, app);
3582
+ return {
3583
+ canvasElement,
3584
+ app
3585
+ };
3463
3586
  };
3464
3587
 
3465
3588
  // src/utils/Ease.ts