| 10 | const TOOLTIP_TEXT = '#fff'; |
| 11 | |
| 12 | export const Tooltip = ({ |
| 13 | point, |
| 14 | width, |
| 15 | height, |
| 16 | plotFrame, |
| 17 | titles: [xTitle, yTitle], |
| 18 | }: { |
| 19 | readonly point: ScaledPoint | undefined; |
| 20 | readonly width: number; |
| 21 | readonly height: number; |
| 22 | readonly plotFrame: PlotFrame; |
| 23 | readonly titles: readonly [xTitle: string, yTitle: string]; |
| 24 | }) => { |
| 25 | if (isNullish(point)) { |
| 26 | return null; |
| 27 | } |
| 28 | |
| 29 | const [, xValue, yValue, x, y, pointXTitle, pointYTitle] = point; |
| 30 | const [plotX, plotY] = plotFrame; |
| 31 | const tooltipX = |
| 32 | x + TOOLTIP_GAP + TOOLTIP_WIDTH > width |
| 33 | ? x - TOOLTIP_GAP - TOOLTIP_WIDTH |
| 34 | : x + TOOLTIP_GAP; |
| 35 | const tooltipY = mathMax( |
| 36 | mathMin(y - TOOLTIP_GAP - TOOLTIP_HEIGHT, height - TOOLTIP_HEIGHT), |
| 37 | 0, |
| 38 | ); |
| 39 | |
| 40 | return ( |
| 41 | <> |
| 42 | <path |
| 43 | className="tooltip-lines" |
| 44 | pointerEvents="none" |
| 45 | stroke={CURRENT_COLOR} |
| 46 | strokeOpacity={0.25} |
| 47 | strokeWidth={1} |
| 48 | d={`M${plotX + x},${plotY}v${height}M${plotX},${plotY + y}h${width}`} |
| 49 | /> |
| 50 | <g |
| 51 | className="tooltip" |
| 52 | transform={`translate(${plotX + tooltipX} ${plotY + tooltipY})`} |
| 53 | fontFamily="sans-serif" |
| 54 | fontWeight={600} |
| 55 | pointerEvents="none" |
| 56 | > |
| 57 | <rect |
| 58 | fill={TOOLTIP_BACKGROUND} |
| 59 | fillOpacity={0.9} |
| 60 | width={TOOLTIP_WIDTH} |
| 61 | height={TOOLTIP_HEIGHT} |
| 62 | rx={6} |
| 63 | /> |
| 64 | <text fill={TOOLTIP_TEXT} x={TOOLTIP_PADDING} y={22}> |
| 65 | {pointXTitle ?? xTitle}: {string(xValue)} |
| 66 | </text> |
| 67 | <text fill={TOOLTIP_TEXT} x={TOOLTIP_PADDING} y={46}> |
| 68 | {pointYTitle ?? yTitle}: {yValue} |
| 69 | </text> |