@manuscripts/body-editor 3.0.2 → 3.0.3-LEAN-4579.1

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 (39) hide show
  1. package/dist/cjs/components/affiliations/AffiliationsModal.js +79 -126
  2. package/dist/cjs/components/authors/AffiliationDrawer.js +24 -0
  3. package/dist/cjs/components/authors/AuthorDetailsForm.js +11 -9
  4. package/dist/cjs/components/authors/AuthorsModal.js +121 -204
  5. package/dist/cjs/components/authors/CreditDrawer.js +37 -0
  6. package/dist/cjs/components/authors/useManageAffiliations.js +41 -0
  7. package/dist/cjs/components/authors/useManageCredit.js +43 -0
  8. package/dist/cjs/components/form/FormFooter.js +2 -0
  9. package/dist/cjs/components/form/ModalFormActions.js +4 -4
  10. package/dist/cjs/components/modal-drawer/GenericDrawer.js +16 -0
  11. package/dist/cjs/components/modal-drawer/GenericDrawerGroup.js +75 -0
  12. package/dist/cjs/lib/normalize.js +49 -0
  13. package/dist/cjs/versions.js +1 -1
  14. package/dist/es/components/affiliations/AffiliationsModal.js +80 -127
  15. package/dist/es/components/authors/AffiliationDrawer.js +17 -0
  16. package/dist/es/components/authors/AuthorDetailsForm.js +9 -7
  17. package/dist/es/components/authors/AuthorsModal.js +123 -206
  18. package/dist/es/components/authors/CreditDrawer.js +30 -0
  19. package/dist/es/components/authors/useManageAffiliations.js +37 -0
  20. package/dist/es/components/authors/useManageCredit.js +39 -0
  21. package/dist/es/components/form/FormFooter.js +2 -0
  22. package/dist/es/components/form/ModalFormActions.js +4 -4
  23. package/dist/es/components/modal-drawer/GenericDrawer.js +9 -0
  24. package/dist/es/components/modal-drawer/GenericDrawerGroup.js +68 -0
  25. package/dist/es/lib/normalize.js +44 -0
  26. package/dist/es/versions.js +1 -1
  27. package/dist/types/components/authors/AffiliationDrawer.d.ts +12 -0
  28. package/dist/types/components/authors/AuthorDetailsForm.d.ts +4 -1
  29. package/dist/types/components/authors/AuthorsModal.d.ts +1 -2
  30. package/dist/types/components/authors/CreditDrawer.d.ts +14 -0
  31. package/dist/types/components/authors/useManageAffiliations.d.ts +18 -0
  32. package/dist/types/components/authors/useManageCredit.d.ts +13 -0
  33. package/dist/types/components/form/ModalFormActions.d.ts +2 -2
  34. package/dist/types/components/modal-drawer/GenericDrawer.d.ts +14 -0
  35. package/dist/types/components/modal-drawer/GenericDrawerGroup.d.ts +45 -0
  36. package/dist/types/lib/normalize.d.ts +25 -0
  37. package/dist/types/types.d.ts +1 -0
  38. package/dist/types/versions.d.ts +1 -1
  39. package/package.json +4 -4
