@oscarpalmer/timer 0.22.0 → 0.23.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,19 @@
1
1
  // src/constants.ts
2
2
  var activeTimers = new Set;
3
+ var beginTypes = new Set(["continue", "start"]);
4
+ var endTypes = new Set(["pause", "stop"]);
5
+ var endOrRestartTypes = new Set([
6
+ "pause",
7
+ "restart",
8
+ "stop"
9
+ ]);
3
10
  var hiddenTimers = new Set;
4
11
  var milliseconds = 1000 / 60;
5
12
  export {
6
13
  milliseconds,
7
14
  hiddenTimers,
15
+ endTypes,
16
+ endOrRestartTypes,
17
+ beginTypes,
8
18
  activeTimers
9
19
  };
@@ -1,9 +1,19 @@
1
1
  // src/constants.ts
2
2
  var activeTimers = new Set;
3
+ var beginTypes = new Set(["continue", "start"]);
4
+ var endTypes = new Set(["pause", "stop"]);
5
+ var endOrRestartTypes = new Set([
6
+ "pause",
7
+ "restart",
8
+ "stop"
9
+ ]);
3
10
  var hiddenTimers = new Set;
4
11
  var milliseconds = 1000 / 60;
5
12
  export {
6
13
  milliseconds,
7
14
  hiddenTimers,
15
+ endTypes,
16
+ endOrRestartTypes,
17
+ beginTypes,
8
18
  activeTimers
9
19
  };
package/dist/functions.js CHANGED
@@ -1,9 +1,23 @@
1
1
  // src/constants.ts
2
2
  var activeTimers = new Set;
3
+ var beginTypes = new Set(["continue", "start"]);
4
+ var endTypes = new Set(["pause", "stop"]);
5
+ var endOrRestartTypes = new Set([
6
+ "pause",
7
+ "restart",
8
+ "stop"
9
+ ]);
3
10
  var hiddenTimers = new Set;
4
11
  var milliseconds = 1000 / 60;
5
12
 
6
13
  // src/functions.ts
