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

react-latex-editor

v2.0.5

Published

A professional React rich text editor with mathematical equation support, built on TipTap with MathLive integration. Production-ready with TypeScript support, accessibility features, and industrial-grade error handling.

Readme

react-latex-editor

npm version npm downloads license TypeScript

A React WYSIWYG editor with first-class LaTeX math support. Built on TipTap with MathLive for equation authoring and MathJax for read-only rendering.

npm · Issues · Changelog


Features

  • Rich text — bold, italic, underline, strike, colors, fonts, headings, lists, links, code blocks, blockquotes
  • Mathematics — inline and display equations via MathLive; persists as HTML for round-trip editing
  • Tables — insert, resize, and edit with row/column controls
  • Images — upload, URL, drag-and-drop, resize, and alignment
  • SVG — paste SVG markup from the toolbar, or insert programmatically
  • YouTube — embed and resize videos
  • Viewer — read-only rendering with MathJax
  • TypeScript — full type definitions included
  • Accessible toolbar — keyboard shortcuts and ARIA labels

Installation

npm install react-latex-editor

Peer dependencies: React 18+ or 19+

npm install react react-dom

Import styles once in your app entry (or layout):

import "react-latex-editor/styles";

Quick start

import { useRef, useState } from "react";
import { Editor, Viewer, type EditorRef } from "react-latex-editor";
import "react-latex-editor/styles";

export default function App() {
  const [content, setContent] = useState("<p></p>");
  const editorRef = useRef<EditorRef>(null);

  return (
    <>
      <Editor
        ref={editorRef}
        initialContent={content}
        onChange={setContent}
        placeholder="Start writing…"
        minHeight="320px"
      />
      <Viewer content={content} />
    </>
  );
}

Next.js

This package uses browser APIs (DOM, MathLive). Load it on the client only.

App Router — mark the module as a client component:

"use client";

import { useState } from "react";
import { Editor } from "react-latex-editor";
import "react-latex-editor/styles";

export default function MyEditor() {
  const [content, setContent] = useState("<p></p>");
  return <Editor initialContent={content} onChange={setContent} />;
}

Pages Router — disable SSR for the editor:

import dynamic from "next/dynamic";

const Editor = dynamic(
  () => import("react-latex-editor").then((m) => m.Editor),
  { ssr: false },
);

Usage

Editor ref

const editorRef = useRef<EditorRef>(null);

editorRef.current?.getHTML();
editorRef.current?.getJSON();
editorRef.current?.getText();
editorRef.current?.setContent("<p>Hello</p>");
editorRef.current?.clearContent();
editorRef.current?.focus();

// Images
editorRef.current?.addImage("https://example.com/photo.png");
editorRef.current?.addImage({
  src: "https://example.com/diagram.svg",
  mediaType: "svg",
  alt: "Diagram",
});

// SVG markup (same path as the toolbar “Paste SVG code” button)
await editorRef.current?.addSvg(`<svg xmlns="http://www.w3.org/2000/svg">…</svg>`);

// Files from your own <input type="file">
await editorRef.current?.addImagesFromFiles(fileList);

Mathematics

Use the equation button in the toolbar (or Ctrl/Cmd+M). Equations can be inline or display mode. Content is stored in the document HTML so getHTML() / setContent() round-trip correctly.

Images and SVG

| Action | Behavior | | --- | --- | | Insert image (toolbar) | Built-in picker (file / URL) unless you pass onImageSelectionRequest | | Paste SVG code (toolbar) | Opens a dialog to paste <svg>…</svg> markup — no extra setup | | Paste / drop | Image and SVG files, plus SVG markup, work in the editor surface | | Custom upload UI | Provide onImageSelectionRequest, then call addImage / addImagesFromFiles / addSvg on the ref |

import { useRef } from "react";
import { Editor, IMAGE_ACCEPT, type EditorRef } from "react-latex-editor";

function EditorWithCustomUpload() {
  const editorRef = useRef<EditorRef>(null);
  const inputRef = useRef<HTMLInputElement>(null);

  return (
    <>
      <input
        ref={inputRef}
        type="file"
        accept={IMAGE_ACCEPT}
        multiple
        hidden
        onChange={async (e) => {
          if (e.target.files?.length) {
            await editorRef.current?.addImagesFromFiles(e.target.files);
          }
          e.target.value = "";
        }}
      />
      <Editor
        ref={editorRef}
        onImageSelectionRequest={() => inputRef.current?.click()}
      />
    </>
  );
}

