RichText Editor Library
A fully-featured rich text editor built with React and Tiptap. This library provides customizable components and extensions to create a seamless and interactive text editing experience.
Table of Contents
Features
- Rich Text Editing: Bold, italic, underline, strikethrough, and more.
- Lists: Support for ordered and unordered lists.
- Links: Easily add and remove hyperlinks.
- Tables: Advanced table management with row and column selection.
- Columns Layout: Create multi-column layouts within the editor.
- Images: Insert and manage images seamlessly.
- Responsive Design: Built with Tailwind CSS for responsive and modern UI.
- Extensible: Easily extendable with custom extensions and plugins.
- Hook Integration: Custom hooks for enhanced functionality.
Installation
Ensure you have Node.js installed.
-
Clone the Repository:
git clone https://github.com/yourusername/richtext-editor-library.git
cd richtext-editor-library
-
Install Dependencies:
npm install
yarn install
-
Start the Development Server:
npm start
yarn start
Usage
Basic Setup
Import the Editor
component and include it in your React application.
import React, { useState } from 'react';
import Editor from './components/Editor';
const App = () => {
const [content, setContent] = useState({});
const handleChange = (doc, raw) => {
setContent(doc);
console.log(raw);
};
return (
<div className="container">
<Editor value={content} onChange={handleChange} />
</div>
);
};
export default App;
Components
Editor
The main editor component allowing full editing capabilities.
import Editor from './components/Editor';
<Editor
id="main-editor"
value={initialContent}
onChange={handleChange}
closeOnBlur={true}
onBlur={handleBlur}
/>
ReadonlyEditor
A non-editable version of the editor for displaying content.
import ReadonlyEditor from './components/ReadonlyEditor';
<ReadonlyEditor
id="readonly-editor"
value={content}
readonly={true}
/>
RichEditor
Combines both editable and readonly states based on focus.
import RichEditor from './components/RichEditor';
<RichEditor
id="rich-editor"
value={content}
readonly={false}
closeOnBlur={true}
onChange={handleChange}
/>
Preview
A simple preview component showcasing the editor.
import Preview from './demo/Preview';
<Preview />
Provides a toolbar with various editing options.
import EditorMenu from './components/EditorMenu';
<EditorMenu editor={editorInstance} />
EditorButton
Reusable button component for editor actions.
import EditorButton from './components/EditorButton';
<EditorButton
onClick={handleClick}
leadingIcon={<FiBold />}
>
Bold
</EditorButton>
EditorActions
Actions for saving or canceling edits.
import EditorActions from './components/EditorActions';
<EditorActions
handleSave={saveContent}
handleBlur={cancelEdit}
/>
Extensions
Table Extensions
Enhance table functionalities with custom behaviors.
- CustomTable: Disables dragging and adds custom styles.
- TableCell: Adds isolation and custom attributes to table cells.
- Columns: Manages multi-column layouts within the editor.
import Table from '@tiptap/extension-table';
import TableRow from '@tiptap/extension-table-row';
import TableCell from '@tiptap/extension-table-cell';
import Columns from './extensions/Columns';
import Column from './extensions/Column';
const editor = useEditor({
extensions: [
Table.configure({ ... }),
TableRow.configure({ ... }),
TableCell.configure({ ... }),
Columns,
Column,
],
});
Columns Extensions
Manage column layouts within the editor.
import Columns, { ColumnLayout } from './extensions/Columns';
editor.chain().focus().setColumns().run();
editor.chain().focus().setLayout(ColumnLayout.TwoColumn).run();
Other Extensions
- Underline: Adds underline functionality.
- Link: Manages hyperlink functionalities.
- Paragraph: Extends paragraph behavior.
import Underline from '@tiptap/extension-underline';
import Link from '@tiptap/extension-link';
import Paragraph from '@tiptap/extension-paragraph';
const editor = useEditor({
extensions: [
Underline,
Link.configure({ ... }),
Paragraph,
],
});
Customization
Customize the editor's appearance and behavior using Tailwind CSS and by extending Tiptap's capabilities.
Styling
Utilize Tailwind CSS classes to style the editor components.
@tailwind base;
@tailwind components;
@tailwind utilities;
.editor-container {
@apply p-4 bg-white rounded-md shadow-md;
}
Extending Functionality
Add or modify editor functionalities by creating custom extensions.
import { Extension } from '@tiptap/core';
const CustomExtension = Extension.create({
name: 'customExtension',
});
export default CustomExtension;
Utilities
cn
A utility function to conditionally join classNames using clsx and tailwind-merge.
import { cn } from './utils/cn';
<div className={cn('base-class', condition && 'conditional-class')} />
import { type ClassValue, clsx } from "clsx";
import { twMerge } from "tailwind-merge";
export function cn(...inputs: ClassValue[]) {
return twMerge(clsx(inputs));
}
Hooks
useClickOutside
Detects clicks outside a specified element to trigger callbacks, useful for closing menus or dialogs.
import { useClickOutside } from './hooks/useClickOutside';
const ref = useRef<HTMLDivElement>(null);
useClickOutside(ref, () => setIsOpen(false));
import { useEffect, RefObject } from "react";
export const useClickOutside = <T extends HTMLElement>(
ref: RefObject<T>,
callback: () => void
) => {
useEffect(() => {
const handleClickOutside = (event: MouseEvent) => {
if (ref.current && !ref.current.contains(event.target as Node)) {
callback();
}
};
document.addEventListener("mousedown", handleClickOutside);
return () => {
document.removeEventListener("mousedown", handleClickOutside);
};
}, []);
};
Contributing
Contributions are welcome! Please follow these steps:
-
Fork the Repository
-
Create a Feature Branch
git checkout -b feature/YourFeature
-
Commit Your Changes
git commit -m "Add some feature"
-
Push to the Branch
git push origin feature/YourFeature
-
Open a Pull Request
Please ensure your code follows the project's coding standards and includes relevant tests.
License
MIT
Feel free to customize this README to better fit the specifics of your library and project structure.