haori 0.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (175) hide show
  1. package/LICENSE +21 -0
  2. package/README.ja.md +157 -0
  3. package/README.md +158 -0
  4. package/dist/haori.cjs.js +13 -0
  5. package/dist/haori.cjs.js.map +1 -0
  6. package/dist/haori.es.js +2929 -0
  7. package/dist/haori.es.js.map +1 -0
  8. package/dist/haori.iife.js +13 -0
  9. package/dist/haori.iife.js.map +1 -0
  10. package/dist/index.d.ts +824 -0
  11. package/dist/src/core.d.ts +144 -0
  12. package/dist/src/core.d.ts.map +1 -0
  13. package/dist/src/core.js +605 -0
  14. package/dist/src/core.js.map +1 -0
  15. package/dist/src/dev.d.ts +35 -0
  16. package/dist/src/dev.d.ts.map +1 -0
  17. package/dist/src/dev.js +44 -0
  18. package/dist/src/dev.js.map +1 -0
  19. package/dist/src/env.d.ts +25 -0
  20. package/dist/src/env.d.ts.map +1 -0
  21. package/dist/src/env.js +64 -0
  22. package/dist/src/env.js.map +1 -0
  23. package/dist/src/event.d.ts +144 -0
  24. package/dist/src/event.d.ts.map +1 -0
  25. package/dist/src/event.js +221 -0
  26. package/dist/src/event.js.map +1 -0
  27. package/dist/src/event_dispatcher.d.ts +50 -0
  28. package/dist/src/event_dispatcher.d.ts.map +1 -0
  29. package/dist/src/event_dispatcher.js +99 -0
  30. package/dist/src/event_dispatcher.js.map +1 -0
  31. package/dist/src/expression.d.ts +39 -0
  32. package/dist/src/expression.d.ts.map +1 -0
  33. package/dist/src/expression.js +148 -0
  34. package/dist/src/expression.js.map +1 -0
  35. package/dist/src/form.d.ts +113 -0
  36. package/dist/src/form.d.ts.map +1 -0
  37. package/dist/src/form.js +361 -0
  38. package/dist/src/form.js.map +1 -0
  39. package/dist/src/fragment.d.ts +427 -0
  40. package/dist/src/fragment.d.ts.map +1 -0
  41. package/dist/src/fragment.js +1168 -0
  42. package/dist/src/fragment.js.map +1 -0
  43. package/dist/src/haori.d.ts +54 -0
  44. package/dist/src/haori.d.ts.map +1 -0
  45. package/dist/src/haori.js +120 -0
  46. package/dist/src/haori.js.map +1 -0
  47. package/dist/src/import.d.ts +19 -0
  48. package/dist/src/import.d.ts.map +1 -0
  49. package/dist/src/import.js +64 -0
  50. package/dist/src/import.js.map +1 -0
  51. package/dist/src/index.d.ts +17 -0
  52. package/dist/src/index.d.ts.map +1 -0
  53. package/dist/src/index.js +21 -0
  54. package/dist/src/index.js.map +1 -0
  55. package/dist/src/log.d.ts +32 -0
  56. package/dist/src/log.d.ts.map +1 -0
  57. package/dist/src/log.js +43 -0
  58. package/dist/src/log.js.map +1 -0
  59. package/dist/src/observer.d.ts +17 -0
  60. package/dist/src/observer.d.ts.map +1 -0
  61. package/dist/src/observer.js +102 -0
  62. package/dist/src/observer.js.map +1 -0
  63. package/dist/src/procedure.d.ts +203 -0
  64. package/dist/src/procedure.d.ts.map +1 -0
  65. package/dist/src/procedure.js +1040 -0
  66. package/dist/src/procedure.js.map +1 -0
  67. package/dist/src/queue.d.ts +28 -0
  68. package/dist/src/queue.d.ts.map +1 -0
  69. package/dist/src/queue.js +150 -0
  70. package/dist/src/queue.js.map +1 -0
  71. package/dist/src/url.d.ts +14 -0
  72. package/dist/src/url.d.ts.map +1 -0
  73. package/dist/src/url.js +22 -0
  74. package/dist/src/url.js.map +1 -0
  75. package/dist/tests/click-attributes.test.d.ts +2 -0
  76. package/dist/tests/click-attributes.test.d.ts.map +1 -0
  77. package/dist/tests/click-attributes.test.js +95 -0
  78. package/dist/tests/click-attributes.test.js.map +1 -0
  79. package/dist/tests/core.test.d.ts +5 -0
  80. package/dist/tests/core.test.d.ts.map +1 -0
  81. package/dist/tests/core.test.js +158 -0
  82. package/dist/tests/core.test.js.map +1 -0
  83. package/dist/tests/data-each-browserlike.test.d.ts +2 -0
  84. package/dist/tests/data-each-browserlike.test.d.ts.map +1 -0
  85. package/dist/tests/data-each-browserlike.test.js +48 -0
  86. package/dist/tests/data-each-browserlike.test.js.map +1 -0
  87. package/dist/tests/data-each-fragment-debug.test.d.ts +2 -0
  88. package/dist/tests/data-each-fragment-debug.test.d.ts.map +1 -0
  89. package/dist/tests/data-each-fragment-debug.test.js +119 -0
  90. package/dist/tests/data-each-fragment-debug.test.js.map +1 -0
  91. package/dist/tests/data-each-table.test.d.ts +2 -0
  92. package/dist/tests/data-each-table.test.d.ts.map +1 -0
  93. package/dist/tests/data-each-table.test.js +63 -0
  94. package/dist/tests/data-each-table.test.js.map +1 -0
  95. package/dist/tests/dev.test.d.ts +2 -0
  96. package/dist/tests/dev.test.d.ts.map +1 -0
  97. package/dist/tests/dev.test.js +51 -0
  98. package/dist/tests/dev.test.js.map +1 -0
  99. package/dist/tests/each_arg.test.d.ts +2 -0
  100. package/dist/tests/each_arg.test.d.ts.map +1 -0
  101. package/dist/tests/each_arg.test.js +41 -0
  102. package/dist/tests/each_arg.test.js.map +1 -0
  103. package/dist/tests/env.test.d.ts +2 -0
  104. package/dist/tests/env.test.d.ts.map +1 -0
  105. package/dist/tests/env.test.js +96 -0
  106. package/dist/tests/env.test.js.map +1 -0
  107. package/dist/tests/event.test.d.ts +2 -0
  108. package/dist/tests/event.test.d.ts.map +1 -0
  109. package/dist/tests/event.test.js +287 -0
  110. package/dist/tests/event.test.js.map +1 -0
  111. package/dist/tests/expression.test.d.ts +2 -0
  112. package/dist/tests/expression.test.d.ts.map +1 -0
  113. package/dist/tests/expression.test.js +281 -0
  114. package/dist/tests/expression.test.js.map +1 -0
  115. package/dist/tests/fetch-and-procedure-scenarios.test.d.ts +2 -0
  116. package/dist/tests/fetch-and-procedure-scenarios.test.d.ts.map +1 -0
  117. package/dist/tests/fetch-and-procedure-scenarios.test.js +133 -0
  118. package/dist/tests/fetch-and-procedure-scenarios.test.js.map +1 -0
  119. package/dist/tests/form.test.d.ts +2 -0
  120. package/dist/tests/form.test.d.ts.map +1 -0
  121. package/dist/tests/form.test.js +607 -0
  122. package/dist/tests/form.test.js.map +1 -0
  123. package/dist/tests/fragment.test.d.ts +2 -0
  124. package/dist/tests/fragment.test.d.ts.map +1 -0
  125. package/dist/tests/fragment.test.js +164 -0
  126. package/dist/tests/fragment.test.js.map +1 -0
  127. package/dist/tests/import.test.d.ts +2 -0
  128. package/dist/tests/import.test.d.ts.map +1 -0
  129. package/dist/tests/import.test.js +148 -0
  130. package/dist/tests/import.test.js.map +1 -0
  131. package/dist/tests/log.test.d.ts +2 -0
  132. package/dist/tests/log.test.d.ts.map +1 -0
  133. package/dist/tests/log.test.js +58 -0
  134. package/dist/tests/log.test.js.map +1 -0
  135. package/dist/tests/procedure-action-operations.test.d.ts +2 -0
  136. package/dist/tests/procedure-action-operations.test.d.ts.map +1 -0
  137. package/dist/tests/procedure-action-operations.test.js +148 -0
  138. package/dist/tests/procedure-action-operations.test.js.map +1 -0
  139. package/dist/tests/procedure-fetch-options.test.d.ts +2 -0
  140. package/dist/tests/procedure-fetch-options.test.d.ts.map +1 -0
  141. package/dist/tests/procedure-fetch-options.test.js +131 -0
  142. package/dist/tests/procedure-fetch-options.test.js.map +1 -0
  143. package/dist/tests/procedure.test.d.ts +2 -0
  144. package/dist/tests/procedure.test.d.ts.map +1 -0
  145. package/dist/tests/procedure.test.js +136 -0
  146. package/dist/tests/procedure.test.js.map +1 -0
  147. package/dist/tests/procedure_events.test.d.ts +7 -0
  148. package/dist/tests/procedure_events.test.d.ts.map +1 -0
  149. package/dist/tests/procedure_events.test.js +96 -0
  150. package/dist/tests/procedure_events.test.js.map +1 -0
  151. package/dist/tests/reset_each.test.d.ts +2 -0
  152. package/dist/tests/reset_each.test.d.ts.map +1 -0
  153. package/dist/tests/reset_each.test.js +215 -0
  154. package/dist/tests/reset_each.test.js.map +1 -0
  155. package/dist/tests/row-move.test.d.ts +2 -0
  156. package/dist/tests/row-move.test.d.ts.map +1 -0
  157. package/dist/tests/row-move.test.js +197 -0
  158. package/dist/tests/row-move.test.js.map +1 -0
  159. package/dist/tests/row-operations.test.d.ts +2 -0
  160. package/dist/tests/row-operations.test.d.ts.map +1 -0
  161. package/dist/tests/row-operations.test.js +238 -0
  162. package/dist/tests/row-operations.test.js.map +1 -0
  163. package/dist/tests/url.test.d.ts +2 -0
  164. package/dist/tests/url.test.d.ts.map +1 -0
  165. package/dist/tests/url.test.js +150 -0
  166. package/dist/tests/url.test.js.map +1 -0
  167. package/dist/vite.config.d.ts +3 -0
  168. package/dist/vite.config.d.ts.map +1 -0
  169. package/dist/vite.config.js +28 -0
  170. package/dist/vite.config.js.map +1 -0
  171. package/dist/vitest.config.d.ts +3 -0
  172. package/dist/vitest.config.d.ts.map +1 -0
  173. package/dist/vitest.config.js +19 -0
  174. package/dist/vitest.config.js.map +1 -0
  175. package/package.json +68 -0
