@oscarpalmer/timer 0.38.1 → 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,21 +1,24 @@
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 >= 10) resolve(values.sort().slice(2, -2).reduce((first, second) => first + second, 0) / (values.length - 4));
9
- else requestAnimationFrame(step);
10
- }
11
- requestAnimationFrame(step);
12
- });
13
- }
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
+ */
14
5
  const BUFFER_INTERVAL = 5;
15
6
  const DEFAULT_TIMEOUT = 3e4;
7
+ /**
8
+ * Message to show when a when-timer is destroyed
9
+ */
16
10
  const MESSAGE_DESTROYED = "Timer has already been destroyed";
11
+ /**
12
+ * Message to show when a when-timer is started
13
+ */
17
14
  const MESSAGE_STARTED = "Timer has already been started";
15
+ /**
16
+ * A set of all active timers
17
+ */
18
18
  const TIMERS_ACTIVE = /* @__PURE__ */ new Set();
19
+ /**
20
+ * A set of timers that were paused due to the document being hidden
21
+ */
19
22
  const TIMERS_HIDDEN = /* @__PURE__ */ new Set();
20
23
  const TYPE_REPEAT = "repeat";
21
24
  const TYPE_WAIT = "wait";
@@ -25,8 +28,4 @@ const WORK_PAUSE = "pause";
25
28
  const WORK_RESTART = "restart";
26
29
  const WORK_START = "start";
27
30
  const WORK_STOP = "stop";
28
- let MILLISECONDS = 1e3 / 60;
29
- calculate().then((value) => {
30
- MILLISECONDS = value;
31
- });
32
- export { BUFFER_INTERVAL, DEFAULT_TIMEOUT, MESSAGE_DESTROYED, MESSAGE_STARTED, MILLISECONDS, TIMERS_ACTIVE, TIMERS_HIDDEN, TYPE_REPEAT, TYPE_WAIT, TYPE_WHEN, WORK_CONTINUE, WORK_PAUSE, WORK_RESTART, WORK_START, WORK_STOP };
31
+ 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 };
package/dist/delay.js CHANGED
@@ -1,15 +1,10 @@
1
- import { BUFFER_INTERVAL, MILLISECONDS } 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, MILLISECONDS);
6
- let start;
7
- function step(now) {
8
- start ??= now;
9
- if (interval === MILLISECONDS || 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
@@ -1,8 +1,14 @@
1
- import { MILLISECONDS, TYPE_REPEAT } from "./constants.js";
1
+ import { FRAME_RATE_MS, 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, MILLISECONDS),
20
+ interval: getValidNumber(options?.interval, FRAME_RATE_MS),
15
21
  timeout: getValidNumber(options?.timeout)
16
22
  }, true);
17
23
  }
