diff --git a/src/list/inner/CascaderItem.tsx b/src/list/inner/CascaderItem.tsx index 435f97a2dd..381b55c6bd 100644 --- a/src/list/inner/CascaderItem.tsx +++ b/src/list/inner/CascaderItem.tsx @@ -11,6 +11,7 @@ import List from '../List'; import { convertChildrenToData, generateSelectParent, generateString } from '../util'; import { ListContext } from '../context'; import { BaseItemProps } from '..'; +import TriggerContext from '../../popover/context'; const CascaderItem: React.ForwardRefRenderFunction< HTMLLIElement, @@ -23,6 +24,7 @@ const CascaderItem: React.ForwardRefRenderFunction< const popoverClassName = `${prefixCls}--content`; /** context */ const context = useContext(ListContext); + const popoverContext = useContext(TriggerContext); const { disabled: contextDisabled, selectParent, onClick: contextOnClick, setOptions } = context; /** end */ const childSelectPrent = generateSelectParent(label, value, selectParent); @@ -91,19 +93,21 @@ const CascaderItem: React.ForwardRefRenderFunction< if (!isEmpty(childrens) || React.isValidElement(children)) { return (
- document.body} - content={content()} - strategy={strategy} - distoryOnHide - delay={200} - offset={[0, 12]} - > - {element} - + + document.body} + content={content()} + strategy={strategy} + distoryOnHide + delay={200} + offset={[0, 12]} + > + {element} + +
); } diff --git a/src/popover/Popover.tsx b/src/popover/Popover.tsx index 1682d72348..34253eaf70 100644 --- a/src/popover/Popover.tsx +++ b/src/popover/Popover.tsx @@ -1,4 +1,4 @@ -import React, { useState, useMemo, useCallback, useRef, useLayoutEffect, useEffect } from 'react'; +import React, { useState, useMemo, useCallback, useRef, useLayoutEffect, useEffect, useContext } from 'react'; import classNames from 'classnames'; import { debounce, isFunction, isNil, omit } from 'lodash'; import ReactDOM from 'react-dom'; @@ -8,6 +8,7 @@ import { PopoverProps } from './interface'; import { composeRef, supportRef } from '../utils/composeRef'; import useControlledState from '../utils/hooks/useControlledState'; import usePop from './usePop'; +import TriggerContext from './context'; const Popover = (props: PopoverProps) => { const { @@ -43,7 +44,10 @@ const Popover = (props: PopoverProps) => { const [referenceElement, setReferenceELement] = useState(null); const [popperElement, setPopperElement] = useState(null); const arrowElement = useRef(null); - + const context = useContext(TriggerContext); + const hasPopupMouseDown = useRef(false); + const mouseDownTimeout = useRef(undefined); + // const useEffect(() => { if (!visible) overContentRef.current = false; }, [visible]); @@ -120,11 +124,32 @@ const Popover = (props: PopoverProps) => { }, [disabled, enterable, setVisible, onVisibleChange, update] ); + + // ============ nest popover on Document click close ============ + const onPopupMouseDown = (event: React.MouseEvent) => { + hasPopupMouseDown.current = true; + + clearTimeout(mouseDownTimeout.current); + mouseDownTimeout.current = window.setTimeout(() => { + hasPopupMouseDown.current = false; + }, 0); + + if (context) { + context?.onPopupMouseDown(event); + } + }; + + const triggerContextValue = { onPopupMouseDown }; + const onDocumentClick = useCallback( (event: MouseEvent) => { const { target } = event; if (isFunction(referenceElement?.contains) && isFunction(popperElement?.contains)) { - if (!referenceElement?.contains(target as Node) && !popperElement?.contains(target as Node)) { + if ( + !referenceElement?.contains(target as Node) && + !popperElement?.contains(target as Node) && + !hasPopupMouseDown.current + ) { updateVisible(false); } } @@ -139,6 +164,8 @@ const Popover = (props: PopoverProps) => { }; }, [onDocumentClick]); + // ============ end ============ + const isClickToShow = useMemo(() => trigger.indexOf('click') !== -1, [trigger]); const isHoverToShow = useMemo(() => trigger.indexOf('hover') !== -1, [trigger]); @@ -224,6 +251,7 @@ const Popover = (props: PopoverProps) => { style={{ ...(overlayStyle || {}), ...styles.popper }} onMouseEnter={onContentMouseEnter} onMouseLeave={onContentMouseLeave} + onMouseDownCapture={(e) => onPopupMouseDown(e)} onClick={onContentClick} role="none" {...omit(rest, 'arrowPointAtCenter')} @@ -257,6 +285,7 @@ const Popover = (props: PopoverProps) => { cloneProps.ref = composeRef(setReferenceELement, (child as any).ref); triggerNode = React.cloneElement(child as React.ReactElement, cloneProps); } + const container = useMemo(() => { if (isFunction(getContainer) && !isNil(referenceElement)) { return getContainer(referenceElement); @@ -277,8 +306,10 @@ const Popover = (props: PopoverProps) => { ); return ( <> - {triggerNode} - {distoryOnHide ? visible && renderContent : renderContent} + + {triggerNode} + {distoryOnHide ? visible && renderContent : renderContent} + ); }; diff --git a/src/popover/context.ts b/src/popover/context.ts new file mode 100644 index 0000000000..632b4cbe50 --- /dev/null +++ b/src/popover/context.ts @@ -0,0 +1,9 @@ +import * as React from 'react'; + +interface TriggerContextProps { + onPopupMouseDown: React.MouseEventHandler; +} + +const TriggerContext = React.createContext(null); + +export default TriggerContext;