@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,236 @@
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 { ContextMenu, ContextMenuProps } from '@manuscripts/style-guide'
18
+ import { isDeleted, isPendingInsert } from '@manuscripts/track-changes-plugin'
19
+ import { FootnoteNode, ManuscriptNode, schema } from '@manuscripts/transform'
20
+
21
+ import { isEqual } from 'lodash'
22
+ import { NodeSelection, Transaction } from 'prosemirror-state'
23
+ import { findParentNodeOfTypeClosestToPos } from 'prosemirror-utils'
24
+
25
+ import {
26
+ DeleteFootnoteDialog,
27
+ DeleteFootnoteDialogProps,
28
+ } from '../components/views/DeleteFootnoteDialog'
29
+ import { alertIcon } from '../icons'
30
+ import { getFootnotesElementState } from '../lib/footnotes'
31
+ import { Trackable } from '../types'
32
+ import { BaseNodeView } from './base_node_view'
33
+ import { createNodeView } from './creators'
34
+ import ReactSubView from './ReactSubView'
35
+ import { handleEnterKey } from '../lib/navigation-utils'
36
+
37
+ export class FootnoteView extends BaseNodeView<Trackable<FootnoteNode>> {
38
+ dialog: HTMLElement
39
+ contextMenu: HTMLDivElement
40
+
41
+ public initialise = () => {
42
+ this.dom = document.createElement('div')
43
+ this.dom.classList.add('footnote')
44
+ this.dom.tabIndex = 0
45
+ this.contentDOM = document.createElement('div')
46
+ this.contentDOM.classList.add('footnote-text')
47
+ this.dom.addEventListener('mousedown', (e) => this.handleClick(e, false))
48
+ this.dom.addEventListener(
49
+ 'keydown',
50
+ handleEnterKey((e) => this.handleClick(e, true))
51
+ )
52
+ this.updateContents()
53
+ }
54
+
55
+ public updateContents() {
56
+ super.updateContents()
57
+
58
+ const { id, fn } = this.getFootnoteState()
59
+
60
+ if (!fn) {
61
+ return
62
+ }
63
+
64
+ const marker = document.createElement('span')
65
+ if (!isDeleted(this.node) && fn.unusedFootnoteIDs.has(id)) {
66
+ marker.classList.add('uncited-footnote')
67
+ marker.innerHTML = alertIcon
68
+ } else {
69
+ marker.classList.add('footnote-marker')
70
+ marker.innerText = fn.labels.get(id) || ''
71
+ }
72
+
73
+ this.dom.innerHTML = ''
74
+ this.dom.appendChild(marker)
75
+ this.contentDOM && this.dom.appendChild(this.contentDOM)
76
+ }
77
+
78
+ getFootnoteState() {
79
+ const id = this.node.attrs.id
80
+ const fn = getFootnotesElementState(this.view.state, id)
81
+ return { id, fn }
82
+ }
83
+
84
+ showContextMenu(element: HTMLElement, autoFocus: boolean) {
85
+ this.props.popper.destroy()
86
+
87
+ const can = this.props.getCapabilities()
88
+ const { id, fn } = this.getFootnoteState()
89
+
90
+ const componentProps: ContextMenuProps = {
91
+ actions: [],
92
+ }
93
+ if (!fn?.unusedFootnoteIDs.has(id)) {
94
+ componentProps.actions.push({
95
+ label: 'Go to footnote Refernce',
96
+ action: () => this.handleMarkerClick(),
97
+ icon: 'Scroll',
98
+ })
99
+ }
100
+ if (can.editArticle && !isDeleted(this.node)) {
101
+ componentProps.actions.push({
102
+ label: 'Delete',
103
+ action: () => this.handleDeleteClick(),
104
+ icon: 'Delete',
105
+ })
106
+ }
107
+
108
+ this.contextMenu = ReactSubView(
109
+ this.props,
110
+ ContextMenu,
111
+ componentProps,
112
+ this.node,
113
+ this.getPos,
114
+ this.view,
115
+ ['context-menu', 'footnote-context-menu']
116
+ )
117
+ this.props.popper.show(
118
+ element,
119
+ this.contextMenu,
120
+ 'right-start',
121
+ true,
122
+ [],
123
+ autoFocus
124
+ )
125
+ }
126
+
127
+ handleClick = (event: Event, fromKeyboard = false) => {
128
+ const element = event.target as HTMLElement
129
+ const item = element.closest('.footnote')
130
+ if (item) {
131
+ this.showContextMenu(item as HTMLElement, fromKeyboard)
132
+ }
133
+ }
134
+
135
+ handleMarkerClick = (e?: Event) => {
136
+ e?.preventDefault()
137
+ e?.stopPropagation()
138
+
139
+ const id = this.node.attrs.id
140
+ const fn = getFootnotesElementState(this.view.state, id)
141
+
142
+ if (!fn) {
143
+ return
144
+ }
145
+
146
+ for (const [node, pos] of fn.inlineFootnotes) {
147
+ if (node.attrs.rids.includes(id)) {
148
+ const tr = this.view.state.tr
149
+ const selection = NodeSelection.create(this.view.state.doc, pos)
150
+ tr.setSelection(selection)
151
+ tr.scrollIntoView()
152
+ this.view.dispatch(tr)
153
+ }
154
+ }
155
+ }
156
+
157
+ handleDeleteClick = (e?: Event) => {
158
+ e?.preventDefault()
159
+ e?.stopPropagation()
160
+ const componentProps: DeleteFootnoteDialogProps = {
161
+ header: 'Delete footnote',
162
+ message:
163
+ 'This action will entirely remove the footnote from the list because it will no longer be used.',
164
+ handleDelete: this.handleDelete,
165
+ }
166
+
167
+ this.dialog = ReactSubView(
168
+ this.props,
169
+ DeleteFootnoteDialog,
170
+ componentProps,
171
+ this.node,
172
+ this.getPos,
173
+ this.view
174
+ )
175
+
176
+ this.props.popper.show(this.dom, this.dialog, 'auto', false)
177
+ }
178
+
179
+ handleDelete = () => {
180
+ const tr = this.view.state.tr
181
+ this.deleteInlineFootnotes(tr)
182
+ this.deleteFootnote(tr)
183
+ this.view.dispatch(tr)
184
+ }
185
+
186
+ deleteInlineFootnotes = (tr: Transaction) => {
187
+ const id = this.node.attrs.id
188
+ const fns = getFootnotesElementState(this.view.state, this.node.attrs.id)
189
+ fns?.inlineFootnotes.forEach(([node, pos]) => {
190
+ pos = tr.mapping.map(pos)
191
+ const rids = node.attrs.rids.filter((rid) => rid !== id)
192
+ if (isEqual(rids, node.attrs.rids)) {
193
+ return
194
+ }
195
+ if (!rids.length) {
196
+ tr.delete(pos, pos + node.nodeSize)
197
+ } else {
198
+ tr.setNodeAttribute(pos, 'rids', rids)
199
+ }
200
+ })
201
+ }
202
+
203
+ deleteFootnote = (tr: Transaction) => {
204
+ const pos = tr.mapping.map(this.getPos())
205
+ const $pos = tr.doc.resolve(pos)
206
+ const element = findParentNodeOfTypeClosestToPos(
207
+ $pos,
208
+ schema.nodes.footnotes_element
209
+ )
210
+ tr.delete(pos, pos + this.node.nodeSize)
211
+
212
+ if (
213
+ element &&
214
+ getEffectiveChildCount(element.node) <= 1 &&
215
+ !isPendingInsert(this.node)
216
+ ) {
217
+ tr.delete(
218
+ tr.mapping.map(element.pos),
219
+ tr.mapping.map(element.pos + element.node.nodeSize)
220
+ )
221
+ }
222
+ }
223
+ }
224
+
225
+ const getEffectiveChildCount = (node: ManuscriptNode) => {
226
+ let count = 0
227
+ for (let i = 0; i < node.childCount; i++) {
228
+ const child = node.child(i)
229
+ if (!isDeleted(child)) {
230
+ count++
231
+ }
232
+ }
233
+ return count
234
+ }
235
+
236
+ export default createNodeView(FootnoteView)
@@ -0,0 +1,54 @@
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 { FootnotesElementNode, ManuscriptNode } from '@manuscripts/transform'
18
+
19
+ import BlockView from './block_view'
20
+ import { createNodeOrElementView } from './creators'
21
+
22
+ export class FootnotesElementView extends BlockView<FootnotesElementNode> {
23
+ public elementType = 'div'
24
+
25
+ updateClasses() {
26
+ super.updateClasses()
27
+ updateClasses(this.node, this.dom)
28
+ }
29
+
30
+ updateContents() {
31
+ super.updateContents()
32
+ this.checkEditability()
33
+ }
34
+
35
+ checkEditability = () => {
36
+ const editable =
37
+ this.props.getCapabilities().editArticle && this.node.childCount
38
+ ? 'true'
39
+ : 'false'
40
+ this.contentDOM?.setAttribute('contenteditable', editable)
41
+ this.dom?.setAttribute('contenteditable', editable)
42
+ }
43
+ }
44
+
45
+ const updateClasses = (node: ManuscriptNode, dom: HTMLElement) => {
46
+ !node.childCount && dom.classList.add('empty-node')
47
+ dom.classList.add('footnotes-element')
48
+ }
49
+
50
+ export default createNodeOrElementView(
51
+ FootnotesElementView,
52
+ 'div',
53
+ updateClasses
54
+ )
@@ -0,0 +1,140 @@
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 { ContextMenu, ContextMenuProps } from '@manuscripts/style-guide'
18
+ import { GeneralTableFootnoteNode, schema } from '@manuscripts/transform'
19
+ import {
20
+ findChildrenByType,
21
+ findParentNodeOfTypeClosestToPos,
22
+ } from 'prosemirror-utils'
23
+
24
+ import {
25
+ DeleteFootnoteDialog,
26
+ DeleteFootnoteDialogProps,
27
+ } from '../components/views/DeleteFootnoteDialog'
28
+ import { Trackable } from '../types'
29
+ import { BaseNodeView } from './base_node_view'
30
+ import { createNodeView } from './creators'
31
+ import ReactSubView from './ReactSubView'
32
+ import { isDeleted, isPendingInsert } from '@manuscripts/track-changes-plugin'
33
+
34
+ export class GeneralTableFootnoteView extends BaseNodeView<
35
+ Trackable<GeneralTableFootnoteNode>
36
+ > {
37
+ dialog: HTMLElement
38
+ contextMenu: HTMLDivElement
39
+
40
+ public initialise = () => {
41
+ this.dom = document.createElement('div')
42
+ this.dom.classList.add('footnote', 'general-table-footnote')
43
+ this.dom.addEventListener('mousedown', this.handleClick)
44
+ this.contentDOM = document.createElement('div')
45
+ this.contentDOM.classList.add('footnote-text')
46
+ this.updateContents()
47
+ }
48
+
49
+ public updateContents() {
50
+ super.updateContents()
51
+ this.dom.innerHTML = ''
52
+ this.contentDOM && this.dom.appendChild(this.contentDOM)
53
+ }
54
+
55
+ handleClick = (e: Event) => {
56
+ const element = e.target as HTMLElement
57
+ const can = this.props.getCapabilities()
58
+
59
+ if (can.editArticle) {
60
+ const item = element.closest('.general-table-footnote')
61
+ if (item) {
62
+ this.showContextMenu(item as HTMLElement)
63
+ }
64
+ }
65
+ }
66
+
67
+ showContextMenu(element: HTMLElement) {
68
+ this.props.popper.destroy()
69
+
70
+ const componentProps: ContextMenuProps = {
71
+ actions: [],
72
+ }
73
+ if (!isDeleted(this.node)) {
74
+ componentProps.actions.push({
75
+ label: 'Delete',
76
+ action: () => this.handleDeleteClick(),
77
+ icon: 'Delete',
78
+ })
79
+ }
80
+
81
+ this.contextMenu = ReactSubView(
82
+ this.props,
83
+ ContextMenu,
84
+ componentProps,
85
+ this.node,
86
+ this.getPos,
87
+ this.view,
88
+ ['context-menu', 'footnote-context-menu']
89
+ )
90
+ this.props.popper.show(element, this.contextMenu, 'right-start')
91
+ }
92
+
93
+ handleDeleteClick = () => {
94
+ const componentProps: DeleteFootnoteDialogProps = {
95
+ header: 'Delete table general note',
96
+ message: 'This action will entirely remove the table general note.',
97
+ handleDelete: this.handleDelete,
98
+ }
99
+
100
+ this.dialog = ReactSubView(
101
+ this.props,
102
+ DeleteFootnoteDialog,
103
+ componentProps,
104
+ this.node,
105
+ this.getPos,
106
+ this.view
107
+ )
108
+
109
+ this.props.popper.show(this.dom, this.dialog, 'auto', false)
110
+ }
111
+
112
+ handleDelete = () => {
113
+ const tr = this.view.state.tr
114
+
115
+ const pos = this.getPos()
116
+ const $pos = this.view.state.doc.resolve(pos)
117
+ // eslint-disable-next-line @typescript-eslint/no-non-null-assertion
118
+ const footer = findParentNodeOfTypeClosestToPos(
119
+ $pos,
120
+ schema.nodes.table_element_footer
121
+ )!
122
+ const element = findChildrenByType(
123
+ footer.node,
124
+ schema.nodes.general_table_footnote
125
+ )[0]
126
+ if (element && !isDeleted(element.node)) {
127
+ const from = tr.mapping.map(pos)
128
+ const to = tr.mapping.map(from + this.node.nodeSize)
129
+ tr.delete(from, to)
130
+ }
131
+ if (footer.node.childCount <= 1 && !isPendingInsert(element.node)) {
132
+ const from = tr.mapping.map(footer.pos)
133
+ const to = tr.mapping.map(from + footer.node.nodeSize)
134
+ tr.delete(from, to)
135
+ }
136
+ this.view.dispatch(tr)
137
+ }
138
+ }
139
+
140
+ export default createNodeView(GeneralTableFootnoteView)
@@ -0,0 +1,76 @@
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 { FigureElementNode } 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 HeroImageView extends BlockView<Trackable<FigureElementNode>> {
26
+ private container: HTMLElement
27
+ private collapsed = false
28
+
29
+ public ignoreMutation = () => true
30
+
31
+ public createElement = () => {
32
+ this.container = document.createElement('div')
33
+ this.container.classList.add('block', 'hero-image-container')
34
+ this.dom.appendChild(this.container)
35
+
36
+ this.container.appendChild(this.createPanel())
37
+
38
+ this.contentDOM = document.createElement('figure')
39
+ this.contentDOM.classList.add('figure-block', 'hero-image-figure')
40
+ this.contentDOM.setAttribute('id', this.node.attrs.id)
41
+
42
+ this.container.appendChild(this.contentDOM)
43
+ }
44
+
45
+ createPanel() {
46
+ const panel = document.createElement('div')
47
+ panel.classList.add('panel-header')
48
+
49
+ const label = document.createElement('span')
50
+ label.textContent = 'Hero image'
51
+ label.contentEditable = 'false'
52
+
53
+ const heroImageToggleBtn = document.createElement('button')
54
+ heroImageToggleBtn.classList.add('toggle-btn', 'button-reset')
55
+
56
+ heroImageToggleBtn.innerHTML = arrowUp
57
+ heroImageToggleBtn.classList.toggle('collapsed', this.collapsed)
58
+
59
+ const handleToggle = () => {
60
+ this.collapsed = !this.collapsed
61
+ if (this.contentDOM) {
62
+ this.contentDOM.style.display = this.collapsed ? 'none' : ''
63
+ }
64
+ heroImageToggleBtn.classList.toggle('collapsed', this.collapsed)
65
+ }
66
+
67
+ heroImageToggleBtn.onclick = handleToggle
68
+ heroImageToggleBtn.addEventListener('keydown', handleEnterKey(handleToggle))
69
+
70
+ panel.appendChild(label)
71
+ panel.appendChild(heroImageToggleBtn)
72
+ return panel
73
+ }
74
+ }
75
+
76
+ export default createNodeView(HeroImageView)
@@ -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 { HeroImageView } from './hero_image'
20
+
21
+ export default createEditableNodeView(EditableBlock(HeroImageView))