@manuscripts/body-editor 3.16.3 → 3.17.1

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.
Files changed (55) hide show
  1. package/dist/cjs/lib/context-menu.js +28 -11
  2. package/dist/cjs/lib/popper.js +18 -3
  3. package/dist/cjs/lib/position-menu.js +175 -100
  4. package/dist/cjs/lib/view.js +10 -1
  5. package/dist/cjs/plugins/detect-inconsistency/index.js +6 -4
  6. package/dist/cjs/plugins/persist.js +3 -0
  7. package/dist/cjs/versions.js +1 -1
  8. package/dist/cjs/views/box_element.js +23 -1
  9. package/dist/cjs/views/caption_title.js +1 -1
  10. package/dist/cjs/views/footnote.js +43 -18
  11. package/dist/cjs/views/general_table_footnote.js +31 -21
  12. package/dist/cjs/views/image_element.js +7 -62
  13. package/dist/cjs/views/pullquote_element.js +23 -1
  14. package/dist/cjs/views/table_element.js +23 -1
  15. package/dist/es/lib/context-menu.js +29 -12
  16. package/dist/es/lib/popper.js +18 -3
  17. package/dist/es/lib/position-menu.js +173 -91
  18. package/dist/es/lib/view.js +8 -0
  19. package/dist/es/plugins/detect-inconsistency/index.js +6 -4
  20. package/dist/es/plugins/persist.js +3 -0
  21. package/dist/es/versions.js +1 -1
  22. package/dist/es/views/box_element.js +23 -1
  23. package/dist/es/views/caption_title.js +1 -1
  24. package/dist/es/views/footnote.js +43 -18
  25. package/dist/es/views/general_table_footnote.js +31 -21
  26. package/dist/es/views/image_element.js +7 -62
  27. package/dist/es/views/pullquote_element.js +23 -1
  28. package/dist/es/views/table_element.js +23 -1
  29. package/dist/types/lib/popper.d.ts +4 -2
  30. package/dist/types/lib/position-menu.d.ts +36 -11
  31. package/dist/types/lib/view.d.ts +3 -1
  32. package/dist/types/versions.d.ts +1 -1
  33. package/dist/types/views/box_element.d.ts +6 -0
  34. package/dist/types/views/footnote.d.ts +5 -2
  35. package/dist/types/views/general_table_footnote.d.ts +2 -2
  36. package/dist/types/views/image_element.d.ts +2 -9
  37. package/dist/types/views/pullquote_element.d.ts +6 -0
  38. package/dist/types/views/table_element.d.ts +6 -0
  39. package/package.json +2 -2
  40. package/src/lib/context-menu.ts +42 -21
  41. package/src/lib/popper.ts +23 -4
  42. package/src/lib/position-menu.ts +243 -137
  43. package/src/lib/view.ts +17 -0
  44. package/src/plugins/detect-inconsistency/index.ts +6 -4
  45. package/src/plugins/persist.ts +3 -0
  46. package/src/versions.ts +1 -1
  47. package/src/views/box_element.ts +34 -1
  48. package/src/views/caption_title.ts +1 -1
  49. package/src/views/footnote.ts +69 -33
  50. package/src/views/general_table_footnote.ts +43 -20
  51. package/src/views/image_element.ts +12 -89
  52. package/src/views/pullquote_element.ts +33 -1
  53. package/src/views/table_element.ts +34 -1
  54. package/styles/AdvancedEditor.css +5 -8
  55. package/styles/Editor.css +9 -5
@@ -16,17 +16,11 @@
16
16
  import { ImageElementNode } from '@manuscripts/transform';
17
17
  import { Trackable } from '../types';
18
18
  import BlockView from './block_view';
