or run

npx @tessl/cli init
Log in

Version

Tile

Overview

Evals

Files

docs

changes.mdcharacter-utils.mdeditor-state.mdextensions.mdindex.mdrange-sets.mdselection.mdtext.mdtransactions.md
tile.json

selection.mddocs/

Selection Management

Selection system supporting single and multiple selection ranges with cursor positioning and range operations.

Capabilities

EditorSelection Class

The main selection class that can hold one or more selection ranges.

/**
 * An editor selection holds one or more selection ranges.
 */
class EditorSelection {
  /** Create a selection with a single cursor at the given position */
  static single(pos: number): EditorSelection;
  
  /** Create a selection with a single cursor */
  static cursor(pos: number, assoc?: number, bidiLevel?: number, goalColumn?: number): EditorSelection;
  
  /** Create a selection with a single range */
  static range(anchor: number, head?: number, goalColumn?: number, bidiLevel?: number): EditorSelection;
  
  /** Create a selection from an array of ranges */
  static create(ranges: readonly SelectionRange[], mainIndex?: number): EditorSelection;
  
  /** Deserialize a selection from JSON */
  static fromJSON(json: any): EditorSelection;
  
  /** The ranges in the selection, sorted by position */
  readonly ranges: readonly SelectionRange[];
  
  /** The index of the main range in the selection */
  readonly mainIndex: number;
  
  /** Get the primary selection range */
  get main(): SelectionRange;
  
  /** Map a selection through a change */
  map(change: ChangeDesc, assoc?: number): EditorSelection;
  
  /** Compare this selection to another selection */
  eq(other: EditorSelection, includeAssoc?: boolean): boolean;
  
  /** Make sure the selection only has one range */
  asSingle(): EditorSelection;
  
  /** Return a JSON-serializable representation */
  toJSON(): any;
}

Usage Examples:

import { EditorSelection } from "@codemirror/state";

// Create a cursor at position 5
const cursor = EditorSelection.cursor(5);
console.log(cursor.main.from); // 5
console.log(cursor.main.to);   // 5 (empty range)

// Create a range selection from position 2 to 8
const range = EditorSelection.range(2, 8);
console.log(range.main.from); // 2
console.log(range.main.to);   // 8

// Create multiple selections (requires allowMultipleSelections facet)
const multiSelect = EditorSelection.create([
  EditorSelection.range(2, 5).main,
  EditorSelection.range(10, 15).main
], 0); // Main selection is first range

// Convert to single selection
const single = multiSelect.asSingle();
console.log(single.ranges.length); // 1

SelectionRange Class

Individual selection range representing a single cursor or text selection.

/**
 * A single selection range. When allowMultipleSelections is enabled,
 * a selection may hold multiple ranges.
 */
class SelectionRange {
  /** The lower boundary of the range */
  readonly from: number;
  
  /** The upper boundary of the range */
  readonly to: number;
  
  /** The anchor of the range—the side that doesn't move when you extend it */
  get anchor(): number;
  
  /** The head of the range, which is moved when the range is extended */
  get head(): number;
  
  /** True when anchor and head are at the same position */
  get empty(): boolean;
  
  /** Character association direction (-1, 0, or 1) */
  get assoc(): -1 | 0 | 1;
  
  /** The bidirectional text level associated with this cursor */
  get bidiLevel(): number | null;
  
  /** The goal column associated with a cursor for vertical motion */
  get goalColumn(): number | undefined;
  
  /** Map this range through a change */
  map(change: ChangeDesc, assoc?: number): SelectionRange;
  
  /** Extend this range to cover at least from to to */
  extend(from: number, to?: number): SelectionRange;
  
  /** Compare this range to another range */
  eq(other: SelectionRange, includeAssoc?: boolean): boolean;
  
  /** Return a JSON-serializable object representing the range */
  toJSON(): any;
  
  /** Convert a JSON representation to a SelectionRange instance */
  static fromJSON(json: any): SelectionRange;
}

Usage Examples:

// Create a range from position 5 to 10
const range = EditorSelection.range(5, 10).main;

console.log(range.from);   // 5
console.log(range.to);     // 10
console.log(range.anchor); // 5 (where selection started)
console.log(range.head);   // 10 (where selection ends)
console.log(range.empty);  // false

// Create a cursor (empty range)
const cursor = EditorSelection.cursor(7).main;
console.log(cursor.empty); // true
console.log(cursor.from);  // 7
console.log(cursor.to);    // 7

