@malaya_jeeva/rich-text-editor
v1.0.13
Published
Custom React Rich Text Editor
Maintainers
Readme
📝 @malaya_jeeva/rich-text-editor
A lightweight, fully-featured Rich Text Editor (WYSIWYG) built from scratch with React + TypeScript. No heavy dependencies — just React.
🚀 Installation
npm install @malaya_jeeva/rich-text-editor📦 Usage
Basic Example
'use client' // required for Next.js (App Router)
import React, { useState } from 'react'
import RichTextEditor from '@malaya_jeeva/rich-text-editor'
export default function Page() {
const [value, setValue] = useState('')
return (
<RichTextEditor
value={value}
onChange={setValue}
placeholder="Write something..."
height={400}
theme="light"
/>
)
}Uncontrolled (no props needed)
import RichTextEditor from '@malaya_jeeva/rich-text-editor'
export default function Page() {
return <RichTextEditor />
}⚙️ Props
| Prop | Type | Required | Default | Description |
| ------------- | ----------------------------- | -------- | -------------------- | --------------------------------------------------------------------------- |
| value | string | No | — | Initial HTML content (read on first mount only) |
| onChange | (value: string) => void | No | — | Fires with full innerHTML on every change |
| toolbar | ToolbarItem[] | No | all items | Controls which toolbar buttons are shown. If omitted, all buttons are shown |
| placeholder | string | No | "Start typing..." | Placeholder text shown when the editor is empty |
| height | number \| string | No | auto (max 350px) | Editor content area height — 500, "400px", "60vh" etc. |
| theme | "light" \| "dark" \| "auto" | No | "auto" | Color theme. "auto" follows the OS prefers-color-scheme setting |
Type export
import type { RichTextEditorProps, ToolbarItem } from '@malaya_jeeva/rich-text-editor'📐 Height
Control the height of the editor content area via the height prop. Accepts a number (pixels) or any valid CSS string.
<RichTextEditor height={500} /> // 500px fixed
<RichTextEditor height="60vh" /> // viewport-relative
<RichTextEditor height="400px" /> // explicit px string
<RichTextEditor /> // default — grows with content, caps at 350px💬 Placeholder
Set the placeholder text shown when the editor is empty.
<RichTextEditor placeholder="Write something..." />
// omit it — defaults to "Start typing..."🌗 Theme
Three options: "light", "dark", or "auto" (default).
<RichTextEditor theme="light" /> // always light
<RichTextEditor theme="dark" /> // always dark
<RichTextEditor /> // auto — follows OS prefers-color-schemeWhen
theme="auto"(or the prop is omitted) the editor automatically switches between light and dark based on the user's OS setting — no extra code needed.
🛠️ Toolbar Customization
Pass a toolbar array to control exactly which buttons appear. If the prop is omitted, all buttons are shown — fully backward compatible.
All available ToolbarItem keys
| Key | Button | Description |
| --- | ------ | ----------- |
| bold | B | Bold text |
| italic | I | Italic text |
| underline | U | Underline text |
| color | A̲ | Text color picker (palette + HSV wheel + remove) |
| blockFormat | Paragraph ▾ | Block format dropdown (Paragraph, H1, H2, H3) |
| alignLeft | ≡ | Align text left |
| alignCenter | ≡ | Align text center |
| alignRight | ≡ | Align text right |
| alignJustify | ≡ | Justify text |
| bulletList | • | Unordered / bullet list |
| numberedList | 1. | Ordered / numbered list |
| indent | → | Increase indent (or go deeper in list) |
| outdent | ← | Decrease indent (or go back up in list) |
| link | 🔗 | Insert / edit hyperlink |
| codeBlock | </> | Wrap selection in <pre><code> |
| image | 🖼 | Insert image (upload, URL, or drop) |
| table | ⊞ | Insert table (grid picker up to 8×8) |
| html | HTML | Toggle between Visual and HTML source view |
| copyHtml | ⎘ | Copy current HTML to clipboard |
Note: Separators between groups are rendered automatically — they appear only when buttons exist on both sides, so you never get a leading, trailing, or double separator regardless of your selection.
✨ Features
Text Formatting
- ✅ Bold, Italic, Underline
- 🎨 Text color picker — palette + custom HSV color wheel + remove color
- 🔠 Block formats — Paragraph, Heading 1 / 2 / 3 (dropdown)
- ↔️ Text alignment — Left, Center, Right, Justify
Lists
- 📌 Bullet & Numbered lists with full multilevel nesting
- Indent/outdent via toolbar or
Tab/Shift+Tab - Nesting style:
1. → a. → i.for ordered,• → ◦ → ▪for unordered
Links
- 🔗 Insert link — floating inline bar appears near the selection
- Edit link — click inside any link to see URL with Edit / Unlink buttons
- Unlink — removes
<a>tag while keeping the text
Images
- 🖼️ Insert via upload — drag & drop onto the zone or click to browse
- 🌐 Insert via URL — paste any image URL with live preview
- 📥 Drop into editor — drag an image file directly onto the content
- Click to edit — selecting an image opens a full control panel:
- Style tab — Display (Block / Inline), Alignment (Left / Center / Right), Width presets (25% / 50% / 75% / 100% / Original), manual width input, Alt text
- Caption tab — wraps image in
<figure>/<figcaption>, editable caption text - Link tab — wrap image in
<a>with Apply / Remove
- 🔲 Drag-to-resize — 8 handles (corners preserve aspect ratio, edges resize freely)
Tables
- 📊 Insert table — grid picker up to 8×8, first row auto-set as
<th> - Floating context toolbar — appears near the active cell:
- Add row above / below, Delete row
- Add column left / right, Delete column
- Delete entire table
- Cell merge — drag or
Shift+clickto select a range → Merge button - Cell split — splits merged cells back to individual cells
- Tab navigation —
Tab/Shift+Tabto move between cells
Code
- 💻 Code block — wraps selection in
<pre><code> - 🔄 HTML / Visual toggle — switch between WYSIWYG and raw HTML source
- ✨ Auto-prettify — HTML view auto-indents on switch
- 📋 Copy HTML — copies current HTML to clipboard
General
- ⌨️ Keyboard shortcuts — Ctrl+B, Ctrl+I, Ctrl+U
- 📊 Live word count
- 🌙 Dark mode support — automatic via
prefers-color-scheme - 🏗️ Library-safe TSX — uses
ReactElementreturns, no global JSX namespace
🧠 Keyboard Shortcuts
| Shortcut | Action |
| -------- | ------ |
| Ctrl + B | Bold |
| Ctrl + I | Italic |
| Ctrl + U | Underline |
| Tab | Indent list item / move to next table cell |
| Shift + Tab | Outdent list item / move to previous table cell |
| Enter (link bar) | Apply link |
| Escape (link bar) | Dismiss link bar |
🖼️ Image Editor — Detail
Click any inserted image to open the image control panel.
Style tab
| Control | Options |
| ------- | ------- |
| Display | Block (full row) · Inline (flows with text) |
| Alignment | Left · Center · Right |
| Width | 25% · 50% · 75% · 100% · Original size · Custom (e.g. 300px) |
| Alt text | Free text input |
| Delete | Removes the image from the editor |
Caption tab
Wraps the image in <figure> + <figcaption>. The caption always renders below the image regardless of float alignment.
Link tab
Wraps the image in an <a> tag. Existing link can be edited or removed.
Drag resize
Drag any of the 8 blue handles around the selected image:
- Corner handles — resize while preserving aspect ratio
- Edge handles — resize width or height freely
📊 Table Guide
Inserting
- Click the table grid icon in the toolbar
- Hover to select rows × columns (up to 8×8)
- Click to insert — first row is automatically
<th>
Cell merge
- Drag across cells, or Shift+click a second cell to select a rectangle
- Selected cells highlight in blue → click Merge in the floating toolbar
Cell split
Click inside a merged cell → Split button appears in the floating toolbar.
🎨 Color Picker
- Palette — 34 preset colors in a compact grid
- Black — one-click reset to automatic color
- Remove — strips color from the selection
- Custom — opens a full HSV color wheel with:
- Saturation/brightness canvas (drag to pick exact shade)
- Hue slider (full 360° spectrum)
- Hex input field
- Live preview swatch
- Apply button
💡 Output Format
onChange returns standard HTML. Example:
<h2>Getting started</h2>
<p>This is a <strong>rich text</strong> editor.</p>
<ul>
<li>Item one</li>
<li>Item two
<ul><li>Nested item</li></ul>
</li>
</ul>
<figure style="margin:0.8em 0;display:block;overflow:hidden;">
<img src="..." alt="diagram" style="max-width:100%;width:50%;" />
<figcaption style="text-align:center;clear:both;">Figure 1</figcaption>
</figure>
<table>
<tr><th>Name</th><th>Role</th></tr>
<tr><td>Alice</td><td>Engineer</td></tr>
</table>⚠️ Sanitization
The editor does not sanitize output. Before persisting to a database or rendering via dangerouslySetInnerHTML, run through a sanitizer:
npm install dompurify
npm install -D @types/dompurifyimport DOMPurify from 'dompurify'
const clean = DOMPurify.sanitize(html)🌐 Browser Support
| Browser | Support | | ------- | ------- | | Chrome 90+ | ✅ | | Firefox 90+ | ✅ | | Safari 15+ | ✅ | | Edge 90+ | ✅ |
🎯 Notes
- Controlled component → always pass
valueandonChangetogether (or omit both) - Works with React 18+ and 19+
- Compatible with Next.js (use
'use client') - Written in TypeScript — all props and internal types are exported
🔄 Local Development
# In the library folder
npm run build
npm link
# In your app
npm link @malaya_jeeva/rich-text-editor👨💻 Author
Malaya Ranjan Jena
📄 License
ISC
