/**
* Copyright by AIWSolutions.
*/
import React from 'react';
import PropTypes from 'prop-types';
import _ from 'lodash';
import { computeStyle, MARGIN_PROPS, PADDING_PROPS } from './utils';
/**
* Represent a simple container which is not a Flex container.
* This container has built in shouldComponentUpdate to prevent unwanted updates when there is no changes on
* its property
* There is also basic property filtering for invalid propery when passing property from its parent like this:
* <Box
* {...props}
* />
*
* @property {string} align - Shorthand for css align-self, this allows the default alignment (or the one
* specified by align-items) to be overridden for individual flex items.
* @property {bool} auto - Shorthand for css flex: 1 1 auto
* @property {string | number} basis - Shorthand for css flex-basis, it defines the default size of an element
* before the remaining space is distributed
* @property {number} col - How many x of 1/12 of width of the parent container that this element should take.
* This equals to css width: (col * 100 / 12)%
* @property {number} grow - Shorthand for css flex-grow, it defines what amount of the available
* space inside the flex container the item should take up
* @property {number} order - Controls the order in which this Box appears in the Flex container
* @property {number} shrink - Shorthand for css flex-shrink, it defines the ability for a flex item
* to shrink if necessary.
* @property {object} style - Element style
*/
class Box extends React.Component {
static propTypes = {
order: PropTypes.number,
auto: PropTypes.bool,
grow: PropTypes.number,
shrink: PropTypes.number,
basis: PropTypes.oneOfType([
PropTypes.string,
PropTypes.number,
]),
align: PropTypes.oneOf([
'auto',
'flex-start',
'flex-end',
'center',
'baseline',
'stretch',
]),
col: PropTypes.oneOf([1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12]),
style: PropTypes.object,
className: PropTypes.string,
};
static ownProps = [..._.keys(Box.propTypes), ...MARGIN_PROPS, ...PADDING_PROPS];
shouldComponentUpdate(nextProps) {
return this.props.children !== nextProps.children
|| !_.isEqual(_.pick(this.props, Box.ownProps), _.pick(nextProps, Box.ownProps));
}
render() {
const {
children, order, auto, grow, shrink, basis, align, col, style, ...others
} = this.props;
const boxStyle = {
WebkitOrder: order,
order,
WebkitBoxSizing: 'border-box',
boxSizing: 'border-box',
WebkitFlexGrow: grow,
flexGrow: grow,
WebkitFlexShrink: shrink,
flexShrink: shrink,
WebkitFlexBasis: basis,
flexBasis: basis,
WebkitAlignSelf: align,
alignSelf: align,
};
if (auto) {
boxStyle.WebkitFlex = '1 1 auto';
boxStyle.flex = '1 1 auto';
}
if (col) {
const widthPercentage = col * 100 / 12;
boxStyle.width = `${widthPercentage.toFixed(2)}%`;
}
const computedStyle = computeStyle(others);
return (
<div
style={Object.assign({}, boxStyle, computedStyle.style, style)}
{...computedStyle.others}
>
{children}
</div>
);
}
}
export default Box;