@mulsense/xnew 0.1.9 → 0.1.11
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/dist/types/basics/Event.d.ts +4 -3
- package/dist/types/core/time.d.ts +6 -2
- package/dist/types/core/unit.d.ts +45 -10
- package/dist/types/core/xnew.d.ts +12 -22
- package/dist/types/index.d.ts +2 -6
- package/dist/xnew.d.ts +48 -58
- package/dist/xnew.js +308 -349
- package/dist/xnew.mjs +308 -349
- package/package.json +1 -1
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,24 +96,117 @@ class MapMap extends Map {
|
|
|
192
96
|
}
|
|
193
97
|
|
|
194
98
|
//----------------------------------------------------------------------------------------------------
|
|
195
|
-
//
|
|
99
|
+
// ticker
|
|
196
100
|
//----------------------------------------------------------------------------------------------------
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
|
|
101
|
+
class Ticker {
|
|
102
|
+
constructor(callback) {
|
|
103
|
+
const self = this;
|
|
104
|
+
this.id = null;
|
|
105
|
+
let previous = 0;
|
|
106
|
+
ticker();
|
|
107
|
+
function ticker() {
|
|
108
|
+
const time = Date.now();
|
|
109
|
+
const fps = 60;
|
|
110
|
+
if (time - previous > (1000 / fps) * 0.9) {
|
|
111
|
+
callback(time);
|
|
112
|
+
previous = time;
|
|
113
|
+
}
|
|
114
|
+
self.id = requestAnimationFrame(ticker);
|
|
115
|
+
}
|
|
203
116
|
}
|
|
204
|
-
|
|
205
|
-
this.
|
|
206
|
-
|
|
117
|
+
clear() {
|
|
118
|
+
if (this.id !== null) {
|
|
119
|
+
cancelAnimationFrame(this.id);
|
|
120
|
+
this.id = null;
|
|
121
|
+
}
|
|
207
122
|
}
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
|
|
123
|
+
}
|
|
124
|
+
//----------------------------------------------------------------------------------------------------
|
|
125
|
+
// timer
|
|
126
|
+
//----------------------------------------------------------------------------------------------------
|
|
127
|
+
class Timer {
|
|
128
|
+
constructor(transition, timeout, duration, { loop = false, easing = 'linear' } = {}) {
|
|
129
|
+
var _a;
|
|
130
|
+
this.transition = transition;
|
|
131
|
+
this.timeout = timeout;
|
|
132
|
+
this.duration = duration !== null && duration !== void 0 ? duration : 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.duration, 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.duration > 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.duration - 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
|
//----------------------------------------------------------------------------------------------------
|
|
@@ -301,7 +298,6 @@ class Unit {
|
|
|
301
298
|
children: [],
|
|
302
299
|
elements: [],
|
|
303
300
|
promises: [],
|
|
304
|
-
captures: [],
|
|
305
301
|
components: [],
|
|
306
302
|
listeners1: new MapMap(),
|
|
307
303
|
listeners2: new MapMap(),
|
|
@@ -316,11 +312,6 @@ class Unit {
|
|
|
316
312
|
Unit.extend(unit, unit._.baseComponent, unit._.props);
|
|
317
313
|
// whether the unit promise was resolved
|
|
318
314
|
Promise.all(unit._.promises).then(() => unit._.state = 'initialized');
|
|
319
|
-
// setup capture
|
|
320
|
-
for (let current = unit; current !== null; current = current._.parent) {
|
|
321
|
-
if (current._.captures.find((capture) => capture(unit)) !== undefined)
|
|
322
|
-
break;
|
|
323
|
-
}
|
|
324
315
|
Unit.current = backup;
|
|
325
316
|
}
|
|
326
317
|
static finalize(unit) {
|
|
@@ -468,15 +459,13 @@ class Unit {
|
|
|
468
459
|
return [...((_a = Unit.component2units.get(component)) !== null && _a !== void 0 ? _a : [])];
|
|
469
460
|
}
|
|
470
461
|
on(type, listener, options) {
|
|
471
|
-
if (this._.state === 'finalized')
|
|
472
|
-
return;
|
|
473
462
|
type.trim().split(/\s+/).forEach((type) => {
|
|
474
463
|
if (SYSTEM_EVENTS.includes(type)) {
|
|
475
464
|
this._.systems[type].push(listener);
|
|
476
465
|
}
|
|
477
466
|
if (this._.listeners1.has(type, listener) === false) {
|
|
478
467
|
const execute = Unit.wrap(Unit.current, listener);
|
|
479
|
-
this._.listeners1.set(type, listener,
|
|
468
|
+
this._.listeners1.set(type, listener, { element: this.element, execute });
|
|
480
469
|
Unit.type2units.add(type, this);
|
|
481
470
|
if (/^[A-Za-z]/.test(type)) {
|
|
482
471
|
this.element.addEventListener(type, execute, options);
|
|
@@ -490,13 +479,12 @@ class Unit {
|
|
|
490
479
|
if (SYSTEM_EVENTS.includes(type)) {
|
|
491
480
|
this._.systems[type] = this._.systems[type].filter((lis) => listener ? lis !== listener : false);
|
|
492
481
|
}
|
|
493
|
-
(listener ? [listener] : [...this._.listeners1.keys(type)]).forEach((
|
|
494
|
-
const
|
|
495
|
-
if (
|
|
496
|
-
|
|
497
|
-
this._.listeners1.delete(type, lis);
|
|
482
|
+
(listener ? [listener] : [...this._.listeners1.keys(type)]).forEach((listener) => {
|
|
483
|
+
const item = this._.listeners1.get(type, listener);
|
|
484
|
+
if (item !== undefined) {
|
|
485
|
+
this._.listeners1.delete(type, listener);
|
|
498
486
|
if (/^[A-Za-z]/.test(type)) {
|
|
499
|
-
|
|
487
|
+
item.element.removeEventListener(type, item.execute);
|
|
500
488
|
}
|
|
501
489
|
}
|
|
502
490
|
});
|
|
@@ -507,23 +495,21 @@ class Unit {
|
|
|
507
495
|
}
|
|
508
496
|
emit(type, ...args) {
|
|
509
497
|
var _a, _b;
|
|
510
|
-
if (this._.state === 'finalized')
|
|
511
|
-
return;
|
|
512
498
|
if (type[0] === '+') {
|
|
513
499
|
(_a = Unit.type2units.get(type)) === null || _a === void 0 ? void 0 : _a.forEach((unit) => {
|
|
514
500
|
var _a;
|
|
515
|
-
(_a = unit._.listeners1.get(type)) === null || _a === void 0 ? void 0 : _a.forEach((
|
|
501
|
+
(_a = unit._.listeners1.get(type)) === null || _a === void 0 ? void 0 : _a.forEach((item) => item.execute(...args));
|
|
516
502
|
});
|
|
517
503
|
}
|
|
518
504
|
else if (type[0] === '-') {
|
|
519
|
-
(_b = this._.listeners1.get(type)) === null || _b === void 0 ? void 0 : _b.forEach((
|
|
505
|
+
(_b = this._.listeners1.get(type)) === null || _b === void 0 ? void 0 : _b.forEach((item) => item.execute(...args));
|
|
520
506
|
}
|
|
521
507
|
}
|
|
522
508
|
static subon(unit, target, type, listener, options) {
|
|
523
509
|
type.trim().split(/\s+/).forEach((type) => {
|
|
524
510
|
if (unit._.listeners2.has(type, listener) === false) {
|
|
525
511
|
const execute = Unit.wrap(unit, listener);
|
|
526
|
-
unit._.listeners2.set(type, listener,
|
|
512
|
+
unit._.listeners2.set(type, listener, { element: target, execute });
|
|
527
513
|
target.addEventListener(type, execute, options);
|
|
528
514
|
}
|
|
529
515
|
});
|
|
@@ -531,14 +517,11 @@ class Unit {
|
|
|
531
517
|
static suboff(unit, target, type, listener) {
|
|
532
518
|
const types = typeof type === 'string' ? type.trim().split(/\s+/) : [...unit._.listeners2.keys()];
|
|
533
519
|
types.forEach((type) => {
|
|
534
|
-
(listener ? [listener] : [...unit._.listeners2.keys(type)]).forEach((
|
|
535
|
-
const
|
|
536
|
-
if (
|
|
537
|
-
|
|
538
|
-
|
|
539
|
-
unit._.listeners2.delete(type, lis);
|
|
540
|
-
element.removeEventListener(type, execute);
|
|
541
|
-
}
|
|
520
|
+
(listener ? [listener] : [...unit._.listeners2.keys(type)]).forEach((listener) => {
|
|
521
|
+
const item = unit._.listeners2.get(type, listener);
|
|
522
|
+
if (item !== undefined && (target === null || target === item.element)) {
|
|
523
|
+
unit._.listeners2.delete(type, listener);
|
|
524
|
+
item.element.removeEventListener(type, item.execute);
|
|
542
525
|
}
|
|
543
526
|
});
|
|
544
527
|
});
|
|
@@ -549,6 +532,78 @@ Unit.component2units = new MapSet();
|
|
|
549
532
|
// event
|
|
550
533
|
//----------------------------------------------------------------------------------------------------
|
|
551
534
|
Unit.type2units = new MapSet();
|
|
535
|
+
//----------------------------------------------------------------------------------------------------
|
|
536
|
+
// unit promise
|
|
537
|
+
//----------------------------------------------------------------------------------------------------
|
|
538
|
+
class UnitPromise {
|
|
539
|
+
constructor(promise) { this.promise = promise; }
|
|
540
|
+
then(callback) {
|
|
541
|
+
this.promise = this.promise.then(Unit.wrap(Unit.current, callback));
|
|
542
|
+
return this;
|
|
543
|
+
}
|
|
544
|
+
catch(callback) {
|
|
545
|
+
this.promise = this.promise.catch(Unit.wrap(Unit.current, callback));
|
|
546
|
+
return this;
|
|
547
|
+
}
|
|
548
|
+
finally(callback) {
|
|
549
|
+
this.promise = this.promise.finally(Unit.wrap(Unit.current, callback));
|
|
550
|
+
return this;
|
|
551
|
+
}
|
|
552
|
+
}
|
|
553
|
+
//----------------------------------------------------------------------------------------------------
|
|
554
|
+
// unit timer
|
|
555
|
+
//----------------------------------------------------------------------------------------------------
|
|
556
|
+
class UnitTimer {
|
|
557
|
+
constructor({ transition, timeout, duration, easing, loop }) {
|
|
558
|
+
this.stack = [];
|
|
559
|
+
this.unit = new Unit(Unit.current, UnitTimer.Component, { snapshot: Unit.snapshot(Unit.current), transition, timeout, duration, easing, loop });
|
|
560
|
+
}
|
|
561
|
+
clear() {
|
|
562
|
+
this.stack = [];
|
|
563
|
+
this.unit.finalize();
|
|
564
|
+
}
|
|
565
|
+
timeout(timeout, duration = 0) {
|
|
566
|
+
UnitTimer.execute(this, { timeout, duration });
|
|
567
|
+
return this;
|
|
568
|
+
}
|
|
569
|
+
transition(transition, duration = 0, easing = 'linear') {
|
|
570
|
+
UnitTimer.execute(this, { transition, duration, easing });
|
|
571
|
+
return this;
|
|
572
|
+
}
|
|
573
|
+
static execute(timer, { transition, timeout, duration, easing, loop }) {
|
|
574
|
+
if (timer.unit._.state === 'finalized') {
|
|
575
|
+
timer.unit = new Unit(Unit.current, UnitTimer.Component, { snapshot: Unit.snapshot(Unit.current), transition, timeout, duration, easing, loop });
|
|
576
|
+
}
|
|
577
|
+
else if (timer.stack.length === 0) {
|
|
578
|
+
timer.stack.push({ snapshot: Unit.snapshot(Unit.current), transition, timeout, duration, easing, loop });
|
|
579
|
+
timer.unit.on('finalize', () => { UnitTimer.next(timer); });
|
|
580
|
+
}
|
|
581
|
+
else {
|
|
582
|
+
timer.stack.push({ snapshot: Unit.snapshot(Unit.current), transition, timeout, duration, easing, loop });
|
|
583
|
+
}
|
|
584
|
+
}
|
|
585
|
+
static next(timer) {
|
|
586
|
+
if (timer.stack.length > 0) {
|
|
587
|
+
timer.unit = new Unit(Unit.current, UnitTimer.Component, timer.stack.shift());
|
|
588
|
+
timer.unit.on('finalize', () => { UnitTimer.next(timer); });
|
|
589
|
+
}
|
|
590
|
+
}
|
|
591
|
+
static Component(unit, { snapshot, transition, timeout, duration, loop, easing }) {
|
|
592
|
+
const timer = new Timer((x) => {
|
|
593
|
+
if (transition !== undefined)
|
|
594
|
+
Unit.scope(snapshot, transition, x);
|
|
595
|
+
}, () => {
|
|
596
|
+
if (transition !== undefined)
|
|
597
|
+
Unit.scope(snapshot, transition, 1.0);
|
|
598
|
+
if (timeout !== undefined)
|
|
599
|
+
Unit.scope(snapshot, timeout);
|
|
600
|
+
if (loop === false) {
|
|
601
|
+
unit.finalize();
|
|
602
|
+
}
|
|
603
|
+
}, duration, { loop, easing });
|
|
604
|
+
unit.on('finalize', () => timer.clear());
|
|
605
|
+
}
|
|
606
|
+
}
|
|
552
607
|
|
|
553
608
|
const xnew$1 = Object.assign(function (...args) {
|
|
554
609
|
if (Unit.root === undefined) {
|
|
@@ -729,105 +784,43 @@ const xnew$1 = Object.assign(function (...args) {
|
|
|
729
784
|
},
|
|
730
785
|
/**
|
|
731
786
|
* Executes a callback once after a delay, managed by component lifecycle
|
|
732
|
-
* @param
|
|
733
|
-
* @param
|
|
787
|
+
* @param timeout - Function to execute after Duration
|
|
788
|
+
* @param duration - Duration in milliseconds
|
|
734
789
|
* @returns Object with clear() method to cancel the timeout
|
|
735
790
|
* @example
|
|
736
791
|
* const timer = xnew.timeout(() => console.log('Delayed'), 1000)
|
|
737
792
|
* // Cancel if needed: timer.clear()
|
|
738
793
|
*/
|
|
739
|
-
timeout(
|
|
740
|
-
|
|
741
|
-
const unit = xnew$1((self) => {
|
|
742
|
-
const timer = new Timer(() => {
|
|
743
|
-
Unit.scope(snapshot, callback);
|
|
744
|
-
self.finalize();
|
|
745
|
-
}, null, delay, false);
|
|
746
|
-
self.on('finalize', () => timer.clear());
|
|
747
|
-
});
|
|
748
|
-
return { clear: () => unit.finalize() };
|
|
794
|
+
timeout(timeout, duration = 0) {
|
|
795
|
+
return new UnitTimer({ timeout, duration });
|
|
749
796
|
},
|
|
750
797
|
/**
|
|
751
798
|
* Executes a callback repeatedly at specified intervals, managed by component lifecycle
|
|
752
|
-
* @param
|
|
753
|
-
* @param
|
|
799
|
+
* @param timeout - Function to execute at each duration
|
|
800
|
+
* @param duration - Duration in milliseconds
|
|
754
801
|
* @returns Object with clear() method to stop the interval
|
|
755
802
|
* @example
|
|
756
803
|
* const timer = xnew.interval(() => console.log('Tick'), 1000)
|
|
757
804
|
* // Stop when needed: timer.clear()
|
|
758
805
|
*/
|
|
759
|
-
interval(
|
|
760
|
-
|
|
761
|
-
const unit = xnew$1((self) => {
|
|
762
|
-
const timer = new Timer(() => {
|
|
763
|
-
Unit.scope(snapshot, callback);
|
|
764
|
-
}, null, delay, true);
|
|
765
|
-
self.on('finalize', () => timer.clear());
|
|
766
|
-
});
|
|
767
|
-
return { clear: () => unit.finalize() };
|
|
806
|
+
interval(timeout, duration) {
|
|
807
|
+
return new UnitTimer({ timeout, duration, loop: true });
|
|
768
808
|
},
|
|
769
809
|
/**
|
|
770
810
|
* Creates a transition animation with easing, executing callback with progress values
|
|
771
811
|
* @param callback - Function called with progress value (0.0 to 1.0)
|
|
772
|
-
* @param
|
|
812
|
+
* @param duration - Duration of transition in milliseconds
|
|
773
813
|
* @param easing - Easing function: 'linear', 'ease', 'ease-in', 'ease-out', 'ease-in-out' (default: 'linear')
|
|
774
814
|
* @returns Object with clear() and next() methods for controlling transitions
|
|
775
815
|
* @example
|
|
776
|
-
* xnew.transition(
|
|
777
|
-
* element.style.opacity =
|
|
778
|
-
* }, 500, 'ease-out').
|
|
779
|
-
* element.style.transform = `scale(${
|
|
816
|
+
* xnew.transition(p => {
|
|
817
|
+
* element.style.opacity = p
|
|
818
|
+
* }, 500, 'ease-out').transition(p => {
|
|
819
|
+
* element.style.transform = `scale(${p})`
|
|
780
820
|
* }, 300)
|
|
781
821
|
*/
|
|
782
|
-
transition(
|
|
783
|
-
|
|
784
|
-
let stacks = [];
|
|
785
|
-
let unit = xnew$1(Local, { callback, interval, easing });
|
|
786
|
-
let isRunning = true;
|
|
787
|
-
const timer = { clear, next };
|
|
788
|
-
return timer;
|
|
789
|
-
function execute() {
|
|
790
|
-
if (isRunning === false && stacks.length > 0) {
|
|
791
|
-
unit = xnew$1(Local, stacks.shift());
|
|
792
|
-
isRunning = true;
|
|
793
|
-
}
|
|
794
|
-
}
|
|
795
|
-
function clear() {
|
|
796
|
-
stacks = [];
|
|
797
|
-
unit.finalize();
|
|
798
|
-
}
|
|
799
|
-
function next(callback, interval = 0, easing = 'linear') {
|
|
800
|
-
stacks.push({ callback, interval, easing });
|
|
801
|
-
execute();
|
|
802
|
-
return timer;
|
|
803
|
-
}
|
|
804
|
-
function Local(self, { callback, interval, easing }) {
|
|
805
|
-
const timer = new Timer(() => {
|
|
806
|
-
Unit.scope(snapshot, callback, 1.0);
|
|
807
|
-
self.finalize();
|
|
808
|
-
}, (x) => {
|
|
809
|
-
if (x < 1.0) {
|
|
810
|
-
if (easing === 'ease-out') {
|
|
811
|
-
x = Math.pow((1.0 - Math.pow((1.0 - x), 2.0)), 0.5);
|
|
812
|
-
}
|
|
813
|
-
else if (easing === 'ease-in') {
|
|
814
|
-
x = Math.pow((1.0 - Math.pow((1.0 - x), 0.5)), 2.0);
|
|
815
|
-
}
|
|
816
|
-
else if (easing === 'ease') {
|
|
817
|
-
x = (1.0 - Math.cos(x * Math.PI)) / 2.0;
|
|
818
|
-
}
|
|
819
|
-
else if (easing === 'ease-in-out') {
|
|
820
|
-
x = (1.0 - Math.cos(x * Math.PI)) / 2.0;
|
|
821
|
-
}
|
|
822
|
-
Unit.scope(snapshot, callback, x);
|
|
823
|
-
}
|
|
824
|
-
}, interval);
|
|
825
|
-
self.on('finalize', () => {
|
|
826
|
-
timer.clear();
|
|
827
|
-
isRunning = false;
|
|
828
|
-
execute();
|
|
829
|
-
});
|
|
830
|
-
}
|
|
822
|
+
transition(transition, duration = 0, easing = 'linear') {
|
|
823
|
+
return new UnitTimer({ transition, duration, easing });
|
|
831
824
|
},
|
|
832
825
|
/**
|
|
833
826
|
* Creates an event listener manager for a target element with automatic cleanup
|
|
@@ -848,20 +841,86 @@ const xnew$1 = Object.assign(function (...args) {
|
|
|
848
841
|
}
|
|
849
842
|
};
|
|
850
843
|
},
|
|
851
|
-
/**
|
|
852
|
-
* Registers a capture function that can intercept and handle child component events
|
|
853
|
-
* @param execute - Function that receives child unit and returns boolean (true to stop propagation)
|
|
854
|
-
* @example
|
|
855
|
-
* xnew.capture((childUnit) => {
|
|
856
|
-
* console.log('Child component created:', childUnit)
|
|
857
|
-
* return false // Continue propagation
|
|
858
|
-
* })
|
|
859
|
-
*/
|
|
860
|
-
capture(execute) {
|
|
861
|
-
Unit.current._.captures.push(Unit.wrap(Unit.current, (unit) => execute(unit)));
|
|
862
|
-
},
|
|
863
844
|
});
|
|
864
845
|
|
|
846
|
+
function AccordionFrame(frame, { open = false, duration = 200, easing = 'ease' } = {}) {
|
|
847
|
+
const internal = xnew$1((internal) => {
|
|
848
|
+
return { frame, open, rate: 0.0, };
|
|
849
|
+
});
|
|
850
|
+
xnew$1.context('xnew.accordionframe', internal);
|
|
851
|
+
internal.on('-transition', ({ rate }) => internal.rate = rate);
|
|
852
|
+
internal.emit('-transition', { rate: open ? 1.0 : 0.0 });
|
|
853
|
+
return {
|
|
854
|
+
toggle() {
|
|
855
|
+
if (internal.rate === 1.0) {
|
|
856
|
+
frame.close();
|
|
857
|
+
}
|
|
858
|
+
else if (internal.rate === 0.0) {
|
|
859
|
+
frame.open();
|
|
860
|
+
}
|
|
861
|
+
},
|
|
862
|
+
open() {
|
|
863
|
+
if (internal.rate === 0.0) {
|
|
864
|
+
xnew$1.transition((x) => internal.emit('-transition', { rate: x }), duration, easing);
|
|
865
|
+
}
|
|
866
|
+
},
|
|
867
|
+
close() {
|
|
868
|
+
if (internal.rate === 1.0) {
|
|
869
|
+
xnew$1.transition((x) => internal.emit('-transition', { rate: 1.0 - x }), duration, easing);
|
|
870
|
+
}
|
|
871
|
+
}
|
|
872
|
+
};
|
|
873
|
+
}
|
|
874
|
+
function AccordionHeader(header, {} = {}) {
|
|
875
|
+
const internal = xnew$1.context('xnew.accordionframe');
|
|
876
|
+
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;">');
|
|
877
|
+
header.on('click', () => internal.frame.toggle());
|
|
878
|
+
}
|
|
879
|
+
function AccordionBullet(bullet, { type = 'arrow' } = {}) {
|
|
880
|
+
const internal = xnew$1.context('xnew.accordionframe');
|
|
881
|
+
xnew$1.nest('<div style="display:inline-block; position: relative; width: 0.55em; margin: 0 0.3em;">');
|
|
882
|
+
if (type === 'arrow') {
|
|
883
|
+
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;">`);
|
|
884
|
+
arrow.element.style.transform = `rotate(${internal.rate * 90 - 45}deg)`;
|
|
885
|
+
internal.on('-transition', ({ rate }) => {
|
|
886
|
+
arrow.element.style.transform = `rotate(${rate * 90 - 45}deg)`;
|
|
887
|
+
});
|
|
888
|
+
}
|
|
889
|
+
else if (type === 'plusminus') {
|
|
890
|
+
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;">`);
|
|
891
|
+
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;">`);
|
|
892
|
+
line2.element.style.transform = `rotate(90deg)`;
|
|
893
|
+
line2.element.style.opacity = `${1.0 - internal.rate}`;
|
|
894
|
+
internal.on('-transition', ({ rate }) => {
|
|
895
|
+
line1.element.style.transform = `rotate(${90 + rate * 90}deg)`;
|
|
896
|
+
line2.element.style.transform = `rotate(${rate * 180}deg)`;
|
|
897
|
+
});
|
|
898
|
+
}
|
|
899
|
+
}
|
|
900
|
+
function AccordionContent(content, {} = {}) {
|
|
901
|
+
const internal = xnew$1.context('xnew.accordionframe');
|
|
902
|
+
xnew$1.nest(`<div style="display: ${internal.open ? 'block' : 'none'};">`);
|
|
903
|
+
xnew$1.nest('<div style="padding: 0; display: flex; flex-direction: column; box-sizing: border-box;">');
|
|
904
|
+
internal.on('-transition', ({ rate }) => {
|
|
905
|
+
content.transition({ element: content.element, rate });
|
|
906
|
+
});
|
|
907
|
+
return {
|
|
908
|
+
transition({ element, rate }) {
|
|
909
|
+
const wrapper = element.parentElement;
|
|
910
|
+
wrapper.style.display = 'block';
|
|
911
|
+
if (rate === 0.0) {
|
|
912
|
+
wrapper.style.display = 'none';
|
|
913
|
+
}
|
|
914
|
+
else if (rate < 1.0) {
|
|
915
|
+
Object.assign(wrapper.style, { height: element.offsetHeight * rate + 'px', overflow: 'hidden', opacity: rate });
|
|
916
|
+
}
|
|
917
|
+
else {
|
|
918
|
+
Object.assign(wrapper.style, { height: 'auto', overflow: 'visible', opacity: 1.0 });
|
|
919
|
+
}
|
|
920
|
+
}
|
|
921
|
+
};
|
|
922
|
+
}
|
|
923
|
+
|
|
865
924
|
function ResizeEvent(resize) {
|
|
866
925
|
const observer = new ResizeObserver((entries) => {
|
|
867
926
|
for (const entry of entries) {
|
|
@@ -878,7 +937,29 @@ function ResizeEvent(resize) {
|
|
|
878
937
|
}
|
|
879
938
|
});
|
|
880
939
|
}
|
|
881
|
-
|
|
940
|
+
function KeyboardEvent(unit) {
|
|
941
|
+
const state = {};
|
|
942
|
+
xnew$1.listener(window).on('keydown', (event) => {
|
|
943
|
+
state[event.code] = 1;
|
|
944
|
+
unit.emit('-keydown', { event, type: '-keydown', code: event.code });
|
|
945
|
+
});
|
|
946
|
+
xnew$1.listener(window).on('keyup', (event) => {
|
|
947
|
+
state[event.code] = 0;
|
|
948
|
+
unit.emit('-keyup', { event, type: '-keyup', code: event.code });
|
|
949
|
+
});
|
|
950
|
+
xnew$1.listener(window).on('keydown', (event) => {
|
|
951
|
+
unit.emit('-arrowkeydown', { event, type: '-arrowkeydown', code: event.code, vector: getVector() });
|
|
952
|
+
});
|
|
953
|
+
xnew$1.listener(window).on('keyup', (event) => {
|
|
954
|
+
unit.emit('-arrowkeyup', { event, type: '-arrowkeyup', code: event.code, vector: getVector() });
|
|
955
|
+
});
|
|
956
|
+
function getVector() {
|
|
957
|
+
return {
|
|
958
|
+
x: (state['ArrowLeft'] ? -1 : 0) + (state['ArrowRight'] ? +1 : 0),
|
|
959
|
+
y: (state['ArrowUp'] ? -1 : 0) + (state['ArrowDown'] ? +1 : 0)
|
|
960
|
+
};
|
|
961
|
+
}
|
|
962
|
+
}
|
|
882
963
|
function PointerEvent(unit) {
|
|
883
964
|
const internal = xnew$1();
|
|
884
965
|
internal.on('pointerdown', (event) => unit.emit('-pointerdown', { event, position: getPosition(unit.element, event) }));
|
|
@@ -995,30 +1076,6 @@ function getPosition(element, event) {
|
|
|
995
1076
|
return { x: event.clientX - rect.left, y: event.clientY - rect.top };
|
|
996
1077
|
}
|
|
997
1078
|
|
|
998
|
-
function KeyboardEvent(unit) {
|
|
999
|
-
const state = {};
|
|
1000
|
-
xnew$1.listener(window).on('keydown', (event) => {
|
|
1001
|
-
state[event.code] = 1;
|
|
1002
|
-
unit.emit('-keydown', { event, type: '-keydown', code: event.code });
|
|
1003
|
-
});
|
|
1004
|
-
xnew$1.listener(window).on('keyup', (event) => {
|
|
1005
|
-
state[event.code] = 0;
|
|
1006
|
-
unit.emit('-keyup', { event, type: '-keyup', code: event.code });
|
|
1007
|
-
});
|
|
1008
|
-
xnew$1.listener(window).on('keydown', (event) => {
|
|
1009
|
-
unit.emit('-arrowkeydown', { event, type: '-arrowkeydown', code: event.code, vector: getVector() });
|
|
1010
|
-
});
|
|
1011
|
-
xnew$1.listener(window).on('keyup', (event) => {
|
|
1012
|
-
unit.emit('-arrowkeyup', { event, type: '-arrowkeyup', code: event.code, vector: getVector() });
|
|
1013
|
-
});
|
|
1014
|
-
function getVector() {
|
|
1015
|
-
return {
|
|
1016
|
-
x: (state['ArrowLeft'] ? -1 : 0) + (state['ArrowRight'] ? +1 : 0),
|
|
1017
|
-
y: (state['ArrowUp'] ? -1 : 0) + (state['ArrowDown'] ? +1 : 0)
|
|
1018
|
-
};
|
|
1019
|
-
}
|
|
1020
|
-
}
|
|
1021
|
-
|
|
1022
1079
|
function Screen(screen, { width = 640, height = 480, fit = 'contain' } = {}) {
|
|
1023
1080
|
const size = { width, height };
|
|
1024
1081
|
const wrapper = xnew$1.nest('<div style="position: relative; width: 100%; height: 100%; overflow: hidden;">');
|
|
@@ -1066,25 +1123,6 @@ function Screen(screen, { width = 640, height = 480, fit = 'contain' } = {}) {
|
|
|
1066
1123
|
};
|
|
1067
1124
|
}
|
|
1068
1125
|
|
|
1069
|
-
function InputFrame(frame, {} = {}) {
|
|
1070
|
-
xnew$1.nest('<div>');
|
|
1071
|
-
xnew$1.capture((unit) => {
|
|
1072
|
-
if (unit.element.tagName.toLowerCase() === 'input') {
|
|
1073
|
-
const element = unit.element;
|
|
1074
|
-
xnew$1.listener(element).on('input', (event) => {
|
|
1075
|
-
frame.emit('-input', { event });
|
|
1076
|
-
});
|
|
1077
|
-
xnew$1.listener(element).on('change', (event) => {
|
|
1078
|
-
frame.emit('-change', { event });
|
|
1079
|
-
});
|
|
1080
|
-
xnew$1.listener(element).on('click', (event) => {
|
|
1081
|
-
frame.emit('-click', { event });
|
|
1082
|
-
});
|
|
1083
|
-
return true;
|
|
1084
|
-
}
|
|
1085
|
-
});
|
|
1086
|
-
}
|
|
1087
|
-
|
|
1088
1126
|
function ModalFrame(frame, { duration = 200, easing = 'ease' } = {}) {
|
|
1089
1127
|
const internal = xnew$1((internal) => {
|
|
1090
1128
|
return {};
|
|
@@ -1175,84 +1213,6 @@ function TabContent(content, { key } = {}) {
|
|
|
1175
1213
|
};
|
|
1176
1214
|
}
|
|
1177
1215
|
|
|
1178
|
-
function AccordionFrame(frame, { open = false, duration = 200, easing = 'ease' } = {}) {
|
|
1179
|
-
const internal = xnew$1((internal) => {
|
|
1180
|
-
return { frame, open, rate: 0.0, };
|
|
1181
|
-
});
|
|
1182
|
-
xnew$1.context('xnew.accordionframe', internal);
|
|
1183
|
-
internal.on('-transition', ({ rate }) => internal.rate = rate);
|
|
1184
|
-
internal.emit('-transition', { rate: open ? 1.0 : 0.0 });
|
|
1185
|
-
return {
|
|
1186
|
-
toggle() {
|
|
1187
|
-
if (internal.rate === 1.0) {
|
|
1188
|
-
frame.close();
|
|
1189
|
-
}
|
|
1190
|
-
else if (internal.rate === 0.0) {
|
|
1191
|
-
frame.open();
|
|
1192
|
-
}
|
|
1193
|
-
},
|
|
1194
|
-
open() {
|
|
1195
|
-
if (internal.rate === 0.0) {
|
|
1196
|
-
xnew$1.transition((x) => internal.emit('-transition', { rate: x }), duration, easing);
|
|
1197
|
-
}
|
|
1198
|
-
},
|
|
1199
|
-
close() {
|
|
1200
|
-
if (internal.rate === 1.0) {
|
|
1201
|
-
xnew$1.transition((x) => internal.emit('-transition', { rate: 1.0 - x }), duration, easing);
|
|
1202
|
-
}
|
|
1203
|
-
}
|
|
1204
|
-
};
|
|
1205
|
-
}
|
|
1206
|
-
function AccordionHeader(header, {} = {}) {
|
|
1207
|
-
const internal = xnew$1.context('xnew.accordionframe');
|
|
1208
|
-
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;">');
|
|
1209
|
-
header.on('click', () => internal.frame.toggle());
|
|
1210
|
-
}
|
|
1211
|
-
function AccordionBullet(bullet, { type = 'arrow' } = {}) {
|
|
1212
|
-
const internal = xnew$1.context('xnew.accordionframe');
|
|
1213
|
-
xnew$1.nest('<div style="display:inline-block; position: relative; width: 0.55em; margin: 0 0.3em;">');
|
|
1214
|
-
if (type === 'arrow') {
|
|
1215
|
-
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;">`);
|
|
1216
|
-
arrow.element.style.transform = `rotate(${internal.rate * 90 - 45}deg)`;
|
|
1217
|
-
internal.on('-transition', ({ rate }) => {
|
|
1218
|
-
arrow.element.style.transform = `rotate(${rate * 90 - 45}deg)`;
|
|
1219
|
-
});
|
|
1220
|
-
}
|
|
1221
|
-
else if (type === 'plusminus') {
|
|
1222
|
-
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;">`);
|
|
1223
|
-
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;">`);
|
|
1224
|
-
line2.element.style.transform = `rotate(90deg)`;
|
|
1225
|
-
line2.element.style.opacity = `${1.0 - internal.rate}`;
|
|
1226
|
-
internal.on('-transition', ({ rate }) => {
|
|
1227
|
-
line1.element.style.transform = `rotate(${90 + rate * 90}deg)`;
|
|
1228
|
-
line2.element.style.transform = `rotate(${rate * 180}deg)`;
|
|
1229
|
-
});
|
|
1230
|
-
}
|
|
1231
|
-
}
|
|
1232
|
-
function AccordionContent(content, {} = {}) {
|
|
1233
|
-
const internal = xnew$1.context('xnew.accordionframe');
|
|
1234
|
-
xnew$1.nest(`<div style="display: ${internal.open ? 'block' : 'none'};">`);
|
|
1235
|
-
xnew$1.nest('<div style="padding: 0; display: flex; flex-direction: column; box-sizing: border-box;">');
|
|
1236
|
-
internal.on('-transition', ({ rate }) => {
|
|
1237
|
-
content.transition({ element: content.element, rate });
|
|
1238
|
-
});
|
|
1239
|
-
return {
|
|
1240
|
-
transition({ element, rate }) {
|
|
1241
|
-
const wrapper = element.parentElement;
|
|
1242
|
-
wrapper.style.display = 'block';
|
|
1243
|
-
if (rate === 0.0) {
|
|
1244
|
-
wrapper.style.display = 'none';
|
|
1245
|
-
}
|
|
1246
|
-
else if (rate < 1.0) {
|
|
1247
|
-
Object.assign(wrapper.style, { height: element.offsetHeight * rate + 'px', overflow: 'hidden', opacity: rate });
|
|
1248
|
-
}
|
|
1249
|
-
else {
|
|
1250
|
-
Object.assign(wrapper.style, { height: 'auto', overflow: 'visible', opacity: 1.0 });
|
|
1251
|
-
}
|
|
1252
|
-
}
|
|
1253
|
-
};
|
|
1254
|
-
}
|
|
1255
|
-
|
|
1256
1216
|
function DragFrame(frame, { x = 0, y = 0 } = {}) {
|
|
1257
1217
|
const absolute = xnew$1.nest(`<div style="position: absolute; top: ${y}px; left: ${x}px;">`);
|
|
1258
1218
|
xnew$1.context('xnew.dragframe', { frame, absolute });
|
|
@@ -1676,7 +1636,6 @@ const basics = {
|
|
|
1676
1636
|
TabFrame,
|
|
1677
1637
|
TabButton,
|
|
1678
1638
|
TabContent,
|
|
1679
|
-
InputFrame,
|
|
1680
1639
|
DragFrame,
|
|
1681
1640
|
DragTarget,
|
|
1682
1641
|
AnalogStick,
|