rvx
Version:
A signal based rendering library
86 lines (81 loc) • 2.32 kB
JavaScript
/*!
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU Affero General Public License as
published by the Free Software Foundation, either version 3 of the
License, or (at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU Affero General Public License for more details.
You should have received a copy of the GNU Affero General Public License
along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
import { ENV, $, leak, watchUpdates, capture, render } from './rvx.js';
const moduleEnv = ENV.current;
class RvxElement extends moduleEnv.HTMLElement {
static observedAttributes;
#signals = new Map();
#startTrigger;
#disposeTrigger;
#shadow;
#dispose;
constructor(options) {
super();
this.#startTrigger = options?.start ?? "on-connect";
this.#disposeTrigger = options?.dispose ?? "on-disconnect";
const shadowInit = (options?.shadow === true ? undefined : options?.shadow) ?? { mode: "open" };
if (shadowInit !== false) {
this.#shadow = this.attachShadow(shadowInit);
}
}
reflect(name) {
let signal = this.#signals.get(name);
if (signal === undefined) {
signal = $(this.getAttribute(name));
this.#signals.set(name, signal);
leak(() => {
watchUpdates(signal, value => {
if (value === null) {
this.removeAttribute(name);
}
else {
this.setAttribute(name, value);
}
});
});
}
return signal;
}
start() {
if (this.#dispose === undefined) {
this.#dispose = capture(() => {
ENV.provide(moduleEnv, () => {
const parent = this.#shadow ?? this;
parent.innerHTML = "";
render(this.render()).appendTo(parent);
});
});
}
}
dispose() {
this.#dispose?.();
this.#dispose = undefined;
}
connectedCallback() {
if (this.#startTrigger === "on-connect") {
this.start();
}
}
disconnectedCallback() {
if (this.#disposeTrigger === "on-disconnect") {
this.dispose();
}
}
attributeChangedCallback(name, oldValue, newValue) {
const signal = this.#signals.get(name);
if (signal !== undefined) {
signal.value = newValue;
}
}
}
export { RvxElement };