All files / src/components/PieChart/Arc Arc.tsx

94.54% Statements 52/55
75% Branches 57/76
76.92% Functions 10/13
93.02% Lines 40/43

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 113 114 115 116 117 118 119 12024x 24x   24x 24x 24x 24x 24x   24x 24x           24x 60x 60x       48x 48x       48x     48x       60x 60x 60x 60x   60x                 48x       48x     24x   24x 48x     48x 48x     60x 60x 60x   60x               60x 60x   60x   60x   60x                                                         24x     60x 60x    
import * as React from 'react';
import { arc as d3Arc } from 'd3-shape';
import { IArcProps, IArcState, IArcStyles } from './Arc.types';
import { classNamesFunction, getId, getRTL } from '@fluentui/react/lib/Utilities';
import { getStyles } from './Arc.styles';
import { wrapContent } from '../../../utilities/utilities';
import { SVGTooltipText } from '../../../utilities/SVGTooltipText';
import { convertToLocaleString } from '../../../utilities/locale-util';
 
export class Arc extends React.Component<IArcProps, IArcState> {
  public static defaultProps: Partial<IArcProps> = {
    arc: d3Arc(),
  };
 
  protected _arcId: string;
 
  public static getDerivedStateFromProps(nextProps: Readonly<IArcProps>): null {
    _updateChart(nextProps);
    return null;
  }
 
  public constructor(props: IArcProps) {
    super(props);
    this.state = {
      isArcFocused: false,
    };
 
    this._arcId = getId('piechart_arc');
  }
 
  public updateChart = (newProps: IArcProps) => {
    _updateChart(newProps);
  };
 
  public render(): JSX.Element {
    const { arc } = this.props;
    const getClassNames = classNamesFunction<IArcProps, IArcStyles>();
    const classNames = getClassNames(props => getStyles(props, this.props.theme), { ...this.props });
 
    return (
      <path
        d={arc(this.props.data)}
        className={`${this.state.isArcFocused ? classNames.arcRootFocussed : classNames.arcRoot}`}
        onClick={this.props.data?.data.onClick}
      />
    );
  }
 
  protected _onFocus = () => {
    this.setState({ isArcFocused: true });
  };
 
  protected _onBlur = () => {
    this.setState({ isArcFocused: false });
  };
}
 
export class LabeledArc extends Arc {
  private _isRTL = getRTL();
 
  public constructor(props: IArcProps) {
    super(props);
    this._arcId = getId('piechart_arc');
  }
 
  public render(): JSX.Element {
    const { data, culture } = this.props;
    const gap = 4;
    // placing the labels on the outside arc
    const [labelX, labelY] = d3Arc().centroid({
      endAngle: data?.endAngle || 0,
      startAngle: data?.startAngle || 0,
      padAngle: data?.padAngle,
      innerRadius: this.props?.outerRadius || 0,
      outerRadius: this.props?.outerRadius || 0 + gap,
    });
 
    const getClassNames = classNamesFunction<IArcProps, IArcStyles>();
    const classNames = getClassNames(props => getStyles(props, this.props.theme));
 
    const angle = ((data?.startAngle || 0) + (data?.endAngle || 0)) / 2;
 
    const content = `${data?.data.x}-${convertToLocaleString(data?.data.y, culture)}`;
 
    return (
      <g
        className={`${classNames.arc} arc`}
        data-is-focusable={true}
        id={this._arcId}
        onFocus={this._onFocus}
        onBlur={this._onBlur}
        aria-label={content}
        role="img"
      >
        {super.render()}
        <SVGTooltipText
          content={content}
          textProps={{
            x: labelX,
            y: labelY,
            dominantBaseline: angle > Math.PI / 2 && angle < (3 * Math.PI) / 2 ? 'hanging' : 'auto',
            textAnchor: (!this._isRTL && angle > Math.PI) || (this._isRTL && angle < Math.PI) ? 'end' : 'start',
            'aria-label': `${data?.data.x}-${convertToLocaleString(data?.data.y, culture)}`,
            className: classNames.arcText,
          }}
          isTooltipVisibleProp={this.state.isArcFocused}
          shouldReceiveFocus={false}
          maxWidth={40}
          wrapContent={wrapContent}
        />
      </g>
    );
  }
}
 
function _updateChart(newProps: IArcProps): void {
  newProps.arc.innerRadius(newProps.innerRadius);
  newProps.arc.outerRadius(newProps.outerRadius);
}