Grid component updated

This commit is contained in:
Andrey Savihin 2019-12-20 14:53:07 +03:00
parent b4cd81edaf
commit 27ee4325be
8 changed files with 425 additions and 194 deletions

View File

@ -75,6 +75,7 @@
"jest": "^24.9.0",
"jest-enzyme": "^7.1.2",
"jest-junit": "^10.0.0",
"jest-styled-components": "^6.3.4",
"postcss": "^7.0.24",
"react": "^16.12.0",
"react-dom": "^16.12.0",

View File

@ -19,8 +19,8 @@ import { Grid } from "asc-web-components";
| `alignContent` | `string` | - | - | - | sets the distribution of space between and around content items along a flexbox's cross-axis or a grid's block axis |
| `alignItems` | `string` | - | - | - | sets the align-self value on all direct children as a group. In Flexbox, it controls the alignment of items on the Cross Axis. In Grid Layout, it controls the alignment of items on the Block Axis within their grid area. |
| `alignSelf` | `string` | - | - | - | overrides a grid or flex item's align-items value. In Grid, it aligns the item inside the grid area. In Flexbox, it aligns the item on the cross axis. |
| `areasProp` | `string`,`object` | - | - | - | specifies named grid areas. |
| `columnsProp` | `string`,`object` | - | - | - | defines the line names and track sizing functions of the grid columns. |
| `areasProp` | `array` | - | `[["header","header"],["navbar","main"]]`, `[{ name: "header", start: [0, 0], end: [1, 0] }, { name: "navbar", start: [0, 1], end: [0, 1] }, { name: "main", start: [1, 1], end: [1, 1] }]` | - | specifies named grid areas. Takes value as array of string arrays that specify named grid areas. Or objects array, that contains names and coordinates of areas. |
| `columnsProp` | `string`,`array`,`object` | - | `"25%"`, `["200px", ["100px","1fr"], "auto"]`, `{ count: 3, size: "100px" }` | - | defines the sizing of the grid columns. Specifying a single string will repeat several columns of this size. Specifying an object allows you to specify the number of repetitions and the size of the column. Or you can specify an array with column sizes. The column size can be specified as an array of minimum and maximum widths. |
| `gridArea` | `string` | - | - | - | is a shorthand property for grid-row-start, grid-column-start, grid-row-end and grid-column-end, specifying a grid items size and location within the grid by contributing a line, a span, or nothing (automatic) to its grid placement, thereby specifying the edges of its grid area. |
| `gridColumnGap` | `string` | - | - | - | sets the size of the gap (gutter) between an element's columns. |
| `gridGap` | `string` | - | - | - | sets the gaps (gutters) between rows and columns. It is a shorthand for row-gap and column-gap. |
@ -31,5 +31,5 @@ import { Grid } from "asc-web-components";
| `justifySelf` | `string` | - | - | - | sets the way a box is justified inside its alignment container along the appropriate axis. |
| `marginProp` | `string` | - | - | - | sets the margin area on all four sides of an element. It is a shorthand for margin-top, margin-right, margin-bottom, and margin-left. |
| `paddingProp` | `string` | - | - | - | sets the padding area on all four sides of an element. It is a shorthand for padding-top, padding-right, padding-bottom, and padding-left |
| `rowsProp` | `string`,`object` | - | - | - | defines the line names and track sizing functions of the grid rows. |
| `rowsProp` | `string`,`array` | - | `"50px"`, `["100px", ["100px","1fr"], "auto"]` | - | defines the sizing of the grid rows. Specifying a single string will repeat several rows of this size. Or you can specify an array with rows sizes. The row size can be specified as an array of minimum and maximum heights. |
| `widthProp` | `string` | - | - | `100%` | defines the width of the border of the element area. |

View File

