@atomico/base-element
It provides a minimum utility interface for the creation of web-components.
class BaseElement extends HTMLElement {
props: Properties;
mounted: Promise<void>;
unmounted: Promise<void>;
static observables: Observables;
setProperty(name: string, value: Values): void;
update(props: Properties): void;
}
This class is used by @atomico/element to use @atomico/core as web-component.
Objective
base-element
, allows to create HTMLElements under other libraries, similar to what it does Skatejs, but less code.
Observables
defines the observables as property and attribute of the component
class CustomElement extends Element {
static Observables = {
fieldString: String,
fieldNumber: Number,
fieldBoolean: Boolean,
fieldObject: Object,
fieldArray: Array
fieldFunction: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.
myCustomElement.fieldArray = [];
myCustomElement.setAttribute("field-array", []);
Example with lit-html
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);
}
}
Example with preact
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);
}
}
Example with innerHTML
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;
}
}
}