canvasengine 2.0.0-beta.13 → 2.0.0-beta.14

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 CHANGED
@@ -1,11 +1,11 @@
1
1
  import * as _signe_reactive from '@signe/reactive';
2
- import { WritableSignal, Signal, WritableArraySignal, WritableObjectSignal } from '@signe/reactive';
2
+ import { WritableSignal, Signal } from '@signe/reactive';
3
3
  export * from '@signe/reactive';
4
4
  import { Subscription, Subject, Observable } from 'rxjs';
5
5
  export { isObservable } from 'rxjs';
6
6
  import { Node } from 'yoga-layout';
7
7
  import * as PIXI from 'pixi.js';
8
- import { ObservablePoint, Graphics as Graphics$1, Texture, TextStyle, Matrix } from 'pixi.js';
8
+ import { FederatedPointerEvent, ObservablePoint, Graphics as Graphics$1, Texture, TextStyle, Matrix } from 'pixi.js';
9
9
  export { Howler } from 'howler';
10
10
  import * as popmotion from 'popmotion';
11
11
 
@@ -68,6 +68,26 @@ declare function animatedSequence(sequence: ((() => Promise<void>) | (() => Prom
68
68
 
69
69
  type SignalOrPrimitive<T> = T | Signal<T> | AnimatedSignal<T>;
70
70
 
71
+ type DragProps = {
72
+ move?: (event: FederatedPointerEvent) => void;
73
+ start?: () => void;
74
+ end?: () => void;
75
+ snap?: SignalOrPrimitive<number>;
76
+ direction?: SignalOrPrimitive<'x' | 'y' | 'all'>;
77
+ viewport?: {
78
+ edgeThreshold?: SignalOrPrimitive<number>;
79
+ maxSpeed?: SignalOrPrimitive<number>;
80
+ };
81
+ };
82
+
83
+ type ViewportFollowProps = {
84
+ viewportFollow?: boolean | {
85
+ speed?: SignalOrPrimitive<number>;
86
+ acceleration?: SignalOrPrimitive<number>;
87
+ radius?: SignalOrPrimitive<number>;
88
+ };
89
+ };
90
+
71
91
  type FlexDirection = 'row' | 'column' | 'row-reverse' | 'column-reverse';
72
92
  type JustifyContent = 'flex-start' | 'flex-end' | 'center' | 'space-between' | 'space-around';
73
93
  type AlignContent = 'flex-start' | 'flex-end' | 'center' | 'space-between' | 'space-around';
@@ -114,6 +134,8 @@ interface DisplayObjectProps {
114
134
  filters?: any[];
115
135
  blendMode?: SignalOrPrimitive<PIXI.BLEND_MODES>;
116
136
  blur?: SignalOrPrimitive<number>;
137
+ drag?: DragProps;
138
+ viewportFollow?: ViewportFollowProps;
117
139
  click?: PIXI.FederatedEventHandler;
118
140
  mousedown?: PIXI.FederatedEventHandler;
119
141
  mouseenter?: PIXI.FederatedEventHandler;
@@ -219,17 +241,6 @@ declare function DisplayObject(extendClass: any): {
219
241
  interface Props {
220
242
  [key: string]: any;
221
243
  }
222
- type ArrayChange<T> = {
223
- type: "add" | "remove" | "update" | "init" | "reset";
224
- index?: number;
225
- items: T[];
226
- };
227
- type ObjectChange<T> = {
228
- type: "add" | "remove" | "update" | "init" | "reset";
229
- key?: string;
230
- value?: T;
231
- items: T[];
232
- };
233
244
  type NestedSignalObjects = {
234
245
  [Key in string]: NestedSignalObjects | Signal<any>;
235
246
  };
@@ -279,7 +290,7 @@ declare function createComponent(tag: string, props?: Props): Element;
279
290
  * @param {Function} createElementFn - A function that takes an item and returns an element representation.
280
291
  * @returns {Observable} An observable that emits the list of created child elements.
281
292
  */
282
- declare function loop<T>(itemsSubject: WritableArraySignal<T[]> | WritableObjectSignal<T>, createElementFn: (item: T, index: number | string) => Element | null): FlowObservable;
293
+ declare function loop<T>(itemsSubject: any, createElementFn: (item: T, index: number | string) => Element | null): FlowObservable;
283
294
  /**
284
295
  * Conditionally creates and destroys elements based on a condition signal.
285
296
  *
@@ -391,23 +402,18 @@ interface GraphicsProps extends DisplayObjectProps {
391
402
  draw?: (graphics: Graphics$1) => void;
392
403
  }
393
404
  interface RectProps extends DisplayObjectProps {
394
- width: number;
395
- height: number;
396
- color: string;
405
+ color: SignalOrPrimitive<string>;
397
406
  }
398
407
  interface CircleProps extends DisplayObjectProps {
399
- radius: number;
400
- color: string;
408
+ radius: SignalOrPrimitive<number>;
409
+ color: SignalOrPrimitive<string>;
401
410
  }
402
411
  interface EllipseProps extends DisplayObjectProps {
403
- width: number;
404
- height: number;
405
- color: string;
412
+ color: SignalOrPrimitive<string>;
406
413
  }
407
414
  interface TriangleProps extends DisplayObjectProps {
408
- base: number;
409
- height: number;
410
- color: string;
415
+ base: SignalOrPrimitive<number>;
416
+ color: SignalOrPrimitive<string>;
411
417
  }
412
418
  interface SvgProps extends DisplayObjectProps {
413
419
  svg: string;
@@ -1134,4 +1140,4 @@ declare namespace utils {
1134
1140
  export { utils_arrayEquals as arrayEquals, utils_calculateDistance as calculateDistance, utils_error as error, utils_fps2ms as fps2ms, utils_get as get, utils_isBrowser as isBrowser, utils_isFunction as isFunction, utils_isObject as isObject, utils_isPromise as isPromise, utils_log as log, utils_preciseNow as preciseNow, utils_set as set, utils_setObservablePoint as setObservablePoint };
1135
1141
  }
1136
1142
 
1137
- export { type AnimateOptions, type AnimatedSignal, type AnimatedState, type ArrayChange, Canvas, Circle, type ComponentFunction, type ComponentInstance, Container, DisplayObject, EVENTS, Easing, type Element, Ellipse, Graphics, NineSliceSprite, type ObjectChange, ParticlesEmitter, type Props, RadialGradient, Rect, Scene, Sprite, Text, TilingSprite, Triangle, utils as Utils, Video, Viewport, animatedSequence, animatedSignal, bootstrapCanvas, cond, createComponent, currentSubscriptionsTracker, h, isAnimatedSignal, isElement, isPrimitive, isTrigger, loop, mount, mountTracker, on, registerComponent, Svg as svg, tick, trigger, useDefineProps, useProps };
1143
+ export { type AnimateOptions, type AnimatedSignal, type AnimatedState, Canvas, Circle, type ComponentFunction, type ComponentInstance, Container, DisplayObject, EVENTS, Easing, type Element, Ellipse, Graphics, NineSliceSprite, ParticlesEmitter, type Props, RadialGradient, Rect, Scene, Sprite, Text, TilingSprite, Triangle, utils as Utils, Video, Viewport, animatedSequence, animatedSignal, bootstrapCanvas, cond, createComponent, currentSubscriptionsTracker, h, isAnimatedSignal, isElement, isPrimitive, isTrigger, loop, mount, mountTracker, on, registerComponent, Svg as svg, tick, trigger, useDefineProps, useProps };
package/dist/index.js CHANGED
@@ -959,135 +959,11 @@ var Scheduler = class extends Directive {
959
959
  };
960
960
  registerDirective("tick", Scheduler);
961
961
 
962
- // src/directives/ViewportFollow.ts
963
- var ViewportFollow = class extends Directive {
964
- onInit(element) {
965
- }
966
- onMount(element) {
967
- this.onUpdate(element.props, element);
968
- }
969
- onUpdate(props, element) {
970
- const { viewportFollow } = element.props;
971
- const { viewport } = element.props.context;
972
- if (!viewport) {
973
- throw error("ViewportFollow directive requires a Viewport component to be mounted in the same context");
974
- }
975
- if (viewportFollow) {
976
- viewport.follow(element.componentInstance);
977
- } else {
978
- viewport.plugins.remove("follow");
979
- }
980
- }
981
- onDestroy(element) {
982
- const { viewportFollow } = element.props;
983
- const { viewport } = element.props.context;
984
- if (viewportFollow) viewport.plugins.remove("follow");
985
- }
986
- };
987
- registerDirective("viewportFollow", ViewportFollow);
988
-
989
- // src/directives/Sound.ts
990
- import { effect } from "@signe/reactive";
991
- import { Howl } from "howler";
992
- var EVENTS = ["load", "loaderror", "playerror", "play", "end", "pause", "stop", "mute", "volume", "rate", "seek", "fade", "unlock"];
993
- var Sound = class extends Directive {
994
- constructor() {
995
- super(...arguments);
996
- this.eventsFn = [];
997
- this.maxVolume = 1;
998
- this.maxDistance = 100;
999
- }
1000
- onInit(element) {
1001
- }
1002
- onMount(element) {
1003
- const { props } = element;
1004
- const tick2 = props.context.tick;
1005
- const { src, autoplay, loop: loop2, volume, spatial } = props.sound;
1006
- this.sound = new Howl({
1007
- src,
1008
- autoplay,
1009
- loop: loop2,
1010
- volume
1011
- });
1012
- for (let event of EVENTS) {
1013
- if (!props.sound[event]) continue;
1014
- const fn = props.sound[event];
1015
- this.eventsFn.push(fn);
1016
- this.sound.on(event, fn);
1017
- }
1018
- if (spatial) {
1019
- const { soundListenerPosition } = props.context;
1020
- if (!soundListenerPosition) {
1021
- throw new error("SoundListenerPosition directive is required for spatial sound in component parent");
1022
- }
1023
- const { x: listenerX, y: listenerY } = soundListenerPosition;
1024
- this.tickSubscription = effect(() => {
1025
- tick2();
1026
- const { x, y } = element.componentInstance;
1027
- const distance = calculateDistance(x, y, listenerX(), listenerY());
1028
- const volume2 = Math.max(this.maxVolume - distance / this.maxDistance, 0);
1029
- this.sound.volume(volume2);
1030
- }).subscription;
1031
- }
1032
- }
1033
- onUpdate(props) {
1034
- const { volume, loop: loop2, mute, seek, playing, rate, spatial } = props;
1035
- if (volume != void 0) this.sound.volume(volume);
1036
- if (loop2 != void 0) this.sound.loop(loop2);
1037
- if (mute != void 0) this.sound.mute(mute);
1038
- if (seek != void 0) this.sound.seek(seek);
1039
- if (playing != void 0) {
1040
- if (playing) this.sound.play();
1041
- else this.sound.pause();
1042
- }
1043
- if (spatial) {
1044
- this.maxVolume = spatial.maxVolume ?? this.maxVolume;
1045
- this.maxDistance = spatial.maxDistance ?? this.maxDistance;
1046
- }
1047
- if (rate != void 0) this.sound.rate(rate);
1048
- }
1049
- onDestroy() {
1050
- this.sound.stop();
1051
- this.tickSubscription?.unsubscribe();
1052
- for (let event of EVENTS) {
1053
- if (this.eventsFn[event]) {
1054
- this.sound.off(event, this.eventsFn[event]);
1055
- }
1056
- }
1057
- }
1058
- };
1059
- var SoundListenerPosition = class extends Directive {
1060
- onMount(element) {
1061
- element.props.context.soundListenerPosition = element.propObservables?.soundListenerPosition;
1062
- }
1063
- onInit(element) {
1064
- }
1065
- onUpdate(props) {
1066
- }
1067
- onDestroy() {
1068
- }
1069
- };
1070
- registerDirective("sound", Sound);
1071
- registerDirective("soundListenerPosition", SoundListenerPosition);
1072
-
1073
- // src/directives/Drag.ts
1074
- import { effect as effect2, isSignal as isSignal3 } from "@signe/reactive";
1075
- import { Rectangle, Point } from "pixi.js";
1076
- import { snap } from "popmotion";
1077
-
1078
- // src/hooks/addContext.ts
1079
- var addContext = (element, key, value) => {
1080
- element.props.context = {
1081
- ...element.props.context ?? {},
1082
- [key]: value
1083
- };
1084
- };
1085
-
1086
962
  // src/hooks/useProps.ts
1087
- import { isSignal as isSignal2, signal } from "@signe/reactive";
963
+ import { isSignal as isSignal2, signal as signal2 } from "@signe/reactive";
1088
964
 
1089
965
  // src/engine/reactive.ts
1090
- import { isSignal } from "@signe/reactive";
966
+ import { isComputed, isSignal, signal } from "@signe/reactive";
1091
967
  import {
1092
968
  Observable,
1093
969
  Subject,
@@ -1116,11 +992,11 @@ function destroyElement(element) {
1116
992
  }
1117
993
  element.propSubscriptions.forEach((sub) => sub.unsubscribe());
1118
994
  element.effectSubscriptions.forEach((sub) => sub.unsubscribe());
995
+ element.effectUnmounts.forEach((fn) => fn?.());
1119
996
  for (let name in element.directives) {
1120
997
  element.directives[name].onDestroy?.(element);
1121
998
  }
1122
999
  element.componentInstance.onDestroy?.(element.parent);
1123
- element.effectUnmounts.forEach((fn) => fn?.());
1124
1000
  }
1125
1001
  function createComponent(tag, props) {
1126
1002
  if (!components[tag]) {
@@ -1285,11 +1161,16 @@ function createComponent(tag, props) {
1285
1161
  return element;
1286
1162
  }
1287
1163
  function loop(itemsSubject, createElementFn) {
1164
+ if (isComputed(itemsSubject) && itemsSubject.dependencies.size == 0) {
1165
+ itemsSubject = signal(itemsSubject());
1166
+ } else if (!isSignal(itemsSubject)) {
1167
+ itemsSubject = signal(itemsSubject);
1168
+ }
1288
1169
  return defer(() => {
1289
1170
  let elements = [];
1290
1171
  let elementMap = /* @__PURE__ */ new Map();
1291
1172
  let isFirstSubscription = true;
1292
- const isArraySignal = (signal8) => Array.isArray(signal8());
1173
+ const isArraySignal = (signal9) => Array.isArray(signal9());
1293
1174
  return new Observable((subscriber) => {
1294
1175
  const subscription = isArraySignal(itemsSubject) ? itemsSubject.observable.subscribe((change) => {
1295
1176
  if (isFirstSubscription) {
@@ -1481,11 +1362,11 @@ var useProps = (props, defaults = {}) => {
1481
1362
  const obj = {};
1482
1363
  for (let key in props) {
1483
1364
  const value = props[key];
1484
- obj[key] = isPrimitive(value) ? signal(value) : value;
1365
+ obj[key] = isPrimitive(value) ? signal2(value) : value;
1485
1366
  }
1486
1367
  for (let key in defaults) {
1487
1368
  if (!(key in obj)) {
1488
- obj[key] = isPrimitive(defaults[key]) ? signal(defaults[key]) : defaults[key];
1369
+ obj[key] = isPrimitive(defaults[key]) ? signal2(defaults[key]) : defaults[key];
1489
1370
  }
1490
1371
  }
1491
1372
  return obj;
@@ -1521,7 +1402,7 @@ var useDefineProps = (props) => {
1521
1402
  validatedValue = value;
1522
1403
  }
1523
1404
  }
1524
- validatedProps[key] = isSignal2(validatedValue) ? validatedValue : signal(validatedValue);
1405
+ validatedProps[key] = isSignal2(validatedValue) ? validatedValue : signal2(validatedValue);
1525
1406
  }
1526
1407
  return {
1527
1408
  ...useProps(rawProps),
@@ -1549,6 +1430,142 @@ function validateType(key, value, types) {
1549
1430
  }
1550
1431
  }
1551
1432
 
1433
+ // src/directives/ViewportFollow.ts
1434
+ var ViewportFollow = class extends Directive {
1435
+ onInit(element) {
1436
+ }
1437
+ onMount(element) {
1438
+ this.onUpdate(element.props.viewportFollow, element);
1439
+ }
1440
+ onUpdate(viewportFollow, element) {
1441
+ const { viewport } = element.props.context;
1442
+ if (!viewport) {
1443
+ throw error("ViewportFollow directive requires a Viewport component to be mounted in the same context");
1444
+ }
1445
+ if (viewportFollow) {
1446
+ if (viewportFollow === true) {
1447
+ viewport.follow(element.componentInstance);
1448
+ } else {
1449
+ const options = useProps(viewportFollow, {
1450
+ speed: void 0,
1451
+ acceleration: void 0,
1452
+ radius: void 0
1453
+ });
1454
+ viewport.follow(element.componentInstance, {
1455
+ speed: options.speed(),
1456
+ acceleration: options.acceleration(),
1457
+ radius: options.radius()
1458
+ });
1459
+ }
1460
+ } else {
1461
+ viewport.plugins.remove("follow");
1462
+ }
1463
+ }
1464
+ onDestroy(element) {
1465
+ const { viewportFollow } = element.props;
1466
+ const { viewport } = element.props.context;
1467
+ if (viewportFollow) viewport.plugins.remove("follow");
1468
+ }
1469
+ };
1470
+ registerDirective("viewportFollow", ViewportFollow);
1471
+
1472
+ // src/directives/Sound.ts
1473
+ import { effect } from "@signe/reactive";
1474
+ import { Howl } from "howler";
1475
+ var EVENTS = ["load", "loaderror", "playerror", "play", "end", "pause", "stop", "mute", "volume", "rate", "seek", "fade", "unlock"];
1476
+ var Sound = class extends Directive {
1477
+ constructor() {
1478
+ super(...arguments);
1479
+ this.eventsFn = [];
1480
+ this.maxVolume = 1;
1481
+ this.maxDistance = 100;
1482
+ }
1483
+ onInit(element) {
1484
+ }
1485
+ onMount(element) {
1486
+ const { props } = element;
1487
+ const tick2 = props.context.tick;
1488
+ const { src, autoplay, loop: loop2, volume, spatial } = props.sound;
1489
+ this.sound = new Howl({
1490
+ src,
1491
+ autoplay,
1492
+ loop: loop2,
1493
+ volume
1494
+ });
1495
+ for (let event of EVENTS) {
1496
+ if (!props.sound[event]) continue;
1497
+ const fn = props.sound[event];
1498
+ this.eventsFn.push(fn);
1499
+ this.sound.on(event, fn);
1500
+ }
1501
+ if (spatial) {
1502
+ const { soundListenerPosition } = props.context;
1503
+ if (!soundListenerPosition) {
1504
+ throw new error("SoundListenerPosition directive is required for spatial sound in component parent");
1505
+ }
1506
+ const { x: listenerX, y: listenerY } = soundListenerPosition;
1507
+ this.tickSubscription = effect(() => {
1508
+ tick2();
1509
+ const { x, y } = element.componentInstance;
1510
+ const distance = calculateDistance(x, y, listenerX(), listenerY());
1511
+ const volume2 = Math.max(this.maxVolume - distance / this.maxDistance, 0);
1512
+ this.sound.volume(volume2);
1513
+ }).subscription;
1514
+ }
1515
+ }
1516
+ onUpdate(props) {
1517
+ const { volume, loop: loop2, mute, seek, playing, rate, spatial } = props;
1518
+ if (volume != void 0) this.sound.volume(volume);
1519
+ if (loop2 != void 0) this.sound.loop(loop2);
1520
+ if (mute != void 0) this.sound.mute(mute);
1521
+ if (seek != void 0) this.sound.seek(seek);
1522
+ if (playing != void 0) {
1523
+ if (playing) this.sound.play();
1524
+ else this.sound.pause();
1525
+ }
1526
+ if (spatial) {
1527
+ this.maxVolume = spatial.maxVolume ?? this.maxVolume;
1528
+ this.maxDistance = spatial.maxDistance ?? this.maxDistance;
1529
+ }
1530
+ if (rate != void 0) this.sound.rate(rate);
1531
+ }
1532
+ onDestroy() {
1533
+ this.sound.stop();
1534
+ this.tickSubscription?.unsubscribe();
1535
+ for (let event of EVENTS) {
1536
+ if (this.eventsFn[event]) {
1537
+ this.sound.off(event, this.eventsFn[event]);
1538
+ }
1539
+ }
1540
+ }
1541
+ };
1542
+ var SoundListenerPosition = class extends Directive {
1543
+ onMount(element) {
1544
+ element.props.context.soundListenerPosition = element.propObservables?.soundListenerPosition;
1545
+ }
1546
+ onInit(element) {
1547
+ }
1548
+ onUpdate(props) {
1549
+ }
1550
+ onDestroy() {
1551
+ }
1552
+ };
1553
+ registerDirective("sound", Sound);
1554
+ registerDirective("soundListenerPosition", SoundListenerPosition);
1555
+
1556
+ // src/directives/Drag.ts
1557
+ import { effect as effect2, isComputed as isComputed2, isSignal as isSignal3 } from "@signe/reactive";
1558
+ import { Rectangle, Point } from "pixi.js";
1559
+ import { snap } from "popmotion";
1560
+
1561
+ // src/hooks/addContext.ts
1562
+ var addContext = (element, key, value) => {
1563
+ element.props.context = {
1564
+ ...element.props.context ?? {},
1565
+ [key]: value
1566
+ };
1567
+ };
1568
+
1552
1569
  // src/directives/Drag.ts
1553
1570
  var Drop = class extends Directive {
1554
1571
  constructor() {
@@ -1674,10 +1691,17 @@ var Drag = class extends Directive {
1674
1691
  }
1675
1692
  this.lastPointerPosition.copyFrom(event.global);
1676
1693
  const { x: xProp, y: yProp } = propObservables;
1677
- if (xProp !== void 0 && isSignal3(xProp)) {
1678
- }
1679
- if (yProp !== void 0 && isSignal3(yProp)) {
1680
- }
1694
+ const updatePosition = (prop, value) => {
1695
+ if (isComputed2(prop)) {
1696
+ prop.dependencies.forEach((dependency) => {
1697
+ dependency.set(value);
1698
+ });
1699
+ } else if (isSignal3(prop)) {
1700
+ prop.set(value);
1701
+ }
1702
+ };
1703
+ if (xProp !== void 0) updatePosition(xProp, instance.position.x);
1704
+ if (yProp !== void 0) updatePosition(yProp, instance.position.y);
1681
1705
  }
1682
1706
  /**
1683
1707
  * Moves the viewport if the dragged element is near screen edges
@@ -1814,12 +1838,12 @@ export * from "@signe/reactive";
1814
1838
  import { Howler } from "howler";
1815
1839
 
1816
1840
  // src/components/Canvas.ts
1817
- import { effect as effect4, signal as signal4 } from "@signe/reactive";
1841
+ import { effect as effect4, signal as signal5 } from "@signe/reactive";
1818
1842
  import { Container as Container3, autoDetectRenderer } from "pixi.js";
1819
1843
  import { loadYoga } from "yoga-layout";
1820
1844
 
1821
1845
  // src/components/DisplayObject.ts
1822
- import { effect as effect3, signal as signal3 } from "@signe/reactive";
1846
+ import { effect as effect3, signal as signal4 } from "@signe/reactive";
1823
1847
  import { DropShadowFilter } from "pixi-filters";
1824
1848
  import { BlurFilter, ObservablePoint } from "pixi.js";
1825
1849
  var EVENTS2 = [
@@ -1909,8 +1933,8 @@ function DisplayObject(extendClass) {
1909
1933
  0
1910
1934
  );
1911
1935
  this.isCustomAnchor = false;
1912
- this.displayWidth = signal3(0);
1913
- this.displayHeight = signal3(0);
1936
+ this.displayWidth = signal4(0);
1937
+ this.displayHeight = signal4(0);
1914
1938
  this.overrideProps = [];
1915
1939
  }
1916
1940
  get yoga() {
@@ -2206,14 +2230,14 @@ registerComponent("Canvas", class Canvas extends DisplayObject(Container3) {
2206
2230
  var Canvas2 = async (props = {}) => {
2207
2231
  let { cursorStyles, width, height, class: className } = useProps(props);
2208
2232
  const Yoga = await loadYoga();
2209
- if (!props.width) width = signal4(800);
2210
- if (!props.height) height = signal4(600);
2233
+ if (!props.width) width = signal5(800);
2234
+ if (!props.height) height = signal5(600);
2211
2235
  const renderer = await autoDetectRenderer({
2212
2236
  ...props,
2213
2237
  width: width?.(),
2214
2238
  height: height?.()
2215
2239
  });
2216
- const canvasSize = signal4({
2240
+ const canvasSize = signal5({
2217
2241
  width: renderer.width,
2218
2242
  height: renderer.height
2219
2243
  });
@@ -2229,7 +2253,7 @@ var Canvas2 = async (props = {}) => {
2229
2253
  height: height?.()
2230
2254
  };
2231
2255
  if (!props.tick) {
2232
- options.context.tick = options.tick = signal4({
2256
+ options.context.tick = options.tick = signal5({
2233
2257
  timestamp: 0,
2234
2258
  deltaTime: 0,
2235
2259
  frame: 0,
@@ -2326,12 +2350,16 @@ var CanvasGraphics = class extends DisplayObject(PixiGraphics) {
2326
2350
  onInit(props) {
2327
2351
  super.onInit(props);
2328
2352
  if (props.draw) {
2329
- effect5(() => {
2353
+ this.clearEffect = effect5(() => {
2330
2354
  this.clear();
2331
2355
  props.draw?.(this);
2332
2356
  });
2333
2357
  }
2334
2358
  }
2359
+ onDestroy() {
2360
+ this.clearEffect.subscription.unsubscribe();
2361
+ super.onDestroy();
2362
+ }
2335
2363
  };
2336
2364
  registerComponent("Graphics", CanvasGraphics);
2337
2365
  function Graphics(props) {
@@ -2515,10 +2543,10 @@ import {
2515
2543
  } from "pixi.js";
2516
2544
 
2517
2545
  // src/engine/animation.ts
2518
- import { effect as effect6, signal as signal5 } from "@signe/reactive";
2546
+ import { effect as effect6, signal as signal6 } from "@signe/reactive";
2519
2547
  import { animate as animatePopmotion } from "popmotion";
2520
- function isAnimatedSignal(signal8) {
2521
- return signal8.animatedState !== void 0;
2548
+ function isAnimatedSignal(signal9) {
2549
+ return signal9.animatedState !== void 0;
2522
2550
  }
2523
2551
  function animatedSignal(initialValue, options = {}) {
2524
2552
  const state = {
@@ -2527,8 +2555,8 @@ function animatedSignal(initialValue, options = {}) {
2527
2555
  end: initialValue
2528
2556
  };
2529
2557
  let animation;
2530
- const publicSignal = signal5(initialValue);
2531
- const privateSignal = signal5(state);
2558
+ const publicSignal = signal6(initialValue);
2559
+ const privateSignal = signal6(state);
2532
2560
  effect6(() => {
2533
2561
  const currentState = privateSignal();
2534
2562
  publicSignal.set(currentState.current);
@@ -2910,7 +2938,7 @@ var Sprite2 = (props) => {
2910
2938
  };
2911
2939
 
2912
2940
  // src/components/Video.ts
2913
- import { effect as effect8, signal as signal6 } from "@signe/reactive";
2941
+ import { effect as effect8, signal as signal7 } from "@signe/reactive";
2914
2942
  function Video(props) {
2915
2943
  const eventsMap = {
2916
2944
  audioprocess: null,
@@ -2935,7 +2963,7 @@ function Video(props) {
2935
2963
  volumechange: null,
2936
2964
  waiting: null
2937
2965
  };
2938
- const video = signal6(null);
2966
+ const video = signal7(null);
2939
2967
  const defineProps = useDefineProps(props);
2940
2968
  const { play, loop: loop2, muted } = defineProps({
2941
2969
  play: {
@@ -3005,12 +3033,12 @@ function Video(props) {
3005
3033
  import { Text as PixiText } from "pixi.js";
3006
3034
 
3007
3035
  // src/engine/trigger.ts
3008
- import { effect as effect9, signal as signal7 } from "@signe/reactive";
3036
+ import { effect as effect9, signal as signal8 } from "@signe/reactive";
3009
3037
  function isTrigger(arg) {
3010
3038
  return arg?.start && arg?.listen;
3011
3039
  }
3012
3040
  function trigger(globalConfig) {
3013
- const _signal = signal7({
3041
+ const _signal = signal8({
3014
3042
  config: globalConfig,
3015
3043
  value: 0,
3016
3044
  resolve: (value) => void 0