or run

npx @tessl/cli init
Log in

Version

Tile

Overview

Evals

Files

docs

block-management.mdcaret-navigation.mdconfiguration.mdeditor-core.mdevent-system.mdindex.mdtool-development.md
tile.json

caret-navigation.mddocs/

Caret Navigation

The Caret API provides precise control over cursor positioning and navigation throughout editor blocks. This enables programmatic focus management and cursor movement, essential for keyboard shortcuts and custom navigation behaviors.

Capabilities

Block Position Navigation

Methods for moving the caret to specific block positions.

/**
 * Set caret to the first block in the editor
 * @param position - Where to place caret within the block
 * @param offset - Character offset from position
 * @returns true if caret was successfully positioned
 */
setToFirstBlock(position?: 'end' | 'start' | 'default', offset?: number): boolean;

/**
 * Set caret to the last block in the editor
 * @param position - Where to place caret within the block
 * @param offset - Character offset from position
 * @returns true if caret was successfully positioned
 */
setToLastBlock(position?: 'end' | 'start' | 'default', offset?: number): boolean;

/**
 * Set caret to the previous block relative to current position
 * @param position - Where to place caret within the block
 * @param offset - Character offset from position
 * @returns true if caret was successfully positioned
 */
setToPreviousBlock(position?: 'end' | 'start' | 'default', offset?: number): boolean;

/**
 * Set caret to the next block relative to current position
 * @param position - Where to place caret within the block
 * @param offset - Character offset from position
 * @returns true if caret was successfully positioned
 */
setToNextBlock(position?: 'end' | 'start' | 'default', offset?: number): boolean;

Usage Examples:

// Move to first block at start
editor.caret.setToFirstBlock('start');

// Move to last block at end
editor.caret.setToLastBlock('end');

// Move to previous block with 5 character offset from start
editor.caret.setToPreviousBlock('start', 5);

// Move to next block with default positioning
editor.caret.setToNextBlock('default');

// Check if navigation was successful
const moved = editor.caret.setToNextBlock();
if (!moved) {
  console.log('Could not move to next block (might be at end)');
}

Specific Block Targeting

Method for setting caret to a specific block by various identifiers.

/**
 * Set caret to specific block
 * @param blockOrIdOrIndex - Block API instance, block ID string, or block index number
 * @param position - Where to place caret within the block
 * @param offset - Character offset from position
 * @returns true if caret was successfully positioned
 */
setToBlock(
  blockOrIdOrIndex: BlockAPI | string | number,
  position?: 'end' | 'start' | 'default',
  offset?: number
): boolean;

Usage Examples:

// Set caret by block index
editor.caret.setToBlock(2, 'start');

// Set caret by block ID
editor.caret.setToBlock('block-id-123', 'end');

// Set caret by BlockAPI instance
const block = editor.blocks.getBlockByIndex(1);
if (block) {
  editor.caret.setToBlock(block, 'start', 10);
}

// Different positioning options
editor.caret.setToBlock(0, 'start');    // Beginning of block
editor.caret.setToBlock(0, 'end');      // End of block
editor.caret.setToBlock(0, 'default');  // Default position (usually start)

// With character offset
editor.caret.setToBlock(1, 'start', 5);  // 5 characters from start
editor.caret.setToBlock(1, 'end', -3);   // 3 characters before end

Focus Management

Method for focusing the editor with caret positioning.

/**
 * Focus the editor and optionally position caret
 * @param atEnd - If true, place caret at end of editor content
 * @returns true if editor was successfully focused
 */
focus(atEnd?: boolean): boolean;

Usage Examples:

// Focus editor at current/default position
editor.caret.focus();

// Focus editor at the very end of content
editor.caret.focus(true);

// Check if focus was successful
const focused = editor.caret.focus();
if (!focused) {
  console.log('Could not focus editor');
}

// Typical usage in event handlers
document.addEventListener('keydown', (e) => {
  if (e.ctrlKey && e.key === 'e') {
    e.preventDefault();
    editor.caret.focus(); // Focus editor on Ctrl+E
  }
});

Position Options

The caret positioning system uses specific position values:

  • 'start': Place caret at the beginning of the block content
  • 'end': Place caret at the end of the block content
  • 'default': Use block's default caret position (typically start)

Offset Behavior

The offset parameter provides fine-grained control:

  • Positive numbers: Move caret forward from the position
  • Negative numbers: Move caret backward from the position
  • Zero or undefined: No offset applied

Navigation Patterns

Usage Examples:

// Keyboard navigation simulation
function simulateArrowKeys() {
  // Up arrow - previous block at end
  editor.caret.setToPreviousBlock('end');
  
  // Down arrow - next block at start
  editor.caret.setToNextBlock('start');
  
  // Home key - current block start
  const currentIndex = editor.blocks.getCurrentBlockIndex();
  editor.caret.setToBlock(currentIndex, 'start');
  
  // End key - current block end
  editor.caret.setToBlock(currentIndex, 'end');
}

// Focus management for modal dialogs
function handleModalClose() {
  // Return focus to editor when modal closes
  setTimeout(() => {
    editor.caret.focus();
  }, 100);
}

// Programmatic content insertion with caret positioning
async function insertQuoteAtPosition() {
  const currentIndex = editor.blocks.getCurrentBlockIndex();
  
  // Insert quote block after current position
  const quoteBlock = editor.blocks.insert(
    'quote',
    { text: 'Inspirational quote here' },
    {},
    currentIndex + 1,
    false // Don't auto-focus
  );
  
  // Manually position caret at end of quote
  editor.caret.setToBlock(quoteBlock.id, 'end');
}

// Multi-block selection and navigation
function selectAndNavigateBlocks() {
  // Move through blocks programmatically
  for (let i = 0; i < editor.blocks.getBlocksCount(); i++) {
    setTimeout(() => {
      editor.caret.setToBlock(i, 'start');
    }, i * 500); // 500ms delay between moves
  }
}

Integration with Block API

Caret navigation works seamlessly with block operations:

Usage Examples:

// Insert and immediately position caret
const newBlock = editor.blocks.insert('paragraph');
editor.caret.setToBlock(newBlock.id, 'start');

// Navigate after block operations
editor.blocks.delete(2); // Delete block at index 2
editor.caret.setToBlock(1, 'end'); // Move to previous block end

// Move blocks and update caret
editor.blocks.move(3, 0); // Move first block to position 3
editor.caret.setToBlock(3, 'start'); // Follow the moved block

Error Handling

Caret methods return boolean values indicating success:

Usage Examples:

// Robust navigation with error handling
function safeNavigateToBlock(index: number) {
  const success = editor.caret.setToBlock(index, 'start');
  
  if (!success) {
    console.warn(`Could not navigate to block ${index}`);
    
    // Fallback: try to focus editor generally
    const focused = editor.caret.focus();
    if (!focused) {
      console.error('Could not focus editor at all');
    }
  }
  
  return success;
}

// Validate navigation in sequences
async function navigateSequence(indices: number[]) {
  for (const index of indices) {
    const success = editor.caret.setToBlock(index);
    if (!success) {
      console.error(`Navigation failed at block ${index}`);
      break;
    }
    // Small delay for visual feedback
    await new Promise(resolve => setTimeout(resolve, 200));
  }
}