Code Monkey home page Code Monkey logo

flow-builder's Introduction

Introduction

English | 简体中文

A highly customizable streaming flow builder. The registration ability can flexibly customize your nodes, different types of node display and form, etc.

demo1 demo2

Try it out

https://bytedance.github.io/flow-builder

Github

https://github.com/bytedance/flow-builder

Installation

yarn add react-flow-builder

or

npm install react-flow-builder

Usage

// index.tsx
import React, { useState, useContext } from 'react';
import FlowBuilder, {
  NodeContext,
  INode,
  IRegisterNode,
} from 'react-flow-builder';

import './index.css';

const StartNodeDisplay: React.FC = () => {
  const node = useContext(NodeContext);
  return <div className="start-node">{node.name}</div>;
};

const EndNodeDisplay: React.FC = () => {
  const node = useContext(NodeContext);
  return <div className="end-node">{node.name}</div>;
};

const OtherNodeDisplay: React.FC = () => {
  const node = useContext(NodeContext);
  return <div className="other-node">{node.name}</div>;
};

const ConditionNodeDisplay: React.FC = () => {
  const node = useContext(NodeContext);
  return <div className="condition-node">{node.name}</div>;
};

const registerNodes: IRegisterNode[] = [
  {
    type: 'start',
    name: 'start node',
    displayComponent: StartNodeDisplay,
    isStart: true,
  },
  {
    type: 'end',
    name: 'end node',
    displayComponent: EndNodeDisplay,
    isEnd: true,
  },
  {
    type: 'node',
    name: 'other node',
    displayComponent: OtherNodeDisplay,
  },
  {
    type: 'condition',
    name: 'condition node',
    displayComponent: ConditionNodeDisplay,
  },
  {
    type: 'branch',
    name: 'branch node',
    conditionNodeType: 'condition',
  },
];

const Demo = () => {
  const [nodes, setNodes] = useState<INode[]>([]);

  const handleChange = (nodes: INode[]) => {
    console.log('nodes change', nodes);
    setNodes(nodes);
  };

  return (
    <FlowBuilder
      nodes={nodes}
      onChange={handleChange}
      registerNodes={registerNodes}
    />
  );
};

export default Demo;

// index.css
.start-node, .end-node {
  height: 64px;
  width: 64px;
  border-radius: 50%;
  line-height: 64px;
  color: #fff;
  text-align: center;
}

.start-node {
  background-color: #338aff;
}

.end-node {
  background-color: #666;
}

.other-node, .condition-node {
  width: 224px;
  border-radius: 4px;
  color: #666;
  background: #fff;
  box-shadow: 0 0 8px rgba(0, 0, 0, 0.08);
}

.other-node {
  height: 118px;
  padding: 16px;
  display: flex;
  flex-direction: column;
}

.condition-node {
  height: 44px;
  padding: 12px 16px;
}

API

FlowBuilder

Property Description Type Required Default Version
backgroundColor The color of background string #F7F7F7
className The class name of the container string -
draggable drag and drop boolean false 1.0.0
DragComponent custom drag component React.FC<DragComponent> - 1.0.0
DropComponent custom drop component React.FC<DropComponent> - 1.0.0
createUuid custom node uuid (type?: string) => string - 2.0.0
DrawerComponent Drawer component React.FC<DrawerComponent> - 2.0.0
PopoverComponent Popover component React.FC<PopoverComponent> - 2.0.0
PopconfirmComponent Popconfirm component React.FC<PopconfirmComponent> - 2.0.0
drawerProps Extra props of DrawerComponent any -
drawerVisibleWhenAddNode Drawer visible when add node boolean false
historyTool undo and redo boolean | HistoryToolConfig false
layout Use vertical or horizontal layout vertical | horizontal vertical
lineColor The color of line string #999999
nodes The nodes of FlowBuilder Node[] -
readonly Readonly mode, cannot add, remove, configure. boolean false
registerNodes The registered nodes RegisterNode[] -
registerRemoteNodes The registered remote nodes RegisterRemoteNode[] - 1.3.0
showPracticalBranchNode - boolean false 1.1.0
showPracticalBranchRemove - boolean false 1.1.0
sortable Condition nodes can be dragged and sorted in branch boolean false 1.4.0
sortableAnchor Anchor for start dragging 序 ReactNode - 1.4.0
spaceX Horizontal spacing between nodes number 16
spaceY Vertical spacing between nodes number 16
zoomTool zoom boolean | ZoomToolConfig false
onChange Callback function for when the data change (nodes: Node[], changeEvent: string, nodeChanged?: INode) => void -
onHistoryChange (undoDisabled: boolean, redoDisabled: boolean) => void -
onZoomChange (outDisabled: boolean, value: number, inDisabled: boolean) => void -
showArrow Show arrow boolean false 1.4.5
arrowIcon The icon of the arrow ReactNode - 1.4.5
onAddNodeSuccess Called when add node success (type: string, node: INode) => void - 1.4.9
onDropNodeSuccess Called when drop node success (type: string, node: INode) => void - 1.4.9
onRemoveNodeSuccess Called when remove node success (node: INode) => void - 2.2.0
allowStartConfig Allow start node config boolean - 2.1.0
allowEndConfig Allow end node config boolean - 2.1.0
scrollByDrag Scroll by mouse dragging boolean - 2.6.0

