wix-style-react
Version:
wix-style-react
79 lines • 3.55 kB
JavaScript
import React, { forwardRef, useCallback, useContext, useEffect, useImperativeHandle, useRef, useState, } from 'react';
import Popover from '../../Popover';
import { SidebarNextContext } from '../../SidebarNext/SidebarNextContext';
import { classes } from '../SidebarSubMenuNext.st.css';
export const ContextMenuPopover = forwardRef(({ element, content, disabled, dataHook, onShow, onHide }, ref) => {
const { skin, scrollAreaRef } = useContext(SidebarNextContext);
const popoverContentRef = useRef(null);
const [shouldShow, setShouldShow] = useState(false);
const visible = !disabled && shouldShow;
const showPopover = useCallback(() => {
setShouldShow(true);
}, []);
const hidePopover = useCallback(() => {
setShouldShow(false);
}, []);
useImperativeHandle(ref, () => ({
hide: hidePopover,
}), [hidePopover]);
const popoverOffset = usePopoverOffset(visible, scrollAreaRef, popoverContentRef);
return (React.createElement(Popover, { dataHook: dataHook, className: classes.navigationPopoverRoot, shown: visible, showArrow: true, fixed: true, appendTo: "window", placement: "right", zIndex: 3000, flip: false, theme: skin === 'neutral' ? 'light' : skin, moveBy: popoverOffset, animate: visible, hideDelay: 50, showDelay: 200, onMouseEnter: showPopover, onMouseLeave: hidePopover, onShow: onShow, onHide: onHide },
React.createElement(Popover.Element, null, element),
React.createElement(Popover.Content, null,
React.createElement("ul", { ref: popoverContentRef, className: classes.navigationPopover, "aria-hidden": true }, content))));
});
const usePopoverOffset = (popoverVisible, scrollAreaRef, popoverContentRef) => {
// FIXME: doesn't work in the original implementation (and here too)
const [moveBy, setMoveBy] = useState({ y: 0 });
useEffect(() => {
const scrollArea = scrollAreaRef?.current;
if (!scrollArea) {
return;
}
const handleScroll = () => {
if (!popoverVisible) {
setMoveBy({ y: 0 });
}
};
scrollArea && scrollArea.addEventListener('scroll', handleScroll);
window.addEventListener('scroll', handleScroll);
return () => {
scrollArea && scrollArea.removeEventListener('scroll', handleScroll);
window.removeEventListener('scroll', handleScroll);
};
// eslint-disable-next-line react-hooks/exhaustive-deps
}, [scrollAreaRef]);
useEffect(() => {
if (!popoverVisible) {
return;
}
const timeout = setTimeout(() => {
const y = moveBy.y || calculateOffsetY(popoverContentRef.current);
setMoveBy({ y });
}, 200);
return () => {
clearTimeout(timeout);
};
}, [popoverVisible, moveBy.y, popoverContentRef]);
return moveBy;
};
const calculateOffsetY = (popoverContentElement) => {
// FIXME: mostly copy-pasta of original implementation
const rect = popoverContentElement?.getBoundingClientRect();
if (!rect) {
return 0;
}
const margin = 12;
const popoverPaddings = 2 * 12;
const screenHeight = window.innerHeight;
const { top } = rect;
const height = rect.height + popoverPaddings;
if (top <= margin) {
return -(top - popoverPaddings - margin);
}
if (top + height > screenHeight) {
return screenHeight - top - height - margin;
}
return 0;
};
//# sourceMappingURL=ContextMenuPopover.js.map