From 47600206d2ebcaeae70ece85dff31bc631ca211b Mon Sep 17 00:00:00 2001 From: Marija Najdova Date: Tue, 2 Aug 2022 10:11:57 +0200 Subject: [PATCH 01/14] [system] Add Stack component & createStack factory --- .../system/components/stack/BasicStack.js | 23 + .../system/components/stack/BasicStack.tsx | 23 + .../components/stack/BasicStack.tsx.preview | 5 + .../system/components/stack/DirectionStack.js | 23 + .../components/stack/DirectionStack.tsx | 23 + .../stack/DirectionStack.tsx.preview | 5 + .../system/components/stack/DividerStack.js | 28 ++ .../system/components/stack/DividerStack.tsx | 28 ++ .../components/stack/DividerStack.tsx.preview | 9 + .../components/stack/InteractiveStack.js | 198 ++++++++ .../components/stack/InteractiveStack.tsx | 198 ++++++++ .../components/stack/ResponsiveStack.js | 26 + .../components/stack/ResponsiveStack.tsx | 26 + .../stack/ResponsiveStack.tsx.preview | 8 + docs/data/system/components/stack/stack.md | 56 +++ docs/data/system/pages.ts | 1 + docs/data/system/pagesApi.js | 1 + docs/pages/system/api/stack.js | 21 + docs/pages/system/api/stack.json | 32 ++ docs/pages/system/react-stack.js | 11 + docs/translations/api-docs/stack/stack.json | 1 - packages/mui-system/src/Stack/Stack.test.js | 465 ++++++++++++++++++ packages/mui-system/src/Stack/Stack.tsx | 58 +++ packages/mui-system/src/Stack/StackProps.ts | 48 ++ packages/mui-system/src/Stack/createStack.tsx | 226 +++++++++ packages/mui-system/src/Stack/index.ts | 3 + packages/mui-system/src/index.d.ts | 3 + packages/mui-system/src/index.js | 3 + packages/mui-system/src/spacing.d.ts | 7 + 29 files changed, 1558 insertions(+), 1 deletion(-) create mode 100644 docs/data/system/components/stack/BasicStack.js create mode 100644 docs/data/system/components/stack/BasicStack.tsx create mode 100644 docs/data/system/components/stack/BasicStack.tsx.preview create mode 100644 docs/data/system/components/stack/DirectionStack.js create mode 100644 docs/data/system/components/stack/DirectionStack.tsx create mode 100644 docs/data/system/components/stack/DirectionStack.tsx.preview create mode 100644 docs/data/system/components/stack/DividerStack.js create mode 100644 docs/data/system/components/stack/DividerStack.tsx create mode 100644 docs/data/system/components/stack/DividerStack.tsx.preview create mode 100644 docs/data/system/components/stack/InteractiveStack.js create mode 100644 docs/data/system/components/stack/InteractiveStack.tsx create mode 100644 docs/data/system/components/stack/ResponsiveStack.js create mode 100644 docs/data/system/components/stack/ResponsiveStack.tsx create mode 100644 docs/data/system/components/stack/ResponsiveStack.tsx.preview create mode 100644 docs/data/system/components/stack/stack.md create mode 100644 docs/pages/system/api/stack.js create mode 100644 docs/pages/system/api/stack.json create mode 100644 docs/pages/system/react-stack.js create mode 100644 packages/mui-system/src/Stack/Stack.test.js create mode 100644 packages/mui-system/src/Stack/Stack.tsx create mode 100644 packages/mui-system/src/Stack/StackProps.ts create mode 100644 packages/mui-system/src/Stack/createStack.tsx create mode 100644 packages/mui-system/src/Stack/index.ts diff --git a/docs/data/system/components/stack/BasicStack.js b/docs/data/system/components/stack/BasicStack.js new file mode 100644 index 00000000000000..6f5b05d97dc02f --- /dev/null +++ b/docs/data/system/components/stack/BasicStack.js @@ -0,0 +1,23 @@ +import * as React from 'react'; +import Paper from '@mui/material/Paper'; +import { styled, Box, Stack } from '@mui/system'; + +const Item = styled(Paper)(({ theme }) => ({ + backgroundColor: theme.palette.mode === 'dark' ? '#1A2027' : '#fff', + ...theme.typography.body2, + padding: theme.spacing(1), + textAlign: 'center', + color: theme.palette.text.secondary, +})); + +export default function BasicStack() { + return ( + + + Item 1 + Item 2 + Item 3 + + + ); +} diff --git a/docs/data/system/components/stack/BasicStack.tsx b/docs/data/system/components/stack/BasicStack.tsx new file mode 100644 index 00000000000000..6f5b05d97dc02f --- /dev/null +++ b/docs/data/system/components/stack/BasicStack.tsx @@ -0,0 +1,23 @@ +import * as React from 'react'; +import Paper from '@mui/material/Paper'; +import { styled, Box, Stack } from '@mui/system'; + +const Item = styled(Paper)(({ theme }) => ({ + backgroundColor: theme.palette.mode === 'dark' ? '#1A2027' : '#fff', + ...theme.typography.body2, + padding: theme.spacing(1), + textAlign: 'center', + color: theme.palette.text.secondary, +})); + +export default function BasicStack() { + return ( + + + Item 1 + Item 2 + Item 3 + + + ); +} diff --git a/docs/data/system/components/stack/BasicStack.tsx.preview b/docs/data/system/components/stack/BasicStack.tsx.preview new file mode 100644 index 00000000000000..fc62473153d42e --- /dev/null +++ b/docs/data/system/components/stack/BasicStack.tsx.preview @@ -0,0 +1,5 @@ + + Item 1 + Item 2 + Item 3 + \ No newline at end of file diff --git a/docs/data/system/components/stack/DirectionStack.js b/docs/data/system/components/stack/DirectionStack.js new file mode 100644 index 00000000000000..1eb6e9fcc84008 --- /dev/null +++ b/docs/data/system/components/stack/DirectionStack.js @@ -0,0 +1,23 @@ +import * as React from 'react'; +import Paper from '@mui/material/Paper'; +import { styled, Stack } from '@mui/system'; + +const Item = styled(Paper)(({ theme }) => ({ + backgroundColor: theme.palette.mode === 'dark' ? '#1A2027' : '#fff', + ...theme.typography.body2, + padding: theme.spacing(1), + textAlign: 'center', + color: theme.palette.text.secondary, +})); + +export default function DirectionStack() { + return ( +
+ + Item 1 + Item 2 + Item 3 + +
+ ); +} diff --git a/docs/data/system/components/stack/DirectionStack.tsx b/docs/data/system/components/stack/DirectionStack.tsx new file mode 100644 index 00000000000000..1eb6e9fcc84008 --- /dev/null +++ b/docs/data/system/components/stack/DirectionStack.tsx @@ -0,0 +1,23 @@ +import * as React from 'react'; +import Paper from '@mui/material/Paper'; +import { styled, Stack } from '@mui/system'; + +const Item = styled(Paper)(({ theme }) => ({ + backgroundColor: theme.palette.mode === 'dark' ? '#1A2027' : '#fff', + ...theme.typography.body2, + padding: theme.spacing(1), + textAlign: 'center', + color: theme.palette.text.secondary, +})); + +export default function DirectionStack() { + return ( +
+ + Item 1 + Item 2 + Item 3 + +
+ ); +} diff --git a/docs/data/system/components/stack/DirectionStack.tsx.preview b/docs/data/system/components/stack/DirectionStack.tsx.preview new file mode 100644 index 00000000000000..0b432fbd09105e --- /dev/null +++ b/docs/data/system/components/stack/DirectionStack.tsx.preview @@ -0,0 +1,5 @@ + + Item 1 + Item 2 + Item 3 + \ No newline at end of file diff --git a/docs/data/system/components/stack/DividerStack.js b/docs/data/system/components/stack/DividerStack.js new file mode 100644 index 00000000000000..19d9aa7cc5b1c6 --- /dev/null +++ b/docs/data/system/components/stack/DividerStack.js @@ -0,0 +1,28 @@ +import * as React from 'react'; +import Paper from '@mui/material/Paper'; +import Divider from '@mui/material/Divider'; +import { styled, Stack } from '@mui/system'; + +const Item = styled(Paper)(({ theme }) => ({ + backgroundColor: theme.palette.mode === 'dark' ? '#1A2027' : '#fff', + ...theme.typography.body2, + padding: theme.spacing(1), + textAlign: 'center', + color: theme.palette.text.secondary, +})); + +export default function DividerStack() { + return ( +
+ } + spacing={2} + > + Item 1 + Item 2 + Item 3 + +
+ ); +} diff --git a/docs/data/system/components/stack/DividerStack.tsx b/docs/data/system/components/stack/DividerStack.tsx new file mode 100644 index 00000000000000..19d9aa7cc5b1c6 --- /dev/null +++ b/docs/data/system/components/stack/DividerStack.tsx @@ -0,0 +1,28 @@ +import * as React from 'react'; +import Paper from '@mui/material/Paper'; +import Divider from '@mui/material/Divider'; +import { styled, Stack } from '@mui/system'; + +const Item = styled(Paper)(({ theme }) => ({ + backgroundColor: theme.palette.mode === 'dark' ? '#1A2027' : '#fff', + ...theme.typography.body2, + padding: theme.spacing(1), + textAlign: 'center', + color: theme.palette.text.secondary, +})); + +export default function DividerStack() { + return ( +
+ } + spacing={2} + > + Item 1 + Item 2 + Item 3 + +
+ ); +} diff --git a/docs/data/system/components/stack/DividerStack.tsx.preview b/docs/data/system/components/stack/DividerStack.tsx.preview new file mode 100644 index 00000000000000..6dff777f9c51cf --- /dev/null +++ b/docs/data/system/components/stack/DividerStack.tsx.preview @@ -0,0 +1,9 @@ +} + spacing={2} +> + Item 1 + Item 2 + Item 3 + \ No newline at end of file diff --git a/docs/data/system/components/stack/InteractiveStack.js b/docs/data/system/components/stack/InteractiveStack.js new file mode 100644 index 00000000000000..0e68b8a0eec201 --- /dev/null +++ b/docs/data/system/components/stack/InteractiveStack.js @@ -0,0 +1,198 @@ +import * as React from 'react'; +import FormControl from '@mui/material/FormControl'; +import FormLabel from '@mui/material/FormLabel'; +import FormControlLabel from '@mui/material/FormControlLabel'; +import HighlightedCode from 'docs/src/modules/components/HighlightedCode'; +import Paper from '@mui/material/Paper'; +import RadioGroup from '@mui/material/RadioGroup'; +import Radio from '@mui/material/Radio'; +import { Stack, Unstable_Grid as Grid } from '@mui/system'; + +export default function InteractiveStack() { + const [direction, setDirection] = React.useState('row'); + const [justifyContent, setJustifyContent] = React.useState('center'); + const [alignItems, setAlignItems] = React.useState('center'); + const [spacing, setSpacing] = React.useState(2); + + const jsx = ` + +`; + + return ( + + + {[0, 1, 2].map((value) => ( + + theme.palette.mode === 'dark' ? '#1A2027' : '#fff', + }} + > + {`Item ${value + 1}`} + + ))} + + + + + + direction + { + setDirection(event.target.value); + }} + > + } label="row" /> + } + label="row-reverse" + /> + } + label="column" + /> + } + label="column-reverse" + /> + + + + + + alignItems + { + setAlignItems(event.target.value); + }} + > + } + label="flex-start" + /> + } + label="center" + /> + } + label="flex-end" + /> + } + label="stretch" + /> + } + label="baseline" + /> + + + + + + justifyContent + { + setJustifyContent(event.target.value); + }} + > + } + label="flex-start" + /> + } + label="center" + /> + } + label="flex-end" + /> + } + label="space-between" + /> + } + label="space-around" + /> + } + label="space-evenly" + /> + + + + + + spacing + { + setSpacing(Number(event.target.value)); + }} + > + {[0, 0.5, 1, 2, 3, 4, 8, 12].map((value) => ( + } + label={value} + /> + ))} + + + + + + + + ); +} diff --git a/docs/data/system/components/stack/InteractiveStack.tsx b/docs/data/system/components/stack/InteractiveStack.tsx new file mode 100644 index 00000000000000..18ad86a76fa03c --- /dev/null +++ b/docs/data/system/components/stack/InteractiveStack.tsx @@ -0,0 +1,198 @@ +import * as React from 'react'; +import FormControl from '@mui/material/FormControl'; +import FormLabel from '@mui/material/FormLabel'; +import FormControlLabel from '@mui/material/FormControlLabel'; +import HighlightedCode from 'docs/src/modules/components/HighlightedCode'; +import Paper from '@mui/material/Paper'; +import RadioGroup from '@mui/material/RadioGroup'; +import Radio from '@mui/material/Radio'; +import { Stack, Unstable_Grid as Grid, StackProps } from '@mui/system'; + +export default function InteractiveStack() { + const [direction, setDirection] = React.useState('row'); + const [justifyContent, setJustifyContent] = React.useState('center'); + const [alignItems, setAlignItems] = React.useState('center'); + const [spacing, setSpacing] = React.useState(2); + + const jsx = ` + +`; + + return ( + + + {[0, 1, 2].map((value) => ( + + theme.palette.mode === 'dark' ? '#1A2027' : '#fff', + }} + > + {`Item ${value + 1}`} + + ))} + + + + + + direction + { + setDirection(event.target.value as StackProps['direction']); + }} + > + } label="row" /> + } + label="row-reverse" + /> + } + label="column" + /> + } + label="column-reverse" + /> + + + + + + alignItems + { + setAlignItems(event.target.value); + }} + > + } + label="flex-start" + /> + } + label="center" + /> + } + label="flex-end" + /> + } + label="stretch" + /> + } + label="baseline" + /> + + + + + + justifyContent + { + setJustifyContent(event.target.value); + }} + > + } + label="flex-start" + /> + } + label="center" + /> + } + label="flex-end" + /> + } + label="space-between" + /> + } + label="space-around" + /> + } + label="space-evenly" + /> + + + + + + spacing + ) => { + setSpacing(Number((event.target as HTMLInputElement).value)); + }} + > + {[0, 0.5, 1, 2, 3, 4, 8, 12].map((value) => ( + } + label={value} + /> + ))} + + + + + + + + ); +} diff --git a/docs/data/system/components/stack/ResponsiveStack.js b/docs/data/system/components/stack/ResponsiveStack.js new file mode 100644 index 00000000000000..0a29179625219c --- /dev/null +++ b/docs/data/system/components/stack/ResponsiveStack.js @@ -0,0 +1,26 @@ +import * as React from 'react'; +import Paper from '@mui/material/Paper'; +import { styled, Stack } from '@mui/system'; + +const Item = styled(Paper)(({ theme }) => ({ + backgroundColor: theme.palette.mode === 'dark' ? '#1A2027' : '#fff', + ...theme.typography.body2, + padding: theme.spacing(1), + textAlign: 'center', + color: theme.palette.text.secondary, +})); + +export default function ResponsiveStack() { + return ( +
+ + Item 1 + Item 2 + Item 3 + +
+ ); +} diff --git a/docs/data/system/components/stack/ResponsiveStack.tsx b/docs/data/system/components/stack/ResponsiveStack.tsx new file mode 100644 index 00000000000000..0a29179625219c --- /dev/null +++ b/docs/data/system/components/stack/ResponsiveStack.tsx @@ -0,0 +1,26 @@ +import * as React from 'react'; +import Paper from '@mui/material/Paper'; +import { styled, Stack } from '@mui/system'; + +const Item = styled(Paper)(({ theme }) => ({ + backgroundColor: theme.palette.mode === 'dark' ? '#1A2027' : '#fff', + ...theme.typography.body2, + padding: theme.spacing(1), + textAlign: 'center', + color: theme.palette.text.secondary, +})); + +export default function ResponsiveStack() { + return ( +
+ + Item 1 + Item 2 + Item 3 + +
+ ); +} diff --git a/docs/data/system/components/stack/ResponsiveStack.tsx.preview b/docs/data/system/components/stack/ResponsiveStack.tsx.preview new file mode 100644 index 00000000000000..86c8eaeab63109 --- /dev/null +++ b/docs/data/system/components/stack/ResponsiveStack.tsx.preview @@ -0,0 +1,8 @@ + + Item 1 + Item 2 + Item 3 + \ No newline at end of file diff --git a/docs/data/system/components/stack/stack.md b/docs/data/system/components/stack/stack.md new file mode 100644 index 00000000000000..16c6274672c64f --- /dev/null +++ b/docs/data/system/components/stack/stack.md @@ -0,0 +1,56 @@ +--- +product: system +title: React Stack component +githubLabel: 'component: Stack' +packageName: '@mui/system' +--- + +# Stack + +

