⚠️ Work in progress — createCMS is pre-1.0 and not production-ready (not tested in production). Expect breaking changes.
createCMS
Reference

Editor canvas

Unstyled parts, hooks, and types for @createcms/react/editor/canvas.

Headless editor primitive: live surface, overlay and interaction layer. Unstyled; styling happens in the consumer's wrapper components (registry). Use inside Editor.Root.

import { Canvas } from '@createcms/react/editor/canvas';

Usage

Canvas.Root renders the store tree through a components map. Pass a plain { heading: Heading } record or a { _components } object (the shape createBlocksMap returns). components is required. Consumer children are the overlay slot, rendered after the tree inside the host.

import { Editor } from '@createcms/react/editor';
import { Canvas } from '@createcms/react/editor/canvas';

function PageCanvas({ schema, tree, pageBlocks }) {
  return (
    <Editor.Root schema={schema} defaultValue={tree}>
      <Canvas.Root components={pageBlocks} style={{ position: 'relative' }}>
        <Canvas.Overlay>
          <Canvas.SelectionRing />
          <Canvas.HoverRing />
          <Canvas.FieldRing />
          <Canvas.BlockToolbar side="top" align="start">
            {/* consumer buttons via useBlockActions(selectedId) */}
          </Canvas.BlockToolbar>
          <Canvas.InsertButton placement="between" type="paragraph" />
          <Canvas.DragHandle blockId="selectedBlockId" />
          <Canvas.PaletteItem type="paragraph" />
          <Canvas.DropIndicator />
          <Canvas.DragPreview />
          <Canvas.InlineText />
        </Canvas.Overlay>
      </Canvas.Root>
    </Editor.Root>
  );
}

Spread edit.block on each block's root element and edit.field.<key> on the element that shows that property (BlockComponentProps.edit from @createcms/core/react). Leftover missing anchors are a dev warning because measurement cannot see a block without data-editor-block.

resolve and components must be referentially stable: an inline object literal re-runs every resolver. surface defaults to 'inline'. surface="frame" throws (Canvas.Root: surface "frame" is not implemented).

interactive is 'edit' | 'select' | 'none' (default 'edit'). Optional resolve handles reference / link / string; never image. Unresolved values omit or mark data-unresolved.

The canvas host needs a positioning context (position: relative or similar) so Canvas.Overlay's absolute; inset: 0 covers the surface. Overlay portals into the host. Overlay is pointer-events: none and is not aria-hidden. Rings set aria-hidden. A child that must receive pointer input sets pointer-events: auto on itself.

DnD is pointer-based (not HTML5 drag). Canvas.InlineText is the GLASS overlay for string / richText in edit.

Parts

PartDefault elementPropsData attributes
Canvas.Rootdivcomponents (required), surface, interactive, resolve, children (overlay), render, div propsdata-editor-canvas, data-interactive, data-dragging, data-editing
Canvas.Overlaydivrender, div props. Portals into the canvas host.data-editor-overlay
Canvas.SelectionRingdivrender, div props. Sized from the selected block rect.data-editor-selection-ring, data-block-type, data-can-move, data-can-delete, data-unresolved
Canvas.HoverRingdivrender, div props. Hidden while dragging, editing, or when hovered equals selected.data-editor-hover-ring, data-block-type, data-can-move, data-can-delete, data-unresolved
Canvas.FieldRingdivrender, div props. Sized from the focused field rect (own-block only).data-editor-field-ring, data-block-type, data-can-move, data-can-delete, data-unresolved
Canvas.BlockToolbardivalign, side, offset, render, div props. Consumer supplies buttons. Shown in edit and select.data-editor-block-toolbar, data-side, data-block-type
Canvas.InsertButtonbuttonplacement (between | container), optional type, optional onInsert, render, button props. Shown only in edit.data-editor-insert-button, data-orientation, data-empty-container
Canvas.DragHandlebuttonblockId (required), render, button props. Move an existing block by pointer drag. Shown only in edit.data-editor-drag-handle, data-dragging on the handle while its block is the move session
Canvas.PaletteItembuttontype (required), optional properties, render, button props. Click inserts like Editor.AddBlock; drag adds by geometry.data-editor-palette-item, data-block-type, data-dragging while this item starts a new-block session
Canvas.DropIndicatordivrender, div props. Line or box from the active drop target. Presentational.data-editor-drop-indicator, data-orientation, data-variant, data-kind (new | move)
Canvas.DragPreviewdivrender, div props, optional children. Follows the pointer during a session. Presentational.data-editor-drag-preview, data-kind (new | move)
Canvas.InlineTextdivsuggest, discardOnEscape, render, div props. Overlays a contentEditable glass on string and richText fields in edit.data-editor-inline-text, data-editing, data-block-type, data-field

Hooks

HookReturnsNotes
useResolvedT | undefinedReads the canvas resolve cache. Throws outside Canvas.Root. undefined is miss or pending.
useBlockRectCanvasRect | nullContent coordinates of a block id (union of same-id nodes). Throws outside Canvas.Root.
useFieldRectCanvasRect | nullContent coordinates of a field on its own block. Throws outside Canvas.Root.
useInsertTargetInsertTarget | nullResolved line or box from pointer and hover. Throws outside Canvas.Root. Null in select / none, while dragging or editing, or without pointer / hover.

