haori 0.4.12 → 0.4.13

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.
@@ -13,5 +13,5 @@ ${d}
13
13
  `)}catch(b){f.error("Haori",`Invalid after script: ${b}`)}}if(t.hasAttribute(c.attrName(e,"dialog"))&&(r.dialogMessage=t.getAttribute(c.attrName(e,"dialog")).replace(/\\n/g,`
14
14
  `)),t.hasAttribute(c.attrName(e,"toast"))){r.toastMessage=t.getAttribute(c.attrName(e,"toast"));const d=t.getRawAttribute(c.attrName(e,"toast-level")),E=["info","warning","error","success"].includes(d);r.toastLevel=E?d:null}if(t.hasAttribute(c.attrName(e,"redirect"))&&(r.redirectUrl=t.getAttribute(c.attrName(e,"redirect"))),t.hasAttribute(c.attrName(e,"scroll-error"))&&(r.scrollOnError=!0),t.hasAttribute(c.attrName(e,"scroll"))&&(r.scrollTarget=t.getAttribute(c.attrName(e,"scroll"))),t.hasAttribute(c.attrName(e,"history"))&&(r.historyUrl=t.getAttribute(c.attrName(e,"history"))),t.hasAttribute(c.attrName(e,"history-data"))&&(r.historyData=c.resolveDataAttribute(t,c.attrName(e,"history-data"))),t.hasAttribute(c.attrName(e,"history-form"))){const d=t.getRawAttribute(c.attrName(e,"history-form"));if(d){const b=document.body.querySelector(d);b!==null?r.historyFormFragment=y.getFormFragment(w.get(b)):f.error("Haori",`Form element not found: ${d} (${c.attrName(e,"history-form")})`)}else r.historyFormFragment=y.getFormFragment(t)}["reset","refetch","click","copy","open","close"].forEach(d=>{const b=c.attrName(e,d);if(!t.hasAttribute(b))return;const E=t.getRawAttribute(b),A=[];if(E?(document.body.querySelectorAll(E).forEach(tt=>{const it=w.get(tt);it&&A.push(it)}),A.length===0&&f.error("Haori",`Element not found: ${E} (${b})`)):A.push(t),A.length>0)switch(d){case"reset":r.resetFragments=A;break;case"refetch":r.refetchFragments=A;break;case"click":r.clickFragments=A;break;case"copy":r.copyFragments=A;break;case"open":r.openFragments=A;break;case"close":r.closeFragments=A;break}})}if(!e&&(t.hasAttribute(c.attrName(null,"data",!0))&&(r.data=c.resolveDataAttribute(t,c.attrName(null,"data",!0))),t.hasAttribute(c.attrName(null,"form",!0)))){const h=t.getRawAttribute(c.attrName(null,"form",!0));if(h){const d=document.body.querySelector(h);d!==null?r.formFragment=y.getFormFragment(w.get(d)):f.error("Haori",`Form element not found: ${h} (${c.attrName(null,"fetch-form",!0)})`)}else r.formFragment=y.getFormFragment(t)}return n&&(!r.bindFragments||r.bindFragments.length===0)&&(r.bindFragments=[t]),r}static isElementFragment(t){if(typeof t!="object"||t===null)return!1;const e=t;return typeof e.getTarget=="function"&&typeof e.getChildElementFragments=="function"}constructor(t,e=null){c.isElementFragment(t)?(this.options=c.buildOptions(t,e),this.eventType=e):(this.options=t,this.eventType=null)}run(){return this.runWithResult().then(()=>{})}runWithResult(){return this.execute()}async execute(){const t=this.acquireExecutionLock();if(t===!1)return!1;try{if(Object.keys(this.options).length===0||this.options.formFragment&&this.validate(this.options.formFragment)===!1||!await this.confirm())return!1;let r=this.options.fetchUrl,s=this.options.fetchOptions;if(this.options.beforeCallback){const l=this.options.beforeCallback(r||null,s||null);if(l!=null){if(l===!1||typeof l=="object"&&l.stop)return!1;typeof l=="object"&&(r="fetchUrl"in l?l.fetchUrl:r,s="fetchOptions"in l?l.fetchOptions:s)}}const n={};if(this.options.formFragment){const l=y.getValues(this.options.formFragment);Object.assign(n,l)}this.options.data&&typeof this.options.data=="object"&&Object.assign(n,this.options.data);const i=Object.keys(n).length>0;if(r){const l={...s||{}},p=new Headers(l.headers||void 0),m=(l.method||"GET").toUpperCase(),v=u.runtime==="demo"&&!ct(m),T=v?"GET":m;if(l.method=T,T==="GET"||T==="HEAD"||T==="OPTIONS")i&&(r=ft(r,n));else if(i){const d=p.get("Content-Type")||"";if(/multipart\/form-data/i.test(d)){p.delete("Content-Type");const b=new FormData;for(const[E,A]of Object.entries(n))A==null?b.append(E,""):A instanceof Blob?b.append(E,A):Array.isArray(A)?A.forEach(x=>b.append(E,String(x))):typeof A=="object"?b.append(E,JSON.stringify(A)):b.append(E,String(A));l.body=b}else if(/application\/x-www-form-urlencoded/i.test(d)){const b=new URLSearchParams;for(const[E,A]of Object.entries(n))A!==void 0&&(A===null?b.append(E,""):Array.isArray(A)?A.forEach(x=>b.append(E,String(x))):typeof A=="object"?b.append(E,JSON.stringify(A)):b.append(E,String(A)));l.body=b}else p.set("Content-Type","application/json"),l.body=JSON.stringify(n)}l.headers=p;let h;if(v&&(h=r&&new URL(r,window.location.href).search||void 0,p.delete("Content-Type"),f.info("Haori demo fetch normalization",{runtime:u.runtime,requestedMethod:m,effectiveMethod:T,transportMode:"query-get",url:r,payload:i?n:void 0,queryString:h})),this.options.targetFragment&&r){const d=performance.now(),b={runtime:u.runtime,requestedMethod:m,effectiveMethod:T,transportMode:v?"query-get":"http",...v?{queryString:h}:{}};return N.fetchStart(this.options.targetFragment.getTarget(),r,l,i?n:void 0,b),fetch(r,l).then(E=>this.handleFetchResult(E,r||void 0,d)).catch(E=>{throw r&&N.fetchError(this.options.targetFragment.getTarget(),r,E),E})}return fetch(r,l).then(d=>this.handleFetchResult(d,r||void 0))}if((!this.options.bindFragments||this.options.bindFragments.length===0)&&this.options.formFragment&&i){const l=this.options.formFragment,p=l.getTarget();p.setAttribute(`${u.prefix}bind`,JSON.stringify(n));const m=l.getBindingData();Object.assign(m,n),await P.setBindingData(p,m)}const a=i?n:{},o=new Response(JSON.stringify(a),{headers:{"Content-Type":"application/json"}});return this.handleFetchResult(o)}finally{this.releaseExecutionLock(t)}}acquireExecutionLock(){if(this.eventType!=="click"||!this.options.targetFragment)return null;const t=this.options.targetFragment.getTarget();return c.RUNNING_CLICK_TARGETS.has(t)||t.hasAttribute("disabled")?!1:(c.RUNNING_CLICK_TARGETS.add(t),t.setAttribute("disabled",""),{target:t,appliedDisabledAttribute:!0})}releaseExecutionLock(t){t&&(c.RUNNING_CLICK_TARGETS.delete(t.target),t.appliedDisabledAttribute&&t.target.removeAttribute("disabled"))}async handleFetchResult(t,e,r){const s=Q();if(!t.ok)return this.options.targetFragment&&e&&N.fetchError(this.options.targetFragment.getTarget(),e,new Error(`${t.status} ${t.statusText}`),t.status,r),await this.handleFetchError(t),!1;if(this.options.targetFragment&&e&&r&&N.fetchEnd(this.options.targetFragment.getTarget(),e,t.status,r),this.options.afterCallback){const a=this.options.afterCallback(t);if(a!=null){if(a===!1||typeof a=="object"&&a.stop)return!1;typeof a=="object"&&"response"in a&&(t="response"in a?a.response:t)}}const n=[];n.push(this.bindResult(t)),n.push(this.adjust()),n.push(this.addRow()),n.push(this.removeRow()),n.push(this.movePrevRow()),n.push(this.moveNextRow()),await Promise.all(n),this.options.resetFragments&&this.options.resetFragments.length>0&&await Promise.all(this.options.resetFragments.map(a=>y.reset(a))),await this.copy();const i=[];return this.options.refetchFragments&&this.options.refetchFragments.length>0&&this.options.refetchFragments.forEach(a=>{i.push(new c(a,null).run())}),this.options.clickFragments&&this.options.clickFragments.length>0&&this.options.clickFragments.forEach(a=>{const o=a.getTarget();typeof o.click=="function"?o.click():o.dispatchEvent(new MouseEvent("click",{bubbles:!0,cancelable:!0}))}),this.options.openFragments&&this.options.openFragments.length>0&&this.options.openFragments.forEach(a=>{const o=a.getTarget();o instanceof HTMLElement?i.push(s.openDialog(o)):f.error("Haori","Element is not an HTML element: ",o)}),this.options.closeFragments&&this.options.closeFragments.length>0&&this.options.closeFragments.forEach(a=>{const o=a.getTarget();o instanceof HTMLElement?i.push(s.closeDialog(o)):f.error("Haori","Element is not an HTML element: ",o)}),await Promise.all(i),this.options.dialogMessage&&await s.dialog(this.options.dialogMessage),this.options.toastMessage&&await s.toast(this.options.toastMessage,this.options.toastLevel??"info"),this.pushHistory(),this.options.scrollTarget&&document.querySelector(this.options.scrollTarget)?.scrollIntoView({behavior:"smooth",block:"nearest"}),this.options.redirectUrl&&(window.location.href=this.options.redirectUrl),!0}pushHistory(){const t=this.options.historyUrl!==void 0&&this.options.historyUrl!==null,e=this.options.historyData!==void 0&&this.options.historyData!==null,r=this.options.historyFormFragment!==void 0&&this.options.historyFormFragment!==null;if(!(!t&&!e&&!r))try{const s=t?this.options.historyUrl:window.location.pathname,n=new URL(s,window.location.href);if(n.origin!==window.location.origin){const a="history.pushState: cross-origin URL is not allowed: "+n.toString();f.error("Haori",a);return}const i=a=>{for(const[o,l]of Object.entries(a))l!=null&&(Array.isArray(l)?l.forEach(p=>n.searchParams.append(o,String(p))):typeof l=="object"?n.searchParams.set(o,JSON.stringify(l)):n.searchParams.set(o,String(l)))};e&&i(this.options.historyData),r&&i(y.getValues(this.options.historyFormFragment)),history.pushState({[lt]:!0},"",n.toString())}catch(s){f.error("Haori",`history.pushState failed: ${s}`)}}async handleFetchError(t){let e=null;this.options.formFragment?e=this.options.formFragment:this.options.targetFragment&&(e=y.getFormFragment(this.options.targetFragment)||this.options.targetFragment);const r=async i=>{const a=e?e.getTarget():document.body;await Q().addErrorMessage(a,i)},s=()=>{if(!this.options.scrollOnError)return;const i=e?e.getTarget():document.body;(i.getAttribute("data-message-level")==="error"?i:i.parentElement?.getAttribute("data-message-level")==="error"?i.parentElement:i.querySelector('[data-message-level="error"]'))?.scrollIntoView({behavior:"smooth",block:"nearest"})};if((t.headers.get("Content-Type")||"").includes("application/json"))try{const i=await t.json(),a=[];if(i&&typeof i=="object"){if(typeof i.message=="string"&&a.push({message:i.message}),Array.isArray(i.messages))for(const o of i.messages)typeof o=="string"&&a.push({message:o});if(i.errors&&typeof i.errors=="object")for(const[o,l]of Object.entries(i.errors))Array.isArray(l)?a.push({key:o,message:l.join(`
