Skip to content

Navigation Menu

Sign in
Sign up

Repository files navigation

FlowGram.AI - Demo Free Layout

Best-practice demo for free layout

Installation

npx @flowgram.ai/create-app@latest free-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 library: Semi Design (@douyinfe/semi-ui)
  • State management: Flowgram’s in-house editor framework
  • Dependency injection: Inversify

Core Dependencies

  • @flowgram.ai/free-layout-editor: Core dependency for the free layout editor
  • @flowgram.ai/free-snap-plugin: Auto-alignment and guide-lines plugin
  • @flowgram.ai/free-lines-plugin: Connection line rendering plugin
  • @flowgram.ai/free-node-panel-plugin: Node add-panel rendering plugin
  • @flowgram.ai/minimap-plugin: Minimap plugin
  • @flowgram.ai/free-container-plugin: Sub-canvas plugin
  • @flowgram.ai/free-group-plugin: Grouping plugin
  • @flowgram.ai/form-materials: Form materials
  • @flowgram.ai/runtime-interface: Runtime interfaces
  • @flowgram.ai/runtime-js: JS runtime module
  • @flowgram.ai/panel-manager-plugin: Sidebar panel management

Code Guide

Directory Structure

src/
├── app.tsx # Application entry file
├── editor.tsx # Main editor component
├── initial-data.ts # Initial data configuration
├── assets/ # Static assets
├── components/ # Component library
│ ├── index.ts
│ ├── add-node/ # Add-node component
│ ├── base-node/ # Base node components
│ ├── comment/ # Comment components
│ ├── group/ # Group components
│ ├── line-add-button/ # Connection add button
│ ├── node-menu/ # Node menu
│ ├── node-panel/ # Node add panel
│ ├── selector-box-popover/ # Selection box popover
│ ├── sidebar/ # Sidebar
│ ├── testrun/ # Test-run module
│ │ ├── hooks/ # Test-run hooks
│ │ ├── node-status-bar/ # Node status bar
│ │ ├── testrun-button/ # Test-run button
│ │ ├── testrun-form/ # Test-run form
│ │ ├── testrun-json-input/ # JSON input component
│ │ └── testrun-panel/ # Test-run panel
│ └── tools/ # Utility components
├── context/ # React Context
│ ├── node-render-context.ts # Current rendering node context
│ ├── sidebar-context # Sidebar context
├── form-components/ # Form component library
│ ├── form-content/ # Form content
│ ├── form-header/ # Form header
│ ├── form-inputs/ # Form inputs
│ └── form-item/ # Form item
│ └── feedback.tsx # Validation error rendering
├── hooks/
│ ├── index.ts
│ ├── use-editor-props.tsx # Editor props hook
│ ├── use-is-sidebar.ts # Sidebar state hook
│ ├── use-node-render-context.ts # Node render context hook
│ └── use-port-click.ts # Port click hook
├── nodes/ # Node definitions
│ ├── index.ts
│ ├── constants.ts # Node constants
│ ├── default-form-meta.ts # Default form metadata
│ ├── block-end/ # Block end node
│ ├── block-start/ # Block start node
│ ├── break/ # Break node
│ ├── code/ # Code node
│ ├── comment/ # Comment node
│ ├── condition/ # Condition node
│ ├── continue/ # Continue node
│ ├── end/ # End node
│ ├── group/ # Group node
│ ├── http/ # HTTP node
│ ├── llm/ # LLM node
│ ├── loop/ # Loop node
│ ├── start/ # Start node
│ └── variable/ # Variable node
├── plugins/ # Plugin system
│ ├── index.ts
│ ├── context-menu-plugin/ # Right-click context menu plugin
│ ├── runtime-plugin/ # Runtime plugin
│ │ ├── client/ # Client
│ │ │ ├── browser-client/ # Browser client
│ │ │ └── server-client/ # Server client
│ │ └── runtime-service/ # Runtime service
│ └── variable-panel-plugin/ # Variable panel plugin
│ └── components/ # Variable panel components
├── services/ # Service layer
│ ├── index.ts
│ └── custom-service.ts # Custom service
├── shortcuts/ # Shortcuts system
│ ├── index.ts
│ ├── constants.ts # Shortcut constants
│ ├── shortcuts.ts # Shortcut definitions
│ ├── type.ts # Type definitions
│ ├── collapse/ # Collapse shortcut
│ ├── copy/ # Copy shortcut
│ ├── delete/ # Delete shortcut
│ ├── expand/ # Expand shortcut
│ ├── paste/ # Paste shortcut
│ ├── select-all/ # Select-all shortcut
│ ├── zoom-in/ # Zoom-in shortcut
│ └── zoom-out/ # Zoom-out shortcut
├── styles/ # Styles
├── typings/ # Type definitions
│ ├── index.ts
│ ├── json-schema.ts # JSON Schema types
│ └── node.ts # Node type definitions
└── utils/ # Utility functions
 ├── index.ts
 └── on-drag-line-end.ts # Handle end of drag line