Types

TypeDescription
CanvasRootPropsProps of Canvas.Root.
CanvasOverlayPropsProps of Canvas.Overlay.
CanvasSelectionRingPropsProps of Canvas.SelectionRing.
CanvasHoverRingPropsProps of Canvas.HoverRing.
CanvasFieldRingPropsProps of Canvas.FieldRing.
CanvasRingStateblockType, canMove, canDelete, unresolved on every ring.
CanvasRect{ x, y, width, height } in canvas content coordinates.
CanvasComponentsA plain block map, or { _components } as createBlocksMap returns.
CanvasComponentOne block component in a CanvasComponents map.
CanvasResolveOptional reference / link / string resolvers. image is never resolved.
ResolveKindWhich resolver slot a value uses (reference, link, or string).
CanvasInteractive'edit' | 'select' | 'none'. Default 'edit'.
CanvasSurface'inline' | 'frame'. Default 'inline'. 'frame' throws.
InsertTargetResolved insert: parentId, index, orientation, variant, rect, allowedTypes, nested.
InsertOrientation'horizontal' | 'vertical'.
InsertVariant'line' | 'box'.
ResolveInsertAtOptionsInjected rects and row-flow stub for resolveInsertAt.
CanvasBlockToolbarPropsProps of Canvas.BlockToolbar.
CanvasInsertButtonPropsProps of Canvas.InsertButton.
CanvasDragHandlePropsProps of Canvas.DragHandle.
CanvasDragPreviewPropsProps of Canvas.DragPreview.
CanvasDropIndicatorPropsProps of Canvas.DropIndicator.
CanvasPaletteItemPropsProps of Canvas.PaletteItem.
PointerStoreExternal pointer snapshot store on the canvas context.
PointerSnapshotOne pointer sample (client coordinates and target block id).
DragSessionActive pointer drag state (new block or move).
CanvasInlineTextPropsProps of Canvas.InlineText.
InlineSuggestOptional $-anchored suggest config: pattern, getItems, render.
InlineSuggestItemSuggest row: insertText plus consumer fields for render.
InlineSuggestRenderContextSuggest UI context: items, highlight, query, anchor rect, accept.

Helpers

ExportDescription
resolveInsertAtPure insert geometry from pointer position and block rects.
INSERT_BOX_PADPadding around an empty container insert box.
INSERT_LINE_THICKNESSHit thickness for line insert targets.
adjustMoveIndexIndex adjustment when moving a block within the same parent.
blockIdAtPointBlock id under a client point from measured rects.
DND_THRESHOLD_PXPointer distance before a drag session starts.
applyTextEditApply a DOM text edit to a string or richText value.
EMPTY_FIELD_PLACEHOLDERZero-width placeholder injected for empty inline fields.
isInlineEditableKindWhether a field kind supports Canvas.InlineText.

Data attributes

AttributeWhereMeaning
data-editor-canvashostPresence marker.
data-interactivehost'edit', 'select', or 'none'.
data-dragginghost, drag handle, palette itemPresent on the host while any canvas drag session is active; on a handle or palette item while that part owns the session.
data-editinghost, inline glassPresent while the local selection has an inline-editing target.
data-editor-blockblock root via edit.blockDocument-tree block id.
data-editor-fieldfield element via edit.field.<key>Property key, counted only inside its own block.
data-unresolvedblock root via edit.block; ringsPresent when a routed reference / link / string value is pending or missing. On a ring: any measured block element for that id has the attribute.
data-editor-readonlywrapper around referenced childrenTogether with inert, excludes the subtree from click-select and measurement.
data-editor-overlayOverlay hostPresence marker. pointer-events: none; not aria-hidden.
data-editor-block-toolbarCanvas.BlockToolbar inner chromePresence marker. role="toolbar".
data-editor-insert-buttonCanvas.InsertButtonPresence marker.
data-sideCanvas.BlockToolbar'top' or 'bottom'.
data-orientationCanvas.InsertButton'horizontal' or 'vertical'.
data-empty-containerCanvas.InsertButtonPresent when the target variant is box.
data-editor-drag-handleCanvas.DragHandlePresence marker.
data-editor-palette-itemCanvas.PaletteItemPresence marker.
data-editor-drop-indicatorCanvas.DropIndicatorPresence marker. aria-hidden.
data-editor-drag-previewCanvas.DragPreviewPresence marker. aria-hidden.
data-kinddrop indicator, drag preview'new' or 'move'.
data-variantCanvas.DropIndicator'line' or 'box'.
data-editor-selection-ringCanvas.SelectionRingPresence marker.
data-editor-hover-ringCanvas.HoverRingPresence marker.
data-editor-field-ringCanvas.FieldRingPresence marker.
data-block-typeringsStore node type. Omitted when the id is unknown.
data-can-moveringsPresent when the block is not the root.
data-can-deleteringsPresent when the block is not the root.
data-editor-inline-textCanvas.InlineText glassPresence marker. role="textbox".
data-fieldCanvas.InlineText glassProperty key being edited.

On this page