haori 0.59.3 → 0.59.4

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.
package/README.ja.md CHANGED
@@ -2,7 +2,7 @@
2
2
 
3
3
  Haori.js は、HTML 属性を中心にして動的な UI を実現する軽量なライブラリです。JavaScript をほとんど書かずに、データバインディング、条件分岐、繰り返し処理、フォームの双方向バインディング、サーバー通信などを HTML 属性で宣言できます。
4
4
 
5
- バージョン: 0.59.3
5
+ バージョン: 0.59.4
6
6
 
7
7
  ---
8
8
 
@@ -122,7 +122,7 @@ Haori.mount(document.body, {items: [{name: 'りんご'}, {name: 'みかん'}]});
122
122
  - `data-input-*` — テキスト入力1文字ごと(`input` イベント)に手続きを起動します。逐次発火するため `data-input-*` を**明示した要素のみ**が対象(オプトイン)で、`change` 同様に先祖フォームを自動検出して双方向バインディングへ反映します。検索欄の逐次絞り込みなどに使えます(例: `<input name="q" data-input-form>`)。
123
123
  - `data-on="イベント名"` + `data-on-*` — `window` / `document` へ dispatch された**任意のカスタムイベント**を契機に手続きを起動します(アクション語彙は `data-{event}-*` と共通)。ネイティブ橋の準備完了通知など、組み込みイベント以外での初期化を宣言的に書けます(例: `<body data-on="appReady" data-on-fetch="/api/init.json" data-on-bind="#app">`)。イベント名は属性値で保持(属性名の小文字化対策)、`window` キャプチャ1本で二重発火なく購読、後挿入要素も追従。組み込みイベント名(click/change/input/load)は警告し購読しません。Haori 購読開始前に発火したイベントは受け取れない点に注意。`data-on-target="#sub-modal"` を足すと、指定した要素(とその子孫)から発火したイベントでだけ起動します(Bootstrap の `hidden.bs.modal` で、特定のモーダルが閉じたときだけ状態を戻すなど)。
124
124
  - `data-validity="{{式}}"` / `data-validity-message="…"` — 入力欄へ宣言するフィールド間検証です。条件を `setCustomValidity()` へ反映してネイティブ検証(`data-{event}-validate`)に相乗りするため、バブル表示・フォーカス移動・`:invalid` の装飾がそのまま使えます。「連絡先いずれか必須」「メールアドレスの一致」のようにネイティブの制約では表現できない条件を宣言できます。
125
- - `data-{event}-if="{{式}}"`(非イベントは `data-fetch-if`)— 手続きの実行条件です。偽なら fetch・リダイレクト・`data-{event}-run` まで含めて実行しません。どちらも**実行時に同期評価**するため、属性の再描画(`requestAnimationFrame`)を待たず、直前に変更した入力を含めて判定されます(`data-attr-disabled` では「最後の欄を直してそのまま押す」操作で 1 フレーム古い判定になります)。押下のブロックに `disabled` を使わないでください。無効化されたボタンはクリックイベントを発火しないため、「直したのに押せない」方向は救えません。
125
+ - `data-{event}-if="{{式}}"`(非イベントは `data-fetch-if`)— 手続きの実行条件です。偽なら fetch・リダイレクト・`data-{event}-run` まで含めて実行しません(入力欄の `change` / `input` では、入力した値のフォームへのコミットだけは行います。`-fetch` を伴わない `-bind` で値をバインド先へ写す構成は除きます)。どちらも**実行時に同期評価**するため、属性の再描画(`requestAnimationFrame`)を待たず、直前に変更した入力を含めて判定されます(`data-attr-disabled` では「最後の欄を直してそのまま押す」操作で 1 フレーム古い判定になります)。押下のブロックに `disabled` を使わないでください。無効化されたボタンはクリックイベントを発火しないため、「直したのに押せない」方向は救えません。
126
126
  - 応答のバインドより**後**に実行されるアクション(`data-{event}-redirect`・`-redirect-replace`・`-redirect-return-param`・`-dialog`・`-toast`・`-history`・`-scroll`)は、実行する直前に属性を評価します。そのため遷移先やメッセージを応答の値で切り替えられます(`data-click-redirect="{{nextAction === 'pay' ? redirectUrl : '/complete.html'}}"`)。応答は `data-{event}-bind` で自要素または祖先へ反映してください(式のスコープに入る位置が必要です)。式が使っていたキーが手続きの途中で消えた場合(全置換の `data-{event}-bind`)は開始時の評価値を使い、開発モードで警告します(遷移が静かに止まりません)。`data-store` のミラーはバインディングと同期なので、遷移前に必ず完了しています。
