lucid-ui
Version:
A UI component library from Xandr.
103 lines • 4.49 kB
JavaScript
import _, { omit } from 'lodash';
import React from 'react';
import PropTypes from 'prop-types';
import { lucidClassNames } from '../../util/style-helpers';
import { findTypes } from '../../util/component-types';
import Resizer from '../Resizer/Resizer';
const cx = lucidClassNames.bind('&-ResponsiveGrid');
const { string, number, arrayOf } = PropTypes;
/** Cell */
const Cell = (_props) => null;
Cell.displayName = 'ResponsiveGrid.Cell';
Cell.peek = {
description: `Renders a \`<article>\` as the grid cell.`,
};
const defaultProps = {
breakPoints: [960, 1430],
};
export class ResponsiveGrid extends React.Component {
constructor() {
super(...arguments);
this.getColumnLayout = (numberOfColumns) => {
const cellProps = _.map(findTypes(this.props, ResponsiveGridWrapper.Cell), 'props');
const columns = _.reduce(_.map(cellProps, (props, key) => (React.createElement("article", { key: key, className: cx('&-Cell') }, props.children))), (columns, cell, idx) => {
columns[idx % numberOfColumns].push(cell);
return columns;
}, _.times(numberOfColumns, () => []));
return (React.createElement("div", { className: cx('&', {
'&-one-column': numberOfColumns === 1,
}) }, _.map(columns, (col, index) => {
return (React.createElement("div", { key: index, className: cx('&-Column') }, col));
})));
};
}
shouldComponentUpdate(nextProps) {
const { width, breakPoints } = this.props;
const { width: nextWidth } = nextProps;
const [breakOne, breakTwo] = breakPoints;
if (nextWidth < width) {
return ((nextWidth < breakOne && width >= breakOne) ||
(nextWidth < breakTwo && width >= breakTwo));
}
else if (nextWidth > width) {
return ((nextWidth > breakOne && width <= breakOne) ||
(nextWidth > breakTwo && width <= breakTwo));
}
return false;
}
render() {
const { width, breakPoints } = this.props;
const [breakOne, breakTwo] = breakPoints;
if (width < breakTwo) {
if (width < breakOne) {
return this.getColumnLayout(1);
}
return this.getColumnLayout(2);
}
return this.getColumnLayout(3);
}
}
ResponsiveGrid.displayName = 'ResponsiveGrid';
ResponsiveGrid.propTypes = {
/**
Width of the grid. Note: this does not set the width of the grid, and should be
provided by calculating the width of the parent element.
*/
width: number,
/**
Break points for the grid to switch column layouts. Break points should be provided
in ascending order. Currently only two break points are used. Example: [960, 1430]
*/
breakPoints: arrayOf(number),
/**
Appended to the component-specific class names set on the root elements.
*/
className: string,
};
const ResponsiveGridWrapper = (props) => {
const { breakPoints, children, className, ...passThroughs } = props;
return (React.createElement(Resizer, { className: cx('&', className), ...omit(passThroughs, ['breakPoints', 'initialState']) }, (width) => {
return (React.createElement(ResponsiveGrid, { width: width, breakPoints: breakPoints }, children));
}));
};
ResponsiveGridWrapper.Cell = Cell;
ResponsiveGridWrapper.defaultProps = defaultProps;
ResponsiveGridWrapper.displayName = ResponsiveGrid.displayName;
ResponsiveGridWrapper.propTypes = {
/**
Break points for the grid to switch column layouts. Break points should be provided
in ascending order. Currently only two break points are used. Example: [960, 1430]
*/
breakPoints: arrayOf(number),
/**
Appended to the component-specific class names set on the root elements.
*/
className: string,
};
ResponsiveGridWrapper.peek = {
description: `A grid container that changes the number of grid columns in response to width changes. By default, the grid cells are displayed in a single column for widths less than \`960px\`, two columns for widths greater than \`960px\` and less than \`1430px\`, and three columns for widths greater than \`1430px\`. Custom break points can be provided through the \`breakPoints\` prop.`,
categories: ['utility'],
madeFrom: ['Resizer'],
};
export default ResponsiveGridWrapper;
//# sourceMappingURL=ResponsiveGrid.js.map