// Extend a range
const extended = range.extend(3, 12);
console.log(extended.from); // 3
console.log(extended.to);   // 12

// Work with reversed selection (head before anchor)
const reversed = EditorSelection.range(10, 5).main;
console.log(reversed.from);   // 5 (still lower boundary)
console.log(reversed.to);     // 10 (still upper boundary)  
console.log(reversed.anchor); // 10 (where selection started)
console.log(reversed.head);   // 5 (where selection ends)

Selection Factory Methods

Static methods for creating common selection types.

/**
 * Create a selection with a single cursor at the given position
 * @param pos The cursor position
 */
static single(pos: number): EditorSelection;

/**
 * Create a selection with a single cursor
 * @param pos The cursor position
 * @param assoc Character association (-1, 0, 1)
 * @param bidiLevel Bidirectional text level
 * @param goalColumn Goal column for vertical motion
 */
static cursor(pos: number, assoc?: number, bidiLevel?: number, goalColumn?: number): EditorSelection;

/**
 * Create a selection with a single range
 * @param anchor The anchor position (where selection starts)  
 * @param head The head position (where selection ends, defaults to anchor)
 * @param goalColumn Goal column for vertical motion
 * @param bidiLevel Bidirectional text level
 */
static range(anchor: number, head?: number, goalColumn?: number, bidiLevel?: number): EditorSelection;

/**
 * Create a selection from an array of ranges
 * @param ranges Array of selection ranges
 * @param mainIndex Index of the main range (defaults to ranges.length - 1)
 */
static create(ranges: readonly SelectionRange[], mainIndex?: number): EditorSelection;

Usage Examples:

// Simple cursor
const cursor = EditorSelection.single(10);

// Cursor with association (prefers character before position)
const associatedCursor = EditorSelection.cursor(10, -1);

// Range selection  
const selection = EditorSelection.range(5, 15);

// Multiple ranges
const ranges = [
  EditorSelection.range(2, 5).main,
  EditorSelection.range(8, 12).main,
  EditorSelection.range(15, 20).main
];
const multiSelection = EditorSelection.create(ranges, 1); // Main is second range

Selection Mapping

Methods for updating selections when the document changes.

/**
 * Map a selection through a change. Used to adjust the selection position for changes.
 * @param change The change to map through
 * @param assoc Association direction for boundary positions
 */
map(change: ChangeDesc, assoc?: number): EditorSelection;

Usage Examples:

import { EditorSelection, ChangeSet } from "@codemirror/state";

// Original selection from 5 to 10
const selection = EditorSelection.range(5, 10);

// Create a change that inserts "Hello " at position 3
const change = ChangeSet.of([{from: 3, insert: "Hello "}], 20);

// Map the selection through the change
const mappedSelection = selection.map(change);
console.log(mappedSelection.main.from); // 11 (5 + 6 characters inserted before)
console.log(mappedSelection.main.to);   // 16 (10 + 6 characters inserted before)

// Selection that spans the change
const spanningSelection = EditorSelection.range(2, 8);
const mappedSpanning = spanningSelection.map(change);
console.log(mappedSpanning.main.from); // 2 (unchanged, before insertion)
console.log(mappedSpanning.main.to);   // 14 (8 + 6 characters inserted)

Selection Serialization

Methods for converting selections to and from JSON format.

/**
 * Return a JSON-serializable representation of the selection
 */
toJSON(): any;

/**
 * Deserialize a selection from its JSON representation
 */
static fromJSON(json: any): EditorSelection;

Usage Examples:

// Serialize selection
const selection = EditorSelection.range(5, 15);
const json = selection.toJSON();
console.log(json); // { ranges: [{anchor: 5, head: 15}], main: 0 }

// Deserialize selection
const restored = EditorSelection.fromJSON(json);
console.log(restored.main.from); // 5
console.log(restored.main.to);   // 15

// Multiple ranges serialization
const multiSelect = EditorSelection.create([
  EditorSelection.range(2, 5).main,
  EditorSelection.range(10, 15).main
]);
const multiJson = multiSelect.toJSON();
const restoredMulti = EditorSelection.fromJSON(multiJson);
console.log(restoredMulti.ranges.length); // 2

Types

/**
 * Validation function for checking selection validity
 */
type SelectionValidator = (selection: EditorSelection, docLength: number) => EditorSelection;