127
127
  - `data-enhance="名前"` — DOM を走査して機能を付加する外部ライブラリ(Choices.js・郵便番号補完など)を宣言で適用します。`Haori.enhancers.register(名前, {init, refresh, destroy})` で登録すると、初期表示・後から追加された要素・`data-each` の新規行では `init`、`data-each` の描画確定・`data-if` の再表示・フォームのリセット(`data-{event}-reset` とネイティブの `form.reset()` の両方。いずれも値の復元が終わった後)では `refresh`、DOM から外れたときは `destroy` が呼ばれます。適用は要素ごと・名前ごとに一度だけで、走査は宣言した要素の配下に限定されます。未登録の名前は適用を保留し、登録時に遡って適用するため読み込み順に依存しません。登録なしで済ませる簡易形 `data-enhance-new="Global.Ctor"` は、ドット区切りのグローバル参照を対象要素で `new` します(値にコードは書けません)。外部ライブラリの生成 DOM は `data-external` で監視対象から外せます。`data-external` の配下で連携が生成した DOM は、`register()` の置き場所や要素の移動によらずフォーム値に収集されません。`init` は Haori が走査した要素に対して呼ばれ、連携が `data-external` の外に生成した DOM は初期表示の途中でも取り込まれます。
128
128
  - 編集可能な行の中で「取得した候補から選択中の 1 件を引く」構成では、`data-attr-value="{{...}}"` のように**宣言バインドで値が決まる入力は、行の値反映で上書きされません**(評価が解決している間)。評価が未解決のあいだは従来どおり行データの値を表示するため、保存済みレコードから復元した値も失われません。応答は式を書いた要素自身か祖先へバインドする必要があるため、行全体で使う場合は `data-fetch-bind` で**行の内側のラッパ**へ寄せてください(行要素自身を指すと行データへの書き戻しになり、候補一覧が収集値へ入ります)。バインド先の外に置いた宣言は既定値のままになるため、開発モードでは「別のスコープでは供給されているキー」として警告します。
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.59.3
5
+ Version: 0.59.4
6
6
 
7
7
  ---
8
8
 
@@ -122,7 +122,7 @@ Event-driven actions:
122
122
  - `data-input-*` — run a procedure on each keystroke (the `input` event) for text inputs. Because `input` fires incrementally, only elements that explicitly declare a `data-input-*` attribute are handled (opt-in); like `change`, it auto-detects the ancestor form and reflects the value into two-way bindings. Useful for incremental search filtering (e.g. `<input name="q" data-input-form>`).
123
123
  - `data-on="eventName"` + `data-on-*` — run a procedure when an arbitrary **custom event** dispatched on `window` / `document` fires (the action vocabulary is shared with `data-{event}-*`). Lets you declaratively initialize on events other than the built-ins, e.g. a native-bridge ready signal (`<body data-on="appReady" data-on-fetch="/api/init.json" data-on-bind="#app">`). The event name is held in the attribute value (attribute names are lowercased), a single `window` capture subscription receives both `window`- and `document`-dispatched events without double-firing, and elements inserted later are picked up too. Built-in names (click/change/input/load) are warned and not subscribed. Note: events dispatched before Haori subscribes are not received (no replay). Add `data-on-target="#sub-modal"` to run the procedure only for events fired from that element or its descendants (for example, reset state only when a specific Bootstrap modal fires `hidden.bs.modal`).
