# All files / composer/components/progress-indicators CircularIndicator.jsx

20% Statements 3/15
0% Branches 0/6
0% Functions 0/1
20% Lines 3/15

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

    1x

    1x

    1x

     import React from 'react';
    import PropTypes from 'prop-types';
    import Svg from '../../components/Svg';
    import styles from '../css/progress-indicators/CircularIndicator.css';

    const CircularIndicator = (props) => {
      const {
        size, progress, initialProgress, showText, classNames, styles: stylesMap,
        strokeWidth,
      } = props;

      const displayedProgress = initialProgress + (progress * (100 - initialProgress) / 100);
      const progressText = (
        progress === 100 ? 'Finishing up…' :
          progress === 0 ? `${progress}%` : `${progress.toFixed(1)}%`
      );

      const circleRadius = size / 2 - strokeWidth / 2;
      const circleCircumference = 2 * Math.PI * circleRadius;

      const containerClassName = [
        styles.container,
        classNames.container,
      ].join(' ');

      const containerDynamicStyle = {
        width: size,
        height: size,
      };

      const svgDynamicStyle = {
        width: size,
        height: size,
      };

      const circleClassName = [
        styles.circle,
        classNames.circle,
      ].join(' ');

      const circleDynamicStyle = {
        strokeDashoffset: (100 - displayedProgress) * circleCircumference / 100,
        strokeDasharray: circleCircumference,
        strokeWidth,
        ...stylesMap.circle,
      };

      const circleDynamicAttributes = {
        cx: size / 2,
        cy: size / 2,
        r: circleRadius,
      };

      return (
        <div className={containerClassName} style={containerDynamicStyle}>
          <Svg className={styles.svg} style={svgDynamicStyle}>
            <circle
              className={circleClassName}
              style={circleDynamicStyle}
              {...circleDynamicAttributes}
            />
          </Svg>

          {showText &&
            <span className={styles.progressText}>{progressText}</span>}
        </div>
      );
    };

    CircularIndicator.propTypes = {
      size: PropTypes.number.isRequired,
      progress: PropTypes.number.isRequired,
      initialProgress: PropTypes.number,
      showText: PropTypes.bool,
      strokeWidth: PropTypes.number,
      classNames: PropTypes.shape({
        container: PropTypes.string,
        circle: PropTypes.string,
      }),
      styles: PropTypes.shape({
        circle: PropTypes.object,
      }),
    };

    CircularIndicator.defaultProps = {
      initialProgress: 0,
      showText: false,
      strokeWidth: 2,
      classNames: {
        container: null,
        circle: null,
      },
      styles: {
        circle: {},
      },
    };

    export default CircularIndicator;