Editor is the editor type returned by createEditor and useCreateEditor. The
selected import path decides whether the instance is headless or React-enabled.
Both forms expose typed plugin portals, api, editor.update() transactions,
and editor-local plugin stores.
| Import | Constructor | Notes |
|---|---|---|
platejs | createEditor(options) | Headless Plate editor for server and non-React code. |
platejs/react | createEditor(options) or useCreateEditor(options) | React-enabled editor with components, stores, DOM integration, and hooks. |
Import the matching Editor type from the same entrypoint as the constructor.
The editor owns document reads, transactions, typed plugin access, DOM services, and lifecycle state.
Unique editor instance id. createEditor uses the provided id or
creates one with nanoid().
Read current document children with editor.read.children(), selection
with editor.read.selection(), and the latest published commit with
editor.read.lastCommit().
Core Plate APIs, explicit editor-wide APIs, and installed plugin APIs inferred under their plugin names.
Transaction entrypoint for document, selection, history, and plugin commands.
Return the descriptor-scoped portal for a plugin's API, update commands, schema identity, and store. The descriptor supplies the inferred type.
Public Plate runtime-instance and lifecycle state. Compiled plugin registries stay private to Plate.
React and DOM runtime state is read through Plate runtime APIs. Plate exposes only editor identity and lifecycle fields on editor.runtime; compiled plugin registries are private implementation data.
| State | Read path | Set by |
|---|---|---|
| composition | editor.api.react.isComposing() | Plate React composition runtime. |
| focus | editor.api.react.isFocused() | Plate React focus runtime. |
| read-only | editor.read.view.isReadOnly() or editor.api.react.isReadOnly() | createEditor, <EditorRoot>, and <EditorContent>. |
| Field | Type | Notes |
|---|---|---|
userId | string | null | undefined | Collaborative identity passed through editor options. |
isNormalizing | boolean | undefined | true while Plate applies initial-value normalization. |
Pass the installed descriptor to editor.plugin(Plugin). TypeScript infers
that plugin's API, reads, update commands, schema identity, and editor-local
state. Keep the descriptor's inferred type at call sites.
import { createEditor, definePlugin } from 'platejs';
const PanelPlugin = definePlugin('panel', {
initialState: { open: false },
api: ({ store }) => ({
isOpen: () => store.get('open'),
}),
});
const editor = createEditor({ plugins: [PanelPlugin] });
const panel = editor.plugin(PanelPlugin);
const open = panel.store.get('open');
const sameApi = editor.api.panel === panel.api;import { createEditor, definePlugin } from 'platejs';
const PanelPlugin = definePlugin('panel', {
initialState: { open: false },
api: ({ store }) => ({
isOpen: () => store.get('open'),
}),
});
const editor = createEditor({ plugins: [PanelPlugin] });
const panel = editor.plugin(PanelPlugin);
const open = panel.store.get('open');
const sameApi = editor.api.panel === panel.api;editor.api.panel and panel.api reference the same immutable API object.
Use editor.read.<name> for plugin reads on a concrete editor, or
editor.plugin(Plugin).read when the descriptor supplies the exact contract.
| Access | Use it for |
|---|---|
editor.plugin(Plugin).installed | Check installation before reading another field when the plugin is optional. |
editor.plugin(Plugin).api | Call plugin services inferred from the descriptor. |
editor.plugin(Plugin).read | Run plugin-owned reads against current editor state. |
editor.plugin(Plugin).update | Run a plugin-owned transaction command. |
editor.plugin(Plugin).store.get(key, ...args) | Read a state field or named selector result. |
editor.plugin(Plugin).store.get() | Read the complete current plugin state. |
editor.plugin(Plugin).schema.type | Read an element descriptor's installed node type. |
editor.plugin(Plugin).schema.key | Read a primary-mark descriptor's installed property key. |
Behavior-only descriptors do not expose a consumer schema. A descriptor
lookup checks the descriptor family as well as the name.
In React, use useEditor().plugin(Plugin) for the inferred portal.
usePluginStore(Plugin, key) or usePluginStore(Plugin, selector) subscribes
the component to plugin state.
editor.plugin requires a descriptor. When application data selects a
capability at runtime, resolve that value through an application-owned map of
allowed descriptors, then pass the selected descriptor to editor.plugin.
Check .installed first when absence is valid. Read .schema.type only when
the caller expects an element plugin, or .schema.key when it expects a primary
mark. A mismatched schema kind throws. A name does not prove a descriptor family
or provide its typed API, update, and store contract.
useCreateEditor memoizes the React createEditor constructor. The React entrypoint
creates each plugin's editor-local store from initialState and installs React
core plugins before user plugins.
import { useCreateEditor } from "platejs/react";
import { BoldPlugin } from "platejs/react";
export function useBasicEditor() {
return useCreateEditor({
plugins: [BoldPlugin],
initialValue: [
{
type: "paragraph",
children: [{ text: "Bold text is ready." }],
},
],
});
}import { useCreateEditor } from "platejs/react";
import { BoldPlugin } from "platejs/react";
export function useBasicEditor() {
return useCreateEditor({
plugins: [BoldPlugin],
initialValue: [
{
type: "paragraph",
children: [{ text: "Bold text is ready." }],
},
],
});
}The headless createEditor performs the shared setup:
| Step | Behavior |
|---|---|
| Runtime state | Preserves Plate editor.id and initializes runtime.userId. |
| Plugin access | Publishes installed APIs under editor.api[name] and resolves descriptor-owned portals through editor.plugin(Plugin). |
| Core plugins | Resolves core plugins, replaces core plugins with custom plugins that share the same name, and resolves the root plugin. |
| Components | Merges components into root-plugin component overrides. |
| Normalization guard | Wraps normalizeNode so editor.api.shouldNormalizeNode(entry) can skip a normalization pass. |
| Initial value | Initializes the value and selection through the runtime update path unless skipInitialization is true. |
initialValue accepts a Plate value or a synchronous function that returns one.
Load remote data before constructing the editor. Use the callback form when a
decoder needs the compiled plugin model.
Core plugins are resolved before user plugins. Navigation Feedback is a React
editor default and can be disabled with navigationFeedback: false. Its API
uses the mounted editor returned by useEditor().
Log a debug message when debug logging is enabled.
Log an info message when the configured log level allows it.
Log a warning when the configured log level allows it.
Throw an EditorError by default in development. Configure DebugPlugin to
change logging or throwErrors.
Deserialize an HTML element into Plate nodes. The HTML parser plugin calls
this for text/html paste data.
Flash a live element in the calling mounted React view without a document or selection change.
Clear this mounted view's feedback and return whether a target was active.
Mutations run through editor.update. Core Plate commands live on the
transaction object, and plugins contribute their keyed commands through
the constructor's update field.
Replace primary children, named roots, persisted meta, and optionally the selection through one configured Plate update.
Insert a node or fragment through the Plate node transaction group.
Update matching nodes through the Plate node transaction group.
Toggle an inline mark through the Plate mark transaction group.
Update the current selection through the Plate selection transaction group.
Some core behavior is exposed by routing browser/editor events into the Plate transaction runtime rather than by adding public editor methods.
| Surface | Effect |
|---|---|
| Product codec registry | Compiles constructor codec declarations created by context-bound defineCodecs(map) or defineCodecs(TargetPlugin, map), then delegates exact ContentSlice decoding and encoding to the generic clipboard runtime. |
| Plate change events | Emits committed node and text change contexts through Plate on.nodeChange and on.textChange. |
| Plate React runtime | Handles editable keyboard, composition, focus, read-only, DOM selection export, and decoration refresh behavior. |
HtmlPlugin | Registers the text/html parser path and owns HTML element conversion through editor.api.html.deserialize. |
BaseParagraphPlugin | Registers the default paragraph element under name paragraph and maps HTML <p> elements, excluding code-font paragraphs. |
Use ReturnType<typeof createBasicEditor> when another module needs the exact
type returned by your editor factory. The installed plugin schema supplies the
value type.
import type { ValueOf } from "platejs";
import { BoldPlugin, createEditor } from "platejs/react";
const BasicKit = [BoldPlugin] as const;
export const createBasicEditor = () => createEditor({ plugins: BasicKit });
type BasicEditor = ReturnType<typeof createBasicEditor>;
type BasicValue = ValueOf<BasicEditor>;import type { ValueOf } from "platejs";
import { BoldPlugin, createEditor } from "platejs/react";
const BasicKit = [BoldPlugin] as const;
export const createBasicEditor = () => createEditor({ plugins: BasicKit });
type BasicEditor = ReturnType<typeof createBasicEditor>;
type BasicValue = ValueOf<BasicEditor>;| Type | Purpose |
|---|---|
Editor | Broad editor type for framework boundaries. |
ReturnType<typeof createBasicEditor> | Exact editor type inferred from the factory's plugin tuple. |
ValueOf<EditorType> | Document value derived from that editor's compiled schema. |
EditorRoot, EditorContent, EditorPreview, and component-layer runtime effects.editor.update.