@oscarpalmer/timer 0.44.0 → 0.46.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.d.mts +3 -14
- package/dist/constants.mjs +5 -13
- package/dist/global.d.mts +3 -0
- package/dist/global.mjs +5 -14
- package/dist/index.d.mts +12 -33
- package/dist/index.mjs +134 -254
- package/dist/{get.d.mts → misc.d.mts} +6 -3
- package/dist/misc.mjs +37 -0
- package/dist/models.d.mts +25 -3
- package/dist/repeat.mjs +1 -1
- package/dist/timer.mjs +15 -28
- package/dist/wait.mjs +1 -1
- package/dist/when.mjs +11 -24
- package/dist/work.d.mts +3 -3
- package/dist/work.mjs +27 -35
- package/package.json +2 -6
- package/src/constants.ts +5 -15
- package/src/global.ts +11 -21
- package/src/index.ts +0 -1
- package/src/misc.ts +55 -0
- package/src/models.ts +25 -2
- package/src/repeat.ts +1 -1
- package/src/timer.ts +17 -43
- package/src/wait.ts +1 -1
- package/src/when.ts +12 -33
- package/src/work.ts +34 -61
- package/dist/delay.d.mts +0 -2
- package/dist/delay.mjs +0 -2
- package/dist/get.mjs +0 -15
- package/src/delay.ts +0 -1
- package/src/get.ts +0 -17
package/dist/timer.mjs
CHANGED
|
@@ -1,31 +1,28 @@
|
|
|
1
1
|
import { WORK_CONTINUE, WORK_PAUSE, WORK_RESTART, WORK_START, WORK_STOP } from "./constants.mjs";
|
|
2
|
-
import {
|
|
2
|
+
import { work } from "./work.mjs";
|
|
3
3
|
import { noop } from "@oscarpalmer/atoms/function";
|
|
4
4
|
//#region src/timer.ts
|
|
5
5
|
function createTimer(name, pick, options, start) {
|
|
6
|
-
function worker(type) {
|
|
7
|
-
return work(type, {
|
|
8
|
-
name,
|
|
9
|
-
instance
|
|
10
|
-
}, state, options);
|
|
11
|
-
}
|
|
12
6
|
const state = {
|
|
13
7
|
...pick,
|
|
8
|
+
name,
|
|
9
|
+
options,
|
|
14
10
|
active: false,
|
|
15
11
|
destroyed: false,
|
|
16
12
|
elapsed: 0,
|
|
17
13
|
frame: void 0,
|
|
18
14
|
index: 0,
|
|
19
15
|
paused: false,
|
|
16
|
+
timer: void 0,
|
|
20
17
|
total: 0
|
|
21
18
|
};
|
|
22
19
|
const instance = {
|
|
23
|
-
continue: () =>
|
|
24
|
-
destroy:
|
|
25
|
-
pause: () =>
|
|
26
|
-
restart: () =>
|
|
27
|
-
start: () =>
|
|
28
|
-
stop: () =>
|
|
20
|
+
continue: () => work(WORK_CONTINUE, state),
|
|
21
|
+
destroy: noop,
|
|
22
|
+
pause: () => work(WORK_PAUSE, state),
|
|
23
|
+
restart: () => work(WORK_RESTART, state),
|
|
24
|
+
start: () => work(WORK_START, state),
|
|
25
|
+
stop: () => work(WORK_STOP, state)
|
|
29
26
|
};
|
|
30
27
|
Object.defineProperties(instance, {
|
|
31
28
|
$timer: {
|
|
@@ -34,11 +31,11 @@ function createTimer(name, pick, options, start) {
|
|
|
34
31
|
},
|
|
35
32
|
active: {
|
|
36
33
|
enumerable: true,
|
|
37
|
-
get: () => state.active
|
|
34
|
+
get: () => state.active && !state.paused
|
|
38
35
|
},
|
|
39
36
|
destroyed: {
|
|
40
37
|
enumerable: true,
|
|
41
|
-
|
|
38
|
+
value: false
|
|
42
39
|
},
|
|
43
40
|
paused: {
|
|
44
41
|
enumerable: true,
|
|
@@ -49,19 +46,9 @@ function createTimer(name, pick, options, start) {
|
|
|
49
46
|
get: () => globalThis._oscarpalmer_timer_debug ?? false ? state.trace : void 0
|
|
50
47
|
}
|
|
51
48
|
});
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
function destroyTimer(name, instance, state, options) {
|
|
56
|
-
state.destroyed = true;
|
|
57
|
-
options.onAfter = noop;
|
|
58
|
-
options.onError = noop;
|
|
59
|
-
state.callback = noop;
|
|
60
|
-
if (!globalThis._oscarpalmer_timer_debug) state.trace = void 0;
|
|
61
|
-
stop({
|
|
62
|
-
instance,
|
|
63
|
-
name
|
|
64
|
-
}, state, options);
|
|
49
|
+
state.timer = Object.freeze(instance);
|
|
50
|
+
if (start) state.timer.start();
|
|
51
|
+
return state.timer;
|
|
65
52
|
}
|
|
66
53
|
//#endregion
|
|
67
54
|
export { createTimer };
|
package/dist/wait.mjs
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { TYPE_WAIT } from "./constants.mjs";
|
|
2
|
-
import { getCallback, getValidNumber } from "./
|
|
2
|
+
import { getCallback, getValidNumber } from "./misc.mjs";
|
|
3
3
|
import "./global.mjs";
|
|
4
4
|
import { TimerTrace } from "./models.mjs";
|
|
5
5
|
import { createTimer } from "./timer.mjs";
|
package/dist/when.mjs
CHANGED
|
@@ -1,21 +1,13 @@
|
|
|
1
|
-
import {
|
|
2
|
-
import { getValidNumber, getValidTimeout } from "./
|
|
1
|
+
import { MESSAGE_STARTED, TYPE_WHEN, WORK_CONTINUE, WORK_PAUSE, WORK_STOP } from "./constants.mjs";
|
|
2
|
+
import { getValidNumber, getValidTimeout } from "./misc.mjs";
|
|
3
3
|
import "./global.mjs";
|
|
4
4
|
import { TimerTrace } from "./models.mjs";
|
|
5
5
|
import { createTimer } from "./timer.mjs";
|
|
6
6
|
import { noop } from "@oscarpalmer/atoms/function";
|
|
7
7
|
//#region src/when.ts
|
|
8
|
-
function
|
|
9
|
-
state.timer?.destroy();
|
|
10
|
-
state.promise = void 0;
|
|
11
|
-
state.resolver = noop;
|
|
12
|
-
state.rejecter = noop;
|
|
13
|
-
state.timer = void 0;
|
|
14
|
-
}
|
|
15
|
-
function onAfter(instance, state) {
|
|
8
|
+
function onAfter(state) {
|
|
16
9
|
if (state.result) state.resolver?.();
|
|
17
10
|
else state.rejecter?.();
|
|
18
|
-
instance.destroy();
|
|
19
11
|
}
|
|
20
12
|
function onCallback(condition, state) {
|
|
21
13
|
try {
|
|
@@ -27,16 +19,11 @@ function onCallback(condition, state) {
|
|
|
27
19
|
state.timer.stop();
|
|
28
20
|
}
|
|
29
21
|
}
|
|
30
|
-
function onError(instance, state) {
|
|
31
|
-
state.rejecter?.();
|
|
32
|
-
instance.destroy();
|
|
33
|
-
}
|
|
34
22
|
function onWhen(type, instance, state) {
|
|
35
23
|
state.timer?.[type]?.();
|
|
36
24
|
return instance;
|
|
37
25
|
}
|
|
38
26
|
function startWhen(state, resolve) {
|
|
39
|
-
if (state.timer == null) throw new Error(MESSAGE_DESTROYED);
|
|
40
27
|
if (state.started) throw new Error(MESSAGE_STARTED);
|
|
41
28
|
state.started = true;
|
|
42
29
|
state.timer.start();
|
|
@@ -64,18 +51,18 @@ function when(condition, options) {
|
|
|
64
51
|
callback: () => onCallback(condition, state),
|
|
65
52
|
trace: new TimerTrace().stack
|
|
66
53
|
}, {
|
|
67
|
-
onAfter: () => onAfter(
|
|
68
|
-
onError: () =>
|
|
54
|
+
onAfter: () => onAfter(state),
|
|
55
|
+
onError: () => state.rejecter?.(),
|
|
69
56
|
count: getValidNumber(options?.count),
|
|
70
57
|
interval: getValidNumber(options?.interval),
|
|
71
58
|
timeout: getValidTimeout(options?.timeout)
|
|
72
59
|
}, false);
|
|
73
60
|
instance = {
|
|
74
61
|
continue: () => onWhen(WORK_CONTINUE, instance, state),
|
|
75
|
-
destroy:
|
|
76
|
-
pause: () => onWhen(
|
|
62
|
+
destroy: noop,
|
|
63
|
+
pause: () => onWhen(WORK_PAUSE, instance, state),
|
|
77
64
|
start: (resolve) => startWhen(state, resolve),
|
|
78
|
-
stop: () => onWhen(
|
|
65
|
+
stop: () => onWhen(WORK_STOP, instance, state)
|
|
79
66
|
};
|
|
80
67
|
Object.defineProperties(instance, {
|
|
81
68
|
$timer: {
|
|
@@ -84,15 +71,15 @@ function when(condition, options) {
|
|
|
84
71
|
},
|
|
85
72
|
active: {
|
|
86
73
|
enumerable: true,
|
|
87
|
-
get: () => state.timer
|
|
74
|
+
get: () => state.timer.active
|
|
88
75
|
},
|
|
89
76
|
destroyed: {
|
|
90
77
|
enumerable: true,
|
|
91
|
-
|
|
78
|
+
value: false
|
|
92
79
|
},
|
|
93
80
|
paused: {
|
|
94
81
|
enumerable: true,
|
|
95
|
-
get: () => state.timer
|
|
82
|
+
get: () => state.timer.paused
|
|
96
83
|
},
|
|
97
84
|
trace: {
|
|
98
85
|
enumerable: true,
|
package/dist/work.d.mts
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
|
-
import { Timer,
|
|
1
|
+
import { Timer, TimerState, WorkHandlerType } from "./models.mjs";
|
|
2
2
|
//#region src/work.d.ts
|
|
3
|
-
declare function stop(
|
|
4
|
-
declare function work(type: WorkHandlerType,
|
|
3
|
+
declare function stop(state: TimerState): Timer;
|
|
4
|
+
declare function work(type: WorkHandlerType, state: TimerState, hide?: boolean): Timer;
|
|
5
5
|
//#endregion
|
|
6
6
|
export { stop, work };
|
package/dist/work.mjs
CHANGED
|
@@ -1,47 +1,39 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { WORK_PAUSE } from "./constants.mjs";
|
|
2
|
+
import { updateStates } from "./misc.mjs";
|
|
2
3
|
//#region src/work.ts
|
|
3
|
-
function finish(
|
|
4
|
+
function finish(state, success) {
|
|
5
|
+
updateStates(state);
|
|
4
6
|
cancelAnimationFrame(state.frame);
|
|
5
|
-
TIMERS_ACTIVE.delete(timer.instance);
|
|
6
7
|
state.active = false;
|
|
7
8
|
state.elapsed = 0;
|
|
8
9
|
state.frame = void 0;
|
|
9
|
-
if (
|
|
10
|
-
else options.onAfter?.(success);
|
|
10
|
+
if (state.name === "wait") state.callback();
|
|
11
|
+
else state.options.onAfter?.(success);
|
|
11
12
|
}
|
|
12
13
|
function ignore(type, state) {
|
|
13
|
-
if (state.destroyed) return type !== WORK_STOP;
|
|
14
14
|
if (state.paused) return type === "pause" || type === "start";
|
|
15
|
-
return state.active && type === "start";
|
|
15
|
+
return state.active && (type === "continue" || type === "start");
|
|
16
16
|
}
|
|
17
|
-
function
|
|
18
|
-
cancelAnimationFrame(state.frame);
|
|
19
|
-
state.frame = void 0;
|
|
20
|
-
return timer.instance;
|
|
21
|
-
}
|
|
22
|
-
function run(timer, state, options) {
|
|
17
|
+
function run(state) {
|
|
23
18
|
let last;
|
|
24
|
-
let start;
|
|
25
19
|
return function step(now) {
|
|
26
20
|
if (!state.active) return;
|
|
27
21
|
last ??= now;
|
|
28
|
-
start ??= now;
|
|
29
22
|
const difference = now - last;
|
|
30
23
|
state.elapsed += difference;
|
|
31
24
|
state.total += difference;
|
|
32
25
|
last = now;
|
|
33
|
-
if (options.timeout > 0 && state.total >= options.timeout) {
|
|
34
|
-
options.onError?.();
|
|
35
|
-
finish(
|
|
26
|
+
if (state.options.timeout > 0 && state.total >= state.options.timeout) {
|
|
27
|
+
state.options.onError?.();
|
|
28
|
+
finish(state, false);
|
|
36
29
|
return;
|
|
37
30
|
}
|
|
38
|
-
if (options.interval === 0 || state.elapsed >= options.interval - 5) {
|
|
39
|
-
if (options.count > -1) state.callback(state.index);
|
|
40
|
-
start = now;
|
|
31
|
+
if (state.options.interval === 0 || state.elapsed >= state.options.interval - 5) {
|
|
32
|
+
if (state.options.count > -1) state.callback(state.index);
|
|
41
33
|
state.elapsed = 0;
|
|
42
34
|
state.index += 1;
|
|
43
|
-
if (options.count === -1 || options.count > 0 && state.index >= options.count) {
|
|
44
|
-
finish(
|
|
35
|
+
if (state.options.count === -1 || state.options.count > 0 && state.index >= state.options.count) {
|
|
36
|
+
finish(state, true);
|
|
45
37
|
return;
|
|
46
38
|
}
|
|
47
39
|
}
|
|
@@ -54,30 +46,30 @@ function setState(type, state) {
|
|
|
54
46
|
state.index = pausable ? state.index : 0;
|
|
55
47
|
state.total = pausable ? state.total : 0;
|
|
56
48
|
}
|
|
57
|
-
function stop(
|
|
49
|
+
function stop(state) {
|
|
50
|
+
updateStates(state);
|
|
58
51
|
cancelAnimationFrame(state.frame);
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
state.active = !stop;
|
|
52
|
+
state.options.onAfter?.(false);
|
|
53
|
+
state.active = false;
|
|
62
54
|
state.frame = void 0;
|
|
63
55
|
state.paused = false;
|
|
64
|
-
return timer
|
|
56
|
+
return state.timer;
|
|
65
57
|
}
|
|
66
|
-
function work(type,
|
|
67
|
-
if (ignore(type, state)) return timer
|
|
58
|
+
function work(type, state, hide) {
|
|
59
|
+
if (ignore(type, state)) return state.timer;
|
|
68
60
|
setState(type, state);
|
|
69
|
-
if (type === "stop") return stop(
|
|
61
|
+
if (type === "stop") return stop(state);
|
|
70
62
|
if (type === "pause" || type === "restart") {
|
|
71
63
|
cancelAnimationFrame(state.frame);
|
|
72
64
|
state.frame = void 0;
|
|
73
65
|
}
|
|
74
66
|
state.active = true;
|
|
75
67
|
state.paused = type === WORK_PAUSE;
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
const runner = run(
|
|
68
|
+
updateStates(state, state.paused ? hide : false);
|
|
69
|
+
if (state.paused) return state.timer;
|
|
70
|
+
const runner = run(state);
|
|
79
71
|
state.frame = requestAnimationFrame(runner);
|
|
80
|
-
return timer
|
|
72
|
+
return state.timer;
|
|
81
73
|
}
|
|
82
74
|
//#endregion
|
|
83
75
|
export { stop, work };
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@oscarpalmer/timer",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.46.0",
|
|
4
4
|
"description": "A better solution for timeout- and interval-based timers.",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"requestAnimationFrame",
|
|
@@ -30,10 +30,6 @@
|
|
|
30
30
|
"types": "./dist/index.d.mts",
|
|
31
31
|
"default": "./dist/index.mjs"
|
|
32
32
|
},
|
|
33
|
-
"./delay": {
|
|
34
|
-
"types": "./dist/delay.d.mts",
|
|
35
|
-
"default": "./dist/delay.mjs"
|
|
36
|
-
},
|
|
37
33
|
"./models": {
|
|
38
34
|
"types": "./dist/models.d.mts",
|
|
39
35
|
"default": "./dist/models.mjs"
|
|
@@ -64,7 +60,7 @@
|
|
|
64
60
|
},
|
|
65
61
|
"devDependencies": {
|
|
66
62
|
"@oxlint/plugins": "^1.80",
|
|
67
|
-
"@types/node": "^26.
|
|
63
|
+
"@types/node": "^26.4",
|
|
68
64
|
"@vitest/coverage-istanbul": "^4.1",
|
|
69
65
|
"jsdom": "^30",
|
|
70
66
|
"tsdown": "^0.22",
|
package/src/constants.ts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import type {
|
|
1
|
+
import type {TimerName, TimerStates, WorkHandlerType} from './models';
|
|
2
2
|
|
|
3
3
|
/**
|
|
4
4
|
* Buffer value to use when evaluating if a specific time is within a certain range
|
|
@@ -7,25 +7,15 @@ export const BUFFER_INTERVAL = 5;
|
|
|
7
7
|
|
|
8
8
|
export const DEFAULT_TIMEOUT = 30_000;
|
|
9
9
|
|
|
10
|
-
/**
|
|
11
|
-
* Message to show when a when-timer is destroyed
|
|
12
|
-
*/
|
|
13
|
-
export const MESSAGE_DESTROYED = 'Timer has already been destroyed';
|
|
14
|
-
|
|
15
10
|
/**
|
|
16
11
|
* Message to show when a when-timer is started
|
|
17
12
|
*/
|
|
18
13
|
export const MESSAGE_STARTED = 'Timer has already been started';
|
|
19
14
|
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
/**
|
|
26
|
-
* A set of timers that were paused due to the document being hidden
|
|
27
|
-
*/
|
|
28
|
-
export const TIMERS_HIDDEN = new Set<Timer>();
|
|
15
|
+
export const STATES: TimerStates = {
|
|
16
|
+
active: new Set(),
|
|
17
|
+
hidden: new Set(),
|
|
18
|
+
};
|
|
29
19
|
|
|
30
20
|
export const TYPE_REPEAT: TimerName = 'repeat';
|
|
31
21
|
|
package/src/global.ts
CHANGED
|
@@ -1,29 +1,19 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import {STATES} from './constants';
|
|
2
|
+
import {onVisibilityChange} from './misc';
|
|
2
3
|
import type {Timer} from './models';
|
|
3
4
|
|
|
4
5
|
declare global {
|
|
5
6
|
var _oscarpalmer_timer_debug: boolean | undefined;
|
|
7
|
+
/**
|
|
8
|
+
* All active timers _(or `undefined` if debugging is not enabled)_
|
|
9
|
+
*/
|
|
6
10
|
var _oscarpalmer_timers: Timer[] | undefined;
|
|
7
11
|
}
|
|
8
12
|
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
},
|
|
14
|
-
});
|
|
15
|
-
}
|
|
16
|
-
|
|
17
|
-
/* istanbul ignore next */
|
|
18
|
-
document.addEventListener('visibilitychange', () => {
|
|
19
|
-
const from = document.hidden ? TIMERS_ACTIVE : TIMERS_HIDDEN;
|
|
20
|
-
const method = document.hidden ? WORK_PAUSE : WORK_CONTINUE;
|
|
21
|
-
const to = document.hidden ? TIMERS_HIDDEN : TIMERS_ACTIVE;
|
|
22
|
-
|
|
23
|
-
for (const timer of from) {
|
|
24
|
-
timer[method]();
|
|
25
|
-
to.add(timer);
|
|
26
|
-
}
|
|
27
|
-
|
|
28
|
-
from.clear();
|
|
13
|
+
Object.defineProperty(globalThis, '_oscarpalmer_timers', {
|
|
14
|
+
get() {
|
|
15
|
+
return globalThis._oscarpalmer_timer_debug ? [...STATES.active].map(state => state.timer) : [];
|
|
16
|
+
},
|
|
29
17
|
});
|
|
18
|
+
|
|
19
|
+
document.addEventListener('visibilitychange', onVisibilityChange);
|
package/src/index.ts
CHANGED
package/src/misc.ts
ADDED
|
@@ -0,0 +1,55 @@
|
|
|
1
|
+
import {noop} from '@oscarpalmer/atoms/function';
|
|
2
|
+
import type {GenericCallback} from '@oscarpalmer/atoms/models';
|
|
3
|
+
import {DEFAULT_TIMEOUT, STATES, WORK_CONTINUE, WORK_PAUSE} from './constants';
|
|
4
|
+
import type {TimerState} from './models';
|
|
5
|
+
import {work} from './work';
|
|
6
|
+
|
|
7
|
+
export function getCallback(value: unknown): GenericCallback {
|
|
8
|
+
return typeof value === 'function' ? (value as GenericCallback) : noop;
|
|
9
|
+
}
|
|
10
|
+
|
|
11
|
+
export function getValidNumber(value: unknown, defaultValue?: number): number {
|
|
12
|
+
const actualDefault = defaultValue ?? 0;
|
|
13
|
+
|
|
14
|
+
return typeof value === 'number' && value > actualDefault ? value : actualDefault;
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
export function getValidTimeout(value: unknown): number {
|
|
18
|
+
return typeof value === 'number' && value > 0 ? value : DEFAULT_TIMEOUT;
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
/* istanbul ignore next */
|
|
22
|
+
export function onVisibilityChange(): void {
|
|
23
|
+
const from = document.hidden ? STATES.active : STATES.hidden;
|
|
24
|
+
const type = document.hidden ? WORK_PAUSE : WORK_CONTINUE;
|
|
25
|
+
|
|
26
|
+
for (const stored of from) {
|
|
27
|
+
const state = stored instanceof WeakRef ? stored.deref() : stored;
|
|
28
|
+
|
|
29
|
+
if (state == null) {
|
|
30
|
+
from.delete(stored as never);
|
|
31
|
+
} else {
|
|
32
|
+
work(type, state, true);
|
|
33
|
+
}
|
|
34
|
+
}
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
export function updateStates(state: TimerState, hide?: boolean): void {
|
|
38
|
+
STATES.active.delete(state);
|
|
39
|
+
|
|
40
|
+
/* istanbul ignore next */
|
|
41
|
+
STATES.hidden.delete(state.reference!);
|
|
42
|
+
|
|
43
|
+
if (hide == null) {
|
|
44
|
+
return;
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
/* istanbul ignore if */
|
|
48
|
+
if (hide) {
|
|
49
|
+
state.reference ??= new WeakRef(state);
|
|
50
|
+
|
|
51
|
+
STATES.hidden.add(state.reference);
|
|
52
|
+
} else {
|
|
53
|
+
STATES.active.add(state);
|
|
54
|
+
}
|
|
55
|
+
}
|
package/src/models.ts
CHANGED
|
@@ -32,6 +32,8 @@ export type Timer = {
|
|
|
32
32
|
|
|
33
33
|
/**
|
|
34
34
|
* Is the timer destroyed?
|
|
35
|
+
*
|
|
36
|
+
* @deprecated Timers take care of their own cleanup; this always returns `false`
|
|
35
37
|
*/
|
|
36
38
|
get destroyed(): boolean;
|
|
37
39
|
|
|
@@ -52,6 +54,8 @@ export type Timer = {
|
|
|
52
54
|
|
|
53
55
|
/**
|
|
54
56
|
* Destroy the timer
|
|
57
|
+
*
|
|
58
|
+
* @deprecated Timers take care of their own cleanup
|
|
55
59
|
*/
|
|
56
60
|
destroy(): void;
|
|
57
61
|
|
|
@@ -91,11 +95,26 @@ export type TimerState = {
|
|
|
91
95
|
callback: () => void;
|
|
92
96
|
destroyed: boolean;
|
|
93
97
|
elapsed: number;
|
|
94
|
-
frame
|
|
98
|
+
frame?: number;
|
|
95
99
|
index: number;
|
|
100
|
+
name: TimerName;
|
|
101
|
+
options: TimerOptions;
|
|
96
102
|
paused: boolean;
|
|
103
|
+
reference?: WeakRef<TimerState>;
|
|
104
|
+
timer: Timer;
|
|
97
105
|
total: number;
|
|
98
|
-
trace
|
|
106
|
+
trace?: string;
|
|
107
|
+
};
|
|
108
|
+
|
|
109
|
+
export type TimerStates = {
|
|
110
|
+
/**
|
|
111
|
+
* A set of all active timers
|
|
112
|
+
*/
|
|
113
|
+
active: Set<TimerState>;
|
|
114
|
+
/**
|
|
115
|
+
* A set of timers that were paused due to the document being hidden
|
|
116
|
+
*/
|
|
117
|
+
hidden: Set<WeakRef<TimerState>>;
|
|
99
118
|
};
|
|
100
119
|
|
|
101
120
|
export class TimerTrace extends Error {
|
|
@@ -114,6 +133,8 @@ export type When = {
|
|
|
114
133
|
|
|
115
134
|
/**
|
|
116
135
|
* Is the timer destroyed?
|
|
136
|
+
*
|
|
137
|
+
* @deprecated Timers take care of their own cleanup; this always returns `false`
|
|
117
138
|
*/
|
|
118
139
|
get destroyed(): boolean;
|
|
119
140
|
|
|
@@ -134,6 +155,8 @@ export type When = {
|
|
|
134
155
|
|
|
135
156
|
/**
|
|
136
157
|
* Destroys the timer _(and stops it,if it was running)_
|
|
158
|
+
*
|
|
159
|
+
* @deprecated Timers take care of their own cleanup
|
|
137
160
|
*/
|
|
138
161
|
destroy(): void;
|
|
139
162
|
|
package/src/repeat.ts
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import {TYPE_REPEAT} from './constants';
|
|
2
|
-
import {getCallback, getValidNumber} from './
|
|
2
|
+
import {getCallback, getValidNumber} from './misc';
|
|
3
3
|
import './global';
|
|
4
4
|
import {type RepeatOptions, type Timer, TimerTrace} from './models';
|
|
5
5
|
import {createTimer} from './timer';
|
package/src/timer.ts
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import {noop} from '@oscarpalmer/atoms/function';
|
|
2
2
|
import {WORK_CONTINUE, WORK_PAUSE, WORK_RESTART, WORK_START, WORK_STOP} from './constants';
|
|
3
|
-
import type {Timer, TimerName, TimerOptions, TimerState
|
|
4
|
-
import {
|
|
3
|
+
import type {Timer, TimerName, TimerOptions, TimerState} from './models';
|
|
4
|
+
import {work} from './work';
|
|
5
5
|
|
|
6
6
|
export function createTimer(
|
|
7
7
|
name: TimerName,
|
|
@@ -9,36 +9,27 @@ export function createTimer(
|
|
|
9
9
|
options: TimerOptions,
|
|
10
10
|
start: boolean,
|
|
11
11
|
): Timer {
|
|
12
|
-
function worker(type: WorkHandlerType): Timer {
|
|
13
|
-
return work(
|
|
14
|
-
type,
|
|
15
|
-
{
|
|
16
|
-
name,
|
|
17
|
-
instance: instance as Timer,
|
|
18
|
-
},
|
|
19
|
-
state,
|
|
20
|
-
options,
|
|
21
|
-
);
|
|
22
|
-
}
|
|
23
|
-
|
|
24
12
|
const state: TimerState = {
|
|
25
13
|
...pick,
|
|
14
|
+
name,
|
|
15
|
+
options,
|
|
26
16
|
active: false,
|
|
27
17
|
destroyed: false,
|
|
28
18
|
elapsed: 0,
|
|
29
19
|
frame: undefined,
|
|
30
20
|
index: 0,
|
|
31
21
|
paused: false,
|
|
22
|
+
timer: undefined as never,
|
|
32
23
|
total: 0,
|
|
33
24
|
};
|
|
34
25
|
|
|
35
26
|
const instance = {
|
|
36
|
-
continue: () =>
|
|
37
|
-
destroy:
|
|
38
|
-
pause: () =>
|
|
39
|
-
restart: () =>
|
|
40
|
-
start: () =>
|
|
41
|
-
stop: () =>
|
|
27
|
+
continue: () => work(WORK_CONTINUE, state),
|
|
28
|
+
destroy: noop,
|
|
29
|
+
pause: () => work(WORK_PAUSE, state),
|
|
30
|
+
restart: () => work(WORK_RESTART, state),
|
|
31
|
+
start: () => work(WORK_START, state),
|
|
32
|
+
stop: () => work(WORK_STOP, state),
|
|
42
33
|
};
|
|
43
34
|
|
|
44
35
|
Object.defineProperties(instance, {
|
|
@@ -48,11 +39,11 @@ export function createTimer(
|
|
|
48
39
|
},
|
|
49
40
|
active: {
|
|
50
41
|
enumerable: true,
|
|
51
|
-
get: () => state.active,
|
|
42
|
+
get: () => state.active && !state.paused,
|
|
52
43
|
},
|
|
53
44
|
destroyed: {
|
|
54
45
|
enumerable: true,
|
|
55
|
-
|
|
46
|
+
value: false,
|
|
56
47
|
},
|
|
57
48
|
paused: {
|
|
58
49
|
enumerable: true,
|
|
@@ -64,28 +55,11 @@ export function createTimer(
|
|
|
64
55
|
},
|
|
65
56
|
});
|
|
66
57
|
|
|
67
|
-
|
|
68
|
-
instance.start();
|
|
69
|
-
}
|
|
70
|
-
|
|
71
|
-
return Object.freeze(instance) as Timer;
|
|
72
|
-
}
|
|
58
|
+
state.timer = Object.freeze(instance) as Timer;
|
|
73
59
|
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
instance: Timer,
|
|
77
|
-
state: TimerState,
|
|
78
|
-
options: TimerOptions,
|
|
79
|
-
): void {
|
|
80
|
-
state.destroyed = true;
|
|
81
|
-
|
|
82
|
-
options.onAfter = noop;
|
|
83
|
-
options.onError = noop;
|
|
84
|
-
state.callback = noop;
|
|
85
|
-
|
|
86
|
-
if (!globalThis._oscarpalmer_timer_debug) {
|
|
87
|
-
state.trace = undefined;
|
|
60
|
+
if (start) {
|
|
61
|
+
state.timer.start();
|
|
88
62
|
}
|
|
89
63
|
|
|
90
|
-
|
|
64
|
+
return state.timer;
|
|
91
65
|
}
|
package/src/wait.ts
CHANGED