├── .eslintrc.js ├── .gitignore ├── .npmrc ├── .nvmrc ├── .prettierignore ├── .prettierrc ├── LICENSE ├── README.md ├── gatsby-browser.js ├── gatsby-config.js ├── gatsby-node.js ├── generators ├── docs.js ├── examples.js ├── markdown-pages.js └── utils.js ├── netlify.toml ├── package-lock.json ├── package.json ├── src ├── assets │ ├── data │ │ ├── examples.json │ │ └── showcases.json │ ├── icons │ │ ├── arrow_right.svg │ │ ├── arrow_right_circle.svg │ │ ├── close.svg │ │ ├── code.svg │ │ ├── eye.svg │ │ ├── favicon_stroke.svg │ │ ├── github_circle.svg │ │ ├── graph_bar.svg │ │ ├── info_circle.svg │ │ ├── lightning.svg │ │ ├── link.svg │ │ ├── mail.svg │ │ ├── menu.svg │ │ ├── pen.svg │ │ ├── phone.svg │ │ ├── twitter_circle.svg │ │ └── twitter_outline.svg │ └── images │ │ ├── blog-webkid-teaser.jpg │ │ ├── logo-white.svg │ │ ├── logo.svg │ │ ├── react-flow-logo.svg │ │ └── showcases │ │ ├── botfront-showcase.png │ │ ├── circles-showcase.png │ │ └── datablocks-showcase.png ├── components │ ├── Button │ │ └── index.js │ ├── CenterContent │ │ └── index.js │ ├── Close │ │ └── index.js │ ├── CodeBlock │ │ ├── Mdx.js │ │ └── index.js │ ├── ContentSection │ │ └── index.js │ ├── Footer │ │ └── index.js │ ├── Header │ │ └── index.js │ ├── HeroFlow │ │ ├── ColorPickerNode.js │ │ └── index.js │ ├── Icon │ │ └── index.js │ ├── InfoBox │ │ └── index.js │ ├── Link │ │ └── index.js │ ├── Logo │ │ └── index.js │ ├── Page │ │ ├── Doc.js │ │ ├── Example.js │ │ ├── MetaTags.js │ │ └── index.js │ ├── SectionIntro │ │ └── index.js │ ├── Showcases │ │ └── index.js │ ├── Sidebar │ │ └── index.js │ ├── TeaserFlow │ │ ├── A.js │ │ ├── B.js │ │ ├── C.js │ │ └── index.js │ └── Typo │ │ └── index.js ├── example-flows │ ├── ContextualZoomFeatures │ │ ├── ZoomNode.js │ │ ├── index.css │ │ └── index.js │ ├── CustomConnectionLine │ │ ├── ConnectionLine.js │ │ └── index.js │ ├── CustomNode │ │ ├── ColorSelectorNode.js │ │ ├── index.css │ │ └── index.js │ ├── DragHandle │ │ ├── DragHandleNode.tsx │ │ └── index.tsx │ ├── DragNDrop │ │ ├── Sidebar.js │ │ ├── dnd.css │ │ └── index.js │ ├── EdgeTypes │ │ ├── index.js │ │ └── utils.js │ ├── EdgeWithButton │ │ ├── ButtonEdge.js │ │ ├── index.css │ │ └── index.js │ ├── Edges │ │ ├── CustomEdge.js │ │ └── index.js │ ├── Empty │ │ └── index.js │ ├── FloatingEdges │ │ ├── FloatingConnectionLine.tsx │ │ ├── FloatingEdge.tsx │ │ ├── index.tsx │ │ ├── style.css │ │ └── utils.ts │ ├── Hidden │ │ └── index.js │ ├── Horizontal │ │ └── index.js │ ├── Interaction │ │ └── index.js │ ├── Layouting │ │ ├── index.js │ │ ├── initial-elements.js │ │ └── layouting.css │ ├── Overview │ │ ├── index.js │ │ └── initial-elements.js │ ├── Provider │ │ ├── Sidebar.js │ │ ├── index.js │ │ └── provider.css │ ├── SaveRestore │ │ ├── index.js │ │ └── save.css │ ├── SmoothTransition │ │ ├── index.js │ │ └── transition.css │ ├── Stress │ │ ├── index.js │ │ └── utils.js │ ├── UpdatableEdge │ │ └── index.js │ ├── UpdateNode │ │ ├── index.js │ │ └── updatenode.css │ ├── Validation │ │ ├── index.js │ │ └── validation.css │ └── ZoomPanHelper │ │ ├── Sidebar.js │ │ ├── index.js │ │ └── zoompanhelper.css ├── hooks │ ├── useExamplePages.js │ ├── useMenuHeight.js │ └── useShowcaseImages.js ├── markdown │ └── docs │ │ ├── api │ │ ├── component-props.md │ │ ├── components │ │ │ ├── background.md │ │ │ ├── controls.md │ │ │ ├── minimap.md │ │ │ └── provider.md │ │ ├── edge-types.md │ │ ├── edge-utils.md │ │ ├── edges.md │ │ ├── handle.md │ │ ├── helper-functions.md │ │ ├── hooks.md │ │ ├── internal-state-actions.md │ │ ├── node-types │ │ │ ├── index.md │ │ │ └── node-types.js │ │ ├── nodes.md │ │ └── react-flow-instance.md │ │ ├── getting-started │ │ ├── Basic.js │ │ ├── BasicFunctions.js │ │ └── index.md │ │ ├── index.md │ │ └── theming.md ├── pages │ ├── 404.js │ └── index.js ├── styles │ └── global.css ├── templates │ ├── doc-page.js │ ├── example-page.js │ └── mdx-renderer │ │ ├── DefaultMdx.js │ │ └── DocMdx.js ├── themes │ ├── global.js │ ├── index.js │ └── normalize.js └── utils │ ├── browser-utils.js │ ├── css-utils.js │ └── project-utils.js └── static ├── favicon.ico ├── fonts ├── JetBrainsMono-Bold.eot ├── JetBrainsMono-Bold.woff ├── JetBrainsMono-Bold.woff2 ├── JetBrainsMono-Regular.eot ├── JetBrainsMono-Regular.woff └── JetBrainsMono-Regular.woff2 ├── images └── react-flow-header.jpg └── robots.txt /.eslintrc.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | env: { 3 | browser: true, 4 | es6: true, 5 | }, 6 | plugins: ['react'], 7 | globals: { 8 | graphql: false, 9 | __REACT_FLOW_VERSION__: true, 10 | }, 11 | parserOptions: { 12 | sourceType: 'module', 13 | ecmaFeatures: { 14 | experimentalObjectRestSpread: true, 15 | jsx: true, 16 | }, 17 | }, 18 | extends: 'react-app', 19 | }; 20 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | node_modules/ 2 | public 3 | .gatsby-context.js 4 | .DS_Store 5 | .intermediate-representation/ 6 | .cache/ 7 | yarn.lock 8 | *.log 9 | .env 10 | .yalc 11 | yalc.lock -------------------------------------------------------------------------------- /.npmrc: -------------------------------------------------------------------------------- 1 | legacy-peer-deps=true -------------------------------------------------------------------------------- /.nvmrc: -------------------------------------------------------------------------------- 1 | v15.10.0 2 | -------------------------------------------------------------------------------- /.prettierignore: -------------------------------------------------------------------------------- 1 | src/pages/blog/**/*.md -------------------------------------------------------------------------------- /.prettierrc: -------------------------------------------------------------------------------- 1 | { 2 | "trailingComma": "es5", 3 | "semi": true, 4 | "singleQuote": true, 5 | "printWidth": 120 6 | } 7 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | The MIT License 2 | 3 | Copyright (c) webkid GmbH 2019-2022 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in 13 | all copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 21 | THE SOFTWARE. 22 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # react-flow-docs-v9 2 | 3 | #### ⚠️ These are the old docs for React Flow v9. For the up-to-date documentation, please refer to: [wbkd/react-flow-docs](https://github.com/wbkd/react-flow-docs) ⚠️ 4 | 5 | ## Development 6 | 7 | - `npm install` 8 | - `npm run dev` 9 | 10 | ## Build 11 | 12 | - `npm run build` 13 | -------------------------------------------------------------------------------- /gatsby-browser.js: -------------------------------------------------------------------------------- 1 | import 'babel-polyfill'; 2 | import './src/styles/global.css'; 3 | 4 | export const onRouteUpdate = () => { 5 | document.body.classList.remove('noscroll'); 6 | }; 7 | -------------------------------------------------------------------------------- /gatsby-config.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | siteMetadata: { 3 | title: `React Flow - Open Source Library`, 4 | siteUrl: `https://reactflow.dev`, 5 | description: 6 | 'React Flow is a highly customizable library for building interactive node-based editors, flow charts and diagrams.', 7 | }, 8 | plugins: [ 9 | 'gatsby-plugin-image', 10 | { 11 | resolve: `gatsby-source-filesystem`, 12 | options: { 13 | name: 'pages', 14 | path: `${__dirname}/src/pages`, 15 | }, 16 | }, 17 | { 18 | resolve: `gatsby-source-filesystem`, 19 | options: { 20 | name: 'exampleflows', 21 | path: `${__dirname}/src/example-flows`, 22 | }, 23 | }, 24 | { 25 | resolve: `gatsby-source-filesystem`, 26 | options: { 27 | name: `markdown`, 28 | path: `${__dirname}/src/markdown`, 29 | }, 30 | }, 31 | { 32 | resolve: `gatsby-source-filesystem`, 33 | options: { 34 | name: `assets`, 35 | path: `${__dirname}/src/assets`, 36 | ignore: [`**/.*`], // ignore files starting with a dot 37 | }, 38 | }, 39 | { 40 | resolve: `gatsby-plugin-manifest`, 41 | options: { 42 | icon: `src/assets/images/react-flow-logo.svg`, 43 | name: `React Flow`, 44 | short_name: `react-flow`, 45 | start_url: `/`, 46 | background_color: `#f7f0eb`, 47 | theme_color: `#1A192B`, 48 | display: `standalone`, 49 | lang: 'en', 50 | }, 51 | }, 52 | `gatsby-plugin-sharp`, 53 | `gatsby-remark-images`, 54 | { 55 | resolve: `gatsby-transformer-remark`, 56 | options: { 57 | plugins: [ 58 | { 59 | resolve: `gatsby-remark-images`, 60 | options: { 61 | linkImagesToOriginal: false, 62 | }, 63 | }, 64 | ], 65 | }, 66 | }, 67 | { 68 | resolve: `gatsby-plugin-mdx`, 69 | options: { 70 | gatsbyRemarkPlugins: [ 71 | { 72 | resolve: `gatsby-remark-images`, 73 | options: { 74 | maxWidth: 1200, 75 | showCaptions: true, 76 | quality: 85, 77 | backgroundColor: 'white', 78 | linkImagesToOriginal: false, 79 | }, 80 | }, 81 | 'gatsby-remark-copy-linked-files', 82 | ], 83 | remarkPlugins: [require('remark-unwrap-images')], 84 | extensions: [`.md`, `.mdx`], 85 | }, 86 | }, 87 | `gatsby-transformer-json`, 88 | `gatsby-plugin-react-helmet`, 89 | `gatsby-plugin-emotion`, 90 | { 91 | resolve: `gatsby-plugin-react-svg`, 92 | options: { 93 | rule: { 94 | include: /icons/, 95 | }, 96 | }, 97 | }, 98 | `gatsby-transformer-sharp`, 99 | `gatsby-plugin-netlify`, 100 | `gatsby-transformer-javascript-frontmatter`, 101 | ], 102 | }; 103 | -------------------------------------------------------------------------------- /gatsby-node.js: -------------------------------------------------------------------------------- 1 | const path = require('path'); 2 | const { createFilePath } = require('gatsby-source-filesystem'); 3 | 4 | const docsGenerator = require('./generators/docs'); 5 | const exampleGenerator = require('./generators/examples'); 6 | 7 | const pkg = require('./package.json'); 8 | 9 | exports.createPages = ({ graphql, actions }) => { 10 | const { createPage } = actions; 11 | 12 | const generateDocs = docsGenerator(createPage, graphql); 13 | const generateExamples = exampleGenerator(createPage, graphql); 14 | 15 | return Promise.all([generateDocs, generateExamples]); 16 | }; 17 | 18 | exports.onCreateNode = ({ node, actions, getNode }) => { 19 | const { createNodeField } = actions; 20 | 21 | if (node.internal.type === 'Mdx') { 22 | const value = createFilePath({ node, getNode }); 23 | 24 | createNodeField({ 25 | name: 'slug', 26 | node, 27 | value, 28 | }); 29 | } 30 | }; 31 | 32 | exports.onCreateWebpackConfig = ({ actions, plugins }) => { 33 | actions.setWebpackConfig({ 34 | resolve: { 35 | modules: [path.resolve(__dirname, 'src'), 'node_modules'], 36 | alias: { 37 | 'example-flows': path.resolve(__dirname, 'src', 'example-flows'), 38 | }, 39 | }, 40 | devServer: { 41 | host: '0.0.0.0', 42 | }, 43 | plugins: [ 44 | plugins.define({ 45 | __REACT_FLOW_VERSION__: JSON.stringify( 46 | pkg.dependencies['react-flow-renderer'].replace('^', '') 47 | ), 48 | }), 49 | ], 50 | }); 51 | }; 52 | -------------------------------------------------------------------------------- /generators/docs.js: -------------------------------------------------------------------------------- 1 | const path = require('path'); 2 | 3 | const docsTemplate = path.resolve('./src/templates/doc-page.js'); 4 | 5 | const docPagesQuery = ` 6 | { 7 | docs: allMdx( 8 | filter: { 9 | fields: { 10 | slug: { regex: "/docs/" }, 11 | } 12 | } 13 | ) { 14 | edges { 15 | node { 16 | fields { 17 | slug 18 | } 19 | frontmatter { 20 | title 21 | id 22 | } 23 | } 24 | } 25 | } 26 | } 27 | `; 28 | 29 | const createDocPages = (createPage, docPages) => { 30 | const menu = docPages.map((page) => ({ 31 | slug: page.node.fields.slug, 32 | ...page.node.frontmatter, 33 | })); 34 | 35 | docPages.forEach((page) => { 36 | createPage({ 37 | path: page.node.fields.slug, 38 | component: docsTemplate, 39 | context: { 40 | slug: page.node.fields.slug, 41 | menu, 42 | }, 43 | }); 44 | }); 45 | }; 46 | 47 | const blogGenerator = (createPage, graphql) => 48 | new Promise((resolve, reject) => { 49 | resolve( 50 | graphql(docPagesQuery).then((result) => { 51 | if (result.errors) { 52 | console.log(result.errors); 53 | reject(result.errors); 54 | } 55 | 56 | const docPages = result.data.docs.edges; 57 | 58 | try { 59 | createDocPages(createPage, docPages); 60 | } catch (e) { 61 | console.log(e); 62 | } 63 | }) 64 | ); 65 | }); 66 | 67 | module.exports = blogGenerator; 68 | -------------------------------------------------------------------------------- /generators/examples.js: -------------------------------------------------------------------------------- 1 | const path = require('path'); 2 | 3 | const exampleTemplate = path.resolve('./src/templates/example-page.js'); 4 | 5 | const examplePagesQuery = `{ 6 | allExamplesJson { 7 | edges { 8 | node { 9 | slug 10 | title 11 | source 12 | description 13 | } 14 | } 15 | } 16 | } 17 | `; 18 | 19 | const createExamplePage = (createPage, examplePages) => { 20 | examplePages.forEach((page) => { 21 | const { slug, title, source, description } = page.node; 22 | 23 | createPage({ 24 | path: slug, 25 | component: exampleTemplate, 26 | context: { 27 | slug, 28 | title, 29 | source, 30 | description, 31 | sourceSlug: `/example-flows/${source}/`, 32 | }, 33 | }); 34 | }); 35 | }; 36 | 37 | const exampleGenerator = (createPage, graphql) => 38 | new Promise((resolve, reject) => { 39 | resolve( 40 | graphql(examplePagesQuery).then((result) => { 41 | if (result.errors) { 42 | console.log(result.errors); 43 | reject(result.errors); 44 | } 45 | 46 | const pages = result.data.allExamplesJson.edges; 47 | 48 | try { 49 | createExamplePage(createPage, pages); 50 | } catch (e) { 51 | console.log(e); 52 | } 53 | }) 54 | ); 55 | }); 56 | 57 | module.exports = exampleGenerator; 58 | -------------------------------------------------------------------------------- /generators/markdown-pages.js: -------------------------------------------------------------------------------- 1 | const path = require('path'); 2 | const utils = require('./utils'); 3 | 4 | const defaultTemplate = path.resolve('./src/templates/default-page.js'); 5 | 6 | const mdQuery = ` 7 | { 8 | pages: allMdx { 9 | edges { 10 | node { 11 | fields { 12 | slug 13 | } 14 | frontmatter { 15 | published 16 | } 17 | } 18 | } 19 | } 20 | } 21 | `; 22 | 23 | const filterSpecialPages = (mdPage) => { 24 | const slug = mdPage.node.fields.slug; 25 | return slug.indexOf('/blog') !== 0 && slug.indexOf('/projects') !== 0; 26 | }; 27 | 28 | const createMdPages = (createPage, mdPages) => { 29 | mdPages 30 | .filter(filterSpecialPages) 31 | .filter(utils.filterPublished) 32 | .forEach((mdPage) => { 33 | createPage({ 34 | path: mdPage.node.fields.slug, 35 | component: defaultTemplate, 36 | context: { 37 | slug: mdPage.node.fields.slug, 38 | fields: mdPage.node.fields, 39 | }, 40 | }); 41 | }); 42 | }; 43 | 44 | const mdPagesGenerator = (createPage, graphql) => 45 | new Promise((resolve, reject) => { 46 | resolve( 47 | graphql(mdQuery).then((result) => { 48 | if (result.errors) { 49 | console.log(result.errors); 50 | reject(result.errors); 51 | } 52 | 53 | const mdPages = result.data.pages.edges; 54 | try { 55 | createMdPages(createPage, mdPages); 56 | } catch (e) { 57 | console.log(e); 58 | } 59 | }) 60 | ); 61 | }); 62 | 63 | module.exports = mdPagesGenerator; 64 | -------------------------------------------------------------------------------- /generators/utils.js: -------------------------------------------------------------------------------- 1 | function filterPublished(post) { 2 | const isPublished = post.node.frontmatter && post.node.frontmatter.published; 3 | return process.env.NODE_ENV === 'development' || isPublished; 4 | } 5 | 6 | module.exports = { 7 | filterPublished, 8 | }; 9 | -------------------------------------------------------------------------------- /netlify.toml: -------------------------------------------------------------------------------- 1 | [[plugins]] 2 | package = "netlify-plugin-gatsby-cache" -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "react-flow-website", 3 | "description": "", 4 | "version": "1.0.0", 5 | "author": "webkid", 6 | "bugs": { 7 | "url": "https://github.com/wbkd/react-flow/issues" 8 | }, 9 | "browserslist": [ 10 | ">0.25%", 11 | "ie 11" 12 | ], 13 | "dependencies": { 14 | "@emotion/react": "^11.4.0", 15 | "@emotion/styled": "^11.3.0", 16 | "@mdx-js/mdx": "^1.6.22", 17 | "@mdx-js/react": "^1.6.22", 18 | "@react-hook/size": "^2.1.2", 19 | "@svgr/webpack": "^5.5.0", 20 | "babel-polyfill": "^6.26.0", 21 | "d3-array": "^3.0.1", 22 | "d3-color": "^3.0.1", 23 | "d3-scale": "^4.0.0", 24 | "d3-shape": "^3.0.1", 25 | "dagre": "^0.8.5", 26 | "emotion-normalize": "^11.0.1", 27 | "gatsby": "^3.8.1", 28 | "gatsby-plugin-draft": "^0.1.0", 29 | "gatsby-plugin-emotion": "^6.8.0", 30 | "gatsby-plugin-image": "^1.8.0", 31 | "gatsby-plugin-manifest": "^3.8.0", 32 | "gatsby-plugin-mdx": "^2.8.0", 33 | "gatsby-plugin-netlify": "^3.8.0", 34 | "gatsby-plugin-react-helmet": "^4.8.0", 35 | "gatsby-plugin-react-svg": "^3.0.1", 36 | "gatsby-plugin-svgr": "^2.1.0", 37 | "gatsby-remark-copy-linked-files": "^4.5.0", 38 | "gatsby-remark-images": "^5.5.0", 39 | "gatsby-remark-unwrap-images": "^1.0.2", 40 | "gatsby-source-filesystem": "^3.8.0", 41 | "gatsby-transformer-javascript-frontmatter": "^3.8.0", 42 | "gatsby-transformer-json": "^3.8.0", 43 | "gatsby-transformer-remark": "^4.5.0", 44 | "localforage": "^1.9.0", 45 | "popmotion": "^10.0.2", 46 | "prism-react-renderer": "^1.2.1", 47 | "rc-table": "^7.17.0", 48 | "react": "^17.0.2", 49 | "react-dom": "^17.0.2", 50 | "react-flow-renderer": "^9.6.9", 51 | "react-helmet": "^6.1.0", 52 | "reflexbox": "^4.0.6", 53 | "remark-unwrap-images": "^2.1.0", 54 | "slugify": "^1.5.3" 55 | }, 56 | "devDependencies": { 57 | "@octokit/rest": "^18.6.6", 58 | "babel-preset-gatsby": "^1.8.0", 59 | "eslint": "^7.29.0", 60 | "eslint-plugin-react": "^7.24.0", 61 | "gatsby-cli": "^3.8.0", 62 | "gatsby-plugin-sharp": "^3.8.0", 63 | "gatsby-transformer-sharp": "^3.8.0", 64 | "gh-pages": "^3.2.3", 65 | "prettier": "^2.3.2", 66 | "sharp": "^0.28.3" 67 | }, 68 | "homepage": "https://reactflow.dev", 69 | "keywords": [ 70 | "gatsby" 71 | ], 72 | "license": "MIT", 73 | "main": "n/a", 74 | "repository": { 75 | "type": "git", 76 | "url": "git+https://github.com/wbkd/react-flow.git" 77 | }, 78 | "scripts": { 79 | "start": "npm run dev", 80 | "dev": "gatsby develop -H 0.0.0.0", 81 | "clean": "gatsby clean", 82 | "lint": "eslint --ext .js,.jsx --ignore-pattern public .", 83 | "test": "echo \"Error: no test specified\" && exit 1", 84 | "format": "prettier --trailing-comma es5 --no-semi --single-quote --write 'src/**/*.js' 'src/**/*.md'", 85 | "build": "GATSBY_EXPERIMENTAL_PAGE_BUILD_ON_DATA_CHANGES=true gatsby build --log-pages", 86 | "deploy": "gatsby build --prefix-paths && gh-pages -d public", 87 | "fix-semi": "eslint --quiet --ignore-pattern node_modules --ignore-pattern public --parser babel-eslint --no-eslintrc --rule '{\"semi\": [2, \"never\"], \"no-extra-semi\": [2]}' --fix gatsby-node.js" 88 | } 89 | } 90 | -------------------------------------------------------------------------------- /src/assets/data/showcases.json: -------------------------------------------------------------------------------- 1 | [ 2 | { 3 | "title": "Botfront - Conversational platform", 4 | "url": "https://botfront.io/", 5 | "image": "../images/showcases/botfront-showcase.png" 6 | }, 7 | { 8 | "title": "datablocks - Node-based data editor", 9 | "url": "https://datablocks.pro", 10 | "image": "../images/showcases/datablocks-showcase.png" 11 | }, 12 | { 13 | "title": "Circles - Visual degree planner", 14 | "url": "https://circles360.github.io/", 15 | "image": "../images/showcases/circles-showcase.png" 16 | } 17 | ] 18 | -------------------------------------------------------------------------------- /src/assets/icons/arrow_right.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | -------------------------------------------------------------------------------- /src/assets/icons/arrow_right_circle.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /src/assets/icons/close.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | -------------------------------------------------------------------------------- /src/assets/icons/code.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | -------------------------------------------------------------------------------- /src/assets/icons/eye.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | -------------------------------------------------------------------------------- /src/assets/icons/favicon_stroke.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | -------------------------------------------------------------------------------- /src/assets/icons/github_circle.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | -------------------------------------------------------------------------------- /src/assets/icons/graph_bar.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /src/assets/icons/info_circle.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | -------------------------------------------------------------------------------- /src/assets/icons/lightning.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /src/assets/icons/link.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /src/assets/icons/mail.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /src/assets/icons/menu.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | -------------------------------------------------------------------------------- /src/assets/icons/pen.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /src/assets/icons/phone.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | -------------------------------------------------------------------------------- /src/assets/icons/twitter_circle.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | -------------------------------------------------------------------------------- /src/assets/icons/twitter_outline.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | -------------------------------------------------------------------------------- /src/assets/images/blog-webkid-teaser.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/xyflow/react-flow-docs-v9/4ab1ff8e6dfbf94c31868f913f6338d57c83667b/src/assets/images/blog-webkid-teaser.jpg -------------------------------------------------------------------------------- /src/assets/images/logo-white.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | -------------------------------------------------------------------------------- /src/assets/images/logo.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | -------------------------------------------------------------------------------- /src/assets/images/react-flow-logo.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | -------------------------------------------------------------------------------- /src/assets/images/showcases/botfront-showcase.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/xyflow/react-flow-docs-v9/4ab1ff8e6dfbf94c31868f913f6338d57c83667b/src/assets/images/showcases/botfront-showcase.png -------------------------------------------------------------------------------- /src/assets/images/showcases/circles-showcase.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/xyflow/react-flow-docs-v9/4ab1ff8e6dfbf94c31868f913f6338d57c83667b/src/assets/images/showcases/circles-showcase.png -------------------------------------------------------------------------------- /src/assets/images/showcases/datablocks-showcase.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/xyflow/react-flow-docs-v9/4ab1ff8e6dfbf94c31868f913f6338d57c83667b/src/assets/images/showcases/datablocks-showcase.png -------------------------------------------------------------------------------- /src/components/Button/index.js: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | import styled from '@emotion/styled'; 3 | import { rgba } from 'utils/css-utils'; 4 | import { Flex } from 'reflexbox'; 5 | 6 | import Icon from 'components/Icon'; 7 | import { getThemeColor } from 'utils/css-utils'; 8 | 9 | const Button = styled.button` 10 | color: ${(p) => p.theme.colors[p.color || 'button']}; 11 | border: ${(p) => 12 | p.type === 'ghost' 13 | ? '1px solid rgba(0,0,0,0)' 14 | : `1px solid ${p.theme.colors[p.color || 'button']}`}; 15 | background: ${(p) => 16 | p.active 17 | ? rgba(p.color ? p.theme.colors[p.color] : p.theme.colors.button, 0.2) 18 | : 'none'}; 19 | padding: ${(p) => (p.type === 'big' ? '12px 20px' : '8px 16px')}; 20 | border-radius: 25px; 21 | outline: none; 22 | cursor: pointer; 23 | font-size: ${(p) => p.theme.fontSizesPx[1]}; 24 | letter-spacing: 0.5px; 25 | line-height: 1; 26 | transition: 0.075s all ease-in-out; 27 | 28 | svg { 29 | width: 100%; 30 | } 31 | 32 | &:visited, 33 | &:focus, 34 | &:active { 35 | color: ${(p) => p.theme.colors[p.color || 'button']}; 36 | } 37 | 38 | &:hover { 39 | opacity: 1; 40 | color: ${getThemeColor('background')}; 41 | background-color: ${getThemeColor('button')}; 42 | 43 | svg { 44 | path, 45 | circle, 46 | rect, 47 | line, 48 | polyline { 49 | stroke: ${getThemeColor('background')}; 50 | } 51 | } 52 | 53 | svg { 54 | .nostroke { 55 | stroke: none; 56 | fill: ${getThemeColor('background')}; 57 | } 58 | } 59 | } 60 | 61 | &:active { 62 | transform: scale(0.95); 63 | } 64 | `; 65 | 66 | export default ({ 67 | icon, 68 | color = 'button', 69 | children, 70 | type = 'normal', 71 | iconWidth = '20px', 72 | ...props 73 | }) => ( 74 | 88 | ); 89 | -------------------------------------------------------------------------------- /src/components/CenterContent/index.js: -------------------------------------------------------------------------------- 1 | import styled from '@emotion/styled'; 2 | import { Box } from 'reflexbox'; 3 | 4 | import { getThemeSpacePx } from 'utils/css-utils'; 5 | 6 | export default styled(Box)` 7 | max-width: ${(p) => 8 | p.maxWidth || (p.big ? p.theme.maxWidthBig : p.theme.maxWidth)}; 9 | margin-left: auto; 10 | margin-right: auto; 11 | padding-left: ${getThemeSpacePx(3)}; 12 | padding-right: ${getThemeSpacePx(3)}; 13 | `; 14 | -------------------------------------------------------------------------------- /src/components/Close/index.js: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | import styled from '@emotion/styled'; 3 | import { Flex } from 'reflexbox'; 4 | 5 | import { getThemeSpacePx } from 'utils/css-utils'; 6 | import Icon from 'components/Icon'; 7 | 8 | const Close = styled(Flex)` 9 | padding: ${getThemeSpacePx(1)}; 10 | line-height: 1; 11 | width: 50px; 12 | height: 50px; 13 | `; 14 | 15 | export default ({ onClick, ...props }) => { 16 | return ( 17 | 18 | 19 | 20 | 21 | 22 | ); 23 | }; 24 | -------------------------------------------------------------------------------- /src/components/CodeBlock/Mdx.js: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | import Highlight, { defaultProps } from 'prism-react-renderer'; 3 | import dracula from 'prism-react-renderer/themes/github'; 4 | 5 | export default ({ children, className = 'javascript', language }) => { 6 | const lang = language ? language : className.replace(/language-/, ''); 7 | 8 | return ( 9 | 15 | {({ className, style, tokens, getLineProps, getTokenProps }) => ( 16 |
27 |           {tokens.map(
28 |             (line, i, lines) =>
29 |               !(
30 |                 line.length === 1 &&
31 |                 line[0].empty &&
32 |                 (i === 0 || i === lines.length - 1)
33 |               ) && (
34 |                 
35 | {line.map((token, key) => ( 36 | 37 | ))} 38 |
39 | ) 40 | )} 41 |
42 | )} 43 |
44 | ); 45 | }; 46 | -------------------------------------------------------------------------------- /src/components/CodeBlock/index.js: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | import styled from '@emotion/styled'; 3 | import { Box } from 'reflexbox'; 4 | 5 | import { colors } from 'themes'; 6 | import CodeBlock from './Mdx'; 7 | import { H4, AttributionText } from 'components/Typo'; 8 | 9 | const Wrapper = styled(Box)` 10 | margin: 0 auto; 11 | padding: 5px 0; 12 | 13 | h4 { 14 | margin-bottom: 10px; 15 | } 16 | 17 | pre { 18 | margin: 0; 19 | font-size: 14px; 20 | } 21 | 22 | code { 23 | border: 1px solid ${colors.lightGrey}; 24 | border-radius: 3px; 25 | } 26 | `; 27 | 28 | export default ({ 29 | language = 'javascript', 30 | code, 31 | title = '', 32 | subtitle = '', 33 | }) => { 34 | return ( 35 | 36 | {title &&

{title}

} 37 | {code} 38 | {subtitle && {subtitle}} 39 |
40 | ); 41 | }; 42 | -------------------------------------------------------------------------------- /src/components/ContentSection/index.js: -------------------------------------------------------------------------------- 1 | import React, { Fragment } from 'react'; 2 | import { Box } from 'reflexbox'; 3 | 4 | import theme from 'themes/index'; 5 | 6 | import CenterContent from 'components/CenterContent'; 7 | 8 | export default ({ 9 | children, 10 | bg = 'transparent', 11 | centered = false, 12 | id = null, 13 | big = false, 14 | ...rest 15 | }) => { 16 | const WrapperComponent = centered ? CenterContent : Fragment; 17 | const wrapperProps = centered ? { big: big } : {}; 18 | 19 | return ( 20 | 26 | {children} 27 | 28 | ); 29 | }; 30 | -------------------------------------------------------------------------------- /src/components/Footer/index.js: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | import styled from '@emotion/styled'; 3 | import { Flex } from 'reflexbox'; 4 | 5 | import Icon from 'components/Icon'; 6 | import Logo from 'components/Logo'; 7 | 8 | const Wrapper = styled.footer` 9 | flex-shrink: 0; 10 | border-top: ${(p) => 11 | p.hasBorder ? `1px solid ${p.theme.colors.silverLighten30}` : 'nonde'}; 12 | `; 13 | 14 | const Header = ({ hasBorder = false }) => { 15 | return ( 16 | 17 | 18 | 19 | A project by 20 | 21 | 22 | 23 | 24 | 25 | 34 | 42 | 43 | 44 | 45 | ); 46 | }; 47 | 48 | export default Header; 49 | -------------------------------------------------------------------------------- /src/components/HeroFlow/ColorPickerNode.js: -------------------------------------------------------------------------------- 1 | import React, { memo, useCallback } from 'react'; 2 | import styled from '@emotion/styled'; 3 | import { Handle } from 'react-flow-renderer'; 4 | 5 | import { getThemeColor } from 'utils/css-utils'; 6 | 7 | const ColorPickerNodeWrapper = styled.div` 8 | padding: 10px; 9 | background: white; 10 | border: 1px solid ${getThemeColor('violet')}; 11 | border-radius: 4px; 12 | box-shadow: ${(p) => 13 | p.selected ? `0 0 0 0.25px ${p.theme.colors.violet}` : 'none'}; 14 | 15 | .react-flow__handle { 16 | background: ${(p) => p.color}; 17 | } 18 | 19 | input { 20 | -webkit-appearance: none; 21 | appearance: none; 22 | width: 100%; 23 | height: 8px; 24 | background: ${getThemeColor('silver')}; 25 | outline: none; 26 | border-radius: 2px; 27 | } 28 | 29 | input::-webkit-slider-thumb { 30 | -webkit-appearance: none; 31 | appearance: none; 32 | width: 12px; 33 | height: 12px; 34 | background: ${(p) => p.color}; 35 | cursor: pointer; 36 | border-radius: 100%; 37 | } 38 | 39 | input::-moz-range-thumb { 40 | width: 12px; 41 | height: 12px; 42 | background: ${(p) => p.color}; 43 | cursor: pointer; 44 | border-radius: 100%; 45 | } 46 | `; 47 | 48 | const ColorPickerNode = memo(({ data, id, selected }) => { 49 | const onChange = useCallback((event) => data.onChange(event, id), [data, id]); 50 | const colorName = `${data.color[0].toUpperCase()}${data.color.substr(1)}`; 51 | 52 | return ( 53 | 58 |
{colorName} amount
59 | 67 | 68 |
69 | ); 70 | }); 71 | 72 | export default ColorPickerNode; 73 | -------------------------------------------------------------------------------- /src/components/Icon/index.js: -------------------------------------------------------------------------------- 1 | import React, { useState, useEffect } from 'react'; 2 | import styled from '@emotion/styled'; 3 | import { Flex } from 'reflexbox'; 4 | import { isOldIE } from 'utils/browser-utils'; 5 | 6 | import Mail from 'assets/icons/mail.svg'; 7 | import Github from 'assets/icons/github_circle.svg'; 8 | import ArrowRight from 'assets/icons/arrow_right.svg'; 9 | import Menu from 'assets/icons/menu.svg'; 10 | import Code from 'assets/icons/code.svg'; 11 | 12 | const IconWrapper = styled(Flex)` 13 | justify-content: center; 14 | align-items: center; 15 | 16 | svg { 17 | max-width: 100%; 18 | height: auto; 19 | display: flex; 20 | flex-direction: column; 21 | justify-content: center; 22 | 23 | path, 24 | circle, 25 | rect, 26 | line, 27 | polyline { 28 | stroke: ${(p) => 29 | p.colorizeStroke 30 | ? p.theme.colors[p.strokeColor] || p.theme.colors.text 31 | : 'none'}; 32 | } 33 | 34 | path.nostroke, 35 | circle.nostroke, 36 | rect.nostroke, 37 | line.nostroke, 38 | polyline.nostroke { 39 | stroke: none; 40 | fill: ${(p) => 41 | p.colorizeStroke 42 | ? p.theme.colors[p.strokeColor] || p.theme.colors.text 43 | : 'none'}; 44 | } 45 | } 46 | `; 47 | 48 | const preLoaded = { 49 | mail: Mail, 50 | arrow_right: ArrowRight, 51 | menu: Menu, 52 | github_circle: Github, 53 | code: Code, 54 | }; 55 | 56 | const getPreLoadedIcon = (name) => 57 | preLoaded[name] ? () => preLoaded[name] : null; 58 | 59 | export default ({ 60 | name = 'datavis', 61 | colorizeStroke = false, 62 | strokeColor = null, 63 | ...restProps 64 | }) => { 65 | const [SVGComponent, setSVGComponent] = useState(getPreLoadedIcon(name)); 66 | 67 | useEffect(() => { 68 | if (!SVGComponent) { 69 | (async () => { 70 | try { 71 | const svgComp = await import(`assets/icons/${name}.svg`); 72 | setSVGComponent(svgComp); 73 | } catch (err) { 74 | console.warn(`error loading icon: ${name}`); 75 | } 76 | })(); 77 | } 78 | }, [SVGComponent, name]); 79 | 80 | if (!SVGComponent) { 81 | return null; 82 | } 83 | 84 | const IconComponent = SVGComponent.default 85 | ? SVGComponent.default 86 | : SVGComponent; 87 | 88 | if (isOldIE()) { 89 | return null; 90 | } 91 | 92 | return ( 93 | 100 | 101 | 102 | ); 103 | }; 104 | -------------------------------------------------------------------------------- /src/components/InfoBox/index.js: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | import styled from '@emotion/styled'; 3 | import { Box } from 'reflexbox'; 4 | 5 | const Wrapper = styled(Box)` 6 | padding: 16px; 7 | background: ${(p) => p.theme.colors.violetLighten45}; 8 | color: white; 9 | border-radius: 5px; 10 | margin: 20px 0; 11 | `; 12 | 13 | const Title = styled(Box)` 14 | font-size: 20px; 15 | margin-bottom: 4px; 16 | font-weight: 900; 17 | `; 18 | 19 | export default ({ title = null, text, ...rest }) => { 20 | return ( 21 | 22 | {title} 23 |
{text}
24 |
25 | ); 26 | }; 27 | -------------------------------------------------------------------------------- /src/components/Link/index.js: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | import { Link as GatsbyLink } from 'gatsby'; 3 | 4 | const Link = ({ children, to, activeClassName, partiallyActive, ...other }) => { 5 | const internal = /^\/(?!\/)/.test(to); 6 | 7 | if (internal) { 8 | return ( 9 | 15 | {children} 16 | 17 | ); 18 | } 19 | return ( 20 | 21 | {children} 22 | 23 | ); 24 | }; 25 | export default Link; 26 | -------------------------------------------------------------------------------- /src/components/Logo/index.js: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | import styled from '@emotion/styled'; 3 | import { useTheme, jsx } from '@emotion/react'; 4 | 5 | import WbkdLogoWhite from 'assets/images/logo-white.svg'; 6 | import WbkdLogoBlack from 'assets/images/logo.svg'; 7 | 8 | const Image = styled.img` 9 | display: block; 10 | width: 75px; 11 | `; 12 | 13 | const getLogoSrc = (type, inverted, theme) => { 14 | if (type) { 15 | return type === 'white' ? WbkdLogoWhite : WbkdLogoBlack; 16 | } 17 | 18 | if (inverted) { 19 | return theme.name === 'light' ? WbkdLogoWhite : WbkdLogoBlack; 20 | } 21 | 22 | return theme.name === 'light' ? WbkdLogoBlack : WbkdLogoWhite; 23 | }; 24 | 25 | export default ({ type = null, inverted = false, style = {} }) => { 26 | const theme = useTheme(); 27 | const logoSrc = getLogoSrc(type, inverted, theme); 28 | 29 | return webkid logo; 30 | }; 31 | -------------------------------------------------------------------------------- /src/components/Page/Doc.js: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | import styled from '@emotion/styled'; 3 | import { Flex, Box } from 'reflexbox'; 4 | 5 | import Page from 'components/Page'; 6 | import Sidebar from 'components/Sidebar'; 7 | 8 | const Wrapper = styled(Flex)` 9 | border-top: 1px solid ${(p) => p.theme.colors.silverLighten30}; 10 | `; 11 | 12 | const DocWrapper = styled(Box)` 13 | max-width: 620px; 14 | margin: 0 auto; 15 | position: relative; 16 | padding: 0 16px; 17 | `; 18 | 19 | export default ({ children, menu = [], ...rest }) => ( 20 | 21 | 22 | 23 | {children} 24 | 25 | 26 | ); 27 | -------------------------------------------------------------------------------- /src/components/Page/Example.js: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | import styled from '@emotion/styled'; 3 | import { Flex, Box } from 'reflexbox'; 4 | 5 | import Page from 'components/Page'; 6 | import Sidebar from 'components/Sidebar'; 7 | import useExamplePages from 'hooks/useExamplePages'; 8 | import CodeBlock from 'components/CodeBlock'; 9 | import { Text, H4 } from 'components/Typo'; 10 | 11 | import 'example-flows/Overview'; 12 | 13 | const Wrapper = styled(Flex)` 14 | flex-grow: 1; 15 | `; 16 | 17 | const ReactFlowWrapper = styled(Box)` 18 | flex-grow: 1; 19 | 20 | .react-flow { 21 | border-bottom: 1px solid ${(p) => p.theme.colors.silverLighten30}; 22 | height: 65vh; 23 | } 24 | `; 25 | 26 | const SourceWrapper = styled(Box)` 27 | max-width: 1000px; 28 | margin: 0 auto; 29 | `; 30 | 31 | const SourceCodeBlock = ({ absolutePath, internal }) => { 32 | const splittedPath = absolutePath.split('/'); 33 | const fileName = splittedPath[splittedPath.length - 1]; 34 | 35 | return ( 36 | 37 | {fileName} 38 | 39 | 40 | ); 41 | }; 42 | 43 | export default ({ children, title, slug, description, sourceCodeFiles = [] }) => { 44 | const menu = useExamplePages(); 45 | 46 | const metaTags = { 47 | title: `React Flow - ${title} Example`, 48 | siteUrl: `https://reactflow.dev/examples/${slug}`, 49 | robots: 'index, follow', 50 | }; 51 | 52 | const hasSource = sourceCodeFiles.length > 0; 53 | 54 | return ( 55 | 56 | 57 | 58 | 59 | {children} 60 | {hasSource && ( 61 | 62 | {description && } 63 |

{title} Source Code

64 | {sourceCodeFiles.map((source) => ( 65 | 66 | ))} 67 |
68 | )} 69 |
70 |
71 |
72 | ); 73 | }; 74 | -------------------------------------------------------------------------------- /src/components/Page/MetaTags.js: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | import { Helmet } from 'react-helmet'; 3 | 4 | const MetaTags = ({ 5 | title, 6 | description, 7 | siteUrl, 8 | robots, 9 | image, 10 | pathname, 11 | article, 12 | }) => { 13 | if (pathname) { 14 | siteUrl = `${siteUrl}${pathname}`; 15 | } 16 | 17 | if (image) { 18 | image = `https://reactflow.dev${image}`; 19 | } else { 20 | image = 'https://reactflow.dev/images/react-flow-header.jpg'; 21 | } 22 | 23 | return ( 24 | 25 | 26 | {title} 27 | {description && } 28 | {description && } 29 | 30 | {siteUrl && } 31 | {(article ? true : null) && } 32 | {title && } 33 | {description && } 34 | {image && } 35 | 36 | 37 | {title && } 38 | {description && } 39 | {image && } 40 | 41 | {process.env.NODE_ENV === 'production' && ( 42 | 47 | )} 48 | 49 | ); 50 | }; 51 | 52 | export default MetaTags; 53 | -------------------------------------------------------------------------------- /src/components/Page/index.js: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | import styled from '@emotion/styled'; 3 | import { ThemeProvider, jsx } from '@emotion/react'; 4 | import { Flex, Box } from 'reflexbox'; 5 | 6 | import Header from 'components/Header'; 7 | import Footer from 'components/Footer'; 8 | import themes from 'themes'; 9 | 10 | import NormalizeStyle from 'themes/normalize'; 11 | import GlobalStyle from 'themes/global'; 12 | import MetaTags from './MetaTags'; 13 | import { getThemeColor } from 'utils/css-utils'; 14 | 15 | const PageWrapper = styled(Flex)` 16 | color: ${getThemeColor('text')}; 17 | width: 100%; 18 | position: relative; 19 | flex-direction: column; 20 | height: 100vh; 21 | position: relative; 22 | `; 23 | 24 | const PageContent = styled(Box)` 25 | flex: 1 0 auto; 26 | `; 27 | 28 | const Page = ({ 29 | children, 30 | theme = 'light', 31 | metaTags, 32 | footerBorder = false, 33 | ...rest 34 | }) => { 35 | const pageTheme = themes[theme]; 36 | 37 | return ( 38 | 39 | 40 | 41 | 42 | 43 |
44 | {children} 45 |