Repository navigation
Shift+click doesn't extend the selection into another paragraph #20
Description
Summary
Drag selection already works across paragraphs, but Shift+click doesn't. With the caret in paragraph A, Shift+clicking in paragraph B never selects from A to B, so toolbar commands such as Bold apply only to part of the intended range. Word and Google Docs extend the selection to the clicked point.
Reproduction (playground at v0.10.0, Chromium with no extensions)
Document: a heading, a long paragraph, a one-line paragraph, another long paragraph. In 0.10.0 the heading and the one-line paragraph render through the wrapped-paragraph textarea. Put the caret in one paragraph, Shift+click in another, then click Bold:
| Caret in → Shift+click in | Result |
|---|---|
| ¶1 → ¶3 (both contenteditable) | selects only to the end of ¶1; only ¶1 is bolded |
| ¶1 → ¶2 (wrapped) | selection collapses at the click in ¶2; nothing is bolded |
| ¶2 (wrapped) → ¶3 | selection collapses at the click in ¶3; nothing is bolded |
Cause
onViewerPointerDown (registered as onPointerDownCapture on the viewer) returns early when event.shiftKey is set, so it never reaches the boundary-based selection that drag uses (resolveBoundaryFromPoint + setSelectionFromDocxBoundaries). Each paragraph is its own editing host, so native Shift+click stays inside the origin paragraph.
Suggested patch (packages/react-viewer/src/editor.tsx)
- if (event.ctrlKey || event.metaKey || event.shiftKey || event.altKey) {
+ // Shift+click extends the current selection to the clicked point, even
+ // when it lands in another paragraph. Reuses the boundary resolution and
+ // range application that drag selection uses.
+ if (event.shiftKey && !event.ctrlKey && !event.metaKey && !event.altKey) {
+ const anchor = editor.activeTextRange?.start;
+ const clicked = resolveBoundaryFromPoint({ x: event.clientX, y: event.clientY });
+ if (
+ anchor &&
+ clicked &&
+ paragraphLocationKey(anchor.location) !== paragraphLocationKey(clicked.location)
+ ) {
+ event.preventDefault();
+ event.stopPropagation();
+ setSelectionFromDocxBoundaries(anchor, clicked);
+ }
+ return;
+ }
+
+ if (event.ctrlKey || event.metaKey || event.altKey) {
return;
}It also adds editor.activeTextRange and setSelectionFromDocxBoundaries to the useCallback dependencies.
With the patch, using the same harness, ¶1→¶3, ¶1→¶2, ¶2→¶3 and ¶3→¶1 all select the full range, and Bold applies to every paragraph in it. Shift+click inside a single paragraph is unchanged. vitest run gives the same result with and without the patch (554 passed, 15 skipped). I did not run the visual Playwright suites.
Known limitations:
- The anchor is
editor.activeTextRange.start. That is right for a caret; when extending an existing selection, the anchor should be the selection's anchor end. You may already track that somewhere. - Shift+ArrowUp/Down across a paragraph boundary has the same problem and isn't covered.
Context: we currently ship a workaround that synthesizes a drag from the anchor to the click point; built-in support would let us remove it.
Activity
andrewlu0 commentedon Oct 15, 2026
hi could u try this on the latest version 0.11? i think it should be fixed
rogegoncalves commentedon Oct 18, 2026
Thanks, confirmed: 0.11.0 fixes it. I tested in our app with
@extend-ai/react-docx@0.11.0from npm (Chromium, no extensions), with our Shift+click workaround removed: Shift+click between regular paragraphs, from a wrapped heading to a paragraph, and from a paragraph to a wrapped heading. Bold and Backspace act on the whole range, the same as a mouse drag. We'll remove our workaround when we upgrade.The keyboard part from my original report (Shift+ArrowUp/Down across paragraphs) is still there in 0.11. I opened #21 with the root cause, a fix and a browser test. Feel free to close this one.