Ви не можете вибрати більше 25 тем Теми мають розпочинатися з літери або цифри, можуть містити дефіси (-) і не повинні перевищувати 35 символів.

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374
  1. // @flow
  2. import { useCallback, useRef, useState } from 'react';
  3. import { findAncestorByClass } from '../../../participants-pane/functions';
  4. type RaiseContext = {|
  5. /**
  6. * Target elements against which positioning calculations are made.
  7. */
  8. offsetTarget?: HTMLElement,
  9. /**
  10. * The entity for which the menu is context menu is raised.
  11. */
  12. entity?: string | Object,
  13. |};
  14. const initialState = Object.freeze({});
  15. const useContextMenu = () => {
  16. const [ raiseContext, setRaiseContext ] = useState < RaiseContext >(initialState);
  17. const isMouseOverMenu = useRef(false);
  18. const lowerMenu = useCallback((force: boolean | Object = false) => {
  19. /**
  20. * We are tracking mouse movement over the active participant item and
  21. * the context menu. Due to the order of enter/leave events, we need to
  22. * defer checking if the mouse is over the context menu with
  23. * queueMicrotask.
  24. */
  25. window.queueMicrotask(() => {
  26. if (isMouseOverMenu.current && !(force === true)) {
  27. return;
  28. }
  29. if (raiseContext !== initialState) {
  30. setRaiseContext(initialState);
  31. }
  32. });
  33. }, [ raiseContext ]);
  34. const raiseMenu = useCallback((entity: string | Object, target: EventTarget) => {
  35. setRaiseContext({
  36. entity,
  37. offsetTarget: findAncestorByClass(target, 'list-item-container')
  38. });
  39. }, [ raiseContext ]);
  40. const toggleMenu = useCallback((entity: string | Object) => (e: MouseEvent) => {
  41. e.stopPropagation();
  42. const { entity: raisedEntity } = raiseContext;
  43. if (raisedEntity && raisedEntity === entity) {
  44. lowerMenu();
  45. } else {
  46. raiseMenu(entity, e.target);
  47. }
  48. }, [ raiseContext ]);
  49. const menuEnter = useCallback(() => {
  50. isMouseOverMenu.current = true;
  51. }, []);
  52. const menuLeave = useCallback(() => {
  53. isMouseOverMenu.current = false;
  54. lowerMenu();
  55. }, [ lowerMenu ]);
  56. return [ lowerMenu, raiseMenu, toggleMenu, menuEnter, menuLeave, raiseContext ];
  57. };
  58. export default useContextMenu;