Files
xyflow/example/SimpleGraph.js
2019-09-11 17:58:18 +02:00

205 lines
6.3 KiB
JavaScript
Raw Blame History

This file contains invisible Unicode characters

This file contains invisible Unicode characters that are indistinguishable to humans but may be processed differently by a computer. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

import React, { PureComponent } from 'react';
import Graph, { isEdge, removeElements, getOutgoers, SourceHandle, TargetHandle, MiniMap } from '../src';
// import Graph, { isEdge, removeElements, getOutgoers, SourceHandle, TargetHandle } from '../dist/ReactGraph';
const SpecialNode = ({ data, styles }) => (
<div
style={{ background: '#FFCC00', padding: 10, borderRadius: 2, ...styles }}
>
<TargetHandle id="a" style={{ left: 10, background: '#999' }} />
<TargetHandle id="b" style={{ left: 30, background: '#999' }} />
<div>I am <strong>special</strong>!<br />{data.label}</div>
<select onChange={(e) => data.onChange(e.target.value, data)}>
<option value="1">1</option>
<option value="2">2</option>
<option value="3">3</option>
</select>
<SourceHandle style={{ left: 10, background: '#999' }} />
</div>
);
const InputNode = ({ data, styles }) => (
<div
style={{ background: '#FFCC00', padding: 10, borderRadius: 2, ...styles }}
>
<TargetHandle style={{ left: 10, background: '#999' }} />
<div>{data.input}</div>
<input onChange={(e) => data.onChange(e.target.value, data)} />
<SourceHandle style={{ left: 10, background: '#999' }} />
</div>
);
const onNodeDragStop = node => console.log('drag stop', node);
class App extends PureComponent {
constructor() {
super();
const onChange = (option, d) => {
this.setState(prevState => (
{elements: prevState.elements.map(e => {
if (isEdge(e) || e.id !== '6') {
return e;
}
return { ...e, data: { ...e.data, label: `Option ${option} selected.` } };
})}
));
}
const onChangeInput = (input, d) => {
this.setState(prevState => (
{elements: prevState.elements.map(e => {
if (isEdge(e) || e.id !== '8') {
return e;
}
if (e.id === '8') {
return { ...e, data: { ...e.data, input: input || 'write something' } };
}
})}
));
}
this.state = {
graphLoaded: false,
elements: [
{ id: '1', type: 'input', data: { label: '1 Tests' }, position: { x: 250, y: 5 } },
{ id: '2', data: { label: '2 This is a node This is a node This is a node This is a node' }, position: { x: 100, y: 100 } },
{ id: '3', data: { label: '3 I bring my own style' }, position: { x: 100, y: 200 }, style: { background: '#eee', color: '#222', border: '1px solid #bbb' } },
{ id: '4', type: 'output', data: { label: '4 nody nodes' }, position: { x: 50, y: 300 } },
{ id: '5', type: 'default', data: { label: '5 Another node'}, position: { x: 400, y: 300 } },
{ id: '6', type: 'special', data: { onChange, label: '6 no option selected' }, position: { x: 425, y: 375 } },
{ id: '7', type: 'output', data: { label: '7 output' }, position: { x: 250, y: 500 } },
{ id: '8', type: 'text', data: { onChange: onChangeInput, input: 'write something' }, position: { x: 300, y: 100 } },
{ source: '1', target: '2', animated: true },
{ source: '1', target: '8', animated: true },
{ source: '2', target: '3' },
{ source: '3', target: '4', type: 'step' },
{ source: '3', target: '5' },
{ source: '5', target: '6__b' },
{ source: '5', target: '6', type: 'step', animated: true, style: { stroke: '#FFCC00' } },
{ source: '6', target: '7', style: { stroke: '#FFCC00' }},
]
};
this.onElementClick = this.onElementClick.bind(this);
this.onConnect = this.onConnect.bind(this);
}
onLoad(graphInstance) {
console.log('graph loaded:', graphInstance);
window.rg = graphInstance;
this.graphInstance = graphInstance;
this.graphInstance.fitView({ padding: 0.1 });
this.setState({
graphLoaded: true
});
}
onFitView() {
this.graphInstance.fitView();
}
onAdd() {
this.setState(prevState => ({
...prevState,
elements: prevState.elements.concat({
id: (prevState.elements.length + 1).toString(),
data: { label: 'Added node' },
position: { x: Math.random() * window.innerWidth, y: Math.random() * window.innerHeight }
})
}));
}
onElementClick(element) {
console.log('click', element);
console.log('outgoers', getOutgoers(element, this.state.elements));
}
onZoomIn() {
this.graphInstance.zoomIn();
}
onZoomOut() {
this.graphInstance.zoomOut();
}
onElementsRemove(elementsToRemove) {
this.setState(prevState => ({
elements: removeElements(prevState.elements, elementsToRemove)
}));
}
onConnect(params) {
console.log('connect', params);
this.setState(prevState => ({
elements: prevState.elements.concat(params)
}));
}
render() {
return (
<Graph
elements={this.state.elements}
onElementClick={this.onElementClick}
onElementsRemove={elements => this.onElementsRemove(elements)}
onConnect={this.onConnect}
onNodeDragStop={onNodeDragStop}
style={{ width: '100%', height: '100%' }}
onLoad={graphInstance => this.onLoad(graphInstance)}
nodeTypes={{
special: SpecialNode,
text: InputNode
}}
connectionLineStyle={{ stroke: '#ddd', strokeWidth: 2 }}
connectionLineType="bezier"
>
<MiniMap
style={{ position: 'absolute', right: 10, bottom: 10 }}
nodeColor={n => {
if (n.type === 'input') return 'blue';
if (n.type === 'output') return 'green';
if (n.type === 'default') return 'red';
return '#FFCC00';
}}
/>
<button
type="button"
onClick={() => this.onAdd()}
style={{ position: 'absolute', right: 10, top: 10, zIndex: 4 }}
>
add
</button>
{this.state.graphLoaded && (
<div className="controls">
<button
type="button"
onClick={() => this.onFitView()}
>
fit
</button>
<button
type="button"
onClick={() => this.onZoomIn()}
>
zoom in
</button>
<button
type="button"
onClick={() => this.onZoomOut()}
>
zoom out
</button>
</div>
)}
</Graph>
);
}
}
export default App;