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 ( {children} ); }); LoadingButton.propTypes = { variant: PropTypes.string, shape: PropTypes.string, children: PropTypes.node, color: PropTypes.string }; LoadingButton.displayName = 'LoadingButton'; export default LoadingButton;