canvasengine 2.0.0-beta.12 → 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 +34 -28
- package/dist/index.js +461 -186
- package/dist/index.js.map +1 -1
- package/package.json +2 -2
- package/src/components/Graphic.ts +15 -13
- package/src/components/Viewport.ts +5 -11
- package/src/components/types/DisplayObject.ts +7 -0
- package/src/directives/Drag.ts +271 -53
- package/src/directives/KeyboardControls.ts +3 -1
- package/src/directives/ViewportFollow.ts +35 -7
- package/src/engine/directive.ts +2 -2
- package/src/engine/reactive.ts +13 -24
- package/src/hooks/useProps.ts +1 -1
package/dist/index.js
CHANGED
|
@@ -347,8 +347,10 @@ var KeyboardControls = class extends Directive {
|
|
|
347
347
|
};
|
|
348
348
|
}
|
|
349
349
|
onInit(element) {
|
|
350
|
+
const value = element.props.controls.value ?? element.props.controls;
|
|
351
|
+
if (!value) return;
|
|
350
352
|
this.setupListeners();
|
|
351
|
-
this.setInputs(
|
|
353
|
+
this.setInputs(value);
|
|
352
354
|
this.interval = setInterval(() => {
|
|
353
355
|
this.preStep();
|
|
354
356
|
}, fps2ms(this.serverFps ?? 60));
|
|
@@ -957,158 +959,11 @@ var Scheduler = class extends Directive {
|
|
|
957
959
|
};
|
|
958
960
|
registerDirective("tick", Scheduler);
|
|
959
961
|
|
|
960
|
-
// src/
|
|
961
|
-
|
|
962
|
-
onInit(element) {
|
|
963
|
-
}
|
|
964
|
-
onMount(element) {
|
|
965
|
-
const { viewportFollow } = element.props;
|
|
966
|
-
const { viewport } = element.props.context;
|
|
967
|
-
if (!viewport) {
|
|
968
|
-
throw error("ViewportFollow directive requires a Viewport component to be mounted in the same context");
|
|
969
|
-
}
|
|
970
|
-
if (viewportFollow) viewport.follow(element.componentInstance);
|
|
971
|
-
}
|
|
972
|
-
onUpdate(props) {
|
|
973
|
-
}
|
|
974
|
-
onDestroy() {
|
|
975
|
-
}
|
|
976
|
-
};
|
|
977
|
-
registerDirective("viewportFollow", ViewportFollow);
|
|
978
|
-
|
|
979
|
-
// src/directives/Sound.ts
|
|
980
|
-
import { effect } from "@signe/reactive";
|
|
981
|
-
import { Howl } from "howler";
|
|
982
|
-
var EVENTS = ["load", "loaderror", "playerror", "play", "end", "pause", "stop", "mute", "volume", "rate", "seek", "fade", "unlock"];
|
|
983
|
-
var Sound = class extends Directive {
|
|
984
|
-
constructor() {
|
|
985
|
-
super(...arguments);
|
|
986
|
-
this.eventsFn = [];
|
|
987
|
-
this.maxVolume = 1;
|
|
988
|
-
this.maxDistance = 100;
|
|
989
|
-
}
|
|
990
|
-
onInit(element) {
|
|
991
|
-
}
|
|
992
|
-
onMount(element) {
|
|
993
|
-
const { props } = element;
|
|
994
|
-
const tick2 = props.context.tick;
|
|
995
|
-
const { src, autoplay, loop: loop2, volume, spatial } = props.sound;
|
|
996
|
-
this.sound = new Howl({
|
|
997
|
-
src,
|
|
998
|
-
autoplay,
|
|
999
|
-
loop: loop2,
|
|
1000
|
-
volume
|
|
1001
|
-
});
|
|
1002
|
-
for (let event of EVENTS) {
|
|
1003
|
-
if (!props.sound[event]) continue;
|
|
1004
|
-
const fn = props.sound[event];
|
|
1005
|
-
this.eventsFn.push(fn);
|
|
1006
|
-
this.sound.on(event, fn);
|
|
1007
|
-
}
|
|
1008
|
-
if (spatial) {
|
|
1009
|
-
const { soundListenerPosition } = props.context;
|
|
1010
|
-
if (!soundListenerPosition) {
|
|
1011
|
-
throw new error("SoundListenerPosition directive is required for spatial sound in component parent");
|
|
1012
|
-
}
|
|
1013
|
-
const { x: listenerX, y: listenerY } = soundListenerPosition;
|
|
1014
|
-
this.tickSubscription = effect(() => {
|
|
1015
|
-
tick2();
|
|
1016
|
-
const { x, y } = element.componentInstance;
|
|
1017
|
-
const distance = calculateDistance(x, y, listenerX(), listenerY());
|
|
1018
|
-
const volume2 = Math.max(this.maxVolume - distance / this.maxDistance, 0);
|
|
1019
|
-
this.sound.volume(volume2);
|
|
1020
|
-
}).subscription;
|
|
1021
|
-
}
|
|
1022
|
-
}
|
|
1023
|
-
onUpdate(props) {
|
|
1024
|
-
const { volume, loop: loop2, mute, seek, playing, rate, spatial } = props;
|
|
1025
|
-
if (volume != void 0) this.sound.volume(volume);
|
|
1026
|
-
if (loop2 != void 0) this.sound.loop(loop2);
|
|
1027
|
-
if (mute != void 0) this.sound.mute(mute);
|
|
1028
|
-
if (seek != void 0) this.sound.seek(seek);
|
|
1029
|
-
if (playing != void 0) {
|
|
1030
|
-
if (playing) this.sound.play();
|
|
1031
|
-
else this.sound.pause();
|
|
1032
|
-
}
|
|
1033
|
-
if (spatial) {
|
|
1034
|
-
this.maxVolume = spatial.maxVolume ?? this.maxVolume;
|
|
1035
|
-
this.maxDistance = spatial.maxDistance ?? this.maxDistance;
|
|
1036
|
-
}
|
|
1037
|
-
if (rate != void 0) this.sound.rate(rate);
|
|
1038
|
-
}
|
|
1039
|
-
onDestroy() {
|
|
1040
|
-
this.sound.stop();
|
|
1041
|
-
this.tickSubscription?.unsubscribe();
|
|
1042
|
-
for (let event of EVENTS) {
|
|
1043
|
-
if (this.eventsFn[event]) {
|
|
1044
|
-
this.sound.off(event, this.eventsFn[event]);
|
|
1045
|
-
}
|
|
1046
|
-
}
|
|
1047
|
-
}
|
|
1048
|
-
};
|
|
1049
|
-
var SoundListenerPosition = class extends Directive {
|
|
1050
|
-
onMount(element) {
|
|
1051
|
-
element.props.context.soundListenerPosition = element.propObservables?.soundListenerPosition;
|
|
1052
|
-
}
|
|
1053
|
-
onInit(element) {
|
|
1054
|
-
}
|
|
1055
|
-
onUpdate(props) {
|
|
1056
|
-
}
|
|
1057
|
-
onDestroy() {
|
|
1058
|
-
}
|
|
1059
|
-
};
|
|
1060
|
-
registerDirective("sound", Sound);
|
|
1061
|
-
registerDirective("soundListenerPosition", SoundListenerPosition);
|
|
1062
|
-
|
|
1063
|
-
// src/directives/Drag.ts
|
|
1064
|
-
import { effect as effect2, isSignal } from "@signe/reactive";
|
|
1065
|
-
import { Rectangle } from "pixi.js";
|
|
1066
|
-
import { snap } from "popmotion";
|
|
1067
|
-
|
|
1068
|
-
// src/directives/Transition.ts
|
|
1069
|
-
import { DisplacementFilter, Sprite, Texture, WRAP_MODES } from "pixi.js";
|
|
1070
|
-
import { animate } from "popmotion";
|
|
1071
|
-
var Transition = class extends Directive {
|
|
1072
|
-
onInit(element) {
|
|
1073
|
-
}
|
|
1074
|
-
onMount(element) {
|
|
1075
|
-
const { image } = element.props.transition;
|
|
1076
|
-
const displacementSprite = new Sprite(Texture.from(image));
|
|
1077
|
-
displacementSprite.texture.baseTexture.wrapMode = WRAP_MODES.REPEAT;
|
|
1078
|
-
const displacementFilter = new DisplacementFilter(displacementSprite);
|
|
1079
|
-
const instance = element.componentInstance;
|
|
1080
|
-
instance.filters = [displacementFilter];
|
|
1081
|
-
instance.addChild(displacementSprite);
|
|
1082
|
-
setTimeout(() => {
|
|
1083
|
-
animate({
|
|
1084
|
-
from: 0,
|
|
1085
|
-
to: 1,
|
|
1086
|
-
duration: 500,
|
|
1087
|
-
onUpdate: (progress) => {
|
|
1088
|
-
displacementFilter.scale.x = progress;
|
|
1089
|
-
displacementFilter.scale.y = progress;
|
|
1090
|
-
}
|
|
1091
|
-
});
|
|
1092
|
-
}, 5e3);
|
|
1093
|
-
}
|
|
1094
|
-
onUpdate(props) {
|
|
1095
|
-
}
|
|
1096
|
-
onDestroy() {
|
|
1097
|
-
}
|
|
1098
|
-
};
|
|
1099
|
-
registerDirective("transition", Transition);
|
|
1100
|
-
|
|
1101
|
-
// src/index.ts
|
|
1102
|
-
export * from "@signe/reactive";
|
|
1103
|
-
import { Howler } from "howler";
|
|
1104
|
-
|
|
1105
|
-
// src/components/Canvas.ts
|
|
1106
|
-
import { effect as effect4, signal as signal3 } from "@signe/reactive";
|
|
1107
|
-
import { Container as Container3, autoDetectRenderer } from "pixi.js";
|
|
1108
|
-
import { loadYoga } from "yoga-layout";
|
|
962
|
+
// src/hooks/useProps.ts
|
|
963
|
+
import { isSignal as isSignal2, signal as signal2 } from "@signe/reactive";
|
|
1109
964
|
|
|
1110
965
|
// src/engine/reactive.ts
|
|
1111
|
-
import { isSignal
|
|
966
|
+
import { isComputed, isSignal, signal } from "@signe/reactive";
|
|
1112
967
|
import {
|
|
1113
968
|
Observable,
|
|
1114
969
|
Subject,
|
|
@@ -1137,11 +992,11 @@ function destroyElement(element) {
|
|
|
1137
992
|
}
|
|
1138
993
|
element.propSubscriptions.forEach((sub) => sub.unsubscribe());
|
|
1139
994
|
element.effectSubscriptions.forEach((sub) => sub.unsubscribe());
|
|
995
|
+
element.effectUnmounts.forEach((fn) => fn?.());
|
|
1140
996
|
for (let name in element.directives) {
|
|
1141
|
-
element.directives[name].onDestroy?.();
|
|
997
|
+
element.directives[name].onDestroy?.(element);
|
|
1142
998
|
}
|
|
1143
999
|
element.componentInstance.onDestroy?.(element.parent);
|
|
1144
|
-
element.effectUnmounts.forEach((fn) => fn?.());
|
|
1145
1000
|
}
|
|
1146
1001
|
function createComponent(tag, props) {
|
|
1147
1002
|
if (!components[tag]) {
|
|
@@ -1174,7 +1029,7 @@ function createComponent(tag, props) {
|
|
|
1174
1029
|
set(element.props, path2 + "." + key, value);
|
|
1175
1030
|
};
|
|
1176
1031
|
Object.entries(props2).forEach(([key, value]) => {
|
|
1177
|
-
if (
|
|
1032
|
+
if (isSignal(value)) {
|
|
1178
1033
|
const _value = value;
|
|
1179
1034
|
if ("dependencies" in _value && _value.dependencies.size == 0) {
|
|
1180
1035
|
_set(path, key, _value());
|
|
@@ -1184,7 +1039,7 @@ function createComponent(tag, props) {
|
|
|
1184
1039
|
_value.observable.subscribe((value2) => {
|
|
1185
1040
|
_set(path, key, value2);
|
|
1186
1041
|
if (element.directives[key]) {
|
|
1187
|
-
element.directives[key].onUpdate?.(value2);
|
|
1042
|
+
element.directives[key].onUpdate?.(value2, element);
|
|
1188
1043
|
}
|
|
1189
1044
|
if (key == "tick") {
|
|
1190
1045
|
return;
|
|
@@ -1235,7 +1090,7 @@ function createComponent(tag, props) {
|
|
|
1235
1090
|
;
|
|
1236
1091
|
async function propagateContext(element2) {
|
|
1237
1092
|
if (element2.props.attach) {
|
|
1238
|
-
const isReactiveAttach =
|
|
1093
|
+
const isReactiveAttach = isSignal(element2.propObservables?.attach);
|
|
1239
1094
|
if (!isReactiveAttach) {
|
|
1240
1095
|
element2.props.children.push(element2.props.attach);
|
|
1241
1096
|
} else {
|
|
@@ -1306,11 +1161,16 @@ function createComponent(tag, props) {
|
|
|
1306
1161
|
return element;
|
|
1307
1162
|
}
|
|
1308
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
|
+
}
|
|
1309
1169
|
return defer(() => {
|
|
1310
1170
|
let elements = [];
|
|
1311
1171
|
let elementMap = /* @__PURE__ */ new Map();
|
|
1312
1172
|
let isFirstSubscription = true;
|
|
1313
|
-
const isArraySignal = (
|
|
1173
|
+
const isArraySignal = (signal9) => Array.isArray(signal9());
|
|
1314
1174
|
return new Observable((subscriber) => {
|
|
1315
1175
|
const subscription = isArraySignal(itemsSubject) ? itemsSubject.observable.subscribe((change) => {
|
|
1316
1176
|
if (isFirstSubscription) {
|
|
@@ -1439,7 +1299,7 @@ function loop(itemsSubject, createElementFn) {
|
|
|
1439
1299
|
}
|
|
1440
1300
|
function cond(condition, createElementFn) {
|
|
1441
1301
|
let element = null;
|
|
1442
|
-
if (
|
|
1302
|
+
if (isSignal(condition)) {
|
|
1443
1303
|
const signalCondition = condition;
|
|
1444
1304
|
return new Observable((subscriber) => {
|
|
1445
1305
|
return signalCondition.observable.subscribe((bool) => {
|
|
@@ -1495,26 +1355,25 @@ function cond(condition, createElementFn) {
|
|
|
1495
1355
|
}
|
|
1496
1356
|
|
|
1497
1357
|
// src/hooks/useProps.ts
|
|
1498
|
-
import { isSignal as isSignal3, signal } from "@signe/reactive";
|
|
1499
1358
|
var useProps = (props, defaults = {}) => {
|
|
1500
|
-
if (
|
|
1359
|
+
if (isSignal2(props)) {
|
|
1501
1360
|
return props();
|
|
1502
1361
|
}
|
|
1503
1362
|
const obj = {};
|
|
1504
1363
|
for (let key in props) {
|
|
1505
1364
|
const value = props[key];
|
|
1506
|
-
obj[key] = isPrimitive(value) ?
|
|
1365
|
+
obj[key] = isPrimitive(value) ? signal2(value) : value;
|
|
1507
1366
|
}
|
|
1508
1367
|
for (let key in defaults) {
|
|
1509
1368
|
if (!(key in obj)) {
|
|
1510
|
-
obj[key] =
|
|
1369
|
+
obj[key] = isPrimitive(defaults[key]) ? signal2(defaults[key]) : defaults[key];
|
|
1511
1370
|
}
|
|
1512
1371
|
}
|
|
1513
1372
|
return obj;
|
|
1514
1373
|
};
|
|
1515
1374
|
var useDefineProps = (props) => {
|
|
1516
1375
|
return (schema) => {
|
|
1517
|
-
const rawProps =
|
|
1376
|
+
const rawProps = isSignal2(props) ? props() : props;
|
|
1518
1377
|
const validatedProps = {};
|
|
1519
1378
|
for (const key in schema) {
|
|
1520
1379
|
const propConfig = schema[key];
|
|
@@ -1543,7 +1402,7 @@ var useDefineProps = (props) => {
|
|
|
1543
1402
|
validatedValue = value;
|
|
1544
1403
|
}
|
|
1545
1404
|
}
|
|
1546
|
-
validatedProps[key] =
|
|
1405
|
+
validatedProps[key] = isSignal2(validatedValue) ? validatedValue : signal2(validatedValue);
|
|
1547
1406
|
}
|
|
1548
1407
|
return {
|
|
1549
1408
|
...useProps(rawProps),
|
|
@@ -1553,7 +1412,7 @@ var useDefineProps = (props) => {
|
|
|
1553
1412
|
};
|
|
1554
1413
|
function validateType(key, value, types) {
|
|
1555
1414
|
if (value === void 0 || value === null) return;
|
|
1556
|
-
const valueToCheck =
|
|
1415
|
+
const valueToCheck = isSignal2(value) ? value() : value;
|
|
1557
1416
|
const valid = types.some((type) => {
|
|
1558
1417
|
if (type === Number) return typeof valueToCheck === "number";
|
|
1559
1418
|
if (type === String) return typeof valueToCheck === "string";
|
|
@@ -1571,8 +1430,420 @@ function validateType(key, value, types) {
|
|
|
1571
1430
|
}
|
|
1572
1431
|
}
|
|
1573
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
|
+
|
|
1569
|
+
// src/directives/Drag.ts
|
|
1570
|
+
var Drop = class extends Directive {
|
|
1571
|
+
constructor() {
|
|
1572
|
+
super(...arguments);
|
|
1573
|
+
this.elementRef = null;
|
|
1574
|
+
}
|
|
1575
|
+
onInit(element) {
|
|
1576
|
+
this.elementRef = element;
|
|
1577
|
+
}
|
|
1578
|
+
onMount(element) {
|
|
1579
|
+
addContext(element, "drop", element);
|
|
1580
|
+
}
|
|
1581
|
+
onUpdate() {
|
|
1582
|
+
}
|
|
1583
|
+
onDestroy() {
|
|
1584
|
+
this.elementRef = null;
|
|
1585
|
+
}
|
|
1586
|
+
};
|
|
1587
|
+
var Drag = class extends Directive {
|
|
1588
|
+
constructor() {
|
|
1589
|
+
super(...arguments);
|
|
1590
|
+
this.elementRef = null;
|
|
1591
|
+
this.stageRef = null;
|
|
1592
|
+
this.offsetInParent = new Point();
|
|
1593
|
+
this.isDragging = false;
|
|
1594
|
+
this.viewport = null;
|
|
1595
|
+
this.animationFrameId = null;
|
|
1596
|
+
this.lastPointerPosition = new Point();
|
|
1597
|
+
this.onDragMoveHandler = () => {
|
|
1598
|
+
};
|
|
1599
|
+
this.onDragEndHandler = () => {
|
|
1600
|
+
};
|
|
1601
|
+
this.onDragStartHandler = () => {
|
|
1602
|
+
};
|
|
1603
|
+
this.subscriptions = [];
|
|
1604
|
+
}
|
|
1605
|
+
onInit(element) {
|
|
1606
|
+
this.elementRef = element;
|
|
1607
|
+
this.onDragMoveHandler = this.onDragMove.bind(this);
|
|
1608
|
+
this.onDragEndHandler = this.onDragEnd.bind(this);
|
|
1609
|
+
this.onDragStartHandler = this.onPointerDown.bind(this);
|
|
1610
|
+
}
|
|
1611
|
+
onMount(element) {
|
|
1612
|
+
const { rootElement, canvasSize, viewport, tick: tick2 } = element.props.context;
|
|
1613
|
+
const instance = element.componentInstance;
|
|
1614
|
+
const dragProps = this.dragProps;
|
|
1615
|
+
const haveNotProps = Object.keys(dragProps).length === 0;
|
|
1616
|
+
if (haveNotProps) {
|
|
1617
|
+
this.onDestroy();
|
|
1618
|
+
return;
|
|
1619
|
+
}
|
|
1620
|
+
if (!instance) return;
|
|
1621
|
+
this.stageRef = rootElement.componentInstance;
|
|
1622
|
+
if (!this.stageRef) return;
|
|
1623
|
+
this.viewport = viewport;
|
|
1624
|
+
instance.eventMode = "static";
|
|
1625
|
+
this.stageRef.eventMode = "static";
|
|
1626
|
+
const _effect = effect2(() => {
|
|
1627
|
+
if (this.stageRef) {
|
|
1628
|
+
this.stageRef.hitArea = new Rectangle(0, 0, canvasSize().width, canvasSize().height);
|
|
1629
|
+
}
|
|
1630
|
+
});
|
|
1631
|
+
instance.on("pointerdown", this.onDragStartHandler);
|
|
1632
|
+
this.stageRef.on("pointerup", this.onDragEndHandler);
|
|
1633
|
+
this.stageRef.on("pointerupoutside", this.onDragEndHandler);
|
|
1634
|
+
this.subscriptions = [
|
|
1635
|
+
tick2.observable.subscribe(() => {
|
|
1636
|
+
if (this.isDragging && this.viewport) {
|
|
1637
|
+
this.updateViewportPosition(this.lastPointerPosition);
|
|
1638
|
+
}
|
|
1639
|
+
}),
|
|
1640
|
+
_effect.subscription
|
|
1641
|
+
];
|
|
1642
|
+
}
|
|
1643
|
+
get dragProps() {
|
|
1644
|
+
const drag = this.elementRef?.props.drag;
|
|
1645
|
+
const options = useProps(drag?.value ?? drag, {
|
|
1646
|
+
snap: 0,
|
|
1647
|
+
viewport: {},
|
|
1648
|
+
direction: "all"
|
|
1649
|
+
});
|
|
1650
|
+
options.viewport = useProps(options.viewport, {
|
|
1651
|
+
edgeThreshold: 300,
|
|
1652
|
+
maxSpeed: 40
|
|
1653
|
+
});
|
|
1654
|
+
return options;
|
|
1655
|
+
}
|
|
1656
|
+
get axis() {
|
|
1657
|
+
const direction = this.dragProps.direction();
|
|
1658
|
+
const axis = {
|
|
1659
|
+
x: true,
|
|
1660
|
+
y: true
|
|
1661
|
+
};
|
|
1662
|
+
if (direction === "x") {
|
|
1663
|
+
axis.y = false;
|
|
1664
|
+
}
|
|
1665
|
+
if (direction === "y") {
|
|
1666
|
+
axis.x = false;
|
|
1667
|
+
}
|
|
1668
|
+
return axis;
|
|
1669
|
+
}
|
|
1670
|
+
/**
|
|
1671
|
+
* Updates element position when dragging and starts continuous viewport movement
|
|
1672
|
+
* @param event The pointer event that triggered the drag move
|
|
1673
|
+
*/
|
|
1674
|
+
onDragMove(event) {
|
|
1675
|
+
if (!this.isDragging || !this.elementRef?.componentInstance || !this.elementRef.componentInstance.parent) return;
|
|
1676
|
+
const instance = this.elementRef.componentInstance;
|
|
1677
|
+
const parent = instance.parent;
|
|
1678
|
+
const dragProps = this.dragProps;
|
|
1679
|
+
const propObservables = this.elementRef.propObservables;
|
|
1680
|
+
const snapTo = snap(dragProps?.snap() ?? 0);
|
|
1681
|
+
dragProps?.move?.(event);
|
|
1682
|
+
const currentParentLocalPointer = parent.toLocal(event.global);
|
|
1683
|
+
const newX = currentParentLocalPointer.x - this.offsetInParent.x;
|
|
1684
|
+
const newY = currentParentLocalPointer.y - this.offsetInParent.y;
|
|
1685
|
+
if (dragProps?.snap()) {
|
|
1686
|
+
instance.position.x = snapTo(newX);
|
|
1687
|
+
instance.position.y = snapTo(newY);
|
|
1688
|
+
} else {
|
|
1689
|
+
if (this.axis.x) instance.position.x = newX;
|
|
1690
|
+
if (this.axis.y) instance.position.y = newY;
|
|
1691
|
+
}
|
|
1692
|
+
this.lastPointerPosition.copyFrom(event.global);
|
|
1693
|
+
const { x: xProp, y: yProp } = propObservables;
|
|
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);
|
|
1705
|
+
}
|
|
1706
|
+
/**
|
|
1707
|
+
* Moves the viewport if the dragged element is near screen edges
|
|
1708
|
+
* @param globalPosition The global pointer position
|
|
1709
|
+
*/
|
|
1710
|
+
updateViewportPosition(globalPosition) {
|
|
1711
|
+
if (!this.viewport || !this.elementRef) return;
|
|
1712
|
+
const dragProps = this.dragProps;
|
|
1713
|
+
const edgeThreshold = dragProps?.viewport?.edgeThreshold();
|
|
1714
|
+
const maxSpeed = dragProps?.viewport?.maxSpeed();
|
|
1715
|
+
const screenLeft = 0;
|
|
1716
|
+
const screenRight = this.viewport.screenWidth;
|
|
1717
|
+
const screenTop = 0;
|
|
1718
|
+
const screenBottom = this.viewport.screenHeight;
|
|
1719
|
+
const instance = this.elementRef.componentInstance;
|
|
1720
|
+
const distanceFromLeft = globalPosition.x - screenLeft;
|
|
1721
|
+
const distanceFromRight = screenRight - globalPosition.x;
|
|
1722
|
+
const distanceFromTop = globalPosition.y - screenTop;
|
|
1723
|
+
const distanceFromBottom = screenBottom - globalPosition.y;
|
|
1724
|
+
let moveX = 0;
|
|
1725
|
+
let moveY = 0;
|
|
1726
|
+
if (distanceFromLeft < edgeThreshold) {
|
|
1727
|
+
const velocity = maxSpeed * (1 - distanceFromLeft / edgeThreshold);
|
|
1728
|
+
moveX = -velocity;
|
|
1729
|
+
} else if (distanceFromRight < edgeThreshold) {
|
|
1730
|
+
const velocity = maxSpeed * (1 - distanceFromRight / edgeThreshold);
|
|
1731
|
+
moveX = velocity;
|
|
1732
|
+
}
|
|
1733
|
+
if (distanceFromTop < edgeThreshold) {
|
|
1734
|
+
const velocity = maxSpeed * (1 - distanceFromTop / edgeThreshold);
|
|
1735
|
+
moveY = -velocity;
|
|
1736
|
+
} else if (distanceFromBottom < edgeThreshold) {
|
|
1737
|
+
const velocity = maxSpeed * (1 - distanceFromBottom / edgeThreshold);
|
|
1738
|
+
moveY = velocity;
|
|
1739
|
+
}
|
|
1740
|
+
if (moveX !== 0 || moveY !== 0) {
|
|
1741
|
+
const lastViewValue = this.viewport.center;
|
|
1742
|
+
this.viewport.moveCenter(
|
|
1743
|
+
this.viewport.center.x + moveX,
|
|
1744
|
+
this.viewport.center.y + moveY
|
|
1745
|
+
);
|
|
1746
|
+
if (this.axis.x && lastViewValue.x !== this.viewport.center.x) {
|
|
1747
|
+
instance.position.x += moveX;
|
|
1748
|
+
}
|
|
1749
|
+
if (this.axis.y && lastViewValue.y !== this.viewport.center.y) {
|
|
1750
|
+
instance.position.y += moveY;
|
|
1751
|
+
}
|
|
1752
|
+
}
|
|
1753
|
+
}
|
|
1754
|
+
/**
|
|
1755
|
+
* Handles drag end event and stops viewport movement
|
|
1756
|
+
*/
|
|
1757
|
+
onDragEnd() {
|
|
1758
|
+
if (!this.isDragging || !this.elementRef) return;
|
|
1759
|
+
const dragProps = this.dragProps;
|
|
1760
|
+
this.isDragging = false;
|
|
1761
|
+
dragProps?.end?.();
|
|
1762
|
+
if (this.stageRef) {
|
|
1763
|
+
this.stageRef.off("pointermove", this.onDragMoveHandler);
|
|
1764
|
+
}
|
|
1765
|
+
}
|
|
1766
|
+
onPointerDown(event) {
|
|
1767
|
+
if (!this.elementRef?.componentInstance || !this.stageRef || !this.elementRef.componentInstance.parent) return;
|
|
1768
|
+
const instance = this.elementRef.componentInstance;
|
|
1769
|
+
const parent = instance.parent;
|
|
1770
|
+
const dragProps = this.dragProps;
|
|
1771
|
+
const parentLocalPointer = parent.toLocal(event.global);
|
|
1772
|
+
this.offsetInParent.x = parentLocalPointer.x - instance.position.x;
|
|
1773
|
+
this.offsetInParent.y = parentLocalPointer.y - instance.position.y;
|
|
1774
|
+
this.isDragging = true;
|
|
1775
|
+
this.lastPointerPosition.copyFrom(event.global);
|
|
1776
|
+
dragProps?.start?.();
|
|
1777
|
+
this.stageRef.on("pointermove", this.onDragMoveHandler);
|
|
1778
|
+
}
|
|
1779
|
+
onUpdate(props) {
|
|
1780
|
+
if (props.type && props.type === "reset") {
|
|
1781
|
+
this.onDestroy();
|
|
1782
|
+
this.onMount(this.elementRef);
|
|
1783
|
+
}
|
|
1784
|
+
}
|
|
1785
|
+
onDestroy() {
|
|
1786
|
+
this.subscriptions.forEach((subscription) => subscription.unsubscribe());
|
|
1787
|
+
const instance = this.elementRef?.componentInstance;
|
|
1788
|
+
if (instance) {
|
|
1789
|
+
instance.off("pointerdown", this.onDragStartHandler);
|
|
1790
|
+
}
|
|
1791
|
+
if (this.stageRef) {
|
|
1792
|
+
this.stageRef.off("pointermove", this.onDragMoveHandler);
|
|
1793
|
+
this.stageRef.off("pointerup", this.onDragEndHandler);
|
|
1794
|
+
this.stageRef.off("pointerupoutside", this.onDragEndHandler);
|
|
1795
|
+
}
|
|
1796
|
+
this.stageRef = null;
|
|
1797
|
+
this.viewport = null;
|
|
1798
|
+
}
|
|
1799
|
+
};
|
|
1800
|
+
registerDirective("drag", Drag);
|
|
1801
|
+
registerDirective("drop", Drop);
|
|
1802
|
+
|
|
1803
|
+
// src/directives/Transition.ts
|
|
1804
|
+
import { DisplacementFilter, Sprite, Texture, WRAP_MODES } from "pixi.js";
|
|
1805
|
+
import { animate } from "popmotion";
|
|
1806
|
+
var Transition = class extends Directive {
|
|
1807
|
+
onInit(element) {
|
|
1808
|
+
}
|
|
1809
|
+
onMount(element) {
|
|
1810
|
+
const { image } = element.props.transition;
|
|
1811
|
+
const displacementSprite = new Sprite(Texture.from(image));
|
|
1812
|
+
displacementSprite.texture.baseTexture.wrapMode = WRAP_MODES.REPEAT;
|
|
1813
|
+
const displacementFilter = new DisplacementFilter(displacementSprite);
|
|
1814
|
+
const instance = element.componentInstance;
|
|
1815
|
+
instance.filters = [displacementFilter];
|
|
1816
|
+
instance.addChild(displacementSprite);
|
|
1817
|
+
setTimeout(() => {
|
|
1818
|
+
animate({
|
|
1819
|
+
from: 0,
|
|
1820
|
+
to: 1,
|
|
1821
|
+
duration: 500,
|
|
1822
|
+
onUpdate: (progress) => {
|
|
1823
|
+
displacementFilter.scale.x = progress;
|
|
1824
|
+
displacementFilter.scale.y = progress;
|
|
1825
|
+
}
|
|
1826
|
+
});
|
|
1827
|
+
}, 5e3);
|
|
1828
|
+
}
|
|
1829
|
+
onUpdate(props) {
|
|
1830
|
+
}
|
|
1831
|
+
onDestroy() {
|
|
1832
|
+
}
|
|
1833
|
+
};
|
|
1834
|
+
registerDirective("transition", Transition);
|
|
1835
|
+
|
|
1836
|
+
// src/index.ts
|
|
1837
|
+
export * from "@signe/reactive";
|
|
1838
|
+
import { Howler } from "howler";
|
|
1839
|
+
|
|
1840
|
+
// src/components/Canvas.ts
|
|
1841
|
+
import { effect as effect4, signal as signal5 } from "@signe/reactive";
|
|
1842
|
+
import { Container as Container3, autoDetectRenderer } from "pixi.js";
|
|
1843
|
+
import { loadYoga } from "yoga-layout";
|
|
1844
|
+
|
|
1574
1845
|
// src/components/DisplayObject.ts
|
|
1575
|
-
import { effect as effect3, signal as
|
|
1846
|
+
import { effect as effect3, signal as signal4 } from "@signe/reactive";
|
|
1576
1847
|
import { DropShadowFilter } from "pixi-filters";
|
|
1577
1848
|
import { BlurFilter, ObservablePoint } from "pixi.js";
|
|
1578
1849
|
var EVENTS2 = [
|
|
@@ -1662,8 +1933,8 @@ function DisplayObject(extendClass) {
|
|
|
1662
1933
|
0
|
|
1663
1934
|
);
|
|
1664
1935
|
this.isCustomAnchor = false;
|
|
1665
|
-
this.displayWidth =
|
|
1666
|
-
this.displayHeight =
|
|
1936
|
+
this.displayWidth = signal4(0);
|
|
1937
|
+
this.displayHeight = signal4(0);
|
|
1667
1938
|
this.overrideProps = [];
|
|
1668
1939
|
}
|
|
1669
1940
|
get yoga() {
|
|
@@ -1959,14 +2230,14 @@ registerComponent("Canvas", class Canvas extends DisplayObject(Container3) {
|
|
|
1959
2230
|
var Canvas2 = async (props = {}) => {
|
|
1960
2231
|
let { cursorStyles, width, height, class: className } = useProps(props);
|
|
1961
2232
|
const Yoga = await loadYoga();
|
|
1962
|
-
if (!props.width) width =
|
|
1963
|
-
if (!props.height) height =
|
|
2233
|
+
if (!props.width) width = signal5(800);
|
|
2234
|
+
if (!props.height) height = signal5(600);
|
|
1964
2235
|
const renderer = await autoDetectRenderer({
|
|
1965
2236
|
...props,
|
|
1966
2237
|
width: width?.(),
|
|
1967
2238
|
height: height?.()
|
|
1968
2239
|
});
|
|
1969
|
-
const canvasSize =
|
|
2240
|
+
const canvasSize = signal5({
|
|
1970
2241
|
width: renderer.width,
|
|
1971
2242
|
height: renderer.height
|
|
1972
2243
|
});
|
|
@@ -1982,7 +2253,7 @@ var Canvas2 = async (props = {}) => {
|
|
|
1982
2253
|
height: height?.()
|
|
1983
2254
|
};
|
|
1984
2255
|
if (!props.tick) {
|
|
1985
|
-
options.context.tick = options.tick =
|
|
2256
|
+
options.context.tick = options.tick = signal5({
|
|
1986
2257
|
timestamp: 0,
|
|
1987
2258
|
deltaTime: 0,
|
|
1988
2259
|
frame: 0,
|
|
@@ -2079,12 +2350,16 @@ var CanvasGraphics = class extends DisplayObject(PixiGraphics) {
|
|
|
2079
2350
|
onInit(props) {
|
|
2080
2351
|
super.onInit(props);
|
|
2081
2352
|
if (props.draw) {
|
|
2082
|
-
effect5(() => {
|
|
2353
|
+
this.clearEffect = effect5(() => {
|
|
2083
2354
|
this.clear();
|
|
2084
2355
|
props.draw?.(this);
|
|
2085
2356
|
});
|
|
2086
2357
|
}
|
|
2087
2358
|
}
|
|
2359
|
+
onDestroy() {
|
|
2360
|
+
this.clearEffect.subscription.unsubscribe();
|
|
2361
|
+
super.onDestroy();
|
|
2362
|
+
}
|
|
2088
2363
|
};
|
|
2089
2364
|
registerComponent("Graphics", CanvasGraphics);
|
|
2090
2365
|
function Graphics(props) {
|
|
@@ -2268,10 +2543,10 @@ import {
|
|
|
2268
2543
|
} from "pixi.js";
|
|
2269
2544
|
|
|
2270
2545
|
// src/engine/animation.ts
|
|
2271
|
-
import { effect as effect6, signal as
|
|
2546
|
+
import { effect as effect6, signal as signal6 } from "@signe/reactive";
|
|
2272
2547
|
import { animate as animatePopmotion } from "popmotion";
|
|
2273
|
-
function isAnimatedSignal(
|
|
2274
|
-
return
|
|
2548
|
+
function isAnimatedSignal(signal9) {
|
|
2549
|
+
return signal9.animatedState !== void 0;
|
|
2275
2550
|
}
|
|
2276
2551
|
function animatedSignal(initialValue, options = {}) {
|
|
2277
2552
|
const state = {
|
|
@@ -2280,8 +2555,8 @@ function animatedSignal(initialValue, options = {}) {
|
|
|
2280
2555
|
end: initialValue
|
|
2281
2556
|
};
|
|
2282
2557
|
let animation;
|
|
2283
|
-
const publicSignal =
|
|
2284
|
-
const privateSignal =
|
|
2558
|
+
const publicSignal = signal6(initialValue);
|
|
2559
|
+
const privateSignal = signal6(state);
|
|
2285
2560
|
effect6(() => {
|
|
2286
2561
|
const currentState = privateSignal();
|
|
2287
2562
|
publicSignal.set(currentState.current);
|
|
@@ -2663,7 +2938,7 @@ var Sprite2 = (props) => {
|
|
|
2663
2938
|
};
|
|
2664
2939
|
|
|
2665
2940
|
// src/components/Video.ts
|
|
2666
|
-
import { effect as effect8, signal as
|
|
2941
|
+
import { effect as effect8, signal as signal7 } from "@signe/reactive";
|
|
2667
2942
|
function Video(props) {
|
|
2668
2943
|
const eventsMap = {
|
|
2669
2944
|
audioprocess: null,
|
|
@@ -2688,7 +2963,7 @@ function Video(props) {
|
|
|
2688
2963
|
volumechange: null,
|
|
2689
2964
|
waiting: null
|
|
2690
2965
|
};
|
|
2691
|
-
const video =
|
|
2966
|
+
const video = signal7(null);
|
|
2692
2967
|
const defineProps = useDefineProps(props);
|
|
2693
2968
|
const { play, loop: loop2, muted } = defineProps({
|
|
2694
2969
|
play: {
|
|
@@ -2758,12 +3033,12 @@ function Video(props) {
|
|
|
2758
3033
|
import { Text as PixiText } from "pixi.js";
|
|
2759
3034
|
|
|
2760
3035
|
// src/engine/trigger.ts
|
|
2761
|
-
import { effect as effect9, signal as
|
|
3036
|
+
import { effect as effect9, signal as signal8 } from "@signe/reactive";
|
|
2762
3037
|
function isTrigger(arg) {
|
|
2763
3038
|
return arg?.start && arg?.listen;
|
|
2764
3039
|
}
|
|
2765
3040
|
function trigger(globalConfig) {
|
|
2766
|
-
const _signal =
|
|
3041
|
+
const _signal = signal8({
|
|
2767
3042
|
config: globalConfig,
|
|
2768
3043
|
value: 0,
|
|
2769
3044
|
resolve: (value) => void 0
|
|
@@ -2981,10 +3256,7 @@ var CanvasViewport = class extends DisplayObject(PixiViewport) {
|
|
|
2981
3256
|
onInit(props) {
|
|
2982
3257
|
super.onInit(props);
|
|
2983
3258
|
for (let event of EVENTS3) {
|
|
2984
|
-
|
|
2985
|
-
if (props[camelCaseEvent]) {
|
|
2986
|
-
this.on(event, props[camelCaseEvent]);
|
|
2987
|
-
}
|
|
3259
|
+
if (props[event]) this.on(event, props[event]);
|
|
2988
3260
|
}
|
|
2989
3261
|
}
|
|
2990
3262
|
onMount(element) {
|
|
@@ -3023,6 +3295,9 @@ var CanvasViewport = class extends DisplayObject(PixiViewport) {
|
|
|
3023
3295
|
if (props.worldHeight !== void 0) {
|
|
3024
3296
|
this.worldHeight = props.worldHeight;
|
|
3025
3297
|
}
|
|
3298
|
+
if (props.drag) {
|
|
3299
|
+
this.drag(props.drag);
|
|
3300
|
+
}
|
|
3026
3301
|
if (props.clamp) {
|
|
3027
3302
|
this.clamp(props.clamp.value ?? props.clamp);
|
|
3028
3303
|
}
|