124
124
  - `data-validity="{{expr}}"` / `data-validity-message="…"` — declarative cross-field validation on an input. The condition is pushed into `setCustomValidity()`, so it rides on native validation (`data-{event}-validate`): bubble message, focus move and `:invalid` styling all keep working. Conditions that native constraints cannot express ("either phone or e-mail", "the two addresses must match") become declarative.
125
- - `data-{event}-if="{{expr}}"` (`data-fetch-if` for the non-event form) — an execution condition for the procedure. When false, nothing runs — fetch, redirect and `data-{event}-run` included. Both are evaluated **synchronously at run time**, so they do not wait for attribute re-rendering (`requestAnimationFrame`) and always see the input the user just changed — unlike `data-attr-disabled`, which is one frame stale when you fix the last field and press straight away. Do not use `disabled` to block a click: a disabled button fires no click event at all, so the "fixed it but cannot press" direction cannot be recovered at run time.
125
+ - `data-{event}-if="{{expr}}"` (`data-fetch-if` for the non-event form) — an execution condition for the procedure. When false, nothing runs — fetch, redirect and `data-{event}-run` included (on an input's `change` / `input`, the typed value is still committed to the form's binding data, except when a `-bind` without `-fetch` redirects the value to its target). Both are evaluated **synchronously at run time**, so they do not wait for attribute re-rendering (`requestAnimationFrame`) and always see the input the user just changed — unlike `data-attr-disabled`, which is one frame stale when you fix the last field and press straight away. Do not use `disabled` to block a click: a disabled button fires no click event at all, so the "fixed it but cannot press" direction cannot be recovered at run time.
126
126
  - Actions that run **after** the response is bound (`data-{event}-redirect`, `-redirect-replace`, `-redirect-return-param`, `-dialog`, `-toast`, `-history`, `-scroll`) evaluate their attribute right before they run, so the destination or message can be decided by the response (`data-click-redirect="{{nextAction === 'pay' ? redirectUrl : '/complete.html'}}"`). Bind the response to the element itself or an ancestor so the keys are in scope. If a key the expression used disappears mid-procedure (a full-replace `data-{event}-bind`), the value evaluated at procedure start is used instead and a warning is logged in dev mode — navigation is never silently dropped. `data-store` mirroring is synchronous with the binding, so it always completes before the redirect.
127
127
  - `data-enhance="name"` applies a DOM-scanning third-party library (Choices.js, postal-code helpers, …) declaratively. Register it once with `Haori.enhancers.register(name, {init, refresh, destroy})` and Haori calls `init` on the initial scan, on nodes added later and on new `data-each` rows, `refresh` when a `data-each` render settles, when a `data-if` branch is shown again and when a form is reset (both `data-{event}-reset` and a native `form.reset()`, always after the values have been restored), and `destroy` when the element leaves the DOM. Application is once per element per name and the scan is limited to the declaring element's subtree. Unregistered names stay pending and are applied retroactively when registered, so load order does not matter. The registration-free shorthand `data-enhance-new="Global.Ctor"` `new`s a dot-separated global reference with the element as its argument (no code allowed in the value). Keep library-generated DOM out of Haori's observation with `data-external`: DOM a library generates under `data-external` is never collected as form values, wherever `register()` runs and even when the container is moved. `init` is called only on elements Haori has scanned, and DOM an enhancer creates outside `data-external` is picked up even during the initial scan.
128
128
  - Inside an editable row, when you pull "the selected one out of the fetched candidates", inputs whose value is decided by a declarative binding (`data-attr-value="{{...}}"` and friends) are **no longer overwritten by the row data** while the expression resolves. While it is unresolved the row data is applied as before, so a value restored from a saved record is not lost. A response is only visible to the bind target and its descendants, so point `data-fetch-bind` at a **wrapper inside the row** when the whole row needs it (pointing at the row element itself writes through to the row data, putting the candidate list into the collected values). Declarations placed outside the bind target keep their fallback value, and development mode now warns that the key is provided in another scope.