@manuscripts/body-editor 3.9.11 → 3.9.13
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 +5 -2
- package/dist/cjs/components/keywords/AddKeywordInline.js +12 -1
- package/dist/cjs/components/views/FigureDropdown.js +65 -6
- package/dist/cjs/configs/ManuscriptsEditor.js +1 -1
- package/dist/cjs/index.js +1 -0
- package/dist/cjs/keys/misc.js +2 -1
- package/dist/cjs/keys/title.js +0 -38
- package/dist/cjs/lib/comments.js +1 -0
- package/dist/cjs/lib/context-menu.js +74 -8
- package/dist/cjs/lib/media.js +27 -3
- package/dist/cjs/lib/navigation-utils.js +132 -0
- package/dist/cjs/lib/popper.js +25 -1
- package/dist/cjs/lib/position-menu.js +3 -0
- package/dist/cjs/lib/utils.js +7 -2
- package/dist/cjs/plugins/accessibility_element.js +10 -2
- package/dist/cjs/plugins/add-subtitle.js +8 -2
- package/dist/cjs/plugins/alt-titles.js +6 -1
- package/dist/cjs/plugins/comments.js +27 -15
- package/dist/cjs/plugins/persistent-cursor.js +4 -6
- package/dist/cjs/plugins/section_category.js +42 -9
- package/dist/cjs/plugins/translations.js +49 -13
- package/dist/cjs/versions.js +1 -1
- package/dist/cjs/views/accessibility_element.js +30 -0
- package/dist/cjs/views/alt_title.js +29 -0
- package/dist/cjs/views/alt_titles_section.js +9 -1
- package/dist/cjs/views/attachment.js +1 -1
- package/dist/cjs/views/bibliography_element.js +39 -17
- package/dist/cjs/views/citation.js +1 -0
- package/dist/cjs/views/citation_editable.js +4 -2
- package/dist/cjs/views/contributors.js +23 -2
- package/dist/cjs/views/cross_reference.js +3 -0
- package/dist/cjs/views/editable_block.js +37 -3
- package/dist/cjs/views/embed.js +3 -3
- package/dist/cjs/views/figure_editable.js +1 -1
- package/dist/cjs/views/figure_element.js +3 -0
- package/dist/cjs/views/footnote.js +3 -0
- package/dist/cjs/views/hero_image.js +4 -1
- package/dist/cjs/views/image_element.js +15 -7
- package/dist/cjs/views/inline_footnote.js +3 -0
- package/dist/cjs/views/keyword.js +15 -0
- package/dist/cjs/views/keyword_group.js +38 -0
- package/dist/cjs/views/quote_image_editable.js +1 -0
- package/dist/cjs/views/supplements.js +4 -1
- package/dist/es/commands.js +5 -2
- package/dist/es/components/keywords/AddKeywordInline.js +12 -1
- package/dist/es/components/views/FigureDropdown.js +66 -7
- package/dist/es/configs/ManuscriptsEditor.js +1 -1
- package/dist/es/index.js +1 -0
- package/dist/es/keys/misc.js +2 -1
- package/dist/es/keys/title.js +1 -39
- package/dist/es/lib/comments.js +1 -0
- package/dist/es/lib/context-menu.js +74 -8
- package/dist/es/lib/media.js +27 -3
- package/dist/es/lib/navigation-utils.js +122 -0
- package/dist/es/lib/popper.js +25 -1
- package/dist/es/lib/position-menu.js +3 -0
- package/dist/es/lib/utils.js +7 -2
- package/dist/es/plugins/accessibility_element.js +10 -2
- package/dist/es/plugins/add-subtitle.js +8 -2
- package/dist/es/plugins/alt-titles.js +6 -1
- package/dist/es/plugins/comments.js +27 -15
- package/dist/es/plugins/persistent-cursor.js +4 -6
- package/dist/es/plugins/section_category.js +42 -9
- package/dist/es/plugins/translations.js +49 -13
- package/dist/es/versions.js +1 -1
- package/dist/es/views/accessibility_element.js +30 -0
- package/dist/es/views/alt_title.js +29 -0
- package/dist/es/views/alt_titles_section.js +9 -1
- package/dist/es/views/attachment.js +1 -1
- package/dist/es/views/bibliography_element.js +39 -17
- package/dist/es/views/citation.js +1 -0
- package/dist/es/views/citation_editable.js +4 -2
- package/dist/es/views/contributors.js +23 -2
- package/dist/es/views/cross_reference.js +3 -0
- package/dist/es/views/editable_block.js +37 -3
- package/dist/es/views/embed.js +3 -3
- package/dist/es/views/figure_editable.js +1 -1
- package/dist/es/views/figure_element.js +3 -0
- package/dist/es/views/footnote.js +3 -0
- package/dist/es/views/hero_image.js +4 -1
- package/dist/es/views/image_element.js +15 -7
- package/dist/es/views/inline_footnote.js +3 -0
- package/dist/es/views/keyword.js +15 -0
- package/dist/es/views/keyword_group.js +38 -0
- package/dist/es/views/quote_image_editable.js +1 -0
- package/dist/es/views/supplements.js +4 -1
- package/dist/types/configs/ManuscriptsEditor.d.ts +1 -1
- package/dist/types/index.d.ts +1 -0
- package/dist/types/lib/context-menu.d.ts +1 -0
- package/dist/types/lib/media.d.ts +1 -1
- package/dist/types/lib/navigation-utils.d.ts +45 -0
- package/dist/types/lib/popper.d.ts +3 -0
- package/dist/types/lib/utils.d.ts +1 -1
- package/dist/types/versions.d.ts +1 -1
- package/dist/types/views/accessibility_element.d.ts +2 -0
- package/dist/types/views/alt_title.d.ts +2 -0
- package/dist/types/views/bibliography_element.d.ts +3 -0
- package/dist/types/views/citation_editable.d.ts +1 -1
- package/dist/types/views/contributors.d.ts +3 -1
- package/dist/types/views/keyword.d.ts +1 -0
- package/dist/types/views/keyword_group.d.ts +4 -0
- package/package.json +4 -4
- package/styles/AdvancedEditor.css +116 -10
- package/styles/Editor.css +61 -6
- package/styles/popper.css +3 -1
|
@@ -19,6 +19,7 @@ import { NodeSelection } from 'prosemirror-state';
|
|
|
19
19
|
import { AuthorsModal, } from '../components/authors/AuthorsModal';
|
|
20
20
|
import { authorComparator, authorLabel, } from '../lib/authors';
|
|
21
21
|
import { handleComment } from '../lib/comments';
|
|
22
|
+
import { createKeyboardInteraction } from '../lib/navigation-utils';
|
|
22
23
|
import { addTrackChangesAttributes, isDeleted, } from '../lib/track-changes-utils';
|
|
23
24
|
import { findInsertionPosition } from '../lib/utils';
|
|
24
25
|
import { deleteNode, findChildByID, findChildByType, findChildrenAttrsByType, updateNodeAttrs, } from '../lib/view';
|
|
@@ -45,11 +46,26 @@ export class ContributorsView extends BlockView {
|
|
|
45
46
|
const can = this.props.getCapabilities();
|
|
46
47
|
if (can.editMetadata) {
|
|
47
48
|
wrapper.addEventListener('click', this.handleClick);
|
|
49
|
+
this.removeKeydownListener = createKeyboardInteraction({
|
|
50
|
+
container: wrapper,
|
|
51
|
+
navigation: {
|
|
52
|
+
getItems: () => {
|
|
53
|
+
return Array.from(wrapper.querySelectorAll('.contributor'));
|
|
54
|
+
},
|
|
55
|
+
arrowKeys: { forward: 'ArrowRight', backward: 'ArrowLeft' },
|
|
56
|
+
},
|
|
57
|
+
additionalKeys: {
|
|
58
|
+
Enter: (e) => {
|
|
59
|
+
e.preventDefault();
|
|
60
|
+
this.handleClick(e);
|
|
61
|
+
},
|
|
62
|
+
},
|
|
63
|
+
});
|
|
48
64
|
}
|
|
49
65
|
const authors = affs.contributors;
|
|
50
66
|
authors.sort(authorComparator).forEach((author, i) => {
|
|
51
67
|
const jointAuthors = this.isJointFirstAuthor(authors, i);
|
|
52
|
-
wrapper.appendChild(this.buildAuthor(author, jointAuthors));
|
|
68
|
+
wrapper.appendChild(this.buildAuthor(author, jointAuthors, i));
|
|
53
69
|
if (i !== authors.length - 1) {
|
|
54
70
|
const separator = document.createElement('span');
|
|
55
71
|
separator.classList.add('separator');
|
|
@@ -59,13 +75,14 @@ export class ContributorsView extends BlockView {
|
|
|
59
75
|
});
|
|
60
76
|
this.container.appendChild(wrapper);
|
|
61
77
|
};
|
|
62
|
-
this.buildAuthor = (attrs, isJointFirstAuthor) => {
|
|
78
|
+
this.buildAuthor = (attrs, isJointFirstAuthor, index) => {
|
|
63
79
|
const state = this.view.state;
|
|
64
80
|
const affs = affiliationsKey.getState(state)?.indexedAffiliationIds;
|
|
65
81
|
const container = document.createElement('span');
|
|
66
82
|
container.classList.add('contributor');
|
|
67
83
|
container.setAttribute('id', attrs.id);
|
|
68
84
|
container.setAttribute('contenteditable', 'false');
|
|
85
|
+
container.tabIndex = index === 0 ? 0 : -1;
|
|
69
86
|
addTrackChangesAttributes(attrs, container);
|
|
70
87
|
const name = authorLabel(attrs);
|
|
71
88
|
container.innerHTML =
|
|
@@ -269,5 +286,9 @@ export class ContributorsView extends BlockView {
|
|
|
269
286
|
note.classList.add('contributor-note');
|
|
270
287
|
return note;
|
|
271
288
|
}
|
|
289
|
+
destroy() {
|
|
290
|
+
this.removeKeydownListener?.();
|
|
291
|
+
super.destroy();
|
|
292
|
+
}
|
|
272
293
|
}
|
|
273
294
|
export default createNodeView(ContributorsView);
|
|
@@ -13,6 +13,7 @@
|
|
|
13
13
|
* See the License for the specific language governing permissions and
|
|
14
14
|
* limitations under the License.
|
|
15
15
|
*/
|
|
16
|
+
import { handleEnterKey } from '../lib/navigation-utils';
|
|
16
17
|
import { objectsKey } from '../plugins/objects';
|
|
17
18
|
import { BaseNodeView } from './base_node_view';
|
|
18
19
|
import { createNodeView } from './creators';
|
|
@@ -37,6 +38,8 @@ export class CrossReferenceView extends BaseNodeView {
|
|
|
37
38
|
this.createDOM = () => {
|
|
38
39
|
this.dom = document.createElement('span');
|
|
39
40
|
this.dom.className = 'cross-reference';
|
|
41
|
+
this.dom.tabIndex = 0;
|
|
42
|
+
this.dom.addEventListener('keydown', handleEnterKey(() => this.handleClick()));
|
|
40
43
|
};
|
|
41
44
|
}
|
|
42
45
|
updateContents() {
|
|
@@ -16,6 +16,7 @@
|
|
|
16
16
|
import { schema } from '@manuscripts/transform';
|
|
17
17
|
import { ContextMenu, contextMenuBtnClass } from '../lib/context-menu';
|
|
18
18
|
import { hasParent, isNotNull } from '../lib/utils';
|
|
19
|
+
import { createKeyboardInteraction } from '../lib/navigation-utils';
|
|
19
20
|
export const EditableBlock = (Base) => {
|
|
20
21
|
return class extends Base {
|
|
21
22
|
constructor() {
|
|
@@ -25,7 +26,12 @@ export const EditableBlock = (Base) => {
|
|
|
25
26
|
};
|
|
26
27
|
}
|
|
27
28
|
gutterButtons() {
|
|
28
|
-
|
|
29
|
+
const buttons = [this.createAddButton(), this.createEditButton()].filter(isNotNull);
|
|
30
|
+
buttons.forEach((btn) => (btn.tabIndex = -1));
|
|
31
|
+
if (buttons.length > 0) {
|
|
32
|
+
buttons[0].tabIndex = 0;
|
|
33
|
+
}
|
|
34
|
+
return buttons;
|
|
29
35
|
}
|
|
30
36
|
actionGutterButtons() {
|
|
31
37
|
return [];
|
|
@@ -53,10 +59,24 @@ export const EditableBlock = (Base) => {
|
|
|
53
59
|
button.setAttribute('role', 'button');
|
|
54
60
|
button.setAttribute('aria-label', `Add an element below`);
|
|
55
61
|
button.setAttribute('data-balloon-pos', 'down-left');
|
|
56
|
-
|
|
62
|
+
const handleClick = (event) => {
|
|
57
63
|
event.preventDefault();
|
|
58
64
|
const menu = this.createMenu();
|
|
59
65
|
menu.showAddMenu(event.currentTarget);
|
|
66
|
+
};
|
|
67
|
+
button.addEventListener('mousedown', handleClick);
|
|
68
|
+
createKeyboardInteraction({
|
|
69
|
+
container: button,
|
|
70
|
+
additionalKeys: {
|
|
71
|
+
Enter: handleClick,
|
|
72
|
+
ArrowRight: () => {
|
|
73
|
+
const parent = button.parentElement;
|
|
74
|
+
const editButton = parent?.querySelector('.edit-block');
|
|
75
|
+
if (editButton) {
|
|
76
|
+
editButton.focus();
|
|
77
|
+
}
|
|
78
|
+
},
|
|
79
|
+
},
|
|
60
80
|
});
|
|
61
81
|
return button;
|
|
62
82
|
}
|
|
@@ -69,10 +89,24 @@ export const EditableBlock = (Base) => {
|
|
|
69
89
|
button.setAttribute('role', 'button');
|
|
70
90
|
button.setAttribute('aria-label', 'Open menu');
|
|
71
91
|
button.setAttribute('data-balloon-pos', 'down-left');
|
|
72
|
-
|
|
92
|
+
const handleClick = (event) => {
|
|
73
93
|
event.preventDefault();
|
|
74
94
|
const menu = this.createMenu();
|
|
75
95
|
menu.showEditMenu(event.currentTarget);
|
|
96
|
+
};
|
|
97
|
+
button.addEventListener('mousedown', handleClick);
|
|
98
|
+
createKeyboardInteraction({
|
|
99
|
+
container: button,
|
|
100
|
+
additionalKeys: {
|
|
101
|
+
Enter: handleClick,
|
|
102
|
+
ArrowLeft: () => {
|
|
103
|
+
const parent = button.parentElement;
|
|
104
|
+
const addButton = parent?.querySelector('.add-block');
|
|
105
|
+
if (addButton) {
|
|
106
|
+
addButton.focus();
|
|
107
|
+
}
|
|
108
|
+
},
|
|
109
|
+
},
|
|
76
110
|
});
|
|
77
111
|
return button;
|
|
78
112
|
}
|
package/dist/es/views/embed.js
CHANGED
|
@@ -158,7 +158,7 @@ export class EmbedView extends BlockView {
|
|
|
158
158
|
const href = this.node.attrs.href;
|
|
159
159
|
let object;
|
|
160
160
|
if (!href) {
|
|
161
|
-
object = createMediaPlaceholder(MediaType.Media, this.view, this.getPos);
|
|
161
|
+
object = createMediaPlaceholder(MediaType.Media, this.view, this.getPos, this.props);
|
|
162
162
|
}
|
|
163
163
|
else if (this.isUploadedFile()) {
|
|
164
164
|
const files = this.props.getFiles();
|
|
@@ -172,14 +172,14 @@ export class EmbedView extends BlockView {
|
|
|
172
172
|
: createUnsupportedFormat(file.name, this.props.getCapabilities().editArticle);
|
|
173
173
|
}
|
|
174
174
|
else {
|
|
175
|
-
object = createMediaPlaceholder(MediaType.Media, this.view, this.getPos);
|
|
175
|
+
object = createMediaPlaceholder(MediaType.Media, this.view, this.getPos, this.props);
|
|
176
176
|
}
|
|
177
177
|
}
|
|
178
178
|
else if (this.isEmbedLink()) {
|
|
179
179
|
object = await this.createEmbedPreview();
|
|
180
180
|
}
|
|
181
181
|
else {
|
|
182
|
-
object = createMediaPlaceholder(MediaType.Media, this.view, this.getPos);
|
|
182
|
+
object = createMediaPlaceholder(MediaType.Media, this.view, this.getPos, this.props);
|
|
183
183
|
}
|
|
184
184
|
const can = this.props.getCapabilities();
|
|
185
185
|
if (can.uploadFile && object.classList.contains('placeholder')) {
|
|
@@ -49,7 +49,7 @@ export class FigureEditableView extends FigureView {
|
|
|
49
49
|
return img;
|
|
50
50
|
};
|
|
51
51
|
this.createPlaceholder = () => {
|
|
52
|
-
return createMediaPlaceholder(MediaType.Figure);
|
|
52
|
+
return createMediaPlaceholder(MediaType.Figure, this.view, this.getPos, this.props);
|
|
53
53
|
};
|
|
54
54
|
}
|
|
55
55
|
initialise() {
|
|
@@ -16,6 +16,7 @@
|
|
|
16
16
|
import { schema } from '@manuscripts/transform';
|
|
17
17
|
import { TextSelection } from 'prosemirror-state';
|
|
18
18
|
import { addAuthorIcon } from '../icons';
|
|
19
|
+
import { handleEnterKey } from '../lib/navigation-utils';
|
|
19
20
|
import { createNodeView } from './creators';
|
|
20
21
|
import { ImageElementView } from './image_element';
|
|
21
22
|
export class FigureElementView extends ImageElementView {
|
|
@@ -71,6 +72,8 @@ export class FigureElementView extends ImageElementView {
|
|
|
71
72
|
title: 'Add figure',
|
|
72
73
|
});
|
|
73
74
|
this.addFigureBtn.addEventListener('click', () => this.addFigure());
|
|
75
|
+
this.addFigureBtn.addEventListener('keydown', handleEnterKey(() => this.addFigure()));
|
|
76
|
+
this.addFigureBtn.tabIndex = 0;
|
|
74
77
|
this.container.prepend(this.addFigureBtn);
|
|
75
78
|
}
|
|
76
79
|
}
|
|
@@ -25,15 +25,18 @@ import { isDeleted, isPendingInsert } from '../lib/track-changes-utils';
|
|
|
25
25
|
import { BaseNodeView } from './base_node_view';
|
|
26
26
|
import { createNodeView } from './creators';
|
|
27
27
|
import ReactSubView from './ReactSubView';
|
|
28
|
+
import { handleEnterKey } from '../lib/navigation-utils';
|
|
28
29
|
export class FootnoteView extends BaseNodeView {
|
|
29
30
|
constructor() {
|
|
30
31
|
super(...arguments);
|
|
31
32
|
this.initialise = () => {
|
|
32
33
|
this.dom = document.createElement('div');
|
|
33
34
|
this.dom.classList.add('footnote');
|
|
35
|
+
this.dom.tabIndex = 0;
|
|
34
36
|
this.contentDOM = document.createElement('div');
|
|
35
37
|
this.contentDOM.classList.add('footnote-text');
|
|
36
38
|
this.dom.addEventListener('mousedown', this.handleClick);
|
|
39
|
+
this.dom.addEventListener('keydown', handleEnterKey(this.handleClick));
|
|
37
40
|
this.updateContents();
|
|
38
41
|
};
|
|
39
42
|
this.handleClick = (event) => {
|
|
@@ -14,6 +14,7 @@
|
|
|
14
14
|
* limitations under the License.
|
|
15
15
|
*/
|
|
16
16
|
import { arrowUp } from '../icons';
|
|
17
|
+
import { handleEnterKey } from '../lib/navigation-utils';
|
|
17
18
|
import BlockView from './block_view';
|
|
18
19
|
import { createNodeView } from './creators';
|
|
19
20
|
export class HeroImageView extends BlockView {
|
|
@@ -42,13 +43,15 @@ export class HeroImageView extends BlockView {
|
|
|
42
43
|
heroImageToggleBtn.classList.add('toggle-btn', 'button-reset');
|
|
43
44
|
heroImageToggleBtn.innerHTML = arrowUp;
|
|
44
45
|
heroImageToggleBtn.classList.toggle('collapsed', this.collapsed);
|
|
45
|
-
|
|
46
|
+
const handleToggle = () => {
|
|
46
47
|
this.collapsed = !this.collapsed;
|
|
47
48
|
if (this.contentDOM) {
|
|
48
49
|
this.contentDOM.style.display = this.collapsed ? 'none' : '';
|
|
49
50
|
}
|
|
50
51
|
heroImageToggleBtn.classList.toggle('collapsed', this.collapsed);
|
|
51
52
|
};
|
|
53
|
+
heroImageToggleBtn.onclick = handleToggle;
|
|
54
|
+
heroImageToggleBtn.addEventListener('keydown', handleEnterKey(handleToggle));
|
|
52
55
|
panel.appendChild(label);
|
|
53
56
|
panel.appendChild(heroImageToggleBtn);
|
|
54
57
|
return panel;
|
|
@@ -17,6 +17,7 @@ import { ContextMenu } from '@manuscripts/style-guide';
|
|
|
17
17
|
import { schema } from '@manuscripts/transform';
|
|
18
18
|
import { deleteIcon, linkIcon } from '../icons';
|
|
19
19
|
import { addInteractionHandlers, createMediaPlaceholder, MediaType, } from '../lib/media';
|
|
20
|
+
import { handleEnterKey } from '../lib/navigation-utils';
|
|
20
21
|
import { createPositionMenuWrapper } from '../lib/position-menu';
|
|
21
22
|
import BlockView from './block_view';
|
|
22
23
|
import { createNodeView } from './creators';
|
|
@@ -194,14 +195,16 @@ export class ImageElementView extends BlockView {
|
|
|
194
195
|
label.innerText = 'Link';
|
|
195
196
|
const container = document.createElement('div');
|
|
196
197
|
container.classList.add('ext-link-editor-placeholder-container');
|
|
197
|
-
const placeholder = createMediaPlaceholder(MediaType.ExternalLink);
|
|
198
|
+
const placeholder = createMediaPlaceholder(MediaType.ExternalLink, this.view, this.getPos, this.props);
|
|
198
199
|
const closeButton = document.createElement('button');
|
|
199
200
|
closeButton.classList.add('close-button');
|
|
200
201
|
closeButton.setAttribute('aria-label', 'Close');
|
|
201
|
-
|
|
202
|
+
const handleClose = () => {
|
|
202
203
|
this.setIsEditingExtLink(false);
|
|
203
204
|
this.updateContents();
|
|
204
|
-
}
|
|
205
|
+
};
|
|
206
|
+
closeButton.addEventListener('click', handleClose);
|
|
207
|
+
closeButton.addEventListener('keydown', handleEnterKey(handleClose));
|
|
205
208
|
container.append(placeholder, closeButton);
|
|
206
209
|
this.extLinkEditorContainer.append(label, container);
|
|
207
210
|
if (can.uploadFile) {
|
|
@@ -216,10 +219,13 @@ export class ImageElementView extends BlockView {
|
|
|
216
219
|
button.appendChild(buttonText);
|
|
217
220
|
button.setAttribute('aria-label', 'Add linked file');
|
|
218
221
|
button.classList.add('icon-button');
|
|
219
|
-
button.
|
|
222
|
+
button.tabIndex = 0;
|
|
223
|
+
const handleAdd = () => {
|
|
220
224
|
this.setIsEditingExtLink(true);
|
|
221
225
|
this.updateContents();
|
|
222
|
-
}
|
|
226
|
+
};
|
|
227
|
+
button.addEventListener('click', handleAdd);
|
|
228
|
+
button.addEventListener('keydown', handleEnterKey(handleAdd));
|
|
223
229
|
this.extLinkEditorContainer.appendChild(button);
|
|
224
230
|
}
|
|
225
231
|
createLinkedFile() {
|
|
@@ -234,10 +240,12 @@ export class ImageElementView extends BlockView {
|
|
|
234
240
|
removeButton.classList.add('icon-button', 'remove-button');
|
|
235
241
|
removeButton.setAttribute('aria-label', 'Remove link');
|
|
236
242
|
removeButton.innerHTML = deleteIcon;
|
|
237
|
-
|
|
243
|
+
const handleRemove = () => {
|
|
238
244
|
this.isEditingExtLink = false;
|
|
239
245
|
this.removeExtLink();
|
|
240
|
-
}
|
|
246
|
+
};
|
|
247
|
+
removeButton.addEventListener('click', handleRemove);
|
|
248
|
+
removeButton.addEventListener('keydown', handleEnterKey(handleRemove));
|
|
241
249
|
div.appendChild(removeButton);
|
|
242
250
|
this.extLinkEditorContainer.appendChild(div);
|
|
243
251
|
}
|
|
@@ -17,6 +17,7 @@ import { ContextMenu } from '@manuscripts/style-guide';
|
|
|
17
17
|
import { NodeSelection, TextSelection } from 'prosemirror-state';
|
|
18
18
|
import { insertFootnotesElement } from '../commands';
|
|
19
19
|
import { FootnotesSelector, } from '../components/views/FootnotesSelector';
|
|
20
|
+
import { handleEnterKey } from '../lib/navigation-utils';
|
|
20
21
|
import { createFootnote, findFootnotesContainerNode, getFootnotesElementState, } from '../lib/footnotes';
|
|
21
22
|
import { isDeleted, isPendingInsert } from '../lib/track-changes-utils';
|
|
22
23
|
import { BaseNodeView } from './base_node_view';
|
|
@@ -102,7 +103,9 @@ export class InlineFootnoteView extends BaseNodeView {
|
|
|
102
103
|
this.initialise = () => {
|
|
103
104
|
this.dom = this.createDOM();
|
|
104
105
|
this.dom.classList.add('footnote-marker');
|
|
106
|
+
this.dom.tabIndex = 0;
|
|
105
107
|
this.dom.addEventListener('click', this.handleClick);
|
|
108
|
+
this.dom.addEventListener('keydown', handleEnterKey(() => this.handleClick()));
|
|
106
109
|
this.updateContents();
|
|
107
110
|
};
|
|
108
111
|
this.selectNode = () => {
|
package/dist/es/views/keyword.js
CHANGED
|
@@ -15,9 +15,11 @@
|
|
|
15
15
|
*/
|
|
16
16
|
import { TextSelection } from 'prosemirror-state';
|
|
17
17
|
import { DeleteKeywordDialog, } from '../components/keywords/DeleteKeywordDialog';
|
|
18
|
+
import { handleEnterKey } from '../lib/navigation-utils';
|
|
18
19
|
import { BaseNodeView } from './base_node_view';
|
|
19
20
|
import { createNodeView } from './creators';
|
|
20
21
|
import ReactSubView from './ReactSubView';
|
|
22
|
+
import { isDeleted } from '../lib/track-changes-utils';
|
|
21
23
|
const deleteIcon = '<svg width="8px" height="8px" viewBox="0 0 26 26" xmlns="http://www.w3.org/2000/svg">\n' +
|
|
22
24
|
' <g stroke="none" stroke-width="1" fill="none" fill-rule="evenodd">\n' +
|
|
23
25
|
' <g fill="#6E6E6E">\n' +
|
|
@@ -36,6 +38,8 @@ export class KeywordView extends BaseNodeView {
|
|
|
36
38
|
this.createDOM = () => {
|
|
37
39
|
this.dom = document.createElement('span');
|
|
38
40
|
this.dom.classList.add('keyword');
|
|
41
|
+
this.dom.tabIndex = this.isFirstKeyword() ? 0 : -1;
|
|
42
|
+
this.dom.addEventListener('keydown', handleEnterKey(() => this.showConfirmationDialog()));
|
|
39
43
|
this.contentDOM = document.createElement('span');
|
|
40
44
|
};
|
|
41
45
|
this.showConfirmationDialog = () => {
|
|
@@ -57,6 +61,17 @@ export class KeywordView extends BaseNodeView {
|
|
|
57
61
|
}
|
|
58
62
|
};
|
|
59
63
|
}
|
|
64
|
+
isFirstKeyword() {
|
|
65
|
+
const pos = this.getPos();
|
|
66
|
+
const parent = this.view.state.doc.resolve(pos).parent;
|
|
67
|
+
for (let i = 0; i < parent.childCount; i++) {
|
|
68
|
+
const child = parent.child(i);
|
|
69
|
+
if (!isDeleted(child)) {
|
|
70
|
+
return child === this.node;
|
|
71
|
+
}
|
|
72
|
+
}
|
|
73
|
+
return false;
|
|
74
|
+
}
|
|
60
75
|
updateContents() {
|
|
61
76
|
super.updateContents();
|
|
62
77
|
this.dom.innerHTML = '';
|
|
@@ -14,6 +14,8 @@
|
|
|
14
14
|
* limitations under the License.
|
|
15
15
|
*/
|
|
16
16
|
import { AddKeywordInline } from '../components/keywords/AddKeywordInline';
|
|
17
|
+
import { createKeyboardInteraction } from '../lib/navigation-utils';
|
|
18
|
+
import { isDeleted } from '../lib/track-changes-utils';
|
|
17
19
|
import BlockView from './block_view';
|
|
18
20
|
import { createNodeView } from './creators';
|
|
19
21
|
import ReactSubView from './ReactSubView';
|
|
@@ -30,6 +32,13 @@ export class KeywordGroupView extends BlockView {
|
|
|
30
32
|
this.contentDOM.setAttribute('id', this.node.attrs.id);
|
|
31
33
|
this.contentDOM.setAttribute('contenteditable', 'false');
|
|
32
34
|
this.element.appendChild(this.contentDOM);
|
|
35
|
+
this.removeKeydownListener = createKeyboardInteraction({
|
|
36
|
+
container: this.element,
|
|
37
|
+
navigation: {
|
|
38
|
+
getItems: () => Array.from(this.element.querySelectorAll('.keyword:not(.deleted), .keyword-add')),
|
|
39
|
+
arrowKeys: { forward: 'ArrowRight', backward: 'ArrowLeft' },
|
|
40
|
+
},
|
|
41
|
+
});
|
|
33
42
|
if (this.props.getCapabilities().editArticle) {
|
|
34
43
|
this.addingTools = ReactSubView(this.props, AddKeywordInline, { getUpdatedNode: () => this.node }, this.node, this.getPos, this.view, ['keywords-editor']);
|
|
35
44
|
}
|
|
@@ -38,5 +47,34 @@ export class KeywordGroupView extends BlockView {
|
|
|
38
47
|
}
|
|
39
48
|
};
|
|
40
49
|
}
|
|
50
|
+
updateContents() {
|
|
51
|
+
super.updateContents();
|
|
52
|
+
this.setKeywordsTabIndices();
|
|
53
|
+
}
|
|
54
|
+
setKeywordsTabIndices() {
|
|
55
|
+
const container = this.contentDOM;
|
|
56
|
+
if (!container) {
|
|
57
|
+
return;
|
|
58
|
+
}
|
|
59
|
+
let firstFocusableFound = false;
|
|
60
|
+
for (let i = 0; i < this.node.childCount; i++) {
|
|
61
|
+
const child = this.node.child(i);
|
|
62
|
+
const keyword = container.querySelector(`.keyword[id="${child.attrs.id}"]`);
|
|
63
|
+
if (!keyword) {
|
|
64
|
+
continue;
|
|
65
|
+
}
|
|
66
|
+
if (!isDeleted(child) && !firstFocusableFound) {
|
|
67
|
+
keyword.tabIndex = 0;
|
|
68
|
+
firstFocusableFound = true;
|
|
69
|
+
}
|
|
70
|
+
else {
|
|
71
|
+
keyword.tabIndex = -1;
|
|
72
|
+
}
|
|
73
|
+
}
|
|
74
|
+
}
|
|
75
|
+
destroy() {
|
|
76
|
+
this.removeKeydownListener?.();
|
|
77
|
+
super.destroy();
|
|
78
|
+
}
|
|
41
79
|
}
|
|
42
80
|
export default createNodeView(KeywordGroupView);
|
|
@@ -23,6 +23,7 @@ export class QuoteImageEditableView extends FigureEditableView {
|
|
|
23
23
|
this.createPlaceholder = () => {
|
|
24
24
|
const element = document.createElement('div');
|
|
25
25
|
element.classList.add('figure', 'placeholder');
|
|
26
|
+
element.tabIndex = 0;
|
|
26
27
|
const instructions = document.createElement('div');
|
|
27
28
|
instructions.classList.add('instructions');
|
|
28
29
|
instructions.innerHTML = `${plusIcon}<div>Drag or click here to upload image</div>`;
|
|
@@ -14,6 +14,7 @@
|
|
|
14
14
|
* limitations under the License.
|
|
15
15
|
*/
|
|
16
16
|
import { arrowUp } from '../icons';
|
|
17
|
+
import { handleEnterKey } from '../lib/navigation-utils';
|
|
17
18
|
import BlockView from './block_view';
|
|
18
19
|
import { createNodeView } from './creators';
|
|
19
20
|
export class SupplementsView extends BlockView {
|
|
@@ -25,11 +26,13 @@ export class SupplementsView extends BlockView {
|
|
|
25
26
|
this.toggleButton = document.createElement('button');
|
|
26
27
|
this.toggleButton.classList.add('supplements-toggle-btn', 'button-reset');
|
|
27
28
|
this.toggleButton.innerHTML = arrowUp;
|
|
28
|
-
|
|
29
|
+
const handleToggle = () => {
|
|
29
30
|
this.collapsed = !this.collapsed;
|
|
30
31
|
this.toggleContent();
|
|
31
32
|
this.toggleButton?.classList.toggle('collapsed', this.collapsed);
|
|
32
33
|
};
|
|
34
|
+
this.toggleButton.onclick = handleToggle;
|
|
35
|
+
this.toggleButton.addEventListener('keydown', handleEnterKey(handleToggle));
|
|
33
36
|
this.contentDOM = document.createElement('div');
|
|
34
37
|
this.contentDOM.classList.add('supplements-content');
|
|
35
38
|
this.contentDOM.classList.add('block');
|
|
@@ -53,7 +53,7 @@ export interface EditorProps {
|
|
|
53
53
|
location: Location;
|
|
54
54
|
isComparingMode?: boolean;
|
|
55
55
|
dispatch?: Dispatch;
|
|
56
|
-
onEditorClick: (
|
|
56
|
+
onEditorClick: (event: Event) => void;
|
|
57
57
|
lockBody: boolean;
|
|
58
58
|
isViewingMode?: boolean;
|
|
59
59
|
hiddenNodeTypes?: ManuscriptNodeType[] | undefined;
|
package/dist/types/index.d.ts
CHANGED
|
@@ -26,6 +26,7 @@ export { CollabProvider } from './classes/collabProvider';
|
|
|
26
26
|
export { PopperManager } from './lib/popper';
|
|
27
27
|
export * from './toolbar';
|
|
28
28
|
export * from './lib/capabilities';
|
|
29
|
+
export * from './lib/navigation-utils';
|
|
29
30
|
export * from './lib/comments';
|
|
30
31
|
export * from './lib/files';
|
|
31
32
|
export * from './lib/footnotes';
|
|
@@ -20,6 +20,7 @@ export declare class ContextMenu {
|
|
|
20
20
|
private readonly node;
|
|
21
21
|
private readonly view;
|
|
22
22
|
private readonly getPos;
|
|
23
|
+
private menuItems;
|
|
23
24
|
constructor(node: ManuscriptNode, view: ManuscriptEditorView, getPos: () => number);
|
|
24
25
|
showAddMenu: (target: Element) => void;
|
|
25
26
|
showEditMenu: (target: Element) => void;
|
|
@@ -23,7 +23,7 @@ export declare enum MediaType {
|
|
|
23
23
|
Figure = "figure",
|
|
24
24
|
ExternalLink = "external_link"
|
|
25
25
|
}
|
|
26
|
-
export declare const createMediaPlaceholder: (mediaType?: MediaType, view?: ManuscriptEditorView, getPos?: () => number) => HTMLElement;
|
|
26
|
+
export declare const createMediaPlaceholder: (mediaType?: MediaType, view?: ManuscriptEditorView, getPos?: () => number, props?: EditorProps) => HTMLElement;
|
|
27
27
|
export interface FileHandlers {
|
|
28
28
|
handleDownload?: () => void;
|
|
29
29
|
handleUpload?: () => void;
|
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
/*!
|
|
2
|
+
* © 2025 Atypon Systems LLC
|
|
3
|
+
*
|
|
4
|
+
* Licensed under the Apache License, Version 2.0 (the "License");
|
|
5
|
+
* you may not use this file except in compliance with the License.
|
|
6
|
+
* You may obtain a copy of the License at
|
|
7
|
+
*
|
|
8
|
+
* http://www.apache.org/licenses/LICENSE-2.0
|
|
9
|
+
*
|
|
10
|
+
* Unless required by applicable law or agreed to in writing, software
|
|
11
|
+
* distributed under the License is distributed on an "AS IS" BASIS,
|
|
12
|
+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
13
|
+
* See the License for the specific language governing permissions and
|
|
14
|
+
* limitations under the License.
|
|
15
|
+
*/
|
|
16
|
+
import { ManuscriptEditorState, ManuscriptEditorView } from '@manuscripts/transform';
|
|
17
|
+
import { EditorView } from 'prosemirror-view';
|
|
18
|
+
import { Dispatch } from '../commands';
|
|
19
|
+
export declare function focusNextElement(elements: Element[] | HTMLElement[], currentIndex: number, direction: 'forward' | 'backward'): void;
|
|
20
|
+
export declare function handleEnterKey(action: (event: KeyboardEvent) => void): (event: KeyboardEvent) => void;
|
|
21
|
+
export declare function handleArrowNavigation(event: KeyboardEvent, elements: HTMLElement[], currentElement: HTMLElement, keys: {
|
|
22
|
+
forward: 'ArrowDown' | 'ArrowRight';
|
|
23
|
+
backward: 'ArrowUp' | 'ArrowLeft';
|
|
24
|
+
}): void;
|
|
25
|
+
type ArrowKey = 'ArrowUp' | 'ArrowDown' | 'ArrowLeft' | 'ArrowRight';
|
|
26
|
+
type SupportedKey = ArrowKey | 'Enter' | 'Escape' | 'Tab';
|
|
27
|
+
type KeyHandlers = Partial<Record<SupportedKey, (event: KeyboardEvent) => void>>;
|
|
28
|
+
type NavigationConfig = {
|
|
29
|
+
getItems: () => HTMLElement[];
|
|
30
|
+
arrowKeys: {
|
|
31
|
+
forward: 'ArrowDown' | 'ArrowRight';
|
|
32
|
+
backward: 'ArrowUp' | 'ArrowLeft';
|
|
33
|
+
};
|
|
34
|
+
getCurrentElement?: (event: KeyboardEvent) => HTMLElement | null;
|
|
35
|
+
};
|
|
36
|
+
export type KeyboardInteractionOptions = {
|
|
37
|
+
container: HTMLElement | Window | Document;
|
|
38
|
+
navigation?: NavigationConfig;
|
|
39
|
+
additionalKeys?: KeyHandlers;
|
|
40
|
+
};
|
|
41
|
+
export declare function createKeyboardInteraction(options: KeyboardInteractionOptions): () => void;
|
|
42
|
+
export declare const focusNearestElement: (state: ManuscriptEditorState, dispatch?: Dispatch, view?: ManuscriptEditorView) => boolean;
|
|
43
|
+
export declare function getCursorContainer(view: EditorView): HTMLElement;
|
|
44
|
+
export declare function findNearestTabbable(container: HTMLElement, verticalPosition: number): HTMLElement | null;
|
|
45
|
+
export {};
|
|
@@ -17,8 +17,11 @@ import { Placement, StrictModifiers } from '@popperjs/core';
|
|
|
17
17
|
export declare class PopperManager {
|
|
18
18
|
private activePopper?;
|
|
19
19
|
private handleDocumentClick?;
|
|
20
|
+
private triggerElement?;
|
|
21
|
+
private container?;
|
|
20
22
|
show(target: Element, contents: HTMLElement, placement?: Placement, showArrow?: boolean, modifiers?: Array<Partial<StrictModifiers>>): void;
|
|
21
23
|
destroy(): void;
|
|
24
|
+
getContainer(): HTMLElement | undefined;
|
|
22
25
|
update(): void;
|
|
23
26
|
isActive: () => boolean;
|
|
24
27
|
private focusInput;
|
|
@@ -34,7 +34,7 @@ export declare const shouldRenderField: (field: string, type: BibliographyItemTy
|
|
|
34
34
|
export declare const cleanItemValues: (item: BibliographyItemAttrs) => BibliographyItemAttrs;
|
|
35
35
|
export declare const isBodyLocked: (state: EditorState) => boolean;
|
|
36
36
|
export declare const isEditAllowed: (state: EditorState) => boolean;
|
|
37
|
-
export declare const createToggleButton: (listener: () => void, what: string) => HTMLButtonElement;
|
|
37
|
+
export declare const createToggleButton: (listener: (event: MouseEvent | KeyboardEvent) => void, what: string) => HTMLButtonElement;
|
|
38
38
|
export declare const getInsertPos: (type: ManuscriptNodeType, parent: ManuscriptNode, pos: number) => number;
|
|
39
39
|
export declare const findInsertionPosition: (type: ManuscriptNodeType, doc: ManuscriptNode) => number;
|
|
40
40
|
export declare const filterBlockNodes: (fragment: Fragment, predicate: (node: ProseMirrorNode) => boolean) => Fragment;
|
package/dist/types/versions.d.ts
CHANGED
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
export declare const VERSION = "3.9.
|
|
1
|
+
export declare const VERSION = "3.9.13";
|
|
2
2
|
export declare const MATHJAX_VERSION = "3.2.2";
|
|
@@ -2,9 +2,11 @@ import { LongDescNode } from '@manuscripts/transform';
|
|
|
2
2
|
import BlockView from './block_view';
|
|
3
3
|
export declare class AccessibilityElementView extends BlockView<LongDescNode> {
|
|
4
4
|
contentDOM: HTMLElement;
|
|
5
|
+
private removeKeydownListener?;
|
|
5
6
|
initialise(): void;
|
|
6
7
|
createDOM(): void;
|
|
7
8
|
createElement(): void;
|
|
9
|
+
destroy(): void;
|
|
8
10
|
}
|
|
9
11
|
declare const _default: (props: import("../configs/ManuscriptsEditor").EditorProps, dispatch?: import("..").Dispatch) => import("../types").NodeViewCreator<AccessibilityElementView>;
|
|
10
12
|
export default _default;
|
|
@@ -17,8 +17,10 @@ import { AltTitleNode, ManuscriptNodeView } from '@manuscripts/transform';
|
|
|
17
17
|
import { BaseNodeView } from './base_node_view';
|
|
18
18
|
export declare class AltTitleView extends BaseNodeView<AltTitleNode> implements ManuscriptNodeView {
|
|
19
19
|
contentDOM: HTMLElement;
|
|
20
|
+
private removeKeydownListener?;
|
|
20
21
|
initialise: () => void;
|
|
21
22
|
protected createDOM: () => void;
|
|
23
|
+
destroy(): void;
|
|
22
24
|
}
|
|
23
25
|
declare const _default: (props: import("../configs/ManuscriptsEditor").EditorProps, dispatch?: import("..").Dispatch) => import("../types").NodeViewCreator<AltTitleView>;
|
|
24
26
|
export default _default;
|
|
@@ -26,7 +26,10 @@ export declare class BibliographyElementBlockView extends BlockView<Trackable<Bi
|
|
|
26
26
|
ignoreMutation: () => boolean;
|
|
27
27
|
private handleEdit;
|
|
28
28
|
private showContextMenu;
|
|
29
|
+
private handleCommentMarkerInteraction;
|
|
30
|
+
private handleBibItemInteraction;
|
|
29
31
|
private handleClick;
|
|
32
|
+
private handleKeyDown;
|
|
30
33
|
updateContents(): void;
|
|
31
34
|
createElement: () => void;
|
|
32
35
|
private handleSave;
|
|
@@ -20,7 +20,7 @@ export declare class CitationEditableView extends CitationView {
|
|
|
20
20
|
private can;
|
|
21
21
|
createDOM(): void;
|
|
22
22
|
stopEvent: (event: Event) => boolean;
|
|
23
|
-
handleClick: (
|
|
23
|
+
handleClick: () => void;
|
|
24
24
|
selectNode: () => void;
|
|
25
25
|
destroy: () => void;
|
|
26
26
|
showContextMenu: () => void;
|
|
@@ -26,10 +26,11 @@ export declare class ContributorsView extends BlockView<Trackable<ContributorsNo
|
|
|
26
26
|
version: string;
|
|
27
27
|
ignoreMutation: () => boolean;
|
|
28
28
|
stopEvent: () => boolean;
|
|
29
|
+
private removeKeydownListener?;
|
|
29
30
|
updateContents(): void;
|
|
30
31
|
selectNode: () => void;
|
|
31
32
|
buildAuthors: (affs: PluginState) => void;
|
|
32
|
-
buildAuthor: (attrs: ContributorAttrs, isJointFirstAuthor: boolean) => HTMLSpanElement;
|
|
33
|
+
buildAuthor: (attrs: ContributorAttrs, isJointFirstAuthor: boolean, index: number) => HTMLSpanElement;
|
|
33
34
|
private createNote;
|
|
34
35
|
private isJointFirstAuthor;
|
|
35
36
|
createElement: () => void;
|
|
@@ -45,6 +46,7 @@ export declare class ContributorsView extends BlockView<Trackable<ContributorsNo
|
|
|
45
46
|
handleDeleteAuthor: (author: ContributorAttrs) => void;
|
|
46
47
|
insertAuthorNode: (attrs: ContributorAttrs) => void;
|
|
47
48
|
insertAffiliationNode: (attrs: AffiliationAttrs) => void;
|
|
49
|
+
destroy(): void;
|
|
48
50
|
}
|
|
49
51
|
declare const _default: (props: import("../configs/ManuscriptsEditor").EditorProps, dispatch?: import("..").Dispatch) => import("../types").NodeViewCreator<ContributorsView>;
|
|
50
52
|
export default _default;
|