HistoryToolConfig

Property Description Type Default
hidden boolean false
max number 10

ZoomToolConfig

Property Description Type Default
hidden boolean false
initialValue number 100
min number 10
max number 200
step number 10

DragComponent

Property Description Type Version
onDragStart The dragStart event of the custom drag component needs to call this method to set the dragged type( dragType in BuilderContext ) (nodeType: string) => void 1.0.0
onDragEnd The dragEnd event of the custom drag component needs to call this method to clear the dragged type( dragType in BuilderContext ) () => void 1.0.0

DropComponent

Property Description Type Version
onDrop The drop event of the custom drop component needs to call this method to add the new node type () => void 1.0.0

DrawerComponent

Property Description Type Version
visible You can judge the boolean value of selectedNode by yourself. any 2.0.0
onClose You can also call closeDrawer by yourself. any 2.0.0
children any 2.0.0
title any 2.0.0
width any 2.0.0
destroyOnClose any 2.0.0
maskClosable any 2.0.0
configComponentRef React.MutableRefObject<any> 2.5.0

PopoverComponent

Property Description Type Version
visible any 2.0.0
onVisibleChange any 2.0.0
children any 2.0.0
overlayClassName any 2.0.0
placement any 2.0.0
trigger any 2.0.0
content any 2.0.0
getPopupContainer any 2.0.0

PopconfirmComponent

Property Description Type Version
title any 2.0.0
onConfirm You can also call removeNode yourself. any 2.0.0
children any 2.0.0
getPopupContainer any 2.0.0

FlowBuilderInstance

Name Description Type Version
add add node (node: INode, newNodeType: string) => void | (newNodeType: string) => void
history undo, redo (type: 'undo' | 'redo') => void
remove remove noded (nodes: INode | INode[] = useContext(NodeContext)) => void
zoom zoom (type: 'out' | 'in' | number) => void
closeDrawer close drawer () => void
context BuilderContext BuilderContext 1.3.5

Formatter

Name Description Type
buildFlatNodes Translate to flat nodes (params: {registerNodes: IRegisterNode[], nodes: INode[]}) => INode[]
buildTreeNodes Translate to tree nodes (params: {nodes: INode[]}) => INode[]
createUuid Create uuid (prefix?: string) => string

RegisterNode

Property Description Type Required Default Version
addableComponent React.FC<AddableComponent> -
addableNodeTypes The list of nodes that can be added below the node string[] -
addIcon The icon in addable node list (There are already some default icons) ReactNode -
addConditionIcon The icon of the branch node when adding a condition (The default icon already exists) ReactNode - 1.3.3
className The class name of node string - 1.3.4
conditionMaxNum The max number of condition node number -
conditionNodeType The type of condition node string -
configComponent The Component of configuring node form React.FC<ConfigComponent> | React.ForwardRefExoticComponent<ConfigComponent & React.RefAttributes<any>> -
configTitle The drawer title of configuring node string | ((node: INode, nodes: INode[]) => string) -
customRemove Custom remove button boolean false
displayComponent The Component of displaying node React.FC<DisplayComponent> -
initialNodeData the initial data when add new node Record<string, any> -
isStart Is start node boolean false
isEnd Is end node boolean false
isLoop Is loop node boolean false 1.4.6
name The name of node string -
removeConfirmTitle The confirmation information before deleting the node. The title of Popconfirm string | ReactNode Are you sure to remove this node?
showPracticalBranchNode - boolean false 1.1.0
showPracticalBranchRemove - boolean false 1.1.0
type The type of node, promise start is start node type and end is end node type string -

RegisterRemoteNode

Property Description Type Required Default Version
url remote url string - 1.3.0
cssUrl remote css url string - 1.3.0

DisplayComponent

