# FlowGram.AI - Demo Fixed Layout

Best practices demo for fixed layout

## Installation

```shell
npx @flowgram.ai/create-app@latest fixed-layout
```

## Project Overview

### Core Tech Stack
- Frontend Framework: React 18 + TypeScript
- Build Tool: Rsbuild (a modern build tool based on Rspack)
- Styling: Less + Styled Components + CSS Variables
- UI Component Library: Semi Design (@douyinfe/semi-ui)
- State Management: Editor framework developed in-house by Flowgram
- Dependency Injection: Inversify


### Core Dependencies

- @flowgram.ai/fixed-layout-editor: Core dependency for the fixed-layout editor
- @flowgram.ai/fixed-semi-materials: Semi Design materials library
- @flowgram.ai/form-materials: Form materials library
- @flowgram.ai/group-plugin: Group plugin
- @flowgram.ai/minimap-plugin: Minimap plugin
- @flowgram.ai/export-plugin: Download/export plugin

## Code Overview

```
src/
├── app.tsx                    # Application entry component
├── editor.tsx                 # Main editor component
├── index.ts                   # Module export entry
├── initial-data.ts            # Initial data configuration
├── type.d.ts                  # Global type declarations
│
├── assets/                    # Static assets
│   ├── icon-mouse.tsx         # Mouse icon component
│   └── icon-pad.tsx           # Trackpad icon component
│
├── components/                # Common components library
│   ├── index.ts               # Components export entry
│   ├── node-list.tsx          # Node list component
│   │
│   ├── agent-adder/           # Agent adder component
│   │   └── index.tsx
│   ├── agent-label/           # Agent label component
│   │   └── index.tsx
│   ├── base-node/             # Base node component
│   │   ├── index.tsx
│   │   └── styles.tsx
│   ├── branch-adder/          # Branch adder component
│   │   ├── index.tsx
│   │   └── styles.tsx
│   ├── drag-node/             # Draggable node component
│   │   ├── index.tsx
│   │   └── styles.tsx
│   ├── node-adder/            # Node adder component
│   │   ├── index.tsx
│   │   ├── styles.tsx
│   │   └── utils.ts
│   ├── selector-box-popover/  # Selection box popover component
│   │   └── index.tsx
│   ├── sidebar/               # Sidebar components
│   │   ├── index.tsx
│   │   ├── sidebar-node-renderer.tsx
│   │   ├── sidebar-provider.tsx
│   │   └── sidebar-renderer.tsx
│   └── tools/                 # Toolbar components
│       ├── index.tsx
│       ├── styles.tsx
│       ├── fit-view.tsx       # Fit view tool
│       ├── minimap-switch.tsx # Minimap toggle
│       ├── minimap.tsx        # Minimap component
│       ├── readonly.tsx       # Readonly mode toggle
│       ├── run.tsx            # Run tool
│       ├── save.tsx           # Save tool
│       ├── switch-vertical.tsx # Vertical layout toggle
│       └── zoom-select.tsx    # Zoom selector
│
├── context/                   # React Context state management
│   ├── index.ts               # Context export entry
│   ├── node-render-context.ts # Node render context
│   └── sidebar-context.ts     # Sidebar context
│
├── form-components/           # Form components library
│   ├── index.ts               # Export entry for form components
│   ├── feedback.tsx           # Feedback component
│   │
│   ├── form-content/          # Form content components
│   │   ├── index.tsx
│   │   └── styles.tsx
│   ├── form-header/           # Form header components
│   │   ├── index.tsx
│   │   ├── styles.tsx
│   │   ├── title-input.tsx
│   │   └── utils.tsx
│   ├── form-inputs/           # Form input components
│   │   ├── index.tsx
│   │   └── styles.tsx
│   ├── form-item/             # Form item component
│   │   ├── index.css
│   │   └── index.tsx
│   ├── form-outputs/          # Form output components
│   │   ├── index.tsx
│   │   └── styles.tsx
│   └── properties-edit/       # Property editing components
│       ├── index.tsx
│       ├── property-edit.tsx
│       └── styles.tsx
│
├── hooks/                     # Custom React hooks
│   ├── index.ts               # Hooks export entry
│   ├── use-editor-props.ts    # Hook for editor properties
│   ├── use-is-sidebar.ts      # Hook for sidebar state
│   └── use-node-render-context.ts # Hook for node render context
│
├── nodes/                     # Flow node definitions
│   ├── index.ts               # Node registry
│   ├── default-form-meta.tsx  # Default form metadata
│   │
│   ├── agent/                 # Agent node type
│   │   ├── index.ts
│   │   ├── agent.ts
│   │   ├── agent-llm.ts
│   │   ├── agent-memory.ts
│   │   ├── agent-tools.ts
│   │   ├── memory.ts
│   │   └── tool.ts
│   ├── break-loop/            # Break loop node
│   │   ├── index.ts
│   │   └── form-meta.tsx
│   ├── case/                  # Case branch node
│   │   ├── index.ts
│   │   └── form-meta.tsx
│   ├── case-default/          # Default case node
│   │   ├── index.ts
│   │   └── form-meta.tsx
│   ├── catch-block/           # Exception catch block node
│   │   ├── index.ts
│   │   └── form-meta.tsx
│   ├── end/                   # End node
│   │   ├── index.ts
│   │   └── form-meta.tsx
│   ├── if/                    # Conditional node
│   │   └── index.ts
│   ├── if-block/              # Conditional block node
│   │   ├── index.ts
│   │   └── form-meta.tsx
│   ├── llm/                   # LLM node
│   │   └── index.ts
│   ├── loop/                  # Loop node
│   │   ├── index.ts
│   │   └── form-meta.tsx
│   ├── start/                 # Start node
│   │   ├── index.ts
│   │   └── form-meta.tsx
│   ├── switch/                # Switch branch node
│   │   └── index.ts
│   └── trycatch/              # Try-Catch node
│       ├── index.ts
│       └── form-meta.tsx
│
├── plugins/                   # Plugin system
│   ├── index.ts               # Plugins export entry
│   │
│   ├── clipboard-plugin/      # Clipboard plugin
│   │   └── create-clipboard-plugin.ts
│   ├── group-plugin/          # Group plugin
│   │   ├── index.ts
│   │   ├── group-box-header.tsx
│   │   ├── group-node.tsx
│   │   ├── group-note.tsx
│   │   ├── group-tools.tsx
│   │   ├── icons/
│   │   │   └── index.tsx
│   │   └── multilang-textarea-editor/ # Multi-language textarea editor
│   │       ├── index.css
│   │       ├── index.tsx
│   │       └── base-textarea.tsx
│   └── variable-panel-plugin/ # Variable panel plugin
│       ├── index.ts
│       ├── variable-panel-layer.tsx
│       ├── variable-panel-plugin.ts
│       └── components/
│           ├── full-variable-list.tsx
│           ├── global-variable-editor.tsx
│           └── variable-panel.tsx
│
├── services/                  # Services layer
│   ├── index.ts
│   └── custom-service.ts      # Custom service
│
├── shortcuts/                 # Shortcuts system
│   ├── index.ts
│   ├── constants.ts           # Shortcut constants
│   └── utils.ts               # Shortcut utilities
│
└── typings/                   # Type definitions
    ├── index.ts               # Types export entry
    ├── json-schema.ts         # JSON Schema types
    └── node.ts                # Node type definitions
```

