@oscarpalmer/timer 0.11.0 → 0.12.1
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/README.md +14 -0
- package/dist/timer.cjs +43 -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 +42 -30
- package/dist/timer.js.map +2 -2
- package/package.json +1 -1
- package/src/index.ts +65 -31
package/README.md
CHANGED
|
@@ -60,6 +60,20 @@ Both the nice helper methods and the class syntax create similar objects – `Wa
|
|
|
60
60
|
|`stop()`|Stops the timer|
|
|
61
61
|
|`restart()`|Restarts the timer|
|
|
62
62
|
|
|
63
|
+
## Callbacks
|
|
64
|
+
|
|
65
|
+
When you create a repeated timer, you can also provide a fourth parameter to act as a callback to run when the timer stops, as below:
|
|
66
|
+
|
|
67
|
+
```typescript
|
|
68
|
+
function after(finished: boolean) {
|
|
69
|
+
// Let's do something fun!
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
repeat(() => {}, 0, 10, after);
|
|
73
|
+
```
|
|
74
|
+
|
|
75
|
+
The `finished`-parameter for the `after`-function can be used to determine if the timer was stopped manually, or if it was able to finish its work.
|
|
76
|
+
|
|
63
77
|
## License
|
|
64
78
|
|
|
65
79
|
[MIT licensed](LICENSE), natch :wink:
|
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,43 +57,57 @@ 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
|
}
|
|
66
69
|
/**
|
|
67
70
|
* Is the timer active?
|
|
68
71
|
*/
|
|
69
72
|
get active() {
|
|
70
|
-
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;
|
|
71
80
|
}
|
|
72
81
|
static run(timed) {
|
|
73
|
-
timed.
|
|
82
|
+
timed.state.active = true;
|
|
83
|
+
timed.state.finished = false;
|
|
84
|
+
const isRepeated = timed instanceof Repeated;
|
|
74
85
|
let count = 0;
|
|
75
86
|
let start;
|
|
76
87
|
function step(timestamp) {
|
|
77
|
-
if (!timed.
|
|
88
|
+
if (!timed.state.active) {
|
|
78
89
|
return;
|
|
79
90
|
}
|
|
80
91
|
start != null ? start : start = timestamp;
|
|
81
92
|
const elapsed = timestamp - start;
|
|
82
93
|
const elapsedMinimum = elapsed - milliseconds;
|
|
83
94
|
const elapsedMaximum = elapsed + milliseconds;
|
|
84
|
-
if (elapsedMinimum < timed.time && timed.time < elapsedMaximum) {
|
|
85
|
-
if (timed.
|
|
86
|
-
timed.
|
|
95
|
+
if (elapsedMinimum < timed.configuration.time && timed.configuration.time < elapsedMaximum) {
|
|
96
|
+
if (timed.state.active) {
|
|
97
|
+
timed.callbacks.default(isRepeated ? count : void 0);
|
|
87
98
|
}
|
|
88
99
|
count += 1;
|
|
89
|
-
if (
|
|
100
|
+
if (isRepeated && count < timed.configuration.count) {
|
|
90
101
|
start = void 0;
|
|
91
102
|
} else {
|
|
103
|
+
timed.state.finished = true;
|
|
92
104
|
timed.stop();
|
|
93
105
|
return;
|
|
94
106
|
}
|
|
95
107
|
}
|
|
96
|
-
timed.frame = request(step);
|
|
108
|
+
timed.state.frame = request(step);
|
|
97
109
|
}
|
|
98
|
-
timed.frame = request(step);
|
|
110
|
+
timed.state.frame = request(step);
|
|
99
111
|
}
|
|
100
112
|
/**
|
|
101
113
|
* Restart timer
|
|
@@ -109,22 +121,23 @@ var Timed = class {
|
|
|
109
121
|
* Start timer
|
|
110
122
|
*/
|
|
111
123
|
start() {
|
|
112
|
-
if (this.
|
|
113
|
-
|
|
124
|
+
if (!this.state.active) {
|
|
125
|
+
Timed.run(this);
|
|
114
126
|
}
|
|
115
|
-
Timed.run(this);
|
|
116
127
|
return this;
|
|
117
128
|
}
|
|
118
129
|
/**
|
|
119
130
|
* Stop timer
|
|
120
131
|
*/
|
|
121
132
|
stop() {
|
|
122
|
-
|
|
123
|
-
|
|
133
|
+
var _a, _b, _c;
|
|
134
|
+
this.state.active = false;
|
|
135
|
+
if (typeof this.state.frame === "undefined") {
|
|
124
136
|
return this;
|
|
125
137
|
}
|
|
126
|
-
|
|
127
|
-
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;
|
|
128
141
|
return this;
|
|
129
142
|
}
|
|
130
143
|
};
|
|
@@ -135,8 +148,8 @@ var Waited = class extends Timed {
|
|
|
135
148
|
super(callback, time, 1);
|
|
136
149
|
}
|
|
137
150
|
};
|
|
138
|
-
function repeat(callback, time, count) {
|
|
139
|
-
return new Repeated(callback, time, count).start();
|
|
151
|
+
function repeat(callback, time, count, afterCallback) {
|
|
152
|
+
return new Repeated(callback, time, count, afterCallback).start();
|
|
140
153
|
}
|
|
141
154
|
function wait(callback, time) {
|
|
142
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,26 +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
|
+
};
|
|
17
15
|
/**
|
|
18
16
|
* Is the timer active?
|
|
19
17
|
*/
|
|
20
18
|
get active() {
|
|
21
|
-
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;
|
|
22
26
|
}
|
|
23
|
-
constructor(callback, time, count) {
|
|
27
|
+
constructor(callback, time, count, afterCallback) {
|
|
24
28
|
const isRepeated = this instanceof Repeated;
|
|
25
29
|
const type = isRepeated ? "repeated" : "waited";
|
|
26
30
|
if (typeof callback !== "function") {
|
|
@@ -32,37 +36,45 @@ var Timed = class {
|
|
|
32
36
|
if (isRepeated && (typeof count !== "number" || count < 2)) {
|
|
33
37
|
throw new Error("A repeated timer must have a number above 1 as its repeat count");
|
|
34
38
|
}
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
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
|
+
};
|
|
38
47
|
}
|
|
39
48
|
static run(timed) {
|
|
40
|
-
timed.
|
|
49
|
+
timed.state.active = true;
|
|
50
|
+
timed.state.finished = false;
|
|
51
|
+
const isRepeated = timed instanceof Repeated;
|
|
41
52
|
let count = 0;
|
|
42
53
|
let start;
|
|
43
54
|
function step(timestamp) {
|
|
44
|
-
if (!timed.
|
|
55
|
+
if (!timed.state.active) {
|
|
45
56
|
return;
|
|
46
57
|
}
|
|
47
58
|
start ??= timestamp;
|
|
48
59
|
const elapsed = timestamp - start;
|
|
49
60
|
const elapsedMinimum = elapsed - milliseconds;
|
|
50
61
|
const elapsedMaximum = elapsed + milliseconds;
|
|
51
|
-
if (elapsedMinimum < timed.time && timed.time < elapsedMaximum) {
|
|
52
|
-
if (timed.
|
|
53
|
-
timed.
|
|
62
|
+
if (elapsedMinimum < timed.configuration.time && timed.configuration.time < elapsedMaximum) {
|
|
63
|
+
if (timed.state.active) {
|
|
64
|
+
timed.callbacks.default(isRepeated ? count : void 0);
|
|
54
65
|
}
|
|
55
66
|
count += 1;
|
|
56
|
-
if (
|
|
67
|
+
if (isRepeated && count < timed.configuration.count) {
|
|
57
68
|
start = void 0;
|
|
58
69
|
} else {
|
|
70
|
+
timed.state.finished = true;
|
|
59
71
|
timed.stop();
|
|
60
72
|
return;
|
|
61
73
|
}
|
|
62
74
|
}
|
|
63
|
-
timed.frame = request(step);
|
|
75
|
+
timed.state.frame = request(step);
|
|
64
76
|
}
|
|
65
|
-
timed.frame = request(step);
|
|
77
|
+
timed.state.frame = request(step);
|
|
66
78
|
}
|
|
67
79
|
/**
|
|
68
80
|
* Restart timer
|
|
@@ -76,22 +88,22 @@ var Timed = class {
|
|
|
76
88
|
* Start timer
|
|
77
89
|
*/
|
|
78
90
|
start() {
|
|
79
|
-
if (this.
|
|
80
|
-
|
|
91
|
+
if (!this.state.active) {
|
|
92
|
+
Timed.run(this);
|
|
81
93
|
}
|
|
82
|
-
Timed.run(this);
|
|
83
94
|
return this;
|
|
84
95
|
}
|
|
85
96
|
/**
|
|
86
97
|
* Stop timer
|
|
87
98
|
*/
|
|
88
99
|
stop() {
|
|
89
|
-
this.
|
|
90
|
-
if (typeof this.frame === "undefined") {
|
|
100
|
+
this.state.active = false;
|
|
101
|
+
if (typeof this.state.frame === "undefined") {
|
|
91
102
|
return this;
|
|
92
103
|
}
|
|
93
|
-
|
|
94
|
-
this.
|
|
104
|
+
(cancelAnimationFrame ?? clearTimeout)?.(this.state.frame);
|
|
105
|
+
this.callbacks.after?.(this.finished);
|
|
106
|
+
this.state.frame = void 0;
|
|
95
107
|
return this;
|
|
96
108
|
}
|
|
97
109
|
};
|
|
@@ -102,8 +114,8 @@ var Waited = class extends Timed {
|
|
|
102
114
|
super(callback, time, 1);
|
|
103
115
|
}
|
|
104
116
|
};
|
|
105
|
-
function repeat(callback, time, count) {
|
|
106
|
-
return new Repeated(callback, time, count).start();
|
|
117
|
+
function repeat(callback, time, count, afterCallback) {
|
|
118
|
+
return new Repeated(callback, time, count, afterCallback).start();
|
|
107
119
|
}
|
|
108
120
|
function wait(callback, time) {
|
|
109
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
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
|
+
};
|
|
5
9
|
|
|
6
|
-
|
|
7
|
-
|
|
10
|
+
type Configuration = {
|
|
11
|
+
count: number;
|
|
12
|
+
time: number;
|
|
8
13
|
};
|
|
9
14
|
|
|
15
|
+
type State = {
|
|
16
|
+
active: boolean;
|
|
17
|
+
finished: boolean;
|
|
18
|
+
frame?: number;
|
|
19
|
+
};
|
|
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,20 +27,29 @@ 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
|
|
|
33
55
|
const type = isRepeated
|
|
@@ -46,20 +68,30 @@ abstract class Timed<Callback> {
|
|
|
46
68
|
throw new Error('A repeated timer must have a number above 1 as its repeat count');
|
|
47
69
|
}
|
|
48
70
|
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
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
|
+
};
|
|
52
81
|
}
|
|
53
82
|
|
|
54
83
|
private static run(timed: Timed<(index: number | undefined) => void>): void {
|
|
55
|
-
timed.
|
|
84
|
+
timed.state.active = true;
|
|
85
|
+
timed.state.finished = false;
|
|
86
|
+
|
|
87
|
+
const isRepeated = timed instanceof Repeated;
|
|
56
88
|
|
|
57
89
|
let count = 0;
|
|
58
90
|
|
|
59
91
|
let start: DOMHighResTimeStamp | undefined;
|
|
60
92
|
|
|
61
93
|
function step(timestamp: DOMHighResTimeStamp): void {
|
|
62
|
-
if (!timed.
|
|
94
|
+
if (!timed.state.active) {
|
|
63
95
|
return;
|
|
64
96
|
}
|
|
65
97
|
|
|
@@ -70,26 +102,28 @@ abstract class Timed<Callback> {
|
|
|
70
102
|
const elapsedMinimum = elapsed - milliseconds;
|
|
71
103
|
const elapsedMaximum = elapsed + milliseconds;
|
|
72
104
|
|
|
73
|
-
if (elapsedMinimum < timed.time && timed.time < elapsedMaximum) {
|
|
74
|
-
if (timed.
|
|
75
|
-
timed.
|
|
105
|
+
if (elapsedMinimum < timed.configuration.time && timed.configuration.time < elapsedMaximum) {
|
|
106
|
+
if (timed.state.active) {
|
|
107
|
+
timed.callbacks.default(isRepeated ? count : undefined);
|
|
76
108
|
}
|
|
77
109
|
|
|
78
110
|
count += 1;
|
|
79
111
|
|
|
80
|
-
if (
|
|
112
|
+
if (isRepeated && count < timed.configuration.count) {
|
|
81
113
|
start = undefined;
|
|
82
114
|
} else {
|
|
115
|
+
timed.state.finished = true;
|
|
116
|
+
|
|
83
117
|
timed.stop();
|
|
84
118
|
|
|
85
119
|
return;
|
|
86
120
|
}
|
|
87
121
|
}
|
|
88
122
|
|
|
89
|
-
timed.frame = request(step);
|
|
123
|
+
timed.state.frame = request(step);
|
|
90
124
|
}
|
|
91
125
|
|
|
92
|
-
timed.frame = request(step);
|
|
126
|
+
timed.state.frame = request(step);
|
|
93
127
|
}
|
|
94
128
|
|
|
95
129
|
/**
|
|
@@ -107,12 +141,10 @@ abstract class Timed<Callback> {
|
|
|
107
141
|
* Start timer
|
|
108
142
|
*/
|
|
109
143
|
start(): this {
|
|
110
|
-
if (this.
|
|
111
|
-
|
|
144
|
+
if (!this.state.active) {
|
|
145
|
+
Timed.run(this as never);
|
|
112
146
|
}
|
|
113
147
|
|
|
114
|
-
Timed.run(this as never);
|
|
115
|
-
|
|
116
148
|
return this;
|
|
117
149
|
}
|
|
118
150
|
|
|
@@ -120,15 +152,17 @@ abstract class Timed<Callback> {
|
|
|
120
152
|
* Stop timer
|
|
121
153
|
*/
|
|
122
154
|
stop(): this {
|
|
123
|
-
this.
|
|
155
|
+
this.state.active = false;
|
|
124
156
|
|
|
125
|
-
if (typeof this.frame === 'undefined') {
|
|
157
|
+
if (typeof this.state.frame === 'undefined') {
|
|
126
158
|
return this;
|
|
127
159
|
}
|
|
128
160
|
|
|
129
|
-
|
|
161
|
+
(cancelAnimationFrame ?? clearTimeout)?.(this.state.frame);
|
|
162
|
+
|
|
163
|
+
this.callbacks.after?.(this.finished);
|
|
130
164
|
|
|
131
|
-
this.frame = undefined;
|
|
165
|
+
this.state.frame = undefined;
|
|
132
166
|
|
|
133
167
|
return this;
|
|
134
168
|
}
|
|
@@ -151,8 +185,8 @@ export class Waited extends Timed<WaitedCallback> {
|
|
|
151
185
|
/**
|
|
152
186
|
* Create and start a new repeated timer
|
|
153
187
|
*/
|
|
154
|
-
export function repeat(callback: RepeatedCallback, time: number, count: number): Repeated {
|
|
155
|
-
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();
|
|
156
190
|
}
|
|
157
191
|
|
|
158
192
|
/**
|