UNPKG

@gatsby-mdx-suite/mdx-layout

Version:
195 lines (181 loc) 5.41 kB
import React, { useMemo, useEffect, useState } from 'react' import propTypes from 'prop-types' import styled from '@emotion/styled' import { css } from '@emotion/react' import tw from 'twin.macro' import { useBreakpoint } from '@gatsby-mdx-suite/helpers/hooks/use-breakpoint' import verticalRhythm from '@gatsby-mdx-suite/helpers/styling/vertical-rhythm' const ColumnsWrapper = styled.div( ({ theme, minColumns, maxColumns, template, templateAt, center }) => { return css` ${tw`w-full grid gap-grid-gap`} ${verticalRhythm} ${template ? css` ${templateAt ? css` @media (min-width: ${theme.screens[templateAt]}) { grid-template-columns: ${template}; } ` : css` grid-template-columns: ${template}; `} ` : css` grid-template-columns: ${theme.gridTemplateColumns[minColumns]}; ${maxColumns === 2 && tw`md:grid-cols-2`} ${maxColumns === 3 && tw`md:grid-cols-3`} ${maxColumns === 4 && tw`md:grid-cols-2 lg:grid-cols-4`} ${maxColumns === 5 && tw`grid-cols-2 md:grid-cols-2 lg:grid-cols-5`} ${maxColumns === 6 && tw`grid-cols-2 md:grid-cols-3 lg:grid-cols-6`} ${maxColumns === 7 && tw`grid-cols-2 md:grid-cols-4 lg:grid-cols-7`} ${maxColumns === 8 && tw`grid-cols-2 md:grid-cols-4 lg:grid-cols-8`} ${maxColumns === 9 && tw`grid-cols-3 md:grid-cols-5 lg:grid-cols-9`} ${maxColumns === 10 && tw`grid-cols-3 md:grid-cols-5 lg:grid-cols-10`} ${maxColumns === 11 && tw`grid-cols-4 md:grid-cols-6 lg:grid-cols-11`} ${maxColumns === 12 && tw`grid-cols-4 md:grid-cols-6 lg:grid-cols-12`}; `} ${center && css` text-align: center; `} ` } ) /** * Display content next to each other. * * **Note:** * * If you need to use multiple elements within a column or want control over colors, * you should use the `<Column/>` element to wrap a single column. * * * @example * <Columns> * <Image id="randomImageId" /> * <Image id="randomImageId" /> * <Image id="randomImageId" /> * <Image id="randomImageId" /> * </Columns> * @example * <Columns maxColumns="2"> * <Image id="randomImageId" /> * <Image id="randomImageId" /> * <Image id="randomImageId" /> * <Image id="randomImageId" /> * </Columns> * * @example * * <Columns center> * <Column center> * * ## Some Content * * Just as a demo * * A very long one * * To get some extra lines * * </Column> * <Column center> * <Image id="randomImageId" /> * </Column> * </Columns> * @example * <Columns> * <Column> * * # Example text * * The quick brown fox jumps over the lazy dog * * </Column> * <Column colorSet="blue"> * * # Example Text * * The quick brown fox jumps over the lazy dog * * </Column> * <Column backgroundImageId="randomPictureId" minAspectRatio="9/16" /> * </Columns> * @example * <Columns template="16fr 9fr"> * <Column colorSet="blue"> * * # Example Text * * The quick brown fox jumps over the lazy dog * * </Column> * <Column backgroundImageId="randomPictureId" minAspectRatio="9/16" /> * </Columns> */ export default function Columns({ children, maxColumns, reverseAt, ...props }) { const originalColumns = useMemo( () => (Array.isArray(children) ? children : [children]), [children] ) const [columns, setColumns] = useState(originalColumns) const breakpoints = useBreakpoint() // Set max columns based on number of columns const realMaxColumns = useMemo(() => { const desiredColumns = parseInt(maxColumns) > 0 ? parseInt(maxColumns) : columns.length if (desiredColumns > 12) { return 12 } return desiredColumns }, [maxColumns, columns.length]) // Reverse columns based on reverseAt useEffect(() => { if (breakpoints[reverseAt]) { setColumns(originalColumns.slice().reverse()) return } setColumns(originalColumns.slice()) }, [breakpoints, reverseAt, originalColumns]) if (!originalColumns.length) { return null } return ( <ColumnsWrapper maxColumns={realMaxColumns} {...props}> {columns} </ColumnsWrapper> ) } Columns.displayName = 'Columns' Columns.defaultProps = { center: false, minColumns: 1, } Columns.propTypes = { children: propTypes.node.isRequired, /** Minimum number of columns for the smallest screen. */ minColumns: propTypes.oneOfType([propTypes.number, propTypes.string]), /** Maximum number of columns for the biggest screen. Defaults to number of items. Maximum is 12. */ maxColumns: propTypes.oneOfType([propTypes.number, propTypes.string]), /** Reverse the order of all columns as soon given screen size is reached */ reverseAt: propTypes.oneOf(['sm', 'md', 'lg', 'xl']), /** Center text content */ center: propTypes.bool, /** * Custom css grid columns template. * * See: https://developer.mozilla.org/en-US/docs/Web/CSS/grid-template-columns */ template: propTypes.string, /** * Apply the template at the given screen size. By default the template is applied to all screen sizes. * * See: https://developer.mozilla.org/en-US/docs/Web/CSS/grid-template-columns */ templateAt: propTypes.string, }