Overview of Slate React
mainSlate and Editable, as well as specialized hooks and editor extensions to manage the editor state and user interactions within a React application.repository·main·Indexed 12 days ago
https://github.com/ianstormtaylor/slateA highly customizable framework for building rich text editors with a modular architecture. It includes core logic for document manipulation, state management, and operation handling, along with specialized sub-libraries like slate-react for React integration, slate-history for undo/redo functionality, and slate-hyperscript for creating documents using JSX.
Slate and Editable, as well as specialized hooks and editor extensions to manage the editor state and user interactions within a React application.slate-history sub-library is responsible for tracking changes to the Slate value state over time. It provides the necessary logic to implement undo and redo functionality within a Slate editor.slate-hyperscript package provides a hyperscript helper that allows you to define and create Slate document structures using JSX syntax. This is a more declarative way to build document trees compared to manual object manipulation.slate package serves as the central engine for the Slate editor, containing the core logic required for document manipulation, state management, and operation handling. While it is the foundation for other packages like slate-react or slate-history, it is primarily focused on the underlying data model and transformation logic.Slate aims to support modern desktop and mobile browsers.
beforeInput event support, which may result in a different development lifecycle and more bugs compared to other platforms.Slate does not provide polyfills for missing native APIs (like el.closest). If you need to support older browsers, you are responsible for providing the necessary polyfills (e.g., via https://polyfill-fastly.io/). Even with polyfills, Slate makes no guarantees of functionality in IE11.
The slate-react package provides React-specific logic for Slate editors. It is organized into the following functional directories:
slate-hyperscript package provides a hyperscript helper that allows you to construct Slate document structures using JSX syntax. This is a more declarative way to build complex nested nodes and text elements compared to manual object construction.The Editor object is the central state container for a Slate editor. It stores the document structure (children), the current user selection (selection), the history of changes (operations), and active text formatting (marks).
Key characteristics:
Node with a path of [].interface Editor {
children: Node[]
selection: Range | null
operations: Operation[]
marks: Omit<Text, 'text'> | null
// Schema-specific node behaviors.
isInline: (element: Element) => boolean
isVoid: (element: Element) => boolean
markableVoid: (element: Element) => boolean
normalizeNode: (entry: NodeEntry) => void
onChange: (options?: { operation?: Operation }) => void
// Overrideable core actions.
addMark: (key: string, value: any) => void
apply: (operation: Operation) => void
deleteBackward: (unit: 'character' | 'word' | 'line' | 'block') => void
deleteForward: (unit: 'character' | 'word' | 'line' | 'block') => void
deleteFragment: () => void
insertBreak: () => void
insertFragment: (fragment: Node[]) => void
insertNode: (node: Node) => void
insertText: (text: string) => void
removeMark: (key: string) => void
}Normalizing is the process of ensuring your editor's content always adheres to a specific, valid data structure. Unlike validation, which only identifies invalid states, normalizing actively fixes the content to make it valid again. This is crucial when handling complex, nested data or when users paste arbitrary rich text that might break your schema.
Slate uses a multi-pass approach: when you apply a fix via a Transform, it triggers a new normalization pass. This allows you to write simple normalizers that focus on fixing a single specific invalid state at a time, trusting that Slate will re-run the process until the entire document is valid.
A Point refers to a specific position within a text node. It combines a Path (to locate the node) and an offset (to locate the position within that node's text string).
Important: Points always refer to text nodes. They cannot be used to point to non-text elements directly; they represent the 'cursors' or 'carets' within the text.
Example for a text node at path [0, 0] containing 'A line of text!':
{ path: [0, 0], offset: 0 }{ path: [0, 0], offset: 15 }interface Point {
path: Path
offset: number
}Operations are the granular, low-level actions that occur when invoking transforms. While a single high-level transform (like a user typing a word) might trigger multiple operations, Slate's core automatically converts complex transforms into these low-level operations and applies them to the editor.
Most developers will interact with high-level transforms. You only need to work directly with operations if you are implementing advanced features like collaborative editing, where you need to define, apply, compose, or undo specific, discrete changes to the document.
// Example of applying a low-level operation directly
editor.apply({
type: 'insert_text',
path: [0, 0],
offset: 15,
text: 'A new string of text to be inserted.',
})In the current architecture, plugins are plain functions that receive an Editor object, augment it, and return it. This uses standard function composition (wrapping) instead of the previous middleware stack.
Plugins can:
editor.exec function.editor.apply.This approach allows plugins to focus purely on rich-text logic, leaving rendering and event handling to React.