_drawSingleReactMeasure(
    context: CanvasRenderingContext2D,
    rect: Rect,
    measure: ReactMeasure,
    nextMeasure: ReactMeasure | null,
    baseY: number,
    scaleFactor: number,
    showGroupHighlight: boolean,
    showHoverHighlight: boolean,
  ): void {
    const {frame, visibleArea} = this;
    const {timestamp, type, duration} = measure;

    let fillStyle = null;
    let hoveredFillStyle = null;
    let groupSelectedFillStyle = null;
    let textFillStyle = null;

    // We could change the max to 0 and just skip over rendering anything that small,
    // but this has the effect of making the chart look very empty when zoomed out.
    // So long as perf is okay- it might be best to err on the side of showing things.
    const width = durationToWidth(duration, scaleFactor);
    if (width <= 0) {
      return; // Too small to render at this zoom level
    }

    const x = timestampToPosition(timestamp, scaleFactor, frame);
    const measureRect: Rect = {
      origin: {x, y: baseY},
      size: {width, height: REACT_MEASURE_HEIGHT},
    };
    if (!rectIntersectsRect(measureRect, rect)) {
      return; // Not in view
    }

    const drawableRect = intersectionOfRects(measureRect, rect);
    let textRect = measureRect;

    switch (type) {
      case 'commit':
        fillStyle = COLORS.REACT_COMMIT;
        hoveredFillStyle = COLORS.REACT_COMMIT_HOVER;
        groupSelectedFillStyle = COLORS.REACT_COMMIT_HOVER;
        textFillStyle = COLORS.REACT_COMMIT_TEXT;

        // Commit phase rects are overlapped by layout and passive rects,
        // and it looks bad if text flows underneath/behind these overlayed rects.
        if (nextMeasure != null) {
          // This clipping shouldn't apply for measures that don't overlap though,
          // like passive effects that are processed after a delay,
          // or if there are now layout or passive effects and the next measure is render or idle.
          if (nextMeasure.timestamp < measure.timestamp + measure.duration) {
            textRect = {
              ...measureRect,
              size: {
                width:
                  timestampToPosition(
                    nextMeasure.timestamp,
                    scaleFactor,
                    frame,
                  ) - x,
                height: REACT_MEASURE_HEIGHT,
              },
            };
          }
        }
        break;
      case 'render-idle':
        // We could render idle time as diagonal hashes.
        // This looks nicer when zoomed in, but not so nice when zoomed out.
        // color = context.createPattern(getIdlePattern(), 'repeat');
        fillStyle = COLORS.REACT_IDLE;
        hoveredFillStyle = COLORS.REACT_IDLE_HOVER;
        groupSelectedFillStyle = COLORS.REACT_IDLE_HOVER;
        break;
      case 'render':
        fillStyle = COLORS.REACT_RENDER;
        hoveredFillStyle = COLORS.REACT_RENDER_HOVER;
        groupSelectedFillStyle = COLORS.REACT_RENDER_HOVER;
        textFillStyle = COLORS.REACT_RENDER_TEXT;
        break;
      case 'layout-effects':
        fillStyle = COLORS.REACT_LAYOUT_EFFECTS;
        hoveredFillStyle = COLORS.REACT_LAYOUT_EFFECTS_HOVER;
        groupSelectedFillStyle = COLORS.REACT_LAYOUT_EFFECTS_HOVER;
        textFillStyle = COLORS.REACT_LAYOUT_EFFECTS_TEXT;
        break;
      case 'passive-effects':
        fillStyle = COLORS.REACT_PASSIVE_EFFECTS;
        hoveredFillStyle = COLORS.REACT_PASSIVE_EFFECTS_HOVER;
        groupSelectedFillStyle = COLORS.REACT_PASSIVE_EFFECTS_HOVER;
        textFillStyle = COLORS.REACT_PASSIVE_EFFECTS_TEXT;
        break;
      default:
        throw new Error(`Unexpected measure type "${type}"`);
    }

    context.fillStyle = showHoverHighlight
      ? hoveredFillStyle
      : showGroupHighlight
        ? groupSelectedFillStyle
        : fillStyle;
    context.fillRect(
      drawableRect.origin.x,
      drawableRect.origin.y,
      drawableRect.size.width,
      drawableRect.size.height,
    );

    if (textFillStyle !== null) {
      drawText(formatDuration(duration), context, textRect, visibleArea, {
        fillStyle: textFillStyle,
      });
    }
  }
Draw a single `ReactMeasure` as a bar in the canvas.