From 551b3bd9215aff882b3f67ec776896a99698d4ec Mon Sep 17 00:00:00 2001 From: robonen Date: Tue, 11 Aug 2026 05:52:54 +0700 Subject: [PATCH] fix(writekit): a node selection is a real DOM range, not an absence of one MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Selecting an atom used to clear every native range and leave the editable root focused with NO selection. The browser then invents a caret at the START of the content, `selectionchange` reads it, and the model's node selection is overwritten by a text caret in the first block — so the Enter meant to exit the freshly inserted atom split the opening paragraph, and typing replaced its text. Reproduced live within a minute of using the slash menu. - the bridge now writes a node selection as `range.selectNode(blockEl)`; the read path maps that range to null, so selectionchange keeps its hands off the model - beforeinput guards the node-selection state: browser edits through the element-wrapping range are prevented; delete falls through to deleteSelection, insertParagraph to exitAtom - browser regression test walks the exact race: select atom → DOM range exists → selectionchange rewrites nothing → Enter lands a paragraph below the atom writekit 0.0.4. Co-Authored-By: Claude Opus 5 (1M context) --- vue/writekit/package.json | 2 +- vue/writekit/src/view/WritekitContent.vue | 16 +++++++- .../view/__test__/writekit.browser.test.ts | 40 +++++++++++++++++++ .../src/view/selection/selection-bridge.ts | 21 ++++++++-- 4 files changed, 74 insertions(+), 5 deletions(-) diff --git a/vue/writekit/package.json b/vue/writekit/package.json index c677059..624c9fd 100644 --- a/vue/writekit/package.json +++ b/vue/writekit/package.json @@ -1,6 +1,6 @@ { "name": "@robonen/writekit", - "version": "0.0.3", + "version": "0.0.4", "license": "Apache-2.0", "description": "Headless block-based rich-text writekit for Vue with a registry-driven schema and pluggable CRDT", "keywords": [ diff --git a/vue/writekit/src/view/WritekitContent.vue b/vue/writekit/src/view/WritekitContent.vue index 8fef550..6b5077a 100644 --- a/vue/writekit/src/view/WritekitContent.vue +++ b/vue/writekit/src/view/WritekitContent.vue @@ -4,7 +4,7 @@ import type { PrimitiveProps } from './primitive';