{"version":3,"file":"ContextMenu.mjs","sources":["../../../../src/components/ContextMenu/ContextMenu.tsx"],"sourcesContent":["import { useRef, useState, useLayoutEffect } from 'react';\nimport * as React from 'react';\nimport { useClickAway } from 'react-use';\n\nimport { selectors } from '@grafana/e2e-selectors';\n\nimport { Menu } from '../Menu/Menu';\nimport { Portal } from '../Portal/Portal';\n\nexport interface ContextMenuProps {\n  /** Starting horizontal position for the menu */\n  x: number;\n  /** Starting vertical position for the menu */\n  y: number;\n  /** Callback for closing the menu */\n  onClose?: () => void;\n  /** On menu open focus the first element */\n  focusOnOpen?: boolean;\n  /** RenderProp function that returns menu items to display */\n  renderMenuItems?: () => React.ReactNode;\n  /** A function that returns header element */\n  renderHeader?: () => React.ReactNode;\n}\n\n/**\n * A menu displaying additional options when it's not possible to show them at all times due to a space constraint.\n *\n * https://developers.grafana.com/ui/latest/index.html?path=/docs/overlays-contextmenu--docs\n */\nexport const ContextMenu = React.memo(\n  ({ x, y, onClose, focusOnOpen = true, renderMenuItems, renderHeader }: ContextMenuProps) => {\n    const menuRef = useRef<HTMLDivElement>(null);\n    const [positionStyles, setPositionStyles] = useState({});\n\n    useLayoutEffect(() => {\n      const menuElement = menuRef.current;\n      if (menuElement) {\n        const rect = menuElement.getBoundingClientRect();\n        const OFFSET = 5;\n        const collisions = {\n          right: window.innerWidth < x + rect.width,\n          bottom: window.innerHeight < y + rect.height + OFFSET,\n        };\n\n        setPositionStyles({\n          position: 'fixed',\n          left: collisions.right ? x - rect.width - OFFSET : x - OFFSET,\n          top: Math.max(0, collisions.bottom ? y - rect.height - OFFSET : y + OFFSET),\n        });\n      }\n    }, [x, y]);\n\n    useClickAway(menuRef, () => {\n      onClose?.();\n    });\n    const header = renderHeader?.();\n    const menuItems = renderMenuItems?.();\n    const onOpen = (setFocusedItem: (a: number) => void) => {\n      if (focusOnOpen) {\n        setFocusedItem(0);\n      }\n    };\n    const onKeyDown = (e: React.KeyboardEvent) => {\n      if (e.key === 'Escape') {\n        e.preventDefault();\n        e.stopPropagation();\n        onClose?.();\n      }\n    };\n\n    return (\n      <Portal>\n        <Menu\n          header={header}\n          ref={menuRef}\n          style={positionStyles}\n          ariaLabel={selectors.components.Menu.MenuComponent('Context')}\n          onOpen={onOpen}\n          onClick={onClose}\n          onKeyDown={onKeyDown}\n        >\n          {menuItems}\n        </Menu>\n      </Portal>\n    );\n  }\n);\n\nContextMenu.displayName = 'ContextMenu';\n"],"names":[],"mappings":";;;;;;;;;AA6BO,MAAM,cAAc,KAAA,CAAM,IAAA;AAAA,EAC/B,CAAC,EAAE,CAAA,EAAG,CAAA,EAAG,SAAS,WAAA,GAAc,IAAA,EAAM,eAAA,EAAiB,YAAA,EAAa,KAAwB;AAC1F,IAAA,MAAM,OAAA,GAAU,OAAuB,IAAI,CAAA;AAC3C,IAAA,MAAM,CAAC,cAAA,EAAgB,iBAAiB,CAAA,GAAI,QAAA,CAAS,EAAE,CAAA;AAEvD,IAAA,eAAA,CAAgB,MAAM;AACpB,MAAA,MAAM,cAAc,OAAA,CAAQ,OAAA;AAC5B,MAAA,IAAI,WAAA,EAAa;AACf,QAAA,MAAM,IAAA,GAAO,YAAY,qBAAA,EAAsB;AAC/C,QAAA,MAAM,MAAA,GAAS,CAAA;AACf,QAAA,MAAM,UAAA,GAAa;AAAA,UACjB,KAAA,EAAO,MAAA,CAAO,UAAA,GAAa,CAAA,GAAI,IAAA,CAAK,KAAA;AAAA,UACpC,MAAA,EAAQ,MAAA,CAAO,WAAA,GAAc,CAAA,GAAI,KAAK,MAAA,GAAS;AAAA,SACjD;AAEA,QAAA,iBAAA,CAAkB;AAAA,UAChB,QAAA,EAAU,OAAA;AAAA,UACV,MAAM,UAAA,CAAW,KAAA,GAAQ,IAAI,IAAA,CAAK,KAAA,GAAQ,SAAS,CAAA,GAAI,MAAA;AAAA,UACvD,GAAA,EAAK,IAAA,CAAK,GAAA,CAAI,CAAA,EAAG,UAAA,CAAW,MAAA,GAAS,CAAA,GAAI,IAAA,CAAK,MAAA,GAAS,MAAA,GAAS,CAAA,GAAI,MAAM;AAAA,SAC3E,CAAA;AAAA,MACH;AAAA,IACF,CAAA,EAAG,CAAC,CAAA,EAAG,CAAC,CAAC,CAAA;AAET,IAAA,YAAA,CAAa,SAAS,MAAM;AAC1B,MAAA,OAAA,IAAA,IAAA,GAAA,KAAA,CAAA,GAAA,OAAA,EAAA;AAAA,IACF,CAAC,CAAA;AACD,IAAA,MAAM,MAAA,GAAS,YAAA,IAAA,IAAA,GAAA,KAAA,CAAA,GAAA,YAAA,EAAA;AACf,IAAA,MAAM,SAAA,GAAY,eAAA,IAAA,IAAA,GAAA,KAAA,CAAA,GAAA,eAAA,EAAA;AAClB,IAAA,MAAM,MAAA,GAAS,CAAC,cAAA,KAAwC;AACtD,MAAA,IAAI,WAAA,EAAa;AACf,QAAA,cAAA,CAAe,CAAC,CAAA;AAAA,MAClB;AAAA,IACF,CAAA;AACA,IAAA,MAAM,SAAA,GAAY,CAAC,CAAA,KAA2B;AAC5C,MAAA,IAAI,CAAA,CAAE,QAAQ,QAAA,EAAU;AACtB,QAAA,CAAA,CAAE,cAAA,EAAe;AACjB,QAAA,CAAA,CAAE,eAAA,EAAgB;AAClB,QAAA,OAAA,IAAA,IAAA,GAAA,KAAA,CAAA,GAAA,OAAA,EAAA;AAAA,MACF;AAAA,IACF,CAAA;AAEA,IAAA,2BACG,MAAA,EAAA,EACC,QAAA,kBAAA,GAAA;AAAA,MAAC,IAAA;AAAA,MAAA;AAAA,QACC,MAAA;AAAA,QACA,GAAA,EAAK,OAAA;AAAA,QACL,KAAA,EAAO,cAAA;AAAA,QACP,SAAA,EAAW,SAAA,CAAU,UAAA,CAAW,IAAA,CAAK,cAAc,SAAS,CAAA;AAAA,QAC5D,MAAA;AAAA,QACA,OAAA,EAAS,OAAA;AAAA,QACT,SAAA;AAAA,QAEC,QAAA,EAAA;AAAA;AAAA,KACH,EACF,CAAA;AAAA,EAEJ;AACF;AAEA,WAAA,CAAY,WAAA,GAAc,aAAA;;;;"}