feat: props blueprint (#8)

This commit is contained in:
Ayo Ayco 2023-12-08 18:00:40 +01:00 committed by GitHub
parent 000e3811cd
commit 00648883fa
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
12 changed files with 78 additions and 16 deletions

View file

@ -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() {

View file

@ -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"];

View file

@ -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"];

View file

@ -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"];

View file

@ -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"];

View file

@ -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() {

View 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);

View 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>

View 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);

View file

@ -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)

View file

@ -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": {

View file

@ -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)
); );
} }