From 086beeb97d6f6959c8a3c434dee4014df737e9b5 Mon Sep 17 00:00:00 2001 From: Matthew Lipski Date: Thu, 7 May 2026 19:40:16 +0200 Subject: [PATCH] Added decoration to `TrailingNodeExtension` to hide trailing block when editor is read-only --- packages/core/src/editor/editor.css | 5 +++ .../extensions/TrailingNode/TrailingNode.ts | 36 +++++++++++++++++++ 2 files changed, 41 insertions(+) diff --git a/packages/core/src/editor/editor.css b/packages/core/src/editor/editor.css index a1a3dda7b0..7e65e448f0 100644 --- a/packages/core/src/editor/editor.css +++ b/packages/core/src/editor/editor.css @@ -195,3 +195,8 @@ For the ShowSelectionPlugin background-color: highlight; padding: 2px 0; } + +/* Hide trailing block when editor is not editable. */ +.bn-editor[contenteditable="false"] .bn-trailing-block { + display: none; +} diff --git a/packages/core/src/extensions/TrailingNode/TrailingNode.ts b/packages/core/src/extensions/TrailingNode/TrailingNode.ts index 523c5fef4a..e71e591439 100644 --- a/packages/core/src/extensions/TrailingNode/TrailingNode.ts +++ b/packages/core/src/extensions/TrailingNode/TrailingNode.ts @@ -1,4 +1,5 @@ import { Plugin, PluginKey } from "prosemirror-state"; +import { Decoration, DecorationSet } from "prosemirror-view"; import { createExtension } from "../../editor/BlockNoteExtension.js"; // based on https://github.com/ueberdosis/tiptap/blob/40a9404c94c7fef7900610c195536384781ae101/demos/src/Experiments/TrailingNode/Vue/trailing-node.ts @@ -19,6 +20,41 @@ export const TrailingNodeExtension = createExtension(() => { prosemirrorPlugins: [ new Plugin({ key: plugin, + props: { + decorations: (state) => { + const { doc } = state; + + const lastBlockGroup = doc.lastChild; + if (!lastBlockGroup || lastBlockGroup.type.name !== "blockGroup") { + return; + } + + const lastBlockContainer = lastBlockGroup.lastChild; + if ( + !lastBlockContainer || + lastBlockContainer.type.name !== "blockContainer" + ) { + return; + } + + const lastBlockContent = lastBlockContainer.firstChild; + if ( + !lastBlockContent || + lastBlockContent.type.spec.content !== "inline*" || + lastBlockContent.content.size > 0 + ) { + return; + } + + const from = doc.content.size - 1 - lastBlockContainer.nodeSize; + + return DecorationSet.create(doc, [ + Decoration.node(from, from + lastBlockContainer.nodeSize, { + class: "bn-trailing-block", + }), + ]); + }, + }, appendTransaction: (_, __, state) => { const { doc, tr, schema } = state; const shouldInsertNodeAtEnd = plugin.getState(state);