Files

@wrnexus/block-editor

Reusable editor state, DOM surfaces, inspector drafts, clipboard-download UI, selection actions, and explicit block/preset composition.

Configure a builder

import { createBuilderKit, createBlockEditorState, mountBlockCanvas } from "@wrnexus/block-editor";
import { emailEditorBlocks } from "@wrnexus/email-renderer/create";
import { emailPresets } from "@wrnexus/email-renderer/presets";

const builder = createBuilderKit({
  blocks: [...emailEditorBlocks, myTrustedBlockDefinition],
  presets: [...emailPresets, myTrustedSectionPreset],
});

const palette = builder.blocks(); // manifests: name, icon, category, schemas
const presets = builder.presets();
const node = builder.createBlock("custom.my-block", { id: () => crypto.randomUUID() });

Definitions use defineBlock from @wrnexus/blocks: manifest, create, renderers, textRenderer, inspector controls, and migrations. Presets have id, localized name, icon, and create({ id }). Registration is explicit and frozen; duplicates and invalid created trees throw before insertion. Factories must return schema-valid instances. Placement still goes through the document-kind command validator; kit validation is not publish authorization.

Use the same trusted definitions in your document kind and server renderer. Adding a block to a palette alone does not enable its rendering or publishing. The built-in email production adapter currently uses its core email kind; custom email target composition and a complete high-level editor component remain work in progress.

The package exports InspectorDrafts, builderOutlineLabel, builderDragAnnouncement, updateBuilderCanvas, showBuilderBlockActions, editBuilderText, showImageFallbacks, and offerBuilderDownload. These are low-level reusable surfaces, not a drop-in complete studio yet. The host owns authenticated load/save/render/asset service callbacks. createBlockEditorState uses validated commands; host applications must actually wire it rather than assuming all application mutations already use that state.