UNPKG

@ramstack/alpinegear-when

Version:

@ramstack/alpinegear-when provides additional directives, magic functions, and utilities for a more productive development experience

88 lines (74 loc) 2.6 kB
const warn = (...args) => console.warn("alpinegear.js:", ...args); const is_template = el => el instanceof HTMLTemplateElement; const is_element = el => el.nodeType === Node.ELEMENT_NODE; function anchor_block(el, template, { addScopeToNode, cleanup, initTree, mutateDom, scope = {} }) { if (el._r_block) { return; } initialize(); let nodes = is_template(template) ? [...template.content.cloneNode(true).childNodes] : [template.cloneNode(true)]; mutateDom(() => { for (let node of nodes) { is_element(node) && addScopeToNode(node, scope, el); el.parentElement.insertBefore(node, el); is_element(node) && initTree(node); } }); el._r_block = { template, update() { mutateDom(() => { for (let node of nodes ?? []) { el.parentElement.insertBefore(node, el); } }); }, delete() { el._r_block = null; for (let node of nodes ?? []) { node.remove(); } nodes = null; } }; cleanup(() => el._r_block?.delete()); } function initialize() { document.body._r_block ??= (() => { const observer = new MutationObserver(mutations => { for (let mutation of mutations) { for (let node of mutation.addedNodes) { node._r_block?.update(); } } }); observer.observe(document.body, { childList: true, subtree: true }); return observer; })(); } function create_getter(evaluate_later, ...args) { const evaluate = evaluate_later(...args); return () => { let result; evaluate(v => result = v); return has_getter(result) ? result.get() : result; }; } function has_getter(value) { return typeof value?.get === "function"; } function plugin({ addScopeToNode, directive, initTree, mutateDom }) { directive("when", (el, { expression }, { cleanup, effect, evaluateLater }) => { if (!is_template(el)) { warn("x-when can only be used on a 'template' tag"); return; } const activate = () => anchor_block(el, el, { addScopeToNode, cleanup, initTree, mutateDom }); const clear = () => el._r_block?.delete(); const get = create_getter(evaluateLater, expression); effect(() => get() ? activate() : clear()); }); } export { plugin as when };