15
15
  `)}):typeof l=="string"?a.push({key:o,message:l}):l!=null&&a.push({key:o,message:String(l)});if(a.length===0)for(const[o,l]of Object.entries(i))o==="message"||o==="messages"||o==="errors"||(Array.isArray(l)?a.push({key:o,message:l.join(`
16
- `)}):typeof l=="string"&&a.push({key:o,message:l}))}if(a.length===0)return await r(`${t.status} ${t.statusText}`),s(),!1;for(const o of a)o.key&&e?await y.addErrorMessage(e,o.key,o.message):await r(o.message);return s(),!1}catch{}try{const i=await t.text();i&&i.trim().length>0?await r(i.trim()):await r(`${t.status} ${t.statusText}`)}catch{await r(`${t.status} ${t.statusText}`)}return s(),!1}validate(t){if(this.options.valid!==!0)return!0;const e=this.findFirstInvalid(t);return e===null?!0:(e.reportValidity(),e.focus(),this.options.scrollOnError&&e.scrollIntoView({behavior:"smooth",block:"nearest"}),!1)}findFirstInvalid(t){let e=null;for(const r of t.getChildElementFragments().reverse()){const s=this.findFirstInvalid(r);s!==null&&(e=s)}return this.checkOne(t)?e:t.getTarget()}checkOne(t){const e=t.getTarget();return e instanceof HTMLInputElement||e instanceof HTMLSelectElement||e instanceof HTMLTextAreaElement?e.checkValidity():!0}confirm(){const t=this.options.confirmMessage;return t==null?Promise.resolve(!0):Q().confirm(t)}bindResult(t){return!this.options.bindFragments||this.options.bindFragments.length===0?Promise.resolve():(t.headers.get("Content-Type")?.includes("application/json")?t.json():t.text()).then(r=>{if(this.options.bindParams){const n={};this.options.bindParams.forEach(i=>{r&&typeof r=="object"&&i in r&&(n[i]=r[i])}),r=n}const s=[];if(this.options.bindArg)this.options.bindFragments.forEach(n=>{const i=n.getBindingData(),a=this.options.bindArg;if(r&&typeof r=="object"&&!Array.isArray(r)){const o=i[a],l=o&&typeof o=="object"&&!Array.isArray(o)?o:{};i[a]=this.mergeAppendBindingData(n,r,l)}else i[a]=r;s.push(P.setBindingData(n.getTarget(),i))});else{if(typeof r=="string")return f.error("Haori","string data cannot be bound without a bindArg."),Promise.reject(new Error("string data cannot be bound without a bindArg."));this.options.bindFragments.forEach(n=>{const i=this.mergeAppendBindingData(n,r);s.push(P.setBindingData(n.getTarget(),i))})}return Promise.all(s).then(()=>{})})}mergeAppendBindingData(t,e,r=t.getBindingData()){if(!this.options.bindAppendParams||this.options.bindAppendParams.length===0)return e;const s={...e},n=r;for(const i of this.options.bindAppendParams){const a=s[i],o=n[i];Array.isArray(o)&&Array.isArray(a)&&(s[i]=o.concat(a))}return s}copy(){if(!this.options.copyFragments||this.options.copyFragments.length===0)return Promise.resolve();const t=this.resolveCopySourceData(),e=this.pickCopyData(t),r=this.options.copyFragments.map(s=>{const n={...s.getBindingData(),...e};return P.setBindingData(s.getTarget(),n)});return Promise.all(r).then(()=>{})}resolveCopySourceData(){return this.options.formFragment?y.getValues(this.options.formFragment):this.options.targetFragment?{...this.options.targetFragment.getBindingData()}:{}}pickCopyData(t){if(!this.options.copyParams||this.options.copyParams.length===0)return t;const e={};return this.options.copyParams.forEach(r=>{r in t&&(e[r]=t[r])}),e}adjust(){if(!this.options.adjustFragments||this.options.adjustFragments.length===0)return Promise.resolve();const t=this.options.adjustValue??0,e=[];for(const r of this.options.adjustFragments){let s=r.getValue();(s==null||s==="")&&(s="0");let n=Number(s);isNaN(n)&&(n=0),n+=t,e.push(r.setValue(String(n)))}return Promise.all(e).then(()=>{})}getRowFragment(){if(!this.options.targetFragment)return f.error("Haori","Target fragment is not specified for row operation."),null;const t=this.options.targetFragment.closestByAttribute(`${u.prefix}row`);return t||(f.error("Haori","Row fragment not found."),null)}addRow(){if(this.options.rowAdd!==!0)return Promise.resolve();const t=this.getRowFragment();if(!t)return Promise.reject(new Error("Row fragment not found."));const e=[],r=t.clone();return e.push(t.getParent().insertAfter(r,t)),e.push(P.evaluateAll(r)),e.push(y.reset(r)),Promise.all(e).then(()=>{})}removeRow(){if(this.options.rowRemove!==!0)return Promise.resolve();const t=this.getRowFragment();if(!t)return Promise.reject(new Error("Row fragment not found."));const e=t.getParent();return e&&e.getChildElementFragments().filter(s=>!s.hasAttribute(`${u.prefix}each-before`)&&!s.hasAttribute(`${u.prefix}each-after`)).length<=1?Promise.resolve():t.remove()}movePrevRow(){if(this.options.rowMovePrev!==!0)return Promise.resolve();const t=this.getRowFragment();if(!t)return Promise.reject(new Error("Row fragment not found."));const e=t.getPrevious();if(!e)return Promise.resolve();const r=t.getParent();return r?r.insertBefore(t,e):Promise.resolve()}moveNextRow(){if(this.options.rowMoveNext!==!0)return Promise.resolve();const t=this.getRowFragment();if(!t)return Promise.reject(new Error("Row fragment not found."));const e=t.getNext();if(!e)return Promise.resolve();const r=t.getParent();return r?r.insertAfter(t,e):Promise.resolve()}};c.DATA_PLACEHOLDER_REGEX=/\{\{\{([\s\S]+?)\}\}\}|\{\{([\s\S]+?)\}\}/g,c.SINGLE_PLACEHOLDER_REGEX=/^(\{\{\{[\s\S]+?\}\}\}|\{\{[\s\S]+?\}\})$/,c.RUNNING_CLICK_TARGETS=new WeakSet;let U=c;class dt{static readParams(){const t={},e=window.location.search;return new URLSearchParams(e).forEach((s,n)=>{t[n]=s}),t}}class pt{static async load(t,e){let r;try{r=await fetch(t,e)}catch(n){throw f.error("[Haori]","Failed to fetch import source:",t,n),new Error(`Failed to fetch: ${t}`)}if(!r.ok){const n=`${r.status} ${r.statusText}`;throw f.error("[Haori]","Import HTTP error:",t,n),new Error(`Failed to load ${t}: ${n}`)}let s;try{s=await r.text()}catch(n){throw f.error("[Haori]","Failed to read response text:",t,n),new Error(`Failed to read response from: ${t}`)}try{const i=new DOMParser().parseFromString(s,"text/html");return i&&i.body?i.body.innerHTML:(f.warn("[Haori]","No body found in imported document:",t),s)}catch(n){return f.error("[Haori]","Failed to parse imported HTML:",t,n),s}}}const g=class g{static isDeferredAttributeName(t){return g.DEFERRED_ATTRIBUTE_SUFFIXES.some(e=>t===`${u.prefix}${e}`)}static isEvaluateAllExcludedAttributeName(t){return g.EVALUATE_ALL_EXCLUDED_ATTRIBUTE_SUFFIXES.some(e=>t===`${u.prefix}${e}`)}static shouldReevaluateAttribute(t,e){return e!==null&&!g.isEvaluateAllExcludedAttributeName(t)&&g.ATTRIBUTE_PLACEHOLDER_REGEX.test(e)}static getAliasedAttributeName(t){const e=`${u.prefix}${g.ATTRIBUTE_ALIAS_SUFFIX}`;return!t.startsWith(e)||t.length<=e.length?null:t.slice(e.length)}static isAliasedAttributeReflection(t,e){const r=w.get(t);return r instanceof M?r.hasAttribute(`${u.prefix}${g.ATTRIBUTE_ALIAS_SUFFIX}${e}`):!1}static reevaluateInterpolatedAttributes(t){let e=Promise.resolve();for(const r of t.getAttributeNames()){const s=t.getRawAttribute(r);g.shouldReevaluateAttribute(r,s)&&(e=e.then(()=>g.setAttribute(t.getTarget(),r,s)))}return e.then(()=>{})}static scan(t){const e=w.get(t);if(!e)return Promise.resolve();t.parentNode&&(w.get(t.parentNode)?.isMounted()||document.body.contains(t)?e.setMounted(!0):e.setMounted(!1));let r=Promise.resolve();const s=new Set;for(const n of g.PRIORITY_ATTRIBUTE_SUFFIXES){const i=u.prefix+n;e.hasAttribute(i)&&(r=r.then(()=>g.setAttribute(e.getTarget(),i,e.getRawAttribute(i))),s.add(i))}for(const n of e.getAttributeNames()){if(s.has(n)||g.isDeferredAttributeName(n))continue;const i=e.getRawAttribute(n);i!==null&&(r=r.then(()=>g.setAttribute(e.getTarget(),n,i)))}for(const n of g.DEFERRED_ATTRIBUTE_SUFFIXES){const i=u.prefix+n;e.hasAttribute(i)&&(r=r.then(()=>g.setAttribute(e.getTarget(),i,e.getRawAttribute(i))),s.add(i))}return r.then(()=>{const n=[];return e.getChildren().forEach(i=>{i instanceof M?n.push(g.scan(i.getTarget())):i instanceof C&&n.push(g.evaluateText(i))}),Promise.all(n).then(()=>{})}).then(()=>{})}static setAttribute(t,e,r,s=!1){const n=w.get(t),i=g.getAliasedAttributeName(e);if(i!==null)return r===null?n.removeAliasedAttribute(e,i):n.setAliasedAttribute(e,i,r,s);const a=[];switch(e){case`${u.prefix}bind`:{r===null?(n.clearBindingDataCache(),n.setBindingData({})):n.setBindingData(g.parseDataBind(r));break}case`${u.prefix}if`:a.push(g.evaluateIf(n));break;case`${u.prefix}each`:a.push(g.evaluateEach(n));break;case`${u.prefix}fetch`:a.push(new U(n,null).run().then(()=>{}));break;case`${u.prefix}import`:{if(typeof r=="string"){const o=n.getTarget(),l=performance.now();o.setAttribute(`${u.prefix}importing`,""),N.importStart(o,r),a.push(pt.load(r).then(p=>{const m=new TextEncoder().encode(p).length;return F.enqueue(()=>{o.innerHTML=p}).then(()=>{if(o.removeAttribute(`${u.prefix}importing`),N.importEnd(o,r,m,l),!document.body.hasAttribute("data-haori-ready")){const v=[];return o.childNodes.forEach(T=>{const h=w.get(T);h instanceof M?v.push(g.scan(h.getTarget())):h instanceof C&&v.push(g.evaluateText(h))}),Promise.all(v).then(()=>{})}})}).catch(p=>{o.removeAttribute(`${u.prefix}importing`),N.importError(o,r,p),f.error("[Haori]","Failed to import HTML:",r,p)}))}break}case`${u.prefix}url-param`:{const o=n.getAttribute(`${u.prefix}url-arg`),l=dt.readParams();if(o===null)a.push(g.setBindingData(t,l));else{const p=n.getRawBindingData()||{};p[String(o)]=l,a.push(g.setBindingData(t,p))}break}}return r===null?a.push(n.removeAttribute(e)):a.push(n.setAttribute(e,r,s)),Promise.all(a).then(()=>{})}static setBindingData(t,e){const r=w.get(t),s=r.getRawBindingData();r.setBindingData(e);let n=r.setAttribute(`${u.prefix}bind`,JSON.stringify(e));if(t.tagName==="FORM"){const i=r.getAttribute(`${u.prefix}form-arg`),a=i&&e[String(i)]&&typeof e[String(i)]=="object"&&!Array.isArray(e[String(i)])?e[String(i)]:i?{}:e;n=n.then(()=>y.syncValues(r,a))}return n=n.then(()=>g.evaluateAll(r)),N.bindChange(t,s,e,"manual"),n.then(()=>{})}static parseDataBind(t){if(t.startsWith("{")||t.startsWith("["))try{return JSON.parse(t)}catch(e){return f.error("[Haori]","Invalid JSON in data-bind:",e),{}}else{const e=new URLSearchParams(t),r={};for(const[s,n]of e.entries())r[s]!==void 0?Array.isArray(r[s])?r[s].push(n):r[s]=[r[s],n]:r[s]=n;return r}}static addNode(t,e){const r=w.get(t);if(r.isSkipMutationNodes())return;const s=w.get(e.nextSibling),n=w.get(e);n&&(r.insertBefore(n,s),n instanceof M?g.scan(n.getTarget()):n instanceof C&&g.evaluateText(n))}static removeNode(t){const e=w.get(t);if(e){const r=e.getParent();if(r&&r.isSkipMutationNodes())return;e.remove()}}static changeText(t,e){const r=w.get(t);r&&r.setContent(e)}static changeValue(t,e){const r=w.get(t);if(r.getValue()===e)return Promise.resolve();const s=[];s.push(r.setValue(e));const n=g.getFormFragment(r);if(n){const i=y.getValues(n),a=n.getAttribute(`${u.prefix}form-arg`);let o;a?(o=n.getRawBindingData(),o||(o={}),o[String(a)]=i):o=i,s.push(g.setBindingData(n.getTarget(),o))}return Promise.all(s).then(()=>{})}static getFormFragment(t){if(t.getTarget()instanceof HTMLFormElement)return t;const e=t.getParent();return e?g.getFormFragment(e):null}static evaluateAll(t){const e=[];return e.push(g.reevaluateInterpolatedAttributes(t)),t.hasAttribute(`${u.prefix}if`)&&e.push(g.evaluateIf(t)),t.hasAttribute(`${u.prefix}each`)?Promise.all(e).then(()=>g.evaluateEach(t)):(t.getChildren().forEach(r=>{r instanceof M?e.push(g.evaluateAll(r)):r instanceof C&&e.push(g.evaluateText(r))}),Promise.all(e).then(()=>{}))}static evaluateText(t){return t.evaluate()}static evaluateIf(t){const e=[],r=t.getAttribute(`${u.prefix}if`);if(r===!1||r===void 0||r===null||Number.isNaN(r))e.push(t.hide().then(()=>{N.hide(t.getTarget())}));else{const s=[];t.getChildren().forEach(n=>{n instanceof M?s.push(g.evaluateAll(n)):n instanceof C&&s.push(g.evaluateText(n))}),e.push(t.show().then(()=>{N.show(t.getTarget())})),e.push(Promise.all(s).then(()=>{}))}return Promise.all(e).then(()=>{})}static evaluateEach(t){if(!t.isVisible()||!t.isMounted())return Promise.resolve();let e=t.getTemplate();if(e===null){let s=!1;t.getChildren().forEach(i=>{if(!s&&i instanceof M){if(i.hasAttribute(`${u.prefix}each-before`)||i.hasAttribute(`${u.prefix}each-after`))return;e=i.clone(),t.setTemplate(e),s=!0,t.removeChild(i);const a=i.getTarget();a.parentNode&&a.parentNode.removeChild(a),i.setMounted(!1)}});const n=t.getAttribute(`${u.prefix}each`);return Array.isArray(n)?this.updateDiff(t,n):(f.error("[Haori]","Invalid each attribute:",n),Promise.reject(new Error("Invalid each attribute.")))}const r=t.getAttribute(`${u.prefix}each`);return Array.isArray(r)?this.updateDiff(t,r):(f.error("[Haori]","Invalid each attribute:",r),Promise.reject(new Error("Invalid each attribute.")))}static updateDiff(t,e){const r=t.getTemplate();if(r===null)return f.error("[Haori]","Template is not set for each element."),Promise.resolve();let s=t.getAttribute(`${u.prefix}each-index`);s&&(s=String(s));const n=t.getAttribute(`${u.prefix}each-key`),i=t.getAttribute(`${u.prefix}each-arg`),a=new Map,o=[];e.forEach((h,d)=>{const b=g.createListKey(h,n?String(n):null,d);o.push(b),a.set(b,{item:h,itemIndex:d})});const l=[];let p=t.getChildren().filter(h=>h instanceof M).filter(h=>!h.hasAttribute(`${u.prefix}each-before`)&&!h.hasAttribute(`${u.prefix}each-after`));p=p.filter(h=>o.indexOf(String(h.getListKey()))===-1?(l.push(h.remove()),!1):!0);const m=p.map(h=>h.getListKey()),v=t.getChildren().filter(h=>h instanceof M).filter(h=>h.hasAttribute(`${u.prefix}each-before`)).length;let T=Promise.resolve();return o.forEach((h,d)=>{const b=m.indexOf(h),{item:E,itemIndex:A}=a.get(h);let x;if(b!==-1)x=p[b],T=T.then(()=>g.updateRowFragment(x,E,s,A,i?String(i):null,h).then(()=>g.evaluateAll(x)).then(()=>g.scheduleEvaluateAll(x)));else{x=r.clone();const tt=v+d;T=T.then(()=>g.updateRowFragment(x,E,s,A,i?String(i):null,h).then(()=>t.insertBefore(x,t.getChildren()[tt]||null).then(()=>g.evaluateAll(x)).then(()=>g.scheduleEvaluateAll(x))))}}),Promise.all(l).then(()=>T).then(()=>{const h=o.filter(A=>A!==null),d=m.filter(A=>A!==null),b=h.filter(A=>!d.includes(A)),E=d.filter(A=>!h.includes(A));N.eachUpdate(t.getTarget(),b,E,h)})}static createListKey(t,e,r){let s;if(typeof t=="object"&&t!==null)if(e){const n=t[e];n==null?s=`__index_${r}`:typeof n=="object"?s=JSON.stringify(n):s=String(n)}else s=`__index_${r}`;else s=String(t);return s}static updateRowFragment(t,e,r,s,n,i){let a=e;if(typeof e=="object"&&e!==null)a={...e},r&&(a[r]=s),n&&(a={[n]:a});else if(n)a={[n]:e},r&&(a[r]=s);else return f.error("[Haori]",`Primitive value requires '${u.prefix}each-arg' attribute: ${e}`),Promise.resolve();return t.setListKey(i),t.setBindingData(a),t.setAttribute(`${u.prefix}row`,i)}static scheduleEvaluateAll(t){setTimeout(()=>{g.evaluateAll(t)},100)}};g.ATTRIBUTE_ALIAS_SUFFIX="attr-",g.PRIORITY_ATTRIBUTE_SUFFIXES=["bind","if","each"],g.DEFERRED_ATTRIBUTE_SUFFIXES=["fetch","url-param"],g.EVALUATE_ALL_EXCLUDED_ATTRIBUTE_SUFFIXES=["bind","if","each","fetch","import","url-param"],g.ATTRIBUTE_PLACEHOLDER_REGEX=/\{\{\{[\s\S]+?\}\}\}|\{\{[\s\S]+?\}\}/;let P=g;const J=class J{constructor(t=document){this.onClick=e=>this.delegate(e,"click"),this.onChange=e=>this.delegate(e,"change"),this.onLoadCapture=e=>this.delegate(e,"load"),this.onWindowLoad=()=>{const e=document.documentElement,r=w.get(e);r&&new U(r,"load").run()},this.onPopstate=e=>{const r=e.state;!r||r[J.HISTORY_STATE_KEY]!==!0||location.reload()},this.root=t}start(){this.root.addEventListener("click",this.onClick),this.root.addEventListener("change",this.onChange),this.root.addEventListener("load",this.onLoadCapture,!0),window.addEventListener("load",this.onWindowLoad,{once:!0}),window.addEventListener("popstate",this.onPopstate)}stop(){this.root.removeEventListener("click",this.onClick),this.root.removeEventListener("change",this.onChange),this.root.removeEventListener("load",this.onLoadCapture,!0),window.removeEventListener("load",this.onWindowLoad),window.removeEventListener("popstate",this.onPopstate)}delegate(t,e){const r=this.getElementFromTarget(t.target);if(!r)return;const s=w.get(r);s&&(e==="change"&&s instanceof M&&s.syncValue(),new U(s,e).run().catch(n=>{f.error("[Haori]","Procedure execution error:",n)}))}getElementFromTarget(t){return t?t instanceof HTMLElement?t:t instanceof Node?t.parentElement:null:null}};J.HISTORY_STATE_KEY="__haoriHistoryState__";let Z=J;const S=class S{static syncTree(t){(t instanceof Element||t instanceof DocumentFragment)&&(t instanceof HTMLElement&&S.syncElement(t),t.querySelectorAll("*").forEach(e=>{S.syncElement(e)}))}static syncElement(t){const e=S.registrations.get(t),r=w.get(t);if(!r||!S.shouldObserve(r)){e&&(e.observer.disconnect(),S.registrations.delete(t));return}if(typeof IntersectionObserver>"u")return;const s=S.resolveRoot(r),n=S.resolveRootMargin(r),i=S.resolveThreshold(r),a=r.hasAttribute(`${u.prefix}intersect-once`);if(e&&e.observer.root===s&&e.observer.rootMargin===n&&S.sameThreshold(e.observer.thresholds,i)&&e.once===a){e.fragment=r;return}e&&(e.observer.disconnect(),S.registrations.delete(t));const o=new IntersectionObserver(l=>{const p=S.registrations.get(t);p&&l.forEach(m=>{!m.isIntersecting||p.running||S.isDisabled(p.fragment)||(p.running=!0,new U(p.fragment,"intersect").runWithResult().then(v=>{v&&p.once&&(p.observer.disconnect(),S.registrations.delete(t))}).catch(v=>{f.error("[Haori]","Intersect procedure execution error:",v)}).finally(()=>{const v=S.registrations.get(t);v&&(v.running=!1)}))})},{root:s,rootMargin:n,threshold:i});o.observe(t),S.registrations.set(t,{fragment:r,observer:o,once:a,running:!1})}static cleanupTree(t){if(t instanceof HTMLElement){const e=S.registrations.get(t);e&&(e.observer.disconnect(),S.registrations.delete(t))}(t instanceof Element||t instanceof DocumentFragment)&&t.querySelectorAll("*").forEach(e=>{const r=S.registrations.get(e);r&&(r.observer.disconnect(),S.registrations.delete(e))})}static disconnectAll(){S.registrations.forEach(t=>{t.observer.disconnect()}),S.registrations.clear()}static shouldObserve(t){return t.getAttributeNames().some(e=>{if(!e.startsWith(`${u.prefix}intersect-`))return!1;const r=e.slice(`${u.prefix}intersect-`.length);return!S.CONFIG_KEYS.has(r)})}static resolveRoot(t){const e=`${u.prefix}intersect-root`;if(!t.hasAttribute(e))return null;const r=t.getAttribute(e);if(typeof r!="string"||r.trim()==="")return null;const s=document.querySelector(r);return s instanceof HTMLElement?s:(f.error("[Haori]",`Intersect root element not found: ${r}`),null)}static resolveRootMargin(t){const e=`${u.prefix}intersect-root-margin`,r=t.getAttribute(e);return r===null||r===!1||r===""?"0px":String(r)}static resolveThreshold(t){const e=`${u.prefix}intersect-threshold`,r=t.getAttribute(e),s=typeof r=="number"?r:Number.parseFloat(String(r??0));return Number.isNaN(s)?0:Math.min(1,Math.max(0,s))}static isDisabled(t){const e=`${u.prefix}intersect-disabled`,r=t.getAttribute(e);if(r===null||r===!1)return!1;if(typeof r=="boolean")return r;const s=String(r).trim().toLowerCase();return s!==""&&s!=="false"&&s!=="0"}static sameThreshold(t,e){return t.length===1&&t[0]===e}};S.CONFIG_KEYS=new Set(["root","root-margin","threshold","disabled","once"]),S.registrations=new Map;let q=S;const $=class ${static async init(){if($._initialized)return;$._initialized=!0;const t=await Promise.allSettled([P.scan(document.head),P.scan(document.body)]),[e,r]=t;e.status!=="fulfilled"&&f.error("[Haori]","Failed to build head fragment:",e.reason),r.status!=="fulfilled"&&f.error("[Haori]","Failed to build body fragment:",r.reason),await F.wait(),document.body.setAttribute("data-haori-ready",""),$.observe(document.head),$.observe(document.body),new Z().start(),q.syncTree(document.body)}static observe(t){new MutationObserver(async r=>{for(const s of r)try{switch(s.type){case"attributes":{f.info("[Haori]","Attribute changed:",s.target,s.attributeName);const n=s.target;if(s.attributeName&&P.isAliasedAttributeReflection(n,s.attributeName))break;P.setAttribute(n,s.attributeName,n.getAttribute(s.attributeName),!0),q.syncElement(n);break}case"childList":{f.info("[Haori]","Child list changed:",Array.from(s.removedNodes).map(n=>n.nodeName),Array.from(s.addedNodes).map(n=>n.nodeName)),Array.from(s.removedNodes).forEach(n=>{q.cleanupTree(n),P.removeNode(n)}),Array.from(s.addedNodes).forEach(n=>{n.parentElement instanceof HTMLElement&&(P.addNode(n.parentElement,n),q.syncTree(n))});break}case"characterData":{f.info("[Haori]","Character data changed:",s.target,s.target.textContent),s.target instanceof Text||s.target instanceof Comment?P.changeText(s.target,s.target.textContent):f.warn("[Haori]","Unsupported character data type:",s.target);break}default:f.warn("[Haori]","Unknown mutation type:",s.type);continue}}catch(n){f.error("[Haori]","Error processing mutation:",n)}}).observe(t,{childList:!0,subtree:!0,attributes:!0,characterData:!0}),f.info("[Haori]","Observer initialized for",t)}};$._initialized=!1;let K=$;document.readyState==="loading"?document.addEventListener("DOMContentLoaded",K.init):K.init();const gt="0.4.12";return k.Core=P,k.Env=u,k.Form=y,k.Fragment=w,k.Haori=j,k.Log=f,k.Queue=F,k.default=j,k.version=gt,Object.defineProperties(k,{__esModule:{value:!0},[Symbol.toStringTag]:{value:"Module"}}),k}({});
16
+ `)}):typeof l=="string"&&a.push({key:o,message:l}))}if(a.length===0)return await r(`${t.status} ${t.statusText}`),s(),!1;for(const o of a)o.key&&e?await y.addErrorMessage(e,o.key,o.message):await r(o.message);return s(),!1}catch{}try{const i=await t.text();i&&i.trim().length>0?await r(i.trim()):await r(`${t.status} ${t.statusText}`)}catch{await r(`${t.status} ${t.statusText}`)}return s(),!1}validate(t){if(this.options.valid!==!0)return!0;const e=this.findFirstInvalid(t);return e===null?!0:(e.reportValidity(),e.focus(),this.options.scrollOnError&&e.scrollIntoView({behavior:"smooth",block:"nearest"}),!1)}findFirstInvalid(t){let e=null;for(const r of t.getChildElementFragments().reverse()){const s=this.findFirstInvalid(r);s!==null&&(e=s)}return this.checkOne(t)?e:t.getTarget()}checkOne(t){const e=t.getTarget();return e instanceof HTMLInputElement||e instanceof HTMLSelectElement||e instanceof HTMLTextAreaElement?e.checkValidity():!0}confirm(){const t=this.options.confirmMessage;return t==null?Promise.resolve(!0):Q().confirm(t)}bindResult(t){return!this.options.bindFragments||this.options.bindFragments.length===0?Promise.resolve():(t.headers.get("Content-Type")?.includes("application/json")?t.json():t.text()).then(r=>{if(this.options.bindParams){const n={};this.options.bindParams.forEach(i=>{r&&typeof r=="object"&&i in r&&(n[i]=r[i])}),r=n}const s=[];if(this.options.bindArg)this.options.bindFragments.forEach(n=>{const i=n.getBindingData(),a=this.options.bindArg;if(r&&typeof r=="object"&&!Array.isArray(r)){const o=i[a],l=o&&typeof o=="object"&&!Array.isArray(o)?o:{};i[a]=this.mergeAppendBindingData(n,r,l)}else i[a]=r;s.push(P.setBindingData(n.getTarget(),i))});else{if(typeof r=="string")return f.error("Haori","string data cannot be bound without a bindArg."),Promise.reject(new Error("string data cannot be bound without a bindArg."));this.options.bindFragments.forEach(n=>{const i=this.mergeAppendBindingData(n,r);s.push(P.setBindingData(n.getTarget(),i))})}return Promise.all(s).then(()=>{})})}mergeAppendBindingData(t,e,r=t.getBindingData()){if(!this.options.bindAppendParams||this.options.bindAppendParams.length===0)return e;const s={...e},n=r;for(const i of this.options.bindAppendParams){const a=s[i],o=n[i];Array.isArray(o)&&Array.isArray(a)&&(s[i]=o.concat(a))}return s}copy(){if(!this.options.copyFragments||this.options.copyFragments.length===0)return Promise.resolve();const t=this.resolveCopySourceData(),e=this.pickCopyData(t),r=this.options.copyFragments.map(s=>{const n={...s.getBindingData(),...e};return P.setBindingData(s.getTarget(),n)});return Promise.all(r).then(()=>{})}resolveCopySourceData(){return this.options.formFragment?y.getValues(this.options.formFragment):this.options.targetFragment?{...this.options.targetFragment.getBindingData()}:{}}pickCopyData(t){if(!this.options.copyParams||this.options.copyParams.length===0)return t;const e={};return this.options.copyParams.forEach(r=>{r in t&&(e[r]=t[r])}),e}adjust(){if(!this.options.adjustFragments||this.options.adjustFragments.length===0)return Promise.resolve();const t=this.options.adjustValue??0,e=[];for(const r of this.options.adjustFragments){let s=r.getValue();(s==null||s==="")&&(s="0");let n=Number(s);isNaN(n)&&(n=0),n+=t,e.push(r.setValue(String(n)))}return Promise.all(e).then(()=>{})}getRowFragment(){if(!this.options.targetFragment)return f.error("Haori","Target fragment is not specified for row operation."),null;const t=this.options.targetFragment.closestByAttribute(`${u.prefix}row`);return t||(f.error("Haori","Row fragment not found."),null)}addRow(){if(this.options.rowAdd!==!0)return Promise.resolve();const t=this.getRowFragment();if(!t)return Promise.reject(new Error("Row fragment not found."));const e=[],r=t.clone();return e.push(t.getParent().insertAfter(r,t)),e.push(P.evaluateAll(r)),e.push(y.reset(r)),Promise.all(e).then(()=>{})}removeRow(){if(this.options.rowRemove!==!0)return Promise.resolve();const t=this.getRowFragment();if(!t)return Promise.reject(new Error("Row fragment not found."));const e=t.getParent();return e&&e.getChildElementFragments().filter(s=>!s.hasAttribute(`${u.prefix}each-before`)&&!s.hasAttribute(`${u.prefix}each-after`)).length<=1?Promise.resolve():t.remove()}movePrevRow(){if(this.options.rowMovePrev!==!0)return Promise.resolve();const t=this.getRowFragment();if(!t)return Promise.reject(new Error("Row fragment not found."));const e=t.getPrevious();if(!e)return Promise.resolve();const r=t.getParent();return r?r.insertBefore(t,e):Promise.resolve()}moveNextRow(){if(this.options.rowMoveNext!==!0)return Promise.resolve();const t=this.getRowFragment();if(!t)return Promise.reject(new Error("Row fragment not found."));const e=t.getNext();if(!e)return Promise.resolve();const r=t.getParent();return r?r.insertAfter(t,e):Promise.resolve()}};c.DATA_PLACEHOLDER_REGEX=/\{\{\{([\s\S]+?)\}\}\}|\{\{([\s\S]+?)\}\}/g,c.SINGLE_PLACEHOLDER_REGEX=/^(\{\{\{[\s\S]+?\}\}\}|\{\{[\s\S]+?\}\})$/,c.RUNNING_CLICK_TARGETS=new WeakSet;let U=c;class dt{static readParams(){const t={},e=window.location.search;return new URLSearchParams(e).forEach((s,n)=>{t[n]=s}),t}}class pt{static async load(t,e){let r;try{r=await fetch(t,e)}catch(n){throw f.error("[Haori]","Failed to fetch import source:",t,n),new Error(`Failed to fetch: ${t}`)}if(!r.ok){const n=`${r.status} ${r.statusText}`;throw f.error("[Haori]","Import HTTP error:",t,n),new Error(`Failed to load ${t}: ${n}`)}let s;try{s=await r.text()}catch(n){throw f.error("[Haori]","Failed to read response text:",t,n),new Error(`Failed to read response from: ${t}`)}try{const i=new DOMParser().parseFromString(s,"text/html");return i&&i.body?i.body.innerHTML:(f.warn("[Haori]","No body found in imported document:",t),s)}catch(n){return f.error("[Haori]","Failed to parse imported HTML:",t,n),s}}}const g=class g{static isDeferredAttributeName(t){return g.DEFERRED_ATTRIBUTE_SUFFIXES.some(e=>t===`${u.prefix}${e}`)}static isEvaluateAllExcludedAttributeName(t){return g.EVALUATE_ALL_EXCLUDED_ATTRIBUTE_SUFFIXES.some(e=>t===`${u.prefix}${e}`)}static shouldReevaluateAttribute(t,e){return e!==null&&!g.isEvaluateAllExcludedAttributeName(t)&&g.ATTRIBUTE_PLACEHOLDER_REGEX.test(e)}static getAliasedAttributeName(t){const e=`${u.prefix}${g.ATTRIBUTE_ALIAS_SUFFIX}`;return!t.startsWith(e)||t.length<=e.length?null:t.slice(e.length)}static isAliasedAttributeReflection(t,e){const r=w.get(t);return r instanceof M?r.hasAttribute(`${u.prefix}${g.ATTRIBUTE_ALIAS_SUFFIX}${e}`):!1}static reevaluateInterpolatedAttributes(t){let e=Promise.resolve();for(const r of t.getAttributeNames()){const s=t.getRawAttribute(r);g.shouldReevaluateAttribute(r,s)&&(e=e.then(()=>g.setAttribute(t.getTarget(),r,s)))}return e.then(()=>{})}static scan(t){const e=w.get(t);if(!e)return Promise.resolve();t.parentNode&&(w.get(t.parentNode)?.isMounted()||document.body.contains(t)?e.setMounted(!0):e.setMounted(!1));let r=Promise.resolve();const s=new Set;for(const n of g.PRIORITY_ATTRIBUTE_SUFFIXES){const i=u.prefix+n;e.hasAttribute(i)&&(r=r.then(()=>g.setAttribute(e.getTarget(),i,e.getRawAttribute(i))),s.add(i))}for(const n of e.getAttributeNames()){if(s.has(n)||g.isDeferredAttributeName(n))continue;const i=e.getRawAttribute(n);i!==null&&(r=r.then(()=>g.setAttribute(e.getTarget(),n,i)))}for(const n of g.DEFERRED_ATTRIBUTE_SUFFIXES){const i=u.prefix+n;e.hasAttribute(i)&&(r=r.then(()=>g.setAttribute(e.getTarget(),i,e.getRawAttribute(i))),s.add(i))}return r.then(()=>{const n=[];return e.getChildren().forEach(i=>{i instanceof M?n.push(g.scan(i.getTarget())):i instanceof C&&n.push(g.evaluateText(i))}),Promise.all(n).then(()=>{})}).then(()=>{})}static setAttribute(t,e,r,s=!1){const n=w.get(t),i=g.getAliasedAttributeName(e);if(i!==null)return r===null?n.removeAliasedAttribute(e,i):n.setAliasedAttribute(e,i,r,s);const a=[];switch(e){case`${u.prefix}bind`:{r===null?(n.clearBindingDataCache(),n.setBindingData({})):n.setBindingData(g.parseDataBind(r));break}case`${u.prefix}if`:a.push(g.evaluateIf(n));break;case`${u.prefix}each`:a.push(g.evaluateEach(n));break;case`${u.prefix}fetch`:a.push(new U(n,null).run().then(()=>{}));break;case`${u.prefix}import`:{if(typeof r=="string"){const o=n.getTarget(),l=performance.now();o.setAttribute(`${u.prefix}importing`,""),N.importStart(o,r),a.push(pt.load(r).then(p=>{const m=new TextEncoder().encode(p).length;return F.enqueue(()=>{o.innerHTML=p}).then(()=>{if(o.removeAttribute(`${u.prefix}importing`),N.importEnd(o,r,m,l),!document.body.hasAttribute("data-haori-ready")){const v=[];return o.childNodes.forEach(T=>{const h=w.get(T);h instanceof M?v.push(g.scan(h.getTarget())):h instanceof C&&v.push(g.evaluateText(h))}),Promise.all(v).then(()=>{})}})}).catch(p=>{o.removeAttribute(`${u.prefix}importing`),N.importError(o,r,p),f.error("[Haori]","Failed to import HTML:",r,p)}))}break}case`${u.prefix}url-param`:{const o=n.getAttribute(`${u.prefix}url-arg`),l=dt.readParams();if(o===null)a.push(g.setBindingData(t,l));else{const p=n.getRawBindingData()||{};p[String(o)]=l,a.push(g.setBindingData(t,p))}break}}return r===null?a.push(n.removeAttribute(e)):a.push(n.setAttribute(e,r,s)),Promise.all(a).then(()=>{})}static setBindingData(t,e){const r=w.get(t),s=r.getRawBindingData();r.setBindingData(e);let n=r.setAttribute(`${u.prefix}bind`,JSON.stringify(e));if(t.tagName==="FORM"){const i=r.getAttribute(`${u.prefix}form-arg`),a=i&&e[String(i)]&&typeof e[String(i)]=="object"&&!Array.isArray(e[String(i)])?e[String(i)]:i?{}:e;n=n.then(()=>y.syncValues(r,a))}return n=n.then(()=>g.evaluateAll(r)),N.bindChange(t,s,e,"manual"),n.then(()=>{})}static parseDataBind(t){if(t.startsWith("{")||t.startsWith("["))try{return JSON.parse(t)}catch(e){return f.error("[Haori]","Invalid JSON in data-bind:",e),{}}else{const e=new URLSearchParams(t),r={};for(const[s,n]of e.entries())r[s]!==void 0?Array.isArray(r[s])?r[s].push(n):r[s]=[r[s],n]:r[s]=n;return r}}static addNode(t,e){const r=w.get(t);if(r.isSkipMutationNodes())return;const s=w.get(e.nextSibling),n=w.get(e);n&&(r.insertBefore(n,s),n instanceof M?g.scan(n.getTarget()):n instanceof C&&g.evaluateText(n))}static removeNode(t){const e=w.get(t);if(e){const r=e.getParent();if(r&&r.isSkipMutationNodes())return;e.remove()}}static changeText(t,e){const r=w.get(t);r&&r.setContent(e)}static changeValue(t,e){const r=w.get(t);if(r.getValue()===e)return Promise.resolve();const s=[];s.push(r.setValue(e));const n=g.getFormFragment(r);if(n){const i=y.getValues(n),a=n.getAttribute(`${u.prefix}form-arg`);let o;a?(o=n.getRawBindingData(),o||(o={}),o[String(a)]=i):o=i,s.push(g.setBindingData(n.getTarget(),o))}return Promise.all(s).then(()=>{})}static getFormFragment(t){if(t.getTarget()instanceof HTMLFormElement)return t;const e=t.getParent();return e?g.getFormFragment(e):null}static evaluateAll(t){const e=[];return e.push(g.reevaluateInterpolatedAttributes(t)),t.hasAttribute(`${u.prefix}if`)&&e.push(g.evaluateIf(t)),t.hasAttribute(`${u.prefix}each`)?Promise.all(e).then(()=>g.evaluateEach(t)):(t.getChildren().forEach(r=>{r instanceof M?e.push(g.evaluateAll(r)):r instanceof C&&e.push(g.evaluateText(r))}),Promise.all(e).then(()=>{}))}static evaluateText(t){return t.evaluate()}static evaluateIf(t){const e=[],r=t.getAttribute(`${u.prefix}if`);if(r===!1||r===void 0||r===null||Number.isNaN(r))e.push(t.hide().then(()=>{N.hide(t.getTarget())}));else{const s=[];t.getChildren().forEach(n=>{n instanceof M?s.push(g.evaluateAll(n)):n instanceof C&&s.push(g.evaluateText(n))}),e.push(t.show().then(()=>{N.show(t.getTarget())})),e.push(Promise.all(s).then(()=>{}))}return Promise.all(e).then(()=>{})}static evaluateEach(t){if(!t.isVisible()||!t.isMounted())return Promise.resolve();let e=t.getTemplate();if(e===null){let s=!1;t.getChildren().forEach(i=>{if(!s&&i instanceof M){if(i.hasAttribute(`${u.prefix}each-before`)||i.hasAttribute(`${u.prefix}each-after`))return;e=i.clone(),t.setTemplate(e),s=!0,t.removeChild(i);const a=i.getTarget();a.parentNode&&a.parentNode.removeChild(a),i.setMounted(!1)}});const n=t.getAttribute(`${u.prefix}each`);return Array.isArray(n)?this.updateDiff(t,n):(f.error("[Haori]","Invalid each attribute:",n),Promise.reject(new Error("Invalid each attribute.")))}const r=t.getAttribute(`${u.prefix}each`);return Array.isArray(r)?this.updateDiff(t,r):(f.error("[Haori]","Invalid each attribute:",r),Promise.reject(new Error("Invalid each attribute.")))}static updateDiff(t,e){const r=t.getTemplate();if(r===null)return f.error("[Haori]","Template is not set for each element."),Promise.resolve();let s=t.getAttribute(`${u.prefix}each-index`);s&&(s=String(s));const n=t.getAttribute(`${u.prefix}each-key`),i=t.getAttribute(`${u.prefix}each-arg`),a=new Map,o=[];e.forEach((h,d)=>{const b=g.createListKey(h,n?String(n):null,d);o.push(b),a.set(b,{item:h,itemIndex:d})});const l=[];let p=t.getChildren().filter(h=>h instanceof M).filter(h=>!h.hasAttribute(`${u.prefix}each-before`)&&!h.hasAttribute(`${u.prefix}each-after`));p=p.filter(h=>o.indexOf(String(h.getListKey()))===-1?(l.push(h.remove()),!1):!0);const m=p.map(h=>h.getListKey()),v=t.getChildren().filter(h=>h instanceof M).filter(h=>h.hasAttribute(`${u.prefix}each-before`)).length;let T=Promise.resolve();return o.forEach((h,d)=>{const b=m.indexOf(h),{item:E,itemIndex:A}=a.get(h);let x;if(b!==-1)x=p[b],T=T.then(()=>g.updateRowFragment(x,E,s,A,i?String(i):null,h).then(()=>g.evaluateAll(x)).then(()=>g.scheduleEvaluateAll(x)));else{x=r.clone();const tt=v+d;T=T.then(()=>g.updateRowFragment(x,E,s,A,i?String(i):null,h).then(()=>t.insertBefore(x,t.getChildren()[tt]||null).then(()=>g.evaluateAll(x)).then(()=>g.scheduleEvaluateAll(x))))}}),Promise.all(l).then(()=>T).then(()=>{const h=o.filter(A=>A!==null),d=m.filter(A=>A!==null),b=h.filter(A=>!d.includes(A)),E=d.filter(A=>!h.includes(A));N.eachUpdate(t.getTarget(),b,E,h)})}static createListKey(t,e,r){let s;if(typeof t=="object"&&t!==null)if(e){const n=t[e];n==null?s=`__index_${r}`:typeof n=="object"?s=JSON.stringify(n):s=String(n)}else s=`__index_${r}`;else s=String(t);return s}static updateRowFragment(t,e,r,s,n,i){let a=e;if(typeof e=="object"&&e!==null)a={...e},r&&(a[r]=s),n&&(a={[n]:a});else if(n)a={[n]:e},r&&(a[r]=s);else return f.error("[Haori]",`Primitive value requires '${u.prefix}each-arg' attribute: ${e}`),Promise.resolve();return t.setListKey(i),t.setBindingData(a),t.setAttribute(`${u.prefix}row`,i)}static scheduleEvaluateAll(t){setTimeout(()=>{g.evaluateAll(t)},100)}};g.ATTRIBUTE_ALIAS_SUFFIX="attr-",g.PRIORITY_ATTRIBUTE_SUFFIXES=["bind","if","each"],g.DEFERRED_ATTRIBUTE_SUFFIXES=["fetch","url-param"],g.EVALUATE_ALL_EXCLUDED_ATTRIBUTE_SUFFIXES=["bind","if","each","fetch","import","url-param"],g.ATTRIBUTE_PLACEHOLDER_REGEX=/\{\{\{[\s\S]+?\}\}\}|\{\{[\s\S]+?\}\}/;let P=g;const J=class J{constructor(t=document){this.onClick=e=>this.delegate(e,"click"),this.onChange=e=>this.delegate(e,"change"),this.onLoadCapture=e=>this.delegate(e,"load"),this.onWindowLoad=()=>{const e=document.documentElement,r=w.get(e);r&&new U(r,"load").run()},this.onPopstate=e=>{const r=e.state;!r||r[J.HISTORY_STATE_KEY]!==!0||location.reload()},this.root=t}start(){this.root.addEventListener("click",this.onClick),this.root.addEventListener("change",this.onChange),this.root.addEventListener("load",this.onLoadCapture,!0),window.addEventListener("load",this.onWindowLoad,{once:!0}),window.addEventListener("popstate",this.onPopstate)}stop(){this.root.removeEventListener("click",this.onClick),this.root.removeEventListener("change",this.onChange),this.root.removeEventListener("load",this.onLoadCapture,!0),window.removeEventListener("load",this.onWindowLoad),window.removeEventListener("popstate",this.onPopstate)}delegate(t,e){const r=this.getElementFromTarget(t.target,e);if(!r)return;const s=w.get(r);s&&(e==="change"&&s instanceof M&&s.syncValue(),new U(s,e).run().catch(n=>{f.error("[Haori]","Procedure execution error:",n)}))}getElementFromTarget(t,e){if(!t)return null;if(t instanceof HTMLElement)return e==="click"?this.findClickableElement(t):t;if(t instanceof Node){const r=t.parentElement;return r?e==="click"?this.findClickableElement(r):r:null}return null}findClickableElement(t){let e=t;for(;e;){if(e.getAttributeNames().some(r=>r.startsWith("data-click-")))return e;e=e.parentElement}return null}};J.HISTORY_STATE_KEY="__haoriHistoryState__";let Z=J;const S=class S{static syncTree(t){(t instanceof Element||t instanceof DocumentFragment)&&(t instanceof HTMLElement&&S.syncElement(t),t.querySelectorAll("*").forEach(e=>{S.syncElement(e)}))}static syncElement(t){const e=S.registrations.get(t),r=w.get(t);if(!r||!S.shouldObserve(r)){e&&(e.observer.disconnect(),S.registrations.delete(t));return}if(typeof IntersectionObserver>"u")return;const s=S.resolveRoot(r),n=S.resolveRootMargin(r),i=S.resolveThreshold(r),a=r.hasAttribute(`${u.prefix}intersect-once`);if(e&&e.observer.root===s&&e.observer.rootMargin===n&&S.sameThreshold(e.observer.thresholds,i)&&e.once===a){e.fragment=r;return}e&&(e.observer.disconnect(),S.registrations.delete(t));const o=new IntersectionObserver(l=>{const p=S.registrations.get(t);p&&l.forEach(m=>{!m.isIntersecting||p.running||S.isDisabled(p.fragment)||(p.running=!0,new U(p.fragment,"intersect").runWithResult().then(v=>{v&&p.once&&(p.observer.disconnect(),S.registrations.delete(t))}).catch(v=>{f.error("[Haori]","Intersect procedure execution error:",v)}).finally(()=>{const v=S.registrations.get(t);v&&(v.running=!1)}))})},{root:s,rootMargin:n,threshold:i});o.observe(t),S.registrations.set(t,{fragment:r,observer:o,once:a,running:!1})}static cleanupTree(t){if(t instanceof HTMLElement){const e=S.registrations.get(t);e&&(e.observer.disconnect(),S.registrations.delete(t))}(t instanceof Element||t instanceof DocumentFragment)&&t.querySelectorAll("*").forEach(e=>{const r=S.registrations.get(e);r&&(r.observer.disconnect(),S.registrations.delete(e))})}static disconnectAll(){S.registrations.forEach(t=>{t.observer.disconnect()}),S.registrations.clear()}static shouldObserve(t){return t.getAttributeNames().some(e=>{if(!e.startsWith(`${u.prefix}intersect-`))return!1;const r=e.slice(`${u.prefix}intersect-`.length);return!S.CONFIG_KEYS.has(r)})}static resolveRoot(t){const e=`${u.prefix}intersect-root`;if(!t.hasAttribute(e))return null;const r=t.getAttribute(e);if(typeof r!="string"||r.trim()==="")return null;const s=document.querySelector(r);return s instanceof HTMLElement?s:(f.error("[Haori]",`Intersect root element not found: ${r}`),null)}static resolveRootMargin(t){const e=`${u.prefix}intersect-root-margin`,r=t.getAttribute(e);return r===null||r===!1||r===""?"0px":String(r)}static resolveThreshold(t){const e=`${u.prefix}intersect-threshold`,r=t.getAttribute(e),s=typeof r=="number"?r:Number.parseFloat(String(r??0));return Number.isNaN(s)?0:Math.min(1,Math.max(0,s))}static isDisabled(t){const e=`${u.prefix}intersect-disabled`,r=t.getAttribute(e);if(r===null||r===!1)return!1;if(typeof r=="boolean")return r;const s=String(r).trim().toLowerCase();return s!==""&&s!=="false"&&s!=="0"}static sameThreshold(t,e){return t.length===1&&t[0]===e}};S.CONFIG_KEYS=new Set(["root","root-margin","threshold","disabled","once"]),S.registrations=new Map;let q=S;const $=class ${static async init(){if($._initialized)return;$._initialized=!0;const t=await Promise.allSettled([P.scan(document.head),P.scan(document.body)]),[e,r]=t;e.status!=="fulfilled"&&f.error("[Haori]","Failed to build head fragment:",e.reason),r.status!=="fulfilled"&&f.error("[Haori]","Failed to build body fragment:",r.reason),await F.wait(),document.body.setAttribute("data-haori-ready",""),$.observe(document.head),$.observe(document.body),new Z().start(),q.syncTree(document.body)}static observe(t){new MutationObserver(async r=>{for(const s of r)try{switch(s.type){case"attributes":{f.info("[Haori]","Attribute changed:",s.target,s.attributeName);const n=s.target;if(s.attributeName&&P.isAliasedAttributeReflection(n,s.attributeName))break;P.setAttribute(n,s.attributeName,n.getAttribute(s.attributeName),!0),q.syncElement(n);break}case"childList":{f.info("[Haori]","Child list changed:",Array.from(s.removedNodes).map(n=>n.nodeName),Array.from(s.addedNodes).map(n=>n.nodeName)),Array.from(s.removedNodes).forEach(n=>{q.cleanupTree(n),P.removeNode(n)}),Array.from(s.addedNodes).forEach(n=>{n.parentElement instanceof HTMLElement&&(P.addNode(n.parentElement,n),q.syncTree(n))});break}case"characterData":{f.info("[Haori]","Character data changed:",s.target,s.target.textContent),s.target instanceof Text||s.target instanceof Comment?P.changeText(s.target,s.target.textContent):f.warn("[Haori]","Unsupported character data type:",s.target);break}default:f.warn("[Haori]","Unknown mutation type:",s.type);continue}}catch(n){f.error("[Haori]","Error processing mutation:",n)}}).observe(t,{childList:!0,subtree:!0,attributes:!0,characterData:!0}),f.info("[Haori]","Observer initialized for",t)}};$._initialized=!1;let K=$;document.readyState==="loading"?document.addEventListener("DOMContentLoaded",K.init):K.init();const gt="0.4.13";return k.Core=P,k.Env=u,k.Form=y,k.Fragment=w,k.Haori=j,k.Log=f,k.Queue=F,k.default=j,k.version=gt,Object.defineProperties(k,{__esModule:{value:!0},[Symbol.toStringTag]:{value:"Module"}}),k}({});
17
17
  //# sourceMappingURL=haori.iife.js.map