All files / src/components/LineChart/eventAnnotation LabelLink.tsx

21.42% Statements 6/28
0% Branches 0/16
0% Functions 0/6
25% Lines 5/20

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 9022x 22x   22x   22x                                               22x                                                                                                                        
import * as React from 'react';
import { Callout, FocusZone, FocusZoneDirection, List } from '@fluentui/react';
import { IEventAnnotation } from '../../../types/IEventAnnotation';
import { Textbox } from './Textbox';
import { ITheme } from '@fluentui/react/lib/Styling';
import { getColorFromToken } from '../../../utilities/colors';
 
export interface ILineDef extends IEventAnnotation {
  x: number;
}
 
export interface ILabelDef {
  x: number;
  aggregatedIdx: number[];
  anchor: 'start' | 'end';
}
 
interface ILabelLinkProps {
  lineDefs: ILineDef[];
  labelDef: ILabelDef;
  textY: number;
  textWidth: number;
  textLineHeight: number;
  textFontSize: string;
  textColor: string | undefined;
  theme: ITheme | undefined;
  mergedLabel: (count: number) => string;
}
 
export const LabelLink: React.FunctionComponent<ILabelLinkProps> = props => {
  const gRef = React.useRef<SVGGElement>(null);
  const [showCard, setShowCard] = React.useState(false);
  const onDismiss = () => setShowCard(false);
  const onClick = () => setShowCard(true);
  const onRenderCell = (i: (() => React.ReactNode) | undefined) => <div data-is-focusable={true}>{i && i()}</div>;
 
  let callout: React.ReactNode = null;
  Iif (showCard) {
    const cards = props.labelDef.aggregatedIdx.map(i => props.lineDefs[i].onRenderCard!).filter(c => !!c);
    Iif (cards.length > 0) {
      callout = (
        <Callout
          target={gRef.current}
          // eslint-disable-next-line react/jsx-no-bind
          onDismiss={onDismiss}
          setInitialFocus={true}
          role="dialog"
        >
          <FocusZone isCircularNavigation={true} direction={FocusZoneDirection.vertical}>
            <List<() => React.ReactNode>
              items={cards}
              // eslint-disable-next-line react/jsx-no-bind
              onRenderCell={onRenderCell}
            />
          </FocusZone>
        </Callout>
      );
    }
  }
 
  let text: string;
  const fill: string | undefined = props.textColor
    ? getColorFromToken(props.textColor, props.theme?.isInverted)
    : props.theme?.semanticColors.messageText;
 
  if (props.labelDef.aggregatedIdx.length === 1) {
    text = props.lineDefs[props.labelDef.aggregatedIdx[0]].event;
  } else {
    text = props.mergedLabel(props.labelDef.aggregatedIdx.length);
  }
 
  return (
    <>
      <g ref={gRef} onClick={onClick} data-is-focusable={false} style={{ cursor: 'pointer' }}>
        <Textbox
          text={text}
          x={props.labelDef.x}
          y={props.textY}
          width={props.textWidth}
          lineHeight={props.textLineHeight}
          textAnchor={props.labelDef.anchor}
          fontSize={props.textFontSize}
          fill={fill}
        />
      </g>
      {callout}
    </>
  );
};