@manuscripts/body-editor 3.12.17 → 3.12.20

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 (57) hide show
  1. package/dist/cjs/commands.js +16 -24
  2. package/dist/cjs/components/affiliations/AffiliationForm.js +5 -6
  3. package/dist/cjs/components/affiliations/AffiliationsModal.js +21 -57
  4. package/dist/cjs/components/affiliations/AffiliationsPanel.js +22 -0
  5. package/dist/cjs/components/authors/AuthorDetailsForm.js +3 -4
  6. package/dist/cjs/components/authors/AuthorsModal.js +15 -48
  7. package/dist/cjs/components/authors/AuthorsPanel.js +18 -0
  8. package/dist/cjs/components/authors/useManageAffiliations.js +6 -4
  9. package/dist/cjs/components/authors-affiliations/AuthorsAndAffiliationsModals.js +134 -0
  10. package/dist/cjs/components/authors-affiliations/GenericPanel.js +136 -0
  11. package/dist/cjs/components/form/ModalFormActions.js +11 -5
  12. package/dist/cjs/keys/title.js +24 -10
  13. package/dist/cjs/lib/__tests__/plugins.test.js +2 -2
  14. package/dist/cjs/lib/context-menu.js +8 -9
  15. package/dist/cjs/plugins/objects.js +24 -19
  16. package/dist/cjs/versions.js +1 -1
  17. package/dist/cjs/views/affiliations.js +5 -11
  18. package/dist/cjs/views/caption.js +1 -1
  19. package/dist/cjs/views/contributors.js +4 -7
  20. package/dist/cjs/views/figure.js +0 -1
  21. package/dist/es/commands.js +16 -24
  22. package/dist/es/components/affiliations/AffiliationForm.js +5 -6
  23. package/dist/es/components/affiliations/AffiliationsModal.js +21 -53
  24. package/dist/es/components/affiliations/AffiliationsPanel.js +15 -0
  25. package/dist/es/components/authors/AuthorDetailsForm.js +3 -4
  26. package/dist/es/components/authors/AuthorsModal.js +15 -45
  27. package/dist/es/components/authors/AuthorsPanel.js +11 -0
  28. package/dist/es/components/authors/useManageAffiliations.js +7 -5
  29. package/dist/es/components/authors-affiliations/AuthorsAndAffiliationsModals.js +93 -0
  30. package/dist/es/components/authors-affiliations/GenericPanel.js +94 -0
  31. package/dist/es/components/form/ModalFormActions.js +11 -5
  32. package/dist/es/keys/title.js +24 -10
  33. package/dist/es/lib/__tests__/plugins.test.js +2 -2
  34. package/dist/es/lib/context-menu.js +8 -9
  35. package/dist/es/plugins/objects.js +25 -20
  36. package/dist/es/versions.js +1 -1
  37. package/dist/es/views/affiliations.js +5 -11
  38. package/dist/es/views/caption.js +1 -1
  39. package/dist/es/views/contributors.js +5 -8
  40. package/dist/es/views/figure.js +0 -1
  41. package/dist/types/components/affiliations/AffiliationForm.d.ts +1 -0
  42. package/dist/types/components/affiliations/AffiliationsModal.d.ts +2 -5
  43. package/dist/types/components/affiliations/AffiliationsPanel.d.ts +11 -0
  44. package/dist/types/components/authors/AuthorDetailsForm.d.ts +1 -0
  45. package/dist/types/components/authors/AuthorsModal.d.ts +2 -4
  46. package/dist/types/components/authors/AuthorsPanel.d.ts +13 -0
  47. package/dist/types/components/authors/useManageAffiliations.d.ts +0 -2
  48. package/dist/types/components/authors-affiliations/AuthorsAndAffiliationsModals.d.ts +29 -0
  49. package/dist/types/components/authors-affiliations/GenericPanel.d.ts +48 -0
  50. package/dist/types/components/form/ModalFormActions.d.ts +1 -0
  51. package/dist/types/versions.d.ts +1 -1
  52. package/package.json +3 -3
  53. package/styles/AdvancedEditor.css +18 -48
  54. package/styles/Editor.css +28 -63
  55. package/dist/cjs/components/authors/AffiliationDrawer.js +0 -24
  56. package/dist/es/components/authors/AffiliationDrawer.js +0 -17
  57. package/dist/types/components/authors/AffiliationDrawer.d.ts +0 -12
