@grafana/ui
Version:
Grafana Components Library
100 lines (97 loc) • 3.16 kB
JavaScript
import { jsx } from 'react/jsx-runtime';
import { cx, css } from '@emotion/css';
import { useRef, useState, useMemo, useLayoutEffect } from 'react';
import { useWindowSize } from 'react-use';
import '@grafana/data';
import { useStyles2 } from '../../themes/ThemeContext.mjs';
import 'micro-memoize';
import '@emotion/react';
import { getTooltipContainerStyles } from '../../themes/mixins.mjs';
import '../../utils/skeleton.mjs';
import { calculateTooltipPosition } from './utils.mjs';
const VizTooltipContainer = ({
position: { x: positionX, y: positionY },
offset: { x: offsetX, y: offsetY },
children,
allowPointerEvents = false,
className,
...otherProps
}) => {
const tooltipRef = useRef(null);
const [tooltipMeasurement, setTooltipMeasurement] = useState({ width: 0, height: 0 });
const { width, height } = useWindowSize();
const [placement, setPlacement] = useState({
x: positionX + offsetX,
y: positionY + offsetY
});
const resizeObserver = useMemo(
() => (
// TS has hard time playing games with @types/resize-observer-browser, hence the ignore
// @ts-ignore
new ResizeObserver((entries) => {
for (let entry of entries) {
const tW = Math.floor(entry.contentRect.width + 2 * 8);
const tH = Math.floor(entry.contentRect.height + 2 * 8);
if (tooltipMeasurement.width !== tW || tooltipMeasurement.height !== tH) {
setTooltipMeasurement({
width: Math.min(tW, width),
height: Math.min(tH, height)
});
}
}
})
),
[tooltipMeasurement, width, height]
);
useLayoutEffect(() => {
if (tooltipRef.current) {
resizeObserver.observe(tooltipRef.current);
}
return () => {
resizeObserver.disconnect();
};
}, [resizeObserver]);
useLayoutEffect(() => {
if (tooltipRef && tooltipRef.current) {
const { x, y } = calculateTooltipPosition(
positionX,
positionY,
tooltipMeasurement.width,
tooltipMeasurement.height,
offsetX,
offsetY,
width,
height
);
setPlacement({ x, y });
}
}, [width, height, positionX, offsetX, positionY, offsetY, tooltipMeasurement]);
const styles = useStyles2(getStyles);
return /* @__PURE__ */ jsx(
"div",
{
ref: tooltipRef,
style: {
position: "fixed",
left: 0,
// disabling pointer-events is to prevent the tooltip from flickering when moving left to right
// see e.g. https://github.com/grafana/grafana/pull/33609
pointerEvents: allowPointerEvents ? "auto" : "none",
top: 0,
transform: `translate(${placement.x}px, ${placement.y}px)`,
transition: "transform ease-out 0.1s"
},
"aria-live": "polite",
"aria-atomic": "true",
...otherProps,
className: cx(styles.wrapper, className),
children
}
);
};
VizTooltipContainer.displayName = "VizTooltipContainer";
const getStyles = (theme) => ({
wrapper: css(getTooltipContainerStyles(theme))
});
export { VizTooltipContainer };
//# sourceMappingURL=VizTooltipContainer.mjs.map