
Security News
pnpm 11.5 Adds Support for Recognizing npm Staged Publishes
pnpm 11.5 now recognizes npm staged publish approvals in release metadata, preventing those releases from being mistaken for lower-trust package publishes.
@editora/react
Advanced tools
React components for Editora - Best Free Premium Rich Text Editor. Free React WYSIWYG editor with enterprise features, 30+ free plugins, and accessibility support.
[!IMPORTANT] Live Website: https://editora-ecosystem.netlify.app/
Storybook: https://editora-ecosystem-storybook.netlify.app/
React components for Editora Rich Text Editor with hooks-based API
React components for Editora Rich Text Editor - A modern, extensible WYSIWYG editor.
npm install @editora/react @editora/core @editora/plugins @editora/themes
@editora/react, @editora/core, react, react-dom@editora/plugins (toolbar/plugin features), @editora/themes (default/dark/acme CSS)@editora/plugins, also import @editora/plugins/styles.css for plugin UI surfaces (table toolbar, dialogs, pickers).@editora/plugins (full), @editora/plugins/lite (common), @editora/plugins/enterprise (advanced), or per-plugin subpaths like @editora/plugins/bold.Minimal install:
npm install @editora/react @editora/core react react-dom
Full-featured install:
npm install @editora/react @editora/core @editora/plugins @editora/themes react react-dom
The React package provides ready-to-use React components for building rich text editing experiences. It includes hooks, components, and utilities specifically designed for React applications.
useEditor, useEditorState)import { EditoraEditor } from '@editora/react';
import { BoldPlugin, ItalicPlugin } from '@editora/plugins';
import "@editora/plugins/styles.css";
import "@editora/themes/themes/default.css";
function App() {
const [content, setContent] = useState('<p>Start writing...</p>');
return (
<EditoraEditor
value={content}
onChange={setContent}
plugins={[
BoldPlugin(),
ItalicPlugin()
]}
placeholder="Type something..."
/>
);
}
import { EditoraEditor } from '@editora/react';
import {
BoldPlugin,
ItalicPlugin,
UnderlinePlugin,
HeadingPlugin,
ParagraphPlugin,
ListPlugin,
LinkPlugin,
MediaManagerPlugin,
TablePlugin,
CodeSamplePlugin,
HistoryPlugin
} from '@editora/plugins';
import "@editora/plugins/styles.css";
import "@editora/themes/themes/default.css";
function FullEditor() {
const [content, setContent] = useState('');
const plugins = [
BoldPlugin(),
ItalicPlugin(),
UnderlinePlugin(),
HeadingPlugin(),
ListPlugin(),
MediaManagerPlugin()
];
return (
<div className="editor-container">
<EditoraEditor
value={content}
onChange={setContent}
plugins={plugins}
placeholder="Start writing your document..."
autofocus
/>
</div>
);
}
<EditoraEditor
plugins={[BoldPlugin(), ItalicPlugin()]}
accessibility={{
enableARIA: true,
keyboardNavigation: true,
checker: true, // auto-enables a11y checker if factory/plugin is available
}}
performance={{
debounceInputMs: 120,
viewportOnlyScan: true,
}}
/>
// Default: fixed layout + scrollable content area
<EditoraEditor plugins={[BoldPlugin()]} />
// Optional: grow editor content height with content
<EditoraEditor
plugins={[BoldPlugin()]}
content={{
autoHeight: true,
minHeight: 220,
maxHeight: 700, // optional cap; keeps scrolling after cap
}}
/>
import { EditoraEditor, Toolbar, ToolbarButton } from '@editora/react';
import { useEditor } from '@editora/react/hooks';
function EditorWithCustomToolbar() {
const { editor, html, setHtml } = useEditor({
plugins: [/* your plugins */],
content: '<p>Hello</p>'
});
return (
<div>
<Toolbar editor={editor}>
<ToolbarButton command="bold" icon="bold" />
<ToolbarButton command="italic" icon="italic" />
<ToolbarButton command="underline" icon="underline" />
<div className="separator" />
<ToolbarButton command="heading" level={1} icon="h1" />
<ToolbarButton command="heading" level={2} icon="h2" />
</Toolbar>
<div
ref={(el) => el && editor.mount(el)}
className="editor-content"
/>
</div>
);
}
<EditoraEditor />Main editor component with built-in toolbar.
Props:
interface EditoraEditorProps {
// Content
value?: string;
defaultValue?: string;
onChange?: (html: string) => void;
// Plugins
plugins?: Plugin[];
// Configuration
placeholder?: string;
readonly?: boolean;
autofocus?: boolean;
maxLength?: number;
// Styling
className?: string;
style?: React.CSSProperties;
// Toolbar
showToolbar?: boolean;
toolbarItems?: ToolbarItem[];
toolbarPosition?: 'top' | 'bottom' | 'floating';
// Events
onFocus?: () => void;
onBlur?: () => void;
onReady?: (editor: Editor) => void;
}
<Toolbar />Customizable toolbar component.
Props:
interface ToolbarProps {
editor: Editor;
items?: ToolbarItem[];
position?: 'top' | 'bottom' | 'floating';
className?: string;
}
<ToolbarButton />Individual toolbar button.
Props:
interface ToolbarButtonProps {
command: string;
icon?: React.ReactNode;
label?: string;
active?: boolean;
disabled?: boolean;
onClick?: () => void;
}
useEditor(config)Main hook for editor management.
const { editor, html, json, setHtml, setJson } = useEditor({
plugins: [...],
content: '<p>Initial content</p>',
onChange: (html) => console.log(html)
});
Returns:
editor: Editor instancehtml: Current HTML contentjson: Current JSON contentsetHtml: Function to set HTML contentsetJson: Function to set JSON contentuseEditorState(editor)Hook for accessing editor state.
const {
isFocused,
isEmpty,
canUndo,
canRedo
} = useEditorState(editor);
useEditorCommands(editor)Hook for editor commands.
const {
bold,
italic,
undo,
redo,
insertText,
insertImage
} = useEditorCommands(editor);
import "@editora/themes/themes/default.css";
import "@editora/themes/themes/dark.css";
import "@editora/themes/themes/acme.css";
<div data-theme="dark">
<EditoraEditor />
</div>
:is([data-theme="custom-brand"], .editora-theme-custom-brand) {
--rte-color-primary: #2563eb;
--rte-color-primary-hover: #1d4ed8;
--rte-color-text-primary: #0f172a;
--rte-color-bg-primary: #ffffff;
--rte-color-border: #cbd5e1;
}
[data-theme="dark"] {
--rte-color-primary: #58a6ff;
}
Apply it in React with a wrapper:
<div data-theme="custom-brand">
<EditoraEditor />
</div>
import { BoldPlugin } from '@editora/plugins';
const boldPlugin = BoldPlugin({
keyboard: 'Mod-b',
icon: <BoldIcon />
});
import { MediaManagerPlugin } from '@editora/plugins';
const imagePlugin = MediaManagerPlugin({
upload: async (file) => {
const url = await uploadToServer(file);
return url;
},
validate: (file) => {
return file.size < 5 * 1024 * 1024; // 5MB limit
},
resize: true,
maxWidth: 1200
});
import { LinkPlugin } from '@editora/plugins';
const linkPlugin = LinkPlugin({
openOnClick: false,
validate: (url) => {
return url.startsWith('http') || url.startsWith('https');
},
onLinkClick: (url) => {
window.open(url, '_blank', 'noopener,noreferrer');
}
});
function BlogPostForm() {
const [formData, setFormData] = useState({
title: '',
content: ''
});
const handleSubmit = async (e) => {
e.preventDefault();
await fetch('/api/posts', {
method: 'POST',
body: JSON.stringify(formData)
});
};
return (
<form onSubmit={handleSubmit}>
<input
type="text"
value={formData.title}
onChange={(e) => setFormData({ ...formData, title: e.target.value })}
placeholder="Post title"
/>
<EditoraEditor
value={formData.content}
onChange={(content) => setFormData({ ...formData, content })}
plugins={[/* ... */]}
/>
<button type="submit">Publish</button>
</form>
);
}
function DocumentEditor() {
const [content, setContent] = useState('');
const [isSaving, setIsSaving] = useState(false);
const handleSave = async () => {
setIsSaving(true);
try {
await fetch('/api/save', {
method: 'POST',
body: JSON.stringify({ content })
});
alert('Saved successfully!');
} catch (error) {
alert('Failed to save');
} finally {
setIsSaving(false);
}
};
return (
<div>
<div className="toolbar-actions">
<button onClick={handleSave} disabled={isSaving}>
{isSaving ? 'Saving...' : 'Save'}
</button>
</div>
<EditoraEditor
value={content}
onChange={setContent}
plugins={[/* ... */]}
/>
</div>
);
}
function ArticlePreview({ html }) {
return (
<EditoraEditor
value={html}
readonly
showToolbar={false}
className="article-preview"
/>
);
}
The package is written in TypeScript and includes comprehensive type definitions.
import type {
Editor,
Plugin,
ToolbarItem,
EditorConfig
} from '@editora/react';
const config: EditorConfig = {
plugins: [],
onChange: (html: string) => {
// TypeScript knows html is a string
}
};
The editor automatically adapts to different screen sizes:
<EditoraEditor
// Toolbar collapses to hamburger menu on mobile
toolbarBreakpoint={768}
// Custom mobile configuration
mobileConfig={{
toolbarPosition: 'bottom',
compactMode: true
}}
/>
The editor is fully accessible and follows WCAG 2.1 guidelines:
MIT © Ajay Kumar
FAQs
React components for Editora - Best Free Premium Rich Text Editor. Free React WYSIWYG editor with enterprise features, 30+ free plugins, and accessibility support.
The npm package @editora/react receives a total of 30 weekly downloads. As such, @editora/react popularity was classified as not popular.
We found that @editora/react demonstrated a healthy version release cadence and project activity because the last version was released less than a year ago. It has 1 open source maintainer collaborating on the project.
Did you know?

Socket for GitHub automatically highlights issues in each pull request and monitors the health of all your open source dependencies. Discover the contents of your packages and block harmful activity before you install or update your dependencies.

Security News
pnpm 11.5 now recognizes npm staged publish approvals in release metadata, preventing those releases from being mistaken for lower-trust package publishes.

Security News
Federal audit finds NIST lacked a plan to clear the NVD backlog, wasted funds on duplicate work, and delayed use of CISA data.

Research
/Security News
A mini Shai-Hulud campaign compromised Red Hat Cloud Services npm packages to steal developer and CI/CD secrets during installation.