@oscarpalmer/timer 0.32.0 → 0.34.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/timer.cjs CHANGED
@@ -1,114 +1,66 @@
1
- 'use strict';
2
-
3
- Object.defineProperty(exports, Symbol.toStringTag, { value: 'Module' });
4
-
5
- const _function = require('@oscarpalmer/atoms/function');
6
- const work = require('./work.cjs');
7
-
8
- class Timer {
9
- constructor(type, state, options, start) {
10
- this.options = options;
11
- this.$timer = type;
12
- this.state = {
13
- ...state,
14
- active: false,
15
- destroyed: false,
16
- elapsed: 0,
17
- frame: void 0,
18
- index: 0,
19
- paused: false,
20
- total: 0
21
- };
22
- if (start) {
23
- this.start();
24
- }
25
- }
26
- state;
27
- /**
28
- * Is the timer active?
29
- */
30
- get active() {
31
- return this.state.active;
32
- }
33
- /**
34
- * Is the timer destroyed?
35
- */
36
- get destroyed() {
37
- return this.state.destroyed;
38
- }
39
- /**
40
- * Is the timer paused?
41
- */
42
- get paused() {
43
- return this.state.paused;
44
- }
45
- /**
46
- * Get the timer's origin _(if debugging is enabled)_
47
- */
48
- get trace() {
49
- return globalThis._oscarpalmer_timer_debug ?? false ? this.state.trace : void 0;
50
- }
51
- /**
52
- * Continue running the timer _(if it's paused)_
53
- */
54
- continue() {
55
- return this.#work("continue");
56
- }
57
- /**
58
- * Destroy the timer
59
- */
60
- destroy() {
61
- this.state.destroyed = true;
62
- this.options.onAfter = _function.noop;
63
- this.options.onError = _function.noop;
64
- this.state.callback = _function.noop;
65
- if (!globalThis._oscarpalmer_timer_debug) {
66
- this.state.trace = void 0;
67
- }
68
- work.stop(
69
- {
70
- instance: this,
71
- type: this.$timer
72
- },
73
- this.state,
74
- this.options
75
- );
76
- }
77
- /**
78
- * Pause the timer _(if it's running)_
79
- */
80
- pause() {
81
- return this.#work("pause");
82
- }
83
- /**
84
- * Restart the timer _(or start it, if it's not running)_
85
- */
86
- restart() {
87
- return this.#work("restart");
88
- }
89
- /**
90
- * Start the timer _(if it's not running)_
91
- */
92
- start() {
93
- return this.#work("start");
94
- }
95
- /**
96
- * Stop the timer _(if it's running)_
97
- */
98
- stop() {
99
- return this.#work("stop");
100
- }
101
- #work(type) {
102
- return work.work(
103
- type,
104
- {
105
- instance: this,
106
- type: this.$timer
107
- },
108
- this.state,
109
- this.options
110
- );
111
- }
112
- }
113
-
1
+ const require_rolldown_runtime = require("./rolldown_runtime.cjs");
2
+ const require_constants = require("./constants.cjs");
3
+ const require_work = require("./work.cjs");
4
+ const __oscarpalmer_atoms_function = require_rolldown_runtime.__toESM(require("@oscarpalmer/atoms/function"));
5
+ var Timer = class {
6
+ get active() {
7
+ return this.state.active;
8
+ }
9
+ get destroyed() {
10
+ return this.state.destroyed;
11
+ }
12
+ get paused() {
13
+ return this.state.paused;
14
+ }
15
+ get trace() {
16
+ return globalThis._oscarpalmer_timer_debug ?? false ? this.state.trace : void 0;
17
+ }
18
+ constructor(type, state, options, start) {
19
+ this.options = options;
20
+ this.$timer = type;
21
+ this.state = {
22
+ ...state,
23
+ active: false,
24
+ destroyed: false,
25
+ elapsed: 0,
26
+ frame: void 0,
27
+ index: 0,
28
+ paused: false,
29
+ total: 0
30
+ };
31
+ if (start) this.start();
32
+ }
33
+ continue() {
34
+ return this.#work(require_constants.WORK_CONTINUE);
35
+ }
36
+ destroy() {
37
+ this.state.destroyed = true;
38
+ this.options.onAfter = __oscarpalmer_atoms_function.noop;
39
+ this.options.onError = __oscarpalmer_atoms_function.noop;
40
+ this.state.callback = __oscarpalmer_atoms_function.noop;
41
+ if (!globalThis._oscarpalmer_timer_debug) this.state.trace = void 0;
42
+ require_work.stop({
43
+ instance: this,
44
+ type: this.$timer
45
+ }, this.state, this.options);
46
+ }
47
+ pause() {
48
+ return this.#work(require_constants.WORK_PAUSE);
49
+ }
50
+ restart() {
51
+ return this.#work(require_constants.WORK_RESTART);
52
+ }
53
+ start() {
54
+ return this.#work(require_constants.WORK_START);
55
+ }
56
+ stop() {
57
+ return this.#work(require_constants.WORK_STOP);
58
+ }
59
+ #work(type) {
60
+ return require_work.work(type, {
61
+ instance: this,
62
+ type: this.$timer
63
+ }, this.state, this.options);
64
+ }
65
+ };
114
66
  exports.Timer = Timer;
