A developer-friendly library for creating flowcharts and diagrams
Flowpoints
A developer-friendly library for creating flowcharts and diagrams.
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.
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"
    },
    "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.