@mulsense/xnew 0.6.8 → 0.7.0
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 +57 -62
- package/dist/xnew.js +180 -86
- package/dist/xnew.mjs +180 -86
- 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,38 @@ 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
|
+
nestElements: {
|
|
79
|
+
element: UnitElement;
|
|
80
|
+
owned: boolean;
|
|
81
|
+
}[];
|
|
82
|
+
Components: Function[];
|
|
83
|
+
listeners: MapMap<string, Function, {
|
|
84
|
+
element: UnitElement;
|
|
85
|
+
Component: Function | null;
|
|
86
|
+
execute: Function;
|
|
87
|
+
}>;
|
|
88
|
+
eventor: Eventor;
|
|
89
|
+
};
|
|
90
|
+
constructor(parent: Unit | null, ...args: UnitArgs);
|
|
91
91
|
get element(): UnitElement;
|
|
92
92
|
start(): void;
|
|
93
93
|
stop(): void;
|
|
@@ -120,49 +120,26 @@ declare class Unit {
|
|
|
120
120
|
static emit(type: string, props?: object): void;
|
|
121
121
|
}
|
|
122
122
|
declare class UnitPromise {
|
|
123
|
-
promise
|
|
124
|
-
|
|
125
|
-
constructor(promise: Promise<any>, Component: Function | null);
|
|
123
|
+
private promise;
|
|
124
|
+
constructor(promise: Promise<any>);
|
|
126
125
|
then(callback: Function): UnitPromise;
|
|
127
126
|
catch(callback: Function): UnitPromise;
|
|
128
127
|
finally(callback: Function): UnitPromise;
|
|
128
|
+
static all(promises: UnitPromise[]): UnitPromise;
|
|
129
129
|
private wrap;
|
|
130
130
|
}
|
|
131
131
|
declare class UnitTimer {
|
|
132
132
|
private unit;
|
|
133
133
|
private queue;
|
|
134
134
|
clear(): void;
|
|
135
|
-
timeout(
|
|
136
|
-
interval(
|
|
135
|
+
timeout(timeout: Function, duration?: number): UnitTimer;
|
|
136
|
+
interval(timeout: Function, duration?: number, iterations?: number): UnitTimer;
|
|
137
137
|
transition(transition: Function, duration?: number, easing?: string): UnitTimer;
|
|
138
138
|
private static execute;
|
|
139
139
|
private static next;
|
|
140
140
|
private static Component;
|
|
141
141
|
}
|
|
142
142
|
|
|
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
143
|
interface TransitionOptions {
|
|
167
144
|
duration?: number;
|
|
168
145
|
easing?: string;
|
|
@@ -230,12 +207,21 @@ declare function Panel(unit: Unit, { params }: PanelOptions): {
|
|
|
230
207
|
separator(): void;
|
|
231
208
|
};
|
|
232
209
|
|
|
210
|
+
declare function Scene(unit: Unit): void;
|
|
233
211
|
declare function Flow(unit: Unit): {
|
|
234
212
|
get scene(): Unit | null;
|
|
235
213
|
set scene(value: Unit);
|
|
236
|
-
next(Component: Function, props?: any): void;
|
|
214
|
+
next(Component: Function, props?: any, callback?: Function): void;
|
|
237
215
|
};
|
|
238
216
|
|
|
217
|
+
declare class XImage {
|
|
218
|
+
canvas: HTMLCanvasElement;
|
|
219
|
+
constructor(canvas: HTMLCanvasElement);
|
|
220
|
+
constructor(width: number, height: number);
|
|
221
|
+
clip(x: number, y: number, width: number, height: number): XImage;
|
|
222
|
+
download(filename: string): void;
|
|
223
|
+
}
|
|
224
|
+
|
|
239
225
|
type SynthesizerOptions = {
|
|
240
226
|
oscillator: OscillatorOptions;
|
|
241
227
|
amp: AmpOptions;
|
|
@@ -280,17 +266,22 @@ declare namespace xnew {
|
|
|
280
266
|
type Unit = InstanceType<typeof Unit>;
|
|
281
267
|
type UnitTimer = InstanceType<typeof UnitTimer>;
|
|
282
268
|
}
|
|
283
|
-
declare const xnew:
|
|
269
|
+
declare const xnew: ((...args: UnitArgs) => Unit) & {
|
|
284
270
|
nest(target: UnitElement | string): HTMLElement | SVGElement;
|
|
285
271
|
extend(Component: Function, props?: Object): {
|
|
286
272
|
[key: string]: any;
|
|
287
273
|
};
|
|
274
|
+
append(parent: Unit, ...args: UnitArgs): void;
|
|
288
275
|
context(key: any): any;
|
|
289
276
|
promise(promise: Function | Promise<any> | Unit): UnitPromise;
|
|
290
277
|
then(callback: Function): UnitPromise;
|
|
291
278
|
catch(callback: Function): UnitPromise;
|
|
292
|
-
commit(object?: Record<string, any>): void;
|
|
293
279
|
finally(callback: Function): UnitPromise;
|
|
280
|
+
resolvers(): {
|
|
281
|
+
resolve(): void;
|
|
282
|
+
reject(): void;
|
|
283
|
+
};
|
|
284
|
+
output(object?: Record<string, any>): void;
|
|
294
285
|
scope(callback: any): any;
|
|
295
286
|
find(Component: Function): Unit[];
|
|
296
287
|
emit(type: string, ...args: any[]): void;
|
|
@@ -308,12 +299,16 @@ declare const xnew: CreateUnit & {
|
|
|
308
299
|
Accordion: typeof Accordion;
|
|
309
300
|
Popup: typeof Popup;
|
|
310
301
|
Flow: typeof Flow;
|
|
302
|
+
Scene: typeof Scene;
|
|
311
303
|
};
|
|
312
304
|
audio: {
|
|
313
305
|
load(path: string): UnitPromise;
|
|
314
306
|
synthesizer(props: SynthesizerOptions): Synthesizer;
|
|
315
307
|
volume: number;
|
|
316
308
|
};
|
|
309
|
+
image: {
|
|
310
|
+
from(canvas: HTMLCanvasElement): XImage;
|
|
311
|
+
};
|
|
317
312
|
};
|
|
318
313
|
|
|
319
314
|
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);
|
|
@@ -650,7 +660,7 @@
|
|
|
650
660
|
return element;
|
|
651
661
|
}
|
|
652
662
|
else {
|
|
653
|
-
throw new Error(`xnew.nest: invalid
|
|
663
|
+
throw new Error(`xnew.nest: invalid tag string [${target}]`);
|
|
654
664
|
}
|
|
655
665
|
}
|
|
656
666
|
}
|
|
@@ -692,7 +702,7 @@
|
|
|
692
702
|
Object.defineProperty(unit._.defines, key, wrapper);
|
|
693
703
|
Object.defineProperty(unit, key, wrapper);
|
|
694
704
|
});
|
|
695
|
-
return defines;
|
|
705
|
+
return Object.assign({}, unit._.defines);
|
|
696
706
|
}
|
|
697
707
|
}
|
|
698
708
|
static start(unit) {
|
|
@@ -729,7 +739,7 @@
|
|
|
729
739
|
static reset() {
|
|
730
740
|
var _a;
|
|
731
741
|
(_a = Unit.rootUnit) === null || _a === void 0 ? void 0 : _a.finalize();
|
|
732
|
-
Unit.currentUnit = Unit.rootUnit = new Unit(null
|
|
742
|
+
Unit.currentUnit = Unit.rootUnit = new Unit(null);
|
|
733
743
|
const ticker = new AnimationTicker(() => {
|
|
734
744
|
Unit.start(Unit.rootUnit);
|
|
735
745
|
Unit.update(Unit.rootUnit);
|
|
@@ -769,7 +779,7 @@
|
|
|
769
779
|
}
|
|
770
780
|
static getContext(unit, key) {
|
|
771
781
|
for (let context = unit._.currentContext; context.previous !== null; context = context.previous) {
|
|
772
|
-
if (context.value === Unit.currentUnit
|
|
782
|
+
if (context.value === Unit.currentUnit)
|
|
773
783
|
continue;
|
|
774
784
|
if (context.key === key)
|
|
775
785
|
return context.value;
|
|
@@ -848,13 +858,13 @@
|
|
|
848
858
|
// extensions
|
|
849
859
|
//----------------------------------------------------------------------------------------------------
|
|
850
860
|
class UnitPromise {
|
|
851
|
-
constructor(promise
|
|
852
|
-
this.promise = promise;
|
|
853
|
-
this.Component = Component;
|
|
854
|
-
}
|
|
861
|
+
constructor(promise) { this.promise = promise; }
|
|
855
862
|
then(callback) { return this.wrap('then', callback); }
|
|
856
863
|
catch(callback) { return this.wrap('catch', callback); }
|
|
857
864
|
finally(callback) { return this.wrap('finally', callback); }
|
|
865
|
+
static all(promises) {
|
|
866
|
+
return new UnitPromise(Promise.all(promises.map(p => p.promise)));
|
|
867
|
+
}
|
|
858
868
|
wrap(key, callback) {
|
|
859
869
|
const snapshot = Unit.snapshot(Unit.currentUnit);
|
|
860
870
|
this.promise = this.promise[key]((...args) => Unit.scope(snapshot, callback, ...args));
|
|
@@ -872,11 +882,11 @@
|
|
|
872
882
|
(_a = this.unit) === null || _a === void 0 ? void 0 : _a.finalize();
|
|
873
883
|
this.unit = null;
|
|
874
884
|
}
|
|
875
|
-
timeout(
|
|
876
|
-
return UnitTimer.execute(this, {
|
|
885
|
+
timeout(timeout, duration = 0) {
|
|
886
|
+
return UnitTimer.execute(this, { timeout, duration }, 1);
|
|
877
887
|
}
|
|
878
|
-
interval(
|
|
879
|
-
return UnitTimer.execute(this, {
|
|
888
|
+
interval(timeout, duration = 0, iterations = 0) {
|
|
889
|
+
return UnitTimer.execute(this, { timeout, duration }, iterations);
|
|
880
890
|
}
|
|
881
891
|
transition(transition, duration = 0, easing) {
|
|
882
892
|
return UnitTimer.execute(this, { transition, duration, easing }, 1);
|
|
@@ -884,7 +894,7 @@
|
|
|
884
894
|
static execute(timer, options, iterations) {
|
|
885
895
|
const props = { options, iterations, snapshot: Unit.snapshot(Unit.currentUnit) };
|
|
886
896
|
if (timer.unit === null || timer.unit._.state === 'finalized') {
|
|
887
|
-
timer.unit = new Unit(Unit.currentUnit,
|
|
897
|
+
timer.unit = new Unit(Unit.currentUnit, UnitTimer.Component, props);
|
|
888
898
|
}
|
|
889
899
|
else if (timer.queue.length === 0) {
|
|
890
900
|
timer.queue.push(props);
|
|
@@ -897,18 +907,18 @@
|
|
|
897
907
|
}
|
|
898
908
|
static next(timer) {
|
|
899
909
|
if (timer.queue.length > 0) {
|
|
900
|
-
timer.unit = new Unit(Unit.currentUnit,
|
|
910
|
+
timer.unit = new Unit(Unit.currentUnit, UnitTimer.Component, timer.queue.shift());
|
|
901
911
|
timer.unit.on('finalize', () => UnitTimer.next(timer));
|
|
902
912
|
}
|
|
903
913
|
}
|
|
904
914
|
static Component(unit, { options, iterations, snapshot }) {
|
|
905
915
|
let counter = 0;
|
|
906
|
-
let timer = new Timer({
|
|
907
|
-
function
|
|
908
|
-
if (options.
|
|
909
|
-
Unit.scope(snapshot, options.
|
|
916
|
+
let timer = new Timer({ timeout, transition, duration: options.duration, easing: options.easing });
|
|
917
|
+
function timeout() {
|
|
918
|
+
if (options.timeout)
|
|
919
|
+
Unit.scope(snapshot, options.timeout);
|
|
910
920
|
if (iterations <= 0 || counter < iterations - 1) {
|
|
911
|
-
timer = new Timer({
|
|
921
|
+
timer = new Timer({ timeout, transition, duration: options.duration, easing: options.easing });
|
|
912
922
|
}
|
|
913
923
|
else {
|
|
914
924
|
unit.finalize();
|
|
@@ -923,29 +933,31 @@
|
|
|
923
933
|
}
|
|
924
934
|
}
|
|
925
935
|
|
|
926
|
-
const xnew$1 = Object.assign(
|
|
936
|
+
const xnew$1 = Object.assign(
|
|
937
|
+
/**
|
|
938
|
+
* creates a new Unit component
|
|
939
|
+
* xnew(Component?: Function | string, props?: Object): Unit;
|
|
940
|
+
* xnew(target: HTMLElement | SVGElement | string, Component?: Function | string, props?: Object): Unit;
|
|
941
|
+
* @param target - HTMLElement | SVGElement, or HTML tag for new element
|
|
942
|
+
* @param Component - component function
|
|
943
|
+
* @param props - properties for component function
|
|
944
|
+
* @returns a new Unit instance
|
|
945
|
+
* @example
|
|
946
|
+
* const unit = xnew(MyComponent, { data: 0 })
|
|
947
|
+
* const unit = xnew(element, MyComponent, { data: 0 })
|
|
948
|
+
* const unit = xnew('<div>', MyComponent, { data: 0 })
|
|
949
|
+
*/
|
|
950
|
+
function (...args) {
|
|
927
951
|
if (Unit.rootUnit === undefined)
|
|
928
952
|
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;
|
|
953
|
+
return new Unit(Unit.currentUnit, ...args);
|
|
943
954
|
}, {
|
|
944
955
|
/**
|
|
945
|
-
* Creates a
|
|
946
|
-
*
|
|
947
|
-
* @
|
|
948
|
-
* @
|
|
956
|
+
* Creates a child HTML/SVG element inside the current component's element.
|
|
957
|
+
* Must be called during component initialization (before setup completes).
|
|
958
|
+
* @param target - An existing HTML/SVG element, or a tag string like `'<div>'`
|
|
959
|
+
* @returns The provided element, or the newly created element
|
|
960
|
+
* @throws Error if called after the component has finished initializing
|
|
949
961
|
* @example
|
|
950
962
|
* const div = xnew.nest('<div>')
|
|
951
963
|
* div.textContent = 'Hello'
|
|
@@ -958,7 +970,7 @@
|
|
|
958
970
|
return Unit.nest(Unit.currentUnit, target);
|
|
959
971
|
}
|
|
960
972
|
catch (error) {
|
|
961
|
-
console.error('xnew.nest(target:
|
|
973
|
+
console.error('xnew.nest(target: UnitElement | string): ', error);
|
|
962
974
|
throw error;
|
|
963
975
|
}
|
|
964
976
|
},
|
|
@@ -984,17 +996,25 @@
|
|
|
984
996
|
throw error;
|
|
985
997
|
}
|
|
986
998
|
},
|
|
999
|
+
append(parent, ...args) {
|
|
1000
|
+
try {
|
|
1001
|
+
new Unit(parent, ...args);
|
|
1002
|
+
}
|
|
1003
|
+
catch (error) {
|
|
1004
|
+
console.error('xnew.append(parent: Unit, ...args: UnitArgs): ', error);
|
|
1005
|
+
throw error;
|
|
1006
|
+
}
|
|
1007
|
+
},
|
|
987
1008
|
/**
|
|
988
|
-
* Gets
|
|
989
|
-
* @param key - component function
|
|
990
|
-
* @returns The
|
|
1009
|
+
* Gets the Unit instance associated with the given component in the ancestor context chain
|
|
1010
|
+
* @param key - component function used as context key
|
|
1011
|
+
* @returns The Unit instance registered with the given component, or undefined if not found
|
|
991
1012
|
* @example
|
|
992
|
-
* // Create unit
|
|
993
|
-
* const
|
|
994
|
-
* ------------------------------
|
|
1013
|
+
* // Create parent unit with component A
|
|
1014
|
+
* const parent = xnew(A);
|
|
995
1015
|
*
|
|
996
|
-
* //
|
|
997
|
-
* const
|
|
1016
|
+
* // Inside a child component, get the parent unit
|
|
1017
|
+
* const parentUnit = xnew.context(A)
|
|
998
1018
|
*/
|
|
999
1019
|
context(key) {
|
|
1000
1020
|
try {
|
|
@@ -1007,24 +1027,22 @@
|
|
|
1007
1027
|
},
|
|
1008
1028
|
/**
|
|
1009
1029
|
* Registers a promise with the current component for lifecycle management
|
|
1010
|
-
* @param promise - Promise to register
|
|
1030
|
+
* @param promise - A Promise, async function, or Unit to register
|
|
1011
1031
|
* @returns UnitPromise wrapper for chaining
|
|
1012
1032
|
* @example
|
|
1013
1033
|
* xnew.promise(fetchData()).then(data => console.log(data))
|
|
1014
1034
|
*/
|
|
1015
1035
|
promise(promise) {
|
|
1016
1036
|
try {
|
|
1017
|
-
const Component = Unit.currentUnit._.currentComponent;
|
|
1018
1037
|
let unitPromise;
|
|
1019
1038
|
if (promise instanceof Unit) {
|
|
1020
|
-
unitPromise =
|
|
1021
|
-
.then(() => promise._.results);
|
|
1039
|
+
unitPromise = UnitPromise.all(promise._.promises).then(() => promise._.results);
|
|
1022
1040
|
}
|
|
1023
1041
|
else if (promise instanceof Promise) {
|
|
1024
|
-
unitPromise = new UnitPromise(promise
|
|
1042
|
+
unitPromise = new UnitPromise(promise);
|
|
1025
1043
|
}
|
|
1026
1044
|
else {
|
|
1027
|
-
unitPromise = new UnitPromise(new Promise(xnew$1.scope(promise))
|
|
1045
|
+
unitPromise = new UnitPromise(new Promise(xnew$1.scope(promise)));
|
|
1028
1046
|
}
|
|
1029
1047
|
Unit.currentUnit._.promises.push(unitPromise);
|
|
1030
1048
|
return unitPromise;
|
|
@@ -1044,8 +1062,7 @@
|
|
|
1044
1062
|
then(callback) {
|
|
1045
1063
|
try {
|
|
1046
1064
|
const currentUnit = Unit.currentUnit;
|
|
1047
|
-
return
|
|
1048
|
-
.then(() => callback(currentUnit._.results));
|
|
1065
|
+
return UnitPromise.all(Unit.currentUnit._.promises).then(() => callback(currentUnit._.results));
|
|
1049
1066
|
}
|
|
1050
1067
|
catch (error) {
|
|
1051
1068
|
console.error('xnew.then(callback: Function): ', error);
|
|
@@ -1061,7 +1078,7 @@
|
|
|
1061
1078
|
*/
|
|
1062
1079
|
catch(callback) {
|
|
1063
1080
|
try {
|
|
1064
|
-
return
|
|
1081
|
+
return UnitPromise.all(Unit.currentUnit._.promises)
|
|
1065
1082
|
.catch(callback);
|
|
1066
1083
|
}
|
|
1067
1084
|
catch (error) {
|
|
@@ -1070,35 +1087,67 @@
|
|
|
1070
1087
|
}
|
|
1071
1088
|
},
|
|
1072
1089
|
/**
|
|
1073
|
-
*
|
|
1074
|
-
* @param
|
|
1075
|
-
* @returns
|
|
1090
|
+
* Executes callback after all registered promises settle (resolve or reject)
|
|
1091
|
+
* @param callback - Function to call after promises settle
|
|
1092
|
+
* @returns UnitPromise for chaining
|
|
1076
1093
|
* @example
|
|
1077
|
-
* xnew.
|
|
1094
|
+
* xnew.finally(() => console.log('All promises settled'))
|
|
1078
1095
|
*/
|
|
1079
|
-
|
|
1096
|
+
finally(callback) {
|
|
1080
1097
|
try {
|
|
1081
|
-
|
|
1098
|
+
return UnitPromise.all(Unit.currentUnit._.promises).finally(callback);
|
|
1082
1099
|
}
|
|
1083
1100
|
catch (error) {
|
|
1084
|
-
console.error('xnew.
|
|
1101
|
+
console.error('xnew.finally(callback: Function): ', error);
|
|
1085
1102
|
throw error;
|
|
1086
1103
|
}
|
|
1087
1104
|
},
|
|
1105
|
+
resolvers() {
|
|
1106
|
+
let state = null;
|
|
1107
|
+
let resolve = null;
|
|
1108
|
+
let reject = null;
|
|
1109
|
+
const unitPromise = new UnitPromise(new Promise((res, rej) => {
|
|
1110
|
+
if (state === 'resolved') {
|
|
1111
|
+
res(null);
|
|
1112
|
+
}
|
|
1113
|
+
else if (state === 'rejected') {
|
|
1114
|
+
rej();
|
|
1115
|
+
}
|
|
1116
|
+
else {
|
|
1117
|
+
resolve = res;
|
|
1118
|
+
reject = rej;
|
|
1119
|
+
state = 'pending';
|
|
1120
|
+
}
|
|
1121
|
+
}));
|
|
1122
|
+
Unit.currentUnit._.promises.push(unitPromise);
|
|
1123
|
+
return {
|
|
1124
|
+
resolve() {
|
|
1125
|
+
if (state === 'pending') {
|
|
1126
|
+
resolve === null || resolve === void 0 ? void 0 : resolve(null);
|
|
1127
|
+
}
|
|
1128
|
+
state = 'resolved';
|
|
1129
|
+
},
|
|
1130
|
+
reject() {
|
|
1131
|
+
if (state === 'pending') {
|
|
1132
|
+
reject === null || reject === void 0 ? void 0 : reject();
|
|
1133
|
+
}
|
|
1134
|
+
state = 'rejected';
|
|
1135
|
+
}
|
|
1136
|
+
};
|
|
1137
|
+
},
|
|
1088
1138
|
/**
|
|
1089
|
-
*
|
|
1090
|
-
* @param
|
|
1091
|
-
* @returns
|
|
1139
|
+
* Outputs a value to the current unit's promise results
|
|
1140
|
+
* @param object - object to output for the promise
|
|
1141
|
+
* @returns void
|
|
1092
1142
|
* @example
|
|
1093
|
-
* xnew.
|
|
1143
|
+
* xnew.output({ data: 123});
|
|
1094
1144
|
*/
|
|
1095
|
-
|
|
1145
|
+
output(object) {
|
|
1096
1146
|
try {
|
|
1097
|
-
|
|
1098
|
-
.finally(callback);
|
|
1147
|
+
Object.assign(Unit.currentUnit._.results, object);
|
|
1099
1148
|
}
|
|
1100
1149
|
catch (error) {
|
|
1101
|
-
console.error('xnew.
|
|
1150
|
+
console.error('xnew.output(object?: Record<string, any>): ', error);
|
|
1102
1151
|
throw error;
|
|
1103
1152
|
}
|
|
1104
1153
|
},
|
|
@@ -1136,7 +1185,7 @@
|
|
|
1136
1185
|
/**
|
|
1137
1186
|
* Emits a custom event to components
|
|
1138
1187
|
* @param type - Event type to emit (prefix with '+' for global events, '-' for local events)
|
|
1139
|
-
* @param
|
|
1188
|
+
* @param props - Event properties object to pass to listeners
|
|
1140
1189
|
* @returns void
|
|
1141
1190
|
* @example
|
|
1142
1191
|
* xnew.emit('+globalevent', { data: 123 }); // Global event
|
|
@@ -1153,7 +1202,7 @@
|
|
|
1153
1202
|
},
|
|
1154
1203
|
/**
|
|
1155
1204
|
* Executes a callback once after a delay, managed by component lifecycle
|
|
1156
|
-
* @param callback - Function to execute after
|
|
1205
|
+
* @param callback - Function to execute after duration
|
|
1157
1206
|
* @param duration - Duration in milliseconds
|
|
1158
1207
|
* @returns Object with clear() method to cancel the timeout
|
|
1159
1208
|
* @example
|
|
@@ -1275,7 +1324,7 @@
|
|
|
1275
1324
|
}
|
|
1276
1325
|
const canvas = xnew$1(`<canvas width="${width}" height="${height}" style="width: 100%; height: 100%; vertical-align: bottom;">`);
|
|
1277
1326
|
return {
|
|
1278
|
-
get canvas() { return canvas.element; }
|
|
1327
|
+
get canvas() { return canvas.element; },
|
|
1279
1328
|
};
|
|
1280
1329
|
}
|
|
1281
1330
|
|
|
@@ -1561,6 +1610,8 @@
|
|
|
1561
1610
|
}
|
|
1562
1611
|
}
|
|
1563
1612
|
|
|
1613
|
+
function Scene(unit) {
|
|
1614
|
+
}
|
|
1564
1615
|
function Flow(unit) {
|
|
1565
1616
|
let scene = null;
|
|
1566
1617
|
return {
|
|
@@ -1570,15 +1621,52 @@
|
|
|
1570
1621
|
get scene() {
|
|
1571
1622
|
return scene;
|
|
1572
1623
|
},
|
|
1573
|
-
next(Component, props) {
|
|
1574
|
-
|
|
1575
|
-
|
|
1576
|
-
(
|
|
1577
|
-
|
|
1578
|
-
|
|
1624
|
+
next(Component, props, callback) {
|
|
1625
|
+
callback = callback !== null && callback !== void 0 ? callback : defaultCallback;
|
|
1626
|
+
callback(scene, create);
|
|
1627
|
+
function defaultCallback(current, create) {
|
|
1628
|
+
current === null || current === void 0 ? void 0 : current.finalize();
|
|
1629
|
+
create();
|
|
1630
|
+
}
|
|
1631
|
+
function create() {
|
|
1632
|
+
scene = xnew$1((unit) => {
|
|
1633
|
+
xnew$1.extend(Scene);
|
|
1634
|
+
xnew$1.extend(Component, props);
|
|
1635
|
+
});
|
|
1636
|
+
return scene;
|
|
1637
|
+
}
|
|
1638
|
+
},
|
|
1579
1639
|
};
|
|
1580
1640
|
}
|
|
1581
1641
|
|
|
1642
|
+
class XImage {
|
|
1643
|
+
constructor(...args) {
|
|
1644
|
+
if (args[0] instanceof HTMLCanvasElement) {
|
|
1645
|
+
this.canvas = args[0];
|
|
1646
|
+
}
|
|
1647
|
+
else {
|
|
1648
|
+
const canvas = document.createElement('canvas');
|
|
1649
|
+
canvas.width = args[0];
|
|
1650
|
+
canvas.height = args[1];
|
|
1651
|
+
this.canvas = canvas;
|
|
1652
|
+
}
|
|
1653
|
+
}
|
|
1654
|
+
clip(x, y, width, height) {
|
|
1655
|
+
var _a;
|
|
1656
|
+
const canvas = document.createElement('canvas');
|
|
1657
|
+
canvas.width = width;
|
|
1658
|
+
canvas.height = height;
|
|
1659
|
+
(_a = canvas.getContext('2d')) === null || _a === void 0 ? void 0 : _a.drawImage(this.canvas, x, y, width, height, 0, 0, width, height);
|
|
1660
|
+
return new XImage(canvas);
|
|
1661
|
+
}
|
|
1662
|
+
download(filename) {
|
|
1663
|
+
const link = document.createElement('a');
|
|
1664
|
+
link.download = filename;
|
|
1665
|
+
link.href = this.canvas.toDataURL('image/png');
|
|
1666
|
+
link.click();
|
|
1667
|
+
}
|
|
1668
|
+
}
|
|
1669
|
+
|
|
1582
1670
|
const context = new window.AudioContext();
|
|
1583
1671
|
const master = context.createGain();
|
|
1584
1672
|
//----------------------------------------------------------------------------------------------------
|
|
@@ -1812,6 +1900,7 @@
|
|
|
1812
1900
|
Accordion,
|
|
1813
1901
|
Popup,
|
|
1814
1902
|
Flow,
|
|
1903
|
+
Scene,
|
|
1815
1904
|
};
|
|
1816
1905
|
const audio = {
|
|
1817
1906
|
load(path) {
|
|
@@ -1840,7 +1929,12 @@
|
|
|
1840
1929
|
master.gain.value = value;
|
|
1841
1930
|
}
|
|
1842
1931
|
};
|
|
1843
|
-
const
|
|
1932
|
+
const image = {
|
|
1933
|
+
from(canvas) {
|
|
1934
|
+
return new XImage(canvas);
|
|
1935
|
+
}
|
|
1936
|
+
};
|
|
1937
|
+
const xnew = Object.assign(xnew$1, { basics, audio, image });
|
|
1844
1938
|
|
|
1845
1939
|
return xnew;
|
|
1846
1940
|
|
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);
|
|
@@ -644,7 +654,7 @@ class Unit {
|
|
|
644
654
|
return element;
|
|
645
655
|
}
|
|
646
656
|
else {
|
|
647
|
-
throw new Error(`xnew.nest: invalid
|
|
657
|
+
throw new Error(`xnew.nest: invalid tag string [${target}]`);
|
|
648
658
|
}
|
|
649
659
|
}
|
|
650
660
|
}
|
|
@@ -686,7 +696,7 @@ class Unit {
|
|
|
686
696
|
Object.defineProperty(unit._.defines, key, wrapper);
|
|
687
697
|
Object.defineProperty(unit, key, wrapper);
|
|
688
698
|
});
|
|
689
|
-
return defines;
|
|
699
|
+
return Object.assign({}, unit._.defines);
|
|
690
700
|
}
|
|
691
701
|
}
|
|
692
702
|
static start(unit) {
|
|
@@ -723,7 +733,7 @@ class Unit {
|
|
|
723
733
|
static reset() {
|
|
724
734
|
var _a;
|
|
725
735
|
(_a = Unit.rootUnit) === null || _a === void 0 ? void 0 : _a.finalize();
|
|
726
|
-
Unit.currentUnit = Unit.rootUnit = new Unit(null
|
|
736
|
+
Unit.currentUnit = Unit.rootUnit = new Unit(null);
|
|
727
737
|
const ticker = new AnimationTicker(() => {
|
|
728
738
|
Unit.start(Unit.rootUnit);
|
|
729
739
|
Unit.update(Unit.rootUnit);
|
|
@@ -763,7 +773,7 @@ class Unit {
|
|
|
763
773
|
}
|
|
764
774
|
static getContext(unit, key) {
|
|
765
775
|
for (let context = unit._.currentContext; context.previous !== null; context = context.previous) {
|
|
766
|
-
if (context.value === Unit.currentUnit
|
|
776
|
+
if (context.value === Unit.currentUnit)
|
|
767
777
|
continue;
|
|
768
778
|
if (context.key === key)
|
|
769
779
|
return context.value;
|
|
@@ -842,13 +852,13 @@ Unit.type2units = new MapSet();
|
|
|
842
852
|
// extensions
|
|
843
853
|
//----------------------------------------------------------------------------------------------------
|
|
844
854
|
class UnitPromise {
|
|
845
|
-
constructor(promise
|
|
846
|
-
this.promise = promise;
|
|
847
|
-
this.Component = Component;
|
|
848
|
-
}
|
|
855
|
+
constructor(promise) { this.promise = promise; }
|
|
849
856
|
then(callback) { return this.wrap('then', callback); }
|
|
850
857
|
catch(callback) { return this.wrap('catch', callback); }
|
|
851
858
|
finally(callback) { return this.wrap('finally', callback); }
|
|
859
|
+
static all(promises) {
|
|
860
|
+
return new UnitPromise(Promise.all(promises.map(p => p.promise)));
|
|
861
|
+
}
|
|
852
862
|
wrap(key, callback) {
|
|
853
863
|
const snapshot = Unit.snapshot(Unit.currentUnit);
|
|
854
864
|
this.promise = this.promise[key]((...args) => Unit.scope(snapshot, callback, ...args));
|
|
@@ -866,11 +876,11 @@ class UnitTimer {
|
|
|
866
876
|
(_a = this.unit) === null || _a === void 0 ? void 0 : _a.finalize();
|
|
867
877
|
this.unit = null;
|
|
868
878
|
}
|
|
869
|
-
timeout(
|
|
870
|
-
return UnitTimer.execute(this, {
|
|
879
|
+
timeout(timeout, duration = 0) {
|
|
880
|
+
return UnitTimer.execute(this, { timeout, duration }, 1);
|
|
871
881
|
}
|
|
872
|
-
interval(
|
|
873
|
-
return UnitTimer.execute(this, {
|
|
882
|
+
interval(timeout, duration = 0, iterations = 0) {
|
|
883
|
+
return UnitTimer.execute(this, { timeout, duration }, iterations);
|
|
874
884
|
}
|
|
875
885
|
transition(transition, duration = 0, easing) {
|
|
876
886
|
return UnitTimer.execute(this, { transition, duration, easing }, 1);
|
|
@@ -878,7 +888,7 @@ class UnitTimer {
|
|
|
878
888
|
static execute(timer, options, iterations) {
|
|
879
889
|
const props = { options, iterations, snapshot: Unit.snapshot(Unit.currentUnit) };
|
|
880
890
|
if (timer.unit === null || timer.unit._.state === 'finalized') {
|
|
881
|
-
timer.unit = new Unit(Unit.currentUnit,
|
|
891
|
+
timer.unit = new Unit(Unit.currentUnit, UnitTimer.Component, props);
|
|
882
892
|
}
|
|
883
893
|
else if (timer.queue.length === 0) {
|
|
884
894
|
timer.queue.push(props);
|
|
@@ -891,18 +901,18 @@ class UnitTimer {
|
|
|
891
901
|
}
|
|
892
902
|
static next(timer) {
|
|
893
903
|
if (timer.queue.length > 0) {
|
|
894
|
-
timer.unit = new Unit(Unit.currentUnit,
|
|
904
|
+
timer.unit = new Unit(Unit.currentUnit, UnitTimer.Component, timer.queue.shift());
|
|
895
905
|
timer.unit.on('finalize', () => UnitTimer.next(timer));
|
|
896
906
|
}
|
|
897
907
|
}
|
|
898
908
|
static Component(unit, { options, iterations, snapshot }) {
|
|
899
909
|
let counter = 0;
|
|
900
|
-
let timer = new Timer({
|
|
901
|
-
function
|
|
902
|
-
if (options.
|
|
903
|
-
Unit.scope(snapshot, options.
|
|
910
|
+
let timer = new Timer({ timeout, transition, duration: options.duration, easing: options.easing });
|
|
911
|
+
function timeout() {
|
|
912
|
+
if (options.timeout)
|
|
913
|
+
Unit.scope(snapshot, options.timeout);
|
|
904
914
|
if (iterations <= 0 || counter < iterations - 1) {
|
|
905
|
-
timer = new Timer({
|
|
915
|
+
timer = new Timer({ timeout, transition, duration: options.duration, easing: options.easing });
|
|
906
916
|
}
|
|
907
917
|
else {
|
|
908
918
|
unit.finalize();
|
|
@@ -917,29 +927,31 @@ class UnitTimer {
|
|
|
917
927
|
}
|
|
918
928
|
}
|
|
919
929
|
|
|
920
|
-
const xnew$1 = Object.assign(
|
|
930
|
+
const xnew$1 = Object.assign(
|
|
931
|
+
/**
|
|
932
|
+
* creates a new Unit component
|
|
933
|
+
* xnew(Component?: Function | string, props?: Object): Unit;
|
|
934
|
+
* xnew(target: HTMLElement | SVGElement | string, Component?: Function | string, props?: Object): Unit;
|
|
935
|
+
* @param target - HTMLElement | SVGElement, or HTML tag for new element
|
|
936
|
+
* @param Component - component function
|
|
937
|
+
* @param props - properties for component function
|
|
938
|
+
* @returns a new Unit instance
|
|
939
|
+
* @example
|
|
940
|
+
* const unit = xnew(MyComponent, { data: 0 })
|
|
941
|
+
* const unit = xnew(element, MyComponent, { data: 0 })
|
|
942
|
+
* const unit = xnew('<div>', MyComponent, { data: 0 })
|
|
943
|
+
*/
|
|
944
|
+
function (...args) {
|
|
921
945
|
if (Unit.rootUnit === undefined)
|
|
922
946
|
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;
|
|
947
|
+
return new Unit(Unit.currentUnit, ...args);
|
|
937
948
|
}, {
|
|
938
949
|
/**
|
|
939
|
-
* Creates a
|
|
940
|
-
*
|
|
941
|
-
* @
|
|
942
|
-
* @
|
|
950
|
+
* Creates a child HTML/SVG element inside the current component's element.
|
|
951
|
+
* Must be called during component initialization (before setup completes).
|
|
952
|
+
* @param target - An existing HTML/SVG element, or a tag string like `'<div>'`
|
|
953
|
+
* @returns The provided element, or the newly created element
|
|
954
|
+
* @throws Error if called after the component has finished initializing
|
|
943
955
|
* @example
|
|
944
956
|
* const div = xnew.nest('<div>')
|
|
945
957
|
* div.textContent = 'Hello'
|
|
@@ -952,7 +964,7 @@ const xnew$1 = Object.assign(function (...args) {
|
|
|
952
964
|
return Unit.nest(Unit.currentUnit, target);
|
|
953
965
|
}
|
|
954
966
|
catch (error) {
|
|
955
|
-
console.error('xnew.nest(target:
|
|
967
|
+
console.error('xnew.nest(target: UnitElement | string): ', error);
|
|
956
968
|
throw error;
|
|
957
969
|
}
|
|
958
970
|
},
|
|
@@ -978,17 +990,25 @@ const xnew$1 = Object.assign(function (...args) {
|
|
|
978
990
|
throw error;
|
|
979
991
|
}
|
|
980
992
|
},
|
|
993
|
+
append(parent, ...args) {
|
|
994
|
+
try {
|
|
995
|
+
new Unit(parent, ...args);
|
|
996
|
+
}
|
|
997
|
+
catch (error) {
|
|
998
|
+
console.error('xnew.append(parent: Unit, ...args: UnitArgs): ', error);
|
|
999
|
+
throw error;
|
|
1000
|
+
}
|
|
1001
|
+
},
|
|
981
1002
|
/**
|
|
982
|
-
* Gets
|
|
983
|
-
* @param key - component function
|
|
984
|
-
* @returns The
|
|
1003
|
+
* Gets the Unit instance associated with the given component in the ancestor context chain
|
|
1004
|
+
* @param key - component function used as context key
|
|
1005
|
+
* @returns The Unit instance registered with the given component, or undefined if not found
|
|
985
1006
|
* @example
|
|
986
|
-
* // Create unit
|
|
987
|
-
* const
|
|
988
|
-
* ------------------------------
|
|
1007
|
+
* // Create parent unit with component A
|
|
1008
|
+
* const parent = xnew(A);
|
|
989
1009
|
*
|
|
990
|
-
* //
|
|
991
|
-
* const
|
|
1010
|
+
* // Inside a child component, get the parent unit
|
|
1011
|
+
* const parentUnit = xnew.context(A)
|
|
992
1012
|
*/
|
|
993
1013
|
context(key) {
|
|
994
1014
|
try {
|
|
@@ -1001,24 +1021,22 @@ const xnew$1 = Object.assign(function (...args) {
|
|
|
1001
1021
|
},
|
|
1002
1022
|
/**
|
|
1003
1023
|
* Registers a promise with the current component for lifecycle management
|
|
1004
|
-
* @param promise - Promise to register
|
|
1024
|
+
* @param promise - A Promise, async function, or Unit to register
|
|
1005
1025
|
* @returns UnitPromise wrapper for chaining
|
|
1006
1026
|
* @example
|
|
1007
1027
|
* xnew.promise(fetchData()).then(data => console.log(data))
|
|
1008
1028
|
*/
|
|
1009
1029
|
promise(promise) {
|
|
1010
1030
|
try {
|
|
1011
|
-
const Component = Unit.currentUnit._.currentComponent;
|
|
1012
1031
|
let unitPromise;
|
|
1013
1032
|
if (promise instanceof Unit) {
|
|
1014
|
-
unitPromise =
|
|
1015
|
-
.then(() => promise._.results);
|
|
1033
|
+
unitPromise = UnitPromise.all(promise._.promises).then(() => promise._.results);
|
|
1016
1034
|
}
|
|
1017
1035
|
else if (promise instanceof Promise) {
|
|
1018
|
-
unitPromise = new UnitPromise(promise
|
|
1036
|
+
unitPromise = new UnitPromise(promise);
|
|
1019
1037
|
}
|
|
1020
1038
|
else {
|
|
1021
|
-
unitPromise = new UnitPromise(new Promise(xnew$1.scope(promise))
|
|
1039
|
+
unitPromise = new UnitPromise(new Promise(xnew$1.scope(promise)));
|
|
1022
1040
|
}
|
|
1023
1041
|
Unit.currentUnit._.promises.push(unitPromise);
|
|
1024
1042
|
return unitPromise;
|
|
@@ -1038,8 +1056,7 @@ const xnew$1 = Object.assign(function (...args) {
|
|
|
1038
1056
|
then(callback) {
|
|
1039
1057
|
try {
|
|
1040
1058
|
const currentUnit = Unit.currentUnit;
|
|
1041
|
-
return
|
|
1042
|
-
.then(() => callback(currentUnit._.results));
|
|
1059
|
+
return UnitPromise.all(Unit.currentUnit._.promises).then(() => callback(currentUnit._.results));
|
|
1043
1060
|
}
|
|
1044
1061
|
catch (error) {
|
|
1045
1062
|
console.error('xnew.then(callback: Function): ', error);
|
|
@@ -1055,7 +1072,7 @@ const xnew$1 = Object.assign(function (...args) {
|
|
|
1055
1072
|
*/
|
|
1056
1073
|
catch(callback) {
|
|
1057
1074
|
try {
|
|
1058
|
-
return
|
|
1075
|
+
return UnitPromise.all(Unit.currentUnit._.promises)
|
|
1059
1076
|
.catch(callback);
|
|
1060
1077
|
}
|
|
1061
1078
|
catch (error) {
|
|
@@ -1064,35 +1081,67 @@ const xnew$1 = Object.assign(function (...args) {
|
|
|
1064
1081
|
}
|
|
1065
1082
|
},
|
|
1066
1083
|
/**
|
|
1067
|
-
*
|
|
1068
|
-
* @param
|
|
1069
|
-
* @returns
|
|
1084
|
+
* Executes callback after all registered promises settle (resolve or reject)
|
|
1085
|
+
* @param callback - Function to call after promises settle
|
|
1086
|
+
* @returns UnitPromise for chaining
|
|
1070
1087
|
* @example
|
|
1071
|
-
* xnew.
|
|
1088
|
+
* xnew.finally(() => console.log('All promises settled'))
|
|
1072
1089
|
*/
|
|
1073
|
-
|
|
1090
|
+
finally(callback) {
|
|
1074
1091
|
try {
|
|
1075
|
-
|
|
1092
|
+
return UnitPromise.all(Unit.currentUnit._.promises).finally(callback);
|
|
1076
1093
|
}
|
|
1077
1094
|
catch (error) {
|
|
1078
|
-
console.error('xnew.
|
|
1095
|
+
console.error('xnew.finally(callback: Function): ', error);
|
|
1079
1096
|
throw error;
|
|
1080
1097
|
}
|
|
1081
1098
|
},
|
|
1099
|
+
resolvers() {
|
|
1100
|
+
let state = null;
|
|
1101
|
+
let resolve = null;
|
|
1102
|
+
let reject = null;
|
|
1103
|
+
const unitPromise = new UnitPromise(new Promise((res, rej) => {
|
|
1104
|
+
if (state === 'resolved') {
|
|
1105
|
+
res(null);
|
|
1106
|
+
}
|
|
1107
|
+
else if (state === 'rejected') {
|
|
1108
|
+
rej();
|
|
1109
|
+
}
|
|
1110
|
+
else {
|
|
1111
|
+
resolve = res;
|
|
1112
|
+
reject = rej;
|
|
1113
|
+
state = 'pending';
|
|
1114
|
+
}
|
|
1115
|
+
}));
|
|
1116
|
+
Unit.currentUnit._.promises.push(unitPromise);
|
|
1117
|
+
return {
|
|
1118
|
+
resolve() {
|
|
1119
|
+
if (state === 'pending') {
|
|
1120
|
+
resolve === null || resolve === void 0 ? void 0 : resolve(null);
|
|
1121
|
+
}
|
|
1122
|
+
state = 'resolved';
|
|
1123
|
+
},
|
|
1124
|
+
reject() {
|
|
1125
|
+
if (state === 'pending') {
|
|
1126
|
+
reject === null || reject === void 0 ? void 0 : reject();
|
|
1127
|
+
}
|
|
1128
|
+
state = 'rejected';
|
|
1129
|
+
}
|
|
1130
|
+
};
|
|
1131
|
+
},
|
|
1082
1132
|
/**
|
|
1083
|
-
*
|
|
1084
|
-
* @param
|
|
1085
|
-
* @returns
|
|
1133
|
+
* Outputs a value to the current unit's promise results
|
|
1134
|
+
* @param object - object to output for the promise
|
|
1135
|
+
* @returns void
|
|
1086
1136
|
* @example
|
|
1087
|
-
* xnew.
|
|
1137
|
+
* xnew.output({ data: 123});
|
|
1088
1138
|
*/
|
|
1089
|
-
|
|
1139
|
+
output(object) {
|
|
1090
1140
|
try {
|
|
1091
|
-
|
|
1092
|
-
.finally(callback);
|
|
1141
|
+
Object.assign(Unit.currentUnit._.results, object);
|
|
1093
1142
|
}
|
|
1094
1143
|
catch (error) {
|
|
1095
|
-
console.error('xnew.
|
|
1144
|
+
console.error('xnew.output(object?: Record<string, any>): ', error);
|
|
1096
1145
|
throw error;
|
|
1097
1146
|
}
|
|
1098
1147
|
},
|
|
@@ -1130,7 +1179,7 @@ const xnew$1 = Object.assign(function (...args) {
|
|
|
1130
1179
|
/**
|
|
1131
1180
|
* Emits a custom event to components
|
|
1132
1181
|
* @param type - Event type to emit (prefix with '+' for global events, '-' for local events)
|
|
1133
|
-
* @param
|
|
1182
|
+
* @param props - Event properties object to pass to listeners
|
|
1134
1183
|
* @returns void
|
|
1135
1184
|
* @example
|
|
1136
1185
|
* xnew.emit('+globalevent', { data: 123 }); // Global event
|
|
@@ -1147,7 +1196,7 @@ const xnew$1 = Object.assign(function (...args) {
|
|
|
1147
1196
|
},
|
|
1148
1197
|
/**
|
|
1149
1198
|
* Executes a callback once after a delay, managed by component lifecycle
|
|
1150
|
-
* @param callback - Function to execute after
|
|
1199
|
+
* @param callback - Function to execute after duration
|
|
1151
1200
|
* @param duration - Duration in milliseconds
|
|
1152
1201
|
* @returns Object with clear() method to cancel the timeout
|
|
1153
1202
|
* @example
|
|
@@ -1269,7 +1318,7 @@ function Screen(unit, { width = 800, height = 600, fit = 'contain' } = {}) {
|
|
|
1269
1318
|
}
|
|
1270
1319
|
const canvas = xnew$1(`<canvas width="${width}" height="${height}" style="width: 100%; height: 100%; vertical-align: bottom;">`);
|
|
1271
1320
|
return {
|
|
1272
|
-
get canvas() { return canvas.element; }
|
|
1321
|
+
get canvas() { return canvas.element; },
|
|
1273
1322
|
};
|
|
1274
1323
|
}
|
|
1275
1324
|
|
|
@@ -1555,6 +1604,8 @@ function Select(_, { key = '', value, items = [] } = {}) {
|
|
|
1555
1604
|
}
|
|
1556
1605
|
}
|
|
1557
1606
|
|
|
1607
|
+
function Scene(unit) {
|
|
1608
|
+
}
|
|
1558
1609
|
function Flow(unit) {
|
|
1559
1610
|
let scene = null;
|
|
1560
1611
|
return {
|
|
@@ -1564,15 +1615,52 @@ function Flow(unit) {
|
|
|
1564
1615
|
get scene() {
|
|
1565
1616
|
return scene;
|
|
1566
1617
|
},
|
|
1567
|
-
next(Component, props) {
|
|
1568
|
-
|
|
1569
|
-
|
|
1570
|
-
(
|
|
1571
|
-
|
|
1572
|
-
|
|
1618
|
+
next(Component, props, callback) {
|
|
1619
|
+
callback = callback !== null && callback !== void 0 ? callback : defaultCallback;
|
|
1620
|
+
callback(scene, create);
|
|
1621
|
+
function defaultCallback(current, create) {
|
|
1622
|
+
current === null || current === void 0 ? void 0 : current.finalize();
|
|
1623
|
+
create();
|
|
1624
|
+
}
|
|
1625
|
+
function create() {
|
|
1626
|
+
scene = xnew$1((unit) => {
|
|
1627
|
+
xnew$1.extend(Scene);
|
|
1628
|
+
xnew$1.extend(Component, props);
|
|
1629
|
+
});
|
|
1630
|
+
return scene;
|
|
1631
|
+
}
|
|
1632
|
+
},
|
|
1573
1633
|
};
|
|
1574
1634
|
}
|
|
1575
1635
|
|
|
1636
|
+
class XImage {
|
|
1637
|
+
constructor(...args) {
|
|
1638
|
+
if (args[0] instanceof HTMLCanvasElement) {
|
|
1639
|
+
this.canvas = args[0];
|
|
1640
|
+
}
|
|
1641
|
+
else {
|
|
1642
|
+
const canvas = document.createElement('canvas');
|
|
1643
|
+
canvas.width = args[0];
|
|
1644
|
+
canvas.height = args[1];
|
|
1645
|
+
this.canvas = canvas;
|
|
1646
|
+
}
|
|
1647
|
+
}
|
|
1648
|
+
clip(x, y, width, height) {
|
|
1649
|
+
var _a;
|
|
1650
|
+
const canvas = document.createElement('canvas');
|
|
1651
|
+
canvas.width = width;
|
|
1652
|
+
canvas.height = height;
|
|
1653
|
+
(_a = canvas.getContext('2d')) === null || _a === void 0 ? void 0 : _a.drawImage(this.canvas, x, y, width, height, 0, 0, width, height);
|
|
1654
|
+
return new XImage(canvas);
|
|
1655
|
+
}
|
|
1656
|
+
download(filename) {
|
|
1657
|
+
const link = document.createElement('a');
|
|
1658
|
+
link.download = filename;
|
|
1659
|
+
link.href = this.canvas.toDataURL('image/png');
|
|
1660
|
+
link.click();
|
|
1661
|
+
}
|
|
1662
|
+
}
|
|
1663
|
+
|
|
1576
1664
|
const context = new window.AudioContext();
|
|
1577
1665
|
const master = context.createGain();
|
|
1578
1666
|
//----------------------------------------------------------------------------------------------------
|
|
@@ -1806,6 +1894,7 @@ const basics = {
|
|
|
1806
1894
|
Accordion,
|
|
1807
1895
|
Popup,
|
|
1808
1896
|
Flow,
|
|
1897
|
+
Scene,
|
|
1809
1898
|
};
|
|
1810
1899
|
const audio = {
|
|
1811
1900
|
load(path) {
|
|
@@ -1834,6 +1923,11 @@ const audio = {
|
|
|
1834
1923
|
master.gain.value = value;
|
|
1835
1924
|
}
|
|
1836
1925
|
};
|
|
1837
|
-
const
|
|
1926
|
+
const image = {
|
|
1927
|
+
from(canvas) {
|
|
1928
|
+
return new XImage(canvas);
|
|
1929
|
+
}
|
|
1930
|
+
};
|
|
1931
|
+
const xnew = Object.assign(xnew$1, { basics, audio, image });
|
|
1838
1932
|
|
|
1839
1933
|
export { xnew as default };
|