Outlook_Addin_LLM/node_modules/@fluentui/react-menu/lib/utils/useOnMenuEnter.js

60 lines
2.4 KiB
JavaScript

import * as React from 'react';
import { useEventCallback, elementContains } from '@fluentui/react-utilities';
/**
* Name of the custom event
*/ export const MENU_ENTER_EVENT = 'fuimenuenter';
/**
* This hook works similarly to @see useOnClickOutside
*
* Problem: Trying to behave the same as system menus:
* When the mouse leaves a stack of nested menus the stack should not dismiss.
* However if the mouse leaves a stack of menus and enters a parent menu all its children menu should dismiss.
*
* We don't use the native mouseenter event because it would trigger too many times in the document
* Instead, dispatch custom DOM event from the menu so that it can bubble
* Each nested menu can use the listener to check if the event is from a child or parent menu
*/ export const useOnMenuMouseEnter = (options)=>{
const { refs, callback, element, disabled } = options;
// Keep mouse event here because this is essentially a custom 'mouseenter' event
const listener = useEventCallback((ev)=>{
const popoverRef = refs[0];
const someMenuPopover = ev.target;
var _popoverRef_current;
// someMenu is a child -> will always be contained because of vParents
// someMenu is a parent -> will always not be contained because no vParent
// someMenu is the current popover -> it will contain itself
const isOutsidePopover = !elementContains((_popoverRef_current = popoverRef.current) !== null && _popoverRef_current !== void 0 ? _popoverRef_current : null, someMenuPopover);
if (isOutsidePopover && !disabled) {
callback(ev);
}
});
React.useEffect(()=>{
// eslint-disable-next-line eqeqeq
if (element == null) {
return;
}
if (!disabled) {
element.addEventListener(MENU_ENTER_EVENT, listener);
}
return ()=>{
element.removeEventListener(MENU_ENTER_EVENT, listener);
};
}, [
listener,
element,
disabled
]);
};
/**
* Dispatches the custom MouseEvent enter event. Similar to calling `el.click()`
* @param el - element for the event target
* @param nativeEvent - the native mouse event this is mapped to
*/ export const dispatchMenuEnterEvent = (el, nativeEvent)=>{
el.dispatchEvent(new CustomEvent(MENU_ENTER_EVENT, {
bubbles: true,
detail: {
nativeEvent
}
}));
};