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

@pawanosman/texteditor

v1.0.1

Published

Advanced text editor React component library with syntax highlighting, custom overlays, and extensive customization options

Readme

@pawanosman/texteditor

npm version License: MIT

An advanced, feature-rich text editor React component library with syntax highlighting, custom overlays, grammar checking support, and extensive customization options.

📦 Installation

npm install @pawanosman/texteditor
# or
yarn add @pawanosman/texteditor
# or
pnpm add @pawanosman/texteditor

✨ Features

  • 🎨 Multiple Editor Modes - Support for plaintext, markdown, code, HTML, CSS, and JSON
  • 🌈 Syntax Highlighting - Built-in support for 25+ programming languages using PrismJS
  • ✏️ Rich Text Editing - Full Markdown support with toolbar buttons for formatting
  • 🎯 Custom Highlights - Add highlights with actions (errors, warnings, suggestions, etc.)
  • 🔲 Custom Overlays - Create custom overlay regions with interactive elements
  • 📝 Grammar-Style Highlights - Built-in support for spelling, grammar, clarity, and tone suggestions
  • 🎛️ Customizable Toolbar - Show/hide built-in buttons or add custom toolbar actions
  • 🌓 Theme Support - Dark, light, and auto (system preference) themes
  • 📏 Line Numbers - Optional line number display
  • 🔍 Find & Replace - Built-in find and replace functionality
  • ⌨️ Keyboard Shortcuts - Comprehensive keyboard shortcut support
  • 🌐 RTL Support - Full right-to-left text direction support
  • 🎨 Font Configuration - Customize font family, size, weight, and more
  • 📱 Responsive Design - Works seamlessly on desktop and mobile devices
  • Accessibility - Built with accessibility in mind

📦 Installation

npm install @pawanosman/texteditor
# or
yarn add @pawanosman/texteditor
# or
pnpm add @pawanosman/texteditor

🚀 Quick Start

import React, { useState } from 'react';
import { TextEditor } from '@pawanosman/texteditor';
import '@pawanosman/texteditor/styles.css';

function App() {
  const [value, setValue] = useState('// Start coding...\nconsole.log("Hello World!");');

  return (
    <TextEditor
      value={value}
      onChange={setValue}
      mode="code"
      language="javascript"
      minHeight={400}
      theme="dark"
    />
  );
}

📖 API Reference

Props

| Prop | Type | Default | Description | |------|------|---------|-------------| | value | string | - | Controlled editor value | | defaultValue | string | "" | Initial value for uncontrolled editor | | onChange | (value: string) => void | - | Called when editor content changes | | mode | EditorMode | "plaintext" | Editor mode (plaintext, markdown, code, html, css, json) | | language | CodeLanguage | "javascript" | Programming language for syntax highlighting (when mode is "code") | | highlights | Highlight[] | - | Array of highlights to display | | onHighlightsChange | (highlights: Highlight[]) => void | - | Called when highlights change | | overlays | CustomOverlay[] | - | Array of custom overlays to display | | onOverlaysChange | (overlays: CustomOverlay[]) => void | - | Called when overlays change | | placeholder | string | "Start typing..." | Placeholder text | | readOnly | boolean | false | Make editor read-only | | disabled | boolean | false | Disable editor | | minHeight | number \| string | 200 | Minimum height of editor | | maxHeight | number \| string | - | Maximum height of editor | | showLineNumbers | boolean | true | Show line numbers | | showToolbar | boolean | true | Show toolbar | | showStatusBar | boolean | true | Show status bar | | renderInlineFormatting | boolean | true | Render inline formatting in markdown mode | | toolbarConfig | ToolbarConfig | - | Toolbar configuration | | direction | TextDirection | "ltr" | Text direction (ltr, rtl, auto) | | fontConfig | FontConfig | - | Font configuration | | theme | ThemeMode | "dark" | Theme mode (light, dark, auto) | | className | string | - | Additional CSS class | | style | React.CSSProperties | - | Additional inline styles |

Ref API

The editor exposes methods through a ref:

import { useRef } from 'react';
import { TextEditor, TextEditorRef } from '@pawanosman/texteditor';

const editorRef = useRef<TextEditorRef>(null);

// Methods
editorRef.current?.getValue(); // Get current value
editorRef.current?.setValue('new value'); // Set value
editorRef.current?.insertText('text'); // Insert text at cursor
editorRef.current?.getSelection(); // Get selection range
editorRef.current?.setSelection(start, end); // Set selection
editorRef.current?.focus(); // Focus editor
editorRef.current?.blur(); // Blur editor
editorRef.current?.addHighlight(highlight); // Add highlight
editorRef.current?.removeHighlight(id); // Remove highlight
editorRef.current?.clearHighlights(); // Clear all highlights
editorRef.current?.addOverlay(overlay); // Add overlay
editorRef.current?.removeOverlay(id); // Remove overlay
editorRef.current?.clearOverlays(); // Clear all overlays
editorRef.current?.setMode(mode); // Set editor mode
editorRef.current?.setLanguage(language); // Set language