@ -0,0 +1,41 @@
import React, {forwardRef} from "react";
import PropTypes from 'prop-types';
import StyledGrid from './styledGrid';
const Grid = forwardRef(({ tag, as, ...rest }, ref) => {
//console.log("Grid render", rest)
return (
<StyledGrid as={!as && tag ? tag : as} ref={ref} {...rest} />
);
});
Grid.propTypes = {
as: PropTypes.string,
alignContent: PropTypes.string,
alignItems: PropTypes.string,
alignSelf: PropTypes.string,
areasProp: PropTypes.array,
columnsProp: PropTypes.oneOfType([PropTypes.string, PropTypes.array, PropTypes.object]),
gridArea: PropTypes.string,
gridColumnGap: PropTypes.string,
gridGap: PropTypes.string,
gridRowGap: PropTypes.string,
heightProp: PropTypes.string,
justifyContent: PropTypes.string,
justifyItems: PropTypes.string,
justifySelf: PropTypes.string,
marginProp: PropTypes.string,
paddingProp: PropTypes.string,
rowsProp: PropTypes.oneOfType([PropTypes.string, PropTypes.array]),
tag: PropTypes.string,
widthProp: PropTypes.string
}
Grid.defaultProps = {
heightProp: '100%',
widthProp: '100%'
};
Grid.displayName = "Grid";
export default Grid;

View File

