UI - МЕЖПРОЕКТНАЯ КОММУНИКАЦИЯ: исправление слоя превью вложений
This commit is contained in:
parent
0be8f01283
commit
3dd99491a4
|
|
@ -6,11 +6,27 @@
|
|||
|
||||
import { Dialog, Transition } from "@headlessui/react";
|
||||
import React, { Fragment } from "react";
|
||||
import { createPortal } from "react-dom";
|
||||
// constants
|
||||
import { cn } from "../utils";
|
||||
import { EModalPosition, EModalWidth } from "./constants";
|
||||
// helpers
|
||||
|
||||
const MODAL_PORTAL_ID = "nodedc-modal-portal";
|
||||
|
||||
const ensureModalPortalRoot = () => {
|
||||
if (typeof document === "undefined") return null;
|
||||
|
||||
const existingPortalRoot = document.getElementById(MODAL_PORTAL_ID);
|
||||
if (existingPortalRoot) return existingPortalRoot;
|
||||
|
||||
const portalRoot = document.createElement("div");
|
||||
portalRoot.id = MODAL_PORTAL_ID;
|
||||
document.body.appendChild(portalRoot);
|
||||
|
||||
return portalRoot;
|
||||
};
|
||||
|
||||
type Props = {
|
||||
children: React.ReactNode;
|
||||
handleClose?: () => void;
|
||||
|
|
@ -29,9 +45,41 @@ export function ModalCore(props: Props) {
|
|||
className = "",
|
||||
} = props;
|
||||
|
||||
return (
|
||||
const [portalRoot, setPortalRoot] = React.useState<HTMLElement | null>(null);
|
||||
const skipNextCloseRef = React.useRef(false);
|
||||
const skipNextCloseTimeoutRef = React.useRef<ReturnType<typeof setTimeout> | null>(null);
|
||||
|
||||
React.useEffect(() => {
|
||||
setPortalRoot(ensureModalPortalRoot());
|
||||
|
||||
return () => {
|
||||
if (skipNextCloseTimeoutRef.current) clearTimeout(skipNextCloseTimeoutRef.current);
|
||||
};
|
||||
}, []);
|
||||
|
||||
const guardContextMenuClose = () => {
|
||||
skipNextCloseRef.current = true;
|
||||
|
||||
if (skipNextCloseTimeoutRef.current) clearTimeout(skipNextCloseTimeoutRef.current);
|
||||
|
||||
skipNextCloseTimeoutRef.current = setTimeout(() => {
|
||||
skipNextCloseRef.current = false;
|
||||
skipNextCloseTimeoutRef.current = null;
|
||||
}, 300);
|
||||
};
|
||||
|
||||
const handleDialogClose = () => {
|
||||
if (skipNextCloseRef.current) {
|
||||
skipNextCloseRef.current = false;
|
||||
return;
|
||||
}
|
||||
|
||||
handleClose?.();
|
||||
};
|
||||
|
||||
const modal = (
|
||||
<Transition.Root show={isOpen} as={Fragment}>
|
||||
<Dialog as="div" className="relative z-30" onClose={() => handleClose && handleClose()}>
|
||||
<Dialog as="div" className="relative z-[180]" data-prevent-outside-click onClose={handleDialogClose}>
|
||||
<Transition.Child
|
||||
as={Fragment}
|
||||
enter="ease-out duration-300"
|
||||
|
|
@ -56,6 +104,16 @@ export function ModalCore(props: Props) {
|
|||
leaveTo="opacity-0 translate-y-4 sm:translate-y-0 sm:scale-95"
|
||||
>
|
||||
<Dialog.Panel
|
||||
onContextMenuCapture={(event) => {
|
||||
event.stopPropagation();
|
||||
guardContextMenuClose();
|
||||
}}
|
||||
onPointerDownCapture={(event) => {
|
||||
if (event.button === 2) {
|
||||
event.stopPropagation();
|
||||
guardContextMenuClose();
|
||||
}
|
||||
}}
|
||||
className={cn(
|
||||
"nodedc-glass-modal relative w-full transform rounded-[28px] text-left transition-all",
|
||||
width,
|
||||
|
|
@ -70,4 +128,8 @@ export function ModalCore(props: Props) {
|
|||
</Dialog>
|
||||
</Transition.Root>
|
||||
);
|
||||
|
||||
if (typeof document !== "undefined" && !portalRoot) return null;
|
||||
|
||||
return portalRoot ? createPortal(modal, portalRoot) : modal;
|
||||
}
|
||||
|
|
|
|||
Loading…
Reference in New Issue