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 with offset
editor.caret.setToFirstBlock('end', 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 | Character offset from position within the target input. |
Errors
blockOrIdOrIndexdoes not resolve to an existing block (unknown id or out-of-range index).(no error thrown — the call returns false)
Check the boolean return value;
setToBlock()never throws, so a falsy result is the only signal the target wasn't found.
// 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();
});