Key Directory Functions

1. /components - Component Library

  • base-node: Base rendering components for all nodes
  • testrun: Complete test-run module, including status bar, form, and panel
  • sidebar: Sidebar components providing tools and property panels
  • node-panel: Node add panel with drag-to-add capability

2. /nodes - Node System

Each node type has its own directory, including:

  • Node registration (index.ts)
  • Form metadata (form-meta.ts)
  • Node-specific components and logic

3. /plugins - Plugin System

  • runtime-plugin: Supports both browser and server modes
  • context-menu-plugin: Right-click context menu
  • variable-panel-plugin: Variable management panel

4. /shortcuts - Shortcuts System

Complete keyboard shortcut support, including:

  • Basic actions: copy, paste, delete, select-all
  • View actions: zoom-in, zoom-out, collapse, expand
  • Each shortcut has its own implementation module

Application Architecture

Core Design Patterns

1. Plugin Architecture

Highly modular plugin system; each feature is an independent plugin:

plugins: () => [
 createFreeLinesPlugin({ renderInsideLine: LineAddButton }),
 createMinimapPlugin({ /* config */ }),
 createFreeSnapPlugin({ /* alignment config */ }),
 createFreeNodePanelPlugin({ renderer: NodePanel }),
 createContainerNodePlugin({}),
 createFreeGroupPlugin({ groupNodeRender: GroupNodeRender }),
 createContextMenuPlugin({}),
 createRuntimePlugin({ mode: 'browser' }),
 createVariablePanelPlugin({})
]

2. Node Registry Pattern

Manage different workflow node types via a registry:

export const nodeRegistries: FlowNodeRegistry[] = [
 ConditionNodeRegistry, // Condition node
 StartNodeRegistry, // Start node
 EndNodeRegistry, // End node
 LLMNodeRegistry, // LLM node
 LoopNodeRegistry, // Loop node
 CommentNodeRegistry, // Comment node
 HTTPNodeRegistry, // HTTP node
 CodeNodeRegistry, // Code node
 // ... more node types
];

3. Dependency Injection

Use Inversify for service DI:

onBind: ({ bind }) => {
 bind(CustomService).toSelf().inSingletonScope();
}

Core Features

1. Editor Configuration System

useEditorProps is the configuration center of the editor:

export function useEditorProps(
 initialData: FlowDocumentJSON,
 nodeRegistries: FlowNodeRegistry[]
): FreeLayoutProps {
 return useMemo<FreeLayoutProps>(() => ({
 background: true, // Background grid
 readonly: false, // Readonly mode
 initialData, // Initial data
 nodeRegistries, // Node registries
 // Core feature configs
 playground: { preventGlobalGesture: true /* Prevent Mac browser swipe gestures */ },
 nodeEngine: { enable: true },
 variableEngine: { enable: true },
 history: { enable: true, enableChangeNode: true },
 // Business rules
 canAddLine: (ctx, fromPort, toPort) => { /* Connection rules */ },
 canDeleteLine: (ctx, line) => { /* Line deletion rules */ },
 canDeleteNode: (ctx, node) => { /* Node deletion rules */ },
 canDropToNode: (ctx, params) => { /* Drag-and-drop rules */ },
 // Plugins
 plugins: () => [/* Plugin list */],
 // Events
 onContentChange: debounce((ctx, event) => { /* Auto save */ }, 1000),
 onInit: (ctx) => { /* Initialization */ },
 onAllLayersRendered: (ctx) => { /* After render */ }
 }), []);
}

