Skip to main content

Overview

Plugin types define the structure and behavior of content blocks in Yoopta Editor. This page documents the core types used to create plugins, configure elements, handle events, and extend editor functionality.

Plugin

The main plugin type that defines a complete block plugin.
type Plugin<
  TElementMap extends Record<string, SlateElement>,
  TPluginOptions = Record<string, unknown>,
> = {
  type: string;
  extensions?: (slate: SlateEditor, editor: YooEditor, blockId: string) => SlateEditor;
  commands?: Record<string, (editor: YooEditor, ...args: any[]) => any>;
  elements: {
    [K in keyof TElementMap]: PluginElement<Exclude<keyof TElementMap, K>, TElementMap[K]['props']>;
  };
  events?: PluginDOMEvents;
  lifecycle?: PluginLifeCycleEvents;
  options?: PluginOptions<TPluginOptions>;
  parsers?: Partial<Record<PluginParserTypes, PluginParsers>>;
};

Plugin Properties

type
string
required
Unique identifier for the plugin in PascalCase (e.g., "Paragraph", "HeadingOne"). This matches the block type in YooptaBlockData.
elements
PluginElementsMap
required
Map of element types to their configuration. Defines the renderable elements that make up the block.
extensions
function
Function to extend the Slate editor instance with custom behavior (e.g., handling void elements, normalizing content).
extensions: (slate, editor, blockId) => {
  const { isVoid } = slate;
  slate.isVoid = (element) => {
    return element.type === 'image' ? true : isVoid(element);
  };
  return slate;
}
commands
Record<string, Function>
Custom commands exposed by the plugin. Commands can be called via the editor instance.
commands: {
  insertImage: (editor, options) => {
    // Implementation
  }
}
events
PluginDOMEvents
DOM event handlers for the plugin (keyboard, mouse, etc.). See PluginDOMEvents.
lifecycle
PluginLifeCycleEvents
Lifecycle hooks called at specific points in the block’s lifecycle. See PluginLifeCycleEvents.
options
PluginOptions<T>
Plugin configuration including display info, shortcuts, and HTML attributes. See PluginOptions.
parsers
Record<string, PluginParsers>
Serialization and deserialization functions for HTML, Markdown, and email formats. See PluginParsers.

PluginElement

Defines a single element type within a plugin.
type PluginElement<TKeys, T> = {
  render?: (props: PluginElementRenderProps) => JSX.Element;
  props?: PluginElementProps<T>;
  asRoot?: boolean;
  children?: TKeys[];
  injectElementsFromPlugins?: string[];
  rootPlugin?: string;
  placeholder?: string;
};

PluginElement Properties

render
function
React component to render the element. Receives props including element, children, attributes, and blockId.
render: (props) => {
  return (
    <div {...props.attributes}>
      {props.children}
    </div>
  );
}
props
PluginElementProps<T>
Default properties for the element, including nodeType and custom properties.
props: {
  nodeType: 'block',
  customProp: 'default value'
}
asRoot
boolean
Whether this element should be the root element when the block is created.
children
string[]
Array of allowed child element types. Used for validation and structure.
injectElementsFromPlugins
string[]
Array of plugin types whose elements should be injectable into this element.
rootPlugin
string
Reference to the parent plugin type if this element belongs to a different plugin.
placeholder
string
Placeholder text shown when the element is empty (leaf elements only).

PluginElementsMap

Map of element types to their configurations.
type PluginElementsMap<TKeys extends string = string, TProps = PluginDefaultProps> = {
  [key in TKeys]: PluginElement<TKeys, TProps>;
};

Example

const elements: PluginElementsMap = {
  'paragraph': {
    render: ParagraphRender,
    props: { nodeType: 'block' }
  },
  'paragraph-link': {
    render: LinkRender,
    props: { nodeType: 'inline' }
  }
};

PluginOptions

Configuration options for a plugin.
type PluginOptions<T> = Partial<{
  display?: {
    title?: string;
    description?: string;
    icon?: ReactNode;
  };
  shortcuts?: string[];
  HTMLAttributes?: HTMLAttributes<HTMLElement>;
} & T>;

Properties

display
object
Display information shown in menus and UI.
shortcuts
string[]
Array of keyboard shortcuts that trigger this block type (e.g., ['mod+shift+7']).
HTMLAttributes
HTMLAttributes<HTMLElement>
Default HTML attributes applied to the rendered element.

Example

const options: PluginOptions<{}> = {
  display: {
    title: 'Heading 1',
    description: 'Large section heading',
    icon: <Heading1Icon />
  },
  shortcuts: ['mod+shift+1', '#'],
  HTMLAttributes: {
    className: 'heading-one',
    spellCheck: true
  }
};

