Shared:ContextMenu:Added scroll to all levels of the context menu. The structure of all context menu views has been changed and nesting has been added.
This commit is contained in:
parent
cb8a1233f0
commit
64233c9342
@ -60,9 +60,11 @@ const ContextMenu = React.forwardRef((props: ContextMenuProps, ref) => {
|
|||||||
const [model, setModel] = React.useState<ContextMenuModel[] | null>(null);
|
const [model, setModel] = React.useState<ContextMenuModel[] | null>(null);
|
||||||
const [changeView, setChangeView] = React.useState(false);
|
const [changeView, setChangeView] = React.useState(false);
|
||||||
const [showMobileMenu, setShowMobileMenu] = React.useState(false);
|
const [showMobileMenu, setShowMobileMenu] = React.useState(false);
|
||||||
const [onLoad, setOnLoad] = React.useState<
|
const [mobileSubMenuItems, setMobileSubMenuItems] = React.useState<
|
||||||
undefined | (() => Promise<ContextMenuModel[]>)
|
ContextMenuModel[] | undefined
|
||||||
>(undefined);
|
>(undefined);
|
||||||
|
const [mobileHeader, setMobileHeader] = React.useState<string>("");
|
||||||
|
|
||||||
const [articleWidth, setArticleWidth] = React.useState(0);
|
const [articleWidth, setArticleWidth] = React.useState(0);
|
||||||
|
|
||||||
const prevReshow = React.useRef(false);
|
const prevReshow = React.useRef(false);
|
||||||
@ -204,7 +206,7 @@ const ContextMenu = React.forwardRef((props: ContextMenuProps, ref) => {
|
|||||||
? rects.left - currentLeftOffset - currentRightOffset
|
? rects.left - currentLeftOffset - currentRightOffset
|
||||||
: event.pageX + 1;
|
: event.pageX + 1;
|
||||||
let top = rects ? rects.top : event.pageY + 1;
|
let top = rects ? rects.top : event.pageY + 1;
|
||||||
const width =
|
let width =
|
||||||
menuRef.current && menuRef.current.offsetParent
|
menuRef.current && menuRef.current.offsetParent
|
||||||
? menuRef.current.offsetWidth
|
? menuRef.current.offsetWidth
|
||||||
: DomHelpers.getHiddenElementOuterWidth(menuRef.current);
|
: DomHelpers.getHiddenElementOuterWidth(menuRef.current);
|
||||||
@ -214,29 +216,46 @@ const ContextMenu = React.forwardRef((props: ContextMenuProps, ref) => {
|
|||||||
: DomHelpers.getHiddenElementOuterHeight(menuRef.current);
|
: DomHelpers.getHiddenElementOuterHeight(menuRef.current);
|
||||||
const viewport = DomHelpers.getViewport();
|
const viewport = DomHelpers.getViewport();
|
||||||
|
|
||||||
|
const mobileView = isMobileUtils() && (height > 210 || ignoreChangeView);
|
||||||
|
|
||||||
|
if (!mobileView) {
|
||||||
|
const options = menuRef?.current?.getElementsByClassName("p-menuitem");
|
||||||
|
const optionsWidth: number[] = [];
|
||||||
|
|
||||||
|
if (options) {
|
||||||
|
Array.from(options).forEach((option) =>
|
||||||
|
optionsWidth.push(option.clientWidth),
|
||||||
|
);
|
||||||
|
|
||||||
|
const widthMaxContent = Math.max(...optionsWidth);
|
||||||
|
|
||||||
|
width = width || widthMaxContent;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
if (theme.interfaceDirection === "rtl" && !rects && left > width) {
|
if (theme.interfaceDirection === "rtl" && !rects && left > width) {
|
||||||
left = event.pageX - width + 1;
|
left = event.pageX - width + 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (
|
// if (
|
||||||
isTabletUtils() &&
|
// isTabletUtils() &&
|
||||||
(height > 483 ||
|
// (height > 483 ||
|
||||||
(isMobileOnly && window.innerHeight < window.innerWidth))
|
// (isMobileOnly && window.innerHeight < window.innerWidth))
|
||||||
) {
|
// ) {
|
||||||
const article = document.getElementById("article-container");
|
// const article = document.getElementById("article-container");
|
||||||
|
|
||||||
let currentArticleWidth = 0;
|
// let currentArticleWidth = 0;
|
||||||
if (article) {
|
// if (article) {
|
||||||
currentArticleWidth = article.offsetWidth;
|
// currentArticleWidth = article.offsetWidth;
|
||||||
}
|
// }
|
||||||
|
|
||||||
setChangeView(true);
|
// setChangeView(true);
|
||||||
setArticleWidth(currentArticleWidth);
|
// setArticleWidth(currentArticleWidth);
|
||||||
|
|
||||||
return;
|
// return;
|
||||||
}
|
// }
|
||||||
|
|
||||||
if (isMobileUtils() && (height > 210 || ignoreChangeView)) {
|
if (mobileView) {
|
||||||
setChangeView(true);
|
setChangeView(true);
|
||||||
setArticleWidth(0);
|
setArticleWidth(0);
|
||||||
|
|
||||||
@ -260,7 +279,10 @@ const ContextMenu = React.forwardRef((props: ContextMenuProps, ref) => {
|
|||||||
|
|
||||||
// fit
|
// fit
|
||||||
if (top < document.body.scrollTop) {
|
if (top < document.body.scrollTop) {
|
||||||
top = document.body.scrollTop;
|
const marginTop = 16;
|
||||||
|
|
||||||
|
if (document.body.scrollTop === 0) top = marginTop;
|
||||||
|
else top = document.body.scrollTop;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (containerRef) {
|
if (containerRef) {
|
||||||
@ -276,6 +298,8 @@ const ContextMenu = React.forwardRef((props: ContextMenuProps, ref) => {
|
|||||||
if (menuRef.current) {
|
if (menuRef.current) {
|
||||||
menuRef.current.style.left = `${left}px`;
|
menuRef.current.style.left = `${left}px`;
|
||||||
menuRef.current.style.top = `${top}px`;
|
menuRef.current.style.top = `${top}px`;
|
||||||
|
|
||||||
|
if (!mobileView) menuRef.current.style.width = `${width}px`;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
@ -399,14 +423,20 @@ const ContextMenu = React.forwardRef((props: ContextMenuProps, ref) => {
|
|||||||
};
|
};
|
||||||
}, [documentResizeListener, onHide, visible]);
|
}, [documentResizeListener, onHide, visible]);
|
||||||
|
|
||||||
const onMobileItemClick = (
|
const onMobileItemClick = async (
|
||||||
e: React.MouseEvent | React.ChangeEvent<HTMLInputElement>,
|
e: React.MouseEvent | React.ChangeEvent<HTMLInputElement>,
|
||||||
|
label: string,
|
||||||
|
items?: ContextMenuModel[],
|
||||||
loadFunc?: () => Promise<ContextMenuModel[]>,
|
loadFunc?: () => Promise<ContextMenuModel[]>,
|
||||||
) => {
|
) => {
|
||||||
e.stopPropagation();
|
e.stopPropagation();
|
||||||
|
|
||||||
setShowMobileMenu(true);
|
setShowMobileMenu(true);
|
||||||
if (loadFunc) setOnLoad(loadFunc);
|
|
||||||
|
const res = loadFunc ? await loadFunc() : items;
|
||||||
|
setMobileSubMenuItems(res);
|
||||||
|
|
||||||
|
setMobileHeader(label);
|
||||||
};
|
};
|
||||||
|
|
||||||
const onBackClick = (e: React.MouseEvent<HTMLDivElement>) => {
|
const onBackClick = (e: React.MouseEvent<HTMLDivElement>) => {
|
||||||
@ -506,7 +536,7 @@ const ContextMenu = React.forwardRef((props: ContextMenuProps, ref) => {
|
|||||||
)}
|
)}
|
||||||
|
|
||||||
<Text className="text" truncate dir="auto">
|
<Text className="text" truncate dir="auto">
|
||||||
{header.title}
|
{showMobileMenu ? mobileHeader : header.title}
|
||||||
</Text>
|
</Text>
|
||||||
</div>
|
</div>
|
||||||
)}
|
)}
|
||||||
@ -516,7 +546,7 @@ const ContextMenu = React.forwardRef((props: ContextMenuProps, ref) => {
|
|||||||
root
|
root
|
||||||
resetMenu={resetMenu}
|
resetMenu={resetMenu}
|
||||||
onLeafClick={onLeafClick}
|
onLeafClick={onLeafClick}
|
||||||
onLoad={onLoad}
|
mobileSubMenuItems={mobileSubMenuItems}
|
||||||
/>
|
/>
|
||||||
) : (
|
) : (
|
||||||
<SubMenu
|
<SubMenu
|
||||||
@ -524,7 +554,6 @@ const ContextMenu = React.forwardRef((props: ContextMenuProps, ref) => {
|
|||||||
root
|
root
|
||||||
resetMenu={resetMenu}
|
resetMenu={resetMenu}
|
||||||
onLeafClick={onLeafClick}
|
onLeafClick={onLeafClick}
|
||||||
changeView={changeView}
|
|
||||||
onMobileItemClick={onMobileItemClick}
|
onMobileItemClick={onMobileItemClick}
|
||||||
/>
|
/>
|
||||||
)}
|
)}
|
||||||
|
@ -44,9 +44,9 @@ const MobileSubMenu = (props: {
|
|||||||
onLeafClick: (e: React.MouseEvent) => void;
|
onLeafClick: (e: React.MouseEvent) => void;
|
||||||
root?: boolean;
|
root?: boolean;
|
||||||
resetMenu: boolean;
|
resetMenu: boolean;
|
||||||
onLoad?: () => Promise<ContextMenuModel[]>;
|
mobileSubMenuItems?: ContextMenuModel[];
|
||||||
}) => {
|
}) => {
|
||||||
const { onLeafClick, root, resetMenu, onLoad } = props;
|
const { onLeafClick, root, resetMenu, mobileSubMenuItems } = props;
|
||||||
|
|
||||||
const [submenu, setSubmenu] = useState<null | ContextMenuModel[]>(null);
|
const [submenu, setSubmenu] = useState<null | ContextMenuModel[]>(null);
|
||||||
|
|
||||||
@ -91,16 +91,12 @@ const MobileSubMenu = (props: {
|
|||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
const fetchSubMenu = React.useCallback(async () => {
|
|
||||||
const res = await onLoad?.();
|
|
||||||
if (res) setSubmenu(res);
|
|
||||||
|
|
||||||
position();
|
|
||||||
}, [position, setSubmenu, onLoad]);
|
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
if (onLoad) fetchSubMenu();
|
if (!mobileSubMenuItems?.length) return;
|
||||||
}, [onLoad, fetchSubMenu]);
|
|
||||||
|
setSubmenu(mobileSubMenuItems);
|
||||||
|
position();
|
||||||
|
}, [mobileSubMenuItems, mobileSubMenuItems?.length, position]);
|
||||||
|
|
||||||
const onItemClick = (e: React.MouseEvent, item: ContextMenuType) => {
|
const onItemClick = (e: React.MouseEvent, item: ContextMenuType) => {
|
||||||
const { disabled, url, onClick, items, action } = item;
|
const { disabled, url, onClick, items, action } = item;
|
||||||
|
@ -32,21 +32,14 @@ import { useTheme } from "styled-components";
|
|||||||
|
|
||||||
import ArrowIcon from "PUBLIC_DIR/images/arrow.right.react.svg";
|
import ArrowIcon from "PUBLIC_DIR/images/arrow.right.react.svg";
|
||||||
import OutsdideIcon from "PUBLIC_DIR/images/arrow.outside.react.svg";
|
import OutsdideIcon from "PUBLIC_DIR/images/arrow.outside.react.svg";
|
||||||
import { isMobile as isMobileDevice } from "react-device-detect";
|
|
||||||
|
|
||||||
import {
|
import { classNames, ObjectUtils, DomHelpers, isMobile } from "../../../utils";
|
||||||
classNames,
|
|
||||||
ObjectUtils,
|
|
||||||
DomHelpers,
|
|
||||||
isMobile,
|
|
||||||
isTablet,
|
|
||||||
} from "../../../utils";
|
|
||||||
import { ContextMenuSkeleton } from "../../../skeletons/context-menu";
|
import { ContextMenuSkeleton } from "../../../skeletons/context-menu";
|
||||||
|
|
||||||
import { Scrollbar } from "../../scrollbar";
|
|
||||||
import { ToggleButton } from "../../toggle-button";
|
import { ToggleButton } from "../../toggle-button";
|
||||||
|
import { Scrollbar } from "../../scrollbar";
|
||||||
|
|
||||||
import { SubMenuItem } from "../ContextMenu.styled";
|
import { SubMenuItem, StyledList } from "../ContextMenu.styled";
|
||||||
import {
|
import {
|
||||||
ContextMenuModel,
|
ContextMenuModel,
|
||||||
ContextMenuType,
|
ContextMenuType,
|
||||||
@ -63,19 +56,13 @@ const SubMenu = (props: {
|
|||||||
) => void;
|
) => void;
|
||||||
onMobileItemClick?: (
|
onMobileItemClick?: (
|
||||||
e: React.MouseEvent | React.ChangeEvent<HTMLInputElement>,
|
e: React.MouseEvent | React.ChangeEvent<HTMLInputElement>,
|
||||||
loadFunc: () => Promise<ContextMenuModel[]>,
|
label: string,
|
||||||
|
items?: ContextMenuModel[],
|
||||||
|
loadFunc?: () => Promise<ContextMenuModel[]>,
|
||||||
) => void;
|
) => void;
|
||||||
changeView?: boolean;
|
|
||||||
onLoad?: () => Promise<ContextMenuModel[]>;
|
onLoad?: () => Promise<ContextMenuModel[]>;
|
||||||
}) => {
|
}) => {
|
||||||
const {
|
const { onLeafClick, root, resetMenu, onMobileItemClick, onLoad } = props;
|
||||||
onLeafClick,
|
|
||||||
root,
|
|
||||||
resetMenu,
|
|
||||||
changeView,
|
|
||||||
onMobileItemClick,
|
|
||||||
onLoad,
|
|
||||||
} = props;
|
|
||||||
|
|
||||||
const [model, setModel] = useState(props?.model);
|
const [model, setModel] = useState(props?.model);
|
||||||
const [isLoading, setIsLoading] = useState(false);
|
const [isLoading, setIsLoading] = useState(false);
|
||||||
@ -86,7 +73,7 @@ const SubMenu = (props: {
|
|||||||
const theme = useTheme();
|
const theme = useTheme();
|
||||||
|
|
||||||
const onItemMouseEnter = (e: React.MouseEvent, item: ContextMenuType) => {
|
const onItemMouseEnter = (e: React.MouseEvent, item: ContextMenuType) => {
|
||||||
if (item.disabled || isMobileDevice) {
|
if (item.disabled) {
|
||||||
e.preventDefault();
|
e.preventDefault();
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@ -98,16 +85,18 @@ const SubMenu = (props: {
|
|||||||
e: React.MouseEvent | React.ChangeEvent<HTMLInputElement>,
|
e: React.MouseEvent | React.ChangeEvent<HTMLInputElement>,
|
||||||
item: ContextMenuType,
|
item: ContextMenuType,
|
||||||
) => {
|
) => {
|
||||||
if (item.onLoad) {
|
const { disabled, url, onClick, items, action, label } = item;
|
||||||
e.preventDefault();
|
|
||||||
if (!isMobile() && !isTablet()) return;
|
|
||||||
|
|
||||||
if (isMobile() || isTablet()) onMobileItemClick?.(e, item.onLoad);
|
if (label && (items || item.onLoad)) {
|
||||||
else onLeafClick?.(e);
|
e.preventDefault();
|
||||||
|
if (!isMobile()) return;
|
||||||
|
|
||||||
|
if (items) onMobileItemClick?.(e, label as string, items, undefined);
|
||||||
|
else if (item.onLoad)
|
||||||
|
onMobileItemClick?.(e, label as string, undefined, item.onLoad);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
const { disabled, url, onClick, items, action } = item;
|
|
||||||
if (disabled) {
|
if (disabled) {
|
||||||
e.preventDefault();
|
e.preventDefault();
|
||||||
return;
|
return;
|
||||||
@ -134,7 +123,9 @@ const SubMenu = (props: {
|
|||||||
const containerOffset = DomHelpers.getOffset(parentItem);
|
const containerOffset = DomHelpers.getOffset(parentItem);
|
||||||
const viewport = DomHelpers.getViewport();
|
const viewport = DomHelpers.getViewport();
|
||||||
|
|
||||||
const subListWidth = subMenuRef.current?.offsetParent
|
const options = subMenuRef.current?.getElementsByClassName("p-menuitem");
|
||||||
|
|
||||||
|
let subListWidth = subMenuRef.current?.offsetParent
|
||||||
? subMenuRef.current.offsetWidth
|
? subMenuRef.current.offsetWidth
|
||||||
: DomHelpers.getHiddenElementOuterWidth(subMenuRef.current);
|
: DomHelpers.getHiddenElementOuterWidth(subMenuRef.current);
|
||||||
|
|
||||||
@ -144,16 +135,49 @@ const SubMenu = (props: {
|
|||||||
|
|
||||||
const isRtl = theme.interfaceDirection === "rtl";
|
const isRtl = theme.interfaceDirection === "rtl";
|
||||||
|
|
||||||
|
if (!isMobile() && options) {
|
||||||
|
const optionsWidth: number[] = [];
|
||||||
|
Array.from(options).forEach((option) =>
|
||||||
|
optionsWidth.push(Math.ceil(option.getBoundingClientRect().width)),
|
||||||
|
);
|
||||||
|
|
||||||
|
const widthMaxContent = Math.max(...optionsWidth);
|
||||||
|
|
||||||
|
subListWidth = subListWidth || widthMaxContent;
|
||||||
|
}
|
||||||
|
|
||||||
if (subMenuRef.current) {
|
if (subMenuRef.current) {
|
||||||
subMenuRef.current.style.top = "0px";
|
let subMenuRefTop = null;
|
||||||
|
|
||||||
|
if (!isMobile()) subMenuRef.current.style.width = `${subListWidth}px`;
|
||||||
|
|
||||||
|
if (!isMobile() && !root) {
|
||||||
|
const firstList = parentItem?.firstChild as HTMLElement;
|
||||||
|
|
||||||
|
const menuItemActive = firstList.querySelector(
|
||||||
|
".p-menuitem-active",
|
||||||
|
) as HTMLElement;
|
||||||
|
|
||||||
|
const top = menuItemActive.offsetTop;
|
||||||
|
const scroller = firstList.querySelector(".scroller") as HTMLElement;
|
||||||
|
const scrollTop = scroller.scrollTop;
|
||||||
|
const positionActiveItem = top - scrollTop;
|
||||||
|
|
||||||
|
subMenuRefTop = positionActiveItem - 2;
|
||||||
|
subMenuRef.current.style.top = `${subMenuRefTop}px`;
|
||||||
|
}
|
||||||
|
|
||||||
const submenuRects = subMenuRef.current.getBoundingClientRect();
|
const submenuRects = subMenuRef.current.getBoundingClientRect();
|
||||||
|
|
||||||
if (submenuRects.bottom > viewport.height) {
|
if (submenuRects.bottom > viewport.height && subMenuRefTop) {
|
||||||
const submenuMargin = 16;
|
const submenuMargin = 16;
|
||||||
const topOffset = submenuRects.bottom - viewport.height + submenuMargin;
|
|
||||||
|
|
||||||
subMenuRef.current.style.top = `${-1 * topOffset}px`;
|
const topOffset =
|
||||||
|
subMenuRefTop -
|
||||||
|
(submenuRects.bottom - viewport.height) -
|
||||||
|
submenuMargin;
|
||||||
|
|
||||||
|
subMenuRef.current.style.top = `${topOffset}px`;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (isRtl) {
|
if (isRtl) {
|
||||||
@ -205,29 +229,6 @@ const SubMenu = (props: {
|
|||||||
/>
|
/>
|
||||||
);
|
);
|
||||||
|
|
||||||
const renderSubMenu = (item: ContextMenuType) => {
|
|
||||||
const loaderItem = {
|
|
||||||
id: "link-loader-option",
|
|
||||||
key: "link-loader",
|
|
||||||
isLoader: true,
|
|
||||||
label: <ContextMenuSkeleton />,
|
|
||||||
};
|
|
||||||
|
|
||||||
if (item.items || item.onLoad) {
|
|
||||||
return (
|
|
||||||
<SubMenu
|
|
||||||
model={item.onLoad ? [loaderItem] : item.items || []}
|
|
||||||
resetMenu={item !== activeItem}
|
|
||||||
onLeafClick={onLeafClick}
|
|
||||||
// onEnter={onEnter}
|
|
||||||
onLoad={item.onLoad}
|
|
||||||
/>
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
return null;
|
|
||||||
};
|
|
||||||
|
|
||||||
const renderMenuitem = (
|
const renderMenuitem = (
|
||||||
item: ContextMenuType,
|
item: ContextMenuType,
|
||||||
index: number,
|
index: number,
|
||||||
@ -273,7 +274,7 @@ const SubMenu = (props: {
|
|||||||
const subMenuIcon = (item.items || item.onLoad) && (
|
const subMenuIcon = (item.items || item.onLoad) && (
|
||||||
<ArrowIcon className={subMenuIconClassName} />
|
<ArrowIcon className={subMenuIconClassName} />
|
||||||
);
|
);
|
||||||
const subMenu = renderSubMenu(item);
|
|
||||||
const dataKeys = Object.fromEntries(
|
const dataKeys = Object.fromEntries(
|
||||||
Object.entries(item).filter((el) => el[0].indexOf("data-") === 0),
|
Object.entries(item).filter((el) => el[0].indexOf("data-") === 0),
|
||||||
);
|
);
|
||||||
@ -330,7 +331,6 @@ const SubMenu = (props: {
|
|||||||
onMouseEnter={(e) => onItemMouseEnter(e, item)}
|
onMouseEnter={(e) => onItemMouseEnter(e, item)}
|
||||||
>
|
>
|
||||||
{content}
|
{content}
|
||||||
{subMenu}
|
|
||||||
<ToggleButton
|
<ToggleButton
|
||||||
isChecked={item.checked || false}
|
isChecked={item.checked || false}
|
||||||
onChange={onClick}
|
onChange={onClick}
|
||||||
@ -350,7 +350,6 @@ const SubMenu = (props: {
|
|||||||
onMouseEnter={(e) => onItemMouseEnter(e, item)}
|
onMouseEnter={(e) => onItemMouseEnter(e, item)}
|
||||||
>
|
>
|
||||||
{content}
|
{content}
|
||||||
{subMenu}
|
|
||||||
</li>
|
</li>
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
@ -389,78 +388,93 @@ const SubMenu = (props: {
|
|||||||
};
|
};
|
||||||
|
|
||||||
const renderMenu = () => {
|
const renderMenu = () => {
|
||||||
if (model) {
|
if (!model) return null;
|
||||||
if (changeView) {
|
|
||||||
const newModel = model.filter(
|
return model.map((item: ContextMenuModel, index: number) => {
|
||||||
(item: ContextMenuModel) => item && !item.disabled,
|
if (item?.disabled) return null;
|
||||||
|
return renderItem(item, index);
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
|
const renderSubMenuLower = () => {
|
||||||
|
if (!model) return null;
|
||||||
|
const submenu: JSX.Element[] = [];
|
||||||
|
|
||||||
|
const loaderItem = {
|
||||||
|
id: "link-loader-option",
|
||||||
|
key: "link-loader",
|
||||||
|
isLoader: true,
|
||||||
|
label: <ContextMenuSkeleton />,
|
||||||
|
};
|
||||||
|
|
||||||
|
model.forEach((item) => {
|
||||||
|
const contextMenuTypeItem = item as ContextMenuType;
|
||||||
|
|
||||||
|
if (contextMenuTypeItem?.items || contextMenuTypeItem?.onLoad) {
|
||||||
|
submenu.push(
|
||||||
|
<SubMenu
|
||||||
|
key={`sub-menu_${item.id}`}
|
||||||
|
model={
|
||||||
|
contextMenuTypeItem?.onLoad
|
||||||
|
? [loaderItem]
|
||||||
|
: contextMenuTypeItem?.items || []
|
||||||
|
}
|
||||||
|
resetMenu={item !== activeItem}
|
||||||
|
onLeafClick={onLeafClick}
|
||||||
|
onLoad={contextMenuTypeItem?.onLoad}
|
||||||
|
/>,
|
||||||
);
|
);
|
||||||
const rowHeights: number[] = newModel.map((item: ContextMenuModel) => {
|
|
||||||
if (!item) return 0;
|
|
||||||
if (item.isSeparator) return 13;
|
|
||||||
return 36;
|
|
||||||
});
|
|
||||||
|
|
||||||
// const getItemSize = (index) => rowHeights[index];
|
|
||||||
|
|
||||||
const height = rowHeights.reduce((a, b) => a + b);
|
|
||||||
const viewport = DomHelpers.getViewport();
|
|
||||||
|
|
||||||
const listHeight =
|
|
||||||
height + 61 > viewport.height - 64
|
|
||||||
? viewport.height - 125
|
|
||||||
: height + 5;
|
|
||||||
|
|
||||||
return (
|
|
||||||
<Scrollbar style={{ height: listHeight }}>
|
|
||||||
{model.map((item: ContextMenuModel, index: number) => {
|
|
||||||
if (!item || item?.disabled) return null;
|
|
||||||
|
|
||||||
return renderItem(item, index);
|
|
||||||
})}
|
|
||||||
</Scrollbar>
|
|
||||||
);
|
|
||||||
|
|
||||||
// return (
|
|
||||||
// <VariableSizeList
|
|
||||||
// height={listHeight}
|
|
||||||
// width={"auto"}
|
|
||||||
// itemCount={newModel.length}
|
|
||||||
// itemSize={getItemSize}
|
|
||||||
// itemData={newModel}
|
|
||||||
// outerElementType={CustomScrollbarsVirtualList}
|
|
||||||
// >
|
|
||||||
// {renderItem}
|
|
||||||
// </VariableSizeList>
|
|
||||||
// );
|
|
||||||
}
|
}
|
||||||
|
});
|
||||||
|
|
||||||
return model.map((item: ContextMenuModel, index: number) => {
|
return submenu;
|
||||||
if (item?.disabled) return null;
|
|
||||||
return renderItem(item, index);
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
return null;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
const className = classNames({ "p-submenu-list": !root });
|
const className = classNames({ "p-submenu-list": !root });
|
||||||
const submenu = renderMenu();
|
const submenu = renderMenu();
|
||||||
const active = isActive();
|
const active = isActive();
|
||||||
|
const submenuLower = renderSubMenuLower();
|
||||||
|
|
||||||
return (
|
const newModel = model.filter(
|
||||||
<CSSTransition
|
(item: ContextMenuModel) => item && !item.disabled,
|
||||||
nodeRef={subMenuRef}
|
|
||||||
classNames="p-contextmenusub"
|
|
||||||
in={active}
|
|
||||||
timeout={{ enter: 0, exit: 0 }}
|
|
||||||
unmountOnExit
|
|
||||||
onEnter={onEnter}
|
|
||||||
>
|
|
||||||
<ul ref={subMenuRef} className={`${className} not-selectable`}>
|
|
||||||
{submenu}
|
|
||||||
</ul>
|
|
||||||
</CSSTransition>
|
|
||||||
);
|
);
|
||||||
|
const rowHeights: number[] = newModel.map((item: ContextMenuModel) => {
|
||||||
|
if (!item) return 0;
|
||||||
|
if (item.isSeparator) return 13;
|
||||||
|
return 36;
|
||||||
|
});
|
||||||
|
|
||||||
|
const height = rowHeights.reduce((a, b) => a + b);
|
||||||
|
const viewport = DomHelpers.getViewport();
|
||||||
|
const paddingList = 12;
|
||||||
|
const marginsList = 32;
|
||||||
|
|
||||||
|
const listHeight =
|
||||||
|
height + paddingList + marginsList > viewport.height
|
||||||
|
? viewport.height - marginsList
|
||||||
|
: height + paddingList;
|
||||||
|
|
||||||
|
if (model) {
|
||||||
|
return (
|
||||||
|
<CSSTransition
|
||||||
|
nodeRef={subMenuRef}
|
||||||
|
classNames="p-contextmenusub"
|
||||||
|
in={active}
|
||||||
|
timeout={{ enter: 0, exit: 0 }}
|
||||||
|
unmountOnExit
|
||||||
|
onEnter={onEnter}
|
||||||
|
>
|
||||||
|
<StyledList
|
||||||
|
ref={subMenuRef}
|
||||||
|
className={`${className} not-selectable`}
|
||||||
|
listHeight={height + paddingList}
|
||||||
|
>
|
||||||
|
<Scrollbar style={{ height: listHeight }}>{submenu}</Scrollbar>
|
||||||
|
{submenuLower}
|
||||||
|
</StyledList>
|
||||||
|
</CSSTransition>
|
||||||
|
);
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
export { SubMenu };
|
export { SubMenu };
|
||||||
|
Loading…
Reference in New Issue
Block a user