@datazymes/dz-rich-text-editor
v2.2.0
Published
A comprehensive React rich text editor component with image upload, resize functionality, and standalone CSS. Ready for NPM publishing.
Downloads
5
Maintainers
Readme
DZRichTextEditor - A React Rich Text Editor Component
DZRichTextEditor is a comprehensive, parameterized React rich text editor component designed for easy integration and customization. It supports image uploads (via drag-drop, paste, or file dialog), client-side image resizing, and comes with a clean, standalone CSS file. It is configured for publishing to NPM and GitHub Packages.
Note on Placeholders: Before publishing, you must replace the placeholder values in package.json (@datazymesrepository, repository URL) and ./.npmrc (@datazymesrepository) with your actual GitHub username or organization name.
Installation
Install the package from GitHub Packages:
npm install @datazymesrepository/dz-rich-text-editorYou will also need to install the peer dependencies:
npm install react react-domPublishing to GitHub Packages
To publish new versions of this package, follow these steps:
1. Authenticate with GitHub Packages
You need to authenticate npm with GitHub Packages.
Create a Personal Access Token (PAT): Go to your GitHub Developer Settings and generate a new classic PAT. Grant it the
write:packagesscope.Log in: Use the following command to log in, replacing
YOUR-USERNAMEwith your GitHub username andYOUR-PATwith the token you just created.npm login --scope=@datazymesrepository --registry=https://npm.pkg.github.com
2. Update Version
Before publishing, update the version in package.json according to semantic versioning rules.
3. Build the Package
Run the build script to transpile the component and generate the distributable files in the dist/ directory.
npm run build4. Publish
Finally, publish the package to the GitHub Packages registry.
npm publishFeatures
- Image Upload: Supports pasting, drag-and-drop, and a toolbar button for image uploads.
- Backend Agnostic: Uploads images via a
fetchcall to a configurable backend endpoint. - Image Resizing: Simple and intuitive client-side image resizing with handles.
- Customizable Uploads: Pass API URLs and credentials via the
uploadConfigprop. - Clean HTML: The editor is designed to keep the underlying HTML clean from temporary resizing elements.
- Standalone CSS: A separate
index.cssfile for easy styling and customization.
Props
DZRichTextEditor
| Prop | Type | Default | Description |
| -------------- | -------- | -------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------ |
| value | string | '' | The HTML content of the editor. |
| onChange | func | (html) => {} | A callback function that receives the updated HTML content whenever it changes. |
| uploadConfig | object | { clientId: 'default', clientSecret: 'default' } | An object containing the configuration for the image upload endpoint. See uploadConfig section below for more details. |
| placeholder | string | 'Compose an epic...' | Placeholder text to display when the editor is empty. |
Quick Start
import React, { useState } from "react";
import DZRichTextEditor from "dz-rich-text-editor";
import "dz-rich-text-editor/index.css"; // Import the CSS
function MyApp() {
const [content, setContent] = useState(
"<p>Welcome to <strong>DZ Rich Text Editor</strong>!</p>"
);
return (
<DZRichTextEditor
value={content}
onChange={setContent}
placeholder="Start typing..."
/>
);
}Image Upload Configuration
To enable image upload functionality, configure the uploadConfig prop:
import React, { useState } from "react";
import DZRichTextEditor from "dz-rich-text-editor";
function EditorWithImageUpload() {
const [content, setContent] = useState("");
const uploadConfig = {
uploadApiUrl: "https://your-api.com/upload",
clientId: "your-client-id",
clientSecret: "your-client-secret",
};
return (
<DZRichTextEditor
value={content}
onChange={setContent}
uploadConfig={uploadConfig}
toolbarOptions={[
"bold",
"italic",
"underline",
"insertImage", // Enable image insert button
"link",
"blockquote",
]}
/>
);
}Upload API Requirements
Your upload API should:
Accept POST requests to the configured endpoint
Accept FormData with the following fields:
image: The image fileclient_id: Authentication client ID (optional)client_secret: Authentication client secret (optional)
Return JSON response in this format:
{ "data": { "authenticatedUrl": "https://your-cdn.com/path/to/uploaded-image.jpg" } }
Example Backend Implementation (Express.js)
app.post("/upload", upload.single("image"), (req, res) => {
const { client_id, client_secret } = req.body;
// Validate credentials
if (!validateCredentials(client_id, client_secret)) {
return res.status(401).json({ error: "Invalid credentials" });
}
// Upload to your storage (GCS, AWS S3, etc.)
const imageUrl = uploadToStorage(req.file);
res.json({
data: {
authenticatedUrl: imageUrl,
},
});
});Image Features
Image Upload Methods
- Toolbar Button: Click the 🖼️ button to select images from your device
- Drag & Drop: Drag images directly into the editor
- Paste: Paste images from clipboard (Ctrl+V)
Image Resize Functionality
Images inserted into the editor can be resized:
- Click any image to select it (shows blue border with resize handles)
- Drag corner handles to resize freely (width and height independently)
- Drag edge handles for single-dimension resizing
- Click outside to deselect the image
Resize Features:
- 8 resize handles (4 corners + 4 edges)
- No aspect ratio constraints - resize to any dimensions
- Minimum size constraints (50px width, 30px height)
- Visual feedback during resize operations
- Clean HTML output (resize controls are editor-only)
Props API
interface DZRichTextEditorProps {
value?: string;
onChange?: (content: string) => void;
toolbarOptions?: string[];
placeholder?: string;
readOnly?: boolean;
height?: string;
width?: string;
toolbarPosition?: "top" | "bottom";
stickyToolbar?: boolean;
stickyOffset?: number;
debounceTime?: number;
customClasses?: CustomClasses;
uploadConfig?: UploadConfig;
}
interface UploadConfig {
uploadApiUrl?: string;
clientId?: string;
clientSecret?: string;
}Core Props
| Prop | Type | Default | Description |
| ---------------- | --------------------------- | ------------------- | ----------------------------- |
| value | string | '' | HTML content of the editor |
| onChange | (content: string) => void | - | Callback when content changes |
| toolbarOptions | string[] | All options | Array of toolbar button names |
| placeholder | string | 'Start typing...' | Placeholder text |
| readOnly | boolean | false | Disable editing |
| uploadConfig | UploadConfig | {} | Image upload configuration |
Layout Props
| Prop | Type | Default | Description |
| ----------------- | ------------------- | ---------- | --------------------- |
| height | string | 'h-64' | CSS height class |
| width | string | 'w-full' | CSS width class |
| toolbarPosition | 'top' \| 'bottom' | 'top' | Toolbar position |
| stickyToolbar | boolean | false | Enable sticky toolbar |
| stickyOffset | number | 0 | Sticky toolbar offset |
Performance Props
| Prop | Type | Default | Description |
| --------------- | --------------- | ------- | -------------------- |
| debounceTime | number | 300 | Debounce delay (ms) |
| customClasses | CustomClasses | {} | Override CSS classes |
Toolbar Options
Configure which tools appear in the toolbar:
// Minimal toolbar
<DZRichTextEditor
toolbarOptions={['bold', 'italic', 'link']}
// ... other props
/>
// Full toolbar (default)
<DZRichTextEditor
toolbarOptions={[
'bold', 'italic', 'underline', 'strikethrough',
'highlight', 'fontColor', 'headings', 'fontFamily',
'lineSpacing', 'alignLeft', 'alignCenter', 'alignRight',
'alignJustify', 'unorderedList', 'orderedList', 'todoList',
'increaseIndent', 'decreaseIndent', 'link', 'insertImage',
'blockquote', 'codeBlock', 'pageBreak', 'caseChange', 'insertTable'
]}
// ... other props
/>Available Options
Basic Formatting:
bold,italic,underline,strikethroughhighlight,fontColor
Structure:
headings,fontFamily,lineSpacingalignLeft,alignCenter,alignRight,alignJustify
Lists & Indentation:
unorderedList,orderedList,todoListincreaseIndent,decreaseIndent
Content:
link,insertImage,blockquote,codeBlockinsertTable,pageBreak
Utilities:
caseChange
Advanced Examples
Custom Styled Editor
<DZRichTextEditor
value={content}
onChange={setContent}
height="h-96"
width="max-w-4xl"
customClasses={{
wrapper: "border-2 border-purple-300 rounded-xl",
toolbar: "bg-purple-50 border-purple-200",
contentArea: "bg-white min-h-64",
button: "hover:bg-purple-100",
}}
uploadConfig={{
uploadApiUrl: process.env.REACT_APP_UPLOAD_URL,
clientId: process.env.REACT_APP_CLIENT_ID,
clientSecret: process.env.REACT_APP_CLIENT_SECRET,
}}
/>Sticky Toolbar Example
<DZRichTextEditor
value={content}
onChange={setContent}
stickyToolbar={true}
stickyOffset={60} // Account for fixed header
height="h-screen"
/>Blog Editor Example
function BlogEditor({ post, onSave }) {
const [content, setContent] = useState(post.content);
const uploadConfig = {
uploadApiUrl: "/api/blog/upload-image",
clientId: "blog-client",
clientSecret: process.env.REACT_APP_BLOG_SECRET,
};
return (
<div className="max-w-4xl mx-auto">
<DZRichTextEditor
value={content}
onChange={setContent}
placeholder="Write your blog post..."
height="h-96"
uploadConfig={uploadConfig}
toolbarOptions={[
"bold",
"italic",
"underline",
"highlight",
"headings",
"alignLeft",
"alignCenter",
"alignRight",
"unorderedList",
"orderedList",
"link",
"insertImage",
"blockquote",
"insertTable",
]}
/>
<button onClick={() => onSave(content)}>Save Post</button>
</div>
);
}Environment Configuration
For applications using environment variables, you can configure the upload settings:
// .env
REACT_APP_UPLOAD_URL=https://your-api.com/upload
REACT_APP_CLIENT_ID=your-client-id
REACT_APP_CLIENT_SECRET=your-client-secret
// Component
const uploadConfig = {
uploadApiUrl: process.env.REACT_APP_UPLOAD_URL,
clientId: process.env.REACT_APP_CLIENT_ID,
clientSecret: process.env.REACT_APP_CLIENT_SECRET
};Migration from Environment Variables
If you were previously using environment variables directly (VITE_* variables), update your configuration:
Before:
// .env
VITE_UPLOAD_API_URL=https://api.example.com/upload
VITE_CLIENT_ID=client123
VITE_CLIENT_SECRET=secret456
// No explicit config needed - read automatically
<DZRichTextEditor value={content} onChange={setContent} />After:
// .env
REACT_APP_UPLOAD_URL=https://api.example.com/upload
REACT_APP_CLIENT_ID=client123
REACT_APP_CLIENT_SECRET=secret456
// Explicit config required
const uploadConfig = {
uploadApiUrl: process.env.REACT_APP_UPLOAD_URL,
clientId: process.env.REACT_APP_CLIENT_ID,
clientSecret: process.env.REACT_APP_CLIENT_SECRET
};
<DZRichTextEditor
value={content}
onChange={setContent}
uploadConfig={uploadConfig}
/>Keyboard Shortcuts
| Shortcut | Action |
| -------------- | ------------------- |
| Ctrl/Cmd + B | Bold |
| Ctrl/Cmd + I | Italic |
| Ctrl/Cmd + U | Underline |
| Ctrl/Cmd + L | Align Left |
| Ctrl/Cmd + E | Align Center |
| Ctrl/Cmd + R | Align Right |
| Ctrl/Cmd + J | Justify |
| Ctrl/Cmd + 1 | Single Line Spacing |
| Ctrl/Cmd + 2 | Double Line Spacing |
| Ctrl/Cmd + 5 | 1.5 Line Spacing |
| Tab | Increase Indent |
| Shift + Tab | Decrease Indent |
Browser Support
- Chrome 80+
- Firefox 75+
- Safari 13+
- Edge 80+
Contributing
Contributions are welcome! Please feel free to submit issues and pull requests.
License
MIT License - see LICENSE file for details.
Version History
v1.3.0
- ✨ Added configurable upload system via props
- 🖼️ Implemented image resize functionality
- 🧹 Clean HTML output (no editor artifacts)
- 📦 Prepared for npm package distribution
- 🔧 Added TypeScript definitions
v1.2.0
- 🎨 Advanced table styling and resizing
- 📱 Improved responsive design
- ⚡ Performance optimizations
v1.1.0
- 🖼️ Image upload via drag & drop and paste
- 🔗 Enhanced link management
- 🎯 Improved toolbar customization
v1.0.0
- 🎉 Initial release
- ✨ Core rich text editing features
- 🎨 Tailwind CSS integration
