Skip to content

An example of how to use React components as NodeViews for ProseMirror

Notifications You must be signed in to change notification settings

johnkueh/prosemirror-react-nodeviews

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

21 Commits
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

ProseMirror React NodeViews

This is an example repo of how to use React FC components as NodeViews for ProseMirror

Screenshot

How to use:

Wrap your root component with ReactNodeViewPortalsProvider

Lets use React portals to preserve your app context (css-in-js, data, etc) when the NodeViews are rendered. ReactNodeViewPortalsProvider is a convenient way to help you with this.

import { createReactNodeView } from "./ReactNodeView";
import ReactNodeViewPortalsProvider from "./ReactNodeViewPortals";

const App: React.FC<Props> = props => {
  return (
    <ReactNodeViewPortalsProvider>
      <App {...props} />
    </ReactNodeViewPortalsProvider>
  );
};

export default App;

Loading ProseMirror with React components

This is how you initialize your ProseMirror editor

import React from "react";
import { useReactNodeViewPortals } from "./ReactNodeViewPortals";

const ProseMirror: React.FC<Props> = () => {
  const { createPortal } = useReactNodeViewPortals();
  const editorViewRef = useRef(null);

  const handleCreatePortal = useCallback(createPortal, []);
  const state = useMemo(() => {
    const doc = schema.nodeFromJSON(YOUR_PROSEMIRROR_SCHEMA);
    return EditorState.create({
      doc,
      plugins: [
        history(),
        keymap({ "Mod-z": undo, "Mod-y": redo }),
        keymap(baseKeymap)
      ]
    });
  }, []);

  const createEditorView = useCallback(
    editorViewDOM => {
      const view = new EditorView(editorViewDOM, {
        state,
        nodeViews: {
          heading(node, view, getPos, decorations) {
            return createReactNodeView({
              node,
              view,
              getPos,
              decorations,
              component: Heading,
              onCreatePortal: handleCreatePortal
            });
          },
          paragraph(node, view, getPos, decorations) {
            return createReactNodeView({
              node,
              view,
              getPos,
              decorations,
              component: Paragraph,
              onCreatePortal: handleCreatePortal
            });
          }
        },
        dispatchTransaction(transaction) {
          const newState = view.state.apply(transaction);
          handleChange(newState.doc.toJSON());
          view.updateState(newState);
        }
      });
    },
    [state, handleChange, handleCreatePortal]
  );

  useEffect(() => {
    const editorViewDOM = editorViewRef.current;
    if (editorViewDOM) {
      createEditorView(editorViewDOM);
    }
  }, [createEditorView]);

  return <div ref={editorViewRef}></div>;
};

export default ProseMirror;

Getting node props within your React components

Each of the React components have been wrapped with a context provider before sending it through the portal, so its easy to access the nodeview's props:

import { Heading } from "@chakra-ui/core";
import React from "react";
import { useReactNodeView } from "./ReactNodeView";

const HeadingBlock: React.FC = ({ children }) => {
  const context = useReactNodeView();
  const level = context.node?.attrs.level;
  return <Heading fontSize={`${7 - level}xl`}>{children}</Heading>;
};

export default HeadingBlock;
import { Box, Image, Text } from "@chakra-ui/core";
import React from "react";
import { useReactNodeView } from "./ReactNodeView";

const ImageBlock: React.FC = () => {
  const context = useReactNodeView();
  const attrs = context.node?.attrs;
  return (
    <Box>
      <Image alt={attrs?.alt} src={attrs?.src} />
      {attrs?.title && (
        <Text mt={2} color="gray.500" textAlign="center" fontSize="xs">
          {attrs.title}
        </Text>
      )}
    </Box>
  );
};

export default ImageBlock;

About

An example of how to use React components as NodeViews for ProseMirror

Resources

Stars

Watchers

Forks

Releases

No releases published

Packages

No packages published