react-summernote-light
v1.0.7
Published
[](https://badge.fury.io/js/react-summernote-light) [](https://opensource.org/licenses/MIT)
Downloads
84
Readme
React Rich Text Editor
A powerful, customizable WYSIWYG editor for React applications built from scratch with modern design and extensive features.
✨ Features
- 🎨 Modern Design - Beautiful UI with Tailwind CSS and smooth animations
- 📝 Rich Text Editing - Bold, italic, underline, headings, lists, alignment, and more
- 🖼️ Media Support - Image and video embedding with custom upload handlers
- 📊 Tables - Full table creation and editing capabilities
- 🎯 Font Sizes - Immediate font size application with visual feedback
- 💻 Code View - Toggle between WYSIWYG and HTML code editing (powered by CodeMirror)
- 🖥️ Fullscreen Mode - Distraction-free editing experience
- 🌙 Theme Support - Light and dark theme compatibility
- 🔧 Highly Customizable - Extensive props and configuration options
- 📱 Responsive - Works seamlessly on desktop and mobile devices
- ⚡ TypeScript - Full TypeScript support with type definitions
🚀 Installation
npm install react-summernote-lightPeer Dependencies
This package requires the following peer dependencies:
npm install react react-dom @radix-ui/react-dialog @radix-ui/react-dropdown-menu @radix-ui/react-popover @radix-ui/react-select @radix-ui/react-separator @radix-ui/react-slot @radix-ui/react-tabs @radix-ui/react-toggle @radix-ui/react-tooltip @uiw/react-codemirror lucide-react class-variance-authority clsx tailwind-mergeTailwind CSS Setup
This component requires Tailwind CSS. Make sure you have it configured in your project:
- Install Tailwind CSS (if not already installed):
npm install tailwindcss- Configure Tailwind to include the package styles in your
tailwind.config.js:
module.exports = {
content: [
"./src/**/*.{js,jsx,ts,tsx}",
"./node_modules/react-summernote-light/dist/**/*.{js,jsx}", // Add this line
],
theme: {
extend: {},
},
plugins: [],
};📖 Quick Start
Basic Usage
import React, { useState } from "react";
import { RichTextEditor } from "react-summernote-light";
function App() {
const [content, setContent] = useState("");
return (
<div className="p-4">
<RichTextEditor
initialValue={content}
onChange={setContent}
placeholder="Start typing your content here..."
minHeight="400px"
/>
</div>
);
}
export default App;🛠️ Toolbar Customization
The editor provides extensive toolbar customization through the toolbarConfig prop. You can customize which buttons appear, how they're grouped, and hide specific buttons.
Available Buttons
| Button Type | Description |
| ---------------------- | --------------------------------- |
| undo | Undo action |
| redo | Redo action |
| formatBlock | Heading/paragraph format selector |
| fontName | Font family selector |
| fontSize | Font size selector |
| bold | Bold formatting |
| italic | Italic formatting |
| underline | Underline formatting |
| strikethrough | Strikethrough formatting |
| foreColor | Text color picker |
| backColor | Background color picker |
| justifyLeft | Align left |
| justifyCenter | Align center |
| justifyRight | Align right |
| justifyFull | Justify text |
| insertUnorderedList | Bullet list |
| insertOrderedList | Numbered list |
| indent | Increase indent |
| outdent | Decrease indent |
| createLink | Insert link |
| insertImage | Insert image |
| insertVideo | Insert video |
| insertTable | Insert table |
| insertHorizontalRule | Insert horizontal line |
| modeToggle | Toggle between visual/code view |
Toolbar Configuration
interface ToolbarConfig {
sections?: ToolbarSection[];
hiddenButtons?: ToolbarButtonType[];
showSeparators?: boolean;
}
interface ToolbarSection {
name: string;
buttons: ToolbarButtonType[];
}Example: Custom Toolbar Sections
<RichTextEditor
toolbarConfig={{
sections: [
{
name: "text-style",
buttons: ["bold", "italic", "underline", "foreColor"],
},
{
name: "lists",
buttons: ["insertUnorderedList", "insertOrderedList"],
},
{
name: "insert",
buttons: ["createLink", "insertImage"],
},
],
showSeparators: true,
hiddenButtons: [],
}}
/>Example: Minimal Toolbar
<RichTextEditor
toolbarConfig={{
sections: [
{
name: "basic",
buttons: ["bold", "italic", "createLink"],
},
],
showSeparators: false,
}}
/>Example: Hide Specific Buttons
<RichTextEditor
toolbarConfig={{
hiddenButtons: ["insertVideo", "insertTable", "foreColor", "backColor"],
}}
/>Example: No Toolbar
<RichTextEditor
showToolbar={false}
placeholder="Clean editor without toolbar..."
/>Advanced Usage
import React, { useState } from "react";
import { RichTextEditor, RichTextEditorProps } from "react-summernote-light";
function AdvancedEditor() {
const [content, setContent] = useState(
"<h2>Welcome!</h2><p>Rich text content here...</p>"
);
// Custom image upload handler
const handleImageUpload = async (file: File): Promise<string> => {
const formData = new FormData();
formData.append("image", file);
try {
const response = await fetch("/api/upload", {
method: "POST",
body: formData,
});
const data = await response.json();
return data.url; // Return the uploaded image URL
} catch (error) {
console.error("Upload failed:", error);
throw error;
}
};
return (
<div className="max-w-4xl mx-auto p-6">
<h1 className="text-2xl font-bold mb-4">Rich Text Editor</h1>
<RichTextEditor
initialValue={content}
onChange={setContent}
onImageUpload={handleImageUpload}
placeholder="Start writing something amazing..."
minHeight="500px"
enableCodeView
enableFullscreen
theme="light"
className="border rounded-lg shadow-sm"
onFocus={() => console.log("Editor focused")}
onBlur={() => console.log("Editor blurred")}
/>
<div className="mt-4 p-4 bg-gray-100 rounded">
<h3 className="font-semibold mb-2">Content Preview:</h3>
<div dangerouslySetInnerHTML={{ __html: content }} />
</div>
</div>
);
}
export default AdvancedEditor;🔧 API Reference
Props
| Prop | Type | Default | Description |
| ------------------ | --------------------------------- | --------- | ----------------------------------------------------------------- |
| initialValue | string | '' | Initial HTML content of the editor |
| onChange | (content: string) => void | - | Callback fired when content changes |
| onFocus | () => void | - | Callback fired when editor gains focus |
| onBlur | () => void | - | Callback fired when editor loses focus |
| onImageUpload | (file: File) => Promise<string> | - | Custom image upload handler. Should return the uploaded image URL |
| placeholder | string | - | Placeholder text shown when editor is empty |
| className | string | - | Additional CSS classes for the editor container |
| height | string | - | Fixed height of the editor |
| minHeight | string | '300px' | Minimum height of the editor |
| maxHeight | string | - | Maximum height of the editor |
| theme | 'light' \| 'dark' | 'light' | Editor theme |
| enableCodeView | boolean | false | Enable HTML code view toggle |
| enableFullscreen | boolean | false | Enable fullscreen mode |
| disableImages | boolean | false | Disable image insertion functionality |
| disableVideos | boolean | false | Disable video embedding functionality |
| disableTables | boolean | false | Disable table creation and editing |
| airMode | boolean | false | Enable air mode (minimal styling) |
| toolbarConfig | ToolbarConfig | - | Custom toolbar configuration |
| showToolbar | boolean | true | Show/hide the toolbar completely |
Types
interface RichTextEditorProps {
initialValue?: string;
onChange?: (content: string) => void;
onFocus?: () => void;
onBlur?: () => void;
onImageUpload?: (file: File) => Promise<string>;
placeholder?: string;
toolbarItems?: ToolbarButton[];
disableImages?: boolean;
disableVideos?: boolean;
disableTables?: boolean;
className?: string;
height?: string;
minHeight?: string;
maxHeight?: string;
theme?: "light" | "dark";
airMode?: boolean;
enableCodeView?: boolean;
enableFullscreen?: boolean;
}
interface ToolbarButton {
icon: string;
tooltip: string;
command: string;
value?: string;
}🎨 Styling and Customization
Custom Styling
You can customize the editor's appearance using CSS classes:
<RichTextEditor
className="custom-editor border-2 border-blue-500 rounded-xl"
// ... other props
/>Theme Customization
The editor supports light and dark themes:
<RichTextEditor
theme="dark"
className="bg-gray-900 text-white"
// ... other props
/>Custom Toolbar
You can customize the toolbar by providing your own toolbar items:
const customToolbar = [
{ icon: "bold", tooltip: "Bold", command: "bold" },
{ icon: "italic", tooltip: "Italic", command: "italic" },
// ... more items
];
<RichTextEditor
toolbarItems={customToolbar}
// ... other props
/>;📝 Usage Examples
With Form Libraries
React Hook Form
import { useForm, Controller } from "react-hook-form";
function MyForm() {
const { control, handleSubmit } = useForm();
const onSubmit = (data) => {
console.log(data.content);
};
return (
<form onSubmit={handleSubmit(onSubmit)}>
<Controller
name="content"
control={control}
render={({ field }) => (
<RichTextEditor
initialValue={field.value}
onChange={field.onChange}
placeholder="Enter your content..."
/>
)}
/>
<button type="submit">Submit</button>
</form>
);
}Formik
import { Formik, Form, Field } from "formik";
function MyFormikForm() {
return (
<Formik
initialValues={{ content: "" }}
onSubmit={(values) => console.log(values)}
>
{({ setFieldValue, values }) => (
<Form>
<RichTextEditor
initialValue={values.content}
onChange={(content) => setFieldValue("content", content)}
placeholder="Enter your content..."
/>
<button type="submit">Submit</button>
</Form>
)}
</Formik>
);
}Image Upload Integration
With Firebase Storage
import { getStorage, ref, uploadBytes, getDownloadURL } from "firebase/storage";
const storage = getStorage();
const handleImageUpload = async (file: File): Promise<string> => {
const storageRef = ref(storage, `images/${file.name}`);
const snapshot = await uploadBytes(storageRef, file);
const downloadURL = await getDownloadURL(snapshot.ref);
return downloadURL;
};
<RichTextEditor
onImageUpload={handleImageUpload}
// ... other props
/>;With AWS S3
import AWS from "aws-sdk";
const s3 = new AWS.S3({
accessKeyId: "your-access-key",
secretAccessKey: "your-secret-key",
region: "your-region",
});
const handleImageUpload = async (file: File): Promise<string> => {
const params = {
Bucket: "your-bucket-name",
Key: `images/${file.name}`,
Body: file,
ContentType: file.type,
};
const result = await s3.upload(params).promise();
return result.Location;
};
<RichTextEditor
onImageUpload={handleImageUpload}
// ... other props
/>;🛠️ Development
Prerequisites
- Node.js 16+
- npm or yarn
Local Development
- Clone the repository:
git clone https://github.com/shakibgithub944/flexi-rich-text.git
cd flexi-rich-text- Install dependencies:
npm install- Start the development server:
npm run dev- Open http://localhost:8080
Building the Package
# Build the library
npm run build:lib
# Build the demo app
npm run build:app
# Build both
npm run buildTesting the Package Locally
# Create a package tarball
npm pack
# In another project, install the local package
npm install path/to/react-summernote-light-1.0.0.tgz🤝 Contributing
Contributions are welcome! Please feel free to submit a Pull Request.
- Fork the repository
- Create your feature branch (
git checkout -b feature/AmazingFeature) - Commit your changes (
git commit -m 'Add some AmazingFeature') - Push to the branch (
git push origin feature/AmazingFeature) - Open a Pull Request
📝 License
This project is licensed under the MIT License - see the LICENSE file for details.
🐛 Issues
If you encounter any issues or have suggestions, please open an issue on GitHub.
🙏 Acknowledgments
- Built with React
- UI components from Radix UI
- Styling with Tailwind CSS
- Code editing with CodeMirror
- Icons from Lucide React
Made with ❤️ by shakibgithub944
