npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2026 – Pkg Stats / Ryan Hefner

free-layout-workflow-editor

v1.1.6

Published

React 工作流自由布局编辑器(NPM 包)。开箱即用,内置默认节点、插件、侧边栏与工具栏,支持类型安全扩展与二次开发。

Downloads

33

Readme

free-layout-workflow-editor

React 工作流自由布局编辑器(NPM 包)。开箱即用,内置默认节点、插件、侧边栏与工具栏,支持类型安全扩展与二次开发。

安装(Installation)

# 推荐
pnpm add free-layout-workflow-editor

# 或者
npm i free-layout-workflow-editor
yarn add free-layout-workflow-editor
  • peerDependencies: react >= 18, react-dom >= 18
  • 样式已在组件内自动引入:@flowgram.ai/free-layout-editor/index.css@douyinfe/semi-ui/dist/css/semi.min.cssfree-layout-workflow-editor/dist/styles/index.css,一般无需手动再引入。

快速开始(Quick Start)

import React from 'react'
import {
  WorkflowEditor,
  defaultNodeRegistries,
  type FlowDocumentJSON
} from 'free-layout-workflow-editor'

const INITIAL_X: number = 180
const INITIAL_Y: number = 180

const data: FlowDocumentJSON = {
  nodes: [
    {
      id: 'start_0',
      type: 'start',
      meta: { position: { x: INITIAL_X, y: INITIAL_Y } },
      data: { title: 'Start' }
    },
    {
      id: 'end_0',
      type: 'end',
      meta: { position: { x: INITIAL_X + 600, y: INITIAL_Y } },
      data: { title: 'End' }
    }
  ],
  edges: [{ sourceNodeID: 'start_0', targetNodeID: 'end_0' }]
}

export default function App(): JSX.Element {
  return (
    <div style={{ height: 600 }}>
      <WorkflowEditor initialData={data} registries={defaultNodeRegistries} />
    </div>
  )
}

导出(Exports)

  • 默认导出: WorkflowEditor
  • 具名导出:
    • 核心组件与类型:
      • WorkflowEditor(同默认导出)
      • type WorkflowEditorProps
      • type WorkflowEditorRef - 编辑器实例引用类型
      • type ToolbarSlots
    • 节点注册与类型:
      • defaultNodeRegistries - 默认节点注册列表
      • type FlowNodeRegistry - 节点注册类型
      • type FlowDocumentJSON - 文档数据类型
      • type FlowNodeJSON - 节点数据类型
      • type FlowNodeMeta - 节点元数据类型
    • 表单相关(用于自定义节点表单):
      • type FormRenderProps - 表单渲染Props类型
      • type FormMeta - 表单元数据类型
      • type FieldRenderProps - 字段渲染Props类型
      • Field - 表单字段组件
      • FormHeader - 表单头部组件
      • FormContent - 表单内容容器
      • FormInputs - 表单输入组件
      • FormItem - 表单项组件
      • Feedback - 反馈提示组件
    • 公共组件:
      • BaseNode - 基础节点组件
    • 上下文:
      • SidebarContext - 侧边栏上下文
      • IsSidebarContext - 是否在侧边栏标志
      • NodeRenderContext - 节点渲染上下文
    • Hooks:
      • useNodeRenderContext - 获取节点渲染上下文
      • useIsSidebar - 判断是否在侧边栏中

主要属性(Props 概览)

interface WorkflowEditorProps {
  initialData: FlowDocumentJSON
  readonly?: boolean

  // 节点注册与渲染扩展
  registries?: FlowNodeRegistry[]
  overrideDefaultRegistries?: boolean
  renderNodes?: NonNullable<FreeLayoutProps['materials']>['renderNodes']
  renderDefaultNode?: NonNullable<FreeLayoutProps['materials']>['renderDefaultNode']

  // 工具栏插槽
  showDefaultToolbar?: boolean
  toolbarSlots?: ToolbarSlots
  minimapDefaultVisible?: boolean

  // 插件与服务扩展
  extendPlugins?: (defaults: Plugin[], ctx: FreeLayoutPluginContext) => Plugin[]
  bindServices?: (bind: PluginBindConfig['bind']) => void

  // 事件覆盖(与默认并行调用)
  onInit?: NonNullable<FreeLayoutProps['onInit']>
  onAllLayersRendered?: NonNullable<FreeLayoutProps['onAllLayersRendered']>
  onDispose?: NonNullable<FreeLayoutProps['onDispose']>
  onContentChange?: NonNullable<FreeLayoutProps['onContentChange']>

  // 其它 FreeLayoutProps 透传覆盖
  editorOverrides?: Partial<FreeLayoutProps>
}

获取编辑器实例(Using Ref)

通过 ref 可以获取 WorkflowEditor 的实例,从而访问编辑器的数据和上下文。

基本用法

import { useRef } from 'react'
import { WorkflowEditor, WorkflowEditorRef } from 'free-layout-workflow-editor'

function App() {
  const editorRef = useRef<WorkflowEditorRef>(null)

  const handleSave = () => {
    // 获取当前工作流数据
    const data = editorRef.current?.getData()
    console.log('工作流数据:', data)
    
    // 保存到服务器
    // saveToServer(data)
  }

  return (
    <div>
      <button onClick={handleSave}>保存工作流</button>
      <WorkflowEditor ref={editorRef} initialData={initialData} />
    </div>
  )
}

