Files
low-code-react-app-b/PROPS_CONFIG_GUIDE.md

7.7 KiB

Props Configuration Guide

Overview

The CodeForge application now supports dynamic component props configuration through the pages.json file. This declarative approach eliminates the need to modify App.tsx when adding or updating component props, making the system more maintainable and scalable.

Architecture

Key Files

  1. src/config/pages.json - Declarative page and props configuration
  2. src/config/page-loader.ts - Props resolution logic and interfaces
  3. src/App.tsx - Consumes the configuration and renders pages

Props Configuration Schema

Basic Props Structure

{
  "id": "example-page",
  "component": "ExampleComponent",
  "props": {
    "state": ["stateKey1", "stateKey2"],
    "actions": ["actionPropName:actionFunctionName"]
  }
}

Props Configuration Options

state Array

Maps application state to component props. Supports two formats:

  1. Direct mapping (prop name = state key):

    "state": ["files", "models", "theme"]
    

    Results in: { files, models, theme }

  2. Renamed mapping (prop name : state key):

    "state": ["trees:componentTrees", "config:flaskConfig"]
    

    Results in: { trees: componentTrees, config: flaskConfig }

actions Array

Maps action functions (handlers/setters) to component props. Uses format:

"actions": ["propName:functionName"]

Example:

"actions": [
  "onModelsChange:setModels",
  "onFileSelect:setActiveFileId"
]

Resizable Page Configuration

For pages with split-panel layouts (e.g., File Explorer + Code Editor):

{
  "id": "code",
  "component": "CodeEditor",
  "requiresResizable": true,
  "props": {
    "state": ["files", "activeFileId"],
    "actions": ["onFileChange:handleFileChange"]
  },
  "resizableConfig": {
    "leftComponent": "FileExplorer",
    "leftProps": {
      "state": ["files", "activeFileId"],
      "actions": ["onFileSelect:setActiveFileId"]
    },
    "leftPanel": {
      "defaultSize": 20,
      "minSize": 15,
      "maxSize": 30
    },
    "rightPanel": {
      "defaultSize": 80
    }
  }
}

Available State Keys

The following state variables are available in the state context:

  • files - Project files
  • models - Data models
  • components - Component definitions
  • componentTrees - Component tree structures
  • workflows - Workflow definitions
  • lambdas - Lambda function definitions
  • theme - Theme configuration
  • playwrightTests - Playwright test definitions
  • storybookStories - Storybook story definitions
  • unitTests - Unit test definitions
  • flaskConfig - Flask API configuration
  • nextjsConfig - Next.js project configuration
  • npmSettings - NPM package settings
  • featureToggles - Feature toggle states
  • activeFileId - Currently selected file ID

Available Actions

The following action functions are available in the action context:

  • handleFileChange - Update file content
  • setActiveFileId - Set active file
  • handleFileClose - Close a file
  • handleFileAdd - Add new file
  • setModels - Update models
  • setComponents - Update components
  • setComponentTrees - Update component trees
  • setWorkflows - Update workflows
  • setLambdas - Update lambdas
  • setTheme - Update theme
  • setPlaywrightTests - Update Playwright tests
  • setStorybookStories - Update Storybook stories
  • setUnitTests - Update unit tests
  • setFlaskConfig - Update Flask config
  • setNextjsConfig - Update Next.js config
  • setNpmSettings - Update NPM settings
  • setFeatureToggles - Update feature toggles

Examples

Simple Component (No Props)

{
  "id": "docs",
  "title": "Documentation",
  "component": "DocumentationView",
  "props": {}
}

Component with State Only

{
  "id": "models",
  "title": "Models",
  "component": "ModelDesigner",
  "props": {
    "state": ["models"]
  }
}

Component with State and Actions

{
  "id": "models",
  "title": "Models",
  "component": "ModelDesigner",
  "props": {
    "state": ["models"],
    "actions": ["onModelsChange:setModels"]
  }
}

Component with Renamed Props

{
  "id": "flask",
  "title": "Flask API",
  "component": "FlaskDesigner",
  "props": {
    "state": ["config:flaskConfig"],
    "actions": ["onConfigChange:setFlaskConfig"]
  }
}

Dashboard with Multiple State Props

{
  "id": "dashboard",
  "title": "Dashboard",
  "component": "ProjectDashboard",
  "props": {
    "state": [
      "files",
      "models",
      "components",
      "theme",
      "playwrightTests",
      "storybookStories",
      "unitTests",
      "flaskConfig"
    ]
  }
}

Adding a New Page

To add a new page with props configuration:

  1. Add the page to pages.json:

    {
      "id": "new-page",
      "title": "New Feature",
      "icon": "Star",
      "component": "NewFeatureComponent",
      "enabled": true,
      "order": 21,
      "props": {
        "state": ["relevantState"],
        "actions": ["onAction:setRelevantState"]
      }
    }
    
  2. Add the component to the lazy import map in App.tsx:

    const componentMap: Record<string, React.LazyExoticComponent<any>> = {
      // ... existing components
      NewFeatureComponent: lazy(() => import('@/components/NewFeatureComponent').then(m => ({ default: m.NewFeatureComponent }))),
    }
    
  3. Optionally add to feature toggles (if applicable):

    {
      "toggleKey": "newFeature"
    }
    

That's it! No need to modify the getPropsForComponent function or other logic in App.tsx.

Benefits

  1. Declarative Configuration - All page configs in one place
  2. No Code Changes - Add/modify pages without touching App.tsx logic
  3. Type Safety - TypeScript interfaces ensure configuration validity
  4. Maintainability - Easy to understand and modify page props
  5. Scalability - Simple to add new pages and props
  6. Consistency - Standardized prop resolution across all pages

Migration from Old System

The old hardcoded propsMap in getPropsForComponent has been replaced with dynamic resolution using resolveProps(). The configuration in pages.json now drives all prop mapping.

Before (Hardcoded in App.tsx)

const propsMap: Record<string, any> = {
  'ModelDesigner': {
    models,
    onModelsChange: setModels,
  },
  // ... 20+ more entries
}

After (Declarative in pages.json)

{
  "id": "models",
  "component": "ModelDesigner",
  "props": {
    "state": ["models"],
    "actions": ["onModelsChange:setModels"]
  }
}

Future Enhancements

Potential extensions to the props configuration system:

  1. Computed Props - Props derived from multiple state values
  2. Prop Transformations - Map/filter/reduce operations on state
  3. Conditional Props - Props based on feature toggles or user state
  4. Default Values - Fallback values for missing state
  5. Validation Rules - Runtime prop validation from schema
  6. Hook Configuration - Custom hooks to inject into components
  7. Event Handlers - Declarative event handler composition

Troubleshooting

Props not being passed to component

  1. Check that the state/action key exists in the context objects
  2. Verify the prop name mapping is correct (before:after colon)
  3. Ensure the page is enabled and not filtered by feature toggles
  4. Check browser console for resolution errors

Component not rendering

  1. Verify the component is added to the componentMap in App.tsx
  2. Check that the component name matches exactly (case-sensitive)
  3. Ensure the component export matches the import pattern

State updates not working

  1. Verify the action function name is correct
  2. Check that the setter is using functional updates for array/object state
  3. Ensure the action is properly mapped in the action context