import classNames from "classnames" ; import * as React from "react" ; import { Classes as CoreClasses , IOverlayLifecycleProps , Portal , Props , Utils as CoreUtils , mergeRefs , } from "@blueprintjs/core" ; import * as Classes from "./classes" ; import { Popover2Props , Popover2 } from "./popover2" ; import { Popover2TargetProps } from "./popover2SharedProps" ; import { Tooltip2Context , Tooltip2Provider } from "./tooltip2Context" ; type Offset = { left : number ; top : number ; } ; /**
 * Render props relevant to the _content_ of a context menu (rendered as the underlying Popover's content).
 */ export interface ContextMenu2ContentProps { /** Whether the context menu is currently open. */ isOpen : boolean ; /**
     * The computed target offset (x, y) coordinates for the context menu click event.
     * On first render, before any context menu click event has occurred, this will be undefined.
     */ targetOffset : Offset | undefined ; /** The context menu click event. If isOpen is false, this will be undefined. */ mouseEvent : React . MouseEvent < HTMLElement > | undefined ; } deprecated export type ContextMenu2RenderProps = ContextMenu2ContentProps ; /**
 * Render props for advanced usage of ContextMenu.
 */ export interface ContextMenu2ChildrenProps { /** Context menu container element class */ className : string ; /** Render props relevant to the content of this context menu */ contentProps : ContextMenu2ContentProps ; /** Context menu handler which implements the custom context menu interaction */ onContextMenu : React . MouseEventHandler < HTMLElement > ; /** Popover element rendered by ContextMenu, used to establish a click target to position the menu */ popover : JSX . Element | undefined ; /** DOM ref for the context menu target, used to detect dark theme */ ref : React . Ref < any > ; } export interface ContextMenu2Props extends Omit < React . HTMLAttributes < HTMLElement > , "children" | "className" | "onContextMenu" > , React . RefAttributes < any > , Props { /**
     * Menu content. This will usually be a Blueprint `<Menu>` component.
     * This optionally functions as a render prop so you can use component state to render content.
     */ content : JSX . Element | ( ( props : ContextMenu2ContentProps ) => JSX . Element | undefined ) | undefined ; /**
     * The context menu target. This may optionally be a render function so you can use
     * component state to render the target.
     */ children : React . ReactNode | ( ( props : ContextMenu2ChildrenProps ) => React . ReactElement ) ; default disabled ? : boolean ; /**
     * An optional context menu event handler. This can be useful if you want to do something with the
     * mouse event unrelated to rendering the context menu itself, especially if that involves setting
     * React state (which is an error to do in the render code path of this component).
     */ onContextMenu ? : React . MouseEventHandler < HTMLElement > ; /**
     * A limited subset of props to forward along to the popover generated by this component.
     */ popoverProps ? : IOverlayLifecycleProps & Pick < Popover2Props , "popoverClassName" | "transitionDuration" > ; default tagName ? : keyof JSX . IntrinsicElements ; } export const ContextMenu2 = React . forwardRef < any , ContextMenu2Props > ( ( props , userRef ) => { const { className , children , content , disabled = false , onContextMenu , popoverProps , tagName = "div" , ... restProps } = props ; const [ , tooltipCtxDispatch ] = React . useContext ( Tooltip2Context ) ; const [ targetOffset , setTargetOffset ] = React . useState < Offset | undefined > ( undefined ) ; const [ mouseEvent , setMouseEvent ] = React . useState < React . MouseEvent < HTMLElement > > ( ) ; const [ isOpen , setIsOpen ] = React . useState < boolean > ( false ) ; const childRef = React . useRef < HTMLDivElement > ( null ) ; React . useEffect ( ( ) => { setIsOpen ( false ) ; tooltipCtxDispatch ( { type : "RESET_DISABLED_STATE" } ) ; } , [ disabled ] ) ; const cancelContextMenu = React . useCallback ( ( e ) => e . preventDefault ( ) , [ ] ) ; const handlePopoverInteraction = React . useCallback ( ( nextOpenState ) => { if ( ! nextOpenState ) { setIsOpen ( false ) ; setMouseEvent ( undefined ) ; tooltipCtxDispatch ( { type : "RESET_DISABLED_STATE" } ) ; } } , [ ] ) ; const renderTarget = React . useCallback ( ( { ref } ) => ( < Portal > < div className = { Classes . CONTEXT_MENU2_VIRTUAL_TARGET } style = { targetOffset } ref = { ref } / > < /Portal>), [targetOffset]); const isDarkTheme = React . useMemo ( ( ) => CoreUtils . isDarkTheme ( childRef . current ) , [ childRef , isOpen ] ) ; const contentProps = { isOpen , mouseEvent , targetOffset } ; const menu = disabled ? undefined : CoreUtils . isFunction ( content ) ? content ( contentProps ) : content ; const maybePopover = menu === undefined ? undefined : ( < Popover2 { ... popoverProps } content = { < div onContextMenu = { cancelContextMenu } > { menu } < /div>} enforceFocus={false}  key = { getPopoverKey ( targetOffset ) } hasBackdrop = { true } backdropProps = { { className : Classes . CONTEXT_MENU2_BACKDROP } } isOpen = { isOpen } minimal = { true } onInteraction = { handlePopoverInteraction } popoverClassName = { classNames ( Classes . CONTEXT_MENU2_POPOVER2 , popoverProps ?. popoverClassName , { [ CoreClasses . DARK ] : isDarkTheme , } ) } placement = "right-start" positioningStrategy = "fixed" rootBoundary = "viewport" renderTarget = { renderTarget } transitionDuration = { popoverProps ?. transitionDuration ?? 100 } />); const handleContextMenu = React . useCallback ( ( e ) => { if ( e . defaultPrevented ) { return ; } const shouldHandleEvent = ! disabled && ( CoreUtils . isFunction ( children ) || maybePopover !== undefined ) ; if ( shouldHandleEvent ) { e . preventDefault ( ) ; e . persist ( ) ; setMouseEvent ( e ) ; setTargetOffset ( { left : e . clientX , top : e . clientY } ) ; setIsOpen ( true ) ; tooltipCtxDispatch ( { type : "FORCE_DISABLED_STATE" } ) ; } onContextMenu ?. ( e ) ; } , [ onContextMenu , disabled ] ) ; const containerClassName = classNames ( className , Classes . CONTEXT_MENU2 ) ; const child = CoreUtils . isFunction ( children ) ? ( children ( { className : containerClassName , contentProps , onContextMenu : handleContextMenu , popover : maybePopover , ref : childRef , } ) ) : ( < > { maybePopover } { React . createElement < React . HTMLAttributes < any > > ( tagName , { className : containerClassName , onContextMenu : handleContextMenu , ref : mergeRefs ( childRef , userRef ) , ... restProps , } , children ) } < />); return < Tooltip2Provider forceDisable = { isOpen } > { child } < /Tooltip2Provider>; } ) ; ContextMenu2 . displayName = "Blueprint.ContextMenu2" ; function getPopoverKey ( targetOffset ) { return targetOffset === undefined ? "default" : `${ targetOffset . left }x${ targetOffset . top }` ; }