4.1.0 • Published 6 years ago

@amilajack/react-digraph v4.1.0

Weekly downloads
-
License
MIT
Repository
github
Last release
6 years ago

react-digraph

Demo

Overview

A React component which makes it easy to create a directed graph editor without implementing any of the SVG drawing or event handling logic.

Installation

npm install --save react-digraph

Usage

The default export is a component called 'GraphView'; it provides a multitude of hooks for various graph editing operations and a set of controls for zooming. Typically, it should be wrapped in a higher order component that supplies various callbacks (onCreateNode, onCreateEdge etc...).

All nodes and edges can have a type attribute set - nodes also support a subtype attribute. These can be passed to GraphView via the nodeTypes, nodeSubtypes, and edgeTypes props. GraphView will look up the corresponding SVG elements for the node's type/subtype and the edge's type and draw it accordingly.

It is often convenient to combine these types into a configuration object that can be referred to elsewhere in the application and used to associate events fired from nodes/edges in the graphView with other actions in the application. Here is an abbreviated example:

import GraphView from 'react-digraph'



const GraphConfig =  {
  NodeTypes: {
    empty: {
      typeText: "None",
      shapeId: "#empty",
      shape: (
        <symbol viewBox="0 0 100 100" id="empty" key="0">
          <circle cx="50" cy="50" r="45"></circle>
        </symbol>
      )
    }
  },
  NodeSubtypes: {},
  EdgeTypes: {
    emptyEdge: {
      shapeId: "#emptyEdge",
      shape: (
        <symbol viewBox="0 0 50 50" id="emptyEdge" key="0">
          <circle cx="25" cy="25" r="8" fill="currentColor"> </circle>
        </symbol>
      )
    }
  }
}

const EMPTY_TYPE = "empty"  // Text on empty nodes is positioned differently
const NODE_KEY = "id"       // Allows D3 to correctly update DOM

class Graph extends Component {

  constructor(props) {
    super(props);

    this.state = {
      graph: sample,
      selected: {}
    }
  }

  /* Define custom graph editing methods here */

  render() {
    const nodes = this.state.graph.nodes;
    const edges = this.state.graph.edges;
    const selected = this.state.selected;

    const NodeTypes = GraphConfig.NodeTypes;
    const NodeSubtypes = GraphConfig.NodeSubtypes;
    const EdgeTypes = GraphConfig.EdgeTypes;

    return (
      <div id='graph' style={styles.graph}>

        <GraphView  ref='GraphView'
                    nodeKey={NODE_KEY}
                    emptyType={EMPTY_TYPE}
                    nodes={nodes}
                    edges={edges}
                    selected={selected}
                    nodeTypes={NodeTypes}
                    nodeSubtypes={NodeSubtypes}
                    edgeTypes={EdgeTypes}
                    getViewNode={this.getViewNode}
                    onSelectNode={this.onSelectNode}
                    onCreateNode={this.onCreateNode}
                    onUpdateNode={this.onUpdateNode}
                    onDeleteNode={this.onDeleteNode}
                    onSelectEdge={this.onSelectEdge}
                    onCreateEdge={this.onCreateEdge}
                    onSwapEdge={this.onSwapEdge}
                    onDeleteEdge={this.onDeleteEdge}/>
      </div>
    );
  }

}

A typical graph that would be stored in the Graph component's state looks something like this:

{
  "nodes": [
    {
      "id": 1,
      "title": "Node A",
      "x": 258.3976135253906,
      "y": 331.9783248901367,
      "type": "empty"
    },
    {
      "id": 2,
      "title": "Node B",
      "x": 593.9393920898438,
      "y": 260.6060791015625,
      "type": "empty"
    },
    {
      "id": 3,
      "title": "Node C",
      "x": 237.5757598876953,
      "y": 61.81818389892578,
      "type": "empty"
    },
    {
      "id": 4,
      "title": "Node C",
      "x": 600.5757598876953,
      "y": 600.81818389892578,
      "type": "empty"
    }
  ],
  "edges": [
    {
      "source": 1,
      "target": 2,
      "type": "emptyEdge"
    },
    {
      "source": 2,
      "target": 4,
      "type": "emptyEdge"
    }
  ]
}

For a detailed example, check out src/examples/graph.js. To run the example:

npm install
npm run example

go to localhost:8000.

  • To add nodes, hold shift and click on the grid.
  • To add edges, hold shift and click/drag to between nodes.
  • To delete a node or edge, click on it and press delete.
  • Click and drag nodes to change their position.

All props are detailed below.

Props

PropTypeRequiredNotes
nodeKeystringtrueKey for D3 to update nodes(typ. UUID).
emptyTypestringtrue'Default' node type.
nodesarraytrueArray of graph nodes.
edgesarraytrueArray of graph edges.
selectedobjecttrueThe currently selected graph entity.
nodeTypesobjecttrueConfig object of available node types.
nodeSubtypesobjecttrueConfig object of available node subtypes.
edgeTypesobjecttrueConfig object of available edge types.
getViewNodefunctrueNode getter.
onSelectNodefunctrueCalled when a node is selected.
onCreateNodefunctrueCalled when a node is created.
onUpdateNodefunctrueCalled when a node is moved.
onDeleteNodefunctrueCalled when a node is deleted.
onSelectEdgefunctrueCalled when an edge is selected.
onCreateEdgefunctrueCalled when an edge is created.
onSwapEdgefunctrueCalled when an edge 'target' is swapped.
onDeleteEdgefunctrueCalled when an edge is deleted.
canDeleteNodefuncfalseCalled before a node is deleted.
canCreateEdgefuncfalseCalled before an edge is created.
canDeleteEdgefuncfalseCalled before an edge is deleted.
renderEdgefuncfalseCalled to render edge geometry.
renderNodefuncfalseCalled to render node geometry.
renderDefsfuncfalseCalled to render svg definitions.
renderBackgroundfuncfalseCalled to render svg background.
readOnlyboolfalseDisables all graph editing interactions.
enableFocusboolfalseAdds a 'focus' toggle state to GraphView.
maxTitleCharsnumberfalseTruncates node title characters.
transitionTimenumberfalseFade-in/Fade-out time.
primarystringfalsePrimary color.
lightstringfalseLight color.
darkstringfalseDark color.
styleobjectfalseStyle prop for wrapper.
gridSizenumberfalseOverall grid size.
gridSpacingnumberfalseGrid spacing.
gridDotnumberfalseGrid dot size.
minZoomnumberfalseMinimum zoom percentage.
maxZoomnumberfalseMaximum zoom percentage.
nodeSizenumberfalseNode bbox size.
edgeHandleSizenumberfalseEdge handle size.
edgeArrowSizenumberfalseEdge arrow size.
zoomDelaynumberfalseDelay before zoom occurs.
zoomDurnumberfalseDuration of zoom transition.
graphControlsbooleantrueWhether to show zoom controls.

Notes

  • To run the tests, you'll need to be using at least node v4.0 (for jsDom).