in packages/charts/src/chart_types/xy_chart/renderer/dom/annotations/line_marker.tsx [53:177]
export function LineMarker({
id,
specId,
datum,
panel,
marker: { icon, body, color, position, alignment, dimension },
chartAreaRef,
chartDimensions,
onDOMElementEnter,
onDOMElementLeave,
onDOMElementClick,
clickable,
getHoverParams,
}: LineMarkerProps) {
const { style, options } = getHoverParams(id);
const iconRef = useRef<HTMLDivElement | null>(null);
const testRef = useRef<HTMLDivElement | null>(null);
const popper = useRef<Instance | null>(null);
const markerStyle: CSSProperties = {
...style,
...getAnimatedStyles(options, style),
color,
top: chartDimensions.top + position.top + panel.top,
left: chartDimensions.left + position.left + panel.left,
cursor: clickable ? 'pointer' : DEFAULT_CSS_CURSOR,
};
const transform = { transform: getMarkerCentredTransform(alignment, Boolean(dimension)) };
const setPopper = useCallback(() => {
if (!iconRef.current || !testRef.current) return;
popper.current = createPopper(iconRef.current, testRef.current, {
strategy: 'absolute',
placement: alignment,
modifiers: [
{
name: 'offset',
options: {
offset: [0, 0],
},
},
{
name: 'preventOverflow',
options: {
boundary: chartAreaRef.current,
},
},
{
name: 'flip',
options: {
// prevents default flip modifier
fallbackPlacements: [],
},
},
],
});
}, [chartAreaRef, alignment]);
useEffect(() => {
if (!popper.current && body) {
setPopper();
}
return () => {
popper?.current?.destroy?.();
popper.current = null;
};
}, [setPopper, body]);
void popper?.current?.update?.();
const ariaLabel = datum.ariaLabel ?? datum.details ?? datum.header ?? `line annotation ${datum.dataValue}`;
// want it to be tabbable if interactive if there is a click handler
return clickable ? (
<button
className="echAnnotation__marker"
onMouseEnter={() => {
onDOMElementEnter({
createdBySpecId: specId,
id,
type: DOMElementType.LineAnnotationMarker,
datum,
});
}}
onMouseLeave={() => onDOMElementLeave()}
onClick={() => onDOMElementClick()}
style={{ ...markerStyle, ...transform }}
type="button"
aria-label={ariaLabel}
>
<div ref={iconRef} className="echAnnotation__icon">
{renderWithProps(icon, datum)}
</div>
{body && (
<div ref={testRef} className="echAnnotation__body">
{renderWithProps(body, datum)}
</div>
)}
</button>
) : (
<div
className="echAnnotation__marker"
onMouseEnter={() => {
onDOMElementEnter({
createdBySpecId: specId,
id,
type: DOMElementType.LineAnnotationMarker,
datum,
});
}}
onMouseLeave={() => onDOMElementLeave()}
style={{ ...markerStyle, ...transform }}
>
<div ref={iconRef} className="echAnnotation__icon">
{renderWithProps(icon, datum)}
</div>
{body && (
<div ref={testRef} className="echAnnotation__body">
{renderWithProps(body, datum)}
</div>
)}
</div>
);
}