haori 0.1.0 → 0.1.2

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 (52) hide show
  1. package/README.ja.md +26 -15
  2. package/README.md +26 -15
  3. package/dist/haori.cjs.js +10 -9
  4. package/dist/haori.cjs.js.map +1 -1
  5. package/dist/haori.es.js +1194 -751
  6. package/dist/haori.es.js.map +1 -1
  7. package/dist/haori.iife.js +9 -8
  8. package/dist/haori.iife.js.map +1 -1
  9. package/dist/index.d.ts +10 -2
  10. package/dist/package.json +70 -0
  11. package/dist/src/core.d.ts.map +1 -1
  12. package/dist/src/core.js +31 -26
  13. package/dist/src/core.js.map +1 -1
  14. package/dist/src/expression.d.ts +92 -0
  15. package/dist/src/expression.d.ts.map +1 -1
  16. package/dist/src/expression.js +475 -2
  17. package/dist/src/expression.js.map +1 -1
  18. package/dist/src/fragment.d.ts +9 -1
  19. package/dist/src/fragment.d.ts.map +1 -1
  20. package/dist/src/fragment.js +50 -6
  21. package/dist/src/fragment.js.map +1 -1
  22. package/dist/src/index.d.ts +1 -1
  23. package/dist/src/index.js +1 -1
  24. package/dist/src/observer.d.ts +1 -0
  25. package/dist/src/observer.d.ts.map +1 -1
  26. package/dist/src/observer.js +5 -0
  27. package/dist/src/observer.js.map +1 -1
  28. package/dist/tests/data-each-table.test.js +5 -20
  29. package/dist/tests/data-each-table.test.js.map +1 -1
  30. package/dist/tests/data-fetch-tbody-dom.test.d.ts +2 -0
  31. package/dist/tests/data-fetch-tbody-dom.test.d.ts.map +1 -0
  32. package/dist/tests/data-fetch-tbody-dom.test.js +99 -0
  33. package/dist/tests/data-fetch-tbody-dom.test.js.map +1 -0
  34. package/dist/tests/event.test.js +3 -2
  35. package/dist/tests/event.test.js.map +1 -1
  36. package/dist/tests/expression.test.js +92 -0
  37. package/dist/tests/expression.test.js.map +1 -1
  38. package/dist/tests/form.test.js +35 -34
  39. package/dist/tests/form.test.js.map +1 -1
  40. package/dist/tests/fragment.test.js +51 -1
  41. package/dist/tests/fragment.test.js.map +1 -1
  42. package/dist/tests/helpers/async.d.ts +19 -0
  43. package/dist/tests/helpers/async.d.ts.map +1 -0
  44. package/dist/tests/helpers/async.js +31 -0
  45. package/dist/tests/helpers/async.js.map +1 -0
  46. package/dist/tests/procedure-action-operations.test.js +15 -12
  47. package/dist/tests/procedure-action-operations.test.js.map +1 -1
  48. package/dist/tests/row-move.test.js +36 -13
  49. package/dist/tests/row-move.test.js.map +1 -1
  50. package/dist/tests/row-operations.test.js +21 -20
  51. package/dist/tests/row-operations.test.js.map +1 -1
  52. package/package.json +70 -68
package/README.ja.md CHANGED
@@ -2,7 +2,7 @@
2
2
 
3
3
  Haori.js は、HTML 属性を中心にして動的な UI を実現する軽量なライブラリです。JavaScript をほとんど書かずに、データバインディング、条件分岐、繰り返し処理、フォームの双方向バインディング、サーバー通信などを HTML 属性で宣言できます。
4
4
 
5
- バージョン: 0.1.0
5
+ バージョン: 0.1.2
6
6
 
7
7
  ---
8
8
 
@@ -41,9 +41,11 @@ npm install haori
41
41
  CDN:
42
42
 
43
43
  ```html
44
- <script src="https://cdn.jsdelivr.net/npm/haori@0.1.0/dist/haori.iife.js"></script>
44
+ <script src="https://cdn.jsdelivr.net/npm/haori/dist/haori.iife.js"></script>
45
45
  ```
46
46
 
47
+ この CDN URL は npm に公開済みの最新バージョンを参照します。
48
+
47
49
  ES Module:
48
50
 
49
51
  ```js
@@ -62,7 +64,7 @@ HTML だけで簡単に使えます。以下は最小の例です。
62
64
  <head>
63
65
  <meta charset="utf-8">
64
66
  <title>Haori サンプル</title>
65
- <script src="https://cdn.jsdelivr.net/npm/haori@0.1.0/dist/haori.iife.js"></script>
67
+ <script src="https://cdn.jsdelivr.net/npm/haori/dist/haori.iife.js"></script>
66
68
  </head>
67
69
  <body>
68
70
  <div data-bind='{"name":"太郎"}'>
@@ -92,13 +94,15 @@ Haori.mount(document.body, { items: [ { name: 'りんご' }, { name: 'みかん'
92
94
  - `data-import` — 外部 HTML を読み込んで挿入
93
95
  - `data-url-param` — URL のクエリパラメータをバインディングに取り込む
94
96
 
97
+ テンプレート式では、プロパティアクセス、動的インデックスを含むブラケットアクセス、optional chaining、三項演算子、配列 `map` / `filter` のアロー関数、spread を伴う呼び出しなどの安全な構文を利用できます。一方で、グローバルオブジェクト、`eval` や `arguments`、`constructor`、`__proto__`、`prototype`、`Reflect` などの脱出経路は使用できません。
98
+
95
99
  詳しい使い方や多数のサンプルについては、公式ドキュメントを参照してください。
96
100
 
97
101
  ---
98
102
 
99
103
  ## 公開・ビルド手順(パッケージ作成)
100
104
 
101
- 開発環境でのビルドと公開の基本手順を示します。
105
+ ローカル確認とリリース準備の基本手順を示します。
102
106
 
103
107
  1. 依存インストール
104
108
 
@@ -106,18 +110,17 @@ Haori.mount(document.body, { items: [ { name: 'りんご' }, { name: 'みかん'
106
110
  npm install
107
111
  ```
108
112
 
109
- 2. 型チェックとビルド
113
+ 2. 型チェックとテスト
110
114
 
111
115
  ```bash
112
116
  npm run compile
113
- # または
114
- npm run build
117
+ npm run test
115
118
  ```
116
119
 
117
- 3. テスト
120
+ 3. 配布物のビルド
118
121
 
119
122
  ```bash
120
- npm run test
123
+ npm run build
121
124
  ```
122
125
 
123
126
  4. バージョン更新
@@ -126,14 +129,22 @@ npm run test
126
129
  npm version patch
127
130
  ```
128
131
 
129
- 5. npm ログインおよび公開
132
+ 5. 版数更新を push し、対象タグから GitHub Release を公開
130
133
 
131
- ```bash
132
- npm login
133
- npm publish --access public
134
- ```
134
+ このリポジトリの npm 公開は GitHub Actions で行います。現在の workflow は `release.published` を契機に起動し、パッケージをビルドしたうえで `NPM_TOKEN` を使って npm へ公開し、あわせて `dist.zip` を GitHub Release のアーティファクトとして添付します。
135
+
136
+ 必要な前提条件:
137
+
138
+ - GitHub リポジトリの Secrets に `NPM_TOKEN` が設定されていること
139
+ - 対象バージョンのタグから Release を `published` 状態で公開すること
140
+
141
+ 公開前の推奨確認:
142
+
143
+ - `npm run test`
144
+ - `npm run build`
145
+ - `npm pack --dry-run`
135
146
 
136
- 注意: `package.json` の `name`, `version`, `description`, `repository`, `license` が正しいことを確認してください。公開対象ファイルは `files` フィールドおよび `.npmignore` に従います。
147
+ 注意: `package.json` の `name`, `version`, `description`, `repository`, `license` が正しいことを確認してください。公開対象ファイルは `files` フィールドに従います。
137
148
 
138
149
  ---
139
150
 
package/README.md CHANGED
@@ -2,7 +2,7 @@
2
2
 
3
3
  Haori.js is a lightweight, HTML-first UI library that enables dynamic user interfaces primarily through HTML attributes. It lets you declare data bindings, conditional rendering, list rendering, form two-way binding, server fetches, and HTML imports without writing much JavaScript.
4
4
 
5
- Version: 0.1.0
5
+ Version: 0.1.2
6
6
 
7
7
  ---
8
8
 
@@ -41,9 +41,11 @@ npm install haori
41
41
  Via CDN:
42
42
 
43
43
  ```html
44
- <script src="https://cdn.jsdelivr.net/npm/haori@0.1.0/dist/haori.iife.js"></script>
44
+ <script src="https://cdn.jsdelivr.net/npm/haori/dist/haori.iife.js"></script>
45
45
  ```
46
46
 
47
+ This CDN URL follows the latest published npm release.
48
+
47
49
  ES Module import:
48
50
 
49
51
  ```js
@@ -62,7 +64,7 @@ You can use Haori with plain HTML. Minimal example:
62
64
  <head>
63
65
  <meta charset="utf-8">
64
66
  <title>Haori Sample</title>
65
- <script src="https://cdn.jsdelivr.net/npm/haori@0.1.0/dist/haori.iife.js"></script>
67
+ <script src="https://cdn.jsdelivr.net/npm/haori/dist/haori.iife.js"></script>
66
68
  </head>
67
69
  <body>
68
70
  <div data-bind='{"name":"Taro"}'>
@@ -92,13 +94,15 @@ Haori.mount(document.body, { items: [ { name: 'apple' }, { name: 'orange' } ] })
92
94
  - `data-import` — load external HTML and insert it
93
95
  - `data-url-param` — import URL query parameters into bindings
94
96
 
97
+ Template expressions support safe JavaScript-like syntax such as property access, bracket access with dynamic indexes, optional chaining, ternary expressions, and method chains including array `map`/`filter` with arrow functions and spread calls. Access to global objects, `eval` or `arguments`, and prototype escape paths such as `constructor`, `__proto__`, `prototype`, or `Reflect` is blocked.
98
+
95
99
  For detailed usage and many examples, see the official documentation.
96
100
 
97
101
  ---
98
102
 
99
103
  ## Build & publish (packaging)
100
104
 
101
- Basic build and publish steps in a development environment:
105
+ Basic local verification and release preparation steps:
102
106
 
103
107
  1. Install dependencies
104
108
 
@@ -106,18 +110,17 @@ Basic build and publish steps in a development environment:
106
110
  npm install
107
111
  ```
108
112
 
109
- 2. Type-check and build
113
+ 2. Type-check and test
110
114
 
111
115
  ```bash
112
116
  npm run compile
113
- # or
114
- npm run build
117
+ npm run test
115
118
  ```
116
119
 
117
- 3. Run tests
120
+ 3. Build release artifacts
118
121
 
119
122
  ```bash
120
- npm run test
123
+ npm run build
121
124
  ```
122
125
 
123
126
  4. Bump version
@@ -126,14 +129,22 @@ npm run test
126
129
  npm version patch
127
130
  ```
128
131
 
129
- 5. Login to npm and publish
132
+ 5. Push the version update and create a GitHub Release for the new tag
130
133
 
131
- ```bash
132
- npm login
133
- npm publish --access public
134
- ```
134
+ Publishing to npm is handled by GitHub Actions when a GitHub Release is published. This repository currently uses release workflows that trigger on `release.published`, build the package, publish it to npm with `NPM_TOKEN`, and upload `dist.zip` to the release artifacts.
135
+
136
+ Required repository setup:
137
+
138
+ - `NPM_TOKEN` must be configured in GitHub repository secrets.
139
+ - The release must be published from the target version tag.
140
+
141
+ Recommended pre-release checks:
142
+
143
+ - `npm run test`
144
+ - `npm run build`
145
+ - `npm pack --dry-run`
135
146
 
136
- Make sure `package.json` fields `name`, `version`, `description`, `repository` and `license` are correct. Files published to npm are controlled by the `files` field in `package.json` and `.npmignore`.
147
+ Make sure `package.json` fields `name`, `version`, `description`, `repository` and `license` are correct. Files published to npm are controlled by the `files` field in `package.json`.
137
148
 
138
149
  ---
139
150
 
