UNPKG

@ramstack/alpinegear-fragment

Version:

@ramstack/alpinegear-fragment provides 'x-format' Alpine.js directive, allowing for fragment-like behavior similar to what's available in frameworks like 'Vue.js' or 'React', where multiple root elements can be grouped together.

76 lines (63 loc) 2.4 kB
(function () { 'use strict'; 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 plugin({ addScopeToNode, directive, initTree, mutateDom }) { directive("fragment", (el, {}, { cleanup }) => { if (!is_template(el)) { warn("x-fragment can only be used on a 'template' tag"); return; } anchor_block(el, el, { addScopeToNode, cleanup, initTree, mutateDom }); }); } document.addEventListener("alpine:init", () => { Alpine.plugin(plugin); }); })();