2. Node Type System

The app supports multiple workflow node types:

export enum WorkflowNodeType {
 Start = 'start', // Start node
 End = 'end', // End node
 LLM = 'llm', // Large language model node
 HTTP = 'http', // HTTP request node
 Code = 'code', // Code execution node
 Variable = 'variable', // Variable node
 Condition = 'condition', // Conditional node
 Loop = 'loop', // Loop node
 BlockStart = 'block-start', // Sub-canvas start node
 BlockEnd = 'block-end', // Sub-canvas end node
 Comment = 'comment', // Comment node
 Continue = 'continue', // Continue node
 Break = 'break', // Break node
}

Each node follows a unified registration pattern:

export const StartNodeRegistry: FlowNodeRegistry = {
 type: WorkflowNodeType.Start,
 meta: {
 isStart: true,
 deleteDisable: true, // Not deletable
 copyDisable: true, // Not copyable
 nodePanelVisible: false, // Hidden in node panel
 defaultPorts: [{ type: 'output' }],
 size: { width: 360, height: 211 }
 },
 info: {
 icon: iconStart,
 description: 'The starting node of the workflow, used to set up information needed to launch the workflow.'
 },
 formMeta, // Form configuration
 canAdd() { return false; } // Disallow multiple start nodes
};

3. Plugin Architecture

App features are modularized via the plugin system:

Core Plugin List

  1. FreeLinesPlugin - Connection rendering and interaction
  2. MinimapPlugin - Minimap navigation
  3. FreeSnapPlugin - Auto-alignment and guide-lines
  4. FreeNodePanelPlugin - Node add panel
  5. ContainerNodePlugin - Container nodes (e.g., loop nodes)
  6. FreeGroupPlugin - Node grouping
  7. ContextMenuPlugin - Right-click context menu
  8. RuntimePlugin - Workflow runtime
  9. VariablePanelPlugin - Variable management panel

4. Runtime System

Two run modes are supported:

createRuntimePlugin({
 mode: 'browser', // Browser mode
 // mode: 'server', // Server mode
 // serverConfig: {
 // domain: 'localhost',
 // port: 4000,
 // protocol: 'http',
 // },
})

Design Philosophy and Advantages

1. Highly Modular

  • Plugin architecture: Each feature is an independent plugin, easy to extend and maintain
  • Node registry system: Add new node types without changing core code
  • Componentized UI: Highly reusable components with clear responsibilities

2. Type Safety

  • Full TypeScript support: End-to-end type safety from configuration to runtime
  • JSON Schema integration: Node data validated by schemas
  • Strongly typed plugin interfaces: Clear type constraints for plugin development

3. User Experience

  • Real-time preview: Run and debug workflows live
  • Rich interactions: Dragging, zooming, snapping, shortcuts for a complete editing experience
  • Visual feedback: Minimap, status indicators, line animations

4. Extensibility

  • Open plugin system: Third parties can easily develop custom plugins
  • Flexible node system: Custom node types and form configurations supported
  • Multiple runtimes: Both browser and server modes

5. Performance

  • On-demand loading: Components and plugins support lazy loading
  • Debounce: Performance optimizations for high-frequency operations like auto-save

Technical Highlights

1. In-house Editor Framework

Based on @flowgram.ai/free-layout-editor, providing:

  • Free-layout canvas system
  • Full undo/redo functionality
  • Lifecycle management for nodes and connections
  • Variable engine and expression system

2. Advanced Build Configuration

Using Rsbuild as the build tool:

export default defineConfig({
 plugins: [pluginReact(), pluginLess()],
 source: {
 entry: { index: './src/app.tsx' },
 decorators: { version: 'legacy' } // Enable decorators
 },
 tools: {
 rspack: {
 ignoreWarnings: [/Criticaldependency/] // Ignore specific warnings
 }
 }
});

3. Internationalization

Built-in multilingual support:

i18n: {
 locale: navigator.language,
 languages: {
 'zh-CN': {
 'Never Remind': '不再提示',
 'Hold {{key}} to drag node out': '按住 {{key}} 可以将节点拖出',
 },
 'en-US': {},
 }
}

About

Resources

Stars

0 stars

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages

AltStyle によって変換されたページ (->オリジナル) /