API

Component

<Flow>

<Flow> is the root container of graph。

props

canvasData?: Partial<CanvasDataType>; // canvas data
flowModelRef?: any; // graph ref
components?: Record<string, React.FC<{ model: any }>>; // registed components
models?: Record<string, typeof CellModel>; // rigisted models
onEvent?: (e: { type: string; data: any }) => void; // invoke when FlowModel.emitEvent
onLoad?: (model: FlowModel) => void;
zoom?: boolean; // enable wheel to zoom
width?: number; // graph's width
height?: number; // graph's height
scaleBy?: number; // zoom speed
grid?: number; // graph's grid size
multiSelect?: boolean; // whether to enable multi-select
linkEdge?: string | ((source: PortDataType, target: PortDataType) => string); // which Component to use when generate a edge
undoRedo?: boolean; // whether to enable undo/redo

<Port>

The <Port> component is the connection stub component of a node.

props

link?: (source, target) => boolean; // determine whether the current connection behavior is successful
dir?: 'left' | 'right' | 'top' | 'bottom'; // The direction of the Port, only takes effect when lineType!=LineType.POLYLINE
anchor: () => { x: number; y: number }; // position of Port's connect anchor
data: PortDataType; // the data of Port

Model

moa-flow uses Model to drive Component, the model in the node component is NodeModel, the model in the edge component is EdgeModel, and they all inherit from CellModel

FlowModel

FlowModel is the context model of the entire graph application. It has many global methods and properties, such as getting canvas data canvasData, setting canvas data setCanvasData

attrs

// graph's height
get height: () => number
set height: (height: number) => void
 
// graph's width
get width: () => number
set width: (width: number) => void
 
// graph's grid size
get grid: () => number
set grid: (grid: number) => void
 
// which Component to use when generate a edge
get linkEdge: () => number
set linkEdge: (linkEdge: string) => void
 
// graph's scale value
get scale: () => number
set scale: (scale: number) => void
 
// graph's x position offset
get x: () => number
set x: (x: number) => void
 
// graph's y position offset
get y: () => number
set y: (y: number) => void
 
// visible of context-menu
get contextMenuVisible: () => boolean
set contextMenuVisible: (visible: boolean) => void
 
// theme color, can be changed by user
color: { primary: string, base: string }
 
// get all cells data
getCellsData: () => CellDataType[];
 
// get all nodes data
getNodesData: () => NodeDataType[];
 
// get all edges data
getEdgesData: () => EdgeDataType[];
 
// get linking port
getLinkingPort: () => string
 
// get current cursors's [canvas coords]
getCursorCoord: (e: React.MouseEvent, isCanvasCoord: boolean = true) => {x: Number, y: number};
 
// graph's canvas data
canvasData: CanvasDataType
 
// set graph's canvas data
setCanvasData: (canvasData: CanvasDataType) => void;
 
// set data of a Cell, including Node, Edge, Port
setCellData: (id: string, data: any, deepMerge: boolean = true) => void;
 
// get all ports connected to a node
getLinkPorts: (nodeId: string) => string[];
 
// get all nodes connected to a node
getLinkNodes: (nodeId: string) => string[];
 
// get all edges connected to a node
getNodeEdges: (nodeId: string) => string[];
 
// get all ports connected to a port
getPortLinkPorts: (portId: string) => string[];
 
// get all nodes connected to a port
getPortLinkNodes: (portId: string) => string[]
 
// delete a Cell
deleCell: (id: string) => string;
 
// add a Cell, return the id of the added Cell
addCell: (componentName: string, initOptions?: any) => string
 
// connect two ports and return the id of the newly added edge
link: (source: string, target: string) => string
 
// adjust the level of a Cell
moveTo: (id: string, index: number) => void
 
// get a Cell's Model
getCellModel: (id: string) => CellModel;
 
// get a Port's react-component instance
getPortInstance: (id: string) => React.Component
 