🎨 Editor Modes

Code Mode

<TextEditor
  mode="code"
  language="typescript"
  value="// Your TypeScript code..."
/>

Supported languages: javascript, typescript, python, java, csharp, cpp, c, go, rust, ruby, php, swift, kotlin, sql, html, css, scss, json, yaml, xml, markdown, bash, shell, powershell, dockerfile, plaintext

Markdown Mode

<TextEditor
  mode="markdown"
  value="# Hello\nThis is **bold** text."
/>

Other Modes

<TextEditor mode="html" />
<TextEditor mode="css" />
<TextEditor mode="json" />
<TextEditor mode="plaintext" />

🎯 Highlights

Highlights allow you to mark regions of text with different styles and optional actions:

import { Highlight } from '@pawanosman/texteditor';

const [highlights, setHighlights] = useState<Highlight[]>([
  {
    id: 'error-1',
    start: 10,
    end: 20,
    type: 'error',
    message: 'Syntax error',
    description: 'Unexpected token',
    suggestion: 'Fix the syntax',
    actions: [
      {
        label: 'Fix',
        onClick: (highlight) => console.log('Fixing', highlight),
        variant: 'primary'
      }
    ]
  }
]);

<TextEditor
  highlights={highlights}
  onHighlightsChange={setHighlights}
/>

Highlight Types

  • highlight - General yellow highlight
  • error - Red error highlight
  • warning - Orange warning highlight
  • success - Green success highlight
  • info - Blue info highlight
  • spelling - Spelling mistake (red)
  • grammar - Grammar error (red)
  • punctuation - Punctuation issue (red)
  • clarity - Clarity suggestion (blue)
  • conciseness - Conciseness suggestion (blue)
  • readability - Readability issue (blue)
  • vocabulary - Vocabulary improvement (green)
  • engagement - Engagement suggestion (green)
  • tone - Tone adjustment (purple)
  • formality - Formality level (purple)
  • politeness - Politeness suggestion (purple)
  • inclusive - Inclusive language (purple)

🔲 Custom Overlays

Overlays provide more customization than highlights:

import { CustomOverlay } from '@pawanosman/texteditor';

const [overlays, setOverlays] = useState<CustomOverlay[]>([
  {
    id: 'overlay-1',
    start: 50,
    end: 100,
    className: 'my-custom-overlay',
    style: {
      background: 'rgba(168, 85, 247, 0.3)',
      borderBottom: '2px dashed #a855f7'
    },
    title: 'AI Suggestion',
    description: 'Consider improving this section',
    actions: [
      {
        label: 'Accept',
        onClick: (overlay) => console.log('Accepted', overlay)
      }
    ],
    onClick: (overlay, event) => console.log('Clicked', overlay)
  }
]);

<TextEditor
  overlays={overlays}
  onOverlaysChange={setOverlays}
/>

🎛️ Toolbar Customization

Hide/Show Built-in Buttons

const toolbarConfig: ToolbarConfig = {
  visibleButtons: ['bold', 'italic', 'underline'], // Only show these
  // or
  hiddenButtons: ['strikethrough', 'codeblock'], // Hide these
  showGroupSeparators: true
};

<TextEditor toolbarConfig={toolbarConfig} />

Available built-in buttons: undo, redo, bold, italic, underline, strikethrough, code, codeblock, link, image, quote, list, numbered-list, task-list, heading1, heading2, heading3, horizontal-rule, indent, outdent, highlight, error-highlight, clear-highlights, find-replace, table

Add Custom Buttons

const toolbarConfig: ToolbarConfig = {
  customButtons: [
    {
      id: 'timestamp',
      label: 'Timestamp',
      tooltip: 'Insert current timestamp',
      icon: <ClockIcon />,
      group: 'custom',
      action: (context) => {
        const timestamp = new Date().toISOString();
        context.setValue(
          context.value.substring(0, context.selection.end) +
          timestamp +
          context.value.substring(context.selection.end)
        );
      },
      disabled: (context) => context.readOnly,
      active: (context) => false
    }
  ]
};

🎨 Theming

Built-in Themes

<TextEditor theme="dark" />    // Dark theme (default)
<TextEditor theme="light" />   // Light theme
<TextEditor theme="auto" />    // Follow system preference

