@grafana/ui
Version:
Grafana Components Library
1 lines • 4.77 kB
Source Map (JSON)
{"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;;;;"}