solarite 0.3.2 → 0.4.0

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.
@@ -1,4 +1,13 @@
1
- // Version 2025.7.28.0000
1
+ // Version 2025.12.26.2040
2
2
  // License: MIT
3
3
  // http://vorticode.github.io/solarite
4
- let lastObjectId=1,objectIds=new WeakMap;function getObjectId(t){let e=objectIds.get(t);return e||(e="~\f"+lastObjectId++,objectIds.set(t,e)),e}let isHashing=!0;function toJSON(){return isHashing?getObjectId(this):this}function getObjectHash(t){let e;Node.prototype.toJSON!==toJSON&&(Node.prototype.toJSON=toJSON,(()=>{}).toJSON!==toJSON&&(Function.prototype.toJSON=toJSON)),isHashing=!0;try{e=JSON.stringify(t)}catch(l){e=getObjectHashCircular(t)}return isHashing=!1,e}function getObjectHashCircular(t){const e=new Set;return JSON.stringify(t,((t,l)=>{if("object"==typeof l&&null!==l){if(e.has(l))return getObjectId(l);e.add(l)}return l}))}var Globals;function reset(){Globals={t:new WeakMap,connected:new WeakSet,l:null,div:document.createElement("div"),i:{},o:{},h:new WeakMap,u:new WeakMap,p:new WeakMap,m:new WeakSet,v:new WeakSet,P:new WeakMap,reset,count:0}}reset();var Globals$1=Globals;function delve(t,e,l=d){let s=l!==d,i=e.length;if(!t&&!s&&i)return;let r=0;for(let o of e){if(void 0===t[o]){if(!s)return;i-1>r&&(t[o]=(e[r+1]+"").match(/^\d+$/)?[]:{})}s&&r===i-1&&(t[o]=l),t=t[o],r++}return t}let d={},Util={$(t,e){let l=t.length;if(l!==e.length)return!1;for(let s=0;l>s;s++)if(t[s]!==e[s])return!1;return!0},N(t,e){let l=e.getAttribute("data-id")||e.getAttribute("id");if(l){if(t[l]&&!(t[l]instanceof Node))throw Error(`${t.constructor.name}.${l} already has a value. Can't set it as a reference to <${e.tagName.toLowerCase()} id="${l}">`);delve(t,l.split(/\./g),e)}},T(t,e){let l=e.getAttribute("data-style");l||(e.constructor.G||(e.constructor.G=1),l=e.constructor.G++,e.setAttribute("data-style",l));let s=e.tagName.toLowerCase();for(let e of t.childNodes)if(3===e.nodeType){let t=e.textContent,i=t.replace(/:host(?=[^a-z0-9_])/gi,`${s}[data-style="${l}"]`);t!==i&&(e.textContent=i)}},A:t=>(t=(t=(t=t.replace(/([a-z0-9])([A-Z])/g,"$1-$2")).replace(/([A-Z])([A-Z][a-z])/g,"$1-$2")).replace(/([a-zA-Z])([0-9])/g,"$1-$2")).toLowerCase(),S:t=>t.replace(/-([a-z])/g,(t=>t[1].toUpperCase())),H:t=>"checkbox"===t.type||"radio"===t.type?t.checked:"file"===t.type?[...t.files]:"number"===t.type||"range"===t.type?t.valueAsNumber:"date"===t.type||"time"===t.type||"datetime-local"===t.type?t.valueAsDate:"select-multiple"===t.type?[...t.selectedOptions].map((t=>t.value)):t.value,O:t=>t.startsWith("on")&&t in Globals$1.div,C(t,e){let l=t.tagName+"."+e,s=Globals$1.o[l];if(void 0===s){let i=Object.getPrototypeOf(t);for(;i;){const t=i.constructor.name;if(t.startsWith("HTML")&&t.endsWith("Element"))break;i=Object.getPrototypeOf(i)}Globals$1.o[l]=s=!!i&&!!Object.getOwnPropertyDescriptor(i,e)?.set}return s},k:t=>Array.isArray(t)&&t.length>=2&&("object"==typeof t[0]||void 0===t[0])&&!t.slice(1).find((t=>"string"!=typeof t&&"number"!=typeof t)),M:t=>void 0===t||!1===t||null===t,j:t=>"function"==typeof t?Util.j(t()):t instanceof Date?t.toISOString().replace(/T/," "):Array.isArray(t)||"object"==typeof t?"":t,U(t,e,l){let s=t.get(e);s?s.push(l):(s=[l],t.set(e,s))},I(t){const e=t=>t.nodeType!==Node.ELEMENT_NODE&&(t.nodeType!==Node.TEXT_NODE||""===t.textContent.trim()),l=[...t];for(;l.length>0&&e(l[0]);)l.shift();for(;l.length>0&&e(l[l.length-1]);)l.pop();return l}};class MultiValueMap{data={};add(t,e){let l=this.data,s=l[t];s||(s=new Set,l[t]=s),s.add(e)}F(){for(let t in this.data)return!0;return!1}getAll(t){return this.data[t]||[]}delete(t,e=void 0){let l,s=this.data,i=s[t];if(i)return void 0===e?([l]=i,i.delete(l)):(i.delete(e),l=e),0===i.size&&delete s[t],l}R(t){let e,l=this.data,s=l[t];if(s)return[e]=s,s.delete(e),0===s.size&&delete l[t],e}V(t,e){let l,s=this.data,i=s[t];if(i)return i.delete(e),l=e,0===i.size&&delete s[t],l}J(t){let e=this.data,l=[];for(let s in e)e[s].has(t)&&l.push(s);return l}}const udomdiff=(t,e,l,s)=>{const i=l.length;let r=e.length,o=i,a=0,n=0,h=null;for(;r>a||o>n;)if(r===a){const e=i>o?n?l[n-1].nextSibling:l[o-n]:s;for(;o>n;){let s=l[n++];t.insertBefore(s,e)}}else if(o===n)for(;r>a;){let l=e[a];h&&h.has(l)||t.removeChild(l),a++}else if(e[a]===l[n])a++,n++;else if(e[r-1]===l[o-1])r--,o--;else if(e[a]===l[o-1]&&l[n]===e[r-1]){const s=e[--r].nextSibling;let i=l[n++],h=e[a++];t.insertBefore(i,h.nextSibling);let f=l[--o];t.insertBefore(f,s),e[r]=l[o]}else{if(!h){h=new Map;let t=n;for(;o>t;)h.set(l[t],t++)}if(h.has(e[a])){const s=h.get(e[a]);if(s>n&&o>s){let i=a,f=1;for(;++i<r&&o>i&&h.get(e[i])===s+f;)f++;if(f>s-n){const i=e[a];for(;s>n;){let e=l[n++];t.insertBefore(e,i)}}else{let s=e[a++],i=l[n++];t.replaceChild(i,s)}}else a++}else{let l=e[a++];t.removeChild(l)}}return l};class ExprPath{type;attrName;L;W;D;_;B;u=[];K;Z;q;X;Y;tt=void 0;constructor(t,e,l=ExprPathType.et,s=null,i=null){this.D=t,this._=e,this.type=l,this.attrName=s,this.L=i,l===ExprPathType.lt&&(this.W=new Set)}apply(t,e=!0){switch(this.type){case 1:this.st(t[0],e);break;case 2:this.it(this._,t[0]);break;case 5:break;case 6:this.rt(this._,t[0],this.B.ot.root);break;default:this.nt(this._,t)}}st(t,e=!0){let l=this;e&&l.ht();let s=[],i=l.u,r=[];l.u=[],l.ft(t,s,r);let o=!1;if(r.length){for(let[t,e]of r){let i=l.ut(s[t],!1),r=i.ct();1===r.length?s[t]=r[0]:(s[t]=r,o=!0),l.u[e]=i}o&&(s=s.flat())}let a=l.ct();if(!Util.$(a,s)){l.K=s,this.B.dt&&this.B.dt.bt(),a.length&&!s.length&&l.yt()||udomdiff(l._.parentNode,a,s,l._);for(let t of i)t.gt.parentNode||t.vt();for(let t of s)if(t instanceof HTMLElement){t.hasAttribute("solarite-placeholder")&&this.B.Et(t);for(let e of t.querySelectorAll("[solarite-placeholder]"))this.B.Et(e)}}}Pt(t){let e=Math.min(t.$t,t.items.length),l=t.$t-e;for(let l=0;e>l;l++){let e=this.u[t.index+l],s=(this.Y||this.X)(t.items[l]);this.Nt(s,(s=>{let i=this.ut(s,!0);if(i&&i===e);else{i||(i=this.ut(s,!1)),this.u[t.index+l]=i;let r=e.gt;for(let t of i.ct())r.parentNode.insertBefore(t,r);i!==e&&e.vt()}}))}if(l>0){for(let s=0;l>s;s++)this.u[t.index+e+s].vt();this.u.splice(t.index+e,l)}else{let l=t.items.slice(e),s=this.u[t.index+e]?.gt||this._;for(let t=0;l.length>t;t++){let e=this.Y(l[t]),i=this.ut(e,!0);i||(i=this.ut(e,!1)),this.u.push(i);for(let t of i.ct())s.parentNode.insertBefore(t,s)}}this.K=null}Nt(t,e){if(Array.isArray(t))for(let l of t)this.Nt(l,e);else if("function"==typeof t)Globals$1.l=this,this.X=t,t=t(),Globals$1.l=null,this.Nt(t,e);else if(t instanceof Template||t instanceof Node)e(t);else{void 0===t||!1===t||null===t?t="":"string"!=typeof t&&(t+="");let l=new Template([t],[]);this.Nt(l,e)}}ft(t,e,l){if(t instanceof Template){let s=this.ut(t,!0);s?(e.push(...s.ct()),this.u.push(s)):(l.push([e.length,this.u.length]),e.push(t),this.u.push(null))}else t instanceof Node?t instanceof DocumentFragment?e.push(...t.childNodes):e.push(t):this.Nt(t,(t=>{this.ft(t,e,l)}))}it(t,e){Array.isArray(e)&&(e=e.flat().join(" "));let l=this.W;if(this.W=new Set,e)if("function"==typeof e&&(Globals$1.l=this,this.X=e,e=e(),Globals$1.l=null),"object"==typeof e)for(let l in e){let s=e[l];void 0!==s&&!1!==s&&null!==s&&(t.setAttribute(l,s),this.W.add(l))}else{let l=(e+"").split(/([\w-]+\s*=\s*(?:"[^"]*"|'[^']*'|[^\s]+))/g).map((t=>t.trim())).filter((t=>t.length));for(let e of l){let[l,s]=e.split(/\s*=\s*/);s=(s||"").replace(/^(['"])(.*)\1$/,"$2"),t.setAttribute(l,s),this.W.add(l)}}for(let e of l)this.W.has(e)||t.removeAttribute(e)}rt(t,e,l){let s,i=this.attrName.slice(2),r=[];if(Array.isArray(e)&&"function"==typeof e[0])s=e[0],r=e.slice(1);else{if("function"!=typeof e)throw Error(`Invalid event binding: <${t.tagName.toLowerCase()} ${this.attrName}=\${${JSON.stringify(e)}}>`);s=e}this.Tt(t,l,i,i,s,r)}Tt(t,e,l,s,i,r,o=!1){let a=Globals$1.h.get(t);a||(a={[l]:[,,,]},Globals$1.h.set(t,a));let n=a[l];if(n||(a[l]=n=[,,,]),"function"!=typeof i)throw Error(`Solarite cannot bind to <${t.tagName.toLowerCase()} ${this.attrName}=\${${i}}> because it's not a function.`);if(n[0]!==i){let[l,r,a]=n;l&&t.removeEventListener(s,r,o);let h=i,f=l=>h.call(e,...n[2],l,t);n[0]=h,n[1]=f,t.addEventListener(s,f,o)}a[l][2]=r}nt(t,e){let l=e[0];if(Util.k(l)){let[e,s]=[l[0],l.slice(1)];if(!e)throw Error(`Solarite cannot bind to <${t.tagName.toLowerCase()} ${this.attrName}=\${[${l.map((t=>t?`'${t}'`:t+"")).join(", ")}]}>.`);let i=delve(e,s);if("value"===this.attrName&&"select-multiple"===t.type&&Array.isArray(i)){let e=i.map((t=>t+""));for(let l of t.options)l.selected=e.includes(l.value)}else{let e=Util.M(i)?"":i;e!==t[this.attrName]&&(t[this.attrName]=e)}let r=()=>{let l="value"===this.attrName?Util.H(t):t[this.attrName];delve(e,s,l)};this.Tt(t,s[0],this.attrName,"input",r,[],!0)}else{let s=this.tt;void 0===s&&(s=this.tt=Util.C(t,this.attrName));let i=this.L;if(!i){if(Globals$1.l=this,"function"==typeof l){if(4===this.type)return;this.X=l,l=l()}else l=Util.j(l);Globals$1.l=null}if(i||void 0!==l&&!1!==l&&null!==l)if(i||!0!==l){let r;if(i){let t=[];for(let l=0;this.L.length>l;l++)if(t.push(this.L[l]),this.L.length-1>l){Globals$1.l=this;let s=Util.j(e[l]);Globals$1.l=null,Util.M(s)||t.push(s)}r=t.join("")}else r=l;(s?t[this.attrName]:t.getAttribute(this.attrName))!==r&&(s&&(t[this.attrName]=r),t.setAttribute(this.attrName,r))}else s&&(t[this.attrName]=!0),t.setAttribute(this.attrName,"");else s&&(t[this.attrName]=!1),t.removeAttribute(this.attrName)}}clone(t,e=0){let l,s,i=t,r=e?this.q.slice(0,-e):this.q;for(let t=r.length-1;t>0;t--)i=i.childNodes[r[t]];let o=i.childNodes;return l=r.length?o[r[0]]:t,this.D&&(s=o[this.Z]),new ExprPath(s,l,this.type,this.attrName,this.L)}bt(){let t=this,e=this._.parentNode;for(;t&&t._.parentNode===e;)t.K=null,t=t.B?.dt}yt(){let t=this.D.parentNode;return this.D===t.firstChild&&this._===t.lastChild&&(t.innerHTML="",t.append(this.D,this._),!0)}ct(){if(this.type===ExprPathType.wt||this.type===ExprPathType.lt||this.type===ExprPathType.Gt)return[this._];let t;if(t=this.K,t)return t;t=[];let e=this.D.nextSibling,l=this._;for(;e&&e!==l;)t.push(e),e=e.nextSibling;return this.K=t,t}xt(){return this._.parentNode}ut(t,e=!0){let l,s=this.At;if(e){if(l=s.R(t.St()),l||(s=this.Ht,l=s.R(t.St())),!l)return null;s.V(t.Ot(),l)}else t.Ct.length&&(l=s.R(t.Ot()),l||(s=this.Ht,l=s.R(t.Ot())),l&&(s.V(l.kt,l),l.Mt(t.Ct),l.kt=t.St()));return l||(l=new NodeGroup(t,this)),this.jt.push(l),l}Ut(){return this.type===ExprPathType.Gt||this.attrName&&this._.tagName&&this._.tagName.includes("-")}jt=[];At=new MultiValueMap;Ht=new MultiValueMap;ht(){let t=this.At.data,e=this.Ht.data;for(let l in t){let s=e[l];if(s)for(let e of t[l])s.add(e);else e[l]=t[l]}this.At=new MultiValueMap;let l=this.At;for(let t of this.jt)l.add(t.kt,t),l.add(t.It,t);this.jt=[]}}const ExprPathType={et:1,lt:2,wt:3,Gt:4,Comment:5,Event:6};function getNodePath(t){let e=[];for(;;){let l=t.parentNode;if(!l)break;e.push([].indexOf.call(t.parentNode.childNodes,t)),t=l}return e}function resolveNodePath(t,e){for(let l=e.length-1;l>=0;l--)t=t.childNodes[e[l]];return t}class HtmlParser{constructor(){this.Ft={context:HtmlParser.Text,quote:null,buffer:"",Rt:null},this.state={...this.Ft}}reset(){return this.state={...this.Ft},this.state.context}parse(t,e=null){if(null===t)return this.reset();for(let l=0;t.length>l;l++){const s=t[l];switch(this.state.context){case HtmlParser.Text:"<"===s&&t[l+1].match(/[/a-z!]/i)&&(e?.(t,l,this.state.context,HtmlParser.Vt),this.state.context=HtmlParser.Vt,this.state.buffer="");break;case HtmlParser.Vt:if(">"===s)e?.(t,l+1,this.state.context,HtmlParser.Text),this.state.context=HtmlParser.Text,this.state.quote=null,this.state.buffer="";else{if(" "===s&&!this.state.buffer)continue;" "===s||"/"===s||"?"===s?this.state.buffer="":'"'===s||"'"===s||"="===s?(e?.(t,l,this.state.context,HtmlParser.Jt),this.state.context=HtmlParser.Jt,this.state.quote="="===s?null:s,this.state.buffer=""):this.state.buffer+=s}break;case HtmlParser.Jt:this.state.quote||this.state.buffer.length||'"'!==s&&"'"!==s?s===this.state.quote||!this.state.quote&&this.state.buffer.length?(e?.(t,l,this.state.context,HtmlParser.Vt),this.state.context=HtmlParser.Vt,this.state.quote=null,this.state.buffer=""):this.state.quote||">"!==s?" "!==s&&(this.state.buffer+=s):(e?.(t,l+1,this.state.context,HtmlParser.Text),this.state.context=HtmlParser.Text,this.state.quote=null,this.state.buffer=""):this.state.quote=s}}return e?.(t,t.length,this.state.context,null),this.state.context}}HtmlParser.Jt="Attribute",HtmlParser.Text="Text",HtmlParser.Vt="Tag";class Shell{fragment;Lt=[];Wt=[];scripts=[];zt=[];Dt=[];constructor(t=null){if(!t)return;if(1===t.length&&!t[0].match(/[<&]/))return void(this.fragment=document.createTextNode(t[0]));let e,l=Shell._t(t),s=document.createElement("template");l?s.innerHTML=l:s.content.append(document.createTextNode("")),this.fragment=s.content;let i=[],r=0;const o=document.createTreeWalker(this.fragment,NodeFilter.SHOW_ELEMENT|NodeFilter.SHOW_COMMENT|NodeFilter.SHOW_TEXT);for(;e=o.nextNode();)if(i.map((t=>t.remove())),i=[],1===e.nodeType)for(let t of[...e.attributes]){let l=t.name.match(/^[\ue000-\uf8ff]$/);if(l)this.Lt.push(new ExprPath(null,e,ExprPathType.lt)),r++,e.removeAttribute(l[0]);else{let l=t.value.split(/[\ue000-\uf8ff]/g);if(l.length>1){let s=2!==l.length||l[0].length||l[1].length?l:null,i=Util.O(t.name)?ExprPathType.Event:ExprPathType.wt;this.Lt.push(new ExprPath(null,e,i,t.name,s)),r+=l.length-1,e.setAttribute(t.name,l.join(""))}}}else if(8===e.nodeType&&"!✨!"===e.nodeValue){let t,l=e.previousSibling;l||(l=document.createComment("ExprPath:"+this.Lt.length),e.parentNode.insertBefore(l,e)),!e.nextSibling||8===e.nextSibling.nodeType&&"!✨!"===e.nextSibling.textContent?(t=e,t.textContent="ExprPathEnd:"+this.Lt.length):(t=e.nextSibling,i.push(e));let s=new ExprPath(l,t,ExprPathType.et);this.Lt.push(s),r++}else{if(3===e.nodeType&&"TEXTAREA"===e.parentNode?.tagName&&e.textContent.includes("\x3c!--!✨!--\x3e"))throw Error('Textarea can\'t have expressions inside them. Use <textarea value="${...}"> instead.');if(e.nodeType===Node.COMMENT_NODE){let t=e.textContent.split(/[\ue000-\uf8ff]/g);for(let l=0;t.length-1>l;l++){let t=new ExprPath(e.previousSibling,e);t.type=ExprPathType.Comment,this.Lt.push(t),r++}}else if(e.nodeType===Node.TEXT_NODE&&["SCRIPT","STYLE"].includes(e.parentNode?.nodeName)){let t=e.textContent.split(commentPlaceholder);if(t.length>1){let l=[];for(let s=0;t.length>s;s++){let i=document.createTextNode(t[s]);e.parentNode.insertBefore(i,e),s>0&&l.push(i)}for(let t,e=0;t=l[e];e++){let e=new ExprPath(t.previousSibling,t,ExprPathType.et);this.Lt.push(e),r++}i.push(e)}}}if(i.map((t=>t.remove())),r!==t.length-1)throw Error("Could not parse expressions in template. Check for duplicate attributes or malformed html: "+t.join("${...}"));for(let t of this.fragment.querySelectorAll("[is]"))t.setAttribute("_is",t.getAttribute("is"));for(let t of this.Lt)t.D&&(t.Z=[].indexOf.call(t.D.parentNode.childNodes,t.D)),t.q=getNodePath(t._),t.type===ExprPathType.wt&&1===t._.nodeType&&(t._.tagName.includes("-")||t._.hasAttribute("is"))&&(t.type=ExprPathType.Gt);this.Bt()}static _t(t){let e=[];function l(t,l){l===HtmlParser.Vt&&(t=t.replace(/^<\/?[a-z][a-z0-9]*-[a-z0-9-]+/i,(t=>t+"-solarite-placeholder solarite-placeholder"))),e.push(t)}let s=new HtmlParser;for(let i=0;t.length>i;i++){let r=0,o=s.parse(t[i],((t,e,s,i)=>{r!==e&&l(t.slice(r,e),s),r=e}));t.length-1>i&&e.push(o===HtmlParser.Text?commentPlaceholder:String.fromCharCode(attribPlaceholder+i))}return e.join("")}Bt(){this.scripts=[].map.call(this.fragment.querySelectorAll("scripts"),(t=>getNodePath(t))),this.zt=[].map.call(this.fragment.querySelectorAll("style"),(t=>getNodePath(t)));let t=this.fragment.querySelectorAll("[id],[data-id]");for(let e of t){let t=e.getAttribute("data-id")||e.getAttribute("id");if(Globals$1.div.hasOwnProperty(t))throw Error(`<${e.tagName.toLowerCase()} id="${t}"> can't override existing HTMLElement id property.`)}this.Wt=[].map.call(t,(t=>getNodePath(t)));for(let t of this.fragment.querySelectorAll("*"))(t.tagName.includes("-")||t.hasAttribute("_is"))&&(this.Lt.find((e=>e._===t))||this.Dt.push(getNodePath(t)))}static get(t){let e=Globals$1.P.get(t);return e||(e=new Shell(t),Globals$1.P.set(t,e)),e}}const commentPlaceholder="\x3c!--!✨!--\x3e",attribPlaceholder=57344;class NodeGroup{ot;dt;gt;Kt;Lt=[];kt;It;K;zt;constructor(t,e=null){if(!(this instanceof RootNodeGroup)){let[l,s]=this.init(t,e);if(l&&t.Ct.length){this.Zt(l,s.Lt);let e=this.qt(l,s);this.Xt(l,s),this.Mt(t.Ct),this.Yt(e)}else s&&this.Xt(l,s)}}init(t,e=null,l=null,s=null){if(this.kt=l||t.St(),this.It=s||t.Ot(),this.dt=e,this.ot=e?.B?.ot||this,this.Qt=t,t.te=this,this instanceof RootNodeGroup||t.Ct.length||t.ee[0].includes("<")){let e=Shell.get(t.ee),l=e.fragment.cloneNode(!0);if(l instanceof DocumentFragment){let t=l.childNodes;this.gt=t[0],this.Kt=t[t.length-1]}else this.gt=this.Kt=l;return[l,e]}{let e=document.createTextNode(t.ee[0]);return this.gt=this.Kt=e,[]}}Mt(t,e=null){let l,s=t.length-1,i=Array((e=e||this.Lt).length);for(let r,o=e.length-1;r=e[o];o--){let a=e[o-1],n=e[o+1];if(r.L?.length>2?(i[o]=t.slice(s-(r.L.length-1)+1,s+1),s-=i[o].length):(i[o]=[t[s]],s--),r._!==this.ot.root&&r.Ut()){if(n&&n.Ut()&&n._===r._||(l=o),!a||!a.Ut()||a._!==r._){let t={};for(let s=o;l>=s;s++)t[e[s].attrName]=i[s].length>1?i[s].join(""):i[s][0];this.le(r._,t);for(let t=o;l>=t;t++)e[t].apply(i[t])}}else r.apply(i[o])}this.se(),this.K=null}le(t,e){let l=getObjectHash(e),s=t.hasAttribute("solarite-placeholder"),i=t.hasAttribute("_is");if(s||i)t=this.Et(t,s,e);else if(t.ie){let l={};for(let t in e||{})l[Util.S(t)]=e[t];t.ie(l)}Globals$1.t.set(t,l)}Et(t,e=void 0,l=void 0){void 0===e&&(e=!t.hasAttribute("_is"));let s=(e?t.tagName.slice(0,-21):t.getAttribute("is")).toLowerCase(),i=customElements.get(s);if(!i)throw Error(`The custom tag name ${s} is not registered.`);let r={};for(let t in l||{})r[Util.S(t)]=l[t];if(t.attributes.length)for(let e of t.attributes){let t=Util.S(e.name);r.hasOwnProperty(t)||"solarite-placeholder"===t||(r[t]=e.value)}let o=new i(r,[...t.childNodes].filter((t=>t.nodeType!==Node.COMMENT_NODE||!t.nodeValue.startsWith("ExprPath"))));e||o.setAttribute("is",t.getAttribute("is").toLowerCase()),t.replaceWith(o);let a=t.getAttribute("data-id")||t.getAttribute("id");a&&delve(this.getRootNode(),a.split(/\./g),o);for(let e of this.Lt)e._===t&&(e._=o),e.D===t&&(e.D=o);this.gt===t&&(this.gt=o),this.Kt===t&&(this.Kt=o),o.re&&o.re();for(let e of t.attributes)"_is"!==e.name&&"solarite-placeholder"!==e.name&&o.setAttribute(e.name,e.value);for(let t in l){let e=l[t];"boolean"==typeof e?!1!==e&&null!=e&&o.setAttribute(t,""):["number","bigint","string"].includes(typeof e)&&o.setAttribute(t,e)}return o}ct(){let t=this.K;if(t)return t;t=[];let e=this.gt,l=this.Kt?.nextSibling;for(;e&&e!==l;)t.push(e),e=e.nextSibling;return this.K=t,t}xt(){return this.gt?.parentNode}getRootNode(){return this.ot.root}oe(){return this.ot}vt(){let t=document.createDocumentFragment();for(let e of this.ct())t.append(e)}Zt(t,e,l){let s=e.length;this.Lt.length=s;for(let i=0;s>i;i++){let s=e[i].clone(t,l);s.B=this,this.Lt[i]=s}}se(){if(this.zt)for(let[t,e]of this.zt)e!==t.textContent&&Util.T(t,this.oe().root)}qt(t,e,l=0){let s=[];for(let i of e.Dt){l&&(i=i.slice(0,-l));let e=resolveNodePath(t,i);t!==e&&s.push(e)}return s}Yt(t){for(let e of t)this.Et(e)}Xt(root,shell,pathOffset=0){let rootEl=this.ot.root;if(rootEl){let options=this.ot.options;if(!1!==options?.Wt)for(let t of shell.Wt){pathOffset&&(t=t.slice(0,-pathOffset));let e=resolveNodePath(root,t);Util.N(rootEl,e)}if(!1!==options?.zt){shell.zt.length&&(this.zt=new Map);for(let t of shell.zt){pathOffset&&(t=t.slice(0,-pathOffset));let e=resolveNodePath(root,t);1===rootEl.nodeType&&(Util.T(e,rootEl),this.zt.set(e,e.textContent))}}if(!1!==options?.scripts)for(let path of shell.scripts){pathOffset&&(path=path.slice(0,-pathOffset));let script=resolveNodePath(root,path);eval(script.textContent)}}}}class RootNodeGroup extends NodeGroup{root;ae=new Map;constructor(t,e,l){super(t),this.options=l,this.ot=this;let[s,i]=this.init(t);if(s instanceof Text)e&&(this.gt=e,this.Kt=e,s.nodeValue.length&&e.append(s),this.root=e),Globals$1.u.set(this.root,this);else{let l=0,r=s;if(e){let t;if(Globals$1.u.set(e,this),e.childNodes.length&&(t=document.createDocumentFragment(),t.append(...e.childNodes)),this.root=e,isReplaceEl(s,e)){e.append(...s.children[0].childNodes);for(let t of s.children[0].attributes)e.hasAttribute(t.name)||"solarite-placeholder"===t.name||e.setAttribute(t.name,t.value);l=1}else 1===s.childNodes.length&&3===s.childNodes[0].nodeType&&""===s.childNodes[0].textContent||e.append(...s.childNodes);if(t){for(let l of e.querySelectorAll("slot[name]")){let e=l.getAttribute("name");if(e){let s=t.querySelectorAll(`[slot='${e}']`);l.append(...s)}}let l=e.querySelector("slot:not([name])");l?l.append(t):e.append(t)}r=e,this.gt=e,this.Kt=e}else{let t=getSingleEl(s);this.root=t||s,Globals$1.u.set(this.root,this),t&&(r=t,l=1)}this.Zt(r,i.Lt,l);let o=this.qt(r,i,l);this.Xt(r,i,l),this.Mt(t.Ct),this.Yt(o)}}}function getSingleEl(t){let e=[];for(let l of t.childNodes)if(1===l.nodeType||3===l.nodeType&&l.textContent.trim().length){if(e.length)return null;e.push(l)}return e[0]}function isReplaceEl(t,e){return 1===t.children.length&&e.tagName.includes("-")&&t.children[0].tagName.replace("-SOLARITE-PLACEHOLDER","")===e.tagName}class Template{Ct=[];ee=[];ne;te;constructor(t,e){this.ee=t,this.Ct=e}toJSON(){return this.ne||(this.ne=[getObjectId(this.ee),this.Ct]),this.ne}ie(t=null,e={}){let l,s=!1;if(t){if(l=Globals$1.u.get(t),l||(l=new RootNodeGroup(this,t,e),Globals$1.u.set(t,l),s=!0),0===l.Lt.length&&this.Ct.length||l.Lt.length>this.Ct.length)throw Error(`Solarite Error: Parent HTMLElement ${l.Qt.ee.join("${...}")} and ${l.Lt.length} \${value} placeholders can't accomodate a Template with ${this.Ct.length} values.`)}else l=new RootNodeGroup(this,null,e),t=l.getRootNode(),Globals$1.u.set(t,l),s=!0;return s||(1!==this.ee?.length||this.ee[0]?l.Mt(this.Ct):t.innerHTML=""),l.ae=new Map,t}St(){return this.kt||(this.kt=this.Ct.length?getObjectHash(this):this.ee[0]),this.kt}Ot(){return this.It||(this.It=this.Ct.length?this.toJSON()[0]:this.ee[0]),this.It}}function h(t=void 0,...e){if(void 0===t&&!e.length&&arguments.length)throw Error("h() cannot be called with undefined.");if(!(t instanceof Node)){if(Array.isArray(t))return new Template(t,e);if("string"==typeof t||t instanceof String){if("object"==typeof e[0]){e.slice(1);let t=[],l=[];return assert(t.length===l.length+1),new Template(t,l)}t.match(/^\s^</)&&(t=t.trim());let l=document.createElement("template");l.innerHTML=t;let s=Util.I(l.content.childNodes);return 1===s.length?s[0]:l.content}if(void 0===t)return(t,...e)=>h(t,...e).ie();if(t instanceof Template)return t.ie();if("object"==typeof t){let e=t;if("Object"!==e.constructor.name)throw Error(`Solarate Web Component class ${e.constructor?.name} must extend HTMLElement.`);if(Globals$1.p.has(e))return((...t)=>{let l=h(...t).ie();Globals$1.p.set(e,l)}).bind(e);{Globals$1.p.set(e,null),e[renderF]();let t=Globals$1.p.get(e);Globals$1.p.delete(e);for(let l in e)t[l]="function"==typeof e[l]?e[l].bind(t):e[l];return t}}throw Error("Unsupported arguments.")}{let l=t,s=e[0];if(!(e[0]instanceof Template)){l.shadowRoot&&(l.innerHTML="");let t=e[0],s=(e,...s)=>(Globals$1.m.add(l),new Template(e,s).ie(l,t));return s}s.ie(l,e[1]),!l.childNodes.length&&this&&l.append(this.ot.xt())}}let renderF="render";function getArg(el,attributeName,defaultValue=void 0,type=ArgType.String,fallback=void 0){let val=defaultValue,attrVal=el.getAttribute(attributeName)||el.getAttribute(Util.A(attributeName)),result;if(null!==attrVal&&(val=attrVal),Array.isArray(type))return type.includes(val)?val:fallback;if("function"==typeof type)return type.constructor?new type(val):type(val);if(type===ArgType.he){let t="string"==typeof val?val.toLowerCase():val;return!["false","0",!1,0,null,void 0,NaN].includes(t)&&(!(!["true",!0].includes(t)&&0===parseFloat(t))||fallback)}switch(type){case ArgType.fe:return result=parseInt(val),isNaN(result)?fallback:result;case ArgType.ue:return result=parseFloat(val),isNaN(result)?fallback:result;case ArgType.String:return[void 0,null,!1].includes(val)?"":val+"";case ArgType.ce:case ArgType.de:if("string"!=typeof val||!val.length)return val;try{return type===ArgType.ce?JSON.parse(val):eval(`(${val})`)}catch(t){return val}default:return val}}function setArgs(t,e,l){for(let s in e)this[s]=getArg(t,s,e[s],l[s]||ArgType.String)}var ArgType={he:"Bool",fe:"Int",ue:"Float",String:"String",JSON:"Json",ce:"Json",de:"Eval"};function defineClass(t,e,l){if(!customElements[getName](t)){(e=e||Util.A(t.name)).includes("-")||(e+="-element");let s=null;l&&(s={pe:l}),customElements[define](e,t,s)}}function createSolarite(t=null){let e=HTMLElement;t&&!t.includes("-")&&(t=t.toLowerCase(),e=Globals$1.i[t],e||(e=document.createElement(t).constructor,Globals$1.i[t]=e));let l=new Proxy(e,{construct:(e,l,s)=>(defineClass(s,null,t),Reflect.construct(e,l,s))});return class extends l{me;be;ye;constructor(t={}){super(),!0===t.ie?this.ie():!1===t.ie&&Globals$1.m.add(this)}re(){!Globals$1.m.has(this)&&this.ie&&this.ie()}ge(){this.re(),Globals$1.connected.has(this)||(Globals$1.connected.add(this),this.be&&this.be()),this.me&&this.me()}ve(){this.ye&&this.ye()}static define(e=null){defineClass(this,e,t)}}}let define="define",getName="getName";const Solarite=new Proxy(createSolarite(),{apply:(t,e,l)=>createSolarite(...l)});export default h;export{ArgType,Globals$1 as Globals,Solarite,Util as SolariteUtil,Template,delve,getArg,h,h as r,setArgs};
4
+ let lastObjectId=1,objectIds=new WeakMap;function getObjectId(t){let e=objectIds.get(t);return e||(e="~\f"+lastObjectId++,objectIds.set(t,e)),e}let isHashing=!0;function toJSON(){return isHashing?getObjectId(this):this}function getObjectHash(t){let e;Node.prototype.toJSON!==toJSON&&(Node.prototype.toJSON=toJSON,(()=>{}).toJSON!==toJSON&&(Function.prototype.toJSON=toJSON)),isHashing=!0;try{e=JSON.stringify(t)}catch(l){e=getObjectHashCircular(t)}return isHashing=!1,e}function getObjectHashCircular(t){const e=new Set;return JSON.stringify(t,((t,l)=>{if("object"==typeof l&&null!==l){if(e.has(l))return getObjectId(l);e.add(l)}return l}))}var Globals;function reset(){Globals={t:new Map,connected:new WeakSet,l:null,div:document.createElement("div"),i:document,o:{},h:{},u:new WeakMap,p:new WeakMap,m:new WeakMap,$:new WeakSet,v:new WeakSet,P:new WeakMap,reset,count:0}}reset();var Globals$1=Globals;function delve(t,e,l=d){let s=l!==d,i=e.length;if(!t&&!s&&i)return;let r=0;for(let o of e){if(void 0===t[o]){if(!s)return;i-1>r&&(t[o]=(e[r+1]+"").match(/^\d+$/)?[]:{})}s&&r===i-1&&(t[o]=l),t=t[o],r++}return t}let d={},Util={T(t,e){let l=t.length;if(l!==e.length)return!1;for(let s=0;l>s;s++)if(t[s]!==e[s])return!1;return!0},N(t,e=null){let l={};for(let s of t.attributes)s.name!==e&&(l[Util.G(s.name)]=s.value);return l},A(t,e){let l=e.getAttribute("data-id")||e.getAttribute("id");if(l){if(t[l]&&!t[l]?.nodeType)throw Error(`${t.constructor.name}.${l} already has a value. Can't set it as a reference to <${e.tagName.toLowerCase()} id="${l}">`);delve(t,l.split(/\./g),e)}},S(t,e){let l,s,i=e.tagName.toLowerCase();if(t.hasAttribute("global")||t.hasAttribute("data-global")){l=i,s="";let r=Globals$1.i||e.ownerDocument||document;r.head.querySelector(`style[data-style="${l}"]`)?t.remove():(r.head.append(t),t.setAttribute("data-style",l))}else{let t=e.getAttribute("data-style");t||(e.constructor.C||(e.constructor.C=1),t=e.constructor.C++,e.setAttribute("data-style",t)),s=`[data-style="${t}"]`}for(let e of t.childNodes)if(3===e.nodeType){let t=e.textContent,l=t.replace(/:host(?=[^a-z0-9_])/gi,`${i}${s}`);t!==l&&(e.textContent=l)}},H:t=>(t=(t=(t=t.replace(/([a-z0-9])([A-Z])/g,"$1-$2")).replace(/([A-Z])([A-Z][a-z])/g,"$1-$2")).replace(/([a-zA-Z])([0-9])/g,"$1-$2")).toLowerCase(),G:t=>t.replace(/-([a-z])/g,(t=>t[1].toUpperCase())),O:t=>"checkbox"===t.type||"radio"===t.type?t.checked:"file"===t.type?[...t.files]:"number"===t.type||"range"===t.type?t.valueAsNumber:"date"===t.type||"time"===t.type||"datetime-local"===t.type?t.valueAsDate:"select-multiple"===t.type?[...t.selectedOptions].map((t=>t.value)):t.hasAttribute("contenteditable")?t.innerHTML:t.value,k:t=>t.startsWith("on")&&t in Globals$1.div,M(t,e){let l=t.tagName+"."+e,s=Globals$1.h[l];if(void 0===s){let i=Object.getPrototypeOf(t);for(;i;){const t=i.constructor.name;if(t.startsWith("HTML")&&t.endsWith("Element"))break;i=Object.getPrototypeOf(i)}Globals$1.h[l]=s=!!i&&!!Object.getOwnPropertyDescriptor(i,e)?.set}return s},j:t=>Array.isArray(t)&&t.length>=2&&("object"==typeof t[0]||void 0===t[0])&&!t.slice(1).find((t=>"string"!=typeof t&&"number"!=typeof t)),U:t=>void 0===t||!1===t||null===t,I:t=>"function"==typeof t?Util.I(t()):t instanceof Date?t.toISOString().replace(/T/," "):Array.isArray(t)||"object"==typeof t?"":t,F(t,e,l){let s=t.get(e);s?s.push(l):(s=[l],t.set(e,s))},J(t){const e=t=>t.nodeType!==Node.ELEMENT_NODE&&(t.nodeType!==Node.TEXT_NODE||""===t.textContent.trim()),l=[...t];for(;l.length>0&&e(l[0]);)l.shift();for(;l.length>0&&e(l[l.length-1]);)l.pop();return l}};class MultiValueMap{data={};add(t,e){let l=this.data,s=l[t];s||(s=new Set,l[t]=s),s.add(e)}R(){for(let t in this.data)return!0;return!1}getAll(t){return this.data[t]||[]}delete(t,e=void 0){let l,s=this.data,i=s[t];if(i)return void 0===e?([l]=i,i.delete(l)):(i.delete(e),l=e),0===i.size&&delete s[t],l}V(t){let e,l=this.data,s=l[t];if(s)return[e]=s,s.delete(e),0===s.size&&delete l[t],e}L(t,e){let l,s=this.data,i=s[t];if(i)return i.delete(e),l=e,0===i.size&&delete s[t],l}W(t){let e=this.data,l=[];for(let s in e)e[s].has(t)&&l.push(s);return l}}const udomdiff=(t,e,l,s)=>{const i=l.length;let r=e.length,o=i,a=0,n=0,h=null;for(;r>a||o>n;)if(r===a){const e=i>o?n?l[n-1].nextSibling:l[o-n]:s;for(;o>n;){let s=l[n++];t.insertBefore(s,e)}}else if(o===n)for(;r>a;){let l=e[a];h&&h.has(l)||t.removeChild(l),a++}else if(e[a]===l[n])a++,n++;else if(e[r-1]===l[o-1])r--,o--;else if(e[a]===l[o-1]&&l[n]===e[r-1]){const s=e[--r].nextSibling;let i=l[n++],h=e[a++];t.insertBefore(i,h.nextSibling);let f=l[--o];t.insertBefore(f,s),e[r]=l[o]}else{if(!h){h=new Map;let t=n;for(;o>t;)h.set(l[t],t++)}if(h.has(e[a])){const s=h.get(e[a]);if(s>n&&o>s){let i=a,f=1;for(;++i<r&&o>i&&h.get(e[i])===s+f;)f++;if(f>s-n){const i=e[a];for(;s>n;){let e=l[n++];t.insertBefore(e,i)}}else{let s=e[a++],i=l[n++];t.replaceChild(i,s)}}else a++}else{let l=e[a++];t.removeChild(l)}}return l};class ExprPath{type;attrName;D;_;Z;B;K;p=[];q;X;Y;tt;et;lt=void 0;constructor(t,e,l=ExprPathType.st,s=null,i=null){this.Z=t,this.B=e,this.type=l,this.attrName=s,this.D=i,l===ExprPathType.it&&(this._=new Set)}apply(t,e=!0){switch(this.type){case 1:this.rt(t[0],e);break;case 2:this.ot(this.B,t[0]);break;case 4:break;case 5:this.nt(this.B,t[0],this.K.ht.root);break;default:this.ft(this.B,t)}}rt(t,e=!0){let l=this;e&&l.ut();let s=[],i=l.p,r=[];l.p=[],l.dt(t,s,r);let o=!1;if(r.length){for(let[t,e]of r){let i=l.ct(s[t],!1),r=i.bt();1===r.length?s[t]=r[0]:(s[t]=r,o=!0),l.p[e]=i}o&&(s=s.flat())}let a=l.bt();if(!Util.T(a,s)){l.q=s,this.K.yt&&this.K.yt.gt(),a.length&&!s.length&&l.$t()||udomdiff(l.B.parentNode,a,s,l.B);for(let t of i)t.Et.parentNode||t.vt();for(let t of s)if(1===t?.nodeType){t.hasAttribute("solarite-placeholder")&&this.K.Pt(t,null,!0);for(let e of t.querySelectorAll("[solarite-placeholder]"))this.K.Pt(e,null,!0)}}}Tt(t){let e=Math.min(t.Nt,t.items.length),l=t.Nt-e;for(let l=0;e>l;l++){let e=this.p[t.index+l],s=(this.et||this.tt)(t.items[l]);this.Gt(s,(s=>{let i=this.ct(s,!0);if(i&&i===e);else{i||(i=this.ct(s,!1)),this.p[t.index+l]=i;let r=e.Et;for(let t of i.bt())r.parentNode.insertBefore(t,r);i!==e&&e.vt()}}))}if(l>0){for(let s=0;l>s;s++)this.p[t.index+e+s].vt();this.p.splice(t.index+e,l)}else{let l=t.items.slice(e),s=this.p[t.index+e]?.Et||this.B;for(let t=0;l.length>t;t++){let e=this.et(l[t]),i=this.ct(e,!0);i||(i=this.ct(e,!1)),this.p.push(i);for(let t of i.bt())s.parentNode.insertBefore(t,s)}}this.q=null}Gt(t,e){if(Array.isArray(t))for(let l of t)this.Gt(l,e);else if("function"==typeof t)Globals$1.l=this,this.tt=t,t=t(),Globals$1.l=null,this.Gt(t,e);else if(t instanceof Template||t?.nodeType)e(t);else{void 0===t||!1===t||null===t?t="":"string"!=typeof t&&(t+="");let l=new Template([t],[]);l.wt=!0,this.Gt(l,e)}}dt(t,e,l){if(t instanceof Template){let s=this.ct(t,!0);if(s){let l=s.bt();e.push(...l);let i=!1;for(let e of l)if(1===e?.nodeType){e.tagName.includes("-")&&(t.xt.find((t=>t?.B===e))?i=!0:this.K.Pt(e,null,!0));for(let l of e.querySelectorAll("*"))l.tagName.includes("-")&&(t.xt.find((t=>t?.B===l))?i=!0:this.K.Pt(l,null,!0))}return i&&s.At(t.xt),this.p.push(s),s}l.push([e.length,this.p.length]),e.push(t),this.p.push(null)}else t?.nodeType?11===t?.nodeType?e.push(...t.childNodes):e.push(t):this.Gt(t,(t=>{this.dt(t,e,l)}))}ot(t,e){Array.isArray(e)&&(e=e.flat().join(" "));let l=this._;if(this._=new Set,e)if("function"==typeof e&&(Globals$1.l=this,this.tt=e,e=e(),Globals$1.l=null),"object"==typeof e)for(let l in e){let s=e[l];void 0!==s&&!1!==s&&null!==s&&(t.setAttribute(l,s),this._.add(l))}else{let l=(e+"").split(/([\w-]+\s*=\s*(?:"[^"]*"|'[^']*'|[^\s]+))/g).map((t=>t.trim())).filter((t=>t.length));for(let e of l){let[l,s]=e.split(/\s*=\s*/);s=(s||"").replace(/^(['"])(.*)\1$/,"$2"),t.setAttribute(l,s),this._.add(l)}}for(let e of l)this._.has(e)||t.removeAttribute(e)}nt(t,e,l){let s,i=this.attrName.slice(2),r=[];if(Array.isArray(e)&&"function"==typeof e[0])s=e[0],r=e.slice(1);else{if("function"!=typeof e)throw Error(`Invalid event binding: <${t.tagName.toLowerCase()} ${this.attrName}=\${${JSON.stringify(e)}}>`);s=e}this.St(t,l,i,i,s,r)}St(t,e,l,s,i,r,o=!1){let a=Globals$1.u.get(t);a||(a={[l]:[,,,]},Globals$1.u.set(t,a));let n=a[l];if(n||(a[l]=n=[,,,]),"function"!=typeof i)throw Error(`Solarite cannot bind to <${t.tagName.toLowerCase()} ${this.attrName}=\${${i}}> because it's not a function.`);if(n[0]!==i){let[l,r,a]=n;l&&t.removeEventListener(s,r,o);let h=i,f=l=>h.call(e,...n[2],l,t);n[0]=h,n[1]=f,t.addEventListener(s,f,o)}a[l][2]=r}ft(t,e){let l=e[0];if(Util.j(l)){let[e,s]=[l[0],l.slice(1)];if(!e)throw Error(`Solarite cannot bind to <${t.tagName.toLowerCase()} ${this.attrName}=\${[${l.map((t=>t?`'${t}'`:t+"")).join(", ")}]}>.`);let i=delve(e,s);if("value"===this.attrName&&"select-multiple"===t.type&&Array.isArray(i)){let e=i.map((t=>t+""));for(let l of t.options)l.selected=e.includes(l.value)}else{const e=Util.U(i)?"":i;"value"===this.attrName&&t.hasAttribute("contenteditable")?e!==t.innerHTML&&(t.innerHTML=e):e!==t[this.attrName]&&(t[this.attrName]=e)}let r=()=>{let l="value"===this.attrName?Util.O(t):t[this.attrName];delve(e,s,l)};this.St(t,s[0],this.attrName,"input",r,[],!0)}else{let s=this.lt;void 0===s&&(s=this.lt=Util.M(t,this.attrName));let i=this.D;if(!i){if(Globals$1.l=this,"function"==typeof l){if(this.Ct)return;this.tt=l,l=l()}else l=Util.I(l);Globals$1.l=null}if(i||void 0!==l&&!1!==l&&null!==l)if(i||!0!==l){let r;if(i){let t=[];for(let l=0;this.D.length>l;l++)if(t.push(this.D[l]),this.D.length-1>l){Globals$1.l=this;let s=Util.I(e[l]);Globals$1.l=null,Util.U(s)||t.push(s)}r=t.join("")}else r=l;(s?t[this.attrName]:t.getAttribute(this.attrName))!==r&&(s?t[this.attrName]=r:t.hasAttribute("contenteditable")&&(t.innerHTML=r),t.setAttribute(this.attrName,r))}else s&&(t[this.attrName]=!0),t.setAttribute(this.attrName,"");else s&&(t[this.attrName]=!1),t.removeAttribute(this.attrName)}}clone(t,e=0){let l,s,i=t,r=e?this.Y.slice(0,-e):this.Y;for(let t=r.length-1;t>0;t--)i=i.childNodes[r[t]];let o=i.childNodes;l=r.length?o[r[0]]:t,this.Z&&(s=o[this.X]);let a=new ExprPath(s,l,this.type,this.attrName,this.D);return a.Ct=this.Ct,a}gt(){let t=this,e=this.B.parentNode;for(;t&&t.B.parentNode===e;)t.q=null,t=t.K?.yt}$t(){let t=this.Z.parentNode;return this.Z===t.firstChild&&this.B===t.lastChild&&(t.innerHTML="",t.append(this.Z,this.B),!0)}bt(){if(this.type===ExprPathType.Ht||this.type===ExprPathType.it)return[this.B];let t;if(t=this.q,t)return t;t=[];let e=this.Z.nextSibling,l=this.B;for(;e&&e!==l;)t.push(e),e=e.nextSibling;return this.q=t,t}Ot(){return this.B.parentNode}ct(t,e=!0){let l,s=this.kt;if(e){if(l=s.V(t.Mt()),l||(s=this.jt,l=s.V(t.Mt())),!l)return null;s.L(t.Ut(),l)}else t.xt.length&&(l=s.V(t.Ut()),l||(s=this.jt,l=s.V(t.Ut())),l&&(s.L(l.It,l),l.At(t.xt),l.It=t.Mt()));return l||(l=new NodeGroup(t,this)),this.Ft.push(l),l}Ft=[];kt=new MultiValueMap;jt=new MultiValueMap;ut(){let t=this.kt.data,e=this.jt.data;for(let l in t){let s=e[l];if(s)for(let e of t[l])s.add(e);else e[l]=t[l]}this.kt=new MultiValueMap;let l=this.kt;for(let t of this.Ft)l.add(t.It,t),l.add(t.Jt,t);this.Ft=[]}}const ExprPathType={st:1,it:2,Ht:3,Comment:4,Event:5};function getNodePath(t){let e=[];for(;;){let l=t.parentNode;if(!l)break;e.push([].indexOf.call(t.parentNode.childNodes,t)),t=l}return e}function resolveNodePath(t,e){for(let l=e.length-1;l>=0;l--)t=t.childNodes[e[l]];return t}class HtmlParser{constructor(){this.Rt={context:HtmlParser.Text,quote:null,buffer:"",Vt:null},this.state={...this.Rt}}reset(){return this.state={...this.Rt},this.state.context}parse(t,e=null){if(null===t)return this.reset();for(let l=0;t.length>l;l++){const s=t[l];switch(this.state.context){case HtmlParser.Text:"<"===s&&t[l+1].match(/[/a-z!]/i)&&(e?.(t,l,this.state.context,HtmlParser.Lt),this.state.context=HtmlParser.Lt,this.state.buffer="");break;case HtmlParser.Lt:if(">"===s)e?.(t,l+1,this.state.context,HtmlParser.Text),this.state.context=HtmlParser.Text,this.state.quote=null,this.state.buffer="";else{if(" "===s&&!this.state.buffer)continue;" "===s||"/"===s||"?"===s?this.state.buffer="":'"'===s||"'"===s||"="===s?(e?.(t,l,this.state.context,HtmlParser.zt),this.state.context=HtmlParser.zt,this.state.quote="="===s?null:s,this.state.buffer=""):this.state.buffer+=s}break;case HtmlParser.zt:this.state.quote||this.state.buffer.length||'"'!==s&&"'"!==s?s===this.state.quote||!this.state.quote&&this.state.buffer.length?(e?.(t,l,this.state.context,HtmlParser.Lt),this.state.context=HtmlParser.Lt,this.state.quote=null,this.state.buffer=""):this.state.quote||">"!==s?" "!==s&&(this.state.buffer+=s):(e?.(t,l+1,this.state.context,HtmlParser.Text),this.state.context=HtmlParser.Text,this.state.quote=null,this.state.buffer=""):this.state.quote=s}}return e?.(t,t.length,this.state.context,null),this.state.context}}HtmlParser.zt="Attribute",HtmlParser.Text="Text",HtmlParser.Lt="Tag";class Shell{fragment;Wt=[];Dt=[];scripts=[];_t=[];Zt=[];constructor(t=null){if(!t)return;if(1===t.length&&!t[0].match(/[<&]/))return void(this.fragment=Globals$1.i.createTextNode(t[0]));let e,l=Shell.Bt(t),s=Globals$1.i.createElement("template");l?s.innerHTML=l:s.content.append(Globals$1.i.createTextNode("")),this.fragment=s.content;let i=[],r=0;const o=Globals$1.i.createTreeWalker(this.fragment,NodeFilter.SHOW_ELEMENT|NodeFilter.SHOW_COMMENT|NodeFilter.SHOW_TEXT);for(;e=o.nextNode();)if(i.map((t=>t.remove())),i=[],1===e.nodeType)for(let t of[...e.attributes]){let l=t.name.match(/^[\ue000-\uf8ff]$/);if(l)this.Wt.push(new ExprPath(null,e,ExprPathType.it)),r++,e.removeAttribute(l[0]);else{let l=t.value.split(/[\ue000-\uf8ff]/g);if(l.length>1){let s=2!==l.length||l[0].length||l[1].length?l:null,i=Util.k(t.name)?ExprPathType.Event:ExprPathType.Ht;this.Wt.push(new ExprPath(null,e,i,t.name,s)),r+=l.length-1,e.setAttribute(t.name,l.join(""))}}}else if(8===e.nodeType&&"!✨!"===e.nodeValue){if(e?.parentNode?.closest&&e?.parentNode?.closest("[contenteditable]"))throw Error('Contenteditable can\'t have expressions inside them. Use <div contenteditable value="${...}"> instead.');let t,l=e.previousSibling;l||(l=Globals$1.i.createComment("ExprPath:"+this.Wt.length),e.parentNode.insertBefore(l,e)),!e.nextSibling||8===e.nextSibling.nodeType&&"!✨!"===e.nextSibling.textContent?(t=e,t.textContent="ExprPathEnd:"+this.Wt.length):(t=e.nextSibling,i.push(e));let s=new ExprPath(l,t,ExprPathType.st);this.Wt.push(s),r++}else{if(3===e.nodeType&&"TEXTAREA"===e.parentNode?.tagName&&e.textContent.includes("\x3c!--!✨!--\x3e"))throw Error('Textarea can\'t have expressions inside them. Use <textarea value="${...}"> instead.');if(e.nodeType===Node.COMMENT_NODE){let t=e.textContent.split(/[\ue000-\uf8ff]/g);for(let l=0;t.length-1>l;l++){let t=new ExprPath(e.previousSibling,e);t.type=ExprPathType.Comment,this.Wt.push(t),r++}}else if(e.nodeType===Node.TEXT_NODE&&["SCRIPT","STYLE"].includes(e.parentNode?.nodeName)){let t=e.textContent.split(commentPlaceholder);if(t.length>1){let l=[];for(let s=0;t.length>s;s++){let i=Globals$1.i.createTextNode(t[s]);e.parentNode.insertBefore(i,e),s>0&&l.push(i)}for(let t,e=0;t=l[e];e++){let e=new ExprPath(t.previousSibling,t,ExprPathType.st);this.Wt.push(e),r++}i.push(e)}}}if(i.map((t=>t.remove())),r!==t.length-1)throw Error("Could not parse expressions in template. Check for duplicate attributes or malformed html: "+t.join("${...}"));for(let t of this.fragment.querySelectorAll("[is]"))t.setAttribute("_is",t.getAttribute("is"));for(let t of this.Wt)t.Z&&(t.X=[].indexOf.call(t.Z.parentNode.childNodes,t.Z)),t.Y=getNodePath(t.B),t.type!==ExprPathType.Ht&&t.type!==ExprPathType.Event||1!==t.B.nodeType||!t.B.tagName.includes("-")&&!t.B.hasAttribute("is")||(t.Ct=!0);this.Kt()}static Bt(t){let e=[];function l(t,l){l===HtmlParser.Lt&&(t=t.replace(/^<\/?[a-z][a-z0-9]*-[a-z0-9-]+/i,(t=>t+"-solarite-placeholder solarite-placeholder"))),e.push(t)}let s=new HtmlParser;for(let i=0;t.length>i;i++){let r=0,o=s.parse(t[i],((t,e,s,i)=>{r!==e&&l(t.slice(r,e),s),r=e}));t.length-1>i&&e.push(o===HtmlParser.Text?commentPlaceholder:String.fromCharCode(attribPlaceholder+i))}return e.join("")}Kt(){this.scripts=[].map.call(this.fragment.querySelectorAll("scripts"),(t=>getNodePath(t))),this._t=[].map.call(this.fragment.querySelectorAll("style"),(t=>getNodePath(t)));let t=this.fragment.querySelectorAll("[id],[data-id]");for(let e of t){let t=e.getAttribute("data-id")||e.getAttribute("id");if(Globals$1.div.hasOwnProperty(t))throw Error(`<${e.tagName.toLowerCase()} id="${t}"> can't override existing HTMLElement id property.`)}this.Dt=[].map.call(t,(t=>getNodePath(t)));for(let t of this.fragment.querySelectorAll("*"))(t.tagName.includes("-")||t.hasAttribute("_is"))&&(this.Wt.find((e=>e.B===t))||this.Zt.push(getNodePath(t)))}static get(t){let e=Globals$1.P.get(t);return e||(e=new Shell(t),Globals$1.P.set(t,e)),e}}const commentPlaceholder="\x3c!--!✨!--\x3e",attribPlaceholder=57344;class NodeGroup{ht;yt;Et;qt;Wt=[];It;Jt;q;_t;Xt=new Set;Zt=[];Yt;constructor(t,e=null){if(this.ht=e?.K?.ht||this,this.yt=e,!(this instanceof RootNodeGroup)){let[e,l]=this.Qt(t);e&&t.xt.length?(this.te(e,l.Wt),this.Zt=this.ee(e,l),this.le(e,l),this.At(t.xt),this.se(this.Zt)):l&&this.le(e,l)}}Qt(t){if(this.Yt=t,this.It=t.Mt(),this.Jt=t.Ut(),t.wt){let e=Globals$1.i.createTextNode(t.ie[0]);return this.Et=this.qt=e,[]}{let e=Shell.get(t.ie),l=e.fragment.cloneNode(!0);if(11===l?.nodeType){let t=l.childNodes;this.Et=t[0],this.qt=t[t.length-1]}else this.Et=this.qt=l;return[l,e]}}At(t,e=null){let l,s=t.length-1,i=Array((e=e||this.Wt).length);for(let r,o=e.length-1;r=e[o];o--){let a=e[o-1],n=e[o+1];if(r.D?.length>2?(i[o]=t.slice(s-(r.D.length-1)+1,s+1),s-=i[o].length):(i[o]=[t[s]],s--),r.B!==this.ht.root&&r.Ct){if(n&&n.Ct&&n.B===r.B||(l=o),!a||!a.Ct||a.B!==r.B){let t={};for(let s=o;l>=s;s++)t[e[s].attrName]=i[s].length>1?i[s].join(""):i[s][0];this.Pt(r.B,t,!0);for(let t=o;l>=t;t++)e[t].apply(i[t])}}else r.apply(i[o])}this.re();for(let t of this.Zt)t.oe&&t.oe(Util.N(t));this.q=null}Pt(t,e=null,l=!0){let s,i,r=t.hasAttribute("solarite-placeholder"),o=t.hasAttribute("_is");if((r||o)&&([t,s,i]=this.ae(t,r,e)),l&&t.oe){if(!s){s=Util.N(t);for(let t in e||{})s[Util.G(t)]=e[t];i=t.childNodes}t.oe(s,i)}return t}ae(t,e=void 0,l=void 0){void 0===e&&(e=!t.hasAttribute("_is"));let s=(e?t.tagName.slice(0,-21):t.getAttribute("is")).toLowerCase(),i=customElements.get(s);if(!i)throw Error(`The custom tag name ${s} is not registered.`);let r=Util.N(t,"solarite-placeholder");for(let t in l||{})r[Util.G(t)]=l[t];let o=[...t.childNodes].filter((t=>t.nodeType!==Node.COMMENT_NODE||!t.nodeValue.startsWith("ExprPath"))),a=new i(r,o);e||a.setAttribute("is",t.getAttribute("is").toLowerCase()),t.replaceWith(a);let n=t.getAttribute("data-id")||t.getAttribute("id");n&&delve(this.getRootNode(),n.split(/\./g),a);for(let e of this.Wt)e.B===t&&(e.B=a),e.Z===t&&(e.Z=a);this.Et===t&&(this.Et=a),this.qt===t&&(this.qt=a),a.ne&&a.ne();for(let e of t.attributes)"_is"!==e.name&&"solarite-placeholder"!==e.name&&a.setAttribute(e.name,e.value);for(let t in l){let e=l[t];"boolean"==typeof e?!1!==e&&null!=e&&a.setAttribute(t,""):["number","bigint","string"].includes(typeof e)&&a.setAttribute(t,e)}return[a,r,o]}bt(){let t=this.q;if(t)return t;t=[];let e=this.Et,l=this.qt?.nextSibling;for(;e&&e!==l;)t.push(e),e=e.nextSibling;return this.q=t,t}Ot(){return this.Et?.parentNode}getRootNode(){return this.ht.root}he(){return this.ht}vt(){let t=Globals$1.i.createDocumentFragment();for(let e of this.bt())t.append(e)}te(t,e,l){let s=e.length;this.Wt.length=s;for(let i=0;s>i;i++){let s=e[i].clone(t,l);s.K=this,this.Wt[i]=s}}re(){if(this._t)for(let[t,e]of this._t)e!==t.textContent&&Util.S(t,this.he().root)}ee(t,e,l=0){let s=[];for(let i of e.Zt){l&&(i=i.slice(0,-l));let e=resolveNodePath(t,i);t!==e&&s.push(e)}return s}se(t){for(let e in t)t[e]=this.Pt(t[e],null,!1)}le(root,shell,pathOffset=0){let rootEl=this.ht.root;if(rootEl){let options=this.ht.options;if(!1!==options?.Dt)for(let t of shell.Dt){pathOffset&&(t=t.slice(0,-pathOffset));let e=resolveNodePath(root,t);Util.A(rootEl,e)}if(!1!==options?._t){shell._t.length&&(this._t=new Map);for(let t of shell._t){pathOffset&&(t=t.slice(0,-pathOffset));let e=resolveNodePath(root,t);1===rootEl.nodeType&&(Util.S(e,rootEl),this._t.set(e,e.textContent))}}if(!1!==options?.scripts)for(let path of shell.scripts){pathOffset&&(path=path.slice(0,-pathOffset));let script=resolveNodePath(root,path);eval(script.textContent)}}}}class RootNodeGroup extends NodeGroup{root;fe=new Map;constructor(t,e,l){super(t),this.options=l;let[s,i]=this.Qt(t),r=0;if(s instanceof Text){if(!e)throw Error("Cannot create a standalone text node");this.Et=e,this.qt=e,s.nodeValue.length&&e.append(s),this.root=e,Globals$1.p.set(this.root,this)}else{if(e){let t;if(this.root=e,e.childNodes.length&&(t=Globals$1.i.createDocumentFragment(),t.append(...e.childNodes)),isReplaceEl(s,e)){e.append(...s.children[0].childNodes);for(let t of s.children[0].attributes)e.hasAttribute(t.name)||"solarite-placeholder"===t.name||e.setAttribute(t.name,t.value);r=1}else 1===s.childNodes.length&&3===s.childNodes[0].nodeType&&""===s.childNodes[0].textContent||e.append(...s.childNodes);if(t){for(let l of e.querySelectorAll("slot[name]")){let e=l.getAttribute("name");if(e){let s=t.querySelectorAll(`[slot='${e}']`);l.append(...s)}}let l=e.querySelector("slot:not([name])");l?l.append(t):e.append(t)}this.Et=e,this.qt=e}else{let t=getSingleEl(s);this.root=t||s,t&&(r=1)}Globals$1.p.set(this.root,this),this.te(this.root,i.Wt,r),this.Zt=this.ee(this.root,i,r),this.le(this.root,i,r),this.At(t.xt),this.se(this.Zt)}}}function getSingleEl(t){let e=[];for(let l of t.childNodes)if(1===l.nodeType||3===l.nodeType&&l.textContent.trim().length){if(e.length)return null;e.push(l)}return e[0]}function isReplaceEl(t,e){return 1===t.children.length&&e.tagName.includes("-")&&t.children[0].tagName.replace("-SOLARITE-PLACEHOLDER","")===e.tagName}class Template{xt=[];ie=[];ue;wt;constructor(t,e){this.ie=t,this.xt=e}toJSON(){return this.ue||(this.ue=[getObjectId(this.ie),this.xt]),this.ue}oe(t=null,e={}){let l,s=!1;if(t){if(l=Globals$1.p.get(t),l||(l=new RootNodeGroup(this,t,e),Globals$1.p.set(t,l),s=!0),0===l.Wt.length&&this.xt.length||l.Wt.length>this.xt.length)throw Error(`Solarite Error: Parent HTMLElement ${l.Yt.ie.join("${...}")} and ${l.Wt.length} \${value} placeholders can't accomodate a Template with ${this.xt.length} values.`)}else l=new RootNodeGroup(this,null,e),t=l.getRootNode(),Globals$1.p.set(t,l),s=!0;return s||(1!==this.ie?.length||this.ie[0]?l.At(this.xt):t.innerHTML=""),l.fe=new Map,t}Mt(){return this.It||(this.It=this.xt.length?getObjectHash(this):this.ie[0]),this.It}Ut(){return this.Jt||(this.Jt=this.xt.length?this.toJSON()[0]:this.ie[0]),this.Jt}static de(t,e,l){const s=selfClosingTags.has(t.toLowerCase());let i=[],r=[],o="<"+t;if(e&&"object"==typeof e)for(let t in e){let l=e[t];"id"!==t&&"data-id"!==t?(o+=` ${t}=`,i.push(o),r.push(l),o=""):o+=` ${t}="${l}"`}if(!s){i.push(i.length>0?'"'===o?'">':">":o+">");for(let t of l)addChild(t,i,r)}return s?i.push(i.length>0?">":o+">"):i[i.length-1]+=`</${t}>`,new Template(i,r)}}const selfClosingTags=new Set(["area","base","br","col","embed","hr","img","input","link","meta","param","source","track","wbr"]),addChild=(t,e,l)=>{if(Array.isArray(t))for(let s of t)addChild(s,e,l);else{let s=!1;if(t instanceof Template)if(t.xt.length>0)s=!0;else{const e=(t.ie[0]||"").match(/^<([a-zA-Z][\w:-]*)/),l=e?e[1].toLowerCase():"";s=selfClosingTags.has(l)}if(s){e[e.length-1]+=t.ie[0];for(let s=0;t.xt.length>s;s++)l.push(t.xt[s]),e.push(t.ie[s+1]??"")}else l.push(t),e.push("")}};function toEl(t){if("string"==typeof t){let e=t;(e.match(/^\s^</)||e.match(/>\s+$/))&&(e=e.trim());let l=Globals$1.i.createElement("template");l.innerHTML=e;let s=Util.J(l.content.childNodes);return 1===s.length?s[0]:l.content}if(t instanceof Template)return t.oe();if(t&&"object"==typeof t){let e=t;if("Object"!==e.constructor.name)throw Error(`Solarate Web Component class ${e.constructor?.name} must extend HTMLElement.`);if(!Globals$1.m.has(e)){Globals$1.m.set(e,null),e[renderF]();let t=Globals$1.m.get(e);Globals$1.m.delete(e);for(let l in e)t[l]="function"==typeof e[l]?e[l].bind(t):e[l];return t}}throw Error("toEl() does not support argument of type: "+(t?typeof t:t))}let renderF="render";function h(t=void 0,...e){if(Array.isArray(arguments[0]))return new Template(arguments[0],e);if("string"==typeof arguments[0]||arguments[0]instanceof String){let t=arguments[0];if(!e.length||"object"!=typeof e[0]&&null!==e[0]){let e=t;return e.match(/^\s^</)&&(e=e.trim()),new Template([e],[])}{let l=t+"",s=e[0]||{},i=e.slice(1);return Template.de(l,s,i)}}if(arguments[0]instanceof HTMLElement||arguments[0]instanceof DocumentFragment){if(!(arguments[1]instanceof Template)){let t=arguments[0],e=arguments[1];t.shadowRoot&&(t.innerHTML="");let l=(l,...s)=>(Globals$1.$.add(t),new Template(l,s).oe(t,e));return l}arguments[1].oe(arguments[0],arguments[2])}else{if(!arguments.length)return(t,...e)=>toEl(h(t,...e));if("object"!=typeof arguments[0]||!Globals$1.m.has(arguments[0]))throw Error("h() does not support argument of type: "+(arguments[0]?typeof arguments[0]:arguments[0]));{let t=arguments[0];if("Object"!==t.constructor.name)throw Error(`Solarate Web Component class ${t.constructor?.name} must extend HTMLElement.`);if(!(arguments[1]instanceof Template))return((...e)=>{let l=h(...e).oe();Globals$1.m.set(t,l)}).bind(t);{let e=arguments[1].oe();Globals$1.m.set(t,e)}}}}function getArg(el,attributeName,defaultValue=void 0,type=ArgType.String,fallback=void 0){let val=defaultValue,attrVal=el.getAttribute(attributeName)||el.getAttribute(Util.H(attributeName)),result;if(null!==attrVal&&(val=attrVal),Array.isArray(type))return type.includes(val)?val:fallback;if("function"==typeof type)return type.constructor?new type(val):type(val);if(type===ArgType.ce){let t="string"==typeof val?val.toLowerCase():val;return!["false","0",!1,0,null,void 0,NaN].includes(t)&&(!(!["true",!0].includes(t)&&0===parseFloat(t))||fallback)}switch(type){case ArgType.pe:return result=parseInt(val),isNaN(result)?fallback:result;case ArgType.be:return result=parseFloat(val),isNaN(result)?fallback:result;case ArgType.String:return[void 0,null,!1].includes(val)?"":val+"";case ArgType.me:case ArgType.ye:if("string"!=typeof val||!val.length)return val;try{return type===ArgType.me?JSON.parse(val):eval(`(${val})`)}catch(t){return val}default:return val}}function setArgs(t,e,l){for(let s in e)this[s]=getArg(t,s,e[s],l[s]||ArgType.String)}var ArgType={ce:"Bool",pe:"Int",be:"Float",String:"String",JSON:"Json",me:"Json",ye:"Eval"};function defineClass(t,e,l){if(!customElements[getName](t)){(e=e||Util.H(t.name)).includes("-")||(e+="-element");let s=null;l&&(s={ge:l}),customElements[define](e,t,s)}}function createSolarite(t=null){let e=HTMLElement;t&&!t.includes("-")&&(t=t.toLowerCase(),e=Globals$1.o[t],e||(e=Globals$1.i.createElement(t).constructor,Globals$1.o[t]=e));let l=new Proxy(e,{construct:(e,l,s)=>(defineClass(s,null,t),Reflect.construct(e,l,s))});return class extends l{$e;Ee;ve;constructor(t={}){super(),!0===t.oe?this.oe():!1===t.oe&&Globals$1.$.add(this)}ne(){!Globals$1.$.has(this)&&this.oe&&this.oe()}Pe(){this.ne(),Globals$1.connected.has(this)||(Globals$1.connected.add(this),this.Ee&&this.Ee()),this.$e&&this.$e()}Te(){this.ve&&this.ve()}static define(e=null){defineClass(this,e,t)}}}let define="define",getName="getName";
5
+ /*
6
+ ┏┓ ┓ •
7
+ ┗┓┏┓┃┏┓┏┓┓╋▗▖
8
+ ┗┛┗┛┗┗┻╹ ╹╹┗
9
+ JavasCript UI library
10
+ @license MIT
11
+ @copyright Vorticode LLC
12
+ https://vorticode.github.io/solarite/ */
13
+ const Solarite=new Proxy(createSolarite(),{apply:(t,e,l)=>createSolarite(...l)});export default h;export{ArgType,Globals$1 as Globals,Solarite,Util as SolariteUtil,Template,getArg,h,h as r,setArgs,toEl};
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "solarite",
3
- "version": "0.3.2",
4
- "description": "Solarite is a small (8KB min+gzip), fast, compilation-free JavaScript library for adding reactivity to native web components, so that updates require minimal re-rendering.",
3
+ "version": "0.4.0",
4
+ "description": "Solarite is a small (9KB min+gzip), fast, compilation-free JavaScript library for adding reactivity to native web components, so that updates require minimal re-rendering.",
5
5
  "main": "dist/Solarite.js",
