@manuscripts/body-editor 3.13.9 → 3.13.11

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 (55) hide show
  1. package/dist/cjs/commands.js +22 -3
  2. package/dist/cjs/configs/editor-views.js +6 -0
  3. package/dist/cjs/icons.js +2 -1
  4. package/dist/cjs/lib/files.js +6 -1
  5. package/dist/cjs/menus.js +8 -0
  6. package/dist/cjs/node-type-icons.js +4 -0
  7. package/dist/cjs/plugins/accessibility_element.js +2 -1
  8. package/dist/cjs/versions.js +1 -1
  9. package/dist/cjs/views/accessibility_element.js +7 -0
  10. package/dist/cjs/views/headshot_element.js +74 -0
  11. package/dist/cjs/views/headshot_element_editable.js +20 -0
  12. package/dist/cjs/views/headshot_grid.js +82 -0
  13. package/dist/cjs/views/headshot_grid_editable.js +21 -0
  14. package/dist/cjs/views/headshot_image_editable.js +79 -0
  15. package/dist/cjs/views/section_title.js +0 -1
  16. package/dist/es/commands.js +19 -1
  17. package/dist/es/configs/editor-views.js +6 -0
  18. package/dist/es/icons.js +2 -1
  19. package/dist/es/lib/files.js +6 -1
  20. package/dist/es/menus.js +9 -1
  21. package/dist/es/node-type-icons.js +5 -1
  22. package/dist/es/plugins/accessibility_element.js +2 -1
  23. package/dist/es/versions.js +1 -1
  24. package/dist/es/views/accessibility_element.js +7 -0
  25. package/dist/es/views/headshot_element.js +70 -0
  26. package/dist/es/views/headshot_element_editable.js +18 -0
  27. package/dist/es/views/headshot_grid.js +75 -0
  28. package/dist/es/views/headshot_grid_editable.js +19 -0
  29. package/dist/es/views/headshot_image_editable.js +75 -0
  30. package/dist/es/views/section_title.js +0 -1
  31. package/dist/types/commands.d.ts +1 -0
  32. package/dist/types/icons.d.ts +1 -0
  33. package/dist/types/versions.d.ts +1 -1
  34. package/dist/types/views/headshot_element.d.ts +29 -0
  35. package/dist/types/views/headshot_element_editable.d.ts +18 -0
  36. package/dist/types/views/headshot_grid.d.ts +28 -0
  37. package/dist/types/views/headshot_grid_editable.d.ts +44 -0
  38. package/dist/types/views/headshot_image_editable.d.ts +28 -0
  39. package/package.json +2 -2
  40. package/src/commands.ts +28 -1
  41. package/src/configs/editor-views.ts +6 -0
  42. package/src/icons.ts +2 -0
  43. package/src/lib/files.ts +7 -1
  44. package/src/menus.tsx +10 -0
  45. package/src/node-type-icons.tsx +12 -0
  46. package/src/plugins/accessibility_element.ts +4 -1
  47. package/src/versions.ts +1 -1
  48. package/src/views/accessibility_element.ts +7 -0
  49. package/src/views/headshot_element.ts +98 -0
  50. package/src/views/headshot_element_editable.ts +20 -0
  51. package/src/views/headshot_grid.ts +98 -0
  52. package/src/views/headshot_grid_editable.ts +21 -0
  53. package/src/views/headshot_image_editable.ts +93 -0
  54. package/src/views/section_title.ts +0 -1
  55. package/styles/AdvancedEditor.css +169 -1
@@ -15,8 +15,8 @@
15
15
  * limitations under the License.
16
16
  */
17
17
  Object.defineProperty(exports, "__esModule", { value: true });
18
- exports.addInlineComment = exports.addNodeComment = exports.createAndFillTableElement = exports.selectAllIsolating = exports.ignoreAtomBlockNodeForward = exports.isAtEndOfTextBlock = exports.ignoreMetaNodeBackspaceCommand = exports.ignoreAtomBlockNodeBackward = exports.isTextSelection = exports.isAtStartOfTextBlock = exports.insertTransGraphicalAbstract = exports.insertTransAbstract = exports.insertTOCSection = exports.insertBibliographySection = exports.insertList = exports.insertKeywords = exports.insertAward = exports.insertAffiliation = exports.insertContributors = exports.insertGraphicalAbstract = exports.insertBackmatterSection = exports.insertAbstractSection = exports.insertSection = exports.insertBoxElement = exports.insertInlineFootnote = exports.insertFootnotesElement = exports.insertTableElementFooter = exports.insertInlineEquation = exports.insertCrossReference = exports.insertInlineCitation = exports.insertLink = exports.insertSectionLabel = exports.findPosBeforeFirstSubsection = exports.insertBreak = exports.deleteBlock = exports.insertBlock = exports.insertAttachment = exports.insertSupplement = exports.insertTable = exports.insertEmbed = exports.insertFigure = exports.insertGeneralTableFootnote = exports.insertInlineTableFootnote = exports.createBlock = exports.createSelection = exports.canInsert = exports.blockActive = exports.isNodeSelection = exports.markActive = exports.addToStart = void 0;
19
- exports.paste = exports.copySelection = exports.exitEditorToContainer = exports.ignoreEnterInSubtitles = exports.insertHeroImage = exports.activateSearchReplace = exports.activateSearch = exports.autoComplete = exports.addColumns = exports.addHeaderRow = exports.addRows = void 0;
18
+ exports.addNodeComment = exports.createAndFillTableElement = exports.selectAllIsolating = exports.ignoreAtomBlockNodeForward = exports.isAtEndOfTextBlock = exports.ignoreMetaNodeBackspaceCommand = exports.ignoreAtomBlockNodeBackward = exports.isTextSelection = exports.isAtStartOfTextBlock = exports.insertTransGraphicalAbstract = exports.insertTransAbstract = exports.insertTOCSection = exports.insertBibliographySection = exports.insertList = exports.insertKeywords = exports.insertAward = exports.insertAffiliation = exports.insertContributors = exports.insertGraphicalAbstract = exports.insertBackmatterSection = exports.insertAbstractSection = exports.insertSection = exports.insertHeadshotGrid = exports.insertBoxElement = exports.insertInlineFootnote = exports.insertFootnotesElement = exports.insertTableElementFooter = exports.insertInlineEquation = exports.insertCrossReference = exports.insertInlineCitation = exports.insertLink = exports.insertSectionLabel = exports.findPosBeforeFirstSubsection = exports.insertBreak = exports.deleteBlock = exports.insertBlock = exports.insertAttachment = exports.insertSupplement = exports.insertTable = exports.insertEmbed = exports.insertFigure = exports.insertGeneralTableFootnote = exports.insertInlineTableFootnote = exports.createBlock = exports.createSelection = exports.canInsert = exports.blockActive = exports.isNodeSelection = exports.markActive = exports.addToStart = void 0;
19
+ exports.paste = exports.copySelection = exports.exitEditorToContainer = exports.ignoreEnterInSubtitles = exports.insertHeroImage = exports.activateSearchReplace = exports.activateSearch = exports.autoComplete = exports.addColumns = exports.addHeaderRow = exports.addRows = exports.addInlineComment = void 0;
20
20
  const track_changes_plugin_1 = require("@manuscripts/track-changes-plugin");
