All files / app/components/Button Button.tsx

91.66% Statements 22/24
94.44% Branches 17/18
100% Functions 5/5
90.9% Lines 20/22

Press n or j to go to the next uncovered block, b, p or k for the previous block.

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87          45x 45x 45x 45x   45x   45x 11009x 1365x                   103x                                           1365x 1365x 1365x   106x 106x   106x 106x         106x     1365x                                           45x 2443x  
import {
  Button as MuiButton,
  ButtonProps,
  styled,
  useTheme,
} from "@mui/material";
import Sentry from "platform/sentry";
import React, { ElementType, ForwardedRef, forwardRef } from "react";
import { useIsMounted, useSafeState } from "utils/hooks";
 
import CircularProgress from "../CircularProgress";
 
const StyledMuiButton = styled(MuiButton, {
  shouldForwardProp: (prop) => prop !== "contained",
})<{ contained: boolean }>(({ theme, contained }) => ({
  minHeight: `calc(calc(${theme.typography.button.lineHeight} * ${
    theme.typography.button.fontSize
  }) + ${theme.typography.pxToRem(12)})`, //from padding
  ...(contained && {
    borderRadius: theme.shape.borderRadius,
    boxShadow: "0px 0px 5px rgba(0, 0, 0, 0.25)",
  }),
}));
 
const StyledCircularProgress = styled(CircularProgress)(() => ({
  position: "absolute",
  bottom: 0,
  left: 0,
  right: 0,
  top: 0,
  margin: "auto",
}));
 
function InternalButton<D extends ElementType = "button">(
  {
    children,
    disabled,
    className,
    loading,
    onClick,
    variant = "contained",
    color = "primary",
    ...otherProps
  }: ButtonProps<D>,
  ref: ForwardedRef<HTMLButtonElement>,
) {
  const isMounted = useIsMounted();
  const [waiting, setWaiting] = useSafeState(isMounted, false);
  const theme = useTheme();
  async function asyncOnClick(event: React.MouseEvent<HTMLButtonElement>) {
    try {
      setWaiting(true);
 
      if (onClick) {
        await onClick(event);
      }
    } catch (e) {
      Sentry.captureException(e);
    } finally {
      setWaiting(false);
    }
  }
  Iif (variant !== "contained" && color !== "primary") {
    throw new Error("Only contained buttons should have color.");
  }
  return (
    <StyledMuiButton
      {...otherProps}
      ref={ref}
      onClick={onClick && asyncOnClick}
      disabled={disabled ? true : loading || waiting}
      className={className}
      contained={variant === "contained"}
      variant={variant}
      color={variant === "contained" ? color : undefined}
    >
      {(loading || waiting) && (
        <StyledCircularProgress size={theme.typography.button.fontSize} />
      )}
      {children}
    </StyledMuiButton>
  );
}
 
const Button = forwardRef(InternalButton);
export default Button;