@manuscripts/body-editor 3.16.2 → 3.17.0
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/dist/cjs/lib/context-menu.js +28 -11
- package/dist/cjs/lib/popper.js +15 -1
- package/dist/cjs/lib/position-menu.js +175 -100
- package/dist/cjs/plugins/detect-inconsistency/index.js +6 -4
- package/dist/cjs/plugins/persist.js +3 -0
- package/dist/cjs/versions.js +1 -1
- package/dist/cjs/views/box_element.js +23 -1
- package/dist/cjs/views/caption_title.js +1 -1
- package/dist/cjs/views/equation.js +2 -0
- package/dist/cjs/views/equation_editable.js +2 -0
- package/dist/cjs/views/image_element.js +7 -62
- package/dist/cjs/views/inline_equation.js +2 -0
- package/dist/cjs/views/inline_equation_editable.js +2 -0
- package/dist/cjs/views/pullquote_element.js +23 -1
- package/dist/cjs/views/table_element.js +23 -1
- package/dist/es/lib/context-menu.js +29 -12
- package/dist/es/lib/popper.js +15 -1
- package/dist/es/lib/position-menu.js +173 -91
- package/dist/es/plugins/detect-inconsistency/index.js +6 -4
- package/dist/es/plugins/persist.js +3 -0
- package/dist/es/versions.js +1 -1
- package/dist/es/views/box_element.js +23 -1
- package/dist/es/views/caption_title.js +1 -1
- package/dist/es/views/equation.js +2 -0
- package/dist/es/views/equation_editable.js +2 -0
- package/dist/es/views/image_element.js +7 -62
- package/dist/es/views/inline_equation.js +2 -0
- package/dist/es/views/inline_equation_editable.js +2 -0
- package/dist/es/views/pullquote_element.js +23 -1
- package/dist/es/views/table_element.js +23 -1
- package/dist/types/lib/popper.d.ts +4 -2
- package/dist/types/lib/position-menu.d.ts +36 -11
- package/dist/types/versions.d.ts +1 -1
- package/dist/types/views/box_element.d.ts +6 -0
- package/dist/types/views/image_element.d.ts +2 -9
- package/dist/types/views/pullquote_element.d.ts +6 -0
- package/dist/types/views/table_element.d.ts +6 -0
- package/package.json +1 -1
- package/src/lib/context-menu.ts +42 -21
- package/src/lib/popper.ts +18 -1
- package/src/lib/position-menu.ts +242 -137
- package/src/plugins/detect-inconsistency/index.ts +6 -4
- package/src/plugins/persist.ts +3 -0
- package/src/versions.ts +1 -1
- package/src/views/box_element.ts +34 -1
- package/src/views/caption_title.ts +1 -1
- package/src/views/equation.ts +5 -0
- package/src/views/equation_editable.ts +3 -0
- package/src/views/image_element.ts +12 -89
- package/src/views/inline_equation.ts +5 -0
- package/src/views/inline_equation_editable.ts +3 -0
- package/src/views/pullquote_element.ts +33 -1
- package/src/views/table_element.ts +34 -1
- package/styles/AdvancedEditor.css +5 -8
- package/styles/Editor.css +11 -6
package/src/lib/position-menu.ts
CHANGED
|
@@ -14,7 +14,7 @@
|
|
|
14
14
|
* limitations under the License.
|
|
15
15
|
*/
|
|
16
16
|
|
|
17
|
-
import { ContextMenu
|
|
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 {
|
|
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,249 @@ export interface PopperMenuPositionOption {
|
|
|
35
41
|
selected: boolean
|
|
36
42
|
}
|
|
37
43
|
|
|
38
|
-
export
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
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
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
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
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
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
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
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
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
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
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
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
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
)
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
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
|
-
|
|
175
|
-
|
|
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
|
+
() => {
|
|
265
|
+
this.menuOpen = false
|
|
266
|
+
}
|
|
267
|
+
)
|
|
268
|
+
this.menuOpen = true
|
|
269
|
+
}
|
|
270
|
+
})
|
|
176
271
|
}
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
272
|
+
|
|
273
|
+
create() {
|
|
274
|
+
if (!this.parent) {
|
|
275
|
+
return
|
|
276
|
+
}
|
|
277
|
+
const p = this.parent
|
|
278
|
+
if (p.props.getCapabilities()?.editArticle) {
|
|
279
|
+
const posSource = this.getPositionSource
|
|
280
|
+
? this.getPositionSource()
|
|
281
|
+
: this.parent.node
|
|
282
|
+
|
|
283
|
+
this.createPositionMenuWrapper(
|
|
284
|
+
posSource?.attrs.type || HorizontalPositions.default,
|
|
285
|
+
p.props
|
|
286
|
+
)
|
|
287
|
+
}
|
|
181
288
|
}
|
|
182
|
-
positionMenuWrapper.appendChild(positionMenuButton)
|
|
183
|
-
return positionMenuWrapper
|
|
184
289
|
}
|
|
@@ -35,11 +35,13 @@ export default (props: EditorProps) => {
|
|
|
35
35
|
key: detectInconsistencyKey,
|
|
36
36
|
state: {
|
|
37
37
|
init: (_, state) => buildPluginState(state, props, false),
|
|
38
|
-
apply: (tr, value, newState) => {
|
|
38
|
+
apply: (tr, value, _, newState) => {
|
|
39
|
+
const metaValue = tr.getMeta(detectInconsistencyKey)
|
|
39
40
|
const showDecorations =
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
41
|
+
metaValue !== undefined ? metaValue : value.showDecorations
|
|
42
|
+
if (!tr.docChanged && metaValue === undefined) {
|
|
43
|
+
return value
|
|
44
|
+
}
|
|
43
45
|
return buildPluginState(newState, props, showDecorations)
|
|
44
46
|
},
|
|
45
47
|
},
|
package/src/plugins/persist.ts
CHANGED
package/src/versions.ts
CHANGED
package/src/views/box_element.ts
CHANGED
|
@@ -18,15 +18,48 @@ import { BoxElementNode } from '@manuscripts/transform'
|
|
|
18
18
|
|
|
19
19
|
import BlockView from './block_view'
|
|
20
20
|
import { createNodeView } from './creators'
|
|
21
|
+
import { HorizontalPositionMenu } from '../lib/position-menu'
|
|
21
22
|
|
|
22
23
|
export class BoxElementView extends BlockView<BoxElementNode> {
|
|
23
24
|
public elementType = 'div'
|
|
25
|
+
container: HTMLDivElement
|
|
24
26
|
|
|
25
27
|
public createElement = () => {
|
|
26
28
|
this.contentDOM = document.createElement(this.elementType)
|
|
27
29
|
this.contentDOM.className = 'block box-element'
|
|
28
30
|
this.contentDOM.setAttribute('id', this.node.attrs.id)
|
|
29
|
-
this.
|
|
31
|
+
this.container = document.createElement('div')
|
|
32
|
+
this.container.classList.add('container')
|
|
33
|
+
this.container.appendChild(this.contentDOM)
|
|
34
|
+
this.dom.appendChild(this.container)
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
public updateContents() {
|
|
38
|
+
super.updateContents()
|
|
39
|
+
this.addTools()
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
protected addTools() {
|
|
43
|
+
this.addPositionMenu()
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
private positionMenu: HorizontalPositionMenu
|
|
47
|
+
|
|
48
|
+
protected addPositionMenu() {
|
|
49
|
+
if (!this.positionMenu) {
|
|
50
|
+
this.positionMenu = new HorizontalPositionMenu(
|
|
51
|
+
this,
|
|
52
|
+
this.updateHorizontalPosition,
|
|
53
|
+
this.container
|
|
54
|
+
)
|
|
55
|
+
}
|
|
56
|
+
this.positionMenu.create()
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
private updateHorizontalPosition(horizontalPosition: string) {
|
|
60
|
+
const tr = this.view.state.tr
|
|
61
|
+
tr.setNodeAttribute(this.getPos(), 'type', horizontalPosition)
|
|
62
|
+
this.view.dispatch(tr)
|
|
30
63
|
}
|
|
31
64
|
}
|
|
32
65
|
|
|
@@ -26,7 +26,7 @@ export class CaptionTitleView extends BaseNodeView<CaptionTitleNode> {
|
|
|
26
26
|
}
|
|
27
27
|
|
|
28
28
|
protected createDOM() {
|
|
29
|
-
this.dom = document.createElement('
|
|
29
|
+
this.dom = document.createElement('div')
|
|
30
30
|
this.dom.className = 'caption-title placeholder'
|
|
31
31
|
this.contentDOM = this.dom
|
|
32
32
|
}
|
package/src/views/equation.ts
CHANGED
|
@@ -20,6 +20,7 @@ import { renderMath } from '../lib/math'
|
|
|
20
20
|
import { Trackable } from '../types'
|
|
21
21
|
import { BaseNodeView } from './base_node_view'
|
|
22
22
|
import { createNodeView } from './creators'
|
|
23
|
+
import { handleEnterKey } from '../lib/navigation-utils'
|
|
23
24
|
|
|
24
25
|
export class EquationView
|
|
25
26
|
extends BaseNodeView<Trackable<EquationNode>>
|
|
@@ -33,6 +34,10 @@ export class EquationView
|
|
|
33
34
|
public createDOM = () => {
|
|
34
35
|
this.dom = document.createElement('div')
|
|
35
36
|
this.dom.classList.add('equation')
|
|
37
|
+
this.dom.addEventListener(
|
|
38
|
+
'keydown',
|
|
39
|
+
handleEnterKey(() => this.selectNode())
|
|
40
|
+
)
|
|
36
41
|
}
|
|
37
42
|
|
|
38
43
|
public updateContents() {
|
|
@@ -14,7 +14,6 @@
|
|
|
14
14
|
* limitations under the License.
|
|
15
15
|
*/
|
|
16
16
|
|
|
17
|
-
import { ContextMenu } from '@manuscripts/style-guide'
|
|
18
17
|
import { FigureNode, ImageElementNode, schema } from '@manuscripts/transform'
|
|
19
18
|
|
|
20
19
|
import { deleteIcon, linkIcon } from '../icons'
|
|
@@ -24,24 +23,16 @@ import {
|
|
|
24
23
|
MediaType,
|
|
25
24
|
} from '../lib/media'
|
|
26
25
|
import { handleEnterKey } from '../lib/navigation-utils'
|
|
27
|
-
import {
|
|
26
|
+
import { HorizontalPositionMenu } from '../lib/position-menu'
|
|
28
27
|
import { Trackable } from '../types'
|
|
29
28
|
import BlockView from './block_view'
|
|
30
29
|
import { createNodeView } from './creators'
|
|
31
|
-
import ReactSubView from './ReactSubView'
|
|
32
|
-
|
|
33
|
-
export enum figurePositions {
|
|
34
|
-
left = 'half-left',
|
|
35
|
-
right = 'half-right',
|
|
36
|
-
default = '',
|
|
37
|
-
}
|
|
38
30
|
|
|
39
31
|
export class ImageElementView extends BlockView<Trackable<ImageElementNode>> {
|
|
40
32
|
public container: HTMLElement
|
|
41
33
|
public subcontainer: HTMLElement
|
|
42
34
|
public extLinkEditorContainer: HTMLDivElement
|
|
43
|
-
private
|
|
44
|
-
private figurePosition: string
|
|
35
|
+
private positionMenu: HorizontalPositionMenu
|
|
45
36
|
private isEditingExtLink = false
|
|
46
37
|
|
|
47
38
|
public ignoreMutation = () => true
|
|
@@ -93,33 +84,12 @@ export class ImageElementView extends BlockView<Trackable<ImageElementNode>> {
|
|
|
93
84
|
this.addPositionMenu()
|
|
94
85
|
}
|
|
95
86
|
|
|
96
|
-
protected addPositionMenu() {
|
|
97
|
-
if (this.props.getCapabilities()?.editArticle) {
|
|
98
|
-
// Remove existing position menu if it exists
|
|
99
|
-
const existingMenu = this.container.querySelector('.position-menu')
|
|
100
|
-
if (existingMenu) {
|
|
101
|
-
existingMenu.remove()
|
|
102
|
-
}
|
|
103
|
-
|
|
104
|
-
const firstFigure = this.getFirstFigure()
|
|
105
|
-
this.figurePosition = firstFigure?.attrs.type || figurePositions.default
|
|
106
|
-
|
|
107
|
-
this.positionMenuWrapper = createPositionMenuWrapper(
|
|
108
|
-
this.figurePosition,
|
|
109
|
-
this.showPositionMenu,
|
|
110
|
-
this.props
|
|
111
|
-
)
|
|
112
|
-
|
|
113
|
-
this.container.prepend(this.positionMenuWrapper)
|
|
114
|
-
}
|
|
115
|
-
}
|
|
116
|
-
|
|
117
87
|
/**
|
|
118
88
|
* Gets the first figure node from the element.
|
|
119
89
|
* Optimized for image_element (direct access) vs figure_element (loop through all).
|
|
120
90
|
* @returns The first figure node or null if no figure exists
|
|
121
91
|
*/
|
|
122
|
-
private getFirstFigure()
|
|
92
|
+
private getFirstFigure() {
|
|
123
93
|
// Optimize for image_element which only has one figure
|
|
124
94
|
if (this.node.type === schema.nodes.image_element) {
|
|
125
95
|
// Direct access to the single figure in image_element
|
|
@@ -166,62 +136,16 @@ export class ImageElementView extends BlockView<Trackable<ImageElementNode>> {
|
|
|
166
136
|
return figures
|
|
167
137
|
}
|
|
168
138
|
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
const options = [
|
|
178
|
-
{
|
|
179
|
-
label: 'Left',
|
|
180
|
-
action: () => {
|
|
181
|
-
this.props.popper.destroy()
|
|
182
|
-
this.updateAllFiguresPosition(figurePositions.left)
|
|
183
|
-
},
|
|
184
|
-
icon: 'ImageLeft',
|
|
185
|
-
selected: this.figurePosition === figurePositions.left,
|
|
186
|
-
},
|
|
187
|
-
{
|
|
188
|
-
label: 'Default',
|
|
189
|
-
action: () => {
|
|
190
|
-
this.props.popper.destroy()
|
|
191
|
-
this.updateAllFiguresPosition(figurePositions.default)
|
|
192
|
-
},
|
|
193
|
-
icon: 'ImageDefault',
|
|
194
|
-
selected: !this.figurePosition,
|
|
195
|
-
},
|
|
196
|
-
{
|
|
197
|
-
label: 'Right',
|
|
198
|
-
action: () => {
|
|
199
|
-
this.props.popper.destroy()
|
|
200
|
-
this.updateAllFiguresPosition(figurePositions.right)
|
|
201
|
-
},
|
|
202
|
-
icon: 'ImageRight',
|
|
203
|
-
selected: this.figurePosition === figurePositions.right,
|
|
204
|
-
},
|
|
205
|
-
]
|
|
206
|
-
|
|
207
|
-
const componentProps = {
|
|
208
|
-
actions: options,
|
|
139
|
+
protected addPositionMenu() {
|
|
140
|
+
if (!this.positionMenu) {
|
|
141
|
+
this.positionMenu = new HorizontalPositionMenu(
|
|
142
|
+
this,
|
|
143
|
+
this.updateAllFiguresPosition.bind(this),
|
|
144
|
+
this.container,
|
|
145
|
+
() => this.getFirstFigure()
|
|
146
|
+
)
|
|
209
147
|
}
|
|
210
|
-
|
|
211
|
-
this.props.popper.show(
|
|
212
|
-
this.positionMenuWrapper,
|
|
213
|
-
ReactSubView(
|
|
214
|
-
this.props,
|
|
215
|
-
ContextMenu,
|
|
216
|
-
componentProps,
|
|
217
|
-
this.node,
|
|
218
|
-
this.getPos,
|
|
219
|
-
this.view,
|
|
220
|
-
['context-menu', 'position-menu']
|
|
221
|
-
),
|
|
222
|
-
'left',
|
|
223
|
-
false
|
|
224
|
-
)
|
|
148
|
+
this.positionMenu.create()
|
|
225
149
|
}
|
|
226
150
|
|
|
227
151
|
/**
|
|
@@ -241,7 +165,6 @@ export class ImageElementView extends BlockView<Trackable<ImageElementNode>> {
|
|
|
241
165
|
})
|
|
242
166
|
|
|
243
167
|
this.view.dispatch(tr)
|
|
244
|
-
this.figurePosition = position
|
|
245
168
|
}
|
|
246
169
|
|
|
247
170
|
// external link editor
|