@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.
Files changed (105) hide show
  1. package/dist/cjs/commands.js +5 -2
  2. package/dist/cjs/components/keywords/AddKeywordInline.js +12 -1
  3. package/dist/cjs/components/views/FigureDropdown.js +65 -6
  4. package/dist/cjs/configs/ManuscriptsEditor.js +1 -1
  5. package/dist/cjs/index.js +1 -0
  6. package/dist/cjs/keys/misc.js +2 -1
  7. package/dist/cjs/keys/title.js +0 -38
  8. package/dist/cjs/lib/comments.js +1 -0
  9. package/dist/cjs/lib/context-menu.js +74 -8
  10. package/dist/cjs/lib/media.js +27 -3
  11. package/dist/cjs/lib/navigation-utils.js +132 -0
  12. package/dist/cjs/lib/popper.js +25 -1
  13. package/dist/cjs/lib/position-menu.js +3 -0
  14. package/dist/cjs/lib/utils.js +7 -2
  15. package/dist/cjs/plugins/accessibility_element.js +10 -2
  16. package/dist/cjs/plugins/add-subtitle.js +8 -2
  17. package/dist/cjs/plugins/alt-titles.js +6 -1
  18. package/dist/cjs/plugins/comments.js +27 -15
  19. package/dist/cjs/plugins/persistent-cursor.js +4 -6
  20. package/dist/cjs/plugins/section_category.js +42 -9
  21. package/dist/cjs/plugins/translations.js +49 -13
  22. package/dist/cjs/versions.js +1 -1
  23. package/dist/cjs/views/accessibility_element.js +30 -0
  24. package/dist/cjs/views/alt_title.js +29 -0
  25. package/dist/cjs/views/alt_titles_section.js +9 -1
  26. package/dist/cjs/views/attachment.js +1 -1
  27. package/dist/cjs/views/bibliography_element.js +39 -17
  28. package/dist/cjs/views/citation.js +1 -0
  29. package/dist/cjs/views/citation_editable.js +4 -2
  30. package/dist/cjs/views/contributors.js +23 -2
  31. package/dist/cjs/views/cross_reference.js +3 -0
  32. package/dist/cjs/views/editable_block.js +37 -3
  33. package/dist/cjs/views/embed.js +3 -3
  34. package/dist/cjs/views/figure_editable.js +1 -1
  35. package/dist/cjs/views/figure_element.js +3 -0
  36. package/dist/cjs/views/footnote.js +3 -0
  37. package/dist/cjs/views/hero_image.js +4 -1
  38. package/dist/cjs/views/image_element.js +15 -7
  39. package/dist/cjs/views/inline_footnote.js +3 -0
  40. package/dist/cjs/views/keyword.js +15 -0
  41. package/dist/cjs/views/keyword_group.js +38 -0
  42. package/dist/cjs/views/quote_image_editable.js +1 -0
  43. package/dist/cjs/views/supplements.js +4 -1
  44. package/dist/es/commands.js +5 -2
  45. package/dist/es/components/keywords/AddKeywordInline.js +12 -1
  46. package/dist/es/components/views/FigureDropdown.js +66 -7
  47. package/dist/es/configs/ManuscriptsEditor.js +1 -1
  48. package/dist/es/index.js +1 -0
  49. package/dist/es/keys/misc.js +2 -1
  50. package/dist/es/keys/title.js +1 -39
  51. package/dist/es/lib/comments.js +1 -0
  52. package/dist/es/lib/context-menu.js +74 -8
  53. package/dist/es/lib/media.js +27 -3
  54. package/dist/es/lib/navigation-utils.js +122 -0
  55. package/dist/es/lib/popper.js +25 -1
  56. package/dist/es/lib/position-menu.js +3 -0
  57. package/dist/es/lib/utils.js +7 -2
  58. package/dist/es/plugins/accessibility_element.js +10 -2
  59. package/dist/es/plugins/add-subtitle.js +8 -2
  60. package/dist/es/plugins/alt-titles.js +6 -1
  61. package/dist/es/plugins/comments.js +27 -15
  62. package/dist/es/plugins/persistent-cursor.js +4 -6
  63. package/dist/es/plugins/section_category.js +42 -9
  64. package/dist/es/plugins/translations.js +49 -13
  65. package/dist/es/versions.js +1 -1
  66. package/dist/es/views/accessibility_element.js +30 -0
  67. package/dist/es/views/alt_title.js +29 -0
  68. package/dist/es/views/alt_titles_section.js +9 -1
  69. package/dist/es/views/attachment.js +1 -1
  70. package/dist/es/views/bibliography_element.js +39 -17
  71. package/dist/es/views/citation.js +1 -0
  72. package/dist/es/views/citation_editable.js +4 -2
  73. package/dist/es/views/contributors.js +23 -2
  74. package/dist/es/views/cross_reference.js +3 -0
  75. package/dist/es/views/editable_block.js +37 -3
  76. package/dist/es/views/embed.js +3 -3
  77. package/dist/es/views/figure_editable.js +1 -1
  78. package/dist/es/views/figure_element.js +3 -0
  79. package/dist/es/views/footnote.js +3 -0
  80. package/dist/es/views/hero_image.js +4 -1
  81. package/dist/es/views/image_element.js +15 -7
  82. package/dist/es/views/inline_footnote.js +3 -0
  83. package/dist/es/views/keyword.js +15 -0
  84. package/dist/es/views/keyword_group.js +38 -0
  85. package/dist/es/views/quote_image_editable.js +1 -0
  86. package/dist/es/views/supplements.js +4 -1
  87. package/dist/types/configs/ManuscriptsEditor.d.ts +1 -1
  88. package/dist/types/index.d.ts +1 -0
  89. package/dist/types/lib/context-menu.d.ts +1 -0
  90. package/dist/types/lib/media.d.ts +1 -1
  91. package/dist/types/lib/navigation-utils.d.ts +45 -0
  92. package/dist/types/lib/popper.d.ts +3 -0
  93. package/dist/types/lib/utils.d.ts +1 -1
  94. package/dist/types/versions.d.ts +1 -1
  95. package/dist/types/views/accessibility_element.d.ts +2 -0
  96. package/dist/types/views/alt_title.d.ts +2 -0
  97. package/dist/types/views/bibliography_element.d.ts +3 -0
  98. package/dist/types/views/citation_editable.d.ts +1 -1
  99. package/dist/types/views/contributors.d.ts +3 -1
  100. package/dist/types/views/keyword.d.ts +1 -0
  101. package/dist/types/views/keyword_group.d.ts +4 -0
  102. package/package.json +4 -4
  103. package/styles/AdvancedEditor.css +116 -10
  104. package/styles/Editor.css +61 -6
  105. package/styles/popper.css +3 -1
