diff --git a/README.md b/README.md index 3e738aaa..84e15e10 100644 --- a/README.md +++ b/README.md @@ -167,6 +167,10 @@ const targetHandleWithValidation = ( - `style`: css properties - `className`: additional class name +### Validation + +The handle receives the additional class names `connecting` when the connection line is above the handle and `valid` if the connection is valid. You can find an example which uses these classes [here](/example/src/Validation/index.js). + ### Multiple Handles If you need multiple source or target handles you can achieve this by creating a custom node. Normally you just use the id of a node for the `source` or `target` of an edge. If you have multiple source or target handles you need to pass an id to these handles. These ids get then added to the node id, so that you can connect a specific handle. If you have a node with an id = `1` and a handle with an id = `a` you can connect this handle by using the id = `1__a`. @@ -345,6 +349,8 @@ The React Flow wrapper has the className `react-flow`. If you want to change the * `.top` is added when position = 'top' * `.left` is added when position = 'left' * `.right` is added when position = 'right' + * `.connecting` is added when connection line is above a handle + * `.valid` is added when connection line is above a handle and the connection is valid * `.react-flow__background` - Background component * `.react-flow__minimap` - Mini map component * `.react-flow__controls` - Controls component diff --git a/example/src/Validation/index.js b/example/src/Validation/index.js new file mode 100644 index 00000000..23a2174e --- /dev/null +++ b/example/src/Validation/index.js @@ -0,0 +1,44 @@ +import React, { useState } from 'react'; + +import ReactFlow, { addEdge, Handle } from 'react-flow-renderer'; + +import './validation.css'; + +const initialElements = [ + { id: '0', type: 'custominput', position: { x: 0, y: 150 } }, + { id: 'A', data: { label : 'A' }, position: { x: 250, y: 0 }, targetPosition: 'left', sourcePosition: 'right' }, + { id: 'B', data: { label : 'B' }, position: { x: 250, y: 150 }, targetPosition: 'left', sourcePosition: 'right' }, + { id: 'C', data: { label : 'C' }, position: { x: 250, y:300 }, targetPosition: 'left', sourcePosition: 'right' }, +]; + +const CustomInput = () => ( + <> +
Only connectable with B
+ connection.target === 'B'} + /> + +); + +const HorizontalFlow = () => { + const [elements, setElements] = useState(initialElements); + const onConnect = (params) => setElements(els => addEdge(params, els)); + + return ( + reactflowInstance.fitView()} + className="validationflow" + nodeTypes={{ + custominput: CustomInput + }} + /> + ); +} + +export default HorizontalFlow; diff --git a/example/src/Validation/validation.css b/example/src/Validation/validation.css new file mode 100644 index 00000000..0b7acd76 --- /dev/null +++ b/example/src/Validation/validation.css @@ -0,0 +1,23 @@ +.validationflow .react-flow__node { + background: #e6e6e9; + border: 1px solid #ddd; +} + +.validationflow .react-flow__node-custominput { + width: 150px; + border-radius: 5px; + padding: 10px; + background: #fff; + color: #555; + border: 1px solid #ddd; + text-align: center; + font-size: 12px; +} + +.validationflow .connecting { + background: #ff6060; +} + +.validationflow .connecting.valid { + background: #55dd99; +} \ No newline at end of file diff --git a/example/src/index.css b/example/src/index.css index 830e6fa4..825917fe 100644 --- a/example/src/index.css +++ b/example/src/index.css @@ -141,6 +141,14 @@ nav a.active:before { color: #f8f8f8; } +.react-flow__node-selectorNode { + font-size: 12px; + background: #eee; + border: 1px solid #555; + border-radius: 5px; + text-align: center; +} + @media screen and (min-width: 768px) { nav { position: relative; diff --git a/example/src/index.js b/example/src/index.js index 7f83d66f..831a7b10 100644 --- a/example/src/index.js +++ b/example/src/index.js @@ -9,6 +9,7 @@ import Stress from './Stress'; import Inactive from './Inactive'; import Empty from './Empty'; import Edges from './Edges'; +import Validation from './Validation'; import Horizontal from './Horizontal'; import './index.css'; @@ -33,6 +34,10 @@ const routes = [{ path: '/horizontal', component: Horizontal, label: 'Horizontal' +}, { + path: '/validation', + component: Validation, + label: 'Validation' }, { path: '/stress', component: Stress, diff --git a/src/style.css b/src/style.css index 44ecc5f9..ae31089c 100644 --- a/src/style.css +++ b/src/style.css @@ -102,13 +102,10 @@ .react-flow__node { position: absolute; - color: #222; - text-align: center; user-select: none; pointer-events: all; transform-origin: 0 0; cursor: grab; - background: #eee; &.selected, &.selected:hover { @@ -124,28 +121,28 @@ } } -.react-flow__node-default { - padding: 10px; - border-radius: 5px; - width: 150px; - background: #ff6060; - font-size: 12px; -} - -.react-flow__node-input { - padding: 10px; - border-radius: 5px; - width: 150px; - background: #9999ff; - font-size: 12px; -} - +.react-flow__node-default, +.react-flow__node-input, .react-flow__node-output { padding: 10px; border-radius: 5px; width: 150px; - background: #55dd99; font-size: 12px; + color: #222; + text-align: center; +} + +.react-flow__node-default { + background: #ff6060; +} + +.react-flow__node-input { + background: #9999ff; +} + +.react-flow__node-output { + background: #55dd99; + } .react-flow__nodesselection { @@ -196,4 +193,4 @@ top: 50%; transform: translate(0, -50%); } -} +} \ No newline at end of file