@plentico/pattr 0.0.16 → 0.0.17

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.
Files changed (3) hide show
  1. package/package.json +1 -1
  2. package/pattr.js +73 -4
  3. package/pattr.min.js +1 -1
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@plentico/pattr",
3
- "version": "0.0.16",
3
+ "version": "0.0.17",
4
4
  "description": "A lightweight reactive framework",
5
5
  "type": "module",
6
6
  "main": "pattr.js",
package/pattr.js CHANGED
@@ -365,13 +365,23 @@ window.Pattr = {
365
365
  return value;
366
366
  },
367
367
  set: (target, key, value) => {
368
+ // If setting a nested object, wrap it with a deep proxy
369
+ if (value !== null && typeof value === 'object') {
370
+ value = createDeepProxy(value, isSynced, syncKey);
371
+ }
372
+
368
373
  target[key] = value;
369
374
 
370
375
  // If this is a synced object, propagate to parent
371
376
  if (isSynced && parentTarget && syncKey) {
372
377
  const parentVal = parentTarget[syncKey];
373
378
  if (parentVal && typeof parentVal === 'object') {
374
- parentVal[key] = value;
379
+ // Also wrap parent's nested object if needed
380
+ if (value !== null && typeof value === 'object' && !parentVal[key]._p_isProxy) {
381
+ parentVal[key] = createDeepProxy(value, isSynced, syncKey);
382
+ } else {
383
+ parentVal[key] = value;
384
+ }
375
385
  }
376
386
  }
377
387
 
@@ -940,7 +950,49 @@ window.Pattr = {
940
950
  }
941
951
 
942
952
  if (value !== undefined) {
943
- eval(`with (el._scope) { ${modelAttr} = value }`);
953
+ // Set on the scope (Proxy) to trigger reactive updates
954
+ // This handles cases like content[key] where content is inherited
955
+ const scope = el._scope;
956
+
957
+ // For bracket notation like content[key], we need to evaluate key first
958
+ if (modelAttr.includes('[')) {
959
+ // Extract the object name and key expression
960
+ const match = modelAttr.match(/^(.+)\[(.+)\]$/);
961
+ if (match) {
962
+ const [, objName, keyExpr] = match;
963
+ const key = eval(`with (scope) { ${keyExpr} }`);
964
+ scope[objName][key] = value; // Set on Proxy to trigger reactivity
965
+ } else {
966
+ eval(`with (scope) { ${modelAttr} = value }`);
967
+ }
968
+ } else if (modelAttr.includes('.')) {
969
+ // Handle dot notation like content.path
970
+ const parts = modelAttr.split('.');
971
+ let obj = scope;
972
+ for (let i = 0; i < parts.length - 1; i++) {
973
+ obj = obj[parts[i]];
974
+ }
975
+ obj[parts[parts.length - 1]] = value;
976
+ } else {
977
+ scope[modelAttr] = value; // Set on Proxy to trigger reactivity
978
+ }
979
+
980
+ // Track the input element to restore focus after re-render
981
+ // The p-for-key is on the parent div in p-for loops
982
+ const pForKey = el.getAttribute('p-for-key') || el.parentElement?.getAttribute('p-for-key');
983
+
984
+ // Re-render DOM to reflect changes
985
+ this.walkDom(this.root, this.data, false);
986
+
987
+ // Restore focus after DOM update using p-for-key
988
+ if (pForKey) {
989
+ requestAnimationFrame(() => {
990
+ const elementToFocus = document.querySelector(`[p-for-key="${pForKey}"] input`);
991
+ if (elementToFocus) {
992
+ elementToFocus.focus();
993
+ }
994
+ });
995
+ }
944
996
  }
945
997
  });
946
998
 
@@ -953,9 +1005,26 @@ window.Pattr = {
953
1005
  } else {
954
1006
  value = e.target.checked ? e.target.value : undefined;
955
1007
  }
956
- if (value !== undefined) {
957
- eval(`with (el._scope) { ${modelAttr} = value }`);
1008
+ if (value !== undefined) {
1009
+ // Set on the scope (Proxy) to trigger reactive updates
1010
+ // This handles cases like content[key] where content is inherited
1011
+ const scope = el._scope;
1012
+
1013
+ // For bracket notation like content[key], we need to evaluate key first
1014
+ if (modelAttr.includes('[')) {
1015
+ // Extract the object name and key expression
1016
+ const match = modelAttr.match(/^(.+)\[(.+)\]$/);
1017
+ if (match) {
1018
+ const [, objName, keyExpr] = match;
1019
+ const key = eval(`with (scope) { ${keyExpr} }`);
1020
+ scope[objName][key] = value; // Set on Proxy to trigger reactivity
1021
+ } else {
1022
+ eval(`with (scope) { ${modelAttr} = value }`);
1023
+ }
1024
+ } else {
1025
+ scope[modelAttr] = value; // Set on Proxy to trigger reactivity
958
1026
  }
1027
+ }
959
1028
  });
960
1029
  }
961
1030
  },
package/pattr.min.js CHANGED
@@ -4,4 +4,4 @@
4
4
  * https://github.com/plentico/pattr
5
5
  * MIT License
6
6
  */
