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.
package/dist/index.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"sources":["../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"],"names":["getInputValue","el","checked","clearValue","input","setDisabled","disabled","applyShow","show","options","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","rules","type","attrName","expression","ast","e","jsonRule","addEffectRules","effects","isElse","effect","key","selector","finalAst","getDependencies","global","row","traverse","BUILTIN_FUNCTIONS","val","list","sub","runRules","debugInfos","globalContext","allGlobalDeps","rule","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","item","c","items","index","field","DebugPanel","saved","state","header","info","listEl","result","error","statusClass","statusText","effectInfo","FormFx","RuleEditor","persist","data","ruleId"],"mappings":"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","file":"index.js","sourcesContent":["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"]}
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"],"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 show() {\r\n if (this.container) {\r\n this.container.style.display = 'block';\r\n }\r\n }\r\n\r\n hide() {\r\n if (this.container) {\r\n this.container.style.display = 'none';\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 * デバッグパネルの表示/非表示を切り替える (v0.4.1)\r\n */\r\n setDebug(enabled: boolean): void {\r\n this.options.debug = enabled;\r\n if (enabled) {\r\n if (!this.debugPanel) {\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 this.evaluate();\r\n } else {\r\n this.debugPanel.show();\r\n }\r\n } else {\r\n if (this.debugPanel) {\r\n this.debugPanel.hide();\r\n }\r\n }\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","import { FormFx } from './core/FormFx';\r\n\r\n/**\r\n * Browser Global Support\r\n * <script>タグで読み込まれた際、自動的に window.FormFx に登録します\r\n */\r\nif (typeof window !== 'undefined') {\r\n // tsupのiife(globalName)を使っている場合、\r\n // エクスポート全体が window.FormFx に代入される。\r\n // その中の FormFx クラスを window.FormFx に直接上書きすることで\r\n // ユーザーが new FormFx() として直感的に使えるようにする。\r\n if ((window as any).FormFx && (window as any).FormFx.FormFx) {\r\n // すでに代入されている場合は即座に。\r\n (window as any).FormFx = (window as any).FormFx.FormFx;\r\n } else {\r\n // まだの場合はタイミングを待つ(tsupのIIFEの戻り値が代入されるタイミングに合わせる)\r\n setTimeout(() => {\r\n if ((window as any).FormFx && (window as any).FormFx.FormFx) {\r\n (window as any).FormFx = (window as any).FormFx.FormFx;\r\n }\r\n }, 0);\r\n }\r\n}\r\n\r\nexport { FormFx };\r\nexport * from './public-types';"],"mappings":"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","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","el","show","options","isCurrentlyVisible","setDisabled","clearValue","applyRequired","required","input","applyDisabled","disabled","applyClear","findById","root","id","el","byName","evaluate","node","context","fieldName","left","right","func","args","arg","el","parse","tokens","current","walk","parseLogicalOr","node","parseLogicalAnd","operator","right","parseComparison","parseAdditive","comparisonOps","parseMultiplicative","parseUnary","parsePrimary","token","args","elements","tokenize","input","tokens","current","char","isRow","value","rowPrefix","idMatch","word","createRules","formElement","options","rules","type","attrName","el","expression","tokens","tokenize","ast","parse","e","jsonRule","addEffectRules","effects","isElse","effect","key","selector","finalAst","node","getDependencies","global","row","traverse","BUILTIN_FUNCTIONS","val","list","sub","runRules","debugInfos","globalContext","allGlobalDeps","rule","id","findById","getInputValue","baseEvalContext","elementToTypeToSource","rowContext","rowItem","fieldName","fieldEl","input","evalContext","boolResult","evaluate","applyShow","applyRequired","applyDisabled","applyClear","errorMsg","setupEventListener","formElement","callback","dependentIds","handler","cleanups","setupMutationObserver","observer","mutations","shouldUpdate","mutation","setupRepeaters","formElement","onUpdate","repeaterElements","cleanups","container","config","handleAdd","addItem","reindex","handleListClick","e","target","item","c","items","index","field","fieldName","input","DebugPanel","saved","state","header","e","info","debugInfos","listEl","rule","result","error","statusClass","statusText","effectInfo","el","FormFx","formElement","options","DebugPanel","setupRepeaters","setupMutationObserver","dependentIds","rule","getDependencies","id","setupEventListener","createRules","debugInfos","runRules","rules","enabled","RuleEditor","persist","data","e","ruleId"]}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "formfx",
3
- "version": "1.0.0",
3
+ "version": "1.0.2",
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",
@@ -1,62 +0,0 @@
1
- var f=class{constructor(t,e){this.fx=t;this.options=e;this.container=document.createElement("div"),this.container.className="formfx-editor";}container;activeRuleIndex=null;mount(){this.options.mount.appendChild(this.container),this.render();}render(){let t=this.fx.exportRules();this.container.innerHTML=`
2
- <div class="formfx-editor-header">
3
- <div class="formfx-editor-title">FormFx Rule Editor</div>
4
- <div class="formfx-editor-actions">
5
- <button class="formfx-btn formfx-btn-primary" id="fx-add-rule">+ Add Rule</button>
6
- </div>
7
- </div>
8
- <div class="formfx-editor-body">
9
- <div class="formfx-rule-list" id="fx-rule-list"></div>
10
- <div class="formfx-rule-form" id="fx-rule-form"></div>
11
- </div>
12
- `,this.renderRuleList(t),this.renderRuleForm(t),this.container.querySelector("#fx-add-rule")?.addEventListener("click",()=>{this.addRule();});}renderRuleList(t){let e=this.container.querySelector("#fx-rule-list");e&&(e.innerHTML=t.map((i,r)=>`
13
- <div class="formfx-rule-item ${this.activeRuleIndex===r?"active":""}" data-index="${r}">
14
- <div class="formfx-rule-item-id">${i.id||"(no id)"}</div>
15
- <div class="formfx-rule-item-expr">if: ${i.if}</div>
16
- </div>
17
- `).join("")||'<div class="formfx-empty-state">No rules defined</div>',e.querySelectorAll(".formfx-rule-item").forEach(i=>{i.addEventListener("click",()=>{this.activeRuleIndex=parseInt(i.getAttribute("data-index")||"0"),this.render();});}));}renderRuleForm(t){let e=this.container.querySelector("#fx-rule-form");if(!e||this.activeRuleIndex===null||!t[this.activeRuleIndex]){e&&(e.innerHTML='<div class="formfx-empty-state">Select a rule to edit</div>');return}let i=t[this.activeRuleIndex];e.innerHTML=`
18
- <div class="formfx-field-group">
19
- <label class="formfx-label">Rule ID</label>
20
- <input type="text" class="formfx-input" id="fx-edit-id" value="${i.id||""}">
21
- </div>
22
- <div class="formfx-field-group">
23
- <label class="formfx-label">If Condition (DSL)</label>
24
- <textarea class="formfx-textarea" id="fx-edit-if" rows="3">${i.if}</textarea>
25
- </div>
26
-
27
- <div class="formfx-field-group">
28
- <label class="formfx-label">Then Effects</label>
29
- <div id="fx-then-list"></div>
30
- <button class="formfx-btn" id="fx-add-then">+ Add Effect</button>
31
- </div>
32
-
33
- <div class="formfx-field-group">
34
- <label class="formfx-label">Else Effects (Optional)</label>
35
- <div id="fx-else-list"></div>
36
- <button class="formfx-btn" id="fx-add-else">+ Add Effect</button>
37
- </div>
38
-
39
- <div style="margin-top: 40px; display: flex; justify-content: space-between;">
40
- <button class="formfx-btn formfx-btn-primary" id="fx-save-rule">Save Changes</button>
41
- <button class="formfx-btn formfx-btn-danger" id="fx-delete-rule">Delete Rule</button>
42
- </div>
43
-
44
- <div class="formfx-json-preview">
45
- <div class="formfx-label">JSON Preview (Readonly)</div>
46
- <div class="formfx-json-content">${JSON.stringify(i,null,2)}</div>
47
- </div>
48
- `,this.renderEffectList("then",i.then),this.renderEffectList("else",i.else||[]),e.querySelector("#fx-save-rule")?.addEventListener("click",()=>this.saveRule()),e.querySelector("#fx-delete-rule")?.addEventListener("click",()=>this.deleteRule()),e.querySelector("#fx-add-then")?.addEventListener("click",()=>this.addEffect("then")),e.querySelector("#fx-add-else")?.addEventListener("click",()=>this.addEffect("else"));}renderEffectList(t,e){let i=this.container.querySelector(`#fx-${t}-list`);i&&(i.innerHTML=e.map((r,s)=>{let n=Object.entries(r)[0]||["show",""],l=n[0],o=n[1];return `
49
- <div class="formfx-effect-row" data-type="${t}" data-index="${s}">
50
- <select class="formfx-select fx-effect-type" style="width: 120px;">
51
- <option value="show" ${l==="show"?"selected":""}>show</option>
52
- <option value="hide" ${l==="hide"?"selected":""}>hide</option>
53
- <option value="required" ${l==="required"?"selected":""}>require</option>
54
- <option value="disabled" ${l==="disabled"?"selected":""}>disabled</option>
55
- <option value="enable" ${l==="enable"?"selected":""}>enable</option>
56
- <option value="clear" ${l==="clear"?"selected":""}>clear</option>
57
- </select>
58
- <input type="text" class="formfx-input fx-effect-selector" placeholder="#id" value="${o}">
59
- <button class="formfx-btn formfx-btn-danger fx-remove-effect">\xD7</button>
60
- </div>
61
- `}).join(""),i.querySelectorAll(".fx-remove-effect").forEach((r,s)=>{r.addEventListener("click",()=>{e.splice(s,1),this.renderRuleForm(this.fx.exportRules());});}));}addRule(){let t=this.fx.exportRules(),e={id:`rule_${Date.now()}`,if:"true",then:[{show:""}]};t.push(e),this.activeRuleIndex=t.length-1,this.fx.importRules(t),this.render();}saveRule(){if(this.activeRuleIndex===null)return;this.fx.pause();let t=this.fx.exportRules(),e=t[this.activeRuleIndex];e.id=this.container.querySelector("#fx-edit-id").value,e.if=this.container.querySelector("#fx-edit-if").value;let i=r=>{let s=this.container.querySelectorAll(`.formfx-effect-row[data-type="${r}"]`),n=[];return s.forEach(l=>{let o=l.querySelector(".fx-effect-type").value,a=l.querySelector(".fx-effect-selector").value,d={};d[o]=a,n.push(d);}),n};e.then=i("then"),e.else=i("else"),e.else.length===0&&delete e.else,this.fx.importRules(t),this.fx.resume(),this.render();}deleteRule(){if(this.activeRuleIndex===null||!confirm("Are you sure you want to delete this rule?"))return;let t=this.fx.exportRules();t.splice(this.activeRuleIndex,1),this.activeRuleIndex=null,this.fx.importRules(t),this.render();}addEffect(t){if(this.activeRuleIndex===null)return;let e=this.fx.exportRules(),i=e[this.activeRuleIndex];t==="then"?i.then.push({show:""}):(i.else=i.else||[],i.else.push({show:""})),this.renderRuleForm(e);}};export{f as a};//# sourceMappingURL=chunk-6E5EWQVW.js.map
62
- //# sourceMappingURL=chunk-6E5EWQVW.js.map
@@ -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-6E5EWQVW.js","sourcesContent":["import { FormFx } from '../core/FormFx';\r\nimport { RuleEditorOptions, JSONRule } from '../types';\r\n\r\nexport class RuleEditor {\r\n private container: HTMLElement;\r\n private activeRuleIndex: number | null = null;\r\n\r\n constructor(\r\n private fx: FormFx,\r\n private options: RuleEditorOptions\r\n ) {\r\n this.container = document.createElement('div');\r\n this.container.className = 'formfx-editor';\r\n }\r\n\r\n mount(): void {\r\n this.options.mount.appendChild(this.container);\r\n this.render();\r\n }\r\n\r\n private render(): void {\r\n const rules = this.fx.exportRules();\r\n \r\n this.container.innerHTML = `\r\n <div class=\"formfx-editor-header\">\r\n <div class=\"formfx-editor-title\">FormFx Rule Editor</div>\r\n <div class=\"formfx-editor-actions\">\r\n <button class=\"formfx-btn formfx-btn-primary\" id=\"fx-add-rule\">+ Add Rule</button>\r\n </div>\r\n </div>\r\n <div class=\"formfx-editor-body\">\r\n <div class=\"formfx-rule-list\" id=\"fx-rule-list\"></div>\r\n <div class=\"formfx-rule-form\" id=\"fx-rule-form\"></div>\r\n </div>\r\n `;\r\n\r\n this.renderRuleList(rules);\r\n this.renderRuleForm(rules);\r\n\r\n this.container.querySelector('#fx-add-rule')?.addEventListener('click', () => {\r\n this.addRule();\r\n });\r\n }\r\n\r\n private renderRuleList(rules: JSONRule[]): void {\r\n const listEl = this.container.querySelector('#fx-rule-list');\r\n if (!listEl) return;\r\n\r\n listEl.innerHTML = rules.map((rule, index) => `\r\n <div class=\"formfx-rule-item ${this.activeRuleIndex === index ? 'active' : ''}\" data-index=\"${index}\">\r\n <div class=\"formfx-rule-item-id\">${rule.id || '(no id)'}</div>\r\n <div class=\"formfx-rule-item-expr\">if: ${rule.if}</div>\r\n </div>\r\n `).join('') || '<div class=\"formfx-empty-state\">No rules defined</div>';\r\n\r\n listEl.querySelectorAll('.formfx-rule-item').forEach(item => {\r\n item.addEventListener('click', () => {\r\n this.activeRuleIndex = parseInt(item.getAttribute('data-index') || '0');\r\n this.render();\r\n });\r\n });\r\n }\r\n\r\n private renderRuleForm(rules: JSONRule[]): void {\r\n const formEl = this.container.querySelector('#fx-rule-form');\r\n if (!formEl || this.activeRuleIndex === null || !rules[this.activeRuleIndex]) {\r\n if (formEl) formEl.innerHTML = '<div class=\"formfx-empty-state\">Select a rule to edit</div>';\r\n return;\r\n }\r\n\r\n const rule = rules[this.activeRuleIndex];\r\n formEl.innerHTML = `\r\n <div class=\"formfx-field-group\">\r\n <label class=\"formfx-label\">Rule ID</label>\r\n <input type=\"text\" class=\"formfx-input\" id=\"fx-edit-id\" value=\"${rule.id || ''}\">\r\n </div>\r\n <div class=\"formfx-field-group\">\r\n <label class=\"formfx-label\">If Condition (DSL)</label>\r\n <textarea class=\"formfx-textarea\" id=\"fx-edit-if\" rows=\"3\">${rule.if}</textarea>\r\n </div>\r\n \r\n <div class=\"formfx-field-group\">\r\n <label class=\"formfx-label\">Then Effects</label>\r\n <div id=\"fx-then-list\"></div>\r\n <button class=\"formfx-btn\" id=\"fx-add-then\">+ Add Effect</button>\r\n </div>\r\n\r\n <div class=\"formfx-field-group\">\r\n <label class=\"formfx-label\">Else Effects (Optional)</label>\r\n <div id=\"fx-else-list\"></div>\r\n <button class=\"formfx-btn\" id=\"fx-add-else\">+ Add Effect</button>\r\n </div>\r\n\r\n <div style=\"margin-top: 40px; display: flex; justify-content: space-between;\">\r\n <button class=\"formfx-btn formfx-btn-primary\" id=\"fx-save-rule\">Save Changes</button>\r\n <button class=\"formfx-btn formfx-btn-danger\" id=\"fx-delete-rule\">Delete Rule</button>\r\n </div>\r\n\r\n <div class=\"formfx-json-preview\">\r\n <div class=\"formfx-label\">JSON Preview (Readonly)</div>\r\n <div class=\"formfx-json-content\">${JSON.stringify(rule, null, 2)}</div>\r\n </div>\r\n `;\r\n\r\n this.renderEffectList('then', rule.then);\r\n this.renderEffectList('else', rule.else || []);\r\n\r\n // Events\r\n formEl.querySelector('#fx-save-rule')?.addEventListener('click', () => this.saveRule());\r\n formEl.querySelector('#fx-delete-rule')?.addEventListener('click', () => this.deleteRule());\r\n formEl.querySelector('#fx-add-then')?.addEventListener('click', () => this.addEffect('then'));\r\n formEl.querySelector('#fx-add-else')?.addEventListener('click', () => this.addEffect('else'));\r\n }\r\n\r\n private renderEffectList(type: 'then' | 'else', effects: any[]): void {\r\n const listEl = this.container.querySelector(`#fx-${type}-list`);\r\n if (!listEl) return;\r\n\r\n listEl.innerHTML = effects.map((eff, i) => {\r\n const entry = Object.entries(eff)[0] || ['show', ''];\r\n const effectType = entry[0];\r\n const selector = entry[1];\r\n\r\n return `\r\n <div class=\"formfx-effect-row\" data-type=\"${type}\" data-index=\"${i}\">\r\n <select class=\"formfx-select fx-effect-type\" style=\"width: 120px;\">\r\n <option value=\"show\" ${effectType === 'show' ? 'selected' : ''}>show</option>\r\n <option value=\"hide\" ${effectType === 'hide' ? 'selected' : ''}>hide</option>\r\n <option value=\"required\" ${effectType === 'required' ? 'selected' : ''}>require</option>\r\n <option value=\"disabled\" ${effectType === 'disabled' ? 'selected' : ''}>disabled</option>\r\n <option value=\"enable\" ${effectType === 'enable' ? 'selected' : ''}>enable</option>\r\n <option value=\"clear\" ${effectType === 'clear' ? 'selected' : ''}>clear</option>\r\n </select>\r\n <input type=\"text\" class=\"formfx-input fx-effect-selector\" placeholder=\"#id\" value=\"${selector}\">\r\n <button class=\"formfx-btn formfx-btn-danger fx-remove-effect\">×</button>\r\n </div>\r\n `;\r\n }).join('');\r\n\r\n listEl.querySelectorAll('.fx-remove-effect').forEach((btn, i) => {\r\n btn.addEventListener('click', () => {\r\n effects.splice(i, 1);\r\n this.renderRuleForm(this.fx.exportRules());\r\n });\r\n });\r\n }\r\n\r\n private addRule(): void {\r\n const rules = this.fx.exportRules();\r\n const newRule: JSONRule = {\r\n id: `rule_${Date.now()}`,\r\n if: 'true',\r\n then: [{ show: '' }]\r\n };\r\n rules.push(newRule);\r\n this.activeRuleIndex = rules.length - 1;\r\n this.fx.importRules(rules);\r\n this.render();\r\n }\r\n\r\n private saveRule(): void {\r\n if (this.activeRuleIndex === null) return;\r\n \r\n this.fx.pause(); // 編集適用中は pause\r\n\r\n const rules = this.fx.exportRules();\r\n const rule = rules[this.activeRuleIndex];\r\n\r\n rule.id = (this.container.querySelector('#fx-edit-id') as HTMLInputElement).value;\r\n rule.if = (this.container.querySelector('#fx-edit-if') as HTMLTextAreaElement).value;\r\n\r\n const readEffects = (type: 'then' | 'else') => {\r\n const rows = this.container.querySelectorAll(`.formfx-effect-row[data-type=\"${type}\"]`);\r\n const effects: any[] = [];\r\n rows.forEach(row => {\r\n const effectType = (row.querySelector('.fx-effect-type') as HTMLSelectElement).value;\r\n const selector = (row.querySelector('.fx-effect-selector') as HTMLInputElement).value;\r\n const obj: any = {};\r\n obj[effectType] = selector;\r\n effects.push(obj);\r\n });\r\n return effects;\r\n };\r\n\r\n rule.then = readEffects('then');\r\n rule.else = readEffects('else');\r\n if (rule.else.length === 0) delete rule.else;\r\n\r\n this.fx.importRules(rules);\r\n this.fx.resume();\r\n this.render();\r\n }\r\n\r\n private deleteRule(): void {\r\n if (this.activeRuleIndex === null || !confirm('Are you sure you want to delete this rule?')) return;\r\n const rules = this.fx.exportRules();\r\n rules.splice(this.activeRuleIndex, 1);\r\n this.activeRuleIndex = null;\r\n this.fx.importRules(rules);\r\n this.render();\r\n }\r\n\r\n private addEffect(type: 'then' | 'else'): void {\r\n if (this.activeRuleIndex === null) return;\r\n const rules = this.fx.exportRules();\r\n const rule = rules[this.activeRuleIndex];\r\n if (type === 'then') {\r\n rule.then.push({ show: '' });\r\n } else {\r\n rule.else = rule.else || [];\r\n rule.else.push({ show: '' });\r\n }\r\n this.renderRuleForm(rules);\r\n }\r\n}\r\n"]}