@@ -0,0 +1,94 @@
1
+ /*!
2
+ * © 2026 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 { AddedIcon, AddIcon, DrawerIcon, DrawerItemLabel, DrawerItemMeta, DrawerItemsList, DrawerLabelContainer, DrawerListItem, IconButton, PlusIcon, } from '@manuscripts/style-guide';
17
+ import React, { useMemo } from 'react';
18
+ import styled from 'styled-components';
19
+ export const ListItems = DrawerItemsList;
20
+ const Panel = styled.div `
21
+ display: flex;
22
+ flex-direction: column;
23
+ `;
24
+ const PanelHeader = styled.div `
25
+ display: flex;
26
+ align-items: flex-start;
27
+ padding: ${(props) => props.theme.grid.unit * 2}px
28
+ ${(props) => props.theme.grid.unit * 4}px;
29
+ `;
30
+ const PanelTitle = styled.span `
31
+ font-family: ${(props) => props.theme.font.family.sans};
32
+ font-size: 18px;
33
+ line-height: 24px;
34
+ letter-spacing: -0.37px;
35
+ color: ${(props) => props.theme.colors.text.secondary};
36
+ `;
37
+ const PanelCreateButton = styled(IconButton) `
38
+ color: #0d79d0;
39
+ font-size: 14px;
40
+ font-weight: 400;
41
+ font-style: normal;
42
+ line-height: 1;
43
+ width: auto;
44
+ height: 24px;
45
+ margin-left: auto;
46
+ svg {
47
+ margin-right: 4px;
48
+ }
49
+ `;
50
+ const PanelEmpty = styled.div `
51
+ display: flex;
52
+ flex-direction: column;
53
+ align-items: center;
54
+ justify-content: center;
55
+ gap: 16px;
56
+ padding: ${(props) => props.theme.grid.unit * 20}px
57
+ ${(props) => props.theme.grid.unit * 4}px;
58
+ `;
59
+ const PanelEmptyIcon = styled.div `
60
+ width: 120px;
61
+ height: 120px;
62
+ flex-shrink: 0;
63
+ display: flex;
64
+ align-items: center;
65
+ justify-content: center;
66
+ svg {
67
+ width: 100%;
68
+ height: 100%;
69
+ }
70
+ `;
71
+ const PanelEmptyText = styled.p `
72
+ margin: 0;
73
+ font-size: 18px;
74
+ line-height: 24px;
75
+ text-align: center;
76
+ letter-spacing: -0.369px;
77
+ `;
78
+ export const GenericPanel = ({ title, createLabel, onCreate, createDataCy, emptyDataCy, isEmpty, emptyIcon, emptyMessage, children, }) => (React.createElement(Panel, null,
79
+ React.createElement(PanelHeader, null,
80
+ React.createElement(PanelTitle, null, title),
81
+ React.createElement(PanelCreateButton, { onClick: onCreate, "data-cy": createDataCy },
82
+ React.createElement(PlusIcon, null),
83
+ createLabel)),
84
+ isEmpty ? (React.createElement(PanelEmpty, { "data-cy": emptyDataCy },
85
+ React.createElement(PanelEmptyIcon, { "aria-hidden": true }, emptyIcon),
86
+ React.createElement(PanelEmptyText, null, emptyMessage))) : (children)));
87
+ export const ListItem = ({ selected, onClick, primary, secondary, }) => (React.createElement(DrawerListItem, { "data-cy": "item", selected: selected, onClick: onClick },
88
+ React.createElement(DrawerIcon, null, selected ? (React.createElement(AddedIcon, { width: 22, height: 22 })) : (React.createElement(AddIcon, { width: 22, height: 22 }))),
89
+ React.createElement(DrawerLabelContainer, null,
90
+ React.createElement(DrawerItemLabel, null, primary),
91
+ secondary != null && secondary !== '' ? (React.createElement(DrawerItemMeta, null, secondary)) : null)));
92
+ export function useListSelectedIds(selectedItems) {
93
+ return useMemo(() => new Set(selectedItems.map((x) => x.id)), [selectedItems]);
94
+ }
@@ -29,14 +29,20 @@ const StyledIconButton = styled(IconButton) `
29
29
  margin-right: 4px;
30
30
  }
31
31
  `;
32
- export const ModalFormActions = ({ type, form, onDelete, showingDeleteDialog, showDeleteDialog, newEntity, isDisableSave, }) => {
32
+ export const ModalFormActions = ({ type, form, onDelete, showingDeleteDialog, showDeleteDialog, newEntity, isDisableSave, onSubmitForm, }) => {
33
+ const saveButton = onSubmitForm ? (React.createElement(StyledIconButton, { disabled: isDisableSave, type: "button", onClick: () => {
34
+ if (!isDisableSave) {
35
+ void onSubmitForm();
36
+ }
37
+ } },
38
+ React.createElement(PlusIcon, null),
39
+ newEntity ? 'Save Details' : 'Update Details')) : (React.createElement(StyledIconButton, { disabled: isDisableSave, type: "submit", form: form },
40
+ React.createElement(PlusIcon, null),
41
+ newEntity ? 'Save Details' : 'Update Details'));
33
42
  return (React.createElement(ActionsContainer, { "data-cy": `${type}-action` },
34
43
  React.createElement(ConfirmationDialog, { isOpen: showingDeleteDialog, onPrimary: () => {
35
44
  onDelete();
36
45
  showDeleteDialog();
37
46
  }, onSecondary: showDeleteDialog, type: DialogType.DELETE, entityType: type }),
38
- React.createElement(StyledButtonGroup, null,
39
- React.createElement(StyledIconButton, { disabled: isDisableSave, type: "submit", form: form },
40
- React.createElement(PlusIcon, null),
41
- newEntity ? 'Save Details' : 'Update Details'))));
47
+ React.createElement(StyledButtonGroup, null, saveButton)));
42
48
  };
@@ -62,9 +62,11 @@ const leaveTitle = (state, dispatch, view) => {
62
62
  }
63
63
  return true;
64
64
  };
65
- const leaveFigcaption = (state) => {
65
+ const leaveCaption = (state) => {
66
66
  const { selection: { $anchor }, } = state;
67
- return $anchor.parent.type === $anchor.parent.type.schema.nodes.caption_title;
67
+ return ($anchor.parent.type === $anchor.parent.type.schema.nodes.caption_title ||
68
+ $anchor.node($anchor.depth - 1)?.type ===
69
+ $anchor.parent.type.schema.nodes.caption);
68
70
  };
69
71
  const protectTitles = (state, dispatch, view) => {
70
72
  const { selection } = state;
@@ -95,25 +97,37 @@ export const protectReferencesTitle = (state) => {
95
97
  };
96
98
  const protectCaption = (state, dispatch) => {
97
99
  const { selection: { $anchor }, } = state;
98
- if (dispatch &&
99
- ($anchor.parent.type === $anchor.parent.type.schema.nodes.caption_title ||
100
- $anchor.parent.type === $anchor.parent.type.schema.nodes.caption) &&
100
+ let nodeType = undefined;
101
+ if ($anchor.node($anchor.depth - 1)?.type ===
102
+ $anchor.parent.type.schema.nodes.caption &&
103
+ $anchor.node($anchor.depth).content.size === 1) {
104
+ nodeType = $anchor.node($anchor.depth - 1).type;
105
+ }
106
+ else if ($anchor.parent.type === $anchor.parent.type.schema.nodes.caption_title &&
101
107
  $anchor.parent.content.size === 1) {
102
- const slice = new Slice(Fragment.from([state.schema.nodes.caption_title.create()]), 1, 1);
108
+ nodeType = $anchor.parent.type;
109
+ }
110
+ if (dispatch && nodeType) {
111
+ const slice = new Slice(Fragment.from([nodeType.create()]), 1, 1);
103
112
  const tr = state.tr.replace($anchor.pos - 1, $anchor.pos, slice);
104
113
  dispatch(tr);
105
114
  return true;
106
115
  }
107
116
  return false;
108
117
  };
109
- const keepCaption = (state) => {
118
+ const keepCaption = (state, dispatch) => {
110
119
  const { selection: { $anchor }, } = state;
111
- return ($anchor.parent.type === $anchor.parent.type.schema.nodes.caption_title &&
112
- $anchor.parent.content.size === 0);
120
+ if (dispatch &&
121
+ $anchor.parent.type === $anchor.parent.type.schema.nodes.caption_title &&
122
+ $anchor.parent.content.size === 1) {
123
+ dispatch(state.tr.delete($anchor.pos, $anchor.pos + 1));
124
+ return true;
125
+ }
126
+ return false;
113
127
  };
114
128
  const titleKeymap = {
115
129
  Backspace: chainCommands(protectTitles, protectReferencesTitle, protectCaption),
116
- Enter: chainCommands(autoComplete, leaveTitle, leaveFigcaption),
130
+ Enter: chainCommands(autoComplete, leaveTitle, leaveCaption),
117
131
  Delete: chainCommands(keepCaption, protectReferencesTitle),
118
132
  };
119
133
  export default titleKeymap;
@@ -94,7 +94,7 @@ describe('editor view', () => {
94
94
  expect(figureElement.childCount).toBe(5);
95
95
  expect(figureElement.type).toBe(schema.nodes.figure_element);
96
96
  expect(figureElement.content.child(0).type).toBe(schema.nodes.figure);
97
- expect(figureElement.content.child(1).type).toBe(schema.nodes.figcaption);
97
+ expect(figureElement.content.child(1).type).toBe(schema.nodes.caption);
98
98
  const sectionWithTable = view.state.doc.child(2).child(8);
99
99
  expect(sectionWithTable.attrs.id).toBe('section-with-table');
100
100
  expect(sectionWithTable.childCount).toBe(2);
@@ -102,7 +102,7 @@ describe('editor view', () => {
102
102
  const tableElement = sectionWithTable.content.child(1);
103
103
  expect(tableElement.childCount).toBe(5);
104
104
  expect(tableElement.type).toBe(tableElement.type.schema.nodes.table_element);
105
- expect(tableElement.content.child(0).type).toBe(tableElement.type.schema.nodes.figcaption);
105
+ expect(tableElement.content.child(0).type).toBe(tableElement.type.schema.nodes.caption_title);
106
106
  expect(tableElement.content.child(1).type).toBe(tableElement.type.schema.nodes.table);
107
107
  });
108
108
  });
@@ -254,19 +254,18 @@ export class ContextMenu {
254
254
  const tr = this.view.state.tr;
255
255
  const boxElementNode = $pos.node($pos.depth - 1);
256
256
  const boxStartPos = $pos.start($pos.depth - 1);
257
- const figcaptions = findChildrenByType(boxElementNode, schema.nodes.figcaption);
258
- const hasLabel = figcaptions.length > 0;
257
+ const captionTitle = findChildrenByType(boxElementNode, schema.nodes.caption_title, false)[0];
258
+ const caption = findChildrenByType(boxElementNode, schema.nodes.caption, false)[0];
259
+ const hasLabel = captionTitle;
259
260
  menu.insertBefore(this.createMenuItem(hasLabel ? 'Delete Label' : 'Add Label', () => {
260
261
  if (hasLabel) {
261
- const figcaptionNode = figcaptions[0].node;
262
- const figcaptionPos = boxStartPos + figcaptions[0].pos;
263
- tr.delete(figcaptionPos, figcaptionPos + figcaptionNode.nodeSize);
262
+ const captionNode = captionTitle.node;
263
+ const captionPos = boxStartPos + captionTitle.pos;
264
+ tr.delete(captionPos, captionPos + captionNode.nodeSize + (caption?.node.nodeSize || 0));
264
265
  }
265
266
  else {
266
- const newFigcaption = schema.nodes.figcaption.create({}, [
267
- schema.nodes.caption_title.create(),
268
- ]);
269
- tr.insert(boxStartPos, newFigcaption);
267
+ const captionTitle = schema.nodes.caption_title.create();
268
+ tr.insert(boxStartPos, captionTitle);
270
269
  }
271
270
  this.view.dispatch(tr);
272
271
  popper.destroy();
@@ -13,9 +13,10 @@
13
13
  * See the License for the specific language governing permissions and
14
14
  * limitations under the License.
15
15
  */
