feat: support objects in props
This commit is contained in:
parent
d6755dd9e3
commit
d7651b5f33
17 changed files with 59 additions and 47 deletions
|
@ -1,5 +1,5 @@
|
||||||
// @ts-check
|
// @ts-check
|
||||||
import WebComponent from "../../src/WebComponent.js";
|
import { WebComponent } from "../../src/WebComponent.js";
|
||||||
import { attachEffect } from "../../src/attach-effect.js";
|
import { attachEffect } from "../../src/attach-effect.js";
|
||||||
|
|
||||||
export class Counter extends WebComponent {
|
export class Counter extends WebComponent {
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
// @ts-check
|
// @ts-check
|
||||||
import WebComponent from "../../src/WebComponent.js";
|
import { WebComponent } from "../../src/WebComponent.js";
|
||||||
import { attachEffect } from "../../src/attach-effect.js";
|
import { attachEffect } from "../../src/attach-effect.js";
|
||||||
|
|
||||||
export class Decrease extends WebComponent {
|
export class Decrease extends WebComponent {
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
import WebComponent from "../../src/WebComponent.js";
|
import { WebComponent } from "../../src/WebComponent.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/WebComponent.js";
|
import { WebComponent } from "../../src/WebComponent.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/WebComponent.js";
|
import { WebComponent } from "../../src/WebComponent.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/WebComponent.js";
|
import { WebComponent } from "../../src/WebComponent.js";
|
||||||
|
|
||||||
class SimpleText extends WebComponent {
|
class SimpleText extends WebComponent {
|
||||||
clickCallback() {
|
clickCallback() {
|
||||||
|
|
|
@ -10,7 +10,7 @@
|
||||||
}
|
}
|
||||||
</style>
|
</style>
|
||||||
<script type="module">
|
<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
|
* @see https://ayco.io/n/web-component-base
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
// @ts-check
|
// @ts-check
|
||||||
import WebComponent from "../../src/WebComponent.js";
|
import { WebComponent } from "../../src/WebComponent.js";
|
||||||
|
|
||||||
export class Counter extends WebComponent {
|
export class Counter extends WebComponent {
|
||||||
static properties = ["count"];
|
static properties = ["count"];
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
import WebComponent from "../../src/WebComponent.js";
|
import { WebComponent } from "../../src/WebComponent.js";
|
||||||
|
|
||||||
export class HelloWorld extends WebComponent {
|
export class HelloWorld extends WebComponent {
|
||||||
static properties = ["name"];
|
static properties = ["name"];
|
||||||
|
|
|
@ -1,14 +1,18 @@
|
||||||
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() {
|
onInit() {
|
||||||
this.props.object = {
|
this.props.object = {
|
||||||
hello: 'world'
|
hello: 'world',
|
||||||
|
age: 2
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
onChanges() {
|
||||||
|
console.log('>>> object', this.props.object)
|
||||||
|
}
|
||||||
get template() {
|
get template() {
|
||||||
return `<textarea>${this.props.object}</textarea>`;
|
return `<textarea>${JSON.stringify(this.props.object)}</textarea>`;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
// @ts-check
|
// @ts-check
|
||||||
import WebComponent from "../../src/WebComponent.js";
|
import { WebComponent } from "../../src/WebComponent.js";
|
||||||
|
|
||||||
export class Toggle extends WebComponent {
|
export class Toggle extends WebComponent {
|
||||||
static properties = ["toggle"];
|
static properties = ["toggle"];
|
||||||
|
|
|
@ -18,7 +18,7 @@
|
||||||
<div>
|
<div>
|
||||||
Counter: <my-counter></my-counter>
|
Counter: <my-counter></my-counter>
|
||||||
</div>
|
</div>
|
||||||
<!-- <div>
|
<div>
|
||||||
Toggle: <my-toggle></my-toggle>
|
Toggle: <my-toggle></my-toggle>
|
||||||
</div>
|
</div>
|
||||||
<div>
|
<div>
|
||||||
|
@ -26,6 +26,6 @@
|
||||||
</div>
|
</div>
|
||||||
<div>
|
<div>
|
||||||
Object: <my-object />
|
Object: <my-object />
|
||||||
</div> -->
|
</div>
|
||||||
</body>
|
</body>
|
||||||
</html>
|
</html>
|
||||||
|
|
11
package.json
11
package.json
|
@ -1,6 +1,6 @@
|
||||||
{
|
{
|
||||||
"name": "web-component-base",
|
"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",
|
"description": "A zero-dependency, ~600 Bytes (minified & gzipped), JS base class for creating reactive custom elements easily",
|
||||||
"type": "module",
|
"type": "module",
|
||||||
"exports": {
|
"exports": {
|
||||||
|
@ -12,14 +12,15 @@
|
||||||
"types": "./WebComponent.d.ts",
|
"types": "./WebComponent.d.ts",
|
||||||
"import": "./WebComponent.js"
|
"import": "./WebComponent.js"
|
||||||
},
|
},
|
||||||
|
"./attach-effect": {
|
||||||
|
"types": "./attach-effect.d.ts",
|
||||||
|
"import": "./attach-effect.js"
|
||||||
|
},
|
||||||
"./WebComponent.min.js": {
|
"./WebComponent.min.js": {
|
||||||
"types": "./WebComponent.d.ts",
|
"types": "./WebComponent.d.ts",
|
||||||
"import": "./WebComponent.min.js"
|
"import": "./WebComponent.min.js"
|
||||||
},
|
},
|
||||||
"./attach-effect": {
|
"./package.json": "./package.json"
|
||||||
"types": "./attach-effect.d.ts",
|
|
||||||
"import": "./attach-effect.js"
|
|
||||||
}
|
|
||||||
},
|
},
|
||||||
"scripts": {
|
"scripts": {
|
||||||
"start": "npx simple-server .",
|
"start": "npx simple-server .",
|
||||||
|
|
|
@ -3,7 +3,7 @@
|
||||||
<head>
|
<head>
|
||||||
<title>WC Base Test</title>
|
<title>WC Base Test</title>
|
||||||
<script type="module">
|
<script type="module">
|
||||||
import WebComponent from "./src/WebComponent.js";
|
import { WebComponent } from "./src/WebComponent.js";
|
||||||
|
|
||||||
class HelloWorld extends WebComponent {
|
class HelloWorld extends WebComponent {
|
||||||
static properties = ["my-name"];
|
static properties = ["my-name"];
|
||||||
|
|
|
@ -57,7 +57,7 @@
|
||||||
<p>The result is a reactive UI on property changes: <my-counter></my-counter></p>
|
<p>The result is a reactive UI on property changes: <my-counter></my-counter></p>
|
||||||
<code-block language="js">
|
<code-block language="js">
|
||||||
<pre>
|
<pre>
|
||||||
import WebComponent from "https://unpkg.com/web-component-base@1.13.0/WebComponent.min.js";
|
import { WebComponent } from "https://unpkg.com/web-component-base@1.13.0/WebComponent.min.js";
|
||||||
|
|
||||||
export class Counter extends WebComponent {
|
export class Counter extends WebComponent {
|
||||||
static properties = ["count"];
|
static properties = ["count"];
|
||||||
|
|
|
@ -93,7 +93,7 @@ export class WebComponent extends HTMLElement {
|
||||||
|
|
||||||
if (previousValue !== currentValue) {
|
if (previousValue !== currentValue) {
|
||||||
this[property] = currentValue === "" || currentValue;
|
this[property] = currentValue === "" || currentValue;
|
||||||
this[camelCaps] = this[property]; // remove on v2
|
this[camelCaps] = this[property];
|
||||||
|
|
||||||
this.#handleUpdateProp(camelCaps, this[property]);
|
this.#handleUpdateProp(camelCaps, this[property]);
|
||||||
|
|
||||||
|
@ -102,10 +102,9 @@ export class WebComponent extends HTMLElement {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#handleUpdateProp(key, value) {
|
#handleUpdateProp(key, stringifiedValue) {
|
||||||
const restored = this.#restoreType(value, this.#typeMap[key]);
|
const restored = this.#deserialize(stringifiedValue, this.#typeMap[key]);
|
||||||
|
if (restored !== this.props[key]) this.props[key] = restored;
|
||||||
if (restored !== this.props[key]) this.props[key] = value;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#getCamelCaps(kebab) {
|
#getCamelCaps(kebab) {
|
||||||
|
@ -113,19 +112,6 @@ export class WebComponent extends HTMLElement {
|
||||||
}
|
}
|
||||||
|
|
||||||
#typeMap = {};
|
#typeMap = {};
|
||||||
|
|
||||||
#restoreType = (value, type) => {
|
|
||||||
switch (type) {
|
|
||||||
case "string":
|
|
||||||
return value;
|
|
||||||
case "number":
|
|
||||||
case "boolean":
|
|
||||||
return JSON.parse(value);
|
|
||||||
default:
|
|
||||||
return value;
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
#effectsMap = {};
|
#effectsMap = {};
|
||||||
|
|
||||||
#handler(setter, meta) {
|
#handler(setter, meta) {
|
||||||
|
@ -151,12 +137,12 @@ export class WebComponent extends HTMLElement {
|
||||||
effectsMap[prop] = [];
|
effectsMap[prop] = [];
|
||||||
}
|
}
|
||||||
effectsMap[prop].push(value.callback);
|
effectsMap[prop].push(value.callback);
|
||||||
console.log('>>> ', Object.getPrototypeOf(obj[prop]).prop)
|
|
||||||
} else if (oldValue !== value) {
|
} else if (oldValue !== value) {
|
||||||
obj[prop] = value;
|
obj[prop] = value;
|
||||||
effectsMap[prop]?.forEach((f) => f(value));
|
effectsMap[prop]?.forEach((f) => f(value));
|
||||||
const kebab = getKebab(prop);
|
const kebab = getKebab(prop);
|
||||||
setter(kebab, value);
|
|
||||||
|
setter(kebab, meta.#serialize(value));
|
||||||
}
|
}
|
||||||
|
|
||||||
return true;
|
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() {
|
#initializeProps() {
|
||||||
if (!this.#props) {
|
if (!this.#props) {
|
||||||
this.#props = new Proxy(
|
this.#props = new Proxy(
|
||||||
|
@ -181,5 +190,3 @@ export class WebComponent extends HTMLElement {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
export default WebComponent;
|
|
||||||
|
|
|
@ -1,2 +1,2 @@
|
||||||
export {attachEffect} from './attach-effect.js';
|
export { attachEffect } from "./attach-effect.js";
|
||||||
export {default as WebComponent} from './WebComponent.js';
|
export { WebComponent } from "./WebComponent.js";
|
||||||
|
|
Loading…
Reference in a new issue