The Stack component manages layout of immediate children along the vertical or horizontal axis with optional spacing and/or dividers between each child.

+ +{{"component": "modules/components/ComponentLinkHeader.js", "design": false}} + +## Usage + +`Stack` is concerned with one-dimensional layouts, while [Grid](/system/react-grid/) handles two-dimensional layouts. The default direction is `column` which stacks children vertically. + +{{"demo": "BasicStack.js", "bg": true}} + +To control space between children, use the `spacing` prop. +The spacing value can be any number, including decimals and any string. +The prop is converted into a CSS property using the [`theme.spacing()`](/material-ui/customization/spacing/) helper. + +## Direction + +By default, `Stack` arranges items vertically in a `column`. +However, the `direction` prop can be used to position items horizontally in a `row` as well. + +{{"demo": "DirectionStack.js", "bg": true}} + +## Dividers + +Use the `divider` prop to insert an element between each child. This works particularly well with the [Divider](/material-ui/react-divider/) component. + +{{"demo": "DividerStack.js", "bg": true}} + +## Responsive values + +You can switch the `direction` or `spacing` values based on the active breakpoint. + +{{"demo": "ResponsiveStack.js", "bg": true}} + +## Interactive + +Below is an interactive demo that lets you explore the visual results of the different settings: + +{{"demo": "InteractiveStack.js", "hideToolbar": true, "bg": true}} + +## System props + +As a CSS utility component, the `Stack` supports all [`system`](/system/properties/) properties. You can use them as props directly on the component. +For instance, a margin-top: + +```jsx + +``` diff --git a/docs/data/system/pages.ts b/docs/data/system/pages.ts index d27eeca2b458ba..2f35f641cf4029 100644 --- a/docs/data/system/pages.ts +++ b/docs/data/system/pages.ts @@ -49,6 +49,7 @@ const pages = [ { pathname: '/system/react-box', title: 'Box' }, { pathname: '/system/react-container', title: 'Container' }, { pathname: '/system/react-grid', title: 'Grid' }, + { pathname: '/system/react-stack', title: 'Stack' }, ], }, { diff --git a/docs/data/system/pagesApi.js b/docs/data/system/pagesApi.js index d77093b35304aa..4e14cb03250c5d 100644 --- a/docs/data/system/pagesApi.js +++ b/docs/data/system/pagesApi.js @@ -2,4 +2,5 @@ module.exports = [ { pathname: '/system/api/box' }, { pathname: '/system/api/container' }, { pathname: '/system/api/grid' }, + { pathname: '/system/api/stack' }, ]; diff --git a/docs/pages/system/api/stack.js b/docs/pages/system/api/stack.js new file mode 100644 index 00000000000000..2f490a542f2b54 --- /dev/null +++ b/docs/pages/system/api/stack.js @@ -0,0 +1,21 @@ +import * as React from 'react'; +import ApiPage from 'docs/src/modules/components/ApiPage'; +import mapApiPageTranslations from 'docs/src/modules/utils/mapApiPageTranslations'; +import jsonPageContent from './stack.json'; + +export default function Page(props) { + const { descriptions, pageContent } = props; + return ; +} + +export function getStaticProps() { + const req = require.context('docs/translations/api-docs/stack', false, /stack.*.json$/); + const descriptions = mapApiPageTranslations(req); + + return { + props: { + descriptions, + pageContent: jsonPageContent, + }, + }; +} diff --git a/docs/pages/system/api/stack.json b/docs/pages/system/api/stack.json new file mode 100644 index 00000000000000..ec49d24e02040e --- /dev/null +++ b/docs/pages/system/api/stack.json @@ -0,0 +1,32 @@ +{ + "props": { + "children": { "type": { "name": "node" } }, + "direction": { + "type": { + "name": "union", + "description": "'column-reverse'
| 'column'
| 'row-reverse'
| 'row'
| Array<'column-reverse'
| 'column'
| 'row-reverse'
| 'row'>
| object" + } + }, + "divider": { "type": { "name": "node" } }, + "spacing": { + "type": { + "name": "union", + "description": "Array<number
| string>
| number
| object
| string" + } + }, + "sx": { + "type": { + "name": "union", + "description": "Array<func
| object
| bool>
| func
| object" + } + } + }, + "name": "Stack", + "styles": { "classes": [], "globalClasses": {}, "name": null }, + "spread": true, + "forwardsRefTo": "HTMLDivElement", + "filename": "/packages/mui-system/src/Stack/Stack.tsx", + "inheritance": null, + "demos": "", + "cssComponent": true +} diff --git a/docs/pages/system/react-stack.js b/docs/pages/system/react-stack.js new file mode 100644 index 00000000000000..412fb69a858c01 --- /dev/null +++ b/docs/pages/system/react-stack.js @@ -0,0 +1,11 @@ +import * as React from 'react'; +import MarkdownDocs from 'docs/src/modules/components/MarkdownDocs'; +import { + demos, + docs, + demoComponents, +} from 'docs/data/system/components/stack/stack.md?@mui/markdown'; + +export default function Page() { + return ; +} diff --git a/docs/translations/api-docs/stack/stack.json b/docs/translations/api-docs/stack/stack.json index 8fa2e742c67f59..528b1904adcce1 100644 --- a/docs/translations/api-docs/stack/stack.json +++ b/docs/translations/api-docs/stack/stack.json @@ -2,7 +2,6 @@ "componentDescription": "", "propDescriptions": { "children": "The content of the component.", - "component": "The component used for the root node. Either a string to use a HTML element or a component.", "direction": "Defines the flex-direction style property. It is applied for all screen sizes.", "divider": "Add an element between each child.", "spacing": "Defines the space between immediate children.", diff --git a/packages/mui-system/src/Stack/Stack.test.js b/packages/mui-system/src/Stack/Stack.test.js new file mode 100644 index 00000000000000..4e20eede395f4a --- /dev/null +++ b/packages/mui-system/src/Stack/Stack.test.js @@ -0,0 +1,465 @@ +import * as React from 'react'; +import { expect } from 'chai'; +import { createRenderer, describeConformance } from 'test/utils'; +import Stack from '@mui/system/Stack'; +import { createTheme } from '@mui/system'; +import { style } from './createStack'; + +describe('', () => { + const { render } = createRenderer(); + + describeConformance(, () => ({ + render, + inheritComponent: 'div', + refInstanceof: window.HTMLDivElement, + muiName: 'MuiStack', + skip: ['componentProp', 'componentsProp', 'rootClass', 'themeVariants', 'themeStyleOverrides'], + })); + + const theme = createTheme(); + + it('should handle breakpoints with a missing key', () => { + expect( + style({ + ownerState: { + direction: { xs: 'column', sm: 'row' }, + spacing: { xs: 1, sm: 2, md: 4 }, + }, + theme, + }), + ).to.deep.equal({ + '@media (min-width:0px)': { + '& > :not(style) + :not(style)': { + margin: 0, + marginTop: '8px', + }, + flexDirection: 'column', + }, + [`@media (min-width:${theme.breakpoints.values.sm}px)`]: { + '& > :not(style) + :not(style)': { + margin: 0, + marginLeft: '16px', + }, + flexDirection: 'row', + }, + [`@media (min-width:${theme.breakpoints.values.md}px)`]: { + '& > :not(style) + :not(style)': { + margin: 0, + marginLeft: '32px', + }, + }, + display: 'flex', + flexDirection: 'column', + }); + }); + + it('should handle direction with multiple keys and spacing with one', () => { + expect( + style({ + ownerState: { + direction: { sm: 'column', md: 'row' }, + spacing: 2, + }, + theme, + }), + ).to.deep.equal({ + [`@media (min-width:${theme.breakpoints.values.sm}px)`]: { + '& > :not(style) + :not(style)': { + margin: 0, + marginTop: '16px', + }, + flexDirection: 'column', + }, + [`@media (min-width:${theme.breakpoints.values.md}px)`]: { + '& > :not(style) + :not(style)': { + margin: 0, + marginLeft: '16px', + }, + flexDirection: 'row', + }, + display: 'flex', + flexDirection: 'column', + }); + }); + + it('should handle spacing with multiple keys and direction with one', () => { + expect( + style({ + ownerState: { + direction: 'column', + spacing: { sm: 2, md: 4 }, + }, + theme, + }), + ).to.deep.equal({ + [`@media (min-width:${theme.breakpoints.values.sm}px)`]: { + '& > :not(style) + :not(style)': { + margin: 0, + marginTop: '16px', + }, + }, + [`@media (min-width:${theme.breakpoints.values.md}px)`]: { + '& > :not(style) + :not(style)': { + margin: 0, + marginTop: '32px', + }, + }, + display: 'flex', + flexDirection: 'column', + }); + }); + + it('should handle spacing with multiple keys and null values', () => { + expect( + style({ + ownerState: { + direction: 'column', + spacing: { sm: 2, md: 0, lg: 4 }, + }, + theme, + }), + ).to.deep.equal({ + [`@media (min-width:${theme.breakpoints.values.sm}px)`]: { + '& > :not(style) + :not(style)': { + margin: 0, + marginTop: '16px', + }, + }, + [`@media (min-width:${theme.breakpoints.values.md}px)`]: { + '& > :not(style) + :not(style)': { + margin: 0, + marginTop: '0px', + }, + }, + [`@media (min-width:${theme.breakpoints.values.lg}px)`]: { + '& > :not(style) + :not(style)': { + margin: 0, + marginTop: '32px', + }, + }, + display: 'flex', + flexDirection: 'column', + }); + }); + + it('should handle flat params', () => { + expect( + style({ + ownerState: { + direction: 'row', + spacing: 3, + }, + theme, + }), + ).to.deep.equal({ + '& > :not(style) + :not(style)': { + margin: 0, + marginLeft: '24px', + }, + display: 'flex', + flexDirection: 'row', + }); + }); + + it('should respect the theme breakpoints order', () => { + expect( + style({ + ownerState: { + direction: { xs: 'column' }, + spacing: { lg: 2, xs: 1 }, + }, + theme, + }), + ).to.deep.equal({ + '@media (min-width:0px)': { + '& > :not(style) + :not(style)': { + margin: 0, + marginTop: '8px', + }, + flexDirection: 'column', + }, + [`@media (min-width:${theme.breakpoints.values.lg}px)`]: { + '& > :not(style) + :not(style)': { + margin: 0, + marginTop: '16px', + }, + }, + display: 'flex', + flexDirection: 'column', + }); + }); + + describe('prop: direction', () => { + it('should generate correct direction given string values', () => { + expect( + style({ + ownerState: { + direction: 'column-reverse', + spacing: 1, + }, + theme, + }), + ).to.deep.equal({ + '& > :not(style) + :not(style)': { + margin: 0, + marginBottom: '8px', + }, + display: 'flex', + flexDirection: 'column-reverse', + }); + }); + + it('should generate correct responsive styles regardless of breakpoints order', () => { + expect( + style({ + ownerState: { + direction: { sm: 'row', xs: 'column' }, + spacing: { xs: 1, sm: 2, md: 3 }, + }, + theme, + }), + ).to.deep.equal({ + '@media (min-width:0px)': { + '& > :not(style) + :not(style)': { + margin: 0, + marginTop: '8px', + }, + flexDirection: 'column', + }, + [`@media (min-width:${theme.breakpoints.values.sm}px)`]: { + '& > :not(style) + :not(style)': { + margin: 0, + marginLeft: '16px', + }, + flexDirection: 'row', + }, + [`@media (min-width:${theme.breakpoints.values.md}px)`]: { + '& > :not(style) + :not(style)': { + margin: 0, + marginLeft: '24px', + }, + }, + display: 'flex', + flexDirection: 'column', + }); + }); + + it('should generate correct direction even though breakpoints are not fully provided', () => { + expect( + style({ + ownerState: { + direction: { lg: 'row' }, + }, + theme, + }), + ).to.deep.equal({ + [`@media (min-width:${theme.breakpoints.values.lg}px)`]: { + flexDirection: 'row', + }, + display: 'flex', + flexDirection: 'column', + }); + }); + + it('should place correct margin direction even though breakpoints are not fully provided', () => { + expect( + style({ + ownerState: { + direction: { lg: 'row' }, + spacing: { xs: 0, md: 2, xl: 4 }, + }, + theme, + }), + ).to.deep.equal({ + [`@media (min-width:${theme.breakpoints.values.xs}px)`]: { + '& > :not(style) + :not(style)': { + margin: 0, + marginTop: '0px', + }, + }, + [`@media (min-width:${theme.breakpoints.values.md}px)`]: { + '& > :not(style) + :not(style)': { + margin: 0, + marginTop: '16px', + }, + }, + [`@media (min-width:${theme.breakpoints.values.lg}px)`]: { + '& > :not(style) + :not(style)': { + margin: 0, + marginLeft: '16px', + }, + flexDirection: 'row', + }, + [`@media (min-width:${theme.breakpoints.values.xl}px)`]: { + '& > :not(style) + :not(style)': { + margin: 0, + marginLeft: '32px', + }, + }, + display: 'flex', + flexDirection: 'column', + }); + + expect( + style({ + ownerState: { + direction: { lg: 'column', sm: 'row' }, + spacing: { md: 2, xl: 4, xs: 0 }, + }, + theme, + }), + ).to.deep.equal({ + [`@media (min-width:${theme.breakpoints.values.xs}px)`]: { + '& > :not(style) + :not(style)': { + margin: 0, + marginTop: '0px', + }, + }, + [`@media (min-width:${theme.breakpoints.values.sm}px)`]: { + '& > :not(style) + :not(style)': { + margin: 0, + marginLeft: '0px', + }, + flexDirection: 'row', + }, + [`@media (min-width:${theme.breakpoints.values.md}px)`]: { + '& > :not(style) + :not(style)': { + margin: 0, + marginLeft: '16px', + }, + }, + [`@media (min-width:${theme.breakpoints.values.lg}px)`]: { + '& > :not(style) + :not(style)': { + margin: 0, + marginTop: '16px', + }, + flexDirection: 'column', + }, + [`@media (min-width:${theme.breakpoints.values.xl}px)`]: { + '& > :not(style) + :not(style)': { + margin: 0, + marginTop: '32px', + }, + }, + display: 'flex', + flexDirection: 'column', + }); + }); + }); + + describe('prop: spacing', () => { + it('should generate correct responsive styles regardless of breakpoints order', () => { + expect( + style({ + ownerState: { + direction: 'column', + spacing: { sm: 2, md: 3, xs: 1 }, + }, + theme, + }), + ).to.deep.equal({ + '@media (min-width:0px)': { + '& > :not(style) + :not(style)': { + margin: 0, + marginTop: '8px', + }, + }, + [`@media (min-width:${theme.breakpoints.values.sm}px)`]: { + '& > :not(style) + :not(style)': { + margin: 0, + marginTop: '16px', + }, + }, + [`@media (min-width:${theme.breakpoints.values.md}px)`]: { + '& > :not(style) + :not(style)': { + margin: 0, + marginTop: '24px', + }, + }, + display: 'flex', + flexDirection: 'column', + }); + }); + + it('should generate correct styles if custom breakpoints are provided in theme', () => { + const customTheme = createTheme({ + breakpoints: { + values: { + smallest: 0, + small: 375, + mobile: 600, + tablet: 992, + desktop: 1200, + }, + }, + }); + + expect( + style({ + ownerState: { + direction: 'column', + spacing: 4, + }, + theme: customTheme, + }), + ).to.deep.equal({ + '& > :not(style) + :not(style)': { + margin: 0, + marginTop: '32px', + }, + display: 'flex', + flexDirection: 'column', + }); + }); + + it('should generate correct responsive styles if custom responsive spacing values are provided', () => { + const customTheme = createTheme({ + breakpoints: { + values: { + smallest: 0, + small: 375, + mobile: 600, + tablet: 992, + desktop: 1200, + }, + }, + }); + + expect( + style({ + ownerState: { + direction: 'column', + spacing: { small: 4 }, + }, + theme: customTheme, + }), + ).to.deep.equal({ + [`@media (min-width:${customTheme.breakpoints.values.small}px)`]: { + '& > :not(style) + :not(style)': { + margin: 0, + marginTop: '32px', + }, + }, + display: 'flex', + flexDirection: 'column', + }); + }); + + it('should list responsive styles in correct order', () => { + const styles = style({ + ownerState: { + direction: { xs: 'column', lg: 'row' }, + spacing: { xs: 0, md: 2, xl: 4 }, + }, + theme, + }); + const keysForResponsiveStyles = Object.keys(styles).filter((prop) => prop.includes('@media')); + expect(keysForResponsiveStyles).to.deep.equal([ + '@media (min-width:0px)', + '@media (min-width:900px)', + '@media (min-width:1200px)', + '@media (min-width:1536px)', + ]); + }); + }); +}); diff --git a/packages/mui-system/src/Stack/Stack.tsx b/packages/mui-system/src/Stack/Stack.tsx new file mode 100644 index 00000000000000..e6fe81d3ed5d7e --- /dev/null +++ b/packages/mui-system/src/Stack/Stack.tsx @@ -0,0 +1,58 @@ +import PropTypes from 'prop-types'; +import createStack from './createStack'; +/** + * + * Demos: + * + * - [Stack (Material UI)](https://mui.com/material-ui/react-stack/) + * + * API: + * + * - [Stack API](https://mui.com/system/api/stack/) + */ +const Stack = createStack(); + +Stack.propTypes /* remove-proptypes */ = { + // ----------------------------- Warning -------------------------------- + // | These PropTypes are generated from the TypeScript type definitions | + // | To update them edit TypeScript types and run "yarn proptypes" | + // ---------------------------------------------------------------------- + /** + * The content of the component. + */ + children: PropTypes.node, + /** + * Defines the `flex-direction` style property. + * It is applied for all screen sizes. + * @default 'column' + */ + direction: PropTypes.oneOfType([ + PropTypes.oneOf(['column-reverse', 'column', 'row-reverse', 'row']), + PropTypes.arrayOf(PropTypes.oneOf(['column-reverse', 'column', 'row-reverse', 'row'])), + PropTypes.object, + ]), + /** + * Add an element between each child. + */ + divider: PropTypes.node, + /** + * Defines the space between immediate children. + * @default 0 + */ + spacing: PropTypes.oneOfType([ + PropTypes.arrayOf(PropTypes.oneOfType([PropTypes.number, PropTypes.string])), + PropTypes.number, + PropTypes.object, + PropTypes.string, + ]), + /** + * The system prop, which allows defining system overrides as well as additional CSS styles. + */ + sx: PropTypes.oneOfType([ + PropTypes.arrayOf(PropTypes.oneOfType([PropTypes.func, PropTypes.object, PropTypes.bool])), + PropTypes.func, + PropTypes.object, + ]), +} as any; + +export default Stack; diff --git a/packages/mui-system/src/Stack/StackProps.ts b/packages/mui-system/src/Stack/StackProps.ts new file mode 100644 index 00000000000000..3b69f8994019da --- /dev/null +++ b/packages/mui-system/src/Stack/StackProps.ts @@ -0,0 +1,48 @@ +import * as React from 'react'; +import { OverrideProps } from '@mui/types'; +import { ResponsiveStyleValue, SxProps } from '../styleFunctionSx'; +import { SystemProps } from '../Box'; +import { Theme } from '../createTheme'; + +export interface StackTypeMap

