From e53a9543cf28b67be6216e5f0ffd99be553cb258 Mon Sep 17 00:00:00 2001 From: Marija Najdova Date: Thu, 5 Nov 2020 19:18:31 +0100 Subject: [PATCH] [system] Merge breakpoints in correct order (#23380) --- packages/material-ui/src/Box/styleFunction.js | 34 +++++++++++++- .../material-ui/src/Box/styleFunction.test.js | 45 +++++++++++++++++++ 2 files changed, 78 insertions(+), 1 deletion(-) diff --git a/packages/material-ui/src/Box/styleFunction.js b/packages/material-ui/src/Box/styleFunction.js index 344b588ecd2e04..1bf2dca864327d 100644 --- a/packages/material-ui/src/Box/styleFunction.js +++ b/packages/material-ui/src/Box/styleFunction.js @@ -72,6 +72,38 @@ const getThemeValue = (prop, value, theme) => { return { [prop]: value }; }; +function createEmptyBreakpointObject(breakpoints) { + const breakpointsInOrder = breakpoints.keys.reduce((acc, key) => { + const breakpointStyleKey = breakpoints.up(key); + acc[breakpointStyleKey] = {}; + return acc; + }, {}); + return breakpointsInOrder; +} + +function removeUnusedBreakpoints(breakpointKeys, style) { + return breakpointKeys.reduce( + (acc, key) => { + const breakpointOutput = acc[key]; + const isBreakpointUnused = Object.keys(breakpointOutput).length === 0; + if (isBreakpointUnused) { + delete acc[key]; + } + return acc; + }, + { ...style }, + ); +} + +const mergeBreakpointsInOrder = (breakpoints, ...styles) => { + const emptyBreakpoints = createEmptyBreakpointObject(breakpoints); + const mergedOutput = [emptyBreakpoints, ...styles].reduce( + (prev, next) => deepmerge(prev, next), + {}, + ); + return removeUnusedBreakpoints(Object.keys(emptyBreakpoints), mergedOutput); +}; + export const styleFunctionSx = (styles, theme) => { if (!styles) return null; @@ -121,7 +153,7 @@ const styleFunction = (props) => { const sxValue = styleFunctionSx(props.sx, props.theme); - return deepmerge(result, sxValue); + return mergeBreakpointsInOrder(props.theme.breakpoints, result, sxValue); }; styleFunction.filterProps = filterProps; diff --git a/packages/material-ui/src/Box/styleFunction.test.js b/packages/material-ui/src/Box/styleFunction.test.js index 45d281a8fb7cb1..318601cdc9e81d 100644 --- a/packages/material-ui/src/Box/styleFunction.test.js +++ b/packages/material-ui/src/Box/styleFunction.test.js @@ -151,6 +151,28 @@ describe('styleFunction', () => { }, }); }); + + it('writes breakpoints in correct order', () => { + const result = styleFunction({ + theme, + sx: { m: { md: 1, lg: 2 }, p: { xs: 0, sm: 1, md: 2 } }, + }); + + // Test the order + expect(Object.keys(result)).to.deep.equal([ + '@media (min-width:0px)', + '@media (min-width:600px)', + '@media (min-width:960px)', + '@media (min-width:1280px)', + ]); + + expect(result).to.deep.equal({ + '@media (min-width:0px)': { padding: '0px' }, + '@media (min-width:600px)': { padding: '10px' }, + '@media (min-width:960px)': { padding: '20px', margin: '10px' }, + '@media (min-width:1280px)': { margin: '20px' }, + }); + }); }); describe('breakpoints', () => { @@ -213,5 +235,28 @@ describe('styleFunction', () => { '@media (min-width:960px)': { padding: '70px', margin: '30px' }, }); }); + + it('writes breakpoints in correct order', () => { + const result = styleFunction({ + theme, + m: { md: 1, lg: 2 }, + sx: { p: { xs: 0, sm: 1, md: 2 } }, + }); + + // Test the order + expect(Object.keys(result)).to.deep.equal([ + '@media (min-width:0px)', + '@media (min-width:600px)', + '@media (min-width:960px)', + '@media (min-width:1280px)', + ]); + + expect(result).to.deep.equal({ + '@media (min-width:0px)': { padding: '0px' }, + '@media (min-width:600px)': { padding: '10px' }, + '@media (min-width:960px)': { padding: '20px', margin: '10px' }, + '@media (min-width:1280px)': { margin: '20px' }, + }); + }); }); });