UNPKG

rvx

Version:

A signal based rendering library

86 lines (81 loc) 2.32 kB
/*! 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 };