npm package: @prmargas/react-wysiwyg-editor
Description: A lightweight, extensible WYSIWYG editor built with React and TypeScript
Author: Pradeep Margasahayam Prakash
Latest version: 1.0.2

# WYSIWYG Editor

![React](https://img.shields.io/badge/React-18.2.0-61dafb.svg)
![TypeScript](https://img.shields.io/badge/TypeScript-5.2.2-3178c6.svg)

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

```bash
npm i @prmargas/react-wysiwyg-editor
```

## 🚀 Quick Start

### Basic Usage

```tsx
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

```tsx
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:

```tsx
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

```tsx
// 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

```tsx
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

```tsx
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:

```tsx
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

```tsx
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:

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

### Custom Styling

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

```css
.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

```bash
# 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](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.**