Skip to content

Caret Navigation

The CaretNavigationPlugin provides platform-aware keyboard navigation for all caret movement — character, word, line boundary, and document boundary. It maps visual arrow-key intent to logical forward/backward direction, handles RTL text correctly, and announces block-type changes to screen readers on cross-block navigation.

import { createEditor, CaretNavigationPlugin } from '@notectl/core';
const editor = await createEditor({
plugins: [new CaretNavigationPlugin()],
});

No configuration is needed. The plugin auto-detects macOS vs Windows/Linux and registers the appropriate keymaps.

All shortcuts below work in both LTR and RTL text. The plugin maps visual direction (left/right) to logical direction (forward/backward) based on the text direction of the focused block.

ActionMacWindows / Linux
Extend selection rightShift+ArrowRightShift+ArrowRight
Extend selection leftShift+ArrowLeftShift+ArrowLeft

Basic character movement (ArrowLeft/ArrowRight without Shift) is handled natively by the browser.

ActionMacWindows / Linux
Move one word rightAlt+ArrowRightCtrl+ArrowRight
Move one word leftAlt+ArrowLeftCtrl+ArrowLeft
Extend selection one word rightShift+Alt+ArrowRightCtrl+Shift+ArrowRight
Extend selection one word leftShift+Alt+ArrowLeftCtrl+Shift+ArrowLeft
ActionMacWindows / Linux
Move to line startCmd+ArrowLeftHome
Move to line endCmd+ArrowRightEnd
Extend to line startCmd+Shift+ArrowLeftShift+Home
Extend to line endCmd+Shift+ArrowRightShift+End
ActionMacWindows / Linux
Extend selection one line upShift+ArrowUpShift+ArrowUp
Extend selection one line downShift+ArrowDownShift+ArrowDown
ActionMacWindows / Linux
Move to document startCmd+ArrowUpCtrl+Home
Move to document endCmd+ArrowDownCtrl+End
Extend to document startCmd+Shift+ArrowUpCtrl+Shift+Home
Extend to document endCmd+Shift+ArrowDownCtrl+Shift+End

When the cursor moves into a different block, the plugin announces the block type to screen readers (e.g. “Heading level 2”, “Bullet list item”, “Paragraph”). Announcements are debounced by 150 ms to avoid noise during rapid navigation. If another plugin has already announced something (e.g. CodeBlockPlugin’s “Left code block”), the caret navigation announcement is suppressed.

The plugin registers keymaps at navigation priority and splits movement into two categories:

  • Model-based commands — Character movement and document-boundary movement operate on the immutable document model directly. They count grapheme clusters and InlineNode boundaries without touching the DOM.
  • View-based commands — Word, line-boundary, and line-up/down movement delegate to the browser’s Selection.modify() API, then read the resulting DOM position back into the model. This ensures correct behavior with complex text shaping, ligatures, and soft-wrapped lines.

For RTL text, visual left/right arrow keys are flipped to the correct logical forward/backward direction by inspecting the computed text direction of the focused block element.