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

34.54% Statements 19/55
0% Branches 0/76
15.38% Functions 2/13
34.88% Lines 15/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 1202x 2x   2x 2x 2x 2x 2x   2x 2x           2x                                   2x                                         2x   2x               2x                                                                                               2x            
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);
}