Flowpoints
A developer-friendly library for creating flowcharts and diagrams.
Simple demo here and cooler demo here, both running the same source code here
Or check out this or this or this
Installation
Quick and easy installation with npm. Package site here.
npm install --save flowpoints
Usage
import React from 'react'; import { Flowpoint, Flowspace } from 'flowpoints'; ... <Flowspace> <Flowpoint key="point_a" outputs={["point_b"]}> Hello world ... </Flowpoint> <Flowpoint key="point_b"> I am point b ... </Flowpoint> </Flowspace> ...
To create a new diagram start by creating open-and-close tags for the "Flowspace". Itβs in between these that you may add flowpoints.
No-drag areas
To create a no-drag area simply set the className of your component/element to "nodrag".
Variants
Can be defined for all flowpoints in the flowspace-props, or individually in each flowpoint's props.
Themes
Used to determine the colors used for the flowpoints. Available themes:
- red
- purple
- deep-purple
- indigo
- blue
- light-blue
- green
- light-green
- lime
- yellow
- amber
- orange
- deep-orange
- brown
- grey
- blue-grey
- black
- white
Outputs
The flowspace extracts information about all connections from the outputs of every flowpoint. Telling a flowpoint about inputs wonβt have any effect.
To change the color and stroke of a single connection: Add that info to the output like shown below
There are two ways to pass info about the connections:
As an array.
Simply pass an array with the keys to all the flowpoints the current one should be connected to.
As an object.
Create an object using the following pattern:
... <Flowpoint key="point_a" outputs={{ "point_b": { output: "auto", input: "auto", inputColor: "red", dash: 5 }, "point_c": { output: "right", input: "left" } }}>Hello World!</Flowpoint> ...
The "right" and "left" arguments tell the flowspace where on the involved flowpoints the connections should attach.
Possible locations: top, left, center (default), right, bottom.
Flowpoint props
<Flowpoint key="point_a" theme="indigo" variant="outlined" outputs={{ "point_b": { output:"right", input:"left", outputColor:"#0c00ff", inputColor:"#ff0022", onClick: (key_a, key_b, e) => { console.log('Click connection ' + key_a + ' -> ' + key_b) } } }} style={{ backgroundColor:'lightblue' }} startPosition={{ x:250, y:100 }} selected={false} snap={{ x:10, y:10 }} dragX={true} dragY={true} minX=50 minY=50 width=100 height=40 onClick={ (e) => {console.log('Click!')} } onDrag={ (position) => {console.log('Drag', position)} } onHover={ (isHovering) => {console.log(isHovering ? 'Hovering' : 'Not hovering')} } > ... </Flowpoint>
Flowspace props
<Flowspace theme="indigo" variant="outlined" background="white" style={{ width:'100vw', height:'100vh' }} connectionSize=4 selected="point_a" selectedLine={{ a:"point_a", b:"point_b" }} onLineClick={(key_a, key_b, e) => { console.log('Click connection ' + key_a + ' -> ' + key_b) }} onClick={e => {console.log('Clicked empty space')}} > ... </Flowspace>
Themes, variants and connectionSizes passed to the flowspace will be the default values used when drawing connections. A different value specified by a flowpoint's outputs will replace the default value for that connection only.
Suggested pattern
Once a flowpoint unmounts it will forget it's last position. To help with this (and a few more things) I find that the following pattern works really well:
import React, { Component } from 'react'; import ReactDOM from "react-dom"; import { Flowpoint, Flowspace } from 'flowpoints'; class App extends Component { constructor(props) { super(props); this.state = { selected_point: null, flowpoints: { "a": { position: { x:50, y:50 }, outputs: { "b": { output:"right", input:"left", outputColor:"blue", inputColor:"white", width:3, onClick={(key_a, key_b) => { ... }} } } } } } } render() { return ( <Flowspace theme="indigo" variant="outlined" background="black" style={{ height:"100vh", width:"100vw" }} onClick={e => { this.setState({ selected_point:null }) }} selected={this.state.selected_point}> { Object.keys(this.state.flowpoints).map(key => { const point = this.state.flowpoints[key] return ( <Flowpoint key={key} snap={ x:10, y:10 } startPosition={point.pos} onClick={() => { var selected_point = this.state.selected_point if (selected_point === key) { selected_point = null } else { selected_point = key } this.setState({selected_point}) }} onDrag={position => { var flowpoints = this.state.flowpoints flowpoints[key].position = position this.setState({flowpoints}) }}>{"Hello from " + key}</Flowpoint> ) }) } </Flowspace> ) } } ReactDOM.render(<App />, document.getElementById('root'))
Of course, you can do with much less code than this, but this example should give a good indication on how you can structure your data for a flowchart.
Check out the demo and it's source code for more.
Contributing
Made some improvements? Make sure to update the demo and create a new pull request!
Things to improve
Connections corners:
Add the option to make paths use straight corners.
Connections animations:
Add an option to make connections appear as dashed lines moving from A to B at user-defined speed.
Better touch:
Make it possible to drag flowpoints on touch screens without also dragging the entire window.
Directory structure
Please maintain the following structure when making pull requests.
flowpoints βββ .gitattributes βββ .gitignore βββ LICENSE βββ package-lock.json βββ package.json βββ README.md β βββ assets β βββ favicon.ico β βββ this_is_flowpoints.png β βββ demo β βββ src β βββ index.css β βββ index.html β βββ index.js β βββ src βββ Flowpoint.js βββ Flowspace.js βββ index.js