@@ -1,16 +1,24 @@
1
- function calculate$1() {
1
+ function calculate() {
2
2
  return new Promise((resolve) => {
3
3
  const values = [];
4
4
  let last;
5
5
  function step(now) {
6
6
  if (last != null) values.push(now - last);
7
7
  last = now;
8
- if (values.length >= 10) resolve(values.sort().slice(2, -2).reduce((first, second) => first + second, 0) / (values.length - 4));
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
9
  else requestAnimationFrame(step);
10
10
  }
11
11
  requestAnimationFrame(step);
12
12
  });
13
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;
14
22
  /**
15
23
  * Buffer value to use when evaluating if a specific time is within a certain range
16
24
  */
@@ -40,14 +48,6 @@ const WORK_PAUSE = "pause";
40
48
  const WORK_RESTART = "restart";
41
49
  const WORK_START = "start";
42
50
  const WORK_STOP = "stop";
43
- /**
44
- * A calculated average of the refresh rate of the display _(in milliseconds)_
45
- */
46
- let MILLISECONDS = 1e3 / 60;
47
- calculate$1().then((value) => {
48
- MILLISECONDS = value;
49
- });
50
-
51
51
  if (globalThis._oscarpalmer_timers == null) Object.defineProperty(globalThis, "_oscarpalmer_timers", { get() {
52
52
  return globalThis._oscarpalmer_timer_debug ? [...TIMERS_ACTIVE] : [];
53
53
  } });
@@ -62,29 +62,8 @@ document.addEventListener("visibilitychange", () => {
62
62
  }
63
63
  from.clear();
64
64
  });
65
-
66
- function calculate() {
67
- return new Promise((resolve) => {
68
- const values = [];
69
- let last;
70
- function step(now) {
71
- if (last != null) values.push(now - last);
72
- last = now;
73
- if (values.length >= CALCULATION_TOTAL) resolve(values.sort().slice(2, -2).reduce((first, second) => first + second, 0) / (values.length - CALCULATION_TRIM));
74
- else requestAnimationFrame(step);
75
- }
76
- requestAnimationFrame(step);
77
- });
78
- }
79
65
  function noop() {}
80
- var CALCULATION_TOTAL = 10;
81
- var CALCULATION_TRIM = 4;
82
- let milliseconds = 1e3 / 60;
83
- calculate().then((value) => {
84
- milliseconds = value;
85
- });
86
-
87
- var TYPED_ARRAYS = new Set([
66
+ new Set([
88
67
  Int8Array,
89
68
  Uint8Array,
90
69
  Uint8ClampedArray,
@@ -97,7 +76,6 @@ var TYPED_ARRAYS = new Set([
97
76
  BigInt64Array,
98
77
  BigUint64Array
99
78
  ]);
100
-
101
79
  function getCallback(value) {
102
80
  return typeof value === "function" ? value : noop;
103
81
  }
@@ -108,25 +86,14 @@ function getValidNumber(value, defaultValue) {
108
86
  const actualDefault = defaultValue ?? 0;
109
87
  return typeof value === "number" && value > actualDefault ? value : actualDefault;
110
88
  }
111
-
112
89
  /**
113
90
  * Create a delayed promise that resolves after a certain amount of time
114
91
  * @param time How long to wait for _(in milliseconds; defaults to screen refresh rate)_
115
92
  * @returns A promise that resolves after the delay
116
93
  */
117
94
  function delay(time) {
118
- return new Promise((resolve) => {
119
- const interval = getValidNumber(time, MILLISECONDS);
120
- let start;
121
- function step(now) {
122
- start ??= now;
123
- if (interval === MILLISECONDS || now - start >= interval - BUFFER_INTERVAL) resolve();
124
- else requestAnimationFrame(step);
125
- }
126
- requestAnimationFrame(step);
127
- });
95
+ return new Promise((resolve) => setTimeout(resolve, getValidNumber(time)));
128
96
  }
129
-
130
97
  function is(names, value) {
131
98
  return names.includes(value?.$timer);
132
99
  }
@@ -162,14 +129,12 @@ function isWaited(value) {
162
129
  function isWhen(value) {
163
130
  return is([TYPE_WHEN], value) && typeof value.then === "function";
164
131
  }
165
-
166
132
  var TimerTrace = class extends Error {
167
133
  constructor() {
168
134
  super();
169
135
  this.name = "TimerTrace";
170
136
  }
171
137
  };
172
-
173
138
  function finish(timer, state, options, success) {
174
139
  cancelAnimationFrame(state.frame);
175
140
  TIMERS_ACTIVE.delete(timer.instance);
@@ -205,7 +170,7 @@ function run(timer, state, options) {
205
170
  finish(timer, state, options, false);
206
171
  return;
207
172
  }
208
- if (options.interval === MILLISECONDS || state.elapsed >= options.interval - BUFFER_INTERVAL) {
173
+ if (options.interval === frame_rate_default || state.elapsed >= options.interval - BUFFER_INTERVAL) {
209
174
  if (options.count > -1) state.callback(state.index);
210
175
  start = now;
211
176
  state.elapsed = 0;
@@ -249,7 +214,6 @@ function work(type, timer, state, options) {
249
214
  state.frame = requestAnimationFrame(runner);
250
215
  return timer.instance;
251
216
  }
252
-
253
217
  var Timer = class {
254
218
  state;
255
219
  /**
@@ -278,7 +242,7 @@ var Timer = class {
278
242
  }
279
243
  constructor(type, state, options, start) {
280
244
  this.options = options;
281
- this.$timer = type;
245
+ Object.defineProperty(this, "$timer", { value: type });
282
246
  this.state = {
283
247
  ...state,
284
248
  active: false,
@@ -342,7 +306,6 @@ var Timer = class {
342
306
  }, this.state, this.options);
343
307
  }
344
308
  };
345
-
346
309
  /**
347
310
  * Create a repeating timer
348
311
  * @param callback Callback to run on each interval
@@ -357,11 +320,10 @@ function repeat(callback, options) {
357
320
  onAfter: getCallback(options?.onAfter),
358
321
  onError: getCallback(options?.onTimeout),
359
322
  count: getValidNumber(options?.count),
360
- interval: getValidNumber(options?.interval, MILLISECONDS),
323
+ interval: getValidNumber(options?.interval, frame_rate_default),
361
324
  timeout: getValidNumber(options?.timeout)
362
325
  }, true);
363
326
  }
364
-
365
327
  /**
366
328
  * Create a waiting timer
367
329
  * @param callback Callback to run when the timer has finished
@@ -375,13 +337,11 @@ function wait(callback, time) {
375
337
  onAfter: void 0,
376
338
  onError: void 0,
377
339
  count: -1,
378
- interval: getValidNumber(time, MILLISECONDS),
340
+ interval: getValidNumber(time, frame_rate_default),
379
341
  timeout: 0
380
342
  }, true);
381
343
  }
382
-
383
344
  var When = class {
384
- $timer = TYPE_WHEN;
385
345
  state = {
386
346
  promise: void 0,
387
347
  rejecter: void 0,
@@ -414,6 +374,7 @@ var When = class {
414
374
  return globalThis._oscarpalmer_timer_debug ?? false ? this.state.timer?.trace : void 0;
415
375
  }
416
376
  constructor(condition, options) {
377
+ Object.defineProperty(this, "$timer", { value: TYPE_WHEN });
417
378
  const { state } = this;
418
379
  state.promise = new Promise((resolve, reject) => {
419
380
  state.resolver = resolve;
@@ -443,7 +404,7 @@ var When = class {
443
404
  this.destroy();
444
405
  },
445
406
  count: getValidNumber(options?.count),
446
- interval: getValidNumber(options?.interval, MILLISECONDS),
407
+ interval: getValidNumber(options?.interval, frame_rate_default),
447
408
  timeout: getValidTimeout(options?.timeout)
448
409
  }, false);
449
410
  }
@@ -513,5 +474,4 @@ var When = class {
513
474
  function when(condition, options) {
514
475
  return new When(condition, options);
515
476
  }
516
-
517
- export { delay, isRepeated, isTimer, isWaited, isWhen, repeat, wait, when };
477
+ export { delay, isRepeated, isTimer, isWaited, isWhen, repeat, wait, when };
package/dist/timer.js CHANGED
@@ -3,21 +3,33 @@ 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
  }
18
30
  constructor(type, state, options, start) {
19
31
  this.options = options;
20
- this.$timer = type;
32
+ Object.defineProperty(this, "$timer", { value: type });
21
33
  this.state = {
22
34
  ...state,
23
35
  active: false,
@@ -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 { MILLISECONDS, TYPE_WAIT } from "./constants.js";
1
+ import { FRAME_RATE_MS, 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, MILLISECONDS),
19
+ interval: getValidNumber(time, FRAME_RATE_MS),
15
20
  timeout: 0
16
21
  }, true);
17
22
  }
package/dist/when.js CHANGED
@@ -1,11 +1,10 @@
1
- import { MESSAGE_DESTROYED, MESSAGE_STARTED, MILLISECONDS, TYPE_WHEN } from "./constants.js";
1
+ import { FRAME_RATE_MS, 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";
5
5
  import { Timer } from "./timer.js";
6
6
  import { noop } from "@oscarpalmer/atoms/function";
7
7
  var When = class {
8
- $timer = TYPE_WHEN;
9
8
  state = {
10
9
  promise: void 0,
11
10
  rejecter: void 0,
@@ -13,19 +12,32 @@ var When = class {
13
12
  started: false,
14
13
  timer: void 0
15
14
  };
15
+ /**
16
+ * Is the timer active?
17
+ */
16
18
  get active() {
17
19
  return this.state.timer?.active ?? false;
18
20
  }
21
+ /**
22
+ * Is the timer destroyed?
23
+ */
19
24
  get destroyed() {
20
25
  return this.state.timer == null;
21
26
  }
27
+ /**
28
+ * Is the timer paused?
29
+ */
22
30
  get paused() {
23
31
  return this.state.timer?.paused ?? false;
24
32
  }
33
+ /**
34
+ * Get the timer's origin _(if debugging is enabled)_
35
+ */
25
36
  get trace() {
26
37
  return globalThis._oscarpalmer_timer_debug ?? false ? this.state.timer?.trace : void 0;
27
38
  }
28
39
  constructor(condition, options) {
40
+ Object.defineProperty(this, "$timer", { value: TYPE_WHEN });
29
41
  const { state } = this;
30
42
  state.promise = new Promise((resolve, reject) => {
31
43
  state.resolver = resolve;
@@ -55,14 +67,20 @@ var When = class {
55
67
  this.destroy();
56
68
  },
57
69
  count: getValidNumber(options?.count),
58
- interval: getValidNumber(options?.interval, MILLISECONDS),
70
+ interval: getValidNumber(options?.interval, FRAME_RATE_MS),
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, MILLISECONDS, TIMERS_ACTIVE, TYPE_WAIT, WORK_CONTINUE, WORK_PAUSE, WORK_RESTART, WORK_START, WORK_STOP } from "./constants.js";
1
+ import { BUFFER_INTERVAL, FRAME_RATE_MS, TIMERS_ACTIVE, TYPE_WAIT, WORK_CONTINUE, WORK_PAUSE, WORK_RESTART, WORK_START, 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 === MILLISECONDS || state.elapsed >= options.interval - 5) {
37
+ if (options.interval === FRAME_RATE_MS || 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.115"
7
+ "@oscarpalmer/atoms": "^0.117"
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.18",
15
- "oxlint": "^1.33",
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": {
@@ -64,11 +64,11 @@
64
64
  "build": "npm run clean && npx vite build && npm run rolldown:build && npx tsc",
65
65
  "clean": "rm -rf ./dist && rm -rf ./types && rm -f ./tsconfig.tsbuildinfo",
66
66
  "rolldown:build": "npx rolldown -c",
67
- "rolldown:watch": "npx rolldown -c --watch",
67
+ "rolldown:watch": "npx rolldown -c ./rolldown.config.js --watch",
68
68
  "test": "npx vitest --coverage",
69
69
  "watch": "npx vite build --watch"
70
70
  },
71
71
  "type": "module",
72
72
  "types": "types/index.d.ts",
73
- "version": "0.38.1"
73
+ "version": "0.40.0"
74
74
  }
package/src/constants.ts CHANGED
@@ -1,39 +1,7 @@
1
+ import FRAME_RATE_MS from '@oscarpalmer/atoms/frame-rate';
1
2
  import type {TimerType, WorkHandlerType} from './models';
2
3
  import type {Timer} from './timer';
3
4
 
4
- function calculate(): Promise<number> {
5
- return new Promise(resolve => {
6
- const values: number[] = [];
7
-
8
- let last: DOMHighResTimeStamp | undefined;
9
-
10
- function step(now: DOMHighResTimeStamp): void {
11
- if (last != null) {
12
- values.push(now - last);
13
- }
14
-
15
- last = now;
16
-
17
- if (values.length >= 10) {
18
- const median =
19
- values
20
- .sort()
21
- .slice(2, -2)
22
- .reduce((first, second) => first + second, 0) /
23
- (values.length - 4);
24
-
25
- resolve(median);
26
- } else {
27
- requestAnimationFrame(step);
28
- }
29
- }
30
-
31
- requestAnimationFrame(step);
32
- });
33
- }
34
-
35
- //
36
-
37
5
  /**
38
6
  * Buffer value to use when evaluating if a specific time is within a certain range
39
7
  */
@@ -77,13 +45,4 @@ export const WORK_START: WorkHandlerType = 'start';
77
45
 
78
46
  export const WORK_STOP: WorkHandlerType = 'stop';
79
47
 
80
- //
81
-
82
- /**
83
- * A calculated average of the refresh rate of the display _(in milliseconds)_
84
- */
85
- export let MILLISECONDS = 1000 / 60;
86
-
87
- calculate().then(value => {
88
- MILLISECONDS = value;
89
- });
48
+ export {FRAME_RATE_MS};
package/src/delay.ts CHANGED
@@ -1,4 +1,3 @@
1
- import {BUFFER_INTERVAL, MILLISECONDS} 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, MILLISECONDS);
12
-
13
- let start: DOMHighResTimeStamp;
14
-
15
- function step(now: DOMHighResTimeStamp) {
16
- start ??= now;
17
-
18
- if (interval === MILLISECONDS || 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/repeat.ts CHANGED
@@ -1,4 +1,4 @@
1
- import {MILLISECONDS, TYPE_REPEAT} from './constants';
1
+ import {FRAME_RATE_MS, 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, MILLISECONDS),
24
+ interval: getValidNumber(options?.interval, FRAME_RATE_MS),
25
25
  timeout: getValidNumber(options?.timeout),
26
26
  },
27
27
  true,
package/src/timer.ts CHANGED
@@ -42,7 +42,9 @@ export class Timer {
42
42
  protected readonly options: TimerOptions,
43
43
  start: boolean,
44
44
  ) {
45
- this.$timer = type;
45
+ Object.defineProperty(this, '$timer', {
46
+ value: type,
47
+ });
46
48
 
47
49
  this.state = {
48
50
  ...state,
package/src/wait.ts CHANGED
@@ -1,4 +1,4 @@
1
- import {MILLISECONDS, TYPE_WAIT} from './constants';
1
+ import {FRAME_RATE_MS, 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, MILLISECONDS),
23
+ interval: getValidNumber(time, FRAME_RATE_MS),
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 {MESSAGE_DESTROYED, MILLISECONDS, MESSAGE_STARTED, TYPE_WHEN} from './constants';
2
+ import {FRAME_RATE_MS, 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 readonly $timer = TYPE_WHEN;
9
+ declare private readonly $timer: string;
10
10
 
11
11
  private readonly state: WhenState = {
12
12
  promise: undefined as never,
@@ -45,6 +45,10 @@ class When {
45
45
  }
46
46
 
47
47
  constructor(condition: () => boolean, options?: Partial<WhenOptions>) {
48
+ Object.defineProperty(this, '$timer', {
49
+ value: TYPE_WHEN,
50
+ });
51
+
48
52
  const {state} = this;
49
53
 
50
54
  state.promise = new Promise<void>((resolve, reject) => {
@@ -86,7 +90,7 @@ class When {
86
90
  this.destroy();
87
91
  },
88
92
  count: getValidNumber(options?.count),
89
- interval: getValidNumber(options?.interval, MILLISECONDS),
93
+ interval: getValidNumber(options?.interval, FRAME_RATE_MS),
90
94
  timeout: getValidTimeout(options?.timeout),
91
95
  },
92
96
  false,
package/src/work.ts CHANGED
@@ -1,7 +1,7 @@
1
1
  import {
2
2
  TIMERS_ACTIVE,
3
3
  BUFFER_INTERVAL,
4
- MILLISECONDS,
4
+ FRAME_RATE_MS,
5
5
  TYPE_WAIT,
6
6
  WORK_CONTINUE,
7
7
  WORK_PAUSE,
@@ -84,7 +84,7 @@ function run(
84
84
  return;
85
85
  }
86
86
 
87
- if (options.interval === MILLISECONDS || state.elapsed >= options.interval - BUFFER_INTERVAL) {
87
+ if (options.interval === FRAME_RATE_MS || state.elapsed >= options.interval - BUFFER_INTERVAL) {
88
88
  if (options.count > -1) {
89
89
  (state.callback as (index: number) => void)(state.index);
90
90
  }
@@ -1,3 +1,4 @@
1
+ import FRAME_RATE_MS from '@oscarpalmer/atoms/frame-rate';
1
2
  import type { TimerType, WorkHandlerType } from './models';
2
3
  import type { Timer } from './timer';
3
4
  /**
@@ -29,7 +30,4 @@ export declare const WORK_PAUSE: WorkHandlerType;
29
30
  export declare const WORK_RESTART: WorkHandlerType;
30
31
  export declare const WORK_START: WorkHandlerType;
31
32
  export declare const WORK_STOP: WorkHandlerType;
32
- /**
33
- * A calculated average of the refresh rate of the display _(in milliseconds)_
34
- */
35
- export declare let MILLISECONDS: number;
33
+ export { FRAME_RATE_MS };