From 7d063046bb51ccec7c1b140181afdcf49f9460f4 Mon Sep 17 00:00:00 2001 From: Rishi Panthee Date: Fri, 17 Nov 2023 12:52:38 -0600 Subject: [PATCH] add sequential masonry --- .../material/components/masonry/Sequential.js | 36 +++++++++++++++++++ .../components/masonry/Sequential.tsx | 36 +++++++++++++++++++ .../material/components/masonry/masonry.md | 7 ++++ docs/pages/material-ui/api/masonry.json | 1 + .../api-docs/masonry/masonry.json | 3 ++ packages/mui-lab/src/Masonry/Masonry.d.ts | 5 +++ packages/mui-lab/src/Masonry/Masonry.js | 26 +++++++++++--- 7 files changed, 109 insertions(+), 5 deletions(-) create mode 100644 docs/data/material/components/masonry/Sequential.js create mode 100644 docs/data/material/components/masonry/Sequential.tsx diff --git a/docs/data/material/components/masonry/Sequential.js b/docs/data/material/components/masonry/Sequential.js new file mode 100644 index 00000000000000..be3d4731df91b6 --- /dev/null +++ b/docs/data/material/components/masonry/Sequential.js @@ -0,0 +1,36 @@ +import * as React from 'react'; +import Box from '@mui/material/Box'; +import { styled } from '@mui/material/styles'; +import Paper from '@mui/material/Paper'; +import Masonry from '@mui/lab/Masonry'; + +const heights = [150, 30, 90, 70, 110, 150, 130, 80, 50, 90, 100, 150, 30, 50, 80]; + +const Item = styled(Paper)(({ theme }) => ({ + backgroundColor: theme.palette.mode === 'dark' ? '#1A2027' : '#fff', + ...theme.typography.body2, + padding: theme.spacing(0.5), + textAlign: 'center', + color: theme.palette.text.secondary, +})); + +export default function Sequential() { + return ( + + + {heights.map((height, index) => ( + + {index + 1} + + ))} + + + ); +} diff --git a/docs/data/material/components/masonry/Sequential.tsx b/docs/data/material/components/masonry/Sequential.tsx new file mode 100644 index 00000000000000..be3d4731df91b6 --- /dev/null +++ b/docs/data/material/components/masonry/Sequential.tsx @@ -0,0 +1,36 @@ +import * as React from 'react'; +import Box from '@mui/material/Box'; +import { styled } from '@mui/material/styles'; +import Paper from '@mui/material/Paper'; +import Masonry from '@mui/lab/Masonry'; + +const heights = [150, 30, 90, 70, 110, 150, 130, 80, 50, 90, 100, 150, 30, 50, 80]; + +const Item = styled(Paper)(({ theme }) => ({ + backgroundColor: theme.palette.mode === 'dark' ? '#1A2027' : '#fff', + ...theme.typography.body2, + padding: theme.spacing(0.5), + textAlign: 'center', + color: theme.palette.text.secondary, +})); + +export default function Sequential() { + return ( + + + {heights.map((height, index) => ( + + {index + 1} + + ))} + + + ); +} diff --git a/docs/data/material/components/masonry/masonry.md b/docs/data/material/components/masonry/masonry.md index 70d1077aeab4df..333c439874680f 100644 --- a/docs/data/material/components/masonry/masonry.md +++ b/docs/data/material/components/masonry/masonry.md @@ -56,6 +56,13 @@ It is important to note that the value provided to the `spacing` prop is multipl {{"demo": "ResponsiveSpacing.js", "bg": true}} +## Sequential + +This example demonstrates the use of the `sequential` to configure the sequential order. +With `sequential` enabled, items are added in order from left to right rather than adding to the shortest column. + +{{"demo": "Sequential.js", "bg": true}} + ## Server-side rendering This example demonstrates the use of the `defaultHeight`, `defaultColumns` and `defaultSpacing`, which are used to diff --git a/docs/pages/material-ui/api/masonry.json b/docs/pages/material-ui/api/masonry.json index 32d1e38045a963..0ab336ce016293 100644 --- a/docs/pages/material-ui/api/masonry.json +++ b/docs/pages/material-ui/api/masonry.json @@ -13,6 +13,7 @@ "defaultColumns": { "type": { "name": "number" } }, "defaultHeight": { "type": { "name": "number" } }, "defaultSpacing": { "type": { "name": "number" } }, + "sequential": { "type": { "name": "bool" }, "default": "false" }, "spacing": { "type": { "name": "union", diff --git a/docs/translations/api-docs/masonry/masonry.json b/docs/translations/api-docs/masonry/masonry.json index 1792b21244c28b..e4de79a0f03d80 100644 --- a/docs/translations/api-docs/masonry/masonry.json +++ b/docs/translations/api-docs/masonry/masonry.json @@ -16,6 +16,9 @@ "defaultSpacing": { "description": "The default spacing of the component. Like spacing, it is a factor of the theme's spacing. This is provided for server-side rendering." }, + "sequential": { + "description": "Allows using sequential order rather than adding to shortest column" + }, "spacing": { "description": "Defines the space between children. It is a factor of the theme's spacing." }, diff --git a/packages/mui-lab/src/Masonry/Masonry.d.ts b/packages/mui-lab/src/Masonry/Masonry.d.ts index 7f338898e34051..530c4666296ca7 100644 --- a/packages/mui-lab/src/Masonry/Masonry.d.ts +++ b/packages/mui-lab/src/Masonry/Masonry.d.ts @@ -34,6 +34,11 @@ export interface MasonryOwnProps { * @default 1 */ spacing?: ResponsiveStyleValue; + /** + * Allows using sequential order rather than adding to shortest column + * @default false + */ + sequential?: boolean; /** * Allows defining system overrides as well as additional CSS styles. */ diff --git a/packages/mui-lab/src/Masonry/Masonry.js b/packages/mui-lab/src/Masonry/Masonry.js index c48e32772f9170..8beb1397d6f63e 100644 --- a/packages/mui-lab/src/Masonry/Masonry.js +++ b/packages/mui-lab/src/Masonry/Masonry.js @@ -181,6 +181,7 @@ const Masonry = React.forwardRef(function Masonry(inProps, ref) { component = 'div', columns = 4, spacing = 1, + sequential = false, defaultColumns, defaultHeight, defaultSpacing, @@ -235,6 +236,7 @@ const Masonry = React.forwardRef(function Masonry(inProps, ref) { const columnHeights = new Array(currentNumberOfColumns).fill(0); let skip = false; + let nextOrder = 1; masonry.childNodes.forEach((child) => { if (child.nodeType !== Node.ELEMENT_NODE || child.dataset.class === 'line-break' || skip) { return; @@ -259,11 +261,20 @@ const Masonry = React.forwardRef(function Masonry(inProps, ref) { } } if (!skip) { - // find the current shortest column (where the current item will be placed) - const currentMinColumnIndex = columnHeights.indexOf(Math.min(...columnHeights)); - columnHeights[currentMinColumnIndex] += childHeight; - const order = currentMinColumnIndex + 1; - child.style.order = order; + if (sequential) { + columnHeights[nextOrder - 1] += childHeight; + child.style.order = nextOrder; + nextOrder += 1; + if (nextOrder > currentNumberOfColumns) { + nextOrder = 1; + } + } else { + // find the current shortest column (where the current item will be placed) + const currentMinColumnIndex = columnHeights.indexOf(Math.min(...columnHeights)); + columnHeights[currentMinColumnIndex] += childHeight; + const order = currentMinColumnIndex + 1; + child.style.order = order; + } } }); if (!skip) { @@ -374,6 +385,11 @@ Masonry.propTypes /* remove-proptypes */ = { * The default spacing of the component. Like `spacing`, it is a factor of the theme's spacing. This is provided for server-side rendering. */ defaultSpacing: PropTypes.number, + /** + * Allows using sequential order rather than adding to shortest column + * @default false + */ + sequential: PropTypes.bool, /** * Defines the space between children. It is a factor of the theme's spacing. * @default 1