Introduction
@erag/text-editor-react is a dependency-free rich text editor component for React 18 and React 19. The package uses React function components, hooks, and native browser editing APIs instead of wrapping another editor framework. React and React DOM are its only peer dependencies.
What it includes
- Controlled HTML content through
valueplusonChange, or uncontrolled content throughdefaultValue. - Container-responsive menubar and toolbar controls for grouped alignment, line height, styled lists, checklists, links, media, tables, code, preview, and fullscreen.
- Optional mentions, merge tags, and consumer-provided templates.
- Consumer-controlled image upload and deletion callbacks, URL uploads with Fetch, paste uploads, alignment, and four-corner resizing.
- Source editing, sanitized preview, print, find and replace, special characters, emoji, and date/time insertion.
- Disabled and read-only modes, keyboard shortcuts, ARIA labels, selection preservation, and typed callback props.
- Automatic light/dark themes from the operating system, with explicit
html.darkanddata-themeoverrides. - ESM output, generated TypeScript declarations, and package-scoped
erag-CSS.
How content flows
The editor is a controlled React component:
import { useState } from 'react';
import { Editor } from '@erag/text-editor-react';
import '@erag/text-editor-react/style.css';
export default function App() {
const [content, setContent] = useState('<p>Hello</p>');
return <Editor value={content} onChange={setContent} />;
}Typing or running an editor action updates the generated HTML. The component calls onChange only when that HTML changes. A new external value updates the canvas without publishing the same value back in a loop.
Defaults and explicit configuration
Omitting init enables the full standard editor. Passing a partial object keeps defaults for omitted properties. Explicit toolbar and menubar choices are exact, and explicit plugin arrays filter plugin-backed controls instead of silently restoring excluded features.
import type { EditorInit } from '@erag/text-editor-react';
const commentEditor: EditorInit = {
height: 240,
menubar: false,
statusbar: false,
plugins: ['history', 'formatting', 'lists', 'link'],
toolbar: 'bold italic | bullist numlist checklist | link',
};Browser API limitations
Native contenteditable and editing commands have small browser differences. Clipboard operations require a user gesture and can be blocked by permissions. Fullscreen uses the Fullscreen API with a CSS fallback. Image uploads require a handler or URL supplied by your application.
The component is SSR-safe during initialization, but browser-only utilities cannot sanitize on the server. Always sanitize untrusted HTML again at your backend boundary.
Feature documentation map
| Package area | Documentation |
|---|---|
| Controlled HTML, dynamic config, disabled/read-only, methods | Basic and dynamic usage, API reference |
| Menubar, toolbar overflow, history, clipboard, shortcuts, status, resize, print | Menubar customization, Workflow and responsive UI |
| Headings, fonts, colors, line height, case, list styles, checklists, indentation | Text formatting, Lists, checklists, and indentation |
| Links, anchors, video, audio, iframe, and tables | Links and anchors, Media and embeds, Table editor |
| Mentions, merge tags, and consumer-defined templates | Mentions, Merge tags, Templates |
| File/URL/paste image uploads, alignment, resize, and deletion | Image uploads |
| Emoji, symbols, horizontal rules, and date-time | Special characters and emoji, Horizontal rules and date-time |
| Source HTML, preview, fullscreen, find, and replace | Code, preview, and fullscreen, Find and replace |
| Sanitization, scoped CSS, themes, public types, and Laravel integration | Security, CSS customization, TypeScript types, Laravel and Inertia |
Next steps
Start with installation, continue to basic usage, and review the editor workflow and responsive UI. Use the configuration reference for the complete option list.