Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[Stack][material] Use createStack from the system #33795

Merged
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 2 additions & 4 deletions docs/pages/material-ui/api/stack.json
Original file line number Diff line number Diff line change
Expand Up @@ -6,16 +6,14 @@
"type": {
"name": "union",
"description": "'column-reverse'<br>&#124;&nbsp;'column'<br>&#124;&nbsp;'row-reverse'<br>&#124;&nbsp;'row'<br>&#124;&nbsp;Array&lt;'column-reverse'<br>&#124;&nbsp;'column'<br>&#124;&nbsp;'row-reverse'<br>&#124;&nbsp;'row'&gt;<br>&#124;&nbsp;object"
},
mnajdova marked this conversation as resolved.
Show resolved Hide resolved
"default": "'column'"
}
},
"divider": { "type": { "name": "node" } },
"spacing": {
"type": {
"name": "union",
"description": "Array&lt;number<br>&#124;&nbsp;string&gt;<br>&#124;&nbsp;number<br>&#124;&nbsp;object<br>&#124;&nbsp;string"
},
"default": "0"
}
},
"sx": {
"type": {
Expand Down
1 change: 1 addition & 0 deletions docs/pages/system/api/stack.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
{
"props": {
"children": { "type": { "name": "node" } },
"component": { "type": { "name": "elementType" } },
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Oops this was missing in the prop types

"direction": {
"type": {
"name": "union",
Expand Down
1 change: 1 addition & 0 deletions docs/translations/api-docs/stack/stack.json
Original file line number Diff line number Diff line change
Expand Up @@ -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 <code>flex-direction</code> style property. It is applied for all screen sizes.",
"divider": "Add an element between each child.",
"spacing": "Defines the space between immediate children.",
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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;
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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<Grid2TypeMap>;
`,
{
code: `
const StaticDateRangePicker = React.forwardRef(function StaticDateRangePicker<TDate>(
Expand Down
5 changes: 5 additions & 0 deletions packages/mui-joy/src/Stack/Stack.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,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.
Expand Down
1 change: 0 additions & 1 deletion packages/mui-material/src/Container/Container.js
Original file line number Diff line number Diff line change
@@ -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';
Expand Down
1 change: 0 additions & 1 deletion packages/mui-material/src/Stack/Stack.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,6 @@ import { Theme } from '../styles/createTheme';
export interface StackTypeMap<P = {}, D extends React.ElementType = 'div'> {
props: P &
SystemProps<Theme> & {
ref?: React.Ref<unknown>;
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Redundant, not sure why we had it here.

/**
* The content of the component.
*/
Expand Down
145 changes: 8 additions & 137 deletions packages/mui-material/src/Stack/Stack.js
Original file line number Diff line number Diff line change
@@ -1,144 +1,15 @@
import * as React from 'react';
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 (
<StackRoot as={component} ownerState={ownerState} ref={ref} {...other}>
{divider ? joinChildren(children, divider) : children}
</StackRoot>
);
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 */ = {
Expand Down
Loading