Skip to content

@editu/react

React 19 components and hooks for Editu editor.

Looking for a guide?

See the React Guide for step-by-step tutorials and common patterns.

Installation

bash
npm install @editu/react

Components

Editu

All-in-one editor component with built-in bubble menu. This is the recommended way to get started.

tsx
import { Editu } from '@editu/react';
import '@editu/core/styles.css';

<Editu
  initialContent={{ type: 'doc', content: [] }}
  placeholder="Start writing..."
  editable={true}
  autofocus="end"
  showBubbleMenu={true}
  enableEmbed={true}
  className="my-editor"
  features={{ markdown: true }}
  onUpdate={({ editor }) => {}}
  onCreate={({ editor }) => {}}
  onFocus={({ editor }) => {}}
  onBlur={({ editor }) => {}}
/>

Props:

PropTypeDefaultDescription
initialContentJSONContent-Initial editor content (JSON)
initialMarkdownstring-Initial editor content (Markdown)
placeholderstring-Placeholder text
editablebooleantrueEditable state
autofocusboolean | 'start' | 'end' | 'all' | number-Auto focus behavior
featuresEdituFeatureOptions-Feature configuration
classNamestring-CSS class name
showToolbarbooleanfalseShow fixed toolbar above editor
toolbarContentReactNode-Custom toolbar content
showBubbleMenubooleantrueShow bubble menu on selection
enableEmbedboolean-Enable embed in link editor
flavorEdituMarkdownFlavor"gfm"Markdown output flavor
localeEdituLocale-Locale for translated UI strings
extensionsExtensions-Additional Tiptap extensions
transformDiagramsOnImportbooleantrueTransform diagram code blocks when importing markdown
markdownstring-Controlled markdown content
onMarkdownChange(markdown: string) => void-Callback when markdown changes
onUpdate({ editor }) => void-Update callback
onCreate({ editor }) => void-Create callback
onDestroy() => void-Destroy callback
onSelectionUpdate({ editor }) => void-Selection change callback
onFocus({ editor }) => void-Focus callback
onBlur({ editor }) => void-Blur callback
onError(error: EdituError) => void-Error callback

Hooks

useEdituEditor

This hook creates and manages a Editu editor instance.

tsx
import { useEdituEditor } from '@editu/react';

const editor = useEdituEditor(options?: EdituEditorOptions);

Returns: Editor | null

useEdituState

This hook forces a re-render on editor state changes.

tsx
import { useEdituState } from '@editu/react';

const updateCount = useEdituState(() => editor);

Returns: number (update count)

useEdituEditorState

This hook returns a EdituEditorState object that reactively tracks editor state (bold, italic, heading level, etc.).

tsx
import { useEdituEditorState } from '@editu/react';

const state = useEdituEditorState(() => editor);
// state.isBold, state.isItalic, state.headingLevel, etc.

Returns: EdituEditorState — reactive object with boolean flags for formatting state and current node info

useEdituAutoSave

This hook auto-saves editor content with debouncing.

tsx
import { useEdituAutoSave } from '@editu/react';

const result = useEdituAutoSave(
  () => editor,
  options?: EdituAutoSaveOptions
);

Returns:

PropertyTypeDescription
statusEdituSaveStatusCurrent save status
hasUnsavedChangesbooleanWhether unsaved changes exist
lastSavedDate | nullLast save timestamp
errorError | nullLast error
save() => Promise<void>Save content manually
restore() => Promise<JSONContent | null>Restore content manually

useEdituMarkdown

This hook provides two-way Markdown synchronization with debouncing.

tsx
import { useEdituMarkdown } from '@editu/react';

const result = useEdituMarkdown(
  () => editor,
  options?: EdituMarkdownSyncOptions
);

Options:

OptionTypeDefaultDescription
debounceMsnumber300Debounce delay in milliseconds
transformDiagramsbooleantrueTransform diagram code blocks when setting markdown

Returns:

PropertyTypeDescription
markdownstringCurrent Markdown content
setMarkdown(md: string) => voidUpdate editor from Markdown
isPendingbooleanWhether sync is pending

useEdituTheme

This hook accesses theme state within EdituThemeProvider.

tsx
import { useEdituTheme } from '@editu/react';

