@oscarpalmer/timer 0.39.0 → 0.40.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,24 @@
1
1
  import FRAME_RATE_MS from "@oscarpalmer/atoms/frame-rate";
2
+ /**
3
+ * Buffer value to use when evaluating if a specific time is within a certain range
4
+ */
2
5
  const BUFFER_INTERVAL = 5;
3
6
  const DEFAULT_TIMEOUT = 3e4;
7
+ /**
8
+ * Message to show when a when-timer is destroyed
9
+ */
4
10
  const MESSAGE_DESTROYED = "Timer has already been destroyed";
11
+ /**
12
+ * Message to show when a when-timer is started
13
+ */
5
14
  const MESSAGE_STARTED = "Timer has already been started";
15
+ /**
16
+ * A set of all active timers
17
+ */
6
18
  const TIMERS_ACTIVE = /* @__PURE__ */ new Set();
19
+ /**
20
+ * A set of timers that were paused due to the document being hidden
21
+ */
7
22
  const TIMERS_HIDDEN = /* @__PURE__ */ new Set();
8
23
  const TYPE_REPEAT = "repeat";
9
24
  const TYPE_WAIT = "wait";
package/dist/delay.js CHANGED
@@ -1,15 +1,10 @@
1
- import { BUFFER_INTERVAL, FRAME_RATE_MS } from "./constants.js";
2
1
  import { getValidNumber } from "./get.js";
2
+ /**
3
+ * Create a delayed promise that resolves after a certain amount of time
4
+ * @param time How long to wait for _(in milliseconds; defaults to screen refresh rate)_
5
+ * @returns A promise that resolves after the delay
6
+ */
3
7
  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
- });
8
+ return new Promise((resolve) => setTimeout(resolve, getValidNumber(time)));
14
9
  }
15
10
  export { delay };
package/dist/is.js CHANGED
@@ -2,15 +2,35 @@ import { TYPE_REPEAT, TYPE_WAIT, TYPE_WHEN } 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
@@ -3,6 +3,12 @@ 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),
@@ -19,11 +19,26 @@ calculate().then((value) => {
19
19
  FRAME_RATE_MS = value;
20
20
  });
21
21
  var frame_rate_default = FRAME_RATE_MS;
22
+ /**
23
+ * Buffer value to use when evaluating if a specific time is within a certain range
24
+ */
22
25
  const BUFFER_INTERVAL = 5;
23
26
  const DEFAULT_TIMEOUT = 3e4;
27
+ /**
28
+ * Message to show when a when-timer is destroyed
29
+ */
24
30
  const MESSAGE_DESTROYED = "Timer has already been destroyed";
31
+ /**
32
+ * Message to show when a when-timer is started
33
+ */
25
34
  const MESSAGE_STARTED = "Timer has already been started";
35
+ /**
36
+ * A set of all active timers
37
+ */
26
38
  const TIMERS_ACTIVE = /* @__PURE__ */ new Set();
39
+ /**
40
+ * A set of timers that were paused due to the document being hidden
41
+ */
27
42
  const TIMERS_HIDDEN = /* @__PURE__ */ new Set();
28
43
  const TYPE_REPEAT = "repeat";
29
44
  const TYPE_WAIT = "wait";
@@ -71,30 +86,46 @@ function getValidNumber(value, defaultValue) {
71
86
  const actualDefault = defaultValue ?? 0;
72
87
  return typeof value === "number" && value > actualDefault ? value : actualDefault;
73
88
  }
89
+ /**
90
+ * Create a delayed promise that resolves after a certain amount of time
91
+ * @param time How long to wait for _(in milliseconds; defaults to screen refresh rate)_
92
+ * @returns A promise that resolves after the delay
93
+ */
74
94
  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);
84
- });
95
+ return new Promise((resolve) => setTimeout(resolve, getValidNumber(time)));
85
96
  }
86
97
  function is(names, value) {
87
98
  return names.includes(value?.$timer);
88
99
  }
100
+ /**
101
+ * Is the value a repeating timer?
102
+ * @param value Value to check
103
+ * @returns `true` if the value is a repeating timer
104
+ */
89
105
  function isRepeated(value) {
90
106
  return is([TYPE_REPEAT], value);
91
107
  }
