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.
114 lines
2.7 KiB
114 lines
2.7 KiB
import { Box as MUIBox, BoxProps as MUIBoxProps } from '@mui/material'; |
|
import { FC, useMemo } from 'react'; |
|
|
|
type FlexBoxDirection = 'column' | 'row'; |
|
|
|
type FlexBoxOptionalProps = { |
|
row?: boolean; |
|
lg?: FlexBoxDirection; |
|
md?: FlexBoxDirection; |
|
sm?: FlexBoxDirection; |
|
spacing?: number | string; |
|
xl?: FlexBoxDirection; |
|
xs?: FlexBoxDirection; |
|
}; |
|
|
|
type FlexBoxProps = MUIBoxProps & FlexBoxOptionalProps; |
|
|
|
const FLEX_BOX_DEFAULT_PROPS: Required< |
|
Omit<FlexBoxOptionalProps, 'lg' | 'md' | 'sm' | 'xl'> |
|
> & |
|
Pick<FlexBoxOptionalProps, 'lg' | 'md' | 'sm' | 'xl'> = { |
|
row: false, |
|
lg: undefined, |
|
md: undefined, |
|
sm: undefined, |
|
spacing: '1em', |
|
xl: undefined, |
|
xs: 'column', |
|
}; |
|
|
|
const FlexBox: FC<FlexBoxProps> = ({ |
|
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, |
|
...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: string | number; |
|
marginTop: string | number; |
|
} |
|
> = useMemo( |
|
() => ({ |
|
column: { |
|
alignItems: 'normal', |
|
marginLeft: 0, |
|
marginTop: spacing, |
|
}, |
|
row: { |
|
alignItems: 'center', |
|
marginLeft: spacing, |
|
marginTop: 0, |
|
}, |
|
}), |
|
[spacing], |
|
); |
|
|
|
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 }, |
|
|
|
'& > :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;
|
|
|