const { theme, resolvedTheme, systemTheme, setTheme } = useEdituTheme();

Returns:

PropertyTypeDescription
themeEdituThemeCurrent theme setting
resolvedThemeEdituResolvedThemeResolved theme
systemThemeEdituResolvedThemeSystem preference
setTheme(theme: EdituTheme) => voidSet theme function

useEdituContext

This hook accesses the editor from EdituProvider context.

tsx
import { useEdituContext } from '@editu/react';

const { editor } = useEdituContext();

useEdituCollaboration

This hook tracks real-time collaboration state with a Yjs provider.

tsx
import { useEdituCollaboration } from '@editu/react';

const {
  isConnected,
  isSynced,
  peerCount,
  error,
  connect,
  disconnect,
  updateUser,
} = useEdituCollaboration(
  () => wsProvider,
  { user: { name: 'Alice', color: '#ff0000' } }
);

Parameters:

ParameterTypeDescription
getProvider() => EdituYjsProvider | null | undefinedGetter function for the Yjs provider
optionsEdituCollaborationOptionsCollaboration options including user info

Returns: UseEdituCollaborationResult

PropertyTypeDescription
isConnectedbooleanWhether the editor is connected to the server
isSyncedbooleanWhether initial sync is complete
peerCountnumberNumber of connected peers
errorError | nullLast error
connect() => voidConnect to the server
disconnect() => voidDisconnect from the server
updateUser(user: EdituCollaborationUser) => voidUpdate user cursor info

useEdituComment

This hook manages document comments and annotations.

tsx
import { useEdituComment } from '@editu/react';

const {
  comments,
  activeCommentId,
  isLoading,
  error,
  addComment,
  removeComment,
  resolveComment,
  reopenComment,
  replyToComment,
  setActiveComment,
  loadComments,
  getCommentById,
} = useEdituComment(() => editor, { key: 'my-comments' });

Parameters:

ParameterTypeDescription
getEditor() => Editor | null | undefinedGetter function for the editor
optionsEdituCommentOptionsComment configuration options

Returns: UseEdituCommentResult

PropertyTypeDescription
commentsEdituComment[]All stored comments (newest first)
activeCommentIdstring | nullCurrently active comment ID
isLoadingbooleanWhether comments are loading
errorError | nullLast error
addComment(text: string, author?: string) => Promise<EdituComment | null>Add a comment to the selection
removeComment(commentId: string) => Promise<void>Remove a comment
resolveComment(commentId: string) => Promise<boolean>Resolve a comment
reopenComment(commentId: string) => Promise<boolean>Reopen a comment
replyToComment(commentId: string, text: string, author?: string) => Promise<EdituCommentReply | null>Reply to a comment
setActiveComment(commentId: string | null) => voidSet the active comment
loadComments() => Promise<EdituComment[]>Load comments from storage
getCommentById(commentId: string) => EdituComment | undefinedGet a comment by ID

useEdituVersionHistory

This hook manages document version history with save, restore, and delete operations.

tsx
import { useEdituVersionHistory } from '@editu/react';

const {
  snapshots,
  isLoading,
  error,
  saveVersion,
  restoreVersion,
  loadVersions,
  deleteVersion,
  clearVersions,
} = useEdituVersionHistory(() => editor, { maxVersions: 20 });

Parameters:

ParameterTypeDescription
getEditor() => Editor | null | undefinedGetter function for the editor
optionsEdituVersionHistoryOptionsVersion history configuration

Returns: UseEdituVersionHistoryResult

PropertyTypeDescription
snapshotsEdituVersionSnapshot[]All stored snapshots (newest first)
isLoadingbooleanWhether history is loading
errorError | nullLast error
saveVersion(description?: string, author?: string) => Promise<EdituVersionSnapshot | null>Save a new version
restoreVersion(versionId: string) => Promise<boolean>Restore a version
loadVersions() => Promise<EdituVersionSnapshot[]>Load versions from storage
deleteVersion(versionId: string) => Promise<void>Delete a version
clearVersions() => Promise<void>Delete all versions

Components

EdituFindReplace

Find & Replace panel component. This component renders when the Find & Replace extension is open.

tsx
import { EdituFindReplace } from '@editu/react';