## Architecture Design Analysis

### Overall Architecture Pattern

This project adopts a layered architecture combined with modular design:

1. Presentation Layer
    - Component layer: responsible for UI rendering and user interactions
    - Tools layer: provides editor tool features

2. Business Logic Layer
    - Node system: defines the behavior and properties of various flow nodes
    - Plugin system: provides extensible functional modules
    - Services layer: handles business logic and data operations

3. Data Layer
    - Context state management: manages global application state
    - Type system: ensures consistency of data structures

### Key Design Patterns

#### 1. Provider Pattern
```typescript
// The main editor component uses multiple nested Providers
<FixedLayoutEditorProvider {...editorProps}>
  <SidebarProvider>
    <EditorRenderer />
    <DemoTools />
    <SidebarRenderer />
  </SidebarProvider>
  </FixedLayoutEditorProvider>
```

Use cases:
- `FixedLayoutEditorProvider`: provides core editor features and state
- `SidebarProvider`: manages sidebar visibility and the selected node

#### 2. Registry Pattern
```typescript
export const FlowNodeRegistries: FlowNodeRegistry[] = [
  StartNodeRegistry,
  EndNodeRegistry,
  SwitchNodeRegistry,
  LLMNodeRegistry,
  // ... more node types
];
```

Advantages:
- Supports dynamic registration of node types
- Easy to extend with new node types
- Decouples node type definitions