14
+ function destroyWhen(state) {
15
+ state.timer?.destroy();
16
+ state.promise = undefined;
17
+ state.rejecter = undefined;
18
+ state.resolver = undefined;
19
+ state.timer = undefined;
20
+ }
7
21
  function getOptions(options, isRepeated) {
8
22
  return {
9
23
  afterCallback: options.afterCallback,
@@ -17,12 +31,12 @@ function getValueOrDefault(value, defaultValue, minimum) {
17
31
  return typeof value === "number" && value > (minimum ?? 0) ? value : defaultValue;
18
32
  }
19
33
  function work(type, timer, state, options) {
20
- if (["continue", "start"].includes(type) && state.active || ["pause", "stop"].includes(type) && !state.active) {
34
+ if (state.destroyed && type !== "stop" || beginTypes.has(type) && state.active || endTypes.has(type) && !state.active) {
21
35
  return timer;
22
36
  }
23
37
  const { count, interval, timeout } = options;
24
38
  const { isRepeated, minimum } = state;
25
- if (["pause", "restart", "stop"].includes(type)) {
39
+ if (endOrRestartTypes.has(type)) {
26
40
  const isStop = type === "stop";
27
41
  activeTimers.delete(timer);
28
42
  cancelAnimationFrame(state.frame);
@@ -93,5 +107,6 @@ function work(type, timer, state, options) {
93
107
  export {
94
108
  work,
95
109
  getValueOrDefault,
96
- getOptions
110
+ getOptions,
111
+ destroyWhen
97
112
  };
@@ -1,5 +1,18 @@
1
1
  // src/functions.ts
2
- import {activeTimers, milliseconds} from "./constants";
2
+ import {
3
+ activeTimers,
4
+ beginTypes,
5
+ endOrRestartTypes,
6
+ endTypes,
7
+ milliseconds
8
+ } from "./constants";
9
+ function destroyWhen(state) {
10
+ state.timer?.destroy();
11
+ state.promise = undefined;
12
+ state.rejecter = undefined;
13
+ state.resolver = undefined;
14
+ state.timer = undefined;
15
+ }
3
16
  function getOptions(options, isRepeated) {
4
17
  return {
5
18
  afterCallback: options.afterCallback,
@@ -13,12 +26,12 @@ function getValueOrDefault(value, defaultValue, minimum) {
13
26
  return typeof value === "number" && value > (minimum ?? 0) ? value : defaultValue;
14
27
  }
15
28
  function work(type, timer, state, options) {
16
- if (["continue", "start"].includes(type) && state.active || ["pause", "stop"].includes(type) && !state.active) {
29
+ if (state.destroyed && type !== "stop" || beginTypes.has(type) && state.active || endTypes.has(type) && !state.active) {
17
30
  return timer;
18
31
  }
19
32
  const { count, interval, timeout } = options;
20
33
  const { isRepeated, minimum } = state;
21
- if (["pause", "restart", "stop"].includes(type)) {
34
+ if (endOrRestartTypes.has(type)) {
22
35
  const isStop = type === "stop";
23
36
  activeTimers.delete(timer);
24
37
  cancelAnimationFrame(state.frame);
@@ -89,5 +102,6 @@ function work(type, timer, state, options) {
89
102
  export {
90
103
  work,
91
104
  getValueOrDefault,
92
- getOptions
105
+ getOptions,
106
+ destroyWhen
93
107
  };
package/dist/global.js CHANGED
@@ -1,5 +1,12 @@
1
1
  // src/constants.ts
2
2
  var activeTimers = new Set;
3
+ var beginTypes = new Set(["continue", "start"]);
4
+ var endTypes = new Set(["pause", "stop"]);
5
+ var endOrRestartTypes = new Set([
6
+ "pause",
7
+ "restart",
8
+ "stop"
9
+ ]);
3
10
  var hiddenTimers = new Set;
4
11
  var milliseconds = 1000 / 60;
5
12
 
package/dist/index.js CHANGED
@@ -4,6 +4,13 @@ function noop() {
4
4
 
5
5
  // src/constants.ts
6
6
  var activeTimers = new Set;
7
+ var beginTypes = new Set(["continue", "start"]);
8
+ var endTypes = new Set(["pause", "stop"]);
9
+ var endOrRestartTypes = new Set([
10
+ "pause",
11
+ "restart",
12
+ "stop"
13
+ ]);
7
14
  var hiddenTimers = new Set;
8
15
  var milliseconds = 1000 / 60;
9
16
 
@@ -17,6 +24,13 @@ if (globalThis._oscarpalmer_timers == null) {
17
24
  }
18
25
 
19
26
  // src/functions.ts
27
+ function destroyWhen(state) {
28
+ state.timer?.destroy();
29
+ state.promise = undefined;
30
+ state.rejecter = undefined;
31
+ state.resolver = undefined;
32
+ state.timer = undefined;
33
+ }
20
34
  function getOptions(options, isRepeated) {
21
35
  return {
22
36
  afterCallback: options.afterCallback,
@@ -30,12 +44,12 @@ function getValueOrDefault(value, defaultValue, minimum) {
30
44
  return typeof value === "number" && value > (minimum ?? 0) ? value : defaultValue;
31
45
  }
32
46
  function work(type, timer, state, options) {
33
- if (["continue", "start"].includes(type) && state.active || ["pause", "stop"].includes(type) && !state.active) {
47
+ if (state.destroyed && type !== "stop" || beginTypes.has(type) && state.active || endTypes.has(type) && !state.active) {
34
48
  return timer;
35
49
  }
36
50
  const { count, interval, timeout } = options;
37
51
  const { isRepeated, minimum } = state;
38
- if (["pause", "restart", "stop"].includes(type)) {
52
+ if (endOrRestartTypes.has(type)) {
39
53
  const isStop = type === "stop";
40
54
  activeTimers.delete(timer);
41
55
  cancelAnimationFrame(state.frame);
@@ -104,6 +118,14 @@ function work(type, timer, state, options) {
104
118
  return timer;
105
119
  }
106
120
 
121
+ // src/models.ts
122
+ class TimerTrace extends Error {
123
+ constructor() {
124
+ super();
125
+ this.name = "TimerTrace";
126
+ }
127
+ }
128
+
107
129
  // src/timer.ts
108
130
  function repeat(callback, options) {
109
131
  return timer("repeat", callback, options ?? {}, true);
@@ -115,6 +137,7 @@ function timer(type, callback, partial, start) {
115
137
  callback,
116
138
  isRepeated,
117
139
  active: false,
140
+ destroyed: false,
118
141
  minimum: options.interval - options.interval % milliseconds / 2,
119
142
  paused: false,
120
143
  trace: new TimerTrace
@@ -141,6 +164,9 @@ class Timer extends BasicTimer {
141
164
  get active() {
142
165
  return this.state.active;
143
166
  }
167
+ get destroyed() {
168
+ return this.state.destroyed;
169
+ }
144
170
  get paused() {
145
171
  return this.state.paused;
146
172
  }
@@ -154,6 +180,16 @@ class Timer extends BasicTimer {
154
180
  continue() {
155
181
  return work("continue", this, this.state, this.options);
156
182
  }
183
+ destroy() {
184
+ if (!this.state.destroyed) {
185
+ this.state.destroyed = true;
186
+ this.stop();
187
+ this.options.afterCallback = undefined;
188
+ this.options.errorCallback = undefined;
189
+ this.state.callback = undefined;
190
+ this.state.trace = undefined;
191
+ }
192
+ }
157
193
  pause() {
158
194
  return work("pause", this, this.state, this.options);
159
195
  }
@@ -168,19 +204,18 @@ class Timer extends BasicTimer {
168
204
  }
169
205
  }
170
206
 
171
- class TimerTrace extends Error {
172
- constructor() {
173
- super();
174
- this.name = "TimerTrace";
175
- }
176
- }
177
-
178
207
  // src/index.ts
179
208
  function delay(time, timeout) {
180
209
  return new Promise((resolve, reject) => {
181
- wait(resolve ?? noop, {
210
+ const delayed = wait(() => {
211
+ delayed.destroy();
212
+ (resolve ?? noop)();
213
+ }, {
182
214
  timeout,
183
- errorCallback: reject ?? noop,
215
+ errorCallback: () => {
216
+ delayed.destroy();
217
+ (reject ?? noop)();
218
+ },
184
219
  interval: time
185
220
  });
186
221
  });
@@ -204,63 +239,80 @@ function isWhen(value) {
204
239
  }
205
240
  // src/when.ts
206
241
  function when(condition, options) {
207
- const repeated = timer("repeat", () => {
208
- if (condition()) {
209
- repeated.stop();
210
- state.resolver?.();
211
- }
212
- }, {
213
- afterCallback() {
214
- if (!repeated.paused) {
215
- if (condition()) {
216
- state.resolver?.();
217
- } else {
218
- state.rejecter?.();
219
- }
242
+ const state = {
243
+ started: false,
244
+ timer: timer("repeat", () => {
245
+ if (condition()) {
246
+ state.timer.stop();
220
247
  }
221
- },
222
- errorCallback() {
223
- state.rejecter?.();
224
- },
225
- count: options?.count,
226
- interval: options?.interval,
227
- timeout: options?.timeout
228
- }, false);
229
- const state = {};
230
- state.promise = new Promise((resolve, reject) => {
248
+ }, {
249
+ afterCallback() {
250
+ if (!state.timer.paused) {
251
+ if (condition()) {
252
+ state.resolver?.();
253
+ } else {
254
+ state.rejecter?.();
255
+ }
256
+ destroyWhen(state);
257
+ }
258
+ },
259
+ errorCallback() {
260
+ state.rejecter?.();
261
+ destroyWhen(state);
262
+ },
263
+ count: options?.count,
264
+ interval: options?.interval,
265
+ timeout: options?.timeout
266
+ }, false)
267
+ };
268
+ const promise = new Promise((resolve, reject) => {
231
269
  state.resolver = resolve;
232
270
  state.rejecter = reject;
233
271
  });
234
- state.timer = repeated;
272
+ state.promise = promise;
235
273
  return new When(state);
236
274
  }
237
275
 
238
276
  class When extends BasicTimer {
239
277
  get active() {
240
- return this.state.timer.active;
278
+ return this.state.timer?.active ?? false;
279
+ }
280
+ get destroyed() {
281
+ return this.state.timer == null;
241
282
  }
242
283
  get paused() {
243
- return this.state.timer.paused;
284
+ return this.state.timer?.paused ?? false;
285
+ }
286
+ get trace() {
287
+ return this.state.timer?.trace;
244
288
  }
245
289
  constructor(state) {
246
290
  super("when", state);
247
291
  }
248
292
  continue() {
249
- this.state.timer.continue();
293
+ this.state.timer?.continue();
250
294
  return this;
251
295
  }
296
+ destroy() {
297
+ if (this.state.timer != null) {
298
+ this.state.timer.destroy();
299
+ }
300
+ }
252
301
  pause() {
253
- this.state.timer.pause();
302
+ this.state.timer?.pause();
254
303
  return this;
255
304
  }
256
305
  stop() {
257
- if (this.state.timer.active) {
258
- this.state.timer.stop();
259
- this.state.rejecter?.();
260
- }
306
+ this.state.timer?.stop();
261
307
  return this;
262
308
  }
263
309
  then(resolve, reject) {
310
+ if (this.state.timer == null || this.state.started) {
311
+ return new Promise(() => {
312
+ (reject ?? noop)();
313
+ });
314
+ }
315
+ this.state.started = true;
264
316
  this.state.timer.start();
265
317
  return this.state.promise.then(resolve ?? noop, reject ?? noop);
266
318
  }
package/dist/index.mjs CHANGED
@@ -5,9 +5,15 @@ import"./global";
5
5
  import {wait} from "./timer";
6
6
  function delay(time, timeout) {
7
7
  return new Promise((resolve, reject) => {
8
- wait(resolve ?? noop, {
8
+ const delayed = wait(() => {
9
+ delayed.destroy();
10
+ (resolve ?? noop)();
11
+ }, {
9
12
  timeout,
10
- errorCallback: reject ?? noop,
13
+ errorCallback: () => {
14
+ delayed.destroy();
15
+ (reject ?? noop)();
16
+ },
11
17
  interval: time
12
18
  });
13
19
  });
package/dist/models.mjs CHANGED
@@ -0,0 +1,10 @@
1
+ // src/models.ts
2
+ class TimerTrace extends Error {
3
+ constructor() {
4
+ super();
5
+ this.name = "TimerTrace";
6
+ }
7
+ }
8
+ export {
9
+ TimerTrace
10
+ };
package/dist/timer.js ADDED
@@ -0,0 +1,192 @@
1
+ // src/constants.ts
2
+ var activeTimers = new Set;
3
+ var beginTypes = new Set(["continue", "start"]);
4
+ var endTypes = new Set(["pause", "stop"]);
5
+ var endOrRestartTypes = new Set([
6
+ "pause",
7
+ "restart",
8
+ "stop"
9
+ ]);
10
+ var hiddenTimers = new Set;
11
+ var milliseconds = 1000 / 60;
12
+
13
+ // src/functions.ts
14
+ function getOptions(options, isRepeated) {
15
+ return {
16
+ afterCallback: options.afterCallback,
17
+ count: getValueOrDefault(options.count, isRepeated ? Number.POSITIVE_INFINITY : 1),
18
+ errorCallback: options.errorCallback,
19
+ interval: getValueOrDefault(options.interval, milliseconds, milliseconds),
20
+ timeout: getValueOrDefault(options.timeout, isRepeated ? Number.POSITIVE_INFINITY : 30000)
21
+ };
22
+ }
23
+ function getValueOrDefault(value, defaultValue, minimum) {
24
+ return typeof value === "number" && value > (minimum ?? 0) ? value : defaultValue;
25
+ }
26
+ function work(type, timer, state, options) {
27
+ if (state.destroyed && type !== "stop" || beginTypes.has(type) && state.active || endTypes.has(type) && !state.active) {
28
+ return timer;
29
+ }
30
+ const { count, interval, timeout } = options;
31
+ const { isRepeated, minimum } = state;
32
+ if (endOrRestartTypes.has(type)) {
33
+ const isStop = type === "stop";
34
+ activeTimers.delete(timer);
35
+ cancelAnimationFrame(state.frame);
36
+ if (isStop) {
37
+ options.afterCallback?.(false);
38
+ }
39
+ state.active = false;
40
+ state.frame = undefined;
41
+ state.paused = !isStop;
42
+ if (isStop) {
43
+ state.elapsed = undefined;
44
+ state.index = undefined;
45
+ }
46
+ return type === "restart" ? work("start", timer, state, options) : timer;
47
+ }
48
+ state.active = true;
49
+ state.paused = false;
50
+ const elapsed = type === "continue" ? +(state.elapsed ?? 0) : 0;
51
+ let index = type === "continue" ? +(state.index ?? 0) : 0;
52
+ state.elapsed = elapsed;
53
+ state.index = index;
54
+ const total = (count === Number.POSITIVE_INFINITY ? Number.POSITIVE_INFINITY : (count - index) * (interval > 0 ? interval : milliseconds)) - elapsed;
55
+ let current;
56
+ let start;
57
+ function finish(finished, error) {
58
+ activeTimers.delete(timer);
59
+ state.active = false;
60
+ state.elapsed = undefined;
61
+ state.frame = undefined;
62
+ state.index = undefined;
63
+ if (error) {
64
+ options.errorCallback?.();
65
+ }
66
+ options.afterCallback?.(finished);
67
+ }
68
+ function step(timestamp) {
69
+ if (!state.active) {
70
+ return;
71
+ }
72
+ current ??= timestamp;
73
+ start ??= timestamp;
74
+ const time = timestamp - current;
75
+ state.elapsed = elapsed + (current - start);
76
+ const finished = time - elapsed >= total;
77
+ if (timestamp - start >= timeout - elapsed) {
78
+ finish(finished, !finished);
79
+ return;
80
+ }
81
+ if (finished || time >= minimum) {
82
+ if (state.active) {
83
+ state.callback(isRepeated ? index : undefined);
84
+ }
85
+ index += 1;
86
+ state.index = index;
87
+ if (!finished && index < count) {
88
+ current = null;
89
+ } else {
90
+ finish(true, false);
91
+ return;
92
+ }
93
+ }
94
+ state.frame = requestAnimationFrame(step);
95
+ }
96
+ activeTimers.add(timer);
97
+ state.frame = requestAnimationFrame(step);
98
+ return timer;
99
+ }
100
+
101
+ // src/models.ts
102
+ class TimerTrace extends Error {
103
+ constructor() {
104
+ super();
105
+ this.name = "TimerTrace";
106
+ }
107
+ }
108
+
109
+ // src/timer.ts
110
+ function repeat(callback, options) {
111
+ return timer("repeat", callback, options ?? {}, true);
112
+ }
113
+ function timer(type, callback, partial, start) {
114
+ const isRepeated = type === "repeat";
115
+ const options = getOptions(partial, isRepeated);
116
+ const instance = new Timer(type, {
117
+ callback,
118
+ isRepeated,
119
+ active: false,
120
+ destroyed: false,
121
+ minimum: options.interval - options.interval % milliseconds / 2,
122
+ paused: false,
123
+ trace: new TimerTrace
124
+ }, options);
125
+ if (start) {
126
+ instance.start();
127
+ }
128
+ return instance;
129
+ }
130
+ function wait(callback, options) {
131
+ return timer("wait", callback, options == null || typeof options === "number" ? {
132
+ interval: options
133
+ } : options, true);
134
+ }
135
+
136
+ class BasicTimer {
137
+ constructor(type, state) {
138
+ this.$timer = type;
139
+ this.state = state;
140
+ }
141
+ }
142
+
143
+ class Timer extends BasicTimer {
144
+ get active() {
145
+ return this.state.active;
146
+ }
147
+ get destroyed() {
148
+ return this.state.destroyed;
149
+ }
150
+ get paused() {
151
+ return this.state.paused;
152
+ }
153
+ get trace() {
154
+ return globalThis._oscarpalmer_timer_debug ? this.state.trace : undefined;
155
+ }
156
+ constructor(type, state, options) {
157
+ super(type, state);
158
+ this.options = options;
159
+ }
160
+ continue() {
161
+ return work("continue", this, this.state, this.options);
162
+ }
163
+ destroy() {
164
+ if (!this.state.destroyed) {
165
+ this.state.destroyed = true;
166
+ this.stop();
167
+ this.options.afterCallback = undefined;
168
+ this.options.errorCallback = undefined;
169
+ this.state.callback = undefined;
170
+ this.state.trace = undefined;
171
+ }
172
+ }
173
+ pause() {
174
+ return work("pause", this, this.state, this.options);
175
+ }
176
+ restart() {
177
+ return work("restart", this, this.state, this.options);
178
+ }
179
+ start() {
180
+ return work("start", this, this.state, this.options);
181
+ }
182
+ stop() {
183
+ return work("stop", this, this.state, this.options);
184
+ }
185
+ }
186
+ export {
187
+ wait,
188
+ timer,
189
+ repeat,
190
+ Timer,
191
+ BasicTimer
192
+ };
package/dist/timer.mjs CHANGED
@@ -1,6 +1,9 @@
1
1
  // src/timer.ts
2
2
  import {milliseconds} from "./constants";
3
3
  import {getOptions, work} from "./functions";
4
+ import {
5
+ TimerTrace
6
+ } from "./models";
4
7
  function repeat(callback, options) {
5
8
  return timer("repeat", callback, options ?? {}, true);
6
9
  }
@@ -11,6 +14,7 @@ function timer(type, callback, partial, start) {
11
14
  callback,
12
15
  isRepeated,
13
16
  active: false,
17
+ destroyed: false,
14
18
  minimum: options.interval - options.interval % milliseconds / 2,
15
19
  paused: false,
16
20
  trace: new TimerTrace
@@ -37,6 +41,9 @@ class Timer extends BasicTimer {
37
41
  get active() {
38
42
  return this.state.active;
39
43
  }
44
+ get destroyed() {
45
+ return this.state.destroyed;
46
+ }
40
47
  get paused() {
41
48
  return this.state.paused;
42
49
  }
@@ -50,6 +57,16 @@ class Timer extends BasicTimer {
50
57
  continue() {
51
58
  return work("continue", this, this.state, this.options);
52
59
  }
60
+ destroy() {
61
+ if (!this.state.destroyed) {
62
+ this.state.destroyed = true;
63
+ this.stop();
64
+ this.options.afterCallback = undefined;
65
+ this.options.errorCallback = undefined;
66
+ this.state.callback = undefined;
67
+ this.state.trace = undefined;
68
+ }
69
+ }
53
70
  pause() {
54
71
  return work("pause", this, this.state, this.options);
55
72
  }
@@ -63,13 +80,6 @@ class Timer extends BasicTimer {
63
80
  return work("stop", this, this.state, this.options);
64
81
  }
65
82
  }
66
-
67
- class TimerTrace extends Error {
68
- constructor() {
69
- super();
70
- this.name = "TimerTrace";
71
- }
72
- }
73
83
  export {
74
84
  wait,
75
85
  timer,