21
21
  const transform_1 = require("@manuscripts/transform");
22
22
  const prosemirror_model_1 = require("prosemirror-model");
@@ -598,6 +598,25 @@ const insertBoxElement = (state, dispatch) => {
598
598
  return true;
599
599
  };
600
600
  exports.insertBoxElement = insertBoxElement;
601
+ const insertHeadshotGrid = (state, dispatch) => {
602
+ const selection = state.selection;
603
+ const { nodes } = transform_1.schema;
604
+ const isBody = (0, prosemirror_utils_1.hasParentNodeOfType)(nodes.body)(selection);
605
+ if (!isBody) {
606
+ return false;
607
+ }
608
+ const position = findBlockInsertPosition(state);
609
+ if (position && dispatch) {
610
+ const headshotElement = transform_1.schema.nodes.headshot_element.createAndFill();
611
+ const node = nodes.headshot_grid.create({}, headshotElement);
612
+ const tr = state.tr.insert(position, node);
613
+ const headshotNamePosition = position + 2;
614
+ tr.setSelection(prosemirror_state_1.TextSelection.create(tr.doc, headshotNamePosition));
615
+ dispatch(tr.scrollIntoView());
616
+ }
617
+ return true;
618
+ };
619
+ exports.insertHeadshotGrid = insertHeadshotGrid;
601
620
  const insertSection = (subsection = false) => (state, dispatch, view) => {
602
621
  const { nodes } = transform_1.schema;
603
622
  const $pos = state.selection.$from;
@@ -963,7 +982,7 @@ const insertTransGraphicalAbstract = (category, insertAfterPos) => (state, dispa
963
982
  lang,
964
983
  category: category.id,
965
984
  }, [
966
- transform_1.schema.nodes.section_title.create({}, transform_1.schema.text(category.titles[0])),
985
+ transform_1.schema.nodes.section_title.create(),
967
986
  createAndFillFigureElement(state),
968
987
  ]);
969
988
  const tr = state.tr.insert(pos, node);
@@ -31,6 +31,9 @@ const footnote_1 = __importDefault(require("../views/footnote"));
31
31
  const footnotes_element_1 = __importDefault(require("../views/footnotes_element"));
32
32
  const general_table_footnote_1 = __importDefault(require("../views/general_table_footnote"));
33
33
  const hero_image_editable_1 = __importDefault(require("../views/hero_image_editable"));
34
+ const headshot_grid_editable_1 = __importDefault(require("../views/headshot_grid_editable"));
35
+ const headshot_element_1 = __importDefault(require("../views/headshot_element"));
36
+ const headshot_image_editable_1 = __importDefault(require("../views/headshot_image_editable"));
34
37
  const image_element_editable_1 = __importDefault(require("../views/image_element_editable"));
35
38
  const inline_equation_editable_1 = __importDefault(require("../views/inline_equation_editable"));
36
39
  const inline_footnote_editable_1 = __importDefault(require("../views/inline_footnote_editable"));
