formfx 1.0.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.
package/LICENSE ADDED
@@ -0,0 +1,28 @@
1
+ BSD 3-Clause License
2
+
3
+ Copyright (c) 2026, https://monou.jp/, Kato Masaya
4
+
5
+ Redistribution and use in source and binary forms, with or without
6
+ modification, are permitted provided that the following conditions are met:
7
+
8
+ 1. Redistributions of source code must retain the above copyright notice, this
9
+ list of conditions and the following disclaimer.
10
+
11
+ 2. Redistributions in binary form must reproduce the above copyright notice,
12
+ this list of conditions and the following disclaimer in the documentation
13
+ and/or other materials provided with the distribution.
14
+
15
+ 3. Neither the name of the copyright holder nor the names of its
16
+ contributors may be used to endorse or promote products derived from
17
+ this software without specific prior written permission.
18
+
19
+ THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
20
+ AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
21
+ IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
22
+ DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
23
+ FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
24
+ DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
25
+ SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
26
+ CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
27
+ OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
28
+ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
package/README.ja.md ADDED
@@ -0,0 +1,171 @@
1
+ # FormFx
2
+
3
+ 強力で軽量、かつ宣言的なフォーム制御ライブラリ。
4
+
5
+ FormFxを使用すると、複雑なJavaScriptを書いたり重いフレームワークに頼ったりすることなく、シンプルなデータ属性やJSONルールを使用して、動的なフォーム動作(表示/非表示、有効/無効、バリデーション)を管理できます。
6
+
7
+ ## なぜ FormFx なのか?
8
+
9
+ - **メンテナンス性の向上**: jQueryやVanilla JSのスパゲッティコードを回避できます。
10
+ - **軽量**: フル機能のフォームエンジンに比べてオーバーヘッドが最小限です。
11
+ - **宣言的**: `data-fx-*` 属性を使用して、ロジックをHTML内に配置できます。
12
+ - **安全**: `eval()` や `new Function()` を使用しません。式は安全に評価されます。
13
+ - **フレームワークに依存しない**: あらゆる環境で動作します。
14
+
15
+ ## インストール
16
+
17
+ ```bash
18
+ npm install formfx
19
+ ```
20
+
21
+ または CDN 経由:
22
+ ```html
23
+ <script src="https://unpkg.com/formfx/dist/index.js"></script>
24
+ ```
25
+
26
+ ## クイックスタート (属性ベース)
27
+
28
+ HTMLのデータ属性を使用してルールを定義するだけです。
29
+
30
+ ```html
31
+ <form id="my-form">
32
+ <input type="checkbox" id="toggle" name="toggle">
33
+
34
+ <div data-fx-show="toggle == true">
35
+ <p>このセクションはチェックボックスがオンのときだけ表示されます。</p>
36
+ <input type="text" name="optional_field" data-fx-required="toggle == true">
37
+ </div>
38
+ </form>
39
+
40
+ <script type="module">
41
+ import { FormFx } from 'formfx';
42
+ const fx = new FormFx(document.getElementById('my-form'));
43
+ fx.mount();
44
+ </script>
45
+ ```
46
+
47
+ ## JSON ルール (高度な使い方)
48
+
49
+ より複雑なロジックや、HTMLをクリーンに保ちたい場合に使用します。JSONルールは属性ベースのルールよりも優先されます。
50
+
51
+ ```javascript
52
+ const fx = new FormFx(form, {
53
+ rules: [
54
+ {
55
+ if: "total > 1000",
56
+ then: [
57
+ { show: "#discount-section" },
58
+ { required: "#coupon-code" }
59
+ ]
60
+ }
61
+ ]
62
+ });
63
+ ```
64
+
65
+ ## リピーター (Repeater)
66
+
67
+ 動的な行の追加・削除を簡単に処理できます。
68
+
69
+ ```html
70
+ <div data-fx-repeater="items" data-fx-min="1" data-fx-max="5">
71
+ <div data-fx-list>
72
+ <template>
73
+ <div data-fx-item>
74
+ <input type="text" data-fx-field="name">
75
+ <button type="button" data-fx-remove-btn>削除</button>
76
+ </div>
77
+ </template>
78
+ </div>
79
+ <button type="button" data-fx-add-btn>アイテムを追加</button>
80
+ </div>
81
+ ```
82
+
83
+ ### 行コンテキスト (`@row.field`)
84
+
85
+ 同じリピーター行内のフィールドを参照します。
86
+
87
+ ```html
88
+ <input type="number" data-fx-field="price">
89
+ <div data-fx-show="@row.price > 100">高額アイテムです!</div>
90
+ ```
91
+
92
+ ## 永続化 (Persistence)
93
+
94
+ フォームルールの状態を自動的に保存・復元します。
95
+
96
+ ```javascript
97
+ const fx = new FormFx(form, {
98
+ persist: {
99
+ key: 'my-form-settings',
100
+ storage: 'localStorage'
101
+ }
102
+ });
103
+ ```
104
+
105
+ ## ルールエディタ (オプションのアドオン)
106
+
107
+ フォームルールのためのビジュアルエディタです。
108
+
109
+ ```javascript
110
+ import { FormFx } from 'formfx';
111
+ // メインバンドルを小さく保つため、エディタは個別にインポートします
112
+ import { RuleEditor } from 'formfx/editor';
113
+ import 'formfx/editor.css';
114
+
115
+ const fx = new FormFx(form);
116
+ fx.mount();
117
+
118
+ const editor = new RuleEditor(fx, {
119
+ mount: document.getElementById('editor-container'),
120
+ mode: 'json'
121
+ });
122
+ editor.mount();
123
+ ```
124
+
125
+ ## デバッグパネル
126
+
127
+ 開発用のビジュアルデバッグ情報。
128
+
129
+ ```javascript
130
+ const fx = new FormFx(form, { debug: true });
131
+ ```
132
+
133
+ ## API リファレンス
134
+
135
+ ### `FormFxOptions`
136
+ - `disableOnHide`: Boolean (デフォルト `true`)
137
+ - `clearOnHide`: Boolean (デフォルト `false`)
138
+ - `rules`: `JSONRule[]`
139
+ - `persist`: `PersistOptions`
140
+ - `debug`: Boolean
141
+
142
+ ### `FormFx` メソッド
143
+ - `mount()`: リスナーとオブザーバーを初期化します。
144
+ - `destroy()`: すべてをクリーンアップします(リスナーとオブザーバーを削除)。
145
+ - `pause()` / `resume()`: ルールの評価を一時停止または再開します。
146
+ - `reEvaluate()`: 手動で評価をトリガーします。
147
+ - `exportRules()`: 現在のJSONルールを取得します。
148
+ - `importRules(rules)`: 新しいJSONルールを読み込みます。
149
+ - `enableRule(ruleId)` / `disableRule(ruleId)`: IDでJSONルールを制御します。
150
+
151
+ ## 互換性
152
+
153
+ - モダンブラウザ (Chrome, Firefox, Safari, Edge)
154
+ - `eval()` を使用していません。厳格な CSP 環境でも安全です。
155
+
156
+ ## セキュリティ
157
+
158
+ - 独自のトークナイザーとパーサーにより、式は特定の安全な操作のみ実行可能です。
159
+ - 式の中から `window` や `document` などのグローバルオブジェクトにはアクセスできません。
160
+
161
+ ## ロードマップ
162
+
163
+ - **v1.1**: 式内での非同期関数のサポート。
164
+ - **v2.0**: カスタムエフェクト用のプラグインシステム。
165
+
166
+ ## ライセンス
167
+
168
+ BSD 3-Clause License
169
+
170
+ ### 貢献に関する同意
171
+ 本リポジトリへの貢献(プルリクエスト等)を行う場合、寄与者ライセンス同意書(CLA)に同意したものとみなされます。これには著作者人格権の不行使や、オーナーによる将来のライセンス変更・商用製品への組み込みの許可が含まれます。詳細は [CONTRIBUTING.ja.md](CONTRIBUTING.ja.md) をご確認ください。
package/README.md ADDED
@@ -0,0 +1,171 @@
1
+ # FormFx
2
+
3
+ Powerful, lightweight, and declarative form control library.
4
+
5
+ FormFx allows you to manage dynamic form behaviors (show/hide, enable/disable, validation) using simple data attributes or JSON rules, without writing complex JavaScript or relying on heavy frameworks.
6
+
7
+ ## Why FormFx?
8
+
9
+ - **Better Maintenance**: Avoid jQuery/Vanilla JS spaghetti code.
10
+ - **Lightweight**: Minimal overhead compared to full-blown form engines.
11
+ - **Declarative**: Logic is co-located with HTML using `data-fx-*` attributes.
12
+ - **Safe**: No `eval()` or `new Function()`. Expressions are evaluated safely.
13
+ - **Framework Agnostic**: Works everywhere.
14
+
15
+ ## Install
16
+
17
+ ```bash
18
+ npm install formfx
19
+ ```
20
+
21
+ Or via CDN:
22
+ ```html
23
+ <script src="https://unpkg.com/formfx/dist/index.js"></script>
24
+ ```
25
+
26
+ ## Quick Start (Attributes)
27
+
28
+ Just define rules in your HTML using data attributes.
29
+
30
+ ```html
31
+ <form id="my-form">
32
+ <input type="checkbox" id="toggle" name="toggle">
33
+
34
+ <div data-fx-show="toggle == true">
35
+ <p>This is only visible when the checkbox is checked.</p>
36
+ <input type="text" name="optional_field" data-fx-required="toggle == true">
37
+ </div>
38
+ </form>
39
+
40
+ <script type="module">
41
+ import { FormFx } from 'formfx';
42
+ const fx = new FormFx(document.getElementById('my-form'));
43
+ fx.mount();
44
+ </script>
45
+ ```
46
+
47
+ ## JSON Rules (Advanced)
48
+
49
+ For more complex logic or when you want to keep HTML clean. JSON rules take precedence over attributes.
50
+
51
+ ```javascript
52
+ const fx = new FormFx(form, {
53
+ rules: [
54
+ {
55
+ if: "total > 1000",
56
+ then: [
57
+ { show: "#discount-section" },
58
+ { required: "#coupon-code" }
59
+ ]
60
+ }
61
+ ]
62
+ });
63
+ ```
64
+
65
+ ## Repeater
66
+
67
+ Handle dynamic rows with ease.
68
+
69
+ ```html
70
+ <div data-fx-repeater="items" data-fx-min="1" data-fx-max="5">
71
+ <div data-fx-list>
72
+ <template>
73
+ <div data-fx-item>
74
+ <input type="text" data-fx-field="name">
75
+ <button type="button" data-fx-remove-btn>Remove</button>
76
+ </div>
77
+ </template>
78
+ </div>
79
+ <button type="button" data-fx-add-btn>Add Item</button>
80
+ </div>
81
+ ```
82
+
83
+ ### Row Context (`@row.field`)
84
+
85
+ Refer to fields within the same repeater row.
86
+
87
+ ```html
88
+ <input type="number" data-fx-field="price">
89
+ <div data-fx-show="@row.price > 100">Expensive item!</div>
90
+ ```
91
+
92
+ ## Persistence
93
+
94
+ Automatically save and restore form rules state.
95
+
96
+ ```javascript
97
+ const fx = new FormFx(form, {
98
+ persist: {
99
+ key: 'my-form-settings',
100
+ storage: 'localStorage'
101
+ }
102
+ });
103
+ ```
104
+
105
+ ## Rule Editor (Optional Add-on)
106
+
107
+ A visual editor for your form rules.
108
+
109
+ ```javascript
110
+ import { FormFx } from 'formfx';
111
+ // Import editor separately to keep main bundle small
112
+ import { RuleEditor } from 'formfx/editor';
113
+ import 'formfx/editor.css';
114
+
115
+ const fx = new FormFx(form);
116
+ fx.mount();
117
+
118
+ const editor = new RuleEditor(fx, {
119
+ mount: document.getElementById('editor-container'),
120
+ mode: 'json'
121
+ });
122
+ editor.mount();
123
+ ```
124
+
125
+ ## Debug Panel
126
+
127
+ Visual debug information for development.
128
+
129
+ ```javascript
130
+ const fx = new FormFx(form, { debug: true });
131
+ ```
132
+
133
+ ## API Reference
134
+
135
+ ### `FormFxOptions`
136
+ - `disableOnHide`: Boolean (default `true`)
137
+ - `clearOnHide`: Boolean (default `false`)
138
+ - `rules`: `JSONRule[]`
139
+ - `persist`: `PersistOptions`
140
+ - `debug`: Boolean
141
+
142
+ ### `FormFx` Methods
143
+ - `mount()`: Initialize listeners and observers.
144
+ - `destroy()`: Cleanup everything (removes listeners and observers).
145
+ - `pause()` / `resume()`: Pause or resume rule evaluation.
146
+ - `reEvaluate()`: Manually trigger evaluation.
147
+ - `exportRules()`: Get current JSON rules.
148
+ - `importRules(rules)`: Load new JSON rules.
149
+ - `enableRule(ruleId)` / `disableRule(ruleId)`: Control JSON rules by ID.
150
+
151
+ ## Compatibility
152
+
153
+ - Modern browsers (Chrome, Firefox, Safari, Edge)
154
+ - No `eval()` used. Safe for strict CSP environments.
155
+
156
+ ## Security
157
+
158
+ - Custom tokenizer and parser ensure expressions are only allowed to perform specific safe operations.
159
+ - No access to global objects like `window` or `document` from within expressions.
160
+
161
+ ## Roadmap
162
+
163
+ - **v1.1**: Async function support in expressions.
164
+ - **v2.0**: Plugin system for custom effects.
165
+
166
+ ## License
167
+
168
+ This project is licensed under the BSD 3-Clause License - see the [LICENSE](LICENSE) file for details.
169
+
170
+ ### Note for Contributors
171
+ By contributing to this repository, you agree to the terms of our Contributor License Agreement (CLA), which includes the waiver of moral rights and allows for future re-licensing or commercial use by the project owner.
@@ -0,0 +1,62 @@
1
+ var f=class{constructor(t,e){this.fx=t;this.options=e;this.container=document.createElement("div"),this.container.className="formfx-editor";}container;activeRuleIndex=null;mount(){this.options.mount.appendChild(this.container),this.render();}render(){let t=this.fx.exportRules();this.container.innerHTML=`
2
+ <div class="formfx-editor-header">
3
+ <div class="formfx-editor-title">FormFx Rule Editor</div>
4
+ <div class="formfx-editor-actions">
5
+ <button class="formfx-btn formfx-btn-primary" id="fx-add-rule">+ Add Rule</button>
6
+ </div>
7
+ </div>
8
+ <div class="formfx-editor-body">
9
+ <div class="formfx-rule-list" id="fx-rule-list"></div>
10
+ <div class="formfx-rule-form" id="fx-rule-form"></div>
11
+ </div>
12
+ `,this.renderRuleList(t),this.renderRuleForm(t),this.container.querySelector("#fx-add-rule")?.addEventListener("click",()=>{this.addRule();});}renderRuleList(t){let e=this.container.querySelector("#fx-rule-list");e&&(e.innerHTML=t.map((i,r)=>`
13
+ <div class="formfx-rule-item ${this.activeRuleIndex===r?"active":""}" data-index="${r}">
14
+ <div class="formfx-rule-item-id">${i.id||"(no id)"}</div>
15
+ <div class="formfx-rule-item-expr">if: ${i.if}</div>
16
+ </div>
17
+ `).join("")||'<div class="formfx-empty-state">No rules defined</div>',e.querySelectorAll(".formfx-rule-item").forEach(i=>{i.addEventListener("click",()=>{this.activeRuleIndex=parseInt(i.getAttribute("data-index")||"0"),this.render();});}));}renderRuleForm(t){let e=this.container.querySelector("#fx-rule-form");if(!e||this.activeRuleIndex===null||!t[this.activeRuleIndex]){e&&(e.innerHTML='<div class="formfx-empty-state">Select a rule to edit</div>');return}let i=t[this.activeRuleIndex];e.innerHTML=`
18
+ <div class="formfx-field-group">
19
+ <label class="formfx-label">Rule ID</label>
20
+ <input type="text" class="formfx-input" id="fx-edit-id" value="${i.id||""}">
21
+ </div>
22
+ <div class="formfx-field-group">
23
+ <label class="formfx-label">If Condition (DSL)</label>
24
+ <textarea class="formfx-textarea" id="fx-edit-if" rows="3">${i.if}</textarea>
25
+ </div>
26
+
27
+ <div class="formfx-field-group">
28
+ <label class="formfx-label">Then Effects</label>
29
+ <div id="fx-then-list"></div>
30
+ <button class="formfx-btn" id="fx-add-then">+ Add Effect</button>
31
+ </div>
32
+
33
+ <div class="formfx-field-group">
34
+ <label class="formfx-label">Else Effects (Optional)</label>
35
+ <div id="fx-else-list"></div>
36
+ <button class="formfx-btn" id="fx-add-else">+ Add Effect</button>
37
+ </div>
38
+
39
+ <div style="margin-top: 40px; display: flex; justify-content: space-between;">
40
+ <button class="formfx-btn formfx-btn-primary" id="fx-save-rule">Save Changes</button>
41
+ <button class="formfx-btn formfx-btn-danger" id="fx-delete-rule">Delete Rule</button>
42
+ </div>
43
+
44
+ <div class="formfx-json-preview">
45
+ <div class="formfx-label">JSON Preview (Readonly)</div>
46
+ <div class="formfx-json-content">${JSON.stringify(i,null,2)}</div>
47
+ </div>
48
+ `,this.renderEffectList("then",i.then),this.renderEffectList("else",i.else||[]),e.querySelector("#fx-save-rule")?.addEventListener("click",()=>this.saveRule()),e.querySelector("#fx-delete-rule")?.addEventListener("click",()=>this.deleteRule()),e.querySelector("#fx-add-then")?.addEventListener("click",()=>this.addEffect("then")),e.querySelector("#fx-add-else")?.addEventListener("click",()=>this.addEffect("else"));}renderEffectList(t,e){let i=this.container.querySelector(`#fx-${t}-list`);i&&(i.innerHTML=e.map((r,s)=>{let n=Object.entries(r)[0]||["show",""],l=n[0],o=n[1];return `
49
+ <div class="formfx-effect-row" data-type="${t}" data-index="${s}">
50
+ <select class="formfx-select fx-effect-type" style="width: 120px;">
51
+ <option value="show" ${l==="show"?"selected":""}>show</option>
52
+ <option value="hide" ${l==="hide"?"selected":""}>hide</option>
53
+ <option value="required" ${l==="required"?"selected":""}>require</option>
54
+ <option value="disabled" ${l==="disabled"?"selected":""}>disabled</option>
55
+ <option value="enable" ${l==="enable"?"selected":""}>enable</option>
56
+ <option value="clear" ${l==="clear"?"selected":""}>clear</option>
57
+ </select>
58
+ <input type="text" class="formfx-input fx-effect-selector" placeholder="#id" value="${o}">
59
+ <button class="formfx-btn formfx-btn-danger fx-remove-effect">\xD7</button>
60
+ </div>
61
+ `}).join(""),i.querySelectorAll(".fx-remove-effect").forEach((r,s)=>{r.addEventListener("click",()=>{e.splice(s,1),this.renderRuleForm(this.fx.exportRules());});}));}addRule(){let t=this.fx.exportRules(),e={id:`rule_${Date.now()}`,if:"true",then:[{show:""}]};t.push(e),this.activeRuleIndex=t.length-1,this.fx.importRules(t),this.render();}saveRule(){if(this.activeRuleIndex===null)return;this.fx.pause();let t=this.fx.exportRules(),e=t[this.activeRuleIndex];e.id=this.container.querySelector("#fx-edit-id").value,e.if=this.container.querySelector("#fx-edit-if").value;let i=r=>{let s=this.container.querySelectorAll(`.formfx-effect-row[data-type="${r}"]`),n=[];return s.forEach(l=>{let o=l.querySelector(".fx-effect-type").value,a=l.querySelector(".fx-effect-selector").value,d={};d[o]=a,n.push(d);}),n};e.then=i("then"),e.else=i("else"),e.else.length===0&&delete e.else,this.fx.importRules(t),this.fx.resume(),this.render();}deleteRule(){if(this.activeRuleIndex===null||!confirm("Are you sure you want to delete this rule?"))return;let t=this.fx.exportRules();t.splice(this.activeRuleIndex,1),this.activeRuleIndex=null,this.fx.importRules(t),this.render();}addEffect(t){if(this.activeRuleIndex===null)return;let e=this.fx.exportRules(),i=e[this.activeRuleIndex];t==="then"?i.then.push({show:""}):(i.else=i.else||[],i.else.push({show:""})),this.renderRuleForm(e);}};export{f as a};//# sourceMappingURL=chunk-6E5EWQVW.js.map
62
+ //# sourceMappingURL=chunk-6E5EWQVW.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/editor/RuleEditor.ts"],"names":["RuleEditor","fx","options","rules","listEl","rule","index","item","formEl","type","effects","eff","i","entry","effectType","selector","btn","newRule","readEffects","rows","row","obj"],"mappings":"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","file":"chunk-6E5EWQVW.js","sourcesContent":["import { FormFx } from '../core/FormFx';\r\nimport { RuleEditorOptions, JSONRule } from '../types';\r\n\r\nexport class RuleEditor {\r\n private container: HTMLElement;\r\n private activeRuleIndex: number | null = null;\r\n\r\n constructor(\r\n private fx: FormFx,\r\n private options: RuleEditorOptions\r\n ) {\r\n this.container = document.createElement('div');\r\n this.container.className = 'formfx-editor';\r\n }\r\n\r\n mount(): void {\r\n this.options.mount.appendChild(this.container);\r\n this.render();\r\n }\r\n\r\n private render(): void {\r\n const rules = this.fx.exportRules();\r\n \r\n this.container.innerHTML = `\r\n <div class=\"formfx-editor-header\">\r\n <div class=\"formfx-editor-title\">FormFx Rule Editor</div>\r\n <div class=\"formfx-editor-actions\">\r\n <button class=\"formfx-btn formfx-btn-primary\" id=\"fx-add-rule\">+ Add Rule</button>\r\n </div>\r\n </div>\r\n <div class=\"formfx-editor-body\">\r\n <div class=\"formfx-rule-list\" id=\"fx-rule-list\"></div>\r\n <div class=\"formfx-rule-form\" id=\"fx-rule-form\"></div>\r\n </div>\r\n `;\r\n\r\n this.renderRuleList(rules);\r\n this.renderRuleForm(rules);\r\n\r\n this.container.querySelector('#fx-add-rule')?.addEventListener('click', () => {\r\n this.addRule();\r\n });\r\n }\r\n\r\n private renderRuleList(rules: JSONRule[]): void {\r\n const listEl = this.container.querySelector('#fx-rule-list');\r\n if (!listEl) return;\r\n\r\n listEl.innerHTML = rules.map((rule, index) => `\r\n <div class=\"formfx-rule-item ${this.activeRuleIndex === index ? 'active' : ''}\" data-index=\"${index}\">\r\n <div class=\"formfx-rule-item-id\">${rule.id || '(no id)'}</div>\r\n <div class=\"formfx-rule-item-expr\">if: ${rule.if}</div>\r\n </div>\r\n `).join('') || '<div class=\"formfx-empty-state\">No rules defined</div>';\r\n\r\n listEl.querySelectorAll('.formfx-rule-item').forEach(item => {\r\n item.addEventListener('click', () => {\r\n this.activeRuleIndex = parseInt(item.getAttribute('data-index') || '0');\r\n this.render();\r\n });\r\n });\r\n }\r\n\r\n private renderRuleForm(rules: JSONRule[]): void {\r\n const formEl = this.container.querySelector('#fx-rule-form');\r\n if (!formEl || this.activeRuleIndex === null || !rules[this.activeRuleIndex]) {\r\n if (formEl) formEl.innerHTML = '<div class=\"formfx-empty-state\">Select a rule to edit</div>';\r\n return;\r\n }\r\n\r\n const rule = rules[this.activeRuleIndex];\r\n formEl.innerHTML = `\r\n <div class=\"formfx-field-group\">\r\n <label class=\"formfx-label\">Rule ID</label>\r\n <input type=\"text\" class=\"formfx-input\" id=\"fx-edit-id\" value=\"${rule.id || ''}\">\r\n </div>\r\n <div class=\"formfx-field-group\">\r\n <label class=\"formfx-label\">If Condition (DSL)</label>\r\n <textarea class=\"formfx-textarea\" id=\"fx-edit-if\" rows=\"3\">${rule.if}</textarea>\r\n </div>\r\n \r\n <div class=\"formfx-field-group\">\r\n <label class=\"formfx-label\">Then Effects</label>\r\n <div id=\"fx-then-list\"></div>\r\n <button class=\"formfx-btn\" id=\"fx-add-then\">+ Add Effect</button>\r\n </div>\r\n\r\n <div class=\"formfx-field-group\">\r\n <label class=\"formfx-label\">Else Effects (Optional)</label>\r\n <div id=\"fx-else-list\"></div>\r\n <button class=\"formfx-btn\" id=\"fx-add-else\">+ Add Effect</button>\r\n </div>\r\n\r\n <div style=\"margin-top: 40px; display: flex; justify-content: space-between;\">\r\n <button class=\"formfx-btn formfx-btn-primary\" id=\"fx-save-rule\">Save Changes</button>\r\n <button class=\"formfx-btn formfx-btn-danger\" id=\"fx-delete-rule\">Delete Rule</button>\r\n </div>\r\n\r\n <div class=\"formfx-json-preview\">\r\n <div class=\"formfx-label\">JSON Preview (Readonly)</div>\r\n <div class=\"formfx-json-content\">${JSON.stringify(rule, null, 2)}</div>\r\n </div>\r\n `;\r\n\r\n this.renderEffectList('then', rule.then);\r\n this.renderEffectList('else', rule.else || []);\r\n\r\n // Events\r\n formEl.querySelector('#fx-save-rule')?.addEventListener('click', () => this.saveRule());\r\n formEl.querySelector('#fx-delete-rule')?.addEventListener('click', () => this.deleteRule());\r\n formEl.querySelector('#fx-add-then')?.addEventListener('click', () => this.addEffect('then'));\r\n formEl.querySelector('#fx-add-else')?.addEventListener('click', () => this.addEffect('else'));\r\n }\r\n\r\n private renderEffectList(type: 'then' | 'else', effects: any[]): void {\r\n const listEl = this.container.querySelector(`#fx-${type}-list`);\r\n if (!listEl) return;\r\n\r\n listEl.innerHTML = effects.map((eff, i) => {\r\n const entry = Object.entries(eff)[0] || ['show', ''];\r\n const effectType = entry[0];\r\n const selector = entry[1];\r\n\r\n return `\r\n <div class=\"formfx-effect-row\" data-type=\"${type}\" data-index=\"${i}\">\r\n <select class=\"formfx-select fx-effect-type\" style=\"width: 120px;\">\r\n <option value=\"show\" ${effectType === 'show' ? 'selected' : ''}>show</option>\r\n <option value=\"hide\" ${effectType === 'hide' ? 'selected' : ''}>hide</option>\r\n <option value=\"required\" ${effectType === 'required' ? 'selected' : ''}>require</option>\r\n <option value=\"disabled\" ${effectType === 'disabled' ? 'selected' : ''}>disabled</option>\r\n <option value=\"enable\" ${effectType === 'enable' ? 'selected' : ''}>enable</option>\r\n <option value=\"clear\" ${effectType === 'clear' ? 'selected' : ''}>clear</option>\r\n </select>\r\n <input type=\"text\" class=\"formfx-input fx-effect-selector\" placeholder=\"#id\" value=\"${selector}\">\r\n <button class=\"formfx-btn formfx-btn-danger fx-remove-effect\">×</button>\r\n </div>\r\n `;\r\n }).join('');\r\n\r\n listEl.querySelectorAll('.fx-remove-effect').forEach((btn, i) => {\r\n btn.addEventListener('click', () => {\r\n effects.splice(i, 1);\r\n this.renderRuleForm(this.fx.exportRules());\r\n });\r\n });\r\n }\r\n\r\n private addRule(): void {\r\n const rules = this.fx.exportRules();\r\n const newRule: JSONRule = {\r\n id: `rule_${Date.now()}`,\r\n if: 'true',\r\n then: [{ show: '' }]\r\n };\r\n rules.push(newRule);\r\n this.activeRuleIndex = rules.length - 1;\r\n this.fx.importRules(rules);\r\n this.render();\r\n }\r\n\r\n private saveRule(): void {\r\n if (this.activeRuleIndex === null) return;\r\n \r\n this.fx.pause(); // 編集適用中は pause\r\n\r\n const rules = this.fx.exportRules();\r\n const rule = rules[this.activeRuleIndex];\r\n\r\n rule.id = (this.container.querySelector('#fx-edit-id') as HTMLInputElement).value;\r\n rule.if = (this.container.querySelector('#fx-edit-if') as HTMLTextAreaElement).value;\r\n\r\n const readEffects = (type: 'then' | 'else') => {\r\n const rows = this.container.querySelectorAll(`.formfx-effect-row[data-type=\"${type}\"]`);\r\n const effects: any[] = [];\r\n rows.forEach(row => {\r\n const effectType = (row.querySelector('.fx-effect-type') as HTMLSelectElement).value;\r\n const selector = (row.querySelector('.fx-effect-selector') as HTMLInputElement).value;\r\n const obj: any = {};\r\n obj[effectType] = selector;\r\n effects.push(obj);\r\n });\r\n return effects;\r\n };\r\n\r\n rule.then = readEffects('then');\r\n rule.else = readEffects('else');\r\n if (rule.else.length === 0) delete rule.else;\r\n\r\n this.fx.importRules(rules);\r\n this.fx.resume();\r\n this.render();\r\n }\r\n\r\n private deleteRule(): void {\r\n if (this.activeRuleIndex === null || !confirm('Are you sure you want to delete this rule?')) return;\r\n const rules = this.fx.exportRules();\r\n rules.splice(this.activeRuleIndex, 1);\r\n this.activeRuleIndex = null;\r\n this.fx.importRules(rules);\r\n this.render();\r\n }\r\n\r\n private addEffect(type: 'then' | 'else'): void {\r\n if (this.activeRuleIndex === null) return;\r\n const rules = this.fx.exportRules();\r\n const rule = rules[this.activeRuleIndex];\r\n if (type === 'then') {\r\n rule.then.push({ show: '' });\r\n } else {\r\n rule.else = rule.else || [];\r\n rule.else.push({ show: '' });\r\n }\r\n this.renderRuleForm(rules);\r\n }\r\n}\r\n"]}
@@ -0,0 +1,62 @@
1
+ 'use strict';var f=class{constructor(t,e){this.fx=t;this.options=e;this.container=document.createElement("div"),this.container.className="formfx-editor";}container;activeRuleIndex=null;mount(){this.options.mount.appendChild(this.container),this.render();}render(){let t=this.fx.exportRules();this.container.innerHTML=`
2
+ <div class="formfx-editor-header">
3
+ <div class="formfx-editor-title">FormFx Rule Editor</div>
4
+ <div class="formfx-editor-actions">
5
+ <button class="formfx-btn formfx-btn-primary" id="fx-add-rule">+ Add Rule</button>
6
+ </div>
7
+ </div>
8
+ <div class="formfx-editor-body">
9
+ <div class="formfx-rule-list" id="fx-rule-list"></div>
10
+ <div class="formfx-rule-form" id="fx-rule-form"></div>
11
+ </div>
12
+ `,this.renderRuleList(t),this.renderRuleForm(t),this.container.querySelector("#fx-add-rule")?.addEventListener("click",()=>{this.addRule();});}renderRuleList(t){let e=this.container.querySelector("#fx-rule-list");e&&(e.innerHTML=t.map((i,r)=>`
13
+ <div class="formfx-rule-item ${this.activeRuleIndex===r?"active":""}" data-index="${r}">
14
+ <div class="formfx-rule-item-id">${i.id||"(no id)"}</div>
15
+ <div class="formfx-rule-item-expr">if: ${i.if}</div>
16
+ </div>
17
+ `).join("")||'<div class="formfx-empty-state">No rules defined</div>',e.querySelectorAll(".formfx-rule-item").forEach(i=>{i.addEventListener("click",()=>{this.activeRuleIndex=parseInt(i.getAttribute("data-index")||"0"),this.render();});}));}renderRuleForm(t){let e=this.container.querySelector("#fx-rule-form");if(!e||this.activeRuleIndex===null||!t[this.activeRuleIndex]){e&&(e.innerHTML='<div class="formfx-empty-state">Select a rule to edit</div>');return}let i=t[this.activeRuleIndex];e.innerHTML=`
18
+ <div class="formfx-field-group">
19
+ <label class="formfx-label">Rule ID</label>
20
+ <input type="text" class="formfx-input" id="fx-edit-id" value="${i.id||""}">
21
+ </div>
22
+ <div class="formfx-field-group">
23
+ <label class="formfx-label">If Condition (DSL)</label>
24
+ <textarea class="formfx-textarea" id="fx-edit-if" rows="3">${i.if}</textarea>
25
+ </div>
26
+
27
+ <div class="formfx-field-group">
28
+ <label class="formfx-label">Then Effects</label>
29
+ <div id="fx-then-list"></div>
30
+ <button class="formfx-btn" id="fx-add-then">+ Add Effect</button>
31
+ </div>
32
+
33
+ <div class="formfx-field-group">
34
+ <label class="formfx-label">Else Effects (Optional)</label>
35
+ <div id="fx-else-list"></div>
36
+ <button class="formfx-btn" id="fx-add-else">+ Add Effect</button>
37
+ </div>
38
+
39
+ <div style="margin-top: 40px; display: flex; justify-content: space-between;">
40
+ <button class="formfx-btn formfx-btn-primary" id="fx-save-rule">Save Changes</button>
41
+ <button class="formfx-btn formfx-btn-danger" id="fx-delete-rule">Delete Rule</button>
42
+ </div>
43
+
44
+ <div class="formfx-json-preview">
45
+ <div class="formfx-label">JSON Preview (Readonly)</div>
46
+ <div class="formfx-json-content">${JSON.stringify(i,null,2)}</div>
47
+ </div>
48
+ `,this.renderEffectList("then",i.then),this.renderEffectList("else",i.else||[]),e.querySelector("#fx-save-rule")?.addEventListener("click",()=>this.saveRule()),e.querySelector("#fx-delete-rule")?.addEventListener("click",()=>this.deleteRule()),e.querySelector("#fx-add-then")?.addEventListener("click",()=>this.addEffect("then")),e.querySelector("#fx-add-else")?.addEventListener("click",()=>this.addEffect("else"));}renderEffectList(t,e){let i=this.container.querySelector(`#fx-${t}-list`);i&&(i.innerHTML=e.map((r,s)=>{let n=Object.entries(r)[0]||["show",""],l=n[0],o=n[1];return `
49
+ <div class="formfx-effect-row" data-type="${t}" data-index="${s}">
50
+ <select class="formfx-select fx-effect-type" style="width: 120px;">
51
+ <option value="show" ${l==="show"?"selected":""}>show</option>
52
+ <option value="hide" ${l==="hide"?"selected":""}>hide</option>
53
+ <option value="required" ${l==="required"?"selected":""}>require</option>
54
+ <option value="disabled" ${l==="disabled"?"selected":""}>disabled</option>
55
+ <option value="enable" ${l==="enable"?"selected":""}>enable</option>
56
+ <option value="clear" ${l==="clear"?"selected":""}>clear</option>
57
+ </select>
58
+ <input type="text" class="formfx-input fx-effect-selector" placeholder="#id" value="${o}">
59
+ <button class="formfx-btn formfx-btn-danger fx-remove-effect">\xD7</button>
60
+ </div>
61
+ `}).join(""),i.querySelectorAll(".fx-remove-effect").forEach((r,s)=>{r.addEventListener("click",()=>{e.splice(s,1),this.renderRuleForm(this.fx.exportRules());});}));}addRule(){let t=this.fx.exportRules(),e={id:`rule_${Date.now()}`,if:"true",then:[{show:""}]};t.push(e),this.activeRuleIndex=t.length-1,this.fx.importRules(t),this.render();}saveRule(){if(this.activeRuleIndex===null)return;this.fx.pause();let t=this.fx.exportRules(),e=t[this.activeRuleIndex];e.id=this.container.querySelector("#fx-edit-id").value,e.if=this.container.querySelector("#fx-edit-if").value;let i=r=>{let s=this.container.querySelectorAll(`.formfx-effect-row[data-type="${r}"]`),n=[];return s.forEach(l=>{let o=l.querySelector(".fx-effect-type").value,a=l.querySelector(".fx-effect-selector").value,d={};d[o]=a,n.push(d);}),n};e.then=i("then"),e.else=i("else"),e.else.length===0&&delete e.else,this.fx.importRules(t),this.fx.resume(),this.render();}deleteRule(){if(this.activeRuleIndex===null||!confirm("Are you sure you want to delete this rule?"))return;let t=this.fx.exportRules();t.splice(this.activeRuleIndex,1),this.activeRuleIndex=null,this.fx.importRules(t),this.render();}addEffect(t){if(this.activeRuleIndex===null)return;let e=this.fx.exportRules(),i=e[this.activeRuleIndex];t==="then"?i.then.push({show:""}):(i.else=i.else||[],i.else.push({show:""})),this.renderRuleForm(e);}};exports.a=f;//# sourceMappingURL=chunk-GXMPHKTF.cjs.map
62
+ //# sourceMappingURL=chunk-GXMPHKTF.cjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/editor/RuleEditor.ts"],"names":["RuleEditor","fx","options","rules","listEl","rule","index","item","formEl","type","effects","eff","i","entry","effectType","selector","btn","newRule","readEffects","rows","row","obj"],"mappings":"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","file":"chunk-GXMPHKTF.cjs","sourcesContent":["import { FormFx } from '../core/FormFx';\r\nimport { RuleEditorOptions, JSONRule } from '../types';\r\n\r\nexport class RuleEditor {\r\n private container: HTMLElement;\r\n private activeRuleIndex: number | null = null;\r\n\r\n constructor(\r\n private fx: FormFx,\r\n private options: RuleEditorOptions\r\n ) {\r\n this.container = document.createElement('div');\r\n this.container.className = 'formfx-editor';\r\n }\r\n\r\n mount(): void {\r\n this.options.mount.appendChild(this.container);\r\n this.render();\r\n }\r\n\r\n private render(): void {\r\n const rules = this.fx.exportRules();\r\n \r\n this.container.innerHTML = `\r\n <div class=\"formfx-editor-header\">\r\n <div class=\"formfx-editor-title\">FormFx Rule Editor</div>\r\n <div class=\"formfx-editor-actions\">\r\n <button class=\"formfx-btn formfx-btn-primary\" id=\"fx-add-rule\">+ Add Rule</button>\r\n </div>\r\n </div>\r\n <div class=\"formfx-editor-body\">\r\n <div class=\"formfx-rule-list\" id=\"fx-rule-list\"></div>\r\n <div class=\"formfx-rule-form\" id=\"fx-rule-form\"></div>\r\n </div>\r\n `;\r\n\r\n this.renderRuleList(rules);\r\n this.renderRuleForm(rules);\r\n\r\n this.container.querySelector('#fx-add-rule')?.addEventListener('click', () => {\r\n this.addRule();\r\n });\r\n }\r\n\r\n private renderRuleList(rules: JSONRule[]): void {\r\n const listEl = this.container.querySelector('#fx-rule-list');\r\n if (!listEl) return;\r\n\r\n listEl.innerHTML = rules.map((rule, index) => `\r\n <div class=\"formfx-rule-item ${this.activeRuleIndex === index ? 'active' : ''}\" data-index=\"${index}\">\r\n <div class=\"formfx-rule-item-id\">${rule.id || '(no id)'}</div>\r\n <div class=\"formfx-rule-item-expr\">if: ${rule.if}</div>\r\n </div>\r\n `).join('') || '<div class=\"formfx-empty-state\">No rules defined</div>';\r\n\r\n listEl.querySelectorAll('.formfx-rule-item').forEach(item => {\r\n item.addEventListener('click', () => {\r\n this.activeRuleIndex = parseInt(item.getAttribute('data-index') || '0');\r\n this.render();\r\n });\r\n });\r\n }\r\n\r\n private renderRuleForm(rules: JSONRule[]): void {\r\n const formEl = this.container.querySelector('#fx-rule-form');\r\n if (!formEl || this.activeRuleIndex === null || !rules[this.activeRuleIndex]) {\r\n if (formEl) formEl.innerHTML = '<div class=\"formfx-empty-state\">Select a rule to edit</div>';\r\n return;\r\n }\r\n\r\n const rule = rules[this.activeRuleIndex];\r\n formEl.innerHTML = `\r\n <div class=\"formfx-field-group\">\r\n <label class=\"formfx-label\">Rule ID</label>\r\n <input type=\"text\" class=\"formfx-input\" id=\"fx-edit-id\" value=\"${rule.id || ''}\">\r\n </div>\r\n <div class=\"formfx-field-group\">\r\n <label class=\"formfx-label\">If Condition (DSL)</label>\r\n <textarea class=\"formfx-textarea\" id=\"fx-edit-if\" rows=\"3\">${rule.if}</textarea>\r\n </div>\r\n \r\n <div class=\"formfx-field-group\">\r\n <label class=\"formfx-label\">Then Effects</label>\r\n <div id=\"fx-then-list\"></div>\r\n <button class=\"formfx-btn\" id=\"fx-add-then\">+ Add Effect</button>\r\n </div>\r\n\r\n <div class=\"formfx-field-group\">\r\n <label class=\"formfx-label\">Else Effects (Optional)</label>\r\n <div id=\"fx-else-list\"></div>\r\n <button class=\"formfx-btn\" id=\"fx-add-else\">+ Add Effect</button>\r\n </div>\r\n\r\n <div style=\"margin-top: 40px; display: flex; justify-content: space-between;\">\r\n <button class=\"formfx-btn formfx-btn-primary\" id=\"fx-save-rule\">Save Changes</button>\r\n <button class=\"formfx-btn formfx-btn-danger\" id=\"fx-delete-rule\">Delete Rule</button>\r\n </div>\r\n\r\n <div class=\"formfx-json-preview\">\r\n <div class=\"formfx-label\">JSON Preview (Readonly)</div>\r\n <div class=\"formfx-json-content\">${JSON.stringify(rule, null, 2)}</div>\r\n </div>\r\n `;\r\n\r\n this.renderEffectList('then', rule.then);\r\n this.renderEffectList('else', rule.else || []);\r\n\r\n // Events\r\n formEl.querySelector('#fx-save-rule')?.addEventListener('click', () => this.saveRule());\r\n formEl.querySelector('#fx-delete-rule')?.addEventListener('click', () => this.deleteRule());\r\n formEl.querySelector('#fx-add-then')?.addEventListener('click', () => this.addEffect('then'));\r\n formEl.querySelector('#fx-add-else')?.addEventListener('click', () => this.addEffect('else'));\r\n }\r\n\r\n private renderEffectList(type: 'then' | 'else', effects: any[]): void {\r\n const listEl = this.container.querySelector(`#fx-${type}-list`);\r\n if (!listEl) return;\r\n\r\n listEl.innerHTML = effects.map((eff, i) => {\r\n const entry = Object.entries(eff)[0] || ['show', ''];\r\n const effectType = entry[0];\r\n const selector = entry[1];\r\n\r\n return `\r\n <div class=\"formfx-effect-row\" data-type=\"${type}\" data-index=\"${i}\">\r\n <select class=\"formfx-select fx-effect-type\" style=\"width: 120px;\">\r\n <option value=\"show\" ${effectType === 'show' ? 'selected' : ''}>show</option>\r\n <option value=\"hide\" ${effectType === 'hide' ? 'selected' : ''}>hide</option>\r\n <option value=\"required\" ${effectType === 'required' ? 'selected' : ''}>require</option>\r\n <option value=\"disabled\" ${effectType === 'disabled' ? 'selected' : ''}>disabled</option>\r\n <option value=\"enable\" ${effectType === 'enable' ? 'selected' : ''}>enable</option>\r\n <option value=\"clear\" ${effectType === 'clear' ? 'selected' : ''}>clear</option>\r\n </select>\r\n <input type=\"text\" class=\"formfx-input fx-effect-selector\" placeholder=\"#id\" value=\"${selector}\">\r\n <button class=\"formfx-btn formfx-btn-danger fx-remove-effect\">×</button>\r\n </div>\r\n `;\r\n }).join('');\r\n\r\n listEl.querySelectorAll('.fx-remove-effect').forEach((btn, i) => {\r\n btn.addEventListener('click', () => {\r\n effects.splice(i, 1);\r\n this.renderRuleForm(this.fx.exportRules());\r\n });\r\n });\r\n }\r\n\r\n private addRule(): void {\r\n const rules = this.fx.exportRules();\r\n const newRule: JSONRule = {\r\n id: `rule_${Date.now()}`,\r\n if: 'true',\r\n then: [{ show: '' }]\r\n };\r\n rules.push(newRule);\r\n this.activeRuleIndex = rules.length - 1;\r\n this.fx.importRules(rules);\r\n this.render();\r\n }\r\n\r\n private saveRule(): void {\r\n if (this.activeRuleIndex === null) return;\r\n \r\n this.fx.pause(); // 編集適用中は pause\r\n\r\n const rules = this.fx.exportRules();\r\n const rule = rules[this.activeRuleIndex];\r\n\r\n rule.id = (this.container.querySelector('#fx-edit-id') as HTMLInputElement).value;\r\n rule.if = (this.container.querySelector('#fx-edit-if') as HTMLTextAreaElement).value;\r\n\r\n const readEffects = (type: 'then' | 'else') => {\r\n const rows = this.container.querySelectorAll(`.formfx-effect-row[data-type=\"${type}\"]`);\r\n const effects: any[] = [];\r\n rows.forEach(row => {\r\n const effectType = (row.querySelector('.fx-effect-type') as HTMLSelectElement).value;\r\n const selector = (row.querySelector('.fx-effect-selector') as HTMLInputElement).value;\r\n const obj: any = {};\r\n obj[effectType] = selector;\r\n effects.push(obj);\r\n });\r\n return effects;\r\n };\r\n\r\n rule.then = readEffects('then');\r\n rule.else = readEffects('else');\r\n if (rule.else.length === 0) delete rule.else;\r\n\r\n this.fx.importRules(rules);\r\n this.fx.resume();\r\n this.render();\r\n }\r\n\r\n private deleteRule(): void {\r\n if (this.activeRuleIndex === null || !confirm('Are you sure you want to delete this rule?')) return;\r\n const rules = this.fx.exportRules();\r\n rules.splice(this.activeRuleIndex, 1);\r\n this.activeRuleIndex = null;\r\n this.fx.importRules(rules);\r\n this.render();\r\n }\r\n\r\n private addEffect(type: 'then' | 'else'): void {\r\n if (this.activeRuleIndex === null) return;\r\n const rules = this.fx.exportRules();\r\n const rule = rules[this.activeRuleIndex];\r\n if (type === 'then') {\r\n rule.then.push({ show: '' });\r\n } else {\r\n rule.else = rule.else || [];\r\n rule.else.push({ show: '' });\r\n }\r\n this.renderRuleForm(rules);\r\n }\r\n}\r\n"]}
@@ -0,0 +1,2 @@
1
+ 'use strict';var chunkGXMPHKTF_cjs=require('./chunk-GXMPHKTF.cjs');Object.defineProperty(exports,"RuleEditor",{enumerable:true,get:function(){return chunkGXMPHKTF_cjs.a}});//# sourceMappingURL=editor.cjs.map
2
+ //# sourceMappingURL=editor.cjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":[],"names":[],"mappings":"","file":"editor.cjs"}