16
- import { buildTargets, isInGraphicalAbstractSection, } from '@manuscripts/transform';
16
+ import { buildTargets, schema, } from '@manuscripts/transform';
17
17
  import { Plugin, PluginKey } from 'prosemirror-state';
18
18
  import { Decoration, DecorationSet } from 'prosemirror-view';
19
+ import { findChildren } from 'prosemirror-utils';
19
20
  import { clear } from '@manuscripts/track-changes-plugin';
20
21
  export const objectsKey = new PluginKey('objects');
21
22
  export default () => {
@@ -38,26 +39,19 @@ export default () => {
38
39
  const { id } = node.attrs;
39
40
  if (id) {
40
41
  const target = targets.get(id);
41
- const resolvedPos = state.doc.resolve(pos);
42
- const isInGraphicalAbstract = isInGraphicalAbstractSection(resolvedPos);
43
- if (target && !isInGraphicalAbstract) {
42
+ if (target) {
44
43
  const labelNode = document.createElement('span');
45
- labelNode.className = 'figure-label';
46
- if (node.type.name === 'image_element') {
47
- labelNode.textContent = target.label;
48
- decorations.push(Decoration.widget(pos + (node.firstChild?.nodeSize || 0) + 1, labelNode));
49
- }
50
- else {
51
- labelNode.textContent = target.label + ':';
52
- node.forEach((child, offset) => {
53
- if (child.type.name === 'figcaption') {
54
- decorations.push(Decoration.widget(pos + 1 + offset + 1, labelNode, {
55
- side: -1,
56
- key: `figure-label-${id}-${target.label}`,
57
- }));
58
- }
59
- });
60
- }
44
+ labelNode.className = 'element-label';
45
+ const caption = findChildren(node, (node) => node.type === schema.nodes.caption ||
46
+ node.type === schema.nodes.caption_title, false)[0];
47
+ const labelPos = getDecorationPos(target, state.doc, pos, caption);
48
+ labelNode.textContent = caption
49
+ ? target.label + ':'
50
+ : target.label;
51
+ decorations.push(Decoration.widget(labelPos, labelNode, {
52
+ side: -1,
53
+ key: `element-label-${id}-${target.label}`,
54
+ }));
61
55
  }
62
56
  }
63
57
  });
@@ -67,3 +61,14 @@ export default () => {
67
61
  },
68
62
  });