<EdituFindReplace
  editor={editor}
  className="my-find-replace"
  onClose={() => console.log('Closed')}
/>

Props:

PropTypeDefaultDescription
editorEditor | null-Editor instance
classNamestring-CSS class name
localeEdituLocale-Locale for translated UI strings
onClose() => void-Called when the panel closes

EdituEditor

This component renders the editor content area.

tsx
import { EdituEditor } from '@editu/react';

<EdituEditor editor={editor} className="my-editor" />

Props:

PropTypeDefaultDescription
editorEditor | null-Editor instance
classNamestring-CSS class name

EdituBlockMenu

Block context menu that appears when clicking the drag handle.

tsx
import { EdituBlockMenu } from '@editu/react';

<EdituBlockMenu />
PropTypeDefaultDescription
actionsEdituBlockMenuAction[]edituDefaultBlockMenuActionsCustom menu actions
nodeTypesEdituNodeTypeOption[]edituDefaultNodeTypesNode types for "Turn into" submenu
classNamestring-CSS class name
localeEdituLocale-Locale for translated UI strings

EdituBubbleMenu

This component renders a floating formatting bubble menu.

tsx
import { EdituBubbleMenu } from '@editu/react';

<EdituBubbleMenu 
  editor={editor}
  className="my-bubble-menu"
/>

Props:

PropTypeDefaultDescription
editorEditor | null-Editor instance
classNamestring-CSS class name
childrenReactNode-Custom content
showDefaultMenubooleantrueShow default formatting menu when no children
pluginKeystring-Custom plugin key for the bubble menu
updateDelaynumber-Delay in ms before updating menu position
shouldShow(props) => boolean-Custom function to control menu visibility
enableEmbedboolean-Enable embed option in link editor

EdituBubbleMenuDefault

This component renders the default bubble menu with all formatting buttons.

tsx
import { EdituBubbleMenuDefault } from '@editu/react';

<EdituBubbleMenuDefault 
  editor={editor}
  enableEmbed={false}
/>

Props:

PropTypeDefaultDescription
editorEditor | null-Editor instance
enableEmbedbooleanfalseEnable embed in links

EdituBubbleMenuButton

This component renders an individual bubble menu button.

tsx
import { EdituBubbleMenuButton } from '@editu/react';

<EdituBubbleMenuButton
  icon="lucide:bold"
  isActive={editor.isActive('bold')}
  onClick={() => editor.chain().focus().toggleBold().run()}
/>

EdituBubbleMenuDivider

This component renders a bubble menu divider.

tsx
import { EdituBubbleMenuDivider } from '@editu/react';

<EdituBubbleMenuDivider />

EdituToolbar

This component renders a fixed toolbar.

tsx
import { EdituToolbar } from '@editu/react';

<EdituToolbar editor={editor} className="my-toolbar" />

Props:

PropTypeDefaultDescription
editorEditor | null-Editor instance (falls back to context)
classNamestring-CSS class name
showDefaultToolbarbooleantrueShow default toolbar content
localeEdituLocale-Locale for translated UI strings
childrenReactNode-Custom toolbar content

EdituToolbarDefault

This component renders the default toolbar content with grouped formatting buttons.

tsx
import { EdituToolbarDefault } from '@editu/react';

<EdituToolbarDefault editor={editor} actions={customActions} />

Props:

PropTypeDefaultDescription
editorEditor-Editor instance (required)
classNamestring-CSS class name
localeEdituLocale-Locale for translated UI strings
actionsEdituToolbarActionItem[]edituDefaultToolbarActionsCustom actions (supports dropdowns)

EdituToolbarDropdown

This component renders a dropdown toolbar button with a popover of nested actions.

tsx
import { EdituToolbarDropdown } from '@editu/react';

<EdituToolbarDropdown editor={editor} dropdown={headingDropdown} />

Props:

PropTypeDefaultDescription
editorEditor-Editor instance (required)
dropdownEdituToolbarDropdownAction-Dropdown action definition (required)
classNamestring-CSS class name

EdituToolbarOverflow

This component renders a "..." overflow button that shows hidden actions in a popover.

tsx
import { EdituToolbarOverflow } from '@editu/react';

<EdituToolbarOverflow editor={editor} actions={overflowActions} />

Props:

