UI - МЕЖПРОЕКТНАЯ КОММУНИКАЦИЯ: исправление слоя превью вложений
This commit is contained in:
parent
0be8f01283
commit
3dd99491a4
|
|
@ -6,11 +6,27 @@
|
||||||
|
|
||||||
import { Dialog, Transition } from "@headlessui/react";
|
import { Dialog, Transition } from "@headlessui/react";
|
||||||
import React, { Fragment } from "react";
|
import React, { Fragment } from "react";
|
||||||
|
import { createPortal } from "react-dom";
|
||||||
// constants
|
// constants
|
||||||
import { cn } from "../utils";
|
import { cn } from "../utils";
|
||||||
import { EModalPosition, EModalWidth } from "./constants";
|
import { EModalPosition, EModalWidth } from "./constants";
|
||||||
// helpers
|
// 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 = {
|
type Props = {
|
||||||
children: React.ReactNode;
|
children: React.ReactNode;
|
||||||
handleClose?: () => void;
|
handleClose?: () => void;
|
||||||
|
|
@ -29,9 +45,41 @@ export function ModalCore(props: Props) {
|
||||||
className = "",
|
className = "",
|
||||||
} = props;
|
} = 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}>
|
<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
|
<Transition.Child
|
||||||
as={Fragment}
|
as={Fragment}
|
||||||
enter="ease-out duration-300"
|
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"
|
leaveTo="opacity-0 translate-y-4 sm:translate-y-0 sm:scale-95"
|
||||||
>
|
>
|
||||||
<Dialog.Panel
|
<Dialog.Panel
|
||||||
|
onContextMenuCapture={(event) => {
|
||||||
|
event.stopPropagation();
|
||||||
|
guardContextMenuClose();
|
||||||
|
}}
|
||||||
|
onPointerDownCapture={(event) => {
|
||||||
|
if (event.button === 2) {
|
||||||
|
event.stopPropagation();
|
||||||
|
guardContextMenuClose();
|
||||||
|
}
|
||||||
|
}}
|
||||||
className={cn(
|
className={cn(
|
||||||
"nodedc-glass-modal relative w-full transform rounded-[28px] text-left transition-all",
|
"nodedc-glass-modal relative w-full transform rounded-[28px] text-left transition-all",
|
||||||
width,
|
width,
|
||||||
|
|
@ -70,4 +128,8 @@ export function ModalCore(props: Props) {
|
||||||
</Dialog>
|
</Dialog>
|
||||||
</Transition.Root>
|
</Transition.Root>
|
||||||
);
|
);
|
||||||
|
|
||||||
|
if (typeof document !== "undefined" && !portalRoot) return null;
|
||||||
|
|
||||||
|
return portalRoot ? createPortal(modal, portalRoot) : modal;
|
||||||
}
|
}
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue