├── examples ├── README.md ├── area.png ├── rows.png ├── columns.png ├── nesting.png ├── public │ ├── favicon.ico │ ├── manifest.json │ └── index.html ├── area-responsive-match.png ├── area-responsive-no-match.png ├── package.json └── src │ ├── createServiceWorker.js │ └── index.js ├── .babelrc ├── .gitignore ├── logo.png ├── .flowconfig ├── .prettierrc ├── .babelrc.js ├── .eslintrc ├── package.json ├── src └── index.js └── README.md /examples/README.md: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /.babelrc: -------------------------------------------------------------------------------- 1 | { 2 | "presets": ["./.babelrc.js"] 3 | } 4 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | node_modules 2 | es/* 3 | dist/* 4 | package-lock.json -------------------------------------------------------------------------------- /logo.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nem035/react-gridit/HEAD/logo.png -------------------------------------------------------------------------------- /examples/area.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nem035/react-gridit/HEAD/examples/area.png -------------------------------------------------------------------------------- /examples/rows.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nem035/react-gridit/HEAD/examples/rows.png -------------------------------------------------------------------------------- /examples/columns.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nem035/react-gridit/HEAD/examples/columns.png -------------------------------------------------------------------------------- /examples/nesting.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nem035/react-gridit/HEAD/examples/nesting.png -------------------------------------------------------------------------------- /.flowconfig: -------------------------------------------------------------------------------- 1 | [ignore] 2 | 3 | [include] 4 | 5 | [libs] 6 | 7 | [lints] 8 | 9 | [options] 10 | -------------------------------------------------------------------------------- /examples/public/favicon.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nem035/react-gridit/HEAD/examples/public/favicon.ico -------------------------------------------------------------------------------- /examples/area-responsive-match.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nem035/react-gridit/HEAD/examples/area-responsive-match.png -------------------------------------------------------------------------------- /.prettierrc: -------------------------------------------------------------------------------- 1 | { 2 | "singleQuote": true, 3 | "semi": true, 4 | "trailingComma": "none", 5 | "parser": "babylon" 6 | } 7 | -------------------------------------------------------------------------------- /examples/area-responsive-no-match.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nem035/react-gridit/HEAD/examples/area-responsive-no-match.png -------------------------------------------------------------------------------- /.babelrc.js: -------------------------------------------------------------------------------- 1 | const modules = 2 | process.env.BABEL_ENV === "cjs" || process.env.NODE_ENV === "test" 3 | ? "commonjs" 4 | : false; 5 | 6 | module.exports = { 7 | presets: ["react", ["es2015", { modules, loose: true }], "flow"] 8 | }; 9 | -------------------------------------------------------------------------------- /.eslintrc: -------------------------------------------------------------------------------- 1 | { 2 | "parser": "babel-eslint", 3 | "extends": ["airbnb", "react", "prettier"], 4 | "plugins": ["prettier"], 5 | "rules": { 6 | "prettier/prettier": ["error"], 7 | "react/jsx-filename-extension": 0, 8 | "no-use-before-define": 0, 9 | "no-param-reassign": 0 10 | }, 11 | "env": { 12 | "browser": true, 13 | "node": true 14 | } 15 | } 16 | -------------------------------------------------------------------------------- /examples/public/manifest.json: -------------------------------------------------------------------------------- 1 | { 2 | "short_name": "React App", 3 | "name": "Create React App Sample", 4 | "icons": [ 5 | { 6 | "src": "favicon.ico", 7 | "sizes": "192x192", 8 | "type": "image/png" 9 | } 10 | ], 11 | "start_url": "./index.html", 12 | "display": "standalone", 13 | "theme_color": "#000000", 14 | "background_color": "#ffffff" 15 | } 16 | -------------------------------------------------------------------------------- /examples/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "react-gridit-examples", 3 | "version": "1.0.0", 4 | "description": "", 5 | "main": "examples.js", 6 | "author": "Nemanja Stojanovic ", 7 | "license": "MIT", 8 | "dependencies": { 9 | "react-dom": "^16.2.0", 10 | "react-gridit": "^0.2.0", 11 | "react-syntax-highlighter": "^6.1.1" 12 | }, 13 | "devDependencies": { 14 | "react-scripts": "1.0.0" 15 | }, 16 | "scripts": { 17 | "start": "react-scripts start", 18 | "build": "react-scripts build", 19 | "test": "react-scripts test --env=jsdom", 20 | "eject": "react-scripts eject" 21 | } 22 | } 23 | -------------------------------------------------------------------------------- /examples/public/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 11 | 12 | 13 | 22 | React App 23 | 24 | 25 | 26 |
27 | 37 | 38 | 39 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "react-gridit", 3 | "version": "0.3.1", 4 | "description": "React grid using CSS Grid and styled-components", 5 | "main": "dist/index.js", 6 | "module": "es/index.js", 7 | "jsnext:main": "es/index.js", 8 | "scripts": { 9 | "build:cjs": "BABEL_ENV=cjs babel src --out-dir dist", 10 | "build:es": "BABEL_ENV=es babel src --out-dir es", 11 | "build": "npm run build:es && npm run build:cjs", 12 | "clean": "trash dist es", 13 | "examples": "cd examples && npm i && npm start", 14 | "flow": "flow", 15 | "format": "prettier-eslint \"{src}/**/*.{js,jsx}\" --write", 16 | "lint": "eslint . --ignore-path .gitignore", 17 | "prebuild": "npm run clean", 18 | "prepare": "npm run build" 19 | }, 20 | "author": "Nemanja Stojanovic ", 21 | "homepage": "https://github.com/nem035/react-gridit.git", 22 | "repository": { 23 | "type": "git", 24 | "url": "https://github.com/nem035/react-gridit.git" 25 | }, 26 | "bugs": { 27 | "url": "https://github.com/nem035/react-gridit/issues" 28 | }, 29 | "pre-commit": ["format", "flow"], 30 | "keywords": [ 31 | "react", 32 | "react-component", 33 | "composition", 34 | "simple", 35 | "grid", 36 | "layout", 37 | "css", 38 | "column", 39 | "row" 40 | ], 41 | "files": ["es", "dist"], 42 | "license": "MIT", 43 | "dependencies": { 44 | "pre-commit": "^1.2.2", 45 | "react": "^16.2.0", 46 | "react-media": "^1.6.1", 47 | "styled-components": "^2.4.0" 48 | }, 49 | "devDependencies": { 50 | "babel-cli": "^6.26.0", 51 | "babel-eslint": "^7.2.3", 52 | "babel-preset-es2015": "^6.24.1", 53 | "babel-preset-flow": "^6.23.0", 54 | "babel-preset-react": "^6.24.1", 55 | "eslint": "^3.19.0", 56 | "eslint-config-airbnb": "^15.0.1", 57 | "eslint-config-prettier": "^2.9.0", 58 | "eslint-plugin-import": "^2.6.1", 59 | "eslint-plugin-jsx-a11y": "^5.1.1", 60 | "eslint-plugin-prettier": "^2.4.0", 61 | "eslint-plugin-react": "^7.1.0", 62 | "flow-bin": "^0.62.0", 63 | "prettier": "^1.9.2", 64 | "prettier-eslint-cli": "^4.7.0", 65 | "trash-cli": "^1.4.0" 66 | } 67 | } 68 | -------------------------------------------------------------------------------- /src/index.js: -------------------------------------------------------------------------------- 1 | // @flow 2 | import React, { Children } from "react"; 3 | 4 | import Media from "react-media"; 5 | import type { Node } from "react"; 6 | import styled from "styled-components"; 7 | 8 | type GridAreaProps = { 9 | children: Node, 10 | area: string, 11 | query?: string, 12 | fallbackArea?: string 13 | }; 14 | 15 | type GridProps = { 16 | children: Node, 17 | size?: string, 18 | minSize?: string 19 | }; 20 | 21 | const dimension = (props: GridProps) => 22 | Children.toArray(props.children).reduce( 23 | (cssString, child) => 24 | child && typeof child.props.size === "string" 25 | ? `${cssString} ${child.props.size}` 26 | : `${cssString} minmax(${props.minSize || "1em"}, 1fr)`, 27 | "" 28 | ); 29 | 30 | const Grid = styled.div` 31 | display: grid; 32 | `; 33 | 34 | export default Grid; 35 | 36 | export const GridRows = styled(Grid)` 37 | grid-template-rows: ${dimension}; 38 | `; 39 | 40 | export const GridColumns = styled(Grid)` 41 | grid-template-columns: ${dimension}; 42 | `; 43 | 44 | const GridAreaView = styled(Grid)` 45 | grid-template-areas: ${props => props.area}; 46 | `; 47 | 48 | export const GridArea = (props: GridAreaProps) => { 49 | const namesSet = new Set( 50 | props.area.split(/"*(\s|\r?\n|\r)"*/).filter(s => s.trim() && s !== ".") 51 | ); 52 | 53 | const children = React.Children.map(props.children, child => { 54 | if (child) { 55 | const areaName = Object.keys(child.props).find(propName => 56 | namesSet.has(propName) 57 | ); 58 | if (areaName) { 59 | return React.cloneElement(child, { 60 | style: { 61 | gridArea: areaName 62 | } 63 | }); 64 | } 65 | } 66 | return child; 67 | }); 68 | 69 | if (props.query) { 70 | return ( 71 | 72 | {matches => 73 | matches ? ( 74 | {children} 75 | ) : ( 76 | {children} 77 | ) 78 | } 79 | 80 | ); 81 | } 82 | 83 | return {children}; 84 | }; 85 | 86 | GridArea.defaultProps = { 87 | query: null 88 | }; 89 | -------------------------------------------------------------------------------- /examples/src/createServiceWorker.js: -------------------------------------------------------------------------------- 1 | // In production, we register a service worker to serve assets from local cache. 2 | 3 | // This lets the app load faster on subsequent visits in production, and gives 4 | // it offline capabilities. However, it also means that developers (and users) 5 | // will only see deployed updates on the "N+1" visit to a page, since previously 6 | // cached resources are updated in the background. 7 | 8 | // To learn more about the benefits of this model, read https://goo.gl/KwvDNy. 9 | // This link also includes instructions on opting out of this behavior. 10 | 11 | export default function register() { 12 | if (process.env.NODE_ENV === 'production' && 'serviceWorker' in navigator) { 13 | window.addEventListener('load', () => { 14 | const swUrl = `${process.env.PUBLIC_URL}/service-worker.js`; 15 | navigator.serviceWorker 16 | .register(swUrl) 17 | .then(registration => { 18 | // eslint-disable-next-line no-param-reassign 19 | registration.onupdatefound = () => { 20 | const installingWorker = registration.installing; 21 | installingWorker.onstatechange = () => { 22 | if (installingWorker.state === 'installed') { 23 | if (navigator.serviceWorker.controller) { 24 | // At this point, the old content will have been purged and 25 | // the fresh content will have been added to the cache. 26 | // It's the perfect time to display a "New content is 27 | // available; please refresh." message in your web app. 28 | console.log('New content is available; please refresh.'); // eslint-disable-line no-console 29 | } else { 30 | // At this point, everything has been precached. 31 | // It's the perfect time to display a 32 | // "Content is cached for offline use." message. 33 | console.log('Content is cached for offline use.'); // eslint-disable-line no-console 34 | } 35 | } 36 | }; 37 | }; 38 | }) 39 | .catch(error => { 40 | console.error('Error during service worker registration:', error); 41 | }); 42 | }); 43 | } 44 | } 45 | 46 | export function unregister() { 47 | if ('serviceWorker' in navigator) { 48 | navigator.serviceWorker.ready.then(registration => { 49 | registration.unregister(); 50 | }); 51 | } 52 | } 53 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 |

