232 lines
5.5 KiB
JavaScript
232 lines
5.5 KiB
JavaScript
import PropTypes from 'prop-types';
|
|
import { forwardRef } from 'react';
|
|
|
|
// material-ui
|
|
import MuiLoadingButton from '@mui/lab/LoadingButton';
|
|
import { alpha, styled, useTheme } from '@mui/material/styles';
|
|
|
|
// project imports
|
|
import getColors from 'utils/getColors';
|
|
import getShadow from 'utils/getShadow';
|
|
|
|
// ==============================|| LOADING BUTTON - COLOR STYLE ||============================== //
|
|
|
|
function getColorStyle({ variant, theme, color, loadingPosition }) {
|
|
const colors = getColors(theme, color);
|
|
const { lighter, main, dark, contrastText } = colors;
|
|
|
|
const buttonShadow = `${color}Button`;
|
|
const shadows = getShadow(theme, buttonShadow);
|
|
|
|
const loadingIndicator = {
|
|
'& .MuiLoadingButton-loadingIndicator': {
|
|
color: main
|
|
}
|
|
};
|
|
|
|
const loadingColor = {
|
|
...(loadingPosition &&
|
|
loadingPosition !== 'center' && {
|
|
color: main
|
|
})
|
|
};
|
|
|
|
const commonShadow = {
|
|
'&::after': {
|
|
boxShadow: `0 0 6px 6px ${alpha(main, 0.9)}`
|
|
},
|
|
'&:active::after': {
|
|
boxShadow: `0 0 0 0 ${alpha(main, 0.9)}`
|
|
},
|
|
'&:focus-visible': {
|
|
outline: `2px solid ${dark}`,
|
|
outlineOffset: 2
|
|
}
|
|
};
|
|
|
|
switch (variant) {
|
|
case 'contained':
|
|
return {
|
|
backgroundColor: main,
|
|
...(loadingPosition &&
|
|
loadingPosition !== 'center' && {
|
|
color: contrastText
|
|
}),
|
|
'& .MuiLoadingButton-loadingIndicator': {
|
|
color: contrastText
|
|
},
|
|
'&:hover': {
|
|
backgroundColor: dark,
|
|
color: contrastText
|
|
},
|
|
...commonShadow
|
|
};
|
|
case 'light':
|
|
return {
|
|
backgroundColor: main,
|
|
...(loadingPosition &&
|
|
loadingPosition !== 'center' && {
|
|
color: contrastText
|
|
}),
|
|
'& .MuiLoadingButton-loadingIndicator': {
|
|
color: contrastText
|
|
},
|
|
'&:hover': {
|
|
backgroundColor: dark,
|
|
color: contrastText
|
|
},
|
|
...commonShadow
|
|
};
|
|
case 'shadow':
|
|
return {
|
|
boxShadow: shadows,
|
|
backgroundColor: main,
|
|
...(loadingPosition &&
|
|
loadingPosition !== 'center' && {
|
|
color: contrastText
|
|
}),
|
|
'& .MuiLoadingButton-loadingIndicator': {
|
|
color: contrastText
|
|
},
|
|
'&:hover': {
|
|
boxShadow: 'none',
|
|
backgroundColor: dark,
|
|
color: contrastText
|
|
},
|
|
...commonShadow
|
|
};
|
|
case 'outlined':
|
|
return {
|
|
backgroundColor: 'transparent',
|
|
borderColor: main,
|
|
...loadingColor,
|
|
...loadingIndicator
|
|
};
|
|
case 'dashed':
|
|
return {
|
|
backgroundColor: lighter,
|
|
borderColor: main,
|
|
...loadingColor,
|
|
...loadingIndicator,
|
|
...commonShadow
|
|
};
|
|
case 'text':
|
|
default:
|
|
return {
|
|
color: main,
|
|
...loadingIndicator,
|
|
...commonShadow
|
|
};
|
|
}
|
|
}
|
|
|
|
// ==============================|| STYLED - LOADING BUTTON ||============================== //
|
|
|
|
const LoadingButtonStyle = styled(MuiLoadingButton, { shouldForwardProp: (prop) => prop !== 'shape' && prop !== 'variant' })(
|
|
({ theme, variant, shape, color, loading, loadingPosition }) => ({
|
|
'::after': {
|
|
content: '""',
|
|
display: 'block',
|
|
position: 'absolute',
|
|
left: 0,
|
|
top: 0,
|
|
width: '100%',
|
|
height: '100%',
|
|
borderRadius: shape === 'rounded' ? '50%' : 4,
|
|
opacity: 0,
|
|
transition: 'all 0.5s'
|
|
},
|
|
|
|
':active::after': {
|
|
position: 'absolute',
|
|
borderRadius: shape === 'rounded' ? '50%' : 4,
|
|
left: 0,
|
|
top: 0,
|
|
opacity: 1,
|
|
transition: '0s'
|
|
},
|
|
...(variant === 'text' && {
|
|
...getColorStyle({ variant, theme, color, loadingPosition }),
|
|
'&.MuiButton-sizeMedium': {
|
|
height: 36
|
|
},
|
|
'&.MuiButton-sizeSmall': {
|
|
height: 30
|
|
},
|
|
'&.MuiButton-sizeLarge': {
|
|
height: 44
|
|
}
|
|
}),
|
|
...(shape && {
|
|
minWidth: 0,
|
|
'&.MuiButton-sizeMedium': {
|
|
width: 36,
|
|
height: 36
|
|
},
|
|
'&.MuiButton-sizeSmall': {
|
|
width: 30,
|
|
height: 30
|
|
},
|
|
'&.MuiButton-sizeLarge': {
|
|
width: 44,
|
|
height: 44
|
|
},
|
|
...(shape === 'rounded' && {
|
|
borderRadius: '50%'
|
|
})
|
|
}),
|
|
|
|
...(variant === 'outlined' && {
|
|
border: '1px solid'
|
|
}),
|
|
...(variant === 'dashed' && {
|
|
border: '1px dashed'
|
|
}),
|
|
...((variant === 'contained' || variant === 'shadow') &&
|
|
!loading && {
|
|
color: '#fff'
|
|
}),
|
|
...(variant !== 'text' && {
|
|
...getColorStyle({ variant, theme, color, loadingPosition })
|
|
}),
|
|
|
|
'&.Mui-disabled': {
|
|
...(variant !== 'text' && {
|
|
...getColorStyle({ variant, theme, color, loadingPosition })
|
|
})
|
|
}
|
|
})
|
|
);
|
|
|
|
// ==============================|| EXTENDED - LOADING BUTTON ||============================== //
|
|
|
|
const LoadingButton = forwardRef(({ variant = 'text', shape, children, color = 'primary', ...others }, ref) => {
|
|
const theme = useTheme();
|
|
|
|
return (
|
|
<LoadingButtonStyle
|
|
ref={ref}
|
|
variant={variant}
|
|
shape={shape}
|
|
theme={theme}
|
|
loadingPosition={others.loadingPosition}
|
|
loading={others.loading}
|
|
color={color}
|
|
{...others}
|
|
>
|
|
{children}
|
|
</LoadingButtonStyle>
|
|
);
|
|
});
|
|
|
|
LoadingButton.propTypes = {
|
|
variant: PropTypes.string,
|
|
shape: PropTypes.string,
|
|
children: PropTypes.node,
|
|
color: PropTypes.string
|
|
};
|
|
|
|
LoadingButton.displayName = 'LoadingButton';
|
|
|
|
export default LoadingButton;
|