It provides a minimum utility interface for the creation of web-components.
class BaseElement extends HTMLElement {
/**
* captures the properties defined in `static attributes`;
*/
props: Properties;
/**
* resolves once the component has been mounted to the document
*/
mounted: Promise<void>;
/**
* resolves once the component has been unmounted from the document.
*/
unmounted: Promise<void>;
/**
* defines the observables as properties and attributes of the component
*/
static observables: Observables;
/**
* validates the `value` which is then delivered to the` update({[name]:value})` method.
*/
setProperty(name: string, value: Values): void;
/**
* dispatches every time `setProperty` is successfully executed
*/
update(props: Properties): void;
}
This class is used by @atomico/element to use @atomico/core as web-component.
base-element
, allows to create HTMLElements under other libraries, similar to what it does Skatejs, but less code.
defines the observables as property and attribute of the component
class CustomElement extends Element {
static Observables = {
fieldString: String, // [field-string]
fieldNumber: Number, // [field-number]
fieldBoolean: Boolean, // [field-boolean]
fieldObject: Object, // [field-object]
fieldArray: Array // [field-array],
fieldFunction:Function // [field-function]
};
}
the attributes force the type of the variable, so if you define an attribute as Object
, it will apply
JSON.parse
to a string type value, to read its type.
// set property, remember that to apply this WC, you must already be registered
myCustomElement.fieldArray = [];
// set attribute, more benefit using setAttribute, since it allows a deferred loading of the WC
myCustomElement.setAttribute("field-array", []);
import { render, html } from "lit-html";
import Element from "@atomico/base-element";
export default class extends Element {
contructor() {
super();
this.attachShadow({ mode: "open" });
this.props = {};
this.update();
}
async update(props) {
this.props = { ...this.props, ...props };
if (this.prevent) return;
this.prevent = true;
await this.mounted;
this.prevent = false;
render(this.render(this.props), this.shadowRoot);
}
}
import { render, h } from "preact";
import Element from "@atomico/base-element";
export default class extends Element {
contructor() {
super();
this.attachShadow({ mode: "open" });
this.props = {};
this.render = this.render.bind(this);
this.unmounted.then(() => render("", this.shadowRoot));
this.update();
}
async update(props) {
this.props = { ...this.props, ...props };
if (this.prevent) return;
this.prevent = true;
await this.mounted;
this.prevent = false;
render(h(this.render, this.props), this.shadowRoot);
}
}
import Element from "@atomico/base-element";
export default class extends Element {
contructor() {
super();
this.attachShadow({ mode: "open" });
this.props = {};
this.update();
}
async update(props) {
this.props = { ...this.props, ...props };
if (this.prevent) return;
this.prevent = true;
await this.mounted;
this.prevent = false;
let nextHTML = this.render(this.props);
if (nextHTML !== this.shadowRoot.innerHTML) {
this.shadowRoot.innerHTML = nextHTML;
}
}
}