@manuscripts/body-editor 3.12.66 → 3.13.0

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,87 @@
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 { schema, SectionTitleNode } from '@manuscripts/transform'
18
+ import { findParentNodeOfTypeClosestToPos } from 'prosemirror-utils'
19
+
20
+ import { sectionTitleKey } from '../plugins/section_title'
21
+ import BlockView from './block_view'
22
+ import { createNodeView } from './creators'
23
+ export class SectionTitleView extends BlockView<SectionTitleNode> {
24
+ public contentDOM: HTMLElement
25
+ public elementType = 'h1'
26
+ private element: HTMLElement
27
+
28
+ public protectedSectionTitles = [
29
+ schema.nodes.bibliography_section,
30
+ schema.nodes.footnotes_section,
31
+ schema.nodes.graphical_abstract_section,
32
+ schema.nodes.trans_graphical_abstract,
33
+ schema.nodes.supplements,
34
+ ]
35
+
36
+ public createElement = () => {
37
+ this.element = document.createElement(this.elementType)
38
+ this.element.className = 'block'
39
+ this.dom.appendChild(this.element)
40
+
41
+ const $pos = this.view.state.doc.resolve(this.getPos())
42
+
43
+ if (this.protectedSectionTitles.includes($pos.parent.type)) {
44
+ this.element.setAttribute('contenteditable', 'false')
45
+ this.renderContent()
46
+ } else {
47
+ this.contentDOM = this.element
48
+ }
49
+ }
50
+
51
+ private renderContent() {
52
+ this.element.textContent = this.node.textContent
53
+ }
54
+
55
+ public updateContents() {
56
+ super.updateContents()
57
+
58
+ if (!this.element.isContentEditable) {
59
+ this.renderContent()
60
+ }
61
+
62
+ const $pos = this.view.state.doc.resolve(this.getPos())
63
+ const sectionTitleState = sectionTitleKey.getState(this.view.state)
64
+ const parentSection = findParentNodeOfTypeClosestToPos(
65
+ $pos,
66
+ schema.nodes.section
67
+ )
68
+ const sectionNumber = sectionTitleState?.get(parentSection?.node.attrs.id)
69
+ let level = $pos.depth > 1 ? $pos.depth - 1 : $pos.depth
70
+
71
+ if (findParentNodeOfTypeClosestToPos($pos, schema.nodes.box_element)) {
72
+ level = level - 2
73
+ }
74
+
75
+ if (this.node.childCount) {
76
+ this.element.classList.remove('empty-node')
77
+ } else {
78
+ this.element.classList.add('empty-node')
79
+ }
80
+ if (sectionTitleState && sectionNumber) {
81
+ this.element.dataset.sectionNumber = sectionNumber
82
+ this.element.dataset.titleLevel = level.toString()
83
+ }
84
+ }
85
+ }
86
+
87
+ export default createNodeView(SectionTitleView)
@@ -0,0 +1,21 @@
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 { createEditableNodeView } from './creators'
18
+ import { EditableBlock } from './editable_block'
19
+ import { SectionTitleView } from './section_title'
20
+
21
+ export default createEditableNodeView(EditableBlock(SectionTitleView))
@@ -0,0 +1,42 @@
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 { ManuscriptNodeView, SubtitleNode } from '@manuscripts/transform'
18
+
19
+ import { BaseNodeView } from './base_node_view'
20
+ import { createNodeView } from './creators'
21
+
22
+ export class SubtitleView
23
+ extends BaseNodeView<SubtitleNode>
24
+ implements ManuscriptNodeView
25
+ {
26
+ public contentDOM: HTMLElement
27
+
28
+ public initialise = () => {
29
+ this.createDOM()
30
+ }
31
+
32
+ protected createDOM = () => {
33
+ this.dom = document.createElement('div')
34
+ this.dom.classList.add('manuscript-subtitle')
35
+
36
+ this.contentDOM = document.createElement('span')
37
+ this.dom.appendChild(this.contentDOM)
38
+
39
+ this.updateContents()
40
+ }
41
+ }
42
+ export default createNodeView(SubtitleView)
@@ -0,0 +1,20 @@
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 { createEditableNodeView } from './creators'
18
+ import { SubtitleView } from './subtitle'
19
+
20
+ export default createEditableNodeView(SubtitleView)
@@ -0,0 +1,34 @@
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 { ManuscriptNodeView, SubtitlesNode } from '@manuscripts/transform'
18
+
19
+ import { Trackable } from '../types'
20
+ import BlockView from './block_view'
21
+ import { createNodeView } from './creators'
22
+
23
+ export class SubtitlesView
24
+ extends BlockView<Trackable<SubtitlesNode>>
25
+ implements ManuscriptNodeView
26
+ {
27
+ public createElement = () => {
28
+ this.contentDOM = document.createElement('div')
29
+ this.contentDOM.classList.add('block')
30
+ this.dom.appendChild(this.contentDOM)
31
+ }
32
+ }
33
+
34
+ export default createNodeView(SubtitlesView)
@@ -0,0 +1,21 @@
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 { createEditableNodeView } from './creators'
18
+ import { EditableBlock } from './editable_block'
19
+ import { SubtitlesView } from './subtitles'
20
+
21
+ export default createEditableNodeView(EditableBlock(SubtitlesView))
@@ -0,0 +1,236 @@
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 { getFileIcon } from '@manuscripts/style-guide'
18
+ import { SupplementNode } from '@manuscripts/transform'
19
+ import { renderToStaticMarkup } from 'react-dom/server'
20
+
21
+ import { draggableIcon } from '../icons'
22
+ import { findNodeByID } from '../lib/doc'
23
+ import { Trackable } from '../types'
24
+ import { BaseNodeView } from './base_node_view'
25
+ import { createNodeView } from './creators'
26
+
27
+ export class SupplementView extends BaseNodeView<Trackable<SupplementNode>> {
28
+ private supplementInfoEl: HTMLDivElement
29
+ private static currentDragSupplementId: string | null = null
30
+ private dragIcon: HTMLDivElement | undefined
31
+
32
+ public ignoreMutation = () => true
33
+
34
+ public initialise() {
35
+ this.createElement()
36
+ this.updateContents()
37
+ this.setupDragAndDrop()
38
+ }
39
+
40
+ public createElement = () => {
41
+ this.dom = document.createElement('div')
42
+ this.dom.classList.add('supplement-item')
43
+ this.dom.classList.add('block')
44
+ this.dom.setAttribute('id', this.node.attrs.id)
45
+ this.dom.setAttribute('href', this.node.attrs.href)
46
+ this.dom.draggable = true
47
+
48
+ this.contentDOM = document.createElement('div')
49
+ this.contentDOM.classList.add('supplement-caption')
50
+ this.dom.appendChild(this.contentDOM)
51
+
52
+ this.addFileInfo()
53
+ this.addDragIcon()
54
+ }
55
+
56
+ public updateContents() {
57
+ super.updateContents()
58
+ this.refreshFileInfo()
59
+ }
60
+
61
+ private getDropSide(element: Element, clientY: number): 'before' | 'after' {
62
+ const { top, bottom } = element.getBoundingClientRect()
63
+ const middleY = (top + bottom) / 2
64
+ return clientY > middleY ? 'after' : 'before'
65
+ }
66
+
67
+ private noActualMove(
68
+ currentPos: number,
69
+ nodeSize: number,
70
+ targetPos: number
71
+ ): boolean {
72
+ // No-move if dropping at the node’s start or end position
73
+ return targetPos === currentPos || targetPos === currentPos + nodeSize
74
+ }
75
+
76
+ private handleDragStart() {
77
+ const supplementId = this.node.attrs.id
78
+ SupplementView.currentDragSupplementId = supplementId
79
+ this.dom.classList.add('dragging')
80
+ }
81
+
82
+ private setupDragAndDrop() {
83
+ const clearDropClasses = () => {
84
+ this.dom.classList.remove('drop-target-above', 'drop-target-below')
85
+ }
86
+
87
+ this.dom.addEventListener('dragstart', () => {
88
+ if (this.node.attrs.id) {
89
+ this.handleDragStart()
90
+ }
91
+ })
92
+
93
+ this.dom.addEventListener('dragend', () => {
94
+ SupplementView.currentDragSupplementId = null
95
+ this.dom.classList.remove('dragging')
96
+ clearDropClasses()
97
+ })
98
+
99
+ this.dom.addEventListener('dragover', (e) => {
100
+ if (SupplementView.currentDragSupplementId) {
101
+ e.preventDefault()
102
+ e.stopPropagation()
103
+ const side = this.getDropSide(this.dom, e.clientY)
104
+ clearDropClasses()
105
+ this.dom.classList.add(
106
+ side === 'before' ? 'drop-target-above' : 'drop-target-below'
107
+ )
108
+ }
109
+ })
110
+
111
+ this.dom.addEventListener('dragleave', (e) => {
112
+ if (!this.dom.contains(e.relatedTarget as Node)) {
113
+ clearDropClasses()
114
+ }
115
+ })
116
+
117
+ this.dom.addEventListener('drop', (e) => {
118
+ if (!SupplementView.currentDragSupplementId) {
119
+ return
120
+ }
121
+
122
+ e.preventDefault()
123
+ e.stopPropagation()
124
+
125
+ const supplementId = SupplementView.currentDragSupplementId
126
+ if (!supplementId) {
127
+ return
128
+ }
129
+ const { state } = this.view
130
+ const supplement = findNodeByID(state.doc, supplementId)
131
+ if (!supplement) {
132
+ return
133
+ }
134
+
135
+ const toPos = this.getPos()
136
+
137
+ const side = this.getDropSide(this.dom, e.clientY)
138
+ const targetPos = side === 'before' ? toPos : toPos + this.node.nodeSize
139
+
140
+ // Check if this would be a no actual position change
141
+ if (
142
+ this.noActualMove(supplement.pos, supplement.node.nodeSize, targetPos)
143
+ ) {
144
+ clearDropClasses()
145
+ return
146
+ }
147
+ this.moveSupplement(
148
+ supplement.pos,
149
+ supplement.node as SupplementNode,
150
+ targetPos
151
+ )
152
+ clearDropClasses()
153
+ })
154
+ }
155
+
156
+ private moveSupplement(
157
+ fromPos: number,
158
+ fromNode: SupplementNode,
159
+ targetPos: number
160
+ ) {
161
+ const { state } = this.view
162
+ const { tr } = state
163
+
164
+ tr.insert(targetPos, fromNode)
165
+
166
+ const mappedFrom = tr.mapping.map(fromPos, -1)
167
+
168
+ tr.delete(mappedFrom, mappedFrom + fromNode.nodeSize)
169
+
170
+ this.view.dispatch(tr)
171
+ }
172
+
173
+ private addFileInfo() {
174
+ this.supplementInfoEl = document.createElement('div')
175
+ this.supplementInfoEl.classList.add('supplement-file-info')
176
+ this.supplementInfoEl.contentEditable = 'false'
177
+
178
+ // Get the file from the file management system
179
+ const files = this.props.getFiles()
180
+ const file = files.find((f) => f.id === this.node.attrs.href)
181
+
182
+ if (file) {
183
+ const iconElement = document.createElement('span')
184
+ iconElement.classList.add('supplement-file-icon')
185
+
186
+ const icon = getFileIcon(file.name)
187
+ if (icon) {
188
+ iconElement.innerHTML = renderToStaticMarkup(icon)
189
+ }
190
+
191
+ this.supplementInfoEl.appendChild(iconElement)
192
+
193
+ // Add file name
194
+ const fileName = document.createElement('span')
195
+ fileName.classList.add('supplement-file-name')
196
+ fileName.textContent = file.name
197
+ this.supplementInfoEl.appendChild(fileName)
198
+ } else {
199
+ // Show placeholder if file not found
200
+ const placeholder = document.createElement('span')
201
+ placeholder.textContent = 'File not found'
202
+ this.supplementInfoEl.appendChild(placeholder)
203
+ }
204
+
205
+ // Add file info to the supplement-item
206
+ this.dom.appendChild(this.supplementInfoEl)
207
+ }
208
+
209
+ private refreshFileInfo() {
210
+ this.supplementInfoEl.remove()
211
+
212
+ // Rebuild with the latest attrs
213
+ this.addFileInfo()
214
+ }
215
+
216
+ private addDragIcon() {
217
+ if (this.dragIcon) {
218
+ this.dragIcon.remove()
219
+ this.dragIcon = undefined
220
+ }
221
+
222
+ const dragIcon = document.createElement('div')
223
+ dragIcon.className = 'drag-icon'
224
+ dragIcon.innerHTML = draggableIcon
225
+ dragIcon.draggable = false
226
+
227
+ dragIcon.addEventListener('mousedown', (e) => {
228
+ e.stopPropagation()
229
+ })
230
+
231
+ this.dragIcon = dragIcon
232
+ this.dom.appendChild(dragIcon)
233
+ }
234
+ }
235
+
236
+ export default createNodeView(SupplementView)
@@ -0,0 +1,20 @@
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 { createEditableNodeView } from './creators'
18
+ import { SupplementView } from './supplement'
19
+
20
+ export default createEditableNodeView(SupplementView)
@@ -0,0 +1,65 @@
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 { SupplementsNode } from '@manuscripts/transform'
18
+
19
+ import { arrowUp } from '../icons'
20
+ import { handleEnterKey } from '../lib/navigation-utils'
21
+ import { Trackable } from '../types'
22
+ import BlockView from './block_view'
23
+ import { createNodeView } from './creators'
24
+
25
+ export class SupplementsView extends BlockView<Trackable<SupplementsNode>> {
26
+ private collapsed = false
27
+ private toggleButton: HTMLElement
28
+
29
+ public ignoreMutation = () => true
30
+
31
+ public createElement = () => {
32
+ this.toggleButton = document.createElement('button')
33
+ this.toggleButton.classList.add('supplements-toggle-btn', 'button-reset')
34
+ this.toggleButton.innerHTML = arrowUp
35
+ const handleToggle = () => {
36
+ this.collapsed = !this.collapsed
37
+ this.toggleContent()
38
+ this.toggleButton?.classList.toggle('collapsed', this.collapsed)
39
+ }
40
+
41
+ this.toggleButton.onclick = handleToggle
42
+ this.toggleButton.addEventListener('keydown', handleEnterKey(handleToggle))
43
+
44
+ this.contentDOM = document.createElement('div')
45
+ this.contentDOM.classList.add('supplements-content')
46
+ this.contentDOM.classList.add('block')
47
+
48
+ this.dom.appendChild(this.toggleButton)
49
+ this.dom.setAttribute('id', this.node.attrs.id)
50
+
51
+ this.dom.appendChild(this.contentDOM)
52
+ }
53
+
54
+ private toggleContent() {
55
+ // Hide/show supplement items
56
+ const supplementItems =
57
+ this.contentDOM?.querySelectorAll('.supplement-item')
58
+ supplementItems?.forEach((item) => {
59
+ const element = item as HTMLElement
60
+ element.style.display = this.collapsed ? 'none' : ''
61
+ })
62
+ }
63
+ }
64
+
65
+ export default createNodeView(SupplementsView)
@@ -0,0 +1,21 @@
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 { createEditableNodeView } from './creators'
18
+ import { EditableBlock } from './editable_block'
19
+ import { SupplementsView } from './supplements'
20
+
21
+ export default createEditableNodeView(EditableBlock(SupplementsView))