@thi.ng/rdom
Version:
Lightweight, reactive, VDOM-less UI/DOM components with async lifecycle and @thi.ng/hiccup compatible
76 lines (75 loc) • 2.05 kB
JavaScript
import { assert } from "@thi.ng/errors/assert";
import { $compile } from "./compile.js";
import { Component } from "./component.js";
import { __nextID } from "./idgen.js";
import { $subWithID } from "./sub.js";
import { $wrapText } from "./wrap.js";
const $switch = (src, keyFn, ctors, error, loader) => $subWithID(
src,
new Switch(keyFn, ctors, error, loader),
__nextID("switch", src)
);
const $refresh = (src, ctor, error, loader) => $subWithID(
src,
new Switch(() => 0, { 0: ctor }, error, loader),
__nextID("refresh", src)
);
class Switch extends Component {
constructor(keyFn, ctors, error = async (e) => $wrapText("span", {}, e), loader = async () => $wrapText("span", {
hidden: true
})) {
super();
this.keyFn = keyFn;
this.ctors = ctors;
this.error = error;
this.loader = loader;
}
val;
parent;
inner;
index;
async mount(parent, index, val) {
this.parent = parent;
this.index = index;
await this.update(val);
return this.inner.el;
}
async unmount() {
this.inner && await this.inner.unmount();
this.val = void 0;
this.parent = void 0;
this.inner = void 0;
}
async update(val) {
this.inner && await this.inner.unmount();
this.inner = void 0;
if (val != null) {
this.val = val;
let loader;
if (this.loader) {
loader = $compile(await this.loader(val));
await loader.mount(this.parent, this.index);
}
try {
const key = this.keyFn(val);
const next = this.ctors[key];
assert(!!next, `missing component for key: ${key}`);
this.inner = $compile(await next(val));
loader && await loader.unmount();
} catch (e) {
if (this.error) {
this.inner = $compile(await this.error(e));
loader && await loader.unmount();
}
}
} else {
this.loader && (this.inner = $compile(await this.loader(val)));
}
this.inner && await this.inner.mount(this.parent, this.index);
}
}
export {
$refresh,
$switch,
Switch
};