class ChildObserver extends MutationObserver { constructor() { super(mutations => { for (const mutation of mutations) { mutation.target.dispatchEvent(new CustomEvent("change", {detail: mutation})) } }) } observe(element) { MutationObserver.prototype.observe.call(this, element, { childList: true }) } } const childObserver = new ChildObserver() export const lense = (methods, extra) => { if (extra) return lense(extra)(methods) const traps = { get(target, prop) { if (prop === "length") { return target.children.length } else if (prop === Symbol.iterator) { return function*() { for (const child of target.children) { yield methods.get(child) } } } else if (prop.match?.call(prop, /^[0-9]+$/)) { const child = target.children[prop] if (child) return methods.get(child) return child } else { return Array.prototype[prop] } }, set(target, prop, value) { if (prop.match?.call(prop, /^[0-9]+$/)) { const child = target.children[prop] if (child) { methods.set(child, value) return true } else { for (let i = target.children.length; i < Number(prop); i++) { target.appendChild(methods.new(undefined)) } const element = methods.new(value) target.appendChild(element) if (methods.get(element) !== value) methods.set(element, value) return true } } else if (prop == "length") { if (value == target.children.length) return true else return false } }, deleteProperty(target, prop) { if (prop.match?.call(prop, /^[0-9]+$/)) { const child = target.children[prop] if (child) child.remove() return true } }, has(target, prop) { return (prop === Symbol.iterator) || (prop in target.children) || (prop in Array.prototype) } } return element => { const proxy = new Proxy(element, traps) if (methods.event) childObserver.observe(element) if (typeof methods.event === "function") element.addEventListener("change", event => { methods.event(proxy, element, event.detail) }) return proxy } } export default lense