@oscarpalmer/timer 0.18.0 → 0.19.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +10 -0
- package/dist/timer.iife.js +140 -147
- package/dist/timer.js +3 -11
- package/package.json +1 -1
- package/src/index.ts +7 -16
package/README.md
CHANGED
|
@@ -62,6 +62,16 @@ Both the nice helper methods and the class syntax create similar objects – `Wa
|
|
|
62
62
|
|
|
63
63
|
## Callbacks
|
|
64
64
|
|
|
65
|
+
Callbacks for waited timers do not receive any arguments, but callbacks for repeated ones do:
|
|
66
|
+
|
|
67
|
+
```typescript
|
|
68
|
+
repeat(index => {
|
|
69
|
+
// 'index' is the current step
|
|
70
|
+
// starts at 0, goes up to a maximum of count - 1
|
|
71
|
+
// for this example: 0 → 9
|
|
72
|
+
}, 0, 10);
|
|
73
|
+
```
|
|
74
|
+
|
|
65
75
|
When you create a repeated timer, you can also provide a fourth parameter to act as a callback to run when the timer stops, as below:
|
|
66
76
|
|
|
67
77
|
```typescript
|
package/dist/timer.iife.js
CHANGED
|
@@ -1,169 +1,162 @@
|
|
|
1
1
|
var Timer = (function (exports) {
|
|
2
|
-
|
|
2
|
+
'use strict';
|
|
3
3
|
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
timedState.active = true;
|
|
20
|
-
timedState.finished = false;
|
|
21
|
-
const isRepeated = timed instanceof Repeated;
|
|
22
|
-
let index = 0;
|
|
23
|
-
let start;
|
|
24
|
-
function step(timestamp) {
|
|
25
|
-
if (!timedState.active) {
|
|
26
|
-
return;
|
|
27
|
-
}
|
|
28
|
-
start ?? (start = timestamp);
|
|
29
|
-
const elapsed = timestamp - start;
|
|
30
|
-
const elapsedMinimum = elapsed - milliseconds;
|
|
31
|
-
const elapsedMaximum = elapsed + milliseconds;
|
|
32
|
-
if (
|
|
33
|
-
elapsedMinimum < timedConfiguration.time &&
|
|
34
|
-
timedConfiguration.time < elapsedMaximum
|
|
35
|
-
) {
|
|
36
|
-
if (timedState.active) {
|
|
37
|
-
timedCallbacks.default(isRepeated ? index : undefined);
|
|
38
|
-
}
|
|
39
|
-
index += 1;
|
|
40
|
-
if (isRepeated && index < timedConfiguration.count) {
|
|
41
|
-
start = undefined;
|
|
42
|
-
} else {
|
|
43
|
-
timedState.finished = true;
|
|
44
|
-
timed.stop();
|
|
4
|
+
const callbacks = new WeakMap();
|
|
5
|
+
const configuration = new WeakMap();
|
|
6
|
+
const state = new WeakMap();
|
|
7
|
+
const milliseconds = Math.round(1000 / 60);
|
|
8
|
+
function run(timed) {
|
|
9
|
+
const timedConfiguration = configuration.get(timed);
|
|
10
|
+
const timedCallbacks = callbacks.get(timed);
|
|
11
|
+
const timedState = state.get(timed);
|
|
12
|
+
timedState.active = true;
|
|
13
|
+
timedState.finished = false;
|
|
14
|
+
const isRepeated = timed instanceof Repeated;
|
|
15
|
+
let index = 0;
|
|
16
|
+
let start;
|
|
17
|
+
function step(timestamp) {
|
|
18
|
+
if (!timedState.active) {
|
|
45
19
|
return;
|
|
46
20
|
}
|
|
21
|
+
start ?? (start = timestamp);
|
|
22
|
+
const elapsed = timestamp - start;
|
|
23
|
+
const elapsedMinimum = elapsed - milliseconds;
|
|
24
|
+
const elapsedMaximum = elapsed + milliseconds;
|
|
25
|
+
if (
|
|
26
|
+
elapsedMinimum < timedConfiguration.time &&
|
|
27
|
+
timedConfiguration.time < elapsedMaximum
|
|
28
|
+
) {
|
|
29
|
+
if (timedState.active) {
|
|
30
|
+
timedCallbacks.default(isRepeated ? index : undefined);
|
|
31
|
+
}
|
|
32
|
+
index += 1;
|
|
33
|
+
if (isRepeated && index < timedConfiguration.count) {
|
|
34
|
+
start = undefined;
|
|
35
|
+
} else {
|
|
36
|
+
timedState.finished = true;
|
|
37
|
+
timed.stop();
|
|
38
|
+
return;
|
|
39
|
+
}
|
|
40
|
+
}
|
|
41
|
+
timedState.frame = globalThis.requestAnimationFrame(step);
|
|
47
42
|
}
|
|
48
|
-
timedState.frame =
|
|
49
|
-
}
|
|
50
|
-
timedState.frame = request(step);
|
|
51
|
-
}
|
|
52
|
-
class Timed {
|
|
53
|
-
get active() {
|
|
54
|
-
return state.get(this)?.active ?? false;
|
|
55
|
-
}
|
|
56
|
-
get finished() {
|
|
57
|
-
return !this.active && (state.get(this)?.finished ?? false);
|
|
43
|
+
timedState.frame = globalThis.requestAnimationFrame(step);
|
|
58
44
|
}
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
* @param {number} count
|
|
63
|
-
* @param {AfterCallback=} afterCallback
|
|
64
|
-
*/
|
|
65
|
-
constructor(callback, time, count, afterCallback) {
|
|
66
|
-
const isRepeated = this instanceof Repeated;
|
|
67
|
-
const type = isRepeated ? 'repeated' : 'waited';
|
|
68
|
-
if (typeof callback !== 'function') {
|
|
69
|
-
throw new TypeError(`A ${type} timer must have a callback function`);
|
|
70
|
-
}
|
|
71
|
-
if (typeof time !== 'number' || time < 0) {
|
|
72
|
-
throw new TypeError(
|
|
73
|
-
`A ${type} timer must have a non-negative number as its time`,
|
|
74
|
-
);
|
|
45
|
+
class Timed {
|
|
46
|
+
get active() {
|
|
47
|
+
return state.get(this)?.active ?? false;
|
|
75
48
|
}
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
'A repeated timer must have a number above 1 as its repeat count',
|
|
79
|
-
);
|
|
49
|
+
get finished() {
|
|
50
|
+
return !this.active && (state.get(this)?.finished ?? false);
|
|
80
51
|
}
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
52
|
+
/**
|
|
53
|
+
* @param {Callback} callback
|
|
54
|
+
* @param {number} time
|
|
55
|
+
* @param {number} count
|
|
56
|
+
* @param {AfterCallback=} afterCallback
|
|
57
|
+
*/
|
|
58
|
+
constructor(callback, time, count, afterCallback) {
|
|
59
|
+
const isRepeated = this instanceof Repeated;
|
|
60
|
+
const type = isRepeated ? 'repeated' : 'waited';
|
|
61
|
+
if (typeof callback !== 'function') {
|
|
62
|
+
throw new TypeError(`A ${type} timer must have a callback function`);
|
|
63
|
+
}
|
|
64
|
+
if (typeof time !== 'number' || time < 0) {
|
|
65
|
+
throw new TypeError(
|
|
66
|
+
`A ${type} timer must have a non-negative number as its time`,
|
|
67
|
+
);
|
|
68
|
+
}
|
|
69
|
+
if (isRepeated && (typeof count !== 'number' || count < 2)) {
|
|
70
|
+
throw new TypeError(
|
|
71
|
+
'A repeated timer must have a number above 1 as its repeat count',
|
|
72
|
+
);
|
|
73
|
+
}
|
|
74
|
+
if (
|
|
75
|
+
isRepeated &&
|
|
76
|
+
afterCallback !== undefined &&
|
|
77
|
+
typeof afterCallback !== 'function'
|
|
78
|
+
) {
|
|
79
|
+
throw new TypeError(
|
|
80
|
+
"A repeated timer's after-callback must be a function",
|
|
81
|
+
);
|
|
82
|
+
}
|
|
83
|
+
callbacks.set(this, {
|
|
84
|
+
after: afterCallback,
|
|
85
|
+
default: callback,
|
|
86
|
+
});
|
|
87
|
+
configuration.set(this, {count, time});
|
|
88
|
+
state.set(this, {
|
|
89
|
+
active: false,
|
|
90
|
+
finished: false,
|
|
91
|
+
});
|
|
89
92
|
}
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
default: callback,
|
|
93
|
-
});
|
|
94
|
-
configuration.set(this, {count, time});
|
|
95
|
-
state.set(this, {
|
|
96
|
-
active: false,
|
|
97
|
-
finished: false,
|
|
98
|
-
frame: undefined,
|
|
99
|
-
});
|
|
100
|
-
}
|
|
101
|
-
restart() {
|
|
102
|
-
this.stop();
|
|
103
|
-
run(this);
|
|
104
|
-
return this;
|
|
105
|
-
}
|
|
106
|
-
start() {
|
|
107
|
-
if (!this.active) {
|
|
93
|
+
restart() {
|
|
94
|
+
this.stop();
|
|
108
95
|
run(this);
|
|
96
|
+
return this;
|
|
109
97
|
}
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
98
|
+
start() {
|
|
99
|
+
if (!this.active) {
|
|
100
|
+
run(this);
|
|
101
|
+
}
|
|
102
|
+
return this;
|
|
103
|
+
}
|
|
104
|
+
stop() {
|
|
105
|
+
const timedCallbacks = callbacks.get(this);
|
|
106
|
+
const timedState = state.get(this);
|
|
107
|
+
timedState.active = false;
|
|
108
|
+
if (timedState.frame === undefined) {
|
|
109
|
+
return this;
|
|
110
|
+
}
|
|
111
|
+
globalThis.cancelAnimationFrame(timedState.frame);
|
|
112
|
+
timedCallbacks.after?.(this.finished);
|
|
113
|
+
timedState.frame = undefined;
|
|
117
114
|
return this;
|
|
118
115
|
}
|
|
119
|
-
(cancelAnimationFrame ?? clearTimeout)?.(timedState.frame);
|
|
120
|
-
timedCallbacks.after?.(this.finished);
|
|
121
|
-
timedState.frame = undefined;
|
|
122
|
-
return this;
|
|
123
116
|
}
|
|
124
|
-
}
|
|
125
|
-
/**
|
|
126
|
-
* A timer that waits and runs repeatedly
|
|
127
|
-
*/
|
|
128
|
-
class Repeated extends Timed {}
|
|
129
|
-
/**
|
|
130
|
-
* A timer that waits and runs once
|
|
131
|
-
*/
|
|
132
|
-
class Waited extends Timed {
|
|
133
117
|
/**
|
|
134
|
-
*
|
|
118
|
+
* A timer that waits and runs repeatedly
|
|
119
|
+
*/
|
|
120
|
+
class Repeated extends Timed {}
|
|
121
|
+
/**
|
|
122
|
+
* A timer that waits and runs once
|
|
123
|
+
*/
|
|
124
|
+
class Waited extends Timed {
|
|
125
|
+
/**
|
|
126
|
+
* Creates a new waited timer
|
|
127
|
+
* @param {() => void} callback
|
|
128
|
+
* @param {number} time
|
|
129
|
+
*/
|
|
130
|
+
constructor(callback, time) {
|
|
131
|
+
super(callback, time, 1);
|
|
132
|
+
}
|
|
133
|
+
}
|
|
134
|
+
/**
|
|
135
|
+
* Creates and starts a new repeated timer
|
|
136
|
+
* @param {RepeatedCallback} callback
|
|
137
|
+
* @param {number} time
|
|
138
|
+
* @param {number} count
|
|
139
|
+
* @param {AfterCallback=} afterCallback
|
|
140
|
+
* @return {Repeated}
|
|
141
|
+
*/
|
|
142
|
+
function repeat(callback, time, count, afterCallback) {
|
|
143
|
+
return new Repeated(callback, time, count, afterCallback).start();
|
|
144
|
+
}
|
|
145
|
+
/**
|
|
146
|
+
* Creates and starts a new waited timer
|
|
135
147
|
* @param {() => void} callback
|
|
136
148
|
* @param {number} time
|
|
149
|
+
* @return {Waited}
|
|
137
150
|
*/
|
|
138
|
-
|
|
139
|
-
|
|
151
|
+
function wait(callback, time) {
|
|
152
|
+
return new Waited(callback, time).start();
|
|
140
153
|
}
|
|
141
|
-
}
|
|
142
|
-
/**
|
|
143
|
-
* Creates and starts a new repeated timer
|
|
144
|
-
* @param {RepeatedCallback} callback
|
|
145
|
-
* @param {number} time
|
|
146
|
-
* @param {number} count
|
|
147
|
-
* @param {AfterCallback=} afterCallback
|
|
148
|
-
* @return {Repeated}
|
|
149
|
-
*/
|
|
150
|
-
function repeat(callback, time, count, afterCallback) {
|
|
151
|
-
return new Repeated(callback, time, count, afterCallback).start();
|
|
152
|
-
}
|
|
153
|
-
/**
|
|
154
|
-
* Creates and starts a new waited timer
|
|
155
|
-
* @param {() => void} callback
|
|
156
|
-
* @param {number} time
|
|
157
|
-
* @return {Waited}
|
|
158
|
-
*/
|
|
159
|
-
function wait(callback, time) {
|
|
160
|
-
return new Waited(callback, time).start();
|
|
161
|
-
}
|
|
162
154
|
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
155
|
+
exports.Repeated = Repeated;
|
|
156
|
+
exports.Waited = Waited;
|
|
157
|
+
exports.repeat = repeat;
|
|
158
|
+
exports.wait = wait;
|
|
159
|
+
|
|
160
|
+
return exports;
|
|
167
161
|
|
|
168
|
-
return exports;
|
|
169
162
|
})({});
|
package/dist/timer.js
CHANGED
|
@@ -12,13 +12,6 @@ const callbacks = new WeakMap();
|
|
|
12
12
|
const configuration = new WeakMap();
|
|
13
13
|
const state = new WeakMap();
|
|
14
14
|
const milliseconds = Math.round(1000 / 60);
|
|
15
|
-
const request =
|
|
16
|
-
requestAnimationFrame ??
|
|
17
|
-
function (callback) {
|
|
18
|
-
return setTimeout?.(() => {
|
|
19
|
-
callback(Date.now());
|
|
20
|
-
}, milliseconds);
|
|
21
|
-
};
|
|
22
15
|
function run(timed) {
|
|
23
16
|
const timedConfiguration = configuration.get(timed);
|
|
24
17
|
const timedCallbacks = callbacks.get(timed);
|
|
@@ -52,9 +45,9 @@ function run(timed) {
|
|
|
52
45
|
return;
|
|
53
46
|
}
|
|
54
47
|
}
|
|
55
|
-
timedState.frame =
|
|
48
|
+
timedState.frame = globalThis.requestAnimationFrame(step);
|
|
56
49
|
}
|
|
57
|
-
timedState.frame =
|
|
50
|
+
timedState.frame = globalThis.requestAnimationFrame(step);
|
|
58
51
|
}
|
|
59
52
|
class Timed {
|
|
60
53
|
get active() {
|
|
@@ -102,7 +95,6 @@ class Timed {
|
|
|
102
95
|
state.set(this, {
|
|
103
96
|
active: false,
|
|
104
97
|
finished: false,
|
|
105
|
-
frame: undefined,
|
|
106
98
|
});
|
|
107
99
|
}
|
|
108
100
|
restart() {
|
|
@@ -123,7 +115,7 @@ class Timed {
|
|
|
123
115
|
if (timedState.frame === undefined) {
|
|
124
116
|
return this;
|
|
125
117
|
}
|
|
126
|
-
|
|
118
|
+
globalThis.cancelAnimationFrame(timedState.frame);
|
|
127
119
|
timedCallbacks.after?.(this.finished);
|
|
128
120
|
timedState.frame = undefined;
|
|
129
121
|
return this;
|
package/package.json
CHANGED
package/src/index.ts
CHANGED
|
@@ -21,7 +21,7 @@ export type RepeatedCallback = (index: number) => void;
|
|
|
21
21
|
type State = {
|
|
22
22
|
active: boolean;
|
|
23
23
|
finished: boolean;
|
|
24
|
-
frame?:
|
|
24
|
+
frame?: number;
|
|
25
25
|
};
|
|
26
26
|
|
|
27
27
|
const callbacks = new WeakMap<Timed<never, never>, Callbacks>();
|
|
@@ -30,14 +30,6 @@ const state = new WeakMap<Timed<never, never>, State>();
|
|
|
30
30
|
|
|
31
31
|
const milliseconds = Math.round(1000 / 60);
|
|
32
32
|
|
|
33
|
-
const request =
|
|
34
|
-
globalThis.requestAnimationFrame ??
|
|
35
|
-
function (callback) {
|
|
36
|
-
return setTimeout?.(() => {
|
|
37
|
-
callback(Date.now());
|
|
38
|
-
}, milliseconds);
|
|
39
|
-
};
|
|
40
|
-
|
|
41
33
|
function run(timed: Timed<never, never>): void {
|
|
42
34
|
const timedConfiguration = configuration.get(timed)!;
|
|
43
35
|
const timedCallbacks = callbacks.get(timed)!;
|
|
@@ -52,7 +44,7 @@ function run(timed: Timed<never, never>): void {
|
|
|
52
44
|
|
|
53
45
|
let start;
|
|
54
46
|
|
|
55
|
-
function step(timestamp: DOMHighResTimeStamp) {
|
|
47
|
+
function step(timestamp: DOMHighResTimeStamp): void {
|
|
56
48
|
if (!timedState.active) {
|
|
57
49
|
return;
|
|
58
50
|
}
|
|
@@ -85,10 +77,10 @@ function run(timed: Timed<never, never>): void {
|
|
|
85
77
|
}
|
|
86
78
|
}
|
|
87
79
|
|
|
88
|
-
timedState.frame =
|
|
80
|
+
timedState.frame = globalThis.requestAnimationFrame(step);
|
|
89
81
|
}
|
|
90
82
|
|
|
91
|
-
timedState.frame =
|
|
83
|
+
timedState.frame = globalThis.requestAnimationFrame(step);
|
|
92
84
|
}
|
|
93
85
|
|
|
94
86
|
class Timed<Type, Callback> {
|
|
@@ -107,7 +99,7 @@ class Timed<Type, Callback> {
|
|
|
107
99
|
* @param {AfterCallback=} afterCallback
|
|
108
100
|
*/
|
|
109
101
|
constructor(
|
|
110
|
-
callback:
|
|
102
|
+
callback: Callback,
|
|
111
103
|
time: number,
|
|
112
104
|
count: number,
|
|
113
105
|
afterCallback?: AfterCallback,
|
|
@@ -144,7 +136,7 @@ class Timed<Type, Callback> {
|
|
|
144
136
|
|
|
145
137
|
callbacks.set(this as never, {
|
|
146
138
|
after: afterCallback,
|
|
147
|
-
default: callback,
|
|
139
|
+
default: callback as never,
|
|
148
140
|
});
|
|
149
141
|
|
|
150
142
|
configuration.set(this as never, {count, time});
|
|
@@ -152,7 +144,6 @@ class Timed<Type, Callback> {
|
|
|
152
144
|
state.set(this as never, {
|
|
153
145
|
active: false,
|
|
154
146
|
finished: false,
|
|
155
|
-
frame: undefined,
|
|
156
147
|
});
|
|
157
148
|
}
|
|
158
149
|
|
|
@@ -182,7 +173,7 @@ class Timed<Type, Callback> {
|
|
|
182
173
|
return this as never;
|
|
183
174
|
}
|
|
184
175
|
|
|
185
|
-
|
|
176
|
+
globalThis.cancelAnimationFrame(timedState.frame);
|
|
186
177
|
|
|
187
178
|
timedCallbacks.after?.(this.finished);
|
|
188
179
|
|