@manuscripts/body-editor 3.12.67 → 3.13.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 (289) hide show
  1. package/dist/cjs/components/toolbar/type-selector/styles.js +2 -1
  2. package/dist/cjs/versions.js +1 -1
  3. package/dist/es/components/toolbar/type-selector/styles.js +2 -1
  4. package/dist/es/versions.js +1 -1
  5. package/dist/types/components/toolbar/type-selector/styles.d.ts +2 -2
  6. package/dist/types/lib/footnotes.d.ts +4 -2
  7. package/dist/types/lib/utils.d.ts +5 -4
  8. package/dist/types/versions.d.ts +1 -1
  9. package/package.json +37 -36
  10. package/{dist/es/lib/statistics.js → src/__mocks__/styleMock.ts} +2 -14
  11. package/src/assets.ts +20 -0
  12. package/src/classes/collabProvider.ts +38 -0
  13. package/src/clipboard.ts +54 -0
  14. package/src/commands.ts +2109 -0
  15. package/src/components/ChangeHandlingForm.tsx +54 -0
  16. package/src/components/LanguageDropdown/index.tsx +343 -0
  17. package/src/components/affiliations/AffiliationForm.tsx +238 -0
  18. package/src/components/affiliations/AffiliationItem.tsx +151 -0
  19. package/src/components/affiliations/AffiliationList.tsx +71 -0
  20. package/src/components/affiliations/AffiliationsModal.tsx +676 -0
  21. package/src/components/affiliations/AffiliationsPanel.tsx +76 -0
  22. package/src/components/affiliations/CreateAffiliationModal.tsx +135 -0
  23. package/src/components/authors/AuthorDetailsForm.tsx +438 -0
  24. package/src/components/authors/AuthorList.tsx +81 -0
  25. package/src/components/authors/AuthorsModal.tsx +642 -0
  26. package/src/components/authors/AuthorsPanel.tsx +69 -0
  27. package/src/components/authors/CreateAuthorModal.tsx +172 -0
  28. package/src/components/authors/CreditDrawer.tsx +71 -0
  29. package/src/components/authors/DraggableAuthor.tsx +228 -0
  30. package/src/components/authors/useManageAffiliations.tsx +77 -0
  31. package/src/components/authors/useManageCredit.tsx +63 -0
  32. package/src/components/authors-affiliations/AuthorsAndAffiliationsModals.tsx +170 -0
  33. package/src/components/authors-affiliations/GenericPanel.tsx +164 -0
  34. package/src/components/authors-affiliations/ModalTabs.tsx +100 -0
  35. package/src/components/awards/AwardForm.tsx +338 -0
  36. package/src/components/awards/AwardModal.tsx +120 -0
  37. package/src/components/awards/DeleteAwardDiaolog.tsx +52 -0
  38. package/src/components/dialog/ConfirmationDialog.tsx +131 -0
  39. package/src/components/form/CreateModalStyles.tsx +37 -0
  40. package/src/components/form/FormFooter.tsx +54 -0
  41. package/src/components/form/FormPlaceholder.tsx +71 -0
  42. package/src/components/form/ModalFormActions.tsx +88 -0
  43. package/src/components/form/UnsavedLabel.tsx +49 -0
  44. package/src/components/hooks/use-debounce.ts +56 -0
  45. package/src/components/hooks/useAffiliationShowsErrorIndicator.ts +51 -0
  46. package/src/components/hooks/useAuthorShowsErrorIndicator.ts +73 -0
  47. package/src/components/keyboard-shortcuts-modal/FormattedShortcut.tsx +56 -0
  48. package/src/components/keyboard-shortcuts-modal/KeyboardShortcutsModal.tsx +283 -0
  49. package/src/components/keyboard-shortcuts-modal/keyboard-shortcuts.ts +304 -0
  50. package/src/components/keywords/AddKeywordInline.tsx +284 -0
  51. package/src/components/keywords/DeleteKeywordDialog.tsx +52 -0
  52. package/src/components/modal-drawer/GenericDrawer.tsx +65 -0
  53. package/src/components/modal-drawer/GenericDrawerGroup.tsx +125 -0
  54. package/src/components/outline/DraggableTree.tsx +438 -0
  55. package/src/components/outline/ManuscriptOutline.tsx +127 -0
  56. package/src/components/outline/Outline.tsx +141 -0
  57. package/src/components/references/BibliographyItemSource.ts +80 -0
  58. package/src/components/references/CitationEditor.tsx +301 -0
  59. package/src/components/references/CitationViewer.tsx +62 -0
  60. package/src/components/references/ImportBibliographyForm.tsx +232 -0
  61. package/src/components/references/ImportBibliographyModal.tsx +159 -0
  62. package/src/components/references/ReferenceForm/PersonDropDown.tsx +93 -0
  63. package/src/components/references/ReferenceForm/ReferenceForm.tsx +701 -0
  64. package/src/components/references/ReferenceForm/config.ts +133 -0
  65. package/src/components/references/ReferenceForm/styled-components.ts +156 -0
  66. package/src/components/references/ReferenceLine.tsx +43 -0
  67. package/src/components/references/ReferenceSearch.tsx +163 -0
  68. package/src/components/references/ReferenceSearchResults.tsx +113 -0
  69. package/src/components/references/ReferenceSearchResultsPlaceholder.tsx +71 -0
  70. package/src/components/references/ReferenceSearchSection.tsx +124 -0
  71. package/src/components/references/ReferencesEditor.tsx +61 -0
  72. package/src/components/references/ReferencesModal.tsx +352 -0
  73. package/src/components/references/SearchInput.tsx +98 -0
  74. package/src/components/toolbar/InsertEmbedDialog.tsx +222 -0
  75. package/src/components/toolbar/InsertTableDialog.tsx +208 -0
  76. package/src/components/toolbar/ListMenuItem.tsx +203 -0
  77. package/src/components/toolbar/helpers.ts +547 -0
  78. package/src/components/toolbar/type-selector/OptionComponent.tsx +89 -0
  79. package/src/components/toolbar/type-selector/TypeSelector.tsx +157 -0
  80. package/src/components/toolbar/type-selector/styles.ts +79 -0
  81. package/src/components/views/CrossReferenceItems.tsx +199 -0
  82. package/src/components/views/DeleteEmbedDialog.tsx +83 -0
  83. package/src/components/views/DeleteFootnoteDialog.tsx +54 -0
  84. package/src/components/views/FigureDropdown.tsx +423 -0
  85. package/src/components/views/FootnotesSelector.tsx +255 -0
  86. package/src/components/views/InsertSpecialCharacter.tsx +245 -0
  87. package/src/components/views/LinkForm.tsx +220 -0
  88. package/src/components/views/TableCellContextMenu.tsx +241 -0
  89. package/src/configs/ManuscriptsEditor.ts +140 -0
  90. package/src/configs/editor-plugins.ts +119 -0
  91. package/src/configs/editor-views.ts +139 -0
  92. package/src/icons.ts +62 -0
  93. package/src/index.ts +65 -0
  94. package/src/keys/highlight.ts +65 -0
  95. package/src/keys/index.ts +33 -0
  96. package/src/keys/keyword.ts +69 -0
  97. package/src/keys/list.ts +156 -0
  98. package/src/keys/misc.ts +112 -0
  99. package/src/keys/title.ts +221 -0
  100. package/src/lib/__tests__/__fixtures__/doc.json +388 -0
  101. package/src/lib/__tests__/__snapshots__/paste.test.ts.snap +24 -0
  102. package/src/lib/__tests__/authors.test.ts +202 -0
  103. package/src/lib/__tests__/helpers.test.ts +46 -0
  104. package/src/lib/__tests__/paste.test.ts +57 -0
  105. package/src/lib/__tests__/plugins.test.ts +176 -0
  106. package/src/lib/__tests__/url.test.ts +31 -0
  107. package/src/lib/array-reducer.ts +68 -0
  108. package/src/lib/authors-and-affiliations.ts +81 -0
  109. package/src/lib/authors.ts +67 -0
  110. package/src/lib/capabilities.ts +55 -0
  111. package/src/lib/codemirror.ts +37 -0
  112. package/src/lib/comments.ts +123 -0
  113. package/src/lib/context-menu.ts +745 -0
  114. package/src/lib/copy.ts +30 -0
  115. package/src/lib/crossref.ts +90 -0
  116. package/src/lib/dnd.ts +29 -0
  117. package/src/lib/doc.ts +167 -0
  118. package/src/lib/dompurify.ts +28 -0
  119. package/src/lib/files.ts +180 -0
  120. package/src/lib/footnotes.ts +83 -0
  121. package/src/lib/get-media-type.ts +105 -0
  122. package/src/lib/helpers.ts +199 -0
  123. package/src/lib/hierarchy.ts +117 -0
  124. package/src/lib/languages.ts +37 -0
  125. package/src/lib/lists.ts +56 -0
  126. package/src/lib/math.ts +111 -0
  127. package/src/lib/media.ts +334 -0
  128. package/src/lib/navigation-utils.ts +235 -0
  129. package/src/lib/normalize.ts +70 -0
  130. package/src/lib/paste.ts +304 -0
  131. package/src/lib/placeholder.ts +32 -0
  132. package/src/lib/platform.ts +18 -0
  133. package/src/lib/plugins.ts +22 -0
  134. package/src/lib/popper.ts +180 -0
  135. package/src/lib/position-menu.ts +184 -0
  136. package/src/lib/references.ts +94 -0
  137. package/src/lib/template.ts +29 -0
  138. package/src/lib/track-changes-utils.ts +34 -0
  139. package/{dist/types/lib/statistics.d.ts → src/lib/url.ts} +11 -8
  140. package/src/lib/use-do-with-debounce.ts +39 -0
  141. package/src/lib/utils.ts +323 -0
  142. package/src/lib/view.ts +100 -0
  143. package/src/menus.tsx +684 -0
  144. package/src/node-type-icons.tsx +83 -0
  145. package/src/plugins/__tests__/__fixtures__/deleted-footnote.json +140 -0
  146. package/src/plugins/__tests__/__fixtures__/inserted-footnote.json +153 -0
  147. package/src/plugins/__tests__/footnotes.test.ts +67 -0
  148. package/src/plugins/accessibility_element.ts +219 -0
  149. package/src/plugins/add-subtitle.ts +102 -0
  150. package/src/plugins/affiliations.ts +136 -0
  151. package/src/plugins/alt-titles.ts +219 -0
  152. package/src/plugins/bibliography.ts +235 -0
  153. package/src/plugins/comments.ts +328 -0
  154. package/src/plugins/cross-references.ts +70 -0
  155. package/src/plugins/detect-inconsistency/detect-inconsistency-utils.ts +102 -0
  156. package/src/plugins/detect-inconsistency/index.ts +55 -0
  157. package/src/plugins/detect-inconsistency/validators.ts +283 -0
  158. package/src/plugins/doi.ts +66 -0
  159. package/src/plugins/editor-props.ts +39 -0
  160. package/src/plugins/elements.ts +60 -0
  161. package/src/plugins/footnotes.ts +298 -0
  162. package/src/plugins/link.ts +53 -0
  163. package/src/plugins/lock-body.ts +136 -0
  164. package/src/plugins/move-node.ts +55 -0
  165. package/src/plugins/objects.ts +125 -0
  166. package/src/plugins/paragraphs.ts +90 -0
  167. package/src/plugins/persist.ts +64 -0
  168. package/src/plugins/persistent-cursor.ts +66 -0
  169. package/src/plugins/placeholder.ts +219 -0
  170. package/src/plugins/prevent-empty.ts +50 -0
  171. package/src/plugins/search-replace/index.ts +157 -0
  172. package/src/plugins/search-replace/lib.ts +95 -0
  173. package/src/plugins/section_category.ts +212 -0
  174. package/src/plugins/section_title/autocompletion.ts +87 -0
  175. package/src/plugins/section_title/index.ts +105 -0
  176. package/src/plugins/selected-suggestion.ts +243 -0
  177. package/src/plugins/tables-cursor-fix.ts +143 -0
  178. package/src/plugins/translations.ts +263 -0
  179. package/src/rules.ts +60 -0
  180. package/src/selection.ts +112 -0
  181. package/src/testing/default-capabilities.ts +48 -0
  182. package/src/testing/default-editor-data.ts +73 -0
  183. package/src/testing/empty-editor-doc.json +62 -0
  184. package/src/testing/polyfill-dom.ts +43 -0
  185. package/src/testing/section-categories.json +161 -0
  186. package/src/testing/setup-editor.ts +55 -0
  187. package/src/tests.ts +42 -0
  188. package/src/toolbar.tsx +259 -0
  189. package/src/types/@citation-js/core.d.ts +16 -0
  190. package/src/types/@citation-js/index.d.ts +16 -0
  191. package/src/types/@citation-js/plugin-bibtex.d.ts +16 -0
  192. package/src/types/@citation-js/plugin-csl.d.ts +16 -0
  193. package/src/types/@citation-js/plugin-doi.d.ts +16 -0
  194. package/src/types/@citation-js/plugin-enw.d.ts +16 -0
  195. package/src/types/@citation-js/plugin-pubmed.d.ts +16 -0
  196. package/src/types/@citation-js/plugin-ris.d.ts +16 -0
  197. package/src/types/citeproc.d.ts +124 -0
  198. package/src/types/css.d.ts +16 -0
  199. package/src/types/json.d.ts +17 -0
  200. package/src/types/prosemirror-dev-tools.d.ts +16 -0
  201. package/src/types/prosemirror-dropcursor.d.ts +16 -0
  202. package/src/types/styled-components.d.ts +23 -0
  203. package/src/types.ts +49 -0
  204. package/src/useEditor.ts +244 -0
  205. package/src/versions.ts +3 -0
  206. package/src/views/ReactSubView.tsx +145 -0
  207. package/src/views/abstracts.ts +46 -0
  208. package/src/views/accessibility_element.ts +86 -0
  209. package/src/views/affiliations.ts +254 -0
  210. package/src/views/alt_title.ts +85 -0
  211. package/src/views/alt_titles_section.ts +97 -0
  212. package/src/views/attachment.ts +160 -0
  213. package/src/views/attachments.ts +72 -0
  214. package/src/views/author_notes.ts +96 -0
  215. package/src/views/award.ts +194 -0
  216. package/src/views/awards.ts +59 -0
  217. package/src/views/base_node_view.ts +85 -0
  218. package/src/views/bibliography_element.ts +313 -0
  219. package/src/views/block_view.ts +100 -0
  220. package/src/views/blockquote_element.ts +26 -0
  221. package/src/views/blockquote_element_editable.ts +24 -0
  222. package/src/views/box_element.ts +33 -0
  223. package/src/views/caption.ts +37 -0
  224. package/src/views/caption_title.ts +33 -0
  225. package/src/views/citation.ts +67 -0
  226. package/src/views/citation_editable.ts +312 -0
  227. package/src/views/contributors.ts +341 -0
  228. package/src/views/creators.ts +82 -0
  229. package/src/views/cross_reference.ts +74 -0
  230. package/src/views/cross_reference_editable.ts +113 -0
  231. package/src/views/editable_block.ts +141 -0
  232. package/src/views/embed.ts +345 -0
  233. package/src/views/empty.ts +26 -0
  234. package/src/views/equation.ts +47 -0
  235. package/src/views/equation_editable.ts +84 -0
  236. package/src/views/equation_element.ts +29 -0
  237. package/src/views/equation_element_editable.ts +21 -0
  238. package/src/views/figure.ts +84 -0
  239. package/src/views/figure_editable.ts +361 -0
  240. package/src/views/figure_element.ts +197 -0
  241. package/src/views/figure_element_editable.ts +21 -0
  242. package/src/views/footnote.ts +236 -0
  243. package/src/views/footnotes_element.ts +54 -0
  244. package/src/views/general_table_footnote.ts +140 -0
  245. package/src/views/hero_image.ts +76 -0
  246. package/src/views/hero_image_editable.ts +21 -0
  247. package/src/views/image_element.ts +373 -0
  248. package/src/views/image_element_editable.ts +21 -0
  249. package/src/views/inline_equation.ts +47 -0
  250. package/src/views/inline_equation_editable.ts +70 -0
  251. package/src/views/inline_footnote.ts +264 -0
  252. package/src/views/inline_footnote_editable.ts +20 -0
  253. package/src/views/keyword.ts +127 -0
  254. package/src/views/keyword_group.ts +109 -0
  255. package/src/views/link.ts +27 -0
  256. package/src/views/link_editable.ts +169 -0
  257. package/src/views/list.ts +46 -0
  258. package/src/views/list_item.ts +26 -0
  259. package/src/views/paragraph.ts +26 -0
  260. package/src/views/paragraph_editable.ts +21 -0
  261. package/src/views/placeholder.ts +35 -0
  262. package/src/views/placeholder_element.ts +38 -0
  263. package/src/views/placeholder_element_editable.ts +21 -0
  264. package/src/views/pullquote_element.ts +106 -0
  265. package/src/views/pullquote_element_editable.ts +24 -0
  266. package/src/views/quote_image_editable.ts +84 -0
  267. package/src/views/section.ts +64 -0
  268. package/src/views/section_label.ts +20 -0
  269. package/src/views/section_title.ts +87 -0
  270. package/src/views/section_title_editable.ts +21 -0
  271. package/src/views/subtitle.ts +42 -0
  272. package/src/views/subtitle_editable.ts +20 -0
  273. package/src/views/subtitles.ts +34 -0
  274. package/src/views/subtitles_editable.ts +21 -0
  275. package/src/views/supplement.ts +236 -0
  276. package/src/views/supplement_editable.ts +20 -0
  277. package/src/views/supplements.ts +65 -0
  278. package/src/views/supplements_editable.ts +21 -0
  279. package/src/views/table_cell.ts +150 -0
  280. package/src/views/table_element.ts +33 -0
  281. package/src/views/table_element_editable.ts +21 -0
  282. package/src/views/table_element_footer.ts +41 -0
  283. package/src/views/title.ts +46 -0
  284. package/src/views/title_editable.ts +20 -0
  285. package/src/views/trans_graphical_abstract.ts +55 -0
  286. package/src/views/trans_graphical_abstract_editable.ts +21 -0
  287. package/src/views/translated_abstract.ts +53 -0
  288. package/src/views/translated_abstract_editable.ts +21 -0
  289. package/dist/cjs/lib/statistics.js +0 -38
