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

@zuilib/text-editor

v0.0.2

Published

ZUI — A markdown editor component wrapping Lexical

Readme

@zuilib/text-editor

Markdown editor for ZUI built on Lexical: rich editing with shortcuts, raw markdown mode, read-only view, checklists, and fenced code highlighting.

When to use

  • Notes, comments, or docs fields stored as markdown strings
  • Controlled value / onChange integration with forms or autosave
  • WYSIWYG-style editing without leaving markdown as the source of truth

Prerequisites

Peer dependencies (install in the consuming app):

| Package | Version | |---------|---------| | react, react-dom | ^18.0.0 \|\| ^19.0.0 | | lexical | ^0.35.0 | | @lexical/react | ^0.35.0 | | @lexical/markdown | ^0.35.0 | | @lexical/rich-text | ^0.35.0 | | @lexical/code | ^0.35.0 | | @lexical/list | ^0.35.0 | | @lexical/link | ^0.35.0 | | @zuilib/core | workspace / published — import core styles |

Installation

pnpm add @zuilib/text-editor @zuilib/core \
  lexical @lexical/react @lexical/markdown @lexical/rich-text \
  @lexical/code @lexical/list @lexical/link

Monorepo:

{
  "dependencies": {
    "@zuilib/text-editor": "workspace:*",
    "@zuilib/core": "workspace:*",
    "lexical": "^0.35.0",
    "@lexical/react": "^0.35.0",
    "@lexical/markdown": "^0.35.0",
    "@lexical/rich-text": "^0.35.0",
    "@lexical/code": "^0.35.0",
    "@lexical/list": "^0.35.0",
    "@lexical/link": "^0.35.0"
  }
}

Import rules

| Rule | Detail | |------|--------| | Named export | import { MarkdownEditor } from '@zuilib/text-editor' | | Types | import type { MarkdownEditorProps } from '@zuilib/text-editor' | | Styles | import '@zuilib/text-editor/styles.css' and @zuilib/core/styles.css | | Controlled | Always pass value + onChange for persisted content | | Mode switches | Switching edit-rawedit-md re-mounts Lexical with latest markdown (cursor-safe) |

Exports

| Subpath | Exports | |---------|---------| | @zuilib/text-editor | MarkdownEditor (default re-exported as named), MarkdownEditorProps | | @zuilib/text-editor/styles.css | Editor chrome + Lexical theme classes |

Quick start

import { useState } from 'react'
import '@zuilib/core/styles.css'
import '@zuilib/text-editor/styles.css'
import { MarkdownEditor } from '@zuilib/text-editor'

function Notes() {
  const [value, setValue] = useState('# Hello\n\n- [ ] Try checklists')

  return (
    <MarkdownEditor
      value={value}
      onChange={setValue}
      placeholder="Start writing…"
    />
  )
}

Modes

| mode | UI | onChange | |--------|-----|------------| | 'edit-md' (default) | Lexical rich editor + markdown shortcuts | Emits markdown string | | 'edit-raw' | Plain <textarea> with markdown source | Emits markdown string | | 'view' | Read-only rendered content | No editing (onChange unused) |

<MarkdownEditor mode="edit-md" value={md} onChange={setMd} />
<MarkdownEditor mode="edit-raw" value={md} onChange={setMd} />
<MarkdownEditor mode="view" value={md} />

Toggle modes in parent state; the editor preserves content via an internal ref when remounting Lexical after raw editing.

Props (MarkdownEditorProps)

| Prop | Type | Default | Description | |------|------|---------|-------------| | value | string | '' | Markdown source (controlled) | | onChange | (value: string) => void | — | Called on every edit | | mode | 'edit-md' \| 'edit-raw' \| 'view' | 'edit-md' | Editing surface | | placeholder | string | 'Start writing...' | Empty state hint | | readOnly | boolean | false | Disables editing in Lexical modes | | autoFocus | boolean | false | Focus on mount | | className | string | — | Root wrapper class |

Markdown features

Shortcuts (edit-md): headings (#), lists, blockquote, links, fenced code (via CodeBlockShortcutPlugin), checklists (- [ ] via ChecklistShortcutPlugin).

Built-in plugins: history (undo/redo), lists, checklists, links, markdown sync (MarkdownSyncPlugin), code highlighting (CodeHighlightPlugin).

Not included: file uploads, collaborative editing, or custom Lexical node registration — extend by forking or wrapping MarkdownEditor.

Form integration

With @zuilib/form:

<FormField control={form.control} name="body">
  {({ field }) => (
    <MarkdownEditor
      value={field.value}
      onChange={field.onChange}
      mode="edit-md"
    />
  )}
</FormField>

Ensure both CSS entry points are loaded in the app layout.

Architecture notes (for extenders)

  • Source: src/MarkdownEditor.tsx, plugins under src/plugins/
  • Lexical namespace: ZuiTextEditor
  • Markdown import/export uses @lexical/markdown transformers (CHECK_LIST prioritized for import)
  • edit-raw bypasses Lexical; switching back to edit-md captures latestValueRef and bumps mountKey to avoid cursor jumps

Related packages

  • @zuilib/core — design tokens and base styles
  • @zuilib/form — react-hook-form wiring

Build (maintainers)

pnpm --filter @zuilib/text-editor build