Caret API: move, focus, and set cursor position
Control cursor position and selection within the editor.
Reaching the editor instance
The methods below run on the editor you created with new Blok(). They are available once editor.isReady resolves.
// You already hold the instance returned by the constructor.
const editor = new Blok({ holder: 'editor' });
await editor.isReady;
// Call any API method on it.
editor.caret.setToLastBlock('end');Methods
caret.setToFirstBlock(position?, offset?)
booleanSet caret to the first block with optional position and offset.
When to use
position accepts 'start'/'end'/'default'; returns false if there's no block to land on.
// Set to start of first block
editor.caret.setToFirstBlock('start');
// Set to end of first block
editor.caret.setToFirstBlock('end');
// Offset applies only to the 'default' position —
// 'start' and 'end' place the caret at the boundary and ignore it
editor.caret.setToFirstBlock('default', 5);caret.setToLastBlock(position?, offset?)
booleanSet caret to the last block with optional position and offset.
When to use
Common after appending content — drop the caret at the end of the new last block with 'end'.
// Focus last block at end
editor.caret.setToLastBlock('end');
// Focus last block at start
editor.caret.setToLastBlock('start');caret.setToPreviousBlock(position?, offset?)
booleanMove caret to the previous block.
When to use
Moves relative to the focused block; returns false at the top edge, so use the return value to detect boundaries.
editor.caret.setToPreviousBlock('end');
// Caret now at end of previous blockcaret.setToNextBlock(position?, offset?)
booleanMove caret to the next block.
When to use
Mirror of setToPreviousBlock(); returns false at the bottom edge.
editor.caret.setToNextBlock('start');
// Caret now at start of next blockcaret.setToBlock(blockOrIdOrIndex, position?, offset?)
booleanSet caret to a specific block by BlockAPI, ID, or index.
When to use
The most flexible setter — target by BlockAPI, id, or index. Prefer id/BlockAPI over index, which shifts as blocks move.
Parameters
| Parameter | Type | Required | Default | Description |
|---|---|---|---|---|
blockOrIdOrIndex | BlockAPI | string | number | Required | — | Target block, given as a BlockAPI instance, block id, or numeric index. |
position | 'start' | 'end' | 'default' | — | 'default' | Where within the block to place the caret. |
offset | number | — | 0 | Absolute character offset from the start of the block's current input. Applied only when position is 'default' — 'start' and 'end' place the caret at the boundary and ignore it. |
Errors
blockOrIdOrIndex is a valid id or index that does not resolve to an existing block (unknown id or out-of-range index).
For id/index inputs, check the boolean return value — a falsy result is the only signal the target wasn't found. Passing a null BlockAPI (e.g. an unchecked getById() result) is invalid input and throws, so null-check before calling.
// By index
editor.caret.setToBlock(0, 'end');
// → true if the caret moved, false if the target block doesn't exist
// By ID
editor.caret.setToBlock('block-123', 'start');
// By BlockAPI (getById can return null, so guard it)
const block = editor.blocks.getById('block-123');
if (block) {
editor.caret.setToBlock(block);
}caret.focus(atEnd?)
booleanSet focus to the editor, optionally at the end of content.
When to use
Lightweight way to focus the editor without choosing a block; pass true for the end. Same as the top-level focus().
// Focus at start
editor.caret.focus();
// Focus at end
editor.caret.focus(true);caret.updateLastCaretAfterPosition()
voidUpdate the "after" position of the most recent caret undo entry. Use after async caret movements.
When to use
Call after an async caret move so undo lands the caret where the user ended up, not where the op started.
// After moving caret asynchronously
requestAnimationFrame(() => {
editor.caret.setToBlock(0);
editor.caret.updateLastCaretAfterPosition();
});