├── .gitignore ├── README.md ├── example ├── index.jsx ├── simplest.jsx └── style.css ├── index.js ├── lib ├── Node.jsx ├── branch-end.jsx ├── branch-handle.jsx ├── constants.json ├── index.jsx ├── node-target.jsx └── style.css ├── package.json └── test └── index.js /.gitignore: -------------------------------------------------------------------------------- 1 | node_modules 2 | *.swp 3 | .DS_Store 4 | npm-debug.log 5 | dump 6 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # React-Flowchart # 2 | 3 | React-Flowchart is an implementation of [React-DND](https://github.com/gaearon/react-dnd) aimed at solving my somewhat specific use case: an interactive flowchart interface. You create your own components for nodes and branches, pass them into React-Flowchart, and it will do the drag & drop wrapping for you, along with drawing lines to connect the nodes (the line drawing portion of the package desperately needs work). 4 | 5 | Parameters: 6 | * nodes: (array of objects) See the example below to get an idea of what this looks like. At the moment, each object in the array needs a nodeId (this will change in the next version). Each object can optionally include a "branches" array, x, and y properties. You can put whatever else you want on it, and all properties of the object will be passed into the NodeContents component as props. 7 | * NodeContents: (component) This is the component that becomes draggable and houses branches. React-Flowchart passes all of the properties of each node in your "nodes" array as props to this component, and adds two additional props: NodeTarget (where a draggable branch can be dropped) and NodeBranches (an array of BranchContents components). 8 | * BranchContents: (component) This is the component that houses the draggable branch handle. It receives as props all of the properties of the associated "branches" object in your "nodes" array, and adds in a "BranchHandle" prop. 9 | * dropBranch(branch, node): (function) this function is fired when you drop a branch onto a valid NodeTarget. It receives as arguments the branch object that was dropped and the node object that it was dropped on. 10 | * dropNode(node, coords): (function) this function is fired when you drop a node into the container area. It receives as arguments the node object that was drag & dropped and the coords{x:123,y:456} where it was dropped. 11 | * BranchHandle: (element - optional) If you want to customize what the draggable branch handle looks like, use this to pass in something that will render. 12 | * BranchEnd: (element - optional) If you want to customize what the branch endpoint looks like, use this to pass in something that will render. 13 | 14 | ## Example ## 15 | 16 | Please see example/index.jsx for implementation details. In order to experiment with the example yourself, download and run this command: 17 | 18 | ``` 19 | npm run example 20 | ``` 21 | 22 | ![Demo](http://i.imgur.com/UNh1eEP.gif) 23 | 24 | While this example works, it doesn't really do anything because there is no change to the data between renders. Look at example/index.jsx to see a bit more of a real world implementation. 25 | 26 | ```js 27 | var data = [ 28 | { 29 | nodeId: 'node1', 30 | x: 20, 31 | y: 20, 32 | branches: [ 33 | {branchId:'branch1', nodeId:"node2"}, 34 | {branchId:'branch2', nodeId:"node2"}, 35 | {branchId:'branch3', nodeId:"node2"} 36 | ] 37 | }, 38 | { 39 | nodeId: 'node2', 40 | x: 250, 41 | y: 20 42 | }, 43 | { 44 | nodeId: 'node3', 45 | x: 250, 46 | y: 200 47 | } 48 | ] 49 | 50 | var NodeContents = React.createClass({ 51 | render : function() { 52 | var html = 53 |
54 | {this.props.NodeTarget} 55 | {this.props.NodeBranches} 56 |
57 | return html 58 | } 59 | }) 60 | 61 | var BranchContents = React.createClass({ 62 | render : function() { 63 | var html = 64 |
65 | {this.props.BranchHandle} 66 |
67 | return html 68 | } 69 | }) 70 | 71 | var dropNode = function (node, coords) { 72 | console.log('dropped at '+coords.x+','+coords.y) 73 | } 74 | 75 | var dropBranch = function (branch, node) { 76 | console.log('dropped branchId:'+branch.branchId+' on nodeId:'+node.nodeId) 77 | } 78 | 79 | 80 | 81 | React.render( 82 | ( 83 |
84 | 90 |
91 | ), 92 | document.body 93 | ) 94 | ``` 95 | 96 | ## To-Do ## 97 | 98 | * Must remove dependence on nodeId and branchId and handle these internally. 99 | * Must make lines suck significantly less. 100 | * Probably other things to handle the nuances of your use case (talk to me on github). 101 | 102 | 103 | 104 | -------------------------------------------------------------------------------- /example/index.jsx: -------------------------------------------------------------------------------- 1 | 2 | var uuid = require('node-uuid'); 3 | var React = require('react') 4 | var ReactFlow = require('../index.js') 5 | var EventEmitter = require('events') 6 | 7 | require('./style.css') 8 | 9 | 10 | var data = [ 11 | { 12 | nodeId: 'node1', 13 | name: 'Node 1', 14 | maxBranches: 10, 15 | x: 20, 16 | y: 20, 17 | branches: [ 18 | {branchId:'branch1', nodeId:"node2"}, 19 | {branchId:'branch2', nodeId:"node2"}, 20 | {branchId:'branch3', nodeId:"node2"} 21 | ] 22 | }, 23 | { 24 | nodeId: 'node2', 25 | name: 'Node 2', 26 | x: 250, 27 | y: 20 28 | }, 29 | { 30 | nodeId: 'node3', 31 | name: 'Node 3', 32 | x: 250, 33 | y: 200 34 | } 35 | ] 36 | 37 | 38 | 39 | 40 | var globalEmitter = new EventEmitter() 41 | 42 | 43 | 44 | var MyFlowchart = React.createClass({ 45 | propTypes: {}, 46 | 47 | getInitialState : function() { 48 | return {nodes:data} 49 | }, 50 | 51 | componentDidMount: function () { 52 | globalEmitter.addListener('updateNode', this._updateNode); 53 | }, 54 | 55 | componentWillUnmount: function () { 56 | globalEmitter.removeListener('updateNode', this._updateNode); 57 | }, 58 | 59 | _updateNode : function (values) { 60 | var nodeId = values.nodeId 61 | var nodes = this.state.nodes 62 | var node = this._findNode(nodeId, nodes) 63 | for (var key in values) { 64 | node[key] = values[key] 65 | } 66 | this.setState({nodes:nodes}) 67 | }, 68 | 69 | _findNode : function (nodeId, nodes) { 70 | for (var index in nodes) { 71 | if (nodes[index].nodeId === nodeId) { 72 | return nodes[index] 73 | } 74 | } 75 | return false 76 | }, 77 | 78 | _findBranch : function (branchId, nodes) { 79 | for (var index in nodes) { 80 | if (nodes[index].branches) { 81 | for (var nindex in nodes[index].branches) { 82 | var branch = nodes[index].branches[nindex] 83 | if (branch.branchId === branchId) { 84 | return branch 85 | } 86 | } 87 | } 88 | } 89 | return false 90 | }, 91 | 92 | _updateBranch : function (branchId, values) { 93 | var nodes = this.state.nodes 94 | var branch = this._findBranch(branchId, nodes) 95 | for (var key in values) { 96 | branch[key] = values[key] 97 | } 98 | this.setState({nodes:nodes}) 99 | }, 100 | 101 | _dropNode : function (node, coords) { 102 | var vals = { 103 | nodeId: node.nodeId, 104 | x: coords.x, 105 | y: coords.y 106 | } 107 | this._updateNode(vals) 108 | }, 109 | 110 | _dropBranch : function (branch, node) { 111 | this._updateBranch(branch.branchId, {nodeId:node.nodeId}) 112 | }, 113 | 114 | render : function() { 115 | var html = 116 |
117 | 123 |
124 | return html 125 | } 126 | }) 127 | 128 | var NodeContents = React.createClass({ 129 | 130 | propTypes: { 131 | NodeBranches: React.PropTypes.array, 132 | NodeTarget: React.PropTypes.element 133 | }, 134 | 135 | _addNewBranch : function() { 136 | var branches = this.props.branches 137 | if (!branches) { 138 | branches = [] 139 | } 140 | branches.push({branchId:uuid.v4()}) 141 | 142 | var node = { 143 | nodeId: this.props.nodeId, 144 | branches: branches 145 | } 146 | globalEmitter.emit('updateNode', node) 147 | }, 148 | 149 | render : function() { 150 | var html = 151 |
152 | {this.props.NodeTarget} 153 |
154 | {this.props.NodeBranches} 155 |
+
156 |
157 |
158 | return html 159 | } 160 | 161 | }) 162 | 163 | var BranchContents = React.createClass({ 164 | 165 | propTypes: { 166 | BranchHandle: React.PropTypes.element, 167 | }, 168 | 169 | render : function() { 170 | var html = 171 |
172 | {this.props.BranchHandle} 173 |
174 | return html 175 | } 176 | 177 | }) 178 | 179 | 180 | 181 | 182 | 183 | React.render( 184 | ( 185 | 186 | ), 187 | document.body 188 | ) 189 | -------------------------------------------------------------------------------- /example/simplest.jsx: -------------------------------------------------------------------------------- 1 | var React = require('react') 2 | var ReactFlow = require('../index.js') 3 | var EventEmitter = require('events') 4 | 5 | require('./style.css') 6 | 7 | 8 | 9 | var data = [ 10 | { 11 | nodeId: 'node1', 12 | x: 20, 13 | y: 20, 14 | branches: [ 15 | {branchId:'branch1', nodeId:"node2"}, 16 | {branchId:'branch2', nodeId:"node2"}, 17 | {branchId:'branch3', nodeId:"node2"} 18 | ] 19 | }, 20 | { 21 | nodeId: 'node2', 22 | x: 250, 23 | y: 20 24 | }, 25 | { 26 | nodeId: 'node3', 27 | x: 250, 28 | y: 200 29 | } 30 | ] 31 | 32 | var NodeContents = React.createClass({ 33 | render : function() { 34 | var html = 35 |
36 | {this.props.NodeTarget} 37 | {this.props.NodeBranches} 38 |
39 | return html 40 | } 41 | }) 42 | 43 | var BranchContents = React.createClass({ 44 | render : function() { 45 | var html = 46 |
47 | {this.props.BranchHandle} 48 |
49 | return html 50 | } 51 | }) 52 | 53 | var dropNode = function (node, coords) { 54 | console.log('dropped at '+coords.x+','+coords.y) 55 | } 56 | 57 | var dropBranch = function (branch, node) { 58 | console.log('dropped branchId:'+branch.branchId+' on nodeId:'+node.nodeId) 59 | } 60 | 61 | 62 | 63 | React.render( 64 | ( 65 |
66 | 72 |
73 | ), 74 | document.body 75 | ) 76 | 77 | -------------------------------------------------------------------------------- /example/style.css: -------------------------------------------------------------------------------- 1 | 2 | body { 3 | margin: 150px 0px 0px 150px; 4 | } 5 | 6 | .container { 7 | border: 1px solid #CCC; 8 | width: 800px; 9 | height: 600px; 10 | } 11 | 12 | .containerCanvas { 13 | position: absolute; 14 | top: 0px; 15 | left: 0px; 16 | z-index: 999; 17 | pointer-events: none; 18 | } 19 | 20 | .containerDragHover { 21 | background-color: green; 22 | } 23 | 24 | .nodeDragHover { 25 | background-color: green; 26 | } 27 | 28 | .node { 29 | background-color: #E0E0E0; 30 | width: 100px; 31 | height: 100px; 32 | } 33 | 34 | .branchHandle { 35 | } 36 | 37 | .branchHolder { 38 | position: absolute; 39 | top: 0px; 40 | right: 0px; 41 | } 42 | -------------------------------------------------------------------------------- /index.js: -------------------------------------------------------------------------------- 1 | 2 | module.exports = require('./lib/index.jsx') 3 | -------------------------------------------------------------------------------- /lib/Node.jsx: -------------------------------------------------------------------------------- 1 | 2 | var dnd = require('react-dnd'); 3 | var React = require('react') 4 | 5 | var BranchEnd = require('./branch-end.jsx') 6 | var BranchHandle = require('./branch-handle.jsx') 7 | var NodeTarget = require('./node-target.jsx') 8 | var ItemTypes = require('./constants.json').ItemTypes 9 | 10 | 11 | 12 | var Node = React.createClass({ 13 | propTypes: {}, 14 | 15 | render : function() { 16 | this.update = false 17 | var branches = [] 18 | 19 | if (this.props.node.branches) { 20 | for (var index in this.props.node.branches) { 21 | var branch = {} 22 | for (var key in this.props.node.branches[index]) { 23 | branch[key] = this.props.node.branches[index][key] 24 | } 25 | 26 | branch.key = 'k'+branch.branchId 27 | branch.BranchHandle = 31 | 32 | branches.push(React.createElement(this.props.BranchContents, branch)) 33 | } 34 | } 35 | 36 | var branchesIn = [] 37 | if (this.props.branchesIn) { 38 | for (var index in this.props.branchesIn) { 39 | branchesIn.push() 42 | } 43 | } 44 | 45 | var connectDragSource = this.props.connectDragSource; 46 | var isDragging = this.props.isDragging; 47 | 48 | var node = {} 49 | for (var index in this.props.node) { 50 | node[index] = this.props.node[index] 51 | } 52 | node.NodeTarget = 53 | node.NodeBranches = branches 54 | node.opts = this.props.opts 55 | 56 | var contents = React.createElement(this.props.NodeContents, node) 57 | 58 | var containerStyle = { 59 | position: 'absolute', 60 | top: this.props.y, 61 | left: this.props.x 62 | } 63 | 64 | var html = 65 | connectDragSource( 66 |
67 | {contents} 68 |
69 | ) 70 | return html 71 | } 72 | 73 | }) 74 | 75 | var nodeSource = { 76 | beginDrag: function (props) { 77 | return {node:props.node, dropNode:props.dropNode} 78 | } 79 | } 80 | 81 | function collect(connect, monitor) { 82 | return { 83 | connectDragSource: connect.dragSource(), 84 | isDragging: monitor.isDragging() 85 | } 86 | } 87 | 88 | 89 | var NodeContainer = module.exports = dnd.DragSource(ItemTypes.nodeContainer, nodeSource, collect)(Node); 90 | 91 | 92 | -------------------------------------------------------------------------------- /lib/branch-end.jsx: -------------------------------------------------------------------------------- 1 | 2 | var React = require('react') 3 | 4 | 5 | var BranchEnd = module.exports = React.createClass({ 6 | 7 | propTypes: { 8 | BranchEndContents: React.PropTypes.node, 9 | branchId: React.PropTypes.string 10 | }, 11 | 12 | render : function() { 13 | var contents = '▶' 14 | if (this.props.BranchEndContents) { 15 | contents = this.props.BranchEndContents 16 | } 17 | 18 | var html = 19 |
20 | {contents} 21 |
22 | return html 23 | } 24 | 25 | }) 26 | 27 | 28 | -------------------------------------------------------------------------------- /lib/branch-handle.jsx: -------------------------------------------------------------------------------- 1 | var dnd = require('react-dnd'); 2 | var React = require('react') 3 | 4 | var ItemTypes = require('./constants.json').ItemTypes 5 | 6 | 7 | var branchSource = { 8 | beginDrag: function (props) { 9 | return {branch:props.branch, dropBranch:props.dropBranch} 10 | } 11 | } 12 | 13 | function collect(connect, monitor) { 14 | return { 15 | connectDragSource: connect.dragSource(), 16 | connectDragPreview: connect.dragPreview(), 17 | isDragging: monitor.isDragging() 18 | } 19 | } 20 | 21 | 22 | var BranchOut = React.createClass({ 23 | 24 | propTypes: { 25 | connectDragSource: React.PropTypes.func.isRequired, 26 | connectDragPreview: React.PropTypes.func.isRequired, 27 | BranchHandleContents: React.PropTypes.node, 28 | isDragging: React.PropTypes.bool.isRequired 29 | }, 30 | 31 | componentDidMount: function () { 32 | var connectDragPreview = this.props.connectDragPreview; 33 | connectDragPreview(
); 34 | }, 35 | 36 | render: function () { 37 | var connectDragSource = this.props.connectDragSource; 38 | var isDragging = this.props.isDragging; 39 | 40 | var contents = '⬤' 41 | if (this.props.BranchEndContents) { 42 | contents = this.props.BranchEndContents 43 | } 44 | 45 | return connectDragSource( 46 |
50 | {contents} 51 |
52 | ); 53 | } 54 | }) 55 | 56 | var BranchHandle = module.exports = dnd.DragSource(ItemTypes.branchOut, branchSource, collect)(BranchOut); 57 | -------------------------------------------------------------------------------- /lib/constants.json: -------------------------------------------------------------------------------- 1 | 2 | { 3 | ItemTypes: { 4 | branchOut: 'branchOut', 5 | nodeIn: 'nodeIn', 6 | nodeContainer: 'nodeContainer', 7 | parentContainer: 'parentContainer' 8 | } 9 | } 10 | -------------------------------------------------------------------------------- /lib/index.jsx: -------------------------------------------------------------------------------- 1 | 2 | 3 | var HTML5Backend = require('react-dnd/modules/backends/HTML5') 4 | var React = require('react') 5 | var dnd = require('react-dnd') 6 | 7 | require('./style.css') 8 | 9 | var Node = require('./node.jsx') 10 | 11 | var ItemTypes = require('./constants.json').ItemTypes 12 | 13 | 14 | var Container = React.createClass({ 15 | 16 | propTypes: { 17 | nodes: React.PropTypes.array.isRequired, 18 | BranchContents: React.PropTypes.element.isRequired, 19 | NodeContents: React.PropTypes.element.isRequired, 20 | BranchHandle: React.PropTypes.node, 21 | BranchEnd: React.PropTypes.node, 22 | NodeContents: React.PropTypes.element.isRequired, 23 | dropBranch: React.PropTypes.func.isRequired, 24 | dropNode: React.PropTypes.func.isRequired, 25 | opts: React.PropTypes.object 26 | }, 27 | 28 | componentWillUpdate : function() { 29 | var canvas = this.refs.containerCanvas.getDOMNode() 30 | var context = canvas.getContext('2d'); 31 | context.clearRect(0, 0, canvas.width, canvas.height); 32 | }, 33 | 34 | componentDidUpdate : function() { 35 | this._resizeCanvas() 36 | this._drawConnections() 37 | }, 38 | 39 | componentDidMount : function() { 40 | this._resizeCanvas() 41 | this._drawConnections() 42 | }, 43 | 44 | _resizeCanvas : function () { 45 | var container = this.refs.container.getDOMNode() 46 | var canvas = this.refs.containerCanvas.getDOMNode() 47 | 48 | canvas.width = container.offsetWidth 49 | canvas.height = container.offsetHeight 50 | }, 51 | 52 | _drawConnections : function () { 53 | var canvas = this.refs.containerCanvas.getDOMNode() 54 | var context = canvas.getContext('2d'); 55 | var thisEl = React.findDOMNode(this) 56 | if (thisEl) { 57 | for (var index in this.props.nodes) { 58 | var node = this.props.nodes[index] 59 | for (var bindex in node.branches) { 60 | var branchId = node.branches[bindex].branchId 61 | var start = thisEl.querySelector('#handle-'+branchId) 62 | var finish = thisEl.querySelector('#end-'+branchId) 63 | if (finish) { 64 | var scoords = start.getBoundingClientRect() 65 | var fcoords = finish.getBoundingClientRect() 66 | var ccoords = thisEl.getBoundingClientRect() 67 | 68 | var smidx = scoords.left + (scoords.width / 2) 69 | var smidy = scoords.top + (scoords.height / 2) 70 | var fmidx = fcoords.left 71 | var fmidy = fcoords.top + (fcoords.height / 2) 72 | 73 | context.beginPath(); 74 | context.moveTo(smidx - ccoords.left, smidy - ccoords.top); 75 | context.lineTo(fmidx - ccoords.left, fmidy - ccoords.top); 76 | context.stroke(); 77 | } 78 | } 79 | } 80 | } 81 | }, 82 | 83 | _collectNodeIn : function () { 84 | var nodes = {} 85 | for (var index in this.props.nodes) { 86 | if (this.props.nodes[index].branches) { 87 | for (var bindex in this.props.nodes[index].branches) { 88 | var branch = this.props.nodes[index].branches[bindex] 89 | if (branch.nodeId) { 90 | if (!nodes[branch.nodeId]) { 91 | nodes[branch.nodeId] = [] 92 | } 93 | nodes[branch.nodeId].push(branch) 94 | } 95 | } 96 | } 97 | } 98 | return nodes 99 | }, 100 | 101 | _branchUsed : function (nodeIn, branchId) { 102 | for (var index in nodeIn) { 103 | for (var bindex in nodeIn[index]) { 104 | if (nodeIn[index][bindex].branchId === branchId) { 105 | return true 106 | } 107 | } 108 | } 109 | return false 110 | }, 111 | 112 | _dropNode : function (node, coords) { 113 | var thisEl = React.findDOMNode(this) 114 | var offset = thisEl.getBoundingClientRect() 115 | var offsetCoords = { 116 | x: coords.x - offset.left, 117 | y: coords.y - offset.top 118 | } 119 | this.props.dropNode(node, offsetCoords) 120 | }, 121 | 122 | render : function() { 123 | var nodes = [] 124 | var nodeIn = this._collectNodeIn() 125 | for (var index in this.props.nodes) { 126 | var node = this.props.nodes[index] 127 | var branchesIn = [] 128 | if (nodeIn[node.nodeId]) { 129 | var branchesIn = nodeIn[node.nodeId] 130 | } 131 | 132 | var x = (node.x) ? node.x : 0 133 | var y = (node.y) ? node.y : 0 134 | 135 | nodes.push() 148 | } 149 | 150 | var connectDropTarget = this.props.connectDropTarget; 151 | var isOver = this.props.isOver; 152 | 153 | var html = 154 | connectDropTarget( 155 |
156 |
157 | {nodes} 158 | {isOver && 159 |
160 | } 161 | 162 | 163 |
164 |
165 | ) 166 | return html 167 | } 168 | 169 | }) 170 | 171 | var containerTarget = { 172 | drop: function (props, monitor) { 173 | var item = monitor.getItem() 174 | var node = item.node 175 | var coords = monitor.getSourceClientOffset() 176 | item.dropNode(node, coords) 177 | } 178 | }; 179 | 180 | function collect(connect, monitor) { 181 | return { 182 | connectDropTarget: connect.dropTarget(), 183 | isOver: monitor.isOver() 184 | }; 185 | } 186 | 187 | 188 | 189 | var DropContainer = dnd.DropTarget(ItemTypes.nodeContainer, containerTarget, collect)(Container); 190 | 191 | 192 | module.exports = dnd.DragDropContext(HTML5Backend)(DropContainer); 193 | 194 | -------------------------------------------------------------------------------- /lib/node-target.jsx: -------------------------------------------------------------------------------- 1 | 2 | var dnd = require('react-dnd') 3 | var React = require('react') 4 | 5 | var ItemTypes = require('./constants.json').ItemTypes 6 | 7 | 8 | 9 | var nodeInTarget = { 10 | drop: function (props, monitor) { 11 | var item = monitor.getItem() 12 | item.dropBranch(item.branch, props.node) 13 | } 14 | }; 15 | 16 | function collect(connect, monitor) { 17 | return { 18 | connectDropTarget: connect.dropTarget(), 19 | isOver: monitor.isOver() 20 | }; 21 | } 22 | 23 | 24 | var NodeIn = React.createClass({ 25 | propTypes: { 26 | connectDropTarget: React.PropTypes.func.isRequired, 27 | isOver: React.PropTypes.bool.isRequired 28 | }, 29 | 30 | render: function () { 31 | var connectDropTarget = this.props.connectDropTarget; 32 | var isOver = this.props.isOver; 33 | 34 | return connectDropTarget( 35 |
36 | {this.props.branchesIn} 37 | {isOver && 38 |
39 | } 40 |
41 | ); 42 | } 43 | }) 44 | 45 | var NodeTarget = module.exports = dnd.DropTarget(ItemTypes.branchOut, nodeInTarget, collect)(NodeIn); 46 | -------------------------------------------------------------------------------- /lib/style.css: -------------------------------------------------------------------------------- 1 | 2 | .rf-containerCanvas { 3 | position: absolute; 4 | top: 0px; 5 | left: 0px; 6 | z-index: 99; 7 | pointer-events: none; 8 | } 9 | 10 | .rf-containerDragHover { 11 | position: absolute; 12 | top: 0px; 13 | left: 0px; 14 | height: 100%; 15 | width: 100%; 16 | z-index: 1; 17 | opacity: 0.5; 18 | } 19 | 20 | .rf-container { 21 | position: relative; 22 | width: 100%; 23 | height: 100%; 24 | } 25 | 26 | .rf-nodeDragHover { 27 | position: relative; 28 | top: 0px; 29 | left: 0px; 30 | height: 100%; 31 | width: 100%; 32 | z-index: 1; 33 | opacity: 0.5; 34 | } 35 | 36 | .rf-dropTarget { 37 | width: 100%; 38 | height: 100%; 39 | } 40 | 41 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "react-flowchart", 3 | "version": "1.3.5", 4 | "description": "An interactive flowchart using React", 5 | "main": "index.js", 6 | "repository": { 7 | "type": "git", 8 | "url": "git@github.com:wunderlink/react-flowchart.git" 9 | }, 10 | "browserify": { 11 | "transform": [ 12 | "reactify", 13 | "envify", 14 | "cssify" 15 | ] 16 | }, 17 | "directories": { 18 | "example": "example", 19 | "test": "test" 20 | }, 21 | "scripts": { 22 | "test": "node test/index.js", 23 | "example": "beefy example/index.jsx", 24 | "simplest": "beefy example/simplest.jsx" 25 | }, 26 | "keywords": [], 27 | "author": "Tyler Bushnell ", 28 | "license": "MIT", 29 | "dependencies": { 30 | "cssify": "^0.6.0", 31 | "envify": "^3.2.0", 32 | "react": "^0.13.3", 33 | "react-dnd": "^1.1.4", 34 | "reactify": "^1.0.0" 35 | }, 36 | "devDependencies": { 37 | "node-uuid": "^1.4.3", 38 | "beefy": "^2.1.5", 39 | "browserify": "^11.0.1", 40 | "react-tap-event-plugin": "^0.1.7", 41 | "tape": "^4.0.0", 42 | "watchify": "^3.3.1" 43 | } 44 | } 45 | -------------------------------------------------------------------------------- /test/index.js: -------------------------------------------------------------------------------- 1 | 2 | 3 | var tape = require('tape') 4 | 5 | tape('Test Something', function (t) { 6 | t.end() 7 | }) 8 | --------------------------------------------------------------------------------