@w-lfpup/wctk 0.1.1 → 0.2.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/browsers.macos.json +51 -0
- package/.github/workflows/browsers.ubuntu.json +37 -0
- package/.github/workflows/builds.yml +13 -4
- package/README.md +35 -10
- package/dist/events.d.ts +2 -3
- package/dist/events.js +8 -22
- package/dist/microtask.d.ts +4 -6
- package/dist/microtask.js +3 -8
- 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 +11 -14
- package/docs/microtask.md +2 -5
- package/docs/query_selector.md +1 -4
- package/docs/wc.md +1 -1
- package/examples/counter/mod.js +13 -17
- package/examples/counter/mod.ts +15 -17
- package/examples/form_associated/mod.js +1 -3
- package/examples/form_associated/mod.ts +0 -1
- package/examples/form_associated/text_input.js +2 -7
- package/examples/form_associated/text_input.ts +2 -3
- package/examples/stopwatch/index.html +6 -3
- 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 +9 -5
- package/src/events.ts +10 -30
- package/src/microtask.ts +6 -17
- 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/src/wc.ts
CHANGED
|
@@ -3,14 +3,14 @@ export interface WcElementInterface {
|
|
|
3
3
|
attachShadow: Element["attachShadow"];
|
|
4
4
|
}
|
|
5
5
|
|
|
6
|
-
type
|
|
6
|
+
type FormValueArgs = Parameters<ElementInternals["setFormValue"]>;
|
|
7
7
|
|
|
8
8
|
export interface WcParamsInterface {
|
|
9
9
|
host: WcElementInterface;
|
|
10
10
|
adoptedStyleSheets?: CSSStyleSheet[];
|
|
11
11
|
shadowRootInit?: ShadowRootInit;
|
|
12
|
-
formValue?:
|
|
13
|
-
formState?:
|
|
12
|
+
formValue?: FormValueArgs[0];
|
|
13
|
+
formState?: FormValueArgs[1];
|
|
14
14
|
}
|
|
15
15
|
|
|
16
16
|
export interface WcInterface {
|
|
@@ -27,26 +27,26 @@ const shadowRootInitFallback: ShadowRootInit = {
|
|
|
27
27
|
};
|
|
28
28
|
|
|
29
29
|
export class Wc implements WcInterface {
|
|
30
|
-
#declarative: boolean =
|
|
30
|
+
#declarative: boolean = false;
|
|
31
31
|
#internals: ElementInternals;
|
|
32
32
|
#shadowRoot: ShadowRoot;
|
|
33
33
|
|
|
34
34
|
constructor(params: WcParamsInterface) {
|
|
35
|
-
let { adoptedStyleSheets, host, formState, formValue, shadowRootInit } =
|
|
35
|
+
let { adoptedStyleSheets, host, formState, formValue, shadowRootInit } =
|
|
36
|
+
params;
|
|
36
37
|
|
|
37
38
|
this.#internals = host.attachInternals();
|
|
38
39
|
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
this.#shadowRoot = shadowRoot;
|
|
40
|
+
if (this.#internals.shadowRoot) {
|
|
41
|
+
this.#declarative = true;
|
|
42
|
+
this.#shadowRoot = this.#internals.shadowRoot;
|
|
42
43
|
} else {
|
|
43
|
-
this.#declarative = false;
|
|
44
44
|
this.#shadowRoot = host.attachShadow(
|
|
45
45
|
shadowRootInit ?? shadowRootInitFallback,
|
|
46
46
|
);
|
|
47
47
|
}
|
|
48
48
|
|
|
49
|
-
|
|
49
|
+
this.adoptedStyleSheets = adoptedStyleSheets ?? [];
|
|
50
50
|
if (formValue) this.setFormValue(formValue, formState);
|
|
51
51
|
}
|
|
52
52
|
|
|
@@ -74,7 +74,7 @@ export class Wc implements WcInterface {
|
|
|
74
74
|
return this.#internals.reportValidity();
|
|
75
75
|
}
|
|
76
76
|
|
|
77
|
-
setFormValue(value:
|
|
77
|
+
setFormValue(value: FormValueArgs[0], state?: FormValueArgs[1]) {
|
|
78
78
|
this.#internals.setFormValue(value, state);
|
|
79
79
|
}
|
|
80
80
|
|
|
@@ -0,0 +1,60 @@
|
|
|
1
|
+
import { findElement, elementClick, elementSendKeys, } from "@w-lfpup/jackrabbit/browser/dist/commands.js";
|
|
2
|
+
import { Events } from "../../dist/mod.js";
|
|
3
|
+
let eventController;
|
|
4
|
+
let eventReceipts = [];
|
|
5
|
+
function setup() {
|
|
6
|
+
eventController = new Events({
|
|
7
|
+
target: document.body,
|
|
8
|
+
connected: true,
|
|
9
|
+
listeners: {
|
|
10
|
+
click: function (e) {
|
|
11
|
+
eventReceipts.push(e);
|
|
12
|
+
},
|
|
13
|
+
input: function (e) {
|
|
14
|
+
eventReceipts.push(e);
|
|
15
|
+
},
|
|
16
|
+
},
|
|
17
|
+
});
|
|
18
|
+
document.body.setHTMLUnsafe(`
|
|
19
|
+
<input>
|
|
20
|
+
<button>
|
|
21
|
+
`);
|
|
22
|
+
}
|
|
23
|
+
async function testClickEvents() {
|
|
24
|
+
let buttonId = await findElement("button");
|
|
25
|
+
if (!buttonId)
|
|
26
|
+
return "failed to query button";
|
|
27
|
+
await elementClick(buttonId);
|
|
28
|
+
await elementClick(buttonId);
|
|
29
|
+
let clicks = [];
|
|
30
|
+
for (let event of eventReceipts) {
|
|
31
|
+
if ("click" === event.type)
|
|
32
|
+
clicks.push(event);
|
|
33
|
+
}
|
|
34
|
+
if (2 !== clicks.length)
|
|
35
|
+
return `incorrect number of clicks: ${clicks.length}/2`;
|
|
36
|
+
}
|
|
37
|
+
async function testInputEvents() {
|
|
38
|
+
const expectedMessage = "UwU";
|
|
39
|
+
let inputId = await findElement("input");
|
|
40
|
+
if (!inputId)
|
|
41
|
+
return "failed to query input element";
|
|
42
|
+
await elementSendKeys(inputId, expectedMessage);
|
|
43
|
+
let inputs = [];
|
|
44
|
+
for (let event of eventReceipts) {
|
|
45
|
+
if ("input" === event.type)
|
|
46
|
+
inputs.push(event);
|
|
47
|
+
}
|
|
48
|
+
if (3 !== inputs.length)
|
|
49
|
+
return `incorrect number of input events: ${inputs.length}/1`;
|
|
50
|
+
let input = document.body.querySelector("input");
|
|
51
|
+
if (expectedMessage !== input?.value)
|
|
52
|
+
return `expected input: ${expectedMessage}, found: ${input?.value}`;
|
|
53
|
+
}
|
|
54
|
+
function tearDown() {
|
|
55
|
+
eventController.disconnect();
|
|
56
|
+
}
|
|
57
|
+
export const tests = [setup, testClickEvents, testInputEvents, tearDown];
|
|
58
|
+
export const options = {
|
|
59
|
+
title: import.meta.url,
|
|
60
|
+
};
|
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
import { Microtask } from "../../dist/mod.js";
|
|
2
|
+
let microtaskController;
|
|
3
|
+
let expectedSleepy = "-_-";
|
|
4
|
+
let expectedHappy = "^_^";
|
|
5
|
+
let span;
|
|
6
|
+
function nextFrame() {
|
|
7
|
+
return new Promise((resolve, reject) => {
|
|
8
|
+
window.queueMicrotask(function () {
|
|
9
|
+
resolve();
|
|
10
|
+
});
|
|
11
|
+
});
|
|
12
|
+
}
|
|
13
|
+
function updateExpression() {
|
|
14
|
+
if (!span)
|
|
15
|
+
return;
|
|
16
|
+
span.textContent = expectedHappy;
|
|
17
|
+
}
|
|
18
|
+
function setup() {
|
|
19
|
+
microtaskController = new Microtask(updateExpression);
|
|
20
|
+
document.body.setHTMLUnsafe(`
|
|
21
|
+
<span>-_-</span>
|
|
22
|
+
`);
|
|
23
|
+
span = document.querySelector("span");
|
|
24
|
+
}
|
|
25
|
+
async function testTaskCycle() {
|
|
26
|
+
if (expectedSleepy !== span?.textContent)
|
|
27
|
+
return "wrong expression, expected sleepy -_-";
|
|
28
|
+
microtaskController.queue();
|
|
29
|
+
if (expectedSleepy !== span?.textContent)
|
|
30
|
+
return "still wrong expression, still expected sleepy -_-";
|
|
31
|
+
await nextFrame();
|
|
32
|
+
if (expectedHappy !== span?.textContent)
|
|
33
|
+
return "wrong expression after frame, expected happy ^_^";
|
|
34
|
+
}
|
|
35
|
+
export const tests = [setup, testTaskCycle];
|
|
36
|
+
export const options = {
|
|
37
|
+
title: import.meta.url,
|
|
38
|
+
};
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
import * as EventTests from "./events.tests.js";
|
|
2
|
+
import * as MicrotaskQueueTests from "./microtask.tests.js";
|
|
3
|
+
import * as QuerySelectorTests from "./query_selector.tests.js";
|
|
4
|
+
import * as WcTests from "./wc.tests.js";
|
|
5
|
+
export const testModules = [
|
|
6
|
+
EventTests,
|
|
7
|
+
MicrotaskQueueTests,
|
|
8
|
+
QuerySelectorTests,
|
|
9
|
+
WcTests,
|
|
10
|
+
];
|
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
import { QuerySelector } from "../../dist/mod.js";
|
|
2
|
+
let qs;
|
|
3
|
+
function setup() {
|
|
4
|
+
qs = new QuerySelector(document.body);
|
|
5
|
+
document.body.setHTMLUnsafe(`
|
|
6
|
+
<p>
|
|
7
|
+
<span data-first>hello</span>
|
|
8
|
+
<span data-second>hai :3</span>
|
|
9
|
+
</p>
|
|
10
|
+
`);
|
|
11
|
+
}
|
|
12
|
+
function testQuerySelector() {
|
|
13
|
+
let p = qs.querySelector("p");
|
|
14
|
+
let span = qs.querySelector("[data-second]");
|
|
15
|
+
if (!p)
|
|
16
|
+
return "failed to query p";
|
|
17
|
+
if (!span)
|
|
18
|
+
return "failed to query span";
|
|
19
|
+
}
|
|
20
|
+
function testQuerySelectorAll() {
|
|
21
|
+
let peas = qs.querySelectorAll("p");
|
|
22
|
+
let spans = qs.querySelectorAll("span");
|
|
23
|
+
if (!peas.length)
|
|
24
|
+
return "failed to query peas";
|
|
25
|
+
if (!spans.length)
|
|
26
|
+
return "failed to query spans";
|
|
27
|
+
if (1 !== peas.length)
|
|
28
|
+
return `failed to query ${peas.length}/1 peas`;
|
|
29
|
+
if (2 !== spans.length)
|
|
30
|
+
return `failed to query ${spans.length}/2 spans`;
|
|
31
|
+
}
|
|
32
|
+
function testDeleteAll() {
|
|
33
|
+
qs.deleteAll();
|
|
34
|
+
}
|
|
35
|
+
export const tests = [
|
|
36
|
+
setup,
|
|
37
|
+
testQuerySelector,
|
|
38
|
+
testQuerySelectorAll,
|
|
39
|
+
testDeleteAll,
|
|
40
|
+
];
|
|
41
|
+
export const options = {
|
|
42
|
+
title: import.meta.url,
|
|
43
|
+
};
|
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
import { Wc } from "../../dist/mod.js";
|
|
2
|
+
class WcDeclarativeElement extends HTMLElement {
|
|
3
|
+
#wc = new Wc({ host: this });
|
|
4
|
+
get delcarative() {
|
|
5
|
+
return this.#wc.declarative;
|
|
6
|
+
}
|
|
7
|
+
}
|
|
8
|
+
window.customElements.define("declarative-element", WcDeclarativeElement);
|
|
9
|
+
let testEl;
|
|
10
|
+
let declarativeEl;
|
|
11
|
+
function setup() {
|
|
12
|
+
document.body.setHTMLUnsafe(`
|
|
13
|
+
<declarative-element></declarative-element>
|
|
14
|
+
<declarative-element data-declarative>
|
|
15
|
+
<template shadowrootmode="open">
|
|
16
|
+
<p>howdy!</p>
|
|
17
|
+
</template>
|
|
18
|
+
</declarative-element>
|
|
19
|
+
`);
|
|
20
|
+
[testEl, declarativeEl] = document.querySelectorAll("declarative-element");
|
|
21
|
+
}
|
|
22
|
+
function testDeclarativeShadowDomDoesNotExist() {
|
|
23
|
+
if (!testEl)
|
|
24
|
+
return "failed to query declarative-element";
|
|
25
|
+
if (testEl.delcarative)
|
|
26
|
+
return "element incorrectly labelled as declarative";
|
|
27
|
+
}
|
|
28
|
+
function testDeclarativeShadowDomExists() {
|
|
29
|
+
if (!declarativeEl)
|
|
30
|
+
return "failed to query declarative-element with declarative shadow dom";
|
|
31
|
+
if (!declarativeEl.delcarative)
|
|
32
|
+
return "element incorrectly labelled as not declarative";
|
|
33
|
+
}
|
|
34
|
+
export const tests = [
|
|
35
|
+
setup,
|
|
36
|
+
testDeclarativeShadowDomExists,
|
|
37
|
+
testDeclarativeShadowDomDoesNotExist,
|
|
38
|
+
];
|
|
39
|
+
export const options = {
|
|
40
|
+
title: import.meta.url,
|
|
41
|
+
};
|
|
@@ -0,0 +1,73 @@
|
|
|
1
|
+
import {
|
|
2
|
+
findElement,
|
|
3
|
+
elementClick,
|
|
4
|
+
elementSendKeys,
|
|
5
|
+
} from "@w-lfpup/jackrabbit/browser/dist/commands.js";
|
|
6
|
+
import { Events } from "../../dist/mod.js";
|
|
7
|
+
|
|
8
|
+
let eventController: Events;
|
|
9
|
+
let eventReceipts: Event[] = [];
|
|
10
|
+
|
|
11
|
+
function setup() {
|
|
12
|
+
eventController = new Events({
|
|
13
|
+
target: document.body,
|
|
14
|
+
connected: true,
|
|
15
|
+
listeners: {
|
|
16
|
+
click: function (e: PointerEvent) {
|
|
17
|
+
eventReceipts.push(e);
|
|
18
|
+
},
|
|
19
|
+
input: function (e: InputEvent) {
|
|
20
|
+
eventReceipts.push(e);
|
|
21
|
+
},
|
|
22
|
+
},
|
|
23
|
+
});
|
|
24
|
+
|
|
25
|
+
document.body.setHTMLUnsafe(`
|
|
26
|
+
<input>
|
|
27
|
+
<button>
|
|
28
|
+
`);
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
async function testClickEvents() {
|
|
32
|
+
let buttonId = await findElement("button");
|
|
33
|
+
if (!buttonId) return "failed to query button";
|
|
34
|
+
await elementClick(buttonId);
|
|
35
|
+
await elementClick(buttonId);
|
|
36
|
+
|
|
37
|
+
let clicks = [];
|
|
38
|
+
for (let event of eventReceipts) {
|
|
39
|
+
if ("click" === event.type) clicks.push(event);
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
if (2 !== clicks.length)
|
|
43
|
+
return `incorrect number of clicks: ${clicks.length}/2`;
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
async function testInputEvents() {
|
|
47
|
+
const expectedMessage = "UwU";
|
|
48
|
+
let inputId = await findElement("input");
|
|
49
|
+
if (!inputId) return "failed to query input element";
|
|
50
|
+
|
|
51
|
+
await elementSendKeys(inputId, expectedMessage);
|
|
52
|
+
let inputs = [];
|
|
53
|
+
for (let event of eventReceipts) {
|
|
54
|
+
if ("input" === event.type) inputs.push(event);
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
if (3 !== inputs.length)
|
|
58
|
+
return `incorrect number of input events: ${inputs.length}/1`;
|
|
59
|
+
|
|
60
|
+
let input = document.body.querySelector("input");
|
|
61
|
+
if (expectedMessage !== input?.value)
|
|
62
|
+
return `expected input: ${expectedMessage}, found: ${input?.value}`;
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
function tearDown() {
|
|
66
|
+
eventController.disconnect();
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
export const tests = [setup, testClickEvents, testInputEvents, tearDown];
|
|
70
|
+
|
|
71
|
+
export const options = {
|
|
72
|
+
title: import.meta.url,
|
|
73
|
+
};
|
|
@@ -0,0 +1,54 @@
|
|
|
1
|
+
import { findElement, log } from "@w-lfpup/jackrabbit/browser/dist/commands.js";
|
|
2
|
+
import { Microtask } from "../../dist/mod.js";
|
|
3
|
+
|
|
4
|
+
let microtaskController: Microtask;
|
|
5
|
+
|
|
6
|
+
let expectedSleepy = "-_-";
|
|
7
|
+
let expectedHappy = "^_^";
|
|
8
|
+
|
|
9
|
+
let span: HTMLSpanElement | null;
|
|
10
|
+
|
|
11
|
+
function nextFrame() {
|
|
12
|
+
return new Promise<void>((resolve, reject) => {
|
|
13
|
+
window.queueMicrotask(function () {
|
|
14
|
+
resolve();
|
|
15
|
+
});
|
|
16
|
+
});
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
function updateExpression() {
|
|
20
|
+
if (!span) return;
|
|
21
|
+
|
|
22
|
+
span.textContent = expectedHappy;
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
function setup() {
|
|
26
|
+
microtaskController = new Microtask(updateExpression);
|
|
27
|
+
|
|
28
|
+
document.body.setHTMLUnsafe(`
|
|
29
|
+
<span>-_-</span>
|
|
30
|
+
`);
|
|
31
|
+
|
|
32
|
+
span = document.querySelector("span");
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
async function testTaskCycle() {
|
|
36
|
+
if (expectedSleepy !== span?.textContent)
|
|
37
|
+
return "wrong expression, expected sleepy -_-";
|
|
38
|
+
|
|
39
|
+
microtaskController.queue();
|
|
40
|
+
|
|
41
|
+
if (expectedSleepy !== span?.textContent)
|
|
42
|
+
return "still wrong expression, still expected sleepy -_-";
|
|
43
|
+
|
|
44
|
+
await nextFrame();
|
|
45
|
+
|
|
46
|
+
if (expectedHappy !== span?.textContent)
|
|
47
|
+
return "wrong expression after frame, expected happy ^_^";
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
export const tests = [setup, testTaskCycle];
|
|
51
|
+
|
|
52
|
+
export const options = {
|
|
53
|
+
title: import.meta.url,
|
|
54
|
+
};
|
package/tests/src/mod.ts
ADDED
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
import * as EventTests from "./events.tests.js";
|
|
2
|
+
import * as MicrotaskQueueTests from "./microtask.tests.js";
|
|
3
|
+
import * as QuerySelectorTests from "./query_selector.tests.js";
|
|
4
|
+
import * as WcTests from "./wc.tests.js";
|
|
5
|
+
|
|
6
|
+
export const testModules = [
|
|
7
|
+
EventTests,
|
|
8
|
+
MicrotaskQueueTests,
|
|
9
|
+
QuerySelectorTests,
|
|
10
|
+
WcTests,
|
|
11
|
+
];
|
|
@@ -0,0 +1,46 @@
|
|
|
1
|
+
import { QuerySelector } from "../../dist/mod.js";
|
|
2
|
+
|
|
3
|
+
let qs: QuerySelector;
|
|
4
|
+
function setup() {
|
|
5
|
+
qs = new QuerySelector(document.body);
|
|
6
|
+
|
|
7
|
+
document.body.setHTMLUnsafe(`
|
|
8
|
+
<p>
|
|
9
|
+
<span data-first>hello</span>
|
|
10
|
+
<span data-second>hai :3</span>
|
|
11
|
+
</p>
|
|
12
|
+
`);
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
function testQuerySelector() {
|
|
16
|
+
let p = qs.querySelector("p");
|
|
17
|
+
let span = qs.querySelector("[data-second]");
|
|
18
|
+
|
|
19
|
+
if (!p) return "failed to query p";
|
|
20
|
+
if (!span) return "failed to query span";
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
function testQuerySelectorAll() {
|
|
24
|
+
let peas = qs.querySelectorAll("p");
|
|
25
|
+
let spans = qs.querySelectorAll("span");
|
|
26
|
+
|
|
27
|
+
if (!peas.length) return "failed to query peas";
|
|
28
|
+
if (!spans.length) return "failed to query spans";
|
|
29
|
+
if (1 !== peas.length) return `failed to query ${peas.length}/1 peas`;
|
|
30
|
+
if (2 !== spans.length) return `failed to query ${spans.length}/2 spans`;
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
function testDeleteAll() {
|
|
34
|
+
qs.deleteAll();
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
export const tests = [
|
|
38
|
+
setup,
|
|
39
|
+
testQuerySelector,
|
|
40
|
+
testQuerySelectorAll,
|
|
41
|
+
testDeleteAll,
|
|
42
|
+
];
|
|
43
|
+
|
|
44
|
+
export const options = {
|
|
45
|
+
title: import.meta.url,
|
|
46
|
+
};
|
|
@@ -0,0 +1,52 @@
|
|
|
1
|
+
import { Wc } from "../../dist/mod.js";
|
|
2
|
+
|
|
3
|
+
class WcDeclarativeElement extends HTMLElement {
|
|
4
|
+
#wc = new Wc({ host: this });
|
|
5
|
+
|
|
6
|
+
get delcarative(): boolean {
|
|
7
|
+
return this.#wc.declarative;
|
|
8
|
+
}
|
|
9
|
+
}
|
|
10
|
+
|
|
11
|
+
window.customElements.define("declarative-element", WcDeclarativeElement);
|
|
12
|
+
|
|
13
|
+
let testEl: WcDeclarativeElement | undefined;
|
|
14
|
+
let declarativeEl: WcDeclarativeElement | undefined;
|
|
15
|
+
|
|
16
|
+
function setup() {
|
|
17
|
+
document.body.setHTMLUnsafe(`
|
|
18
|
+
<declarative-element></declarative-element>
|
|
19
|
+
<declarative-element data-declarative>
|
|
20
|
+
<template shadowrootmode="open">
|
|
21
|
+
<p>howdy!</p>
|
|
22
|
+
</template>
|
|
23
|
+
</declarative-element>
|
|
24
|
+
`);
|
|
25
|
+
|
|
26
|
+
[testEl, declarativeEl] = document.querySelectorAll<WcDeclarativeElement>(
|
|
27
|
+
"declarative-element",
|
|
28
|
+
);
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
function testDeclarativeShadowDomDoesNotExist() {
|
|
32
|
+
if (!testEl) return "failed to query declarative-element";
|
|
33
|
+
if (testEl.delcarative)
|
|
34
|
+
return "element incorrectly labelled as declarative";
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
function testDeclarativeShadowDomExists() {
|
|
38
|
+
if (!declarativeEl)
|
|
39
|
+
return "failed to query declarative-element with declarative shadow dom";
|
|
40
|
+
if (!declarativeEl.delcarative)
|
|
41
|
+
return "element incorrectly labelled as not declarative";
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
export const tests = [
|
|
45
|
+
setup,
|
|
46
|
+
testDeclarativeShadowDomExists,
|
|
47
|
+
testDeclarativeShadowDomDoesNotExist,
|
|
48
|
+
];
|
|
49
|
+
|
|
50
|
+
export const options = {
|
|
51
|
+
title: import.meta.url,
|
|
52
|
+
};
|
package/dist/bind.d.ts
DELETED
package/dist/bind.js
DELETED
|
@@ -1,14 +0,0 @@
|
|
|
1
|
-
export class Bind {
|
|
2
|
-
constructor(params) {
|
|
3
|
-
let { host, callbacks } = params;
|
|
4
|
-
for (let callback of callbacks) {
|
|
5
|
-
// do not bind and replace already bound functions
|
|
6
|
-
if (callback instanceof Function &&
|
|
7
|
-
!callback.hasOwnProperty("prototype")) {
|
|
8
|
-
let { name } = callback;
|
|
9
|
-
if (!name.startsWith("#"))
|
|
10
|
-
host[name] = callback.bind(host);
|
|
11
|
-
}
|
|
12
|
-
}
|
|
13
|
-
}
|
|
14
|
-
}
|
package/docs/bind.md
DELETED
|
@@ -1,26 +0,0 @@
|
|
|
1
|
-
# Bind Controller
|
|
2
|
-
|
|
3
|
-
Bind functions to objects.
|
|
4
|
-
|
|
5
|
-
This utility is mainly designed to avoid using the constructor.
|
|
6
|
-
|
|
7
|
-
## How to use
|
|
8
|
-
|
|
9
|
-
Add a `Bind` controller to a web component.
|
|
10
|
-
|
|
11
|
-
Add a list of methods on instantiation. The methods cannot be `#private`.
|
|
12
|
-
|
|
13
|
-
```ts
|
|
14
|
-
import { Bind } from "wctk";
|
|
15
|
-
|
|
16
|
-
class MyElement extends HTMLElement {
|
|
17
|
-
#bc = new Bind({
|
|
18
|
-
host: this,
|
|
19
|
-
callbacks: [this.elementCallback],
|
|
20
|
-
};
|
|
21
|
-
|
|
22
|
-
elementCallback(e: KeyboardEvent) {
|
|
23
|
-
// This function can be passed as a callback to event listeners now!
|
|
24
|
-
}
|
|
25
|
-
}
|
|
26
|
-
```
|
package/docs/subscription.md
DELETED
|
@@ -1,85 +0,0 @@
|
|
|
1
|
-
# Subscribe Controller
|
|
2
|
-
|
|
3
|
-
Subscribe web components to external state.
|
|
4
|
-
|
|
5
|
-
## How to use
|
|
6
|
-
|
|
7
|
-
### Callbacks
|
|
8
|
-
|
|
9
|
-
Create functions that subscribe and unsubscribe an element from a data store.
|
|
10
|
-
|
|
11
|
-
The result of the subscribe function is passed as the to the unsubscribe function.
|
|
12
|
-
|
|
13
|
-
```ts
|
|
14
|
-
import { Datastore } from "./some-datastore.js";
|
|
15
|
-
|
|
16
|
-
let store = new Datastore();
|
|
17
|
-
|
|
18
|
-
function subscribe(callback): number {
|
|
19
|
-
return store.subscribe(callback);
|
|
20
|
-
}
|
|
21
|
-
|
|
22
|
-
function unsubscribe(results: number): void {
|
|
23
|
-
store.unsubscribe(results);
|
|
24
|
-
}
|
|
25
|
-
|
|
26
|
-
export { store, subscribe, unsubscribe };
|
|
27
|
-
```
|
|
28
|
-
|
|
29
|
-
### Controller
|
|
30
|
-
|
|
31
|
-
Add a `Subscription` controller to a web component. Pass subscribe, unsubscribe, and a callback function on instantiation.
|
|
32
|
-
|
|
33
|
-
```ts
|
|
34
|
-
import { Subscription } from "wctk";
|
|
35
|
-
import { getState, subscribe, unsubscribe } from "./datastore.js";
|
|
36
|
-
|
|
37
|
-
class MyElement extends HTMLElement {
|
|
38
|
-
#sc = new Subscription({
|
|
39
|
-
host: this,
|
|
40
|
-
callback: this.#update,
|
|
41
|
-
subscribe,
|
|
42
|
-
unsubscribe,
|
|
43
|
-
});
|
|
44
|
-
|
|
45
|
-
#update() {
|
|
46
|
-
let state = getState();
|
|
47
|
-
// do something with state
|
|
48
|
-
}
|
|
49
|
-
|
|
50
|
-
// lifecycle method
|
|
51
|
-
connectedCallback() {
|
|
52
|
-
this.#sc.connect();
|
|
53
|
-
this.#update();
|
|
54
|
-
}
|
|
55
|
-
|
|
56
|
-
// lifecycle method
|
|
57
|
-
disconnectedCallback() {
|
|
58
|
-
this.#sc.disconnect();
|
|
59
|
-
}
|
|
60
|
-
}
|
|
61
|
-
```
|
|
62
|
-
|
|
63
|
-
### Shortcut life cycle methods
|
|
64
|
-
|
|
65
|
-
In the example below, the `connected` property is set to true and the component is immediately subscribed on instantiation.
|
|
66
|
-
|
|
67
|
-
```ts
|
|
68
|
-
import { Subscription } from "wctk";
|
|
69
|
-
import { getState, subscribe, unsubscribe } from "./datastore.js";
|
|
70
|
-
|
|
71
|
-
class MyElement extends HTMLElement {
|
|
72
|
-
#sc = new Subscription({
|
|
73
|
-
host: this,
|
|
74
|
-
callback: this.#update,
|
|
75
|
-
connected: true,
|
|
76
|
-
subscribe,
|
|
77
|
-
unsubscribe,
|
|
78
|
-
});
|
|
79
|
-
|
|
80
|
-
#update() {
|
|
81
|
-
let state = getState();
|
|
82
|
-
// do something with state
|
|
83
|
-
}
|
|
84
|
-
}
|
|
85
|
-
```
|
package/src/bind.ts
DELETED
|
@@ -1,22 +0,0 @@
|
|
|
1
|
-
export interface BindParamsInterface {
|
|
2
|
-
host: Object;
|
|
3
|
-
callbacks: Function[];
|
|
4
|
-
}
|
|
5
|
-
|
|
6
|
-
export class Bind {
|
|
7
|
-
constructor(params: BindParamsInterface) {
|
|
8
|
-
let { host, callbacks } = params;
|
|
9
|
-
|
|
10
|
-
for (let callback of callbacks) {
|
|
11
|
-
// do not bind and replace already bound functions
|
|
12
|
-
if (
|
|
13
|
-
callback instanceof Function &&
|
|
14
|
-
!callback.hasOwnProperty("prototype")
|
|
15
|
-
) {
|
|
16
|
-
let { name } = callback;
|
|
17
|
-
if (!name.startsWith("#"))
|
|
18
|
-
host[name as keyof typeof host] = callback.bind(host);
|
|
19
|
-
}
|
|
20
|
-
}
|
|
21
|
-
}
|
|
22
|
-
}
|