PropTypeDefaultDescription
editorEditor-Editor instance (required)
actionsEdituToolbarActionItem[]-Actions to show in overflow (required)
classNamestring-CSS class name
localeEdituLocale-Locale for translated UI strings

EdituToolbarButton

This component renders an individual toolbar button.

tsx
import { EdituToolbarButton } from '@editu/react';

<EdituToolbarButton
  onClick={() => editor.chain().focus().toggleBold().run()}
  isActive={editor.isActive("bold")}
  title="Bold (Cmd+B)"
>
  <EdituIcon name="bold" />
</EdituToolbarButton>

Props:

PropTypeDefaultDescription
onClick() => void-Click handler
isActivebooleanfalseActive state
disabledbooleanfalseDisabled state
childrenReactNode-Button content
titlestring-Tooltip text
classNamestring-CSS class name
actionstring-Action identifier

EdituToolbarDivider

This component renders a divider between toolbar button groups.

tsx
import { EdituToolbarDivider } from '@editu/react';

<EdituToolbarDivider />

EdituThemeProvider

This component provides theme context to its children.

tsx
import { EdituThemeProvider } from '@editu/react';

<EdituThemeProvider
  defaultTheme="system"
  storageKey="editu-theme"
  disableTransitionOnChange={false}
>
  {children}
</EdituThemeProvider>

Props:

PropTypeDefaultDescription
defaultThemeEdituTheme"system"Default theme
storageKeystring"editu-theme"Storage key
targetSelectorstring-Theme target
disableTransitionOnChangebooleanfalseDisable transitions
childrenReactNode-Children

EdituSaveIndicator

This component displays the save status.

tsx
import { EdituSaveIndicator } from '@editu/react';

<EdituSaveIndicator status={status} lastSaved={lastSaved} />

Props:

PropTypeDescription
statusEdituSaveStatusSave status
lastSavedDate | nullLast save time
classNamestringCSS class name

EdituPortal

This component renders its children in a portal.

tsx
import { EdituPortal } from '@editu/react';

<EdituPortal container={document.body}>{children}</EdituPortal>

Props:

PropTypeDescription
childrenReactNodeContent to render
containerHTMLElementPortal target

EdituColorPicker

This component renders a color selection interface.

tsx
import { EdituColorPicker } from '@editu/react';

<EdituColorPicker
  colors={colors}
  value={currentColor}
  onChange={setColor}
  recentColors={recentColors}
/>

EdituIconProvider

This component provides custom icons for Editu components.

tsx
import { EdituIconProvider } from '@editu/react';
import type { CustomIconMap } from '@editu/core';

const icons: CustomIconMap = {
  bold: 'mdi:format-bold',
  italic: 'mdi:format-italic',
};

<EdituIconProvider icons={icons}>
  <Editu />
</EdituIconProvider>

Props:

PropTypeDescription
iconsCustomIconMapMap of icon names to Iconify icon IDs
childrenReactNodeChildren

EdituSlashMenu

This component renders the slash command menu.

tsx
import { EdituSlashMenu } from '@editu/react';

<EdituSlashMenu
  items={items}
  command={handleCommand}
  className="my-menu"
/>

Utilities

createEdituSlashMenuRenderer

This function creates a slash menu renderer for the SlashCommand extension.

tsx
import { createEdituSlashMenuRenderer } from '@editu/react';

const suggestion = createEdituSlashMenuRenderer();

const editor = useEdituEditor({
  features: {
    slashCommand: {
      suggestion,
    },
  },
});

Importing from @editu/core and @tiptap/core

Framework packages do not re-export from @editu/core. You must import directly:

tsx
// Framework-specific components and hooks
import { 
  Editu, 
  EdituEditor, 
  EdituBubbleMenu, 
  EdituThemeProvider,
  useEdituEditor,
  useEdituMarkdown,
  useEdituAutoSave,
} from '@editu/react';

// Editu types and utilities from @editu/core
import { getEdituEditorState, EDITU_TEXT_COLORS } from '@editu/core';
import type { EdituEditorOptions, EdituSaveStatus } from '@editu/core';

// Tiptap types from @tiptap/core
import { Editor } from '@tiptap/core';
import type { JSONContent } from '@tiptap/core';

Released under the MIT License.