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 Layout

PreviousNext

Derive page geometry, line fragments, and paged editor mount plans from Plite state.

@platejs/plite-layout derives page geometry, line fragments, and page-level mount plans from a Plite editor. Use it for pagination lanes, print-like surfaces, and page virtualization that still keeps Plite as the document model. Keep production use behind explicit flags until your browser, export, table, image, and collaboration requirements are proven.

Page Layout

Create a layout reader with createPliteLayout. The reader chooses the built-in measurement engine and derives layout from the current editor snapshot and your page settings.

import { createPliteLayout } from "@platejs/plite-layout";
 
const layout = createPliteLayout(editor, {
  page: {
    margins: 72,
    preset: "letter",








Plite HyperscriptAnnotations

On This Page

Page LayoutReact UsageHeadless And Static UseLayout-Owned BoxesPage VirtualizationMeasurement CaveatRelated Docs
Build your editor
Production-ready AI template and reusable components.
Get all-access
},
});
layout.reconfigure({
page: {
margins: 48,
preset: "a4",
},
});
import { createPliteLayout } from "@platejs/plite-layout";
 
const layout = createPliteLayout(editor, {
  page: {
    margins: 72,
    preset: "letter",
  },
});
 
layout.reconfigure({
  page: {
    margins: 48,
    preset: "a4",
  },
});

The layout output is derived state. Store document content in Plite roots and store product settings in state fields; do not write layout fragments into the document unless your product explicitly needs authoritative page breaks.

React Usage

Use PagedEditable from @platejs/plite-layout/react when the editor surface should render pages.

import { Plite, usePliteEditor } from "@platejs/plite-react";
import { PagedEditable, usePliteLayout } from "@platejs/plite-layout/react";
 
const DocumentEditor = () => {
  const editor = usePliteEditor({
    initialValue,
  });
  const layout = usePliteLayout(editor, {
    page: { margins: 72, preset: "letter" },
  });
 
  return (
    <Plite editor={editor}>
      <PagedEditable layout={layout} />
    </Plite>
  );
};
import { Plite, usePliteEditor } from "@platejs/plite-react";
import { PagedEditable, usePliteLayout } from "@platejs/plite-layout/react";
 
const DocumentEditor = () => {
  const editor = usePliteEditor({
    initialValue,
  });
  const layout = usePliteLayout(editor, {
    page: { margins: 72, preset: "letter" },
  });
 
  return (
    <Plite editor={editor}>
      <PagedEditable layout={layout} />
    </Plite>
  );
};

PagedEditable wraps Editable, so normal Editable props still apply: renderElement, renderLeaf, decorate, domStrategy, and keyboard handlers stay on the editor surface.

usePliteLayout publishes option changes after React commits. Outside React, call layout.reconfigure(nextOptions) to replace the complete configuration in one atomic refresh.

Use createPlitePageLayout or usePlitePageLayout only when you provide an explicit engine, such as a custom measurement engine or pretextPageLayoutEngine().

Headless And Static Use

createPliteLayout can run outside React and can fall back to an estimated engine when browser canvas measurement is unavailable. Use that for previews, tests, and export planning. Treat static output as derived geometry, not as an authoritative PDF, print, or collaboration layout source unless your product provides the measurement engine and proof for that target.

Layout-Owned Boxes

Tables, images, embeds, and other block formatting context style nodes should own their layout units through the selected layout engine. The engine should not split the Plite table node just to paginate a table. It can paginate engine-owned row units while the document tree stays stable.

Page Virtualization

Use page-level virtualization when pagination is enabled. Virtualizing whole pages keeps layout, selection, and page chrome aligned better than mounting and unmounting individual blocks inside a page.

The page mount plan keeps pages mounted when they are visible, selected, promoted by interaction, or involved in composition. That makes it the right boundary for print-like editors.

Measurement Caveat

The built-in Pretext-backed engine measures text with browser font metrics. That gives stable results inside one browser profile, but different operating systems and browsers can still produce slightly different line breaks. Products that need exact collaboration or export parity should use an authoritative page break source or a shared measurement profile.

Related Docs

  • Improving Performance
  • Virtualized Rendering
  • DOM Coverage Boundaries