@manuscripts/body-editor 2.7.29 → 2.7.30-LEAN-4096.2
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/components/views/FigureDropdown.js +12 -45
- package/dist/cjs/configs/editor-plugins.js +2 -0
- package/dist/cjs/index.js +1 -0
- package/dist/cjs/lib/context-menu.js +71 -4
- package/dist/cjs/lib/view.js +3 -1
- package/dist/cjs/plugins/inspector-tabs.js +84 -0
- package/dist/cjs/versions.js +1 -1
- package/dist/cjs/views/ReactSubView.js +4 -4
- package/dist/cjs/views/affiliations.js +1 -1
- package/dist/cjs/views/award.js +3 -3
- package/dist/cjs/views/bibliography_element.js +2 -2
- package/dist/cjs/views/citation_editable.js +3 -3
- package/dist/cjs/views/contributors.js +2 -2
- package/dist/cjs/views/cross_reference_editable.js +1 -1
- package/dist/cjs/views/embed.js +1 -1
- package/dist/cjs/views/figure_editable.js +96 -9
- package/dist/cjs/views/figure_element.js +0 -79
- package/dist/cjs/views/inline_footnote.js +2 -2
- package/dist/cjs/views/keyword.js +1 -1
- package/dist/cjs/views/keyword_group.js +1 -1
- package/dist/cjs/views/link_editable.js +1 -1
- package/dist/cjs/views/table_cell.js +1 -1
- package/dist/es/components/views/FigureDropdown.js +12 -44
- package/dist/es/configs/editor-plugins.js +2 -0
- package/dist/es/index.js +1 -0
- package/dist/es/lib/context-menu.js +72 -5
- package/dist/es/lib/view.js +3 -1
- package/dist/es/plugins/inspector-tabs.js +81 -0
- package/dist/es/versions.js +1 -1
- package/dist/es/views/ReactSubView.js +4 -4
- package/dist/es/views/affiliations.js +1 -1
- package/dist/es/views/award.js +3 -3
- package/dist/es/views/bibliography_element.js +2 -2
- package/dist/es/views/citation_editable.js +3 -3
- package/dist/es/views/contributors.js +2 -2
- package/dist/es/views/cross_reference_editable.js +1 -1
- package/dist/es/views/embed.js +1 -1
- package/dist/es/views/figure_editable.js +96 -9
- package/dist/es/views/figure_element.js +0 -79
- package/dist/es/views/inline_footnote.js +2 -2
- package/dist/es/views/keyword.js +1 -1
- package/dist/es/views/keyword_group.js +1 -1
- package/dist/es/views/link_editable.js +1 -1
- package/dist/es/views/table_cell.js +1 -1
- package/dist/types/components/views/FigureDropdown.d.ts +0 -1
- package/dist/types/index.d.ts +1 -0
- package/dist/types/lib/context-menu.d.ts +3 -0
- package/dist/types/plugins/inspector-tabs.d.ts +35 -0
- package/dist/types/versions.d.ts +1 -1
- package/dist/types/views/ReactSubView.d.ts +1 -1
- package/dist/types/views/figure_editable.d.ts +9 -0
- package/dist/types/views/figure_element.d.ts +0 -3
- package/package.json +3 -3
- package/styles/AdvancedEditor.css +15 -5
- package/styles/Editor.css +10 -1
- package/styles/popper.css +33 -11
|
@@ -27,16 +27,25 @@ var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
|
27
27
|
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
28
28
|
};
|
|
29
29
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
30
|
-
exports.FigureEditableView = void 0;
|
|
30
|
+
exports.FigureEditableView = exports.figurePositions = void 0;
|
|
31
31
|
const style_guide_1 = require("@manuscripts/style-guide");
|
|
32
|
+
const transform_1 = require("@manuscripts/transform");
|
|
33
|
+
const prosemirror_state_1 = require("prosemirror-state");
|
|
32
34
|
const react_1 = require("react");
|
|
33
35
|
const server_1 = require("react-dom/server");
|
|
34
36
|
const FigureDropdown_1 = require("../components/views/FigureDropdown");
|
|
35
37
|
const files_1 = require("../lib/files");
|
|
38
|
+
const view_1 = require("../lib/view");
|
|
36
39
|
const creators_1 = require("./creators");
|
|
37
40
|
const figure_1 = require("./figure");
|
|
38
41
|
const figure_uploader_1 = require("./figure_uploader");
|
|
39
42
|
const ReactSubView_1 = __importDefault(require("./ReactSubView"));
|
|
43
|
+
var figurePositions;
|
|
44
|
+
(function (figurePositions) {
|
|
45
|
+
figurePositions["left"] = "half-left";
|
|
46
|
+
figurePositions["right"] = "half-right";
|
|
47
|
+
figurePositions["default"] = "";
|
|
48
|
+
})(figurePositions = exports.figurePositions || (exports.figurePositions = {}));
|
|
40
49
|
class FigureEditableView extends figure_1.FigureView {
|
|
41
50
|
constructor() {
|
|
42
51
|
super(...arguments);
|
|
@@ -45,8 +54,10 @@ class FigureEditableView extends figure_1.FigureView {
|
|
|
45
54
|
this.updateContents();
|
|
46
55
|
};
|
|
47
56
|
this.setSrc = (src) => {
|
|
48
|
-
const {
|
|
49
|
-
|
|
57
|
+
const { tr } = this.view.state;
|
|
58
|
+
const pos = this.getPos();
|
|
59
|
+
tr.setNodeMarkup(pos, undefined, Object.assign(Object.assign({}, this.node.attrs), { src: src }));
|
|
60
|
+
tr.setSelection(prosemirror_state_1.NodeSelection.create(tr.doc, pos));
|
|
50
61
|
this.view.dispatch(tr);
|
|
51
62
|
};
|
|
52
63
|
this.createUnsupportedFormat = (name) => {
|
|
@@ -84,11 +95,75 @@ class FigureEditableView extends figure_1.FigureView {
|
|
|
84
95
|
element.classList.add('figure', 'placeholder');
|
|
85
96
|
const instructions = document.createElement('div');
|
|
86
97
|
instructions.classList.add('instructions');
|
|
87
|
-
instructions.
|
|
88
|
-
|
|
98
|
+
instructions.innerHTML = `
|
|
99
|
+
<p>Drag or click here to upload image <br>
|
|
100
|
+
or drag items here from the file inspector tabs <br>
|
|
101
|
+
<a data-action='open-other-files'>'Other files'</a> |
|
|
102
|
+
<a data-action='open-supplement-files'>'Supplements'</a></p>
|
|
103
|
+
`;
|
|
89
104
|
element.appendChild(instructions);
|
|
90
105
|
return element;
|
|
91
106
|
};
|
|
107
|
+
this.createPositionMenuWrapper = () => {
|
|
108
|
+
this.positionMenuWrapper = document.createElement('div');
|
|
109
|
+
this.positionMenuWrapper.classList.add('position-menu');
|
|
110
|
+
const positionMenuButton = document.createElement('div');
|
|
111
|
+
positionMenuButton.classList.add('position-menu-button');
|
|
112
|
+
let icon;
|
|
113
|
+
switch (this.figurePosition) {
|
|
114
|
+
case figurePositions.left:
|
|
115
|
+
icon = style_guide_1.ImageLeftIcon;
|
|
116
|
+
break;
|
|
117
|
+
case figurePositions.right:
|
|
118
|
+
icon = style_guide_1.ImageRightIcon;
|
|
119
|
+
break;
|
|
120
|
+
default:
|
|
121
|
+
icon = style_guide_1.ImageDefaultIcon;
|
|
122
|
+
break;
|
|
123
|
+
}
|
|
124
|
+
if (icon) {
|
|
125
|
+
positionMenuButton.innerHTML = (0, server_1.renderToStaticMarkup)((0, react_1.createElement)(icon));
|
|
126
|
+
}
|
|
127
|
+
positionMenuButton.addEventListener('click', this.showPositionMenu);
|
|
128
|
+
this.positionMenuWrapper.appendChild(positionMenuButton);
|
|
129
|
+
return this.positionMenuWrapper;
|
|
130
|
+
};
|
|
131
|
+
this.showPositionMenu = () => {
|
|
132
|
+
this.props.popper.destroy();
|
|
133
|
+
const figure = this.node;
|
|
134
|
+
const componentProps = {
|
|
135
|
+
actions: [
|
|
136
|
+
{
|
|
137
|
+
label: 'Left',
|
|
138
|
+
action: () => {
|
|
139
|
+
this.props.popper.destroy();
|
|
140
|
+
(0, view_1.updateNodeAttrs)(this.view, transform_1.schema.nodes.figure, Object.assign(Object.assign({}, figure.attrs), { type: figurePositions.left }));
|
|
141
|
+
},
|
|
142
|
+
icon: 'ImageLeft',
|
|
143
|
+
selected: this.figurePosition === figurePositions.left,
|
|
144
|
+
},
|
|
145
|
+
{
|
|
146
|
+
label: 'Default',
|
|
147
|
+
action: () => {
|
|
148
|
+
this.props.popper.destroy();
|
|
149
|
+
(0, view_1.updateNodeAttrs)(this.view, transform_1.schema.nodes.figure, Object.assign(Object.assign({}, figure.attrs), { type: figurePositions.default }));
|
|
150
|
+
},
|
|
151
|
+
icon: 'ImageDefault',
|
|
152
|
+
selected: !this.figurePosition,
|
|
153
|
+
},
|
|
154
|
+
{
|
|
155
|
+
label: 'Right',
|
|
156
|
+
action: () => {
|
|
157
|
+
this.props.popper.destroy();
|
|
158
|
+
(0, view_1.updateNodeAttrs)(this.view, transform_1.schema.nodes.figure, Object.assign(Object.assign({}, figure.attrs), { type: figurePositions.right }));
|
|
159
|
+
},
|
|
160
|
+
icon: 'ImageRight',
|
|
161
|
+
selected: this.figurePosition === figurePositions.right,
|
|
162
|
+
},
|
|
163
|
+
],
|
|
164
|
+
};
|
|
165
|
+
this.props.popper.show(this.positionMenuWrapper, (0, ReactSubView_1.default)(this.props, style_guide_1.ContextMenu, componentProps, this.node, this.getPos, this.view, ['context-menu', 'position-menu']), 'left', false);
|
|
166
|
+
};
|
|
92
167
|
}
|
|
93
168
|
updateContents() {
|
|
94
169
|
var _a;
|
|
@@ -97,6 +172,7 @@ class FigureEditableView extends figure_1.FigureView {
|
|
|
97
172
|
const src = attrs.src;
|
|
98
173
|
const files = this.props.getFiles();
|
|
99
174
|
const file = src && files.filter((f) => f.id === src)[0];
|
|
175
|
+
this.figurePosition = attrs.type;
|
|
100
176
|
this.container.innerHTML = '';
|
|
101
177
|
const can = this.props.getCapabilities();
|
|
102
178
|
const link = file && this.props.fileManagement.previewLink(file);
|
|
@@ -115,20 +191,30 @@ class FigureEditableView extends figure_1.FigureView {
|
|
|
115
191
|
this.props.fileManagement.download(file);
|
|
116
192
|
};
|
|
117
193
|
}
|
|
118
|
-
handleReplace = (file) => {
|
|
119
|
-
this.setSrc(file.id);
|
|
120
|
-
};
|
|
121
194
|
handleDetach = () => {
|
|
122
195
|
this.setSrc('');
|
|
123
196
|
};
|
|
124
197
|
}
|
|
198
|
+
if (can.replaceFile) {
|
|
199
|
+
handleReplace = (file) => {
|
|
200
|
+
this.setSrc(file.id);
|
|
201
|
+
};
|
|
202
|
+
}
|
|
125
203
|
if (can.uploadFile) {
|
|
126
204
|
const upload = (file) => __awaiter(this, void 0, void 0, function* () {
|
|
127
205
|
const result = yield this.props.fileManagement.upload(file);
|
|
128
206
|
this.setSrc(result.id);
|
|
129
207
|
});
|
|
130
208
|
handleUpload = (0, figure_uploader_1.figureUploader)(upload);
|
|
131
|
-
|
|
209
|
+
const handlePlaceholderClick = (event) => {
|
|
210
|
+
const target = event.target;
|
|
211
|
+
if (target.dataset && target.dataset.action) {
|
|
212
|
+
return;
|
|
213
|
+
}
|
|
214
|
+
const triggerUpload = (0, figure_uploader_1.figureUploader)(upload);
|
|
215
|
+
triggerUpload();
|
|
216
|
+
};
|
|
217
|
+
img.addEventListener('click', handlePlaceholderClick);
|
|
132
218
|
img.addEventListener('mouseenter', () => {
|
|
133
219
|
img.classList.toggle('over', true);
|
|
134
220
|
});
|
|
@@ -176,6 +262,7 @@ class FigureEditableView extends figure_1.FigureView {
|
|
|
176
262
|
this.reactTools = (0, ReactSubView_1.default)(this.props, FigureDropdown_1.FigureOptions, componentProps, this.node, this.getPos, this.view);
|
|
177
263
|
this.dom.insertBefore(this.reactTools, this.dom.firstChild);
|
|
178
264
|
}
|
|
265
|
+
this.container.appendChild(this.createPositionMenuWrapper());
|
|
179
266
|
}
|
|
180
267
|
}
|
|
181
268
|
exports.FigureEditableView = FigureEditableView;
|
|
@@ -14,28 +14,13 @@
|
|
|
14
14
|
* See the License for the specific language governing permissions and
|
|
15
15
|
* limitations under the License.
|
|
16
16
|
*/
|
|
17
|
-
var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
|
|
18
|
-
function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
|
|
19
|
-
return new (P || (P = Promise))(function (resolve, reject) {
|
|
20
|
-
function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
|
|
21
|
-
function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
|
|
22
|
-
function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
|
|
23
|
-
step((generator = generator.apply(thisArg, _arguments || [])).next());
|
|
24
|
-
});
|
|
25
|
-
};
|
|
26
17
|
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
27
18
|
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
28
19
|
};
|
|
29
20
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
30
21
|
exports.FigureElementView = void 0;
|
|
31
|
-
const transform_1 = require("@manuscripts/transform");
|
|
32
|
-
const FigureDropdown_1 = require("../components/views/FigureDropdown");
|
|
33
|
-
const files_1 = require("../lib/files");
|
|
34
|
-
const utils_1 = require("../lib/utils");
|
|
35
22
|
const block_view_1 = __importDefault(require("./block_view"));
|
|
36
23
|
const creators_1 = require("./creators");
|
|
37
|
-
const figure_uploader_1 = require("./figure_uploader");
|
|
38
|
-
const ReactSubView_1 = __importDefault(require("./ReactSubView"));
|
|
39
24
|
class FigureElementView extends block_view_1.default {
|
|
40
25
|
constructor() {
|
|
41
26
|
super(...arguments);
|
|
@@ -50,70 +35,6 @@ class FigureElementView extends block_view_1.default {
|
|
|
50
35
|
this.container.appendChild(this.contentDOM);
|
|
51
36
|
};
|
|
52
37
|
}
|
|
53
|
-
updateContents() {
|
|
54
|
-
var _a;
|
|
55
|
-
super.updateContents();
|
|
56
|
-
if (!this.contentDOM) {
|
|
57
|
-
throw new Error('No contentDOM');
|
|
58
|
-
}
|
|
59
|
-
const can = this.props.getCapabilities();
|
|
60
|
-
let handleUpload = () => {
|
|
61
|
-
};
|
|
62
|
-
const hasUploadedImage = !!(0, utils_1.getMatchingChild)(this.node, (node) => node.type === transform_1.schema.nodes.figure && node.attrs.src);
|
|
63
|
-
const handleAdd = (file) => __awaiter(this, void 0, void 0, function* () {
|
|
64
|
-
const { state: { tr, schema, selection }, dispatch, } = this.view;
|
|
65
|
-
const src = file.id;
|
|
66
|
-
const figure = (0, utils_1.getMatchingChild)(this.node, (node) => node.type === schema.nodes.figure);
|
|
67
|
-
if (figure === null || figure === void 0 ? void 0 : figure.attrs.src) {
|
|
68
|
-
const figure = schema.nodes.figure.createAndFill({
|
|
69
|
-
src,
|
|
70
|
-
}, []);
|
|
71
|
-
let position = 0;
|
|
72
|
-
this.node.forEach((node, pos) => {
|
|
73
|
-
if (node.type === schema.nodes.figure) {
|
|
74
|
-
position = pos + node.nodeSize;
|
|
75
|
-
}
|
|
76
|
-
});
|
|
77
|
-
dispatch(tr.insert(this.getPos() + position + 1, figure));
|
|
78
|
-
}
|
|
79
|
-
else if (figure) {
|
|
80
|
-
tr.setNodeMarkup(this.getPos() + 1, undefined, Object.assign(Object.assign({}, figure.attrs), { src })).setSelection(selection.map(tr.doc, tr.mapping));
|
|
81
|
-
dispatch(tr);
|
|
82
|
-
}
|
|
83
|
-
this.deleteSupplementNode(file);
|
|
84
|
-
});
|
|
85
|
-
if (can.uploadFile) {
|
|
86
|
-
const upload = (file) => __awaiter(this, void 0, void 0, function* () {
|
|
87
|
-
const result = yield this.props.fileManagement.upload(file);
|
|
88
|
-
yield handleAdd(result);
|
|
89
|
-
});
|
|
90
|
-
handleUpload = (0, figure_uploader_1.figureUploader)(upload);
|
|
91
|
-
}
|
|
92
|
-
if (this.props.dispatch && this.props.theme) {
|
|
93
|
-
const files = this.props.getFiles();
|
|
94
|
-
const doc = this.view.state.doc;
|
|
95
|
-
const componentProps = {
|
|
96
|
-
can: can,
|
|
97
|
-
files: (0, files_1.groupFiles)(doc, files),
|
|
98
|
-
onUpload: handleUpload,
|
|
99
|
-
onAdd: handleAdd,
|
|
100
|
-
hasUploadedImage: hasUploadedImage,
|
|
101
|
-
};
|
|
102
|
-
(_a = this.reactTools) === null || _a === void 0 ? void 0 : _a.remove();
|
|
103
|
-
this.reactTools = (0, ReactSubView_1.default)(this.props, FigureDropdown_1.FigureElementOptions, componentProps, this.node, this.getPos, this.view);
|
|
104
|
-
this.dom.insertBefore(this.reactTools, this.dom.firstChild);
|
|
105
|
-
}
|
|
106
|
-
}
|
|
107
|
-
deleteSupplementNode(file) {
|
|
108
|
-
const tr = this.view.state.tr;
|
|
109
|
-
this.view.state.doc.descendants((node, pos) => {
|
|
110
|
-
if (node.type === transform_1.schema.nodes.supplement &&
|
|
111
|
-
node.attrs.href === file.id) {
|
|
112
|
-
tr.delete(pos, pos + node.nodeSize);
|
|
113
|
-
}
|
|
114
|
-
});
|
|
115
|
-
this.view.dispatch(tr);
|
|
116
|
-
}
|
|
117
38
|
}
|
|
118
39
|
exports.FigureElementView = FigureElementView;
|
|
119
40
|
exports.default = (0, creators_1.createNodeView)(FigureElementView);
|
|
@@ -58,7 +58,7 @@ class InlineFootnoteView extends base_node_view_1.BaseNodeView {
|
|
|
58
58
|
},
|
|
59
59
|
],
|
|
60
60
|
};
|
|
61
|
-
this.props.popper.show(this.dom, (0, ReactSubView_1.default)(this.props, style_guide_1.ContextMenu, componentProps, this.node, this.getPos, this.view, 'context-menu'), 'right-start', false);
|
|
61
|
+
this.props.popper.show(this.dom, (0, ReactSubView_1.default)(this.props, style_guide_1.ContextMenu, componentProps, this.node, this.getPos, this.view, ['context-menu']), 'right-start', false);
|
|
62
62
|
};
|
|
63
63
|
this.handleClick = () => {
|
|
64
64
|
if ((0, track_changes_utils_1.isDeleted)(this.node)) {
|
|
@@ -106,7 +106,7 @@ class InlineFootnoteView extends base_node_view_1.BaseNodeView {
|
|
|
106
106
|
onAdd: this.handleAdd,
|
|
107
107
|
onInsert: this.handleInsert,
|
|
108
108
|
};
|
|
109
|
-
this.popperContainer = (0, ReactSubView_1.default)(this.props, FootnotesSelector_1.FootnotesSelector, props, this.node, this.getPos, this.view, 'footnote-editor');
|
|
109
|
+
this.popperContainer = (0, ReactSubView_1.default)(this.props, FootnotesSelector_1.FootnotesSelector, props, this.node, this.getPos, this.view, ['footnote-editor']);
|
|
110
110
|
this.props.popper.show(this.dom, this.popperContainer, 'auto', false);
|
|
111
111
|
};
|
|
112
112
|
this.initialise = () => {
|
|
@@ -58,7 +58,7 @@ class KeywordView extends base_node_view_1.BaseNodeView {
|
|
|
58
58
|
keyword: keyword.textContent,
|
|
59
59
|
handleDelete: handleDelete,
|
|
60
60
|
};
|
|
61
|
-
this.dialog = (0, ReactSubView_1.default)(this.props, DeleteKeywordDialog_1.DeleteKeywordDialog, componentProps, this.node, this.getPos, this.view, 'keywords-delete');
|
|
61
|
+
this.dialog = (0, ReactSubView_1.default)(this.props, DeleteKeywordDialog_1.DeleteKeywordDialog, componentProps, this.node, this.getPos, this.view, ['keywords-delete']);
|
|
62
62
|
if (this.dialog) {
|
|
63
63
|
this.dom.appendChild(this.dialog);
|
|
64
64
|
}
|
|
@@ -37,7 +37,7 @@ class KeywordGroupView extends block_view_1.default {
|
|
|
37
37
|
this.contentDOM.setAttribute('contenteditable', 'false');
|
|
38
38
|
this.element.appendChild(this.contentDOM);
|
|
39
39
|
if (this.props.getCapabilities().editArticle) {
|
|
40
|
-
this.addingTools = (0, ReactSubView_1.default)(this.props, AddKeywordInline_1.AddKeywordInline, { getUpdatedNode: () => this.node }, this.node, this.getPos, this.view, 'keywords-editor');
|
|
40
|
+
this.addingTools = (0, ReactSubView_1.default)(this.props, AddKeywordInline_1.AddKeywordInline, { getUpdatedNode: () => this.node }, this.node, this.getPos, this.view, ['keywords-editor']);
|
|
41
41
|
}
|
|
42
42
|
if (this.addingTools) {
|
|
43
43
|
this.element.appendChild(this.addingTools);
|
|
@@ -71,7 +71,7 @@ class LinkEditableView extends link_1.LinkView {
|
|
|
71
71
|
onRemove: this.handleRemove,
|
|
72
72
|
onSave: this.handleSave,
|
|
73
73
|
};
|
|
74
|
-
this.popperContainer = (0, ReactSubView_1.default)(this.props, LinkForm_1.LinkForm, componentProps, this.node, this.getPos, this.view, 'link-editor');
|
|
74
|
+
this.popperContainer = (0, ReactSubView_1.default)(this.props, LinkForm_1.LinkForm, componentProps, this.node, this.getPos, this.view, ['link-editor']);
|
|
75
75
|
this.props.popper.show(this.dom, this.popperContainer, 'bottom');
|
|
76
76
|
};
|
|
77
77
|
this.handleClick = (e) => {
|
|
@@ -79,7 +79,7 @@ class TableCellView extends block_view_1.default {
|
|
|
79
79
|
contextMenuButton.classList.toggle('open-context-menu');
|
|
80
80
|
},
|
|
81
81
|
onCancelColumnDialog: () => this.addOutClickListener(contextMenuButton),
|
|
82
|
-
}, this.view.state.selection.$from.node(), this.getPos, this.view, 'table-cell-context-menu');
|
|
82
|
+
}, this.view.state.selection.$from.node(), this.getPos, this.view, ['table-cell-context-menu']);
|
|
83
83
|
contextMenuButton.classList.toggle('open-context-menu');
|
|
84
84
|
this.props.popper.show(contextMenuButton, contextMenu, 'right', false);
|
|
85
85
|
this.addOutClickListener(contextMenuButton);
|
|
@@ -1,53 +1,39 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { DotsIcon, DropdownList, getFileIcon, IconButton, IconTextButton, isImageFile, TriangleCollapsedIcon, UploadIcon, useDropdown, } from '@manuscripts/style-guide';
|
|
2
2
|
import React from 'react';
|
|
3
3
|
import styled from 'styled-components';
|
|
4
|
-
export const
|
|
4
|
+
export const FigureOptions = ({ can, files, onDownload, onUpload, onDetach, onReplace, }) => {
|
|
5
5
|
const { isOpen, toggleOpen, wrapperRef } = useDropdown();
|
|
6
6
|
const supplements = files.supplements
|
|
7
7
|
.map((s) => s.file)
|
|
8
8
|
.filter((f) => isImageFile(f.name));
|
|
9
|
-
const others = files.others.filter((f) => isImageFile(f.name));
|
|
10
|
-
return (React.createElement(FilesDropdownWrapper, { onClick: toggleOpen, ref: wrapperRef },
|
|
11
|
-
React.createElement(FilesButton, { disabled: hasUploadedImage },
|
|
12
|
-
React.createElement(AttachIcon, null)),
|
|
13
|
-
isOpen && (React.createElement(DropdownList, { direction: 'left', width: 208, height: 187, onClick: toggleOpen, top: 7 },
|
|
14
|
-
React.createElement(NestedDropdown, { disabled: !can.replaceFile || supplements.length < 1, parentToggleOpen: toggleOpen, buttonText: 'Supplements', list: React.createElement(React.Fragment, null, supplements.map((file) => (React.createElement(ListItemButton, { key: file.id, onClick: () => onAdd(file) },
|
|
15
|
-
getFileIcon(file.name),
|
|
16
|
-
React.createElement(ListItemText, null, file.name))))) }),
|
|
17
|
-
React.createElement(NestedDropdown, { disabled: !can.replaceFile || others.length < 1, parentToggleOpen: toggleOpen, buttonText: 'Other files', list: React.createElement(React.Fragment, null, others.map((file) => (React.createElement(ListItemButton, { key: file.id, onClick: () => onAdd(file) },
|
|
18
|
-
getFileIcon(file.name),
|
|
19
|
-
React.createElement(ListItemText, null, file.name))))) }),
|
|
20
|
-
React.createElement(UploadButton, { onClick: onUpload, disabled: !can.uploadFile },
|
|
21
|
-
React.createElement(AddIcon, null),
|
|
22
|
-
" New file...")))));
|
|
23
|
-
};
|
|
24
|
-
export const FigureOptions = ({ can, files, onDownload, onUpload, onDetach, onReplace, }) => {
|
|
25
|
-
const { isOpen, toggleOpen, wrapperRef } = useDropdown();
|
|
26
9
|
const otherFiles = files.others.filter((f) => isImageFile(f.name));
|
|
27
10
|
const showDownload = onDownload && can.downloadFiles;
|
|
28
11
|
const showUpload = onUpload && can.uploadFile;
|
|
29
12
|
const showDetach = onDetach && can.detachFile;
|
|
30
13
|
const showReplace = onReplace && can.replaceFile;
|
|
14
|
+
const replaceBtnText = onDownload ? 'Replace' : 'Choose file';
|
|
31
15
|
return (React.createElement(DropdownWrapper, { ref: wrapperRef },
|
|
32
16
|
React.createElement(OptionsButton, { className: 'options-button', onClick: toggleOpen },
|
|
33
17
|
React.createElement(DotsIcon, null)),
|
|
34
18
|
isOpen && (React.createElement(OptionsDropdownList, { direction: 'right', width: 128, top: 5 },
|
|
35
|
-
React.createElement(
|
|
36
|
-
|
|
19
|
+
React.createElement(NestedDropdown, { disabled: !showReplace, parentToggleOpen: toggleOpen, buttonText: replaceBtnText, moveLeft: true, list: React.createElement(React.Fragment, null,
|
|
20
|
+
supplements.map((file, index) => (React.createElement(ListItemButton, { key: file.id, id: index.toString(), onClick: () => onReplace && onReplace(file) },
|
|
21
|
+
getFileIcon(file.name),
|
|
22
|
+
React.createElement(ListItemText, null, file.name)))),
|
|
37
23
|
otherFiles.map((file, index) => (React.createElement(ListItemButton, { key: file.id, id: index.toString(), onClick: () => onReplace && onReplace(file) },
|
|
38
24
|
getFileIcon(file.name),
|
|
39
25
|
React.createElement(ListItemText, null, file.name)))),
|
|
40
26
|
React.createElement(UploadButton, { onClick: onUpload, disabled: !showUpload },
|
|
41
27
|
React.createElement(UploadIcon, null),
|
|
42
28
|
" Upload new...")) }),
|
|
29
|
+
React.createElement(ListItemButton, { onClick: onDownload, disabled: !showDownload }, "Download"),
|
|
43
30
|
React.createElement(ListItemButton, { onClick: onDetach, disabled: !showDetach }, "Detach")))));
|
|
44
31
|
};
|
|
45
32
|
const NestedDropdown = ({ parentToggleOpen, buttonText, disabled, list, moveLeft }) => {
|
|
46
33
|
const { isOpen, toggleOpen, wrapperRef } = useDropdown();
|
|
47
34
|
return (React.createElement(DropdownWrapper, { ref: wrapperRef },
|
|
48
35
|
React.createElement(NestedListButton, { onClick: toggleOpen, disabled: disabled },
|
|
49
|
-
buttonText,
|
|
50
|
-
" ",
|
|
36
|
+
React.createElement("div", null, buttonText),
|
|
51
37
|
React.createElement(TriangleCollapsedIcon, null)),
|
|
52
38
|
isOpen && (React.createElement(NestedListDropdownList, { direction: 'right', moveLeft: moveLeft, width: 192, onClick: (e) => {
|
|
53
39
|
toggleOpen();
|
|
@@ -67,9 +53,6 @@ const OptionsButton = styled(IconButton) `
|
|
|
67
53
|
margin: ${(props) => props.theme.grid.unit}px;
|
|
68
54
|
visibility: hidden;
|
|
69
55
|
background: white;
|
|
70
|
-
position: absolute;
|
|
71
|
-
top: -4px;
|
|
72
|
-
right: 4%;
|
|
73
56
|
|
|
74
57
|
&:hover {
|
|
75
58
|
background: #f2fbfc !important;
|
|
@@ -111,30 +94,15 @@ const ListItemText = styled.div `
|
|
|
111
94
|
text-overflow: ellipsis;
|
|
112
95
|
text-align: start;
|
|
113
96
|
`;
|
|
114
|
-
const FilesButton = styled(RoundIconButton) `
|
|
115
|
-
path {
|
|
116
|
-
stroke: #6e6e6e;
|
|
117
|
-
}
|
|
118
|
-
|
|
119
|
-
&:active,
|
|
120
|
-
&:focus {
|
|
121
|
-
path {
|
|
122
|
-
stroke: #1a9bc7;
|
|
123
|
-
}
|
|
124
|
-
}
|
|
125
|
-
`;
|
|
126
|
-
const FilesDropdownWrapper = styled.div `
|
|
127
|
-
position: absolute;
|
|
128
|
-
top: 8px;
|
|
129
|
-
left: 70px;
|
|
130
|
-
z-index: 1;
|
|
131
|
-
`;
|
|
132
97
|
const NestedListButton = styled(ListItemButton) `
|
|
133
98
|
width: 100%;
|
|
134
99
|
&:active,
|
|
135
100
|
&:focus {
|
|
136
101
|
background: #f2fbfc;
|
|
137
102
|
}
|
|
103
|
+
svg {
|
|
104
|
+
margin-right: 0;
|
|
105
|
+
}
|
|
138
106
|
`;
|
|
139
107
|
const NestedListDropdownList = styled(DropdownList) `
|
|
140
108
|
top: 0;
|
|
@@ -29,6 +29,7 @@ import doi from '../plugins/doi';
|
|
|
29
29
|
import editorProps from '../plugins/editor-props';
|
|
30
30
|
import elements from '../plugins/elements';
|
|
31
31
|
import footnotes from '../plugins/footnotes';
|
|
32
|
+
import inspector_tabs from '../plugins/inspector-tabs';
|
|
32
33
|
import objects from '../plugins/objects';
|
|
33
34
|
import paragraphs from '../plugins/paragraphs';
|
|
34
35
|
import persist from '../plugins/persist';
|
|
@@ -70,6 +71,7 @@ export default (props) => {
|
|
|
70
71
|
doi(),
|
|
71
72
|
section_category(props),
|
|
72
73
|
cross_references(),
|
|
74
|
+
inspector_tabs(),
|
|
73
75
|
];
|
|
74
76
|
if (props.collabProvider) {
|
|
75
77
|
allPlugins.push(collab({ version: props.collabProvider.currentVersion }));
|
package/dist/es/index.js
CHANGED
|
@@ -39,3 +39,4 @@ export { footnotesKey as footnotesPluginKey } from './plugins/footnotes';
|
|
|
39
39
|
export { bibliographyKey as bibliographyPluginKey } from './plugins/bibliography';
|
|
40
40
|
export { metadata } from './lib/references';
|
|
41
41
|
export { authorLabel, affiliationLabel, } from './lib/authors';
|
|
42
|
+
export * from './plugins/inspector-tabs';
|
|
@@ -13,11 +13,16 @@
|
|
|
13
13
|
* See the License for the specific language governing permissions and
|
|
14
14
|
* limitations under the License.
|
|
15
15
|
*/
|
|
16
|
+
import { ImageDefaultIcon, ImageLeftIcon, ImageRightIcon, TriangleCollapsedIcon, } from '@manuscripts/style-guide';
|
|
16
17
|
import { getListType, isInBibliographySection, isSectionTitleNode, nodeNames, schema, } from '@manuscripts/transform';
|
|
17
18
|
import { findChildrenByType } from 'prosemirror-utils';
|
|
19
|
+
import { createElement } from 'react';
|
|
20
|
+
import { renderToStaticMarkup } from 'react-dom/server';
|
|
18
21
|
import { addNodeComment, createBlock, findPosBeforeFirstSubsection, insertGeneralTableFootnote, insertInlineTableFootnote, } from '../commands';
|
|
22
|
+
import { figurePositions } from '../views/figure_editable';
|
|
19
23
|
import { PopperManager } from './popper';
|
|
20
|
-
import { isChildOfNodeTypes, isSelectionInNode } from './utils';
|
|
24
|
+
import { getMatchingChild, isChildOfNodeTypes, isSelectionInNode, } from './utils';
|
|
25
|
+
import { updateNodeAttrs } from './view';
|
|
21
26
|
const popper = new PopperManager();
|
|
22
27
|
const readonlyTypes = [
|
|
23
28
|
schema.nodes.keywords,
|
|
@@ -38,6 +43,7 @@ const hasAny = (set, ...items) => {
|
|
|
38
43
|
return items.some((i) => set.has(i));
|
|
39
44
|
};
|
|
40
45
|
export const contextMenuBtnClass = 'btn-context-menu';
|
|
46
|
+
const contextSubmenuBtnClass = 'context-submenu-trigger';
|
|
41
47
|
export class ContextMenu {
|
|
42
48
|
constructor(node, view, getPos, actions = {}) {
|
|
43
49
|
this.showAddMenu = (target, after) => {
|
|
@@ -146,6 +152,36 @@ export class ContextMenu {
|
|
|
146
152
|
const $pos = this.resolvePos();
|
|
147
153
|
const isBox = isBoxElementSectionTitle($pos, this.node);
|
|
148
154
|
const type = isBox ? schema.nodes.box_element : this.node.type;
|
|
155
|
+
if (type === schema.nodes.figure_element ||
|
|
156
|
+
type === schema.nodes.image_element) {
|
|
157
|
+
const figure = getMatchingChild(this.node, (node) => node.type === schema.nodes.figure);
|
|
158
|
+
if (figure) {
|
|
159
|
+
const attrType = figure.attrs.type;
|
|
160
|
+
const submenuOptions = [
|
|
161
|
+
{
|
|
162
|
+
title: 'Left',
|
|
163
|
+
action: () => updateNodeAttrs(this.view, schema.nodes.figure, Object.assign(Object.assign({}, figure.attrs), { type: figurePositions.left })),
|
|
164
|
+
Icon: ImageLeftIcon,
|
|
165
|
+
selected: attrType === figurePositions.left,
|
|
166
|
+
},
|
|
167
|
+
{
|
|
168
|
+
title: 'Default',
|
|
169
|
+
action: () => updateNodeAttrs(this.view, schema.nodes.figure, Object.assign(Object.assign({}, figure.attrs), { type: figurePositions.default })),
|
|
170
|
+
Icon: ImageDefaultIcon,
|
|
171
|
+
selected: !attrType,
|
|
172
|
+
},
|
|
173
|
+
{
|
|
174
|
+
title: 'Right',
|
|
175
|
+
action: () => updateNodeAttrs(this.view, schema.nodes.figure, Object.assign(Object.assign({}, figure.attrs), { type: figurePositions.right })),
|
|
176
|
+
Icon: ImageRightIcon,
|
|
177
|
+
selected: attrType === figurePositions.right,
|
|
178
|
+
},
|
|
179
|
+
];
|
|
180
|
+
const submenuLabel = 'Position';
|
|
181
|
+
const submenu = this.createSubmenu(submenuLabel, submenuOptions);
|
|
182
|
+
menu.appendChild(submenu);
|
|
183
|
+
}
|
|
184
|
+
}
|
|
149
185
|
if (type === schema.nodes.list) {
|
|
150
186
|
menu.appendChild(this.createMenuSection((section) => {
|
|
151
187
|
const attrs = this.node.attrs;
|
|
@@ -210,22 +246,48 @@ export class ContextMenu {
|
|
|
210
246
|
popper.show(target, menu, 'right', true);
|
|
211
247
|
this.addPopperEventListeners();
|
|
212
248
|
};
|
|
213
|
-
this.
|
|
249
|
+
this.createSubmenuTrigger = (contents) => {
|
|
250
|
+
const item = document.createElement('div');
|
|
251
|
+
item.className = 'menu-item';
|
|
252
|
+
const textNode = document.createTextNode(contents);
|
|
253
|
+
item.innerHTML = renderToStaticMarkup(createElement(TriangleCollapsedIcon));
|
|
254
|
+
item.prepend(textNode);
|
|
255
|
+
item.classList.add(contextSubmenuBtnClass);
|
|
256
|
+
item.addEventListener('mousedown', this.toggleSubmenu);
|
|
257
|
+
return item;
|
|
258
|
+
};
|
|
259
|
+
this.createMenuItem = (contents, handler, Icon = null, selected = false) => {
|
|
214
260
|
const item = document.createElement('div');
|
|
215
261
|
item.className = 'menu-item';
|
|
216
|
-
item.
|
|
262
|
+
selected && item.classList.add('selected');
|
|
263
|
+
if (Icon) {
|
|
264
|
+
item.innerHTML = renderToStaticMarkup(createElement(Icon));
|
|
265
|
+
}
|
|
266
|
+
const textNode = document.createTextNode(contents);
|
|
267
|
+
item.appendChild(textNode);
|
|
217
268
|
item.addEventListener('mousedown', (event) => {
|
|
218
269
|
event.preventDefault();
|
|
219
270
|
handler(event);
|
|
220
271
|
});
|
|
221
272
|
return item;
|
|
222
273
|
};
|
|
223
|
-
this.createMenuSection = (createMenuItems) => {
|
|
274
|
+
this.createMenuSection = (createMenuItems, isSubmenu = false) => {
|
|
224
275
|
const section = document.createElement('div');
|
|
225
276
|
section.className = 'menu-section';
|
|
277
|
+
isSubmenu && section.classList.add('menu');
|
|
226
278
|
createMenuItems(section);
|
|
227
279
|
return section;
|
|
228
280
|
};
|
|
281
|
+
this.createSubmenu = (submenuLabel, items) => {
|
|
282
|
+
const submenu = document.createElement('div');
|
|
283
|
+
submenu.classList.add('menu-section', 'context-submenu');
|
|
284
|
+
submenu.append(this.createSubmenuTrigger(submenuLabel), this.createMenuSection((section) => {
|
|
285
|
+
items.forEach(({ title, action, Icon, selected }) => {
|
|
286
|
+
section.appendChild(this.createMenuItem(title, action, Icon, selected));
|
|
287
|
+
});
|
|
288
|
+
}, true));
|
|
289
|
+
return submenu;
|
|
290
|
+
};
|
|
229
291
|
this.insertableTypes = (after, insertPos, endPos) => {
|
|
230
292
|
const { nodes } = schema;
|
|
231
293
|
const insertable = new Set();
|
|
@@ -287,7 +349,8 @@ export class ContextMenu {
|
|
|
287
349
|
this.addPopperEventListeners = () => {
|
|
288
350
|
const mouseListener = (event) => {
|
|
289
351
|
const target = event.target;
|
|
290
|
-
if (target.classList.contains(contextMenuBtnClass)
|
|
352
|
+
if (target.classList.contains(contextMenuBtnClass) ||
|
|
353
|
+
target.classList.contains(contextSubmenuBtnClass)) {
|
|
291
354
|
return;
|
|
292
355
|
}
|
|
293
356
|
window.requestAnimationFrame(() => {
|
|
@@ -319,6 +382,10 @@ export class ContextMenu {
|
|
|
319
382
|
}
|
|
320
383
|
return this.node;
|
|
321
384
|
};
|
|
385
|
+
this.toggleSubmenu = (ev) => {
|
|
386
|
+
const submenu = ev.target.nextElementSibling;
|
|
387
|
+
submenu === null || submenu === void 0 ? void 0 : submenu.classList.toggle('show');
|
|
388
|
+
};
|
|
322
389
|
this.node = node;
|
|
323
390
|
this.view = view;
|
|
324
391
|
this.getPos = getPos;
|
package/dist/es/lib/view.js
CHANGED
|
@@ -14,6 +14,7 @@
|
|
|
14
14
|
* limitations under the License.
|
|
15
15
|
*/
|
|
16
16
|
import { schema, } from '@manuscripts/transform';
|
|
17
|
+
import { NodeSelection } from 'prosemirror-state';
|
|
17
18
|
import * as utils from 'prosemirror-utils';
|
|
18
19
|
import { isHidden, sanitizeAttrsChange } from './track-changes-utils';
|
|
19
20
|
const metaNodeTypes = [
|
|
@@ -44,7 +45,8 @@ export const updateNodeAttrs = (view, type, attrs) => {
|
|
|
44
45
|
const copy = sanitizeAttrsChange(attrs, child.node.attrs);
|
|
45
46
|
delete copy.dataTracked;
|
|
46
47
|
const pos = child.pos;
|
|
47
|
-
const tr = view.state.tr
|
|
48
|
+
const tr = view.state.tr;
|
|
49
|
+
tr.setNodeMarkup(pos, undefined, copy).setSelection(NodeSelection.create(tr.doc, pos));
|
|
48
50
|
if (metaNodeTypes.includes(type)) {
|
|
49
51
|
tr.setMeta(updateMetaNode, true);
|
|
50
52
|
}
|