@mulsense/xnew 0.6.8 → 0.7.1
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/README.md +3 -3
- package/dist/addons/xpixi.js +5 -0
- package/dist/addons/xpixi.mjs +5 -0
- package/dist/addons/xthree.js +16 -0
- package/dist/addons/xthree.mjs +16 -0
- package/dist/xnew.d.ts +59 -66
- package/dist/xnew.js +189 -93
- package/dist/xnew.mjs +189 -93
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -13,7 +13,7 @@ providing a flexible architecture well-suited for applications with dynamic scen
|
|
|
13
13
|
### Via CDN
|
|
14
14
|
Include the following script in your HTML file:
|
|
15
15
|
```html
|
|
16
|
-
<script src="https://unpkg.com/@mulsense/xnew@0.
|
|
16
|
+
<script src="https://unpkg.com/@mulsense/xnew@0.7.x/dist/xnew.js"></script>
|
|
17
17
|
```
|
|
18
18
|
|
|
19
19
|
### Via CDN (ESM)
|
|
@@ -22,7 +22,7 @@ Use the ES module version with an import map:
|
|
|
22
22
|
<script type="importmap">
|
|
23
23
|
{
|
|
24
24
|
"imports": {
|
|
25
|
-
"@mulsense/xnew": "https://unpkg.com/@mulsense/xnew@0.
|
|
25
|
+
"@mulsense/xnew": "https://unpkg.com/@mulsense/xnew@0.7.x/dist/xnew.mjs"
|
|
26
26
|
}
|
|
27
27
|
}
|
|
28
28
|
</script>
|
|
@@ -37,7 +37,7 @@ import xnew from '@mulsense/xnew';
|
|
|
37
37
|
### Via npm
|
|
38
38
|
Install `xnew` using npm:
|
|
39
39
|
```bash
|
|
40
|
-
npm install @mulsense/xnew@0.
|
|
40
|
+
npm install @mulsense/xnew@0.7.x
|
|
41
41
|
```
|
|
42
42
|
|
|
43
43
|
Then import it in your JavaScript file:
|
package/dist/addons/xpixi.js
CHANGED
package/dist/addons/xpixi.mjs
CHANGED
package/dist/addons/xthree.js
CHANGED
|
@@ -29,6 +29,11 @@
|
|
|
29
29
|
},
|
|
30
30
|
nest(object) {
|
|
31
31
|
xnew(Nest, { object });
|
|
32
|
+
xnew.extend(() => {
|
|
33
|
+
return {
|
|
34
|
+
get threeObject() { return object; }
|
|
35
|
+
};
|
|
36
|
+
});
|
|
32
37
|
return object;
|
|
33
38
|
},
|
|
34
39
|
get renderer() {
|
|
@@ -67,6 +72,17 @@
|
|
|
67
72
|
parent.add(object);
|
|
68
73
|
unit.on('finalize', () => {
|
|
69
74
|
parent.remove(object);
|
|
75
|
+
object.traverse((obj) => {
|
|
76
|
+
if (obj.isMesh) {
|
|
77
|
+
obj.geometry.dispose();
|
|
78
|
+
if (Array.isArray(obj.material)) {
|
|
79
|
+
obj.material.forEach((mat) => mat.dispose());
|
|
80
|
+
}
|
|
81
|
+
else {
|
|
82
|
+
obj.material.dispose();
|
|
83
|
+
}
|
|
84
|
+
}
|
|
85
|
+
});
|
|
70
86
|
});
|
|
71
87
|
return {
|
|
72
88
|
get threeObject() { return object; },
|
package/dist/addons/xthree.mjs
CHANGED
|
@@ -7,6 +7,11 @@ var xthree = {
|
|
|
7
7
|
},
|
|
8
8
|
nest(object) {
|
|
9
9
|
xnew(Nest, { object });
|
|
10
|
+
xnew.extend(() => {
|
|
11
|
+
return {
|
|
12
|
+
get threeObject() { return object; }
|
|
13
|
+
};
|
|
14
|
+
});
|
|
10
15
|
return object;
|
|
11
16
|
},
|
|
12
17
|
get renderer() {
|
|
@@ -45,6 +50,17 @@ function Nest(unit, { object }) {
|
|
|
45
50
|
parent.add(object);
|
|
46
51
|
unit.on('finalize', () => {
|
|
47
52
|
parent.remove(object);
|
|
53
|
+
object.traverse((obj) => {
|
|
54
|
+
if (obj.isMesh) {
|
|
55
|
+
obj.geometry.dispose();
|
|
56
|
+
if (Array.isArray(obj.material)) {
|
|
57
|
+
obj.material.forEach((mat) => mat.dispose());
|
|
58
|
+
}
|
|
59
|
+
else {
|
|
60
|
+
obj.material.dispose();
|
|
61
|
+
}
|
|
62
|
+
}
|
|
63
|
+
});
|
|
48
64
|
});
|
|
49
65
|
return {
|
|
50
66
|
get threeObject() { return object; },
|
package/dist/xnew.d.ts
CHANGED
|
@@ -44,6 +44,7 @@ declare class Eventor {
|
|
|
44
44
|
}
|
|
45
45
|
|
|
46
46
|
type UnitElement = HTMLElement | SVGElement;
|
|
47
|
+
type UnitArgs = [Component?: Function | string, props?: Object] | [target: UnitElement | string, Component?: Function | string, props?: Object];
|
|
47
48
|
interface Context {
|
|
48
49
|
previous: Context | null;
|
|
49
50
|
key?: any;
|
|
@@ -55,39 +56,39 @@ interface Snapshot {
|
|
|
55
56
|
element: UnitElement;
|
|
56
57
|
Component: Function | null;
|
|
57
58
|
}
|
|
58
|
-
interface Internal {
|
|
59
|
-
parent: Unit | null;
|
|
60
|
-
ancestors: Unit[];
|
|
61
|
-
children: Unit[];
|
|
62
|
-
state: string;
|
|
63
|
-
tostart: boolean;
|
|
64
|
-
protected: boolean;
|
|
65
|
-
promises: UnitPromise[];
|
|
66
|
-
results: Record<string, any>;
|
|
67
|
-
defines: Record<string, any>;
|
|
68
|
-
systems: Record<string, {
|
|
69
|
-
listener: Function;
|
|
70
|
-
execute: Function;
|
|
71
|
-
}[]>;
|
|
72
|
-
currentElement: UnitElement;
|
|
73
|
-
currentContext: Context;
|
|
74
|
-
currentComponent: Function | null;
|
|
75
|
-
nestElements: {
|
|
76
|
-
element: UnitElement;
|
|
77
|
-
owned: boolean;
|
|
78
|
-
}[];
|
|
79
|
-
Components: Function[];
|
|
80
|
-
listeners: MapMap<string, Function, {
|
|
81
|
-
element: UnitElement;
|
|
82
|
-
Component: Function | null;
|
|
83
|
-
execute: Function;
|
|
84
|
-
}>;
|
|
85
|
-
eventor: Eventor;
|
|
86
|
-
}
|
|
87
59
|
declare class Unit {
|
|
88
60
|
[key: string]: any;
|
|
89
|
-
_:
|
|
90
|
-
|
|
61
|
+
_: {
|
|
62
|
+
parent: Unit | null;
|
|
63
|
+
ancestors: Unit[];
|
|
64
|
+
children: Unit[];
|
|
65
|
+
state: string;
|
|
66
|
+
tostart: boolean;
|
|
67
|
+
protected: boolean;
|
|
68
|
+
promises: UnitPromise[];
|
|
69
|
+
results: Record<string, any>;
|
|
70
|
+
defines: Record<string, any>;
|
|
71
|
+
systems: Record<string, {
|
|
72
|
+
listener: Function;
|
|
73
|
+
execute: Function;
|
|
74
|
+
}[]>;
|
|
75
|
+
currentElement: UnitElement;
|
|
76
|
+
currentContext: Context;
|
|
77
|
+
currentComponent: Function | null;
|
|
78
|
+
afterSnapshot: Snapshot | null;
|
|
79
|
+
nestElements: {
|
|
80
|
+
element: UnitElement;
|
|
81
|
+
owned: boolean;
|
|
82
|
+
}[];
|
|
83
|
+
Components: Function[];
|
|
84
|
+
listeners: MapMap<string, Function, {
|
|
85
|
+
element: UnitElement;
|
|
86
|
+
Component: Function | null;
|
|
87
|
+
execute: Function;
|
|
88
|
+
}>;
|
|
89
|
+
eventor: Eventor;
|
|
90
|
+
};
|
|
91
|
+
constructor(parent: Unit | null, ...args: UnitArgs);
|
|
91
92
|
get element(): UnitElement;
|
|
92
93
|
start(): void;
|
|
93
94
|
stop(): void;
|
|
@@ -120,49 +121,26 @@ declare class Unit {
|
|
|
120
121
|
static emit(type: string, props?: object): void;
|
|
121
122
|
}
|
|
122
123
|
declare class UnitPromise {
|
|
123
|
-
promise
|
|
124
|
-
|
|
125
|
-
constructor(promise: Promise<any>, Component: Function | null);
|
|
124
|
+
private promise;
|
|
125
|
+
constructor(promise: Promise<any>);
|
|
126
126
|
then(callback: Function): UnitPromise;
|
|
127
127
|
catch(callback: Function): UnitPromise;
|
|
128
128
|
finally(callback: Function): UnitPromise;
|
|
129
|
+
static all(promises: UnitPromise[]): UnitPromise;
|
|
129
130
|
private wrap;
|
|
130
131
|
}
|
|
131
132
|
declare class UnitTimer {
|
|
132
133
|
private unit;
|
|
133
134
|
private queue;
|
|
134
135
|
clear(): void;
|
|
135
|
-
timeout(
|
|
136
|
-
interval(
|
|
136
|
+
timeout(timeout: Function, duration?: number): UnitTimer;
|
|
137
|
+
interval(timeout: Function, duration?: number, iterations?: number): UnitTimer;
|
|
137
138
|
transition(transition: Function, duration?: number, easing?: string): UnitTimer;
|
|
138
139
|
private static execute;
|
|
139
140
|
private static next;
|
|
140
141
|
private static Component;
|
|
141
142
|
}
|
|
142
143
|
|
|
143
|
-
interface CreateUnit {
|
|
144
|
-
/**
|
|
145
|
-
* creates a new Unit component
|
|
146
|
-
* @param Component - component function
|
|
147
|
-
* @param props - properties for component function
|
|
148
|
-
* @returns a new Unit instance
|
|
149
|
-
* @example
|
|
150
|
-
* const unit = xnew(MyComponent, { data: 0 })
|
|
151
|
-
*/
|
|
152
|
-
(Component?: Function | string, props?: Object): Unit;
|
|
153
|
-
/**
|
|
154
|
-
* creates a new Unit component
|
|
155
|
-
* @param target - HTMLElement | SVGElement, or HTML tag for new element
|
|
156
|
-
* @param Component - component function
|
|
157
|
-
* @param props - properties for component function
|
|
158
|
-
* @returns a new Unit instance
|
|
159
|
-
* @example
|
|
160
|
-
* const unit = xnew(element, MyComponent, { data: 0 })
|
|
161
|
-
* const unit = xnew('<div>', MyComponent, { data: 0 })
|
|
162
|
-
*/
|
|
163
|
-
(target: HTMLElement | SVGElement | string, Component?: Function | string, props?: Object): Unit;
|
|
164
|
-
}
|
|
165
|
-
|
|
166
144
|
interface TransitionOptions {
|
|
167
145
|
duration?: number;
|
|
168
146
|
easing?: string;
|
|
@@ -230,12 +208,19 @@ declare function Panel(unit: Unit, { params }: PanelOptions): {
|
|
|
230
208
|
separator(): void;
|
|
231
209
|
};
|
|
232
210
|
|
|
233
|
-
declare function
|
|
234
|
-
|
|
235
|
-
|
|
236
|
-
next(Component: Function, props?: any): void;
|
|
211
|
+
declare function Scene(unit: Unit): {
|
|
212
|
+
moveTo(Component: Function, props?: any): void;
|
|
213
|
+
append(Component: Function, props?: any): void;
|
|
237
214
|
};
|
|
238
215
|
|
|
216
|
+
declare class XImage {
|
|
217
|
+
canvas: HTMLCanvasElement;
|
|
218
|
+
constructor(canvas: HTMLCanvasElement);
|
|
219
|
+
constructor(width: number, height: number);
|
|
220
|
+
crop(x: number, y: number, width: number, height: number): XImage;
|
|
221
|
+
download(filename: string): void;
|
|
222
|
+
}
|
|
223
|
+
|
|
239
224
|
type SynthesizerOptions = {
|
|
240
225
|
oscillator: OscillatorOptions;
|
|
241
226
|
amp: AmpOptions;
|
|
@@ -280,17 +265,22 @@ declare namespace xnew {
|
|
|
280
265
|
type Unit = InstanceType<typeof Unit>;
|
|
281
266
|
type UnitTimer = InstanceType<typeof UnitTimer>;
|
|
282
267
|
}
|
|
283
|
-
declare const xnew:
|
|
268
|
+
declare const xnew: ((...args: UnitArgs) => Unit) & {
|
|
284
269
|
nest(target: UnitElement | string): HTMLElement | SVGElement;
|
|
285
270
|
extend(Component: Function, props?: Object): {
|
|
286
271
|
[key: string]: any;
|
|
287
272
|
};
|
|
273
|
+
append(parent: Unit, ...args: UnitArgs): void;
|
|
288
274
|
context(key: any): any;
|
|
289
275
|
promise(promise: Function | Promise<any> | Unit): UnitPromise;
|
|
290
276
|
then(callback: Function): UnitPromise;
|
|
291
277
|
catch(callback: Function): UnitPromise;
|
|
292
|
-
commit(object?: Record<string, any>): void;
|
|
293
278
|
finally(callback: Function): UnitPromise;
|
|
279
|
+
resolvers(): {
|
|
280
|
+
resolve(): void;
|
|
281
|
+
reject(): void;
|
|
282
|
+
};
|
|
283
|
+
output(object?: Record<string, any>): void;
|
|
294
284
|
scope(callback: any): any;
|
|
295
285
|
find(Component: Function): Unit[];
|
|
296
286
|
emit(type: string, ...args: any[]): void;
|
|
@@ -307,13 +297,16 @@ declare const xnew: CreateUnit & {
|
|
|
307
297
|
Panel: typeof Panel;
|
|
308
298
|
Accordion: typeof Accordion;
|
|
309
299
|
Popup: typeof Popup;
|
|
310
|
-
|
|
300
|
+
Scene: typeof Scene;
|
|
311
301
|
};
|
|
312
302
|
audio: {
|
|
313
303
|
load(path: string): UnitPromise;
|
|
314
304
|
synthesizer(props: SynthesizerOptions): Synthesizer;
|
|
315
305
|
volume: number;
|
|
316
306
|
};
|
|
307
|
+
image: {
|
|
308
|
+
from(canvas: HTMLCanvasElement): XImage;
|
|
309
|
+
};
|
|
317
310
|
};
|
|
318
311
|
|
|
319
312
|
export { xnew as default };
|
package/dist/xnew.js
CHANGED
|
@@ -192,7 +192,7 @@
|
|
|
192
192
|
this.id = null;
|
|
193
193
|
this.time = { start: 0.0, processed: 0.0 };
|
|
194
194
|
(_b = (_a = this.options).transition) === null || _b === void 0 ? void 0 : _b.call(_a, 1.0);
|
|
195
|
-
(_d = (_c = this.options).
|
|
195
|
+
(_d = (_c = this.options).timeout) === null || _d === void 0 ? void 0 : _d.call(_c);
|
|
196
196
|
this.clear();
|
|
197
197
|
}, this.options.duration - this.time.processed);
|
|
198
198
|
this.time.start = Date.now();
|
|
@@ -519,16 +519,26 @@
|
|
|
519
519
|
return { position };
|
|
520
520
|
}
|
|
521
521
|
|
|
522
|
-
//----------------------------------------------------------------------------------------------------
|
|
523
|
-
// utils
|
|
524
|
-
//----------------------------------------------------------------------------------------------------
|
|
525
522
|
const SYSTEM_EVENTS = ['start', 'update', 'render', 'stop', 'finalize'];
|
|
526
523
|
//----------------------------------------------------------------------------------------------------
|
|
527
524
|
// unit
|
|
528
525
|
//----------------------------------------------------------------------------------------------------
|
|
529
526
|
class Unit {
|
|
530
|
-
constructor(parent,
|
|
527
|
+
constructor(parent, ...args) {
|
|
531
528
|
var _a;
|
|
529
|
+
let target;
|
|
530
|
+
let Component;
|
|
531
|
+
let props;
|
|
532
|
+
if (args[0] instanceof HTMLElement || args[0] instanceof SVGElement || typeof args[0] === 'string') {
|
|
533
|
+
target = args[0];
|
|
534
|
+
Component = args[1];
|
|
535
|
+
props = args[2];
|
|
536
|
+
}
|
|
537
|
+
else {
|
|
538
|
+
target = null;
|
|
539
|
+
Component = args[0];
|
|
540
|
+
props = args[1];
|
|
541
|
+
}
|
|
532
542
|
const backup = Unit.currentUnit;
|
|
533
543
|
Unit.currentUnit = this;
|
|
534
544
|
parent === null || parent === void 0 ? void 0 : parent._.children.push(this);
|
|
@@ -561,6 +571,7 @@
|
|
|
561
571
|
currentElement: baseElement,
|
|
562
572
|
currentContext: baseContext,
|
|
563
573
|
currentComponent: null,
|
|
574
|
+
afterSnapshot: null,
|
|
564
575
|
ancestors: parent ? [parent, ...parent._.ancestors] : [],
|
|
565
576
|
children: [],
|
|
566
577
|
nestElements: [],
|
|
@@ -581,6 +592,7 @@
|
|
|
581
592
|
if (this._.state === 'invoked') {
|
|
582
593
|
this._.state = 'initialized';
|
|
583
594
|
}
|
|
595
|
+
this._.afterSnapshot = Unit.snapshot(this);
|
|
584
596
|
Unit.currentUnit = backup;
|
|
585
597
|
}
|
|
586
598
|
get element() {
|
|
@@ -650,7 +662,7 @@
|
|
|
650
662
|
return element;
|
|
651
663
|
}
|
|
652
664
|
else {
|
|
653
|
-
throw new Error(`xnew.nest: invalid
|
|
665
|
+
throw new Error(`xnew.nest: invalid tag string [${target}]`);
|
|
654
666
|
}
|
|
655
667
|
}
|
|
656
668
|
}
|
|
@@ -692,7 +704,7 @@
|
|
|
692
704
|
Object.defineProperty(unit._.defines, key, wrapper);
|
|
693
705
|
Object.defineProperty(unit, key, wrapper);
|
|
694
706
|
});
|
|
695
|
-
return defines;
|
|
707
|
+
return Object.assign({}, unit._.defines);
|
|
696
708
|
}
|
|
697
709
|
}
|
|
698
710
|
static start(unit) {
|
|
@@ -729,7 +741,7 @@
|
|
|
729
741
|
static reset() {
|
|
730
742
|
var _a;
|
|
731
743
|
(_a = Unit.rootUnit) === null || _a === void 0 ? void 0 : _a.finalize();
|
|
732
|
-
Unit.currentUnit = Unit.rootUnit = new Unit(null
|
|
744
|
+
Unit.currentUnit = Unit.rootUnit = new Unit(null);
|
|
733
745
|
const ticker = new AnimationTicker(() => {
|
|
734
746
|
Unit.start(Unit.rootUnit);
|
|
735
747
|
Unit.update(Unit.rootUnit);
|
|
@@ -769,7 +781,7 @@
|
|
|
769
781
|
}
|
|
770
782
|
static getContext(unit, key) {
|
|
771
783
|
for (let context = unit._.currentContext; context.previous !== null; context = context.previous) {
|
|
772
|
-
if (context.value === Unit.currentUnit
|
|
784
|
+
if (context.value === Unit.currentUnit)
|
|
773
785
|
continue;
|
|
774
786
|
if (context.key === key)
|
|
775
787
|
return context.value;
|
|
@@ -848,13 +860,13 @@
|
|
|
848
860
|
// extensions
|
|
849
861
|
//----------------------------------------------------------------------------------------------------
|
|
850
862
|
class UnitPromise {
|
|
851
|
-
constructor(promise
|
|
852
|
-
this.promise = promise;
|
|
853
|
-
this.Component = Component;
|
|
854
|
-
}
|
|
863
|
+
constructor(promise) { this.promise = promise; }
|
|
855
864
|
then(callback) { return this.wrap('then', callback); }
|
|
856
865
|
catch(callback) { return this.wrap('catch', callback); }
|
|
857
866
|
finally(callback) { return this.wrap('finally', callback); }
|
|
867
|
+
static all(promises) {
|
|
868
|
+
return new UnitPromise(Promise.all(promises.map(p => p.promise)));
|
|
869
|
+
}
|
|
858
870
|
wrap(key, callback) {
|
|
859
871
|
const snapshot = Unit.snapshot(Unit.currentUnit);
|
|
860
872
|
this.promise = this.promise[key]((...args) => Unit.scope(snapshot, callback, ...args));
|
|
@@ -872,11 +884,11 @@
|
|
|
872
884
|
(_a = this.unit) === null || _a === void 0 ? void 0 : _a.finalize();
|
|
873
885
|
this.unit = null;
|
|
874
886
|
}
|
|
875
|
-
timeout(
|
|
876
|
-
return UnitTimer.execute(this, {
|
|
887
|
+
timeout(timeout, duration = 0) {
|
|
888
|
+
return UnitTimer.execute(this, { timeout, duration }, 1);
|
|
877
889
|
}
|
|
878
|
-
interval(
|
|
879
|
-
return UnitTimer.execute(this, {
|
|
890
|
+
interval(timeout, duration = 0, iterations = 0) {
|
|
891
|
+
return UnitTimer.execute(this, { timeout, duration }, iterations);
|
|
880
892
|
}
|
|
881
893
|
transition(transition, duration = 0, easing) {
|
|
882
894
|
return UnitTimer.execute(this, { transition, duration, easing }, 1);
|
|
@@ -884,7 +896,7 @@
|
|
|
884
896
|
static execute(timer, options, iterations) {
|
|
885
897
|
const props = { options, iterations, snapshot: Unit.snapshot(Unit.currentUnit) };
|
|
886
898
|
if (timer.unit === null || timer.unit._.state === 'finalized') {
|
|
887
|
-
timer.unit = new Unit(Unit.currentUnit,
|
|
899
|
+
timer.unit = new Unit(Unit.currentUnit, UnitTimer.Component, props);
|
|
888
900
|
}
|
|
889
901
|
else if (timer.queue.length === 0) {
|
|
890
902
|
timer.queue.push(props);
|
|
@@ -897,18 +909,18 @@
|
|
|
897
909
|
}
|
|
898
910
|
static next(timer) {
|
|
899
911
|
if (timer.queue.length > 0) {
|
|
900
|
-
timer.unit = new Unit(Unit.currentUnit,
|
|
912
|
+
timer.unit = new Unit(Unit.currentUnit, UnitTimer.Component, timer.queue.shift());
|
|
901
913
|
timer.unit.on('finalize', () => UnitTimer.next(timer));
|
|
902
914
|
}
|
|
903
915
|
}
|
|
904
916
|
static Component(unit, { options, iterations, snapshot }) {
|
|
905
917
|
let counter = 0;
|
|
906
|
-
let timer = new Timer({
|
|
907
|
-
function
|
|
908
|
-
if (options.
|
|
909
|
-
Unit.scope(snapshot, options.
|
|
918
|
+
let timer = new Timer({ timeout, transition, duration: options.duration, easing: options.easing });
|
|
919
|
+
function timeout() {
|
|
920
|
+
if (options.timeout)
|
|
921
|
+
Unit.scope(snapshot, options.timeout);
|
|
910
922
|
if (iterations <= 0 || counter < iterations - 1) {
|
|
911
|
-
timer = new Timer({
|
|
923
|
+
timer = new Timer({ timeout, transition, duration: options.duration, easing: options.easing });
|
|
912
924
|
}
|
|
913
925
|
else {
|
|
914
926
|
unit.finalize();
|
|
@@ -923,29 +935,31 @@
|
|
|
923
935
|
}
|
|
924
936
|
}
|
|
925
937
|
|
|
926
|
-
const xnew$1 = Object.assign(
|
|
938
|
+
const xnew$1 = Object.assign(
|
|
939
|
+
/**
|
|
940
|
+
* creates a new Unit component
|
|
941
|
+
* xnew(Component?: Function | string, props?: Object): Unit;
|
|
942
|
+
* xnew(target: HTMLElement | SVGElement | string, Component?: Function | string, props?: Object): Unit;
|
|
943
|
+
* @param target - HTMLElement | SVGElement, or HTML tag for new element
|
|
944
|
+
* @param Component - component function
|
|
945
|
+
* @param props - properties for component function
|
|
946
|
+
* @returns a new Unit instance
|
|
947
|
+
* @example
|
|
948
|
+
* const unit = xnew(MyComponent, { data: 0 })
|
|
949
|
+
* const unit = xnew(element, MyComponent, { data: 0 })
|
|
950
|
+
* const unit = xnew('<div>', MyComponent, { data: 0 })
|
|
951
|
+
*/
|
|
952
|
+
function (...args) {
|
|
927
953
|
if (Unit.rootUnit === undefined)
|
|
928
954
|
Unit.reset();
|
|
929
|
-
|
|
930
|
-
if (args[0] instanceof HTMLElement || args[0] instanceof SVGElement) {
|
|
931
|
-
target = args.shift(); // an existing html element
|
|
932
|
-
}
|
|
933
|
-
else if (typeof args[0] === 'string' && args[0].match(/<((\w+)[^>]*?)\/?>/)) {
|
|
934
|
-
target = args.shift();
|
|
935
|
-
}
|
|
936
|
-
else {
|
|
937
|
-
target = null;
|
|
938
|
-
}
|
|
939
|
-
const Component = args.shift();
|
|
940
|
-
const props = args.shift();
|
|
941
|
-
const unit = new Unit(Unit.currentUnit, target, Component, props);
|
|
942
|
-
return unit;
|
|
955
|
+
return new Unit(Unit.currentUnit, ...args);
|
|
943
956
|
}, {
|
|
944
957
|
/**
|
|
945
|
-
* Creates a
|
|
946
|
-
*
|
|
947
|
-
* @
|
|
948
|
-
* @
|
|
958
|
+
* Creates a child HTML/SVG element inside the current component's element.
|
|
959
|
+
* Must be called during component initialization (before setup completes).
|
|
960
|
+
* @param target - An existing HTML/SVG element, or a tag string like `'<div>'`
|
|
961
|
+
* @returns The provided element, or the newly created element
|
|
962
|
+
* @throws Error if called after the component has finished initializing
|
|
949
963
|
* @example
|
|
950
964
|
* const div = xnew.nest('<div>')
|
|
951
965
|
* div.textContent = 'Hello'
|
|
@@ -958,7 +972,7 @@
|
|
|
958
972
|
return Unit.nest(Unit.currentUnit, target);
|
|
959
973
|
}
|
|
960
974
|
catch (error) {
|
|
961
|
-
console.error('xnew.nest(target:
|
|
975
|
+
console.error('xnew.nest(target: UnitElement | string): ', error);
|
|
962
976
|
throw error;
|
|
963
977
|
}
|
|
964
978
|
},
|
|
@@ -984,17 +998,43 @@
|
|
|
984
998
|
throw error;
|
|
985
999
|
}
|
|
986
1000
|
},
|
|
1001
|
+
append(parent, ...args) {
|
|
1002
|
+
var _a;
|
|
1003
|
+
try {
|
|
1004
|
+
const snapshot = (_a = parent._.afterSnapshot) !== null && _a !== void 0 ? _a : Unit.snapshot(parent);
|
|
1005
|
+
Unit.scope(snapshot, () => {
|
|
1006
|
+
new Unit(parent, ...args);
|
|
1007
|
+
});
|
|
1008
|
+
}
|
|
1009
|
+
catch (error) {
|
|
1010
|
+
console.error('xnew.append(parent: Unit, ...args: UnitArgs): ', error);
|
|
1011
|
+
throw error;
|
|
1012
|
+
}
|
|
1013
|
+
},
|
|
1014
|
+
next(unit, ...args) {
|
|
1015
|
+
var _a;
|
|
1016
|
+
try {
|
|
1017
|
+
const parent = unit._.parent;
|
|
1018
|
+
const snapshot = (_a = parent._.afterSnapshot) !== null && _a !== void 0 ? _a : Unit.snapshot(parent);
|
|
1019
|
+
Unit.scope(snapshot, () => {
|
|
1020
|
+
new Unit(parent, ...args);
|
|
1021
|
+
});
|
|
1022
|
+
}
|
|
1023
|
+
catch (error) {
|
|
1024
|
+
console.error('xnew.next(unit: Unit, ...args: UnitArgs): ', error);
|
|
1025
|
+
throw error;
|
|
1026
|
+
}
|
|
1027
|
+
},
|
|
987
1028
|
/**
|
|
988
|
-
* Gets
|
|
989
|
-
* @param key - component function
|
|
990
|
-
* @returns The
|
|
1029
|
+
* Gets the Unit instance associated with the given component in the ancestor context chain
|
|
1030
|
+
* @param key - component function used as context key
|
|
1031
|
+
* @returns The Unit instance registered with the given component, or undefined if not found
|
|
991
1032
|
* @example
|
|
992
|
-
* // Create unit
|
|
993
|
-
* const
|
|
994
|
-
* ------------------------------
|
|
1033
|
+
* // Create parent unit with component A
|
|
1034
|
+
* const parent = xnew(A);
|
|
995
1035
|
*
|
|
996
|
-
* //
|
|
997
|
-
* const
|
|
1036
|
+
* // Inside a child component, get the parent unit
|
|
1037
|
+
* const parentUnit = xnew.context(A)
|
|
998
1038
|
*/
|
|
999
1039
|
context(key) {
|
|
1000
1040
|
try {
|
|
@@ -1007,24 +1047,22 @@
|
|
|
1007
1047
|
},
|
|
1008
1048
|
/**
|
|
1009
1049
|
* Registers a promise with the current component for lifecycle management
|
|
1010
|
-
* @param promise - Promise to register
|
|
1050
|
+
* @param promise - A Promise, async function, or Unit to register
|
|
1011
1051
|
* @returns UnitPromise wrapper for chaining
|
|
1012
1052
|
* @example
|
|
1013
1053
|
* xnew.promise(fetchData()).then(data => console.log(data))
|
|
1014
1054
|
*/
|
|
1015
1055
|
promise(promise) {
|
|
1016
1056
|
try {
|
|
1017
|
-
const Component = Unit.currentUnit._.currentComponent;
|
|
1018
1057
|
let unitPromise;
|
|
1019
1058
|
if (promise instanceof Unit) {
|
|
1020
|
-
unitPromise =
|
|
1021
|
-
.then(() => promise._.results);
|
|
1059
|
+
unitPromise = UnitPromise.all(promise._.promises).then(() => promise._.results);
|
|
1022
1060
|
}
|
|
1023
1061
|
else if (promise instanceof Promise) {
|
|
1024
|
-
unitPromise = new UnitPromise(promise
|
|
1062
|
+
unitPromise = new UnitPromise(promise);
|
|
1025
1063
|
}
|
|
1026
1064
|
else {
|
|
1027
|
-
unitPromise = new UnitPromise(new Promise(xnew$1.scope(promise))
|
|
1065
|
+
unitPromise = new UnitPromise(new Promise(xnew$1.scope(promise)));
|
|
1028
1066
|
}
|
|
1029
1067
|
Unit.currentUnit._.promises.push(unitPromise);
|
|
1030
1068
|
return unitPromise;
|
|
@@ -1044,8 +1082,7 @@
|
|
|
1044
1082
|
then(callback) {
|
|
1045
1083
|
try {
|
|
1046
1084
|
const currentUnit = Unit.currentUnit;
|
|
1047
|
-
return
|
|
1048
|
-
.then(() => callback(currentUnit._.results));
|
|
1085
|
+
return UnitPromise.all(Unit.currentUnit._.promises).then(() => callback(currentUnit._.results));
|
|
1049
1086
|
}
|
|
1050
1087
|
catch (error) {
|
|
1051
1088
|
console.error('xnew.then(callback: Function): ', error);
|
|
@@ -1061,7 +1098,7 @@
|
|
|
1061
1098
|
*/
|
|
1062
1099
|
catch(callback) {
|
|
1063
1100
|
try {
|
|
1064
|
-
return
|
|
1101
|
+
return UnitPromise.all(Unit.currentUnit._.promises)
|
|
1065
1102
|
.catch(callback);
|
|
1066
1103
|
}
|
|
1067
1104
|
catch (error) {
|
|
@@ -1070,35 +1107,67 @@
|
|
|
1070
1107
|
}
|
|
1071
1108
|
},
|
|
1072
1109
|
/**
|
|
1073
|
-
*
|
|
1074
|
-
* @param
|
|
1075
|
-
* @returns
|
|
1110
|
+
* Executes callback after all registered promises settle (resolve or reject)
|
|
1111
|
+
* @param callback - Function to call after promises settle
|
|
1112
|
+
* @returns UnitPromise for chaining
|
|
1076
1113
|
* @example
|
|
1077
|
-
* xnew.
|
|
1114
|
+
* xnew.finally(() => console.log('All promises settled'))
|
|
1078
1115
|
*/
|
|
1079
|
-
|
|
1116
|
+
finally(callback) {
|
|
1080
1117
|
try {
|
|
1081
|
-
|
|
1118
|
+
return UnitPromise.all(Unit.currentUnit._.promises).finally(callback);
|
|
1082
1119
|
}
|
|
1083
1120
|
catch (error) {
|
|
1084
|
-
console.error('xnew.
|
|
1121
|
+
console.error('xnew.finally(callback: Function): ', error);
|
|
1085
1122
|
throw error;
|
|
1086
1123
|
}
|
|
1087
1124
|
},
|
|
1125
|
+
resolvers() {
|
|
1126
|
+
let state = null;
|
|
1127
|
+
let resolve = null;
|
|
1128
|
+
let reject = null;
|
|
1129
|
+
const unitPromise = new UnitPromise(new Promise((res, rej) => {
|
|
1130
|
+
if (state === 'resolved') {
|
|
1131
|
+
res(null);
|
|
1132
|
+
}
|
|
1133
|
+
else if (state === 'rejected') {
|
|
1134
|
+
rej();
|
|
1135
|
+
}
|
|
1136
|
+
else {
|
|
1137
|
+
resolve = res;
|
|
1138
|
+
reject = rej;
|
|
1139
|
+
state = 'pending';
|
|
1140
|
+
}
|
|
1141
|
+
}));
|
|
1142
|
+
Unit.currentUnit._.promises.push(unitPromise);
|
|
1143
|
+
return {
|
|
1144
|
+
resolve() {
|
|
1145
|
+
if (state === 'pending') {
|
|
1146
|
+
resolve === null || resolve === void 0 ? void 0 : resolve(null);
|
|
1147
|
+
}
|
|
1148
|
+
state = 'resolved';
|
|
1149
|
+
},
|
|
1150
|
+
reject() {
|
|
1151
|
+
if (state === 'pending') {
|
|
1152
|
+
reject === null || reject === void 0 ? void 0 : reject();
|
|
1153
|
+
}
|
|
1154
|
+
state = 'rejected';
|
|
1155
|
+
}
|
|
1156
|
+
};
|
|
1157
|
+
},
|
|
1088
1158
|
/**
|
|
1089
|
-
*
|
|
1090
|
-
* @param
|
|
1091
|
-
* @returns
|
|
1159
|
+
* Outputs a value to the current unit's promise results
|
|
1160
|
+
* @param object - object to output for the promise
|
|
1161
|
+
* @returns void
|
|
1092
1162
|
* @example
|
|
1093
|
-
* xnew.
|
|
1163
|
+
* xnew.output({ data: 123});
|
|
1094
1164
|
*/
|
|
1095
|
-
|
|
1165
|
+
output(object) {
|
|
1096
1166
|
try {
|
|
1097
|
-
|
|
1098
|
-
.finally(callback);
|
|
1167
|
+
Object.assign(Unit.currentUnit._.results, object);
|
|
1099
1168
|
}
|
|
1100
1169
|
catch (error) {
|
|
1101
|
-
console.error('xnew.
|
|
1170
|
+
console.error('xnew.output(object?: Record<string, any>): ', error);
|
|
1102
1171
|
throw error;
|
|
1103
1172
|
}
|
|
1104
1173
|
},
|
|
@@ -1136,7 +1205,7 @@
|
|
|
1136
1205
|
/**
|
|
1137
1206
|
* Emits a custom event to components
|
|
1138
1207
|
* @param type - Event type to emit (prefix with '+' for global events, '-' for local events)
|
|
1139
|
-
* @param
|
|
1208
|
+
* @param props - Event properties object to pass to listeners
|
|
1140
1209
|
* @returns void
|
|
1141
1210
|
* @example
|
|
1142
1211
|
* xnew.emit('+globalevent', { data: 123 }); // Global event
|
|
@@ -1153,7 +1222,7 @@
|
|
|
1153
1222
|
},
|
|
1154
1223
|
/**
|
|
1155
1224
|
* Executes a callback once after a delay, managed by component lifecycle
|
|
1156
|
-
* @param callback - Function to execute after
|
|
1225
|
+
* @param callback - Function to execute after duration
|
|
1157
1226
|
* @param duration - Duration in milliseconds
|
|
1158
1227
|
* @returns Object with clear() method to cancel the timeout
|
|
1159
1228
|
* @example
|
|
@@ -1275,7 +1344,7 @@
|
|
|
1275
1344
|
}
|
|
1276
1345
|
const canvas = xnew$1(`<canvas width="${width}" height="${height}" style="width: 100%; height: 100%; vertical-align: bottom;">`);
|
|
1277
1346
|
return {
|
|
1278
|
-
get canvas() { return canvas.element; }
|
|
1347
|
+
get canvas() { return canvas.element; },
|
|
1279
1348
|
};
|
|
1280
1349
|
}
|
|
1281
1350
|
|
|
@@ -1561,24 +1630,46 @@
|
|
|
1561
1630
|
}
|
|
1562
1631
|
}
|
|
1563
1632
|
|
|
1564
|
-
function
|
|
1565
|
-
let scene = null;
|
|
1633
|
+
function Scene(unit) {
|
|
1566
1634
|
return {
|
|
1567
|
-
|
|
1568
|
-
|
|
1635
|
+
moveTo(Component, props) {
|
|
1636
|
+
xnew$1.next(unit, Component, props);
|
|
1637
|
+
unit.finalize();
|
|
1569
1638
|
},
|
|
1570
|
-
|
|
1571
|
-
|
|
1572
|
-
},
|
|
1573
|
-
next(Component, props) {
|
|
1574
|
-
var _a;
|
|
1575
|
-
// scene change
|
|
1576
|
-
(_a = unit.scene) === null || _a === void 0 ? void 0 : _a.finalize();
|
|
1577
|
-
unit.scene = xnew$1(Component, props);
|
|
1639
|
+
append(Component, props) {
|
|
1640
|
+
xnew$1.append(unit, Component, props);
|
|
1578
1641
|
}
|
|
1579
1642
|
};
|
|
1580
1643
|
}
|
|
1581
1644
|
|
|
1645
|
+
class XImage {
|
|
1646
|
+
constructor(...args) {
|
|
1647
|
+
if (args[0] instanceof HTMLCanvasElement) {
|
|
1648
|
+
this.canvas = args[0];
|
|
1649
|
+
}
|
|
1650
|
+
else {
|
|
1651
|
+
const canvas = document.createElement('canvas');
|
|
1652
|
+
canvas.width = args[0];
|
|
1653
|
+
canvas.height = args[1];
|
|
1654
|
+
this.canvas = canvas;
|
|
1655
|
+
}
|
|
1656
|
+
}
|
|
1657
|
+
crop(x, y, width, height) {
|
|
1658
|
+
var _a;
|
|
1659
|
+
const canvas = document.createElement('canvas');
|
|
1660
|
+
canvas.width = width;
|
|
1661
|
+
canvas.height = height;
|
|
1662
|
+
(_a = canvas.getContext('2d')) === null || _a === void 0 ? void 0 : _a.drawImage(this.canvas, x, y, width, height, 0, 0, width, height);
|
|
1663
|
+
return new XImage(canvas);
|
|
1664
|
+
}
|
|
1665
|
+
download(filename) {
|
|
1666
|
+
const link = document.createElement('a');
|
|
1667
|
+
link.download = filename;
|
|
1668
|
+
link.href = this.canvas.toDataURL('image/png');
|
|
1669
|
+
link.click();
|
|
1670
|
+
}
|
|
1671
|
+
}
|
|
1672
|
+
|
|
1582
1673
|
const context = new window.AudioContext();
|
|
1583
1674
|
const master = context.createGain();
|
|
1584
1675
|
//----------------------------------------------------------------------------------------------------
|
|
@@ -1811,7 +1902,7 @@
|
|
|
1811
1902
|
Panel,
|
|
1812
1903
|
Accordion,
|
|
1813
1904
|
Popup,
|
|
1814
|
-
|
|
1905
|
+
Scene,
|
|
1815
1906
|
};
|
|
1816
1907
|
const audio = {
|
|
1817
1908
|
load(path) {
|
|
@@ -1840,7 +1931,12 @@
|
|
|
1840
1931
|
master.gain.value = value;
|
|
1841
1932
|
}
|
|
1842
1933
|
};
|
|
1843
|
-
const
|
|
1934
|
+
const image = {
|
|
1935
|
+
from(canvas) {
|
|
1936
|
+
return new XImage(canvas);
|
|
1937
|
+
}
|
|
1938
|
+
};
|
|
1939
|
+
const xnew = Object.assign(xnew$1, { basics, audio, image });
|
|
1844
1940
|
|
|
1845
1941
|
return xnew;
|
|
1846
1942
|
|
package/dist/xnew.mjs
CHANGED
|
@@ -186,7 +186,7 @@ class Timer {
|
|
|
186
186
|
this.id = null;
|
|
187
187
|
this.time = { start: 0.0, processed: 0.0 };
|
|
188
188
|
(_b = (_a = this.options).transition) === null || _b === void 0 ? void 0 : _b.call(_a, 1.0);
|
|
189
|
-
(_d = (_c = this.options).
|
|
189
|
+
(_d = (_c = this.options).timeout) === null || _d === void 0 ? void 0 : _d.call(_c);
|
|
190
190
|
this.clear();
|
|
191
191
|
}, this.options.duration - this.time.processed);
|
|
192
192
|
this.time.start = Date.now();
|
|
@@ -513,16 +513,26 @@ function pointer(element, event) {
|
|
|
513
513
|
return { position };
|
|
514
514
|
}
|
|
515
515
|
|
|
516
|
-
//----------------------------------------------------------------------------------------------------
|
|
517
|
-
// utils
|
|
518
|
-
//----------------------------------------------------------------------------------------------------
|
|
519
516
|
const SYSTEM_EVENTS = ['start', 'update', 'render', 'stop', 'finalize'];
|
|
520
517
|
//----------------------------------------------------------------------------------------------------
|
|
521
518
|
// unit
|
|
522
519
|
//----------------------------------------------------------------------------------------------------
|
|
523
520
|
class Unit {
|
|
524
|
-
constructor(parent,
|
|
521
|
+
constructor(parent, ...args) {
|
|
525
522
|
var _a;
|
|
523
|
+
let target;
|
|
524
|
+
let Component;
|
|
525
|
+
let props;
|
|
526
|
+
if (args[0] instanceof HTMLElement || args[0] instanceof SVGElement || typeof args[0] === 'string') {
|
|
527
|
+
target = args[0];
|
|
528
|
+
Component = args[1];
|
|
529
|
+
props = args[2];
|
|
530
|
+
}
|
|
531
|
+
else {
|
|
532
|
+
target = null;
|
|
533
|
+
Component = args[0];
|
|
534
|
+
props = args[1];
|
|
535
|
+
}
|
|
526
536
|
const backup = Unit.currentUnit;
|
|
527
537
|
Unit.currentUnit = this;
|
|
528
538
|
parent === null || parent === void 0 ? void 0 : parent._.children.push(this);
|
|
@@ -555,6 +565,7 @@ class Unit {
|
|
|
555
565
|
currentElement: baseElement,
|
|
556
566
|
currentContext: baseContext,
|
|
557
567
|
currentComponent: null,
|
|
568
|
+
afterSnapshot: null,
|
|
558
569
|
ancestors: parent ? [parent, ...parent._.ancestors] : [],
|
|
559
570
|
children: [],
|
|
560
571
|
nestElements: [],
|
|
@@ -575,6 +586,7 @@ class Unit {
|
|
|
575
586
|
if (this._.state === 'invoked') {
|
|
576
587
|
this._.state = 'initialized';
|
|
577
588
|
}
|
|
589
|
+
this._.afterSnapshot = Unit.snapshot(this);
|
|
578
590
|
Unit.currentUnit = backup;
|
|
579
591
|
}
|
|
580
592
|
get element() {
|
|
@@ -644,7 +656,7 @@ class Unit {
|
|
|
644
656
|
return element;
|
|
645
657
|
}
|
|
646
658
|
else {
|
|
647
|
-
throw new Error(`xnew.nest: invalid
|
|
659
|
+
throw new Error(`xnew.nest: invalid tag string [${target}]`);
|
|
648
660
|
}
|
|
649
661
|
}
|
|
650
662
|
}
|
|
@@ -686,7 +698,7 @@ class Unit {
|
|
|
686
698
|
Object.defineProperty(unit._.defines, key, wrapper);
|
|
687
699
|
Object.defineProperty(unit, key, wrapper);
|
|
688
700
|
});
|
|
689
|
-
return defines;
|
|
701
|
+
return Object.assign({}, unit._.defines);
|
|
690
702
|
}
|
|
691
703
|
}
|
|
692
704
|
static start(unit) {
|
|
@@ -723,7 +735,7 @@ class Unit {
|
|
|
723
735
|
static reset() {
|
|
724
736
|
var _a;
|
|
725
737
|
(_a = Unit.rootUnit) === null || _a === void 0 ? void 0 : _a.finalize();
|
|
726
|
-
Unit.currentUnit = Unit.rootUnit = new Unit(null
|
|
738
|
+
Unit.currentUnit = Unit.rootUnit = new Unit(null);
|
|
727
739
|
const ticker = new AnimationTicker(() => {
|
|
728
740
|
Unit.start(Unit.rootUnit);
|
|
729
741
|
Unit.update(Unit.rootUnit);
|
|
@@ -763,7 +775,7 @@ class Unit {
|
|
|
763
775
|
}
|
|
764
776
|
static getContext(unit, key) {
|
|
765
777
|
for (let context = unit._.currentContext; context.previous !== null; context = context.previous) {
|
|
766
|
-
if (context.value === Unit.currentUnit
|
|
778
|
+
if (context.value === Unit.currentUnit)
|
|
767
779
|
continue;
|
|
768
780
|
if (context.key === key)
|
|
769
781
|
return context.value;
|
|
@@ -842,13 +854,13 @@ Unit.type2units = new MapSet();
|
|
|
842
854
|
// extensions
|
|
843
855
|
//----------------------------------------------------------------------------------------------------
|
|
844
856
|
class UnitPromise {
|
|
845
|
-
constructor(promise
|
|
846
|
-
this.promise = promise;
|
|
847
|
-
this.Component = Component;
|
|
848
|
-
}
|
|
857
|
+
constructor(promise) { this.promise = promise; }
|
|
849
858
|
then(callback) { return this.wrap('then', callback); }
|
|
850
859
|
catch(callback) { return this.wrap('catch', callback); }
|
|
851
860
|
finally(callback) { return this.wrap('finally', callback); }
|
|
861
|
+
static all(promises) {
|
|
862
|
+
return new UnitPromise(Promise.all(promises.map(p => p.promise)));
|
|
863
|
+
}
|
|
852
864
|
wrap(key, callback) {
|
|
853
865
|
const snapshot = Unit.snapshot(Unit.currentUnit);
|
|
854
866
|
this.promise = this.promise[key]((...args) => Unit.scope(snapshot, callback, ...args));
|
|
@@ -866,11 +878,11 @@ class UnitTimer {
|
|
|
866
878
|
(_a = this.unit) === null || _a === void 0 ? void 0 : _a.finalize();
|
|
867
879
|
this.unit = null;
|
|
868
880
|
}
|
|
869
|
-
timeout(
|
|
870
|
-
return UnitTimer.execute(this, {
|
|
881
|
+
timeout(timeout, duration = 0) {
|
|
882
|
+
return UnitTimer.execute(this, { timeout, duration }, 1);
|
|
871
883
|
}
|
|
872
|
-
interval(
|
|
873
|
-
return UnitTimer.execute(this, {
|
|
884
|
+
interval(timeout, duration = 0, iterations = 0) {
|
|
885
|
+
return UnitTimer.execute(this, { timeout, duration }, iterations);
|
|
874
886
|
}
|
|
875
887
|
transition(transition, duration = 0, easing) {
|
|
876
888
|
return UnitTimer.execute(this, { transition, duration, easing }, 1);
|
|
@@ -878,7 +890,7 @@ class UnitTimer {
|
|
|
878
890
|
static execute(timer, options, iterations) {
|
|
879
891
|
const props = { options, iterations, snapshot: Unit.snapshot(Unit.currentUnit) };
|
|
880
892
|
if (timer.unit === null || timer.unit._.state === 'finalized') {
|
|
881
|
-
timer.unit = new Unit(Unit.currentUnit,
|
|
893
|
+
timer.unit = new Unit(Unit.currentUnit, UnitTimer.Component, props);
|
|
882
894
|
}
|
|
883
895
|
else if (timer.queue.length === 0) {
|
|
884
896
|
timer.queue.push(props);
|
|
@@ -891,18 +903,18 @@ class UnitTimer {
|
|
|
891
903
|
}
|
|
892
904
|
static next(timer) {
|
|
893
905
|
if (timer.queue.length > 0) {
|
|
894
|
-
timer.unit = new Unit(Unit.currentUnit,
|
|
906
|
+
timer.unit = new Unit(Unit.currentUnit, UnitTimer.Component, timer.queue.shift());
|
|
895
907
|
timer.unit.on('finalize', () => UnitTimer.next(timer));
|
|
896
908
|
}
|
|
897
909
|
}
|
|
898
910
|
static Component(unit, { options, iterations, snapshot }) {
|
|
899
911
|
let counter = 0;
|
|
900
|
-
let timer = new Timer({
|
|
901
|
-
function
|
|
902
|
-
if (options.
|
|
903
|
-
Unit.scope(snapshot, options.
|
|
912
|
+
let timer = new Timer({ timeout, transition, duration: options.duration, easing: options.easing });
|
|
913
|
+
function timeout() {
|
|
914
|
+
if (options.timeout)
|
|
915
|
+
Unit.scope(snapshot, options.timeout);
|
|
904
916
|
if (iterations <= 0 || counter < iterations - 1) {
|
|
905
|
-
timer = new Timer({
|
|
917
|
+
timer = new Timer({ timeout, transition, duration: options.duration, easing: options.easing });
|
|
906
918
|
}
|
|
907
919
|
else {
|
|
908
920
|
unit.finalize();
|
|
@@ -917,29 +929,31 @@ class UnitTimer {
|
|
|
917
929
|
}
|
|
918
930
|
}
|
|
919
931
|
|
|
920
|
-
const xnew$1 = Object.assign(
|
|
932
|
+
const xnew$1 = Object.assign(
|
|
933
|
+
/**
|
|
934
|
+
* creates a new Unit component
|
|
935
|
+
* xnew(Component?: Function | string, props?: Object): Unit;
|
|
936
|
+
* xnew(target: HTMLElement | SVGElement | string, Component?: Function | string, props?: Object): Unit;
|
|
937
|
+
* @param target - HTMLElement | SVGElement, or HTML tag for new element
|
|
938
|
+
* @param Component - component function
|
|
939
|
+
* @param props - properties for component function
|
|
940
|
+
* @returns a new Unit instance
|
|
941
|
+
* @example
|
|
942
|
+
* const unit = xnew(MyComponent, { data: 0 })
|
|
943
|
+
* const unit = xnew(element, MyComponent, { data: 0 })
|
|
944
|
+
* const unit = xnew('<div>', MyComponent, { data: 0 })
|
|
945
|
+
*/
|
|
946
|
+
function (...args) {
|
|
921
947
|
if (Unit.rootUnit === undefined)
|
|
922
948
|
Unit.reset();
|
|
923
|
-
|
|
924
|
-
if (args[0] instanceof HTMLElement || args[0] instanceof SVGElement) {
|
|
925
|
-
target = args.shift(); // an existing html element
|
|
926
|
-
}
|
|
927
|
-
else if (typeof args[0] === 'string' && args[0].match(/<((\w+)[^>]*?)\/?>/)) {
|
|
928
|
-
target = args.shift();
|
|
929
|
-
}
|
|
930
|
-
else {
|
|
931
|
-
target = null;
|
|
932
|
-
}
|
|
933
|
-
const Component = args.shift();
|
|
934
|
-
const props = args.shift();
|
|
935
|
-
const unit = new Unit(Unit.currentUnit, target, Component, props);
|
|
936
|
-
return unit;
|
|
949
|
+
return new Unit(Unit.currentUnit, ...args);
|
|
937
950
|
}, {
|
|
938
951
|
/**
|
|
939
|
-
* Creates a
|
|
940
|
-
*
|
|
941
|
-
* @
|
|
942
|
-
* @
|
|
952
|
+
* Creates a child HTML/SVG element inside the current component's element.
|
|
953
|
+
* Must be called during component initialization (before setup completes).
|
|
954
|
+
* @param target - An existing HTML/SVG element, or a tag string like `'<div>'`
|
|
955
|
+
* @returns The provided element, or the newly created element
|
|
956
|
+
* @throws Error if called after the component has finished initializing
|
|
943
957
|
* @example
|
|
944
958
|
* const div = xnew.nest('<div>')
|
|
945
959
|
* div.textContent = 'Hello'
|
|
@@ -952,7 +966,7 @@ const xnew$1 = Object.assign(function (...args) {
|
|
|
952
966
|
return Unit.nest(Unit.currentUnit, target);
|
|
953
967
|
}
|
|
954
968
|
catch (error) {
|
|
955
|
-
console.error('xnew.nest(target:
|
|
969
|
+
console.error('xnew.nest(target: UnitElement | string): ', error);
|
|
956
970
|
throw error;
|
|
957
971
|
}
|
|
958
972
|
},
|
|
@@ -978,17 +992,43 @@ const xnew$1 = Object.assign(function (...args) {
|
|
|
978
992
|
throw error;
|
|
979
993
|
}
|
|
980
994
|
},
|
|
995
|
+
append(parent, ...args) {
|
|
996
|
+
var _a;
|
|
997
|
+
try {
|
|
998
|
+
const snapshot = (_a = parent._.afterSnapshot) !== null && _a !== void 0 ? _a : Unit.snapshot(parent);
|
|
999
|
+
Unit.scope(snapshot, () => {
|
|
1000
|
+
new Unit(parent, ...args);
|
|
1001
|
+
});
|
|
1002
|
+
}
|
|
1003
|
+
catch (error) {
|
|
1004
|
+
console.error('xnew.append(parent: Unit, ...args: UnitArgs): ', error);
|
|
1005
|
+
throw error;
|
|
1006
|
+
}
|
|
1007
|
+
},
|
|
1008
|
+
next(unit, ...args) {
|
|
1009
|
+
var _a;
|
|
1010
|
+
try {
|
|
1011
|
+
const parent = unit._.parent;
|
|
1012
|
+
const snapshot = (_a = parent._.afterSnapshot) !== null && _a !== void 0 ? _a : Unit.snapshot(parent);
|
|
1013
|
+
Unit.scope(snapshot, () => {
|
|
1014
|
+
new Unit(parent, ...args);
|
|
1015
|
+
});
|
|
1016
|
+
}
|
|
1017
|
+
catch (error) {
|
|
1018
|
+
console.error('xnew.next(unit: Unit, ...args: UnitArgs): ', error);
|
|
1019
|
+
throw error;
|
|
1020
|
+
}
|
|
1021
|
+
},
|
|
981
1022
|
/**
|
|
982
|
-
* Gets
|
|
983
|
-
* @param key - component function
|
|
984
|
-
* @returns The
|
|
1023
|
+
* Gets the Unit instance associated with the given component in the ancestor context chain
|
|
1024
|
+
* @param key - component function used as context key
|
|
1025
|
+
* @returns The Unit instance registered with the given component, or undefined if not found
|
|
985
1026
|
* @example
|
|
986
|
-
* // Create unit
|
|
987
|
-
* const
|
|
988
|
-
* ------------------------------
|
|
1027
|
+
* // Create parent unit with component A
|
|
1028
|
+
* const parent = xnew(A);
|
|
989
1029
|
*
|
|
990
|
-
* //
|
|
991
|
-
* const
|
|
1030
|
+
* // Inside a child component, get the parent unit
|
|
1031
|
+
* const parentUnit = xnew.context(A)
|
|
992
1032
|
*/
|
|
993
1033
|
context(key) {
|
|
994
1034
|
try {
|
|
@@ -1001,24 +1041,22 @@ const xnew$1 = Object.assign(function (...args) {
|
|
|
1001
1041
|
},
|
|
1002
1042
|
/**
|
|
1003
1043
|
* Registers a promise with the current component for lifecycle management
|
|
1004
|
-
* @param promise - Promise to register
|
|
1044
|
+
* @param promise - A Promise, async function, or Unit to register
|
|
1005
1045
|
* @returns UnitPromise wrapper for chaining
|
|
1006
1046
|
* @example
|
|
1007
1047
|
* xnew.promise(fetchData()).then(data => console.log(data))
|
|
1008
1048
|
*/
|
|
1009
1049
|
promise(promise) {
|
|
1010
1050
|
try {
|
|
1011
|
-
const Component = Unit.currentUnit._.currentComponent;
|
|
1012
1051
|
let unitPromise;
|
|
1013
1052
|
if (promise instanceof Unit) {
|
|
1014
|
-
unitPromise =
|
|
1015
|
-
.then(() => promise._.results);
|
|
1053
|
+
unitPromise = UnitPromise.all(promise._.promises).then(() => promise._.results);
|
|
1016
1054
|
}
|
|
1017
1055
|
else if (promise instanceof Promise) {
|
|
1018
|
-
unitPromise = new UnitPromise(promise
|
|
1056
|
+
unitPromise = new UnitPromise(promise);
|
|
1019
1057
|
}
|
|
1020
1058
|
else {
|
|
1021
|
-
unitPromise = new UnitPromise(new Promise(xnew$1.scope(promise))
|
|
1059
|
+
unitPromise = new UnitPromise(new Promise(xnew$1.scope(promise)));
|
|
1022
1060
|
}
|
|
1023
1061
|
Unit.currentUnit._.promises.push(unitPromise);
|
|
1024
1062
|
return unitPromise;
|
|
@@ -1038,8 +1076,7 @@ const xnew$1 = Object.assign(function (...args) {
|
|
|
1038
1076
|
then(callback) {
|
|
1039
1077
|
try {
|
|
1040
1078
|
const currentUnit = Unit.currentUnit;
|
|
1041
|
-
return
|
|
1042
|
-
.then(() => callback(currentUnit._.results));
|
|
1079
|
+
return UnitPromise.all(Unit.currentUnit._.promises).then(() => callback(currentUnit._.results));
|
|
1043
1080
|
}
|
|
1044
1081
|
catch (error) {
|
|
1045
1082
|
console.error('xnew.then(callback: Function): ', error);
|
|
@@ -1055,7 +1092,7 @@ const xnew$1 = Object.assign(function (...args) {
|
|
|
1055
1092
|
*/
|
|
1056
1093
|
catch(callback) {
|
|
1057
1094
|
try {
|
|
1058
|
-
return
|
|
1095
|
+
return UnitPromise.all(Unit.currentUnit._.promises)
|
|
1059
1096
|
.catch(callback);
|
|
1060
1097
|
}
|
|
1061
1098
|
catch (error) {
|
|
@@ -1064,35 +1101,67 @@ const xnew$1 = Object.assign(function (...args) {
|
|
|
1064
1101
|
}
|
|
1065
1102
|
},
|
|
1066
1103
|
/**
|
|
1067
|
-
*
|
|
1068
|
-
* @param
|
|
1069
|
-
* @returns
|
|
1104
|
+
* Executes callback after all registered promises settle (resolve or reject)
|
|
1105
|
+
* @param callback - Function to call after promises settle
|
|
1106
|
+
* @returns UnitPromise for chaining
|
|
1070
1107
|
* @example
|
|
1071
|
-
* xnew.
|
|
1108
|
+
* xnew.finally(() => console.log('All promises settled'))
|
|
1072
1109
|
*/
|
|
1073
|
-
|
|
1110
|
+
finally(callback) {
|
|
1074
1111
|
try {
|
|
1075
|
-
|
|
1112
|
+
return UnitPromise.all(Unit.currentUnit._.promises).finally(callback);
|
|
1076
1113
|
}
|
|
1077
1114
|
catch (error) {
|
|
1078
|
-
console.error('xnew.
|
|
1115
|
+
console.error('xnew.finally(callback: Function): ', error);
|
|
1079
1116
|
throw error;
|
|
1080
1117
|
}
|
|
1081
1118
|
},
|
|
1119
|
+
resolvers() {
|
|
1120
|
+
let state = null;
|
|
1121
|
+
let resolve = null;
|
|
1122
|
+
let reject = null;
|
|
1123
|
+
const unitPromise = new UnitPromise(new Promise((res, rej) => {
|
|
1124
|
+
if (state === 'resolved') {
|
|
1125
|
+
res(null);
|
|
1126
|
+
}
|
|
1127
|
+
else if (state === 'rejected') {
|
|
1128
|
+
rej();
|
|
1129
|
+
}
|
|
1130
|
+
else {
|
|
1131
|
+
resolve = res;
|
|
1132
|
+
reject = rej;
|
|
1133
|
+
state = 'pending';
|
|
1134
|
+
}
|
|
1135
|
+
}));
|
|
1136
|
+
Unit.currentUnit._.promises.push(unitPromise);
|
|
1137
|
+
return {
|
|
1138
|
+
resolve() {
|
|
1139
|
+
if (state === 'pending') {
|
|
1140
|
+
resolve === null || resolve === void 0 ? void 0 : resolve(null);
|
|
1141
|
+
}
|
|
1142
|
+
state = 'resolved';
|
|
1143
|
+
},
|
|
1144
|
+
reject() {
|
|
1145
|
+
if (state === 'pending') {
|
|
1146
|
+
reject === null || reject === void 0 ? void 0 : reject();
|
|
1147
|
+
}
|
|
1148
|
+
state = 'rejected';
|
|
1149
|
+
}
|
|
1150
|
+
};
|
|
1151
|
+
},
|
|
1082
1152
|
/**
|
|
1083
|
-
*
|
|
1084
|
-
* @param
|
|
1085
|
-
* @returns
|
|
1153
|
+
* Outputs a value to the current unit's promise results
|
|
1154
|
+
* @param object - object to output for the promise
|
|
1155
|
+
* @returns void
|
|
1086
1156
|
* @example
|
|
1087
|
-
* xnew.
|
|
1157
|
+
* xnew.output({ data: 123});
|
|
1088
1158
|
*/
|
|
1089
|
-
|
|
1159
|
+
output(object) {
|
|
1090
1160
|
try {
|
|
1091
|
-
|
|
1092
|
-
.finally(callback);
|
|
1161
|
+
Object.assign(Unit.currentUnit._.results, object);
|
|
1093
1162
|
}
|
|
1094
1163
|
catch (error) {
|
|
1095
|
-
console.error('xnew.
|
|
1164
|
+
console.error('xnew.output(object?: Record<string, any>): ', error);
|
|
1096
1165
|
throw error;
|
|
1097
1166
|
}
|
|
1098
1167
|
},
|
|
@@ -1130,7 +1199,7 @@ const xnew$1 = Object.assign(function (...args) {
|
|
|
1130
1199
|
/**
|
|
1131
1200
|
* Emits a custom event to components
|
|
1132
1201
|
* @param type - Event type to emit (prefix with '+' for global events, '-' for local events)
|
|
1133
|
-
* @param
|
|
1202
|
+
* @param props - Event properties object to pass to listeners
|
|
1134
1203
|
* @returns void
|
|
1135
1204
|
* @example
|
|
1136
1205
|
* xnew.emit('+globalevent', { data: 123 }); // Global event
|
|
@@ -1147,7 +1216,7 @@ const xnew$1 = Object.assign(function (...args) {
|
|
|
1147
1216
|
},
|
|
1148
1217
|
/**
|
|
1149
1218
|
* Executes a callback once after a delay, managed by component lifecycle
|
|
1150
|
-
* @param callback - Function to execute after
|
|
1219
|
+
* @param callback - Function to execute after duration
|
|
1151
1220
|
* @param duration - Duration in milliseconds
|
|
1152
1221
|
* @returns Object with clear() method to cancel the timeout
|
|
1153
1222
|
* @example
|
|
@@ -1269,7 +1338,7 @@ function Screen(unit, { width = 800, height = 600, fit = 'contain' } = {}) {
|
|
|
1269
1338
|
}
|
|
1270
1339
|
const canvas = xnew$1(`<canvas width="${width}" height="${height}" style="width: 100%; height: 100%; vertical-align: bottom;">`);
|
|
1271
1340
|
return {
|
|
1272
|
-
get canvas() { return canvas.element; }
|
|
1341
|
+
get canvas() { return canvas.element; },
|
|
1273
1342
|
};
|
|
1274
1343
|
}
|
|
1275
1344
|
|
|
@@ -1555,24 +1624,46 @@ function Select(_, { key = '', value, items = [] } = {}) {
|
|
|
1555
1624
|
}
|
|
1556
1625
|
}
|
|
1557
1626
|
|
|
1558
|
-
function
|
|
1559
|
-
let scene = null;
|
|
1627
|
+
function Scene(unit) {
|
|
1560
1628
|
return {
|
|
1561
|
-
|
|
1562
|
-
|
|
1629
|
+
moveTo(Component, props) {
|
|
1630
|
+
xnew$1.next(unit, Component, props);
|
|
1631
|
+
unit.finalize();
|
|
1563
1632
|
},
|
|
1564
|
-
|
|
1565
|
-
|
|
1566
|
-
},
|
|
1567
|
-
next(Component, props) {
|
|
1568
|
-
var _a;
|
|
1569
|
-
// scene change
|
|
1570
|
-
(_a = unit.scene) === null || _a === void 0 ? void 0 : _a.finalize();
|
|
1571
|
-
unit.scene = xnew$1(Component, props);
|
|
1633
|
+
append(Component, props) {
|
|
1634
|
+
xnew$1.append(unit, Component, props);
|
|
1572
1635
|
}
|
|
1573
1636
|
};
|
|
1574
1637
|
}
|
|
1575
1638
|
|
|
1639
|
+
class XImage {
|
|
1640
|
+
constructor(...args) {
|
|
1641
|
+
if (args[0] instanceof HTMLCanvasElement) {
|
|
1642
|
+
this.canvas = args[0];
|
|
1643
|
+
}
|
|
1644
|
+
else {
|
|
1645
|
+
const canvas = document.createElement('canvas');
|
|
1646
|
+
canvas.width = args[0];
|
|
1647
|
+
canvas.height = args[1];
|
|
1648
|
+
this.canvas = canvas;
|
|
1649
|
+
}
|
|
1650
|
+
}
|
|
1651
|
+
crop(x, y, width, height) {
|
|
1652
|
+
var _a;
|
|
1653
|
+
const canvas = document.createElement('canvas');
|
|
1654
|
+
canvas.width = width;
|
|
1655
|
+
canvas.height = height;
|
|
1656
|
+
(_a = canvas.getContext('2d')) === null || _a === void 0 ? void 0 : _a.drawImage(this.canvas, x, y, width, height, 0, 0, width, height);
|
|
1657
|
+
return new XImage(canvas);
|
|
1658
|
+
}
|
|
1659
|
+
download(filename) {
|
|
1660
|
+
const link = document.createElement('a');
|
|
1661
|
+
link.download = filename;
|
|
1662
|
+
link.href = this.canvas.toDataURL('image/png');
|
|
1663
|
+
link.click();
|
|
1664
|
+
}
|
|
1665
|
+
}
|
|
1666
|
+
|
|
1576
1667
|
const context = new window.AudioContext();
|
|
1577
1668
|
const master = context.createGain();
|
|
1578
1669
|
//----------------------------------------------------------------------------------------------------
|
|
@@ -1805,7 +1896,7 @@ const basics = {
|
|
|
1805
1896
|
Panel,
|
|
1806
1897
|
Accordion,
|
|
1807
1898
|
Popup,
|
|
1808
|
-
|
|
1899
|
+
Scene,
|
|
1809
1900
|
};
|
|
1810
1901
|
const audio = {
|
|
1811
1902
|
load(path) {
|
|
@@ -1834,6 +1925,11 @@ const audio = {
|
|
|
1834
1925
|
master.gain.value = value;
|
|
1835
1926
|
}
|
|
1836
1927
|
};
|
|
1837
|
-
const
|
|
1928
|
+
const image = {
|
|
1929
|
+
from(canvas) {
|
|
1930
|
+
return new XImage(canvas);
|
|
1931
|
+
}
|
|
1932
|
+
};
|
|
1933
|
+
const xnew = Object.assign(xnew$1, { basics, audio, image });
|
|
1838
1934
|
|
|
1839
1935
|
export { xnew as default };
|