class Root {
constructor({ lookup, dispatchFn }) {
this.lookup = lookup;
this.multi = defmulti(dispatchFn);
Object.defineProperties(this, {
_list: { value: [], writable: true }
});
}
get value() {
return this;
}
render(rootId, ctx) {
return this.multi.dispatch(ctx, this.lookup(rootId));
}
addView(dispatchVal, viewFn) {
return Generators.observe(next => {
next(
this.multi.addMethod(dispatchVal, (ctx, x) => {
const args =
this.resolveChildren(x, x => this.multi.dispatch(ctx, x)) || x;
return viewFn(ctx, args);
})
);
this.dispatchEvent(this);
return () => {
this.multi.removeMethod(dispatchVal);
this.dispatchEvent(this);
};
});
}
resolveChildren({ content, ...x }, transform = identity) {
if (content) {
if (checks.isArray(content)) {
x.content = content.map(id =>
this.resolveChildren({ content: id }, transform)
);
} else if (checks.isObject(content)) {
const out = {};
for (let k in content) {
out[k] = this.resolveChildren({ content: content[k] }, transform);
}
x.content = out;
} else {
return transform(this.lookup(content));
}
return x;
}
}
addEventListener(type, listener) {
if (this._list.includes(listener)) return;
this._list = [listener].concat(this._list);
}
removeEventListener(type, listener) {
this._list = this._list.filter(l => l !== listener);
}
dispatchEvent(event) {
const p = Promise.resolve(event);
this._list.forEach(l => p.then(l));
}
}