@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.
- package/dist/cjs/lib/context-menu.js +28 -11
- package/dist/cjs/lib/popper.js +18 -3
- package/dist/cjs/lib/position-menu.js +175 -100
- package/dist/cjs/lib/view.js +10 -1
- 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/footnote.js +43 -18
- package/dist/cjs/views/general_table_footnote.js +31 -21
- package/dist/cjs/views/image_element.js +7 -62
- 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 +18 -3
- package/dist/es/lib/position-menu.js +173 -91
- package/dist/es/lib/view.js +8 -0
- 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/footnote.js +43 -18
- package/dist/es/views/general_table_footnote.js +31 -21
- package/dist/es/views/image_element.js +7 -62
- 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/lib/view.d.ts +3 -1
- package/dist/types/versions.d.ts +1 -1
- package/dist/types/views/box_element.d.ts +6 -0
- package/dist/types/views/footnote.d.ts +5 -2
- package/dist/types/views/general_table_footnote.d.ts +2 -2
- 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 +2 -2
- package/src/lib/context-menu.ts +42 -21
- package/src/lib/popper.ts +23 -4
- package/src/lib/position-menu.ts +243 -137
- package/src/lib/view.ts +17 -0
- 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/footnote.ts +69 -33
- package/src/views/general_table_footnote.ts +43 -20
- package/src/views/image_element.ts +12 -89
- 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 +9 -5
package/src/lib/view.ts
CHANGED
|
@@ -27,6 +27,7 @@ import * as utils from 'prosemirror-utils'
|
|
|
27
27
|
|
|
28
28
|
import { isHidden } from './track-changes-utils'
|
|
29
29
|
import { sanitizeAttrsChange } from '@manuscripts/track-changes-plugin'
|
|
30
|
+
import { EditorView } from 'prosemirror-view'
|
|
30
31
|
|
|
31
32
|
const metaNodeTypes = [
|
|
32
33
|
schema.nodes.bibliography_item,
|
|
@@ -163,3 +164,19 @@ export const saveBibliographyItem = (
|
|
|
163
164
|
|
|
164
165
|
insertBibliographyItems(view, attrs)
|
|
165
166
|
}
|
|
167
|
+
|
|
168
|
+
export const isSelectionInsideNode = (
|
|
169
|
+
view: EditorView,
|
|
170
|
+
node: ManuscriptNode,
|
|
171
|
+
pos: number
|
|
172
|
+
) => {
|
|
173
|
+
const { from, to, empty } = view.state.selection
|
|
174
|
+
const end = pos + node.nodeSize
|
|
175
|
+
|
|
176
|
+
// Treat a cursor as "inside" only when it is strictly within the node range.
|
|
177
|
+
if (empty) {
|
|
178
|
+
return from > pos && from < end
|
|
179
|
+
}
|
|
180
|
+
|
|
181
|
+
return from >= pos && to <= end
|
|
182
|
+
}
|
|
@@ -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/footnote.ts
CHANGED
|
@@ -19,6 +19,7 @@ import { isDeleted, isPendingInsert } from '@manuscripts/track-changes-plugin'
|
|
|
19
19
|
import { FootnoteNode, ManuscriptNode, schema } from '@manuscripts/transform'
|
|
20
20
|
|
|
21
21
|
import isEqual from 'lodash/isEqual'
|
|
22
|
+
import xor from 'lodash/xor'
|
|
22
23
|
import { NodeSelection, Transaction } from 'prosemirror-state'
|
|
23
24
|
import { findParentNodeOfTypeClosestToPos } from 'prosemirror-utils'
|
|
24
25
|
|
|
@@ -33,10 +34,13 @@ import { BaseNodeView } from './base_node_view'
|
|
|
33
34
|
import { createNodeView } from './creators'
|
|
34
35
|
import ReactSubView from './ReactSubView'
|
|
35
36
|
import { handleEnterKey } from '../lib/navigation-utils'
|
|
37
|
+
import { isSelectionInsideNode } from '../lib/view'
|
|
36
38
|
|
|
37
39
|
export class FootnoteView extends BaseNodeView<Trackable<FootnoteNode>> {
|
|
38
40
|
dialog: HTMLElement
|
|
39
41
|
contextMenu: HTMLDivElement
|
|
42
|
+
isMenuShown: boolean = false
|
|
43
|
+
previousActionsLabels: string[] = []
|
|
40
44
|
|
|
41
45
|
public initialise = () => {
|
|
42
46
|
this.dom = document.createElement('div')
|
|
@@ -44,10 +48,24 @@ export class FootnoteView extends BaseNodeView<Trackable<FootnoteNode>> {
|
|
|
44
48
|
this.dom.tabIndex = 0
|
|
45
49
|
this.contentDOM = document.createElement('div')
|
|
46
50
|
this.contentDOM.classList.add('footnote-text')
|
|
47
|
-
this.
|
|
51
|
+
if (!this.view.editable) {
|
|
52
|
+
// when the editor is in the viewing mode we can't depend on the selection to show context-menu so we use mousedown
|
|
53
|
+
// as in that case will not have the same listener from prosemirror-view to interfere with it
|
|
54
|
+
const actions = this.getContextMenuActions()
|
|
55
|
+
if (actions.length > 0) {
|
|
56
|
+
this.dom.addEventListener('mousedown', () =>
|
|
57
|
+
this.showContextMenu(actions, true)
|
|
58
|
+
)
|
|
59
|
+
}
|
|
60
|
+
}
|
|
48
61
|
this.dom.addEventListener(
|
|
49
62
|
'keydown',
|
|
50
|
-
handleEnterKey((
|
|
63
|
+
handleEnterKey(() => {
|
|
64
|
+
const actions = this.getContextMenuActions()
|
|
65
|
+
if (actions.length > 0) {
|
|
66
|
+
this.showContextMenu(actions, true)
|
|
67
|
+
}
|
|
68
|
+
})
|
|
51
69
|
)
|
|
52
70
|
this.updateContents()
|
|
53
71
|
}
|
|
@@ -73,6 +91,29 @@ export class FootnoteView extends BaseNodeView<Trackable<FootnoteNode>> {
|
|
|
73
91
|
this.dom.innerHTML = ''
|
|
74
92
|
this.dom.appendChild(marker)
|
|
75
93
|
this.contentDOM && this.dom.appendChild(this.contentDOM)
|
|
94
|
+
|
|
95
|
+
const selectionInsideNode = isSelectionInsideNode(
|
|
96
|
+
this.view,
|
|
97
|
+
this.node,
|
|
98
|
+
this.getPos()
|
|
99
|
+
)
|
|
100
|
+
|
|
101
|
+
const actions = this.getContextMenuActions()
|
|
102
|
+
const hasActions = actions.length > 0
|
|
103
|
+
const currentLabels = actions.map(({ label }) => label)
|
|
104
|
+
const changedLabels = xor(currentLabels, this.previousActionsLabels)
|
|
105
|
+
if (
|
|
106
|
+
selectionInsideNode &&
|
|
107
|
+
hasActions &&
|
|
108
|
+
(!this.isMenuShown || changedLabels.length > 0)
|
|
109
|
+
) {
|
|
110
|
+
this.showContextMenu(actions, false)
|
|
111
|
+
this.previousActionsLabels = actions.map(({ label }) => label)
|
|
112
|
+
} else if ((!hasActions || !selectionInsideNode) && this.isMenuShown) {
|
|
113
|
+
this.props.popper.destroy()
|
|
114
|
+
this.isMenuShown = false
|
|
115
|
+
this.previousActionsLabels = []
|
|
116
|
+
}
|
|
76
117
|
}
|
|
77
118
|
|
|
78
119
|
getFootnoteState() {
|
|
@@ -81,55 +122,50 @@ export class FootnoteView extends BaseNodeView<Trackable<FootnoteNode>> {
|
|
|
81
122
|
return { id, fn }
|
|
82
123
|
}
|
|
83
124
|
|
|
84
|
-
showContextMenu(
|
|
125
|
+
showContextMenu(actions: ContextMenuProps['actions'], autoFocus: boolean) {
|
|
126
|
+
this.isMenuShown = true
|
|
85
127
|
this.props.popper.destroy()
|
|
86
|
-
|
|
87
|
-
const can = this.props.getCapabilities()
|
|
88
|
-
const { id, fn } = this.getFootnoteState()
|
|
89
|
-
|
|
90
|
-
const componentProps: ContextMenuProps = {
|
|
91
|
-
actions: [],
|
|
92
|
-
}
|
|
93
|
-
if (!fn?.unusedFootnoteIDs.has(id)) {
|
|
94
|
-
componentProps.actions.push({
|
|
95
|
-
label: 'Go to footnote Refernce',
|
|
96
|
-
action: () => this.handleMarkerClick(),
|
|
97
|
-
icon: 'Scroll',
|
|
98
|
-
})
|
|
99
|
-
}
|
|
100
|
-
if (can.editArticle && !isDeleted(this.node)) {
|
|
101
|
-
componentProps.actions.push({
|
|
102
|
-
label: 'Delete',
|
|
103
|
-
action: () => this.handleDeleteClick(),
|
|
104
|
-
icon: 'Delete',
|
|
105
|
-
})
|
|
106
|
-
}
|
|
107
|
-
|
|
108
128
|
this.contextMenu = ReactSubView(
|
|
109
129
|
this.props,
|
|
110
130
|
ContextMenu,
|
|
111
|
-
|
|
131
|
+
{ actions },
|
|
112
132
|
this.node,
|
|
113
133
|
this.getPos,
|
|
114
134
|
this.view,
|
|
115
135
|
['context-menu', 'footnote-context-menu']
|
|
116
136
|
)
|
|
117
137
|
this.props.popper.show(
|
|
118
|
-
|
|
138
|
+
this.dom,
|
|
119
139
|
this.contextMenu,
|
|
120
140
|
'right-start',
|
|
121
141
|
true,
|
|
122
142
|
[],
|
|
123
|
-
autoFocus
|
|
143
|
+
autoFocus,
|
|
144
|
+
false
|
|
124
145
|
)
|
|
125
146
|
}
|
|
126
147
|
|
|
127
|
-
|
|
128
|
-
const
|
|
129
|
-
const
|
|
130
|
-
|
|
131
|
-
|
|
148
|
+
getContextMenuActions() {
|
|
149
|
+
const can = this.props.getCapabilities()
|
|
150
|
+
const { id, fn } = this.getFootnoteState()
|
|
151
|
+
const actions: ContextMenuProps['actions'] = []
|
|
152
|
+
|
|
153
|
+
if (!fn?.unusedFootnoteIDs.has(id)) {
|
|
154
|
+
actions.push({
|
|
155
|
+
label: 'Go to footnote Reference',
|
|
156
|
+
action: () => this.handleMarkerClick(),
|
|
157
|
+
icon: 'Scroll',
|
|
158
|
+
})
|
|
159
|
+
}
|
|
160
|
+
if (can.editArticle && !isDeleted(this.node)) {
|
|
161
|
+
actions.push({
|
|
162
|
+
label: 'Delete',
|
|
163
|
+
action: () => this.handleDeleteClick(),
|
|
164
|
+
icon: 'Delete',
|
|
165
|
+
})
|
|
132
166
|
}
|
|
167
|
+
|
|
168
|
+
return actions
|
|
133
169
|
}
|
|
134
170
|
|
|
135
171
|
handleMarkerClick = (e?: Event) => {
|
|
@@ -30,17 +30,30 @@ import { BaseNodeView } from './base_node_view'
|
|
|
30
30
|
import { createNodeView } from './creators'
|
|
31
31
|
import ReactSubView from './ReactSubView'
|
|
32
32
|
import { isDeleted, isPendingInsert } from '@manuscripts/track-changes-plugin'
|
|
33
|
+
import { handleEnterKey } from '../lib/navigation-utils'
|
|
34
|
+
import { isSelectionInsideNode } from '../lib/view'
|
|
33
35
|
|
|
34
36
|
export class GeneralTableFootnoteView extends BaseNodeView<
|
|
35
37
|
Trackable<GeneralTableFootnoteNode>
|
|
36
38
|
> {
|
|
37
39
|
dialog: HTMLElement
|
|
38
40
|
contextMenu: HTMLDivElement
|
|
41
|
+
isMenuShown: boolean = false
|
|
39
42
|
|
|
40
43
|
public initialise = () => {
|
|
41
44
|
this.dom = document.createElement('div')
|
|
42
45
|
this.dom.classList.add('footnote', 'general-table-footnote')
|
|
43
|
-
this.dom.
|
|
46
|
+
this.dom.tabIndex = 0
|
|
47
|
+
this.dom.addEventListener(
|
|
48
|
+
'keydown',
|
|
49
|
+
handleEnterKey(() => {
|
|
50
|
+
const can = this.props.getCapabilities()
|
|
51
|
+
const canShowMenu = can.editArticle && !isDeleted(this.node)
|
|
52
|
+
if (canShowMenu) {
|
|
53
|
+
this.showContextMenu(true)
|
|
54
|
+
}
|
|
55
|
+
})
|
|
56
|
+
)
|
|
44
57
|
this.contentDOM = document.createElement('div')
|
|
45
58
|
this.contentDOM.classList.add('footnote-text')
|
|
46
59
|
this.updateContents()
|
|
@@ -50,32 +63,34 @@ export class GeneralTableFootnoteView extends BaseNodeView<
|
|
|
50
63
|
super.updateContents()
|
|
51
64
|
this.dom.innerHTML = ''
|
|
52
65
|
this.contentDOM && this.dom.appendChild(this.contentDOM)
|
|
53
|
-
}
|
|
54
66
|
|
|
55
|
-
|
|
56
|
-
|
|
67
|
+
const selectionInsideNode = isSelectionInsideNode(
|
|
68
|
+
this.view,
|
|
69
|
+
this.node,
|
|
70
|
+
this.getPos()
|
|
71
|
+
)
|
|
57
72
|
const can = this.props.getCapabilities()
|
|
58
|
-
|
|
59
|
-
if (
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
73
|
+
const canShowMenu = can.editArticle && !isDeleted(this.node)
|
|
74
|
+
if (canShowMenu && selectionInsideNode && !this.isMenuShown) {
|
|
75
|
+
this.showContextMenu(false)
|
|
76
|
+
} else if ((!canShowMenu || !selectionInsideNode) && this.isMenuShown) {
|
|
77
|
+
this.props.popper.destroy()
|
|
78
|
+
this.isMenuShown = false
|
|
64
79
|
}
|
|
65
80
|
}
|
|
66
81
|
|
|
67
|
-
showContextMenu(
|
|
82
|
+
showContextMenu(autoFocus = false) {
|
|
83
|
+
this.isMenuShown = true
|
|
68
84
|
this.props.popper.destroy()
|
|
69
85
|
|
|
70
86
|
const componentProps: ContextMenuProps = {
|
|
71
|
-
actions: [
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
})
|
|
87
|
+
actions: [
|
|
88
|
+
{
|
|
89
|
+
label: 'Delete',
|
|
90
|
+
action: () => this.handleDeleteClick(),
|
|
91
|
+
icon: 'Delete',
|
|
92
|
+
},
|
|
93
|
+
],
|
|
79
94
|
}
|
|
80
95
|
|
|
81
96
|
this.contextMenu = ReactSubView(
|
|
@@ -87,7 +102,15 @@ export class GeneralTableFootnoteView extends BaseNodeView<
|
|
|
87
102
|
this.view,
|
|
88
103
|
['context-menu', 'footnote-context-menu']
|
|
89
104
|
)
|
|
90
|
-
this.props.popper.show(
|
|
105
|
+
this.props.popper.show(
|
|
106
|
+
this.dom,
|
|
107
|
+
this.contextMenu,
|
|
108
|
+
'right-start',
|
|
109
|
+
false,
|
|
110
|
+
[],
|
|
111
|
+
autoFocus,
|
|
112
|
+
false
|
|
113
|
+
)
|
|
91
114
|
}
|
|
92
115
|
|
|
93
116
|
handleDeleteClick = () => {
|
|
@@ -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
|
|
@@ -24,10 +24,13 @@ import { setCommentSelection } from '../plugins/comments'
|
|
|
24
24
|
import BlockView from './block_view'
|
|
25
25
|
import { createNodeOrElementView } from './creators'
|
|
26
26
|
import ReactSubView from './ReactSubView'
|
|
27
|
+
import { HorizontalPositionMenu } from '../lib/position-menu'
|
|
27
28
|
|
|
28
29
|
export class PullquoteElementView extends BlockView<PullquoteElementNode> {
|
|
29
30
|
public elementType = 'aside'
|
|
30
31
|
contextMenu: HTMLElement
|
|
32
|
+
container: HTMLDivElement
|
|
33
|
+
private positionMenu: HorizontalPositionMenu
|
|
31
34
|
|
|
32
35
|
public ignoreMutation = () => true
|
|
33
36
|
public stopEvent = () => true
|
|
@@ -51,7 +54,10 @@ export class PullquoteElementView extends BlockView<PullquoteElementNode> {
|
|
|
51
54
|
this.contentDOM.className = 'block'
|
|
52
55
|
this.contentDOM.classList.add('pullquote')
|
|
53
56
|
|
|
54
|
-
this.
|
|
57
|
+
this.container = document.createElement('div')
|
|
58
|
+
this.container.classList.add('container')
|
|
59
|
+
this.container.appendChild(this.contentDOM)
|
|
60
|
+
this.dom.appendChild(this.container)
|
|
55
61
|
|
|
56
62
|
// Add click event listener to handle comment marker clicks
|
|
57
63
|
this.dom.addEventListener('click', this.handleClick)
|
|
@@ -96,11 +102,37 @@ export class PullquoteElementView extends BlockView<PullquoteElementNode> {
|
|
|
96
102
|
return undefined
|
|
97
103
|
}
|
|
98
104
|
|
|
105
|
+
public updateContents() {
|
|
106
|
+
super.updateContents()
|
|
107
|
+
this.addTools()
|
|
108
|
+
}
|
|
109
|
+
|
|
99
110
|
public destroy = () => {
|
|
100
111
|
// Clean up event listener
|
|
101
112
|
this.dom.removeEventListener('click', this.handleClick)
|
|
102
113
|
super.destroy()
|
|
103
114
|
}
|
|
115
|
+
|
|
116
|
+
protected addTools() {
|
|
117
|
+
this.addPositionMenu()
|
|
118
|
+
}
|
|
119
|
+
|
|
120
|
+
protected addPositionMenu() {
|
|
121
|
+
if (!this.positionMenu) {
|
|
122
|
+
this.positionMenu = new HorizontalPositionMenu(
|
|
123
|
+
this,
|
|
124
|
+
this.updateHorizontalPosition,
|
|
125
|
+
this.container
|
|
126
|
+
)
|
|
127
|
+
}
|
|
128
|
+
this.positionMenu.create()
|
|
129
|
+
}
|
|
130
|
+
|
|
131
|
+
private updateHorizontalPosition(horizontalPosition: string) {
|
|
132
|
+
const tr = this.view.state.tr
|
|
133
|
+
tr.setNodeAttribute(this.getPos(), 'type', horizontalPosition)
|
|
134
|
+
this.view.dispatch(tr)
|
|
135
|
+
}
|
|
104
136
|
}
|
|
105
137
|
|
|
106
138
|
export default createNodeOrElementView(PullquoteElementView, 'aside')
|
|
@@ -18,15 +18,48 @@ import { TableElementNode } 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 TableElementView extends BlockView<TableElementNode> {
|
|
23
24
|
public elementType = 'figure'
|
|
25
|
+
container: HTMLDivElement
|
|
26
|
+
private positionMenu: HorizontalPositionMenu
|
|
24
27
|
|
|
25
28
|
public createElement = () => {
|
|
26
29
|
this.contentDOM = document.createElement('figure')
|
|
27
30
|
this.contentDOM.classList.add('block')
|
|
28
31
|
this.contentDOM.setAttribute('id', this.node.attrs.id)
|
|
29
|
-
|
|
32
|
+
|
|
33
|
+
this.container = document.createElement('div')
|
|
34
|
+
this.container.classList.add('container')
|
|
35
|
+
this.container.appendChild(this.contentDOM)
|
|
36
|
+
this.dom.appendChild(this.container)
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
public updateContents() {
|
|
40
|
+
super.updateContents()
|
|
41
|
+
this.addTools()
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
protected addTools() {
|
|
45
|
+
this.addPositionMenu()
|
|
46
|
+
}
|
|
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
|
|