diff --git a/website/gatsby-config.js b/website/gatsby-config.js index 731a8063..e853a4ee 100644 --- a/website/gatsby-config.js +++ b/website/gatsby-config.js @@ -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', }, diff --git a/website/src/assets/data/showcases.json b/website/src/assets/data/showcases.json index b7263f04..ec485921 100644 --- a/website/src/assets/data/showcases.json +++ b/website/src/assets/data/showcases.json @@ -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" } ] diff --git a/website/src/assets/icons/favicon.svg b/website/src/assets/icons/favicon.svg deleted file mode 100644 index e5592d40..00000000 --- a/website/src/assets/icons/favicon.svg +++ /dev/null @@ -1,4 +0,0 @@ - - - - diff --git a/website/src/assets/images/showcases/circles-showcase.png b/website/src/assets/images/showcases/circles-showcase.png new file mode 100644 index 00000000..646bca89 Binary files /dev/null and b/website/src/assets/images/showcases/circles-showcase.png differ diff --git a/website/src/assets/images/showcases/showcase-1.jpg b/website/src/assets/images/showcases/showcase-1.jpg deleted file mode 100644 index 028d12b0..00000000 Binary files a/website/src/assets/images/showcases/showcase-1.jpg and /dev/null differ diff --git a/website/src/assets/images/showcases/showcase-2.jpg b/website/src/assets/images/showcases/showcase-2.jpg deleted file mode 100644 index 028d12b0..00000000 Binary files a/website/src/assets/images/showcases/showcase-2.jpg and /dev/null differ diff --git a/website/src/assets/images/showcases/showcase.jpg b/website/src/assets/images/showcases/showcase.jpg deleted file mode 100644 index 028d12b0..00000000 Binary files a/website/src/assets/images/showcases/showcase.jpg and /dev/null differ diff --git a/website/src/components/CodeBlock/Mdx.js b/website/src/components/CodeBlock/Mdx.js index e140b69f..6fcd4ba5 100644 --- a/website/src/components/CodeBlock/Mdx.js +++ b/website/src/components/CodeBlock/Mdx.js @@ -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) => ( -
- {line.map((token, key) => ( - - ))} -
- ))} + {tokens.map( + (line, i, lines) => + !( + line.length === 1 && + line[0].empty && + (i === 0 || i === lines.length - 1) + ) && ( +
+ {line.map((token, key) => ( + + ))} +
+ ) + )} )} diff --git a/website/src/components/CodeBlock/index.js b/website/src/components/CodeBlock/index.js index 112d6594..2a54f394 100644 --- a/website/src/components/CodeBlock/index.js +++ b/website/src/components/CodeBlock/index.js @@ -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 { diff --git a/website/src/components/CollaborationButton/index.js b/website/src/components/CollaborationButton/index.js deleted file mode 100644 index bdc077b4..00000000 --- a/website/src/components/CollaborationButton/index.js +++ /dev/null @@ -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 ( - -

{caption}

- -
- ); -}; diff --git a/website/src/components/Header/index.js b/website/src/components/Header/index.js index ca849ab7..cc95262a 100644 --- a/website/src/components/Header/index.js +++ b/website/src/components/Header/index.js @@ -209,10 +209,10 @@ const Header = () => { Home - + Docs - + Examples diff --git a/website/src/components/Mdx/CodeBlock/index.js b/website/src/components/Mdx/CodeBlock/index.js deleted file mode 100644 index 06e24b30..00000000 --- a/website/src/components/Mdx/CodeBlock/index.js +++ /dev/null @@ -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 ( - - {({ className, style, tokens, getLineProps, getTokenProps }) => ( -
-          {tokens
-            .filter((line) => line.some((l) => l.content))
-            .map((line, i) => (
-              
- {line.map((token, key) => ( - - ))} -
- ))} -
- )} -
- ); -}; diff --git a/website/src/components/Mdx/index.js b/website/src/components/Mdx/index.js deleted file mode 100644 index b4ec3053..00000000 --- a/website/src/components/Mdx/index.js +++ /dev/null @@ -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 - ) : ( - - {child} - - ) - ); -}; - -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) =>
, - code: CodeBlock, - wrapper: MdxWrapper, -}; - -const Mdx = ({ content = null }) => { - return ( - - - {content} - - - ); -}; - -export default Mdx; diff --git a/website/src/components/ProjectTeaser/Large.js b/website/src/components/ProjectTeaser/Large.js deleted file mode 100644 index 90d24fe9..00000000 --- a/website/src/components/ProjectTeaser/Large.js +++ /dev/null @@ -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 ( - - - - - - {kicker} -

{title}

-

{text}

- - Read more -
-
- - ); -}; - -export default ProjectTeaser; diff --git a/website/src/components/ProjectTeaser/Small.js b/website/src/components/ProjectTeaser/Small.js deleted file mode 100644 index 7d12464d..00000000 --- a/website/src/components/ProjectTeaser/Small.js +++ /dev/null @@ -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 ( - - - - {kicker} -

{title}

- {text} -
-
- - ); -}; - -export default ProjectTeaser; diff --git a/website/src/components/Showcases/index.js b/website/src/components/Showcases/index.js index 2af1ddd2..93527ec3 100644 --- a/website/src/components/Showcases/index.js +++ b/website/src/components/Showcases/index.js @@ -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 ( {showcases.map((showcase) => ( - - {showcase.title} + + {showcase.title} + {showcase.url} ))} + {emptyShowCases.map((index) => ( + + + react flow logo + + Your Project here + + Let us know if you made something with React Flow. + + + ))} ); diff --git a/website/src/components/TeaserFlow/A.js b/website/src/components/TeaserFlow/A.js index 4c201d47..a019cf9e 100644 --- a/website/src/components/TeaserFlow/A.js +++ b/website/src/components/TeaserFlow/A.js @@ -80,7 +80,7 @@ const flowProps = { export default () => ( 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 ( { console.log('handle onConnect', params)} />
Custom Color Picker Node: {data.color}
- - - + + + ); }); diff --git a/website/src/example-flows/CustomNode/index.js b/website/src/example-flows/CustomNode/index.js index 494aea73..d27cdf1b 100644 --- a/website/src/example-flows/CustomNode/index.js +++ b/website/src/example-flows/CustomNode/index.js @@ -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} > { - 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'; }} /> diff --git a/website/src/example-flows/Interaction/index.js b/website/src/example-flows/Interaction/index.js index 0e6080e9..f9c493e7 100644 --- a/website/src/example-flows/Interaction/index.js +++ b/website/src/example-flows/Interaction/index.js @@ -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} > diff --git a/website/src/example-flows/Overview/index.js b/website/src/example-flows/Overview/index.js index 7bfdf62b..07185ca4 100644 --- a/website/src/example-flows/Overview/index.js +++ b/website/src/example-flows/Overview/index.js @@ -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{' '} - - Github - - - ), + label: 'Another default node', }, }, { - id: 'overview-5', + id: '5', data: { - label: ( - <> - Or check out the other examples - - ), + 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 ( { connectionLineStyle={connectionLineStyle} snapToGrid={true} snapGrid={snapGrid} - key="overview" > { + 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} /> diff --git a/website/src/markdown/docs/api/component-props.md b/website/src/markdown/docs/api/component-props.md index b61a2fe9..9a2af14b 100644 --- a/website/src/markdown/docs/api/component-props.md +++ b/website/src/markdown/docs/api/component-props.md @@ -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` diff --git a/website/src/markdown/docs/api/components/background.md b/website/src/markdown/docs/api/components/background.md index f22109cb..da687ea3 100644 --- a/website/src/markdown/docs/api/components/background.md +++ b/website/src/markdown/docs/api/components/background.md @@ -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 diff --git a/website/src/markdown/docs/api/components/provider.md b/website/src/markdown/docs/api/components/provider.md index bad87c77..34a710f7 100644 --- a/website/src/markdown/docs/api/components/provider.md +++ b/website/src/markdown/docs/api/components/provider.md @@ -18,4 +18,4 @@ const FlowWithOwnProvider = () => ( ); ``` -It is used in the [provider example](example/src/Provider/index.js). \ No newline at end of file +It is used in the [provider example](https://github.com/wbkd/react-flow/blob/main/example/src/Provider/index.js). \ No newline at end of file diff --git a/website/src/markdown/docs/api/edge-types.md b/website/src/markdown/docs/api/edge-types.md new file mode 100644 index 00000000..879e5941 --- /dev/null +++ b/website/src/markdown/docs/api/edge-types.md @@ -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). diff --git a/website/src/markdown/docs/api/edge-utils.md b/website/src/markdown/docs/api/edge-utils.md new file mode 100644 index 00000000..af3c6043 --- /dev/null +++ b/website/src/markdown/docs/api/edge-utils.md @@ -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 +``` \ No newline at end of file diff --git a/website/src/markdown/docs/api/edges.md b/website/src/markdown/docs/api/edges.md index 33ee27d6..a380ca64 100644 --- a/website/src/markdown/docs/api/edges.md +++ b/website/src/markdown/docs/api/edges.md @@ -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` \ No newline at end of file diff --git a/website/src/markdown/docs/api/handle.md b/website/src/markdown/docs/api/handle.md new file mode 100644 index 00000000..1cd2cf4f --- /dev/null +++ b/website/src/markdown/docs/api/handle.md @@ -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 = ( + 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). \ No newline at end of file diff --git a/website/src/markdown/docs/api/helper-functions.md b/website/src/markdown/docs/api/helper-functions.md index 9a18334e..645f314b 100644 --- a/website/src/markdown/docs/api/helper-functions.md +++ b/website/src/markdown/docs/api/helper-functions.md @@ -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. diff --git a/website/src/markdown/docs/api/internal-state-actions.md b/website/src/markdown/docs/api/internal-state-actions.md index 6870a416..e80c46ec 100644 --- a/website/src/markdown/docs/api/internal-state-actions.md +++ b/website/src/markdown/docs/api/internal-state-actions.md @@ -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'; diff --git a/website/src/markdown/docs/api/node-types.md b/website/src/markdown/docs/api/node-types.md new file mode 100644 index 00000000..5898f1ff --- /dev/null +++ b/website/src/markdown/docs/api/node-types.md @@ -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`. diff --git a/website/src/markdown/docs/api/nodes.md b/website/src/markdown/docs/api/nodes.md index dd91758c..fbb5e7c8 100644 --- a/website/src/markdown/docs/api/nodes.md +++ b/website/src/markdown/docs/api/nodes.md @@ -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 = ( - 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). \ No newline at end of file diff --git a/website/src/markdown/docs/api/react-flow-instance.md b/website/src/markdown/docs/api/react-flow-instance.md index e8e40ed7..f5dcf1c7 100644 --- a/website/src/markdown/docs/api/react-flow-instance.md +++ b/website/src/markdown/docs/api/react-flow-instance.md @@ -15,31 +15,42 @@ const onLoad = (reactFlowInstance) => { const BasicFlow = () => ; ``` -`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` \ No newline at end of file +`setTransform = (transform: FlowTransform): void` + +**example:** +``` +reactFlowInstance.setTransform({ x: 100, y: 100, zoom: 1.5 }); +``` \ No newline at end of file diff --git a/website/src/markdown/docs/getting-started/index.md b/website/src/markdown/docs/getting-started/index.md index 8d62a26f..3baf4bc4 100644 --- a/website/src/markdown/docs/getting-started/index.md +++ b/website/src/markdown/docs/getting-started/index.md @@ -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 = () => ; import Flow from './index'; - \ No newline at end of file + + +You can find more advanced examples in the [examples](reactflow.dev/examples/) section. diff --git a/website/src/markdown/docs/index.md b/website/src/markdown/docs/index.md index 3333d8c9..61d562fe 100644 --- a/website/src/markdown/docs/index.md +++ b/website/src/markdown/docs/index.md @@ -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 diff --git a/website/src/pages/examples/edge-types.js b/website/src/pages/examples/edge-types.js index 56bec9c2..85642e0d 100644 --- a/website/src/pages/examples/edge-types.js +++ b/website/src/pages/examples/edge-types.js @@ -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 () => { diff --git a/website/src/pages/examples/hidden.js b/website/src/pages/examples/hidden.js index 6f1b3a08..76816c3a 100644 --- a/website/src/pages/examples/hidden.js +++ b/website/src/pages/examples/hidden.js @@ -7,7 +7,7 @@ import { ReactFlowProvider } from 'react-flow-renderer'; export const frontmatter = { title: 'Hidden', slug: 'hidden', - order: 4, + order: 12, }; export default () => { diff --git a/website/src/pages/index.js b/website/src/pages/index.js index 8c7d0bd5..df03a015 100644 --- a/website/src/pages/index.js +++ b/website/src/pages/index.js @@ -92,7 +92,7 @@ const Home = () => { -

Wire your ideas together with React Flow

+

Wire your ideas with React Flow

Highly customizable React.js library for building node-based editors and diagrams. @@ -128,7 +128,7 @@ const Home = () => { @@ -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: ;`} @@ -187,7 +187,7 @@ const BasicFlow = () => ;`} diff --git a/website/src/templates/doc-page.js b/website/src/templates/doc-page.js index b4e31132..4c36da53 100644 --- a/website/src/templates/doc-page.js +++ b/website/src/templates/doc-page.js @@ -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', diff --git a/website/static/favicon.ico b/website/static/favicon.ico index 85a4d9fa..731acd59 100644 Binary files a/website/static/favicon.ico and b/website/static/favicon.ico differ