button-menu.tsx 2.2 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495
  1. import { FC, memo, useRef } from 'react'
  2. import { Button, ListGroup, Overlay, Popover } from 'react-bootstrap'
  3. import Icon from '../../../../shared/components/icon'
  4. import useDropdown from '../../../../shared/hooks/use-dropdown'
  5. import Tooltip from '../../../../shared/components/tooltip'
  6. import { EditorView } from '@codemirror/view'
  7. import { emitCommandEvent } from '../../extensions/toolbar/utils/analytics'
  8. import { useCodeMirrorViewContext } from '../codemirror-editor'
  9. export const ToolbarButtonMenu: FC<{
  10. id: string
  11. label: string
  12. icon: string
  13. altCommand?: (view: EditorView) => void
  14. }> = memo(function ButtonMenu({ icon, id, label, altCommand, children }) {
  15. const target = useRef<any>(null)
  16. const { open, onToggle, ref } = useDropdown()
  17. const view = useCodeMirrorViewContext()
  18. const button = (
  19. <Button
  20. type="button"
  21. className="ol-cm-toolbar-button"
  22. aria-label={label}
  23. bsStyle={null}
  24. onMouseDown={event => {
  25. event.preventDefault()
  26. event.stopPropagation()
  27. }}
  28. onClick={event => {
  29. if (event.altKey && altCommand && open === false) {
  30. emitCommandEvent(view, id)
  31. event.preventDefault()
  32. altCommand(view)
  33. view.focus()
  34. } else {
  35. onToggle(!open)
  36. }
  37. }}
  38. ref={target}
  39. >
  40. <Icon type={icon} fw />
  41. </Button>
  42. )
  43. const overlay = (
  44. <Overlay
  45. show={open}
  46. target={target.current}
  47. placement="bottom"
  48. container={document.querySelector('.cm-editor')}
  49. containerPadding={0}
  50. animation
  51. onHide={() => onToggle(false)}
  52. >
  53. <Popover
  54. id={`${id}-menu`}
  55. ref={ref}
  56. className="ol-cm-toolbar-button-menu-popover"
  57. >
  58. <ListGroup
  59. role="menu"
  60. onClick={() => {
  61. onToggle(false)
  62. }}
  63. >
  64. {children}
  65. </ListGroup>
  66. </Popover>
  67. </Overlay>
  68. )
  69. if (!label) {
  70. return (
  71. <>
  72. {button}
  73. {overlay}
  74. </>
  75. )
  76. }
  77. return (
  78. <>
  79. <Tooltip
  80. hidden={open}
  81. id={id}
  82. description={<div>{label}</div>}
  83. overlayProps={{ placement: 'bottom' }}
  84. >
  85. {button}
  86. </Tooltip>
  87. {overlay}
  88. </>
  89. )
  90. })