Skip to main content
The YooEditor instance is the central object that manages your editor’s state, operations, and plugins. You create it using createYooptaEditor and pass it to the YooptaEditor component.

Creating an Editor

import { createYooptaEditor } from '@yoopta/editor';
import { useMemo } from 'react';

const editor = useMemo(() => createYooptaEditor({
  plugins: PLUGINS,
  marks: MARKS,
  value: initialValue,
  readOnly: false,
}), []);
Always create the editor instance inside useMemo to prevent re-creating it on every render. This is critical for performance and maintaining editor state.

Configuration Options

packages/core/editor/src/editor/index.tsx
type CreateYooptaEditorOptions = {
  id?: string;
  plugins: readonly YooptaPlugin<Record<string, SlateElement>>[];
  marks?: YooptaMark<any>[];
  value?: YooptaContentValue;
  readOnly?: boolean;
};

Options Reference

OptionTypeRequiredDescription
pluginsYooptaPlugin[]YesArray of plugins to enable
marksYooptaMark[]NoText formatting marks (bold, italic, etc.)
valueYooptaContentValueNoInitial editor content
readOnlybooleanNoEnable read-only mode (default: false)
idstringNoCustom editor ID (auto-generated if omitted)

YooEditor API Reference

The YooEditor instance provides a comprehensive API for interacting with the editor:

Block Operations

packages/core/editor/src/editor/types.ts
interface YooEditor {
  // Block handlers
  insertBlock: (type: string, options?: InsertBlockOptions) => string;
  updateBlock: (blockId: string, options: UpdateBlockOptions) => void;
  deleteBlock: (blockId: string, options?: DeleteBlockOptions) => void;
  duplicateBlock: (blockId: string, options?: DuplicateBlockOptions) => string;
  toggleBlock: (blockId: string, options: ToggleBlockOptions) => void;
  moveBlock: (blockId: string, options: MoveBlockOptions) => void;
  focusBlock: (blockId: string, options?: FocusBlockOptions) => void;
  mergeBlock: (options: MergeBlockOptions) => void;
  splitBlock: (options?: SplitBlockOptions) => string | undefined;
  getBlock: (options: GetBlockOptions) => YooptaBlockData | null;
  
  // Depth control
  increaseBlockDepth: (blockId: string, options?: DepthOptions) => void;
  decreaseBlockDepth: (blockId: string, options?: DepthOptions) => void;
}
See Block System for detailed documentation of each method.

Element Operations

packages/core/editor/src/editor/types.ts
interface YooEditor {
  // Element handlers
  insertElement: (options: InsertElementOptions) => void;
  updateElement: (options: UpdateElementOptions) => void;
  deleteElement: (options: DeleteElementOptions) => void;
  getElement: (options: GetElementOptions) => SlateElement | null;
  getElements: (options: GetElementsOptions) => SlateElement[];
  getElementEntry: (options: GetElementEntryOptions) => NodeEntry | null;
  getElementPath: (options: GetElementPathOptions) => Path | null;
  getElementRect: (options: GetElementRectOptions) => DOMRect | null;
  getParentElementPath: (options: GetParentElementPathOptions) => Path | null;
  getElementChildren: (options: GetElementChildrenOptions) => Descendant[];
  isElementEmpty: (options: IsElementEmptyOptions) => boolean;
}
See Element System for detailed documentation.

Element Builder

The editor.y method provides a fluent API for building element structures:
packages/core/editor/src/editor/types.ts
interface YooEditor {
  // Element structure builder
  y: ((type: string, options?: ElementStructureOptions) => SlateElement) & {
    text: (text: string, marks?: TextNodeOptions) => SlateElementTextNode;
    inline: (type: string, options?: ElementStructureOptions) => SlateElement;
  };
}
The y builder method is inspired by JSX but works with plain JavaScript/TypeScript. It’s a powerful way to construct complex element hierarchies programmatically.
// Create a paragraph with formatted text
const element = editor.y('paragraph', {
  children: [
    editor.y.text('Hello '),
    editor.y.text('world', { bold: true }),
    editor.y.text('!'),
  ]
});

// Create a link (inline element)
const link = editor.y.inline('link', {
  props: { url: 'https://example.com', target: '_blank' },
  children: [editor.y.text('Click here')]
});
See Element System for more examples.

State Management

packages/core/editor/src/editor/types.ts
interface YooEditor {
  id: string;
  readOnly: boolean;
  children: YooptaContentValue;  // Current content
  path: YooptaPath;              // Current selection/path
  
  isEmpty: () => boolean;
  getEditorValue: () => YooptaContentValue;
  setEditorValue: (value: YooptaContentValue) => void;
  setPath: (path: YooptaPath) => void;
}

Events