Custom CSS Variables

You can customize the appearance using CSS variables:

.te-editor-container {
  --te-bg-primary: #0a0a0b;
  --te-bg-secondary: #18181b;
  --te-bg-tertiary: #27272a;
  --te-border: #3f3f46;
  --te-text-primary: #fafafa;
  --te-text-secondary: #a1a1aa;
  --te-text-tertiary: #71717a;
  --te-accent: #3b82f6;
  --te-accent-hover: #2563eb;
  --te-font-mono: 'JetBrains Mono', monospace;
  --te-font-sans: 'Inter', sans-serif;
  --te-font-size: 13px;
  --te-line-height: 1.6;
}

🎨 Font Configuration

const fontConfig: FontConfig = {
  fontFamily: '"JetBrains Mono", monospace',
  fontSize: 14,
  fontWeight: 400,
  lineHeight: 1.6,
  letterSpacing: '0.5px',
  fontStyle: 'normal',
  uiFontFamily: '"Inter", sans-serif'
};

<TextEditor fontConfig={fontConfig} />

⌨️ Keyboard Shortcuts

| Shortcut | Action | |----------|--------| | Ctrl + Z | Undo | | Ctrl + Y | Redo | | Ctrl + B | Bold | | Ctrl + I | Italic | | Ctrl + U | Underline | | Ctrl + E | Inline Code | | Ctrl + K | Link | | Ctrl + F | Find/Replace | | Ctrl + Shift + S | Strikethrough | | Ctrl + Shift + K | Code Block | | Ctrl + Shift + Q | Quote | | Ctrl + Shift + U | List | | Ctrl + Shift + O | Numbered List | | Escape | Close panels/popups |

🌍 RTL Support

<TextEditor direction="rtl" />    // Right-to-left
<TextEditor direction="ltr" />    // Left-to-right (default)
<TextEditor direction="auto" />   // Auto-detect

📝 Examples

Grammar Checker Integration

function GrammarCheckerEditor() {
  const [highlights, setHighlights] = useState<Highlight[]>([]);
  
  const checkGrammar = async (text: string) => {
    const results = await grammarService.check(text);
    const newHighlights = results.map(error => ({
      id: `grammar-${error.id}`,
      start: error.start,
      end: error.end,
      type: error.type, // 'spelling', 'grammar', 'clarity', etc.
      message: error.message,
      suggestion: error.suggestion,
      suggestions: error.alternatives
    }));
    setHighlights(newHighlights);
  };
  
  return (
    <TextEditor
      highlights={highlights}
      onHighlightsChange={setHighlights}
      onChange={checkGrammar}
    />
  );
}

AI-Powered Writing Assistant

function AIWritingAssistant() {
  const [overlays, setOverlays] = useState<CustomOverlay[]>([]);
  
  const addAISuggestion = (selection: { start: number, end: number }) => {
    const overlay: CustomOverlay = {
      id: `ai-${Date.now()}`,
      start: selection.start,
      end: selection.end,
      className: 'ai-suggestion',
      title: 'AI Suggestion',
      description: 'Click to see AI-powered improvements',
      actions: [
        {
          label: 'Improve',
          variant: 'primary',
          onClick: async (overlay) => {
            const improved = await aiService.improve(text);
            // Apply improvement...
          }
        }
      ]
    };
    setOverlays(prev => [...prev, overlay]);
  };
  
  return <TextEditor overlays={overlays} />;
}

Collaborative Editor

function CollaborativeEditor() {
  const [cursors, setCursors] = useState<UserCursor[]>([]);
  const [highlights, setHighlights] = useState<Highlight[]>([]);
  
  // Simulate remote user selections
  useEffect(() => {
    socket.on('user-selection', (user: User) => {
      const overlay: CustomOverlay = {
        id: `cursor-${user.id}`,
        start: user.selection.start,
        end: user.selection.end,
        className: 'remote-cursor',
        style: { 
          backgroundColor: user.color,
          opacity: 0.3 
        },
        title: user.name
      };
      setOverlays(prev => [...prev.filter(o => !o.id.startsWith(`cursor-${user.id}`)), overlay]);
    });
  }, []);
  
  return <TextEditor overlays={overlays} />;
}

🤝 Contributing

We welcome contributions! Please see our Contributing Guide for details.

📄 License

MIT © Pawan Osman

🙏 Acknowledgments

📚 More Examples

For more comprehensive examples, check out our Examples Page or run the demo locally:

git clone https://github.com/PawanOsman/TextEditor.git
cd TextEditor
npm install
npm run dev

Made with ❤️ by Pawan Osman