2019-10-21 11:40:24 +00:00
|
|
|
import React, { useRef, useEffect } from "react";
|
|
|
|
|
import styled from "styled-components";
|
|
|
|
|
import { createPortal } from "react-dom";
|
2020-06-04 13:49:22 +00:00
|
|
|
import PopperJS, { Placement, PopperOptions } from "popper.js";
|
|
|
|
|
|
2019-10-21 11:40:24 +00:00
|
|
|
type PopperProps = {
|
2020-06-04 13:49:22 +00:00
|
|
|
zIndex: number;
|
2019-10-21 11:40:24 +00:00
|
|
|
isOpen: boolean;
|
2020-01-02 12:42:02 +00:00
|
|
|
targetNode?: Element;
|
2019-10-21 11:40:24 +00:00
|
|
|
children: JSX.Element;
|
2020-06-04 13:49:22 +00:00
|
|
|
placement: Placement;
|
|
|
|
|
modifiers?: Partial<PopperOptions["modifiers"]>;
|
2019-10-21 11:40:24 +00:00
|
|
|
};
|
|
|
|
|
|
2020-06-04 13:49:22 +00:00
|
|
|
const PopperWrapper = styled.div<{ zIndex: number }>`
|
2020-12-24 04:32:25 +00:00
|
|
|
z-index: ${(props) => props.zIndex};
|
2019-10-21 11:40:24 +00:00
|
|
|
position: absolute;
|
|
|
|
|
`;
|
|
|
|
|
|
|
|
|
|
/* eslint-disable react/display-name */
|
|
|
|
|
export default (props: PopperProps) => {
|
|
|
|
|
const contentRef = useRef(null);
|
|
|
|
|
useEffect(() => {
|
2020-01-02 12:42:02 +00:00
|
|
|
const parentElement = props.targetNode && props.targetNode.parentElement;
|
2019-12-27 10:10:04 +00:00
|
|
|
if (
|
|
|
|
|
parentElement &&
|
|
|
|
|
parentElement.parentElement &&
|
2020-01-02 12:42:02 +00:00
|
|
|
props.targetNode &&
|
2019-12-27 10:10:04 +00:00
|
|
|
props.isOpen
|
|
|
|
|
) {
|
2020-01-08 04:11:23 +00:00
|
|
|
// TODO: To further optimize this, we can go through the popper API
|
|
|
|
|
// and figure out a way to keep an app instance level popper instance
|
|
|
|
|
// which we can update to have different references when called here.
|
|
|
|
|
// However, the performance benefit gained by such an optimization
|
|
|
|
|
// remaines to be discovered.
|
2020-01-07 12:28:58 +00:00
|
|
|
const _popper = new PopperJS(
|
2020-01-02 12:42:02 +00:00
|
|
|
props.targetNode,
|
Property Pane Controls
- Fixes #121, #122, #123, #124, #90, #46, #65, #100, #101, #68, #102
2019-10-24 05:24:45 +00:00
|
|
|
(contentRef.current as unknown) as Element,
|
|
|
|
|
{
|
2020-06-04 13:49:22 +00:00
|
|
|
placement: props.placement,
|
Property Pane Controls
- Fixes #121, #122, #123, #124, #90, #46, #65, #100, #101, #68, #102
2019-10-24 05:24:45 +00:00
|
|
|
modifiers: {
|
|
|
|
|
flip: {
|
|
|
|
|
behavior: ["right", "left", "bottom", "top"],
|
|
|
|
|
},
|
|
|
|
|
keepTogether: {
|
|
|
|
|
enabled: false,
|
|
|
|
|
},
|
|
|
|
|
arrow: {
|
|
|
|
|
enabled: false,
|
|
|
|
|
},
|
2020-01-15 04:49:36 +00:00
|
|
|
preventOverflow: {
|
|
|
|
|
enabled: true,
|
|
|
|
|
boundariesElement: "viewport",
|
|
|
|
|
},
|
2020-06-04 13:49:22 +00:00
|
|
|
...props.modifiers,
|
2019-10-21 11:40:24 +00:00
|
|
|
},
|
|
|
|
|
},
|
Property Pane Controls
- Fixes #121, #122, #123, #124, #90, #46, #65, #100, #101, #68, #102
2019-10-24 05:24:45 +00:00
|
|
|
);
|
2020-01-07 12:28:58 +00:00
|
|
|
return () => {
|
|
|
|
|
_popper.destroy();
|
|
|
|
|
};
|
Property Pane Controls
- Fixes #121, #122, #123, #124, #90, #46, #65, #100, #101, #68, #102
2019-10-24 05:24:45 +00:00
|
|
|
}
|
2020-06-04 13:49:22 +00:00
|
|
|
}, [props.targetNode, props.isOpen, props.modifiers, props.placement]);
|
2019-10-21 11:40:24 +00:00
|
|
|
return createPortal(
|
2020-06-04 13:49:22 +00:00
|
|
|
<PopperWrapper ref={contentRef} zIndex={props.zIndex}>
|
|
|
|
|
{props.children}
|
|
|
|
|
</PopperWrapper>,
|
2019-10-21 11:40:24 +00:00
|
|
|
document.body,
|
|
|
|
|
);
|
|
|
|
|
};
|