6
6
  "files": [
7
7
  "readme.md",
package/readme.md CHANGED
@@ -1,10 +1,10 @@
1
1
  # Solarite
2
2
 
3
- Solarite is a small, fast, compilation-free JavaScript library for adding reactivity to native web components, so that updates require minimal re-rendering. It follows modern web standards and is easy to use with vanilla JavaScript.
3
+ Solarite is a smal, fast, compilation-free JavaScript library for performing minimal DOM updates on web components when your data changes. It follows modern web standards and is easy to use with vanilla JavaScript.
4
4
 
5
5
  For documentation and examples, see the **[Official Solarite Page](https://vorticode.github.io/solarite/)**.
6
6
 
7
- Download [Solarite.js](https://vorticode.github.io/solarite/dist/Solarite.js) (109KB, 8.6KB min+gzip)
7
+ Download [Solarite.js](https://vorticode.github.io/solarite/dist/Solarite.js) (117KB, 9KB min+gzip)
8
8
 
9
9
  Or:
10
10
 
package/src/ExprPath.js CHANGED
@@ -127,13 +127,13 @@ export default class ExprPath {
127
127
  case 2: // PathType.Multiple:
128
128
  this.applyMultipleAttribs(this.nodeMarker, exprs[0]);
129
129
  break;
130
- case 5: // PathType.Comment:
130
+ case 4: // PathType.Comment:
131
131
  // Expressions inside Html comments. Deliberately empty because we won't waste time updating them.
132
132
  break;
133
- case 6: // PathType.Event:
133
+ case 5: // PathType.Event:
134
134
  this.applyEventAttrib(this.nodeMarker, exprs[0], this.parentNg.rootNg.root);
135
135
  break;
136
- default: // TODO: Is this still used? Lots of tests fail without it.
136
+ default: // 3 PathType.Attribute
137
137
  // One attribute value may have multiple expressions. Here we apply them all at once.
138
138
  this.applyValueAttrib(this.nodeMarker, exprs);
139
139
  break;
@@ -143,7 +143,7 @@ export default class ExprPath {
143
143
  /**
144
144
  * Insert/replace the nodes created by a single expression.
145
145
  * Called by applyExprs()
146
- * This function is recursive, as the functions it calls also call it.
146
+ * This function is recursive. It calls functions that call applyNodes().
147
147
  * @param expr {Expr}
148
148
  * @param freeNodeGroups {boolean}
149
149
  * @return {Node[]} New Nodes created. */
@@ -178,7 +178,6 @@ export default class ExprPath {
178
178
  if (secondPass.length) {
179
179
  for (let [nodesIndex, ngIndex] of secondPass) {
180
180
  let ng = path.getNodeGroup(newNodes[nodesIndex], false);
181
-
182
181
  let ngNodes = ng.getNodes();
183
182
 
184
183
  /*#IFDEV*/assert(!(newNodes[nodesIndex] instanceof NodeGroup))/*#ENDIF*/
@@ -199,11 +198,8 @@ export default class ExprPath {
199
198
 
200
199
  /*#IFDEV*/assert(!path.nodeGroups.includes(null))/*#ENDIF*/
201
200
 
202
-
203
-
204
201
  let oldNodes = path.getNodes();
205
202
 
206
-
207
203
  // This pre-check makes it a few percent faster?
208
204
  let same = Util.arraySame(oldNodes, newNodes);
209
205
  if (!same) {
@@ -216,7 +212,6 @@ export default class ExprPath {
216
212
  // Fast clear method
217
213
  let isNowEmpty = oldNodes.length && !newNodes.length;
218
214
  if (!isNowEmpty || !path.fastClear())
219
-
220
215
  // Rearrange nodes.
221
216
  udomdiff(path.nodeMarker.parentNode, oldNodes, newNodes, path.nodeMarker)
222
217
 
@@ -229,18 +224,17 @@ export default class ExprPath {
229
224
  ng.removeAndSaveOrphans();
230
225
 
231
226
  // Instantiate components created within ${...} expressions.
232
- // Embedded style tags are handled elsewhere, but where?
227
+ // Also see this.applyExactNodes() which handles calling render() on web components even if they are unchanged.
233
228
  for (let el of newNodes) {
234
- if (el instanceof HTMLElement) {
229
+ if (el?.nodeType === 1) { // HTMLElement
235
230
  if (el.hasAttribute('solarite-placeholder'))
236
- this.parentNg.instantiateComponent(el);
231
+ this.parentNg.handleComponent(el, null, true);
237
232
  for (let child of el.querySelectorAll('[solarite-placeholder]'))
238
- this.parentNg.instantiateComponent(child);
233
+ this.parentNg.handleComponent(child, null, true);
239
234
  }
240
235
  }
241
236
  }
242
237
 
243
-
244
238
  /*#IFDEV*/path.verify();/*#ENDIF*/
245
239
  }
246
240
 
@@ -353,7 +347,7 @@ export default class ExprPath {
353
347
  }
354
348
 
355
349
  // String/Number/Date/Boolean
356
- else if (!(expr instanceof Template) && !(expr instanceof Node)){
350
+ else if (!(expr instanceof Template) && !(expr?.nodeType)){
357
351
  // Convert expression to a string.
358
352
  if (expr === undefined || expr === false || expr === null) // Util.isFalsy() inlined
359
353
  expr = '';
@@ -363,7 +357,9 @@ export default class ExprPath {
363
357
  // Get the same Template for the same string each time.
364
358
  // let template = Globals.stringTemplates[expr];
365
359
  // if (!template) {
360
+
366
361
  let template = new Template([expr], []);
362
+ template.isText = true;
367
363
  // Globals.stringTemplates[expr] = template;
368
364
  //}
369
365
 
@@ -388,12 +384,44 @@ export default class ExprPath {
388
384
 
389
385
  if (expr instanceof Template) {
390
386
  let ng = this.getNodeGroup(expr, true);
387
+
391
388
  if (ng) {
389
+ let newestNodes = ng.getNodes();
390
+ newNodes.push(...newestNodes);
391
+
392
+ // New!
393
+ // Re-apply all expressions if there's a web component, so we can pass them to its constructor.
394
+ // NodeGroup.applyExprs() is used to call applyComponentExprs() on web components that have expression attributes.
395
+ // For those that don't, we call applyComponentExprs() directly here.
396
+ // Also see similar code at the end of this.applyNodes() which handles web components being instantiated the first time.
397
+ let apply = false;
398
+ for (let el of newestNodes) {
399
+ if (el?.nodeType === 1) { // HTMLElement
400
+
401
+ if (el.tagName.includes('-')) {
402
+ if (!expr.exprs.find(expr => expr?.nodeMarker === el))
403
+ this.parentNg.handleComponent(el, null, true);
404
+ else // Commenting out this "else" causes render() to be called too often, but other UI code fails if it's present.
405
+ apply = true;
406
+ }
407
+ for (let child of el.querySelectorAll('*')) {
408
+ if (child.tagName.includes('-')) {
409
+ if (!expr.exprs.find(expr => expr?.nodeMarker === child))
410
+ this.parentNg.handleComponent(child, null, true);
411
+ else
412
+ apply = true;
413
+ }
414
+ }
415
+ }
416
+ }
392
417
 
393
- // TODO: Track ranges of changed nodes and only pass those to udomdiff?
394
- // But will that break the swap benchmark?
395
- newNodes.push(...ng.getNodes());
418
+ // This calls render() on web components that have expressions as attributes.
419
+ if (apply)
420
+ ng.applyExprs(expr.exprs);
421
+
396
422
  this.nodeGroups.push(ng);
423
+
424
+ return ng;
397
425
  }
398
426
 
399
427
  // If expression, mark it to be evaluated later in ExprPath.apply() to find partial match.
@@ -405,10 +433,10 @@ export default class ExprPath {
405
433
  }
406
434
 
407
435
  // Node(s) created by an expression.
408
- else if (expr instanceof Node) {
436
+ else if (expr?.nodeType) {
409
437
 
410
438
  // DocumentFragment created by an expression.
411
- if (expr instanceof DocumentFragment)
439
+ if (expr?.nodeType === 11) // DocumentFragment
412
440
  newNodes.push(...expr.childNodes);
413
441
  else
414
442
  newNodes.push(expr);
@@ -484,8 +512,8 @@ export default class ExprPath {
484
512
  * @param root */
485
513
  applyEventAttrib(node, expr, root) {
486
514
  /*#IFDEV*/
487
- assert(this.type === ExprPathType.Event/* || this.type === PathType.Component*/);
488
- assert(root instanceof HTMLElement);
515
+ assert(this.type === ExprPathType.Event);
516
+ assert(root?.nodeType === 1);
489
517
  /*#ENDIF*/
490
518
 
491
519
  let eventName = this.attrName.slice(2); // remove "on-" prefix.
@@ -565,7 +593,7 @@ export default class ExprPath {
565
593
  }
566
594
 
567
595
  /**
568
- * Handle values, including two-way binding.
596
+ * Set the value of an attribute. This can be for any attribute, not just attributes named "value".
569
597
  * @param node
570
598
  * @param exprs */
571
599
  // TODO: node is always this.nodeMarker?
@@ -595,12 +623,21 @@ export default class ExprPath {
595
623
  }
596
624
  else {
597
625
  // TODO: should we remove isFalsy, since these are always props?
598
- let strValue = Util.isFalsy(value) ? '' : value;
626
+ const strValue = Util.isFalsy(value) ? '' : value;
599
627
 
600
- // If we don't have this condition, when we call render(), the browser will scroll to the currently
601
- // selected item in a <select> and mess up manually scrolling to a different value.
602
- if (strValue !== node[this.attrName])
603
- node[this.attrName] = strValue;
628
+ // Special case for contenteditable
629
+ if (this.attrName === 'value' && node.hasAttribute('contenteditable')) {
630
+ const existingValue = node.innerHTML;
631
+ if (strValue !== existingValue)
632
+ node.innerHTML = strValue;
633
+ }
634
+ else {
635
+
636
+ // If we don't have this condition, when we call render(), the browser will scroll to the currently
637
+ // selected item in a <select> and mess up manually scrolling to a different value.
638
+ if (strValue !== node[this.attrName])
639
+ node[this.attrName] = strValue;
640
+ }
604
641
  }
605
642
 
606
643
  // TODO: We need to remove any old listeners, like in bindEventAttribute.
@@ -620,16 +657,8 @@ export default class ExprPath {
620
657
 
621
658
  // Regular attribute
622
659
  else {
623
- // TODO: Cache this on ExprPath.isProp when Shell creates the props. Have ExprPath.clone() copy .isProp
624
- // Or make it a new PathType.
625
- //if (this.attrName === 'disabled')
626
- // debugger;
627
-
628
- // hasOwnProperty() checks only the object, not the parents
629
- // this.attrName in node checks the node and the parents.
630
- // This version checks the html element it extends from, to see if has a setter set:
631
- // Object.getOwnPropertyDescriptor(Object.getPrototypeOf(node), this.attrName)?.set
632
- //let isProp = Object.getOwnPropertyDescriptor(Object.getPrototypeOf(node), this.attrName)?.set;
660
+ // Cache this on ExprPath.isHtmlProperty when Shell creates the props.
661
+ // Have ExprPath.clone() copy .isHtmlProperty?
633
662
  let isProp = this.isHtmlProperty;
634
663
  if (isProp === undefined)
635
664
  isProp = this.isHtmlProperty = Util.isHtmlProp(node, this.attrName);
@@ -639,7 +668,7 @@ export default class ExprPath {
639
668
  if (!multiple) {
640
669
  Globals.currentExprPath = this; // Used by watch()
641
670
  if (typeof expr === 'function') {
642
- if (this.type === 4) { // Don't evaluate functions before passing them to components
671
+ if (this.isComponent) { // Don't evaluate functions before passing them to components
643
672
  return
644
673
  }
645
674
  this.watchFunction = expr; // The function that gets the expression, used for renderWatched()
@@ -697,6 +726,13 @@ export default class ExprPath {
697
726
  // since we also prohibit expressions that are a child of textarea.
698
727
  if (isProp)
699
728
  node[this.attrName] = joinedValue;
729
+
730
+ // Allow one-way binding to contenteditable value attribute.
731
+ // Contenteditables normally don't have a value attribute and have their content set via innerHTML.
732
+ // Solarite doesn't allow contenteditables to have expressions as their children.
733
+ else if (node.hasAttribute('contenteditable'))
734
+ node.innerHTML = joinedValue;
735
+
700
736
  // TODO: Putting an 'else' here would be more performant
701
737
  node.setAttribute(this.attrName, joinedValue);
702
738
  }
@@ -727,11 +763,9 @@ export default class ExprPath {
727
763
  nodeBefore = childNodes[this.nodeBeforeIndex];
728
764
 
729
765
  let result = new ExprPath(nodeBefore, nodeMarker, this.type, this.attrName, this.attrValue);
766
+ result.isComponent = this.isComponent;
730
767
 
731
768
  //#IFDEV
732
- result.nodeMarker.exprPath = result;
733
- if (result.nodeBefore)
734
- result.nodeBefore.prevExprPath = result;
735
769
  result.verify();
736
770
  //#ENDIF
737
771
 
@@ -740,9 +774,7 @@ export default class ExprPath {
740
774
 
741
775
  /**
742
776
  * Clear the nodeCache of this ExprPath, as well as all parent and child ExprPaths that
743
- * share the same DOM parent node.
744
- *
745
- * TODO: Is recursive clearing ever necessary? */
777
+ * share the same DOM parent node. */
746
778
  clearNodesCache() {
747
779
  let path = this;
748
780
 
@@ -755,23 +787,6 @@ export default class ExprPath {
755
787
  // If stuck in an infinite loop here, the problem is likely due to Template hash colisions.
756
788
  // Which cause one path to be the descendant of itself, creating a cycle.
757
789
  }
758
-
759
- function clearChildNodeCache(path) {
760
-
761
- // Clear cache of child ExprPaths that have the same parentNode
762
- for (let ng of path.nodeGroups) {
763
- if (ng) // Can be null from apply()'s push(null) call.
764
- for (let path2 of ng.paths) {
765
- if (path2.type === ExprPathType.Content && path2.parentNode === parentNode) {
766
- path2.nodesCache = null;
767
- clearChildNodeCache(path2);
768
- }
769
- }
770
- }
771
- }
772
-
773
- // Commented out on Sep 30, 2024 b/c it was making the benchmark never finish when adding 10k rows.
774
- //clearChildNodeCache(this);
775
790
  }
776
791
 
777
792
 
@@ -813,7 +828,7 @@ export default class ExprPath {
813
828
  // result2.push(...ng.getNodes())
814
829
  // return result2;
815
830
 
816
- if (this.type === ExprPathType.AttribValue || this.type === ExprPathType.AttribMultiple || this.type === ExprPathType.ComponentAttribValue) {
831
+ if (this.type === ExprPathType.AttribValue || this.type === ExprPathType.AttribMultiple) {
817
832
  return [this.nodeMarker];
818
833
  }
819
834
 
@@ -873,11 +888,13 @@ export default class ExprPath {
873
888
  result = collection.deleteAny(template.getExactKey());
874
889
  }
875
890
 
876
- if (result) // also delete the matching close key.
891
+ if (result) {// also delete the matching close key.
877
892
  collection.deleteSpecific(template.getCloseKey(), result);
878
- else {
879
- return null;
893
+
894
+ //result.applyExprs(template.exprs);
880
895
  }
896
+ else
897
+ return null;
881
898
  }
882
899
 
883
900
  // Find a close match.
@@ -911,12 +928,6 @@ export default class ExprPath {
911
928
  return result;
912
929
  }
913
930
 
914
- isComponent() {
915
- // Events won't have type===Component.
916
- // TODO: Have a special flag for components instead of it being on the type?
917
- return this.type === ExprPathType.ComponentAttribValue || (this.attrName && this.nodeMarker.tagName && this.nodeMarker.tagName.includes('-'));
918
- }
919
-
920
931
  /**
921
932
  * TODO: Rename this to nodeGroupsInUse, nodeGroupsAvialableAttached and nodeGroupsAvailableDetached?
922
933
  * Nodes that have been used during the current render().
@@ -974,7 +985,7 @@ export default class ExprPath {
974
985
  `parentNode: ${this.nodeBefore.parentNode?.tagName?.toLowerCase()}`,
975
986
  'nodes:',
976
987
  ...setIndent(this.getNodes().map(item => {
977
- if (item instanceof Node)
988
+ if (item?.nodeType)
978
989
  return item.outerHTML || item.textContent
979
990
  else if (item instanceof NodeGroup)
980
991
  return item.debug
@@ -1065,7 +1076,7 @@ function setValue(root, path, node) {
1065
1076
  /** @enum {int} */
1066
1077
  export const ExprPathType = {
1067
1078
  /** Child of a node */
1068
- Content: 1,
1079
+ Content: 1, // TODO: Rename to Nodes
1069
1080
 
1070
1081
  /** One or more whole attributes */
1071
1082
  AttribMultiple: 2,
@@ -1073,14 +1084,11 @@ export const ExprPathType = {
1073
1084
  /** Value of an attribute. */
1074
1085
  AttribValue: 3,
1075
1086
 
1076
- /** Value of an attribute being passed to a component. */
1077
- ComponentAttribValue: 4,
1078
-
1079
1087
  /** Expressions inside Html comments. */
1080
- Comment: 5,
1088
+ Comment: 4,
1081
1089
 
1082
1090
  /** Value of an attribute. */
1083
- Event: 6,
1091
+ Event: 5,
1084
1092
  }
1085
1093
 
1086
1094
 
package/src/Globals.js CHANGED
@@ -6,8 +6,9 @@ function reset() {
6
6
  Globals = {
7
7
 
8
8
  /**
9
- * Used by NodeGroup.applyComponentExprs() */
10
- componentArgsHash: new WeakMap(),
9
+ * Dynamic values that should be passed to a Component's constructor and render() function.
10
+ * @type {Map<HTMLElement, any[]>} */
11
+ componentArgs: new Map(),
11
12
 
12
13
  /**
13
14
  * Store which instances of Solarite have already been added to the DOM.
@@ -22,6 +23,9 @@ function reset() {
22
23
 
23
24
  div: document.createElement("div"),
24
25
 
26
+ /** @type {HTMLDocument} */
27
+ doc: document,
28
+
25
29
  /**
26
30
  * @type {Record<string, Class<Node>>} A map from built-in tag names to the constructors that create them. */
27
31
  elementClasses: {},
@@ -40,20 +44,20 @@ function reset() {
40
44
  nodeGroups: new WeakMap(),
41
45
 
42
46
  /**
43
- * Used by r() path 9. */
47
+ * Used by h() path 9. */
44
48
  objToEl: new WeakMap(),
45
49
 
46
50
  //pendingChildren: [],
47
51
 
48
52
 
49
53
  /**
50
- * Elements that have been rendered to by r() at least once.
54
+ * Elements that have been rendered to by h() at least once.
51
55
  * This is used by the Solarite class to know when to call onFirstConnect()
52
56
  * @type {WeakSet<HTMLElement>} */
53
57
  rendered: new WeakSet(),
54
58
 
55
59
  /**
56
- * Elements that are currently rendering via the r() function.
60
+ * Elements that are currently rendering via the h() function.
57
61
  * @type {WeakSet<HTMLElement>} */
58
62
  rendering: new WeakSet(),
59
63