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 🙏

© 2025 – Pkg Stats / Ryan Hefner

@prmargas/react-wysiwyg-editor

v1.0.2

Published

A lightweight, extensible WYSIWYG editor built with React and TypeScript

Readme

WYSIWYG Editor

React TypeScript

A powerful, modern What You See Is What You Get editor built with React, TypeScript, and React Router. Features dual-mode editing (WYSIWYG + Markdown), advanced image handling, and a streamlined user interface with full-page preview functionality.

Features

  • 🚀 Lightweight: Pure React implementation with no heavy dependencies
  • 🎨 Rich Formatting: Bold, italic, underline, headings, lists, and more
  • 🔗 Smart Link Management: Insert, edit, and manage links with preview popup
  • 📷 Media Support: Insert and crop images, upload files
  • 🎯 Accessibility: Full keyboard navigation and screen reader support
  • 📱 Responsive: Works seamlessly on desktop and mobile devices
  • 🛡️ Secure: Built-in content sanitization to prevent XSS attacks
  • TypeScript: Full type safety and excellent developer experience
  • 🎨 Configurable Toolbar: Multiple preset configurations and custom toolbar layouts
  • 🔧 Easy Integration: Drop-in toolbar configuration selector component

Installation

npm i @prmargas/react-wysiwyg-editor

🚀 Quick Start

Basic Usage

import React, { useState } from "react";
import { WYSIWYGEditor } from "@prmargas/react-wysiwyg-editor";
import "@prmargas/react-wysiwyg-editor/styles";

function App() {
  const [content, setContent] = useState("<p>Start typing...</p>");

  return (
    <div>
      <h1>My Editor</h1>
      <WYSIWYGEditor
        initialContent={content}
        placeholder="Enter your text here..."
        onChange={setContent}
      />
    </div>
  );
}

export default App;

With Configurable Toolbar

import React, { useState } from "react";
import { 
  WYSIWYGEditor, 
  ToolbarConfigSelector, 
  TOOLBAR_CONFIGURATIONS 
} from "@prmargas/react-wysiwyg-editor";
import "@prmargas/react-wysiwyg-editor/styles";

function App() {
  const [content, setContent] = useState("<p>Start typing...</p>");
  const [selectedConfig, setSelectedConfig] = useState('standard');

  return (
    <div>
      <h1>My Configurable Editor</h1>
      
      <ToolbarConfigSelector
        selectedConfig={selectedConfig}
        onConfigChange={setSelectedConfig}
        showDescription={true}
      />
      
      <WYSIWYGEditor
        initialContent={content}
        placeholder="Enter your text here..."
        onChange={setContent}
        toolbarConfig={TOOLBAR_CONFIGURATIONS[selectedConfig].config}
      />
    </div>
  );
}

export default App;

🎯 Advanced Usage

🔧 Toolbar Configuration

The editor supports multiple toolbar configurations to suit different use cases:

import { WYSIWYGEditor, ToolbarConfig } from "@prmargas/react-wysiwyg-editor";

// Using preset configurations
function EditorWithPresets() {
  const [content, setContent] = useState("");

  return (
    <div>
      {/* Minimal toolbar */}
      <WYSIWYGEditor
        initialContent={content}
        onChange={setContent}
        toolbarConfig={{ preset: 'minimal' }}
      />
      
      {/* Full-featured toolbar */}
      <WYSIWYGEditor
        initialContent={content}
        onChange={setContent}
        toolbarConfig={{ preset: 'full' }}
      />
    </div>
  );
}

// Custom toolbar configuration
function EditorWithCustomToolbar() {
  const [content, setContent] = useState("");
  
  const customConfig: ToolbarConfig = {
    groups: [
      { buttons: ['undo', 'redo'] },
      { buttons: ['bold', 'italic', 'underline'] },
      { buttons: ['formatBlock-H1', 'formatBlock-H2'] },
      { buttons: ['createLink', 'insertImage'] }
    ]
  };

  return (
    <WYSIWYGEditor
      initialContent={content}
      onChange={setContent}
      toolbarConfig={customConfig}
    />
  );
}

