file-tree-context-menu.tsx 1.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960
  1. import React from 'react'
  2. import ReactDOM from 'react-dom'
  3. import { Dropdown } from 'react-bootstrap'
  4. import { useEditorContext } from '../../../shared/context/editor-context'
  5. import { useFileTreeMainContext } from '../contexts/file-tree-main'
  6. import FileTreeItemMenuItems from './file-tree-item/file-tree-item-menu-items'
  7. function FileTreeContextMenu() {
  8. const { permissionsLevel } = useEditorContext()
  9. const { contextMenuCoords, setContextMenuCoords } = useFileTreeMainContext()
  10. if (permissionsLevel === 'readOnly' || !contextMenuCoords) return null
  11. function close() {
  12. // reset context menu
  13. setContextMenuCoords(null)
  14. }
  15. function handleToggle(wantOpen: boolean) {
  16. if (!wantOpen) close()
  17. }
  18. function handleClick() {
  19. handleToggle(false)
  20. }
  21. return ReactDOM.createPortal(
  22. <Dropdown
  23. onClick={handleClick}
  24. open
  25. id="dropdown-file-tree-context-menu"
  26. onToggle={handleToggle}
  27. dropup={
  28. document.body.offsetHeight / contextMenuCoords.top < 2 &&
  29. document.body.offsetHeight - contextMenuCoords.top < 250
  30. }
  31. className="context-menu"
  32. style={contextMenuCoords}
  33. >
  34. <FakeDropDownToggle bsRole="toggle" />
  35. <Dropdown.Menu>
  36. <FileTreeItemMenuItems />
  37. </Dropdown.Menu>
  38. </Dropdown>,
  39. document.body
  40. )
  41. }
  42. // fake component required as Dropdowns require a Toggle, even tho we don't want
  43. // one for the context menu
  44. const FakeDropDownToggle = React.forwardRef<undefined, { bsRole: string }>(
  45. ({ bsRole }, ref) => {
  46. return null
  47. }
  48. )
  49. FakeDropDownToggle.displayName = 'FakeDropDownToggle'
  50. export default FileTreeContextMenu