{ + props: P & + SystemProps & { + ref?: React.Ref; + /** + * The content of the component. + */ + children?: React.ReactNode; + /** + * Defines the `flex-direction` style property. + * It is applied for all screen sizes. + * @default 'column' + */ + direction?: ResponsiveStyleValue<'row' | 'row-reverse' | 'column' | 'column-reverse'>; + /** + * Defines the space between immediate children. + * @default 0 + */ + spacing?: ResponsiveStyleValue; + /** + * Add an element between each child. + */ + divider?: React.ReactNode; + /** + * The system prop, which allows defining system overrides as well as additional CSS styles. + */ + sx?: SxProps; + }; + defaultComponent: D; +} + +export type StackProps< + D extends React.ElementType = StackTypeMap['defaultComponent'], + P = { + component?: React.ElementType; + }, +> = OverrideProps, D>; + +export interface StackOwnerState { + direction: StackProps['direction']; + spacing: StackProps['spacing']; +} diff --git a/packages/mui-system/src/Stack/createStack.tsx b/packages/mui-system/src/Stack/createStack.tsx new file mode 100644 index 00000000000000..f8b732050f00a5 --- /dev/null +++ b/packages/mui-system/src/Stack/createStack.tsx @@ -0,0 +1,226 @@ +import * as React from 'react'; +import PropTypes from 'prop-types'; +import { OverridableComponent } from '@mui/types'; +import { + deepmerge, + unstable_composeClasses as composeClasses, + unstable_generateUtilityClass as generateUtilityClass, +} from '@mui/utils'; +import systemStyled from '../styled'; +import useThemePropsSystem from '../useThemeProps'; +import { extendSxProp } from '../styleFunctionSx'; +import createTheme from '../createTheme'; +import { CreateMUIStyled } from '../createStyled'; +import { StackTypeMap, StackOwnerState } from './StackProps'; +import type { Breakpoint } from '../createTheme'; +import { Breakpoints } from '../createTheme/createBreakpoints'; +import { + handleBreakpoints, + mergeBreakpointsInOrder, + resolveBreakpointValues, +} from '../breakpoints'; +import { createUnarySpacing, getValue } from '../spacing'; +import { Spacing } from '../createTheme/createSpacing'; + +const defaultTheme = createTheme(); + +interface StyleFunctionProps { + theme: { breakpoints: Breakpoints; spacing: Spacing }; + ownerState: StackOwnerState; +} + +// widening Theme to any so that the consumer can own the theme structure. +const defaultCreateStyledComponent = (systemStyled as CreateMUIStyled)('div', { + name: 'MuiStack', + slot: 'Root', + overridesResolver: (props, styles) => styles.root, +}); + +function useThemePropsDefault(props: T) { + return useThemePropsSystem({ + props, + name: 'MuiStack', + defaultTheme, + }); +} + +/** + * Return an array with the separator React element interspersed between + * each React node of the input children. + * + * > joinChildren([1,2,3], 0) + * [1,0,2,0,3] + */ +function joinChildren(children: React.ReactNode, separator: React.ReactElement) { + const childrenArray = React.Children.toArray(children).filter(Boolean); + + return childrenArray.reduce((output, child, index) => { + output.push(child); + + if (index < childrenArray.length - 1) { + output.push(React.cloneElement(separator, { key: `separator-${index}` })); + } + + return output; + }, []); +} + +const getSideFromDirection = (direction: StackOwnerState['direction']) => { + return { + row: 'Left', + 'row-reverse': 'Right', + column: 'Top', + 'column-reverse': 'Bottom', + // @ts-ignore + }[direction]; +}; + +export const style = ({ ownerState, theme }: StyleFunctionProps) => { + let styles = { + display: 'flex', + flexDirection: 'column', + ...handleBreakpoints( + { theme }, + // @ts-ignore TODO: add types for resolveBreakpointValues + resolveBreakpointValues({ + values: ownerState.direction, + breakpoints: theme.breakpoints.values, + }), + (propValue: string) => ({ + flexDirection: propValue, + }), + ), + }; + + if (ownerState.spacing) { + const transformer = createUnarySpacing(theme); + + const base = Object.keys(theme.breakpoints.values).reduce((acc, breakpoint) => { + if ( + // @ts-ignore + (typeof ownerState.spacing === 'object' && ownerState.spacing[breakpoint] != null) || + // @ts-ignore + (typeof ownerState.direction === 'object' && ownerState.direction[breakpoint] != null) + ) { + // @ts-ignore + acc[breakpoint] = true; + } + return acc; + }, {}); + + // @ts-ignore TODO: add types for resolveBreakpointValues + const directionValues = resolveBreakpointValues({ + values: ownerState.direction, + base, + }); + + // @ts-ignore TODO: add types for resolveBreakpointValues + const spacingValues = resolveBreakpointValues({ + values: ownerState.spacing, + base, + }); + + if (typeof directionValues === 'object') { + Object.keys(directionValues).forEach((breakpoint, index, breakpoints) => { + const directionValue = directionValues[breakpoint]; + if (!directionValue) { + const previousDirectionValue = + index > 0 ? directionValues[breakpoints[index - 1]] : 'column'; + directionValues[breakpoint] = previousDirectionValue; + } + }); + } + + const styleFromPropValue = (propValue: string | number | null, breakpoint: Breakpoint) => { + return { + '& > :not(style) + :not(style)': { + margin: 0, + [`margin${getSideFromDirection( + breakpoint ? directionValues[breakpoint] : ownerState.direction, + )}`]: getValue(transformer, propValue), + }, + }; + }; + styles = deepmerge(styles, handleBreakpoints({ theme }, spacingValues, styleFromPropValue)); + } + + styles = mergeBreakpointsInOrder(theme.breakpoints, styles); + + return styles; +}; + +export default function createStack( + options: { + createStyledComponent?: typeof defaultCreateStyledComponent; + useThemeProps?: typeof useThemePropsDefault; + componentName?: string; + } = {}, +) { + const { + // This will allow adding custom styled fn (for example for custom sx style function) + createStyledComponent = defaultCreateStyledComponent, + useThemeProps = useThemePropsDefault, + componentName = 'MuiStack', + } = options; + + // TODO: Why the Stack in Material UI didn't have any utility classes? + const useUtilityClasses = (ownerState: StackOwnerState, theme: typeof defaultTheme) => { + const slots = { + root: ['root'], + }; + + return composeClasses(slots, (slot) => generateUtilityClass(componentName, slot), {}); + }; + + const StackRoot = createStyledComponent<{ + ownerState: StackOwnerState; + }>(style); + + const Stack = React.forwardRef(function Grid(inProps, ref) { + const themeProps = useThemeProps(inProps); + const props = extendSxProp(themeProps); + const { + component = 'div', + direction = 'column', + spacing = 0, + divider, + children, + ...other + } = props; + + const ownerState = { + direction, + spacing, + }; + + return ( + // @ts-ignore ref type mismatch + + {divider ? joinChildren(children, divider as React.ReactElement) : children} + + ); + }) as OverridableComponent; + + Stack.propTypes /* remove-proptypes */ = { + children: PropTypes.node, + direction: PropTypes.oneOfType([ + PropTypes.oneOf(['column-reverse', 'column', 'row-reverse', 'row']), + PropTypes.arrayOf(PropTypes.oneOf(['column-reverse', 'column', 'row-reverse', 'row'])), + PropTypes.object, + ]), + divider: PropTypes.node, + spacing: PropTypes.oneOfType([ + PropTypes.arrayOf(PropTypes.oneOfType([PropTypes.number, PropTypes.string])), + PropTypes.number, + PropTypes.object, + PropTypes.string, + ]), + sx: PropTypes.oneOfType([ + PropTypes.arrayOf(PropTypes.oneOfType([PropTypes.func, PropTypes.object, PropTypes.bool])), + PropTypes.func, + PropTypes.object, + ]), + }; + + return Stack; +} diff --git a/packages/mui-system/src/Stack/index.ts b/packages/mui-system/src/Stack/index.ts new file mode 100644 index 00000000000000..79789bd7002511 --- /dev/null +++ b/packages/mui-system/src/Stack/index.ts @@ -0,0 +1,3 @@ +export { default } from './Stack'; +export { default as createStack } from './createStack'; +export * from './StackProps'; diff --git a/packages/mui-system/src/index.d.ts b/packages/mui-system/src/index.d.ts index ddcf861551ba49..5d85064d263350 100644 --- a/packages/mui-system/src/index.d.ts +++ b/packages/mui-system/src/index.d.ts @@ -178,3 +178,6 @@ export * from './Container'; export { default as Unstable_Grid } from './Unstable_Grid'; export * from './Unstable_Grid'; + +export { default as Stack } from './Stack'; +export * from './Stack'; diff --git a/packages/mui-system/src/index.js b/packages/mui-system/src/index.js index c404c373d5f970..b6a85cbacdce68 100644 --- a/packages/mui-system/src/index.js +++ b/packages/mui-system/src/index.js @@ -57,3 +57,6 @@ export * from './Container'; export { default as Unstable_Grid } from './Unstable_Grid/Grid'; export * from './Unstable_Grid'; + +export { default as Stack } from './Stack/Stack'; +export * from './Stack'; diff --git a/packages/mui-system/src/spacing.d.ts b/packages/mui-system/src/spacing.d.ts index fe25376999e56b..9d45ddbd482e89 100644 --- a/packages/mui-system/src/spacing.d.ts +++ b/packages/mui-system/src/spacing.d.ts @@ -1,3 +1,4 @@ +import { string } from 'prop-types'; import { SimpleStyleFunction, spacing, PropsFor } from './Box'; export type SpacingProps = PropsFor; @@ -58,4 +59,10 @@ export const padding: SimpleStyleFunction< | 'paddingBlockEnd' >; +type SpacingValue = string | number | null | undefined; +export function getValue( + transformer: (prop: SpacingValue) => SpacingValue, + propValue: SpacingValue, +): SpacingValue; + export type PaddingProps = PropsFor; From c5f61cb813ac3d7e7c7c500e2ce0db25b70b9395 Mon Sep 17 00:00:00 2001 From: Marija Najdova Date: Tue, 2 Aug 2022 14:46:03 +0200 Subject: [PATCH 02/14] Resolve some type issues --- packages/mui-system/src/Stack/createStack.tsx | 36 +++++++++---------- packages/mui-system/src/breakpoints.d.ts | 21 +++++++++++ packages/mui-system/src/index.d.ts | 7 +--- 3 files changed, 39 insertions(+), 25 deletions(-) create mode 100644 packages/mui-system/src/breakpoints.d.ts diff --git a/packages/mui-system/src/Stack/createStack.tsx b/packages/mui-system/src/Stack/createStack.tsx index f8b732050f00a5..0aeeca3c4768da 100644 --- a/packages/mui-system/src/Stack/createStack.tsx +++ b/packages/mui-system/src/Stack/createStack.tsx @@ -71,8 +71,7 @@ const getSideFromDirection = (direction: StackOwnerState['direction']) => { 'row-reverse': 'Right', column: 'Top', 'column-reverse': 'Bottom', - // @ts-ignore - }[direction]; + }[direction as string]; }; export const style = ({ ownerState, theme }: StyleFunctionProps) => { @@ -81,7 +80,6 @@ export const style = ({ ownerState, theme }: StyleFunctionProps) => { flexDirection: 'column', ...handleBreakpoints( { theme }, - // @ts-ignore TODO: add types for resolveBreakpointValues resolveBreakpointValues({ values: ownerState.direction, breakpoints: theme.breakpoints.values, @@ -95,26 +93,26 @@ export const style = ({ ownerState, theme }: StyleFunctionProps) => { if (ownerState.spacing) { const transformer = createUnarySpacing(theme); - const base = Object.keys(theme.breakpoints.values).reduce((acc, breakpoint) => { - if ( - // @ts-ignore - (typeof ownerState.spacing === 'object' && ownerState.spacing[breakpoint] != null) || - // @ts-ignore - (typeof ownerState.direction === 'object' && ownerState.direction[breakpoint] != null) - ) { - // @ts-ignore - acc[breakpoint] = true; - } - return acc; - }, {}); - - // @ts-ignore TODO: add types for resolveBreakpointValues + const base = Object.keys(theme.breakpoints.values).reduce>( + (acc, breakpoint) => { + if ( + (typeof ownerState.spacing === 'object' && + (ownerState.spacing as any)[breakpoint] != null) || + (typeof ownerState.direction === 'object' && + (ownerState.direction as any)[breakpoint] != null) + ) { + acc[breakpoint] = true; + } + return acc; + }, + {}, + ); + const directionValues = resolveBreakpointValues({ values: ownerState.direction, base, }); - // @ts-ignore TODO: add types for resolveBreakpointValues const spacingValues = resolveBreakpointValues({ values: ownerState.spacing, base, @@ -131,7 +129,7 @@ export const style = ({ ownerState, theme }: StyleFunctionProps) => { }); } - const styleFromPropValue = (propValue: string | number | null, breakpoint: Breakpoint) => { + const styleFromPropValue = (propValue: string | number | null, breakpoint?: Breakpoint) => { return { '& > :not(style) + :not(style)': { margin: 0, diff --git a/packages/mui-system/src/breakpoints.d.ts b/packages/mui-system/src/breakpoints.d.ts new file mode 100644 index 00000000000000..44c23e7799e83e --- /dev/null +++ b/packages/mui-system/src/breakpoints.d.ts @@ -0,0 +1,21 @@ +import { CSSObject } from '@mui/styled-engine'; +import { Breakpoints } from './createTheme/createBreakpoints'; +import type { Breakpoint } from './createTheme'; +import { ResponsiveStyleValue } from './styleFunctionSx'; + +export interface ResolveBreakpointValuesOptions { + values: ResponsiveStyleValue; + breakpoints?: Breakpoints['values']; + base?: Record; +} +export function resolveBreakpointValues( + options: ResolveBreakpointValuesOptions, +): Record; + +export function mergeBreakpointsInOrder(breakpoints: Breakpoints, styles: CSSObject[]): CSSObject; + +export function handleBreakpoints( + props: Props, + propValue: any, + styleFromPropValue: (value: any, breakpoint?: Breakpoint) => any, +): any; diff --git a/packages/mui-system/src/index.d.ts b/packages/mui-system/src/index.d.ts index 5d85064d263350..c2dc1bdda444e8 100644 --- a/packages/mui-system/src/index.d.ts +++ b/packages/mui-system/src/index.d.ts @@ -32,12 +32,7 @@ export type BordersProps = PropsFor; // breakpoints.js type DefaultBreakPoints = 'xs' | 'sm' | 'md' | 'lg' | 'xl'; - -export function handleBreakpoints( - props: Props, - propValue: any, - styleFromPropValue: (value: any) => any, -): any; +export { handleBreakpoints } from './breakpoints'; /** * @returns An enhanced stylefunction that considers breakpoints From 3368b3a5720727349ba39a7bb883dcfc50b39591 Mon Sep 17 00:00:00 2001 From: Marija Najdova Date: Tue, 2 Aug 2022 14:57:52 +0200 Subject: [PATCH 03/14] Fix ref & color type issue --- packages/mui-system/src/Stack/StackProps.ts | 45 ++++++++++--------- packages/mui-system/src/Stack/createStack.tsx | 3 +- 2 files changed, 24 insertions(+), 24 deletions(-) diff --git a/packages/mui-system/src/Stack/StackProps.ts b/packages/mui-system/src/Stack/StackProps.ts index 3b69f8994019da..15928fbaf8d792 100644 --- a/packages/mui-system/src/Stack/StackProps.ts +++ b/packages/mui-system/src/Stack/StackProps.ts @@ -4,34 +4,35 @@ import { ResponsiveStyleValue, SxProps } from '../styleFunctionSx'; import { SystemProps } from '../Box'; import { Theme } from '../createTheme'; +export interface StackBaseProps { + /** + * The content of the component. + */ + children?: React.ReactNode; + /** + * Defines the `flex-direction` style property. + * It is applied for all screen sizes. + * @default 'column' + */ + direction?: ResponsiveStyleValue<'row' | 'row-reverse' | 'column' | 'column-reverse'>; + /** + * Defines the space between immediate children. + * @default 0 + */ + spacing?: ResponsiveStyleValue; + /** + * Add an element between each child. + */ + divider?: React.ReactNode; +} export interface StackTypeMap

