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

@type-editor/adapter-react

v0.0.3

Published

Type editor React adapter

Downloads

157

Readme

@type-editor/adapter-react

React adapter for integrating custom React components as ProseMirror node views, mark views, plugin views, and widget decorations.

Overview

@type-editor/adapter-react bridges ProseMirror's view layer and React's rendering pipeline. Each ProseMirror node, mark, plugin view, or widget decoration can be backed by an ordinary React component. State changes are propagated through React context; rendering happens via React portals.

Installation

npm install @type-editor/adapter-react
# or
pnpm add @type-editor/adapter-react

Peer dependencies: react, react-dom

Setup

Wrap the component that contains your editor with ProsemirrorAdapterProvider. This sets up the rendering infrastructure and makes the factory hooks available to all descendant components.

import { ProsemirrorAdapterProvider } from '@type-editor/adapter-react';
import { createRoot } from 'react-dom/client';
import { Editor } from './Editor';

createRoot(document.getElementById('app')!).render(
    <ProsemirrorAdapterProvider>
        <Editor />
    </ProsemirrorAdapterProvider>
);

Usage

As this is a fork of @prosemirror-adapter/react, you'll find more documentation and examples in the original repository: https://github.com/prosekit/prosemirror-adapter/tree/main/packages/react

Node views

1. Create a React component

Access the current node, decorations, and editor state through useNodeViewContext:

import { useNodeViewContext } from '@type-editor/adapter-react';
import { useEffect } from 'react';

export function Paragraph() {
    const { dom, node, contentRef } = useNodeViewContext();

    useEffect(() => {
        if (!dom) return;
        if (node.attrs.align) {
            dom.style.textAlign = node.attrs.align as string;
        }
    }, [dom, node]);

    // Render nothing – ProseMirror manages the content directly inside `dom`
    // when contentAs: 'self' is used.
    return null;
}

When you need a content-editable region inside your component, attach contentRef to the wrapper element:

export function MyNode() {
    const { contentRef } = useNodeViewContext();
    return <div ref={contentRef} />;
}

2. Create a node view factory

Use useNodeViewFactory inside a component that is a descendant of ProsemirrorAdapterProvider:

import { useNodeViewFactory } from '@type-editor/adapter-react';
import { PmNode } from '@type-editor/model';
import { Paragraph } from './Paragraph';

export function Editor() {
    const nodeViewFactory = useNodeViewFactory();

    const paragraphView = nodeViewFactory({
        component: Paragraph,
        as: (node: PmNode): HTMLElement => {
            const p = document.createElement('p');
            if (node.attrs.align) p.style.textAlign = node.attrs.align;
            return p;
        },
        contentAs: 'self',
    });

    // Pass to ProseMirror's EditorView
    const editorView = new EditorView(container, {
        state,
        nodeViews: { paragraph: paragraphView },
    });
}

Mark views

import { useMarkViewContext, useMarkViewFactory } from '@type-editor/adapter-react';

export function BoldMark() {
    const { contentRef } = useMarkViewContext();
    return <strong ref={contentRef} />;
}

// In your editor component:
const markViewFactory = useMarkViewFactory();
const boldView = markViewFactory({ component: BoldMark });

Plugin views

import { usePluginViewContext, usePluginViewFactory } from '@type-editor/adapter-react';

export function Toolbar() {
    const { view } = usePluginViewContext();
    // render toolbar using the editor view
    return <div className="toolbar">…</div>;
}

// In your editor component:
const pluginViewFactory = usePluginViewFactory();
const toolbarPlugin = new Plugin({
    view: pluginViewFactory({ component: Toolbar }),
});

Widget views

import { useWidgetViewFactory } from '@type-editor/adapter-react';

// In your editor component:
const widgetViewFactory = useWidgetViewFactory();
const decoration = widgetViewFactory(pos, { component: MyWidget });

API reference

ProsemirrorAdapterProvider

Provider component. Must wrap any component that uses the factory hooks.

Hooks

| Hook | Returns | Description | |--------------------------|---------------------|-------------------------------------------------------------------------| | useNodeViewFactory() | NodeViewFactory | Creates a ProseMirror NodeViewConstructor backed by a React component | | useMarkViewFactory() | MarkViewFactory | Creates a ProseMirror MarkViewConstructor backed by a React component | | usePluginViewFactory() | PluginViewFactory | Creates a ProseMirror PluginView factory backed by a React component | | useWidgetViewFactory() | WidgetViewFactory | Creates a widget decoration factory backed by a React component | | useNodeViewContext() | NodeViewContext | Reads editor state inside a node view component | | useMarkViewContext() | MarkViewContext | Reads editor state inside a mark view component | | usePluginViewContext() | PluginViewContext | Reads editor state inside a plugin view component | | useWidgetViewContext() | WidgetViewContext | Reads editor state inside a widget view component |

NodeViewContext

| Property | Type | Description | |--------------------|-------------------------------------|---------------------------------------------------------| | contentRef | (el: HTMLElement \| null) => void | Ref callback for the content-editable container | | dom | HTMLElement | The outer DOM element of this node view | | view | PmEditorView | The ProseMirror editor view | | getPos | () => number \| undefined | Returns the node's current document position | | setAttrs | (attrs: Attrs) => void | Dispatches a transaction updating the node's attributes | | node | Node | The current ProseMirror document node | | selected | boolean | Whether this node is currently selected | | decorations | ReadonlyArray<PmDecoration> | Decorations applied to this node | | innerDecorations | DecorationSource | Decorations applied to this node's content |

License

MIT