lego-dom 2.1.5 → 2.1.7
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/lego.d.ts +2 -1
- package/dist/lego.min.js +2 -2
- package/dist/lego.mjs +2 -2
- package/package.json +1 -1
- package/src/core/batcher.js +7 -2
- package/src/core/lifecycle.js +75 -9
- package/src/core/parser.js +9 -2
- package/src/core/reactive.js +32 -4
- package/src/core/registry.js +10 -0
- package/src/core/renderer.js +162 -103
- package/src/core/stylesheets.js +8 -5
- package/src/core/tracking.js +65 -0
- package/src/directives/b-enter.js +5 -1
- package/src/directives/b-for.js +82 -8
- package/src/directives/b-html.js +39 -7
- package/src/directives/b-leave.js +5 -1
- package/src/directives/b-mount.js +30 -0
- package/src/directives/b-props.js +103 -0
- package/src/directives/b-show.js +10 -1
- package/src/directives/b-sync.js +2 -1
- package/src/directives/b-text.js +4 -2
- package/src/directives/index.js +3 -1
- package/src/features/error.js +25 -4
- package/src/features/mount.js +77 -0
- package/src/features/persistence.js +79 -26
- package/src/features/router.js +26 -3
- package/src/index.js +119 -11
- package/src/lego.d.ts +2 -1
- package/src/utils/dom.js +56 -0
- package/src/utils/helpers.js +15 -2
- package/src/utils/parser-utils.js +8 -2
- package/src/utils/safe-eval.js +68 -7
package/dist/lego.d.ts
CHANGED
package/dist/lego.min.js
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
|
-
(()=>{var
|
|
1
|
+
(()=>{var S={},Y=new WeakMap,A=new WeakMap,W=new WeakMap,ue=new WeakMap,C=new Set,U=new Set,I=new Map,q=new Map,ee=new Map;var j={locked:!1},M=e=>(A.has(e)||A.set(e,{snapped:!1,bindings:null,bound:!1,rendering:!1,anchor:null}),A.get(e));var wt=/^[a-zA-Z_$][\w$]*$/,J=new Map,vt=(e,t="<unknown>")=>{if(!e||typeof e!="string")return null;let r=e.trim();if(!r||r.startsWith("{")&&r.endsWith("}")&&(r=r.slice(1,-1).trim(),!r))return null;let o=r.split(",").map(i=>i.trim()).filter(Boolean);if(o.length===0)return null;let n=[];for(let i of o){if(!wt.test(i))return console.error(`[Lego] Invalid b-props on <${t}>: token "${i}" is not a bare identifier. b-props declares names only \u2014 use b-logic for values. Got: "${e}"`),null;n.push(i)}return n},z={register(e,t){if(!t){J.delete(e);return}let r=vt(t,e);r?J.set(e,r):J.delete(e)},unregister(e){J.delete(e)},get(e){return J.get(e)||null},validate({instanceLogic:e,state:t,tagName:r}){let o=J.get(r);if(o){if(e)for(let n of Object.keys(e))o.includes(n)||console.warn(`[Lego] <${r}> received b-logic key "${n}" not declared in b-props. Declared: { ${o.join(", ")} }.`);for(let n of o)t[n]===void 0&&console.warn(`[Lego] <${r}> is missing prop "${n}" (declared in b-props but not provided).`)}}};var _={},De=e=>{_=e};var te=class{constructor(t=1e3){this.limit=t,this.cache=new Map}get(t){if(!this.cache.has(t))return;let r=this.cache.get(t);return this.cache.delete(t),this.cache.set(t,r),r}set(t,r){if(this.cache.has(t))this.cache.delete(t);else if(this.cache.size>=this.limit){let o=this.cache.keys().next().value;this.cache.delete(o)}this.cache.set(t,r)}get size(){return this.cache.size}clear(){this.cache.clear()}};var V=(e,t)=>{if(!e)return;let r=e.parentElement||(e.getRootNode?e.getRootNode().host:null);for(;r;){let o=r.tagName?r.tagName.toLowerCase():"";if(o&&(t==="*"&&S[o]||o===t.toLowerCase()))return r;r=r.parentElement||r.getRootNode&&r.getRootNode().host}},pe=(e,t)=>{if(typeof e=="function"){let o=Array.from(document.querySelectorAll("*")).filter(n=>n.tagName.includes("-"));return[].concat(e(o))}if(e.startsWith("#")){let o=document.getElementById(e.slice(1));return o?[o]:[]}let r=t?.querySelectorAll(e)||[];return r.length>0?[...r]:[...document.querySelectorAll(e)]},K=e=>e.attributes?[...e.attributes].find(t=>t.name==="b-sync"||t.name.startsWith("b-sync.")):null,St=new Set(["script","iframe","object","embed","link","meta","base","style"]),xt=new Set(["href","src","xlink:href","action","formaction","srcdoc","data"]),Re=e=>{if(typeof e!="string"||e===""||typeof document>"u")return e;let t=document.createElement("template");t.innerHTML=e;let r=document.createTreeWalker(t.content,NodeFilter.SHOW_ELEMENT),o=[],n;for(;n=r.nextNode();){if(St.has(n.tagName.toLowerCase())){o.push(n);continue}for(let i=n.attributes.length-1;i>=0;i--){let a=n.attributes[i],s=a.name.toLowerCase();if(s.startsWith("on")){n.removeAttribute(a.name);continue}if(xt.has(s)){let c=a.value.trim().toLowerCase();(c.startsWith("javascript:")||c.startsWith("data:text/html")||c.startsWith("vbscript:"))&&n.removeAttribute(a.name)}}}return o.forEach(i=>i.remove()),t.innerHTML},re=(e,t)=>{if(e.type==="checkbox")e.checked!==!!t&&(e.checked=!!t);else if(e.type==="radio"){let r=t!=null&&String(t)===e.value;e.checked!==r&&(e.checked=r)}else{let r=t==null?"":String(t);e.value!==r&&(e.value=r)}};var g={onError:(e,t,r)=>{console.error(`[Lego Error] [${t}]`,e,r)},metrics:{},debug:!1,syntax:"brackets",sanitize:null,loaderAllowlist:null},G=(e,t)=>{!e||!t||Object.getOwnPropertyNames(e).forEach(r=>{let o=Object.getOwnPropertyDescriptor(e,r);Object.defineProperty(t,r,o)})},oe=()=>g.syntax==="brackets"?["[[","]]"]:["{{","}}"],Ee=new Map,we=()=>{let[e,t]=oe(),r=e+t;if(Ee.has(r)){let a=Ee.get(r);return a.lastIndex=0,a}let o=e.replace(/[.*+?^${}()|[\]\\]/g,"\\$&"),n=t.replace(/[.*+?^${}()|[\]\\]/g,"\\$&"),i=new RegExp(`${o}(.*?)${n}`,"g");return Ee.set(r,i),i},Pe=e=>{let r=e.split("/").pop().replace(/\.lego$/,"").replace(/_/g,"-").replace(/([a-z])([A-Z])/g,"$1-$2").toLowerCase();if(!r.includes("-"))throw new Error(`[Lego] Invalid block definition: "${e}". Block names must contain a hyphen (e.g. user-card.lego or UserCard.lego).`);return r},D=(e,t)=>{if(!e)return"";let r=e.trim().split("."),o=t;for(let n of r){if(o==null)return"";o=o[n]}return o??""},ve=e=>typeof Node<"u"&&e instanceof Node,O=(e,t,r)=>{if(t.nodeType!==Node.ELEMENT_NODE)return;let o=[...t.attributes].find(i=>i.name===e||i.name.startsWith(`${e}.`));if(!o)return;let n={};return r&&(n=r(o,t)),{type:e,node:t,expr:o.value,modifiers:o.name.split(".").slice(1),...n}};var Se=null,Fe=e=>{Se=e},ne=[],ze=0,xe=e=>{let t=ne.find(n=>n.regex.test(e));if(!t)return null;let r=e.match(t.regex).slice(1),o=t.paramNames?Object.fromEntries(t.paramNames.map((n,i)=>[n,r[i]])):{};return{match:t,params:o}},me=async(e=null,t=null)=>{if(typeof window>"u")return;let r=++ze,o=()=>r===ze,n=window.location.pathname,i=xe(n);if(g.debug&&console.log("[Lego Trace] Matching route",n,i?.match),!i)return;let{match:a,params:s}=i,c=window.location.search;if(a.middleware){let u=await a.middleware({path:n,params:s});if(!o()||!u)return}_.$route.url=n+c,_.$route.route=a.path,_.$route.params=s,_.$route.query=Object.fromEntries(new URLSearchParams(c));let f=e&&e.length?e:["lego-router"],l=t||document;if(a.tagName){if(!o())return;f.flatMap(d=>pe(d,l)).forEach(d=>{if(!d||!o())return;d.innerHTML="";let p=document.createElement(a.tagName);d.appendChild(p),Se&&Se(p)})}},ge=(e,...t)=>r=>{let o=async(n,i=null,a=!0,s={})=>{if(a&&typeof history<"u"){let f={legoTargets:t.filter(l=>typeof l=="string"),method:n,body:i};history.pushState(f,"",e)}await me(t.length?t:null,r)};return{get:(n=!0,i={})=>o("GET",null,n,i),post:(n,i=!0,a={})=>o("POST",n,i,a),put:(n,i=!0,a={})=>o("PUT",n,i,a),patch:(n,i=!0,a={})=>o("PATCH",n,i,a),delete:(n=!0,i={})=>o("DELETE",null,n,i)}};var $e=null,$t=null,He=(e,t)=>{$e=e,$t=t},F=(e,t,r)=>{if(e!=null&&(e=String(e).toLowerCase(),!e.includes("-"))){console.warn(`[Lego] $mount: "${e}" is not a valid custom element name (must contain a hyphen).`);return}if(t===void 0){if(!e)return;let i=document.createElement(e);return r&&(i.$initialState=r),i}let o;if(t instanceof Element)o=[t];else if(Array.isArray(t))o=t;else if(typeof t=="string")o=pe(t);else{console.warn("[Lego] $mount: Invalid target",t);return}if(o.length===0){g.debug&&console.log(`[Lego] $mount: No targets found for "${t}"`);return}let n=[];return o.forEach(i=>{if(!i||(i.innerHTML="",!e))return;let a=document.createElement(e);r&&(a.$initialState=r),i.appendChild(a),$e&&$e(a),n.push(a)}),n.length===1?n[0]:n.length>0?n:void 0};var We=new te(1e3),Ie=new te(500),_t=/\b(eval|import|constructor|__proto__)\b/,Lt=/(?<![\w.$])(class|module|prototype)(?![\w$])/,L=(e,t,r=!0)=>{if(_t.test(e)||Lt.test(e)||/\[\s*['"`].*\+|\+.*['"`]\s*\]/.test(e)){console.warn(`[Lego] Security Warning: Blocked dangerous expression "${e}"`);return}try{let o=t.state||{},n=We.get(e);n||(n=new Function("global","self","event","helpers",`
|
|
2
2
|
with(this) {
|
|
3
3
|
with(helpers) {
|
|
4
4
|
return ${e}
|
|
5
5
|
}
|
|
6
6
|
}
|
|
7
|
-
`),_e.set(e,r));let n={$ancestors:i=>q(t.self,i),$registry:i=>oe.get(i.toLowerCase()),$element:t.self,$route:_.$route,$params:_.$route?.params||{},$go:(i,...c)=>ae(i,...c)(t.self),$db:_.$db,$emit:(i,c)=>{t.self.dispatchEvent(new CustomEvent(i,{detail:c,bubbles:!0,composed:!0}))}},a=r.call(s,t.global,t.self,t.event,n);return typeof a=="function"?a.call(s,t.event):a}catch(s){if(o)throw s;if(s instanceof ReferenceError)return;throw s}},me=(e,t={})=>{if(!e||e.trim()==="{}")return{};let o=s=>new Function("scope","global",`with(global) { with(scope) { return (${s}); } }`)(t,_);try{return o(e)}catch(s){let r=e.trim();if(!r.startsWith("{")&&r.includes(":"))try{return o(`{${e}}`)}catch{}return console.error(`[Lego] Error parsing b-logic: "${e.length>80?e.slice(0,80)+"...":e}"`,s),{}}};var Ne={name:"b-if",scan:(e,{checkGlobal:t,getPrivateData:o})=>B("b-if",e,(s,r)=>{t(s.value);let n=document.createComment(`b-if: ${s.value}`),a=o(r);return a.anchor=n,{anchor:n}}),execute({binding:e,state:t,global:o}){let{node:s,anchor:r,expr:n}=e,a=!!N(n,{state:t,global:o,self:s}),i=!!s.parentNode;a&&!i?r.parentNode&&r.parentNode.replaceChild(s,r):!a&&i&&s.parentNode.replaceChild(r,s)},destroy({binding:e}){e.anchor&&e.anchor.parentNode&&e.anchor.remove()}};var $e={name:"b-show",scan(e,{checkGlobal:t}){if(e.nodeType===Node.ELEMENT_NODE&&e.hasAttribute("b-show")){let o=e.getAttribute("b-show");return t(o),{type:"b-show",node:e,expr:o}}},execute({binding:e,state:t,global:o}){let{node:s,expr:r}=e;s.style.display=N(r,{state:t,global:o,self:s})?"":"none"}};var Le={name:"b-text",scan(e){if(e.nodeType===Node.ELEMENT_NODE&&e.hasAttribute("b-text"))return{type:"b-text",node:e,path:e.getAttribute("b-text")}},execute({binding:e,state:t,global:o}){let{node:s,path:r}=e;r.startsWith("global.")?s.textContent=C(r.slice(7),o)??"":s.textContent=C(r,t)??""}};var Te={name:"b-html",scan:e=>B("b-html",e),execute:({binding:e,state:t,global:o})=>{let{node:s,expr:r}=e,n=N(r,{state:t,global:o,self:s})||"";s._bHtmlPrev!==n&&(s._bHtmlPrev=n,s.innerHTML=n)},destroy({binding:e}){let{node:t}=e;t&&(delete t._bHtmlPrev,t.innerHTML="")}};var Ae={name:"b-sync",scan(e){if(e.nodeType!==Node.ELEMENT_NODE)return;let t=F(e);if(!t)return;let o=t.name.split(".").slice(1);return{type:"b-sync",node:e,expr:t.value,modifiers:o}},execute({binding:e,state:t,global:o}){let{node:s,expr:r}=e;r.startsWith("global.")?V(s,C(r.slice(7),o)??""):V(s,C(r,t)??"")},destroy({binding:e}){let{node:t}=e;t&&t._bSyncHandler&&(t.removeEventListener("input",t._bSyncHandler),t.removeEventListener("change",t._bSyncHandler),delete t._bSyncHandler)}};var Ce={name:"b-for",scan(e,{checkGlobal:t,pendingOperations:o}){if(e.nodeType!==Node.ELEMENT_NODE)return;let s=e.getAttribute("b-for")?.match(/^\s*(\w+)\s+in\s+([\s\S]+?)\s*$/);if(s){t(s[2]);let r=document.createComment(`b-for: ${s[1]} in ${s[2].trim()}`);return o.push(()=>{e.parentNode&&(e.parentNode.insertBefore(r,e),e.remove())}),{type:"b-for",anchor:r,itemName:s[1],listName:s[2].trim(),keyPath:e.getAttribute("b-key")||null,template:e.cloneNode(!0),terminal:!0}}},execute({binding:e,state:t,global:o,helpers:s}){let{bind:r,updateNodeBindings:n}=s;if(!r||!n){console.error("[Lego] b-for directive missing required helpers: bind, updateNodeBindings");return}let{anchor:a,listName:i,itemName:c,keyPath:f,template:d}=e,{contextEl:u}=s,l=N(i,{state:t,global:o,self:u})||[];P.has(a)||P.set(a,new Map);let p=P.get(a),S=new Set,x=[];l.forEach((m,b)=>{let v;f?(v=C(f,m),(v==null||v==="")&&(console.warn(`[Lego] b-key="${f}" could not resolve a value for item at index ${b}. Falling back to index-based key.`),v=`__bfor_${b}`)):m&&typeof m=="object"?(v=m.id||m._id||m.uuid||m.key,v===void 0&&(re.has(m)||re.set(m,Math.random()),v=re.get(m))):v=`${b}-${m}`,S.add(v);let h=p.get(v);h?h._loopCtx.index=b:(h=d.cloneNode(!0),h.removeAttribute("b-for"),h.removeAttribute("b-key"),p.set(v,h),h._loopCtx={name:c,listName:i,index:b},r(h,u,h._loopCtx));let M=Object.assign(Object.create(t),{[c]:m,$index:b});n(h,M),[h,...h.querySelectorAll("*")].filter(H=>F(H)).forEach(H=>{let Ee=F(H).value;Ee.startsWith(`${c}.`)&&V(H,C(Ee.split(".").slice(1).join("."),l[b]))}),x.push(h)});let E=a.nextSibling;x.forEach(m=>{m!==E?a.parentNode.insertBefore(m,E):E=E.nextSibling});for(let[m,b]of p.entries())S.has(m)||(b.remove(),p.delete(m))},destroy({binding:e}){let{anchor:t}=e;if(t&&P.has(t)){let o=P.get(t);o.forEach(s=>s.remove()),o.clear(),P.delete(t)}t&&t.parentNode&&t.remove()}};var ke={scan:e=>{if(e.hasAttribute("b-init"))return{type:"b-init",node:e,expr:e.getAttribute("b-init")}},execute:({binding:e,state:t,global:o})=>{e.initialized||(e.initialized=!0,N(e.expr,{state:t,global:o,self:e.node}))}};var Oe={name:"b-enter",scan:e=>B("b-enter",e,(t,o)=>({modifiers:t.name.split(".").slice(1)})),execute:({binding:e,state:t,global:o})=>{if(e.observer||e.done)return;let s=new IntersectionObserver((r,n)=>{r[0].isIntersecting&&(N(e.expr,{state:t,global:o,self:e.node}),e.modifiers.includes("once")&&(n.disconnect(),e.observer=null,e.done=!0))});s.observe(e.node),e.observer=s},destroy:({binding:e})=>{e.observer&&(e.observer.disconnect(),e.observer=null)}};var Me={name:"b-leave",scan:e=>B("b-leave",e),execute:({binding:e,state:t,global:o})=>{if(e.observer||e.done)return;let s=new IntersectionObserver((r,n)=>{let a=r[0];a.isIntersecting&&(e.activated=!0),!a.isIntersecting&&e.activated&&(N(e.expr,{state:t,global:o,self:e.node}),e.modifiers.includes("once")&&(n.disconnect(),e.observer=null,e.done=!0))});s.observe(e.node),e.observer=s},destroy:({binding:e})=>{e.observer&&(e.observer.disconnect(),e.observer=null)}};var Y={"b-if":Ne,"b-show":$e,"b-text":Le,"b-html":Te,"b-sync":Ae,"b-for":Ce,"b-init":ke,"b-enter":Oe,"b-leave":Me};var Ge=(e=null)=>{let t=!1,o=new Set,s=!1,r=e,n=new Set,a=null,i=new Set,c=l=>{r=l},f=()=>{a&&clearTimeout(a),a=setTimeout(()=>{i.forEach(l=>{let p=l._studs;if(p&&typeof p.updated=="function")try{p.updated.call(p)}catch(S){console.error("[Lego] Error in updated hook:",S)}}),i.clear(),a=null},50)},d=()=>{n.size>0&&(n.forEach(l=>o.add(l)),n.clear(),!t&&o.size>0&&(t=!0,requestAnimationFrame(u)))},u=()=>{s=!0;let l=Array.from(o);o.clear(),t=!1,l.forEach(p=>{p.isConnected&&r&&r(p)}),l.forEach(p=>i.add(p)),f(),s=!1,d()};return{add:l=>{if(l){if(s){n.add(l);return}o.add(l),!t&&(t=!0,requestAnimationFrame(u))}},setHandler:c}},ie=Ge();var L=new Map,ce=new Map,ee=new WeakMap,te=new Map,Je=e=>{let t=Array.from(te.entries()).filter(([r])=>r.startsWith("lego:")).sort((r,n)=>r[1].timestamp-n[1].timestamp),o=0,s=[];for(let[r,n]of t){if(o>=e)break;try{localStorage.removeItem(r),o+=n.size,s.push(r),te.delete(r)}catch(a){console.error(`[Lego] Failed to evict ${r}:`,a)}}return s},Be=(e,t,o)=>{g.debug&&console.log("[Lego Trace] scheduleSave",e,t,o),ce.has(e)&&clearTimeout(ce.get(e));let s=()=>{try{let r=JSON.stringify(t),n=new Blob([r]).size;localStorage.setItem(e,r);let a=e.startsWith("lego:")?e:`lego:${e}`;te.set(a,{timestamp:Date.now(),size:n}),ce.delete(e)}catch(r){if(r.name==="QuotaExceededError"){console.warn(`[Lego] Storage quota exceeded for key: ${e}`);try{let n=JSON.stringify(t),a=new Blob([n]).size,i=Je(a*2);if(i.length>0){g.debug&&console.log(`[Lego] Evicted ${i.length} old keys, retrying save`),localStorage.setItem(e,n);let c=e.startsWith("lego:")?e:`lego:${e}`;te.set(c,{timestamp:Date.now(),size:a})}else g.onError(new Error("Storage quota exceeded and no keys available for eviction"),"quota",e)}catch{g.onError(new Error(`Critical: Could not save ${e} even after eviction`),"quota-critical",e)}}else console.error(`[Lego] Storage Error (${e}):`,r)}};o>0?ce.set(e,setTimeout(s,o)):s()},ge=e=>({__type:"lego-db",key:e,_default:void 0,_debounce:0,default(o){return this._default=o,this},debounce(o){return this._debounce=o,this},set(o,s=0){return Be(e,o,s),L.has(e)&&L.get(e).forEach(({target:r,prop:n,el:a,batcher:i})=>{r[n]=o,a&&i&&i.add(a)}),o},get(){try{let o=localStorage.getItem(e);return o!==null?JSON.parse(o):null}catch(o){return console.warn(`[Lego] Failed to get localStorage value for key "${e}":`,o),null}},delete(){try{return localStorage.removeItem(e),te.delete(e.startsWith("lego:")?e:`lego:${e}`),L.has(e)&&L.get(e).forEach(({target:o,prop:s,el:r,batcher:n})=>{o[s]=null,r&&n&&n.add(r)}),!0}catch(o){return console.error(`[Lego] Failed to delete localStorage key "${e}":`,o),!1}}}),De=e=>e&&e.__type==="lego-db",Pe=(e,t,o,s,r)=>{g.debug&&console.log("[Lego Trace] Reactive DB Init:",t,o);let n=o._default;try{let a=localStorage.getItem(o.key);a!==null&&(n=JSON.parse(a))}catch(a){console.warn(`[Lego] Failed to parse localStorage value for key "${o.key}":`,a)}e[t]=n,ee.has(e)||ee.set(e,{}),ee.get(e)[t]={key:o.key,debounce:o._debounce},g.debug&&console.log("[Lego Trace] DB Metadata Set:",t,ee.get(e)[t]),L.has(o.key)||L.set(o.key,new Set),L.get(o.key).add({target:e,prop:t,el:s,batcher:r})},Re=(e,t,o)=>{let s=ee.get(e);if(s&&s[t]){let r=s[t].key;Be(r,o,s[t].debounce),L.has(r)&&L.get(r).forEach(({target:n,prop:a,el:i,batcher:c})=>{n!==e&&(n[a]=o,i&&c&&c.add(i))})}},Fe=()=>{typeof window<"u"&&window.addEventListener("storage",e=>{if(!(!e.key||!L.has(e.key)))try{let t=JSON.parse(e.newValue);L.get(e.key).forEach(({target:o,prop:s,el:r,batcher:n})=>{o[s]=t,r&&n&&n.add(r)})}catch(t){console.warn("[Lego] Cross-tab sync error:",t)}})};var j=(e,t,o=ie)=>{if(e===null||typeof e!="object"||de(e))return e;if(G.has(e))return G.get(e);for(let n in e){let a=Object.getOwnPropertyDescriptor(e,n);if(a&&a.get)continue;let i=e[n];De(i)&&Pe(e,n,i,t,o)}let s={get:(n,a)=>{let i=Reflect.get(n,a);return i!==null&&typeof i=="object"&&!de(i)?j(i,t,o):i},set:(n,a,i,c)=>{if(a==="__proto__"||a==="constructor"||a==="prototype")return console.warn(`[Lego] Blocked setting dangerous property: "${a}"`),!0;let f=n[a];g.debug&&f!==i&&console.log("[Lego Trace] Reactive SET:",a,"Old:",f,"New:",i,"Target:",n);let d=c===G.get(n),u=Object.prototype.hasOwnProperty.call(n,a),l=!d&&u?Reflect.set(n,a,i):Reflect.set(n,a,i,c);return(d||u)&&f!==i&&(o.add(t),Re(n,a,i)),l},deleteProperty:(n,a)=>{let i=Reflect.deleteProperty(n,a);return o.add(t),i}},r=new Proxy(e,s);return G.set(e,r),r};var Ve=e=>{let t=e;for(;t;){let o=t.getAttribute&&t.getAttribute("b-error");if(o&&o.toLowerCase()!==e.tagName.toLowerCase())return{errorTag:o,targetElement:t};let s=t.tagName?t.tagName.toLowerCase():"",r=w[s];if(r){let n=r.getAttribute("b-error");if(n&&n.toLowerCase()!==e.tagName.toLowerCase())return{errorTag:n,targetElement:t}}t=t.parentElement||t.getRootNode&&t.getRootNode().host}return null},he=null,ze=null,He=(e,t)=>{he=e,ze=t},Xe=(e,t,o)=>{if(!he||!ze){console.error("[Lego] Error boundary dependencies not loaded",o);return}try{t.shadowRoot?t.shadowRoot.innerHTML="":t.innerHTML="";let s=document.createElement(e);s.$initialState={$error:{message:o.message,stack:o.stack,component:t.tagName.toLowerCase()}},(t.shadowRoot||t).appendChild(s),he(s)}catch(s){console.error("[Lego] Error boundary failed to render:",s),console.error("[Lego] Original error:",o)}},U=(e,t,o)=>{let s=Ve(t);s?Xe(s.errorTag,s.targetElement,e):g.onError(e,o,t)};var le=(e,t,o=null)=>{let s=t._studs,r=i=>{let c=A(i);if(!c.bound){if(i.hasAttributes()){let f=i.attributes;for(let u=0;u<f.length;u++){let l=f[u];if(l.name.startsWith("@")){let p=l.name.slice(1).split("."),S=p[0],x=p.slice(1);i.addEventListener(S,E=>{if(x.includes("prevent")&&E.preventDefault(),x.includes("stop")&&E.stopPropagation(),!(x.includes("self")&&E.target!==E.currentTarget)){if(typeof KeyboardEvent<"u"&&E instanceof KeyboardEvent){if(x.includes("ctrl")&&!E.ctrlKey||x.includes("alt")&&!E.altKey||x.includes("shift")&&!E.shiftKey||x.includes("meta")&&!E.metaKey)return;let m=x.filter(b=>!["prevent","stop","self","ctrl","alt","shift","meta","capture","once","passive"].includes(b));if(m.length>0){let b=E.key.toLowerCase();if(!m.some(h=>h==="enter"?b==="enter":h==="esc"||h==="escape"?b==="escape":h==="space"?b===" ":h==="tab"?b==="tab":h==="delete"?b==="delete":h==="backspace"?b==="backspace":h==="up"?b==="arrowup":h==="down"?b==="arrowdown":h==="left"?b==="arrowleft":h==="right"?b==="arrowright":h==="alpha"?/^[a-z]$/.test(b):h==="numbers"?/^[0-9]$/.test(b):h===b))return}}try{let m=s;if(o){let v=N(o.listName,{state:s,global:_,self:t})[o.index];m=Object.assign(Object.create(s),{[o.name]:v})}N(l.value,{state:m,global:_,self:i,event:E,$event:E},!0)}catch(m){U(m,t,"event-handler")}}})}}let d=F(i);if(d){let u=d.value,l=d.name.split(".").slice(1),p=l.includes("lazy"),S=l.includes("number"),x=l.includes("trim"),E=()=>{try{let m,b;if(u.startsWith("global.")){let h=u.slice(7).split(".");b=h.pop(),m=h.reduce((M,D)=>M[D],_)}else if(o&&u.startsWith(`${o.name}.`)){let M=N(o.listName,{state:s,global:_,self:t})[o.index];if(!M)return;let D=u.split(".").slice(1);b=D.pop(),m=D.reduce((H,ye)=>H[ye],M)}else{let h=u.split(".");b=h.pop(),m=h.reduce((M,D)=>M[D],s)}let v=i.type==="checkbox"?i.checked:i.value;if(x&&typeof v=="string"&&(v=v.trim()),S){let h=parseFloat(v);isNaN(h)||(v=h)}m&&m[b]!==v&&(m[b]=v)}catch(m){g.onError(m,"sync-update",i)}};i._bSyncHandler=E,p||i.addEventListener("input",E),i.addEventListener("change",E)}if(i.hasAttribute("b-var")){let u=i.getAttribute("b-var");s.$vars&&(s.$vars[u]=i)}}c.bound=!0}};e instanceof Element&&r(e);let n=document.createTreeWalker(e,NodeFilter.SHOW_ELEMENT),a;for(;a=n.nextNode();)r(a)},Qe=e=>{let t=[],o=document.createTreeWalker(e,NodeFilter.SHOW_ELEMENT|NodeFilter.SHOW_TEXT),s,r=[];for(;s=o.nextNode();){let n=s;if((c=>{let f=c.parentNode;for(;f&&f!==e;){if(f.hasAttribute&&f.hasAttribute("b-for"))return!0;f=f.parentNode}return!1})(s))continue;let i=c=>{if(/\bglobal\b/.test(c)){let f=e.host||e;J.add(f)}};if(s.nodeType===Node.ELEMENT_NODE){let c=!1;for(let[d,u]of Object.entries(Y))if(u.scan){let l=u.scan(s,{checkGlobal:i,getPrivateData:A,pendingOperations:r,current:n});l&&(t.push(l),l.terminal&&(c=!0))}if(c)continue;let[f]=X();[...s.attributes].forEach(d=>{d.value.includes(f)&&(i(d.value),t.push({type:"attr",node:s,attrName:d.name,template:d.value}))})}else if(s.nodeType===Node.TEXT_NODE){let[c]=X();s.textContent.includes(c)&&(i(s.textContent),t.push({type:"text",node:s,template:s.textContent}))}}return r.forEach(n=>n()),t},Ze=(e,t)=>{let o=n=>{if(n.nodeType===Node.TEXT_NODE){n._tpl===void 0&&(n._tpl=n.textContent);let a=n._tpl.replace(Q(),(i,c)=>N(c.trim(),{state:t,global:_,self:n},!1)??"");n.textContent!==a&&(n.textContent=a)}else if(n.nodeType===Node.ELEMENT_NODE){let[a]=X();[...n.attributes].forEach(i=>{if(i._tpl===void 0&&(i._tpl=i.value),i._tpl.includes(a)){let c=i._tpl.replace(Q(),(f,d)=>N(d.trim(),{state:t,global:_,self:n},!1)??"");i.value!==c&&(i.value=c,i.name==="class"&&(n.className=c))}})}};o(e);let s=document.createTreeWalker(e,NodeFilter.SHOW_ELEMENT|NodeFilter.SHOW_TEXT),r;for(;r=s.nextNode();)o(r)},K=e=>{g.debug&&console.log("[Lego Trace] render() called for:",e.tagName);let t=e._studs;if(!t)return;let o=A(e);if(!o.rendering){o.rendering=!0,g.metrics&&g.metrics.onRenderStart&&g.metrics.onRenderStart(e);try{let s=e.shadowRoot||e;o.bindings||(o.bindings=Qe(s)),o.bindings.forEach(r=>{let n=Y[r.type];if(n){n.execute({binding:r,state:t,global:_,helpers:{bind:le,updateNodeBindings:Ze,contextEl:e}});return}if(r.type==="text"){let a=r.template.replace(Q(),(i,c)=>N(c.trim(),{state:t,global:_,self:r.node},!1)??"");r.node.textContent!==a&&(r.node.textContent=a)}if(r.type==="attr"){let a=r.template.replace(Q(),(i,c)=>N(c.trim(),{state:t,global:_,self:r.node},!1)??"");r.node.getAttribute(r.attrName)!==a&&(r.node.setAttribute(r.attrName,a),r.attrName==="class"&&(r.node.className=a))}}),t===_&&J.forEach(r=>K(r))}catch(s){U(s,e,"render")}finally{g.metrics&&g.metrics.onRenderEnd&&g.metrics.onRenderEnd(e),o.rendering=!1}}};var We=new Map,Ie={},qe=e=>{Ie=e},je=async()=>{let e=Object.entries(Ie).map(async([t,o])=>{let s=await Promise.all(o.map(async r=>{try{if(r instanceof CSSStyleSheet)return r;let n=await fetch(r);if(!n.ok)throw new Error(`Status ${n.status}`);let a=await n.text(),i=new CSSStyleSheet;return await i.replace(a),i}catch(n){return console.error(`[Lego] Failed to load stylesheet: ${r}`,n),null}}));We.set(t,s.filter(r=>r!==null))});await Promise.all(e),g.debug&&console.log("[Lego Debug] Re-applying stylesheets to",T.size,"blocks"),T.forEach(t=>{be(t)})},be=e=>{if(!e.shadowRoot&&!e._legoShadow)return;let t=e.shadowRoot||e._legoShadow,o=e.tagName.toLowerCase(),s=w[o],r=(s&&s.getAttribute("b-stylesheets")||"").split(/\s+/).filter(Boolean),n=(e.getAttribute("b-stylesheets")||"").split(/\s+/).filter(Boolean),a=[],i=e.parentElement||(e.getRootNode?e.getRootNode().host:null);for(;i;){let u=(i.getAttribute("b-cascade")||"").split(/\s+/).filter(Boolean);u.length&&a.push(...u);let l=i.tagName?i.tagName.toLowerCase():"";if(w[l]){let p=(w[l].getAttribute("b-cascade")||"").split(/\s+/).filter(Boolean);p.length&&a.push(...p)}i=i.parentElement||i.getRootNode&&i.getRootNode().host}let c=[...new Set([...r,...n])],f=[...new Set(a)],d=[...new Set([...f,...c])];if(d.length>0){let u=d.flatMap(l=>We.get(l)||[]);if(u.length>0&&g.debug&&console.log("[Lego Debug] Applying styles to",e.tagName,"- Names:",d,"- Sheets:",u.length),u.length>0){let l=t.adoptedStyleSheets.filter(p=>!u.includes(p));t.adoptedStyleSheets=[...l,...u]}}e._studsMeta={stylesheets:{explicit:c,inherited:f,applied:d}}};var $=e=>{if(g.debug&&console.log("[Lego Trace] snap() called for:",e.tagName),!e||e.nodeType!==Node.ELEMENT_NODE)return;let t=A(e),o=e.tagName.toLowerCase(),s=w[o];if(s&&!t.snapped){t.snapped=!0;let n=s.content.cloneNode(!0),a=e.shadowRoot;a?a.innerHTML="":a=e.attachShadow({mode:"open"}),be(e);let i=q(e,"*")||q(e.getRootNode().host,"*"),c=i&&i.state?i.state:{},f=I.get(o)||{},d=me(s.getAttribute("b-logic")||s.getAttribute("b-data")||"{}"),u=me(e.getAttribute("b-logic")||e.getAttribute("b-data")||"{}",c),l={$vars:{},$element:e,get $parent(){return q(e,"*")},$emit:(x,E)=>{e.dispatchEvent(new CustomEvent(x,{detail:E,bubbles:!0,composed:!0}))},get $route(){return _.$route},get $go(){return _.$go}};z(f,l),z(d,l),z(u,l),e.$initialState&&(z(e.$initialState,l),delete e.$initialState),e._studs=j(l,e),Object.defineProperty(e,"state",{get(){return this._studs},set(x){Object.assign(this._studs,x)},configurable:!0,enumerable:!1}),R.locked=!0,a.appendChild(n),R.locked=!1;let p=a.querySelector("style");if(p&&(p.textContent=p.textContent.replace(/\bself\b/g,":host")),le(a,e),T.add(e),K(e),e.setAttribute("b-id",o),e._legoShadow||(e._legoShadow=a),typeof e._studs.mounted=="function")try{e._studs.mounted.call(e._studs)}catch(x){U(x,e,"mounted")}let S=a.querySelectorAll("*");g.debug&&console.log("[Lego Debug] Nested scan in",e.tagName,"- Found elements:",S.length),S.forEach(x=>{let E=x.tagName.toLowerCase(),m=!!w[E];m&&g.debug&&console.log("[Lego Debug] Checking",E,"- Registered:",m),m&&$(x)})}let r=e.parentElement;for(;r&&!r._studs;)r=r.parentElement;r&&r._studs&&le(e,r),[...e.children].forEach($)},k=e=>{if(e._studs&&typeof e._studs.unmounted=="function")try{e._studs.unmounted.call(e._studs)}catch(o){U(o,e,"unmounted")}e.shadowRoot&&[...e.shadowRoot.children].forEach(k),T.delete(e),J.delete(e),e._studs&&(e._studs.$element=null,e._studs.$vars&&(Object.keys(e._studs.$vars).forEach(o=>{e._studs.$vars[o]=null}),e._studs.$vars=null),e._studs.$emit&&(e._studs.$emit=null),delete e._studs.$parent,delete e._studs.$route,delete e._studs.$go,e._studs=null),e.hasOwnProperty("state")&&delete e.state;let t=W.get(e);t&&(t.bindings&&(t.bindings.forEach(o=>{let s=Y[o.type];if(s&&s.destroy)try{s.destroy({binding:o})}catch(r){console.error(`[Lego] Error in directive cleanup (${o.type}):`,r)}o.node=null,o.anchor=null}),t.bindings=null),t.anchor=null,W.delete(e)),[...e.children].forEach(k)};function Ue(e,t="block.lego"){let o={template:"",script:"",style:"",stylesAttr:"",cascadeAttr:"",errorAttr:"",blockName:Se(t),hasTemplate:!1,hasScript:!1,hasStyle:!1},s=e,r=/<(template|script|style)\b((?:\s+(?:[^>"']|"[^"]*"|'[^']*')*)*)>/i;for(;s;){let n=s.match(r);if(!n)break;let a=n[1].toLowerCase(),i=n[2],c=n[0],f=n.index,d=`</${a}>`,u=f+c.length,l=s.indexOf(d,u);if(l===-1){console.warn(`[Lego] Unclosed <${a}> tag in ${t}`);break}let p=s.slice(u,l);if(a==="template"){o.hasTemplate=!0,o.template=p.trim();let S=i.match(/b-stylesheets=["']([^"']+)["']/);S&&(o.stylesAttr=S[1]);let x=i.match(/b-cascade=["']([^"']+)["']/);x&&(o.cascadeAttr=x[1]);let E=i.match(/b-error=["']([^"']+)["']/);E&&(o.errorAttr=E[1])}else if(a==="script"){o.hasScript=!0,o.script=p.trim();let S=i.match(/lang=["']([^"']+)["']/);S&&(o.scriptLang=S[1])}else a==="style"&&(o.hasStyle=!0,o.style=p.trim());s=s.slice(l+d.length)}return o}var Ke=(e,t,o="block.lego")=>{let s=Ue(t,o),{blockName:r,template:n,script:a,style:i,stylesAttr:c,cascadeAttr:f,errorAttr:d}=s,u={};if(a)try{let p=a.trim(),S=p.match(/export\s+default\s+(?:\/\*[\s\S]*?\*\/\s*|\/\/[^\n]*\n\s*)*({[\s\S]*})/),x=S?S[1]:p;u=new Function("Lego","$db",`return ${x}`)(e,e.globals.$db)}catch(p){g.onError(p,"script",r)}let l=n;i&&(l=`<style>${i}</style>`+l),w[r]=document.createElement("template"),w[r].innerHTML=l,c&&w[r].setAttribute("b-stylesheets",c),f&&w[r].setAttribute("b-cascade",f),d&&w[r].setAttribute("b-error",d),I.set(r,u),document.querySelectorAll(r).forEach(p=>!A(p).snapped&&$(p))};ie.setHandler(K);He($,K);ve($);var Ye={url:typeof window<"u"?window.location.pathname:"/",route:"",params:{},query:{},method:"GET",body:null},O=j({$route:Ye,$go:(e,...t)=>ae(e,...t)(document.body),$db:ge},typeof document<"u"?document.body:null);we(O);var y={db:ge,snap:$,unsnap:k,defineLegoFile:(e,t)=>Ke(y,e,t),block:(e,t,o={},s="",r="",n="")=>{let a=document.createElement("template");a.setAttribute("b-id",e),a.setAttribute("b-stylesheets",s),r&&a.setAttribute("b-cascade",r),n&&a.setAttribute("b-error",n),a.innerHTML=t,w[e]=a,I.set(e,o);try{let i={};z(o,i),oe.set(e.toLowerCase(),j(i,document.body))}catch(i){g.onError(i,"define",e)}if(customElements.get(e))document.querySelectorAll(e).forEach(i=>{k(i),$(i)}),T.forEach(i=>{i._legoShadow&&i._legoShadow.querySelectorAll(e).forEach(c=>{k(c),$(c)})});else try{customElements.define(e,class extends HTMLElement{connectedCallback(){R.locked||w[e]&&$(this)}disconnectedCallback(){k(this)}})}catch(i){console.warn(`[Lego] Failed to register web component ${e}:`,i)}},getActiveBlocksCount:()=>T.size,getLegos:()=>Object.keys(w),config:g,globals:O,route:(e,t,o=null)=>{let s=[],r=e==="*"?".*":e;r=r.replace(/:([^\/]+)|[.*+?^${}()|[\]\\]/g,(n,a)=>a?(s.push(a),"([^/]+)"):"\\"+n),Z.push({path:e,regex:new RegExp(`^${r}$`),tagName:t,paramNames:s,middleware:o})},debug:{stylesheets:e=>!e||!e._studsMeta?null:e._studsMeta.stylesheets},init:async(e=document.body,t={})=>{if((!e||typeof e.nodeType!="number")&&(e=document.body),qe(t.styles||{}),g.loader=t.loader,g.debug=t.debug===!0,await je(),Z.length>0){let r=window.location.pathname,n=window.location.search,a=pe(r);if(a){let{match:i,params:c}=a,f=Object.fromEntries(new URLSearchParams(n));O.$route.url=r+n,O.$route.route=i.path,O.$route.params=c,O.$route.query=f,O.$route.method="GET",O.$route.body=null}}document.querySelectorAll("template[b-id]").forEach(r=>{let n=r.getAttribute("b-id");w[n]=r,customElements.get(n)||customElements.define(n,class extends HTMLElement{connectedCallback(){R.locked||w[n]&&$(this)}disconnectedCallback(){k(this)}})});let o=r=>{if(!r)return{};let n={};return Object.entries(r).forEach(([a,i])=>{if(typeof i=="function")n[a]=i();else if(typeof i=="string"&&i.startsWith("$db.")){let c=i.slice(4);n[a]=y.db(c).get()}else if(typeof i=="string"&&i.startsWith("$globals.")){let c=i.slice(9);n[a]=_[c]}else n[a]=i}),n},s=(r,n,a={})=>{customElements.get(r)||customElements.define(r,class extends HTMLElement{async connectedCallback(){if(w[r]){R.locked||$(this);return}if(y._fetching||(y._fetching=new Set),y._pendingLazy||(y._pendingLazy={}),y._fetching.has(r)){y._pendingLazy[r]||(y._pendingLazy[r]=new Set),y._pendingLazy[r].add(this);return}y._fetching.add(r);try{let i=n.startsWith("POST:")?"POST":"GET",c=n.replace(/^POST:/,""),f=o(a.headers),d={method:i,headers:f,credentials:a.credentials},l=await(await fetch(c,d)).text();y.defineLegoFile(l,`${r}.lego`),w[r]&&$(this);let p=y._pendingLazy[r];p&&(p.forEach(S=>{S.isConnected&&w[r]&&!A(S).snapped&&$(S)}),delete y._pendingLazy[r])}catch(i){console.error(`[Lego] Failed to load manifest block ${r}:`,i)}finally{y._fetching.delete(r)}}disconnectedCallback(){k(this)}})};if(t.manifest){let r=t.manifest;if(r.url&&typeof r.url=="string")try{let a=o(r.headers);r=await(await fetch(r.url,{headers:a,credentials:r.credentials})).json()}catch(a){console.error("[Lego] Failed to load manifest:",a),r=[]}else if(typeof r=="string")try{r=await(await fetch(r)).json()}catch(a){console.error("[Lego] Failed to load manifest:",a),r=[]}let n=Array.isArray(r)?r:[r];for(let a of n){let i=a.base||"",c=a.suffix===!0?".lego":a.suffix||"",f={headers:a.headers||{},credentials:a.credentials};a.legos&&a.legos.forEach(d=>{s(d,`${i}${d}${c}`,f)}),a.map&&Object.entries(a.map).forEach(([d,u])=>{let l=u.match(/^https?:|^\//)?u:`${i}${u}`;s(d,l,f)})}}if(g.loader){let r=a=>{if(a.nodeType!==Node.ELEMENT_NODE)return;let i=a.tagName.toLowerCase();if(i.includes("-")&&!w[i]&&!T.has(a)){if(y._fetching&&y._fetching.has(i))return;y._fetching||(y._fetching=new Set),y._fetching.add(i);let c=g.loader(i);if(c){let f=typeof c=="string"?fetch(c).then(d=>d.text()):c;Promise.resolve(f).then(d=>{y.defineLegoFile(d,`${i}.lego`),y._fetching.delete(i)}).catch(d=>{console.error(`[Lego] Failed to load ${i}:`,d),y._fetching.delete(i)})}}if(a.children.length>0){let c=a.firstElementChild;for(;c;)r(c),c=c.nextElementSibling}};y._discoveryObserver&&y._discoveryObserver.disconnect(),y._discoveryObserver=new MutationObserver(a=>a.forEach(i=>{i.addedNodes.forEach(r)})),y._discoveryObserver.observe(e,{childList:!0,subtree:!0});let n=document.createTreeWalker(e,NodeFilter.SHOW_ELEMENT);for(;n.nextNode();)r(n.currentNode)}if(t.studio){if(!w["lego-studio"]){let r=document.createElement("script");r.src="https://unpkg.com/@legodom/studio@0.0.2/dist/lego-studio.js",r.onerror=()=>console.warn("[Lego] Failed to load Studio from CDN"),document.head.appendChild(r)}y.route("/_/studio","lego-studio"),y.route("/_/studio/:block","lego-studio")}Z.length>0&&(window.addEventListener("popstate",r=>{let n=r.state?.legoTargets||null;ne(n)}),document.addEventListener("submit",r=>{r.preventDefault()}),document.addEventListener("click",r=>{let a=r.composedPath().find(i=>i.tagName==="A"&&(i.hasAttribute("b-target")||i.hasAttribute("b-link")));if(a){r.preventDefault();let i=a.getAttribute("href"),c=a.getAttribute("b-target"),f=c?c.split(/\s+/).filter(Boolean):[],d=a.getAttribute("b-link")!=="false";O.$go(i,...f).get(d)}}),ne()),Fe()}};typeof window<"u"?window.Lego=y:typeof global<"u"&&(global.Lego=y);var yo=y;})();
|
|
7
|
+
`),We.set(e,n));let i={$ancestors:s=>V(t.self,s),$registry:s=>ee.get(s.toLowerCase()),$element:t.self,$route:_.$route,$params:_.$route?.params||{},$go:(s,...c)=>ge(s,...c)(t.self),$db:_.$db,$mount:(s,c,f)=>F(s,c,f),$emit:(s,c)=>{t.self.dispatchEvent(new CustomEvent(s,{detail:c,bubbles:!0,composed:!0}))}},a=n.call(o,t.global,t.self,t.event,i);return typeof a=="function"&&t.event!==void 0?a.call(o,t.event):a}catch(o){if(r)throw o;if(o instanceof ReferenceError&&!g.strict)return;throw o}},_e=(e,t={})=>{if(!e||e.trim()==="{}")return{};let[r,o]=oe();if(e.includes(r)&&e.includes(o))return console.error(`[Lego] Refusing to parse b-logic containing template delimiters ("${r}...${o}"). b-logic is evaluated as JavaScript; templating user data into it is unsafe. Pass values through state instead. Got: "${e.length>80?e.slice(0,80)+"...":e}"`),{};let n=a=>{let s=Ie.get(a);return s||(s=new Function("scope","global",`with(global) { with(scope) { return (${a}); } }`),Ie.set(a,s)),s},i=a=>n(a)(t,_);try{return i(e)}catch(a){let s=e.trim();if(!s.startsWith("{")&&s.includes(":"))try{return i(`{${e}}`)}catch{}return console.error(`[Lego] Error parsing b-logic: "${e.length>80?e.slice(0,80)+"...":e}"`,a),{}}};var qe={name:"b-if",scan:(e,{checkGlobal:t,getPrivateData:r})=>O("b-if",e,(o,n)=>{t(o.value);let i=document.createComment(`b-if: ${o.value}`),a=r(n);return a.anchor=i,{anchor:i}}),execute({binding:e,state:t,global:r}){let{node:o,anchor:n,expr:i}=e,a=!!L(i,{state:t,global:r,self:o}),s=!!o.parentNode;a&&!s?n.parentNode&&n.parentNode.replaceChild(o,n):!a&&s&&o.parentNode.replaceChild(n,o)},destroy({binding:e}){e.anchor&&e.anchor.parentNode&&e.anchor.remove()}};var je={name:"b-show",scan(e,{checkGlobal:t}){if(e.nodeType===Node.ELEMENT_NODE&&e.hasAttribute("b-show")){let r=e.getAttribute("b-show");return t(r),{type:"b-show",node:e,expr:r}}},execute({binding:e,state:t,global:r}){let{node:o,expr:n}=e;o._bShowOriginal===void 0&&(o._bShowOriginal=o.style.display);let i=!!L(n,{state:t,global:r,self:o});o.style.display=i?o._bShowOriginal:"none"}};var Ke={name:"b-text",scan(e,{checkGlobal:t}){if(e.nodeType===Node.ELEMENT_NODE&&e.hasAttribute("b-text")){let r=e.getAttribute("b-text");return t(r),{type:"b-text",node:e,path:r}}},execute({binding:e,state:t,global:r}){let{node:o,path:n}=e;n.startsWith("global.")?o.textContent=D(n.slice(7),r)??"":o.textContent=D(n,t)??""}};var Ge={name:"b-html",scan:e=>O("b-html",e),execute:({binding:e,state:t,global:r,helpers:o})=>{let{node:n,expr:i,modifiers:a}=e,s=L(i,{state:t,global:r,self:n})??"";if(a&&a.includes("safe")&&(s=(typeof g.sanitize=="function"?g.sanitize:Re)(s)),n._bHtmlPrev!==s){n._bHtmlPrev=s;let c=o&&o.contextEl;if(c){let f=A.get(c);if(f&&f.bindings&&f.bindings.length){for(let l of f.bindings)l!==e&&l.node&&l.node!==n&&n.contains(l.node)&&(l.dead=!0,l.node=null);f.bindings.some(l=>l.dead)&&(f.bindings=f.bindings.filter(l=>!l.dead))}}n.innerHTML=s}},destroy({binding:e}){let{node:t}=e;t&&(delete t._bHtmlPrev,t.innerHTML="")}};var Ue={name:"b-sync",scan(e,{checkGlobal:t}){if(e.nodeType!==Node.ELEMENT_NODE)return;let r=K(e);if(!r)return;t(r.value);let o=r.name.split(".").slice(1);return{type:"b-sync",node:e,expr:r.value,modifiers:o}},execute({binding:e,state:t,global:r}){let{node:o,expr:n}=e;n.startsWith("global.")?re(o,D(n.slice(7),r)??""):re(o,D(n,t)??"")},destroy({binding:e}){let{node:t}=e;t&&t._bSyncHandler&&(t.removeEventListener("input",t._bSyncHandler),t.removeEventListener("change",t._bSyncHandler),delete t._bSyncHandler)}};var Tt=0,Je={name:"b-for",scan(e,{checkGlobal:t,pendingOperations:r}){if(e.nodeType!==Node.ELEMENT_NODE)return;let o=e.getAttribute("b-for")?.match(/^\s*(\w+)\s+in\s+([\s\S]+?)\s*$/);if(o){t(o[2]);let n=document.createComment(`b-for: ${o[1]} in ${o[2].trim()}`);return r.push(()=>{e.parentNode&&(e.parentNode.insertBefore(n,e),e.remove())}),{type:"b-for",anchor:n,itemName:o[1],listName:o[2].trim(),keyPath:e.getAttribute("b-key")||null,template:e.cloneNode(!0),terminal:!0}}},execute({binding:e,state:t,global:r,helpers:o}){let{bind:n,scanForBindings:i,runBinding:a}=o;if(!n||!a){console.error("[Lego] b-for directive missing required helpers: bind, runBinding");return}let{anchor:s,listName:c,itemName:f,keyPath:l,template:u}=e,{contextEl:d}=o,p=L(c,{state:t,global:r,self:d})||[];W.has(s)||W.set(s,new Map);let m=W.get(s),h=new Set,x=[];p.forEach((w,E)=>{let $;l?($=D(l,w),($==null||$==="")&&(console.warn(`[Lego] b-key="${l}" could not resolve a value for item at index ${E}. Falling back to index-based key.`),$=`__bfor_${E}`)):w&&typeof w=="object"?($=w.id||w._id||w.uuid||w.key,$===void 0&&(ue.has(w)||ue.set(w,++Tt),$=ue.get(w))):$=`${E}-${w}`,h.add($);let b=m.get($);b?b._loopCtx.index=E:(b=u.cloneNode(!0),b.removeAttribute("b-for"),b.removeAttribute("b-key"),m.set($,b),b._loopCtx={name:f,listName:c,index:E},n(b,d,b._loopCtx),i&&(b._loopBindings=i(b,d)));let k=b._loopScope;if(k||(b._loopScope=k=Object.create(t)),k[f]=w,k.$index=E,b._loopBindings)for(let P of b._loopBindings)try{a(P,k,d,!1)}catch(Oe){console.error("[Lego] Error in b-for inner binding:",Oe)}[b,...b.querySelectorAll("*")].filter(P=>K(P)).forEach(P=>{let Be=K(P).value;Be.startsWith(`${f}.`)&&re(P,D(Be.split(".").slice(1).join("."),p[E]))}),x.push(b)});let y=s.nextSibling;x.forEach(w=>{w!==y?s.parentNode.insertBefore(w,y):y=y.nextSibling});for(let[w,E]of m.entries())h.has(w)||(E.remove(),m.delete(w))},destroy({binding:e}){let{anchor:t}=e;if(t&&W.has(t)){let r=W.get(t);r.forEach(o=>{[o,...o.querySelectorAll("*")].forEach(i=>{let a=A.get(i);a&&(a.listeners&&(a.listeners.forEach(({eventName:s,handler:c})=>{i.removeEventListener(s,c)}),a.listeners=null),a.bindings&&(a.bindings.forEach(s=>{s.observer&&(s.observer.disconnect(),s.observer=null)}),a.bindings=null))}),o.remove()}),r.clear(),W.delete(t)}t&&t.parentNode&&t.remove()}};var Ve={scan:e=>{if(e.hasAttribute("b-init"))return{type:"b-init",node:e,expr:e.getAttribute("b-init")}},execute:({binding:e,state:t,global:r})=>{e.initialized||(e.initialized=!0,L(e.expr,{state:t,global:r,self:e.node}))}};var Xe={name:"b-enter",scan:e=>O("b-enter",e,(t,r)=>({modifiers:t.name.split(".").slice(1)})),execute:({binding:e,state:t,global:r})=>{if(e.observer||e.done)return;let o=new IntersectionObserver((n,i)=>{if(n[0].isIntersecting){try{L(e.expr,{state:t,global:r,self:e.node})}catch(s){console.error("[Lego] Error in b-enter handler:",s)}e.modifiers.includes("once")&&(i.disconnect(),e.observer=null,e.done=!0)}});o.observe(e.node),e.observer=o},destroy:({binding:e})=>{e.observer&&(e.observer.disconnect(),e.observer=null)}};var Ze={name:"b-leave",scan:e=>O("b-leave",e),execute:({binding:e,state:t,global:r})=>{if(e.observer||e.done)return;let o=new IntersectionObserver((n,i)=>{let a=n[0];if(a.isIntersecting&&(e.activated=!0),!a.isIntersecting&&e.activated){try{L(e.expr,{state:t,global:r,self:e.node})}catch(s){console.error("[Lego] Error in b-leave handler:",s)}e.modifiers.includes("once")&&(i.disconnect(),e.observer=null,e.done=!0)}});o.observe(e.node),e.observer=o},destroy:({binding:e})=>{e.observer&&(e.observer.disconnect(),e.observer=null)}};var Qe={name:"b-mount",scan:(e,{checkGlobal:t})=>O("b-mount",e,r=>(t(r.value),{_lastTag:null})),execute({binding:e,state:t,global:r}){let{node:o,expr:n}=e,i=L(n,{state:t,global:r,self:o},!1),a=i?String(i).toLowerCase():null;a!==e._lastTag&&(e._lastTag=a,F(a,o))},destroy({binding:e}){e.node&&F(null,e.node),e._lastTag=null}};var se={"b-if":qe,"b-show":je,"b-text":Ke,"b-html":Ge,"b-sync":Ue,"b-for":Je,"b-init":Ve,"b-enter":Xe,"b-leave":Ze,"b-mount":Qe};var At=(e=null)=>{let t=!1,r=new Set,o=!1,n=e,i=new Set,a=null,s=new Set,c=d=>{n=d},f=()=>{a||(a=setTimeout(()=>{s.forEach(d=>{let p=d._studs;if(p&&typeof p.updated=="function")try{p.updated.call(p)}catch(m){console.error("[Lego] Error in updated hook:",m)}}),s.clear(),a=null},50))},l=()=>{i.size>0&&(i.forEach(d=>r.add(d)),i.clear(),!t&&r.size>0&&(t=!0,requestAnimationFrame(u)))},u=()=>{o=!0;let d=Array.from(r);r.clear(),t=!1,d.forEach(p=>{p.isConnected&&n&&n(p)}),d.forEach(p=>s.add(p)),f(),o=!1,l()};return{add:d=>{if(d){if(o){i.add(d);return}r.add(d),!t&&(t=!0,requestAnimationFrame(u))}},setHandler:c}},X=At();var N=new Map,he=new Map,ie=new WeakMap,le=new Map,ae=new WeakMap,ce=!1,kt=e=>{let t=Array.from(le.entries()).sort((n,i)=>n[1].timestamp-i[1].timestamp),r=0,o=[];for(let[n,i]of t){if(r>=e)break;try{localStorage.removeItem(n),r+=i.size,o.push(n),le.delete(n)}catch(a){console.error(`[Lego] Failed to evict ${n}:`,a)}}return o},et=(e,t,r)=>{g.debug&&console.log("[Lego Trace] scheduleSave",e,t,r),he.has(e)&&clearTimeout(he.get(e));let o=()=>{try{let n=JSON.stringify(t),i=new Blob([n]).size;localStorage.setItem(e,n),le.set(e,{timestamp:Date.now(),size:i}),he.delete(e)}catch(n){if(n.name==="QuotaExceededError"){console.warn(`[Lego] Storage quota exceeded for key: ${e}`);try{let i=JSON.stringify(t),a=new Blob([i]).size,s=kt(a*2);s.length>0?(g.debug&&console.log(`[Lego] Evicted ${s.length} old keys, retrying save`),localStorage.setItem(e,i),le.set(e,{timestamp:Date.now(),size:a})):g.onError(new Error("Storage quota exceeded and no keys available for eviction"),"quota",e)}catch{g.onError(new Error(`Critical: Could not save ${e} even after eviction`),"quota-critical",e)}}else console.error(`[Lego] Storage Error (${e}):`,n)}};r>0?he.set(e,setTimeout(o,r)):o()},Le=e=>({__type:"lego-db",key:e,_default:void 0,_debounce:0,default(r){return this._default=r,this},debounce(r){return this._debounce=r,this},set(r,o=0){return et(e,r,o),N.has(e)&&N.get(e).forEach(({target:n,prop:i,el:a,batcher:s})=>{n[i]=r,a&&s&&s.add(a)}),r},get(){try{let r=localStorage.getItem(e);return r!==null?JSON.parse(r):null}catch(r){return console.warn(`[Lego] Failed to get localStorage value for key "${e}":`,r),null}},delete(){try{return localStorage.removeItem(e),le.delete(e),N.has(e)&&N.get(e).forEach(({target:r,prop:o,el:n,batcher:i})=>{r[o]=null,n&&i&&i.add(n)}),!0}catch(r){return console.error(`[Lego] Failed to delete localStorage key "${e}":`,r),!1}}}),tt=e=>e&&e.__type==="lego-db",rt=(e,t,r,o,n)=>{g.debug&&console.log("[Lego Trace] Reactive DB Init:",t,r);let i=r._default;try{let s=localStorage.getItem(r.key);s!==null&&(i=JSON.parse(s))}catch(s){console.warn(`[Lego] Failed to parse localStorage value for key "${r.key}":`,s)}e[t]=i,ie.has(e)||ie.set(e,{}),ie.get(e)[t]={key:r.key,debounce:r._debounce},g.debug&&console.log("[Lego Trace] DB Metadata Set:",t,ie.get(e)[t]),N.has(r.key)||N.set(r.key,new Set);let a={target:e,prop:t,el:o,batcher:n};N.get(r.key).add(a),o&&(ae.has(o)||ae.set(o,new Set),ae.get(o).add({key:r.key,entry:a}))},ot=(e,t,r)=>{if(ce)return;let o=ie.get(e);if(o&&o[t]){let n=o[t].key;if(et(n,r,o[t].debounce),N.has(n)){ce=!0;try{N.get(n).forEach(({target:i,prop:a,el:s,batcher:c})=>{i!==e&&(i[a]=r,s&&c&&c.add(s))})}finally{ce=!1}}}},nt=e=>{let t=ae.get(e);t&&(t.forEach(({key:r,entry:o})=>{let n=N.get(r);n&&n.delete(o)}),ae.delete(e))},Ye=!1,st=()=>{typeof window>"u"||Ye||(Ye=!0,window.addEventListener("storage",e=>{if(!(!e.key||!N.has(e.key)))try{let t=e.newValue===null?null:JSON.parse(e.newValue);ce=!0;try{N.get(e.key).forEach(({target:r,prop:o,el:n,batcher:i})=>{r[o]=t,n&&i&&i.add(n)})}finally{ce=!1}}catch(t){console.warn("[Lego] Cross-tab sync error:",t)}}))};var Te=new WeakMap,be=null,Ae=null,it=(e,t)=>{be=e,Ae=t},at=()=>{be=null,Ae=null},ct=(e,t,r)=>{if(!be||Ae!==e)return;let o=Te.get(e);o||(o=new Map,Te.set(e,o));let n=o.get(t);n||(n=new Map,o.set(t,n));let i=n.get(r);i||(i=new Set,n.set(r,i)),i.add(be)},lt=(e,t,r)=>{let o=Te.get(e);if(!o)return null;let n=o.get(t);return n&&n.get(r)||null};var Z=(e,t,r=X)=>{if(e===null||typeof e!="object"||ve(e))return e;if(Y.has(e))return Y.get(e);for(let i in e){let a=Object.getOwnPropertyDescriptor(e,i);if(a&&a.get)continue;let s=e[i];tt(s)&&rt(e,i,s,t,r)}let o={get:(i,a,s)=>{ct(t,i,a);let c=Reflect.get(i,a,s);return c!==null&&typeof c=="object"&&!ve(c)?Z(c,t,r):c},set:(i,a,s,c)=>{if(a==="__proto__"||a==="constructor"||a==="prototype")return console.warn(`[Lego] Blocked setting dangerous property: "${a}"`),!0;let f=i[a];g.debug&&f!==s&&console.log("[Lego Trace] Reactive SET:",a,"Old:",f,"New:",s,"Target:",i);let l=c===Y.get(i),u=Object.prototype.hasOwnProperty.call(i,a),d=!l&&u?Reflect.set(i,a,s):Reflect.set(i,a,s,c);if((l||u)&&f!==s){let p=lt(t,i,a);if(p&&p.size>0){let m=A.get(t);m&&(m.dirtyBindings||(m.dirtyBindings=new Set),p.forEach(h=>m.dirtyBindings.add(h)))}r.add(t,a),ot(i,a,s)}return d},deleteProperty:(i,a)=>{let s=Reflect.deleteProperty(i,a),c=A.get(t);return c&&(c.dirtyBindings=null),r.add(t),s}},n=new Proxy(e,o);return Y.set(e,n),n};var Nt=e=>{let t=e;for(;t;){let r=t.getAttribute&&t.getAttribute("b-error");if(r&&r.toLowerCase()!==e.tagName.toLowerCase())return{errorTag:r,targetElement:t};let o=t.tagName?t.tagName.toLowerCase():"",n=S[o];if(n){let i=n.getAttribute("b-error");if(i&&i.toLowerCase()!==e.tagName.toLowerCase())return{errorTag:i,targetElement:t}}t=t.parentElement||t.getRootNode&&t.getRootNode().host}return null},ke=null,ft=null,dt=(e,t)=>{ke=e,ft=t},Ct=(e,t,r)=>{if(!ke||!ft){console.error("[Lego] Error boundary dependencies not loaded",r);return}try{t.shadowRoot?t.shadowRoot.innerHTML="":t.innerHTML="";let o=document.createElement(e);o.$initialState={$error:{message:r.message,stack:r.stack,component:t.tagName.toLowerCase()}},(t.shadowRoot||t).appendChild(o),ke(o)}catch(o){console.error("[Lego] Error boundary failed to render:",o),console.error("[Lego] Original error:",r)}},fe=new WeakMap,Mt=3,Q=(e,t,r)=>{let o=Nt(t);if(!o){g.onError(e,r,t);return}let n=o.targetElement,i=fe.get(n)||0;if(i>=Mt){console.error("[Lego] Error boundary recursion limit reached:",e),g.onError(e,r,t);return}fe.set(n,i+1);try{Ct(o.errorTag,n,e)}finally{let a=(fe.get(n)||0)-1;a<=0?fe.delete(n):fe.set(n,a)}};var ye=(e,t,r=null)=>{let o=t._studs,n=s=>{let c=M(s);if(!c.bound){if(s.hasAttributes()){let f=s.attributes;for(let u=0;u<f.length;u++){let d=f[u];if(d.name.startsWith("@")){let p=d.name.slice(1).split("."),m=p[0],h=p.slice(1),x=y=>{if(h.includes("prevent")&&y.preventDefault(),h.includes("stop")&&y.stopPropagation(),!(h.includes("self")&&y.target!==y.currentTarget)){if(typeof KeyboardEvent<"u"&&y instanceof KeyboardEvent){if(h.includes("ctrl")&&!y.ctrlKey||h.includes("alt")&&!y.altKey||h.includes("shift")&&!y.shiftKey||h.includes("meta")&&!y.metaKey)return;let w=h.filter(E=>!["prevent","stop","self","ctrl","alt","shift","meta","capture","once","passive"].includes(E));if(w.length>0){let E=y.key.toLowerCase();if(!w.some(b=>b==="enter"?E==="enter":b==="esc"||b==="escape"?E==="escape":b==="space"?E===" ":b==="tab"?E==="tab":b==="delete"?E==="delete":b==="backspace"?E==="backspace":b==="up"?E==="arrowup":b==="down"?E==="arrowdown":b==="left"?E==="arrowleft":b==="right"?E==="arrowright":b==="alpha"?/^[a-z]$/.test(E):b==="numbers"?/^[0-9]$/.test(E):b===E))return}}try{let w=o;if(r){let $=L(r.listName,{state:o,global:_,self:t})[r.index];w=Object.assign(Object.create(o),{[r.name]:$})}L(d.value,{state:w,global:_,self:s,event:y,$event:y},!0)}catch(w){Q(w,t,"event-handler")}}};s.addEventListener(m,x),c.listeners||(c.listeners=[]),c.listeners.push({eventName:m,handler:x})}}let l=K(s);if(l){let u=l.value,d=l.name.split(".").slice(1),p=d.includes("lazy"),m=d.includes("number"),h=d.includes("trim"),x=()=>{try{let y,w;if(u.startsWith("global.")){let $=u.slice(7).split(".");w=$.pop(),y=$.reduce((b,k)=>b[k],_)}else if(r&&u.startsWith(`${r.name}.`)){let b=L(r.listName,{state:o,global:_,self:t})[r.index];if(!b)return;let k=u.split(".").slice(1);w=k.pop(),y=k.reduce((Me,P)=>Me[P],b)}else{let $=u.split(".");w=$.pop(),y=$.reduce((b,k)=>b[k],o)}let E=s.type==="checkbox"?s.checked:s.value;if(h&&typeof E=="string"&&(E=E.trim()),m){let $=parseFloat(E);isNaN($)||(E=$)}y&&y[w]!==E&&(y[w]=E)}catch(y){g.onError(y,"sync-update",s)}};s._bSyncHandler=x,c.listeners||(c.listeners=[]),p||(s.addEventListener("input",x),c.listeners.push({eventName:"input",handler:x})),s.addEventListener("change",x),c.listeners.push({eventName:"change",handler:x})}if(s.hasAttribute("b-var")){let u=s.getAttribute("b-var");o.$vars&&(o.$vars[u]=s)}}c.bound=!0}};e instanceof Element&&n(e);let i=document.createTreeWalker(e,NodeFilter.SHOW_ELEMENT),a;for(;a=i.nextNode();)n(a)},ut=(e,t=null)=>{let r=[],o=[],[n]=oe(),i=t||e.host||e,a=Object.entries(se),s=/\bglobal\.([\w$]+)([\w$.]*)/g,c=l=>{if(!/\bglobal\b/.test(l))return;let u=!1,d=new Set,p;for(s.lastIndex=0;(p=s.exec(l))!==null;){if((p[2]||"").includes(".")){u=!0;break}d.add(p[1])}if(d.size===0&&(u=!0),u){U.add(i);return}d.forEach(m=>{let h=I.get(m);h||(h=new Set,I.set(m,h)),h.add(i)})},f=l=>{if(l.nodeType===Node.ELEMENT_NODE){let u=!1;for(let[,d]of a){if(!d.scan)continue;let p=d.scan(l,{checkGlobal:c,getPrivateData:M,pendingOperations:o,current:l});p&&(r.push(p),p.terminal&&(u=!0))}if(u)return;for(let d of l.attributes)d.value.includes(n)&&(c(d.value),r.push({type:"attr",node:l,attrName:d.name,template:d.value}));for(let d=l.firstChild;d;d=d.nextSibling)f(d)}else l.nodeType===Node.TEXT_NODE&&l.textContent.includes(n)&&(c(l.textContent),r.push({type:"text",node:l,template:l.textContent}))};if(e.nodeType===Node.ELEMENT_NODE)for(let l of e.attributes)l.value.includes(n)&&(c(l.value),r.push({type:"attr",node:e,attrName:l.name,template:l.value}));else e.nodeType===Node.TEXT_NODE&&e.textContent.includes(n)&&(c(e.textContent),r.push({type:"text",node:e,template:e.textContent}));for(let l=e.firstChild;l;l=l.nextSibling)f(l);return o.forEach(l=>l()),r},Ne=(e,t,r,o=!0)=>{if(!e.dead){o&&it(e,r);try{let n=se[e.type];if(n){n.execute({binding:e,state:t,global:_,helpers:{bind:ye,scanForBindings:ut,runBinding:Ne,contextEl:r}});return}if(e.type==="text"){let i=e.template.replace(we(),(a,s)=>L(s.trim(),{state:t,global:_,self:e.node},!1)??"");e.node.textContent!==i&&(e.node.textContent=i)}else if(e.type==="attr"){let i=e.template.replace(we(),(a,s)=>L(s.trim(),{state:t,global:_,self:e.node},!1)??"");e.node.getAttribute(e.attrName)!==i&&(e.node.setAttribute(e.attrName,i),e.attrName==="class"&&(e.node.className=i))}}finally{o&&at()}}},de=e=>{g.debug&&console.log("[Lego Trace] render() called for:",e.tagName);let t=e._studs;if(!t)return;let r=M(e);if(!r.rendering){r.rendering=!0,g.metrics&&g.metrics.onRenderStart&&g.metrics.onRenderStart(e);try{let o=e.shadowRoot||e;if(r.bindings||(r.bindings=ut(o)),r.dirtyBindings&&r.dirtyBindings.size>0){let n=r.dirtyBindings;r.dirtyBindings=null,n.forEach(i=>Ne(i,t,e))}else r.bindings.forEach(n=>Ne(n,t,e))}catch(o){Q(o,e,"render")}finally{g.metrics&&g.metrics.onRenderEnd&&g.metrics.onRenderEnd(e),r.rendering=!1}}};var pt=new Map,H=new Map,mt={},gt=e=>{mt=e},ht=async()=>{let e=Object.entries(mt).map(async([t,r])=>{let o=await Promise.all(r.map(async n=>{try{if(n instanceof CSSStyleSheet)return n;let i=await fetch(n);if(!i.ok)throw new Error(`Status ${i.status}`);let a=await i.text(),s=new CSSStyleSheet;return await s.replace(a),s}catch(i){return console.error(`[Lego] Failed to load stylesheet: ${n}`,i),null}}));pt.set(t,o.filter(n=>n!==null))});await Promise.all(e),g.debug&&console.log("[Lego Debug] Re-applying stylesheets to",C.size,"blocks"),C.forEach(t=>{Ce(t)})},Ce=e=>{if(!e.shadowRoot&&!e._legoShadow)return;let t=e.shadowRoot||e._legoShadow,r=e.tagName.toLowerCase(),o=S[r],n=(o&&o.getAttribute("b-stylesheets")||"").split(/\s+/).filter(Boolean),i=(e.getAttribute("b-stylesheets")||"").split(/\s+/).filter(Boolean),a=[],s=e.parentElement||(e.getRootNode?e.getRootNode().host:null);for(;s;){let u=(s.getAttribute("b-cascade")||"").split(/\s+/).filter(Boolean);u.length&&a.push(...u);let d=s.tagName?s.tagName.toLowerCase():"",p=H.get(d);p&&p.length&&a.push(...p),s=s.parentElement||s.getRootNode&&s.getRootNode().host}let c=[...new Set([...n,...i])],f=[...new Set(a)],l=[...new Set([...f,...c])];if(l.length>0){let u=l.flatMap(d=>pt.get(d)||[]);if(u.length>0&&g.debug&&console.log("[Lego Debug] Applying styles to",e.tagName,"- Names:",l,"- Sheets:",u.length),u.length>0){let d=t.adoptedStyleSheets.filter(p=>!u.includes(p));t.adoptedStyleSheets=[...d,...u]}}e._studsMeta={stylesheets:{explicit:c,inherited:f,applied:l}}};var bt=!1,T=e=>{if(g.debug&&console.log("[Lego Trace] snap() called for:",e.tagName),!e||e.nodeType!==Node.ELEMENT_NODE)return;let t=M(e),r=e.tagName.toLowerCase(),o=S[r];if(o&&!t.snapped){t.snapped=!0;let i=o.content.cloneNode(!0),a=e.shadowRoot;a?a.innerHTML="":a=e.attachShadow({mode:"open"}),Ce(e);let s=V(e,"*")||V(e.getRootNode().host,"*"),c=s&&s.state?s.state:{},f=q.get(r)||{},l=_e(o.getAttribute("b-logic")||o.getAttribute("b-data")||"{}"),u=_e(e.getAttribute("b-logic")||e.getAttribute("b-data")||"{}",c),d={$vars:{},$element:e,get $parent(){return V(e,"*")},$emit:(h,x)=>{e.dispatchEvent(new CustomEvent(h,{detail:x,bubbles:!0,composed:!0}))},get $route(){return _.$route},get $go(){return _.$go},get $mount(){return _.$mount}};G(f,d),G(l,d),G(u,d),e.$initialState&&(G(e.$initialState,d),delete e.$initialState),z.validate({instanceLogic:u,state:d,tagName:r}),e._studs=Z(d,e),Object.defineProperty(e,"state",{get(){return this._studs},set(h){bt||(bt=!0,console.warn("[Lego] `el.state = X` performs a shallow merge (Object.assign), not a replacement. Keys present on state but absent from X are preserved. Mutate state keys directly if you want this behaviour or remount the element to start fresh.")),Object.assign(this._studs,h)},configurable:!0,enumerable:!1}),j.locked=!0;try{a.appendChild(i)}finally{j.locked=!1}let p=a.querySelector("style");if(p){let h=[],x="__LEGO_SEG_",w=p.textContent.replace(/\/\*[\s\S]*?\*\/|"(?:\\.|[^"\\])*"|'(?:\\.|[^'\\])*'/g,E=>(h.push(E),`${x}${h.length-1}__`)).replace(/(?<![-\w])self(?![-\w])/g,":host");p.textContent=w.replace(/__LEGO_SEG_(\d+)__/g,(E,$)=>h[+$])}if(ye(a,e),C.add(e),de(e),e.setAttribute("b-id",r),e._legoShadow||(e._legoShadow=a),typeof e._studs.mounted=="function")try{e._studs.mounted.call(e._studs)}catch(h){Q(h,e,"mounted")}let m=a.querySelectorAll("*");g.debug&&console.log("[Lego Debug] Nested scan in",e.tagName,"- Found elements:",m.length),m.forEach(h=>{let x=h.tagName.toLowerCase(),y=!!S[x];y&&g.debug&&console.log("[Lego Debug] Checking",x,"- Registered:",y),y&&T(h)})}let n=e.parentElement;for(;n&&!n._studs;)n=n.parentElement;n&&n._studs&&ye(e,n),[...e.children].forEach(T)},B=e=>{if(e._studs&&typeof e._studs.unmounted=="function")try{e._studs.unmounted.call(e._studs)}catch(r){Q(r,e,"unmounted")}if(e.shadowRoot){let r=document.createTreeWalker(e.shadowRoot,NodeFilter.SHOW_ELEMENT),o;for(;o=r.nextNode();){let n=A.get(o);n&&n.listeners&&(n.listeners.forEach(({eventName:i,handler:a})=>{o.removeEventListener(i,a)}),n.listeners=null)}[...e.shadowRoot.children].forEach(B)}nt(e),C.delete(e),U.delete(e),I.forEach(r=>r.delete(e)),e._studs&&(e._studs.$element=null,e._studs.$vars&&(Object.keys(e._studs.$vars).forEach(r=>{e._studs.$vars[r]=null}),e._studs.$vars=null),e._studs.$emit&&(e._studs.$emit=null),delete e._studs.$parent,delete e._studs.$route,delete e._studs.$go,delete e._studs.$mount,e._studs=null),e.hasOwnProperty("state")&&delete e.state;let t=A.get(e);t&&(t.bindings&&(t.bindings.forEach(r=>{let o=se[r.type];if(o&&o.destroy)try{o.destroy({binding:r})}catch(n){console.error(`[Lego] Error in directive cleanup (${r.type}):`,n)}r.node=null,r.anchor=null}),t.bindings=null),t.anchor=null,A.delete(e)),[...e.children].forEach(B)};function yt(e,t="block.lego"){let r={template:"",script:"",style:"",stylesAttr:"",cascadeAttr:"",errorAttr:"",propsAttr:"",blockName:Pe(t),hasTemplate:!1,hasScript:!1,hasStyle:!1},o=e,n=/<(template|script|style)\b((?:\s+(?:[^>"']|"[^"]*"|'[^']*')*)*)>/i;for(;o;){let i=o.match(n);if(!i)break;let a=i[1].toLowerCase(),s=i[2],c=i[0],f=i.index,l=`</${a}>`,u=f+c.length,d=o.indexOf(l,u);if(d===-1){console.warn(`[Lego] Unclosed <${a}> tag in ${t}`);break}let p=o.slice(u,d);if(a==="template"){r.hasTemplate=!0,r.template=p.trim();let m=s.match(/b-stylesheets=["']([^"']+)["']/);m&&(r.stylesAttr=m[1]);let h=s.match(/b-cascade=["']([^"']+)["']/);h&&(r.cascadeAttr=h[1]);let x=s.match(/b-error=["']([^"']+)["']/);x&&(r.errorAttr=x[1]);let y=s.match(/b-props=["']([^"']+)["']/);y&&(r.propsAttr=y[1])}else if(a==="script"){r.hasScript=!0,r.script=p.trim();let m=s.match(/lang=["']([^"']+)["']/);m&&(r.scriptLang=m[1])}else a==="style"&&(r.hasStyle=!0,r.style=p.trim());o=o.slice(d+l.length)}return r}var Et=(e,t,r="block.lego")=>{let o=yt(t,r),{blockName:n,template:i,script:a,style:s,stylesAttr:c,cascadeAttr:f,errorAttr:l,propsAttr:u}=o,d={};if(a)try{let m=a.trim(),h=m.match(/export\s+default\s+(?:\/\*[\s\S]*?\*\/\s*|\/\/[^\n]*\n\s*)*({[\s\S]*})/),x=h?h[1]:m;d=new Function("Lego","$db",`return ${x}`)(e,e.globals.$db)}catch(m){g.onError(m,"script",n)}let p=i;s&&(p=`<style>${s}</style>`+p),S[n]=document.createElement("template"),S[n].innerHTML=p,c&&S[n].setAttribute("b-stylesheets",c),f&&(S[n].setAttribute("b-cascade",f),H.set(n,f.split(/\s+/).filter(Boolean))),l&&S[n].setAttribute("b-error",l),u&&S[n].setAttribute("b-props",u),z.register(n,u),q.set(n,d),document.querySelectorAll(n).forEach(m=>!M(m).snapped&&T(m))};X.setHandler(de);dt(T,de);Fe(T);He(T,B);var Ot={url:typeof window<"u"?window.location.pathname:"/",route:"",params:{},query:{},method:"GET",body:null},Bt={add(e,t){if(t!==void 0){let r=I.get(t);r&&r.forEach(o=>X.add(o))}U.forEach(r=>X.add(r))}},R=Z({$route:Ot,$go:(e,...t)=>ge(e,...t)(document.body),$mount:(e,t,r)=>F(e,t,r),$db:Le},typeof document<"u"?document.body:null,Bt);De(R);var v={db:Le,snap:T,unsnap:B,mount:F,defineLegoFile:(e,t)=>Et(v,e,t),block:(e,t,r={},o="",n="",i="",a="")=>{let s=document.createElement("template");s.setAttribute("b-id",e),s.setAttribute("b-stylesheets",o),n&&s.setAttribute("b-cascade",n),i&&s.setAttribute("b-error",i),a&&s.setAttribute("b-props",a),s.innerHTML=t,S[e]=s,q.set(e,r),z.register(e,a),n?H.set(e,n.split(/\s+/).filter(Boolean)):H.delete(e);try{let c={};G(r,c),ee.set(e.toLowerCase(),Z(c,document.body))}catch(c){g.onError(c,"define",e)}if(customElements.get(e))document.querySelectorAll(e).forEach(c=>{B(c),T(c)}),C.forEach(c=>{c._legoShadow&&c._legoShadow.querySelectorAll(e).forEach(f=>{B(f),T(f)})});else try{customElements.define(e,class extends HTMLElement{connectedCallback(){j.locked||S[e]&&T(this)}disconnectedCallback(){B(this)}})}catch(c){console.warn(`[Lego] Failed to register web component ${e}:`,c),delete S[e],q.delete(e),z.unregister(e),ee.delete(e.toLowerCase()),H.delete(e);return}},getActiveBlocksCount:()=>C.size,getLegos:()=>Object.keys(S),config:g,globals:R,route:(e,t,r=null)=>{let o=[],n=e.replace(/:([^\/]+)|\*|[.+?^${}()|[\]\\]/g,(i,a)=>a?(o.push(a),"([^/]+)"):i==="*"?".*":"\\"+i);ne.push({path:e,regex:new RegExp(`^${n}$`),tagName:t,paramNames:o,middleware:r})},debug:{stylesheets:e=>!e||!e._studsMeta?null:e._studsMeta.stylesheets},init:async(e=document.body,t={})=>{if((!e||typeof e.nodeType!="number")&&(e=document.body),gt(t.styles||{}),g.loader=t.loader,g.debug=t.debug===!0,await ht(),ne.length>0){let s=window.location.pathname,c=window.location.search,f=xe(s);if(f){let{match:l,params:u}=f,d=Object.fromEntries(new URLSearchParams(c));R.$route.url=s+c,R.$route.route=l.path,R.$route.params=u,R.$route.query=d,R.$route.method="GET",R.$route.body=null}}document.querySelectorAll("template[b-id]").forEach(s=>{let c=s.getAttribute("b-id");S[c]=s,z.register(c,s.getAttribute("b-props"));let f=s.getAttribute("b-cascade")||"";f&&H.set(c,f.split(/\s+/).filter(Boolean)),customElements.get(c)||customElements.define(c,class extends HTMLElement{connectedCallback(){j.locked||S[c]&&T(this)}disconnectedCallback(){B(this)}})});let r=/^[a-z][a-z0-9]*(-[a-z0-9]+)+$/,o=g.loaderAllowlist,n=s=>o?(Array.isArray(o)?o:[o]).some(f=>typeof f=="string"?f===s:typeof f=="function"?!!f(s):f&&typeof f.test=="function"?!!f.test(s):!1):!0,i=s=>{if(!s)return{};let c={};return Object.entries(s).forEach(([f,l])=>{if(typeof l=="function")c[f]=l();else if(typeof l=="string"&&l.startsWith("$db.")){let u=l.slice(4);c[f]=v.db(u).get()}else if(typeof l=="string"&&l.startsWith("$globals.")){let u=l.slice(9);c[f]=_[u]}else c[f]=l}),c},a=(s,c,f={})=>{if(!customElements.get(s)){if(!r.test(s)){console.warn(`[Lego] Manifest skipped malformed tag "${s}"`);return}if(!n(s)){console.warn(`[Lego] Manifest skipped "${s}": not in loaderAllowlist`);return}customElements.define(s,class extends HTMLElement{async connectedCallback(){if(S[s]){j.locked||T(this);return}if(v._fetching||(v._fetching=new Set),v._pendingLazy||(v._pendingLazy={}),v._fetching.has(s)){v._pendingLazy[s]||(v._pendingLazy[s]=new Set),v._pendingLazy[s].add(this);return}v._fetching.add(s);try{let l=c.startsWith("POST:")?"POST":"GET",u=c.replace(/^POST:/,""),d=i(f.headers),p={method:l,headers:d,credentials:f.credentials},m=await fetch(u,p);if(!m.ok)throw new Error(`HTTP ${m.status} loading block "${s}" from ${u}`);let h=await m.text();v.defineLegoFile(h,`${s}.lego`),S[s]&&T(this);let x=v._pendingLazy[s];x&&(x.forEach(y=>{y.isConnected&&S[s]&&!M(y).snapped&&T(y)}),delete v._pendingLazy[s])}catch(l){console.error(`[Lego] Failed to load manifest block ${s}:`,l)}finally{v._fetching.delete(s)}}disconnectedCallback(){B(this)}})}};if(t.manifest){let s=t.manifest;if(s.url&&typeof s.url=="string")try{let f=i(s.headers);s=await(await fetch(s.url,{headers:f,credentials:s.credentials})).json()}catch(f){console.error("[Lego] Failed to load manifest:",f),s=[]}else if(typeof s=="string")try{s=await(await fetch(s)).json()}catch(f){console.error("[Lego] Failed to load manifest:",f),s=[]}let c=Array.isArray(s)?s:[s];for(let f of c){let l=f.base||"",u=f.suffix===!0?".lego":f.suffix||"",d={headers:f.headers||{},credentials:f.credentials};f.legos&&f.legos.forEach(p=>{a(p,`${l}${p}${u}`,d)}),f.map&&Object.entries(f.map).forEach(([p,m])=>{let h=m.match(/^https?:|^\//)?m:`${l}${m}`;a(p,h,d)})}}if(g.loader){let s=!1,c=l=>{if(l.nodeType!==Node.ELEMENT_NODE)return;let u=l.tagName.toLowerCase();if(u.includes("-")&&!S[u]&&!C.has(l)){if(v._fetching&&v._fetching.has(u))return;if(!r.test(u)){g.debug&&console.warn(`[Lego] Loader skipped malformed tag "${u}"`);return}if(!n(u)){g.debug&&console.warn(`[Lego] Loader skipped "${u}": not in loaderAllowlist`);return}!o&&!s&&(s=!0,console.warn("[Lego] config.loader is set without config.loaderAllowlist. Any unknown hyphenated tag inserted into the page will trigger a fetch. Set Lego.config.loaderAllowlist to restrict this.")),v._fetching||(v._fetching=new Set),v._fetching.add(u);let d=g.loader(u);if(d){let p=typeof d=="string"?fetch(d).then(m=>m.text()):d;Promise.resolve(p).then(m=>{v.defineLegoFile(m,`${u}.lego`),v._fetching.delete(u)}).catch(m=>{console.error(`[Lego] Failed to load ${u}:`,m),v._fetching.delete(u)})}}if(l.children.length>0){let d=l.firstElementChild;for(;d;)c(d),d=d.nextElementSibling}};v._discoveryObserver&&v._discoveryObserver.disconnect(),v._discoveryObserver=new MutationObserver(l=>l.forEach(u=>{u.addedNodes.forEach(c)})),v._discoveryObserver.observe(e,{childList:!0,subtree:!0});let f=e.firstElementChild;for(;f;)c(f),f=f.nextElementSibling}if(t.studio){if(!S["lego-studio"]){let s=document.createElement("script");s.src="https://unpkg.com/@legodom/studio@0.0.2/dist/lego-studio.js",s.onerror=()=>console.warn("[Lego] Failed to load Studio from CDN"),document.head.appendChild(s)}v.route("/_/studio","lego-studio"),v.route("/_/studio/:block","lego-studio")}ne.length>0&&(window.addEventListener("popstate",s=>{let c=s.state?.legoTargets||null;me(c)}),document.addEventListener("submit",s=>{s.target.hasAttribute("b-action")&&s.preventDefault()}),document.addEventListener("click",s=>{let f=s.composedPath().find(l=>l.tagName==="A"&&(l.hasAttribute("b-target")||l.hasAttribute("b-link")));if(f){s.preventDefault();let l=f.getAttribute("href"),u=f.getAttribute("b-target"),d=u?u.split(/\s+/).filter(Boolean):[],p=f.getAttribute("b-link")!=="false";R.$go(l,...d).get(p)}}),me()),st()}};typeof window<"u"?window.Lego=v:typeof global<"u"&&(global.Lego=v);var xn=v;})();
|
package/dist/lego.mjs
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
|
-
var
|
|
1
|
+
var S={},Y=new WeakMap,A=new WeakMap,W=new WeakMap,ue=new WeakMap,C=new Set,U=new Set,I=new Map,q=new Map,ee=new Map;var j={locked:!1},M=e=>(A.has(e)||A.set(e,{snapped:!1,bindings:null,bound:!1,rendering:!1,anchor:null}),A.get(e));var wt=/^[a-zA-Z_$][\w$]*$/,J=new Map,vt=(e,t="<unknown>")=>{if(!e||typeof e!="string")return null;let r=e.trim();if(!r||r.startsWith("{")&&r.endsWith("}")&&(r=r.slice(1,-1).trim(),!r))return null;let o=r.split(",").map(i=>i.trim()).filter(Boolean);if(o.length===0)return null;let n=[];for(let i of o){if(!wt.test(i))return console.error(`[Lego] Invalid b-props on <${t}>: token "${i}" is not a bare identifier. b-props declares names only \u2014 use b-logic for values. Got: "${e}"`),null;n.push(i)}return n},z={register(e,t){if(!t){J.delete(e);return}let r=vt(t,e);r?J.set(e,r):J.delete(e)},unregister(e){J.delete(e)},get(e){return J.get(e)||null},validate({instanceLogic:e,state:t,tagName:r}){let o=J.get(r);if(o){if(e)for(let n of Object.keys(e))o.includes(n)||console.warn(`[Lego] <${r}> received b-logic key "${n}" not declared in b-props. Declared: { ${o.join(", ")} }.`);for(let n of o)t[n]===void 0&&console.warn(`[Lego] <${r}> is missing prop "${n}" (declared in b-props but not provided).`)}}};var _={},De=e=>{_=e};var te=class{constructor(t=1e3){this.limit=t,this.cache=new Map}get(t){if(!this.cache.has(t))return;let r=this.cache.get(t);return this.cache.delete(t),this.cache.set(t,r),r}set(t,r){if(this.cache.has(t))this.cache.delete(t);else if(this.cache.size>=this.limit){let o=this.cache.keys().next().value;this.cache.delete(o)}this.cache.set(t,r)}get size(){return this.cache.size}clear(){this.cache.clear()}};var V=(e,t)=>{if(!e)return;let r=e.parentElement||(e.getRootNode?e.getRootNode().host:null);for(;r;){let o=r.tagName?r.tagName.toLowerCase():"";if(o&&(t==="*"&&S[o]||o===t.toLowerCase()))return r;r=r.parentElement||r.getRootNode&&r.getRootNode().host}},pe=(e,t)=>{if(typeof e=="function"){let o=Array.from(document.querySelectorAll("*")).filter(n=>n.tagName.includes("-"));return[].concat(e(o))}if(e.startsWith("#")){let o=document.getElementById(e.slice(1));return o?[o]:[]}let r=t?.querySelectorAll(e)||[];return r.length>0?[...r]:[...document.querySelectorAll(e)]},K=e=>e.attributes?[...e.attributes].find(t=>t.name==="b-sync"||t.name.startsWith("b-sync.")):null,St=new Set(["script","iframe","object","embed","link","meta","base","style"]),xt=new Set(["href","src","xlink:href","action","formaction","srcdoc","data"]),Re=e=>{if(typeof e!="string"||e===""||typeof document>"u")return e;let t=document.createElement("template");t.innerHTML=e;let r=document.createTreeWalker(t.content,NodeFilter.SHOW_ELEMENT),o=[],n;for(;n=r.nextNode();){if(St.has(n.tagName.toLowerCase())){o.push(n);continue}for(let i=n.attributes.length-1;i>=0;i--){let a=n.attributes[i],s=a.name.toLowerCase();if(s.startsWith("on")){n.removeAttribute(a.name);continue}if(xt.has(s)){let c=a.value.trim().toLowerCase();(c.startsWith("javascript:")||c.startsWith("data:text/html")||c.startsWith("vbscript:"))&&n.removeAttribute(a.name)}}}return o.forEach(i=>i.remove()),t.innerHTML},re=(e,t)=>{if(e.type==="checkbox")e.checked!==!!t&&(e.checked=!!t);else if(e.type==="radio"){let r=t!=null&&String(t)===e.value;e.checked!==r&&(e.checked=r)}else{let r=t==null?"":String(t);e.value!==r&&(e.value=r)}};var g={onError:(e,t,r)=>{console.error(`[Lego Error] [${t}]`,e,r)},metrics:{},debug:!1,syntax:"brackets",sanitize:null,loaderAllowlist:null},G=(e,t)=>{!e||!t||Object.getOwnPropertyNames(e).forEach(r=>{let o=Object.getOwnPropertyDescriptor(e,r);Object.defineProperty(t,r,o)})},oe=()=>g.syntax==="brackets"?["[[","]]"]:["{{","}}"],Ee=new Map,we=()=>{let[e,t]=oe(),r=e+t;if(Ee.has(r)){let a=Ee.get(r);return a.lastIndex=0,a}let o=e.replace(/[.*+?^${}()|[\]\\]/g,"\\$&"),n=t.replace(/[.*+?^${}()|[\]\\]/g,"\\$&"),i=new RegExp(`${o}(.*?)${n}`,"g");return Ee.set(r,i),i},Pe=e=>{let r=e.split("/").pop().replace(/\.lego$/,"").replace(/_/g,"-").replace(/([a-z])([A-Z])/g,"$1-$2").toLowerCase();if(!r.includes("-"))throw new Error(`[Lego] Invalid block definition: "${e}". Block names must contain a hyphen (e.g. user-card.lego or UserCard.lego).`);return r},D=(e,t)=>{if(!e)return"";let r=e.trim().split("."),o=t;for(let n of r){if(o==null)return"";o=o[n]}return o??""},ve=e=>typeof Node<"u"&&e instanceof Node,O=(e,t,r)=>{if(t.nodeType!==Node.ELEMENT_NODE)return;let o=[...t.attributes].find(i=>i.name===e||i.name.startsWith(`${e}.`));if(!o)return;let n={};return r&&(n=r(o,t)),{type:e,node:t,expr:o.value,modifiers:o.name.split(".").slice(1),...n}};var Se=null,Fe=e=>{Se=e},ne=[],ze=0,xe=e=>{let t=ne.find(n=>n.regex.test(e));if(!t)return null;let r=e.match(t.regex).slice(1),o=t.paramNames?Object.fromEntries(t.paramNames.map((n,i)=>[n,r[i]])):{};return{match:t,params:o}},me=async(e=null,t=null)=>{if(typeof window>"u")return;let r=++ze,o=()=>r===ze,n=window.location.pathname,i=xe(n);if(g.debug&&console.log("[Lego Trace] Matching route",n,i?.match),!i)return;let{match:a,params:s}=i,c=window.location.search;if(a.middleware){let u=await a.middleware({path:n,params:s});if(!o()||!u)return}_.$route.url=n+c,_.$route.route=a.path,_.$route.params=s,_.$route.query=Object.fromEntries(new URLSearchParams(c));let f=e&&e.length?e:["lego-router"],l=t||document;if(a.tagName){if(!o())return;f.flatMap(d=>pe(d,l)).forEach(d=>{if(!d||!o())return;d.innerHTML="";let p=document.createElement(a.tagName);d.appendChild(p),Se&&Se(p)})}},ge=(e,...t)=>r=>{let o=async(n,i=null,a=!0,s={})=>{if(a&&typeof history<"u"){let f={legoTargets:t.filter(l=>typeof l=="string"),method:n,body:i};history.pushState(f,"",e)}await me(t.length?t:null,r)};return{get:(n=!0,i={})=>o("GET",null,n,i),post:(n,i=!0,a={})=>o("POST",n,i,a),put:(n,i=!0,a={})=>o("PUT",n,i,a),patch:(n,i=!0,a={})=>o("PATCH",n,i,a),delete:(n=!0,i={})=>o("DELETE",null,n,i)}};var $e=null,$t=null,He=(e,t)=>{$e=e,$t=t},F=(e,t,r)=>{if(e!=null&&(e=String(e).toLowerCase(),!e.includes("-"))){console.warn(`[Lego] $mount: "${e}" is not a valid custom element name (must contain a hyphen).`);return}if(t===void 0){if(!e)return;let i=document.createElement(e);return r&&(i.$initialState=r),i}let o;if(t instanceof Element)o=[t];else if(Array.isArray(t))o=t;else if(typeof t=="string")o=pe(t);else{console.warn("[Lego] $mount: Invalid target",t);return}if(o.length===0){g.debug&&console.log(`[Lego] $mount: No targets found for "${t}"`);return}let n=[];return o.forEach(i=>{if(!i||(i.innerHTML="",!e))return;let a=document.createElement(e);r&&(a.$initialState=r),i.appendChild(a),$e&&$e(a),n.push(a)}),n.length===1?n[0]:n.length>0?n:void 0};var We=new te(1e3),Ie=new te(500),_t=/\b(eval|import|constructor|__proto__)\b/,Lt=/(?<![\w.$])(class|module|prototype)(?![\w$])/,L=(e,t,r=!0)=>{if(_t.test(e)||Lt.test(e)||/\[\s*['"`].*\+|\+.*['"`]\s*\]/.test(e)){console.warn(`[Lego] Security Warning: Blocked dangerous expression "${e}"`);return}try{let o=t.state||{},n=We.get(e);n||(n=new Function("global","self","event","helpers",`
|
|
2
2
|
with(this) {
|
|
3
3
|
with(helpers) {
|
|
4
4
|
return ${e}
|
|
5
5
|
}
|
|
6
6
|
}
|
|
7
|
-
`),_e.set(e,r));let n={$ancestors:i=>q(t.self,i),$registry:i=>oe.get(i.toLowerCase()),$element:t.self,$route:_.$route,$params:_.$route?.params||{},$go:(i,...c)=>ae(i,...c)(t.self),$db:_.$db,$emit:(i,c)=>{t.self.dispatchEvent(new CustomEvent(i,{detail:c,bubbles:!0,composed:!0}))}},a=r.call(s,t.global,t.self,t.event,n);return typeof a=="function"?a.call(s,t.event):a}catch(s){if(o)throw s;if(s instanceof ReferenceError)return;throw s}},me=(e,t={})=>{if(!e||e.trim()==="{}")return{};let o=s=>new Function("scope","global",`with(global) { with(scope) { return (${s}); } }`)(t,_);try{return o(e)}catch(s){let r=e.trim();if(!r.startsWith("{")&&r.includes(":"))try{return o(`{${e}}`)}catch{}return console.error(`[Lego] Error parsing b-logic: "${e.length>80?e.slice(0,80)+"...":e}"`,s),{}}};var Ne={name:"b-if",scan:(e,{checkGlobal:t,getPrivateData:o})=>B("b-if",e,(s,r)=>{t(s.value);let n=document.createComment(`b-if: ${s.value}`),a=o(r);return a.anchor=n,{anchor:n}}),execute({binding:e,state:t,global:o}){let{node:s,anchor:r,expr:n}=e,a=!!N(n,{state:t,global:o,self:s}),i=!!s.parentNode;a&&!i?r.parentNode&&r.parentNode.replaceChild(s,r):!a&&i&&s.parentNode.replaceChild(r,s)},destroy({binding:e}){e.anchor&&e.anchor.parentNode&&e.anchor.remove()}};var $e={name:"b-show",scan(e,{checkGlobal:t}){if(e.nodeType===Node.ELEMENT_NODE&&e.hasAttribute("b-show")){let o=e.getAttribute("b-show");return t(o),{type:"b-show",node:e,expr:o}}},execute({binding:e,state:t,global:o}){let{node:s,expr:r}=e;s.style.display=N(r,{state:t,global:o,self:s})?"":"none"}};var Le={name:"b-text",scan(e){if(e.nodeType===Node.ELEMENT_NODE&&e.hasAttribute("b-text"))return{type:"b-text",node:e,path:e.getAttribute("b-text")}},execute({binding:e,state:t,global:o}){let{node:s,path:r}=e;r.startsWith("global.")?s.textContent=C(r.slice(7),o)??"":s.textContent=C(r,t)??""}};var Te={name:"b-html",scan:e=>B("b-html",e),execute:({binding:e,state:t,global:o})=>{let{node:s,expr:r}=e,n=N(r,{state:t,global:o,self:s})||"";s._bHtmlPrev!==n&&(s._bHtmlPrev=n,s.innerHTML=n)},destroy({binding:e}){let{node:t}=e;t&&(delete t._bHtmlPrev,t.innerHTML="")}};var Ae={name:"b-sync",scan(e){if(e.nodeType!==Node.ELEMENT_NODE)return;let t=F(e);if(!t)return;let o=t.name.split(".").slice(1);return{type:"b-sync",node:e,expr:t.value,modifiers:o}},execute({binding:e,state:t,global:o}){let{node:s,expr:r}=e;r.startsWith("global.")?V(s,C(r.slice(7),o)??""):V(s,C(r,t)??"")},destroy({binding:e}){let{node:t}=e;t&&t._bSyncHandler&&(t.removeEventListener("input",t._bSyncHandler),t.removeEventListener("change",t._bSyncHandler),delete t._bSyncHandler)}};var Ce={name:"b-for",scan(e,{checkGlobal:t,pendingOperations:o}){if(e.nodeType!==Node.ELEMENT_NODE)return;let s=e.getAttribute("b-for")?.match(/^\s*(\w+)\s+in\s+([\s\S]+?)\s*$/);if(s){t(s[2]);let r=document.createComment(`b-for: ${s[1]} in ${s[2].trim()}`);return o.push(()=>{e.parentNode&&(e.parentNode.insertBefore(r,e),e.remove())}),{type:"b-for",anchor:r,itemName:s[1],listName:s[2].trim(),keyPath:e.getAttribute("b-key")||null,template:e.cloneNode(!0),terminal:!0}}},execute({binding:e,state:t,global:o,helpers:s}){let{bind:r,updateNodeBindings:n}=s;if(!r||!n){console.error("[Lego] b-for directive missing required helpers: bind, updateNodeBindings");return}let{anchor:a,listName:i,itemName:c,keyPath:f,template:d}=e,{contextEl:u}=s,l=N(i,{state:t,global:o,self:u})||[];P.has(a)||P.set(a,new Map);let p=P.get(a),S=new Set,x=[];l.forEach((m,b)=>{let v;f?(v=C(f,m),(v==null||v==="")&&(console.warn(`[Lego] b-key="${f}" could not resolve a value for item at index ${b}. Falling back to index-based key.`),v=`__bfor_${b}`)):m&&typeof m=="object"?(v=m.id||m._id||m.uuid||m.key,v===void 0&&(re.has(m)||re.set(m,Math.random()),v=re.get(m))):v=`${b}-${m}`,S.add(v);let h=p.get(v);h?h._loopCtx.index=b:(h=d.cloneNode(!0),h.removeAttribute("b-for"),h.removeAttribute("b-key"),p.set(v,h),h._loopCtx={name:c,listName:i,index:b},r(h,u,h._loopCtx));let M=Object.assign(Object.create(t),{[c]:m,$index:b});n(h,M),[h,...h.querySelectorAll("*")].filter(H=>F(H)).forEach(H=>{let Ee=F(H).value;Ee.startsWith(`${c}.`)&&V(H,C(Ee.split(".").slice(1).join("."),l[b]))}),x.push(h)});let E=a.nextSibling;x.forEach(m=>{m!==E?a.parentNode.insertBefore(m,E):E=E.nextSibling});for(let[m,b]of p.entries())S.has(m)||(b.remove(),p.delete(m))},destroy({binding:e}){let{anchor:t}=e;if(t&&P.has(t)){let o=P.get(t);o.forEach(s=>s.remove()),o.clear(),P.delete(t)}t&&t.parentNode&&t.remove()}};var ke={scan:e=>{if(e.hasAttribute("b-init"))return{type:"b-init",node:e,expr:e.getAttribute("b-init")}},execute:({binding:e,state:t,global:o})=>{e.initialized||(e.initialized=!0,N(e.expr,{state:t,global:o,self:e.node}))}};var Oe={name:"b-enter",scan:e=>B("b-enter",e,(t,o)=>({modifiers:t.name.split(".").slice(1)})),execute:({binding:e,state:t,global:o})=>{if(e.observer||e.done)return;let s=new IntersectionObserver((r,n)=>{r[0].isIntersecting&&(N(e.expr,{state:t,global:o,self:e.node}),e.modifiers.includes("once")&&(n.disconnect(),e.observer=null,e.done=!0))});s.observe(e.node),e.observer=s},destroy:({binding:e})=>{e.observer&&(e.observer.disconnect(),e.observer=null)}};var Me={name:"b-leave",scan:e=>B("b-leave",e),execute:({binding:e,state:t,global:o})=>{if(e.observer||e.done)return;let s=new IntersectionObserver((r,n)=>{let a=r[0];a.isIntersecting&&(e.activated=!0),!a.isIntersecting&&e.activated&&(N(e.expr,{state:t,global:o,self:e.node}),e.modifiers.includes("once")&&(n.disconnect(),e.observer=null,e.done=!0))});s.observe(e.node),e.observer=s},destroy:({binding:e})=>{e.observer&&(e.observer.disconnect(),e.observer=null)}};var Y={"b-if":Ne,"b-show":$e,"b-text":Le,"b-html":Te,"b-sync":Ae,"b-for":Ce,"b-init":ke,"b-enter":Oe,"b-leave":Me};var Ge=(e=null)=>{let t=!1,o=new Set,s=!1,r=e,n=new Set,a=null,i=new Set,c=l=>{r=l},f=()=>{a&&clearTimeout(a),a=setTimeout(()=>{i.forEach(l=>{let p=l._studs;if(p&&typeof p.updated=="function")try{p.updated.call(p)}catch(S){console.error("[Lego] Error in updated hook:",S)}}),i.clear(),a=null},50)},d=()=>{n.size>0&&(n.forEach(l=>o.add(l)),n.clear(),!t&&o.size>0&&(t=!0,requestAnimationFrame(u)))},u=()=>{s=!0;let l=Array.from(o);o.clear(),t=!1,l.forEach(p=>{p.isConnected&&r&&r(p)}),l.forEach(p=>i.add(p)),f(),s=!1,d()};return{add:l=>{if(l){if(s){n.add(l);return}o.add(l),!t&&(t=!0,requestAnimationFrame(u))}},setHandler:c}},ie=Ge();var L=new Map,ce=new Map,ee=new WeakMap,te=new Map,Je=e=>{let t=Array.from(te.entries()).filter(([r])=>r.startsWith("lego:")).sort((r,n)=>r[1].timestamp-n[1].timestamp),o=0,s=[];for(let[r,n]of t){if(o>=e)break;try{localStorage.removeItem(r),o+=n.size,s.push(r),te.delete(r)}catch(a){console.error(`[Lego] Failed to evict ${r}:`,a)}}return s},Be=(e,t,o)=>{g.debug&&console.log("[Lego Trace] scheduleSave",e,t,o),ce.has(e)&&clearTimeout(ce.get(e));let s=()=>{try{let r=JSON.stringify(t),n=new Blob([r]).size;localStorage.setItem(e,r);let a=e.startsWith("lego:")?e:`lego:${e}`;te.set(a,{timestamp:Date.now(),size:n}),ce.delete(e)}catch(r){if(r.name==="QuotaExceededError"){console.warn(`[Lego] Storage quota exceeded for key: ${e}`);try{let n=JSON.stringify(t),a=new Blob([n]).size,i=Je(a*2);if(i.length>0){g.debug&&console.log(`[Lego] Evicted ${i.length} old keys, retrying save`),localStorage.setItem(e,n);let c=e.startsWith("lego:")?e:`lego:${e}`;te.set(c,{timestamp:Date.now(),size:a})}else g.onError(new Error("Storage quota exceeded and no keys available for eviction"),"quota",e)}catch{g.onError(new Error(`Critical: Could not save ${e} even after eviction`),"quota-critical",e)}}else console.error(`[Lego] Storage Error (${e}):`,r)}};o>0?ce.set(e,setTimeout(s,o)):s()},ge=e=>({__type:"lego-db",key:e,_default:void 0,_debounce:0,default(o){return this._default=o,this},debounce(o){return this._debounce=o,this},set(o,s=0){return Be(e,o,s),L.has(e)&&L.get(e).forEach(({target:r,prop:n,el:a,batcher:i})=>{r[n]=o,a&&i&&i.add(a)}),o},get(){try{let o=localStorage.getItem(e);return o!==null?JSON.parse(o):null}catch(o){return console.warn(`[Lego] Failed to get localStorage value for key "${e}":`,o),null}},delete(){try{return localStorage.removeItem(e),te.delete(e.startsWith("lego:")?e:`lego:${e}`),L.has(e)&&L.get(e).forEach(({target:o,prop:s,el:r,batcher:n})=>{o[s]=null,r&&n&&n.add(r)}),!0}catch(o){return console.error(`[Lego] Failed to delete localStorage key "${e}":`,o),!1}}}),De=e=>e&&e.__type==="lego-db",Pe=(e,t,o,s,r)=>{g.debug&&console.log("[Lego Trace] Reactive DB Init:",t,o);let n=o._default;try{let a=localStorage.getItem(o.key);a!==null&&(n=JSON.parse(a))}catch(a){console.warn(`[Lego] Failed to parse localStorage value for key "${o.key}":`,a)}e[t]=n,ee.has(e)||ee.set(e,{}),ee.get(e)[t]={key:o.key,debounce:o._debounce},g.debug&&console.log("[Lego Trace] DB Metadata Set:",t,ee.get(e)[t]),L.has(o.key)||L.set(o.key,new Set),L.get(o.key).add({target:e,prop:t,el:s,batcher:r})},Re=(e,t,o)=>{let s=ee.get(e);if(s&&s[t]){let r=s[t].key;Be(r,o,s[t].debounce),L.has(r)&&L.get(r).forEach(({target:n,prop:a,el:i,batcher:c})=>{n!==e&&(n[a]=o,i&&c&&c.add(i))})}},Fe=()=>{typeof window<"u"&&window.addEventListener("storage",e=>{if(!(!e.key||!L.has(e.key)))try{let t=JSON.parse(e.newValue);L.get(e.key).forEach(({target:o,prop:s,el:r,batcher:n})=>{o[s]=t,r&&n&&n.add(r)})}catch(t){console.warn("[Lego] Cross-tab sync error:",t)}})};var j=(e,t,o=ie)=>{if(e===null||typeof e!="object"||de(e))return e;if(G.has(e))return G.get(e);for(let n in e){let a=Object.getOwnPropertyDescriptor(e,n);if(a&&a.get)continue;let i=e[n];De(i)&&Pe(e,n,i,t,o)}let s={get:(n,a)=>{let i=Reflect.get(n,a);return i!==null&&typeof i=="object"&&!de(i)?j(i,t,o):i},set:(n,a,i,c)=>{if(a==="__proto__"||a==="constructor"||a==="prototype")return console.warn(`[Lego] Blocked setting dangerous property: "${a}"`),!0;let f=n[a];g.debug&&f!==i&&console.log("[Lego Trace] Reactive SET:",a,"Old:",f,"New:",i,"Target:",n);let d=c===G.get(n),u=Object.prototype.hasOwnProperty.call(n,a),l=!d&&u?Reflect.set(n,a,i):Reflect.set(n,a,i,c);return(d||u)&&f!==i&&(o.add(t),Re(n,a,i)),l},deleteProperty:(n,a)=>{let i=Reflect.deleteProperty(n,a);return o.add(t),i}},r=new Proxy(e,s);return G.set(e,r),r};var Ve=e=>{let t=e;for(;t;){let o=t.getAttribute&&t.getAttribute("b-error");if(o&&o.toLowerCase()!==e.tagName.toLowerCase())return{errorTag:o,targetElement:t};let s=t.tagName?t.tagName.toLowerCase():"",r=w[s];if(r){let n=r.getAttribute("b-error");if(n&&n.toLowerCase()!==e.tagName.toLowerCase())return{errorTag:n,targetElement:t}}t=t.parentElement||t.getRootNode&&t.getRootNode().host}return null},he=null,ze=null,He=(e,t)=>{he=e,ze=t},Xe=(e,t,o)=>{if(!he||!ze){console.error("[Lego] Error boundary dependencies not loaded",o);return}try{t.shadowRoot?t.shadowRoot.innerHTML="":t.innerHTML="";let s=document.createElement(e);s.$initialState={$error:{message:o.message,stack:o.stack,component:t.tagName.toLowerCase()}},(t.shadowRoot||t).appendChild(s),he(s)}catch(s){console.error("[Lego] Error boundary failed to render:",s),console.error("[Lego] Original error:",o)}},U=(e,t,o)=>{let s=Ve(t);s?Xe(s.errorTag,s.targetElement,e):g.onError(e,o,t)};var le=(e,t,o=null)=>{let s=t._studs,r=i=>{let c=A(i);if(!c.bound){if(i.hasAttributes()){let f=i.attributes;for(let u=0;u<f.length;u++){let l=f[u];if(l.name.startsWith("@")){let p=l.name.slice(1).split("."),S=p[0],x=p.slice(1);i.addEventListener(S,E=>{if(x.includes("prevent")&&E.preventDefault(),x.includes("stop")&&E.stopPropagation(),!(x.includes("self")&&E.target!==E.currentTarget)){if(typeof KeyboardEvent<"u"&&E instanceof KeyboardEvent){if(x.includes("ctrl")&&!E.ctrlKey||x.includes("alt")&&!E.altKey||x.includes("shift")&&!E.shiftKey||x.includes("meta")&&!E.metaKey)return;let m=x.filter(b=>!["prevent","stop","self","ctrl","alt","shift","meta","capture","once","passive"].includes(b));if(m.length>0){let b=E.key.toLowerCase();if(!m.some(h=>h==="enter"?b==="enter":h==="esc"||h==="escape"?b==="escape":h==="space"?b===" ":h==="tab"?b==="tab":h==="delete"?b==="delete":h==="backspace"?b==="backspace":h==="up"?b==="arrowup":h==="down"?b==="arrowdown":h==="left"?b==="arrowleft":h==="right"?b==="arrowright":h==="alpha"?/^[a-z]$/.test(b):h==="numbers"?/^[0-9]$/.test(b):h===b))return}}try{let m=s;if(o){let v=N(o.listName,{state:s,global:_,self:t})[o.index];m=Object.assign(Object.create(s),{[o.name]:v})}N(l.value,{state:m,global:_,self:i,event:E,$event:E},!0)}catch(m){U(m,t,"event-handler")}}})}}let d=F(i);if(d){let u=d.value,l=d.name.split(".").slice(1),p=l.includes("lazy"),S=l.includes("number"),x=l.includes("trim"),E=()=>{try{let m,b;if(u.startsWith("global.")){let h=u.slice(7).split(".");b=h.pop(),m=h.reduce((M,D)=>M[D],_)}else if(o&&u.startsWith(`${o.name}.`)){let M=N(o.listName,{state:s,global:_,self:t})[o.index];if(!M)return;let D=u.split(".").slice(1);b=D.pop(),m=D.reduce((H,ye)=>H[ye],M)}else{let h=u.split(".");b=h.pop(),m=h.reduce((M,D)=>M[D],s)}let v=i.type==="checkbox"?i.checked:i.value;if(x&&typeof v=="string"&&(v=v.trim()),S){let h=parseFloat(v);isNaN(h)||(v=h)}m&&m[b]!==v&&(m[b]=v)}catch(m){g.onError(m,"sync-update",i)}};i._bSyncHandler=E,p||i.addEventListener("input",E),i.addEventListener("change",E)}if(i.hasAttribute("b-var")){let u=i.getAttribute("b-var");s.$vars&&(s.$vars[u]=i)}}c.bound=!0}};e instanceof Element&&r(e);let n=document.createTreeWalker(e,NodeFilter.SHOW_ELEMENT),a;for(;a=n.nextNode();)r(a)},Qe=e=>{let t=[],o=document.createTreeWalker(e,NodeFilter.SHOW_ELEMENT|NodeFilter.SHOW_TEXT),s,r=[];for(;s=o.nextNode();){let n=s;if((c=>{let f=c.parentNode;for(;f&&f!==e;){if(f.hasAttribute&&f.hasAttribute("b-for"))return!0;f=f.parentNode}return!1})(s))continue;let i=c=>{if(/\bglobal\b/.test(c)){let f=e.host||e;J.add(f)}};if(s.nodeType===Node.ELEMENT_NODE){let c=!1;for(let[d,u]of Object.entries(Y))if(u.scan){let l=u.scan(s,{checkGlobal:i,getPrivateData:A,pendingOperations:r,current:n});l&&(t.push(l),l.terminal&&(c=!0))}if(c)continue;let[f]=X();[...s.attributes].forEach(d=>{d.value.includes(f)&&(i(d.value),t.push({type:"attr",node:s,attrName:d.name,template:d.value}))})}else if(s.nodeType===Node.TEXT_NODE){let[c]=X();s.textContent.includes(c)&&(i(s.textContent),t.push({type:"text",node:s,template:s.textContent}))}}return r.forEach(n=>n()),t},Ze=(e,t)=>{let o=n=>{if(n.nodeType===Node.TEXT_NODE){n._tpl===void 0&&(n._tpl=n.textContent);let a=n._tpl.replace(Q(),(i,c)=>N(c.trim(),{state:t,global:_,self:n},!1)??"");n.textContent!==a&&(n.textContent=a)}else if(n.nodeType===Node.ELEMENT_NODE){let[a]=X();[...n.attributes].forEach(i=>{if(i._tpl===void 0&&(i._tpl=i.value),i._tpl.includes(a)){let c=i._tpl.replace(Q(),(f,d)=>N(d.trim(),{state:t,global:_,self:n},!1)??"");i.value!==c&&(i.value=c,i.name==="class"&&(n.className=c))}})}};o(e);let s=document.createTreeWalker(e,NodeFilter.SHOW_ELEMENT|NodeFilter.SHOW_TEXT),r;for(;r=s.nextNode();)o(r)},K=e=>{g.debug&&console.log("[Lego Trace] render() called for:",e.tagName);let t=e._studs;if(!t)return;let o=A(e);if(!o.rendering){o.rendering=!0,g.metrics&&g.metrics.onRenderStart&&g.metrics.onRenderStart(e);try{let s=e.shadowRoot||e;o.bindings||(o.bindings=Qe(s)),o.bindings.forEach(r=>{let n=Y[r.type];if(n){n.execute({binding:r,state:t,global:_,helpers:{bind:le,updateNodeBindings:Ze,contextEl:e}});return}if(r.type==="text"){let a=r.template.replace(Q(),(i,c)=>N(c.trim(),{state:t,global:_,self:r.node},!1)??"");r.node.textContent!==a&&(r.node.textContent=a)}if(r.type==="attr"){let a=r.template.replace(Q(),(i,c)=>N(c.trim(),{state:t,global:_,self:r.node},!1)??"");r.node.getAttribute(r.attrName)!==a&&(r.node.setAttribute(r.attrName,a),r.attrName==="class"&&(r.node.className=a))}}),t===_&&J.forEach(r=>K(r))}catch(s){U(s,e,"render")}finally{g.metrics&&g.metrics.onRenderEnd&&g.metrics.onRenderEnd(e),o.rendering=!1}}};var We=new Map,Ie={},qe=e=>{Ie=e},je=async()=>{let e=Object.entries(Ie).map(async([t,o])=>{let s=await Promise.all(o.map(async r=>{try{if(r instanceof CSSStyleSheet)return r;let n=await fetch(r);if(!n.ok)throw new Error(`Status ${n.status}`);let a=await n.text(),i=new CSSStyleSheet;return await i.replace(a),i}catch(n){return console.error(`[Lego] Failed to load stylesheet: ${r}`,n),null}}));We.set(t,s.filter(r=>r!==null))});await Promise.all(e),g.debug&&console.log("[Lego Debug] Re-applying stylesheets to",T.size,"blocks"),T.forEach(t=>{be(t)})},be=e=>{if(!e.shadowRoot&&!e._legoShadow)return;let t=e.shadowRoot||e._legoShadow,o=e.tagName.toLowerCase(),s=w[o],r=(s&&s.getAttribute("b-stylesheets")||"").split(/\s+/).filter(Boolean),n=(e.getAttribute("b-stylesheets")||"").split(/\s+/).filter(Boolean),a=[],i=e.parentElement||(e.getRootNode?e.getRootNode().host:null);for(;i;){let u=(i.getAttribute("b-cascade")||"").split(/\s+/).filter(Boolean);u.length&&a.push(...u);let l=i.tagName?i.tagName.toLowerCase():"";if(w[l]){let p=(w[l].getAttribute("b-cascade")||"").split(/\s+/).filter(Boolean);p.length&&a.push(...p)}i=i.parentElement||i.getRootNode&&i.getRootNode().host}let c=[...new Set([...r,...n])],f=[...new Set(a)],d=[...new Set([...f,...c])];if(d.length>0){let u=d.flatMap(l=>We.get(l)||[]);if(u.length>0&&g.debug&&console.log("[Lego Debug] Applying styles to",e.tagName,"- Names:",d,"- Sheets:",u.length),u.length>0){let l=t.adoptedStyleSheets.filter(p=>!u.includes(p));t.adoptedStyleSheets=[...l,...u]}}e._studsMeta={stylesheets:{explicit:c,inherited:f,applied:d}}};var $=e=>{if(g.debug&&console.log("[Lego Trace] snap() called for:",e.tagName),!e||e.nodeType!==Node.ELEMENT_NODE)return;let t=A(e),o=e.tagName.toLowerCase(),s=w[o];if(s&&!t.snapped){t.snapped=!0;let n=s.content.cloneNode(!0),a=e.shadowRoot;a?a.innerHTML="":a=e.attachShadow({mode:"open"}),be(e);let i=q(e,"*")||q(e.getRootNode().host,"*"),c=i&&i.state?i.state:{},f=I.get(o)||{},d=me(s.getAttribute("b-logic")||s.getAttribute("b-data")||"{}"),u=me(e.getAttribute("b-logic")||e.getAttribute("b-data")||"{}",c),l={$vars:{},$element:e,get $parent(){return q(e,"*")},$emit:(x,E)=>{e.dispatchEvent(new CustomEvent(x,{detail:E,bubbles:!0,composed:!0}))},get $route(){return _.$route},get $go(){return _.$go}};z(f,l),z(d,l),z(u,l),e.$initialState&&(z(e.$initialState,l),delete e.$initialState),e._studs=j(l,e),Object.defineProperty(e,"state",{get(){return this._studs},set(x){Object.assign(this._studs,x)},configurable:!0,enumerable:!1}),R.locked=!0,a.appendChild(n),R.locked=!1;let p=a.querySelector("style");if(p&&(p.textContent=p.textContent.replace(/\bself\b/g,":host")),le(a,e),T.add(e),K(e),e.setAttribute("b-id",o),e._legoShadow||(e._legoShadow=a),typeof e._studs.mounted=="function")try{e._studs.mounted.call(e._studs)}catch(x){U(x,e,"mounted")}let S=a.querySelectorAll("*");g.debug&&console.log("[Lego Debug] Nested scan in",e.tagName,"- Found elements:",S.length),S.forEach(x=>{let E=x.tagName.toLowerCase(),m=!!w[E];m&&g.debug&&console.log("[Lego Debug] Checking",E,"- Registered:",m),m&&$(x)})}let r=e.parentElement;for(;r&&!r._studs;)r=r.parentElement;r&&r._studs&&le(e,r),[...e.children].forEach($)},k=e=>{if(e._studs&&typeof e._studs.unmounted=="function")try{e._studs.unmounted.call(e._studs)}catch(o){U(o,e,"unmounted")}e.shadowRoot&&[...e.shadowRoot.children].forEach(k),T.delete(e),J.delete(e),e._studs&&(e._studs.$element=null,e._studs.$vars&&(Object.keys(e._studs.$vars).forEach(o=>{e._studs.$vars[o]=null}),e._studs.$vars=null),e._studs.$emit&&(e._studs.$emit=null),delete e._studs.$parent,delete e._studs.$route,delete e._studs.$go,e._studs=null),e.hasOwnProperty("state")&&delete e.state;let t=W.get(e);t&&(t.bindings&&(t.bindings.forEach(o=>{let s=Y[o.type];if(s&&s.destroy)try{s.destroy({binding:o})}catch(r){console.error(`[Lego] Error in directive cleanup (${o.type}):`,r)}o.node=null,o.anchor=null}),t.bindings=null),t.anchor=null,W.delete(e)),[...e.children].forEach(k)};function Ue(e,t="block.lego"){let o={template:"",script:"",style:"",stylesAttr:"",cascadeAttr:"",errorAttr:"",blockName:Se(t),hasTemplate:!1,hasScript:!1,hasStyle:!1},s=e,r=/<(template|script|style)\b((?:\s+(?:[^>"']|"[^"]*"|'[^']*')*)*)>/i;for(;s;){let n=s.match(r);if(!n)break;let a=n[1].toLowerCase(),i=n[2],c=n[0],f=n.index,d=`</${a}>`,u=f+c.length,l=s.indexOf(d,u);if(l===-1){console.warn(`[Lego] Unclosed <${a}> tag in ${t}`);break}let p=s.slice(u,l);if(a==="template"){o.hasTemplate=!0,o.template=p.trim();let S=i.match(/b-stylesheets=["']([^"']+)["']/);S&&(o.stylesAttr=S[1]);let x=i.match(/b-cascade=["']([^"']+)["']/);x&&(o.cascadeAttr=x[1]);let E=i.match(/b-error=["']([^"']+)["']/);E&&(o.errorAttr=E[1])}else if(a==="script"){o.hasScript=!0,o.script=p.trim();let S=i.match(/lang=["']([^"']+)["']/);S&&(o.scriptLang=S[1])}else a==="style"&&(o.hasStyle=!0,o.style=p.trim());s=s.slice(l+d.length)}return o}var Ke=(e,t,o="block.lego")=>{let s=Ue(t,o),{blockName:r,template:n,script:a,style:i,stylesAttr:c,cascadeAttr:f,errorAttr:d}=s,u={};if(a)try{let p=a.trim(),S=p.match(/export\s+default\s+(?:\/\*[\s\S]*?\*\/\s*|\/\/[^\n]*\n\s*)*({[\s\S]*})/),x=S?S[1]:p;u=new Function("Lego","$db",`return ${x}`)(e,e.globals.$db)}catch(p){g.onError(p,"script",r)}let l=n;i&&(l=`<style>${i}</style>`+l),w[r]=document.createElement("template"),w[r].innerHTML=l,c&&w[r].setAttribute("b-stylesheets",c),f&&w[r].setAttribute("b-cascade",f),d&&w[r].setAttribute("b-error",d),I.set(r,u),document.querySelectorAll(r).forEach(p=>!A(p).snapped&&$(p))};ie.setHandler(K);He($,K);ve($);var Ye={url:typeof window<"u"?window.location.pathname:"/",route:"",params:{},query:{},method:"GET",body:null},O=j({$route:Ye,$go:(e,...t)=>ae(e,...t)(document.body),$db:ge},typeof document<"u"?document.body:null);we(O);var y={db:ge,snap:$,unsnap:k,defineLegoFile:(e,t)=>Ke(y,e,t),block:(e,t,o={},s="",r="",n="")=>{let a=document.createElement("template");a.setAttribute("b-id",e),a.setAttribute("b-stylesheets",s),r&&a.setAttribute("b-cascade",r),n&&a.setAttribute("b-error",n),a.innerHTML=t,w[e]=a,I.set(e,o);try{let i={};z(o,i),oe.set(e.toLowerCase(),j(i,document.body))}catch(i){g.onError(i,"define",e)}if(customElements.get(e))document.querySelectorAll(e).forEach(i=>{k(i),$(i)}),T.forEach(i=>{i._legoShadow&&i._legoShadow.querySelectorAll(e).forEach(c=>{k(c),$(c)})});else try{customElements.define(e,class extends HTMLElement{connectedCallback(){R.locked||w[e]&&$(this)}disconnectedCallback(){k(this)}})}catch(i){console.warn(`[Lego] Failed to register web component ${e}:`,i)}},getActiveBlocksCount:()=>T.size,getLegos:()=>Object.keys(w),config:g,globals:O,route:(e,t,o=null)=>{let s=[],r=e==="*"?".*":e;r=r.replace(/:([^\/]+)|[.*+?^${}()|[\]\\]/g,(n,a)=>a?(s.push(a),"([^/]+)"):"\\"+n),Z.push({path:e,regex:new RegExp(`^${r}$`),tagName:t,paramNames:s,middleware:o})},debug:{stylesheets:e=>!e||!e._studsMeta?null:e._studsMeta.stylesheets},init:async(e=document.body,t={})=>{if((!e||typeof e.nodeType!="number")&&(e=document.body),qe(t.styles||{}),g.loader=t.loader,g.debug=t.debug===!0,await je(),Z.length>0){let r=window.location.pathname,n=window.location.search,a=pe(r);if(a){let{match:i,params:c}=a,f=Object.fromEntries(new URLSearchParams(n));O.$route.url=r+n,O.$route.route=i.path,O.$route.params=c,O.$route.query=f,O.$route.method="GET",O.$route.body=null}}document.querySelectorAll("template[b-id]").forEach(r=>{let n=r.getAttribute("b-id");w[n]=r,customElements.get(n)||customElements.define(n,class extends HTMLElement{connectedCallback(){R.locked||w[n]&&$(this)}disconnectedCallback(){k(this)}})});let o=r=>{if(!r)return{};let n={};return Object.entries(r).forEach(([a,i])=>{if(typeof i=="function")n[a]=i();else if(typeof i=="string"&&i.startsWith("$db.")){let c=i.slice(4);n[a]=y.db(c).get()}else if(typeof i=="string"&&i.startsWith("$globals.")){let c=i.slice(9);n[a]=_[c]}else n[a]=i}),n},s=(r,n,a={})=>{customElements.get(r)||customElements.define(r,class extends HTMLElement{async connectedCallback(){if(w[r]){R.locked||$(this);return}if(y._fetching||(y._fetching=new Set),y._pendingLazy||(y._pendingLazy={}),y._fetching.has(r)){y._pendingLazy[r]||(y._pendingLazy[r]=new Set),y._pendingLazy[r].add(this);return}y._fetching.add(r);try{let i=n.startsWith("POST:")?"POST":"GET",c=n.replace(/^POST:/,""),f=o(a.headers),d={method:i,headers:f,credentials:a.credentials},l=await(await fetch(c,d)).text();y.defineLegoFile(l,`${r}.lego`),w[r]&&$(this);let p=y._pendingLazy[r];p&&(p.forEach(S=>{S.isConnected&&w[r]&&!A(S).snapped&&$(S)}),delete y._pendingLazy[r])}catch(i){console.error(`[Lego] Failed to load manifest block ${r}:`,i)}finally{y._fetching.delete(r)}}disconnectedCallback(){k(this)}})};if(t.manifest){let r=t.manifest;if(r.url&&typeof r.url=="string")try{let a=o(r.headers);r=await(await fetch(r.url,{headers:a,credentials:r.credentials})).json()}catch(a){console.error("[Lego] Failed to load manifest:",a),r=[]}else if(typeof r=="string")try{r=await(await fetch(r)).json()}catch(a){console.error("[Lego] Failed to load manifest:",a),r=[]}let n=Array.isArray(r)?r:[r];for(let a of n){let i=a.base||"",c=a.suffix===!0?".lego":a.suffix||"",f={headers:a.headers||{},credentials:a.credentials};a.legos&&a.legos.forEach(d=>{s(d,`${i}${d}${c}`,f)}),a.map&&Object.entries(a.map).forEach(([d,u])=>{let l=u.match(/^https?:|^\//)?u:`${i}${u}`;s(d,l,f)})}}if(g.loader){let r=a=>{if(a.nodeType!==Node.ELEMENT_NODE)return;let i=a.tagName.toLowerCase();if(i.includes("-")&&!w[i]&&!T.has(a)){if(y._fetching&&y._fetching.has(i))return;y._fetching||(y._fetching=new Set),y._fetching.add(i);let c=g.loader(i);if(c){let f=typeof c=="string"?fetch(c).then(d=>d.text()):c;Promise.resolve(f).then(d=>{y.defineLegoFile(d,`${i}.lego`),y._fetching.delete(i)}).catch(d=>{console.error(`[Lego] Failed to load ${i}:`,d),y._fetching.delete(i)})}}if(a.children.length>0){let c=a.firstElementChild;for(;c;)r(c),c=c.nextElementSibling}};y._discoveryObserver&&y._discoveryObserver.disconnect(),y._discoveryObserver=new MutationObserver(a=>a.forEach(i=>{i.addedNodes.forEach(r)})),y._discoveryObserver.observe(e,{childList:!0,subtree:!0});let n=document.createTreeWalker(e,NodeFilter.SHOW_ELEMENT);for(;n.nextNode();)r(n.currentNode)}if(t.studio){if(!w["lego-studio"]){let r=document.createElement("script");r.src="https://unpkg.com/@legodom/studio@0.0.2/dist/lego-studio.js",r.onerror=()=>console.warn("[Lego] Failed to load Studio from CDN"),document.head.appendChild(r)}y.route("/_/studio","lego-studio"),y.route("/_/studio/:block","lego-studio")}Z.length>0&&(window.addEventListener("popstate",r=>{let n=r.state?.legoTargets||null;ne(n)}),document.addEventListener("submit",r=>{r.preventDefault()}),document.addEventListener("click",r=>{let a=r.composedPath().find(i=>i.tagName==="A"&&(i.hasAttribute("b-target")||i.hasAttribute("b-link")));if(a){r.preventDefault();let i=a.getAttribute("href"),c=a.getAttribute("b-target"),f=c?c.split(/\s+/).filter(Boolean):[],d=a.getAttribute("b-link")!=="false";O.$go(i,...f).get(d)}}),ne()),Fe()}};typeof window<"u"?window.Lego=y:typeof global<"u"&&(global.Lego=y);var yo=y;export{y as Lego,yo as default};
|
|
7
|
+
`),We.set(e,n));let i={$ancestors:s=>V(t.self,s),$registry:s=>ee.get(s.toLowerCase()),$element:t.self,$route:_.$route,$params:_.$route?.params||{},$go:(s,...c)=>ge(s,...c)(t.self),$db:_.$db,$mount:(s,c,f)=>F(s,c,f),$emit:(s,c)=>{t.self.dispatchEvent(new CustomEvent(s,{detail:c,bubbles:!0,composed:!0}))}},a=n.call(o,t.global,t.self,t.event,i);return typeof a=="function"&&t.event!==void 0?a.call(o,t.event):a}catch(o){if(r)throw o;if(o instanceof ReferenceError&&!g.strict)return;throw o}},_e=(e,t={})=>{if(!e||e.trim()==="{}")return{};let[r,o]=oe();if(e.includes(r)&&e.includes(o))return console.error(`[Lego] Refusing to parse b-logic containing template delimiters ("${r}...${o}"). b-logic is evaluated as JavaScript; templating user data into it is unsafe. Pass values through state instead. Got: "${e.length>80?e.slice(0,80)+"...":e}"`),{};let n=a=>{let s=Ie.get(a);return s||(s=new Function("scope","global",`with(global) { with(scope) { return (${a}); } }`),Ie.set(a,s)),s},i=a=>n(a)(t,_);try{return i(e)}catch(a){let s=e.trim();if(!s.startsWith("{")&&s.includes(":"))try{return i(`{${e}}`)}catch{}return console.error(`[Lego] Error parsing b-logic: "${e.length>80?e.slice(0,80)+"...":e}"`,a),{}}};var qe={name:"b-if",scan:(e,{checkGlobal:t,getPrivateData:r})=>O("b-if",e,(o,n)=>{t(o.value);let i=document.createComment(`b-if: ${o.value}`),a=r(n);return a.anchor=i,{anchor:i}}),execute({binding:e,state:t,global:r}){let{node:o,anchor:n,expr:i}=e,a=!!L(i,{state:t,global:r,self:o}),s=!!o.parentNode;a&&!s?n.parentNode&&n.parentNode.replaceChild(o,n):!a&&s&&o.parentNode.replaceChild(n,o)},destroy({binding:e}){e.anchor&&e.anchor.parentNode&&e.anchor.remove()}};var je={name:"b-show",scan(e,{checkGlobal:t}){if(e.nodeType===Node.ELEMENT_NODE&&e.hasAttribute("b-show")){let r=e.getAttribute("b-show");return t(r),{type:"b-show",node:e,expr:r}}},execute({binding:e,state:t,global:r}){let{node:o,expr:n}=e;o._bShowOriginal===void 0&&(o._bShowOriginal=o.style.display);let i=!!L(n,{state:t,global:r,self:o});o.style.display=i?o._bShowOriginal:"none"}};var Ke={name:"b-text",scan(e,{checkGlobal:t}){if(e.nodeType===Node.ELEMENT_NODE&&e.hasAttribute("b-text")){let r=e.getAttribute("b-text");return t(r),{type:"b-text",node:e,path:r}}},execute({binding:e,state:t,global:r}){let{node:o,path:n}=e;n.startsWith("global.")?o.textContent=D(n.slice(7),r)??"":o.textContent=D(n,t)??""}};var Ge={name:"b-html",scan:e=>O("b-html",e),execute:({binding:e,state:t,global:r,helpers:o})=>{let{node:n,expr:i,modifiers:a}=e,s=L(i,{state:t,global:r,self:n})??"";if(a&&a.includes("safe")&&(s=(typeof g.sanitize=="function"?g.sanitize:Re)(s)),n._bHtmlPrev!==s){n._bHtmlPrev=s;let c=o&&o.contextEl;if(c){let f=A.get(c);if(f&&f.bindings&&f.bindings.length){for(let l of f.bindings)l!==e&&l.node&&l.node!==n&&n.contains(l.node)&&(l.dead=!0,l.node=null);f.bindings.some(l=>l.dead)&&(f.bindings=f.bindings.filter(l=>!l.dead))}}n.innerHTML=s}},destroy({binding:e}){let{node:t}=e;t&&(delete t._bHtmlPrev,t.innerHTML="")}};var Ue={name:"b-sync",scan(e,{checkGlobal:t}){if(e.nodeType!==Node.ELEMENT_NODE)return;let r=K(e);if(!r)return;t(r.value);let o=r.name.split(".").slice(1);return{type:"b-sync",node:e,expr:r.value,modifiers:o}},execute({binding:e,state:t,global:r}){let{node:o,expr:n}=e;n.startsWith("global.")?re(o,D(n.slice(7),r)??""):re(o,D(n,t)??"")},destroy({binding:e}){let{node:t}=e;t&&t._bSyncHandler&&(t.removeEventListener("input",t._bSyncHandler),t.removeEventListener("change",t._bSyncHandler),delete t._bSyncHandler)}};var Tt=0,Je={name:"b-for",scan(e,{checkGlobal:t,pendingOperations:r}){if(e.nodeType!==Node.ELEMENT_NODE)return;let o=e.getAttribute("b-for")?.match(/^\s*(\w+)\s+in\s+([\s\S]+?)\s*$/);if(o){t(o[2]);let n=document.createComment(`b-for: ${o[1]} in ${o[2].trim()}`);return r.push(()=>{e.parentNode&&(e.parentNode.insertBefore(n,e),e.remove())}),{type:"b-for",anchor:n,itemName:o[1],listName:o[2].trim(),keyPath:e.getAttribute("b-key")||null,template:e.cloneNode(!0),terminal:!0}}},execute({binding:e,state:t,global:r,helpers:o}){let{bind:n,scanForBindings:i,runBinding:a}=o;if(!n||!a){console.error("[Lego] b-for directive missing required helpers: bind, runBinding");return}let{anchor:s,listName:c,itemName:f,keyPath:l,template:u}=e,{contextEl:d}=o,p=L(c,{state:t,global:r,self:d})||[];W.has(s)||W.set(s,new Map);let m=W.get(s),h=new Set,x=[];p.forEach((w,E)=>{let $;l?($=D(l,w),($==null||$==="")&&(console.warn(`[Lego] b-key="${l}" could not resolve a value for item at index ${E}. Falling back to index-based key.`),$=`__bfor_${E}`)):w&&typeof w=="object"?($=w.id||w._id||w.uuid||w.key,$===void 0&&(ue.has(w)||ue.set(w,++Tt),$=ue.get(w))):$=`${E}-${w}`,h.add($);let b=m.get($);b?b._loopCtx.index=E:(b=u.cloneNode(!0),b.removeAttribute("b-for"),b.removeAttribute("b-key"),m.set($,b),b._loopCtx={name:f,listName:c,index:E},n(b,d,b._loopCtx),i&&(b._loopBindings=i(b,d)));let k=b._loopScope;if(k||(b._loopScope=k=Object.create(t)),k[f]=w,k.$index=E,b._loopBindings)for(let P of b._loopBindings)try{a(P,k,d,!1)}catch(Oe){console.error("[Lego] Error in b-for inner binding:",Oe)}[b,...b.querySelectorAll("*")].filter(P=>K(P)).forEach(P=>{let Be=K(P).value;Be.startsWith(`${f}.`)&&re(P,D(Be.split(".").slice(1).join("."),p[E]))}),x.push(b)});let y=s.nextSibling;x.forEach(w=>{w!==y?s.parentNode.insertBefore(w,y):y=y.nextSibling});for(let[w,E]of m.entries())h.has(w)||(E.remove(),m.delete(w))},destroy({binding:e}){let{anchor:t}=e;if(t&&W.has(t)){let r=W.get(t);r.forEach(o=>{[o,...o.querySelectorAll("*")].forEach(i=>{let a=A.get(i);a&&(a.listeners&&(a.listeners.forEach(({eventName:s,handler:c})=>{i.removeEventListener(s,c)}),a.listeners=null),a.bindings&&(a.bindings.forEach(s=>{s.observer&&(s.observer.disconnect(),s.observer=null)}),a.bindings=null))}),o.remove()}),r.clear(),W.delete(t)}t&&t.parentNode&&t.remove()}};var Ve={scan:e=>{if(e.hasAttribute("b-init"))return{type:"b-init",node:e,expr:e.getAttribute("b-init")}},execute:({binding:e,state:t,global:r})=>{e.initialized||(e.initialized=!0,L(e.expr,{state:t,global:r,self:e.node}))}};var Xe={name:"b-enter",scan:e=>O("b-enter",e,(t,r)=>({modifiers:t.name.split(".").slice(1)})),execute:({binding:e,state:t,global:r})=>{if(e.observer||e.done)return;let o=new IntersectionObserver((n,i)=>{if(n[0].isIntersecting){try{L(e.expr,{state:t,global:r,self:e.node})}catch(s){console.error("[Lego] Error in b-enter handler:",s)}e.modifiers.includes("once")&&(i.disconnect(),e.observer=null,e.done=!0)}});o.observe(e.node),e.observer=o},destroy:({binding:e})=>{e.observer&&(e.observer.disconnect(),e.observer=null)}};var Ze={name:"b-leave",scan:e=>O("b-leave",e),execute:({binding:e,state:t,global:r})=>{if(e.observer||e.done)return;let o=new IntersectionObserver((n,i)=>{let a=n[0];if(a.isIntersecting&&(e.activated=!0),!a.isIntersecting&&e.activated){try{L(e.expr,{state:t,global:r,self:e.node})}catch(s){console.error("[Lego] Error in b-leave handler:",s)}e.modifiers.includes("once")&&(i.disconnect(),e.observer=null,e.done=!0)}});o.observe(e.node),e.observer=o},destroy:({binding:e})=>{e.observer&&(e.observer.disconnect(),e.observer=null)}};var Qe={name:"b-mount",scan:(e,{checkGlobal:t})=>O("b-mount",e,r=>(t(r.value),{_lastTag:null})),execute({binding:e,state:t,global:r}){let{node:o,expr:n}=e,i=L(n,{state:t,global:r,self:o},!1),a=i?String(i).toLowerCase():null;a!==e._lastTag&&(e._lastTag=a,F(a,o))},destroy({binding:e}){e.node&&F(null,e.node),e._lastTag=null}};var se={"b-if":qe,"b-show":je,"b-text":Ke,"b-html":Ge,"b-sync":Ue,"b-for":Je,"b-init":Ve,"b-enter":Xe,"b-leave":Ze,"b-mount":Qe};var At=(e=null)=>{let t=!1,r=new Set,o=!1,n=e,i=new Set,a=null,s=new Set,c=d=>{n=d},f=()=>{a||(a=setTimeout(()=>{s.forEach(d=>{let p=d._studs;if(p&&typeof p.updated=="function")try{p.updated.call(p)}catch(m){console.error("[Lego] Error in updated hook:",m)}}),s.clear(),a=null},50))},l=()=>{i.size>0&&(i.forEach(d=>r.add(d)),i.clear(),!t&&r.size>0&&(t=!0,requestAnimationFrame(u)))},u=()=>{o=!0;let d=Array.from(r);r.clear(),t=!1,d.forEach(p=>{p.isConnected&&n&&n(p)}),d.forEach(p=>s.add(p)),f(),o=!1,l()};return{add:d=>{if(d){if(o){i.add(d);return}r.add(d),!t&&(t=!0,requestAnimationFrame(u))}},setHandler:c}},X=At();var N=new Map,he=new Map,ie=new WeakMap,le=new Map,ae=new WeakMap,ce=!1,kt=e=>{let t=Array.from(le.entries()).sort((n,i)=>n[1].timestamp-i[1].timestamp),r=0,o=[];for(let[n,i]of t){if(r>=e)break;try{localStorage.removeItem(n),r+=i.size,o.push(n),le.delete(n)}catch(a){console.error(`[Lego] Failed to evict ${n}:`,a)}}return o},et=(e,t,r)=>{g.debug&&console.log("[Lego Trace] scheduleSave",e,t,r),he.has(e)&&clearTimeout(he.get(e));let o=()=>{try{let n=JSON.stringify(t),i=new Blob([n]).size;localStorage.setItem(e,n),le.set(e,{timestamp:Date.now(),size:i}),he.delete(e)}catch(n){if(n.name==="QuotaExceededError"){console.warn(`[Lego] Storage quota exceeded for key: ${e}`);try{let i=JSON.stringify(t),a=new Blob([i]).size,s=kt(a*2);s.length>0?(g.debug&&console.log(`[Lego] Evicted ${s.length} old keys, retrying save`),localStorage.setItem(e,i),le.set(e,{timestamp:Date.now(),size:a})):g.onError(new Error("Storage quota exceeded and no keys available for eviction"),"quota",e)}catch{g.onError(new Error(`Critical: Could not save ${e} even after eviction`),"quota-critical",e)}}else console.error(`[Lego] Storage Error (${e}):`,n)}};r>0?he.set(e,setTimeout(o,r)):o()},Le=e=>({__type:"lego-db",key:e,_default:void 0,_debounce:0,default(r){return this._default=r,this},debounce(r){return this._debounce=r,this},set(r,o=0){return et(e,r,o),N.has(e)&&N.get(e).forEach(({target:n,prop:i,el:a,batcher:s})=>{n[i]=r,a&&s&&s.add(a)}),r},get(){try{let r=localStorage.getItem(e);return r!==null?JSON.parse(r):null}catch(r){return console.warn(`[Lego] Failed to get localStorage value for key "${e}":`,r),null}},delete(){try{return localStorage.removeItem(e),le.delete(e),N.has(e)&&N.get(e).forEach(({target:r,prop:o,el:n,batcher:i})=>{r[o]=null,n&&i&&i.add(n)}),!0}catch(r){return console.error(`[Lego] Failed to delete localStorage key "${e}":`,r),!1}}}),tt=e=>e&&e.__type==="lego-db",rt=(e,t,r,o,n)=>{g.debug&&console.log("[Lego Trace] Reactive DB Init:",t,r);let i=r._default;try{let s=localStorage.getItem(r.key);s!==null&&(i=JSON.parse(s))}catch(s){console.warn(`[Lego] Failed to parse localStorage value for key "${r.key}":`,s)}e[t]=i,ie.has(e)||ie.set(e,{}),ie.get(e)[t]={key:r.key,debounce:r._debounce},g.debug&&console.log("[Lego Trace] DB Metadata Set:",t,ie.get(e)[t]),N.has(r.key)||N.set(r.key,new Set);let a={target:e,prop:t,el:o,batcher:n};N.get(r.key).add(a),o&&(ae.has(o)||ae.set(o,new Set),ae.get(o).add({key:r.key,entry:a}))},ot=(e,t,r)=>{if(ce)return;let o=ie.get(e);if(o&&o[t]){let n=o[t].key;if(et(n,r,o[t].debounce),N.has(n)){ce=!0;try{N.get(n).forEach(({target:i,prop:a,el:s,batcher:c})=>{i!==e&&(i[a]=r,s&&c&&c.add(s))})}finally{ce=!1}}}},nt=e=>{let t=ae.get(e);t&&(t.forEach(({key:r,entry:o})=>{let n=N.get(r);n&&n.delete(o)}),ae.delete(e))},Ye=!1,st=()=>{typeof window>"u"||Ye||(Ye=!0,window.addEventListener("storage",e=>{if(!(!e.key||!N.has(e.key)))try{let t=e.newValue===null?null:JSON.parse(e.newValue);ce=!0;try{N.get(e.key).forEach(({target:r,prop:o,el:n,batcher:i})=>{r[o]=t,n&&i&&i.add(n)})}finally{ce=!1}}catch(t){console.warn("[Lego] Cross-tab sync error:",t)}}))};var Te=new WeakMap,be=null,Ae=null,it=(e,t)=>{be=e,Ae=t},at=()=>{be=null,Ae=null},ct=(e,t,r)=>{if(!be||Ae!==e)return;let o=Te.get(e);o||(o=new Map,Te.set(e,o));let n=o.get(t);n||(n=new Map,o.set(t,n));let i=n.get(r);i||(i=new Set,n.set(r,i)),i.add(be)},lt=(e,t,r)=>{let o=Te.get(e);if(!o)return null;let n=o.get(t);return n&&n.get(r)||null};var Z=(e,t,r=X)=>{if(e===null||typeof e!="object"||ve(e))return e;if(Y.has(e))return Y.get(e);for(let i in e){let a=Object.getOwnPropertyDescriptor(e,i);if(a&&a.get)continue;let s=e[i];tt(s)&&rt(e,i,s,t,r)}let o={get:(i,a,s)=>{ct(t,i,a);let c=Reflect.get(i,a,s);return c!==null&&typeof c=="object"&&!ve(c)?Z(c,t,r):c},set:(i,a,s,c)=>{if(a==="__proto__"||a==="constructor"||a==="prototype")return console.warn(`[Lego] Blocked setting dangerous property: "${a}"`),!0;let f=i[a];g.debug&&f!==s&&console.log("[Lego Trace] Reactive SET:",a,"Old:",f,"New:",s,"Target:",i);let l=c===Y.get(i),u=Object.prototype.hasOwnProperty.call(i,a),d=!l&&u?Reflect.set(i,a,s):Reflect.set(i,a,s,c);if((l||u)&&f!==s){let p=lt(t,i,a);if(p&&p.size>0){let m=A.get(t);m&&(m.dirtyBindings||(m.dirtyBindings=new Set),p.forEach(h=>m.dirtyBindings.add(h)))}r.add(t,a),ot(i,a,s)}return d},deleteProperty:(i,a)=>{let s=Reflect.deleteProperty(i,a),c=A.get(t);return c&&(c.dirtyBindings=null),r.add(t),s}},n=new Proxy(e,o);return Y.set(e,n),n};var Nt=e=>{let t=e;for(;t;){let r=t.getAttribute&&t.getAttribute("b-error");if(r&&r.toLowerCase()!==e.tagName.toLowerCase())return{errorTag:r,targetElement:t};let o=t.tagName?t.tagName.toLowerCase():"",n=S[o];if(n){let i=n.getAttribute("b-error");if(i&&i.toLowerCase()!==e.tagName.toLowerCase())return{errorTag:i,targetElement:t}}t=t.parentElement||t.getRootNode&&t.getRootNode().host}return null},ke=null,ft=null,dt=(e,t)=>{ke=e,ft=t},Ct=(e,t,r)=>{if(!ke||!ft){console.error("[Lego] Error boundary dependencies not loaded",r);return}try{t.shadowRoot?t.shadowRoot.innerHTML="":t.innerHTML="";let o=document.createElement(e);o.$initialState={$error:{message:r.message,stack:r.stack,component:t.tagName.toLowerCase()}},(t.shadowRoot||t).appendChild(o),ke(o)}catch(o){console.error("[Lego] Error boundary failed to render:",o),console.error("[Lego] Original error:",r)}},fe=new WeakMap,Mt=3,Q=(e,t,r)=>{let o=Nt(t);if(!o){g.onError(e,r,t);return}let n=o.targetElement,i=fe.get(n)||0;if(i>=Mt){console.error("[Lego] Error boundary recursion limit reached:",e),g.onError(e,r,t);return}fe.set(n,i+1);try{Ct(o.errorTag,n,e)}finally{let a=(fe.get(n)||0)-1;a<=0?fe.delete(n):fe.set(n,a)}};var ye=(e,t,r=null)=>{let o=t._studs,n=s=>{let c=M(s);if(!c.bound){if(s.hasAttributes()){let f=s.attributes;for(let u=0;u<f.length;u++){let d=f[u];if(d.name.startsWith("@")){let p=d.name.slice(1).split("."),m=p[0],h=p.slice(1),x=y=>{if(h.includes("prevent")&&y.preventDefault(),h.includes("stop")&&y.stopPropagation(),!(h.includes("self")&&y.target!==y.currentTarget)){if(typeof KeyboardEvent<"u"&&y instanceof KeyboardEvent){if(h.includes("ctrl")&&!y.ctrlKey||h.includes("alt")&&!y.altKey||h.includes("shift")&&!y.shiftKey||h.includes("meta")&&!y.metaKey)return;let w=h.filter(E=>!["prevent","stop","self","ctrl","alt","shift","meta","capture","once","passive"].includes(E));if(w.length>0){let E=y.key.toLowerCase();if(!w.some(b=>b==="enter"?E==="enter":b==="esc"||b==="escape"?E==="escape":b==="space"?E===" ":b==="tab"?E==="tab":b==="delete"?E==="delete":b==="backspace"?E==="backspace":b==="up"?E==="arrowup":b==="down"?E==="arrowdown":b==="left"?E==="arrowleft":b==="right"?E==="arrowright":b==="alpha"?/^[a-z]$/.test(E):b==="numbers"?/^[0-9]$/.test(E):b===E))return}}try{let w=o;if(r){let $=L(r.listName,{state:o,global:_,self:t})[r.index];w=Object.assign(Object.create(o),{[r.name]:$})}L(d.value,{state:w,global:_,self:s,event:y,$event:y},!0)}catch(w){Q(w,t,"event-handler")}}};s.addEventListener(m,x),c.listeners||(c.listeners=[]),c.listeners.push({eventName:m,handler:x})}}let l=K(s);if(l){let u=l.value,d=l.name.split(".").slice(1),p=d.includes("lazy"),m=d.includes("number"),h=d.includes("trim"),x=()=>{try{let y,w;if(u.startsWith("global.")){let $=u.slice(7).split(".");w=$.pop(),y=$.reduce((b,k)=>b[k],_)}else if(r&&u.startsWith(`${r.name}.`)){let b=L(r.listName,{state:o,global:_,self:t})[r.index];if(!b)return;let k=u.split(".").slice(1);w=k.pop(),y=k.reduce((Me,P)=>Me[P],b)}else{let $=u.split(".");w=$.pop(),y=$.reduce((b,k)=>b[k],o)}let E=s.type==="checkbox"?s.checked:s.value;if(h&&typeof E=="string"&&(E=E.trim()),m){let $=parseFloat(E);isNaN($)||(E=$)}y&&y[w]!==E&&(y[w]=E)}catch(y){g.onError(y,"sync-update",s)}};s._bSyncHandler=x,c.listeners||(c.listeners=[]),p||(s.addEventListener("input",x),c.listeners.push({eventName:"input",handler:x})),s.addEventListener("change",x),c.listeners.push({eventName:"change",handler:x})}if(s.hasAttribute("b-var")){let u=s.getAttribute("b-var");o.$vars&&(o.$vars[u]=s)}}c.bound=!0}};e instanceof Element&&n(e);let i=document.createTreeWalker(e,NodeFilter.SHOW_ELEMENT),a;for(;a=i.nextNode();)n(a)},ut=(e,t=null)=>{let r=[],o=[],[n]=oe(),i=t||e.host||e,a=Object.entries(se),s=/\bglobal\.([\w$]+)([\w$.]*)/g,c=l=>{if(!/\bglobal\b/.test(l))return;let u=!1,d=new Set,p;for(s.lastIndex=0;(p=s.exec(l))!==null;){if((p[2]||"").includes(".")){u=!0;break}d.add(p[1])}if(d.size===0&&(u=!0),u){U.add(i);return}d.forEach(m=>{let h=I.get(m);h||(h=new Set,I.set(m,h)),h.add(i)})},f=l=>{if(l.nodeType===Node.ELEMENT_NODE){let u=!1;for(let[,d]of a){if(!d.scan)continue;let p=d.scan(l,{checkGlobal:c,getPrivateData:M,pendingOperations:o,current:l});p&&(r.push(p),p.terminal&&(u=!0))}if(u)return;for(let d of l.attributes)d.value.includes(n)&&(c(d.value),r.push({type:"attr",node:l,attrName:d.name,template:d.value}));for(let d=l.firstChild;d;d=d.nextSibling)f(d)}else l.nodeType===Node.TEXT_NODE&&l.textContent.includes(n)&&(c(l.textContent),r.push({type:"text",node:l,template:l.textContent}))};if(e.nodeType===Node.ELEMENT_NODE)for(let l of e.attributes)l.value.includes(n)&&(c(l.value),r.push({type:"attr",node:e,attrName:l.name,template:l.value}));else e.nodeType===Node.TEXT_NODE&&e.textContent.includes(n)&&(c(e.textContent),r.push({type:"text",node:e,template:e.textContent}));for(let l=e.firstChild;l;l=l.nextSibling)f(l);return o.forEach(l=>l()),r},Ne=(e,t,r,o=!0)=>{if(!e.dead){o&&it(e,r);try{let n=se[e.type];if(n){n.execute({binding:e,state:t,global:_,helpers:{bind:ye,scanForBindings:ut,runBinding:Ne,contextEl:r}});return}if(e.type==="text"){let i=e.template.replace(we(),(a,s)=>L(s.trim(),{state:t,global:_,self:e.node},!1)??"");e.node.textContent!==i&&(e.node.textContent=i)}else if(e.type==="attr"){let i=e.template.replace(we(),(a,s)=>L(s.trim(),{state:t,global:_,self:e.node},!1)??"");e.node.getAttribute(e.attrName)!==i&&(e.node.setAttribute(e.attrName,i),e.attrName==="class"&&(e.node.className=i))}}finally{o&&at()}}},de=e=>{g.debug&&console.log("[Lego Trace] render() called for:",e.tagName);let t=e._studs;if(!t)return;let r=M(e);if(!r.rendering){r.rendering=!0,g.metrics&&g.metrics.onRenderStart&&g.metrics.onRenderStart(e);try{let o=e.shadowRoot||e;if(r.bindings||(r.bindings=ut(o)),r.dirtyBindings&&r.dirtyBindings.size>0){let n=r.dirtyBindings;r.dirtyBindings=null,n.forEach(i=>Ne(i,t,e))}else r.bindings.forEach(n=>Ne(n,t,e))}catch(o){Q(o,e,"render")}finally{g.metrics&&g.metrics.onRenderEnd&&g.metrics.onRenderEnd(e),r.rendering=!1}}};var pt=new Map,H=new Map,mt={},gt=e=>{mt=e},ht=async()=>{let e=Object.entries(mt).map(async([t,r])=>{let o=await Promise.all(r.map(async n=>{try{if(n instanceof CSSStyleSheet)return n;let i=await fetch(n);if(!i.ok)throw new Error(`Status ${i.status}`);let a=await i.text(),s=new CSSStyleSheet;return await s.replace(a),s}catch(i){return console.error(`[Lego] Failed to load stylesheet: ${n}`,i),null}}));pt.set(t,o.filter(n=>n!==null))});await Promise.all(e),g.debug&&console.log("[Lego Debug] Re-applying stylesheets to",C.size,"blocks"),C.forEach(t=>{Ce(t)})},Ce=e=>{if(!e.shadowRoot&&!e._legoShadow)return;let t=e.shadowRoot||e._legoShadow,r=e.tagName.toLowerCase(),o=S[r],n=(o&&o.getAttribute("b-stylesheets")||"").split(/\s+/).filter(Boolean),i=(e.getAttribute("b-stylesheets")||"").split(/\s+/).filter(Boolean),a=[],s=e.parentElement||(e.getRootNode?e.getRootNode().host:null);for(;s;){let u=(s.getAttribute("b-cascade")||"").split(/\s+/).filter(Boolean);u.length&&a.push(...u);let d=s.tagName?s.tagName.toLowerCase():"",p=H.get(d);p&&p.length&&a.push(...p),s=s.parentElement||s.getRootNode&&s.getRootNode().host}let c=[...new Set([...n,...i])],f=[...new Set(a)],l=[...new Set([...f,...c])];if(l.length>0){let u=l.flatMap(d=>pt.get(d)||[]);if(u.length>0&&g.debug&&console.log("[Lego Debug] Applying styles to",e.tagName,"- Names:",l,"- Sheets:",u.length),u.length>0){let d=t.adoptedStyleSheets.filter(p=>!u.includes(p));t.adoptedStyleSheets=[...d,...u]}}e._studsMeta={stylesheets:{explicit:c,inherited:f,applied:l}}};var bt=!1,T=e=>{if(g.debug&&console.log("[Lego Trace] snap() called for:",e.tagName),!e||e.nodeType!==Node.ELEMENT_NODE)return;let t=M(e),r=e.tagName.toLowerCase(),o=S[r];if(o&&!t.snapped){t.snapped=!0;let i=o.content.cloneNode(!0),a=e.shadowRoot;a?a.innerHTML="":a=e.attachShadow({mode:"open"}),Ce(e);let s=V(e,"*")||V(e.getRootNode().host,"*"),c=s&&s.state?s.state:{},f=q.get(r)||{},l=_e(o.getAttribute("b-logic")||o.getAttribute("b-data")||"{}"),u=_e(e.getAttribute("b-logic")||e.getAttribute("b-data")||"{}",c),d={$vars:{},$element:e,get $parent(){return V(e,"*")},$emit:(h,x)=>{e.dispatchEvent(new CustomEvent(h,{detail:x,bubbles:!0,composed:!0}))},get $route(){return _.$route},get $go(){return _.$go},get $mount(){return _.$mount}};G(f,d),G(l,d),G(u,d),e.$initialState&&(G(e.$initialState,d),delete e.$initialState),z.validate({instanceLogic:u,state:d,tagName:r}),e._studs=Z(d,e),Object.defineProperty(e,"state",{get(){return this._studs},set(h){bt||(bt=!0,console.warn("[Lego] `el.state = X` performs a shallow merge (Object.assign), not a replacement. Keys present on state but absent from X are preserved. Mutate state keys directly if you want this behaviour or remount the element to start fresh.")),Object.assign(this._studs,h)},configurable:!0,enumerable:!1}),j.locked=!0;try{a.appendChild(i)}finally{j.locked=!1}let p=a.querySelector("style");if(p){let h=[],x="__LEGO_SEG_",w=p.textContent.replace(/\/\*[\s\S]*?\*\/|"(?:\\.|[^"\\])*"|'(?:\\.|[^'\\])*'/g,E=>(h.push(E),`${x}${h.length-1}__`)).replace(/(?<![-\w])self(?![-\w])/g,":host");p.textContent=w.replace(/__LEGO_SEG_(\d+)__/g,(E,$)=>h[+$])}if(ye(a,e),C.add(e),de(e),e.setAttribute("b-id",r),e._legoShadow||(e._legoShadow=a),typeof e._studs.mounted=="function")try{e._studs.mounted.call(e._studs)}catch(h){Q(h,e,"mounted")}let m=a.querySelectorAll("*");g.debug&&console.log("[Lego Debug] Nested scan in",e.tagName,"- Found elements:",m.length),m.forEach(h=>{let x=h.tagName.toLowerCase(),y=!!S[x];y&&g.debug&&console.log("[Lego Debug] Checking",x,"- Registered:",y),y&&T(h)})}let n=e.parentElement;for(;n&&!n._studs;)n=n.parentElement;n&&n._studs&&ye(e,n),[...e.children].forEach(T)},B=e=>{if(e._studs&&typeof e._studs.unmounted=="function")try{e._studs.unmounted.call(e._studs)}catch(r){Q(r,e,"unmounted")}if(e.shadowRoot){let r=document.createTreeWalker(e.shadowRoot,NodeFilter.SHOW_ELEMENT),o;for(;o=r.nextNode();){let n=A.get(o);n&&n.listeners&&(n.listeners.forEach(({eventName:i,handler:a})=>{o.removeEventListener(i,a)}),n.listeners=null)}[...e.shadowRoot.children].forEach(B)}nt(e),C.delete(e),U.delete(e),I.forEach(r=>r.delete(e)),e._studs&&(e._studs.$element=null,e._studs.$vars&&(Object.keys(e._studs.$vars).forEach(r=>{e._studs.$vars[r]=null}),e._studs.$vars=null),e._studs.$emit&&(e._studs.$emit=null),delete e._studs.$parent,delete e._studs.$route,delete e._studs.$go,delete e._studs.$mount,e._studs=null),e.hasOwnProperty("state")&&delete e.state;let t=A.get(e);t&&(t.bindings&&(t.bindings.forEach(r=>{let o=se[r.type];if(o&&o.destroy)try{o.destroy({binding:r})}catch(n){console.error(`[Lego] Error in directive cleanup (${r.type}):`,n)}r.node=null,r.anchor=null}),t.bindings=null),t.anchor=null,A.delete(e)),[...e.children].forEach(B)};function yt(e,t="block.lego"){let r={template:"",script:"",style:"",stylesAttr:"",cascadeAttr:"",errorAttr:"",propsAttr:"",blockName:Pe(t),hasTemplate:!1,hasScript:!1,hasStyle:!1},o=e,n=/<(template|script|style)\b((?:\s+(?:[^>"']|"[^"]*"|'[^']*')*)*)>/i;for(;o;){let i=o.match(n);if(!i)break;let a=i[1].toLowerCase(),s=i[2],c=i[0],f=i.index,l=`</${a}>`,u=f+c.length,d=o.indexOf(l,u);if(d===-1){console.warn(`[Lego] Unclosed <${a}> tag in ${t}`);break}let p=o.slice(u,d);if(a==="template"){r.hasTemplate=!0,r.template=p.trim();let m=s.match(/b-stylesheets=["']([^"']+)["']/);m&&(r.stylesAttr=m[1]);let h=s.match(/b-cascade=["']([^"']+)["']/);h&&(r.cascadeAttr=h[1]);let x=s.match(/b-error=["']([^"']+)["']/);x&&(r.errorAttr=x[1]);let y=s.match(/b-props=["']([^"']+)["']/);y&&(r.propsAttr=y[1])}else if(a==="script"){r.hasScript=!0,r.script=p.trim();let m=s.match(/lang=["']([^"']+)["']/);m&&(r.scriptLang=m[1])}else a==="style"&&(r.hasStyle=!0,r.style=p.trim());o=o.slice(d+l.length)}return r}var Et=(e,t,r="block.lego")=>{let o=yt(t,r),{blockName:n,template:i,script:a,style:s,stylesAttr:c,cascadeAttr:f,errorAttr:l,propsAttr:u}=o,d={};if(a)try{let m=a.trim(),h=m.match(/export\s+default\s+(?:\/\*[\s\S]*?\*\/\s*|\/\/[^\n]*\n\s*)*({[\s\S]*})/),x=h?h[1]:m;d=new Function("Lego","$db",`return ${x}`)(e,e.globals.$db)}catch(m){g.onError(m,"script",n)}let p=i;s&&(p=`<style>${s}</style>`+p),S[n]=document.createElement("template"),S[n].innerHTML=p,c&&S[n].setAttribute("b-stylesheets",c),f&&(S[n].setAttribute("b-cascade",f),H.set(n,f.split(/\s+/).filter(Boolean))),l&&S[n].setAttribute("b-error",l),u&&S[n].setAttribute("b-props",u),z.register(n,u),q.set(n,d),document.querySelectorAll(n).forEach(m=>!M(m).snapped&&T(m))};X.setHandler(de);dt(T,de);Fe(T);He(T,B);var Ot={url:typeof window<"u"?window.location.pathname:"/",route:"",params:{},query:{},method:"GET",body:null},Bt={add(e,t){if(t!==void 0){let r=I.get(t);r&&r.forEach(o=>X.add(o))}U.forEach(r=>X.add(r))}},R=Z({$route:Ot,$go:(e,...t)=>ge(e,...t)(document.body),$mount:(e,t,r)=>F(e,t,r),$db:Le},typeof document<"u"?document.body:null,Bt);De(R);var v={db:Le,snap:T,unsnap:B,mount:F,defineLegoFile:(e,t)=>Et(v,e,t),block:(e,t,r={},o="",n="",i="",a="")=>{let s=document.createElement("template");s.setAttribute("b-id",e),s.setAttribute("b-stylesheets",o),n&&s.setAttribute("b-cascade",n),i&&s.setAttribute("b-error",i),a&&s.setAttribute("b-props",a),s.innerHTML=t,S[e]=s,q.set(e,r),z.register(e,a),n?H.set(e,n.split(/\s+/).filter(Boolean)):H.delete(e);try{let c={};G(r,c),ee.set(e.toLowerCase(),Z(c,document.body))}catch(c){g.onError(c,"define",e)}if(customElements.get(e))document.querySelectorAll(e).forEach(c=>{B(c),T(c)}),C.forEach(c=>{c._legoShadow&&c._legoShadow.querySelectorAll(e).forEach(f=>{B(f),T(f)})});else try{customElements.define(e,class extends HTMLElement{connectedCallback(){j.locked||S[e]&&T(this)}disconnectedCallback(){B(this)}})}catch(c){console.warn(`[Lego] Failed to register web component ${e}:`,c),delete S[e],q.delete(e),z.unregister(e),ee.delete(e.toLowerCase()),H.delete(e);return}},getActiveBlocksCount:()=>C.size,getLegos:()=>Object.keys(S),config:g,globals:R,route:(e,t,r=null)=>{let o=[],n=e.replace(/:([^\/]+)|\*|[.+?^${}()|[\]\\]/g,(i,a)=>a?(o.push(a),"([^/]+)"):i==="*"?".*":"\\"+i);ne.push({path:e,regex:new RegExp(`^${n}$`),tagName:t,paramNames:o,middleware:r})},debug:{stylesheets:e=>!e||!e._studsMeta?null:e._studsMeta.stylesheets},init:async(e=document.body,t={})=>{if((!e||typeof e.nodeType!="number")&&(e=document.body),gt(t.styles||{}),g.loader=t.loader,g.debug=t.debug===!0,await ht(),ne.length>0){let s=window.location.pathname,c=window.location.search,f=xe(s);if(f){let{match:l,params:u}=f,d=Object.fromEntries(new URLSearchParams(c));R.$route.url=s+c,R.$route.route=l.path,R.$route.params=u,R.$route.query=d,R.$route.method="GET",R.$route.body=null}}document.querySelectorAll("template[b-id]").forEach(s=>{let c=s.getAttribute("b-id");S[c]=s,z.register(c,s.getAttribute("b-props"));let f=s.getAttribute("b-cascade")||"";f&&H.set(c,f.split(/\s+/).filter(Boolean)),customElements.get(c)||customElements.define(c,class extends HTMLElement{connectedCallback(){j.locked||S[c]&&T(this)}disconnectedCallback(){B(this)}})});let r=/^[a-z][a-z0-9]*(-[a-z0-9]+)+$/,o=g.loaderAllowlist,n=s=>o?(Array.isArray(o)?o:[o]).some(f=>typeof f=="string"?f===s:typeof f=="function"?!!f(s):f&&typeof f.test=="function"?!!f.test(s):!1):!0,i=s=>{if(!s)return{};let c={};return Object.entries(s).forEach(([f,l])=>{if(typeof l=="function")c[f]=l();else if(typeof l=="string"&&l.startsWith("$db.")){let u=l.slice(4);c[f]=v.db(u).get()}else if(typeof l=="string"&&l.startsWith("$globals.")){let u=l.slice(9);c[f]=_[u]}else c[f]=l}),c},a=(s,c,f={})=>{if(!customElements.get(s)){if(!r.test(s)){console.warn(`[Lego] Manifest skipped malformed tag "${s}"`);return}if(!n(s)){console.warn(`[Lego] Manifest skipped "${s}": not in loaderAllowlist`);return}customElements.define(s,class extends HTMLElement{async connectedCallback(){if(S[s]){j.locked||T(this);return}if(v._fetching||(v._fetching=new Set),v._pendingLazy||(v._pendingLazy={}),v._fetching.has(s)){v._pendingLazy[s]||(v._pendingLazy[s]=new Set),v._pendingLazy[s].add(this);return}v._fetching.add(s);try{let l=c.startsWith("POST:")?"POST":"GET",u=c.replace(/^POST:/,""),d=i(f.headers),p={method:l,headers:d,credentials:f.credentials},m=await fetch(u,p);if(!m.ok)throw new Error(`HTTP ${m.status} loading block "${s}" from ${u}`);let h=await m.text();v.defineLegoFile(h,`${s}.lego`),S[s]&&T(this);let x=v._pendingLazy[s];x&&(x.forEach(y=>{y.isConnected&&S[s]&&!M(y).snapped&&T(y)}),delete v._pendingLazy[s])}catch(l){console.error(`[Lego] Failed to load manifest block ${s}:`,l)}finally{v._fetching.delete(s)}}disconnectedCallback(){B(this)}})}};if(t.manifest){let s=t.manifest;if(s.url&&typeof s.url=="string")try{let f=i(s.headers);s=await(await fetch(s.url,{headers:f,credentials:s.credentials})).json()}catch(f){console.error("[Lego] Failed to load manifest:",f),s=[]}else if(typeof s=="string")try{s=await(await fetch(s)).json()}catch(f){console.error("[Lego] Failed to load manifest:",f),s=[]}let c=Array.isArray(s)?s:[s];for(let f of c){let l=f.base||"",u=f.suffix===!0?".lego":f.suffix||"",d={headers:f.headers||{},credentials:f.credentials};f.legos&&f.legos.forEach(p=>{a(p,`${l}${p}${u}`,d)}),f.map&&Object.entries(f.map).forEach(([p,m])=>{let h=m.match(/^https?:|^\//)?m:`${l}${m}`;a(p,h,d)})}}if(g.loader){let s=!1,c=l=>{if(l.nodeType!==Node.ELEMENT_NODE)return;let u=l.tagName.toLowerCase();if(u.includes("-")&&!S[u]&&!C.has(l)){if(v._fetching&&v._fetching.has(u))return;if(!r.test(u)){g.debug&&console.warn(`[Lego] Loader skipped malformed tag "${u}"`);return}if(!n(u)){g.debug&&console.warn(`[Lego] Loader skipped "${u}": not in loaderAllowlist`);return}!o&&!s&&(s=!0,console.warn("[Lego] config.loader is set without config.loaderAllowlist. Any unknown hyphenated tag inserted into the page will trigger a fetch. Set Lego.config.loaderAllowlist to restrict this.")),v._fetching||(v._fetching=new Set),v._fetching.add(u);let d=g.loader(u);if(d){let p=typeof d=="string"?fetch(d).then(m=>m.text()):d;Promise.resolve(p).then(m=>{v.defineLegoFile(m,`${u}.lego`),v._fetching.delete(u)}).catch(m=>{console.error(`[Lego] Failed to load ${u}:`,m),v._fetching.delete(u)})}}if(l.children.length>0){let d=l.firstElementChild;for(;d;)c(d),d=d.nextElementSibling}};v._discoveryObserver&&v._discoveryObserver.disconnect(),v._discoveryObserver=new MutationObserver(l=>l.forEach(u=>{u.addedNodes.forEach(c)})),v._discoveryObserver.observe(e,{childList:!0,subtree:!0});let f=e.firstElementChild;for(;f;)c(f),f=f.nextElementSibling}if(t.studio){if(!S["lego-studio"]){let s=document.createElement("script");s.src="https://unpkg.com/@legodom/studio@0.0.2/dist/lego-studio.js",s.onerror=()=>console.warn("[Lego] Failed to load Studio from CDN"),document.head.appendChild(s)}v.route("/_/studio","lego-studio"),v.route("/_/studio/:block","lego-studio")}ne.length>0&&(window.addEventListener("popstate",s=>{let c=s.state?.legoTargets||null;me(c)}),document.addEventListener("submit",s=>{s.target.hasAttribute("b-action")&&s.preventDefault()}),document.addEventListener("click",s=>{let f=s.composedPath().find(l=>l.tagName==="A"&&(l.hasAttribute("b-target")||l.hasAttribute("b-link")));if(f){s.preventDefault();let l=f.getAttribute("href"),u=f.getAttribute("b-target"),d=u?u.split(/\s+/).filter(Boolean):[],p=f.getAttribute("b-link")!=="false";R.$go(l,...d).get(p)}}),me()),st()}};typeof window<"u"?window.Lego=v:typeof global<"u"&&(global.Lego=v);var xn=v;export{v as Lego,xn as default};
|
package/package.json
CHANGED
package/src/core/batcher.js
CHANGED
|
@@ -14,7 +14,12 @@ export const createBatcher = (renderHandler = null) => {
|
|
|
14
14
|
const setHandler = (fn) => { _render = fn; };
|
|
15
15
|
|
|
16
16
|
const scheduleUpdatedHooks = () => {
|
|
17
|
-
if
|
|
17
|
+
// Trailing-only debounce: do NOT reset the timer if it's already pending.
|
|
18
|
+
// Resetting on every batch lets sustained mutation (animations, websockets)
|
|
19
|
+
// starve the hook indefinitely. With this guard, the first batch arms the
|
|
20
|
+
// timer; subsequent batches within the window add to pendingUpdated but
|
|
21
|
+
// the hook still fires within ~50ms of the first update.
|
|
22
|
+
if (updatedTimer) return;
|
|
18
23
|
updatedTimer = setTimeout(() => {
|
|
19
24
|
pendingUpdated.forEach(el => {
|
|
20
25
|
const state = el._studs;
|
|
@@ -24,7 +29,7 @@ export const createBatcher = (renderHandler = null) => {
|
|
|
24
29
|
});
|
|
25
30
|
pendingUpdated.clear();
|
|
26
31
|
updatedTimer = null;
|
|
27
|
-
}, 50);
|
|
32
|
+
}, 50);
|
|
28
33
|
};
|
|
29
34
|
|
|
30
35
|
const processPendingQueue = () => {
|
package/src/core/lifecycle.js
CHANGED
|
@@ -1,8 +1,10 @@
|
|
|
1
|
-
import { registry, legoFileLogic, sharedStates, activeBlocks, getPrivateData, globalSubscribers, privateData, snapState } from './registry.js';
|
|
1
|
+
import { registry, legoFileLogic, sharedStates, activeBlocks, getPrivateData, globalSubscribers, globalKeySubscribers, privateData, snapState } from './registry.js';
|
|
2
|
+
import { bProps } from '../directives/b-props.js';
|
|
2
3
|
import { globals } from './globals.js';
|
|
3
4
|
import { directives } from '../directives/index.js';
|
|
4
5
|
import { config, mergeDescriptors, resolve, isNode } from '../utils/helpers.js';
|
|
5
6
|
import { findAncestor } from '../utils/dom.js';
|
|
7
|
+
import { cleanupDbBindings } from '../features/persistence.js';
|
|
6
8
|
import { parseJSObject } from '../utils/safe-eval.js';
|
|
7
9
|
import { reactive } from './reactive.js';
|
|
8
10
|
import { bind, render } from './renderer.js';
|
|
@@ -10,6 +12,12 @@ import { applyStyles } from './stylesheets.js';
|
|
|
10
12
|
import { findErrorBoundary, renderErrorBlock, handleError } from '../features/error.js';
|
|
11
13
|
import { _go } from '../features/router.js';
|
|
12
14
|
|
|
15
|
+
// Audit fix #24: `el.state = X` performs a shallow merge (Object.assign),
|
|
16
|
+
// not a replacement. Warn once per session so authors who expect
|
|
17
|
+
// assignment semantics (`=` looks like assignment, after all) discover
|
|
18
|
+
// the actual behaviour without flooding logs in steady-state apps.
|
|
19
|
+
let _stateAssignWarned = false;
|
|
20
|
+
|
|
13
21
|
export const snap = (el) => {
|
|
14
22
|
if (config.debug) console.log('[Lego Trace] snap() called for:', el.tagName);
|
|
15
23
|
if (!el || el.nodeType !== Node.ELEMENT_NODE) return;
|
|
@@ -50,7 +58,8 @@ export const snap = (el) => {
|
|
|
50
58
|
el.dispatchEvent(new CustomEvent(name, { detail, bubbles: true, composed: true }));
|
|
51
59
|
},
|
|
52
60
|
get $route() { return globals.$route },
|
|
53
|
-
get $go() { return globals.$go }
|
|
61
|
+
get $go() { return globals.$go },
|
|
62
|
+
get $mount() { return globals.$mount }
|
|
54
63
|
};
|
|
55
64
|
|
|
56
65
|
mergeDescriptors(scriptLogic, baseState);
|
|
@@ -63,11 +72,24 @@ export const snap = (el) => {
|
|
|
63
72
|
delete el.$initialState; // Cleanup
|
|
64
73
|
}
|
|
65
74
|
|
|
75
|
+
bProps.validate({ instanceLogic, state: baseState, tagName: name });
|
|
76
|
+
|
|
66
77
|
el._studs = reactive(baseState, el);
|
|
67
78
|
|
|
68
79
|
Object.defineProperty(el, 'state', {
|
|
69
80
|
get() { return this._studs },
|
|
70
|
-
set(v) {
|
|
81
|
+
set(v) {
|
|
82
|
+
if (!_stateAssignWarned) {
|
|
83
|
+
_stateAssignWarned = true;
|
|
84
|
+
console.warn(
|
|
85
|
+
'[Lego] `el.state = X` performs a shallow merge (Object.assign), ' +
|
|
86
|
+
'not a replacement. Keys present on state but absent from X are ' +
|
|
87
|
+
'preserved. Mutate state keys directly if you want this behaviour ' +
|
|
88
|
+
'or remount the element to start fresh.'
|
|
89
|
+
);
|
|
90
|
+
}
|
|
91
|
+
Object.assign(this._studs, v);
|
|
92
|
+
},
|
|
71
93
|
configurable: true,
|
|
72
94
|
enumerable: false
|
|
73
95
|
});
|
|
@@ -75,12 +97,36 @@ export const snap = (el) => {
|
|
|
75
97
|
// Suppress child connectedCallbacks during appendChild so children
|
|
76
98
|
// don't snap before this parent's mounted() hook has run.
|
|
77
99
|
snapState.locked = true;
|
|
78
|
-
|
|
79
|
-
|
|
100
|
+
try {
|
|
101
|
+
shadow.appendChild(tpl);
|
|
102
|
+
} finally {
|
|
103
|
+
snapState.locked = false;
|
|
104
|
+
}
|
|
80
105
|
|
|
81
106
|
const style = shadow.querySelector('style');
|
|
82
107
|
if (style) {
|
|
83
|
-
|
|
108
|
+
// Audit fix #38: don't reach into strings or comments. Previously the
|
|
109
|
+
// raw substitution turned `content: "self"` into `content: ":host"`
|
|
110
|
+
// and similarly mangled custom-property values that legitimately
|
|
111
|
+
// contained the bareword `self`. Stash strings + comments behind
|
|
112
|
+
// sentinel placeholders, run the rewrite, then restore. Doesn't
|
|
113
|
+
// attempt to distinguish selector context from value context — that
|
|
114
|
+
// would require a real CSS parser — but covers the common foot-guns.
|
|
115
|
+
const segments = [];
|
|
116
|
+
// Multi-char sentinel that never appears in normal CSS source.
|
|
117
|
+
const SENTINEL = '__LEGO_SEG_';
|
|
118
|
+
const protectedCss = style.textContent.replace(
|
|
119
|
+
/\/\*[\s\S]*?\*\/|"(?:\\.|[^"\\])*"|'(?:\\.|[^'\\])*'/g,
|
|
120
|
+
(m) => {
|
|
121
|
+
segments.push(m);
|
|
122
|
+
return `${SENTINEL}${segments.length - 1}__`;
|
|
123
|
+
}
|
|
124
|
+
);
|
|
125
|
+
const rewritten = protectedCss.replace(/(?<![-\w])self(?![-\w])/g, ':host');
|
|
126
|
+
style.textContent = rewritten.replace(
|
|
127
|
+
/__LEGO_SEG_(\d+)__/g,
|
|
128
|
+
(_, idx) => segments[+idx]
|
|
129
|
+
);
|
|
84
130
|
}
|
|
85
131
|
|
|
86
132
|
bind(shadow, el);
|
|
@@ -131,16 +177,35 @@ export const unsnap = (el) => {
|
|
|
131
177
|
}
|
|
132
178
|
}
|
|
133
179
|
|
|
134
|
-
// 2.
|
|
180
|
+
// 2. Remove stored event listeners from shadow root elements
|
|
135
181
|
if (el.shadowRoot) {
|
|
182
|
+
const walker = document.createTreeWalker(el.shadowRoot, NodeFilter.SHOW_ELEMENT);
|
|
183
|
+
let node;
|
|
184
|
+
while (node = walker.nextNode()) {
|
|
185
|
+
const nodeData = privateData.get(node);
|
|
186
|
+
if (nodeData && nodeData.listeners) {
|
|
187
|
+
nodeData.listeners.forEach(({ eventName, handler }) => {
|
|
188
|
+
node.removeEventListener(eventName, handler);
|
|
189
|
+
});
|
|
190
|
+
nodeData.listeners = null;
|
|
191
|
+
}
|
|
192
|
+
}
|
|
193
|
+
// Recursively unsnap children in shadowRoot
|
|
136
194
|
[...el.shadowRoot.children].forEach(unsnap);
|
|
137
195
|
}
|
|
138
196
|
|
|
139
|
-
// 3.
|
|
197
|
+
// 3. Clean up persistence bindings
|
|
198
|
+
cleanupDbBindings(el);
|
|
199
|
+
|
|
200
|
+
// 4. Remove from active blocks tracking
|
|
140
201
|
activeBlocks.delete(el);
|
|
141
202
|
globalSubscribers.delete(el);
|
|
203
|
+
// Audit fix #20: also drop el from each per-key subscriber set.
|
|
204
|
+
// Iterating the map is bounded by the number of distinct global keys
|
|
205
|
+
// ever subscribed (small in practice).
|
|
206
|
+
globalKeySubscribers.forEach(set => set.delete(el));
|
|
142
207
|
|
|
143
|
-
//
|
|
208
|
+
// 5. Break circular references
|
|
144
209
|
if (el._studs) {
|
|
145
210
|
// Clear element references in state object
|
|
146
211
|
el._studs.$element = null;
|
|
@@ -158,6 +223,7 @@ export const unsnap = (el) => {
|
|
|
158
223
|
delete el._studs.$parent;
|
|
159
224
|
delete el._studs.$route;
|
|
160
225
|
delete el._studs.$go;
|
|
226
|
+
delete el._studs.$mount;
|
|
161
227
|
|
|
162
228
|
// Break the proxy -> element reference
|
|
163
229
|
el._studs = null;
|