package/dist/haori.cjs.js CHANGED
@@ -1,13 +1,14 @@
1
- "use strict";Object.defineProperties(exports,{__esModule:{value:!0},[Symbol.toStringTag]:{value:"Module"}});const C=class C{static isEnabled(){return C.devMode}static enable(){C.devMode=!0}static disable(){C.devMode=!1}static set(t){C.devMode=t}};C.devMode=!1;let D=C;const k=class k{static detect(){try{const t=document.currentScript||document.querySelector('script[src*="haori"]');if(t instanceof HTMLScriptElement){const s=t.getAttribute("data-prefix")||k._prefix;k._prefix=s.endsWith("-")?s:s+"-"}if(t instanceof HTMLScriptElement&&t.hasAttribute(`${k._prefix}dev`)){D.set(!0);return}const e=window.location.hostname;if(e==="localhost"||e.endsWith(".localhost")||e==="127.0.0.1"||e==="::1"||e.endsWith(".local")){D.set(!0);return}D.set(!1)}catch{}}static get prefix(){return k._prefix}};k._prefix="data-";let c=k;document.readyState==="loading"?document.addEventListener("DOMContentLoaded",c.detect):c.detect();class h{static info(t,...e){D.isEnabled()&&console.log&&console.log(t,...e)}static warn(t,...e){D.isEnabled()&&console.warn&&console.warn(t,...e)}static error(t,...e){console.error(t,...e)}}class X{constructor(){this.MAX_BUDGET=8,this.queue=[],this.processing=!1}enqueue(t,e=!1){let s,i;const r=new Promise((a,u)=>{s=a,i=u}),n={task:t,timestamp:performance.now(),promise:r,resolve:s,reject:i};return e?this.queue.unshift(n):this.queue.push(n),this.scheduleProcessing(),r}async processQueue(){if(!(this.processing||this.queue.length===0)){this.processing=!0;try{const t=performance.now();for(;this.queue.length>0;){const e=this.queue.shift();if(!e)return;try{const s=await e.task();e.resolve(s)}catch(s){e.reject(s),h.error("[Haori]",`Task ${e.timestamp} failed:`,s)}if(performance.now()-t>this.MAX_BUDGET)break}}catch(t){h.error("[Haori]","Error processing queue:",t)}finally{this.processing=!1,this.queue.length>0&&this.scheduleProcessing()}}}scheduleProcessing(){this.processing||(typeof requestAnimationFrame<"u"?requestAnimationFrame(()=>{this.processQueue()}):setTimeout(()=>{this.processQueue()},16))}async wait(){if(this.queue.length===0&&!this.processing)return;const t=this.queue.map(e=>e.promise);t.length>0&&await Promise.allSettled(t)}}const K=class K{static enqueue(t,e=!1){return this.ASYNC_QUEUE.enqueue(t,e)}static wait(){return this.ASYNC_QUEUE.wait()}};K.ASYNC_QUEUE=new X;let v=K;class M{static dialog(t){return v.enqueue(()=>{window.alert(t)},!0)}static async toast(t,e){const s=document.createElement("div");s.className=`haori-toast haori-toast-${e}`,s.textContent=t,s.setAttribute("popover","manual"),s.setAttribute("role","status"),s.setAttribute("aria-live","polite"),document.body.appendChild(s),s.showPopover(),setTimeout(()=>{try{s.hidePopover()}finally{s.remove()}},3e3)}static confirm(t){return v.enqueue(()=>window.confirm(t),!0)}static openDialog(t){return v.enqueue(()=>{t instanceof HTMLDialogElement?t.showModal():h.error("[Haori]","Element is not a dialog: ",t)},!0)}static closeDialog(t){return v.enqueue(()=>{t instanceof HTMLDialogElement?t.close():h.error("[Haori]","Element is not a dialog: ",t)},!0)}static addErrorMessage(t,e){return v.enqueue(()=>{if(t instanceof HTMLFormElement){t.setAttribute("data-message",e);return}if(t.parentElement){t.parentElement.setAttribute("data-message",e);return}t.setAttribute("data-message",e)},!0)}static clearMessages(t){return v.enqueue(()=>{t.removeAttribute("data-message"),t.querySelectorAll("[data-message]").forEach(e=>{e.removeAttribute("data-message")})},!0)}}class m{static getValues(t){const e={};return m.getPartValues(t,e)}static getPartValues(t,e){const s=t.getAttribute("name"),i=t.getAttribute(`${c.prefix}form-object`),r=t.getAttribute(`${c.prefix}form-list`);if(s){r?Array.isArray(e[String(s)])?e[String(s)].push(t.getValue()):e[String(s)]=[t.getValue()]:e[String(s)]=t.getValue(),i&&h.warn("Haori",`Element cannot have both ${c.prefix}form-object and name attributes.`);for(const n of t.getChildElementFragments())m.getPartValues(n,e)}else if(i){const n={};for(const a of t.getChildElementFragments())m.getPartValues(a,n);Object.keys(n).length>0&&(e[String(i)]=n),r&&h.warn("Haori",`Element cannot have both ${c.prefix}form-list and ${c.prefix}form-object attributes.`)}else if(r){const n=[];for(const a of t.getChildElementFragments()){const u={};m.getPartValues(a,u),Object.keys(u).length>0&&n.push(u)}n.length>0&&(e[String(r)]=n)}else for(const n of t.getChildElementFragments())m.getPartValues(n,e);return e}static setValues(t,e,s=!1){return m.setPartValues(t,e,null,s)}static setPartValues(t,e,s=null,i=!1){const r=[],n=t.getAttribute("name"),a=t.getAttribute(`${c.prefix}form-object`),u=t.getAttribute(`${c.prefix}form-list`),b=t.getAttribute(`${c.prefix}form-detach`);if(n){if(!b||i){const l=e[String(n)];u&&Array.isArray(l)&&s!==null?r.push(t.setValue(l[s])):typeof l=="string"||typeof l=="number"||typeof l=="boolean"||l===null?r.push(t.setValue(l)):r.push(t.setValue(String(l)))}}else if(a){const l=e[String(a)];if(l&&typeof l=="object")for(const E of t.getChildElementFragments())r.push(m.setPartValues(E,l,null,i))}else if(u){const l=e[String(u)];if(Array.isArray(l)){const E=t.getChildElementFragments();for(let o=0;o<E.length;o++){const d=E[o];l.length>o?r.push(m.setPartValues(d,l[o],o,i)):r.push(m.setPartValues(d,{},o,i))}}}else for(const l of t.getChildElementFragments())r.push(m.setPartValues(l,e,null,i));return Promise.all(r).then(()=>{})}static async reset(t){m.clearValues(t),await Promise.all([m.clearMessages(t),m.clearEachClones(t)]),await v.enqueue(()=>{const e=t.getTarget();if(e instanceof HTMLFormElement)e.reset();else{const s=e.parentElement;if(s){const i=e.nextElementSibling,r=document.createElement("form");r.appendChild(e),r.reset(),s.insertBefore(e,i)}}}),await N.evaluateAll(t)}static clearEachClones(t){const e=[],s=r=>{if(r.hasAttribute(`${c.prefix}each`))for(const n of r.getChildElementFragments()){const a=n.hasAttribute(`${c.prefix}each-before`),u=n.hasAttribute(`${c.prefix}each-after`);!a&&!u&&e.push(n.remove())}},i=r=>{s(r);for(const n of r.getChildElementFragments())i(n)};s(t);for(const r of t.getChildElementFragments())i(r);return Promise.all(e).then(()=>{})}static clearValues(t){t.clearValue();for(const e of t.getChildElementFragments())m.clearValues(e)}static clearMessages(t){return M.clearMessages(t.getTarget())}static addErrorMessage(t,e,s){const i=[],r=m.findFragmentsByKey(t,e);return r.forEach(n=>{i.push(M.addErrorMessage(n.getTarget(),s))}),r.length===0&&i.push(M.addErrorMessage(t.getTarget(),s)),Promise.all(i).then(()=>{})}static findFragmentsByKey(t,e){return m.findFragmentByKeyParts(t,e.split("."))}static findFragmentByKeyParts(t,e){const s=[],i=e[0];if(e.length==1&&t.getAttribute("name")===i&&s.push(t),t.hasAttribute(`${c.prefix}form-object`))e.length>1&&t.getAttribute(`${c.prefix}form-object`)===i&&t.getChildElementFragments().forEach(n=>{s.push(...m.findFragmentByKeyParts(n,e.slice(1)))});else if(t.hasAttribute(`${c.prefix}form-list`)){if(e.length>1){const r=t.getAttribute(`${c.prefix}form-list`),n=i.lastIndexOf("["),a=i.lastIndexOf("]");if(n!==-1&&a!==-1&&n<a){const u=i.substring(0,n);if(r===u){const b=i.substring(n+1,a),l=Number(b);if(isNaN(l))h.error("Haori",`Invalid index: ${i}`);else{const E=t.getChildElementFragments().filter(o=>o.hasAttribute(`${c.prefix}row`));l<E.length&&s.push(...m.findFragmentByKeyParts(E[l],e.slice(1)))}}}}}else t.getChildElementFragments().forEach(r=>{s.push(...m.findFragmentByKeyParts(r,e))});return s}static getFormFragment(t){if(t.getTarget()instanceof HTMLFormElement)return t;const s=t.getParent();return s?this.getFormFragment(s):null}}const P=class P{static evaluate(t,e={}){if(t.trim()==="")return h.warn("[Haori]",t,"Expression is empty"),null;if(this.containsDangerousPatterns(t))return h.warn("[Haori]",t,"Expression contains dangerous patterns"),null;if(this.containsForbiddenKeys(e))return h.warn("[Haori]",e,"Binded values contain forbidden keys"),null;const s=Object.keys(e).filter(n=>!this.FORBIDDEN_NAMES.includes(n)&&!this.STRICT_FORBIDDEN_NAMES.includes(n)).sort(),i=`${t}:${s.join(",")}`;let r=this.EXPRESSION_CACHE.get(i);if(!r){const n=`"use strict";
1
+ "use strict";Object.defineProperties(exports,{__esModule:{value:!0},[Symbol.toStringTag]:{value:"Module"}});const R=class R{static isEnabled(){return R.devMode}static enable(){R.devMode=!0}static disable(){R.devMode=!1}static set(t){R.devMode=t}};R.devMode=!1;let O=R;const D=class D{static detect(){try{const t=document.currentScript||document.querySelector('script[src*="haori"]');if(t instanceof HTMLScriptElement){const r=t.getAttribute("data-prefix")||D._prefix;D._prefix=r.endsWith("-")?r:r+"-"}if(t instanceof HTMLScriptElement&&t.hasAttribute(`${D._prefix}dev`)){O.set(!0);return}const e=window.location.hostname;if(e==="localhost"||e.endsWith(".localhost")||e==="127.0.0.1"||e==="::1"||e.endsWith(".local")){O.set(!0);return}O.set(!1)}catch{}}static get prefix(){return D._prefix}};D._prefix="data-";let c=D;document.readyState==="loading"?document.addEventListener("DOMContentLoaded",c.detect):c.detect();class h{static info(t,...e){O.isEnabled()&&console.log&&console.log(t,...e)}static warn(t,...e){O.isEnabled()&&console.warn&&console.warn(t,...e)}static error(t,...e){console.error(t,...e)}}class Y{constructor(){this.MAX_BUDGET=8,this.queue=[],this.processing=!1}enqueue(t,e=!1){let r,i;const s=new Promise((a,o)=>{r=a,i=o}),n={task:t,timestamp:performance.now(),promise:s,resolve:r,reject:i};return e?this.queue.unshift(n):this.queue.push(n),this.scheduleProcessing(),s}async processQueue(){if(!(this.processing||this.queue.length===0)){this.processing=!0;try{const t=performance.now();for(;this.queue.length>0;){const e=this.queue.shift();if(!e)return;try{const r=await e.task();e.resolve(r)}catch(r){e.reject(r),h.error("[Haori]",`Task ${e.timestamp} failed:`,r)}if(performance.now()-t>this.MAX_BUDGET)break}}catch(t){h.error("[Haori]","Error processing queue:",t)}finally{this.processing=!1,this.queue.length>0&&this.scheduleProcessing()}}}scheduleProcessing(){this.processing||(typeof requestAnimationFrame<"u"?requestAnimationFrame(()=>{this.processQueue()}):setTimeout(()=>{this.processQueue()},16))}async wait(){if(this.queue.length===0&&!this.processing)return;const t=this.queue.map(e=>e.promise);t.length>0&&await Promise.allSettled(t)}}const G=class G{static enqueue(t,e=!1){return this.ASYNC_QUEUE.enqueue(t,e)}static wait(){return this.ASYNC_QUEUE.wait()}};G.ASYNC_QUEUE=new Y;let w=G;class k{static dialog(t){return w.enqueue(()=>{window.alert(t)},!0)}static async toast(t,e){const r=document.createElement("div");r.className=`haori-toast haori-toast-${e}`,r.textContent=t,r.setAttribute("popover","manual"),r.setAttribute("role","status"),r.setAttribute("aria-live","polite"),document.body.appendChild(r),r.showPopover(),setTimeout(()=>{try{r.hidePopover()}finally{r.remove()}},3e3)}static confirm(t){return w.enqueue(()=>window.confirm(t),!0)}static openDialog(t){return w.enqueue(()=>{t instanceof HTMLDialogElement?t.showModal():h.error("[Haori]","Element is not a dialog: ",t)},!0)}static closeDialog(t){return w.enqueue(()=>{t instanceof HTMLDialogElement?t.close():h.error("[Haori]","Element is not a dialog: ",t)},!0)}static addErrorMessage(t,e){return w.enqueue(()=>{if(t instanceof HTMLFormElement){t.setAttribute("data-message",e);return}if(t.parentElement){t.parentElement.setAttribute("data-message",e);return}t.setAttribute("data-message",e)},!0)}static clearMessages(t){return w.enqueue(()=>{t.removeAttribute("data-message"),t.querySelectorAll("[data-message]").forEach(e=>{e.removeAttribute("data-message")})},!0)}}class y{static getValues(t){const e={};return y.getPartValues(t,e)}static getPartValues(t,e){const r=t.getAttribute("name"),i=t.getAttribute(`${c.prefix}form-object`),s=t.getAttribute(`${c.prefix}form-list`);if(r){s?Array.isArray(e[String(r)])?e[String(r)].push(t.getValue()):e[String(r)]=[t.getValue()]:e[String(r)]=t.getValue(),i&&h.warn("Haori",`Element cannot have both ${c.prefix}form-object and name attributes.`);for(const n of t.getChildElementFragments())y.getPartValues(n,e)}else if(i){const n={};for(const a of t.getChildElementFragments())y.getPartValues(a,n);Object.keys(n).length>0&&(e[String(i)]=n),s&&h.warn("Haori",`Element cannot have both ${c.prefix}form-list and ${c.prefix}form-object attributes.`)}else if(s){const n=[];for(const a of t.getChildElementFragments()){const o={};y.getPartValues(a,o),Object.keys(o).length>0&&n.push(o)}n.length>0&&(e[String(s)]=n)}else for(const n of t.getChildElementFragments())y.getPartValues(n,e);return e}static setValues(t,e,r=!1){return y.setPartValues(t,e,null,r)}static setPartValues(t,e,r=null,i=!1){const s=[],n=t.getAttribute("name"),a=t.getAttribute(`${c.prefix}form-object`),o=t.getAttribute(`${c.prefix}form-list`),g=t.getAttribute(`${c.prefix}form-detach`);if(n){if(!g||i){const u=e[String(n)];o&&Array.isArray(u)&&r!==null?s.push(t.setValue(u[r])):typeof u=="string"||typeof u=="number"||typeof u=="boolean"||u===null?s.push(t.setValue(u)):s.push(t.setValue(String(u)))}}else if(a){const u=e[String(a)];if(u&&typeof u=="object")for(const b of t.getChildElementFragments())s.push(y.setPartValues(b,u,null,i))}else if(o){const u=e[String(o)];if(Array.isArray(u)){const b=t.getChildElementFragments();for(let l=0;l<b.length;l++){const f=b[l];u.length>l?s.push(y.setPartValues(f,u[l],l,i)):s.push(y.setPartValues(f,{},l,i))}}}else for(const u of t.getChildElementFragments())s.push(y.setPartValues(u,e,null,i));return Promise.all(s).then(()=>{})}static async reset(t){y.clearValues(t),await Promise.all([y.clearMessages(t),y.clearEachClones(t)]),await w.enqueue(()=>{const e=t.getTarget();if(e instanceof HTMLFormElement)e.reset();else{const r=e.parentElement;if(r){const i=e.nextElementSibling,s=document.createElement("form");s.appendChild(e),s.reset(),r.insertBefore(e,i)}}}),await N.evaluateAll(t)}static clearEachClones(t){const e=[],r=s=>{if(s.hasAttribute(`${c.prefix}each`))for(const n of s.getChildElementFragments()){const a=n.hasAttribute(`${c.prefix}each-before`),o=n.hasAttribute(`${c.prefix}each-after`);!a&&!o&&e.push(n.remove())}},i=s=>{r(s);for(const n of s.getChildElementFragments())i(n)};r(t);for(const s of t.getChildElementFragments())i(s);return Promise.all(e).then(()=>{})}static clearValues(t){t.clearValue();for(const e of t.getChildElementFragments())y.clearValues(e)}static clearMessages(t){return k.clearMessages(t.getTarget())}static addErrorMessage(t,e,r){const i=[],s=y.findFragmentsByKey(t,e);return s.forEach(n=>{i.push(k.addErrorMessage(n.getTarget(),r))}),s.length===0&&i.push(k.addErrorMessage(t.getTarget(),r)),Promise.all(i).then(()=>{})}static findFragmentsByKey(t,e){return y.findFragmentByKeyParts(t,e.split("."))}static findFragmentByKeyParts(t,e){const r=[],i=e[0];if(e.length==1&&t.getAttribute("name")===i&&r.push(t),t.hasAttribute(`${c.prefix}form-object`))e.length>1&&t.getAttribute(`${c.prefix}form-object`)===i&&t.getChildElementFragments().forEach(n=>{r.push(...y.findFragmentByKeyParts(n,e.slice(1)))});else if(t.hasAttribute(`${c.prefix}form-list`)){if(e.length>1){const s=t.getAttribute(`${c.prefix}form-list`),n=i.lastIndexOf("["),a=i.lastIndexOf("]");if(n!==-1&&a!==-1&&n<a){const o=i.substring(0,n);if(s===o){const g=i.substring(n+1,a),u=Number(g);if(isNaN(u))h.error("Haori",`Invalid index: ${i}`);else{const b=t.getChildElementFragments().filter(l=>l.hasAttribute(`${c.prefix}row`));u<b.length&&r.push(...y.findFragmentByKeyParts(b[u],e.slice(1)))}}}}}else t.getChildElementFragments().forEach(s=>{r.push(...y.findFragmentByKeyParts(s,e))});return r}static getFormFragment(t){if(t.getTarget()instanceof HTMLFormElement)return t;const r=t.getParent();return r?this.getFormFragment(r):null}}const M=class M{static evaluate(t,e={}){if(t.trim()==="")return h.warn("[Haori]",t,"Expression is empty"),null;if(this.containsDangerousPatterns(t))return h.warn("[Haori]",t,"Expression contains dangerous patterns"),null;if(this.containsForbiddenKeys(e))return h.warn("[Haori]",e,"Binded values contain forbidden keys"),null;const r=Object.keys(e).filter(n=>!this.FORBIDDEN_NAMES.includes(n)&&!this.STRICT_FORBIDDEN_NAMES.includes(n)).sort(),i=`${t}:${r.join(",")}`;let s=this.EXPRESSION_CACHE.get(i);if(!s){const n=`"use strict";
2
2
  ${this.assignments};
3
- return (${t});`;try{r=new Function(...s,n),this.EXPRESSION_CACHE.set(i,r)}catch(a){return h.error("[Haori]","Failed to compile expression:",t,a),null}}try{const n=[];return s.forEach(a=>{n.push(e[a])}),r(...n)}catch(n){return h.error("[Haori]","Expression evaluation error:",t,n),n instanceof ReferenceError?void 0:null}}static containsDangerousPatterns(t){return[/\beval\s*\(/,/\barguments\s*\[/,/\barguments\s*\./].some(s=>s.test(t))}static containsForbiddenKeys(t){if(t&&typeof t=="object"){for(const e of Object.keys(t))if(this.FORBIDDEN_NAMES.includes(e)||this.STRICT_FORBIDDEN_NAMES.includes(e)||this.containsForbiddenKeys(t[e]))return!0}return!1}};P.FORBIDDEN_NAMES=["window","self","globalThis","frames","parent","top","Function","setTimeout","setInterval","requestAnimationFrame","alert","confirm","prompt","fetch","XMLHttpRequest","constructor","__proto__","prototype","Object","document","location","navigator","localStorage","sessionStorage","IndexedDB","history"],P.STRICT_FORBIDDEN_NAMES=["eval","arguments"],P.EXPRESSION_CACHE=new Map,(()=>{const t=[];P.FORBIDDEN_NAMES.forEach(e=>{t.push(`const ${e} = undefined`)}),P.assignments=t.join(`;
4
- `)})();let L=P;const R=class R{constructor(t){this.parent=null,this.mounted=!1,this.skipMutationNodes=!1,this.target=t,R.FRAGMENT_CACHE.set(t,this)}static get(t){if(t==null)return null;if(R.FRAGMENT_CACHE.has(t))return R.FRAGMENT_CACHE.get(t);let e;switch(t.nodeType){case Node.ELEMENT_NODE:e=new F(t);break;case Node.TEXT_NODE:e=new j(t);break;case Node.COMMENT_NODE:e=new U(t);break;default:return h.warn("[Haori]","Unsupported node type:",t.nodeType),null}return e}isSkipMutationNodes(){return this.skipMutationNodes}unmount(){if(!this.mounted||this.skipMutationNodes)return Promise.resolve();if(this.parent){const t=this.parent,e=t.skipMutationNodes;return v.enqueue(()=>{t.skipMutationNodes=!0,this.target.parentNode===t.getTarget()&&t.getTarget().removeChild(this.target),this.mounted=!1}).finally(()=>{t.skipMutationNodes=e})}else{const t=this.target.parentNode;if(t)return v.enqueue(()=>{this.target.parentNode===t&&t.removeChild(this.target),this.mounted=!1});this.mounted=!1}return Promise.resolve()}mount(){if(this.mounted||this.skipMutationNodes)return Promise.resolve();if(this.parent){const t=this.parent,e=t.skipMutationNodes;return v.enqueue(()=>{t.skipMutationNodes=!0,this.target.parentNode!==t.getTarget()&&t.getTarget().appendChild(this.target),this.mounted=!0}).finally(()=>{t.skipMutationNodes=e})}return Promise.resolve()}isMounted(){return this.mounted}setMounted(t){this.mounted=t}remove(t=!0){return this.parent&&this.parent.removeChild(this),R.FRAGMENT_CACHE.delete(this.target),t?this.unmount():Promise.resolve()}getTarget(){return this.target}getParent(){return this.parent}setParent(t){this.parent=t}};R.FRAGMENT_CACHE=new WeakMap;let A=R;class F extends A{constructor(t){super(t),this.INPUT_EVENT_TYPES=["text","password","email","url","tel","search","number","range","color","date","datetime-local","month","time","week"],this.children=[],this.attributeMap=new Map,this.bindingData=null,this.bindingDataCache=null,this.visible=!0,this.display=null,this.template=null,this.listKey=null,this.value=null,this.skipMutationAttributes=!1,this.skipChangeValue=!1,this.syncValue(),t.getAttributeNames().forEach(e=>{const s=t.getAttribute(e);if(s!==null&&!this.attributeMap.has(e)){const i=new I(e,s);this.attributeMap.set(e,i)}}),t.childNodes.forEach(e=>{const s=A.get(e);s.setParent(this),this.children.push(s)})}getChildren(){return this.children}getChildElementFragments(){return this.children.filter(t=>t instanceof F)}pushChild(t){this.children.push(t),t.setParent(this)}removeChild(t){const e=this.children.indexOf(t);if(e<0){h.warn("[Haori]","Child fragment not found.",t);return}this.children.splice(e,1),t.setParent(null)}clone(){const t=new F(this.target.cloneNode(!1));return this.children.forEach(e=>{const s=e.clone();t.getTarget().appendChild(s.getTarget()),t.pushChild(s)}),t.mounted=!1,t.bindingData=this.bindingData,t.clearBindingDataCache(),t.visible=this.visible,t.display=this.display,t.template=this.template,t}remove(t=!0){const e=[];return this.children.forEach(s=>{e.push(s.remove(!1))}),this.children.length=0,this.attributeMap.clear(),this.bindingData=null,this.bindingDataCache=null,this.template&&(e.push(this.template.remove(!1)),this.template=null),e.push(super.remove(t)),Promise.all(e).then(()=>{})}getTarget(){return this.target}getBindingData(){return this.bindingDataCache?this.bindingDataCache:(this.bindingDataCache={},this.parent&&Object.assign(this.bindingDataCache,this.parent.getBindingData()),this.bindingData&&Object.assign(this.bindingDataCache,this.bindingData),this.bindingDataCache)}getRawBindingData(){return this.bindingData}setBindingData(t){this.bindingData=t,this.clearBindingDataCache()}clearBindingDataCache(){this.bindingDataCache=null,this.children.forEach(t=>{t instanceof F&&t.clearBindingDataCache()})}getTemplate(){return this.template}setTemplate(t){this.template=t}setListKey(t){this.listKey=t}getListKey(){return this.listKey}setValue(t){if(this.skipChangeValue||this.value===t)return Promise.resolve();const e=this.getTarget();if(e instanceof HTMLInputElement&&(e.type==="checkbox"||e.type==="radio")){const s=this.getAttribute("value");let i;return s==="true"?i=t===!0:s==="false"?i=t===!1:i=s===String(t),this.value=i?t:null,e.checked===i?Promise.resolve():(this.skipChangeValue=!0,v.enqueue(()=>{e.checked=i,e.dispatchEvent(new Event("change",{bubbles:!0}))}).finally(()=>{this.skipChangeValue=!1}))}else return e instanceof HTMLInputElement||e instanceof HTMLTextAreaElement||e instanceof HTMLSelectElement?(this.value=t,this.skipChangeValue=!0,v.enqueue(()=>{e.value=t===null?"":String(t),(e instanceof HTMLInputElement&&this.INPUT_EVENT_TYPES.includes(e.type)||e instanceof HTMLTextAreaElement)&&e.dispatchEvent(new Event("input",{bubbles:!0})),e.dispatchEvent(new Event("change",{bubbles:!0}))}).finally(()=>{this.skipChangeValue=!1})):(h.warn("[Haori]","setValue is not supported for this element type.",e),Promise.resolve())}getValue(){return this.value}clearValue(){this.value=null}syncValue(){const t=this.getTarget();if(t instanceof HTMLInputElement)if(t.type==="checkbox"||t.type==="radio")if(t.checked){const e=t.value;e==="true"?this.value=!0:e==="false"?this.value=!1:this.value=e}else{const e=t.value;e==="true"?this.value=!1:e==="false"?this.value=!0:this.value=null}else this.value=t.value;else t instanceof HTMLTextAreaElement?this.value=t.value:t instanceof HTMLSelectElement&&(this.value=t.value)}setAttribute(t,e){if(this.skipMutationAttributes)return Promise.resolve();if(e===null)return this.removeAttribute(t);const s=new I(t,e);this.attributeMap.set(t,s),this.skipMutationAttributes=!0;const i=this.getTarget(),r=s.isForceEvaluation()?e:this.getAttribute(t);return v.enqueue(()=>{if(r===null||r===!1)i.removeAttribute(t);else{const n=String(r);i.getAttribute(t)!==n&&i.setAttribute(t,n)}}).finally(()=>{this.skipMutationAttributes=!1})}removeAttribute(t){if(this.skipMutationAttributes)return Promise.resolve();this.attributeMap.delete(t),this.skipMutationAttributes=!0;const e=this.getTarget();return v.enqueue(()=>{e.removeAttribute(t)}).finally(()=>{this.skipMutationAttributes=!1})}getAttribute(t){const e=this.attributeMap.get(t);if(e===void 0)return null;const s=e.evaluate(this.getBindingData());return s.length===1?s[0]:$.joinEvaluateResults(s)}getRawAttribute(t){const e=this.attributeMap.get(t);return e===void 0?null:e.getValue()}getAttributeNames(){return Array.from(this.attributeMap.keys())}hasAttribute(t){return this.attributeMap.has(t)}insertBefore(t,e){if(this.skipMutationNodes)return Promise.resolve();if(t===this)return h.error("[Haori]","Cannot insert element as child of itself"),Promise.reject(new Error("Self-insertion not allowed"));const s=new Set;let i=this.parent;for(;i;)s.add(i),i=i.getParent();if(s.has(t))return h.error("[Haori]","Cannot create circular reference"),Promise.reject(new Error("Circular reference detected"));const r=t.getParent()===this;let n=-1,a=-1;r&&(n=this.children.indexOf(t),e!==null&&(a=this.children.indexOf(e)));const u=t.getParent();if(u!==null&&u.removeChild(t),e===null)this.children.push(t);else{let l;r?n!==-1&&n<a?l=a-1:l=a:l=this.children.indexOf(e),l===-1?(h.warn("[Haori]","Reference child not found in children.",e),this.children.push(t)):this.children.splice(l,0,t)}t.setParent(this),t.setMounted(this.mounted);const b=this.skipMutationNodes;return this.skipMutationNodes=!0,v.enqueue(()=>{this.target.insertBefore(t.getTarget(),e?.getTarget()||null)}).finally(()=>{this.skipMutationNodes=b})}insertAfter(t,e){if(e==null)return this.insertBefore(t,null);const s=this.children.indexOf(e);return s===-1?(h.warn("[Haori]","Reference child not found in children.",e),this.insertBefore(t,null)):this.insertBefore(t,this.children[s+1]||null)}getPrevious(){const t=this.getParent();if(t===null)return null;const e=t.getChildElementFragments(),s=e.indexOf(this);return s<=0?null:e[s-1]}getNext(){const t=this.getParent();if(t===null)return null;const e=t.getChildElementFragments(),s=e.indexOf(this);return s<0||s+1>=e.length?null:e[s+1]}isVisible(){return this.visible}hide(){return this.visible=!1,this.display=this.getTarget().style.display,this.getTarget().style.display="none",this.getTarget().setAttribute(`${c.prefix}if-false`,""),Promise.resolve()}show(){return this.getTarget().style.display=this.display??"",this.getTarget().removeAttribute(`${c.prefix}if-false`),this.visible=!0,Promise.resolve()}closestByAttribute(t){if(this.hasAttribute(t))return this;const e=this.getParent();return e===null?null:e.closestByAttribute(t)}}class j extends A{constructor(t){super(t),this.skipMutation=!1,this.text=t.textContent||"",this.contents=new $(this.text)}clone(){const t=new j(this.target.cloneNode(!0));return t.mounted=!1,t.text=this.text,t.contents=this.contents,t}getTarget(){return this.target}setContent(t){return this.skipMutation||this.text===t?Promise.resolve():(this.text=t,this.contents=new $(t),this.evaluate())}evaluate(){return this.contents.isRawEvaluate&&this.parent===null?Promise.reject(new Error("Parent fragment is required for raw evaluation")):v.enqueue(()=>{this.skipMutation=!0,this.contents.isRawEvaluate?this.parent.getTarget().innerHTML=this.contents.evaluate(this.parent.getBindingData())[0]:this.contents.isEvaluate?this.target.textContent=$.joinEvaluateResults(this.contents.evaluate(this.parent.getBindingData())):this.target.textContent=this.text}).finally(()=>{this.skipMutation=!1})}}class U extends A{constructor(t){super(t),this.skipMutation=!1,this.text=t.textContent||""}clone(){const t=new U(this.target.cloneNode(!0));return t.mounted=!1,t.text=this.text,t}getTarget(){return this.target}setContent(t){return this.skipMutation||this.text===t?Promise.resolve():(this.text=t,v.enqueue(()=>{this.skipMutation=!0,this.target.textContent=this.text}).finally(()=>{this.skipMutation=!1}))}}const V=class V{constructor(t){this.contents=[],this.isEvaluate=!1,this.isRawEvaluate=!1,this.value=t;const e=[...t.matchAll(V.PLACEHOLDER_REGEX)];let s=0,i=!1,r=!1;for(const n of e){n.index>s&&this.contents.push({text:t.slice(s,n.index),type:0});const a={text:n[1]??n[2],type:n[1]?2:1};i=!0,r=r||a.type===2,this.contents.push(a),s=n.index+n[0].length}s<t.length&&this.contents.push({text:t.slice(s),type:0}),this.isEvaluate=i,this.isRawEvaluate=r,this.checkRawExpressions()}static joinEvaluateResults(t){return t===null||t.length===0?"":t.map(e=>e==null||e===!1||Number.isNaN(e)?"":typeof e!="string"?String(e):e).join("")}getValue(){return this.value}checkRawExpressions(){for(let t=0;t<this.contents.length;t++)this.contents[t].type===2&&this.contents.length>1&&(h.error("[Haori]","Raw expressions are not allowed in multi-content expressions."),this.contents[t].type=1)}evaluate(t){if(!this.isEvaluate&&!this.isRawEvaluate)return this.contents.map(s=>s.text);const e=[];return this.contents.forEach(s=>{try{if(s.type===1||s.type===2){const i=L.evaluate(s.text,t);e.push(i)}else e.push(s.text)}catch(i){h.error("[Haori]",`Error evaluating text expression: ${s.text}`,i),e.push("")}}),e}};V.PLACEHOLDER_REGEX=/\{\{\{([\s\S]+?)\}\}\}|\{\{([\s\S]+?)\}\}/g;let $=V;const q=class q extends ${constructor(t,e){super(e),this.forceEvaluation=q.FORCE_EVALUATION_ATTRIBUTES.includes(t)}isForceEvaluation(){return this.forceEvaluation}evaluate(t){if(!this.isEvaluate&&!this.forceEvaluation)return this.contents.map(s=>s.text);const e=[];return this.contents.forEach(s=>{try{if(this.forceEvaluation&&s.type===0||s.type===1||s.type===2){const i=L.evaluate(s.text,t);e.push(i)}else e.push(s.text)}catch(i){h.error("[Haori]",`Error evaluating attribute expression: ${s.text}`,i),e.push("")}}),this.forceEvaluation&&e.length>1?(h.error("[Haori]","each or if expressions must have a single content.",e),[e[0]]):e}};q.FORCE_EVALUATION_ATTRIBUTES=["data-if","hor-if","data-each","hor-each"];let I=q;class y{static dispatch(t,e,s,i){const r=new CustomEvent(`haori:${e}`,{bubbles:i?.bubbles??!0,cancelable:i?.cancelable??!1,composed:i?.composed??!0,detail:s});return t.dispatchEvent(r)}static ready(t){y.dispatch(document,"ready",{version:t})}static render(t){y.dispatch(t,"render",{target:t})}static importStart(t,e){y.dispatch(t,"importstart",{url:e,startedAt:performance.now()})}static importEnd(t,e,s,i){y.dispatch(t,"importend",{url:e,bytes:s,durationMs:performance.now()-i})}static importError(t,e,s){y.dispatch(t,"importerror",{url:e,error:s})}static bindChange(t,e,s,i="other"){const r=[],n=new Set(Object.keys(e||{})),a=new Set(Object.keys(s)),u=new Set([...n,...a]);for(const b of u){const l=e?.[b],E=s[b];l!==E&&r.push(b)}y.dispatch(t,"bindchange",{previous:e||{},next:s,changedKeys:r,reason:i})}static eachUpdate(t,e,s,i){y.dispatch(t,"eachupdate",{added:e,removed:s,order:i,total:i.length})}static rowAdd(t,e,s,i){y.dispatch(t,"rowadd",{key:e,index:s,item:i})}static rowRemove(t,e,s){y.dispatch(t,"rowremove",{key:e,index:s})}static rowMove(t,e,s,i){y.dispatch(t,"rowmove",{key:e,from:s,to:i})}static show(t){y.dispatch(t,"show",{visible:!0})}static hide(t){y.dispatch(t,"hide",{visible:!1})}static fetchStart(t,e,s,i){y.dispatch(t,"fetchstart",{url:e,options:s||{},payload:i,startedAt:performance.now()})}static fetchEnd(t,e,s,i){y.dispatch(t,"fetchend",{url:e,status:s,durationMs:performance.now()-i})}static fetchError(t,e,s,i,r){y.dispatch(t,"fetcherror",{url:e,status:i,error:s,durationMs:r?performance.now()-r:void 0})}}class f{static attrName(t,e,s=!1){return t?`${c.prefix}${t}-${e}`:s?`${c.prefix}fetch-${e}`:`${c.prefix}${e}`}static buildOptions(t,e){const s={targetFragment:t};if(e){if(t.hasAttribute(f.attrName(e,"validate"))&&(s.valid=!0),t.hasAttribute(f.attrName(e,"confirm"))&&(s.confirmMessage=t.getAttribute(f.attrName(e,"confirm"))),t.hasAttribute(f.attrName(e,"data"))&&(s.data=N.parseDataBind(t.getRawAttribute(f.attrName(e,"data")))),t.hasAttribute(f.attrName(e,"form"))){const o=t.getRawAttribute(f.attrName(e,"form"));if(o){const d=document.body.querySelector(o);d!==null?s.formFragment=m.getFormFragment(A.get(d)):h.error("Haori",`Form element not found: ${o} (${f.attrName(e,"form")})`)}else s.formFragment=m.getFormFragment(t)}else e==="change"&&(s.formFragment=m.getFormFragment(t));if(t.hasAttribute(`${c.prefix}${e}-before-run`)){const o=t.getRawAttribute(`${c.prefix}${e}-before-run`);try{s.beforeCallback=new Function("fetchUrl","fetchOptions",`
3
+ return (${t});`;try{s=new Function(...r,n),this.EXPRESSION_CACHE.set(i,s)}catch(a){return h.error("[Haori]","Failed to compile expression:",t,a),null}}try{const n=[],a=this.wrapBoundValues(e);return r.forEach(o=>{n.push(a[o])}),this.withBlockedPropertyAccess(()=>s(...n))}catch(n){return h.error("[Haori]","Expression evaluation error:",t,n),n instanceof ReferenceError?void 0:null}}static containsDangerousPatterns(t){return this.hasAllowedSyntax(t)?[/\beval\s*\(/,/\barguments\s*\[/,/\barguments\s*\./].some(r=>r.test(t)):!0}static hasAllowedSyntax(t){const e=this.tokenizeExpression(t);if(e===null||e.length===0)return!1;const r=[];let i=null;for(let s=0;s<e.length;s++){const n=e[s],a=e[s+1]||null,o=r[r.length-1]||null;if(n.type==="identifier"&&(this.DISALLOWED_KEYWORDS.has(n.value)||this.STRICT_FORBIDDEN_NAMES.includes(n.value)||(i?.value==="."||i?.value==="?.")&&this.FORBIDDEN_PROPERTY_NAMES.has(n.value))||o==="member"&&n.value!=="]"&&n.type==="string"&&this.FORBIDDEN_PROPERTY_NAMES.has(this.decodeStringLiteral(n.value))||n.value==="."&&a?.type!=="identifier"||n.value==="?."&&a?.type!=="identifier"&&a?.value!=="["&&a?.value!=="(")return!1;switch(n.value){case"(":r.push("paren");break;case")":{if(r.pop()!=="paren")return!1;break}case"[":{const g=this.startsMemberAccess(i)?"member":"array";r.push(g);break}case"]":{if(r.pop()===void 0)return!1;break}}i=n}return r.length===0}static tokenizeExpression(t){const e=[],r=["===","!==","...","?.","&&","||",">=","<=","==","!=","=>"],i=new Set(["(",")","[","]",".",",","?",":","+","-","*","/","%","!",">","<"]);let s=0;for(;s<t.length;){const n=t[s];if(/\s/.test(n)){s+=1;continue}if(n==="/"&&(t[s+1]==="/"||t[s+1]==="*"))return null;if(n==='"'||n==="'"){const o=this.readStringToken(t,s);if(o===null)return null;e.push(o.token),s=o.nextIndex;continue}const a=r.find(o=>t.startsWith(o,s));if(a){e.push({type:"operator",value:a,position:s}),s+=a.length;continue}if(/[0-9]/.test(n)){const o=this.readNumberToken(t,s);e.push(o.token),s=o.nextIndex;continue}if(/[A-Za-z_$]/.test(n)){const o=this.readIdentifierToken(t,s);e.push(o.token),s=o.nextIndex;continue}if(i.has(n)){e.push({type:"operator",value:n,position:s}),s+=1;continue}return null}return e}static readStringToken(t,e){const r=t[e];let i=e+1;for(;i<t.length;){const s=t[i];if(s==="\\"){i+=2;continue}if(s===r)return{token:{type:"string",value:t.slice(e,i+1),position:e},nextIndex:i+1};i+=1}return null}static readNumberToken(t,e){let r=e;for(;r<t.length&&/[0-9_]/.test(t[r]);)r+=1;if(t[r]===".")for(r+=1;r<t.length&&/[0-9_]/.test(t[r]);)r+=1;return{token:{type:"number",value:t.slice(e,r),position:e},nextIndex:r}}static readIdentifierToken(t,e){let r=e;for(;r<t.length&&/[A-Za-z0-9_$]/.test(t[r]);)r+=1;return{token:{type:"identifier",value:t.slice(e,r),position:e},nextIndex:r}}static startsMemberAccess(t){return t===null?!1:t.type==="identifier"||t.type==="number"?!0:t.value===")"||t.value==="]"||t.value==="?."}static decodeStringLiteral(t){return t.slice(1,-1).replace(/\\u([0-9a-fA-F]{4})/g,(e,r)=>String.fromCharCode(parseInt(r,16))).replace(/\\x([0-9a-fA-F]{2})/g,(e,r)=>String.fromCharCode(parseInt(r,16))).replace(/\\(["'\\bfnrtv0])/g,(e,r)=>{switch(r){case"b":return"\b";case"f":return"\f";case"n":return`
4
+ `;case"r":return"\r";case"t":return" ";case"v":return"\v";case"0":return"\0";default:return r}})}static wrapBoundValues(t){const e=new WeakMap,r={};return Object.entries(t).forEach(([i,s])=>{r[i]=this.wrapBoundValue(s,e)}),r}static wrapBoundValue(t,e){if(!this.shouldWrapValue(t))return t;const r=t,i=e.get(r);if(i!==void 0)return i;const s=new Proxy(r,{get:(n,a,o)=>{if(typeof a=="string"&&this.FORBIDDEN_PROPERTY_NAMES.has(a))return;const g=Reflect.get(n,a,o);return typeof a=="symbol"?g:this.wrapBoundValue(g,e)},has:(n,a)=>typeof a=="string"&&this.FORBIDDEN_PROPERTY_NAMES.has(a)?!1:Reflect.has(n,a),getOwnPropertyDescriptor:(n,a)=>{if(!(typeof a=="string"&&this.FORBIDDEN_PROPERTY_NAMES.has(a)))return Reflect.getOwnPropertyDescriptor(n,a)},apply:(n,a,o)=>{const g=Reflect.apply(n,a,o);return this.isIteratorLike(g)?g:this.wrapBoundValue(g,e)},construct:(n,a,o)=>this.wrapBoundValue(Reflect.construct(n,a,o),e)});return e.set(r,s),s}static shouldWrapValue(t){if(typeof t=="function")return!0;if(t===null||typeof t!="object")return!1;if(Array.isArray(t))return!0;const e=Object.getPrototypeOf(t);return e===Object.prototype||e===null}static withBlockedPropertyAccess(t){const r=[{target:Object.prototype,property:"constructor"},{target:Function.prototype,property:"constructor"},{target:Object.prototype,property:"__proto__"}].map(i=>({...i,descriptor:Object.getOwnPropertyDescriptor(i.target,i.property)})).filter(i=>i.descriptor?.configurable===!0);r.forEach(({target:i,property:s})=>{Object.defineProperty(i,s,{configurable:!0,enumerable:!1,get:()=>{},set:()=>{}})});try{return t()}finally{r.forEach(({target:i,property:s,descriptor:n})=>{n!==void 0&&Object.defineProperty(i,s,n)})}}static isIteratorLike(t){return t===null||typeof t!="object"?!1:typeof t.next=="function"}static containsForbiddenKeys(t){if(t&&typeof t=="object"){for(const e of Object.keys(t))if(this.FORBIDDEN_NAMES.includes(e)||this.STRICT_FORBIDDEN_NAMES.includes(e)||this.containsForbiddenKeys(t[e]))return!0}return!1}};M.FORBIDDEN_NAMES=["window","self","globalThis","frames","parent","top","Function","setTimeout","setInterval","requestAnimationFrame","alert","confirm","prompt","fetch","XMLHttpRequest","Reflect","constructor","__proto__","prototype","Object","document","location","navigator","localStorage","sessionStorage","IndexedDB","history"],M.STRICT_FORBIDDEN_NAMES=["eval","arguments"],M.FORBIDDEN_PROPERTY_NAMES=new Set(["constructor","__proto__","prototype"]),M.DISALLOWED_KEYWORDS=new Set(["await","break","case","catch","class","const","continue","debugger","default","delete","do","else","export","finally","for","function","if","import","in","instanceof","let","new","return","switch","this","throw","try","typeof","var","void","while","with","yield"]),M.EXPRESSION_CACHE=new Map,(()=>{const t=[];M.FORBIDDEN_NAMES.forEach(e=>{t.push(`const ${e} = undefined`)}),M.assignments=t.join(`;
5
+ `)})();let H=M;const P=class P{constructor(t){this.parent=null,this.mounted=!1,this.skipMutationNodes=!1,this.target=t,P.FRAGMENT_CACHE.set(t,this)}static get(t){if(t==null)return null;if(P.FRAGMENT_CACHE.has(t))return P.FRAGMENT_CACHE.get(t);let e;switch(t.nodeType){case Node.ELEMENT_NODE:e=new S(t);break;case Node.TEXT_NODE:e=new j(t);break;case Node.COMMENT_NODE:e=new K(t);break;default:return h.warn("[Haori]","Unsupported node type:",t.nodeType),null}return e}isSkipMutationNodes(){return this.skipMutationNodes}unmount(){if(!this.mounted||this.skipMutationNodes)return Promise.resolve();if(this.parent){const t=this.parent,e=t.skipMutationNodes;return w.enqueue(()=>{t.skipMutationNodes=!0,this.target.parentNode===t.getTarget()&&t.getTarget().removeChild(this.target),this.mounted=!1}).finally(()=>{t.skipMutationNodes=e})}else{const t=this.target.parentNode;if(t)return w.enqueue(()=>{this.target.parentNode===t&&t.removeChild(this.target),this.mounted=!1});this.mounted=!1}return Promise.resolve()}mount(){if(this.mounted||this.skipMutationNodes)return Promise.resolve();if(this.parent){const t=this.parent,e=t.skipMutationNodes;return w.enqueue(()=>{t.skipMutationNodes=!0,this.target.parentNode!==t.getTarget()&&t.getTarget().appendChild(this.target),this.mounted=!0}).finally(()=>{t.skipMutationNodes=e})}return Promise.resolve()}isMounted(){return this.mounted}setMounted(t){this.mounted=t}remove(t=!0){return this.parent&&this.parent.removeChild(this),P.FRAGMENT_CACHE.delete(this.target),t?this.unmount():Promise.resolve()}getTarget(){return this.target}getParent(){return this.parent}setParent(t){this.parent=t}};P.FRAGMENT_CACHE=new WeakMap;let A=P;class S extends A{constructor(t){super(t),this.INPUT_EVENT_TYPES=["text","password","email","url","tel","search","number","range","color","date","datetime-local","month","time","week"],this.children=[],this.attributeMap=new Map,this.bindingData=null,this.bindingDataCache=null,this.visible=!0,this.display=null,this.template=null,this.listKey=null,this.value=null,this.skipMutationAttributes=!1,this.skipChangeValue=!1,this.syncValue(),t.getAttributeNames().forEach(e=>{const r=t.getAttribute(e);if(r!==null&&!this.attributeMap.has(e)){const i=new L(e,r);this.attributeMap.set(e,i)}}),t.childNodes.forEach(e=>{const r=A.get(e);r.setParent(this),this.children.push(r)})}getChildren(){return this.children}getChildElementFragments(){return this.children.filter(t=>t instanceof S)}pushChild(t){this.children.push(t),t.setParent(this)}removeChild(t){const e=this.children.indexOf(t);if(e<0){h.warn("[Haori]","Child fragment not found.",t);return}this.children.splice(e,1),t.setParent(null)}clone(){const t=new S(this.target.cloneNode(!1));return this.children.forEach(e=>{const r=e.clone();t.getTarget().appendChild(r.getTarget()),t.pushChild(r)}),t.mounted=!1,t.bindingData=this.bindingData,t.clearBindingDataCache(),t.visible=this.visible,t.display=this.display,t.template=this.template,t}remove(t=!0){const e=[];return this.children.forEach(r=>{e.push(r.remove(!1))}),this.children.length=0,this.attributeMap.clear(),this.bindingData=null,this.bindingDataCache=null,this.template&&(e.push(this.template.remove(!1)),this.template=null),e.push(super.remove(t)),Promise.all(e).then(()=>{})}getTarget(){return this.target}getBindingData(){return this.bindingDataCache?this.bindingDataCache:(this.bindingDataCache={},this.parent&&Object.assign(this.bindingDataCache,this.parent.getBindingData()),this.bindingData&&Object.assign(this.bindingDataCache,this.bindingData),this.bindingDataCache)}getRawBindingData(){return this.bindingData}setBindingData(t){this.bindingData=t,this.clearBindingDataCache()}clearBindingDataCache(){this.bindingDataCache=null,this.children.forEach(t=>{t instanceof S&&t.clearBindingDataCache()})}getTemplate(){return this.template}setTemplate(t){this.template=t}setListKey(t){this.listKey=t}getListKey(){return this.listKey}setValue(t){if(this.skipChangeValue||this.value===t)return Promise.resolve();const e=this.getTarget();if(e instanceof HTMLInputElement&&(e.type==="checkbox"||e.type==="radio")){const r=this.getAttribute("value");let i;return r==="true"?i=t===!0:r==="false"?i=t===!1:i=r===String(t),this.value=i?t:null,e.checked===i?Promise.resolve():(this.skipChangeValue=!0,w.enqueue(()=>{e.checked=i,e.dispatchEvent(new Event("change",{bubbles:!0}))}).finally(()=>{this.skipChangeValue=!1}))}else return e instanceof HTMLInputElement||e instanceof HTMLTextAreaElement||e instanceof HTMLSelectElement?(this.value=t,this.skipChangeValue=!0,w.enqueue(()=>{e.value=t===null?"":String(t),(e instanceof HTMLInputElement&&this.INPUT_EVENT_TYPES.includes(e.type)||e instanceof HTMLTextAreaElement)&&e.dispatchEvent(new Event("input",{bubbles:!0})),e.dispatchEvent(new Event("change",{bubbles:!0}))}).finally(()=>{this.skipChangeValue=!1})):(h.warn("[Haori]","setValue is not supported for this element type.",e),Promise.resolve())}getValue(){return this.value}clearValue(){this.value=null}syncValue(){const t=this.getTarget();if(t instanceof HTMLInputElement)if(t.type==="checkbox"||t.type==="radio")if(t.checked){const e=t.value;e==="true"?this.value=!0:e==="false"?this.value=!1:this.value=e}else{const e=t.value;e==="true"?this.value=!1:e==="false"?this.value=!0:this.value=null}else this.value=t.value;else t instanceof HTMLTextAreaElement?this.value=t.value:t instanceof HTMLSelectElement&&(this.value=t.value)}setAttribute(t,e){if(this.skipMutationAttributes)return Promise.resolve();if(e===null)return this.removeAttribute(t);const r=new L(t,e);this.attributeMap.set(t,r),this.skipMutationAttributes=!0;const i=this.getTarget(),s=r.isForceEvaluation()?e:this.getAttribute(t);return w.enqueue(()=>{if(s===null||s===!1)i.removeAttribute(t);else{const n=String(s);i.getAttribute(t)!==n&&i.setAttribute(t,n)}}).finally(()=>{this.skipMutationAttributes=!1})}removeAttribute(t){if(this.skipMutationAttributes)return Promise.resolve();this.attributeMap.delete(t),this.skipMutationAttributes=!0;const e=this.getTarget();return w.enqueue(()=>{e.removeAttribute(t)}).finally(()=>{this.skipMutationAttributes=!1})}getAttribute(t){const e=this.attributeMap.get(t);if(e===void 0)return null;const r=e.evaluate(this.getBindingData());return r.length===1?r[0]:$.joinEvaluateResults(r)}getRawAttribute(t){const e=this.attributeMap.get(t);return e===void 0?null:e.getValue()}getAttributeNames(){return Array.from(this.attributeMap.keys())}hasAttribute(t){return this.attributeMap.has(t)}resolveInsertionPointFromDom(t,e){const r=t.getTarget();if(r.parentNode!==this.target)return null;const i=e?r.nextSibling:r;let s=e?r.nextSibling:r;for(;s!==null;){const n=A.get(s);if(n!==null){const a=this.children.indexOf(n);if(a!==-1)return{index:a,referenceNode:i}}s=s.nextSibling}return{index:this.children.length,referenceNode:i}}insertBefore(t,e,r){if(this.skipMutationNodes)return Promise.resolve();if(t===this)return h.error("[Haori]","Cannot insert element as child of itself"),Promise.reject(new Error("Self-insertion not allowed"));const i=new Set;let s=this.parent;for(;s;)i.add(s),s=s.getParent();if(i.has(t))return h.error("[Haori]","Cannot create circular reference"),Promise.reject(new Error("Circular reference detected"));const n=t.getParent()===this;let a=-1,o=-1;n&&(a=this.children.indexOf(t),e!==null&&(o=this.children.indexOf(e)));const g=t.getParent();g!==null&&g.removeChild(t);let u=r===void 0?e?.getTarget()||null:r;if(e===null)this.children.push(t);else{let l;if(n?a!==-1&&a<o?l=o-1:l=o:l=this.children.indexOf(e),l===-1){const f=this.resolveInsertionPointFromDom(e,!1);f===null?(h.warn("[Haori]","Reference child not found in children.",e),this.children.push(t)):(this.children.splice(f.index,0,t),u=f.referenceNode)}else this.children.splice(l,0,t)}t.setParent(this),t.setMounted(this.mounted);const b=this.skipMutationNodes;return this.skipMutationNodes=!0,w.enqueue(()=>{this.target.insertBefore(t.getTarget(),u)}).finally(()=>{this.skipMutationNodes=b})}insertAfter(t,e){if(e==null)return this.insertBefore(t,null);const r=this.children.indexOf(e);if(r===-1){const i=this.resolveInsertionPointFromDom(e,!0);return i===null?(h.warn("[Haori]","Reference child not found in children.",e),this.insertBefore(t,null)):this.insertBefore(t,this.children[i.index]||null,i.referenceNode)}return this.insertBefore(t,this.children[r+1]||null)}getPrevious(){const t=this.getParent();if(t===null)return null;const e=t.getChildElementFragments(),r=e.indexOf(this);return r<=0?null:e[r-1]}getNext(){const t=this.getParent();if(t===null)return null;const e=t.getChildElementFragments(),r=e.indexOf(this);return r<0||r+1>=e.length?null:e[r+1]}isVisible(){return this.visible}hide(){return this.visible=!1,this.display=this.getTarget().style.display,this.getTarget().style.display="none",this.getTarget().setAttribute(`${c.prefix}if-false`,""),Promise.resolve()}show(){return this.getTarget().style.display=this.display??"",this.getTarget().removeAttribute(`${c.prefix}if-false`),this.visible=!0,Promise.resolve()}closestByAttribute(t){if(this.hasAttribute(t))return this;const e=this.getParent();return e===null?null:e.closestByAttribute(t)}}class j extends A{constructor(t){super(t),this.skipMutation=!1,this.text=t.textContent||"",this.contents=new $(this.text)}clone(){const t=new j(this.target.cloneNode(!0));return t.mounted=!1,t.text=this.text,t.contents=this.contents,t}getTarget(){return this.target}setContent(t){return this.skipMutation||this.text===t?Promise.resolve():(this.text=t,this.contents=new $(t),this.evaluate())}evaluate(){return this.contents.isRawEvaluate&&this.parent===null?Promise.reject(new Error("Parent fragment is required for raw evaluation")):w.enqueue(()=>{this.skipMutation=!0,this.contents.isRawEvaluate?this.parent.getTarget().innerHTML=this.contents.evaluate(this.parent.getBindingData())[0]:this.contents.isEvaluate?this.target.textContent=$.joinEvaluateResults(this.contents.evaluate(this.parent.getBindingData())):this.target.textContent=this.text}).finally(()=>{this.skipMutation=!1})}}class K extends A{constructor(t){super(t),this.skipMutation=!1,this.text=t.textContent||""}clone(){const t=new K(this.target.cloneNode(!0));return t.mounted=!1,t.text=this.text,t}getTarget(){return this.target}setContent(t){return this.skipMutation||this.text===t?Promise.resolve():(this.text=t,w.enqueue(()=>{this.skipMutation=!0,this.target.textContent=this.text}).finally(()=>{this.skipMutation=!1}))}}const q=class q{constructor(t){this.contents=[],this.isEvaluate=!1,this.isRawEvaluate=!1,this.value=t;const e=[...t.matchAll(q.PLACEHOLDER_REGEX)];let r=0,i=!1,s=!1;for(const n of e){n.index>r&&this.contents.push({text:t.slice(r,n.index),type:0});const a={text:n[1]??n[2],type:n[1]?2:1};i=!0,s=s||a.type===2,this.contents.push(a),r=n.index+n[0].length}r<t.length&&this.contents.push({text:t.slice(r),type:0}),this.isEvaluate=i,this.isRawEvaluate=s,this.checkRawExpressions()}static joinEvaluateResults(t){return t===null||t.length===0?"":t.map(e=>e==null||e===!1||Number.isNaN(e)?"":typeof e!="string"?String(e):e).join("")}getValue(){return this.value}checkRawExpressions(){for(let t=0;t<this.contents.length;t++)this.contents[t].type===2&&this.contents.length>1&&(h.error("[Haori]","Raw expressions are not allowed in multi-content expressions."),this.contents[t].type=1)}evaluate(t){if(!this.isEvaluate&&!this.isRawEvaluate)return this.contents.map(r=>r.text);const e=[];return this.contents.forEach(r=>{try{if(r.type===1||r.type===2){const i=H.evaluate(r.text,t);e.push(i)}else e.push(r.text)}catch(i){h.error("[Haori]",`Error evaluating text expression: ${r.text}`,i),e.push("")}}),e}};q.PLACEHOLDER_REGEX=/\{\{\{([\s\S]+?)\}\}\}|\{\{([\s\S]+?)\}\}/g;let $=q;const U=class U extends ${constructor(t,e){super(e),this.forceEvaluation=U.FORCE_EVALUATION_ATTRIBUTES.includes(t)}isForceEvaluation(){return this.forceEvaluation}evaluate(t){if(!this.isEvaluate&&!this.forceEvaluation)return this.contents.map(r=>r.text);const e=[];return this.contents.forEach(r=>{try{if(this.forceEvaluation&&r.type===0||r.type===1||r.type===2){const i=H.evaluate(r.text,t);e.push(i)}else e.push(r.text)}catch(i){h.error("[Haori]",`Error evaluating attribute expression: ${r.text}`,i),e.push("")}}),this.forceEvaluation&&e.length>1?(h.error("[Haori]","each or if expressions must have a single content.",e),[e[0]]):e}};U.FORCE_EVALUATION_ATTRIBUTES=["data-if","hor-if","data-each","hor-each"];let L=U;class E{static dispatch(t,e,r,i){const s=new CustomEvent(`haori:${e}`,{bubbles:i?.bubbles??!0,cancelable:i?.cancelable??!1,composed:i?.composed??!0,detail:r});return t.dispatchEvent(s)}static ready(t){E.dispatch(document,"ready",{version:t})}static render(t){E.dispatch(t,"render",{target:t})}static importStart(t,e){E.dispatch(t,"importstart",{url:e,startedAt:performance.now()})}static importEnd(t,e,r,i){E.dispatch(t,"importend",{url:e,bytes:r,durationMs:performance.now()-i})}static importError(t,e,r){E.dispatch(t,"importerror",{url:e,error:r})}static bindChange(t,e,r,i="other"){const s=[],n=new Set(Object.keys(e||{})),a=new Set(Object.keys(r)),o=new Set([...n,...a]);for(const g of o){const u=e?.[g],b=r[g];u!==b&&s.push(g)}E.dispatch(t,"bindchange",{previous:e||{},next:r,changedKeys:s,reason:i})}static eachUpdate(t,e,r,i){E.dispatch(t,"eachupdate",{added:e,removed:r,order:i,total:i.length})}static rowAdd(t,e,r,i){E.dispatch(t,"rowadd",{key:e,index:r,item:i})}static rowRemove(t,e,r){E.dispatch(t,"rowremove",{key:e,index:r})}static rowMove(t,e,r,i){E.dispatch(t,"rowmove",{key:e,from:r,to:i})}static show(t){E.dispatch(t,"show",{visible:!0})}static hide(t){E.dispatch(t,"hide",{visible:!1})}static fetchStart(t,e,r,i){E.dispatch(t,"fetchstart",{url:e,options:r||{},payload:i,startedAt:performance.now()})}static fetchEnd(t,e,r,i){E.dispatch(t,"fetchend",{url:e,status:r,durationMs:performance.now()-i})}static fetchError(t,e,r,i,s){E.dispatch(t,"fetcherror",{url:e,status:i,error:r,durationMs:s?performance.now()-s:void 0})}}class d{static attrName(t,e,r=!1){return t?`${c.prefix}${t}-${e}`:r?`${c.prefix}fetch-${e}`:`${c.prefix}${e}`}static buildOptions(t,e){const r={targetFragment:t};if(e){if(t.hasAttribute(d.attrName(e,"validate"))&&(r.valid=!0),t.hasAttribute(d.attrName(e,"confirm"))&&(r.confirmMessage=t.getAttribute(d.attrName(e,"confirm"))),t.hasAttribute(d.attrName(e,"data"))&&(r.data=N.parseDataBind(t.getRawAttribute(d.attrName(e,"data")))),t.hasAttribute(d.attrName(e,"form"))){const l=t.getRawAttribute(d.attrName(e,"form"));if(l){const f=document.body.querySelector(l);f!==null?r.formFragment=y.getFormFragment(A.get(f)):h.error("Haori",`Form element not found: ${l} (${d.attrName(e,"form")})`)}else r.formFragment=y.getFormFragment(t)}else e==="change"&&(r.formFragment=y.getFormFragment(t));if(t.hasAttribute(`${c.prefix}${e}-before-run`)){const l=t.getRawAttribute(`${c.prefix}${e}-before-run`);try{r.beforeCallback=new Function("fetchUrl","fetchOptions",`
5
6
  "use strict";
6
- ${o}
7
- `)}catch(d){h.error("Haori",`Invalid before script: ${d}`)}}}const i=f.attrName(e,"fetch"),r=t.hasAttribute(i);r&&(s.fetchUrl=t.getAttribute(i));const n={};if(e){const o=f.attrName(e,"fetch-method");t.hasAttribute(o)&&(n.method=t.getAttribute(o))}else{const o=f.attrName(null,"method",!0);t.hasAttribute(o)&&(n.method=t.getAttribute(o))}if(e){const o=f.attrName(e,"fetch-headers");if(t.hasAttribute(o)){const d=t.getRawAttribute(o);try{n.headers=N.parseDataBind(d)}catch(g){h.error("Haori",`Invalid fetch headers: ${g}`)}}}else{const o=f.attrName(null,"headers",!0);if(t.hasAttribute(o)){const d=t.getRawAttribute(o);try{n.headers=N.parseDataBind(d)}catch(g){h.error("Haori",`Invalid fetch headers: ${g}`)}}}if(e){const o=f.attrName(e,"fetch-content-type");if(t.hasAttribute(o))n.headers={...n.headers,"Content-Type":t.getAttribute(o)};else if(n.method&&n.method!=="GET"&&n.method!=="HEAD"&&n.method!=="OPTIONS"){let d=!1;n.headers&&typeof n.headers=="object"&&(d="Content-Type"in n.headers),d||(n.headers={...n.headers,"Content-Type":"application/json"})}else n.method&&(n.method==="GET"||n.method==="HEAD"||n.method==="OPTIONS")&&(n.headers={...n.headers,"Content-Type":"application/x-www-form-urlencoded"})}else{const o=f.attrName(null,"content-type",!0);if(t.hasAttribute(o))n.headers={...n.headers,"Content-Type":t.getAttribute(o)};else if(n.method&&n.method!=="GET"&&n.method!=="HEAD"&&n.method!=="OPTIONS"){let d=!1;n.headers&&typeof n.headers=="object"&&(d="Content-Type"in n.headers),d||(n.headers={...n.headers,"Content-Type":"application/json"})}else n.method&&(n.method==="GET"||n.method==="HEAD"||n.method==="OPTIONS")&&(n.headers={...n.headers,"Content-Type":"application/x-www-form-urlencoded"})}Object.keys(n).length>0&&(s.fetchOptions=n);const a=e?f.attrName(e,"bind"):f.attrName(null,"bind",!0);if(t.hasAttribute(a)){const o=t.getRawAttribute(a);if(o){const d=document.body.querySelectorAll(o);d.length>0?(s.bindFragments=[],d.forEach(g=>{const w=A.get(g);w&&s.bindFragments.push(w)})):h.error("Haori",`Bind element not found: ${o} (${a})`)}}const u=f.attrName(e,"bind-arg"),b=f.attrName(null,"arg",!0),l=f.attrName(null,"bind-arg",!0);e?t.hasAttribute(u)&&(s.bindArg=t.getRawAttribute(u)):t.hasAttribute(b)?s.bindArg=t.getRawAttribute(b):t.hasAttribute(l)&&(s.bindArg=t.getRawAttribute(l));const E=e?f.attrName(e,"bind-params"):f.attrName(null,"bind-params",!0);if(t.hasAttribute(E)){const o=t.getRawAttribute(E);s.bindParams=o.split("&").map(d=>d.trim())}if(e){if(t.hasAttribute(f.attrName(e,"adjust"))){const d=t.getRawAttribute(f.attrName(e,"adjust"));if(d){const g=document.body.querySelectorAll(d);g.length>0?(s.adjustFragments=[],g.forEach(w=>{const T=A.get(w);T&&s.adjustFragments.push(T)})):h.error("Haori",`Adjust element not found: ${d} (${f.attrName(e,"adjust")})`)}if(t.hasAttribute(f.attrName(e,"adjust-value"))){const g=t.getRawAttribute(f.attrName(e,"adjust-value")),w=Number(g);isNaN(w)||(s.adjustValue=w)}}if(t.hasAttribute(f.attrName(e,"row-add"))&&(s.rowAdd=!0),t.hasAttribute(f.attrName(e,"row-remove"))&&(s.rowRemove=!0),t.hasAttribute(f.attrName(e,"row-prev"))&&(s.rowMovePrev=!0),t.hasAttribute(f.attrName(e,"row-next"))&&(s.rowMoveNext=!0),t.hasAttribute(`${c.prefix}${e}-after-run`)){const d=t.getRawAttribute(`${c.prefix}${e}-after-run`);try{s.afterCallback=new Function("response",`
7
+ ${l}
8
+ `)}catch(f){h.error("Haori",`Invalid before script: ${f}`)}}}const i=d.attrName(e,"fetch"),s=t.hasAttribute(i);s&&(r.fetchUrl=t.getAttribute(i));const n={};if(e){const l=d.attrName(e,"fetch-method");t.hasAttribute(l)&&(n.method=t.getAttribute(l))}else{const l=d.attrName(null,"method",!0);t.hasAttribute(l)&&(n.method=t.getAttribute(l))}if(e){const l=d.attrName(e,"fetch-headers");if(t.hasAttribute(l)){const f=t.getRawAttribute(l);try{n.headers=N.parseDataBind(f)}catch(p){h.error("Haori",`Invalid fetch headers: ${p}`)}}}else{const l=d.attrName(null,"headers",!0);if(t.hasAttribute(l)){const f=t.getRawAttribute(l);try{n.headers=N.parseDataBind(f)}catch(p){h.error("Haori",`Invalid fetch headers: ${p}`)}}}if(e){const l=d.attrName(e,"fetch-content-type");if(t.hasAttribute(l))n.headers={...n.headers,"Content-Type":t.getAttribute(l)};else if(n.method&&n.method!=="GET"&&n.method!=="HEAD"&&n.method!=="OPTIONS"){let f=!1;n.headers&&typeof n.headers=="object"&&(f="Content-Type"in n.headers),f||(n.headers={...n.headers,"Content-Type":"application/json"})}else n.method&&(n.method==="GET"||n.method==="HEAD"||n.method==="OPTIONS")&&(n.headers={...n.headers,"Content-Type":"application/x-www-form-urlencoded"})}else{const l=d.attrName(null,"content-type",!0);if(t.hasAttribute(l))n.headers={...n.headers,"Content-Type":t.getAttribute(l)};else if(n.method&&n.method!=="GET"&&n.method!=="HEAD"&&n.method!=="OPTIONS"){let f=!1;n.headers&&typeof n.headers=="object"&&(f="Content-Type"in n.headers),f||(n.headers={...n.headers,"Content-Type":"application/json"})}else n.method&&(n.method==="GET"||n.method==="HEAD"||n.method==="OPTIONS")&&(n.headers={...n.headers,"Content-Type":"application/x-www-form-urlencoded"})}Object.keys(n).length>0&&(r.fetchOptions=n);const a=e?d.attrName(e,"bind"):d.attrName(null,"bind",!0);if(t.hasAttribute(a)){const l=t.getRawAttribute(a);if(l){const f=document.body.querySelectorAll(l);f.length>0?(r.bindFragments=[],f.forEach(p=>{const v=A.get(p);v&&r.bindFragments.push(v)})):h.error("Haori",`Bind element not found: ${l} (${a})`)}}const o=d.attrName(e,"bind-arg"),g=d.attrName(null,"arg",!0),u=d.attrName(null,"bind-arg",!0);e?t.hasAttribute(o)&&(r.bindArg=t.getRawAttribute(o)):t.hasAttribute(g)?r.bindArg=t.getRawAttribute(g):t.hasAttribute(u)&&(r.bindArg=t.getRawAttribute(u));const b=e?d.attrName(e,"bind-params"):d.attrName(null,"bind-params",!0);if(t.hasAttribute(b)){const l=t.getRawAttribute(b);r.bindParams=l.split("&").map(f=>f.trim())}if(e){if(t.hasAttribute(d.attrName(e,"adjust"))){const f=t.getRawAttribute(d.attrName(e,"adjust"));if(f){const p=document.body.querySelectorAll(f);p.length>0?(r.adjustFragments=[],p.forEach(v=>{const T=A.get(v);T&&r.adjustFragments.push(T)})):h.error("Haori",`Adjust element not found: ${f} (${d.attrName(e,"adjust")})`)}if(t.hasAttribute(d.attrName(e,"adjust-value"))){const p=t.getRawAttribute(d.attrName(e,"adjust-value")),v=Number(p);isNaN(v)||(r.adjustValue=v)}}if(t.hasAttribute(d.attrName(e,"row-add"))&&(r.rowAdd=!0),t.hasAttribute(d.attrName(e,"row-remove"))&&(r.rowRemove=!0),t.hasAttribute(d.attrName(e,"row-prev"))&&(r.rowMovePrev=!0),t.hasAttribute(d.attrName(e,"row-next"))&&(r.rowMoveNext=!0),t.hasAttribute(`${c.prefix}${e}-after-run`)){const f=t.getRawAttribute(`${c.prefix}${e}-after-run`);try{r.afterCallback=new Function("response",`
8
9
  "use strict";
9
- ${d}
10
- `)}catch(g){h.error("Haori",`Invalid after script: ${g}`)}}t.hasAttribute(f.attrName(e,"dialog"))&&(s.dialogMessage=t.getAttribute(f.attrName(e,"dialog"))),t.hasAttribute(f.attrName(e,"toast"))&&(s.toastMessage=t.getAttribute(f.attrName(e,"toast"))),t.hasAttribute(f.attrName(e,"redirect"))&&(s.redirectUrl=t.getAttribute(f.attrName(e,"redirect"))),["reset","refetch","click","open","close"].forEach(d=>{const g=f.attrName(e,d);if(!t.hasAttribute(g))return;const w=t.getRawAttribute(g),T=[];if(w?(document.body.querySelectorAll(w).forEach(x=>{const S=A.get(x);S&&T.push(S)}),T.length===0&&h.error("Haori",`Element not found: ${w} (${g})`)):T.push(t),T.length>0)switch(d){case"reset":s.resetFragments=T;break;case"refetch":s.refetchFragments=T;break;case"click":s.clickFragments=T;break;case"open":s.openFragments=T;break;case"close":s.closeFragments=T;break}})}if(!e){if(t.hasAttribute(f.attrName(null,"data",!0))){const o=t.getRawAttribute(f.attrName(null,"data",!0));s.data=N.parseDataBind(o)}if(t.hasAttribute(f.attrName(null,"form",!0))){const o=t.getRawAttribute(f.attrName(null,"form",!0));if(o){const d=document.body.querySelector(o);d!==null?s.formFragment=m.getFormFragment(A.get(d)):h.error("Haori",`Form element not found: ${o} (${f.attrName(null,"fetch-form",!0)})`)}else s.formFragment=m.getFormFragment(t)}}return r&&(!s.bindFragments||s.bindFragments.length===0)&&(s.bindFragments=[t]),s}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){f.isElementFragment(t)?this.options=f.buildOptions(t,e):this.options=t}run(){return Object.keys(this.options).length===0||this.options.formFragment&&this.validate(this.options.formFragment)===!1?Promise.resolve():this.confirm().then(t=>{if(!t)return Promise.resolve();let e=this.options.fetchUrl,s=this.options.fetchOptions;if(this.options.beforeCallback){const n=this.options.beforeCallback(e||null,s||null);if(n!=null){if(n===!1||typeof n=="object"&&n.stop)return Promise.resolve();typeof n=="object"&&(e="fetchUrl"in n?n.fetchUrl:e,s="fetchOptions"in n?n.fetchOptions:s)}}const i={};if(this.options.formFragment){const n=m.getValues(this.options.formFragment);Object.assign(i,n)}this.options.data&&typeof this.options.data=="object"&&Object.assign(i,this.options.data);const r=Object.keys(i).length>0;if(e){const n={...s||{}},a=new Headers(n.headers||void 0),u=(n.method||"GET").toUpperCase();if(u==="GET"||u==="HEAD"||u==="OPTIONS"){if(r){const b=new URL(e,window.location.href),l=new URLSearchParams(b.search);for(const[E,o]of Object.entries(i))o!==void 0&&(o===null?l.append(E,""):Array.isArray(o)?o.forEach(d=>{l.append(E,String(d))}):typeof o=="object"||typeof o=="function"?l.append(E,JSON.stringify(o)):l.append(E,String(o)));b.search=l.toString(),e=b.toString()}}else if(r){const b=a.get("Content-Type")||"";if(/multipart\/form-data/i.test(b)){a.delete("Content-Type");const l=new FormData;for(const[E,o]of Object.entries(i))o==null?l.append(E,""):o instanceof Blob?l.append(E,o):Array.isArray(o)?o.forEach(d=>l.append(E,String(d))):typeof o=="object"?l.append(E,JSON.stringify(o)):l.append(E,String(o));n.body=l}else if(/application\/x-www-form-urlencoded/i.test(b)){const l=new URLSearchParams;for(const[E,o]of Object.entries(i))o!==void 0&&(o===null?l.append(E,""):Array.isArray(o)?o.forEach(d=>l.append(E,String(d))):typeof o=="object"?l.append(E,JSON.stringify(o)):l.append(E,String(o)));n.body=l}else a.set("Content-Type","application/json"),n.body=JSON.stringify(i)}if(n.headers=a,this.options.targetFragment&&e){const b=performance.now();return y.fetchStart(this.options.targetFragment.getTarget(),e,n,r?i:void 0),fetch(e,n).then(l=>this.handleFetchResult(l,e||void 0,b)).catch(l=>{throw e&&y.fetchError(this.options.targetFragment.getTarget(),e,l),l})}else return e?fetch(e,n).then(b=>this.handleFetchResult(b,e||void 0)):Promise.resolve()}else{if((!this.options.bindFragments||this.options.bindFragments.length===0)&&this.options.formFragment&&r){const u=this.options.formFragment,b=u.getTarget();b.setAttribute(`${c.prefix}bind`,JSON.stringify(i));const l=u.getBindingData();return Object.assign(l,i),N.setBindingData(b,l)}const n=r?i:{},a=new Response(JSON.stringify(n),{headers:{"Content-Type":"application/json"}});return this.handleFetchResult(a)}})}handleFetchResult(t,e,s){if(!t.ok)return this.options.targetFragment&&e&&y.fetchError(this.options.targetFragment.getTarget(),e,new Error(`${t.status} ${t.statusText}`),t.status,s),this.handleFetchError(t);if(this.options.targetFragment&&e&&s&&y.fetchEnd(this.options.targetFragment.getTarget(),e,t.status,s),this.options.afterCallback){const r=this.options.afterCallback(t);if(r!=null){if(r===!1||typeof r=="object"&&r.stop)return Promise.resolve();typeof r=="object"&&"response"in r&&(t="response"in r?r.response:t)}}const i=[];return i.push(this.bindResult(t)),i.push(this.adjust()),i.push(this.addRow()),i.push(this.removeRow()),i.push(this.movePrevRow()),i.push(this.moveNextRow()),this.options.resetFragments&&this.options.resetFragments.length>0&&this.options.resetFragments.forEach(r=>{i.push(m.reset(r))}),this.options.refetchFragments&&this.options.refetchFragments.length>0&&this.options.refetchFragments.forEach(r=>{i.push(new f(r,null).run())}),this.options.clickFragments&&this.options.clickFragments.length>0&&this.options.clickFragments.forEach(r=>{const n=r.getTarget();typeof n.click=="function"?n.click():n.dispatchEvent(new MouseEvent("click",{bubbles:!0,cancelable:!0}))}),this.options.openFragments&&this.options.openFragments.length>0&&this.options.openFragments.forEach(r=>{const n=r.getTarget();n instanceof HTMLDialogElement?i.push(M.openDialog(n)):h.error("Haori","Element is not a dialog: ",n)}),this.options.closeFragments&&this.options.closeFragments.length>0&&this.options.closeFragments.forEach(r=>{const n=r.getTarget();n instanceof HTMLDialogElement?i.push(M.closeDialog(n)):h.error("Haori","Element is not a dialog: ",n)}),Promise.all(i).then(()=>this.options.dialogMessage?M.dialog(this.options.dialogMessage):Promise.resolve()).then(()=>this.options.toastMessage?M.toast(this.options.toastMessage,"info"):Promise.resolve()).then(()=>(this.options.redirectUrl&&(window.location.href=this.options.redirectUrl),Promise.resolve()))}async handleFetchError(t){let e=null;this.options.formFragment?e=this.options.formFragment:this.options.targetFragment&&(e=m.getFormFragment(this.options.targetFragment)||this.options.targetFragment);const s=async r=>{const n=e?e.getTarget():document.body;await M.addErrorMessage(n,r)};if((t.headers.get("Content-Type")||"").includes("application/json"))try{const r=await t.json(),n=[];if(r&&typeof r=="object"){if(typeof r.message=="string"&&n.push({message:r.message}),Array.isArray(r.messages))for(const a of r.messages)typeof a=="string"&&n.push({message:a});if(r.errors&&typeof r.errors=="object")for(const[a,u]of Object.entries(r.errors))Array.isArray(u)?n.push({key:a,message:u.join(`
11
- `)}):typeof u=="string"?n.push({key:a,message:u}):u!=null&&n.push({key:a,message:String(u)});if(n.length===0)for(const[a,u]of Object.entries(r))a==="message"||a==="messages"||a==="errors"||(Array.isArray(u)?n.push({key:a,message:u.join(`
12
- `)}):typeof u=="string"&&n.push({key:a,message:u}))}if(n.length===0){await s(`${t.status} ${t.statusText}`);return}for(const a of n)a.key&&e?await m.addErrorMessage(e,a.key,a.message):await s(a.message);return}catch{}try{const r=await t.text();r&&r.trim().length>0?await s(r.trim()):await s(`${t.status} ${t.statusText}`)}catch{await s(`${t.status} ${t.statusText}`)}}validate(t){if(this.options.valid!==!0)return!0;const e=t.getTarget();let s=this.validateOne(t);return s||e.focus(),t.getChildElementFragments().reverse().forEach(i=>{s&&=this.validate(i)}),s}validateOne(t){const e=t.getTarget();return e instanceof HTMLInputElement||e instanceof HTMLSelectElement||e instanceof HTMLTextAreaElement?e.reportValidity():!0}confirm(){const t=this.options.confirmMessage;return t==null?Promise.resolve(!0):M.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(s=>{if(this.options.bindParams){const r={};this.options.bindParams.forEach(n=>{s&&typeof s=="object"&&n in s&&(r[n]=s[n])}),s=r}const i=[];if(this.options.bindArg)this.options.bindFragments.forEach(r=>{const n=r.getBindingData();n[this.options.bindArg]=s,i.push(N.setBindingData(r.getTarget(),n))});else{if(typeof s=="string")return h.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(r=>{i.push(N.setBindingData(r.getTarget(),s))})}return Promise.all(i).then(()=>{})})}adjust(){if(!this.options.adjustFragments||this.options.adjustFragments.length===0)return Promise.resolve();const t=this.options.adjustValue??0,e=[];for(const s of this.options.adjustFragments){let i=s.getValue();(i==null||i==="")&&(i="0");let r=Number(i);isNaN(r)&&(r=0),r+=t,e.push(s.setValue(String(r)))}return Promise.all(e).then(()=>{})}getRowFragment(){if(!this.options.targetFragment)return h.error("Haori","Target fragment is not specified for row operation."),null;const t=this.options.targetFragment.closestByAttribute(`${c.prefix}row`);return t||(h.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=[],s=t.clone();return e.push(t.getParent().insertAfter(s,t)),e.push(N.evaluateAll(s)),e.push(m.reset(s)),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(i=>!i.hasAttribute(`${c.prefix}each-before`)&&!i.hasAttribute(`${c.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 s=t.getParent();return s?s.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 s=t.getParent();return s?s.insertAfter(t,e):Promise.resolve()}}class J{static readParams(){const t={},e=window.location.search;return new URLSearchParams(e).forEach((i,r)=>{t[r]=i}),t}}class W{static async load(t,e){let s;try{s=await fetch(t,e)}catch(r){throw h.error("[Haori]","Failed to fetch import source:",t,r),new Error(`Failed to fetch: ${t}`)}if(!s.ok){const r=`${s.status} ${s.statusText}`;throw h.error("[Haori]","Import HTTP error:",t,r),new Error(`Failed to load ${t}: ${r}`)}let i;try{i=await s.text()}catch(r){throw h.error("[Haori]","Failed to read response text:",t,r),new Error(`Failed to read response from: ${t}`)}try{const n=new DOMParser().parseFromString(i,"text/html");return n&&n.body?n.body.innerHTML:(h.warn("[Haori]","No body found in imported document:",t),i)}catch(r){return h.error("[Haori]","Failed to parse imported HTML:",t,r),i}}}const p=class p{static isDeferredAttributeName(t){return p.DEFERRED_ATTRIBUTE_SUFFIXES.some(e=>t===`${c.prefix}${e}`)}static scan(t){const e=A.get(t);if(!e)return Promise.resolve();t.parentNode&&(A.get(t.parentNode)?.isMounted()||document.body.contains(t)?e.setMounted(!0):e.setMounted(!1));const s=[],i=new Set;for(const r of p.PRIORITY_ATTRIBUTE_SUFFIXES){const n=c.prefix+r;e.hasAttribute(n)&&(s.push(p.setAttribute(e.getTarget(),n,e.getRawAttribute(n))),i.add(n))}for(const r of e.getAttributeNames()){if(i.has(r)||p.isDeferredAttributeName(r))continue;const n=e.getRawAttribute(r);n!==null&&s.push(p.setAttribute(e.getTarget(),r,n))}for(const r of p.DEFERRED_ATTRIBUTE_SUFFIXES){const n=c.prefix+r;e.hasAttribute(n)&&(s.push(p.setAttribute(e.getTarget(),n,e.getRawAttribute(n))),i.add(n))}return e.getChildren().forEach(r=>{r instanceof F?s.push(p.scan(r.getTarget())):r instanceof j&&s.push(p.evaluateText(r))}),Promise.all(s).then(()=>{})}static setAttribute(t,e,s){const i=A.get(t),r=[];switch(e){case`${c.prefix}bind`:{s===null?(i.clearBindingDataCache(),i.setBindingData({})):i.setBindingData(p.parseDataBind(s));break}case`${c.prefix}if`:r.push(p.evaluateIf(i));break;case`${c.prefix}each`:r.push(p.evaluateEach(i));break;case`${c.prefix}fetch`:r.push(new f(i,null).run());break;case`${c.prefix}import`:{if(typeof s=="string"){const n=i.getTarget(),a=performance.now();y.importStart(n,s),r.push(W.load(s).then(u=>{const b=new TextEncoder().encode(u).length;return v.enqueue(()=>{n.innerHTML=u}).then(()=>{y.importEnd(n,s,b,a)})}).catch(u=>{y.importError(n,s,u),h.error("[Haori]","Failed to import HTML:",s,u)}))}break}case`${c.prefix}url-param`:{const n=i.getAttribute(`${c.prefix}url-arg`),a=J.readParams();if(n===null)p.setBindingData(t,a);else{const u=i.getRawBindingData()||{};u[String(n)]=a,p.setBindingData(t,u)}break}}return s===null?r.push(i.removeAttribute(e)):r.push(i.setAttribute(e,s)),Promise.all(r).then(()=>{})}static setBindingData(t,e){const s=A.get(t),i=s.getRawBindingData();s.setBindingData(e);const r=[];return r.push(s.setAttribute(`${c.prefix}bind`,JSON.stringify(e))),r.push(p.evaluateAll(s)),y.bindChange(t,i,e,"manual"),Promise.all(r).then(()=>{})}static parseDataBind(t){if(t.startsWith("{")||t.startsWith("["))try{return JSON.parse(t)}catch(e){return h.error("[Haori]","Invalid JSON in data-bind:",e),{}}else{const e=new URLSearchParams(t),s={};for(const[i,r]of e.entries())s[i]!==void 0?Array.isArray(s[i])?s[i].push(r):s[i]=[s[i],r]:s[i]=r;return s}}static addNode(t,e){const s=A.get(t);if(s.isSkipMutationNodes())return;const i=A.get(e.nextSibling),r=A.get(e);r&&(s.insertBefore(r,i),r instanceof F?p.scan(r.getTarget()):r instanceof j&&p.evaluateText(r))}static removeNode(t){const e=A.get(t);if(e){const s=e.getParent();if(s&&s.isSkipMutationNodes())return;e.remove()}}static changeText(t,e){const s=A.get(t);s&&s.setContent(e)}static changeValue(t,e){const s=A.get(t);if(s.getValue()===e)return Promise.resolve();const i=[];i.push(s.setValue(e));const r=p.getFormFragment(s);if(r){const n=m.getValues(r),a=r.getAttribute(`${c.prefix}form-arg`);let u;a?(u=r.getRawBindingData(),u||(u={}),u[String(a)]=n):u=n,i.push(p.setBindingData(r.getTarget(),u))}return Promise.all(i).then(()=>{})}static getFormFragment(t){if(t.getTarget()instanceof HTMLFormElement)return t;const e=t.getParent();return e?p.getFormFragment(e):null}static evaluateAll(t){const e=[];return t.hasAttribute(`${c.prefix}if`)&&e.push(p.evaluateIf(t)),t.hasAttribute(`${c.prefix}each`)&&e.push(p.evaluateEach(t)),t.getChildren().forEach(s=>{s instanceof F?e.push(p.evaluateAll(s)):s instanceof j&&e.push(p.evaluateText(s))}),Promise.all(e).then(()=>{})}static evaluateText(t){return t.evaluate()}static evaluateIf(t){const e=[],s=t.getAttribute(`${c.prefix}if`);return s===!1||s===void 0||s===null||Number.isNaN(s)?t.isVisible()&&e.push(t.hide().then(()=>{y.hide(t.getTarget())})):t.isVisible()||(e.push(t.show().then(()=>{y.show(t.getTarget())})),e.push(p.evaluateAll(t))),Promise.all(e).then(()=>{})}static evaluateEach(t){if(!t.isVisible()||!t.isMounted())return Promise.resolve();let e=t.getTemplate();if(e===null){const i=[];t.getChildren().forEach(n=>{if(n instanceof F){if(n.hasAttribute(`${c.prefix}each-before`)||n.hasAttribute(`${c.prefix}each-after`))return;if(e===null){e=n,t.removeChild(n);const a=n.getTarget();a.parentNode&&i.push(v.enqueue(()=>{a.parentNode&&a.parentNode.removeChild(a),n.setMounted(!1)}))}else h.warn("[Haori]","Template must be a single child element.")}}),t.setTemplate(e);const r=t.getAttribute(`${c.prefix}each`);return Array.isArray(r)?Promise.all(i).then(()=>this.updateDiff(t,r)):(h.error("[Haori]","Invalid each attribute:",r),Promise.reject(new Error("Invalid each attribute.")))}const s=t.getAttribute(`${c.prefix}each`);return Array.isArray(s)?this.updateDiff(t,s):(h.error("[Haori]","Invalid each attribute:",s),Promise.reject(new Error("Invalid each attribute.")))}static updateDiff(t,e){const s=t.getTemplate();if(s===null)return h.error("[Haori]","Template is not set for each element."),Promise.resolve();let i=t.getAttribute(`${c.prefix}each-index`);i&&(i=String(i));const r=t.getAttribute(`${c.prefix}each-key`),n=t.getAttribute(`${c.prefix}each-arg`),a=new Map,u=[];e.forEach((g,w)=>{const T=p.createListKey(g,r?String(r):null,w);u.push(T),a.set(T,{item:g,itemIndex:w})});const b=[];let l=t.getChildren().filter(g=>g instanceof F).filter(g=>!g.hasAttribute(`${c.prefix}each-before`)&&!g.hasAttribute(`${c.prefix}each-after`));l=l.filter(g=>u.indexOf(String(g.getListKey()))===-1?(b.push(g.remove()),!1):!0);const E=l.map(g=>g.getListKey()),o=t.getChildren().filter(g=>g instanceof F).filter(g=>g.hasAttribute(`${c.prefix}each-before`)).length;let d=Promise.resolve();return u.forEach((g,w)=>{const T=E.indexOf(g),{item:B,itemIndex:x}=a.get(g);let S;T!==-1?S=l[T]:S=s.clone(),p.updateRowFragment(S,B,i,x,n?String(n):null,g);const G=o+w;d=d.then(()=>t.insertBefore(S,t.getChildren()[G]||null).then(()=>p.evaluateAll(S)))}),Promise.all(b).then(()=>d).then(()=>{const g=u.filter(x=>x!==null),w=E.filter(x=>x!==null),T=g.filter(x=>!w.includes(x)),B=w.filter(x=>!g.includes(x));y.eachUpdate(t.getTarget(),T,B,g)})}static createListKey(t,e,s){let i;if(typeof t=="object"&&t!==null)if(e){const r=t[e];r==null?i=`__index_${s}`:typeof r=="object"?i=JSON.stringify(r):i=String(r)}else i=`__index_${s}`;else i=String(t);return i}static updateRowFragment(t,e,s,i,r,n){let a=e;if(typeof e=="object"&&e!==null)a={...e},s&&(a[s]=i),r&&(a={[r]:a});else if(r)a={[r]:e},s&&(a[s]=i);else{h.error("[Haori]",`Primitive value requires '${c.prefix}each-arg' attribute: ${e}`);return}t.setListKey(n),t.setAttribute(`${c.prefix}row`,n),t.setBindingData(a)}};p.PRIORITY_ATTRIBUTE_SUFFIXES=["bind","if","each"],p.DEFERRED_ATTRIBUTE_SUFFIXES=["fetch","url-param"];let N=p;class Y{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,s=A.get(e);s&&new f(s,"load").run()},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})}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)}delegate(t,e){const s=this.getElementFromTarget(t.target);if(!s)return;const i=A.get(s);i&&(e==="change"&&i instanceof F&&i.syncValue(),new f(i,e).run().catch(r=>{h.error("[Haori]","Procedure execution error:",r)}))}getElementFromTarget(t){return t?t instanceof HTMLElement?t:t instanceof Node?t.parentElement:null:null}}class O{static async init(){const t=await Promise.allSettled([N.scan(document.head),N.scan(document.body)]),[e,s]=t;e.status!=="fulfilled"&&h.error("[Haori]","Failed to build head fragment:",e.reason),s.status!=="fulfilled"&&h.error("[Haori]","Failed to build body fragment:",s.reason),O.observe(document.head),O.observe(document.body),new Y().start()}static observe(t){new MutationObserver(async s=>{for(const i of s)try{switch(i.type){case"attributes":{h.info("[Haori]","Attribute changed:",i.target,i.attributeName);const r=i.target;N.setAttribute(r,i.attributeName,r.getAttribute(i.attributeName));break}case"childList":{h.info("[Haori]","Child list changed:",Array.from(i.removedNodes).map(r=>r.nodeName),Array.from(i.addedNodes).map(r=>r.nodeName)),Array.from(i.removedNodes).forEach(r=>{N.removeNode(r)}),Array.from(i.addedNodes).forEach(r=>{r.parentElement instanceof HTMLElement&&N.addNode(r.parentElement,r)});break}case"characterData":{h.info("[Haori]","Character data changed:",i.target,i.target.textContent),i.target instanceof Text||i.target instanceof Comment?N.changeText(i.target,i.target.textContent):h.warn("[Haori]","Unsupported character data type:",i.target);break}default:h.warn("[Haori]","Unknown mutation type:",i.type);continue}}catch(r){h.error("[Haori]","Error processing mutation:",r)}}).observe(t,{childList:!0,subtree:!0,attributes:!0,characterData:!0}),h.info("[Haori]","Observer initialized for",t)}}document.readyState==="loading"?document.addEventListener("DOMContentLoaded",O.init):O.init();const Q="0.1.0";exports.Core=N;exports.Env=c;exports.Form=m;exports.Fragment=A;exports.Haori=M;exports.Log=h;exports.Queue=v;exports.default=M;exports.version=Q;
10
+ ${f}
11
+ `)}catch(p){h.error("Haori",`Invalid after script: ${p}`)}}t.hasAttribute(d.attrName(e,"dialog"))&&(r.dialogMessage=t.getAttribute(d.attrName(e,"dialog"))),t.hasAttribute(d.attrName(e,"toast"))&&(r.toastMessage=t.getAttribute(d.attrName(e,"toast"))),t.hasAttribute(d.attrName(e,"redirect"))&&(r.redirectUrl=t.getAttribute(d.attrName(e,"redirect"))),["reset","refetch","click","open","close"].forEach(f=>{const p=d.attrName(e,f);if(!t.hasAttribute(p))return;const v=t.getRawAttribute(p),T=[];if(v?(document.body.querySelectorAll(v).forEach(x=>{const F=A.get(x);F&&T.push(F)}),T.length===0&&h.error("Haori",`Element not found: ${v} (${p})`)):T.push(t),T.length>0)switch(f){case"reset":r.resetFragments=T;break;case"refetch":r.refetchFragments=T;break;case"click":r.clickFragments=T;break;case"open":r.openFragments=T;break;case"close":r.closeFragments=T;break}})}if(!e){if(t.hasAttribute(d.attrName(null,"data",!0))){const l=t.getRawAttribute(d.attrName(null,"data",!0));r.data=N.parseDataBind(l)}if(t.hasAttribute(d.attrName(null,"form",!0))){const l=t.getRawAttribute(d.attrName(null,"form",!0));if(l){const f=document.body.querySelector(l);f!==null?r.formFragment=y.getFormFragment(A.get(f)):h.error("Haori",`Form element not found: ${l} (${d.attrName(null,"fetch-form",!0)})`)}else r.formFragment=y.getFormFragment(t)}}return s&&(!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){d.isElementFragment(t)?this.options=d.buildOptions(t,e):this.options=t}run(){return Object.keys(this.options).length===0||this.options.formFragment&&this.validate(this.options.formFragment)===!1?Promise.resolve():this.confirm().then(t=>{if(!t)return Promise.resolve();let e=this.options.fetchUrl,r=this.options.fetchOptions;if(this.options.beforeCallback){const n=this.options.beforeCallback(e||null,r||null);if(n!=null){if(n===!1||typeof n=="object"&&n.stop)return Promise.resolve();typeof n=="object"&&(e="fetchUrl"in n?n.fetchUrl:e,r="fetchOptions"in n?n.fetchOptions:r)}}const i={};if(this.options.formFragment){const n=y.getValues(this.options.formFragment);Object.assign(i,n)}this.options.data&&typeof this.options.data=="object"&&Object.assign(i,this.options.data);const s=Object.keys(i).length>0;if(e){const n={...r||{}},a=new Headers(n.headers||void 0),o=(n.method||"GET").toUpperCase();if(o==="GET"||o==="HEAD"||o==="OPTIONS"){if(s){const g=new URL(e,window.location.href),u=new URLSearchParams(g.search);for(const[b,l]of Object.entries(i))l!==void 0&&(l===null?u.append(b,""):Array.isArray(l)?l.forEach(f=>{u.append(b,String(f))}):typeof l=="object"||typeof l=="function"?u.append(b,JSON.stringify(l)):u.append(b,String(l)));g.search=u.toString(),e=g.toString()}}else if(s){const g=a.get("Content-Type")||"";if(/multipart\/form-data/i.test(g)){a.delete("Content-Type");const u=new FormData;for(const[b,l]of Object.entries(i))l==null?u.append(b,""):l instanceof Blob?u.append(b,l):Array.isArray(l)?l.forEach(f=>u.append(b,String(f))):typeof l=="object"?u.append(b,JSON.stringify(l)):u.append(b,String(l));n.body=u}else if(/application\/x-www-form-urlencoded/i.test(g)){const u=new URLSearchParams;for(const[b,l]of Object.entries(i))l!==void 0&&(l===null?u.append(b,""):Array.isArray(l)?l.forEach(f=>u.append(b,String(f))):typeof l=="object"?u.append(b,JSON.stringify(l)):u.append(b,String(l)));n.body=u}else a.set("Content-Type","application/json"),n.body=JSON.stringify(i)}if(n.headers=a,this.options.targetFragment&&e){const g=performance.now();return E.fetchStart(this.options.targetFragment.getTarget(),e,n,s?i:void 0),fetch(e,n).then(u=>this.handleFetchResult(u,e||void 0,g)).catch(u=>{throw e&&E.fetchError(this.options.targetFragment.getTarget(),e,u),u})}else return e?fetch(e,n).then(g=>this.handleFetchResult(g,e||void 0)):Promise.resolve()}else{if((!this.options.bindFragments||this.options.bindFragments.length===0)&&this.options.formFragment&&s){const o=this.options.formFragment,g=o.getTarget();g.setAttribute(`${c.prefix}bind`,JSON.stringify(i));const u=o.getBindingData();return Object.assign(u,i),N.setBindingData(g,u)}const n=s?i:{},a=new Response(JSON.stringify(n),{headers:{"Content-Type":"application/json"}});return this.handleFetchResult(a)}})}handleFetchResult(t,e,r){if(!t.ok)return this.options.targetFragment&&e&&E.fetchError(this.options.targetFragment.getTarget(),e,new Error(`${t.status} ${t.statusText}`),t.status,r),this.handleFetchError(t);if(this.options.targetFragment&&e&&r&&E.fetchEnd(this.options.targetFragment.getTarget(),e,t.status,r),this.options.afterCallback){const s=this.options.afterCallback(t);if(s!=null){if(s===!1||typeof s=="object"&&s.stop)return Promise.resolve();typeof s=="object"&&"response"in s&&(t="response"in s?s.response:t)}}const i=[];return i.push(this.bindResult(t)),i.push(this.adjust()),i.push(this.addRow()),i.push(this.removeRow()),i.push(this.movePrevRow()),i.push(this.moveNextRow()),this.options.resetFragments&&this.options.resetFragments.length>0&&this.options.resetFragments.forEach(s=>{i.push(y.reset(s))}),this.options.refetchFragments&&this.options.refetchFragments.length>0&&this.options.refetchFragments.forEach(s=>{i.push(new d(s,null).run())}),this.options.clickFragments&&this.options.clickFragments.length>0&&this.options.clickFragments.forEach(s=>{const n=s.getTarget();typeof n.click=="function"?n.click():n.dispatchEvent(new MouseEvent("click",{bubbles:!0,cancelable:!0}))}),this.options.openFragments&&this.options.openFragments.length>0&&this.options.openFragments.forEach(s=>{const n=s.getTarget();n instanceof HTMLDialogElement?i.push(k.openDialog(n)):h.error("Haori","Element is not a dialog: ",n)}),this.options.closeFragments&&this.options.closeFragments.length>0&&this.options.closeFragments.forEach(s=>{const n=s.getTarget();n instanceof HTMLDialogElement?i.push(k.closeDialog(n)):h.error("Haori","Element is not a dialog: ",n)}),Promise.all(i).then(()=>this.options.dialogMessage?k.dialog(this.options.dialogMessage):Promise.resolve()).then(()=>this.options.toastMessage?k.toast(this.options.toastMessage,"info"):Promise.resolve()).then(()=>(this.options.redirectUrl&&(window.location.href=this.options.redirectUrl),Promise.resolve()))}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 s=>{const n=e?e.getTarget():document.body;await k.addErrorMessage(n,s)};if((t.headers.get("Content-Type")||"").includes("application/json"))try{const s=await t.json(),n=[];if(s&&typeof s=="object"){if(typeof s.message=="string"&&n.push({message:s.message}),Array.isArray(s.messages))for(const a of s.messages)typeof a=="string"&&n.push({message:a});if(s.errors&&typeof s.errors=="object")for(const[a,o]of Object.entries(s.errors))Array.isArray(o)?n.push({key:a,message:o.join(`
12
+ `)}):typeof o=="string"?n.push({key:a,message:o}):o!=null&&n.push({key:a,message:String(o)});if(n.length===0)for(const[a,o]of Object.entries(s))a==="message"||a==="messages"||a==="errors"||(Array.isArray(o)?n.push({key:a,message:o.join(`
13
+ `)}):typeof o=="string"&&n.push({key:a,message:o}))}if(n.length===0){await r(`${t.status} ${t.statusText}`);return}for(const a of n)a.key&&e?await y.addErrorMessage(e,a.key,a.message):await r(a.message);return}catch{}try{const s=await t.text();s&&s.trim().length>0?await r(s.trim()):await r(`${t.status} ${t.statusText}`)}catch{await r(`${t.status} ${t.statusText}`)}}validate(t){if(this.options.valid!==!0)return!0;const e=t.getTarget();let r=this.validateOne(t);return r||e.focus(),t.getChildElementFragments().reverse().forEach(i=>{r&&=this.validate(i)}),r}validateOne(t){const e=t.getTarget();return e instanceof HTMLInputElement||e instanceof HTMLSelectElement||e instanceof HTMLTextAreaElement?e.reportValidity():!0}confirm(){const t=this.options.confirmMessage;return t==null?Promise.resolve(!0):k.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 s={};this.options.bindParams.forEach(n=>{r&&typeof r=="object"&&n in r&&(s[n]=r[n])}),r=s}const i=[];if(this.options.bindArg)this.options.bindFragments.forEach(s=>{const n=s.getBindingData();n[this.options.bindArg]=r,i.push(N.setBindingData(s.getTarget(),n))});else{if(typeof r=="string")return h.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(s=>{i.push(N.setBindingData(s.getTarget(),r))})}return Promise.all(i).then(()=>{})})}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 i=r.getValue();(i==null||i==="")&&(i="0");let s=Number(i);isNaN(s)&&(s=0),s+=t,e.push(r.setValue(String(s)))}return Promise.all(e).then(()=>{})}getRowFragment(){if(!this.options.targetFragment)return h.error("Haori","Target fragment is not specified for row operation."),null;const t=this.options.targetFragment.closestByAttribute(`${c.prefix}row`);return t||(h.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(N.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(i=>!i.hasAttribute(`${c.prefix}each-before`)&&!i.hasAttribute(`${c.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()}}class X{static readParams(){const t={},e=window.location.search;return new URLSearchParams(e).forEach((i,s)=>{t[s]=i}),t}}class J{static async load(t,e){let r;try{r=await fetch(t,e)}catch(s){throw h.error("[Haori]","Failed to fetch import source:",t,s),new Error(`Failed to fetch: ${t}`)}if(!r.ok){const s=`${r.status} ${r.statusText}`;throw h.error("[Haori]","Import HTTP error:",t,s),new Error(`Failed to load ${t}: ${s}`)}let i;try{i=await r.text()}catch(s){throw h.error("[Haori]","Failed to read response text:",t,s),new Error(`Failed to read response from: ${t}`)}try{const n=new DOMParser().parseFromString(i,"text/html");return n&&n.body?n.body.innerHTML:(h.warn("[Haori]","No body found in imported document:",t),i)}catch(s){return h.error("[Haori]","Failed to parse imported HTML:",t,s),i}}}const m=class m{static isDeferredAttributeName(t){return m.DEFERRED_ATTRIBUTE_SUFFIXES.some(e=>t===`${c.prefix}${e}`)}static scan(t){const e=A.get(t);if(!e)return Promise.resolve();t.parentNode&&(A.get(t.parentNode)?.isMounted()||document.body.contains(t)?e.setMounted(!0):e.setMounted(!1));const r=[],i=new Set;for(const s of m.PRIORITY_ATTRIBUTE_SUFFIXES){const n=c.prefix+s;e.hasAttribute(n)&&(r.push(m.setAttribute(e.getTarget(),n,e.getRawAttribute(n))),i.add(n))}for(const s of e.getAttributeNames()){if(i.has(s)||m.isDeferredAttributeName(s))continue;const n=e.getRawAttribute(s);n!==null&&r.push(m.setAttribute(e.getTarget(),s,n))}for(const s of m.DEFERRED_ATTRIBUTE_SUFFIXES){const n=c.prefix+s;e.hasAttribute(n)&&(r.push(m.setAttribute(e.getTarget(),n,e.getRawAttribute(n))),i.add(n))}return e.getChildren().forEach(s=>{s instanceof S?r.push(m.scan(s.getTarget())):s instanceof j&&r.push(m.evaluateText(s))}),Promise.all(r).then(()=>{})}static setAttribute(t,e,r){const i=A.get(t),s=[];switch(e){case`${c.prefix}bind`:{r===null?(i.clearBindingDataCache(),i.setBindingData({})):i.setBindingData(m.parseDataBind(r));break}case`${c.prefix}if`:s.push(m.evaluateIf(i));break;case`${c.prefix}each`:s.push(m.evaluateEach(i));break;case`${c.prefix}fetch`:s.push(new d(i,null).run());break;case`${c.prefix}import`:{if(typeof r=="string"){const n=i.getTarget(),a=performance.now();E.importStart(n,r),s.push(J.load(r).then(o=>{const g=new TextEncoder().encode(o).length;return w.enqueue(()=>{n.innerHTML=o}).then(()=>{E.importEnd(n,r,g,a)})}).catch(o=>{E.importError(n,r,o),h.error("[Haori]","Failed to import HTML:",r,o)}))}break}case`${c.prefix}url-param`:{const n=i.getAttribute(`${c.prefix}url-arg`),a=X.readParams();if(n===null)m.setBindingData(t,a);else{const o=i.getRawBindingData()||{};o[String(n)]=a,m.setBindingData(t,o)}break}}return r===null?s.push(i.removeAttribute(e)):s.push(i.setAttribute(e,r)),Promise.all(s).then(()=>{})}static setBindingData(t,e){const r=A.get(t),i=r.getRawBindingData();r.setBindingData(e);const s=[];return s.push(r.setAttribute(`${c.prefix}bind`,JSON.stringify(e))),s.push(m.evaluateAll(r)),E.bindChange(t,i,e,"manual"),Promise.all(s).then(()=>{})}static parseDataBind(t){if(t.startsWith("{")||t.startsWith("["))try{return JSON.parse(t)}catch(e){return h.error("[Haori]","Invalid JSON in data-bind:",e),{}}else{const e=new URLSearchParams(t),r={};for(const[i,s]of e.entries())r[i]!==void 0?Array.isArray(r[i])?r[i].push(s):r[i]=[r[i],s]:r[i]=s;return r}}static addNode(t,e){const r=A.get(t);if(r.isSkipMutationNodes())return;const i=A.get(e.nextSibling),s=A.get(e);s&&(r.insertBefore(s,i),s instanceof S?m.scan(s.getTarget()):s instanceof j&&m.evaluateText(s))}static removeNode(t){const e=A.get(t);if(e){const r=e.getParent();if(r&&r.isSkipMutationNodes())return;e.remove()}}static changeText(t,e){const r=A.get(t);r&&r.setContent(e)}static changeValue(t,e){const r=A.get(t);if(r.getValue()===e)return Promise.resolve();const i=[];i.push(r.setValue(e));const s=m.getFormFragment(r);if(s){const n=y.getValues(s),a=s.getAttribute(`${c.prefix}form-arg`);let o;a?(o=s.getRawBindingData(),o||(o={}),o[String(a)]=n):o=n,i.push(m.setBindingData(s.getTarget(),o))}return Promise.all(i).then(()=>{})}static getFormFragment(t){if(t.getTarget()instanceof HTMLFormElement)return t;const e=t.getParent();return e?m.getFormFragment(e):null}static evaluateAll(t){const e=[];return t.hasAttribute(`${c.prefix}if`)&&e.push(m.evaluateIf(t)),t.hasAttribute(`${c.prefix}each`)&&e.push(m.evaluateEach(t)),t.getChildren().forEach(r=>{r instanceof S?e.push(m.evaluateAll(r)):r instanceof j&&e.push(m.evaluateText(r))}),Promise.all(e).then(()=>{})}static evaluateText(t){return t.evaluate()}static evaluateIf(t){const e=[],r=t.getAttribute(`${c.prefix}if`);return r===!1||r===void 0||r===null||Number.isNaN(r)?t.isVisible()&&e.push(t.hide().then(()=>{E.hide(t.getTarget())})):t.isVisible()||(e.push(t.show().then(()=>{E.show(t.getTarget())})),e.push(m.evaluateAll(t))),Promise.all(e).then(()=>{})}static evaluateEach(t){if(!t.isVisible()||!t.isMounted())return Promise.resolve();let e=t.getTemplate();if(e===null){let i=!1;t.getChildren().forEach(n=>{if(!i&&n instanceof S){if(n.hasAttribute(`${c.prefix}each-before`)||n.hasAttribute(`${c.prefix}each-after`))return;e=n.clone(),t.setTemplate(e),i=!0,t.removeChild(n);const a=n.getTarget();a.parentNode&&a.parentNode.removeChild(a),n.setMounted(!1)}});const s=t.getAttribute(`${c.prefix}each`);return Array.isArray(s)?this.updateDiff(t,s):(h.error("[Haori]","Invalid each attribute:",s),Promise.reject(new Error("Invalid each attribute.")))}const r=t.getAttribute(`${c.prefix}each`);return Array.isArray(r)?this.updateDiff(t,r):(h.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 h.error("[Haori]","Template is not set for each element."),Promise.resolve();let i=t.getAttribute(`${c.prefix}each-index`);i&&(i=String(i));const s=t.getAttribute(`${c.prefix}each-key`),n=t.getAttribute(`${c.prefix}each-arg`),a=new Map,o=[];e.forEach((p,v)=>{const T=m.createListKey(p,s?String(s):null,v);o.push(T),a.set(T,{item:p,itemIndex:v})});const g=[];let u=t.getChildren().filter(p=>p instanceof S).filter(p=>!p.hasAttribute(`${c.prefix}each-before`)&&!p.hasAttribute(`${c.prefix}each-after`));u=u.filter(p=>o.indexOf(String(p.getListKey()))===-1?(g.push(p.remove()),!1):!0);const b=u.map(p=>p.getListKey()),l=t.getChildren().filter(p=>p instanceof S).filter(p=>p.hasAttribute(`${c.prefix}each-before`)).length;let f=Promise.resolve();return o.forEach((p,v)=>{const T=b.indexOf(p),{item:B,itemIndex:x}=a.get(p);let F;if(T!==-1)F=u[T],m.updateRowFragment(F,B,i,x,n?String(n):null,p),typeof F.clearBindingDataCache=="function"&&F.clearBindingDataCache(),f=f.then(()=>m.evaluateAll(F));else{F=r.clone(),m.updateRowFragment(F,B,i,x,n?String(n):null,p),typeof F.clearBindingDataCache=="function"&&F.clearBindingDataCache();const W=l+v;f=f.then(()=>t.insertBefore(F,t.getChildren()[W]||null).then(()=>m.evaluateAll(F)))}}),Promise.all(g).then(()=>f).then(()=>{const p=o.filter(x=>x!==null),v=b.filter(x=>x!==null),T=p.filter(x=>!v.includes(x)),B=v.filter(x=>!p.includes(x));E.eachUpdate(t.getTarget(),T,B,p)})}static createListKey(t,e,r){let i;if(typeof t=="object"&&t!==null)if(e){const s=t[e];s==null?i=`__index_${r}`:typeof s=="object"?i=JSON.stringify(s):i=String(s)}else i=`__index_${r}`;else i=String(t);return i}static updateRowFragment(t,e,r,i,s,n){let a=e;if(typeof e=="object"&&e!==null)a={...e},r&&(a[r]=i),s&&(a={[s]:a});else if(s)a={[s]:e},r&&(a[r]=i);else{h.error("[Haori]",`Primitive value requires '${c.prefix}each-arg' attribute: ${e}`);return}t.setListKey(n),t.setAttribute(`${c.prefix}row`,n),t.setBindingData(a)}};m.PRIORITY_ATTRIBUTE_SUFFIXES=["bind","if","each"],m.DEFERRED_ATTRIBUTE_SUFFIXES=["fetch","url-param"];let N=m;class z{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=A.get(e);r&&new d(r,"load").run()},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})}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)}delegate(t,e){const r=this.getElementFromTarget(t.target);if(!r)return;const i=A.get(r);i&&(e==="change"&&i instanceof S&&i.syncValue(),new d(i,e).run().catch(s=>{h.error("[Haori]","Procedure execution error:",s)}))}getElementFromTarget(t){return t?t instanceof HTMLElement?t:t instanceof Node?t.parentElement:null:null}}const C=class C{static async init(){if(C._initialized)return;C._initialized=!0;const t=await Promise.allSettled([N.scan(document.head),N.scan(document.body)]),[e,r]=t;e.status!=="fulfilled"&&h.error("[Haori]","Failed to build head fragment:",e.reason),r.status!=="fulfilled"&&h.error("[Haori]","Failed to build body fragment:",r.reason),C.observe(document.head),C.observe(document.body),new z().start()}static observe(t){new MutationObserver(async r=>{for(const i of r)try{switch(i.type){case"attributes":{h.info("[Haori]","Attribute changed:",i.target,i.attributeName);const s=i.target;N.setAttribute(s,i.attributeName,s.getAttribute(i.attributeName));break}case"childList":{h.info("[Haori]","Child list changed:",Array.from(i.removedNodes).map(s=>s.nodeName),Array.from(i.addedNodes).map(s=>s.nodeName)),Array.from(i.removedNodes).forEach(s=>{N.removeNode(s)}),Array.from(i.addedNodes).forEach(s=>{s.parentElement instanceof HTMLElement&&N.addNode(s.parentElement,s)});break}case"characterData":{h.info("[Haori]","Character data changed:",i.target,i.target.textContent),i.target instanceof Text||i.target instanceof Comment?N.changeText(i.target,i.target.textContent):h.warn("[Haori]","Unsupported character data type:",i.target);break}default:h.warn("[Haori]","Unknown mutation type:",i.type);continue}}catch(s){h.error("[Haori]","Error processing mutation:",s)}}).observe(t,{childList:!0,subtree:!0,attributes:!0,characterData:!0}),h.info("[Haori]","Observer initialized for",t)}};C._initialized=!1;let V=C;document.readyState==="loading"?document.addEventListener("DOMContentLoaded",V.init):V.init();const Q="0.1.2";exports.Core=N;exports.Env=c;exports.Form=y;exports.Fragment=A;exports.Haori=k;exports.Log=h;exports.Queue=w;exports.default=k;exports.version=Q;
13
14
  //# sourceMappingURL=haori.cjs.js.map