feat(website): init
This commit is contained in:
@@ -0,0 +1,88 @@
|
||||
import React from 'react';
|
||||
|
||||
import TeaserFlow from 'components/TeaserFlow';
|
||||
|
||||
const elements = [
|
||||
{
|
||||
id: '1',
|
||||
type: 'input',
|
||||
position: {
|
||||
x: 200,
|
||||
y: 5,
|
||||
},
|
||||
data: {
|
||||
label: 'Input',
|
||||
},
|
||||
},
|
||||
{
|
||||
id: '2',
|
||||
position: {
|
||||
x: 0,
|
||||
y: 150,
|
||||
},
|
||||
data: {
|
||||
label: 'Default',
|
||||
},
|
||||
},
|
||||
{
|
||||
id: '3',
|
||||
position: {
|
||||
x: 400,
|
||||
y: 150,
|
||||
},
|
||||
data: {
|
||||
label: 'Default',
|
||||
},
|
||||
},
|
||||
{
|
||||
id: '4',
|
||||
type: 'output',
|
||||
position: {
|
||||
x: 200,
|
||||
y: 300,
|
||||
},
|
||||
data: {
|
||||
label: 'Output',
|
||||
},
|
||||
},
|
||||
{
|
||||
id: 'e1',
|
||||
source: '1',
|
||||
target: '2',
|
||||
label: 'default edge',
|
||||
},
|
||||
{
|
||||
id: 'e2',
|
||||
source: '1',
|
||||
target: '3',
|
||||
animated: true,
|
||||
label: 'animated edge',
|
||||
},
|
||||
{
|
||||
id: 'e3',
|
||||
source: '2',
|
||||
target: '4',
|
||||
type: 'smoothstep',
|
||||
},
|
||||
{
|
||||
id: 'e4',
|
||||
source: '3',
|
||||
target: '4',
|
||||
type: 'smoothstep',
|
||||
},
|
||||
];
|
||||
|
||||
const flowProps = {
|
||||
elements,
|
||||
onLoad: (rf) => rf.fitView({ padding: 0.2 }),
|
||||
};
|
||||
|
||||
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."
|
||||
flowProps={flowProps}
|
||||
withControls
|
||||
fitView
|
||||
/>
|
||||
);
|
||||
@@ -0,0 +1,182 @@
|
||||
import React, { useState, useEffect } from 'react';
|
||||
import styled from '@emotion/styled';
|
||||
import ReactFlow, {
|
||||
Handle,
|
||||
ReactFlowProvider,
|
||||
Background,
|
||||
Controls,
|
||||
} from 'react-flow-renderer';
|
||||
|
||||
import TeaserFlow from 'components/TeaserFlow';
|
||||
import { baseColors } from 'themes';
|
||||
|
||||
const NodeWrapper = styled.div`
|
||||
background: ${(p) => p.theme.colors.silverLighten30};
|
||||
padding: 8px 10px;
|
||||
font-size: 12px;
|
||||
border-radius: 4px;
|
||||
|
||||
input {
|
||||
font-size: 12px;
|
||||
border: 1px solid ${(p) => p.theme.colors.violetLighten60};
|
||||
width: 100%;
|
||||
border-radius: 2px;
|
||||
max-width: 100px;
|
||||
}
|
||||
|
||||
.react-flow__handle {
|
||||
background: ${(p) => p.theme.colors.violetLighten60};
|
||||
}
|
||||
`;
|
||||
|
||||
const InputLabel = styled.div`
|
||||
color: ${(p) => p.theme.colors.violetLighten60};
|
||||
`;
|
||||
|
||||
const InputNode = ({ id, data }) => {
|
||||
return (
|
||||
<NodeWrapper>
|
||||
<InputLabel>{data.label}:</InputLabel>
|
||||
<input
|
||||
className="nodrag"
|
||||
value={data.value}
|
||||
onChange={(event) => data.onChange(event, id)}
|
||||
/>
|
||||
<Handle type="source" position="bottom" />
|
||||
</NodeWrapper>
|
||||
);
|
||||
};
|
||||
|
||||
const ResultNode = ({ data }) => {
|
||||
return (
|
||||
<NodeWrapper>
|
||||
<div>{data.value}</div>
|
||||
<Handle type="target" position="top" id="a" style={{ left: '40%' }} />
|
||||
<Handle type="target" position="top" id="b" style={{ left: '60%' }} />
|
||||
</NodeWrapper>
|
||||
);
|
||||
};
|
||||
|
||||
const nodeTypes = {
|
||||
nameinput: InputNode,
|
||||
result: ResultNode,
|
||||
};
|
||||
|
||||
const onLoad = (rf) => rf.fitView({ padding: 0.2 });
|
||||
|
||||
const findNodeById = (id) => (n) => n.id === id;
|
||||
|
||||
export default () => {
|
||||
const [elements, setElements] = useState([]);
|
||||
|
||||
useEffect(() => {
|
||||
const onChange = (event, id) => {
|
||||
setElements((els) => {
|
||||
const nextElements = els.map((e) => {
|
||||
if (e.id !== id) {
|
||||
return e;
|
||||
}
|
||||
|
||||
const value = event.target.value;
|
||||
|
||||
return {
|
||||
...e,
|
||||
data: {
|
||||
...e.data,
|
||||
value,
|
||||
},
|
||||
};
|
||||
});
|
||||
|
||||
const forname = nextElements.find(findNodeById('1')).data.value;
|
||||
const lastname = nextElements.find(findNodeById('2')).data.value;
|
||||
|
||||
const result = `${forname} ${lastname}`;
|
||||
const resultNode = nextElements.find((n) => n.type === 'result');
|
||||
|
||||
resultNode.data = {
|
||||
...resultNode.data,
|
||||
value: result,
|
||||
};
|
||||
|
||||
return nextElements;
|
||||
});
|
||||
};
|
||||
|
||||
const initialElements = [
|
||||
{
|
||||
id: '1',
|
||||
type: 'nameinput',
|
||||
position: {
|
||||
x: 0,
|
||||
y: 200,
|
||||
},
|
||||
data: {
|
||||
label: 'Forename',
|
||||
value: 'React',
|
||||
onChange,
|
||||
},
|
||||
},
|
||||
{
|
||||
id: '2',
|
||||
type: 'nameinput',
|
||||
position: {
|
||||
x: 400,
|
||||
y: 200,
|
||||
},
|
||||
data: {
|
||||
label: 'Lastname',
|
||||
value: 'Flow',
|
||||
onChange,
|
||||
},
|
||||
},
|
||||
{
|
||||
id: '3',
|
||||
type: 'result',
|
||||
position: {
|
||||
x: 200,
|
||||
y: 400,
|
||||
},
|
||||
data: {
|
||||
value: 'React Flow',
|
||||
},
|
||||
},
|
||||
{
|
||||
id: 'e1',
|
||||
source: '1',
|
||||
target: '3__a',
|
||||
animated: true,
|
||||
},
|
||||
{
|
||||
id: 'e2',
|
||||
source: '2',
|
||||
target: '3__b',
|
||||
animated: true,
|
||||
},
|
||||
];
|
||||
|
||||
setElements(initialElements);
|
||||
}, []);
|
||||
|
||||
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."
|
||||
textPosition="right"
|
||||
fitView
|
||||
isDark
|
||||
>
|
||||
<ReactFlowProvider>
|
||||
<ReactFlow
|
||||
elements={elements}
|
||||
nodeTypes={nodeTypes}
|
||||
onLoad={onLoad}
|
||||
zoomOnScroll={false}
|
||||
>
|
||||
<Background color={baseColors.silverDarken60} gap={15} />
|
||||
<Controls showInteractive={false} />
|
||||
</ReactFlow>
|
||||
</ReactFlowProvider>
|
||||
</TeaserFlow>
|
||||
);
|
||||
};
|
||||
@@ -0,0 +1,173 @@
|
||||
import React from 'react';
|
||||
|
||||
import TeaserFlow from 'components/TeaserFlow';
|
||||
|
||||
const defaultNodeOptions = {
|
||||
targetPosition: 'left',
|
||||
sourcePosition: 'right',
|
||||
style: {
|
||||
width: 50,
|
||||
},
|
||||
};
|
||||
|
||||
const elements = [
|
||||
{
|
||||
id: 'input',
|
||||
type: 'input',
|
||||
position: {
|
||||
x: 0,
|
||||
y: 100,
|
||||
},
|
||||
data: {
|
||||
label: 'Input',
|
||||
},
|
||||
...defaultNodeOptions,
|
||||
},
|
||||
{
|
||||
id: 'A',
|
||||
position: {
|
||||
x: 150,
|
||||
y: 0,
|
||||
},
|
||||
data: {
|
||||
label: 'A',
|
||||
},
|
||||
...defaultNodeOptions,
|
||||
},
|
||||
{
|
||||
id: 'B',
|
||||
position: {
|
||||
x: 250,
|
||||
y: 0,
|
||||
},
|
||||
data: {
|
||||
label: 'B',
|
||||
},
|
||||
...defaultNodeOptions,
|
||||
},
|
||||
{
|
||||
id: 'C',
|
||||
position: {
|
||||
x: 350,
|
||||
y: 0,
|
||||
},
|
||||
data: {
|
||||
label: 'C',
|
||||
},
|
||||
...defaultNodeOptions,
|
||||
},
|
||||
{
|
||||
id: 'D',
|
||||
position: {
|
||||
x: 150,
|
||||
y: 200,
|
||||
},
|
||||
data: {
|
||||
label: 'D',
|
||||
},
|
||||
...defaultNodeOptions,
|
||||
},
|
||||
{
|
||||
id: 'E',
|
||||
position: {
|
||||
x: 250,
|
||||
y: 200,
|
||||
},
|
||||
data: {
|
||||
label: 'E',
|
||||
},
|
||||
...defaultNodeOptions,
|
||||
},
|
||||
{
|
||||
id: 'F',
|
||||
position: {
|
||||
x: 350,
|
||||
y: 200,
|
||||
},
|
||||
data: {
|
||||
label: 'F',
|
||||
},
|
||||
...defaultNodeOptions,
|
||||
},
|
||||
{
|
||||
id: 'output',
|
||||
type: 'output',
|
||||
position: {
|
||||
x: 500,
|
||||
y: 100,
|
||||
},
|
||||
data: {
|
||||
label: 'Output',
|
||||
},
|
||||
...defaultNodeOptions,
|
||||
},
|
||||
{
|
||||
id: 'e1',
|
||||
source: 'input',
|
||||
target: 'A',
|
||||
type: 'step',
|
||||
},
|
||||
{
|
||||
id: 'e2',
|
||||
source: 'A',
|
||||
target: 'B',
|
||||
type: 'step',
|
||||
},
|
||||
{
|
||||
id: 'e3',
|
||||
source: 'B',
|
||||
target: 'C',
|
||||
type: 'step',
|
||||
},
|
||||
{
|
||||
id: 'e4',
|
||||
source: 'C',
|
||||
target: 'output',
|
||||
type: 'step',
|
||||
},
|
||||
{
|
||||
id: 'e5',
|
||||
source: 'input',
|
||||
target: 'D',
|
||||
type: 'step',
|
||||
animated: true,
|
||||
},
|
||||
{
|
||||
id: 'e6',
|
||||
source: 'D',
|
||||
target: 'E',
|
||||
type: 'step',
|
||||
animated: true,
|
||||
},
|
||||
{
|
||||
id: 'e7',
|
||||
source: 'E',
|
||||
target: 'F',
|
||||
type: 'step',
|
||||
animated: true,
|
||||
},
|
||||
{
|
||||
id: 'e8',
|
||||
source: 'F',
|
||||
target: 'output',
|
||||
type: 'step',
|
||||
animated: true,
|
||||
},
|
||||
];
|
||||
|
||||
const flowProps = {
|
||||
elements,
|
||||
onLoad: (rf) => rf.fitView({ padding: 0.2 }),
|
||||
};
|
||||
|
||||
export default () => (
|
||||
<TeaserFlow
|
||||
title="Additional Components"
|
||||
description="React Flow includes a MiniMap, Controls, Background and a FlowProvider you can use to access internal state outside the ReactFlow component."
|
||||
flowProps={flowProps}
|
||||
withControls
|
||||
withMinimap
|
||||
fitView
|
||||
linesBg
|
||||
/>
|
||||
);
|
||||
@@ -0,0 +1,89 @@
|
||||
import React from 'react';
|
||||
import styled from '@emotion/styled';
|
||||
import { Flex, Box } from 'reflexbox';
|
||||
import Link from 'gatsby-link';
|
||||
import ReactFlow, {
|
||||
ReactFlowProvider,
|
||||
Background,
|
||||
Controls,
|
||||
MiniMap,
|
||||
} from 'react-flow-renderer';
|
||||
|
||||
import { H2, Text } from 'components/Typo';
|
||||
import Icon from 'components/Icon';
|
||||
import { baseColors } from 'themes';
|
||||
|
||||
const Wrapper = styled(Flex)`
|
||||
justify-content: space-between;
|
||||
align-items: center;
|
||||
flex-wrap: wrap;
|
||||
`;
|
||||
|
||||
const ReactFlowWrapper = styled(Box)`
|
||||
height: 400px;
|
||||
background: ${(p) => (p.isDark ? baseColors.violet : 'white')};
|
||||
border-radius: 5px;
|
||||
|
||||
.react-flow__controls {
|
||||
opacity: ${(p) => (p.isDark ? 0.5 : 1)};
|
||||
}
|
||||
`;
|
||||
|
||||
const DocsLink = styled(Link)`
|
||||
display: flex;
|
||||
align-items: center;
|
||||
margin-top: 16px;
|
||||
`;
|
||||
|
||||
const Description = ({ title, description }) => (
|
||||
<Box width={[1, 1, 0.35]}>
|
||||
<H2>{title}</H2>
|
||||
<Text>{description}</Text>
|
||||
<DocsLink to="/docs">
|
||||
Documentation{' '}
|
||||
<Icon width={24} name="arrow_right" colorizeStroke strokeColor="red" />
|
||||
</DocsLink>
|
||||
</Box>
|
||||
);
|
||||
|
||||
export default ({
|
||||
title,
|
||||
description,
|
||||
textPosition = 'left',
|
||||
flowProps,
|
||||
withControls = false,
|
||||
withMinimap = false,
|
||||
isDark = false,
|
||||
linesBg = false,
|
||||
children,
|
||||
}) => {
|
||||
const bgColor = isDark ? baseColors.violetLighten60 : baseColors.violet;
|
||||
|
||||
return (
|
||||
<Wrapper mb={[6, 6, 7]}>
|
||||
{textPosition === 'left' && (
|
||||
<Description title={title} description={description} />
|
||||
)}
|
||||
<ReactFlowWrapper width={[1, 1, 0.6]} isDark={isDark}>
|
||||
{children ? (
|
||||
children
|
||||
) : (
|
||||
<ReactFlowProvider>
|
||||
<ReactFlow {...flowProps} zoomOnScroll={false}>
|
||||
<Background
|
||||
color={linesBg ? '#eee' : bgColor}
|
||||
gap={15}
|
||||
variant={linesBg ? 'lines' : 'dots'}
|
||||
/>
|
||||
{withControls && <Controls />}
|
||||
{withMinimap && <MiniMap />}
|
||||
</ReactFlow>
|
||||
</ReactFlowProvider>
|
||||
)}
|
||||
</ReactFlowWrapper>
|
||||
{textPosition !== 'left' && (
|
||||
<Description title={title} description={description} />
|
||||
)}
|
||||
</Wrapper>
|
||||
);
|
||||
};
|
||||
Reference in New Issue
Block a user