@@ -0,0 +1,54 @@
1
+ /*!
2
+ * © 2025 Atypon Systems LLC
3
+ *
4
+ * Licensed under the Apache License, Version 2.0 (the "License");
5
+ * you may not use this file except in compliance with the License.
6
+ * You may obtain a copy of the License at
7
+ *
8
+ * http://www.apache.org/licenses/LICENSE-2.0
9
+ *
10
+ * Unless required by applicable law or agreed to in writing, software
11
+ * distributed under the License is distributed on an "AS IS" BASIS,
12
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13
+ * See the License for the specific language governing permissions and
14
+ * limitations under the License.
15
+ */
16
+ import { IconTextButton } from '@manuscripts/style-guide'
17
+ import React from 'react'
18
+ import styled from 'styled-components'
19
+
20
+ const Footer = styled.div`
21
+ display: flex;
22
+ justify-content: flex-end;
23
+ align-items: center;
24
+ gap: ${(props) => props.theme.grid.unit * 6}px;
25
+ padding: 16px 32px;
26
+ min-height: 40px;
27
+ box-shadow: 0px -2px 12px 0px rgba(216, 216, 216, 0.26);
28
+ border-radius: 0px 0px 8px 8px;
29
+ position: relative;
30
+ z-index: 3;
31
+ `
32
+
33
+ const StyledIconTextButton = styled(IconTextButton)`
34
+ color: ${(props) => props.theme.colors.brand.default};
35
+ `
36
+
37
+ const FormFooter = ({
38
+ onCancel,
39
+ primaryAction,
40
+ }: {
41
+ onCancel: () => void
42
+ primaryAction?: React.ReactNode
43
+ }) => {
44
+ return (
45
+ <Footer>
46
+ <StyledIconTextButton color="secondary" onClick={onCancel}>
47
+ Close
48
+ </StyledIconTextButton>
49
+ {primaryAction}
50
+ </Footer>
51
+ )
52
+ }
53
+
54
+ export default FormFooter
@@ -0,0 +1,71 @@
1
+ /*!
2
+ * © 2024 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
+ import styled from 'styled-components'
18
+
19
+ const Container = styled.div`
20
+ display: flex;
21
+ flex-direction: column;
22
+ align-items: center;
23
+ justify-content: center;
24
+ height: 100%;
25
+ overflow-y: auto;
26
+ `
27
+
28
+ const Placeholder = styled.div`
29
+ margin-bottom: ${(props) => props.theme.grid.unit * 5}px;
30
+ `
31
+
32
+ const Action = styled.div`
33
+ font-size: ${(props) => props.theme.font.size.xlarge};
34
+ font-weight: ${(props) => props.theme.font.weight.medium};
35
+ letter-spacing: -0.5px;
36
+ `
37
+
38
+ const Message = styled.div`
39
+ max-width: 400px;
40
+ font-size: ${(props) => props.theme.font.size.xlarge};
41
+ margin-top: ${(props) => props.theme.grid.unit * 6}px;
42
+ font-weight: ${(props) => props.theme.font.weight.light};
43
+ color: ${(props) => props.theme.colors.text.secondary};
44
+ text-align: center;
45
+
46
+ @media (max-width: 850px) {
47
+ margin-right: ${(props) => props.theme.grid.unit * 5}px;
48
+ margin-left: ${(props) => props.theme.grid.unit * 5}px;
49
+ max-width: 350px;
50
+ }
51
+ `
52
+
53
+ interface FormPlaceholderProps {
54
+ type: string
55
+ title: string
56
+ message: string
57
+ placeholderIcon: React.ReactNode
58
+ }
59
+
60
+ export const FormPlaceholder: React.FC<FormPlaceholderProps> = ({
61
+ type,
62
+ title,
63
+ message,
64
+ placeholderIcon,
65
+ }) => (
66
+ <Container data-cy={`${type}-details`}>
67
+ <Placeholder>{placeholderIcon}</Placeholder>
68
+ <Action>{title}</Action>
69
+ <Message>{message}</Message>
70
+ </Container>
71
+ )
@@ -0,0 +1,88 @@
1
+ /*!
2
+ * © 2024 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 { PrimaryButton } from '@manuscripts/style-guide'
17
+ import React from 'react'
18
+
19
+ import { ConfirmationDialog, DialogType } from '../dialog/ConfirmationDialog'
20
+ import styled from 'styled-components'
21
+
22
+ export interface ModalFormSaveButtonProps {
23
+ form: string
24
+ isDisableSave: boolean
25
+ onSubmitForm?: () => void | Promise<void>
26
+ label?: string
27
+ }
28
+
29
+ export const ModalFormSaveButton: React.FC<ModalFormSaveButtonProps> = ({
30
+ form,
31
+ isDisableSave,
32
+ onSubmitForm,
33
+ label,
34
+ }) => {
35
+ label = label || 'Save Changes'
36
+
37
+ const saveButton = onSubmitForm ? (
38
+ <StylePrimaryButton
39
+ data-cy="save-changes"
40
+ disabled={isDisableSave}
41
+ type="button"
42
+ onClick={() => {
43
+ if (!isDisableSave) {
44
+ void onSubmitForm()
45
+ }
46
+ }}
47
+ >
48
+ {label}
49
+ </StylePrimaryButton>
50
+ ) : (
51
+ <StylePrimaryButton disabled={isDisableSave} type="submit" form={form}>
52
+ {label}
53
+ </StylePrimaryButton>
54
+ )
55
+
56
+ return saveButton
57
+ }
58
+
59
+ interface ModalFormActionsProps {
60
+ type: string
61
+ onDelete: () => void
62
+ showingDeleteDialog: boolean
63
+ showDeleteDialog: () => void
64
+ }
65
+
66
+ export const ModalFormActions: React.FC<ModalFormActionsProps> = ({
67
+ type,
68
+ onDelete,
69
+ showingDeleteDialog,
70
+ showDeleteDialog,
71
+ }) => {
72
+ return (
73
+ <ConfirmationDialog
74
+ isOpen={showingDeleteDialog}
75
+ onPrimary={() => {
76
+ onDelete()
77
+ showDeleteDialog()
78
+ }}
79
+ onSecondary={showDeleteDialog}
80
+ type={DialogType.DELETE}
81
+ entityType={type}
82
+ />
83
+ )
84
+ }
85
+
86
+ const StylePrimaryButton = styled(PrimaryButton)`
87
+ min-width: 145px;
88
+ `
@@ -0,0 +1,49 @@
1
+ /*!
2
+ * © 2025 Atypon Systems LLC
3
+ *
4
+ * Licensed under the Apache License, Version 2.0 (the "License");
5
+ * you may not use this file except in compliance with the License.
6
+ * You may obtain a copy of the License at
7
+ *
8
+ * http://www.apache.org/licenses/LICENSE-2.0
9
+ *
10
+ * Unless required by applicable law or agreed to in writing, software
11
+ * distributed under the License is distributed on an "AS IS" BASIS,
12
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13
+ * See the License for the specific language governing permissions and
14
+ * limitations under the License.
15
+ */
16
+ import { Label } from '@manuscripts/style-guide'
17
+ import React from 'react'
18
+ import styled from 'styled-components'
19
+
20
+ interface UnsavedLabelProps {
21
+ htmlFor: string
22
+ showDot: boolean
23
+ children: React.ReactNode
24
+ }
25
+
26
+ export const UnsavedLabel: React.FC<UnsavedLabelProps> = ({
27
+ htmlFor,
28
+ showDot,
29
+ children,
30
+ }) => (
31
+ <UnsavedLabelRow>
32
+ {showDot ? <FieldUnsavedDot aria-hidden /> : null}
33
+ <Label htmlFor={htmlFor}>{children}</Label>
34
+ </UnsavedLabelRow>
35
+ )
36
+
37
+ export const UnsavedLabelRow = styled.div`
38
+ display: inline-flex;
39
+ align-items: center;
40
+ gap: 6px;
41
+ `
42
+
43
+ export const FieldUnsavedDot = styled.span`
44
+ width: 8px;
45
+ height: 8px;
46
+ border-radius: 50%;
47
+ background: ${(props) => props.theme.colors.text.warning};
48
+ flex-shrink: 0;
49
+ `
@@ -0,0 +1,56 @@
1
+ /*!
2
+ * © 2019 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
+
17
+ import { useCallback, useEffect, useRef, useState } from 'react'
18
+
19
+ export const useDebounce = <T>(value: T, delay: number): T => {
20
+ const [debouncedValue, setDebouncedValue] = useState(value)
21
+
22
+ useEffect(() => {
23
+ const handler = setTimeout(() => {
24
+ setDebouncedValue(value)
25
+ }, delay)
26
+
27
+ return () => {
28
+ clearTimeout(handler)
29
+ }
30
+ }, [value, delay])
31
+
32
+ return debouncedValue
33
+ }
34
+
35
+ export default function useDebounced<Input, Output>(
36
+ fn: (arg: Input) => Promise<Output>,
37
+ delay: number
38
+ ): (arg: Input) => Promise<Output> {
39
+ const timeoutRef = useRef<ReturnType<typeof setTimeout> | null>(null)
40
+
41
+ return useCallback(
42
+ (arg: Input) => {
43
+ const timeout = timeoutRef.current
44
+ if (timeout) {
45
+ clearTimeout(timeout)
46
+ }
47
+
48
+ return new Promise((resolve) => {
49
+ timeoutRef.current = setTimeout(async () => {
50
+ resolve(await fn(arg))
51
+ }, delay)
52
+ })
53
+ },
54
+ [fn, delay]
55
+ )
56
+ }
@@ -0,0 +1,51 @@
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 { FormikProps, getIn, useFormikContext } from 'formik'
17
+ import { useEffect } from 'react'
18
+
19
+ import { AffiliationAttrs } from '../../lib/authors'
20
+
21
+ export function isInstitutionError(
22
+ formik: FormikProps<AffiliationAttrs>,
23
+ newEntity: boolean
24
+ ) {
25
+ if (!getIn(formik.errors, 'institution')) {
26
+ return false
27
+ }
28
+ if (newEntity) {
29
+ return Boolean(formik.touched.institution || formik.dirty)
30
+ }
31
+ return Boolean(formik.touched.institution)
32
+ }
33
+
34
+ export function affiliationShowsErrorIndicator(
35
+ formik: FormikProps<AffiliationAttrs>,
36
+ newEntity: boolean
37
+ ) {
38
+ return isInstitutionError(formik, newEntity)
39
+ }
40
+
41
+ export const useAffiliationShowsErrorIndicator = (
42
+ newEntity: boolean,
43
+ onChange?: (hasError: boolean) => void
44
+ ) => {
45
+ const formik = useFormikContext<AffiliationAttrs>()
46
+ const hasError = affiliationShowsErrorIndicator(formik, newEntity)
47
+
48
+ useEffect(() => {
49
+ onChange?.(hasError)
50
+ }, [hasError, onChange])
51
+ }
@@ -0,0 +1,73 @@
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 { FormikProps, getIn, useFormikContext } from 'formik'
17
+ import { useEffect } from 'react'
18
+
19
+ import { ContributorAttrs } from '../../lib/authors'
20
+
21
+ export function isNamePairError(
22
+ formik: FormikProps<ContributorAttrs>,
23
+ newEntity: boolean,
24
+ requiredContinueActive = false
25
+ ) {
26
+ if (!getIn(formik.errors, 'given')) {
27
+ return false
28
+ }
29
+ if (requiredContinueActive) {
30
+ return true
31
+ }
32
+ if (newEntity) {
33
+ return Boolean(formik.touched.given || formik.touched.family)
34
+ }
35
+ return Boolean(formik.touched.given || formik.touched.family || formik.dirty)
36
+ }
37
+
38
+ export function authorShowsErrorIndicator(
39
+ formik: FormikProps<ContributorAttrs>,
40
+ newEntity: boolean,
41
+ requiredContinueActive = false
42
+ ) {
43
+ if (isNamePairError(formik, newEntity, requiredContinueActive)) {
44
+ return true
45
+ }
46
+ if (
47
+ (getIn(formik.touched, 'email') || requiredContinueActive) &&
48
+ getIn(formik.errors, 'email')
49
+ ) {
50
+ return true
51
+ }
52
+ if (getIn(formik.touched, 'ORCID') && getIn(formik.errors, 'ORCID')) {
53
+ return true
54
+ }
55
+ return false
56
+ }
57
+
58
+ export const useAuthorShowsErrorIndicator = (
59
+ newEntity: boolean,
60
+ requiredContinueActive: boolean,
61
+ onChange?: (hasError: boolean) => void
62
+ ) => {
63
+ const formik = useFormikContext<ContributorAttrs>()
64
+ const hasError = authorShowsErrorIndicator(
65
+ formik,
66
+ newEntity,
67
+ requiredContinueActive
68
+ )
69
+
70
+ useEffect(() => {
71
+ onChange?.(hasError)
72
+ }, [hasError, onChange])
73
+ }
@@ -0,0 +1,56 @@
1
+ /*!
2
+ * © 2025 Atypon Systems LLC
3
+ *
4
+ * Licensed under the Apache License, Version 2.0 (the "License");
5
+ * you may not use this file except in compliance with the License.
6
+ * You may obtain a copy of the License at
7
+ *
8
+ * http://www.apache.org/licenses/LICENSE-2.0
9
+ *
10
+ * Unless required by applicable law or agreed to in writing, software
11
+ * distributed under the License is distributed on an "AS IS" BASIS,
12
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13
+ * See the License for the specific language governing permissions and
14
+ * limitations under the License.
15
+ */
16
+
17
+ import { Shortcut, ShortcutConnector } from '@manuscripts/style-guide'
18
+ import React, { JSX } from 'react'
19
+
20
+ import { isMac } from '../../lib/platform'
21
+
22
+ const keyMap: Record<string, React.ReactNode> = {
23
+ CommandOrControl: isMac ? '⌘' : 'Ctrl',
24
+ Option: isMac ? '⌥' : 'Alt',
25
+ Shift: isMac ? '⇧' : 'Shift',
26
+ ArrowUp: '↑',
27
+ ArrowDown: '↓',
28
+ ArrowLeft: '←',
29
+ ArrowRight: '→',
30
+ BracketLeft: '[',
31
+ BracketRight: ']',
32
+ Escape: 'Esc',
33
+ Tab: 'Tab',
34
+ Enter: '↵',
35
+ }
36
+
37
+ export const formattedShortCut = (accelerator: string): JSX.Element => {
38
+ const parts = accelerator.split('+').map((p) => p.trim())
39
+
40
+ return (
41
+ <>
42
+ {parts.map((part, index) => {
43
+ const content = keyMap[part] ?? part
44
+
45
+ return (
46
+ <React.Fragment key={`${part}-${index}`}>
47
+ <Shortcut>{content}</Shortcut>
48
+ {index < parts.length - 1 && (
49
+ <ShortcutConnector>+</ShortcutConnector>
50
+ )}
51
+ </React.Fragment>
52
+ )
53
+ })}
54
+ </>
55
+ )
56
+ }