@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.
Files changed (37) hide show
  1. package/README.md +46 -46
  2. package/dist/types/audio/audio.d.ts +55 -2
  3. package/dist/types/audio/loader.d.ts +6 -2
  4. package/dist/types/basics/Event.d.ts +4 -3
  5. package/dist/types/basics/Touch.d.ts +9 -8
  6. package/dist/types/core/time.d.ts +6 -2
  7. package/dist/types/core/unit.d.ts +41 -10
  8. package/dist/types/core/xnew.d.ts +11 -21
  9. package/dist/types/index.d.ts +3 -12
  10. package/dist/xnew.d.ts +48 -63
  11. package/dist/xnew.js +375 -400
  12. package/dist/xnew.mjs +375 -400
  13. package/package.json +78 -78
  14. package/dist/addons/xmatter.d.ts +0 -6
  15. package/dist/addons/xmatter.js +0 -43
  16. package/dist/addons/xmatter.mjs +0 -38
  17. package/dist/addons/xpixi.d.ts +0 -10
  18. package/dist/addons/xpixi.js +0 -99
  19. package/dist/addons/xpixi.mjs +0 -75
  20. package/dist/addons/xrapier2d.d.ts +0 -6
  21. package/dist/addons/xrapier2d.js +0 -69
  22. package/dist/addons/xrapier2d.mjs +0 -64
  23. package/dist/addons/xthree.d.ts +0 -9
  24. package/dist/addons/xthree.js +0 -77
  25. package/dist/addons/xthree.mjs +0 -53
  26. package/dist/types/basics/Block.d.ts +0 -24
  27. package/dist/types/basics/Bullet.d.ts +0 -7
  28. package/dist/types/basics/ControlPanel.d.ts +0 -7
  29. package/dist/types/basics/Navigation.d.ts +0 -1
  30. package/dist/types/basics/Panel.d.ts +0 -6
  31. package/dist/types/basics/Popup.d.ts +0 -8
  32. package/dist/types/basics/TabView.d.ts +0 -18
  33. package/dist/types/basics/Tabs.d.ts +0 -8
  34. package/dist/types/basics/Transition.d.ts +0 -17
  35. package/dist/types/basics/WorkSpace.d.ts +0 -16
  36. package/dist/types/core/util.d.ts +0 -1
  37. 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
- // utils
99
+ // ticker
196
100
  //----------------------------------------------------------------------------------------------------
197
- const SYSTEM_EVENTS = ['start', 'update', 'stop', 'finalize'];
198
- class UnitPromise {
199
- constructor(promise) { this.promise = promise; }
200
- then(callback) {
201
- this.promise = this.promise.then(Unit.wrap(Unit.current, callback));
202
- return this;
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
- catch(callback) {
205
- this.promise = this.promise.catch(Unit.wrap(Unit.current, callback));
206
- return this;
117
+ clear() {
118
+ if (this.id !== null) {
119
+ cancelAnimationFrame(this.id);
120
+ this.id = null;
121
+ }
207
122
  }
208
- finally(callback) {
209
- this.promise = this.promise.finally(Unit.wrap(Unit.current, callback));
210
- return this;
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, target, component, props) {
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.componentUnits.delete(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.componentUnits.add(component, 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.componentUnits.get(component)) !== null && _a !== void 0 ? _a : [])];
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.typeUnits.add(type, this);
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.typeUnits.delete(type, this);
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.typeUnits.get(type)) === null || _a === void 0 ? void 0 : _a.forEach((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.componentUnits = new MapSet();
544
+ Unit.component2units = new MapSet();
529
545
  //----------------------------------------------------------------------------------------------------
530
546
  // event
531
547
  //----------------------------------------------------------------------------------------------------
532
- Unit.typeUnits = new MapSet();
533
-
534
- const xnew$1 = Object.assign(function (...args) {
535
- if (Unit.root === undefined) {
536
- Unit.reset();
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
- let target;
539
- if (args[0] instanceof HTMLElement || args[0] instanceof SVGElement) {
540
- target = args.shift(); // an existing html element
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
- else if (typeof args[0] === 'string') {
543
- const str = args.shift(); // a selector for an existing html element
544
- if (str.match(/<([^>]*)\/?>/)) {
545
- target = str;
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
- target = document.querySelector(str);
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
- else {
555
- target = null;
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, target, ...args);
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 callback - Function to execute after delay
754
- * @param delay - Delay in milliseconds
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(callback, delay) {
761
- const snapshot = Unit.snapshot(Unit.current);
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 callback - Function to execute at each interval
774
- * @param delay - Interval duration in milliseconds
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(callback, delay) {
781
- const snapshot = Unit.snapshot(Unit.current);
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(progress => {
798
- * element.style.opacity = progress
799
- * }, 500, 'ease-out').next(progress => {
800
- * element.style.transform = `scale(${progress})`
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(callback, interval, easing = 'linear') {
804
- const snapshot = Unit.snapshot(Unit.current);
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
- function load(path) {
1472
- return new AudioFile(path);
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 store = new Map();
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
- if (store.has(path)) {
1478
- this.buffer = store.get(path);
1479
- this.promise = Promise.resolve();
1480
- }
1481
- else {
1482
- this.promise = fetch(path)
1483
- .then((response) => response.arrayBuffer())
1484
- .then((response) => context.decodeAudioData(response))
1485
- .then((response) => {
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 freq = typeof frequency === 'string' ? keymap[frequency] : frequency;
1564
- const dura = typeof duration === 'string' ? (notemap[duration] * 60 / ((_a = props.bpm) !== null && _a !== void 0 ? _a : 120)) : (typeof duration === 'number' ? (duration / 1000) : 0);
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 = freq;
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 = freq * (Math.pow(2.0, props.oscillator.LFO.amount / 12.0) - 1.0);
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 && props.filter.type && props.filter.cutoff) {
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 = freq * (Math.pow(2.0, props.oscillator.envelope.amount / 12.0) - 1.0);
1609
- startEnvelope(nodes.oscillator.frequency, freq, amount, props.oscillator.envelope.ADSR);
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 (dura > 0) {
1596
+ if (dv > 0) {
1617
1597
  release();
1618
1598
  }
1619
1599
  else {
1620
1600
  return { release };
1621
1601
  }
1622
1602
  function release() {
1623
- const end = dura > 0 ? dura : (context.currentTime - start);
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 = freq * (Math.pow(2.0, props.oscillator.envelope.amount / 12.0) - 1.0);
1638
- stopEnvelope(nodes.oscillator.frequency, freq, amount, props.oscillator.envelope.ADSR);
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(dura / (ADSR[0] / 1000), 1.0);
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, dura));
1665
- param.linearRampToValueAtTime(base, start + Math.max((ADSR[0] + ADSR[1]) / 1000 * rate, dura) + ADSR[3] / 1000);
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