prosemirror-slash-menu-react
TypeScript icon, indicating that this package has built-in type declarations

0.0.11 • Public • Published

prosemirror-slash-menu-react

made by Emergence Engineering

Made by Emergence-Engineering

A UI package used together with prosemirror-slash-menu to display the menu with react.

By Horváth Áron & Viktor Váczi at Emergence Engineering

Try it out at https://emergence-engineering.com/blog/prosemirror-slash-menu alt text

Features

  • Displaying prosemirror-slash-menu with react
  • Menu positioning at the cursor position
  • Displaying the menu upwards in case of overflow
  • Default styling
  • Custom styling with css classnames
  • Optional popper reference element, placement and offset
  • Outside click handling

Behavior

You can open the menu with the / key in an empty paragraph or after a space and you can filter the elements just by typing, or you can navigate with the keyboard. For exact behaviour description checkout prosemirror-slash-menu.

Installation and Usage

Install from npm with:

npm install prosemirror-slash-menu-react

Usage in the app:

import React, { useEffect, useRef, useState } from "react";
import { exampleSetup } from "prosemirror-example-setup";
import { EditorState } from "prosemirror-state";
import { EditorView } from "prosemirror-view";
import schema from "./schema";
import { SlashMenuPlugin } from "prosemirror-slash-menu";
import {
  defaultElements,
  defaultIcons,
  Icons,
  SlashMenuReact,
} from "prosemirror-slash-menu-react";

const ProseMirrorSlashMenuDemo = () => {
  const [pmState, setPmState] = useState<EditorState>();
  const [editorView, setEditorView] = useState<EditorView>();
  const editorRef = useRef<HTMLDivElement>(null);
  useEffect(() => {
    if (!editorRef.current) return;
    const state = EditorState.create({
      doc: schema.nodeFromJSON({
        content: [
          {
            content: [
              {
                text: "Type '/' after a space to open the menu. ",
                type: "text",
              },
            ],
            type: "paragraph",
          },
        ],
        type: "doc",
      }),
      plugins: [
        SlashMenuPlugin(defaultElements),
        ...exampleSetup({
          schema,
        }),
      ],
    });
    const view: EditorView = new EditorView(editorRef.current, {
      state,
      dispatchTransaction: (tr) => {
        try {
          const newState = view.state.apply(tr);
          view.updateState(newState);
          setPmState(newState);
        } catch (e) {}
      },
    });
    setEditorView(view);
    return () => {
      view && view.destroy();
    };
  }, [editorRef]);
  return (
    <>
      <div ref={editorRef} id="editor" />
      {pmState && editorView && (
        <SlashMenuReact
          icons={{
            [Icons.HeaderMenu]: defaultIcons.H1Icon,
            [Icons.Level1]: defaultIcons.H1Icon,
            [Icons.Level2]: defaultIcons.H2Icon,
            [Icons.Level3]: defaultIcons.H3Icon,
            [Icons.Bold]: defaultIcons.BoldIcon,
            [Icons.Italic]: defaultIcons.ItalicIcon,
            [Icons.Code]: defaultIcons.CodeIcon,
            [Icons.Link]: defaultIcons.LinkIcon,
          }}
          editorState={pmState}
          editorView={editorView}
        />
      )}
    </>
  );
};

Styling

To use the basic styling you can import menu-style.css into your project. If you want to use your own styling you can override the following classnames.

  • menu-display-root root div for the menu
  • menu-element-wrapper root of menu elements
  • menu-element-wrapper-clickable root of menu elements when the menu items are set to be clickable
  • menu-element-selected classname that is added alongside menu-element-wrapper when an element is selected
  • menu-element-icon if icon is provided for the element it's rendered in this div
  • menu-element-right-icon if right icon is provided its rendered in this div
  • menu-element-label label of the menu element
  • menu-placeholder when there is no matching items for the filter, this is displayed with the text "No matching items"
  • menu-filter-wrapper root of the filter display, positioned above the menu by default
  • menu-filter the filter text
  • menu-filter-placeholder placeholder text for the filter field
  • menu-filter-icon if icon is provided for the filter field it's rendered in this div
  • submenu-label The label of the submenu is shown above the menu elements when its opened

Props

  • editorState prosemirrors editor state
  • editorView prosemirror editor view
  • icons Optional, if you want to provide icons for your menu elements. Type of {[key: string]: FC} where the key is the id of the menu element and the value is a FunctionComponent that renders the icon
  • rightIcons Same as icons but these appear on the right on the menu element, most commonly used for indicating a submenu with an arrow
  • subMenuIcon Optional icon for submenu label. By default, when a submenu is open an arrow is displayed indicating that the user is in a subMenu, it can be replaced with a react node of your choice
  • filterFieldIcon Optional icon in the filter field.
  • filterPlaceHolder Optional placeholder text for the filter field.
  • mainMenuLabel Optional label for the main menu. By default, there is none.
  • popperReference Optional popper reference HTMLElement, for displaying the menu next to whatever element you want
  • popperOptions You can pass in placement and offset to position your menu around the reference Element
  • clickable Optional boolean, if true the menu items are clickable, by default they are used only with keyboard

Package Sidebar

Install

npm i prosemirror-slash-menu-react

Weekly Downloads

39

Version

0.0.11

License

ISC

Unpacked Size

57.1 kB

Total Files

15

Last publish

Collaborators

  • viktorvacziee
  • matejcsok
  • aaron-ee