19
- export declare enum figurePositions {
20
- left = "half-left",
21
- right = "half-right",
22
- default = ""
23
- }
24
19
  export declare class ImageElementView extends BlockView<Trackable<ImageElementNode>> {
25
20
  container: HTMLElement;
26
21
  subcontainer: HTMLElement;
27
22
  extLinkEditorContainer: HTMLDivElement;
28
- private positionMenuWrapper;
29
- private figurePosition;
23
+ private positionMenu;
30
24
  private isEditingExtLink;
31
25
  ignoreMutation: () => boolean;
32
26
  upload: (file: File) => Promise<void>;
@@ -35,10 +29,9 @@ export declare class ImageElementView extends BlockView<Trackable<ImageElementNo
35
29
  createElement(): void;
36
30
  updateContents(): void;
37
31
  protected addTools(): void;
38
- protected addPositionMenu(): void;
39
32
  private getFirstFigure;
40
33
  private getAllFigures;
41
- private showPositionMenu;
34
+ protected addPositionMenu(): void;
42
35
  private updateAllFiguresPosition;
43
36
  private removeExtLink;
44
37
  private setExtLink;
@@ -18,6 +18,8 @@ import BlockView from './block_view';
18
18
  export declare class PullquoteElementView extends BlockView<PullquoteElementNode> {
19
19
  elementType: string;
20
20
  contextMenu: HTMLElement;
21
+ container: HTMLDivElement;
22
+ private positionMenu;
21
23
  ignoreMutation: () => boolean;
22
24
  stopEvent: () => boolean;
23
25
  private handleClick;
@@ -25,7 +27,11 @@ export declare class PullquoteElementView extends BlockView<PullquoteElementNode
25
27
  handleAddFigure(): void;
26
28
  actionGutterButtons: () => HTMLElement[];
27
29
  addFigureContextMenu: () => HTMLElement | undefined;
30
+ updateContents(): void;
28
31
  destroy: () => void;
32
+ protected addTools(): void;
33
+ protected addPositionMenu(): void;
34
+ private updateHorizontalPosition;
29
35
  }
30
36
  declare const _default: (props: import("../configs/ManuscriptsEditor").EditorProps) => import("../types").NodeViewCreator<PullquoteElementView>;
31
37
  export default _default;
@@ -17,7 +17,13 @@ import { TableElementNode } from '@manuscripts/transform';
17
17
  import BlockView from './block_view';
18
18
  export declare class TableElementView extends BlockView<TableElementNode> {
19
19
  elementType: string;
20
+ container: HTMLDivElement;
21
+ private positionMenu;
20
22
  createElement: () => void;
23
+ updateContents(): void;
24
+ protected addTools(): void;
25
+ protected addPositionMenu(): void;
26
+ private updateHorizontalPosition;
21
27
  }
22
28
  declare const _default: (props: import("../configs/ManuscriptsEditor").EditorProps, dispatch?: import("..").Dispatch) => import("../types").NodeViewCreator<TableElementView>;
23
29
  export default _default;
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@manuscripts/body-editor",
3
3
  "description": "Prosemirror components for editing and viewing manuscripts",
4
- "version": "3.16.3",
4
+ "version": "3.17.1",
5
5
  "repository": "github:Atypon-OpenSource/manuscripts-body-editor",
6
6
  "license": "Apache-2.0",
7
7
  "main": "dist/cjs",
@@ -43,7 +43,7 @@
43
43
  "@iarna/word-count": "1.1.2",
44
44
  "@manuscripts/style-guide": "3.7.1",
45
45
  "@manuscripts/track-changes-plugin": "2.4.0",
46
- "@manuscripts/transform": "4.5.1",
46
+ "@manuscripts/transform": "4.5.2",
47
47
  "@popperjs/core": "2.11.8",
48
48
  "citeproc": "2.4.63",
49
49
  "codemirror": "5.65.19",
@@ -42,7 +42,7 @@ import {
42
42
  insertInlineTableFootnote,
43
43
  } from '../commands'
44
44
  import { PopperManager } from './popper'
45
- import { createPositionOptions } from './position-menu'
45
+ import { HorizontalPositionMenu } from './position-menu'
46
46
  import { templateAllows } from './template'
47
47
  import {
48
48
  getMatchingChild,
@@ -59,9 +59,18 @@ const readonlyTypes = [
59
59
  schema.nodes.footnotes_section,
60
60
  ]
61
61
 
62
- const isBoxElementSectionTitle = ($pos: ResolvedPos, node: ManuscriptNode) =>
63
- isSectionTitleNode(node) &&
64
- $pos.node($pos.depth - 1).type === schema.nodes.box_element
62
+ const getBoxElementOfSectionTitle = (
63
+ $pos: ResolvedPos,
64
+ node: ManuscriptNode
65
+ ) => {
66
+ if (isSectionTitleNode(node)) {
67
+ const parent = $pos.node($pos.depth - 1)
68
+ if (parent.type === schema.nodes.box_element) {
69
+ return parent
70
+ }
71
+ }
72
+ return null
73
+ }
65
74
 
66
75
  export const sectionLevel = (depth: number) => {
67
76
  switch (depth) {
@@ -245,31 +254,43 @@ export class ContextMenu {
245
254
  menu.className = 'menu'
246
255
 
247
256
  const $pos = this.resolvePos()
248
- const isBox = isBoxElementSectionTitle($pos, this.node)
249
- const type = isBox ? schema.nodes.box_element : this.node.type
257
+ const boxParent = getBoxElementOfSectionTitle($pos, this.node)
258
+ const type = boxParent ? schema.nodes.box_element : this.node.type
250
259
 
251
- if (
252
- type === schema.nodes.figure_element ||
253
- type === schema.nodes.image_element
254
- ) {
260
+ const positionableTypes = [
261
+ schema.nodes.figure_element,
262
+ schema.nodes.image_element,
263
+ schema.nodes.box_element,
264
+ schema.nodes.pullquote_element,
265
+ schema.nodes.table_element,
266
+ ]
267
+
268
+ let nodeBase = this.node
269
+
270
+ if (positionableTypes.includes(type)) {
255
271
  const figure = getMatchingChild(
256
272
  this.node,
257
273
  (node) => node.type === schema.nodes.figure
258
274
  )
259
275
 
260
276
  if (figure) {
261
- const attrType = figure.attrs.type
262
- const submenuOptions = createPositionOptions(
263
- schema.nodes.figure,
264
- figure,
265
- attrType,
266
- this.view,
267
- () => popper.destroy()
268
- )
269
- const submenuLabel = 'Position'
270
- const submenu = this.createSubmenu(submenuLabel, submenuOptions)
271
- menu.appendChild(submenu)
277
+ nodeBase = figure
278
+ }
279
+
280
+ if (boxParent) {
281
+ nodeBase = boxParent
272
282
  }
283
+
284
+ const submenuOptions = HorizontalPositionMenu.createPositionOptions(
285
+ schema.nodes[nodeBase.type.name],
286
+ nodeBase,
287
+ nodeBase.attrs.type,
288
+ this.view,
289
+ () => popper.destroy()
290
+ )
291
+ const submenuLabel = 'Position'
292
+ const submenu = this.createSubmenu(submenuLabel, submenuOptions)
293
+ menu.appendChild(submenu)
273
294
  }
274
295
 
275
296
  if (type === schema.nodes.list) {
package/src/lib/popper.ts CHANGED
@@ -27,6 +27,7 @@ export class PopperManager {
27
27
  private handleDocumentClick?: (e: Event) => void
28
28
  private triggerElement?: Element
29
29
  private container?: HTMLElement
30
+ private destructionListener?: (i: Instance) => void
30
31
 
31
32
  public show(
32
33
  target: Element,
@@ -34,7 +35,9 @@ export class PopperManager {
34
35
  placement: Placement = 'bottom',
35
36
  showArrow = true,
36
37
  modifiers: Array<Partial<StrictModifiers>> = [],
37
- autoFocus = true
38
+ autoFocus = true,
39
+ autoCloseOnOutsideClick = true,
40
+ onDestroy: ((i: Instance) => void) | undefined = undefined
38
41
  ) {
39
42
  // destroy any existing popper first
40
43
  // checking activePopper is in destroy() method
@@ -42,6 +45,7 @@ export class PopperManager {
42
45
 
43
46
  // Store the trigger element to return focus later
44
47
  this.triggerElement = target
48
+ this.destructionListener = onDestroy
45
49
 
46
50
  window.requestAnimationFrame(() => {
47
51
  const container = document.createElement('div')
@@ -111,9 +115,10 @@ export class PopperManager {
111
115
  // add EventListener for checking if click was done outside of editor
112
116
  // only if popper has class 'context-menu'
113
117
  if (
114
- contents.classList.contains('context-menu') ||
115
- contents.classList.contains('language') ||
116
- contents.classList.contains('section-category')
118
+ (contents.classList.contains('context-menu') ||
119
+ contents.classList.contains('language') ||
120
+ contents.classList.contains('section-category')) &&
121
+ autoCloseOnOutsideClick
117
122
  ) {
118
123
  window.addEventListener('click', this.handleDocumentClick)
119
124
  }
@@ -125,6 +130,8 @@ export class PopperManager {
125
130
  this.removeContainerClass(
126
131
  this.activePopper.state.elements.reference as Element
127
132
  )
133
+ this.destructionListener?.(this.activePopper)
134
+ this.destructionListener = undefined
128
135
  this.activePopper.destroy()
129
136
  this.activePopper.state.elements.popper.remove()
130
137
  if (this.handleDocumentClick) {
@@ -146,6 +153,18 @@ export class PopperManager {
146
153
  }
147
154
  }
148
155
 
156
+ public replaceContent(newContent: HTMLElement) {
157
+ if (this.container && this.activePopper) {
158
+ const arrow = this.container.querySelector('.popper-arrow')
159
+ this.container.innerHTML = ''
160
+ if (arrow) {
161
+ this.container.appendChild(arrow)
162
+ }
163
+ this.container.appendChild(newContent)
164
+ this.activePopper.update()
165
+ }
166
+ }
167
+
149
168
  public isActive = () => !!this.activePopper
150
169
 
151
170
  private focusInput(container: HTMLDivElement, autoFocus = true) {
@@ -14,7 +14,7 @@
14
14
  * limitations under the License.
15
15
  */
16
16
 
17
- import { ContextMenu, ContextMenuProps } from '@manuscripts/style-guide'
17
+ import { ContextMenu } from '@manuscripts/style-guide'
18
18
  import {
19
19
  ManuscriptEditorView,
20
20
  ManuscriptNode,
@@ -23,10 +23,16 @@ import {
23
23
 
24
24
  import { EditorProps } from '../configs/ManuscriptsEditor'
25
25
  import { imageDefaultIcon, imageLeftIcon, imageRightIcon } from '../icons'
26
- import { figurePositions } from '../views/image_element'
27
- import ReactSubView from '../views/ReactSubView'
26
+ import { createSubViewAsync } from '../views/ReactSubView'
28
27
  import { handleEnterKey } from './navigation-utils'
29
28
  import { updateNodeAttrs } from './view'
29
+ import BlockView from '../views/block_view'
30
+
31
+ export enum HorizontalPositions {
32
+ left = 'half-left',
33
+ right = 'half-right',
34
+ default = '',
35
+ }
30
36
 
31
37
  export interface PopperMenuPositionOption {
32
38
  label: string
@@ -35,150 +41,250 @@ export interface PopperMenuPositionOption {
35
41
  selected: boolean
36
42
  }
37
43
 
38
- export const createPositionOptions = <T extends ManuscriptNode>(
39
- nodeType: ManuscriptNodeType,
40
- node: T,
41
- currentPosition: string,
42
- view: ManuscriptEditorView,
43
- onComplete?: () => void
44
- ) => {
45
- const createAction = (position: string) => () => {
46
- onComplete?.()
47
- updateNodeAttrs(view, nodeType, {
48
- ...node.attrs,
49
- type: position,
50
- })
44
+ export class HorizontalPositionMenu {
45
+ private parent: BlockView<ManuscriptNode>
46
+
47
+ menuOpen: boolean = false
48
+ posMenuSelector = 'position-menu'
49
+ onChange: (newPos: HorizontalPositions) => void
50
+ positionMenuWrapper: HTMLDivElement
51
+ location: HTMLElement
52
+ getPositionSource?: () => ManuscriptNode | null
53
+
54
+ constructor(
55
+ parent: BlockView<ManuscriptNode>,
56
+ onChange: (newPos: HorizontalPositions) => void,
57
+ location?: HTMLElement,
58
+ getPositionSource?: () => ManuscriptNode | null // if different from parent as in figure element case
59
+ ) {
60
+ const preSource = getPositionSource?.() || parent.node
61
+ if (typeof preSource.attrs.type === 'undefined') {
62
+ console.error("This node doesn't support horizontal alignment")
63
+ return
64
+ }
65
+ this.getPositionSource = getPositionSource
66
+ this.location = location || parent.dom
67
+ this.onChange = onChange.bind(parent)
68
+ this.parent = parent
51
69
  }
52
70
 
53
- return [
54
- {
55
- title: 'Left',
56
- action: createAction(figurePositions.left),
57
- IconComponent: imageLeftIcon,
58
- iconName: 'ImageLeft',
59
- selected: currentPosition === figurePositions.left,
60
- },
61
- {
62
- title: 'Center',
63
- action: createAction(figurePositions.default),
64
- IconComponent: imageDefaultIcon,
65
- iconName: 'ImageDefault',
66
- selected: !currentPosition,
67
- },
68
- {
69
- title: 'Right',
70
- action: createAction(figurePositions.right),
71
- IconComponent: imageRightIcon,
72
- iconName: 'ImageRight',
73
- selected: currentPosition === figurePositions.right,
74
- },
75
- ]
76
- }
71
+ static createPositionOptions<T extends ManuscriptNode>(
72
+ nodeType: ManuscriptNodeType,
73
+ node: T,
74
+ currentPosition: string,
75
+ view: ManuscriptEditorView,
76
+ onComplete?: () => void
77
+ ) {
78
+ const createAction = (position: string) => () => {
79
+ onComplete?.()
80
+ updateNodeAttrs(view, nodeType, {
81
+ ...node.attrs,
82
+ type: position,
83
+ })
84
+ }
77
85
 
78
- export const createPopperMenuPositionOptions = <T extends ManuscriptNode>(
79
- nodeType: ManuscriptNodeType,
80
- node: T,
81
- currentPosition: string,
82
- view: ManuscriptEditorView,
83
- onComplete?: () => void
84
- ): PopperMenuPositionOption[] => {
85
- return createPositionOptions(
86
- nodeType,
87
- node,
88
- currentPosition,
89
- view,
90
- onComplete
91
- ).map((option) => ({
92
- label: option.title,
93
- action: option.action,
94
- icon: option.iconName,
95
- selected: option.selected,
96
- }))
97
- }
86
+ return [
87
+ {
88
+ title: 'Left',
89
+ action: createAction(HorizontalPositions.left),
90
+ IconComponent: imageLeftIcon,
91
+ iconName: 'ImageLeft',
92
+ selected: currentPosition === HorizontalPositions.left,
93
+ },
94
+ {
95
+ title: 'Default',
96
+ action: createAction(HorizontalPositions.default),
97
+ IconComponent: imageDefaultIcon,
98
+ iconName: 'ImageDefault',
99
+ selected:
100
+ !currentPosition || currentPosition === HorizontalPositions.default,
101
+ },
102
+ {
103
+ title: 'Right',
104
+ action: createAction(HorizontalPositions.right),
105
+ IconComponent: imageRightIcon,
106
+ iconName: 'ImageRight',
107
+ selected: currentPosition === HorizontalPositions.right,
108
+ },
109
+ ]
110
+ }
98
111
 
99
- export const showPositionMenu = <T extends ManuscriptNode>(
100
- nodeType: ManuscriptNodeType,
101
- node: T,
102
- currentPosition: string,
103
- positionMenuWrapper: HTMLElement,
104
- view: ManuscriptEditorView,
105
- getPos: () => number,
106
- props: EditorProps
107
- ) => {
108
- props.popper.destroy()
109
-
110
- const options = createPopperMenuPositionOptions(
111
- nodeType,
112
- node,
113
- currentPosition,
114
- view,
115
- () => props.popper.destroy()
116
- )
117
-
118
- const componentProps: ContextMenuProps = {
119
- actions: options,
112
+ createPopperMenuPositionOptions<T extends ManuscriptNode>(
113
+ nodeType: ManuscriptNodeType,
114
+ node: T,
115
+ currentPosition: string,
116
+ view: ManuscriptEditorView,
117
+ onComplete?: () => void
118
+ ): PopperMenuPositionOption[] {
119
+ return HorizontalPositionMenu.createPositionOptions(
120
+ nodeType,
121
+ node,
122
+ currentPosition,
123
+ view,
124
+ onComplete
125
+ ).map((option) => ({
126
+ label: option.title,
127
+ action: option.action,
128
+ icon: option.iconName,
129
+ selected: option.selected,
130
+ }))
120
131
  }
121
132
 
122
- props.popper.show(
123
- positionMenuWrapper,
124
- ReactSubView(props, ContextMenu, componentProps, node, getPos, view, [
125
- 'context-menu',
126
- 'position-menu',
127
- ]),
128
- 'left',
129
- false
130
- )
131
- }
133
+ buttonClass = 'position-menu-button'
134
+
135
+ createPositionMenuWrapper(currentPosition: string, props: EditorProps) {
136
+ const can = props.getCapabilities()
137
+ const positionMenuWrapper = document.createElement('div')
138
+ positionMenuWrapper.classList.add(this.posMenuSelector)
139
+
140
+ const positionMenuButton = document.createElement('div')
141
+ positionMenuButton.classList.add(this.buttonClass)
132
142
 
133
- export const setElementPositionAlignment = (
134
- element: HTMLElement,
135
- position: string
136
- ): void => {
137
- switch (position) {
138
- case figurePositions.left:
139
- element.setAttribute('data-alignment', 'left')
140
- break
141
- case figurePositions.right:
142
- element.setAttribute('data-alignment', 'right')
143
- break
144
- default:
145
- element.removeAttribute('data-alignment')
146
- break
143
+ let icon
144
+ switch (currentPosition) {
145
+ case HorizontalPositions.left:
146
+ icon = imageLeftIcon
147
+ break
148
+ case HorizontalPositions.right:
149
+ icon = imageRightIcon
150
+ break
151
+ default:
152
+ icon = imageDefaultIcon
153
+ break
154
+ }
155
+ if (icon) {
156
+ positionMenuButton.innerHTML = icon
157
+ }
158
+ const onClick = () => {
159
+ this.showPositionMenu()
160
+ }
161
+ if (can.editArticle) {
162
+ positionMenuButton.tabIndex = -1
163
+
164
+ positionMenuButton.addEventListener('click', onClick)
165
+ positionMenuButton.addEventListener('keydown', handleEnterKey(onClick))
166
+ }
167
+
168
+ if (this.positionMenuWrapper) {
169
+ const button = this.positionMenuWrapper.querySelector(
170
+ '.' + this.buttonClass
171
+ )
172
+ if (button) {
173
+ this.positionMenuWrapper.removeChild(button)
174
+ this.positionMenuWrapper.appendChild(positionMenuButton)
175
+ }
176
+ } else {
177
+ positionMenuWrapper.appendChild(positionMenuButton)
178
+ this.positionMenuWrapper = positionMenuWrapper
179
+ this.location.prepend(this.positionMenuWrapper)
180
+ }
147
181
  }
148
- }
149
182
 
150
- export const createPositionMenuWrapper = (
151
- currentPosition: string,
152
- onClick: () => void,
153
- props: EditorProps
154
- ): HTMLDivElement => {
155
- const can = props.getCapabilities()
156
- const positionMenuWrapper = document.createElement('div')
157
- positionMenuWrapper.classList.add('position-menu')
158
-
159
- const positionMenuButton = document.createElement('div')
160
- positionMenuButton.classList.add('position-menu-button')
161
-
162
- let icon
163
- switch (currentPosition) {
164
- case figurePositions.left:
165
- icon = imageLeftIcon
166
- break
167
- case figurePositions.right:
168
- icon = imageRightIcon
169
- break
170
- default:
171
- icon = imageDefaultIcon
172
- break
183
+ getHorizontalPositionOptions(
184
+ current: string,
185
+ onPick: (newPos: HorizontalPositions) => void,
186
+ destroy: () => void
187
+ ) {
188
+ const componentProps = {
189
+ actions: [
190
+ {
191
+ label: 'Left',
192
+ action: () => {
193
+ destroy()
194
+ this.menuOpen = false
195
+ onPick(HorizontalPositions.left)
196
+ },
197
+ icon: 'ImageLeft',
198
+ selected: current === HorizontalPositions.left,
199
+ },
200
+ {
201
+ label: 'Default',
202
+ action: () => {
203
+ destroy()
204
+ this.menuOpen = false
205
+ onPick(HorizontalPositions.default)
206
+ },
207
+ icon: 'ImageDefault',
208
+ selected: !current,
209
+ },
210
+ {
211
+ label: 'Right',
212
+ action: () => {
213
+ destroy()
214
+ this.menuOpen = false
215
+ onPick(HorizontalPositions.right)
216
+ },
217
+ icon: 'ImageRight',
218
+ selected: current === HorizontalPositions.right,
219
+ },
220
+ ],
221
+ }
222
+
223
+ return componentProps
173
224
  }
174
- if (icon) {
175
- positionMenuButton.innerHTML = icon
225
+
226
+ showPositionMenu(force = false) {
227
+ const p = this.parent
228
+
229
+ if (this.menuOpen && !force) {
230
+ // Toggle off on click
231
+ p.props.popper.destroy()
232
+ this.menuOpen = false
233
+ return
234
+ }
235
+ const posSource = this.getPositionSource
236
+ ? this.getPositionSource()
237
+ : this.parent.node
238
+
239
+ const componentProps = this.getHorizontalPositionOptions(
240
+ posSource?.attrs.type || HorizontalPositions.default,
241
+ this.onChange,
242
+ p.props.popper.destroy.bind(p.props.popper)
243
+ )
244
+
245
+ createSubViewAsync(
246
+ p.props,
247
+ ContextMenu,
248
+ componentProps,
249
+ p.node,
250
+ p.getPos,
251
+ p.view,
252
+ ['context-menu', this.posMenuSelector]
253
+ ).then((content) => {
254
+ if (this.menuOpen && p.props.popper.isActive()) {
255
+ p.props.popper.replaceContent(content)
256
+ } else {
257
+ p.props.popper.show(
258
+ this.positionMenuWrapper,
259
+ content,
260
+ 'left',
261
+ false,
262
+ [],
263
+ true,
264
+ true,
265
+ () => {
266
+ this.menuOpen = false
267
+ }
268
+ )
269
+ this.menuOpen = true
270
+ }
271
+ })
176
272
  }
177
- if (can.editArticle) {
178
- positionMenuButton.tabIndex = 0
179
- positionMenuButton.addEventListener('click', onClick)
180
- positionMenuButton.addEventListener('keydown', handleEnterKey(onClick))
273
+
274
+ create() {
275
+ if (!this.parent) {
276
+ return
277
+ }
278
+ const p = this.parent
279
+ if (p.props.getCapabilities()?.editArticle) {
280
+ const posSource = this.getPositionSource
281
+ ? this.getPositionSource()
282
+ : this.parent.node
283
+
284
+ this.createPositionMenuWrapper(
285
+ posSource?.attrs.type || HorizontalPositions.default,
286
+ p.props
287
+ )
288
+ }
181
289
  }
182
- positionMenuWrapper.appendChild(positionMenuButton)
183
- return positionMenuWrapper
184
290
  }