formfx 1.0.0 → 1.0.1

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.
@@ -0,0 +1,62 @@
1
+ var FormFx=(function(exports){'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.RuleEditor=f;return exports;})({});//# sourceMappingURL=editor.global.js.map
62
+ //# sourceMappingURL=editor.global.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":"editor.global.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,198 @@
1
+ var FormFx=(function(exports){'use strict';var J=Object.defineProperty;var U=(t,e)=>()=>(t&&(e=t(t=0)),e);var V=(t,e)=>{for(var r in e)J(t,r,{get:e[r],enumerable:true});};var B={};V(B,{RuleEditor:()=>exports.RuleEditor});exports.RuleEditor=void 0;var O=U(()=>{exports.RuleEditor=class{constructor(e,r){this.fx=e;this.options=r;this.container=document.createElement("div"),this.container.className="formfx-editor";}container;activeRuleIndex=null;mount(){this.options.mount.appendChild(this.container),this.render();}render(){let e=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(e),this.renderRuleForm(e),this.container.querySelector("#fx-add-rule")?.addEventListener("click",()=>{this.addRule();});}renderRuleList(e){let r=this.container.querySelector("#fx-rule-list");r&&(r.innerHTML=e.map((s,i)=>`
13
+ <div class="formfx-rule-item ${this.activeRuleIndex===i?"active":""}" data-index="${i}">
14
+ <div class="formfx-rule-item-id">${s.id||"(no id)"}</div>
15
+ <div class="formfx-rule-item-expr">if: ${s.if}</div>
16
+ </div>
17
+ `).join("")||'<div class="formfx-empty-state">No rules defined</div>',r.querySelectorAll(".formfx-rule-item").forEach(s=>{s.addEventListener("click",()=>{this.activeRuleIndex=parseInt(s.getAttribute("data-index")||"0"),this.render();});}));}renderRuleForm(e){let r=this.container.querySelector("#fx-rule-form");if(!r||this.activeRuleIndex===null||!e[this.activeRuleIndex]){r&&(r.innerHTML='<div class="formfx-empty-state">Select a rule to edit</div>');return}let s=e[this.activeRuleIndex];r.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="${s.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">${s.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(s,null,2)}</div>
47
+ </div>
48
+ `,this.renderEffectList("then",s.then),this.renderEffectList("else",s.else||[]),r.querySelector("#fx-save-rule")?.addEventListener("click",()=>this.saveRule()),r.querySelector("#fx-delete-rule")?.addEventListener("click",()=>this.deleteRule()),r.querySelector("#fx-add-then")?.addEventListener("click",()=>this.addEffect("then")),r.querySelector("#fx-add-else")?.addEventListener("click",()=>this.addEffect("else"));}renderEffectList(e,r){let s=this.container.querySelector(`#fx-${e}-list`);s&&(s.innerHTML=r.map((i,n)=>{let c=Object.entries(i)[0]||["show",""],u=c[0],a=c[1];return `
49
+ <div class="formfx-effect-row" data-type="${e}" data-index="${n}">
50
+ <select class="formfx-select fx-effect-type" style="width: 120px;">
51
+ <option value="show" ${u==="show"?"selected":""}>show</option>
52
+ <option value="hide" ${u==="hide"?"selected":""}>hide</option>
53
+ <option value="required" ${u==="required"?"selected":""}>require</option>
54
+ <option value="disabled" ${u==="disabled"?"selected":""}>disabled</option>
55
+ <option value="enable" ${u==="enable"?"selected":""}>enable</option>
56
+ <option value="clear" ${u==="clear"?"selected":""}>clear</option>
57
+ </select>
58
+ <input type="text" class="formfx-input fx-effect-selector" placeholder="#id" value="${a}">
59
+ <button class="formfx-btn formfx-btn-danger fx-remove-effect">\xD7</button>
60
+ </div>
61
+ `}).join(""),s.querySelectorAll(".fx-remove-effect").forEach((i,n)=>{i.addEventListener("click",()=>{r.splice(n,1),this.renderRuleForm(this.fx.exportRules());});}));}addRule(){let e=this.fx.exportRules(),r={id:`rule_${Date.now()}`,if:"true",then:[{show:""}]};e.push(r),this.activeRuleIndex=e.length-1,this.fx.importRules(e),this.render();}saveRule(){if(this.activeRuleIndex===null)return;this.fx.pause();let e=this.fx.exportRules(),r=e[this.activeRuleIndex];r.id=this.container.querySelector("#fx-edit-id").value,r.if=this.container.querySelector("#fx-edit-if").value;let s=i=>{let n=this.container.querySelectorAll(`.formfx-effect-row[data-type="${i}"]`),c=[];return n.forEach(u=>{let a=u.querySelector(".fx-effect-type").value,l=u.querySelector(".fx-effect-selector").value,o={};o[a]=l,c.push(o);}),c};r.then=s("then"),r.else=s("else"),r.else.length===0&&delete r.else,this.fx.importRules(e),this.fx.resume(),this.render();}deleteRule(){if(this.activeRuleIndex===null||!confirm("Are you sure you want to delete this rule?"))return;let e=this.fx.exportRules();e.splice(this.activeRuleIndex,1),this.activeRuleIndex=null,this.fx.importRules(e),this.render();}addEffect(e){if(this.activeRuleIndex===null)return;let r=this.fx.exportRules(),s=r[this.activeRuleIndex];e==="then"?s.then.push({show:""}):(s.else=s.else||[],s.else.push({show:""})),this.renderRuleForm(r);}};});function w(t){if(t instanceof HTMLInputElement){if(t.type==="checkbox")return t.checked;if(t.type==="radio"){if(t.name){let r=(t.closest("form")||document).querySelector(`input[name="${t.name}"]:checked`);return r?r.value:null}return t.checked?t.value:null}return t.type==="number"||t.type==="range"?t.value===""?null:Number(t.value):t.value}return t instanceof HTMLSelectElement||t instanceof HTMLTextAreaElement?t.value:null}function y(t){t instanceof HTMLInputElement?t.type==="checkbox"||t.type==="radio"?t.checked=false:t.value="":t instanceof HTMLSelectElement?(t.selectedIndex=-1,t.value=""):t instanceof HTMLTextAreaElement?t.value="":t.querySelectorAll("input, select, textarea").forEach(r=>y(r));}function g(t,e){"disabled"in t?t.disabled=e:t.querySelectorAll("input, select, textarea").forEach(s=>{s.disabled=e;});}function $(t,e,r){let s=t.style.display!=="none";e?(t.style.display=t.dataset.fxOriginalDisplay||"",r.disableOnHide&&!s&&g(t,false)):(s&&!t.dataset.fxOriginalDisplay&&(t.dataset.fxOriginalDisplay=t.style.display),t.style.display="none",s&&((t.dataset.fxClearOnHide==="true"||r.clearOnHide)&&y(t),r.disableOnHide&&g(t,true)));}function H(t,e){t instanceof HTMLInputElement||t instanceof HTMLSelectElement||t instanceof HTMLTextAreaElement?t.required=e:t.querySelectorAll("input, select, textarea").forEach(s=>{s.required=e;});}function S(t,e){g(t,e);}function N(t){y(t);}function F(t,e){let r=t.querySelector(`#${e.replace(/([#;?%&,.+*~\':"!^$[\]()=>|/@])/g,"\\$1")}`);if(r)return r;let s=t.querySelector(`[name="${e}"]`);return s||t.querySelector(`[data-fx-id="${e}"]`)}function h(t,e){switch(t.type){case "Literal":return t.value;case "Identifier":{if(t.name.startsWith("@row.")){let r=t.name.substring(5);return e.row&&e.row[r]!==void 0?e.row[r]:null}return e.global[t.name]!==void 0?e.global[t.name]:null}case "UnaryExpression":if(t.operator==="!")return !h(t.argument,e);throw new Error(`Unknown unary operator: ${t.operator}`);case "BinaryExpression":{let r=h(t.left,e),s=h(t.right,e);if(t.operator==="==")return r==s;if(t.operator==="!=")return r!=s;if(t.operator===">")return r>s;if(t.operator===">=")return r>=s;if(t.operator==="<")return r<s;if(t.operator==="<=")return r<=s;if(t.operator==="+")return r+s;if(t.operator==="-")return r-s;if(t.operator==="*")return r*s;if(t.operator==="/")return r/s;if(t.operator==="%")return r%s;throw new Error(`Unknown binary operator: ${t.operator}`)}case "LogicalExpression":{let r=h(t.left,e);if(t.operator==="&&")return r&&h(t.right,e);if(t.operator==="||")return r||h(t.right,e);throw new Error(`Unknown logical operator: ${t.operator}`)}case "CallExpression":{let r=e.functions[t.callee];if(!r)throw new Error(`Unknown function: ${t.callee}`);let s=t.arguments.map(i=>h(i,e));return r(...s)}case "ArrayExpression":return t.elements.map(r=>h(r,e));default:throw new Error(`Unknown AST node type: ${t.type}`)}}function L(t){let e=0;function r(){return s()}function s(){let o=i();for(;e<t.length&&t[e].value==="||";){let d=t[e].value;e++;let p=i();o={type:"LogicalExpression",operator:d,left:o,right:p};}return o}function i(){let o=n();for(;e<t.length&&t[e].value==="&&";){let d=t[e].value;e++;let p=n();o={type:"LogicalExpression",operator:d,left:o,right:p};}return o}function n(){let o=c(),d=["==","!=",">",">=","<","<="];for(;e<t.length&&d.includes(t[e].value);){let p=t[e].value;e++;let f=c();o={type:"BinaryExpression",operator:p,left:o,right:f};}return o}function c(){let o=u();for(;e<t.length&&(t[e].value==="+"||t[e].value==="-");){let d=t[e].value;e++;let p=u();o={type:"BinaryExpression",operator:d,left:o,right:p};}return o}function u(){let o=a();for(;e<t.length&&(t[e].value==="*"||t[e].value==="/"||t[e].value==="%");){let d=t[e].value;e++;let p=a();o={type:"BinaryExpression",operator:d,left:o,right:p};}return o}function a(){return e<t.length&&t[e].value==="!"?(e++,{type:"UnaryExpression",operator:"!",argument:a()}):l()}function l(){let o=t[e];if(o.type==="PAREN"&&o.value==="("){e++;let d=r();if(t[e]?.value!==")")throw new Error("Expected )");return e++,d}if(o.type==="IDENTIFIER"){if(e++,e<t.length&&t[e].type==="PAREN"&&t[e].value==="("){e++;let d=[];if(!(t[e].type==="PAREN"&&t[e].value===")"))for(;;){if(d.push(r()),t[e].type==="COMMA"){e++;continue}if(t[e].type==="PAREN"&&t[e].value===")")break;throw new Error(`Expected , or ) in function call "${o.value}"`)}return e++,{type:"CallExpression",callee:o.value,arguments:d}}return {type:"Identifier",name:o.value}}if(o.type==="BRACKET"&&o.value==="["){e++;let d=[];if(!(t[e].type==="BRACKET"&&t[e].value==="]"))for(;;){if(d.push(r()),t[e].type==="COMMA"){e++;continue}if(t[e].type==="BRACKET"&&t[e].value==="]")break;throw new Error("Expected , or ] in array literal")}return e++,{type:"ArrayExpression",elements:d}}if(o.type==="NUMBER")return e++,{type:"Literal",value:parseFloat(o.value)};if(o.type==="STRING")return e++,{type:"Literal",value:o.value};if(o.type==="BOOLEAN")return e++,{type:"Literal",value:o.value==="true"};throw new Error(`Unexpected token: ${o.value}`)}return r()}function A(t){let e=[],r=0;for(;r<t.length;){let s=t[r];if(/\s/.test(s)){r++;continue}if(s==="("||s===")"){e.push({type:"PAREN",value:s}),r++;continue}if(s==="["||s==="]"){e.push({type:"BRACKET",value:s}),r++;continue}if(s===","){e.push({type:"COMMA",value:s}),r++;continue}if(s==="#"||s==="@"){let n=s==="@",c=n?"@":"";if(r++,n){let u="";for(;r<t.length&&/[a-zA-Z0-9_-]/.test(t[r]);)u+=t[r],r++;if(c+=u,t[r]===".")for(c+=".",r++;r<t.length&&/[a-zA-Z0-9_-]/.test(t[r]);)c+=t[r],r++;}else for(;r<t.length&&/[a-zA-Z0-9_-]/.test(t[r]);)c+=t[r],r++;e.push({type:"IDENTIFIER",value:c});continue}if(/[0-9]/.test(s)){let n="";for(;r<t.length&&/[0-9.]/.test(t[r]);)n+=t[r],r++;e.push({type:"NUMBER",value:n});continue}if(s==="'"){let n="";for(r++;r<t.length&&t[r]!=="'";)n+=t[r],r++;r++,e.push({type:"STRING",value:n});continue}if(s==="="&&t[r+1]==="="){e.push({type:"OPERATOR",value:"=="}),r+=2;continue}if(s==="!"&&t[r+1]==="="){e.push({type:"OPERATOR",value:"!="}),r+=2;continue}if(s===">"&&t[r+1]==="="){e.push({type:"OPERATOR",value:">="}),r+=2;continue}if(s==="<"&&t[r+1]==="="){e.push({type:"OPERATOR",value:"<="}),r+=2;continue}if(s===">"){e.push({type:"OPERATOR",value:">"}),r++;continue}if(s==="<"){e.push({type:"OPERATOR",value:"<"}),r++;continue}if(s==="&"&&t[r+1]==="&"){e.push({type:"OPERATOR",value:"&&"}),r+=2;continue}if(s==="|"&&t[r+1]==="|"){e.push({type:"OPERATOR",value:"||"}),r+=2;continue}if(s==="!"){e.push({type:"OPERATOR",value:"!"}),r++;continue}if(s==="+"||s==="-"||s==="*"||s==="/"||s==="%"){e.push({type:"OPERATOR",value:s}),r++;continue}let i=t.slice(r).match(/^[a-zA-Z][a-zA-Z0-9_]*/);if(i){let n=i[0];n==="true"||n==="false"?(e.push({type:"BOOLEAN",value:n}),r+=n.length):(e.push({type:"IDENTIFIER",value:n}),r+=n.length);continue}throw new Error(`Unexpected character: ${s} at position ${r}`)}return e}function P(t,e={}){let r=[];return ["show","required","disabled","enable","clear"].forEach(i=>{let n=`data-fx-${i}`;t.querySelectorAll(`[${n}]`).forEach(u=>{let a=u.getAttribute(n)||"";try{let l=A(a),o=L(l);r.push({element:u,type:i,expression:a,ast:o,source:"attribute"});}catch(l){console.warn(`[FormFx] Failed to parse expression "${a}" for ${n}:`,l);}});}),e.rules&&e.rules.forEach(i=>{try{let n=A(i.if),c=L(n),u=(a,l)=>{a.forEach(o=>{Object.entries(o).forEach(([d,p])=>{if(typeof p!="string"||!p)return;let f=d==="require"?"required":d,v=i.if,m=c;f==="hide"&&(f="show",m={type:"UnaryExpression",operator:"!",argument:c},v=`!(${i.if})`),l&&(m={type:"UnaryExpression",operator:"!",argument:m},v=`!(${v})`),t.querySelectorAll(p).forEach(x=>{let z=x;r.push({id:i.id,element:z,type:f,expression:v,ast:m,source:"json",rawRule:i,disabled:i.disabled});});});});};u(i.then,!1),i.else&&u(i.else,!0);}catch(n){console.warn("[FormFx] Failed to parse JSON rule:",i,n);}}),r}function E(t){let e=new Set,r=new Set;function s(i){i.type==="Identifier"?i.name.startsWith("@row.")?r.add(i.name.substring(5)):e.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(t),{global:Array.from(e),row:Array.from(r)}}var X={in:(t,e)=>Array.isArray(e)?e.includes(t):false,contains:(t,e)=>typeof t!="string"?false:t.includes(e)};function q(t,e,r){let s=[],i={},n=new Set;e.forEach(a=>{E(a.ast).global.forEach(l=>n.add(l));}),n.forEach(a=>{let l=F(t,a);l?i[a]=w(l):i[a]=null;});let c={global:i,functions:X},u=new Map;return e.forEach(a=>{u.has(a.element)||u.set(a.element,new Map),u.get(a.element).set(a.type,a.source);}),e.forEach(a=>{if(!a.disabled&&!(a.source==="attribute"&&u.get(a.element)?.get(a.type)==="json"))try{let l,o=a.element.closest("[data-fx-item]");o&&(l={},E(a.ast).row.forEach(m=>{let T=o.querySelector(`[data-fx-field="${m}"]`);if(T){let x=T.querySelector("input, select, textarea");l[m]=x?w(x):null;}else l[m]=null;}));let d={...c,row:l},f=!!h(a.ast,d);switch(r.debug&&(s.push({rule:a,result:f,elements:[a.element]}),console.debug(`[FormFx Debug] Rule: ${a.type}="${a.expression}" (source: ${a.source}, result: ${f})`,{element:a.element,result:f,context:d})),a.type){case "show":$(a.element,f,r);break;case "required":H(a.element,f);break;case "disabled":S(a.element,f);break;case "enable":S(a.element,!f);break;case "clear":f&&a.lastResult===!1&&N(a.element);break}a.lastResult=f;}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 C(t,e,r){let s=()=>{e();};return t.addEventListener("input",s),t.addEventListener("change",s),()=>{t.removeEventListener("input",s),t.removeEventListener("change",s);}}function D(t,e){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&&e();});return r.observe(t,{childList:true,subtree:true}),r}function k(t,e){let r=t.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 c=()=>{n.listContainer.querySelectorAll("[data-fx-item]").length<n.max&&(j(n),M(n),e());};n.addButton&&(n.addButton.addEventListener("click",c),s.push(()=>n.addButton?.removeEventListener("click",c)));let u=a=>{let l=a.target;if(l.closest("[data-fx-remove]")){let o=l.closest("[data-fx-item]");o&&(o.remove(),M(n),e());}};n.listContainer.addEventListener("click",u),s.push(()=>n.listContainer.removeEventListener("click",u)),M(n);}),()=>s.forEach(i=>i())}function j(t){let r=t.template.content.cloneNode(true).querySelector("[data-fx-item]");r&&t.listContainer.appendChild(r);}function M(t){let e=t.listContainer.querySelectorAll("[data-fx-item]");e.forEach((r,s)=>{r.setAttribute("data-fx-index",s.toString()),r.querySelectorAll("[data-fx-field]").forEach(n=>{let c=n.getAttribute("data-fx-field");c&&n.querySelectorAll("input, select, textarea").forEach(a=>{a.name=`${t.name}[${s}].${c}`;});});}),t.addButton&&(e.length>=t.max?t.addButton.style.display="none":t.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 e=localStorage.getItem("formfx-debug-state");if(e){let r=JSON.parse(e);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 e=this.shadow.querySelector(".header");if(!e)return;e.style.cursor="move",e.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(e){this.persistInfo=e;}renderInitial(){this.shadow&&(this.shadow.innerHTML=`
62
+ <style>
63
+ :host {
64
+ position: fixed;
65
+ bottom: ${this.pos.y}px;
66
+ right: ${this.pos.x}px;
67
+ width: 350px;
68
+ max-height: 80vh;
69
+ background: rgba(0, 0, 0, 0.85);
70
+ color: white;
71
+ font-family: monospace;
72
+ font-size: 12px;
73
+ border-radius: 8px;
74
+ overflow: hidden;
75
+ z-index: 10000;
76
+ box-shadow: 0 4px 12px rgba(0,0,0,0.3);
77
+ border: 1px solid #444;
78
+ display: flex;
79
+ flex-direction: column;
80
+ }
81
+ .header {
82
+ padding: 8px 12px;
83
+ background: #222;
84
+ border-bottom: 1px solid #444;
85
+ font-weight: bold;
86
+ display: flex;
87
+ justify-content: space-between;
88
+ align-items: center;
89
+ user-select: none;
90
+ }
91
+ .content {
92
+ padding: 8px;
93
+ overflow-y: auto;
94
+ display: ${this.isMinimized?"none":"block"};
95
+ }
96
+ .header-controls {
97
+ display: flex;
98
+ gap: 8px;
99
+ }
100
+ .btn-icon {
101
+ cursor: pointer;
102
+ padding: 2px 6px;
103
+ border-radius: 4px;
104
+ background: #444;
105
+ border: none;
106
+ color: white;
107
+ font-size: 10px;
108
+ }
109
+ .btn-icon:hover {
110
+ background: #666;
111
+ }
112
+ .rule {
113
+ margin-bottom: 8px;
114
+ padding: 6px;
115
+ border-radius: 4px;
116
+ background: #333;
117
+ }
118
+ .rule-header {
119
+ display: flex;
120
+ justify-content: space-between;
121
+ margin-bottom: 4px;
122
+ }
123
+ .rule-id {
124
+ color: #aaa;
125
+ font-size: 10px;
126
+ }
127
+ .rule-expr {
128
+ word-break: break-all;
129
+ color: #88ccff;
130
+ }
131
+ .status {
132
+ font-weight: bold;
133
+ padding: 2px 4px;
134
+ border-radius: 2px;
135
+ font-size: 10px;
136
+ }
137
+ .status-true { background: #228b22; }
138
+ .status-false { background: #b22222; }
139
+ .status-error { background: #ff4500; }
140
+ .status-disabled { background: #666; color: #ccc; }
141
+ .persist-badge {
142
+ font-size: 9px;
143
+ background: #444;
144
+ padding: 1px 4px;
145
+ border-radius: 4px;
146
+ color: #00ff00;
147
+ border: 1px solid #00ff00;
148
+ }
149
+ .header-top {
150
+ display: flex;
151
+ align-items: center;
152
+ gap: 8px;
153
+ }
154
+ .effects {
155
+ margin-top: 4px;
156
+ padding-left: 12px;
157
+ border-left: 2px solid #555;
158
+ font-size: 11px;
159
+ }
160
+ .effect-item {
161
+ margin-top: 2px;
162
+ }
163
+ .effect-skipped {
164
+ color: #888;
165
+ text-decoration: line-through;
166
+ }
167
+ .error-msg {
168
+ color: #ff6347;
169
+ font-size: 10px;
170
+ margin-top: 4px;
171
+ }
172
+ </style>
173
+ <div class="header">
174
+ <div class="header-top">
175
+ <span>FormFx Debug</span>
176
+ ${this.persistInfo?'<span class="persist-badge">PERSIST</span>':""}
177
+ </div>
178
+ <div class="header-controls">
179
+ <button id="toggle-minimize" class="btn-icon">${this.isMinimized?"\u25A1":"_"} </button>
180
+ </div>
181
+ </div>
182
+ <div id="rule-list" class="content">
183
+ Waiting for evaluation...
184
+ </div>
185
+ `,this.setupDragging());}update(e){if(!this.shadow)return;let r=this.shadow.getElementById("rule-list");r&&(r.innerHTML=e.map(s=>{let{rule:i,result:n,error:c}=s,u=n==="error"?"status-error":n?"status-true":"status-false",a=n==="error"?"ERROR":n.toString().toUpperCase();i.disabled&&(u="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>`),`
186
+ <div class="rule">
187
+ <div class="rule-header">
188
+ <span class="rule-id">${i.id||(i.source==="attribute"?"Attr":"JSON")}</span>
189
+ <span class="status ${u}">${a}</span>
190
+ </div>
191
+ <div class="rule-expr">${i.expression}</div>
192
+ <div class="effects">
193
+ <div class="effect-item">${l}</div>
194
+ </div>
195
+ ${c?`<div class="error-msg">Error: ${c}</div>`:""}
196
+ </div>
197
+ `}).join(""));}getSelector(e){return e.id?`#${e.id}`:e.className?`.${e.className.split(" ").join(".")}`:e.tagName.toLowerCase()}destroy(){this.container&&this.container.parentNode&&this.container.parentNode.removeChild(this.container);}};var I=class{constructor(e,r={}){this.formElement=e;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=k(this.formElement,()=>{this.refreshRules(),this.setupEvents(),this.evaluate();}),this.setupEvents(),this.observer=D(this.formElement,()=>{this.refreshRules(),this.setupEvents(),this.evaluate();}),this.evaluate();}reEvaluate(){this.evaluate();}setupEvents(){this.cleanupEvents&&this.cleanupEvents();let e=new Set;this.rules.forEach(r=>{E(r.ast).global.forEach(s=>{e.add(s);});}),this.cleanupEvents=C(this.formElement,()=>{this.evaluate();},Array.from(e));}refreshRules(){this.rules=P(this.formElement,this.options);}evaluate(){if(this.isPaused)return;let e=q(this.formElement,this.rules,this.options);this.debugPanel&&this.debugPanel.update(e);}pause(){this.isPaused=true;}resume(){this.isPaused=false,this.evaluate();}exportRules(){return this.options.rules||[]}importRules(e){this.options.rules=e,this.savePersistedRules(),this.refreshRules(),this.setupEvents(),this.evaluate();}async enableRuleEditor(e){let{RuleEditor:r}=await Promise.resolve().then(()=>(O(),B));new r(this,e).mount();}loadPersistedRules(){let{persist:e}=this.options;if(e)try{let s=(e.storage==="localStorage"?localStorage:sessionStorage).getItem(e.key);s&&(this.options.rules=JSON.parse(s));}catch(r){console.error("[FormFx] Failed to load persisted rules:",r);}}savePersistedRules(){let{persist:e,rules:r}=this.options;if(!(!e||!r))try{(e.storage==="localStorage"?localStorage:sessionStorage).setItem(e.key,JSON.stringify(r));}catch(s){console.error("[FormFx] Failed to save rules:",s);}}enableRule(e){this.rules.forEach(r=>{r.id===e&&r.source==="json"&&(r.disabled=false);}),this.options.rules&&(this.options.rules.forEach(r=>{r.id===e&&(r.disabled=false);}),this.savePersistedRules()),this.evaluate();}disableRule(e){this.rules.forEach(r=>{r.id===e&&r.source==="json"&&(r.disabled=true);}),this.options.rules&&(this.options.rules.forEach(r=>{r.id===e&&(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=[];}};O();exports.FormFx=I;return exports;})({});//# sourceMappingURL=index.global.js.map
198
+ //# sourceMappingURL=index.global.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/editor/RuleEditor.ts","../src/internal/dom/value.ts","../src/internal/dom/effects.ts","../src/internal/dom/select.ts","../src/internal/expr/evaluator.ts","../src/internal/expr/parser.ts","../src/internal/expr/tokenizer.ts","../src/internal/engine.ts","../src/internal/observe.ts","../src/plugins/repeater/index.ts","../src/internal/debug/panel.ts","../src/core/FormFx.ts","../src/index.ts"],"names":["RuleEditor_exports","__export","RuleEditor","init_RuleEditor","__esmMin","fx","options","rules","listEl","rule","index","item","formEl","type","effects","eff","i","entry","effectType","selector","btn","newRule","readEffects","rows","row","obj","getInputValue","el","checked","clearValue","input","setDisabled","disabled","applyShow","show","isCurrentlyVisible","applyRequired","required","applyDisabled","applyClear","findById","root","id","byName","evaluate","node","context","fieldName","left","right","func","args","arg","parse","tokens","current","walk","parseLogicalOr","parseLogicalAnd","operator","parseComparison","parseAdditive","comparisonOps","parseMultiplicative","parseUnary","parsePrimary","token","elements","tokenize","char","isRow","value","rowPrefix","idMatch","word","createRules","formElement","attrName","expression","ast","e","jsonRule","addEffectRules","isElse","effect","key","finalAst","getDependencies","global","traverse","BUILTIN_FUNCTIONS","val","list","sub","runRules","debugInfos","globalContext","allGlobalDeps","baseEvalContext","elementToTypeToSource","rowContext","rowItem","fieldEl","evalContext","boolResult","errorMsg","setupEventListener","callback","dependentIds","handler","setupMutationObserver","observer","mutations","shouldUpdate","mutation","setupRepeaters","onUpdate","repeaterElements","cleanups","container","config","handleAdd","addItem","reindex","handleListClick","target","c","items","field","DebugPanel","saved","state","header","info","result","error","statusClass","statusText","effectInfo","FormFx","persist","data","ruleId"],"mappings":"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","file":"index.global.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","import { FXValue } from '../../types';\r\n\r\nexport function getInputValue(el: HTMLElement): FXValue {\r\n if (el instanceof HTMLInputElement) {\r\n if (el.type === 'checkbox') {\r\n return el.checked;\r\n }\r\n if (el.type === 'radio') {\r\n // ラジオボタンの場合は、同じnameを持つチェックされている要素を探す\r\n if (el.name) {\r\n const form = el.closest('form') || document;\r\n const checked = form.querySelector(`input[name=\"${el.name}\"]:checked`) as HTMLInputElement;\r\n return checked ? checked.value : null;\r\n }\r\n return el.checked ? el.value : null;\r\n }\r\n if (el.type === 'number' || el.type === 'range') {\r\n return el.value === '' ? null : Number(el.value);\r\n }\r\n return el.value;\r\n }\r\n \r\n if (el instanceof HTMLSelectElement || el instanceof HTMLTextAreaElement) {\r\n return el.value;\r\n }\r\n\r\n return null;\r\n}\r\n\r\nexport function clearValue(el: HTMLElement): void {\r\n if (el instanceof HTMLInputElement) {\r\n if (el.type === 'checkbox' || el.type === 'radio') {\r\n el.checked = false;\r\n } else {\r\n el.value = '';\r\n }\r\n } else if (el instanceof HTMLSelectElement) {\r\n el.selectedIndex = -1;\r\n el.value = '';\r\n } else if (el instanceof HTMLTextAreaElement) {\r\n el.value = '';\r\n } else {\r\n // コンテナの場合は配下の要素をクリア\r\n const inputs = el.querySelectorAll('input, select, textarea');\r\n inputs.forEach(input => clearValue(input as HTMLElement));\r\n }\r\n}\r\n\r\nexport function setDisabled(el: HTMLElement, disabled: boolean): void {\r\n if ('disabled' in el) {\r\n (el as any).disabled = disabled;\r\n } else {\r\n // コンテナの場合は配下の要素を制御\r\n const inputs = el.querySelectorAll('input, select, textarea');\r\n inputs.forEach(input => {\r\n (input as HTMLInputElement).disabled = disabled;\r\n });\r\n }\r\n}\r\n","import { FormFxOptions } from '../../types';\r\nimport { clearValue, setDisabled } from './value';\r\n\r\nexport function applyShow(el: HTMLElement, show: boolean, options: FormFxOptions): void {\r\n const isCurrentlyVisible = el.style.display !== 'none';\r\n \r\n if (show) {\r\n el.style.display = el.dataset.fxOriginalDisplay || '';\r\n // 再表示されたときに disabled を解除するかどうかは要件にないが、\r\n // disableOnHide=true の場合は対称性を持たせるのが一般的\r\n if (options.disableOnHide && !isCurrentlyVisible) {\r\n setDisabled(el, false);\r\n }\r\n } else {\r\n if (isCurrentlyVisible && !el.dataset.fxOriginalDisplay) {\r\n el.dataset.fxOriginalDisplay = el.style.display;\r\n }\r\n el.style.display = 'none';\r\n \r\n // 非表示になったときの追加処理\r\n if (isCurrentlyVisible) {\r\n if (el.dataset.fxClearOnHide === 'true' || options.clearOnHide) {\r\n clearValue(el);\r\n }\r\n if (options.disableOnHide) {\r\n setDisabled(el, true);\r\n }\r\n }\r\n }\r\n}\r\n\r\nexport function applyRequired(el: HTMLElement, required: boolean): void {\r\n if (el instanceof HTMLInputElement || el instanceof HTMLSelectElement || el instanceof HTMLTextAreaElement) {\r\n el.required = required;\r\n } else {\r\n // コンテナの場合、配下の全ての入力要素に適用\r\n const inputs = el.querySelectorAll('input, select, textarea');\r\n inputs.forEach(input => {\r\n (input as HTMLInputElement).required = required;\r\n });\r\n }\r\n}\r\n\r\nexport function applyDisabled(el: HTMLElement, disabled: boolean): void {\r\n setDisabled(el, disabled);\r\n}\r\n\r\nexport function applyClear(el: HTMLElement): void {\r\n clearValue(el);\r\n}\r\n","export function findById(root: HTMLElement, id: string): HTMLElement | null {\r\n // 1. Try to find by ID\r\n const el = root.querySelector(`#${id.replace(/([#;?%&,.+*~\\':\"!^$[\\]()=>|/@])/g, '\\\\$1')}`);\r\n if (el) return el as HTMLElement;\r\n\r\n // 2. Try to find by name attribute (v1.0 enhancement)\r\n const byName = root.querySelector(`[name=\"${id}\"]`);\r\n if (byName) return byName as HTMLElement;\r\n \r\n // 3. Try to find by data-fx-id\r\n return root.querySelector(`[data-fx-id=\"${id}\"]`) as HTMLElement | null;\r\n}\r\n\r\nexport function findByFxAttr(root: HTMLElement, attr: string): HTMLElement[] {\r\n return Array.from(root.querySelectorAll(`[${attr}]`));\r\n}\r\n","import { ASTNode, FXValue, EvaluationContext } from '../../types';\r\n\r\nexport function evaluate(node: ASTNode, context: EvaluationContext): FXValue {\r\n switch (node.type) {\r\n case 'Literal':\r\n return node.value;\r\n\r\n case 'Identifier': {\r\n if (node.name.startsWith('@row.')) {\r\n const fieldName = node.name.substring(5);\r\n return context.row && context.row[fieldName] !== undefined ? context.row[fieldName] : null;\r\n }\r\n return context.global[node.name] !== undefined ? context.global[node.name] : null;\r\n }\r\n\r\n case 'UnaryExpression':\r\n if (node.operator === '!') {\r\n return !evaluate(node.argument, context);\r\n }\r\n throw new Error(`Unknown unary operator: ${(node as any).operator}`);\r\n\r\n case 'BinaryExpression': {\r\n const left = evaluate(node.left, context);\r\n const right = evaluate(node.right, context);\r\n if (node.operator === '==') return left == right;\r\n if (node.operator === '!=') return left != right;\r\n if (node.operator === '>') return (left as any) > (right as any);\r\n if (node.operator === '>=') return (left as any) >= (right as any);\r\n if (node.operator === '<') return (left as any) < (right as any);\r\n if (node.operator === '<=') return (left as any) <= (right as any);\r\n if (node.operator === '+') return (left as any) + (right as any);\r\n if (node.operator === '-') return (left as any) - (right as any);\r\n if (node.operator === '*') return (left as any) * (right as any);\r\n if (node.operator === '/') return (left as any) / (right as any);\r\n if (node.operator === '%') return (left as any) % (right as any);\r\n throw new Error(`Unknown binary operator: ${node.operator}`);\r\n }\r\n\r\n case 'LogicalExpression': {\r\n const left = evaluate(node.left, context);\r\n if (node.operator === '&&') {\r\n return left && evaluate(node.right, context);\r\n }\r\n if (node.operator === '||') {\r\n return left || evaluate(node.right, context);\r\n }\r\n throw new Error(`Unknown logical operator: ${node.operator}`);\r\n }\r\n\r\n case 'CallExpression': {\r\n const func = context.functions[node.callee];\r\n if (!func) {\r\n throw new Error(`Unknown function: ${node.callee}`);\r\n }\r\n const args = node.arguments.map((arg: ASTNode) => evaluate(arg, context));\r\n return func(...args);\r\n }\r\n\r\n case 'ArrayExpression': {\r\n return node.elements.map((el: ASTNode) => evaluate(el, context));\r\n }\r\n\r\n default:\r\n throw new Error(`Unknown AST node type: ${(node as any).type}`);\r\n }\r\n}\r\n","import { ASTNode, Token } from '../../types';\r\n\r\n/**\r\n * 簡易的な再帰下降構文解析器\r\n * 優先順位:\r\n * 1. Primary (Identifier, Literal, Parentheses)\r\n * 2. Unary (!)\r\n * 3. Comparison (==, !=)\r\n * 4. Logical AND (&&)\r\n * 5. Logical OR (||)\r\n */\r\nexport function parse(tokens: Token[]): ASTNode {\r\n let current = 0;\r\n\r\n function walk(): ASTNode {\r\n return parseLogicalOr();\r\n }\r\n\r\n function parseLogicalOr(): ASTNode {\r\n let node = parseLogicalAnd();\r\n while (current < tokens.length && tokens[current].value === '||') {\r\n const operator = tokens[current].value as '||';\r\n current++;\r\n const right = parseLogicalAnd();\r\n node = { type: 'LogicalExpression', operator, left: node, right };\r\n }\r\n return node;\r\n }\r\n\r\n function parseLogicalAnd(): ASTNode {\r\n let node = parseComparison();\r\n while (current < tokens.length && tokens[current].value === '&&') {\r\n const operator = tokens[current].value as '&&';\r\n current++;\r\n const right = parseComparison();\r\n node = { type: 'LogicalExpression', operator, left: node, right };\r\n }\r\n return node;\r\n }\r\n\r\n function parseComparison(): ASTNode {\r\n let node = parseAdditive();\r\n const comparisonOps = ['==', '!=', '>', '>=', '<', '<='];\r\n while (current < tokens.length && comparisonOps.includes(tokens[current].value)) {\r\n const operator = tokens[current].value;\r\n current++;\r\n const right = parseAdditive();\r\n node = { type: 'BinaryExpression', operator, left: node, right };\r\n }\r\n return node;\r\n }\r\n\r\n function parseAdditive(): ASTNode {\r\n let node = parseMultiplicative();\r\n while (current < tokens.length && (tokens[current].value === '+' || tokens[current].value === '-')) {\r\n const operator = tokens[current].value;\r\n current++;\r\n const right = parseMultiplicative();\r\n node = { type: 'BinaryExpression', operator, left: node, right };\r\n }\r\n return node;\r\n }\r\n\r\n function parseMultiplicative(): ASTNode {\r\n let node = parseUnary();\r\n while (current < tokens.length && (tokens[current].value === '*' || tokens[current].value === '/' || tokens[current].value === '%')) {\r\n const operator = tokens[current].value;\r\n current++;\r\n const right = parseUnary();\r\n node = { type: 'BinaryExpression', operator, left: node, right };\r\n }\r\n return node;\r\n }\r\n\r\n function parseUnary(): ASTNode {\r\n if (current < tokens.length && tokens[current].value === '!') {\r\n current++;\r\n return { type: 'UnaryExpression', operator: '!', argument: parseUnary() };\r\n }\r\n return parsePrimary();\r\n }\r\n\r\n function parsePrimary(): ASTNode {\r\n const token = tokens[current];\r\n\r\n if (token.type === 'PAREN' && token.value === '(') {\r\n current++;\r\n const node = walk();\r\n if (tokens[current]?.value !== ')') {\r\n throw new Error('Expected )');\r\n }\r\n current++;\r\n return node;\r\n }\r\n\r\n if (token.type === 'IDENTIFIER') {\r\n current++;\r\n // 関数呼び出しのチェック: id(arg1, arg2)\r\n if (current < tokens.length && tokens[current].type === 'PAREN' && tokens[current].value === '(') {\r\n current++; // skip (\r\n const args: ASTNode[] = [];\r\n if (!(tokens[current].type === 'PAREN' && tokens[current].value === ')')) {\r\n while (true) {\r\n args.push(walk());\r\n if (tokens[current].type === 'COMMA') {\r\n current++;\r\n continue;\r\n }\r\n if (tokens[current].type === 'PAREN' && tokens[current].value === ')') {\r\n break;\r\n }\r\n throw new Error(`Expected , or ) in function call \"${token.value}\"`);\r\n }\r\n }\r\n current++; // skip )\r\n return { type: 'CallExpression', callee: token.value, arguments: args };\r\n }\r\n return { type: 'Identifier', name: token.value };\r\n }\r\n\r\n if (token.type === 'BRACKET' && token.value === '[') {\r\n current++; // skip [\r\n const elements: ASTNode[] = [];\r\n if (!(tokens[current].type === 'BRACKET' && tokens[current].value === ']')) {\r\n while (true) {\r\n elements.push(walk());\r\n if (tokens[current].type === 'COMMA') {\r\n current++;\r\n continue;\r\n }\r\n if (tokens[current].type === 'BRACKET' && tokens[current].value === ']') {\r\n break;\r\n }\r\n throw new Error('Expected , or ] in array literal');\r\n }\r\n }\r\n current++; // skip ]\r\n return { type: 'ArrayExpression', elements };\r\n }\r\n\r\n if (token.type === 'NUMBER') {\r\n current++;\r\n return { type: 'Literal', value: parseFloat(token.value) };\r\n }\r\n\r\n if (token.type === 'STRING') {\r\n current++;\r\n return { type: 'Literal', value: token.value };\r\n }\r\n\r\n if (token.type === 'BOOLEAN') {\r\n current++;\r\n return { type: 'Literal', value: token.value === 'true' };\r\n }\r\n\r\n throw new Error(`Unexpected token: ${token.value}`);\r\n }\r\n\r\n return walk();\r\n}\r\n","import { Token } from '../../types';\r\n\r\nexport function tokenize(input: string): Token[] {\r\n const tokens: Token[] = [];\r\n let current = 0;\r\n\r\n while (current < input.length) {\r\n let char = input[current];\r\n\r\n if (/\\s/.test(char)) {\r\n current++;\r\n continue;\r\n }\r\n\r\n if (char === '(' || char === ')') {\r\n tokens.push({ type: 'PAREN', value: char });\r\n current++;\r\n continue;\r\n }\r\n\r\n if (char === '[' || char === ']') {\r\n tokens.push({ type: 'BRACKET', value: char });\r\n current++;\r\n continue;\r\n }\r\n\r\n if (char === ',') {\r\n tokens.push({ type: 'COMMA', value: char });\r\n current++;\r\n continue;\r\n }\r\n\r\n if (char === '#' || char === '@') {\r\n const isRow = char === '@';\r\n let value = isRow ? '@' : '';\r\n current++; // skip # or @\r\n \r\n // @row.fieldName 対応\r\n if (isRow) {\r\n let rowPrefix = '';\r\n while (current < input.length && /[a-zA-Z0-9_-]/.test(input[current])) {\r\n rowPrefix += input[current];\r\n current++;\r\n }\r\n value += rowPrefix;\r\n if (input[current] === '.') {\r\n value += '.';\r\n current++;\r\n while (current < input.length && /[a-zA-Z0-9_-]/.test(input[current])) {\r\n value += input[current];\r\n current++;\r\n }\r\n }\r\n } else {\r\n while (current < input.length && /[a-zA-Z0-9_-]/.test(input[current])) {\r\n value += input[current];\r\n current++;\r\n }\r\n }\r\n tokens.push({ type: 'IDENTIFIER', value });\r\n continue;\r\n }\r\n\r\n if (/[0-9]/.test(char)) {\r\n let value = '';\r\n while (current < input.length && /[0-9.]/.test(input[current])) {\r\n value += input[current];\r\n current++;\r\n }\r\n tokens.push({ type: 'NUMBER', value });\r\n continue;\r\n }\r\n\r\n if (char === \"'\") {\r\n let value = '';\r\n current++; // skip '\r\n while (current < input.length && input[current] !== \"'\") {\r\n value += input[current];\r\n current++;\r\n }\r\n current++; // skip '\r\n tokens.push({ type: 'STRING', value });\r\n continue;\r\n }\r\n\r\n // Operators: ==, !=, &&, ||, !, >=, <=, >, <\r\n if (char === '=' && input[current + 1] === '=') {\r\n tokens.push({ type: 'OPERATOR', value: '==' });\r\n current += 2;\r\n continue;\r\n }\r\n if (char === '!' && input[current + 1] === '=') {\r\n tokens.push({ type: 'OPERATOR', value: '!=' });\r\n current += 2;\r\n continue;\r\n }\r\n if (char === '>' && input[current + 1] === '=') {\r\n tokens.push({ type: 'OPERATOR', value: '>=' });\r\n current += 2;\r\n continue;\r\n }\r\n if (char === '<' && input[current + 1] === '=') {\r\n tokens.push({ type: 'OPERATOR', value: '<=' });\r\n current += 2;\r\n continue;\r\n }\r\n if (char === '>') {\r\n tokens.push({ type: 'OPERATOR', value: '>' });\r\n current++;\r\n continue;\r\n }\r\n if (char === '<') {\r\n tokens.push({ type: 'OPERATOR', value: '<' });\r\n current++;\r\n continue;\r\n }\r\n if (char === '&' && input[current + 1] === '&') {\r\n tokens.push({ type: 'OPERATOR', value: '&&' });\r\n current += 2;\r\n continue;\r\n }\r\n if (char === '|' && input[current + 1] === '|') {\r\n tokens.push({ type: 'OPERATOR', value: '||' });\r\n current += 2;\r\n continue;\r\n }\r\n if (char === '!') {\r\n tokens.push({ type: 'OPERATOR', value: '!' });\r\n current++;\r\n continue;\r\n }\r\n\r\n if (char === '+' || char === '-' || char === '*' || char === '/' || char === '%') {\r\n tokens.push({ type: 'OPERATOR', value: char });\r\n current++;\r\n continue;\r\n }\r\n\r\n // Identifiers (for functions like in, contains)\r\n const idMatch = input.slice(current).match(/^[a-zA-Z][a-zA-Z0-9_]*/);\r\n if (idMatch) {\r\n // boolean check already exists below, so we handle it here or let it fall through\r\n const word = idMatch[0];\r\n if (word === 'true' || word === 'false') {\r\n tokens.push({ type: 'BOOLEAN', value: word });\r\n current += word.length;\r\n } else {\r\n tokens.push({ type: 'IDENTIFIER', value: word });\r\n current += word.length;\r\n }\r\n continue;\r\n }\r\n\r\n throw new Error(`Unexpected character: ${char} at position ${current}`);\r\n }\r\n\r\n return tokens;\r\n}\r\n","import { ASTNode, DebugInfo, EffectType, EvaluationContext, FormFxOptions, FXValue, JSONEffect, JSONRule, Rule } from '../types';\r\nimport { applyClear, applyDisabled, applyRequired, applyShow } from './dom/effects';\r\nimport { findById } from './dom/select';\r\nimport { getInputValue } from './dom/value';\r\nimport { evaluate } from './expr/evaluator';\r\nimport { parse } from './expr/parser';\r\nimport { tokenize } from './expr/tokenizer';\r\n\r\nexport function createRules(formElement: HTMLElement, options: FormFxOptions = {}): Rule[] {\r\n const rules: Rule[] = [];\r\n \r\n // 1. attributes ルール\r\n const attributeTypes: EffectType[] = ['show', 'required', 'disabled', 'enable', 'clear'];\r\n\r\n attributeTypes.forEach(type => {\r\n const attrName = `data-fx-${type}`;\r\n const elements = formElement.querySelectorAll<HTMLElement>(`[${attrName}]`);\r\n \r\n elements.forEach(el => {\r\n const expression = el.getAttribute(attrName) || '';\r\n try {\r\n const tokens = tokenize(expression);\r\n const ast = parse(tokens);\r\n rules.push({\r\n element: el,\r\n type,\r\n expression,\r\n ast,\r\n source: 'attribute'\r\n });\r\n } catch (e) {\r\n console.warn(`[FormFx] Failed to parse expression \"${expression}\" for ${attrName}:`, e);\r\n }\r\n });\r\n });\r\n\r\n // 2. JSON rules\r\n if (options.rules) {\r\n options.rules.forEach(jsonRule => {\r\n try {\r\n const tokens = tokenize(jsonRule.if);\r\n const ast = parse(tokens);\r\n \r\n const addEffectRules = (effects: JSONEffect[], isElse: boolean) => {\r\n effects.forEach(effect => {\r\n Object.entries(effect).forEach(([key, selector]) => {\r\n if (typeof selector !== 'string' || !selector) return;\r\n let type = (key === 'require' ? 'required' : key) as EffectType;\r\n let expression = jsonRule.if;\r\n let finalAst = ast;\r\n\r\n if (type === 'hide') {\r\n type = 'show';\r\n finalAst = { type: 'UnaryExpression', operator: '!', argument: ast };\r\n expression = `!(${jsonRule.if})`;\r\n }\r\n\r\n if (isElse) {\r\n finalAst = { type: 'UnaryExpression', operator: '!', argument: finalAst };\r\n expression = `!(${expression})`;\r\n }\r\n\r\n const elements = formElement.querySelectorAll(selector);\r\n elements.forEach(node => {\r\n const el = node as HTMLElement;\r\n rules.push({\r\n id: jsonRule.id,\r\n element: el,\r\n type,\r\n expression,\r\n ast: finalAst,\r\n source: 'json',\r\n rawRule: jsonRule,\r\n disabled: jsonRule.disabled // v0.4\r\n });\r\n });\r\n });\r\n });\r\n };\r\n\r\n addEffectRules(jsonRule.then, false);\r\n if (jsonRule.else) {\r\n addEffectRules(jsonRule.else, true);\r\n }\r\n } catch (e) {\r\n console.warn(`[FormFx] Failed to parse JSON rule:`, jsonRule, e);\r\n }\r\n });\r\n }\r\n\r\n return rules;\r\n}\r\n\r\n/**\r\n * 依存しているフィールド(#id または @row.field)をASTから抽出する\r\n */\r\nexport function getDependencies(ast: ASTNode): { global: string[], row: string[] } {\r\n const global = new Set<string>();\r\n const row = new Set<string>();\r\n \r\n function traverse(node: ASTNode) {\r\n if (node.type === 'Identifier') {\r\n if (node.name.startsWith('@row.')) {\r\n row.add(node.name.substring(5));\r\n } else {\r\n global.add(node.name);\r\n }\r\n } else if (node.type === 'BinaryExpression' || node.type === 'LogicalExpression') {\r\n traverse(node.left);\r\n traverse(node.right);\r\n } else if (node.type === 'UnaryExpression') {\r\n traverse(node.argument);\r\n } else if (node.type === 'CallExpression') {\r\n node.arguments.forEach(traverse);\r\n } else if (node.type === 'ArrayExpression') {\r\n node.elements.forEach(traverse);\r\n }\r\n }\r\n \r\n traverse(ast);\r\n return {\r\n global: Array.from(global),\r\n row: Array.from(row)\r\n };\r\n}\r\n\r\nconst BUILTIN_FUNCTIONS: Record<string, (...args: any[]) => FXValue> = {\r\n in: (val, list) => {\r\n if (!Array.isArray(list)) return false;\r\n return list.includes(val);\r\n },\r\n contains: (val, sub) => {\r\n if (typeof val !== 'string') return false;\r\n return val.includes(sub);\r\n }\r\n};\r\n\r\nexport function runRules(formElement: HTMLElement, rules: Rule[], options: FormFxOptions): DebugInfo[] {\r\n const debugInfos: DebugInfo[] = [];\r\n // コンテキスト(値の辞書)を作成\r\n const globalContext: Record<string, FXValue> = {};\r\n \r\n // キャッシュして効率化することも考えられるが、まずは全ルール評価\r\n const allGlobalDeps = new Set<string>();\r\n rules.forEach(rule => {\r\n getDependencies(rule.ast).global.forEach(id => allGlobalDeps.add(id));\r\n });\r\n\r\n allGlobalDeps.forEach(id => {\r\n const el = findById(formElement, id);\r\n if (el) {\r\n globalContext[id] = getInputValue(el);\r\n } else {\r\n globalContext[id] = null;\r\n }\r\n });\r\n\r\n const baseEvalContext: EvaluationContext = {\r\n global: globalContext,\r\n functions: BUILTIN_FUNCTIONS\r\n };\r\n\r\n // 各ルールを評価して適用\r\n const elementToTypeToSource = new Map<HTMLElement, Map<EffectType, 'attribute' | 'json'>>();\r\n rules.forEach(rule => {\r\n if (!elementToTypeToSource.has(rule.element)) {\r\n elementToTypeToSource.set(rule.element, new Map());\r\n }\r\n const types = elementToTypeToSource.get(rule.element)!;\r\n // JSONが後にあるので、JSONがあれば上書きされる\r\n types.set(rule.type, rule.source);\r\n });\r\n\r\n rules.forEach(rule => {\r\n if (rule.disabled) return;\r\n\r\n // Determine if this rule should be skipped because a JSON rule for the same element and type exists.\r\n // JSON rules (added later in createRules) take precedence over attribute rules.\r\n if (rule.source === 'attribute') {\r\n const winner = elementToTypeToSource.get(rule.element)?.get(rule.type);\r\n if (winner === 'json') return;\r\n }\r\n\r\n try {\r\n // row context の構築\r\n let rowContext: Record<string, FXValue> | undefined = undefined;\r\n const rowItem = rule.element.closest('[data-fx-item]');\r\n if (rowItem) {\r\n rowContext = {};\r\n const deps = getDependencies(rule.ast);\r\n deps.row.forEach(fieldName => {\r\n const fieldEl = rowItem.querySelector(`[data-fx-field=\"${fieldName}\"]`);\r\n if (fieldEl) {\r\n // フィールド内の実際の入力要素を取得\r\n const input = fieldEl.querySelector('input, select, textarea') as HTMLElement;\r\n rowContext![fieldName] = input ? getInputValue(input) : null;\r\n } else {\r\n rowContext![fieldName] = null;\r\n }\r\n });\r\n }\r\n\r\n const evalContext: EvaluationContext = {\r\n ...baseEvalContext,\r\n row: rowContext\r\n };\r\n\r\n const result = evaluate(rule.ast, evalContext);\r\n const boolResult = !!result;\r\n\r\n if (options.debug) {\r\n debugInfos.push({\r\n rule,\r\n result: boolResult,\r\n elements: [rule.element]\r\n });\r\n console.debug(`[FormFx Debug] Rule: ${rule.type}=\"${rule.expression}\" (source: ${rule.source}, result: ${boolResult})`, {\r\n element: rule.element,\r\n result: boolResult,\r\n context: evalContext\r\n });\r\n }\r\n\r\n switch (rule.type) {\r\n case 'show':\r\n applyShow(rule.element, boolResult, options);\r\n break;\r\n case 'required':\r\n applyRequired(rule.element, boolResult);\r\n break;\r\n case 'disabled':\r\n applyDisabled(rule.element, boolResult);\r\n break;\r\n case 'enable':\r\n applyDisabled(rule.element, !boolResult);\r\n break;\r\n case 'clear':\r\n // 変化した瞬間(false -> true)のみクリア\r\n if (boolResult && rule.lastResult === false) {\r\n applyClear(rule.element);\r\n }\r\n break;\r\n }\r\n \r\n rule.lastResult = boolResult;\r\n\r\n } catch (e) {\r\n const errorMsg = e instanceof Error ? e.message : String(e);\r\n if (options.debug) {\r\n debugInfos.push({\r\n rule,\r\n result: 'error',\r\n error: errorMsg,\r\n elements: [rule.element]\r\n });\r\n console.warn(`[FormFx Debug] Evaluation failed: \"${rule.expression}\"`, e);\r\n } else {\r\n console.warn(`[FormFx] Failed to evaluate expression \"${rule.expression}\":`, e);\r\n }\r\n }\r\n });\r\n\r\n return debugInfos;\r\n}\r\n","export function setupEventListener(\r\n formElement: HTMLElement,\r\n callback: () => void,\r\n dependentIds: string[]\r\n): () => void {\r\n const handler = () => {\r\n callback();\r\n };\r\n\r\n // 依存フィールド単位での監視\r\n // ※ 動的に要素が追加される場合は MutationObserver がカバーする\r\n const cleanups: (() => void)[] = [];\r\n\r\n // 全体を監視しつつ、特定要素へのリスナーも検討可能だが、\r\n // シンプルさと確実性のために formElement への委譲を維持しつつ、\r\n // 将来的にはここで絞り込みを行う。\r\n // v0.2では「参照されているフィールドのみ」を意識した設計にする。\r\n \r\n formElement.addEventListener('input', handler);\r\n formElement.addEventListener('change', handler);\r\n\r\n return () => {\r\n formElement.removeEventListener('input', handler);\r\n formElement.removeEventListener('change', handler);\r\n };\r\n}\r\n\r\nexport function setupMutationObserver(\r\n formElement: HTMLElement,\r\n callback: () => void\r\n): MutationObserver {\r\n const observer = new MutationObserver((mutations) => {\r\n let shouldUpdate = false;\r\n for (const mutation of mutations) {\r\n if (mutation.type === 'childList' && (mutation.addedNodes.length > 0 || mutation.removedNodes.length > 0)) {\r\n shouldUpdate = true;\r\n break;\r\n }\r\n }\r\n \r\n if (shouldUpdate) {\r\n callback();\r\n }\r\n });\r\n\r\n observer.observe(formElement, {\r\n childList: true,\r\n subtree: true\r\n });\r\n\r\n return observer;\r\n}\r\n","import { RepeaterConfig } from '../../types';\r\n\r\nexport function setupRepeaters(\r\n formElement: HTMLElement,\r\n onUpdate: () => void\r\n): () => void {\r\n const repeaterElements = formElement.querySelectorAll<HTMLElement>('[data-fx-repeater]');\r\n const cleanups: (() => void)[] = [];\r\n\r\n repeaterElements.forEach(container => {\r\n const config: RepeaterConfig = {\r\n container,\r\n name: container.getAttribute('data-fx-name') || '',\r\n max: parseInt(container.getAttribute('data-fx-max') || '10', 10),\r\n addButton: container.querySelector<HTMLElement>('[data-fx-add]'),\r\n listContainer: container.querySelector<HTMLElement>('[data-fx-list]') || container,\r\n template: container.querySelector<HTMLTemplateElement>('template[data-fx-template]')!\r\n };\r\n\r\n if (!config.template) {\r\n console.warn('[FormFx] Repeater template not found', container);\r\n return;\r\n }\r\n\r\n const handleAdd = () => {\r\n const items = config.listContainer.querySelectorAll('[data-fx-item]');\r\n if (items.length < config.max) {\r\n addItem(config);\r\n reindex(config);\r\n onUpdate();\r\n }\r\n };\r\n\r\n if (config.addButton) {\r\n config.addButton.addEventListener('click', handleAdd);\r\n cleanups.push(() => config.addButton?.removeEventListener('click', handleAdd));\r\n }\r\n\r\n // 既存のアイテムに対してもイベント設定とリインデックスが必要\r\n const handleListClick = (e: Event) => {\r\n const target = e.target as HTMLElement;\r\n if (target.closest('[data-fx-remove]')) {\r\n const item = target.closest('[data-fx-item]');\r\n if (item) {\r\n item.remove();\r\n reindex(config);\r\n onUpdate();\r\n }\r\n }\r\n };\r\n\r\n config.listContainer.addEventListener('click', handleListClick);\r\n cleanups.push(() => config.listContainer.removeEventListener('click', handleListClick));\r\n\r\n // 初期化時に一度リインデックス\r\n reindex(config);\r\n });\r\n\r\n return () => cleanups.forEach(c => c());\r\n}\r\n\r\nfunction addItem(config: RepeaterConfig) {\r\n const content = config.template.content.cloneNode(true) as DocumentFragment;\r\n const item = content.querySelector('[data-fx-item]');\r\n if (item) {\r\n config.listContainer.appendChild(item);\r\n }\r\n}\r\n\r\nfunction reindex(config: RepeaterConfig) {\r\n const items = config.listContainer.querySelectorAll<HTMLElement>('[data-fx-item]');\r\n items.forEach((item, index) => {\r\n // data-fx-index 属性を付与(デバッグや特定用途向け)\r\n item.setAttribute('data-fx-index', index.toString());\r\n\r\n const fields = item.querySelectorAll<HTMLElement>('[data-fx-field]');\r\n fields.forEach(field => {\r\n const fieldName = field.getAttribute('data-fx-field');\r\n if (fieldName) {\r\n const inputs = field.querySelectorAll<HTMLInputElement | HTMLSelectElement | HTMLTextAreaElement>('input, select, textarea');\r\n inputs.forEach(input => {\r\n input.name = `${config.name}[${index}].${fieldName}`;\r\n // 行内参照を容易にするため、input自体にも field 名を保持させることがあるが、\r\n // 今回は closest('[data-fx-field]') で解決する設計とした。\r\n });\r\n }\r\n });\r\n });\r\n\r\n // 追加ボタンの表示/非表示制御(任意だが親切)\r\n if (config.addButton) {\r\n if (items.length >= config.max) {\r\n config.addButton.style.display = 'none';\r\n } else {\r\n config.addButton.style.display = '';\r\n }\r\n }\r\n}\r\n","import { DebugInfo, PersistOptions } from '../../types';\r\n\r\nexport class DebugPanel {\r\n private container: HTMLElement | null = null;\r\n private shadow: ShadowRoot | null = null;\r\n private persistInfo: PersistOptions | null = null;\r\n private isMinimized = false;\r\n private pos = { x: 10, y: 10 };\r\n private isDragging = false;\r\n private dragStart = { x: 0, y: 0 };\r\n\r\n constructor() {\r\n this.loadState();\r\n this.container = document.createElement('div');\r\n this.container.id = 'formfx-debug-panel';\r\n this.shadow = this.container.attachShadow({ mode: 'open' });\r\n this.renderInitial();\r\n document.body.appendChild(this.container);\r\n this.setupDragging();\r\n }\r\n\r\n private loadState() {\r\n try {\r\n const saved = localStorage.getItem('formfx-debug-state');\r\n if (saved) {\r\n const state = JSON.parse(saved);\r\n this.isMinimized = !!state.isMinimized;\r\n if (state.pos) this.pos = state.pos;\r\n }\r\n } catch (e) {\r\n // Ignore\r\n }\r\n }\r\n\r\n private saveState() {\r\n try {\r\n localStorage.setItem('formfx-debug-state', JSON.stringify({\r\n isMinimized: this.isMinimized,\r\n pos: this.pos\r\n }));\r\n } catch (e) {\r\n // Ignore\r\n }\r\n }\r\n\r\n private setupDragging() {\r\n if (!this.shadow || !this.container) return;\r\n const header = this.shadow.querySelector('.header') as HTMLElement;\r\n if (!header) return;\r\n\r\n header.style.cursor = 'move';\r\n header.addEventListener('mousedown', (e) => {\r\n this.isDragging = true;\r\n this.dragStart = {\r\n x: e.clientX + this.pos.x,\r\n y: e.clientY + this.pos.y\r\n };\r\n e.preventDefault();\r\n });\r\n\r\n window.addEventListener('mousemove', (e) => {\r\n if (!this.isDragging) return;\r\n this.pos.x = this.dragStart.x - e.clientX;\r\n this.pos.y = this.dragStart.y - e.clientY;\r\n this.updatePosition();\r\n });\r\n\r\n window.addEventListener('mouseup', () => {\r\n if (this.isDragging) {\r\n this.isDragging = false;\r\n this.saveState();\r\n }\r\n });\r\n\r\n const toggleBtn = this.shadow.getElementById('toggle-minimize');\r\n toggleBtn?.addEventListener('click', (e) => {\r\n e.stopPropagation();\r\n this.isMinimized = !this.isMinimized;\r\n this.renderInitial();\r\n this.updatePosition();\r\n this.saveState();\r\n });\r\n }\r\n\r\n private updatePosition() {\r\n if (!this.container) return;\r\n this.container.style.bottom = `${this.pos.y}px`;\r\n this.container.style.right = `${this.pos.x}px`;\r\n }\r\n\r\n setPersistInfo(info: PersistOptions) {\r\n this.persistInfo = info;\r\n }\r\n\r\n private renderInitial() {\r\n if (!this.shadow) return;\r\n this.shadow.innerHTML = `\r\n <style>\r\n :host {\r\n position: fixed;\r\n bottom: ${this.pos.y}px;\r\n right: ${this.pos.x}px;\r\n width: 350px;\r\n max-height: 80vh;\r\n background: rgba(0, 0, 0, 0.85);\r\n color: white;\r\n font-family: monospace;\r\n font-size: 12px;\r\n border-radius: 8px;\r\n overflow: hidden;\r\n z-index: 10000;\r\n box-shadow: 0 4px 12px rgba(0,0,0,0.3);\r\n border: 1px solid #444;\r\n display: flex;\r\n flex-direction: column;\r\n }\r\n .header {\r\n padding: 8px 12px;\r\n background: #222;\r\n border-bottom: 1px solid #444;\r\n font-weight: bold;\r\n display: flex;\r\n justify-content: space-between;\r\n align-items: center;\r\n user-select: none;\r\n }\r\n .content {\r\n padding: 8px;\r\n overflow-y: auto;\r\n display: ${this.isMinimized ? 'none' : 'block'};\r\n }\r\n .header-controls {\r\n display: flex;\r\n gap: 8px;\r\n }\r\n .btn-icon {\r\n cursor: pointer;\r\n padding: 2px 6px;\r\n border-radius: 4px;\r\n background: #444;\r\n border: none;\r\n color: white;\r\n font-size: 10px;\r\n }\r\n .btn-icon:hover {\r\n background: #666;\r\n }\r\n .rule {\r\n margin-bottom: 8px;\r\n padding: 6px;\r\n border-radius: 4px;\r\n background: #333;\r\n }\r\n .rule-header {\r\n display: flex;\r\n justify-content: space-between;\r\n margin-bottom: 4px;\r\n }\r\n .rule-id {\r\n color: #aaa;\r\n font-size: 10px;\r\n }\r\n .rule-expr {\r\n word-break: break-all;\r\n color: #88ccff;\r\n }\r\n .status {\r\n font-weight: bold;\r\n padding: 2px 4px;\r\n border-radius: 2px;\r\n font-size: 10px;\r\n }\r\n .status-true { background: #228b22; }\r\n .status-false { background: #b22222; }\r\n .status-error { background: #ff4500; }\r\n .status-disabled { background: #666; color: #ccc; }\r\n .persist-badge {\r\n font-size: 9px;\r\n background: #444;\r\n padding: 1px 4px;\r\n border-radius: 4px;\r\n color: #00ff00;\r\n border: 1px solid #00ff00;\r\n }\r\n .header-top {\r\n display: flex;\r\n align-items: center;\r\n gap: 8px;\r\n }\r\n .effects {\r\n margin-top: 4px;\r\n padding-left: 12px;\r\n border-left: 2px solid #555;\r\n font-size: 11px;\r\n }\r\n .effect-item {\r\n margin-top: 2px;\r\n }\r\n .effect-skipped {\r\n color: #888;\r\n text-decoration: line-through;\r\n }\r\n .error-msg {\r\n color: #ff6347;\r\n font-size: 10px;\r\n margin-top: 4px;\r\n }\r\n </style>\r\n <div class=\"header\">\r\n <div class=\"header-top\">\r\n <span>FormFx Debug</span>\r\n ${this.persistInfo ? `<span class=\"persist-badge\">PERSIST</span>` : ''}\r\n </div>\r\n <div class=\"header-controls\">\r\n <button id=\"toggle-minimize\" class=\"btn-icon\">${this.isMinimized ? '□' : '_'} </button>\r\n </div>\r\n </div>\r\n <div id=\"rule-list\" class=\"content\">\r\n Waiting for evaluation...\r\n </div>\r\n `;\r\n this.setupDragging();\r\n }\r\n\r\n update(debugInfos: DebugInfo[]) {\r\n if (!this.shadow) return;\r\n const listEl = this.shadow.getElementById('rule-list');\r\n if (!listEl) return;\r\n\r\n listEl.innerHTML = debugInfos.map(info => {\r\n const { rule, result, error } = info;\r\n \r\n let statusClass = result === 'error' ? 'status-error' : (result ? 'status-true' : 'status-false');\r\n let statusText = result === 'error' ? 'ERROR' : result.toString().toUpperCase();\r\n\r\n if (rule.disabled) {\r\n statusClass = 'status-disabled';\r\n statusText = 'DISABLED';\r\n }\r\n \r\n let effectInfo = `${rule.type} ${this.getSelector(rule.element)}`;\r\n if (result !== true && result !== 'error' && !rule.disabled) {\r\n effectInfo = `<span class=\"effect-skipped\">${effectInfo} (skipped)</span>`;\r\n }\r\n if (rule.disabled) {\r\n effectInfo = `<span class=\"effect-skipped\">${effectInfo}</span>`;\r\n }\r\n\r\n return `\r\n <div class=\"rule\">\r\n <div class=\"rule-header\">\r\n <span class=\"rule-id\">${rule.id || (rule.source === 'attribute' ? 'Attr' : 'JSON')}</span>\r\n <span class=\"status ${statusClass}\">${statusText}</span>\r\n </div>\r\n <div class=\"rule-expr\">${rule.expression}</div>\r\n <div class=\"effects\">\r\n <div class=\"effect-item\">${effectInfo}</div>\r\n </div>\r\n ${error ? `<div class=\"error-msg\">Error: ${error}</div>` : ''}\r\n </div>\r\n `;\r\n }).join('');\r\n }\r\n\r\n private getSelector(el: HTMLElement): string {\r\n if (el.id) return `#${el.id}`;\r\n if (el.className) return `.${el.className.split(' ').join('.')}`;\r\n return el.tagName.toLowerCase();\r\n }\r\n\r\n destroy() {\r\n if (this.container && this.container.parentNode) {\r\n this.container.parentNode.removeChild(this.container);\r\n }\r\n }\r\n}\r\n","import { FormFxOptions, Rule, JSONRule, RuleEditorOptions } from '../types';\r\nimport { createRules, runRules, getDependencies } from '../internal/engine';\r\nimport { setupEventListener, setupMutationObserver } from '../internal/observe';\r\nimport { setupRepeaters } from '../plugins/repeater';\r\nimport { DebugPanel } from '../internal/debug/panel';\r\n\r\nexport class FormFx {\r\n private rules: Rule[] = [];\r\n private options: FormFxOptions;\r\n private cleanupEvents: (() => void) | null = null;\r\n private cleanupRepeaters: (() => void) | null = null;\r\n private observer: MutationObserver | null = null;\r\n private debugPanel: DebugPanel | null = null;\r\n private isPaused = false;\r\n\r\n constructor(private formElement: HTMLElement, options: FormFxOptions = {}) {\r\n this.options = {\r\n disableOnHide: true,\r\n clearOnHide: false,\r\n ...options\r\n };\r\n\r\n // 永続化データの読み込み (JSON rulesのみ)\r\n this.loadPersistedRules();\r\n }\r\n\r\n mount(): void {\r\n // 0. Debug Panel の初期化\r\n if (this.options.debug) {\r\n this.debugPanel = new DebugPanel();\r\n if (this.options.persist) {\r\n this.debugPanel.setPersistInfo(this.options.persist);\r\n }\r\n }\r\n\r\n // 1. ルールの初回収集\r\n this.refreshRules();\r\n\r\n // 2. リピーターの初期化\r\n this.cleanupRepeaters = setupRepeaters(this.formElement, () => {\r\n // DOMが変化した後にルールを再収集して評価\r\n this.refreshRules();\r\n this.setupEvents(); // 依存フィールドが変わる可能性があるため再設定\r\n this.evaluate();\r\n });\r\n\r\n // 3. イベントリスナーの設定\r\n this.setupEvents();\r\n\r\n // 4. MutationObserverの設定(動的な属性追加などに対応)\r\n this.observer = setupMutationObserver(this.formElement, () => {\r\n this.refreshRules();\r\n this.setupEvents();\r\n this.evaluate();\r\n });\r\n\r\n // 5. 初回評価\r\n this.evaluate();\r\n }\r\n\r\n reEvaluate(): void {\r\n this.evaluate();\r\n }\r\n\r\n private setupEvents(): void {\r\n if (this.cleanupEvents) this.cleanupEvents();\r\n\r\n const dependentIds = new Set<string>();\r\n this.rules.forEach(rule => {\r\n getDependencies(rule.ast).global.forEach(id => {\r\n // IDだけでなくnameでも参照される可能性があるため、基本的には広めに監視する\r\n dependentIds.add(id);\r\n });\r\n });\r\n\r\n this.cleanupEvents = setupEventListener(this.formElement, () => {\r\n this.evaluate();\r\n }, Array.from(dependentIds));\r\n }\r\n\r\n private refreshRules(): void {\r\n // attributes ルールと JSON ルールの両方を収集\r\n // JSON rules が優先されるように後でマージするが、\r\n // createRules 内で JSON rules は後に追加されるように実装済み\r\n this.rules = createRules(this.formElement, this.options);\r\n }\r\n\r\n private evaluate(): void {\r\n if (this.isPaused) return;\r\n\r\n const debugInfos = runRules(this.formElement, this.rules, this.options);\r\n if (this.debugPanel) {\r\n this.debugPanel.update(debugInfos);\r\n }\r\n }\r\n\r\n /**\r\n * ルール評価を一時停止する (v0.4)\r\n */\r\n pause(): void {\r\n this.isPaused = true;\r\n }\r\n\r\n /**\r\n * ルール評価を再開する (v0.4)\r\n */\r\n resume(): void {\r\n this.isPaused = false;\r\n this.evaluate();\r\n }\r\n\r\n /**\r\n * JSONルールをエクスポートする (v0.4)\r\n */\r\n exportRules(): JSONRule[] {\r\n return this.options.rules || [];\r\n }\r\n\r\n /**\r\n * JSONルールをインポートする (v0.4)\r\n */\r\n importRules(rules: JSONRule[]): void {\r\n this.options.rules = rules;\r\n this.savePersistedRules();\r\n this.refreshRules();\r\n this.setupEvents();\r\n this.evaluate();\r\n }\r\n\r\n /**\r\n * Rule Editor を有効化する (v0.4)\r\n */\r\n async enableRuleEditor(options: RuleEditorOptions): Promise<void> {\r\n const { RuleEditor } = await import('../editor/RuleEditor');\r\n const editor = new RuleEditor(this, options);\r\n editor.mount();\r\n }\r\n\r\n private loadPersistedRules(): void {\r\n const { persist } = this.options;\r\n if (!persist) return;\r\n\r\n try {\r\n const storage = persist.storage === 'localStorage' ? localStorage : sessionStorage;\r\n const data = storage.getItem(persist.key);\r\n if (data) {\r\n this.options.rules = JSON.parse(data);\r\n }\r\n } catch (e) {\r\n console.error('[FormFx] Failed to load persisted rules:', e);\r\n }\r\n }\r\n\r\n private savePersistedRules(): void {\r\n const { persist, rules } = this.options;\r\n if (!persist || !rules) return;\r\n\r\n try {\r\n const storage = persist.storage === 'localStorage' ? localStorage : sessionStorage;\r\n storage.setItem(persist.key, JSON.stringify(rules));\r\n } catch (e) {\r\n console.error('[FormFx] Failed to save rules:', e);\r\n }\r\n }\r\n\r\n /**\r\n * JSONルールを有効化する\r\n * @param ruleId \r\n */\r\n enableRule(ruleId: string): void {\r\n this.rules.forEach(r => {\r\n if (r.id === ruleId && r.source === 'json') {\r\n r.disabled = false;\r\n }\r\n });\r\n if (this.options.rules) {\r\n this.options.rules.forEach(r => {\r\n if (r.id === ruleId) r.disabled = false;\r\n });\r\n this.savePersistedRules();\r\n }\r\n this.evaluate();\r\n }\r\n\r\n /**\r\n * JSONルールを無効化する\r\n * @param ruleId \r\n */\r\n disableRule(ruleId: string): void {\r\n this.rules.forEach(r => {\r\n if (r.id === ruleId && r.source === 'json') {\r\n r.disabled = true;\r\n }\r\n });\r\n if (this.options.rules) {\r\n this.options.rules.forEach(r => {\r\n if (r.id === ruleId) r.disabled = true;\r\n });\r\n this.savePersistedRules();\r\n }\r\n this.evaluate();\r\n }\r\n\r\n destroy(): void {\r\n if (this.cleanupEvents) this.cleanupEvents();\r\n if (this.cleanupRepeaters) this.cleanupRepeaters();\r\n if (this.observer) this.observer.disconnect();\r\n if (this.debugPanel) this.debugPanel.destroy();\r\n \r\n // イベントリスナーの再解除を確実にするため\r\n this.cleanupEvents = null;\r\n this.cleanupRepeaters = null;\r\n this.observer = null;\r\n this.debugPanel = null;\r\n\r\n // 適用されたスタイルや属性をリセットしたい場合があるが、\r\n // 基本的には「監視を止める」のが destroy の責務\r\n this.rules = [];\r\n }\r\n}\r\n","export { FormFx } from './core/FormFx';\r\nexport { RuleEditor } from './editor/RuleEditor';\r\nexport * from './public-types';\r\n"]}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "formfx",
3
- "version": "1.0.0",
3
+ "version": "1.0.1",
4
4
  "description": "Powerful & Lightweight form control library with data attributes and safe expression evaluation.",
5
5
  "type": "module",
6
6
  "main": "./dist/index.cjs",