UNPKG

lucid-ui

Version:

A UI component library from Xandr.

103 lines 4.49 kB
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