@manuscripts/body-editor 1.7.39-LEAN-3049.0 → 1.7.39
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/commands.js +12 -14
- package/dist/cjs/components/authors/AuthorsModal.js +11 -2
- package/dist/cjs/components/views/LinkForm.js +36 -30
- package/dist/cjs/views/link.js +35 -0
- package/dist/cjs/views/link_editable.js +27 -70
- package/dist/es/commands.js +12 -14
- package/dist/es/components/authors/AuthorsModal.js +11 -2
- package/dist/es/components/views/LinkForm.js +35 -29
- package/dist/es/views/link.js +35 -0
- package/dist/es/views/link_editable.js +28 -71
- package/dist/types/components/views/LinkForm.d.ts +5 -6
- package/dist/types/views/link.d.ts +3 -0
- package/dist/types/views/link_editable.d.ts +0 -6
- package/package.json +3 -3
package/dist/cjs/commands.js
CHANGED
|
@@ -242,23 +242,21 @@ const insertSectionLabel = (state, dispatch, currentTr) => {
|
|
|
242
242
|
return true;
|
|
243
243
|
};
|
|
244
244
|
exports.insertSectionLabel = insertSectionLabel;
|
|
245
|
-
const isLink = (text) => /^\s*(https?:\S+)/.test(text);
|
|
246
245
|
const insertLink = (state, dispatch) => {
|
|
247
|
-
const
|
|
248
|
-
const
|
|
249
|
-
|
|
250
|
-
|
|
251
|
-
|
|
252
|
-
|
|
253
|
-
|
|
254
|
-
|
|
255
|
-
|
|
256
|
-
|
|
257
|
-
|
|
258
|
-
}
|
|
246
|
+
const text = selectedText();
|
|
247
|
+
const contents = text ? state.schema.text(text) : undefined;
|
|
248
|
+
const matches = text.match(/^\s*(https?:\S+)/);
|
|
249
|
+
const attrs = {
|
|
250
|
+
href: matches ? matches[1] : '',
|
|
251
|
+
};
|
|
252
|
+
const range = new prosemirror_model_1.NodeRange(state.selection.$from, state.selection.$to, state.selection.$from.depth);
|
|
253
|
+
const { tr } = state;
|
|
254
|
+
const wrapping = (0, prosemirror_transform_1.findWrapping)(range, state.schema.nodes.link, attrs);
|
|
255
|
+
if (wrapping) {
|
|
256
|
+
tr.wrap(range, wrapping);
|
|
259
257
|
}
|
|
260
258
|
else {
|
|
261
|
-
tr.insert(state.selection.anchor,
|
|
259
|
+
tr.insert(state.selection.anchor, state.schema.nodes.link.create(attrs, contents));
|
|
262
260
|
}
|
|
263
261
|
if (dispatch) {
|
|
264
262
|
const selection = prosemirror_state_1.NodeSelection.create(tr.doc, state.tr.selection.from);
|
|
@@ -112,6 +112,15 @@ const AuthorsModal = ({ authors: $authors, affiliations: $affiliations, author,
|
|
|
112
112
|
setSelection(author);
|
|
113
113
|
}
|
|
114
114
|
};
|
|
115
|
+
const handleClose = () => {
|
|
116
|
+
const values = valuesRef.current;
|
|
117
|
+
if (values && selection && !(0, lodash_1.isEqual)(values, normalize(selection))) {
|
|
118
|
+
setShowConfirmationDialog(true);
|
|
119
|
+
}
|
|
120
|
+
else {
|
|
121
|
+
setOpen(false);
|
|
122
|
+
}
|
|
123
|
+
};
|
|
115
124
|
const handleSaveAuthor = (values) => {
|
|
116
125
|
if (!values || !selection) {
|
|
117
126
|
return;
|
|
@@ -202,10 +211,10 @@ const AuthorsModal = ({ authors: $authors, affiliations: $affiliations, author,
|
|
|
202
211
|
const handleChangeAuthor = (values) => {
|
|
203
212
|
valuesRef.current = values;
|
|
204
213
|
};
|
|
205
|
-
return (react_1.default.createElement(style_guide_1.StyledModal, { isOpen: isOpen, onRequestClose: () =>
|
|
214
|
+
return (react_1.default.createElement(style_guide_1.StyledModal, { isOpen: isOpen, onRequestClose: () => handleClose(), shouldCloseOnOverlayClick: true },
|
|
206
215
|
react_1.default.createElement(style_guide_1.ModalContainer, null,
|
|
207
216
|
react_1.default.createElement(style_guide_1.ModalHeader, null,
|
|
208
|
-
react_1.default.createElement(style_guide_1.CloseButton, { onClick: () =>
|
|
217
|
+
react_1.default.createElement(style_guide_1.CloseButton, { onClick: () => handleClose(), "data-cy": "modal-close-button" })),
|
|
209
218
|
react_1.default.createElement(style_guide_1.ModalBody, null,
|
|
210
219
|
react_1.default.createElement(style_guide_1.ModalSidebar, { "data-cy": "authors-sidebar" },
|
|
211
220
|
react_1.default.createElement(style_guide_1.ModalSidebarHeader, null,
|
|
@@ -46,6 +46,42 @@ const style_guide_1 = require("@manuscripts/style-guide");
|
|
|
46
46
|
const react_1 = __importStar(require("react"));
|
|
47
47
|
const styled_components_1 = __importDefault(require("styled-components"));
|
|
48
48
|
const url_1 = require("../../lib/url");
|
|
49
|
+
const LinkForm = ({ handleCancel, handleRemove, handleSave, value }) => {
|
|
50
|
+
const [href, setHref] = (0, react_1.useState)(value.href);
|
|
51
|
+
const [text, setText] = (0, react_1.useState)(value.text);
|
|
52
|
+
const [title, setTitle] = (0, react_1.useState)(value.title || '');
|
|
53
|
+
const handleSubmit = (0, react_1.useCallback)((event) => {
|
|
54
|
+
event.preventDefault();
|
|
55
|
+
handleSave({ href, text, title });
|
|
56
|
+
}, [href, text, title, handleSave]);
|
|
57
|
+
return (react_1.default.createElement(Form, { onSubmit: handleSubmit },
|
|
58
|
+
react_1.default.createElement(Field, null,
|
|
59
|
+
react_1.default.createElement(FieldHeading, null,
|
|
60
|
+
react_1.default.createElement(Label, null, "URL"),
|
|
61
|
+
href && (0, url_1.allowedHref)(href) && (react_1.default.createElement(Open, { href: href, target: '_blank', rel: 'noopener' }))),
|
|
62
|
+
react_1.default.createElement(style_guide_1.TextField, { type: 'url', name: 'href', value: href, autoComplete: 'off', autoFocus: true, required: true, onChange: (event) => {
|
|
63
|
+
setHref(event.target.value);
|
|
64
|
+
} })),
|
|
65
|
+
react_1.default.createElement(Field, null,
|
|
66
|
+
react_1.default.createElement(FieldHeading, null,
|
|
67
|
+
react_1.default.createElement(Label, null, "Text")),
|
|
68
|
+
react_1.default.createElement(style_guide_1.TextField, { type: 'text', name: 'text', value: text, autoComplete: 'off', required: true, onChange: (event) => {
|
|
69
|
+
setText(event.target.value);
|
|
70
|
+
} })),
|
|
71
|
+
react_1.default.createElement(Field, null,
|
|
72
|
+
react_1.default.createElement(FieldHeading, null,
|
|
73
|
+
react_1.default.createElement(Label, null, "Title (optional)")),
|
|
74
|
+
react_1.default.createElement(style_guide_1.TextField, { type: 'text', name: 'title', value: title, autoComplete: 'off', required: false, onChange: (event) => {
|
|
75
|
+
setTitle(event.target.value);
|
|
76
|
+
} })),
|
|
77
|
+
react_1.default.createElement(Actions, null,
|
|
78
|
+
react_1.default.createElement(ActionGroup, null,
|
|
79
|
+
react_1.default.createElement(style_guide_1.SecondaryButton, { type: 'button', mini: true, onClick: handleRemove }, "Remove Link")),
|
|
80
|
+
react_1.default.createElement(ActionGroup, null,
|
|
81
|
+
react_1.default.createElement(style_guide_1.SecondaryButton, { type: 'button', onClick: handleCancel }, "Cancel"),
|
|
82
|
+
react_1.default.createElement(style_guide_1.PrimaryButton, { type: 'submit' }, "Save")))));
|
|
83
|
+
};
|
|
84
|
+
exports.LinkForm = LinkForm;
|
|
49
85
|
const Form = styled_components_1.default.form `
|
|
50
86
|
padding: 16px;
|
|
51
87
|
`;
|
|
@@ -91,33 +127,3 @@ const Open = styled_components_1.default.a `
|
|
|
91
127
|
margin-left: 4px;
|
|
92
128
|
}
|
|
93
129
|
`;
|
|
94
|
-
const LinkForm = ({ onCancel, onRemove, onSave, value, }) => {
|
|
95
|
-
const [href, setHref] = (0, react_1.useState)(value.href);
|
|
96
|
-
const [text, setText] = (0, react_1.useState)(value.text);
|
|
97
|
-
const [title, setTitle] = (0, react_1.useState)(value.title || '');
|
|
98
|
-
const handleSubmit = (0, react_1.useCallback)((event) => {
|
|
99
|
-
event.preventDefault();
|
|
100
|
-
onSave({ href, text, title });
|
|
101
|
-
}, [href, text, title, onSave]);
|
|
102
|
-
return (react_1.default.createElement(Form, { onSubmit: handleSubmit },
|
|
103
|
-
react_1.default.createElement(Field, null,
|
|
104
|
-
react_1.default.createElement(FieldHeading, null,
|
|
105
|
-
react_1.default.createElement(Label, null, "URL"),
|
|
106
|
-
href && (0, url_1.allowedHref)(href) && (react_1.default.createElement(Open, { href: href, target: '_blank', rel: 'noopener' }))),
|
|
107
|
-
react_1.default.createElement(style_guide_1.TextField, { type: 'url', name: 'href', value: href, autoComplete: 'off', autoFocus: true, required: true, onChange: (e) => setHref(e.target.value) })),
|
|
108
|
-
react_1.default.createElement(Field, null,
|
|
109
|
-
react_1.default.createElement(FieldHeading, null,
|
|
110
|
-
react_1.default.createElement(Label, null, "Text")),
|
|
111
|
-
react_1.default.createElement(style_guide_1.TextField, { type: 'text', name: 'text', value: text, autoComplete: 'off', required: true, onChange: (e) => setText(e.target.value) })),
|
|
112
|
-
react_1.default.createElement(Field, null,
|
|
113
|
-
react_1.default.createElement(FieldHeading, null,
|
|
114
|
-
react_1.default.createElement(Label, null, "Title (optional)")),
|
|
115
|
-
react_1.default.createElement(style_guide_1.TextField, { type: 'text', name: 'title', value: title, autoComplete: 'off', required: false, onChange: (e) => setTitle(e.target.value) })),
|
|
116
|
-
react_1.default.createElement(Actions, null,
|
|
117
|
-
react_1.default.createElement(ActionGroup, null,
|
|
118
|
-
react_1.default.createElement(style_guide_1.SecondaryButton, { type: 'button', mini: true, onClick: onRemove }, "Remove Link")),
|
|
119
|
-
react_1.default.createElement(ActionGroup, null,
|
|
120
|
-
react_1.default.createElement(style_guide_1.SecondaryButton, { type: 'button', onClick: onCancel }, "Cancel"),
|
|
121
|
-
react_1.default.createElement(style_guide_1.PrimaryButton, { type: 'submit' }, "Save")))));
|
|
122
|
-
};
|
|
123
|
-
exports.LinkForm = LinkForm;
|
package/dist/cjs/views/link.js
CHANGED
|
@@ -16,9 +16,44 @@
|
|
|
16
16
|
*/
|
|
17
17
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
18
18
|
exports.LinkView = void 0;
|
|
19
|
+
const track_changes_utils_1 = require("../lib/track-changes-utils");
|
|
20
|
+
const url_1 = require("../lib/url");
|
|
19
21
|
const base_node_view_1 = require("./base_node_view");
|
|
20
22
|
const creators_1 = require("./creators");
|
|
21
23
|
class LinkView extends base_node_view_1.BaseNodeView {
|
|
24
|
+
constructor() {
|
|
25
|
+
super(...arguments);
|
|
26
|
+
this.initialise = () => {
|
|
27
|
+
this.createDOM();
|
|
28
|
+
this.updateContents();
|
|
29
|
+
};
|
|
30
|
+
this.updateContents = () => {
|
|
31
|
+
var _a, _b, _c;
|
|
32
|
+
const linkText = ((_c = (_b = (_a = this.node) === null || _a === void 0 ? void 0 : _a.content) === null || _b === void 0 ? void 0 : _b.firstChild) === null || _c === void 0 ? void 0 : _c.text) || '';
|
|
33
|
+
if (!(0, track_changes_utils_1.isRejectedInsert)(this.node)) {
|
|
34
|
+
const { href, title } = this.node.attrs;
|
|
35
|
+
const linkElement = document.createElement('a');
|
|
36
|
+
linkElement.classList.add('link');
|
|
37
|
+
linkElement.style.position = 'relative';
|
|
38
|
+
if (href && (0, url_1.allowedHref)(href)) {
|
|
39
|
+
linkElement.setAttribute('href', href);
|
|
40
|
+
}
|
|
41
|
+
if (title) {
|
|
42
|
+
linkElement.setAttribute('title', title);
|
|
43
|
+
}
|
|
44
|
+
linkElement.innerHTML = linkText;
|
|
45
|
+
this.dom.innerHTML = '';
|
|
46
|
+
this.dom.appendChild(linkElement);
|
|
47
|
+
}
|
|
48
|
+
else {
|
|
49
|
+
this.dom.innerHTML = linkText;
|
|
50
|
+
}
|
|
51
|
+
};
|
|
52
|
+
this.createDOM = () => {
|
|
53
|
+
this.dom = document.createElement('span');
|
|
54
|
+
this.contentDOM = this.dom;
|
|
55
|
+
};
|
|
56
|
+
}
|
|
22
57
|
}
|
|
23
58
|
exports.LinkView = LinkView;
|
|
24
59
|
exports.default = (0, creators_1.createNodeView)(LinkView);
|
|
@@ -19,119 +19,76 @@ var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
|
19
19
|
};
|
|
20
20
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
21
21
|
exports.LinkEditableView = void 0;
|
|
22
|
-
const transform_1 = require("@manuscripts/transform");
|
|
23
22
|
const prosemirror_state_1 = require("prosemirror-state");
|
|
24
23
|
const LinkForm_1 = require("../components/views/LinkForm");
|
|
25
|
-
const track_changes_utils_1 = require("../lib/track-changes-utils");
|
|
26
|
-
const url_1 = require("../lib/url");
|
|
27
24
|
const creators_1 = require("./creators");
|
|
28
25
|
const link_1 = require("./link");
|
|
29
26
|
const ReactSubView_1 = __importDefault(require("./ReactSubView"));
|
|
30
27
|
class LinkEditableView extends link_1.LinkView {
|
|
31
28
|
constructor() {
|
|
32
29
|
super(...arguments);
|
|
33
|
-
this.ignoreMutation = () => true;
|
|
34
|
-
this.initialise = () => {
|
|
35
|
-
this.createDOM();
|
|
36
|
-
this.updateContents();
|
|
37
|
-
};
|
|
38
|
-
this.updateContents = () => {
|
|
39
|
-
if ((0, track_changes_utils_1.isRejectedInsert)(this.node)) {
|
|
40
|
-
this.dom.innerHTML = '';
|
|
41
|
-
this.contentDOM = undefined;
|
|
42
|
-
return;
|
|
43
|
-
}
|
|
44
|
-
this.contentDOM = this.dom;
|
|
45
|
-
const attrs = (0, track_changes_utils_1.getActualAttrs)(this.node);
|
|
46
|
-
const href = attrs.href;
|
|
47
|
-
const title = attrs.title;
|
|
48
|
-
const classes = ['link', ...(0, track_changes_utils_1.getChangeClasses)(this.node.attrs.dataTracked)];
|
|
49
|
-
this.dom.className = classes.join(' ');
|
|
50
|
-
this.dom.setAttribute('href', (0, url_1.allowedHref)(href) ? href : '');
|
|
51
|
-
this.dom.setAttribute('target', '_blank');
|
|
52
|
-
this.dom.setAttribute('title', title || '');
|
|
53
|
-
};
|
|
54
|
-
this.createDOM = () => {
|
|
55
|
-
this.dom = document.createElement('a');
|
|
56
|
-
this.dom.addEventListener('click', this.handleClick);
|
|
57
|
-
};
|
|
58
30
|
this.selectNode = () => {
|
|
59
|
-
|
|
60
|
-
this.showForm();
|
|
61
|
-
}
|
|
31
|
+
this.showForm();
|
|
62
32
|
};
|
|
63
33
|
this.destroy = () => {
|
|
64
34
|
this.closeForm();
|
|
65
35
|
};
|
|
66
36
|
this.deselectNode = () => {
|
|
67
|
-
const attrs = (0, track_changes_utils_1.getActualAttrs)(this.node);
|
|
68
|
-
if (!this.node.content.size || !attrs.href) {
|
|
69
|
-
this.removeLink();
|
|
70
|
-
}
|
|
71
37
|
this.closeForm();
|
|
72
38
|
};
|
|
73
|
-
this.showForm = () => {
|
|
39
|
+
this.showForm = (event) => {
|
|
40
|
+
if (event) {
|
|
41
|
+
event.preventDefault();
|
|
42
|
+
}
|
|
74
43
|
if (!this.props.getCapabilities().editArticle) {
|
|
75
44
|
return;
|
|
76
45
|
}
|
|
77
|
-
const
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
title: attrs.title,
|
|
46
|
+
const originalValue = {
|
|
47
|
+
href: this.node.attrs.href,
|
|
48
|
+
title: this.node.attrs.title,
|
|
81
49
|
text: this.node.textContent,
|
|
82
50
|
};
|
|
83
51
|
const componentProps = {
|
|
84
|
-
value,
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
52
|
+
value: originalValue,
|
|
53
|
+
handleCancel: this.handleCancel,
|
|
54
|
+
handleRemove: this.handleRemove,
|
|
55
|
+
handleSave: this.handleSave,
|
|
88
56
|
};
|
|
89
57
|
this.popperContainer = (0, ReactSubView_1.default)(this.props, LinkForm_1.LinkForm, componentProps, this.node, this.getPos, this.view, 'link-editor');
|
|
90
58
|
this.props.popper.show(this.dom, this.popperContainer, 'bottom');
|
|
91
59
|
};
|
|
92
|
-
this.handleClick = (e) => {
|
|
93
|
-
if (this.props.getCapabilities().editArticle) {
|
|
94
|
-
e.preventDefault();
|
|
95
|
-
}
|
|
96
|
-
};
|
|
97
60
|
this.handleCancel = () => {
|
|
98
|
-
const
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
61
|
+
const tr = this.view.state.tr;
|
|
62
|
+
const pos = this.getPos();
|
|
63
|
+
tr.setSelection(prosemirror_state_1.TextSelection.create(tr.doc, pos));
|
|
64
|
+
this.view.focus();
|
|
65
|
+
this.view.dispatch(tr);
|
|
102
66
|
this.closeForm();
|
|
103
67
|
};
|
|
104
68
|
this.handleRemove = () => {
|
|
105
|
-
this.
|
|
69
|
+
const tr = this.view.state.tr;
|
|
70
|
+
const pos = this.getPos();
|
|
71
|
+
const to = pos + this.node.nodeSize;
|
|
72
|
+
tr.replaceWith(pos, to, this.node.content).setSelection(prosemirror_state_1.TextSelection.create(tr.doc, pos));
|
|
73
|
+
this.view.focus();
|
|
74
|
+
this.view.dispatch(tr);
|
|
106
75
|
this.closeForm();
|
|
107
76
|
};
|
|
108
77
|
this.handleSave = (value) => {
|
|
109
78
|
const tr = this.view.state.tr;
|
|
110
|
-
const
|
|
79
|
+
const link = this.node;
|
|
111
80
|
const pos = this.getPos();
|
|
112
|
-
if (value.href !== attrs.href || value.title !== attrs.title) {
|
|
81
|
+
if (value.href !== link.attrs.href || value.title !== link.attrs.title) {
|
|
113
82
|
tr.setNodeMarkup(pos, undefined, Object.assign(Object.assign({}, this.node.attrs), { href: value.href, title: value.title }));
|
|
114
83
|
}
|
|
115
|
-
if (value.text !==
|
|
116
|
-
tr.
|
|
117
|
-
tr.insert(pos + 1, transform_1.schema.text(value.text));
|
|
84
|
+
if (value.text !== link.textContent) {
|
|
85
|
+
tr.insertText(value.text, pos + 1, pos + this.node.nodeSize - 1);
|
|
118
86
|
}
|
|
119
87
|
tr.setSelection(prosemirror_state_1.TextSelection.create(tr.doc, pos));
|
|
120
88
|
this.view.focus();
|
|
121
89
|
this.view.dispatch(tr);
|
|
122
90
|
this.closeForm();
|
|
123
91
|
};
|
|
124
|
-
this.removeLink = () => {
|
|
125
|
-
const tr = this.view.state.tr;
|
|
126
|
-
const pos = this.getPos();
|
|
127
|
-
tr.delete(pos, pos + this.node.nodeSize);
|
|
128
|
-
const text = this.node.textContent;
|
|
129
|
-
if (text) {
|
|
130
|
-
tr.insert(pos, transform_1.schema.text(text));
|
|
131
|
-
}
|
|
132
|
-
tr.setSelection(prosemirror_state_1.TextSelection.create(tr.doc, pos));
|
|
133
|
-
this.view.dispatch(tr);
|
|
134
|
-
};
|
|
135
92
|
this.closeForm = () => {
|
|
136
93
|
var _a;
|
|
137
94
|
this.props.popper.destroy();
|
package/dist/es/commands.js
CHANGED
|
@@ -227,23 +227,21 @@ export const insertSectionLabel = (state, dispatch, currentTr) => {
|
|
|
227
227
|
}
|
|
228
228
|
return true;
|
|
229
229
|
};
|
|
230
|
-
const isLink = (text) => /^\s*(https?:\S+)/.test(text);
|
|
231
230
|
export const insertLink = (state, dispatch) => {
|
|
232
|
-
const
|
|
233
|
-
const
|
|
234
|
-
|
|
235
|
-
|
|
236
|
-
|
|
237
|
-
|
|
238
|
-
|
|
239
|
-
|
|
240
|
-
|
|
241
|
-
|
|
242
|
-
|
|
243
|
-
}
|
|
231
|
+
const text = selectedText();
|
|
232
|
+
const contents = text ? state.schema.text(text) : undefined;
|
|
233
|
+
const matches = text.match(/^\s*(https?:\S+)/);
|
|
234
|
+
const attrs = {
|
|
235
|
+
href: matches ? matches[1] : '',
|
|
236
|
+
};
|
|
237
|
+
const range = new NodeRange(state.selection.$from, state.selection.$to, state.selection.$from.depth);
|
|
238
|
+
const { tr } = state;
|
|
239
|
+
const wrapping = findWrapping(range, state.schema.nodes.link, attrs);
|
|
240
|
+
if (wrapping) {
|
|
241
|
+
tr.wrap(range, wrapping);
|
|
244
242
|
}
|
|
245
243
|
else {
|
|
246
|
-
tr.insert(state.selection.anchor, schema.nodes.link.create());
|
|
244
|
+
tr.insert(state.selection.anchor, state.schema.nodes.link.create(attrs, contents));
|
|
247
245
|
}
|
|
248
246
|
if (dispatch) {
|
|
249
247
|
const selection = NodeSelection.create(tr.doc, state.tr.selection.from);
|
|
@@ -83,6 +83,15 @@ export const AuthorsModal = ({ authors: $authors, affiliations: $affiliations, a
|
|
|
83
83
|
setSelection(author);
|
|
84
84
|
}
|
|
85
85
|
};
|
|
86
|
+
const handleClose = () => {
|
|
87
|
+
const values = valuesRef.current;
|
|
88
|
+
if (values && selection && !isEqual(values, normalize(selection))) {
|
|
89
|
+
setShowConfirmationDialog(true);
|
|
90
|
+
}
|
|
91
|
+
else {
|
|
92
|
+
setOpen(false);
|
|
93
|
+
}
|
|
94
|
+
};
|
|
86
95
|
const handleSaveAuthor = (values) => {
|
|
87
96
|
if (!values || !selection) {
|
|
88
97
|
return;
|
|
@@ -173,10 +182,10 @@ export const AuthorsModal = ({ authors: $authors, affiliations: $affiliations, a
|
|
|
173
182
|
const handleChangeAuthor = (values) => {
|
|
174
183
|
valuesRef.current = values;
|
|
175
184
|
};
|
|
176
|
-
return (React.createElement(StyledModal, { isOpen: isOpen, onRequestClose: () =>
|
|
185
|
+
return (React.createElement(StyledModal, { isOpen: isOpen, onRequestClose: () => handleClose(), shouldCloseOnOverlayClick: true },
|
|
177
186
|
React.createElement(ModalContainer, null,
|
|
178
187
|
React.createElement(ModalHeader, null,
|
|
179
|
-
React.createElement(CloseButton, { onClick: () =>
|
|
188
|
+
React.createElement(CloseButton, { onClick: () => handleClose(), "data-cy": "modal-close-button" })),
|
|
180
189
|
React.createElement(ModalBody, null,
|
|
181
190
|
React.createElement(ModalSidebar, { "data-cy": "authors-sidebar" },
|
|
182
191
|
React.createElement(ModalSidebarHeader, null,
|
|
@@ -17,6 +17,41 @@ import { PrimaryButton, SecondaryButton, TextField, } from '@manuscripts/style-g
|
|
|
17
17
|
import React, { useCallback, useState } from 'react';
|
|
18
18
|
import styled from 'styled-components';
|
|
19
19
|
import { allowedHref } from '../../lib/url';
|
|
20
|
+
export const LinkForm = ({ handleCancel, handleRemove, handleSave, value }) => {
|
|
21
|
+
const [href, setHref] = useState(value.href);
|
|
22
|
+
const [text, setText] = useState(value.text);
|
|
23
|
+
const [title, setTitle] = useState(value.title || '');
|
|
24
|
+
const handleSubmit = useCallback((event) => {
|
|
25
|
+
event.preventDefault();
|
|
26
|
+
handleSave({ href, text, title });
|
|
27
|
+
}, [href, text, title, handleSave]);
|
|
28
|
+
return (React.createElement(Form, { onSubmit: handleSubmit },
|
|
29
|
+
React.createElement(Field, null,
|
|
30
|
+
React.createElement(FieldHeading, null,
|
|
31
|
+
React.createElement(Label, null, "URL"),
|
|
32
|
+
href && allowedHref(href) && (React.createElement(Open, { href: href, target: '_blank', rel: 'noopener' }))),
|
|
33
|
+
React.createElement(TextField, { type: 'url', name: 'href', value: href, autoComplete: 'off', autoFocus: true, required: true, onChange: (event) => {
|
|
34
|
+
setHref(event.target.value);
|
|
35
|
+
} })),
|
|
36
|
+
React.createElement(Field, null,
|
|
37
|
+
React.createElement(FieldHeading, null,
|
|
38
|
+
React.createElement(Label, null, "Text")),
|
|
39
|
+
React.createElement(TextField, { type: 'text', name: 'text', value: text, autoComplete: 'off', required: true, onChange: (event) => {
|
|
40
|
+
setText(event.target.value);
|
|
41
|
+
} })),
|
|
42
|
+
React.createElement(Field, null,
|
|
43
|
+
React.createElement(FieldHeading, null,
|
|
44
|
+
React.createElement(Label, null, "Title (optional)")),
|
|
45
|
+
React.createElement(TextField, { type: 'text', name: 'title', value: title, autoComplete: 'off', required: false, onChange: (event) => {
|
|
46
|
+
setTitle(event.target.value);
|
|
47
|
+
} })),
|
|
48
|
+
React.createElement(Actions, null,
|
|
49
|
+
React.createElement(ActionGroup, null,
|
|
50
|
+
React.createElement(SecondaryButton, { type: 'button', mini: true, onClick: handleRemove }, "Remove Link")),
|
|
51
|
+
React.createElement(ActionGroup, null,
|
|
52
|
+
React.createElement(SecondaryButton, { type: 'button', onClick: handleCancel }, "Cancel"),
|
|
53
|
+
React.createElement(PrimaryButton, { type: 'submit' }, "Save")))));
|
|
54
|
+
};
|
|
20
55
|
const Form = styled.form `
|
|
21
56
|
padding: 16px;
|
|
22
57
|
`;
|
|
@@ -62,32 +97,3 @@ const Open = styled.a `
|
|
|
62
97
|
margin-left: 4px;
|
|
63
98
|
}
|
|
64
99
|
`;
|
|
65
|
-
export const LinkForm = ({ onCancel, onRemove, onSave, value, }) => {
|
|
66
|
-
const [href, setHref] = useState(value.href);
|
|
67
|
-
const [text, setText] = useState(value.text);
|
|
68
|
-
const [title, setTitle] = useState(value.title || '');
|
|
69
|
-
const handleSubmit = useCallback((event) => {
|
|
70
|
-
event.preventDefault();
|
|
71
|
-
onSave({ href, text, title });
|
|
72
|
-
}, [href, text, title, onSave]);
|
|
73
|
-
return (React.createElement(Form, { onSubmit: handleSubmit },
|
|
74
|
-
React.createElement(Field, null,
|
|
75
|
-
React.createElement(FieldHeading, null,
|
|
76
|
-
React.createElement(Label, null, "URL"),
|
|
77
|
-
href && allowedHref(href) && (React.createElement(Open, { href: href, target: '_blank', rel: 'noopener' }))),
|
|
78
|
-
React.createElement(TextField, { type: 'url', name: 'href', value: href, autoComplete: 'off', autoFocus: true, required: true, onChange: (e) => setHref(e.target.value) })),
|
|
79
|
-
React.createElement(Field, null,
|
|
80
|
-
React.createElement(FieldHeading, null,
|
|
81
|
-
React.createElement(Label, null, "Text")),
|
|
82
|
-
React.createElement(TextField, { type: 'text', name: 'text', value: text, autoComplete: 'off', required: true, onChange: (e) => setText(e.target.value) })),
|
|
83
|
-
React.createElement(Field, null,
|
|
84
|
-
React.createElement(FieldHeading, null,
|
|
85
|
-
React.createElement(Label, null, "Title (optional)")),
|
|
86
|
-
React.createElement(TextField, { type: 'text', name: 'title', value: title, autoComplete: 'off', required: false, onChange: (e) => setTitle(e.target.value) })),
|
|
87
|
-
React.createElement(Actions, null,
|
|
88
|
-
React.createElement(ActionGroup, null,
|
|
89
|
-
React.createElement(SecondaryButton, { type: 'button', mini: true, onClick: onRemove }, "Remove Link")),
|
|
90
|
-
React.createElement(ActionGroup, null,
|
|
91
|
-
React.createElement(SecondaryButton, { type: 'button', onClick: onCancel }, "Cancel"),
|
|
92
|
-
React.createElement(PrimaryButton, { type: 'submit' }, "Save")))));
|
|
93
|
-
};
|
package/dist/es/views/link.js
CHANGED
|
@@ -13,8 +13,43 @@
|
|
|
13
13
|
* See the License for the specific language governing permissions and
|
|
14
14
|
* limitations under the License.
|
|
15
15
|
*/
|
|
16
|
+
import { isRejectedInsert } from '../lib/track-changes-utils';
|
|
17
|
+
import { allowedHref } from '../lib/url';
|
|
16
18
|
import { BaseNodeView } from './base_node_view';
|
|
17
19
|
import { createNodeView } from './creators';
|
|
18
20
|
export class LinkView extends BaseNodeView {
|
|
21
|
+
constructor() {
|
|
22
|
+
super(...arguments);
|
|
23
|
+
this.initialise = () => {
|
|
24
|
+
this.createDOM();
|
|
25
|
+
this.updateContents();
|
|
26
|
+
};
|
|
27
|
+
this.updateContents = () => {
|
|
28
|
+
var _a, _b, _c;
|
|
29
|
+
const linkText = ((_c = (_b = (_a = this.node) === null || _a === void 0 ? void 0 : _a.content) === null || _b === void 0 ? void 0 : _b.firstChild) === null || _c === void 0 ? void 0 : _c.text) || '';
|
|
30
|
+
if (!isRejectedInsert(this.node)) {
|
|
31
|
+
const { href, title } = this.node.attrs;
|
|
32
|
+
const linkElement = document.createElement('a');
|
|
33
|
+
linkElement.classList.add('link');
|
|
34
|
+
linkElement.style.position = 'relative';
|
|
35
|
+
if (href && allowedHref(href)) {
|
|
36
|
+
linkElement.setAttribute('href', href);
|
|
37
|
+
}
|
|
38
|
+
if (title) {
|
|
39
|
+
linkElement.setAttribute('title', title);
|
|
40
|
+
}
|
|
41
|
+
linkElement.innerHTML = linkText;
|
|
42
|
+
this.dom.innerHTML = '';
|
|
43
|
+
this.dom.appendChild(linkElement);
|
|
44
|
+
}
|
|
45
|
+
else {
|
|
46
|
+
this.dom.innerHTML = linkText;
|
|
47
|
+
}
|
|
48
|
+
};
|
|
49
|
+
this.createDOM = () => {
|
|
50
|
+
this.dom = document.createElement('span');
|
|
51
|
+
this.contentDOM = this.dom;
|
|
52
|
+
};
|
|
53
|
+
}
|
|
19
54
|
}
|
|
20
55
|
export default createNodeView(LinkView);
|
|
@@ -13,119 +13,76 @@
|
|
|
13
13
|
* See the License for the specific language governing permissions and
|
|
14
14
|
* limitations under the License.
|
|
15
15
|
*/
|
|
16
|
-
import { schema } from '@manuscripts/transform';
|
|
17
16
|
import { TextSelection } from 'prosemirror-state';
|
|
18
|
-
import { LinkForm
|
|
19
|
-
import { getActualAttrs, getChangeClasses, isDeleted, isRejectedInsert, } from '../lib/track-changes-utils';
|
|
20
|
-
import { allowedHref } from '../lib/url';
|
|
17
|
+
import { LinkForm } from '../components/views/LinkForm';
|
|
21
18
|
import { createEditableNodeView } from './creators';
|
|
22
19
|
import { LinkView } from './link';
|
|
23
20
|
import ReactSubView from './ReactSubView';
|
|
24
21
|
export class LinkEditableView extends LinkView {
|
|
25
22
|
constructor() {
|
|
26
23
|
super(...arguments);
|
|
27
|
-
this.ignoreMutation = () => true;
|
|
28
|
-
this.initialise = () => {
|
|
29
|
-
this.createDOM();
|
|
30
|
-
this.updateContents();
|
|
31
|
-
};
|
|
32
|
-
this.updateContents = () => {
|
|
33
|
-
if (isRejectedInsert(this.node)) {
|
|
34
|
-
this.dom.innerHTML = '';
|
|
35
|
-
this.contentDOM = undefined;
|
|
36
|
-
return;
|
|
37
|
-
}
|
|
38
|
-
this.contentDOM = this.dom;
|
|
39
|
-
const attrs = getActualAttrs(this.node);
|
|
40
|
-
const href = attrs.href;
|
|
41
|
-
const title = attrs.title;
|
|
42
|
-
const classes = ['link', ...getChangeClasses(this.node.attrs.dataTracked)];
|
|
43
|
-
this.dom.className = classes.join(' ');
|
|
44
|
-
this.dom.setAttribute('href', allowedHref(href) ? href : '');
|
|
45
|
-
this.dom.setAttribute('target', '_blank');
|
|
46
|
-
this.dom.setAttribute('title', title || '');
|
|
47
|
-
};
|
|
48
|
-
this.createDOM = () => {
|
|
49
|
-
this.dom = document.createElement('a');
|
|
50
|
-
this.dom.addEventListener('click', this.handleClick);
|
|
51
|
-
};
|
|
52
24
|
this.selectNode = () => {
|
|
53
|
-
|
|
54
|
-
this.showForm();
|
|
55
|
-
}
|
|
25
|
+
this.showForm();
|
|
56
26
|
};
|
|
57
27
|
this.destroy = () => {
|
|
58
28
|
this.closeForm();
|
|
59
29
|
};
|
|
60
30
|
this.deselectNode = () => {
|
|
61
|
-
const attrs = getActualAttrs(this.node);
|
|
62
|
-
if (!this.node.content.size || !attrs.href) {
|
|
63
|
-
this.removeLink();
|
|
64
|
-
}
|
|
65
31
|
this.closeForm();
|
|
66
32
|
};
|
|
67
|
-
this.showForm = () => {
|
|
33
|
+
this.showForm = (event) => {
|
|
34
|
+
if (event) {
|
|
35
|
+
event.preventDefault();
|
|
36
|
+
}
|
|
68
37
|
if (!this.props.getCapabilities().editArticle) {
|
|
69
38
|
return;
|
|
70
39
|
}
|
|
71
|
-
const
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
title: attrs.title,
|
|
40
|
+
const originalValue = {
|
|
41
|
+
href: this.node.attrs.href,
|
|
42
|
+
title: this.node.attrs.title,
|
|
75
43
|
text: this.node.textContent,
|
|
76
44
|
};
|
|
77
45
|
const componentProps = {
|
|
78
|
-
value,
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
46
|
+
value: originalValue,
|
|
47
|
+
handleCancel: this.handleCancel,
|
|
48
|
+
handleRemove: this.handleRemove,
|
|
49
|
+
handleSave: this.handleSave,
|
|
82
50
|
};
|
|
83
51
|
this.popperContainer = ReactSubView(this.props, LinkForm, componentProps, this.node, this.getPos, this.view, 'link-editor');
|
|
84
52
|
this.props.popper.show(this.dom, this.popperContainer, 'bottom');
|
|
85
53
|
};
|
|
86
|
-
this.handleClick = (e) => {
|
|
87
|
-
if (this.props.getCapabilities().editArticle) {
|
|
88
|
-
e.preventDefault();
|
|
89
|
-
}
|
|
90
|
-
};
|
|
91
54
|
this.handleCancel = () => {
|
|
92
|
-
const
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
55
|
+
const tr = this.view.state.tr;
|
|
56
|
+
const pos = this.getPos();
|
|
57
|
+
tr.setSelection(TextSelection.create(tr.doc, pos));
|
|
58
|
+
this.view.focus();
|
|
59
|
+
this.view.dispatch(tr);
|
|
96
60
|
this.closeForm();
|
|
97
61
|
};
|
|
98
62
|
this.handleRemove = () => {
|
|
99
|
-
this.
|
|
63
|
+
const tr = this.view.state.tr;
|
|
64
|
+
const pos = this.getPos();
|
|
65
|
+
const to = pos + this.node.nodeSize;
|
|
66
|
+
tr.replaceWith(pos, to, this.node.content).setSelection(TextSelection.create(tr.doc, pos));
|
|
67
|
+
this.view.focus();
|
|
68
|
+
this.view.dispatch(tr);
|
|
100
69
|
this.closeForm();
|
|
101
70
|
};
|
|
102
71
|
this.handleSave = (value) => {
|
|
103
72
|
const tr = this.view.state.tr;
|
|
104
|
-
const
|
|
73
|
+
const link = this.node;
|
|
105
74
|
const pos = this.getPos();
|
|
106
|
-
if (value.href !== attrs.href || value.title !== attrs.title) {
|
|
75
|
+
if (value.href !== link.attrs.href || value.title !== link.attrs.title) {
|
|
107
76
|
tr.setNodeMarkup(pos, undefined, Object.assign(Object.assign({}, this.node.attrs), { href: value.href, title: value.title }));
|
|
108
77
|
}
|
|
109
|
-
if (value.text !==
|
|
110
|
-
tr.
|
|
111
|
-
tr.insert(pos + 1, schema.text(value.text));
|
|
78
|
+
if (value.text !== link.textContent) {
|
|
79
|
+
tr.insertText(value.text, pos + 1, pos + this.node.nodeSize - 1);
|
|
112
80
|
}
|
|
113
81
|
tr.setSelection(TextSelection.create(tr.doc, pos));
|
|
114
82
|
this.view.focus();
|
|
115
83
|
this.view.dispatch(tr);
|
|
116
84
|
this.closeForm();
|
|
117
85
|
};
|
|
118
|
-
this.removeLink = () => {
|
|
119
|
-
const tr = this.view.state.tr;
|
|
120
|
-
const pos = this.getPos();
|
|
121
|
-
tr.delete(pos, pos + this.node.nodeSize);
|
|
122
|
-
const text = this.node.textContent;
|
|
123
|
-
if (text) {
|
|
124
|
-
tr.insert(pos, schema.text(text));
|
|
125
|
-
}
|
|
126
|
-
tr.setSelection(TextSelection.create(tr.doc, pos));
|
|
127
|
-
this.view.dispatch(tr);
|
|
128
|
-
};
|
|
129
86
|
this.closeForm = () => {
|
|
130
87
|
var _a;
|
|
131
88
|
this.props.popper.destroy();
|
|
@@ -19,10 +19,9 @@ export interface LinkValue {
|
|
|
19
19
|
href: string;
|
|
20
20
|
title?: string;
|
|
21
21
|
}
|
|
22
|
-
export
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
22
|
+
export declare const LinkForm: React.FC<{
|
|
23
|
+
handleCancel: () => void;
|
|
24
|
+
handleRemove: () => void;
|
|
25
|
+
handleSave: (value: LinkValue) => void;
|
|
26
26
|
value: LinkValue;
|
|
27
|
-
}
|
|
28
|
-
export declare const LinkForm: React.FC<LinkFormProps>;
|
|
27
|
+
}>;
|
|
@@ -16,6 +16,9 @@
|
|
|
16
16
|
import { ManuscriptNodeView } from '@manuscripts/transform';
|
|
17
17
|
import { BaseNodeProps, BaseNodeView } from './base_node_view';
|
|
18
18
|
export declare class LinkView<PropsType extends BaseNodeProps> extends BaseNodeView<PropsType> implements ManuscriptNodeView {
|
|
19
|
+
initialise: () => void;
|
|
20
|
+
updateContents: () => void;
|
|
21
|
+
protected createDOM: () => void;
|
|
19
22
|
}
|
|
20
23
|
declare const _default: (props: BaseNodeProps, dispatch?: import("..").Dispatch | undefined) => import("../types").NodeViewCreator<LinkView<any>>;
|
|
21
24
|
export default _default;
|
|
@@ -17,19 +17,13 @@ import { EditableBlockProps } from './editable_block';
|
|
|
17
17
|
import { LinkView } from './link';
|
|
18
18
|
export declare class LinkEditableView extends LinkView<EditableBlockProps> {
|
|
19
19
|
protected popperContainer: HTMLDivElement;
|
|
20
|
-
ignoreMutation: () => boolean;
|
|
21
|
-
initialise: () => void;
|
|
22
|
-
updateContents: () => void;
|
|
23
|
-
protected createDOM: () => void;
|
|
24
20
|
selectNode: () => void;
|
|
25
21
|
destroy: () => void;
|
|
26
22
|
deselectNode: () => void;
|
|
27
23
|
private showForm;
|
|
28
|
-
private handleClick;
|
|
29
24
|
private handleCancel;
|
|
30
25
|
private handleRemove;
|
|
31
26
|
private handleSave;
|
|
32
|
-
private removeLink;
|
|
33
27
|
private closeForm;
|
|
34
28
|
}
|
|
35
29
|
declare const _default: (props: EditableBlockProps, dispatch?: import("..").Dispatch | undefined) => import("../types").NodeViewCreator<LinkEditableView>;
|
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": "1.7.39
|
|
4
|
+
"version": "1.7.39",
|
|
5
5
|
"repository": "github:Atypon-OpenSource/manuscripts-body-editor",
|
|
6
6
|
"license": "Apache-2.0",
|
|
7
7
|
"main": "dist/cjs",
|
|
@@ -31,9 +31,9 @@
|
|
|
31
31
|
"@manuscripts/assets": "^0.6.4",
|
|
32
32
|
"@manuscripts/json-schema": "^2.2.7",
|
|
33
33
|
"@manuscripts/library": "^1.3.6",
|
|
34
|
-
"@manuscripts/style-guide": "1.8.
|
|
34
|
+
"@manuscripts/style-guide": "1.8.7",
|
|
35
35
|
"@manuscripts/track-changes-plugin": "1.7.9",
|
|
36
|
-
"@manuscripts/transform": "2.1.
|
|
36
|
+
"@manuscripts/transform": "2.1.13",
|
|
37
37
|
"astrocite-eutils": "^0.16.4",
|
|
38
38
|
"axios": "^1.6.7",
|
|
39
39
|
"mathjax-full": "^3.2.2",
|