📋 Available Toolbar Presets

  • minimal: Basic formatting (Bold, Italic, Underline)
  • standard: Common features for most use cases
  • full: All features enabled (default)
  • writer_focused: Optimized for content writers
  • social_media: Perfect for social media posts

🎨 Custom Configurations

// Using categories for quick setup
const categoryConfig: ToolbarConfig = {
  groups: [
    { buttons: ['clipboard'] },      // undo, redo
    { buttons: ['basicstyles'] },    // bold, italic, underline, etc.
    { buttons: ['colors'] },         // font and background colors
    { buttons: ['links'] },          // create/remove links
    { buttons: ['insert'] }          // images, tables, special chars
  ]
};

// Excluding specific features
const restrictedConfig: ToolbarConfig = {
  preset: 'standard',
  exclude: ['insertImage', 'uploadFile'] // Remove image features
};

// Adding specific features to a preset
const enhancedConfig: ToolbarConfig = {
  preset: 'minimal',
  include: ['fontColor', 'backgroundColor'] // Add color tools
};

Event Handlers

function EditorWithEvents() {
  const [content, setContent] = useState("");

  const handleFocus = () => {
    console.log("Editor focused");
  };

  const handleBlur = () => {
    console.log("Editor blurred");
  };

  const handleChange = (newContent: string) => {
    console.log("Content changed:", newContent);
    setContent(newContent);
  };

  return (
    <WYSIWYGEditor
      initialContent={content}
      onChange={handleChange}
      onFocus={handleFocus}
      onBlur={handleBlur}
      placeholder="Type something..."
    />
  );
}

API Reference

WYSIWYGEditor Props

| Prop | Type | Default | Description | | ---------------- | --------------------------- | ------------------- | -------------------------------------- | | initialContent | string | '' | Initial HTML content for the editor | | placeholder | string | 'Start typing...' | Placeholder text when editor is empty | | 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 | | toolbarConfig | ToolbarConfig | { preset: 'full' }| Toolbar configuration object |

ToolbarConfigSelector Props

| Prop | Type | Default | Description | | ---------------- | --------------------------- | ------------------------- | ---------------------------------------- | | selectedConfig | string | - | Currently selected configuration key | | onConfigChange | (configKey: string) => void | - | Callback when configuration changes | | label | string | 'Toolbar Configuration:' | Label text for the selector | | showDescription| boolean | true | Whether to show configuration description | | showConfigCode | boolean | false | Whether to show the configuration JSON | | className | string | '' | Additional CSS class name | | style | React.CSSProperties | {} | Additional inline styles |

ToolbarConfig Interface

interface ToolbarConfig {
  preset?: 'minimal' | 'standard' | 'full';
  buttons?: (ToolbarButtonId | ToolbarCategory)[];
  groups?: ToolbarGroup[];
  exclude?: (ToolbarButtonId | ToolbarCategory)[];
  include?: ToolbarButtonId[];
}

Available Components

  • WYSIWYGEditor: Main editor component
  • ToolbarConfigSelector: Interactive toolbar configuration selector
  • Toolbar: Basic toolbar with essential formatting options
  • AdvancedToolbar: Extended toolbar with additional features
  • EditableArea: The contentEditable area (used internally)

ToolbarConfigSelector Component

The ToolbarConfigSelector provides an easy way for users to switch between different toolbar configurations:

import { ToolbarConfigSelector, TOOLBAR_CONFIGURATIONS } from "@prmargas/react-wysiwyg-editor";

function ConfigurableEditor() {
  const [selectedConfig, setSelectedConfig] = useState('standard');
  const [content, setContent] = useState('');

  return (
    <div>
      <ToolbarConfigSelector
        selectedConfig={selectedConfig}
        onConfigChange={setSelectedConfig}
        label="Choose toolbar style:"
        showDescription={true}
        showConfigCode={false}
      />
      
      <WYSIWYGEditor
        initialContent={content}
        onChange={setContent}
        toolbarConfig={TOOLBAR_CONFIGURATIONS[selectedConfig].config}
      />
    </div>
  );
}

Utility Functions

import {
  CommandExecutor,
  contentSanitizer,
  getCurrentSelection,
  restoreSelection,
  TOOLBAR_CONFIGURATIONS,
  resolveToolbarConfig
} from "@prmargas/react-wysiwyg-editor";

