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

nextext-editor

v0.1.3

Published

A modern, customizable rich text editor for React with shadcn/ui patterns, Tailwind CSS styling, and collaborative editing powered by Loro CRDT

Readme

NextText Editor

A modern, customizable rich text editor for React with shadcn/ui patterns, Tailwind CSS styling, and collaborative editing powered by Loro CRDT.

npm version

Preview

NextText Editor Screenshot

Features

  • 🎨 Rich Formatting - Bold, italic, underline, strikethrough, inline code, text color, and highlighting
  • 📝 Block Types - Headings (H1-H6), paragraphs, bullet lists, numbered lists, blockquotes, code blocks, horizontal rules
  • 🖼️ Media Support - Image upload with drag-and-drop (max 5MB, auto-styled)
  • 📊 Tables - Insert and edit tables with styled cells
  • 🔄 Built-in Collaboration - Loro CRDT for conflict-free real-time editing
  • 🎨 Customizable Design - shadcn/ui-inspired design tokens for easy theming
  • 📱 Responsive - Works seamlessly on desktop and mobile
  • ⌨️ Keyboard Shortcuts - Familiar shortcuts (Ctrl/Cmd+B, I, U, Z, Y)
  • 🔍 Live Preview - View your content in HTML, Text, or JSON format
  • 📊 Word & Character Count - Real-time statistics display
  • 🎯 TypeScript - Fully typed for better DX

Installation

npm install nextext-editor
# or
yarn add nextext-editor
# or
pnpm add nextext-editor

Quick Start

Basic Usage

import { EditorBlock } from 'nextext-editor';
import 'nextext-editor/styles.css';

function App() {
  return <EditorBlock placeholder="Start writing..." />;
}

With Preview Panel

import { EditorBlock } from 'nextext-editor';
import 'nextext-editor/styles.css';

function App() {
  return (
    <EditorBlock
      showPreview
      placeholder="Start writing..."
    />
  );
}

Controlled Mode with External State

import { useState } from 'react';
import { EditorBlock } from 'nextext-editor';
import 'nextext-editor/styles.css';

function App() {
  const [content, setContent] = useState('<p>Initial content</p>');

  return (
    <EditorBlock
      externalContent={content}
      onContentChange={setContent}
      showPreview
    />
  );
}

Using Loro CRDT for Collaboration

import { useLoroEditor, EditorBlock } from 'nextext-editor';
import 'nextext-editor/styles.css';

function CollaborativeEditor() {
  const { content, updateContent, loroDoc } = useLoroEditor();

  // Share loroDoc with other clients for real-time sync

  return (
    <EditorBlock
      externalContent={content}
      onContentChange={updateContent}
    />
  );
}

Using Editor Directly (Headless)

If you want to build your own toolbar and UI, use the low-level Editor component:

import { useState } from 'react';
import { Editor } from 'nextext-editor';
import 'nextext-editor/styles.css';

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

  return (
    <div>
      <div className="my-custom-toolbar">
        <button onClick={() => document.execCommand('bold')}>Bold</button>
        <button onClick={() => document.execCommand('italic')}>Italic</button>
      </div>
      <Editor
        content={content}
        onContentChange={setContent}
        placeholder="Write something..."
      />
    </div>
  );
}

Tech Stack

  • React 18 - UI framework
  • TypeScript - Type safety
  • Loro CRDT - Conflict-free collaboration
  • Tailwind CSS v4 - Styling
  • Lucide React - Icons
  • Vite - Build tool

API Reference

Editor Props (Core ContentEditable Component)

| Prop | Type | Default | Description | |------|------|---------|-------------| | content | string | required | HTML content to display | | onContentChange | (html: string) => void | required | Called when content changes | | placeholder | string | "Start typing..." | Placeholder text when empty | | className | string | - | Custom class for the editable area | | tokens | EditorTokens | editorTokens | Custom design tokens |

EditorBlock Props (Complete Editor with Toolbar & Preview)

| Prop | Type | Default | Description | |------|------|---------|-------------| | initialContent | string | - | Initial HTML content | | showPreview | boolean | false | Show live preview panel | | showToolbar | boolean | true | Show formatting toolbar | | externalContent | string | - | Controlled content (for controlled mode) | | onContentChange | (html: string) => void | - | Content change callback | | className | string | - | Custom container class | | placeholder | string | "Start typing..." | Placeholder text | | tokens | EditorTokens | editorTokens | Custom design tokens |

