@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 CHANGED
@@ -1,9 +1,23 @@
1
- import FRAME_RATE_MS from "@oscarpalmer/atoms/frame-rate";
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, FRAME_RATE_MS, MESSAGE_DESTROYED, MESSAGE_STARTED, TIMERS_ACTIVE, TIMERS_HIDDEN, TYPE_REPEAT, TYPE_WAIT, TYPE_WHEN, WORK_CONTINUE, WORK_PAUSE, WORK_RESTART, WORK_START, WORK_STOP };
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, TYPE_WHEN } from "./constants.js";
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 { FRAME_RATE_MS, TYPE_REPEAT } from "./constants.js";
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, FRAME_RATE_MS),
20
+ interval: getValidNumber(options?.interval),
15
21
  timeout: getValidNumber(options?.timeout)
16
22
  }, true);
17
23
  }
@@ -1,29 +1,23 @@
1
- function calculate() {
2
- return new Promise((resolve) => {
3
- const values = [];
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
- function noop() {}
51
- new Set([
52
- Int8Array,
53
- Uint8Array,
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 getValidTimeout(value) {
68
- return typeof value === "number" && value > 0 ? value : DEFAULT_TIMEOUT;
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 getValidNumber(value, defaultValue) {
71
- const actualDefault = defaultValue ?? 0;
72
- return typeof value === "number" && value > actualDefault ? value : actualDefault;
61
+ function settlePromise(aborter, settler, value, signal) {
62
+ signal?.removeEventListener(PROMISE_EVENT_NAME, aborter);
63
+ settler(value);
73
64
  }
74
- function delay(time) {
75
- return new Promise((resolve) => {
76
- const interval = getValidNumber(time, frame_rate_default);
77
- let start;
78
- function step(now) {
79
- start ??= now;
80
- if (interval === frame_rate_default || now - start >= interval - BUFFER_INTERVAL) resolve();
81
- else requestAnimationFrame(step);
82
- }
83
- requestAnimationFrame(step);
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 === frame_rate_default || state.elapsed >= options.interval - BUFFER_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, frame_rate_default),
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, frame_rate_default),
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, frame_rate_default),
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 { FRAME_RATE_MS, TYPE_WAIT } from "./constants.js";
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, FRAME_RATE_MS),
19
+ interval: getValidNumber(time),
15
20
  timeout: 0
16
21
  }, true);
17
22
  }
package/dist/when.js CHANGED
@@ -1,4 +1,4 @@
1
- import { FRAME_RATE_MS, MESSAGE_DESTROYED, MESSAGE_STARTED, TYPE_WHEN } from "./constants.js";
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, FRAME_RATE_MS),
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 { BUFFER_INTERVAL, FRAME_RATE_MS, TIMERS_ACTIVE, TYPE_WAIT, WORK_CONTINUE, WORK_PAUSE, WORK_RESTART, WORK_START, WORK_STOP } from "./constants.js";
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 === FRAME_RATE_MS || state.elapsed >= options.interval - 5) {
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.117"
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": "^27.3",
14
- "oxfmt": "^0.19",
15
- "oxlint": "^1.34",
16
- "rolldown": "1.0.0-beta.55",
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.2",
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.39.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
@@ -1,6 +1,6 @@
1
1
  import './global';
2
2
 
3
- export * from './delay';
3
+ export {delay} from '@oscarpalmer/atoms/promise';
4
4
  export {isRepeated, isTimer, isWaited, isWhen} from './is';
5
5
  export * from './repeat';
6
6
  export type {Timer} from './timer';
package/src/repeat.ts CHANGED
@@ -1,4 +1,4 @@
1
- import {FRAME_RATE_MS, TYPE_REPEAT} from './constants';
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, FRAME_RATE_MS),
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 {FRAME_RATE_MS, TYPE_WAIT} from './constants';
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, FRAME_RATE_MS),
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 {FRAME_RATE_MS, MESSAGE_DESTROYED, MESSAGE_STARTED, TYPE_WHEN} from './constants';
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 declare readonly $timer: string;
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, FRAME_RATE_MS),
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 === FRAME_RATE_MS || state.elapsed >= options.interval - BUFFER_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
  }
@@ -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
@@ -1,5 +1,5 @@
1
1
  import './global';
2
- export * from './delay';
2
+ export { delay } from '@oscarpalmer/atoms/promise';
3
3
  export { isRepeated, isTimer, isWaited, isWhen } from './is';
4
4
  export * from './repeat';
5
5
  export type { Timer } from './timer';
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>;