69
63
  };
64
+ const getDecorationPos = (target, doc, pos, caption) => {
65
+ const $pos = doc.resolve(pos + (caption?.pos || 1) + 1);
66
+ let targetPos = $pos.pos;
67
+ if (!caption) {
68
+ targetPos = $pos.end();
69
+ }
70
+ else if (!$pos.nodeBefore) {
71
+ targetPos -= 1;
72
+ }
73
+ return targetPos;
74
+ };
@@ -1,2 +1,2 @@
1
- export const VERSION = '3.12.17';
1
+ export const VERSION = '3.12.20';
2
2
  export const MATHJAX_VERSION = '3.2.2';
@@ -17,7 +17,7 @@ import { ContextMenu } from '@manuscripts/style-guide';
17
17
  import { addTrackChangesAttributes, isDeleted, } from '@manuscripts/track-changes-plugin';
18
18
  import { schema } from '@manuscripts/transform';
19
19
  import { NodeSelection } from 'prosemirror-state';
20
- import { AffiliationsModal, handleDeleteAffiliation, handleSaveAffiliation, handleUpdateAuthors, } from '../components/affiliations/AffiliationsModal';
20
+ import { AuthorsAndAffiliationsModals, } from '../components/authors-affiliations/AuthorsAndAffiliationsModals';
21
21
  import { alertIcon } from '../icons';
