docs(website): sidebar mobile
This commit is contained in:
@@ -1,5 +1,5 @@
|
||||
{
|
||||
"name": "react-flow-examples",
|
||||
"name": "react-flow-tests",
|
||||
"version": "0.1.0",
|
||||
"private": true,
|
||||
"dependencies": {
|
||||
BIN
dev-flows/public/favicon.ico
Normal file
BIN
dev-flows/public/favicon.ico
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 1.1 KiB |
@@ -4,12 +4,10 @@
|
||||
<meta charset="utf-8" />
|
||||
<link rel="icon" href="%PUBLIC_URL%/favicon.ico" />
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1, user-scalable=no" />
|
||||
<meta name="theme-color" content="#222222" />
|
||||
<meta name="description" content="react flow examples" />
|
||||
<title>React Flow Examples</title>
|
||||
<meta name="description" content="React Flow test flows" />
|
||||
<title>React Flow - Test Flows</title>
|
||||
</head>
|
||||
<body>
|
||||
<noscript>You need to enable JavaScript to run this app.</noscript>
|
||||
<div id="root"></div>
|
||||
</body>
|
||||
</html>
|
||||
@@ -1,7 +1,5 @@
|
||||
@import url('https://fonts.googleapis.com/css2?family=Roboto:wght@400;700&display=swap');
|
||||
|
||||
body {
|
||||
font-family: 'Roboto', sans-serif;
|
||||
font-family: sans-serif;
|
||||
color: #111;
|
||||
}
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
import React, { useState } from 'react';
|
||||
import ReactDOM from 'react-dom';
|
||||
import { BrowserRouter as Router, Route, Switch, NavLink, withRouter } from 'react-router-dom';
|
||||
import { BrowserRouter as Router, Route, Switch, NavLink } from 'react-router-dom';
|
||||
|
||||
import Overview from './Overview';
|
||||
import Basic from './Basic';
|
||||
@@ -10,7 +10,6 @@ import Interaction from './Interaction';
|
||||
import Empty from './Empty';
|
||||
import Edges from './Edges';
|
||||
import Validation from './Validation';
|
||||
import Horizontal from './Horizontal';
|
||||
import Provider from './Provider';
|
||||
import Hidden from './Hidden';
|
||||
import EdgeTypes from './EdgeTypes';
|
||||
@@ -34,11 +33,6 @@ const routes = [
|
||||
component: CustomNode,
|
||||
label: 'CustomNode',
|
||||
},
|
||||
{
|
||||
path: '/horizontal',
|
||||
component: Horizontal,
|
||||
label: 'Horizontal',
|
||||
},
|
||||
{
|
||||
path: '/validation',
|
||||
component: Validation,
|
||||
@@ -83,24 +77,13 @@ const routes = [
|
||||
|
||||
const navLinks = routes.filter((route) => route.label);
|
||||
|
||||
const SourceDisplay = withRouter(({ location }) => {
|
||||
const route = routes.find((route) => route.path === location.pathname);
|
||||
const sourceLink = `https://github.com/wbkd/react-flow/tree/main/example/src/${route.label}/index.js`;
|
||||
|
||||
return (
|
||||
<a className="sourcedisplay" href={sourceLink}>
|
||||
{'<Source />'}
|
||||
</a>
|
||||
);
|
||||
});
|
||||
|
||||
const Header = () => {
|
||||
const [menuOpen, setMenuOpen] = useState();
|
||||
|
||||
return (
|
||||
<header>
|
||||
<a className="logo" href="https://github.com/wbkd/react-flow">
|
||||
React Flow
|
||||
React Flow Dev
|
||||
</a>
|
||||
<nav className={menuOpen ? 'is-open' : ''}>
|
||||
{navLinks.map((route) => (
|
||||
@@ -119,7 +102,6 @@ const Header = () => {
|
||||
ReactDOM.render(
|
||||
<Router forceRefresh={true}>
|
||||
<Header />
|
||||
<SourceDisplay />
|
||||
<Switch>
|
||||
{routes.map((route) => (
|
||||
<Route exact path={route.path} render={() => <route.component />} key={route.path} />
|
||||
Binary file not shown.
|
Before Width: | Height: | Size: 22 KiB |
Binary file not shown.
|
Before Width: | Height: | Size: 8.4 KiB |
Binary file not shown.
|
Before Width: | Height: | Size: 22 KiB |
@@ -1,25 +0,0 @@
|
||||
{
|
||||
"short_name": "React App",
|
||||
"name": "Create React App Sample",
|
||||
"icons": [
|
||||
{
|
||||
"src": "favicon.ico",
|
||||
"sizes": "64x64 32x32 24x24 16x16",
|
||||
"type": "image/x-icon"
|
||||
},
|
||||
{
|
||||
"src": "logo192.png",
|
||||
"type": "image/png",
|
||||
"sizes": "192x192"
|
||||
},
|
||||
{
|
||||
"src": "logo512.png",
|
||||
"type": "image/png",
|
||||
"sizes": "512x512"
|
||||
}
|
||||
],
|
||||
"start_url": ".",
|
||||
"display": "standalone",
|
||||
"theme_color": "#000000",
|
||||
"background_color": "#ffffff"
|
||||
}
|
||||
@@ -1,90 +0,0 @@
|
||||
import React, { useState } from 'react';
|
||||
|
||||
import ReactFlow, { removeElements, addEdge } from 'react-flow-renderer';
|
||||
|
||||
const onLoad = (reactFlowInstance) => reactFlowInstance.fitView();
|
||||
|
||||
const onNodeMouseEnter = (event, node) => console.log('mouse enter:', node);
|
||||
const onNodeMouseMove = (event, node) => console.log('mouse move:', node);
|
||||
const onNodeMouseLeave = (event, node) => console.log('mouse leave:', node);
|
||||
const onNodeContextMenu = (event, node) => {
|
||||
event.preventDefault();
|
||||
console.log('context menu:', node);
|
||||
};
|
||||
|
||||
const initialElements = [
|
||||
{
|
||||
id: '1',
|
||||
sourcePosition: 'right',
|
||||
type: 'input',
|
||||
className: 'dark-node',
|
||||
data: { label: 'Input' },
|
||||
position: { x: 0, y: 80 },
|
||||
},
|
||||
{ id: '2', sourcePosition: 'right', targetPosition: 'left', data: { label: 'A Node' }, position: { x: 250, y: 0 } },
|
||||
{ id: '3', sourcePosition: 'right', targetPosition: 'left', data: { label: 'Node 3' }, position: { x: 250, y: 160 } },
|
||||
{ id: '4', sourcePosition: 'right', targetPosition: 'left', data: { label: 'Node 4' }, position: { x: 500, y: 0 } },
|
||||
{ id: '5', sourcePosition: 'top', targetPosition: 'bottom', data: { label: 'Node 5' }, position: { x: 500, y: 100 } },
|
||||
{ id: '6', sourcePosition: 'bottom', targetPosition: 'top', data: { label: 'Node 6' }, position: { x: 500, y: 230 } },
|
||||
{
|
||||
id: '7',
|
||||
type: 'output',
|
||||
sourcePosition: 'right',
|
||||
targetPosition: 'left',
|
||||
data: { label: 'Node 7' },
|
||||
position: { x: 750, y: 50 },
|
||||
},
|
||||
{
|
||||
id: '8',
|
||||
type: 'output',
|
||||
sourcePosition: 'right',
|
||||
targetPosition: 'left',
|
||||
data: { label: 'Node 8' },
|
||||
position: { x: 750, y: 300 },
|
||||
},
|
||||
|
||||
{ id: 'e1-2', source: '1', type: 'smoothstep', target: '2', animated: true },
|
||||
{ id: 'e1-3', source: '1', type: 'smoothstep', target: '3', animated: true },
|
||||
{ id: 'e1-4', source: '2', type: 'smoothstep', target: '4', label: 'edge label' },
|
||||
{ id: 'e3-5', source: '3', type: 'smoothstep', target: '5', animated: true },
|
||||
{ id: 'e3-6', source: '3', type: 'smoothstep', target: '6', animated: true },
|
||||
{ id: 'e5-7', source: '5', type: 'smoothstep', target: '7', animated: true },
|
||||
{ id: 'e6-8', source: '6', type: 'smoothstep', target: '8', animated: true },
|
||||
];
|
||||
|
||||
const HorizontalFlow = () => {
|
||||
const [elements, setElements] = useState(initialElements);
|
||||
const onElementsRemove = (elementsToRemove) => setElements((els) => removeElements(elementsToRemove, els));
|
||||
const onConnect = (params) => setElements((els) => addEdge(params, els));
|
||||
const changeClassName = () => {
|
||||
setElements((elms) =>
|
||||
elms.map((el) => {
|
||||
if (el.type === 'input') {
|
||||
el.className = el.className ? '' : 'dark-node';
|
||||
}
|
||||
|
||||
return { ...el };
|
||||
})
|
||||
);
|
||||
};
|
||||
|
||||
return (
|
||||
<ReactFlow
|
||||
elements={elements}
|
||||
onElementsRemove={onElementsRemove}
|
||||
onConnect={onConnect}
|
||||
onLoad={onLoad}
|
||||
selectNodesOnDrag={false}
|
||||
onNodeMouseEnter={onNodeMouseEnter}
|
||||
onNodeMouseMove={onNodeMouseMove}
|
||||
onNodeMouseLeave={onNodeMouseLeave}
|
||||
onNodeContextMenu={onNodeContextMenu}
|
||||
>
|
||||
<button onClick={changeClassName} style={{ position: 'absolute', right: 10, top: 30, zIndex: 4 }}>
|
||||
change class name
|
||||
</button>
|
||||
</ReactFlow>
|
||||
);
|
||||
};
|
||||
|
||||
export default HorizontalFlow;
|
||||
@@ -12,10 +12,10 @@
|
||||
"scripts": {
|
||||
"build": "rollup -c --environment NODE_ENV:production",
|
||||
"start": "rollup -w -c",
|
||||
"dev": "npm run build && npm start & cd example && npm start",
|
||||
"start:examples": "npm run build && cd example && npm start",
|
||||
"dev:wait": "start-server-and-test start:examples http-get://localhost:3000",
|
||||
"build:example": "npm install && npm run build && cd example && npm install && npm run build",
|
||||
"dev": "npm run build && npm start & cd dev-flows && npm start",
|
||||
"start:devflows": "npm run build && cd dev-flows && npm start",
|
||||
"dev:wait": "start-server-and-test start:devflows http-get://localhost:3000",
|
||||
"build:devflows": "npm install && npm run build && cd dev-flows && npm install && npm run build",
|
||||
"build:website": "cd website && npm install && GATSBY_EXPERIMENTAL_PAGE_BUILD_ON_DATA_CHANGES=true npm run build",
|
||||
"cy:open": "cypress open",
|
||||
"cypress": "npm run dev:wait cy:open",
|
||||
|
||||
@@ -53,9 +53,6 @@ module.exports = {
|
||||
linkImagesToOriginal: false,
|
||||
},
|
||||
},
|
||||
{
|
||||
resolve: `gatsby-remark-images-medium-zoom`,
|
||||
},
|
||||
],
|
||||
},
|
||||
},
|
||||
@@ -73,18 +70,7 @@ module.exports = {
|
||||
linkImagesToOriginal: false,
|
||||
},
|
||||
},
|
||||
{
|
||||
resolve: `gatsby-remark-responsive-iframe`,
|
||||
options: {
|
||||
wrapperStyle: `margin-bottom: 1.0725rem`,
|
||||
},
|
||||
},
|
||||
'gatsby-remark-copy-linked-files',
|
||||
{
|
||||
resolve: `gatsby-remark-images-medium-zoom`, // Important!
|
||||
options: {},
|
||||
},
|
||||
// 'gatsby-remark-unwrap-images',
|
||||
],
|
||||
remarkPlugins: [require('remark-unwrap-images')],
|
||||
extensions: [`.md`, `.mdx`],
|
||||
|
||||
102
website/package-lock.json
generated
102
website/package-lock.json
generated
@@ -1446,11 +1446,6 @@
|
||||
}
|
||||
}
|
||||
},
|
||||
"@fastly/performance-observer-polyfill": {
|
||||
"version": "1.1.1",
|
||||
"resolved": "https://registry.npmjs.org/@fastly/performance-observer-polyfill/-/performance-observer-polyfill-1.1.1.tgz",
|
||||
"integrity": "sha512-hmXJBYhIs77KPyg/IcPM5sDeQSPLrTzD6DqGfSUUtvEUoQxbW6nxHYCYJE8CP+Ay+OUqLZlTpW+w1OEOZWckzQ=="
|
||||
},
|
||||
"@graphql-tools/schema": {
|
||||
"version": "6.2.2",
|
||||
"resolved": "https://registry.npmjs.org/@graphql-tools/schema/-/schema-6.2.2.tgz",
|
||||
@@ -12300,98 +12295,6 @@
|
||||
}
|
||||
}
|
||||
},
|
||||
"gatsby-remark-images-medium-zoom": {
|
||||
"version": "1.7.0",
|
||||
"resolved": "https://registry.npmjs.org/gatsby-remark-images-medium-zoom/-/gatsby-remark-images-medium-zoom-1.7.0.tgz",
|
||||
"integrity": "sha512-TLaq+ua+nO2CX/B/FnWB0OvJiLdplzbRCXrgCxYoZs3RkN5IfUu9BJYKEFjzx6J3uhwLvBA7XqE5cFOZ2cu4AQ==",
|
||||
"requires": {
|
||||
"@fastly/performance-observer-polyfill": "^1.1.1",
|
||||
"medium-zoom": "^1.0.4"
|
||||
}
|
||||
},
|
||||
"gatsby-remark-responsive-iframe": {
|
||||
"version": "2.4.14",
|
||||
"resolved": "https://registry.npmjs.org/gatsby-remark-responsive-iframe/-/gatsby-remark-responsive-iframe-2.4.14.tgz",
|
||||
"integrity": "sha512-BsAyKplgZaLAXGd5d1DNBkuk3xS5rSiQn6J5Rx2ZQi4PznZiCuHAdOzFHRq/K/mQw8rEsesy1bsf6p/gQltwlw==",
|
||||
"requires": {
|
||||
"@babel/runtime": "^7.11.2",
|
||||
"cheerio": "^1.0.0-rc.3",
|
||||
"common-tags": "^1.8.0",
|
||||
"lodash": "^4.17.20",
|
||||
"unist-util-visit": "^1.4.1"
|
||||
},
|
||||
"dependencies": {
|
||||
"@babel/runtime": {
|
||||
"version": "7.11.2",
|
||||
"resolved": "https://registry.npmjs.org/@babel/runtime/-/runtime-7.11.2.tgz",
|
||||
"integrity": "sha512-TeWkU52so0mPtDcaCTxNBI/IHiz0pZgr8VEFqXFtZWpYD08ZB6FaSwVAS8MKRQAP3bYKiVjwysOJgMFY28o6Tw==",
|
||||
"requires": {
|
||||
"regenerator-runtime": "^0.13.4"
|
||||
}
|
||||
},
|
||||
"cheerio": {
|
||||
"version": "1.0.0-rc.3",
|
||||
"resolved": "https://registry.npmjs.org/cheerio/-/cheerio-1.0.0-rc.3.tgz",
|
||||
"integrity": "sha512-0td5ijfUPuubwLUu0OBoe98gZj8C/AA+RW3v67GPlGOrvxWjZmBXiBCRU+I8VEiNyJzjth40POfHiz2RB3gImA==",
|
||||
"requires": {
|
||||
"css-select": "~1.2.0",
|
||||
"dom-serializer": "~0.1.1",
|
||||
"entities": "~1.1.1",
|
||||
"htmlparser2": "^3.9.1",
|
||||
"lodash": "^4.15.0",
|
||||
"parse5": "^3.0.1"
|
||||
}
|
||||
},
|
||||
"dom-serializer": {
|
||||
"version": "0.1.1",
|
||||
"resolved": "https://registry.npmjs.org/dom-serializer/-/dom-serializer-0.1.1.tgz",
|
||||
"integrity": "sha512-l0IU0pPzLWSHBcieZbpOKgkIn3ts3vAh7ZuFyXNwJxJXk/c4Gwj9xaTJwIDVQCXawWD0qb3IzMGH5rglQaO0XA==",
|
||||
"requires": {
|
||||
"domelementtype": "^1.3.0",
|
||||
"entities": "^1.1.1"
|
||||
}
|
||||
},
|
||||
"entities": {
|
||||
"version": "1.1.2",
|
||||
"resolved": "https://registry.npmjs.org/entities/-/entities-1.1.2.tgz",
|
||||
"integrity": "sha512-f2LZMYl1Fzu7YSBKg+RoROelpOaNrcGmE9AZubeDfrCEia483oW4MI4VyFd5VNHIgQ/7qm1I0wUHK1eJnn2y2w=="
|
||||
},
|
||||
"lodash": {
|
||||
"version": "4.17.20",
|
||||
"resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.20.tgz",
|
||||
"integrity": "sha512-PlhdFcillOINfeV7Ni6oF1TAEayyZBoZ8bcshTHqOYJYlrqzRK5hagpagky5o4HfCzzd1TRkXPMFq6cKk9rGmA=="
|
||||
},
|
||||
"parse5": {
|
||||
"version": "3.0.3",
|
||||
"resolved": "https://registry.npmjs.org/parse5/-/parse5-3.0.3.tgz",
|
||||
"integrity": "sha512-rgO9Zg5LLLkfJF9E6CCmXlSE4UVceloys8JrFqCcHloC3usd/kJCyPDwH2SOlzix2j3xaP9sUX3e8+kvkuleAA==",
|
||||
"requires": {
|
||||
"@types/node": "*"
|
||||
}
|
||||
},
|
||||
"unist-util-is": {
|
||||
"version": "3.0.0",
|
||||
"resolved": "https://registry.npmjs.org/unist-util-is/-/unist-util-is-3.0.0.tgz",
|
||||
"integrity": "sha512-sVZZX3+kspVNmLWBPAB6r+7D9ZgAFPNWm66f7YNb420RlQSbn+n8rG8dGZSkrER7ZIXGQYNm5pqC3v3HopH24A=="
|
||||
},
|
||||
"unist-util-visit": {
|
||||
"version": "1.4.1",
|
||||
"resolved": "https://registry.npmjs.org/unist-util-visit/-/unist-util-visit-1.4.1.tgz",
|
||||
"integrity": "sha512-AvGNk7Bb//EmJZyhtRUnNMEpId/AZ5Ph/KUpTI09WHQuDZHKovQ1oEv3mfmKpWKtoMzyMC4GLBm1Zy5k12fjIw==",
|
||||
"requires": {
|
||||
"unist-util-visit-parents": "^2.0.0"
|
||||
}
|
||||
},
|
||||
"unist-util-visit-parents": {
|
||||
"version": "2.1.2",
|
||||
"resolved": "https://registry.npmjs.org/unist-util-visit-parents/-/unist-util-visit-parents-2.1.2.tgz",
|
||||
"integrity": "sha512-DyN5vD4NE3aSeB+PXYNKxzGsfocxp6asDc2XXE3b0ekO2BaRUpBicbbUygfSvYfUz1IkmjFR1YF7dPklraMZ2g==",
|
||||
"requires": {
|
||||
"unist-util-is": "^3.0.0"
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"gatsby-remark-unwrap-images": {
|
||||
"version": "1.0.2",
|
||||
"resolved": "https://registry.npmjs.org/gatsby-remark-unwrap-images/-/gatsby-remark-unwrap-images-1.0.2.tgz",
|
||||
@@ -16300,11 +16203,6 @@
|
||||
"resolved": "https://registry.npmjs.org/media-typer/-/media-typer-0.3.0.tgz",
|
||||
"integrity": "sha1-hxDXrwqmJvj/+hzgAWhUUmMlV0g="
|
||||
},
|
||||
"medium-zoom": {
|
||||
"version": "1.0.6",
|
||||
"resolved": "https://registry.npmjs.org/medium-zoom/-/medium-zoom-1.0.6.tgz",
|
||||
"integrity": "sha512-UdiUWfvz9fZMg1pzf4dcuqA0W079o0mpqbTnOz5ip4VGYX96QjmbM+OgOU/0uOzAytxC0Ny4z+VcYQnhdifimg=="
|
||||
},
|
||||
"memoizerific": {
|
||||
"version": "1.11.3",
|
||||
"resolved": "https://registry.npmjs.org/memoizerific/-/memoizerific-1.11.3.tgz",
|
||||
|
||||
@@ -36,8 +36,6 @@
|
||||
"gatsby-plugin-svgr": "^2.0.2",
|
||||
"gatsby-remark-copy-linked-files": "^2.3.15",
|
||||
"gatsby-remark-images": "^3.3.30",
|
||||
"gatsby-remark-images-medium-zoom": "^1.7.0",
|
||||
"gatsby-remark-responsive-iframe": "^2.4.14",
|
||||
"gatsby-remark-unwrap-images": "^1.0.2",
|
||||
"gatsby-source-filesystem": "^2.3.30",
|
||||
"gatsby-transformer-javascript-frontmatter": "^2.3.13",
|
||||
|
||||
23
website/src/components/Close/index.js
Normal file
23
website/src/components/Close/index.js
Normal file
@@ -0,0 +1,23 @@
|
||||
import React from 'react';
|
||||
import styled from '@emotion/styled';
|
||||
import { Flex } from 'reflexbox';
|
||||
|
||||
import { getThemeSpacePx } from 'utils/css-utils';
|
||||
import Icon from 'components/Icon';
|
||||
|
||||
const Close = styled(Flex)`
|
||||
padding: ${getThemeSpacePx(1)};
|
||||
line-height: 1;
|
||||
width: 50px;
|
||||
height: 50px;
|
||||
`;
|
||||
|
||||
export default ({ onClick, ...props }) => {
|
||||
return (
|
||||
<Flex pb={4} alignItems="center" justifyContent="center" {...props}>
|
||||
<Close alignItems="center" justifyContent="center" onClick={onClick}>
|
||||
<Icon name="close" strokeColor="text" colorizeStroke />
|
||||
</Close>
|
||||
</Flex>
|
||||
);
|
||||
};
|
||||
@@ -1,11 +1,14 @@
|
||||
import React, { useEffect, useState } from 'react';
|
||||
import React, { useState } from 'react';
|
||||
import { Link } from 'gatsby';
|
||||
import styled from '@emotion/styled';
|
||||
import { Flex, Box } from 'reflexbox';
|
||||
|
||||
import Icon from 'components/Icon';
|
||||
import Button from 'components/Button';
|
||||
import Close from 'components/Close';
|
||||
import { getThemeColor, getThemeSpacePx, device, px } from 'utils/css-utils';
|
||||
import useMenuHeight from 'hooks/useMenuHeight';
|
||||
|
||||
import ReactFlowLogo from 'assets/images/react-flow-logo.svg';
|
||||
|
||||
const Centered = styled(Flex)`
|
||||
@@ -26,7 +29,7 @@ const NavWrapper = styled(Box)`
|
||||
left: 0;
|
||||
width: 100%;
|
||||
padding: ${getThemeSpacePx(3)};
|
||||
z-index: 100;
|
||||
z-index: 500;
|
||||
background: ${getThemeColor('background')};
|
||||
align-items: center;
|
||||
flex-direction: column;
|
||||
@@ -112,6 +115,18 @@ const NavItem = styled(Link)`
|
||||
`;
|
||||
|
||||
const GithubButton = styled.a`
|
||||
font-size: 30px;
|
||||
display: block;
|
||||
padding: ${(p) => (p.isButton ? '8px 16px' : '16px 0')};
|
||||
text-align: center;
|
||||
color: ${getThemeColor('textLight')};
|
||||
|
||||
&:focus,
|
||||
&:visited,
|
||||
&:active {
|
||||
color: ${getThemeColor('textLight')};
|
||||
}
|
||||
|
||||
@media ${device.tablet} {
|
||||
margin-left: 50px;
|
||||
font-size: 16px;
|
||||
@@ -126,16 +141,6 @@ const GithubButton = styled.a`
|
||||
}
|
||||
`;
|
||||
|
||||
const Close = styled.div`
|
||||
padding: ${getThemeSpacePx(1)};
|
||||
line-height: 1;
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
width: 50px;
|
||||
height: 50px;
|
||||
`;
|
||||
|
||||
const NavButton = styled.div`
|
||||
cursor: pointer;
|
||||
|
||||
@@ -166,10 +171,9 @@ const LogoSubtitle = styled(Box)`
|
||||
`;
|
||||
|
||||
const Header = () => {
|
||||
const [menuHeight, setMenuHeight] = useState(
|
||||
typeof window !== 'undefined' ? window.innerHeight : 0
|
||||
);
|
||||
const [menuOpen, setMenuOpen] = useState(false);
|
||||
const menuHeight = useMenuHeight();
|
||||
|
||||
const toggleMenu = () => {
|
||||
const nextMenuOpen = !menuOpen;
|
||||
|
||||
@@ -178,18 +182,6 @@ const Header = () => {
|
||||
setMenuOpen(nextMenuOpen);
|
||||
};
|
||||
|
||||
useEffect(() => {
|
||||
const onResize = () => {
|
||||
setMenuHeight(typeof window !== 'undefined' ? window.innerHeight : 0);
|
||||
};
|
||||
|
||||
window.addEventListener('resize', onResize);
|
||||
|
||||
return () => {
|
||||
window.removeEventListener('resize', onResize);
|
||||
};
|
||||
});
|
||||
|
||||
return (
|
||||
<Wrapper>
|
||||
<Centered>
|
||||
@@ -228,21 +220,17 @@ const Header = () => {
|
||||
Github
|
||||
</Button>
|
||||
|
||||
<a
|
||||
<GithubButton
|
||||
href="https://github.com/wbkd/react-flow"
|
||||
activeClassName="active"
|
||||
className="mobile"
|
||||
isButton
|
||||
>
|
||||
Github
|
||||
</a>
|
||||
</GithubButton>
|
||||
</NavInner>
|
||||
</Nav>
|
||||
<Flex pb={4} alignItems="center" className="mobile">
|
||||
<Close onClick={toggleMenu}>
|
||||
<Icon name="close" strokeColor="text" colorizeStroke />
|
||||
</Close>
|
||||
</Flex>
|
||||
<Close onClick={toggleMenu} className="mobile" />
|
||||
</NavWrapper>
|
||||
</Centered>
|
||||
</Wrapper>
|
||||
|
||||
@@ -9,15 +9,11 @@ const Wrapper = styled(Flex)`
|
||||
border-top: 1px solid ${(p) => p.theme.colors.silverLighten30};
|
||||
`;
|
||||
|
||||
const left =
|
||||
typeof window !== 'undefined' && window.innerWidth > 1000
|
||||
? Math.min(350, window.innerWidth * 0.3) / 2
|
||||
: 0;
|
||||
|
||||
const DocWrapper = styled(Box)`
|
||||
max-width: 620px;
|
||||
margin: 0 auto;
|
||||
position: relative;
|
||||
padding: 0 16px;
|
||||
`;
|
||||
|
||||
export default ({ children, menu = [], ...rest }) => (
|
||||
|
||||
@@ -1,14 +1,54 @@
|
||||
import React, { Fragment } from 'react';
|
||||
import React, { Fragment, useState } from 'react';
|
||||
import Link from 'gatsby-link';
|
||||
import styled from '@emotion/styled';
|
||||
import { Flex } from 'reflexbox';
|
||||
|
||||
import { getThemeColor, getThemeSpacePx } from 'utils/css-utils';
|
||||
import Icon from 'components/Icon';
|
||||
import Close from 'components/Close';
|
||||
import useMenuHeight from 'hooks/useMenuHeight';
|
||||
import { getThemeColor, getThemeSpacePx, device, px } from 'utils/css-utils';
|
||||
|
||||
const Aside = styled.aside`
|
||||
width: 30%;
|
||||
max-width: 300px;
|
||||
padding: 16px;
|
||||
border-right: 1px solid ${getThemeColor('silverLighten30')};
|
||||
display: ${(p) => (p.isOpen ? 'block' : 'none')};
|
||||
position: absolute;
|
||||
left: 0;
|
||||
top: 0;
|
||||
width: 100%;
|
||||
height: ${(p) => px(p.height)};
|
||||
overflow-y: auto;
|
||||
background: white;
|
||||
z-index: 400;
|
||||
|
||||
@media ${device.tablet} {
|
||||
width: 30%;
|
||||
max-width: 300px;
|
||||
padding: 16px;
|
||||
border-right: 1px solid ${getThemeColor('silverLighten30')};
|
||||
display: block;
|
||||
position: relative;
|
||||
height: auto;
|
||||
|
||||
.mobile {
|
||||
display: none;
|
||||
}
|
||||
}
|
||||
`;
|
||||
|
||||
const AsideInner = styled.div``;
|
||||
|
||||
const MobileButton = styled(Flex)`
|
||||
z-index: 10;
|
||||
background: ${getThemeColor('violetLighten5')};
|
||||
position: fixed;
|
||||
right: 16px;
|
||||
bottom: 16px;
|
||||
color: white;
|
||||
border-radius: 100%;
|
||||
width: 36px;
|
||||
height: 36px;
|
||||
cursor: pointer;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
`;
|
||||
|
||||
const MenuLink = styled(Link)`
|
||||
@@ -53,10 +93,34 @@ const SideBarParts = ({ items, level }) =>
|
||||
});
|
||||
|
||||
const Sidebar = ({ menu }) => {
|
||||
const [isOpen, setIsOpen] = useState(false);
|
||||
const menuHeight = useMenuHeight();
|
||||
|
||||
const toggleSidebar = () => {
|
||||
const nextMenuOpen = !isOpen;
|
||||
|
||||
document.body.classList.toggle('noscroll', nextMenuOpen);
|
||||
|
||||
setIsOpen(nextMenuOpen);
|
||||
};
|
||||
|
||||
return (
|
||||
<Aside>
|
||||
<SideBarParts items={menu} level={0} />
|
||||
</Aside>
|
||||
<>
|
||||
<MobileButton onClick={toggleSidebar}>
|
||||
<Icon
|
||||
name="menu"
|
||||
width="24px"
|
||||
colorizeStroke
|
||||
strokeColor="silverLighten60"
|
||||
/>
|
||||
</MobileButton>
|
||||
<Aside isOpen={isOpen} height={menuHeight}>
|
||||
<AsideInner>
|
||||
<SideBarParts items={menu} level={0} />
|
||||
<Close className="mobile" onClick={toggleSidebar} />
|
||||
</AsideInner>
|
||||
</Aside>
|
||||
</>
|
||||
);
|
||||
};
|
||||
|
||||
|
||||
23
website/src/hooks/useMenuHeight.js
Normal file
23
website/src/hooks/useMenuHeight.js
Normal file
@@ -0,0 +1,23 @@
|
||||
import { useState, useEffect } from 'react';
|
||||
|
||||
const getInnerHeight = () => {
|
||||
return typeof window !== 'undefined' ? window.innerHeight : 0;
|
||||
};
|
||||
|
||||
export default function useMenuHeight() {
|
||||
const [menuHeight, setMenuHeight] = useState(getInnerHeight());
|
||||
|
||||
useEffect(() => {
|
||||
const onResize = () => {
|
||||
setMenuHeight(getInnerHeight());
|
||||
};
|
||||
|
||||
window.addEventListener('resize', onResize);
|
||||
|
||||
return () => {
|
||||
window.removeEventListener('resize', onResize);
|
||||
};
|
||||
});
|
||||
|
||||
return menuHeight;
|
||||
}
|
||||
@@ -2,14 +2,34 @@ import React from 'react';
|
||||
import ReactFlow from 'react-flow-renderer';
|
||||
|
||||
const elements = [
|
||||
{ id: '1', data: { label: 'Node 1' }, position: { x: 250, y: 5 } },
|
||||
// you can also pass a React component as a label
|
||||
{ id: '2', data: { label: <div>Node 2</div> }, position: { x: 100, y: 100 } },
|
||||
// input node
|
||||
{
|
||||
id: '1',
|
||||
type: 'input',
|
||||
data: { label: 'Input Node' },
|
||||
position: { x: 250, y: 25 },
|
||||
},
|
||||
// default node
|
||||
{
|
||||
id: '2',
|
||||
// you can also pass a React component as a label
|
||||
data: { label: <div>Default Node</div> },
|
||||
position: { x: 100, y: 125 },
|
||||
},
|
||||
// output node
|
||||
{
|
||||
id: '3',
|
||||
type: 'output',
|
||||
// you can also pass a React component as a label
|
||||
data: { label: 'Output Node' },
|
||||
position: { x: 250, y: 250 },
|
||||
},
|
||||
{ id: 'e1-2', source: '1', target: '2', animated: true },
|
||||
{ id: 'e2-3', source: '2', target: '3' },
|
||||
];
|
||||
|
||||
export default () => (
|
||||
<div style={{ height: 400, border: '1px solid #EAEDF1', borderRadius: 5 }}>
|
||||
<div style={{ height: 300, border: '1px solid #EAEDF1', borderRadius: 5 }}>
|
||||
<ReactFlow elements={elements} />
|
||||
</div>
|
||||
);
|
||||
|
||||
@@ -25,10 +25,31 @@ import React from 'react';
|
||||
import ReactFlow from 'react-flow-renderer';
|
||||
|
||||
const elements = [
|
||||
{ id: '1', data: { label: 'Node 1' }, position: { x: 250, y: 5 } },
|
||||
// you can also pass a React component as a label
|
||||
{ id: '2', data: { label: <div>Node 2</div> }, position: { x: 100, y: 100 } },
|
||||
// input node
|
||||
{
|
||||
id: '1',
|
||||
type: 'input',
|
||||
data: { label: 'Input Node' },
|
||||
position: { x: 250, y: 25 },
|
||||
},
|
||||
// default node
|
||||
{
|
||||
id: '2',
|
||||
// you can also pass a React component as a label
|
||||
data: { label: <div>Default Node</div> },
|
||||
position: { x: 100, y: 125 },
|
||||
},
|
||||
// output node
|
||||
{
|
||||
id: '3',
|
||||
type: 'output',
|
||||
// you can also pass a React component as a label
|
||||
data: { label: 'Output Node' },
|
||||
position: { x: 250, y: 250 },
|
||||
},
|
||||
// animated edge
|
||||
{ id: 'e1-2', source: '1', target: '2', animated: true },
|
||||
{ id: 'e2-3', source: '2', target: '3' },
|
||||
];
|
||||
|
||||
const BasicFlow = () => <ReactFlow elements={elements} />;
|
||||
|
||||
@@ -100,7 +100,7 @@ const Home = () => {
|
||||
<Flex mt={3} alignItems="center">
|
||||
<DocsButton
|
||||
as={Link}
|
||||
to="/docs"
|
||||
to="/docs/"
|
||||
icon="code"
|
||||
colorizeStroke
|
||||
color="textInverted"
|
||||
@@ -108,7 +108,7 @@ const Home = () => {
|
||||
>
|
||||
Documentation
|
||||
</DocsButton>
|
||||
<ExampleButton to="/examples">
|
||||
<ExampleButton to="/examples/">
|
||||
Examples
|
||||
<Icon
|
||||
width="24px"
|
||||
|
||||
@@ -9,7 +9,7 @@ import CodeBlock from 'components/CodeBlock/Mdx';
|
||||
|
||||
import { getThemeSpacePx } from 'utils/css-utils';
|
||||
|
||||
const PostWrapper = styled.div`
|
||||
const DocWrapper = styled.div`
|
||||
${Text} {
|
||||
margin-bottom: ${getThemeSpacePx(3)};
|
||||
margin-top: ${getThemeSpacePx(3)};
|
||||
@@ -18,16 +18,21 @@ const PostWrapper = styled.div`
|
||||
background: rgb(246, 248, 250);
|
||||
border-radius: 2px;
|
||||
padding: 0 3px;
|
||||
font-size: 14px;
|
||||
}
|
||||
}
|
||||
|
||||
ul,
|
||||
ol {
|
||||
padding-left: ${getThemeSpacePx(5)};
|
||||
padding-left: ${getThemeSpacePx(4)};
|
||||
}
|
||||
|
||||
li {
|
||||
margin-bottom: ${getThemeSpacePx(2)};
|
||||
|
||||
code {
|
||||
font-size: 14px;
|
||||
}
|
||||
}
|
||||
|
||||
hr {
|
||||
@@ -123,9 +128,9 @@ const CustomComponents = {
|
||||
const BlogMdx = ({ content = null }) => {
|
||||
return (
|
||||
<MDXProvider components={CustomComponents}>
|
||||
<PostWrapper>
|
||||
<DocWrapper>
|
||||
<MDXRenderer>{content}</MDXRenderer>
|
||||
</PostWrapper>
|
||||
</DocWrapper>
|
||||
</MDXProvider>
|
||||
);
|
||||
};
|
||||
|
||||
Reference in New Issue
Block a user