feat: support objects in props

This commit is contained in:
Ayo 2023-12-07 17:30:53 +01:00
parent d6755dd9e3
commit d7651b5f33
17 changed files with 59 additions and 47 deletions

View file

@ -1,5 +1,5 @@
// @ts-check
import WebComponent from "../../src/WebComponent.js";
import { WebComponent } from "../../src/WebComponent.js";
import { attachEffect } from "../../src/attach-effect.js";
export class Counter extends WebComponent {

View file

@ -1,5 +1,5 @@
// @ts-check
import WebComponent from "../../src/WebComponent.js";
import { WebComponent } from "../../src/WebComponent.js";
import { attachEffect } from "../../src/attach-effect.js";
export class Decrease extends WebComponent {

View file

@ -1,4 +1,4 @@
import WebComponent from "../../src/WebComponent.js";
import { WebComponent } from "../../src/WebComponent.js";
export class BooleanPropTest extends WebComponent {
static properties = ["is-inline", "anotherone"];

View file

@ -1,5 +1,5 @@
// @ts-check
import WebComponent from "../../src/WebComponent.js";
import { WebComponent } from "../../src/WebComponent.js";
export class Counter extends WebComponent {
static properties = ["count"];

View file

@ -1,5 +1,5 @@
// @ts-check
import WebComponent from "../../src/WebComponent.js";
import { WebComponent } from "../../src/WebComponent.js";
export class HelloWorld extends WebComponent {
static properties = ["count", "emotion"];

View file

@ -1,5 +1,5 @@
// @ts-check
import WebComponent from "../../src/WebComponent.js";
import { WebComponent } from "../../src/WebComponent.js";
class SimpleText extends WebComponent {
clickCallback() {

View file

@ -10,7 +10,7 @@
}
</style>
<script type="module">
import WebComponent from "https://unpkg.com/web-component-base@1.13.3/WebComponent.min.js";
import { WebComponent } from "https://unpkg.com/web-component-base@1.13.3/WebComponent.min.js";
/**
* @see https://ayco.io/n/web-component-base

View file

@ -1,5 +1,5 @@
// @ts-check
import WebComponent from "../../src/WebComponent.js";
import { WebComponent } from "../../src/WebComponent.js";
export class Counter extends WebComponent {
static properties = ["count"];

View file

@ -1,4 +1,4 @@
import WebComponent from "../../src/WebComponent.js";
import { WebComponent } from "../../src/WebComponent.js";
export class HelloWorld extends WebComponent {
static properties = ["name"];

View file

@ -1,14 +1,18 @@
import WebComponent from "../../src/WebComponent.js";
import { WebComponent } from "../../src/WebComponent.js";
export class ObjectText extends WebComponent {
static properties = ["object"];
onInit() {
this.props.object = {
hello: 'world'
hello: 'world',
age: 2
};
}
onChanges() {
console.log('>>> object', this.props.object)
}
get template() {
return `<textarea>${this.props.object}</textarea>`;
return `<textarea>${JSON.stringify(this.props.object)}</textarea>`;
}
}

View file

@ -1,5 +1,5 @@
// @ts-check
import WebComponent from "../../src/WebComponent.js";
import { WebComponent } from "../../src/WebComponent.js";
export class Toggle extends WebComponent {
static properties = ["toggle"];

View file

@ -18,7 +18,7 @@
<div>
Counter: <my-counter></my-counter>
</div>
<!-- <div>
<div>
Toggle: <my-toggle></my-toggle>
</div>
<div>
@ -26,6 +26,6 @@
</div>
<div>
Object: <my-object />
</div> -->
</div>
</body>
</html>

View file

@ -1,6 +1,6 @@
{
"name": "web-component-base",
"version": "2.0.0-beta",
"version": "2.0.0-beta.1",
"description": "A zero-dependency, ~600 Bytes (minified & gzipped), JS base class for creating reactive custom elements easily",
"type": "module",
"exports": {
@ -12,14 +12,15 @@
"types": "./WebComponent.d.ts",
"import": "./WebComponent.js"
},
"./attach-effect": {
"types": "./attach-effect.d.ts",
"import": "./attach-effect.js"
},
"./WebComponent.min.js": {
"types": "./WebComponent.d.ts",
"import": "./WebComponent.min.js"
},
"./attach-effect": {
"types": "./attach-effect.d.ts",
"import": "./attach-effect.js"
}
"./package.json": "./package.json"
},
"scripts": {
"start": "npx simple-server .",

View file

@ -3,7 +3,7 @@
<head>
<title>WC Base Test</title>
<script type="module">
import WebComponent from "./src/WebComponent.js";
import { WebComponent } from "./src/WebComponent.js";
class HelloWorld extends WebComponent {
static properties = ["my-name"];

View file

@ -57,7 +57,7 @@
<p>The result is a reactive UI on property changes: <my-counter></my-counter></p>
<code-block language="js">
<pre>
import WebComponent from &quot;https://unpkg.com/web-component-base@1.13.0/WebComponent.min.js&quot;;
import { WebComponent } from &quot;https://unpkg.com/web-component-base@1.13.0/WebComponent.min.js&quot;;
export class Counter extends WebComponent {
static properties = [&quot;count&quot;];

View file

@ -93,7 +93,7 @@ export class WebComponent extends HTMLElement {
if (previousValue !== currentValue) {
this[property] = currentValue === "" || currentValue;
this[camelCaps] = this[property]; // remove on v2
this[camelCaps] = this[property];
this.#handleUpdateProp(camelCaps, this[property]);
@ -102,10 +102,9 @@ export class WebComponent extends HTMLElement {
}
}
#handleUpdateProp(key, value) {
const restored = this.#restoreType(value, this.#typeMap[key]);
if (restored !== this.props[key]) this.props[key] = value;
#handleUpdateProp(key, stringifiedValue) {
const restored = this.#deserialize(stringifiedValue, this.#typeMap[key]);
if (restored !== this.props[key]) this.props[key] = restored;
}
#getCamelCaps(kebab) {
@ -113,19 +112,6 @@ export class WebComponent extends HTMLElement {
}
#typeMap = {};
#restoreType = (value, type) => {
switch (type) {
case "string":
return value;
case "number":
case "boolean":
return JSON.parse(value);
default:
return value;
}
};
#effectsMap = {};
#handler(setter, meta) {
@ -151,12 +137,12 @@ export class WebComponent extends HTMLElement {
effectsMap[prop] = [];
}
effectsMap[prop].push(value.callback);
console.log('>>> ', Object.getPrototypeOf(obj[prop]).prop)
} else if (oldValue !== value) {
obj[prop] = value;
effectsMap[prop]?.forEach((f) => f(value));
const kebab = getKebab(prop);
setter(kebab, value);
setter(kebab, meta.#serialize(value));
}
return true;
@ -172,6 +158,29 @@ export class WebComponent extends HTMLElement {
};
}
#deserialize(value, type){
switch (type) {
case 'number':
case 'boolean':
case 'object':
case 'undefined':
return JSON.parse(value);
default:
return value;
}
};
#serialize(value) {
switch(typeof value) {
case 'number':
case 'boolean':
case 'object':
case 'undefined':
return JSON.stringify(value);
default: return value;
}
}
#initializeProps() {
if (!this.#props) {
this.#props = new Proxy(
@ -181,5 +190,3 @@ export class WebComponent extends HTMLElement {
}
}
}
export default WebComponent;

View file

@ -1,2 +1,2 @@
export {attachEffect} from './attach-effect.js';
export {default as WebComponent} from './WebComponent.js';
export { attachEffect } from "./attach-effect.js";
export { WebComponent } from "./WebComponent.js";