@@ -0,0 +1,75 @@
1
+ "use strict";
2
+ /*!
3
+ * © 2025 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.DrawerSection = exports.DrawerSectionHeader = exports.AssignButton = exports.DrawerGroup = void 0;
22
+ const style_guide_1 = require("@manuscripts/style-guide");
23
+ const react_1 = __importDefault(require("react"));
24
+ const styled_components_1 = __importDefault(require("styled-components"));
25
+ function DrawerGroup({ removeItem, selectedItems, onSelect, items, showDrawer, setShowDrawer, title, labelField, Drawer, cy, Icon, buttonText, }) {
26
+ return (react_1.default.createElement(react_1.default.Fragment, null,
27
+ react_1.default.createElement(exports.DrawerSection, null,
28
+ react_1.default.createElement(exports.DrawerSectionHeader, null,
29
+ react_1.default.createElement(DrawerSectionTitle, null, title),
30
+ react_1.default.createElement(exports.AssignButton, { onClick: () => setShowDrawer(true), "data-cy": cy + 'assign-button' },
31
+ Icon,
32
+ buttonText)),
33
+ react_1.default.createElement(style_guide_1.SelectedItemsBox, { "data-cy": cy + '-selected-items', items: selectedItems.map((i) => ({
34
+ id: String(i.id),
35
+ label: String(i[labelField] ?? ''),
36
+ })), onRemove: removeItem, placeholder: `No ${title}s assigned` })),
37
+ showDrawer && (react_1.default.createElement(Drawer, { items: items, selectedItems: selectedItems, title: title, onSelect: onSelect, onBack: () => setShowDrawer(false), width: "100%" }))));
38
+ }
39
+ exports.DrawerGroup = DrawerGroup;
40
+ const DrawerSectionTitle = styled_components_1.default.h3 `
41
+ margin: 0;
42
+ font-weight: ${(props) => props.theme.font.weight.normal};
43
+ font-size: ${(props) => props.theme.font.size.large};
44
+ font-family: ${(props) => props.theme.font.family.sans};
45
+ color: ${(props) => props.theme.colors.text.secondary};
46
+ `;
47
+ exports.AssignButton = styled_components_1.default.button `
48
+ color: ${(props) => props.theme.colors.brand.default};
49
+ background: none;
50
+ border: none;
51
+ cursor: pointer;
52
+ padding: 0;
53
+ font: ${(props) => props.theme.font.weight.normal}
54
+ ${(props) => props.theme.font.size.normal}
55
+ ${(props) => props.theme.font.family.sans};
56
+ display: flex;
57
+ align-items: center;
58
+ gap: 4px;
59
+ margin-top: ${(props) => props.theme.grid.unit * 2}px;
60
+ &:hover {
61
+ opacity: 0.8;
62
+ }
63
+ `;
64
+ exports.DrawerSectionHeader = styled_components_1.default.div `
65
+ display: flex;
66
+ justify-content: space-between;
67
+ align-items: flex-start;
68
+ flex-direction: column;
69
+ margin-bottom: ${(props) => props.theme.grid.unit * 2}px;
70
+ `;
71
+ exports.DrawerSection = styled_components_1.default.div `
72
+ margin-top: ${(props) => props.theme.grid.unit * 4}px;
73
+ padding-top: ${(props) => props.theme.grid.unit * 4}px;
74
+ border-top: 1px solid ${(props) => props.theme.colors.border.tertiary};
75
+ `;
@@ -0,0 +1,49 @@
1
+ "use strict";
2
+ /*!
3
+ * © 2025 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.checkID = exports.normalizeAuthor = void 0;
19
+ const transform_1 = require("@manuscripts/transform");
20
+ const normalizeAuthor = (author) => {
21
+ const basic = {
22
+ id: author.id,
23
+ role: author.role || '',
24
+ affiliations: (author.affiliations || []).sort(),
25
+ bibliographicName: author.bibliographicName,
26
+ email: author.email || '',
27
+ isCorresponding: author.isCorresponding || false,
28
+ ORCIDIdentifier: author.ORCIDIdentifier || '',
29
+ priority: author.priority || 0,
30
+ isJointContributor: author.isJointContributor || false,
31
+ userID: author.userID || '',
32
+ invitationID: author.invitationID || '',
33
+ footnote: author.footnote || [],
34
+ corresp: author.corresp || [],
35
+ prefix: author.prefix || '',
36
+ };
37
+ if (author.creditRoles && Array.isArray(author.creditRoles)) {
38
+ basic.creditRoles = author.creditRoles;
39
+ }
40
+ return basic;
41
+ };
42
+ exports.normalizeAuthor = normalizeAuthor;
43
+ const checkID = (attrs, nodeType) => {
44
+ return {
45
+ ...attrs,
46
+ id: attrs.id || (0, transform_1.generateNodeID)(transform_1.schema.nodes[nodeType]),
47
+ };
48
+ };
49
+ exports.checkID = checkID;
@@ -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.0.2';
4
+ exports.VERSION = '3.0.3-LEAN-4579.1';
5
5
  exports.MATHJAX_VERSION = '3.2.2';
@@ -1,102 +1,30 @@
1
- import { generateID, ObjectTypes } from '@manuscripts/json-schema';
2
- import { AddIcon, AddUserIcon, AffiliationPlaceholderIcon, CloseButton, Drawer, ModalBody, ModalContainer, ModalHeader, ModalSidebar, ModalSidebarHeader, ModalSidebarTitle, ScrollableModalContent, SelectedItemsBox, SidebarContent, StyledModal, } from '@manuscripts/style-guide';
1
+ import { AddIcon, AddUserIcon, AffiliationPlaceholderIcon, CloseButton, ModalBody, ModalContainer, ModalHeader, ModalSidebar, ModalSidebarHeader, ModalSidebarTitle, ScrollableModalContent, SidebarContent, StyledModal, } from '@manuscripts/style-guide';
2
+ import { generateNodeID, schema } from '@manuscripts/transform';
3
3
  import { isEqual } from 'lodash';
4
4
  import React, { useCallback, useEffect, useReducer, useRef, useState, } from 'react';
5
5
  import styled from 'styled-components';
6
6
  import { authorComparator, } from '../../lib/authors';
7
- import { affiliationsReducer, authorsReducer } from '../authors/AuthorsModal';
7
+ import { checkID } from '../../lib/normalize';
8
+ import { authorsReducer } from '../authors/AuthorsModal';
9
+ import { affiliationsReducer } from '../authors/useManageAffiliations';
8
10
  import { ConfirmationDialog, DialogType } from '../dialog/ConfirmationDialog';
9
11
  import FormFooter from '../form/FormFooter';
10
12
  import { FormPlaceholder } from '../form/FormPlaceholder';
11
13
  import { ModalFormActions } from '../form/ModalFormActions';
14
+ import { GenericDrawer } from '../modal-drawer/GenericDrawer';
15
+ import { DrawerGroup } from '../modal-drawer/GenericDrawerGroup';
12
16
  import { AffiliationForm } from './AffiliationForm';
13
17
  import { AffiliationList } from './AffiliationList';
14
- const StyledSidebarContent = styled(SidebarContent) `
15
- padding: 0;
16
- `;
17
- const AddAffiliationButton = styled.div `
18
- display: flex;
19
- align-items: center;
20
- padding: 12px 8px 12px 12px;
21
- cursor: pointer;
22
- &[data-active='true'] {
23
- background: ${(props) => props.theme.colors.background.fifth};
24
- border: 1px solid ${(props) => props.theme.colors.border.primary};
25
- border-left: 0;
26
- border-right: 0;
27
- }
28
- `;
29
- const ActionTitle = styled.div `
30
- padding-left: ${(props) => props.theme.grid.unit * 2}px;
31
- `;
32
- const AffiliationForms = styled.div `
33
- padding-left: ${(props) => props.theme.grid.unit * 3}px;
34
- padding-right: ${(props) => props.theme.grid.unit * 3}px;
35
- position: relative;
36
- margin-top: 20px;
37
- `;
38
- const AuthorsSection = styled.div `
39
- margin-top: ${(props) => props.theme.grid.unit * 4}px;
40
- padding-top: ${(props) => props.theme.grid.unit * 4}px;
41
- border-top: 1px solid ${(props) => props.theme.colors.border.tertiary};
42
- `;
43
- const AuthorsHeader = styled.div `
44
- display: flex;
45
- justify-content: space-between;
46
- align-items: flex-start;
47
- flex-direction: column;
48
- margin-bottom: ${(props) => props.theme.grid.unit * 2}px;
49
- `;
50
- const AuthorsTitle = styled.h3 `
51
- margin: 0;
52
- font-weight: ${(props) => props.theme.font.weight.normal};
53
- font-size: ${(props) => props.theme.font.size.large};
54
- font-family: ${(props) => props.theme.font.family.sans};
55
- color: ${(props) => props.theme.colors.text.secondary};
56
- `;
57
- const AffiliateButton = styled.button `
58
- color: ${(props) => props.theme.colors.brand.default};
59
- background: none;
60
- border: none;
61
- cursor: pointer;
62
- padding: 0;
63
- font: ${(props) => props.theme.font.weight.normal}
64
- ${(props) => props.theme.font.size.normal}
65
- ${(props) => props.theme.font.family.sans};
66
- display: flex;
67
- align-items: center;
68
- gap: 4px;
69
- margin-top: ${(props) => props.theme.grid.unit * 2}px;
70
- &:hover {
71
- opacity: 0.8;
72
- }
73
- `;
74
- const StyledModalBody = styled(ModalBody) `
75
- position: relative;
76
- height: calc(90vh - 40px);
77
- `;
78
- const StyledModalSidebarHeader = styled(ModalSidebarHeader) `
79
- margin-top: 8px;
80
- margin-bottom: 16px;
81
- `;
82
- const normalize = (affiliation) => ({
83
- id: affiliation.id || generateID(ObjectTypes.Affiliation),
84
- institution: affiliation.institution,
85
- department: affiliation.department,
86
- addressLine1: affiliation.addressLine1,
87
- addressLine2: affiliation.addressLine2,
88
- addressLine3: affiliation.addressLine3,
89
- postCode: affiliation.postCode,
90
- country: affiliation.country,
91
- county: affiliation.county,
92
- city: affiliation.city,
93
- email: affiliation.email,
94
- priority: affiliation.priority,
95
- });
18
+ function makeAuthorItems(authors) {
19
+ return authors.map((author) => ({
20
+ id: author.id,
21
+ label: `${author.bibliographicName.given} ${author.bibliographicName.family}`,
22
+ }));
23
+ }
96
24
  export const AffiliationsModal = ({ authors: $authors, affiliations: $affiliations, affiliation, onSaveAffiliation, onDeleteAffiliation, onUpdateAuthors, addNewAffiliation = false, }) => {
97
25
  const [isOpen, setIsOpen] = useState(true);
98
26
  const [selection, setSelection] = useState(affiliation);
99
- const [showDeleteDialog, setShowDeleteDialog] = useState(false);
27
+ const [showingDeleteDialog, setShowDeleteDialog] = useState(false);
100
28
  const valuesRef = useRef();
101
29
  const actionsRef = useRef();
102
30
  const [authors, dispatchAuthors] = useReducer(authorsReducer, $authors.sort(authorComparator));
@@ -128,7 +56,7 @@ export const AffiliationsModal = ({ authors: $authors, affiliations: $affiliatio
128
56
  }, []);
129
57
  const handleClose = () => {
130
58
  const values = valuesRef.current;
131
- const hasAffiliationChanges = selection && !isEqual(values, normalize(selection));
59
+ const hasAffiliationChanges = selection && !isEqual(values, checkID(selection, 'affiliation'));
132
60
  const originalAuthors = selection
133
61
  ? affiliationAuthorMap.get(selection.id) ?? []
134
62
  : [];
@@ -150,7 +78,7 @@ export const AffiliationsModal = ({ authors: $authors, affiliations: $affiliatio
150
78
  };
151
79
  const handleSelect = (affiliation) => {
152
80
  const values = valuesRef.current;
153
- const hasAffiliationChanges = selection && !isEqual(values, normalize(selection));
81
+ const hasAffiliationChanges = selection && !isEqual(values, checkID(selection, 'affiliation'));
154
82
  const originalAuthors = selection
155
83
  ? affiliationAuthorMap.get(selection.id) ?? []
156
84
  : [];
@@ -188,7 +116,7 @@ export const AffiliationsModal = ({ authors: $authors, affiliations: $affiliatio
188
116
  }
189
117
  setIsDisableSave(true);
190
118
  const affiliation = {
191
- ...normalize(selection),
119
+ ...checkID(selection, 'affiliation'),
192
120
  ...values,
193
121
  };
194
122
  onSaveAffiliation(affiliation);
@@ -235,7 +163,8 @@ export const AffiliationsModal = ({ authors: $authors, affiliations: $affiliatio
235
163
  return;
236
164
  }
237
165
  const isInstitutionEmpty = !values.institution?.trim();
238
- const hasAffiliationChanges = selection && !isEqual(normalize(values), normalize(selection));
166
+ const hasAffiliationChanges = selection &&
167
+ !isEqual(checkID(values, 'affiliation'), checkID(selection, 'affiliation'));
239
168
  const originalAuthors = affiliationAuthorMap.get(selection.id) ?? [];
240
169
  const hasAuthorChanges = selection && !isEqual(originalAuthors.sort(), selectedAuthorIds.sort());
241
170
  const shouldEnableSave = !isInstitutionEmpty && (hasAffiliationChanges || hasAuthorChanges);
@@ -265,7 +194,7 @@ export const AffiliationsModal = ({ authors: $authors, affiliations: $affiliatio
265
194
  setSelectedAuthorIds([]);
266
195
  setSelection(undefined);
267
196
  };
268
- const handleAuthorSelect = (authorId) => {
197
+ const selectAuthor = (authorId) => {
269
198
  if (!selection) {
270
199
  return;
271
200
  }
@@ -273,17 +202,13 @@ export const AffiliationsModal = ({ authors: $authors, affiliations: $affiliatio
273
202
  ? selectedAuthorIds.filter((id) => id !== authorId)
274
203
  : [...selectedAuthorIds, authorId];
275
204
  setSelectedAuthorIds(newSelectedAuthorIds);
276
- const hasAffiliationChanges = !isEqual(valuesRef.current, normalize(selection));
205
+ const hasAffiliationChanges = !isEqual(valuesRef.current, checkID(selection, 'affiliation'));
277
206
  const originalAuthors = affiliationAuthorMap.get(selection.id) ?? [];
278
207
  const hasAuthorChanges = !isEqual(originalAuthors.sort(), newSelectedAuthorIds.sort());
279
208
  const isInstitutionEmpty = !valuesRef.current?.institution?.trim();
280
209
  const shouldEnableSave = !isInstitutionEmpty && (hasAffiliationChanges || hasAuthorChanges);
281
210
  setIsDisableSave(!shouldEnableSave);
282
211
  };
283
- const authorItems = authors.map((author) => ({
284
- id: author.id,
285
- label: `${author.bibliographicName.given} ${author.bibliographicName.family}`,
286
- }));
287
212
  const selectedAuthors = selectedAuthorIds
288
213
  .map((authorId) => {
289
214
  const author = authors.find((a) => a.id === authorId);
@@ -299,23 +224,7 @@ export const AffiliationsModal = ({ authors: $authors, affiliations: $affiliatio
299
224
  const values = valuesRef.current;
300
225
  const hasChanges = !isDisableSave;
301
226
  const isInstitutionEmpty = values?.institution?.trim() === '';
302
- const emptyAffiliation = {
303
- id: generateID(ObjectTypes.Affiliation),
304
- institution: '',
305
- department: '',
306
- addressLine1: '',
307
- addressLine2: '',
308
- addressLine3: '',
309
- postCode: '',
310
- country: '',
311
- county: '',
312
- city: '',
313
- email: {
314
- href: '',
315
- text: '',
316
- },
317
- priority: affiliations.length,
318
- };
227
+ const emptyAffiliation = createEmptyAffiliation(affiliations.length);
319
228
  if (hasChanges) {
320
229
  setPendingAction('new');
321
230
  if (isInstitutionEmpty) {
@@ -354,7 +263,7 @@ export const AffiliationsModal = ({ authors: $authors, affiliations: $affiliatio
354
263
  .filter((author) => author.affiliations?.some((aff) => aff === pendingSelection.id))
355
264
  .map((author) => author.id);
356
265
  setSelectedAuthorIds(affiliatedAuthorIds);
357
- valuesRef.current = normalize(pendingSelection);
266
+ valuesRef.current = checkID(pendingSelection, 'affiliation');
358
267
  setIsDisableSave(true);
359
268
  setAffiliationAuthorMap((prevMap) => {
360
269
  const newMap = new Map(prevMap);
@@ -392,7 +301,7 @@ export const AffiliationsModal = ({ authors: $authors, affiliations: $affiliatio
392
301
  setSelectedAuthorIds([]);
393
302
  }
394
303
  if (pendingSelection) {
395
- valuesRef.current = normalize(pendingSelection);
304
+ valuesRef.current = checkID(pendingSelection, 'affiliation');
396
305
  }
397
306
  else {
398
307
  valuesRef.current = undefined;
@@ -417,19 +326,63 @@ export const AffiliationsModal = ({ authors: $authors, affiliations: $affiliatio
417
326
  React.createElement(ActionTitle, null, "New Affiliation")),
418
327
  React.createElement(AffiliationList, { affiliation: selection, affiliations: affiliations, onSelect: handleSelect, onDelete: handleShowDeleteDialog, lastSavedAffiliationId: savedAffiliationId }))),
419
328
  React.createElement(ScrollableModalContent, { "data-cy": "affiliations-modal-content" }, selection ? (React.createElement(AffiliationForms, null,
420
- React.createElement(ModalFormActions, { type: 'affiliation', form: 'affiliation-form', onDelete: handleDeleteAffiliation, showDeleteDialog: showDeleteDialog, handleShowDeleteDialog: handleShowDeleteDialog, newEntity: newAffiliation, isDisableSave: isDisableSave }),
421
- React.createElement(AffiliationForm, { values: normalize(selection), onSave: () => handleSaveAffiliation(valuesRef.current), onChange: handleAffiliationChange, actionsRef: actionsRef }),
329
+ React.createElement(ModalFormActions, { type: 'affiliation', form: 'affiliation-form', onDelete: handleDeleteAffiliation, showingDeleteDialog: showingDeleteDialog, showDeleteDialog: handleShowDeleteDialog, newEntity: newAffiliation, isDisableSave: isDisableSave }),
330
+ React.createElement(AffiliationForm, { values: checkID(selection, 'affiliation'), onSave: () => handleSaveAffiliation(valuesRef.current), onChange: handleAffiliationChange, actionsRef: actionsRef }),
422
331
  React.createElement(ConfirmationDialog, { isOpen: showRequiredFieldConfirmationDialog, onPrimary: () => setShowRequiredFieldConfirmationDialog(false), onSecondary: handleConfirmationCancel, type: DialogType.REQUIRED, entityType: "affiliation" }),
423
332
  React.createElement(ConfirmationDialog, { isOpen: showConfirmationDialog, onPrimary: handleConfirmationSave, onSecondary: handleConfirmationCancel, type: DialogType.SAVE, entityType: "affiliation" }),
424
- React.createElement(AuthorsSection, null,
425
- React.createElement(AuthorsHeader, null,
426
- React.createElement(AuthorsTitle, null, "Authors"),
427
- React.createElement(AffiliateButton, { onClick: () => setShowAuthorDrawer(true), "data-cy": "affiliate-authors-button" },
428
- React.createElement(AddUserIcon, { width: 16, height: 16 }),
429
- "Affiliate Authors")),
430
- React.createElement(SelectedItemsBox, { "data-cy": "affiliation-authors", items: selectedAuthors, onRemove: (id) => {
431
- setSelectedAuthorIds((prev) => prev.filter((authorId) => authorId !== id));
432
- }, placeholder: "No authors assigned" })),
433
- showAuthorDrawer && (React.createElement(Drawer, { items: authorItems, selectedIds: selectedAuthorIds, title: "Authors", onSelect: handleAuthorSelect, onBack: () => setShowAuthorDrawer(false), width: "100%" })))) : (React.createElement(FormPlaceholder, { type: "affiliation", title: "Affiliation Details", message: "Select an affiliation from the list to display it's details here.", placeholderIcon: React.createElement(AffiliationPlaceholderIcon, null) })))),
333
+ React.createElement(DrawerGroup, { Drawer: GenericDrawer, removeItem: (id) => {
334
+ setSelectedAuthorIds((prev) => prev.filter((authorId) => authorId !== id));
335
+ }, selectedItems: selectedAuthors, onSelect: selectAuthor, items: makeAuthorItems(authors), showDrawer: showAuthorDrawer, setShowDrawer: setShowAuthorDrawer, title: "Authors", cy: "affiliations", labelField: "label", buttonText: "Affiliate Authors", Icon: React.createElement(AddUserIcon, { width: 16, height: 16 }) }))) : (React.createElement(FormPlaceholder, { type: "affiliation", title: "Affiliation Details", message: "Select an affiliation from the list to display it's details here.", placeholderIcon: React.createElement(AffiliationPlaceholderIcon, null) })))),
434
336
  React.createElement(FormFooter, { onCancel: handleClose }))));
435
337
  };
338
+ function createEmptyAffiliation(priority) {
339
+ return {
340
+ id: generateNodeID(schema.nodes.affiliation),
341
+ institution: '',
342
+ department: '',
343
+ addressLine1: '',
344
+ addressLine2: '',
345
+ addressLine3: '',
346
+ postCode: '',
347
+ country: '',
348
+ county: '',
349
+ city: '',
350
+ email: {
351
+ href: '',
352
+ text: '',
353
+ },
354
+ priority: priority,
355
+ };
356
+ }
357
+ const StyledSidebarContent = styled(SidebarContent) `
358
+ padding: 0;
359
+ `;
360
+ const AddAffiliationButton = styled.div `
361
+ display: flex;
362
+ align-items: center;
363
+ padding: 12px 8px 12px 12px;
364
+ cursor: pointer;
365
+ &[data-active='true'] {
366
+ background: ${(props) => props.theme.colors.background.fifth};
367
+ border: 1px solid ${(props) => props.theme.colors.border.primary};
368
+ border-left: 0;
369
+ border-right: 0;
370
+ }
371
+ `;
372
+ const ActionTitle = styled.div `
373
+ padding-left: ${(props) => props.theme.grid.unit * 2}px;
374
+ `;
375
+ const AffiliationForms = styled.div `
376
+ padding-left: ${(props) => props.theme.grid.unit * 3}px;
377
+ padding-right: ${(props) => props.theme.grid.unit * 3}px;
378
+ position: relative;
379
+ margin-top: 20px;
380
+ `;
381
+ const StyledModalBody = styled(ModalBody) `
382
+ position: relative;
383
+ height: calc(90vh - 40px);
384
+ `;
385
+ const StyledModalSidebarHeader = styled(ModalSidebarHeader) `
386
+ margin-top: 8px;
387
+ margin-bottom: 16px;
388
+ `;
@@ -0,0 +1,17 @@
1
+ import { AddedIcon, AddIcon, Drawer, DrawerIcon, DrawerItemLabel, DrawerItemMeta, DrawerItemsList, DrawerLabelContainer, DrawerListItem, } from '@manuscripts/style-guide';
2
+ import React from 'react';
3
+ export const AffiliationsDrawer = ({ items, selectedItems = [], onSelect, ...drawerProps }) => {
4
+ return (React.createElement(Drawer, { ...drawerProps },
5
+ React.createElement(DrawerItemsList, null, items.map((item) => (React.createElement(DrawerListItem, { "data-cy": "item", key: item.id, selected: selectedItems?.map((a) => a.id).includes(item.id), onClick: () => onSelect(item.id) },
6
+ React.createElement(DrawerIcon, null, selectedItems?.map((a) => a.id).includes(item.id) ? (React.createElement(AddedIcon, { width: 22, height: 22 })) : (React.createElement(AddIcon, { width: 22, height: 22 }))),
7
+ React.createElement(DrawerLabelContainer, null,
8
+ React.createElement(DrawerItemLabel, null, item.institution),
9
+ React.createElement(DrawerItemMeta, null,
10
+ item.city && (React.createElement(React.Fragment, null,
11
+ item.city,
12
+ item.county || item.country ? ', ' : '')),
13
+ item.county && (React.createElement(React.Fragment, null,
14
+ item.county,
15
+ item.country ? ', ' : '')),
16
+ item.country && React.createElement(React.Fragment, null, item.country)))))))));
17
+ };
@@ -1,5 +1,5 @@
1
1
  /*!
2
- * © 2019 Atypon Systems LLC
2
+ * © 2025 Atypon Systems LLC
3
3
  *
4
4
  * Licensed under the Apache License, Version 2.0 (the "License");
5
5
  * you may not use this file except in compliance with the License.
@@ -41,18 +41,23 @@ const TextFieldWithError = styled(TextField) `
41
41
  color: ${(props) => props.theme.colors.text.error};
42
42
  }
43
43
  `;
44
- const CheckboxContainer = styled.div `
44
+ export const CheckboxContainer = styled.div `
45
45
  display: flex;
46
46
  align-items: center;
47
47
  gap: 32px;
48
48
  `;
49
- export const AuthorDetailsForm = ({ values, onChange, onSave, actionsRef, isEmailRequired, selectedAffiliations, authorFormRef, }) => {
49
+ export const AuthorDetailsForm = ({ values, onChange, onSave, actionsRef, isEmailRequired, selectedAffiliations, selectedCreditRoles, authorFormRef, }) => {
50
50
  const formRef = useRef(null);
51
51
  useEffect(() => {
52
52
  if (selectedAffiliations && formRef.current) {
53
53
  formRef.current.setFieldValue('affiliations', selectedAffiliations);
54
54
  }
55
55
  }, [selectedAffiliations]);
56
+ useEffect(() => {
57
+ if (selectedCreditRoles && formRef.current) {
58
+ formRef.current.setFieldValue('creditRoles', selectedCreditRoles);
59
+ }
60
+ }, [selectedCreditRoles]);
56
61
  if (actionsRef && !actionsRef.current) {
57
62
  actionsRef.current = {
58
63
  reset: () => {
@@ -81,9 +86,6 @@ export const AuthorDetailsForm = ({ values, onChange, onSave, actionsRef, isEmai
81
86
  React.createElement(OrcidContainer, null,
82
87
  React.createElement(TextFieldLabel, null,
83
88
  React.createElement(LabelText, null, "ORCID"),
84
- React.createElement(Field, { name: 'ORCIDIdentifier', type: 'text' }, (props) => (React.createElement(TextField, { id: 'orcid', placeholder: 'https://orcid.org/...', pattern: "https://orcid\\.org/\\d{4}-\\d{4}-\\d{4}-\\d{4}", title: "Please enter a valid ORCID URL format: https://orcid.org/xxxx-xxxx-xxxx-xxxx", ...props.field }))))),
85
- React.createElement(Field, { name: "affiliations", type: "hidden" }, (props) => {
86
- return (React.createElement(TextField, { type: "hidden", ...props.field, value: selectedAffiliations || [] }));
87
- }))));
89
+ React.createElement(Field, { name: 'ORCIDIdentifier', type: 'text' }, (props) => (React.createElement(TextField, { id: 'orcid', placeholder: 'https://orcid.org/...', pattern: "https://orcid\\.org/\\d{4}-\\d{4}-\\d{4}-\\d{4}", title: "Please enter a valid ORCID URL format: https://orcid.org/xxxx-xxxx-xxxx-xxxx", ...props.field }))))))));
88
90
  }));
89
91
  };