npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2026 – Pkg Stats / Ryan Hefner

@jonahschulte/rtf-editor

v0.3.0

Published

React WYSIWYG editor for RTF documents with track changes support

Readme

@jonahschulte/rtf-editor

React WYSIWYG editor for RTF documents with track changes support.

Features

  • WYSIWYG Editing - Rich text editing powered by Quill
  • Track Changes Support - Visual display of insertions and deletions
  • Accept/Reject Changes - Individual or bulk change management
  • Multiple View Modes - Markup, Final, and Original views
  • Customizable Styling - Custom colors for track changes
  • Responsive Design - Works on desktop and mobile

Installation

npm install @jonahschulte/rtf-editor

Peer Dependencies

npm install react react-dom

Usage

Basic Usage

import { useState } from 'react';
import { RTFEditor } from '@jonahschulte/rtf-editor';

function App() {
  const [rtfContent, setRtfContent] = useState('');

  return (
    <RTFEditor
      value={rtfContent}
      onChange={(rtf, html) => setRtfContent(rtf)}
      showSidebar
      showTrackChangesToolbar
    />
  );
}

With Track Changes Callbacks

import { RTFEditor } from '@jonahschulte/rtf-editor';

function App() {
  const handleTrackChangesUpdate = (doc, changes) => {
    console.log(`${changes.length} changes remaining`);
  };

  return (
    <RTFEditor
      value={rtfContent}
      onChange={handleChange}
      onTrackChangesUpdate={handleTrackChangesUpdate}
      showSidebar
      showTrackChangesToolbar
    />
  );
}

Custom Colors

<RTFEditor
  value={rtfContent}
  onChange={handleChange}
  trackChangesColors={{
    insertionColor: '#e6ffe6',
    deletionColor: '#ffe6e6',
    insertionBorderColor: '#00cc00',
    deletionBorderColor: '#cc0000',
  }}
/>

Read-Only Mode

<RTFEditor
  value={rtfContent}
  readOnly
  showSidebar
  defaultViewMode="final"
/>

Props

| Prop | Type | Default | Description | |------|------|---------|-------------| | value | string | '' | RTF content | | onChange | (rtf: string, html: string) => void | - | Called when content changes | | onTrackChangesUpdate | (doc, changes) => void | - | Called when changes are accepted/rejected | | readOnly | boolean | false | Disable editing | | allowEditingWithChanges | boolean | false | Allow editing when track changes exist (not recommended) | | placeholder | string | 'Start typing...' | Placeholder text | | showSidebar | boolean | true | Show track changes sidebar | | showTrackChangesToolbar | boolean | true | Show track changes toolbar | | defaultViewMode | 'markup' \| 'final' \| 'original' | 'markup' | Initial view mode | | className | string | '' | Custom CSS class | | height | string \| number | 400 | Editor height | | toolbarOptions | array | - | Custom Quill toolbar options | | trackChangesColors | object | - | Custom colors for track changes |

View Modes

| Mode | Description | |------|-------------| | markup | Shows all changes with visual styling (green for insertions, red strikethrough for deletions) | | final | Shows the document as if all changes were accepted | | original | Shows the document as if all changes were rejected |

Read-Only Mode with Track Changes

By default, the editor becomes read-only when unresolved track changes exist. This prevents data loss and confusion:

  • ✅ Prevents edits from being lost when accepting/rejecting changes
  • ✅ Clear workflow: resolve all changes first, then edit the clean document
  • ✅ Visual indicator explains why editing is disabled
  • ✅ Matches behavior of professional editors like Microsoft Word

To enable editing:

  1. Accept or reject all track changes to remove them
  2. Or set allowEditingWithChanges={true} to override (not recommended)

Why read-only by default?

When you edit a document with track changes and then accept/reject a change, the entire document structure is regenerated to apply the change. Any edits you made will be lost because they exist only in the HTML layer, not the underlying RTF structure. Read-only mode prevents this confusion.

Undo/Redo Track Changes

The editor supports undoing and redoing track changes operations (accept/reject):

  • Keyboard shortcuts:
    • Ctrl/Cmd + Z - Undo last accept/reject operation
    • Ctrl/Cmd + Shift + Z - Redo last undone operation
  • Toolbar buttons: Undo and Redo buttons appear in the track changes toolbar when available
  • Automatic: Undo stack is cleared when loading new documents
  • Scope: Only affects accept/reject operations, not content editing (which uses Quill's built-in undo)

Components

The package also exports individual components for custom layouts:

import {
  RTFEditor,
  TrackChangesSidebar,
  TrackChangesToolbar
} from '@jonahschulte/rtf-editor';

Known Limitations

Lossy HTML-to-RTF Conversion

When editing content in the WYSIWYG editor, the onChange callback provides both RTF and HTML. However, the HTML-to-RTF conversion is lossy and will not preserve:

  • Track changes metadata (insertions, deletions, author info, timestamps)
  • Custom fonts (defaults to Times New Roman)
  • Color tables
  • Revision tables
  • Other RTF-specific formatting

This is because:

  1. The editor uses Quill (HTML-based) for WYSIWYG editing
  2. Quill doesn't understand RTF-specific concepts like track changes
  3. The convertHTMLToRTF function creates a new RTF document from scratch

Recommendations:

  • Use this editor primarily for viewing RTF documents with track changes
  • For editing, consider storing the HTML output separately
  • If you need to preserve the original RTF, keep a copy and only use the HTML for display
  • Accept/reject track changes through the UI before editing content

Debounced onChange

The onChange callback is debounced (500ms) to prevent performance issues during rapid typing. This means:

  • Changes are not emitted on every keystroke
  • The callback fires 500ms after the user stops typing
  • This is intentional to avoid re-render loops

Related

License

MIT