Viewer

import { Viewer } from "react-latex-editor";

<Viewer
  content={html}
  className="viewer-shell"
  contentClassName="prose max-w-none"
  enableMath
/>
  • className — wrapper element
  • contentClassName — content root (prefer this for typography)

API

Editor props

| Prop | Type | Default | Description | | --- | --- | --- | --- | | initialContent | string | "<p></p>" | Initial HTML | | onChange | (html: string) => void | — | Fires on every update | | placeholder | string | "Start typing..." | Empty-state placeholder | | readOnly | boolean | false | Disable editing | | autoFocus | boolean | false | Focus on mount | | className | string | "" | Extra class on the editor | | minHeight | string | "300px" | Minimum editor height | | maxHeight | string | — | Max height (scrollable) | | showCharacterCount | boolean | true | Footer character / word stats | | showTableControls | boolean | true | Table editing chrome | | onImageSelectionRequest | () => void | — | Custom image picker; omit for built-in | | onError | (error: Error) => void | — | Error callback |

EditorRef methods

| Method | Signature | Description | | --- | --- | --- | | getHTML | () => string | Serialized HTML | | getJSON | () => Record<string, unknown> | TipTap JSON document | | getText | () => string | Plain text | | setContent | (content: string) => void | Replace document | | clearContent | () => void | Empty the editor | | focus / blur | () => void | Focus management | | isEmpty | () => boolean | Whether the doc is empty | | getEditor | () => Editor \| null | Underlying TipTap instance | | addImage | (input: ImageInsertInput) => void | Insert image(s) or SVG figures | | addSvg | (source: string \| File, options?) => Promise<void> | Insert SVG from markup, URL, or file | | addImagesFromFiles | (files: FileList \| File[]) => Promise<void> | Insert from a file list (data URLs) |

Viewer props

| Prop | Type | Default | Description | | --- | --- | --- | --- | | content | string | — | HTML to display | | className | string | "" | Wrapper class | | contentClassName | string | "" | Content class | | enableMath | boolean | true | Enable MathJax | | mathJaxConfig | object | {} | MathJax overrides |

Notable exports

import {
  Editor,
  Viewer,
  IMAGE_ACCEPT,
  insertMath,
  insertSvg,
  addImagesFromFiles,
  type EditorProps,
  type EditorRef,
  type ImageInsertItem,
  type ImageInsertInput,
} from "react-latex-editor";

Examples

Minimal

<Editor onChange={setContent} showCharacterCount={false} showTableControls={false} />

Fixed height

<Editor minHeight="400px" maxHeight="640px" onChange={setContent} />

Math-heavy content

<Editor
  initialContent="<p>Quadratic formula: </p>"
  placeholder="Write with equations…"
  onChange={setContent}
/>

Styled viewer

<Viewer
  content={content}
  className="rounded-lg bg-neutral-50 p-6"
  contentClassName="text-lg leading-relaxed"
/>

Troubleshooting

| Issue | Fix | | --- | --- | | Unstyled editor | Import react-latex-editor/styles | | Next.js window is not defined | Use "use client" or dynamic(..., { ssr: false }) | | Math missing in Viewer | Keep enableMath enabled (default); check that content includes math nodes from the Editor | | Custom image button does nothing | Call addImagesFromFiles / addImage / addSvg inside your onImageSelectionRequest handler | | SVG not inserting | Use the Paste SVG code toolbar button, or addSvg with full <svg>…</svg> markup | | getStyleProperty / TipTap export errors | Caused by mixing TipTap v2 and v3 in the host app. Use [email protected]+ (TipTap is pinned and bundled). Delete node_modules + lockfile and reinstall, or align all @tiptap/* packages to the same major. |


Requirements

  • Node.js 16+
  • React 18 or 19
  • Modern evergreen browsers

Contributing

  1. Fork and create a feature branch
  2. Install dependencies and run npm run dev
  3. Keep changes focused; run npm run type-check before opening a PR
  4. Open a pull request with a clear description

License

MIT © Bablu Mia