canvasengine 2.0.0-beta.23 → 2.0.0-beta.24

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
@@ -1,4259 +1,2 @@
1
- var __defProp = Object.defineProperty;
2
- var __typeError = (msg) => {
3
- throw TypeError(msg);
4
- };
5
- var __export = (target, all) => {
6
- for (var name in all)
7
- __defProp(target, name, { get: all[name], enumerable: true });
8
- };
9
- var __accessCheck = (obj, member, msg) => member.has(obj) || __typeError("Cannot " + msg);
10
- var __privateGet = (obj, member, getter) => (__accessCheck(obj, member, "read from private field"), getter ? getter.call(obj) : member.get(obj));
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
- var __privateSet = (obj, member, value, setter) => (__accessCheck(obj, member, "write to private field"), setter ? setter.call(obj, value) : member.set(obj, value), value);
13
-
14
- // src/engine/directive.ts
15
- var directives = {};
16
- var Directive = class {
17
- };
18
- function registerDirective(name, directive) {
19
- directives[name] = directive;
20
- }
21
- function applyDirective(element, directiveName) {
22
- if (!directives[directiveName]) {
23
- return null;
24
- }
25
- const directive = new directives[directiveName]();
26
- directive.onInit?.(element);
27
- return directive;
28
- }
29
-
30
- // src/engine/utils.ts
31
- var utils_exports = {};
32
- __export(utils_exports, {
33
- arrayEquals: () => arrayEquals,
34
- calculateDistance: () => calculateDistance,
35
- error: () => error,
36
- fps2ms: () => fps2ms,
37
- get: () => get,
38
- isBrowser: () => isBrowser,
39
- isFunction: () => isFunction,
40
- isObject: () => isObject,
41
- isObservable: () => isObservable,
42
- isPromise: () => isPromise,
43
- log: () => log,
44
- preciseNow: () => preciseNow,
45
- set: () => set,
46
- setObservablePoint: () => setObservablePoint
47
- });
48
- import { Observable } from "rxjs";
49
- function isBrowser() {
50
- return typeof window !== "undefined";
51
- }
52
- function preciseNow() {
53
- return typeof performance !== "undefined" ? performance.now() : Date.now();
54
- }
55
- function fps2ms(fps) {
56
- return 1e3 / fps;
57
- }
58
- function isPromise(value) {
59
- return value && value instanceof Promise;
60
- }
61
- function arrayEquals(a, b) {
62
- if (a.length !== b.length) return false;
63
- for (let i = 0; i < a.length; i++) {
64
- const v = a[i];
65
- const bv = b[i];
66
- if (typeof v === "object" && v !== null) {
67
- if (typeof bv !== "object" || bv === null) return false;
68
- if (Array.isArray(v)) {
69
- if (!Array.isArray(bv) || !arrayEquals(v, bv)) return false;
70
- } else if (!objectEquals(v, bv)) {
71
- return false;
72
- }
73
- } else if (v !== bv) {
74
- return false;
75
- }
76
- }
77
- return true;
78
- }
79
- function objectEquals(a, b) {
80
- const keysA = Object.keys(a);
81
- const keysB = Object.keys(b);
82
- if (keysA.length !== keysB.length) return false;
83
- for (let key of keysA) {
84
- if (!b.hasOwnProperty(key)) return false;
85
- if (!deepEquals(a[key], b[key])) return false;
86
- }
87
- return true;
88
- }
89
- function deepEquals(a, b) {
90
- if (a === b) return true;
91
- if (typeof a !== typeof b) return false;
92
- if (typeof a === "object" && a !== null) {
93
- if (Array.isArray(a)) {
94
- return Array.isArray(b) && arrayEquals(a, b);
95
- }
96
- return objectEquals(a, b);
97
- }
98
- return false;
99
- }
100
- function isFunction(val) {
101
- return {}.toString.call(val) === "[object Function]";
102
- }
103
- function isObject(val) {
104
- return typeof val == "object" && val != null && !Array.isArray(val) && val.constructor === Object;
105
- }
106
- function isObservable(val) {
107
- return val instanceof Observable;
108
- }
109
- function set(obj, path, value, onlyPlainObject = false) {
110
- if (Object(obj) !== obj) return obj;
111
- if (typeof path === "string") {
112
- path = path.split(".");
113
- }
114
- let len = path.length;
115
- if (!len) return obj;
116
- let current = obj;
117
- for (let i = 0; i < len - 1; i++) {
118
- let segment = path[i];
119
- let nextSegment = path[i + 1];
120
- let isNextNumeric = !isNaN(Number(nextSegment)) && isFinite(Number(nextSegment));
121
- if (!current[segment] || typeof current[segment] !== "object") {
122
- current[segment] = isNextNumeric && !onlyPlainObject ? [] : {};
123
- }
124
- current = current[segment];
125
- }
126
- current[path[len - 1]] = value;
127
- return obj;
128
- }
129
- function get(obj, path) {
130
- const keys = path.split(".");
131
- let current = obj;
132
- for (let key of keys) {
133
- if (current[key] === void 0) {
134
- return void 0;
135
- }
136
- current = current[key];
137
- }
138
- return current;
139
- }
140
- function log(text) {
141
- console.log(text);
142
- }
143
- function error(text) {
144
- console.error(text);
145
- }
146
- function setObservablePoint(observablePoint, point) {
147
- if (typeof point === "number") {
148
- observablePoint.set(point);
149
- } else if (Array.isArray(point)) {
150
- observablePoint.set(point[0], point[1]);
151
- } else {
152
- observablePoint.set(point.x, point.y);
153
- }
154
- }
155
- function calculateDistance(x1, y1, x2, y2) {
156
- const dx = x1 - x2;
157
- const dy = y1 - y2;
158
- return Math.sqrt(dx * dx + dy * dy);
159
- }
160
-
161
- // src/directives/KeyboardControls.ts
162
- var keyCodeTable = {
163
- 3: "break",
164
- 8: "backspace",
165
- // backspace / delete
166
- 9: "tab",
167
- 12: "clear",
168
- 13: "enter",
169
- 16: "shift",
170
- 17: "ctrl",
171
- 18: "alt",
172
- 19: "pause/break",
173
- 20: "caps lock",
174
- 27: "escape",
175
- 28: "conversion",
176
- 29: "non-conversion",
177
- 32: "space",
178
- 33: "page up",
179
- 34: "page down",
180
- 35: "end",
181
- 36: "home",
182
- 37: "left",
183
- 38: "up",
184
- 39: "right",
185
- 40: "down",
186
- 41: "select",
187
- 42: "print",
188
- 43: "execute",
189
- 44: "Print Screen",
190
- 45: "insert",
191
- 46: "delete",
192
- 48: "n0",
193
- 49: "n1",
194
- 50: "n2",
195
- 51: "n3",
196
- 52: "n4",
197
- 53: "n5",
198
- 54: "n6",
199
- 55: "n7",
200
- 56: "n8",
201
- 57: "n9",
202
- 58: ":",
203
- 59: "semicolon (firefox), equals",
204
- 60: "<",
205
- 61: "equals (firefox)",
206
- 63: "\xDF",
207
- 64: "@",
208
- 65: "a",
209
- 66: "b",
210
- 67: "c",
211
- 68: "d",
212
- 69: "e",
213
- 70: "f",
214
- 71: "g",
215
- 72: "h",
216
- 73: "i",
217
- 74: "j",
218
- 75: "k",
219
- 76: "l",
220
- 77: "m",
221
- 78: "n",
222
- 79: "o",
223
- 80: "p",
224
- 81: "q",
225
- 82: "r",
226
- 83: "s",
227
- 84: "t",
228
- 85: "u",
229
- 86: "v",
230
- 87: "w",
231
- 88: "x",
232
- 89: "y",
233
- 90: "z",
234
- 91: "Windows Key / Left \u2318 / Chromebook Search key",
235
- 92: "right window key",
236
- 93: "Windows Menu / Right \u2318",
237
- 96: "numpad 0",
238
- 97: "numpad 1",
239
- 98: "numpad 2",
240
- 99: "numpad 3",
241
- 100: "numpad 4",
242
- 101: "numpad 5",
243
- 102: "numpad 6",
244
- 103: "numpad 7",
245
- 104: "numpad 8",
246
- 105: "numpad 9",
247
- 106: "multiply",
248
- 107: "add",
249
- 108: "numpad period (firefox)",
250
- 109: "subtract",
251
- 110: "decimal point",
252
- 111: "divide",
253
- 112: "f1",
254
- 113: "f2",
255
- 114: "f3",
256
- 115: "f4",
257
- 116: "f5",
258
- 117: "f6",
259
- 118: "f7",
260
- 119: "f8",
261
- 120: "f9",
262
- 121: "f10",
263
- 122: "f11",
264
- 123: "f12",
265
- 124: "f13",
266
- 125: "f14",
267
- 126: "f15",
268
- 127: "f16",
269
- 128: "f17",
270
- 129: "f18",
271
- 130: "f19",
272
- 131: "f20",
273
- 132: "f21",
274
- 133: "f22",
275
- 134: "f23",
276
- 135: "f24",
277
- 144: "num lock",
278
- 145: "scroll lock",
279
- 160: "^",
280
- 161: "!",
281
- 163: "#",
282
- 164: "$",
283
- 165: "\xF9",
284
- 166: "page backward",
285
- 167: "page forward",
286
- 169: "closing paren (AZERTY)",
287
- 170: "*",
288
- 171: "~ + * key",
289
- 173: "minus (firefox), mute/unmute",
290
- 174: "decrease volume level",
291
- 175: "increase volume level",
292
- 176: "next",
293
- 177: "previous",
294
- 178: "stop",
295
- 179: "play/pause",
296
- 180: "e-mail",
297
- 181: "mute/unmute (firefox)",
298
- 182: "decrease volume level (firefox)",
299
- 183: "increase volume level (firefox)",
300
- 186: "semi-colon / \xF1",
301
- 187: "equal sign",
302
- 188: "comma",
303
- 189: "dash",
304
- 190: "period",
305
- 191: "forward slash / \xE7",
306
- 192: "grave accent / \xF1 / \xE6",
307
- 193: "?, / or \xB0",
308
- 194: "numpad period (chrome)",
309
- 219: "open bracket",
310
- 220: "back slash",
311
- 221: "close bracket / \xE5",
312
- 222: "single quote / \xF8",
313
- 223: "`",
314
- 224: "left or right \u2318 key (firefox)",
315
- 225: "altgr",
316
- 226: "< /git >",
317
- 230: "GNOME Compose Key",
318
- 231: "\xE7",
319
- 233: "XF86Forward",
320
- 234: "XF86Back",
321
- 240: "alphanumeric",
322
- 242: "hiragana/katakana",
323
- 243: "half-width/full-width",
324
- 244: "kanji",
325
- 255: "toggle touchpad"
326
- };
327
- var inverse = (obj) => {
328
- const newObj = {};
329
- for (let key in obj) {
330
- const val = obj[key];
331
- newObj[val] = key;
332
- }
333
- return newObj;
334
- };
335
- var inverseKeyCodeTable = inverse(keyCodeTable);
336
- var KeyboardControls = class extends Directive {
337
- constructor() {
338
- super(...arguments);
339
- this.keyState = {};
340
- this.boundKeys = {};
341
- this.stop = false;
342
- this.lastKeyPressed = null;
343
- this._controlsOptions = {};
344
- // TODO: This should be dynamic
345
- this.serverFps = 60;
346
- this.directionState = {
347
- up: false,
348
- down: false,
349
- left: false,
350
- right: false
351
- };
352
- }
353
- onInit(element) {
354
- const value = element.props.controls.value ?? element.props.controls;
355
- if (!value) return;
356
- this.setupListeners();
357
- this.setInputs(value);
358
- this.interval = setInterval(() => {
359
- this.preStep();
360
- }, fps2ms(this.serverFps ?? 60));
361
- }
362
- onMount(element) {
363
- }
364
- onUpdate(props) {
365
- this.setInputs(props);
366
- }
367
- onDestroy() {
368
- clearInterval(this.interval);
369
- document.removeEventListener("keydown", (e) => {
370
- this.onKeyChange(e, true);
371
- });
372
- document.removeEventListener("keyup", (e) => {
373
- this.onKeyChange(e, false);
374
- });
375
- }
376
- /** @internal */
377
- preStep() {
378
- if (this.stop) return;
379
- const direction = this.getDirection();
380
- if (direction !== "none") {
381
- const directionControl = this.boundKeys[direction];
382
- if (directionControl) {
383
- const { keyDown } = directionControl.options;
384
- if (keyDown) {
385
- this.applyInput(direction);
386
- }
387
- }
388
- } else {
389
- const boundKeys = Object.keys(this.boundKeys);
390
- for (let keyName of boundKeys) {
391
- this.applyInput(keyName);
392
- }
393
- }
394
- }
395
- applyInput(keyName) {
396
- const keyState = this.keyState[keyName];
397
- if (!keyState) return;
398
- const { isDown, count } = keyState;
399
- if (isDown) {
400
- const { repeat, keyDown } = this.boundKeys[keyName].options;
401
- if (repeat || count == 0) {
402
- let parameters = this.boundKeys[keyName].parameters;
403
- if (typeof parameters === "function") {
404
- parameters = parameters();
405
- }
406
- if (keyDown) {
407
- keyDown(this.boundKeys[keyName]);
408
- }
409
- this.keyState[keyName].count++;
410
- }
411
- }
412
- }
413
- setupListeners() {
414
- document.addEventListener("keydown", (e) => {
415
- this.onKeyChange(e, true);
416
- });
417
- document.addEventListener("keyup", (e) => {
418
- this.onKeyChange(e, false);
419
- });
420
- }
421
- bindKey(keys, actionName, options, parameters) {
422
- if (!Array.isArray(keys)) keys = [keys];
423
- const keyOptions = Object.assign({
424
- repeat: false
425
- }, options);
426
- keys.forEach((keyName) => {
427
- this.boundKeys[keyName] = { actionName, options: keyOptions, parameters };
428
- });
429
- }
430
- applyKeyDown(name) {
431
- const code = inverseKeyCodeTable[name];
432
- const e = new Event("keydown");
433
- e.keyCode = code;
434
- this.onKeyChange(e, true);
435
- }
436
- applyKeyUp(name) {
437
- const code = inverseKeyCodeTable[name];
438
- const e = new Event("keyup");
439
- e.keyCode = code;
440
- this.onKeyChange(e, false);
441
- }
442
- applyKeyPress(name) {
443
- return new Promise((resolve) => {
444
- this.applyKeyDown(name);
445
- setTimeout(() => {
446
- this.applyKeyUp(name);
447
- resolve();
448
- }, 200);
449
- });
450
- }
451
- onKeyChange(e, isDown) {
452
- e = e || window.event;
453
- const keyName = keyCodeTable[e.keyCode];
454
- if (keyName && this.boundKeys[keyName]) {
455
- if (this.keyState[keyName] == null) {
456
- this.keyState[keyName] = {
457
- count: 0,
458
- isDown: true
459
- };
460
- }
461
- this.keyState[keyName].isDown = isDown;
462
- if (!isDown) {
463
- this.keyState[keyName].count = 0;
464
- const { keyUp } = this.boundKeys[keyName].options;
465
- if (keyUp) {
466
- keyUp(this.boundKeys[keyName]);
467
- }
468
- }
469
- this.lastKeyPressed = isDown ? e.keyCode : null;
470
- }
471
- if (keyName) {
472
- this.updateDirectionState(keyName, isDown);
473
- }
474
- }
475
- updateDirectionState(keyName, isDown) {
476
- switch (keyName) {
477
- case "up":
478
- this.directionState.up = isDown;
479
- break;
480
- case "down":
481
- this.directionState.down = isDown;
482
- break;
483
- case "left":
484
- this.directionState.left = isDown;
485
- break;
486
- case "right":
487
- this.directionState.right = isDown;
488
- break;
489
- }
490
- }
491
- getDirection() {
492
- const { up, down, left, right } = this.directionState;
493
- if (up && left) return "up_left";
494
- if (up && right) return "up_right";
495
- if (down && left) return "down_left";
496
- if (down && right) return "down_right";
497
- if (up) return "up";
498
- if (down) return "down";
499
- if (left) return "left";
500
- if (right) return "right";
501
- return "none";
502
- }
503
- /**
504
- * From the name of the entry, we retrieve the control information
505
- *
506
- * ```ts
507
- * import { Input, inject, KeyboardControls } from '@rpgjs/client'
508
- *
509
- * const controls = inject(KeyboardControls)
510
- * controls.getControl(Input.Enter)
511
-
512
- * if (control) {
513
- * console.log(control.actionName) // action
514
- * }
515
- * ```
516
- * @title Get Control
517
- * @method getControl(inputName)
518
- * @param {string} inputName
519
- * @returns { { actionName: string, options: any } | undefined }
520
- * @memberof KeyboardControls
521
- */
522
- getControl(inputName) {
523
- return this.boundKeys[inputName];
524
- }
525
- /**
526
- * Returns all controls
527
- *
528
- * @method getControls()
529
- * @since 4.2.0
530
- * @returns { { [key: string]: BoundKey } }
531
- * @memberof KeyboardControls
532
- */
533
- getControls() {
534
- return this.boundKeys;
535
- }
536
- /**
537
- * Triggers an input according to the name of the control
538
- *
539
- * ```ts
540
- * import { Control, inject, KeyboardControls } from '@rpgjs/client'
541
- *
542
- * const controls = inject(KeyboardControls)
543
- * controls.applyControl(Control.Action)
544
- * ```
545
- *
546
- * You can put a second parameter or indicate on whether the key is pressed or released
547
- *
548
- * ```ts
549
- * import { Control, inject, KeyboardControls } from '@rpgjs/client'
550
- *
551
- * const controls = inject(KeyboardControls)
552
- * controls.applyControl(Control.Up, true) // keydown
553
- * controls.applyControl(Control.Up, false) // keyup
554
- * ```
555
- * @title Apply Control
556
- * @method applyControl(controlName,isDown)
557
- * @param {string} controlName
558
- * @param {boolean} [isDown]
559
- * @returns {Promise<void>}
560
- * @memberof KeyboardControls
561
- */
562
- async applyControl(controlName, isDown) {
563
- const control = this._controlsOptions[controlName];
564
- if (control) {
565
- const input = Array.isArray(control.bind) ? control.bind[0] : control.bind;
566
- if (isDown === void 0) {
567
- await this.applyKeyPress(input);
568
- } else if (isDown) {
569
- this.applyKeyDown(input);
570
- } else {
571
- this.applyKeyUp(input);
572
- }
573
- }
574
- }
575
- /**
576
- * Stop listening to the inputs. Pressing a key won't do anything
577
- *
578
- * @title Stop Inputs
579
- * @method stopInputs()
580
- * @returns {void}
581
- * @memberof KeyboardControls
582
- */
583
- stopInputs() {
584
- this.stop = true;
585
- }
586
- /**
587
- * Listen to the inputs again
588
- *
589
- * @title Listen Inputs
590
- * @method listenInputs()
591
- * @returns {void}
592
- * @memberof KeyboardControls
593
- */
594
- listenInputs() {
595
- this.stop = false;
596
- this.keyState = {};
597
- }
598
- /**
599
- * Assign custom inputs to the scene
600
- *
601
- * The object is the following:
602
- *
603
- * * the key of the object is the name of the control. Either it is existing controls (Up, Dow, Left, Right, Action, Back) or customized controls
604
- * * The value is an object representing control information:
605
- * * repeat {boolean} The key can be held down to repeat the action. (false by default)
606
- * * bind {string | string[]} To which key is linked the control
607
- * * method {Function} Function to be triggered. If you do not set this property, the name of the control is sent directly to the server.
608
- * * delay {object|number} (since v3.2.0) Indicates how long (in milliseconds) the player can press the key again to perform the action
609
- * * delay.duration
610
- * * delay.otherControls {string | string[]} Indicates the other controls that will also have the delay at the same time
611
- *
612
- * ```ts
613
- * import { Control, Input, inject, KeyboardControls } from '@rpgjs/client'
614
- *
615
- * const controls = inject(KeyboardControls)
616
- * controls.setInputs({
617
- [Control.Up]: {
618
- repeat: true,
619
- bind: Input.Up
620
- },
621
- [Control.Down]: {
622
- repeat: true,
623
- bind: Input.Down
624
- },
625
- [Control.Right]: {
626
- repeat: true,
627
- bind: Input.Right
628
- },
629
- [Control.Left]: {
630
- repeat: true,
631
- bind: Input.Left
632
- },
633
- [Control.Action]: {
634
- bind: [Input.Space, Input.Enter]
635
- },
636
- [Control.Back]: {
637
- bind: Input.Escape
638
- },
639
-
640
- // The myscustom1 control is sent to the server when the A key is pressed.
641
- mycustom1: {
642
- bind: Input.A
643
- },
644
-
645
- // the myAction method is executed when the B key is pressed
646
- mycustom2: {
647
- bind: Input.B,
648
- method({ actionName }) {
649
- console.log('cool', actionName)
650
- }
651
- },
652
-
653
- // The player can redo the action after 400ms
654
- mycustom3: {
655
- bind: Input.C,
656
- delay: 400 // ms
657
- },
658
-
659
- // The player can redo the action (mycustom4) and the directions after 400ms
660
- mycustom4: {
661
- bind: Input.C,
662
- delay: {
663
- duration: 400,
664
- otherControls: [Control.Up, Control.Down, Control.Left, Control.Right]
665
- }
666
- }
667
- })
668
- *
669
- * ```
670
- * @enum {string} Control
671
- *
672
- * Control.Up | up
673
- * Control.Down | down
674
- * Control.Left | left
675
- * Control.Right | right
676
- * Control.Action | action
677
- * Control.Back | back
678
- *
679
- * @enum {string} Mouse Event
680
- *
681
- * click | Click
682
- * dblclick | Double Click
683
- * mousedown | Mouse Down
684
- * mouseup | Mouse Up
685
- * mouseover | Mouse Over
686
- * mousemove | Mouse Move
687
- * mouseout | Mouse Out
688
- * contextmenu | Context Menu
689
- *
690
- *
691
- * @enum {string} Input
692
- *
693
- * break | Pause
694
- * backspace | Backspace / Delete
695
- * tab | Tab
696
- * clear | Clear
697
- * enter | Enter
698
- * shift | Shift
699
- * ctrl | Control
700
- * alt | Alt
701
- * pause/break | Pause / Break
702
- * caps lock | Caps Lock
703
- * escape | Escape
704
- * conversion | Conversion
705
- * non-conversion | Non-conversion
706
- * space | Space
707
- * page up | Page Up
708
- * page down | Page Down
709
- * end | End
710
- * home | Home
711
- * left | Left Arrow
712
- * up | Up Arrow
713
- * right | Right Arrow
714
- * down | Down Arrow
715
- * select | Select
716
- * print | Print
717
- * execute | Execute
718
- * Print Screen | Print Screen
719
- * insert | Insert
720
- * delete | Delete
721
- * n0 | 0
722
- * n1 | 1
723
- * n2 | 2
724
- * n3 | 3
725
- * n4 | 4
726
- * n5 | 5
727
- * n6 | 6
728
- * n7 | 7
729
- * n8 | 8
730
- * n9 | 9
731
- * : | Colon
732
- * semicolon (firefox), equals | Semicolon (Firefox), Equals
733
- * < | Less Than
734
- * equals (firefox) | Equals (Firefox)
735
- * ß | Eszett
736
- * @ | At
737
- * a | A
738
- * b | B
739
- * c | C
740
- * d | D
741
- * e | E
742
- * f | F
743
- * g | G
744
- * h | H
745
- * i | I
746
- * j | J
747
- * k | K
748
- * l | L
749
- * m | M
750
- * n | N
751
- * o | O
752
- * p | P
753
- * q | Q
754
- * r | R
755
- * s | S
756
- * t | T
757
- * u | U
758
- * v | V
759
- * w | W
760
- * x | X
761
- * y | Y
762
- * z | Z
763
- * Windows Key / Left ⌘ / Chromebook Search key | Windows Key / Left Command ⌘ / Chromebook Search Key
764
- * right window key | Right Windows Key
765
- * Windows Menu / Right ⌘ | Windows Menu / Right Command ⌘
766
- * numpad 0 | Numpad 0
767
- * numpad 1 | Numpad 1
768
- * numpad 2 | Numpad 2
769
- * numpad 3 | Numpad 3
770
- * numpad 4 | Numpad 4
771
- * numpad 5 | Numpad 5
772
- * numpad 6 | Numpad 6
773
- * numpad 7 | Numpad 7
774
- * numpad 8 | Numpad 8
775
- * numpad 9 | Numpad 9
776
- * multiply | Multiply
777
- * add | Add
778
- * numpad period (firefox) | Numpad Period (Firefox)
779
- * subtract | Subtract
780
- * decimal point | Decimal Point
781
- * divide | Divide
782
- * f1 | F1
783
- * f2 | F2
784
- * f3 | F3
785
- * f4 | F4
786
- * f5 | F5
787
- * f6 | F6
788
- * f7 | F7
789
- * f8 | F8
790
- * f9 | F9
791
- * f10 | F10
792
- * f11 | F11
793
- * f12 | F12
794
- * f13 | F13
795
- * f14 | F14
796
- * f15 | F15
797
- * f16 | F16
798
- * f17 | F17
799
- * f18 | F18
800
- * f19 | F19
801
- * f20 | F20
802
- * f21 | F21
803
- * f22 | F22
804
- * f23 | F23
805
- * f24 | F24
806
- * num lock | Num Lock
807
- * scroll lock | Scroll Lock
808
- * ^ | Caret
809
- * ! | Exclamation Point
810
- * # | Hash
811
- * $ | Dollar Sign
812
- * ù | Grave Accent U
813
- * page backward | Page Backward
814
- * page forward | Page Forward
815
- * closing paren (AZERTY) | Closing Parenthesis (AZERTY)
816
- * * | Asterisk
817
- * ~ + * key | Tilde + Asterisk Key
818
- * minus (firefox), mute/unmute | Minus (Firefox), Mute/Unmute
819
- * decrease volume level | Decrease Volume Level
820
- * increase volume level | Increase Volume Level
821
- * next | Next
822
- * previous | Previous
823
- * stop | Stop
824
- * play/pause | Play/Pause
825
- * e-mail | Email
826
- * mute/unmute (firefox) | Mute/Unmute (Firefox)
827
- * decrease volume level (firefox) | Decrease Volume Level (Firefox)
828
- * increase volume level (firefox) | Increase Volume Level (Firefox)
829
- * semi-colon / ñ | Semicolon / ñ
830
- * equal sign | Equal Sign
831
- * comma | Comma
832
- * dash | Dash
833
- * period | Period
834
- * forward slash / ç | Forward Slash / ç
835
- * grave accent / ñ / æ | Grave Accent / ñ / æ
836
- * ?, / or ° | ?, / or °
837
- * numpad period (chrome) | Numpad Period (Chrome)
838
- * open bracket | Open Bracket
839
- * back slash | Backslash
840
- * close bracket / å | Close Bracket / å
841
- * single quote / ø | Single Quote / ø
842
- * \` | Backtick
843
- * left or right ⌘ key (firefox) | Left or Right Command Key (Firefox)
844
- * altgr | AltGr
845
- * < /git > | < /git >
846
- * GNOME Compose Key | GNOME Compose Key
847
- * ç | ç
848
- * XF86Forward | XF86Forward
849
- * XF86Back | XF86Back
850
- * alphanumeric | Alphanumeric
851
- * hiragana/katakana | Hiragana/Katakana
852
- * half-width/full-width | Half-Width/Full-Width
853
- * kanji | Kanji
854
- * toggle touchpad | Toggle Touchpad
855
- *
856
- * @title Set Inputs
857
- * @method setInputs(inputs)
858
- * @param {object} inputs
859
- * @memberof KeyboardControls
860
- */
861
- setInputs(inputs) {
862
- if (!inputs) return;
863
- this.boundKeys = {};
864
- let inputsTransformed = {};
865
- for (let control in inputs) {
866
- const option = inputs[control];
867
- const { bind } = option;
868
- let inputsKey = bind;
869
- if (!Array.isArray(inputsKey)) {
870
- inputsKey = [bind];
871
- }
872
- for (let input of inputsKey) {
873
- this.bindKey(input, control, option);
874
- }
875
- }
876
- this._controlsOptions = inputs;
877
- }
878
- get options() {
879
- return this._controlsOptions;
880
- }
881
- };
882
- registerDirective("controls", KeyboardControls);
883
-
884
- // src/directives/Scheduler.ts
885
- var Scheduler = class extends Directive {
886
- constructor() {
887
- super(...arguments);
888
- this.fps = 60;
889
- this.deltaTime = 0;
890
- this.frame = 0;
891
- this.timestamp = 0;
892
- this.requestedDelay = 0;
893
- this.lastTimestamp = 0;
894
- this._stop = false;
895
- }
896
- onInit(element) {
897
- this.tick = element.propObservables?.tick;
898
- }
899
- onDestroy() {
900
- }
901
- onMount(element) {
902
- }
903
- onUpdate(props) {
904
- }
905
- nextTick(timestamp) {
906
- this.lastTimestamp = this.lastTimestamp || this.timestamp;
907
- this.deltaTime = preciseNow() - this.timestamp;
908
- this.timestamp = timestamp;
909
- this.tick.set({
910
- timestamp: this.timestamp,
911
- deltaTime: this.deltaTime,
912
- frame: this.frame,
913
- deltaRatio: ~~this.deltaTime / ~~fps2ms(this.fps)
914
- });
915
- this.lastTimestamp = this.timestamp;
916
- this.frame++;
917
- }
918
- /**
919
- * start the schedule
920
- * @return {Scheduler} returns this scheduler instance
921
- */
922
- start(options = {}) {
923
- if (options.maxFps) this.maxFps = options.maxFps;
924
- if (options.fps) this.fps = options.fps;
925
- if (options.delay) this.requestedDelay = options.delay;
926
- const requestAnimationFrame = (fn) => {
927
- if (isBrowser()) {
928
- window.requestAnimationFrame(fn.bind(this));
929
- } else {
930
- setTimeout(() => {
931
- this.requestedDelay = 0;
932
- fn(preciseNow());
933
- }, fps2ms(this.fps) + this.requestedDelay);
934
- }
935
- };
936
- if (!this.maxFps) {
937
- const loop2 = (timestamp) => {
938
- requestAnimationFrame(loop2);
939
- this.nextTick(timestamp);
940
- };
941
- requestAnimationFrame(loop2);
942
- } else {
943
- const msInterval = fps2ms(this.maxFps);
944
- let now = preciseNow();
945
- let then = preciseNow();
946
- const loop2 = (timestamp) => {
947
- if (this._stop) return;
948
- requestAnimationFrame(loop2);
949
- now = preciseNow();
950
- const elapsed = now - then;
951
- if (elapsed > msInterval) {
952
- then = now - elapsed % msInterval;
953
- this.nextTick(timestamp);
954
- }
955
- };
956
- requestAnimationFrame(loop2);
957
- }
958
- return this;
959
- }
960
- stop() {
961
- this._stop = true;
962
- }
963
- };
964
- registerDirective("tick", Scheduler);
965
-
966
- // src/hooks/useProps.ts
967
- import { isSignal as isSignal2, signal as signal2 } from "@signe/reactive";
968
-
969
- // src/engine/reactive.ts
970
- import { isComputed, isSignal, signal } from "@signe/reactive";
971
- import {
972
- Observable as Observable2,
973
- Subject,
974
- defer,
975
- from,
976
- map,
977
- of,
978
- share
979
- } from "rxjs";
980
- var components = {};
981
- var isElement = (value) => {
982
- return value && typeof value === "object" && "tag" in value && "props" in value && "componentInstance" in value;
983
- };
984
- var isPrimitive = (value) => {
985
- return typeof value === "string" || typeof value === "number" || typeof value === "boolean" || value === null || value === void 0;
986
- };
987
- function registerComponent(name, component) {
988
- components[name] = component;
989
- }
990
- function destroyElement(element) {
991
- if (Array.isArray(element)) {
992
- element.forEach((e) => destroyElement(e));
993
- return;
994
- }
995
- if (!element) {
996
- return;
997
- }
998
- if (element.props?.children) {
999
- for (let child of element.props.children) {
1000
- destroyElement(child);
1001
- }
1002
- }
1003
- for (let name in element.directives) {
1004
- element.directives[name].onDestroy?.(element);
1005
- }
1006
- if (element.componentInstance && element.componentInstance.onDestroy) {
1007
- element.componentInstance.onDestroy(element.parent, () => {
1008
- element.propSubscriptions?.forEach((sub) => sub.unsubscribe());
1009
- element.effectSubscriptions?.forEach((sub) => sub.unsubscribe());
1010
- element.effectUnmounts?.forEach((fn) => fn?.());
1011
- });
1012
- } else {
1013
- element.propSubscriptions?.forEach((sub) => sub.unsubscribe());
1014
- element.effectSubscriptions?.forEach((sub) => sub.unsubscribe());
1015
- element.effectUnmounts?.forEach((fn) => fn?.());
1016
- }
1017
- }
1018
- function createComponent(tag, props) {
1019
- if (!components[tag]) {
1020
- throw new Error(`Component ${tag} is not registered`);
1021
- }
1022
- const instance = new components[tag]();
1023
- const element = {
1024
- tag,
1025
- props: {},
1026
- componentInstance: instance,
1027
- propSubscriptions: [],
1028
- propObservables: props,
1029
- parent: null,
1030
- directives: {},
1031
- effectUnmounts: [],
1032
- effectSubscriptions: [],
1033
- effectMounts: [],
1034
- destroy() {
1035
- destroyElement(this);
1036
- },
1037
- allElements: new Subject()
1038
- };
1039
- if (props) {
1040
- const recursiveProps = (props2, path = "") => {
1041
- const _set = (path2, key, value) => {
1042
- if (path2 == "") {
1043
- element.props[key] = value;
1044
- return;
1045
- }
1046
- set(element.props, path2 + "." + key, value);
1047
- };
1048
- Object.entries(props2).forEach(([key, value]) => {
1049
- if (isSignal(value)) {
1050
- const _value = value;
1051
- if ("dependencies" in _value && _value.dependencies.size == 0) {
1052
- _set(path, key, _value());
1053
- return;
1054
- }
1055
- element.propSubscriptions.push(
1056
- _value.observable.subscribe((value2) => {
1057
- _set(path, key, value2);
1058
- if (element.directives[key]) {
1059
- element.directives[key].onUpdate?.(value2, element);
1060
- }
1061
- if (key == "tick") {
1062
- return;
1063
- }
1064
- instance.onUpdate?.(
1065
- path == "" ? {
1066
- [key]: value2
1067
- } : set({}, path + "." + key, value2)
1068
- );
1069
- })
1070
- );
1071
- } else {
1072
- if (isObject(value) && key != "context" && !isElement(value)) {
1073
- recursiveProps(value, (path ? path + "." : "") + key);
1074
- } else {
1075
- _set(path, key, value);
1076
- }
1077
- }
1078
- });
1079
- };
1080
- recursiveProps(props);
1081
- }
1082
- instance.onInit?.(element.props);
1083
- const elementsListen = new Subject();
1084
- if (props?.isRoot) {
1085
- element.allElements = elementsListen;
1086
- element.props.context.rootElement = element;
1087
- element.componentInstance.onMount?.(element);
1088
- propagateContext(element);
1089
- }
1090
- if (props) {
1091
- for (let key in props) {
1092
- const directive = applyDirective(element, key);
1093
- if (directive) element.directives[key] = directive;
1094
- }
1095
- }
1096
- function onMount(parent, element2, index) {
1097
- element2.props.context = parent.props.context;
1098
- element2.parent = parent;
1099
- element2.componentInstance.onMount?.(element2, index);
1100
- for (let name in element2.directives) {
1101
- element2.directives[name].onMount?.(element2);
1102
- }
1103
- element2.effectMounts.forEach((fn) => {
1104
- element2.effectUnmounts.push(fn(element2));
1105
- });
1106
- }
1107
- ;
1108
- async function propagateContext(element2) {
1109
- if (element2.props.attach) {
1110
- const isReactiveAttach = isSignal(element2.propObservables?.attach);
1111
- if (!isReactiveAttach) {
1112
- element2.props.children.push(element2.props.attach);
1113
- } else {
1114
- await new Promise((resolve) => {
1115
- let lastElement = null;
1116
- element2.propSubscriptions.push(element2.propObservables.attach.observable.subscribe(async (args) => {
1117
- const value = args?.value ?? args;
1118
- if (!value) {
1119
- throw new Error(`attach in ${element2.tag} is undefined or null, add a component`);
1120
- }
1121
- if (lastElement) {
1122
- destroyElement(lastElement);
1123
- }
1124
- lastElement = value;
1125
- await createElement(element2, value);
1126
- resolve(void 0);
1127
- }));
1128
- });
1129
- }
1130
- }
1131
- if (!element2.props.children) {
1132
- return;
1133
- }
1134
- for (let child of element2.props.children) {
1135
- if (!child) continue;
1136
- await createElement(element2, child);
1137
- }
1138
- }
1139
- ;
1140
- async function createElement(parent, child) {
1141
- if (isPromise(child)) {
1142
- child = await child;
1143
- }
1144
- if (child instanceof Observable2) {
1145
- child.subscribe(
1146
- ({
1147
- elements: comp,
1148
- prev
1149
- }) => {
1150
- const components2 = comp.filter((c) => c !== null);
1151
- if (prev) {
1152
- components2.forEach((c) => {
1153
- const index = parent.props.children.indexOf(prev.props.key);
1154
- onMount(parent, c, index + 1);
1155
- propagateContext(c);
1156
- });
1157
- return;
1158
- }
1159
- components2.forEach((component) => {
1160
- if (!Array.isArray(component)) {
1161
- onMount(parent, component);
1162
- propagateContext(component);
1163
- } else {
1164
- component.forEach((comp2) => {
1165
- onMount(parent, comp2);
1166
- propagateContext(comp2);
1167
- });
1168
- }
1169
- });
1170
- elementsListen.next(void 0);
1171
- }
1172
- );
1173
- } else {
1174
- onMount(parent, child);
1175
- await propagateContext(child);
1176
- }
1177
- }
1178
- return element;
1179
- }
1180
- function loop(itemsSubject, createElementFn) {
1181
- if (isComputed(itemsSubject) && itemsSubject.dependencies.size == 0) {
1182
- itemsSubject = signal(itemsSubject());
1183
- } else if (!isSignal(itemsSubject)) {
1184
- itemsSubject = signal(itemsSubject);
1185
- }
1186
- return defer(() => {
1187
- let elements = [];
1188
- let elementMap = /* @__PURE__ */ new Map();
1189
- let isFirstSubscription = true;
1190
- const isArraySignal = (signal10) => Array.isArray(signal10());
1191
- return new Observable2((subscriber) => {
1192
- const subscription = isArraySignal(itemsSubject) ? itemsSubject.observable.subscribe((change) => {
1193
- if (isFirstSubscription) {
1194
- isFirstSubscription = false;
1195
- elements.forEach((el) => el.destroy());
1196
- elements = [];
1197
- elementMap.clear();
1198
- const items = itemsSubject();
1199
- if (items) {
1200
- items.forEach((item, index) => {
1201
- const element = createElementFn(item, index);
1202
- if (element) {
1203
- elements.push(element);
1204
- elementMap.set(index, element);
1205
- }
1206
- });
1207
- }
1208
- subscriber.next({
1209
- elements: [...elements]
1210
- });
1211
- return;
1212
- }
1213
- if (change.type === "init" || change.type === "reset") {
1214
- elements.forEach((el) => el.destroy());
1215
- elements = [];
1216
- elementMap.clear();
1217
- const items = itemsSubject();
1218
- if (items) {
1219
- items.forEach((item, index) => {
1220
- const element = createElementFn(item, index);
1221
- if (element) {
1222
- elements.push(element);
1223
- elementMap.set(index, element);
1224
- }
1225
- });
1226
- }
1227
- } else if (change.type === "add" && change.index !== void 0) {
1228
- const newElements = change.items.map((item, i) => {
1229
- const element = createElementFn(item, change.index + i);
1230
- if (element) {
1231
- elementMap.set(change.index + i, element);
1232
- }
1233
- return element;
1234
- }).filter((el) => el !== null);
1235
- elements.splice(change.index, 0, ...newElements);
1236
- } else if (change.type === "remove" && change.index !== void 0) {
1237
- const removed = elements.splice(change.index, 1);
1238
- removed.forEach((el) => {
1239
- el.destroy();
1240
- elementMap.delete(change.index);
1241
- });
1242
- } else if (change.type === "update" && change.index !== void 0 && change.items.length === 1) {
1243
- const index = change.index;
1244
- const newItem = change.items[0];
1245
- if (index >= elements.length || elements[index] === void 0 || !elementMap.has(index)) {
1246
- const newElement = createElementFn(newItem, index);
1247
- if (newElement) {
1248
- elements.splice(index, 0, newElement);
1249
- elementMap.set(index, newElement);
1250
- } else {
1251
- console.warn(`Element creation returned null for index ${index} during add-like update.`);
1252
- }
1253
- } else {
1254
- const oldElement = elements[index];
1255
- oldElement.destroy();
1256
- const newElement = createElementFn(newItem, index);
1257
- if (newElement) {
1258
- elements[index] = newElement;
1259
- elementMap.set(index, newElement);
1260
- } else {
1261
- elements.splice(index, 1);
1262
- elementMap.delete(index);
1263
- }
1264
- }
1265
- }
1266
- subscriber.next({
1267
- elements: [...elements]
1268
- // Create a new array to ensure change detection
1269
- });
1270
- }) : itemsSubject.observable.subscribe((change) => {
1271
- const key = change.key;
1272
- if (isFirstSubscription) {
1273
- isFirstSubscription = false;
1274
- elements.forEach((el) => el.destroy());
1275
- elements = [];
1276
- elementMap.clear();
1277
- const items = itemsSubject();
1278
- if (items) {
1279
- Object.entries(items).forEach(([key2, value]) => {
1280
- const element = createElementFn(value, key2);
1281
- if (element) {
1282
- elements.push(element);
1283
- elementMap.set(key2, element);
1284
- }
1285
- });
1286
- }
1287
- subscriber.next({
1288
- elements: [...elements]
1289
- });
1290
- return;
1291
- }
1292
- if (change.type === "init" || change.type === "reset") {
1293
- elements.forEach((el) => el.destroy());
1294
- elements = [];
1295
- elementMap.clear();
1296
- const items = itemsSubject();
1297
- if (items) {
1298
- Object.entries(items).forEach(([key2, value]) => {
1299
- const element = createElementFn(value, key2);
1300
- if (element) {
1301
- elements.push(element);
1302
- elementMap.set(key2, element);
1303
- }
1304
- });
1305
- }
1306
- } else if (change.type === "add" && change.key && change.value !== void 0) {
1307
- const element = createElementFn(change.value, key);
1308
- if (element) {
1309
- elements.push(element);
1310
- elementMap.set(key, element);
1311
- }
1312
- } else if (change.type === "remove" && change.key) {
1313
- const index = elements.findIndex((el) => elementMap.get(key) === el);
1314
- if (index !== -1) {
1315
- const [removed] = elements.splice(index, 1);
1316
- removed.destroy();
1317
- elementMap.delete(key);
1318
- }
1319
- } else if (change.type === "update" && change.key && change.value !== void 0) {
1320
- const index = elements.findIndex((el) => elementMap.get(key) === el);
1321
- if (index !== -1) {
1322
- const oldElement = elements[index];
1323
- oldElement.destroy();
1324
- const newElement = createElementFn(change.value, key);
1325
- if (newElement) {
1326
- elements[index] = newElement;
1327
- elementMap.set(key, newElement);
1328
- }
1329
- }
1330
- }
1331
- subscriber.next({
1332
- elements: [...elements]
1333
- // Create a new array to ensure change detection
1334
- });
1335
- });
1336
- return subscription;
1337
- });
1338
- });
1339
- }
1340
- function cond(condition, createElementFn) {
1341
- let element = null;
1342
- if (isSignal(condition)) {
1343
- const signalCondition = condition;
1344
- return new Observable2((subscriber) => {
1345
- return signalCondition.observable.subscribe((bool) => {
1346
- if (bool) {
1347
- let _el = createElementFn();
1348
- if (isPromise(_el)) {
1349
- from(_el).subscribe((el) => {
1350
- element = el;
1351
- subscriber.next({
1352
- type: "init",
1353
- elements: [el]
1354
- });
1355
- });
1356
- } else {
1357
- element = _el;
1358
- subscriber.next({
1359
- type: "init",
1360
- elements: [element]
1361
- });
1362
- }
1363
- } else if (element) {
1364
- destroyElement(element);
1365
- subscriber.next({
1366
- elements: []
1367
- });
1368
- } else {
1369
- subscriber.next({
1370
- elements: []
1371
- });
1372
- }
1373
- });
1374
- }).pipe(share());
1375
- } else {
1376
- if (condition) {
1377
- let _el = createElementFn();
1378
- if (isPromise(_el)) {
1379
- return from(_el).pipe(
1380
- map((el) => ({
1381
- type: "init",
1382
- elements: [el]
1383
- }))
1384
- );
1385
- }
1386
- return of({
1387
- type: "init",
1388
- elements: [_el]
1389
- });
1390
- }
1391
- return of({
1392
- elements: []
1393
- });
1394
- }
1395
- }
1396
-
1397
- // src/hooks/useProps.ts
1398
- var useProps = (props, defaults = {}) => {
1399
- if (isSignal2(props)) {
1400
- return props();
1401
- }
1402
- const obj = {};
1403
- for (let key in props) {
1404
- const value = props[key];
1405
- obj[key] = isPrimitive(value) ? signal2(value) : value;
1406
- }
1407
- for (let key in defaults) {
1408
- if (!(key in obj)) {
1409
- obj[key] = isPrimitive(defaults[key]) ? signal2(defaults[key]) : defaults[key];
1410
- }
1411
- }
1412
- return obj;
1413
- };
1414
- var useDefineProps = (props) => {
1415
- return (schema) => {
1416
- const rawProps = isSignal2(props) ? props() : props;
1417
- const validatedProps = {};
1418
- for (const key in schema) {
1419
- const propConfig = schema[key];
1420
- const value = rawProps[key];
1421
- let validatedValue;
1422
- if (typeof propConfig === "function") {
1423
- validateType(key, value, [propConfig]);
1424
- validatedValue = value;
1425
- } else if (Array.isArray(propConfig)) {
1426
- validateType(key, value, propConfig);
1427
- validatedValue = value;
1428
- } else if (propConfig && typeof propConfig === "object") {
1429
- if (propConfig.required && value === void 0) {
1430
- throw new Error(`Missing required prop: ${key}`);
1431
- }
1432
- if (propConfig.type) {
1433
- const types = Array.isArray(propConfig.type) ? propConfig.type : [propConfig.type];
1434
- validateType(key, value, types);
1435
- }
1436
- if (propConfig.validator && !propConfig.validator(value, rawProps)) {
1437
- throw new Error(`Invalid prop: custom validation failed for prop "${key}"`);
1438
- }
1439
- if (value === void 0 && "default" in propConfig) {
1440
- validatedValue = typeof propConfig.default === "function" ? propConfig.default(rawProps) : propConfig.default;
1441
- } else {
1442
- validatedValue = value;
1443
- }
1444
- }
1445
- validatedProps[key] = isSignal2(validatedValue) ? validatedValue : signal2(validatedValue);
1446
- }
1447
- return {
1448
- ...useProps(rawProps),
1449
- ...validatedProps
1450
- };
1451
- };
1452
- };
1453
- function validateType(key, value, types) {
1454
- if (value === void 0 || value === null) return;
1455
- const valueToCheck = isSignal2(value) ? value() : value;
1456
- const valid = types.some((type) => {
1457
- if (type === Number) return typeof valueToCheck === "number";
1458
- if (type === String) return typeof valueToCheck === "string";
1459
- if (type === Boolean) return typeof valueToCheck === "boolean";
1460
- if (type === Function) return typeof valueToCheck === "function";
1461
- if (type === Object) return typeof valueToCheck === "object";
1462
- if (type === Array) return Array.isArray(valueToCheck);
1463
- if (type === null) return valueToCheck === null;
1464
- return valueToCheck instanceof type;
1465
- });
1466
- if (!valid) {
1467
- throw new Error(
1468
- `Invalid prop: type check failed for prop "${key}". Expected ${types.map((t) => t.name).join(" or ")}`
1469
- );
1470
- }
1471
- }
1472
-
1473
- // src/directives/ViewportFollow.ts
1474
- var ViewportFollow = class extends Directive {
1475
- onInit(element) {
1476
- }
1477
- onMount(element) {
1478
- this.onUpdate(element.props.viewportFollow, element);
1479
- }
1480
- onUpdate(viewportFollow, element) {
1481
- const { viewport } = element.props.context;
1482
- if (!viewport) {
1483
- throw error("ViewportFollow directive requires a Viewport component to be mounted in the same context");
1484
- }
1485
- if (viewportFollow) {
1486
- if (viewportFollow === true) {
1487
- viewport.follow(element.componentInstance);
1488
- } else {
1489
- const options = useProps(viewportFollow, {
1490
- speed: void 0,
1491
- acceleration: void 0,
1492
- radius: void 0
1493
- });
1494
- viewport.follow(element.componentInstance, {
1495
- speed: options.speed(),
1496
- acceleration: options.acceleration(),
1497
- radius: options.radius()
1498
- });
1499
- }
1500
- } else if (viewportFollow === null) {
1501
- viewport.plugins.remove("follow");
1502
- }
1503
- }
1504
- onDestroy(element) {
1505
- const { viewportFollow } = element.props;
1506
- const { viewport } = element.props.context;
1507
- if (viewportFollow) viewport.plugins.remove("follow");
1508
- }
1509
- };
1510
- registerDirective("viewportFollow", ViewportFollow);
1511
-
1512
- // src/directives/Sound.ts
1513
- import { effect } from "@signe/reactive";
1514
- import { Howl } from "howler";
1515
- var EVENTS = ["load", "loaderror", "playerror", "play", "end", "pause", "stop", "mute", "volume", "rate", "seek", "fade", "unlock"];
1516
- var Sound = class extends Directive {
1517
- constructor() {
1518
- super(...arguments);
1519
- this.sounds = [];
1520
- this.eventsFn = [];
1521
- this.maxVolume = 1;
1522
- this.maxDistance = 100;
1523
- }
1524
- onInit(element) {
1525
- }
1526
- onMount(element) {
1527
- const { props } = element;
1528
- const tick2 = props.context.tick;
1529
- const propsSound = props.sound.value ?? props.sound;
1530
- if (!propsSound.src) {
1531
- return;
1532
- }
1533
- const { src, autoplay, loop: loop2, volume, spatial } = propsSound;
1534
- const sources = Array.isArray(src) ? src : [src];
1535
- for (const source of sources) {
1536
- if (!source) continue;
1537
- const sound = new Howl({
1538
- src: source,
1539
- autoplay,
1540
- loop: loop2,
1541
- volume
1542
- });
1543
- for (let event of EVENTS) {
1544
- if (!propsSound[event]) continue;
1545
- const fn = propsSound[event];
1546
- this.eventsFn.push(fn);
1547
- sound.on(event, fn);
1548
- }
1549
- this.sounds.push(sound);
1550
- }
1551
- if (spatial && this.sounds.length > 0) {
1552
- const { soundListenerPosition } = props.context;
1553
- if (!soundListenerPosition) {
1554
- throw new error("SoundListenerPosition directive is required for spatial sound in component parent");
1555
- }
1556
- const { x: listenerX, y: listenerY } = soundListenerPosition;
1557
- this.tickSubscription = effect(() => {
1558
- tick2();
1559
- const { x, y } = element.componentInstance;
1560
- const distance = calculateDistance(x, y, listenerX(), listenerY());
1561
- const volume2 = Math.max(this.maxVolume - distance / this.maxDistance, 0);
1562
- this.sounds.forEach((sound) => sound.volume(volume2));
1563
- }).subscription;
1564
- }
1565
- this.onUpdate(propsSound);
1566
- }
1567
- onUpdate(props) {
1568
- const soundProps = props.value ?? props;
1569
- const { volume, loop: loop2, mute, seek, playing, rate, spatial } = soundProps;
1570
- this.sounds.forEach((sound) => {
1571
- if (volume !== void 0) sound.volume(volume);
1572
- if (loop2 !== void 0) sound.loop(loop2);
1573
- if (mute !== void 0) sound.mute(mute);
1574
- if (seek !== void 0) sound.seek(seek);
1575
- if (playing !== void 0) {
1576
- if (playing) sound.play();
1577
- else sound.pause();
1578
- }
1579
- if (rate !== void 0) sound.rate(rate);
1580
- });
1581
- if (spatial) {
1582
- this.maxVolume = spatial.maxVolume ?? this.maxVolume;
1583
- this.maxDistance = spatial.maxDistance ?? this.maxDistance;
1584
- }
1585
- }
1586
- onDestroy() {
1587
- this.sounds.forEach((sound) => {
1588
- sound.stop();
1589
- for (let event of EVENTS) {
1590
- const eventFn = this.eventsFn.find((fn) => fn === this.eventsFn[event]);
1591
- if (eventFn) {
1592
- sound.off(event, eventFn);
1593
- }
1594
- }
1595
- });
1596
- this.sounds = [];
1597
- this.eventsFn = [];
1598
- this.tickSubscription?.unsubscribe();
1599
- }
1600
- };
1601
- var SoundListenerPosition = class extends Directive {
1602
- onMount(element) {
1603
- element.props.context.soundListenerPosition = element.propObservables?.soundListenerPosition;
1604
- }
1605
- onInit(element) {
1606
- }
1607
- onUpdate(props) {
1608
- }
1609
- onDestroy() {
1610
- }
1611
- };
1612
- registerDirective("sound", Sound);
1613
- registerDirective("soundListenerPosition", SoundListenerPosition);
1614
-
1615
- // src/directives/Drag.ts
1616
- import { effect as effect2, isComputed as isComputed2, isSignal as isSignal3 } from "@signe/reactive";
1617
- import { Rectangle, Point } from "pixi.js";
1618
- import { snap } from "popmotion";
1619
-
1620
- // src/hooks/addContext.ts
1621
- var addContext = (element, key, value) => {
1622
- element.props.context = {
1623
- ...element.props.context ?? {},
1624
- [key]: value
1625
- };
1626
- };
1627
-
1628
- // src/directives/Drag.ts
1629
- var Drop = class extends Directive {
1630
- constructor() {
1631
- super(...arguments);
1632
- this.elementRef = null;
1633
- }
1634
- onInit(element) {
1635
- this.elementRef = element;
1636
- }
1637
- onMount(element) {
1638
- addContext(element, "drop", element);
1639
- }
1640
- onUpdate() {
1641
- }
1642
- onDestroy() {
1643
- this.elementRef = null;
1644
- }
1645
- };
1646
- var Drag = class extends Directive {
1647
- constructor() {
1648
- super(...arguments);
1649
- this.elementRef = null;
1650
- this.stageRef = null;
1651
- this.offsetInParent = new Point();
1652
- this.isDragging = false;
1653
- this.viewport = null;
1654
- this.animationFrameId = null;
1655
- this.lastPointerPosition = new Point();
1656
- this.pressedKeys = /* @__PURE__ */ new Set();
1657
- this.pointerIsDown = false;
1658
- this.onDragMoveHandler = () => {
1659
- };
1660
- this.onDragEndHandler = () => {
1661
- };
1662
- this.onDragStartHandler = () => {
1663
- };
1664
- this.onKeyDownHandler = () => {
1665
- };
1666
- this.onKeyUpHandler = () => {
1667
- };
1668
- this.subscriptions = [];
1669
- }
1670
- onInit(element) {
1671
- this.elementRef = element;
1672
- this.onDragMoveHandler = this.onDragMove.bind(this);
1673
- this.onDragEndHandler = this.onDragEnd.bind(this);
1674
- this.onDragStartHandler = this.onPointerDown.bind(this);
1675
- this.onKeyDownHandler = this.onKeyDown.bind(this);
1676
- this.onKeyUpHandler = this.onKeyUp.bind(this);
1677
- }
1678
- onMount(element) {
1679
- const { rootElement, canvasSize, viewport, tick: tick2 } = element.props.context;
1680
- const instance = element.componentInstance;
1681
- const dragProps = this.dragProps;
1682
- const haveNotProps = Object.keys(dragProps).length === 0;
1683
- if (haveNotProps) {
1684
- this.onDestroy();
1685
- return;
1686
- }
1687
- if (!instance) return;
1688
- this.stageRef = rootElement.componentInstance;
1689
- if (!this.stageRef) return;
1690
- this.viewport = viewport;
1691
- instance.eventMode = "static";
1692
- this.stageRef.eventMode = "static";
1693
- const _effect = effect2(() => {
1694
- if (this.stageRef) {
1695
- this.stageRef.hitArea = new Rectangle(0, 0, canvasSize().width, canvasSize().height);
1696
- }
1697
- });
1698
- instance.on("pointerdown", this.onDragStartHandler);
1699
- this.stageRef.on("pointerup", this.onDragEndHandler);
1700
- this.stageRef.on("pointerupoutside", this.onDragEndHandler);
1701
- const keysToPress = dragProps.keyToPress ? dragProps.keyToPress : [];
1702
- window.addEventListener("keydown", this.onKeyDownHandler);
1703
- window.addEventListener("keyup", this.onKeyUpHandler);
1704
- this.subscriptions = [
1705
- tick2.observable.subscribe(() => {
1706
- if (this.isDragging && this.viewport) {
1707
- this.updateViewportPosition(this.lastPointerPosition);
1708
- }
1709
- }),
1710
- _effect.subscription
1711
- ];
1712
- }
1713
- get dragProps() {
1714
- const drag = this.elementRef?.props.drag;
1715
- const options = useProps(drag?.value ?? drag, {
1716
- snap: 0,
1717
- viewport: {},
1718
- direction: "all",
1719
- keyToPress: []
1720
- });
1721
- options.viewport = useProps(options.viewport, {
1722
- edgeThreshold: 300,
1723
- maxSpeed: 40
1724
- });
1725
- return options;
1726
- }
1727
- get axis() {
1728
- const direction = this.dragProps.direction();
1729
- const axis = {
1730
- x: true,
1731
- y: true
1732
- };
1733
- if (direction === "x") {
1734
- axis.y = false;
1735
- }
1736
- if (direction === "y") {
1737
- axis.x = false;
1738
- }
1739
- return axis;
1740
- }
1741
- /**
1742
- * Updates element position when dragging and starts continuous viewport movement
1743
- * @param event The pointer event that triggered the drag move
1744
- */
1745
- onDragMove(event) {
1746
- if (!this.isDragging || !this.elementRef?.componentInstance || !this.elementRef.componentInstance.parent) return;
1747
- const instance = this.elementRef.componentInstance;
1748
- const parent = instance.parent;
1749
- const dragProps = this.dragProps;
1750
- const propObservables = this.elementRef.propObservables;
1751
- const snapTo = snap(dragProps?.snap() ?? 0);
1752
- dragProps?.move?.(event);
1753
- const currentParentLocalPointer = parent.toLocal(event.global);
1754
- const newX = currentParentLocalPointer.x - this.offsetInParent.x;
1755
- const newY = currentParentLocalPointer.y - this.offsetInParent.y;
1756
- if (dragProps?.snap()) {
1757
- instance.position.x = snapTo(newX);
1758
- instance.position.y = snapTo(newY);
1759
- } else {
1760
- if (this.axis.x) instance.position.x = newX;
1761
- if (this.axis.y) instance.position.y = newY;
1762
- }
1763
- this.lastPointerPosition.copyFrom(event.global);
1764
- const { x: xProp, y: yProp } = propObservables;
1765
- const updatePosition = (prop, value) => {
1766
- if (isComputed2(prop)) {
1767
- prop.dependencies.forEach((dependency) => {
1768
- dependency.set(value);
1769
- });
1770
- } else if (isSignal3(prop)) {
1771
- prop.set(value);
1772
- }
1773
- };
1774
- if (xProp !== void 0) updatePosition(xProp, instance.position.x);
1775
- if (yProp !== void 0) updatePosition(yProp, instance.position.y);
1776
- }
1777
- /**
1778
- * Moves the viewport if the dragged element is near screen edges
1779
- * @param globalPosition The global pointer position
1780
- */
1781
- updateViewportPosition(globalPosition) {
1782
- if (!this.viewport || !this.elementRef) return;
1783
- const dragProps = this.dragProps;
1784
- const edgeThreshold = dragProps?.viewport?.edgeThreshold();
1785
- const maxSpeed = dragProps?.viewport?.maxSpeed();
1786
- const screenLeft = 0;
1787
- const screenRight = this.viewport.screenWidth;
1788
- const screenTop = 0;
1789
- const screenBottom = this.viewport.screenHeight;
1790
- const instance = this.elementRef.componentInstance;
1791
- const distanceFromLeft = globalPosition.x - screenLeft;
1792
- const distanceFromRight = screenRight - globalPosition.x;
1793
- const distanceFromTop = globalPosition.y - screenTop;
1794
- const distanceFromBottom = screenBottom - globalPosition.y;
1795
- let moveX = 0;
1796
- let moveY = 0;
1797
- if (distanceFromLeft < edgeThreshold) {
1798
- const velocity = maxSpeed * (1 - distanceFromLeft / edgeThreshold);
1799
- moveX = -velocity;
1800
- } else if (distanceFromRight < edgeThreshold) {
1801
- const velocity = maxSpeed * (1 - distanceFromRight / edgeThreshold);
1802
- moveX = velocity;
1803
- }
1804
- if (distanceFromTop < edgeThreshold) {
1805
- const velocity = maxSpeed * (1 - distanceFromTop / edgeThreshold);
1806
- moveY = -velocity;
1807
- } else if (distanceFromBottom < edgeThreshold) {
1808
- const velocity = maxSpeed * (1 - distanceFromBottom / edgeThreshold);
1809
- moveY = velocity;
1810
- }
1811
- if (moveX !== 0 || moveY !== 0) {
1812
- const lastViewValue = this.viewport.center;
1813
- this.viewport.moveCenter(
1814
- this.viewport.center.x + moveX,
1815
- this.viewport.center.y + moveY
1816
- );
1817
- if (this.axis.x && lastViewValue.x !== this.viewport.center.x) {
1818
- instance.position.x += moveX;
1819
- }
1820
- if (this.axis.y && lastViewValue.y !== this.viewport.center.y) {
1821
- instance.position.y += moveY;
1822
- }
1823
- }
1824
- }
1825
- /**
1826
- * Handles drag end event and stops viewport movement
1827
- */
1828
- onDragEnd() {
1829
- this.pointerIsDown = false;
1830
- if (!this.isDragging) return;
1831
- const dragProps = this.dragProps;
1832
- this.isDragging = false;
1833
- dragProps?.end?.();
1834
- if (this.stageRef) {
1835
- this.stageRef.off("pointermove", this.onDragMoveHandler);
1836
- }
1837
- }
1838
- onKeyDown(event) {
1839
- this.pressedKeys.add(event.code);
1840
- this.pressedKeys.add(event.key.toLowerCase());
1841
- if (this.pointerIsDown && !this.isDragging && this.areRequiredKeysPressed()) {
1842
- this.startDrag();
1843
- }
1844
- }
1845
- onKeyUp(event) {
1846
- this.pressedKeys.delete(event.code);
1847
- this.pressedKeys.delete(event.key.toLowerCase());
1848
- if (this.isDragging && !this.areRequiredKeysPressed()) {
1849
- this.onDragEnd();
1850
- }
1851
- }
1852
- areRequiredKeysPressed() {
1853
- const keyToPress = this.dragProps.keyToPress ? this.dragProps.keyToPress : [];
1854
- if (!keyToPress || keyToPress.length === 0) {
1855
- return true;
1856
- }
1857
- return keyToPress.some((key) => {
1858
- if (this.pressedKeys.has(key)) {
1859
- return true;
1860
- }
1861
- if (key.toLowerCase() === "space") {
1862
- return this.pressedKeys.has("Space") || this.pressedKeys.has(" ");
1863
- }
1864
- if (key.toLowerCase() === "shift") {
1865
- return this.pressedKeys.has("ShiftLeft") || this.pressedKeys.has("ShiftRight");
1866
- }
1867
- if (key.toLowerCase() === "control" || key.toLowerCase() === "ctrl") {
1868
- return this.pressedKeys.has("ControlLeft") || this.pressedKeys.has("ControlRight");
1869
- }
1870
- if (key.toLowerCase() === "alt") {
1871
- return this.pressedKeys.has("AltLeft") || this.pressedKeys.has("AltRight");
1872
- }
1873
- return false;
1874
- });
1875
- }
1876
- onPointerDown(event) {
1877
- if (!this.elementRef?.componentInstance || !this.stageRef || !this.elementRef.componentInstance.parent) return;
1878
- this.pointerIsDown = true;
1879
- const instance = this.elementRef.componentInstance;
1880
- const parent = instance.parent;
1881
- const parentLocalPointer = parent.toLocal(event.global);
1882
- this.offsetInParent.x = parentLocalPointer.x - instance.position.x;
1883
- this.offsetInParent.y = parentLocalPointer.y - instance.position.y;
1884
- this.lastPointerPosition.copyFrom(event.global);
1885
- if (this.areRequiredKeysPressed()) {
1886
- this.startDrag();
1887
- }
1888
- }
1889
- startDrag() {
1890
- if (this.isDragging || !this.stageRef) return;
1891
- this.isDragging = true;
1892
- const dragProps = this.dragProps;
1893
- dragProps?.start?.();
1894
- this.stageRef.on("pointermove", this.onDragMoveHandler);
1895
- }
1896
- onUpdate(props) {
1897
- if (props.type && props.type === "reset") {
1898
- this.onDestroy();
1899
- this.onMount(this.elementRef);
1900
- }
1901
- }
1902
- onDestroy() {
1903
- this.subscriptions.forEach((subscription) => subscription.unsubscribe());
1904
- const instance = this.elementRef?.componentInstance;
1905
- if (instance) {
1906
- instance.off("pointerdown", this.onDragStartHandler);
1907
- }
1908
- if (this.stageRef) {
1909
- this.stageRef.off("pointermove", this.onDragMoveHandler);
1910
- this.stageRef.off("pointerup", this.onDragEndHandler);
1911
- this.stageRef.off("pointerupoutside", this.onDragEndHandler);
1912
- }
1913
- window.removeEventListener("keydown", this.onKeyDownHandler);
1914
- window.removeEventListener("keyup", this.onKeyUpHandler);
1915
- this.stageRef = null;
1916
- this.viewport = null;
1917
- this.pressedKeys.clear();
1918
- this.pointerIsDown = false;
1919
- }
1920
- };
1921
- registerDirective("drag", Drag);
1922
- registerDirective("drop", Drop);
1923
-
1924
- // src/directives/Transition.ts
1925
- import { DisplacementFilter, Sprite, Texture, WRAP_MODES } from "pixi.js";
1926
- import { animate } from "popmotion";
1927
- var Transition = class extends Directive {
1928
- onInit(element) {
1929
- }
1930
- onMount(element) {
1931
- const { image } = element.props.transition;
1932
- const displacementSprite = new Sprite(Texture.from(image));
1933
- displacementSprite.texture.baseTexture.wrapMode = WRAP_MODES.REPEAT;
1934
- const displacementFilter = new DisplacementFilter(displacementSprite);
1935
- const instance = element.componentInstance;
1936
- instance.filters = [displacementFilter];
1937
- instance.addChild(displacementSprite);
1938
- setTimeout(() => {
1939
- animate({
1940
- from: 0,
1941
- to: 1,
1942
- duration: 500,
1943
- onUpdate: (progress) => {
1944
- displacementFilter.scale.x = progress;
1945
- displacementFilter.scale.y = progress;
1946
- }
1947
- });
1948
- }, 5e3);
1949
- }
1950
- onUpdate(props) {
1951
- }
1952
- onDestroy() {
1953
- }
1954
- };
1955
- registerDirective("transition", Transition);
1956
-
1957
- // src/index.ts
1958
- export * from "@signe/reactive";
1959
- import { Howler } from "howler";
1960
-
1961
- // src/components/Canvas.ts
1962
- import { effect as effect3, signal as signal5 } from "@signe/reactive";
1963
- import { Container as Container3 } from "pixi.js";
1964
-
1965
- // src/components/DisplayObject.ts
1966
- import { signal as signal4 } from "@signe/reactive";
1967
- import { BlurFilter, ObservablePoint } from "pixi.js";
1968
-
1969
- // src/utils/functions.ts
1970
- function isPercent(value) {
1971
- if (!value) return false;
1972
- if (typeof value === "string") {
1973
- return value.endsWith("%");
1974
- }
1975
- return false;
1976
- }
1977
-
1978
- // src/components/DisplayObject.ts
1979
- import { BehaviorSubject } from "rxjs";
1980
- var EVENTS2 = [
1981
- "added",
1982
- "childAdded",
1983
- "childRemoved",
1984
- "click",
1985
- "clickcapture",
1986
- "destroyed",
1987
- "globalmousemove",
1988
- "globalpointermove",
1989
- "globaltouchmove",
1990
- "mousedown",
1991
- "mousedowncapture",
1992
- "mouseenter",
1993
- "mouseentercapture",
1994
- "mouseleave",
1995
- "mouseleavecapture",
1996
- "mousemove",
1997
- "mousemovecapture",
1998
- "mouseout",
1999
- "mouseoutcapture",
2000
- "mouseover",
2001
- "mouseovercapture",
2002
- "mouseup",
2003
- "mouseupcapture",
2004
- "mouseupoutside",
2005
- "mouseupoutsidecapture",
2006
- "pointercancel",
2007
- "pointercancelcapture",
2008
- "pointerdown",
2009
- "pointerdowncapture",
2010
- "pointerenter",
2011
- "pointerentercapture",
2012
- "pointerleave",
2013
- "pointerleavecapture",
2014
- "pointermove",
2015
- "pointermovecapture",
2016
- "pointerout",
2017
- "pointeroutcapture",
2018
- "pointerover",
2019
- "pointerovercapture",
2020
- "pointertap",
2021
- "pointertapcapture",
2022
- "pointerup",
2023
- "pointerupcapture",
2024
- "pointerupoutside",
2025
- "pointerupoutsidecapture",
2026
- "removed",
2027
- "rightclick",
2028
- "rightclickcapture",
2029
- "rightdown",
2030
- "rightdowncapture",
2031
- "rightup",
2032
- "rightupcapture",
2033
- "rightupoutside",
2034
- "rightupoutsidecapture",
2035
- "tap",
2036
- "tapcapture",
2037
- "touchcancel",
2038
- "touchcancelcapture",
2039
- "touchend",
2040
- "touchendcapture",
2041
- "touchendoutside",
2042
- "touchendoutsidecapture",
2043
- "touchmove",
2044
- "touchmovecapture",
2045
- "touchstart",
2046
- "touchstartcapture",
2047
- "wheel",
2048
- "wheelcapture"
2049
- ];
2050
- function DisplayObject(extendClass) {
2051
- var _canvasContext, _a;
2052
- return _a = class extends extendClass {
2053
- constructor() {
2054
- super(...arguments);
2055
- __privateAdd(this, _canvasContext, null);
2056
- this.isFlex = false;
2057
- this.fullProps = {};
2058
- this.isMounted = false;
2059
- this._anchorPoints = new ObservablePoint({ _onUpdate: () => {
2060
- } }, 0, 0);
2061
- this.isCustomAnchor = false;
2062
- this.displayWidth = signal4(0);
2063
- this.displayHeight = signal4(0);
2064
- this.overrideProps = [];
2065
- this.layout = null;
2066
- this.onBeforeDestroy = null;
2067
- this.onAfterMount = null;
2068
- this.subjectInit = new BehaviorSubject(null);
2069
- this.disableLayout = false;
2070
- }
2071
- get deltaRatio() {
2072
- return __privateGet(this, _canvasContext)?.scheduler?.tick.value.deltaRatio;
2073
- }
2074
- get parentIsFlex() {
2075
- if (this.disableLayout) return false;
2076
- return this.parent?.isFlex;
2077
- }
2078
- onInit(props) {
2079
- this._id = props.id;
2080
- for (let event of EVENTS2) {
2081
- if (props[event] && !this.overrideProps.includes(event)) {
2082
- this.eventMode = "static";
2083
- this.on(event, props[event]);
2084
- }
2085
- }
2086
- if (props.onBeforeDestroy || props["on-before-destroy"]) {
2087
- this.onBeforeDestroy = props.onBeforeDestroy || props["on-before-destroy"];
2088
- }
2089
- if (props.onAfterMount || props["on-after-mount"]) {
2090
- this.onAfterMount = props.onAfterMount || props["on-after-mount"];
2091
- }
2092
- if (props.justifyContent || props.alignItems || props.flexDirection || props.flexWrap || props.alignContent || props.display == "flex" || isPercent(props.width) || isPercent(props.height) || props.isRoot) {
2093
- this.layout = {};
2094
- this.isFlex = true;
2095
- }
2096
- this.subjectInit.next(this);
2097
- }
2098
- async onMount({ parent, props }, index) {
2099
- __privateSet(this, _canvasContext, props.context);
2100
- if (parent) {
2101
- const instance = parent.componentInstance;
2102
- if (instance.isFlex && !this.layout && !this.disableLayout) {
2103
- try {
2104
- this.layout = {};
2105
- } catch (error2) {
2106
- console.warn("Failed to set layout:", error2);
2107
- }
2108
- }
2109
- if (index === void 0) {
2110
- instance.addChild(this);
2111
- } else {
2112
- instance.addChildAt(this, index);
2113
- }
2114
- this.isMounted = true;
2115
- this.onUpdate(props);
2116
- if (this.onAfterMount) {
2117
- await this.onAfterMount();
2118
- }
2119
- }
2120
- }
2121
- onUpdate(props) {
2122
- this.fullProps = {
2123
- ...this.fullProps,
2124
- ...props
2125
- };
2126
- if (!__privateGet(this, _canvasContext) || !this.parent) return;
2127
- if (props.x !== void 0) this.setX(props.x);
2128
- if (props.y !== void 0) this.setY(props.y);
2129
- if (props.scale !== void 0)
2130
- setObservablePoint(this.scale, props.scale);
2131
- if (props.anchor !== void 0 && !this.isCustomAnchor) {
2132
- setObservablePoint(this.anchor, props.anchor);
2133
- }
2134
- if (props.width !== void 0) this.setWidth(props.width);
2135
- if (props.height !== void 0) this.setHeight(props.height);
2136
- if (props.minWidth !== void 0) this.setMinWidth(props.minWidth);
2137
- if (props.minHeight !== void 0) this.setMinHeight(props.minHeight);
2138
- if (props.maxWidth !== void 0) this.setMaxWidth(props.maxWidth);
2139
- if (props.maxHeight !== void 0) this.setMaxHeight(props.maxHeight);
2140
- if (props.aspectRatio !== void 0)
2141
- this.setAspectRatio(props.aspectRatio);
2142
- if (props.flexGrow !== void 0) this.setFlexGrow(props.flexGrow);
2143
- if (props.flexShrink !== void 0) this.setFlexShrink(props.flexShrink);
2144
- if (props.flexBasis !== void 0) this.setFlexBasis(props.flexBasis);
2145
- if (props.rowGap !== void 0) this.setRowGap(props.rowGap);
2146
- if (props.columnGap !== void 0) this.setColumnGap(props.columnGap);
2147
- if (props.top !== void 0) this.setTop(props.top);
2148
- if (props.left !== void 0) this.setLeft(props.left);
2149
- if (props.right !== void 0) this.setRight(props.right);
2150
- if (props.bottom !== void 0) this.setBottom(props.bottom);
2151
- if (props.objectFit !== void 0) this.setObjectFit(props.objectFit);
2152
- if (props.objectPosition !== void 0)
2153
- this.setObjectPosition(props.objectPosition);
2154
- if (props.transformOrigin !== void 0)
2155
- this.setTransformOrigin(props.transformOrigin);
2156
- if (props.skew !== void 0) setObservablePoint(this.skew, props.skew);
2157
- if (props.tint) this.tint = props.tint;
2158
- if (props.rotation !== void 0) this.rotation = props.rotation;
2159
- if (props.angle !== void 0) this.angle = props.angle;
2160
- if (props.zIndex !== void 0) this.zIndex = props.zIndex;
2161
- if (props.roundPixels !== void 0) this.roundPixels = props.roundPixels;
2162
- if (props.cursor) this.cursor = props.cursor;
2163
- if (props.visible !== void 0) this.visible = props.visible;
2164
- if (props.alpha !== void 0) this.alpha = props.alpha;
2165
- if (props.pivot) setObservablePoint(this.pivot, props.pivot);
2166
- if (props.flexDirection) this.setFlexDirection(props.flexDirection);
2167
- if (props.flexWrap) this.setFlexWrap(props.flexWrap);
2168
- if (props.justifyContent) this.setJustifyContent(props.justifyContent);
2169
- if (props.alignItems) this.setAlignItems(props.alignItems);
2170
- if (props.alignContent) this.setAlignContent(props.alignContent);
2171
- if (props.alignSelf) this.setAlignSelf(props.alignSelf);
2172
- if (props.margin) this.setMargin(props.margin);
2173
- if (props.padding) this.setPadding(props.padding);
2174
- if (props.gap) this.setGap(props.gap);
2175
- if (props.border) this.setBorder(props.border);
2176
- if (props.positionType) this.setPositionType(props.positionType);
2177
- if (props.filters) this.filters = props.filters;
2178
- if (props.maskOf) {
2179
- if (isElement(props.maskOf)) {
2180
- props.maskOf.componentInstance.mask = this;
2181
- }
2182
- }
2183
- if (props.blendMode) this.blendMode = props.blendMode;
2184
- if (props.filterArea) this.filterArea = props.filterArea;
2185
- const currentFilters = this.filters || [];
2186
- if (props.blur) {
2187
- let blurFilter = currentFilters.find(
2188
- (filter2) => filter2 instanceof BlurFilter
2189
- );
2190
- if (!blurFilter) {
2191
- const options = typeof props.blur === "number" ? {
2192
- strength: props.blur
2193
- } : props.blur;
2194
- blurFilter = new BlurFilter(options);
2195
- currentFilters.push(blurFilter);
2196
- }
2197
- Object.assign(blurFilter, props.blur);
2198
- }
2199
- this.filters = currentFilters;
2200
- }
2201
- async onDestroy(parent, afterDestroy) {
2202
- if (this.onBeforeDestroy) {
2203
- await this.onBeforeDestroy();
2204
- }
2205
- super.destroy();
2206
- if (afterDestroy) afterDestroy();
2207
- }
2208
- setFlexDirection(direction) {
2209
- this.layout = { flexDirection: direction };
2210
- }
2211
- setFlexWrap(wrap) {
2212
- this.layout = { flexWrap: wrap };
2213
- }
2214
- setAlignContent(align) {
2215
- this.layout = { alignContent: align };
2216
- }
2217
- setAlignSelf(align) {
2218
- this.layout = { alignSelf: align };
2219
- }
2220
- setAlignItems(align) {
2221
- this.layout = { alignItems: align };
2222
- }
2223
- setJustifyContent(justifyContent) {
2224
- this.layout = { justifyContent };
2225
- }
2226
- setPosition(position) {
2227
- if (position instanceof Array) {
2228
- if (position.length === 2) {
2229
- this.layout = {
2230
- positionY: position[0],
2231
- positionX: position[1]
2232
- };
2233
- } else if (position.length === 4) {
2234
- this.layout = {
2235
- positionTop: position[0],
2236
- positionRight: position[1],
2237
- positionBottom: position[2],
2238
- positionLeft: position[3]
2239
- };
2240
- }
2241
- } else {
2242
- this.layout = { position };
2243
- }
2244
- }
2245
- setX(x) {
2246
- x = x + this.getWidth() * this._anchorPoints.x;
2247
- if (!this.parentIsFlex) {
2248
- this.x = x;
2249
- } else {
2250
- this.x = x;
2251
- this.layout = { x };
2252
- }
2253
- }
2254
- setY(y) {
2255
- y = y + this.getHeight() * this._anchorPoints.y;
2256
- if (!this.parentIsFlex) {
2257
- this.y = y;
2258
- } else {
2259
- this.y = y;
2260
- this.layout = { y };
2261
- }
2262
- }
2263
- setPadding(padding) {
2264
- if (padding instanceof Array) {
2265
- if (padding.length === 2) {
2266
- this.layout = {
2267
- paddingVertical: padding[0],
2268
- paddingHorizontal: padding[1]
2269
- };
2270
- } else if (padding.length === 4) {
2271
- this.layout = {
2272
- paddingTop: padding[0],
2273
- paddingRight: padding[1],
2274
- paddingBottom: padding[2],
2275
- paddingLeft: padding[3]
2276
- };
2277
- }
2278
- } else {
2279
- this.layout = { padding };
2280
- }
2281
- }
2282
- setMargin(margin) {
2283
- if (margin instanceof Array) {
2284
- if (margin.length === 2) {
2285
- this.layout = {
2286
- marginVertical: margin[0],
2287
- marginHorizontal: margin[1]
2288
- };
2289
- } else if (margin.length === 4) {
2290
- this.layout = {
2291
- marginTop: margin[0],
2292
- marginRight: margin[1],
2293
- marginBottom: margin[2],
2294
- marginLeft: margin[3]
2295
- };
2296
- }
2297
- } else {
2298
- this.layout = { margin };
2299
- }
2300
- }
2301
- setGap(gap) {
2302
- this.layout = { gap };
2303
- }
2304
- setBorder(border) {
2305
- if (border instanceof Array) {
2306
- if (border.length === 2) {
2307
- this.layout = {
2308
- borderVertical: border[0],
2309
- borderHorizontal: border[1]
2310
- };
2311
- } else if (border.length === 4) {
2312
- this.layout = {
2313
- borderTop: border[0],
2314
- borderRight: border[1],
2315
- borderBottom: border[2],
2316
- borderLeft: border[3]
2317
- };
2318
- }
2319
- } else {
2320
- this.layout = { border };
2321
- }
2322
- }
2323
- setPositionType(positionType) {
2324
- this.layout = { position: positionType };
2325
- }
2326
- setWidth(width) {
2327
- this.displayWidth.set(width);
2328
- if (!this.parentIsFlex) {
2329
- this.width = width;
2330
- } else {
2331
- this.layout = { width };
2332
- }
2333
- }
2334
- setHeight(height) {
2335
- this.displayHeight.set(height);
2336
- if (!this.parentIsFlex) {
2337
- this.height = height;
2338
- } else {
2339
- this.layout = { height };
2340
- }
2341
- }
2342
- getWidth() {
2343
- return this.displayWidth();
2344
- }
2345
- getHeight() {
2346
- return this.displayHeight();
2347
- }
2348
- // Min/Max constraints
2349
- setMinWidth(minWidth) {
2350
- this.layout = { minWidth };
2351
- }
2352
- setMinHeight(minHeight) {
2353
- this.layout = { minHeight };
2354
- }
2355
- setMaxWidth(maxWidth) {
2356
- this.layout = { maxWidth };
2357
- }
2358
- setMaxHeight(maxHeight) {
2359
- this.layout = { maxHeight };
2360
- }
2361
- // Aspect ratio
2362
- setAspectRatio(aspectRatio) {
2363
- this.layout = { aspectRatio };
2364
- }
2365
- // Flex properties
2366
- setFlexGrow(flexGrow) {
2367
- this.layout = { flexGrow };
2368
- }
2369
- setFlexShrink(flexShrink) {
2370
- this.layout = { flexShrink };
2371
- }
2372
- setFlexBasis(flexBasis) {
2373
- this.layout = { flexBasis };
2374
- }
2375
- // Gap properties
2376
- setRowGap(rowGap) {
2377
- this.layout = { rowGap };
2378
- }
2379
- setColumnGap(columnGap) {
2380
- this.layout = { columnGap };
2381
- }
2382
- // Position insets
2383
- setTop(top) {
2384
- this.layout = { top };
2385
- }
2386
- setLeft(left) {
2387
- this.layout = { left };
2388
- }
2389
- setRight(right) {
2390
- this.layout = { right };
2391
- }
2392
- setBottom(bottom) {
2393
- this.layout = { bottom };
2394
- }
2395
- // Object properties
2396
- setObjectFit(objectFit) {
2397
- this.layout = { objectFit };
2398
- }
2399
- setObjectPosition(objectPosition) {
2400
- this.layout = { objectPosition };
2401
- }
2402
- setTransformOrigin(transformOrigin) {
2403
- this.layout = { transformOrigin };
2404
- }
2405
- }, _canvasContext = new WeakMap(), _a;
2406
- }
2407
-
2408
- // src/components/Canvas.ts
2409
- registerComponent("Canvas", class Canvas extends DisplayObject(Container3) {
2410
- });
2411
- var Canvas2 = async (props = {}) => {
2412
- let { cursorStyles, width, height, class: className } = useProps(props);
2413
- if (!props.width) width = signal5(800);
2414
- if (!props.height) height = signal5(600);
2415
- const canvasSize = signal5({
2416
- width: 0,
2417
- height: 0
2418
- });
2419
- props.isRoot = true;
2420
- const options = {
2421
- ...props,
2422
- context: {
2423
- canvasSize,
2424
- app: signal5(null)
2425
- },
2426
- width: width?.(),
2427
- height: height?.()
2428
- };
2429
- if (!props.tick) {
2430
- options.context.tick = options.tick = signal5({
2431
- timestamp: 0,
2432
- deltaTime: 0,
2433
- frame: 0,
2434
- deltaRatio: 1
2435
- });
2436
- }
2437
- const canvasElement = createComponent("Canvas", options);
2438
- canvasElement.render = (rootElement, app) => {
2439
- if (!app) {
2440
- return;
2441
- }
2442
- const renderer = app.renderer;
2443
- const canvasEl = renderer.view.canvas;
2444
- globalThis.__PIXI_STAGE__ = canvasElement.componentInstance;
2445
- globalThis.__PIXI_RENDERER__ = renderer;
2446
- if (props.tickStart !== false) canvasElement.directives.tick.start();
2447
- effect3(() => {
2448
- canvasElement.propObservables.tick();
2449
- renderer.render(canvasElement.componentInstance);
2450
- });
2451
- app.stage = canvasElement.componentInstance;
2452
- app.stage.layout = {
2453
- width: app.screen.width,
2454
- height: app.screen.height,
2455
- justifyContent: props.justifyContent,
2456
- alignItems: props.alignItems
2457
- };
2458
- canvasSize.set({ width: app.screen.width, height: app.screen.height });
2459
- app.renderer.on("resize", (width2, height2) => {
2460
- canvasSize.set({ width: width2, height: height2 });
2461
- if (app.stage.layout) {
2462
- app.stage.layout = {
2463
- width: width2,
2464
- height: height2
2465
- };
2466
- }
2467
- });
2468
- if (props.tickStart !== false) canvasElement.directives.tick.start();
2469
- app.ticker.add(() => {
2470
- canvasElement.propObservables.tick();
2471
- });
2472
- if (cursorStyles) {
2473
- effect3(() => {
2474
- renderer.events.cursorStyles = cursorStyles();
2475
- });
2476
- }
2477
- if (className) {
2478
- effect3(() => {
2479
- canvasEl.classList.add(className());
2480
- });
2481
- }
2482
- const existingCanvas = rootElement.querySelector("canvas");
2483
- if (existingCanvas) {
2484
- rootElement.replaceChild(canvasEl, existingCanvas);
2485
- } else {
2486
- rootElement.appendChild(canvasEl);
2487
- }
2488
- options.context.app.set(app);
2489
- };
2490
- return canvasElement;
2491
- };
2492
-
2493
- // src/components/Container.ts
2494
- import { Container as PixiContainer } from "pixi.js";
2495
- var CanvasContainer = class extends DisplayObject(PixiContainer) {
2496
- constructor() {
2497
- super(...arguments);
2498
- this.isCustomAnchor = true;
2499
- }
2500
- onUpdate(props) {
2501
- if (props.anchor) {
2502
- setObservablePoint(this._anchorPoints, props.anchor);
2503
- props.pivot = [
2504
- this.getWidth() * this._anchorPoints.x,
2505
- this.getHeight() * this._anchorPoints.y
2506
- ];
2507
- }
2508
- super.onUpdate(props);
2509
- if (props.sortableChildren != void 0) {
2510
- this.sortableChildren = props.sortableChildren;
2511
- }
2512
- }
2513
- async onMount(args) {
2514
- await super.onMount(args);
2515
- const { componentInstance, props } = args;
2516
- const { pixiChildren } = props;
2517
- if (pixiChildren) {
2518
- pixiChildren.forEach((child) => {
2519
- componentInstance.addChild(child);
2520
- });
2521
- }
2522
- }
2523
- };
2524
- registerComponent("Container", CanvasContainer);
2525
- var Container4 = (props) => {
2526
- return createComponent("Container", props);
2527
- };
2528
-
2529
- // src/components/Graphic.ts
2530
- import { effect as effect4, isSignal as isSignal4, signal as signal6 } from "@signe/reactive";
2531
- import { Assets, Graphics as PixiGraphics } from "pixi.js";
2532
- var CanvasGraphics = class extends DisplayObject(PixiGraphics) {
2533
- /**
2534
- * Initializes the graphics component with reactive width and height handling.
2535
- *
2536
- * This method handles different types of width and height props:
2537
- * - **Numbers**: Direct pixel values
2538
- * - **Strings with %**: Percentage values that trigger flex layout and use layout box dimensions
2539
- * - **Signals**: Reactive values that update automatically
2540
- *
2541
- * When percentage values are detected, the component:
2542
- * 1. Sets `display: 'flex'` to enable layout calculations
2543
- * 2. Listens to layout events to get computed dimensions
2544
- * 3. Updates internal width/height signals with layout box values
2545
- *
2546
- * The draw function receives the reactive width and height signals as parameters.
2547
- *
2548
- * @param props - Component properties including width, height, and draw function
2549
- * @example
2550
- * ```typescript
2551
- * // With pixel values
2552
- * Graphics({ width: 100, height: 50, draw: (g, w, h) => g.rect(0, 0, w(), h()) });
2553
- *
2554
- * // With percentage values (uses layout box)
2555
- * Graphics({ width: "50%", height: "100%", draw: (g, w, h) => g.rect(0, 0, w(), h()) });
2556
- *
2557
- * // With signals
2558
- * const width = signal(100);
2559
- * Graphics({ width, height: 50, draw: (g, w, h) => g.rect(0, 0, w(), h()) });
2560
- * ```
2561
- */
2562
- async onInit(props) {
2563
- await super.onInit(props);
2564
- }
2565
- /**
2566
- * Called when the component is mounted to the scene graph.
2567
- * Creates the reactive effect for drawing using the original signals from propObservables.
2568
- * @param {Element<DisplayObject>} element - The element being mounted with props and propObservables.
2569
- * @param {number} [index] - The index of the component among its siblings.
2570
- */
2571
- async onMount(element, index) {
2572
- await super.onMount(element, index);
2573
- const { props, propObservables } = element;
2574
- const width = isSignal4(propObservables?.width) ? propObservables.width : signal6(props.width || 0);
2575
- const height = isSignal4(propObservables?.height) ? propObservables.height : signal6(props.height || 0);
2576
- this.width = width;
2577
- this.height = height;
2578
- const isWidthPercentage = isPercent(width());
2579
- const isHeightPercentage = isPercent(height());
2580
- if (props.draw) {
2581
- this.clearEffect = effect4(() => {
2582
- const w = width();
2583
- const h2 = height();
2584
- if (typeof w == "string" || typeof h2 == "string") {
2585
- return;
2586
- }
2587
- if (w == 0 || h2 == 0) {
2588
- return;
2589
- }
2590
- this.clear();
2591
- props.draw?.(this, w, h2);
2592
- this.subjectInit.next(this);
2593
- });
2594
- }
2595
- this.on("layout", (event) => {
2596
- const layoutBox = event.computedLayout;
2597
- if (isWidthPercentage && isSignal4(width)) {
2598
- width.set(layoutBox.width);
2599
- }
2600
- if (isHeightPercentage && isSignal4(height)) {
2601
- height.set(layoutBox.height);
2602
- }
2603
- });
2604
- }
2605
- /**
2606
- * Called when component props are updated.
2607
- * Updates the internal width and height signals when props change.
2608
- * @param props - Updated properties
2609
- */
2610
- onUpdate(props) {
2611
- super.onUpdate(props);
2612
- if (props.width !== void 0 && this.width) {
2613
- if (isSignal4(props.width)) {
2614
- this.width = props.width;
2615
- } else {
2616
- this.width.set(props.width);
2617
- }
2618
- }
2619
- if (props.height !== void 0 && this.height) {
2620
- if (isSignal4(props.height)) {
2621
- this.height = props.height;
2622
- } else {
2623
- this.height.set(props.height);
2624
- }
2625
- }
2626
- }
2627
- /**
2628
- * Called when the component is about to be destroyed.
2629
- * This method should be overridden by subclasses to perform any cleanup.
2630
- * It ensures that the clearEffect subscription is unsubscribed before calling the original afterDestroy callback.
2631
- * @param parent The parent element.
2632
- * @param afterDestroy A callback function to be executed after the component's own destruction logic.
2633
- * @example
2634
- * // This method is typically called by the engine internally.
2635
- * // await component.onDestroy(parentElement, () => console.log('Component destroyed'));
2636
- */
2637
- async onDestroy(parent, afterDestroy) {
2638
- const _afterDestroyCallback = async () => {
2639
- this.clearEffect.subscription.unsubscribe();
2640
- afterDestroy();
2641
- };
2642
- await super.onDestroy(parent, _afterDestroyCallback);
2643
- }
2644
- };
2645
- registerComponent("Graphics", CanvasGraphics);
2646
- function Graphics(props) {
2647
- return createComponent("Graphics", props);
2648
- }
2649
- function Rect(props) {
2650
- const { color, borderRadius, border } = useProps(props, {
2651
- borderRadius: null,
2652
- border: null
2653
- });
2654
- return Graphics({
2655
- draw: (g, width, height) => {
2656
- if (borderRadius()) {
2657
- g.roundRect(0, 0, width, height, borderRadius());
2658
- } else {
2659
- g.rect(0, 0, width, height);
2660
- }
2661
- if (border) {
2662
- g.stroke(border);
2663
- }
2664
- g.fill(color());
2665
- },
2666
- ...props
2667
- });
2668
- }
2669
- function drawShape(g, shape, props) {
2670
- const { color, border } = props;
2671
- if ("radius" in props) {
2672
- g.circle(0, 0, props.radius());
2673
- } else {
2674
- g.ellipse(0, 0, props.width() / 2, props.height() / 2);
2675
- }
2676
- if (border()) {
2677
- g.stroke(border());
2678
- }
2679
- g.fill(color());
2680
- }
2681
- function Circle(props) {
2682
- const { radius, color, border } = useProps(props, {
2683
- border: null
2684
- });
2685
- return Graphics({
2686
- draw: (g) => drawShape(g, "circle", { radius, color, border }),
2687
- ...props
2688
- });
2689
- }
2690
- function Ellipse(props) {
2691
- const { width, height, color, border } = useProps(props, {
2692
- border: null
2693
- });
2694
- return Graphics({
2695
- draw: (g, gWidth, gHeight) => drawShape(g, "ellipse", { width: signal6(gWidth), height: signal6(gHeight), color, border }),
2696
- ...props
2697
- });
2698
- }
2699
- function Triangle(props) {
2700
- const { width, height, color, border } = useProps(props, {
2701
- border: null,
2702
- color: "#000"
2703
- });
2704
- return Graphics({
2705
- draw: (g, gWidth, gHeight) => {
2706
- g.moveTo(0, gHeight);
2707
- g.lineTo(gWidth / 2, 0);
2708
- g.lineTo(gWidth, gHeight);
2709
- g.lineTo(0, gHeight);
2710
- g.fill(color());
2711
- if (border) {
2712
- g.stroke(border);
2713
- }
2714
- },
2715
- ...props
2716
- });
2717
- }
2718
- function Svg(props) {
2719
- return Graphics({
2720
- draw: async (g) => {
2721
- if (props.src) {
2722
- const svgData = await Assets.load({
2723
- src: props.src,
2724
- data: {
2725
- parseAsGraphicsContext: true
2726
- }
2727
- });
2728
- const graphics = new PixiGraphics(svgData);
2729
- g.context = graphics.context;
2730
- } else if (props.content) {
2731
- g.svg(props.content);
2732
- } else if (props.svg) {
2733
- g.svg(props.svg);
2734
- }
2735
- },
2736
- ...props
2737
- });
2738
- }
2739
-
2740
- // src/components/Mesh.ts
2741
- import { Mesh as PixiMesh, Geometry, Assets as Assets2 } from "pixi.js";
2742
- var CanvasMesh = class extends DisplayObject(PixiMesh) {
2743
- /**
2744
- * Constructor for the CanvasMesh component.
2745
- * Initializes the PixiMesh with default geometry and shader to prevent errors.
2746
- *
2747
- * @example
2748
- * ```typescript
2749
- * // This constructor is called internally by the engine
2750
- * const mesh = new CanvasMesh();
2751
- * ```
2752
- */
2753
- constructor() {
2754
- super({
2755
- geometry: new Geometry()
2756
- });
2757
- }
2758
- /**
2759
- * Initializes the mesh component with the provided properties.
2760
- * This method is called before onUpdate to set up initial state.
2761
- *
2762
- * @param props - The initial properties
2763
- * @example
2764
- * ```typescript
2765
- * // This method is called internally when the component is created
2766
- * mesh.onInit({
2767
- * geometry: myGeometry,
2768
- * texture: "texture.png"
2769
- * });
2770
- * ```
2771
- */
2772
- onInit(props) {
2773
- super.onInit(props);
2774
- if (props.geometry) {
2775
- try {
2776
- this.geometry = props.geometry;
2777
- } catch (error2) {
2778
- console.warn("Failed to set geometry:", error2);
2779
- }
2780
- }
2781
- if (props.shader) {
2782
- this.shader = props.shader;
2783
- }
2784
- }
2785
- /**
2786
- * Updates the mesh component when properties change.
2787
- * Handles texture loading, shader updates, and other property changes.
2788
- *
2789
- * @param props - The updated properties
2790
- * @example
2791
- * ```typescript
2792
- * // This method is called internally when props change
2793
- * mesh.onUpdate({
2794
- * tint: 0x00ff00,
2795
- * texture: "new-texture.png"
2796
- * });
2797
- * ```
2798
- */
2799
- async onUpdate(props) {
2800
- super.onUpdate(props);
2801
- if (props.geometry) {
2802
- try {
2803
- this.geometry = props.geometry;
2804
- } catch (error2) {
2805
- console.warn("Failed to update geometry:", error2);
2806
- }
2807
- }
2808
- if (props.shader) {
2809
- this.shader = props.shader;
2810
- }
2811
- if (props.texture) {
2812
- if (typeof props.texture === "string") {
2813
- this.texture = await Assets2.load(props.texture);
2814
- } else {
2815
- this.texture = props.texture;
2816
- }
2817
- } else if (props.image) {
2818
- this.texture = await Assets2.load(props.image);
2819
- }
2820
- if (props.tint !== void 0) {
2821
- this.tint = props.tint;
2822
- }
2823
- if (props.blendMode !== void 0) {
2824
- this.blendMode = props.blendMode;
2825
- }
2826
- if (props.roundPixels !== void 0) {
2827
- this.roundPixels = props.roundPixels;
2828
- }
2829
- }
2830
- /**
2831
- * Called when the component is about to be destroyed.
2832
- * Cleans up the draw effect subscription and calls the parent destroy method.
2833
- *
2834
- * @param parent - The parent element
2835
- * @param afterDestroy - Callback function to execute after destruction
2836
- * @example
2837
- * ```typescript
2838
- * // This method is typically called by the engine internally
2839
- * await mesh.onDestroy(parentElement, () => console.log('Mesh destroyed'));
2840
- * ```
2841
- */
2842
- async onDestroy(parent, afterDestroy) {
2843
- const _afterDestroyCallback = async () => {
2844
- afterDestroy();
2845
- };
2846
- await super.onDestroy(parent, _afterDestroyCallback);
2847
- }
2848
- };
2849
- registerComponent("Mesh", CanvasMesh);
2850
- var Mesh = (props) => {
2851
- return createComponent("Mesh", props);
2852
- };
2853
-
2854
- // src/engine/signal.ts
2855
- var currentSubscriptionsTracker = null;
2856
- var mountTracker = null;
2857
- function mount(fn) {
2858
- mountTracker?.(fn);
2859
- }
2860
- function tick(fn) {
2861
- mount((el) => {
2862
- const { context } = el.props;
2863
- let subscription;
2864
- if (context.tick) {
2865
- subscription = context.tick.observable.subscribe(({ value }) => {
2866
- fn(value, el);
2867
- });
2868
- }
2869
- return () => {
2870
- subscription?.unsubscribe();
2871
- };
2872
- });
2873
- }
2874
- function h(componentFunction, props = {}, ...children) {
2875
- const allSubscriptions = /* @__PURE__ */ new Set();
2876
- const allMounts = /* @__PURE__ */ new Set();
2877
- currentSubscriptionsTracker = (subscription) => {
2878
- allSubscriptions.add(subscription);
2879
- };
2880
- mountTracker = (fn) => {
2881
- allMounts.add(fn);
2882
- };
2883
- if (children[0] instanceof Array) {
2884
- children = children[0];
2885
- }
2886
- let component = componentFunction({ ...props, children });
2887
- if (!component) {
2888
- component = {};
2889
- }
2890
- component.effectSubscriptions = Array.from(allSubscriptions);
2891
- component.effectMounts = [
2892
- ...Array.from(allMounts),
2893
- ...component.effectMounts ?? []
2894
- ];
2895
- if (component instanceof Promise) {
2896
- component.then((component2) => {
2897
- if (component2.props.isRoot) {
2898
- allMounts.forEach((fn) => fn(component2));
2899
- }
2900
- });
2901
- }
2902
- currentSubscriptionsTracker = null;
2903
- mountTracker = null;
2904
- return component;
2905
- }
2906
-
2907
- // src/components/Scene.ts
2908
- function Scene(props) {
2909
- return h(Container4);
2910
- }
2911
-
2912
- // src/components/ParticleEmitter.ts
2913
- import * as particles from "@barvynkoa/particle-emitter";
2914
- var CanvasParticlesEmitter = class extends CanvasContainer {
2915
- constructor() {
2916
- super(...arguments);
2917
- this.elapsed = Date.now();
2918
- }
2919
- async onMount(params) {
2920
- await super.onMount(params);
2921
- const { props } = params;
2922
- const tick2 = props.context.tick;
2923
- this.emitter = new particles.Emitter(this, props.config);
2924
- this.subscriptionTick = tick2.observable.subscribe((value) => {
2925
- if (!this.emitter) return;
2926
- const now = Date.now();
2927
- this.emitter.update((now - this.elapsed) * 1e-3);
2928
- this.elapsed = now;
2929
- });
2930
- }
2931
- onUpdate(props) {
2932
- }
2933
- async onDestroy(parent, afterDestroy) {
2934
- const _afterDestroy = async () => {
2935
- this.emitter?.destroy();
2936
- this.emitter = null;
2937
- this.subscriptionTick.unsubscribe();
2938
- afterDestroy();
2939
- };
2940
- await super.onDestroy(parent, _afterDestroy);
2941
- }
2942
- };
2943
- registerComponent("ParticlesEmitter", CanvasParticlesEmitter);
2944
- function ParticlesEmitter(props) {
2945
- return createComponent("ParticlesEmitter", props);
2946
- }
2947
-
2948
- // src/components/Sprite.ts
2949
- import { Howl as Howl2 } from "howler";
2950
- import { computed, effect as effect6, isSignal as isSignal5 } from "@signe/reactive";
2951
- import {
2952
- Assets as Assets3,
2953
- Container as Container5,
2954
- Sprite as PixiSprite,
2955
- Rectangle as Rectangle2,
2956
- Texture as Texture3
2957
- } from "pixi.js";
2958
-
2959
- // src/engine/animation.ts
2960
- import { effect as effect5, signal as signal7 } from "@signe/reactive";
2961
- import { animate as animatePopmotion } from "popmotion";
2962
- function isAnimatedSignal(signal10) {
2963
- return signal10.animatedState !== void 0;
2964
- }
2965
- function animatedSignal(initialValue, options = {}) {
2966
- const state = {
2967
- current: initialValue,
2968
- start: initialValue,
2969
- end: initialValue
2970
- };
2971
- let animation;
2972
- const publicSignal = signal7(initialValue);
2973
- const privateSignal = signal7(state);
2974
- effect5(() => {
2975
- const currentState = privateSignal();
2976
- publicSignal.set(currentState.current);
2977
- });
2978
- function animatedSignal2(newValue, animationConfig = {}) {
2979
- if (newValue === void 0) {
2980
- return privateSignal();
2981
- }
2982
- const prevState = privateSignal();
2983
- const newState = {
2984
- current: prevState.current,
2985
- start: prevState.current,
2986
- end: newValue
2987
- };
2988
- privateSignal.set(newState);
2989
- if (animation) {
2990
- animation.stop();
2991
- }
2992
- animation = animatePopmotion({
2993
- // TODO
2994
- duration: 20,
2995
- ...options,
2996
- ...animationConfig,
2997
- from: prevState.current,
2998
- to: newValue,
2999
- onUpdate: (value) => {
3000
- privateSignal.update((s) => ({ ...s, current: value }));
3001
- if (options.onUpdate) {
3002
- options.onUpdate(value);
3003
- }
3004
- }
3005
- });
3006
- }
3007
- const fn = function() {
3008
- return privateSignal().current;
3009
- };
3010
- for (const key in publicSignal) {
3011
- fn[key] = publicSignal[key];
3012
- }
3013
- fn.animatedState = privateSignal;
3014
- fn.update = (updater) => {
3015
- animatedSignal2(updater(privateSignal().current));
3016
- };
3017
- fn.set = async (newValue, animationConfig = {}) => {
3018
- return new Promise((resolve) => {
3019
- animatedSignal2(newValue, {
3020
- ...animationConfig,
3021
- onComplete: resolve
3022
- });
3023
- });
3024
- };
3025
- return fn;
3026
- }
3027
- async function animatedSequence(sequence) {
3028
- for (const item of sequence) {
3029
- if (Array.isArray(item)) {
3030
- await Promise.all(item.map((fn) => fn()));
3031
- } else {
3032
- await item();
3033
- }
3034
- }
3035
- }
3036
-
3037
- // src/components/Sprite.ts
3038
- var log2 = console.log;
3039
- var CanvasSprite = class extends DisplayObject(PixiSprite) {
3040
- constructor() {
3041
- super(...arguments);
3042
- this.currentAnimation = null;
3043
- this.time = 0;
3044
- this.frameIndex = 0;
3045
- this.animations = /* @__PURE__ */ new Map();
3046
- this.subscriptionSheet = [];
3047
- this.sheetParams = {};
3048
- this.sheetCurrentAnimation = "stand" /* Stand */;
3049
- this.app = null;
3050
- this.currentAnimationContainer = null;
3051
- }
3052
- get renderer() {
3053
- return this.app?.renderer;
3054
- }
3055
- async createTextures(options) {
3056
- const { width, height, framesHeight, framesWidth, image, offset } = options;
3057
- if (!image || typeof image !== "string" || image.trim() === "") {
3058
- console.warn("Invalid image path provided to createTextures:", image);
3059
- return [];
3060
- }
3061
- const texture = await Assets3.load(image);
3062
- const spriteWidth = options.spriteWidth;
3063
- const spriteHeight = options.spriteHeight;
3064
- const frames = [];
3065
- const offsetX = offset && offset.x || 0;
3066
- const offsetY = offset && offset.y || 0;
3067
- for (let i = 0; i < framesHeight; i++) {
3068
- frames[i] = [];
3069
- for (let j = 0; j < framesWidth; j++) {
3070
- const rectX = j * spriteWidth + offsetX;
3071
- const rectY = i * spriteHeight + offsetY;
3072
- if (rectY > height) {
3073
- throw log2(
3074
- `Warning, there is a problem with the height of the "${this.id}" spritesheet. When cutting into frames, the frame exceeds the height of the image.`
3075
- );
3076
- }
3077
- if (rectX > width) {
3078
- throw log2(
3079
- `Warning, there is a problem with the width of the "${this.id}" spritesheet. When cutting into frames, the frame exceeds the width of the image.`
3080
- );
3081
- }
3082
- frames[i].push(
3083
- new Texture3({
3084
- source: texture.source,
3085
- frame: new Rectangle2(rectX, rectY, spriteWidth, spriteHeight)
3086
- })
3087
- );
3088
- }
3089
- }
3090
- return frames;
3091
- }
3092
- async createAnimations() {
3093
- const { textures } = this.spritesheet;
3094
- if (!textures) {
3095
- return;
3096
- }
3097
- for (let animationName in textures) {
3098
- const props = [
3099
- "width",
3100
- "height",
3101
- "framesHeight",
3102
- "framesWidth",
3103
- "rectWidth",
3104
- "rectHeight",
3105
- "offset",
3106
- "image",
3107
- "sound"
3108
- ];
3109
- const parentObj = props.reduce(
3110
- (prev, val) => ({ ...prev, [val]: this.spritesheet[val] }),
3111
- {}
3112
- );
3113
- const optionsTextures = {
3114
- ...parentObj,
3115
- ...textures[animationName]
3116
- };
3117
- const {
3118
- rectWidth,
3119
- width = 0,
3120
- framesWidth = 1,
3121
- rectHeight,
3122
- height = 0,
3123
- framesHeight = 1
3124
- } = optionsTextures;
3125
- optionsTextures.spriteWidth = rectWidth ? rectWidth : width / framesWidth;
3126
- optionsTextures.spriteHeight = rectHeight ? rectHeight : height / framesHeight;
3127
- this.animations.set(animationName, {
3128
- frames: await this.createTextures(
3129
- optionsTextures
3130
- ),
3131
- name: animationName,
3132
- animations: textures[animationName].animations,
3133
- params: [],
3134
- data: optionsTextures,
3135
- sprites: []
3136
- });
3137
- }
3138
- }
3139
- async onMount(params) {
3140
- const { props, propObservables } = params;
3141
- const tick2 = props.context.tick;
3142
- const sheet = props.sheet ?? {};
3143
- this.app = props.context.app();
3144
- if (sheet?.onFinish) {
3145
- this.onFinish = sheet.onFinish;
3146
- }
3147
- this.subscriptionTick = tick2.observable.subscribe((value) => {
3148
- this.update(value);
3149
- });
3150
- if (props.sheet?.definition) {
3151
- this.spritesheet = props.sheet.definition;
3152
- await this.createAnimations();
3153
- }
3154
- if (sheet.params) {
3155
- for (let key in propObservables?.sheet["params"]) {
3156
- const value = propObservables?.sheet["params"][key];
3157
- if (isSignal5(value)) {
3158
- this.subscriptionSheet.push(
3159
- value.observable.subscribe((value2) => {
3160
- if (this.animations.size == 0) return;
3161
- this.play(this.sheetCurrentAnimation, [{ [key]: value2 }]);
3162
- })
3163
- );
3164
- } else {
3165
- this.play(this.sheetCurrentAnimation, [{ [key]: value }]);
3166
- }
3167
- }
3168
- }
3169
- const isMoving = computed(() => {
3170
- const { x, y } = propObservables ?? {};
3171
- if (!x || !y) return false;
3172
- const xSignal = x;
3173
- const ySignal = y;
3174
- const isMovingX = isAnimatedSignal(xSignal) && xSignal.animatedState().current !== xSignal.animatedState().end;
3175
- const isMovingY = isAnimatedSignal(ySignal) && ySignal.animatedState().current !== ySignal.animatedState().end;
3176
- return isMovingX || isMovingY;
3177
- });
3178
- effect6(() => {
3179
- const _isMoving = isMoving();
3180
- if (!this.isMounted) return;
3181
- if (_isMoving) {
3182
- this.sheetCurrentAnimation = "walk" /* Walk */;
3183
- } else {
3184
- this.sheetCurrentAnimation = "stand" /* Stand */;
3185
- }
3186
- if (this.spritesheet) this.play(this.sheetCurrentAnimation, [this.sheetParams]);
3187
- });
3188
- super.onMount(params);
3189
- }
3190
- async onUpdate(props) {
3191
- super.onUpdate(props);
3192
- const setTexture = async (image) => {
3193
- if (!image || typeof image !== "string" || image.trim() === "") {
3194
- console.warn("Invalid image path provided to setTexture:", image);
3195
- return null;
3196
- }
3197
- const onProgress = this.fullProps.loader?.onProgress;
3198
- const texture = await Assets3.load(image, (progress) => {
3199
- if (onProgress) onProgress(progress);
3200
- if (progress == 1) {
3201
- const onComplete = this.fullProps.loader?.onComplete;
3202
- if (onComplete) {
3203
- setTimeout(() => {
3204
- onComplete(texture);
3205
- });
3206
- }
3207
- }
3208
- });
3209
- return texture;
3210
- };
3211
- const sheet = props.sheet;
3212
- if (sheet?.params) this.sheetParams = sheet?.params;
3213
- if (sheet?.playing && this.isMounted) {
3214
- this.sheetCurrentAnimation = sheet?.playing;
3215
- this.play(this.sheetCurrentAnimation, [this.sheetParams]);
3216
- }
3217
- if (props.hitbox) this.hitbox = props.hitbox;
3218
- if (props.scaleMode) this.baseTexture.scaleMode = props.scaleMode;
3219
- else if (props.image && this.fullProps.rectangle === void 0) {
3220
- const texture = await setTexture(this.fullProps.image);
3221
- if (texture) {
3222
- this.texture = texture;
3223
- }
3224
- } else if (props.texture) {
3225
- if (isElement(props.texture)) {
3226
- const textureInstance = props.texture.componentInstance;
3227
- textureInstance.subjectInit.subscribe((value) => {
3228
- console.log("a", value?.width);
3229
- });
3230
- this.texture = this.renderer?.generateTexture(props.texture.componentInstance);
3231
- } else {
3232
- this.texture = props.texture;
3233
- }
3234
- }
3235
- if (props.rectangle !== void 0) {
3236
- const { x, y, width, height } = props.rectangle?.value ?? props.rectangle;
3237
- const texture = await setTexture(this.fullProps.image);
3238
- if (texture) {
3239
- this.texture = new Texture3({
3240
- source: texture.source,
3241
- frame: new Rectangle2(x, y, width, height)
3242
- });
3243
- }
3244
- }
3245
- }
3246
- async onDestroy(parent, afterDestroy) {
3247
- await super.onDestroy(parent);
3248
- this.subscriptionSheet.forEach((sub) => sub.unsubscribe());
3249
- this.subscriptionTick.unsubscribe();
3250
- if (this.currentAnimationContainer && this.parent instanceof Container5) {
3251
- this.parent.removeChild(this.currentAnimationContainer);
3252
- }
3253
- }
3254
- has(name) {
3255
- return this.animations.has(name);
3256
- }
3257
- get(name) {
3258
- return this.animations.get(name);
3259
- }
3260
- isPlaying(name) {
3261
- if (!name) return !!this.currentAnimation;
3262
- if (this.currentAnimation == null) return false;
3263
- return this.currentAnimation.name == name;
3264
- }
3265
- stop() {
3266
- this.currentAnimation = null;
3267
- this.destroy();
3268
- }
3269
- play(name, params = []) {
3270
- const animParams = this.currentAnimation?.params;
3271
- if (this.isPlaying(name) && arrayEquals(params, animParams || [])) return;
3272
- const animation = this.get(name);
3273
- if (!animation) {
3274
- throw new Error(
3275
- `Impossible to play the ${name} animation because it doesn't exist on the "${this.id}" spritesheet`
3276
- );
3277
- }
3278
- const cloneParams = structuredClone(params);
3279
- this.removeChildren();
3280
- animation.sprites = [];
3281
- this.currentAnimation = animation;
3282
- this.currentAnimation.params = cloneParams;
3283
- this.time = 0;
3284
- this.frameIndex = 0;
3285
- let animations = animation.animations;
3286
- animations = isFunction(animations) ? animations(...cloneParams) : animations;
3287
- this.currentAnimationContainer = new Container5();
3288
- for (let container of animations) {
3289
- const sprite = new PixiSprite();
3290
- for (let frame of container) {
3291
- this.currentAnimation.sprites.push(frame);
3292
- }
3293
- this.currentAnimationContainer.addChild(sprite);
3294
- }
3295
- const sound = this.currentAnimation.data.sound;
3296
- if (sound) {
3297
- new Howl2({
3298
- src: sound,
3299
- autoplay: true,
3300
- loop: false,
3301
- volume: 1
3302
- });
3303
- }
3304
- this.update({
3305
- deltaRatio: 1
3306
- });
3307
- }
3308
- update({ deltaRatio }) {
3309
- if (!this.isPlaying() || !this.currentAnimation || !this.currentAnimationContainer)
3310
- return;
3311
- const self = this;
3312
- const { frames, sprites, data } = this.currentAnimation;
3313
- let frame = sprites[this.frameIndex];
3314
- const nextFrame = sprites[this.frameIndex + 1];
3315
- for (let _sprite of this.currentAnimationContainer.children) {
3316
- let applyTransformValue = function(prop, alias) {
3317
- const optionProp = alias || prop;
3318
- const val = getVal(optionProp);
3319
- if (val !== void 0) {
3320
- self[prop] = val;
3321
- }
3322
- };
3323
- const sprite = _sprite;
3324
- if (!frame || frame.frameY == void 0 || frame.frameX == void 0) {
3325
- continue;
3326
- }
3327
- this.texture = frames[frame.frameY][frame.frameX];
3328
- const getVal = (prop) => {
3329
- return frame[prop] ?? data[prop] ?? this.spritesheet[prop];
3330
- };
3331
- const applyTransform = (prop) => {
3332
- const val = getVal(prop);
3333
- if (val) {
3334
- this[prop].set(...val);
3335
- }
3336
- };
3337
- if (this.applyTransform) {
3338
- frame = {
3339
- ...frame,
3340
- ...this.applyTransform(frame, data, this.spritesheet)
3341
- };
3342
- }
3343
- const realSize = getVal("spriteRealSize");
3344
- const heightOfSprite = typeof realSize == "number" ? realSize : realSize?.height;
3345
- const widthOfSprite = typeof realSize == "number" ? realSize : realSize?.width;
3346
- const applyAnchorBySize = () => {
3347
- if (heightOfSprite && this.hitbox) {
3348
- const { spriteWidth, spriteHeight } = data;
3349
- const w = (spriteWidth - this.hitbox.w) / 2 / spriteWidth;
3350
- const gap = (spriteHeight - heightOfSprite) / 2;
3351
- const h2 = (spriteHeight - this.hitbox.h - gap) / spriteHeight;
3352
- this.anchor.set(w, h2);
3353
- }
3354
- };
3355
- if (frame.sound) {
3356
- }
3357
- applyAnchorBySize();
3358
- applyTransform("anchor");
3359
- applyTransform("scale");
3360
- applyTransform("skew");
3361
- applyTransform("pivot");
3362
- applyTransformValue("alpha", "opacity");
3363
- applyTransformValue("x");
3364
- applyTransformValue("y");
3365
- applyTransformValue("angle");
3366
- applyTransformValue("rotation");
3367
- applyTransformValue("visible");
3368
- }
3369
- if (!nextFrame) {
3370
- this.time = 0;
3371
- this.frameIndex = 0;
3372
- if (this.onFinish && sprites.length > 1) this.onFinish();
3373
- return;
3374
- }
3375
- this.time += deltaRatio ?? 1;
3376
- if (this.time >= nextFrame.time) {
3377
- this.frameIndex++;
3378
- }
3379
- }
3380
- };
3381
- registerComponent("Sprite", CanvasSprite);
3382
- var Sprite2 = (props) => {
3383
- return createComponent("Sprite", props);
3384
- };
3385
-
3386
- // src/components/Video.ts
3387
- import { effect as effect7, signal as signal8 } from "@signe/reactive";
3388
- function Video(props) {
3389
- const eventsMap = {
3390
- audioprocess: null,
3391
- canplay: null,
3392
- canplaythrough: null,
3393
- complete: null,
3394
- durationchange: null,
3395
- emptied: null,
3396
- ended: null,
3397
- loadeddata: null,
3398
- loadedmetadata: null,
3399
- pause: null,
3400
- play: null,
3401
- playing: null,
3402
- progress: null,
3403
- ratechange: null,
3404
- seeked: null,
3405
- seeking: null,
3406
- stalled: null,
3407
- suspend: null,
3408
- timeupdate: null,
3409
- volumechange: null,
3410
- waiting: null
3411
- };
3412
- const video = signal8(null);
3413
- const defineProps = useDefineProps(props);
3414
- const { play, loop: loop2, muted } = defineProps({
3415
- play: {
3416
- type: Boolean,
3417
- default: true
3418
- },
3419
- loop: {
3420
- type: Boolean,
3421
- default: false
3422
- },
3423
- muted: {
3424
- type: Boolean,
3425
- default: false
3426
- }
3427
- });
3428
- effect7(() => {
3429
- const _video = video();
3430
- const state = play();
3431
- if (_video && state !== void 0) {
3432
- if (state) {
3433
- _video.play();
3434
- } else {
3435
- _video.pause();
3436
- }
3437
- }
3438
- if (_video && loop2()) {
3439
- _video.loop = loop2();
3440
- }
3441
- if (_video && muted()) {
3442
- _video.muted = muted();
3443
- }
3444
- });
3445
- mount(() => {
3446
- return () => {
3447
- for (let event in eventsMap) {
3448
- if (eventsMap[event]) {
3449
- video().removeEventListener(event, eventsMap[event]);
3450
- }
3451
- }
3452
- };
3453
- });
3454
- return h(Sprite2, {
3455
- ...props,
3456
- image: props.src,
3457
- loader: {
3458
- onComplete: (texture) => {
3459
- const source = texture.source.resource;
3460
- video.set(source);
3461
- if (props?.loader?.onComplete) {
3462
- props.loader.onComplete(texture);
3463
- }
3464
- for (let event in eventsMap) {
3465
- if (props[event]) {
3466
- const cb = (ev) => {
3467
- props[event](ev);
3468
- };
3469
- eventsMap[event] = cb;
3470
- source.addEventListener(event, cb);
3471
- }
3472
- }
3473
- }
3474
- }
3475
- });
3476
- }
3477
-
3478
- // src/components/Text.ts
3479
- import { Text as PixiText } from "pixi.js";
3480
-
3481
- // src/engine/trigger.ts
3482
- import { effect as effect8, signal as signal9 } from "@signe/reactive";
3483
- function isTrigger(arg) {
3484
- return arg?.start && arg?.listen;
3485
- }
3486
- function trigger(globalConfig) {
3487
- const _signal = signal9({
3488
- config: globalConfig,
3489
- value: 0,
3490
- resolve: (value) => void 0
3491
- });
3492
- return {
3493
- start: (config) => {
3494
- return new Promise((resolve) => {
3495
- _signal.set({
3496
- config: {
3497
- ...globalConfig,
3498
- ...config
3499
- },
3500
- resolve,
3501
- value: Math.random()
3502
- });
3503
- });
3504
- },
3505
- listen: () => {
3506
- return {
3507
- config: globalConfig,
3508
- seed: _signal()
3509
- };
3510
- }
3511
- };
3512
- }
3513
- function on(triggerSignal, callback) {
3514
- if (!isTrigger(triggerSignal)) {
3515
- throw new Error("In 'on(arg)' must have a trigger signal type");
3516
- }
3517
- effect8(() => {
3518
- const result = triggerSignal.listen();
3519
- if (result?.seed.value) {
3520
- const ret = callback(result?.seed.config);
3521
- if (ret && typeof ret.then === "function") {
3522
- ret.then(result?.seed.resolve);
3523
- }
3524
- }
3525
- });
3526
- }
3527
-
3528
- // src/components/Text.ts
3529
- var CanvasText = class extends DisplayObject(PixiText) {
3530
- constructor() {
3531
- super(...arguments);
3532
- this.fullText = "";
3533
- this.currentIndex = 0;
3534
- this.typewriterSpeed = 1;
3535
- // Default speed
3536
- this._wordWrapWidth = 0;
3537
- this.typewriterOptions = {};
3538
- }
3539
- /**
3540
- * Called when the component is mounted to the scene graph.
3541
- * Initializes the typewriter effect if configured.
3542
- * @param {Element<CanvasText>} element - The element being mounted with parent and props.
3543
- * @param {number} [index] - The index of the component among its siblings.
3544
- */
3545
- async onMount(element, index) {
3546
- const { props } = element;
3547
- await super.onMount(element, index);
3548
- const tick2 = props.context.tick;
3549
- if (props.text && props.typewriter) {
3550
- this.fullText = props.text;
3551
- this.text = "";
3552
- this.currentIndex = 0;
3553
- if (props.typewriter) {
3554
- this.typewriterOptions = props.typewriter;
3555
- if (this.typewriterOptions.skip && isTrigger(this.typewriterOptions.skip)) {
3556
- on(this.typewriterOptions.skip, () => {
3557
- this.skipTypewriter();
3558
- });
3559
- }
3560
- }
3561
- }
3562
- this.subscriptionTick = tick2.observable.subscribe(() => {
3563
- if (props.typewriter) {
3564
- this.typewriterEffect();
3565
- }
3566
- });
3567
- }
3568
- onUpdate(props) {
3569
- super.onUpdate(props);
3570
- if (props.typewriter) {
3571
- if (props.typewriter) {
3572
- this.typewriterOptions = props.typewriter;
3573
- }
3574
- }
3575
- if (props.text !== void 0) {
3576
- this.text = "" + props.text;
3577
- }
3578
- if (props.text !== void 0 && props.text !== this.fullText && this.fullProps.typewriter) {
3579
- this.text = "";
3580
- this.currentIndex = 0;
3581
- this.fullText = props.text;
3582
- }
3583
- if (props.style) {
3584
- for (const key in props.style) {
3585
- this.style[key] = props.style[key];
3586
- }
3587
- if (props.style.wordWrapWidth) {
3588
- this._wordWrapWidth = props.style.wordWrapWidth;
3589
- }
3590
- }
3591
- if (props.color) {
3592
- this.style.fill = props.color;
3593
- }
3594
- if (props.size) {
3595
- this.style.fontSize = props.size;
3596
- }
3597
- if (props.fontFamily) {
3598
- this.style.fontFamily = props.fontFamily;
3599
- }
3600
- if (this._wordWrapWidth) {
3601
- this.setWidth(this._wordWrapWidth);
3602
- } else {
3603
- this.setWidth(this.width);
3604
- }
3605
- this.setHeight(this.height);
3606
- }
3607
- get onCompleteCallback() {
3608
- return this.typewriterOptions.onComplete;
3609
- }
3610
- typewriterEffect() {
3611
- if (this.currentIndex < this.fullText.length) {
3612
- const nextIndex = Math.min(
3613
- this.currentIndex + (this.typewriterOptions.speed ?? 1),
3614
- this.fullText.length
3615
- );
3616
- this.text = this.fullText.slice(0, nextIndex);
3617
- this.currentIndex = nextIndex;
3618
- if (this.currentIndex === this.fullText.length && this.onCompleteCallback) {
3619
- this.onCompleteCallback();
3620
- }
3621
- }
3622
- }
3623
- // Add a method to skip the typewriter effect
3624
- skipTypewriter() {
3625
- if (this.skipSignal) {
3626
- this.skipSignal();
3627
- }
3628
- this.text = this.fullText;
3629
- this.currentIndex = this.fullText.length;
3630
- }
3631
- /**
3632
- * Called when the component is about to be destroyed.
3633
- * Unsubscribes from the tick observable.
3634
- * @param {Element<any>} parent - The parent element.
3635
- * @param {() => void} [afterDestroy] - An optional callback function to be executed after the component's own destruction logic.
3636
- */
3637
- async onDestroy(parent, afterDestroy) {
3638
- const _afterDestroy = async () => {
3639
- if (this.subscriptionTick) {
3640
- this.subscriptionTick.unsubscribe();
3641
- }
3642
- if (afterDestroy) {
3643
- afterDestroy();
3644
- }
3645
- };
3646
- await super.onDestroy(parent, _afterDestroy);
3647
- }
3648
- };
3649
- registerComponent("Text", CanvasText);
3650
- function Text(props) {
3651
- return createComponent("Text", props);
3652
- }
3653
-
3654
- // src/components/TilingSprite.ts
3655
- import { TilingSprite as PixiTilingSprite, Texture as Texture4 } from "pixi.js";
3656
- var CanvasTilingSprite = class extends DisplayObject(PixiTilingSprite) {
3657
- onUpdate(props) {
3658
- super.onUpdate(props);
3659
- if (props.image) {
3660
- this.texture = Texture4.from(props.image);
3661
- }
3662
- if (props.tileScale) {
3663
- this.tileScale.set(props.tileScale.x, props.tileScale.y);
3664
- }
3665
- if (props.tilePosition) {
3666
- this.tilePosition.set(props.tilePosition.x, props.tilePosition.y);
3667
- }
3668
- if (props.width !== void 0) {
3669
- this.width = props.width;
3670
- }
3671
- if (props.height !== void 0) {
3672
- this.height = props.height;
3673
- }
3674
- }
3675
- };
3676
- registerComponent("TilingSprite", CanvasTilingSprite);
3677
- function TilingSprite(props) {
3678
- return createComponent("TilingSprite", props);
3679
- }
3680
-
3681
- // src/components/Viewport.ts
3682
- import { Viewport as PixiViewport } from "pixi-viewport";
3683
- import { effect as effect9 } from "@signe/reactive";
3684
- var EVENTS3 = [
3685
- "bounce-x-end",
3686
- "bounce-x-start",
3687
- "bounce-y-end",
3688
- "bounce-y-start",
3689
- "clicked",
3690
- "drag-end",
3691
- "drag-start",
3692
- "frame-end",
3693
- "mouse-edge-end",
3694
- "mouse-edge-start",
3695
- "moved",
3696
- "moved-end",
3697
- "pinch-end",
3698
- "pinch-start",
3699
- "snap-end",
3700
- "snap-start",
3701
- "snap-zoom-end",
3702
- "snap-zoom-start",
3703
- "wheel-scroll",
3704
- "zoomed",
3705
- "zoomed-end"
3706
- ];
3707
- var CanvasViewport = class extends DisplayObject(PixiViewport) {
3708
- constructor() {
3709
- const defaultOptions = {
3710
- noTicker: true,
3711
- events: {
3712
- domElement: {
3713
- addEventListener: () => {
3714
- }
3715
- }
3716
- }
3717
- };
3718
- super(defaultOptions);
3719
- this.overrideProps = ["wheel"];
3720
- }
3721
- onInit(props) {
3722
- super.onInit(props);
3723
- for (let event of EVENTS3) {
3724
- if (props[event]) this.on(event, props[event]);
3725
- }
3726
- }
3727
- /**
3728
- * Called when the component is mounted to the scene graph.
3729
- * Initializes viewport settings and subscriptions.
3730
- * @param {Element<CanvasViewport>} element - The element being mounted. Its `props` property (of type ViewportProps) contains component properties and context.
3731
- * @param {number} [index] - The index of the component among its siblings.
3732
- */
3733
- async onMount(element, index) {
3734
- await super.onMount(element, index);
3735
- const { props } = element;
3736
- const { tick: tick2, app, canvasSize } = props.context;
3737
- let isDragging = false;
3738
- effect9(() => {
3739
- this.screenWidth = canvasSize().width;
3740
- this.screenHeight = canvasSize().height;
3741
- });
3742
- effect9(() => {
3743
- const _app = app();
3744
- if (!_app) return;
3745
- const renderer = _app.renderer;
3746
- renderer.events.domElement.addEventListener(
3747
- "wheel",
3748
- this.input.wheelFunction
3749
- );
3750
- this.options.events = renderer.events;
3751
- });
3752
- this.tickSubscription = tick2.observable.subscribe(({ value }) => {
3753
- this.update(value.timestamp);
3754
- });
3755
- element.props.context.viewport = this;
3756
- this.updateViewportSettings(props);
3757
- }
3758
- onUpdate(props) {
3759
- super.onUpdate(props);
3760
- this.updateViewportSettings(props);
3761
- }
3762
- updateViewportSettings(props) {
3763
- if (props.screenWidth !== void 0) {
3764
- this.screenWidth = props.screenWidth;
3765
- }
3766
- if (props.screenHeight !== void 0) {
3767
- this.screenHeight = props.screenHeight;
3768
- }
3769
- if (props.worldWidth !== void 0) {
3770
- this.worldWidth = props.worldWidth;
3771
- }
3772
- if (props.worldHeight !== void 0) {
3773
- this.worldHeight = props.worldHeight;
3774
- }
3775
- if (props.drag) {
3776
- this.drag(props.drag);
3777
- }
3778
- if (props.clamp) {
3779
- this.clamp(props.clamp.value ?? props.clamp);
3780
- }
3781
- if (props.wheel) {
3782
- if (props.wheel === true) {
3783
- this.wheel();
3784
- } else {
3785
- this.wheel(props.wheel);
3786
- }
3787
- }
3788
- if (props.decelerate) {
3789
- if (props.decelerate === true) {
3790
- this.decelerate();
3791
- } else {
3792
- this.decelerate(props.decelerate);
3793
- }
3794
- }
3795
- if (props.pinch) {
3796
- if (props.pinch === true) {
3797
- this.pinch();
3798
- } else {
3799
- this.pinch(props.pinch);
3800
- }
3801
- }
3802
- }
3803
- /**
3804
- * Called when the component is about to be destroyed.
3805
- * Unsubscribes from the tick observable.
3806
- * @param {Element<any>} parent - The parent element.
3807
- * @param {() => void} [afterDestroy] - An optional callback function to be executed after the component's own destruction logic.
3808
- */
3809
- async onDestroy(parent, afterDestroy) {
3810
- const _afterDestroy = async () => {
3811
- this.tickSubscription.unsubscribe();
3812
- afterDestroy();
3813
- };
3814
- await super.onDestroy(parent, _afterDestroy);
3815
- }
3816
- };
3817
- registerComponent("Viewport", CanvasViewport);
3818
- function Viewport(props) {
3819
- return createComponent("Viewport", props);
3820
- }
3821
-
3822
- // src/components/NineSliceSprite.ts
3823
- import { Assets as Assets4, NineSliceSprite as PixiNineSliceSprite } from "pixi.js";
3824
- var CanvasNineSliceSprite = class extends DisplayObject(PixiNineSliceSprite) {
3825
- constructor() {
3826
- super({
3827
- width: 0,
3828
- height: 0
3829
- });
3830
- }
3831
- async onUpdate(props) {
3832
- for (const [key, value] of Object.entries(props)) {
3833
- if (value !== void 0) {
3834
- if (key === "image") {
3835
- this.texture = await Assets4.load(value);
3836
- } else if (key in this) {
3837
- this[key] = value;
3838
- }
3839
- }
3840
- }
3841
- }
3842
- };
3843
- registerComponent("NineSliceSprite", CanvasNineSliceSprite);
3844
- function NineSliceSprite(props) {
3845
- return createComponent("NineSliceSprite", props);
3846
- }
3847
-
3848
- // src/components/DOMContainer.ts
3849
- import { DOMContainer as PixiDOMContainer } from "pixi.js";
3850
-
3851
- // src/components/DOMElement.ts
3852
- import { isSignal as isSignal6 } from "@signe/reactive";
3853
- var EVENTS4 = [
3854
- "click",
3855
- "mouseover",
3856
- "mouseout",
3857
- "mouseenter",
3858
- "mouseleave",
3859
- "mousemove",
3860
- "mouseup",
3861
- "mousedown",
3862
- "touchstart",
3863
- "touchend",
3864
- "touchmove",
3865
- "touchcancel",
3866
- "wheel",
3867
- "scroll",
3868
- "resize",
3869
- "focus",
3870
- "blur",
3871
- "change",
3872
- "input",
3873
- "submit",
3874
- "reset",
3875
- "keydown",
3876
- "keyup",
3877
- "keypress",
3878
- "contextmenu",
3879
- "drag",
3880
- "dragend",
3881
- "dragenter",
3882
- "dragleave",
3883
- "dragover",
3884
- "drop",
3885
- "dragstart",
3886
- "select",
3887
- "selectstart",
3888
- "selectend",
3889
- "selectall",
3890
- "selectnone"
3891
- ];
3892
- var CanvasDOMElement = class {
3893
- constructor() {
3894
- this.eventListeners = /* @__PURE__ */ new Map();
3895
- this.onBeforeDestroy = null;
3896
- this.valueSignal = null;
3897
- this.isFormElementType = false;
3898
- }
3899
- /**
3900
- * Checks if the element is a form element that supports the value attribute
3901
- * @param elementType - The element type string from props
3902
- * @returns true if the element is a form element with value support
3903
- */
3904
- isFormElement(elementType) {
3905
- const formElements = ["input", "textarea", "select"];
3906
- return formElements.includes(elementType.toLowerCase());
3907
- }
3908
- onInit(props) {
3909
- if (typeof props.element === "string") {
3910
- this.element = document.createElement(props.element);
3911
- this.isFormElementType = this.isFormElement(props.element);
3912
- } else {
3913
- this.element = props.element.value;
3914
- this.isFormElementType = this.isFormElement(this.element.tagName);
3915
- }
3916
- if (props.onBeforeDestroy || props["on-before-destroy"]) {
3917
- this.onBeforeDestroy = props.onBeforeDestroy || props["on-before-destroy"];
3918
- }
3919
- for (const event of EVENTS4) {
3920
- if (props.attrs?.[event]) {
3921
- const eventHandler = (e) => {
3922
- if (event === "submit" && this.element.tagName.toLowerCase() === "form") {
3923
- e.preventDefault();
3924
- const formData = new FormData(this.element);
3925
- const formObject = {};
3926
- formData.forEach((value, key) => {
3927
- if (formObject[key]) {
3928
- if (Array.isArray(formObject[key])) {
3929
- formObject[key].push(value);
3930
- } else {
3931
- formObject[key] = [formObject[key], value];
3932
- }
3933
- } else {
3934
- formObject[key] = value;
3935
- }
3936
- });
3937
- props.attrs[event]?.(e, formObject);
3938
- } else {
3939
- props.attrs[event]?.(e);
3940
- }
3941
- };
3942
- this.eventListeners.set(event, eventHandler);
3943
- this.element.addEventListener(event, eventHandler, false);
3944
- }
3945
- }
3946
- if (props.children) {
3947
- for (const child of props.children) {
3948
- if (isObservable(child)) {
3949
- child.subscribe(({ elements }) => {
3950
- for (const element of elements) {
3951
- this.element.appendChild(element.componentInstance.element);
3952
- }
3953
- });
3954
- } else {
3955
- this.element.appendChild(child.componentInstance.element);
3956
- }
3957
- }
3958
- }
3959
- this.onUpdate(props);
3960
- }
3961
- onMount(context) {
3962
- const props = context.propObservables;
3963
- const attrs = props.attrs;
3964
- if (this.isFormElementType && attrs?.value && isSignal6(attrs.value)) {
3965
- this.valueSignal = attrs.value;
3966
- this.element.value = this.valueSignal();
3967
- const inputHandler = (e) => {
3968
- const target = e.target;
3969
- this.valueSignal.set(target.value);
3970
- };
3971
- this.eventListeners.set("input", inputHandler);
3972
- this.element.addEventListener("input", inputHandler, false);
3973
- }
3974
- }
3975
- onUpdate(props) {
3976
- if (!this.element) return;
3977
- for (const [key, value] of Object.entries(props.attrs || {})) {
3978
- if (key === "class") {
3979
- const classList = value.items || value.value || value;
3980
- this.element.className = "";
3981
- if (typeof classList === "string") {
3982
- this.element.className = classList;
3983
- } else if (Array.isArray(classList)) {
3984
- this.element.classList.add(...classList);
3985
- } else if (typeof classList === "object" && classList !== null) {
3986
- for (const [className, shouldAdd] of Object.entries(classList)) {
3987
- if (shouldAdd) {
3988
- this.element.classList.add(className);
3989
- }
3990
- }
3991
- }
3992
- } else if (key === "style") {
3993
- const styleValue = value.items || value.value || value;
3994
- if (typeof styleValue === "string") {
3995
- this.element.setAttribute("style", styleValue);
3996
- } else if (typeof styleValue === "object" && styleValue !== null) {
3997
- for (const [styleProp, styleVal] of Object.entries(styleValue)) {
3998
- if (styleVal !== null && styleVal !== void 0) {
3999
- this.element.style[styleProp] = styleVal;
4000
- }
4001
- }
4002
- }
4003
- } else if (key === "value" && this.isFormElementType) {
4004
- if (isSignal6(value)) {
4005
- const currentValue = this.element.value;
4006
- const signalValue = value();
4007
- if (currentValue !== signalValue) {
4008
- this.element.value = signalValue;
4009
- }
4010
- } else {
4011
- this.element.value = value;
4012
- }
4013
- } else if (!EVENTS4.includes(key)) {
4014
- this.element.setAttribute(key, value);
4015
- }
4016
- }
4017
- if (props.textContent) {
4018
- this.element.textContent = props.textContent;
4019
- }
4020
- }
4021
- async onDestroy(parent, afterDestroy) {
4022
- if (this.element) {
4023
- if (this.onBeforeDestroy) {
4024
- await this.onBeforeDestroy();
4025
- }
4026
- for (const [event, handler] of this.eventListeners) {
4027
- this.element.removeEventListener(event, handler, false);
4028
- }
4029
- this.eventListeners.clear();
4030
- this.element.remove();
4031
- if (afterDestroy) {
4032
- afterDestroy();
4033
- }
4034
- }
4035
- }
4036
- };
4037
- registerComponent("DOMElement", CanvasDOMElement);
4038
- var DOMElement = (props) => {
4039
- return createComponent("DOMElement", props);
4040
- };
4041
-
4042
- // src/components/DOMContainer.ts
4043
- var CanvasDOMContainer = class extends DisplayObject(PixiDOMContainer) {
4044
- constructor() {
4045
- super(...arguments);
4046
- this.disableLayout = true;
4047
- }
4048
- onInit(props) {
4049
- const div = h(DOMElement, { element: "div" }, props.children);
4050
- this.element = div.componentInstance.element;
4051
- }
4052
- };
4053
- registerComponent("DOMContainer", CanvasDOMContainer);
4054
- var DOMContainer = (props) => {
4055
- return createComponent("DOMContainer", props);
4056
- };
4057
-
4058
- // src/engine/bootstrap.ts
4059
- import "@pixi/layout";
4060
- import { Application as Application3 } from "pixi.js";
4061
- var bootstrapCanvas = async (rootElement, canvas, options) => {
4062
- const app = new Application3();
4063
- await app.init({
4064
- resizeTo: rootElement,
4065
- autoStart: false,
4066
- ...options ?? {}
4067
- });
4068
- const canvasElement = await h(canvas);
4069
- if (canvasElement.tag != "Canvas") {
4070
- throw new Error("Canvas is required");
4071
- }
4072
- canvasElement.render(rootElement, app);
4073
- const { backgroundColor } = useProps(canvasElement.props, {
4074
- backgroundColor: "black"
4075
- });
4076
- app.renderer.background.color = backgroundColor();
4077
- return {
4078
- canvasElement,
4079
- app
4080
- };
4081
- };
4082
-
4083
- // src/utils/Ease.ts
4084
- import {
4085
- linear,
4086
- easeIn,
4087
- easeInOut,
4088
- easeOut,
4089
- circIn,
4090
- circInOut,
4091
- circOut,
4092
- backIn,
4093
- backInOut,
4094
- backOut,
4095
- anticipate,
4096
- bounceIn,
4097
- bounceInOut,
4098
- bounceOut
4099
- } from "popmotion";
4100
- var Easing = {
4101
- linear,
4102
- easeIn,
4103
- easeInOut,
4104
- easeOut,
4105
- circIn,
4106
- circInOut,
4107
- circOut,
4108
- backIn,
4109
- backInOut,
4110
- backOut,
4111
- anticipate,
4112
- bounceIn,
4113
- bounceInOut,
4114
- bounceOut
4115
- };
4116
-
4117
- // src/utils/RadialGradient.ts
4118
- import { Texture as Texture6, ImageSource, DOMAdapter, Matrix } from "pixi.js";
4119
- var RadialGradient = class {
4120
- /**
4121
- * Creates a new RadialGradient instance
4122
- * @param x0 - The x-coordinate of the starting circle
4123
- * @param y0 - The y-coordinate of the starting circle
4124
- * @param x1 - The x-coordinate of the ending circle
4125
- * @param y1 - The y-coordinate of the ending circle
4126
- * @param x2 - The x-coordinate for gradient transformation
4127
- * @param y2 - The y-coordinate for gradient transformation
4128
- * @param focalPoint - The focal point of the gradient (0-1), defaults to 0
4129
- */
4130
- constructor(x0, y0, x1, y1, x2, y2, focalPoint = 0) {
4131
- this.x0 = x0;
4132
- this.y0 = y0;
4133
- this.x1 = x1;
4134
- this.y1 = y1;
4135
- this.x2 = x2;
4136
- this.y2 = y2;
4137
- this.focalPoint = focalPoint;
4138
- this.gradient = null;
4139
- this.texture = null;
4140
- this.size = 600;
4141
- this.size = x0;
4142
- const halfSize = this.size * 0.5;
4143
- this.canvas = DOMAdapter.get().createCanvas();
4144
- this.canvas.width = this.size;
4145
- this.canvas.height = this.size;
4146
- this.ctx = this.canvas.getContext("2d");
4147
- if (this.ctx) {
4148
- this.gradient = this.ctx.createRadialGradient(
4149
- halfSize * (1 - focalPoint),
4150
- halfSize,
4151
- 0,
4152
- halfSize,
4153
- halfSize,
4154
- halfSize - 0.5
4155
- );
4156
- }
4157
- }
4158
- /**
4159
- * Adds a color stop to the gradient
4160
- * @param offset - The position of the color stop (0-1)
4161
- * @param color - The color value (any valid CSS color string)
4162
- */
4163
- addColorStop(offset, color) {
4164
- if (this.gradient) {
4165
- this.gradient.addColorStop(offset, color);
4166
- }
4167
- }
4168
- /**
4169
- * Renders the gradient and returns the texture with its transformation matrix
4170
- * @param options - Render options
4171
- * @param options.translate - Optional translation coordinates
4172
- * @returns Object containing the texture and transformation matrix
4173
- */
4174
- render({ translate } = {}) {
4175
- const { x0, y0, x1, y1, x2, y2, focalPoint } = this;
4176
- const defaultSize = this.size;
4177
- if (this.ctx && this.gradient) {
4178
- this.ctx.fillStyle = this.gradient;
4179
- this.ctx.fillRect(0, 0, defaultSize, defaultSize);
4180
- this.texture = new Texture6({
4181
- source: new ImageSource({
4182
- resource: this.canvas,
4183
- addressModeU: "clamp-to-edge",
4184
- addressModeV: "clamp-to-edge"
4185
- })
4186
- });
4187
- const m = new Matrix();
4188
- const dx = Math.sqrt((x1 - x0) * (x1 - x0) + (y1 - y0) * (y1 - y0));
4189
- const dy = Math.sqrt((x2 - x0) * (x2 - x0) + (y2 - y0) * (y2 - y0));
4190
- const angle = Math.atan2(y1 - y0, x1 - x0);
4191
- const scaleX = dx / defaultSize;
4192
- const scaleY = dy / defaultSize;
4193
- m.rotate(-angle);
4194
- m.scale(scaleX, scaleY);
4195
- if (translate) {
4196
- m.translate(translate.x, translate.y);
4197
- }
4198
- this.transform = m;
4199
- }
4200
- return {
4201
- texture: this.texture,
4202
- matrix: this.transform
4203
- };
4204
- }
4205
- };
4206
-
4207
- // src/index.ts
4208
- import { isObservable as isObservable2 } from "rxjs";
4209
- import * as Howl3 from "howler";
4210
- export {
4211
- Canvas2 as Canvas,
4212
- Circle,
4213
- Container4 as Container,
4214
- DOMContainer,
4215
- DOMElement,
4216
- DisplayObject,
4217
- EVENTS2 as EVENTS,
4218
- Easing,
4219
- Ellipse,
4220
- Graphics,
4221
- Howl3 as Howl,
4222
- Howler,
4223
- Mesh,
4224
- NineSliceSprite,
4225
- ParticlesEmitter,
4226
- RadialGradient,
4227
- Rect,
4228
- Scene,
4229
- Sprite2 as Sprite,
4230
- Svg,
4231
- Text,
4232
- TilingSprite,
4233
- Triangle,
4234
- utils_exports as Utils,
4235
- Video,
4236
- Viewport,
4237
- animatedSequence,
4238
- animatedSignal,
4239
- bootstrapCanvas,
4240
- cond,
4241
- createComponent,
4242
- currentSubscriptionsTracker,
4243
- h,
4244
- isAnimatedSignal,
4245
- isElement,
4246
- isObservable2 as isObservable,
4247
- isPrimitive,
4248
- isTrigger,
4249
- loop,
4250
- mount,
4251
- mountTracker,
4252
- on,
4253
- registerComponent,
4254
- tick,
4255
- trigger,
4256
- useDefineProps,
4257
- useProps
4258
- };
1
+ var dt=Object.defineProperty;var Fe=r=>{throw TypeError(r)};var ht=(r,n)=>{for(var e in n)dt(r,e,{get:n[e],enumerable:!0})};var Re=(r,n,e)=>n.has(r)||Fe("Cannot "+e);var q=(r,n,e)=>(Re(r,n,"read from private field"),e?e.call(r):n.get(r)),He=(r,n,e)=>n.has(r)?Fe("Cannot add the same private member more than once"):n instanceof WeakSet?n.add(r):n.set(r,e),Le=(r,n,e,i)=>(Re(r,n,"write to private field"),i?i.call(r,e):n.set(r,e),e);var G={},x=class{};function S(r,n){G[r]=n}function je(r,n){if(!G[n])return null;let e=new G[n];return e.onInit?.(r),e}var Q={};ht(Q,{arrayEquals:()=>H,calculateDistance:()=>J,error:()=>L,fps2ms:()=>D,get:()=>gt,isBrowser:()=>I,isFunction:()=>X,isObject:()=>Y,isObservable:()=>$,isPromise:()=>R,log:()=>bt,preciseNow:()=>k,set:()=>B,setObservablePoint:()=>C});import{Observable as pt}from"rxjs";function I(){return typeof window<"u"}function k(){return typeof performance<"u"?performance.now():Date.now()}function D(r){return 1e3/r}function R(r){return r&&r instanceof Promise}function H(r,n){if(r.length!==n.length)return!1;for(let e=0;e<r.length;e++){let i=r[e],s=n[e];if(typeof i=="object"&&i!==null){if(typeof s!="object"||s===null)return!1;if(Array.isArray(i)){if(!Array.isArray(s)||!H(i,s))return!1}else if(!We(i,s))return!1}else if(i!==s)return!1}return!0}function We(r,n){let e=Object.keys(r),i=Object.keys(n);if(e.length!==i.length)return!1;for(let s of e)if(!n.hasOwnProperty(s)||!yt(r[s],n[s]))return!1;return!0}function yt(r,n){return r===n?!0:typeof r!=typeof n?!1:typeof r=="object"&&r!==null?Array.isArray(r)?Array.isArray(n)&&H(r,n):We(r,n):!1}function X(r){return{}.toString.call(r)==="[object Function]"}function Y(r){return typeof r=="object"&&r!=null&&!Array.isArray(r)&&r.constructor===Object}function $(r){return r instanceof pt}function B(r,n,e,i=!1){if(Object(r)!==r)return r;typeof n=="string"&&(n=n.split("."));let s=n.length;if(!s)return r;let t=r;for(let a=0;a<s-1;a++){let l=n[a],o=n[a+1],c=!isNaN(Number(o))&&isFinite(Number(o));(!t[l]||typeof t[l]!="object")&&(t[l]=c&&!i?[]:{}),t=t[l]}return t[n[s-1]]=e,r}function gt(r,n){let e=n.split("."),i=r;for(let s of e){if(i[s]===void 0)return;i=i[s]}return i}function bt(r){console.log(r)}function L(r){console.error(r)}function C(r,n){typeof n=="number"?r.set(n):Array.isArray(n)?r.set(n[0],n[1]):r.set(n.x,n.y)}function J(r,n,e,i){let s=r-e,t=n-i;return Math.sqrt(s*s+t*t)}var Ue={3:"break",8:"backspace",9:"tab",12:"clear",13:"enter",16:"shift",17:"ctrl",18:"alt",19:"pause/break",20:"caps lock",27:"escape",28:"conversion",29:"non-conversion",32:"space",33:"page up",34:"page down",35:"end",36:"home",37:"left",38:"up",39:"right",40:"down",41:"select",42:"print",43:"execute",44:"Print Screen",45:"insert",46:"delete",48:"n0",49:"n1",50:"n2",51:"n3",52:"n4",53:"n5",54:"n6",55:"n7",56:"n8",57:"n9",58:":",59:"semicolon (firefox), equals",60:"<",61:"equals (firefox)",63:"\xDF",64:"@",65:"a",66:"b",67:"c",68:"d",69:"e",70:"f",71:"g",72:"h",73:"i",74:"j",75:"k",76:"l",77:"m",78:"n",79:"o",80:"p",81:"q",82:"r",83:"s",84:"t",85:"u",86:"v",87:"w",88:"x",89:"y",90:"z",91:"Windows Key / Left \u2318 / Chromebook Search key",92:"right window key",93:"Windows Menu / Right \u2318",96:"numpad 0",97:"numpad 1",98:"numpad 2",99:"numpad 3",100:"numpad 4",101:"numpad 5",102:"numpad 6",103:"numpad 7",104:"numpad 8",105:"numpad 9",106:"multiply",107:"add",108:"numpad period (firefox)",109:"subtract",110:"decimal point",111:"divide",112:"f1",113:"f2",114:"f3",115:"f4",116:"f5",117:"f6",118:"f7",119:"f8",120:"f9",121:"f10",122:"f11",123:"f12",124:"f13",125:"f14",126:"f15",127:"f16",128:"f17",129:"f18",130:"f19",131:"f20",132:"f21",133:"f22",134:"f23",135:"f24",144:"num lock",145:"scroll lock",160:"^",161:"!",163:"#",164:"$",165:"\xF9",166:"page backward",167:"page forward",169:"closing paren (AZERTY)",170:"*",171:"~ + * key",173:"minus (firefox), mute/unmute",174:"decrease volume level",175:"increase volume level",176:"next",177:"previous",178:"stop",179:"play/pause",180:"e-mail",181:"mute/unmute (firefox)",182:"decrease volume level (firefox)",183:"increase volume level (firefox)",186:"semi-colon / \xF1",187:"equal sign",188:"comma",189:"dash",190:"period",191:"forward slash / \xE7",192:"grave accent / \xF1 / \xE6",193:"?, / or \xB0",194:"numpad period (chrome)",219:"open bracket",220:"back slash",221:"close bracket / \xE5",222:"single quote / \xF8",223:"`",224:"left or right \u2318 key (firefox)",225:"altgr",226:"< /git >",230:"GNOME Compose Key",231:"\xE7",233:"XF86Forward",234:"XF86Back",240:"alphanumeric",242:"hiragana/katakana",243:"half-width/full-width",244:"kanji",255:"toggle touchpad"},vt=r=>{let n={};for(let e in r){let i=r[e];n[i]=e}return n},Ke=vt(Ue),Z=class extends x{constructor(){super(...arguments);this.keyState={};this.boundKeys={};this.stop=!1;this.lastKeyPressed=null;this._controlsOptions={};this.serverFps=60;this.directionState={up:!1,down:!1,left:!1,right:!1}}onInit(e){let i=e.props.controls.value??e.props.controls;i&&(this.setupListeners(),this.setInputs(i),this.interval=setInterval(()=>{this.preStep()},D(this.serverFps??60)))}onMount(e){}onUpdate(e){this.setInputs(e)}onDestroy(){clearInterval(this.interval),document.removeEventListener("keydown",e=>{this.onKeyChange(e,!0)}),document.removeEventListener("keyup",e=>{this.onKeyChange(e,!1)})}preStep(){if(this.stop)return;let e=this.getDirection();if(e!=="none"){let i=this.boundKeys[e];if(i){let{keyDown:s}=i.options;s&&this.applyInput(e)}}else{let i=Object.keys(this.boundKeys);for(let s of i)this.applyInput(s)}}applyInput(e){let i=this.keyState[e];if(!i)return;let{isDown:s,count:t}=i;if(s){let{repeat:a,keyDown:l}=this.boundKeys[e].options;if(a||t==0){let o=this.boundKeys[e].parameters;typeof o=="function"&&(o=o()),l&&l(this.boundKeys[e]),this.keyState[e].count++}}}setupListeners(){document.addEventListener("keydown",e=>{this.onKeyChange(e,!0)}),document.addEventListener("keyup",e=>{this.onKeyChange(e,!1)})}bindKey(e,i,s,t){Array.isArray(e)||(e=[e]);let a=Object.assign({repeat:!1},s);e.forEach(l=>{this.boundKeys[l]={actionName:i,options:a,parameters:t}})}applyKeyDown(e){let i=Ke[e],s=new Event("keydown");s.keyCode=i,this.onKeyChange(s,!0)}applyKeyUp(e){let i=Ke[e],s=new Event("keyup");s.keyCode=i,this.onKeyChange(s,!1)}applyKeyPress(e){return new Promise(i=>{this.applyKeyDown(e),setTimeout(()=>{this.applyKeyUp(e),i()},200)})}onKeyChange(e,i){e=e||window.event;let s=Ue[e.keyCode];if(s&&this.boundKeys[s]){if(this.keyState[s]==null&&(this.keyState[s]={count:0,isDown:!0}),this.keyState[s].isDown=i,!i){this.keyState[s].count=0;let{keyUp:t}=this.boundKeys[s].options;t&&t(this.boundKeys[s])}this.lastKeyPressed=i?e.keyCode:null}s&&this.updateDirectionState(s,i)}updateDirectionState(e,i){switch(e){case"up":this.directionState.up=i;break;case"down":this.directionState.down=i;break;case"left":this.directionState.left=i;break;case"right":this.directionState.right=i;break}}getDirection(){let{up:e,down:i,left:s,right:t}=this.directionState;return e&&s?"up_left":e&&t?"up_right":i&&s?"down_left":i&&t?"down_right":e?"up":i?"down":s?"left":t?"right":"none"}getControl(e){return this.boundKeys[e]}getControls(){return this.boundKeys}async applyControl(e,i){let s=this._controlsOptions[e];if(s){let t=Array.isArray(s.bind)?s.bind[0]:s.bind;i===void 0?await this.applyKeyPress(t):i?this.applyKeyDown(t):this.applyKeyUp(t)}}stopInputs(){this.stop=!0}listenInputs(){this.stop=!1,this.keyState={}}setInputs(e){if(!e)return;this.boundKeys={};let i={};for(let s in e){let t=e[s],{bind:a}=t,l=a;Array.isArray(l)||(l=[a]);for(let o of l)this.bindKey(o,s,t)}this._controlsOptions=e}get options(){return this._controlsOptions}};S("controls",Z);var ee=class extends x{constructor(){super(...arguments);this.fps=60;this.deltaTime=0;this.frame=0;this.timestamp=0;this.requestedDelay=0;this.lastTimestamp=0;this._stop=!1}onInit(e){this.tick=e.propObservables?.tick}onDestroy(){}onMount(e){}onUpdate(e){}nextTick(e){this.lastTimestamp=this.lastTimestamp||this.timestamp,this.deltaTime=k()-this.timestamp,this.timestamp=e,this.tick.set({timestamp:this.timestamp,deltaTime:this.deltaTime,frame:this.frame,deltaRatio:~~this.deltaTime/~~D(this.fps)}),this.lastTimestamp=this.timestamp,this.frame++}start(e={}){e.maxFps&&(this.maxFps=e.maxFps),e.fps&&(this.fps=e.fps),e.delay&&(this.requestedDelay=e.delay);let i=s=>{I()?window.requestAnimationFrame(s.bind(this)):setTimeout(()=>{this.requestedDelay=0,s(k())},D(this.fps)+this.requestedDelay)};if(this.maxFps){let s=D(this.maxFps),t=k(),a=k(),l=o=>{if(this._stop)return;i(l),t=k();let c=t-a;c>s&&(a=t-c%s,this.nextTick(o))};i(l)}else{let s=t=>{i(s),this.nextTick(t)};i(s)}return this}stop(){this._stop=!0}};S("tick",ee);import{isSignal as z,signal as se}from"@signe/reactive";import{isComputed as xt,isSignal as _,signal as Ne}from"@signe/reactive";import{Observable as ie,Subject as Be,defer as wt,from as _e,map as Pt,of as ze,share as St}from"rxjs";var te={},W=r=>r&&typeof r=="object"&&"tag"in r&&"props"in r&&"componentInstance"in r,ne=r=>typeof r=="string"||typeof r=="number"||typeof r=="boolean"||r===null||r===void 0;function y(r,n){te[r]=n}function j(r){if(Array.isArray(r)){r.forEach(n=>j(n));return}if(r){if(r.props?.children)for(let n of r.props.children)j(n);for(let n in r.directives)r.directives[n].onDestroy?.(r);r.componentInstance&&r.componentInstance.onDestroy?r.componentInstance.onDestroy(r.parent,()=>{r.propSubscriptions?.forEach(n=>n.unsubscribe()),r.effectSubscriptions?.forEach(n=>n.unsubscribe()),r.effectUnmounts?.forEach(n=>n?.())}):(r.propSubscriptions?.forEach(n=>n.unsubscribe()),r.effectSubscriptions?.forEach(n=>n.unsubscribe()),r.effectUnmounts?.forEach(n=>n?.()))}}function g(r,n){if(!te[r])throw new Error(`Component ${r} is not registered`);let e=new te[r],i={tag:r,props:{},componentInstance:e,propSubscriptions:[],propObservables:n,parent:null,directives:{},effectUnmounts:[],effectSubscriptions:[],effectMounts:[],destroy(){j(this)},allElements:new Be};if(n){let o=(c,f="")=>{let m=(u,d,h)=>{if(u==""){i.props[d]=h;return}B(i.props,u+"."+d,h)};Object.entries(c).forEach(([u,d])=>{if(_(d)){let h=d;if("dependencies"in h&&h.dependencies.size==0){m(f,u,h());return}i.propSubscriptions.push(h.observable.subscribe(p=>{m(f,u,p),i.directives[u]&&i.directives[u].onUpdate?.(p,i),u!="tick"&&e.onUpdate?.(f==""?{[u]:p}:B({},f+"."+u,p))}))}else Y(d)&&u!="context"&&!W(d)?o(d,(f?f+".":"")+u):m(f,u,d)})};o(n)}e.onInit?.(i.props);let s=new Be;if(n?.isRoot&&(i.allElements=s,i.props.context.rootElement=i,i.componentInstance.onMount?.(i),a(i)),n)for(let o in n){let c=je(i,o);c&&(i.directives[o]=c)}function t(o,c,f){c.props.context=o.props.context,c.parent=o,c.componentInstance.onMount?.(c,f);for(let m in c.directives)c.directives[m].onMount?.(c);c.effectMounts.forEach(m=>{c.effectUnmounts.push(m(c))})}async function a(o){if(o.props.attach&&(_(o.propObservables?.attach)?await new Promise(f=>{let m=null;o.propSubscriptions.push(o.propObservables.attach.observable.subscribe(async u=>{let d=u?.value??u;if(!d)throw new Error(`attach in ${o.tag} is undefined or null, add a component`);m&&j(m),m=d,await l(o,d),f(void 0)}))}):o.props.children.push(o.props.attach)),!!o.props.children)for(let c of o.props.children)c&&await l(o,c)}async function l(o,c){R(c)&&(c=await c),c instanceof ie?c.subscribe(({elements:f,prev:m})=>{let u=f.filter(d=>d!==null);if(m){u.forEach(d=>{let h=o.props.children.indexOf(m.props.key);t(o,d,h+1),a(d)});return}u.forEach(d=>{Array.isArray(d)?d.forEach(h=>{t(o,h),a(h)}):(t(o,d),a(d))}),s.next(void 0)}):(t(o,c),await a(c))}return i}function fn(r,n){return xt(r)&&r.dependencies.size==0?r=Ne(r()):_(r)||(r=Ne(r)),wt(()=>{let e=[],i=new Map,s=!0,t=a=>Array.isArray(a());return new ie(a=>t(r)?r.observable.subscribe(o=>{if(s){s=!1,e.forEach(f=>f.destroy()),e=[],i.clear();let c=r();c&&c.forEach((f,m)=>{let u=n(f,m);u&&(e.push(u),i.set(m,u))}),a.next({elements:[...e]});return}if(o.type==="init"||o.type==="reset"){e.forEach(f=>f.destroy()),e=[],i.clear();let c=r();c&&c.forEach((f,m)=>{let u=n(f,m);u&&(e.push(u),i.set(m,u))})}else if(o.type==="add"&&o.index!==void 0){let c=o.items.map((f,m)=>{let u=n(f,o.index+m);return u&&i.set(o.index+m,u),u}).filter(f=>f!==null);e.splice(o.index,0,...c)}else if(o.type==="remove"&&o.index!==void 0)e.splice(o.index,1).forEach(f=>{f.destroy(),i.delete(o.index)});else if(o.type==="update"&&o.index!==void 0&&o.items.length===1){let c=o.index,f=o.items[0];if(c>=e.length||e[c]===void 0||!i.has(c)){let m=n(f,c);m?(e.splice(c,0,m),i.set(c,m)):console.warn(`Element creation returned null for index ${c} during add-like update.`)}else{e[c].destroy();let u=n(f,c);u?(e[c]=u,i.set(c,u)):(e.splice(c,1),i.delete(c))}}a.next({elements:[...e]})}):r.observable.subscribe(o=>{let c=o.key;if(s){s=!1,e.forEach(m=>m.destroy()),e=[],i.clear();let f=r();f&&Object.entries(f).forEach(([m,u])=>{let d=n(u,m);d&&(e.push(d),i.set(m,d))}),a.next({elements:[...e]});return}if(o.type==="init"||o.type==="reset"){e.forEach(m=>m.destroy()),e=[],i.clear();let f=r();f&&Object.entries(f).forEach(([m,u])=>{let d=n(u,m);d&&(e.push(d),i.set(m,d))})}else if(o.type==="add"&&o.key&&o.value!==void 0){let f=n(o.value,c);f&&(e.push(f),i.set(c,f))}else if(o.type==="remove"&&o.key){let f=e.findIndex(m=>i.get(c)===m);if(f!==-1){let[m]=e.splice(f,1);m.destroy(),i.delete(c)}}else if(o.type==="update"&&o.key&&o.value!==void 0){let f=e.findIndex(m=>i.get(c)===m);if(f!==-1){e[f].destroy();let u=n(o.value,c);u&&(e[f]=u,i.set(c,u))}}a.next({elements:[...e]})}))})}function mn(r,n){let e=null;if(_(r)){let i=r;return new ie(s=>i.observable.subscribe(t=>{if(t){let a=n();R(a)?_e(a).subscribe(l=>{e=l,s.next({type:"init",elements:[l]})}):(e=a,s.next({type:"init",elements:[e]}))}else e?(j(e),s.next({elements:[]})):s.next({elements:[]})})).pipe(St())}else{if(r){let i=n();return R(i)?_e(i).pipe(Pt(s=>({type:"init",elements:[s]}))):ze({type:"init",elements:[i]})}return ze({elements:[]})}}var w=(r,n={})=>{if(z(r))return r();let e={};for(let i in r){let s=r[i];e[i]=ne(s)?se(s):s}for(let i in n)i in e||(e[i]=ne(n[i])?se(n[i]):n[i]);return e},oe=r=>n=>{let e=z(r)?r():r,i={};for(let s in n){let t=n[s],a=e[s],l;if(typeof t=="function")re(s,a,[t]),l=a;else if(Array.isArray(t))re(s,a,t),l=a;else if(t&&typeof t=="object"){if(t.required&&a===void 0)throw new Error(`Missing required prop: ${s}`);if(t.type){let o=Array.isArray(t.type)?t.type:[t.type];re(s,a,o)}if(t.validator&&!t.validator(a,e))throw new Error(`Invalid prop: custom validation failed for prop "${s}"`);a===void 0&&"default"in t?l=typeof t.default=="function"?t.default(e):t.default:l=a}i[s]=z(l)?l:se(l)}return{...w(e),...i}};function re(r,n,e){if(n==null)return;let i=z(n)?n():n;if(!e.some(t=>t===Number?typeof i=="number":t===String?typeof i=="string":t===Boolean?typeof i=="boolean":t===Function?typeof i=="function":t===Object?typeof i=="object":t===Array?Array.isArray(i):t===null?i===null:i instanceof t))throw new Error(`Invalid prop: type check failed for prop "${r}". Expected ${e.map(t=>t.name).join(" or ")}`)}var ae=class extends x{onInit(n){}onMount(n){this.onUpdate(n.props.viewportFollow,n)}onUpdate(n,e){let{viewport:i}=e.props.context;if(!i)throw L("ViewportFollow directive requires a Viewport component to be mounted in the same context");if(n)if(n===!0)i.follow(e.componentInstance);else{let s=w(n,{speed:void 0,acceleration:void 0,radius:void 0});i.follow(e.componentInstance,{speed:s.speed(),acceleration:s.acceleration(),radius:s.radius()})}else n===null&&i.plugins.remove("follow")}onDestroy(n){let{viewportFollow:e}=n.props,{viewport:i}=n.props.context;e&&i.plugins.remove("follow")}};S("viewportFollow",ae);import{effect as Et}from"@signe/reactive";import{Howl as Tt}from"howler";var Ve=["load","loaderror","playerror","play","end","pause","stop","mute","volume","rate","seek","fade","unlock"],le=class extends x{constructor(){super(...arguments);this.sounds=[];this.eventsFn=[];this.maxVolume=1;this.maxDistance=100}onInit(e){}onMount(e){let{props:i}=e,s=i.context.tick,t=i.sound.value??i.sound;if(!t.src)return;let{src:a,autoplay:l,loop:o,volume:c,spatial:f}=t,m=Array.isArray(a)?a:[a];for(let u of m){if(!u)continue;let d=new Tt({src:u,autoplay:l,loop:o,volume:c});for(let h of Ve){if(!t[h])continue;let p=t[h];this.eventsFn.push(p),d.on(h,p)}this.sounds.push(d)}if(f&&this.sounds.length>0){let{soundListenerPosition:u}=i.context;if(!u)throw new L("SoundListenerPosition directive is required for spatial sound in component parent");let{x:d,y:h}=u;this.tickSubscription=Et(()=>{s();let{x:p,y:P}=e.componentInstance,E=J(p,P,d(),h()),v=Math.max(this.maxVolume-E/this.maxDistance,0);this.sounds.forEach(T=>T.volume(v))}).subscription}this.onUpdate(t)}onUpdate(e){let i=e.value??e,{volume:s,loop:t,mute:a,seek:l,playing:o,rate:c,spatial:f}=i;this.sounds.forEach(m=>{s!==void 0&&m.volume(s),t!==void 0&&m.loop(t),a!==void 0&&m.mute(a),l!==void 0&&m.seek(l),o!==void 0&&(o?m.play():m.pause()),c!==void 0&&m.rate(c)}),f&&(this.maxVolume=f.maxVolume??this.maxVolume,this.maxDistance=f.maxDistance??this.maxDistance)}onDestroy(){this.sounds.forEach(e=>{e.stop();for(let i of Ve){let s=this.eventsFn.find(t=>t===this.eventsFn[i]);s&&e.off(i,s)}}),this.sounds=[],this.eventsFn=[],this.tickSubscription?.unsubscribe()}},ce=class extends x{onMount(n){n.props.context.soundListenerPosition=n.propObservables?.soundListenerPosition}onInit(n){}onUpdate(n){}onDestroy(){}};S("sound",le);S("soundListenerPosition",ce);import{effect as Ct,isComputed as Ot,isSignal as kt}from"@signe/reactive";import{Rectangle as Dt,Point as Ge}from"pixi.js";import{snap as Mt}from"popmotion";var qe=(r,n,e)=>{r.props.context={...r.props.context??{},[n]:e}};var fe=class extends x{constructor(){super(...arguments);this.elementRef=null}onInit(e){this.elementRef=e}onMount(e){qe(e,"drop",e)}onUpdate(){}onDestroy(){this.elementRef=null}},me=class extends x{constructor(){super(...arguments);this.elementRef=null;this.stageRef=null;this.offsetInParent=new Ge;this.isDragging=!1;this.viewport=null;this.animationFrameId=null;this.lastPointerPosition=new Ge;this.pressedKeys=new Set;this.pointerIsDown=!1;this.onDragMoveHandler=()=>{};this.onDragEndHandler=()=>{};this.onDragStartHandler=()=>{};this.onKeyDownHandler=()=>{};this.onKeyUpHandler=()=>{};this.subscriptions=[]}onInit(e){this.elementRef=e,this.onDragMoveHandler=this.onDragMove.bind(this),this.onDragEndHandler=this.onDragEnd.bind(this),this.onDragStartHandler=this.onPointerDown.bind(this),this.onKeyDownHandler=this.onKeyDown.bind(this),this.onKeyUpHandler=this.onKeyUp.bind(this)}onMount(e){let{rootElement:i,canvasSize:s,viewport:t,tick:a}=e.props.context,l=e.componentInstance,o=this.dragProps;if(Object.keys(o).length===0){this.onDestroy();return}if(!l||(this.stageRef=i.componentInstance,!this.stageRef))return;this.viewport=t,l.eventMode="static",this.stageRef.eventMode="static";let f=Ct(()=>{this.stageRef&&(this.stageRef.hitArea=new Dt(0,0,s().width,s().height))});l.on("pointerdown",this.onDragStartHandler),this.stageRef.on("pointerup",this.onDragEndHandler),this.stageRef.on("pointerupoutside",this.onDragEndHandler);let m=o.keyToPress?o.keyToPress:[];window.addEventListener("keydown",this.onKeyDownHandler),window.addEventListener("keyup",this.onKeyUpHandler),this.subscriptions=[a.observable.subscribe(()=>{this.isDragging&&this.viewport&&this.updateViewportPosition(this.lastPointerPosition)}),f.subscription]}get dragProps(){let e=this.elementRef?.props.drag,i=w(e?.value??e,{snap:0,viewport:{},direction:"all",keyToPress:[]});return i.viewport=w(i.viewport,{edgeThreshold:300,maxSpeed:40}),i}get axis(){let e=this.dragProps.direction(),i={x:!0,y:!0};return e==="x"&&(i.y=!1),e==="y"&&(i.x=!1),i}onDragMove(e){if(!this.isDragging||!this.elementRef?.componentInstance||!this.elementRef.componentInstance.parent)return;let i=this.elementRef.componentInstance,s=i.parent,t=this.dragProps,a=this.elementRef.propObservables,l=Mt(t?.snap()??0);t?.move?.(e);let o=s.toLocal(e.global),c=o.x-this.offsetInParent.x,f=o.y-this.offsetInParent.y;t?.snap()?(i.position.x=l(c),i.position.y=l(f)):(this.axis.x&&(i.position.x=c),this.axis.y&&(i.position.y=f)),this.lastPointerPosition.copyFrom(e.global);let{x:m,y:u}=a,d=(h,p)=>{Ot(h)?h.dependencies.forEach(P=>{P.set(p)}):kt(h)&&h.set(p)};m!==void 0&&d(m,i.position.x),u!==void 0&&d(u,i.position.y)}updateViewportPosition(e){if(!this.viewport||!this.elementRef)return;let i=this.dragProps,s=i?.viewport?.edgeThreshold(),t=i?.viewport?.maxSpeed(),a=0,l=this.viewport.screenWidth,o=0,c=this.viewport.screenHeight,f=this.elementRef.componentInstance,m=e.x-a,u=l-e.x,d=e.y-o,h=c-e.y,p=0,P=0;if(m<s?p=-(t*(1-m/s)):u<s&&(p=t*(1-u/s)),d<s?P=-(t*(1-d/s)):h<s&&(P=t*(1-h/s)),p!==0||P!==0){let E=this.viewport.center;this.viewport.moveCenter(this.viewport.center.x+p,this.viewport.center.y+P),this.axis.x&&E.x!==this.viewport.center.x&&(f.position.x+=p),this.axis.y&&E.y!==this.viewport.center.y&&(f.position.y+=P)}}onDragEnd(){if(this.pointerIsDown=!1,!this.isDragging)return;let e=this.dragProps;this.isDragging=!1,e?.end?.(),this.stageRef&&this.stageRef.off("pointermove",this.onDragMoveHandler)}onKeyDown(e){this.pressedKeys.add(e.code),this.pressedKeys.add(e.key.toLowerCase()),this.pointerIsDown&&!this.isDragging&&this.areRequiredKeysPressed()&&this.startDrag()}onKeyUp(e){this.pressedKeys.delete(e.code),this.pressedKeys.delete(e.key.toLowerCase()),this.isDragging&&!this.areRequiredKeysPressed()&&this.onDragEnd()}areRequiredKeysPressed(){let e=this.dragProps.keyToPress?this.dragProps.keyToPress:[];return!e||e.length===0?!0:e.some(i=>this.pressedKeys.has(i)?!0:i.toLowerCase()==="space"?this.pressedKeys.has("Space")||this.pressedKeys.has(" "):i.toLowerCase()==="shift"?this.pressedKeys.has("ShiftLeft")||this.pressedKeys.has("ShiftRight"):i.toLowerCase()==="control"||i.toLowerCase()==="ctrl"?this.pressedKeys.has("ControlLeft")||this.pressedKeys.has("ControlRight"):i.toLowerCase()==="alt"?this.pressedKeys.has("AltLeft")||this.pressedKeys.has("AltRight"):!1)}onPointerDown(e){if(!this.elementRef?.componentInstance||!this.stageRef||!this.elementRef.componentInstance.parent)return;this.pointerIsDown=!0;let i=this.elementRef.componentInstance,t=i.parent.toLocal(e.global);this.offsetInParent.x=t.x-i.position.x,this.offsetInParent.y=t.y-i.position.y,this.lastPointerPosition.copyFrom(e.global),this.areRequiredKeysPressed()&&this.startDrag()}startDrag(){if(this.isDragging||!this.stageRef)return;this.isDragging=!0,this.dragProps?.start?.(),this.stageRef.on("pointermove",this.onDragMoveHandler)}onUpdate(e){e.type&&e.type==="reset"&&(this.onDestroy(),this.onMount(this.elementRef))}onDestroy(){this.subscriptions.forEach(i=>i.unsubscribe());let e=this.elementRef?.componentInstance;e&&e.off("pointerdown",this.onDragStartHandler),this.stageRef&&(this.stageRef.off("pointermove",this.onDragMoveHandler),this.stageRef.off("pointerup",this.onDragEndHandler),this.stageRef.off("pointerupoutside",this.onDragEndHandler)),window.removeEventListener("keydown",this.onKeyDownHandler),window.removeEventListener("keyup",this.onKeyUpHandler),this.stageRef=null,this.viewport=null,this.pressedKeys.clear(),this.pointerIsDown=!1}};S("drag",me);S("drop",fe);import{DisplacementFilter as At,Sprite as Ft,Texture as Rt,WRAP_MODES as Ht}from"pixi.js";import{animate as Lt}from"popmotion";var ue=class extends x{onInit(n){}onMount(n){let{image:e}=n.props.transition,i=new Ft(Rt.from(e));i.texture.baseTexture.wrapMode=Ht.REPEAT;let s=new At(i),t=n.componentInstance;t.filters=[s],t.addChild(i),setTimeout(()=>{Lt({from:0,to:1,duration:500,onUpdate:a=>{s.scale.x=a,s.scale.y=a}})},5e3)}onUpdate(n){}onDestroy(){}};S("transition",ue);export*from"@signe/reactive";import{Howler as Io}from"howler";import{effect as de,signal as K}from"@signe/reactive";import{Container as Ut}from"pixi.js";import{signal as Ie}from"@signe/reactive";import{BlurFilter as Xe,ObservablePoint as jt}from"pixi.js";function M(r){return r&&typeof r=="string"?r.endsWith("%"):!1}import{BehaviorSubject as Wt}from"rxjs";var Kt=["added","childAdded","childRemoved","click","clickcapture","destroyed","globalmousemove","globalpointermove","globaltouchmove","mousedown","mousedowncapture","mouseenter","mouseentercapture","mouseleave","mouseleavecapture","mousemove","mousemovecapture","mouseout","mouseoutcapture","mouseover","mouseovercapture","mouseup","mouseupcapture","mouseupoutside","mouseupoutsidecapture","pointercancel","pointercancelcapture","pointerdown","pointerdowncapture","pointerenter","pointerentercapture","pointerleave","pointerleavecapture","pointermove","pointermovecapture","pointerout","pointeroutcapture","pointerover","pointerovercapture","pointertap","pointertapcapture","pointerup","pointerupcapture","pointerupoutside","pointerupoutsidecapture","removed","rightclick","rightclickcapture","rightdown","rightdowncapture","rightup","rightupcapture","rightupoutside","rightupoutsidecapture","tap","tapcapture","touchcancel","touchcancelcapture","touchend","touchendcapture","touchendoutside","touchendoutsidecapture","touchmove","touchmovecapture","touchstart","touchstartcapture","wheel","wheelcapture"];function b(r){var n,e;return e=class extends r{constructor(){super(...arguments);He(this,n,null);this.isFlex=!1;this.fullProps={};this.isMounted=!1;this._anchorPoints=new jt({_onUpdate:()=>{}},0,0);this.isCustomAnchor=!1;this.displayWidth=Ie(0);this.displayHeight=Ie(0);this.overrideProps=[];this.layout=null;this.onBeforeDestroy=null;this.onAfterMount=null;this.subjectInit=new Wt(null);this.disableLayout=!1}get deltaRatio(){return q(this,n)?.scheduler?.tick.value.deltaRatio}get parentIsFlex(){return this.disableLayout?!1:this.parent?.isFlex}onInit(t){this._id=t.id;for(let a of Kt)t[a]&&!this.overrideProps.includes(a)&&(this.eventMode="static",this.on(a,t[a]));(t.onBeforeDestroy||t["on-before-destroy"])&&(this.onBeforeDestroy=t.onBeforeDestroy||t["on-before-destroy"]),(t.onAfterMount||t["on-after-mount"])&&(this.onAfterMount=t.onAfterMount||t["on-after-mount"]),(t.justifyContent||t.alignItems||t.flexDirection||t.flexWrap||t.alignContent||t.display=="flex"||M(t.width)||M(t.height)||t.isRoot)&&(this.layout={},this.isFlex=!0),this.subjectInit.next(this)}async onMount({parent:t,props:a},l){if(Le(this,n,a.context),t){let o=t.componentInstance;if(o.isFlex&&!this.layout&&!this.disableLayout)try{this.layout={}}catch(c){console.warn("Failed to set layout:",c)}l===void 0?o.addChild(this):o.addChildAt(this,l),this.isMounted=!0,this.onUpdate(a),this.onAfterMount&&await this.onAfterMount()}}onUpdate(t){if(this.fullProps={...this.fullProps,...t},!q(this,n)||!this.parent)return;t.x!==void 0&&this.setX(t.x),t.y!==void 0&&this.setY(t.y),t.scale!==void 0&&C(this.scale,t.scale),t.anchor!==void 0&&!this.isCustomAnchor&&C(this.anchor,t.anchor),t.width!==void 0&&this.setWidth(t.width),t.height!==void 0&&this.setHeight(t.height),t.minWidth!==void 0&&this.setMinWidth(t.minWidth),t.minHeight!==void 0&&this.setMinHeight(t.minHeight),t.maxWidth!==void 0&&this.setMaxWidth(t.maxWidth),t.maxHeight!==void 0&&this.setMaxHeight(t.maxHeight),t.aspectRatio!==void 0&&this.setAspectRatio(t.aspectRatio),t.flexGrow!==void 0&&this.setFlexGrow(t.flexGrow),t.flexShrink!==void 0&&this.setFlexShrink(t.flexShrink),t.flexBasis!==void 0&&this.setFlexBasis(t.flexBasis),t.rowGap!==void 0&&this.setRowGap(t.rowGap),t.columnGap!==void 0&&this.setColumnGap(t.columnGap),t.top!==void 0&&this.setTop(t.top),t.left!==void 0&&this.setLeft(t.left),t.right!==void 0&&this.setRight(t.right),t.bottom!==void 0&&this.setBottom(t.bottom),t.objectFit!==void 0&&this.setObjectFit(t.objectFit),t.objectPosition!==void 0&&this.setObjectPosition(t.objectPosition),t.transformOrigin!==void 0&&this.setTransformOrigin(t.transformOrigin),t.skew!==void 0&&C(this.skew,t.skew),t.tint&&(this.tint=t.tint),t.rotation!==void 0&&(this.rotation=t.rotation),t.angle!==void 0&&(this.angle=t.angle),t.zIndex!==void 0&&(this.zIndex=t.zIndex),t.roundPixels!==void 0&&(this.roundPixels=t.roundPixels),t.cursor&&(this.cursor=t.cursor),t.visible!==void 0&&(this.visible=t.visible),t.alpha!==void 0&&(this.alpha=t.alpha),t.pivot&&C(this.pivot,t.pivot),t.flexDirection&&this.setFlexDirection(t.flexDirection),t.flexWrap&&this.setFlexWrap(t.flexWrap),t.justifyContent&&this.setJustifyContent(t.justifyContent),t.alignItems&&this.setAlignItems(t.alignItems),t.alignContent&&this.setAlignContent(t.alignContent),t.alignSelf&&this.setAlignSelf(t.alignSelf),t.margin&&this.setMargin(t.margin),t.padding&&this.setPadding(t.padding),t.gap&&this.setGap(t.gap),t.border&&this.setBorder(t.border),t.positionType&&this.setPositionType(t.positionType),t.filters&&(this.filters=t.filters),t.maskOf&&W(t.maskOf)&&(t.maskOf.componentInstance.mask=this),t.blendMode&&(this.blendMode=t.blendMode),t.filterArea&&(this.filterArea=t.filterArea);let a=this.filters||[];if(t.blur){let l=a.find(o=>o instanceof Xe);if(!l){let o=typeof t.blur=="number"?{strength:t.blur}:t.blur;l=new Xe(o),a.push(l)}Object.assign(l,t.blur)}this.filters=a}async onDestroy(t,a){this.onBeforeDestroy&&await this.onBeforeDestroy(),super.destroy(),a&&a()}setFlexDirection(t){this.layout={flexDirection:t}}setFlexWrap(t){this.layout={flexWrap:t}}setAlignContent(t){this.layout={alignContent:t}}setAlignSelf(t){this.layout={alignSelf:t}}setAlignItems(t){this.layout={alignItems:t}}setJustifyContent(t){this.layout={justifyContent:t}}setPosition(t){t instanceof Array?t.length===2?this.layout={positionY:t[0],positionX:t[1]}:t.length===4&&(this.layout={positionTop:t[0],positionRight:t[1],positionBottom:t[2],positionLeft:t[3]}):this.layout={position:t}}setX(t){t=t+this.getWidth()*this._anchorPoints.x,this.parentIsFlex?(this.x=t,this.layout={x:t}):this.x=t}setY(t){t=t+this.getHeight()*this._anchorPoints.y,this.parentIsFlex?(this.y=t,this.layout={y:t}):this.y=t}setPadding(t){t instanceof Array?t.length===2?this.layout={paddingVertical:t[0],paddingHorizontal:t[1]}:t.length===4&&(this.layout={paddingTop:t[0],paddingRight:t[1],paddingBottom:t[2],paddingLeft:t[3]}):this.layout={padding:t}}setMargin(t){t instanceof Array?t.length===2?this.layout={marginVertical:t[0],marginHorizontal:t[1]}:t.length===4&&(this.layout={marginTop:t[0],marginRight:t[1],marginBottom:t[2],marginLeft:t[3]}):this.layout={margin:t}}setGap(t){this.layout={gap:t}}setBorder(t){t instanceof Array?t.length===2?this.layout={borderVertical:t[0],borderHorizontal:t[1]}:t.length===4&&(this.layout={borderTop:t[0],borderRight:t[1],borderBottom:t[2],borderLeft:t[3]}):this.layout={border:t}}setPositionType(t){this.layout={position:t}}setWidth(t){this.displayWidth.set(t),this.parentIsFlex?this.layout={width:t}:this.width=t}setHeight(t){this.displayHeight.set(t),this.parentIsFlex?this.layout={height:t}:this.height=t}getWidth(){return this.displayWidth()}getHeight(){return this.displayHeight()}setMinWidth(t){this.layout={minWidth:t}}setMinHeight(t){this.layout={minHeight:t}}setMaxWidth(t){this.layout={maxWidth:t}}setMaxHeight(t){this.layout={maxHeight:t}}setAspectRatio(t){this.layout={aspectRatio:t}}setFlexGrow(t){this.layout={flexGrow:t}}setFlexShrink(t){this.layout={flexShrink:t}}setFlexBasis(t){this.layout={flexBasis:t}}setRowGap(t){this.layout={rowGap:t}}setColumnGap(t){this.layout={columnGap:t}}setTop(t){this.layout={top:t}}setLeft(t){this.layout={left:t}}setRight(t){this.layout={right:t}}setBottom(t){this.layout={bottom:t}}setObjectFit(t){this.layout={objectFit:t}}setObjectPosition(t){this.layout={objectPosition:t}}setTransformOrigin(t){this.layout={transformOrigin:t}}},n=new WeakMap,e}y("Canvas",class extends b(Ut){});var Nt=async(r={})=>{let{cursorStyles:n,width:e,height:i,class:s}=w(r);r.width||(e=K(800)),r.height||(i=K(600));let t=K({width:0,height:0});r.isRoot=!0;let a={...r,context:{canvasSize:t,app:K(null)},width:e?.(),height:i?.()};r.tick||(a.context.tick=a.tick=K({timestamp:0,deltaTime:0,frame:0,deltaRatio:1}));let l=g("Canvas",a);return l.render=(o,c)=>{if(!c)return;let f=c.renderer,m=f.view.canvas;globalThis.__PIXI_STAGE__=l.componentInstance,globalThis.__PIXI_RENDERER__=f,r.tickStart!==!1&&l.directives.tick.start(),de(()=>{l.propObservables.tick(),f.render(l.componentInstance)}),c.stage=l.componentInstance,c.stage.layout={width:c.screen.width,height:c.screen.height,justifyContent:r.justifyContent,alignItems:r.alignItems},t.set({width:c.screen.width,height:c.screen.height}),c.renderer.on("resize",(d,h)=>{t.set({width:d,height:h}),c.stage.layout&&(c.stage.layout={width:d,height:h})}),r.tickStart!==!1&&l.directives.tick.start(),c.ticker.add(()=>{l.propObservables.tick()}),n&&de(()=>{f.events.cursorStyles=n()}),s&&de(()=>{m.classList.add(s())});let u=o.querySelector("canvas");u?o.replaceChild(m,u):o.appendChild(m),a.context.app.set(c)},l};import{Container as Bt}from"pixi.js";var U=class extends b(Bt){constructor(){super(...arguments);this.isCustomAnchor=!0}onUpdate(e){e.anchor&&(C(this._anchorPoints,e.anchor),e.pivot=[this.getWidth()*this._anchorPoints.x,this.getHeight()*this._anchorPoints.y]),super.onUpdate(e),e.sortableChildren!=null&&(this.sortableChildren=e.sortableChildren)}async onMount(e){await super.onMount(e);let{componentInstance:i,props:s}=e,{pixiChildren:t}=s;t&&t.forEach(a=>{i.addChild(a)})}};y("Container",U);var he=r=>g("Container",r);import{effect as _t,isSignal as A,signal as V}from"@signe/reactive";import{Assets as zt,Graphics as Ye}from"pixi.js";var pe=class extends b(Ye){async onInit(n){await super.onInit(n)}async onMount(n,e){await super.onMount(n,e);let{props:i,propObservables:s}=n,t=A(s?.width)?s.width:V(i.width||0),a=A(s?.height)?s.height:V(i.height||0);this.width=t,this.height=a;let l=M(t()),o=M(a());i.draw&&(this.clearEffect=_t(()=>{let c=t(),f=a();typeof c=="string"||typeof f=="string"||c==0||f==0||(this.clear(),i.draw?.(this,c,f),this.subjectInit.next(this))})),this.on("layout",c=>{let f=c.computedLayout;l&&A(t)&&t.set(f.width),o&&A(a)&&a.set(f.height)})}onUpdate(n){super.onUpdate(n),n.width!==void 0&&this.width&&(A(n.width)?this.width=n.width:this.width.set(n.width)),n.height!==void 0&&this.height&&(A(n.height)?this.height=n.height:this.height.set(n.height))}async onDestroy(n,e){let i=async()=>{this.clearEffect.subscription.unsubscribe(),e()};await super.onDestroy(n,i)}};y("Graphics",pe);function F(r){return g("Graphics",r)}function Vt(r){let{color:n,borderRadius:e,border:i}=w(r,{borderRadius:null,border:null});return F({draw:(s,t,a)=>{e()?s.roundRect(0,0,t,a,e()):s.rect(0,0,t,a),i&&s.stroke(i),s.fill(n())},...r})}function $e(r,n,e){let{color:i,border:s}=e;"radius"in e?r.circle(0,0,e.radius()):r.ellipse(0,0,e.width()/2,e.height()/2),s()&&r.stroke(s()),r.fill(i())}function qt(r){let{radius:n,color:e,border:i}=w(r,{border:null});return F({draw:s=>$e(s,"circle",{radius:n,color:e,border:i}),...r})}function Gt(r){let{width:n,height:e,color:i,border:s}=w(r,{border:null});return F({draw:(t,a,l)=>$e(t,"ellipse",{width:V(a),height:V(l),color:i,border:s}),...r})}function It(r){let{width:n,height:e,color:i,border:s}=w(r,{border:null,color:"#000"});return F({draw:(t,a,l)=>{t.moveTo(0,l),t.lineTo(a/2,0),t.lineTo(a,l),t.lineTo(0,l),t.fill(i()),s&&t.stroke(s)},...r})}function Xt(r){return F({draw:async n=>{if(r.src){let e=await zt.load({src:r.src,data:{parseAsGraphicsContext:!0}}),i=new Ye(e);n.context=i.context}else r.content?n.svg(r.content):r.svg&&n.svg(r.svg)},...r})}import{Mesh as Yt,Geometry as $t,Assets as Je}from"pixi.js";var ye=class extends b(Yt){constructor(){super({geometry:new $t})}onInit(n){if(super.onInit(n),n.geometry)try{this.geometry=n.geometry}catch(e){console.warn("Failed to set geometry:",e)}n.shader&&(this.shader=n.shader)}async onUpdate(n){if(super.onUpdate(n),n.geometry)try{this.geometry=n.geometry}catch(e){console.warn("Failed to update geometry:",e)}n.shader&&(this.shader=n.shader),n.texture?typeof n.texture=="string"?this.texture=await Je.load(n.texture):this.texture=n.texture:n.image&&(this.texture=await Je.load(n.image)),n.tint!==void 0&&(this.tint=n.tint),n.blendMode!==void 0&&(this.blendMode=n.blendMode),n.roundPixels!==void 0&&(this.roundPixels=n.roundPixels)}async onDestroy(n,e){let i=async()=>{e()};await super.onDestroy(n,i)}};y("Mesh",ye);var Jt=r=>g("Mesh",r);var Qe=null,ge=null;function be(r){ge?.(r)}function qr(r){be(n=>{let{context:e}=n.props,i;return e.tick&&(i=e.tick.observable.subscribe(({value:s})=>{r(s,n)})),()=>{i?.unsubscribe()}})}function O(r,n={},...e){let i=new Set,s=new Set;Qe=a=>{i.add(a)},ge=a=>{s.add(a)},e[0]instanceof Array&&(e=e[0]);let t=r({...n,children:e});return t||(t={}),t.effectSubscriptions=Array.from(i),t.effectMounts=[...Array.from(s),...t.effectMounts??[]],t instanceof Promise&&t.then(a=>{a.props.isRoot&&s.forEach(l=>l(a))}),Qe=null,ge=null,t}function Qt(r){return O(he)}import*as Ze from"@barvynkoa/particle-emitter";var ve=class extends U{constructor(){super(...arguments);this.elapsed=Date.now()}async onMount(e){await super.onMount(e);let{props:i}=e,s=i.context.tick;this.emitter=new Ze.Emitter(this,i.config),this.subscriptionTick=s.observable.subscribe(t=>{if(!this.emitter)return;let a=Date.now();this.emitter.update((a-this.elapsed)*.001),this.elapsed=a})}onUpdate(e){}async onDestroy(e,i){let s=async()=>{this.emitter?.destroy(),this.emitter=null,this.subscriptionTick.unsubscribe(),i()};await super.onDestroy(e,s)}};y("ParticlesEmitter",ve);function Zt(r){return g("ParticlesEmitter",r)}import{Howl as ii}from"howler";import{computed as ni,effect as ri,isSignal as si}from"@signe/reactive";import{Assets as tt,Container as it,Sprite as nt,Rectangle as rt,Texture as st}from"pixi.js";import{effect as ei,signal as et}from"@signe/reactive";import{animate as ti}from"popmotion";function xe(r){return r.animatedState!==void 0}function is(r,n={}){let e={current:r,start:r,end:r},i,s=et(r),t=et(e);ei(()=>{let o=t();s.set(o.current)});function a(o,c={}){if(o===void 0)return t();let f=t(),m={current:f.current,start:f.current,end:o};t.set(m),i&&i.stop(),i=ti({duration:20,...n,...c,from:f.current,to:o,onUpdate:u=>{t.update(d=>({...d,current:u})),n.onUpdate&&n.onUpdate(u)}})}let l=function(){return t().current};for(let o in s)l[o]=s[o];return l.animatedState=t,l.update=o=>{a(o(t().current))},l.set=async(o,c={})=>new Promise(f=>{a(o,{...c,onComplete:f})}),l}async function ns(r){for(let n of r)Array.isArray(n)?await Promise.all(n.map(e=>e())):await n()}var ot=console.log;var we=class extends b(nt){constructor(){super(...arguments);this.currentAnimation=null;this.time=0;this.frameIndex=0;this.animations=new Map;this.subscriptionSheet=[];this.sheetParams={};this.sheetCurrentAnimation="stand";this.app=null;this.currentAnimationContainer=null}get renderer(){return this.app?.renderer}async createTextures(e){let{width:i,height:s,framesHeight:t,framesWidth:a,image:l,offset:o}=e;if(!l||typeof l!="string"||l.trim()==="")return console.warn("Invalid image path provided to createTextures:",l),[];let c=await tt.load(l),f=e.spriteWidth,m=e.spriteHeight,u=[],d=o&&o.x||0,h=o&&o.y||0;for(let p=0;p<t;p++){u[p]=[];for(let P=0;P<a;P++){let E=P*f+d,v=p*m+h;if(v>s)throw ot(`Warning, there is a problem with the height of the "${this.id}" spritesheet. When cutting into frames, the frame exceeds the height of the image.`);if(E>i)throw ot(`Warning, there is a problem with the width of the "${this.id}" spritesheet. When cutting into frames, the frame exceeds the width of the image.`);u[p].push(new st({source:c.source,frame:new rt(E,v,f,m)}))}}return u}async createAnimations(){let{textures:e}=this.spritesheet;if(e)for(let i in e){let a={...["width","height","framesHeight","framesWidth","rectWidth","rectHeight","offset","image","sound"].reduce((d,h)=>({...d,[h]:this.spritesheet[h]}),{}),...e[i]},{rectWidth:l,width:o=0,framesWidth:c=1,rectHeight:f,height:m=0,framesHeight:u=1}=a;a.spriteWidth=l||o/c,a.spriteHeight=f||m/u,this.animations.set(i,{frames:await this.createTextures(a),name:i,animations:e[i].animations,params:[],data:a,sprites:[]})}}async onMount(e){let{props:i,propObservables:s}=e,t=i.context.tick,a=i.sheet??{};if(this.app=i.context.app(),a?.onFinish&&(this.onFinish=a.onFinish),this.subscriptionTick=t.observable.subscribe(o=>{this.update(o)}),i.sheet?.definition&&(this.spritesheet=i.sheet.definition,await this.createAnimations()),a.params)for(let o in s?.sheet.params){let c=s?.sheet.params[o];si(c)?this.subscriptionSheet.push(c.observable.subscribe(f=>{this.animations.size!=0&&this.play(this.sheetCurrentAnimation,[{[o]:f}])})):this.play(this.sheetCurrentAnimation,[{[o]:c}])}let l=ni(()=>{let{x:o,y:c}=s??{};if(!o||!c)return!1;let f=o,m=c,u=xe(f)&&f.animatedState().current!==f.animatedState().end,d=xe(m)&&m.animatedState().current!==m.animatedState().end;return u||d});ri(()=>{let o=l();this.isMounted&&(o?this.sheetCurrentAnimation="walk":this.sheetCurrentAnimation="stand",this.spritesheet&&this.play(this.sheetCurrentAnimation,[this.sheetParams]))}),super.onMount(e)}async onUpdate(e){super.onUpdate(e);let i=async t=>{if(!t||typeof t!="string"||t.trim()==="")return console.warn("Invalid image path provided to setTexture:",t),null;let a=this.fullProps.loader?.onProgress,l=await tt.load(t,o=>{if(a&&a(o),o==1){let c=this.fullProps.loader?.onComplete;c&&setTimeout(()=>{c(l)})}});return l},s=e.sheet;if(s?.params&&(this.sheetParams=s?.params),s?.playing&&this.isMounted&&(this.sheetCurrentAnimation=s?.playing,this.play(this.sheetCurrentAnimation,[this.sheetParams])),e.hitbox&&(this.hitbox=e.hitbox),e.scaleMode)this.baseTexture.scaleMode=e.scaleMode;else if(e.image&&this.fullProps.rectangle===void 0){let t=await i(this.fullProps.image);t&&(this.texture=t)}else e.texture&&(W(e.texture)?(e.texture.componentInstance.subjectInit.subscribe(a=>{console.log("a",a?.width)}),this.texture=this.renderer?.generateTexture(e.texture.componentInstance)):this.texture=e.texture);if(e.rectangle!==void 0){let{x:t,y:a,width:l,height:o}=e.rectangle?.value??e.rectangle,c=await i(this.fullProps.image);c&&(this.texture=new st({source:c.source,frame:new rt(t,a,l,o)}))}}async onDestroy(e,i){await super.onDestroy(e),this.subscriptionSheet.forEach(s=>s.unsubscribe()),this.subscriptionTick.unsubscribe(),this.currentAnimationContainer&&this.parent instanceof it&&this.parent.removeChild(this.currentAnimationContainer)}has(e){return this.animations.has(e)}get(e){return this.animations.get(e)}isPlaying(e){return e?this.currentAnimation==null?!1:this.currentAnimation.name==e:!!this.currentAnimation}stop(){this.currentAnimation=null,this.destroy()}play(e,i=[]){let s=this.currentAnimation?.params;if(this.isPlaying(e)&&H(i,s||[]))return;let t=this.get(e);if(!t)throw new Error(`Impossible to play the ${e} animation because it doesn't exist on the "${this.id}" spritesheet`);let a=structuredClone(i);this.removeChildren(),t.sprites=[],this.currentAnimation=t,this.currentAnimation.params=a,this.time=0,this.frameIndex=0;let l=t.animations;l=X(l)?l(...a):l,this.currentAnimationContainer=new it;for(let c of l){let f=new nt;for(let m of c)this.currentAnimation.sprites.push(m);this.currentAnimationContainer.addChild(f)}let o=this.currentAnimation.data.sound;o&&new ii({src:o,autoplay:!0,loop:!1,volume:1}),this.update({deltaRatio:1})}update({deltaRatio:e}){if(!this.isPlaying()||!this.currentAnimation||!this.currentAnimationContainer)return;let i=this,{frames:s,sprites:t,data:a}=this.currentAnimation,l=t[this.frameIndex],o=t[this.frameIndex+1];for(let c of this.currentAnimationContainer.children){let d=function(v,T){let N=m(T||v);N!==void 0&&(i[v]=N)},f=c;if(!l||l.frameY==null||l.frameX==null)continue;this.texture=s[l.frameY][l.frameX];let m=v=>l[v]??a[v]??this.spritesheet[v],u=v=>{let T=m(v);T&&this[v].set(...T)};this.applyTransform&&(l={...l,...this.applyTransform(l,a,this.spritesheet)});let h=m("spriteRealSize"),p=typeof h=="number"?h:h?.height,P=typeof h=="number"?h:h?.width,E=()=>{if(p&&this.hitbox){let{spriteWidth:v,spriteHeight:T}=a,Ae=(v-this.hitbox.w)/2/v,N=(T-p)/2,ut=(T-this.hitbox.h-N)/T;this.anchor.set(Ae,ut)}};l.sound,E(),u("anchor"),u("scale"),u("skew"),u("pivot"),d("alpha","opacity"),d("x"),d("y"),d("angle"),d("rotation"),d("visible")}if(!o){this.time=0,this.frameIndex=0,this.onFinish&&t.length>1&&this.onFinish();return}this.time+=e??1,this.time>=o.time&&this.frameIndex++}};y("Sprite",we);var Pe=r=>g("Sprite",r);import{effect as oi,signal as ai}from"@signe/reactive";function li(r){let n={audioprocess:null,canplay:null,canplaythrough:null,complete:null,durationchange:null,emptied:null,ended:null,loadeddata:null,loadedmetadata:null,pause:null,play:null,playing:null,progress:null,ratechange:null,seeked:null,seeking:null,stalled:null,suspend:null,timeupdate:null,volumechange:null,waiting:null},e=ai(null),i=oe(r),{play:s,loop:t,muted:a}=i({play:{type:Boolean,default:!0},loop:{type:Boolean,default:!1},muted:{type:Boolean,default:!1}});return oi(()=>{let l=e(),o=s();l&&o!==void 0&&(o?l.play():l.pause()),l&&t()&&(l.loop=t()),l&&a()&&(l.muted=a())}),be(()=>()=>{for(let l in n)n[l]&&e().removeEventListener(l,n[l])}),O(Pe,{...r,image:r.src,loader:{onComplete:l=>{let o=l.source.resource;e.set(o),r?.loader?.onComplete&&r.loader.onComplete(l);for(let c in n)if(r[c]){let f=m=>{r[c](m)};n[c]=f,o.addEventListener(c,f)}}}})}import{Text as mi}from"pixi.js";import{effect as ci,signal as fi}from"@signe/reactive";function Se(r){return r?.start&&r?.listen}function Es(r){let n=fi({config:r,value:0,resolve:e=>{}});return{start:e=>new Promise(i=>{n.set({config:{...r,...e},resolve:i,value:Math.random()})}),listen:()=>({config:r,seed:n()})}}function at(r,n){if(!Se(r))throw new Error("In 'on(arg)' must have a trigger signal type");ci(()=>{let e=r.listen();if(e?.seed.value){let i=n(e?.seed.config);i&&typeof i.then=="function"&&i.then(e?.seed.resolve)}})}var Ee=class extends b(mi){constructor(){super(...arguments);this.fullText="";this.currentIndex=0;this.typewriterSpeed=1;this._wordWrapWidth=0;this.typewriterOptions={}}async onMount(e,i){let{props:s}=e;await super.onMount(e,i);let t=s.context.tick;s.text&&s.typewriter&&(this.fullText=s.text,this.text="",this.currentIndex=0,s.typewriter&&(this.typewriterOptions=s.typewriter,this.typewriterOptions.skip&&Se(this.typewriterOptions.skip)&&at(this.typewriterOptions.skip,()=>{this.skipTypewriter()}))),this.subscriptionTick=t.observable.subscribe(()=>{s.typewriter&&this.typewriterEffect()})}onUpdate(e){if(super.onUpdate(e),e.typewriter&&e.typewriter&&(this.typewriterOptions=e.typewriter),e.text!==void 0&&(this.text=""+e.text),e.text!==void 0&&e.text!==this.fullText&&this.fullProps.typewriter&&(this.text="",this.currentIndex=0,this.fullText=e.text),e.style){for(let i in e.style)this.style[i]=e.style[i];e.style.wordWrapWidth&&(this._wordWrapWidth=e.style.wordWrapWidth)}e.color&&(this.style.fill=e.color),e.size&&(this.style.fontSize=e.size),e.fontFamily&&(this.style.fontFamily=e.fontFamily),this._wordWrapWidth?this.setWidth(this._wordWrapWidth):this.setWidth(this.width),this.setHeight(this.height)}get onCompleteCallback(){return this.typewriterOptions.onComplete}typewriterEffect(){if(this.currentIndex<this.fullText.length){let e=Math.min(this.currentIndex+(this.typewriterOptions.speed??1),this.fullText.length);this.text=this.fullText.slice(0,e),this.currentIndex=e,this.currentIndex===this.fullText.length&&this.onCompleteCallback&&this.onCompleteCallback()}}skipTypewriter(){this.skipSignal&&this.skipSignal(),this.text=this.fullText,this.currentIndex=this.fullText.length}async onDestroy(e,i){let s=async()=>{this.subscriptionTick&&this.subscriptionTick.unsubscribe(),i&&i()};await super.onDestroy(e,s)}};y("Text",Ee);function ui(r){return g("Text",r)}import{TilingSprite as di,Texture as hi}from"pixi.js";var Te=class extends b(di){onUpdate(n){super.onUpdate(n),n.image&&(this.texture=hi.from(n.image)),n.tileScale&&this.tileScale.set(n.tileScale.x,n.tileScale.y),n.tilePosition&&this.tilePosition.set(n.tilePosition.x,n.tilePosition.y),n.width!==void 0&&(this.width=n.width),n.height!==void 0&&(this.height=n.height)}};y("TilingSprite",Te);function pi(r){return g("TilingSprite",r)}import{Viewport as yi}from"pixi-viewport";import{effect as lt}from"@signe/reactive";var gi=["bounce-x-end","bounce-x-start","bounce-y-end","bounce-y-start","clicked","drag-end","drag-start","frame-end","mouse-edge-end","mouse-edge-start","moved","moved-end","pinch-end","pinch-start","snap-end","snap-start","snap-zoom-end","snap-zoom-start","wheel-scroll","zoomed","zoomed-end"],Ce=class extends b(yi){constructor(){super({noTicker:!0,events:{domElement:{addEventListener:()=>{}}}});this.overrideProps=["wheel"]}onInit(e){super.onInit(e);for(let i of gi)e[i]&&this.on(i,e[i])}async onMount(e,i){await super.onMount(e,i);let{props:s}=e,{tick:t,app:a,canvasSize:l}=s.context,o=!1;lt(()=>{this.screenWidth=l().width,this.screenHeight=l().height}),lt(()=>{let c=a();if(!c)return;let f=c.renderer;f.events.domElement.addEventListener("wheel",this.input.wheelFunction),this.options.events=f.events}),this.tickSubscription=t.observable.subscribe(({value:c})=>{this.update(c.timestamp)}),e.props.context.viewport=this,this.updateViewportSettings(s)}onUpdate(e){super.onUpdate(e),this.updateViewportSettings(e)}updateViewportSettings(e){e.screenWidth!==void 0&&(this.screenWidth=e.screenWidth),e.screenHeight!==void 0&&(this.screenHeight=e.screenHeight),e.worldWidth!==void 0&&(this.worldWidth=e.worldWidth),e.worldHeight!==void 0&&(this.worldHeight=e.worldHeight),e.drag&&this.drag(e.drag),e.clamp&&this.clamp(e.clamp.value??e.clamp),e.wheel&&(e.wheel===!0?this.wheel():this.wheel(e.wheel)),e.decelerate&&(e.decelerate===!0?this.decelerate():this.decelerate(e.decelerate)),e.pinch&&(e.pinch===!0?this.pinch():this.pinch(e.pinch))}async onDestroy(e,i){let s=async()=>{this.tickSubscription.unsubscribe(),i()};await super.onDestroy(e,s)}};y("Viewport",Ce);function bi(r){return g("Viewport",r)}import{Assets as vi,NineSliceSprite as xi}from"pixi.js";var Oe=class extends b(xi){constructor(){super({width:0,height:0})}async onUpdate(n){for(let[e,i]of Object.entries(n))i!==void 0&&(e==="image"?this.texture=await vi.load(i):e in this&&(this[e]=i))}};y("NineSliceSprite",Oe);function wi(r){return g("NineSliceSprite",r)}import{DOMContainer as Pi}from"pixi.js";import{isSignal as ct}from"@signe/reactive";var ft=["click","mouseover","mouseout","mouseenter","mouseleave","mousemove","mouseup","mousedown","touchstart","touchend","touchmove","touchcancel","wheel","scroll","resize","focus","blur","change","input","submit","reset","keydown","keyup","keypress","contextmenu","drag","dragend","dragenter","dragleave","dragover","drop","dragstart","select","selectstart","selectend","selectall","selectnone"],ke=class{constructor(){this.eventListeners=new Map;this.onBeforeDestroy=null;this.valueSignal=null;this.isFormElementType=!1}isFormElement(n){return["input","textarea","select"].includes(n.toLowerCase())}onInit(n){typeof n.element=="string"?(this.element=document.createElement(n.element),this.isFormElementType=this.isFormElement(n.element)):(this.element=n.element.value,this.isFormElementType=this.isFormElement(this.element.tagName)),(n.onBeforeDestroy||n["on-before-destroy"])&&(this.onBeforeDestroy=n.onBeforeDestroy||n["on-before-destroy"]);for(let e of ft)if(n.attrs?.[e]){let i=s=>{if(e==="submit"&&this.element.tagName.toLowerCase()==="form"){s.preventDefault();let t=new FormData(this.element),a={};t.forEach((l,o)=>{a[o]?Array.isArray(a[o])?a[o].push(l):a[o]=[a[o],l]:a[o]=l}),n.attrs[e]?.(s,a)}else n.attrs[e]?.(s)};this.eventListeners.set(e,i),this.element.addEventListener(e,i,!1)}if(n.children)for(let e of n.children)$(e)?e.subscribe(({elements:i})=>{for(let s of i)this.element.appendChild(s.componentInstance.element)}):this.element.appendChild(e.componentInstance.element);this.onUpdate(n)}onMount(n){let i=n.propObservables.attrs;if(this.isFormElementType&&i?.value&&ct(i.value)){this.valueSignal=i.value,this.element.value=this.valueSignal();let s=t=>{let a=t.target;this.valueSignal.set(a.value)};this.eventListeners.set("input",s),this.element.addEventListener("input",s,!1)}}onUpdate(n){if(this.element){for(let[e,i]of Object.entries(n.attrs||{}))if(e==="class"){let s=i.items||i.value||i;if(this.element.className="",typeof s=="string")this.element.className=s;else if(Array.isArray(s))this.element.classList.add(...s);else if(typeof s=="object"&&s!==null)for(let[t,a]of Object.entries(s))a&&this.element.classList.add(t)}else if(e==="style"){let s=i.items||i.value||i;if(typeof s=="string")this.element.setAttribute("style",s);else if(typeof s=="object"&&s!==null)for(let[t,a]of Object.entries(s))a!=null&&(this.element.style[t]=a)}else if(e==="value"&&this.isFormElementType)if(ct(i)){let s=this.element.value,t=i();s!==t&&(this.element.value=t)}else this.element.value=i;else ft.includes(e)||this.element.setAttribute(e,i);n.textContent&&(this.element.textContent=n.textContent)}}async onDestroy(n,e){if(this.element){this.onBeforeDestroy&&await this.onBeforeDestroy();for(let[i,s]of this.eventListeners)this.element.removeEventListener(i,s,!1);this.eventListeners.clear(),this.element.remove(),e&&e()}}};y("DOMElement",ke);var De=r=>g("DOMElement",r);var Me=class extends b(Pi){constructor(){super(...arguments);this.disableLayout=!0}onInit(e){let i=O(De,{element:"div"},e.children);this.element=i.componentInstance.element}};y("DOMContainer",Me);var Si=r=>g("DOMContainer",r);import"@pixi/layout";import{Application as Ei}from"pixi.js";var jo=async(r,n,e)=>{let i=new Ei;await i.init({resizeTo:r,autoStart:!1,...e??{}});let s=await O(n);if(s.tag!="Canvas")throw new Error("Canvas is required");s.render(r,i);let{backgroundColor:t}=w(s.props,{backgroundColor:"black"});return i.renderer.background.color=t(),{canvasElement:s,app:i}};import{linear as Ti,easeIn as Ci,easeInOut as Oi,easeOut as ki,circIn as Di,circInOut as Mi,circOut as Ai,backIn as Fi,backInOut as Ri,backOut as Hi,anticipate as Li,bounceIn as ji,bounceInOut as Wi,bounceOut as Ki}from"popmotion";var Uo={linear:Ti,easeIn:Ci,easeInOut:Oi,easeOut:ki,circIn:Di,circInOut:Mi,circOut:Ai,backIn:Fi,backInOut:Ri,backOut:Hi,anticipate:Li,bounceIn:ji,bounceInOut:Wi,bounceOut:Ki};import{Texture as Ui,ImageSource as Ni,DOMAdapter as Bi,Matrix as _i}from"pixi.js";var mt=class{constructor(n,e,i,s,t,a,l=0){this.x0=n;this.y0=e;this.x1=i;this.y1=s;this.x2=t;this.y2=a;this.focalPoint=l;this.gradient=null;this.texture=null;this.size=600;this.size=n;let o=this.size*.5;this.canvas=Bi.get().createCanvas(),this.canvas.width=this.size,this.canvas.height=this.size,this.ctx=this.canvas.getContext("2d"),this.ctx&&(this.gradient=this.ctx.createRadialGradient(o*(1-l),o,0,o,o,o-.5))}addColorStop(n,e){this.gradient&&this.gradient.addColorStop(n,e)}render({translate:n}={}){let{x0:e,y0:i,x1:s,y1:t,x2:a,y2:l,focalPoint:o}=this,c=this.size;if(this.ctx&&this.gradient){this.ctx.fillStyle=this.gradient,this.ctx.fillRect(0,0,c,c),this.texture=new Ui({source:new Ni({resource:this.canvas,addressModeU:"clamp-to-edge",addressModeV:"clamp-to-edge"})});let f=new _i,m=Math.sqrt((s-e)*(s-e)+(t-i)*(t-i)),u=Math.sqrt((a-e)*(a-e)+(l-i)*(l-i)),d=Math.atan2(t-i,s-e),h=m/c,p=u/c;f.rotate(-d),f.scale(h,p),n&&f.translate(n.x,n.y),this.transform=f}return{texture:this.texture,matrix:this.transform}}};import{isObservable as sa}from"rxjs";import*as oa from"howler";export{Nt as Canvas,qt as Circle,he as Container,Si as DOMContainer,De as DOMElement,b as DisplayObject,Kt as EVENTS,Uo as Easing,Gt as Ellipse,F as Graphics,oa as Howl,Io as Howler,Jt as Mesh,wi as NineSliceSprite,Zt as ParticlesEmitter,mt as RadialGradient,Vt as Rect,Qt as Scene,Pe as Sprite,Xt as Svg,ui as Text,pi as TilingSprite,It as Triangle,Q as Utils,li as Video,bi as Viewport,ns as animatedSequence,is as animatedSignal,jo as bootstrapCanvas,mn as cond,g as createComponent,Qe as currentSubscriptionsTracker,O as h,xe as isAnimatedSignal,W as isElement,sa as isObservable,ne as isPrimitive,Se as isTrigger,fn as loop,be as mount,ge as mountTracker,at as on,y as registerComponent,qr as tick,Es as trigger,oe as useDefineProps,w as useProps};
4259
2
  //# sourceMappingURL=index.js.map