feat: use shadow mode (#39)
This commit is contained in:
parent
d4dcea4503
commit
29fa864ca2
4 changed files with 83 additions and 5 deletions
13
examples/use-shadow/index.html
Normal file
13
examples/use-shadow/index.html
Normal file
|
@ -0,0 +1,13 @@
|
|||
<!doctype html>
|
||||
<html lang="en">
|
||||
<head>
|
||||
<meta charset="UTF-8" />
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
|
||||
<title>WC demo</title>
|
||||
<script type="module" src="./index.js"></script>
|
||||
</head>
|
||||
<body>
|
||||
<h2>With our html</h2>
|
||||
<my-counter></my-counter>
|
||||
</body>
|
||||
</html>
|
55
examples/use-shadow/index.js
Normal file
55
examples/use-shadow/index.js
Normal file
|
@ -0,0 +1,55 @@
|
|||
// @ts-check
|
||||
import { WebComponent, html } from "../../src/index.js";
|
||||
|
||||
export class Counter extends WebComponent {
|
||||
static props = {
|
||||
count: 123,
|
||||
};
|
||||
static shadowRootInit = {
|
||||
mode: "closed",
|
||||
};
|
||||
|
||||
get template() {
|
||||
const list = ["a", "b", "c", "what"];
|
||||
const links = [
|
||||
{
|
||||
url: "https://ayco.io",
|
||||
text: "Ayo Ayco",
|
||||
},
|
||||
{
|
||||
url: "https://ayco.io/gh/McFly",
|
||||
text: "McFly",
|
||||
},
|
||||
];
|
||||
|
||||
return html`
|
||||
<button
|
||||
class="hey"
|
||||
id="btn"
|
||||
onClick=${() => ++this.props.count}
|
||||
style=${{ backgroundColor: "green", color: "white" }}
|
||||
about="Elephant"
|
||||
data-name="thing"
|
||||
aria-name="thingz"
|
||||
>
|
||||
<span>${this.props.count}</span>
|
||||
</button>
|
||||
<form style="margin: 1em 0;">
|
||||
<label data-my-name="Ayo" for="the-input">Name</label>
|
||||
<input id="the-input" type="foo" value="Name:" />
|
||||
</form>
|
||||
${list.map((item) => html`<p>${item}</p>`)}
|
||||
<h3 about="Elephant">Links</h3>
|
||||
<ul>
|
||||
${links.map(
|
||||
(link) =>
|
||||
html`<li>
|
||||
<a href=${link.url} target="_blank">${link.text}</a>
|
||||
</li>`
|
||||
)}
|
||||
</ul>
|
||||
`;
|
||||
}
|
||||
}
|
||||
|
||||
customElements.define("my-counter", Counter);
|
|
@ -1,6 +1,6 @@
|
|||
{
|
||||
"name": "web-component-base",
|
||||
"version": "2.1.0-beta.1",
|
||||
"version": "2.1.0-beta.2",
|
||||
"description": "A zero-dependency & tiny JS base class for creating reactive custom elements easily",
|
||||
"type": "module",
|
||||
"exports": {
|
||||
|
|
|
@ -38,6 +38,12 @@ export class WebComponent extends HTMLElement {
|
|||
return "";
|
||||
}
|
||||
|
||||
/**
|
||||
* Shadow root initialization options
|
||||
* @type {ShadowRootInit}
|
||||
*/
|
||||
static shadowRootInit;
|
||||
|
||||
/**
|
||||
* Read-only property containing camelCase counterparts of observed attributes.
|
||||
* @see https://www.npmjs.com/package/web-component-base#prop-access
|
||||
|
@ -146,7 +152,7 @@ export class WebComponent extends HTMLElement {
|
|||
throw TypeError(
|
||||
`Cannot assign ${typeof value} to ${
|
||||
typeMap[prop]
|
||||
} property (setting '${prop}' of ${meta.constructor.name})`,
|
||||
} property (setting '${prop}' of ${meta.constructor.name})`
|
||||
);
|
||||
} else if (oldValue !== value) {
|
||||
obj[prop] = value;
|
||||
|
@ -178,7 +184,7 @@ export class WebComponent extends HTMLElement {
|
|||
if (!this.#props) {
|
||||
this.#props = new Proxy(
|
||||
initialProps,
|
||||
this.#handler((key, value) => this.setAttribute(key, value), this),
|
||||
this.#handler((key, value) => this.setAttribute(key, value), this)
|
||||
);
|
||||
}
|
||||
}
|
||||
|
@ -188,14 +194,18 @@ export class WebComponent extends HTMLElement {
|
|||
if (typeof this.template === "string") {
|
||||
this.innerHTML = this.template;
|
||||
} else if (typeof this.template === "object") {
|
||||
let host = this;
|
||||
if (this.constructor.shadowRootInit) {
|
||||
host = this.attachShadow(this.constructor.shadowRootInit);
|
||||
}
|
||||
const tree = this.template;
|
||||
|
||||
// TODO: smart diffing
|
||||
if (JSON.stringify(this.#prevDOM) !== JSON.stringify(tree)) {
|
||||
const el = createElement(tree);
|
||||
if (el) {
|
||||
if (Array.isArray(el)) this.replaceChildren(...el);
|
||||
else this.replaceChildren(el);
|
||||
if (Array.isArray(el)) host.replaceChildren(...el);
|
||||
else host.replaceChildren(el);
|
||||
}
|
||||
this.#prevDOM = tree;
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue