Web: Components: Section: fixed closing the context menu when uploading files

This commit is contained in:
Nikita Gopienko 2024-08-15 18:22:03 +03:00
parent b4840a2807
commit 6d5c567da4
3 changed files with 88 additions and 63 deletions

View File

@ -145,3 +145,7 @@ export interface SectionProps {
isDesktop?: boolean; isDesktop?: boolean;
getContextModel?: () => ContextMenuModel[]; getContextModel?: () => ContextMenuModel[];
} }
export interface SectionContextMenuProps {
getContextModel: () => ContextMenuModel[];
}

View File

@ -29,14 +29,13 @@ import { useLocation } from "react-router-dom";
// import { inject, observer } from "mobx-react"; // import { inject, observer } from "mobx-react";
import { ContextMenu } from "@docspace/shared/components/context-menu";
import { import {
StyledDropZoneBody, StyledDropZoneBody,
StyledSpacer, StyledSpacer,
StyledSectionBody, StyledSectionBody,
} from "../Section.styled"; } from "../Section.styled";
import { SectionBodyProps } from "../Section.types"; import { SectionBodyProps } from "../Section.types";
import SectionContextMenu from "./SectionContextMenu";
const SectionBody = React.memo( const SectionBody = React.memo(
({ ({
@ -53,49 +52,9 @@ const SectionBody = React.memo(
getContextModel, getContextModel,
}: SectionBodyProps) => { }: SectionBodyProps) => {
const focusRef = React.useRef<HTMLDivElement | null>(null); const focusRef = React.useRef<HTMLDivElement | null>(null);
const cmRef = React.useRef<null | {
show: (e: React.MouseEvent | MouseEvent) => void;
hide: (e: React.MouseEvent | MouseEvent) => void;
toggle: (e: React.MouseEvent | MouseEvent) => boolean;
getVisible: () => boolean;
}>(null);
const location = useLocation(); const location = useLocation();
const [isOpen, setIsOpen] = React.useState(false);
const onContextMenu = React.useCallback(
(e: MouseEvent | React.MouseEvent<Element, MouseEvent>) => {
const bodyElem = document.getElementsByClassName(
"section-body",
)[0] as HTMLDivElement;
const target = e.target as Node;
if (
!getContextModel ||
!getContextModel() ||
!bodyElem ||
!bodyElem.contains(target)
)
return;
e.stopPropagation();
e.preventDefault();
// if (cmRef.current) cmRef.current.toggle(e);
if (cmRef.current) {
if (!isOpen) cmRef?.current?.show(e);
else cmRef?.current?.hide(e);
setIsOpen(!isOpen);
}
},
[getContextModel, isOpen],
);
const onHide = () => {
setIsOpen(false);
};
const focusSectionBody = React.useCallback(() => { const focusSectionBody = React.useCallback(() => {
if (focusRef.current) focusRef.current.focus({ preventScroll: true }); if (focusRef.current) focusRef.current.focus({ preventScroll: true });
}, []); }, []);
@ -108,14 +67,6 @@ const SectionBody = React.memo(
[focusSectionBody], [focusSectionBody],
); );
React.useEffect(() => {
document.addEventListener("contextmenu", onContextMenu);
return () => {
document.removeEventListener("contextmenu", onContextMenu);
};
}, [onContextMenu]);
React.useEffect(() => { React.useEffect(() => {
if (!autoFocus) return; if (!autoFocus) return;
@ -145,16 +96,6 @@ const SectionBody = React.memo(
} }
: {}; : {};
const contextBlock = (
<ContextMenu
ref={cmRef}
onHide={onHide}
getContextModel={getContextModel}
withBackdrop
model={[]}
/>
);
return uploadFiles ? ( return uploadFiles ? (
<StyledDropZoneBody <StyledDropZoneBody
isDropZone isDropZone
@ -179,7 +120,7 @@ const SectionBody = React.memo(
</div> </div>
)} )}
{contextBlock} <SectionContextMenu getContextModel={getContextModel} />
</StyledDropZoneBody> </StyledDropZoneBody>
) : ( ) : (
<StyledSectionBody <StyledSectionBody
@ -200,7 +141,7 @@ const SectionBody = React.memo(
) : ( ) : (
<div className="section-wrapper">{children}</div> <div className="section-wrapper">{children}</div>
)} )}
{contextBlock} <SectionContextMenu getContextModel={getContextModel} />
</StyledSectionBody> </StyledSectionBody>
); );
}, },

View File

@ -0,0 +1,80 @@
import React from "react";
import { ContextMenu } from "@docspace/shared/components/context-menu";
import isEqual from "lodash/isEqual";
import { SectionContextMenuProps } from "../Section.types";
const areEqual = (
prevProps: SectionContextMenuProps,
nextProps: SectionContextMenuProps,
) => {
if (!isEqual(prevProps, nextProps)) return true;
return false;
};
const SectionContextMenu = React.memo(
({ getContextModel }: SectionContextMenuProps) => {
const [isOpen, setIsOpen] = React.useState(false);
const cmRef = React.useRef<null | {
show: (e: React.MouseEvent | MouseEvent) => void;
hide: (e: React.MouseEvent | MouseEvent) => void;
toggle: (e: React.MouseEvent | MouseEvent) => boolean;
getVisible: () => boolean;
}>(null);
const onHide = () => {
setIsOpen(false);
};
const onContextMenu = React.useCallback(
(e: MouseEvent | React.MouseEvent<Element, MouseEvent>) => {
const bodyElem = document.getElementsByClassName(
"section-body",
)[0] as HTMLDivElement;
const target = e.target as Node;
if (
!getContextModel ||
!getContextModel() ||
!bodyElem ||
!bodyElem.contains(target)
)
return;
e.stopPropagation();
e.preventDefault();
// if (cmRef.current) cmRef.current.toggle(e);
if (cmRef.current) {
if (!isOpen) cmRef?.current?.show(e);
else cmRef?.current?.hide(e);
setIsOpen(!isOpen);
}
},
[getContextModel, isOpen],
);
React.useEffect(() => {
document.addEventListener("contextmenu", onContextMenu);
return () => {
document.removeEventListener("contextmenu", onContextMenu);
};
}, [onContextMenu]);
return (
<ContextMenu
ref={cmRef}
onHide={onHide}
getContextModel={getContextModel}
withBackdrop
model={[]}
/>
);
},
areEqual,
);
SectionContextMenu.displayName = "SectionContextMenu";
export default SectionContextMenu;