All files / Rindu/components/icons Add.tsx

15.38% Statements 4/26
0% Branches 0/12
0% Functions 0/7
16% Lines 4/25

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 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112            19x   19x   19x 19x                                                                                                                                                                                                        
import {
  ReactElement,
  SVGProps,
  useCallback,
  useEffect,
  useState,
} from "react";
 
import { useLottie } from "lottie-react";
 
import AddAnimation from "animations/add-circle.json";
import { handleAsyncError } from "utils";
 
export function Add(
  props: SVGProps<SVGSVGElement> & {
    handleClick?: () => Promise<boolean>;
    isAdded?: boolean;
    shouldUpdateList?: boolean;
  }
): ReactElement {
  const [isPlaying, setIsPlaying] = useState(false);
  const { View, goToAndPlay, animationItem, pause, goToAndStop } = useLottie(
    {
      animationData: AddAnimation,
      loop: 0,
      autoplay: false,
      onSegmentStart: () => {
        setIsPlaying(true);
      },
      onComplete: () => {
        setIsPlaying(false);
      },
    },
    {
      width: 24,
      height: 24,
    }
  );
  useEffect(() => {
    Iif (props.isAdded && props.shouldUpdateList && !isPlaying) {
      goToAndStop(50, true);
    }
  }, [goToAndStop, isPlaying, props.isAdded, props.shouldUpdateList]);
 
  useEffect(() => {
    animationItem?.addEventListener("enterFrame", () => {
      Iif (
        animationItem?.currentFrame > 50 &&
        animationItem?.currentFrame < 60
      ) {
        pause();
        setIsPlaying(false);
      }
    });
  }, [animationItem, pause]);
 
  const handleClick = useCallback(async () => {
    Iif (isPlaying) return;
    Iif (props.handleClick) {
      const res = await props.handleClick();
      if (res) {
        goToAndPlay(0);
      } else {
        goToAndPlay(60, true);
      }
    }
  }, [goToAndPlay, isPlaying, props]);
 
  Iif (!props.handleClick) {
    return (
      <svg height="12" width="12" viewBox="0 0 16 16" {...props}>
        <path d="M14 7H9V2H7v5H2v2h5v5h2V9h5z"></path>
        <path fill="none" d="M0 0h16v16H0z"></path>
      </svg>
    );
  }
 
  return (
    <button
      type="button"
      aria-label="Add"
      onClick={handleAsyncError(handleClick)}
    >
      {View}
      <style jsx>{`
        button {
          position: relative;
          background: none;
          border: none;
          display: block;
          width: 24px;
          height: 24px;
          max-width: 24px;
          max-height: 24px;
          overflow: hidden;
        }
        button :global(div) {
          position: absolute;
          transform: scale(5.6);
          top: 0;
          left: 0;
          display: inline-block;
        }
        button:hover :global(svg > g > g:nth-child(1) path),
        button:hover :global(svg > g > g:nth-child(2) path:nth-child(1)) {
          stroke: #fff;
        }
      `}</style>
    </button>
  );
}