import React from "react";
import { isHtmlElement } from "../../util/dom";
const SCREEN_PADDING = 16;
export interface Props {
screenLeft: number;
screenTop: number;
}
export class CenteredAtPoint extends React.Component {
private offsetParent: HTMLElement | undefined | null;
private span: HTMLSpanElement | undefined | null;
public componentWillUpdate() {
this.span!.style.marginLeft = null;
}
public componentDidUpdate() {
this.updatePositionStyle();
}
public render() {
return (
{this.props.children}
);
}
private updatePositionStyle() {
if (this.offsetParent != null && this.span != null && typeof window !== "undefined") {
this.span.style.top = `${window.scrollY + this.props.screenTop - this.offsetParent.offsetTop}px`;
this.span.style.left = `${window.scrollX + this.props.screenLeft - this.offsetParent.offsetLeft}px`;
const boundingClientRect = this.span.getBoundingClientRect();
if (boundingClientRect.left < SCREEN_PADDING) {
this.span.style.marginLeft = `${0 - boundingClientRect.left + SCREEN_PADDING}px`;
}
}
}
private readonly handleRef = (span: HTMLSpanElement | null) => {
this.span = span;
if (span !== null) {
this.offsetParent = this.findOffsetParent(span);
this.updatePositionStyle();
} else {
this.offsetParent = null;
}
};
private findOffsetParent(domNode: Element | null): HTMLElement | null {
if (domNode !== null && isHtmlElement(domNode)) {
const { offsetParent } = domNode;
if (isHtmlElement(offsetParent)) {
return offsetParent;
}
}
return null;
}
}