@@ -111,6 +114,9 @@ exports.default = (props, dispatch) => {
111
114
  long_desc: (0, accessibility_element_1.default)(props, dispatch),
112
115
  alt_text: (0, accessibility_element_1.default)(props, dispatch),
113
116
  hero_image: (0, hero_image_editable_1.default)(props, dispatch),
117
+ headshot_grid: (0, headshot_grid_editable_1.default)(props, dispatch),
118
+ headshot_element: (0, headshot_element_1.default)(props, dispatch),
119
+ headshot_image: (0, headshot_image_editable_1.default)(props, dispatch),
114
120
  abstracts: (0, abstracts_1.default)(props),
115
121
  trans_abstract: (0, translated_abstract_editable_1.default)(props),
116
122
  trans_graphical_abstract: (0, trans_graphical_abstract_editable_1.default)(props),
package/dist/cjs/icons.js CHANGED
@@ -1,6 +1,6 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.ORCIDIcon = exports.tickIcon = exports.fileMainDocumentIcon = exports.linkIcon = exports.translateIcon = exports.draggableIcon = exports.fileCorruptedIcon = exports.imageDefaultIcon = exports.imageLeftIcon = exports.imageRightIcon = exports.plusIcon = exports.lockIcon = exports.scrollIcon = exports.sectionCategoryIcon = exports.editIcon = exports.deleteIcon = exports.alertIcon = exports.arrowUp = exports.arrowDown = exports.addAuthorIcon = void 0;
3
+ exports.ORCIDIcon = exports.tickIcon = exports.fileMainDocumentIcon = exports.linkIcon = exports.translateIcon = exports.draggableIcon = exports.fileCorruptedIcon = exports.imageDefaultIcon = exports.imageLeftIcon = exports.imageRightIcon = exports.plusIcon = exports.lockIcon = exports.scrollIcon = exports.sectionCategoryIcon = exports.editIcon = exports.deleteIcon = exports.cameraIcon = exports.alertIcon = exports.arrowUp = exports.arrowDown = exports.addAuthorIcon = void 0;
4
4
  const style_guide_1 = require("@manuscripts/style-guide");
5
5
  const react_1 = require("react");
6
6
  const server_1 = require("react-dom/server");
@@ -9,6 +9,7 @@ exports.addAuthorIcon = renderIcon(style_guide_1.AddAuthorIcon);
9
9
  exports.arrowDown = renderIcon(style_guide_1.ArrowDownCircleIcon);
10
10
  exports.arrowUp = renderIcon(style_guide_1.ArrowUpIcon);
11
11
  exports.alertIcon = renderIcon(style_guide_1.AlertIcon);
12
+ exports.cameraIcon = renderIcon(style_guide_1.CameraIcon);
12
13
  exports.deleteIcon = renderIcon(style_guide_1.DeleteIcon);
13
14
  exports.editIcon = renderIcon(style_guide_1.EditIcon);
14
15
  exports.sectionCategoryIcon = renderIcon(style_guide_1.SectionCategoryIcon);
@@ -13,6 +13,7 @@ const figureTypes = [
13
13
  transform_1.schema.nodes.figure_element,
14
14
  transform_1.schema.nodes.image_element,
15
15
  transform_1.schema.nodes.hero_image,
16
+ transform_1.schema.nodes.headshot_grid,
16
17
  transform_1.schema.nodes.embed,
17
18
  ];
18
19
  function memoGroupFiles() {
@@ -56,7 +57,11 @@ const groupFiles = (doc, files) => {
56
57
  }
57
58
  }
58
59
  else {
59
- for (const figure of (0, prosemirror_utils_1.findChildrenByType)(node, transform_1.schema.nodes.figure)) {
60
+ const descend = node.type === transform_1.schema.nodes.headshot_grid;
61
+ const figureNodeType = node.type === transform_1.schema.nodes.headshot_grid
62
+ ? transform_1.schema.nodes.headshot_image
63
+ : transform_1.schema.nodes.figure;
64
+ for (const figure of (0, prosemirror_utils_1.findChildrenByType)(node, figureNodeType, descend)) {
60
65
  if ((0, track_changes_utils_1.isHidden)(figure.node)) {
61
66
  continue;
62
67
  }
package/dist/cjs/menus.js CHANGED
@@ -272,6 +272,14 @@ const getEditorMenus = (editor) => {
272
272
  run: doCommand(commands_1.insertBoxElement),
273
273
  isHidden: !(0, template_1.templateAllows)(state, transform_1.schema.nodes.box_element),
274
274
  },
275
+ {
276
+ id: 'insert-headshot-grid',
277
+ label: 'Headshot Panel',
278
+ isEnabled: (0, utils_1.isEditAllowed)(state) &&
279
+ isCommandValid((0, commands_1.canInsert)(transform_1.schema.nodes.headshot_grid)),
280
+ run: doCommand(commands_1.insertHeadshotGrid),
281
+ isHidden: !(0, template_1.templateAllows)(state, transform_1.schema.nodes.headshot_grid),
282
+ },
275
283
  {
276
284
  role: 'separator',
277
285
  },
@@ -23,6 +23,8 @@ const style_guide_1 = require("@manuscripts/style-guide");
23
23
  const transform_1 = require("@manuscripts/transform");
24
24
  const react_1 = __importDefault(require("react"));
25
25
  const { nodes } = transform_1.schema;
26
+ const OutlineHeadshotGridIcon = () => (react_1.default.createElement(style_guide_1.FileHeadshotGridIcon, { width: "12", height: "12" }));
27
+ const OutlineHeadshotElementIcon = () => (react_1.default.createElement(style_guide_1.AvatarIcon, { width: "16", height: "16" }));
26
28
  const OutlineImageIcon = () => (react_1.default.createElement(style_guide_1.FileImageIcon, { width: "11", height: "14" }));
27
29
  const OutlineSupplementsIcon = () => (react_1.default.createElement(style_guide_1.SupplementsIcon, { width: "11", height: "14" }));
28
30
  const OutlineMainDocumentIcon = () => (react_1.default.createElement(style_guide_1.FileDocumentIcon, { width: "11", height: "14" }));
@@ -44,6 +46,8 @@ const icons = new Map([
44
46
  [nodes.hero_image, OutlineImageIcon],
45
47
  [nodes.supplements, OutlineSupplementsIcon],
46
48
  [nodes.attachments, OutlineMainDocumentIcon],
49
+ [nodes.headshot_grid, OutlineHeadshotGridIcon],
50
+ [nodes.headshot_element, OutlineHeadshotElementIcon],
47
51
  ]);
48
52
  const nodeTypeIcon = (nodeType, listType) => {
49
53
  if (nodeType === transform_1.schema.nodes.list) {
@@ -30,7 +30,8 @@ const isSelectionWithin = (node, pos, selection) => {
30
30
  const buildExpandButtonDecorations = (doc) => {
31
31
  const decorations = [];
32
32
  doc.descendants((node, pos) => {
33
- if (node.type.spec.content?.includes('alt_text')) {
33
+ if (node.type !== transform_1.schema.nodes.headshot_element &&
34
+ node.type.spec.content?.includes('alt_text')) {
34
35
  decorations.push(prosemirror_view_1.Decoration.widget(pos + node.nodeSize - 1, (view) => {
35
36
  const container = document.createElement('div');
36
37
  container.className =
@@ -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.13.9';
4
+ exports.VERSION = '3.13.11';
5
5
  exports.MATHJAX_VERSION = '3.2.2';
@@ -9,8 +9,15 @@ const prosemirror_state_1 = require("prosemirror-state");
9
9
  const navigation_utils_1 = require("../lib/navigation-utils");
10
10
  const block_view_1 = __importDefault(require("./block_view"));
11
11
  const creators_1 = require("./creators");
12
+ const empty_1 = __importDefault(require("./empty"));
12
13
  class AccessibilityElementView extends block_view_1.default {
13
14
  initialise() {
15
+ const $pos = this.view.state.doc.resolve(this.getPos());
16
+ if ($pos.parent.type === transform_1.schema.nodes.headshot_element) {
17
+ const { dom } = (0, empty_1.default)('accessibility_element')();
18
+ this.dom = dom;
19
+ return;
20
+ }
14
21
  this.createDOM();
15
22
  this.createElement();
16
23
  this.updateContents();
@@ -0,0 +1,74 @@
1
+ "use strict";
2
+ /*!
3
+ * © 2026 Atypon Systems LLC
4
+ *
5
+ * Licensed under the Apache License, Version 2.0 (the "License");
6
+ * you may not use this file except in compliance with the License.
7
+ * You may obtain a copy of the License at
8
+ *
9
+ * http://www.apache.org/licenses/LICENSE-2.0
10
+ *
11
+ * Unless required by applicable law or agreed to in writing, software
12
+ * distributed under the License is distributed on an "AS IS" BASIS,
13
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14
+ * See the License for the specific language governing permissions and
15
+ * limitations under the License.
16
+ */
17
+ Object.defineProperty(exports, "__esModule", { value: true });
18
+ exports.HeadshotElement = void 0;
19
+ const prosemirror_state_1 = require("prosemirror-state");
20
+ const icons_1 = require("../icons");
21
+ const navigation_utils_1 = require("../lib/navigation-utils");
22
+ const base_node_view_1 = require("./base_node_view");
23
+ const creators_1 = require("./creators");
24
+ class HeadshotElement extends base_node_view_1.BaseNodeView {
25
+ constructor() {
26
+ super(...arguments);
27
+ this.elementType = 'div';
28
+ this.createElement = () => {
29
+ this.dom = document.createElement('div');
30
+ this.dom.classList.add('headshot-element');
31
+ this.dom.tabIndex = 0;
32
+ this.dom.setAttribute('id', this.node.attrs.id);
33
+ this.container = document.createElement('div');
34
+ this.container.classList.add('block');
35
+ this.dom.appendChild(this.container);
36
+ this.contentDOM = document.createElement('div');
37
+ this.contentDOM.classList.add('block-container', 'headshot-element-block');
38
+ this.container.appendChild(this.contentDOM);
39
+ const can = this.props.getCapabilities();
40
+ if (can.editArticle) {
41
+ this.deleteHeadshotButton = document.createElement('button');
42
+ this.deleteHeadshotButton.innerHTML = icons_1.plusIcon;
43
+ this.deleteHeadshotButton.classList.add('headshot-remove-button');
44
+ this.deleteHeadshotButton.setAttribute('data-cy', 'headshot-delete');
45
+ this.deleteHeadshotButton.contentEditable = 'false';
46
+ this.deleteHeadshotButton.addEventListener('click', this.handleDeleteHeadshot);
47
+ this.deleteHeadshotButton.addEventListener('keydown', (0, navigation_utils_1.handleEnterKey)(this.handleDeleteHeadshot));
48
+ this.container.appendChild(this.deleteHeadshotButton);
49
+ }
50
+ };
51
+ this.handleDeleteHeadshot = () => {
52
+ const { state, dispatch } = this.view;
53
+ const { tr } = state;
54
+ const pos = this.getPos();
55
+ tr.delete(pos, pos + this.node.nodeSize);
56
+ this.view.focus();
57
+ const $pos = tr.doc.resolve(pos);
58
+ if ($pos.node().nodeSize > 2) {
59
+ tr.setSelection(prosemirror_state_1.TextSelection.near(tr.doc.resolve($pos.start()))).scrollIntoView();
60
+ }
61
+ dispatch(tr);
62
+ };
63
+ }
64
+ initialise() {
65
+ this.createElement();
66
+ this.updateContents();
67
+ }
68
+ destroy() {
69
+ this.deleteHeadshotButton?.removeEventListener('click', this.handleDeleteHeadshot);
70
+ super.destroy();
71
+ }
72
+ }
73
+ exports.HeadshotElement = HeadshotElement;
74
+ exports.default = (0, creators_1.createNodeView)(HeadshotElement);
@@ -0,0 +1,20 @@
1
+ "use strict";
2
+ /*!
3
+ * © 2026 Atypon Systems LLC
4
+ *
5
+ * Licensed under the Apache License, Version 2.0 (the "License");
6
+ * you may not use this file except in compliance with the License.
7
+ * You may obtain a copy of the License at
8
+ *
9
+ * http://www.apache.org/licenses/LICENSE-2.0
10
+ *
11
+ * Unless required by applicable law or agreed to in writing, software
12
+ * distributed under the License is distributed on an "AS IS" BASIS,
13
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14
+ * See the License for the specific language governing permissions and
15
+ * limitations under the License.
16
+ */
17
+ Object.defineProperty(exports, "__esModule", { value: true });
18
+ const creators_1 = require("./creators");
19
+ const headshot_element_1 = require("./headshot_element");
20
+ exports.default = (0, creators_1.createEditableNodeView)(headshot_element_1.HeadshotElement);
@@ -0,0 +1,82 @@
1
+ "use strict";
2
+ /*!
3
+ * © 2026 Atypon Systems LLC
4
+ *
5
+ * Licensed under the Apache License, Version 2.0 (the "License");
6
+ * you may not use this file except in compliance with the License.
7
+ * You may obtain a copy of the License at
8
+ *
9
+ * http://www.apache.org/licenses/LICENSE-2.0
10
+ *
11
+ * Unless required by applicable law or agreed to in writing, software
12
+ * distributed under the License is distributed on an "AS IS" BASIS,
13
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14
+ * See the License for the specific language governing permissions and
15
+ * limitations under the License.
16
+ */
17
+ var __importDefault = (this && this.__importDefault) || function (mod) {
18
+ return (mod && mod.__esModule) ? mod : { "default": mod };
19
+ };
20
+ Object.defineProperty(exports, "__esModule", { value: true });
21
+ exports.HeadshotGridView = void 0;
22
+ const transform_1 = require("@manuscripts/transform");
23
+ const prosemirror_state_1 = require("prosemirror-state");
24
+ const icons_1 = require("../icons");
25
+ const navigation_utils_1 = require("../lib/navigation-utils");
26
+ const block_view_1 = __importDefault(require("./block_view"));
27
+ const creators_1 = require("./creators");
28
+ class HeadshotGridView extends block_view_1.default {
29
+ constructor() {
30
+ super(...arguments);
31
+ this.elementType = 'div';
32
+ this.createElement = () => {
33
+ this.container = document.createElement('div');
34
+ this.container.classList.add('block', 'headshot-grid-container');
35
+ this.dom.appendChild(this.container);
36
+ this.contentDOM = document.createElement('div');
37
+ this.contentDOM.classList.add('headshot-grid-block');
38
+ this.contentDOM.setAttribute('id', this.node.attrs.id);
39
+ this.removeKeydownListener = (0, navigation_utils_1.createKeyboardInteraction)({
40
+ container: this.contentDOM,
41
+ navigation: {
42
+ arrowKeys: { forward: 'ArrowDown', backward: 'ArrowUp' },
43
+ getItems: () => [...(this.contentDOM?.children || [])],
44
+ },
45
+ });
46
+ this.container.appendChild(this.contentDOM);
47
+ const can = this.props.getCapabilities();
48
+ if (can.editArticle) {
49
+ this.addHeadshotButton = document.createElement('button');
50
+ this.addHeadshotButton.classList.add('add-headshot-element-button');
51
+ this.addHeadshotButton.setAttribute('data-cy', 'headshot-add');
52
+ this.addHeadshotButton.contentEditable = 'false';
53
+ this.addHeadshotButton.innerHTML = icons_1.addAuthorIcon;
54
+ const buttonText = document.createElement('span');
55
+ buttonText.classList.add('add-headshot-element-text');
56
+ buttonText.innerText = 'Add Headshot';
57
+ this.addHeadshotButton.appendChild(buttonText);
58
+ this.addHeadshotButton.addEventListener('click', this.handleAddHeadshot);
59
+ this.addHeadshotButton.addEventListener('keydown', (0, navigation_utils_1.handleEnterKey)(this.handleAddHeadshot));
60
+ this.container.appendChild(this.addHeadshotButton);
61
+ }
62
+ this.dom.appendChild(this.container);
63
+ };
64
+ this.handleAddHeadshot = () => {
65
+ const { state, dispatch } = this.view;
66
+ const { tr } = state;
67
+ const headshotElementNode = transform_1.schema.nodes.headshot_element.createAndFill();
68
+ const insertPos = this.getPos() + 1;
69
+ tr.insert(insertPos, headshotElementNode);
70
+ this.view.focus();
71
+ tr.setSelection(prosemirror_state_1.TextSelection.create(tr.doc, insertPos));
72
+ dispatch(tr.scrollIntoView());
73
+ };
74
+ }
75
+ destroy() {
76
+ this.addHeadshotButton?.removeEventListener('click', this.handleAddHeadshot);
77
+ this.removeKeydownListener?.();
78
+ super.destroy();
79
+ }
80
+ }
81
+ exports.HeadshotGridView = HeadshotGridView;
82
+ exports.default = (0, creators_1.createNodeView)(HeadshotGridView);
@@ -0,0 +1,21 @@
1
+ "use strict";
2
+ /*!
3
+ * © 2026 Atypon Systems LLC
4
+ *
5
+ * Licensed under the Apache License, Version 2.0 (the "License");
6
+ * you may not use this file except in compliance with the License.
7
+ * You may obtain a copy of the License at
8
+ *
9
+ * http://www.apache.org/licenses/LICENSE-2.0
10
+ *
11
+ * Unless required by applicable law or agreed to in writing, software
12
+ * distributed under the License is distributed on an "AS IS" BASIS,
13
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14
+ * See the License for the specific language governing permissions and
15
+ * limitations under the License.
16
+ */
17
+ Object.defineProperty(exports, "__esModule", { value: true });
18
+ const creators_1 = require("./creators");
19
+ const editable_block_1 = require("./editable_block");
20
+ const headshot_grid_1 = require("./headshot_grid");
21
+ exports.default = (0, creators_1.createEditableNodeView)((0, editable_block_1.EditableBlock)(headshot_grid_1.HeadshotGridView));
@@ -0,0 +1,79 @@
1
+ "use strict";
2
+ /*!
3
+ * © 2026 Atypon Systems LLC
4
+ *
5
+ * Licensed under the Apache License, Version 2.0 (the "License");
6
+ * you may not use this file except in compliance with the License.
7
+ * You may obtain a copy of the License at
8
+ *
9
+ * http://www.apache.org/licenses/LICENSE-2.0
10
+ *
11
+ * Unless required by applicable law or agreed to in writing, software
12
+ * distributed under the License is distributed on an "AS IS" BASIS,
13
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14
+ * See the License for the specific language governing permissions and
15
+ * limitations under the License.
16
+ */
17
+ Object.defineProperty(exports, "__esModule", { value: true });
18
+ exports.HeadshotImageEditableView = void 0;
19
+ const track_changes_plugin_1 = require("@manuscripts/track-changes-plugin");
20
+ const icons_1 = require("../icons");
21
+ const navigation_utils_1 = require("../lib/navigation-utils");
22
+ const creators_1 = require("./creators");
23
+ const figure_editable_1 = require("./figure_editable");
24
+ class HeadshotImageEditableView extends figure_editable_1.FigureEditableView {
25
+ constructor() {
26
+ super(...arguments);
27
+ this.ignoreMutation = () => true;
28
+ this.createPlaceholder = () => {
29
+ const element = document.createElement('div');
30
+ element.classList.add('figure', 'placeholder');
31
+ element.tabIndex = 0;
32
+ const instructions = document.createElement('div');
33
+ instructions.classList.add('instructions');
34
+ instructions.innerHTML = `${icons_1.cameraIcon}<div>Upload<br>photo</div>`;
35
+ element.appendChild(instructions);
36
+ return element;
37
+ };
38
+ this.handleDetachImage = () => {
39
+ const { state, dispatch } = this.view;
40
+ const pos = this.getPos();
41
+ dispatch(state.tr.delete(pos, pos + this.node.nodeSize));
42
+ };
43
+ }
44
+ createDOM() {
45
+ this.dom = document.createElement('figure');
46
+ this.container = document.createElement('div');
47
+ this.container.className = 'headshot-figure';
48
+ this.container.contentEditable = 'false';
49
+ this.dom.appendChild(this.container);
50
+ }
51
+ addTools() {
52
+ const src = this.node.attrs.src;
53
+ const files = this.props.getFiles();
54
+ const file = src && files.filter((f) => f.id === src)[0];
55
+ const link = file && this.props.fileManagement.previewLink(file);
56
+ const can = this.props.getCapabilities();
57
+ if (can.detachFile && link) {
58
+ this.detachImageButton = document.createElement('button');
59
+ this.detachImageButton.innerHTML = icons_1.plusIcon;
60
+ this.detachImageButton.classList.add('headshot-remove-button');
61
+ this.detachImageButton.setAttribute('data-cy', 'headshot-image-detach');
62
+ this.detachImageButton.contentEditable = 'false';
63
+ this.detachImageButton.addEventListener('click', this.handleDetachImage);
64
+ this.detachImageButton.addEventListener('keydown', (0, navigation_utils_1.handleEnterKey)(this.handleDetachImage));
65
+ this.container.appendChild(this.detachImageButton);
66
+ }
67
+ }
68
+ updateContents() {
69
+ super.updateContents();
70
+ (0, track_changes_plugin_1.addTrackChangesAttributes)(this.node.attrs, this.dom);
71
+ (0, track_changes_plugin_1.addTrackChangesClassNames)(this.node.attrs, this.dom);
72
+ }
73
+ destroy() {
74
+ this.detachImageButton?.removeEventListener('click', this.handleDetachImage);
75
+ super.destroy();
76
+ }
77
+ }
78
+ exports.HeadshotImageEditableView = HeadshotImageEditableView;
79
+ exports.default = (0, creators_1.createEditableNodeView)(HeadshotImageEditableView);
@@ -32,7 +32,6 @@ class SectionTitleView extends block_view_1.default {
32
32
  transform_1.schema.nodes.bibliography_section,
33
33
  transform_1.schema.nodes.footnotes_section,
34
34
  transform_1.schema.nodes.graphical_abstract_section,
35
- transform_1.schema.nodes.trans_graphical_abstract,
36
35
  transform_1.schema.nodes.supplements,
37
36
  ];
38
37
  this.createElement = () => {
@@ -567,6 +567,24 @@ export const insertBoxElement = (state, dispatch) => {
567
567
  }
568
568
  return true;
569
569
  };
570
+ export const insertHeadshotGrid = (state, dispatch) => {
571
+ const selection = state.selection;
572
+ const { nodes } = schema;
573
+ const isBody = hasParentNodeOfType(nodes.body)(selection);
574
+ if (!isBody) {
575
+ return false;
576
+ }
577
+ const position = findBlockInsertPosition(state);
578
+ if (position && dispatch) {
579
+ const headshotElement = schema.nodes.headshot_element.createAndFill();
580
+ const node = nodes.headshot_grid.create({}, headshotElement);
581
+ const tr = state.tr.insert(position, node);
582
+ const headshotNamePosition = position + 2;
583
+ tr.setSelection(TextSelection.create(tr.doc, headshotNamePosition));
584
+ dispatch(tr.scrollIntoView());
585
+ }
586
+ return true;
587
+ };
570
588
  export const insertSection = (subsection = false) => (state, dispatch, view) => {
571
589
  const { nodes } = schema;
572
590
  const $pos = state.selection.$from;
@@ -920,7 +938,7 @@ export const insertTransGraphicalAbstract = (category, insertAfterPos) => (state
920
938
  lang,
921
939
  category: category.id,
922
940
  }, [
923
- schema.nodes.section_title.create({}, schema.text(category.titles[0])),
941
+ schema.nodes.section_title.create(),
924
942
  createAndFillFigureElement(state),
925
943
  ]);
926
944
  const tr = state.tr.insert(pos, node);
@@ -26,6 +26,9 @@ import footnote from '../views/footnote';
26
26
  import footnotesElement from '../views/footnotes_element';
27
27
  import generalTableFootnote from '../views/general_table_footnote';
28
28
  import heroImage from '../views/hero_image_editable';
29
+ import headshotGrid from '../views/headshot_grid_editable';
30
+ import headshotElement from '../views/headshot_element';
31
+ import headshotImage from '../views/headshot_image_editable';
29
32
  import imageElement from '../views/image_element_editable';
30
33
  import inlineEquation from '../views/inline_equation_editable';
31
34
  import inlineFootnote from '../views/inline_footnote_editable';
@@ -106,6 +109,9 @@ export default (props, dispatch) => {
106
109
  long_desc: accessibilityElement(props, dispatch),
107
110
  alt_text: accessibilityElement(props, dispatch),
108
111
  hero_image: heroImage(props, dispatch),
112
+ headshot_grid: headshotGrid(props, dispatch),
113
+ headshot_element: headshotElement(props, dispatch),
114
+ headshot_image: headshotImage(props, dispatch),
109
115
  abstracts: abstracts(props),
110
116
  trans_abstract: transAbstract(props),
111
117
  trans_graphical_abstract: transGraphicalAbstract(props),
package/dist/es/icons.js CHANGED
@@ -1,4 +1,4 @@
1
- import { AddAuthorIcon, AlertIcon, ArrowDownCircleIcon, ArrowUpIcon, DeleteIcon, DraggableIcon, EditIcon, FileCorruptedIcon, FileMainDocumentIcon, ImageDefaultIcon, ImageLeftIcon, ImageRightIcon, LinkIcon, LockIcon, ORCIDIcon as ORCID, PlusIcon, ScrollIcon, SectionCategoryIcon, TickIcon, TranslateIcon, } from '@manuscripts/style-guide';
1
+ import { AddAuthorIcon, AlertIcon, ArrowDownCircleIcon, ArrowUpIcon, CameraIcon, DeleteIcon, DraggableIcon, EditIcon, FileCorruptedIcon, FileMainDocumentIcon, ImageDefaultIcon, ImageLeftIcon, ImageRightIcon, LinkIcon, LockIcon, ORCIDIcon as ORCID, PlusIcon, ScrollIcon, SectionCategoryIcon, TickIcon, TranslateIcon, } from '@manuscripts/style-guide';
2
2
  import { createElement } from 'react';
3
3
  import { renderToStaticMarkup } from 'react-dom/server';
4
4
  const renderIcon = (c) => renderToStaticMarkup(createElement(c));
@@ -6,6 +6,7 @@ export const addAuthorIcon = renderIcon(AddAuthorIcon);
6
6
  export const arrowDown = renderIcon(ArrowDownCircleIcon);
7
7
  export const arrowUp = renderIcon(ArrowUpIcon);
8
8
  export const alertIcon = renderIcon(AlertIcon);
9
+ export const cameraIcon = renderIcon(CameraIcon);
9
10
  export const deleteIcon = renderIcon(DeleteIcon);
10
11
  export const editIcon = renderIcon(EditIcon);
11
12
  export const sectionCategoryIcon = renderIcon(SectionCategoryIcon);
@@ -9,6 +9,7 @@ const figureTypes = [
9
9
  schema.nodes.figure_element,
10
10
  schema.nodes.image_element,
11
11
  schema.nodes.hero_image,
12
+ schema.nodes.headshot_grid,
12
13
  schema.nodes.embed,
13
14
  ];
14
15
  export function memoGroupFiles() {
@@ -52,7 +53,11 @@ export const groupFiles = (doc, files) => {
52
53
  }
53
54
  }
54
55
  else {
55
- for (const figure of findChildrenByType(node, schema.nodes.figure)) {
56
+ const descend = node.type === schema.nodes.headshot_grid;
57
+ const figureNodeType = node.type === schema.nodes.headshot_grid
58
+ ? schema.nodes.headshot_image
59
+ : schema.nodes.figure;
60
+ for (const figure of findChildrenByType(node, figureNodeType, descend)) {
56
61
  if (isHidden(figure.node)) {
57
62
  continue;
58
63
  }
package/dist/es/menus.js CHANGED
@@ -16,7 +16,7 @@
16
16
  import { getGroupCategories, schema, } from '@manuscripts/transform';
17
17
  import { toggleMark } from 'prosemirror-commands';
18
18
  import { redo, undo } from 'prosemirror-history';
19
- import { activateSearchReplace, addInlineComment, blockActive, canInsert, copySelection, insertAbstractSection, insertAffiliation, insertAward, insertBackmatterSection, insertBlock, insertBoxElement, insertContributors, insertCrossReference, insertEmbed, insertGraphicalAbstract, insertHeroImage, insertInlineCitation, insertInlineEquation, insertInlineFootnote, insertKeywords, insertLink, insertList, insertSection, markActive, paste, } from './commands';
19
+ import { activateSearchReplace, addInlineComment, blockActive, canInsert, copySelection, insertAbstractSection, insertAffiliation, insertAward, insertBackmatterSection, insertBlock, insertBoxElement, insertContributors, insertCrossReference, insertEmbed, insertGraphicalAbstract, insertHeadshotGrid, insertHeroImage, insertInlineCitation, insertInlineEquation, insertInlineFootnote, insertKeywords, insertLink, insertList, insertSection, markActive, paste, } from './commands';
20
20
  import { openInsertTableDialog } from './components/toolbar/InsertTableDialog';
21
21
  import { ListMenuItem } from './components/toolbar/ListMenuItem';
22
22
  import { openInsertSpecialCharacterDialog } from './components/views/InsertSpecialCharacter';
@@ -269,6 +269,14 @@ export const getEditorMenus = (editor) => {
269
269
  run: doCommand(insertBoxElement),
270
270
  isHidden: !templateAllows(state, schema.nodes.box_element),
271
271
  },
272
+ {
273
+ id: 'insert-headshot-grid',
274
+ label: 'Headshot Panel',
275
+ isEnabled: isEditAllowed(state) &&
276
+ isCommandValid(canInsert(schema.nodes.headshot_grid)),
277
+ run: doCommand(insertHeadshotGrid),
278
+ isHidden: !templateAllows(state, schema.nodes.headshot_grid),
279
+ },
272
280
  {
273
281
  role: 'separator',
274
282
  },
@@ -13,10 +13,12 @@
13
13
  * See the License for the specific language governing permissions and
14
14
  * limitations under the License.
15
15
  */
16
- import { FileDocumentIcon, SupplementsIcon, FileImageIcon, OutlineBlockQuoteIcon, OutlineEmbedIcon, OutlineEquationIcon, OutlineFigureIcon, OutlineManuscriptIcon, OutlineOrderedListIcon, OutlineParagraphIcon, OutlinePullQuoteIcon, OutlineSectionIcon, OutlineTableIcon, OutlineUnorderedListIcon, } from '@manuscripts/style-guide';
16
+ import { AvatarIcon, FileDocumentIcon, SupplementsIcon, FileImageIcon, FileHeadshotGridIcon, OutlineBlockQuoteIcon, OutlineEmbedIcon, OutlineEquationIcon, OutlineFigureIcon, OutlineManuscriptIcon, OutlineOrderedListIcon, OutlineParagraphIcon, OutlinePullQuoteIcon, OutlineSectionIcon, OutlineTableIcon, OutlineUnorderedListIcon, } from '@manuscripts/style-guide';
17
17
  import { schema } from '@manuscripts/transform';
18
18
  import React from 'react';
19
19
  const { nodes } = schema;
20
+ const OutlineHeadshotGridIcon = () => (React.createElement(FileHeadshotGridIcon, { width: "12", height: "12" }));
21
+ const OutlineHeadshotElementIcon = () => (React.createElement(AvatarIcon, { width: "16", height: "16" }));
20
22
  const OutlineImageIcon = () => (React.createElement(FileImageIcon, { width: "11", height: "14" }));
21
23
  const OutlineSupplementsIcon = () => (React.createElement(SupplementsIcon, { width: "11", height: "14" }));
22
24
  const OutlineMainDocumentIcon = () => (React.createElement(FileDocumentIcon, { width: "11", height: "14" }));
@@ -38,6 +40,8 @@ const icons = new Map([
38
40
  [nodes.hero_image, OutlineImageIcon],
39
41
  [nodes.supplements, OutlineSupplementsIcon],
40
42
  [nodes.attachments, OutlineMainDocumentIcon],
43
+ [nodes.headshot_grid, OutlineHeadshotGridIcon],
44
+ [nodes.headshot_element, OutlineHeadshotElementIcon],
41
45
  ]);
42
46
  export const nodeTypeIcon = (nodeType, listType) => {
43
47
  if (nodeType === schema.nodes.list) {
@@ -27,7 +27,8 @@ const isSelectionWithin = (node, pos, selection) => {
27
27
  const buildExpandButtonDecorations = (doc) => {
28
28
  const decorations = [];
29
29
  doc.descendants((node, pos) => {
30
- if (node.type.spec.content?.includes('alt_text')) {
30
+ if (node.type !== schema.nodes.headshot_element &&
31
+ node.type.spec.content?.includes('alt_text')) {
31
32
  decorations.push(Decoration.widget(pos + node.nodeSize - 1, (view) => {
32
33
  const container = document.createElement('div');
33
34
  container.className =
@@ -1,2 +1,2 @@
1
- export const VERSION = '3.13.9';
1
+ export const VERSION = '3.13.11';
2
2
  export const MATHJAX_VERSION = '3.2.2';