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

@veztraa/editor

v0.1.1

Published

Full-featured WYSIWYG rich text editor as a standalone React component — toolbar, source view, HTML sanitizer, dark mode.

Readme

@veztraa/editor

Documentation & Live Demo →

A full-featured, zero-config WYSIWYG rich-text editor as a single React component. Drop <Editor /> into any React app and your users get a modern editing experience in seconds — a Notion-style slash menu, a floating selection toolbar, Markdown shortcuts, a full emoji picker, live code-block syntax highlighting, image uploads, and clean semantic HTML out.

TypeScript-first, framework-agnostic (React 18 & 19, Next.js App Router, Vite), dark mode built in. Styles auto-inject on mount — no CSS import required.

Installation

npm install @veztraa/editor

Quick start

import { useState } from "react";
import { Editor } from "@veztraa/editor"; // styles auto-inject — no CSS import

export default function App() {
  const [html, setHtml] = useState("<p>Hello world</p>");
  return <Editor value={html} onChange={setHtml} height={400} />;
}

Modal mode

<EditorModal /> renders in a fullscreen portal and commits changes only when the user clicks Done.

import { EditorModal } from "@veztraa/editor";

{open && (
  <EditorModal
    value={content}
    onChange={(html) => { save(html); setOpen(false); }}
    onClose={() => setOpen(false)}
    title="Edit content"
  />
)}

Features

  • Slash menu — type / for headings, lists, tables, images, code blocks, and more
  • Bubble toolbar — a formatting bar that appears over selected text
  • Markdown shortcuts — #, -, 1., >, ```, **bold**, *italic*, `code`, ~~strike~~ format as you type
  • Emoji picker — the full 1,900+ Unicode set in a categorized grid, plus :shortcode: autocomplete
  • Code blocks — live syntax highlighting
  • Autolink — URLs become links as you type
  • URL auto-embed — paste a YouTube/Vimeo link → a responsive, sandboxed embed
  • Images — drag-drop, paste (incl. screenshots), or the toolbar button; inline base64 by default or upload to your server via onImageUpload
  • Tables, text/background color, alignment, indent, sub/superscript, find & replace, print
  • Character limit with a live counter (maxLength)
  • Extensible — add your own slash commands and toolbar buttons
  • Clean output — semantic HTML via onChange, plus a sanitizeHtml() helper
  • Dark & light themes, one-hex accentColor, controlled or uncontrolled

Framework notes

  • Vite / CRA — import and use, nothing extra.
  • Next.js (App Router) — the editor renders on the client. Mark the file "use client", or import it with next/dynamic and { ssr: false }. Importing the package in a server file is safe (it touches no DOM at import time). No CSS import is needed — styles inject on first render.
  • sanitizeHtml() runs in the browser — your editor value already lives client-side, so sanitize there before submitting.

Key props

| Prop | Type | Description | |---|---|---| | value | string | HTML content (controlled). | | onChange | (html: string) => void | Fires on every change with the current HTML. | | placeholder | string | Placeholder shown when empty. | | height | number \| string | Editor height (px number or any CSS value). | | theme | "light" \| "dark" | Controlled color theme. | | readOnly | boolean | Display content without editing. | | accentColor | string | 6-digit hex driving buttons, focus rings, active states. | | maxLength | number | Hard character cap; the counter turns red at the limit. | | onImageUpload | (file: File) => Promise<string> \| string | Upload handler for dropped/pasted/picked images; return the hosted URL. Omit to inline as base64. | | slashCommands | SlashCommand[] | Extra entries for the / menu. | | toolbarButtons | ToolbarButton[] | Extra toolbar buttons (icon + action). | | onFocus / onBlur | () => void | Focus / blur of the editing area. | | onLinkClick | (href, event) => void | Link clicks; call event.preventDefault() to handle navigation yourself. | | slashMenu / bubbleToolbar / statusBar | boolean | Toggle the premium UI layers (all default true). | | config | object | Passthrough to the underlying engine options. |

EditorProps, EditorModalProps, SlashCommand, and ToolbarButton are all exported.

Recipes

Upload images to your server

<Editor
  value={html}
  onChange={setHtml}
  onImageUpload={async (file) => {
    const body = new FormData();
    body.append("file", file);
    const res = await fetch("/api/upload", { method: "POST", body });
    const { url } = await res.json();
    return url; // inserted as <img src={url}>
  }}
/>

Custom slash commands

<Editor
  value={html}
  onChange={setHtml}
  slashCommands={[
    {
      title: "Callout",
      description: "Highlighted note box",
      action: ({ insertHTML }) =>
        insertHTML("<blockquote>💡 <strong>Note:</strong> …</blockquote>"),
    },
  ]}
/>

Custom toolbar buttons

<Editor
  value={html}
  onChange={setHtml}
  toolbarButtons={[
    {
      name: "insertDate",
      tooltip: "Insert today's date",
      iconSvg: '<svg class="rte-mico" viewBox="0 0 24 24"><rect x="3" y="4" width="18" height="18" rx="2"/><path d="M3 10h18"/></svg>',
      exec: ({ insertText }) => insertText(new Date().toLocaleDateString()),
    },
  ]}
/>

Sanitize before you store

import { sanitizeHtml } from "@veztraa/editor";

const clean = sanitizeHtml(dirtyHtml); // allowlist: safe tags, attrs & styles only

License

MIT © Veztraa Solutions. This package bundles a modified third-party editor engine under its own MIT license; see THIRD-PARTY-NOTICES.txt.