prosemirror-slash-menu-react 0.0.3 → 0.0.5

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/LICENSE ADDED
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2023 Emergence Engineering
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
package/README.md CHANGED
@@ -4,9 +4,12 @@
4
4
 
5
5
  [**Made by Emergence-Engineering**](https://emergence-engineering.com/)
6
6
 
7
- A UI package used together with [prosemirror-slash-menu](https://github.com/emergence-engineering/prosemirror-slash-menu) to display the menu with react.
7
+ A UI package used together
8
+ with [prosemirror-slash-menu](https://github.com/emergence-engineering/prosemirror-slash-menu) to display the menu with
9
+ react.
8
10
 
9
- By Horváth Áron & [Viktor Váczi](https://emergence-engineering.com/cv/viktor) at [Emergence Engineering](https://emergence-engineering.com/)
11
+ By Horváth Áron & [Viktor Váczi](https://emergence-engineering.com/cv/viktor)
12
+ at [Emergence Engineering](https://emergence-engineering.com/)
10
13
 
11
14
  Try it out at <https://emergence-engineering.com/blog/prosemirror-slash-menu>
12
15
  ![alt text](https://github.com/emergence-engineering/prosemirror-slash-menu-react/blob/main/public/prosemirror-slash-menu.gif?raw=true)
@@ -18,106 +21,109 @@ Try it out at <https://emergence-engineering.com/blog/prosemirror-slash-menu>
18
21
  - Displaying the menu upwards in case of overflow
19
22
  - Default styling
20
23
  - Custom styling with css classnames
24
+ - Optional popper reference element, placement and offset
21
25
  - Outside click handling
22
26
 
23
27
  # Behavior
24
28
 
25
- 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.
26
- For exact behaviour description checkout [prosemirror-slash-menu](https://github.com/emergence-engineering/prosemirror-slash-menu).
27
-
29
+ You can open the menu with the `/` key in an empty paragraph or after a space and you can filter the elements just by
30
+ typing, or you can navigate with the keyboard. For exact behaviour description
31
+ checkout [prosemirror-slash-menu](https://github.com/emergence-engineering/prosemirror-slash-menu).
28
32
 
29
33
  # Installation and Usage
34
+
30
35
  Install from npm with:
31
36
 
32
- `npm install prosemirror-slash-menu-react`
37
+ `npm install prosemirror-slash-menu-react`
33
38
 
34
39
  Usage in the app:
35
40
 
36
41
  ```tsx
37
- import React, { useEffect, useRef, useState } from "react";
38
- import { exampleSetup } from "prosemirror-example-setup";
39
- import { EditorState } from "prosemirror-state";
40
- import { EditorView } from "prosemirror-view";
42
+ import React, {useEffect, useRef, useState} from "react";
43
+ import {exampleSetup} from "prosemirror-example-setup";
44
+ import {EditorState} from "prosemirror-state";
45
+ import {EditorView} from "prosemirror-view";
41
46
  import schema from "./schema";
42
- import { SlashMenuPlugin } from "prosemirror-slash-menu";
47
+ import {SlashMenuPlugin} from "prosemirror-slash-menu";
43
48
  import {
44
- defaultElements,
45
- defaultIcons,
46
- Icons,
47
- SlashMenuReact,
49
+ defaultElements,
50
+ defaultIcons,
51
+ Icons,
52
+ SlashMenuReact,
48
53
  } from "prosemirror-slash-menu-react";
49
54
 
50
55
  const ProseMirrorSlashMenuDemo = () => {
51
- const [pmState, setPmState] = useState<EditorState>();
52
- const [editorView, setEditorView] = useState<EditorView>();
53
- const editorRef = useRef<HTMLDivElement>(null);
54
- useEffect(() => {
55
- if (!editorRef.current) return;
56
- const state = EditorState.create({
57
- doc: schema.nodeFromJSON({
58
- content: [
59
- {
60
- content: [
61
- {
62
- text: "Type '/' after a space to open the menu. ",
63
- type: "text",
64
- },
56
+ const [pmState, setPmState] = useState<EditorState>();
57
+ const [editorView, setEditorView] = useState<EditorView>();
58
+ const editorRef = useRef<HTMLDivElement>(null);
59
+ useEffect(() => {
60
+ if (!editorRef.current) return;
61
+ const state = EditorState.create({
62
+ doc: schema.nodeFromJSON({
63
+ content: [
64
+ {
65
+ content: [
66
+ {
67
+ text: "Type '/' after a space to open the menu. ",
68
+ type: "text",
69
+ },
70
+ ],
71
+ type: "paragraph",
72
+ },
73
+ ],
74
+ type: "doc",
75
+ }),
76
+ plugins: [
77
+ SlashMenuPlugin(defaultElements),
78
+ ...exampleSetup({
79
+ schema,
80
+ }),
65
81
  ],
66
- type: "paragraph",
67
- },
68
- ],
69
- type: "doc",
70
- }),
71
- plugins: [
72
- SlashMenuPlugin(defaultElements),
73
- ...exampleSetup({
74
- schema,
75
- }),
76
- ],
77
- });
78
- const view: EditorView = new EditorView(editorRef.current, {
79
- state,
80
- dispatchTransaction: (tr) => {
81
- try {
82
- const newState = view.state.apply(tr);
83
- view.updateState(newState);
84
- setPmState(newState);
85
- } catch (e) {}
86
- },
87
- });
88
- setEditorView(view);
89
- return () => {
90
- view && view.destroy();
91
- };
92
- }, [editorRef]);
93
- return (
94
- <>
95
- <div ref={editorRef} id="editor" />
96
- {pmState && editorView && (
97
- <SlashMenuReact
98
- icons={{
99
- [Icons.HeaderMenu]: defaultIcons.H1Icon,
100
- [Icons.Level1]: defaultIcons.H1Icon,
101
- [Icons.Level2]: defaultIcons.H2Icon,
102
- [Icons.Level3]: defaultIcons.H3Icon,
103
- [Icons.Bold]: defaultIcons.BoldIcon,
104
- [Icons.Italic]: defaultIcons.ItalicIcon,
105
- [Icons.Code]: defaultIcons.CodeIcon,
106
- [Icons.Link]: defaultIcons.LinkIcon,
107
- }}
108
- editorState={pmState}
109
- editorView={editorView}
110
- />
111
- )}
112
- </>
113
- );
82
+ });
83
+ const view: EditorView = new EditorView(editorRef.current, {
84
+ state,
85
+ dispatchTransaction: (tr) => {
86
+ try {
87
+ const newState = view.state.apply(tr);
88
+ view.updateState(newState);
89
+ setPmState(newState);
90
+ } catch (e) {
91
+ }
92
+ },
93
+ });
94
+ setEditorView(view);
95
+ return () => {
96
+ view && view.destroy();
97
+ };
98
+ }, [editorRef]);
99
+ return (
100
+ <>
101
+ <div ref={editorRef} id="editor"/>
102
+ {pmState && editorView && (
103
+ <SlashMenuReact
104
+ icons={{
105
+ [Icons.HeaderMenu]: defaultIcons.H1Icon,
106
+ [Icons.Level1]: defaultIcons.H1Icon,
107
+ [Icons.Level2]: defaultIcons.H2Icon,
108
+ [Icons.Level3]: defaultIcons.H3Icon,
109
+ [Icons.Bold]: defaultIcons.BoldIcon,
110
+ [Icons.Italic]: defaultIcons.ItalicIcon,
111
+ [Icons.Code]: defaultIcons.CodeIcon,
112
+ [Icons.Link]: defaultIcons.LinkIcon,
113
+ }}
114
+ editorState={pmState}
115
+ editorView={editorView}
116
+ />
117
+ )}
118
+ </>
119
+ );
114
120
  };
115
121
  ```
116
122
 
123
+ # Styling
117
124
 
118
- # Styling
119
-
120
- 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.
125
+ To use the basic styling you can import `menu-style.css` into your project. If you want to use your own styling you can
126
+ override the following classnames.
121
127
 
122
128
  - `menu-display-root` root div for the menu
123
129
  - `menu-element-wrapper` root of menu elements
@@ -126,12 +132,21 @@ To use the basic styling you can import `menu-style.css` into your project. If y
126
132
  - `menu-element-label` label of the menu element
127
133
  - `menu-placeholder` when there is no matching items for the filter, this is displayed with the text "No matching items"
128
134
  - `menu-filter-wrapper` root of the filter display, positioned above the menu by default
129
- - `menu-filter` the filter text
135
+ - `menu-filter` the filter text
136
+ - `menu-filter-placeholder` placeholder text for the filter field
137
+ - `menu-filter-icon` if icon is provided for the filter field it's rendered in this div
130
138
  - `submenu-label` The label of the submenu is shown above the menu elements when its opened
131
139
 
132
- # Props
140
+ # Props
133
141
 
134
142
  - `editorState` prosemirrors editor state
135
143
  - `editorView` prosemirror editor view
136
- - `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
137
- - `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
144
+ - `icons` Optional, if you want to provide icons for your menu elements. Type of `{[key: string]: FC}` where the key is
145
+ the id of the menu element and the value is a `FunctionComponent` that renders the icon
146
+ - `subMenuIcon` Optional icon for submenu label. By default, when a submenu is open an arrow is displayed indicating
147
+ that the user is in a subMenu, it can be replaced with a react node of your choice
148
+ - `filterFieldIcon` Optional icon in the filter field.
149
+ - `filterPlaceHolder` Optional placeholder text for the filter field.
150
+ - `mainMenuLabel` Optional label for the main menu. By default, there is none.
151
+ - `popperReference` Optional popper reference HTMLElement, for displaying the menu next to whatever element you want
152
+ - `popperOptions` You can pass in `placement` and `offset` to position your menu around the reference Element
@@ -0,0 +1,73 @@
1
+ .menu-display-root {
2
+ position: absolute;
3
+ display: flex;
4
+ flex-direction: column;
5
+ flex: 1;
6
+ max-height: 150px;
7
+ width: 200px;
8
+ z-index: 100;
9
+ overflow: scroll;
10
+ border-radius: 0.3rem;
11
+ background-color: #fafafa;
12
+ border: 2px solid #dddddd;
13
+ }
14
+
15
+ .menu-element-wrapper {
16
+ display: flex;
17
+ border-radius: 0.3rem;
18
+ padding: 0.2rem 0.5rem;
19
+ }
20
+
21
+ .menu-element-selected {
22
+ background-color: #f1f1f1;
23
+ }
24
+
25
+ .menu-element-icon {
26
+ width: 23px;
27
+ height: auto;
28
+ display: flex;
29
+ align-items: center;
30
+ }
31
+
32
+ .menu-element-label {
33
+ color: black;
34
+ display: flex;
35
+ align-items: center;
36
+ margin-left: 0.5rem;
37
+ }
38
+
39
+ .menu-placeholder {
40
+ color: #aaaaaa;
41
+ text-align: center;
42
+ padding-top: 1rem;
43
+ }
44
+
45
+ .menu-filter-wrapper {
46
+ display: flex;
47
+ background-color: transparent;
48
+ padding: 0.2rem 0.5rem;
49
+ position: absolute;
50
+ top: -1.5rem;
51
+ width: 200px;
52
+ }
53
+
54
+ .menu-filter-icon {
55
+ width: 23px;
56
+ height: auto;
57
+ display: flex;
58
+ align-items: center;
59
+ }
60
+
61
+ .menu-filter {
62
+ color: #aaaaaa;
63
+ font-style: italic
64
+ }
65
+
66
+ .menu-filter-placeholder {
67
+ color: #aaaaaa;
68
+ font-style: italic
69
+ }
70
+
71
+ .submenu-label {
72
+ margin-left: 0.5rem;
73
+ }
@@ -0,0 +1,72 @@
1
+ .menu-display-root {
2
+ position: absolute;
3
+ display: flex;
4
+ flex-direction: column;
5
+ height: 150px;
6
+ width: 200px;
7
+ z-index: 100;
8
+ overflow: scroll;
9
+ border-radius: 0.3rem;
10
+ background-color: #fafafa;
11
+ border: 2px solid #dddddd;
12
+ }
13
+
14
+ .menu-element-wrapper {
15
+ display: flex;
16
+ border-radius: 0.3rem;
17
+ padding: 0.2rem 0.5rem;
18
+ }
19
+
20
+ .menu-element-selected {
21
+ background-color: #f1f1f1;
22
+ }
23
+
24
+ .menu-element-icon {
25
+ width: 23px;
26
+ height: auto;
27
+ display: flex;
28
+ align-items: center;
29
+ }
30
+
31
+ .menu-element-label {
32
+ color: black;
33
+ display: flex;
34
+ align-items: center;
35
+ margin-left: 0.5rem;
36
+ }
37
+
38
+ .menu-placeholder {
39
+ color: #aaaaaa;
40
+ text-align: center;
41
+ padding-top: 1rem;
42
+ }
43
+
44
+ .menu-filter-wrapper {
45
+ display: flex;
46
+ background-color: transparent;
47
+ padding: 0.2rem 0.5rem;
48
+ position: absolute;
49
+ top: -1.5rem;
50
+ width: 200px;
51
+ }
52
+
53
+ .menu-filter-icon {
54
+ width: 23px;
55
+ height: auto;
56
+ display: flex;
57
+ align-items: center;
58
+ }
59
+
60
+ .menu-filter {
61
+ color: #aaaaaa;
62
+ font-style: italic
63
+ }
64
+
65
+ .menu-filter-placeholder {
66
+ color: #aaaaaa;
67
+ font-style: italic
68
+ }
69
+
70
+ .submenu-label {
71
+ margin-left: 0.5rem;
72
+ }
@@ -0,0 +1,71 @@
1
+ .menu-display-root {
2
+ position: absolute;
3
+ display: flex;
4
+ flex-direction: column;
5
+ height: 150px;
6
+ width: 200px;
7
+ z-index: 100;
8
+ overflow: scroll;
9
+ border-radius: 0.3rem;
10
+ background-color: #fafafa;
11
+ border: 2px solid #dddddd;
12
+ }
13
+
14
+ .menu-element-wrapper {
15
+ display: flex;
16
+ border-radius: 0.3rem;
17
+ padding: 0.2rem 0.5rem;
18
+ }
19
+
20
+ .menu-element-selected {
21
+ background-color: #f1f1f1;
22
+ }
23
+
24
+ .menu-element-icon {
25
+ width: 23px;
26
+ height: auto;
27
+ display: flex;
28
+ align-items: center;
29
+ }
30
+
31
+ .menu-element-label {
32
+ color: black;
33
+ display: flex;
34
+ align-items: center;
35
+ margin-left: 0.5rem;
36
+ }
37
+
38
+ .menu-placeholder {
39
+ color: #aaaaaa;
40
+ text-align: center;
41
+ padding-top: 1rem;
42
+ }
43
+
44
+ .menu-filter-wrapper {
45
+ display: flex;
46
+ background-color: transparent;
47
+ padding: 0.2rem 0.5rem;
48
+ position: absolute;
49
+ top: -1.5rem;
50
+ }
51
+
52
+ .menu-filter-icon {
53
+ width: 23px;
54
+ height: auto;
55
+ display: flex;
56
+ align-items: center;
57
+ }
58
+
59
+ .menu-filter {
60
+ color: #aaaaaa;
61
+ font-style: italic
62
+ }
63
+
64
+ .menu-filter-placeholder {
65
+ color: #aaaaaa;
66
+ font-style: italic
67
+ }
68
+
69
+ .submenu-label {
70
+ margin-left: 0.5rem;
71
+ }
@@ -0,0 +1,73 @@
1
+ .menu-display-root {
2
+ position: absolute;
3
+ display: flex;
4
+ flex-direction: column;
5
+ flex: 1;
6
+ max-height: 150px;
7
+ width: 200px;
8
+ z-index: 100;
9
+ overflow: scroll;
10
+ border-radius: 0.3rem;
11
+ background-color: #fafafa;
12
+ border: 2px solid #dddddd;
13
+ }
14
+
15
+ .menu-element-wrapper {
16
+ display: flex;
17
+ border-radius: 0.3rem;
18
+ padding: 0.2rem 0.5rem;
19
+ }
20
+
21
+ .menu-element-selected {
22
+ background-color: #f1f1f1;
23
+ }
24
+
25
+ .menu-element-icon {
26
+ width: 23px;
27
+ height: auto;
28
+ display: flex;
29
+ align-items: center;
30
+ }
31
+
32
+ .menu-element-label {
33
+ color: black;
34
+ display: flex;
35
+ align-items: center;
36
+ margin-left: 0.5rem;
37
+ }
38
+
39
+ .menu-placeholder {
40
+ color: #aaaaaa;
41
+ text-align: center;
42
+ padding: 0 0.5rem;
43
+ }
44
+
45
+ .menu-filter-wrapper {
46
+ display: flex;
47
+ background-color: transparent;
48
+ padding: 0.2rem 0.5rem;
49
+ position: absolute;
50
+ top: -1.5rem;
51
+ width: 200px;
52
+ }
53
+
54
+ .menu-filter-icon {
55
+ width: 23px;
56
+ height: auto;
57
+ display: flex;
58
+ align-items: center;
59
+ }
60
+
61
+ .menu-filter {
62
+ color: #aaaaaa;
63
+ font-style: italic
64
+ }
65
+
66
+ .menu-filter-placeholder {
67
+ color: #aaaaaa;
68
+ font-style: italic
69
+ }
70
+
71
+ .submenu-label {
72
+ margin-left: 0.5rem;
73
+ }
@@ -0,0 +1,71 @@
1
+ .menu-display-root {
2
+ position: absolute;
3
+ display: flex;
4
+ flex-direction: column;
5
+ height: 150px;
6
+ width: 200px;
7
+ z-index: 100;
8
+ overflow: scroll;
9
+ border-radius: 0.3rem;
10
+ background-color: #fafafa;
11
+ border: 2px solid #dddddd;
12
+ }
13
+
14
+ .menu-element-wrapper {
15
+ display: flex;
16
+ border-radius: 0.3rem;
17
+ padding: 0.2rem 0.5rem;
18
+ }
19
+
20
+ .menu-element-selected {
21
+ background-color: #f1f1f1;
22
+ }
23
+
24
+ .menu-element-icon {
25
+ width: 23px;
26
+ height: auto;
27
+ display: flex;
28
+ align-items: center;
29
+ }
30
+
31
+ .menu-element-label {
32
+ color: black;
33
+ display: flex;
34
+ align-items: center;
35
+ margin-left: 0.5rem;
36
+ }
37
+
38
+ .menu-placeholder {
39
+ color: #aaaaaa;
40
+ text-align: center;
41
+ padding-top: 1rem;
42
+ }
43
+
44
+ .menu-filter-wrapper {
45
+ display: flex;
46
+ background-color: transparent;
47
+ padding: 0.2rem 0.5rem;
48
+ position: absolute;
49
+ top: -1.5rem;
50
+ }
51
+
52
+ .menu-filter-icon {
53
+ width: 23px;
54
+ height: auto;
55
+ display: flex;
56
+ align-items: center;
57
+ }
58
+
59
+ .menu-filter {
60
+ color: #aaaaaa;
61
+ font-style: italic
62
+ }
63
+
64
+ .menu-filter-placeholder {
65
+ color: #aaaaaa;
66
+ font-style: italic
67
+ }
68
+
69
+ .submenu-label {
70
+ margin-left: 0.5rem;
71
+ }
@@ -0,0 +1,73 @@
1
+ .menu-display-root {
2
+ position: absolute;
3
+ display: flex;
4
+ flex-direction: column;
5
+ flex: 1;
6
+ max-height: 150px;
7
+ width: 200px;
8
+ z-index: 100;
9
+ overflow: scroll;
10
+ border-radius: 0.3rem;
11
+ background-color: #fafafa;
12
+ border: 2px solid #dddddd;
13
+ }
14
+
15
+ .menu-element-wrapper {
16
+ display: flex;
17
+ border-radius: 0.3rem;
18
+ padding: 0.2rem 0.5rem;
19
+ }
20
+
21
+ .menu-element-selected {
22
+ background-color: #f1f1f1;
23
+ }
24
+
25
+ .menu-element-icon {
26
+ width: 23px;
27
+ height: auto;
28
+ display: flex;
29
+ align-items: center;
30
+ }
31
+
32
+ .menu-element-label {
33
+ color: black;
34
+ display: flex;
35
+ align-items: center;
36
+ margin-left: 0.5rem;
37
+ }
38
+
39
+ .menu-placeholder {
40
+ color: #aaaaaa;
41
+ text-align: center;
42
+ padding: 0 0.5rem;
43
+ }
44
+
45
+ .menu-filter-wrapper {
46
+ display: flex;
47
+ background-color: transparent;
48
+ padding: 0.2rem 0.5rem;
49
+ position: absolute;
50
+ top: -1.5rem;
51
+ width: 200px;
52
+ }
53
+
54
+ .menu-filter-icon {
55
+ width: 23px;
56
+ height: auto;
57
+ display: flex;
58
+ align-items: center;
59
+ }
60
+
61
+ .menu-filter {
62
+ color: #aaaaaa;
63
+ font-style: italic
64
+ }
65
+
66
+ .menu-filter-placeholder {
67
+ color: #aaaaaa;
68
+ font-style: italic
69
+ }
70
+
71
+ .submenu-label {
72
+ margin-left: 0.5rem;
73
+ }