package/LICENSE ADDED
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2025 Kazuyuki Nishijima
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
package/README.ja.md ADDED
@@ -0,0 +1,157 @@
1
+ # Haori.js(日本語ドキュメント)
2
+
3
+ Haori.js は、HTML 属性を中心にして動的な UI を実現する軽量なライブラリです。JavaScript をほとんど書かずに、データバインディング、条件分岐、繰り返し処理、フォームの双方向バインディング、サーバー通信などを HTML 属性で宣言できます。
4
+
5
+ バージョン: 0.1.0
6
+
7
+ ---
8
+
9
+ **目次**
10
+
11
+ - 概要
12
+ - インストール
13
+ - クイックスタート
14
+ - よく使う属性(概要)
15
+ - 公開・ビルド手順
16
+ - ライセンス・貢献
17
+ - 詳細ドキュメント
18
+
19
+ ---
20
+
21
+ ## 概要
22
+
23
+ - 設計思想: HTML-First(HTML 属性のみで UI を宣言)
24
+ - 主な特徴:
25
+ - データバインディング(`data-bind`)
26
+ - 条件表示(`data-if`)
27
+ - 繰り返し表示(`data-each`)
28
+ - フォーム双方向バインディング(`name` 属性による自動バインド)
29
+ - サーバー通信(`data-fetch`)
30
+ - HTML インポート(`data-import`)
31
+ - ゼロ依存(ブラウザネイティブのみ)
32
+
33
+ ## インストール
34
+
35
+ npm:
36
+
37
+ ```bash
38
+ npm install haori
39
+ ```
40
+
41
+ CDN:
42
+
43
+ ```html
44
+ <script src="https://cdn.jsdelivr.net/npm/haori@0.1.0/dist/haori.iife.js"></script>
45
+ ```
46
+
47
+ ES Module:
48
+
49
+ ```js
50
+ import Haori from 'haori'
51
+ ```
52
+
53
+ ---
54
+
55
+ ## クイックスタート
56
+
57
+ HTML だけで簡単に使えます。以下は最小の例です。
58
+
59
+ ```html
60
+ <!DOCTYPE html>
61
+ <html lang="ja">
62
+ <head>
63
+ <meta charset="utf-8">
64
+ <title>Haori サンプル</title>
65
+ <script src="https://cdn.jsdelivr.net/npm/haori@0.1.0/dist/haori.iife.js"></script>
66
+ </head>
67
+ <body>
68
+ <div data-bind='{"name":"太郎"}'>
69
+ <p>こんにちは、{{name}} さん</p>
70
+ </div>
71
+ </body>
72
+ </html>
73
+ ```
74
+
75
+ JavaScript からマウントする例:
76
+
77
+ ```js
78
+ import Haori from 'haori'
79
+
80
+ Haori.mount(document.body, { items: [ { name: 'りんご' }, { name: 'みかん' } ] })
81
+ ```
82
+
83
+ ---
84
+
85
+ ## よく使う属性(概要)
86
+
87
+ - `data-bind` — 要素にバインディングデータを設定(JSON またはパラメータ形式)
88
+ - `{{ ... }}` — テンプレート式(式評価により挿入)
89
+ - `data-if` — 条件に応じて要素を表示 / 非表示
90
+ - `data-each` — 配列を繰り返し表示(`data-each-key`, `data-each-arg`, `data-each-index` など)
91
+ - `data-fetch` — サーバーからデータを取得してバインド
92
+ - `data-import` — 外部 HTML を読み込んで挿入
93
+ - `data-url-param` — URL のクエリパラメータをバインディングに取り込む
94
+
95
+ 詳しい使い方や多数のサンプルについては、公式ドキュメントを参照してください。
96
+
97
+ ---
98
+
99
+ ## 公開・ビルド手順(パッケージ作成)
100
+
101
+ 開発環境でのビルドと公開の基本手順を示します。
102
+
103
+ 1. 依存インストール
104
+
105
+ ```bash
106
+ npm install
107
+ ```
108
+
109
+ 2. 型チェックとビルド
110
+
111
+ ```bash
112
+ npm run compile
113
+ # または
114
+ npm run build
115
+ ```
116
+
117
+ 3. テスト
118
+
119
+ ```bash
120
+ npm run test
121
+ ```
122
+
123
+ 4. バージョン更新
124
+
125
+ ```bash
126
+ npm version patch
127
+ ```
128
+
129
+ 5. npm ログインおよび公開
130
+
131
+ ```bash
132
+ npm login
133
+ npm publish --access public
134
+ ```
135
+
136
+ 注意: `package.json` の `name`, `version`, `description`, `repository`, `license` が正しいことを確認してください。公開対象ファイルは `files` フィールドおよび `.npmignore` に従います。
137
+
138
+ ---
139
+
140
+ ## ライセンス・貢献
141
+
142
+ - ライセンス: MIT(リポジトリの `LICENSE` を参照)
143
+
144
+ 貢献歓迎: バグ報告、改善提案、プルリクエストは GitHub リポジトリへお願いします。
145
+
146
+ ---
147
+
148
+ ## 詳細ドキュメント
149
+
150
+ より詳しい使い方、属性仕様、内部設計については以下のドキュメントを参照してください。
151
+
152
+ - `docs/ja/guide.md` — 利用ガイド(サンプル多数)
153
+ - `docs/ja/specs.md` — 技術仕様書(内部設計・API など)
154
+
155
+ ---
156
+
157
+ README の作成にあたって追加してほしい項目(API 参照、図、例など)があれば教えてください。
package/README.md ADDED
@@ -0,0 +1,158 @@
1
+ # Haori.js
2
+
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
+
5
+ Version: 0.1.0
6
+
7
+ ---
8
+
9
+ Contents
10
+
11
+ - Overview
12
+ - Installation
13
+ - Quick start
14
+ - Common attributes (summary)
15
+ - Build & publish
16
+ - License & contributing
17
+ - Further documentation
18
+
19
+ ---
20
+
21
+ ## Overview
22
+
23
+ - Design principle: HTML-first — declare UI behavior with HTML attributes
24
+ - Key features:
25
+ - Data binding via `data-bind`
26
+ - Conditional rendering via `data-if`
27
+ - List rendering via `data-each`
28
+ - Two-way form binding (automatic binding based on `name` attributes)
29
+ - Server fetches via `data-fetch`
30
+ - HTML imports via `data-import`
31
+ - Zero runtime dependencies (uses browser-native APIs)
32
+
33
+ ## Installation
34
+
35
+ Install from npm:
36
+
37
+ ```bash
38
+ npm install haori
39
+ ```
40
+
41
+ Via CDN:
42
+
43
+ ```html
44
+ <script src="https://cdn.jsdelivr.net/npm/haori@0.1.0/dist/haori.iife.js"></script>
45
+ ```
46
+
47
+ ES Module import:
48
+
49
+ ```js
50
+ import Haori from 'haori'
51
+ ```
52
+
53
+ ---
54
+
55
+ ## Quick start
56
+
57
+ You can use Haori with plain HTML. Minimal example:
58
+
59
+ ```html
60
+ <!DOCTYPE html>
61
+ <html lang="en">
62
+ <head>
63
+ <meta charset="utf-8">
64
+ <title>Haori Sample</title>
65
+ <script src="https://cdn.jsdelivr.net/npm/haori@0.1.0/dist/haori.iife.js"></script>
66
+ </head>
67
+ <body>
68
+ <div data-bind='{"name":"Taro"}'>
69
+ <p>Hello, {{name}}</p>
70
+ </div>
71
+ </body>
72
+ </html>
73
+ ```
74
+
75
+ Mounting from JavaScript:
76
+
77
+ ```js
78
+ import Haori from 'haori'
79
+
80
+ Haori.mount(document.body, { items: [ { name: 'apple' }, { name: 'orange' } ] })
81
+ ```
82
+
83
+ ---
84
+
85
+ ## Common attributes (summary)
86
+
87
+ - `data-bind` — set binding data for an element (JSON or parameter format)
88
+ - `{{ ... }}` — template expressions (evaluated and inserted)
89
+ - `data-if` — show/hide an element based on a condition
90
+ - `data-each` — repeat an element for items in an array (`data-each-key`, `data-each-arg`, `data-each-index`)
91
+ - `data-fetch` — fetch data from a server and bind the result
92
+ - `data-import` — load external HTML and insert it
93
+ - `data-url-param` — import URL query parameters into bindings
94
+
95
+ For detailed usage and many examples, see the official documentation.
96
+
97
+ ---
98
+
99
+ ## Build & publish (packaging)
100
+
101
+ Basic build and publish steps in a development environment:
102
+
103
+ 1. Install dependencies
104
+
105
+ ```bash
106
+ npm install
107
+ ```
108
+
109
+ 2. Type-check and build
110
+
111
+ ```bash
112
+ npm run compile
113
+ # or
114
+ npm run build
115
+ ```
116
+
117
+ 3. Run tests
118
+
119
+ ```bash
120
+ npm run test
121
+ ```
122
+
123
+ 4. Bump version
124
+
125
+ ```bash
126
+ npm version patch
127
+ ```
128
+
129
+ 5. Login to npm and publish
130
+
131
+ ```bash
132
+ npm login
133
+ npm publish --access public
134
+ ```
135
+
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`.
137
+
138
+ ---
139
+
140
+ ## License & Contributing
141
+
142
+ - License: MIT (see `LICENSE` in this repository)
143
+
144
+ Contributions are welcome — please open issues or pull requests on the GitHub repository.
145
+
146
+ ---
147
+
148
+ ## Further documentation
149
+
150
+ For more detailed usage, attribute specs, and internal design, see:
151
+
152
+ - `docs/ja/guide.md` — User guide (many examples)
153
+ - `docs/ja/specs.md` — Technical specifications (internal design, API)
154
+
155
+ ---
156
+
157
+ If you would like additional sections (API reference, diagrams, more examples), tell me what to include and I will expand the README.
158
+
@@ -0,0 +1,13 @@
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";
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",`
5
+ "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",`
8
+ "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;
13
+ //# sourceMappingURL=haori.cjs.js.map