UNPKG

decla

Version:

Decla - declarative apps framework

83 lines (72 loc) 2.32 kB
// TODO: sync dom updates with browser // using requestAnimationFrame/setTimeout const eventHandler = function (event) { this.events[event.type](event) } const updateDomNode = (node, oldAttrs, newAttrs) => node.nodeType === Node.TEXT_NODE ? oldAttrs !== newAttrs ? (node.nodeValue = newAttrs, node) : node : Object.keys({ ...oldAttrs, ...newAttrs}) .filter(attr => oldAttrs[attr] !== newAttrs[attr]) .reduce((node, attr) => { if(attr.startsWith('on')){ node.events = node.events || {} node.events[attr.slice(2)] = newAttrs[attr] if(!oldAttrs[attr]) node.addEventListener(attr.slice(2), eventHandler) else if(!newAttrs[attr]) node.removeEventListener(attr.slice(2), eventHandler) } else if(newAttrs[attr]) { node.setAttribute(attr, newAttrs[attr]) } else if(!newAttrs[attr]){ node.removeAttribute(attr) } return node }, node) const createDomNode = (tag, attrs) => updateDomNode( tag !== 'text' ? document.createElement(tag, { is: attrs.is }) : document.createTextNode(attrs), {}, attrs ) export const dom = (parent) => { const DomEffect = (prev, next, propagate, context = { parent, idx: 0 }) => { let el if(prev && prev[1].tagName === next[1].tagName){ el = context.parent.childNodes[context.idx] context.idx++ updateDomNode(el, prev[1].attrs, next[1].attrs) propagate(prev[2], next[2], { parent: el, idx: 0 }) } else { if(prev) prev[3](context) el = context.parent.insertBefore( createDomNode(next[1].tagName, next[1].attrs), context.parent.childNodes[context.idx] ) context.idx++ propagate([], next[2], { parent: el, idx: 0 }) } return (context) => { context && context.parent.removeChild(el) } } const h = (name, attrs, ...child) => ( typeof name !== 'object' ? [ typeof name === 'string' ? DomEffect : name, typeof name === 'string' ? { tagName: name, attrs: attrs || {} } : attrs || {}, child.map(item => typeof item === 'string' || typeof item === 'number' ? h(DomEffect, { tagName: 'text', attrs: item }) : item ) ] : [attrs, ...child] ) return { DomEffect, h } }