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

documint

v0.0.7

Published

A canvas-based, batteries-included markdown editor for React.

Downloads

896

Readme

🌿 Documint

A canvas-based, batteries-included markdown editor for React.

Try it out: Documint playground.

Features

  • Markdown in, markdown out — Documents are parsed from markdown and serialized back to markdown. Full support for CommonMark, GFM tables, task lists, strikethrough, and fenced code blocks with language hints.

  • Rich semantic editing — Context-sensitive behavior that adapts to what you're editing. Enter splits a paragraph but adds a new row in a table. Backspace at the start of a list item dedents it. Tab indents a list but inserts a column in a table. The editor understands the structure of your document, so every gesture does the right thing.

  • Subtle, delightful animations — A typing trail highlights newly inserted text. Deleted text fades out before disappearing. List markers pop into place. Punctuation pulses with a soft ring on keystroke. Small details that make editing feel fun.

  • Mobile-native editing — Responsive layout with full support for iOS and Android gestures: auto-capitalization, auto-correct, auto-scroll on keyboard appearance, shake-to-undo, and selection handles all work as expected.

  • Context-aware toolbars ("leaves") — Floating toolbars that appear based on what you're interacting with: text formatting options on selection, link editing on links, column/row controls on tables, and block insertion (headings, lists, quotes, tables) on empty lines.

  • Configurable themes and keybindings — Ships with built-in light and dark themes, follows the system theme by default, and lets you customize every theme value or start from presets like mint, midnight, and sunrise. Keybindings are configurable too — remap formatting shortcuts, navigation, and list operations to match your users' expectations.

  • Comments and presence for review workflows — Anchor comments to any range of text, with full threading (replies, resolution, deletion) and self-repairing quote-based matching after edits. External user and AI agent presence can be projected into the document as live cursors and viewport indicators without becoming document content.

  • Fast and lightweight — Canvas-based rendering optimized for hot-path performance even on large documents. A custom markdown parser, editor engine, and layout/rendering system all ship in a bundle <70 KB gzipped.

Getting Started

  1. Install the package: npm install documint (or bun add documint)
  2. Import the Documint component from the package
  3. Pass your markdown content to it and listen for changes
import { useState } from "react";
import { Documint } from "documint";

const initialMarkdown = `# Hello Documint

This editor takes markdown in and gives markdown back out.
`;

export function App() {
  const [content, setContent] = useState(initialMarkdown);

  return <Documint content={content} onContentChanged={setContent} />;
}

Custom Themes

By default, Documint will detect the end-user's system theme and apply either the built-in light or dark theme. You can also specify a theme explicitly by passing "light" or "dark" to the theme prop, or provide a custom theme object with your own colors and styles.

import { useState } from "react";
import { Documint, lightTheme } from "documint";

const customTheme = {
  ...lightTheme,
  background: "#fff7ed",
  headingText: "#7c2d12",
  linkText: "#c2410c",
};

export function App() {
  const [content, setContent] = useState("# Themed Documint");

  return <Documint content={content} onContentChanged={setContent} theme={customTheme} />;
}

Custom Storage

If the document includes http-based images, then the editor will automatically load and render them. However, if you want to support pasting images from the clipboard or uploading images from the user's device, you'll need to provide a storage prop that implements the DocumintStorage interface.

import { useState } from "react";
import { Documint, DocumintStorage } from "documint";

function createInMemoryStorage(): DocumintStorage {
  const files = new Map<string, Blob>();

  return {
    async readFile(path) {
      return files.get(path) ?? null;
    },
    async writeFile(file) {
      files.set(file.name, file);
      return file.name;
    },
  };
}

const storage = createInMemoryStorage();

export function App() {
  const [content, setContent] = useState("# Documint with Custom Storage");

  return <Documint content={content} onContentChanged={setContent} storage={storage} />;
}