import React, { useMemo, useState, useContext } from 'react'; import { CSSTransitionProps } from 'react-transition-group/CSSTransition'; import OverlayTrigger, { OverlayTriggerProps, OverlayTriggerRef } from '@uiw/react-overlay-trigger'; import Icon from '@uiw/react-icon'; import { IProps } from '@uiw/utils'; import { MenuItem, MenuItemProps, TagType } from './MenuItem'; import { MenuProps, Menu, ThemeContext } from './Menu'; import './style/submenu.less'; export interface SubMenuProps extends IProps, MenuItemProps { overlayProps?: OverlayTriggerProps; collapse?: boolean; disabled?: boolean; inlineCollapsed?: boolean; inlineIndent?: number; } function checkedMenuItem(node?: HTMLElement) { let isCheck = false; if (node) { // eslint-disable-next-line do { if (!node.dataset.menu) { isCheck = true; } if (node.dataset.menu && /^(subitem|divider)$/.test(node.dataset.menu)) { isCheck = false; } } while (!node.dataset.menu && (node = node.parentNode as HTMLElement)); } return isCheck; } function IconView({ prefixCls, collapse, isOpen }: { prefixCls?: string; collapse?: boolean; isOpen: boolean }) { return useMemo( () => ( ), [prefixCls, collapse, isOpen], ); } export const SubMenu = React.forwardRef(function ( props: SubMenuProps, ref: React.Ref, ) { const { prefixCls = 'w-menu-subitem', className, disabled, overlayProps = {}, children, collapse = false, inlineIndent, inlineCollapsed, ...other } = props; const overlayTriggerProps = {} as OverlayTriggerProps & CSSTransitionProps; const menuProps: MenuProps = { bordered: true, children, inlineIndent, className: [prefixCls ? `${prefixCls}-overlay` : null].filter(Boolean).join(' ').trim(), }; const popupRef = React.useRef(null); const refNode = React.useRef(); const elementSource = React.useRef(); const [isOpen, setIsOpen] = useState(!!overlayProps.isOpen); const { height, setContextHeight, ele } = useContext(ThemeContext); React.useEffect(() => { if (refNode.current && refNode.current.style && ele === elementSource.current) { const currentHeight = Number(refNode.current!.style.height.substr(0, refNode.current!.style.height.length - 2)); // 设置的高度 < '已有展开的高度', if (refNode.current!.getBoundingClientRect().height < currentHeight) { refNode.current!.style.height = currentHeight + 'px'; } else { refNode.current!.style.height = currentHeight + height + 'px'; } } }, [height, ele]); useMemo(() => { if (collapse) setIsOpen(false); }, [collapse]); function onClick(e: React.MouseEvent) { const target = e.currentTarget; const related = (e.relatedTarget || e.nativeEvent.target) as HTMLElement; if (target.children.length < 1) return; if (checkedMenuItem(related)) { if (popupRef.current) { popupRef.current!.hide(); } } } function onEnter(node: HTMLElement) { node.style.height = '0px'; refNode.current = node; setIsOpen(true); if (popupRef.current && popupRef.current.overlayDom.current) { setContextHeight({ height: popupRef.current.overlayDom.current.getBoundingClientRect().height, ele: elementSource.current!, }); } } function onEntering(node: HTMLElement) { node.style.height = `${node.scrollHeight}px`; } function onEntered(node: HTMLElement) { // node.style.height = 'initial'; if (popupRef.current && popupRef.current.overlayDom.current) { node.style.height = popupRef.current.overlayDom.current.getBoundingClientRect().height + 'px'; } } function onExiting(node: HTMLElement) { node.style.height = '0px'; if (popupRef.current && popupRef.current.overlayDom.current) { setContextHeight({ height: -popupRef.current!.overlayDom.current!.getBoundingClientRect().height, ele: elementSource.current!, }); } } function onExit(node: HTMLElement) { node.style.height = `${node.scrollHeight}px`; setIsOpen(false); } if (!collapse) { delete menuProps.onClick; menuProps.bordered = false; overlayTriggerProps.className = `${prefixCls}-collapse`; overlayTriggerProps.appear = false; overlayTriggerProps.isOutside = true; overlayTriggerProps.isClickOutside = false; overlayTriggerProps.unmountOnExit = false; overlayTriggerProps.trigger = 'click'; overlayTriggerProps.transitionName = `${prefixCls}`; overlayTriggerProps.onExit = onExit; overlayTriggerProps.onExiting = onExiting; overlayTriggerProps.onEnter = onEnter; overlayTriggerProps.onEntered = onEntered; overlayTriggerProps.onEntering = onEntering; } else { overlayTriggerProps.className = `${prefixCls}-popup`; overlayTriggerProps.trigger = 'hover'; overlayTriggerProps.usePortal = true; menuProps.onClick = onClick; } return (
  • { if (collapse) { e.stopPropagation(); return; } elementSource.current = e.target; }} > } > } className={[ prefixCls ? `${prefixCls}-title` : null, !collapse ? `${prefixCls}-collapse-title` : null, className, ] .filter(Boolean) .join(' ') .trim()} />
  • ); }); SubMenu.displayName = 'uiw.SubMenu';