108
+ /**
109
+ * Is the value a timer?
110
+ * @param value Value to check
111
+ * @returns `true` if the value is a timer
112
+ */
92
113
  function isTimer(value) {
93
114
  return is([TYPE_REPEAT, TYPE_WAIT], value);
94
115
  }
116
+ /**
117
+ * Is the value a waiting timer?
118
+ * @param value Value to check
119
+ * @returns `true` if the value is a waiting timer
120
+ */
95
121
  function isWaited(value) {
96
122
  return is([TYPE_WAIT], value);
97
123
  }
124
+ /**
125
+ * Is the value a conditional timer?
126
+ * @param value Value to check
127
+ * @returns `true` if the value is a conditional timer
128
+ */
98
129
  function isWhen(value) {
99
130
  return is([TYPE_WHEN], value) && typeof value.then === "function";
100
131
  }
@@ -185,15 +216,27 @@ function work(type, timer, state, options) {
185
216
  }
186
217
  var Timer = class {
187
218
  state;
219
+ /**
220
+ * Is the timer active?
221
+ */
188
222
  get active() {
189
223
  return this.state.active;
190
224
  }
225
+ /**
226
+ * Is the timer destroyed?
227
+ */
191
228
  get destroyed() {
192
229
  return this.state.destroyed;
193
230
  }
231
+ /**
232
+ * Is the timer paused?
233
+ */
194
234
  get paused() {
195
235
  return this.state.paused;
196
236
  }
237
+ /**
238
+ * Get the timer's origin _(if debugging is enabled)_
239
+ */
197
240
  get trace() {
198
241
  return globalThis._oscarpalmer_timer_debug ?? false ? this.state.trace : void 0;
199
242
  }
@@ -212,9 +255,15 @@ var Timer = class {
212
255
  };
213
256
  if (start) this.start();
214
257
  }
258
+ /**
259
+ * Continue running the timer _(if it's paused)_
260
+ */
215
261
  continue() {
216
262
  return this.#work(WORK_CONTINUE);
217
263
  }
264
+ /**
265
+ * Destroy the timer
266
+ */
218
267
  destroy() {
219
268
  this.state.destroyed = true;
220
269
  this.options.onAfter = noop;
@@ -226,15 +275,27 @@ var Timer = class {
226
275
  type: this.$timer
227
276
  }, this.state, this.options);
228
277
  }
278
+ /**
279
+ * Pause the timer _(if it's running)_
280
+ */
229
281
  pause() {
230
282
  return this.#work(WORK_PAUSE);
231
283
  }
284
+ /**
285
+ * Restart the timer _(or start it, if it's not running)_
286
+ */
232
287
  restart() {
233
288
  return this.#work(WORK_RESTART);
234
289
  }
290
+ /**
291
+ * Start the timer _(if it's not running)_
292
+ */
235
293
  start() {
236
294
  return this.#work(WORK_START);
237
295
  }
296
+ /**
297
+ * Stop the timer _(if it's running)_
298
+ */
238
299
  stop() {
239
300
  return this.#work(WORK_STOP);
240
301
  }
@@ -245,6 +306,12 @@ var Timer = class {
245
306
  }, this.state, this.options);
246
307
  }
247
308
  };
