Path: blob/1.0-develop/resources/scripts/components/elements/ProgressBar.tsx
7461 views
import React, { useEffect, useRef, useState } from 'react';1import styled from 'styled-components/macro';2import { useStoreActions, useStoreState } from 'easy-peasy';3import { randomInt } from '@/helpers';4import { CSSTransition } from 'react-transition-group';5import tw from 'twin.macro';67const BarFill = styled.div`8${tw`h-full bg-cyan-400`};9transition: 250ms ease-in-out;10box-shadow: 0 -2px 10px 2px hsl(178, 78%, 57%);11`;1213type Timer = ReturnType<typeof setTimeout>;1415export default () => {16const interval = useRef<Timer>(null) as React.MutableRefObject<Timer>;17const timeout = useRef<Timer>(null) as React.MutableRefObject<Timer>;18const [visible, setVisible] = useState(false);19const progress = useStoreState((state) => state.progress.progress);20const continuous = useStoreState((state) => state.progress.continuous);21const setProgress = useStoreActions((actions) => actions.progress.setProgress);2223useEffect(() => {24return () => {25timeout.current && clearTimeout(timeout.current);26interval.current && clearInterval(interval.current);27};28}, []);2930useEffect(() => {31setVisible((progress || 0) > 0);3233if (progress === 100) {34timeout.current = setTimeout(() => setProgress(undefined), 500);35}36}, [progress]);3738useEffect(() => {39if (!continuous) {40interval.current && clearInterval(interval.current);41return;42}4344if (!progress || progress === 0) {45setProgress(randomInt(20, 30));46}47}, [continuous]);4849useEffect(() => {50if (continuous) {51interval.current && clearInterval(interval.current);52if ((progress || 0) >= 90) {53setProgress(90);54} else {55interval.current = setTimeout(() => setProgress((progress || 0) + randomInt(1, 5)), 500);56}57}58}, [progress, continuous]);5960return (61<div css={tw`w-full fixed`} style={{ height: '2px' }}>62<CSSTransition timeout={150} appear in={visible} unmountOnExit classNames={'fade'}>63<BarFill style={{ width: progress === undefined ? '100%' : `${progress}%` }} />64</CSSTransition>65</div>66);67};686970