richblocks
v2.2.2
Published
A powerful React rich text editor with AI generation, internationalization support, markup conversion, and customizable theming
Maintainers
Readme
RichBlocks
A modern, fully customizable WYSIWYG Markdown editor for React with AI-powered text generation.
Features
- ✏️ WYSIWYG Editing — Write visually, export Markdown or HTML
- 🤖 AI Text Generation — Built-in support for OpenAI, Anthropic, Groq, Google Gemini, and Mistral
- 💻 Code Blocks — Syntax highlighting with copy button
- 🔗 Smart Links — Auto-fetch previews with title and favicon
- 🖼️ Image Upload — Custom upload handlers
- 🌐 i18n — English, Portuguese, and French
- 🎨 Theming — 8 AI themes + dark mode support
- 📱 Responsive — Mobile-first design
- ⚡ Performance — Lazy loading and optimization utilities
- 🔄 Migration — Import from Quill, WordPress Gutenberg, and legacy formats
- 📦 TypeScript — Fully typed API
Installation
npm install richblocksQuick Start
import { RichEditor } from 'richblocks';
function App() {
return (
<RichEditor
onChange={(data: { markdown: string; html: string }) => {
console.log(data.markdown);
console.log(data.html);
}}
placeholder="Start writing..."
/>
);
}Configuration with Provider
import { RichBlocksProvider, RichEditor } from 'richblocks';
function App() {
return (
<RichBlocksProvider config={{
themeColor: '#3b82f6',
darkMode: false,
language: 'en',
toolbar: {
show: true,
items: ['bold', 'italic', 'h1', 'h2', 'link', 'image', 'code', 'ai']
},
editor: {
minHeight: '200px',
maxHeight: '600px'
},
codeBlock: {
showCopyButton: true,
showLanguageLabel: true,
theme: 'dark'
},
ai: {
enabled: true,
theme: 'gradient',
twoStepMode: false,
defaultModel: 'gemini-2.0-flash',
temperature: 0.7,
maxTokens: 2048,
providers: {
google: { apiKey: 'your-api-key' }
}
}
}}>
<RichEditor />
</RichBlocksProvider>
);
}Toolbar Items
toolbar: {
items: [
'bold', 'italic', 'underline', 'strikethrough',
'h1', 'h2', 'h3', 'paragraph',
'ul', 'ol',
'quote', 'code', 'link', 'image',
'alignLeft', 'alignCenter', 'alignRight',
'undo', 'redo',
'ai'
]
}AI Text Generation
Supported Providers
| Provider | Models |
|----------|--------|
| OpenAI | gpt-4o, gpt-4o-mini, gpt-4-turbo |
| Anthropic | claude-3-5-sonnet, claude-3-opus |
| Groq | llama-3.1-70b-versatile, mixtral-8x7b |
| Google | gemini-2.0-flash, gemini-1.5-pro |
| Mistral | mistral-large-latest |
AI Themes
8 built-in themes: default, gradient, liquid-glass, minimal, neon, sunset, ocean, forest, rose-gold
ai: {
theme: 'liquid-glass',
twoStepMode: true
}Programmatic AI Service
import { createAIService } from 'richblocks';
const ai = createAIService({
providers: {
openai: { apiKey: 'sk-...' }
}
});
await ai.generateStream('Write a poem', {
model: 'gpt-4o-mini',
onChunk: (chunk: { content: string }) => console.log(chunk.content),
onComplete: (fullText: string) => console.log('Done:', fullText)
});Rendering Markdown
import { RichBlocksProvider, useRichBlocks } from 'richblocks';
function Preview({ content }: { content: string }) {
const { format, toHtml } = useRichBlocks();
// As React component with styles (returns JSX)
return <div>{format(content)}</div>;
// With dark mode background included
// return <div>{format(content, { includeBackground: true })}</div>;
// Or as HTML string
// const html = toHtml(content);
}
// Must be wrapped in RichBlocksProvider to use useRichBlocks
function App() {
return (
<RichBlocksProvider config={{ darkMode: true }}>
<Preview content="# Hello **World**" />
</RichBlocksProvider>
);
}Image Upload
<RichBlocksProvider config={{
onImageUpload: async (file: File) => {
const formData = new FormData();
formData.append('file', file);
const res = await fetch('/api/upload', { method: 'POST', body: formData });
const { url } = await res.json();
return url;
}
}}>
<RichEditor />
</RichBlocksProvider>Migration from Other Editors
import { normalizeContent, normalizeMarkdown, normalizeHtml, deltaToHtml, gutenbergToHtml } from 'richblocks';
// Auto-detect format and normalize
const markdown = normalizeContent(legacyContent, { format: 'auto' });
// Normalize legacy markdown (GFM, Obsidian, WordPress shortcodes)
const cleanMarkdown = normalizeMarkdown(legacyMarkdown);
// Clean HTML from TinyMCE, CKEditor, Quill, Draft.js
const cleanHtml = normalizeHtml(dirtyHtml);
// Convert Quill Delta to HTML
const html = deltaToHtml(quillDelta);
// Convert WordPress Gutenberg blocks to HTML
const html = gutenbergToHtml(gutenbergBlocks);Performance Optimization
Lazy Loading
import { LazyRender, preloadOnHover, preloadWhenIdle, createLazyComponent, SuspenseWrapper } from 'richblocks';
// Render only when visible in viewport
<LazyRender rootMargin="100px" threshold={0.1}>
<RichEditor />
</LazyRender>
// Preload on hover
<button onMouseEnter={preloadOnHover(() => import('richblocks'))}>
Open Editor
</button>
// Preload when browser is idle
preloadWhenIdle(() => import('richblocks'));
// Create lazy component
const LazyEditor = createLazyComponent(
() => import('richblocks').then(m => ({ default: m.RichEditor }))
);
// Use with SuspenseWrapper
<SuspenseWrapper fallback={<div>Loading...</div>}>
<LazyEditor />
</SuspenseWrapper>Utilities
import { debounce, throttle, rafThrottle } from 'richblocks';
// Debounce - wait until pause in calls
const debouncedSave = debounce((content: string) => save(content), 500);
// Throttle - max calls per interval
const throttledUpdate = throttle(() => update(), 100);
// RAF Throttle - sync with animation frames
const rafUpdate = rafThrottle(() => updateAnimation());Editor Props
| Prop | Type | Description |
|------|------|-------------|
| onChange | (data: { markdown: string; html: string }) => void | Content change callback |
| initialValue | string | Initial Markdown content |
| placeholder | string | Placeholder text |
| maxLength | number \| null | Character limit |
| language | 'en' \| 'pt' \| 'fr' | UI language |
| themeColor | string | Theme color |
| darkMode | boolean | Enable dark mode |
| onImageUpload | (file: File) => Promise<string> | Image upload handler |
| className | string | Container class |
| toolbar | object | Toolbar configuration |
| editor | object | Editor configuration |
| codeBlock | object | Code block configuration |
| styles | object | Custom styles |
Supported Markdown
| Syntax | Output |
|--------|--------|
| # H1 | Heading 1 |
| ## H2 | Heading 2 |
| ### H3 | Heading 3 |
| **bold** | bold |
| *italic* | italic |
| __underline__ | underline |
| ~~strike~~ | ~~strike~~ |
| > quote | Blockquote |
| `code` | Inline code |
| ```js | Code block |
| [text](url) | Link |
|  | Image |
| - item | Bullet list |
| 1. item | Numbered list |
TypeScript
import type {
RichBlocksConfig,
RichEditorProps,
ToolbarItem,
AIConfigWithTheme,
AIConfig,
AIModel,
AIThemeTemplate,
LegacyFormat,
LazyComponentOptions
} from 'richblocks';
import type { Language } from 'richblocks';Browser Support
Chrome, Firefox, Safari, Edge (latest versions)
License
ISC
