@mulsense/xnew 0.1.8 → 0.1.10
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 +46 -46
- package/dist/types/audio/audio.d.ts +55 -2
- package/dist/types/audio/loader.d.ts +6 -2
- package/dist/types/basics/Event.d.ts +4 -3
- package/dist/types/basics/Touch.d.ts +9 -8
- package/dist/types/core/time.d.ts +6 -2
- package/dist/types/core/unit.d.ts +41 -10
- package/dist/types/core/xnew.d.ts +11 -21
- package/dist/types/index.d.ts +3 -12
- package/dist/xnew.d.ts +48 -63
- package/dist/xnew.js +375 -400
- package/dist/xnew.mjs +375 -400
- package/package.json +78 -78
- package/dist/addons/xmatter.d.ts +0 -6
- package/dist/addons/xmatter.js +0 -43
- package/dist/addons/xmatter.mjs +0 -38
- package/dist/addons/xpixi.d.ts +0 -10
- package/dist/addons/xpixi.js +0 -99
- package/dist/addons/xpixi.mjs +0 -75
- package/dist/addons/xrapier2d.d.ts +0 -6
- package/dist/addons/xrapier2d.js +0 -69
- package/dist/addons/xrapier2d.mjs +0 -64
- package/dist/addons/xthree.d.ts +0 -9
- package/dist/addons/xthree.js +0 -77
- package/dist/addons/xthree.mjs +0 -53
- package/dist/types/basics/Block.d.ts +0 -24
- package/dist/types/basics/Bullet.d.ts +0 -7
- package/dist/types/basics/ControlPanel.d.ts +0 -7
- package/dist/types/basics/Navigation.d.ts +0 -1
- package/dist/types/basics/Panel.d.ts +0 -6
- package/dist/types/basics/Popup.d.ts +0 -8
- package/dist/types/basics/TabView.d.ts +0 -18
- package/dist/types/basics/Tabs.d.ts +0 -8
- package/dist/types/basics/Transition.d.ts +0 -17
- package/dist/types/basics/WorkSpace.d.ts +0 -16
- package/dist/types/core/util.d.ts +0 -1
- package/dist/types/xnew.d.ts +0 -8
package/dist/xnew.mjs
CHANGED
|
@@ -1,99 +1,3 @@
|
|
|
1
|
-
//----------------------------------------------------------------------------------------------------
|
|
2
|
-
// ticker
|
|
3
|
-
//----------------------------------------------------------------------------------------------------
|
|
4
|
-
class Ticker {
|
|
5
|
-
constructor(callback) {
|
|
6
|
-
const self = this;
|
|
7
|
-
this.id = null;
|
|
8
|
-
let previous = 0;
|
|
9
|
-
ticker();
|
|
10
|
-
function ticker() {
|
|
11
|
-
const time = Date.now();
|
|
12
|
-
const interval = 1000 / 60;
|
|
13
|
-
if (time - previous > interval * 0.9) {
|
|
14
|
-
callback(time);
|
|
15
|
-
previous = time;
|
|
16
|
-
}
|
|
17
|
-
self.id = requestAnimationFrame(ticker);
|
|
18
|
-
}
|
|
19
|
-
}
|
|
20
|
-
clear() {
|
|
21
|
-
if (this.id !== null) {
|
|
22
|
-
cancelAnimationFrame(this.id);
|
|
23
|
-
this.id = null;
|
|
24
|
-
}
|
|
25
|
-
}
|
|
26
|
-
}
|
|
27
|
-
//----------------------------------------------------------------------------------------------------
|
|
28
|
-
// timer
|
|
29
|
-
//----------------------------------------------------------------------------------------------------
|
|
30
|
-
class Timer {
|
|
31
|
-
constructor(timeout, transition, delay, loop = false) {
|
|
32
|
-
var _a;
|
|
33
|
-
this.timeout = timeout;
|
|
34
|
-
this.transition = transition;
|
|
35
|
-
this.delay = delay;
|
|
36
|
-
this.loop = loop;
|
|
37
|
-
this.id = null;
|
|
38
|
-
this.time = 0.0;
|
|
39
|
-
this.offset = 0.0;
|
|
40
|
-
this.status = 0;
|
|
41
|
-
this.ticker = new Ticker((time) => { var _a; return (_a = this.transition) === null || _a === void 0 ? void 0 : _a.call(this, this.elapsed() / this.delay); });
|
|
42
|
-
this.visibilitychange = () => document.hidden === false ? this._start() : this._stop();
|
|
43
|
-
document.addEventListener('visibilitychange', this.visibilitychange);
|
|
44
|
-
if (this.delay > 0.0) {
|
|
45
|
-
(_a = this.transition) === null || _a === void 0 ? void 0 : _a.call(this, 0.0);
|
|
46
|
-
}
|
|
47
|
-
this.start();
|
|
48
|
-
}
|
|
49
|
-
clear() {
|
|
50
|
-
if (this.id !== null) {
|
|
51
|
-
clearTimeout(this.id);
|
|
52
|
-
this.id = null;
|
|
53
|
-
}
|
|
54
|
-
document.removeEventListener('visibilitychange', this.visibilitychange);
|
|
55
|
-
this.ticker.clear();
|
|
56
|
-
}
|
|
57
|
-
elapsed() {
|
|
58
|
-
return this.offset + (this.id !== null ? (Date.now() - this.time) : 0);
|
|
59
|
-
}
|
|
60
|
-
start() {
|
|
61
|
-
this.status = 1;
|
|
62
|
-
this._start();
|
|
63
|
-
}
|
|
64
|
-
stop() {
|
|
65
|
-
this._stop();
|
|
66
|
-
this.status = 0;
|
|
67
|
-
}
|
|
68
|
-
_start() {
|
|
69
|
-
if (this.status === 1 && this.id === null) {
|
|
70
|
-
this.id = setTimeout(() => {
|
|
71
|
-
var _a;
|
|
72
|
-
this.timeout();
|
|
73
|
-
(_a = this.transition) === null || _a === void 0 ? void 0 : _a.call(this, 1.0);
|
|
74
|
-
this.id = null;
|
|
75
|
-
this.time = 0.0;
|
|
76
|
-
this.offset = 0.0;
|
|
77
|
-
if (this.loop) {
|
|
78
|
-
this.start();
|
|
79
|
-
}
|
|
80
|
-
else {
|
|
81
|
-
this.clear();
|
|
82
|
-
}
|
|
83
|
-
}, this.delay - this.offset);
|
|
84
|
-
this.time = Date.now();
|
|
85
|
-
}
|
|
86
|
-
}
|
|
87
|
-
_stop() {
|
|
88
|
-
if (this.status === 1 && this.id !== null) {
|
|
89
|
-
this.offset = this.offset + Date.now() - this.time;
|
|
90
|
-
clearTimeout(this.id);
|
|
91
|
-
this.id = null;
|
|
92
|
-
this.time = 0.0;
|
|
93
|
-
}
|
|
94
|
-
}
|
|
95
|
-
}
|
|
96
|
-
|
|
97
1
|
//----------------------------------------------------------------------------------------------------
|
|
98
2
|
// map set
|
|
99
3
|
//----------------------------------------------------------------------------------------------------
|
|
@@ -192,30 +96,141 @@ class MapMap extends Map {
|
|
|
192
96
|
}
|
|
193
97
|
|
|
194
98
|
//----------------------------------------------------------------------------------------------------
|
|
195
|
-
//
|
|
99
|
+
// ticker
|
|
196
100
|
//----------------------------------------------------------------------------------------------------
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
|
|
101
|
+
class Ticker {
|
|
102
|
+
constructor(callback) {
|
|
103
|
+
const self = this;
|
|
104
|
+
this.id = null;
|
|
105
|
+
let previous = 0;
|
|
106
|
+
ticker();
|
|
107
|
+
function ticker() {
|
|
108
|
+
const time = Date.now();
|
|
109
|
+
const interval = 1000 / 60;
|
|
110
|
+
if (time - previous > interval * 0.9) {
|
|
111
|
+
callback(time);
|
|
112
|
+
previous = time;
|
|
113
|
+
}
|
|
114
|
+
self.id = requestAnimationFrame(ticker);
|
|
115
|
+
}
|
|
203
116
|
}
|
|
204
|
-
|
|
205
|
-
this.
|
|
206
|
-
|
|
117
|
+
clear() {
|
|
118
|
+
if (this.id !== null) {
|
|
119
|
+
cancelAnimationFrame(this.id);
|
|
120
|
+
this.id = null;
|
|
121
|
+
}
|
|
207
122
|
}
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
|
|
123
|
+
}
|
|
124
|
+
//----------------------------------------------------------------------------------------------------
|
|
125
|
+
// timer
|
|
126
|
+
//----------------------------------------------------------------------------------------------------
|
|
127
|
+
class Timer {
|
|
128
|
+
constructor(transition, timeout, interval, { loop = false, easing = 'linear' } = {}) {
|
|
129
|
+
var _a;
|
|
130
|
+
this.transition = transition;
|
|
131
|
+
this.timeout = timeout;
|
|
132
|
+
this.interval = interval !== null && interval !== void 0 ? interval : 0;
|
|
133
|
+
this.loop = loop;
|
|
134
|
+
this.easing = easing;
|
|
135
|
+
this.id = null;
|
|
136
|
+
this.time = 0.0;
|
|
137
|
+
this.offset = 0.0;
|
|
138
|
+
this.status = 0;
|
|
139
|
+
this.ticker = new Ticker((time) => {
|
|
140
|
+
var _a;
|
|
141
|
+
let p = Math.min(this.elapsed() / this.interval, 1.0);
|
|
142
|
+
if (easing === 'ease-out') {
|
|
143
|
+
p = Math.pow((1.0 - Math.pow((1.0 - p), 2.0)), 0.5);
|
|
144
|
+
}
|
|
145
|
+
else if (easing === 'ease-in') {
|
|
146
|
+
p = Math.pow((1.0 - Math.pow((1.0 - p), 0.5)), 2.0);
|
|
147
|
+
}
|
|
148
|
+
else if (easing === 'ease') {
|
|
149
|
+
p = (1.0 - Math.cos(p * Math.PI)) / 2.0;
|
|
150
|
+
}
|
|
151
|
+
else if (easing === 'ease-in-out') {
|
|
152
|
+
p = (1.0 - Math.cos(p * Math.PI)) / 2.0;
|
|
153
|
+
}
|
|
154
|
+
(_a = this.transition) === null || _a === void 0 ? void 0 : _a.call(this, p);
|
|
155
|
+
});
|
|
156
|
+
this.visibilitychange = () => document.hidden === false ? this._start() : this._stop();
|
|
157
|
+
document.addEventListener('visibilitychange', this.visibilitychange);
|
|
158
|
+
if (this.interval > 0.0) {
|
|
159
|
+
(_a = this.transition) === null || _a === void 0 ? void 0 : _a.call(this, 0.0);
|
|
160
|
+
}
|
|
161
|
+
this.start();
|
|
162
|
+
}
|
|
163
|
+
clear() {
|
|
164
|
+
if (this.id !== null) {
|
|
165
|
+
clearTimeout(this.id);
|
|
166
|
+
this.id = null;
|
|
167
|
+
}
|
|
168
|
+
document.removeEventListener('visibilitychange', this.visibilitychange);
|
|
169
|
+
this.ticker.clear();
|
|
170
|
+
}
|
|
171
|
+
elapsed() {
|
|
172
|
+
return this.offset + (this.id !== null ? (Date.now() - this.time) : 0);
|
|
173
|
+
}
|
|
174
|
+
start() {
|
|
175
|
+
this.status = 1;
|
|
176
|
+
this._start();
|
|
177
|
+
}
|
|
178
|
+
stop() {
|
|
179
|
+
this._stop();
|
|
180
|
+
this.status = 0;
|
|
181
|
+
}
|
|
182
|
+
_start() {
|
|
183
|
+
if (this.status === 1 && this.id === null) {
|
|
184
|
+
this.id = setTimeout(() => {
|
|
185
|
+
var _a, _b;
|
|
186
|
+
(_a = this.timeout) === null || _a === void 0 ? void 0 : _a.call(this);
|
|
187
|
+
(_b = this.transition) === null || _b === void 0 ? void 0 : _b.call(this, 1.0);
|
|
188
|
+
this.id = null;
|
|
189
|
+
this.time = 0.0;
|
|
190
|
+
this.offset = 0.0;
|
|
191
|
+
this.loop ? this.start() : this.clear();
|
|
192
|
+
}, this.interval - this.offset);
|
|
193
|
+
this.time = Date.now();
|
|
194
|
+
}
|
|
195
|
+
}
|
|
196
|
+
_stop() {
|
|
197
|
+
if (this.status === 1 && this.id !== null) {
|
|
198
|
+
this.offset = this.offset + Date.now() - this.time;
|
|
199
|
+
clearTimeout(this.id);
|
|
200
|
+
this.id = null;
|
|
201
|
+
this.time = 0.0;
|
|
202
|
+
}
|
|
211
203
|
}
|
|
212
204
|
}
|
|
205
|
+
|
|
206
|
+
//----------------------------------------------------------------------------------------------------
|
|
207
|
+
// utils
|
|
208
|
+
//----------------------------------------------------------------------------------------------------
|
|
209
|
+
const SYSTEM_EVENTS = ['start', 'update', 'stop', 'finalize'];
|
|
213
210
|
//----------------------------------------------------------------------------------------------------
|
|
214
211
|
// unit
|
|
215
212
|
//----------------------------------------------------------------------------------------------------
|
|
216
213
|
class Unit {
|
|
217
|
-
constructor(parent,
|
|
214
|
+
constructor(parent, ...args) {
|
|
218
215
|
var _a;
|
|
216
|
+
let target;
|
|
217
|
+
if (args[0] instanceof HTMLElement || args[0] instanceof SVGElement) {
|
|
218
|
+
target = args.shift(); // an existing html element
|
|
219
|
+
}
|
|
220
|
+
else if (typeof args[0] === 'string' && args[0].match(/<((\w+)[^>]*?)\/?>/)) {
|
|
221
|
+
target = args.shift();
|
|
222
|
+
}
|
|
223
|
+
else if (typeof args[0] === 'string') {
|
|
224
|
+
const query = args.shift();
|
|
225
|
+
target = document.querySelector(query);
|
|
226
|
+
if (target === null)
|
|
227
|
+
throw new Error(`'${query}' can not be found.`);
|
|
228
|
+
}
|
|
229
|
+
else {
|
|
230
|
+
target = null;
|
|
231
|
+
}
|
|
232
|
+
const component = args.shift();
|
|
233
|
+
const props = args.shift();
|
|
219
234
|
let baseElement;
|
|
220
235
|
if (target instanceof HTMLElement || target instanceof SVGElement) {
|
|
221
236
|
baseElement = target;
|
|
@@ -268,6 +283,9 @@ class Unit {
|
|
|
268
283
|
Unit.finalize(this);
|
|
269
284
|
Unit.initialize(this, anchor);
|
|
270
285
|
}
|
|
286
|
+
append(...args) {
|
|
287
|
+
new Unit(this, ...args);
|
|
288
|
+
}
|
|
271
289
|
static initialize(unit, anchor) {
|
|
272
290
|
const backup = Unit.current;
|
|
273
291
|
Unit.current = unit;
|
|
@@ -309,7 +327,7 @@ class Unit {
|
|
|
309
327
|
unit._.systems.finalize.forEach((listener) => Unit.scope(Unit.snapshot(unit), listener));
|
|
310
328
|
unit.off();
|
|
311
329
|
Unit.suboff(unit, null);
|
|
312
|
-
unit._.components.forEach((component) => Unit.
|
|
330
|
+
unit._.components.forEach((component) => Unit.component2units.delete(component, unit));
|
|
313
331
|
if (unit._.elements.length > 0) {
|
|
314
332
|
unit._.baseElement.removeChild(unit._.elements[0]);
|
|
315
333
|
unit._.currentElement = unit._.baseElement;
|
|
@@ -347,7 +365,7 @@ class Unit {
|
|
|
347
365
|
static extend(unit, component, props) {
|
|
348
366
|
var _a;
|
|
349
367
|
unit._.components.push(component);
|
|
350
|
-
Unit.
|
|
368
|
+
Unit.component2units.add(component, unit);
|
|
351
369
|
const defines = (_a = component(unit, props)) !== null && _a !== void 0 ? _a : {};
|
|
352
370
|
Object.keys(defines).forEach((key) => {
|
|
353
371
|
if (unit[key] !== undefined && unit._.defines[key] === undefined) {
|
|
@@ -355,12 +373,10 @@ class Unit {
|
|
|
355
373
|
}
|
|
356
374
|
const descriptor = Object.getOwnPropertyDescriptor(defines, key);
|
|
357
375
|
const wrapper = { configurable: true, enumerable: true };
|
|
358
|
-
if (descriptor === null || descriptor === void 0 ? void 0 : descriptor.get)
|
|
376
|
+
if (descriptor === null || descriptor === void 0 ? void 0 : descriptor.get)
|
|
359
377
|
wrapper.get = Unit.wrap(unit, descriptor.get);
|
|
360
|
-
|
|
361
|
-
if (descriptor === null || descriptor === void 0 ? void 0 : descriptor.set) {
|
|
378
|
+
if (descriptor === null || descriptor === void 0 ? void 0 : descriptor.set)
|
|
362
379
|
wrapper.set = Unit.wrap(unit, descriptor.set);
|
|
363
|
-
}
|
|
364
380
|
if (typeof (descriptor === null || descriptor === void 0 ? void 0 : descriptor.value) === 'function') {
|
|
365
381
|
wrapper.value = Unit.wrap(unit, descriptor.value);
|
|
366
382
|
}
|
|
@@ -446,7 +462,7 @@ class Unit {
|
|
|
446
462
|
}
|
|
447
463
|
static find(component) {
|
|
448
464
|
var _a;
|
|
449
|
-
return [...((_a = Unit.
|
|
465
|
+
return [...((_a = Unit.component2units.get(component)) !== null && _a !== void 0 ? _a : [])];
|
|
450
466
|
}
|
|
451
467
|
on(type, listener, options) {
|
|
452
468
|
if (this._.state === 'finalized')
|
|
@@ -458,7 +474,7 @@ class Unit {
|
|
|
458
474
|
if (this._.listeners1.has(type, listener) === false) {
|
|
459
475
|
const execute = Unit.wrap(Unit.current, listener);
|
|
460
476
|
this._.listeners1.set(type, listener, [this.element, execute]);
|
|
461
|
-
Unit.
|
|
477
|
+
Unit.type2units.add(type, this);
|
|
462
478
|
if (/^[A-Za-z]/.test(type)) {
|
|
463
479
|
this.element.addEventListener(type, execute, options);
|
|
464
480
|
}
|
|
@@ -482,7 +498,7 @@ class Unit {
|
|
|
482
498
|
}
|
|
483
499
|
});
|
|
484
500
|
if (this._.listeners1.has(type) === false) {
|
|
485
|
-
Unit.
|
|
501
|
+
Unit.type2units.delete(type, this);
|
|
486
502
|
}
|
|
487
503
|
});
|
|
488
504
|
}
|
|
@@ -491,7 +507,7 @@ class Unit {
|
|
|
491
507
|
if (this._.state === 'finalized')
|
|
492
508
|
return;
|
|
493
509
|
if (type[0] === '+') {
|
|
494
|
-
(_a = Unit.
|
|
510
|
+
(_a = Unit.type2units.get(type)) === null || _a === void 0 ? void 0 : _a.forEach((unit) => {
|
|
495
511
|
var _a;
|
|
496
512
|
(_a = unit._.listeners1.get(type)) === null || _a === void 0 ? void 0 : _a.forEach(([_, execute]) => execute(...args));
|
|
497
513
|
});
|
|
@@ -525,36 +541,87 @@ class Unit {
|
|
|
525
541
|
});
|
|
526
542
|
}
|
|
527
543
|
}
|
|
528
|
-
Unit.
|
|
544
|
+
Unit.component2units = new MapSet();
|
|
529
545
|
//----------------------------------------------------------------------------------------------------
|
|
530
546
|
// event
|
|
531
547
|
//----------------------------------------------------------------------------------------------------
|
|
532
|
-
Unit.
|
|
533
|
-
|
|
534
|
-
|
|
535
|
-
|
|
536
|
-
|
|
548
|
+
Unit.type2units = new MapSet();
|
|
549
|
+
//----------------------------------------------------------------------------------------------------
|
|
550
|
+
// unit promise
|
|
551
|
+
//----------------------------------------------------------------------------------------------------
|
|
552
|
+
class UnitPromise {
|
|
553
|
+
constructor(promise) { this.promise = promise; }
|
|
554
|
+
then(callback) {
|
|
555
|
+
this.promise = this.promise.then(Unit.wrap(Unit.current, callback));
|
|
556
|
+
return this;
|
|
557
|
+
}
|
|
558
|
+
catch(callback) {
|
|
559
|
+
this.promise = this.promise.catch(Unit.wrap(Unit.current, callback));
|
|
560
|
+
return this;
|
|
537
561
|
}
|
|
538
|
-
|
|
539
|
-
|
|
540
|
-
|
|
562
|
+
finally(callback) {
|
|
563
|
+
this.promise = this.promise.finally(Unit.wrap(Unit.current, callback));
|
|
564
|
+
return this;
|
|
565
|
+
}
|
|
566
|
+
}
|
|
567
|
+
//----------------------------------------------------------------------------------------------------
|
|
568
|
+
// unit timer
|
|
569
|
+
//----------------------------------------------------------------------------------------------------
|
|
570
|
+
class UnitTimer {
|
|
571
|
+
constructor({ transition, timeout, interval, easing, loop }) {
|
|
572
|
+
this.stack = [];
|
|
573
|
+
this.unit = new Unit(Unit.current, UnitTimer.Component, { snapshot: Unit.snapshot(Unit.current), transition, timeout, interval, easing, loop });
|
|
574
|
+
}
|
|
575
|
+
clear() {
|
|
576
|
+
this.unit.off();
|
|
577
|
+
this.unit.finalize();
|
|
541
578
|
}
|
|
542
|
-
|
|
543
|
-
|
|
544
|
-
|
|
545
|
-
|
|
579
|
+
timeout(timeout, interval = 0) {
|
|
580
|
+
UnitTimer.execute(this, { timeout, interval });
|
|
581
|
+
return this;
|
|
582
|
+
}
|
|
583
|
+
transition(transition, interval = 0, easing = 'linear') {
|
|
584
|
+
UnitTimer.execute(this, { transition, interval, easing });
|
|
585
|
+
return this;
|
|
586
|
+
}
|
|
587
|
+
static execute(timer, { transition, timeout, interval, easing, loop }) {
|
|
588
|
+
if (timer.unit._.state === 'finalized') {
|
|
589
|
+
timer.unit = new Unit(Unit.current, UnitTimer.Component, { snapshot: Unit.snapshot(Unit.current), transition, timeout, interval, easing, loop });
|
|
590
|
+
}
|
|
591
|
+
else if (timer.stack.length === 0) {
|
|
592
|
+
timer.stack.push({ snapshot: Unit.snapshot(Unit.current), transition, timeout, interval, easing, loop });
|
|
593
|
+
timer.unit.on('finalize', () => { UnitTimer.next(timer); });
|
|
546
594
|
}
|
|
547
595
|
else {
|
|
548
|
-
|
|
549
|
-
if (target == null) {
|
|
550
|
-
throw new Error(`'${str}' can not be found.`);
|
|
551
|
-
}
|
|
596
|
+
timer.stack.push({ snapshot: Unit.snapshot(Unit.current), transition, timeout, interval, easing, loop });
|
|
552
597
|
}
|
|
553
598
|
}
|
|
554
|
-
|
|
555
|
-
|
|
599
|
+
static next(timer) {
|
|
600
|
+
if (timer.stack.length > 0) {
|
|
601
|
+
timer.unit = new Unit(Unit.current, UnitTimer.Component, timer.stack.shift());
|
|
602
|
+
timer.unit.on('finalize', () => { UnitTimer.next(timer); });
|
|
603
|
+
}
|
|
604
|
+
}
|
|
605
|
+
static Component(unit, { snapshot, transition, timeout, interval, loop, easing }) {
|
|
606
|
+
const timer = new Timer((x) => {
|
|
607
|
+
if (transition !== undefined)
|
|
608
|
+
Unit.scope(snapshot, transition, x);
|
|
609
|
+
}, () => {
|
|
610
|
+
if (transition !== undefined)
|
|
611
|
+
Unit.scope(snapshot, transition, 1.0);
|
|
612
|
+
if (timeout !== undefined)
|
|
613
|
+
Unit.scope(snapshot, timeout);
|
|
614
|
+
unit.finalize();
|
|
615
|
+
}, interval, { loop, easing });
|
|
616
|
+
unit.on('finalize', () => timer.clear());
|
|
617
|
+
}
|
|
618
|
+
}
|
|
619
|
+
|
|
620
|
+
const xnew$1 = Object.assign(function (...args) {
|
|
621
|
+
if (Unit.root === undefined) {
|
|
622
|
+
Unit.reset();
|
|
556
623
|
}
|
|
557
|
-
return new Unit(Unit.current,
|
|
624
|
+
return new Unit(Unit.current, ...args);
|
|
558
625
|
}, {
|
|
559
626
|
/**
|
|
560
627
|
* Creates a nested HTML/SVG element within the current component
|
|
@@ -727,65 +794,29 @@ const xnew$1 = Object.assign(function (...args) {
|
|
|
727
794
|
throw new Error('xnew.find(component: Function): [component] is invalid.');
|
|
728
795
|
}
|
|
729
796
|
},
|
|
730
|
-
/**
|
|
731
|
-
* Appends new components to existing component(s) in the tree
|
|
732
|
-
* @param anchor - Component function or Unit instance to append to
|
|
733
|
-
* @param args - Arguments to pass to xnew for creating child components
|
|
734
|
-
* @throws Error if anchor parameter is invalid
|
|
735
|
-
* @example
|
|
736
|
-
* xnew.append(MyContainer, ChildComponent, { prop: 'value' })
|
|
737
|
-
* xnew.append(unitInstance, AnotherComponent)
|
|
738
|
-
*/
|
|
739
|
-
append(anchor, ...args) {
|
|
740
|
-
if (typeof anchor === 'function') {
|
|
741
|
-
const units = Unit.find(anchor);
|
|
742
|
-
Unit.scope(Unit.snapshot(units[0]), xnew$1, ...args);
|
|
743
|
-
}
|
|
744
|
-
else if (anchor instanceof Unit) {
|
|
745
|
-
Unit.scope(Unit.snapshot(anchor), xnew$1, ...args);
|
|
746
|
-
}
|
|
747
|
-
else {
|
|
748
|
-
throw new Error('xnew.append(anchor: Function | Unit, xnew arguments): [anchor] is invalid.');
|
|
749
|
-
}
|
|
750
|
-
},
|
|
751
797
|
/**
|
|
752
798
|
* Executes a callback once after a delay, managed by component lifecycle
|
|
753
|
-
* @param
|
|
754
|
-
* @param
|
|
799
|
+
* @param timeout - Function to execute after Interval
|
|
800
|
+
* @param interval - Interval duration in milliseconds
|
|
755
801
|
* @returns Object with clear() method to cancel the timeout
|
|
756
802
|
* @example
|
|
757
803
|
* const timer = xnew.timeout(() => console.log('Delayed'), 1000)
|
|
758
804
|
* // Cancel if needed: timer.clear()
|
|
759
805
|
*/
|
|
760
|
-
timeout(
|
|
761
|
-
|
|
762
|
-
const unit = xnew$1((self) => {
|
|
763
|
-
const timer = new Timer(() => {
|
|
764
|
-
Unit.scope(snapshot, callback);
|
|
765
|
-
self.finalize();
|
|
766
|
-
}, null, delay, false);
|
|
767
|
-
self.on('finalize', () => timer.clear());
|
|
768
|
-
});
|
|
769
|
-
return { clear: () => unit.finalize() };
|
|
806
|
+
timeout(timeout, interval = 0) {
|
|
807
|
+
return new UnitTimer({ timeout, interval });
|
|
770
808
|
},
|
|
771
809
|
/**
|
|
772
810
|
* Executes a callback repeatedly at specified intervals, managed by component lifecycle
|
|
773
|
-
* @param
|
|
774
|
-
* @param
|
|
811
|
+
* @param timeout - Function to execute at each interval
|
|
812
|
+
* @param interval - Interval duration in milliseconds
|
|
775
813
|
* @returns Object with clear() method to stop the interval
|
|
776
814
|
* @example
|
|
777
815
|
* const timer = xnew.interval(() => console.log('Tick'), 1000)
|
|
778
816
|
* // Stop when needed: timer.clear()
|
|
779
817
|
*/
|
|
780
|
-
interval(
|
|
781
|
-
|
|
782
|
-
const unit = xnew$1((self) => {
|
|
783
|
-
const timer = new Timer(() => {
|
|
784
|
-
Unit.scope(snapshot, callback);
|
|
785
|
-
}, null, delay, true);
|
|
786
|
-
self.on('finalize', () => timer.clear());
|
|
787
|
-
});
|
|
788
|
-
return { clear: () => unit.finalize() };
|
|
818
|
+
interval(timeout, interval) {
|
|
819
|
+
return new UnitTimer({ timeout, interval, loop: true });
|
|
789
820
|
},
|
|
790
821
|
/**
|
|
791
822
|
* Creates a transition animation with easing, executing callback with progress values
|
|
@@ -794,61 +825,14 @@ const xnew$1 = Object.assign(function (...args) {
|
|
|
794
825
|
* @param easing - Easing function: 'linear', 'ease', 'ease-in', 'ease-out', 'ease-in-out' (default: 'linear')
|
|
795
826
|
* @returns Object with clear() and next() methods for controlling transitions
|
|
796
827
|
* @example
|
|
797
|
-
* xnew.transition(
|
|
798
|
-
* element.style.opacity =
|
|
799
|
-
* }, 500, 'ease-out').
|
|
800
|
-
* element.style.transform = `scale(${
|
|
828
|
+
* xnew.transition(p => {
|
|
829
|
+
* element.style.opacity = p
|
|
830
|
+
* }, 500, 'ease-out').transition(p => {
|
|
831
|
+
* element.style.transform = `scale(${p})`
|
|
801
832
|
* }, 300)
|
|
802
833
|
*/
|
|
803
|
-
transition(
|
|
804
|
-
|
|
805
|
-
let stacks = [];
|
|
806
|
-
let unit = xnew$1(Local, { callback, interval, easing });
|
|
807
|
-
let isRunning = true;
|
|
808
|
-
const timer = { clear, next };
|
|
809
|
-
return timer;
|
|
810
|
-
function execute() {
|
|
811
|
-
if (isRunning === false && stacks.length > 0) {
|
|
812
|
-
unit = xnew$1(Local, stacks.shift());
|
|
813
|
-
isRunning = true;
|
|
814
|
-
}
|
|
815
|
-
}
|
|
816
|
-
function clear() {
|
|
817
|
-
stacks = [];
|
|
818
|
-
unit.finalize();
|
|
819
|
-
}
|
|
820
|
-
function next(callback, interval = 0, easing = 'linear') {
|
|
821
|
-
stacks.push({ callback, interval, easing });
|
|
822
|
-
execute();
|
|
823
|
-
return timer;
|
|
824
|
-
}
|
|
825
|
-
function Local(self, { callback, interval, easing }) {
|
|
826
|
-
const timer = new Timer(() => {
|
|
827
|
-
Unit.scope(snapshot, callback, 1.0);
|
|
828
|
-
self.finalize();
|
|
829
|
-
}, (progress) => {
|
|
830
|
-
if (progress < 1.0) {
|
|
831
|
-
if (easing === 'ease-out') {
|
|
832
|
-
progress = Math.pow((1.0 - Math.pow((1.0 - progress), 2.0)), 0.5);
|
|
833
|
-
}
|
|
834
|
-
else if (easing === 'ease-in') {
|
|
835
|
-
progress = Math.pow((1.0 - Math.pow((1.0 - progress), 0.5)), 2.0);
|
|
836
|
-
}
|
|
837
|
-
else if (easing === 'ease') {
|
|
838
|
-
progress = (1.0 - Math.cos(progress * Math.PI)) / 2.0;
|
|
839
|
-
}
|
|
840
|
-
else if (easing === 'ease-in-out') {
|
|
841
|
-
progress = (1.0 - Math.cos(progress * Math.PI)) / 2.0;
|
|
842
|
-
}
|
|
843
|
-
Unit.scope(snapshot, callback, progress);
|
|
844
|
-
}
|
|
845
|
-
}, interval);
|
|
846
|
-
self.on('finalize', () => {
|
|
847
|
-
timer.clear();
|
|
848
|
-
isRunning = false;
|
|
849
|
-
execute();
|
|
850
|
-
});
|
|
851
|
-
}
|
|
834
|
+
transition(transition, interval = 0, easing = 'linear') {
|
|
835
|
+
return new UnitTimer({ transition, interval, easing });
|
|
852
836
|
},
|
|
853
837
|
/**
|
|
854
838
|
* Creates an event listener manager for a target element with automatic cleanup
|
|
@@ -883,6 +867,84 @@ const xnew$1 = Object.assign(function (...args) {
|
|
|
883
867
|
},
|
|
884
868
|
});
|
|
885
869
|
|
|
870
|
+
function AccordionFrame(frame, { open = false, duration = 200, easing = 'ease' } = {}) {
|
|
871
|
+
const internal = xnew$1((internal) => {
|
|
872
|
+
return { frame, open, rate: 0.0, };
|
|
873
|
+
});
|
|
874
|
+
xnew$1.context('xnew.accordionframe', internal);
|
|
875
|
+
internal.on('-transition', ({ rate }) => internal.rate = rate);
|
|
876
|
+
internal.emit('-transition', { rate: open ? 1.0 : 0.0 });
|
|
877
|
+
return {
|
|
878
|
+
toggle() {
|
|
879
|
+
if (internal.rate === 1.0) {
|
|
880
|
+
frame.close();
|
|
881
|
+
}
|
|
882
|
+
else if (internal.rate === 0.0) {
|
|
883
|
+
frame.open();
|
|
884
|
+
}
|
|
885
|
+
},
|
|
886
|
+
open() {
|
|
887
|
+
if (internal.rate === 0.0) {
|
|
888
|
+
xnew$1.transition((x) => internal.emit('-transition', { rate: x }), duration, easing);
|
|
889
|
+
}
|
|
890
|
+
},
|
|
891
|
+
close() {
|
|
892
|
+
if (internal.rate === 1.0) {
|
|
893
|
+
xnew$1.transition((x) => internal.emit('-transition', { rate: 1.0 - x }), duration, easing);
|
|
894
|
+
}
|
|
895
|
+
}
|
|
896
|
+
};
|
|
897
|
+
}
|
|
898
|
+
function AccordionHeader(header, {} = {}) {
|
|
899
|
+
const internal = xnew$1.context('xnew.accordionframe');
|
|
900
|
+
xnew$1.nest('<button style="display: flex; align-items: center; margin: 0; padding: 0; width: 100%; text-align: left; border: none; font: inherit; color: inherit; background: none; cursor: pointer;">');
|
|
901
|
+
header.on('click', () => internal.frame.toggle());
|
|
902
|
+
}
|
|
903
|
+
function AccordionBullet(bullet, { type = 'arrow' } = {}) {
|
|
904
|
+
const internal = xnew$1.context('xnew.accordionframe');
|
|
905
|
+
xnew$1.nest('<div style="display:inline-block; position: relative; width: 0.55em; margin: 0 0.3em;">');
|
|
906
|
+
if (type === 'arrow') {
|
|
907
|
+
const arrow = xnew$1(`<div style="width: 100%; height: 0.55em; border-right: 0.12em solid currentColor; border-bottom: 0.12em solid currentColor; box-sizing: border-box; transform-origin: center;">`);
|
|
908
|
+
arrow.element.style.transform = `rotate(${internal.rate * 90 - 45}deg)`;
|
|
909
|
+
internal.on('-transition', ({ rate }) => {
|
|
910
|
+
arrow.element.style.transform = `rotate(${rate * 90 - 45}deg)`;
|
|
911
|
+
});
|
|
912
|
+
}
|
|
913
|
+
else if (type === 'plusminus') {
|
|
914
|
+
const line1 = xnew$1(`<div style="position: absolute; width: 100%; border-top: 0.06em solid currentColor; border-bottom: 0.06em solid currentColor; box-sizing: border-box; transform-origin: center;">`);
|
|
915
|
+
const line2 = xnew$1(`<div style="position: absolute; width: 100%; border-top: 0.06em solid currentColor; border-bottom: 0.06em solid currentColor; box-sizing: border-box; transform-origin: center;">`);
|
|
916
|
+
line2.element.style.transform = `rotate(90deg)`;
|
|
917
|
+
line2.element.style.opacity = `${1.0 - internal.rate}`;
|
|
918
|
+
internal.on('-transition', ({ rate }) => {
|
|
919
|
+
line1.element.style.transform = `rotate(${90 + rate * 90}deg)`;
|
|
920
|
+
line2.element.style.transform = `rotate(${rate * 180}deg)`;
|
|
921
|
+
});
|
|
922
|
+
}
|
|
923
|
+
}
|
|
924
|
+
function AccordionContent(content, {} = {}) {
|
|
925
|
+
const internal = xnew$1.context('xnew.accordionframe');
|
|
926
|
+
xnew$1.nest(`<div style="display: ${internal.open ? 'block' : 'none'};">`);
|
|
927
|
+
xnew$1.nest('<div style="padding: 0; display: flex; flex-direction: column; box-sizing: border-box;">');
|
|
928
|
+
internal.on('-transition', ({ rate }) => {
|
|
929
|
+
content.transition({ element: content.element, rate });
|
|
930
|
+
});
|
|
931
|
+
return {
|
|
932
|
+
transition({ element, rate }) {
|
|
933
|
+
const wrapper = element.parentElement;
|
|
934
|
+
wrapper.style.display = 'block';
|
|
935
|
+
if (rate === 0.0) {
|
|
936
|
+
wrapper.style.display = 'none';
|
|
937
|
+
}
|
|
938
|
+
else if (rate < 1.0) {
|
|
939
|
+
Object.assign(wrapper.style, { height: element.offsetHeight * rate + 'px', overflow: 'hidden', opacity: rate });
|
|
940
|
+
}
|
|
941
|
+
else {
|
|
942
|
+
Object.assign(wrapper.style, { height: 'auto', overflow: 'visible', opacity: 1.0 });
|
|
943
|
+
}
|
|
944
|
+
}
|
|
945
|
+
};
|
|
946
|
+
}
|
|
947
|
+
|
|
886
948
|
function ResizeEvent(resize) {
|
|
887
949
|
const observer = new ResizeObserver((entries) => {
|
|
888
950
|
for (const entry of entries) {
|
|
@@ -899,7 +961,29 @@ function ResizeEvent(resize) {
|
|
|
899
961
|
}
|
|
900
962
|
});
|
|
901
963
|
}
|
|
902
|
-
|
|
964
|
+
function KeyboardEvent(unit) {
|
|
965
|
+
const state = {};
|
|
966
|
+
xnew$1.listener(window).on('keydown', (event) => {
|
|
967
|
+
state[event.code] = 1;
|
|
968
|
+
unit.emit('-keydown', { event, type: '-keydown', code: event.code });
|
|
969
|
+
});
|
|
970
|
+
xnew$1.listener(window).on('keyup', (event) => {
|
|
971
|
+
state[event.code] = 0;
|
|
972
|
+
unit.emit('-keyup', { event, type: '-keyup', code: event.code });
|
|
973
|
+
});
|
|
974
|
+
xnew$1.listener(window).on('keydown', (event) => {
|
|
975
|
+
unit.emit('-arrowkeydown', { event, type: '-arrowkeydown', code: event.code, vector: getVector() });
|
|
976
|
+
});
|
|
977
|
+
xnew$1.listener(window).on('keyup', (event) => {
|
|
978
|
+
unit.emit('-arrowkeyup', { event, type: '-arrowkeyup', code: event.code, vector: getVector() });
|
|
979
|
+
});
|
|
980
|
+
function getVector() {
|
|
981
|
+
return {
|
|
982
|
+
x: (state['ArrowLeft'] ? -1 : 0) + (state['ArrowRight'] ? +1 : 0),
|
|
983
|
+
y: (state['ArrowUp'] ? -1 : 0) + (state['ArrowDown'] ? +1 : 0)
|
|
984
|
+
};
|
|
985
|
+
}
|
|
986
|
+
}
|
|
903
987
|
function PointerEvent(unit) {
|
|
904
988
|
const internal = xnew$1();
|
|
905
989
|
internal.on('pointerdown', (event) => unit.emit('-pointerdown', { event, position: getPosition(unit.element, event) }));
|
|
@@ -1016,30 +1100,6 @@ function getPosition(element, event) {
|
|
|
1016
1100
|
return { x: event.clientX - rect.left, y: event.clientY - rect.top };
|
|
1017
1101
|
}
|
|
1018
1102
|
|
|
1019
|
-
function KeyboardEvent(unit) {
|
|
1020
|
-
const state = {};
|
|
1021
|
-
xnew$1.listener(window).on('keydown', (event) => {
|
|
1022
|
-
state[event.code] = 1;
|
|
1023
|
-
unit.emit('-keydown', { event, type: '-keydown', code: event.code });
|
|
1024
|
-
});
|
|
1025
|
-
xnew$1.listener(window).on('keyup', (event) => {
|
|
1026
|
-
state[event.code] = 0;
|
|
1027
|
-
unit.emit('-keyup', { event, type: '-keyup', code: event.code });
|
|
1028
|
-
});
|
|
1029
|
-
xnew$1.listener(window).on('keydown', (event) => {
|
|
1030
|
-
unit.emit('-arrowkeydown', { event, type: '-arrowkeydown', code: event.code, vector: getVector() });
|
|
1031
|
-
});
|
|
1032
|
-
xnew$1.listener(window).on('keyup', (event) => {
|
|
1033
|
-
unit.emit('-arrowkeyup', { event, type: '-arrowkeyup', code: event.code, vector: getVector() });
|
|
1034
|
-
});
|
|
1035
|
-
function getVector() {
|
|
1036
|
-
return {
|
|
1037
|
-
x: (state['ArrowLeft'] ? -1 : 0) + (state['ArrowRight'] ? +1 : 0),
|
|
1038
|
-
y: (state['ArrowUp'] ? -1 : 0) + (state['ArrowDown'] ? +1 : 0)
|
|
1039
|
-
};
|
|
1040
|
-
}
|
|
1041
|
-
}
|
|
1042
|
-
|
|
1043
1103
|
function Screen(screen, { width = 640, height = 480, fit = 'contain' } = {}) {
|
|
1044
1104
|
const size = { width, height };
|
|
1045
1105
|
const wrapper = xnew$1.nest('<div style="position: relative; width: 100%; height: 100%; overflow: hidden;">');
|
|
@@ -1196,84 +1256,6 @@ function TabContent(content, { key } = {}) {
|
|
|
1196
1256
|
};
|
|
1197
1257
|
}
|
|
1198
1258
|
|
|
1199
|
-
function AccordionFrame(frame, { open = false, duration = 200, easing = 'ease' } = {}) {
|
|
1200
|
-
const internal = xnew$1((internal) => {
|
|
1201
|
-
return { frame, open, rate: 0.0, };
|
|
1202
|
-
});
|
|
1203
|
-
xnew$1.context('xnew.accordionframe', internal);
|
|
1204
|
-
internal.on('-transition', ({ rate }) => internal.rate = rate);
|
|
1205
|
-
internal.emit('-transition', { rate: open ? 1.0 : 0.0 });
|
|
1206
|
-
return {
|
|
1207
|
-
toggle() {
|
|
1208
|
-
if (internal.rate === 1.0) {
|
|
1209
|
-
frame.close();
|
|
1210
|
-
}
|
|
1211
|
-
else if (internal.rate === 0.0) {
|
|
1212
|
-
frame.open();
|
|
1213
|
-
}
|
|
1214
|
-
},
|
|
1215
|
-
open() {
|
|
1216
|
-
if (internal.rate === 0.0) {
|
|
1217
|
-
xnew$1.transition((x) => internal.emit('-transition', { rate: x }), duration, easing);
|
|
1218
|
-
}
|
|
1219
|
-
},
|
|
1220
|
-
close() {
|
|
1221
|
-
if (internal.rate === 1.0) {
|
|
1222
|
-
xnew$1.transition((x) => internal.emit('-transition', { rate: 1.0 - x }), duration, easing);
|
|
1223
|
-
}
|
|
1224
|
-
}
|
|
1225
|
-
};
|
|
1226
|
-
}
|
|
1227
|
-
function AccordionHeader(header, {} = {}) {
|
|
1228
|
-
const internal = xnew$1.context('xnew.accordionframe');
|
|
1229
|
-
xnew$1.nest('<button style="display: flex; align-items: center; margin: 0; padding: 0; width: 100%; text-align: left; border: none; font: inherit; color: inherit; background: none; cursor: pointer;">');
|
|
1230
|
-
header.on('click', () => internal.frame.toggle());
|
|
1231
|
-
}
|
|
1232
|
-
function AccordionBullet(bullet, { type = 'arrow' } = {}) {
|
|
1233
|
-
const internal = xnew$1.context('xnew.accordionframe');
|
|
1234
|
-
xnew$1.nest('<div style="display:inline-block; position: relative; width: 0.55em; margin: 0 0.3em;">');
|
|
1235
|
-
if (type === 'arrow') {
|
|
1236
|
-
const arrow = xnew$1(`<div style="width: 100%; height: 0.55em; border-right: 0.12em solid currentColor; border-bottom: 0.12em solid currentColor; box-sizing: border-box; transform-origin: center;">`);
|
|
1237
|
-
arrow.element.style.transform = `rotate(${internal.rate * 90 - 45}deg)`;
|
|
1238
|
-
internal.on('-transition', ({ rate }) => {
|
|
1239
|
-
arrow.element.style.transform = `rotate(${rate * 90 - 45}deg)`;
|
|
1240
|
-
});
|
|
1241
|
-
}
|
|
1242
|
-
else if (type === 'plusminus') {
|
|
1243
|
-
const line1 = xnew$1(`<div style="position: absolute; width: 100%; border-top: 0.06em solid currentColor; border-bottom: 0.06em solid currentColor; box-sizing: border-box; transform-origin: center;">`);
|
|
1244
|
-
const line2 = xnew$1(`<div style="position: absolute; width: 100%; border-top: 0.06em solid currentColor; border-bottom: 0.06em solid currentColor; box-sizing: border-box; transform-origin: center;">`);
|
|
1245
|
-
line2.element.style.transform = `rotate(90deg)`;
|
|
1246
|
-
line2.element.style.opacity = `${1.0 - internal.rate}`;
|
|
1247
|
-
internal.on('-transition', ({ rate }) => {
|
|
1248
|
-
line1.element.style.transform = `rotate(${90 + rate * 90}deg)`;
|
|
1249
|
-
line2.element.style.transform = `rotate(${rate * 180}deg)`;
|
|
1250
|
-
});
|
|
1251
|
-
}
|
|
1252
|
-
}
|
|
1253
|
-
function AccordionContent(content, {} = {}) {
|
|
1254
|
-
const internal = xnew$1.context('xnew.accordionframe');
|
|
1255
|
-
xnew$1.nest(`<div style="display: ${internal.open ? 'block' : 'none'};">`);
|
|
1256
|
-
xnew$1.nest('<div style="padding: 0; display: flex; flex-direction: column; box-sizing: border-box;">');
|
|
1257
|
-
internal.on('-transition', ({ rate }) => {
|
|
1258
|
-
content.transition({ element: content.element, rate });
|
|
1259
|
-
});
|
|
1260
|
-
return {
|
|
1261
|
-
transition({ element, rate }) {
|
|
1262
|
-
const wrapper = element.parentElement;
|
|
1263
|
-
wrapper.style.display = 'block';
|
|
1264
|
-
if (rate === 0.0) {
|
|
1265
|
-
wrapper.style.display = 'none';
|
|
1266
|
-
}
|
|
1267
|
-
else if (rate < 1.0) {
|
|
1268
|
-
Object.assign(wrapper.style, { height: element.offsetHeight * rate + 'px', overflow: 'hidden', opacity: rate });
|
|
1269
|
-
}
|
|
1270
|
-
else {
|
|
1271
|
-
Object.assign(wrapper.style, { height: 'auto', overflow: 'visible', opacity: 1.0 });
|
|
1272
|
-
}
|
|
1273
|
-
}
|
|
1274
|
-
};
|
|
1275
|
-
}
|
|
1276
|
-
|
|
1277
1259
|
function DragFrame(frame, { x = 0, y = 0 } = {}) {
|
|
1278
1260
|
const absolute = xnew$1.nest(`<div style="position: absolute; top: ${y}px; left: ${x}px;">`);
|
|
1279
1261
|
xnew$1.context('xnew.dragframe', { frame, absolute });
|
|
@@ -1311,11 +1293,11 @@ function DragTarget(target, {} = {}) {
|
|
|
1311
1293
|
// controller
|
|
1312
1294
|
//----------------------------------------------------------------------------------------------------
|
|
1313
1295
|
function SVGTemplate(self, { fill = null, fillOpacity = 0.8, stroke = null, strokeOpacity = 0.8, strokeWidth = 2, strokeLinejoin = 'round' }) {
|
|
1314
|
-
xnew$1.nest(`<svg
|
|
1315
|
-
viewBox="0 0 100 100"
|
|
1316
|
-
style="position: absolute; width: 100%; height: 100%; pointer-select: none;
|
|
1317
|
-
${fill ? `fill: ${fill}; fill-opacity: ${fillOpacity};` : ''}
|
|
1318
|
-
${stroke ? `stroke: ${stroke}; stroke-opacity: ${strokeOpacity}; stroke-width: ${strokeWidth}; stroke-linejoin: ${strokeLinejoin};` : ''}
|
|
1296
|
+
xnew$1.nest(`<svg
|
|
1297
|
+
viewBox="0 0 100 100"
|
|
1298
|
+
style="position: absolute; width: 100%; height: 100%; pointer-select: none;
|
|
1299
|
+
${fill ? `fill: ${fill}; fill-opacity: ${fillOpacity};` : ''}
|
|
1300
|
+
${stroke ? `stroke: ${stroke}; stroke-opacity: ${strokeOpacity}; stroke-width: ${strokeWidth}; stroke-linejoin: ${strokeLinejoin};` : ''}
|
|
1319
1301
|
">`);
|
|
1320
1302
|
}
|
|
1321
1303
|
function AnalogStick(self, { size, fill = '#FFF', fillOpacity = 0.8, stroke = '#000', strokeOpacity = 0.8, strokeWidth = 2, strokeLinejoin = 'round' } = {}) {
|
|
@@ -1467,29 +1449,41 @@ const context = new AudioContext();
|
|
|
1467
1449
|
const master = context.createGain();
|
|
1468
1450
|
master.gain.value = 1.0;
|
|
1469
1451
|
master.connect(context.destination);
|
|
1470
|
-
|
|
1471
|
-
|
|
1472
|
-
|
|
1452
|
+
window.addEventListener('touchstart', initialize, true);
|
|
1453
|
+
window.addEventListener('mousedown', initialize, true);
|
|
1454
|
+
function initialize() {
|
|
1455
|
+
new Synthesizer({ oscillator: { type: 'sine' }, amp: { envelope: { amount: 0, ADSR: [0, 0, 0, 0] } } }).press(440);
|
|
1456
|
+
window.removeEventListener('touchstart', initialize, true);
|
|
1457
|
+
window.removeEventListener('mousedown', initialize, true);
|
|
1473
1458
|
}
|
|
1474
|
-
const
|
|
1459
|
+
const audio = {
|
|
1460
|
+
load(path) {
|
|
1461
|
+
return new AudioFile(path);
|
|
1462
|
+
},
|
|
1463
|
+
synthesizer(props) {
|
|
1464
|
+
return new Synthesizer(props);
|
|
1465
|
+
},
|
|
1466
|
+
get volume() {
|
|
1467
|
+
return master.gain.value;
|
|
1468
|
+
},
|
|
1469
|
+
set volume(value) {
|
|
1470
|
+
master.gain.value = value;
|
|
1471
|
+
}
|
|
1472
|
+
};
|
|
1473
|
+
//----------------------------------------------------------------------------------------------------
|
|
1474
|
+
// audio file
|
|
1475
|
+
//----------------------------------------------------------------------------------------------------
|
|
1475
1476
|
class AudioFile {
|
|
1476
1477
|
constructor(path) {
|
|
1477
|
-
|
|
1478
|
-
|
|
1479
|
-
|
|
1480
|
-
|
|
1481
|
-
|
|
1482
|
-
|
|
1483
|
-
|
|
1484
|
-
|
|
1485
|
-
|
|
1486
|
-
this.buffer = response;
|
|
1487
|
-
})
|
|
1488
|
-
.catch(() => {
|
|
1489
|
-
console.warn(`"${path}" could not be loaded.`);
|
|
1490
|
-
});
|
|
1491
|
-
store.set(path, this.buffer);
|
|
1492
|
-
}
|
|
1478
|
+
this.promise = fetch(path)
|
|
1479
|
+
.then((response) => response.arrayBuffer())
|
|
1480
|
+
.then((response) => context.decodeAudioData(response))
|
|
1481
|
+
.then((response) => {
|
|
1482
|
+
this.buffer = response;
|
|
1483
|
+
})
|
|
1484
|
+
.catch(() => {
|
|
1485
|
+
console.warn(`"${path}" could not be loaded.`);
|
|
1486
|
+
});
|
|
1493
1487
|
this.start = null;
|
|
1494
1488
|
}
|
|
1495
1489
|
// set volume(value: number) {
|
|
@@ -1528,17 +1522,6 @@ class AudioFile {
|
|
|
1528
1522
|
}
|
|
1529
1523
|
}
|
|
1530
1524
|
}
|
|
1531
|
-
|
|
1532
|
-
function synthesizer(props) {
|
|
1533
|
-
return new Synthesizer(props);
|
|
1534
|
-
}
|
|
1535
|
-
window.addEventListener('touchstart', initialize, true);
|
|
1536
|
-
window.addEventListener('mousedown', initialize, true);
|
|
1537
|
-
function initialize() {
|
|
1538
|
-
new Synthesizer({ oscillator: { type: 'sine' }, amp: { envelope: { amount: 0, ADSR: [0, 0, 0, 0] } } }).press(440);
|
|
1539
|
-
window.removeEventListener('touchstart', initialize, true);
|
|
1540
|
-
window.removeEventListener('mousedown', initialize, true);
|
|
1541
|
-
}
|
|
1542
1525
|
const keymap = {
|
|
1543
1526
|
'A0': 27.500, 'A#0': 29.135, 'B0': 30.868,
|
|
1544
1527
|
'C1': 32.703, 'C#1': 34.648, 'D1': 36.708, 'D#1': 38.891, 'E1': 41.203, 'F1': 43.654, 'F#1': 46.249, 'G1': 48.999, 'G#1': 51.913, 'A1': 55.000, 'A#1': 58.270, 'B1': 61.735,
|
|
@@ -1554,23 +1537,21 @@ const notemap = {
|
|
|
1554
1537
|
'1m': 4.000, '2n': 2.000, '4n': 1.000, '8n': 0.500, '16n': 0.250, '32n': 0.125,
|
|
1555
1538
|
};
|
|
1556
1539
|
class Synthesizer {
|
|
1557
|
-
constructor(props) {
|
|
1558
|
-
this.props = props;
|
|
1559
|
-
}
|
|
1540
|
+
constructor(props) { this.props = props; }
|
|
1560
1541
|
press(frequency, duration, wait) {
|
|
1561
1542
|
var _a;
|
|
1562
1543
|
const props = this.props;
|
|
1563
|
-
const
|
|
1564
|
-
const
|
|
1544
|
+
const fv = typeof frequency === 'string' ? keymap[frequency] : frequency;
|
|
1545
|
+
const dv = typeof duration === 'string' ? (notemap[duration] * 60 / ((_a = props.bpm) !== null && _a !== void 0 ? _a : 120)) : (typeof duration === 'number' ? (duration / 1000) : 0);
|
|
1565
1546
|
const start = context.currentTime + (wait !== null && wait !== void 0 ? wait : 0) / 1000;
|
|
1566
1547
|
const nodes = {};
|
|
1567
1548
|
nodes.oscillator = context.createOscillator();
|
|
1568
1549
|
nodes.oscillator.type = props.oscillator.type;
|
|
1569
|
-
nodes.oscillator.frequency.value =
|
|
1550
|
+
nodes.oscillator.frequency.value = fv;
|
|
1570
1551
|
if (props.oscillator.LFO) {
|
|
1571
1552
|
nodes.oscillatorLFO = context.createOscillator();
|
|
1572
1553
|
nodes.oscillatorLFODepth = context.createGain();
|
|
1573
|
-
nodes.oscillatorLFODepth.gain.value =
|
|
1554
|
+
nodes.oscillatorLFODepth.gain.value = fv * (Math.pow(2.0, props.oscillator.LFO.amount / 12.0) - 1.0);
|
|
1574
1555
|
nodes.oscillatorLFO.type = props.oscillator.LFO.type;
|
|
1575
1556
|
nodes.oscillatorLFO.frequency.value = props.oscillator.LFO.rate;
|
|
1576
1557
|
nodes.oscillatorLFO.start(start);
|
|
@@ -1583,7 +1564,7 @@ class Synthesizer {
|
|
|
1583
1564
|
nodes.target.gain.value = 1.0;
|
|
1584
1565
|
nodes.amp.connect(nodes.target);
|
|
1585
1566
|
nodes.target.connect(master);
|
|
1586
|
-
if (props.filter
|
|
1567
|
+
if (props.filter) {
|
|
1587
1568
|
nodes.filter = context.createBiquadFilter();
|
|
1588
1569
|
nodes.filter.type = props.filter.type;
|
|
1589
1570
|
nodes.filter.frequency.value = props.filter.cutoff;
|
|
@@ -1605,22 +1586,22 @@ class Synthesizer {
|
|
|
1605
1586
|
nodes.convolverDepth.connect(master);
|
|
1606
1587
|
}
|
|
1607
1588
|
if (props.oscillator.envelope) {
|
|
1608
|
-
const amount =
|
|
1609
|
-
startEnvelope(nodes.oscillator.frequency,
|
|
1589
|
+
const amount = fv * (Math.pow(2.0, props.oscillator.envelope.amount / 12.0) - 1.0);
|
|
1590
|
+
startEnvelope(nodes.oscillator.frequency, fv, amount, props.oscillator.envelope.ADSR);
|
|
1610
1591
|
}
|
|
1611
1592
|
if (props.amp.envelope) {
|
|
1612
1593
|
startEnvelope(nodes.amp.gain, 0.0, props.amp.envelope.amount, props.amp.envelope.ADSR);
|
|
1613
1594
|
}
|
|
1614
|
-
let stop = null;
|
|
1615
1595
|
nodes.oscillator.start(start);
|
|
1616
|
-
if (
|
|
1596
|
+
if (dv > 0) {
|
|
1617
1597
|
release();
|
|
1618
1598
|
}
|
|
1619
1599
|
else {
|
|
1620
1600
|
return { release };
|
|
1621
1601
|
}
|
|
1622
1602
|
function release() {
|
|
1623
|
-
|
|
1603
|
+
let stop = null;
|
|
1604
|
+
const end = dv > 0 ? dv : (context.currentTime - start);
|
|
1624
1605
|
if (props.amp.envelope) {
|
|
1625
1606
|
const ADSR = props.amp.envelope.ADSR;
|
|
1626
1607
|
const adsr = [ADSR[0] / 1000, ADSR[1] / 1000, ADSR[2], ADSR[3] / 1000];
|
|
@@ -1634,8 +1615,8 @@ class Synthesizer {
|
|
|
1634
1615
|
nodes.oscillatorLFO.stop(stop);
|
|
1635
1616
|
}
|
|
1636
1617
|
if (props.oscillator.envelope) {
|
|
1637
|
-
const amount =
|
|
1638
|
-
stopEnvelope(nodes.oscillator.frequency,
|
|
1618
|
+
const amount = fv * (Math.pow(2.0, props.oscillator.envelope.amount / 12.0) - 1.0);
|
|
1619
|
+
stopEnvelope(nodes.oscillator.frequency, fv, amount, props.oscillator.envelope.ADSR);
|
|
1639
1620
|
}
|
|
1640
1621
|
if (props.amp.envelope) {
|
|
1641
1622
|
stopEnvelope(nodes.amp.gain, 0.0, props.amp.envelope.amount, props.amp.envelope.ADSR);
|
|
@@ -1654,15 +1635,15 @@ class Synthesizer {
|
|
|
1654
1635
|
}, 2000);
|
|
1655
1636
|
}
|
|
1656
1637
|
function stopEnvelope(param, base, amount, ADSR) {
|
|
1657
|
-
const rate = ADSR[0] === 0.0 ? 1.0 : Math.min(
|
|
1638
|
+
const rate = ADSR[0] === 0.0 ? 1.0 : Math.min(dv / (ADSR[0] / 1000), 1.0);
|
|
1658
1639
|
if (rate < 1.0) {
|
|
1659
1640
|
param.cancelScheduledValues(start);
|
|
1660
1641
|
param.setValueAtTime(base, start);
|
|
1661
1642
|
param.linearRampToValueAtTime(base + amount * rate, start + ADSR[0] / 1000 * rate);
|
|
1662
1643
|
param.linearRampToValueAtTime(base + amount * rate * ADSR[2], start + (ADSR[0] + ADSR[1]) / 1000 * rate);
|
|
1663
1644
|
}
|
|
1664
|
-
param.linearRampToValueAtTime(base + amount * rate * ADSR[2], start + Math.max((ADSR[0] + ADSR[1]) / 1000 * rate,
|
|
1665
|
-
param.linearRampToValueAtTime(base, start + Math.max((ADSR[0] + ADSR[1]) / 1000 * rate,
|
|
1645
|
+
param.linearRampToValueAtTime(base + amount * rate * ADSR[2], start + Math.max((ADSR[0] + ADSR[1]) / 1000 * rate, dv));
|
|
1646
|
+
param.linearRampToValueAtTime(base, start + Math.max((ADSR[0] + ADSR[1]) / 1000 * rate, dv) + ADSR[3] / 1000);
|
|
1666
1647
|
}
|
|
1667
1648
|
function startEnvelope(param, base, amount, ADSR) {
|
|
1668
1649
|
param.value = base;
|
|
@@ -1704,12 +1685,6 @@ const basics = {
|
|
|
1704
1685
|
AnalogStick,
|
|
1705
1686
|
DirectionalPad,
|
|
1706
1687
|
};
|
|
1707
|
-
const audio = {
|
|
1708
|
-
master,
|
|
1709
|
-
context,
|
|
1710
|
-
synthesizer,
|
|
1711
|
-
load
|
|
1712
|
-
};
|
|
1713
1688
|
const xnew = Object.assign(xnew$1, {
|
|
1714
1689
|
basics,
|
|
1715
1690
|
audio
|