packages/core/editor/src/editor/types.ts
interface YooEditor {
  on: <K extends keyof YooptaEventsMap>(
    event: K,
    fn: (payload: YooptaEventsMap[K]) => void,
  ) => void;
  once: <K extends keyof YooptaEventsMap>(
    event: K,
    fn: (payload: YooptaEventsMap[K]) => void,
  ) => void;
  off: <K extends keyof YooptaEventsMap>(
    event: K,
    fn: (payload: YooptaEventsMap[K]) => void,
  ) => void;
  emit: <K extends keyof YooptaEventsMap>(
    event: K,
    payload: YooptaEventsMap[K]
  ) => void;
}
See Event System for available events and usage examples.

Focus Management

packages/core/editor/src/editor/types.ts
interface YooEditor {
  isFocused: () => boolean;
  blur: (options?: EditorBlurOptions) => void;
  focus: () => void;
  refElement: HTMLElement | null;  // Reference to editor DOM element
}

Content Parsers

packages/core/editor/src/editor/types.ts
interface YooEditor {
  getHTML: (content: YooptaContentValue) => string;
  getMarkdown: (content: YooptaContentValue) => string;
  getPlainText: (content: YooptaContentValue) => string;
  getEmail: (content: YooptaContentValue, options?: EmailTemplateOptions) => string;
  getYooptaJSON: (content: YooptaContentValue) => string;
}

History

packages/core/editor/src/editor/types.ts
interface YooEditor {
  undo: (options?: UndoRedoOptions) => void;
  redo: (options?: UndoRedoOptions) => void;
  batchOperations: (fn: () => void) => void;
  
  // History control
  isSavingHistory: () => boolean;
  isMergingHistory: () => boolean;
  withoutSavingHistory: (fn: () => void) => void;
  withSavingHistory: (fn: () => void) => void;
  withoutMergingHistory: (fn: () => void) => void;
  withMergingHistory: (fn: () => void) => void;
}

Advanced

packages/core/editor/src/editor/types.ts
interface YooEditor {
  // Plugin and format access
  plugins: Record<string, Plugin>;
  formats: YooptaFormats;
  marks: YooptaMark<any>[];
  
  // Block editor map (Slate instances per block)
  blockEditorsMap: YooptaPluginsEditorMap;
  
  // Low-level operations
  applyTransforms: (operations: YooptaOperation[], options?: ApplyTransformsOptions) => void;
  
  // Decorators (for collaboration cursors, search highlights, etc.)
  decorators: Map<string, DecoratorFn>;
  leafDecorators: Map<string, LeafDecoratorRenderFn>;
  
  // Collaboration hooks
  buildSlateEditorFn?: (blockId: string) => SlateEditor;
  isRemoteSlateOp?: (slate: SlateEditor) => boolean;
}

Usage Example

Here’s a complete example showing editor creation and usage:
import { createYooptaEditor, YooptaEditor } from '@yoopta/editor';
import { Paragraph, HeadingOne, HeadingTwo } from '@yoopta/plugins';
import { Bold, Italic, Underline } from '@yoopta/marks';
import { useMemo, useState } from 'react';

const PLUGINS = [Paragraph, HeadingOne, HeadingTwo];
const MARKS = [Bold, Italic, Underline];

function MyEditor() {
  const [value, setValue] = useState({});
  
  const editor = useMemo(() => createYooptaEditor({
    plugins: PLUGINS,
    marks: MARKS,
    value,
  }), []);
  
  // Listen to changes
  const handleChange = (newValue, { operations }) => {
    setValue(newValue);
    console.log('Operations:', operations);
  };
  
  // Custom button to insert a heading
  const insertHeading = () => {
    editor.insertBlock('HeadingOne', {
      focus: true,
      elements: editor.y('heading-one', {
        children: [editor.y.text('New Heading')]
      })
    });
  };
  
  return (
    <div>
      <button onClick={insertHeading}>Add Heading</button>
      <YooptaEditor
        editor={editor}
        onChange={handleChange}
        placeholder="Start typing..."
        style={{ width: 750 }}
      />
    </div>
  );
}

Read-Only Mode

You can enable read-only mode to prevent editing:
const editor = useMemo(() => createYooptaEditor({
  plugins: PLUGINS,
  marks: MARKS,
  value: content,
  readOnly: true,  // Enable read-only mode
}), []);
Read-only mode is useful for displaying content without allowing edits, such as in a preview or public view.

Accessing Editor from Context

Inside custom plugin components, you can access the editor instance using hooks:
import { useYooptaEditor, useBlockData } from '@yoopta/editor';

function MyCustomComponent() {
  const editor = useYooptaEditor();
  const block = useBlockData();
  
  const handleClick = () => {
    editor.updateBlock(block.id, {
      type: 'HeadingOne'
    });
  };
  
  return <button onClick={handleClick}>Convert to Heading</button>;
}

Next Steps

Block System

Learn about block operations and management

Element System

Work with elements within blocks

Event System

Handle editor events

Plugin System

Build custom plugins

Build docs developers (and LLMs) love