@oscarpalmer/timer 0.10.0 → 0.12.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 +55 -30
- package/dist/timer.cjs.map +2 -2
- package/dist/timer.iife.js +1 -1
- package/dist/timer.iife.js.map +3 -3
- package/dist/timer.js +54 -30
- package/dist/timer.js.map +2 -2
- package/package.json +10 -10
- package/src/index.ts +69 -32
package/dist/timer.cjs
CHANGED
|
@@ -32,9 +32,6 @@ __export(src_exports, {
|
|
|
32
32
|
});
|
|
33
33
|
module.exports = __toCommonJS(src_exports);
|
|
34
34
|
var milliseconds = Math.round(1e3 / 60);
|
|
35
|
-
var cancel = cancelAnimationFrame != null ? cancelAnimationFrame : function(id) {
|
|
36
|
-
clearTimeout == null ? void 0 : clearTimeout(id);
|
|
37
|
-
};
|
|
38
35
|
var request = requestAnimationFrame != null ? requestAnimationFrame : function(callback) {
|
|
39
36
|
var _a;
|
|
40
37
|
return (_a = setTimeout == null ? void 0 : setTimeout(() => {
|
|
@@ -42,12 +39,13 @@ var request = requestAnimationFrame != null ? requestAnimationFrame : function(c
|
|
|
42
39
|
}, milliseconds)) != null ? _a : -1;
|
|
43
40
|
};
|
|
44
41
|
var Timed = class {
|
|
45
|
-
constructor(callback, time, count) {
|
|
46
|
-
__publicField(this, "
|
|
47
|
-
__publicField(this, "
|
|
48
|
-
__publicField(this, "
|
|
49
|
-
|
|
50
|
-
|
|
42
|
+
constructor(callback, time, count, afterCallback) {
|
|
43
|
+
__publicField(this, "callbacks");
|
|
44
|
+
__publicField(this, "configuration");
|
|
45
|
+
__publicField(this, "state", {
|
|
46
|
+
active: false,
|
|
47
|
+
finished: false
|
|
48
|
+
});
|
|
51
49
|
const isRepeated = this instanceof Repeated;
|
|
52
50
|
const type = isRepeated ? "repeated" : "waited";
|
|
53
51
|
if (typeof callback !== "function") {
|
|
@@ -59,60 +57,87 @@ var Timed = class {
|
|
|
59
57
|
if (isRepeated && (typeof count !== "number" || count < 2)) {
|
|
60
58
|
throw new Error("A repeated timer must have a number above 1 as its repeat count");
|
|
61
59
|
}
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
60
|
+
if (isRepeated && afterCallback != null && typeof afterCallback !== "function") {
|
|
61
|
+
throw new Error("A repeated timer's after-callback must be a function");
|
|
62
|
+
}
|
|
63
|
+
this.configuration = { count, time };
|
|
64
|
+
this.callbacks = {
|
|
65
|
+
after: afterCallback,
|
|
66
|
+
default: callback
|
|
67
|
+
};
|
|
65
68
|
}
|
|
69
|
+
/**
|
|
70
|
+
* Is the timer active?
|
|
71
|
+
*/
|
|
66
72
|
get active() {
|
|
67
|
-
return this.
|
|
73
|
+
return this.state.active;
|
|
74
|
+
}
|
|
75
|
+
/**
|
|
76
|
+
* Has the timer finished?
|
|
77
|
+
*/
|
|
78
|
+
get finished() {
|
|
79
|
+
return !this.state.active && this.state.finished;
|
|
68
80
|
}
|
|
69
81
|
static run(timed) {
|
|
70
|
-
timed.
|
|
82
|
+
timed.state.active = true;
|
|
83
|
+
timed.state.finished = false;
|
|
84
|
+
const isRepeated = timed instanceof Repeated;
|
|
71
85
|
let count = 0;
|
|
72
86
|
let start;
|
|
73
87
|
function step(timestamp) {
|
|
74
|
-
if (!timed.
|
|
88
|
+
if (!timed.state.active) {
|
|
75
89
|
return;
|
|
76
90
|
}
|
|
77
91
|
start != null ? start : start = timestamp;
|
|
78
92
|
const elapsed = timestamp - start;
|
|
79
93
|
const elapsedMinimum = elapsed - milliseconds;
|
|
80
94
|
const elapsedMaximum = elapsed + milliseconds;
|
|
81
|
-
if (elapsedMinimum < timed.time && timed.time < elapsedMaximum) {
|
|
82
|
-
if (timed.
|
|
83
|
-
timed.
|
|
95
|
+
if (elapsedMinimum < timed.configuration.time && timed.configuration.time < elapsedMaximum) {
|
|
96
|
+
if (timed.state.active) {
|
|
97
|
+
timed.callbacks.default(isRepeated ? count : void 0);
|
|
84
98
|
}
|
|
85
99
|
count += 1;
|
|
86
|
-
if (
|
|
100
|
+
if (isRepeated && count < timed.configuration.count) {
|
|
87
101
|
start = void 0;
|
|
88
102
|
} else {
|
|
103
|
+
timed.state.finished = true;
|
|
89
104
|
timed.stop();
|
|
90
105
|
return;
|
|
91
106
|
}
|
|
92
107
|
}
|
|
93
|
-
timed.frame = request(step);
|
|
108
|
+
timed.state.frame = request(step);
|
|
94
109
|
}
|
|
95
|
-
timed.frame = request(step);
|
|
110
|
+
timed.state.frame = request(step);
|
|
96
111
|
}
|
|
112
|
+
/**
|
|
113
|
+
* Restart timer
|
|
114
|
+
*/
|
|
97
115
|
restart() {
|
|
98
116
|
this.stop();
|
|
99
117
|
Timed.run(this);
|
|
100
118
|
return this;
|
|
101
119
|
}
|
|
120
|
+
/**
|
|
121
|
+
* Start timer
|
|
122
|
+
*/
|
|
102
123
|
start() {
|
|
103
|
-
if (this.
|
|
104
|
-
|
|
124
|
+
if (!this.state.active) {
|
|
125
|
+
Timed.run(this);
|
|
105
126
|
}
|
|
106
|
-
Timed.run(this);
|
|
107
127
|
return this;
|
|
108
128
|
}
|
|
129
|
+
/**
|
|
130
|
+
* Stop timer
|
|
131
|
+
*/
|
|
109
132
|
stop() {
|
|
110
|
-
|
|
111
|
-
|
|
133
|
+
var _a, _b, _c;
|
|
134
|
+
this.state.active = false;
|
|
135
|
+
if (typeof this.state.frame === "undefined") {
|
|
112
136
|
return this;
|
|
113
137
|
}
|
|
114
|
-
|
|
115
|
-
this.
|
|
138
|
+
(_a = cancelAnimationFrame != null ? cancelAnimationFrame : clearTimeout) == null ? void 0 : _a(this.state.frame);
|
|
139
|
+
(_c = (_b = this.callbacks).after) == null ? void 0 : _c.call(_b, this.finished);
|
|
140
|
+
this.state.frame = void 0;
|
|
116
141
|
return this;
|
|
117
142
|
}
|
|
118
143
|
};
|
|
@@ -123,8 +148,8 @@ var Waited = class extends Timed {
|
|
|
123
148
|
super(callback, time, 1);
|
|
124
149
|
}
|
|
125
150
|
};
|
|
126
|
-
function repeat(callback, time, count) {
|
|
127
|
-
return new Repeated(callback, time, count).start();
|
|
151
|
+
function repeat(callback, time, count, afterCallback) {
|
|
152
|
+
return new Repeated(callback, time, count, afterCallback).start();
|
|
128
153
|
}
|
|
129
154
|
function wait(callback, time) {
|
|
130
155
|
return new Waited(callback, time).start();
|
package/dist/timer.cjs.map
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"version": 3,
|
|
3
3
|
"sources": ["../src/index.ts"],
|
|
4
|
-
"sourcesContent": ["type RepeatedCallback = (index: number) => void;\ntype WaitedCallback = () => void;\n\
|
|
5
|
-
"mappings": ";;;;;;;;;;;;;;;;;;;;;;;;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;
|
|
4
|
+
"sourcesContent": ["type AfterCallback = (finished: boolean) => void;\ntype RepeatedCallback = (index: number) => void;\ntype WaitedCallback = () => void;\n\ntype Callbacks<Callback> = {\n\tafter?: AfterCallback;\n\tdefault: Callback;\n};\n\ntype Configuration = {\n\tcount: number;\n\ttime: number;\n};\n\ntype State = {\n\tactive: boolean;\n\tfinished: boolean;\n\tframe?: number;\n};\n\nconst milliseconds = Math.round(1000 / 60);\n\nconst request = requestAnimationFrame ?? function (callback: FrameRequestCallback): number {\n\treturn (setTimeout?.(() => {\n\t\tcallback(Date.now());\n\t}, milliseconds) ?? -1) as unknown as number;\n};\n\nabstract class Timed<Callback> {\n\treadonly callbacks!: Callbacks<Callback>;\n\treadonly configuration!: Configuration;\n\n\treadonly state: State = {\n\t\tactive: false,\n\t\tfinished: false,\n\t};\n\n\t/**\n\t * Is the timer active?\n\t */\n\tget active(): boolean {\n\t\treturn this.state.active;\n\t}\n\n\t/**\n\t * Has the timer finished?\n\t */\n get finished(): boolean {\n\t\treturn !this.state.active && this.state.finished;\n\t}\n\n\tconstructor(callback: Callback, time: number,\tcount: number, afterCallback?: AfterCallback) {\n\t\tconst isRepeated = this instanceof Repeated;\n\n\t\tconst type = isRepeated\n\t\t? 'repeated'\n\t\t: 'waited';\n\n\t\tif (typeof callback !== 'function') {\n\t\t\tthrow new Error(`A ${type} timer must have a callback function`);\n\t\t}\n\n\t\tif (typeof time !== 'number' || time < 0) {\n\t\t\tthrow new Error(`A ${type} timer must have a non-negative number as its time`);\n\t\t}\n\n\t\tif (isRepeated && (typeof count !== 'number' || count < 2)) {\n\t\t\tthrow new Error('A repeated timer must have a number above 1 as its repeat count');\n\t\t}\n\n\t\tif (isRepeated && afterCallback != null && typeof afterCallback !== 'function') {\n\t\t\tthrow new Error('A repeated timer\\'s after-callback must be a function');\n\t\t}\n\n\t\tthis.configuration = {count, time};\n\n\t\tthis.callbacks = {\n\t\t\tafter: afterCallback,\n\t\t\tdefault: callback,\n\t\t};\n\t}\n\n\tprivate static run(timed: Timed<(index: number | undefined) => void>): void {\n\t\ttimed.state.active = true;\n\t\ttimed.state.finished = false;\n\n\t\tconst isRepeated = timed instanceof Repeated;\n\n\t\tlet count = 0;\n\n\t\tlet start: DOMHighResTimeStamp | undefined;\n\n\t\tfunction step(timestamp: DOMHighResTimeStamp): void {\n\t\t\tif (!timed.state.active) {\n\t\t\t\treturn;\n\t\t\t}\n\n\t\t\tstart ??= timestamp;\n\n\t\t\tconst elapsed = timestamp - start;\n\n\t\t\tconst elapsedMinimum = elapsed - milliseconds;\n\t\t\tconst elapsedMaximum = elapsed + milliseconds;\n\n\t\t\tif (elapsedMinimum < timed.configuration.time && timed.configuration.time < elapsedMaximum) {\n\t\t\t\tif (timed.state.active) {\n\t\t\t\t\ttimed.callbacks.default(isRepeated ? count : undefined);\n\t\t\t\t}\n\n\t\t\t\tcount += 1;\n\n\t\t\t\tif (isRepeated && count < timed.configuration.count) {\n\t\t\t\t\tstart = undefined;\n\t\t\t\t} else {\n\t\t\t\t\ttimed.state.finished = true;\n\n\t\t\t\t\ttimed.stop();\n\n\t\t\t\t\treturn;\n\t\t\t\t}\n\t\t\t}\n\n\t\t\ttimed.state.frame = request(step);\n\t\t}\n\n\t\ttimed.state.frame = request(step);\n\t}\n\n\t/**\n\t * Restart timer\n\t */\n\trestart(): this {\n\t\tthis.stop();\n\n\t\tTimed.run(this as never);\n\n\t\treturn this;\n\t}\n\n\t/**\n\t * Start timer\n\t */\n\tstart(): this {\n\t\tif (!this.state.active) {\n\t\t\tTimed.run(this as never);\n\t\t}\n\n\t\treturn this;\n\t}\n\n\t/**\n\t * Stop timer\n\t */\n\tstop(): this {\n\t\tthis.state.active = false;\n\n\t\tif (typeof this.state.frame === 'undefined') {\n\t\t\treturn this;\n\t\t}\n\n\t\t(cancelAnimationFrame ?? clearTimeout)?.(this.state.frame);\n\n\t\tthis.callbacks.after?.(this.finished);\n\n\t\tthis.state.frame = undefined;\n\n\t\treturn this;\n\t}\n}\n\n/**\n * A repeated timer\n */\nexport class Repeated extends Timed<RepeatedCallback> {}\n\n/**\n * A waited timer\n */\nexport class Waited extends Timed<WaitedCallback> {\n\tconstructor(callback: WaitedCallback, time: number) {\n\t\tsuper(callback, time, 1);\n\t}\n}\n\n/**\n * Create and start a new repeated timer\n */\nexport function repeat(callback: RepeatedCallback, time: number, count: number, afterCallback?: AfterCallback): Repeated {\n\treturn (new Repeated(callback, time, count, afterCallback)).start();\n}\n\n/**\n * Create and start a new waited timer\n */\nexport function wait(callback: WaitedCallback, time: number): Waited {\n\treturn (new Waited(callback, time)).start();\n}\n"],
|
|
5
|
+
"mappings": "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",
|
|
6
6
|
"names": []
|
|
7
7
|
}
|
package/dist/timer.iife.js
CHANGED
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
"use strict";var Timer=(()=>{var c=Object.defineProperty;var
|
|
1
|
+
"use strict";var Timer=(()=>{var c=Object.defineProperty;var v=Object.getOwnPropertyDescriptor;var k=Object.getOwnPropertyNames;var C=Object.prototype.hasOwnProperty;var y=(a,e,t)=>e in a?c(a,e,{enumerable:!0,configurable:!0,writable:!0,value:t}):a[e]=t;var w=(a,e)=>{for(var t in e)c(a,t,{get:e[t],enumerable:!0})},g=(a,e,t,n)=>{if(e&&typeof e=="object"||typeof e=="function")for(let i of k(e))!C.call(a,i)&&i!==t&&c(a,i,{get:()=>e[i],enumerable:!(n=v(e,i))||n.enumerable});return a};var A=a=>g(c({},"__esModule",{value:!0}),a);var l=(a,e,t)=>(y(a,typeof e!="symbol"?e+"":e,t),t);var M={};w(M,{Repeated:()=>o,Waited:()=>f,repeat:()=>x,wait:()=>R});var b=Math.round(16.666666666666668),d=requestAnimationFrame!=null?requestAnimationFrame:function(a){var e;return(e=setTimeout==null?void 0:setTimeout(()=>{a(Date.now())},b))!=null?e:-1},r=class{constructor(e,t,n,i){l(this,"callbacks");l(this,"configuration");l(this,"state",{active:!1,finished:!1});let s=this instanceof o,u=s?"repeated":"waited";if(typeof e!="function")throw new Error(`A ${u} timer must have a callback function`);if(typeof t!="number"||t<0)throw new Error(`A ${u} timer must have a non-negative number as its time`);if(s&&(typeof n!="number"||n<2))throw new Error("A repeated timer must have a number above 1 as its repeat count");if(s&&i!=null&&typeof i!="function")throw new Error("A repeated timer's after-callback must be a function");this.configuration={count:n,time:t},this.callbacks={after:i,default:e}}get active(){return this.state.active}get finished(){return!this.state.active&&this.state.finished}static run(e){e.state.active=!0,e.state.finished=!1;let t=e instanceof o,n=0,i;function s(u){if(!e.state.active)return;i!=null||(i=u);let h=u-i,p=h-b,m=h+b;if(p<e.configuration.time&&e.configuration.time<m)if(e.state.active&&e.callbacks.default(t?n:void 0),n+=1,t&&n<e.configuration.count)i=void 0;else{e.state.finished=!0,e.stop();return}e.state.frame=d(s)}e.state.frame=d(s)}restart(){return this.stop(),r.run(this),this}start(){return this.state.active||r.run(this),this}stop(){var e,t,n;return this.state.active=!1,typeof this.state.frame=="undefined"?this:((e=cancelAnimationFrame!=null?cancelAnimationFrame:clearTimeout)==null||e(this.state.frame),(n=(t=this.callbacks).after)==null||n.call(t,this.finished),this.state.frame=void 0,this)}},o=class extends r{},f=class extends r{constructor(e,t){super(e,t,1)}};function x(a,e,t,n){return new o(a,e,t,n).start()}function R(a,e){return new f(a,e).start()}return A(M);})();
|
|
2
2
|
//# sourceMappingURL=timer.iife.js.map
|
package/dist/timer.iife.js.map
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"version": 3,
|
|
3
3
|
"sources": ["../src/index.ts"],
|
|
4
|
-
"sourcesContent": ["type RepeatedCallback = (index: number) => void;\ntype WaitedCallback = () => void;\n\
|
|
5
|
-
"mappings": "qkBAAA,IAAAA,EAAA,GAAAC,EAAAD,EAAA,cAAAE,EAAA,WAAAC,EAAA,WAAAC,EAAA,SAAAC,
|
|
6
|
-
"names": ["src_exports", "__export", "Repeated", "Waited", "repeat", "wait", "milliseconds", "
|
|
4
|
+
"sourcesContent": ["type AfterCallback = (finished: boolean) => void;\ntype RepeatedCallback = (index: number) => void;\ntype WaitedCallback = () => void;\n\ntype Callbacks<Callback> = {\n\tafter?: AfterCallback;\n\tdefault: Callback;\n};\n\ntype Configuration = {\n\tcount: number;\n\ttime: number;\n};\n\ntype State = {\n\tactive: boolean;\n\tfinished: boolean;\n\tframe?: number;\n};\n\nconst milliseconds = Math.round(1000 / 60);\n\nconst request = requestAnimationFrame ?? function (callback: FrameRequestCallback): number {\n\treturn (setTimeout?.(() => {\n\t\tcallback(Date.now());\n\t}, milliseconds) ?? -1) as unknown as number;\n};\n\nabstract class Timed<Callback> {\n\treadonly callbacks!: Callbacks<Callback>;\n\treadonly configuration!: Configuration;\n\n\treadonly state: State = {\n\t\tactive: false,\n\t\tfinished: false,\n\t};\n\n\t/**\n\t * Is the timer active?\n\t */\n\tget active(): boolean {\n\t\treturn this.state.active;\n\t}\n\n\t/**\n\t * Has the timer finished?\n\t */\n get finished(): boolean {\n\t\treturn !this.state.active && this.state.finished;\n\t}\n\n\tconstructor(callback: Callback, time: number,\tcount: number, afterCallback?: AfterCallback) {\n\t\tconst isRepeated = this instanceof Repeated;\n\n\t\tconst type = isRepeated\n\t\t? 'repeated'\n\t\t: 'waited';\n\n\t\tif (typeof callback !== 'function') {\n\t\t\tthrow new Error(`A ${type} timer must have a callback function`);\n\t\t}\n\n\t\tif (typeof time !== 'number' || time < 0) {\n\t\t\tthrow new Error(`A ${type} timer must have a non-negative number as its time`);\n\t\t}\n\n\t\tif (isRepeated && (typeof count !== 'number' || count < 2)) {\n\t\t\tthrow new Error('A repeated timer must have a number above 1 as its repeat count');\n\t\t}\n\n\t\tif (isRepeated && afterCallback != null && typeof afterCallback !== 'function') {\n\t\t\tthrow new Error('A repeated timer\\'s after-callback must be a function');\n\t\t}\n\n\t\tthis.configuration = {count, time};\n\n\t\tthis.callbacks = {\n\t\t\tafter: afterCallback,\n\t\t\tdefault: callback,\n\t\t};\n\t}\n\n\tprivate static run(timed: Timed<(index: number | undefined) => void>): void {\n\t\ttimed.state.active = true;\n\t\ttimed.state.finished = false;\n\n\t\tconst isRepeated = timed instanceof Repeated;\n\n\t\tlet count = 0;\n\n\t\tlet start: DOMHighResTimeStamp | undefined;\n\n\t\tfunction step(timestamp: DOMHighResTimeStamp): void {\n\t\t\tif (!timed.state.active) {\n\t\t\t\treturn;\n\t\t\t}\n\n\t\t\tstart ??= timestamp;\n\n\t\t\tconst elapsed = timestamp - start;\n\n\t\t\tconst elapsedMinimum = elapsed - milliseconds;\n\t\t\tconst elapsedMaximum = elapsed + milliseconds;\n\n\t\t\tif (elapsedMinimum < timed.configuration.time && timed.configuration.time < elapsedMaximum) {\n\t\t\t\tif (timed.state.active) {\n\t\t\t\t\ttimed.callbacks.default(isRepeated ? count : undefined);\n\t\t\t\t}\n\n\t\t\t\tcount += 1;\n\n\t\t\t\tif (isRepeated && count < timed.configuration.count) {\n\t\t\t\t\tstart = undefined;\n\t\t\t\t} else {\n\t\t\t\t\ttimed.state.finished = true;\n\n\t\t\t\t\ttimed.stop();\n\n\t\t\t\t\treturn;\n\t\t\t\t}\n\t\t\t}\n\n\t\t\ttimed.state.frame = request(step);\n\t\t}\n\n\t\ttimed.state.frame = request(step);\n\t}\n\n\t/**\n\t * Restart timer\n\t */\n\trestart(): this {\n\t\tthis.stop();\n\n\t\tTimed.run(this as never);\n\n\t\treturn this;\n\t}\n\n\t/**\n\t * Start timer\n\t */\n\tstart(): this {\n\t\tif (!this.state.active) {\n\t\t\tTimed.run(this as never);\n\t\t}\n\n\t\treturn this;\n\t}\n\n\t/**\n\t * Stop timer\n\t */\n\tstop(): this {\n\t\tthis.state.active = false;\n\n\t\tif (typeof this.state.frame === 'undefined') {\n\t\t\treturn this;\n\t\t}\n\n\t\t(cancelAnimationFrame ?? clearTimeout)?.(this.state.frame);\n\n\t\tthis.callbacks.after?.(this.finished);\n\n\t\tthis.state.frame = undefined;\n\n\t\treturn this;\n\t}\n}\n\n/**\n * A repeated timer\n */\nexport class Repeated extends Timed<RepeatedCallback> {}\n\n/**\n * A waited timer\n */\nexport class Waited extends Timed<WaitedCallback> {\n\tconstructor(callback: WaitedCallback, time: number) {\n\t\tsuper(callback, time, 1);\n\t}\n}\n\n/**\n * Create and start a new repeated timer\n */\nexport function repeat(callback: RepeatedCallback, time: number, count: number, afterCallback?: AfterCallback): Repeated {\n\treturn (new Repeated(callback, time, count, afterCallback)).start();\n}\n\n/**\n * Create and start a new waited timer\n */\nexport function wait(callback: WaitedCallback, time: number): Waited {\n\treturn (new Waited(callback, time)).start();\n}\n"],
|
|
5
|
+
"mappings": "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",
|
|
6
|
+
"names": ["src_exports", "__export", "Repeated", "Waited", "repeat", "wait", "milliseconds", "request", "callback", "_a", "Timed", "time", "count", "afterCallback", "__publicField", "isRepeated", "Repeated", "type", "timed", "start", "step", "timestamp", "elapsed", "elapsedMinimum", "elapsedMaximum", "_b", "_c", "Waited", "repeat", "wait"]
|
|
7
7
|
}
|
package/dist/timer.js
CHANGED
|
@@ -1,23 +1,30 @@
|
|
|
1
1
|
// src/index.ts
|
|
2
2
|
var milliseconds = Math.round(1e3 / 60);
|
|
3
|
-
var cancel = cancelAnimationFrame ?? function(id) {
|
|
4
|
-
clearTimeout?.(id);
|
|
5
|
-
};
|
|
6
3
|
var request = requestAnimationFrame ?? function(callback) {
|
|
7
4
|
return setTimeout?.(() => {
|
|
8
5
|
callback(Date.now());
|
|
9
6
|
}, milliseconds) ?? -1;
|
|
10
7
|
};
|
|
11
8
|
var Timed = class {
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
9
|
+
callbacks;
|
|
10
|
+
configuration;
|
|
11
|
+
state = {
|
|
12
|
+
active: false,
|
|
13
|
+
finished: false
|
|
14
|
+
};
|
|
15
|
+
/**
|
|
16
|
+
* Is the timer active?
|
|
17
|
+
*/
|
|
17
18
|
get active() {
|
|
18
|
-
return this.
|
|
19
|
+
return this.state.active;
|
|
20
|
+
}
|
|
21
|
+
/**
|
|
22
|
+
* Has the timer finished?
|
|
23
|
+
*/
|
|
24
|
+
get finished() {
|
|
25
|
+
return !this.state.active && this.state.finished;
|
|
19
26
|
}
|
|
20
|
-
constructor(callback, time, count) {
|
|
27
|
+
constructor(callback, time, count, afterCallback) {
|
|
21
28
|
const isRepeated = this instanceof Repeated;
|
|
22
29
|
const type = isRepeated ? "repeated" : "waited";
|
|
23
30
|
if (typeof callback !== "function") {
|
|
@@ -29,57 +36,74 @@ var Timed = class {
|
|
|
29
36
|
if (isRepeated && (typeof count !== "number" || count < 2)) {
|
|
30
37
|
throw new Error("A repeated timer must have a number above 1 as its repeat count");
|
|
31
38
|
}
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
39
|
+
if (isRepeated && afterCallback != null && typeof afterCallback !== "function") {
|
|
40
|
+
throw new Error("A repeated timer's after-callback must be a function");
|
|
41
|
+
}
|
|
42
|
+
this.configuration = { count, time };
|
|
43
|
+
this.callbacks = {
|
|
44
|
+
after: afterCallback,
|
|
45
|
+
default: callback
|
|
46
|
+
};
|
|
35
47
|
}
|
|
36
48
|
static run(timed) {
|
|
37
|
-
timed.
|
|
49
|
+
timed.state.active = true;
|
|
50
|
+
timed.state.finished = false;
|
|
51
|
+
const isRepeated = timed instanceof Repeated;
|
|
38
52
|
let count = 0;
|
|
39
53
|
let start;
|
|
40
54
|
function step(timestamp) {
|
|
41
|
-
if (!timed.
|
|
55
|
+
if (!timed.state.active) {
|
|
42
56
|
return;
|
|
43
57
|
}
|
|
44
58
|
start ??= timestamp;
|
|
45
59
|
const elapsed = timestamp - start;
|
|
46
60
|
const elapsedMinimum = elapsed - milliseconds;
|
|
47
61
|
const elapsedMaximum = elapsed + milliseconds;
|
|
48
|
-
if (elapsedMinimum < timed.time && timed.time < elapsedMaximum) {
|
|
49
|
-
if (timed.
|
|
50
|
-
timed.
|
|
62
|
+
if (elapsedMinimum < timed.configuration.time && timed.configuration.time < elapsedMaximum) {
|
|
63
|
+
if (timed.state.active) {
|
|
64
|
+
timed.callbacks.default(isRepeated ? count : void 0);
|
|
51
65
|
}
|
|
52
66
|
count += 1;
|
|
53
|
-
if (
|
|
67
|
+
if (isRepeated && count < timed.configuration.count) {
|
|
54
68
|
start = void 0;
|
|
55
69
|
} else {
|
|
70
|
+
timed.state.finished = true;
|
|
56
71
|
timed.stop();
|
|
57
72
|
return;
|
|
58
73
|
}
|
|
59
74
|
}
|
|
60
|
-
timed.frame = request(step);
|
|
75
|
+
timed.state.frame = request(step);
|
|
61
76
|
}
|
|
62
|
-
timed.frame = request(step);
|
|
77
|
+
timed.state.frame = request(step);
|
|
63
78
|
}
|
|
79
|
+
/**
|
|
80
|
+
* Restart timer
|
|
81
|
+
*/
|
|
64
82
|
restart() {
|
|
65
83
|
this.stop();
|
|
66
84
|
Timed.run(this);
|
|
67
85
|
return this;
|
|
68
86
|
}
|
|
87
|
+
/**
|
|
88
|
+
* Start timer
|
|
89
|
+
*/
|
|
69
90
|
start() {
|
|
70
|
-
if (this.
|
|
71
|
-
|
|
91
|
+
if (!this.state.active) {
|
|
92
|
+
Timed.run(this);
|
|
72
93
|
}
|
|
73
|
-
Timed.run(this);
|
|
74
94
|
return this;
|
|
75
95
|
}
|
|
96
|
+
/**
|
|
97
|
+
* Stop timer
|
|
98
|
+
*/
|
|
76
99
|
stop() {
|
|
77
|
-
this.
|
|
78
|
-
if (typeof this.frame === "undefined") {
|
|
100
|
+
this.state.active = false;
|
|
101
|
+
if (typeof this.state.frame === "undefined") {
|
|
79
102
|
return this;
|
|
80
103
|
}
|
|
81
|
-
|
|
82
|
-
this.
|
|
104
|
+
(cancelAnimationFrame ?? clearTimeout)?.(this.state.frame);
|
|
105
|
+
this.callbacks.after?.(this.finished);
|
|
106
|
+
this.state.frame = void 0;
|
|
83
107
|
return this;
|
|
84
108
|
}
|
|
85
109
|
};
|
|
@@ -90,8 +114,8 @@ var Waited = class extends Timed {
|
|
|
90
114
|
super(callback, time, 1);
|
|
91
115
|
}
|
|
92
116
|
};
|
|
93
|
-
function repeat(callback, time, count) {
|
|
94
|
-
return new Repeated(callback, time, count).start();
|
|
117
|
+
function repeat(callback, time, count, afterCallback) {
|
|
118
|
+
return new Repeated(callback, time, count, afterCallback).start();
|
|
95
119
|
}
|
|
96
120
|
function wait(callback, time) {
|
|
97
121
|
return new Waited(callback, time).start();
|
package/dist/timer.js.map
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"version": 3,
|
|
3
3
|
"sources": ["../src/index.ts"],
|
|
4
|
-
"sourcesContent": ["type RepeatedCallback = (index: number) => void;\ntype WaitedCallback = () => void;\n\
|
|
5
|
-
"mappings": ";
|
|
4
|
+
"sourcesContent": ["type AfterCallback = (finished: boolean) => void;\ntype RepeatedCallback = (index: number) => void;\ntype WaitedCallback = () => void;\n\ntype Callbacks<Callback> = {\n\tafter?: AfterCallback;\n\tdefault: Callback;\n};\n\ntype Configuration = {\n\tcount: number;\n\ttime: number;\n};\n\ntype State = {\n\tactive: boolean;\n\tfinished: boolean;\n\tframe?: number;\n};\n\nconst milliseconds = Math.round(1000 / 60);\n\nconst request = requestAnimationFrame ?? function (callback: FrameRequestCallback): number {\n\treturn (setTimeout?.(() => {\n\t\tcallback(Date.now());\n\t}, milliseconds) ?? -1) as unknown as number;\n};\n\nabstract class Timed<Callback> {\n\treadonly callbacks!: Callbacks<Callback>;\n\treadonly configuration!: Configuration;\n\n\treadonly state: State = {\n\t\tactive: false,\n\t\tfinished: false,\n\t};\n\n\t/**\n\t * Is the timer active?\n\t */\n\tget active(): boolean {\n\t\treturn this.state.active;\n\t}\n\n\t/**\n\t * Has the timer finished?\n\t */\n get finished(): boolean {\n\t\treturn !this.state.active && this.state.finished;\n\t}\n\n\tconstructor(callback: Callback, time: number,\tcount: number, afterCallback?: AfterCallback) {\n\t\tconst isRepeated = this instanceof Repeated;\n\n\t\tconst type = isRepeated\n\t\t? 'repeated'\n\t\t: 'waited';\n\n\t\tif (typeof callback !== 'function') {\n\t\t\tthrow new Error(`A ${type} timer must have a callback function`);\n\t\t}\n\n\t\tif (typeof time !== 'number' || time < 0) {\n\t\t\tthrow new Error(`A ${type} timer must have a non-negative number as its time`);\n\t\t}\n\n\t\tif (isRepeated && (typeof count !== 'number' || count < 2)) {\n\t\t\tthrow new Error('A repeated timer must have a number above 1 as its repeat count');\n\t\t}\n\n\t\tif (isRepeated && afterCallback != null && typeof afterCallback !== 'function') {\n\t\t\tthrow new Error('A repeated timer\\'s after-callback must be a function');\n\t\t}\n\n\t\tthis.configuration = {count, time};\n\n\t\tthis.callbacks = {\n\t\t\tafter: afterCallback,\n\t\t\tdefault: callback,\n\t\t};\n\t}\n\n\tprivate static run(timed: Timed<(index: number | undefined) => void>): void {\n\t\ttimed.state.active = true;\n\t\ttimed.state.finished = false;\n\n\t\tconst isRepeated = timed instanceof Repeated;\n\n\t\tlet count = 0;\n\n\t\tlet start: DOMHighResTimeStamp | undefined;\n\n\t\tfunction step(timestamp: DOMHighResTimeStamp): void {\n\t\t\tif (!timed.state.active) {\n\t\t\t\treturn;\n\t\t\t}\n\n\t\t\tstart ??= timestamp;\n\n\t\t\tconst elapsed = timestamp - start;\n\n\t\t\tconst elapsedMinimum = elapsed - milliseconds;\n\t\t\tconst elapsedMaximum = elapsed + milliseconds;\n\n\t\t\tif (elapsedMinimum < timed.configuration.time && timed.configuration.time < elapsedMaximum) {\n\t\t\t\tif (timed.state.active) {\n\t\t\t\t\ttimed.callbacks.default(isRepeated ? count : undefined);\n\t\t\t\t}\n\n\t\t\t\tcount += 1;\n\n\t\t\t\tif (isRepeated && count < timed.configuration.count) {\n\t\t\t\t\tstart = undefined;\n\t\t\t\t} else {\n\t\t\t\t\ttimed.state.finished = true;\n\n\t\t\t\t\ttimed.stop();\n\n\t\t\t\t\treturn;\n\t\t\t\t}\n\t\t\t}\n\n\t\t\ttimed.state.frame = request(step);\n\t\t}\n\n\t\ttimed.state.frame = request(step);\n\t}\n\n\t/**\n\t * Restart timer\n\t */\n\trestart(): this {\n\t\tthis.stop();\n\n\t\tTimed.run(this as never);\n\n\t\treturn this;\n\t}\n\n\t/**\n\t * Start timer\n\t */\n\tstart(): this {\n\t\tif (!this.state.active) {\n\t\t\tTimed.run(this as never);\n\t\t}\n\n\t\treturn this;\n\t}\n\n\t/**\n\t * Stop timer\n\t */\n\tstop(): this {\n\t\tthis.state.active = false;\n\n\t\tif (typeof this.state.frame === 'undefined') {\n\t\t\treturn this;\n\t\t}\n\n\t\t(cancelAnimationFrame ?? clearTimeout)?.(this.state.frame);\n\n\t\tthis.callbacks.after?.(this.finished);\n\n\t\tthis.state.frame = undefined;\n\n\t\treturn this;\n\t}\n}\n\n/**\n * A repeated timer\n */\nexport class Repeated extends Timed<RepeatedCallback> {}\n\n/**\n * A waited timer\n */\nexport class Waited extends Timed<WaitedCallback> {\n\tconstructor(callback: WaitedCallback, time: number) {\n\t\tsuper(callback, time, 1);\n\t}\n}\n\n/**\n * Create and start a new repeated timer\n */\nexport function repeat(callback: RepeatedCallback, time: number, count: number, afterCallback?: AfterCallback): Repeated {\n\treturn (new Repeated(callback, time, count, afterCallback)).start();\n}\n\n/**\n * Create and start a new waited timer\n */\nexport function wait(callback: WaitedCallback, time: number): Waited {\n\treturn (new Waited(callback, time)).start();\n}\n"],
|
|
5
|
+
"mappings": "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",
|
|
6
6
|
"names": []
|
|
7
7
|
}
|
package/package.json
CHANGED
|
@@ -6,15 +6,15 @@
|
|
|
6
6
|
"browser": "dist/timer.iife.js",
|
|
7
7
|
"description": "A better solution for timeout- and interval-based timers.",
|
|
8
8
|
"devDependencies": {
|
|
9
|
-
"@tsconfig/recommended": "^1.0
|
|
10
|
-
"@types/node": "^18.
|
|
11
|
-
"@typescript-eslint/eslint-plugin": "^5.
|
|
12
|
-
"@typescript-eslint/parser": "^5.
|
|
13
|
-
"esbuild": "^0.
|
|
14
|
-
"eslint": "^8.
|
|
15
|
-
"eslint-config-xo": "^0.
|
|
16
|
-
"eslint-config-xo-typescript": "^0.
|
|
17
|
-
"typescript": "^
|
|
9
|
+
"@tsconfig/recommended": "^1.0",
|
|
10
|
+
"@types/node": "^18.15",
|
|
11
|
+
"@typescript-eslint/eslint-plugin": "^5.57",
|
|
12
|
+
"@typescript-eslint/parser": "^5.57",
|
|
13
|
+
"esbuild": "^0.17",
|
|
14
|
+
"eslint": "^8.38",
|
|
15
|
+
"eslint-config-xo": "^0.43",
|
|
16
|
+
"eslint-config-xo-typescript": "^0.57",
|
|
17
|
+
"typescript": "^5.0"
|
|
18
18
|
},
|
|
19
19
|
"exports": {
|
|
20
20
|
".": {
|
|
@@ -52,5 +52,5 @@
|
|
|
52
52
|
"type": "module",
|
|
53
53
|
"types": "src/index.d.ts",
|
|
54
54
|
"unpkg": "dist/timer.iife.js",
|
|
55
|
-
"version": "0.
|
|
55
|
+
"version": "0.12.0"
|
|
56
56
|
}
|
package/src/index.ts
CHANGED
|
@@ -1,12 +1,25 @@
|
|
|
1
|
+
type AfterCallback = (finished: boolean) => void;
|
|
1
2
|
type RepeatedCallback = (index: number) => void;
|
|
2
3
|
type WaitedCallback = () => void;
|
|
3
4
|
|
|
4
|
-
|
|
5
|
+
type Callbacks<Callback> = {
|
|
6
|
+
after?: AfterCallback;
|
|
7
|
+
default: Callback;
|
|
8
|
+
};
|
|
9
|
+
|
|
10
|
+
type Configuration = {
|
|
11
|
+
count: number;
|
|
12
|
+
time: number;
|
|
13
|
+
};
|
|
5
14
|
|
|
6
|
-
|
|
7
|
-
|
|
15
|
+
type State = {
|
|
16
|
+
active: boolean;
|
|
17
|
+
finished: boolean;
|
|
18
|
+
frame?: number;
|
|
8
19
|
};
|
|
9
20
|
|
|
21
|
+
const milliseconds = Math.round(1000 / 60);
|
|
22
|
+
|
|
10
23
|
const request = requestAnimationFrame ?? function (callback: FrameRequestCallback): number {
|
|
11
24
|
return (setTimeout?.(() => {
|
|
12
25
|
callback(Date.now());
|
|
@@ -14,22 +27,34 @@ const request = requestAnimationFrame ?? function (callback: FrameRequestCallbac
|
|
|
14
27
|
};
|
|
15
28
|
|
|
16
29
|
abstract class Timed<Callback> {
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
30
|
+
readonly callbacks!: Callbacks<Callback>;
|
|
31
|
+
readonly configuration!: Configuration;
|
|
32
|
+
|
|
33
|
+
readonly state: State = {
|
|
34
|
+
active: false,
|
|
35
|
+
finished: false,
|
|
36
|
+
};
|
|
22
37
|
|
|
23
38
|
/**
|
|
24
39
|
* Is the timer active?
|
|
25
40
|
*/
|
|
26
41
|
get active(): boolean {
|
|
27
|
-
return this.
|
|
42
|
+
return this.state.active;
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
/**
|
|
46
|
+
* Has the timer finished?
|
|
47
|
+
*/
|
|
48
|
+
get finished(): boolean {
|
|
49
|
+
return !this.state.active && this.state.finished;
|
|
28
50
|
}
|
|
29
51
|
|
|
30
|
-
constructor(callback: Callback, time: number, count: number) {
|
|
52
|
+
constructor(callback: Callback, time: number, count: number, afterCallback?: AfterCallback) {
|
|
31
53
|
const isRepeated = this instanceof Repeated;
|
|
32
|
-
|
|
54
|
+
|
|
55
|
+
const type = isRepeated
|
|
56
|
+
? 'repeated'
|
|
57
|
+
: 'waited';
|
|
33
58
|
|
|
34
59
|
if (typeof callback !== 'function') {
|
|
35
60
|
throw new Error(`A ${type} timer must have a callback function`);
|
|
@@ -43,20 +68,30 @@ abstract class Timed<Callback> {
|
|
|
43
68
|
throw new Error('A repeated timer must have a number above 1 as its repeat count');
|
|
44
69
|
}
|
|
45
70
|
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
71
|
+
if (isRepeated && afterCallback != null && typeof afterCallback !== 'function') {
|
|
72
|
+
throw new Error('A repeated timer\'s after-callback must be a function');
|
|
73
|
+
}
|
|
74
|
+
|
|
75
|
+
this.configuration = {count, time};
|
|
76
|
+
|
|
77
|
+
this.callbacks = {
|
|
78
|
+
after: afterCallback,
|
|
79
|
+
default: callback,
|
|
80
|
+
};
|
|
49
81
|
}
|
|
50
82
|
|
|
51
83
|
private static run(timed: Timed<(index: number | undefined) => void>): void {
|
|
52
|
-
timed.
|
|
84
|
+
timed.state.active = true;
|
|
85
|
+
timed.state.finished = false;
|
|
86
|
+
|
|
87
|
+
const isRepeated = timed instanceof Repeated;
|
|
53
88
|
|
|
54
89
|
let count = 0;
|
|
55
90
|
|
|
56
91
|
let start: DOMHighResTimeStamp | undefined;
|
|
57
92
|
|
|
58
93
|
function step(timestamp: DOMHighResTimeStamp): void {
|
|
59
|
-
if (!timed.
|
|
94
|
+
if (!timed.state.active) {
|
|
60
95
|
return;
|
|
61
96
|
}
|
|
62
97
|
|
|
@@ -67,26 +102,28 @@ abstract class Timed<Callback> {
|
|
|
67
102
|
const elapsedMinimum = elapsed - milliseconds;
|
|
68
103
|
const elapsedMaximum = elapsed + milliseconds;
|
|
69
104
|
|
|
70
|
-
if (elapsedMinimum < timed.time && timed.time < elapsedMaximum) {
|
|
71
|
-
if (timed.
|
|
72
|
-
timed.
|
|
105
|
+
if (elapsedMinimum < timed.configuration.time && timed.configuration.time < elapsedMaximum) {
|
|
106
|
+
if (timed.state.active) {
|
|
107
|
+
timed.callbacks.default(isRepeated ? count : undefined);
|
|
73
108
|
}
|
|
74
109
|
|
|
75
110
|
count += 1;
|
|
76
111
|
|
|
77
|
-
if (
|
|
112
|
+
if (isRepeated && count < timed.configuration.count) {
|
|
78
113
|
start = undefined;
|
|
79
114
|
} else {
|
|
115
|
+
timed.state.finished = true;
|
|
116
|
+
|
|
80
117
|
timed.stop();
|
|
81
118
|
|
|
82
119
|
return;
|
|
83
120
|
}
|
|
84
121
|
}
|
|
85
122
|
|
|
86
|
-
timed.frame = request(step);
|
|
123
|
+
timed.state.frame = request(step);
|
|
87
124
|
}
|
|
88
125
|
|
|
89
|
-
timed.frame = request(step);
|
|
126
|
+
timed.state.frame = request(step);
|
|
90
127
|
}
|
|
91
128
|
|
|
92
129
|
/**
|
|
@@ -104,12 +141,10 @@ abstract class Timed<Callback> {
|
|
|
104
141
|
* Start timer
|
|
105
142
|
*/
|
|
106
143
|
start(): this {
|
|
107
|
-
if (this.
|
|
108
|
-
|
|
144
|
+
if (!this.state.active) {
|
|
145
|
+
Timed.run(this as never);
|
|
109
146
|
}
|
|
110
147
|
|
|
111
|
-
Timed.run(this as never);
|
|
112
|
-
|
|
113
148
|
return this;
|
|
114
149
|
}
|
|
115
150
|
|
|
@@ -117,15 +152,17 @@ abstract class Timed<Callback> {
|
|
|
117
152
|
* Stop timer
|
|
118
153
|
*/
|
|
119
154
|
stop(): this {
|
|
120
|
-
this.
|
|
155
|
+
this.state.active = false;
|
|
121
156
|
|
|
122
|
-
if (typeof this.frame === 'undefined') {
|
|
157
|
+
if (typeof this.state.frame === 'undefined') {
|
|
123
158
|
return this;
|
|
124
159
|
}
|
|
125
160
|
|
|
126
|
-
|
|
161
|
+
(cancelAnimationFrame ?? clearTimeout)?.(this.state.frame);
|
|
162
|
+
|
|
163
|
+
this.callbacks.after?.(this.finished);
|
|
127
164
|
|
|
128
|
-
this.frame = undefined;
|
|
165
|
+
this.state.frame = undefined;
|
|
129
166
|
|
|
130
167
|
return this;
|
|
131
168
|
}
|
|
@@ -148,8 +185,8 @@ export class Waited extends Timed<WaitedCallback> {
|
|
|
148
185
|
/**
|
|
149
186
|
* Create and start a new repeated timer
|
|
150
187
|
*/
|
|
151
|
-
export function repeat(callback: RepeatedCallback, time: number, count: number): Repeated {
|
|
152
|
-
return (new Repeated(callback, time, count)).start();
|
|
188
|
+
export function repeat(callback: RepeatedCallback, time: number, count: number, afterCallback?: AfterCallback): Repeated {
|
|
189
|
+
return (new Repeated(callback, time, count, afterCallback)).start();
|
|
153
190
|
}
|
|
154
191
|
|
|
155
192
|
/**
|