@ -4,16 +4,70 @@ import withReadme from 'storybook-readme/with-readme';
import Readme from './README.md';
import Grid from '.';
import Box from '../box';
import Text from "../text";
const gridProps = {
marginProp: "0 0 20px 0"
};
const boxProps = {
paddingProp: "10px",
displayProp: "flex",
alignItems: "center",
justifyContent: "center"
};
storiesOf('Components|Grid', module)
.addDecorator(withReadme(Readme))
.add('base', () => (
.add("Columns", () => (
<>
<Grid {...gridProps} columnsProp={["200px", ["100px","1fr"], "auto"]}>
<Box {...boxProps} backgroundProp="#F4991A"><Text>200px</Text></Box>
<Box {...boxProps} backgroundProp="#F2EAD3"><Text>minmax(100px,1fr)</Text></Box>
<Box {...boxProps} backgroundProp="#F9F5F0"><Text>auto</Text></Box>
</Grid>
<Grid {...gridProps} columnsProp="25%">
<Box {...boxProps} backgroundProp="#F4991A"><Text>25%</Text></Box>
<Box {...boxProps} backgroundProp="#F2EAD3"><Text>25%</Text></Box>
<Box {...boxProps} backgroundProp="#F9F5F0"><Text>25%</Text></Box>
</Grid>
<Grid {...gridProps} columnsProp={{ count: 3, size: "100px" }}>
<Box {...boxProps} backgroundProp="#F4991A"><Text>100px</Text></Box>
<Box {...boxProps} backgroundProp="#F2EAD3"><Text>100px</Text></Box>
<Box {...boxProps} backgroundProp="#F9F5F0"><Text>100px</Text></Box>
</Grid>
<Grid {...gridProps} columnsProp={{ count: 3, size: ["100px", "1fr"] }}>
<Box {...boxProps} backgroundProp="#F4991A"><Text>minmax(100px,1fr)</Text></Box>
<Box {...boxProps} backgroundProp="#F2EAD3"><Text>minmax(100px,1fr)</Text></Box>
<Box {...boxProps} backgroundProp="#F9F5F0"><Text>minmax(100px,1fr)</Text></Box>
</Grid>
</>
))
.add("Rows", () => (
<>
<Grid {...gridProps} rowsProp={["100px", ["100px","1fr"], "auto"]}>
<Box {...boxProps} backgroundProp="#F4991A"><Text>100px</Text></Box>
<Box {...boxProps} backgroundProp="#F2EAD3"><Text>minmax(100px,1fr)</Text></Box>
<Box {...boxProps} backgroundProp="#F9F5F0"><Text>auto</Text></Box>
</Grid>
<Grid {...gridProps} rowsProp="50px">
<Box {...boxProps} backgroundProp="#F4991A"><Text>50px</Text></Box>
<Box {...boxProps} backgroundProp="#F2EAD3"><Text>50px</Text></Box>
<Box {...boxProps} backgroundProp="#F9F5F0"><Text>50px</Text></Box>
</Grid>
</>
))
.add('Layout', () => (
<Grid
widthProp="100%"
widthProp="100vw"
heightProp="100vh"
gridGap="10px"
rowsProp={["auto", "1fr", "auto"]}
columnsProp={[["100px","1fr"], "3fr", "100px"]}
columnsProp={[["100px","1fr"], "3fr", ["100px","1fr"]]}
areasProp={[
{ name: "header", start: [0, 0], end: [2, 0] },
{ name: "navbar", start: [0, 1], end: [0, 1] },
@ -22,58 +76,10 @@ storiesOf('Components|Grid', module)
{ name: "footer", start: [0, 2], end: [2, 2] }
]}
>
<Box
gridArea="header"
displayProp="flex"
alignItems="center"
justifyContent="center"
backgroundProp="#F4991A"
paddingProp="30px"
>
header
</Box>
<Box
gridArea="navbar"
displayProp="flex"
alignItems="center"
justifyContent="center"
backgroundProp="radial-gradient(red, blue)"
>
navbar
</Box>
<Box
gridArea="main"
borderProp={{
style: "dashed solid double dotted",
width: "2em 1rem 1px 2%",
color: "red yellow green blue",
radius: "10% 30% 50% 70%"
}}
displayProp="flex"
alignItems="center"
justifyContent="center"
backgroundProp="#F9F5F0"
>
main
</Box>
<Box
gridArea="sidebar"
displayProp="flex"
alignItems="center"
justifyContent="center"
backgroundProp="#F2EAD3"
>
sidebar
</Box>
<Box
gridArea="footer"
displayProp="flex"
alignItems="center"
justifyContent="center"
backgroundProp="#F4991A"
marginProp="30px"
>
footer
</Box>
<Box {...boxProps} gridArea="header" backgroundProp="#F4991A"><Text>header</Text></Box>
<Box {...boxProps} gridArea="navbar" backgroundProp="#F2EAD3"><Text>navbar</Text></Box>
<Box {...boxProps} gridArea="main" backgroundProp="#F9F5F0"><Text>main</Text></Box>
<Box {...boxProps} gridArea="sidebar" backgroundProp="#F2EAD3"><Text>sidebar</Text></Box>
<Box {...boxProps} gridArea="footer" backgroundProp="#F4991A"><Text>footer</Text></Box>
</Grid>
));

View File

@ -1,5 +1,7 @@
import React from 'react';
import { mount } from 'enzyme';
import renderer from 'react-test-renderer'
import 'jest-styled-components'
import Grid from '.';
describe('<Grid />', () => {
@ -10,4 +12,204 @@ describe('<Grid />', () => {
expect(wrapper).toExist();
});
});
it("id, className, style is exists", () => {
const wrapper = mount(
<Grid id="testId" className="test" style={{ color: "red" }} />
);
expect(wrapper.prop("id")).toEqual("testId");
expect(wrapper.prop("className")).toEqual("test");
expect(wrapper.getDOMNode().style).toHaveProperty("color", "red");
});
it("props transfer test", () => {
const wrapper = mount(
<Grid
alignContent="center"
alignItems="center"
alignSelf="center"
areasProp={[
{ name: "header", start: [0, 0], end: [2, 0] },
{ name: "navbar", start: [0, 1], end: [0, 1] },
{ name: "main", start: [1, 1], end: [1, 1] },
{ name: "sidebar", start: [2, 1], end: [2, 1] },
{ name: "footer", start: [0, 2], end: [2, 2] }
]}
columnsProp={[["100px","1fr"], "3fr", ["100px","1fr"]]}
gridArea="grid"
gridColumnGap="10px"
gridGap="10px"
gridRowGap="10px"
heightProp="100vh"
justifyContent="center"
justifyItems="center"
justifySelf="center"
marginProp="10px"
paddingProp="10px"
rowsProp={["auto", "1fr", "auto"]}
tag="div"
widthProp="100vw"
/>
);
expect(wrapper.props().alignContent).toEqual("center");
expect(wrapper.props().alignItems).toEqual("center");
expect(wrapper.props().alignSelf).toEqual("center");
expect(Array.isArray(wrapper.props().areasProp)).toEqual(true);
expect(wrapper.props().areasProp.length).toEqual(5);
expect(wrapper.props().areasProp[0].name).toEqual("header");
expect(Array.isArray(wrapper.props().areasProp[0].start)).toEqual(true);
expect(wrapper.props().areasProp[0].start.length).toEqual(2);
expect(wrapper.props().areasProp[0].start[0]).toEqual(0);
expect(wrapper.props().areasProp[0].start[1]).toEqual(0);
expect(Array.isArray(wrapper.props().areasProp[0].end)).toEqual(true);
expect(wrapper.props().areasProp[0].end.length).toEqual(2);
expect(wrapper.props().areasProp[0].end[0]).toEqual(2);
expect(wrapper.props().areasProp[0].end[1]).toEqual(0);
expect(wrapper.props().areasProp[1].name).toEqual("navbar");
expect(Array.isArray(wrapper.props().areasProp[1].start)).toEqual(true);
expect(wrapper.props().areasProp[1].start.length).toEqual(2);
expect(wrapper.props().areasProp[1].start[0]).toEqual(0);
expect(wrapper.props().areasProp[1].start[1]).toEqual(1);
expect(Array.isArray(wrapper.props().areasProp[1].end)).toEqual(true);
expect(wrapper.props().areasProp[1].end.length).toEqual(2);
expect(wrapper.props().areasProp[1].end[0]).toEqual(0);
expect(wrapper.props().areasProp[1].end[1]).toEqual(1);
expect(wrapper.props().areasProp[2].name).toEqual("main");
expect(Array.isArray(wrapper.props().areasProp[2].start)).toEqual(true);
expect(wrapper.props().areasProp[2].start.length).toEqual(2);
expect(wrapper.props().areasProp[2].start[0]).toEqual(1);
expect(wrapper.props().areasProp[2].start[1]).toEqual(1);
expect(Array.isArray(wrapper.props().areasProp[2].end)).toEqual(true);
expect(wrapper.props().areasProp[2].end.length).toEqual(2);
expect(wrapper.props().areasProp[2].end[0]).toEqual(1);
expect(wrapper.props().areasProp[2].end[1]).toEqual(1);
expect(wrapper.props().areasProp[3].name).toEqual("sidebar");
expect(Array.isArray(wrapper.props().areasProp[3].start)).toEqual(true);
expect(wrapper.props().areasProp[3].start.length).toEqual(2);
expect(wrapper.props().areasProp[3].start[0]).toEqual(2);
expect(wrapper.props().areasProp[3].start[1]).toEqual(1);
expect(Array.isArray(wrapper.props().areasProp[3].end)).toEqual(true);
expect(wrapper.props().areasProp[3].end.length).toEqual(2);
expect(wrapper.props().areasProp[3].end[0]).toEqual(2);
expect(wrapper.props().areasProp[3].end[1]).toEqual(1);
expect(wrapper.props().areasProp[4].name).toEqual("footer");
expect(Array.isArray(wrapper.props().areasProp[4].start)).toEqual(true);
expect(wrapper.props().areasProp[4].start.length).toEqual(2);
expect(wrapper.props().areasProp[4].start[0]).toEqual(0);
expect(wrapper.props().areasProp[4].start[1]).toEqual(2);
expect(Array.isArray(wrapper.props().areasProp[4].end)).toEqual(true);
expect(wrapper.props().areasProp[4].end.length).toEqual(2);
expect(wrapper.props().areasProp[4].end[0]).toEqual(2);
expect(wrapper.props().areasProp[4].end[1]).toEqual(2);
expect(Array.isArray(wrapper.props().columnsProp)).toEqual(true);
expect(wrapper.props().columnsProp.length).toEqual(3);
expect(wrapper.props().gridArea).toEqual("grid");
expect(wrapper.props().gridColumnGap).toEqual("10px");
expect(wrapper.props().gridGap).toEqual("10px");
expect(wrapper.props().gridRowGap).toEqual("10px");
expect(wrapper.props().heightProp).toEqual("100vh");
expect(wrapper.props().justifyContent).toEqual("center");
expect(wrapper.props().justifyItems).toEqual("center");
expect(wrapper.props().justifySelf).toEqual("center");
expect(wrapper.props().marginProp).toEqual("10px");
expect(wrapper.props().paddingProp).toEqual("10px");
expect(Array.isArray(wrapper.props().rowsProp)).toEqual(true);
expect(wrapper.props().rowsProp.length).toEqual(3);
expect(wrapper.props().rowsProp[0]).toEqual("auto");
expect(wrapper.props().rowsProp[1]).toEqual("1fr");
expect(wrapper.props().rowsProp[2]).toEqual("auto");
expect(wrapper.props().tag).toEqual("div");
expect(wrapper.props().widthProp).toEqual("100vw");
const wrapper2 = mount(<Grid columnsProp={{ count: 3, size: "100px" }} />);
expect(typeof wrapper.props().columnsProp).toEqual("object");
expect(wrapper2.props().columnsProp.count).toEqual(3);
expect(wrapper2.props().columnsProp.size).toEqual("100px");
const wrapper3 = mount(<Grid columnsProp="25%" />);
expect(typeof wrapper3.props().columnsProp).toEqual("string");
expect(wrapper3.props().columnsProp).toEqual("25%");
const wrapper4 = mount(<Grid rowsProp="50px" />);
expect(typeof wrapper4.props().rowsProp).toEqual("string");
expect(wrapper4.props().rowsProp).toEqual("50px");
const wrapper5 = mount(<Grid areasProp={[
["header", "header", "header"],
["navbar", "main", "sidebar"],
["footer", "footer", "footer"]
]} />);
expect(Array.isArray(wrapper5.props().areasProp)).toEqual(true);
expect(wrapper5.props().areasProp.length).toEqual(3);
expect(Array.isArray(wrapper5.props().areasProp[0])).toEqual(true);
expect(wrapper5.props().areasProp[0].length).toEqual(3);
expect(wrapper5.props().areasProp[0][0]).toEqual("header");
expect(wrapper5.props().areasProp[0][1]).toEqual("header");
expect(wrapper5.props().areasProp[0][2]).toEqual("header");
expect(Array.isArray(wrapper5.props().areasProp[1])).toEqual(true);
expect(wrapper5.props().areasProp[1].length).toEqual(3);
expect(wrapper5.props().areasProp[1][0]).toEqual("navbar");
expect(wrapper5.props().areasProp[1][1]).toEqual("main");
expect(wrapper5.props().areasProp[1][2]).toEqual("sidebar");
expect(Array.isArray(wrapper5.props().areasProp[2])).toEqual(true);
expect(wrapper5.props().areasProp[2].length).toEqual(3);
expect(wrapper5.props().areasProp[2][0]).toEqual("footer");
expect(wrapper5.props().areasProp[2][1]).toEqual("footer");
expect(wrapper5.props().areasProp[2][2]).toEqual("footer");
});
test('it applies styles', () => {
const tree = renderer.create(<Grid />).toJSON();
expect(tree).toHaveStyleRule('display', 'grid');
const tree1 = renderer.create(<Grid columnsProp={["200px", ["100px","1fr"], "auto"]} />).toJSON();
expect(tree1).toHaveStyleRule('grid-template-columns', '200px minmax(100px,1fr) auto');
const tree2 = renderer.create(<Grid columnsProp="25%" />).toJSON();
expect(tree2).toHaveStyleRule('grid-template-columns', 'repeat(auto-fill,25%)');
const tree3 = renderer.create(<Grid columnsProp={{ count: 3, size: "100px" }} />).toJSON();
expect(tree3).toHaveStyleRule('grid-template-columns', 'repeat(3,100px)');
const tree4 = renderer.create(<Grid columnsProp={{ count: 3, size: ["100px", "1fr"] }} />).toJSON();
expect(tree4).toHaveStyleRule('grid-template-columns', 'repeat(3,minmax(100px,1fr))');
const tree5 = renderer.create(<Grid rowsProp={["100px", ["100px","1fr"], "auto"]} />).toJSON();
expect(tree5).toHaveStyleRule('grid-template-rows', '100px minmax(100px,1fr) auto');
const tree6 = renderer.create(<Grid rowsProp="50px" />).toJSON();
expect(tree6).toHaveStyleRule('grid-auto-rows', '50px');
const tree7 = renderer.create(<Grid areasProp={[["header","header"],["navbar","main"]]} />).toJSON();
expect(tree7).toHaveStyleRule('grid-template-areas', '"header header" "navbar main"');
const tree8 = renderer.create(<Grid
rowsProp={["auto", "1fr", "auto"]}
columnsProp={[["100px","1fr"], "3fr", ["100px","1fr"]]}
areasProp={[
{ name: "header", start: [0, 0], end: [2, 0] },
{ name: "navbar", start: [0, 1], end: [0, 1] },
{ name: "main", start: [1, 1], end: [1, 1] },
{ name: "sidebar", start: [2, 1], end: [2, 1] },
{ name: "footer", start: [0, 2], end: [2, 2] }
]} />).toJSON();
expect(tree8).toHaveStyleRule('grid-template-areas', '"header header header" "navbar main sidebar" "footer footer footer"');
expect(tree8).toHaveStyleRule('grid-template-columns', 'minmax(100px,1fr) 3fr minmax(100px,1fr)');
expect(tree8).toHaveStyleRule('grid-template-rows', 'auto 1fr auto');
});
});

