Local modifications to ClusterLabs/Anvil by Alteeve
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 
 
 

143 lines
3.5 KiB

import { Box as MUIBox, BoxProps as MUIBoxProps } from '@mui/material';
import { FC, useMemo } from 'react';
type FlexBoxDirection = 'column' | 'row';
type FlexBoxSpacing = number | string;
type FlexBoxOptionalPropsWithDefault = {
fullWidth?: boolean;
growFirst?: boolean;
row?: boolean;
spacing?: FlexBoxSpacing;
xs?: FlexBoxDirection;
};
type FlexBoxOptionalPropsWithoutDefault = {
columnSpacing?: FlexBoxSpacing;
rowSpacing?: FlexBoxSpacing;
lg?: FlexBoxDirection;
md?: FlexBoxDirection;
sm?: FlexBoxDirection;
xl?: FlexBoxDirection;
};
type FlexBoxOptionalProps = FlexBoxOptionalPropsWithDefault &
FlexBoxOptionalPropsWithoutDefault;
type FlexBoxProps = MUIBoxProps & FlexBoxOptionalProps;
const FLEX_BOX_DEFAULT_PROPS: Required<FlexBoxOptionalPropsWithDefault> &
FlexBoxOptionalPropsWithoutDefault = {
columnSpacing: undefined,
fullWidth: false,
growFirst: false,
row: false,
rowSpacing: undefined,
lg: undefined,
md: undefined,
sm: undefined,
spacing: '1em',
xl: undefined,
xs: 'column',
};
const FlexBox: FC<FlexBoxProps> = ({
fullWidth,
growFirst,
lg: dLg = FLEX_BOX_DEFAULT_PROPS.lg,
md: dMd = FLEX_BOX_DEFAULT_PROPS.md,
row: isRow,
sm: dSm = FLEX_BOX_DEFAULT_PROPS.sm,
spacing = FLEX_BOX_DEFAULT_PROPS.spacing,
sx,
xl: dXl = FLEX_BOX_DEFAULT_PROPS.xl,
xs: dXs = FLEX_BOX_DEFAULT_PROPS.xs,
// Input props that depend on other input props.
columnSpacing = spacing,
rowSpacing = spacing,
...muiBoxRestProps
}) => {
const xs = useMemo(() => (isRow ? 'row' : dXs), [dXs, isRow]);
const sm = useMemo(() => dSm || xs, [dSm, xs]);
const md = useMemo(() => dMd || sm, [dMd, sm]);
const lg = useMemo(() => dLg || md, [dLg, md]);
const xl = useMemo(() => dXl || lg, [dXl, lg]);
const mapToSx: Record<
FlexBoxDirection,
{
alignItems: string;
marginLeft: FlexBoxSpacing;
marginTop: FlexBoxSpacing;
}
> = useMemo(
() => ({
column: {
alignItems: 'normal',
marginLeft: 0,
marginTop: columnSpacing,
},
row: {
alignItems: 'center',
marginLeft: rowSpacing,
marginTop: 0,
},
}),
[columnSpacing, rowSpacing],
);
const firstChildFlexGrow = useMemo(
() => (growFirst ? 1 : undefined),
[growFirst],
);
const width = useMemo(() => (fullWidth ? '100%' : undefined), [fullWidth]);
return (
<MUIBox
{...{
...muiBoxRestProps,
sx: {
alignItems: {
xs: mapToSx[xs].alignItems,
sm: mapToSx[sm].alignItems,
md: mapToSx[md].alignItems,
lg: mapToSx[lg].alignItems,
xl: mapToSx[xl].alignItems,
},
display: 'flex',
flexDirection: { xs, sm, md, lg, xl },
width,
'& > :first-child': {
flexGrow: firstChildFlexGrow,
},
'& > :not(:first-child)': {
marginLeft: {
xs: mapToSx[xs].marginLeft,
sm: mapToSx[sm].marginLeft,
md: mapToSx[md].marginLeft,
lg: mapToSx[lg].marginLeft,
xl: mapToSx[xl].marginLeft,
},
marginTop: {
xs: mapToSx[xs].marginTop,
sm: mapToSx[sm].marginTop,
md: mapToSx[md].marginTop,
lg: mapToSx[lg].marginTop,
xl: mapToSx[xl].marginTop,
},
},
...sx,
},
}}
/>
);
};
FlexBox.defaultProps = FLEX_BOX_DEFAULT_PROPS;
export type { FlexBoxProps };
export default FlexBox;