From c32878dea92ada47b57b5d167d21514fe4bee001 Mon Sep 17 00:00:00 2001 From: austaras Date: Mon, 1 Aug 2022 16:37:18 +0800 Subject: [PATCH] fix(plugin): fix left menu behavior --- .../components/editor-core/src/RenderRoot.tsx | 22 ++--- libs/components/editor-core/src/Selection.tsx | 11 +-- .../src/editor/drag-drop/drag-drop.ts | 47 ++++------ .../editor-core/src/editor/editor.ts | 13 +++ .../editor-core/src/editor/plugin/hooks.ts | 12 +-- .../src/editor/selection/selection.ts | 15 +-- .../editor-core/src/editor/types.ts | 10 +- .../src/menu/group-menu/GropuMenu.tsx | 31 ++++--- .../src/menu/left-menu/LeftMenu.tsx | 58 ++++++------ .../src/menu/left-menu/LeftMenuDraggable.tsx | 72 ++++++--------- .../src/menu/left-menu/LeftMenuPlugin.tsx | 92 ++++++++++--------- 11 files changed, 173 insertions(+), 210 deletions(-) diff --git a/libs/components/editor-core/src/RenderRoot.tsx b/libs/components/editor-core/src/RenderRoot.tsx index 06e0f22804593..aed9ebea50ba3 100644 --- a/libs/components/editor-core/src/RenderRoot.tsx +++ b/libs/components/editor-core/src/RenderRoot.tsx @@ -1,5 +1,4 @@ import type { BlockEditor } from './editor'; -import { Point } from '@toeverything/utils'; import { styled, usePatchNodes } from '@toeverything/components/ui'; import type { FC, PropsWithChildren } from 'react'; import React, { useEffect, useRef, useState, useCallback } from 'react'; @@ -76,20 +75,6 @@ export const RenderRoot: FC> = ({ ) => { selectionRef.current?.onMouseMove(event); editor.getHooks().onRootNodeMouseMove(event); - - const slidingBlock = await editor.getBlockByPoint( - new Point(event.clientX, event.clientY) - ); - - if (slidingBlock && slidingBlock.dom) { - editor.getHooks().afterOnNodeMouseMove(event, { - blockId: slidingBlock.id, - dom: slidingBlock.dom, - rect: slidingBlock.dom.getBoundingClientRect(), - type: slidingBlock.type, - properties: slidingBlock.getProperties(), - }); - } }; const onMouseDown = ( @@ -142,6 +127,12 @@ export const RenderRoot: FC> = ({ } }; + const onDragLeave = (event: React.DragEvent) => { + if (editor.dragDropManager.isEnabled()) { + editor.getHooks().onRootNodeDragLeave(event); + } + }; + const onDragOverCapture = (event: React.DragEvent) => { event.preventDefault(); if (editor.dragDropManager.isEnabled()) { @@ -178,6 +169,7 @@ export const RenderRoot: FC> = ({ onKeyDownCapture={onKeyDownCapture} onKeyUp={onKeyUp} onDragOver={onDragOver} + onDragLeave={onDragLeave} onDragOverCapture={onDragOverCapture} onDragEnd={onDragEnd} onDrop={onDrop} diff --git a/libs/components/editor-core/src/Selection.tsx b/libs/components/editor-core/src/Selection.tsx index 9d2a4c1d6cf4f..4a31aa17d2d20 100644 --- a/libs/components/editor-core/src/Selection.tsx +++ b/libs/components/editor-core/src/Selection.tsx @@ -119,9 +119,7 @@ export const SelectionRect = forwardRef( startPointRef.current = new Point(event.clientX, event.clientY); startPointBlock.current = ((await selectionManager.rootDomReady()) && - (await selectionManager.getBlockByPoint( - startPointRef.current - ))) || + (await editor.getBlockByPoint(startPointRef.current))) || null; mouseType.current = 'down'; if (scrollManager.scrollContainer) { @@ -137,10 +135,9 @@ export const SelectionRect = forwardRef( if (mouseType.current === 'down') { endPointRef.current = new Point(event.clientX, event.clientY); if (startPointBlock.current) { - const endpointBlock = - await selectionManager.getBlockByPoint( - endPointRef.current - ); + const endpointBlock = await editor.getBlockByPoint( + endPointRef.current + ); // TODO: delete after multi-block text selection done // if drag out of startblock change selection type to block if (endpointBlock?.id === startPointBlock.current.id) { diff --git a/libs/components/editor-core/src/editor/drag-drop/drag-drop.ts b/libs/components/editor-core/src/editor/drag-drop/drag-drop.ts index b8f602fb2c7a5..d3160d56f596a 100644 --- a/libs/components/editor-core/src/editor/drag-drop/drag-drop.ts +++ b/libs/components/editor-core/src/editor/drag-drop/drag-drop.ts @@ -1,4 +1,4 @@ -import { domToRect, Point, ValueOf } from '@toeverything/utils'; +import { domToRect, Point } from '@toeverything/utils'; import { AsyncBlock } from '../..'; import { GridDropType } from '../commands/types'; import { Editor } from '../editor'; @@ -6,9 +6,10 @@ import { BlockDropPlacement, GroupDirection } from '../types'; // TODO: Evaluate implementing custom events with Rxjs import EventEmitter from 'eventemitter3'; -type DargType = - | ValueOf['dragActions']> - | ''; +enum DragType { + dragBlock = 'dragBlock', + dragGroup = 'dragGroup', +} const DRAG_STATE_CHANGE_EVENT_KEY = 'dragStateChange'; export class DragDropManager { @@ -18,16 +19,13 @@ export class DragDropManager { private _blockIdKey = 'blockId'; private _rootIdKey = 'rootId'; - private _dragType: DargType; + private _dragType?: DragType; private _blockDragDirection: BlockDropPlacement; - private _blockDragTargetId = ''; + private _blockDragTargetId?: string; private _dragBlockHotDistance = 20; - private _dragActions = { - dragBlock: 'dragBlock', - dragGroup: 'dragGroup', - } as const; + private _dragActions = DragType; private _isOnDrag = false; @@ -49,7 +47,6 @@ export class DragDropManager { constructor(editor: Editor) { this._editor = editor; this._enabled = true; - this._dragType = ''; this._blockDragDirection = BlockDropPlacement.none; this._initMouseEvent(); } @@ -58,7 +55,7 @@ export class DragDropManager { return this._dragType; } - set dragType(type: DargType) { + set dragType(type: DragType) { this._dragType = type; } @@ -119,22 +116,9 @@ export class DragDropManager { } } - public async getGroupBlockByPoint(point: Point) { - const blockList = await this._editor.getBlockList(); - return blockList.find(block => { - if (block.type === 'group' && block.dom) { - const rect = domToRect(block.dom); - if (rect.fromNewLeft(rect.left - 30).isContainPoint(point)) { - return true; - } - } - return false; - }); - } - private async _handleDropGroup(event: React.DragEvent) { const blockId = event.dataTransfer.getData(this._blockIdKey); - const toGroup = await this.getGroupBlockByPoint( + const toGroup = await this._editor.getGroupBlockByPoint( new Point(event.clientX, event.clientY) ); if (toGroup && blockId && toGroup.id !== blockId) { @@ -262,7 +246,7 @@ export class DragDropManager { this._handleDropGroup(event); } } - this.dragType = ''; + this.dragType = undefined; } public handlerEditorDragOver(event: React.DragEvent) { @@ -280,9 +264,14 @@ export class DragDropManager { } private _resetDragDropData() { - this._dragType = ''; + this._dragType = undefined; + this._setBlockDragDirection(BlockDropPlacement.none); + this._setBlockDragTargetId(undefined); + } + + public clearDropInfo() { this._setBlockDragDirection(BlockDropPlacement.none); - this._setBlockDragTargetId(''); + this._setBlockDragTargetId(undefined); } public async checkDragGroupDirection( diff --git a/libs/components/editor-core/src/editor/editor.ts b/libs/components/editor-core/src/editor/editor.ts index da46769ed5f83..73e7f6f7d5b88 100644 --- a/libs/components/editor-core/src/editor/editor.ts +++ b/libs/components/editor-core/src/editor/editor.ts @@ -389,6 +389,19 @@ export class Editor implements Virgo { }); } + public async getGroupBlockByPoint(point: Point) { + const blockList = await this.getBlockList(); + return blockList.find(block => { + if (block.type === 'group' && block.dom) { + const rect = domToRect(block.dom); + if (rect.fromNewLeft(rect.left - 30).isContainPoint(point)) { + return true; + } + } + return false; + }); + } + async undo() { await services.api.editorBlock.undo(this.workspace); } diff --git a/libs/components/editor-core/src/editor/plugin/hooks.ts b/libs/components/editor-core/src/editor/plugin/hooks.ts index 5a54bd78475f4..1c05308a84a3c 100644 --- a/libs/components/editor-core/src/editor/plugin/hooks.ts +++ b/libs/components/editor-core/src/editor/plugin/hooks.ts @@ -1,3 +1,4 @@ +import { DragEvent } from 'react'; import { Observable, Subject } from 'rxjs'; import { HooksRunner, HookType, BlockDomInfo, PluginHooks } from '../types'; @@ -86,13 +87,6 @@ export class Hooks implements HooksRunner, PluginHooks { this._runHook(HookType.ON_ROOTNODE_MOUSE_LEAVE, e); } - public afterOnNodeMouseMove( - e: React.MouseEvent, - node: BlockDomInfo - ): void { - this._runHook(HookType.AFTER_ON_NODE_MOUSE_MOVE, e, node); - } - public afterOnResize( e: React.MouseEvent ): void { @@ -103,6 +97,10 @@ export class Hooks implements HooksRunner, PluginHooks { this._runHook(HookType.ON_ROOTNODE_DRAG_OVER, e); } + public onRootNodeDragLeave(e: React.DragEvent): void { + this._runHook(HookType.ON_ROOTNODE_DRAG_LEAVE, e); + } + public onRootNodeDragEnd(e: React.DragEvent): void { this._runHook(HookType.ON_ROOTNODE_DRAG_END, e); } diff --git a/libs/components/editor-core/src/editor/selection/selection.ts b/libs/components/editor-core/src/editor/selection/selection.ts index ab57513965efe..b66d1b5fd6b69 100644 --- a/libs/components/editor-core/src/editor/selection/selection.ts +++ b/libs/components/editor-core/src/editor/selection/selection.ts @@ -293,21 +293,8 @@ export class SelectionManager implements VirgoSelection { return Boolean(rootBlock?.dom); } - public async getBlockByPoint(point: Point) { - const blockList = await this._editor.getBlockList(); - const outBlockList = blockList.filter(block => { - return ( - Boolean(block.dom) && domToRect(block.dom).isContainPoint(point) - ); - }); - - return outBlockList.length - ? outBlockList[outBlockList.length - 1] - : undefined; - } - public async isPointInBlocks(point: Point) { - return Boolean(this.getBlockByPoint(point)); + return Boolean(this._editor.getBlockByPoint(point)); } /** diff --git a/libs/components/editor-core/src/editor/types.ts b/libs/components/editor-core/src/editor/types.ts index c40db2ecbaa0e..f4124170148b1 100644 --- a/libs/components/editor-core/src/editor/types.ts +++ b/libs/components/editor-core/src/editor/types.ts @@ -22,6 +22,7 @@ import type { BlockCommands } from './commands/block-commands'; import type { DragDropManager } from './drag-drop'; import { MouseManager } from './mouse'; import { Observable } from 'rxjs'; +import { Point } from '@toeverything/utils'; // import { BrowserClipboard } from './clipboard/browser-clipboard'; @@ -105,6 +106,8 @@ export interface Virgo { // clipboard: BrowserClipboard; workspace: string; getBlockDomById: (id: string) => Promise; + getBlockByPoint: (point: Point) => Promise; + getGroupBlockByPoint: (point: Point) => Promise; isWhiteboard: boolean; mouseManager: MouseManager; } @@ -166,9 +169,9 @@ export enum HookType { ON_ROOTNODE_MOUSE_OUT = 'onRootNodeMouseOut', ON_ROOTNODE_MOUSE_LEAVE = 'onRootNodeMouseLeave', ON_SEARCH = 'onSearch', - AFTER_ON_NODE_MOUSE_MOVE = 'afterOnNodeMouseMove', AFTER_ON_RESIZE = 'afterOnResize', ON_ROOTNODE_DRAG_OVER = 'onRootNodeDragOver', + ON_ROOTNODE_DRAG_LEAVE = 'onRootNodeDragLeave', ON_ROOTNODE_DRAG_END = 'onRootNodeDragEnd', ON_ROOTNODE_DRAG_OVER_CAPTURE = 'onRootNodeDragOverCapture', ON_ROOTNODE_DROP = 'onRootNodeDrop', @@ -209,13 +212,10 @@ export interface HooksRunner { e: React.MouseEvent ) => void; onSearch: () => void; - afterOnNodeMouseMove: ( - e: React.MouseEvent, - node: BlockDomInfo - ) => void; afterOnResize: (e: React.MouseEvent) => void; onRootNodeDragOver: (e: React.DragEvent) => void; onRootNodeDragEnd: (e: React.DragEvent) => void; + onRootNodeDragLeave: (e: React.DragEvent) => void; onRootNodeDrop: (e: React.DragEvent) => void; afterOnNodeDragOver: ( e: React.DragEvent, diff --git a/libs/components/editor-plugins/src/menu/group-menu/GropuMenu.tsx b/libs/components/editor-plugins/src/menu/group-menu/GropuMenu.tsx index 8a33fd9b50688..790ee98636929 100644 --- a/libs/components/editor-plugins/src/menu/group-menu/GropuMenu.tsx +++ b/libs/components/editor-plugins/src/menu/group-menu/GropuMenu.tsx @@ -28,14 +28,11 @@ export const GroupMenu = function ({ editor, hooks }: GroupMenuProps) { const handleRootMouseMove = useCallback( async (e: React.MouseEvent) => { - const groupBlockNew = - await editor.dragDropManager.getGroupBlockByPoint( - new Point(e.clientX, e.clientY) - ); + const groupBlockNew = await editor.getGroupBlockByPoint( + new Point(e.clientX, e.clientY) + ); if (groupBlockNew) { setGroupBlock(groupBlockNew); - } else { - setGroupBlock(null); } }, [editor, setGroupBlock] @@ -59,10 +56,9 @@ export const GroupMenu = function ({ editor, hooks }: GroupMenuProps) { let groupBlockOnDragOver = null; const mousePoint = new Point(e.clientX, e.clientY); if (editor.dragDropManager.isDragGroup(e)) { - groupBlockOnDragOver = - await editor.dragDropManager.getGroupBlockByPoint( - mousePoint - ); + groupBlockOnDragOver = await editor.getGroupBlockByPoint( + mousePoint + ); if (groupBlockOnDragOver?.id === groupBlock?.id) { groupBlockOnDragOver = null; } @@ -83,10 +79,9 @@ export const GroupMenu = function ({ editor, hooks }: GroupMenuProps) { async (e: React.DragEvent) => { let groupBlockOnDrop = null; if (editor.dragDropManager.isDragGroup(e)) { - groupBlockOnDrop = - await editor.dragDropManager.getGroupBlockByPoint( - new Point(e.clientX, e.clientY) - ); + groupBlockOnDrop = await editor.getGroupBlockByPoint( + new Point(e.clientX, e.clientY) + ); if (groupBlockOnDrop?.id === groupBlock?.id) { groupBlockOnDrop = null; } @@ -95,6 +90,8 @@ export const GroupMenu = function ({ editor, hooks }: GroupMenuProps) { [editor, groupBlock] ); + const handleRootMouseLeave = useCallback(() => setGroupBlock(null), []); + const handleRootDragEnd = () => { setDragOverGroup(null); }; @@ -118,6 +115,11 @@ export const GroupMenu = function ({ editor, hooks }: GroupMenuProps) { .get(HookType.ON_ROOTNODE_DRAG_END) .subscribe(handleRootDragEnd) ); + sub.add( + hooks + .get(HookType.ON_ROOTNODE_MOUSE_LEAVE) + .subscribe(handleRootMouseLeave) + ); return () => { sub.unsubscribe(); }; @@ -127,6 +129,7 @@ export const GroupMenu = function ({ editor, hooks }: GroupMenuProps) { handleRootMouseDown, handleRootDragOver, handleRootDrop, + handleRootMouseLeave, ]); useEffect(() => { diff --git a/libs/components/editor-plugins/src/menu/left-menu/LeftMenu.tsx b/libs/components/editor-plugins/src/menu/left-menu/LeftMenu.tsx index d153af97ada45..3dfd8e8b09a49 100644 --- a/libs/components/editor-plugins/src/menu/left-menu/LeftMenu.tsx +++ b/libs/components/editor-plugins/src/menu/left-menu/LeftMenu.tsx @@ -55,36 +55,36 @@ export function LeftMenu(props: LeftMenuProps) { const [menuList, setMenuList] = useState(menu); - const filter_items = ( - value: string, - menuList: CascaderItemProps[], - filterList: CascaderItemProps[] - ) => { - menuList.forEach(item => { - if (item?.subItems.length === 0) { - if (item.title.toLocaleLowerCase().indexOf(value) !== -1) { - filterList.push(item); - } - } else { - filter_items(value, item.subItems || [], filterList); - } - }); - }; + // const filterItems = ( + // value: string, + // menuList: CascaderItemProps[], + // filterList: CascaderItemProps[] + // ) => { + // menuList.forEach(item => { + // if (item?.subItems.length === 0) { + // if (item.title.toLocaleLowerCase().indexOf(value) !== -1) { + // filterList.push(item); + // } + // } else { + // filterItems(value, item.subItems || [], filterList); + // } + // }); + // }; - const on_filter = ( - e: React.ChangeEvent - ) => { - const value = e.currentTarget.value; - if (!value) { - setMenuList(menu); - } else { - const filterList: CascaderItemProps[] = []; - filter_items(value.toLocaleLowerCase(), menu, filterList); - setMenuList( - filterList.length > 0 ? filterList : [{ title: 'No Result' }] - ); - } - }; + // const on_filter = ( + // e: React.ChangeEvent + // ) => { + // const value = e.currentTarget.value; + // if (!value) { + // setMenuList(menu); + // } else { + // const filterList: CascaderItemProps[] = []; + // filter_items(value.toLocaleLowerCase(), menu, filterList); + // setMenuList( + // filterList.length > 0 ? filterList : [{ title: 'No Result' }] + // ); + // } + // }; return ( <> diff --git a/libs/components/editor-plugins/src/menu/left-menu/LeftMenuDraggable.tsx b/libs/components/editor-plugins/src/menu/left-menu/LeftMenuDraggable.tsx index e8e8b0fc6da7a..602c08aacbf73 100644 --- a/libs/components/editor-plugins/src/menu/left-menu/LeftMenuDraggable.tsx +++ b/libs/components/editor-plugins/src/menu/left-menu/LeftMenuDraggable.tsx @@ -10,8 +10,7 @@ import { Button } from '@toeverything/components/common'; import { styled } from '@toeverything/components/ui'; import { LeftMenu } from './LeftMenu'; -import { debounce } from '@toeverything/utils'; -import type { Subject } from 'rxjs'; +import { distinctUntilChanged, Subject } from 'rxjs'; import { HandleChildIcon } from '@toeverything/components/icons'; import { MENU_WIDTH } from './menu-config'; @@ -123,33 +122,24 @@ export const LeftMenuDraggable: FC = props => { const [block, setBlock] = useState(); const [line, setLine] = useState(undefined); - const handleDragStart = (event: React.DragEvent) => { - window.addEventListener('dragover', handleDragOverCapture, { - capture: true, - }); - - const onDragStart = async (event: React.DragEvent) => { - editor.dragDropManager.isOnDrag = true; - if (block == null) return; - setRootRect(editor.container.getBoundingClientRect()); - const dragImage = await editor.blockHelper.getBlockDragImg( - block.blockId - ); - if (dragImage) { - event.dataTransfer.setDragImage(dragImage, -50, -10); - editor.dragDropManager.setDragBlockInfo(event, block.blockId); - } - setVisible(false); - }; - onDragStart(event); + const handleDragStart = async (event: React.DragEvent) => { event.stopPropagation(); + setVisible(false); + + editor.dragDropManager.isOnDrag = true; + if (block == null) return; + setRootRect(editor.container.getBoundingClientRect()); + const dragImage = await editor.blockHelper.getBlockDragImg( + block.blockId + ); + if (dragImage) { + event.dataTransfer.setDragImage(dragImage, -50, -10); + editor.dragDropManager.setDragBlockInfo(event, block.blockId); + } }; const handleDragEnd = (event: React.DragEvent) => { event.preventDefault(); - window.removeEventListener('dragover', handleDragOverCapture, { - capture: true, - }); setLine(undefined); }; @@ -161,28 +151,20 @@ export const LeftMenuDraggable: FC = props => { setAnchorEl(currentTarget); }; - /** - * clear line info - */ - const handleDragOverCapture = debounce((e: MouseEvent) => { - const { target } = e; - if ( - target instanceof HTMLElement && - (!target.closest('[data-block-id]') || - !editor.container.contains(target)) - ) { - setLine(undefined); - } - }, 10); - useEffect(() => { - const sub = blockInfo.subscribe(block => { - setBlock(block); - if (block != null) { - setRootRect(editor.container.getBoundingClientRect()); - setVisible(true); - } - }); + const sub = blockInfo + .pipe( + distinctUntilChanged( + (prev, curr) => prev?.blockId === curr?.blockId + ) + ) + .subscribe(block => { + setBlock(block); + if (block != null) { + setRootRect(editor.container.getBoundingClientRect()); + setVisible(true); + } + }); return () => sub.unsubscribe(); }, [blockInfo, editor]); diff --git a/libs/components/editor-plugins/src/menu/left-menu/LeftMenuPlugin.tsx b/libs/components/editor-plugins/src/menu/left-menu/LeftMenuPlugin.tsx index 08f80c13bb8c8..00d301287eb65 100644 --- a/libs/components/editor-plugins/src/menu/left-menu/LeftMenuPlugin.tsx +++ b/libs/components/editor-plugins/src/menu/left-menu/LeftMenuPlugin.tsx @@ -10,7 +10,6 @@ import { domToRect, last, Point } from '@toeverything/utils'; export class LeftMenuPlugin extends BasePlugin { private _mousedown?: boolean; private _root?: PluginRenderRoot; - private _preBlockId: string; private _hideTimer: number; private _blockInfo: Subject = new Subject(); @@ -23,7 +22,7 @@ export class LeftMenuPlugin extends BasePlugin { public override init(): void { this.sub.add( this.hooks - .get(HookType.AFTER_ON_NODE_MOUSE_MOVE) + .get(HookType.ON_ROOTNODE_MOUSE_MOVE) .subscribe(this._handleMouseMove) ); this.sub.add( @@ -31,11 +30,6 @@ export class LeftMenuPlugin extends BasePlugin { .get(HookType.ON_ROOTNODE_MOUSE_DOWN) .subscribe(this._handleMouseDown) ); - this.sub.add( - this.hooks - .get(HookType.ON_ROOTNODE_MOUSE_LEAVE) - .subscribe(this._hideLeftMenu) - ); this.sub.add( this.hooks .get(HookType.ON_ROOTNODE_MOUSE_UP) @@ -46,10 +40,22 @@ export class LeftMenuPlugin extends BasePlugin { .get(HookType.AFTER_ON_NODE_DRAG_OVER) .subscribe(this._handleDragOverBlockNode) ); + this.sub.add( + this.hooks.get(HookType.ON_ROOTNODE_MOUSE_LEAVE).subscribe(() => { + this._hideLeftMenu(); + this._lineInfo.next(undefined); + }) + ); + this.sub.add( + this.hooks.get(HookType.ON_ROOTNODE_DRAG_LEAVE).subscribe(() => { + this.editor.dragDropManager.clearDropInfo(); + this._lineInfo.next(undefined); + }) + ); this.sub.add( this.hooks .get(HookType.ON_ROOT_NODE_KEYDOWN) - .subscribe(this._handleKeyDown) + .subscribe(this._hideLeftMenu) ); this.sub.add( this.hooks.get(HookType.ON_ROOTNODE_DROP).subscribe(this._onDrop) @@ -57,7 +63,6 @@ export class LeftMenuPlugin extends BasePlugin { } private _onDrop = () => { - this._preBlockId = ''; this._lineInfo.next(undefined); }; private _handleDragOverBlockNode = async ([event, blockInfo]: [ @@ -80,10 +85,9 @@ export class LeftMenuPlugin extends BasePlugin { } }; - private _handleMouseMove = async ([e, node]: [ - React.MouseEvent, - BlockDomInfo - ]) => { + private _handleMouseMove = async ( + event: React.MouseEvent + ) => { if (!this._hideTimer) { this._hideTimer = window.setTimeout(() => { if (this._mousedown) { @@ -97,31 +101,40 @@ export class LeftMenuPlugin extends BasePlugin { this._hideLeftMenu(); return; } - if (node.blockId !== this._preBlockId) { - if (node.dom) { - const mousePoint = new Point(e.clientX, e.clientY); - const children = await ( - await this.editor.getBlockById(node.blockId) - ).children(); - // if mouse point is between the first and last child do not show left menu - if (children.length) { - const firstChildren = children[0]; - const lastChildren = last(children); - if (firstChildren.dom && lastChildren.dom) { - const firstChildrenRect = domToRect(firstChildren.dom); - const lastChildrenRect = domToRect(lastChildren.dom); - if ( - firstChildrenRect.top < mousePoint.y && - lastChildrenRect.bottom > mousePoint.y - ) { - return; - } + const node = await this.editor.getBlockByPoint( + new Point(event.clientX, event.clientY) + ); + if (node == null || ignoreBlockTypes.includes(node.type)) { + return; + } + if (node.dom) { + const mousePoint = new Point(event.clientX, event.clientY); + const children = await ( + await this.editor.getBlockById(node.id) + ).children(); + // if mouse point is between the first and last child do not show left menu + if (children.length) { + const firstChildren = children[0]; + const lastChildren = last(children); + if (firstChildren.dom && lastChildren.dom) { + const firstChildrenRect = domToRect(firstChildren.dom); + const lastChildrenRect = domToRect(lastChildren.dom); + if ( + firstChildrenRect.top < mousePoint.y && + lastChildrenRect.bottom > mousePoint.y + ) { + return; } } } - this._preBlockId = node.blockId; - this._showLeftMenu(node); } + this._blockInfo.next({ + blockId: node.id, + dom: node.dom, + rect: node.dom.getBoundingClientRect(), + type: node.type, + properties: node.getProperties(), + }); }; private _handleMouseUp() { @@ -140,17 +153,6 @@ export class LeftMenuPlugin extends BasePlugin { this._blockInfo.next(undefined); }; - private _handleKeyDown = () => { - this._hideLeftMenu(); - }; - - private _showLeftMenu = (blockInfo: BlockDomInfo): void => { - if (ignoreBlockTypes.includes(blockInfo.type)) { - return; - } - this._blockInfo.next(blockInfo); - }; - protected override _onRender(): void { this._root = new PluginRenderRoot({ name: LeftMenuPlugin.pluginName,