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

Plite DOM

PreviousNext

Use DOM, clipboard, hotkey, and coverage helpers outside React-owned rendering.

@platejs/plite-dom is the DOM bridge for Plite editors. It owns DOM point/range conversion, selection conversion, clipboard formatting, hotkey helpers, contenteditable helpers, and DOM coverage metadata used by framework runtimes. React apps normally use these APIs through @platejs/plite-react.

Usage

Framework runtimes usually call the DOM bridge through installed editor APIs.

editor.api.dom.focus();
editor.api.dom.clipboard.insertTextData(dataTransfer);
editor.api.dom.focus();
ResourcesHistory Editor API

On This Page

UsagePublic Utility GroupsHost CodecsPublic Type GroupsDOM CoverageInternal SubpathRelated Docs
Build your editor
Production-ready AI template and reusable components.
Get all-access
editor.api.dom.clipboard.
insertTextData
(dataTransfer);

Use direct public imports from @platejs/plite-dom for framework integration code that needs DOM bridge helpers without React.

import { DOMCoverage, Hotkeys, isDOMNode } from "@platejs/plite-dom";
import { DOMCoverage, Hotkeys, isDOMNode } from "@platejs/plite-dom";

Public Utility Groups

dom() installs the DOM bridge extension on a core editor. PliteDOMResolutionError is the thrown error type for failed assert-style DOM resolution.

DOMCoverage owns hidden, staged, and virtualized same-root coverage metadata.

Hotkeys, isHotkey, and Key cover keyboard matching and keyboard names. TRIPLE_CLICK is the click count Plite uses for block-level triple-click handling.

DOM utilities include shadow-aware traversal, active element/window/selection lookups, DOM type guards, DOM point normalization, plain-text paste detection, tracked mutation detection, and DOM order checks:

import {
  closestShadowAware,
  containsShadowAware,
  getActiveElement,
  getDefaultView,
  getSelection,
  hasShadowRoot,
  isAfter,
  isBefore,
  isDOMElement,
  isDOMNode,
  isDOMSelection,
  isDOMText,
  isPlainTextOnlyPaste,
  isTrackedMutation,
  normalizeDOMPoint,
} from "@platejs/plite-dom";
import {
  closestShadowAware,
  containsShadowAware,
  getActiveElement,
  getDefaultView,
  getSelection,
  hasShadowRoot,
  isAfter,
  isBefore,
  isDOMElement,
  isDOMNode,
  isDOMSelection,
  isDOMText,
  isPlainTextOnlyPaste,
  isTrackedMutation,
  normalizeDOMPoint,
} from "@platejs/plite-dom";

Text-diff utilities include string diff normalization, merging, point/range projection, target-range calculation, and state verification:

import {
  applyStringDiff,
  mergeStringDiffs,
  normalizePoint,
  normalizeRange,
  normalizeStringDiff,
  targetRange,
  verifyDiffState,
} from "@platejs/plite-dom";
import {
  applyStringDiff,
  mergeStringDiffs,
  normalizePoint,
  normalizeRange,
  normalizeStringDiff,
  targetRange,
  verifyDiffState,
} from "@platejs/plite-dom";

CAN_USE_DOM guards SSR-only initialization. Mounted DOM adapters resolve browser behavior from their own root.

Decoration helpers include isElementDecorationsEqual, isTextDecorationsEqual, and splitDecorationsByChild.

Host Codecs

Install schema-aware clipboard formats as one named extension with hostCodecs. Keep a codec inline when that extension is its only owner; use defineHostCodec only when the same codec is reused. Each callback receives an immutable EditorCoreStateView; parse callbacks also receive a snapshot of the incoming host formats and files.

import {
  defineExtension,
  property,
  schema,
  target,
} from "@platejs/plite";
import { hostCodecs } from "@platejs/plite-dom";
import { decodeHtmlSlice, encodeHtmlSlice } from "./html-codec";
 
const Bold = schema.textProperty("bold", property.boolean(), {
  target: target.type("paragraph"),
});
const DataAttribute = schema.elementProperty(
  schema.key.prefix("data_"),
  property.string(),
  { target: target.group("block") }
);
 
const editor = usePliteEditor({
  extensions: [
    defineExtension("app-schema", {
      schema: { properties: [Bold, DataAttribute] },
    }),
    hostCodecs("app-host-codecs", [
      {
        format: "text/html",
        key: "app-html",
        owns: [{ kind: "element", type: "paragraph" }, Bold, DataAttribute],
        parse: ({ data, state }) => decodeHtmlSlice(data, state.schema),
        serialize: ({ slice, state }) => encodeHtmlSlice(slice, state.schema),
      },
    ]),
  ],
  initialValue,
});
import {
  defineExtension,
  property,
  schema,
  target,
} from "@platejs/plite";
import { hostCodecs } from "@platejs/plite-dom";
import { decodeHtmlSlice, encodeHtmlSlice } from "./html-codec";
 