Property Description Type
node The all information of node (NodeContext is recommended since V1) Node
nodes (BuilderContext is recommended since V1) Node[]
readonly (BuilderContext is recommended since V1) boolean
remove Remove node (useAction is recommended since V1) (nodes?: INode | INode[]) => void

ConfigComponent

Property Description Type
cancel Called on cancel, used to close the drawer (useDrawer is recommended since V1) () => void
node The all information of node (NodeContext is recommended since V1) Node
nodes (BuilderContext is recommended since V1) Node[]
save Called on save node data (automatically close the drawer, no need to call cancel). FlowBuilder will set the validateStatusError property according to the second param (useDrawer is recommended since V1) (values: any, validateStatusError?: boolean) => void

AddableComponent

Property Description Type
add (type: string) => void
node The all information of node (NodeContext is recommended since V1) Node
nodes (BuilderContext is recommended since V1) Node[]

Node

Property Description Type
children The condition nodes array of branch node, or the next flow of condition node Node[]
configuring Whether configuring of node. The display Component can highlight the node according to this property boolean
data The data of node any
id The unique id of node string
name The name of node. Same as the name of the registered node string
path The full path in FlowBuilder string[]
type The type of node. Same as the type of the registered node string
validateStatusError The Component of configuring node form validate failed. The display Component can highlight the node according to this property boolean

Context

Added since V1

In the context of FlowBuilder the following contexts can be used

BuilderContext

Contains props and state. The following is the state:

Property Description Type
zoomValue current zoom value number
setZoomValue set zoomValue (zoomValue: number) => void
historyRecords history nodes records INode[][]
setHistoryRecords set historyRecords (records: INode[][]) => void
activeHistoryRecordIndex current index in history nodes records number
setActiveHistoryRecordIndex set activeHistoryRecordIndex (index: number) => void
selectedNode current selecred node INode | undefined
setSelectedNode set selectedNode (node: INode | undefined) => void
drawerTitle the title of Drawer string
setDrawerTitle set drawerTitle (title: string) => void
dragType dragged node type string
setDragType set dragType (type: string) => void

NodeContext

Get the data of the node where it is used. For details Node

Hooks

Added since V1

In the context of FlowBuilder the following hooks can be used

useAction

Property Description Type Version
clickNode click node (node: INode = useContext(NodeContext)) => void
addNode add one node. (Get the current node through NodeContext when there is no node property) (node: INode, newNodeType: string) => void | (newNodeType: string) => void
addNodeInLoop add one node in loop node. (newNodeType: string) => void 1.4.6
removeNode remove one node or more nodes. (targetNode: INode | INode[] = useContext(NodeContext)) => void

useDrawer

Property Description Type
closeDrawer close Drawer and clear selectedNode () => void
saveDrawer save the content in Drawer (same as the save method in ConfigComponent) (values: any, validateStatusError?: boolean) => void

useZoom

Property Description Type
minZoom minimum zoom value number
maxZoom maximum zoom value number
zoom change zoom value (same as the zoom method in FlowBuilderInstance) (type: 'out' | 'in' | number) => void

useHistory

Property Description Type
maxLength Maximum length of history nodes records number
pushHistory add history nodes record (record?: INode[] = useContext(BuilderContext).nodes) => void
history undo, redo (same as the history method in FlowBuilderInstance) (type: 'undo' | 'redo') => void

useSort

Property Description Type Version
backward sort to backward (node: INode = useContext(NodeContext)) => void 1.4.3
forward sort to forward (node: INode = useContext(NodeContext)) => void 1.4.3
end sort to end (node: INode = useContext(NodeContext)) => void 1.4.3
start sort to start (node: INode = useContext(NodeContext)) => void 1.4.3

flow-builder's People

Contributors

darrelk avatar lixiao1022 avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

flow-builder's Issues

Cannot add data to the node with addNode

Hi, I am facing the issue that I cannot add data to the node with addNode function. Currently accept second parameter is a String type. Any idea to solve it? Thank you

Add Multiple `isStart` Nodes.

I want to add multiple isStart and connect that node to any of the node. How do i achieve that? Any help here is appreciated.

Conflicting peer dependency - react-sortable-hoc

It seems when using react 18.2.0 (next 13.x)
There are dependency problems with the react-sortable-hoc library