#### 3. Plugin Pattern
```typescript
plugins: () => [
  createMinimapPlugin({...}),
  createGroupPlugin({...}),
  createClipboardPlugin(),
  createVariablePanelPlugin({}),
]
```

Plugin system highlights:
- Minimap plugin: provides a canvas minimap
- Group plugin: supports node grouping and management
- Clipboard plugin: enables copy and paste
- Variable panel plugin: provides a UI for variable management

#### 4. Factory Pattern
Widely used in node creation and configuration:
```typescript
getNodeDefaultRegistry(type) {
  return {
    type,
    meta: {
      defaultExpanded: true,
    },
  };
}
```

#### 5. Observer Pattern
Implemented via the history system:
```typescript
history: {
  enable: true,
  enableChangeNode: true,
  onApply: debounce((ctx, opt) => {
    console.log('auto save: ', ctx.document.toJSON());
  }, 100),
}
```

#### 6. Strategy Pattern
Reflected in the materials system:
```typescript
materials: {
  components: {
    ...defaultFixedSemiMaterials,
    [FlowRendererKey.ADDER]: NodeAdder,
    [FlowRendererKey.BRANCH_ADDER]: BranchAdder,
    // Different render strategies can be swapped by key
  }
}
```

### State Management Architecture

#### Context System Design
The project uses multiple dedicated Contexts to manage different domains of state:

1. SidebarContext: manages sidebar state
```typescript
export const SidebarContext = React.createContext<{
  visible: boolean;
  nodeId?: string;
  setNodeId: (node: string | undefined) => void;
}>({ visible: false, setNodeId: () => {} });
```

2. NodeRenderContext: manages state related to node rendering
3. IsSidebarContext: simple boolean state

#### Custom Hooks
- `useEditorProps`: centralizes all editor configuration props
- `useIsSidebar`: determines whether the current environment is the sidebar
- `useNodeRenderContext`: gets the node render context

### Component Architecture

#### Component Layering
1. Base components
    - `BaseNode`: base rendering component for all nodes
    - `DragNode`: node component in drag state

2. Functional components
    - Adders: `NodeAdder`, `BranchAdder`, `AgentAdder`
    - Tools: zoom, save, run, and other utilities

3. Container components
    - `Sidebar`: sidebar container and its subcomponents
    - `Tools`: toolbar container

### Data Flow Architecture

#### Initial Data Structure
The project defines a complete initial flow dataset, including examples of multiple node types:
- Start node: entry point of the flow, defines output parameters
- Agent node: contains LLM, Memory, and Tools subcomponents
- LLM node: large language model processing node
- Switch node: conditional branch node
- Loop node: loop processing node
- TryCatch node: exception handling node
- End node: end of the flow

#### Data Transformation Mechanism
```typescript
fromNodeJSON(node, json) {
  return json; // Transform logic on data import
},
toNodeJSON(node, json) {
  return json; // Transform logic on data export
}
```