@@ -17,18 +17,36 @@
17
17
  Object.defineProperty(exports, "__esModule", { value: true });
18
18
  exports.PopperManager = void 0;
19
19
  const core_1 = require("@popperjs/core");
20
+ const navigation_utils_1 = require("./navigation-utils");
20
21
  class PopperManager {
21
22
  constructor() {
22
23
  this.isActive = () => !!this.activePopper;
23
24
  }
24
25
  show(target, contents, placement = 'bottom', showArrow = true, modifiers = []) {
25
26
  this.destroy();
27
+ this.triggerElement = target;
26
28
  window.requestAnimationFrame(() => {
27
29
  const container = document.createElement('div');
28
30
  container.className = 'popper';
31
+ this.container = container;
29
32
  container.addEventListener('click', (e) => {
30
33
  e.stopPropagation();
31
34
  });
35
+ const closeAndRestoreFocus = (e) => {
36
+ e.preventDefault();
37
+ e.stopPropagation();
38
+ this.destroy();
39
+ if (this.triggerElement instanceof HTMLElement) {
40
+ this.triggerElement.focus();
41
+ }
42
+ };
43
+ (0, navigation_utils_1.createKeyboardInteraction)({
44
+ container,
45
+ additionalKeys: {
46
+ Escape: closeAndRestoreFocus,
47
+ Tab: closeAndRestoreFocus,
48
+ },
49
+ });
32
50
  if (showArrow) {
33
51
  const arrow = document.createElement('div');
34
52
  arrow.className = 'popper-arrow';
@@ -80,15 +98,21 @@ class PopperManager {
80
98
  window.removeEventListener('click', this.handleDocumentClick);
81
99
  }
82
100
  delete this.activePopper;
101
+ delete this.container;
83
102
  }
84
103
  }
104
+ getContainer() {
105
+ return this.container;
106
+ }
85
107
  update() {
86
108
  if (this.activePopper) {
87
109
  this.activePopper.update();
88
110
  }
89
111
  }
90
112
  focusInput(container) {
91
- const element = container.querySelector('input');
113
+ const input = container.querySelector('input');
114
+ const button = container.querySelector('button:not([disabled])');
115
+ const element = input || button;
92
116
  if (element) {
93
117
  element.focus();
94
118
  }
@@ -23,6 +23,7 @@ const style_guide_1 = require("@manuscripts/style-guide");
23
23
  const icons_1 = require("../icons");
24
24
  const image_element_1 = require("../views/image_element");
25
25
  const ReactSubView_1 = __importDefault(require("../views/ReactSubView"));
26
+ const navigation_utils_1 = require("./navigation-utils");
26
27
  const view_1 = require("./view");
27
28
  const createPositionOptions = (nodeType, node, currentPosition, view, onComplete) => {
28
29
  const createAction = (position) => () => {
@@ -114,7 +115,9 @@ const createPositionMenuWrapper = (currentPosition, onClick, props) => {
114
115
  positionMenuButton.innerHTML = icon;
115
116
  }
116
117
  if (can.editArticle) {
118
+ positionMenuButton.tabIndex = 0;
117
119
  positionMenuButton.addEventListener('click', onClick);
120
+ positionMenuButton.addEventListener('keydown', (0, navigation_utils_1.handleEnterKey)(onClick));
118
121
  }
119
122
  positionMenuWrapper.appendChild(positionMenuButton);
120
123
  return positionMenuWrapper;
@@ -22,6 +22,7 @@ const prosemirror_model_1 = require("prosemirror-model");
22
22
  const prosemirror_utils_1 = require("prosemirror-utils");
23
23
  const config_1 = require("../components/references/ReferenceForm/config");
24
24
  const icons_1 = require("../icons");
25
+ const navigation_utils_1 = require("./navigation-utils");
25
26
  const editor_props_1 = require("../plugins/editor-props");
26
27
  function* iterateChildren(node, recurse = false) {
27
28
  for (let i = 0; i < node.childCount; i++) {
@@ -158,10 +159,14 @@ const createToggleButton = (listener, what) => {
158
159
  altTitlesButton.classList.add('toggle-button-open', 'button-reset');
159
160
  altTitlesButton.setAttribute('aria-label', `Expand ${what}`);
160
161
  altTitlesButton.innerHTML = icons_1.arrowDown;
161
- altTitlesButton.addEventListener('click', (e) => {
162
+ const activate = (e) => {
162
163
  e.preventDefault();
163
- listener();
164
+ listener(e);
165
+ };
166
+ altTitlesButton.addEventListener('click', (e) => {
167
+ activate(e);
164
168
  });
169
+ altTitlesButton.addEventListener('keydown', (0, navigation_utils_1.handleEnterKey)(activate));
165
170
  return altTitlesButton;
166
171
  };
167
172
  exports.createToggleButton = createToggleButton;
@@ -7,10 +7,18 @@ const prosemirror_view_1 = require("prosemirror-view");
7
7
  const utils_1 = require("../lib/utils");
8
8
  exports.accessibilityElementKey = new prosemirror_state_1.PluginKey('accessibility-element');
9
9
  const nodeTypes = [transform_1.schema.nodes.alt_text, transform_1.schema.nodes.long_desc];
10
- const handleExpandButtonClick = (view, node) => {
10
+ const handleExpandButtonClick = (view, node, event) => {
11
11
  const tr = view.state.tr;
12
12
  (0, exports.toggleAccessibilitySection)(tr, node);
13
13
  view.dispatch(tr);
14
+ const isKeyboardEvent = event.type === 'keydown';
15
+ if (isKeyboardEvent) {
16
+ const parentElement = view.dom.querySelector(`[id="${node.attrs.id}"]`);
17
+ if (parentElement) {
18
+ const firstInput = parentElement.querySelector('.accessibility_element_input');
19
+ firstInput?.focus();
20
+ }
21
+ }
14
22
  };
15
23
  const isSelectionWithin = (node, pos, selection) => {
16
24
  if (!selection || !nodeTypes.includes(node.type)) {
@@ -27,7 +35,7 @@ const buildExpandButtonDecorations = (doc) => {
27
35
  const container = document.createElement('div');
28
36
  container.className =
29
37
  'accessibility_element_expander_button_container';
30
- container.appendChild((0, utils_1.createToggleButton)(() => handleExpandButtonClick(view, node), 'additional info'));
38
+ container.appendChild((0, utils_1.createToggleButton)((e) => handleExpandButtonClick(view, node, e), 'additional info'));
31
39
  return container;
32
40
  }, {
33
41
  key: node.attrs.id,
@@ -20,15 +20,21 @@ const prosemirror_state_1 = require("prosemirror-state");
20
20
  const prosemirror_view_1 = require("prosemirror-view");
21
21
  const uuid_1 = require("uuid");
22
22
  const icons_1 = require("../icons");
23
+ const navigation_utils_1 = require("../lib/navigation-utils");
23
24
  const utils_1 = require("../lib/utils");
24
25
  const createAddSubtitleButton = (handler) => {
25
26
  const button = document.createElement('span');
26
27
  button.className = 'add-subtitle';
27
28
  button.innerHTML = `${icons_1.addAuthorIcon} <span class="add-subtitle-text">Add subtitle</span>`;
28
- button.addEventListener('mousedown', (e) => {
29
- e.preventDefault();
29
+ button.tabIndex = 0;
30
+ const activate = (event) => {
31
+ event.preventDefault();
30
32
  handler();
33
+ };
34
+ button.addEventListener('mousedown', (e) => {
35
+ activate(e);
31
36
  });
37
+ button.addEventListener('keydown', (0, navigation_utils_1.handleEnterKey)(activate));
32
38
  return button;
33
39
  };
34
40
  exports.default = (props) => new prosemirror_state_1.Plugin({
@@ -134,11 +134,16 @@ exports.default = () => {
134
134
  else if (pState.title[0].textContent.length) {
135
135
  const titleEnd = pState.title[0].nodeSize + pState.title[1];
136
136
  decorations.push(prosemirror_view_1.Decoration.widget(titleEnd - 1, (view) => {
137
- return (0, utils_1.createToggleButton)(() => {
137
+ return (0, utils_1.createToggleButton)((e) => {
138
138
  const tr = view.state.tr.setMeta(exports.altTitlesKey, {
139
139
  collapsed: false,
140
140
  });
141
141
  view.dispatch((0, track_changes_plugin_1.skipTracking)(tr));
142
+ const isKeyboardEvent = e.type === 'keydown';
143
+ if (isKeyboardEvent) {
144
+ const altTitle = view.dom.querySelector('.alt-title-text');
145
+ altTitle?.focus();
146
+ }
142
147
  }, 'alternative titles');
143
148
  }, {
144
149
  side: -1,
@@ -5,10 +5,28 @@ const transform_1 = require("@manuscripts/transform");
5
5
  const prosemirror_state_1 = require("prosemirror-state");
6
6
  const prosemirror_utils_1 = require("prosemirror-utils");
7
7
  const prosemirror_view_1 = require("prosemirror-view");
8
+ const navigation_utils_1 = require("../lib/navigation-utils");
8
9
  const comments_1 = require("../lib/comments");
9
10
  exports.commentsKey = new prosemirror_state_1.PluginKey('comments');
10
11
  const COMMENT_SELECTION = 'comment-selection';
11
12
  const EMPTY_SELECTION = {};
13
+ const handleCommentMarkerInteraction = (view, target) => {
14
+ const state = view.state;
15
+ const com = exports.commentsKey.getState(state);
16
+ const marker = target?.closest('[data-key]');
17
+ if (!marker && !com?.selection) {
18
+ return false;
19
+ }
20
+ const tr = state.tr;
21
+ if (marker) {
22
+ const key = marker.dataset.key;
23
+ (0, exports.setCommentSelection)(tr, key, undefined, false);
24
+ }
25
+ else {
26
+ (0, exports.clearCommentSelection)(tr);
27
+ }
28
+ view.dispatch(tr);
29
+ };
12
30
  exports.default = () => {
13
31
  return new prosemirror_state_1.Plugin({
14
32
  key: exports.commentsKey,
@@ -27,22 +45,16 @@ exports.default = () => {
27
45
  props: {
28
46
  decorations: (state) => exports.commentsKey.getState(state)?.decorations,
29
47
  handleClick: (view, pos, e) => {
30
- const state = view.state;
31
- const com = exports.commentsKey.getState(state);
32
48
  const target = e.target;
33
- const marker = target.closest('[data-key]');
34
- if (!marker && !com?.selection) {
35
- return;
36
- }
37
- const tr = state.tr;
38
- if (marker) {
39
- const key = marker.dataset.key;
40
- (0, exports.setCommentSelection)(tr, key, undefined, false);
41
- }
42
- else {
43
- (0, exports.clearCommentSelection)(tr);
44
- }
45
- view.dispatch(tr);
49
+ return handleCommentMarkerInteraction(view, target);
50
+ },
51
+ handleDOMEvents: {
52
+ keydown: (view, e) => {
53
+ return (0, navigation_utils_1.handleEnterKey)(() => {
54
+ const target = document.activeElement;
55
+ handleCommentMarkerInteraction(view, target);
56
+ })(e);
57
+ },
46
58
  },
47
59
  },
48
60
  });
@@ -49,12 +49,10 @@ exports.default = () => {
49
49
  },
50
50
  handleDOMEvents: {
51
51
  focus(view, event) {
52
- const newTr = view.state.tr.setMeta(exports.persistentCursor, { on: false });
53
- view.dispatch(newTr);
54
- },
55
- blur(view, event) {
56
- const newTr = view.state.tr.setMeta(exports.persistentCursor, { on: true });
57
- view.dispatch(newTr);
52
+ if (this.getState(view.state)?.on) {
53
+ const newTr = view.state.tr.setMeta(exports.persistentCursor, { on: false });
54
+ view.dispatch(newTr);
55
+ }
58
56
  },
59
57
  },
60
58
  },
@@ -6,6 +6,7 @@ const prosemirror_state_1 = require("prosemirror-state");
6
6
  const prosemirror_utils_1 = require("prosemirror-utils");
7
7
  const prosemirror_view_1 = require("prosemirror-view");
8
8
  const icons_1 = require("../icons");
9
+ const navigation_utils_1 = require("../lib/navigation-utils");
9
10
  exports.sectionCategoryKey = new prosemirror_state_1.PluginKey('section-category');
10
11
  exports.default = (props) => new prosemirror_state_1.Plugin({
11
12
  key: exports.sectionCategoryKey,
@@ -32,27 +33,51 @@ const createMenuItem = (props, contents, handler, isDisabled, isSelected) => {
32
33
  item.classList.add('disabled');
33
34
  }
34
35
  item.textContent = contents;
35
- item.addEventListener('mousedown', (event) => {
36
- handler(event);
37
- props.popper.destroy();
38
- });
36
+ item.setAttribute('tabindex', '0');
37
+ item.addEventListener('mousedown', handler);
38
+ item.addEventListener('keydown', (0, navigation_utils_1.handleEnterKey)(handler));
39
39
  return item;
40
40
  };
41
41
  const createMenu = (props, currentCategory, categories, usedCategoryIDs, onSelect) => {
42
42
  const menu = document.createElement('div');
43
43
  menu.className = 'section-category menu';
44
+ const menuItems = [];
45
+ const removeKeydownListener = (0, navigation_utils_1.createKeyboardInteraction)({
46
+ container: document,
47
+ navigation: {
48
+ getItems: () => menuItems,
49
+ arrowKeys: {
50
+ forward: 'ArrowDown',
51
+ backward: 'ArrowUp',
52
+ },
53
+ getCurrentElement: () => document.activeElement,
54
+ },
55
+ });
56
+ const destroy = () => {
57
+ removeKeydownListener();
58
+ props.popper.destroy();
59
+ };
44
60
  categories.forEach((category) => {
45
- const item = createMenuItem(props, category.titles[0], () => onSelect(category), category.isUnique && usedCategoryIDs.has(category.id), currentCategory === category);
61
+ const item = createMenuItem(props, category.titles[0], () => {
62
+ onSelect(category);
63
+ destroy();
64
+ }, category.isUnique && usedCategoryIDs.has(category.id), currentCategory === category);
65
+ menuItems.push(item);
46
66
  menu.appendChild(item);
47
67
  });
48
- return menu;
68
+ return { menu, destroy };
49
69
  };
50
70
  const createButton = (props, view, pos, currentCategory, categories, usedCategoryIDs, canEdit = true, disabled) => {
71
+ let menuInstance = null;
51
72
  const handleSelect = (category) => {
52
73
  const tr = view.state.tr;
53
74
  tr.setNodeAttribute(pos, 'category', category.id);
54
75
  view.dispatch(tr);
55
76
  };
77
+ const openMenu = () => {
78
+ menuInstance = createMenu(props, currentCategory, categories, usedCategoryIDs, handleSelect);
79
+ props.popper.show(button, menuInstance.menu, 'bottom-end', false);
80
+ };
56
81
  const button = document.createElement('button');
57
82
  button.innerHTML = icons_1.sectionCategoryIcon;
58
83
  button.classList.add('section-category-button');
@@ -65,9 +90,17 @@ const createButton = (props, view, pos, currentCategory, categories, usedCategor
65
90
  button.classList.add('disabled');
66
91
  }
67
92
  else if (canEdit) {
68
- button.addEventListener('mousedown', () => {
69
- const menu = createMenu(props, currentCategory, categories, usedCategoryIDs, handleSelect);
70
- props.popper.show(button, menu, 'bottom-end', false);
93
+ button.addEventListener('click', openMenu);
94
+ (0, navigation_utils_1.createKeyboardInteraction)({
95
+ container: button,
96
+ additionalKeys: {
97
+ Enter: openMenu,
98
+ Escape: (e) => {
99
+ e.preventDefault();
100
+ menuInstance?.destroy();
101
+ menuInstance = null;
102
+ },
103
+ },
71
104
  });
72
105
  }
73
106
  return button;
@@ -22,24 +22,43 @@ const commands_1 = require("../commands");
22
22
  const icons_1 = require("../icons");
23
23
  const languages_1 = require("../lib/languages");
24
24
  const template_1 = require("../lib/template");
25
- const createMenuItem = (props, contents, handler, isSelected = false) => {
25
+ const navigation_utils_1 = require("../lib/navigation-utils");
26
+ const createMenuItem = (props, contents, handler, isSelected = false, tabIndex) => {
26
27
  const item = document.createElement('div');
27
28
  item.className = `menu-item ${isSelected ? 'selected' : ''}`;
28
29
  item.textContent = contents;
29
- item.addEventListener('mousedown', (event) => {
30
- handler(event);
31
- props.popper.destroy();
32
- });
30
+ item.tabIndex = tabIndex;
31
+ item.addEventListener('mousedown', handler);
32
+ item.addEventListener('keydown', (0, navigation_utils_1.handleEnterKey)(handler));
33
33
  return item;
34
34
  };
35
35
  const createLanguageMenu = (props, selectedCode, onSelect) => {
36
36
  const menu = document.createElement('div');
37
37
  menu.className = 'language menu';
38
- props.languages.forEach((language) => {
39
- const item = createMenuItem(props, (0, languages_1.getLanguageLabel)(language), () => onSelect(language.code), selectedCode === language.code);
38
+ const menuItems = [];
39
+ const removeKeydownListener = (0, navigation_utils_1.createKeyboardInteraction)({
40
+ container: document,
41
+ navigation: {
42
+ getItems: () => menuItems,
43
+ arrowKeys: {
44
+ forward: 'ArrowDown',
45
+ backward: 'ArrowUp',
46
+ },
47
+ },
48
+ });
49
+ const destroy = () => {
50
+ removeKeydownListener();
51
+ props.popper.destroy();
52
+ };
53
+ props.languages.forEach((language, index) => {
54
+ const item = createMenuItem(props, (0, languages_1.getLanguageLabel)(language), () => {
55
+ onSelect(language.code);
56
+ destroy();
57
+ }, selectedCode === language.code, index === 0 ? 0 : -1);
58
+ menuItems.push(item);
40
59
  menu.appendChild(item);
41
60
  });
42
- return menu;
61
+ return { menu, destroy };
43
62
  };
44
63
  exports.default = (props) => new prosemirror_state_1.Plugin({
45
64
  props: {
@@ -66,10 +85,11 @@ exports.default = (props) => new prosemirror_state_1.Plugin({
66
85
  if (canEdit) {
67
86
  widgets.push(prosemirror_view_1.Decoration.widget(pos + 1, (view) => {
68
87
  const $span = document.createElement('span');
88
+ $span.tabIndex = 0;
69
89
  $span.className = 'add-trans-abstract';
70
90
  $span.title = 'Add translation';
71
91
  $span.innerHTML = `${icons_1.addAuthorIcon} <span class="add-trans-abstract-text">Add translation</span>`;
72
- $span.addEventListener('mousedown', (event) => {
92
+ const handleActivate = (event) => {
73
93
  event.preventDefault();
74
94
  event.stopPropagation();
75
95
  if (isGraphical && category) {
@@ -78,7 +98,9 @@ exports.default = (props) => new prosemirror_state_1.Plugin({
78
98
  else {
79
99
  (0, commands_1.insertTransAbstract)(view.state, view.dispatch, node.attrs.category, pos + node.nodeSize);
80
100
  }
81
- });
101
+ };
102
+ $span.addEventListener('mousedown', handleActivate);
103
+ $span.addEventListener('keydown', (0, navigation_utils_1.handleEnterKey)(handleActivate));
82
104
  return $span;
83
105
  }));
84
106
  }
@@ -94,12 +116,14 @@ exports.default = (props) => new prosemirror_state_1.Plugin({
94
116
  $btn.className = 'language-selector-btn';
95
117
  $btn.setAttribute('data-cy', 'language-selector-btn');
96
118
  $btn.contentEditable = 'false';
119
+ $btn.tabIndex = canEdit ? 0 : -1;
97
120
  const code = node.attrs.lang || 'en';
98
121
  const lang = (0, languages_1.getLanguage)(code, props.languages);
99
122
  const label = (0, languages_1.getLanguageLabel)(lang);
100
123
  $btn.innerHTML = `<span>${label}</span> ${icons_1.translateIcon}`;
101
124
  if (canEdit) {
102
- $btn.addEventListener('mousedown', (event) => {
125
+ let menuInstance = null;
126
+ const handleOpenMenu = (event) => {
103
127
  event.preventDefault();
104
128
  event.stopPropagation();
105
129
  props.popper.destroy();
@@ -107,9 +131,21 @@ exports.default = (props) => new prosemirror_state_1.Plugin({
107
131
  const tr = view.state.tr.setNodeAttribute(pos, 'lang', code);
108
132
  view.dispatch(tr);
109
133
  };
110
- const menu = createLanguageMenu(props, code, handleSelect);
111
- props.popper.show($btn, menu, 'bottom-end', false);
134
+ menuInstance = createLanguageMenu(props, code, handleSelect);
135
+ props.popper.show($btn, menuInstance.menu, 'bottom-end', false);
136
+ };
137
+ (0, navigation_utils_1.createKeyboardInteraction)({
138
+ container: $btn,
139
+ additionalKeys: {
140
+ Enter: handleOpenMenu,
141
+ Escape: (e) => {
142
+ e.preventDefault();
143
+ menuInstance?.destroy();
144
+ menuInstance = null;
145
+ },
146
+ },
112
147
  });
148
+ $btn.addEventListener('mousedown', handleOpenMenu);
113
149
  }
114
150
  return $btn;
115
151
  }));
@@ -1,5 +1,5 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.MATHJAX_VERSION = exports.VERSION = void 0;
4
- exports.VERSION = '3.9.11';
4
+ exports.VERSION = '3.9.13';
5
5
  exports.MATHJAX_VERSION = '3.2.2';
@@ -5,6 +5,8 @@ var __importDefault = (this && this.__importDefault) || function (mod) {
5
5
  Object.defineProperty(exports, "__esModule", { value: true });
6
6
  exports.AccessibilityElementView = void 0;
7
7
  const transform_1 = require("@manuscripts/transform");
8
+ const prosemirror_state_1 = require("prosemirror-state");
9
+ const navigation_utils_1 = require("../lib/navigation-utils");
8
10
  const block_view_1 = __importDefault(require("./block_view"));
9
11
  const creators_1 = require("./creators");
10
12
  class AccessibilityElementView extends block_view_1.default {
@@ -29,6 +31,34 @@ class AccessibilityElementView extends block_view_1.default {
29
31
  super.createElement();
30
32
  this.contentDOM.className = 'accessibility_element_input';
31
33
  this.contentDOM.setAttribute('contenteditable', 'true');
34
+ this.contentDOM.tabIndex = this.node.type === transform_1.schema.nodes.alt_text ? 0 : -1;
35
+ this.removeKeydownListener = (0, navigation_utils_1.createKeyboardInteraction)({
36
+ container: this.contentDOM,
37
+ navigation: {
38
+ getItems: () => {
39
+ const parentEl = this.dom.parentElement;
40
+ if (!parentEl) {
41
+ return [];
42
+ }
43
+ return Array.from(parentEl.querySelectorAll('.accessibility_element_input'));
44
+ },
45
+ arrowKeys: { forward: 'ArrowDown', backward: 'ArrowUp' },
46
+ getCurrentElement: () => this.contentDOM,
47
+ },
48
+ additionalKeys: {
49
+ Enter: (e) => {
50
+ e.preventDefault();
51
+ const pos = this.getPos();
52
+ const tr = this.view.state.tr.setSelection(prosemirror_state_1.TextSelection.create(this.view.state.doc, pos + 1));
53
+ this.view.dispatch(tr);
54
+ this.view.focus();
55
+ },
56
+ },
57
+ });
58
+ }
59
+ destroy() {
60
+ this.removeKeydownListener?.();
61
+ super.destroy();
32
62
  }
33
63
  }
34
64
  exports.AccessibilityElementView = AccessibilityElementView;
@@ -16,6 +16,8 @@
16
16
  */
17
17
  Object.defineProperty(exports, "__esModule", { value: true });
18
18
  exports.AltTitleView = void 0;
19
+ const prosemirror_state_1 = require("prosemirror-state");
20
+ const navigation_utils_1 = require("../lib/navigation-utils");
19
21
  const base_node_view_1 = require("./base_node_view");
20
22
  const creators_1 = require("./creators");
21
23
  class AltTitleView extends base_node_view_1.BaseNodeView {
@@ -34,11 +36,38 @@ class AltTitleView extends base_node_view_1.BaseNodeView {
34
36
  this.dom.setAttribute('data-type', this.node.attrs.type);
35
37
  this.contentDOM = document.createElement('div');
36
38
  this.contentDOM.classList.add('alt-title-text');
39
+ this.contentDOM.tabIndex = this.node.attrs.type === 'running' ? 0 : -1;
40
+ this.removeKeydownListener = (0, navigation_utils_1.createKeyboardInteraction)({
41
+ container: this.contentDOM,
42
+ navigation: {
43
+ getItems: () => {
44
+ const allAltTitles = Array.from(this.view.dom.querySelectorAll('.alt-title-text'));
45
+ return allAltTitles;
46
+ },
47
+ arrowKeys: { forward: 'ArrowDown', backward: 'ArrowUp' },
48
+ getCurrentElement: () => this.contentDOM,
49
+ },
50
+ additionalKeys: {
51
+ Enter: (e) => {
52
+ e.preventDefault();
53
+ const pos = this.getPos();
54
+ if (typeof pos === 'number') {
55
+ const tr = this.view.state.tr.setSelection(prosemirror_state_1.TextSelection.create(this.view.state.doc, pos + 1));
56
+ this.view.dispatch(tr);
57
+ this.view.focus();
58
+ }
59
+ },
60
+ },
61
+ });
37
62
  this.dom.appendChild(label);
38
63
  this.dom.appendChild(this.contentDOM);
39
64
  this.updateContents();
40
65
  };
41
66
  }
67
+ destroy() {
68
+ this.removeKeydownListener?.();
69
+ super.destroy();
70
+ }
42
71
  }
43
72
  exports.AltTitleView = AltTitleView;
44
73
  exports.default = (0, creators_1.createNodeView)(AltTitleView);
@@ -25,6 +25,7 @@ const icons_1 = require("../icons");
25
25
  const alt_titles_1 = require("../plugins/alt-titles");
26
26
  const block_view_1 = __importDefault(require("./block_view"));
27
27
  const creators_1 = require("./creators");
28
+ const navigation_utils_1 = require("../lib/navigation-utils");
28
29
  class AltTitleSectionView extends block_view_1.default {
29
30
  constructor() {
30
31
  super(...arguments);
@@ -47,7 +48,7 @@ class AltTitleSectionView extends block_view_1.default {
47
48
  button.classList.add('alt-titles-closing-button', 'button-reset');
48
49
  button.setAttribute('aria-label', 'Collapse alternative titles');
49
50
  button.innerHTML = icons_1.arrowDown;
50
- button.addEventListener('click', () => {
51
+ const handleCollapse = () => {
51
52
  const tr = this.view.state.tr.setMeta(alt_titles_1.altTitlesKey, {
52
53
  collapsed: true,
53
54
  });
@@ -59,7 +60,14 @@ class AltTitleSectionView extends block_view_1.default {
59
60
  tr.setSelection(prosemirror_state_1.TextSelection.create(tr.doc, titleEndPos));
60
61
  }
61
62
  this.view.dispatch(tr);
63
+ const toggleButton = this.view.dom.querySelector('.toggle-button-open');
64
+ toggleButton?.focus();
65
+ };
66
+ button.addEventListener('click', (e) => {
67
+ e.preventDefault();
68
+ handleCollapse();
62
69
  });
70
+ button.addEventListener('keydown', (0, navigation_utils_1.handleEnterKey)(() => handleCollapse()));
63
71
  closingPanel.appendChild(button);
64
72
  return closingPanel;
65
73
  }
@@ -123,7 +123,7 @@ class AttachmentView extends block_view_1.default {
123
123
  stopPropagation: () => {
124
124
  },
125
125
  };
126
- this.props.onEditorClick(this.getPos(), this.node, this.getPos(), event);
126
+ this.props.onEditorClick(event);
127
127
  }
128
128
  }
129
129
  }