From zbeyens. The source code is available on GitHub.

Plate
PlatePliteEditorsTemplates
GitHub16kGitHub
DiscordDiscord
UNPUBLISHED
  • Overview
  • Why This Fork
  • Examples
Walkthroughs
  • Installing Plite
  • Adding Event Handlers
  • Defining Custom Elements
  • Applying Custom Formatting
  • Executing Commands
  • Saving to a Database
  • Canonical Change Substrate
  • Improving Performance
Concepts
  • Interfaces
  • Nodes
  • Locations
  • Transforms
  • Document Changes
  • Commands
  • Editor
  • Extensions
  • Rendering
  • Serializing
  • Normalizing
  • Using TypeScript
  • Roots
  • Document State
  • Editing Behavior
  • Selection And DOM
  • Clipboard And Paste
  • Projection And Overlays
  • Schema
API
  • Anchor API
  • Location API
  • Path API
  • PointEntry API
  • Point API
  • Range API
  • Selection API
  • Location Types APIs
  • Span API
  • Editor
  • Element API
  • NodeEntry API
  • Node API
  • Node Types APIs
  • Text API
  • Debug Value Scrubbing
  • Transforms API
Libraries
  • Plite DOM
  • History Editor API
  • History Extension Setup
  • History
  • Plite History
  • Plite Hyperscript
  • Plite Layout
  • Annotations
  • DOM Coverage Boundaries
  • Editable Component
  • Plite React Event Handling
  • Virtualized Rendering
  • Plite React Hooks
  • React Editor Setup
  • React Editor
  • Plite React
  • Plite Component
  • Plite Yjs
  • Plite
General
  • Migration
  • Contributing
  • Docs Proof Map
  • FAQ
  • Resources

Selection API

PreviousNext

Active ranges, exact node membership, and semantic selection writes.

editor.read.selection() returns the active Slate-shaped range. Plite owns the complete serializable selection state: text selection or one directional exact node selection. Extensions cannot add selection kinds.

type EditorSelection = TextSelection | NodeSelection;
type Selection<TSelection extends SelectionValue = SelectionValue> =
  | TSelection
  | null;
type EditorSelection = TextSelection | NodeSelection;
type Selection<TSelection extends SelectionValue

Range APILocation Types APIs

On This Page

Editor Readseditor.read.selection() => Range | nulleditor.read.selection.ranges() => readonly Range[]Editor Updateseditor.update.selection.setNodes(targets, options?)Static MethodsSelectionApi.equals(left: Selection, right: Selection) => booleanSelectionApi.isSelection(value: unknown) => value is SelectionValueSelectionApi.isText(value: unknown) => value is TextSelectionSelectionApi.isNode(value: unknown) => value is NodeSelectionSelectionApi.root(selection) => NamedRootKey | undefinedSelectionApi.text(range: Range, options?) => TextSelectionSelectionApi.nodes(paths: readonly [Path, ...Path[]], options?) => NodeSelectionEditor Validationstate.selection.isValid(value: unknown) => value is Selection
Build your editor
Production-ready AI template and reusable components.
Get all-access
=
SelectionValue
>
=
| TSelection
| null;

SelectionApi is frozen. Compose a custom helper around it instead of mutating the namespace.

Editor Reads

editor.read.selection() => Range | null

Read the active range or null. The same callable is available as state.selection() and tx.selection() inside read and update callbacks. The returned object contains only anchor and focus; it has no selection-kind tag or extension payload.

Use it directly wherever a Slate Range is expected.

import { RangeApi } from "@platejs/plite";
 
const selection = editor.read.selection();
 
if (selection) {
  const { anchor, focus } = selection;
  const expanded = RangeApi.isExpanded(selection);
}
import { RangeApi } from "@platejs/plite";
 
const selection = editor.read.selection();
 
if (selection) {
  const { anchor, focus } = selection;
  const expanded = RangeApi.isExpanded(selection);
}

For a node selection, selection() returns the directed representative range between its anchor and focus nodes. Read exact disjoint membership with selection.nodes() and one exact range per node with selection.ranges(). Range predicates such as selection.isExpanded(), isWithinBlock(), and isAcrossBlocks() inspect that same representative range. Use nodes() for exact node-selection membership instead of treating those predicates as a selection-kind test.

editor.read.selection.ranges() => readonly Range[]

Read every exact range in the current selection. Text selections return one range and node selections return one range per selected path. Each result is a plain Range. A missing selection returns an empty array.

Use state.selection.ranges() or tx.selection.ranges() inside a read or update callback.

Editor Updates

editor.update.selection.setNodes(targets, options?)

Select live nodes by Path, NodeKey, or live descendant. The editor resolves every target in one root, sorts and deduplicates the paths, and drops descendants of selected ancestors. An empty collection clears the selection. A missing or foreign target rejects the whole update.

Pass { anchor, focus } when gesture direction matters. Both endpoints must be members of the exact selected targets. Omit the options for deterministic document-order endpoints.

Use tx.selection.setNodes(targets) when earlier writes in the same transaction create or move the targets.

Static Methods

SelectionApi.equals(left: Selection, right: Selection) => boolean

Compare complete text or node selection values.

SelectionApi.isSelection(value: unknown) => value is SelectionValue

Strictly check either built-in serializable selection shape. This predicate does not verify whether its points or paths exist in a document.

SelectionApi.isText(value: unknown) => value is TextSelection

Strictly check the built-in text-selection shape. Insertion marks are valid only on a collapsed text selection.

SelectionApi.isNode(value: unknown) => value is NodeSelection

Strictly check the built-in node-selection shape and canonical path membership.

SelectionApi.root(selection) => NamedRootKey | undefined

Read the named root declared by a text or node selection. A primary-root selection returns undefined.

SelectionApi.text(range: Range, options?) => TextSelection

Create a text selection from a range and optional affinity or insertion marks.

SelectionApi.nodes(paths: readonly [Path, ...Path[]], options?) => NodeSelection

Create a detached multi-node selection. Paths are non-empty, deduplicated, and sorted in document order. Descendants of selected ancestors are removed. anchorPath and focusPath preserve direction and must both be exact members. Live editor code uses selection.setNodes(targets, { anchor, focus }) instead.

Read exact selected entries with editor.read.selection.nodes() or tx.selection.nodes(). Use editor.read.nodes.blocks() to project the active selection to schema blocks. ranges() projects one range per selected node, while contains and intersects evaluate those exact projections.

Editor Validation

state.selection.isValid(value: unknown) => value is Selection

Validate a complete built-in selection against the current document. The direct read form is editor.read.selection.isValid(value).

if (editor.read.selection.isValid(input)) {
  editor.update.selection.set(input);
}
if (editor.read.selection.isValid(input)) {
  editor.update.selection.set(input);
}

This check accepts null, rejects unknown kinds, and verifies every text point or exact node path against its document root.

In Plite React, node selection is model-only: selection() still exposes its active model range while the editor remains focused and the native browser selection has no range. See Keyboard-Selectable Content for asset focus, child-content navigation, and deletion.

Plate React apps can render selected-block highlights and blank-space drag selection with the Node Selection components.