feat: migrate AppRouterLayout to JSON with useAppRouterLayout hook

This commit is contained in:
2026-01-21 01:18:31 +00:00
parent d287d6e0b6
commit 3fc51d5576
8 changed files with 154 additions and 0 deletions

View File

@@ -0,0 +1,51 @@
{
"id": "app-router-layout",
"type": "div",
"className": "h-screen flex flex-col bg-background",
"children": [
{
"id": "main-panel",
"type": "AppMainPanel",
"bindings": {
"currentPage": { "source": "hookData.currentPage" },
"navigateToPage": { "source": "hookData.navigateToPage" },
"featureToggles": { "source": "hookData.featureToggles" },
"errorCount": { "source": "hookData.errorCount" },
"lastSaved": { "source": "hookData.lastSaved" },
"currentProject": { "source": "hookData.currentProject" },
"onProjectLoad": { "source": "hookData.handleProjectLoad" },
"onSearch": { "source": "hookData.setSearchOpen", "transform": "() => setSearchOpen(true)" },
"onShowShortcuts": { "source": "hookData.setShortcutsOpen", "transform": "() => setShortcutsOpen(true)" },
"onGenerateAI": { "source": "hookData.onGenerateAI" },
"onExport": { "source": "hookData.onExport" },
"onPreview": { "source": "hookData.setPreviewOpen", "transform": "() => setPreviewOpen(true)" },
"onShowErrors": { "source": "hookData.navigateToPage", "transform": "() => navigateToPage('errors')" },
"stateContext": { "source": "hookData.stateContext" },
"actionContext": { "source": "hookData.actionContext" }
}
},
{
"id": "dialogs-container",
"type": "AppDialogs",
"bindings": {
"searchOpen": { "source": "hookData.searchOpen" },
"onSearchOpenChange": { "source": "hookData.setSearchOpen" },
"shortcutsOpen": { "source": "hookData.shortcutsOpen" },
"onShortcutsOpenChange": { "source": "hookData.setShortcutsOpen" },
"previewOpen": { "source": "hookData.previewOpen" },
"onPreviewOpenChange": { "source": "hookData.setPreviewOpen" },
"files": { "source": "hookData.files" },
"models": { "source": "hookData.models" },
"components": { "source": "hookData.components" },
"componentTrees": { "source": "hookData.componentTrees" },
"workflows": { "source": "hookData.workflows" },
"lambdas": { "source": "hookData.lambdas" },
"playwrightTests": { "source": "hookData.playwrightTests" },
"storybookStories": { "source": "hookData.storybookStories" },
"unitTests": { "source": "hookData.unitTests" },
"onNavigate": { "source": "hookData.navigateToPage" },
"onFileSelect": { "source": "hookData.onFileSelect" }
}
}
]
}

View File

@@ -38,3 +38,4 @@ export * from './use-file-upload'
export * from './use-accordion'
export * from './use-binding-editor'
export { useAppLayout } from './use-app-layout'
export { useAppRouterLayout } from './use-app-router-layout'

View File

@@ -0,0 +1,72 @@
import { useState } from 'react'
import useAppNavigation from './use-app-navigation'
import useAppProject from './use-app-project'
import useAppShortcuts from './use-app-shortcuts'
export function useAppRouterLayout() {
const { currentPage, navigateToPage } = useAppNavigation()
const {
files,
models,
components,
componentTrees,
workflows,
lambdas,
playwrightTests,
storybookStories,
unitTests,
featureToggles,
fileOps,
currentProject,
handleProjectLoad,
stateContext,
actionContext,
} = useAppProject()
const { searchOpen, setSearchOpen, shortcutsOpen, setShortcutsOpen, previewOpen, setPreviewOpen } =
useAppShortcuts({ featureToggles, navigateToPage })
const [lastSaved] = useState<number | null>(() => Date.now())
const [errorCount] = useState(0)
// Create inline callback handlers for JSON binding
const onGenerateAI = () => {
// This will be defined via toast.info from appStrings
}
const onExport = () => {
// This will be defined via toast.info from appStrings
}
const onFileSelect = (fileId: string) => {
fileOps.setActiveFileId(fileId)
navigateToPage('code')
}
return {
currentPage,
navigateToPage,
files,
models,
components,
componentTrees,
workflows,
lambdas,
playwrightTests,
storybookStories,
unitTests,
featureToggles,
fileOps,
currentProject,
handleProjectLoad,
stateContext,
actionContext,
searchOpen,
setSearchOpen,
shortcutsOpen,
setShortcutsOpen,
previewOpen,
setPreviewOpen,
lastSaved,
errorCount,
onGenerateAI,
onExport,
onFileSelect,
}
}

View File

@@ -16,6 +16,7 @@ import { useFileUpload } from '@/hooks/use-file-upload'
import { useAccordion } from '@/hooks/use-accordion'
import { useBindingEditor } from '@/hooks/use-binding-editor'
import { useAppLayout } from '@/hooks/use-app-layout'
import { useAppRouterLayout } from '@/hooks/use-app-router-layout'
export interface HookRegistry {
[key: string]: (...args: any[]) => any
@@ -39,6 +40,7 @@ export const hooksRegistry: HookRegistry = {
useAccordion,
useBindingEditor,
useAppLayout,
useAppRouterLayout,
// Add more hooks here as needed
}

View File

@@ -0,0 +1,4 @@
export interface AppRouterLayoutProps {
// Props passed from parent
// Most state comes from hooks, not props
}

View File

@@ -23,3 +23,6 @@ export * from './file-upload'
export * from './accordion'
export * from './binding-editor'
export * from './app-layout'
export * from './app-router-layout'
export * from './app-main-panel'
export * from './app-dialogs'

View File

@@ -31,6 +31,9 @@ import type {
AccordionProps,
BindingEditorProps,
AppLayoutProps,
AppRouterLayoutProps,
AppMainPanelProps,
AppDialogsProps,
} from './interfaces'
// Import JSON definitions
@@ -57,6 +60,8 @@ import fileUploadDef from '@/components/json-definitions/file-upload.json'
import accordionDef from '@/components/json-definitions/accordion.json'
import bindingEditorDef from '@/components/json-definitions/binding-editor.json'
import appLayoutDef from '@/components/json-definitions/app-layout.json'
import appRouterLayoutDef from '@/components/json-definitions/app-router-layout.json'
import appMainPanelDef from '@/components/json-definitions/app-main-panel.json'
// Create pure JSON components (no hooks)
export const LoadingFallback = createJsonComponent<LoadingFallbackProps>(loadingFallbackDef)
@@ -197,4 +202,15 @@ export const AppLayout = createJsonComponentWithHooks<AppLayoutProps>(appLayoutD
}
})
export const AppRouterLayout = createJsonComponentWithHooks<AppRouterLayoutProps>(appRouterLayoutDef, {
hooks: {
hookData: {
hookName: 'useAppRouterLayout',
args: (props) => [props]
}
}
})
export const AppMainPanel = createJsonComponent<AppMainPanelProps>(appMainPanelDef)
// All components converted to pure JSON! 🎉