@@ -1,4 +1,4 @@
1
- function calculate() {
1
+ function calculate$1() {
2
2
  return new Promise(resolve => {
3
3
  const values = [];
4
4
  let last;
@@ -26,10 +26,6 @@ function calculate() {
26
26
  * A set of all active timers
27
27
  */
28
28
  const activeTimers = new Set();
29
- /**
30
- * A set of types that allow work to begin
31
- */
32
- const beginTypes = new Set(['continue', 'start']);
33
29
  /**
34
30
  * Buffer value to use when evaluating if a specific time is within a certain range
35
31
  */
@@ -38,33 +34,28 @@ const intervalBuffer = 5;
38
34
  * Message to show when a when-timer is destroyed
39
35
  */
40
36
  const destroyedMessage = 'Timer has already been destroyed';
41
- /**
42
- * A set of types that allow work to end
43
- */
44
- const endTypes = new Set(['pause', 'stop']);
45
- /**
46
- * A set of types that allow work to end or restart
47
- */
48
- const endOrRestartTypes = new Set([
49
- 'pause',
50
- 'restart',
51
- 'stop',
52
- ]);
53
37
  /**
54
38
  * A set of timers that were paused due to the document being hidden
55
39
  */
56
40
  const hiddenTimers = new Set();
57
- const pauseTypes = new Set(['continue', 'pause']);
58
41
  /**
59
42
  * Message to show when a when-timer is started
60
43
  */
61
44
  const startedMessage = 'Timer has already been started';
45
+ const TYPE_REPEAT = 'repeat';
46
+ const TYPE_WAIT = 'wait';
47
+ const TYPE_WHEN = 'when';
48
+ const WORK_CONTINUE = 'continue';
49
+ const WORK_PAUSE = 'pause';
50
+ const WORK_RESTART = 'restart';
51
+ const WORK_START = 'start';
52
+ const WORK_STOP = 'stop';
62
53
  //
63
54
  /**
64
55
  * A calculated average of the refresh rate of the display _(in milliseconds)_
65
56
  */
66
57
  let milliseconds = 1000 / 60;
67
- calculate().then(value => {
58
+ calculate$1().then(value => {
68
59
  milliseconds = value;
69
60
  });
70
61
 
@@ -76,22 +67,33 @@ if (globalThis._oscarpalmer_timers == null) {
76
67
  });
77
68
  }
78
69
  document.addEventListener('visibilitychange', () => {
79
- if (document.hidden) {
80
- for (const timer of activeTimers) {
81
- hiddenTimers.add(timer);
82
- timer.pause();
83
- }
84
- }
85
- else {
86
- for (const timer of hiddenTimers) {
87
- timer.continue();
88
- }
89
- hiddenTimers.clear();
70
+ const from = document.hidden ? activeTimers : hiddenTimers;
71
+ const method = document.hidden ? WORK_PAUSE : WORK_CONTINUE;
72
+ const to = document.hidden ? hiddenTimers : activeTimers;
73
+ for (const timer of from) {
74
+ timer[method]();
75
+ to.add(timer);
90
76
  }
77
+ from.clear();
91
78
  });
92
79
 
93
- function noop() {
80
+ function calculate() {
81
+ return new Promise((resolve) => {
82
+ const values = [];
83
+ let last;
84
+ function step(now) {
85
+ if (last != null) values.push(now - last);
86
+ if (last = now, values.length >= 10) {
87
+ const median = values.sort().slice(2, -2).reduce((first, second) => first + second, 0) / (values.length - 4);
88
+ resolve(median);
89
+ } else requestAnimationFrame(step);
90
+ }
91
+ requestAnimationFrame(step);
92
+ });
94
93
  }
94
+ function noop() {}
95
+ calculate().then((value) => {
96
+ });
95
97
 
96
98
  function getCallback(value) {
97
99
  return typeof value === 'function' ? value : noop;
@@ -130,25 +132,25 @@ function is(names, value) {
130
132
  * Is the value a repeating timer?
131
133
  */
132
134
  function isRepeated(value) {
133
- return is(['repeat'], value);
135
+ return is([TYPE_REPEAT], value);
134
136
  }
135
137
  /**
136
138
  * Is the value a timer?
137
139
  */
138
140
  function isTimer(value) {
139
- return is(['repeat', 'wait'], value);
141
+ return is([TYPE_REPEAT, TYPE_WAIT], value);
140
142
  }
141
143
  /**
142
144
  * Is the value a waiting timer?
143
145
  */
144
146
  function isWaited(value) {
145
- return is(['wait'], value);
147
+ return is([TYPE_WAIT], value);
146
148
  }
147
149
  /**
148
150
  * Is the value a conditional timer?
149
151
  */
150
152
  function isWhen(value) {
151
- return is(['when'], value) && typeof value.then === 'function';
153
+ return is([TYPE_WHEN], value) && typeof value.then === 'function';
152
154
  }
153
155
 
154
156
  class TimerTrace extends Error {
@@ -158,24 +160,13 @@ class TimerTrace extends Error {
158
160
  }
159
161
  }
160
162
 
161
- function endOrRestart(type, timer, state, options) {
162
- cancelAnimationFrame(state.frame);
163
- if (type === 'stop') {
164
- options.onAfter?.(false);
165
- }
166
- state.active = false;
167
- state.frame = undefined;
168
- state.paused = type === 'pause';
169
- return type === 'restart'
170
- ? work('start', timer, state, options)
171
- : timer.instance;
172
- }
173
163
  function finish(timer, state, options, success) {
164
+ cancelAnimationFrame(state.frame);
174
165
  activeTimers.delete(timer.instance);
175
166
  state.active = false;
176
167
  state.elapsed = 0;
177
168
  state.frame = undefined;
178
- if (timer.type === 'wait') {
169
+ if (timer.type === TYPE_WAIT) {
179
170
  state.callback();
180
171
  }
181
172
  else {
@@ -183,19 +174,30 @@ function finish(timer, state, options, success) {
183
174
  }
184
175
  }
185
176
  function ignore(type, state) {
186
- return ((state.destroyed && type !== 'stop') ||
187
- (state.active ? beginTypes.has(type) : endTypes.has(type)));
177
+ if (state.destroyed) {
178
+ return type !== WORK_STOP;
179
+ }
180
+ if (state.paused) {
181
+ return type === WORK_PAUSE || type === WORK_START;
182
+ }
183
+ return state.active && type === WORK_START;
184
+ }
185
+ function pause(timer, state) {
186
+ cancelAnimationFrame(state.frame);
187
+ state.frame = undefined;
188
+ return timer.instance;
188
189
  }
189
190
  function run(timer, state, options) {
190
- let start;
191
+ let last;
191
192
  return function step(now) {
192
193
  if (!state.active) {
193
194
  return;
194
195
  }
195
- start ??= now;
196
- const difference = now - start;
196
+ last ??= now;
197
+ const difference = now - last;
197
198
  state.elapsed += difference;
198
199
  state.total += difference;
200
+ last = now;
199
201
  if (options.timeout > 0 && state.total >= options.timeout) {
200
202
  options.onError?.();
201
203
  finish(timer, state, options, false);
@@ -206,7 +208,6 @@ function run(timer, state, options) {
206
208
  if (options.count > -1) {
207
209
  state.callback(state.index);
208
210
  }
209
- start = now;
210
211
  state.elapsed = 0;
211
212
  state.index += 1;
212
213
  if (options.count === -1 ||
@@ -219,24 +220,37 @@ function run(timer, state, options) {
219
220
  };
220
221
  }
221
222
  function setState(type, state) {
222
- const pausable = pauseTypes.has(type);
223
+ const pausable = type === WORK_CONTINUE || type === WORK_PAUSE;
223
224
  state.elapsed = pausable ? state.elapsed : 0;
224
225
  state.index = pausable ? state.index : 0;
225
226
  state.total = pausable ? state.total : 0;
226
227
  }
227
228
  function stop(timer, state, options) {
228
- endOrRestart('stop', timer, state, options);
229
+ cancelAnimationFrame(state.frame);
230
+ activeTimers.delete(timer.instance);
231
+ options.onAfter?.(false);
232
+ state.active = !stop;
233
+ state.frame = undefined;
234
+ state.paused = false;
235
+ return timer.instance;
229
236
  }
230
237
  function work(type, timer, state, options) {
231
238
  if (ignore(type, state)) {
232
239
  return timer.instance;
233
240
  }
234
241
  setState(type, state);
235
- if (endOrRestartTypes.has(type)) {
236
- return endOrRestart(type, timer, state, options);
242
+ if (type === WORK_STOP) {
243
+ return stop(timer, state, options);
244
+ }
245
+ if (type === WORK_PAUSE || type === WORK_RESTART) {
246
+ cancelAnimationFrame(state.frame);
247
+ state.frame = undefined;
237
248
  }
238
249
  state.active = true;
239
- state.paused = false;
250
+ state.paused = type === WORK_PAUSE;
251
+ if (state.paused) {
252
+ return pause(timer, state);
253
+ }
240
254
  activeTimers.add(timer.instance);
241
255
  const runner = run(timer, state, options);
242
256
  state.frame = requestAnimationFrame(runner);
@@ -268,7 +282,7 @@ class Timer {
268
282
  * Get the timer's origin _(if debugging is enabled)_
269
283
  */
270
284
  get trace() {
271
- return globalThis._oscarpalmer_timer_debug ?? false
285
+ return (globalThis._oscarpalmer_timer_debug ?? false)
272
286
  ? this.state.trace
273
287
  : undefined;
274
288
  }
@@ -293,7 +307,7 @@ class Timer {
293
307
  * Continue running the timer _(if it's paused)_
294
308
  */
295
309
  continue() {
296
- return this.#work('continue');
310
+ return this.#work(WORK_CONTINUE);
297
311
  }
298
312
  /**
299
313
  * Destroy the timer
@@ -315,25 +329,25 @@ class Timer {
315
329
  * Pause the timer _(if it's running)_
316
330
  */
317
331
  pause() {
318
- return this.#work('pause');
332
+ return this.#work(WORK_PAUSE);
319
333
  }
320
334
  /**
321
335
  * Restart the timer _(or start it, if it's not running)_
322
336
  */
323
337
  restart() {
324
- return this.#work('restart');
338
+ return this.#work(WORK_RESTART);
325
339
  }
326
340
  /**
327
341
  * Start the timer _(if it's not running)_
328
342
  */
329
343
  start() {
330
- return this.#work('start');
344
+ return this.#work(WORK_START);
331
345
  }
332
346
  /**
333
347
  * Stop the timer _(if it's running)_
334
348
  */
335
349
  stop() {
336
- return this.#work('stop');
350
+ return this.#work(WORK_STOP);
337
351
  }
338
352
  #work(type) {
339
353
  return work(type, {
@@ -347,7 +361,7 @@ class Timer {
347
361
  * Create a repeating timer
348
362
  */
349
363
  function repeat(callback, options) {
350
- return new Timer('repeat', {
364
+ return new Timer(TYPE_REPEAT, {
351
365
  callback: getCallback(callback),
352
366
  trace: new TimerTrace().stack,
353
367
  }, {
@@ -365,7 +379,7 @@ function repeat(callback, options) {
365
379
  * @param time How long to wait for _(in milliseconds; defaults to screen refresh rate)_
366
380
  */
367
381
  function wait(callback, time) {
368
- return new Timer('wait', {
382
+ return new Timer(TYPE_WAIT, {
369
383
  callback: getCallback(callback),
370
384
  trace: new TimerTrace().stack,
371
385
  }, {
@@ -378,7 +392,7 @@ function wait(callback, time) {
378
392
  }
379
393
 
380
394
  class When {
381
- $timer = 'when';
395
+ $timer = TYPE_WHEN;
382
396
  state = {
383
397
  promise: undefined,
384
398
  rejecter: undefined,
@@ -408,7 +422,7 @@ class When {
408
422
  * Get the timer's origin _(if debugging is enabled)_
409
423
  */
410
424
  get trace() {
411
- return globalThis._oscarpalmer_timer_debug ?? false
425
+ return (globalThis._oscarpalmer_timer_debug ?? false)
412
426
  ? this.state.timer?.trace
413
427
  : undefined;
414
428
  }
@@ -419,7 +433,7 @@ class When {
419
433
  state.rejecter = reject;
420
434
  });
421
435
  let result = false;
422
- this.state.timer = new Timer('when', {
436
+ this.state.timer = new Timer(TYPE_WHEN, {
423
437
  callback() {
424
438
  try {
425
439
  if (condition()) {
package/dist/timer.js CHANGED
@@ -1,110 +1,65 @@
1
- import { noop } from '@oscarpalmer/atoms/function';
2
- import { stop, work } from './work.js';
3
-
4
- class Timer {
5
- constructor(type, state, options, start) {
6
- this.options = options;
7
- this.$timer = type;
8
- this.state = {
9
- ...state,
10
- active: false,
11
- destroyed: false,
12
- elapsed: 0,
13
- frame: void 0,
14
- index: 0,
15
- paused: false,
16
- total: 0
17
- };
18
- if (start) {
19
- this.start();
20
- }
21
- }
22
- state;
23
- /**
24
- * Is the timer active?
25
- */
26
- get active() {
27
- return this.state.active;
28
- }
29
- /**
30
- * Is the timer destroyed?
31
- */
32
- get destroyed() {
33
- return this.state.destroyed;
34
- }
35
- /**
36
- * Is the timer paused?
37
- */
38
- get paused() {
39
- return this.state.paused;
40
- }
41
- /**
42
- * Get the timer's origin _(if debugging is enabled)_
43
- */
44
- get trace() {
45
- return globalThis._oscarpalmer_timer_debug ?? false ? this.state.trace : void 0;
46
- }
47
- /**
48
- * Continue running the timer _(if it's paused)_
49
- */
50
- continue() {
51
- return this.#work("continue");
52
- }
53
- /**
54
- * Destroy the timer
55
- */
56
- destroy() {
57
- this.state.destroyed = true;
58
- this.options.onAfter = noop;
59
- this.options.onError = noop;
60
- this.state.callback = noop;
61
- if (!globalThis._oscarpalmer_timer_debug) {
62
- this.state.trace = void 0;
63
- }
64
- stop(
65
- {
66
- instance: this,
67
- type: this.$timer
68
- },
69
- this.state,
70
- this.options
71
- );
72
- }
73
- /**
74
- * Pause the timer _(if it's running)_
75
- */
76
- pause() {
77
- return this.#work("pause");
78
- }
79
- /**
80
- * Restart the timer _(or start it, if it's not running)_
81
- */
82
- restart() {
83
- return this.#work("restart");
84
- }
85
- /**
86
- * Start the timer _(if it's not running)_
87
- */
88
- start() {
89
- return this.#work("start");
90
- }
91
- /**
92
- * Stop the timer _(if it's running)_
93
- */
94
- stop() {
95
- return this.#work("stop");
96
- }
97
- #work(type) {
98
- return work(
99
- type,
100
- {
101
- instance: this,
102
- type: this.$timer
103
- },
104
- this.state,
105
- this.options
106
- );
107
- }
108
- }
109
-
1
+ import { WORK_CONTINUE, WORK_PAUSE, WORK_RESTART, WORK_START, WORK_STOP } from "./constants.js";
2
+ import { stop, work } from "./work.js";
3
+ import { noop } from "@oscarpalmer/atoms/function";
4
+ var Timer = class {
5
+ get active() {
6
+ return this.state.active;
7
+ }
8
+ get destroyed() {
9
+ return this.state.destroyed;
10
+ }
11
+ get paused() {
12
+ return this.state.paused;
13
+ }
14
+ get trace() {
15
+ return globalThis._oscarpalmer_timer_debug ?? false ? this.state.trace : void 0;
16
+ }
17
+ constructor(type, state, options, start) {
18
+ this.options = options;
19
+ this.$timer = type;
20
+ this.state = {
21
+ ...state,
22
+ active: false,
23
+ destroyed: false,
24
+ elapsed: 0,
25
+ frame: void 0,
26
+ index: 0,
27
+ paused: false,
28
+ total: 0
29
+ };
30
+ if (start) this.start();
31
+ }
32
+ continue() {
33
+ return this.#work(WORK_CONTINUE);
34
+ }
35
+ destroy() {
36
+ this.state.destroyed = true;
37
+ this.options.onAfter = noop;
38
+ this.options.onError = noop;
39
+ this.state.callback = noop;
40
+ if (!globalThis._oscarpalmer_timer_debug) this.state.trace = void 0;
41
+ stop({
42
+ instance: this,
43
+ type: this.$timer
44
+ }, this.state, this.options);
45
+ }
46
+ pause() {
47
+ return this.#work(WORK_PAUSE);
48
+ }
49
+ restart() {
50
+ return this.#work(WORK_RESTART);
51
+ }
52
+ start() {
53
+ return this.#work(WORK_START);
54
+ }
55
+ stop() {
56
+ return this.#work(WORK_STOP);
57
+ }
58
+ #work(type) {
59
+ return work(type, {
60
+ instance: this,
61
+ type: this.$timer
62
+ }, this.state, this.options);
63
+ }
64
+ };
110
65
  export { Timer };