Gap Cursor
The GapCursorPlugin provides a virtual cursor that appears at the boundary of void blocks (images, horizontal rules, code blocks in some configurations) where no native browser caret can exist. This lets users navigate to positions before or after void blocks and type to insert new content.
import { createEditor } from '@notectl/core';import { GapCursorPlugin } from '@notectl/core/plugins/gap-cursor';
const editor = await createEditor({ plugins: [new GapCursorPlugin()],});Configuration
Section titled “Configuration”The plugin requires no configuration. It activates automatically when the selection lands on a gap position adjacent to a void block.
Keyboard Shortcuts
Section titled “Keyboard Shortcuts”The plugin registers arrow key keymaps that activate only when a gap cursor is present:
| Key | Action |
|---|---|
ArrowLeft | Move to previous position (end of previous block, or NodeSelection) |
ArrowRight | Move to next position (start of next block, or NodeSelection) |
ArrowUp | Move up (equivalent to ArrowLeft) |
ArrowDown | Move down (equivalent to ArrowRight) |
Other keys such as Enter, Backspace, Delete, and character input are handled by the core InputHandler, not by this plugin. In all other selection states, the arrow key keymaps pass through to other handlers.
Accessibility
Section titled “Accessibility”- When the gap cursor activates, the plugin announces “Gap cursor active. Type to insert new paragraph.” to screen readers via a live region.
- The gap cursor is rendered as a CSS pseudo-element (
::beforeor::after) on the void block — no separate DOM element is created, so it is purely visual and not exposed to the accessibility tree.
How It Works
Section titled “How It Works”DOM Rendering
Section titled “DOM Rendering”The gap cursor does not create a separate DOM element. Instead, it adds a CSS class to the void block element itself, depending on side:
before— addsnotectl-gap-cursor--beforeto the void block (renders a::beforepseudo-element visually above it)after— addsnotectl-gap-cursor--afterto the void block (renders an::afterpseudo-element visually below it)
The pseudo-element renders a full-width, 1px-tall blinking line.
CSS Animation
Section titled “CSS Animation”The blinking animation uses a step function for a sharp on/off effect:
@keyframes notectl-gap-blink { 50% { opacity: 0; }}
.notectl-gap-cursor--before::before,.notectl-gap-cursor--after::after { animation: notectl-gap-blink 1.1s step-end infinite; background: currentColor;}- Animation:
notectl-gap-blink, 1.1s cycle,step-endtiming - Color:
currentColor— automatically matches your editor’s text color and works with any theme - Reduced motion: The animation is disabled when
prefers-reduced-motion: reduceis active
Navigation Flow
Section titled “Navigation Flow”When arrow keys move the cursor past a void block, the selection progresses through three states:
- Text cursor in an adjacent text block
- NodeSelection on the void block itself
- GapCursorSelection at the boundary where no text block exists
This gives users full keyboard access to every position in the document, even between consecutive void blocks.