@w-lfpup/wctk 0.1.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/.github/workflows/build_and_test.yml +18 -0
- package/.prettierignore +5 -0
- package/.prettierrc +5 -0
- package/LICENSE +28 -0
- package/README.md +49 -0
- package/dist/bind.d.ts +7 -0
- package/dist/bind.js +14 -0
- package/dist/events.d.ts +21 -0
- package/dist/events.js +39 -0
- package/dist/microtask.d.ts +12 -0
- package/dist/microtask.js +23 -0
- package/dist/mod.d.ts +6 -0
- package/dist/mod.js +6 -0
- package/dist/query_selector.d.ts +15 -0
- package/dist/query_selector.js +25 -0
- package/dist/subscription.d.ts +19 -0
- package/dist/subscription.js +26 -0
- package/dist/wc.d.ts +33 -0
- package/dist/wc.js +46 -0
- package/docs/bind.md +26 -0
- package/docs/events.md +99 -0
- package/docs/microtask.md +35 -0
- package/docs/query_selector.md +39 -0
- package/docs/subscription.md +85 -0
- package/docs/wc.md +57 -0
- package/examples/counter/index.html +30 -0
- package/examples/counter/mod.js +39 -0
- package/examples/counter/mod.ts +51 -0
- package/examples/form_associated/index.html +31 -0
- package/examples/form_associated/mod.js +13 -0
- package/examples/form_associated/mod.ts +21 -0
- package/examples/form_associated/text_input.js +25 -0
- package/examples/form_associated/text_input.ts +28 -0
- package/examples/stopwatch/index.html +29 -0
- package/examples/stopwatch/mod.js +8 -0
- package/examples/stopwatch/mod.ts +11 -0
- package/examples/stopwatch/stopwatch.js +45 -0
- package/examples/stopwatch/stopwatch.ts +61 -0
- package/examples/tsconfig.json +10 -0
- package/package.json +22 -0
- package/src/bind.ts +22 -0
- package/src/events.ts +67 -0
- package/src/microtask.ts +37 -0
- package/src/mod.ts +6 -0
- package/src/query_selector.ts +46 -0
- package/src/subscription.ts +47 -0
- package/src/tsconfig.json +7 -0
- package/src/wc.ts +87 -0
- package/tsconfig.json +9 -0
package/src/microtask.ts
ADDED
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
export interface MicrotaskParamsInterface {
|
|
2
|
+
host: Object;
|
|
3
|
+
callback: Function;
|
|
4
|
+
}
|
|
5
|
+
|
|
6
|
+
export interface MicrotaskInterface {
|
|
7
|
+
queue(): void;
|
|
8
|
+
}
|
|
9
|
+
|
|
10
|
+
export class Microtask implements MicrotaskInterface {
|
|
11
|
+
#queued = false;
|
|
12
|
+
#callback: Function;
|
|
13
|
+
|
|
14
|
+
constructor(params: MicrotaskParamsInterface) {
|
|
15
|
+
let { host, callback } = params;
|
|
16
|
+
|
|
17
|
+
this.queue = this.queue.bind(this);
|
|
18
|
+
this.#callback = callback;
|
|
19
|
+
if (
|
|
20
|
+
callback instanceof Function &&
|
|
21
|
+
!callback.hasOwnProperty("prototype")
|
|
22
|
+
) {
|
|
23
|
+
this.#callback = callback.bind(host);
|
|
24
|
+
}
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
queue() {
|
|
28
|
+
if (this.#queued) return;
|
|
29
|
+
this.#queued = true;
|
|
30
|
+
|
|
31
|
+
// could this be a bound function? less function creation
|
|
32
|
+
queueMicrotask(() => {
|
|
33
|
+
this.#queued = false;
|
|
34
|
+
this.#callback();
|
|
35
|
+
});
|
|
36
|
+
}
|
|
37
|
+
}
|
package/src/mod.ts
ADDED
|
@@ -0,0 +1,46 @@
|
|
|
1
|
+
export interface QuerySelectorParamsInterface {
|
|
2
|
+
parent: ParentNode;
|
|
3
|
+
}
|
|
4
|
+
|
|
5
|
+
export interface QuerySelectorInterface {
|
|
6
|
+
querySelector(name: string): Element | undefined;
|
|
7
|
+
querySelectorAll(name: string): Element[] | undefined;
|
|
8
|
+
deleteAll(): void;
|
|
9
|
+
}
|
|
10
|
+
|
|
11
|
+
export class QuerySelector implements QuerySelectorInterface {
|
|
12
|
+
#queries: Map<string, Element[]> = new Map();
|
|
13
|
+
#params: QuerySelectorParamsInterface;
|
|
14
|
+
|
|
15
|
+
constructor(params: QuerySelectorParamsInterface) {
|
|
16
|
+
this.#params = params;
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
querySelector(selector: string): Element | undefined {
|
|
20
|
+
return getQuery(this.#params, this.#queries, selector)[0];
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
querySelectorAll(selector: string): Element[] {
|
|
24
|
+
return getQuery(this.#params, this.#queries, selector);
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
deleteAll() {
|
|
28
|
+
this.#queries = new Map();
|
|
29
|
+
}
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
function getQuery(
|
|
33
|
+
params: QuerySelectorParamsInterface,
|
|
34
|
+
queries: Map<string, Element[]>,
|
|
35
|
+
selector: string,
|
|
36
|
+
): Element[] {
|
|
37
|
+
const { parent } = params;
|
|
38
|
+
|
|
39
|
+
let results = queries.get(selector);
|
|
40
|
+
if (!results) {
|
|
41
|
+
results = Array.from(parent.querySelectorAll(selector));
|
|
42
|
+
queries.set(selector, results);
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
return results;
|
|
46
|
+
}
|
|
@@ -0,0 +1,47 @@
|
|
|
1
|
+
export type Subscribe<E, A> = (cb: E) => A;
|
|
2
|
+
export type Unsubscribe<A> = (affect: A) => void;
|
|
3
|
+
|
|
4
|
+
export interface SubscriptionInterface {
|
|
5
|
+
connect(): void;
|
|
6
|
+
disconnect(): void;
|
|
7
|
+
}
|
|
8
|
+
|
|
9
|
+
export interface SubscriptionParamsInterface<E, A> {
|
|
10
|
+
host: Object;
|
|
11
|
+
callback: E;
|
|
12
|
+
connected?: boolean;
|
|
13
|
+
subscribe: Subscribe<E, A>;
|
|
14
|
+
unsubscribe: Unsubscribe<A>;
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
export class Subscription<E, A> implements SubscriptionInterface {
|
|
18
|
+
#callback: E;
|
|
19
|
+
#affect?: A;
|
|
20
|
+
#subscribe: Subscribe<E, A>;
|
|
21
|
+
#unsubscribe: Unsubscribe<A>;
|
|
22
|
+
|
|
23
|
+
constructor(params: SubscriptionParamsInterface<E, A>) {
|
|
24
|
+
let { host, callback, connected, subscribe, unsubscribe } = params;
|
|
25
|
+
|
|
26
|
+
this.#subscribe = subscribe;
|
|
27
|
+
this.#unsubscribe = unsubscribe;
|
|
28
|
+
|
|
29
|
+
this.#callback = callback;
|
|
30
|
+
if (
|
|
31
|
+
callback instanceof Function &&
|
|
32
|
+
!callback.hasOwnProperty("prototype")
|
|
33
|
+
) {
|
|
34
|
+
this.#callback = callback.bind(host);
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
if (connected) this.connect();
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
connect() {
|
|
41
|
+
if (!this.#affect) this.#affect = this.#subscribe(this.#callback);
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
disconnect() {
|
|
45
|
+
if (this.#affect) this.#unsubscribe(this.#affect);
|
|
46
|
+
}
|
|
47
|
+
}
|
package/src/wc.ts
ADDED
|
@@ -0,0 +1,87 @@
|
|
|
1
|
+
export interface WcElementInterface {
|
|
2
|
+
attachInternals: HTMLElement["attachInternals"];
|
|
3
|
+
attachShadow: Element["attachShadow"];
|
|
4
|
+
}
|
|
5
|
+
|
|
6
|
+
type FormDataArguments = Parameters<ElementInternals["setFormValue"]>;
|
|
7
|
+
|
|
8
|
+
export interface WcParamsInterface {
|
|
9
|
+
host: WcElementInterface;
|
|
10
|
+
adoptedStyleSheets?: CSSStyleSheet[];
|
|
11
|
+
shadowRootInit?: ShadowRootInit;
|
|
12
|
+
formValue?: FormDataArguments[0];
|
|
13
|
+
formState?: FormDataArguments[1];
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
export interface WcInterface {
|
|
17
|
+
readonly declarative: boolean;
|
|
18
|
+
readonly shadowRoot: ShadowRoot;
|
|
19
|
+
adoptedStyleSheets: DocumentOrShadowRoot["adoptedStyleSheets"];
|
|
20
|
+
setFormValue: ElementInternals["setFormValue"];
|
|
21
|
+
setValidity: ElementInternals["setValidity"];
|
|
22
|
+
reportValidity: ElementInternals["reportValidity"];
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
const shadowRootInitFallback: ShadowRootInit = {
|
|
26
|
+
mode: "closed",
|
|
27
|
+
};
|
|
28
|
+
|
|
29
|
+
export class Wc implements WcInterface {
|
|
30
|
+
#declarative: boolean = true;
|
|
31
|
+
#internals: ElementInternals;
|
|
32
|
+
#shadowRoot: ShadowRoot;
|
|
33
|
+
|
|
34
|
+
constructor(params: WcParamsInterface) {
|
|
35
|
+
let { host, shadowRootInit, adoptedStyleSheets, formValue, formState } =
|
|
36
|
+
params;
|
|
37
|
+
this.#internals = host.attachInternals();
|
|
38
|
+
|
|
39
|
+
let { shadowRoot } = this.#internals;
|
|
40
|
+
if (!shadowRoot) {
|
|
41
|
+
this.#declarative = false;
|
|
42
|
+
shadowRoot = host.attachShadow(
|
|
43
|
+
shadowRootInit ?? shadowRootInitFallback,
|
|
44
|
+
);
|
|
45
|
+
}
|
|
46
|
+
this.#shadowRoot = shadowRoot;
|
|
47
|
+
|
|
48
|
+
if (formValue) this.setFormValue(formValue, formState);
|
|
49
|
+
if (adoptedStyleSheets) this.adoptedStyleSheets = adoptedStyleSheets;
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
get declarative(): boolean {
|
|
53
|
+
return this.#declarative;
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
get shadowRoot(): ShadowRoot {
|
|
57
|
+
return this.#shadowRoot;
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
get adoptedStyleSheets(): CSSStyleSheet[] {
|
|
61
|
+
return this.#shadowRoot.adoptedStyleSheets ?? [];
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
set adoptedStyleSheets(stylesheets: CSSStyleSheet[]) {
|
|
65
|
+
this.#shadowRoot.adoptedStyleSheets = stylesheets;
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
checkValidity() {
|
|
69
|
+
return this.#internals.checkValidity();
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
reportValidity(): boolean {
|
|
73
|
+
return this.#internals.reportValidity();
|
|
74
|
+
}
|
|
75
|
+
|
|
76
|
+
setFormValue(value: FormDataArguments[0], state?: FormDataArguments[1]) {
|
|
77
|
+
this.#internals.setFormValue(value, state);
|
|
78
|
+
}
|
|
79
|
+
|
|
80
|
+
setValidity(
|
|
81
|
+
flags?: ValidityStateFlags,
|
|
82
|
+
message?: string,
|
|
83
|
+
anchor?: HTMLElement,
|
|
84
|
+
) {
|
|
85
|
+
this.#internals.setValidity(flags, message, anchor);
|
|
86
|
+
}
|
|
87
|
+
}
|