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

@richkitjs/editors

v0.5.0

Published

Ready-made React editors for RichKit — minimal, simple, HTML, Markdown, mentions, comment box and find & replace — each a form input with value/onChange.

Readme

@richkitjs/editors

Ready-made React editors for RichKit. Each one works like a form input: value in, onChange out.

| Component | What it is | | ------------------- | ----------------------------------------------------------- | | MinimalEditor | Paragraphs, bold, italic, links; bubble menu only | | MarkdownEditor | Rich editing beside live Markdown source; value is Markdown | | HtmlEditor | Rich editing beside live HTML source | | MentionsEditor | Chat composer: @ mentions, Enter sends | | CommentBoxEditor | Reply box with a character limit | | FindReplaceEditor | Editor under an always-open find and replace bar |

MIT, free for any use. The Simple, Notion, Classic, Question, Comments, Track changes, DOCX and Agent editors are RichKit Pro, in @richkitjs/editors-pro.

Install

npm install @richkitjs/editors
import '@richkitjs/editors/style.css'

Mount <NotificationsHost /> once near your app root. The link, image and prompt dialogs render through it:

import { NotificationsHost } from '@richkitjs/editors'

Use it like an input

import { useState } from 'react'
import { MinimalEditor } from '@richkitjs/editors'

function PostForm() {
  const [body, setBody] = useState('<p>Hello</p>')
  return <MinimalEditor value={body} onChange={setBody} />
}

An empty document reads as '', not <p></p>, so required and dirty checks behave like they do for a <textarea>. When the parent changes value (a form reset, a loaded record), the editor replaces its content. It does not fire onChange for that and does not add it to undo history. When value is only the editor's own onChange coming back, nothing happens, so the caret does not jump.

react-hook-form

<Controller
  name="description"
  control={control}
  rules={{ required: true }}
  render={({ field, fieldState }) => <MinimalEditor {...field} aria-invalid={!!fieldState.error} />}
/>

field.ref gets a handle with focus(), so focus-on-error works.

Native forms

<form action="/posts" method="post">
  <MinimalEditor name="body" defaultValue="" />
  <button>Save</button>
</form>

name renders a hidden input that holds the current value.

Shared props

| Prop | Type | | | ----------------------------- | ------------------------------------------ | ---------------------------------------------------------- | | value / defaultValue | string (or JSON with format="json") | controlled / uncontrolled content | | onChange | (value) => void | after every edit | | format | 'html' \| 'markdown' \| 'text' \| 'json' | default 'html' (MarkdownEditor: markdown) | | onBlur / onFocus | () => void | | | name | string | hidden input for native form submit | | disabled / readOnly | boolean | toggles in place, no rebuild | | placeholder | string | | | autoFocus | boolean | | | theme | 'light' \| 'dark' | | | className / style | | on the root element | | aria-label / aria-invalid | | on the editable element | | onEditorReady | (editor: Editor) => void | the live editor, for any command | | ref | EditorHandle | editor, focus, blur, getValue, setValue, clear |

clear() fires onChange with ''. setValue() does not — like a new value from the parent, it is for uncontrolled editors; a controlled one should change value instead.

MarkdownEditor keeps formulas as $…$ and $$…$$. To render them, load the math styles: import '@richkitjs/extension-math/style.css'.

Each editor also has its own props, for example MentionsEditor's mentions or CommentBoxEditor's limit. All of them are typed and documented in the package's type definitions.

Build your own

The components are built from @richkitjs/react. useControlledEditor gives any custom editor the same input contract:

import { useControlledEditor, EditorContent } from '@richkitjs/react'
import { StarterKit } from '@richkitjs/starter-kit'

function MyEditor({ value, onChange }: { value: string; onChange: (html: string) => void }) {
  const editor = useControlledEditor({ extensions: StarterKit, value, onChange })
  return <EditorContent editor={editor} />
}

License

MIT — free for any use, commercial or not.