prosemirror-slash-menu-react
v0.1.0
Published
Implementation of prosemirror-slash-menu in react
Downloads
215
Readme
prosemirror-slash-menu-react
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
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 menumenu-element-wrapper
root of menu elementsmenu-element-wrapper-clickable
root of menu elements when the menu items are set to be clickablemenu-element-selected
classname that is added alongsidemenu-element-wrapper
when an element is selectedmenu-element-icon
if icon is provided for the element it's rendered in this divmenu-element-right-icon
if right icon is provided its rendered in this divmenu-element-label
label of the menu elementmenu-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 defaultmenu-filter
the filter textmenu-filter-placeholder
placeholder text for the filter fieldmenu-filter-icon
if icon is provided for the filter field it's rendered in this divsubmenu-label
The label of the submenu is shown above the menu elements when its openedgroup-wrapper
wrapper around the menu elements, if there are multiple groups of elementsgroup-label
label/title of the group
Props
editorState
prosemirrors editor stateeditorView
prosemirror editor viewicons
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 aFunctionComponent
that renders the iconrightIcons
Same as icons but these appear on the right on the menu element, most commonly used for indicating a submenu with an arrowsubMenuIcon
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 choicefilterFieldIcon
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 wantpopperOptions
You can pass inplacement
andoffset
to position your menu around the reference Elementclickable
Optional boolean, if true the menu items are clickable, by default they are used only with keyboard