UNPKG

alpinejs-component

Version:

Directive-based Alpine.js components with Shadow DOM encapsulation, slots, and cached template rendering

4 lines (3 loc) 4.32 kB
(()=>{function C(o=100){let n=new Map;return n.maxEntries=o,n}function y(o,n,t){for(o.set(n,t);o.size>o.maxEntries;){let c=o.keys().next().value;o.delete(c)}}var T=C(200),S=C(200),g=C(100);function I(o){if(!o)return!0;try{return new URL(o,window.location.href).origin===window.location.origin}catch{return!1}}function L(o,n=new Set){if(!o||n.has(o))return"";n.add(o);try{return[...o.cssRules].map(t=>typeof CSSImportRule<"u"&&t instanceof CSSImportRule?L(t.styleSheet,n):typeof CSSStyleRule<"u"&&t instanceof CSSStyleRule&&t.selectorText===":root"?"":t.cssText).filter(Boolean).join(` `)}catch{return""}}function R(o,n){let t=[...new Set(n.map(d=>d.trim()).filter(Boolean))];if(!t.length)return;let c=t.slice().sort().join(",");if(!g.has(c)){let e=(t.includes("global")?[...document.styleSheets]:[...document.styleSheets].filter(({title:r})=>t.includes(r))).filter(({href:r})=>I(r)).map(r=>L(r)).join(` `),l=new CSSStyleSheet;l.replaceSync(e),y(g,c,l)}o.adoptedStyleSheets=[g.get(c)]}function b(o){let n=document.createElement("template");return n.innerHTML=o,n.content}function $(o,{allowCrossOrigin:n=!1}={}){let t=(o||"").trim();if(!t.length)return"";let c;try{c=new URL(t,window.location.href)}catch{throw new Error(`Invalid URL for x-component.url: ${t}`)}if(!["http:","https:"].includes(c.protocol))throw new Error(`Unsupported URL protocol for x-component.url: ${c.protocol}`);if(!n&&c.origin!==window.location.origin)throw new Error(`Cross-origin URL blocked for x-component.url: ${c.href}`);return c.href}function F(o){let n=(o||"").trim();if(!n.length)return null;if(!T.has(n)){let t=document.getElementById(n);if(!t)return console.warn(`[alpinejs-component] Missing template: "${n}"`),null;y(T,n,b(t.innerHTML))}return T.get(n).cloneNode(!0)}async function j(o,n={}){let t=$(o,n);if(!t.length)return null;S.has(t)||y(S,t,fetch(t).then(c=>{if(!c.ok)throw new Error(`Request failed (${c.status}) for ${t}`);return c.text()}));try{let c=await S.get(t);return b(c).cloneNode(!0)}catch(c){throw S.delete(t),c}}function _(o){function n(e,l){if(!e)return"";try{let r=l(e);return typeof r=="string"?r.trim():r===null||typeof r>"u"?"":String(r)}catch(r){return console.error(`[alpinejs-component] Failed to evaluate expression: ${e}`,r),{value:"",error:r}}}function t(e){return(e.getAttribute("x-component-styles")||e.getAttribute("styles")||"").split(",").map(r=>r.trim()).filter(Boolean)}function c(e,l,r={}){e.dispatchEvent(new CustomEvent(l,{bubbles:!0,composed:!0,detail:r}))}function d(e){let l=e._x_componentSlots||[];for(let r of l)r.nodeType===Node.ELEMENT_NODE&&o.destroyTree(r),r.remove();e._x_componentSlots=[]}function x(e){d(e);let l=[...e.querySelectorAll(":scope > template[x-slot]")];if(!l.length)return;let r=[];for(let s of l){let w=(s.getAttribute("x-slot")||"").trim(),h=s.content.cloneNode(!0),u=[...h.childNodes];if(w.length)for(let i of u)i.nodeType===Node.ELEMENT_NODE&&i.setAttribute("slot",w);s.after(h),r.push(...u)}for(let s of r)s.nodeType===Node.ELEMENT_NODE&&o.initTree(s);e._x_componentSlots=r}o.directive("component",(e,{expression:l,modifiers:r},{effect:s,cleanup:w,evaluate:h})=>{let u=0,i=!1;s(()=>{let f=n(l,h),a=typeof f=="string"?f:f.value;if(typeof f=="object"&&f.error&&c(e,"x-component:error",{source:l,error:f.error}),!a.length){d(e),e.shadowRoot&&i&&(o.destroyTree(e.shadowRoot),e.shadowRoot.replaceChildren(),i=!1);return}let E=++u;(async()=>{let N=r.includes("url");try{N&&c(e,"x-component:loading",{source:a});let p=N?await j(a,{allowCrossOrigin:r.includes("external")}):F(a);if(E!==u)return;if(!p){let v=new Error(`Component source resolved but no fragment was returned: ${a}`);d(e),e.shadowRoot&&i&&(o.destroyTree(e.shadowRoot),e.shadowRoot.replaceChildren(),i=!1),console.error(`[alpinejs-component] Failed to render component: ${a}`,v),c(e,"x-component:error",{source:a,error:v});return}let m=e.shadowRoot||e.attachShadow({mode:"open"});i&&o.destroyTree(m),o.addScopeToNode(m,{},e),x(e),m.replaceChildren(p);let U=t(e);U.length&&R(m,U),o.initTree(m),i=!0,c(e,"x-component:loaded",{source:a})}catch(p){console.error(`[alpinejs-component] Failed to render component: ${a}`,p),c(e,"x-component:error",{source:a,error:p})}})()}),w(()=>{u+=1,d(e),e.shadowRoot&&i&&o.destroyTree(e.shadowRoot)})})}document.addEventListener("alpine:init",()=>window.Alpine.plugin(_));})();