@oscarpalmer/timer 0.47.0 → 0.49.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 +15 -14
- package/dist/constants.mjs +3 -1
- package/dist/global.d.mts +2 -1
- package/dist/global.mjs +5 -3
- package/dist/index.d.mts +9 -8
- package/dist/index.mjs +146 -106
- package/dist/is.d.mts +5 -6
- package/dist/is.mjs +11 -11
- package/dist/misc.d.mts +8 -7
- package/dist/misc.mjs +5 -1
- package/dist/models.d.mts +15 -15
- package/dist/repeat.d.mts +2 -3
- package/dist/timer.d.mts +3 -3
- package/dist/timer.mjs +54 -38
- package/dist/wait.d.mts +2 -3
- package/dist/when.d.mts +3 -3
- package/dist/when.mjs +67 -54
- package/dist/work.d.mts +3 -4
- package/dist/work.mjs +8 -7
- package/package.json +5 -5
- package/src/constants.ts +8 -0
- package/src/global.ts +23 -7
- package/src/is.ts +20 -12
- package/src/misc.ts +15 -0
- package/src/models.ts +9 -4
- package/src/repeat.ts +4 -0
- package/src/timer.ts +110 -51
- package/src/wait.ts +4 -0
- package/src/when.ts +128 -66
- package/src/work.ts +15 -9
package/dist/models.d.mts
CHANGED
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
/**
|
|
3
3
|
* Options for a repeating timer
|
|
4
4
|
*/
|
|
5
|
-
type RepeatOptions = {
|
|
5
|
+
export type RepeatOptions = {
|
|
6
6
|
/**
|
|
7
7
|
* Callback to be called when the timer has stopped, either manually or by completing its work
|
|
8
8
|
*/
|
|
@@ -24,7 +24,7 @@ type RepeatOptions = {
|
|
|
24
24
|
*/
|
|
25
25
|
timeout: number;
|
|
26
26
|
};
|
|
27
|
-
type Timer = {
|
|
27
|
+
export type Timer = {
|
|
28
28
|
/**
|
|
29
29
|
* Is the timer active?
|
|
30
30
|
*/
|
|
@@ -70,15 +70,15 @@ type Timer = {
|
|
|
70
70
|
*/
|
|
71
71
|
stop(): Timer;
|
|
72
72
|
};
|
|
73
|
-
type TimerName = 'repeat' | 'wait' | 'when';
|
|
74
|
-
type TimerOptions = {
|
|
73
|
+
export type TimerName = 'repeat' | 'wait' | 'when';
|
|
74
|
+
export type TimerOptions = {
|
|
75
75
|
onAfter: ((finished: boolean) => void) | undefined;
|
|
76
76
|
onError: (() => void) | undefined;
|
|
77
77
|
count: number;
|
|
78
78
|
interval: number;
|
|
79
79
|
timeout: number;
|
|
80
80
|
};
|
|
81
|
-
type TimerState = {
|
|
81
|
+
export type TimerState = {
|
|
82
82
|
active: boolean;
|
|
83
83
|
callback: () => void;
|
|
84
84
|
destroyed: boolean;
|
|
@@ -93,7 +93,7 @@ type TimerState = {
|
|
|
93
93
|
total: number;
|
|
94
94
|
trace?: string;
|
|
95
95
|
};
|
|
96
|
-
type TimerStates = {
|
|
96
|
+
export type TimerStates = {
|
|
97
97
|
/**
|
|
98
98
|
* A set of all active timers
|
|
99
99
|
*/
|
|
@@ -103,10 +103,10 @@ type TimerStates = {
|
|
|
103
103
|
*/
|
|
104
104
|
hidden: Set<WeakRef<TimerState>>;
|
|
105
105
|
};
|
|
106
|
-
declare class TimerTrace extends Error {
|
|
106
|
+
export declare class TimerTrace extends Error {
|
|
107
107
|
constructor();
|
|
108
108
|
}
|
|
109
|
-
type When = {
|
|
109
|
+
export type When = {
|
|
110
110
|
/**
|
|
111
111
|
* Is the timer active?
|
|
112
112
|
*/
|
|
@@ -154,7 +154,7 @@ type When = {
|
|
|
154
154
|
/**
|
|
155
155
|
* Options for a conditional timer
|
|
156
156
|
*/
|
|
157
|
-
type WhenOptions = {
|
|
157
|
+
export type WhenOptions = {
|
|
158
158
|
/**
|
|
159
159
|
* How many times the timer should check the condition
|
|
160
160
|
*/
|
|
@@ -168,7 +168,8 @@ type WhenOptions = {
|
|
|
168
168
|
*/
|
|
169
169
|
timeout: number;
|
|
170
170
|
};
|
|
171
|
-
type WhenState = {
|
|
171
|
+
export type WhenState = {
|
|
172
|
+
name: TimerName;
|
|
172
173
|
promise: Promise<void>;
|
|
173
174
|
rejecter?: () => void;
|
|
174
175
|
resolver?: () => void;
|
|
@@ -176,11 +177,10 @@ type WhenState = {
|
|
|
176
177
|
started: boolean;
|
|
177
178
|
timer: Timer;
|
|
178
179
|
};
|
|
179
|
-
type WorkHandler = (type: WorkHandlerType, timer: WorkHandlerTimer, state: TimerState, options: TimerOptions) => Timer;
|
|
180
|
-
type WorkHandlerTimer = {
|
|
180
|
+
export type WorkHandler = (type: WorkHandlerType, timer: WorkHandlerTimer, state: TimerState, options: TimerOptions) => Timer;
|
|
181
|
+
export type WorkHandlerTimer = {
|
|
181
182
|
instance: Timer;
|
|
182
183
|
name: TimerName;
|
|
183
184
|
};
|
|
184
|
-
type WorkHandlerType = 'continue' | 'pause' | 'restart' | 'start' | 'stop';
|
|
185
|
-
//#endregion
|
|
186
|
-
export { RepeatOptions, Timer, TimerName, TimerOptions, TimerState, TimerStates, TimerTrace, When, WhenOptions, WhenState, WorkHandler, WorkHandlerTimer, WorkHandlerType };
|
|
185
|
+
export type WorkHandlerType = 'continue' | 'pause' | 'restart' | 'start' | 'stop';
|
|
186
|
+
//#endregion
|
package/dist/repeat.d.mts
CHANGED
|
@@ -8,6 +8,5 @@ import "./global.mjs";
|
|
|
8
8
|
* @param options Timer options
|
|
9
9
|
* @returns Repeating timer
|
|
10
10
|
*/
|
|
11
|
-
declare function repeat(callback: (index: number) => void, options?: Partial<RepeatOptions>): Timer;
|
|
12
|
-
//#endregion
|
|
13
|
-
export { repeat };
|
|
11
|
+
export declare function repeat(callback: (index: number) => void, options?: Partial<RepeatOptions>): Timer;
|
|
12
|
+
//#endregion
|
package/dist/timer.d.mts
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { Timer, TimerName, TimerOptions, TimerState } from "./models.mjs";
|
|
2
2
|
//#region src/timer.d.ts
|
|
3
|
-
declare function
|
|
4
|
-
|
|
5
|
-
|
|
3
|
+
declare function Timer(this: any, name: TimerName, state: Pick<TimerState, 'callback' | 'trace'>, options: TimerOptions, start: boolean): void;
|
|
4
|
+
export declare function createTimer(name: TimerName, state: Pick<TimerState, 'callback' | 'trace'>, options: TimerOptions, start: boolean): Timer;
|
|
5
|
+
//#endregion
|
package/dist/timer.mjs
CHANGED
|
@@ -1,10 +1,9 @@
|
|
|
1
|
-
import { WORK_CONTINUE, WORK_PAUSE, WORK_RESTART, WORK_START, WORK_STOP } from "./constants.mjs";
|
|
1
|
+
import { SYMBOL, WORK_CONTINUE, WORK_PAUSE, WORK_RESTART, WORK_START, WORK_STOP } from "./constants.mjs";
|
|
2
2
|
import { work } from "./work.mjs";
|
|
3
|
-
import { noop } from "@oscarpalmer/atoms/function";
|
|
4
3
|
//#region src/timer.ts
|
|
5
|
-
function
|
|
6
|
-
|
|
7
|
-
...
|
|
4
|
+
function Timer(name, state, options, start) {
|
|
5
|
+
Object.defineProperty(this, SYMBOL, { value: {
|
|
6
|
+
...state,
|
|
8
7
|
name,
|
|
9
8
|
options,
|
|
10
9
|
active: false,
|
|
@@ -15,40 +14,57 @@ function createTimer(name, pick, options, start) {
|
|
|
15
14
|
paused: false,
|
|
16
15
|
timer: void 0,
|
|
17
16
|
total: 0
|
|
18
|
-
};
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
get: () => state.active && !state.paused
|
|
35
|
-
},
|
|
36
|
-
destroyed: {
|
|
37
|
-
enumerable: true,
|
|
38
|
-
value: false
|
|
39
|
-
},
|
|
40
|
-
paused: {
|
|
41
|
-
enumerable: true,
|
|
42
|
-
get: () => state.paused
|
|
43
|
-
},
|
|
44
|
-
trace: {
|
|
45
|
-
enumerable: true,
|
|
46
|
-
get: () => globalThis._oscarpalmer_timer_debug ?? false ? state.trace : void 0
|
|
17
|
+
} });
|
|
18
|
+
if (start) startTimer.call(this);
|
|
19
|
+
}
|
|
20
|
+
Object.defineProperties(Timer.prototype, {
|
|
21
|
+
active: {
|
|
22
|
+
enumerable: true,
|
|
23
|
+
get() {
|
|
24
|
+
return isActiveTimer.call(this);
|
|
25
|
+
}
|
|
26
|
+
},
|
|
27
|
+
continue: { value: continueTimer },
|
|
28
|
+
pause: { value: pauseTimer },
|
|
29
|
+
paused: {
|
|
30
|
+
enumerable: true,
|
|
31
|
+
get() {
|
|
32
|
+
return isPausedTimer.call(this);
|
|
47
33
|
}
|
|
48
|
-
}
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
34
|
+
},
|
|
35
|
+
restart: { value: restartTimer },
|
|
36
|
+
start: { value: startTimer },
|
|
37
|
+
stop: { value: stopTimer },
|
|
38
|
+
trace: { get() {
|
|
39
|
+
return getTimerTrace.call(this);
|
|
40
|
+
} }
|
|
41
|
+
});
|
|
42
|
+
function continueTimer() {
|
|
43
|
+
return work(WORK_CONTINUE, this[SYMBOL]);
|
|
44
|
+
}
|
|
45
|
+
function createTimer(name, state, options, start) {
|
|
46
|
+
return new Timer(name, state, options, start);
|
|
47
|
+
}
|
|
48
|
+
function getTimerTrace() {
|
|
49
|
+
return globalThis._oscarpalmer_timer_debug ?? false ? this[SYMBOL].trace : void 0;
|
|
50
|
+
}
|
|
51
|
+
function isActiveTimer() {
|
|
52
|
+
return this[SYMBOL].active && !this[SYMBOL].paused;
|
|
53
|
+
}
|
|
54
|
+
function isPausedTimer() {
|
|
55
|
+
return this[SYMBOL].paused;
|
|
56
|
+
}
|
|
57
|
+
function pauseTimer() {
|
|
58
|
+
return work(WORK_PAUSE, this[SYMBOL]);
|
|
59
|
+
}
|
|
60
|
+
function restartTimer() {
|
|
61
|
+
return work(WORK_RESTART, this[SYMBOL]);
|
|
62
|
+
}
|
|
63
|
+
function startTimer() {
|
|
64
|
+
return work(WORK_START, this[SYMBOL]);
|
|
65
|
+
}
|
|
66
|
+
function stopTimer() {
|
|
67
|
+
return work(WORK_STOP, this[SYMBOL]);
|
|
52
68
|
}
|
|
53
69
|
//#endregion
|
|
54
70
|
export { createTimer };
|
package/dist/wait.d.mts
CHANGED
|
@@ -8,6 +8,5 @@ import "./global.mjs";
|
|
|
8
8
|
* @param time How long to wait for _(in milliseconds; defaults to screen refresh rate)_
|
|
9
9
|
* @returns Waiting timer
|
|
10
10
|
*/
|
|
11
|
-
declare function wait(callback: () => void, time?: number): Timer;
|
|
12
|
-
//#endregion
|
|
13
|
-
export { wait };
|
|
11
|
+
export declare function wait(callback: () => void, time?: number): Timer;
|
|
12
|
+
//#endregion
|
package/dist/when.d.mts
CHANGED
|
@@ -1,12 +1,12 @@
|
|
|
1
1
|
import { When, WhenOptions } from "./models.mjs";
|
|
2
2
|
import "./global.mjs";
|
|
3
3
|
//#region src/when.d.ts
|
|
4
|
+
declare function When(this: any, condition: () => boolean, options: WhenOptions): void;
|
|
4
5
|
/**
|
|
5
6
|
* Create a conditional timer
|
|
6
7
|
* @param condition Condition to check
|
|
7
8
|
* @param options Timer options
|
|
8
9
|
* @returns Timer instance
|
|
9
10
|
*/
|
|
10
|
-
declare function when(condition: () => boolean, options?: Partial<WhenOptions>): When;
|
|
11
|
-
//#endregion
|
|
12
|
-
export { when };
|
|
11
|
+
export declare function when(condition: () => boolean, options?: Partial<WhenOptions>): When;
|
|
12
|
+
//#endregion
|
package/dist/when.mjs
CHANGED
|
@@ -1,10 +1,66 @@
|
|
|
1
|
-
import { MESSAGE_STARTED, TYPE_WHEN, WORK_CONTINUE, WORK_PAUSE, WORK_STOP } from "./constants.mjs";
|
|
1
|
+
import { MESSAGE_STARTED, SYMBOL, TYPE_WHEN, WORK_CONTINUE, WORK_PAUSE, WORK_STOP } from "./constants.mjs";
|
|
2
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
|
-
import { noop } from "@oscarpalmer/atoms/function";
|
|
7
6
|
//#region src/when.ts
|
|
7
|
+
function When(condition, options) {
|
|
8
|
+
const state = {
|
|
9
|
+
name: TYPE_WHEN,
|
|
10
|
+
promise: void 0,
|
|
11
|
+
result: false,
|
|
12
|
+
started: false,
|
|
13
|
+
timer: void 0
|
|
14
|
+
};
|
|
15
|
+
Object.defineProperty(this, SYMBOL, { value: state });
|
|
16
|
+
state.promise = new Promise((resolve, reject) => {
|
|
17
|
+
state.resolver = resolve;
|
|
18
|
+
state.rejecter = reject;
|
|
19
|
+
});
|
|
20
|
+
state.timer = createTimer(TYPE_WHEN, {
|
|
21
|
+
callback: () => onCallback(condition, state),
|
|
22
|
+
trace: new TimerTrace().stack
|
|
23
|
+
}, {
|
|
24
|
+
...options,
|
|
25
|
+
onAfter: () => onAfter(state),
|
|
26
|
+
onError: () => state.rejecter?.()
|
|
27
|
+
}, false);
|
|
28
|
+
}
|
|
29
|
+
Object.defineProperties(When.prototype, {
|
|
30
|
+
active: { get() {
|
|
31
|
+
return isActiveWhen.call(this);
|
|
32
|
+
} },
|
|
33
|
+
continue: { value: continueWhen },
|
|
34
|
+
pause: { value: pauseWhen },
|
|
35
|
+
paused: { get() {
|
|
36
|
+
return isPausedWhen.call(this);
|
|
37
|
+
} },
|
|
38
|
+
start: { value: startWhen },
|
|
39
|
+
stop: { value: stopWhen },
|
|
40
|
+
trace: { get() {
|
|
41
|
+
return getWhenTrace.call(this);
|
|
42
|
+
} }
|
|
43
|
+
});
|
|
44
|
+
function continueWhen() {
|
|
45
|
+
return onWhen(WORK_CONTINUE, this, this[SYMBOL]);
|
|
46
|
+
}
|
|
47
|
+
function getWhenOptions(input) {
|
|
48
|
+
const options = typeof input === "object" && input !== null ? input : {};
|
|
49
|
+
return {
|
|
50
|
+
count: getValidNumber(options?.count),
|
|
51
|
+
interval: getValidNumber(options?.interval),
|
|
52
|
+
timeout: getValidTimeout(options?.timeout)
|
|
53
|
+
};
|
|
54
|
+
}
|
|
55
|
+
function getWhenTrace() {
|
|
56
|
+
return globalThis._oscarpalmer_timer_debug ?? false ? this[SYMBOL].timer?.trace : void 0;
|
|
57
|
+
}
|
|
58
|
+
function isActiveWhen() {
|
|
59
|
+
return this[SYMBOL].timer.active;
|
|
60
|
+
}
|
|
61
|
+
function isPausedWhen() {
|
|
62
|
+
return this[SYMBOL].timer.paused;
|
|
63
|
+
}
|
|
8
64
|
function onAfter(state) {
|
|
9
65
|
if (state.result) state.resolver?.();
|
|
10
66
|
else state.rejecter?.();
|
|
@@ -23,12 +79,19 @@ function onWhen(type, instance, state) {
|
|
|
23
79
|
state.timer?.[type]?.();
|
|
24
80
|
return instance;
|
|
25
81
|
}
|
|
26
|
-
function
|
|
82
|
+
function pauseWhen() {
|
|
83
|
+
return onWhen(WORK_PAUSE, this, this[SYMBOL]);
|
|
84
|
+
}
|
|
85
|
+
function startWhen(resolve) {
|
|
86
|
+
const state = this[SYMBOL];
|
|
27
87
|
if (state.started) throw new Error(MESSAGE_STARTED);
|
|
28
88
|
state.started = true;
|
|
29
89
|
state.timer.start();
|
|
30
90
|
return state.promise.then(resolve);
|
|
31
91
|
}
|
|
92
|
+
function stopWhen() {
|
|
93
|
+
return onWhen(WORK_STOP, this, this[SYMBOL]);
|
|
94
|
+
}
|
|
32
95
|
/**
|
|
33
96
|
* Create a conditional timer
|
|
34
97
|
* @param condition Condition to check
|
|
@@ -36,57 +99,7 @@ function startWhen(state, resolve) {
|
|
|
36
99
|
* @returns Timer instance
|
|
37
100
|
*/
|
|
38
101
|
function when(condition, options) {
|
|
39
|
-
|
|
40
|
-
promise: void 0,
|
|
41
|
-
result: false,
|
|
42
|
-
started: false,
|
|
43
|
-
timer: void 0
|
|
44
|
-
};
|
|
45
|
-
let instance;
|
|
46
|
-
state.promise = new Promise((resolve, reject) => {
|
|
47
|
-
state.resolver = resolve;
|
|
48
|
-
state.rejecter = reject;
|
|
49
|
-
});
|
|
50
|
-
state.timer = createTimer(TYPE_WHEN, {
|
|
51
|
-
callback: () => onCallback(condition, state),
|
|
52
|
-
trace: new TimerTrace().stack
|
|
53
|
-
}, {
|
|
54
|
-
onAfter: () => onAfter(state),
|
|
55
|
-
onError: () => state.rejecter?.(),
|
|
56
|
-
count: getValidNumber(options?.count),
|
|
57
|
-
interval: getValidNumber(options?.interval),
|
|
58
|
-
timeout: getValidTimeout(options?.timeout)
|
|
59
|
-
}, false);
|
|
60
|
-
instance = {
|
|
61
|
-
continue: () => onWhen(WORK_CONTINUE, instance, state),
|
|
62
|
-
destroy: noop,
|
|
63
|
-
pause: () => onWhen(WORK_PAUSE, instance, state),
|
|
64
|
-
start: (resolve) => startWhen(state, resolve),
|
|
65
|
-
stop: () => onWhen(WORK_STOP, instance, state)
|
|
66
|
-
};
|
|
67
|
-
Object.defineProperties(instance, {
|
|
68
|
-
$timer: {
|
|
69
|
-
enumerable: false,
|
|
70
|
-
value: TYPE_WHEN
|
|
71
|
-
},
|
|
72
|
-
active: {
|
|
73
|
-
enumerable: true,
|
|
74
|
-
get: () => state.timer.active
|
|
75
|
-
},
|
|
76
|
-
destroyed: {
|
|
77
|
-
enumerable: true,
|
|
78
|
-
value: false
|
|
79
|
-
},
|
|
80
|
-
paused: {
|
|
81
|
-
enumerable: true,
|
|
82
|
-
get: () => state.timer.paused
|
|
83
|
-
},
|
|
84
|
-
trace: {
|
|
85
|
-
enumerable: true,
|
|
86
|
-
get: () => globalThis._oscarpalmer_timer_debug ?? false ? state.timer?.trace : void 0
|
|
87
|
-
}
|
|
88
|
-
});
|
|
89
|
-
return Object.freeze(instance);
|
|
102
|
+
return new When(condition, getWhenOptions(options));
|
|
90
103
|
}
|
|
91
104
|
//#endregion
|
|
92
105
|
export { when };
|
package/dist/work.d.mts
CHANGED
|
@@ -1,6 +1,5 @@
|
|
|
1
1
|
import { Timer, TimerState, WorkHandlerType } from "./models.mjs";
|
|
2
2
|
//#region src/work.d.ts
|
|
3
|
-
declare function stop(state: TimerState): Timer;
|
|
4
|
-
declare function work(type: WorkHandlerType, state: TimerState, hide?: boolean): Timer;
|
|
5
|
-
//#endregion
|
|
6
|
-
export { stop, work };
|
|
3
|
+
export declare function stop(state: TimerState): Timer;
|
|
4
|
+
export declare function work(type: WorkHandlerType, state: TimerState, hide?: boolean): Timer;
|
|
5
|
+
//#endregion
|
package/dist/work.mjs
CHANGED
|
@@ -1,9 +1,9 @@
|
|
|
1
1
|
import { WORK_PAUSE } from "./constants.mjs";
|
|
2
|
-
import { updateStates } from "./misc.mjs";
|
|
2
|
+
import { startTimer, stopTimer, updateStates } from "./misc.mjs";
|
|
3
3
|
//#region src/work.ts
|
|
4
4
|
function finish(state, success) {
|
|
5
5
|
updateStates(state);
|
|
6
|
-
|
|
6
|
+
stopTimer(state.frame);
|
|
7
7
|
state.active = false;
|
|
8
8
|
state.elapsed = 0;
|
|
9
9
|
state.frame = void 0;
|
|
@@ -16,8 +16,9 @@ function ignore(type, state) {
|
|
|
16
16
|
}
|
|
17
17
|
function run(state) {
|
|
18
18
|
let last;
|
|
19
|
-
return function step(
|
|
19
|
+
return function step() {
|
|
20
20
|
if (!state.active) return;
|
|
21
|
+
const now = performance.now();
|
|
21
22
|
last ??= now;
|
|
22
23
|
const difference = now - last;
|
|
23
24
|
state.elapsed += difference;
|
|
@@ -37,7 +38,7 @@ function run(state) {
|
|
|
37
38
|
return;
|
|
38
39
|
}
|
|
39
40
|
}
|
|
40
|
-
state.frame =
|
|
41
|
+
state.frame = startTimer(step);
|
|
41
42
|
};
|
|
42
43
|
}
|
|
43
44
|
function setState(type, state) {
|
|
@@ -48,7 +49,7 @@ function setState(type, state) {
|
|
|
48
49
|
}
|
|
49
50
|
function stop(state) {
|
|
50
51
|
updateStates(state);
|
|
51
|
-
|
|
52
|
+
stopTimer(state.frame);
|
|
52
53
|
state.options.onAfter?.(false);
|
|
53
54
|
state.active = false;
|
|
54
55
|
state.frame = void 0;
|
|
@@ -60,7 +61,7 @@ function work(type, state, hide) {
|
|
|
60
61
|
setState(type, state);
|
|
61
62
|
if (type === "stop") return stop(state);
|
|
62
63
|
if (type === "pause" || type === "restart") {
|
|
63
|
-
|
|
64
|
+
stopTimer(state.frame);
|
|
64
65
|
state.frame = void 0;
|
|
65
66
|
}
|
|
66
67
|
state.active = true;
|
|
@@ -68,7 +69,7 @@ function work(type, state, hide) {
|
|
|
68
69
|
updateStates(state, state.paused ? hide : false);
|
|
69
70
|
if (state.paused) return state.timer;
|
|
70
71
|
const runner = run(state);
|
|
71
|
-
state.frame =
|
|
72
|
+
state.frame = startTimer(runner);
|
|
72
73
|
return state.timer;
|
|
73
74
|
}
|
|
74
75
|
//#endregion
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@oscarpalmer/timer",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.49.0",
|
|
4
4
|
"description": "A better solution for timeout- and interval-based timers.",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"requestAnimationFrame",
|
|
@@ -60,14 +60,14 @@
|
|
|
60
60
|
"watch": "npx vite build --watch"
|
|
61
61
|
},
|
|
62
62
|
"dependencies": {
|
|
63
|
-
"@oscarpalmer/atoms": "^0.
|
|
63
|
+
"@oscarpalmer/atoms": "^0.203"
|
|
64
64
|
},
|
|
65
65
|
"devDependencies": {
|
|
66
|
-
"@oxlint/plugins": "^1.
|
|
67
|
-
"@types/node": "^26.
|
|
66
|
+
"@oxlint/plugins": "^1.82",
|
|
67
|
+
"@types/node": "^26.5",
|
|
68
68
|
"@vitest/coverage-istanbul": "^4.1",
|
|
69
69
|
"jsdom": "^30",
|
|
70
|
-
"tsdown": "^0.
|
|
70
|
+
"tsdown": "^0.23",
|
|
71
71
|
"typescript": "^6",
|
|
72
72
|
"vite": "npm:@voidzero-dev/vite-plus-core@latest",
|
|
73
73
|
"vite-plus": "latest",
|
package/src/constants.ts
CHANGED
|
@@ -1,5 +1,7 @@
|
|
|
1
1
|
import type {TimerName, TimerStates, WorkHandlerType} from './models';
|
|
2
2
|
|
|
3
|
+
// #region Variables
|
|
4
|
+
|
|
3
5
|
/**
|
|
4
6
|
* Buffer value to use when evaluating if a specific time is within a certain range
|
|
5
7
|
*/
|
|
@@ -7,6 +9,8 @@ export const BUFFER_INTERVAL = 5;
|
|
|
7
9
|
|
|
8
10
|
export const DEFAULT_TIMEOUT = 30_000;
|
|
9
11
|
|
|
12
|
+
export const GLOBAL_NAME = '_oscarpalmer_timers';
|
|
13
|
+
|
|
10
14
|
/**
|
|
11
15
|
* Message to show when a when-timer is started
|
|
12
16
|
*/
|
|
@@ -17,6 +21,8 @@ export const STATES: TimerStates = {
|
|
|
17
21
|
hidden: new Set(),
|
|
18
22
|
};
|
|
19
23
|
|
|
24
|
+
export const SYMBOL = Symbol('timer');
|
|
25
|
+
|
|
20
26
|
export const TYPE_REPEAT: TimerName = 'repeat';
|
|
21
27
|
|
|
22
28
|
export const TYPE_WAIT: TimerName = 'wait';
|
|
@@ -32,3 +38,5 @@ export const WORK_RESTART: WorkHandlerType = 'restart';
|
|
|
32
38
|
export const WORK_START: WorkHandlerType = 'start';
|
|
33
39
|
|
|
34
40
|
export const WORK_STOP: WorkHandlerType = 'stop';
|
|
41
|
+
|
|
42
|
+
// #endregion
|
package/src/global.ts
CHANGED
|
@@ -1,7 +1,9 @@
|
|
|
1
|
-
import {STATES} from './constants';
|
|
1
|
+
import {GLOBAL_NAME, STATES} from './constants';
|
|
2
2
|
import {onVisibilityChange} from './misc';
|
|
3
3
|
import type {Timer} from './models';
|
|
4
4
|
|
|
5
|
+
// #region Types
|
|
6
|
+
|
|
5
7
|
declare global {
|
|
6
8
|
var _oscarpalmer_timer_debug: boolean | undefined;
|
|
7
9
|
/**
|
|
@@ -10,10 +12,24 @@ declare global {
|
|
|
10
12
|
var _oscarpalmer_timers: Timer[] | undefined;
|
|
11
13
|
}
|
|
12
14
|
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
15
|
+
// #endregion
|
|
16
|
+
|
|
17
|
+
// #region Initialization
|
|
18
|
+
|
|
19
|
+
/* istanbul ignore next */
|
|
20
|
+
if (!(GLOBAL_NAME in globalThis)) {
|
|
21
|
+
Object.defineProperty(globalThis, GLOBAL_NAME, {
|
|
22
|
+
get() {
|
|
23
|
+
return globalThis._oscarpalmer_timer_debug
|
|
24
|
+
? [...STATES.active].map(state => state.timer)
|
|
25
|
+
: [];
|
|
26
|
+
},
|
|
27
|
+
});
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
/* istanbul ignore next */
|
|
31
|
+
if ('document' in globalThis) {
|
|
32
|
+
document.addEventListener('visibilitychange', onVisibilityChange);
|
|
33
|
+
}
|
|
18
34
|
|
|
19
|
-
|
|
35
|
+
// #endregion
|
package/src/is.ts
CHANGED
|
@@ -1,47 +1,55 @@
|
|
|
1
|
-
import
|
|
2
|
-
import {TYPE_REPEAT, TYPE_WAIT, TYPE_WHEN} from './constants';
|
|
1
|
+
import {SYMBOL, TYPE_REPEAT, TYPE_WAIT, TYPE_WHEN} from './constants';
|
|
3
2
|
import type {Timer, When} from './models';
|
|
4
3
|
|
|
5
|
-
|
|
6
|
-
|
|
4
|
+
// #region Functions
|
|
5
|
+
|
|
6
|
+
function isInstance(names: string[], value: unknown) {
|
|
7
|
+
return (
|
|
8
|
+
typeof value === 'object' &&
|
|
9
|
+
value !== null &&
|
|
10
|
+
SYMBOL in value &&
|
|
11
|
+
names.includes((value as any)[SYMBOL].name as string)
|
|
12
|
+
);
|
|
7
13
|
}
|
|
8
14
|
|
|
9
15
|
/**
|
|
10
16
|
* Is the value a repeating timer?
|
|
11
|
-
*
|
|
17
|
+
*
|
|
12
18
|
* @param value Value to check
|
|
13
19
|
* @returns `true` if the value is a repeating timer, otherwise `false`
|
|
14
20
|
*/
|
|
15
21
|
export function isRepeated(value: unknown): value is Timer {
|
|
16
|
-
return
|
|
22
|
+
return isInstance([TYPE_REPEAT], value);
|
|
17
23
|
}
|
|
18
24
|
|
|
19
25
|
/**
|
|
20
26
|
* Is the value a timer?
|
|
21
|
-
*
|
|
27
|
+
*
|
|
22
28
|
* @param value Value to check
|
|
23
29
|
* @returns `true` if the value is a timer, otherwise `false`
|
|
24
30
|
*/
|
|
25
31
|
export function isTimer(value: unknown): value is Timer {
|
|
26
|
-
return
|
|
32
|
+
return isInstance([TYPE_REPEAT, TYPE_WAIT], value);
|
|
27
33
|
}
|
|
28
34
|
|
|
29
35
|
/**
|
|
30
36
|
* Is the value a waiting timer?
|
|
31
|
-
*
|
|
37
|
+
*
|
|
32
38
|
* @param value Value to check
|
|
33
39
|
* @returns `true` if the value is a waiting timer, otherwise `false`
|
|
34
40
|
*/
|
|
35
41
|
export function isWaited(value: unknown): value is Timer {
|
|
36
|
-
return
|
|
42
|
+
return isInstance([TYPE_WAIT], value);
|
|
37
43
|
}
|
|
38
44
|
|
|
39
45
|
/**
|
|
40
46
|
* Is the value a conditional timer?
|
|
41
|
-
*
|
|
47
|
+
*
|
|
42
48
|
* @param value Value to check
|
|
43
49
|
* @returns `true` if the value is a conditional timer, otherwise `false`
|
|
44
50
|
*/
|
|
45
51
|
export function isWhen(value: unknown): value is When {
|
|
46
|
-
return
|
|
52
|
+
return isInstance([TYPE_WHEN], value) && typeof (value as When).start === 'function';
|
|
47
53
|
}
|
|
54
|
+
|
|
55
|
+
// #endregion
|
package/src/misc.ts
CHANGED
|
@@ -4,6 +4,8 @@ import {DEFAULT_TIMEOUT, STATES, WORK_CONTINUE, WORK_PAUSE} from './constants';
|
|
|
4
4
|
import type {TimerState} from './models';
|
|
5
5
|
import {work} from './work';
|
|
6
6
|
|
|
7
|
+
// #region Functions
|
|
8
|
+
|
|
7
9
|
export function getCallback(value: unknown): GenericCallback {
|
|
8
10
|
return typeof value === 'function' ? (value as GenericCallback) : noop;
|
|
9
11
|
}
|
|
@@ -53,3 +55,16 @@ export function updateStates(state: TimerState, hide?: boolean): void {
|
|
|
53
55
|
STATES.active.add(state);
|
|
54
56
|
}
|
|
55
57
|
}
|
|
58
|
+
|
|
59
|
+
// #endregion
|
|
60
|
+
|
|
61
|
+
// #region Variables
|
|
62
|
+
|
|
63
|
+
/* istanbul ignore next */
|
|
64
|
+
export const startTimer =
|
|
65
|
+
'requestAnimationFrame' in globalThis ? requestAnimationFrame : setTimeout;
|
|
66
|
+
|
|
67
|
+
/* istanbul ignore next */
|
|
68
|
+
export const stopTimer = 'cancelAnimationFrame' in globalThis ? cancelAnimationFrame : clearTimeout;
|
|
69
|
+
|
|
70
|
+
// #endregion
|