View File

@ -1,135 +1,3 @@
import styled, { css } from 'styled-components';
import PropTypes from 'prop-types';
const alignContentStyle = alignContent => `align-content: ${alignContent};`;
const alignItemsStyle = alignItems => `align-items: ${alignItems};`;
const alignSelfStyle = alignSelf => `align-self: ${alignSelf};`;
const areasStyle = props => {
if (
Array.isArray(props.areasProp) &&
props.areasProp.every(area => Array.isArray(area))
) {
return `grid-template-areas: ${props.areasProp
.map(area => `"${area.join(' ')}"`)
.join(' ')};`;
}
const cells = props.rowsProp.map(() => props.columnsProp.map(() => '.'));
props.areasProp.forEach(area => {
for (let row = area.start[1]; row <= area.end[1]; row += 1) {
for (let column = area.start[0]; column <= area.end[0]; column += 1) {
cells[row][column] = area.name;
}
}
});
return `grid-template-areas: ${cells
.map(r => `"${r.join(' ')}"`)
.join(' ')};`;
};
const getRepeatCount = count => typeof count === 'number' ? count : `auto-${count}`;
const getRepeatSize = size => Array.isArray(size) ? `minmax(${size[0]}, ${size[1]})` : `minmax(${size}, 1fr)`;
const columnsStyle = props => {
if (Array.isArray(props.columnsProp)) {
return css`
grid-template-columns: ${props.columnsProp
.map(column => {
return Array.isArray(column) ? `minmax(${column[0]}, ${column[1]})` : column;
})
.join(' ')};
`;
}
if (typeof props.columnsProp === 'object') {
return css`
grid-template-columns: repeat(
${getRepeatCount(props.columnsProp.count)},
${getRepeatSize(props.columnsProp.size)}
);
`;
}
return css`
grid-template-columns: repeat(
auto-fill,
${getRepeatSize(props.columnsProp)}
);
`;
};
const gridAreaStyle = gridArea => `grid-area: ${gridArea};`;
const gridColumnGapStyle = gridColumnGap => `grid-column-gap: ${gridColumnGap};`;
const gridGapStyle = gridGap => `grid-gap: ${gridGap};`;
const gridRowGapStyle = gridRowGap => `grid-row-gap: ${gridRowGap};`;
const heightStyle = heightProp => `height: ${heightProp};`;
const justifyContentStyle = justifyContent => `justify-content: ${justifyContent};`;
const justifyItemsStyle = justifyItems => `justify-items: ${justifyItems};`;
const justifySelfStyle = justifySelf => `justify-self: ${justifySelf};`;
const marginStyle = marginProp => `margin: ${marginProp};`;
const paddingStyle = paddingProp => `padding: ${paddingProp};`;
const rowsStyle = props => {
if (Array.isArray(props.rowsProp)) {
return css`
grid-template-rows: ${props.rowsProp
.map(row => {
return Array.isArray(row) ? `minmax(${row[0]}, ${row[1]})` : row;
})
.join(' ')};
`;
}
return css`
grid-auto-rows: ${props.rowsProp};
`;
};
const widthStyle = widthProp => `width: ${widthProp};`;
const Grid = styled.div`
${props => props.alignContent && alignContentStyle(props.alignContent)}
${props => props.alignItems && alignItemsStyle(props.alignItems)}
${props => props.alignSelf && alignSelfStyle(props.alignSelf)}
${props => props.areasProp && areasStyle(props)}
box-sizing: border-box;
${props => props.columnsProp && columnsStyle(props)}
display: grid;
${props => props.gridArea && gridAreaStyle(props.gridArea)}
${props => props.gridColumnGap && gridColumnGapStyle(props)}
${props => props.gridGap && gridGapStyle(props.gridGap)}
${props => props.gridRowGap && gridRowGapStyle(props)}
${props => props.heightProp && heightStyle(props.heightProp)}
${props => props.justifyContent && justifyContentStyle(props.justifyContent)}
${props => props.justifyItems && justifyItemsStyle(props.justifyItems)}
${props => props.justifySelf && justifySelfStyle(props.justifySelf)}
${props => props.marginProp && marginStyle(props.marginProp)}
${props => props.paddingProp && paddingStyle(props.paddingProp)}
${props => props.rowsProp && rowsStyle(props)}
${props => props.widthProp && widthStyle(props.widthProp)}
`;
Grid.propTypes = {
alignContent: PropTypes.string,
alignItems: PropTypes.string,
alignSelf: PropTypes.string,
areasProp: PropTypes.array,
columnsProp: PropTypes.array,
gridArea: PropTypes.string,
gridColumnGap: PropTypes.string,
gridGap: PropTypes.string,
gridRowGap: PropTypes.string,
heightProp: PropTypes.string,
justifyContent: PropTypes.string,
justifyItems: PropTypes.string,
justifySelf: PropTypes.string,
marginProp: PropTypes.string,
paddingProp: PropTypes.string,
rowsProp: PropTypes.array,
widthProp: PropTypes.string
}
Grid.defaultProps = {
heightProp: '100%',
widthProp: '100%'
};
import Grid from "./grid";
export default Grid;

View File

@ -0,0 +1,96 @@
import styled, { css } from 'styled-components';
const alignContentStyle = alignContent => `align-content: ${alignContent};`;
const alignItemsStyle = alignItems => `align-items: ${alignItems};`;
const alignSelfStyle = alignSelf => `align-self: ${alignSelf};`;
const areasStyle = props => {
if (
Array.isArray(props.areasProp) &&
props.areasProp.every(area => Array.isArray(area))
) {
return `grid-template-areas: ${props.areasProp
.map(area => `"${area.join(' ')}"`)
.join(' ')};`;
}
const cells = props.rowsProp.map(() => props.columnsProp.map(() => '.'));
props.areasProp.forEach(area => {
for (let row = area.start[1]; row <= area.end[1]; row += 1) {
for (let column = area.start[0]; column <= area.end[0]; column += 1) {
cells[row][column] = area.name;
}
}
});
return `grid-template-areas: ${cells
.map(r => `"${r.join(' ')}"`)
.join(' ')};`;
};
const getSizeValue = value => Array.isArray(value) ? `minmax(${value[0]}, ${value[1]})` : value;
const columnsStyle = props => {
if (Array.isArray(props.columnsProp)) {
return css`
grid-template-columns: ${props.columnsProp
.map(getSizeValue)
.join(' ')};
`;
}
if (typeof props.columnsProp === 'object') {
return css`
grid-template-columns: repeat(${props.columnsProp.count}, ${getSizeValue(props.columnsProp.size)});
`;
}
return css`
grid-template-columns: repeat(auto-fill, ${getSizeValue(props.columnsProp)});
`;
};
const gridAreaStyle = gridArea => `grid-area: ${gridArea};`;
const gridColumnGapStyle = gridColumnGap => `grid-column-gap: ${gridColumnGap};`;
const gridGapStyle = gridGap => `grid-gap: ${gridGap};`;
const gridRowGapStyle = gridRowGap => `grid-row-gap: ${gridRowGap};`;
const heightStyle = heightProp => `height: ${heightProp};`;
const justifyContentStyle = justifyContent => `justify-content: ${justifyContent};`;
const justifyItemsStyle = justifyItems => `justify-items: ${justifyItems};`;
const justifySelfStyle = justifySelf => `justify-self: ${justifySelf};`;
const marginStyle = marginProp => `margin: ${marginProp};`;
const paddingStyle = paddingProp => `padding: ${paddingProp};`;
const rowsStyle = props => {
if (Array.isArray(props.rowsProp)) {
return css`
grid-template-rows: ${props.rowsProp
.map(getSizeValue)
.join(' ')};
`;
}
return css`
grid-auto-rows: ${props.rowsProp};
`;
};
const widthStyle = widthProp => `width: ${widthProp};`;
const StyledGrid = styled.div`
${props => props.alignContent && alignContentStyle(props.alignContent)}
${props => props.alignItems && alignItemsStyle(props.alignItems)}
${props => props.alignSelf && alignSelfStyle(props.alignSelf)}
${props => props.areasProp && areasStyle(props)}
${props => props.columnsProp && columnsStyle(props)}
display: grid;
${props => props.gridArea && gridAreaStyle(props.gridArea)}
${props => props.gridColumnGap && gridColumnGapStyle(props)}
${props => props.gridGap && gridGapStyle(props.gridGap)}
${props => props.gridRowGap && gridRowGapStyle(props)}
${props => props.heightProp && heightStyle(props.heightProp)}
${props => props.justifyContent && justifyContentStyle(props.justifyContent)}
${props => props.justifyItems && justifyItemsStyle(props.justifyItems)}
${props => props.justifySelf && justifySelfStyle(props.justifySelf)}
${props => props.marginProp && marginStyle(props.marginProp)}
${props => props.paddingProp && paddingStyle(props.paddingProp)}
${props => props.rowsProp && rowsStyle(props)}
${props => props.widthProp && widthStyle(props.widthProp)}
`;
export default StyledGrid;