useLoroEditor Hook

Returns an object with:

{
  content: string;              // Current HTML content
  format: TextFormat;           // Current text format state
  updateContent: (html: string) => void;  // Update content
  insertText: (text: string, position?: number) => void;  // Insert text
  deleteText: (start: number, length: number) => void;  // Delete text
  applyFormat: (start: number, end: number, format: TextFormat) => void;  // Apply formatting
  getSnapshot: () => Uint8Array;  // Export Loro snapshot
  loadSnapshot: (snapshot: Uint8Array) => void;  // Import Loro snapshot
  loroDoc: Loro | null;         // Raw Loro document instance
}

Design Tokens

Customize the editor's appearance by passing custom tokens:

import { EditorBlock, editorTokens } from 'nextext-editor';

const customTokens = {
  ...editorTokens,
  container: {
    ...editorTokens.container,
    base: 'w-full bg-slate-900 rounded-xl border border-slate-700',
  },
  editor: {
    ...editorTokens.editor,
    base: 'min-h-[500px] p-8 text-slate-100',
  },
};

function App() {
  return <EditorBlock tokens={customTokens} />;
}

Toolbar Actions

The editor supports these formatting actions:

Text Formatting

  • bold - Toggle bold text
  • italic - Toggle italic text
  • underline - Toggle underline
  • strikethrough - Toggle strikethrough
  • code - Toggle inline code
  • textColor - Change text color
  • highlight - Change background color
  • clearMarks - Remove all formatting

Block Types

  • paragraph - Normal paragraph
  • h1, h2, h3, h4, h5, h6 - Headings
  • bulletList - Unordered list
  • numberedList - Ordered list
  • codeBlock - Code block
  • blockquote - Blockquote
  • clearNodes - Reset to paragraph

Content

  • image - Upload image (max 5MB)
  • table - Insert 3x3 table
  • horizontalRule - Insert horizontal line
  • hardBreak - Insert line break

History

  • undo - Undo last change
  • redo - Redo last change

Keyboard Shortcuts

  • Ctrl/Cmd + B - Bold
  • Ctrl/Cmd + I - Italic
  • Ctrl/Cmd + U - Underline
  • Ctrl/Cmd + Z - Undo
  • Ctrl/Cmd + Y - Redo

Architecture

The editor follows a clean component hierarchy:

Editor (Core - in components/)
└── Low-level contentEditable component
    └── Handles HTML editing, cursor management, keyboard events

EditorBlock (Complete Editor - in block/)
├── Uses Editor component
├── Adds Toolbar
├── Adds Preview panel
├── Adds word/character count
└── Integrates with Loro CRDT via useLoroEditor hook

File Structure:

src/
├── components/
│   ├── Editor.tsx          ← Core contentEditable (low-level)
│   ├── Toolbar.tsx
│   ├── Preview.tsx
│   └── ...
├── block/
│   └── EditorBlock.tsx     ← Complete editor (high-level)
├── hooks/
│   └── useLoroEditor.ts
└── index.ts

Exported Components

import {
  Editor,           // Core contentEditable component (low-level)
  EditorBlock,      // Complete editor with toolbar & preview (high-level)
  Toolbar,          // Formatting toolbar component
  Preview,          // Preview panel component
  ColorPicker,      // Color picker dropdown
  HeadingSelector,  // Heading selector dropdown
} from 'nextext-editor';

Exported Utilities

import {
  useLoroEditor,    // Loro CRDT hook
  editorTokens,     // Default design tokens
  cn,               // className utility (clsx + tailwind-merge)
} from 'nextext-editor';

TypeScript Types

import type {
  TextFormat,       // Text formatting state
  EditorState,      // Editor state
  ToolbarAction,    // Toolbar action types
  PreviewMode,      // Preview mode ('html' | 'text' | 'json')
  EditorTokens,     // Design tokens type
  EditorBlockProps, // EditorBlock props
} from 'nextext-editor';

License

MIT © NaveenChand

Contributing

Contributions are welcome! Please check out the GitHub repository.

Support