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