Skip to content

Instantly share code, notes, and snippets.

@loopmode
Created October 19, 2019 08:21
Show Gist options
  • Save loopmode/81b71f96bebe22697f8c2ee22fa12cf8 to your computer and use it in GitHub Desktop.
Save loopmode/81b71f96bebe22697f8c2ee22fa12cf8 to your computer and use it in GitHub Desktop.
Hook for displaying electron context menu for an element
import {
remote,
MenuItemConstructorOptions,
ContextMenuParams,
Event as ElectronEvent
} from 'electron';
import contextMenu from 'electron-context-menu';
import React from 'react';
const { MenuItem, getCurrentWindow } = remote;
export type MenuMode = 'menu' | 'append' | 'prepend';
/**
* Performance could be improved, see discussion in https://github.com/sindresorhus/electron-context-menu/issues/78
* @param targetSelectorOrRef Either a string selector or a ref object for the element to show this context menu on
* @param menuItems an array of MenuItem options for menu items to display
* @param options
*/
export default function useContextMenu(
targetSelectorOrRef: string | React.MutableRefObject<HTMLElement | null>,
menuItems: Partial<MenuItemConstructorOptions>[],
mode: MenuMode = 'menu',
options: Partial<contextMenu.Options> = {}
) {
React.useEffect(() => {
contextMenu({
...options,
window: options.window || getCurrentWindow(),
[mode]: () => menuItems.map(options => new MenuItem(options)),
shouldShowMenu: createShouldShowMenu(targetSelectorOrRef)
});
}, []);
}
function createShouldShowMenu(
targetSelectorOrRef: string | React.MutableRefObject<HTMLElement | null>
) {
return function shouldShowMenu(
event: ElectronEvent,
params: ContextMenuParams
) {
const elTarget =
typeof targetSelectorOrRef === 'string'
? document.querySelector(targetSelectorOrRef)
: targetSelectorOrRef.current;
if (!elTarget) {
return false;
}
const elCurrent = document.elementFromPoint(params.x, params.y);
if (!elCurrent) {
return false;
}
return elCurrent === elTarget || elTarget.contains(elCurrent);
};
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment