├── .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 | 
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 |
--------------------------------------------------------------------------------