Skip to content

Preview rich-text editor: open with drag-selection preserved (bd-abo9m23f)#383

Merged
cscheid merged 3 commits into
mainfrom
feature/bd-abo9m23f-drag-selection-richtext
Jul 7, 2026
Merged

Preview rich-text editor: open with drag-selection preserved (bd-abo9m23f)#383
cscheid merged 3 commits into
mainfrom
feature/bd-abo9m23f-drag-selection-richtext

Conversation

@cscheid

@cscheid cscheid commented Jul 7, 2026

Copy link
Copy Markdown
Member

Summary

In q2 preview --allow-edit (and hub-client's format: q2-preview), a mouse drag inside a single block now opens the rich-text editor with the dragged selection recreated — direction-aware, so a right-to-left drag keeps its focus at the release end — instead of a bare caret at the mouse-release point. This makes the selection-driven toolbar (bold, italic, link, …) immediately usable after a drag: drag, click B, done.

A drag whose selection spans multiple blocks no longer activates an editor at all. Previously the release block opened with a caret and the DOM swap destroyed the user's selection — breaking plain copy gestures.

Mechanism

Extends the bd-q9lyghv2 caret-at-click coordinate bridge from a single point to an anchor/head pair (same geometric premise: the editor renders the same visual text in the same measured box, so viewport coords captured before the DOM swap land on the same glyphs after it):

  • dragSelectionCapture.ts (new): classifyOpenSelection classifies the DOM selection at the activate() chokepoint into caret / range / suppress, using direction-aware selection endpoints (anchor/focus, not the normalized range) and ownerDocument-relative lookups (iframe-safe).
  • pendingClickCoordsRefpendingOpenSelectionRef with a union payload; read-once-and-clear semantics at editor mount unchanged (self-heal remounts still fall back to end-of-block).
  • placeSelectionFromDrag: replays both endpoints through posAtCoords and applies TextSelection.between(resolve(anchor), resolve(head)) — direction preserved, endpoints nudged to valid text positions.
  • Mount fallback chain: range → caret at head (release point) → focus('end').

Keyboard and touch activation are untouched (no click coords → no classification).

Tests

  • 9 unit tests for the capture classification (contained/backward/cross-block/collapsed/no-rects/invalid-offset).
  • 5 unit tests for the replay against a real EditorState (direction preserved; misses and degenerate same-pos return false).
  • Hover + editor integration tests extended: range payload stash, suppression (mouse-only — keyboard with a live selection still opens), read-once consume, fallback chain.
  • New Playwright e2e (q2-preview-spa/e2e/drag-selection-open.spec.ts) driving real trusted mouse drags against the real q2 binary: forward drag (editor selection equals the selection recorded at pointerup), backward drag stays backward, cross-block drag opens nothing and preserves the selection. 3/3 passed.
  • Manually verified end-to-end with q2 preview --allow-edit: drag-selecting "quick brown fox jumps over the lazy" opens the editor with that exact selection highlighted; toolbar Bold produces <strong> around exactly that range.
  • cargo xtask verify green (the previously-failing changelog Q-2-17 WASM test passes after rebasing onto fix(hub-client): unbreak main — escape lone tilde in changelog (bd-q5o7ekzn) #381's fix).

Plan/design record: claude-notes/plans/2026-07-07-preview-drag-selection-into-richtext.md (strand bd-abo9m23f).

🤖 Generated with Claude Code

cscheid and others added 3 commits July 7, 2026 14:45
…m23f)

A mouse drag inside a single block now opens the rich-text editor with
the dragged selection recreated (direction-aware, so a right-to-left
drag keeps its focus at the release end), instead of a bare caret at
the release point. This makes the selection-driven toolbar (bold,
italic, link, ...) immediately usable after a drag.

A drag whose selection spans multiple blocks no longer activates an
editor at all: the previous behavior swapped the DOM under the release
block and destroyed a selection the user may have made just to copy
text.

Mechanism: extends the bd-q9lyghv2 caret-at-click coordinate bridge
from a single point to an anchor/head pair. `classifyOpenSelection`
(new dragSelectionCapture.ts) classifies the DOM selection at the
activate() chokepoint into caret / range / suppress; the payload rides
the renamed `pendingOpenSelectionRef` (read-once at editor mount) and
is replayed through `posAtCoords` x2 + `TextSelection.between`
(`placeSelectionFromDrag`), falling back range -> caret -> end-of-block.

Tests: 9 new capture unit tests, 5 new replay unit tests against a real
EditorState, hover/editor integration tests extended (suppression,
fallback chain, read-once), and a new Playwright e2e
(q2-preview-spa/e2e/drag-selection-open.spec.ts) driving real trusted
mouse drags against the real q2 binary: forward drag, backward drag
direction, cross-block suppression.

Verified end-to-end with `q2 preview --allow-edit`: drag-selecting text
opens the editor with the selection highlighted; toolbar Bold applies
to exactly the dragged range. `cargo xtask verify` green except the
pre-existing changelog.md ~37MB / Q-2-17 WASM-render failure on main
(fix already in flight in an open PR).

Plan: claude-notes/plans/2026-07-07-preview-drag-selection-into-richtext.md

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
…af08ef)

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
@posit-snyk-bot

posit-snyk-bot commented Jul 7, 2026

Copy link
Copy Markdown

Snyk checks have passed. No issues have been found so far.

Status Scan Engine Critical High Medium Low Total (0)
Open Source Security 0 0 0 0 0 issues
Licenses 0 0 0 0 0 issues

💻 Catch issues earlier using the plugins for VS Code, JetBrains IDEs, Visual Studio, and Eclipse.

@cscheid cscheid merged commit 30fbc5b into main Jul 7, 2026
8 checks passed
@cscheid cscheid deleted the feature/bd-abo9m23f-drag-selection-richtext branch July 7, 2026 20:02
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants