From b7a58bfc14918249a57d0c4bfe77cfe2eee43809 Mon Sep 17 00:00:00 2001 From: Matthew Lipski Date: Thu, 6 Jun 2024 13:19:41 +0200 Subject: [PATCH 1/3] Fixed logic for getting block from coords --- .../src/extensions/SideMenu/SideMenuPlugin.ts | 56 ++++++++----------- .../TableHandles/TableHandlesPlugin.ts | 4 +- 2 files changed, 25 insertions(+), 35 deletions(-) diff --git a/packages/core/src/extensions/SideMenu/SideMenuPlugin.ts b/packages/core/src/extensions/SideMenu/SideMenuPlugin.ts index 1db5aecb92..92c8a10945 100644 --- a/packages/core/src/extensions/SideMenu/SideMenuPlugin.ts +++ b/packages/core/src/extensions/SideMenu/SideMenuPlugin.ts @@ -26,46 +26,26 @@ export type SideMenuState< block: Block; }; -export function getDraggableBlockFromCoords( - coords: { left: number; top: number }, +export function getDraggableBlockFromElement( + element: Element, view: EditorView ) { - if (!view.dom.isConnected) { - // view is not connected to the DOM, this can cause posAtCoords to fail - // (Cannot read properties of null (reading 'nearestDesc'), https://github.com/TypeCellOS/BlockNote/issues/123) - return undefined; - } - - const pos = view.posAtCoords(coords); - if (!pos) { - return undefined; - } - let node = view.domAtPos(pos.pos).node as HTMLElement; - - if (node === view.dom) { - // mouse over root - return undefined; - } - while ( - node && - node.parentNode && - node.parentNode !== view.dom && - !node.hasAttribute?.("data-id") + element && + element.parentElement && + element.parentElement !== view.dom && + !element.hasAttribute?.("data-id") ) { - node = node.parentNode as HTMLElement; + element = element.parentElement; } - if (!node) { + if (!element.hasAttribute("data-id")) { return undefined; } - return { node, id: node.getAttribute("data-id")! }; + return { node: element as HTMLElement, id: element.getAttribute("data-id")! }; } -function blockPositionFromCoords( - coords: { left: number; top: number }, - view: EditorView -) { - const block = getDraggableBlockFromCoords(coords, view); +function blockPositionFromElement(element: Element, view: EditorView) { + const block = getDraggableBlockFromElement(element, view); if (block && block.node.nodeType === 1) { // TODO: this uses undocumented PM APIs? do we need this / let's add docs? @@ -197,7 +177,12 @@ function dragStart< top: e.clientY, }; - const pos = blockPositionFromCoords(coords, view); + const element = document.elementFromPoint(coords.left, coords.top); + if (element === null) { + return; + } + + const pos = blockPositionFromElement(element, view); if (pos != null) { const selection = view.state.selection; const doc = view.state.doc; @@ -327,7 +312,12 @@ export class SideMenuView< left: editorBoundingBox.left + editorBoundingBox.width / 2, // take middle of editor top: this.mousePos.y, }; - const block = getDraggableBlockFromCoords(coords, this.pmView); + const element = document.elementFromPoint(coords.left, coords.top); + if (element === null) { + return; + } + + const block = getDraggableBlockFromElement(element, this.pmView); // Closes the menu if the mouse cursor is beyond the editor vertically. if (!block || !this.editor.isEditable) { diff --git a/packages/core/src/extensions/TableHandles/TableHandlesPlugin.ts b/packages/core/src/extensions/TableHandles/TableHandlesPlugin.ts index eb5172769a..57f1533773 100644 --- a/packages/core/src/extensions/TableHandles/TableHandlesPlugin.ts +++ b/packages/core/src/extensions/TableHandles/TableHandlesPlugin.ts @@ -11,7 +11,7 @@ import { } from "../../schema"; import { checkBlockIsDefaultType } from "../../blocks/defaultBlockTypeGuards"; import { EventEmitter } from "../../util/EventEmitter"; -import { getDraggableBlockFromCoords } from "../SideMenu/SideMenuPlugin"; +import { getDraggableBlockFromElement } from "../SideMenu/SideMenuPlugin"; let dragImageElement: HTMLElement | undefined; @@ -146,7 +146,7 @@ export class TableHandlesView< const tableRect = target.parentElement!.parentElement!.getBoundingClientRect(); - const blockEl = getDraggableBlockFromCoords(cellRect, this.pmView); + const blockEl = getDraggableBlockFromElement(target, this.pmView); if (!blockEl) { return; } From 836f4bf1ba27397e74cee2e03ad71a2eacaac374 Mon Sep 17 00:00:00 2001 From: Matthew Lipski Date: Thu, 6 Jun 2024 14:31:43 +0200 Subject: [PATCH 2/3] Fixed side menu not showing when hovering other menus --- .../core/src/extensions/SideMenu/SideMenuPlugin.ts | 14 +++++++++----- 1 file changed, 9 insertions(+), 5 deletions(-) diff --git a/packages/core/src/extensions/SideMenu/SideMenuPlugin.ts b/packages/core/src/extensions/SideMenu/SideMenuPlugin.ts index 92c8a10945..18f9da3f0a 100644 --- a/packages/core/src/extensions/SideMenu/SideMenuPlugin.ts +++ b/packages/core/src/extensions/SideMenu/SideMenuPlugin.ts @@ -312,12 +312,16 @@ export class SideMenuView< left: editorBoundingBox.left + editorBoundingBox.width / 2, // take middle of editor top: this.mousePos.y, }; - const element = document.elementFromPoint(coords.left, coords.top); - if (element === null) { - return; - } - const block = getDraggableBlockFromElement(element, this.pmView); + const elements = document.elementsFromPoint(coords.left, coords.top); + let block = undefined; + + for (const element of elements) { + if (this.pmView.dom.contains(element)) { + block = getDraggableBlockFromElement(element, this.pmView); + break; + } + } // Closes the menu if the mouse cursor is beyond the editor vertically. if (!block || !this.editor.isEditable) { From 0e22af45c60f19fd4c111af8eb19fdd8d3832d53 Mon Sep 17 00:00:00 2001 From: Matthew Lipski Date: Thu, 6 Jun 2024 15:30:13 +0200 Subject: [PATCH 3/3] Test fixes --- .../src/extensions/SideMenu/SideMenuPlugin.ts | 15 ++++++++++++--- tests/src/end-to-end/dragdrop/dragdrop.test.ts | 5 ----- tests/src/end-to-end/shadcn/shadcn.test.ts | 2 +- 3 files changed, 13 insertions(+), 9 deletions(-) diff --git a/packages/core/src/extensions/SideMenu/SideMenuPlugin.ts b/packages/core/src/extensions/SideMenu/SideMenuPlugin.ts index 18f9da3f0a..5e73ed79d1 100644 --- a/packages/core/src/extensions/SideMenu/SideMenuPlugin.ts +++ b/packages/core/src/extensions/SideMenu/SideMenuPlugin.ts @@ -177,12 +177,21 @@ function dragStart< top: e.clientY, }; - const element = document.elementFromPoint(coords.left, coords.top); - if (element === null) { + const elements = document.elementsFromPoint(coords.left, coords.top); + let blockEl = undefined; + + for (const element of elements) { + if (view.dom.contains(element)) { + blockEl = getDraggableBlockFromElement(element, view); + break; + } + } + + if (!blockEl) { return; } - const pos = blockPositionFromElement(element, view); + const pos = blockPositionFromElement(blockEl.node, view); if (pos != null) { const selection = view.state.selection; const doc = view.state.doc; diff --git a/tests/src/end-to-end/dragdrop/dragdrop.test.ts b/tests/src/end-to-end/dragdrop/dragdrop.test.ts index eb7350add2..f51fd953f1 100644 --- a/tests/src/end-to-end/dragdrop/dragdrop.test.ts +++ b/tests/src/end-to-end/dragdrop/dragdrop.test.ts @@ -66,23 +66,18 @@ test.describe("Check Block Dragging Functionality", () => { // Dragging first heading into next nested element. let dragTarget = await page.locator(H_ONE_BLOCK_SELECTOR); let dropTarget = await page.locator(H_TWO_BLOCK_SELECTOR); - await page.pause(); await dragAndDropBlock(page, dragTarget, dropTarget, true); // Dragging second heading into next nested element. dragTarget = await page.locator(H_TWO_BLOCK_SELECTOR); dropTarget = await page.locator(H_THREE_BLOCK_SELECTOR); - await page.pause(); await dragAndDropBlock(page, dragTarget, dropTarget, true); // Dragging third heading into outside nesting. dragTarget = await page.locator(H_THREE_BLOCK_SELECTOR); dropTarget = await page.locator(BLOCK_CONTAINER_SELECTOR).last(); - await page.pause(); await dragAndDropBlock(page, dragTarget, dropTarget, true); - await page.pause(); - await compareDocToSnapshot(page, "dragdropnested"); }); }); diff --git a/tests/src/end-to-end/shadcn/shadcn.test.ts b/tests/src/end-to-end/shadcn/shadcn.test.ts index 9569774c55..63f7872308 100644 --- a/tests/src/end-to-end/shadcn/shadcn.test.ts +++ b/tests/src/end-to-end/shadcn/shadcn.test.ts @@ -31,7 +31,7 @@ test.describe("Check ShadCN UI", () => { await page.keyboard.press("Shift+Home"); await page.waitForSelector(LINK_BUTTON_SELECTOR); - await page.click(LINK_BUTTON_SELECTOR); + await page.click(LINK_BUTTON_SELECTOR, { position: { x: 5, y: 5 } }); await page.keyboard.type("link"); await page.keyboard.press("Enter");