@w-lfpup/wctk 0.1.0 → 0.1.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/.github/workflows/{build_and_test.yml → builds.yml} +2 -2
- package/README.md +5 -5
- package/dist/events.d.ts +19 -9
- package/dist/events.js +5 -2
- package/dist/wc.js +8 -6
- package/docs/events.md +14 -13
- package/docs/query_selector.md +1 -0
- package/docs/wc.md +2 -4
- package/examples/counter/mod.js +5 -3
- package/examples/counter/mod.ts +9 -6
- package/examples/form_associated/text_input.js +4 -2
- package/examples/form_associated/text_input.ts +7 -4
- package/examples/stopwatch/mod.js +16 -1
- package/examples/stopwatch/mod.ts +18 -2
- package/examples/stopwatch/stopwatch.js +8 -19
- package/examples/stopwatch/stopwatch.ts +14 -26
- package/package.json +2 -2
- package/src/events.ts +33 -12
- package/src/wc.ts +7 -6
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
name:
|
|
1
|
+
name: Builds
|
|
2
2
|
|
|
3
3
|
on:
|
|
4
4
|
push:
|
|
@@ -10,7 +10,7 @@ jobs:
|
|
|
10
10
|
build_and_test:
|
|
11
11
|
runs-on: ubuntu-latest
|
|
12
12
|
steps:
|
|
13
|
-
- uses: actions/checkout@
|
|
13
|
+
- uses: actions/checkout@v6
|
|
14
14
|
- uses: actions/setup-node@v4
|
|
15
15
|
- name: Install
|
|
16
16
|
run: npm ci
|
package/README.md
CHANGED
|
@@ -1,6 +1,8 @@
|
|
|
1
1
|
# Wctk-JS
|
|
2
2
|
|
|
3
|
-
A web component tool kit.
|
|
3
|
+
A web component tool kit without dependencies.
|
|
4
|
+
|
|
5
|
+
[](https://github.com/w-lfpup/wctk-js/actions/workflows/builds.yml)
|
|
4
6
|
|
|
5
7
|
## About
|
|
6
8
|
|
|
@@ -14,11 +16,9 @@ A half-dozen controllers help developers:
|
|
|
14
16
|
- [query](./docs/query_selector.md) the shadow dom
|
|
15
17
|
- [bind](./docs/bind.md) functions to elements
|
|
16
18
|
|
|
17
|
-
All features are compositional and built to support [declarative shadow dom](https://developer.mozilla.org/en-US/docs/Web/API/Web_components/Using_shadow_DOM#declaratively_with_html) SSR.
|
|
18
|
-
|
|
19
|
-
There are no base classes or decorators.
|
|
19
|
+
All features are compositional and built to support [declarative shadow dom](https://developer.mozilla.org/en-US/docs/Web/API/Web_components/Using_shadow_DOM#declaratively_with_html) and SSR.
|
|
20
20
|
|
|
21
|
-
|
|
21
|
+
There are no base classes, decorators, or mixins.
|
|
22
22
|
|
|
23
23
|
## Install
|
|
24
24
|
|
package/dist/events.d.ts
CHANGED
|
@@ -1,17 +1,26 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
connect(): void;
|
|
4
|
-
disconnect(): void;
|
|
1
|
+
interface GenericEventListener<E> {
|
|
2
|
+
(evt: E): void;
|
|
5
3
|
}
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
4
|
+
interface GenericEventListenerObject<E> {
|
|
5
|
+
handleEvent(object: E): void;
|
|
6
|
+
}
|
|
7
|
+
type GenericCallbacks<E> = GenericEventListener<E> | GenericEventListenerObject<E>;
|
|
8
|
+
type EventMap = Partial<{
|
|
9
|
+
[Property in keyof GlobalEventHandlersEventMap]: GenericCallbacks<GlobalEventHandlersEventMap[Property]>;
|
|
10
|
+
}>;
|
|
11
|
+
interface EventElementInterface {
|
|
12
|
+
addEventListener: Element["addEventListener"];
|
|
13
|
+
removeEventListener: Element["removeEventListener"];
|
|
9
14
|
}
|
|
10
15
|
export interface EventParamsInterface {
|
|
11
|
-
|
|
16
|
+
callbacks: EventMap;
|
|
12
17
|
connected?: boolean;
|
|
18
|
+
host: EventElementInterface;
|
|
13
19
|
target?: EventElementInterface;
|
|
14
|
-
|
|
20
|
+
}
|
|
21
|
+
export interface EventsInterface {
|
|
22
|
+
connect(): void;
|
|
23
|
+
disconnect(): void;
|
|
15
24
|
}
|
|
16
25
|
export declare class Events implements EventsInterface {
|
|
17
26
|
#private;
|
|
@@ -19,3 +28,4 @@ export declare class Events implements EventsInterface {
|
|
|
19
28
|
connect(): void;
|
|
20
29
|
disconnect(): void;
|
|
21
30
|
}
|
|
31
|
+
export {};
|
package/dist/events.js
CHANGED
|
@@ -28,12 +28,15 @@ export class Events {
|
|
|
28
28
|
}
|
|
29
29
|
function getBoundCallbacks(host, callbacks) {
|
|
30
30
|
let boundCallbacks = [];
|
|
31
|
-
for (let [name, callback] of callbacks) {
|
|
31
|
+
for (let [name, callback] of Object.entries(callbacks)) {
|
|
32
32
|
if (callback instanceof Function &&
|
|
33
33
|
!callback.hasOwnProperty("prototype")) {
|
|
34
34
|
callback = callback.bind(host);
|
|
35
35
|
}
|
|
36
|
-
boundCallbacks.push([
|
|
36
|
+
boundCallbacks.push([
|
|
37
|
+
name,
|
|
38
|
+
callback,
|
|
39
|
+
]);
|
|
37
40
|
}
|
|
38
41
|
return boundCallbacks;
|
|
39
42
|
}
|
package/dist/wc.js
CHANGED
|
@@ -6,18 +6,20 @@ export class Wc {
|
|
|
6
6
|
#internals;
|
|
7
7
|
#shadowRoot;
|
|
8
8
|
constructor(params) {
|
|
9
|
-
let {
|
|
9
|
+
let { adoptedStyleSheets, host, formState, formValue, shadowRootInit } = params;
|
|
10
10
|
this.#internals = host.attachInternals();
|
|
11
11
|
let { shadowRoot } = this.#internals;
|
|
12
|
-
if (
|
|
12
|
+
if (shadowRoot) {
|
|
13
|
+
this.#shadowRoot = shadowRoot;
|
|
14
|
+
}
|
|
15
|
+
else {
|
|
13
16
|
this.#declarative = false;
|
|
14
|
-
shadowRoot = host.attachShadow(shadowRootInit ?? shadowRootInitFallback);
|
|
17
|
+
this.#shadowRoot = host.attachShadow(shadowRootInit ?? shadowRootInitFallback);
|
|
15
18
|
}
|
|
16
|
-
this.#shadowRoot = shadowRoot;
|
|
17
|
-
if (formValue)
|
|
18
|
-
this.setFormValue(formValue, formState);
|
|
19
19
|
if (adoptedStyleSheets)
|
|
20
20
|
this.adoptedStyleSheets = adoptedStyleSheets;
|
|
21
|
+
if (formValue)
|
|
22
|
+
this.setFormValue(formValue, formState);
|
|
21
23
|
}
|
|
22
24
|
get declarative() {
|
|
23
25
|
return this.#declarative;
|
package/docs/events.md
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
# Events Controller
|
|
2
2
|
|
|
3
|
-
Add
|
|
3
|
+
Add event listeners to web components.
|
|
4
4
|
|
|
5
5
|
## How to use
|
|
6
6
|
|
|
@@ -12,14 +12,14 @@ An Events `params` object has four properties:
|
|
|
12
12
|
|
|
13
13
|
```ts
|
|
14
14
|
interface EventParams {
|
|
15
|
-
|
|
16
|
-
callbacks: Array<[string, EventListener]>;
|
|
15
|
+
callbacks: Record<string, EventListenerOrEventListenerObject>;
|
|
17
16
|
connected?: boolean;
|
|
17
|
+
host: Node;
|
|
18
18
|
target?: Node;
|
|
19
19
|
}
|
|
20
20
|
```
|
|
21
21
|
|
|
22
|
-
The `Events` controller binds a
|
|
22
|
+
The `Events` controller binds a record of `callbacks` to a `host`.
|
|
23
23
|
|
|
24
24
|
Afterwards, the `Events` controller adds the callbacks as event listeners on a `target` node.
|
|
25
25
|
|
|
@@ -36,20 +36,21 @@ import { Events, Wc } from "wctk";
|
|
|
36
36
|
|
|
37
37
|
class MyElement extends HTMLElement {
|
|
38
38
|
#wc = new Wc({ this: host });
|
|
39
|
+
|
|
39
40
|
#ec = new Events({
|
|
40
41
|
host: this,
|
|
41
42
|
target: this.#wc.shadowRoot,
|
|
42
|
-
callbacks:
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
43
|
+
callbacks: {
|
|
44
|
+
click: this.#onClick,
|
|
45
|
+
keydown: this.#onKeyDown,
|
|
46
|
+
},
|
|
46
47
|
});
|
|
47
48
|
|
|
48
49
|
#onClick(e: PointerEvent) {
|
|
49
50
|
// do something with pointer events here!
|
|
50
51
|
}
|
|
51
52
|
|
|
52
|
-
#onKeyDown(e:
|
|
53
|
+
#onKeyDown(e: KeyboardEvent) {
|
|
53
54
|
// do something with key events here!
|
|
54
55
|
}
|
|
55
56
|
|
|
@@ -78,10 +79,10 @@ class MyElement extends HTMLElement {
|
|
|
78
79
|
host: this,
|
|
79
80
|
target: this.#wc.shadowRoot,
|
|
80
81
|
connected: true,
|
|
81
|
-
callbacks:
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
82
|
+
callbacks: {
|
|
83
|
+
click: this.#onClick,
|
|
84
|
+
keydown: this.#onKeyDown,
|
|
85
|
+
},
|
|
85
86
|
});
|
|
86
87
|
|
|
87
88
|
#onClick(e: PointerEvent) {
|
package/docs/query_selector.md
CHANGED
package/docs/wc.md
CHANGED
|
@@ -4,9 +4,7 @@ Build a web component.
|
|
|
4
4
|
|
|
5
5
|
## How to use
|
|
6
6
|
|
|
7
|
-
Add a `Wc` controller to a custom element
|
|
8
|
-
|
|
9
|
-
One line is all it takes.
|
|
7
|
+
Add a `Wc` controller to a custom element with only one line
|
|
10
8
|
|
|
11
9
|
```ts
|
|
12
10
|
import { Wc } from "wctk";
|
|
@@ -18,7 +16,7 @@ class MyElement extends HTMLElement {
|
|
|
18
16
|
|
|
19
17
|
## Adopted stylesheets and form values
|
|
20
18
|
|
|
21
|
-
The `Wc` controller is also a facade for core web componet APIs like adopted stylesheets and form values.
|
|
19
|
+
The `Wc` controller is also a facade for fast access to core web componet APIs like adopted stylesheets and form values.
|
|
22
20
|
|
|
23
21
|
```ts
|
|
24
22
|
class MyElement extends HTMLElement {
|
package/examples/counter/mod.js
CHANGED
|
@@ -1,17 +1,19 @@
|
|
|
1
|
-
import { Wc, Events } from "wctk";
|
|
2
1
|
/*
|
|
3
2
|
Custom Element with state and interactivity.
|
|
4
3
|
*/
|
|
4
|
+
import { Wc, Events } from "wctk";
|
|
5
5
|
class Counter extends HTMLElement {
|
|
6
6
|
#wc = new Wc({ host: this });
|
|
7
7
|
#ev = new Events({
|
|
8
8
|
host: this,
|
|
9
9
|
target: this.#wc.shadowRoot,
|
|
10
10
|
connected: true,
|
|
11
|
-
callbacks:
|
|
11
|
+
callbacks: {
|
|
12
|
+
click: this.#onClick,
|
|
13
|
+
},
|
|
12
14
|
});
|
|
13
15
|
#state = getStateFromDOM(this.#wc.shadowRoot);
|
|
14
|
-
#
|
|
16
|
+
#onClick(e) {
|
|
15
17
|
if (!this.#state)
|
|
16
18
|
return;
|
|
17
19
|
let increment = getIncrement(e);
|
package/examples/counter/mod.ts
CHANGED
|
@@ -1,3 +1,7 @@
|
|
|
1
|
+
/*
|
|
2
|
+
Custom Element with state and interactivity.
|
|
3
|
+
*/
|
|
4
|
+
|
|
1
5
|
import { Wc, Events } from "wctk";
|
|
2
6
|
|
|
3
7
|
interface State {
|
|
@@ -5,9 +9,6 @@ interface State {
|
|
|
5
9
|
count: number;
|
|
6
10
|
}
|
|
7
11
|
|
|
8
|
-
/*
|
|
9
|
-
Custom Element with state and interactivity.
|
|
10
|
-
*/
|
|
11
12
|
class Counter extends HTMLElement {
|
|
12
13
|
#wc = new Wc({ host: this });
|
|
13
14
|
|
|
@@ -15,12 +16,14 @@ class Counter extends HTMLElement {
|
|
|
15
16
|
host: this,
|
|
16
17
|
target: this.#wc.shadowRoot,
|
|
17
18
|
connected: true,
|
|
18
|
-
callbacks:
|
|
19
|
+
callbacks: {
|
|
20
|
+
click: this.#onClick,
|
|
21
|
+
},
|
|
19
22
|
});
|
|
20
23
|
|
|
21
24
|
#state?: State = getStateFromDOM(this.#wc.shadowRoot);
|
|
22
25
|
|
|
23
|
-
#
|
|
26
|
+
#onClick(e: PointerEvent) {
|
|
24
27
|
if (!this.#state) return;
|
|
25
28
|
|
|
26
29
|
let increment = getIncrement(e);
|
|
@@ -31,7 +34,7 @@ class Counter extends HTMLElement {
|
|
|
31
34
|
}
|
|
32
35
|
}
|
|
33
36
|
|
|
34
|
-
function getStateFromDOM(shadowRoot: ShadowRoot) {
|
|
37
|
+
function getStateFromDOM(shadowRoot: ShadowRoot): State | undefined {
|
|
35
38
|
let slot = shadowRoot.querySelector("slot");
|
|
36
39
|
if (slot)
|
|
37
40
|
for (let el of slot.assignedNodes()) {
|
|
@@ -1,7 +1,7 @@
|
|
|
1
|
-
import { Wc, Events } from "wctk";
|
|
2
1
|
/*
|
|
3
2
|
Form associated custom element.
|
|
4
3
|
*/
|
|
4
|
+
import { Wc, Events } from "wctk";
|
|
5
5
|
export class TextInput extends HTMLElement {
|
|
6
6
|
static formAssociated = true;
|
|
7
7
|
#wc = new Wc({ host: this });
|
|
@@ -9,7 +9,9 @@ export class TextInput extends HTMLElement {
|
|
|
9
9
|
host: this,
|
|
10
10
|
target: this.#wc.shadowRoot,
|
|
11
11
|
connected: true,
|
|
12
|
-
callbacks:
|
|
12
|
+
callbacks: {
|
|
13
|
+
change: this.#changeHandler,
|
|
14
|
+
},
|
|
13
15
|
});
|
|
14
16
|
#changeHandler(event) {
|
|
15
17
|
let { target } = event;
|
|
@@ -1,8 +1,9 @@
|
|
|
1
|
-
import { Wc, Events } from "wctk";
|
|
2
|
-
|
|
3
1
|
/*
|
|
4
2
|
Form associated custom element.
|
|
5
3
|
*/
|
|
4
|
+
|
|
5
|
+
import { Wc, Events } from "wctk";
|
|
6
|
+
|
|
6
7
|
export class TextInput extends HTMLElement {
|
|
7
8
|
static formAssociated = true;
|
|
8
9
|
|
|
@@ -11,10 +12,12 @@ export class TextInput extends HTMLElement {
|
|
|
11
12
|
host: this,
|
|
12
13
|
target: this.#wc.shadowRoot,
|
|
13
14
|
connected: true,
|
|
14
|
-
callbacks:
|
|
15
|
+
callbacks: {
|
|
16
|
+
change: this.#changeHandler,
|
|
17
|
+
},
|
|
15
18
|
});
|
|
16
19
|
|
|
17
|
-
#changeHandler(event: Event) {
|
|
20
|
+
#changeHandler(event: Event): void {
|
|
18
21
|
let { target } = event;
|
|
19
22
|
if (target instanceof HTMLInputElement)
|
|
20
23
|
this.#wc.setFormValue(target.value);
|
|
@@ -1,8 +1,23 @@
|
|
|
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
|
+
}
|
|
4
19
|
document.addEventListener("click", function (e) {
|
|
5
20
|
if (stopwatch && e.target instanceof HTMLButtonElement) {
|
|
6
|
-
e.target.hasAttribute("start") ?
|
|
21
|
+
e.target.hasAttribute("start") ? start() : pause();
|
|
7
22
|
}
|
|
8
23
|
});
|
|
@@ -1,11 +1,27 @@
|
|
|
1
1
|
import { Stopwatch } from "./stopwatch.js";
|
|
2
2
|
|
|
3
3
|
customElements.define("stopwatch-wc", Stopwatch);
|
|
4
|
-
|
|
5
4
|
const stopwatch = document.querySelector<Stopwatch>("stopwatch-wc");
|
|
6
5
|
|
|
6
|
+
let receipt: number;
|
|
7
|
+
function draw(timestamp: DOMHighResTimeStamp) {
|
|
8
|
+
if (!stopwatch) return;
|
|
9
|
+
|
|
10
|
+
receipt = requestAnimationFrame(draw);
|
|
11
|
+
stopwatch.update(timestamp);
|
|
12
|
+
}
|
|
13
|
+
|
|
14
|
+
function start() {
|
|
15
|
+
if (!stopwatch) return;
|
|
16
|
+
requestAnimationFrame(draw);
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
function pause() {
|
|
20
|
+
cancelAnimationFrame(receipt);
|
|
21
|
+
}
|
|
22
|
+
|
|
7
23
|
document.addEventListener("click", function (e: Event) {
|
|
8
24
|
if (stopwatch && e.target instanceof HTMLButtonElement) {
|
|
9
|
-
e.target.hasAttribute("start") ?
|
|
25
|
+
e.target.hasAttribute("start") ? start() : pause();
|
|
10
26
|
}
|
|
11
27
|
});
|
|
@@ -1,35 +1,23 @@
|
|
|
1
|
-
import { Wc, Microtask } from "wctk";
|
|
2
1
|
/*
|
|
3
2
|
Custom Element with performant and "asynchronous" renders
|
|
4
3
|
on the microtask queue.
|
|
5
4
|
*/
|
|
6
|
-
|
|
5
|
+
import { Wc, Microtask } from "wctk";
|
|
6
|
+
class Stopwatch extends HTMLElement {
|
|
7
7
|
#wc = new Wc({ host: this });
|
|
8
8
|
#rc = new Microtask({ host: this, callback: this.#render });
|
|
9
|
-
#boundUpdate = this.#update.bind(this);
|
|
10
9
|
#state = getStateFromShadowDOM(this.#wc.shadowRoot);
|
|
11
|
-
|
|
12
|
-
if (this.#state)
|
|
13
|
-
this.#state.el.textContent = this.#state.count.toFixed(2);
|
|
14
|
-
}
|
|
15
|
-
#update(timestamp) {
|
|
16
|
-
if (!this.#state)
|
|
10
|
+
update(timestamp) {
|
|
11
|
+
if (!this.#state || timestamp < this.#state.prevTimestamp)
|
|
17
12
|
return;
|
|
18
|
-
this.#state.receipt = requestAnimationFrame(this.#boundUpdate);
|
|
19
13
|
this.#state.count += (timestamp - this.#state.prevTimestamp) * 0.001;
|
|
20
14
|
this.#state.prevTimestamp = timestamp;
|
|
21
15
|
// push render to microtask queue
|
|
22
16
|
this.#rc.queue();
|
|
23
17
|
}
|
|
24
|
-
|
|
25
|
-
if (
|
|
26
|
-
|
|
27
|
-
this.#state.receipt = requestAnimationFrame(this.#boundUpdate);
|
|
28
|
-
this.#state.prevTimestamp = performance.now();
|
|
29
|
-
}
|
|
30
|
-
pause() {
|
|
31
|
-
if (this.#state && this.#state.receipt)
|
|
32
|
-
this.#state.receipt = cancelAnimationFrame(this.#state.receipt);
|
|
18
|
+
#render() {
|
|
19
|
+
if (this.#state)
|
|
20
|
+
this.#state.el.textContent = this.#state.count.toFixed(2);
|
|
33
21
|
}
|
|
34
22
|
}
|
|
35
23
|
function getStateFromShadowDOM(shadowRoot) {
|
|
@@ -43,3 +31,4 @@ function getStateFromShadowDOM(shadowRoot) {
|
|
|
43
31
|
};
|
|
44
32
|
}
|
|
45
33
|
}
|
|
34
|
+
export { Stopwatch };
|
|
@@ -1,4 +1,9 @@
|
|
|
1
|
-
|
|
1
|
+
/*
|
|
2
|
+
Custom Element with performant and "asynchronous" renders
|
|
3
|
+
on the microtask queue.
|
|
4
|
+
*/
|
|
5
|
+
|
|
6
|
+
import { Wc, Microtask } from "wctk";
|
|
2
7
|
|
|
3
8
|
interface State {
|
|
4
9
|
receipt: number | void;
|
|
@@ -7,26 +12,14 @@ interface State {
|
|
|
7
12
|
el: HTMLSpanElement;
|
|
8
13
|
}
|
|
9
14
|
|
|
10
|
-
|
|
11
|
-
Custom Element with performant and "asynchronous" renders
|
|
12
|
-
on the microtask queue.
|
|
13
|
-
*/
|
|
14
|
-
export class Stopwatch extends HTMLElement {
|
|
15
|
+
class Stopwatch extends HTMLElement {
|
|
15
16
|
#wc = new Wc({ host: this });
|
|
16
17
|
#rc = new Microtask({ host: this, callback: this.#render });
|
|
17
18
|
|
|
18
|
-
#boundUpdate = this.#update.bind(this);
|
|
19
19
|
#state?: State = getStateFromShadowDOM(this.#wc.shadowRoot);
|
|
20
20
|
|
|
21
|
-
|
|
22
|
-
if (this.#state)
|
|
23
|
-
this.#state.el.textContent = this.#state.count.toFixed(2);
|
|
24
|
-
}
|
|
25
|
-
|
|
26
|
-
#update(timestamp: DOMHighResTimeStamp) {
|
|
27
|
-
if (!this.#state) return;
|
|
28
|
-
|
|
29
|
-
this.#state.receipt = requestAnimationFrame(this.#boundUpdate);
|
|
21
|
+
update(timestamp: DOMHighResTimeStamp) {
|
|
22
|
+
if (!this.#state || timestamp < this.#state.prevTimestamp) return;
|
|
30
23
|
|
|
31
24
|
this.#state.count += (timestamp - this.#state.prevTimestamp) * 0.001;
|
|
32
25
|
this.#state.prevTimestamp = timestamp;
|
|
@@ -35,16 +28,9 @@ export class Stopwatch extends HTMLElement {
|
|
|
35
28
|
this.#rc.queue();
|
|
36
29
|
}
|
|
37
30
|
|
|
38
|
-
|
|
39
|
-
if (
|
|
40
|
-
|
|
41
|
-
this.#state.receipt = requestAnimationFrame(this.#boundUpdate);
|
|
42
|
-
this.#state.prevTimestamp = performance.now();
|
|
43
|
-
}
|
|
44
|
-
|
|
45
|
-
pause() {
|
|
46
|
-
if (this.#state && this.#state.receipt)
|
|
47
|
-
this.#state.receipt = cancelAnimationFrame(this.#state.receipt);
|
|
31
|
+
#render() {
|
|
32
|
+
if (this.#state)
|
|
33
|
+
this.#state.el.textContent = this.#state.count.toFixed(2);
|
|
48
34
|
}
|
|
49
35
|
}
|
|
50
36
|
|
|
@@ -59,3 +45,5 @@ function getStateFromShadowDOM(shadowRoot: ShadowRoot): State | undefined {
|
|
|
59
45
|
};
|
|
60
46
|
}
|
|
61
47
|
}
|
|
48
|
+
|
|
49
|
+
export { Stopwatch };
|
package/package.json
CHANGED
|
@@ -4,9 +4,9 @@
|
|
|
4
4
|
"main": "dist/mod.js",
|
|
5
5
|
"description": "A bare-metal web component toolkit",
|
|
6
6
|
"license": "BSD-3-Clause",
|
|
7
|
-
"version": "0.1.
|
|
7
|
+
"version": "0.1.1",
|
|
8
8
|
"scripts": {
|
|
9
|
-
"prepare": "npm run build
|
|
9
|
+
"prepare": "npm run build",
|
|
10
10
|
"build": "npx tsc --project ./src",
|
|
11
11
|
"build:examples": "npx tsc --project ./examples",
|
|
12
12
|
"format": "prettier --write ./"
|
package/src/events.ts
CHANGED
|
@@ -1,20 +1,38 @@
|
|
|
1
|
-
|
|
1
|
+
interface GenericEventListener<E> {
|
|
2
|
+
(evt: E): void;
|
|
3
|
+
}
|
|
2
4
|
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
disconnect(): void;
|
|
5
|
+
interface GenericEventListenerObject<E> {
|
|
6
|
+
handleEvent(object: E): void;
|
|
6
7
|
}
|
|
7
8
|
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
9
|
+
type GenericCallbacks<E> =
|
|
10
|
+
| GenericEventListener<E>
|
|
11
|
+
| GenericEventListenerObject<E>;
|
|
12
|
+
|
|
13
|
+
type EventMap = Partial<{
|
|
14
|
+
[Property in keyof GlobalEventHandlersEventMap]: GenericCallbacks<
|
|
15
|
+
GlobalEventHandlersEventMap[Property]
|
|
16
|
+
>;
|
|
17
|
+
}>;
|
|
18
|
+
|
|
19
|
+
type Callbacks = Array<[string, EventListenerOrEventListenerObject]>;
|
|
20
|
+
|
|
21
|
+
interface EventElementInterface {
|
|
22
|
+
addEventListener: Element["addEventListener"];
|
|
23
|
+
removeEventListener: Element["removeEventListener"];
|
|
11
24
|
}
|
|
12
25
|
|
|
13
26
|
export interface EventParamsInterface {
|
|
14
|
-
|
|
27
|
+
callbacks: EventMap;
|
|
15
28
|
connected?: boolean;
|
|
29
|
+
host: EventElementInterface;
|
|
16
30
|
target?: EventElementInterface;
|
|
17
|
-
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
export interface EventsInterface {
|
|
34
|
+
connect(): void;
|
|
35
|
+
disconnect(): void;
|
|
18
36
|
}
|
|
19
37
|
|
|
20
38
|
export class Events implements EventsInterface {
|
|
@@ -50,9 +68,9 @@ export class Events implements EventsInterface {
|
|
|
50
68
|
}
|
|
51
69
|
}
|
|
52
70
|
|
|
53
|
-
function getBoundCallbacks(host: Object, callbacks:
|
|
71
|
+
function getBoundCallbacks(host: Object, callbacks: EventMap): Callbacks {
|
|
54
72
|
let boundCallbacks: Callbacks = [];
|
|
55
|
-
for (let [name, callback] of callbacks) {
|
|
73
|
+
for (let [name, callback] of Object.entries(callbacks)) {
|
|
56
74
|
if (
|
|
57
75
|
callback instanceof Function &&
|
|
58
76
|
!callback.hasOwnProperty("prototype")
|
|
@@ -60,7 +78,10 @@ function getBoundCallbacks(host: Object, callbacks: Callbacks): Callbacks {
|
|
|
60
78
|
callback = callback.bind(host);
|
|
61
79
|
}
|
|
62
80
|
|
|
63
|
-
boundCallbacks.push([
|
|
81
|
+
boundCallbacks.push([
|
|
82
|
+
name,
|
|
83
|
+
callback as EventListenerOrEventListenerObject,
|
|
84
|
+
]);
|
|
64
85
|
}
|
|
65
86
|
|
|
66
87
|
return boundCallbacks;
|
package/src/wc.ts
CHANGED
|
@@ -32,21 +32,22 @@ export class Wc implements WcInterface {
|
|
|
32
32
|
#shadowRoot: ShadowRoot;
|
|
33
33
|
|
|
34
34
|
constructor(params: WcParamsInterface) {
|
|
35
|
-
let {
|
|
36
|
-
|
|
35
|
+
let { adoptedStyleSheets, host, formState, formValue, shadowRootInit } = params;
|
|
36
|
+
|
|
37
37
|
this.#internals = host.attachInternals();
|
|
38
38
|
|
|
39
39
|
let { shadowRoot } = this.#internals;
|
|
40
|
-
if (
|
|
40
|
+
if (shadowRoot) {
|
|
41
|
+
this.#shadowRoot = shadowRoot;
|
|
42
|
+
} else {
|
|
41
43
|
this.#declarative = false;
|
|
42
|
-
shadowRoot = host.attachShadow(
|
|
44
|
+
this.#shadowRoot = host.attachShadow(
|
|
43
45
|
shadowRootInit ?? shadowRootInitFallback,
|
|
44
46
|
);
|
|
45
47
|
}
|
|
46
|
-
this.#shadowRoot = shadowRoot;
|
|
47
48
|
|
|
48
|
-
if (formValue) this.setFormValue(formValue, formState);
|
|
49
49
|
if (adoptedStyleSheets) this.adoptedStyleSheets = adoptedStyleSheets;
|
|
50
|
+
if (formValue) this.setFormValue(formValue, formState);
|
|
50
51
|
}
|
|
51
52
|
|
|
52
53
|
get declarative(): boolean {
|