22
22
  import { affiliationName, } from '../lib/authors';
23
23
  import { handleComment } from '../lib/comments';
@@ -52,22 +52,16 @@ export class AffiliationsView extends BlockView {
52
52
  };
53
53
  this.handleEdit = (id, addNew) => {
54
54
  this.props.popper.destroy();
55
- const contributors = findChildrenAttrsByType(this.view, schema.nodes.contributor);
56
55
  const affiliations = findChildrenAttrsByType(this.view, schema.nodes.affiliation);
57
- const affiliation = id
58
- ? affiliations.filter((a) => a.id === id)[0]
59
- : undefined;
56
+ const affiliation = id ? affiliations.find((a) => a.id === id) : undefined;
60
57
  const componentProps = {
58
+ initialModal: 'affiliations',
59
+ view: this.view,
61
60
  affiliation,
62
- authors: contributors,
63
- affiliations,
64
- onSaveAffiliation: (affiliation) => handleSaveAffiliation(this.view, affiliation, this.getPos()),
65
- onDeleteAffiliation: (affiliation) => handleDeleteAffiliation(this.view, affiliation),
66
- onUpdateAuthors: (authors) => handleUpdateAuthors(this.view, authors),
67
61
  addNewAffiliation: addNew,
68
62
  };
69
63
  this.popper?.remove();
70
- this.popper = ReactSubView(this.props, AffiliationsModal, componentProps, this.node, this.getPos, this.view);
64
+ this.popper = ReactSubView(this.props, AuthorsAndAffiliationsModals, componentProps, this.node, this.getPos, this.view);
71
65
  this.container.appendChild(this.popper);
72
66
  };