npm WARN ERESOLVE overriding peer dependency npm WARN While resolving: [email protected] npm WARN Found: [email protected] npm WARN node_modules/react npm WARN react@"18.2.0" from the root project npm WARN 63 more (@ant-design/cssinjs, @ant-design/icons, ...) npm WARN npm WARN Could not resolve dependency: npm WARN peer react@"^16.3.0 || ^17.0.0" from [email protected] npm WARN node_modules/react-flow-builder/node_modules/react-sortable-hoc npm WARN react-sortable-hoc@"^2.0.0" from [email protected] npm WARN node_modules/react-flow-builder npm WARN npm WARN Conflicting peer dependency: [email protected] npm WARN node_modules/react npm WARN peer react@"^16.3.0 || ^17.0.0" from [email protected] npm WARN node_modules/react-flow-builder/node_modules/react-sortable-hoc npm WARN react-sortable-hoc@"^2.0.0" from [email protected] npm WARN node_modules/react-flow-builder npm WARN ERESOLVE overriding peer dependency npm WARN While resolving: [email protected] npm WARN Found: [email protected] npm WARN node_modules/react-dom npm WARN react-dom@"18.2.0" from the root project npm WARN 50 more (@ant-design/cssinjs, @ant-design/icons, ...) npm WARN npm WARN Could not resolve dependency: npm WARN peer react-dom@"^16.3.0 || ^17.0.0" from [email protected] npm WARN node_modules/react-flow-builder/node_modules/react-sortable-hoc npm WARN react-sortable-hoc@"^2.0.0" from [email protected] npm WARN node_modules/react-flow-builder npm WARN npm WARN Conflicting peer dependency: [email protected] npm WARN node_modules/react-dom npm WARN peer react-dom@"^16.3.0 || ^17.0.0" from [email protected] npm WARN node_modules/react-flow-builder/node_modules/react-sortable-hoc

image

The latest version of the library is 3 years old. Maybe you have to look for another component that matches the version of react and does not generate more warnings when installing packages.

If I find something to replace it, I'll leave it in the comments.

Getting the current position (index) of the clicked "add node button"

Hello @lixiao1022 I have created a customPoperComponent
const CustomPopoverComponent = ({
visible,
onVisibleChange,
overlayClassName,
placement,
trigger,
content,

children,
...props

}) => {
const [isOpen, setOpen] = useState(false);

return (
  <>
    <div
      className={overlayClassName}
      style={{ cursor: "pointer" }}
      onClick={() => setOpen(true)}
    >
      <Icon name="Plus" size={32} isOnclick />
    </div>
    <Modal open={isOpen} footer={[]} onCancel={() => setOpen(false)} width={800} size="lg">
      <StyledModalBody>{content}</StyledModalBody>
    </Modal>
  </>
);

};

When I click on the icon to trigger my modal.
I would like to know the position.

My main goal is I would like to render different options when the node before it is start, or different type.

Thanks for the help.

Support for If Condition node with yes / no child

Hi,

I wanted to implement a condition node with a parent and then two sub-nodes to it.
I have tried loop and branch nodes but they dont seem to fulfil the requirement.

Is it possible to add that kind of a node type?

样式优化

当前所有的线都是通过dom 绘制 看能否支持条件节点的圆角

image

Cannot use removeNode to remove my branch node

Hi, I try to use removeNode in useAction hook to remove my branch node but seem it not working (only work with another node types). May I missed something?
BranchNode.tsx
const { addNode, removeNode } = useAction()
const node = useContext(NodeContext)
removeNode(node)

