feat: props blueprint (#8)
This commit is contained in:
parent
000e3811cd
commit
00648883fa
12 changed files with 78 additions and 16 deletions
|
@ -1,5 +1,5 @@
|
||||||
// @ts-check
|
// @ts-check
|
||||||
import { WebComponent, attachEffect } from "../../src/";
|
import { WebComponent, attachEffect } from "../../src/index.js";
|
||||||
export class Counter extends WebComponent {
|
export class Counter extends WebComponent {
|
||||||
static properties = ["count"];
|
static properties = ["count"];
|
||||||
onInit() {
|
onInit() {
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
// @ts-check
|
// @ts-check
|
||||||
import { WebComponent, attachEffect } from "../../src/";
|
import { WebComponent, attachEffect } from "../../src/index.js";
|
||||||
|
|
||||||
export class Decrease extends WebComponent {
|
export class Decrease extends WebComponent {
|
||||||
static properties = ["count"];
|
static properties = ["count"];
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
import { WebComponent } from "../../src";
|
import { WebComponent } from "../../src/index.js"
|
||||||
|
|
||||||
export class BooleanPropTest extends WebComponent {
|
export class BooleanPropTest extends WebComponent {
|
||||||
static properties = ["is-inline", "anotherone"];
|
static properties = ["is-inline", "anotherone"];
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
// @ts-check
|
// @ts-check
|
||||||
import { WebComponent } from "../../src";
|
import { WebComponent } from "../../src/index.js"
|
||||||
|
|
||||||
export class Counter extends WebComponent {
|
export class Counter extends WebComponent {
|
||||||
static properties = ["count"];
|
static properties = ["count"];
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
// @ts-check
|
// @ts-check
|
||||||
import { WebComponent } from "../../src";
|
import { WebComponent } from "../../src/index.js"
|
||||||
|
|
||||||
export class HelloWorld extends WebComponent {
|
export class HelloWorld extends WebComponent {
|
||||||
static properties = ["count", "emotion"];
|
static properties = ["count", "emotion"];
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
// @ts-check
|
// @ts-check
|
||||||
import { WebComponent } from "../../src"
|
import { WebComponent } from "../../src/index.js"
|
||||||
|
|
||||||
class SimpleText extends WebComponent {
|
class SimpleText extends WebComponent {
|
||||||
clickCallback() {
|
clickCallback() {
|
||||||
|
|
12
examples/props-blueprint/hello-world.js
Normal file
12
examples/props-blueprint/hello-world.js
Normal file
|
@ -0,0 +1,12 @@
|
||||||
|
import { WebComponent } from "../../src/index.js";
|
||||||
|
|
||||||
|
export class HelloWorld extends WebComponent {
|
||||||
|
static props = {
|
||||||
|
myName: 'World',
|
||||||
|
};
|
||||||
|
get template() {
|
||||||
|
return `<p>Hello ${this.props.myName}</p>`;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
customElements.define("hello-world", HelloWorld);
|
14
examples/props-blueprint/index.html
Normal file
14
examples/props-blueprint/index.html
Normal file
|
@ -0,0 +1,14 @@
|
||||||
|
<!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>
|
||||||
|
<script type="module" src="./hello-world.js"></script>
|
||||||
|
</head>
|
||||||
|
<body>
|
||||||
|
<my-counter></my-counter>
|
||||||
|
<hello-world></hello-world>
|
||||||
|
</body>
|
||||||
|
</html>
|
15
examples/props-blueprint/index.js
Normal file
15
examples/props-blueprint/index.js
Normal file
|
@ -0,0 +1,15 @@
|
||||||
|
import { WebComponent } from "../../src/index.js";
|
||||||
|
|
||||||
|
export class Counter extends WebComponent {
|
||||||
|
static props = {
|
||||||
|
count: 123,
|
||||||
|
};
|
||||||
|
onInit() {
|
||||||
|
this.onclick = () => ++this.props.count;
|
||||||
|
}
|
||||||
|
get template() {
|
||||||
|
return `<button id="btn">${this.props.count}</button>`;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
customElements.define("my-counter", Counter);
|
|
@ -1,12 +1,12 @@
|
||||||
import { WebComponent } from "../../src/WebComponent.js";
|
import { WebComponent } from "../../src/WebComponent.js";
|
||||||
|
|
||||||
export class ObjectText extends WebComponent {
|
export class ObjectText extends WebComponent {
|
||||||
static properties = ["object"];
|
// static properties = ["object"];
|
||||||
onInit() {
|
static props = {
|
||||||
this.props.object = {
|
object: {
|
||||||
hello: 'worldzz',
|
hello: 'worldzz',
|
||||||
age: 2
|
age: 2
|
||||||
};
|
}
|
||||||
}
|
}
|
||||||
onChanges() {
|
onChanges() {
|
||||||
console.log('>>> object', this.props.object)
|
console.log('>>> object', this.props.object)
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
{
|
{
|
||||||
"name": "web-component-base",
|
"name": "web-component-base",
|
||||||
"version": "2.0.0-beta.4",
|
"version": "2.0.0-beta.6",
|
||||||
"description": "A zero-dependency, ~600 Bytes (minified & gzipped), JS base class for creating reactive custom elements easily",
|
"description": "A zero-dependency, ~600 Bytes (minified & gzipped), JS base class for creating reactive custom elements easily",
|
||||||
"type": "module",
|
"type": "module",
|
||||||
"exports": {
|
"exports": {
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
import { getKebabCase, getCamelCase, serialize, deserialize } from "./utils";
|
import { getKebabCase, getCamelCase, serialize, deserialize } from "./utils/index.js";
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* A minimal base class to reduce the complexity of creating reactive custom elements
|
* A minimal base class to reduce the complexity of creating reactive custom elements
|
||||||
|
@ -13,6 +13,11 @@ export class WebComponent extends HTMLElement {
|
||||||
*/
|
*/
|
||||||
static properties = [];
|
static properties = [];
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Blueprint for the Proxy props
|
||||||
|
*/
|
||||||
|
static props;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Read-only string property that represents how the component will be rendered
|
* Read-only string property that represents how the component will be rendered
|
||||||
* @returns {string | Node | (string | Node)[]}
|
* @returns {string | Node | (string | Node)[]}
|
||||||
|
@ -74,7 +79,14 @@ export class WebComponent extends HTMLElement {
|
||||||
}
|
}
|
||||||
|
|
||||||
static get observedAttributes() {
|
static get observedAttributes() {
|
||||||
return this.properties;
|
const propKeys = this.props ? Object.keys(this.props).map(camelCase => getKebabCase(camelCase)) : [];
|
||||||
|
|
||||||
|
return [...(
|
||||||
|
new Set([
|
||||||
|
...this.properties,
|
||||||
|
...propKeys
|
||||||
|
])
|
||||||
|
)]
|
||||||
}
|
}
|
||||||
|
|
||||||
connectedCallback() {
|
connectedCallback() {
|
||||||
|
@ -147,9 +159,18 @@ export class WebComponent extends HTMLElement {
|
||||||
}
|
}
|
||||||
|
|
||||||
#initializeProps() {
|
#initializeProps() {
|
||||||
|
let initialProps = {}
|
||||||
|
if(this.constructor.props) {
|
||||||
|
initialProps = this.constructor.props;
|
||||||
|
Object.keys(initialProps).forEach(camelCase => {
|
||||||
|
const value = initialProps[camelCase]
|
||||||
|
this.#typeMap[camelCase] = typeof value
|
||||||
|
this.setAttribute(getKebabCase(camelCase), serialize(value))
|
||||||
|
})
|
||||||
|
}
|
||||||
if (!this.#props) {
|
if (!this.#props) {
|
||||||
this.#props = new Proxy(
|
this.#props = new Proxy(
|
||||||
{},
|
initialProps,
|
||||||
this.#handler((key, value) => this.setAttribute(key, value), this)
|
this.#handler((key, value) => this.setAttribute(key, value), this)
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in a new issue