73
67
  this.showGroupContextMenu = () => {
@@ -23,7 +23,7 @@ export class CaptionView extends BaseNodeView {
23
23
  };
24
24
  }
25
25
  createDOM() {
26
- this.dom = document.createElement('p');
26
+ this.dom = document.createElement('caption');
27
27
  this.dom.className = 'caption-description placeholder';
28
28
  this.dom.contentEditable = 'true';
29
29
  this.contentDOM = this.dom;
@@ -17,8 +17,8 @@ import { ContextMenu } from '@manuscripts/style-guide';
17
17
  import { addTrackChangesAttributes, isDeleted, } from '@manuscripts/track-changes-plugin';
18
18
  import { schema } from '@manuscripts/transform';
19
19
  import { NodeSelection } from 'prosemirror-state';
20
- import { AuthorsModal, handleDeleteContributor, handleSaveContributor, } from '../components/authors/AuthorsModal';
21
- import { authorComparator, authorLabel, } from '../lib/authors';
20
+ import { AuthorsAndAffiliationsModals, } from '../components/authors-affiliations/AuthorsAndAffiliationsModals';
21
+ import { authorComparator, authorLabel } from '../lib/authors';
22
22
  import { handleComment } from '../lib/comments';
23
23
  import { createKeyboardInteraction } from '../lib/navigation-utils';
24
24
  import { findChildByID, findChildrenAttrsByType } from '../lib/view';
@@ -210,18 +210,15 @@ export class ContributorsView extends BlockView {
210
210
  this.handleEdit = (id, addNew) => {
211
211
  this.props.popper.destroy();
212
212
  const contributors = findChildrenAttrsByType(this.view, schema.nodes.contributor);
213
- const affiliations = findChildrenAttrsByType(this.view, schema.nodes.affiliation);
214
213
  const author = id ? contributors.filter((a) => a.id === id)[0] : undefined;
215
214
  const componentProps = {
215
+ initialModal: 'authors',
216
+ view: this.view,
216
217
  author,
217
- authors: contributors,
218
- affiliations,
219
- onSaveAuthor: (contributor) => handleSaveContributor(this.view, contributor, this.getPos()),
220
- onDeleteAuthor: (contributor) => handleDeleteContributor(this.view, contributor),
221
218
  addNewAuthor: addNew,
222
219
  };
223
220
  this.popper?.remove();
224
- this.popper = ReactSubView(this.props, AuthorsModal, componentProps, this.node, this.getPos, this.view);
221
+ this.popper = ReactSubView(this.props, AuthorsAndAffiliationsModals, componentProps, this.node, this.getPos, this.view);
225
222
  this.container.appendChild(this.popper);
226
223
  };
227
224
  }
@@ -57,7 +57,6 @@ export class FigureView extends BaseNodeView {
57
57
  this.container.contentEditable = 'false';
58
58
  this.dom.appendChild(this.container);
59
59
  this.contentDOM = document.createElement('div');
60
- this.contentDOM.className = 'figure-caption';
61
60
  this.contentDOM.setAttribute('tabindex', '1337');
62
61
  this.dom.appendChild(this.contentDOM);
63
62
  }
@@ -2,6 +2,7 @@ import React from 'react';
2
2
  import { AffiliationAttrs } from '../../lib/authors';
3
3
  export interface FormActions {
4
4
  reset: () => void;
5
+ submitForm: () => Promise<void> | void;
5
6
  }
6
7
  export interface AffiliationFormProps {
7
8
  values: AffiliationAttrs;
@@ -1,6 +1,5 @@
1
1
  import React from 'react';
2
2
  import { AffiliationAttrs, ContributorAttrs } from '../../lib/authors';
3
- import { EditorView } from 'prosemirror-view';
4
3
  export interface AffiliationsModalProps {
5
4
  affiliation?: AffiliationAttrs;
6
5
  authors: ContributorAttrs[];
@@ -9,9 +8,7 @@ export interface AffiliationsModalProps {
9
8
  onDeleteAffiliation: (affiliation: AffiliationAttrs) => void;
10
9
  onUpdateAuthors: (authors: ContributorAttrs[]) => void;
11
10
  addNewAffiliation?: boolean;
11
+ onClose?: () => void;
12
+ onOpenAuthorsModal?: () => void;
12
13
  }
13
14
  export declare const AffiliationsModal: React.FC<AffiliationsModalProps>;
14
- export declare const openAffiliationsModal: (pos: number, view?: EditorView) => void;
15
- export declare const handleSaveAffiliation: (view: EditorView, affiliation: AffiliationAttrs, affiliationsPos: number) => void;
16
- export declare const handleDeleteAffiliation: (view: EditorView, affiliation: AffiliationAttrs) => void;
17
- export declare const handleUpdateAuthors: (view: EditorView, authors: ContributorAttrs[]) => void;
@@ -0,0 +1,11 @@
1
+ import React from 'react';
2
+ import { AffiliationAttrs } from '../../lib/authors';
3
+ export interface AffiliationsPanelProps {
4
+ items: AffiliationAttrs[];
5
+ selectedItems: {
6
+ id: string;
7
+ }[];
8
+ onSelect: (id: string) => void;
9
+ onOpenAffiliationsModal: () => void;
10
+ }
11
+ export declare const AffiliationsPanel: React.FC<AffiliationsPanelProps>;
@@ -18,6 +18,7 @@ import React, { MutableRefObject } from 'react';
18
18
  import { ContributorAttrs } from '../../lib/authors';
19
19
  export interface FormActions {
20
20
  reset: () => void;
21
+ submitForm: () => Promise<void> | void;
21
22
  }
22
23
  interface AuthorDetailsFormProps {
23
24
  values: ContributorAttrs;
@@ -15,7 +15,6 @@
15
15
  */
16
16
  import React from 'react';
17
17
  import { AffiliationAttrs, ContributorAttrs } from '../../lib/authors';
18
- import { EditorView } from 'prosemirror-view';
19
18
  export declare const authorsReducer: (state: ContributorAttrs[], action: import("../../lib/array-reducer").Action<ContributorAttrs>) => ContributorAttrs[];
20
19
  export interface AuthorsModalProps {
21
20
  author?: ContributorAttrs;
@@ -24,8 +23,7 @@ export interface AuthorsModalProps {
24
23
  onSaveAuthor: (author: ContributorAttrs) => void;
25
24
  onDeleteAuthor: (author: ContributorAttrs) => void;
26
25
  addNewAuthor?: boolean;
26
+ onOpenAffiliationsModal?: () => void;
27
+ onClose?: () => void;
27
28
  }
28
29
  export declare const AuthorsModal: React.FC<AuthorsModalProps>;
29
- export declare const openAuthorsModal: (pos: number, view?: EditorView) => void;
30
- export declare const handleSaveContributor: (view: EditorView, contributor: ContributorAttrs, contributorsPos: number) => void;
31
- export declare const handleDeleteContributor: (view: EditorView, contributor: ContributorAttrs) => void;
@@ -0,0 +1,13 @@
1
+ import React from 'react';
2
+ export interface AuthorsPanelProps {
3
+ items: {
4
+ id: string;
5
+ label: string;
6
+ }[];
7
+ selectedItems?: {
8
+ id: string;
9
+ }[];
10
+ onSelect: (id: string) => void;
11
+ onOpenAuthorsModal: () => void;
12
+ }
13
+ export declare const AuthorsPanel: React.FC<AuthorsPanelProps>;
@@ -1,8 +1,6 @@
1
1
  import { AffiliationAttrs, ContributorAttrs } from '../../lib/authors';
2
2
  export declare const affiliationsReducer: (state: AffiliationAttrs[], action: import("../../lib/array-reducer").Action<AffiliationAttrs>) => AffiliationAttrs[];
3
3
  export declare const useManageAffiliations: (selection: ContributorAttrs | undefined, $affiliations: AffiliationAttrs[]) => {
4
- showAffiliationDrawer: boolean;
5
- setShowAffiliationDrawer: import("react").Dispatch<import("react").SetStateAction<boolean>>;
6
4
  selectedAffiliations: {
7
5
  id: string;
8
6
  institution: string;
@@ -0,0 +1,29 @@
1
+ /*!
2
+ * © 2026 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 { ManuscriptEditorView } from '@manuscripts/transform';
17
+ import { EditorView } from 'prosemirror-view';
18
+ import React from 'react';
19
+ import { AffiliationAttrs, ContributorAttrs } from '../../lib/authors';
20
+ export interface AuthorsAndAffiliationsModalsProps {
21
+ initialModal: 'authors' | 'affiliations';
22
+ view: ManuscriptEditorView;
23
+ author?: ContributorAttrs;
24
+ affiliation?: AffiliationAttrs;
25
+ addNewAuthor?: boolean;
26
+ addNewAffiliation?: boolean;
27
+ }
28
+ export declare const AuthorsAndAffiliationsModals: React.FC<AuthorsAndAffiliationsModalsProps>;
29
+ export declare const openAuthorsAndAffiliationsModals: (pos: number, view: ManuscriptEditorView | EditorView | undefined, initialModal: "authors" | "affiliations") => void;
@@ -0,0 +1,48 @@
1
+ /*!
2
+ * © 2026 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 React from 'react';
17
+ export declare const ListItems: import("styled-components").StyledComponent<React.ForwardRefExoticComponent<Omit<{
18
+ [x: string]: any;
19
+ [x: number]: any;
20
+ [x: symbol]: any;
21
+ } & {
22
+ theme?: import("styled-components").DefaultTheme | undefined;
23
+ } & {
24
+ as?: string | React.ComponentType<any> | undefined;
25
+ forwardedAs?: string | React.ComponentType<any> | undefined;
26
+ }, "ref"> & React.RefAttributes<HTMLElement>>, import("styled-components").DefaultTheme, {}, never>;
27
+ export interface GenericPanelProps {
28
+ title: string;
29
+ createLabel: string;
30
+ onCreate: () => void;
31
+ createDataCy: string;
32
+ emptyDataCy: string;
33
+ isEmpty: boolean;
34
+ emptyIcon: React.ReactNode;
35
+ emptyMessage: React.ReactNode;
36
+ children: React.ReactNode;
37
+ }
38
+ export declare const GenericPanel: React.FC<GenericPanelProps>;
39
+ export interface ListItemProps {
40
+ selected: boolean;
41
+ onClick: () => void;
42
+ primary: React.ReactNode;
43
+ secondary?: React.ReactNode;
44
+ }
45
+ export declare const ListItem: React.FC<ListItemProps>;
46
+ export declare function useListSelectedIds(selectedItems: {
47
+ id: string;
48
+ }[]): Set<string>;
@@ -7,5 +7,6 @@ export interface FormActionsProps {
7
7
  showDeleteDialog: () => void;
8
8
  newEntity: boolean;
9
9
  isDisableSave: boolean;
10
+ onSubmitForm?: () => void | Promise<void>;
10
11
  }
11
12
  export declare const ModalFormActions: React.FC<FormActionsProps>;
@@ -1,2 +1,2 @@
1
- export declare const VERSION = "3.12.17";
1
+ export declare const VERSION = "3.12.20";
2
2
  export declare const MATHJAX_VERSION = "3.2.2";
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@manuscripts/body-editor",
3
3
  "description": "Prosemirror components for editing and viewing manuscripts",
4
- "version": "3.12.17",
4
+ "version": "3.12.20",
5
5
  "repository": "github:Atypon-OpenSource/manuscripts-body-editor",
6
6
  "license": "Apache-2.0",
7
7
  "main": "dist/cjs",
@@ -38,8 +38,8 @@
38
38
  "@citation-js/plugin-ris": "0.7.18",
39
39
  "@iarna/word-count": "1.1.2",
40
40
  "@manuscripts/style-guide": "3.5.7",
41
- "@manuscripts/track-changes-plugin": "2.3.9",
42
- "@manuscripts/transform": "4.3.33",
41
+ "@manuscripts/track-changes-plugin": "2.3.10",
42
+ "@manuscripts/transform": "4.3.34",
43
43
  "@popperjs/core": "2.11.8",
44
44
  "citeproc": "2.4.63",
45
45
  "codemirror": "5.65.19",