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 | 1x 1x 1x 1x 1x 1x 1x 13x 13x 13x 13x 13x 13x 13x 13x 13x 13x 13x 13x 13x 13x 13x 13x 13x 13x 13x 13x 13x 13x 13x 13x 13x 13x 4x 4x 13x 13x 13x 13x 13x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x | import * as React from "react"
import { observable, computed, action } from "mobx"
import { observer } from "mobx-react"
import { Bounds } from "../../clientUtils/Bounds"
import { TooltipProps, TooltipManager } from "./TooltipProps"
 
@observer
export class TooltipView extends React.Component<{
    tooltipProvider: TooltipManager
    width: number
    height: number
}> {
    @computed private get rendered() {
        const { bounds } = this
        const tooltipProvider = this.props.tooltipProvider
 
        if (!tooltipProvider.tooltip) return null
        const tooltip = tooltipProvider.tooltip
        const offsetX = tooltip.offsetX ?? 0
        let offsetY = tooltip.offsetY ?? 0
        if (tooltip.offsetYDirection === "upward") {
            offsetY = -offsetY - (bounds?.height ?? 0)
        }
        let x = tooltip.x + offsetX
        let y = tooltip.y + offsetY
        // Ensure tooltip remains inside chart
        if (bounds) {
            if (x + bounds.width > this.props.width)
                x -= bounds.width + 2 * offsetX
            if (y + bounds.height > this.props.height)
                y -= bounds.height + 2 * offsetY
            if (x < 0) x = 0
            if (y < 0) y = 0
        }
        const tooltipStyle: React.CSSProperties = {
            position: "absolute",
            pointerEvents: "none",
            left: `${x}px`,
            top: `${y}px`,
            whiteSpace: "nowrap",
            backgroundColor: "rgba(255,255,255,0.92)",
            boxShadow: "0 2px 2px rgba(0,0,0,.12), 0 0 1px rgba(0,0,0,.35)",
            borderRadius: "2px",
            textAlign: "left",
            fontSize: "0.9em",
        }
        return (
            <div
                ref={this.base}
                className="Tooltip"
                style={{ ...tooltipStyle, ...tooltip.style }}
            >
                {tooltip.children}
            </div>
        )
    }
 
    private base: React.RefObject<HTMLDivElement> = React.createRef()
 
    @observable.struct private bounds?: Bounds
    @action.bound private updateBounds(): void {
        if (this.base.current)
            this.bounds = Bounds.fromElement(this.base.current)
    }
 
    componentDidMount(): void {
        this.updateBounds()
    }
 
    componentDidUpdate(): void {
        this.updateBounds()
    }
 
    render(): JSX.Element | null {
        return this.rendered
    }
}
 
@observer
export class Tooltip extends React.Component<TooltipProps> {
    componentDidMount(): void {
        this.connectTooltipToContainer()
    }
 
    @action.bound private connectTooltipToContainer(): void {
        this.props.tooltipManager.tooltip = this.props
    }
 
    @action.bound private removeToolTipFromContainer(): void {
        this.props.tooltipManager.tooltip = undefined
    }
 
    componentDidUpdate(): void {
        this.connectTooltipToContainer()
    }
 
    componentWillUnmount(): void {
        this.removeToolTipFromContainer()
    }
 
    render(): null {
        return null
    }
}
  |