diff --git a/packages/block-editor/package.json b/packages/block-editor/package.json index c86d2ffa..141b698d 100644 --- a/packages/block-editor/package.json +++ b/packages/block-editor/package.json @@ -1,6 +1,6 @@ { "name": "@wrnexus/block-editor", - "version": "0.1.10", + "version": "0.1.11", "type": "module", "description": "Hydrated accessible editor runtime for WRNexus block documents.", "exports": { diff --git a/packages/block-editor/src/canvas.ts b/packages/block-editor/src/canvas.ts index 64540284..c45851bf 100644 --- a/packages/block-editor/src/canvas.ts +++ b/packages/block-editor/src/canvas.ts @@ -22,6 +22,10 @@ export function mountBlockCanvas(root: HTMLElement, tree: BlockNode, options: Mo handle.setAttribute("aria-label", `Move ${node.type}`); handle.style.touchAction = "none"; handle.textContent = "⋮⋮"; + // Clicks must not bubble into selection or inline-edit handlers. + // Pointer/keyboard sensor events remain available to the DnD backend. + for (const name of ["click", "dblclick"]) + handle.addEventListener(name, event => { event.preventDefault(); event.stopPropagation(); }); element.prepend(handle); cleanup.push(() => handle.remove()); } diff --git a/packages/block-editor/test/canvas.test.ts b/packages/block-editor/test/canvas.test.ts index 6dbddcb1..fe5f9bdd 100644 --- a/packages/block-editor/test/canvas.test.ts +++ b/packages/block-editor/test/canvas.test.ts @@ -20,6 +20,16 @@ test("canvas annotates exact node locations and cleans editor decorations withou expect(column.getAttribute("data-block-slot")).toBe("content"); expect(column.getAttribute("draggable")).toBe("false"); expect(root.querySelectorAll("[data-block-handle]")).toHaveLength(1); + const handle = root.querySelector("[data-block-handle]")!; + let clicks = 0, pointers = 0; + column.addEventListener("click", () => clicks++); + column.addEventListener("dblclick", () => clicks++); + column.addEventListener("pointerdown", () => pointers++); + handle.dispatchEvent(new window.MouseEvent("click", { bubbles: true })); + handle.dispatchEvent(new window.MouseEvent("dblclick", { bubbles: true })); + handle.dispatchEvent(new window.PointerEvent("pointerdown", { bubbles: true })); + expect(clicks).toBe(0); + expect(pointers).toBe(1); expect(root.querySelector("[data-block-slot-target]")?.getAttribute("data-block-parent")).toBe("column"); expect(JSON.stringify(tree)).toBe(before); mounted.destroy(); mounted.destroy();