This commit is contained in:
2026-01-19 12:15:20 +00:00
parent 3bcabbf078
commit 7208a53d8f

View File

@@ -52,13 +52,15 @@ Follow this workflow strictly:
2) If stateful, extract logic into a custom hook file in src/hooks/use-<component>.ts.
3) Create JSON definition under src/components/json-definitions/<component>.json.
4) Create interface in src/lib/json-ui/interfaces/<component>.ts.
5) Provide export updates for:
5) Create config page schema under src/config/pages/<category>/<component-name-kebab>.json.
6) Update json-components-registry.json with a new entry for the component if missing.
7) Provide export updates for:
- src/hooks/index.ts (if hook exists)
- src/lib/json-ui/hooks-registry.ts (if hook exists)
- src/lib/json-ui/interfaces/index.ts
- src/lib/json-ui/json-components.ts
- src/components/<category>/index.ts
6) Indicate that TSX file should be deleted.
8) Indicate that TSX file should be deleted.
IMPORTANT:
- Return ONLY valid JSON. No Markdown or code fences.
@@ -69,6 +71,87 @@ IMPORTANT:
- Do NOT output any `jsonComponents` object or registry literal.
- Provide `diffs` with unified diff lines (one string per line) for each target file,
using the provided file contents as the "before" version.
- Include diffs for the config page schema file and json-components-registry.json.
Config page schema format (src/config/pages/<category>/<component-name-kebab>.json):
- Simple JSON-compatible component:
{{
"type": "ComponentName",
"props": {{ ... }}
}}
- Wrapper-required component (use when hooks/complex logic or not JSON-compatible):
{{
"type": "ComponentName",
"jsonCompatible": false,
"wrapperRequired": true,
"load": {{
"path": "@/components/<category>/ComponentName",
"export": "ComponentName"
}},
"props": {{ ... }},
"metadata": {{
"notes": "Contains hooks - needs wrapper"
}}
}}
JSON definition schema (src/components/json-definitions/<component>.json):
- Single UIComponent tree using this shape:
{{
"id": "component-id",
"type": "ComponentType",
"props": {{ ... }},
"className": "optional classes",
"style": {{ ... }},
"bindings": {{
"propName": {{
"source": "data.path",
"path": "optional.path",
"transform": "optional js expression"
}}
}},
"dataBinding": "data.path" | {{
"source": "data.path",
"path": "optional.path",
"transform": "optional js expression"
}},
"events": [{{ "event": "click", "actions": [{{ "id": "...", "type": "custom" }}] }}] |
{{ "click": {{ "action": "customActionId" }} }},
"conditional": {{
"if": "expression",
"then": {{ ... }} | [{{ ... }}, "..."] | "...",
"else": {{ ... }} | [{{ ... }}, "..."] | "..."
}},
"loop": {{
"source": "data.path",
"itemVar": "item",
"indexVar": "index"
}},
"children": "text" | [{{ ... }}, "..."]
}}
- Use nested UIComponents in children.
Registry entry format (json-components-registry.json) for the component if missing:
{{
"type": "ComponentName",
"name": "ComponentName",
"category": "layout|input|display|navigation|feedback|data|custom",
"canHaveChildren": true|false,
"description": "Short description",
"status": "supported",
"source": "atoms|molecules|organisms|ui|custom",
"jsonCompatible": true|false,
"wrapperRequired": true|false,
"load": {{
"path": "@/components/<category>/ComponentName",
"export": "ComponentName"
}},
"metadata": {{
"conversionDate": "YYYY-MM-DD",
"autoGenerated": true,
"notes": "Optional notes"
}}
}}
Omit optional fields when not applicable.
Return ONLY valid JSON with this shape:
{{
@@ -88,6 +171,10 @@ Return ONLY valid JSON with this shape:
"filePath": "src/lib/json-ui/interfaces/component-name.ts",
"source": "...typescript..."
}},
"configPageSchema": {{
"filePath": "src/config/pages/<category>/component-name.json",
"source": {{ ...json... }}
}},
"jsonComponentExport": {{
"filePath": "src/lib/json-ui/json-components.ts",
"source": "...typescript snippet..."
@@ -161,6 +248,12 @@ def _strip_code_fences(output: str) -> str:
return trimmed
def _to_kebab_case(name: str) -> str:
if not name:
return ""
return re.sub(r"([A-Z])", r"-\1", name).lower().lstrip("-")
def _extract_json_payload(output: str) -> str:
trimmed = _strip_code_fences(output)
start = trimmed.find("{")
@@ -263,6 +356,7 @@ def run_agent_for_component(
target: ComponentTarget, out_dir: Path, debug: bool = False
) -> Dict[str, Any]:
tsx = target.path.read_text(encoding="utf-8")
config_file_name = f"{_to_kebab_case(target.name)}.json"
existing_files = {
"src/lib/json-ui/json-components.ts": _read_existing_file(
out_dir, "src/lib/json-ui/json-components.ts"
@@ -274,6 +368,12 @@ def run_agent_for_component(
"src/lib/json-ui/hooks-registry.ts": _read_existing_file(
out_dir, "src/lib/json-ui/hooks-registry.ts"
),
"json-components-registry.json": _read_existing_file(
out_dir, "json-components-registry.json"
),
f"src/config/pages/{target.category}/{config_file_name}": _read_existing_file(
out_dir, f"src/config/pages/{target.category}/{config_file_name}"
),
f"src/components/{target.category}/index.ts": _read_existing_file(
out_dir, f"src/components/{target.category}/index.ts"
),
@@ -425,7 +525,7 @@ def _apply_unified_diff(original: str, diff_lines: List[str]) -> str:
def write_output(out_dir: Path, data: Dict[str, Any], target: ComponentTarget) -> None:
component_name = data.get("componentName") or "unknown-component"
component_name = data.get("componentName") or target.name or "unknown-component"
report_path = out_dir / "migration-reports" / f"{component_name}.json"
report_path.parent.mkdir(parents=True, exist_ok=True)