// Execute formatting commands programmatically
const executor = CommandExecutor.getInstance();
executor.executeCommand("BOLD");

// Sanitize HTML content
const cleanHtml = contentSanitizer.sanitizeHtml(
  '<script>alert("xss")</script><p>Safe content</p>'
);

// Work with selections
const selection = getCurrentSelection();
// ... modify content ...
restoreSelection(selection);

// Access predefined toolbar configurations
const minimalConfig = TOOLBAR_CONFIGURATIONS.minimal.config;
const standardConfig = TOOLBAR_CONFIGURATIONS.standard.config;

// Resolve custom toolbar configurations
const resolved = resolveToolbarConfig({
  preset: 'standard',
  exclude: ['insertImage']
});

Styling

The editor comes with default styles that you can import:

import "@prmargas/react-wysiwyg-editor/styles";

Custom Styling

You can override the default styles by targeting the CSS classes:

.wysiwyg-editor {
  border: 2px solid #your-color;
  border-radius: 8px;
}

.toolbar {
  background: #your-background;
}

.editable-area {
  min-height: 200px;
  font-family: "Your Font", sans-serif;
}

Link Management

The editor features an intuitive link management system:

Link Preview Popup

When you click on any link in the editor, a popup appears with:

  • Go to link: Click the URL to visit the link in a new tab
  • Change: Edit the link URL with the current value pre-filled
  • Remove: Remove the link while preserving the text

Creating Links

  1. Select text in the editor
  2. Click the link button in the toolbar (or use Ctrl/Cmd + K)
  3. Enter the URL in the modal
  4. The link is created with target="_blank" for security

Editing Links

  1. Click on any link in the editor
  2. Click "Change" in the popup that appears
  3. Modify the URL in the modal (current URL is pre-filled)
  4. Click "Update Link" to save changes

Keyboard Shortcuts

| Shortcut | Action | | -------------- | ----------- | | Ctrl/Cmd + B | Bold | | Ctrl/Cmd + I | Italic | | Ctrl/Cmd + U | Underline | | Ctrl/Cmd + Z | Undo | | Ctrl/Cmd + Y | Redo | | Ctrl/Cmd + K | Insert Link |

Browser Support

  • Chrome 60+
  • Firefox 55+
  • Safari 12+
  • Edge 79+

Security

The editor includes built-in content sanitization to prevent XSS attacks:

  • Removes dangerous HTML tags (<script>, <iframe>, etc.)
  • Sanitizes URLs to prevent javascript: and data: protocols
  • Filters CSS properties to prevent malicious styles
  • Cleans pasted content from external sources

Contributing

  1. Fork the repository
  2. Create your feature branch (git checkout -b feature/amazing-feature)
  3. Commit your changes (git commit -m 'Add some amazing feature')
  4. Push to the branch (git push origin feature/amazing-feature)
  5. Open a Pull Request

Development

# Install dependencies
npm install

# Start development server
npm run dev

# Build library
npm run build

# Run tests
npm test

# Build demo
npm run build:demo

License

MIT License - see the LICENSE file for details.

Recent Updates

Latest Features

  • 🎛️ Configurable Toolbar System: Multiple preset configurations (minimal, standard, full, writer-focused, social media)
  • 🔧 ToolbarConfigSelector Component: Interactive component for switching toolbar configurations
  • 📋 Predefined Configurations: 10+ ready-to-use toolbar layouts for different use cases
  • 🎨 Custom Configuration Support: Create your own toolbar layouts with groups, categories, and exclusions
  • 📚 Enhanced Documentation: Comprehensive guides and examples for toolbar configuration

Previous Features

  • Basic rich text editing functionality
  • Advanced toolbar with color picker
  • Image and file upload support
  • Content sanitization
  • TypeScript support
  • Accessibility features
  • Smart link management with preview popup
  • Table support and special characters
  • Find & replace functionality

🙏 Acknowledgments

  • React Team for the excellent framework
  • React Image Crop for the utility-first styling system
  • DOMPurify for content sanitization

Built with ❤️ using React, TypeScript, and modern web technologies.