WorkflowEditorRef API

  • getData(): FlowDocumentJSON | null - 获取当前工作流的完整数据(JSON格式)
  • getPlayground(): Playground | null - 获取编辑器的 Playground 实例
  • getContext(): FreeLayoutPluginContext | null - 获取编辑器的插件上下文

完整示例

import { useRef } from 'react'
import { WorkflowEditor, WorkflowEditorRef } from 'free-layout-workflow-editor'

function App() {
  const editorRef = useRef<WorkflowEditorRef>(null)

  // 保存工作流
  const handleSave = async () => {
    const data = editorRef.current?.getData()
    if (!data) return

    await fetch('/api/workflow/save', {
      method: 'POST',
      headers: { 'Content-Type': 'application/json' },
      body: JSON.stringify(data)
    })
  }

  // 导出工作流
  const handleExport = () => {
    const data = editorRef.current?.getData()
    if (!data) return

    const blob = new Blob([JSON.stringify(data, null, 2)], {
      type: 'application/json'
    })
    const url = URL.createObjectURL(blob)
    const a = document.createElement('a')
    a.href = url
    a.download = 'workflow.json'
    a.click()
    URL.revokeObjectURL(url)
  }

  // 重置缩放
  const handleResetZoom = () => {
    const playground = editorRef.current?.getPlayground()
    if (playground) {
      playground.config.zoom = 1
    }
  }

  return (
    <div>
      <button onClick={handleSave}>保存</button>
      <button onClick={handleExport}>导出</button>
      <button onClick={handleResetZoom}>重置缩放</button>
      <WorkflowEditor ref={editorRef} initialData={initialData} />
    </div>
  )
}

查看 docs/ref-usage.md 获取更详细的使用指南。

资源与构建(Assets & Bundlers)

  • 组件产物会从 dist/assets/ 引用图标资源(jpg/png/svg 等)。
  • v1 及以上版本已在构建中复制图片资源,并在包内提供对应相对路径,常见打包器(Rspack/Webpack/Vite)可直接解析。
  • 若你的项目使用原生 esbuild,请确保为静态资源配置 loader,例如:
// esbuild 示例
require('esbuild').build({
  // ...其他配置
  loader: {
    '.png': 'file',
    '.jpg': 'file',
    '.jpeg': 'file',
    '.svg': 'file',
    '.gif': 'file',
    '.webp': 'file',
    '.ico': 'file'
  }
})

自定义节点表单

概述

点击节点时弹出的右侧侧边栏内容由节点的 formMeta.render 函数定义。你可以通过注册自定义节点来完全控制侧边栏的显示内容。

基本示例

import {
  FormHeader,
  FormContent,
  FormInputs,
  Field,
  type FlowNodeRegistry,
  type FormRenderProps
} from 'free-layout-workflow-editor';
import { Input, Divider } from '@douyinfe/semi-ui';

// 自定义表单渲染
const CustomFormRender = ({ form }: FormRenderProps) => (
  <>
    <FormHeader />
    <FormContent>
      {/* 自定义配置区域 */}
      <Field name="customField">
        {({ field }) => (
          <div>
            <label>自定义字段</label>
            <Input
              value={field.value}
              onChange={field.onChange}
            />
          </div>
        )}
      </Field>
      
      <Divider />
      
      {/* 复用默认的输入表单 */}
      <FormInputs />
    </FormContent>
  </>
);

// 自定义节点注册
export const MyCustomNodeRegistry: FlowNodeRegistry = {
  type: 'my-custom-node',
  info: {
    icon: '/icons/custom.svg',
    description: '我的自定义节点'
  },
  onAdd() {
    return {
      id: `custom_${Date.now()}`,
      type: 'my-custom-node',
      data: {
        title: '自定义节点',
        customField: ''
      }
    };
  },
  formMeta: {
    render: CustomFormRender
  }
};

// 使用自定义节点
<WorkflowEditor
  initialData={data}
  registries={[
    ...defaultNodeRegistries,
    MyCustomNodeRegistry
  ]}
/>

可复用的组件

包导出了以下组件供你在自定义表单中使用:

  • FormHeader - 包含节点图标、标题编辑、菜单等
  • FormContent - 提供统一的内容容器和滚动
  • FormInputs - 默认的输入参数表单
  • FormItem - 统一的表单项布局
  • Feedback - 错误/警告提示

数据同步

使用 Field 组件修改数据时,变更会自动同步到画布:

import { Field } from '@flowgram.ai/free-layout-editor';

<Field name="title">
  {({ field }) => (
    <input
      value={field.value}
      onChange={(e) => field.onChange(e.target.value)}
    />
  )}
</Field>

完整文档

查看 CUSTOM_NODE_FORM.md 获取详细的自定义节点表单指南和完整示例。

参考示例

项目源码中的节点实现可作为参考:

  • src/nodes/http/ - HTTP节点(复杂表单)
  • src/nodes/code/ - 代码节点(代码编辑器)
  • src/nodes/variable/ - 变量节点(简单表单)
  • src/nodes/loop/ - 循环节点(嵌套子画布)