React Logoreact-draft-wysiwyg

React-Draft-WYSIWYG: A Rich Text Editor for React

`react-draft-wysiwyg` is a popular React component that provides a powerful and customizable WYSIWYG (What You See Is What You Get) rich text editor. It is built on top of Facebook's `draft-js` library, which is a framework for building rich text editors in React. While `draft-js` offers a low-level API for editor state management, `react-draft-wysiwyg` abstracts much of that complexity, offering a ready-to-use, feature-rich user interface.

# Key Features:

1. Rich Text Formatting: Supports common formatting options like bold, italic, underline, strikethrough, monospace, font size, font family, and text color.
2. Block Types: Allows for different block types such as headings (h1-h6), blockquotes, code blocks, unordered lists, and ordered lists.
3. Alignment and Indentation: Provides controls for text alignment (left, center, right, justify) and indentation.
4. Links and Images: Easy insertion and management of hyperlinks and images, often with built-in upload capabilities or URL embedding.
5. Undo/Redo History: Standard undo and redo functionalities.
6. Full-Screen Mode: A toggle to expand the editor to full screen for better focus.
7. Customizable Toolbar: The toolbar is highly customizable, allowing developers to choose which controls to display and even create custom controls.
8. Internationalization (i18n): Supports multiple languages for the toolbar and editor messages.
9. Markdown Support: Can convert content to Markdown or HTML for persistence.
10. Accessibility: Designed with accessibility in mind.

# Why Use It?

- Simplifies Rich Text Editing: Instead of building an editor from scratch with `draft-js`, `react-draft-wysiwyg` provides a full-featured UI out-of-the-box, significantly reducing development time.
- Leverages Draft.js Power: It benefits from `draft-js`'s immutable editor state, robust content management, and extensibility, while offering a developer-friendly API.
- Highly Customizable: Despite being a complete solution, it offers extensive customization options for the toolbar, styling, and even integrating custom blocks.
- Active Community & Maintenance: It's a widely used library with good community support and ongoing maintenance.

# How It Works:

At its core, `react-draft-wysiwyg` manages the editor's content and selection using `EditorState` objects from `draft-js`. The `Editor` component takes an `editorState` prop (an immutable record that represents the full state of the editor) and an `onEditorStateChange` callback. When a user interacts with the editor, a new `EditorState` is generated, which you then pass back to the `Editor` component to re-render it. This controlled component pattern is typical for React inputs.

To integrate it into a React application, you typically install both `react-draft-wysiwyg` and `draft-js`.

Installation:
`npm install react-draft-wysiwyg draft-js`
or
`yarn add react-draft-wysiwyg draft-js`

And don't forget to import its CSS for proper styling: `import 'react-draft-wysiwyg/dist/react-draft-wysiwyg.css';`

Example Code

import React, { useState } from 'react';
import { EditorState, convertToRaw, ContentState } from 'draft-js';
import { Editor } from 'react-draft-wysiwyg';
import 'react-draft-wysiwyg/dist/react-draft-wysiwyg.css'; // Import the editor's CSS

function MyWysiwygEditor() {
  // Initialize editorState with an empty editor
  const [editorState, setEditorState] = useState(() =>
    EditorState.createEmpty()
  );

  // Callback function to update editorState when content changes
  const onEditorStateChange = (newEditorState) => {
    setEditorState(newEditorState);
  };

  // Function to log the raw content of the editor to the console
  const logEditorContent = () => {
    const contentState = editorState.getCurrentContent();
    console.log('Raw Editor Content:', convertToRaw(contentState));
  };

  return (
    <div style={{
      border: '1px solid #ddd',
      minHeight: '350px',
      padding: '10px',
      borderRadius: '5px',
      fontFamily: 'Arial, sans-serif'
    }}>
      <h2 style={{ textAlign: 'center', color: '#333' }}>React Draft WYSIWYG Editor Example</h2>
      <Editor
        editorState={editorState}
        onEditorStateChange={onEditorStateChange}
        wrapperClassName="demo-wrapper"
        editorClassName="demo-editor"
        toolbarClassName="demo-toolbar"
        placeholder="Start typing your rich text here..."
        toolbar={{
          options: [
            'inline', 'blockType', 'fontSize', 'fontFamily', 'list', 
            'textAlign', 'colorPicker', 'link', 'image', 'history'
          ],
          inline: { inDropdown: false, options: ['bold', 'italic', 'underline', 'strikethrough', 'monospace'] },
          list: { inDropdown: true },
          textAlign: { inDropdown: true },
          link: { inDropdown: true, options: ['link', 'unlink'] },
          image: { 
            uploadEnabled: true,
            urlEnabled: true,
            alignmentEnabled: true,
            uploadCallback: (file) => {
              return new Promise(
                (resolve, reject) => {
                  // Simulate image upload
                  setTimeout(() => {
                    resolve({ data: { link: URL.createObjectURL(file) } });
                  }, 500);
                }
              );
            },
            previewImage: true,
            inputAccept: 'image/gif,image/jpeg,image/jpg,image/png,image/svg',
            alt: { present: false, mandatory: false },
            defaultSize: { height: 'auto', width: 'auto' },
          },
          history: { inDropdown: false, options: ['undo', 'redo'] },
        }}
      />
      <button 
        onClick={logEditorContent}
        style={{
          marginTop: '15px',
          padding: '10px 20px',
          backgroundColor: '#007bff',
          color: 'white',
          border: 'none',
          borderRadius: '5px',
          cursor: 'pointer',
          fontSize: '16px',
          fontWeight: 'bold'
        }}
      >
        Log Editor Content to Console
      </button>
      
      <div style={{ marginTop: '25px', borderTop: '1px solid #eee', paddingTop: '15px' }}>
        <h3>Current Raw Content (JSON Preview):</h3>
        <pre style={{
          backgroundColor: '#f8f8f8',
          padding: '15px',
          borderRadius: '5px',
          border: '1px solid #ddd',
          overflowX: 'auto',
          whiteSpace: 'pre-wrap',
          wordWrap: 'break-word'
        }}>
          {JSON.stringify(convertToRaw(editorState.getCurrentContent()), null, 2)}
        </pre>
      </div>
    </div>
  );
}

export default MyWysiwygEditor;