309
+ /**
310
+ * Create a repeating timer
311
+ * @param callback Callback to run on each interval
312
+ * @param options Timer options
313
+ * @returns Timer instance
314
+ */
248
315
  function repeat(callback, options) {
249
316
  return new Timer(TYPE_REPEAT, {
250
317
  callback: getCallback(callback),
@@ -257,6 +324,11 @@ function repeat(callback, options) {
257
324
  timeout: getValidNumber(options?.timeout)
258
325
  }, true);
259
326
  }
327
+ /**
328
+ * Create a waiting timer
329
+ * @param callback Callback to run when the timer has finished
330
+ * @param time How long to wait for _(in milliseconds; defaults to screen refresh rate)_
331
+ */
260
332
  function wait(callback, time) {
261
333
  return new Timer(TYPE_WAIT, {
262
334
  callback: getCallback(callback),
@@ -277,15 +349,27 @@ var When = class {
277
349
  started: false,
278
350
  timer: void 0
279
351
  };
352
+ /**
353
+ * Is the timer active?
354
+ */
280
355
  get active() {
281
356
  return this.state.timer?.active ?? false;
282
357
  }
358
+ /**
359
+ * Is the timer destroyed?
360
+ */
283
361
  get destroyed() {
284
362
  return this.state.timer == null;
285
363
  }
364
+ /**
365
+ * Is the timer paused?
366
+ */
286
367
  get paused() {
287
368
  return this.state.timer?.paused ?? false;
288
369
  }
370
+ /**
371
+ * Get the timer's origin _(if debugging is enabled)_
372
+ */
289
373
  get trace() {
290
374
  return globalThis._oscarpalmer_timer_debug ?? false ? this.state.timer?.trace : void 0;
291
375
  }
@@ -324,10 +408,16 @@ var When = class {
324
408
  timeout: getValidTimeout(options?.timeout)
325
409
  }, false);
326
410
  }
411
+ /**
412
+ * Continues the timer _(if it was paused)_
413
+ */
327
414
  continue() {
328
415
  this.state.timer?.continue();
329
416
  return this;
330
417
  }
418
+ /**
419
+ * Destroys the timer _(and stops it,if it was running)_
420
+ */
331
421
  destroy() {
332
422
  const { state } = this;
333
423
  state.timer?.destroy();
@@ -336,10 +426,19 @@ var When = class {
336
426
  state.rejecter = noop;
337
427
  state.timer = void 0;
338
428
  }
429
+ /**
430
+ * Pauses the timer _(if it was running)_
431
+ */
339
432
  pause() {
340
433
  this.state.timer?.pause();
341
434
  return this;
342
435
  }
436
+ /**
437
+ * Start the timer
438
+ * @param resolve Optional resolve callback
439
+ * @param reject Optional reject callback
440
+ * @returns Promise that resolves when the condition is met
441
+ */
343
442
  start(resolve, reject) {
344
443
  const { state } = this;
345
444
  if (state.timer == null) throw new Error(MESSAGE_DESTROYED);
@@ -348,14 +447,30 @@ var When = class {
348
447
  state.timer.start();
349
448
  return state.promise.then(resolve ?? noop, reject ?? noop);
350
449
  }
450
+ /**
451
+ * Stops the timer _(if it was running)_
452
+ */
351
453
  stop() {
352
454
  this.state.timer?.stop();
353
455
  return this;
354
456
  }
457
+ /**
458
+ * Start the timer
459
+ * @deprecated Use `start()` instead
460
+ * @param resolve Optional resolve callback
461
+ * @param reject Optional reject callback
462
+ * @returns Promise that resolves when the condition is met
463
+ */
355
464
  then(resolve, reject) {
356
465
  return this.start(resolve, reject);
357
466
  }
358
467
  };
468
+ /**
469
+ * Create a conditional timer
470
+ * @param condition Condition to check
471
+ * @param options Timer options
472
+ * @returns Timer instance
473
+ */
359
474
  function when(condition, options) {
360
475
  return new When(condition, options);
361
476
  }
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
@@ -3,6 +3,11 @@ 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),
package/dist/when.js CHANGED
@@ -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
  }
@@ -59,10 +71,16 @@ var When = class {
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/package.json CHANGED
@@ -8,15 +8,15 @@
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.2",
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.33",
15
+ "oxlint": "^1.48",
16
+ "rolldown": "1.0.0-rc.4",
17
17
  "tslib": "^2.8",
18
18
  "typescript": "^5.9",
19
- "vite": "8.0.0-beta.2",
19
+ "vite": "8.0.0-beta.14",
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.40.0"
74
74
  }
package/src/delay.ts CHANGED
@@ -1,4 +1,3 @@
1
- import {BUFFER_INTERVAL, FRAME_RATE_MS} from './constants';
2
1
  import {getValidNumber} from './get';
3
2
 
4
3
  /**
@@ -7,21 +6,5 @@ import {getValidNumber} from './get';
7
6
  * @returns A promise that resolves after the delay
8
7
  */
9
8
  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
- });
9
+ return new Promise(resolve => setTimeout(resolve, getValidNumber(time)));
27
10
  }
package/src/when.ts CHANGED
@@ -6,7 +6,7 @@ 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,