@oscarpalmer/timer 0.18.0 → 0.19.0

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