All files / app/components/Button Button.tsx

90.9% Statements 20/22
90% Branches 18/20
100% Functions 5/5
90% Lines 18/20

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 7871x 71x 71x   71x   71x 27743x 3468x                   210x                                           3468x 3468x   177x 177x   177x 177x         177x     3468x                                       71x 7917x  
import { Button as MuiButton, ButtonProps, styled, useTheme } from "@mui/material";
import Sentry from "platform/sentry";
import React, { ElementType, ForwardedRef, forwardRef, useState } from "react";
 
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 [waiting, setWaiting] = useState(false);
  const theme = useTheme();
  async function asyncOnClick(event: React.MouseEvent<HTMLButtonElement>) {
    try {
      setWaiting(true);
 
      Eif (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;