From 486679bb7b99058fe7fa0d38899086b2a12cef04 Mon Sep 17 00:00:00 2001 From: stravo1 Date: Tue, 28 Jul 2026 12:32:50 +0530 Subject: [PATCH 1/2] fix: Keep newly created text block editable through the creating click Selecting synchronously in makeBlockEditable prevents the block's own deferred selectBlock call from clearing editableBlock right after it's set. TextBlock also swallows the one spurious click-outside event that the creating click's native "click" triggers before the block has rendered, and catches up the focus/edit-mode entry that the isEditable watch missed because the editor didn't exist yet at mount time. --- frontend/src/block.ts | 10 ++++++---- frontend/src/components/TextBlock.vue | 13 +++++++++++++ 2 files changed, 19 insertions(+), 4 deletions(-) diff --git a/frontend/src/block.ts b/frontend/src/block.ts index 06d0e1643..26e270077 100644 --- a/frontend/src/block.ts +++ b/frontend/src/block.ts @@ -583,11 +583,11 @@ class Block implements BlockOptions { const childBlock = getBlockInstance(child); childBlock.parentBlock = this; this.children.splice(index, 0, childBlock); - if (select) { - childBlock.selectBlock(); - } if (childBlock.isText()) { + // makeBlockEditable() selects the block and enters edit mode synchronously. childBlock.makeBlockEditable(); + } else if (select) { + childBlock.selectBlock(); } if (childBlock.getStyle("position")) { @@ -757,7 +757,9 @@ class Block implements BlockOptions { } makeBlockEditable() { const canvasStore = useCanvasStore(); - this.selectBlock(); + // canvasStore.selectBlock() runs synchronously here. A deferred call would clear + // editableBlock right after this line sets it. + canvasStore.selectBlock(this, null); canvasStore.editableBlock = this; nextTick(() => { this.getEditor()?.commands.focus("all"); diff --git a/frontend/src/components/TextBlock.vue b/frontend/src/components/TextBlock.vue index ba7d619d1..25b44ccf8 100644 --- a/frontend/src/components/TextBlock.vue +++ b/frontend/src/components/TextBlock.vue @@ -140,6 +140,9 @@ onBeforeMount(() => { }); let pauseId: PauseId | undefined = undefined; +// The creating click also fires a native click event before the block renders. +// vOnClickOutside reads that as an outside click and ends edit mode. This flag skips it once. +let skipNextClickOutside = false; watch( () => isEditable.value, @@ -292,6 +295,12 @@ if (!props.preview) { props.block.setEditor(editor.value); editor.value?.setEditable(isEditable.value); + // A block can already be editable at mount, before editor.value exists. + // The isEditable watch above then misses the focus call. This catches up now. + if (isEditable.value) { + editor.value?.commands.focus("all"); + skipNextClickOutside = true; + } } else { destroyEditor(); } @@ -319,6 +328,10 @@ const handleEscKey = () => { }; const handleClickOutside = (e: MouseEvent) => { + if (skipNextClickOutside) { + skipNextClickOutside = false; + return; + } if ((e.target as HTMLElement).closest(".canvas-container")) { canvasStore.editableBlock = null; } From 4e835d885f7d79758c2cd70bdb730246d6e5cf31 Mon Sep 17 00:00:00 2001 From: stravo1 Date: Tue, 28 Jul 2026 12:46:05 +0530 Subject: [PATCH 2/2] fix: Respect select=false for text children in addChild addChild called makeBlockEditable() for text children even when a caller passed select=false, so component-instance sync and drag-to-a-new-parent reordering could select and focus a text block with no user interaction. --- frontend/src/block.ts | 12 +++++++----- 1 file changed, 7 insertions(+), 5 deletions(-) diff --git a/frontend/src/block.ts b/frontend/src/block.ts index 26e270077..19aae7bfa 100644 --- a/frontend/src/block.ts +++ b/frontend/src/block.ts @@ -583,11 +583,13 @@ class Block implements BlockOptions { const childBlock = getBlockInstance(child); childBlock.parentBlock = this; this.children.splice(index, 0, childBlock); - if (childBlock.isText()) { - // makeBlockEditable() selects the block and enters edit mode synchronously. - childBlock.makeBlockEditable(); - } else if (select) { - childBlock.selectBlock(); + if (select) { + if (childBlock.isText()) { + // makeBlockEditable() selects the block and enters edit mode synchronously. + childBlock.makeBlockEditable(); + } else { + childBlock.selectBlock(); + } } if (childBlock.getStyle("position")) {