formfx 1.0.0 → 1.0.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -1,62 +0,0 @@
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
@@ -1 +0,0 @@
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"]}
package/dist/editor.cjs DELETED
@@ -1,2 +0,0 @@
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
@@ -1 +0,0 @@
1
- {"version":3,"sources":[],"names":[],"mappings":"","file":"editor.cjs"}
package/dist/editor.d.cts DELETED
@@ -1,141 +0,0 @@
1
- /**
2
- * FormFx Public Types
3
- * v1.0
4
- */
5
- interface FormFxOptions {
6
- /**
7
- * 非表示になったとき、内部の入力値をdisabledにするかどうか
8
- * @default true
9
- */
10
- disableOnHide?: boolean;
11
- /**
12
- * 非表示になったとき、内部の入力値をクリアするかどうか
13
- * @default false
14
- */
15
- clearOnHide?: boolean;
16
- /**
17
- * デバッグモード
18
- * @default false
19
- */
20
- debug?: boolean;
21
- /**
22
- * JSON形式のルール定義
23
- */
24
- rules?: JSONRule[];
25
- /**
26
- * ルールの永続化設定 (v0.4)
27
- */
28
- persist?: PersistOptions;
29
- }
30
- /**
31
- * 永続化オプション (v0.4)
32
- */
33
- interface PersistOptions {
34
- key: string;
35
- storage: 'localStorage' | 'sessionStorage';
36
- }
37
- /**
38
- * Rule Editor 設定 (v0.4)
39
- */
40
- interface RuleEditorOptions {
41
- mount: HTMLElement;
42
- mode: 'json' | 'attributes';
43
- }
44
- type FXValue = string | number | boolean | null | FXValue[];
45
- type EffectType = 'show' | 'hide' | 'required' | 'disabled' | 'enable' | 'clear';
46
- interface JSONEffect {
47
- show?: string;
48
- hide?: string;
49
- require?: string;
50
- required?: string;
51
- disabled?: string;
52
- enable?: string;
53
- clear?: string;
54
- }
55
- interface JSONRule {
56
- id?: string;
57
- if: string;
58
- then: JSONEffect[];
59
- else?: JSONEffect[];
60
- disabled?: boolean;
61
- }
62
- /**
63
- * 外部公開用のデバッグ情報
64
- */
65
- interface FormFxDebugInfo {
66
- ruleId?: string;
67
- type: EffectType;
68
- expression: string;
69
- result: boolean | 'error';
70
- error?: string;
71
- element: HTMLElement;
72
- }
73
-
74
- declare class FormFx {
75
- private formElement;
76
- private rules;
77
- private options;
78
- private cleanupEvents;
79
- private cleanupRepeaters;
80
- private observer;
81
- private debugPanel;
82
- private isPaused;
83
- constructor(formElement: HTMLElement, options?: FormFxOptions);
84
- mount(): void;
85
- reEvaluate(): void;
86
- private setupEvents;
87
- private refreshRules;
88
- private evaluate;
89
- /**
90
- * ルール評価を一時停止する (v0.4)
91
- */
92
- pause(): void;
93
- /**
94
- * ルール評価を再開する (v0.4)
95
- */
96
- resume(): void;
97
- /**
98
- * JSONルールをエクスポートする (v0.4)
99
- */
100
- exportRules(): JSONRule[];
101
- /**
102
- * JSONルールをインポートする (v0.4)
103
- */
104
- importRules(rules: JSONRule[]): void;
105
- /**
106
- * Rule Editor を有効化する (v0.4)
107
- */
108
- enableRuleEditor(options: RuleEditorOptions): Promise<void>;
109
- private loadPersistedRules;
110
- private savePersistedRules;
111
- /**
112
- * JSONルールを有効化する
113
- * @param ruleId
114
- */
115
- enableRule(ruleId: string): void;
116
- /**
117
- * JSONルールを無効化する
118
- * @param ruleId
119
- */
120
- disableRule(ruleId: string): void;
121
- destroy(): void;
122
- }
123
-
124
- declare class RuleEditor {
125
- private fx;
126
- private options;
127
- private container;
128
- private activeRuleIndex;
129
- constructor(fx: FormFx, options: RuleEditorOptions);
130
- mount(): void;
131
- private render;
132
- private renderRuleList;
133
- private renderRuleForm;
134
- private renderEffectList;
135
- private addRule;
136
- private saveRule;
137
- private deleteRule;
138
- private addEffect;
139
- }
140
-
141
- export { type EffectType as E, FormFx as F, type JSONEffect as J, type PersistOptions as P, type RuleEditorOptions as R, RuleEditor, type FormFxOptions as a, type FXValue as b, type JSONRule as c, type FormFxDebugInfo as d };
package/dist/editor.d.ts DELETED
@@ -1,141 +0,0 @@
1
- /**
2
- * FormFx Public Types
3
- * v1.0
4
- */
5
- interface FormFxOptions {
6
- /**
7
- * 非表示になったとき、内部の入力値をdisabledにするかどうか
8
- * @default true
9
- */
10
- disableOnHide?: boolean;
11
- /**
12
- * 非表示になったとき、内部の入力値をクリアするかどうか
13
- * @default false
14
- */
15
- clearOnHide?: boolean;
16
- /**
17
- * デバッグモード
18
- * @default false
19
- */
20
- debug?: boolean;
21
- /**
22
- * JSON形式のルール定義
23
- */
24
- rules?: JSONRule[];
25
- /**
26
- * ルールの永続化設定 (v0.4)
27
- */
28
- persist?: PersistOptions;
29
- }
30
- /**
31
- * 永続化オプション (v0.4)
32
- */
33
- interface PersistOptions {
34
- key: string;
35
- storage: 'localStorage' | 'sessionStorage';
36
- }
37
- /**
38
- * Rule Editor 設定 (v0.4)
39
- */
40
- interface RuleEditorOptions {
41
- mount: HTMLElement;
42
- mode: 'json' | 'attributes';
43
- }
44
- type FXValue = string | number | boolean | null | FXValue[];
45
- type EffectType = 'show' | 'hide' | 'required' | 'disabled' | 'enable' | 'clear';
46
- interface JSONEffect {
47
- show?: string;
48
- hide?: string;
49
- require?: string;
50
- required?: string;
51
- disabled?: string;
52
- enable?: string;
53
- clear?: string;
54
- }
55
- interface JSONRule {
56
- id?: string;
57
- if: string;
58
- then: JSONEffect[];
59
- else?: JSONEffect[];
60
- disabled?: boolean;
61
- }
62
- /**
63
- * 外部公開用のデバッグ情報
64
- */
65
- interface FormFxDebugInfo {
66
- ruleId?: string;
67
- type: EffectType;
68
- expression: string;
69
- result: boolean | 'error';
70
- error?: string;
71
- element: HTMLElement;
72
- }
73
-
74
- declare class FormFx {
75
- private formElement;
76
- private rules;
77
- private options;
78
- private cleanupEvents;
79
- private cleanupRepeaters;
80
- private observer;
81
- private debugPanel;
82
- private isPaused;
83
- constructor(formElement: HTMLElement, options?: FormFxOptions);
84
- mount(): void;
85
- reEvaluate(): void;
86
- private setupEvents;
87
- private refreshRules;
88
- private evaluate;
89
- /**
90
- * ルール評価を一時停止する (v0.4)
91
- */
92
- pause(): void;
93
- /**
94
- * ルール評価を再開する (v0.4)
95
- */
96
- resume(): void;
97
- /**
98
- * JSONルールをエクスポートする (v0.4)
99
- */
100
- exportRules(): JSONRule[];
101
- /**
102
- * JSONルールをインポートする (v0.4)
103
- */
104
- importRules(rules: JSONRule[]): void;
105
- /**
106
- * Rule Editor を有効化する (v0.4)
107
- */
108
- enableRuleEditor(options: RuleEditorOptions): Promise<void>;
109
- private loadPersistedRules;
110
- private savePersistedRules;
111
- /**
112
- * JSONルールを有効化する
113
- * @param ruleId
114
- */
115
- enableRule(ruleId: string): void;
116
- /**
117
- * JSONルールを無効化する
118
- * @param ruleId
119
- */
120
- disableRule(ruleId: string): void;
121
- destroy(): void;
122
- }
123
-
124
- declare class RuleEditor {
125
- private fx;
126
- private options;
127
- private container;
128
- private activeRuleIndex;
129
- constructor(fx: FormFx, options: RuleEditorOptions);
130
- mount(): void;
131
- private render;
132
- private renderRuleList;
133
- private renderRuleForm;
134
- private renderEffectList;
135
- private addRule;
136
- private saveRule;
137
- private deleteRule;
138
- private addEffect;
139
- }
140
-
141
- export { type EffectType as E, FormFx as F, type JSONEffect as J, type PersistOptions as P, type RuleEditorOptions as R, RuleEditor, type FormFxOptions as a, type FXValue as b, type JSONRule as c, type FormFxDebugInfo as d };
package/dist/editor.js DELETED
@@ -1,2 +0,0 @@
1
- export{a as RuleEditor}from'./chunk-6E5EWQVW.js';//# sourceMappingURL=editor.js.map
2
- //# sourceMappingURL=editor.js.map
@@ -1 +0,0 @@
1
- {"version":3,"sources":[],"names":[],"mappings":"","file":"editor.js"}
package/dist/index.cjs DELETED
@@ -1,138 +0,0 @@
1
- 'use strict';var chunkGXMPHKTF_cjs=require('./chunk-GXMPHKTF.cjs');function w(e){if(e instanceof HTMLInputElement){if(e.type==="checkbox")return e.checked;if(e.type==="radio"){if(e.name){let r=(e.closest("form")||document).querySelector(`input[name="${e.name}"]:checked`);return r?r.value:null}return e.checked?e.value:null}return e.type==="number"||e.type==="range"?e.value===""?null:Number(e.value):e.value}return e instanceof HTMLSelectElement||e instanceof HTMLTextAreaElement?e.value:null}function y(e){e instanceof HTMLInputElement?e.type==="checkbox"||e.type==="radio"?e.checked=false:e.value="":e instanceof HTMLSelectElement?(e.selectedIndex=-1,e.value=""):e instanceof HTMLTextAreaElement?e.value="":e.querySelectorAll("input, select, textarea").forEach(r=>y(r));}function E(e,t){"disabled"in e?e.disabled=t:e.querySelectorAll("input, select, textarea").forEach(s=>{s.disabled=t;});}function O(e,t,r){let s=e.style.display!=="none";t?(e.style.display=e.dataset.fxOriginalDisplay||"",r.disableOnHide&&!s&&E(e,false)):(s&&!e.dataset.fxOriginalDisplay&&(e.dataset.fxOriginalDisplay=e.style.display),e.style.display="none",s&&((e.dataset.fxClearOnHide==="true"||r.clearOnHide)&&y(e),r.disableOnHide&&E(e,true)));}function N(e,t){e instanceof HTMLInputElement||e instanceof HTMLSelectElement||e instanceof HTMLTextAreaElement?e.required=t:e.querySelectorAll("input, select, textarea").forEach(s=>{s.required=t;});}function S(e,t){E(e,t);}function H(e){y(e);}function I(e,t){let r=e.querySelector(`#${t.replace(/([#;?%&,.+*~\':"!^$[\]()=>|/@])/g,"\\$1")}`);if(r)return r;let s=e.querySelector(`[name="${t}"]`);return s||e.querySelector(`[data-fx-id="${t}"]`)}function h(e,t){switch(e.type){case "Literal":return e.value;case "Identifier":{if(e.name.startsWith("@row.")){let r=e.name.substring(5);return t.row&&t.row[r]!==void 0?t.row[r]:null}return t.global[e.name]!==void 0?t.global[e.name]:null}case "UnaryExpression":if(e.operator==="!")return !h(e.argument,t);throw new Error(`Unknown unary operator: ${e.operator}`);case "BinaryExpression":{let r=h(e.left,t),s=h(e.right,t);if(e.operator==="==")return r==s;if(e.operator==="!=")return r!=s;if(e.operator===">")return r>s;if(e.operator===">=")return r>=s;if(e.operator==="<")return r<s;if(e.operator==="<=")return r<=s;if(e.operator==="+")return r+s;if(e.operator==="-")return r-s;if(e.operator==="*")return r*s;if(e.operator==="/")return r/s;if(e.operator==="%")return r%s;throw new Error(`Unknown binary operator: ${e.operator}`)}case "LogicalExpression":{let r=h(e.left,t);if(e.operator==="&&")return r&&h(e.right,t);if(e.operator==="||")return r||h(e.right,t);throw new Error(`Unknown logical operator: ${e.operator}`)}case "CallExpression":{let r=t.functions[e.callee];if(!r)throw new Error(`Unknown function: ${e.callee}`);let s=e.arguments.map(i=>h(i,t));return r(...s)}case "ArrayExpression":return e.elements.map(r=>h(r,t));default:throw new Error(`Unknown AST node type: ${e.type}`)}}function R(e){let t=0;function r(){return s()}function s(){let o=i();for(;t<e.length&&e[t].value==="||";){let c=e[t].value;t++;let f=i();o={type:"LogicalExpression",operator:c,left:o,right:f};}return o}function i(){let o=n();for(;t<e.length&&e[t].value==="&&";){let c=e[t].value;t++;let f=n();o={type:"LogicalExpression",operator:c,left:o,right:f};}return o}function n(){let o=u(),c=["==","!=",">",">=","<","<="];for(;t<e.length&&c.includes(e[t].value);){let f=e[t].value;t++;let d=u();o={type:"BinaryExpression",operator:f,left:o,right:d};}return o}function u(){let o=p();for(;t<e.length&&(e[t].value==="+"||e[t].value==="-");){let c=e[t].value;t++;let f=p();o={type:"BinaryExpression",operator:c,left:o,right:f};}return o}function p(){let o=a();for(;t<e.length&&(e[t].value==="*"||e[t].value==="/"||e[t].value==="%");){let c=e[t].value;t++;let f=a();o={type:"BinaryExpression",operator:c,left:o,right:f};}return o}function a(){return t<e.length&&e[t].value==="!"?(t++,{type:"UnaryExpression",operator:"!",argument:a()}):l()}function l(){let o=e[t];if(o.type==="PAREN"&&o.value==="("){t++;let c=r();if(e[t]?.value!==")")throw new Error("Expected )");return t++,c}if(o.type==="IDENTIFIER"){if(t++,t<e.length&&e[t].type==="PAREN"&&e[t].value==="("){t++;let c=[];if(!(e[t].type==="PAREN"&&e[t].value===")"))for(;;){if(c.push(r()),e[t].type==="COMMA"){t++;continue}if(e[t].type==="PAREN"&&e[t].value===")")break;throw new Error(`Expected , or ) in function call "${o.value}"`)}return t++,{type:"CallExpression",callee:o.value,arguments:c}}return {type:"Identifier",name:o.value}}if(o.type==="BRACKET"&&o.value==="["){t++;let c=[];if(!(e[t].type==="BRACKET"&&e[t].value==="]"))for(;;){if(c.push(r()),e[t].type==="COMMA"){t++;continue}if(e[t].type==="BRACKET"&&e[t].value==="]")break;throw new Error("Expected , or ] in array literal")}return t++,{type:"ArrayExpression",elements:c}}if(o.type==="NUMBER")return t++,{type:"Literal",value:parseFloat(o.value)};if(o.type==="STRING")return t++,{type:"Literal",value:o.value};if(o.type==="BOOLEAN")return t++,{type:"Literal",value:o.value==="true"};throw new Error(`Unexpected token: ${o.value}`)}return r()}function A(e){let t=[],r=0;for(;r<e.length;){let s=e[r];if(/\s/.test(s)){r++;continue}if(s==="("||s===")"){t.push({type:"PAREN",value:s}),r++;continue}if(s==="["||s==="]"){t.push({type:"BRACKET",value:s}),r++;continue}if(s===","){t.push({type:"COMMA",value:s}),r++;continue}if(s==="#"||s==="@"){let n=s==="@",u=n?"@":"";if(r++,n){let p="";for(;r<e.length&&/[a-zA-Z0-9_-]/.test(e[r]);)p+=e[r],r++;if(u+=p,e[r]===".")for(u+=".",r++;r<e.length&&/[a-zA-Z0-9_-]/.test(e[r]);)u+=e[r],r++;}else for(;r<e.length&&/[a-zA-Z0-9_-]/.test(e[r]);)u+=e[r],r++;t.push({type:"IDENTIFIER",value:u});continue}if(/[0-9]/.test(s)){let n="";for(;r<e.length&&/[0-9.]/.test(e[r]);)n+=e[r],r++;t.push({type:"NUMBER",value:n});continue}if(s==="'"){let n="";for(r++;r<e.length&&e[r]!=="'";)n+=e[r],r++;r++,t.push({type:"STRING",value:n});continue}if(s==="="&&e[r+1]==="="){t.push({type:"OPERATOR",value:"=="}),r+=2;continue}if(s==="!"&&e[r+1]==="="){t.push({type:"OPERATOR",value:"!="}),r+=2;continue}if(s===">"&&e[r+1]==="="){t.push({type:"OPERATOR",value:">="}),r+=2;continue}if(s==="<"&&e[r+1]==="="){t.push({type:"OPERATOR",value:"<="}),r+=2;continue}if(s===">"){t.push({type:"OPERATOR",value:">"}),r++;continue}if(s==="<"){t.push({type:"OPERATOR",value:"<"}),r++;continue}if(s==="&"&&e[r+1]==="&"){t.push({type:"OPERATOR",value:"&&"}),r+=2;continue}if(s==="|"&&e[r+1]==="|"){t.push({type:"OPERATOR",value:"||"}),r+=2;continue}if(s==="!"){t.push({type:"OPERATOR",value:"!"}),r++;continue}if(s==="+"||s==="-"||s==="*"||s==="/"||s==="%"){t.push({type:"OPERATOR",value:s}),r++;continue}let i=e.slice(r).match(/^[a-zA-Z][a-zA-Z0-9_]*/);if(i){let n=i[0];n==="true"||n==="false"?(t.push({type:"BOOLEAN",value:n}),r+=n.length):(t.push({type:"IDENTIFIER",value:n}),r+=n.length);continue}throw new Error(`Unexpected character: ${s} at position ${r}`)}return t}function F(e,t={}){let r=[];return ["show","required","disabled","enable","clear"].forEach(i=>{let n=`data-fx-${i}`;e.querySelectorAll(`[${n}]`).forEach(p=>{let a=p.getAttribute(n)||"";try{let l=A(a),o=R(l);r.push({element:p,type:i,expression:a,ast:o,source:"attribute"});}catch(l){console.warn(`[FormFx] Failed to parse expression "${a}" for ${n}:`,l);}});}),t.rules&&t.rules.forEach(i=>{try{let n=A(i.if),u=R(n),p=(a,l)=>{a.forEach(o=>{Object.entries(o).forEach(([c,f])=>{if(typeof f!="string"||!f)return;let d=c==="require"?"required":c,g=i.if,m=u;d==="hide"&&(d="show",m={type:"UnaryExpression",operator:"!",argument:u},g=`!(${i.if})`),l&&(m={type:"UnaryExpression",operator:"!",argument:m},g=`!(${g})`),e.querySelectorAll(f).forEach(v=>{let q=v;r.push({id:i.id,element:q,type:d,expression:g,ast:m,source:"json",rawRule:i,disabled:i.disabled});});});});};p(i.then,!1),i.else&&p(i.else,!0);}catch(n){console.warn("[FormFx] Failed to parse JSON rule:",i,n);}}),r}function x(e){let t=new Set,r=new Set;function s(i){i.type==="Identifier"?i.name.startsWith("@row.")?r.add(i.name.substring(5)):t.add(i.name):i.type==="BinaryExpression"||i.type==="LogicalExpression"?(s(i.left),s(i.right)):i.type==="UnaryExpression"?s(i.argument):i.type==="CallExpression"?i.arguments.forEach(s):i.type==="ArrayExpression"&&i.elements.forEach(s);}return s(e),{global:Array.from(t),row:Array.from(r)}}var z={in:(e,t)=>Array.isArray(t)?t.includes(e):false,contains:(e,t)=>typeof e!="string"?false:e.includes(t)};function $(e,t,r){let s=[],i={},n=new Set;t.forEach(a=>{x(a.ast).global.forEach(l=>n.add(l));}),n.forEach(a=>{let l=I(e,a);l?i[a]=w(l):i[a]=null;});let u={global:i,functions:z},p=new Map;return t.forEach(a=>{p.has(a.element)||p.set(a.element,new Map),p.get(a.element).set(a.type,a.source);}),t.forEach(a=>{if(!a.disabled&&!(a.source==="attribute"&&p.get(a.element)?.get(a.type)==="json"))try{let l,o=a.element.closest("[data-fx-item]");o&&(l={},x(a.ast).row.forEach(m=>{let T=o.querySelector(`[data-fx-field="${m}"]`);if(T){let v=T.querySelector("input, select, textarea");l[m]=v?w(v):null;}else l[m]=null;}));let c={...u,row:l},d=!!h(a.ast,c);switch(r.debug&&(s.push({rule:a,result:d,elements:[a.element]}),console.debug(`[FormFx Debug] Rule: ${a.type}="${a.expression}" (source: ${a.source}, result: ${d})`,{element:a.element,result:d,context:c})),a.type){case "show":O(a.element,d,r);break;case "required":N(a.element,d);break;case "disabled":S(a.element,d);break;case "enable":S(a.element,!d);break;case "clear":d&&a.lastResult===!1&&H(a.element);break}a.lastResult=d;}catch(l){let o=l instanceof Error?l.message:String(l);r.debug?(s.push({rule:a,result:"error",error:o,elements:[a.element]}),console.warn(`[FormFx Debug] Evaluation failed: "${a.expression}"`,l)):console.warn(`[FormFx] Failed to evaluate expression "${a.expression}":`,l);}}),s}function P(e,t,r){let s=()=>{t();};return e.addEventListener("input",s),e.addEventListener("change",s),()=>{e.removeEventListener("input",s),e.removeEventListener("change",s);}}function C(e,t){let r=new MutationObserver(s=>{let i=false;for(let n of s)if(n.type==="childList"&&(n.addedNodes.length>0||n.removedNodes.length>0)){i=true;break}i&&t();});return r.observe(e,{childList:true,subtree:true}),r}function D(e,t){let r=e.querySelectorAll("[data-fx-repeater]"),s=[];return r.forEach(i=>{let n={name:i.getAttribute("data-fx-name")||"",max:parseInt(i.getAttribute("data-fx-max")||"10",10),addButton:i.querySelector("[data-fx-add]"),listContainer:i.querySelector("[data-fx-list]")||i,template:i.querySelector("template[data-fx-template]")};if(!n.template){console.warn("[FormFx] Repeater template not found",i);return}let u=()=>{n.listContainer.querySelectorAll("[data-fx-item]").length<n.max&&(k(n),L(n),t());};n.addButton&&(n.addButton.addEventListener("click",u),s.push(()=>n.addButton?.removeEventListener("click",u)));let p=a=>{let l=a.target;if(l.closest("[data-fx-remove]")){let o=l.closest("[data-fx-item]");o&&(o.remove(),L(n),t());}};n.listContainer.addEventListener("click",p),s.push(()=>n.listContainer.removeEventListener("click",p)),L(n);}),()=>s.forEach(i=>i())}function k(e){let r=e.template.content.cloneNode(true).querySelector("[data-fx-item]");r&&e.listContainer.appendChild(r);}function L(e){let t=e.listContainer.querySelectorAll("[data-fx-item]");t.forEach((r,s)=>{r.setAttribute("data-fx-index",s.toString()),r.querySelectorAll("[data-fx-field]").forEach(n=>{let u=n.getAttribute("data-fx-field");u&&n.querySelectorAll("input, select, textarea").forEach(a=>{a.name=`${e.name}[${s}].${u}`;});});}),e.addButton&&(t.length>=e.max?e.addButton.style.display="none":e.addButton.style.display="");}var b=class{container=null;shadow=null;persistInfo=null;isMinimized=false;pos={x:10,y:10};isDragging=false;dragStart={x:0,y:0};constructor(){this.loadState(),this.container=document.createElement("div"),this.container.id="formfx-debug-panel",this.shadow=this.container.attachShadow({mode:"open"}),this.renderInitial(),document.body.appendChild(this.container),this.setupDragging();}loadState(){try{let t=localStorage.getItem("formfx-debug-state");if(t){let r=JSON.parse(t);this.isMinimized=!!r.isMinimized,r.pos&&(this.pos=r.pos);}}catch{}}saveState(){try{localStorage.setItem("formfx-debug-state",JSON.stringify({isMinimized:this.isMinimized,pos:this.pos}));}catch{}}setupDragging(){if(!this.shadow||!this.container)return;let t=this.shadow.querySelector(".header");if(!t)return;t.style.cursor="move",t.addEventListener("mousedown",s=>{this.isDragging=true,this.dragStart={x:s.clientX+this.pos.x,y:s.clientY+this.pos.y},s.preventDefault();}),window.addEventListener("mousemove",s=>{this.isDragging&&(this.pos.x=this.dragStart.x-s.clientX,this.pos.y=this.dragStart.y-s.clientY,this.updatePosition());}),window.addEventListener("mouseup",()=>{this.isDragging&&(this.isDragging=false,this.saveState());}),this.shadow.getElementById("toggle-minimize")?.addEventListener("click",s=>{s.stopPropagation(),this.isMinimized=!this.isMinimized,this.renderInitial(),this.updatePosition(),this.saveState();});}updatePosition(){this.container&&(this.container.style.bottom=`${this.pos.y}px`,this.container.style.right=`${this.pos.x}px`);}setPersistInfo(t){this.persistInfo=t;}renderInitial(){this.shadow&&(this.shadow.innerHTML=`
2
- <style>
3
- :host {
4
- position: fixed;
5
- bottom: ${this.pos.y}px;
6
- right: ${this.pos.x}px;
7
- width: 350px;
8
- max-height: 80vh;
9
- background: rgba(0, 0, 0, 0.85);
10
- color: white;
11
- font-family: monospace;
12
- font-size: 12px;
13
- border-radius: 8px;
14
- overflow: hidden;
15
- z-index: 10000;
16
- box-shadow: 0 4px 12px rgba(0,0,0,0.3);
17
- border: 1px solid #444;
18
- display: flex;
19
- flex-direction: column;
20
- }
21
- .header {
22
- padding: 8px 12px;
23
- background: #222;
24
- border-bottom: 1px solid #444;
25
- font-weight: bold;
26
- display: flex;
27
- justify-content: space-between;
28
- align-items: center;
29
- user-select: none;
30
- }
31
- .content {
32
- padding: 8px;
33
- overflow-y: auto;
34
- display: ${this.isMinimized?"none":"block"};
35
- }
36
- .header-controls {
37
- display: flex;
38
- gap: 8px;
39
- }
40
- .btn-icon {
41
- cursor: pointer;
42
- padding: 2px 6px;
43
- border-radius: 4px;
44
- background: #444;
45
- border: none;
46
- color: white;
47
- font-size: 10px;
48
- }
49
- .btn-icon:hover {
50
- background: #666;
51
- }
52
- .rule {
53
- margin-bottom: 8px;
54
- padding: 6px;
55
- border-radius: 4px;
56
- background: #333;
57
- }
58
- .rule-header {
59
- display: flex;
60
- justify-content: space-between;
61
- margin-bottom: 4px;
62
- }
63
- .rule-id {
64
- color: #aaa;
65
- font-size: 10px;
66
- }
67
- .rule-expr {
68
- word-break: break-all;
69
- color: #88ccff;
70
- }
71
- .status {
72
- font-weight: bold;
73
- padding: 2px 4px;
74
- border-radius: 2px;
75
- font-size: 10px;
76
- }
77
- .status-true { background: #228b22; }
78
- .status-false { background: #b22222; }
79
- .status-error { background: #ff4500; }
80
- .status-disabled { background: #666; color: #ccc; }
81
- .persist-badge {
82
- font-size: 9px;
83
- background: #444;
84
- padding: 1px 4px;
85
- border-radius: 4px;
86
- color: #00ff00;
87
- border: 1px solid #00ff00;
88
- }
89
- .header-top {
90
- display: flex;
91
- align-items: center;
92
- gap: 8px;
93
- }
94
- .effects {
95
- margin-top: 4px;
96
- padding-left: 12px;
97
- border-left: 2px solid #555;
98
- font-size: 11px;
99
- }
100
- .effect-item {
101
- margin-top: 2px;
102
- }
103
- .effect-skipped {
104
- color: #888;
105
- text-decoration: line-through;
106
- }
107
- .error-msg {
108
- color: #ff6347;
109
- font-size: 10px;
110
- margin-top: 4px;
111
- }
112
- </style>
113
- <div class="header">
114
- <div class="header-top">
115
- <span>FormFx Debug</span>
116
- ${this.persistInfo?'<span class="persist-badge">PERSIST</span>':""}
117
- </div>
118
- <div class="header-controls">
119
- <button id="toggle-minimize" class="btn-icon">${this.isMinimized?"\u25A1":"_"} </button>
120
- </div>
121
- </div>
122
- <div id="rule-list" class="content">
123
- Waiting for evaluation...
124
- </div>
125
- `,this.setupDragging());}update(t){if(!this.shadow)return;let r=this.shadow.getElementById("rule-list");r&&(r.innerHTML=t.map(s=>{let{rule:i,result:n,error:u}=s,p=n==="error"?"status-error":n?"status-true":"status-false",a=n==="error"?"ERROR":n.toString().toUpperCase();i.disabled&&(p="status-disabled",a="DISABLED");let l=`${i.type} ${this.getSelector(i.element)}`;return n!==true&&n!=="error"&&!i.disabled&&(l=`<span class="effect-skipped">${l} (skipped)</span>`),i.disabled&&(l=`<span class="effect-skipped">${l}</span>`),`
126
- <div class="rule">
127
- <div class="rule-header">
128
- <span class="rule-id">${i.id||(i.source==="attribute"?"Attr":"JSON")}</span>
129
- <span class="status ${p}">${a}</span>
130
- </div>
131
- <div class="rule-expr">${i.expression}</div>
132
- <div class="effects">
133
- <div class="effect-item">${l}</div>
134
- </div>
135
- ${u?`<div class="error-msg">Error: ${u}</div>`:""}
136
- </div>
137
- `}).join(""));}getSelector(t){return t.id?`#${t.id}`:t.className?`.${t.className.split(" ").join(".")}`:t.tagName.toLowerCase()}destroy(){this.container&&this.container.parentNode&&this.container.parentNode.removeChild(this.container);}};var M=class{constructor(t,r={}){this.formElement=t;this.options={disableOnHide:true,clearOnHide:false,...r},this.loadPersistedRules();}rules=[];options;cleanupEvents=null;cleanupRepeaters=null;observer=null;debugPanel=null;isPaused=false;mount(){this.options.debug&&(this.debugPanel=new b,this.options.persist&&this.debugPanel.setPersistInfo(this.options.persist)),this.refreshRules(),this.cleanupRepeaters=D(this.formElement,()=>{this.refreshRules(),this.setupEvents(),this.evaluate();}),this.setupEvents(),this.observer=C(this.formElement,()=>{this.refreshRules(),this.setupEvents(),this.evaluate();}),this.evaluate();}reEvaluate(){this.evaluate();}setupEvents(){this.cleanupEvents&&this.cleanupEvents();let t=new Set;this.rules.forEach(r=>{x(r.ast).global.forEach(s=>{t.add(s);});}),this.cleanupEvents=P(this.formElement,()=>{this.evaluate();},Array.from(t));}refreshRules(){this.rules=F(this.formElement,this.options);}evaluate(){if(this.isPaused)return;let t=$(this.formElement,this.rules,this.options);this.debugPanel&&this.debugPanel.update(t);}pause(){this.isPaused=true;}resume(){this.isPaused=false,this.evaluate();}exportRules(){return this.options.rules||[]}importRules(t){this.options.rules=t,this.savePersistedRules(),this.refreshRules(),this.setupEvents(),this.evaluate();}async enableRuleEditor(t){let{RuleEditor:r}=await import('./editor.cjs');new r(this,t).mount();}loadPersistedRules(){let{persist:t}=this.options;if(t)try{let s=(t.storage==="localStorage"?localStorage:sessionStorage).getItem(t.key);s&&(this.options.rules=JSON.parse(s));}catch(r){console.error("[FormFx] Failed to load persisted rules:",r);}}savePersistedRules(){let{persist:t,rules:r}=this.options;if(!(!t||!r))try{(t.storage==="localStorage"?localStorage:sessionStorage).setItem(t.key,JSON.stringify(r));}catch(s){console.error("[FormFx] Failed to save rules:",s);}}enableRule(t){this.rules.forEach(r=>{r.id===t&&r.source==="json"&&(r.disabled=false);}),this.options.rules&&(this.options.rules.forEach(r=>{r.id===t&&(r.disabled=false);}),this.savePersistedRules()),this.evaluate();}disableRule(t){this.rules.forEach(r=>{r.id===t&&r.source==="json"&&(r.disabled=true);}),this.options.rules&&(this.options.rules.forEach(r=>{r.id===t&&(r.disabled=true);}),this.savePersistedRules()),this.evaluate();}destroy(){this.cleanupEvents&&this.cleanupEvents(),this.cleanupRepeaters&&this.cleanupRepeaters(),this.observer&&this.observer.disconnect(),this.debugPanel&&this.debugPanel.destroy(),this.cleanupEvents=null,this.cleanupRepeaters=null,this.observer=null,this.debugPanel=null,this.rules=[];}};Object.defineProperty(exports,"RuleEditor",{enumerable:true,get:function(){return chunkGXMPHKTF_cjs.a}});exports.FormFx=M;//# sourceMappingURL=index.cjs.map
138
- //# sourceMappingURL=index.cjs.map