ziko 0.38.1 → 0.40.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/ziko.cjs +962 -1360
- package/dist/ziko.js +962 -1360
- package/dist/ziko.min.js +2 -2
- package/dist/ziko.mjs +902 -1342
- package/package.json +1 -1
- package/src/data/index.js +2 -2
- package/src/data/string/checkers.js +27 -0
- package/src/data/string/converters.js +24 -0
- package/src/data/string/index.js +2 -1
- package/src/data/string-dep/index.js +1 -0
- package/src/events/types/clipboard.d.ts +2 -2
- package/src/events/types/focus.d.ts +2 -2
- package/src/events/types/pointer.d.ts +2 -2
- package/src/hooks/use-state.js +11 -8
- package/src/index.js +2 -1
- package/src/math/index.js +17 -17
- package/src/reactivity/hooks/UI/index.js +1 -1
- package/src/reactivity/hooks/UI/useRoot.js +3 -3
- package/src/time/animation/index.js +88 -70
- package/src/time/clocks/clock.js +62 -0
- package/src/time/clocks/index.js +3 -0
- package/src/time/clocks/scheduler.js +69 -0
- package/src/time/clocks/tick.js +34 -0
- package/src/time/converters/index.js +1 -0
- package/src/time/delay/index.js +2 -0
- package/src/time/delay/sleep.js +3 -0
- package/src/time/delay/timeout.js +15 -0
- package/src/time/ease/index.js +77 -0
- package/src/time/index.js +6 -9
- package/src/time/loop/index.js +67 -51
- package/src/time/utils/index.js +2 -2
- package/src/ui/__methods__/attrs.js +49 -0
- package/src/ui/__methods__/index.js +2 -1
- package/src/ui/__methods__/style.js +34 -0
- package/src/ui/__utils__/index.js +2 -2
- package/src/ui/constructors/{ZikoUIElement.js → UIElement.js} +23 -64
- package/src/ui/constructors/{ZikoUINode.js → UINode.js} +2 -2
- package/src/ui/constructors/style/index.js +2 -1
- package/src/ui/flex/index.js +8 -8
- package/src/ui/graphics/canvas.js +2 -2
- package/src/ui/graphics/svg.js +2 -2
- package/src/ui/grid/index.js +4 -4
- package/src/ui/index.js +2 -2
- package/src/ui/suspense/index.js +3 -3
- package/src/ui/tags/index.d.ts.txt +125 -125
- package/src/ui/tags/index.js +12 -16
- package/src/ui/text/index.js +2 -2
- package/src/ui/wrapper/index.js +3 -3
- package/src/time/utils/ease.js +0 -144
- /package/src/data/{string → string-dep}/patterns.js +0 -0
- /package/src/data/{string → string-dep}/string.js +0 -0
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "ziko",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.40.0",
|
|
4
4
|
"description": "A versatile JavaScript library offering a rich set of Hyperscript Based UI components, advanced mathematical utilities, interactivity ,animations, client side routing and more ...",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"front-end",
|
package/src/data/index.js
CHANGED
|
@@ -1,12 +1,12 @@
|
|
|
1
1
|
export * from "./api"
|
|
2
2
|
export * from "./converter"
|
|
3
3
|
export * from "./parser"
|
|
4
|
-
export * from "./string"
|
|
4
|
+
export * from "./string-dep"
|
|
5
5
|
|
|
6
6
|
import * as Api from "./api"
|
|
7
7
|
import * as Converter from "./converter"
|
|
8
8
|
import * as Parser from "./parser"
|
|
9
|
-
import * as String from "./string"
|
|
9
|
+
import * as String from "./string-dep"
|
|
10
10
|
|
|
11
11
|
const Data = {
|
|
12
12
|
...Api,
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
export const is_camelcase = (text = '') =>{
|
|
2
|
+
if (text.length === 0) return false;
|
|
3
|
+
const camelCasePattern = /^[a-z][a-zA-Z0-9]*$/;
|
|
4
|
+
return camelCasePattern.test(text);
|
|
5
|
+
}
|
|
6
|
+
export const is_hyphencase = (text = '') => text.split('-').length > 0;
|
|
7
|
+
export const is_snakeCase = (text = '') => text.split('_').length > 0;
|
|
8
|
+
export const is_pascalcalse = (text = '') => {
|
|
9
|
+
if (text.length === 0) return false;
|
|
10
|
+
const PascalCasePattern = /^[A-Z][a-zA-Z0-9]*$/;
|
|
11
|
+
return PascalCasePattern.test(text);
|
|
12
|
+
}
|
|
13
|
+
|
|
14
|
+
export const is_palindrome = text =>{
|
|
15
|
+
const str = text.toLocaleLowerCase();
|
|
16
|
+
let l = str.length,i;
|
|
17
|
+
for(i=0;i<l/2;i++)if(str[i]!=str[l-i-1])return false;
|
|
18
|
+
return true;
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
export const is_anagram = (word, words) =>{
|
|
22
|
+
word=word.split("").sort();
|
|
23
|
+
words=words.split("").sort();
|
|
24
|
+
return JSON.stringify(word)===JSON.stringify(words);
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
export const is_isogram = (text = '') => [...new Set(text.toLowerCase())].length === text.length;
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
export const camel2hyphencase = (text = '') => text.replace(/[A-Z]/g, match => '-' + match.toLowerCase());
|
|
2
|
+
export const camel2snakecase = (text = '') => text.replace(/[A-Z]/g, match => '_' + match.toLowerCase());
|
|
3
|
+
export const camel2pascalcase = (text = '') => text.charAt(0).toUpperCase() + text.slice(1);
|
|
4
|
+
export const camel2constantcase = (text = '') => text.replace(/[A-Z]/g, match => '_' + match).toUpperCase();
|
|
5
|
+
|
|
6
|
+
export const pascal2snakecase = (text = '') => text.replace(/([A-Z])/g, (match, offset) => offset ? '_' + match.toLowerCase() : match.toLowerCase());
|
|
7
|
+
export const pascal2hyphencase = (text = '') => text.replace(/([A-Z])/g, (match, offset) => offset ? '-' + match.toLowerCase() : match.toLowerCase());
|
|
8
|
+
export const pascal2camelcase = (text = '') => text.charAt(0).toLowerCase() + text.slice(1);
|
|
9
|
+
export const pascal2constantcase = (text = '') => text.replace(/([A-Z])/g, (match, offset) => offset ? '_' + match : match).toUpperCase();
|
|
10
|
+
|
|
11
|
+
export const snake2camelcase = (text = '') => text.replace(/(_\w)/g, match => match[1].toUpperCase());
|
|
12
|
+
export const snake2hyphencase = (text = '') => text.replace(/_/g, "-");
|
|
13
|
+
export const snake2pascalcase = (text = '') => text.split('_').map(word => word.charAt(0).toUpperCase() + word.slice(1)).join('');
|
|
14
|
+
export const snake2constantcase = (text = '') => text.toUpperCase();
|
|
15
|
+
|
|
16
|
+
export const hyphen2camelcase = (text = '') => text.replace(/-([a-z])/g, match => match[1].toUpperCase());
|
|
17
|
+
export const hyphen2snakecase = (text = '') => text.replace(/-/g, '_');
|
|
18
|
+
export const hyphen2pascalcase = (text = '') => text.split('-').map(word => word.charAt(0).toUpperCase() + word.slice(1)).join('');
|
|
19
|
+
export const hyphen2constantcase = (text = '') => text.replace(/-/g, '_').toUpperCase();
|
|
20
|
+
|
|
21
|
+
export const constant2camelcase = (text = '') => text.toLowerCase().replace(/_([a-z])/g, match => match[1].toUpperCase());
|
|
22
|
+
export const constant2snakecase = (text = '') => text.toLowerCase();
|
|
23
|
+
export const constant2pascalcase = (text = '') => text.toLowerCase().split('_').map(word => word.charAt(0).toUpperCase() + word.slice(1)).join('');
|
|
24
|
+
export const constant2hyphencase = (text = '') => text.toLowerCase().replace(/_/g, '-');
|
package/src/data/string/index.js
CHANGED
|
@@ -1 +1,2 @@
|
|
|
1
|
-
export * from
|
|
1
|
+
export * from './converters.js';
|
|
2
|
+
export * from './checkers.js'
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
// export * from "./string.js";
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { __ZikoEvent__ } from "../__ZikoEvent__.js";
|
|
2
2
|
import type { Callback, ClipboardEventKeys } from './__Shared__.js';
|
|
3
|
-
import {
|
|
3
|
+
import { UIElement } from "../../ui/index.js";
|
|
4
4
|
|
|
5
5
|
declare class ZikoEventClipboard extends __ZikoEvent__ {
|
|
6
6
|
constructor(target: any, customizer?: Function);
|
|
@@ -12,7 +12,7 @@ declare class ZikoEventClipboard extends __ZikoEvent__ {
|
|
|
12
12
|
|
|
13
13
|
}
|
|
14
14
|
|
|
15
|
-
declare const bindClipboardEvent: (target:
|
|
15
|
+
declare const bindClipboardEvent: (target: UIElement, customizer?: Function) => ZikoEventClipboard;
|
|
16
16
|
|
|
17
17
|
export {
|
|
18
18
|
ZikoEventClipboard,
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { __ZikoEvent__ } from "../__ZikoEvent__.js";
|
|
2
2
|
import type { Callback } from './__Shared__.js';
|
|
3
|
-
import {
|
|
3
|
+
import { UIElement } from "../../ui/index.js";
|
|
4
4
|
|
|
5
5
|
declare class ZikoEventFocus extends __ZikoEvent__ {
|
|
6
6
|
constructor(target: any, customizer?: Function);
|
|
@@ -11,7 +11,7 @@ declare class ZikoEventFocus extends __ZikoEvent__ {
|
|
|
11
11
|
|
|
12
12
|
}
|
|
13
13
|
|
|
14
|
-
declare const bindFocusEvent: (target:
|
|
14
|
+
declare const bindFocusEvent: (target: UIElement, customizer?: Function) => ZikoEventFocus;
|
|
15
15
|
|
|
16
16
|
export {
|
|
17
17
|
ZikoEventFocus,
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { __ZikoEvent__ } from "../__ZikoEvent__.js";
|
|
2
2
|
import type { EventMethodesBinder, Callback, PointerEventKeys } from './__Shared__.js';
|
|
3
|
-
import {
|
|
3
|
+
import { UIElement } from "../../ui/index.js";
|
|
4
4
|
|
|
5
5
|
type PointerEventMethodesBinder = EventMethodesBinder<PointerEventKeys, ZikoEventPointer>;
|
|
6
6
|
|
|
@@ -37,7 +37,7 @@ declare class ZikoEventPointer extends __ZikoEvent__ implements PointerEventMeth
|
|
|
37
37
|
|
|
38
38
|
}
|
|
39
39
|
|
|
40
|
-
declare const bindPointerEvent: (target:
|
|
40
|
+
declare const bindPointerEvent: (target: UIElement, customizer?: Function) => ZikoEventPointer;
|
|
41
41
|
|
|
42
42
|
export {
|
|
43
43
|
ZikoEventPointer,
|
package/src/hooks/use-state.js
CHANGED
|
@@ -7,17 +7,20 @@ export function useState(initialValue) {
|
|
|
7
7
|
return {
|
|
8
8
|
value,
|
|
9
9
|
isStateGetter: () => true,
|
|
10
|
-
_subscribe: (
|
|
10
|
+
_subscribe: (
|
|
11
|
+
fn,
|
|
12
|
+
// UIElement
|
|
13
|
+
) => {
|
|
11
14
|
subscribers.add(fn);
|
|
12
15
|
|
|
13
|
-
const observer = new MutationObserver(() => {
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
});
|
|
16
|
+
// const observer = new MutationObserver(() => {
|
|
17
|
+
// if (!document.body.contains(UIElement.element)) {
|
|
18
|
+
// subscribers.delete(fn);
|
|
19
|
+
// observer.disconnect();
|
|
20
|
+
// }
|
|
21
|
+
// });
|
|
19
22
|
|
|
20
|
-
observer.observe(document.body, { childList: true, subtree: true });
|
|
23
|
+
// observer.observe(document.body, { childList: true, subtree: true });
|
|
21
24
|
},
|
|
22
25
|
};
|
|
23
26
|
}
|
package/src/index.js
CHANGED
|
@@ -4,9 +4,10 @@ export * from "./time/index.js";
|
|
|
4
4
|
export * from "./data/index.js";
|
|
5
5
|
export * from "./reactivity/index.js"
|
|
6
6
|
export * from "./app/index.js";
|
|
7
|
+
export * from './hooks/index.js';
|
|
8
|
+
export * from './use/index.js'
|
|
7
9
|
|
|
8
10
|
export * from "./events/index.js";
|
|
9
|
-
export * from "./use/index.js";
|
|
10
11
|
|
|
11
12
|
if(globalThis?.document){
|
|
12
13
|
document?.addEventListener("DOMContentLoaded", __Ziko__.__Config__.init());
|
package/src/math/index.js
CHANGED
|
@@ -1,19 +1,19 @@
|
|
|
1
|
-
import * as __Const__ from "./const.js"
|
|
2
|
-
import * as __Functions__ from "./functions/index.js"
|
|
3
|
-
import * as __Random__ from "./random"
|
|
4
|
-
import * as __Complex__ from "./complex"
|
|
5
|
-
import * as __Matrix__ from "./matrix"
|
|
6
|
-
import * as __Discrect__ from "./discret"
|
|
7
|
-
import * as __Utils__ from "./utils"
|
|
8
|
-
const Math = {
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
}
|
|
1
|
+
// import * as __Const__ from "./const.js"
|
|
2
|
+
// import * as __Functions__ from "./functions/index.js"
|
|
3
|
+
// import * as __Random__ from "./random"
|
|
4
|
+
// import * as __Complex__ from "./complex"
|
|
5
|
+
// import * as __Matrix__ from "./matrix"
|
|
6
|
+
// import * as __Discrect__ from "./discret"
|
|
7
|
+
// import * as __Utils__ from "./utils"
|
|
8
|
+
// const Math = {
|
|
9
|
+
// ...__Const__,
|
|
10
|
+
// ...__Functions__,
|
|
11
|
+
// ...__Complex__,
|
|
12
|
+
// ...__Matrix__,
|
|
13
|
+
// ...__Random__,
|
|
14
|
+
// ...__Utils__,
|
|
15
|
+
// ...__Discrect__,
|
|
16
|
+
// }
|
|
17
17
|
export * from "./const.js"
|
|
18
18
|
export * from "./functions/index.js"
|
|
19
19
|
export * from "./complex"
|
|
@@ -22,5 +22,5 @@ export * from "./discret"
|
|
|
22
22
|
export * from "./random"
|
|
23
23
|
export * from "./utils"
|
|
24
24
|
export * from "./statistics"
|
|
25
|
-
export default Math;
|
|
25
|
+
// export default Math;
|
|
26
26
|
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { camel2hyphencase } from "../../../data/converter/string/index.js";
|
|
2
2
|
class ZikoUseRoot{
|
|
3
3
|
constructor(props){
|
|
4
4
|
this.props={};
|
|
@@ -15,7 +15,7 @@ class ZikoUseRoot{
|
|
|
15
15
|
return this;
|
|
16
16
|
}
|
|
17
17
|
#setOneProp(prop, value){
|
|
18
|
-
const CssProp = `--${
|
|
18
|
+
const CssProp = `--${camel2hyphencase(prop)}`
|
|
19
19
|
document.documentElement.style.setProperty(CssProp,value);
|
|
20
20
|
Object.assign(this.props, {[prop]: `var(${CssProp})`})
|
|
21
21
|
Object.assign(this, {[prop] : `var(${CssProp})`})
|
|
@@ -23,7 +23,7 @@ class ZikoUseRoot{
|
|
|
23
23
|
}
|
|
24
24
|
|
|
25
25
|
const useRootValue=CssVar=>{
|
|
26
|
-
if(!CssVar.startsWith("--")) CssVar = `--${
|
|
26
|
+
if(!CssVar.startsWith("--")) CssVar = `--${camel2hyphencase(CssVar)}`
|
|
27
27
|
return `var(${CssVar})`
|
|
28
28
|
}
|
|
29
29
|
// const useRootStaticValue=CssVar=>{
|
|
@@ -1,76 +1,94 @@
|
|
|
1
|
-
import {
|
|
2
|
-
import { map } from "../../math/utils"
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
this.ty=this.cache.ease(this.tx);
|
|
26
|
-
this.callback(this)
|
|
27
|
-
if(this.t>=this.cache.duration){
|
|
28
|
-
clearInterval(this.cache.AnimationId);
|
|
29
|
-
this.cache.isRunning=false;
|
|
30
|
-
}
|
|
31
|
-
}
|
|
32
|
-
reset(restart=true){
|
|
33
|
-
this.t=0
|
|
34
|
-
this.tx=0;
|
|
35
|
-
this.ty=0;
|
|
36
|
-
this.i=0;
|
|
37
|
-
if(restart)this.start();
|
|
38
|
-
return this;
|
|
39
|
-
}
|
|
40
|
-
#animate(reset=true){
|
|
41
|
-
if(!this.cache.isRunning){
|
|
42
|
-
if(reset)this.reset(false);
|
|
43
|
-
this.cache.isRunning=true;
|
|
44
|
-
this.cache.startTime = Date.now();
|
|
45
|
-
this.cache.AnimationId=setInterval(this.#animation_handler.bind(this),this.cache.step);
|
|
46
|
-
}
|
|
47
|
-
return this;
|
|
48
|
-
}
|
|
49
|
-
start(){
|
|
50
|
-
this.#animate(true);
|
|
51
|
-
return this;
|
|
1
|
+
import { Linear } from "../ease/index.js";
|
|
2
|
+
import { map } from "../../math/utils/index.js";
|
|
3
|
+
|
|
4
|
+
class TimeAnimation {
|
|
5
|
+
constructor(callback, { ease = Linear, step = 50, t0 = 0, start = true, duration = 3000 } = {}) {
|
|
6
|
+
this.callback = callback;
|
|
7
|
+
this.state = {
|
|
8
|
+
isRunning: false,
|
|
9
|
+
animationId: null,
|
|
10
|
+
startTime: null,
|
|
11
|
+
ease,
|
|
12
|
+
step,
|
|
13
|
+
// interval: [t0, t1],
|
|
14
|
+
autoStart: start,
|
|
15
|
+
duration
|
|
16
|
+
};
|
|
17
|
+
|
|
18
|
+
this.t = 0; // elapsed time
|
|
19
|
+
this.tx = 0; // normalized [0,1]
|
|
20
|
+
this.ty = 0; // eased value
|
|
21
|
+
this.i = 0; // frame index
|
|
22
|
+
|
|
23
|
+
if (this.state.autoStart) {
|
|
24
|
+
this.start();
|
|
52
25
|
}
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
// ---- private loop handler ----
|
|
29
|
+
#tick = () => {
|
|
30
|
+
this.t += this.state.step;
|
|
31
|
+
this.i++;
|
|
32
|
+
|
|
33
|
+
this.tx = map(this.t, 0, this.state.duration, 0, 1);
|
|
34
|
+
this.ty = this.state.ease(this.tx);
|
|
35
|
+
|
|
36
|
+
this.callback(this);
|
|
37
|
+
|
|
38
|
+
if (this.t >= this.state.duration) {
|
|
39
|
+
clearInterval(this.state.animationId);
|
|
40
|
+
this.state.isRunning = false;
|
|
59
41
|
}
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
42
|
+
};
|
|
43
|
+
|
|
44
|
+
// ---- core runner ----
|
|
45
|
+
#run(reset = true) {
|
|
46
|
+
if (!this.state.isRunning) {
|
|
47
|
+
if (reset) this.reset(false);
|
|
48
|
+
|
|
49
|
+
this.state.isRunning = true;
|
|
50
|
+
this.state.startTime = Date.now();
|
|
51
|
+
this.state.animationId = setInterval(this.#tick, this.state.step);
|
|
63
52
|
}
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
53
|
+
return this;
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
// ---- lifecycle methods ----
|
|
57
|
+
start() {
|
|
58
|
+
return this.#run(true);
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
pause() {
|
|
62
|
+
if (this.state.isRunning) {
|
|
63
|
+
clearInterval(this.state.animationId);
|
|
64
|
+
this.state.isRunning = false;
|
|
68
65
|
}
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
66
|
+
return this;
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
resume() {
|
|
70
|
+
return this.#run(false);
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
stop() {
|
|
74
|
+
this.pause();
|
|
75
|
+
this.reset(false);
|
|
76
|
+
return this;
|
|
77
|
+
}
|
|
78
|
+
|
|
79
|
+
reset(restart = true) {
|
|
80
|
+
this.t = 0;
|
|
81
|
+
this.tx = 0;
|
|
82
|
+
this.ty = 0;
|
|
83
|
+
this.i = 0;
|
|
84
|
+
|
|
85
|
+
if (restart) this.start();
|
|
86
|
+
return this;
|
|
87
|
+
}
|
|
73
88
|
}
|
|
74
89
|
|
|
75
|
-
|
|
76
|
-
|
|
90
|
+
// Hook-style factory
|
|
91
|
+
const animation = (callback, {ease, t0, t1, start, duration} = {}) =>
|
|
92
|
+
new TimeAnimation(callback, {ease, t0, t1, start, duration});
|
|
93
|
+
|
|
94
|
+
export { TimeAnimation, animation };
|
|
@@ -0,0 +1,62 @@
|
|
|
1
|
+
import { Tick } from "./tick.js";
|
|
2
|
+
|
|
3
|
+
class Clock extends Tick {
|
|
4
|
+
constructor(tickMs = 1000 / 60) {
|
|
5
|
+
super(tickMs, () => this._tick());
|
|
6
|
+
this.elapsed = 0;
|
|
7
|
+
this._lastTime = performance.now();
|
|
8
|
+
this._callbacks = new Set();
|
|
9
|
+
}
|
|
10
|
+
|
|
11
|
+
_tick() {
|
|
12
|
+
const now = performance.now();
|
|
13
|
+
const delta = now - this._lastTime;
|
|
14
|
+
this.elapsed += delta;
|
|
15
|
+
this._lastTime = now;
|
|
16
|
+
|
|
17
|
+
for (const cb of this._callbacks) {
|
|
18
|
+
cb({ elapsed: this.elapsed, delta });
|
|
19
|
+
}
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
onTick(cb) {
|
|
23
|
+
this._callbacks.add(cb);
|
|
24
|
+
return () => this._callbacks.delete(cb);
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
reset() {
|
|
28
|
+
this.elapsed = 0;
|
|
29
|
+
this._lastTime = performance.now();
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
pause() {
|
|
33
|
+
super.stop();
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
resume() {
|
|
37
|
+
this._lastTime = performance.now();
|
|
38
|
+
super.start();
|
|
39
|
+
}
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
const clock = (tickMs) => new Clock(tickMs)
|
|
43
|
+
export{
|
|
44
|
+
Clock,
|
|
45
|
+
clock
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
|
|
49
|
+
/*
|
|
50
|
+
|
|
51
|
+
const clock = new Clock(200);
|
|
52
|
+
|
|
53
|
+
clock.onTick(({ elapsed, delta }) => {
|
|
54
|
+
console.log(`Elapsed: ${elapsed.toFixed(0)}ms, Delta: ${delta.toFixed(0)}ms`);
|
|
55
|
+
});
|
|
56
|
+
|
|
57
|
+
clock.start();
|
|
58
|
+
|
|
59
|
+
setTimeout(() => clock.pause(), 1000);
|
|
60
|
+
setTimeout(() => clock.resume(), 2000);
|
|
61
|
+
|
|
62
|
+
*/
|
|
@@ -0,0 +1,69 @@
|
|
|
1
|
+
export class TimeScheduler {
|
|
2
|
+
constructor(tasks = [], { repeat = 1, loop = false } = {}) {
|
|
3
|
+
this.tasks = tasks;
|
|
4
|
+
this.repeat = repeat;
|
|
5
|
+
this.loop = loop;
|
|
6
|
+
|
|
7
|
+
this.stopped = false;
|
|
8
|
+
this.running = false;
|
|
9
|
+
|
|
10
|
+
// lifecycle hooks
|
|
11
|
+
this.onStart = null;
|
|
12
|
+
this.onTask = null;
|
|
13
|
+
this.onEnd = null;
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
async run() {
|
|
17
|
+
if (this.running) return;
|
|
18
|
+
this.running = true;
|
|
19
|
+
this.stopped = false;
|
|
20
|
+
|
|
21
|
+
if (this.onStart) this.onStart();
|
|
22
|
+
|
|
23
|
+
let repeatCount = this.repeat;
|
|
24
|
+
|
|
25
|
+
do {
|
|
26
|
+
for (const task of this.tasks) {
|
|
27
|
+
if (this.stopped) return;
|
|
28
|
+
|
|
29
|
+
if (Array.isArray(task)) {
|
|
30
|
+
// Parallel tasks
|
|
31
|
+
await Promise.all(
|
|
32
|
+
task.map(({ fn, delay = 0 }) =>
|
|
33
|
+
new Promise(async (resolve) => {
|
|
34
|
+
if (delay > 0) await new Promise(r => setTimeout(r, delay));
|
|
35
|
+
if (this.onTask) this.onTask(fn);
|
|
36
|
+
await fn();
|
|
37
|
+
resolve();
|
|
38
|
+
})
|
|
39
|
+
)
|
|
40
|
+
);
|
|
41
|
+
} else {
|
|
42
|
+
// Single task
|
|
43
|
+
const { fn, delay = 0 } = task;
|
|
44
|
+
if (delay > 0) await new Promise(r => setTimeout(r, delay));
|
|
45
|
+
if (this.onTask) this.onTask(fn);
|
|
46
|
+
await fn();
|
|
47
|
+
}
|
|
48
|
+
}
|
|
49
|
+
} while (this.loop && !this.stopped && (repeatCount === Infinity || repeatCount-- > 1));
|
|
50
|
+
|
|
51
|
+
if (!this.stopped && this.onEnd) this.onEnd();
|
|
52
|
+
this.running = false;
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
stop() {
|
|
56
|
+
this.stopped = true;
|
|
57
|
+
this.running = false;
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
addTask(task) {
|
|
61
|
+
this.tasks.push(task);
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
clearTasks() {
|
|
65
|
+
this.tasks = [];
|
|
66
|
+
}
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
export const Scheduler = (tasks, { repeat = null} = {}) => new TimeScheduler(tasks, { repeat})
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
class Tick {
|
|
2
|
+
constructor(ms, fn) {
|
|
3
|
+
this.ms = ms;
|
|
4
|
+
this.fn = fn;
|
|
5
|
+
this.id = null;
|
|
6
|
+
this.running = false;
|
|
7
|
+
}
|
|
8
|
+
|
|
9
|
+
start() {
|
|
10
|
+
if (!this.running) {
|
|
11
|
+
this.running = true;
|
|
12
|
+
this.id = setInterval(this.fn, this.ms);
|
|
13
|
+
}
|
|
14
|
+
return this;
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
stop() {
|
|
18
|
+
if (this.running) {
|
|
19
|
+
this.running = false;
|
|
20
|
+
clearInterval(this.id);
|
|
21
|
+
this.id = null;
|
|
22
|
+
}
|
|
23
|
+
return this;
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
isRunning() {
|
|
27
|
+
return this.running;
|
|
28
|
+
}
|
|
29
|
+
}
|
|
30
|
+
const tick = (ms, fn) => new Tick(ms, fn);
|
|
31
|
+
export{
|
|
32
|
+
Tick,
|
|
33
|
+
tick
|
|
34
|
+
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export const step_fps = (step_or_fps) => 1000 / step_or_fps;
|