// emit event, use onEvent in <Flow> to receive
emitEvent: (data: any) => void
 
// let canvas content automatically adapt to the width and height of the graph
fit: (nodeWidth: number, nodeHeight: number) => void
 
// adapt the width and height of the graph to parent element
fitParentSize: () => void

CellModel

attrs

Both NodeModel and EdgeModel are inherited from CellModel

// Model's data
data: {
  id: string; // Cell's id
  cellType: string; // Cell's type
  component: string; // Cell's Component
}
 
// default Model data
defaultData: () => CellDataType;
 
// same as FlowModel, you can use CellModel.context to get the global context of the graph application
context: FlowModel;
 
// is selected
isSelect: boolean
 
// get element instance of the cell's wrapping div/g
getWrapperRef: () => HTMLDivElement
 
setData: (data: any, rec: boolean = true): void

NodeModel

NodeModel inherits from CellModel, it is Node's model, with unique methods and properties such as data.x, data.y

attrs

data: {
  x: number,
  y: number
} & CellDataType
 
// get all nodes connected to the node
getLinkNodes: () => string[]
 
// get all ports connected by a node
getLinkPorts: () => string[]
 
// get all edges connected by the node
getNodeEdges: () => string[]
 
// get ids of all child nodes
getChildren: () => string
 
// sync ports data to context,call after adding/deleting port
syncPorts: () => void;
 
& CellModel // Contains all properties/methods of CellModel

EdgeModel

EdgeModel inherits from CellModel, it is Edge's model, it has unique methods and attributes such as data.source, data.target

attrs

data: {
  source: "", // starting port's id of the connection
  target: "", // ending port's id of the connection
  label: "", // edge's label
  verticies: [], // inflection point of the edge segment, only effective when lineType=LineType.POLYLINE
} & CellDataType // contains all properties/methods of CellModel
 
lineType: LineType | (() => LineType) = LineType.BEZIER; // line type
lineExtra: number | (() => number) = 20; // The length of the minimum connecting endpoint segment of an orthogonal line, effective when lineType=LineType.ORTH
enum LineType {
  ORTH,
  BEZIER,
  POLYLINE,
}
 
// get the start/end port's data of the connection
getLinkPortsData: () => {source: PortData, target: PortData}
 
// get the start/end port's id of the connection
getLinkNodes: () => {source: string, target: string}
 
// get the start/end node's data of the connection
getLinkNodesData: () => {source: Object, target: Object}
 
// get the start/end coordinates of the connection
getAnchors: () => {source: Vector2d, target: Vector2d}
 
// get the coordinates at a certain length of the line (ratio > 0), or the coordinates at a certain percentage length (ratio < 0)
getPointAt: (ratio: number) => {x: number, y: number}
 
// the function used to format the label, the last displayed label is the return value of this function
label: (label: string) => string
 
// the data of the <path> element
d: string
 
// used to adjust the control point of the Bezier curve, the larger the value, the less likely it is to bend
controlPointOffset: () => number
 
// only works when lineType=LineType.POLYLINE, line routing method, which can customize the points passed by the middle of the line
route: ({ vectors }: { vectors: Vector2d[] }) => Vector2d[]
 
// default line rendering component
LineRender:
React.FC<{{
  pathProps?: React.SVGProps<SVGPathElement>; // edge's path props
  arrowProps?: React.SVGProps<SVGPathElement> & {size?: number}; // edge's arrow props
  markerProps?: React.SVGProps<SVGMarkerElement>; // arrow's <marker> wrapper props
} & React.SVGProps<SVGGElement>}>
 
// default label rendering component in the middle of the line
LabelRender:
React.FC<React.SVGProps<SVGTextElement>>
 
// default rendering component for the entire edge (line+label)
EdgeRender:
React.FC<React.SVGProps<SVGGElement>>
 
& CellModel // contains all properties/methods of CellModel
Last updated on March 3, 2023
;