prosemirror-slash-menu-react 0.0.4 → 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/README.md CHANGED
@@ -21,6 +21,7 @@ Try it out at <https://emergence-engineering.com/blog/prosemirror-slash-menu>
21
21
  - Displaying the menu upwards in case of overflow
22
22
  - Default styling
23
23
  - Custom styling with css classnames
24
+ - Optional popper reference element, placement and offset
24
25
  - Outside click handling
25
26
 
26
27
  # Behavior
@@ -146,4 +147,6 @@ override the following classnames.
146
147
  that the user is in a subMenu, it can be replaced with a react node of your choice
147
148
  - `filterFieldIcon` Optional icon in the filter field.
148
149
  - `filterPlaceHolder` Optional placeholder text for the filter field.
149
- - `mainMenuLabel` Optional label for the main menu. By default, there is none.
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
+ }
@@ -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,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
+ }
package/dist/index.es.js CHANGED
@@ -1,19 +1,8 @@
1
1
  import React, { useEffect, useMemo, useRef } from 'react';
2
- import { getElementById, SlashMenuKey, dispatchWithMeta, SlashMetaTypes } from 'prosemirror-slash-menu';
2
+ import { SlashMenuKey, getElementById, dispatchWithMeta, SlashMetaTypes } from 'prosemirror-slash-menu';
3
3
  import { usePopper } from 'react-popper';
4
4
  import { setBlockType, toggleMark } from 'prosemirror-commands';
5
5
 