const Bold = schema.textProperty("bold", property.boolean(), {
  target: target.type("paragraph"),
});
const DataAttribute = schema.elementProperty(
  schema.key.prefix("data_"),
  property.string(),
  { target: target.group(


















Parsing returns an intact ContentSlice, including its open edge depths. Use ContentSlice.closed(content) for a closed fragment or ContentSlice.fromJSON(payload) for a validated open slice. The replace-slice command fits the result against the actual paste range. Returning null or a slice that cannot fit delegates to the next codec without publishing a partial write. Codecs run in reverse configuration order, so the last configured codec gets the first chance to handle a format.

Parse and query callbacks receive { data, format, source, state }. Serialization receives { format, slice, state }. Codecs do not receive the editor, a live DataTransfer, a fitter, or a write transaction. query is a read-only applicability check; parsing only decodes the payload, and the host dispatcher owns fitting and insertion.

Ownership claims compile against the candidate editor schema before an extension revision publishes. { kind: "schema" } owns the complete schema. Element claims use stable element types. Property claims reuse the same schema.elementProperty(...) or schema.textProperty(...) declaration in the schema contribution and codec. Matching is structural, not object-identity based. The compiler derives one stable identity from the declaration's placement, key, and target, so equal keys with disjoint targets remain independently claimable. Key-only claims and raw compiled IDs are not accepted. Duplicate codec keys, unknown declarations, and overlapping claims in the same MIME format and direction reject the complete configuration revision. Parse and serialize ownership are independent.

Codec parsing is a pure decode boundary. Return false from query or null from parse when a payload does not apply; insertion belongs exclusively to the fitted replace-slice command. Query, parse, and serialize exceptions go to the editor's lifecycleErrorSink with source: "host-codec", the codec key, format, phase, extension owner, and original cause. The registry then tries the next eligible codec.

Framework clipboard writers call writeHostFragmentData(editor, data, slice) to run registered serializers into a setData-compatible host sink. Applications normally use editor.api.dom.clipboard.writeSelection(dataTransfer), which writes the native Plite payload and registered host formats together.

Public Type Groups

DOM bridge types include DOMApi, DOMClipboardApi, DOMClipboardInsertDataHandler, DOMEditorOptions, ScrollIntoViewOptions, and ScrollIntoViewTarget.

DOM coverage types include DOMCoverageBoundary, DOMCoverageSelectionPolicy, DOMCoveragePlitePointResult, and DOMCoverageDOMRangeResult. Use these when a framework layer needs to describe hidden, staged, or virtualized same-root content.

DOM primitive type names include DOMNode, DOMElement, DOMText, DOMPoint, DOMRange, DOMStaticRange, and DOMSelection.

Host codec types include HostCodec, HostCodecParseContext, HostCodecPhase, HostCodecSerializeContext, HostDataSource, and HostCodecSchemaTarget.

Hotkey and diff helper types include HotkeySpec, HotkeyPlatform, HotkeyMatchOptions, KeyboardEventLike, StringDiff, and TextDiff.

DOM Coverage

DOM coverage boundaries model same-root content whose DOM is hidden, staged, or virtualized. They keep selection, copy, find, and Plite-to-DOM conversion tied to explicit policies instead of assuming every document node is mounted.

React applications usually configure DOM coverage through EditableDOMCoverageBoundary.

Internal Subpath

The /internal package subpath is reserved for sibling Plite packages in this repo. Applications, extension libraries, and framework adapters outside this workspace should use the root @platejs/plite-dom export.

Related Docs

  • React Editor
  • Editable Component
  • Clipboard And Paste
  • DOM Coverage Boundaries
  • Event Handling
"block"
) }
);
const editor = usePliteEditor({
extensions: [
defineExtension("app-schema", {
schema: { properties: [Bold, DataAttribute] },
}),
hostCodecs("app-host-codecs", [
{
format: "text/html",
key: "app-html",
owns: [{ kind: "element", type: "paragraph" }, Bold, DataAttribute],
parse: ({ data, state }) => decodeHtmlSlice(data, state.schema),
serialize: ({ slice, state }) => encodeHtmlSlice(slice, state.schema),
},
]),
],
initialValue,
});