From d31058b1978d55e10a721a0fd86ecde8f8a321af Mon Sep 17 00:00:00 2001 From: Guillaume Fauvet Date: Thu, 27 Aug 2026 16:28:22 +0200 Subject: [PATCH] fix(sorter): keep the placeholder attached when the editor is in a shadow root MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Sorter#ensurePlaceholderElement re-appended the placeholder to containerContext.container whenever `!el.ownerDocument.contains(el)`. `Node.contains` walks the node tree without crossing shadow boundaries, so for an editor mounted in a shadow root the guard always answered "not attached" — the placeholder element is `Canvas#getPlacerEl()`, which lives in the tools layer, i.e. in the host page DOM. Every placeholder move therefore ripped it out of the tools layer and injected it into the container, which for the canvas sorters is the iframe body (Droppable, SelectPosition and BlocksView all pair `getPlacerEl()` with the canvas body). The GrapesJS stylesheet is not loaded there, so the placeholder became invisible. Fix: test `el.isConnected`, the shadow-aware equivalent, which behaves identically outside shadow DOM. Introduced by the sorter refactor in #6149 (0.22.1). The previous implementation only appended the placeholder when the `placer` option was absent, and the canvas sorters always passed it, so the append branch was never taken. --- packages/core/src/utils/sorter/Sorter.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/core/src/utils/sorter/Sorter.ts b/packages/core/src/utils/sorter/Sorter.ts index 78897968f..a366860bf 100644 --- a/packages/core/src/utils/sorter/Sorter.ts +++ b/packages/core/src/utils/sorter/Sorter.ts @@ -173,7 +173,7 @@ export default class Sorter> { private ensurePlaceholderElement() { const el = this.placeholder.el; const container = this.containerContext.container; - if (!el.ownerDocument.contains(el)) { + if (!el.isConnected) { container.append(this.placeholder.el); } }