@oscarpalmer/timer 0.39.0 → 0.41.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/dist/constants.js +16 -2
- package/dist/index.js +1 -1
- package/dist/is.js +21 -1
- package/dist/repeat.js +8 -2
- package/dist/timer.full.js +202 -56
- package/dist/timer.js +30 -0
- package/dist/wait.js +7 -2
- package/dist/when.js +45 -2
- package/dist/work.js +2 -2
- package/package.json +8 -8
- package/src/constants.ts +0 -3
- package/src/index.ts +1 -1
- package/src/repeat.ts +2 -2
- package/src/wait.ts +2 -2
- package/src/when.ts +3 -3
- package/src/work.ts +1 -2
- package/types/constants.d.ts +0 -2
- package/types/index.d.ts +1 -1
- package/dist/delay.js +0 -15
- package/src/delay.ts +0 -27
- package/types/delay.d.ts +0 -6
package/dist/constants.js
CHANGED
|
@@ -1,9 +1,23 @@
|
|
|
1
|
-
|
|
1
|
+
/**
|
|
2
|
+
* Buffer value to use when evaluating if a specific time is within a certain range
|
|
3
|
+
*/
|
|
2
4
|
const BUFFER_INTERVAL = 5;
|
|
3
5
|
const DEFAULT_TIMEOUT = 3e4;
|
|
6
|
+
/**
|
|
7
|
+
* Message to show when a when-timer is destroyed
|
|
8
|
+
*/
|
|
4
9
|
const MESSAGE_DESTROYED = "Timer has already been destroyed";
|
|
10
|
+
/**
|
|
11
|
+
* Message to show when a when-timer is started
|
|
12
|
+
*/
|
|
5
13
|
const MESSAGE_STARTED = "Timer has already been started";
|
|
14
|
+
/**
|
|
15
|
+
* A set of all active timers
|
|
16
|
+
*/
|
|
6
17
|
const TIMERS_ACTIVE = /* @__PURE__ */ new Set();
|
|
18
|
+
/**
|
|
19
|
+
* A set of timers that were paused due to the document being hidden
|
|
20
|
+
*/
|
|
7
21
|
const TIMERS_HIDDEN = /* @__PURE__ */ new Set();
|
|
8
22
|
const TYPE_REPEAT = "repeat";
|
|
9
23
|
const TYPE_WAIT = "wait";
|
|
@@ -13,4 +27,4 @@ const WORK_PAUSE = "pause";
|
|
|
13
27
|
const WORK_RESTART = "restart";
|
|
14
28
|
const WORK_START = "start";
|
|
15
29
|
const WORK_STOP = "stop";
|
|
16
|
-
export { BUFFER_INTERVAL, DEFAULT_TIMEOUT,
|
|
30
|
+
export { BUFFER_INTERVAL, DEFAULT_TIMEOUT, MESSAGE_DESTROYED, MESSAGE_STARTED, TIMERS_ACTIVE, TIMERS_HIDDEN, TYPE_REPEAT, TYPE_WAIT, TYPE_WHEN, WORK_CONTINUE, WORK_PAUSE, WORK_RESTART, WORK_START, WORK_STOP };
|
package/dist/index.js
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
|
-
import { delay } from "./delay.js";
|
|
2
1
|
import "./global.js";
|
|
3
2
|
import { isRepeated, isTimer, isWaited, isWhen } from "./is.js";
|
|
4
3
|
import { repeat } from "./repeat.js";
|
|
5
4
|
import { wait } from "./wait.js";
|
|
6
5
|
import { when } from "./when.js";
|
|
6
|
+
import { delay } from "@oscarpalmer/atoms/promise";
|
|
7
7
|
export { delay, isRepeated, isTimer, isWaited, isWhen, repeat, wait, when };
|
package/dist/is.js
CHANGED
|
@@ -1,16 +1,36 @@
|
|
|
1
|
-
import { TYPE_REPEAT, TYPE_WAIT
|
|
1
|
+
import { TYPE_REPEAT, TYPE_WAIT } from "./constants.js";
|
|
2
2
|
function is(names, value) {
|
|
3
3
|
return names.includes(value?.$timer);
|
|
4
4
|
}
|
|
5
|
+
/**
|
|
6
|
+
* Is the value a repeating timer?
|
|
7
|
+
* @param value Value to check
|
|
8
|
+
* @returns `true` if the value is a repeating timer
|
|
9
|
+
*/
|
|
5
10
|
function isRepeated(value) {
|
|
6
11
|
return is([TYPE_REPEAT], value);
|
|
7
12
|
}
|
|
13
|
+
/**
|
|
14
|
+
* Is the value a timer?
|
|
15
|
+
* @param value Value to check
|
|
16
|
+
* @returns `true` if the value is a timer
|
|
17
|
+
*/
|
|
8
18
|
function isTimer(value) {
|
|
9
19
|
return is([TYPE_REPEAT, TYPE_WAIT], value);
|
|
10
20
|
}
|
|
21
|
+
/**
|
|
22
|
+
* Is the value a waiting timer?
|
|
23
|
+
* @param value Value to check
|
|
24
|
+
* @returns `true` if the value is a waiting timer
|
|
25
|
+
*/
|
|
11
26
|
function isWaited(value) {
|
|
12
27
|
return is([TYPE_WAIT], value);
|
|
13
28
|
}
|
|
29
|
+
/**
|
|
30
|
+
* Is the value a conditional timer?
|
|
31
|
+
* @param value Value to check
|
|
32
|
+
* @returns `true` if the value is a conditional timer
|
|
33
|
+
*/
|
|
14
34
|
function isWhen(value) {
|
|
15
35
|
return is(["when"], value) && typeof value.then === "function";
|
|
16
36
|
}
|
package/dist/repeat.js
CHANGED
|
@@ -1,8 +1,14 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { TYPE_REPEAT } from "./constants.js";
|
|
2
2
|
import { getCallback, getValidNumber } from "./get.js";
|
|
3
3
|
import "./global.js";
|
|
4
4
|
import { TimerTrace } from "./models.js";
|
|
5
5
|
import { Timer } from "./timer.js";
|
|
6
|
+
/**
|
|
7
|
+
* Create a repeating timer
|
|
8
|
+
* @param callback Callback to run on each interval
|
|
9
|
+
* @param options Timer options
|
|
10
|
+
* @returns Timer instance
|
|
11
|
+
*/
|
|
6
12
|
function repeat(callback, options) {
|
|
7
13
|
return new Timer(TYPE_REPEAT, {
|
|
8
14
|
callback: getCallback(callback),
|
|
@@ -11,7 +17,7 @@ function repeat(callback, options) {
|
|
|
11
17
|
onAfter: getCallback(options?.onAfter),
|
|
12
18
|
onError: getCallback(options?.onTimeout),
|
|
13
19
|
count: getValidNumber(options?.count),
|
|
14
|
-
interval: getValidNumber(options?.interval
|
|
20
|
+
interval: getValidNumber(options?.interval),
|
|
15
21
|
timeout: getValidNumber(options?.timeout)
|
|
16
22
|
}, true);
|
|
17
23
|
}
|
package/dist/timer.full.js
CHANGED
|
@@ -1,29 +1,23 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
let last;
|
|
5
|
-
function step(now) {
|
|
6
|
-
if (last != null) values.push(now - last);
|
|
7
|
-
last = now;
|
|
8
|
-
if (values.length >= CALCULATION_TOTAL) resolve(values.sort().slice(CALCULATION_TRIM_PART, -CALCULATION_TRIM_PART).reduce((first, second) => first + second, 0) / (values.length - CALCULATION_TRIM_TOTAL));
|
|
9
|
-
else requestAnimationFrame(step);
|
|
10
|
-
}
|
|
11
|
-
requestAnimationFrame(step);
|
|
12
|
-
});
|
|
13
|
-
}
|
|
14
|
-
var CALCULATION_TOTAL = 10;
|
|
15
|
-
var CALCULATION_TRIM_PART = 2;
|
|
16
|
-
var CALCULATION_TRIM_TOTAL = 4;
|
|
17
|
-
var FRAME_RATE_MS = 1e3 / 60;
|
|
18
|
-
calculate().then((value) => {
|
|
19
|
-
FRAME_RATE_MS = value;
|
|
20
|
-
});
|
|
21
|
-
var frame_rate_default = FRAME_RATE_MS;
|
|
1
|
+
/**
|
|
2
|
+
* Buffer value to use when evaluating if a specific time is within a certain range
|
|
3
|
+
*/
|
|
22
4
|
const BUFFER_INTERVAL = 5;
|
|
23
5
|
const DEFAULT_TIMEOUT = 3e4;
|
|
6
|
+
/**
|
|
7
|
+
* Message to show when a when-timer is destroyed
|
|
8
|
+
*/
|
|
24
9
|
const MESSAGE_DESTROYED = "Timer has already been destroyed";
|
|
10
|
+
/**
|
|
11
|
+
* Message to show when a when-timer is started
|
|
12
|
+
*/
|
|
25
13
|
const MESSAGE_STARTED = "Timer has already been started";
|
|
14
|
+
/**
|
|
15
|
+
* A set of all active timers
|
|
16
|
+
*/
|
|
26
17
|
const TIMERS_ACTIVE = /* @__PURE__ */ new Set();
|
|
18
|
+
/**
|
|
19
|
+
* A set of timers that were paused due to the document being hidden
|
|
20
|
+
*/
|
|
27
21
|
const TIMERS_HIDDEN = /* @__PURE__ */ new Set();
|
|
28
22
|
const TYPE_REPEAT = "repeat";
|
|
29
23
|
const TYPE_WAIT = "wait";
|
|
@@ -47,57 +41,125 @@ document.addEventListener("visibilitychange", () => {
|
|
|
47
41
|
}
|
|
48
42
|
from.clear();
|
|
49
43
|
});
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
Uint8ClampedArray,
|
|
55
|
-
Int16Array,
|
|
56
|
-
Uint16Array,
|
|
57
|
-
Int32Array,
|
|
58
|
-
Uint32Array,
|
|
59
|
-
Float32Array,
|
|
60
|
-
Float64Array,
|
|
61
|
-
BigInt64Array,
|
|
62
|
-
BigUint64Array
|
|
63
|
-
]);
|
|
64
|
-
function getCallback(value) {
|
|
65
|
-
return typeof value === "function" ? value : noop;
|
|
44
|
+
const PROMISE_ABORT_OPTIONS = { once: true };
|
|
45
|
+
const PROMISE_EVENT_NAME = "abort";
|
|
46
|
+
function getNumberOrDefault(value) {
|
|
47
|
+
return typeof value === "number" && value > 0 ? value : 0;
|
|
66
48
|
}
|
|
67
|
-
function
|
|
68
|
-
|
|
49
|
+
function getPromiseOptions(input) {
|
|
50
|
+
if (typeof input === "number") return { time: getNumberOrDefault(input) };
|
|
51
|
+
if (input instanceof AbortSignal) return {
|
|
52
|
+
signal: input,
|
|
53
|
+
time: 0
|
|
54
|
+
};
|
|
55
|
+
const options = typeof input === "object" && input !== null ? input : {};
|
|
56
|
+
return {
|
|
57
|
+
signal: options.signal instanceof AbortSignal ? options.signal : void 0,
|
|
58
|
+
time: getNumberOrDefault(options.time)
|
|
59
|
+
};
|
|
69
60
|
}
|
|
70
|
-
function
|
|
71
|
-
|
|
72
|
-
|
|
61
|
+
function settlePromise(aborter, settler, value, signal) {
|
|
62
|
+
signal?.removeEventListener(PROMISE_EVENT_NAME, aborter);
|
|
63
|
+
settler(value);
|
|
73
64
|
}
|
|
74
|
-
function
|
|
75
|
-
return
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
65
|
+
function getInterval(value) {
|
|
66
|
+
return typeof value === "number" && value > 0 ? value : 0;
|
|
67
|
+
}
|
|
68
|
+
function getTimer(type, callback, time) {
|
|
69
|
+
const interval = getInterval(time);
|
|
70
|
+
function run(now) {
|
|
71
|
+
start ??= now;
|
|
72
|
+
if (interval === 0 || now - start >= interval - OFFSET) {
|
|
73
|
+
if (throttle) start = now;
|
|
74
|
+
callback(...args);
|
|
75
|
+
} else frame = requestAnimationFrame(run);
|
|
76
|
+
}
|
|
77
|
+
const throttle = type === TIMER_THROTTLE;
|
|
78
|
+
let args;
|
|
79
|
+
let frame;
|
|
80
|
+
let start;
|
|
81
|
+
const timer = (...parameters) => {
|
|
82
|
+
timer.cancel();
|
|
83
|
+
args = parameters;
|
|
84
|
+
frame = requestAnimationFrame(run);
|
|
85
|
+
};
|
|
86
|
+
timer.cancel = () => {
|
|
87
|
+
cancelAnimationFrame(frame);
|
|
88
|
+
};
|
|
89
|
+
return timer;
|
|
90
|
+
}
|
|
91
|
+
var OFFSET = 5;
|
|
92
|
+
const TIMER_THROTTLE = "throttle";
|
|
93
|
+
const TIMER_WAIT = "wait";
|
|
94
|
+
function delay(options) {
|
|
95
|
+
const { signal, time } = getPromiseOptions(options);
|
|
96
|
+
if (signal?.aborted ?? false) return Promise.reject(signal.reason);
|
|
97
|
+
function abort() {
|
|
98
|
+
timer.cancel();
|
|
99
|
+
rejector(signal.reason);
|
|
100
|
+
}
|
|
101
|
+
const timer = getTimer(TIMER_WAIT, () => {
|
|
102
|
+
settlePromise(abort, resolver, void 0, signal);
|
|
103
|
+
}, time);
|
|
104
|
+
signal?.addEventListener("abort", abort, PROMISE_ABORT_OPTIONS);
|
|
105
|
+
let rejector;
|
|
106
|
+
let resolver;
|
|
107
|
+
return new Promise((resolve, reject) => {
|
|
108
|
+
rejector = reject;
|
|
109
|
+
resolver = resolve;
|
|
110
|
+
if (time === 0) settlePromise(abort, resolve, void 0, signal);
|
|
111
|
+
else timer();
|
|
84
112
|
});
|
|
85
113
|
}
|
|
86
114
|
function is(names, value) {
|
|
87
115
|
return names.includes(value?.$timer);
|
|
88
116
|
}
|
|
117
|
+
/**
|
|
118
|
+
* Is the value a repeating timer?
|
|
119
|
+
* @param value Value to check
|
|
120
|
+
* @returns `true` if the value is a repeating timer
|
|
121
|
+
*/
|
|
89
122
|
function isRepeated(value) {
|
|
90
123
|
return is([TYPE_REPEAT], value);
|
|
91
124
|
}
|
|
125
|
+
/**
|
|
126
|
+
* Is the value a timer?
|
|
127
|
+
* @param value Value to check
|
|
128
|
+
* @returns `true` if the value is a timer
|
|
129
|
+
*/
|
|
92
130
|
function isTimer(value) {
|
|
93
131
|
return is([TYPE_REPEAT, TYPE_WAIT], value);
|
|
94
132
|
}
|
|
133
|
+
/**
|
|
134
|
+
* Is the value a waiting timer?
|
|
135
|
+
* @param value Value to check
|
|
136
|
+
* @returns `true` if the value is a waiting timer
|
|
137
|
+
*/
|
|
95
138
|
function isWaited(value) {
|
|
96
139
|
return is([TYPE_WAIT], value);
|
|
97
140
|
}
|
|
141
|
+
/**
|
|
142
|
+
* Is the value a conditional timer?
|
|
143
|
+
* @param value Value to check
|
|
144
|
+
* @returns `true` if the value is a conditional timer
|
|
145
|
+
*/
|
|
98
146
|
function isWhen(value) {
|
|
99
147
|
return is([TYPE_WHEN], value) && typeof value.then === "function";
|
|
100
148
|
}
|
|
149
|
+
/**
|
|
150
|
+
* A function that does nothing, which can be useful, I guess…
|
|
151
|
+
*/
|
|
152
|
+
function noop() {}
|
|
153
|
+
function getCallback(value) {
|
|
154
|
+
return typeof value === "function" ? value : noop;
|
|
155
|
+
}
|
|
156
|
+
function getValidTimeout(value) {
|
|
157
|
+
return typeof value === "number" && value > 0 ? value : DEFAULT_TIMEOUT;
|
|
158
|
+
}
|
|
159
|
+
function getValidNumber(value, defaultValue) {
|
|
160
|
+
const actualDefault = defaultValue ?? 0;
|
|
161
|
+
return typeof value === "number" && value > actualDefault ? value : actualDefault;
|
|
162
|
+
}
|
|
101
163
|
var TimerTrace = class extends Error {
|
|
102
164
|
constructor() {
|
|
103
165
|
super();
|
|
@@ -139,7 +201,7 @@ function run(timer, state, options) {
|
|
|
139
201
|
finish(timer, state, options, false);
|
|
140
202
|
return;
|
|
141
203
|
}
|
|
142
|
-
if (options.interval ===
|
|
204
|
+
if (options.interval === 0 || state.elapsed >= options.interval - BUFFER_INTERVAL) {
|
|
143
205
|
if (options.count > -1) state.callback(state.index);
|
|
144
206
|
start = now;
|
|
145
207
|
state.elapsed = 0;
|
|
@@ -185,15 +247,27 @@ function work(type, timer, state, options) {
|
|
|
185
247
|
}
|
|
186
248
|
var Timer = class {
|
|
187
249
|
state;
|
|
250
|
+
/**
|
|
251
|
+
* Is the timer active?
|
|
252
|
+
*/
|
|
188
253
|
get active() {
|
|
189
254
|
return this.state.active;
|
|
190
255
|
}
|
|
256
|
+
/**
|
|
257
|
+
* Is the timer destroyed?
|
|
258
|
+
*/
|
|
191
259
|
get destroyed() {
|
|
192
260
|
return this.state.destroyed;
|
|
193
261
|
}
|
|
262
|
+
/**
|
|
263
|
+
* Is the timer paused?
|
|
264
|
+
*/
|
|
194
265
|
get paused() {
|
|
195
266
|
return this.state.paused;
|
|
196
267
|
}
|
|
268
|
+
/**
|
|
269
|
+
* Get the timer's origin _(if debugging is enabled)_
|
|
270
|
+
*/
|
|
197
271
|
get trace() {
|
|
198
272
|
return globalThis._oscarpalmer_timer_debug ?? false ? this.state.trace : void 0;
|
|
199
273
|
}
|
|
@@ -212,9 +286,15 @@ var Timer = class {
|
|
|
212
286
|
};
|
|
213
287
|
if (start) this.start();
|
|
214
288
|
}
|
|
289
|
+
/**
|
|
290
|
+
* Continue running the timer _(if it's paused)_
|
|
291
|
+
*/
|
|
215
292
|
continue() {
|
|
216
293
|
return this.#work(WORK_CONTINUE);
|
|
217
294
|
}
|
|
295
|
+
/**
|
|
296
|
+
* Destroy the timer
|
|
297
|
+
*/
|
|
218
298
|
destroy() {
|
|
219
299
|
this.state.destroyed = true;
|
|
220
300
|
this.options.onAfter = noop;
|
|
@@ -226,15 +306,27 @@ var Timer = class {
|
|
|
226
306
|
type: this.$timer
|
|
227
307
|
}, this.state, this.options);
|
|
228
308
|
}
|
|
309
|
+
/**
|
|
310
|
+
* Pause the timer _(if it's running)_
|
|
311
|
+
*/
|
|
229
312
|
pause() {
|
|
230
313
|
return this.#work(WORK_PAUSE);
|
|
231
314
|
}
|
|
315
|
+
/**
|
|
316
|
+
* Restart the timer _(or start it, if it's not running)_
|
|
317
|
+
*/
|
|
232
318
|
restart() {
|
|
233
319
|
return this.#work(WORK_RESTART);
|
|
234
320
|
}
|
|
321
|
+
/**
|
|
322
|
+
* Start the timer _(if it's not running)_
|
|
323
|
+
*/
|
|
235
324
|
start() {
|
|
236
325
|
return this.#work(WORK_START);
|
|
237
326
|
}
|
|
327
|
+
/**
|
|
328
|
+
* Stop the timer _(if it's running)_
|
|
329
|
+
*/
|
|
238
330
|
stop() {
|
|
239
331
|
return this.#work(WORK_STOP);
|
|
240
332
|
}
|
|
@@ -245,6 +337,12 @@ var Timer = class {
|
|
|
245
337
|
}, this.state, this.options);
|
|
246
338
|
}
|
|
247
339
|
};
|
|
340
|
+
/**
|
|
341
|
+
* Create a repeating timer
|
|
342
|
+
* @param callback Callback to run on each interval
|
|
343
|
+
* @param options Timer options
|
|
344
|
+
* @returns Timer instance
|
|
345
|
+
*/
|
|
248
346
|
function repeat(callback, options) {
|
|
249
347
|
return new Timer(TYPE_REPEAT, {
|
|
250
348
|
callback: getCallback(callback),
|
|
@@ -253,10 +351,15 @@ function repeat(callback, options) {
|
|
|
253
351
|
onAfter: getCallback(options?.onAfter),
|
|
254
352
|
onError: getCallback(options?.onTimeout),
|
|
255
353
|
count: getValidNumber(options?.count),
|
|
256
|
-
interval: getValidNumber(options?.interval
|
|
354
|
+
interval: getValidNumber(options?.interval),
|
|
257
355
|
timeout: getValidNumber(options?.timeout)
|
|
258
356
|
}, true);
|
|
259
357
|
}
|
|
358
|
+
/**
|
|
359
|
+
* Create a waiting timer
|
|
360
|
+
* @param callback Callback to run when the timer has finished
|
|
361
|
+
* @param time How long to wait for _(in milliseconds; defaults to screen refresh rate)_
|
|
362
|
+
*/
|
|
260
363
|
function wait(callback, time) {
|
|
261
364
|
return new Timer(TYPE_WAIT, {
|
|
262
365
|
callback: getCallback(callback),
|
|
@@ -265,7 +368,7 @@ function wait(callback, time) {
|
|
|
265
368
|
onAfter: void 0,
|
|
266
369
|
onError: void 0,
|
|
267
370
|
count: -1,
|
|
268
|
-
interval: getValidNumber(time
|
|
371
|
+
interval: getValidNumber(time),
|
|
269
372
|
timeout: 0
|
|
270
373
|
}, true);
|
|
271
374
|
}
|
|
@@ -277,15 +380,27 @@ var When = class {
|
|
|
277
380
|
started: false,
|
|
278
381
|
timer: void 0
|
|
279
382
|
};
|
|
383
|
+
/**
|
|
384
|
+
* Is the timer active?
|
|
385
|
+
*/
|
|
280
386
|
get active() {
|
|
281
387
|
return this.state.timer?.active ?? false;
|
|
282
388
|
}
|
|
389
|
+
/**
|
|
390
|
+
* Is the timer destroyed?
|
|
391
|
+
*/
|
|
283
392
|
get destroyed() {
|
|
284
393
|
return this.state.timer == null;
|
|
285
394
|
}
|
|
395
|
+
/**
|
|
396
|
+
* Is the timer paused?
|
|
397
|
+
*/
|
|
286
398
|
get paused() {
|
|
287
399
|
return this.state.timer?.paused ?? false;
|
|
288
400
|
}
|
|
401
|
+
/**
|
|
402
|
+
* Get the timer's origin _(if debugging is enabled)_
|
|
403
|
+
*/
|
|
289
404
|
get trace() {
|
|
290
405
|
return globalThis._oscarpalmer_timer_debug ?? false ? this.state.timer?.trace : void 0;
|
|
291
406
|
}
|
|
@@ -320,14 +435,20 @@ var When = class {
|
|
|
320
435
|
this.destroy();
|
|
321
436
|
},
|
|
322
437
|
count: getValidNumber(options?.count),
|
|
323
|
-
interval: getValidNumber(options?.interval
|
|
438
|
+
interval: getValidNumber(options?.interval),
|
|
324
439
|
timeout: getValidTimeout(options?.timeout)
|
|
325
440
|
}, false);
|
|
326
441
|
}
|
|
442
|
+
/**
|
|
443
|
+
* Continues the timer _(if it was paused)_
|
|
444
|
+
*/
|
|
327
445
|
continue() {
|
|
328
446
|
this.state.timer?.continue();
|
|
329
447
|
return this;
|
|
330
448
|
}
|
|
449
|
+
/**
|
|
450
|
+
* Destroys the timer _(and stops it,if it was running)_
|
|
451
|
+
*/
|
|
331
452
|
destroy() {
|
|
332
453
|
const { state } = this;
|
|
333
454
|
state.timer?.destroy();
|
|
@@ -336,10 +457,19 @@ var When = class {
|
|
|
336
457
|
state.rejecter = noop;
|
|
337
458
|
state.timer = void 0;
|
|
338
459
|
}
|
|
460
|
+
/**
|
|
461
|
+
* Pauses the timer _(if it was running)_
|
|
462
|
+
*/
|
|
339
463
|
pause() {
|
|
340
464
|
this.state.timer?.pause();
|
|
341
465
|
return this;
|
|
342
466
|
}
|
|
467
|
+
/**
|
|
468
|
+
* Start the timer
|
|
469
|
+
* @param resolve Optional resolve callback
|
|
470
|
+
* @param reject Optional reject callback
|
|
471
|
+
* @returns Promise that resolves when the condition is met
|
|
472
|
+
*/
|
|
343
473
|
start(resolve, reject) {
|
|
344
474
|
const { state } = this;
|
|
345
475
|
if (state.timer == null) throw new Error(MESSAGE_DESTROYED);
|
|
@@ -348,14 +478,30 @@ var When = class {
|
|
|
348
478
|
state.timer.start();
|
|
349
479
|
return state.promise.then(resolve ?? noop, reject ?? noop);
|
|
350
480
|
}
|
|
481
|
+
/**
|
|
482
|
+
* Stops the timer _(if it was running)_
|
|
483
|
+
*/
|
|
351
484
|
stop() {
|
|
352
485
|
this.state.timer?.stop();
|
|
353
486
|
return this;
|
|
354
487
|
}
|
|
488
|
+
/**
|
|
489
|
+
* Start the timer
|
|
490
|
+
* @deprecated Use `start()` instead
|
|
491
|
+
* @param resolve Optional resolve callback
|
|
492
|
+
* @param reject Optional reject callback
|
|
493
|
+
* @returns Promise that resolves when the condition is met
|
|
494
|
+
*/
|
|
355
495
|
then(resolve, reject) {
|
|
356
496
|
return this.start(resolve, reject);
|
|
357
497
|
}
|
|
358
498
|
};
|
|
499
|
+
/**
|
|
500
|
+
* Create a conditional timer
|
|
501
|
+
* @param condition Condition to check
|
|
502
|
+
* @param options Timer options
|
|
503
|
+
* @returns Timer instance
|
|
504
|
+
*/
|
|
359
505
|
function when(condition, options) {
|
|
360
506
|
return new When(condition, options);
|
|
361
507
|
}
|
package/dist/timer.js
CHANGED
|
@@ -3,15 +3,27 @@ import { stop, work } from "./work.js";
|
|
|
3
3
|
import { noop } from "@oscarpalmer/atoms/function";
|
|
4
4
|
var Timer = class {
|
|
5
5
|
state;
|
|
6
|
+
/**
|
|
7
|
+
* Is the timer active?
|
|
8
|
+
*/
|
|
6
9
|
get active() {
|
|
7
10
|
return this.state.active;
|
|
8
11
|
}
|
|
12
|
+
/**
|
|
13
|
+
* Is the timer destroyed?
|
|
14
|
+
*/
|
|
9
15
|
get destroyed() {
|
|
10
16
|
return this.state.destroyed;
|
|
11
17
|
}
|
|
18
|
+
/**
|
|
19
|
+
* Is the timer paused?
|
|
20
|
+
*/
|
|
12
21
|
get paused() {
|
|
13
22
|
return this.state.paused;
|
|
14
23
|
}
|
|
24
|
+
/**
|
|
25
|
+
* Get the timer's origin _(if debugging is enabled)_
|
|
26
|
+
*/
|
|
15
27
|
get trace() {
|
|
16
28
|
return globalThis._oscarpalmer_timer_debug ?? false ? this.state.trace : void 0;
|
|
17
29
|
}
|
|
@@ -30,9 +42,15 @@ var Timer = class {
|
|
|
30
42
|
};
|
|
31
43
|
if (start) this.start();
|
|
32
44
|
}
|
|
45
|
+
/**
|
|
46
|
+
* Continue running the timer _(if it's paused)_
|
|
47
|
+
*/
|
|
33
48
|
continue() {
|
|
34
49
|
return this.#work(WORK_CONTINUE);
|
|
35
50
|
}
|
|
51
|
+
/**
|
|
52
|
+
* Destroy the timer
|
|
53
|
+
*/
|
|
36
54
|
destroy() {
|
|
37
55
|
this.state.destroyed = true;
|
|
38
56
|
this.options.onAfter = noop;
|
|
@@ -44,15 +62,27 @@ var Timer = class {
|
|
|
44
62
|
type: this.$timer
|
|
45
63
|
}, this.state, this.options);
|
|
46
64
|
}
|
|
65
|
+
/**
|
|
66
|
+
* Pause the timer _(if it's running)_
|
|
67
|
+
*/
|
|
47
68
|
pause() {
|
|
48
69
|
return this.#work(WORK_PAUSE);
|
|
49
70
|
}
|
|
71
|
+
/**
|
|
72
|
+
* Restart the timer _(or start it, if it's not running)_
|
|
73
|
+
*/
|
|
50
74
|
restart() {
|
|
51
75
|
return this.#work(WORK_RESTART);
|
|
52
76
|
}
|
|
77
|
+
/**
|
|
78
|
+
* Start the timer _(if it's not running)_
|
|
79
|
+
*/
|
|
53
80
|
start() {
|
|
54
81
|
return this.#work(WORK_START);
|
|
55
82
|
}
|
|
83
|
+
/**
|
|
84
|
+
* Stop the timer _(if it's running)_
|
|
85
|
+
*/
|
|
56
86
|
stop() {
|
|
57
87
|
return this.#work(WORK_STOP);
|
|
58
88
|
}
|
package/dist/wait.js
CHANGED
|
@@ -1,8 +1,13 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { TYPE_WAIT } from "./constants.js";
|
|
2
2
|
import { getCallback, getValidNumber } from "./get.js";
|
|
3
3
|
import "./global.js";
|
|
4
4
|
import { TimerTrace } from "./models.js";
|
|
5
5
|
import { Timer } from "./timer.js";
|
|
6
|
+
/**
|
|
7
|
+
* Create a waiting timer
|
|
8
|
+
* @param callback Callback to run when the timer has finished
|
|
9
|
+
* @param time How long to wait for _(in milliseconds; defaults to screen refresh rate)_
|
|
10
|
+
*/
|
|
6
11
|
function wait(callback, time) {
|
|
7
12
|
return new Timer(TYPE_WAIT, {
|
|
8
13
|
callback: getCallback(callback),
|
|
@@ -11,7 +16,7 @@ function wait(callback, time) {
|
|
|
11
16
|
onAfter: void 0,
|
|
12
17
|
onError: void 0,
|
|
13
18
|
count: -1,
|
|
14
|
-
interval: getValidNumber(time
|
|
19
|
+
interval: getValidNumber(time),
|
|
15
20
|
timeout: 0
|
|
16
21
|
}, true);
|
|
17
22
|
}
|
package/dist/when.js
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { MESSAGE_DESTROYED, MESSAGE_STARTED, TYPE_WHEN } from "./constants.js";
|
|
2
2
|
import { getValidNumber, getValidTimeout } from "./get.js";
|
|
3
3
|
import "./global.js";
|
|
4
4
|
import { TimerTrace } from "./models.js";
|
|
@@ -12,15 +12,27 @@ var When = class {
|
|
|
12
12
|
started: false,
|
|
13
13
|
timer: void 0
|
|
14
14
|
};
|
|
15
|
+
/**
|
|
16
|
+
* Is the timer active?
|
|
17
|
+
*/
|
|
15
18
|
get active() {
|
|
16
19
|
return this.state.timer?.active ?? false;
|
|
17
20
|
}
|
|
21
|
+
/**
|
|
22
|
+
* Is the timer destroyed?
|
|
23
|
+
*/
|
|
18
24
|
get destroyed() {
|
|
19
25
|
return this.state.timer == null;
|
|
20
26
|
}
|
|
27
|
+
/**
|
|
28
|
+
* Is the timer paused?
|
|
29
|
+
*/
|
|
21
30
|
get paused() {
|
|
22
31
|
return this.state.timer?.paused ?? false;
|
|
23
32
|
}
|
|
33
|
+
/**
|
|
34
|
+
* Get the timer's origin _(if debugging is enabled)_
|
|
35
|
+
*/
|
|
24
36
|
get trace() {
|
|
25
37
|
return globalThis._oscarpalmer_timer_debug ?? false ? this.state.timer?.trace : void 0;
|
|
26
38
|
}
|
|
@@ -55,14 +67,20 @@ var When = class {
|
|
|
55
67
|
this.destroy();
|
|
56
68
|
},
|
|
57
69
|
count: getValidNumber(options?.count),
|
|
58
|
-
interval: getValidNumber(options?.interval
|
|
70
|
+
interval: getValidNumber(options?.interval),
|
|
59
71
|
timeout: getValidTimeout(options?.timeout)
|
|
60
72
|
}, false);
|
|
61
73
|
}
|
|
74
|
+
/**
|
|
75
|
+
* Continues the timer _(if it was paused)_
|
|
76
|
+
*/
|
|
62
77
|
continue() {
|
|
63
78
|
this.state.timer?.continue();
|
|
64
79
|
return this;
|
|
65
80
|
}
|
|
81
|
+
/**
|
|
82
|
+
* Destroys the timer _(and stops it,if it was running)_
|
|
83
|
+
*/
|
|
66
84
|
destroy() {
|
|
67
85
|
const { state } = this;
|
|
68
86
|
state.timer?.destroy();
|
|
@@ -71,10 +89,19 @@ var When = class {
|
|
|
71
89
|
state.rejecter = noop;
|
|
72
90
|
state.timer = void 0;
|
|
73
91
|
}
|
|
92
|
+
/**
|
|
93
|
+
* Pauses the timer _(if it was running)_
|
|
94
|
+
*/
|
|
74
95
|
pause() {
|
|
75
96
|
this.state.timer?.pause();
|
|
76
97
|
return this;
|
|
77
98
|
}
|
|
99
|
+
/**
|
|
100
|
+
* Start the timer
|
|
101
|
+
* @param resolve Optional resolve callback
|
|
102
|
+
* @param reject Optional reject callback
|
|
103
|
+
* @returns Promise that resolves when the condition is met
|
|
104
|
+
*/
|
|
78
105
|
start(resolve, reject) {
|
|
79
106
|
const { state } = this;
|
|
80
107
|
if (state.timer == null) throw new Error(MESSAGE_DESTROYED);
|
|
@@ -83,14 +110,30 @@ var When = class {
|
|
|
83
110
|
state.timer.start();
|
|
84
111
|
return state.promise.then(resolve ?? noop, reject ?? noop);
|
|
85
112
|
}
|
|
113
|
+
/**
|
|
114
|
+
* Stops the timer _(if it was running)_
|
|
115
|
+
*/
|
|
86
116
|
stop() {
|
|
87
117
|
this.state.timer?.stop();
|
|
88
118
|
return this;
|
|
89
119
|
}
|
|
120
|
+
/**
|
|
121
|
+
* Start the timer
|
|
122
|
+
* @deprecated Use `start()` instead
|
|
123
|
+
* @param resolve Optional resolve callback
|
|
124
|
+
* @param reject Optional reject callback
|
|
125
|
+
* @returns Promise that resolves when the condition is met
|
|
126
|
+
*/
|
|
90
127
|
then(resolve, reject) {
|
|
91
128
|
return this.start(resolve, reject);
|
|
92
129
|
}
|
|
93
130
|
};
|
|
131
|
+
/**
|
|
132
|
+
* Create a conditional timer
|
|
133
|
+
* @param condition Condition to check
|
|
134
|
+
* @param options Timer options
|
|
135
|
+
* @returns Timer instance
|
|
136
|
+
*/
|
|
94
137
|
function when(condition, options) {
|
|
95
138
|
return new When(condition, options);
|
|
96
139
|
}
|
package/dist/work.js
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { TIMERS_ACTIVE, WORK_PAUSE, WORK_STOP } from "./constants.js";
|
|
2
2
|
function finish(timer, state, options, success) {
|
|
3
3
|
cancelAnimationFrame(state.frame);
|
|
4
4
|
TIMERS_ACTIVE.delete(timer.instance);
|
|
@@ -34,7 +34,7 @@ function run(timer, state, options) {
|
|
|
34
34
|
finish(timer, state, options, false);
|
|
35
35
|
return;
|
|
36
36
|
}
|
|
37
|
-
if (options.interval ===
|
|
37
|
+
if (options.interval === 0 || state.elapsed >= options.interval - 5) {
|
|
38
38
|
if (options.count > -1) state.callback(state.index);
|
|
39
39
|
start = now;
|
|
40
40
|
state.elapsed = 0;
|
package/package.json
CHANGED
|
@@ -4,19 +4,19 @@
|
|
|
4
4
|
"url": "https://oscarpalmer.se"
|
|
5
5
|
},
|
|
6
6
|
"dependencies": {
|
|
7
|
-
"@oscarpalmer/atoms": "^0.
|
|
7
|
+
"@oscarpalmer/atoms": "^0.152"
|
|
8
8
|
},
|
|
9
9
|
"description": "A better solution for timeout- and interval-based timers.",
|
|
10
10
|
"devDependencies": {
|
|
11
|
-
"@types/node": "^25",
|
|
11
|
+
"@types/node": "^25.3",
|
|
12
12
|
"@vitest/coverage-istanbul": "^4",
|
|
13
|
-
"jsdom": "^
|
|
14
|
-
"oxfmt": "^0.
|
|
15
|
-
"oxlint": "^1.
|
|
16
|
-
"rolldown": "1.0.0-
|
|
13
|
+
"jsdom": "^28.1",
|
|
14
|
+
"oxfmt": "^0.36",
|
|
15
|
+
"oxlint": "^1.51",
|
|
16
|
+
"rolldown": "1.0.0-rc.6",
|
|
17
17
|
"tslib": "^2.8",
|
|
18
18
|
"typescript": "^5.9",
|
|
19
|
-
"vite": "8.0.0-beta.
|
|
19
|
+
"vite": "8.0.0-beta.16",
|
|
20
20
|
"vitest": "^4"
|
|
21
21
|
},
|
|
22
22
|
"exports": {
|
|
@@ -70,5 +70,5 @@
|
|
|
70
70
|
},
|
|
71
71
|
"type": "module",
|
|
72
72
|
"types": "types/index.d.ts",
|
|
73
|
-
"version": "0.
|
|
73
|
+
"version": "0.41.0"
|
|
74
74
|
}
|
package/src/constants.ts
CHANGED
|
@@ -1,4 +1,3 @@
|
|
|
1
|
-
import FRAME_RATE_MS from '@oscarpalmer/atoms/frame-rate';
|
|
2
1
|
import type {TimerType, WorkHandlerType} from './models';
|
|
3
2
|
import type {Timer} from './timer';
|
|
4
3
|
|
|
@@ -44,5 +43,3 @@ export const WORK_RESTART: WorkHandlerType = 'restart';
|
|
|
44
43
|
export const WORK_START: WorkHandlerType = 'start';
|
|
45
44
|
|
|
46
45
|
export const WORK_STOP: WorkHandlerType = 'stop';
|
|
47
|
-
|
|
48
|
-
export {FRAME_RATE_MS};
|
package/src/index.ts
CHANGED
package/src/repeat.ts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import {TYPE_REPEAT} from './constants';
|
|
2
2
|
import {getCallback, getValidNumber} from './get';
|
|
3
3
|
import './global';
|
|
4
4
|
import {type RepeatOptions, TimerTrace} from './models';
|
|
@@ -21,7 +21,7 @@ export function repeat(callback: (index: number) => void, options?: Partial<Repe
|
|
|
21
21
|
onAfter: getCallback(options?.onAfter),
|
|
22
22
|
onError: getCallback(options?.onTimeout),
|
|
23
23
|
count: getValidNumber(options?.count),
|
|
24
|
-
interval: getValidNumber(options?.interval
|
|
24
|
+
interval: getValidNumber(options?.interval),
|
|
25
25
|
timeout: getValidNumber(options?.timeout),
|
|
26
26
|
},
|
|
27
27
|
true,
|
package/src/wait.ts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import {TYPE_WAIT} from './constants';
|
|
2
2
|
import {getCallback, getValidNumber} from './get';
|
|
3
3
|
import './global';
|
|
4
4
|
import {TimerTrace} from './models';
|
|
@@ -20,7 +20,7 @@ export function wait(callback: () => void, time?: number): Timer {
|
|
|
20
20
|
onAfter: undefined,
|
|
21
21
|
onError: undefined,
|
|
22
22
|
count: -1,
|
|
23
|
-
interval: getValidNumber(time
|
|
23
|
+
interval: getValidNumber(time),
|
|
24
24
|
timeout: 0,
|
|
25
25
|
},
|
|
26
26
|
true,
|
package/src/when.ts
CHANGED
|
@@ -1,12 +1,12 @@
|
|
|
1
1
|
import {noop} from '@oscarpalmer/atoms/function';
|
|
2
|
-
import {
|
|
2
|
+
import {MESSAGE_DESTROYED, MESSAGE_STARTED, TYPE_WHEN} from './constants';
|
|
3
3
|
import {getValidNumber, getValidTimeout} from './get';
|
|
4
4
|
import './global';
|
|
5
5
|
import {TimerTrace, type WhenOptions, type WhenState} from './models';
|
|
6
6
|
import {Timer} from './timer';
|
|
7
7
|
|
|
8
8
|
class When {
|
|
9
|
-
private
|
|
9
|
+
declare private readonly $timer: string;
|
|
10
10
|
|
|
11
11
|
private readonly state: WhenState = {
|
|
12
12
|
promise: undefined as never,
|
|
@@ -90,7 +90,7 @@ class When {
|
|
|
90
90
|
this.destroy();
|
|
91
91
|
},
|
|
92
92
|
count: getValidNumber(options?.count),
|
|
93
|
-
interval: getValidNumber(options?.interval
|
|
93
|
+
interval: getValidNumber(options?.interval),
|
|
94
94
|
timeout: getValidTimeout(options?.timeout),
|
|
95
95
|
},
|
|
96
96
|
false,
|
package/src/work.ts
CHANGED
|
@@ -1,7 +1,6 @@
|
|
|
1
1
|
import {
|
|
2
2
|
TIMERS_ACTIVE,
|
|
3
3
|
BUFFER_INTERVAL,
|
|
4
|
-
FRAME_RATE_MS,
|
|
5
4
|
TYPE_WAIT,
|
|
6
5
|
WORK_CONTINUE,
|
|
7
6
|
WORK_PAUSE,
|
|
@@ -84,7 +83,7 @@ function run(
|
|
|
84
83
|
return;
|
|
85
84
|
}
|
|
86
85
|
|
|
87
|
-
if (options.interval ===
|
|
86
|
+
if (options.interval === 0 || state.elapsed >= options.interval - BUFFER_INTERVAL) {
|
|
88
87
|
if (options.count > -1) {
|
|
89
88
|
(state.callback as (index: number) => void)(state.index);
|
|
90
89
|
}
|
package/types/constants.d.ts
CHANGED
|
@@ -1,4 +1,3 @@
|
|
|
1
|
-
import FRAME_RATE_MS from '@oscarpalmer/atoms/frame-rate';
|
|
2
1
|
import type { TimerType, WorkHandlerType } from './models';
|
|
3
2
|
import type { Timer } from './timer';
|
|
4
3
|
/**
|
|
@@ -30,4 +29,3 @@ export declare const WORK_PAUSE: WorkHandlerType;
|
|
|
30
29
|
export declare const WORK_RESTART: WorkHandlerType;
|
|
31
30
|
export declare const WORK_START: WorkHandlerType;
|
|
32
31
|
export declare const WORK_STOP: WorkHandlerType;
|
|
33
|
-
export { FRAME_RATE_MS };
|
package/types/index.d.ts
CHANGED
package/dist/delay.js
DELETED
|
@@ -1,15 +0,0 @@
|
|
|
1
|
-
import { BUFFER_INTERVAL, FRAME_RATE_MS } from "./constants.js";
|
|
2
|
-
import { getValidNumber } from "./get.js";
|
|
3
|
-
function delay(time) {
|
|
4
|
-
return new Promise((resolve) => {
|
|
5
|
-
const interval = getValidNumber(time, FRAME_RATE_MS);
|
|
6
|
-
let start;
|
|
7
|
-
function step(now) {
|
|
8
|
-
start ??= now;
|
|
9
|
-
if (interval === FRAME_RATE_MS || now - start >= interval - 5) resolve();
|
|
10
|
-
else requestAnimationFrame(step);
|
|
11
|
-
}
|
|
12
|
-
requestAnimationFrame(step);
|
|
13
|
-
});
|
|
14
|
-
}
|
|
15
|
-
export { delay };
|
package/src/delay.ts
DELETED
|
@@ -1,27 +0,0 @@
|
|
|
1
|
-
import {BUFFER_INTERVAL, FRAME_RATE_MS} from './constants';
|
|
2
|
-
import {getValidNumber} from './get';
|
|
3
|
-
|
|
4
|
-
/**
|
|
5
|
-
* Create a delayed promise that resolves after a certain amount of time
|
|
6
|
-
* @param time How long to wait for _(in milliseconds; defaults to screen refresh rate)_
|
|
7
|
-
* @returns A promise that resolves after the delay
|
|
8
|
-
*/
|
|
9
|
-
export function delay(time?: number): Promise<void> {
|
|
10
|
-
return new Promise(resolve => {
|
|
11
|
-
const interval = getValidNumber(time, FRAME_RATE_MS);
|
|
12
|
-
|
|
13
|
-
let start: DOMHighResTimeStamp;
|
|
14
|
-
|
|
15
|
-
function step(now: DOMHighResTimeStamp) {
|
|
16
|
-
start ??= now;
|
|
17
|
-
|
|
18
|
-
if (interval === FRAME_RATE_MS || now - start >= interval - BUFFER_INTERVAL) {
|
|
19
|
-
resolve();
|
|
20
|
-
} else {
|
|
21
|
-
requestAnimationFrame(step);
|
|
22
|
-
}
|
|
23
|
-
}
|
|
24
|
-
|
|
25
|
-
requestAnimationFrame(step);
|
|
26
|
-
});
|
|
27
|
-
}
|
package/types/delay.d.ts
DELETED
|
@@ -1,6 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Create a delayed promise that resolves after a certain amount of time
|
|
3
|
-
* @param time How long to wait for _(in milliseconds; defaults to screen refresh rate)_
|
|
4
|
-
* @returns A promise that resolves after the delay
|
|
5
|
-
*/
|
|
6
|
-
export declare function delay(time?: number): Promise<void>;
|