|
@@ -1,21 +1,30 @@
|
|
|
-import React from 'react';
|
|
|
-import { useBlockSideToolbar } from './BlockSideToolbar.hooks';
|
|
|
-import ExpandCircleDownSharpIcon from '@mui/icons-material/ExpandCircleDownSharp';
|
|
|
-import DragIndicatorRoundedIcon from '@mui/icons-material/DragIndicatorRounded';
|
|
|
+import React, { useCallback, useContext, useState } from 'react';
|
|
|
+import { useBlockSideToolbar, usePopover } from './BlockSideToolbar.hooks';
|
|
|
import Portal from '../BlockPortal';
|
|
|
-import { IconButton } from '@mui/material';
|
|
|
-import BlockMenu from '../BlockMenu';
|
|
|
-import { useAppSelector } from '$app/stores/store';
|
|
|
-
|
|
|
-const sx = { height: 24, width: 24 };
|
|
|
+import { useAppDispatch, useAppSelector } from '$app/stores/store';
|
|
|
+import Popover from '@mui/material/Popover';
|
|
|
+import DragIndicatorRoundedIcon from '@mui/icons-material/DragIndicatorRounded';
|
|
|
+import AddSharpIcon from '@mui/icons-material/AddSharp';
|
|
|
+import BlockMenu from './BlockMenu';
|
|
|
+import ToolbarButton from './ToolbarButton';
|
|
|
+import { rectSelectionActions } from '$app_reducers/document/slice';
|
|
|
+import { addBlockBelowClickThunk } from '$app_reducers/document/async-actions/menu';
|
|
|
+import { DocumentControllerContext } from '$app/stores/effects/document/document_controller';
|
|
|
|
|
|
-export default function BlockSideToolbar(props: { container: HTMLDivElement }) {
|
|
|
- const { nodeId, style, ref, menuOpen, handleToggleMenu } = useBlockSideToolbar(props);
|
|
|
+export default function BlockSideToolbar({ container }: { container: HTMLDivElement }) {
|
|
|
+ const dispatch = useAppDispatch();
|
|
|
+ const controller = useContext(DocumentControllerContext);
|
|
|
+ const { nodeId, style, ref } = useBlockSideToolbar({ container });
|
|
|
const isDragging = useAppSelector(
|
|
|
(state) => state.documentRangeSelection.isDragging || state.documentRectSelection.isDragging
|
|
|
);
|
|
|
+ const { handleOpen, ...popoverProps } = usePopover();
|
|
|
+
|
|
|
+ // prevent popover from showing when anchorEl is not in DOM
|
|
|
+ const showPopover = popoverProps.anchorEl ? document.contains(popoverProps.anchorEl) : true;
|
|
|
|
|
|
if (!nodeId || isDragging) return null;
|
|
|
+
|
|
|
return (
|
|
|
<>
|
|
|
<Portal blockId={nodeId}>
|
|
@@ -32,15 +41,41 @@ export default function BlockSideToolbar(props: { container: HTMLDivElement }) {
|
|
|
e.stopPropagation();
|
|
|
}}
|
|
|
>
|
|
|
- <IconButton onClick={() => handleToggleMenu(true)} sx={sx}>
|
|
|
- <ExpandCircleDownSharpIcon />
|
|
|
- </IconButton>
|
|
|
- <IconButton sx={sx}>
|
|
|
+ {/** Add Block below */}
|
|
|
+ <ToolbarButton
|
|
|
+ tooltip={'Add a new block below'}
|
|
|
+ onClick={(e: React.MouseEvent<HTMLButtonElement>) => {
|
|
|
+ if (!nodeId || !controller) return;
|
|
|
+ dispatch(
|
|
|
+ addBlockBelowClickThunk({
|
|
|
+ id: nodeId,
|
|
|
+ controller,
|
|
|
+ })
|
|
|
+ );
|
|
|
+ }}
|
|
|
+ >
|
|
|
+ <AddSharpIcon />
|
|
|
+ </ToolbarButton>
|
|
|
+
|
|
|
+ {/** Open menu or drag */}
|
|
|
+ <ToolbarButton
|
|
|
+ tooltip={'Click to open Menu'}
|
|
|
+ onClick={(e: React.MouseEvent<HTMLButtonElement>) => {
|
|
|
+ if (!nodeId) return;
|
|
|
+ dispatch(rectSelectionActions.setSelectionById(nodeId));
|
|
|
+ handleOpen(e);
|
|
|
+ }}
|
|
|
+ >
|
|
|
<DragIndicatorRoundedIcon />
|
|
|
- </IconButton>
|
|
|
+ </ToolbarButton>
|
|
|
</div>
|
|
|
</Portal>
|
|
|
- <BlockMenu open={menuOpen} onClose={() => handleToggleMenu(false)} nodeId={nodeId} />
|
|
|
+
|
|
|
+ {showPopover && (
|
|
|
+ <Popover {...popoverProps}>
|
|
|
+ <BlockMenu id={nodeId} onClose={popoverProps.onClose} />
|
|
|
+ </Popover>
|
|
|
+ )}
|
|
|
</>
|
|
|
);
|
|
|
}
|