@oscarpalmer/timer 0.8.0 → 0.10.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/README.md +19 -1
- package/dist/{timer.cjs.js → timer.cjs} +43 -36
- package/dist/timer.cjs.map +7 -0
- package/dist/timer.iife.js +2 -127
- package/dist/timer.iife.js.map +7 -0
- package/dist/timer.js +50 -51
- package/dist/timer.js.map +7 -0
- package/package.json +17 -17
- package/src/index.ts +160 -0
package/README.md
CHANGED
|
@@ -6,7 +6,9 @@ A better solution for timeout- and interval-based timers.
|
|
|
6
6
|
|
|
7
7
|
## Installation
|
|
8
8
|
|
|
9
|
-
Timer is available on _npm_ as [`@oscarpalmer/timer`](https://www.npmjs.com/package/@oscarpalmer/timer).
|
|
9
|
+
Timer is available on _npm_ as [`@oscarpalmer/timer`](https://www.npmjs.com/package/@oscarpalmer/timer) to be bundled with your awesome projects.
|
|
10
|
+
|
|
11
|
+
If you don't need to bundle things, you can use the CDN-version and include a script in your proejcts right away, thanks to [jsDelivr](https://www.jsdelivr.com/package/npm/@oscarpalmer/timer) and [UNPKG](https://unpkg.com/@oscarpalmer/timer).
|
|
10
12
|
|
|
11
13
|
## Getting started
|
|
12
14
|
|
|
@@ -32,6 +34,22 @@ waited = new Waited(callback, time);
|
|
|
32
34
|
repeated = new Repeated(callback, time, count);
|
|
33
35
|
```
|
|
34
36
|
|
|
37
|
+
### CDN & IIFE
|
|
38
|
+
|
|
39
|
+
If you're using Timer by including the file suffixed with `.iife.js` – or one of the CDN-versions mentioned above – you won't have to import any of the classes or methods.
|
|
40
|
+
|
|
41
|
+
Instead, just include a `script`-tag in your HTML linking to Timer and you can access Timer in other scripts, as below:
|
|
42
|
+
|
|
43
|
+
```javascript
|
|
44
|
+
// With auto-start
|
|
45
|
+
var waited = Timer.wait(callback, time);
|
|
46
|
+
var repeated = Timer.repeat(callback, time, count);
|
|
47
|
+
|
|
48
|
+
// With manual start
|
|
49
|
+
waited = new Timer.Waited(callback, time);
|
|
50
|
+
repeated = new Timer.Repeated(callback, time, count);
|
|
51
|
+
```
|
|
52
|
+
|
|
35
53
|
## Methods
|
|
36
54
|
|
|
37
55
|
Both the nice helper methods and the class syntax create similar objects – `Waited` and `Repeated` – which share methods:
|
|
@@ -32,52 +32,40 @@ __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
|
+
var request = requestAnimationFrame != null ? requestAnimationFrame : function(callback) {
|
|
39
|
+
var _a;
|
|
40
|
+
return (_a = setTimeout == null ? void 0 : setTimeout(() => {
|
|
41
|
+
callback(Date.now());
|
|
42
|
+
}, milliseconds)) != null ? _a : -1;
|
|
43
|
+
};
|
|
35
44
|
var Timed = class {
|
|
36
|
-
constructor(
|
|
45
|
+
constructor(callback, time, count) {
|
|
37
46
|
__publicField(this, "callback");
|
|
38
47
|
__publicField(this, "count");
|
|
39
48
|
__publicField(this, "frame");
|
|
40
49
|
__publicField(this, "running", false);
|
|
41
50
|
__publicField(this, "time");
|
|
42
|
-
|
|
51
|
+
const isRepeated = this instanceof Repeated;
|
|
52
|
+
const type = isRepeated ? "repeated" : "waited";
|
|
43
53
|
if (typeof callback !== "function") {
|
|
44
54
|
throw new Error(`A ${type} timer must have a callback function`);
|
|
45
55
|
}
|
|
46
56
|
if (typeof time !== "number" || time < 0) {
|
|
47
57
|
throw new Error(`A ${type} timer must have a non-negative number as its time`);
|
|
48
58
|
}
|
|
49
|
-
if (
|
|
50
|
-
throw new Error(
|
|
59
|
+
if (isRepeated && (typeof count !== "number" || count < 2)) {
|
|
60
|
+
throw new Error("A repeated timer must have a number above 1 as its repeat count");
|
|
51
61
|
}
|
|
52
|
-
this.type = type;
|
|
53
62
|
this.callback = callback;
|
|
54
|
-
this.time = time;
|
|
55
63
|
this.count = count;
|
|
64
|
+
this.time = time;
|
|
56
65
|
}
|
|
57
66
|
get active() {
|
|
58
67
|
return this.running;
|
|
59
68
|
}
|
|
60
|
-
restart() {
|
|
61
|
-
this.stop();
|
|
62
|
-
Timed.run(this);
|
|
63
|
-
return this;
|
|
64
|
-
}
|
|
65
|
-
start() {
|
|
66
|
-
if (this.running) {
|
|
67
|
-
return this;
|
|
68
|
-
}
|
|
69
|
-
Timed.run(this);
|
|
70
|
-
return this;
|
|
71
|
-
}
|
|
72
|
-
stop() {
|
|
73
|
-
this.running = false;
|
|
74
|
-
if (typeof this.frame === "undefined") {
|
|
75
|
-
return this;
|
|
76
|
-
}
|
|
77
|
-
window.cancelAnimationFrame(this.frame);
|
|
78
|
-
this.frame = void 0;
|
|
79
|
-
return this;
|
|
80
|
-
}
|
|
81
69
|
static run(timed) {
|
|
82
70
|
timed.running = true;
|
|
83
71
|
let count = 0;
|
|
@@ -86,35 +74,53 @@ var Timed = class {
|
|
|
86
74
|
if (!timed.running) {
|
|
87
75
|
return;
|
|
88
76
|
}
|
|
89
|
-
start
|
|
77
|
+
start != null ? start : start = timestamp;
|
|
90
78
|
const elapsed = timestamp - start;
|
|
91
79
|
const elapsedMinimum = elapsed - milliseconds;
|
|
92
80
|
const elapsedMaximum = elapsed + milliseconds;
|
|
93
81
|
if (elapsedMinimum < timed.time && timed.time < elapsedMaximum) {
|
|
94
82
|
if (timed.running) {
|
|
95
|
-
timed.callback(timed
|
|
83
|
+
timed.callback(timed instanceof Repeated ? count : void 0);
|
|
96
84
|
}
|
|
97
85
|
count += 1;
|
|
98
|
-
if (timed
|
|
86
|
+
if (timed instanceof Repeated && count < timed.count) {
|
|
99
87
|
start = void 0;
|
|
100
88
|
} else {
|
|
101
89
|
timed.stop();
|
|
102
90
|
return;
|
|
103
91
|
}
|
|
104
92
|
}
|
|
105
|
-
timed.frame =
|
|
93
|
+
timed.frame = request(step);
|
|
106
94
|
}
|
|
107
|
-
timed.frame =
|
|
95
|
+
timed.frame = request(step);
|
|
96
|
+
}
|
|
97
|
+
restart() {
|
|
98
|
+
this.stop();
|
|
99
|
+
Timed.run(this);
|
|
100
|
+
return this;
|
|
101
|
+
}
|
|
102
|
+
start() {
|
|
103
|
+
if (this.running) {
|
|
104
|
+
return this;
|
|
105
|
+
}
|
|
106
|
+
Timed.run(this);
|
|
107
|
+
return this;
|
|
108
|
+
}
|
|
109
|
+
stop() {
|
|
110
|
+
this.running = false;
|
|
111
|
+
if (typeof this.frame === "undefined") {
|
|
112
|
+
return this;
|
|
113
|
+
}
|
|
114
|
+
cancel(this.frame);
|
|
115
|
+
this.frame = void 0;
|
|
116
|
+
return this;
|
|
108
117
|
}
|
|
109
118
|
};
|
|
110
119
|
var Repeated = class extends Timed {
|
|
111
|
-
constructor(callback, time, count) {
|
|
112
|
-
super("repeated", callback, time, count);
|
|
113
|
-
}
|
|
114
120
|
};
|
|
115
121
|
var Waited = class extends Timed {
|
|
116
122
|
constructor(callback, time) {
|
|
117
|
-
super(
|
|
123
|
+
super(callback, time, 1);
|
|
118
124
|
}
|
|
119
125
|
};
|
|
120
126
|
function repeat(callback, time, count) {
|
|
@@ -123,3 +129,4 @@ function repeat(callback, time, count) {
|
|
|
123
129
|
function wait(callback, time) {
|
|
124
130
|
return new Waited(callback, time).start();
|
|
125
131
|
}
|
|
132
|
+
//# sourceMappingURL=timer.cjs.map
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
{
|
|
2
|
+
"version": 3,
|
|
3
|
+
"sources": ["../src/index.ts"],
|
|
4
|
+
"sourcesContent": ["type RepeatedCallback = (index: number) => void;\ntype WaitedCallback = () => void;\n\nconst milliseconds = Math.round(1000 / 60);\n\nconst cancel = cancelAnimationFrame ?? function (id: number): void {\n\tclearTimeout?.(id);\n};\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\tprivate readonly callback: Callback;\n\tprivate readonly count: number;\n\tprivate frame: number | undefined;\n\tprivate running = false;\n\tprivate readonly time: number;\n\n\t/**\n\t * Is the timer active?\n\t */\n\tget active(): boolean {\n\t\treturn this.running;\n\t}\n\n\tconstructor(callback: Callback, time: number,\tcount: number) {\n\t\tconst isRepeated = this instanceof Repeated;\n\t\tconst type = isRepeated ? 'repeated' : '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\tthis.callback = callback;\n\t\tthis.count = count;\n\t\tthis.time = time;\n\t}\n\n\tprivate static run(timed: Timed<(index: number | undefined) => void>): void {\n\t\ttimed.running = true;\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.running) {\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.time && timed.time < elapsedMaximum) {\n\t\t\t\tif (timed.running) {\n\t\t\t\t\ttimed.callback(timed instanceof Repeated ? count : undefined);\n\t\t\t\t}\n\n\t\t\t\tcount += 1;\n\n\t\t\t\tif ((timed instanceof Repeated) && count < timed.count) {\n\t\t\t\t\tstart = undefined;\n\t\t\t\t} else {\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.frame = request(step);\n\t\t}\n\n\t\ttimed.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.running) {\n\t\t\treturn this;\n\t\t}\n\n\t\tTimed.run(this as never);\n\n\t\treturn this;\n\t}\n\n\t/**\n\t * Stop timer\n\t */\n\tstop(): this {\n\t\tthis.running = false;\n\n\t\tif (typeof this.frame === 'undefined') {\n\t\t\treturn this;\n\t\t}\n\n\t\tcancel(this.frame);\n\n\t\tthis.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): Repeated {\n\treturn (new Repeated(callback, time, count)).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": ";;;;;;;;;;;;;;;;;;;;;;;;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAGA,IAAM,eAAe,KAAK,MAAM,MAAO,EAAE;AAEzC,IAAM,SAAS,sDAAwB,SAAU,IAAkB;AAClE,+CAAe;AAChB;AAEA,IAAM,UAAU,wDAAyB,SAAU,UAAwC;AAT3F;AAUC,UAAQ,8CAAa,MAAM;AAC1B,aAAS,KAAK,IAAI,CAAC;AAAA,EACpB,GAAG,kBAFK,YAEY;AACrB;AAEA,IAAe,QAAf,MAA+B;AAAA,EAc9B,YAAY,UAAoB,MAAc,OAAe;AAb7D,wBAAiB;AACjB,wBAAiB;AACjB,wBAAQ;AACR,wBAAQ,WAAU;AAClB,wBAAiB;AAUhB,UAAM,aAAa,gBAAgB;AACnC,UAAM,OAAO,aAAa,aAAa;AAEvC,QAAI,OAAO,aAAa,YAAY;AACnC,YAAM,IAAI,MAAM,KAAK,0CAA0C;AAAA,IAChE;AAEA,QAAI,OAAO,SAAS,YAAY,OAAO,GAAG;AACzC,YAAM,IAAI,MAAM,KAAK,wDAAwD;AAAA,IAC9E;AAEA,QAAI,eAAe,OAAO,UAAU,YAAY,QAAQ,IAAI;AAC3D,YAAM,IAAI,MAAM,iEAAiE;AAAA,IAClF;AAEA,SAAK,WAAW;AAChB,SAAK,QAAQ;AACb,SAAK,OAAO;AAAA,EACb;AAAA,EAvBA,IAAI,SAAkB;AACrB,WAAO,KAAK;AAAA,EACb;AAAA,EAuBA,OAAe,IAAI,OAAyD;AAC3E,UAAM,UAAU;AAEhB,QAAI,QAAQ;AAEZ,QAAI;AAEJ,aAAS,KAAK,WAAsC;AACnD,UAAI,CAAC,MAAM,SAAS;AACnB;AAAA,MACD;AAEA,sCAAU;AAEV,YAAM,UAAU,YAAY;AAE5B,YAAM,iBAAiB,UAAU;AACjC,YAAM,iBAAiB,UAAU;AAEjC,UAAI,iBAAiB,MAAM,QAAQ,MAAM,OAAO,gBAAgB;AAC/D,YAAI,MAAM,SAAS;AAClB,gBAAM,SAAS,iBAAiB,WAAW,QAAQ,MAAS;AAAA,QAC7D;AAEA,iBAAS;AAET,YAAK,iBAAiB,YAAa,QAAQ,MAAM,OAAO;AACvD,kBAAQ;AAAA,QACT,OAAO;AACN,gBAAM,KAAK;AAEX;AAAA,QACD;AAAA,MACD;AAEA,YAAM,QAAQ,QAAQ,IAAI;AAAA,IAC3B;AAEA,UAAM,QAAQ,QAAQ,IAAI;AAAA,EAC3B;AAAA,EAKA,UAAgB;AACf,SAAK,KAAK;AAEV,UAAM,IAAI,IAAa;AAEvB,WAAO;AAAA,EACR;AAAA,EAKA,QAAc;AACb,QAAI,KAAK,SAAS;AACjB,aAAO;AAAA,IACR;AAEA,UAAM,IAAI,IAAa;AAEvB,WAAO;AAAA,EACR;AAAA,EAKA,OAAa;AACZ,SAAK,UAAU;AAEf,QAAI,OAAO,KAAK,UAAU,aAAa;AACtC,aAAO;AAAA,IACR;AAEA,WAAO,KAAK,KAAK;AAEjB,SAAK,QAAQ;AAEb,WAAO;AAAA,EACR;AACD;AAKO,IAAM,WAAN,cAAuB,MAAwB;AAAC;AAKhD,IAAM,SAAN,cAAqB,MAAsB;AAAA,EACjD,YAAY,UAA0B,MAAc;AACnD,UAAM,UAAU,MAAM,CAAC;AAAA,EACxB;AACD;AAKO,SAAS,OAAO,UAA4B,MAAc,OAAyB;AACzF,SAAQ,IAAI,SAAS,UAAU,MAAM,KAAK,EAAG,MAAM;AACpD;AAKO,SAAS,KAAK,UAA0B,MAAsB;AACpE,SAAQ,IAAI,OAAO,UAAU,IAAI,EAAG,MAAM;AAC3C;",
|
|
6
|
+
"names": []
|
|
7
|
+
}
|
package/dist/timer.iife.js
CHANGED
|
@@ -1,127 +1,2 @@
|
|
|
1
|
-
"use strict";
|
|
2
|
-
|
|
3
|
-
var __defProp = Object.defineProperty;
|
|
4
|
-
var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
|
|
5
|
-
var __getOwnPropNames = Object.getOwnPropertyNames;
|
|
6
|
-
var __hasOwnProp = Object.prototype.hasOwnProperty;
|
|
7
|
-
var __defNormalProp = (obj, key, value) => key in obj ? __defProp(obj, key, { enumerable: true, configurable: true, writable: true, value }) : obj[key] = value;
|
|
8
|
-
var __export = (target, all) => {
|
|
9
|
-
for (var name in all)
|
|
10
|
-
__defProp(target, name, { get: all[name], enumerable: true });
|
|
11
|
-
};
|
|
12
|
-
var __copyProps = (to, from, except, desc) => {
|
|
13
|
-
if (from && typeof from === "object" || typeof from === "function") {
|
|
14
|
-
for (let key of __getOwnPropNames(from))
|
|
15
|
-
if (!__hasOwnProp.call(to, key) && key !== except)
|
|
16
|
-
__defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
|
|
17
|
-
}
|
|
18
|
-
return to;
|
|
19
|
-
};
|
|
20
|
-
var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
|
|
21
|
-
var __publicField = (obj, key, value) => {
|
|
22
|
-
__defNormalProp(obj, typeof key !== "symbol" ? key + "" : key, value);
|
|
23
|
-
return value;
|
|
24
|
-
};
|
|
25
|
-
|
|
26
|
-
// src/index.ts
|
|
27
|
-
var src_exports = {};
|
|
28
|
-
__export(src_exports, {
|
|
29
|
-
Repeated: () => Repeated,
|
|
30
|
-
Waited: () => Waited,
|
|
31
|
-
repeat: () => repeat,
|
|
32
|
-
wait: () => wait
|
|
33
|
-
});
|
|
34
|
-
var milliseconds = Math.round(1e3 / 60);
|
|
35
|
-
var Timed = class {
|
|
36
|
-
constructor(type, callback, time, count) {
|
|
37
|
-
__publicField(this, "callback");
|
|
38
|
-
__publicField(this, "count");
|
|
39
|
-
__publicField(this, "frame");
|
|
40
|
-
__publicField(this, "running", false);
|
|
41
|
-
__publicField(this, "time");
|
|
42
|
-
__publicField(this, "type");
|
|
43
|
-
if (typeof callback !== "function") {
|
|
44
|
-
throw new Error(`A ${type} timer must have a callback function`);
|
|
45
|
-
}
|
|
46
|
-
if (typeof time !== "number" || time < 0) {
|
|
47
|
-
throw new Error(`A ${type} timer must have a non-negative number as its time`);
|
|
48
|
-
}
|
|
49
|
-
if (type === "repeated" && (typeof count !== "number" || count < 2)) {
|
|
50
|
-
throw new Error(`A ${type} timer must have a number above 1 as its repeat count`);
|
|
51
|
-
}
|
|
52
|
-
this.type = type;
|
|
53
|
-
this.callback = callback;
|
|
54
|
-
this.time = time;
|
|
55
|
-
this.count = count;
|
|
56
|
-
}
|
|
57
|
-
get active() {
|
|
58
|
-
return this.running;
|
|
59
|
-
}
|
|
60
|
-
restart() {
|
|
61
|
-
this.stop();
|
|
62
|
-
Timed.run(this);
|
|
63
|
-
return this;
|
|
64
|
-
}
|
|
65
|
-
start() {
|
|
66
|
-
if (this.running) {
|
|
67
|
-
return this;
|
|
68
|
-
}
|
|
69
|
-
Timed.run(this);
|
|
70
|
-
return this;
|
|
71
|
-
}
|
|
72
|
-
stop() {
|
|
73
|
-
this.running = false;
|
|
74
|
-
if (typeof this.frame === "undefined") {
|
|
75
|
-
return this;
|
|
76
|
-
}
|
|
77
|
-
window.cancelAnimationFrame(this.frame);
|
|
78
|
-
this.frame = void 0;
|
|
79
|
-
return this;
|
|
80
|
-
}
|
|
81
|
-
static run(timed) {
|
|
82
|
-
timed.running = true;
|
|
83
|
-
let count = 0;
|
|
84
|
-
let start;
|
|
85
|
-
function step(timestamp) {
|
|
86
|
-
if (!timed.running) {
|
|
87
|
-
return;
|
|
88
|
-
}
|
|
89
|
-
start ?? (start = timestamp);
|
|
90
|
-
const elapsed = timestamp - start;
|
|
91
|
-
const elapsedMinimum = elapsed - milliseconds;
|
|
92
|
-
const elapsedMaximum = elapsed + milliseconds;
|
|
93
|
-
if (elapsedMinimum < timed.time && timed.time < elapsedMaximum) {
|
|
94
|
-
if (timed.running) {
|
|
95
|
-
timed.callback(timed.type === "repeated" ? count : void 0);
|
|
96
|
-
}
|
|
97
|
-
count += 1;
|
|
98
|
-
if (timed.type === "repeated" && count < timed.count) {
|
|
99
|
-
start = void 0;
|
|
100
|
-
} else {
|
|
101
|
-
timed.stop();
|
|
102
|
-
return;
|
|
103
|
-
}
|
|
104
|
-
}
|
|
105
|
-
timed.frame = window.requestAnimationFrame(step);
|
|
106
|
-
}
|
|
107
|
-
timed.frame = window.requestAnimationFrame(step);
|
|
108
|
-
}
|
|
109
|
-
};
|
|
110
|
-
var Repeated = class extends Timed {
|
|
111
|
-
constructor(callback, time, count) {
|
|
112
|
-
super("repeated", callback, time, count);
|
|
113
|
-
}
|
|
114
|
-
};
|
|
115
|
-
var Waited = class extends Timed {
|
|
116
|
-
constructor(callback, time) {
|
|
117
|
-
super("waited", callback, time, 1);
|
|
118
|
-
}
|
|
119
|
-
};
|
|
120
|
-
function repeat(callback, time, count) {
|
|
121
|
-
return new Repeated(callback, time, count).start();
|
|
122
|
-
}
|
|
123
|
-
function wait(callback, time) {
|
|
124
|
-
return new Waited(callback, time).start();
|
|
125
|
-
}
|
|
126
|
-
return __toCommonJS(src_exports);
|
|
127
|
-
})();
|
|
1
|
+
"use strict";var Timer=(()=>{var c=Object.defineProperty;var h=Object.getOwnPropertyDescriptor;var v=Object.getOwnPropertyNames;var k=Object.prototype.hasOwnProperty;var w=(n,e,t)=>e in n?c(n,e,{enumerable:!0,configurable:!0,writable:!0,value:t}):n[e]=t;var g=(n,e)=>{for(var t in e)c(n,t,{get:e[t],enumerable:!0})},C=(n,e,t,r)=>{if(e&&typeof e=="object"||typeof e=="function")for(let a of v(e))!k.call(n,a)&&a!==t&&c(n,a,{get:()=>e[a],enumerable:!(r=h(e,a))||r.enumerable});return n};var y=n=>C(c({},"__esModule",{value:!0}),n);var u=(n,e,t)=>(w(n,typeof e!="symbol"?e+"":e,t),t);var M={};g(M,{Repeated:()=>i,Waited:()=>l,repeat:()=>R,wait:()=>A});var f=Math.round(16.666666666666668),x=cancelAnimationFrame!=null?cancelAnimationFrame:function(n){clearTimeout==null||clearTimeout(n)},m=requestAnimationFrame!=null?requestAnimationFrame:function(n){var e;return(e=setTimeout==null?void 0:setTimeout(()=>{n(Date.now())},f))!=null?e:-1},s=class{constructor(e,t,r){u(this,"callback");u(this,"count");u(this,"frame");u(this,"running",!1);u(this,"time");let a=this instanceof i,o=a?"repeated":"waited";if(typeof e!="function")throw new Error(`A ${o} timer must have a callback function`);if(typeof t!="number"||t<0)throw new Error(`A ${o} timer must have a non-negative number as its time`);if(a&&(typeof r!="number"||r<2))throw new Error("A repeated timer must have a number above 1 as its repeat count");this.callback=e,this.count=r,this.time=t}get active(){return this.running}static run(e){e.running=!0;let t=0,r;function a(o){if(!e.running)return;r!=null||(r=o);let b=o-r,p=b-f,d=b+f;if(p<e.time&&e.time<d)if(e.running&&e.callback(e instanceof i?t:void 0),t+=1,e instanceof i&&t<e.count)r=void 0;else{e.stop();return}e.frame=m(a)}e.frame=m(a)}restart(){return this.stop(),s.run(this),this}start(){return this.running?this:(s.run(this),this)}stop(){return this.running=!1,typeof this.frame=="undefined"?this:(x(this.frame),this.frame=void 0,this)}},i=class extends s{},l=class extends s{constructor(e,t){super(e,t,1)}};function R(n,e,t){return new i(n,e,t).start()}function A(n,e){return new l(n,e).start()}return y(M);})();
|
|
2
|
+
//# sourceMappingURL=timer.iife.js.map
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
{
|
|
2
|
+
"version": 3,
|
|
3
|
+
"sources": ["../src/index.ts"],
|
|
4
|
+
"sourcesContent": ["type RepeatedCallback = (index: number) => void;\ntype WaitedCallback = () => void;\n\nconst milliseconds = Math.round(1000 / 60);\n\nconst cancel = cancelAnimationFrame ?? function (id: number): void {\n\tclearTimeout?.(id);\n};\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\tprivate readonly callback: Callback;\n\tprivate readonly count: number;\n\tprivate frame: number | undefined;\n\tprivate running = false;\n\tprivate readonly time: number;\n\n\t/**\n\t * Is the timer active?\n\t */\n\tget active(): boolean {\n\t\treturn this.running;\n\t}\n\n\tconstructor(callback: Callback, time: number,\tcount: number) {\n\t\tconst isRepeated = this instanceof Repeated;\n\t\tconst type = isRepeated ? 'repeated' : '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\tthis.callback = callback;\n\t\tthis.count = count;\n\t\tthis.time = time;\n\t}\n\n\tprivate static run(timed: Timed<(index: number | undefined) => void>): void {\n\t\ttimed.running = true;\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.running) {\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.time && timed.time < elapsedMaximum) {\n\t\t\t\tif (timed.running) {\n\t\t\t\t\ttimed.callback(timed instanceof Repeated ? count : undefined);\n\t\t\t\t}\n\n\t\t\t\tcount += 1;\n\n\t\t\t\tif ((timed instanceof Repeated) && count < timed.count) {\n\t\t\t\t\tstart = undefined;\n\t\t\t\t} else {\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.frame = request(step);\n\t\t}\n\n\t\ttimed.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.running) {\n\t\t\treturn this;\n\t\t}\n\n\t\tTimed.run(this as never);\n\n\t\treturn this;\n\t}\n\n\t/**\n\t * Stop timer\n\t */\n\tstop(): this {\n\t\tthis.running = false;\n\n\t\tif (typeof this.frame === 'undefined') {\n\t\t\treturn this;\n\t\t}\n\n\t\tcancel(this.frame);\n\n\t\tthis.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): Repeated {\n\treturn (new Repeated(callback, time, count)).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": "qkBAAA,IAAAA,EAAA,GAAAC,EAAAD,EAAA,cAAAE,EAAA,WAAAC,EAAA,WAAAC,EAAA,SAAAC,IAGA,IAAMC,EAAe,KAAK,MAAM,kBAAS,EAEnCC,EAAS,gDAAwB,SAAUC,EAAkB,CAClE,iCAAeA,EAChB,EAEMC,EAAU,kDAAyB,SAAUC,EAAwC,CAT3F,IAAAC,EAUC,OAAQA,EAAA,mCAAa,IAAM,CAC1BD,EAAS,KAAK,IAAI,CAAC,CACpB,EAAGJ,KAFK,KAAAK,EAEY,EACrB,EAEeC,EAAf,KAA+B,CAc9B,YAAYF,EAAoBG,EAAcC,EAAe,CAb7DC,EAAA,KAAiB,YACjBA,EAAA,KAAiB,SACjBA,EAAA,KAAQ,SACRA,EAAA,KAAQ,UAAU,IAClBA,EAAA,KAAiB,QAUhB,IAAMC,EAAa,gBAAgBC,EAC7BC,EAAOF,EAAa,WAAa,SAEvC,GAAI,OAAON,GAAa,WACvB,MAAM,IAAI,MAAM,KAAKQ,uCAA0C,EAGhE,GAAI,OAAOL,GAAS,UAAYA,EAAO,EACtC,MAAM,IAAI,MAAM,KAAKK,qDAAwD,EAG9E,GAAIF,IAAe,OAAOF,GAAU,UAAYA,EAAQ,GACvD,MAAM,IAAI,MAAM,iEAAiE,EAGlF,KAAK,SAAWJ,EAChB,KAAK,MAAQI,EACb,KAAK,KAAOD,CACb,CAvBA,IAAI,QAAkB,CACrB,OAAO,KAAK,OACb,CAuBA,OAAe,IAAIM,EAAyD,CAC3EA,EAAM,QAAU,GAEhB,IAAIL,EAAQ,EAERM,EAEJ,SAASC,EAAKC,EAAsC,CACnD,GAAI,CAACH,EAAM,QACV,OAGDC,GAAA,OAAAA,EAAUE,GAEV,IAAMC,EAAUD,EAAYF,EAEtBI,EAAiBD,EAAUjB,EAC3BmB,EAAiBF,EAAUjB,EAEjC,GAAIkB,EAAiBL,EAAM,MAAQA,EAAM,KAAOM,EAO/C,GANIN,EAAM,SACTA,EAAM,SAASA,aAAiBF,EAAWH,EAAQ,MAAS,EAG7DA,GAAS,EAEJK,aAAiBF,GAAaH,EAAQK,EAAM,MAChDC,EAAQ,WACF,CACND,EAAM,KAAK,EAEX,MACD,CAGDA,EAAM,MAAQV,EAAQY,CAAI,CAC3B,CAEAF,EAAM,MAAQV,EAAQY,CAAI,CAC3B,CAKA,SAAgB,CACf,YAAK,KAAK,EAEVT,EAAM,IAAI,IAAa,EAEhB,IACR,CAKA,OAAc,CACb,OAAI,KAAK,QACD,MAGRA,EAAM,IAAI,IAAa,EAEhB,KACR,CAKA,MAAa,CAGZ,OAFA,KAAK,QAAU,GAEX,OAAO,KAAK,OAAU,YAClB,MAGRL,EAAO,KAAK,KAAK,EAEjB,KAAK,MAAQ,OAEN,KACR,CACD,EAKaU,EAAN,cAAuBL,CAAwB,CAAC,EAK1Cc,EAAN,cAAqBd,CAAsB,CACjD,YAAYF,EAA0BG,EAAc,CACnD,MAAMH,EAAUG,EAAM,CAAC,CACxB,CACD,EAKO,SAASc,EAAOjB,EAA4BG,EAAcC,EAAyB,CACzF,OAAQ,IAAIG,EAASP,EAAUG,EAAMC,CAAK,EAAG,MAAM,CACpD,CAKO,SAASc,EAAKlB,EAA0BG,EAAsB,CACpE,OAAQ,IAAIa,EAAOhB,EAAUG,CAAI,EAAG,MAAM,CAC3C",
|
|
6
|
+
"names": ["src_exports", "__export", "Repeated", "Waited", "repeat", "wait", "milliseconds", "cancel", "id", "request", "callback", "_a", "Timed", "time", "count", "__publicField", "isRepeated", "Repeated", "type", "timed", "start", "step", "timestamp", "elapsed", "elapsedMinimum", "elapsedMaximum", "Waited", "repeat", "wait"]
|
|
7
|
+
}
|
package/dist/timer.js
CHANGED
|
@@ -1,57 +1,37 @@
|
|
|
1
|
-
var __defProp = Object.defineProperty;
|
|
2
|
-
var __defNormalProp = (obj, key, value) => key in obj ? __defProp(obj, key, { enumerable: true, configurable: true, writable: true, value }) : obj[key] = value;
|
|
3
|
-
var __publicField = (obj, key, value) => {
|
|
4
|
-
__defNormalProp(obj, typeof key !== "symbol" ? key + "" : key, value);
|
|
5
|
-
return value;
|
|
6
|
-
};
|
|
7
|
-
|
|
8
1
|
// src/index.ts
|
|
9
2
|
var milliseconds = Math.round(1e3 / 60);
|
|
3
|
+
var cancel = cancelAnimationFrame ?? function(id) {
|
|
4
|
+
clearTimeout?.(id);
|
|
5
|
+
};
|
|
6
|
+
var request = requestAnimationFrame ?? function(callback) {
|
|
7
|
+
return setTimeout?.(() => {
|
|
8
|
+
callback(Date.now());
|
|
9
|
+
}, milliseconds) ?? -1;
|
|
10
|
+
};
|
|
10
11
|
var Timed = class {
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
12
|
+
callback;
|
|
13
|
+
count;
|
|
14
|
+
frame;
|
|
15
|
+
running = false;
|
|
16
|
+
time;
|
|
17
|
+
get active() {
|
|
18
|
+
return this.running;
|
|
19
|
+
}
|
|
20
|
+
constructor(callback, time, count) {
|
|
21
|
+
const isRepeated = this instanceof Repeated;
|
|
22
|
+
const type = isRepeated ? "repeated" : "waited";
|
|
18
23
|
if (typeof callback !== "function") {
|
|
19
24
|
throw new Error(`A ${type} timer must have a callback function`);
|
|
20
25
|
}
|
|
21
26
|
if (typeof time !== "number" || time < 0) {
|
|
22
27
|
throw new Error(`A ${type} timer must have a non-negative number as its time`);
|
|
23
28
|
}
|
|
24
|
-
if (
|
|
25
|
-
throw new Error(
|
|
29
|
+
if (isRepeated && (typeof count !== "number" || count < 2)) {
|
|
30
|
+
throw new Error("A repeated timer must have a number above 1 as its repeat count");
|
|
26
31
|
}
|
|
27
|
-
this.type = type;
|
|
28
32
|
this.callback = callback;
|
|
29
|
-
this.time = time;
|
|
30
33
|
this.count = count;
|
|
31
|
-
|
|
32
|
-
get active() {
|
|
33
|
-
return this.running;
|
|
34
|
-
}
|
|
35
|
-
restart() {
|
|
36
|
-
this.stop();
|
|
37
|
-
Timed.run(this);
|
|
38
|
-
return this;
|
|
39
|
-
}
|
|
40
|
-
start() {
|
|
41
|
-
if (this.running) {
|
|
42
|
-
return this;
|
|
43
|
-
}
|
|
44
|
-
Timed.run(this);
|
|
45
|
-
return this;
|
|
46
|
-
}
|
|
47
|
-
stop() {
|
|
48
|
-
this.running = false;
|
|
49
|
-
if (typeof this.frame === "undefined") {
|
|
50
|
-
return this;
|
|
51
|
-
}
|
|
52
|
-
window.cancelAnimationFrame(this.frame);
|
|
53
|
-
this.frame = void 0;
|
|
54
|
-
return this;
|
|
34
|
+
this.time = time;
|
|
55
35
|
}
|
|
56
36
|
static run(timed) {
|
|
57
37
|
timed.running = true;
|
|
@@ -61,35 +41,53 @@ var Timed = class {
|
|
|
61
41
|
if (!timed.running) {
|
|
62
42
|
return;
|
|
63
43
|
}
|
|
64
|
-
start
|
|
44
|
+
start ??= timestamp;
|
|
65
45
|
const elapsed = timestamp - start;
|
|
66
46
|
const elapsedMinimum = elapsed - milliseconds;
|
|
67
47
|
const elapsedMaximum = elapsed + milliseconds;
|
|
68
48
|
if (elapsedMinimum < timed.time && timed.time < elapsedMaximum) {
|
|
69
49
|
if (timed.running) {
|
|
70
|
-
timed.callback(timed
|
|
50
|
+
timed.callback(timed instanceof Repeated ? count : void 0);
|
|
71
51
|
}
|
|
72
52
|
count += 1;
|
|
73
|
-
if (timed
|
|
53
|
+
if (timed instanceof Repeated && count < timed.count) {
|
|
74
54
|
start = void 0;
|
|
75
55
|
} else {
|
|
76
56
|
timed.stop();
|
|
77
57
|
return;
|
|
78
58
|
}
|
|
79
59
|
}
|
|
80
|
-
timed.frame =
|
|
60
|
+
timed.frame = request(step);
|
|
81
61
|
}
|
|
82
|
-
timed.frame =
|
|
62
|
+
timed.frame = request(step);
|
|
63
|
+
}
|
|
64
|
+
restart() {
|
|
65
|
+
this.stop();
|
|
66
|
+
Timed.run(this);
|
|
67
|
+
return this;
|
|
68
|
+
}
|
|
69
|
+
start() {
|
|
70
|
+
if (this.running) {
|
|
71
|
+
return this;
|
|
72
|
+
}
|
|
73
|
+
Timed.run(this);
|
|
74
|
+
return this;
|
|
75
|
+
}
|
|
76
|
+
stop() {
|
|
77
|
+
this.running = false;
|
|
78
|
+
if (typeof this.frame === "undefined") {
|
|
79
|
+
return this;
|
|
80
|
+
}
|
|
81
|
+
cancel(this.frame);
|
|
82
|
+
this.frame = void 0;
|
|
83
|
+
return this;
|
|
83
84
|
}
|
|
84
85
|
};
|
|
85
86
|
var Repeated = class extends Timed {
|
|
86
|
-
constructor(callback, time, count) {
|
|
87
|
-
super("repeated", callback, time, count);
|
|
88
|
-
}
|
|
89
87
|
};
|
|
90
88
|
var Waited = class extends Timed {
|
|
91
89
|
constructor(callback, time) {
|
|
92
|
-
super(
|
|
90
|
+
super(callback, time, 1);
|
|
93
91
|
}
|
|
94
92
|
};
|
|
95
93
|
function repeat(callback, time, count) {
|
|
@@ -104,3 +102,4 @@ export {
|
|
|
104
102
|
repeat,
|
|
105
103
|
wait
|
|
106
104
|
};
|
|
105
|
+
//# sourceMappingURL=timer.js.map
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
{
|
|
2
|
+
"version": 3,
|
|
3
|
+
"sources": ["../src/index.ts"],
|
|
4
|
+
"sourcesContent": ["type RepeatedCallback = (index: number) => void;\ntype WaitedCallback = () => void;\n\nconst milliseconds = Math.round(1000 / 60);\n\nconst cancel = cancelAnimationFrame ?? function (id: number): void {\n\tclearTimeout?.(id);\n};\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\tprivate readonly callback: Callback;\n\tprivate readonly count: number;\n\tprivate frame: number | undefined;\n\tprivate running = false;\n\tprivate readonly time: number;\n\n\t/**\n\t * Is the timer active?\n\t */\n\tget active(): boolean {\n\t\treturn this.running;\n\t}\n\n\tconstructor(callback: Callback, time: number,\tcount: number) {\n\t\tconst isRepeated = this instanceof Repeated;\n\t\tconst type = isRepeated ? 'repeated' : '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\tthis.callback = callback;\n\t\tthis.count = count;\n\t\tthis.time = time;\n\t}\n\n\tprivate static run(timed: Timed<(index: number | undefined) => void>): void {\n\t\ttimed.running = true;\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.running) {\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.time && timed.time < elapsedMaximum) {\n\t\t\t\tif (timed.running) {\n\t\t\t\t\ttimed.callback(timed instanceof Repeated ? count : undefined);\n\t\t\t\t}\n\n\t\t\t\tcount += 1;\n\n\t\t\t\tif ((timed instanceof Repeated) && count < timed.count) {\n\t\t\t\t\tstart = undefined;\n\t\t\t\t} else {\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.frame = request(step);\n\t\t}\n\n\t\ttimed.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.running) {\n\t\t\treturn this;\n\t\t}\n\n\t\tTimed.run(this as never);\n\n\t\treturn this;\n\t}\n\n\t/**\n\t * Stop timer\n\t */\n\tstop(): this {\n\t\tthis.running = false;\n\n\t\tif (typeof this.frame === 'undefined') {\n\t\t\treturn this;\n\t\t}\n\n\t\tcancel(this.frame);\n\n\t\tthis.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): Repeated {\n\treturn (new Repeated(callback, time, count)).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": ";AAGA,IAAM,eAAe,KAAK,MAAM,MAAO,EAAE;AAEzC,IAAM,SAAS,wBAAwB,SAAU,IAAkB;AAClE,iBAAe,EAAE;AAClB;AAEA,IAAM,UAAU,yBAAyB,SAAU,UAAwC;AAC1F,SAAQ,aAAa,MAAM;AAC1B,aAAS,KAAK,IAAI,CAAC;AAAA,EACpB,GAAG,YAAY,KAAK;AACrB;AAEA,IAAe,QAAf,MAA+B;AAAA,EACb;AAAA,EACA;AAAA,EACT;AAAA,EACA,UAAU;AAAA,EACD;AAAA,EAKjB,IAAI,SAAkB;AACrB,WAAO,KAAK;AAAA,EACb;AAAA,EAEA,YAAY,UAAoB,MAAc,OAAe;AAC5D,UAAM,aAAa,gBAAgB;AACnC,UAAM,OAAO,aAAa,aAAa;AAEvC,QAAI,OAAO,aAAa,YAAY;AACnC,YAAM,IAAI,MAAM,KAAK,0CAA0C;AAAA,IAChE;AAEA,QAAI,OAAO,SAAS,YAAY,OAAO,GAAG;AACzC,YAAM,IAAI,MAAM,KAAK,wDAAwD;AAAA,IAC9E;AAEA,QAAI,eAAe,OAAO,UAAU,YAAY,QAAQ,IAAI;AAC3D,YAAM,IAAI,MAAM,iEAAiE;AAAA,IAClF;AAEA,SAAK,WAAW;AAChB,SAAK,QAAQ;AACb,SAAK,OAAO;AAAA,EACb;AAAA,EAEA,OAAe,IAAI,OAAyD;AAC3E,UAAM,UAAU;AAEhB,QAAI,QAAQ;AAEZ,QAAI;AAEJ,aAAS,KAAK,WAAsC;AACnD,UAAI,CAAC,MAAM,SAAS;AACnB;AAAA,MACD;AAEA,gBAAU;AAEV,YAAM,UAAU,YAAY;AAE5B,YAAM,iBAAiB,UAAU;AACjC,YAAM,iBAAiB,UAAU;AAEjC,UAAI,iBAAiB,MAAM,QAAQ,MAAM,OAAO,gBAAgB;AAC/D,YAAI,MAAM,SAAS;AAClB,gBAAM,SAAS,iBAAiB,WAAW,QAAQ,MAAS;AAAA,QAC7D;AAEA,iBAAS;AAET,YAAK,iBAAiB,YAAa,QAAQ,MAAM,OAAO;AACvD,kBAAQ;AAAA,QACT,OAAO;AACN,gBAAM,KAAK;AAEX;AAAA,QACD;AAAA,MACD;AAEA,YAAM,QAAQ,QAAQ,IAAI;AAAA,IAC3B;AAEA,UAAM,QAAQ,QAAQ,IAAI;AAAA,EAC3B;AAAA,EAKA,UAAgB;AACf,SAAK,KAAK;AAEV,UAAM,IAAI,IAAa;AAEvB,WAAO;AAAA,EACR;AAAA,EAKA,QAAc;AACb,QAAI,KAAK,SAAS;AACjB,aAAO;AAAA,IACR;AAEA,UAAM,IAAI,IAAa;AAEvB,WAAO;AAAA,EACR;AAAA,EAKA,OAAa;AACZ,SAAK,UAAU;AAEf,QAAI,OAAO,KAAK,UAAU,aAAa;AACtC,aAAO;AAAA,IACR;AAEA,WAAO,KAAK,KAAK;AAEjB,SAAK,QAAQ;AAEb,WAAO;AAAA,EACR;AACD;AAKO,IAAM,WAAN,cAAuB,MAAwB;AAAC;AAKhD,IAAM,SAAN,cAAqB,MAAsB;AAAA,EACjD,YAAY,UAA0B,MAAc;AACnD,UAAM,UAAU,MAAM,CAAC;AAAA,EACxB;AACD;AAKO,SAAS,OAAO,UAA4B,MAAc,OAAyB;AACzF,SAAQ,IAAI,SAAS,UAAU,MAAM,KAAK,EAAG,MAAM;AACpD;AAKO,SAAS,KAAK,UAA0B,MAAsB;AACpE,SAAQ,IAAI,OAAO,UAAU,IAAI,EAAG,MAAM;AAC3C;",
|
|
6
|
+
"names": []
|
|
7
|
+
}
|
package/package.json
CHANGED
|
@@ -8,8 +8,8 @@
|
|
|
8
8
|
"devDependencies": {
|
|
9
9
|
"@tsconfig/recommended": "^1.0.0",
|
|
10
10
|
"@types/node": "^18.7.0",
|
|
11
|
-
"@typescript-eslint/eslint-plugin": "^5.
|
|
12
|
-
"@typescript-eslint/parser": "^5.
|
|
11
|
+
"@typescript-eslint/eslint-plugin": "^5.38.0",
|
|
12
|
+
"@typescript-eslint/parser": "^5.38.0",
|
|
13
13
|
"esbuild": "^0.15.0",
|
|
14
14
|
"eslint": "^8.23.0",
|
|
15
15
|
"eslint-config-xo": "^0.42.0",
|
|
@@ -19,15 +19,15 @@
|
|
|
19
19
|
"exports": {
|
|
20
20
|
".": {
|
|
21
21
|
"types": "./src/index.d.ts",
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
22
|
+
"browser": "./dist/timer.iife.js",
|
|
23
|
+
"module": "./dist/timer.js",
|
|
24
|
+
"import": "./dist/timer.js",
|
|
25
|
+
"require": "./dist/timer.cjs"
|
|
26
|
+
},
|
|
27
|
+
"./package.json": "./package.json"
|
|
28
28
|
},
|
|
29
|
-
"files": ["dist", "src
|
|
30
|
-
"jsdelivr": "dist/timer.js",
|
|
29
|
+
"files": ["dist", "src"],
|
|
30
|
+
"jsdelivr": "dist/timer.iife.js",
|
|
31
31
|
"keywords": [
|
|
32
32
|
"timer",
|
|
33
33
|
"setTimeout",
|
|
@@ -35,7 +35,7 @@
|
|
|
35
35
|
"requestAnimationFrame"
|
|
36
36
|
],
|
|
37
37
|
"license": "MIT",
|
|
38
|
-
"main": "dist/timer.cjs
|
|
38
|
+
"main": "dist/timer.cjs",
|
|
39
39
|
"module": "dist/timer.js",
|
|
40
40
|
"name": "@oscarpalmer/timer",
|
|
41
41
|
"repository": {
|
|
@@ -44,13 +44,13 @@
|
|
|
44
44
|
},
|
|
45
45
|
"scripts": {
|
|
46
46
|
"build": "npm run build:cjs; npm run build:esm; npm run build:iife",
|
|
47
|
-
"build:cjs": "esbuild ./src/index.ts --bundle --
|
|
48
|
-
"build:esm": "esbuild ./src/index.ts --bundle --
|
|
49
|
-
"build:iife": "esbuild ./src/index.ts --bundle --
|
|
50
|
-
"watch": "esbuild ./src/index.ts --bundle --
|
|
47
|
+
"build:cjs": "esbuild ./src/index.ts --bundle --sourcemap --format=cjs --outfile=./dist/timer.cjs --target=es2017",
|
|
48
|
+
"build:esm": "esbuild ./src/index.ts --bundle --sourcemap --format=esm --outfile=./dist/timer.js --target=esnext",
|
|
49
|
+
"build:iife": "esbuild ./src/index.ts --bundle --minify --sourcemap --format=iife --global-name=Timer --outfile=./dist/timer.iife.js --target=es2017",
|
|
50
|
+
"watch": "esbuild ./src/index.ts --bundle --watch --format=esm --outfile=./dist/timer.js --platform=browser --target=esnext"
|
|
51
51
|
},
|
|
52
52
|
"type": "module",
|
|
53
53
|
"types": "src/index.d.ts",
|
|
54
|
-
"unpkg": "dist/timer.js",
|
|
55
|
-
"version": "0.
|
|
54
|
+
"unpkg": "dist/timer.iife.js",
|
|
55
|
+
"version": "0.10.0"
|
|
56
56
|
}
|
package/src/index.ts
ADDED
|
@@ -0,0 +1,160 @@
|
|
|
1
|
+
type RepeatedCallback = (index: number) => void;
|
|
2
|
+
type WaitedCallback = () => void;
|
|
3
|
+
|
|
4
|
+
const milliseconds = Math.round(1000 / 60);
|
|
5
|
+
|
|
6
|
+
const cancel = cancelAnimationFrame ?? function (id: number): void {
|
|
7
|
+
clearTimeout?.(id);
|
|
8
|
+
};
|
|
9
|
+
|
|
10
|
+
const request = requestAnimationFrame ?? function (callback: FrameRequestCallback): number {
|
|
11
|
+
return (setTimeout?.(() => {
|
|
12
|
+
callback(Date.now());
|
|
13
|
+
}, milliseconds) ?? -1) as unknown as number;
|
|
14
|
+
};
|
|
15
|
+
|
|
16
|
+
abstract class Timed<Callback> {
|
|
17
|
+
private readonly callback: Callback;
|
|
18
|
+
private readonly count: number;
|
|
19
|
+
private frame: number | undefined;
|
|
20
|
+
private running = false;
|
|
21
|
+
private readonly time: number;
|
|
22
|
+
|
|
23
|
+
/**
|
|
24
|
+
* Is the timer active?
|
|
25
|
+
*/
|
|
26
|
+
get active(): boolean {
|
|
27
|
+
return this.running;
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
constructor(callback: Callback, time: number, count: number) {
|
|
31
|
+
const isRepeated = this instanceof Repeated;
|
|
32
|
+
const type = isRepeated ? 'repeated' : 'waited';
|
|
33
|
+
|
|
34
|
+
if (typeof callback !== 'function') {
|
|
35
|
+
throw new Error(`A ${type} timer must have a callback function`);
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
if (typeof time !== 'number' || time < 0) {
|
|
39
|
+
throw new Error(`A ${type} timer must have a non-negative number as its time`);
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
if (isRepeated && (typeof count !== 'number' || count < 2)) {
|
|
43
|
+
throw new Error('A repeated timer must have a number above 1 as its repeat count');
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
this.callback = callback;
|
|
47
|
+
this.count = count;
|
|
48
|
+
this.time = time;
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
private static run(timed: Timed<(index: number | undefined) => void>): void {
|
|
52
|
+
timed.running = true;
|
|
53
|
+
|
|
54
|
+
let count = 0;
|
|
55
|
+
|
|
56
|
+
let start: DOMHighResTimeStamp | undefined;
|
|
57
|
+
|
|
58
|
+
function step(timestamp: DOMHighResTimeStamp): void {
|
|
59
|
+
if (!timed.running) {
|
|
60
|
+
return;
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
start ??= timestamp;
|
|
64
|
+
|
|
65
|
+
const elapsed = timestamp - start;
|
|
66
|
+
|
|
67
|
+
const elapsedMinimum = elapsed - milliseconds;
|
|
68
|
+
const elapsedMaximum = elapsed + milliseconds;
|
|
69
|
+
|
|
70
|
+
if (elapsedMinimum < timed.time && timed.time < elapsedMaximum) {
|
|
71
|
+
if (timed.running) {
|
|
72
|
+
timed.callback(timed instanceof Repeated ? count : undefined);
|
|
73
|
+
}
|
|
74
|
+
|
|
75
|
+
count += 1;
|
|
76
|
+
|
|
77
|
+
if ((timed instanceof Repeated) && count < timed.count) {
|
|
78
|
+
start = undefined;
|
|
79
|
+
} else {
|
|
80
|
+
timed.stop();
|
|
81
|
+
|
|
82
|
+
return;
|
|
83
|
+
}
|
|
84
|
+
}
|
|
85
|
+
|
|
86
|
+
timed.frame = request(step);
|
|
87
|
+
}
|
|
88
|
+
|
|
89
|
+
timed.frame = request(step);
|
|
90
|
+
}
|
|
91
|
+
|
|
92
|
+
/**
|
|
93
|
+
* Restart timer
|
|
94
|
+
*/
|
|
95
|
+
restart(): this {
|
|
96
|
+
this.stop();
|
|
97
|
+
|
|
98
|
+
Timed.run(this as never);
|
|
99
|
+
|
|
100
|
+
return this;
|
|
101
|
+
}
|
|
102
|
+
|
|
103
|
+
/**
|
|
104
|
+
* Start timer
|
|
105
|
+
*/
|
|
106
|
+
start(): this {
|
|
107
|
+
if (this.running) {
|
|
108
|
+
return this;
|
|
109
|
+
}
|
|
110
|
+
|
|
111
|
+
Timed.run(this as never);
|
|
112
|
+
|
|
113
|
+
return this;
|
|
114
|
+
}
|
|
115
|
+
|
|
116
|
+
/**
|
|
117
|
+
* Stop timer
|
|
118
|
+
*/
|
|
119
|
+
stop(): this {
|
|
120
|
+
this.running = false;
|
|
121
|
+
|
|
122
|
+
if (typeof this.frame === 'undefined') {
|
|
123
|
+
return this;
|
|
124
|
+
}
|
|
125
|
+
|
|
126
|
+
cancel(this.frame);
|
|
127
|
+
|
|
128
|
+
this.frame = undefined;
|
|
129
|
+
|
|
130
|
+
return this;
|
|
131
|
+
}
|
|
132
|
+
}
|
|
133
|
+
|
|
134
|
+
/**
|
|
135
|
+
* A repeated timer
|
|
136
|
+
*/
|
|
137
|
+
export class Repeated extends Timed<RepeatedCallback> {}
|
|
138
|
+
|
|
139
|
+
/**
|
|
140
|
+
* A waited timer
|
|
141
|
+
*/
|
|
142
|
+
export class Waited extends Timed<WaitedCallback> {
|
|
143
|
+
constructor(callback: WaitedCallback, time: number) {
|
|
144
|
+
super(callback, time, 1);
|
|
145
|
+
}
|
|
146
|
+
}
|
|
147
|
+
|
|
148
|
+
/**
|
|
149
|
+
* Create and start a new repeated timer
|
|
150
|
+
*/
|
|
151
|
+
export function repeat(callback: RepeatedCallback, time: number, count: number): Repeated {
|
|
152
|
+
return (new Repeated(callback, time, count)).start();
|
|
153
|
+
}
|
|
154
|
+
|
|
155
|
+
/**
|
|
156
|
+
* Create and start a new waited timer
|
|
157
|
+
*/
|
|
158
|
+
export function wait(callback: WaitedCallback, time: number): Waited {
|
|
159
|
+
return (new Waited(callback, time)).start();
|
|
160
|
+
}
|