@w-lfpup/wctk 0.1.1 → 0.2.2
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/.github/workflows/browsers.macos.json +51 -0
- package/.github/workflows/browsers.ubuntu.json +37 -0
- package/.github/workflows/builds.yml +13 -4
- package/README.md +40 -13
- package/dist/events.d.ts +6 -7
- package/dist/events.js +8 -22
- package/dist/microtask.d.ts +4 -6
- package/dist/microtask.js +9 -13
- package/dist/mod.d.ts +0 -2
- package/dist/mod.js +0 -2
- package/dist/query_selector.d.ts +2 -5
- package/dist/query_selector.js +16 -14
- package/dist/subscription.d.ts +0 -1
- package/dist/subscription.js +6 -14
- package/dist/wc.d.ts +4 -4
- package/dist/wc.js +5 -7
- package/docs/events.md +15 -22
- package/docs/microtask.md +3 -6
- package/docs/query_selector.md +2 -5
- package/docs/wc.md +3 -3
- package/examples/counter/index.html +1 -1
- package/examples/counter/mod.js +14 -18
- package/examples/counter/mod.ts +16 -18
- package/examples/form_associated/mod.js +1 -3
- package/examples/form_associated/mod.ts +0 -1
- package/examples/form_associated/text_input.js +3 -8
- package/examples/form_associated/text_input.ts +4 -4
- package/examples/stopwatch/index.html +7 -4
- package/examples/stopwatch/mod.js +8 -18
- package/examples/stopwatch/mod.ts +6 -20
- package/examples/stopwatch/stopwatch.js +38 -24
- package/examples/stopwatch/stopwatch.ts +46 -25
- package/examples/tsconfig.json +1 -0
- package/jr.json +25 -0
- package/package.json +10 -5
- package/src/events.ts +20 -38
- package/src/microtask.ts +13 -22
- package/src/mod.ts +0 -2
- package/src/query_selector.ts +18 -27
- package/src/wc.ts +11 -11
- package/tests/dist/events.tests.js +60 -0
- package/tests/dist/microtask.tests.js +38 -0
- package/tests/dist/mod.js +10 -0
- package/tests/dist/query_selector.tests.js +43 -0
- package/tests/dist/wc.tests.js +41 -0
- package/tests/src/events.tests.ts +73 -0
- package/tests/src/microtask.tests.ts +54 -0
- package/tests/src/mod.ts +11 -0
- package/tests/src/query_selector.tests.ts +46 -0
- package/tests/src/wc.tests.ts +52 -0
- package/tests/tsconfig.json +8 -0
- package/dist/bind.d.ts +0 -7
- package/dist/bind.js +0 -14
- package/docs/bind.md +0 -26
- package/docs/subscription.md +0 -85
- package/src/bind.ts +0 -22
- package/src/subscription.ts +0 -47
package/examples/counter/mod.js
CHANGED
|
@@ -1,41 +1,37 @@
|
|
|
1
|
-
/*
|
|
2
|
-
Custom Element with state and interactivity.
|
|
3
|
-
*/
|
|
4
1
|
import { Wc, Events } from "wctk";
|
|
5
2
|
class Counter extends HTMLElement {
|
|
6
3
|
#wc = new Wc({ host: this });
|
|
7
4
|
#ev = new Events({
|
|
8
|
-
host: this,
|
|
9
|
-
target: this.#wc.shadowRoot,
|
|
10
5
|
connected: true,
|
|
11
|
-
|
|
12
|
-
|
|
6
|
+
target: this.#wc.shadowRoot,
|
|
7
|
+
listeners: {
|
|
8
|
+
click: this.#clickHandler.bind(this),
|
|
13
9
|
},
|
|
14
10
|
});
|
|
15
11
|
#state = getStateFromDOM(this.#wc.shadowRoot);
|
|
16
|
-
#
|
|
17
|
-
if (!this.#state)
|
|
18
|
-
return;
|
|
12
|
+
#clickHandler(e) {
|
|
19
13
|
let increment = getIncrement(e);
|
|
20
14
|
if (increment) {
|
|
21
15
|
this.#state.count += increment;
|
|
22
|
-
|
|
16
|
+
let el = this.#state.el;
|
|
17
|
+
if (el)
|
|
18
|
+
el.textContent = this.#state.count.toString();
|
|
23
19
|
}
|
|
24
20
|
}
|
|
25
21
|
}
|
|
26
22
|
function getStateFromDOM(shadowRoot) {
|
|
27
23
|
let slot = shadowRoot.querySelector("slot");
|
|
24
|
+
let el;
|
|
28
25
|
if (slot)
|
|
29
|
-
for (let
|
|
30
|
-
if (
|
|
31
|
-
|
|
32
|
-
}
|
|
26
|
+
for (let slotted of slot.assignedNodes()) {
|
|
27
|
+
if (slotted instanceof HTMLSpanElement)
|
|
28
|
+
el = slotted;
|
|
33
29
|
}
|
|
30
|
+
return { el, count: parseInt(el?.textContent ?? "0") };
|
|
34
31
|
}
|
|
35
32
|
function getIncrement(e) {
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
return target.hasAttribute("increase") ? 1 : -1;
|
|
33
|
+
if (e.target instanceof HTMLButtonElement) {
|
|
34
|
+
return e.target.hasAttribute("increase") ? 1 : -1;
|
|
39
35
|
}
|
|
40
36
|
}
|
|
41
37
|
customElements.define("counter-wc", Counter);
|
package/examples/counter/mod.ts
CHANGED
|
@@ -5,7 +5,7 @@
|
|
|
5
5
|
import { Wc, Events } from "wctk";
|
|
6
6
|
|
|
7
7
|
interface State {
|
|
8
|
-
el: HTMLSpanElement;
|
|
8
|
+
el: HTMLSpanElement | undefined;
|
|
9
9
|
count: number;
|
|
10
10
|
}
|
|
11
11
|
|
|
@@ -13,41 +13,39 @@ class Counter extends HTMLElement {
|
|
|
13
13
|
#wc = new Wc({ host: this });
|
|
14
14
|
|
|
15
15
|
#ev = new Events({
|
|
16
|
-
host: this,
|
|
17
|
-
target: this.#wc.shadowRoot,
|
|
18
16
|
connected: true,
|
|
19
|
-
|
|
20
|
-
|
|
17
|
+
target: this.#wc.shadowRoot,
|
|
18
|
+
listeners: {
|
|
19
|
+
click: this.#clickHandler.bind(this),
|
|
21
20
|
},
|
|
22
21
|
});
|
|
23
22
|
|
|
24
|
-
#state
|
|
25
|
-
|
|
26
|
-
#onClick(e: PointerEvent) {
|
|
27
|
-
if (!this.#state) return;
|
|
23
|
+
#state: State = getStateFromDOM(this.#wc.shadowRoot);
|
|
28
24
|
|
|
25
|
+
#clickHandler(e: PointerEvent) {
|
|
29
26
|
let increment = getIncrement(e);
|
|
30
27
|
if (increment) {
|
|
31
28
|
this.#state.count += increment;
|
|
32
|
-
|
|
29
|
+
let el = this.#state.el;
|
|
30
|
+
if (el) el.textContent = this.#state.count.toString();
|
|
33
31
|
}
|
|
34
32
|
}
|
|
35
33
|
}
|
|
36
34
|
|
|
37
|
-
function getStateFromDOM(shadowRoot: ShadowRoot): State
|
|
35
|
+
function getStateFromDOM(shadowRoot: ShadowRoot): State {
|
|
38
36
|
let slot = shadowRoot.querySelector("slot");
|
|
37
|
+
let el: HTMLSpanElement | undefined;
|
|
39
38
|
if (slot)
|
|
40
|
-
for (let
|
|
41
|
-
if (
|
|
42
|
-
return { el, count: parseInt(el.textContent ?? "0") };
|
|
43
|
-
}
|
|
39
|
+
for (let slotted of slot.assignedNodes()) {
|
|
40
|
+
if (slotted instanceof HTMLSpanElement) el = slotted;
|
|
44
41
|
}
|
|
42
|
+
|
|
43
|
+
return { el, count: parseInt(el?.textContent ?? "0") };
|
|
45
44
|
}
|
|
46
45
|
|
|
47
46
|
function getIncrement(e: Event) {
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
return target.hasAttribute("increase") ? 1 : -1;
|
|
47
|
+
if (e.target instanceof HTMLButtonElement) {
|
|
48
|
+
return e.target.hasAttribute("increase") ? 1 : -1;
|
|
51
49
|
}
|
|
52
50
|
}
|
|
53
51
|
|
|
@@ -7,7 +7,5 @@ document.addEventListener("submit", function (e) {
|
|
|
7
7
|
e.preventDefault();
|
|
8
8
|
let formdata = new FormData(e.target);
|
|
9
9
|
if (results)
|
|
10
|
-
results.textContent = JSON.stringify(
|
|
11
|
-
// @ts-expect-error
|
|
12
|
-
Object.fromEntries(formdata), undefined, " ");
|
|
10
|
+
results.textContent = JSON.stringify(Object.fromEntries(formdata), undefined, " ");
|
|
13
11
|
});
|
|
@@ -1,16 +1,12 @@
|
|
|
1
|
-
/*
|
|
2
|
-
Form associated custom element.
|
|
3
|
-
*/
|
|
4
1
|
import { Wc, Events } from "wctk";
|
|
5
2
|
export class TextInput extends HTMLElement {
|
|
6
3
|
static formAssociated = true;
|
|
7
4
|
#wc = new Wc({ host: this });
|
|
8
5
|
#ev = new Events({
|
|
9
|
-
host: this,
|
|
10
|
-
target: this.#wc.shadowRoot,
|
|
11
6
|
connected: true,
|
|
12
|
-
|
|
13
|
-
|
|
7
|
+
target: this.#wc.shadowRoot,
|
|
8
|
+
listeners: {
|
|
9
|
+
change: this.#changeHandler.bind(this),
|
|
14
10
|
},
|
|
15
11
|
});
|
|
16
12
|
#changeHandler(event) {
|
|
@@ -18,7 +14,6 @@ export class TextInput extends HTMLElement {
|
|
|
18
14
|
if (target instanceof HTMLInputElement)
|
|
19
15
|
this.#wc.setFormValue(target.value);
|
|
20
16
|
}
|
|
21
|
-
// lifecycle method
|
|
22
17
|
formStateRestoreCallback(state) {
|
|
23
18
|
let input = this.#wc.shadowRoot.querySelector("input");
|
|
24
19
|
if (input)
|
|
@@ -8,12 +8,12 @@ export class TextInput extends HTMLElement {
|
|
|
8
8
|
static formAssociated = true;
|
|
9
9
|
|
|
10
10
|
#wc = new Wc({ host: this });
|
|
11
|
+
|
|
11
12
|
#ev = new Events({
|
|
12
|
-
host: this,
|
|
13
|
-
target: this.#wc.shadowRoot,
|
|
14
13
|
connected: true,
|
|
15
|
-
|
|
16
|
-
|
|
14
|
+
target: this.#wc.shadowRoot,
|
|
15
|
+
listeners: {
|
|
16
|
+
change: this.#changeHandler.bind(this),
|
|
17
17
|
},
|
|
18
18
|
});
|
|
19
19
|
|
|
@@ -14,16 +14,19 @@
|
|
|
14
14
|
</head>
|
|
15
15
|
<body>
|
|
16
16
|
<main>
|
|
17
|
-
|
|
18
|
-
<button>| |</button>
|
|
19
|
-
|
|
20
|
-
<!-- web component -->
|
|
17
|
+
<!-- webcomponent -->
|
|
21
18
|
<stopwatch-wc>
|
|
22
19
|
<template shadowrootmode="closed">
|
|
23
20
|
<!-- Shadow DOM content -->
|
|
24
21
|
<span>117.00</span>
|
|
25
22
|
</template>
|
|
26
23
|
</stopwatch-wc>
|
|
24
|
+
|
|
25
|
+
<section>
|
|
26
|
+
<button start>|></button>
|
|
27
|
+
<button pause>| |</button>
|
|
28
|
+
<button stop>[ ]</button>
|
|
29
|
+
</section>
|
|
27
30
|
</main>
|
|
28
31
|
</body>
|
|
29
32
|
</html>
|
|
@@ -1,23 +1,13 @@
|
|
|
1
1
|
import { Stopwatch } from "./stopwatch.js";
|
|
2
2
|
customElements.define("stopwatch-wc", Stopwatch);
|
|
3
3
|
const stopwatch = document.querySelector("stopwatch-wc");
|
|
4
|
-
let receipt;
|
|
5
|
-
function draw(timestamp) {
|
|
6
|
-
if (!stopwatch)
|
|
7
|
-
return;
|
|
8
|
-
receipt = requestAnimationFrame(draw);
|
|
9
|
-
stopwatch.update(timestamp);
|
|
10
|
-
}
|
|
11
|
-
function start() {
|
|
12
|
-
if (!stopwatch)
|
|
13
|
-
return;
|
|
14
|
-
requestAnimationFrame(draw);
|
|
15
|
-
}
|
|
16
|
-
function pause() {
|
|
17
|
-
cancelAnimationFrame(receipt);
|
|
18
|
-
}
|
|
19
4
|
document.addEventListener("click", function (e) {
|
|
20
|
-
if (stopwatch && e.target instanceof HTMLButtonElement)
|
|
21
|
-
|
|
22
|
-
|
|
5
|
+
if (!(stopwatch && e.target instanceof HTMLButtonElement))
|
|
6
|
+
return;
|
|
7
|
+
if (e.target.hasAttribute("start"))
|
|
8
|
+
stopwatch.start();
|
|
9
|
+
if (e.target.hasAttribute("pause"))
|
|
10
|
+
stopwatch.pause();
|
|
11
|
+
if (e.target.hasAttribute("stop"))
|
|
12
|
+
stopwatch.stop();
|
|
23
13
|
});
|
|
@@ -1,27 +1,13 @@
|
|
|
1
1
|
import { Stopwatch } from "./stopwatch.js";
|
|
2
2
|
|
|
3
3
|
customElements.define("stopwatch-wc", Stopwatch);
|
|
4
|
-
const stopwatch = document.querySelector<Stopwatch>("stopwatch-wc");
|
|
5
|
-
|
|
6
|
-
let receipt: number;
|
|
7
|
-
function draw(timestamp: DOMHighResTimeStamp) {
|
|
8
|
-
if (!stopwatch) return;
|
|
9
4
|
|
|
10
|
-
|
|
11
|
-
stopwatch.update(timestamp);
|
|
12
|
-
}
|
|
13
|
-
|
|
14
|
-
function start() {
|
|
15
|
-
if (!stopwatch) return;
|
|
16
|
-
requestAnimationFrame(draw);
|
|
17
|
-
}
|
|
5
|
+
const stopwatch = document.querySelector<Stopwatch>("stopwatch-wc");
|
|
18
6
|
|
|
19
|
-
function
|
|
20
|
-
|
|
21
|
-
}
|
|
7
|
+
document.addEventListener("click", function (e: PointerEvent) {
|
|
8
|
+
if (!(stopwatch && e.target instanceof HTMLButtonElement)) return;
|
|
22
9
|
|
|
23
|
-
|
|
24
|
-
if (
|
|
25
|
-
|
|
26
|
-
}
|
|
10
|
+
if (e.target.hasAttribute("start")) stopwatch.start();
|
|
11
|
+
if (e.target.hasAttribute("pause")) stopwatch.pause();
|
|
12
|
+
if (e.target.hasAttribute("stop")) stopwatch.stop();
|
|
27
13
|
});
|
|
@@ -1,34 +1,48 @@
|
|
|
1
|
-
/*
|
|
2
|
-
Custom Element with performant and "asynchronous" renders
|
|
3
|
-
on the microtask queue.
|
|
4
|
-
*/
|
|
5
1
|
import { Wc, Microtask } from "wctk";
|
|
6
|
-
class Stopwatch extends HTMLElement {
|
|
2
|
+
export class Stopwatch extends HTMLElement {
|
|
7
3
|
#wc = new Wc({ host: this });
|
|
8
|
-
#rc = new Microtask(
|
|
4
|
+
#rc = new Microtask(this.#render.bind(this));
|
|
9
5
|
#state = getStateFromShadowDOM(this.#wc.shadowRoot);
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
6
|
+
#render() {
|
|
7
|
+
let { el } = this.#state;
|
|
8
|
+
if (el)
|
|
9
|
+
el.textContent = this.#state.count.toFixed(2);
|
|
10
|
+
}
|
|
11
|
+
#update = this.#undboundUpdate.bind(this);
|
|
12
|
+
#undboundUpdate(now) {
|
|
13
|
+
this.#state.count += (now - this.#state.prevTimestamp) * 0.001;
|
|
14
|
+
this.#state.prevTimestamp = now;
|
|
15
|
+
this.#state.receipt = window.requestAnimationFrame(this.#update);
|
|
16
16
|
this.#rc.queue();
|
|
17
17
|
}
|
|
18
|
-
|
|
19
|
-
if (this.#state)
|
|
20
|
-
|
|
18
|
+
start() {
|
|
19
|
+
if (this.#state.receipt)
|
|
20
|
+
return;
|
|
21
|
+
this.#state.prevTimestamp = performance.now();
|
|
22
|
+
this.#state.receipt = window.requestAnimationFrame(this.#update);
|
|
23
|
+
}
|
|
24
|
+
pause() {
|
|
25
|
+
let { receipt } = this.#state;
|
|
26
|
+
if (receipt)
|
|
27
|
+
window.cancelAnimationFrame(receipt);
|
|
28
|
+
this.#state.receipt = undefined;
|
|
29
|
+
}
|
|
30
|
+
stop() {
|
|
31
|
+
this.pause();
|
|
32
|
+
this.#state.count = 0;
|
|
33
|
+
this.#rc.queue();
|
|
21
34
|
}
|
|
22
35
|
}
|
|
23
36
|
function getStateFromShadowDOM(shadowRoot) {
|
|
24
37
|
let el = shadowRoot.querySelector("span");
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
38
|
+
let count = parseInt(el?.textContent ?? "0");
|
|
39
|
+
if (Number.isNaN(count))
|
|
40
|
+
count = 0;
|
|
41
|
+
let prevTimestamp = performance.now();
|
|
42
|
+
return {
|
|
43
|
+
count,
|
|
44
|
+
el,
|
|
45
|
+
prevTimestamp,
|
|
46
|
+
receipt: undefined,
|
|
47
|
+
};
|
|
33
48
|
}
|
|
34
|
-
export { Stopwatch };
|
|
@@ -3,47 +3,68 @@
|
|
|
3
3
|
on the microtask queue.
|
|
4
4
|
*/
|
|
5
5
|
|
|
6
|
+
// This example uses window.requestAnimationFrame.
|
|
7
|
+
// Multiple stopwatches means multiple animation frame requests.
|
|
8
|
+
// This is not terribly performant but it's a quick way to retrieve
|
|
9
|
+
// accurate timestamp data for a stopwatch.
|
|
10
|
+
|
|
6
11
|
import { Wc, Microtask } from "wctk";
|
|
7
12
|
|
|
8
13
|
interface State {
|
|
9
|
-
receipt: number | void;
|
|
10
14
|
count: number;
|
|
15
|
+
el: HTMLSpanElement | null;
|
|
11
16
|
prevTimestamp: DOMHighResTimeStamp;
|
|
12
|
-
|
|
17
|
+
receipt: number | void;
|
|
13
18
|
}
|
|
14
19
|
|
|
15
|
-
class Stopwatch extends HTMLElement {
|
|
20
|
+
export class Stopwatch extends HTMLElement {
|
|
16
21
|
#wc = new Wc({ host: this });
|
|
17
|
-
#rc = new Microtask(
|
|
22
|
+
#rc = new Microtask(this.#render.bind(this));
|
|
23
|
+
#state: State = getStateFromShadowDOM(this.#wc.shadowRoot);
|
|
18
24
|
|
|
19
|
-
#
|
|
25
|
+
#render() {
|
|
26
|
+
let { el } = this.#state;
|
|
27
|
+
if (el) el.textContent = this.#state.count.toFixed(2);
|
|
28
|
+
}
|
|
20
29
|
|
|
21
|
-
update(
|
|
22
|
-
|
|
30
|
+
#update = this.#undboundUpdate.bind(this);
|
|
31
|
+
#undboundUpdate(now: DOMHighResTimeStamp) {
|
|
32
|
+
this.#state.count += (now - this.#state.prevTimestamp) * 0.001;
|
|
33
|
+
this.#state.prevTimestamp = now;
|
|
34
|
+
this.#state.receipt = window.requestAnimationFrame(this.#update);
|
|
35
|
+
this.#rc.queue();
|
|
36
|
+
}
|
|
23
37
|
|
|
24
|
-
|
|
25
|
-
this.#state.
|
|
38
|
+
start() {
|
|
39
|
+
if (this.#state.receipt) return;
|
|
26
40
|
|
|
27
|
-
|
|
28
|
-
this.#
|
|
41
|
+
this.#state.prevTimestamp = performance.now();
|
|
42
|
+
this.#state.receipt = window.requestAnimationFrame(this.#update);
|
|
29
43
|
}
|
|
30
44
|
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
45
|
+
pause() {
|
|
46
|
+
let { receipt } = this.#state;
|
|
47
|
+
if (receipt) window.cancelAnimationFrame(receipt);
|
|
48
|
+
this.#state.receipt = undefined;
|
|
34
49
|
}
|
|
35
|
-
}
|
|
36
50
|
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
el,
|
|
42
|
-
count: parseInt(el.textContent ?? "0"),
|
|
43
|
-
receipt: 0,
|
|
44
|
-
prevTimestamp: performance.now(),
|
|
45
|
-
};
|
|
51
|
+
stop() {
|
|
52
|
+
this.pause();
|
|
53
|
+
this.#state.count = 0;
|
|
54
|
+
this.#rc.queue();
|
|
46
55
|
}
|
|
47
56
|
}
|
|
48
57
|
|
|
49
|
-
|
|
58
|
+
function getStateFromShadowDOM(shadowRoot: ShadowRoot): State {
|
|
59
|
+
let el = shadowRoot.querySelector("span");
|
|
60
|
+
let count = parseInt(el?.textContent ?? "0");
|
|
61
|
+
if (Number.isNaN(count)) count = 0;
|
|
62
|
+
let prevTimestamp = performance.now();
|
|
63
|
+
|
|
64
|
+
return {
|
|
65
|
+
count,
|
|
66
|
+
el,
|
|
67
|
+
prevTimestamp,
|
|
68
|
+
receipt: undefined,
|
|
69
|
+
};
|
|
70
|
+
}
|
package/examples/tsconfig.json
CHANGED
package/jr.json
ADDED
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
{
|
|
2
|
+
"jackrabbit_url": "http://localhost:4000",
|
|
3
|
+
"run_asynchronously": false,
|
|
4
|
+
"webdrivers": [
|
|
5
|
+
{
|
|
6
|
+
"command": "safaridriver -p 4001",
|
|
7
|
+
"title": "Safari",
|
|
8
|
+
"timeout_ms": 20000,
|
|
9
|
+
"webdriver_url": "http://localhost:4001"
|
|
10
|
+
},
|
|
11
|
+
{
|
|
12
|
+
"command": "geckodriver -p 4001",
|
|
13
|
+
"title": "Firefox",
|
|
14
|
+
"timeout_ms": 20000,
|
|
15
|
+
"webdriver_url": "http://localhost:4001",
|
|
16
|
+
"capabilities": {
|
|
17
|
+
"alwaysMatch": {
|
|
18
|
+
"moz:firefoxOptions": {
|
|
19
|
+
"args": ["-headless"]
|
|
20
|
+
}
|
|
21
|
+
}
|
|
22
|
+
}
|
|
23
|
+
}
|
|
24
|
+
]
|
|
25
|
+
}
|
package/package.json
CHANGED
|
@@ -2,18 +2,23 @@
|
|
|
2
2
|
"name": "@w-lfpup/wctk",
|
|
3
3
|
"type": "module",
|
|
4
4
|
"main": "dist/mod.js",
|
|
5
|
-
"description": "A bare-metal
|
|
5
|
+
"description": "A bare-metal webcomponent toolkit",
|
|
6
6
|
"license": "BSD-3-Clause",
|
|
7
|
-
"version": "0.
|
|
7
|
+
"version": "0.2.2",
|
|
8
8
|
"scripts": {
|
|
9
9
|
"prepare": "npm run build",
|
|
10
|
-
"build": "
|
|
10
|
+
"build": "npm run build:src && npm run build:tests && npm run build:examples",
|
|
11
|
+
"build:src": "npx tsc --project ./src",
|
|
12
|
+
"build:tests": "npx tsc --project ./tests",
|
|
11
13
|
"build:examples": "npx tsc --project ./examples",
|
|
14
|
+
"test": "npm run test:browsers",
|
|
15
|
+
"test:browsers": "npx jackrabbit_webdriver jr.json tests/dist/mod.js",
|
|
12
16
|
"format": "prettier --write ./"
|
|
13
17
|
},
|
|
14
18
|
"devDependencies": {
|
|
15
|
-
"
|
|
16
|
-
"
|
|
19
|
+
"@w-lfpup/jackrabbit": "^0.3.2",
|
|
20
|
+
"prettier": "^3.8.3",
|
|
21
|
+
"typescript": "^6.0.2"
|
|
17
22
|
},
|
|
18
23
|
"repository": {
|
|
19
24
|
"type": "git",
|
package/src/events.ts
CHANGED
|
@@ -1,20 +1,22 @@
|
|
|
1
|
-
interface GenericEventListener<E> {
|
|
1
|
+
interface GenericEventListener<E extends Event> {
|
|
2
2
|
(evt: E): void;
|
|
3
3
|
}
|
|
4
4
|
|
|
5
|
-
interface GenericEventListenerObject<E> {
|
|
5
|
+
interface GenericEventListenerObject<E extends Event> {
|
|
6
6
|
handleEvent(object: E): void;
|
|
7
7
|
}
|
|
8
8
|
|
|
9
|
-
type GenericCallbacks<E> =
|
|
9
|
+
type GenericCallbacks<E extends Event> =
|
|
10
10
|
| GenericEventListener<E>
|
|
11
11
|
| GenericEventListenerObject<E>;
|
|
12
12
|
|
|
13
|
-
type EventMap =
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
13
|
+
type EventMap =
|
|
14
|
+
| Partial<{
|
|
15
|
+
[Property in keyof GlobalEventHandlersEventMap]: GenericCallbacks<
|
|
16
|
+
GlobalEventHandlersEventMap[Property]
|
|
17
|
+
>;
|
|
18
|
+
}>
|
|
19
|
+
| Record<string, EventListenerOrEventListenerObject>;
|
|
18
20
|
|
|
19
21
|
type Callbacks = Array<[string, EventListenerOrEventListenerObject]>;
|
|
20
22
|
|
|
@@ -24,10 +26,9 @@ interface EventElementInterface {
|
|
|
24
26
|
}
|
|
25
27
|
|
|
26
28
|
export interface EventParamsInterface {
|
|
27
|
-
|
|
29
|
+
listeners: EventMap;
|
|
28
30
|
connected?: boolean;
|
|
29
|
-
|
|
30
|
-
target?: EventElementInterface;
|
|
31
|
+
target: EventElementInterface;
|
|
31
32
|
}
|
|
32
33
|
|
|
33
34
|
export interface EventsInterface {
|
|
@@ -37,14 +38,14 @@ export interface EventsInterface {
|
|
|
37
38
|
|
|
38
39
|
export class Events implements EventsInterface {
|
|
39
40
|
#connected: boolean = false;
|
|
40
|
-
#
|
|
41
|
+
#listeners: Callbacks = [];
|
|
41
42
|
#target: EventElementInterface;
|
|
42
43
|
|
|
43
44
|
constructor(params: EventParamsInterface) {
|
|
44
|
-
const {
|
|
45
|
+
const { target, listeners, connected } = params;
|
|
45
46
|
|
|
46
|
-
this.#target = target
|
|
47
|
-
this.#
|
|
47
|
+
this.#target = target;
|
|
48
|
+
this.#listeners = Object.entries(listeners) as Callbacks;
|
|
48
49
|
|
|
49
50
|
if (connected) this.connect();
|
|
50
51
|
}
|
|
@@ -53,8 +54,8 @@ export class Events implements EventsInterface {
|
|
|
53
54
|
if (this.#connected) return;
|
|
54
55
|
this.#connected = true;
|
|
55
56
|
|
|
56
|
-
for (let [name,
|
|
57
|
-
this.#target.addEventListener(name,
|
|
57
|
+
for (let [name, listener] of this.#listeners) {
|
|
58
|
+
this.#target.addEventListener(name, listener);
|
|
58
59
|
}
|
|
59
60
|
}
|
|
60
61
|
|
|
@@ -62,27 +63,8 @@ export class Events implements EventsInterface {
|
|
|
62
63
|
if (!this.#connected) return;
|
|
63
64
|
this.#connected = false;
|
|
64
65
|
|
|
65
|
-
for (let [name,
|
|
66
|
-
this.#target.removeEventListener(name,
|
|
66
|
+
for (let [name, listener] of this.#listeners) {
|
|
67
|
+
this.#target.removeEventListener(name, listener);
|
|
67
68
|
}
|
|
68
69
|
}
|
|
69
70
|
}
|
|
70
|
-
|
|
71
|
-
function getBoundCallbacks(host: Object, callbacks: EventMap): Callbacks {
|
|
72
|
-
let boundCallbacks: Callbacks = [];
|
|
73
|
-
for (let [name, callback] of Object.entries(callbacks)) {
|
|
74
|
-
if (
|
|
75
|
-
callback instanceof Function &&
|
|
76
|
-
!callback.hasOwnProperty("prototype")
|
|
77
|
-
) {
|
|
78
|
-
callback = callback.bind(host);
|
|
79
|
-
}
|
|
80
|
-
|
|
81
|
-
boundCallbacks.push([
|
|
82
|
-
name,
|
|
83
|
-
callback as EventListenerOrEventListenerObject,
|
|
84
|
-
]);
|
|
85
|
-
}
|
|
86
|
-
|
|
87
|
-
return boundCallbacks;
|
|
88
|
-
}
|
package/src/microtask.ts
CHANGED
|
@@ -1,37 +1,28 @@
|
|
|
1
|
-
export interface MicrotaskParamsInterface {
|
|
2
|
-
host: Object;
|
|
3
|
-
callback: Function;
|
|
4
|
-
}
|
|
5
|
-
|
|
6
1
|
export interface MicrotaskInterface {
|
|
7
2
|
queue(): void;
|
|
8
3
|
}
|
|
9
4
|
|
|
5
|
+
type Callback = () => void;
|
|
6
|
+
|
|
10
7
|
export class Microtask implements MicrotaskInterface {
|
|
11
8
|
#queued = false;
|
|
12
|
-
#callback:
|
|
9
|
+
#callback: Callback;
|
|
13
10
|
|
|
14
|
-
constructor(
|
|
15
|
-
let { host, callback } = params;
|
|
16
|
-
|
|
17
|
-
this.queue = this.queue.bind(this);
|
|
11
|
+
constructor(callback: Callback) {
|
|
18
12
|
this.#callback = callback;
|
|
19
|
-
if (
|
|
20
|
-
callback instanceof Function &&
|
|
21
|
-
!callback.hasOwnProperty("prototype")
|
|
22
|
-
) {
|
|
23
|
-
this.#callback = callback.bind(host);
|
|
24
|
-
}
|
|
25
13
|
}
|
|
26
14
|
|
|
27
|
-
queue()
|
|
15
|
+
queue = this.#queue.bind(this);
|
|
16
|
+
#queue() {
|
|
28
17
|
if (this.#queued) return;
|
|
29
18
|
this.#queued = true;
|
|
30
19
|
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
20
|
+
window.queueMicrotask(this.#microtask);
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
#microtask = this.#unboundMicrotask.bind(this);
|
|
24
|
+
#unboundMicrotask() {
|
|
25
|
+
this.#queued = false;
|
|
26
|
+
this.#callback();
|
|
36
27
|
}
|
|
37
28
|
}
|