PluginDOMEvents

DOM event handlers for plugins.
type PluginDOMEvents = {
  [key in keyof EditorEventHandlers]: (
    editor: YooEditor,
    slate: SlateEditor,
    options: PluginEventHandlerOptions,
  ) => EditorEventHandlers[key] | void;
};

Common Events

events: {
  onKeyDown: (editor, slate, { hotkeys }) => (event) => {
    if (hotkeys.isEnter(event)) {
      event.preventDefault();
      // Handle Enter key
    }
  },
  
  onPaste: (editor, slate) => (event) => {
    // Handle paste event
  },
  
  onDrop: (editor, slate) => (event) => {
    // Handle drag and drop
  }
}

PluginLifeCycleEvents

Lifecycle hooks called at specific points.
type PluginLifeCycleEvents = {
  beforeCreate?: (editor: YooEditor) => SlateElement;
  onCreate?: (editor: YooEditor, blockId: string) => void;
  onDestroy?: (editor: YooEditor, blockId: string) => void;
};

Lifecycle Hooks

beforeCreate
function
Called before a block is created. Returns the initial element structure.
beforeCreate: (editor) => {
  return editor.y('paragraph', {
    children: [editor.y.text('')]
  });
}
onCreate
function
Called after a block is created and inserted into the editor.
onCreate: (editor, blockId) => {
  console.log('Block created:', blockId);
  // Focus the new block, initialize state, etc.
}
onDestroy
function
Called before a block is removed from the editor.
onDestroy: (editor, blockId) => {
  console.log('Block destroyed:', blockId);
  // Cleanup resources, save state, etc.
}

PluginParsers

Serialization and deserialization functions.
type PluginParsers = {
  deserialize?: PluginDeserializeParser;
  serialize?: PluginSerializeParser;
};

type PluginSerializeParser = (
  element: SlateElement,
  content: string,
  blockMetaData?: YooptaBlockBaseMeta,
) => string;

type PluginDeserializeParser = {
  nodeNames: string[];
  parse?: (el: HTMLElement, editor: YooEditor) => SlateElement | YooptaBlockData[] | void;
};

Example Parsers

parsers: {
  html: {
    deserialize: {
      nodeNames: ['P'],
      parse: (el, editor) => {
        return editor.y('paragraph', {
          children: [editor.y.text(el.textContent || '')]
        });
      }
    },
    serialize: (element, content) => {
      return `<p>${content}</p>`;
    }
  },
  markdown: {
    serialize: (element, content) => {
      return content; // Plain text for paragraphs
    }
  }
}

PluginElementRenderProps

Props passed to element render functions.
type PluginElementRenderProps = RenderSlateElementProps & {
  blockId: string;
  HTMLAttributes?: HTMLAttributes<HTMLElement>;
};

type RenderSlateElementProps = Omit<RenderElementProps, 'element'> & {
  element: SlateElement;
};

Using Render Props

const ParagraphRender = (props: PluginElementRenderProps) => {
  const { element, children, attributes, blockId, HTMLAttributes } = props;
  
  return (
    <p
      {...attributes}
      {...HTMLAttributes}
      data-block-id={blockId}
    >
      {children}
    </p>
  );
};

NodeType Enum

Defines element behavior types.
enum NodeType {
  Block = 'block',
  Inline = 'inline',
  Void = 'void',
  InlineVoid = 'inlineVoid',
}

Complete Plugin Example

import { Plugin } from '@yoopta/editor';

const ParagraphPlugin: Plugin = {
  type: 'Paragraph',
  
  elements: {
    paragraph: {
      render: ParagraphRender,
      props: {
        nodeType: 'block'
      },
      placeholder: 'Type "/" for commands...'
    }
  },
  
  options: {
    display: {
      title: 'Paragraph',
      description: 'Basic text block',
      icon: <ParagraphIcon />
    },
    shortcuts: ['p']
  },
  
  events: {
    onKeyDown: (editor, slate, { hotkeys }) => (event) => {
      if (hotkeys.isEnter(event)) {
        // Handle Enter key
      }
    }
  },
  
  parsers: {
    html: {
      deserialize: {
        nodeNames: ['P'],
        parse: (el, editor) => {
          return editor.y('paragraph', {
            children: [editor.y.text(el.textContent || '')]
          });
        }
      },
      serialize: (element, content) => `<p>${content}</p>`
    }
  }
};

Type Imports

import type {
  Plugin,
  PluginElement,
  PluginElementsMap,
  PluginOptions,
  PluginDOMEvents,
  PluginLifeCycleEvents,
  PluginParsers,
  PluginElementRenderProps,
  PluginElementProps,
  NodeType,
} from '@yoopta/editor';

See Also

Build docs developers (and LLMs) love