{ props: P & - SystemProps & { - ref?: React.Ref; - /** - * The content of the component. - */ - children?: React.ReactNode; - /** - * Defines the `flex-direction` style property. - * It is applied for all screen sizes. - * @default 'column' - */ - direction?: ResponsiveStyleValue<'row' | 'row-reverse' | 'column' | 'column-reverse'>; - /** - * Defines the space between immediate children. - * @default 0 - */ - spacing?: ResponsiveStyleValue; - /** - * Add an element between each child. - */ - divider?: React.ReactNode; + StackBaseProps & { /** * The system prop, which allows defining system overrides as well as additional CSS styles. */ sx?: SxProps; - }; + } & SystemProps; defaultComponent: D; } diff --git a/packages/mui-system/src/Stack/createStack.tsx b/packages/mui-system/src/Stack/createStack.tsx index 0aeeca3c4768da..0c40687907acdc 100644 --- a/packages/mui-system/src/Stack/createStack.tsx +++ b/packages/mui-system/src/Stack/createStack.tsx @@ -176,7 +176,7 @@ export default function createStack( const Stack = React.forwardRef(function Grid(inProps, ref) { const themeProps = useThemeProps(inProps); - const props = extendSxProp(themeProps); + const props = extendSxProp(themeProps) as Omit; // `color` type conflicts with html color attribute. const { component = 'div', direction = 'column', @@ -192,7 +192,6 @@ export default function createStack( }; return ( - // @ts-ignore ref type mismatch {divider ? joinChildren(children, divider as React.ReactElement) : children} From bd4ea359642e581ad22b1ea440077565c7c4c56b Mon Sep 17 00:00:00 2001 From: Marija Najdova Date: Tue, 2 Aug 2022 16:11:23 +0200 Subject: [PATCH 04/14] [Stack} Replace with createStack --- docs/pages/material-ui/api/stack.json | 9 +- packages/mui-material/src/Stack/Stack.js | 151 +----- packages/mui-material/src/Stack/Stack.test.js | 468 +----------------- 3 files changed, 24 insertions(+), 604 deletions(-) diff --git a/docs/pages/material-ui/api/stack.json b/docs/pages/material-ui/api/stack.json index 8731cf74b412e0..69ef1476ad6795 100644 --- a/docs/pages/material-ui/api/stack.json +++ b/docs/pages/material-ui/api/stack.json @@ -1,21 +1,18 @@ { "props": { "children": { "type": { "name": "node" } }, - "component": { "type": { "name": "elementType" } }, "direction": { "type": { "name": "union", "description": "'column-reverse'
| 'column'
| 'row-reverse'
| 'row'
| Array<'column-reverse'
| 'column'
| 'row-reverse'
| 'row'>
| object" - }, - "default": "'column'" + } }, "divider": { "type": { "name": "node" } }, "spacing": { "type": { "name": "union", "description": "Array<number
| string>
| number
| object
| string" - }, - "default": "0" + } }, "sx": { "type": { @@ -27,7 +24,7 @@ "name": "Stack", "styles": { "classes": [], "globalClasses": {}, "name": null }, "spread": true, - "forwardsRefTo": "HTMLDivElement", + "forwardsRefTo": "HTMLElement", "filename": "/packages/mui-material/src/Stack/Stack.js", "inheritance": null, "demos": "

", diff --git a/packages/mui-material/src/Stack/Stack.js b/packages/mui-material/src/Stack/Stack.js index ea9df2eb7645c7..b98e4ef72d6721 100644 --- a/packages/mui-material/src/Stack/Stack.js +++ b/packages/mui-material/src/Stack/Stack.js @@ -1,144 +1,16 @@ -import * as React from 'react'; +/* eslint-disable material-ui/mui-name-matches-component-name */ import PropTypes from 'prop-types'; -import { - createUnarySpacing, - getValue, - handleBreakpoints, - mergeBreakpointsInOrder, - unstable_extendSxProp as extendSxProp, - unstable_resolveBreakpointValues as resolveBreakpointValues, -} from '@mui/system'; -import { deepmerge } from '@mui/utils'; +import { createStack } from '@mui/system'; import styled from '../styles/styled'; import useThemeProps from '../styles/useThemeProps'; -/** - * Return an array with the separator React element interspersed between - * each React node of the input children. - * - * > joinChildren([1,2,3], 0) - * [1,0,2,0,3] - */ -function joinChildren(children, separator) { - const childrenArray = React.Children.toArray(children).filter(Boolean); - - return childrenArray.reduce((output, child, index) => { - output.push(child); - - if (index < childrenArray.length - 1) { - output.push(React.cloneElement(separator, { key: `separator-${index}` })); - } - - return output; - }, []); -} - -const getSideFromDirection = (direction) => { - return { - row: 'Left', - 'row-reverse': 'Right', - column: 'Top', - 'column-reverse': 'Bottom', - }[direction]; -}; - -export const style = ({ ownerState, theme }) => { - let styles = { - display: 'flex', - flexDirection: 'column', - ...handleBreakpoints( - { theme }, - resolveBreakpointValues({ - values: ownerState.direction, - breakpoints: theme.breakpoints.values, - }), - (propValue) => ({ - flexDirection: propValue, - }), - ), - }; - - if (ownerState.spacing) { - const transformer = createUnarySpacing(theme); - - const base = Object.keys(theme.breakpoints.values).reduce((acc, breakpoint) => { - if ( - (typeof ownerState.spacing === 'object' && ownerState.spacing[breakpoint] != null) || - (typeof ownerState.direction === 'object' && ownerState.direction[breakpoint] != null) - ) { - acc[breakpoint] = true; - } - return acc; - }, {}); - - const directionValues = resolveBreakpointValues({ - values: ownerState.direction, - base, - }); - - const spacingValues = resolveBreakpointValues({ - values: ownerState.spacing, - base, - }); - - if (typeof directionValues === 'object') { - Object.keys(directionValues).forEach((breakpoint, index, breakpoints) => { - const directionValue = directionValues[breakpoint]; - if (!directionValue) { - const previousDirectionValue = - index > 0 ? directionValues[breakpoints[index - 1]] : 'column'; - directionValues[breakpoint] = previousDirectionValue; - } - }); - } - - const styleFromPropValue = (propValue, breakpoint) => { - return { - '& > :not(style) + :not(style)': { - margin: 0, - [`margin${getSideFromDirection( - breakpoint ? directionValues[breakpoint] : ownerState.direction, - )}`]: getValue(transformer, propValue), - }, - }; - }; - styles = deepmerge(styles, handleBreakpoints({ theme }, spacingValues, styleFromPropValue)); - } - - styles = mergeBreakpointsInOrder(theme.breakpoints, styles); - - return styles; -}; - -const StackRoot = styled('div', { - name: 'MuiStack', - slot: 'Root', - overridesResolver: (props, styles) => { - return [styles.root]; - }, -})(style); - -const Stack = React.forwardRef(function Stack(inProps, ref) { - const themeProps = useThemeProps({ props: inProps, name: 'MuiStack' }); - const props = extendSxProp(themeProps); - const { - component = 'div', - direction = 'column', - spacing = 0, - divider, - children, - ...other - } = props; - const ownerState = { - direction, - spacing, - }; - - return ( - - {divider ? joinChildren(children, divider) : children} - - ); +const Stack = createStack({ + createStyledComponent: styled('div', { + name: 'MuiStack', + slot: 'Root', + overridesResolver: (props, styles) => [styles.root], + }), + useThemeProps: (inProps) => useThemeProps({ props: inProps, name: 'MuiStack' }), }); Stack.propTypes /* remove-proptypes */ = { @@ -150,11 +22,6 @@ Stack.propTypes /* remove-proptypes */ = { * The content of the component. */ children: PropTypes.node, - /** - * The component used for the root node. - * Either a string to use a HTML element or a component. - */ - component: PropTypes.elementType, /** * Defines the `flex-direction` style property. * It is applied for all screen sizes. diff --git a/packages/mui-material/src/Stack/Stack.test.js b/packages/mui-material/src/Stack/Stack.test.js index d2733b2d844dc9..f77957264f1b97 100644 --- a/packages/mui-material/src/Stack/Stack.test.js +++ b/packages/mui-material/src/Stack/Stack.test.js @@ -1,466 +1,22 @@ import * as React from 'react'; -import { expect } from 'chai'; -import { createRenderer, describeConformance } from 'test/utils'; +import { describeConformance, createRenderer } from 'test/utils'; import Stack from '@mui/material/Stack'; -import { createTheme } from '@mui/material/styles'; -import defaultTheme from '@mui/material/styles/defaultTheme'; -import { style } from './Stack'; +// The main tests are in mui-system Stack folder describe('', () => { const { render } = createRenderer(); - describeConformance(, () => ({ - render, + const defaultProps = { + children:
, + }; + + describeConformance(, () => ({ + classes: {}, inheritComponent: 'div', - refInstanceof: window.HTMLDivElement, + render, + refInstanceof: window.HTMLElement, muiName: 'MuiStack', - skip: ['componentProp', 'componentsProp', 'rootClass', 'themeVariants', 'themeStyleOverrides'], + testVariantProps: { direction: 'row' }, + skip: ['componentsProp', 'classesRoot'], })); - - const theme = createTheme(); - - it('should handle breakpoints with a missing key', () => { - expect( - style({ - ownerState: { - direction: { xs: 'column', sm: 'row' }, - spacing: { xs: 1, sm: 2, md: 4 }, - }, - theme, - }), - ).to.deep.equal({ - '@media (min-width:0px)': { - '& > :not(style) + :not(style)': { - margin: 0, - marginTop: '8px', - }, - flexDirection: 'column', - }, - [`@media (min-width:${defaultTheme.breakpoints.values.sm}px)`]: { - '& > :not(style) + :not(style)': { - margin: 0, - marginLeft: '16px', - }, - flexDirection: 'row', - }, - [`@media (min-width:${defaultTheme.breakpoints.values.md}px)`]: { - '& > :not(style) + :not(style)': { - margin: 0, - marginLeft: '32px', - }, - }, - display: 'flex', - flexDirection: 'column', - }); - }); - - it('should handle direction with multiple keys and spacing with one', () => { - expect( - style({ - ownerState: { - direction: { sm: 'column', md: 'row' }, - spacing: 2, - }, - theme, - }), - ).to.deep.equal({ - [`@media (min-width:${defaultTheme.breakpoints.values.sm}px)`]: { - '& > :not(style) + :not(style)': { - margin: 0, - marginTop: '16px', - }, - flexDirection: 'column', - }, - [`@media (min-width:${defaultTheme.breakpoints.values.md}px)`]: { - '& > :not(style) + :not(style)': { - margin: 0, - marginLeft: '16px', - }, - flexDirection: 'row', - }, - display: 'flex', - flexDirection: 'column', - }); - }); - - it('should handle spacing with multiple keys and direction with one', () => { - expect( - style({ - ownerState: { - direction: 'column', - spacing: { sm: 2, md: 4 }, - }, - theme, - }), - ).to.deep.equal({ - [`@media (min-width:${defaultTheme.breakpoints.values.sm}px)`]: { - '& > :not(style) + :not(style)': { - margin: 0, - marginTop: '16px', - }, - }, - [`@media (min-width:${defaultTheme.breakpoints.values.md}px)`]: { - '& > :not(style) + :not(style)': { - margin: 0, - marginTop: '32px', - }, - }, - display: 'flex', - flexDirection: 'column', - }); - }); - - it('should handle spacing with multiple keys and null values', () => { - expect( - style({ - ownerState: { - direction: 'column', - spacing: { sm: 2, md: 0, lg: 4 }, - }, - theme, - }), - ).to.deep.equal({ - [`@media (min-width:${defaultTheme.breakpoints.values.sm}px)`]: { - '& > :not(style) + :not(style)': { - margin: 0, - marginTop: '16px', - }, - }, - [`@media (min-width:${defaultTheme.breakpoints.values.md}px)`]: { - '& > :not(style) + :not(style)': { - margin: 0, - marginTop: '0px', - }, - }, - [`@media (min-width:${defaultTheme.breakpoints.values.lg}px)`]: { - '& > :not(style) + :not(style)': { - margin: 0, - marginTop: '32px', - }, - }, - display: 'flex', - flexDirection: 'column', - }); - }); - - it('should handle flat params', () => { - expect( - style({ - ownerState: { - direction: 'row', - spacing: 3, - }, - theme, - }), - ).to.deep.equal({ - '& > :not(style) + :not(style)': { - margin: 0, - marginLeft: '24px', - }, - display: 'flex', - flexDirection: 'row', - }); - }); - - it('should respect the theme breakpoints order', () => { - expect( - style({ - ownerState: { - direction: { xs: 'column' }, - spacing: { lg: 2, xs: 1 }, - }, - theme, - }), - ).to.deep.equal({ - '@media (min-width:0px)': { - '& > :not(style) + :not(style)': { - margin: 0, - marginTop: '8px', - }, - flexDirection: 'column', - }, - [`@media (min-width:${defaultTheme.breakpoints.values.lg}px)`]: { - '& > :not(style) + :not(style)': { - margin: 0, - marginTop: '16px', - }, - }, - display: 'flex', - flexDirection: 'column', - }); - }); - - describe('prop: direction', () => { - it('should generate correct direction given string values', () => { - expect( - style({ - ownerState: { - direction: 'column-reverse', - spacing: 1, - }, - theme, - }), - ).to.deep.equal({ - '& > :not(style) + :not(style)': { - margin: 0, - marginBottom: '8px', - }, - display: 'flex', - flexDirection: 'column-reverse', - }); - }); - - it('should generate correct responsive styles regardless of breakpoints order', () => { - expect( - style({ - ownerState: { - direction: { sm: 'row', xs: 'column' }, - spacing: { xs: 1, sm: 2, md: 3 }, - }, - theme, - }), - ).to.deep.equal({ - '@media (min-width:0px)': { - '& > :not(style) + :not(style)': { - margin: 0, - marginTop: '8px', - }, - flexDirection: 'column', - }, - [`@media (min-width:${defaultTheme.breakpoints.values.sm}px)`]: { - '& > :not(style) + :not(style)': { - margin: 0, - marginLeft: '16px', - }, - flexDirection: 'row', - }, - [`@media (min-width:${defaultTheme.breakpoints.values.md}px)`]: { - '& > :not(style) + :not(style)': { - margin: 0, - marginLeft: '24px', - }, - }, - display: 'flex', - flexDirection: 'column', - }); - }); - - it('should generate correct direction even though breakpoints are not fully provided', () => { - expect( - style({ - ownerState: { - direction: { lg: 'row' }, - }, - theme, - }), - ).to.deep.equal({ - [`@media (min-width:${defaultTheme.breakpoints.values.lg}px)`]: { - flexDirection: 'row', - }, - display: 'flex', - flexDirection: 'column', - }); - }); - - it('should place correct margin direction even though breakpoints are not fully provided', () => { - expect( - style({ - ownerState: { - direction: { lg: 'row' }, - spacing: { xs: 0, md: 2, xl: 4 }, - }, - theme, - }), - ).to.deep.equal({ - [`@media (min-width:${defaultTheme.breakpoints.values.xs}px)`]: { - '& > :not(style) + :not(style)': { - margin: 0, - marginTop: '0px', - }, - }, - [`@media (min-width:${defaultTheme.breakpoints.values.md}px)`]: { - '& > :not(style) + :not(style)': { - margin: 0, - marginTop: '16px', - }, - }, - [`@media (min-width:${defaultTheme.breakpoints.values.lg}px)`]: { - '& > :not(style) + :not(style)': { - margin: 0, - marginLeft: '16px', - }, - flexDirection: 'row', - }, - [`@media (min-width:${defaultTheme.breakpoints.values.xl}px)`]: { - '& > :not(style) + :not(style)': { - margin: 0, - marginLeft: '32px', - }, - }, - display: 'flex', - flexDirection: 'column', - }); - - expect( - style({ - ownerState: { - direction: { lg: 'column', sm: 'row' }, - spacing: { md: 2, xl: 4, xs: 0 }, - }, - theme, - }), - ).to.deep.equal({ - [`@media (min-width:${defaultTheme.breakpoints.values.xs}px)`]: { - '& > :not(style) + :not(style)': { - margin: 0, - marginTop: '0px', - }, - }, - [`@media (min-width:${defaultTheme.breakpoints.values.sm}px)`]: { - '& > :not(style) + :not(style)': { - margin: 0, - marginLeft: '0px', - }, - flexDirection: 'row', - }, - [`@media (min-width:${defaultTheme.breakpoints.values.md}px)`]: { - '& > :not(style) + :not(style)': { - margin: 0, - marginLeft: '16px', - }, - }, - [`@media (min-width:${defaultTheme.breakpoints.values.lg}px)`]: { - '& > :not(style) + :not(style)': { - margin: 0, - marginTop: '16px', - }, - flexDirection: 'column', - }, - [`@media (min-width:${defaultTheme.breakpoints.values.xl}px)`]: { - '& > :not(style) + :not(style)': { - margin: 0, - marginTop: '32px', - }, - }, - display: 'flex', - flexDirection: 'column', - }); - }); - }); - - describe('prop: spacing', () => { - it('should generate correct responsive styles regardless of breakpoints order', () => { - expect( - style({ - ownerState: { - direction: 'column', - spacing: { sm: 2, md: 3, xs: 1 }, - }, - theme, - }), - ).to.deep.equal({ - '@media (min-width:0px)': { - '& > :not(style) + :not(style)': { - margin: 0, - marginTop: '8px', - }, - }, - [`@media (min-width:${defaultTheme.breakpoints.values.sm}px)`]: { - '& > :not(style) + :not(style)': { - margin: 0, - marginTop: '16px', - }, - }, - [`@media (min-width:${defaultTheme.breakpoints.values.md}px)`]: { - '& > :not(style) + :not(style)': { - margin: 0, - marginTop: '24px', - }, - }, - display: 'flex', - flexDirection: 'column', - }); - }); - - it('should generate correct styles if custom breakpoints are provided in theme', () => { - const customTheme = createTheme({ - breakpoints: { - values: { - smallest: 0, - small: 375, - mobile: 600, - tablet: 992, - desktop: 1200, - }, - }, - }); - - expect( - style({ - ownerState: { - direction: 'column', - spacing: 4, - }, - theme: customTheme, - }), - ).to.deep.equal({ - '& > :not(style) + :not(style)': { - margin: 0, - marginTop: '32px', - }, - display: 'flex', - flexDirection: 'column', - }); - }); - - it('should generate correct responsive styles if custom responsive spacing values are provided', () => { - const customTheme = createTheme({ - breakpoints: { - values: { - smallest: 0, - small: 375, - mobile: 600, - tablet: 992, - desktop: 1200, - }, - }, - }); - - expect( - style({ - ownerState: { - direction: 'column', - spacing: { small: 4 }, - }, - theme: customTheme, - }), - ).to.deep.equal({ - [`@media (min-width:${customTheme.breakpoints.values.small}px)`]: { - '& > :not(style) + :not(style)': { - margin: 0, - marginTop: '32px', - }, - }, - display: 'flex', - flexDirection: 'column', - }); - }); - - it('should list responsive styles in correct order', () => { - const styles = style({ - ownerState: { - direction: { xs: 'column', lg: 'row' }, - spacing: { xs: 0, md: 2, xl: 4 }, - }, - theme, - }); - const keysForResponsiveStyles = Object.keys(styles).filter((prop) => prop.includes('@media')); - expect(keysForResponsiveStyles).to.deep.equal([ - '@media (min-width:0px)', - '@media (min-width:900px)', - '@media (min-width:1200px)', - '@media (min-width:1536px)', - ]); - }); - }); }); From 7c3bb07a82eaba3107625d3aa0b89ead3c86d7aa Mon Sep 17 00:00:00 2001 From: Marija Najdova Date: Wed, 3 Aug 2022 10:20:27 +0200 Subject: [PATCH 05/14] Fix CI issues --- .../system/components/stack/BasicStack.js | 2 -- .../system/components/stack/BasicStack.tsx | 2 -- .../system/components/stack/DirectionStack.js | 2 -- .../components/stack/DirectionStack.tsx | 2 -- .../system/components/stack/DividerStack.js | 2 -- .../system/components/stack/DividerStack.tsx | 2 -- .../components/stack/InteractiveStack.js | 8 ++++---- .../components/stack/InteractiveStack.tsx | 8 ++++---- .../components/stack/ResponsiveStack.js | 2 -- .../components/stack/ResponsiveStack.tsx | 2 -- docs/translations/translations.json | 1 + packages/mui-material/src/Stack/Stack.test.js | 4 ++-- packages/mui-material/src/Stack/index.d.ts | 3 +++ packages/mui-material/src/Stack/index.js | 1 + .../mui-material/src/Stack/stackClasses.ts | 13 +++++++++++++ packages/mui-system/src/Stack/createStack.tsx | 15 ++++++++++++--- packages/mui-system/src/Stack/index.ts | 3 +++ packages/mui-system/src/Stack/stackClasses.ts | 19 +++++++++++++++++++ packages/mui-system/src/spacing.d.ts | 1 - 19 files changed, 62 insertions(+), 30 deletions(-) create mode 100644 packages/mui-material/src/Stack/stackClasses.ts create mode 100644 packages/mui-system/src/Stack/stackClasses.ts diff --git a/docs/data/system/components/stack/BasicStack.js b/docs/data/system/components/stack/BasicStack.js index 6f5b05d97dc02f..9dcd0ce6dc6491 100644 --- a/docs/data/system/components/stack/BasicStack.js +++ b/docs/data/system/components/stack/BasicStack.js @@ -4,10 +4,8 @@ import { styled, Box, Stack } from '@mui/system'; const Item = styled(Paper)(({ theme }) => ({ backgroundColor: theme.palette.mode === 'dark' ? '#1A2027' : '#fff', - ...theme.typography.body2, padding: theme.spacing(1), textAlign: 'center', - color: theme.palette.text.secondary, })); export default function BasicStack() { diff --git a/docs/data/system/components/stack/BasicStack.tsx b/docs/data/system/components/stack/BasicStack.tsx index 6f5b05d97dc02f..9dcd0ce6dc6491 100644 --- a/docs/data/system/components/stack/BasicStack.tsx +++ b/docs/data/system/components/stack/BasicStack.tsx @@ -4,10 +4,8 @@ import { styled, Box, Stack } from '@mui/system'; const Item = styled(Paper)(({ theme }) => ({ backgroundColor: theme.palette.mode === 'dark' ? '#1A2027' : '#fff', - ...theme.typography.body2, padding: theme.spacing(1), textAlign: 'center', - color: theme.palette.text.secondary, })); export default function BasicStack() { diff --git a/docs/data/system/components/stack/DirectionStack.js b/docs/data/system/components/stack/DirectionStack.js index 1eb6e9fcc84008..c7dffe7e0b7946 100644 --- a/docs/data/system/components/stack/DirectionStack.js +++ b/docs/data/system/components/stack/DirectionStack.js @@ -4,10 +4,8 @@ import { styled, Stack } from '@mui/system'; const Item = styled(Paper)(({ theme }) => ({ backgroundColor: theme.palette.mode === 'dark' ? '#1A2027' : '#fff', - ...theme.typography.body2, padding: theme.spacing(1), textAlign: 'center', - color: theme.palette.text.secondary, })); export default function DirectionStack() { diff --git a/docs/data/system/components/stack/DirectionStack.tsx b/docs/data/system/components/stack/DirectionStack.tsx index 1eb6e9fcc84008..c7dffe7e0b7946 100644 --- a/docs/data/system/components/stack/DirectionStack.tsx +++ b/docs/data/system/components/stack/DirectionStack.tsx @@ -4,10 +4,8 @@ import { styled, Stack } from '@mui/system'; const Item = styled(Paper)(({ theme }) => ({ backgroundColor: theme.palette.mode === 'dark' ? '#1A2027' : '#fff', - ...theme.typography.body2, padding: theme.spacing(1), textAlign: 'center', - color: theme.palette.text.secondary, })); export default function DirectionStack() { diff --git a/docs/data/system/components/stack/DividerStack.js b/docs/data/system/components/stack/DividerStack.js index 19d9aa7cc5b1c6..746419439250ef 100644 --- a/docs/data/system/components/stack/DividerStack.js +++ b/docs/data/system/components/stack/DividerStack.js @@ -5,10 +5,8 @@ import { styled, Stack } from '@mui/system'; const Item = styled(Paper)(({ theme }) => ({ backgroundColor: theme.palette.mode === 'dark' ? '#1A2027' : '#fff', - ...theme.typography.body2, padding: theme.spacing(1), textAlign: 'center', - color: theme.palette.text.secondary, })); export default function DividerStack() { diff --git a/docs/data/system/components/stack/DividerStack.tsx b/docs/data/system/components/stack/DividerStack.tsx index 19d9aa7cc5b1c6..746419439250ef 100644 --- a/docs/data/system/components/stack/DividerStack.tsx +++ b/docs/data/system/components/stack/DividerStack.tsx @@ -5,10 +5,8 @@ import { styled, Stack } from '@mui/system'; const Item = styled(Paper)(({ theme }) => ({ backgroundColor: theme.palette.mode === 'dark' ? '#1A2027' : '#fff', - ...theme.typography.body2, padding: theme.spacing(1), textAlign: 'center', - color: theme.palette.text.secondary, })); export default function DividerStack() { diff --git a/docs/data/system/components/stack/InteractiveStack.js b/docs/data/system/components/stack/InteractiveStack.js index 0e68b8a0eec201..8db420a1582d0c 100644 --- a/docs/data/system/components/stack/InteractiveStack.js +++ b/docs/data/system/components/stack/InteractiveStack.js @@ -51,7 +51,7 @@ export default function InteractiveStack() { - + direction - + alignItems - + justifyContent - + spacing - + direction - + alignItems - + justifyContent - + spacing ({ backgroundColor: theme.palette.mode === 'dark' ? '#1A2027' : '#fff', - ...theme.typography.body2, padding: theme.spacing(1), textAlign: 'center', - color: theme.palette.text.secondary, })); export default function ResponsiveStack() { diff --git a/docs/data/system/components/stack/ResponsiveStack.tsx b/docs/data/system/components/stack/ResponsiveStack.tsx index 0a29179625219c..406cbf6659e603 100644 --- a/docs/data/system/components/stack/ResponsiveStack.tsx +++ b/docs/data/system/components/stack/ResponsiveStack.tsx @@ -4,10 +4,8 @@ import { styled, Stack } from '@mui/system'; const Item = styled(Paper)(({ theme }) => ({ backgroundColor: theme.palette.mode === 'dark' ? '#1A2027' : '#fff', - ...theme.typography.body2, padding: theme.spacing(1), textAlign: 'center', - color: theme.palette.text.secondary, })); export default function ResponsiveStack() { diff --git a/docs/translations/translations.json b/docs/translations/translations.json index bf62c8cd5f19a3..66dd83fcdc9ea6 100644 --- a/docs/translations/translations.json +++ b/docs/translations/translations.json @@ -181,6 +181,7 @@ "/system/react-box": "Box", "/system/react-container": "Container", "/system/react-grid": "Grid", + "/system/react-stack": "Stack", "/system/styles": "Styles", "/system/styles/basics": "Basics", "/system/styles/advanced": "Advanced", diff --git a/packages/mui-material/src/Stack/Stack.test.js b/packages/mui-material/src/Stack/Stack.test.js index f77957264f1b97..b2df4e44a7974a 100644 --- a/packages/mui-material/src/Stack/Stack.test.js +++ b/packages/mui-material/src/Stack/Stack.test.js @@ -1,6 +1,6 @@ import * as React from 'react'; import { describeConformance, createRenderer } from 'test/utils'; -import Stack from '@mui/material/Stack'; +import Stack, { stackClasses as classes } from '@mui/material/Stack'; // The main tests are in mui-system Stack folder describe('', () => { @@ -11,7 +11,7 @@ describe('', () => { }; describeConformance(, () => ({ - classes: {}, + classes, inheritComponent: 'div', render, refInstanceof: window.HTMLElement, diff --git a/packages/mui-material/src/Stack/index.d.ts b/packages/mui-material/src/Stack/index.d.ts index 70b9b479f0c6dc..4f6b1828b2d3b6 100644 --- a/packages/mui-material/src/Stack/index.d.ts +++ b/packages/mui-material/src/Stack/index.d.ts @@ -1,2 +1,5 @@ export { default } from './Stack'; export * from './Stack'; + +export { default as stackClasses } from './stackClasses'; +export * from './stackClasses'; diff --git a/packages/mui-material/src/Stack/index.js b/packages/mui-material/src/Stack/index.js index 129ee566c9f837..2eb8645cc51ca0 100644 --- a/packages/mui-material/src/Stack/index.js +++ b/packages/mui-material/src/Stack/index.js @@ -1 +1,2 @@ export { default } from './Stack'; +export { default as stackClasses } from './stackClasses'; diff --git a/packages/mui-material/src/Stack/stackClasses.ts b/packages/mui-material/src/Stack/stackClasses.ts new file mode 100644 index 00000000000000..1025beef1927e8 --- /dev/null +++ b/packages/mui-material/src/Stack/stackClasses.ts @@ -0,0 +1,13 @@ +import { generateUtilityClass, generateUtilityClasses } from '@mui/base'; +import { StackClasses } from '@mui/system'; + +export type { StackClassKey } from '@mui/system'; +export type { StackClasses }; + +export function getStackUtilityClass(slot: string): string { + return generateUtilityClass('MuiStack', slot); +} + +const stackClasses: StackClasses = generateUtilityClasses('MuiStack', ['root']); + +export default stackClasses; diff --git a/packages/mui-system/src/Stack/createStack.tsx b/packages/mui-system/src/Stack/createStack.tsx index 0c40687907acdc..9de8daf6d72850 100644 --- a/packages/mui-system/src/Stack/createStack.tsx +++ b/packages/mui-system/src/Stack/createStack.tsx @@ -1,5 +1,6 @@ import * as React from 'react'; import PropTypes from 'prop-types'; +import clsx from 'clsx'; import { OverridableComponent } from '@mui/types'; import { deepmerge, @@ -161,8 +162,7 @@ export default function createStack( componentName = 'MuiStack', } = options; - // TODO: Why the Stack in Material UI didn't have any utility classes? - const useUtilityClasses = (ownerState: StackOwnerState, theme: typeof defaultTheme) => { + const useUtilityClasses = () => { const slots = { root: ['root'], }; @@ -183,6 +183,7 @@ export default function createStack( spacing = 0, divider, children, + className, ...other } = props; @@ -191,8 +192,16 @@ export default function createStack( spacing, }; + const classes = useUtilityClasses(); + return ( - + {divider ? joinChildren(children, divider as React.ReactElement) : children} ); diff --git a/packages/mui-system/src/Stack/index.ts b/packages/mui-system/src/Stack/index.ts index 79789bd7002511..3e02c9de01261b 100644 --- a/packages/mui-system/src/Stack/index.ts +++ b/packages/mui-system/src/Stack/index.ts @@ -1,3 +1,6 @@ export { default } from './Stack'; export { default as createStack } from './createStack'; export * from './StackProps'; + +export { default as stackClasses } from './stackClasses'; +export * from './stackClasses'; diff --git a/packages/mui-system/src/Stack/stackClasses.ts b/packages/mui-system/src/Stack/stackClasses.ts new file mode 100644 index 00000000000000..3c3aea3ec5e8b4 --- /dev/null +++ b/packages/mui-system/src/Stack/stackClasses.ts @@ -0,0 +1,19 @@ +import { + unstable_generateUtilityClass as generateUtilityClass, + unstable_generateUtilityClasses as generateUtilityClasses, +} from '@mui/utils'; + +export interface StackClasses { + /** Styles applied to the root element. */ + root: string; +} + +export type StackClassKey = keyof StackClasses; + +export function getStackUtilityClass(slot: string): string { + return generateUtilityClass('MuiStack', slot); +} + +const stackClasses: StackClasses = generateUtilityClasses('MuiStack', ['root']); + +export default stackClasses; diff --git a/packages/mui-system/src/spacing.d.ts b/packages/mui-system/src/spacing.d.ts index 9d45ddbd482e89..5f2fd95e75a010 100644 --- a/packages/mui-system/src/spacing.d.ts +++ b/packages/mui-system/src/spacing.d.ts @@ -1,4 +1,3 @@ -import { string } from 'prop-types'; import { SimpleStyleFunction, spacing, PropsFor } from './Box'; export type SpacingProps = PropsFor; From 99aae35b0d084df5b28783768ba2576230f33522 Mon Sep 17 00:00:00 2001 From: Marija Najdova Date: Wed, 3 Aug 2022 10:33:48 +0200 Subject: [PATCH 06/14] Export all types --- packages/mui-system/src/spacing.d.ts | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/packages/mui-system/src/spacing.d.ts b/packages/mui-system/src/spacing.d.ts index 5f2fd95e75a010..9157d8c676d615 100644 --- a/packages/mui-system/src/spacing.d.ts +++ b/packages/mui-system/src/spacing.d.ts @@ -58,10 +58,10 @@ export const padding: SimpleStyleFunction< | 'paddingBlockEnd' >; -type SpacingValue = string | number | null | undefined; +export type SpacingValueType = string | number | null | undefined; export function getValue( - transformer: (prop: SpacingValue) => SpacingValue, - propValue: SpacingValue, -): SpacingValue; + transformer: (prop: SpacingValueType) => SpacingValueType, + propValue: SpacingValueType, +): SpacingValueType; export type PaddingProps = PropsFor; From aa992965dc5d6c18e78a09df6312984b58471f61 Mon Sep 17 00:00:00 2001 From: Marija Najdova Date: Thu, 4 Aug 2022 13:58:14 +0200 Subject: [PATCH 07/14] Fix prop types generation --- docs/pages/material-ui/api/stack.json | 1 + docs/pages/system/api/stack.json | 1 + docs/translations/api-docs/stack/stack.json | 1 + packages/mui-material/src/Stack/Stack.d.ts | 1 - packages/mui-material/src/Stack/Stack.js | 5 +++++ packages/mui-system/src/Stack/Stack.tsx | 5 +++++ scripts/generateProptypes.ts | 1 + 7 files changed, 14 insertions(+), 1 deletion(-) diff --git a/docs/pages/material-ui/api/stack.json b/docs/pages/material-ui/api/stack.json index 69ef1476ad6795..85d7aa7c9c2985 100644 --- a/docs/pages/material-ui/api/stack.json +++ b/docs/pages/material-ui/api/stack.json @@ -1,6 +1,7 @@ { "props": { "children": { "type": { "name": "node" } }, + "component": { "type": { "name": "elementType" } }, "direction": { "type": { "name": "union", diff --git a/docs/pages/system/api/stack.json b/docs/pages/system/api/stack.json index ec49d24e02040e..5a6e82c4c9024d 100644 --- a/docs/pages/system/api/stack.json +++ b/docs/pages/system/api/stack.json @@ -1,6 +1,7 @@ { "props": { "children": { "type": { "name": "node" } }, + "component": { "type": { "name": "elementType" } }, "direction": { "type": { "name": "union", diff --git a/docs/translations/api-docs/stack/stack.json b/docs/translations/api-docs/stack/stack.json index 528b1904adcce1..8fa2e742c67f59 100644 --- a/docs/translations/api-docs/stack/stack.json +++ b/docs/translations/api-docs/stack/stack.json @@ -2,6 +2,7 @@ "componentDescription": "", "propDescriptions": { "children": "The content of the component.", + "component": "The component used for the root node. Either a string to use a HTML element or a component.", "direction": "Defines the flex-direction style property. It is applied for all screen sizes.", "divider": "Add an element between each child.", "spacing": "Defines the space between immediate children.", diff --git a/packages/mui-material/src/Stack/Stack.d.ts b/packages/mui-material/src/Stack/Stack.d.ts index a56cef8f258487..3394ad6c19e9f6 100644 --- a/packages/mui-material/src/Stack/Stack.d.ts +++ b/packages/mui-material/src/Stack/Stack.d.ts @@ -6,7 +6,6 @@ import { Theme } from '../styles/createTheme'; export interface StackTypeMap

{ props: P & SystemProps & { - ref?: React.Ref; /** * The content of the component. */ diff --git a/packages/mui-material/src/Stack/Stack.js b/packages/mui-material/src/Stack/Stack.js index b98e4ef72d6721..40f7704257d69f 100644 --- a/packages/mui-material/src/Stack/Stack.js +++ b/packages/mui-material/src/Stack/Stack.js @@ -22,6 +22,11 @@ Stack.propTypes /* remove-proptypes */ = { * The content of the component. */ children: PropTypes.node, + /** + * The component used for the root node. + * Either a string to use a HTML element or a component. + */ + component: PropTypes.elementType, /** * Defines the `flex-direction` style property. * It is applied for all screen sizes. diff --git a/packages/mui-system/src/Stack/Stack.tsx b/packages/mui-system/src/Stack/Stack.tsx index e6fe81d3ed5d7e..6b8feee47d9173 100644 --- a/packages/mui-system/src/Stack/Stack.tsx +++ b/packages/mui-system/src/Stack/Stack.tsx @@ -21,6 +21,11 @@ Stack.propTypes /* remove-proptypes */ = { * The content of the component. */ children: PropTypes.node, + /** + * The component used for the root node. + * Either a string to use a HTML element or a component. + */ + component: PropTypes.elementType, /** * Defines the `flex-direction` style property. * It is applied for all screen sizes. diff --git a/scripts/generateProptypes.ts b/scripts/generateProptypes.ts index 376b3d4a3483bb..2089742be4a45f 100644 --- a/scripts/generateProptypes.ts +++ b/scripts/generateProptypes.ts @@ -74,6 +74,7 @@ const useExternalDocumentation: Record = { Radio: ['disableRipple', 'id', 'inputProps', 'inputRef', 'required'], Checkbox: ['defaultChecked'], Container: ['component'], + Stack: ['component'], Switch: [ 'checked', 'defaultChecked', From 6f504820f41e67acc8d7c58d104c725ff3ae0c60 Mon Sep 17 00:00:00 2001 From: Marija Najdova Date: Wed, 31 Aug 2022 13:17:53 +0200 Subject: [PATCH 08/14] run proptypes & docs:api --- packages/mui-joy/src/Stack/Stack.tsx | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/packages/mui-joy/src/Stack/Stack.tsx b/packages/mui-joy/src/Stack/Stack.tsx index 5a484fcaa641f4..d6ff09cf9af4b6 100644 --- a/packages/mui-joy/src/Stack/Stack.tsx +++ b/packages/mui-joy/src/Stack/Stack.tsx @@ -24,6 +24,11 @@ Stack.propTypes /* remove-proptypes */ = { * The content of the component. */ children: PropTypes.node, + /** + * The component used for the root node. + * Either a string to use a HTML element or a component. + */ + component: PropTypes.elementType, /** * Defines the `flex-direction` style property. * It is applied for all screen sizes. From be732c6960a03d763d329d2556b868130e35c911 Mon Sep 17 00:00:00 2001 From: Marija Najdova Date: Wed, 31 Aug 2022 13:41:26 +0200 Subject: [PATCH 09/14] Fix forwardsRefTo --- docs/pages/material-ui/api/stack.json | 2 +- packages/mui-material/src/Stack/Stack.test.js | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/docs/pages/material-ui/api/stack.json b/docs/pages/material-ui/api/stack.json index 85d7aa7c9c2985..2727a13bdb3082 100644 --- a/docs/pages/material-ui/api/stack.json +++ b/docs/pages/material-ui/api/stack.json @@ -25,7 +25,7 @@ "name": "Stack", "styles": { "classes": [], "globalClasses": {}, "name": null }, "spread": true, - "forwardsRefTo": "HTMLElement", + "forwardsRefTo": "HTMLDivElement", "filename": "/packages/mui-material/src/Stack/Stack.js", "inheritance": null, "demos": "

", diff --git a/packages/mui-material/src/Stack/Stack.test.js b/packages/mui-material/src/Stack/Stack.test.js index b2df4e44a7974a..a95d40de219861 100644 --- a/packages/mui-material/src/Stack/Stack.test.js +++ b/packages/mui-material/src/Stack/Stack.test.js @@ -14,7 +14,7 @@ describe('', () => { classes, inheritComponent: 'div', render, - refInstanceof: window.HTMLElement, + refInstanceof: window.HTMLDivElement, muiName: 'MuiStack', testVariantProps: { direction: 'row' }, skip: ['componentsProp', 'classesRoot'], From 07f2d0e77d48c3bb3d649f480ccc72664c60fd66 Mon Sep 17 00:00:00 2001 From: siriwatknp Date: Thu, 1 Sep 2022 08:28:25 +0700 Subject: [PATCH 10/14] update eslint to support component factory --- .../rules/mui-name-matches-component-name.js | 14 ++++++++++ .../mui-name-matches-component-name.test.js | 28 +++++++++++++++++++ 2 files changed, 42 insertions(+) diff --git a/packages/eslint-plugin-material-ui/src/rules/mui-name-matches-component-name.js b/packages/eslint-plugin-material-ui/src/rules/mui-name-matches-component-name.js index 799fcca065339a..70aabd06e4d7f8 100644 --- a/packages/eslint-plugin-material-ui/src/rules/mui-name-matches-component-name.js +++ b/packages/eslint-plugin-material-ui/src/rules/mui-name-matches-component-name.js @@ -98,6 +98,20 @@ const rule = { componentName = parent.id.name; } + if ( + parent.type === 'VariableDeclarator' && + parent.init.type.match(/(CallExpression|TSAsExpression)/) + ) { + const callee = + parent.init.type === 'TSAsExpression' + ? parent.init.expression.callee + : parent.init.callee; + if (callee.name.includes(parent.id.name)) { + // For component factory, e.g. const Container = createContainer({ ... }) + componentName = parent.id.name; + } + } + parent = parent.parent; } diff --git a/packages/eslint-plugin-material-ui/src/rules/mui-name-matches-component-name.test.js b/packages/eslint-plugin-material-ui/src/rules/mui-name-matches-component-name.test.js index 77d67624bd7cbb..34f55378923bed 100644 --- a/packages/eslint-plugin-material-ui/src/rules/mui-name-matches-component-name.test.js +++ b/packages/eslint-plugin-material-ui/src/rules/mui-name-matches-component-name.test.js @@ -17,6 +17,34 @@ ruleTester.run('mui-name-matches-component-name', rule, { useThemeProps({ props: inProps, name: 'MuiCssBaseline' }); } `, + ` + const Container = createContainer({ + createStyledComponent: styled('div', { + name: 'MuiContainer', + slot: 'Root', + overridesResolver: (props, styles) => { + const { ownerState } = props; + + return [ + styles.root, + ownerState.fixed && styles.fixed, + ownerState.disableGutters && styles.disableGutters, + ]; + }, + }), + useThemeProps: (inProps) => useThemeProps({ props: inProps, name: 'MuiContainer' }), + }); + `, + ` + const Grid2 = createGrid2({ + createStyledComponent: styled('div', { + name: 'MuiGrid2', + overridesResolver: (props, styles) => styles.root, + }), + componentName: 'MuiGrid2', + useThemeProps: (inProps) => useThemeProps({ props: inProps, name: 'MuiGrid2' }), + }) as OverridableComponent; + `, { code: ` const StaticDateRangePicker = React.forwardRef(function StaticDateRangePicker( From 290f4a597fe964fe9b0965878cc8cb46d55570d1 Mon Sep 17 00:00:00 2001 From: siriwatknp Date: Thu, 1 Sep 2022 08:38:37 +0700 Subject: [PATCH 11/14] remove eslint-disable --- packages/mui-material/src/Container/Container.js | 1 - packages/mui-material/src/Stack/Stack.js | 1 - packages/mui-material/src/Unstable_Grid2/Grid2.tsx | 5 ++--- 3 files changed, 2 insertions(+), 5 deletions(-) diff --git a/packages/mui-material/src/Container/Container.js b/packages/mui-material/src/Container/Container.js index f2a213bbb42226..63c2f720d13736 100644 --- a/packages/mui-material/src/Container/Container.js +++ b/packages/mui-material/src/Container/Container.js @@ -1,4 +1,3 @@ -/* eslint-disable material-ui/mui-name-matches-component-name */ import PropTypes from 'prop-types'; import { createContainer } from '@mui/system'; import capitalize from '../utils/capitalize'; diff --git a/packages/mui-material/src/Stack/Stack.js b/packages/mui-material/src/Stack/Stack.js index 40f7704257d69f..bc9271899b7b7f 100644 --- a/packages/mui-material/src/Stack/Stack.js +++ b/packages/mui-material/src/Stack/Stack.js @@ -1,4 +1,3 @@ -/* eslint-disable material-ui/mui-name-matches-component-name */ import PropTypes from 'prop-types'; import { createStack } from '@mui/system'; import styled from '../styles/styled'; diff --git a/packages/mui-material/src/Unstable_Grid2/Grid2.tsx b/packages/mui-material/src/Unstable_Grid2/Grid2.tsx index 5b452cf9fe4938..c4e17e071c3d16 100644 --- a/packages/mui-material/src/Unstable_Grid2/Grid2.tsx +++ b/packages/mui-material/src/Unstable_Grid2/Grid2.tsx @@ -1,16 +1,15 @@ import PropTypes from 'prop-types'; -import { createGrid } from '@mui/system/Unstable_Grid'; +import { createGrid as createGrid2 } from '@mui/system/Unstable_Grid'; import { OverridableComponent } from '@mui/types'; import { styled, useThemeProps } from '../styles'; import { Grid2TypeMap } from './Grid2Props'; -const Grid2 = createGrid({ +const Grid2 = createGrid2({ createStyledComponent: styled('div', { name: 'MuiGrid2', overridesResolver: (props, styles) => styles.root, }), componentName: 'MuiGrid2', - // eslint-disable-next-line material-ui/mui-name-matches-component-name useThemeProps: (inProps) => useThemeProps({ props: inProps, name: 'MuiGrid2' }), }) as OverridableComponent; From ded56f17cc994307ea03ff3fdae34622fa2f2cbc Mon Sep 17 00:00:00 2001 From: Marija Najdova Date: Thu, 23 Feb 2023 10:00:25 +0100 Subject: [PATCH 12/14] Fix wrong import --- packages/mui-material/src/Stack/stackClasses.ts | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/packages/mui-material/src/Stack/stackClasses.ts b/packages/mui-material/src/Stack/stackClasses.ts index 1025beef1927e8..77384ff3dbb0c3 100644 --- a/packages/mui-material/src/Stack/stackClasses.ts +++ b/packages/mui-material/src/Stack/stackClasses.ts @@ -1,4 +1,5 @@ -import { generateUtilityClass, generateUtilityClasses } from '@mui/base'; +import { unstable_generateUtilityClasses as generateUtilityClasses } from '@mui/utils'; +import generateUtilityClass from '../generateUtilityClass'; import { StackClasses } from '@mui/system'; export type { StackClassKey } from '@mui/system'; From 9598cb7f0e0c7c900b0d7cda3510681b31a9db8a Mon Sep 17 00:00:00 2001 From: Marija Najdova Date: Thu, 23 Feb 2023 10:59:24 +0100 Subject: [PATCH 13/14] lint fix --- packages/mui-material/src/Stack/stackClasses.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/mui-material/src/Stack/stackClasses.ts b/packages/mui-material/src/Stack/stackClasses.ts index 77384ff3dbb0c3..f8fa09fb8dc005 100644 --- a/packages/mui-material/src/Stack/stackClasses.ts +++ b/packages/mui-material/src/Stack/stackClasses.ts @@ -1,6 +1,6 @@ import { unstable_generateUtilityClasses as generateUtilityClasses } from '@mui/utils'; -import generateUtilityClass from '../generateUtilityClass'; import { StackClasses } from '@mui/system'; +import generateUtilityClass from '../generateUtilityClass'; export type { StackClassKey } from '@mui/system'; export type { StackClasses }; From 34e4536019c6afe8be745f7d22c68ea03f2bfe7c Mon Sep 17 00:00:00 2001 From: Marija Najdova Date: Thu, 23 Feb 2023 13:40:18 +0100 Subject: [PATCH 14/14] Update packages/mui-material/src/Stack/Stack.js Co-authored-by: Siriwat K Signed-off-by: Marija Najdova --- packages/mui-material/src/Stack/Stack.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/mui-material/src/Stack/Stack.js b/packages/mui-material/src/Stack/Stack.js index bc9271899b7b7f..f3d2ab9804f4a2 100644 --- a/packages/mui-material/src/Stack/Stack.js +++ b/packages/mui-material/src/Stack/Stack.js @@ -7,7 +7,7 @@ const Stack = createStack({ createStyledComponent: styled('div', { name: 'MuiStack', slot: 'Root', - overridesResolver: (props, styles) => [styles.root], + overridesResolver: (props, styles) => styles.root, }), useThemeProps: (inProps) => useThemeProps({ props: inProps, name: 'MuiStack' }), });