7
- window.Pattr={_templateScopeCounter:0,directives:{"p-text":(e,t,r={})=>{let s=String(t);if(r.trim&&r.trim.length>0){const e=parseInt(r.trim[0])||100;s.length>e&&(s=s.substring(0,e)+"...")}e.innerText=s},"p-html":(e,t,r={})=>{let s=t;if(r.allow&&r.allow.length>0){const e=r.allow,t=document.createElement("div");t.innerHTML=s;const a=t=>{if(t.nodeType===Node.ELEMENT_NODE){const r=t.tagName.toLowerCase();if(!e.includes(r)){const e=document.createDocumentFragment();return Array.from(t.childNodes).forEach(t=>{const r=a(t);r&&e.appendChild(r)}),e}const s=t.cloneNode(!1);return Array.from(t.childNodes).forEach(e=>{const t=a(e);t&&s.appendChild(t)}),s}return t.cloneNode()},o=document.createElement("div");Array.from(t.childNodes).forEach(e=>{const t=a(e);t&&o.appendChild(t)}),s=o.innerHTML}if(r.trim&&r.trim.length>0){const e=parseInt(r.trim[0])||100,t=document.createElement("div");t.innerHTML=s;let a=0,o=!1;const n=t=>{if(o)return null;if(t.nodeType===Node.TEXT_NODE){const r=t.textContent,s=e-a;if(r.length<=s)return a+=r.length,t.cloneNode();{o=!0;const e=r.substring(0,s)+"...";return document.createTextNode(e)}}if(t.nodeType===Node.ELEMENT_NODE){const e=t.cloneNode(!1);for(let r of t.childNodes){const t=n(r);if(t&&e.appendChild(t),o)break}return e}return t.cloneNode()},i=document.createElement("div");for(let e of t.childNodes){const t=n(e);if(t&&i.appendChild(t),o)break}s=i.innerHTML}e.innerHTML=s},"p-show":(e,t)=>{e.style.display=t?"":"none"},"p-style":(e,t)=>{"string"==typeof t?e.style.cssText=t:"object"==typeof t&&null!==t&&Object.assign(e.style,t)},"p-class":(e,t,r={})=>{if(void 0!==r.replace)return void("string"==typeof t?e.className=t:Array.isArray(t)?e.className=t.join(" "):"object"==typeof t&&null!==t&&(e.className=Object.keys(t).filter(e=>t[e]).join(" ")));let s=new Set,a=new Set;if("string"==typeof t&&t?t.split(" ").forEach(e=>{e&&(s.add(e),a.add(e))}):Array.isArray(t)?t.forEach(e=>{e&&(s.add(e),a.add(e))}):"object"==typeof t&&null!==t&&Object.keys(t).forEach(e=>{a.add(e),t[e]&&s.add(e)}),!e._p_staticClasses){const t=e.className?e.className.split(" ").filter(e=>e):[];e._p_staticClasses=t.filter(e=>!a.has(e))}e._p_dynamicClasses||(e._p_dynamicClasses=new Set),e._p_dynamicClasses=s;const o=[...e._p_staticClasses,...e._p_dynamicClasses];e.className=o.join(" ")},"p-model":(e,t)=>{Array.isArray(t)?e.value=t.join(", "):e.value=t},"p-attr":(e,t,r={})=>{const s=Object.keys(r);if(s.length>0){const r=s[0];null==t||!1===t?e.removeAttribute(r):e.setAttribute(r,String(t))}else"object"==typeof t&&null!==t&&Object.keys(t).forEach(r=>{const s=t[r];null==s||!1===s?e.removeAttribute(r):e.setAttribute(r,String(s))})}},parseDirectiveModifiers(e){const t=e.split(":"),r=t[0],s={};for(let e=1;e<t.length;e++){const r=t[e].split("."),a=r[0],o=r.slice(1);s[a]=o}return{directive:r,modifiers:s}},async start(){this.root=document.documentElement;const e=document.getElementById("p-root-data")?.textContent;try{this.rawData=JSON.parse(e||"{}")}catch(e){console.error("Error parsing root data JSON:",e)}this.buildScopeData(this.root,this.rawData),this.data=this.observe(this.rawData),this.walkDom(this.root,this.data,!0),this.refreshAllLoops()},generateDomPathId(e){const t=[];let r=e;for(;r&&"HTML"!==r.tagName;){const e=r.parentElement;if(e){const s=Array.from(e.children).indexOf(r);t.unshift(`${r.tagName}[${s}]`)}r=e}return t.join("/")},buildScopeData(e,t){let r=t;const s=Array.from(e.attributes).find(e=>e.name.startsWith("p-scope"));if(s){const a=e.getAttribute("p-id")||this.generateDomPathId(e);t._p_children||(t._p_children={}),t._p_children[a]||(t._p_children[a]={}),r=t._p_children[a],r._p_scope=e.getAttribute(s.name),r._p_id=a}let a=e.firstElementChild;for(;a;)this.buildScopeData(a,r),a=a.nextElementSibling},observe(e,t,r=[]){const s=e;let a=s;t&&(a=Object.create(t._p_target||t),Object.assign(a,s));const o=new Set(r),n=t?._p_target||t,i=new WeakSet,c=(e,t=!1,r=null)=>{if(null===e||"object"!=typeof e)return e;if(i.has(e))return e;if(e instanceof Date||e instanceof RegExp||e instanceof Map||e instanceof Set)return e;const s=new Proxy(e,{get:(e,s)=>{if("_p_target"===s)return e;if("_p_syncParent"===s)return n;if("_p_syncKey"===s)return r;const a=e[s];return t&&null!==a&&"object"==typeof a?c(a,!0,r):a},set:(e,s,a)=>{if(e[s]=a,t&&n&&r){const e=n[r];e&&"object"==typeof e&&(e[s]=a)}return this.walkDom(this.root,this.data,!1),!0},has:(e,t)=>t in e});return i.add(e),s};if(n)for(const e of o){if(e in a){const t=a[e];null!==t&&"object"==typeof t&&(a[e]=c(t,!0))}if(e in n){const t=n[e];null!==t&&"object"==typeof t&&(n[e]=c(t,!0))}}return new Proxy(a,{get:(e,t)=>"_p_target"===t?e:e[t],set:(e,t,r)=>(o.has(t)&&null!==r&&"object"==typeof r&&(r=c(r,!0,t)),e[t]=r,o.has(t)&&n&&t in n&&(n[t]=r),this.walkDom(this.root,this.data,!1),!0),has:(e,t)=>t in e})},splitPScopeStatements(e){const t=[];let r="",s=0,a=0,o=!1,n=null;for(let i=0;i<e.length;i++){const c=e[i],l=i>0?e[i-1]:null;'"'!==c&&"'"!==c&&"`"!==c||"\\"===l||(o?n===c&&(o=!1,n=null):(o=!0,n=c)),o||("{"===c?s++:"}"===c?s--:"("===c?a++:")"===c&&a--),";"!==c||o||0!==s||0!==a?r+=c:(r.trim()&&t.push(r.trim()),r="")}return r.trim()&&t.push(r.trim()),t},getPScopeOutputVars(e){const t=[];return this.splitPScopeStatements(e).forEach(e=>{const r=e.match(/^\[([^\]]+)\]\s*=\s*(.+)$/);if(r){const e=r[1].split(",").map(e=>e.trim());return void t.push(...e)}const s=e.match(/^\{([^}]+)\}\s*=\s*(.+)$/);if(s){const e=s[1].split(",").map(e=>e.trim());return void t.push(...e)}const a=e.match(/^(\w+)\s*=\s*(.+)$/);a&&t.push(a[1])}),t},initScope(e,t){const r=e.getAttribute("p-id")||this.generateDomPathId(e),s=t._p_target._p_children[r],a=e.getAttribute("p-scope"),o=Array.from(e.attributes).find(e=>e.name.startsWith("p-scope")&&e.name.includes("sync"));let n=[],i=[];if(a&&n.push(a),o){const t=e.getAttribute(o.name);n.push(t),i=this.getPScopeOutputVars(t)}const c=n.join("; "),l=this.observe(s,t,i);i.length>0&&(e._p_syncVars=new Set(i)),this.executePScopeStatements(l,c);const p=Object.getPrototypeOf(l._p_target);e._parentSnapshot={};for(let t in p)t.startsWith("_p_")||(e._parentSnapshot[t]=p[t]);const h=l._p_target;e._localSnapshot={};for(let t of Object.keys(h))t.startsWith("_p_")||(e._localSnapshot[t]=h[t]);return l},refreshScope(e,t){let r=e._scope;if(!r)return t;const s=e.getAttribute("p-scope"),a=Array.from(e.attributes).find(e=>e.name.startsWith("p-scope")&&e.name.includes("sync"));let o=[];s&&o.push(s),a&&o.push(e.getAttribute(a.name));const n=o.join("; ");return n&&r._p_target&&this.updateScopeFromParent(e,r,n),r},executePScopeStatements(scope,pScopeExpr){const statements=this.splitPScopeStatements(pScopeExpr),target=scope._p_target,sequentialScope=new Proxy(target,{get:(e,t)=>Object.prototype.hasOwnProperty.call(e,t)?e[t]:scope[t],has:(e,t)=>Object.prototype.hasOwnProperty.call(e,t)||t in scope});for(const stmt of statements){const arrayDestructMatch=stmt.match(/^\[([^\]]+)\]\s*=\s*(.+)$/);if(arrayDestructMatch){const[,vars,expr]=arrayDestructMatch,varNames=vars.split(",").map(e=>e.trim());try{const value=eval(`with (sequentialScope) { (${expr}) }`);Array.isArray(value)&&varNames.forEach((e,t)=>{target[e]=value[t]})}catch(e){console.error(`Error executing p-scope array destructuring "${stmt}":`,e)}continue}const objDestructMatch=stmt.match(/^\{([^}]+)\}\s*=\s*(.+)$/);if(objDestructMatch){const[,vars,expr]=objDestructMatch,varNames=vars.split(",").map(e=>e.trim());try{const value=eval(`with (sequentialScope) { (${expr}) }`);"object"==typeof value&&null!==value&&varNames.forEach(e=>{target[e]=value[e]})}catch(e){console.error(`Error executing p-scope object destructuring "${stmt}":`,e)}continue}const match=stmt.match(/^(\w+)\s*=\s*(.+)$/);if(match){const[,varName,expr]=match;try{const value=eval(`with (sequentialScope) { (${expr}) }`);target[varName]=value}catch(e){console.error(`Error executing p-scope statement "${stmt}":`,e)}}}},updateScopeFromParent(el,scope,pScopeExpr){const parentProto=Object.getPrototypeOf(scope._p_target),target=scope._p_target,changedParentVars=new Set,changedLocalVars=new Set;el._parentSnapshot||(el._parentSnapshot={});for(let e in parentProto)e.startsWith("_p_")||(el._parentSnapshot[e]!==parentProto[e]&&changedParentVars.add(e),el._parentSnapshot[e]=parentProto[e]);el._localSnapshot||(el._localSnapshot={});for(let e of Object.keys(target))e.startsWith("_p_")||(el._localSnapshot[e]!==target[e]&&changedLocalVars.add(e),el._localSnapshot[e]=target[e]);const allChangedVars=new Set([...changedParentVars,...changedLocalVars]);if(0!==allChangedVars.size)try{const statements=this.splitPScopeStatements(pScopeExpr),outputVars=new Set;statements.forEach(e=>{const t=e.match(/^\[([^\]]+)\]\s*=\s*(.+)$/);if(t){return void t[1].split(",").map(e=>e.trim()).forEach(e=>outputVars.add(e))}const r=e.match(/^\{([^}]+)\}\s*=\s*(.+)$/);if(r){return void r[1].split(",").map(e=>e.trim()).forEach(e=>outputVars.add(e))}const s=e.match(/^(\w+)\s*=\s*(.+)$/);s&&outputVars.add(s[1])});const setInThisPass=new Set,sequentialScope=new Proxy(target,{get:(e,t)=>"_p_target"===t||"_p_children"===t||"_p_scope"===t||setInThisPass.has(t)?e[t]:changedParentVars.has(t)?parentProto[t]:changedLocalVars.has(t)||Object.prototype.hasOwnProperty.call(e,t)?e[t]:parentProto[t],set:(e,t,r)=>(e[t]=r,!0),has:(e,t)=>setInThisPass.has(t)||Object.prototype.hasOwnProperty.call(e,t)||t in parentProto});statements.forEach(stmt=>{let shouldExecute=!1;const parts=stmt.split("=");if(parts.length<=1)return;const rhs=parts.slice(1).join("=");if(changedParentVars.forEach(e=>{rhs.includes(e)&&(shouldExecute=!0)}),changedLocalVars.forEach(e=>{!outputVars.has(e)&&rhs.includes(e)&&(shouldExecute=!0)}),shouldExecute||setInThisPass.forEach(e=>{rhs.includes(e)&&(shouldExecute=!0)}),shouldExecute){const arrayMatch=stmt.match(/^\[([^\]]+)\]\s*=\s*(.+)$/);if(arrayMatch){const[,vars,expr]=arrayMatch,varNames=vars.split(",").map(e=>e.trim()),value=eval(`with (sequentialScope) { (${expr}) }`);return void(Array.isArray(value)&&varNames.forEach((e,t)=>{target[e]=value[t],setInThisPass.add(e)}))}const objMatch=stmt.match(/^\{([^}]+)\}\s*=\s*(.+)$/);if(objMatch){const[,vars,expr]=objMatch,varNames=vars.split(",").map(e=>e.trim()),value=eval(`with (sequentialScope) { (${expr}) }`);return void("object"==typeof value&&null!==value&&varNames.forEach(e=>{target[e]=value[e],setInThisPass.add(e)}))}const match=stmt.match(/^(\w+)\s*=\s*(.+)$/);if(match){const[,varName,expr]=match,value=eval(`with (sequentialScope) { (${expr}) }`);target[varName]=value,setInThisPass.add(varName)}}});for(let e of Object.keys(target))e.startsWith("_p_")||(el._localSnapshot[e]=target[e])}catch(e){console.error("Error re-executing p-scope expression:",e)}},registerEventListeners(el){Array.from(el.attributes).forEach(attr=>{if(attr.name.startsWith("p-on:")){const event=attr.name.replace("p-on:","");el.addEventListener(event,()=>{eval(`with (el._scope) { ${attr.value} }`),this.walkDom(this.root,this.data,!1),this.refreshAllLoops()})}})},registerModelBinding(el){const modelAttr=el.getAttribute("p-model");modelAttr&&(el.addEventListener("input",e=>{let value;const type=e.target.type;if("number"===type||"range"===type)value=""===e.target.value?null:Number(e.target.value);else if("checkbox"===type)value=e.target.checked;else if("radio"===type)value=e.target.checked?e.target.value:void 0;else{const currentValue=eval(`with (el._scope) { ${modelAttr} }`);value=Array.isArray(currentValue)?e.target.value.split(",").map(e=>e.trim()).filter(e=>e):e.target.value}void 0!==value&&eval(`with (el._scope) { ${modelAttr} = value }`)}),"checkbox"!==el.type&&"radio"!==el.type||el.addEventListener("change",e=>{let value;value="checkbox"===el.type?e.target.checked:e.target.checked?e.target.value:void 0,void 0!==value&&eval(`with (el._scope) { ${modelAttr} = value }`)}))},evaluateDirectives(el,scope){Array.from(el.attributes).forEach(attr=>{const parsed=this.parseDirectiveModifiers(attr.name);if(Object.keys(this.directives).includes(parsed.directive)){const evalScope=el._scope||scope,value=eval(`with (evalScope) { (${attr.value}) }`);this.directives[parsed.directive](el,value,parsed.modifiers)}})},setForTemplateRecursive(e,t){e._forTemplate=t,Array.from(e.children).forEach(e=>{this.setForTemplateRecursive(e,t)})},refreshAllLoops(e=this.root,t=new Set){if("TEMPLATE"===e.tagName&&e.hasAttribute("p-for")){if(t.has(e))return;return t.add(e),void this.handleFor(e,e._scope||this.data,!1)}let r=e.firstElementChild;for(;r;){const e=r.nextElementSibling;this.refreshAllLoops(r,t),r=e}},handleFor(e,t,r){const s=e.getAttribute("p-for"),a=s.match(/^(?:const|let)?\s*(.+?)\s+(of|in)\s+(.+)$/);if(!a)return void console.error(`Invalid p-for expression: ${s}`);const[,o,n,i]=a;r?this.hydrateLoop(e,t,o,i):this.refreshLoop(e,t,o,i)},getTemplateScopePrefix(e){let t="",r=e.nextElementSibling;if(r&&r.hasAttribute&&r.hasAttribute("p-for-key")){const s=r.getAttribute("p-for-key"),a=s.lastIndexOf(":");if(a>0){const r=s.substring(0,a+1),o=r.lastIndexOf("-");if(o>=0){t=r.substring(0,o+1);const s=r.substring(o+1,r.length-1);e._forScopeId=s}else e._forScopeId=r.substring(0,r.length-1);return r}}if(e._forTemplate){const r=e._forTemplate._forData;if(r&&r.scopePrefix){let r=e.previousElementSibling;for(;r;){if(r.hasAttribute&&r.hasAttribute("p-for-key")){t=r.getAttribute("p-for-key")+"-";break}r=r.previousElementSibling}}}if(!t){let r=e.previousElementSibling;for(;r;){if(r.hasAttribute&&r.hasAttribute("p-for-key")&&r._forTemplate===e._forTemplate){t=r.getAttribute("p-for-key")+"-";break}r=r.previousElementSibling}}if(!t){let r=e.parentElement;for(;r;){if(r.hasAttribute&&r.hasAttribute("p-for-key")){t=r.getAttribute("p-for-key")+"-";break}if(r._forTemplate){const e=r._forTemplate._forData;if(e){const s=e.renderedElements.indexOf(r);if(s>=0){t=(e.scopePrefix||"")+s+"-";break}}}r=r.parentElement}}return e._forScopeId||(e._forScopeId="s"+this._templateScopeCounter++),t+e._forScopeId+":"},hydrateLoop(template,parentScope,varPattern,iterableExpr){template._scope=parentScope;try{const iterable=eval(`with (parentScope) { (${iterableExpr}) }`),scopePrefix=this.getTemplateScopePrefix(template);template._forData={varPattern:varPattern,iterableExpr:iterableExpr,renderedElements:[],scopePrefix:scopePrefix};const existingElementsByKey={};let sibling=template.nextElementSibling;for(;sibling&&sibling.hasAttribute("p-for-key");){const e=sibling.getAttribute("p-for-key"),t=e.startsWith(scopePrefix)||!e.includes(":")&&!e.includes("-");if(t){let t;t=e.startsWith(scopePrefix)?e.substring(scopePrefix.length):e,existingElementsByKey[t]||(existingElementsByKey[t]=[]),existingElementsByKey[t].push(sibling)}sibling=sibling.nextElementSibling}let index=0,lastInserted=template;for(const e of iterable){const t=this.createLoopScope(parentScope,varPattern,e);if(existingElementsByKey[String(index)])existingElementsByKey[String(index)].forEach(e=>{e._scope=t,this.setForTemplateRecursive(e,template),"TEMPLATE"!==e.tagName&&e.setAttribute("p-for-key",scopePrefix+index),this.walkDom(e,t,!0),template._forData.renderedElements.push(e),lastInserted=e});else{const e=template.content.cloneNode(!0),r=Array.from(e.children);r.forEach(e=>{e._scope=t,this.setForTemplateRecursive(e,template),"TEMPLATE"!==e.tagName&&e.setAttribute("p-for-key",scopePrefix+index),this.walkDom(e,t,!0)});const s=document.createDocumentFragment();r.forEach(e=>s.appendChild(e)),lastInserted.parentNode.insertBefore(s,lastInserted.nextSibling),template._forData.renderedElements.push(...r),lastInserted=r[r.length-1]||lastInserted}index++}Object.keys(existingElementsByKey).forEach(e=>{parseInt(e)>=index&&existingElementsByKey[e].forEach(e=>e.remove())})}catch(e){console.error(`Error in p-for hydration: ${iterableExpr}`,e)}},removeLoopElements(e){e.forEach(e=>{if(e._forData&&e._forData.renderedElements&&(this.removeLoopElements(e._forData.renderedElements),e._forData.renderedElements=[]),e.querySelectorAll){e.querySelectorAll("template[p-for]").forEach(e=>{e._forData&&e._forData.renderedElements&&(this.removeLoopElements(e._forData.renderedElements),e._forData.renderedElements=[])})}e.remove()})},refreshLoop(template,parentScope,varPattern,iterableExpr){const forData=template._forData;if(forData)try{const iterable=eval(`with (parentScope._p_target || parentScope) { (${iterableExpr}) }`),scopePrefix=forData.scopePrefix||this.getTemplateScopePrefix(template);this.removeLoopElements(forData.renderedElements),forData.renderedElements=[];let lastInsertedElement=template,index=0;for(const e of iterable){const t=template.content.cloneNode(!0),r=this.createLoopScope(parentScope,forData.varPattern,e),s=Array.from(t.children);s.forEach(e=>{e._scope=r,this.setForTemplateRecursive(e,template),"TEMPLATE"!==e.tagName&&e.setAttribute("p-for-key",scopePrefix+index)});const a=document.createDocumentFragment();s.forEach(e=>a.appendChild(e)),lastInsertedElement.parentNode.insertBefore(a,lastInsertedElement.nextSibling),forData.renderedElements.push(...s),s.forEach(e=>{this.walkDom(e,r,!0)});const o=s[s.length-1];o&&(lastInsertedElement=this.findLastRenderedSibling(o)),index++}}catch(e){console.error(`Error in p-for refresh: ${iterableExpr}`,e)}},findLastRenderedSibling(e){if("TEMPLATE"===e.tagName&&e._forData&&e._forData.renderedElements.length>0){const t=e._forData.renderedElements[e._forData.renderedElements.length-1];return this.findLastRenderedSibling(t)}return e},createLoopScope(e,t,r){const s={};if((t=t.trim()).startsWith("[")){const e=t.slice(1,-1).split(",").map(e=>e.trim());Array.isArray(r)?e.forEach((e,t)=>s[e]=r[t]):s[e[0]]=r}else if(t.startsWith("{")){t.slice(1,-1).split(",").map(e=>e.trim()).forEach(e=>{const[t,a]=e.split(":").map(e=>e.trim());s[a||t]=r[t]})}else s[t]=r;if(!e)return console.error("parentScope is undefined in createLoopScope"),new Proxy({},{get:()=>{},set:()=>!1});const a=e._p_target||e;if(!a||"object"!=typeof a)return console.error("Invalid parentTarget:",a),new Proxy(s,{get:(e,t)=>e[t],set:(e,t,r)=>(e[t]=r,!0)});const o=Object.create(a);Object.assign(o,s);const n=new Proxy(o,{get:(e,t)=>e[t],set:(e,t,r)=>(t in s?e[t]=r:a[t]=r,!0)});return n._p_target=o,n},walkDom(el,parentScope,isHydrating=!1){if("TEMPLATE"===el.tagName&&el.hasAttribute("p-for")){if(!isHydrating&&el._forTemplate)return;return void this.handleFor(el,parentScope,isHydrating)}const preScopeShowAttr=Array.from(el.attributes).find(e=>{const t=this.parseDirectiveModifiers(e.name);return"p-show"===t.directive&&t.modifiers["pre-scope"]});if(preScopeShowAttr&&parentScope){const value=eval(`with (parentScope) { (${preScopeShowAttr.value}) }`);this.directives["p-show"](el,value)}let currentScope=parentScope;const hasPScope=Array.from(el.attributes).some(e=>e.name.startsWith("p-scope"));hasPScope&&(currentScope=isHydrating?this.initScope(el,parentScope):this.refreshScope(el,parentScope)),isHydrating&&(el._scope=currentScope,this.registerEventListeners(el),this.registerModelBinding(el)),currentScope&&Array.from(el.attributes).forEach(attr=>{const parsed=this.parseDirectiveModifiers(attr.name);if(("p-show"!==parsed.directive||!parsed.modifiers["pre-scope"])&&Object.keys(this.directives).includes(parsed.directive)){const evalScope=el._scope||currentScope,value=eval(`with (evalScope) { (${attr.value}) }`);this.directives[parsed.directive](el,value,parsed.modifiers)}});const children=Array.from(el.children);for(const e of children)this.walkDom(e,currentScope,isHydrating)}},window.Pattr.start();
7
+ window.Pattr={_templateScopeCounter:0,directives:{"p-text":(e,t,r={})=>{let s=String(t);if(r.trim&&r.trim.length>0){const e=parseInt(r.trim[0])||100;s.length>e&&(s=s.substring(0,e)+"...")}e.innerText=s},"p-html":(e,t,r={})=>{let s=t;if(r.allow&&r.allow.length>0){const e=r.allow,t=document.createElement("div");t.innerHTML=s;const a=t=>{if(t.nodeType===Node.ELEMENT_NODE){const r=t.tagName.toLowerCase();if(!e.includes(r)){const e=document.createDocumentFragment();return Array.from(t.childNodes).forEach(t=>{const r=a(t);r&&e.appendChild(r)}),e}const s=t.cloneNode(!1);return Array.from(t.childNodes).forEach(e=>{const t=a(e);t&&s.appendChild(t)}),s}return t.cloneNode()},o=document.createElement("div");Array.from(t.childNodes).forEach(e=>{const t=a(e);t&&o.appendChild(t)}),s=o.innerHTML}if(r.trim&&r.trim.length>0){const e=parseInt(r.trim[0])||100,t=document.createElement("div");t.innerHTML=s;let a=0,o=!1;const n=t=>{if(o)return null;if(t.nodeType===Node.TEXT_NODE){const r=t.textContent,s=e-a;if(r.length<=s)return a+=r.length,t.cloneNode();{o=!0;const e=r.substring(0,s)+"...";return document.createTextNode(e)}}if(t.nodeType===Node.ELEMENT_NODE){const e=t.cloneNode(!1);for(let r of t.childNodes){const t=n(r);if(t&&e.appendChild(t),o)break}return e}return t.cloneNode()},i=document.createElement("div");for(let e of t.childNodes){const t=n(e);if(t&&i.appendChild(t),o)break}s=i.innerHTML}e.innerHTML=s},"p-show":(e,t)=>{e.style.display=t?"":"none"},"p-style":(e,t)=>{"string"==typeof t?e.style.cssText=t:"object"==typeof t&&null!==t&&Object.assign(e.style,t)},"p-class":(e,t,r={})=>{if(void 0!==r.replace)return void("string"==typeof t?e.className=t:Array.isArray(t)?e.className=t.join(" "):"object"==typeof t&&null!==t&&(e.className=Object.keys(t).filter(e=>t[e]).join(" ")));let s=new Set,a=new Set;if("string"==typeof t&&t?t.split(" ").forEach(e=>{e&&(s.add(e),a.add(e))}):Array.isArray(t)?t.forEach(e=>{e&&(s.add(e),a.add(e))}):"object"==typeof t&&null!==t&&Object.keys(t).forEach(e=>{a.add(e),t[e]&&s.add(e)}),!e._p_staticClasses){const t=e.className?e.className.split(" ").filter(e=>e):[];e._p_staticClasses=t.filter(e=>!a.has(e))}e._p_dynamicClasses||(e._p_dynamicClasses=new Set),e._p_dynamicClasses=s;const o=[...e._p_staticClasses,...e._p_dynamicClasses];e.className=o.join(" ")},"p-model":(e,t)=>{Array.isArray(t)?e.value=t.join(", "):e.value=t},"p-attr":(e,t,r={})=>{const s=Object.keys(r);if(s.length>0){const r=s[0];null==t||!1===t?e.removeAttribute(r):e.setAttribute(r,String(t))}else"object"==typeof t&&null!==t&&Object.keys(t).forEach(r=>{const s=t[r];null==s||!1===s?e.removeAttribute(r):e.setAttribute(r,String(s))})}},parseDirectiveModifiers(e){const t=e.split(":"),r=t[0],s={};for(let e=1;e<t.length;e++){const r=t[e].split("."),a=r[0],o=r.slice(1);s[a]=o}return{directive:r,modifiers:s}},async start(){this.root=document.documentElement;const e=document.getElementById("p-root-data")?.textContent;try{this.rawData=JSON.parse(e||"{}")}catch(e){console.error("Error parsing root data JSON:",e)}this.buildScopeData(this.root,this.rawData),this.data=this.observe(this.rawData),this.walkDom(this.root,this.data,!0),this.refreshAllLoops()},generateDomPathId(e){const t=[];let r=e;for(;r&&"HTML"!==r.tagName;){const e=r.parentElement;if(e){const s=Array.from(e.children).indexOf(r);t.unshift(`${r.tagName}[${s}]`)}r=e}return t.join("/")},buildScopeData(e,t){let r=t;const s=Array.from(e.attributes).find(e=>e.name.startsWith("p-scope"));if(s){const a=e.getAttribute("p-id")||this.generateDomPathId(e);t._p_children||(t._p_children={}),t._p_children[a]||(t._p_children[a]={}),r=t._p_children[a],r._p_scope=e.getAttribute(s.name),r._p_id=a}let a=e.firstElementChild;for(;a;)this.buildScopeData(a,r),a=a.nextElementSibling},observe(e,t,r=[]){const s=e;let a=s;t&&(a=Object.create(t._p_target||t),Object.assign(a,s));const o=new Set(r),n=t?._p_target||t,i=new WeakSet,c=(e,t=!1,r=null)=>{if(null===e||"object"!=typeof e)return e;if(i.has(e))return e;if(e instanceof Date||e instanceof RegExp||e instanceof Map||e instanceof Set)return e;const s=new Proxy(e,{get:(e,s)=>{if("_p_target"===s)return e;if("_p_syncParent"===s)return n;if("_p_syncKey"===s)return r;const a=e[s];return t&&null!==a&&"object"==typeof a?c(a,!0,r):a},set:(e,s,a)=>{if(null!==a&&"object"==typeof a&&(a=c(a,t,r)),e[s]=a,t&&n&&r){const e=n[r];e&&"object"==typeof e&&(null===a||"object"!=typeof a||e[s]._p_isProxy?e[s]=a:e[s]=c(a,t,r))}return this.walkDom(this.root,this.data,!1),!0},has:(e,t)=>t in e});return i.add(e),s};if(n)for(const e of o){if(e in a){const t=a[e];null!==t&&"object"==typeof t&&(a[e]=c(t,!0))}if(e in n){const t=n[e];null!==t&&"object"==typeof t&&(n[e]=c(t,!0))}}return new Proxy(a,{get:(e,t)=>"_p_target"===t?e:e[t],set:(e,t,r)=>(o.has(t)&&null!==r&&"object"==typeof r&&(r=c(r,!0,t)),e[t]=r,o.has(t)&&n&&t in n&&(n[t]=r),this.walkDom(this.root,this.data,!1),!0),has:(e,t)=>t in e})},splitPScopeStatements(e){const t=[];let r="",s=0,a=0,o=!1,n=null;for(let i=0;i<e.length;i++){const c=e[i],l=i>0?e[i-1]:null;'"'!==c&&"'"!==c&&"`"!==c||"\\"===l||(o?n===c&&(o=!1,n=null):(o=!0,n=c)),o||("{"===c?s++:"}"===c?s--:"("===c?a++:")"===c&&a--),";"!==c||o||0!==s||0!==a?r+=c:(r.trim()&&t.push(r.trim()),r="")}return r.trim()&&t.push(r.trim()),t},getPScopeOutputVars(e){const t=[];return this.splitPScopeStatements(e).forEach(e=>{const r=e.match(/^\[([^\]]+)\]\s*=\s*(.+)$/);if(r){const e=r[1].split(",").map(e=>e.trim());return void t.push(...e)}const s=e.match(/^\{([^}]+)\}\s*=\s*(.+)$/);if(s){const e=s[1].split(",").map(e=>e.trim());return void t.push(...e)}const a=e.match(/^(\w+)\s*=\s*(.+)$/);a&&t.push(a[1])}),t},initScope(e,t){const r=e.getAttribute("p-id")||this.generateDomPathId(e),s=t._p_target._p_children[r],a=e.getAttribute("p-scope"),o=Array.from(e.attributes).find(e=>e.name.startsWith("p-scope")&&e.name.includes("sync"));let n=[],i=[];if(a&&n.push(a),o){const t=e.getAttribute(o.name);n.push(t),i=this.getPScopeOutputVars(t)}const c=n.join("; "),l=this.observe(s,t,i);i.length>0&&(e._p_syncVars=new Set(i)),this.executePScopeStatements(l,c);const p=Object.getPrototypeOf(l._p_target);e._parentSnapshot={};for(let t in p)t.startsWith("_p_")||(e._parentSnapshot[t]=p[t]);const h=l._p_target;e._localSnapshot={};for(let t of Object.keys(h))t.startsWith("_p_")||(e._localSnapshot[t]=h[t]);return l},refreshScope(e,t){let r=e._scope;if(!r)return t;const s=e.getAttribute("p-scope"),a=Array.from(e.attributes).find(e=>e.name.startsWith("p-scope")&&e.name.includes("sync"));let o=[];s&&o.push(s),a&&o.push(e.getAttribute(a.name));const n=o.join("; ");return n&&r._p_target&&this.updateScopeFromParent(e,r,n),r},executePScopeStatements(scope,pScopeExpr){const statements=this.splitPScopeStatements(pScopeExpr),target=scope._p_target,sequentialScope=new Proxy(target,{get:(e,t)=>Object.prototype.hasOwnProperty.call(e,t)?e[t]:scope[t],has:(e,t)=>Object.prototype.hasOwnProperty.call(e,t)||t in scope});for(const stmt of statements){const arrayDestructMatch=stmt.match(/^\[([^\]]+)\]\s*=\s*(.+)$/);if(arrayDestructMatch){const[,vars,expr]=arrayDestructMatch,varNames=vars.split(",").map(e=>e.trim());try{const value=eval(`with (sequentialScope) { (${expr}) }`);Array.isArray(value)&&varNames.forEach((e,t)=>{target[e]=value[t]})}catch(e){console.error(`Error executing p-scope array destructuring "${stmt}":`,e)}continue}const objDestructMatch=stmt.match(/^\{([^}]+)\}\s*=\s*(.+)$/);if(objDestructMatch){const[,vars,expr]=objDestructMatch,varNames=vars.split(",").map(e=>e.trim());try{const value=eval(`with (sequentialScope) { (${expr}) }`);"object"==typeof value&&null!==value&&varNames.forEach(e=>{target[e]=value[e]})}catch(e){console.error(`Error executing p-scope object destructuring "${stmt}":`,e)}continue}const match=stmt.match(/^(\w+)\s*=\s*(.+)$/);if(match){const[,varName,expr]=match;try{const value=eval(`with (sequentialScope) { (${expr}) }`);target[varName]=value}catch(e){console.error(`Error executing p-scope statement "${stmt}":`,e)}}}},updateScopeFromParent(el,scope,pScopeExpr){const parentProto=Object.getPrototypeOf(scope._p_target),target=scope._p_target,changedParentVars=new Set,changedLocalVars=new Set;el._parentSnapshot||(el._parentSnapshot={});for(let e in parentProto)e.startsWith("_p_")||(el._parentSnapshot[e]!==parentProto[e]&&changedParentVars.add(e),el._parentSnapshot[e]=parentProto[e]);el._localSnapshot||(el._localSnapshot={});for(let e of Object.keys(target))e.startsWith("_p_")||(el._localSnapshot[e]!==target[e]&&changedLocalVars.add(e),el._localSnapshot[e]=target[e]);const allChangedVars=new Set([...changedParentVars,...changedLocalVars]);if(0!==allChangedVars.size)try{const statements=this.splitPScopeStatements(pScopeExpr),outputVars=new Set;statements.forEach(e=>{const t=e.match(/^\[([^\]]+)\]\s*=\s*(.+)$/);if(t){return void t[1].split(",").map(e=>e.trim()).forEach(e=>outputVars.add(e))}const r=e.match(/^\{([^}]+)\}\s*=\s*(.+)$/);if(r){return void r[1].split(",").map(e=>e.trim()).forEach(e=>outputVars.add(e))}const s=e.match(/^(\w+)\s*=\s*(.+)$/);s&&outputVars.add(s[1])});const setInThisPass=new Set,sequentialScope=new Proxy(target,{get:(e,t)=>"_p_target"===t||"_p_children"===t||"_p_scope"===t||setInThisPass.has(t)?e[t]:changedParentVars.has(t)?parentProto[t]:changedLocalVars.has(t)||Object.prototype.hasOwnProperty.call(e,t)?e[t]:parentProto[t],set:(e,t,r)=>(e[t]=r,!0),has:(e,t)=>setInThisPass.has(t)||Object.prototype.hasOwnProperty.call(e,t)||t in parentProto});statements.forEach(stmt=>{let shouldExecute=!1;const parts=stmt.split("=");if(parts.length<=1)return;const rhs=parts.slice(1).join("=");if(changedParentVars.forEach(e=>{rhs.includes(e)&&(shouldExecute=!0)}),changedLocalVars.forEach(e=>{!outputVars.has(e)&&rhs.includes(e)&&(shouldExecute=!0)}),shouldExecute||setInThisPass.forEach(e=>{rhs.includes(e)&&(shouldExecute=!0)}),shouldExecute){const arrayMatch=stmt.match(/^\[([^\]]+)\]\s*=\s*(.+)$/);if(arrayMatch){const[,vars,expr]=arrayMatch,varNames=vars.split(",").map(e=>e.trim()),value=eval(`with (sequentialScope) { (${expr}) }`);return void(Array.isArray(value)&&varNames.forEach((e,t)=>{target[e]=value[t],setInThisPass.add(e)}))}const objMatch=stmt.match(/^\{([^}]+)\}\s*=\s*(.+)$/);if(objMatch){const[,vars,expr]=objMatch,varNames=vars.split(",").map(e=>e.trim()),value=eval(`with (sequentialScope) { (${expr}) }`);return void("object"==typeof value&&null!==value&&varNames.forEach(e=>{target[e]=value[e],setInThisPass.add(e)}))}const match=stmt.match(/^(\w+)\s*=\s*(.+)$/);if(match){const[,varName,expr]=match,value=eval(`with (sequentialScope) { (${expr}) }`);target[varName]=value,setInThisPass.add(varName)}}});for(let e of Object.keys(target))e.startsWith("_p_")||(el._localSnapshot[e]=target[e])}catch(e){console.error("Error re-executing p-scope expression:",e)}},registerEventListeners(el){Array.from(el.attributes).forEach(attr=>{if(attr.name.startsWith("p-on:")){const event=attr.name.replace("p-on:","");el.addEventListener(event,()=>{eval(`with (el._scope) { ${attr.value} }`),this.walkDom(this.root,this.data,!1),this.refreshAllLoops()})}})},registerModelBinding(el){const modelAttr=el.getAttribute("p-model");modelAttr&&(el.addEventListener("input",e=>{let value;const type=e.target.type;if("number"===type||"range"===type)value=""===e.target.value?null:Number(e.target.value);else if("checkbox"===type)value=e.target.checked;else if("radio"===type)value=e.target.checked?e.target.value:void 0;else{const currentValue=eval(`with (el._scope) { ${modelAttr} }`);value=Array.isArray(currentValue)?e.target.value.split(",").map(e=>e.trim()).filter(e=>e):e.target.value}if(void 0!==value){const scope=el._scope;if(modelAttr.includes("[")){const match=modelAttr.match(/^(.+)\[(.+)\]$/);if(match){const[,objName,keyExpr]=match,key=eval(`with (scope) { ${keyExpr} }`);scope[objName][key]=value}else eval(`with (scope) { ${modelAttr} = value }`)}else if(modelAttr.includes(".")){const e=modelAttr.split(".");let t=scope;for(let r=0;r<e.length-1;r++)t=t[e[r]];t[e[e.length-1]]=value}else scope[modelAttr]=value;const pForKey=el.getAttribute("p-for-key")||el.parentElement?.getAttribute("p-for-key");this.walkDom(this.root,this.data,!1),pForKey&&requestAnimationFrame(()=>{const e=document.querySelector(`[p-for-key="${pForKey}"] input`);e&&e.focus()})}}),"checkbox"!==el.type&&"radio"!==el.type||el.addEventListener("change",e=>{let value;if(value="checkbox"===el.type?e.target.checked:e.target.checked?e.target.value:void 0,void 0!==value){const scope=el._scope;if(modelAttr.includes("[")){const match=modelAttr.match(/^(.+)\[(.+)\]$/);if(match){const[,objName,keyExpr]=match,key=eval(`with (scope) { ${keyExpr} }`);scope[objName][key]=value}else eval(`with (scope) { ${modelAttr} = value }`)}else scope[modelAttr]=value}}))},evaluateDirectives(el,scope){Array.from(el.attributes).forEach(attr=>{const parsed=this.parseDirectiveModifiers(attr.name);if(Object.keys(this.directives).includes(parsed.directive)){const evalScope=el._scope||scope,value=eval(`with (evalScope) { (${attr.value}) }`);this.directives[parsed.directive](el,value,parsed.modifiers)}})},setForTemplateRecursive(e,t){e._forTemplate=t,Array.from(e.children).forEach(e=>{this.setForTemplateRecursive(e,t)})},refreshAllLoops(e=this.root,t=new Set){if("TEMPLATE"===e.tagName&&e.hasAttribute("p-for")){if(t.has(e))return;return t.add(e),void this.handleFor(e,e._scope||this.data,!1)}let r=e.firstElementChild;for(;r;){const e=r.nextElementSibling;this.refreshAllLoops(r,t),r=e}},handleFor(e,t,r){const s=e.getAttribute("p-for"),a=s.match(/^(?:const|let)?\s*(.+?)\s+(of|in)\s+(.+)$/);if(!a)return void console.error(`Invalid p-for expression: ${s}`);const[,o,n,i]=a;r?this.hydrateLoop(e,t,o,i):this.refreshLoop(e,t,o,i)},getTemplateScopePrefix(e){let t="",r=e.nextElementSibling;if(r&&r.hasAttribute&&r.hasAttribute("p-for-key")){const s=r.getAttribute("p-for-key"),a=s.lastIndexOf(":");if(a>0){const r=s.substring(0,a+1),o=r.lastIndexOf("-");if(o>=0){t=r.substring(0,o+1);const s=r.substring(o+1,r.length-1);e._forScopeId=s}else e._forScopeId=r.substring(0,r.length-1);return r}}if(e._forTemplate){const r=e._forTemplate._forData;if(r&&r.scopePrefix){let r=e.previousElementSibling;for(;r;){if(r.hasAttribute&&r.hasAttribute("p-for-key")){t=r.getAttribute("p-for-key")+"-";break}r=r.previousElementSibling}}}if(!t){let r=e.previousElementSibling;for(;r;){if(r.hasAttribute&&r.hasAttribute("p-for-key")&&r._forTemplate===e._forTemplate){t=r.getAttribute("p-for-key")+"-";break}r=r.previousElementSibling}}if(!t){let r=e.parentElement;for(;r;){if(r.hasAttribute&&r.hasAttribute("p-for-key")){t=r.getAttribute("p-for-key")+"-";break}if(r._forTemplate){const e=r._forTemplate._forData;if(e){const s=e.renderedElements.indexOf(r);if(s>=0){t=(e.scopePrefix||"")+s+"-";break}}}r=r.parentElement}}return e._forScopeId||(e._forScopeId="s"+this._templateScopeCounter++),t+e._forScopeId+":"},hydrateLoop(template,parentScope,varPattern,iterableExpr){template._scope=parentScope;try{const iterable=eval(`with (parentScope) { (${iterableExpr}) }`),scopePrefix=this.getTemplateScopePrefix(template);template._forData={varPattern:varPattern,iterableExpr:iterableExpr,renderedElements:[],scopePrefix:scopePrefix};const existingElementsByKey={};let sibling=template.nextElementSibling;for(;sibling&&sibling.hasAttribute("p-for-key");){const e=sibling.getAttribute("p-for-key"),t=e.startsWith(scopePrefix)||!e.includes(":")&&!e.includes("-");if(t){let t;t=e.startsWith(scopePrefix)?e.substring(scopePrefix.length):e,existingElementsByKey[t]||(existingElementsByKey[t]=[]),existingElementsByKey[t].push(sibling)}sibling=sibling.nextElementSibling}let index=0,lastInserted=template;for(const e of iterable){const t=this.createLoopScope(parentScope,varPattern,e);if(existingElementsByKey[String(index)])existingElementsByKey[String(index)].forEach(e=>{e._scope=t,this.setForTemplateRecursive(e,template),"TEMPLATE"!==e.tagName&&e.setAttribute("p-for-key",scopePrefix+index),this.walkDom(e,t,!0),template._forData.renderedElements.push(e),lastInserted=e});else{const e=template.content.cloneNode(!0),r=Array.from(e.children);r.forEach(e=>{e._scope=t,this.setForTemplateRecursive(e,template),"TEMPLATE"!==e.tagName&&e.setAttribute("p-for-key",scopePrefix+index),this.walkDom(e,t,!0)});const s=document.createDocumentFragment();r.forEach(e=>s.appendChild(e)),lastInserted.parentNode.insertBefore(s,lastInserted.nextSibling),template._forData.renderedElements.push(...r),lastInserted=r[r.length-1]||lastInserted}index++}Object.keys(existingElementsByKey).forEach(e=>{parseInt(e)>=index&&existingElementsByKey[e].forEach(e=>e.remove())})}catch(e){console.error(`Error in p-for hydration: ${iterableExpr}`,e)}},removeLoopElements(e){e.forEach(e=>{if(e._forData&&e._forData.renderedElements&&(this.removeLoopElements(e._forData.renderedElements),e._forData.renderedElements=[]),e.querySelectorAll){e.querySelectorAll("template[p-for]").forEach(e=>{e._forData&&e._forData.renderedElements&&(this.removeLoopElements(e._forData.renderedElements),e._forData.renderedElements=[])})}e.remove()})},refreshLoop(template,parentScope,varPattern,iterableExpr){const forData=template._forData;if(forData)try{const iterable=eval(`with (parentScope._p_target || parentScope) { (${iterableExpr}) }`),scopePrefix=forData.scopePrefix||this.getTemplateScopePrefix(template);this.removeLoopElements(forData.renderedElements),forData.renderedElements=[];let lastInsertedElement=template,index=0;for(const e of iterable){const t=template.content.cloneNode(!0),r=this.createLoopScope(parentScope,forData.varPattern,e),s=Array.from(t.children);s.forEach(e=>{e._scope=r,this.setForTemplateRecursive(e,template),"TEMPLATE"!==e.tagName&&e.setAttribute("p-for-key",scopePrefix+index)});const a=document.createDocumentFragment();s.forEach(e=>a.appendChild(e)),lastInsertedElement.parentNode.insertBefore(a,lastInsertedElement.nextSibling),forData.renderedElements.push(...s),s.forEach(e=>{this.walkDom(e,r,!0)});const o=s[s.length-1];o&&(lastInsertedElement=this.findLastRenderedSibling(o)),index++}}catch(e){console.error(`Error in p-for refresh: ${iterableExpr}`,e)}},findLastRenderedSibling(e){if("TEMPLATE"===e.tagName&&e._forData&&e._forData.renderedElements.length>0){const t=e._forData.renderedElements[e._forData.renderedElements.length-1];return this.findLastRenderedSibling(t)}return e},createLoopScope(e,t,r){const s={};if((t=t.trim()).startsWith("[")){const e=t.slice(1,-1).split(",").map(e=>e.trim());Array.isArray(r)?e.forEach((e,t)=>s[e]=r[t]):s[e[0]]=r}else if(t.startsWith("{")){t.slice(1,-1).split(",").map(e=>e.trim()).forEach(e=>{const[t,a]=e.split(":").map(e=>e.trim());s[a||t]=r[t]})}else s[t]=r;if(!e)return console.error("parentScope is undefined in createLoopScope"),new Proxy({},{get:()=>{},set:()=>!1});const a=e._p_target||e;if(!a||"object"!=typeof a)return console.error("Invalid parentTarget:",a),new Proxy(s,{get:(e,t)=>e[t],set:(e,t,r)=>(e[t]=r,!0)});const o=Object.create(a);Object.assign(o,s);const n=new Proxy(o,{get:(e,t)=>e[t],set:(e,t,r)=>(t in s?e[t]=r:a[t]=r,!0)});return n._p_target=o,n},walkDom(el,parentScope,isHydrating=!1){if("TEMPLATE"===el.tagName&&el.hasAttribute("p-for")){if(!isHydrating&&el._forTemplate)return;return void this.handleFor(el,parentScope,isHydrating)}const preScopeShowAttr=Array.from(el.attributes).find(e=>{const t=this.parseDirectiveModifiers(e.name);return"p-show"===t.directive&&t.modifiers["pre-scope"]});if(preScopeShowAttr&&parentScope){const value=eval(`with (parentScope) { (${preScopeShowAttr.value}) }`);this.directives["p-show"](el,value)}let currentScope=parentScope;const hasPScope=Array.from(el.attributes).some(e=>e.name.startsWith("p-scope"));hasPScope&&(currentScope=isHydrating?this.initScope(el,parentScope):this.refreshScope(el,parentScope)),isHydrating&&(el._scope=currentScope,this.registerEventListeners(el),this.registerModelBinding(el)),currentScope&&Array.from(el.attributes).forEach(attr=>{const parsed=this.parseDirectiveModifiers(attr.name);if(("p-show"!==parsed.directive||!parsed.modifiers["pre-scope"])&&Object.keys(this.directives).includes(parsed.directive)){const evalScope=el._scope||currentScope,value=eval(`with (evalScope) { (${attr.value}) }`);this.directives[parsed.directive](el,value,parsed.modifiers)}});const children=Array.from(el.children);for(const e of children)this.walkDom(e,currentScope,isHydrating)}},window.Pattr.start();