import { useEffect } from 'react'; type FloatingOptionBoundaryRef = { readonly current: HTMLElement | null; }; type UseImageCanvasFloatingOptionDismissOptions = { isOpen: boolean; boundaryRefs: Array; onDismiss: () => void; }; function isEventInsideBoundary( target: EventTarget | null, boundaryRefs: Array, ) { if (!(target instanceof Node)) { return false; } return boundaryRefs.some((boundaryRef) => { const element = boundaryRef?.current; return element ? element.contains(target) : false; }); } function isEventInsideFloatingMenu(target: EventTarget | null) { return ( target instanceof Element && target.closest('.image-canvas-editor__portal-menu') ); } export function useImageCanvasFloatingOptionDismiss({ isOpen, boundaryRefs, onDismiss, }: UseImageCanvasFloatingOptionDismissOptions) { useEffect(() => { if (!isOpen || typeof document === 'undefined') { return undefined; } const handleClick = (event: MouseEvent) => { // 中文注释:选项项点击后要保留浮层;父级面板其它区域点击才收起。 if ( isEventInsideBoundary(event.target, boundaryRefs) || isEventInsideFloatingMenu(event.target) ) { return; } onDismiss(); }; document.addEventListener('click', handleClick); return () => { document.removeEventListener('click', handleClick); }; }, [boundaryRefs, isOpen, onDismiss]); }