import type { ContextMenuProps as BluePrintContextMenuProps, MenuItemProps, TooltipProps, } from '@blueprintjs/core'; import { Menu, MenuItem, Tooltip, showContextMenu } from '@blueprintjs/core'; import type { ComponentProps, ElementType, MouseEvent, ReactNode } from 'react'; type ContextMenuCheck = boolean | ((data: any) => boolean); export interface ContextMenuItem extends Omit { data?: object; tooltip?: TooltipProps; disabled?: ContextMenuCheck; visible?: ContextMenuCheck; } type ElementProps = E extends ElementType ? ComponentProps : never; export interface BaseContextMenuProps { options: ContextMenuItem[]; onSelect: (data?: object) => void; } interface ContextMenuProps extends BaseContextMenuProps, Omit { as?: E; children: ReactNode; data?: any; } export function ContextMenu( props: ContextMenuProps & ElementProps, ) { const { options, onSelect, children, as: Wrapper = 'div', data, ...other } = props; function handleContextMenu(event: MouseEvent) { if (!Array.isArray(options) || options.length === 0) { return; } const content = ( {options .filter(({ visible = true }: any) => typeof visible === 'function' ? visible(data) : visible, ) .map(({ tooltip = {}, ...options }: any) => { const { disabled = false, visible, ...otherOptions } = options; const isDisabled = typeof disabled === 'function' ? disabled(data) : disabled; return ( (
onSelect(otherOptions?.data)} />
)} key={otherOptions.text} {...tooltip} /> ); })}
); event.preventDefault(); showContextMenu({ content, targetOffset: { left: event.clientX, top: event.clientY, }, }); } return ( {children} ); }