@baransu/react-styled-flexboxgrid
Version:
Grid system based on styled-components and flexbox for React
112 lines (97 loc) • 2.27 kB
JavaScript
import PropTypes from "prop-types";
import styled from "@emotion/styled";
import { css } from "@emotion/core";
import isInteger from "lodash.isinteger";
import config, { DIMENSION_NAMES } from "../config";
const ModificatorType = PropTypes.oneOfType([PropTypes.number, PropTypes.bool]);
const offsetProps = DIMENSION_NAMES.map(d => d + "Offset");
const DimensionPropTypes = DIMENSION_NAMES.reduce((propTypes, dimension) => {
propTypes[dimension] = ModificatorType;
propTypes[dimension + "Offset"] = PropTypes.number;
return propTypes;
}, {});
const content = (p, k) => {
const grid = `
${(100 / config(p).gridSize) * p[k]}%
`;
return `
${
isInteger(p[k])
? // Integer value
`
flex-basis: ${grid};
max-width: ${grid};
display: block;
`
: // Boolean
p[k]
? // Auto-width
`
flex-grow: 1;
flex-basis: 0;
max-width: 100%;
display: block;
`
: // Hide element
`
display: none;
`
}
`;
};
const col = (p, k) => {
return `
@media ${config(p).media[k]} {
${content(p, k)}
}
`;
};
let column = p =>
css`
${Object.keys(p)
.filter(k => ~DIMENSION_NAMES.indexOf(k))
.sort(
(k1, k2) => DIMENSION_NAMES.indexOf(k1) - DIMENSION_NAMES.indexOf(k2)
)
.map(k => col(p, k))
.join("\n")}
`;
const reverse = p =>
p.reverse
? css`
flex-direction: column-reverse;
`
: css``;
const margin = p =>
css`
${Object.keys(p)
.filter(k => ~offsetProps.indexOf(k))
.map(k => {
return `
@media ${config(p).media[k.replace(/Offset$/, "")]} {
margin-left: ${(100 / config(p).gridSize) * p[k]}%;
}
`;
})
.join("\n")}
`;
const padding = p =>
css`
${config(p).gutterWidth / 2}rem;
`;
const Col = styled.div`
box-sizing: border-box;
flex: 0 0 auto;
padding-right: ${padding}
padding-left: ${padding}
${column}
${reverse}
${margin}
`;
Col.displayName = "Col";
Col.propTypes = {
...DimensionPropTypes,
reverse: PropTypes.bool,
children: PropTypes.node
};
export default Col;