@thi.ng/rdom
Version:
Lightweight, reactive, VDOM-less UI/DOM components with async lifecycle and @thi.ng/hiccup compatible
85 lines (84 loc) • 2.14 kB
JavaScript
import { isString } from "@thi.ng/checks/is-string";
import { $compile } from "./compile.js";
import { Component } from "./component.js";
import { __nextID } from "./idgen.js";
import { __initList } from "./internal/list.js";
import { $subWithID } from "./sub.js";
const $list = (src, opts) => $subWithID(src, new List(opts), __nextID("list", src));
class List extends Component {
constructor(opts) {
super();
this.opts = opts;
}
opts;
prev;
items;
anchor;
offset = 0;
numChildren = -1;
async mount(parent, index, state) {
this.prev = [];
this.items = [];
const { el, anchor } = __initList(parent, index, this.opts);
this.el = el;
this.anchor = anchor;
this.update(state);
return this.el;
}
async unmount() {
this.items.forEach((c) => c.unmount());
if (isString(this.opts.el)) this.$remove();
this.anchor?.remove();
this.el = void 0;
this.items = void 0;
this.prev = void 0;
}
async update(curr) {
if (!curr) return;
const {
opts: { item: ctor, equiv = (a, b) => a === b },
items,
prev,
el: parent,
anchor
} = this;
const nb = curr.length;
let na = prev.length;
let n = Math.min(na, nb);
let offset = this.offset;
const children = parent.childNodes;
if (anchor && children.length !== this.numChildren) {
this.numChildren = children.length;
this.offset = offset = [...children].indexOf(anchor);
}
for (let i = 0; i < n; i++) {
if (!equiv(prev[i], curr[i])) {
await items[i].unmount();
const val = curr[i];
const child = $compile(ctor(val));
await child.mount(parent, i + offset);
items[i] = child;
prev[i] = val;
}
}
if (na < nb) {
for (; n < nb; n++) {
const val = curr[n];
const child = $compile(ctor(val));
await child.mount(parent, n + offset);
items[n] = child;
prev[n] = val;
}
} else {
while (--na >= nb) {
await items[na].unmount();
items.pop();
prev.pop();
}
}
}
}
export {
$list,
List
};