UNPKG

@surface/custom-element

Version:

Provides support of directives and data binding on custom elements.

59 lines (58 loc) 2.7 kB
import bind from "../bind.js"; import Directive from "../directive.js"; import observe from "../observe.js"; export default function elementFactory(tag, attributes, binds, events, customDirectives, childs) { return () => { const element = document.createElement(tag); window.customElements.upgrade(element); if (attributes) { for (const [key, value] of attributes) { element.setAttribute(key, value); } } const activators = []; if (childs) { for (const childFactory of childs) { const [childElement, activator] = childFactory(); // TODO: Allow factory returns multiples nodes. element.appendChild(childElement); activators.push(activator); } } const activator = (_parent, host, scope, directives) => { const disposables = []; const subscriptions = []; for (const activator of activators) { disposables.push(activator(element, host, scope, directives)); } if (binds) { for (const [type, key, expression, observables] of binds) { switch (type) { case "oneway": subscriptions.push(observe(scope, observables, () => void (element[key] = expression(scope)), false)); break; case "twoway": subscriptions.push(bind(element, [key], scope, observables[0])); break; default: subscriptions.push(observe(scope, observables, () => element.setAttribute(key, `${expression(scope)}`), false)); } } } if (events) { for (const [key, expression] of events) { const listener = expression(scope); element.addEventListener(key, listener); subscriptions.push({ unsubscribe: () => element.removeEventListener(key, listener) }); } } if (customDirectives) { for (const [key, expression, observables] of customDirectives) { disposables.push(new Directive({ element, scope, key, expression, observables })); } } return { dispose: () => (subscriptions.splice(0).forEach(x => x.unsubscribe()), disposables.splice(0).forEach(x => x.dispose())) }; }; return [element, activator]; }; }