@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.js
CHANGED
|
@@ -4,102 +4,6 @@
|
|
|
4
4
|
(global = typeof globalThis !== 'undefined' ? globalThis : global || self, global.xnew = factory());
|
|
5
5
|
})(this, (function () { 'use strict';
|
|
6
6
|
|
|
7
|
-
//----------------------------------------------------------------------------------------------------
|
|
8
|
-
// ticker
|
|
9
|
-
//----------------------------------------------------------------------------------------------------
|
|
10
|
-
class Ticker {
|
|
11
|
-
constructor(callback) {
|
|
12
|
-
const self = this;
|
|
13
|
-
this.id = null;
|
|
14
|
-
let previous = 0;
|
|
15
|
-
ticker();
|
|
16
|
-
function ticker() {
|
|
17
|
-
const time = Date.now();
|
|
18
|
-
const interval = 1000 / 60;
|
|
19
|
-
if (time - previous > interval * 0.9) {
|
|
20
|
-
callback(time);
|
|
21
|
-
previous = time;
|
|
22
|
-
}
|
|
23
|
-
self.id = requestAnimationFrame(ticker);
|
|
24
|
-
}
|
|
25
|
-
}
|
|
26
|
-
clear() {
|
|
27
|
-
if (this.id !== null) {
|
|
28
|
-
cancelAnimationFrame(this.id);
|
|
29
|
-
this.id = null;
|
|
30
|
-
}
|
|
31
|
-
}
|
|
32
|
-
}
|
|
33
|
-
//----------------------------------------------------------------------------------------------------
|
|
34
|
-
// timer
|
|
35
|
-
//----------------------------------------------------------------------------------------------------
|
|
36
|
-
class Timer {
|
|
37
|
-
constructor(timeout, transition, delay, loop = false) {
|
|
38
|
-
var _a;
|
|
39
|
-
this.timeout = timeout;
|
|
40
|
-
this.transition = transition;
|
|
41
|
-
this.delay = delay;
|
|
42
|
-
this.loop = loop;
|
|
43
|
-
this.id = null;
|
|
44
|
-
this.time = 0.0;
|
|
45
|
-
this.offset = 0.0;
|
|
46
|
-
this.status = 0;
|
|
47
|
-
this.ticker = new Ticker((time) => { var _a; return (_a = this.transition) === null || _a === void 0 ? void 0 : _a.call(this, this.elapsed() / this.delay); });
|
|
48
|
-
this.visibilitychange = () => document.hidden === false ? this._start() : this._stop();
|
|
49
|
-
document.addEventListener('visibilitychange', this.visibilitychange);
|
|
50
|
-
if (this.delay > 0.0) {
|
|
51
|
-
(_a = this.transition) === null || _a === void 0 ? void 0 : _a.call(this, 0.0);
|
|
52
|
-
}
|
|
53
|
-
this.start();
|
|
54
|
-
}
|
|
55
|
-
clear() {
|
|
56
|
-
if (this.id !== null) {
|
|
57
|
-
clearTimeout(this.id);
|
|
58
|
-
this.id = null;
|
|
59
|
-
}
|
|
60
|
-
document.removeEventListener('visibilitychange', this.visibilitychange);
|
|
61
|
-
this.ticker.clear();
|
|
62
|
-
}
|
|
63
|
-
elapsed() {
|
|
64
|
-
return this.offset + (this.id !== null ? (Date.now() - this.time) : 0);
|
|
65
|
-
}
|
|
66
|
-
start() {
|
|
67
|
-
this.status = 1;
|
|
68
|
-
this._start();
|
|
69
|
-
}
|
|
70
|
-
stop() {
|
|
71
|
-
this._stop();
|
|
72
|
-
this.status = 0;
|
|
73
|
-
}
|
|
74
|
-
_start() {
|
|
75
|
-
if (this.status === 1 && this.id === null) {
|
|
76
|
-
this.id = setTimeout(() => {
|
|
77
|
-
var _a;
|
|
78
|
-
this.timeout();
|
|
79
|
-
(_a = this.transition) === null || _a === void 0 ? void 0 : _a.call(this, 1.0);
|
|
80
|
-
this.id = null;
|
|
81
|
-
this.time = 0.0;
|
|
82
|
-
this.offset = 0.0;
|
|
83
|
-
if (this.loop) {
|
|
84
|
-
this.start();
|
|
85
|
-
}
|
|
86
|
-
else {
|
|
87
|
-
this.clear();
|
|
88
|
-
}
|
|
89
|
-
}, this.delay - this.offset);
|
|
90
|
-
this.time = Date.now();
|
|
91
|
-
}
|
|
92
|
-
}
|
|
93
|
-
_stop() {
|
|
94
|
-
if (this.status === 1 && this.id !== null) {
|
|
95
|
-
this.offset = this.offset + Date.now() - this.time;
|
|
96
|
-
clearTimeout(this.id);
|
|
97
|
-
this.id = null;
|
|
98
|
-
this.time = 0.0;
|
|
99
|
-
}
|
|
100
|
-
}
|
|
101
|
-
}
|
|
102
|
-
|
|
103
7
|
//----------------------------------------------------------------------------------------------------
|
|
104
8
|
// map set
|
|
105
9
|
//----------------------------------------------------------------------------------------------------
|
|
@@ -198,30 +102,141 @@
|
|
|
198
102
|
}
|
|
199
103
|
|
|
200
104
|
//----------------------------------------------------------------------------------------------------
|
|
201
|
-
//
|
|
105
|
+
// ticker
|
|
202
106
|
//----------------------------------------------------------------------------------------------------
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
|
|
107
|
+
class Ticker {
|
|
108
|
+
constructor(callback) {
|
|
109
|
+
const self = this;
|
|
110
|
+
this.id = null;
|
|
111
|
+
let previous = 0;
|
|
112
|
+
ticker();
|
|
113
|
+
function ticker() {
|
|
114
|
+
const time = Date.now();
|
|
115
|
+
const interval = 1000 / 60;
|
|
116
|
+
if (time - previous > interval * 0.9) {
|
|
117
|
+
callback(time);
|
|
118
|
+
previous = time;
|
|
119
|
+
}
|
|
120
|
+
self.id = requestAnimationFrame(ticker);
|
|
121
|
+
}
|
|
209
122
|
}
|
|
210
|
-
|
|
211
|
-
this.
|
|
212
|
-
|
|
123
|
+
clear() {
|
|
124
|
+
if (this.id !== null) {
|
|
125
|
+
cancelAnimationFrame(this.id);
|
|
126
|
+
this.id = null;
|
|
127
|
+
}
|
|
213
128
|
}
|
|
214
|
-
|
|
215
|
-
|
|
216
|
-
|
|
129
|
+
}
|
|
130
|
+
//----------------------------------------------------------------------------------------------------
|
|
131
|
+
// timer
|
|
132
|
+
//----------------------------------------------------------------------------------------------------
|
|
133
|
+
class Timer {
|
|
134
|
+
constructor(transition, timeout, interval, { loop = false, easing = 'linear' } = {}) {
|
|
135
|
+
var _a;
|
|
136
|
+
this.transition = transition;
|
|
137
|
+
this.timeout = timeout;
|
|
138
|
+
this.interval = interval !== null && interval !== void 0 ? interval : 0;
|
|
139
|
+
this.loop = loop;
|
|
140
|
+
this.easing = easing;
|
|
141
|
+
this.id = null;
|
|
142
|
+
this.time = 0.0;
|
|
143
|
+
this.offset = 0.0;
|
|
144
|
+
this.status = 0;
|
|
145
|
+
this.ticker = new Ticker((time) => {
|
|
146
|
+
var _a;
|
|
147
|
+
let p = Math.min(this.elapsed() / this.interval, 1.0);
|
|
148
|
+
if (easing === 'ease-out') {
|
|
149
|
+
p = Math.pow((1.0 - Math.pow((1.0 - p), 2.0)), 0.5);
|
|
150
|
+
}
|
|
151
|
+
else if (easing === 'ease-in') {
|
|
152
|
+
p = Math.pow((1.0 - Math.pow((1.0 - p), 0.5)), 2.0);
|
|
153
|
+
}
|
|
154
|
+
else if (easing === 'ease') {
|
|
155
|
+
p = (1.0 - Math.cos(p * Math.PI)) / 2.0;
|
|
156
|
+
}
|
|
157
|
+
else if (easing === 'ease-in-out') {
|
|
158
|
+
p = (1.0 - Math.cos(p * Math.PI)) / 2.0;
|
|
159
|
+
}
|
|
160
|
+
(_a = this.transition) === null || _a === void 0 ? void 0 : _a.call(this, p);
|
|
161
|
+
});
|
|
162
|
+
this.visibilitychange = () => document.hidden === false ? this._start() : this._stop();
|
|
163
|
+
document.addEventListener('visibilitychange', this.visibilitychange);
|
|
164
|
+
if (this.interval > 0.0) {
|
|
165
|
+
(_a = this.transition) === null || _a === void 0 ? void 0 : _a.call(this, 0.0);
|
|
166
|
+
}
|
|
167
|
+
this.start();
|
|
168
|
+
}
|
|
169
|
+
clear() {
|
|
170
|
+
if (this.id !== null) {
|
|
171
|
+
clearTimeout(this.id);
|
|
172
|
+
this.id = null;
|
|
173
|
+
}
|
|
174
|
+
document.removeEventListener('visibilitychange', this.visibilitychange);
|
|
175
|
+
this.ticker.clear();
|
|
176
|
+
}
|
|
177
|
+
elapsed() {
|
|
178
|
+
return this.offset + (this.id !== null ? (Date.now() - this.time) : 0);
|
|
179
|
+
}
|
|
180
|
+
start() {
|
|
181
|
+
this.status = 1;
|
|
182
|
+
this._start();
|
|
183
|
+
}
|
|
184
|
+
stop() {
|
|
185
|
+
this._stop();
|
|
186
|
+
this.status = 0;
|
|
187
|
+
}
|
|
188
|
+
_start() {
|
|
189
|
+
if (this.status === 1 && this.id === null) {
|
|
190
|
+
this.id = setTimeout(() => {
|
|
191
|
+
var _a, _b;
|
|
192
|
+
(_a = this.timeout) === null || _a === void 0 ? void 0 : _a.call(this);
|
|
193
|
+
(_b = this.transition) === null || _b === void 0 ? void 0 : _b.call(this, 1.0);
|
|
194
|
+
this.id = null;
|
|
195
|
+
this.time = 0.0;
|
|
196
|
+
this.offset = 0.0;
|
|
197
|
+
this.loop ? this.start() : this.clear();
|
|
198
|
+
}, this.interval - this.offset);
|
|
199
|
+
this.time = Date.now();
|
|
200
|
+
}
|
|
201
|
+
}
|
|
202
|
+
_stop() {
|
|
203
|
+
if (this.status === 1 && this.id !== null) {
|
|
204
|
+
this.offset = this.offset + Date.now() - this.time;
|
|
205
|
+
clearTimeout(this.id);
|
|
206
|
+
this.id = null;
|
|
207
|
+
this.time = 0.0;
|
|
208
|
+
}
|
|
217
209
|
}
|
|
218
210
|
}
|
|
211
|
+
|
|
212
|
+
//----------------------------------------------------------------------------------------------------
|
|
213
|
+
// utils
|
|
214
|
+
//----------------------------------------------------------------------------------------------------
|
|
215
|
+
const SYSTEM_EVENTS = ['start', 'update', 'stop', 'finalize'];
|
|
219
216
|
//----------------------------------------------------------------------------------------------------
|
|
220
217
|
// unit
|
|
221
218
|
//----------------------------------------------------------------------------------------------------
|
|
222
219
|
class Unit {
|
|
223
|
-
constructor(parent,
|
|
220
|
+
constructor(parent, ...args) {
|
|
224
221
|
var _a;
|
|
222
|
+
let target;
|
|
223
|
+
if (args[0] instanceof HTMLElement || args[0] instanceof SVGElement) {
|
|
224
|
+
target = args.shift(); // an existing html element
|
|
225
|
+
}
|
|
226
|
+
else if (typeof args[0] === 'string' && args[0].match(/<((\w+)[^>]*?)\/?>/)) {
|
|
227
|
+
target = args.shift();
|
|
228
|
+
}
|
|
229
|
+
else if (typeof args[0] === 'string') {
|
|
230
|
+
const query = args.shift();
|
|
231
|
+
target = document.querySelector(query);
|
|
232
|
+
if (target === null)
|
|
233
|
+
throw new Error(`'${query}' can not be found.`);
|
|
234
|
+
}
|
|
235
|
+
else {
|
|
236
|
+
target = null;
|
|
237
|
+
}
|
|
238
|
+
const component = args.shift();
|
|
239
|
+
const props = args.shift();
|
|
225
240
|
let baseElement;
|
|
226
241
|
if (target instanceof HTMLElement || target instanceof SVGElement) {
|
|
227
242
|
baseElement = target;
|
|
@@ -274,6 +289,9 @@
|
|
|
274
289
|
Unit.finalize(this);
|
|
275
290
|
Unit.initialize(this, anchor);
|
|
276
291
|
}
|
|
292
|
+
append(...args) {
|
|
293
|
+
new Unit(this, ...args);
|
|
294
|
+
}
|
|
277
295
|
static initialize(unit, anchor) {
|
|
278
296
|
const backup = Unit.current;
|
|
279
297
|
Unit.current = unit;
|
|
@@ -315,7 +333,7 @@
|
|
|
315
333
|
unit._.systems.finalize.forEach((listener) => Unit.scope(Unit.snapshot(unit), listener));
|
|
316
334
|
unit.off();
|
|
317
335
|
Unit.suboff(unit, null);
|
|
318
|
-
unit._.components.forEach((component) => Unit.
|
|
336
|
+
unit._.components.forEach((component) => Unit.component2units.delete(component, unit));
|
|
319
337
|
if (unit._.elements.length > 0) {
|
|
320
338
|
unit._.baseElement.removeChild(unit._.elements[0]);
|
|
321
339
|
unit._.currentElement = unit._.baseElement;
|
|
@@ -353,7 +371,7 @@
|
|
|
353
371
|
static extend(unit, component, props) {
|
|
354
372
|
var _a;
|
|
355
373
|
unit._.components.push(component);
|
|
356
|
-
Unit.
|
|
374
|
+
Unit.component2units.add(component, unit);
|
|
357
375
|
const defines = (_a = component(unit, props)) !== null && _a !== void 0 ? _a : {};
|
|
358
376
|
Object.keys(defines).forEach((key) => {
|
|
359
377
|
if (unit[key] !== undefined && unit._.defines[key] === undefined) {
|
|
@@ -361,12 +379,10 @@
|
|
|
361
379
|
}
|
|
362
380
|
const descriptor = Object.getOwnPropertyDescriptor(defines, key);
|
|
363
381
|
const wrapper = { configurable: true, enumerable: true };
|
|
364
|
-
if (descriptor === null || descriptor === void 0 ? void 0 : descriptor.get)
|
|
382
|
+
if (descriptor === null || descriptor === void 0 ? void 0 : descriptor.get)
|
|
365
383
|
wrapper.get = Unit.wrap(unit, descriptor.get);
|
|
366
|
-
|
|
367
|
-
if (descriptor === null || descriptor === void 0 ? void 0 : descriptor.set) {
|
|
384
|
+
if (descriptor === null || descriptor === void 0 ? void 0 : descriptor.set)
|
|
368
385
|
wrapper.set = Unit.wrap(unit, descriptor.set);
|
|
369
|
-
}
|
|
370
386
|
if (typeof (descriptor === null || descriptor === void 0 ? void 0 : descriptor.value) === 'function') {
|
|
371
387
|
wrapper.value = Unit.wrap(unit, descriptor.value);
|
|
372
388
|
}
|
|
@@ -452,7 +468,7 @@
|
|
|
452
468
|
}
|
|
453
469
|
static find(component) {
|
|
454
470
|
var _a;
|
|
455
|
-
return [...((_a = Unit.
|
|
471
|
+
return [...((_a = Unit.component2units.get(component)) !== null && _a !== void 0 ? _a : [])];
|
|
456
472
|
}
|
|
457
473
|
on(type, listener, options) {
|
|
458
474
|
if (this._.state === 'finalized')
|
|
@@ -464,7 +480,7 @@
|
|
|
464
480
|
if (this._.listeners1.has(type, listener) === false) {
|
|
465
481
|
const execute = Unit.wrap(Unit.current, listener);
|
|
466
482
|
this._.listeners1.set(type, listener, [this.element, execute]);
|
|
467
|
-
Unit.
|
|
483
|
+
Unit.type2units.add(type, this);
|
|
468
484
|
if (/^[A-Za-z]/.test(type)) {
|
|
469
485
|
this.element.addEventListener(type, execute, options);
|
|
470
486
|
}
|
|
@@ -488,7 +504,7 @@
|
|
|
488
504
|
}
|
|
489
505
|
});
|
|
490
506
|
if (this._.listeners1.has(type) === false) {
|
|
491
|
-
Unit.
|
|
507
|
+
Unit.type2units.delete(type, this);
|
|
492
508
|
}
|
|
493
509
|
});
|
|
494
510
|
}
|
|
@@ -497,7 +513,7 @@
|
|
|
497
513
|
if (this._.state === 'finalized')
|
|
498
514
|
return;
|
|
499
515
|
if (type[0] === '+') {
|
|
500
|
-
(_a = Unit.
|
|
516
|
+
(_a = Unit.type2units.get(type)) === null || _a === void 0 ? void 0 : _a.forEach((unit) => {
|
|
501
517
|
var _a;
|
|
502
518
|
(_a = unit._.listeners1.get(type)) === null || _a === void 0 ? void 0 : _a.forEach(([_, execute]) => execute(...args));
|
|
503
519
|
});
|
|
@@ -531,36 +547,87 @@
|
|
|
531
547
|
});
|
|
532
548
|
}
|
|
533
549
|
}
|
|
534
|
-
Unit.
|
|
550
|
+
Unit.component2units = new MapSet();
|
|
535
551
|
//----------------------------------------------------------------------------------------------------
|
|
536
552
|
// event
|
|
537
553
|
//----------------------------------------------------------------------------------------------------
|
|
538
|
-
Unit.
|
|
539
|
-
|
|
540
|
-
|
|
541
|
-
|
|
542
|
-
|
|
554
|
+
Unit.type2units = new MapSet();
|
|
555
|
+
//----------------------------------------------------------------------------------------------------
|
|
556
|
+
// unit promise
|
|
557
|
+
//----------------------------------------------------------------------------------------------------
|
|
558
|
+
class UnitPromise {
|
|
559
|
+
constructor(promise) { this.promise = promise; }
|
|
560
|
+
then(callback) {
|
|
561
|
+
this.promise = this.promise.then(Unit.wrap(Unit.current, callback));
|
|
562
|
+
return this;
|
|
563
|
+
}
|
|
564
|
+
catch(callback) {
|
|
565
|
+
this.promise = this.promise.catch(Unit.wrap(Unit.current, callback));
|
|
566
|
+
return this;
|
|
543
567
|
}
|
|
544
|
-
|
|
545
|
-
|
|
546
|
-
|
|
568
|
+
finally(callback) {
|
|
569
|
+
this.promise = this.promise.finally(Unit.wrap(Unit.current, callback));
|
|
570
|
+
return this;
|
|
571
|
+
}
|
|
572
|
+
}
|
|
573
|
+
//----------------------------------------------------------------------------------------------------
|
|
574
|
+
// unit timer
|
|
575
|
+
//----------------------------------------------------------------------------------------------------
|
|
576
|
+
class UnitTimer {
|
|
577
|
+
constructor({ transition, timeout, interval, easing, loop }) {
|
|
578
|
+
this.stack = [];
|
|
579
|
+
this.unit = new Unit(Unit.current, UnitTimer.Component, { snapshot: Unit.snapshot(Unit.current), transition, timeout, interval, easing, loop });
|
|
580
|
+
}
|
|
581
|
+
clear() {
|
|
582
|
+
this.unit.off();
|
|
583
|
+
this.unit.finalize();
|
|
547
584
|
}
|
|
548
|
-
|
|
549
|
-
|
|
550
|
-
|
|
551
|
-
|
|
585
|
+
timeout(timeout, interval = 0) {
|
|
586
|
+
UnitTimer.execute(this, { timeout, interval });
|
|
587
|
+
return this;
|
|
588
|
+
}
|
|
589
|
+
transition(transition, interval = 0, easing = 'linear') {
|
|
590
|
+
UnitTimer.execute(this, { transition, interval, easing });
|
|
591
|
+
return this;
|
|
592
|
+
}
|
|
593
|
+
static execute(timer, { transition, timeout, interval, easing, loop }) {
|
|
594
|
+
if (timer.unit._.state === 'finalized') {
|
|
595
|
+
timer.unit = new Unit(Unit.current, UnitTimer.Component, { snapshot: Unit.snapshot(Unit.current), transition, timeout, interval, easing, loop });
|
|
596
|
+
}
|
|
597
|
+
else if (timer.stack.length === 0) {
|
|
598
|
+
timer.stack.push({ snapshot: Unit.snapshot(Unit.current), transition, timeout, interval, easing, loop });
|
|
599
|
+
timer.unit.on('finalize', () => { UnitTimer.next(timer); });
|
|
552
600
|
}
|
|
553
601
|
else {
|
|
554
|
-
|
|
555
|
-
if (target == null) {
|
|
556
|
-
throw new Error(`'${str}' can not be found.`);
|
|
557
|
-
}
|
|
602
|
+
timer.stack.push({ snapshot: Unit.snapshot(Unit.current), transition, timeout, interval, easing, loop });
|
|
558
603
|
}
|
|
559
604
|
}
|
|
560
|
-
|
|
561
|
-
|
|
605
|
+
static next(timer) {
|
|
606
|
+
if (timer.stack.length > 0) {
|
|
607
|
+
timer.unit = new Unit(Unit.current, UnitTimer.Component, timer.stack.shift());
|
|
608
|
+
timer.unit.on('finalize', () => { UnitTimer.next(timer); });
|
|
609
|
+
}
|
|
610
|
+
}
|
|
611
|
+
static Component(unit, { snapshot, transition, timeout, interval, loop, easing }) {
|
|
612
|
+
const timer = new Timer((x) => {
|
|
613
|
+
if (transition !== undefined)
|
|
614
|
+
Unit.scope(snapshot, transition, x);
|
|
615
|
+
}, () => {
|
|
616
|
+
if (transition !== undefined)
|
|
617
|
+
Unit.scope(snapshot, transition, 1.0);
|
|
618
|
+
if (timeout !== undefined)
|
|
619
|
+
Unit.scope(snapshot, timeout);
|
|
620
|
+
unit.finalize();
|
|
621
|
+
}, interval, { loop, easing });
|
|
622
|
+
unit.on('finalize', () => timer.clear());
|
|
623
|
+
}
|
|
624
|
+
}
|
|
625
|
+
|
|
626
|
+
const xnew$1 = Object.assign(function (...args) {
|
|
627
|
+
if (Unit.root === undefined) {
|
|
628
|
+
Unit.reset();
|
|
562
629
|
}
|
|
563
|
-
return new Unit(Unit.current,
|
|
630
|
+
return new Unit(Unit.current, ...args);
|
|
564
631
|
}, {
|
|
565
632
|
/**
|
|
566
633
|
* Creates a nested HTML/SVG element within the current component
|
|
@@ -733,65 +800,29 @@
|
|
|
733
800
|
throw new Error('xnew.find(component: Function): [component] is invalid.');
|
|
734
801
|
}
|
|
735
802
|
},
|
|
736
|
-
/**
|
|
737
|
-
* Appends new components to existing component(s) in the tree
|
|
738
|
-
* @param anchor - Component function or Unit instance to append to
|
|
739
|
-
* @param args - Arguments to pass to xnew for creating child components
|
|
740
|
-
* @throws Error if anchor parameter is invalid
|
|
741
|
-
* @example
|
|
742
|
-
* xnew.append(MyContainer, ChildComponent, { prop: 'value' })
|
|
743
|
-
* xnew.append(unitInstance, AnotherComponent)
|
|
744
|
-
*/
|
|
745
|
-
append(anchor, ...args) {
|
|
746
|
-
if (typeof anchor === 'function') {
|
|
747
|
-
const units = Unit.find(anchor);
|
|
748
|
-
Unit.scope(Unit.snapshot(units[0]), xnew$1, ...args);
|
|
749
|
-
}
|
|
750
|
-
else if (anchor instanceof Unit) {
|
|
751
|
-
Unit.scope(Unit.snapshot(anchor), xnew$1, ...args);
|
|
752
|
-
}
|
|
753
|
-
else {
|
|
754
|
-
throw new Error('xnew.append(anchor: Function | Unit, xnew arguments): [anchor] is invalid.');
|
|
755
|
-
}
|
|
756
|
-
},
|
|
757
803
|
/**
|
|
758
804
|
* Executes a callback once after a delay, managed by component lifecycle
|
|
759
|
-
* @param
|
|
760
|
-
* @param
|
|
805
|
+
* @param timeout - Function to execute after Interval
|
|
806
|
+
* @param interval - Interval duration in milliseconds
|
|
761
807
|
* @returns Object with clear() method to cancel the timeout
|
|
762
808
|
* @example
|
|
763
809
|
* const timer = xnew.timeout(() => console.log('Delayed'), 1000)
|
|
764
810
|
* // Cancel if needed: timer.clear()
|
|
765
811
|
*/
|
|
766
|
-
timeout(
|
|
767
|
-
|
|
768
|
-
const unit = xnew$1((self) => {
|
|
769
|
-
const timer = new Timer(() => {
|
|
770
|
-
Unit.scope(snapshot, callback);
|
|
771
|
-
self.finalize();
|
|
772
|
-
}, null, delay, false);
|
|
773
|
-
self.on('finalize', () => timer.clear());
|
|
774
|
-
});
|
|
775
|
-
return { clear: () => unit.finalize() };
|
|
812
|
+
timeout(timeout, interval = 0) {
|
|
813
|
+
return new UnitTimer({ timeout, interval });
|
|
776
814
|
},
|
|
777
815
|
/**
|
|
778
816
|
* Executes a callback repeatedly at specified intervals, managed by component lifecycle
|
|
779
|
-
* @param
|
|
780
|
-
* @param
|
|
817
|
+
* @param timeout - Function to execute at each interval
|
|
818
|
+
* @param interval - Interval duration in milliseconds
|
|
781
819
|
* @returns Object with clear() method to stop the interval
|
|
782
820
|
* @example
|
|
783
821
|
* const timer = xnew.interval(() => console.log('Tick'), 1000)
|
|
784
822
|
* // Stop when needed: timer.clear()
|
|
785
823
|
*/
|
|
786
|
-
interval(
|
|
787
|
-
|
|
788
|
-
const unit = xnew$1((self) => {
|
|
789
|
-
const timer = new Timer(() => {
|
|
790
|
-
Unit.scope(snapshot, callback);
|
|
791
|
-
}, null, delay, true);
|
|
792
|
-
self.on('finalize', () => timer.clear());
|
|
793
|
-
});
|
|
794
|
-
return { clear: () => unit.finalize() };
|
|
824
|
+
interval(timeout, interval) {
|
|
825
|
+
return new UnitTimer({ timeout, interval, loop: true });
|
|
795
826
|
},
|
|
796
827
|
/**
|
|
797
828
|
* Creates a transition animation with easing, executing callback with progress values
|
|
@@ -800,61 +831,14 @@
|
|
|
800
831
|
* @param easing - Easing function: 'linear', 'ease', 'ease-in', 'ease-out', 'ease-in-out' (default: 'linear')
|
|
801
832
|
* @returns Object with clear() and next() methods for controlling transitions
|
|
802
833
|
* @example
|
|
803
|
-
* xnew.transition(
|
|
804
|
-
* element.style.opacity =
|
|
805
|
-
* }, 500, 'ease-out').
|
|
806
|
-
* element.style.transform = `scale(${
|
|
834
|
+
* xnew.transition(p => {
|
|
835
|
+
* element.style.opacity = p
|
|
836
|
+
* }, 500, 'ease-out').transition(p => {
|
|
837
|
+
* element.style.transform = `scale(${p})`
|
|
807
838
|
* }, 300)
|
|
808
839
|
*/
|
|
809
|
-
transition(
|
|
810
|
-
|
|
811
|
-
let stacks = [];
|
|
812
|
-
let unit = xnew$1(Local, { callback, interval, easing });
|
|
813
|
-
let isRunning = true;
|
|
814
|
-
const timer = { clear, next };
|
|
815
|
-
return timer;
|
|
816
|
-
function execute() {
|
|
817
|
-
if (isRunning === false && stacks.length > 0) {
|
|
818
|
-
unit = xnew$1(Local, stacks.shift());
|
|
819
|
-
isRunning = true;
|
|
820
|
-
}
|
|
821
|
-
}
|
|
822
|
-
function clear() {
|
|
823
|
-
stacks = [];
|
|
824
|
-
unit.finalize();
|
|
825
|
-
}
|
|
826
|
-
function next(callback, interval = 0, easing = 'linear') {
|
|
827
|
-
stacks.push({ callback, interval, easing });
|
|
828
|
-
execute();
|
|
829
|
-
return timer;
|
|
830
|
-
}
|
|
831
|
-
function Local(self, { callback, interval, easing }) {
|
|
832
|
-
const timer = new Timer(() => {
|
|
833
|
-
Unit.scope(snapshot, callback, 1.0);
|
|
834
|
-
self.finalize();
|
|
835
|
-
}, (progress) => {
|
|
836
|
-
if (progress < 1.0) {
|
|
837
|
-
if (easing === 'ease-out') {
|
|
838
|
-
progress = Math.pow((1.0 - Math.pow((1.0 - progress), 2.0)), 0.5);
|
|
839
|
-
}
|
|
840
|
-
else if (easing === 'ease-in') {
|
|
841
|
-
progress = Math.pow((1.0 - Math.pow((1.0 - progress), 0.5)), 2.0);
|
|
842
|
-
}
|
|
843
|
-
else if (easing === 'ease') {
|
|
844
|
-
progress = (1.0 - Math.cos(progress * Math.PI)) / 2.0;
|
|
845
|
-
}
|
|
846
|
-
else if (easing === 'ease-in-out') {
|
|
847
|
-
progress = (1.0 - Math.cos(progress * Math.PI)) / 2.0;
|
|
848
|
-
}
|
|
849
|
-
Unit.scope(snapshot, callback, progress);
|
|
850
|
-
}
|
|
851
|
-
}, interval);
|
|
852
|
-
self.on('finalize', () => {
|
|
853
|
-
timer.clear();
|
|
854
|
-
isRunning = false;
|
|
855
|
-
execute();
|
|
856
|
-
});
|
|
857
|
-
}
|
|
840
|
+
transition(transition, interval = 0, easing = 'linear') {
|
|
841
|
+
return new UnitTimer({ transition, interval, easing });
|
|
858
842
|
},
|
|
859
843
|
/**
|
|
860
844
|
* Creates an event listener manager for a target element with automatic cleanup
|
|
@@ -889,6 +873,84 @@
|
|
|
889
873
|
},
|
|
890
874
|
});
|
|
891
875
|
|
|
876
|
+
function AccordionFrame(frame, { open = false, duration = 200, easing = 'ease' } = {}) {
|
|
877
|
+
const internal = xnew$1((internal) => {
|
|
878
|
+
return { frame, open, rate: 0.0, };
|
|
879
|
+
});
|
|
880
|
+
xnew$1.context('xnew.accordionframe', internal);
|
|
881
|
+
internal.on('-transition', ({ rate }) => internal.rate = rate);
|
|
882
|
+
internal.emit('-transition', { rate: open ? 1.0 : 0.0 });
|
|
883
|
+
return {
|
|
884
|
+
toggle() {
|
|
885
|
+
if (internal.rate === 1.0) {
|
|
886
|
+
frame.close();
|
|
887
|
+
}
|
|
888
|
+
else if (internal.rate === 0.0) {
|
|
889
|
+
frame.open();
|
|
890
|
+
}
|
|
891
|
+
},
|
|
892
|
+
open() {
|
|
893
|
+
if (internal.rate === 0.0) {
|
|
894
|
+
xnew$1.transition((x) => internal.emit('-transition', { rate: x }), duration, easing);
|
|
895
|
+
}
|
|
896
|
+
},
|
|
897
|
+
close() {
|
|
898
|
+
if (internal.rate === 1.0) {
|
|
899
|
+
xnew$1.transition((x) => internal.emit('-transition', { rate: 1.0 - x }), duration, easing);
|
|
900
|
+
}
|
|
901
|
+
}
|
|
902
|
+
};
|
|
903
|
+
}
|
|
904
|
+
function AccordionHeader(header, {} = {}) {
|
|
905
|
+
const internal = xnew$1.context('xnew.accordionframe');
|
|
906
|
+
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;">');
|
|
907
|
+
header.on('click', () => internal.frame.toggle());
|
|
908
|
+
}
|
|
909
|
+
function AccordionBullet(bullet, { type = 'arrow' } = {}) {
|
|
910
|
+
const internal = xnew$1.context('xnew.accordionframe');
|
|
911
|
+
xnew$1.nest('<div style="display:inline-block; position: relative; width: 0.55em; margin: 0 0.3em;">');
|
|
912
|
+
if (type === 'arrow') {
|
|
913
|
+
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;">`);
|
|
914
|
+
arrow.element.style.transform = `rotate(${internal.rate * 90 - 45}deg)`;
|
|
915
|
+
internal.on('-transition', ({ rate }) => {
|
|
916
|
+
arrow.element.style.transform = `rotate(${rate * 90 - 45}deg)`;
|
|
917
|
+
});
|
|
918
|
+
}
|
|
919
|
+
else if (type === 'plusminus') {
|
|
920
|
+
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;">`);
|
|
921
|
+
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;">`);
|
|
922
|
+
line2.element.style.transform = `rotate(90deg)`;
|
|
923
|
+
line2.element.style.opacity = `${1.0 - internal.rate}`;
|
|
924
|
+
internal.on('-transition', ({ rate }) => {
|
|
925
|
+
line1.element.style.transform = `rotate(${90 + rate * 90}deg)`;
|
|
926
|
+
line2.element.style.transform = `rotate(${rate * 180}deg)`;
|
|
927
|
+
});
|
|
928
|
+
}
|
|
929
|
+
}
|
|
930
|
+
function AccordionContent(content, {} = {}) {
|
|
931
|
+
const internal = xnew$1.context('xnew.accordionframe');
|
|
932
|
+
xnew$1.nest(`<div style="display: ${internal.open ? 'block' : 'none'};">`);
|
|
933
|
+
xnew$1.nest('<div style="padding: 0; display: flex; flex-direction: column; box-sizing: border-box;">');
|
|
934
|
+
internal.on('-transition', ({ rate }) => {
|
|
935
|
+
content.transition({ element: content.element, rate });
|
|
936
|
+
});
|
|
937
|
+
return {
|
|
938
|
+
transition({ element, rate }) {
|
|
939
|
+
const wrapper = element.parentElement;
|
|
940
|
+
wrapper.style.display = 'block';
|
|
941
|
+
if (rate === 0.0) {
|
|
942
|
+
wrapper.style.display = 'none';
|
|
943
|
+
}
|
|
944
|
+
else if (rate < 1.0) {
|
|
945
|
+
Object.assign(wrapper.style, { height: element.offsetHeight * rate + 'px', overflow: 'hidden', opacity: rate });
|
|
946
|
+
}
|
|
947
|
+
else {
|
|
948
|
+
Object.assign(wrapper.style, { height: 'auto', overflow: 'visible', opacity: 1.0 });
|
|
949
|
+
}
|
|
950
|
+
}
|
|
951
|
+
};
|
|
952
|
+
}
|
|
953
|
+
|
|
892
954
|
function ResizeEvent(resize) {
|
|
893
955
|
const observer = new ResizeObserver((entries) => {
|
|
894
956
|
for (const entry of entries) {
|
|
@@ -905,7 +967,29 @@
|
|
|
905
967
|
}
|
|
906
968
|
});
|
|
907
969
|
}
|
|
908
|
-
|
|
970
|
+
function KeyboardEvent(unit) {
|
|
971
|
+
const state = {};
|
|
972
|
+
xnew$1.listener(window).on('keydown', (event) => {
|
|
973
|
+
state[event.code] = 1;
|
|
974
|
+
unit.emit('-keydown', { event, type: '-keydown', code: event.code });
|
|
975
|
+
});
|
|
976
|
+
xnew$1.listener(window).on('keyup', (event) => {
|
|
977
|
+
state[event.code] = 0;
|
|
978
|
+
unit.emit('-keyup', { event, type: '-keyup', code: event.code });
|
|
979
|
+
});
|
|
980
|
+
xnew$1.listener(window).on('keydown', (event) => {
|
|
981
|
+
unit.emit('-arrowkeydown', { event, type: '-arrowkeydown', code: event.code, vector: getVector() });
|
|
982
|
+
});
|
|
983
|
+
xnew$1.listener(window).on('keyup', (event) => {
|
|
984
|
+
unit.emit('-arrowkeyup', { event, type: '-arrowkeyup', code: event.code, vector: getVector() });
|
|
985
|
+
});
|
|
986
|
+
function getVector() {
|
|
987
|
+
return {
|
|
988
|
+
x: (state['ArrowLeft'] ? -1 : 0) + (state['ArrowRight'] ? +1 : 0),
|
|
989
|
+
y: (state['ArrowUp'] ? -1 : 0) + (state['ArrowDown'] ? +1 : 0)
|
|
990
|
+
};
|
|
991
|
+
}
|
|
992
|
+
}
|
|
909
993
|
function PointerEvent(unit) {
|
|
910
994
|
const internal = xnew$1();
|
|
911
995
|
internal.on('pointerdown', (event) => unit.emit('-pointerdown', { event, position: getPosition(unit.element, event) }));
|
|
@@ -1022,30 +1106,6 @@
|
|
|
1022
1106
|
return { x: event.clientX - rect.left, y: event.clientY - rect.top };
|
|
1023
1107
|
}
|
|
1024
1108
|
|
|
1025
|
-
function KeyboardEvent(unit) {
|
|
1026
|
-
const state = {};
|
|
1027
|
-
xnew$1.listener(window).on('keydown', (event) => {
|
|
1028
|
-
state[event.code] = 1;
|
|
1029
|
-
unit.emit('-keydown', { event, type: '-keydown', code: event.code });
|
|
1030
|
-
});
|
|
1031
|
-
xnew$1.listener(window).on('keyup', (event) => {
|
|
1032
|
-
state[event.code] = 0;
|
|
1033
|
-
unit.emit('-keyup', { event, type: '-keyup', code: event.code });
|
|
1034
|
-
});
|
|
1035
|
-
xnew$1.listener(window).on('keydown', (event) => {
|
|
1036
|
-
unit.emit('-arrowkeydown', { event, type: '-arrowkeydown', code: event.code, vector: getVector() });
|
|
1037
|
-
});
|
|
1038
|
-
xnew$1.listener(window).on('keyup', (event) => {
|
|
1039
|
-
unit.emit('-arrowkeyup', { event, type: '-arrowkeyup', code: event.code, vector: getVector() });
|
|
1040
|
-
});
|
|
1041
|
-
function getVector() {
|
|
1042
|
-
return {
|
|
1043
|
-
x: (state['ArrowLeft'] ? -1 : 0) + (state['ArrowRight'] ? +1 : 0),
|
|
1044
|
-
y: (state['ArrowUp'] ? -1 : 0) + (state['ArrowDown'] ? +1 : 0)
|
|
1045
|
-
};
|
|
1046
|
-
}
|
|
1047
|
-
}
|
|
1048
|
-
|
|
1049
1109
|
function Screen(screen, { width = 640, height = 480, fit = 'contain' } = {}) {
|
|
1050
1110
|
const size = { width, height };
|
|
1051
1111
|
const wrapper = xnew$1.nest('<div style="position: relative; width: 100%; height: 100%; overflow: hidden;">');
|
|
@@ -1202,84 +1262,6 @@
|
|
|
1202
1262
|
};
|
|
1203
1263
|
}
|
|
1204
1264
|
|
|
1205
|
-
function AccordionFrame(frame, { open = false, duration = 200, easing = 'ease' } = {}) {
|
|
1206
|
-
const internal = xnew$1((internal) => {
|
|
1207
|
-
return { frame, open, rate: 0.0, };
|
|
1208
|
-
});
|
|
1209
|
-
xnew$1.context('xnew.accordionframe', internal);
|
|
1210
|
-
internal.on('-transition', ({ rate }) => internal.rate = rate);
|
|
1211
|
-
internal.emit('-transition', { rate: open ? 1.0 : 0.0 });
|
|
1212
|
-
return {
|
|
1213
|
-
toggle() {
|
|
1214
|
-
if (internal.rate === 1.0) {
|
|
1215
|
-
frame.close();
|
|
1216
|
-
}
|
|
1217
|
-
else if (internal.rate === 0.0) {
|
|
1218
|
-
frame.open();
|
|
1219
|
-
}
|
|
1220
|
-
},
|
|
1221
|
-
open() {
|
|
1222
|
-
if (internal.rate === 0.0) {
|
|
1223
|
-
xnew$1.transition((x) => internal.emit('-transition', { rate: x }), duration, easing);
|
|
1224
|
-
}
|
|
1225
|
-
},
|
|
1226
|
-
close() {
|
|
1227
|
-
if (internal.rate === 1.0) {
|
|
1228
|
-
xnew$1.transition((x) => internal.emit('-transition', { rate: 1.0 - x }), duration, easing);
|
|
1229
|
-
}
|
|
1230
|
-
}
|
|
1231
|
-
};
|
|
1232
|
-
}
|
|
1233
|
-
function AccordionHeader(header, {} = {}) {
|
|
1234
|
-
const internal = xnew$1.context('xnew.accordionframe');
|
|
1235
|
-
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;">');
|
|
1236
|
-
header.on('click', () => internal.frame.toggle());
|
|
1237
|
-
}
|
|
1238
|
-
function AccordionBullet(bullet, { type = 'arrow' } = {}) {
|
|
1239
|
-
const internal = xnew$1.context('xnew.accordionframe');
|
|
1240
|
-
xnew$1.nest('<div style="display:inline-block; position: relative; width: 0.55em; margin: 0 0.3em;">');
|
|
1241
|
-
if (type === 'arrow') {
|
|
1242
|
-
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;">`);
|
|
1243
|
-
arrow.element.style.transform = `rotate(${internal.rate * 90 - 45}deg)`;
|
|
1244
|
-
internal.on('-transition', ({ rate }) => {
|
|
1245
|
-
arrow.element.style.transform = `rotate(${rate * 90 - 45}deg)`;
|
|
1246
|
-
});
|
|
1247
|
-
}
|
|
1248
|
-
else if (type === 'plusminus') {
|
|
1249
|
-
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;">`);
|
|
1250
|
-
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;">`);
|
|
1251
|
-
line2.element.style.transform = `rotate(90deg)`;
|
|
1252
|
-
line2.element.style.opacity = `${1.0 - internal.rate}`;
|
|
1253
|
-
internal.on('-transition', ({ rate }) => {
|
|
1254
|
-
line1.element.style.transform = `rotate(${90 + rate * 90}deg)`;
|
|
1255
|
-
line2.element.style.transform = `rotate(${rate * 180}deg)`;
|
|
1256
|
-
});
|
|
1257
|
-
}
|
|
1258
|
-
}
|
|
1259
|
-
function AccordionContent(content, {} = {}) {
|
|
1260
|
-
const internal = xnew$1.context('xnew.accordionframe');
|
|
1261
|
-
xnew$1.nest(`<div style="display: ${internal.open ? 'block' : 'none'};">`);
|
|
1262
|
-
xnew$1.nest('<div style="padding: 0; display: flex; flex-direction: column; box-sizing: border-box;">');
|
|
1263
|
-
internal.on('-transition', ({ rate }) => {
|
|
1264
|
-
content.transition({ element: content.element, rate });
|
|
1265
|
-
});
|
|
1266
|
-
return {
|
|
1267
|
-
transition({ element, rate }) {
|
|
1268
|
-
const wrapper = element.parentElement;
|
|
1269
|
-
wrapper.style.display = 'block';
|
|
1270
|
-
if (rate === 0.0) {
|
|
1271
|
-
wrapper.style.display = 'none';
|
|
1272
|
-
}
|
|
1273
|
-
else if (rate < 1.0) {
|
|
1274
|
-
Object.assign(wrapper.style, { height: element.offsetHeight * rate + 'px', overflow: 'hidden', opacity: rate });
|
|
1275
|
-
}
|
|
1276
|
-
else {
|
|
1277
|
-
Object.assign(wrapper.style, { height: 'auto', overflow: 'visible', opacity: 1.0 });
|
|
1278
|
-
}
|
|
1279
|
-
}
|
|
1280
|
-
};
|
|
1281
|
-
}
|
|
1282
|
-
|
|
1283
1265
|
function DragFrame(frame, { x = 0, y = 0 } = {}) {
|
|
1284
1266
|
const absolute = xnew$1.nest(`<div style="position: absolute; top: ${y}px; left: ${x}px;">`);
|
|
1285
1267
|
xnew$1.context('xnew.dragframe', { frame, absolute });
|
|
@@ -1317,11 +1299,11 @@
|
|
|
1317
1299
|
// controller
|
|
1318
1300
|
//----------------------------------------------------------------------------------------------------
|
|
1319
1301
|
function SVGTemplate(self, { fill = null, fillOpacity = 0.8, stroke = null, strokeOpacity = 0.8, strokeWidth = 2, strokeLinejoin = 'round' }) {
|
|
1320
|
-
xnew$1.nest(`<svg
|
|
1321
|
-
viewBox="0 0 100 100"
|
|
1322
|
-
style="position: absolute; width: 100%; height: 100%; pointer-select: none;
|
|
1323
|
-
${fill ? `fill: ${fill}; fill-opacity: ${fillOpacity};` : ''}
|
|
1324
|
-
${stroke ? `stroke: ${stroke}; stroke-opacity: ${strokeOpacity}; stroke-width: ${strokeWidth}; stroke-linejoin: ${strokeLinejoin};` : ''}
|
|
1302
|
+
xnew$1.nest(`<svg
|
|
1303
|
+
viewBox="0 0 100 100"
|
|
1304
|
+
style="position: absolute; width: 100%; height: 100%; pointer-select: none;
|
|
1305
|
+
${fill ? `fill: ${fill}; fill-opacity: ${fillOpacity};` : ''}
|
|
1306
|
+
${stroke ? `stroke: ${stroke}; stroke-opacity: ${strokeOpacity}; stroke-width: ${strokeWidth}; stroke-linejoin: ${strokeLinejoin};` : ''}
|
|
1325
1307
|
">`);
|
|
1326
1308
|
}
|
|
1327
1309
|
function AnalogStick(self, { size, fill = '#FFF', fillOpacity = 0.8, stroke = '#000', strokeOpacity = 0.8, strokeWidth = 2, strokeLinejoin = 'round' } = {}) {
|
|
@@ -1473,29 +1455,41 @@
|
|
|
1473
1455
|
const master = context.createGain();
|
|
1474
1456
|
master.gain.value = 1.0;
|
|
1475
1457
|
master.connect(context.destination);
|
|
1476
|
-
|
|
1477
|
-
|
|
1478
|
-
|
|
1458
|
+
window.addEventListener('touchstart', initialize, true);
|
|
1459
|
+
window.addEventListener('mousedown', initialize, true);
|
|
1460
|
+
function initialize() {
|
|
1461
|
+
new Synthesizer({ oscillator: { type: 'sine' }, amp: { envelope: { amount: 0, ADSR: [0, 0, 0, 0] } } }).press(440);
|
|
1462
|
+
window.removeEventListener('touchstart', initialize, true);
|
|
1463
|
+
window.removeEventListener('mousedown', initialize, true);
|
|
1479
1464
|
}
|
|
1480
|
-
const
|
|
1465
|
+
const audio = {
|
|
1466
|
+
load(path) {
|
|
1467
|
+
return new AudioFile(path);
|
|
1468
|
+
},
|
|
1469
|
+
synthesizer(props) {
|
|
1470
|
+
return new Synthesizer(props);
|
|
1471
|
+
},
|
|
1472
|
+
get volume() {
|
|
1473
|
+
return master.gain.value;
|
|
1474
|
+
},
|
|
1475
|
+
set volume(value) {
|
|
1476
|
+
master.gain.value = value;
|
|
1477
|
+
}
|
|
1478
|
+
};
|
|
1479
|
+
//----------------------------------------------------------------------------------------------------
|
|
1480
|
+
// audio file
|
|
1481
|
+
//----------------------------------------------------------------------------------------------------
|
|
1481
1482
|
class AudioFile {
|
|
1482
1483
|
constructor(path) {
|
|
1483
|
-
|
|
1484
|
-
|
|
1485
|
-
|
|
1486
|
-
|
|
1487
|
-
|
|
1488
|
-
|
|
1489
|
-
|
|
1490
|
-
|
|
1491
|
-
|
|
1492
|
-
this.buffer = response;
|
|
1493
|
-
})
|
|
1494
|
-
.catch(() => {
|
|
1495
|
-
console.warn(`"${path}" could not be loaded.`);
|
|
1496
|
-
});
|
|
1497
|
-
store.set(path, this.buffer);
|
|
1498
|
-
}
|
|
1484
|
+
this.promise = fetch(path)
|
|
1485
|
+
.then((response) => response.arrayBuffer())
|
|
1486
|
+
.then((response) => context.decodeAudioData(response))
|
|
1487
|
+
.then((response) => {
|
|
1488
|
+
this.buffer = response;
|
|
1489
|
+
})
|
|
1490
|
+
.catch(() => {
|
|
1491
|
+
console.warn(`"${path}" could not be loaded.`);
|
|
1492
|
+
});
|
|
1499
1493
|
this.start = null;
|
|
1500
1494
|
}
|
|
1501
1495
|
// set volume(value: number) {
|
|
@@ -1534,17 +1528,6 @@
|
|
|
1534
1528
|
}
|
|
1535
1529
|
}
|
|
1536
1530
|
}
|
|
1537
|
-
|
|
1538
|
-
function synthesizer(props) {
|
|
1539
|
-
return new Synthesizer(props);
|
|
1540
|
-
}
|
|
1541
|
-
window.addEventListener('touchstart', initialize, true);
|
|
1542
|
-
window.addEventListener('mousedown', initialize, true);
|
|
1543
|
-
function initialize() {
|
|
1544
|
-
new Synthesizer({ oscillator: { type: 'sine' }, amp: { envelope: { amount: 0, ADSR: [0, 0, 0, 0] } } }).press(440);
|
|
1545
|
-
window.removeEventListener('touchstart', initialize, true);
|
|
1546
|
-
window.removeEventListener('mousedown', initialize, true);
|
|
1547
|
-
}
|
|
1548
1531
|
const keymap = {
|
|
1549
1532
|
'A0': 27.500, 'A#0': 29.135, 'B0': 30.868,
|
|
1550
1533
|
'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,
|
|
@@ -1560,23 +1543,21 @@
|
|
|
1560
1543
|
'1m': 4.000, '2n': 2.000, '4n': 1.000, '8n': 0.500, '16n': 0.250, '32n': 0.125,
|
|
1561
1544
|
};
|
|
1562
1545
|
class Synthesizer {
|
|
1563
|
-
constructor(props) {
|
|
1564
|
-
this.props = props;
|
|
1565
|
-
}
|
|
1546
|
+
constructor(props) { this.props = props; }
|
|
1566
1547
|
press(frequency, duration, wait) {
|
|
1567
1548
|
var _a;
|
|
1568
1549
|
const props = this.props;
|
|
1569
|
-
const
|
|
1570
|
-
const
|
|
1550
|
+
const fv = typeof frequency === 'string' ? keymap[frequency] : frequency;
|
|
1551
|
+
const dv = typeof duration === 'string' ? (notemap[duration] * 60 / ((_a = props.bpm) !== null && _a !== void 0 ? _a : 120)) : (typeof duration === 'number' ? (duration / 1000) : 0);
|
|
1571
1552
|
const start = context.currentTime + (wait !== null && wait !== void 0 ? wait : 0) / 1000;
|
|
1572
1553
|
const nodes = {};
|
|
1573
1554
|
nodes.oscillator = context.createOscillator();
|
|
1574
1555
|
nodes.oscillator.type = props.oscillator.type;
|
|
1575
|
-
nodes.oscillator.frequency.value =
|
|
1556
|
+
nodes.oscillator.frequency.value = fv;
|
|
1576
1557
|
if (props.oscillator.LFO) {
|
|
1577
1558
|
nodes.oscillatorLFO = context.createOscillator();
|
|
1578
1559
|
nodes.oscillatorLFODepth = context.createGain();
|
|
1579
|
-
nodes.oscillatorLFODepth.gain.value =
|
|
1560
|
+
nodes.oscillatorLFODepth.gain.value = fv * (Math.pow(2.0, props.oscillator.LFO.amount / 12.0) - 1.0);
|
|
1580
1561
|
nodes.oscillatorLFO.type = props.oscillator.LFO.type;
|
|
1581
1562
|
nodes.oscillatorLFO.frequency.value = props.oscillator.LFO.rate;
|
|
1582
1563
|
nodes.oscillatorLFO.start(start);
|
|
@@ -1589,7 +1570,7 @@
|
|
|
1589
1570
|
nodes.target.gain.value = 1.0;
|
|
1590
1571
|
nodes.amp.connect(nodes.target);
|
|
1591
1572
|
nodes.target.connect(master);
|
|
1592
|
-
if (props.filter
|
|
1573
|
+
if (props.filter) {
|
|
1593
1574
|
nodes.filter = context.createBiquadFilter();
|
|
1594
1575
|
nodes.filter.type = props.filter.type;
|
|
1595
1576
|
nodes.filter.frequency.value = props.filter.cutoff;
|
|
@@ -1611,22 +1592,22 @@
|
|
|
1611
1592
|
nodes.convolverDepth.connect(master);
|
|
1612
1593
|
}
|
|
1613
1594
|
if (props.oscillator.envelope) {
|
|
1614
|
-
const amount =
|
|
1615
|
-
startEnvelope(nodes.oscillator.frequency,
|
|
1595
|
+
const amount = fv * (Math.pow(2.0, props.oscillator.envelope.amount / 12.0) - 1.0);
|
|
1596
|
+
startEnvelope(nodes.oscillator.frequency, fv, amount, props.oscillator.envelope.ADSR);
|
|
1616
1597
|
}
|
|
1617
1598
|
if (props.amp.envelope) {
|
|
1618
1599
|
startEnvelope(nodes.amp.gain, 0.0, props.amp.envelope.amount, props.amp.envelope.ADSR);
|
|
1619
1600
|
}
|
|
1620
|
-
let stop = null;
|
|
1621
1601
|
nodes.oscillator.start(start);
|
|
1622
|
-
if (
|
|
1602
|
+
if (dv > 0) {
|
|
1623
1603
|
release();
|
|
1624
1604
|
}
|
|
1625
1605
|
else {
|
|
1626
1606
|
return { release };
|
|
1627
1607
|
}
|
|
1628
1608
|
function release() {
|
|
1629
|
-
|
|
1609
|
+
let stop = null;
|
|
1610
|
+
const end = dv > 0 ? dv : (context.currentTime - start);
|
|
1630
1611
|
if (props.amp.envelope) {
|
|
1631
1612
|
const ADSR = props.amp.envelope.ADSR;
|
|
1632
1613
|
const adsr = [ADSR[0] / 1000, ADSR[1] / 1000, ADSR[2], ADSR[3] / 1000];
|
|
@@ -1640,8 +1621,8 @@
|
|
|
1640
1621
|
nodes.oscillatorLFO.stop(stop);
|
|
1641
1622
|
}
|
|
1642
1623
|
if (props.oscillator.envelope) {
|
|
1643
|
-
const amount =
|
|
1644
|
-
stopEnvelope(nodes.oscillator.frequency,
|
|
1624
|
+
const amount = fv * (Math.pow(2.0, props.oscillator.envelope.amount / 12.0) - 1.0);
|
|
1625
|
+
stopEnvelope(nodes.oscillator.frequency, fv, amount, props.oscillator.envelope.ADSR);
|
|
1645
1626
|
}
|
|
1646
1627
|
if (props.amp.envelope) {
|
|
1647
1628
|
stopEnvelope(nodes.amp.gain, 0.0, props.amp.envelope.amount, props.amp.envelope.ADSR);
|
|
@@ -1660,15 +1641,15 @@
|
|
|
1660
1641
|
}, 2000);
|
|
1661
1642
|
}
|
|
1662
1643
|
function stopEnvelope(param, base, amount, ADSR) {
|
|
1663
|
-
const rate = ADSR[0] === 0.0 ? 1.0 : Math.min(
|
|
1644
|
+
const rate = ADSR[0] === 0.0 ? 1.0 : Math.min(dv / (ADSR[0] / 1000), 1.0);
|
|
1664
1645
|
if (rate < 1.0) {
|
|
1665
1646
|
param.cancelScheduledValues(start);
|
|
1666
1647
|
param.setValueAtTime(base, start);
|
|
1667
1648
|
param.linearRampToValueAtTime(base + amount * rate, start + ADSR[0] / 1000 * rate);
|
|
1668
1649
|
param.linearRampToValueAtTime(base + amount * rate * ADSR[2], start + (ADSR[0] + ADSR[1]) / 1000 * rate);
|
|
1669
1650
|
}
|
|
1670
|
-
param.linearRampToValueAtTime(base + amount * rate * ADSR[2], start + Math.max((ADSR[0] + ADSR[1]) / 1000 * rate,
|
|
1671
|
-
param.linearRampToValueAtTime(base, start + Math.max((ADSR[0] + ADSR[1]) / 1000 * rate,
|
|
1651
|
+
param.linearRampToValueAtTime(base + amount * rate * ADSR[2], start + Math.max((ADSR[0] + ADSR[1]) / 1000 * rate, dv));
|
|
1652
|
+
param.linearRampToValueAtTime(base, start + Math.max((ADSR[0] + ADSR[1]) / 1000 * rate, dv) + ADSR[3] / 1000);
|
|
1672
1653
|
}
|
|
1673
1654
|
function startEnvelope(param, base, amount, ADSR) {
|
|
1674
1655
|
param.value = base;
|
|
@@ -1710,12 +1691,6 @@
|
|
|
1710
1691
|
AnalogStick,
|
|
1711
1692
|
DirectionalPad,
|
|
1712
1693
|
};
|
|
1713
|
-
const audio = {
|
|
1714
|
-
master,
|
|
1715
|
-
context,
|
|
1716
|
-
synthesizer,
|
|
1717
|
-
load
|
|
1718
|
-
};
|
|
1719
1694
|
const xnew = Object.assign(xnew$1, {
|
|
1720
1695
|
basics,
|
|
1721
1696
|
audio
|