View File

@ -5011,6 +5011,16 @@ css-what@2.1, css-what@^2.1.2:
resolved "https://registry.yarnpkg.com/css-what/-/css-what-2.1.3.tgz#a6d7604573365fe74686c3f311c56513d88285f2"
integrity sha512-a+EPoD+uZiNfh+5fxw2nO9QwFa6nJe2Or35fGY6Ipw1R3R4AGz1d1TEZrCegvw2YTmZ0jXirGYlzxxpYSHwpEg==
css@^2.2.4:
version "2.2.4"
resolved "https://registry.yarnpkg.com/css/-/css-2.2.4.tgz#c646755c73971f2bba6a601e2cf2fd71b1298929"
integrity sha512-oUnjmWpy0niI3x/mPL8dVEI1l7MnG3+HHyRPHf+YFSbK+svOhXpmSOcDURUh2aOCgl2grzrOPt1nHLuCVFULLw==
dependencies:
inherits "^2.0.3"
source-map "^0.6.1"
source-map-resolve "^0.5.2"
urix "^0.1.0"
cssesc@^0.1.0:
version "0.1.0"
resolved "https://registry.yarnpkg.com/cssesc/-/cssesc-0.1.0.tgz#c814903e45623371a0477b40109aaafbeeaddbb4"
@ -7959,6 +7969,13 @@ jest-snapshot@^24.9.0:
pretty-format "^24.9.0"
semver "^6.2.0"
jest-styled-components@^6.3.4:
version "6.3.4"
resolved "https://registry.yarnpkg.com/jest-styled-components/-/jest-styled-components-6.3.4.tgz#64de9c0ceae14f311248734c79dcc66b447f90f1"
integrity sha512-dc32l0/6n3FtsILODpvKNz6SLg50OmbJ/3r3oRh9jc2VIPPGZT5jWv7BKIcNCYH7E38ZK7uejNl3zJsCOIenng==
dependencies:
css "^2.2.4"
jest-util@^24.9.0:
version "24.9.0"
resolved "https://registry.yarnpkg.com/jest-util/-/jest-util-24.9.0.tgz#7396814e48536d2e85a37de3e4c431d7cb140162"
@ -11804,7 +11821,7 @@ source-list-map@^2.0.0:
resolved "https://registry.yarnpkg.com/source-list-map/-/source-list-map-2.0.1.tgz#3993bd873bfc48479cca9ea3a547835c7c154b34"
integrity sha512-qnQ7gVMxGNxsiL4lEuJwe/To8UnK7fAnmbGEEH8RpLouuKbeEm0lhbQVFIrNSuB+G7tVrAlVsZgETT5nljf+Iw==
source-map-resolve@^0.5.0:
source-map-resolve@^0.5.0, source-map-resolve@^0.5.2:
version "0.5.2"
resolved "https://registry.yarnpkg.com/source-map-resolve/-/source-map-resolve-0.5.2.tgz#72e2cc34095543e43b2c62b2c4c10d4a9054f259"
integrity sha512-MjqsvNwyz1s0k81Goz/9vRBe9SZdB09Bdw+/zYyO+3CuPk6fouTaxscHkgtE8jKvf01kVfl8riHzERQ/kefaSA==