@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
npm install @editu/reactComponents
Editu
All-in-one editor component with built-in bubble menu. This is the recommended way to get started.
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:
| Prop | Type | Default | Description |
|---|---|---|---|
initialContent | JSONContent | - | Initial editor content (JSON) |
initialMarkdown | string | - | Initial editor content (Markdown) |
placeholder | string | - | Placeholder text |
editable | boolean | true | Editable state |
autofocus | boolean | 'start' | 'end' | 'all' | number | - | Auto focus behavior |
features | EdituFeatureOptions | - | Feature configuration |
className | string | - | CSS class name |
showToolbar | boolean | false | Show fixed toolbar above editor |
toolbarContent | ReactNode | - | Custom toolbar content |
showBubbleMenu | boolean | true | Show bubble menu on selection |
enableEmbed | boolean | - | Enable embed in link editor |
flavor | EdituMarkdownFlavor | "gfm" | Markdown output flavor |
locale | EdituLocale | - | Locale for translated UI strings |
extensions | Extensions | - | Additional Tiptap extensions |
transformDiagramsOnImport | boolean | true | Transform diagram code blocks when importing markdown |
markdown | string | - | 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.
import { useEdituEditor } from '@editu/react';
const editor = useEdituEditor(options?: EdituEditorOptions);Returns: Editor | null
useEdituState
This hook forces a re-render on editor state changes.
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.).
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.
import { useEdituAutoSave } from '@editu/react';
const result = useEdituAutoSave(
() => editor,
options?: EdituAutoSaveOptions
);Returns:
| Property | Type | Description |
|---|---|---|
status | EdituSaveStatus | Current save status |
hasUnsavedChanges | boolean | Whether unsaved changes exist |
lastSaved | Date | null | Last save timestamp |
error | Error | null | Last error |
save | () => Promise<void> | Save content manually |
restore | () => Promise<JSONContent | null> | Restore content manually |
useEdituMarkdown
This hook provides two-way Markdown synchronization with debouncing.
import { useEdituMarkdown } from '@editu/react';
const result = useEdituMarkdown(
() => editor,
options?: EdituMarkdownSyncOptions
);Options:
| Option | Type | Default | Description |
|---|---|---|---|
debounceMs | number | 300 | Debounce delay in milliseconds |
transformDiagrams | boolean | true | Transform diagram code blocks when setting markdown |
Returns:
| Property | Type | Description |
|---|---|---|
markdown | string | Current Markdown content |
setMarkdown | (md: string) => void | Update editor from Markdown |
isPending | boolean | Whether sync is pending |
useEdituTheme
This hook accesses theme state within EdituThemeProvider.
import { useEdituTheme } from '@editu/react';
const { theme, resolvedTheme, systemTheme, setTheme } = useEdituTheme();Returns:
| Property | Type | Description |
|---|---|---|
theme | EdituTheme | Current theme setting |
resolvedTheme | EdituResolvedTheme | Resolved theme |
systemTheme | EdituResolvedTheme | System preference |
setTheme | (theme: EdituTheme) => void | Set theme function |
useEdituContext
This hook accesses the editor from EdituProvider context.
import { useEdituContext } from '@editu/react';
const { editor } = useEdituContext();useEdituCollaboration
This hook tracks real-time collaboration state with a Yjs provider.
import { useEdituCollaboration } from '@editu/react';
const {
isConnected,
isSynced,
peerCount,
error,
connect,
disconnect,
updateUser,
} = useEdituCollaboration(
() => wsProvider,
{ user: { name: 'Alice', color: '#ff0000' } }
);Parameters:
| Parameter | Type | Description |
|---|---|---|
getProvider | () => EdituYjsProvider | null | undefined | Getter function for the Yjs provider |
options | EdituCollaborationOptions | Collaboration options including user info |
Returns: UseEdituCollaborationResult
| Property | Type | Description |
|---|---|---|
isConnected | boolean | Whether the editor is connected to the server |
isSynced | boolean | Whether initial sync is complete |
peerCount | number | Number of connected peers |
error | Error | null | Last error |
connect | () => void | Connect to the server |
disconnect | () => void | Disconnect from the server |
updateUser | (user: EdituCollaborationUser) => void | Update user cursor info |
useEdituComment
This hook manages document comments and annotations.
import { useEdituComment } from '@editu/react';
const {
comments,
activeCommentId,
isLoading,
error,
addComment,
removeComment,
resolveComment,
reopenComment,
replyToComment,
setActiveComment,
loadComments,
getCommentById,
} = useEdituComment(() => editor, { key: 'my-comments' });Parameters:
| Parameter | Type | Description |
|---|---|---|
getEditor | () => Editor | null | undefined | Getter function for the editor |
options | EdituCommentOptions | Comment configuration options |
Returns: UseEdituCommentResult
| Property | Type | Description |
|---|---|---|
comments | EdituComment[] | All stored comments (newest first) |
activeCommentId | string | null | Currently active comment ID |
isLoading | boolean | Whether comments are loading |
error | Error | null | Last 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) => void | Set the active comment |
loadComments | () => Promise<EdituComment[]> | Load comments from storage |
getCommentById | (commentId: string) => EdituComment | undefined | Get a comment by ID |
useEdituVersionHistory
This hook manages document version history with save, restore, and delete operations.
import { useEdituVersionHistory } from '@editu/react';
const {
snapshots,
isLoading,
error,
saveVersion,
restoreVersion,
loadVersions,
deleteVersion,
clearVersions,
} = useEdituVersionHistory(() => editor, { maxVersions: 20 });Parameters:
| Parameter | Type | Description |
|---|---|---|
getEditor | () => Editor | null | undefined | Getter function for the editor |
options | EdituVersionHistoryOptions | Version history configuration |
Returns: UseEdituVersionHistoryResult
| Property | Type | Description |
|---|---|---|
snapshots | EdituVersionSnapshot[] | All stored snapshots (newest first) |
isLoading | boolean | Whether history is loading |
error | Error | null | Last 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.
import { EdituFindReplace } from '@editu/react';
<EdituFindReplace
editor={editor}
className="my-find-replace"
onClose={() => console.log('Closed')}
/>Props:
| Prop | Type | Default | Description |
|---|---|---|---|
editor | Editor | null | - | Editor instance |
className | string | - | CSS class name |
locale | EdituLocale | - | Locale for translated UI strings |
onClose | () => void | - | Called when the panel closes |
EdituEditor
This component renders the editor content area.
import { EdituEditor } from '@editu/react';
<EdituEditor editor={editor} className="my-editor" />Props:
| Prop | Type | Default | Description |
|---|---|---|---|
editor | Editor | null | - | Editor instance |
className | string | - | CSS class name |
EdituBlockMenu
Block context menu that appears when clicking the drag handle.
import { EdituBlockMenu } from '@editu/react';
<EdituBlockMenu />| Prop | Type | Default | Description |
|---|---|---|---|
actions | EdituBlockMenuAction[] | edituDefaultBlockMenuActions | Custom menu actions |
nodeTypes | EdituNodeTypeOption[] | edituDefaultNodeTypes | Node types for "Turn into" submenu |
className | string | - | CSS class name |
locale | EdituLocale | - | Locale for translated UI strings |
EdituBubbleMenu
This component renders a floating formatting bubble menu.
import { EdituBubbleMenu } from '@editu/react';
<EdituBubbleMenu
editor={editor}
className="my-bubble-menu"
/>Props:
| Prop | Type | Default | Description |
|---|---|---|---|
editor | Editor | null | - | Editor instance |
className | string | - | CSS class name |
children | ReactNode | - | Custom content |
showDefaultMenu | boolean | true | Show default formatting menu when no children |
pluginKey | string | - | Custom plugin key for the bubble menu |
updateDelay | number | - | Delay in ms before updating menu position |
shouldShow | (props) => boolean | - | Custom function to control menu visibility |
enableEmbed | boolean | - | Enable embed option in link editor |
EdituBubbleMenuDefault
This component renders the default bubble menu with all formatting buttons.
import { EdituBubbleMenuDefault } from '@editu/react';
<EdituBubbleMenuDefault
editor={editor}
enableEmbed={false}
/>Props:
| Prop | Type | Default | Description |
|---|---|---|---|
editor | Editor | null | - | Editor instance |
enableEmbed | boolean | false | Enable embed in links |
EdituBubbleMenuButton
This component renders an individual bubble menu button.
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.
import { EdituBubbleMenuDivider } from '@editu/react';
<EdituBubbleMenuDivider />EdituToolbar
This component renders a fixed toolbar.
import { EdituToolbar } from '@editu/react';
<EdituToolbar editor={editor} className="my-toolbar" />Props:
| Prop | Type | Default | Description |
|---|---|---|---|
editor | Editor | null | - | Editor instance (falls back to context) |
className | string | - | CSS class name |
showDefaultToolbar | boolean | true | Show default toolbar content |
locale | EdituLocale | - | Locale for translated UI strings |
children | ReactNode | - | Custom toolbar content |
EdituToolbarDefault
This component renders the default toolbar content with grouped formatting buttons.
import { EdituToolbarDefault } from '@editu/react';
<EdituToolbarDefault editor={editor} actions={customActions} />Props:
| Prop | Type | Default | Description |
|---|---|---|---|
editor | Editor | - | Editor instance (required) |
className | string | - | CSS class name |
locale | EdituLocale | - | Locale for translated UI strings |
actions | EdituToolbarActionItem[] | edituDefaultToolbarActions | Custom actions (supports dropdowns) |
EdituToolbarDropdown
This component renders a dropdown toolbar button with a popover of nested actions.
import { EdituToolbarDropdown } from '@editu/react';
<EdituToolbarDropdown editor={editor} dropdown={headingDropdown} />Props:
| Prop | Type | Default | Description |
|---|---|---|---|
editor | Editor | - | Editor instance (required) |
dropdown | EdituToolbarDropdownAction | - | Dropdown action definition (required) |
className | string | - | CSS class name |
EdituToolbarOverflow
This component renders a "..." overflow button that shows hidden actions in a popover.
import { EdituToolbarOverflow } from '@editu/react';
<EdituToolbarOverflow editor={editor} actions={overflowActions} />Props:
| Prop | Type | Default | Description |
|---|---|---|---|
editor | Editor | - | Editor instance (required) |
actions | EdituToolbarActionItem[] | - | Actions to show in overflow (required) |
className | string | - | CSS class name |
locale | EdituLocale | - | Locale for translated UI strings |
EdituToolbarButton
This component renders an individual toolbar button.
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:
| Prop | Type | Default | Description |
|---|---|---|---|
onClick | () => void | - | Click handler |
isActive | boolean | false | Active state |
disabled | boolean | false | Disabled state |
children | ReactNode | - | Button content |
title | string | - | Tooltip text |
className | string | - | CSS class name |
action | string | - | Action identifier |
EdituToolbarDivider
This component renders a divider between toolbar button groups.
import { EdituToolbarDivider } from '@editu/react';
<EdituToolbarDivider />EdituThemeProvider
This component provides theme context to its children.
import { EdituThemeProvider } from '@editu/react';
<EdituThemeProvider
defaultTheme="system"
storageKey="editu-theme"
disableTransitionOnChange={false}
>
{children}
</EdituThemeProvider>Props:
| Prop | Type | Default | Description |
|---|---|---|---|
defaultTheme | EdituTheme | "system" | Default theme |
storageKey | string | "editu-theme" | Storage key |
targetSelector | string | - | Theme target |
disableTransitionOnChange | boolean | false | Disable transitions |
children | ReactNode | - | Children |
EdituSaveIndicator
This component displays the save status.
import { EdituSaveIndicator } from '@editu/react';
<EdituSaveIndicator status={status} lastSaved={lastSaved} />Props:
| Prop | Type | Description |
|---|---|---|
status | EdituSaveStatus | Save status |
lastSaved | Date | null | Last save time |
className | string | CSS class name |
EdituPortal
This component renders its children in a portal.
import { EdituPortal } from '@editu/react';
<EdituPortal container={document.body}>{children}</EdituPortal>Props:
| Prop | Type | Description |
|---|---|---|
children | ReactNode | Content to render |
container | HTMLElement | Portal target |
EdituColorPicker
This component renders a color selection interface.
import { EdituColorPicker } from '@editu/react';
<EdituColorPicker
colors={colors}
value={currentColor}
onChange={setColor}
recentColors={recentColors}
/>EdituIconProvider
This component provides custom icons for Editu components.
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:
| Prop | Type | Description |
|---|---|---|
icons | CustomIconMap | Map of icon names to Iconify icon IDs |
children | ReactNode | Children |
EdituSlashMenu
This component renders the slash command menu.
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.
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:
// 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';