docs(website): texts, docs, examples, favicon, cleanup
@@ -31,12 +31,12 @@ module.exports = {
|
||||
{
|
||||
resolve: `gatsby-plugin-manifest`,
|
||||
options: {
|
||||
icon: `src/assets/icons/favicon.svg`,
|
||||
icon: `src/assets/images/react-flow-logo.svg`,
|
||||
name: `React Flow`,
|
||||
short_name: `react-flow`,
|
||||
start_url: `/`,
|
||||
background_color: `#f7f0eb`,
|
||||
theme_color: `#a2466c`,
|
||||
theme_color: `#1A192B`,
|
||||
display: `standalone`,
|
||||
lang: 'en',
|
||||
},
|
||||
|
||||
@@ -1,17 +1,7 @@
|
||||
[
|
||||
{
|
||||
"title": "Showcase 1",
|
||||
"url": "https://github.com",
|
||||
"image": "../images/showcases/showcase.jpg"
|
||||
},
|
||||
{
|
||||
"title": "Showcase 2",
|
||||
"url": "https://github.com",
|
||||
"image": "../images/showcases/showcase.jpg"
|
||||
},
|
||||
{
|
||||
"title": "Showcase 3",
|
||||
"url": "https://github.com",
|
||||
"image": "../images/showcases/showcase.jpg"
|
||||
"title": "Circles - Visual degree planner",
|
||||
"url": "https://circles360.github.io/",
|
||||
"image": "../images/showcases/circles-showcase.png"
|
||||
}
|
||||
]
|
||||
|
||||
@@ -1,4 +0,0 @@
|
||||
<svg width="342" height="342" viewBox="0 0 342 342" fill="none" xmlns="http://www.w3.org/2000/svg">
|
||||
<path d="M123.5 290L19 48L228 48L123.5 290Z" fill="#C5CBD2"/>
|
||||
<path d="M218.5 290L114 48L323 48L218.5 290Z" fill="#1A192B"/>
|
||||
</svg>
|
||||
|
Before Width: | Height: | Size: 232 B |
|
After Width: | Height: | Size: 162 KiB |
|
Before Width: | Height: | Size: 78 KiB |
|
Before Width: | Height: | Size: 78 KiB |
|
Before Width: | Height: | Size: 78 KiB |
@@ -18,21 +18,26 @@ export default ({ children, className = 'javascript', language }) => {
|
||||
style={{
|
||||
...style,
|
||||
overflowX: 'auto',
|
||||
padding: '20px',
|
||||
borderRadius: '6px',
|
||||
margin: '40px 0 40px 0',
|
||||
padding: 16,
|
||||
borderRadius: 4,
|
||||
margin: '20px 0 20px 0',
|
||||
fontSize: 14,
|
||||
}}
|
||||
>
|
||||
{tokens
|
||||
.filter((line) => line.some((l) => l.content))
|
||||
.map((line, i) => (
|
||||
<div key={i} {...getLineProps({ line, key: i })}>
|
||||
{line.map((token, key) => (
|
||||
<span key={key} {...getTokenProps({ token, key })} />
|
||||
))}
|
||||
</div>
|
||||
))}
|
||||
{tokens.map(
|
||||
(line, i, lines) =>
|
||||
!(
|
||||
line.length === 1 &&
|
||||
line[0].empty &&
|
||||
(i === 0 || i === lines.length - 1)
|
||||
) && (
|
||||
<div key={i} {...getLineProps({ line, key: i })}>
|
||||
{line.map((token, key) => (
|
||||
<span key={key} {...getTokenProps({ token, key })} />
|
||||
))}
|
||||
</div>
|
||||
)
|
||||
)}
|
||||
</pre>
|
||||
)}
|
||||
</Highlight>
|
||||
|
||||
@@ -3,11 +3,11 @@ import styled from '@emotion/styled';
|
||||
import { Box } from 'reflexbox';
|
||||
|
||||
import { colors } from 'themes';
|
||||
import CodeBlock from 'components/Mdx/CodeBlock';
|
||||
import CodeBlock from './Mdx';
|
||||
import { H4, AttributionText } from 'components/Typo';
|
||||
|
||||
const Wrapper = styled(Box)`
|
||||
max-width: 800px;
|
||||
max-width: 750px;
|
||||
margin: 0 auto;
|
||||
|
||||
h4 {
|
||||
|
||||
@@ -1,30 +0,0 @@
|
||||
import React from 'react';
|
||||
import styled from '@emotion/styled';
|
||||
import { Flex } from 'reflexbox';
|
||||
import { Link } from 'gatsby';
|
||||
|
||||
import Button from 'components/Button';
|
||||
import { H3 } from 'components/Typo';
|
||||
import { getThemeSpacePx } from 'utils/css-utils';
|
||||
|
||||
const Wrapper = styled(Flex)`
|
||||
text-align: center;
|
||||
|
||||
${H3} {
|
||||
margin-bottom: ${getThemeSpacePx(3)};
|
||||
}
|
||||
`;
|
||||
|
||||
export default ({
|
||||
caption = 'Are you interested in a collaboration?',
|
||||
...props
|
||||
}) => {
|
||||
return (
|
||||
<Wrapper alignItems="center" px={2} flexDirection="column" {...props}>
|
||||
<H3 as="div">{caption}</H3>
|
||||
<Button as={Link} to="/contact" icon="mail">
|
||||
Contact us
|
||||
</Button>
|
||||
</Wrapper>
|
||||
);
|
||||
};
|
||||
@@ -209,10 +209,10 @@ const Header = () => {
|
||||
<NavItem to="/" activeClassName="active" className="mobile">
|
||||
Home
|
||||
</NavItem>
|
||||
<NavItem to="/docs" activeClassName="active">
|
||||
<NavItem to="/docs/" activeClassName="active">
|
||||
Docs
|
||||
</NavItem>
|
||||
<NavItem to="/examples" activeClassName="active">
|
||||
<NavItem to="/examples/" activeClassName="active">
|
||||
Examples
|
||||
</NavItem>
|
||||
|
||||
|
||||
@@ -1,33 +0,0 @@
|
||||
import React from 'react';
|
||||
import Highlight, { defaultProps } from 'prism-react-renderer';
|
||||
import dracula from 'prism-react-renderer/themes/github';
|
||||
|
||||
export default ({ children, className = 'javascript', language }) => {
|
||||
const lang = language ? language : className.replace(/language-/, '');
|
||||
|
||||
return (
|
||||
<Highlight
|
||||
{...defaultProps}
|
||||
theme={dracula}
|
||||
code={children}
|
||||
language={lang}
|
||||
>
|
||||
{({ className, style, tokens, getLineProps, getTokenProps }) => (
|
||||
<pre
|
||||
className={className}
|
||||
style={{ ...style, overflowX: 'auto', padding: '20px' }}
|
||||
>
|
||||
{tokens
|
||||
.filter((line) => line.some((l) => l.content))
|
||||
.map((line, i) => (
|
||||
<div key={i} {...getLineProps({ line, key: i })}>
|
||||
{line.map((token, key) => (
|
||||
<span key={key} {...getTokenProps({ token, key })} />
|
||||
))}
|
||||
</div>
|
||||
))}
|
||||
</pre>
|
||||
)}
|
||||
</Highlight>
|
||||
);
|
||||
};
|
||||
@@ -1,58 +0,0 @@
|
||||
import React from 'react';
|
||||
import styled from '@emotion/styled';
|
||||
|
||||
import { MDXProvider } from '@mdx-js/react';
|
||||
import { MDXRenderer } from 'gatsby-plugin-mdx';
|
||||
|
||||
import { H1, H2, H3, H4, Text } from 'components/Typo';
|
||||
import CodeBlock from 'components/Mdx/CodeBlock';
|
||||
import CenterContent from 'components/CenterContent';
|
||||
|
||||
const doNotWrap = ['BlogpostAd'];
|
||||
|
||||
const MdxWrapper = ({ children }) => {
|
||||
return children.map((child, i) =>
|
||||
doNotWrap.includes(child.props?.mdxType) ? (
|
||||
child
|
||||
) : (
|
||||
<CenterContent key={i} mb={2} maxWidth="680px">
|
||||
{child}
|
||||
</CenterContent>
|
||||
)
|
||||
);
|
||||
};
|
||||
|
||||
const PostWrapper = styled.div`
|
||||
img {
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
.gatsby-resp-image-wrapper {
|
||||
border: 1px solid ${(p) => p.theme.colors.silver};
|
||||
border-radius: 2px;
|
||||
overflow: hidden;
|
||||
}
|
||||
`;
|
||||
|
||||
const CustomComponents = {
|
||||
h1: H1,
|
||||
h2: H2,
|
||||
h3: H3,
|
||||
h4: H4,
|
||||
p: Text,
|
||||
pre: (props) => <div {...props} />,
|
||||
code: CodeBlock,
|
||||
wrapper: MdxWrapper,
|
||||
};
|
||||
|
||||
const Mdx = ({ content = null }) => {
|
||||
return (
|
||||
<MDXProvider components={CustomComponents}>
|
||||
<PostWrapper>
|
||||
<MDXRenderer>{content}</MDXRenderer>
|
||||
</PostWrapper>
|
||||
</MDXProvider>
|
||||
);
|
||||
};
|
||||
|
||||
export default Mdx;
|
||||
@@ -1,100 +0,0 @@
|
||||
import React from 'react';
|
||||
import styled from '@emotion/styled';
|
||||
import { Box } from 'reflexbox';
|
||||
import { Link } from 'gatsby';
|
||||
import Img from 'gatsby-image';
|
||||
|
||||
import { H2, H4, TextLight } from 'components/Typo';
|
||||
import { getThemeColor, getThemeSpacePx, device } from 'utils/css-utils';
|
||||
|
||||
const Teaser = styled(Box)`
|
||||
position: relative;
|
||||
|
||||
.gatsby-image-wrapper {
|
||||
transition: transform 200ms ease, box-shadow 200ms ease;
|
||||
}
|
||||
|
||||
&:hover {
|
||||
.gatsby-image-wrapper {
|
||||
transform-origin: center center;
|
||||
transform: scale(1.025);
|
||||
box-shadow: 0 2px 14px 2px rgba(0, 0, 0, 0.25);
|
||||
}
|
||||
}
|
||||
`;
|
||||
|
||||
const StyledImg = styled(Img)`
|
||||
border-radius: 4px;
|
||||
margin-bottom: ${getThemeSpacePx(3)};
|
||||
`;
|
||||
|
||||
const ReadMore = styled(Box)`
|
||||
color: ${(p) => p.theme.colors.text};
|
||||
|
||||
&:hover {
|
||||
opacity: 0.6;
|
||||
}
|
||||
`;
|
||||
|
||||
const TextWrapper = styled.div`
|
||||
padding: 0;
|
||||
position: relative;
|
||||
top: 0;
|
||||
left: 0;
|
||||
width: 100%;
|
||||
z-index: 10;
|
||||
|
||||
&& {
|
||||
a,
|
||||
a:visited,
|
||||
a:hover,
|
||||
a:focus,
|
||||
a:active {
|
||||
color: ${getThemeColor('silverLighten60')};
|
||||
}
|
||||
}
|
||||
|
||||
${TextLight} {
|
||||
color: ${getThemeColor('silverDarken30')};
|
||||
}
|
||||
|
||||
${H2} {
|
||||
color: ${getThemeColor('silverLighten60')};
|
||||
margin-top: 5px;
|
||||
}
|
||||
|
||||
${H4} {
|
||||
font-weight: 400;
|
||||
color: ${getThemeColor('silverDarken30')};
|
||||
}
|
||||
|
||||
@media ${device.tablet} {
|
||||
width: 80%;
|
||||
}
|
||||
`;
|
||||
|
||||
const ProjectTeaser = ({
|
||||
kicker = '',
|
||||
title = '',
|
||||
text = '',
|
||||
fluid = null,
|
||||
slug = '/',
|
||||
}) => {
|
||||
return (
|
||||
<Link to={slug}>
|
||||
<Teaser mb={[4, 5, 6]}>
|
||||
<StyledImg fluid={fluid} />
|
||||
|
||||
<TextWrapper>
|
||||
<TextLight>{kicker}</TextLight>
|
||||
<H2 as="div">{title}</H2>
|
||||
<H4 as="div">{text}</H4>
|
||||
|
||||
<ReadMore mt={3}>Read more</ReadMore>
|
||||
</TextWrapper>
|
||||
</Teaser>
|
||||
</Link>
|
||||
);
|
||||
};
|
||||
|
||||
export default ProjectTeaser;
|
||||
@@ -1,133 +0,0 @@
|
||||
import React from 'react';
|
||||
import styled from '@emotion/styled';
|
||||
import { Box } from 'reflexbox';
|
||||
import { Link } from 'gatsby';
|
||||
|
||||
import { H3, H2, H4, TextLight, Text } from 'components/Typo';
|
||||
import {
|
||||
px,
|
||||
getThemeColor,
|
||||
getThemeSpacePx,
|
||||
rgba,
|
||||
device,
|
||||
} from 'utils/css-utils';
|
||||
|
||||
const Wrapper = styled(Box)`
|
||||
border-radius: 6px;
|
||||
background: ${(props) =>
|
||||
props.isDark
|
||||
? props.theme.colors.dark.cardBackground
|
||||
: props.theme.colors.light.background};
|
||||
background-image: ${(props) =>
|
||||
props.imgSrc ? `url(${props.imgSrc})` : 'none'};
|
||||
background-repeat: no-repeat;
|
||||
background-position: ${(props) => props.imgPosition};
|
||||
color: ${(p) => p.theme.colors[p.isDark ? 'dark' : 'light'].text};
|
||||
background-size: cover;
|
||||
flex-grow: 1;
|
||||
height: 270px;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
|
||||
&.scale {
|
||||
transition: transform 200ms ease, box-shadow 200ms ease;
|
||||
transform-style: preserve-3d;
|
||||
backface-visibility: hidden;
|
||||
|
||||
&:hover {
|
||||
transform-origin: center center;
|
||||
transform: scale(1.02);
|
||||
box-shadow: 0 2px 12px 2px rgba(0, 0, 0, 0.45);
|
||||
}
|
||||
}
|
||||
|
||||
&& {
|
||||
a,
|
||||
a:visited,
|
||||
a:hover,
|
||||
a:focus,
|
||||
a:active {
|
||||
color: ${(p) => p.theme.colors[p.isDark ? 'dark' : 'light'].text};
|
||||
}
|
||||
}
|
||||
`;
|
||||
|
||||
const getTextShadow = (props) => {
|
||||
const color = props.theme.colors[props.isDark ? 'light' : 'dark'].text;
|
||||
const rgbaColor = rgba(color, props.isDark ? 0.2 : 0.8);
|
||||
return `-1px 0 14px ${rgbaColor}, 0 1px 14px ${rgbaColor}, 1px 0 14px ${rgbaColor}, 0 -1px 14px ${rgbaColor};`;
|
||||
};
|
||||
|
||||
const TextWrapper = styled.div`
|
||||
padding: ${getThemeSpacePx(3)};
|
||||
position: relative;
|
||||
top: 0;
|
||||
left: 0;
|
||||
width: 100%;
|
||||
z-index: 10;
|
||||
text-shadow: ${getTextShadow};
|
||||
|
||||
${H2} {
|
||||
margin-top: 5px;
|
||||
}
|
||||
|
||||
${H3} {
|
||||
margin-top: 5px;
|
||||
}
|
||||
|
||||
${TextLight} {
|
||||
color: ${(p) =>
|
||||
p.isDark
|
||||
? getThemeColor('silverDarken30')
|
||||
: getThemeColor('silverDarken60')};
|
||||
}
|
||||
|
||||
${Text} {
|
||||
color: ${(p) =>
|
||||
p.isDark
|
||||
? getThemeColor('silverDarken30')
|
||||
: getThemeColor('silverDarken60')};
|
||||
}
|
||||
|
||||
${H4} {
|
||||
color: ${getThemeColor('silverDarken30')};
|
||||
}
|
||||
|
||||
@media ${device.tablet} {
|
||||
width: 50%;
|
||||
}
|
||||
`;
|
||||
|
||||
const ProjectTeaser = ({
|
||||
kicker = '',
|
||||
title = '',
|
||||
text = '',
|
||||
imgSrc = null,
|
||||
isDark = false,
|
||||
imgPosition = null,
|
||||
imgSize = '100%',
|
||||
slug = '/',
|
||||
hoverEffect = null,
|
||||
}) => {
|
||||
const imagePosition = imgPosition ? imgPosition : 'center right';
|
||||
|
||||
return (
|
||||
<Link to={slug}>
|
||||
<Wrapper
|
||||
imgSrc={imgSrc}
|
||||
isDark={isDark}
|
||||
imgPosition={imagePosition}
|
||||
imgSize={imgSize}
|
||||
className={hoverEffect}
|
||||
>
|
||||
<TextWrapper isDark={isDark}>
|
||||
<TextLight>{kicker}</TextLight>
|
||||
<H3 as="div">{title}</H3>
|
||||
<Text as="div">{text}</Text>
|
||||
</TextWrapper>
|
||||
</Wrapper>
|
||||
</Link>
|
||||
);
|
||||
};
|
||||
|
||||
export default ProjectTeaser;
|
||||
@@ -5,13 +5,25 @@ import Img from 'gatsby-image';
|
||||
|
||||
import CenterContent from 'components/CenterContent';
|
||||
import useShowcaseImages from 'hooks/useShowcaseImages';
|
||||
import { H4 } from 'components/Typo';
|
||||
import { H4, Text } from 'components/Typo';
|
||||
import { getThemeColor } from 'utils/css-utils';
|
||||
import reactFlowIconSrc from 'assets/images/react-flow-logo.svg';
|
||||
|
||||
const gridPadding = 2;
|
||||
|
||||
const RoundImage = styled(Img)`
|
||||
border-radius: 4px;
|
||||
height: 250px;
|
||||
transition: transform 200ms ease;
|
||||
`;
|
||||
|
||||
const EmptyCase = styled(Box)`
|
||||
border-radius: 4px;
|
||||
height: 250px;
|
||||
background: ${(p) => p.theme.colors.silverLighten60};
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
`;
|
||||
|
||||
const Title = styled(H4)`
|
||||
@@ -26,25 +38,42 @@ const Link = styled.a`
|
||||
|
||||
&:hover {
|
||||
color: ${getThemeColor('silverLighten15')};
|
||||
|
||||
${RoundImage} {
|
||||
transform: scale(1.025);
|
||||
}
|
||||
}
|
||||
}
|
||||
`;
|
||||
|
||||
const Showcases = () => {
|
||||
const showcases = useShowcaseImages();
|
||||
const emptyShowCases = [...Array(3 - showcases.length).keys()];
|
||||
|
||||
return (
|
||||
<CenterContent>
|
||||
<Flex marginX={-gridPadding}>
|
||||
{showcases.map((showcase) => (
|
||||
<Box key={showcase.title} width={1 / 3} px={gridPadding}>
|
||||
<RoundImage fluid={showcase.image.childImageSharp.fluid} />
|
||||
<Title>{showcase.title}</Title>
|
||||
<Link href={showcase.url} target="_blank" rel="noopener noreferrer">
|
||||
<RoundImage fluid={showcase.image.childImageSharp.fluid} />
|
||||
<Title>{showcase.title}</Title>
|
||||
|
||||
{showcase.url}
|
||||
</Link>
|
||||
</Box>
|
||||
))}
|
||||
{emptyShowCases.map((index) => (
|
||||
<Box key={index} width={1 / 3} px={gridPadding}>
|
||||
<EmptyCase>
|
||||
<img src={reactFlowIconSrc} alt="react flow logo" />
|
||||
</EmptyCase>
|
||||
<Title>Your Project here</Title>
|
||||
<Text color="silverDarken15">
|
||||
Let us know if you made something with React Flow.
|
||||
</Text>
|
||||
</Box>
|
||||
))}
|
||||
</Flex>
|
||||
</CenterContent>
|
||||
);
|
||||
|
||||
@@ -80,7 +80,7 @@ const flowProps = {
|
||||
export default () => (
|
||||
<TeaserFlow
|
||||
title="Feature-rich"
|
||||
description="You only need a few lines to get started. You get seamless zooming & panning, different edge and node types, single and multi-selection, controls and more."
|
||||
description="React Flow comes with seamless zooming & panning, different edge and node types, single and multi-selection, controls, several event handlers and more."
|
||||
flowProps={flowProps}
|
||||
withControls
|
||||
fitView
|
||||
|
||||
@@ -62,7 +62,7 @@ const nodeTypes = {
|
||||
result: ResultNode,
|
||||
};
|
||||
|
||||
const onLoad = (rf) => rf.fitView({ padding: 0.2 });
|
||||
const onLoad = (rf) => setTimeout(() => rf.fitView({ padding: 0.1 }), 1);
|
||||
|
||||
const findNodeById = (id) => (n) => n.id === id;
|
||||
|
||||
@@ -96,7 +96,7 @@ export default () => {
|
||||
|
||||
resultNode.data = {
|
||||
...resultNode.data,
|
||||
value: result,
|
||||
value: !forname && !lastname ? '*please enter a name*' : result,
|
||||
};
|
||||
|
||||
return nextElements;
|
||||
@@ -161,7 +161,7 @@ export default () => {
|
||||
return (
|
||||
<TeaserFlow
|
||||
title="Customizable"
|
||||
description="You can create your own node and edge types. Implement complex UIs inside your nodes or add functionality to your edges. React Flow comes with a lot of event handlers."
|
||||
description="You can create your own node and edge types or just pass a custom style. You can implement custom UIs inside your nodes and add functionality to your edges."
|
||||
textPosition="right"
|
||||
fitView
|
||||
isDark
|
||||
|
||||
@@ -8,15 +8,30 @@ export default memo(({ data }) => {
|
||||
<Handle
|
||||
type="target"
|
||||
position="left"
|
||||
style={{ background: '#fff' }}
|
||||
style={{ background: '#555' }}
|
||||
onConnect={(params) => console.log('handle onConnect', params)}
|
||||
/>
|
||||
<div>
|
||||
Custom Color Picker Node: <strong>{data.color}</strong>
|
||||
</div>
|
||||
<input className="nodrag" type="color" onChange={data.onChange} defaultValue={data.color} />
|
||||
<Handle type="source" position="right" id="a" style={{ top: 10, background: '#fff' }} />
|
||||
<Handle type="source" position="right" id="b" style={{ bottom: 10, top: 'auto', background: '#fff' }} />
|
||||
<input
|
||||
className="nodrag"
|
||||
type="color"
|
||||
onChange={data.onChange}
|
||||
defaultValue={data.color}
|
||||
/>
|
||||
<Handle
|
||||
type="source"
|
||||
position="right"
|
||||
id="a"
|
||||
style={{ top: 10, background: '#555' }}
|
||||
/>
|
||||
<Handle
|
||||
type="source"
|
||||
position="right"
|
||||
id="b"
|
||||
style={{ bottom: 10, top: 'auto', background: '#555' }}
|
||||
/>
|
||||
</>
|
||||
);
|
||||
});
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
import React, { useState, useEffect } from 'react';
|
||||
|
||||
import ReactFlow, {
|
||||
isEdge,
|
||||
removeElements,
|
||||
@@ -11,15 +12,17 @@ import ColorSelectorNode from './ColorSelectorNode';
|
||||
|
||||
import './index.css';
|
||||
|
||||
const onLoad = (reactFlowInstance) =>
|
||||
const onLoad = (reactFlowInstance) => {
|
||||
console.log('flow loaded:', reactFlowInstance);
|
||||
setTimeout(() => reactFlowInstance.fitView(), 1);
|
||||
};
|
||||
const onNodeDragStop = (event, node) => console.log('drag stop', node);
|
||||
const onElementClick = (event, element) => console.log('click', element);
|
||||
|
||||
const initBgColor = '#f0e742';
|
||||
const initBgColor = '#1A192B';
|
||||
|
||||
const connectionLineStyle = { stroke: '#fff' };
|
||||
const snapGrid = [16, 16];
|
||||
const snapGrid = [20, 20];
|
||||
const nodeTypes = {
|
||||
selectorNode: ColorSelectorNode,
|
||||
};
|
||||
@@ -32,7 +35,7 @@ const CustomNodeFlow = () => {
|
||||
const onChange = (event) => {
|
||||
setElements((els) =>
|
||||
els.map((e) => {
|
||||
if (isEdge(e) || e.id !== 'custom-2') {
|
||||
if (isEdge(e) || e.id !== '2') {
|
||||
return e;
|
||||
}
|
||||
|
||||
@@ -53,52 +56,52 @@ const CustomNodeFlow = () => {
|
||||
|
||||
setElements([
|
||||
{
|
||||
id: 'custom-1',
|
||||
id: '1',
|
||||
type: 'input',
|
||||
data: { label: 'An input node' },
|
||||
position: { x: 0, y: 50 },
|
||||
sourcePosition: 'right',
|
||||
},
|
||||
{
|
||||
id: 'custom-2',
|
||||
id: '2',
|
||||
type: 'selectorNode',
|
||||
data: { onChange: onChange, color: initBgColor },
|
||||
style: { border: '1px solid #777', padding: 10 },
|
||||
position: { x: 250, y: 50 },
|
||||
position: { x: 300, y: 50 },
|
||||
},
|
||||
{
|
||||
id: 'custom-3',
|
||||
id: '3',
|
||||
type: 'output',
|
||||
data: { label: 'Output A' },
|
||||
position: { x: 550, y: 25 },
|
||||
position: { x: 650, y: 25 },
|
||||
targetPosition: 'left',
|
||||
},
|
||||
{
|
||||
id: 'custom-4',
|
||||
id: '4',
|
||||
type: 'output',
|
||||
data: { label: 'Output B' },
|
||||
position: { x: 550, y: 100 },
|
||||
position: { x: 650, y: 100 },
|
||||
targetPosition: 'left',
|
||||
},
|
||||
|
||||
{
|
||||
id: 'custom-e1-2',
|
||||
source: 'custom-1',
|
||||
target: 'custom-2',
|
||||
id: 'e1-2',
|
||||
source: '1',
|
||||
target: '2',
|
||||
animated: true,
|
||||
style: { stroke: '#fff' },
|
||||
},
|
||||
{
|
||||
id: 'custom-e2a-3',
|
||||
source: 'custom-2__a',
|
||||
target: 'custom-3',
|
||||
id: 'e2a-3',
|
||||
source: '2__a',
|
||||
target: '3',
|
||||
animated: true,
|
||||
style: { stroke: '#fff' },
|
||||
},
|
||||
{
|
||||
id: 'custom-e2b-4',
|
||||
source: 'custom-2__b',
|
||||
target: 'custom-4',
|
||||
id: 'e2b-4',
|
||||
source: '2__b',
|
||||
target: '4',
|
||||
animated: true,
|
||||
style: { stroke: '#fff' },
|
||||
},
|
||||
@@ -125,12 +128,17 @@ const CustomNodeFlow = () => {
|
||||
connectionLineStyle={connectionLineStyle}
|
||||
snapToGrid={true}
|
||||
snapGrid={snapGrid}
|
||||
defaultZoom={1.5}
|
||||
>
|
||||
<MiniMap
|
||||
nodeColor={(n) => {
|
||||
if (n.type === 'input') return 'blue';
|
||||
nodeStrokeColor={(n) => {
|
||||
if (n.type === 'input') return '#0041d0';
|
||||
if (n.type === 'selectorNode') return bgColor;
|
||||
if (n.type === 'output') return 'green';
|
||||
if (n.type === 'output') return '#ff0072';
|
||||
}}
|
||||
nodeColor={(n) => {
|
||||
if (n.type === 'selectorNode') return bgColor;
|
||||
return '#fff';
|
||||
}}
|
||||
/>
|
||||
<Controls />
|
||||
|
||||
@@ -39,6 +39,8 @@ const onElementClick = (event, element) => console.log('click', element);
|
||||
const onPaneClick = (event) => console.log('onPaneClick', event);
|
||||
const onPaneScroll = (event) => console.log('onPaneScroll', event);
|
||||
const onPaneContextMenu = (event) => console.log('onPaneContextMenu', event);
|
||||
const onLoad = (reactFlowInstance) =>
|
||||
reactFlowInstance.fitView({ padding: 0.2 });
|
||||
|
||||
const InteractionFlow = () => {
|
||||
const [elements, setElements] = useState(initialElements);
|
||||
@@ -70,6 +72,7 @@ const InteractionFlow = () => {
|
||||
onPaneClick={captureZoomClick ? onPaneClick : undefined}
|
||||
onPaneScroll={captureZoomScroll ? onPaneScroll : undefined}
|
||||
onPaneContextMenu={captureZoomClick ? onPaneContextMenu : undefined}
|
||||
onLoad={onLoad}
|
||||
>
|
||||
<MiniMap />
|
||||
<Controls />
|
||||
|
||||
@@ -33,7 +33,7 @@ const onMoveEnd = (transform) => console.log('zoom/move end', transform);
|
||||
|
||||
const initialElements = [
|
||||
{
|
||||
id: 'overview-1',
|
||||
id: '1',
|
||||
type: 'input',
|
||||
data: {
|
||||
label: (
|
||||
@@ -45,7 +45,7 @@ const initialElements = [
|
||||
position: { x: 250, y: 0 },
|
||||
},
|
||||
{
|
||||
id: 'overview-2',
|
||||
id: '2',
|
||||
data: {
|
||||
label: (
|
||||
<>
|
||||
@@ -56,7 +56,7 @@ const initialElements = [
|
||||
position: { x: 100, y: 100 },
|
||||
},
|
||||
{
|
||||
id: 'overview-3',
|
||||
id: '3',
|
||||
data: {
|
||||
label: (
|
||||
<>
|
||||
@@ -73,36 +73,21 @@ const initialElements = [
|
||||
},
|
||||
},
|
||||
{
|
||||
id: 'overview-4',
|
||||
id: '4',
|
||||
position: { x: 250, y: 200 },
|
||||
data: {
|
||||
label: (
|
||||
<>
|
||||
You can find the docs on{' '}
|
||||
<a
|
||||
href="https://github.com/wbkd/react-flow"
|
||||
target="_blank"
|
||||
rel="noopener noreferrer"
|
||||
>
|
||||
Github
|
||||
</a>
|
||||
</>
|
||||
),
|
||||
label: 'Another default node',
|
||||
},
|
||||
},
|
||||
{
|
||||
id: 'overview-5',
|
||||
id: '5',
|
||||
data: {
|
||||
label: (
|
||||
<>
|
||||
Or check out the other <strong>examples</strong>
|
||||
</>
|
||||
),
|
||||
label: 'Node id: 5',
|
||||
},
|
||||
position: { x: 250, y: 325 },
|
||||
},
|
||||
{
|
||||
id: 'overview-6',
|
||||
id: '6',
|
||||
type: 'output',
|
||||
data: {
|
||||
label: (
|
||||
@@ -114,43 +99,38 @@ const initialElements = [
|
||||
position: { x: 100, y: 480 },
|
||||
},
|
||||
{
|
||||
id: 'overview-7',
|
||||
id: '7',
|
||||
type: 'output',
|
||||
data: { label: 'Another output node' },
|
||||
position: { x: 400, y: 450 },
|
||||
},
|
||||
{ id: 'e1-2', source: '1', target: '2', label: 'this is an edge label' },
|
||||
{ id: 'e1-3', source: '1', target: '3' },
|
||||
{
|
||||
id: 'overview-e1-2',
|
||||
source: 'overview-1',
|
||||
target: 'overview-2',
|
||||
label: 'this is an edge label',
|
||||
},
|
||||
{ id: 'overview-e1-3', source: 'overview-1', target: 'overview-3' },
|
||||
{
|
||||
id: 'overview-e3-4',
|
||||
source: 'overview-3',
|
||||
target: 'overview-4',
|
||||
id: 'e3-4',
|
||||
source: '3',
|
||||
target: '4',
|
||||
animated: true,
|
||||
label: 'animated edge',
|
||||
},
|
||||
{
|
||||
id: 'overview-e4-5',
|
||||
source: 'overview-4',
|
||||
target: 'overview-5',
|
||||
id: 'e4-5',
|
||||
source: '4',
|
||||
target: '5',
|
||||
arrowHeadType: 'arrowclosed',
|
||||
label: 'edge with arrow head',
|
||||
},
|
||||
{
|
||||
id: 'overview-e5-6',
|
||||
source: 'overview-5',
|
||||
target: 'overview-6',
|
||||
id: 'e5-6',
|
||||
source: '5',
|
||||
target: '6',
|
||||
type: 'smoothstep',
|
||||
label: 'smooth step edge',
|
||||
},
|
||||
{
|
||||
id: 'overview-e5-7',
|
||||
source: 'overview-5',
|
||||
target: 'overview-7',
|
||||
id: 'e5-7',
|
||||
source: '5',
|
||||
target: '7',
|
||||
type: 'step',
|
||||
style: { stroke: '#f6ab6c' },
|
||||
label: 'a step edge',
|
||||
@@ -168,8 +148,6 @@ const OverviewFlow = () => {
|
||||
setElements((els) => removeElements(elementsToRemove, els));
|
||||
const onConnect = (params) => setElements((els) => addEdge(params, els));
|
||||
|
||||
console.log('render overview');
|
||||
|
||||
return (
|
||||
<ReactFlow
|
||||
elements={elements}
|
||||
@@ -188,17 +166,22 @@ const OverviewFlow = () => {
|
||||
connectionLineStyle={connectionLineStyle}
|
||||
snapToGrid={true}
|
||||
snapGrid={snapGrid}
|
||||
key="overview"
|
||||
>
|
||||
<MiniMap
|
||||
nodeColor={(n) => {
|
||||
nodeStrokeColor={(n) => {
|
||||
if (n.style?.background) return n.style.background;
|
||||
if (n.type === 'input') return '#9999ff';
|
||||
if (n.type === 'output') return '#79c9b7';
|
||||
if (n.type === 'default') return '#ff6060';
|
||||
if (n.type === 'input') return '#0041d0';
|
||||
if (n.type === 'output') return '#ff0072';
|
||||
if (n.type === 'default') return '#1a192b';
|
||||
|
||||
return '#eee';
|
||||
}}
|
||||
nodeColor={(n) => {
|
||||
if (n.style?.background) return n.style.background;
|
||||
|
||||
return '#fff';
|
||||
}}
|
||||
borderRadius={2}
|
||||
/>
|
||||
<Controls />
|
||||
<Background color="#aaa" gap={16} />
|
||||
|
||||
@@ -2,8 +2,14 @@
|
||||
title: Prop Types
|
||||
---
|
||||
|
||||
This is the list of prop types you can pass to the main `ReactFlow` component.
|
||||
|
||||
```jsx
|
||||
import ReactFlow from 'react-flow-renderer';
|
||||
```
|
||||
|
||||
### Basic Props
|
||||
- `elements`: array of [nodes](#nodes) and [edges](#edges) *(required)*
|
||||
- `elements`: array of [nodes](/docs/api/nodes/) and [edges](/docs/api/edges/) *(required)*
|
||||
- `style`: css properties
|
||||
- `className`: additional class name
|
||||
|
||||
@@ -13,7 +19,7 @@ title: Prop Types
|
||||
- `defaultZoom`: default: `1`
|
||||
- `defaultPosition`: default: `[0, 0]`
|
||||
- `snapToGrid`: default: `false`
|
||||
- `snapGrid`: [x, y] array - default: `[16, 16]`
|
||||
- `snapGrid`: [x, y] array - default: `[15, 15]`
|
||||
- `onlyRenderVisibleNodes`: default: `true`
|
||||
- `translateExtent`: [default `[[-∞, -∞], [+∞, +∞]]`](https://github.com/d3/d3-zoom#zoom_translateExtent)
|
||||
|
||||
@@ -55,7 +61,7 @@ title: Prop Types
|
||||
### Element Customization
|
||||
- `nodeTypes`: object with [node types](#node-types--custom-nodes)
|
||||
- `edgeTypes`: object with [edge types](#edge-types--custom-edges)
|
||||
- `arrowHeadColor`: default: `#bbb`
|
||||
- `arrowHeadColor`: default: `#b1b1b7`
|
||||
|
||||
### Connection Line Options
|
||||
- `connectionLineType`: connection line type = `default` (bezier), `straight`, `step`, `smoothstep`
|
||||
|
||||
@@ -26,6 +26,6 @@ const FlowWithBackground = () => (
|
||||
- `variant`: string - has to be 'dots' or 'lines' - default: `dots`
|
||||
- `gap`: number - the gap between the dots or lines - default: `16`
|
||||
- `size`: number - the radius of the dots or the stroke width of the lines - default: `0.5`
|
||||
- `color`: string - the color of the dots or lines - default: `#999` for dots, `#eee` for lines
|
||||
- `color`: string - the color of the dots or lines - default: `#81818a` for dots, `#eee` for lines
|
||||
- `style`: css properties
|
||||
- `className`: additional class name
|
||||
|
||||
@@ -18,4 +18,4 @@ const FlowWithOwnProvider = () => (
|
||||
);
|
||||
```
|
||||
|
||||
It is used in the [provider example](example/src/Provider/index.js).
|
||||
It is used in the [provider example](https://github.com/wbkd/react-flow/blob/main/example/src/Provider/index.js).
|
||||
@@ -0,0 +1,28 @@
|
||||
---
|
||||
title: Edge Types & Custom Edges
|
||||
---
|
||||
|
||||
React Flow comes with four edge types (`default`, `straight`, `step`, `smoothstep`). As the names indicate, the edges differ in the representation. The default type is a bezier edge.
|
||||
The basic edge types are `default` (bezier), `straight`, `step` and `smoothstep`. The default `edgeTypes` object looks like this:
|
||||
|
||||
```javascript
|
||||
{
|
||||
default: BezierEdge,
|
||||
straight: StraightEdge,
|
||||
step: StepEdge,
|
||||
smoothstep: SmoothStepEdge
|
||||
}
|
||||
```
|
||||
|
||||
The keys represent the type names and the values are the edge components.
|
||||
If you want to introduce a new edge type you can pass an `edgeTypes` object to the `ReactFlow` component:
|
||||
|
||||
```javascript
|
||||
edgeTypes={{
|
||||
special: MyCustomEdge
|
||||
}}
|
||||
```
|
||||
|
||||
Now you could use the new type `special` for an edge.
|
||||
The `straight`, `default` and `step` types would still be available unless you overwrote one of them.
|
||||
There is an implementation of a custom edge in the [edges example](/example/src/Edges/index.js).
|
||||
@@ -0,0 +1,61 @@
|
||||
---
|
||||
title: Edge Utils
|
||||
---
|
||||
|
||||
There are several utils that help you to create a custom edge. They are used in the [custom edge](/examples/custom-edge) example.
|
||||
|
||||
### `getBezierPath`
|
||||
|
||||
Returns the path of a bezier edge.
|
||||
|
||||
```
|
||||
getBezierPath({
|
||||
sourceX,
|
||||
sourceY,
|
||||
sourcePosition = Position.Bottom, // optional
|
||||
targetX,
|
||||
targetY,
|
||||
targetPosition = Position.Top, // optional
|
||||
centerX, // optional
|
||||
centerY, // optional
|
||||
}: GetBezierPathParams): string
|
||||
```
|
||||
|
||||
### `getSmoothStepPath`
|
||||
|
||||
Returns the path of a smooth step edge. You can set `borderRadius` = `0` to get a step edge path.
|
||||
|
||||
```
|
||||
getSmoothStepPath({
|
||||
sourceX,
|
||||
sourceY,
|
||||
sourcePosition = Position.Bottom, // optional
|
||||
targetX,
|
||||
targetY,
|
||||
targetPosition = Position.Top, // optional
|
||||
borderRadius = 5, // optional
|
||||
centerX, // optional
|
||||
centerY, // optional
|
||||
}: GetSmoothStepPathParams): string
|
||||
```
|
||||
|
||||
### `getEdgeCenter`
|
||||
|
||||
Returns the center position and offset `[centerX, centerY, offsetX, offsetY]` of the edge.
|
||||
|
||||
```
|
||||
getEdgeCenter({
|
||||
sourceX,
|
||||
sourceY,
|
||||
targetX,
|
||||
targetY
|
||||
}: GetCenterParams): [number, number, number, number]
|
||||
```
|
||||
|
||||
### `getMarkerEnd`
|
||||
|
||||
Returns the marker end url for displaying the arrow head.
|
||||
|
||||
```
|
||||
getMarkerEnd(arrowHeadType?: ArrowHeadType, markerEndId?: string): string
|
||||
```
|
||||
@@ -1,10 +1,8 @@
|
||||
---
|
||||
id: edges
|
||||
title: Edges
|
||||
title: Edge Options
|
||||
---
|
||||
|
||||
|
||||
React Flow comes with four [edge types](#edge-types--custom-edges) (`default`, `straight`, `step`, `smoothstep`). As the names indicate, the edges differ in the representation. The default type is a bezier edge. You create edges by adding them to your `elements` array of the `ReactFlow` component.
|
||||
You create edges by adding them to your `elements` array of the `ReactFlow` component.
|
||||
|
||||
Edge example:
|
||||
|
||||
@@ -42,72 +40,3 @@ If you wanted to display this edge, you would need a node with id = 1 (source no
|
||||
- `data`: {} you can use this to pass data to your custom edges.
|
||||
|
||||
You can find an example with different edges in the [edges example](https://reactflow.dev/edges).
|
||||
|
||||
## Edge Types & Custom Edges
|
||||
|
||||
The basic edge types are `default` (bezier), `straight`, `step` and `smoothstep`. The default `edgeTypes` object looks like this:
|
||||
|
||||
```javascript
|
||||
{
|
||||
default: BezierEdge,
|
||||
straight: StraightEdge,
|
||||
step: StepEdge,
|
||||
smoothstep: SmoothStepEdge
|
||||
}
|
||||
```
|
||||
|
||||
The keys represent the type names and the values are the edge components.
|
||||
If you want to introduce a new edge type you can pass an `edgeTypes` object to the `ReactFlow` component:
|
||||
|
||||
```javascript
|
||||
edgeTypes={{
|
||||
special: MyCustomEdge
|
||||
}}
|
||||
```
|
||||
|
||||
Now you could use the new type `special` for an edge.
|
||||
The `straight`, `default` and `step` types would still be available unless you overwrote one of them.
|
||||
There is an implementation of a custom edge in the [edges example](/example/src/Edges/index.js).
|
||||
|
||||
## Edge Utils
|
||||
|
||||
There are several utils that help you to create a custom edge. They are used in the [custom edge](/example/src/Edges/CustomEdge.js) example.
|
||||
|
||||
### `getBezierPath`
|
||||
|
||||
Returns the path of a bezier edge.
|
||||
|
||||
`getBezierPath({
|
||||
sourceX,
|
||||
sourceY,
|
||||
sourcePosition = Position.Bottom,
|
||||
targetX,
|
||||
targetY,
|
||||
targetPosition = Position.Top,
|
||||
}: GetBezierPathParams): string`
|
||||
|
||||
### `getSmoothStepPath`
|
||||
|
||||
Returns the path of a smooth step edge. You can set `borderRadius` = `0` to get a step edge path.
|
||||
|
||||
`getSmoothStepPath({
|
||||
sourceX,
|
||||
sourceY,
|
||||
sourcePosition = Position.Bottom,
|
||||
targetX,
|
||||
targetY,
|
||||
targetPosition = Position.Top,
|
||||
borderRadius = 5,
|
||||
}: GetSmoothStepPathParams): string`
|
||||
|
||||
### `getEdgeCenter`
|
||||
|
||||
Returns the center poostion `[centerX, centerY]` of the edge.
|
||||
|
||||
`getEdgeCenter({ sourceX, sourceY, targetX, targetY }: GetCenterParams): [number, number, number, number]`
|
||||
|
||||
### `getMarkerEnd`
|
||||
|
||||
Returns the marker end url for displaying the arrow head.
|
||||
|
||||
`getMarkerEnd(arrowHeadType?: ArrowHeadType, markerEndId?: string): string`
|
||||
@@ -0,0 +1,38 @@
|
||||
---
|
||||
title: Handle Component
|
||||
---
|
||||
|
||||
We export a `Handle` component as a helper for your custom nodes:
|
||||
|
||||
```javascript
|
||||
import { Handle } from 'react-flow-renderer';
|
||||
|
||||
const targetHandleWithValidation = (
|
||||
<Handle
|
||||
type="target"
|
||||
position="left"
|
||||
isValidConnection={(connection) => connection.source === 'some-id'}
|
||||
onConnect={params => console.log('handle onConnect', params)}
|
||||
style={{ background: '#fff' }}
|
||||
/>
|
||||
);
|
||||
```
|
||||
|
||||
### Prop Types
|
||||
|
||||
- `type`: 'source' or 'target'
|
||||
- `id`: string - you only need this when you have multiple source or target handles (otherwise the node id is used)
|
||||
- `position`: 'left', 'right', 'top' or 'bottom' handle position - default: 'top' for type target, 'bottom' for type source
|
||||
- `onConnect`: function that gets triggered on connect
|
||||
- `isValidConnection`: function receives a connection `{ target: 'some-id', source: 'another-id' }` as param, returns a boolean - default: `true`
|
||||
- `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](/examples/validation).
|
||||
|
||||
### 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`.
|
||||
You can find an example of how to implement a custom node with multiple handles in the [custom node example](https://github.com/wbkd/react-flow/blob/main/example/src/CustomNode/ColorSelectorNode.js#L18-L29).
|
||||
@@ -50,4 +50,4 @@ Returns all edges that are connected to the passed nodes.
|
||||
|
||||
`getConnectedEdges = (nodes: Node[], edges: Edge[]): Edge[]`
|
||||
|
||||
You can use these function as seen in [this example](/example/src/Overview/index.js#L40-L41) or use your own ones.
|
||||
You can use these function as seen in [this example](https://github.com/wbkd/react-flow/blob/main/example/src/Overview/index.js#L119-L120) or use your own ones.
|
||||
|
||||
@@ -27,7 +27,7 @@ const Flow = () => (
|
||||
|
||||
### Internal actions
|
||||
|
||||
You will not need this in most cases but you can also use the internal actions that are defined in the [store](/src/store/index.ts):
|
||||
You will not need this in most cases but you can also use the internal actions that are defined in the [store](https://github.com/wbkd/react-flow/blob/main/src/store/index.ts):
|
||||
|
||||
```jsx
|
||||
import React, { useEffect } from 'react';
|
||||
|
||||
@@ -0,0 +1,41 @@
|
||||
---
|
||||
title: Node Types & Custom Nodes
|
||||
---
|
||||
|
||||
There are three different node types (`default`, `input`, `output`) you can use. The node types differ in the number and types of handles. An input node has only a source handle, a default node has a source and a target and an output node has only a target handle. The default node types object looks like this:
|
||||
|
||||
```js
|
||||
{
|
||||
input: InputNode,
|
||||
default: DefaultNode,
|
||||
output: OutputNode
|
||||
}
|
||||
```
|
||||
|
||||
The keys represent the type names and the values are the components that get rendered.
|
||||
If you want to introduce a new type you can pass a `nodeTypes` object to the `ReactFlow` component:
|
||||
|
||||
```js
|
||||
nodeTypes={{
|
||||
special: MyCustomNode
|
||||
}}
|
||||
```
|
||||
|
||||
You can now use the type `special` for a node.
|
||||
The `default`, `input` and `output` types would be still available except you overwrote one of them.
|
||||
There is an example of a custom node implementation in the [custom node example](/examples/custom-node).
|
||||
|
||||
## Custom Node Props
|
||||
|
||||
Your custom nodes are wrapped so that the basic functions like dragging or selecting work. Custom nodes receive the following props:
|
||||
|
||||
- `id`: string
|
||||
- `data`: object
|
||||
- `type`: string
|
||||
- `selected`: boolean
|
||||
- `sourcePosition`: string
|
||||
- `targetPosition`: string
|
||||
|
||||
### Prevent dragging
|
||||
|
||||
If you have controls or other elements inside your custom node that should not drag the node you can add the class name `nodrag`.
|
||||
@@ -1,9 +1,7 @@
|
||||
---
|
||||
id: nodes
|
||||
title: Nodes
|
||||
title: Node Options
|
||||
---
|
||||
|
||||
There are three different [node types](#node-types--custom-nodes) (`default`, `input`, `output`) you can use. The node types differ in the number and types of handles. An input node has only a source handle, a default node has a source and a target and an output node has only a target handle. You create nodes by adding them to the `elements` array of the `ReactFlow` component.
|
||||
You create nodes by adding them to the `elements` array of the `ReactFlow` component.
|
||||
|
||||
Node example:
|
||||
|
||||
@@ -30,80 +28,3 @@ Node example:
|
||||
- `draggable`: boolean - if option is not set, the node is draggable (overwrites general `nodesDraggable` option)
|
||||
- `connectable`: boolean - if option is not set, the node is connectable (overwrites general `nodesConnectable` option)
|
||||
- `selectable`: boolean - if option is not set, the node is selectable (overwrites general `elementsSelectable` option)
|
||||
|
||||
## Node Types & Custom Nodes
|
||||
|
||||
The standard node types are `input`, `default` and `output`. The default node types object looks like this:
|
||||
|
||||
```js
|
||||
{
|
||||
input: InputNode,
|
||||
default: DefaultNode,
|
||||
output: OutputNode
|
||||
}
|
||||
```
|
||||
|
||||
The keys represent the type names and the values are the components that get rendered.
|
||||
If you want to introduce a new type you can pass a `nodeTypes` object to the `ReactFlow` component:
|
||||
|
||||
```js
|
||||
nodeTypes={{
|
||||
special: MyCustomNode
|
||||
}}
|
||||
```
|
||||
|
||||
You can now use the type `special` for a node.
|
||||
The `default`, `input` and `output` types would be still available except you overwrote one of them.
|
||||
There is an example of a custom node implementation in the [custom node example](/example/src/CustomNode).
|
||||
|
||||
## Custom Node Props
|
||||
|
||||
Your custom nodes are wrapped so that the basic functions like dragging or selecting work. Custom nodes receive the following props:
|
||||
|
||||
- `id`: string
|
||||
- `data`: object
|
||||
- `type`: string
|
||||
- `selected`: boolean
|
||||
- `sourcePosition`: string
|
||||
- `targetPosition`: string
|
||||
|
||||
### Prevent dragging
|
||||
|
||||
If you have controls or other elements inside your custom node that should not drag the node you can add the class name `nodrag`.
|
||||
|
||||
## Handle Component
|
||||
|
||||
We export a `Handle` component as a helper for your custom nodes:
|
||||
|
||||
```javascript
|
||||
import { Handle } from 'react-flow-renderer';
|
||||
|
||||
const targetHandleWithValidation = (
|
||||
<Handle
|
||||
type="target"
|
||||
position="left"
|
||||
isValidConnection={(connection) => connection.source === 'some-id'}
|
||||
onConnect={params => console.log('handle onConnect', params)}
|
||||
style={{ background: '#fff' }}
|
||||
/>
|
||||
);
|
||||
```
|
||||
|
||||
### Prop Types
|
||||
|
||||
- `type`: 'source' or 'target'
|
||||
- `id`: string - you only need this when you have multiple source or target handles (otherwise the node id is used)
|
||||
- `position`: 'left', 'right', 'top' or 'bottom' handle position - default: 'top' for type target, 'bottom' for type source
|
||||
- `onConnect`: function that gets triggered on connect
|
||||
- `isValidConnection`: function receives a connection `{ target: 'some-id', source: 'another-id' }` as param, returns a boolean - default: `true`
|
||||
- `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`.
|
||||
You can find an example of how to implement a custom node with multiple handles in the [custom node example](/example/src/CustomNode/ColorSelectorNode.js#L18-L29).
|
||||
@@ -15,31 +15,42 @@ const onLoad = (reactFlowInstance) => {
|
||||
const BasicFlow = () => <ReactFlow onLoad={onLoad} elements={[]} />;
|
||||
```
|
||||
|
||||
`reactFlowInstance` has the following functions:
|
||||
The `reactFlowInstance` has the following functions:
|
||||
|
||||
### `project`
|
||||
|
||||
Transforms pixel coordinates to the internal ReactFlow coordinate system.
|
||||
This can be used when you drag nodes (from a side bar for example) and need the position on the pane.
|
||||
This can be used when you drag nodes (from a side bar for example) and need the internal position on the pane.
|
||||
|
||||
`project = (position: XYPosition): XYPosition`
|
||||
|
||||
**example:**
|
||||
```
|
||||
reactFlowInstance.project({ x: 100, y: 100 });
|
||||
```
|
||||
|
||||
### `fitView`
|
||||
|
||||
Fits view port so that all nodes are inside the view port.
|
||||
Fits the view port so that all nodes are visible
|
||||
|
||||
`fitView = ({ padding }): void`
|
||||
|
||||
### `zoomIn`
|
||||
|
||||
Zoom in
|
||||
|
||||
`zoomIn = (): void`
|
||||
|
||||
### `zoomOut`
|
||||
|
||||
Zoom out
|
||||
|
||||
`zoomOut = (): void`
|
||||
|
||||
### `zoomTo`
|
||||
|
||||
Zooms to the specified zoom level
|
||||
|
||||
`zoomTo = (zoomLevel: number): void`
|
||||
|
||||
### `getElements`
|
||||
@@ -50,4 +61,9 @@ Fits view port so that all nodes are inside the view port.
|
||||
|
||||
Sets position and zoom of the pane.
|
||||
|
||||
`setTransform = (transform: FlowTransform): void`
|
||||
`setTransform = (transform: FlowTransform): void`
|
||||
|
||||
**example:**
|
||||
```
|
||||
reactFlowInstance.setTransform({ x: 100, y: 100, zoom: 1.5 });
|
||||
```
|
||||
@@ -2,17 +2,23 @@
|
||||
title: Getting Started
|
||||
---
|
||||
|
||||
Before you can start to use React Flow you need to install `react-flow-renderer` from npm:
|
||||
Before you can start to use React Flow you need to install `react-flow-renderer`:
|
||||
|
||||
## Installation
|
||||
|
||||
**npm:**
|
||||
```bash
|
||||
npm install react-flow-renderer
|
||||
```
|
||||
|
||||
**yarn:**
|
||||
```bash
|
||||
yarn add react-flow-renderer
|
||||
```
|
||||
|
||||
## Usage
|
||||
|
||||
This is a very basic example of how to use React Flow. We are rendering two nodes connected with an edge. There are more advanced examples in the [examples](/examples) section.
|
||||
This is a very basic example of how to use React Flow. A flow consists of nodes and edges (or just nodes). Together we call them elements. You can pass a set of elements as a prop to the ReactFlow component. Hereby all elements need unique ids. A node needs a position and a label and an edge needs a source (node id) and a target (node id). This is the most basic for a flow. A simple flow could look like this:
|
||||
|
||||
```jsx
|
||||
import React from 'react';
|
||||
@@ -30,4 +36,6 @@ const BasicFlow = () => <ReactFlow elements={elements} />;
|
||||
|
||||
import Flow from './index';
|
||||
|
||||
<Flow />
|
||||
<Flow />
|
||||
|
||||
You can find more advanced examples in the [examples](reactflow.dev/examples/) section.
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
title: Introduction
|
||||
---
|
||||
|
||||
React Flow is a library for building node-based graphs. You can easily implement custom node types and it comes with components like a mini-map and graph controls. Feel free to check out the [examples](https://reactflow.dev/) or read the [blog post](https://webkid.io/blog/react-flow-node-based-graph-library/) to get started.
|
||||
React Flow is a library for building node-based applications. These can be simple static diagrams or complex node-based editors. You can implement custom node types and edge types and it comes with components like a mini-map and graph controls. Feel free to check out the [examples](https://reactflow.dev/examples/) or read the [blog post](https://webkid.io/blog/react-flow-node-based-graph-library/) to get started.
|
||||
|
||||
## Key Features
|
||||
|
||||
|
||||
@@ -7,7 +7,7 @@ import { ReactFlowProvider } from 'react-flow-renderer';
|
||||
export const frontmatter = {
|
||||
title: 'Edge Types',
|
||||
slug: 'edge-types',
|
||||
order: 4,
|
||||
order: 11,
|
||||
};
|
||||
|
||||
export default () => {
|
||||
|
||||
@@ -7,7 +7,7 @@ import { ReactFlowProvider } from 'react-flow-renderer';
|
||||
export const frontmatter = {
|
||||
title: 'Hidden',
|
||||
slug: 'hidden',
|
||||
order: 4,
|
||||
order: 12,
|
||||
};
|
||||
|
||||
export default () => {
|
||||
|
||||
@@ -92,7 +92,7 @@ const Home = () => {
|
||||
<HeadlineAbsolute>
|
||||
<CenterContent>
|
||||
<HeadlineWrapper>
|
||||
<H1>Wire your ideas together with React Flow</H1>
|
||||
<H1>Wire your ideas with React Flow</H1>
|
||||
<SectionSubtitle>
|
||||
Highly customizable React.js library for building node-based
|
||||
editors and diagrams.
|
||||
@@ -128,7 +128,7 @@ const Home = () => {
|
||||
<CenterContent>
|
||||
<SectionIntro
|
||||
title="Getting Started"
|
||||
text="With React Flow you can build node-based applications. From complex interactive editors to simple static diagrams."
|
||||
text="React Flow enables you to build node-based applications. From simple static diagrams to complex interactive editors."
|
||||
color={baseColors.textLight}
|
||||
/>
|
||||
<Paragraph mb={3} color={baseColors.textLight}>
|
||||
@@ -151,8 +151,8 @@ const Home = () => {
|
||||
them elements. You can pass a set of elements as a prop to the
|
||||
ReactFlow component. Hereby all elements need unique ids. A node
|
||||
needs a position and a label and an edge needs a source (node id)
|
||||
and a target (node id). This is the most basic set up you need to
|
||||
get started. A simple flow could look like this:
|
||||
and a target (node id). This is the most basic for a flow. A simple
|
||||
flow could look like this:
|
||||
</Paragraph>
|
||||
<CodeBlock
|
||||
code={`import React from 'react';
|
||||
@@ -179,7 +179,7 @@ const BasicFlow = () => <ReactFlow elements={elements} />;`}
|
||||
<ContentSection bg="violetLighten5">
|
||||
<SectionIntro
|
||||
title="Built with React Flow"
|
||||
text="React Flow has a fast growing community. Since the first release new projects popup. Ranging from Music Synthesizers and Study catalogs over to presentational business logic."
|
||||
text="You can do a wide range of applications with React Flow. Ranging from music synthesizers and study planners to visualizations of neural nets."
|
||||
color={baseColors.textLight}
|
||||
/>
|
||||
<Showcases />
|
||||
@@ -187,7 +187,7 @@ const BasicFlow = () => <ReactFlow elements={elements} />;`}
|
||||
|
||||
<ContentSection>
|
||||
<SectionIntro
|
||||
title="Do you want to realize a data driven experience?"
|
||||
title="Do you want to build a data driven application?"
|
||||
text="Reach out and contact us. We’re happy to chat and always excited for a new data driven challenge."
|
||||
/>
|
||||
|
||||
|
||||
@@ -12,10 +12,24 @@ const docsMenu = [
|
||||
group: 'API Reference',
|
||||
items: [
|
||||
{ title: 'Prop Types' },
|
||||
{ title: 'Instance' },
|
||||
{ title: 'Nodes' },
|
||||
{ title: 'Edges' },
|
||||
{ title: 'Helper Functions' },
|
||||
{
|
||||
group: 'Nodes',
|
||||
items: [
|
||||
{ title: 'Node Options' },
|
||||
{ title: 'Node Types & Custom Nodes' },
|
||||
{ title: 'Handle Component' },
|
||||
],
|
||||
},
|
||||
{
|
||||
group: 'Edges',
|
||||
items: [
|
||||
{ title: 'Edge Options' },
|
||||
{ title: 'Edge Types & Custom Edges' },
|
||||
{ title: 'Edge Utils' },
|
||||
],
|
||||
},
|
||||
{ title: 'Instance' },
|
||||
{ title: 'Internal State and Actions' },
|
||||
{
|
||||
group: 'Components',
|
||||
|
||||
|
Before Width: | Height: | Size: 198 B After Width: | Height: | Size: 1.1 KiB |