export function LineMarker()

in packages/charts/src/chart_types/xy_chart/renderer/dom/annotations/line_marker.tsx [53:177]


export function LineMarker({
  id,
  specId,
  datum,
  panel,
  marker: { icon, body, color, position, alignment, dimension },
  chartAreaRef,
  chartDimensions,
  onDOMElementEnter,
  onDOMElementLeave,
  onDOMElementClick,
  clickable,
  getHoverParams,
}: LineMarkerProps) {
  const { style, options } = getHoverParams(id);
  const iconRef = useRef<HTMLDivElement | null>(null);
  const testRef = useRef<HTMLDivElement | null>(null);
  const popper = useRef<Instance | null>(null);
  const markerStyle: CSSProperties = {
    ...style,
    ...getAnimatedStyles(options, style),
    color,
    top: chartDimensions.top + position.top + panel.top,
    left: chartDimensions.left + position.left + panel.left,
    cursor: clickable ? 'pointer' : DEFAULT_CSS_CURSOR,
  };

  const transform = { transform: getMarkerCentredTransform(alignment, Boolean(dimension)) };
  const setPopper = useCallback(() => {
    if (!iconRef.current || !testRef.current) return;

    popper.current = createPopper(iconRef.current, testRef.current, {
      strategy: 'absolute',
      placement: alignment,
      modifiers: [
        {
          name: 'offset',
          options: {
            offset: [0, 0],
          },
        },
        {
          name: 'preventOverflow',
          options: {
            boundary: chartAreaRef.current,
          },
        },
        {
          name: 'flip',
          options: {
            // prevents default flip modifier
            fallbackPlacements: [],
          },
        },
      ],
    });
  }, [chartAreaRef, alignment]);

  useEffect(() => {
    if (!popper.current && body) {
      setPopper();
    }

    return () => {
      popper?.current?.destroy?.();
      popper.current = null;
    };
  }, [setPopper, body]);

  void popper?.current?.update?.();

  const ariaLabel = datum.ariaLabel ?? datum.details ?? datum.header ?? `line annotation ${datum.dataValue}`;

  // want it to be tabbable if interactive if there is a click handler
  return clickable ? (
    <button
      className="echAnnotation__marker"
      onMouseEnter={() => {
        onDOMElementEnter({
          createdBySpecId: specId,
          id,
          type: DOMElementType.LineAnnotationMarker,
          datum,
        });
      }}
      onMouseLeave={() => onDOMElementLeave()}
      onClick={() => onDOMElementClick()}
      style={{ ...markerStyle, ...transform }}
      type="button"
      aria-label={ariaLabel}
    >
      <div ref={iconRef} className="echAnnotation__icon">
        {renderWithProps(icon, datum)}
      </div>
      {body && (
        <div ref={testRef} className="echAnnotation__body">
          {renderWithProps(body, datum)}
        </div>
      )}
    </button>
  ) : (
    <div
      className="echAnnotation__marker"
      onMouseEnter={() => {
        onDOMElementEnter({
          createdBySpecId: specId,
          id,
          type: DOMElementType.LineAnnotationMarker,
          datum,
        });
      }}
      onMouseLeave={() => onDOMElementLeave()}
      style={{ ...markerStyle, ...transform }}
    >
      <div ref={iconRef} className="echAnnotation__icon">
        {renderWithProps(icon, datum)}
      </div>
      {body && (
        <div ref={testRef} className="echAnnotation__body">
          {renderWithProps(body, datum)}
        </div>
      )}
    </div>
  );
}