My registedNode
{
type: 'branch',
name: 'Branch',
conditionNodeType: 'condition',
displayComponent: BranchNode,
addableComponent: ModalAddNode,
addConditionIcon: <div style={{ width: 2, height: 10, backgroundColor: '#999' }} />,
addableNodeTypes: []
}`

【特性】增加点击节点和点击画布的回调通知

现在只有在配置了ConfigComponent的情况下才会通过onChange触发点击节点的回调通知。但是更灵活的界面组织需要在不使用内置的ConfigComponent机制的情况下也得到相应通知,然后动态选择如何处理,例如根据节点类型不同,动态选择drawer/dialog/property editor等编辑控件,显示位置也不同。
目前我在低代码平台NopPlatform中想集成FlowBuilder作为审批流的配置控件,我们会根据一个元模型配置动态生成前端的流程设计器,而不是在前端写死设计器的代码,所以需要更灵活的配置机制。希望能开放相关回调接口
https://github.com/entropy-cloud/nop-entropy

Get only changed node

It would be nice to detect any changes, to get only that node that was modified.

Currently FlowBuilder.onChange() shows all nodes,
Maybe it could be added as a parameter but only the modified node:

onChange: (nodes: INode[], changeEvent?: string, nodeChanged: INode) => void
The second parameter would have to be managed differently, perhaps with a default value, so that it does not break

Or add a new method to FlowBuilder: onNodeChanged(nodeChanged: INode)

Zoom not working in Firefox (115.0.3)

When using react-flow-builder v2 rendered in Firefox browser, the zoom feature does not work as expected.

When I click my custom zoom buttons or the internal FlowBuilder zoom buttons:

Expected result:
View is updated accordingly in all modern browsers

Actual result:
View is not changed after zoom value is changed when rendered in Firefox. Works as expected in Chrome.
Callback onZoomChange does however provide the expected resulting zoom value also in Firefox. So only the rendered view is not updated.

My zoom handling code:

  const builderRef = useRef<IFlowBuilderMethod>(null);

//Called from click event handler on custom zoom buttons. Also tested with setting zoom numerical value.
  const handleZoom = (zoomtype: ZoomType) => {
    builderRef.current!.zoom(zoomtype);
  };

//Provided as FlowBuilders onZoomChange callback. 
//This is called by FlowBuilder with the expected resulting value after zoom level change
  const handleZoomChange = (
    outDisabled: boolean,
    value: number,
    inDisabled: boolean
  ) => {
    setOutDisabled(outDisabled);
    setInDisabled(inDisabled);
    setZoom(value);
  };
        <FlowBuilder
          readonly
          ref={builderRef}
          nodes={nodes as INode[]}
          onZoomChange={handleZoomChange}
          zoomTool={{
            hidden: false, 
            min: 10,
            max: 150,
            step: 5,
          }}
          onChange={handleChange}
          registerNodes={registerNodes}
        />

[Feature Request] 增加并行节点类型

目前的分支节点必须后置条件节点。并行分支应用场景还是比较多的,请问是否考虑增加并行节点类型。或者目前有什么实现方式?

Change `onAddNodeSuccess` to return `INode`

Is there any method to get only the aggregated node?
I see that there is the onAddNodeSuccess method but it only returns the type, it will be nice if it returns the entire node (INode)

Requesting support for canvas drag and drop feature

Hello,

I am currently using React Flow Builder in my project and I have found that it does not support canvas drag and drop feature out of the box. After doing some research, I tried to implement this feature manually by adding a div wrapper and using the react-draggable and react-flow-renderer libraries. However, this solution has some limitations and is not very stable.

I would like to request that the React Flow Builder team add support for canvas drag and drop feature natively. This would greatly improve the user experience for those who use React Flow Builder in their projects.

Thank you for your attention to this matter. Let me know if you have any questions or if I can provide any additional information.

zoom缩放

使用zoom缩放 在节点中加入一些antd的 popover组件 ,然后进行缩放会导致 位置错误

当ConfigComponent中表单存在树形结构,渲染报错

点击节点后drawer弹出,当drawer中form中存在treeSelect这种value值是对象形式,save成功后,再次点击该节点,会报错
image
drawer中表单代码

  const ConfigForm: React.FC = () => {
  const { selectedNode: node, setDrawerTitle } = useContext(BuilderContext);

  const { saveDrawer: save } = useDrawer();

  const [form] = Form.useForm();
  const [treeData, setTreeData] = React.useState<API.System.DeptTreeUser[]>([]);
  useEffect(() => {
    (async () => {
      setDrawerTitle('配置');
      const { data } = await getDeptTreeUser();
      setTreeData(data as API.System.DeptTreeUser[]);
      form.setFieldsValue({
        name: node!.data?.name,
      });
    })();
  }, []);

  async function handleSubmit() {
    try {
      const values = await form.validateFields();
      save?.(values);
    } catch (e) {
      const values = form.getFieldsValue();
      save?.(values, !!e);
    }
  }
  return (
    <div>
      <Form<{ name: API.System.DeptTreeUser }> form={form}>
        <Form.Item name="name" label="处理人" rules={[{ required: true, message: '请选择处理人' }]}>
          <TreeSelect
            allowClear
            treeData={treeData}
            placeholder="请选择处理人"
            showArrow={false}
            filterTreeNode={true}
            showSearch={true}
            popupMatchSelectWidth={false}
            labelInValue={true}
            autoClearSearchValue={true}
            multiple={false}
            treeNodeFilterProp="label"
            fieldNames={{ value: 'id' }}
          />
        </Form.Item>
      </Form>
      <Button.Group>
        <Button type={'primary'} onClick={handleSubmit}>
          确定
        </Button>
      </Button.Group>
    </div>
  );
};

export default ConfigForm;

buildFlatNodes 报错

const handleChange = (nodes: INode[]) => {
    console.log('nodes change', nodes);
    setNodes(nodes);
    console.log(buildFlatNodes({ registerNodes, nodes }));
};

image

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.