2 | 3 | react-gridit 4 | 5 |

6 | 7 | # [react-gridit](https://www.npmjs.org/package/react-gridit) 8 | 9 | React grid using [CSS Grid](https://developer.mozilla.org/en-US/docs/Web/CSS/CSS_Grid_Layout) and [styled-components](https://www.styled-components.com/) 10 | 11 | ## Install 12 | 13 | ```bash 14 | npm i react-gridit 15 | ``` 16 | 17 | or 18 | 19 | ```bash 20 | yarn add react-gridit 21 | ``` 22 | 23 | ## Examples 24 | 25 | [![Codesandbox examples](https://codesandbox.io/static/img/play-codesandbox.svg)](https://codesandbox.io/s/10p4l2m33) or checkout the [examples](https://github.com/nem035/react-gridit/tree/master/examples) React app. 26 | 27 | You can run the examples locally by doing `npm run examples`. 28 | 29 | ### Rows 30 | 31 | ```jsx 32 | 33 | 1 34 | 2 35 | 3 36 | 4 37 | 5 38 | 39 | ``` 40 | 41 | Output: 42 | 43 | react-gridit-rows 44 | 45 | ### Columns 46 | 47 | ```jsx 48 | 49 | 1 50 | 2 51 | 3 52 | 4 53 | 5 54 | 55 | ``` 56 | 57 | react-gridit-columns 58 | 59 | ### Nesting 60 | 61 | ```jsx 62 | 63 | 64 | 1 65 | 3 66 | 67 | 68 | 1 69 | 70 | 71 | 1 72 | 4 73 | 2 74 | 75 | 76 | ``` 77 | 78 | react-gridit-nesting 79 | 80 | ### Areas 81 | 82 | ```jsx 83 | 90 | Header 91 | Sidebar 92 | Main1 93 | Main2 94 | Footer 95 | 96 | ``` 97 | 98 | Output: 99 | 100 | react-gridit-area 101 | 102 | ### Responsive areas 103 | 104 | ```jsx 105 | 113 | A 114 | B 115 | C 116 | D 117 | 118 | ``` 119 | 120 | Output (match): 121 | 122 | react-gridit-area-responsive-match 123 | 124 | Output (no match): 125 | 126 | react-gridit-area-responsive-no-match 127 | 128 | ## License 129 | 130 | MIT 131 | -------------------------------------------------------------------------------- /examples/src/index.js: -------------------------------------------------------------------------------- 1 | import { GridArea, GridColumns, GridRows } from "react-gridit"; 2 | 3 | /* eslint-disable */ 4 | import React from "react"; 5 | import SyntaxHighlighter from "react-syntax-highlighter/prism"; 6 | import { dark } from "react-syntax-highlighter/styles/prism"; 7 | import { render } from "react-dom"; 8 | import styled from "styled-components"; 9 | 10 | const colors = ["#1abc9c", "#3498db", "#2ecc71", "#9b59b6", "#34495e"]; 11 | 12 | const getColorFromChar = props => { 13 | if (props.a || props.header) return colors[0]; 14 | if (props.b || props.sidebar) return colors[1]; 15 | if (props.c || props.main1) return colors[2]; 16 | if (props.d || props.main2) return colors[3]; 17 | return colors[4]; 18 | }; 19 | 20 | const Block = styled.div` 21 | display: flex; 22 | align-items: center; 23 | justify-content: center; 24 | background-color: ${props => 25 | props.size ? colors[parseInt(props.size) - 1] : getColorFromChar(props)}; 26 | padding: 5px; 27 | `; 28 | 29 | const Title = styled.h2` 30 | background-color: #ccc; 31 | color: #2c3e50; 32 | margin: 0; 33 | text-align: center; 34 | border-bottom: 5px dashed #2c3e50; 35 | `; 36 | 37 | const Examples = styled.div` 38 | border: 5px dashed #2c3e50; 39 | background-color: #ecf0f1; 40 | `; 41 | 42 | const Example = styled.div` 43 | height: 100%; 44 | width: 100%; 45 | &:not(:last-child) { 46 | border-bottom: 5px dashed #2c3e50; 47 | } 48 | `; 49 | 50 | const Center = styled.div` 51 | display: flex; 52 | justify-content: center; 53 | align-items: center; 54 | `; 55 | 56 | render( 57 | 58 | 59 | GridRows 60 |
61 | 62 | {` 63 | 1 64 | 2 65 | 3 66 | 4 67 | 5 68 | `} 69 | 70 |
71 | 72 | 1 73 | 2 74 | 3 75 | 4 76 | 5 77 | 78 |
79 | 80 | GridColumns 81 |
82 | 83 | {` 84 | 1 85 | 2 86 | 3 87 | 4 88 | 5 89 | `} 90 | 91 |
92 | 93 | 1 94 | 2 95 | 3 96 | 4 97 | 5 98 | 99 |
100 | 101 | GridArea 102 |
103 | 104 | {` 110 | Header 111 | Sidebar 112 | Main1 113 | Main2 114 | Footer 115 | `} 116 | 117 |
118 | 125 | Header 126 | Sidebar 127 | Main1 128 | Main2 129 | Footer 130 | 131 |
132 | 133 | GridArea (Responsive) 134 |
135 | 136 | {` 144 | A 145 | B 146 | C 147 | D 148 | Footer 149 | `} 150 | 151 |
152 | 160 | A 161 | B 162 | C 163 | D 164 | 165 |
166 |
, 167 | document.getElementById("root") 168 | ); 169 | --------------------------------------------------------------------------------