diff --git a/frontend/src/block.ts b/frontend/src/block.ts index 06d0e1643..19aae7bfa 100644 --- a/frontend/src/block.ts +++ b/frontend/src/block.ts @@ -584,10 +584,12 @@ class Block implements BlockOptions { childBlock.parentBlock = this; this.children.splice(index, 0, childBlock); if (select) { - childBlock.selectBlock(); - } - if (childBlock.isText()) { - childBlock.makeBlockEditable(); + if (childBlock.isText()) { + // makeBlockEditable() selects the block and enters edit mode synchronously. + childBlock.makeBlockEditable(); + } else { + childBlock.selectBlock(); + } } if (childBlock.getStyle("position")) { @@ -757,7 +759,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; }