whisper-money/resources/js/lib/chart-tooltip-position.ts

54 lines
1.5 KiB
TypeScript

export interface TooltipPositionInput {
/** Cursor x in viewport coordinates. */
cx: number;
/** Cursor y in viewport coordinates. */
cy: number;
/** Measured tooltip width. */
tipW: number;
/** Measured tooltip height. */
tipH: number;
/** Gap between the cursor and the tooltip. */
offset: number;
/** Viewport width (window.innerWidth). */
viewportW: number;
/** Viewport height (window.innerHeight). */
viewportH: number;
}
/**
* Computes the fixed-position coordinates for the chart tooltip, flipping it to
* the opposite side of the cursor when it would overflow the viewport and
* clamping it to an 8px margin. The result is rounded to whole pixels so that
* sub-pixel jitter from `getBoundingClientRect` collapses to the same
* coordinate. (The effect's dependency array in chart.tsx is what actually
* stops the render loop; rounding only reduces how often the equality guard is
* defeated by a fractional difference.)
*/
export function computeTooltipPosition({
cx,
cy,
tipW,
tipH,
offset,
viewportW,
viewportH,
}: TooltipPositionInput): { x: number; y: number } {
let x = cx + offset;
let y = cy + offset;
if (x + tipW > viewportW - 8) {
x = cx - tipW - offset;
}
if (y + tipH > viewportH - 8) {
y = cy - tipH - offset;
}
if (x < 8) {
x = 8;
}
if (y < 8) {
y = 8;
}
return { x: Math.round(x), y: Math.round(y) };
}