6
- const getElements = (state) => {
7
- const { subMenuId, filteredElements } = state;
8
- if (!subMenuId) {
9
- return filteredElements;
10
- }
11
- const subMenu = getElementById(subMenuId, state);
12
- if (subMenu && subMenu.type === "submenu") {
13
- return subMenu.elements;
14
- }
15
- };
16
-
17
6
  const ListItem = ({ menuState, id, Icon, idx, label }) => {
18
7
  useEffect(() => {
19
8
  const element = document.getElementById(id);
@@ -162,7 +151,25 @@ const defaultIcons = {
162
151
  ArrowRight,
163
152
  };
164
153
 
165
- const SlashMenuReact = ({ editorState, editorView, icons, subMenuIcon, }) => {
154
+ var Placement;
155
+ (function (Placement) {
156
+ Placement["auto"] = "auto";
157
+ Placement["autoStart"] = "auto-start";
158
+ Placement["autoEnd"] = "auto-end";
159
+ Placement["top"] = "top";
160
+ Placement["topStart"] = "top-start";
161
+ Placement["topEnd"] = "top-end";
162
+ Placement["bottom"] = "bottom";
163
+ Placement["bottomStart"] = "bottom-start";
164
+ Placement["bottomEnd"] = "bottom-end";
165
+ Placement["right"] = "right";
166
+ Placement["rightStart"] = "right-start";
167
+ Placement["rightEnd"] = "right-end";
168
+ Placement["left"] = "left";
169
+ Placement["leftStart"] = "left-start";
170
+ Placement["leftEnd"] = "left-end";
171
+ })(Placement || (Placement = {}));
172
+ const SlashMenuReact = ({ editorState, editorView, icons, subMenuIcon, filterFieldIcon, filterPlaceHolder, mainMenuLabel, popperReference, popperOptions, }) => {
166
173
  const menuState = useMemo(() => {
167
174
  if (!editorState)
168
175
  return;
@@ -171,7 +178,7 @@ const SlashMenuReact = ({ editorState, editorView, icons, subMenuIcon, }) => {
171
178
  const elements = useMemo(() => {
172
179
  if (!menuState)
173
180
  return;
174
- return getElements(menuState);
181
+ return menuState.filteredElements;
175
182
  }, [menuState]);
176
183
  const rootRef = useRef(null);
177
184
  useEffect(() => {
@@ -225,15 +232,28 @@ const SlashMenuReact = ({ editorState, editorView, icons, subMenuIcon, }) => {
225
232
  },
226
233
  };
227
234
  }, [editorState, window.scrollY]);
228
- const { styles, attributes } = usePopper(virtualReference, popperElement, {
235
+ const offsetModifier = useMemo(() => {
236
+ const filterElement = document.getElementById("menu-filter-wrapper");
237
+ filterElement === null || filterElement === void 0 ? void 0 : filterElement.getBoundingClientRect().top;
238
+ return {
239
+ name: "offset",
240
+ options: {
241
+ offset: [0, 36],
242
+ },
243
+ };
244
+ }, [popperReference]);
245
+ const { styles, attributes } = usePopper(popperReference || virtualReference, popperElement, {
246
+ placement: (popperOptions === null || popperOptions === void 0 ? void 0 : popperOptions.placement)
247
+ ? popperOptions.placement
248
+ : Placement.bottomStart,
229
249
  modifiers: [
230
250
  { name: "flip", enabled: true },
231
251
  {
232
252
  name: "preventOverflow",
233
- options: {
234
- mainAxis: false,
235
- },
236
253
  },
254
+ (popperOptions === null || popperOptions === void 0 ? void 0 : popperOptions.offsetModifier)
255
+ ? popperOptions.offsetModifier
256
+ : offsetModifier,
237
257
  ],
238
258
  });
239
259
  useEffect(() => {
@@ -280,18 +300,26 @@ const SlashMenuReact = ({ editorState, editorView, icons, subMenuIcon, }) => {
280
300
  return (_a = getElementById(menuState.subMenuId, menuState)) === null || _a === void 0 ? void 0 : _a.label;
281
301
  }
282
302
  }, [menuState]);
303
+ useEffect(() => {
304
+ editorView.focus();
305
+ }, [menuState === null || menuState === void 0 ? void 0 : menuState.open]);
283
306
  return (React.createElement(React.Fragment, null, (menuState === null || menuState === void 0 ? void 0 : menuState.open) ? (React.createElement("div", Object.assign({
284
307
  // @ts-ignore
285
308
  ref: setPopperElement, style: Object.assign({}, styles.popper) }, attributes.popper),
286
309
  menuState.filter ? (React.createElement("div", { className: "menu-filter-wrapper" },
287
- React.createElement("div", { id: "menu-filter", className: "menu-filter" }, menuState.filter))) : null,
310
+ filterFieldIcon ? (React.createElement("div", { className: "menu-filter-icon" }, filterFieldIcon)) : null,
311
+ React.createElement("div", { id: "menu-filter", className: "menu-filter" }, menuState.filter))) : (React.createElement("div", { className: "menu-filter-wrapper" },
312
+ filterFieldIcon ? (React.createElement("div", { className: "menu-filter-icon" }, filterFieldIcon)) : null,
313
+ React.createElement("div", { className: "menu-filter-placeholder" }, filterPlaceHolder))),
288
314
  React.createElement("div", { id: "slashDisplay", ref: rootRef, className: "menu-display-root" },
289
315
  menuState.subMenuId ? (React.createElement("div", { className: "menu-element-wrapper" },
290
- React.createElement("div", { className: "menu-element-icon" }, subMenuIcon || defaultIcons.ArrowLeft()),
291
- React.createElement("div", { className: "submenu-label" }, subMenuLabel))) : null, elements === null || elements === void 0 ? void 0 :
316
+ React.createElement("div", { className: "menu-element-icon-left" }, subMenuIcon || defaultIcons.ArrowLeft()),
317
+ React.createElement("div", { className: "submenu-label" }, subMenuLabel))) : null,
318
+ !menuState.subMenuId && mainMenuLabel ? (React.createElement("div", { className: "menu-element-wrapper" },
319
+ React.createElement("div", { className: "submenu-label" }, mainMenuLabel))) : null, elements === null || elements === void 0 ? void 0 :
292
320
  elements.map((el, idx) => (React.createElement(ListItem, { key: el.id, menuState: menuState, id: el.id, Icon: icons === null || icons === void 0 ? void 0 : icons[el.id], idx: idx, label: el.label }))),
293
321
  (elements === null || elements === void 0 ? void 0 : elements.length) === 0 ? (React.createElement("div", { className: "menu-placeholder" }, "No matching items")) : null))) : null));
294
322
  };
295
323
 
296
- export { Icons, SlashMenuReact, defaultElements, defaultIcons };
324
+ export { Icons, Placement, SlashMenuReact, defaultElements, defaultIcons };
297
325
  //# sourceMappingURL=index.es.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.es.js","sources":[],"sourcesContent":[],"names":[],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;"}
1
+ {"version":3,"file":"index.es.js","sources":[],"sourcesContent":[],"names":[],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;"}
package/dist/index.js CHANGED
@@ -11,17 +11,6 @@ function _interopDefaultLegacy (e) { return e && typeof e === 'object' && 'defau
11
11
 
12
12
  var React__default = /*#__PURE__*/_interopDefaultLegacy(React);
13
13
 
14
- const getElements = (state) => {
15
- const { subMenuId, filteredElements } = state;
16
- if (!subMenuId) {
17
- return filteredElements;
18
- }
19
- const subMenu = prosemirrorSlashMenu.getElementById(subMenuId, state);
20
- if (subMenu && subMenu.type === "submenu") {
21
- return subMenu.elements;
22
- }
23
- };
24
-
25
14
  const ListItem = ({ menuState, id, Icon, idx, label }) => {
26
15
  React.useEffect(() => {
27
16
  const element = document.getElementById(id);
@@ -170,7 +159,25 @@ const defaultIcons = {
170
159
  ArrowRight,
171
160
  };
172
161
 
173
- const SlashMenuReact = ({ editorState, editorView, icons, subMenuIcon, }) => {
162
+ exports.Placement = void 0;
163
+ (function (Placement) {
164
+ Placement["auto"] = "auto";
165
+ Placement["autoStart"] = "auto-start";
166
+ Placement["autoEnd"] = "auto-end";
167
+ Placement["top"] = "top";
168
+ Placement["topStart"] = "top-start";
169
+ Placement["topEnd"] = "top-end";
170
+ Placement["bottom"] = "bottom";
171
+ Placement["bottomStart"] = "bottom-start";
172
+ Placement["bottomEnd"] = "bottom-end";
173
+ Placement["right"] = "right";
174
+ Placement["rightStart"] = "right-start";
175
+ Placement["rightEnd"] = "right-end";
176
+ Placement["left"] = "left";
177
+ Placement["leftStart"] = "left-start";
178
+ Placement["leftEnd"] = "left-end";
179
+ })(exports.Placement || (exports.Placement = {}));
180
+ const SlashMenuReact = ({ editorState, editorView, icons, subMenuIcon, filterFieldIcon, filterPlaceHolder, mainMenuLabel, popperReference, popperOptions, }) => {
174
181
  const menuState = React.useMemo(() => {
175
182
  if (!editorState)
176
183
  return;
@@ -179,7 +186,7 @@ const SlashMenuReact = ({ editorState, editorView, icons, subMenuIcon, }) => {
179
186
  const elements = React.useMemo(() => {
180
187
  if (!menuState)
181
188
  return;
182
- return getElements(menuState);
189
+ return menuState.filteredElements;
183
190
  }, [menuState]);
184
191
  const rootRef = React.useRef(null);
185
192
  React.useEffect(() => {
@@ -233,15 +240,28 @@ const SlashMenuReact = ({ editorState, editorView, icons, subMenuIcon, }) => {
233
240
  },
234
241
  };
235
242
  }, [editorState, window.scrollY]);
236
- const { styles, attributes } = reactPopper.usePopper(virtualReference, popperElement, {
243
+ const offsetModifier = React.useMemo(() => {
244
+ const filterElement = document.getElementById("menu-filter-wrapper");
245
+ filterElement === null || filterElement === void 0 ? void 0 : filterElement.getBoundingClientRect().top;
246
+ return {
247
+ name: "offset",
248
+ options: {
249
+ offset: [0, 36],
250
+ },
251
+ };
252
+ }, [popperReference]);
253
+ const { styles, attributes } = reactPopper.usePopper(popperReference || virtualReference, popperElement, {
254
+ placement: (popperOptions === null || popperOptions === void 0 ? void 0 : popperOptions.placement)
255
+ ? popperOptions.placement
256
+ : exports.Placement.bottomStart,
237
257
  modifiers: [
238
258
  { name: "flip", enabled: true },
239
259
  {
240
260
  name: "preventOverflow",
241
- options: {
242
- mainAxis: false,
243
- },
244
261
  },
262
+ (popperOptions === null || popperOptions === void 0 ? void 0 : popperOptions.offsetModifier)
263
+ ? popperOptions.offsetModifier
264
+ : offsetModifier,
245
265
  ],
246
266
  });
247
267
  React.useEffect(() => {
@@ -288,15 +308,23 @@ const SlashMenuReact = ({ editorState, editorView, icons, subMenuIcon, }) => {
288
308
  return (_a = prosemirrorSlashMenu.getElementById(menuState.subMenuId, menuState)) === null || _a === void 0 ? void 0 : _a.label;
289
309
  }
290
310
  }, [menuState]);
311
+ React.useEffect(() => {
312
+ editorView.focus();
313
+ }, [menuState === null || menuState === void 0 ? void 0 : menuState.open]);
291
314
  return (React__default["default"].createElement(React__default["default"].Fragment, null, (menuState === null || menuState === void 0 ? void 0 : menuState.open) ? (React__default["default"].createElement("div", Object.assign({
292
315
  // @ts-ignore
293
316
  ref: setPopperElement, style: Object.assign({}, styles.popper) }, attributes.popper),
294
317
  menuState.filter ? (React__default["default"].createElement("div", { className: "menu-filter-wrapper" },
295
- React__default["default"].createElement("div", { id: "menu-filter", className: "menu-filter" }, menuState.filter))) : null,
318
+ filterFieldIcon ? (React__default["default"].createElement("div", { className: "menu-filter-icon" }, filterFieldIcon)) : null,
319
+ React__default["default"].createElement("div", { id: "menu-filter", className: "menu-filter" }, menuState.filter))) : (React__default["default"].createElement("div", { className: "menu-filter-wrapper" },
320
+ filterFieldIcon ? (React__default["default"].createElement("div", { className: "menu-filter-icon" }, filterFieldIcon)) : null,
321
+ React__default["default"].createElement("div", { className: "menu-filter-placeholder" }, filterPlaceHolder))),
296
322
  React__default["default"].createElement("div", { id: "slashDisplay", ref: rootRef, className: "menu-display-root" },
297
323
  menuState.subMenuId ? (React__default["default"].createElement("div", { className: "menu-element-wrapper" },
298
- React__default["default"].createElement("div", { className: "menu-element-icon" }, subMenuIcon || defaultIcons.ArrowLeft()),
299
- React__default["default"].createElement("div", { className: "submenu-label" }, subMenuLabel))) : null, elements === null || elements === void 0 ? void 0 :
324
+ React__default["default"].createElement("div", { className: "menu-element-icon-left" }, subMenuIcon || defaultIcons.ArrowLeft()),
325
+ React__default["default"].createElement("div", { className: "submenu-label" }, subMenuLabel))) : null,
326
+ !menuState.subMenuId && mainMenuLabel ? (React__default["default"].createElement("div", { className: "menu-element-wrapper" },
327
+ React__default["default"].createElement("div", { className: "submenu-label" }, mainMenuLabel))) : null, elements === null || elements === void 0 ? void 0 :
300
328
  elements.map((el, idx) => (React__default["default"].createElement(ListItem, { key: el.id, menuState: menuState, id: el.id, Icon: icons === null || icons === void 0 ? void 0 : icons[el.id], idx: idx, label: el.label }))),
301
329
  (elements === null || elements === void 0 ? void 0 : elements.length) === 0 ? (React__default["default"].createElement("div", { className: "menu-placeholder" }, "No matching items")) : null))) : null));
302
330
  };
package/dist/index.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","sources":[],"sourcesContent":[],"names":[],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;"}
1
+ {"version":3,"file":"index.js","sources":[],"sourcesContent":[],"names":[],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;"}
@@ -1,4 +1,5 @@
1
1
  import { CommandItem, SubMenu } from "prosemirror-slash-menu";
2
+ import React from "react";
2
3
  export declare enum Icons {
3
4
  "HeaderMenu" = "HeaderMenu",
4
5
  "Level1" = "Level1",
@@ -10,7 +11,6 @@ export declare enum Icons {
10
11
  "Code" = "Code"
11
12
  }
12
13
  export declare const defaultElements: (CommandItem | SubMenu)[];
13
- import React from "react";
14
14
  export declare const defaultIcons: {
15
15
  H1Icon: () => React.JSX.Element;
16
16
  H2Icon: () => React.JSX.Element;
@@ -2,6 +2,32 @@ import { FC, ReactNode } from "react";
2
2
  import { EditorState } from "prosemirror-state";
3
3
  import { EditorView } from "prosemirror-view";
4
4
  import "./styles/menu-style.css";
5
+ export declare enum Placement {
6
+ auto = "auto",
7
+ autoStart = "auto-start",
8
+ autoEnd = "auto-end",
9
+ top = "top",
10
+ topStart = "top-start",
11
+ topEnd = "top-end",
12
+ bottom = "bottom",
13
+ bottomStart = "bottom-start",
14
+ bottomEnd = "bottom-end",
15
+ right = "right",
16
+ rightStart = "right-start",
17
+ rightEnd = "right-end",
18
+ left = "left",
19
+ leftStart = "left-start",
20
+ leftEnd = "left-end"
21
+ }
22
+ export interface PopperOptions {
23
+ placement: Placement;
24
+ offsetModifier: {
25
+ name: string;
26
+ options: {
27
+ offset: number[];
28
+ };
29
+ };
30
+ }
5
31
  export interface SlashMenuProps {
6
32
  editorState: EditorState;
7
33
  editorView: EditorView;
@@ -9,5 +35,10 @@ export interface SlashMenuProps {
9
35
  [key: string]: FC;
10
36
  };
11
37
  subMenuIcon?: ReactNode;
38
+ filterFieldIcon?: ReactNode;
39
+ filterPlaceHolder?: string;
40
+ mainMenuLabel?: string;
41
+ popperReference?: HTMLElement;
42
+ popperOptions?: PopperOptions;
12
43
  }
13
44
  export declare const SlashMenuReact: FC<SlashMenuProps>;
@@ -1,60 +1,73 @@
1
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;
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;
12
13
  }
13
14
 
14
15
  .menu-element-wrapper {
15
- display: flex;
16
- border-radius: 0.3rem;
17
- padding: 0.2rem 0.5rem;
16
+ display: flex;
17
+ border-radius: 0.3rem;
18
+ padding: 0.2rem 0.5rem;
18
19
  }
19
20
 
20
21
  .menu-element-selected {
21
- background-color: #f1f1f1;
22
+ background-color: #f1f1f1;
22
23
  }
23
24
 
24
25
  .menu-element-icon {
25
- width: 23px;
26
- height: auto;
27
- display: flex;
28
- align-items: center;
26
+ width: 23px;
27
+ height: auto;
28
+ display: flex;
29
+ align-items: center;
29
30
  }
30
31
 
31
32
  .menu-element-label {
32
- color: black;
33
- display: flex;
34
- align-items: center;
35
- margin-left: 0.5rem;
33
+ color: black;
34
+ display: flex;
35
+ align-items: center;
36
+ margin-left: 0.5rem;
36
37
  }
37
38
 
38
39
  .menu-placeholder {
39
- color: #aaaaaa;
40
- text-align: center;
41
- padding-top: 1rem;
40
+ color: #aaaaaa;
41
+ text-align: center;
42
+ padding: 0 0.5rem;
42
43
  }
43
44
 
44
45
  .menu-filter-wrapper {
45
- display: flex;
46
- background-color: transparent;
47
- padding: 0.2rem 0.5rem;
48
- position: absolute;
49
- top: -1.5rem;
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;
50
59
  }
51
60
 
52
61
  .menu-filter {
53
- color: #aaaaaa;
54
- font-style: italic;
62
+ color: #aaaaaa;
63
+ font-style: italic
55
64
  }
56
65
 
66
+ .menu-filter-placeholder {
67
+ color: #aaaaaa;
68
+ font-style: italic
69
+ }
57
70
 
58
- .submenu-label{
59
- margin-left: 0.5rem;
71
+ .submenu-label {
72
+ margin-left: 0.5rem;
60
73
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "prosemirror-slash-menu-react",
3
- "version": "0.0.4",
3
+ "version": "0.0.5",
4
4
  "description": "Implementation of prosemirror-slash-menu in react",
5
5
  "main": "dist/index.js",
6
6
  "module": "dist/index.es.js",
@@ -20,7 +20,7 @@
20
20
  "prettier": "^2.8.8",
21
21
  "prosemirror-commands": "^1.5.2",
22
22
  "prosemirror-schema-basic": "^1.2.2",
23
- "prosemirror-slash-menu": "^0.1.2",
23
+ "prosemirror-slash-menu": "^0.1.4",
24
24
  "prosemirror-view": "^1.31.4",
25
25
  "react": "^18.2.0",
26
26
  "react-dom": "^18.2.0",
@@ -1,9 +0,0 @@
1
- import { FC } from "react";
2
- import { SlashMenuState } from "prosemirror-slash-menu";
3
- export declare const ListItem: FC<{
4
- menuState: SlashMenuState;
5
- id: string;
6
- Icon?: FC;
7
- idx: number;
8
- label: string;
9
- }>;
@@ -1,11 +0,0 @@
1
- import { SlashMenuState } from "prosemirror-slash-menu";
2
- export declare enum Icons {
3
- "Level1" = "Level1",
4
- "Level2" = "Level2",
5
- "Level3" = "Level3",
6
- "Bold" = "Bold",
7
- "Italic" = "Italic",
8
- "Link" = "Link",
9
- "Code" = "Code"
10
- }
11
- export declare const defaultConfig: Partial<SlashMenuState>;
@@ -1,17 +0,0 @@
1
- import { FC } from "react";
2
- import { EditorState } from "prosemirror-state";
3
- import { EditorView } from "prosemirror-view";
4
- export interface SlashMenuDisplayConfig {
5
- height: number;
6
- minHeight: number;
7
- overflowPadding: number;
8
- }
9
- export interface SlashMenuProps {
10
- editorState: EditorState;
11
- editorView: EditorView;
12
- config: SlashMenuDisplayConfig;
13
- icons?: {
14
- [key: string]: FC;
15
- };
16
- }
17
- export declare const SlashMenuDisplay: FC<SlashMenuProps>;
@@ -1,2 +0,0 @@
1
- import { SlashMenuState } from "prosemirror-slash-menu";
2
- export declare const getElements: (state: SlashMenuState) => import("prosemirror-slash-menu").MenuElement[] | undefined;